Dark Bit Factory & Gravity
PROGRAMMING => Other languages => ASM => Topic started by: ninogenio on June 17, 2008
-
hi all ive been tinkering about again and i got stuck with divison. do you have to do a divide on the current screen_addr byte from left to right to get to the next pixel location ie 128 64 32 16 8 4 2 1 or is there an easyer way of moving about pixel wise in screen address space.
if divison is the only way then is srl a the only option i have or is there another way that can divide by more than 2 at a time.
cheers!
-
could you be a bit more specific about what you are trying to achieve and what specific hardware you use?
(edit: ok, looking at your other posts your hardware is obviously zx...)
seems like you are talking about "shifting" to address a single bit in a byte (so you are probably using a monochrome video-mode).
division (http://en.wikipedia.org/wiki/Division_(digital)), on the other hand, is an issue on its own.
generally you have to organize your code in such a way, that you simply know which pixel (bit) is next.
is srl a the only option or is there another way that can divide by more than 2
two srl's can divide by four ;)
-
You can mul or div by powers of 2 using shifts. lsl or asl multiply by 2, lsr or asr divide by 2. But if you want 'real' division then either:
a) don't do division. Think of a different algorithm.
b) use repeated subtraction (11/2=11-2-2-2-2-2) 5 lots of 2 can be subtracted. 11/2=5.
c) use multiplication 11*(1/2)==(1/2).
d) you can write a specific routine to do your division.
e) you can do b or c using self writing/modifying code.
f) don't do division.
Jim
-
thanks guys,
@jim i really think a) is the the best option on the zx and really quite acceptable most times.
im just trying to get my head around pixel pefect movement and its really hard to do especially if the graphic is two or three bytes in x and y.
do you guys know any specific algo that will take an x and a y for a graphic and move the screen ptr to the correct byte and bit shift the gfx to the correct pixel carrying over any bits too the next byte?
-
the stupid way:
don't move by single pixels but only by multiples of 8.
the easy way:
just move by a single pixel from one frame to another so you just need a single shift per byte.
the brute-force way:
store your graphics 8 times (each moved by one pixel) and copy the coresponding version.
-
Yeah that is one complicated display mode alright with the bitmap memory starting sequentially then going off down a different street. Im still trying to figure out how to store pixels to the bottom half of the screen with no success :(
I can appreciate that things were very limited in those days but they could have hired a monkey to come up with a better solution. Exactly why are there gaps in the display memory is just beyond me and I have been tippy-toe-ing around the issue hoping that things will eventually make sense.
-
@hellfire cheers mate all input is much appreciated, i have a rough sketch of what i want to do in my head so ill keep bashing away at it.
@rain they left gaps in video memory kepping in mind that there is no gfx acceleration and speed is a of big importance so that
inc h can be used and its pretty much the fastest instruction for a vertical movement available, it makes life hard for us but its quicker than simple memory manipulation.
when moving in a y direction this function works well i got it from the z80/.sna assembler refrence.
inc_row:
inc h ; move down one row
ld a,h
and 7 ; moved over a character cell ?
ret nz ; nz = no, all done
ld a,l
add a,32 ; update character row number
ld l,a
ret c
ld a,h
sub 8 ; if no carry, need to re-adjust h
ld h,a
ret nz
-
There's no gaps as such - the pixel screen memory is 32*192 bytes - but you're right, the first 32bytes are scanline 1, the 2nd 32bytes are scanline 8!
The Spectrum manual suggests thinking about the address in base 8. See if that helps.
Jim
-
From what I gather from this thread and I might be completely wrong it might be something like this to get the byte address of a pixel given x and y:
address = screen_address + (y and 7)*768 + ((y and 248)shl 2) + (x shr 3)
with the exception of the last part of that involving x, the results of each step must be calculated to 16 bit before doing the addition.
As for how to shift the pixels for drawing a bitmap sprite or something to the screen I can't think of anything yet.
EDIT: still not sure if that's right.
-
after a little mess around on the calculator, im not shure thats quite right fryer,
i dont think an algo is possible on the spectrum after looking a bit deeper, because of the weird mapping.
each screen row on the speccy is 32 bytes or 256 bits/pixels. the problem comes in on the 33 byte as this points to the 8th scanline and the 65 byte points to the 16th scanline and so on. the 257 byte however points to the second scanline. if you draw it on paper it turns into a real mess belive me :)
@jim your right if you convert y to octal and swap the least two significant bits then convert back to decimal your looking at the number bytes down you need! for example.
if i wanted to find y = 1
1 converted to octal is 001 swaped is 010 and converted to decimal is 0x64 + 1x8 + 0 = 8 row!! cool stuff.
-
the 257 byte however points to the second scanline.
Ah, didn't realise that, sorry.
-
Another possibility on the ZX Spectrum is to use the ROM routines for division (rst 28h). You can look up the details in the Incomplete Spectrum ROM Disassembly on WoS.
Jim
-
yeah ive been looking into various rom routines,
and they can be really handy. i was actually thinking of asking how fast are they i mean using a routine such as divide from machine code will it execute much faster than calling it in basic and is it better to use tailor made routines where ever applicable for speed and rom routines for generalized stuff (and where memory becomes tight) like lots of diffrent divides in a tight loop where tailor made routines with safety checks and such chopped out just wont work.
-
Any routine should execute at the same speed no matter where it's called from, what might make a difference is how the data the routine needs gets into the right place before the routine is called. I don't know but I doubt there's any fixed point routines other than for dealing with integers and floating point calculations will probably be pretty slow compared to some well written fixed point routines.
-
The ROM only does floating point - in ZXBASIC you only have floating point numbers :) Bit like yabasic!
Jim
-
You're joking! that must've been terrible for stuff like loops and poking with address pointers/data.
-
lol yeah fryer the zxbasic is pretty useless for anything other than calling machine code, its painfully slow.
although the one thing i find incredable usefull is the usr command as it runs the machine code and returns the bc register pair by default, so you can have say a really quick algo stored in memory and do let a=usr xxxxxx and in machine code you just drop whatever answer you like into bc before ret'ing.
with some assembler's you can also pass basic variables to the machine code routine thus creating fully fledged functions.
i havent went into that to much yet though im just messing around getting my head around everything.
-
The floating point number representation wasn't IEEE, they had some cheeky short cuts, but yup, it didn't help the speed :)
Jim