It is like a fractal to just have an image for the demo, such thing is not used in game.
The heaviest part in there is multiplication, "(x-16)*(y-16)". But *32 is not multiplication, just shift.
While this pain
(c-int(c/256)*256) and 255
was stumbeling with the BASIC 15bit maths and what I wanted was far from a division
ld a,h
just give me that high byte.
A matter of 1.4 microseconds on the machine level.
do BASIC compilers have high byte low byte features?
In the gosub 11000 are lots of those "/256", if BASIC compiler makes a division then speed is superbad.
Then can try setting DEFUSR or BASE.
They are 16bit values that one can set and then PEEK the high byte and low byte from sysarea.
The low byte is a simple AND. Afaik the only way to get the high byte is an integer division by 256.
bad things happen.
in attempts to prevent overflows I got wrong results.
but I can't reproduce the example.
something in the corner
doing /256 one gets minus 0.something
then some OUT makes some implicit conversion, which one is it, cint() or int(), who knows.
cint(-0.9) = 0, a candidate.
the thing ends up with 0 instead the desired high byte.
when one adds an int() op trying to put something straight, it gets -1, and an OUT of -1 is an error.
I dont know whether BASIC programmers know ways about it.
for me storing the value to DEFUSR or BASE worked best. and then PEEK the bytes.
that is because defusr = 65535 does not make an error, the 16th bit is available.
when defusr = 32768 would make an error, it was thought "ok, that is confusing, because its a 64k machine".
And at that point DEFUSR did get a conversion to 16bit available nowhere else.
Maybe I should explain the problem simpler.
a = 65535 ? a and 255 Overflow BEEP!
With blitter sx dx values it still works, they can stay below 32768.
DEFNIT A-Z on turbobasic makes real wanders.
It does not only accelerate the FOR loops but all mathematical calculations as long as those are done with integers.
This is why I try to find solutions with integer calculations as much as I can.
Anyway, if you need a non-integer variable in particular, you can DEFINTA-Y and you can use Z as you wish.
Or you can use the variable modifier characters on the one variable name you need to be calculated different, the same way you do with Strings...
So, even if you put DEFINTA-Z on the first line of your program:
A$= will always be a String variable
A#= will always be a double precision variable
A!= will always be a single precision variable
A%= will always be an integer variable.
It is like a fractal to just have an image for the demo, such thing is not used in game.
The heaviest part in there is multiplication, "(x-16)*(y-16)". But *32 is not multiplication, just shift.
Does the BASIC interpreter is smart enough to treat operations with powers of two (2, 4, 8, 16, 32...) as shift operations, or it will treat like normal multiplications?
Maybe I should explain the problem simpler.
a = 65535 ? a and 255 Overflow BEEP!
With blitter sx dx values it still works, they can stay below 32768.
Didn't worked here either.
What I know: BASIC works with signed INTs.
What I think, but I don't know: Maybe you can't work with unsigned INTs, and logic operators only work with INTegers.
If you enter:
a% = 65535
you will get overflow right away.
BUT if you replace 65535 with "-1" (using binary representation, both 65535 unsigned int and -1 signed int are equal to &B1111111111111111) your code works:
a = -1 ? a and 255 255 Ok
Maybe I should explain the problem simpler.
a = 65535 ? a and 255 Overflow BEEP!
Hmm ok, because they are 16-bit signed integers... You can use -1 to represent 65535, but that doesn’t work for the division. That’s a shame. (Btw, use the integer division \.)
I guess you could use if x < 0 then (x + 1) \ 256 + 255... but yeah, meh.
Just to wrap the offtopic:
I found a HD63C09 and a SRAM on my parts drawer. As it has specific multiplication and division instructions, I'm thinking on putting it inside a cartridge to test how fast things could be if Z80 had a better ALU.
Now, that creating pixel art post made me think how those images look on V9990, and how easily we can animate them...
a multiplication with gfx 9000 in 134 cycles.
the deal is that the 128k table needs no main RAM.
;HL = H * L 8 ld a,3 12 out (0x64),a 12 add hl,hl 8 adc a ;a = 6 or a = 7. 60000..7ffff 8 add n ;different location in vram 8 ld c,0x63 14 out (c),l 14 out (c),h 14 out (c),a 8 ld c,0x60 14 in l,(c) 14 in h,(c) -- 134
how to communicate with the 63xx?
5 ld a,l 12 out (0),a 5 ld a,h 12 out (1),a 5 xor a 12 out (2),a ;I have provided new value, go wait: 12 in a,(2) 5 rrca 11 jp nc,wait 12 in a,(0) 5 ld l,a 12 in a,(1) 5 ld h,a -- 113
the fastest communication I could think of.
but I dont think the 63xx gonna set the result to all 3 ports in the 12 z80 cycles.
more loops needed.
what about logartihm. it can to great things with mul and div.
ld l,(hl)
that was a logarithm lookup 8bit->8bit.
ld e,(hl)
inc h
ld d,(hl)
that was logarithm 8bit->16bit precision result
512 bytes table, superfast, very intriguing.
except that no completed code was ever seen.
kunbasic needs horrible 50 rasterlines to make a blit.
the /256 results in 3 calls to some maths code.
but using defusr1 to store and peek, it looks like this
ld hl,(0x8d61) ;sx ld (0xf39c),hl ;defusr1 ld hl,0xf39c ld l,(hl) ld h,0 ld a,l out (0x63),a ld hl,0xf39d ld l,(hl) ld h,0 ld a,l out (0x63),a -- 122
The whole gosub should go in 4 rasterlines on z80.
It's not like asm coding but can make a game.
One could fire 80 blits in 50fps.
same demo again, but without the div in blitter code
1 defint a-z 2 dim sx(32), sy(32) 9 out &h6f,0 : rem 'init superimpose 10 for i = 0 to 24 : read a 12 out &h64,i : rem 'write register i 14 out &h63,a 16 next i 60 for i = 0 to 15 : rem 'palette 61 out (&h64),128+14 : out (&h63),i*4 70 out (&h61),i*2 : out (&h61),i*2 : out (&h61),i*1 + 13 80 next i 90 'CLS beta 92 nx = 512 : ny = 256 : sx = 0 : sy = 0 : dx = s0 : dy = 0 94 ar = 0 : lo = &h00 : op = &h40 96 gosub 11000 100 rem '16bit bitmap 110 for y = 0 to 31 115 p = 0 : a = y * 512 * 2 : gosub 10000 120 for x = 0 to 31 125 c = (y and &h1f) *32*32 + &h1f*32 + (x and &h1f) 126 if abs((x-16)*(y-16)) > 64 then c = 0 130 out &h60,(c-int(c/256)*256) and 255 135 out &h60,(c/256) and 255 140 next x,y 200 pi = 3.1415926 210 for i = -1 to 20 220 nx = 32 : ny = 32 : sx = 0 : sy = 0 : dx = i*13 : dy = 128-i*4 : gosub 11600 230 next i 250 for i = -1 to 15 260 nx = 32 : ny = 32 : sx = 0 : sy = 0 : dx = 128+i*4 : dy = i*13-1 : gosub 11600 270 next i 290 for i = 31 to 0 step -1 291 sx(i) = sx(i) + sy(i) 292 next i 300 dx = &h23 : dy = &h24 : gosub 11600 : goto 300 9990 if inkey$ = "" then 9990 9991 out &h6f,16 : rem 'superimpose tidy exit 9999 stop 10000 'vram write address = p*65536 + a . out &h60 vpokes with autoincrement. 10005 out &h64,0 : rem 'write vdp registers 0+ 10006 defusr1 = a : rem 'to get at H,L 10010 xx = peek(&hf39c) : out &h63,xx : '?xx; 10020 xx = peek(&hf39d) : out &h63,xx : '?xx;"." 10030 out &h63,p : rem 'bit 7 address increment inhibit 10050 return 11000 if inp(&h65) and 1 then 11000 'wait for blitter 11005 dx = dx and 32767 : dy = dy and 32767 'math problems of BASIC 11010 out &h64,32 'write r32+ 11015 defusr1 = sx 11020 out &h63,peek(&hf39c) 'r32 11030 out &h63,peek(&hf39d) 'r33 11025 defusr1 = sy 11040 out &h63,peek(&hf39c) 'r34 11050 out &h63,peek(&hf39d) 'r35 11055 defusr1 = dx 11060 out &h63,peek(&hf39c) 'r36 11070 out &h63,peek(&hf39d) 'r37 11075 defusr1 = dy 11080 out &h63,peek(&hf39c) 'r38 11090 out &h63,peek(&hf39d) 'r39 11095 defusr1 = nx 11100 out &h63,peek(&hf39c) 'r40 11110 out &h63,peek(&hf39d) 'r41 11115 defusr1 = ny 11120 out &h63,peek(&hf39c) 'r42 11130 out &h63,peek(&hf39d) 'r43 11140 out &h63,ar 'r44 arg 11150 out &h63,lo 'r45 lop 11151 out &h63,255 'r46 11152 out &h63,255 'r47 11160 out &h64,52 'write r52+ 11170 out &h63,op 'r52 11180 return 11500 'blit (sx,sy)-(sx+nx-1,sy+ny-1) to (dx,dy) 11510 op = &h40 'lmmm 11520 ar = 0 : lo = &hc 11530 gosub 11000 : return 11600 'blit (sx,sy)-(sx+nx-1,sy+ny-1) to (dx,dy) with source value = 0 meaning transparent pixel. 11610 op = &h40 'lmmm 11620 ar = 0 : lo = &h1c 11630 gosub 11000 : return 21000 'regs 21010 data 0,0,0,0 21020 data 0,0,&h87,0 21030 data &hC2,0,0,0 21040 data 0,0,0,0 21050 data 0,0,0,0 21060 data 0,0,0,0 21070 data 0 50000 'B1-B6 VRAM 50010 'Physical mapping: even addresses (bit 0=0) in VRAM0 and odd addresses (bit0=1) in VRAM1. 50020 '00000-7FDFF Bitmap Data 50030 '7FE00-7FFFF Cursor area (512 bytes)
why only the OUT(&H63) on the ML code?
well, I think I know the answer, there isn't a way to pass two parameters to ML code via USR(x), right?