Boriel Basic Forum
Stack Bug in ZXB 1.2.5-r1489 ? - Printable Version

+- Boriel Basic Forum (https://forum.boriel.com)
+-- Forum: Compilers and Computer Languages (https://forum.boriel.com/forumdisplay.php?fid=12)
+--- Forum: ZX Basic Compiler (https://forum.boriel.com/forumdisplay.php?fid=11)
+---- Forum: Bug Reports (https://forum.boriel.com/forumdisplay.php?fid=15)
+---- Thread: Stack Bug in ZXB 1.2.5-r1489 ? (/showthread.php?tid=172)

Pages: 1 2


Stack Bug in ZXB 1.2.5-r1489 ? - britlion - 2010-03-05

I was updating fourspriter to use SUBs as opposed to gotos. Probably slower, but a little cleaner on the interface to the user.

Anyway, as it stands the main program:

Calls initialize for the first sprite
which calls a dummy "data" routine (which is really just for asm. The first line is return. It only calls it to make sure it's not peephole optimized out)
Comes back to main
calls coords for the first sprite
comes back to main
calls initialize for the second sprite
which calls the dummy data routine again......

and then it goes wrong. It never comes back from this data routine this second time, even though it should return immediately. In fact, it restarts the main program again. Over and over - and then after a few cycles, crashes.


I confirmed the code does the same thing with 1.23 and 1.22; and I didn't think they had the stack bugs, so it could be something I'm doing wrong, I suppose. I can't really see what could go wrong with "return" being the only statement, though.

The code is a bit complex, and is unfinished; but hopefully you can see where I'm going. It has testing PRINTs in it. Just copy and paste and see if it behaves the same way for you.

Code:
SUB fspInitialize (n as uByte, a as uByte, b as uByte, c as uByte, d as uByte) 'Initialize Sprite: n (sprite number 0-3);a,b,c,d (UDG number 0-20,99 means the sprite won't be printed) PRINT AT 0,0;"Initialize" : PAUSE 1: PAUSE 0 fspData() : REM call the data sub to make sure it isn't optimized out of the compile. That call just returns. PRINT AT 2,0;"FSPData came back to Initialize" : PAUSE 1: PAUSE 0 IF n>3 OR a>20 or b>20 or c>20 or d>20 then return : END IF : REM Bounds checking - so a bad function call doesn't poke all over memory. DIM targetAddr as uInteger targetAddr=@fspDataStart+(48*n) POKE targetAddr,a targetAddr=targetAddr+1 POKE targetAddr,b targetAddr=targetAddr+1 POKE targetAddr,c targetAddr=targetAddr+1 POKE targetAddr,d PRINT AT 3,0;"We're at the end of Initialize" PAUSE 1:PAUSE 0 END SUB SUB fspDisable (n as UByte) IF n>3 then return : END IF POKE @fspDataStart+48*n,99 end SUB SUB fspCoord (n as uByte, x as uByte, y as uByte) 'Set sprite coords: n (sprite number);x,y (vertical,horizontal coords) IF n>3 then return : END IF DIM targetAddr as uInteger targetAddr=@fspDataStart+4+48*n POKE targetAddr,x targetAddr=targetAddr+1 POKE targetAddr,y rem targetAddr=targetAddr+1 rem POKE targetAddr,x rem targetAddr=targetAddr+1 rem POKE targetAddr,y END SUB SUB fspAttrs (n as uByte, attra as uByte, attrb as uByte, attrc as uByte, attrd as uByte) 'Set sprite attrs: n (sprite number);a,b,c,d (UDG attrs) IF n>3 then return : END IF DIM targetAddr as uInteger targetAddr=@fspDataStart+40+48*n POKE targetAddr,attra targetAddr=targetAddr+1 POKE targetAddr,attrb targetAddr=targetAddr+1 POKE targetAddr,attrc targetAddr=targetAddr+1 POKE targetAddr,attrd END SUB FUNCTION fspAttrByte(fspInk as uByte,fspPaper as uByte,fspBright as uByte, fspFlash as uByte) as uByte if fspInk > 7 OR fspPaper > 7 OR fspBright > 1 or fspFlash >1 then return 0: END IF: Rem bounds check return (fspFlash shl 7) + (fspBright shl 6) + (fspPaper shl 3) + fspInk END FUNCTION SUB fspAttr(n as uByte,fspInk as uByte,fspPaper as uByte,fspBright as uByte, fspFlash as uByte) if fspInk > 7 OR fspPaper > 7 OR fspBright > 1 or fspFlash >1 then return : END IF: Rem bounds check DIM attrByte as uByte attrByte=fspAttrByte(fspInk,fspPaper,fspBright,fspFlash) fspAttrs(n,fspAttrByte,fspAttrByte,fspAttrByte,fspAttrByte) END SUB SUB fspData() fspDataStart: RETURN : REM if called we should return immediately. This sub is for data and ASM only. REM This routine contains Fourspriter data and code that is called by other routines. In effect, it's a dummy subroutine. REM It is called by fspInitialize in order to ensure it is included in the build. ASM ;; 16x16 Sprites moving a character each frame ;; Copyleft 2009 The Mojon Twins. ;; Pergreñado por na_th_an ;; Uses UDGs (it reads the address from the system variables). ;; It moves up to 4 sprites, preserving the backgrounds. datap: ; each block is 48 bytes long. [This comment originally said 40 bytes, and it's clearly 48] ;; Sprite 1 udgs1: defb 0,0,0,0 ; Four UDGs of the first sprite. x_pos1: defb 0 ; X position in chars. y_pos1: defb 0 ; Y position in chars. cx_pos1: defb 0 ; Previous X position in chars. cy_pos1: defb 0 ; Previous Y position in chars. buffer1: defb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; Background Gfx buffer. attrs1: defb 7,7,7,7 ; Sprite ATTRs buffatrs1: defb 0,0,0,0 ; Background Attr's buffer ;; Sprite 2 udgs2: defb 0,0,0,0 x_pos2: defb 0 y_pos2: defb 0 cx_pos2: defb 0 cy_pos2: defb 0 buffer2: defb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 attrs2: defb 7,7,7,7 buffatrs2: defb 0,0,0,0 ;; Sprite 3 udgs3: defb 0,0,0,0 x_pos3: defb 0 y_pos3: defb 0 cx_pos3: defb 0 cy_pos3: defb 0 buffer3: defb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 attrs3: defb 7,7,7,7 buffatrs3: defb 0,0,0,0 ;; Sprite 4 udgs4: defb 0,0,0,0 x_pos4: defb 0 y_pos4: defb 0 cx_pos4: defb 0 cy_pos4: defb 0 buffer4: defb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 attrs4: defb 7,7,7,7 buffatrs4: defb 0,0,0,0 ;; General use coordinates xpos: defb 0 ypos: defb 0 cxpos: defb 0 cypos: defb 0 ;; Sprite control is done writing a certain number ;; in the Sprite's first UDG ;; If the first UDG is 99, it won't be printed docopy: call get_scr_address ; Dirección (xpos, ypos) en BC ld l, c ld h, b ; Dirección (xpos, ypos) en HL ld a, (de) ld (hl), a inc h inc de ld a, (de) ld (hl), a inc h inc de ld a, (de) ld (hl), a inc h inc de ld a, (de) ld (hl), a inc h inc de ld a, (de) ld (hl), a inc h inc de ld a, (de) ld (hl), a inc h inc de ld a, (de) ld (hl), a inc h inc de ld a, (de) ld (hl), a inc h inc de ret ;; Esta función devuelve en bc la dirección de memoria ;; de la posición (xpos, ypos) en carácteres. Extraído de código ;; por BloodBaz. get_scr_address: push de ld a, (xpos) and 31 ld c, a ld a, (ypos) ld d, a and 24 add a, 64 ld b, a ld a, d and 7 rrca rrca rrca or c ld c, a pop de ret ;; Esta función devuelve en bc la dirección de memoria ;; de la posición (xpos, ypos) dentro del archivo de atributos. ;; Adaptado de código por Jonathan Cauldwell. ;; 010110YY YYYXXXXX get_attr_address: ld a, (ypos) ; Cogemos y rrca rrca rrca ; La multiplicamos por 32 ld c, a ; nos lo guardamos en c and 3 ; ponemos una mascarita 00000011 add a, 88 ; 88 * 256 = 22528, aquí empieza el tema ld b, a ; Hecho el bite superior. ld a, c ; Nos volvemos a traer y * 32 and 224 ; Mascarita 11100000 ld c, a ; Lo volvemos a poner en c ld a, (xpos) ; Cogemos x add a, c ; Le sumamos lo que teníamos antes. ld c, a ; Listo. Ya tenemos en BC la dirección. ret spare: defb 85,85,85,85,85,85,85, 85 END ASM END SUB SUB fspErase() asm ;; Routine to save the background to the buffer ;borra_sprites: ; pointer = datap ; for (i = 0; i < 4; i ++) { ; CX = *(pointer + 6) ; CY = *(pointer + 7) ; scr_address = get_scr_address (CX, CY); ; for (j = 0; j < 8; j ++) { ; *scr_address = *(pointer + 8 + j); ; scr_address += 256; ; } ; scr_address = get_scr_address (CX+1, CY); ; for (j = 0; j < 8; j ++) { ; *scr_address = *(pointer + 16 + j); ; scr_address += 256; ; } ; scr_address = get_scr_address (CX, CY+1); ; for (j = 0; j < 8; j ++) { ; *scr_address = *(pointer + 24 + j); ; scr_address += 256; ; } ; scr_address = get_scr_address (CX+1, CY+1); ; for (j = 0; j < 8; j ++) { ; *scr_address = *(pointer + 32 + j); ; scr_address += 256; ; } ; pointer += 40; ; } ld de, datap ; ld b, 4 ; i4chars2: push bc ;; ld a, (de) cp 99 jr z, nxt2 ;; A inc de inc de inc de inc de inc de inc de ; Obtenemos xpos = CX ld a, (de) ld hl, xpos ld (hl), a inc de ; Obtenemos ypos = CY ld a, (de) ld hl, ypos ld (hl), a inc de ;; B ; Pintamos el primer char call borra_char ; xpos++ ld hl, xpos inc (hl) ;; C ; Pintamos el segundo char call borra_char ; xpos -- ld hl, xpos ld a, (hl) dec a ld (hl), a ; ypos ++ ld hl, ypos inc (hl) ;; D ; Pintamos el tercer char call borra_char ; xpos++ ld hl, xpos inc (hl) ;; E ; Pintamos el cuarto char call borra_char ;; attr inc de inc de inc de inc de ;; ; xpos -- ld hl, xpos ld a, (hl) dec a ld (hl), a ; ypos -- ld hl, ypos ld a, (hl) dec a ld (hl), a ; call get_attr_address ; call copyattrs ; nxt2: pop bc djnz i4chars2 jp fspErase_end borra_char: call get_scr_address ; ld l, c ld h, b ; ld a, (de) ld (hl), a inc h inc de ld a, (de) ld (hl), a inc h inc de ld a, (de) ld (hl), a inc h inc de ld a, (de) ld (hl), a inc h inc de ld a, (de) ld (hl), a inc h inc de ld a, (de) ld (hl), a inc h inc de ld a, (de) ld (hl), a inc h inc de ld a, (de) ld (hl), a inc h inc de ret fspErase_end: end asm END SUB SUB fspBufferBackground() asm init_sprites: ; pointer = datap ; for (i = 0; i < 4; i ++) { ; X = *(pointer + 4); // A ; Y = *(pointer + 5); ; scr_address = get_scr_address (X, Y); // B ; for (j = 0; j < 8; j ++) { ; *(pointer + 8 + j) = *scraddress; ; scraddress += 256; ; } ; scr_address = get_scr_address (X+1, Y); // C ; for (j = 0; j < 8; j ++) { ; *(pointer + 16 + j) = *scraddress; ; scraddress += 256; ; } ; scr_address = get_scr_address (X, Y+1); // D ; for (j = 0; j < 8; j ++) { ; *(pointer + 24 + j) = *scraddress; ; scraddress += 256; ; } ; scr_address = get_scr_address (X+1, Y+1); // E ; for (j = 0; j < 8; j ++) { ; *(pointer + 32 + j) = *scraddress; ; scraddress += 256; ; } ; pointer = pointer + 40; ; } ld de, datap ; ld b, 4 ; i4chars: push bc ;; ld a, (de) cp 99 jr z, nxt1 ;; A inc de inc de inc de inc de ; ld a, (de) ld hl, xpos ld (hl), a inc de ; ld a, (de) ld hl, ypos ld (hl), a inc de inc de inc de ;; B ; call copia_char ; xpos++ ld hl, xpos inc (hl) ;; C ; call copia_char ; xpos -- ld hl, xpos ld a, (hl) dec a ld (hl), a ; ypos ++ ld hl, ypos inc (hl) ;; D ; call copia_char ; xpos++ ld hl, xpos inc (hl) ;; E ; call copia_char ;; Now we point to the ATTR buffer,adding 4: inc de inc de inc de inc de ;; ; xpos -- ld hl, xpos ld a, (hl) dec a ld (hl), a ; ypos -- ld hl, ypos ld a, (hl) dec a ld (hl), a ; call get_attr_address ; ld l, c ld h, b ld bc, 31 ld a, (hl) ld (de), a ; Primer carácter inc hl inc de ld a, (hl) ld (de), a ; Segundo carácter add hl, bc inc de ld a, (hl) ld (de), a ; Tercer carácter inc hl inc de ld a, (hl) ld (de), a ; Cuarto carácter inc de ; Fin del bucle nxt1: pop bc djnz i4chars ;ret jp fspBufferBackground_end copia_char: call get_scr_address ; ld l, c ld h, b ; ld a, (hl) ld (de), a inc h inc de ld a, (hl) ld (de), a inc h inc de ld a, (hl) ld (de), a inc h inc de ld a, (hl) ld (de), a inc h inc de ld a, (hl) ld (de), a inc h inc de ld a, (hl) ld (de), a inc h inc de ld a, (hl) ld (de), a inc h inc de ld a, (hl) ld (de), a inc h inc de ret ; Subroutines don't need to return themselves. fspBufferBackground_end: ;; Routine to move the sprites: end asm END SUB SUB fspRedraw() asm halt end asm ';call borra_sprites ; Erase the sprites fspErase() ';call init_sprites ; Save background fspBufferBackground() ';call draw_sprites ; print sprites fspDraw() ';call update_coordinates ; update coordinates :) fspUpdate() ';ret END SUB SUB fspDraw() asm ;; Print sprites routine ;; UDGs are labeled from 0 to 21. The addres of the UDG is: ;; *(23675) + 256 * *(23676) + 8 * N draw_sprites: ld de, datap ; ld b, 4 ; i4chars3: push bc ld a, (de) cp 99 jr z, nxt3 ;; copiar aquí "de" a un buffer call charsabuff ; Obtenemos xpos ld a, (de) ld hl, xpos ld (hl), a inc de ; Obtenemos ypos ld a, (de) ld hl, ypos ld (hl), a inc de inc de inc de push de ld hl, bufchars call getde call docopy ; xpos++ ld hl, xpos inc (hl) ; Dirección del gráfico ld hl, bufchars inc hl call getde ; Pintamos el segundo char call docopy ; xpos-- ld hl, xpos ld a, (hl) dec a ld (hl), a ; ypos ++ ld hl, ypos inc (hl) ; Dirección del gráfico ld hl, bufchars inc hl inc hl call getde ; Pintamos el tercer char call docopy ; xpos ++ ld hl, xpos inc (hl) ; Dirección del gráfico ld hl, bufchars inc hl inc hl inc hl call getde ; Pintamos el cuarto char call docopy pop de ; de = de + 32 ld bc, 32 ld h, d ld l, e add hl, bc ld d, h ld e, l ;; attr ; xpos -- ld hl, xpos ld a, (hl) dec a ld (hl), a ; ypos -- ld hl, ypos ld a, (hl) dec a ld (hl), a ; call get_attr_address ; call copyattrs inc de inc de inc de inc de ; nxt3: pop bc djnz i4chars3 ;ret jp fspDraw_end ;; Esta función calcula la posición en memoria del UDG apuntado por ;; el número que está en la dirección hl. getde: ld a, (hl) ld d, a ld hl, 23676 ld a, (hl) ld e, a ld hl, 23675 ld a, (hl) ld l, a ld a, e ld h, a ;; HL = *(23675) + 256 * *(23676) ld a, d rlca rlca rlca ; a = N * 8 ld d, 0 ld e, a add hl, de ld d, h ld e, l ret bufchars: defb 0,0,0, 0 ; charsabuff: ld hl, bufchars ld a, (de) ld (hl), a inc de inc hl ld a, (de) ld (hl), a inc de inc hl ld a, (de) ld (hl), a inc de inc hl ld a, (de) ld (hl), a inc de inc hl ret copyattrs: ld l, c ld h, b ld bc, 31 ld a, (de) ld (hl), a ; Primer carácter inc hl inc de ld a, (de) ld (hl), a ; Segundo carácter add hl, bc inc de ld a, (de) ld (hl), a ; Tercer carácter inc hl inc de ld a, (de) ld (hl), a ; Cuarto carácter inc de ; Ahora de apunta a datap+48, o sea, al siguiente sprite. ret fspDraw_end: END ASM END SUB SUB fspUpdate() asm update_coordinates: ld de, datap ; Apuntamos a la zona de datos ld hl, datap ; idem ld b, 4 ; 4 iteraciones i4chars4: push bc ;; Para cada sprite hay que hacer: ;; *(datap + 6) = *(datap + 4) ;; *(datap + 7) = *(datap + 5) inc de inc de inc de inc de ld a, (de) ; a = X inc hl inc hl inc hl inc hl inc hl inc hl ld (hl), a ; CX = a inc de ld a, (de) ; a = Y inc hl ld (hl), a ; CY = a inc hl ;; hl = hl + 40 ld bc, 40 add hl, bc ;; de = hl ld d, h ld e, l pop bc djnz i4chars4 ;ret END ASM END SUB #include <sinclair.bas> #include <memcopy.bas> #include <keys.bas> 100 DIM gentle (0 to 3,0 to 7) AS uByte => { { 15, 15, 15, 15, 15, 15, 13, 15} , _ { 240, 144, 208, 208, 240, 240, 176, 240} , _ { 15, 14, 63, 0, 0, 12, 26, 30} , _ { 176, 112, 252, 0, 0, 48, 104, 120}} 110 POKE Uinteger 23675, @gentle(0,0) memcopy (0,16384,4092) LET gx=10:LET gy=10:let dx=3:let dy=3:let tx=6:let ty=6:let cx=18:let cy=18 let dmx=1:let dmy=1:let tmx=-1:let tmy=-1:let cmx=1:let cmy=-1 fspInitialize (0,0,1,2,3) PRINT AT 5,0;"We came back from Initialize the first time" : PAUSE 1: PAUSE 0 fspCoord (0,gy,gx) PRINT AT 6,0;"We came back from fspCoord the first time": PAUSE 1: PAUSE 0 CLS fspInitialize (1,0,1,2,3) PRINT AT 7,0;"We came back from Initialize the second time" : PAUSE 1: PAUSE 0 fspCoord (1,dy,dx) fspInitialize (2,0,1,2,3) fspCoord (2,ty,tx) fspInitialize (3,0,1,2,3) fspCoord (3,cy,cx) fspAttrs (0,31,31,31,31) fspAttrs (1,12,12,12,12) fspAttrs (2,26,26,26,26) fspAttrs (3,6,6,6,6) DO IF MULTIKEYS(KEYO)<>0 and gx>0 THEN LET gx=gx-1: END IF IF MULTIKEYS(KEYP)<>0 and gx<30 THEN LET gx=gx+1:END IF IF MULTIKEYS(KEYQ)<>0 and gy>0 THEN LET gy=gy-1 :END IF IF MULTIKEYS(KEYA)<>0 and gy<22 THEN LET gy=gy+1: END IF let dx=dx+dmx:if dx=0 or dx=30 then let dmx=-dmx : END IF let dy=dy+dmy:if dy=0 or dy=22 then let dmy=-dmy: END IF let tx=tx+tmx:if tx=0 or tx=30 then let tmx=-tmx: END IF let ty=ty+tmy:if ty=0 or ty=22 then let tmy=-tmy: END IF let cx=cx+cmx:if cx=0 or cx=30 then let cmx=-cmx: END IF let cy=cy+cmy:if cy=0 or cy=22 then let cmy=-cmy: END IF pause 2 fspCoord (0,gx,gy) fspCoord (1,dx,dy) fspCoord (2,tx,ty) fspCoord (3,cx,cy) fspRedraw() loop



Re: Stack Bug in ZXB 1.2.5-r1489 ? - boriel - 2010-03-07

In this case, it's a bug in your program: in fspInitialize you call fspData():
Code:
SUB fspInitialize (n as uByte, a as uByte, b as uByte, c as uByte, d as uByte) 'Initialize Sprite: n (sprite number 0-3);a,b,c,d (UDG number 0-20,99 means the sprite won't be printed) PRINT AT 0,0;"Initialize" : PAUSE 1: PAUSE 0 fspData() : REM call the data sub to make sure it isn't optimized out of the compile. That call just returns. ...
And later call fspDisable() with n = 0:
Code:
SUB fspDisable (n as UByte) IF n>3 then return : END IF POKE @fspDataStart+48*n,99 end SUB
Look carefully at the above code and now look at fsbData definition:
Code:
SUB fspData() fspDataStart: RETURN : REM if called we should return immediately. This sub is for data and ASM only. REM This routine contains Fourspriter data and code that is called by other routines. In effect, it's a dummy subroutine. REM It is called by fspInitialize in order to ensure it is included in the build. ...

When you call fspDisable(0) you're effectively *destroying* the RETURN sentence of fspData(), because you're doing
POKE @fspDataStart, 99 (which is @RETURN address). Rewriting fspData this way, fixes the bug:
Code:
SUB fspData() RETURN : REM if called we should return immediately. This sub is for data and ASM only. fspDataStart: REM this label *AFTER* return to avoid being POKEd REM This routine contains Fourspriter data and code that is called by other routines. In effect, it's a dummy subroutine. REM It is called by fspInitialize in order to ensure it is included in the build. ...



Re: Stack Bug in ZXB 1.2.5-r1489 ? - britlion - 2010-03-08

Very, very well spotted. This is why you make the compiler, and I just break it :-)

You are right - the return was put in later on, and it should be before the label, not after it.

Your explanation confused me a little at first, because I'm quite certain I don't call fspdisable at all - but I DO call fspCoords, which pokes exactly where you say.

Erk.


Thankyou for clearing that up!

It turns out I fixed it by redesigning where all the code is, more or less by accident. It does show that mixing compiled code with assembler and worst of all using poke can leave you with unintentional self-modifying code!

Now I feel bad I made you dig through my rookie mistake!

Thanks, Boriel. I bow to your superior skills Wink


Re: Stack Bug in ZXB 1.2.5-r1489 ? - boriel - 2010-03-08

I've finally fixed the -O2 -O3 bugs. Please download 1.2.5-r1489f
<!-- m --><a class="postlink" href="http://www.boriel.com/files/zxb/zxbasic-1.2.5r1489f.msi">http://www.boriel.com/files/zxb/zxbasic-1.2.5r1489f.msi</a><!-- m -->

This release should be a Release Candidate (RC1).
If there are no more bugs to fix, we can finally release it and move to 1.2.6 and add bOR, bAND and bXOR to the language. :!:


Re: Stack Bug in ZXB 1.2.5-r1489 ? - apenao - 2010-03-09

I've downloaded the new version (1.2.5-r1489f) and tried to compile my last crap game. It compiled OK with version 1.2.5-r1489 and no optimization.

Now, with no optimization I get this message (and it compiles OK):
Code:
> Executing: C:\Archivos de programa\ConTEXT\ConExec.exe -i "C:\Archivos de programa\Boriel Tm\ZX Basic Compiler\zxb.exe" -T -B -a -S 28000 clash3.bas memcopy.bas:29: warning: SUB 'memcopy' declared as FASTCALL with 3 parameters > Execution finished.


With optimization -O 2, or -O 3 I get this message (and it doesn't compile):

Code:
> Executing: C:\Archivos de programa\ConTEXT\ConExec.exe -i "C:\Archivos de programa\Boriel Tm\ZX Basic Compiler\zxb.exe" -T -B -a -O 2 -S 28000 clash3.bas INFO: BORDER is not defined. No optimization is done. INFO: COPY_ATTR is not defined. No optimization is done. INFO: CLS is not defined. No optimization is done. INFO: BRIGHT is not defined. No optimization is done. INFO: BOLD_TMP is not defined. No optimization is done. INFO: PRINT_STR is not defined. No optimization is done. INFO: PRINT_EOL_ATTR is not defined. No optimization is done. INFO: ITALIC_TMP is not defined. No optimization is done. INFO: BRIGHT_TMP is not defined. No optimization is done. INFO: INVERSE_TMP is not defined. No optimization is done. INFO: __FTOU32REG is not defined. No optimization is done. INFO: __EQ32 is not defined. No optimization is done. INFO: PRINT_EOL is not defined. No optimization is done. INFO: __PAUSE is not defined. No optimization is done. INFO: __EQ16 is not defined. No optimization is done. INFO: FLASH_TMP is not defined. No optimization is done. INFO: __AND8 is not defined. No optimization is done. INFO: __ABS8 is not defined. No optimization is done. INFO: __STOP is not defined. No optimization is done. INFO: __MUL8_FAST is not defined. No optimization is done. INFO: BEEP is not defined. No optimization is done. memcopy.bas:29: warning: SUB 'memcopy' declared as FASTCALL with 3 parameters clash3.bas:27: warning: Function 'attr' is never called and has been ignored clash3.bas:66: warning: Function 'setattr' is never called and has been ignored clash3.bas:27: warning: Function 'point' is never called and has been ignored clash3.bas:29: warning: Function 'screen' is never called and has been ignored clash3.bas:26: warning: Function 'input' is never called and has been ignored clash3.bas:22: warning: Function 'GetKey' is never called and has been ignored clash3.bas:59: warning: Function 'GetKeyScanCode' is never called and has been ignored clash3.bas:1: warning: Function 'psprite' is never called and has been ignored clash3.bas:19: warning: Function 'orsprite' is never called and has been ignored clash3.bas:12: warning: Function 'cpattr' is never called and has been ignored clash3.bas:20: warning: Function 'rstattr' is never called and has been ignored clash3.bas:29: warning: Variable 'dest' is never used clash3.bas:29: warning: Variable 'source' is never used clash3.bas:29: warning: Variable 'length' is never used clash3.bas:41: warning: Variable 'scancode' is never used Traceback (most recent call last): File "zxb.py", line 244, in <module> File "zxb.py", line 209, in main File "optimizer.pyc", line 2021, in optimize File "optimizer.pyc", line 1316, in update_goes_and_comes IndexError: list index out of range > Execution finished.


It's probably my code (I'm so proud of its crapyness...) but maybe the last lines of the optimization message tells you something. I don't want to make you search within a long, untidy, unsorted and crap piece of code, so if you can point me to what should I look for, I'll do. Or if you think it's my code's fault I'll let it as is (it compiles without optimization and that more than enough for me).

Anyway, if you still want to see my code, I'll send you the .bas file, the attachments and also the .tzx file so you can play and delight yourself (or not).


Re: Stack Bug in ZXB 1.2.5-r1489 ? - apenao - 2010-03-09

By the way, when I intalled this last version (1.2.5 r1489f) I had to manually uninstall the previous one. This is probably OK, but as in previous versions instalations it just overwrited the old data, I thought I better tell you just in case.


Re: Stack Bug in ZXB 1.2.5-r1489 ? - boriel - 2010-03-09

apenao Wrote:I've downloaded the new version (1.2.5-r1489f) and tried to compile my last crap game. It compiled OK with version 1.2.5-r1489 and no optimization.

Now, with no optimization I get this message (and it compiles OK):
Code:
> Executing: C:\Archivos de programa\ConTEXT\ConExec.exe -i "C:\Archivos de programa\Boriel Tm\ZX Basic Compiler\zxb.exe" -T -B -a -S 28000 clash3.bas memcopy.bas:29: warning: SUB 'memcopy' declared as FASTCALL with 3 parameters > Execution finished.

With optimization -O 2, or -O 3 I get this message (and it doesn't compile):

Code:
Traceback (most recent call last): File "zxb.py", line 244, in <module> File "zxb.py", line 209, in main File "optimizer.pyc", line 2021, in optimize File "optimizer.pyc", line 1316, in update_goes_and_comes IndexError: list index out of range > Execution finished.

It's probably my code (I'm so proud of its crapyness...) but maybe the last lines of the optimization message tells you something.
If your code were not ok, the compiler should just end with a compiler error, not with an internal *crash*. This is a compiler bug. :?
I need your code to debug this. If you don't want to publish it here (for whatever reason, contact with me with a private message). Another option is to shorten the code to minimum portion which produces this error.


Re: Stack Bug in ZXB 1.2.5-r1489 ? - boriel - 2010-03-09

apenao Wrote:By the way, when I installed this last version (1.2.5 r1489f) I had to manually uninstall the previous one. This is probably OK, but as in previous versions installations it just overwritten the old data, I thought I better tell you just in case.
This should not happen. Every version should automatically uninstall the previous one. What happened exactly?
On the other hand, try to completely uninstall and reinstall de compiler: If you change any of the installed files in the zxbasic directory (or place a .bas file there), the uninstaller will leave the changed/new files there (all .MSI installers do this, to preserve user modifications; this feature is not unique to ZX BASIC)


Re: Stack Bug in ZXB 1.2.5-r1489 ? - britlion - 2010-03-09

1> Optimize - Admittedly not with the latest version (I've been leaving Optimization off lately), I've seen this same problem with update_comes_and_goes - it seems to happen with larger programs, though obviously I haven't tried any sizing games to find out if that's the case.

2> Installation. For some but not all of the recent beta versions now, I've had the issue where the installer refuses to install because it says there's a newer version already installed. This latest build, I had to uninstall and reinstall. No files in the program folder are modified.


Re: Stack Bug in ZXB 1.2.5-r1489 ? - apenao - 2010-03-09

1) My program: I will send you the program. I have no problem posting it here, but it's quite long and comes with some binary attachments that can't be posted here. I won't be able to do that until tonight thought. I'll also try to isolate parts of the program to see if I can see where the problem is.

2) Instalation: The same as britlion said, but I had some custom .bas files in the library.


Re: Stack Bug in ZXB 1.2.5-r1489 ? - boriel - 2010-03-09

apenao Wrote:1) My program: I will send you the program. I have no problem posting it here, but it's quite long and comes with some binary attachments that can't be posted here. I won't be able to do that until tonight thought. I'll also try to isolate parts of the program to see if I can see where the problem is.
Ok, send me private msg then.

Quote:2) Installation: The same as britlion said, but I had some custom .bas files in the library.
If you put new files in any subdirectory, those files will be unchanged upon uninstallation, so these files and it's folders will be there. The best way to use your own library files is work on a local directory out of the ZX BASIC directories, and use #include "file.bas" instead of #include <file.bas>. This is explained either in the Wiki or in this forum, but I cannot find where Tongue


Re: Stack Bug in ZXB 1.2.5-r1489 ? - apenao - 2010-03-09

Here goes the .bas listing of the program. I'll post the custom library files following this. I have to think of a way to send the binary files.

Ladies and gentlemen, prepare yourself to witness the future of videogames:

Colour Clash of the Titans (aka Trash of the Titans - aka Crap of the Titans - aka Ruins Fighter VII Turbo):

Code:
#include <sinclair.bas> #include <memcopy.bas> #include <keys.bas> REM INICIALIZAR VARIABLES DIM bicho as uinteger: DIM enemigo as uinteger LET protaizda=@arqueroizda: LET protadcha=@arquerodcha LET eneizda=@zeusizda: LET enedcha=@zeusdcha LET bicho=protadcha: LET enemigo=enedcha DIM ACEL AS BYTE: DIM DIF AS BYTE: DIM DIFY AS BYTE DIM GOLPE AS UBYTE: DIM GOLPEE AS UBYTE: DIM HERIDA AS UBYTE: DIM HERIDAE AS UBYTE LET GOLPE=0: LET GOLPEE=0: LET HERIDA=0: LET HERIDAE=0 LET ACEL=0 LET gfxproyizda=@flechaizda: LET gfxproydcha=@flechadcha LET gfxproyeizda=@rayo: LET gfxproyedcha=@rayo DIM VIDA AS UBYTE: DIM VIDAE AS UBYTE LET VIDA=192: LET VIDAE=192 DIM salto as ubyte: DIM disparo as ubyte: DIM saltoE as ubyte: DIM disparoE as ubyte LET salto=0: LET disparo=0 : LET saltoE=0: LET disparoE=0 LET X=174:LET Y=200 : LET XA=174:LET YA=200 :let frame=0 LET XE=174:LET YE=40 : LET XAE=174:LET YAE=40 :let frameE=0 LET dispx=0:let dispy=0:let dispxa=0:let dispya=0 LET dispxe=0: let dispye=0: let dispxea=0: let dispyea=0 DIM VELOCIDAD AS UBYTE: DIM VELOCIDADE AS UBYTE: DIM VELDISPARO AS UBYTE: DIM VELDISPAROE AS UBYTE: DIM SALTAR AS UBYTE: DIM SALTARE AS UBYTE: DIM FUERZA AS UBYTE: DIM FUERZAE AS UBYTE DIM DEMO AS UBYTE: DIM DEMOTIME AS UINTEGER DIM PAUSA AS UINTEGER spriteh (16) border 0 menu: LET DEMOTIME=1200 PAPER 0:INK 7 CLS BRIGHT 1 PRINT BOLD 1; AT 0,3; INK 1;"C";INK 2;"O";INK 3;"L";INK 4;"O";INK 5;"U";INK 6;"R";INK 7;" CLASH OF THE TITANS" PRINT INK 4;AT 2,4;"P: 1 PLAYER" PRINT INK 7; AT 6,1;"H:SELECT HERO" PRINT INK 6; AT 8,2;"MACISTE" PRINT INK 4;AT 9,2;"ZEUS" PRINT INK 5;AT 10,2;"HADES" PRINT INK 3;AT 11,2;"LEGOLAS" BRIGHT 0 PRINT INK 7; AT 6,16;"R:SELECT RIVAL" PRINT INK 6; AT 8,17;"LEGOLAS" PRINT INK 4;AT 9,17;"HADES" PRINT INK 5;AT 10,17;"ZEUS" PRINT INK 3;AT 11,17;"MACISTE" BRIGHT 1 PRINT AT 14,5;INK 7;"S:SELECT SCENARIO" PRINT AT 15,2;INK 1;"RUINS OF THE ANCIENT GREECE" PRINT AT 16,2;INK 3;"RUINS OF THE BRITISH EMPIRE" PRINT AT 17,2;INK 4;"RUINS OF THE ISLAND EGOS" PRINT AT 18,2;INK 6;"RUINS OF THE WORLD'S SOUL" PRINT AT 19,2;INK 2;"RUINS OF THE SPANISH ECONOMY" PRINT ITALIC 1;INK 1;PAPER 7;BRIGHT 0;INVERSE 1; AT 22,8;"ENTER TO START" INK 2 PLOT 6,140: DRAW -3,0:DRAW -2,-2:DRAW 0,-46:DRAW 2,-2: DRAW 112,0: DRAW 2,2: DRAW 0,46: DRAW -2,2: DRAW -3,0 PLOT 127,140: DRAW -3,0:DRAW -2,-2:DRAW 0,-46:DRAW 2,-2: DRAW 120,0: DRAW 2,2: DRAW 0,46: DRAW -2,2: DRAW -3,0 INK 6 PLOT 38,76: DRAW -35,0:DRAW -2,-2: DRAW 0,-46:DRAW 2,-2: DRAW 241,0: DRAW 2,2: DRAW 0,46: DRAW -2,2: DRAW -67,0 INK 1 PLOT 30,172: DRAW -27,0:DRAW -2,-2: DRAW 0,-20:DRAW 2,-2: DRAW 241,0:DRAW 2,2: DRAW 0,20:DRAW -2,2:DRAW -27,0 LET HERO=0:LET RIVAL=0:LET SCENARIO=0:LET JUGADORES=1 menudos: LET ALEA=INT (RND*300): IF ALEA=0 THEN PRINT ITALIC 1;BOLD 1;INK INT (RND*7)+1;AT 0,10;"TRASH": ELSE IF ALEA=1 THEN PRINT ITALIC 1;BOLD 1;INK INT (RND*7)+1;AT 0,10;"CRAP ":ELSE IF ALEA=2 THEN PRINT AT 0,10;ITALIC 1;BOLD 1;INK INT (RND*7)+1;"CLASH":END IF:END IF:END IF PRINT AT 8+HERO,1;INK INT (RND*7)+1;">" PRINT AT 8+RIVAL,16;INK INT (RND*7)+1;">" PRINT AT 15+SCENARIO,1;INK INT (RND*7)+1;">" IF MULTIKEYS (KEYH)<>0 THEN PRINT AT 8+HERO,1;" ":LET HERO=HERO+1:PAUSE 1:PAUSE 5:IF HERO>3 THEN LET HERO=0:END IF:END IF IF MULTIKEYS (KEYR)<>0 THEN PRINT AT 8+RIVAL,16;" ":LET RIVAL=RIVAL+1:PAUSE 1:PAUSE 5:IF RIVAL>3 THEN LET RIVAL=0:END IF:END IF IF MULTIKEYS (KEYS)<>0 THEN PRINT AT 15+SCENARIO,1;" ":LET SCENARIO=SCENARIO+1:PAUSE 1:PAUSE 5:IF SCENARIO>4 THEN LET SCENARIO=0:END IF:END IF IF MULTIKEYS (KEYP)<>0 THEN LET JUGADORES=JUGADORES+1:PAUSE 1: PAUSE 10:IF JUGADORES =3 THEN LET JUGADORES=1:END IF: END IF IF JUGADORES=1 THEN PRINT INK 4;AT 2,4;"P: 1 PLAYER ";AT 3,3;"O:LEFT P:RIGHT U:UP M:FIRE";AT 4,3;" ":ELSE PRINT INK 5;AT 2,16;"P: 2 PLAYERS";AT 4,3;"Q:LEFT W:RIGHT R:UP V:FIRE":END IF IF MULTIKEYS (KEYENTER)<>0 THEN GOTO INICIO: END IF LET DEMOTIME=DEMOTIME-1: IF DEMOTIME=0 THEN LET DEMO=1:LET HERO=INT (RND*4):LET RIVAL=INT (RND*4):LET SCENARIO=INT (RND*5):LET CAMINO=1:GOTO INICIO:END IF GOTO menudos PAUSE 1:PAUSE 0 INICIO: IF HERO=0 THEN LET protaizda=@macisteizda: LET protadcha=@macistedcha: LET gfxproyizda=@ondaizda: LET gfxproydcha=@ondadcha:LET VELOCIDAD=1:LET VELDISPARO=1:LET FUERZA=3: LET SALTAR=80:END IF IF HERO=1 THEN LET protaizda=@zeusizda: LET protadcha=@zeusdcha: LET gfxproyizda=@rayo: LET gfxproydcha=@rayo:LET VELOCIDAD=1:LET VELDISPARO=2:LET FUERZA=2: LET SALTAR=90:END IF IF HERO=2 THEN LET protaizda=@etizda: LET protadcha=@etdcha: LET gfxproyizda=@telefono: LET gfxproydcha=@telefono:LET VELOCIDAD=2:LET VELDISPARO=2:LET FUERZA=2: LET SALTAR=48:END IF IF HERO=3 THEN LET protaizda=@arqueroizda: LET protadcha=@arquerodcha: LET gfxproyizda=@flechaizda: LET gfxproydcha=@flechadcha:LET VELOCIDAD=2:LET VELDISPARO=3:LET FUERZA=1: LET SALTAR=60:END IF IF RIVAL=0 THEN LET eneizda=@arqueroizda: LET enedcha=@arquerodcha: LET gfxproyeizda=@flechaizda: LET gfxproyedcha=@flechadcha:LET VELOCIDADE=2:LET VELDISPAROE=3:LET FUERZAE=1: LET SALTARE=60:END IF IF RIVAL=1 THEN LET eneizda=@etizda: LET enedcha=@etdcha: LET gfxproyeizda=@telefono: LET gfxproyedcha=@telefono:LET VELOCIDADE=2:LET VELDISPAROE=2:LET FUERZAE=2: LET SALTARE=48:END IF IF RIVAL=2 THEN LET eneizda=@zeusizda: LET enedcha=@zeusdcha: LET gfxproyeizda=@rayo: LET gfxproyedcha=@rayo:LET VELOCIDADE=1:LET VELDISPAROE=2:LET FUERZAE=2: LET SALTARE=90:END IF IF RIVAL=3 THEN LET eneizda=@macisteizda: LET enedcha=@macistedcha: LET gfxproyeizda=@ondaizda: LET gfxproyedcha=@ondadcha:LET VELOCIDADE=1:LET VELDISPAROE=1:LET FUERZAE=3: LET SALTARE=80:END IF LET bicho=protaizda: LET enemigo=enedcha IF SCENARIO>0 THEN GOTO ESCENARIOUNO: END IF unchunk (@partenon,16384,3927) GOTO JUEGO ESCENARIOUNO: IF SCENARIO>1 THEN GOTO ESCENARIODOS: END IF unchunk (@stonehedge,16384,3372) GOTO JUEGO ESCENARIODOS: IF SCENARIO>2 THEN GOTO ESCENARIOTRES: END IF unchunk (@pascua,16384,3997) GOTO JUEGO ESCENARIOTRES: IF SCENARIO>3 THEN GOTO ESCENARIOCUATRO: END IF unchunk (@ny,16384,3652) GOTO JUEGO ESCENARIOCUATRO: unchunk (@marbella,16384,3049) JUEGO: LET VIDA=192: LET VIDAE=192 LET salto=0: LET disparo=0 : LET saltoE=0: LET disparoE=0 LET X=174:LET Y=200 : LET XA=174:LET YA=200 :let frame=0 LET XE=174:LET YE=40 : LET XAE=174:LET YAE=40 :let frameE=0 LET XDISP=0:let YDISP=0:let XDISPE=0:let YDISPE=0 LET GOLPE=0: LET GOLPEE=0: LET HERIDA=0: LET HERIDAE=0 memcopy (@logo,16384,2048) memcopy (@logo+2048,22528,256) IF DEMO=1 THEN PRINT AT 12,4;PAPER 1;INK 6;FLASH 1;ITALIC 1;"ENTER TO EXIT DEMO MODE":END IF cpbuffer(X,Y,@buser) andsprite (X,Y,bicho) xorsprite (X,Y,bicho+64) andsprite (32,232,bicho) xorsprite (32,232,bicho+64) cpbuffer(XE,YE,@buserene) andsprite (XE,YE,enemigo) xorsprite (XE,YE,enemigo+64) andsprite (32,8,enemigo) xorsprite (32,8,enemigo+64) bucle: IF DEMO=1 THEN GOTO DEMOMODE: END IF LET O=MULTIKEYS(KEYO) LET P= MULTIKEYS(KEYP) LET M=MULTIKEYS(KEYM) LET Q=MULTIKEYS(KEYU):IF Q>0 AND salto=0 THEN LET salto=SALTAR:END IF IF M>0 AND O>0 AND disparo=0 THEN LET disparo=1:LET XDISP=X: LET YDISP=Y-16: LET XDISPA=X:LET YDISPA=Y-16: LET PROY=gfxproyizda: LET MOVPROY=-VELDISPARO: END IF IF M>0 AND P>0 AND disparo=0 THEN LET disparo=1:LET XDISP=X: LET YDISP=Y+16: LET XDISPA=X:LET YDISPA=Y+16: LET PROY=gfxproydcha: LET MOVPROY=VELDISPARO:END IF IF JUGADORES=1 THEN GOTO INTELIGENCIA: END IF LET OE=MULTIKEYS(KEYQ) LET PE= MULTIKEYS(KEYW) LET QE=MULTIKEYS(KEYV) LET R=MULTIKEYS(KEYR):IF R>0 AND saltoE=0 THEN LET saltoE=SALTARE:END IF IF QE>0 AND OE>0 AND disparoE=0 THEN LET disparoE=1:LET XDISPE=XE: LET YDISPE=YE-16: LET XDISPAE=XE:LET YDISPAE=YE-16: LET PROYE=gfxproyeizda: LET MOVPROYE=-VELDISPAROE: END IF IF QE>0 AND PE>0 AND disparoE=0 THEN LET disparoE=1:LET XDISPE=XE: LET YDISPE=YE+16: LET XDISPAE=XE:LET YDISPAE=YE+16: LET PROYE=gfxproyedcha: LET MOVPROYE=VELDISPAROE:END IF GOTO DECISIONIMPRIME REM MOVIMIENTO ENEMIGO INTELIGENCIA: LET PE=0:LET PO=0:LET QE=0:LET DIF=X-XE: LET DIFY=Y-YE IF Y>YE AND Y-YE>36 THEN LET PE=1:ELSE LET PE=0:END IF IF Y<YE AND YE-Y>36 THEN LET OE=1:ELSE LET OE=0:END IF IF disparo=1 AND saltoE=0 THEN LET QE=1: END IF IF QE>0 AND saltoE=0 THEN LET saltoE=SALTARE:END IF IF Y>YE AND ABS DIF<20 AND disparoE=0 THEN LET disparoE=1:LET XDISPE=XE: LET YDISPE=YE+16: LET XDISPAE=XE:LET YDISPAE=YE+16: LET PROYE=gfxproyedcha: LET MOVPROYE=VELDISPAROE: END IF IF Y<YE AND ABS DIF<20 AND disparoE=0 THEN LET disparoE=1:LET XDISPE=XE: LET YDISPE=YE-16: LET XDISPAE=XE:LET YDISPAE=YE-16: LET PROYE=gfxproyeizda: LET MOVPROYE=-VELDISPAROE: END IF IF Y>YE AND Y<80 THEN LET PE=1:END IF IF YE>Y AND Y>176 THEN LET OE=1:END IF DECISIONIMPRIME: IF O+P>0 OR salto>0 OR OE+PE>0 OR saltoE>0 OR disparo>0 OR disparoE>0 THEN GOSUB imprime : END IF goto bucle DEMOMODE: IF MULTIKEYS (KEYENTER)<>0 THEN GOTO menu: END IF LET P=0:LET O=0:LET Q=0 IF Y<40 THEN LET CAMINO=0:END IF IF Y>210 THEN LET CAMINO=1: END IF IF CAMINO=1 THEN LET O=1:END IF IF CAMINO=0 THEN LET P=1: END IF SEGUNDAOPCION: IF disparoE=1 AND salto=0 THEN LET Q=1: END IF IF Q>0 AND salto=0 THEN LET salto=SALTAR:END IF IF Y<YE AND disparo=0 THEN LET disparo=1:LET XDISP=X: LET YDISP=Y+16: LET XDISPA=X:LET YDISPA=Y+16: LET PROY=gfxproydcha: LET MOVPROY=VELDISPARO: END IF IF Y>YE AND disparo=0 THEN LET disparo=1:LET XDISP=X: LET YDISP=Y-16: LET XDISPA=X:LET YDISPA=Y-16: LET PROY=gfxproyizda: LET MOVPROY=-VELDISPARO: END IF LET PE=0:LET PO=0:LET QE=0:LET DIF=X-XE: LET DIFY=Y-YE IF Y>YE AND Y-YE>36 THEN LET PE=1:ELSE LET PE=0:END IF IF Y<YE AND YE-Y>36 THEN LET OE=1:ELSE LET OE=0:END IF IF disparo=1 AND saltoE=0 THEN LET QE=1: END IF IF QE>0 AND saltoE=0 THEN LET saltoE=SALTARE:END IF IF Y>YE AND ABS DIF<20 AND disparoE=0 THEN LET disparoE=1:LET XDISPE=XE: LET YDISPE=YE+16: LET XDISPAE=XE:LET YDISPAE=YE+16: LET PROYE=gfxproyedcha: LET MOVPROYE=VELDISPAROE: END IF IF Y<YE AND ABS DIF<20 AND disparoE=0 THEN LET disparoE=1:LET XDISPE=XE: LET YDISPE=YE-16: LET XDISPAE=XE:LET YDISPAE=YE-16: LET PROYE=gfxproyeizda: LET MOVPROYE=-VELDISPAROE: END IF IF Y>YE AND Y<80 THEN LET PE=1:END IF IF YE>Y AND Y>176 THEN LET OE=1:END IF GOTO DECISIONIMPRIME stop imprime: IF O<>0 AND Y>8 THEN LET Y=Y-VELOCIDAD:LET bicho=protaizda:let frame=frame+1:if frame>1 then let frame=0:end if: END IF IF P<>0 AND Y<232 THEN LET Y=Y+VELOCIDAD: LET bicho=protadcha:let frame=frame+1:if frame>1 then let frame=0:end if: END IF IF salto>SALTAR/2 THEN LET X=X-1:LET salto=salto-1: ELSE IF salto<1+SALTAR/2 AND salto>0 THEN LET X=X+1: LET salto=salto-1: END IF: END IF IF OE>0 AND YE>8 THEN LET YE=YE-VELOCIDADE:LET enemigo=eneizda:let frameE=frameE+1:if frameE>1 then let frameE=0:end if: END IF IF PE>0 AND YE<232 THEN LET YE=YE+VELOCIDADE: LET enemigo=enedcha:let frameE=frameE+1:if frameE>1 then let frameE=0:end if: END IF IF saltoE>SALTARE/2 THEN LET XE=XE-1:LET saltoE=saltoE-1: ELSE IF saltoE<1+SALTARE/2 AND saltoE>0 THEN LET XE=XE+1: LET saltoE=saltoE-1: END IF: END IF asm halt end asm movbicho: rstbuffer(XA,YA,@buser) rstbuffer(XAE,YAE,@buserene) saltouno: cpbuffer(XE,YE,@buserene) cpbuffer(X,Y,@buser) if disparo<1 then goto saltodos: end if xorsprite (XDISPA,YDISPA,PROY) saltodos: if disparoE<1 then goto saltodosmedio: end if xorsprite (XDISPAE,YDISPAE,PROYE) saltodosmedio: andsprite (X,Y,bicho+frame*32) xorsprite (X,Y,bicho+64+frame*32) movenemigo: andsprite (XE,YE,enemigo+frameE*32) xorsprite (XE,YE,enemigo+64+frameE*32) if disparo<1 then goto saltotres : end if xorsprite (XDISP,YDISP,PROY) saltotres: if disparoE<1 then goto saltotresmedio : end if xorsprite (XDISPE,YDISPE,PROYE) saltotresmedio: LET XA=X:LET YA=Y:LET XAE=XE:LET YAE=YE if disparo<1 then goto saltocuatro:END IF LET YDISP=YDISP+MOVPROY IF YDISP<1 OR YDISP>240 THEN LET disparo=0:gosub DISPEND: END IF let YDISPA=YDISP saltocuatro: if disparoE<1 then goto saltocuatromedio:END IF LET YDISPE=YDISPE+MOVPROYE IF YDISPE<1 OR YDISPE>240 THEN LET disparoE=0:gosub DISPEND: END IF let YDISPAE=YDISPE saltocuatromedio: for coluno=1 to FUERZAE:GOSUB COLISIONESUNO:NEXT FOR COLDOS=1 TO FUERZA:GOSUB COLISIONESDOS:NEXT return DISPIZDA: LET disparo=2 return DISPEND: return COLISIONESUNO: IF Y-YDISPE>16 THEN RETURN: END IF IF X-XDISPE>16 THEN RETURN: END IF LET GOLPE=GOLPE+1 BEEP .005,RND*8 PAPER 8: INK 8 PLOT 248,192-GOLPE DRAW 7,0 IF GOLPE>64 THEN GOTO GANAENE : END IF RETURN COLISIONESDOS: IF YE-YDISP>16 THEN RETURN: END IF IF XE-XDISP>16 THEN RETURN: END IF LET GOLPEE=GOLPEE+1 BEEP .005,RND*8 PAPER 8: INK 8 PLOT 40,192-GOLPEE DRAW 7,0 IF GOLPEE>64 THEN GOTO GANAPROTA : END IF RETURN GANAENE: PRINT FLASH 1;PAPER 2;INK 7; BOLD 1; AT 15,12;"PLY2 WIN!":PAUSE 1:PAUSE 50:FOR PAUSA=O TO 30000:NEXT:GOTO menu GANAPROTA: PRINT FLASH 1;PAPER 3;INK 1; BOLD 1; AT 15,12;"PLY1 WIN!":PAUSE 1:PAUSE 50:FOR PAUSA=O TO 30000:NEXT: GOTO menu end #include <sprite.bas> #include <spritebuffer.bas> #include <unchunk.bas> ondaizda: ASM ondaizda: DEFB 0, 0, 4, 0, 28,128, 57,136 DEFB 99, 25,102, 51,204,103,216,204 DEFB 216,204,204,103,102, 51, 99, 25 DEFB 57,136, 28,128, 4, 0, 0, 0 END ASM ondadcha: ASM DEFB 0, 0, 0, 32, 1, 56, 17,156 DEFB 152,198,204,102,230, 51, 51, 27 DEFB 51, 27,230, 51,204,102,152,198 DEFB 17,156, 1, 56, 0, 32, 0, 0 END ASM telefono: ASM DEFB 127,254,255,255,255,255,240, 15 DEFB 112, 14, 0, 0, 4, 16, 15,248 DEFB 25, 44, 29,100, 63,254, 46,178 DEFB 36,154,127,255,127,255,127,255 END ASM etizda: ASM et: DEFB 128, 1, 0, 0, 0, 0, 0, 0 DEFB 0, 0, 0, 0, 0, 0, 0, 0 DEFB 0, 0,192, 0, 0, 0, 0, 0 DEFB 0, 0,224, 0,128, 1,128, 1 DEFB 224, 1,192, 0,192, 0,192, 0 DEFB 192, 0,192, 0,192, 0,192, 0 DEFB 192, 0,192, 0,128, 0,128, 0 DEFB 128, 1,224, 3,224, 7,224, 7 DEFB 0, 0, 63,252,127,254, 79,238 DEFB 111,254,127,254, 31,230,127, 6 DEFB 0, 62, 3,254, 31,254,127,254 DEFB 15,254, 6,236, 14, 28, 62,124 DEFB 0, 0, 15,252, 31,254, 18,110 DEFB 23,126, 31,254, 16,230, 31,198 DEFB 0, 62, 3,254, 31,254, 63,252 DEFB 15,248, 1,176, 3,240, 15,240 END ASM etdcha: ASM etdcha: DEFB 128, 1, 0, 0, 0, 0, 0, 0 DEFB 0, 0, 0, 0, 0, 0, 0, 0 DEFB 0, 0, 0, 3, 0, 0, 0, 0 DEFB 0, 0, 0, 7,128, 1,128, 1 DEFB 128, 7, 0, 3, 0, 3, 0, 3 DEFB 0, 3, 0, 3, 0, 3, 0, 3 DEFB 0, 3, 0, 3, 0, 1, 0, 1 DEFB 128, 1,192, 7,224, 7,224, 7 DEFB 0, 0, 63,252,127,254,119,242 DEFB 127,246,127,254,103,248, 96,254 DEFB 124, 0,127,192,127,248,127,254 DEFB 127,240, 55, 96, 56,112, 62,124 DEFB 0, 0, 63,240,127,248,118, 72 DEFB 126,232,127,248,103, 8, 99,248 DEFB 124, 0,127,192,127,248, 63,252 DEFB 31,240, 13,128, 15,192, 15,240 END ASM macistedcha: ASM macistedcha: DEFB 192, 7,192, 7,192, 7,192, 7 DEFB 192, 3,128, 1,128, 1,128, 1 DEFB 128, 1,128, 1,192, 1,224, 3 DEFB 248, 15,248, 7,248, 3,248, 3 DEFB 224, 3,224, 3,224, 3,224, 3 DEFB 224, 3,192, 1,192, 0,192, 0 DEFB 192, 0,224, 0,240, 7,224, 15 DEFB 192, 1,192, 1,192,129,193,195 DEFB 15,224, 29,176, 31,240, 15, 96 DEFB 3,128, 27,184, 59,220, 55,236 DEFB 59,236, 29,220, 13,216, 3,192 DEFB 3, 64, 3, 96, 3,176, 3,216 DEFB 7,240, 15,104, 15,248, 7, 48 DEFB 1,192, 13,232, 27,252, 29,246 DEFB 14,246, 6,240, 1,224, 3,192 DEFB 15, 96, 30,116, 24, 60, 12, 24 END ASM macisteizda: ASM macisteizda: DEFB 224, 3,224, 3,224, 3,224, 3 DEFB 192, 3,128, 1,128, 1,128, 1 DEFB 128, 1,128, 1,128, 3,192, 7 DEFB 240, 31,224, 31,192, 31,192, 31 DEFB 192, 7,192, 7,192, 7,192, 7 DEFB 192, 7,128, 3, 0, 3, 0, 3 DEFB 0, 3, 0, 7,224, 15,240, 7 DEFB 128, 3,128, 3,129, 3,195,131 DEFB 7,240, 13,184, 15,248, 6,240 DEFB 1,192, 29,216, 59,220, 55,236 DEFB 55,220, 59,184, 27,176, 3,192 DEFB 2,192, 6,192, 13,192, 27,192 DEFB 15,224, 22,240, 31,240, 12,224 DEFB 3,128, 23,176, 63,216,111,184 DEFB 111,112, 15, 96, 7,128, 3,192 DEFB 6,240, 46,120, 60, 24, 24, 48 END ASM arquerodcha: ASM DEFB 240, 63,224, 15,224, 7,224, 3 DEFB 192, 1,128, 0,128, 0,192, 0 DEFB 224, 16,240, 24,224, 56,224, 17 DEFB 240, 3,240, 7,240, 15,240, 31 DEFB 240, 63,224, 15,224, 7,224, 3 DEFB 192, 1,128, 0,128, 0,192, 0 DEFB 224, 0,224, 0,224, 0,224, 1 DEFB 224, 3,194, 7,135, 7,131,131 DEFB 7,128, 15, 64, 15,240, 7,168 DEFB 27, 68, 54,242, 57,126, 30,143 DEFB 14,193, 1, 66, 14,130, 15, 68 DEFB 5,168, 5,176, 7,128, 7,192 DEFB 7,128, 15, 64, 15,240, 7,168 DEFB 27, 68, 54,242, 57,126, 30,143 DEFB 14,193, 1, 66, 14,130, 15,116 DEFB 13,136, 24,192, 48,112, 56, 56 END ASM arqueroizda: ASM DEFB 252, 15,240, 7,224, 7,192, 7 DEFB 128, 3, 0, 1, 0, 1, 0, 3 DEFB 8, 7, 24, 15, 28, 7,136, 7 DEFB 192, 15,224, 15,240, 15,248, 15 DEFB 252, 15,240, 7,224, 7,192, 7 DEFB 128, 3, 0, 1, 0, 1, 0, 3 DEFB 0, 7, 0, 7, 0, 7,128, 7 DEFB 192, 7,224, 67,224,225,193,193 DEFB 1,224, 2,240, 15,240, 21,224 DEFB 34,216, 79,108,126,156,241,120 DEFB 131,112, 66,128, 65,112, 34,240 DEFB 21,160, 13,160, 1,224, 3,224 DEFB 1,224, 2,240, 15,240, 21,224 DEFB 34,216, 79,108,126,156,241,120 DEFB 131,112, 66,128, 65,112, 46,240 DEFB 17,176, 3, 24, 14, 12, 28, 28 END ASM flechaizda: ASM DEFB 0, 0, 0, 0, 0, 0, 0, 0 DEFB 0, 0, 0, 0, 24, 18,120, 36 DEFB 255,252,120, 36, 24, 18, 0, 0 DEFB 0, 0, 0, 0, 0, 0, 0, 0 END ASM flechadcha: ASM DEFB 0, 0, 0, 0, 0, 0, 0, 0 DEFB 0, 0, 0, 0, 72, 24, 36, 30 DEFB 63,255, 36, 30, 72, 24, 0, 0 DEFB 0, 0, 0, 0, 0, 0, 0, 0 END ASM zeusizda: ASM DEFB 224, 63,192, 31,224, 15,224, 15 DEFB 192, 7,128, 3, 0, 1, 0, 1 DEFB 0, 1,128, 3,128, 7,128, 7 DEFB 128, 7,128, 1,128, 0,192, 0 DEFB 224, 63,192, 31,224, 15,224, 15 DEFB 192, 7,128, 3, 0, 1, 0, 1 DEFB 0, 1, 96, 1,240, 1,224, 3 DEFB 192, 7,128, 7, 0, 7, 0, 7 DEFB 15,128, 31,192, 9, 96, 0, 32 DEFB 31,160, 25,184, 95,132,175, 20 DEFB 47, 44, 47, 56, 38, 48, 38, 0 DEFB 40, 16, 40, 8, 40, 6, 15,254 DEFB 15,128, 31,192, 9, 96, 0, 32 DEFB 31,160, 25,184, 95,132,175, 20 DEFB 151, 20, 11, 20, 4, 28, 10, 0 DEFB 17, 16, 48,144, 96, 16,127,240 END ASM zeusdcha: ASM DEFB 252, 7,248, 3,240, 7,240, 7 DEFB 224, 3,192, 1,128, 0,128, 0 DEFB 128, 0,192, 1,224, 1,224, 1 DEFB 224, 1,128, 1, 0, 1, 0, 3 DEFB 252, 7,248, 3,240, 7,240, 7 DEFB 224, 3,192, 1,128, 0,128, 0 DEFB 128, 0,128, 6,128, 15,192, 7 DEFB 224, 3,224, 1,224, 0,224, 0 DEFB 1,240, 3,248, 6,144, 4, 0 DEFB 5,248, 29,152, 33,250, 40,245 DEFB 52,244, 28,244, 12,100, 0,100 DEFB 8, 20, 16, 20, 96, 20,127,240 DEFB 1,240, 3,248, 6,144, 4, 0 DEFB 5,248, 29,152, 33,250, 40,245 DEFB 40,233, 40,208, 56, 32, 0, 80 DEFB 8,136, 9, 12, 8, 6, 15,254 END ASM rayo: ASM DEFB 0, 0, 0, 0, 0, 7, 0, 11 DEFB 1, 21, 2,170, 5, 84, 10,168 DEFB 21, 80, 42,160, 84, 64,168, 0 DEFB 208, 0,224, 0, 0, 0, 0, 0 END ASM buser: ASM buser: defb 0,0,0,0,0,0,0,0 defb 0,0,0,0,0,0,0,0 defb 0,0,0,0,0,0,0,0 defb 0,0,0,0,0,0,0,0 defb 0,0,0,0,0,0,0,0 defb 0,0,0,0,0,0,0,0 END ASM buserene: ASM buserene: defb 0,0,0,0,0,0,0,0 defb 0,0,0,0,0,0,0,0 defb 0,0,0,0,0,0,0,0 defb 0,0,0,0,0,0,0,0 defb 0,0,0,0,0,0,0,0 defb 0,0,0,0,0,0,0,0 END ASM marbella: asm incbin"marbella.rle" END ASM ny: asm incbin"ny.rle" END ASM pascua: asm incbin"pascua.rle" END ASM stonehedge: asm incbin"stonehedge.rle" END ASM logo: asm incbin"ruinsfighter.bin" END ASM partenon: ASM incbin"partenon.rle" END ASM



Re: Stack Bug in ZXB 1.2.5-r1489 ? - apenao - 2010-03-09

Unchunk: This is the uncompression routine by S.Romero (I think, but not sure) posted in the Speccy.org wiki:

Code:
SUB unchunk (source as uinteger,display as uinteger,size as uinteger) POKE uinteger @datosch,source: POKE uinteger @datosch+2,display: POKE uinteger @datosch+4,size gosub chunk END SUB datosch: ASM sourcech: defw 0 displaych: defw 0 sizech: defw 0 END ASM chunk: ASM ; Prueba de descompresion RLE ; Desempaquetamos un SCR comprimido con RLE sobre la pantalla ;ORG 32768 ; Cargamos los datos y preparamos nuestra rutina LD HL, (sourcech) LD DE, (displaych) LD BC, (sizech) ;CALL RLE_decompress ;; ;; RLE_decompress ;; Descomprime un bloque de datos RLE de memoria a memoria. ;; ;; Entrada a la rutina: ;; ;; HL = dirección origen de los datos RLE. ;; DE = destino donde descomprimir los datos. ;; BC = tamaño de los datos comprimidos. ;; RLE_decompress: RLE_dec_loop: ld a,(hl) ; leemos un byte cp 192 jp nc, RLE_dec_compressed ; si byte > 192 = está comprimido ld (de), a ; si no está comprimido, escribirlo inc de inc hl dec bc RLE_dec_loop2: ld a,b or c jr nz, RLE_dec_loop ret ; miramos si hemos acabado RLE_dec_compressed: ; bucle para descompresión push bc and 63 ; cogemos el numero de repeticiones ld b, a ; lo salvamos en B inc hl ; y leemos otro byte (dato a repetir) ld a, (hl) RLE_dec_loop3: ld (de),a ; bucle de escritura del dato B veces inc de djnz RLE_dec_loop3 inc hl pop bc ; recuperamos BC dec bc ; Este DEC BC puede hacer BC=0 si los datos ; RLE no correctos. Cuidado (mem-smashing). dec bc jr RLE_dec_loop2 ret END ASM



Re: Stack Bug in ZXB 1.2.5-r1489 ? - apenao - 2010-03-09

Sprite.bas: This is a sprite shifting routine by Johnatan Cauldwell. I modified it a bit so it could not only XOR graphics, but also AND, OR and stright PRINT. I only use the AND and XOR because I love masked graphics.

It's too slow ATM, so it flickers a lot (which is good for a game made for the crap games compo). I want to make a version that works in a backbuffer and then copy the buffer to screen. In fact that's what I am doing at the moment (the transfer routine), but it's my first ever assembler routine and I'm having problems Smile I'll post it when it's finished Smile

Code:
SUB psprite (xd as ubyte,yd as ubyte,gfx as uinteger) POKE @esprite,xd: POKE @esprite+1,yd: POKE Uinteger (@esprite+2),gfx POKE @xor1,121:POKE @xor2,122:POKE @xor3,123 gosub printsprite END SUB SUB xorsprite (xd as ubyte,yd as ubyte,gfx as uinteger) POKE @esprite,xd: POKE @esprite+1,yd: POKE Uinteger (@esprite+2),gfx POKE @xor1,169:POKE @xor2,170:POKE @xor3,171:POKE @mask+1,0: POKE @carry,167':POKE @esprite+5,7:'POKE @esprite+4,255':POKE @esprite+6,60 gosub printsprite END SUB SUB andsprite (xd as ubyte,yd as ubyte,gfx as uinteger) POKE @esprite,xd: POKE @esprite+1,yd: POKE Uinteger (@esprite+2),gfx POKE @xor1,161:POKE @xor2,162:POKE @xor3,163:POKE @mask+1,255:POKE @carry,0':POKE @esprite+5,0:POKE @esprite+4,246'230':POKE @esprite+6,0 gosub printsprite END SUB SUB orsprite (xd as ubyte,yd as ubyte,gfx as uinteger) POKE @esprite,xd: POKE @esprite+1,yd: POKE Uinteger (@esprite+2),gfx POKE @xor1,177:POKE @xor2,178:POKE @xor3,179 gosub printsprite END SUB SUB spriteh (h as ubyte) POKE @altura+1,h END SUB esprite: ASM xp: defb 0 yp: defb 0 gfxdir: defw 0 ; This is the sprite routine and expects coordinates in (c ,b) form, ; where c is the vertical coord from the top of the screen (0-176), and ; b is the horizontal coord from the left of the screen (0 to 240). ; Sprite data is stored as you'd expect in its unshifted form as this ; routine takes care of all the shifting itself. This means that sprite ; handling isn't particularly fast but the graphics only take 1/8th of the ; space they would require in pre-shifted form. ; On entry HL must point to the unshifted sprite data. sprit7: xor 7 ; complement last 3 bits. inc a ; add one for luck! sprit3: rl d ; rotate left... rl c ; ...into middle byte... rl e ; ...and finally into left character cell. dec a ; count shifts we've done. jr nz,sprit3 ; return until all shifts complete. ; Line of sprite image is now in e + c + d, we need it in form c + d + e. ld a,e ; left edge of image is currently in e. ld e,d ; put right edge there instead. ld d,c ; middle bit goes in d. ld c,a ; and the left edge back into c. jr sprit0 ; we've done the switch so transfer to screen. END ASM printsprite: ASM sprite: ld hl,(gfxdir) ld bc,(xp) ld (dispx),bc ; store coords in dispx for now. call scadd ; calculate screen address. END ASM altura: ASM ld a,16 ; height of sprite in pixels. sprit1: ex af,af' ; store loop counter. push de ; store screen address. ld c,(hl) ; first sprite graphic. inc hl ; increment poiinter to sprite data. ld d,(hl) ; next bit of sprite image. inc hl ; point to next row of sprite data. ld (sprtmp),hl ; store it for later. END ASM mask: ASM ld e,0 ; blank right byte for now. ld a,b ; b holds y position. and 7 ; how are we straddling character cells? jr z,sprit0 ; we're not straddling them, don't bother shifting. cp 8 ; 5 or more right shifts needed? jr nc,sprit7 ; yes, shift from left as it's quicker. end asm carry: asm and a ; oops, carry flag is set so clear it. sprit2: rr c ; rotate left byte right... rr d ; ...through middle byte... rr e ; ...into right byte. dec a ; one less shift to do. jr nz,sprit2 ; return until all shifts complete. sprit0: pop hl ; pop screen address from stack. ld a,(hl) ; what's there already. END ASM xor1: ASM xor c ; merge in image data. a9 169 a1 161 79 121 b1 177 ld (hl),a ; place onto screen. inc l ; next character cell to right please. ld a,(hl) ; what's there already. END ASM xor2: ASM xor d ; merge with middle bit of image. aa 170 a2 162 7a 122 b2 178 ld (hl),a ; put back onto screen. inc l ; next bit of screen area. ld a,(hl) ; what's already there. END ASM xor3: ASM xor e ; right edge of sprite image data. ab 171 a3 163 7b 123 b3 179 ld (hl),a ; plonk it on screen. ld a,(dispx) ; vertical coordinate. inc a ; next line down. ld (dispx),a ; store new position. and 63 ; are we moving to next third of screen? jr z,sprit4 ; yes so find next segment. and 7 ; moving into character cell below? jr z,sprit5 ; yes, find next row. dec l ; left 2 bytes. dec l ; not straddling 256-byte boundary here. inc h ; next row of this character cell. sprit6: ex de,hl ; screen address in de. ld hl,(sprtmp) ; restore graphic address. ex af,af' ; restore loop counter. dec a ; decrement it. jp nz,sprit1 ; not reached bottom of sprite yet to repeat. ret ; job done. sprit4: ld de,30 ; next segment is 30 bytes on. add hl,de ; add to screen address. jp sprit6 ; repeat. sprit5: ld de,63774 ; minus 1762. add hl,de ; subtract 1762 from physical screen address. jp sprit6 ; rejoin loop. ; This routine returns a screen address for (c, b) in de. scadd: ld a,c ; get vertical position. and 7 ; line 0-7 within character square. add a,64 ; 64 * 256 = 16384 (Start of screen display) ld d,a ; line * 256. ld a,c ; get vertical again. rrca ; multiply by 32. rrca rrca and 24 ; high byte of segment displacement. add a,d ; add to existing screen high byte. ld d,a ; that's the high byte sorted. ld a,c ; 8 character squares per segment. rlca ; 8 pixels per cell, mulplied by 4 = 32. rlca ; cell x 32 gives position within segment. and 224 ; make sure it's a multiple of 32. ld e,a ; vertical coordinate calculation done. ld a,b ; y coordinate. rrca ; only need to divide by 8. rrca rrca and 31 ; squares 0 - 31 across screen. add a,e ; add to total so far. ld e,a ; hl = address of screen. ret dispx: defb 0 ; general-use coordinates. dispy: defb 0 sprtmp: defw 0 ; sprite temporary address. END ASM



Re: Stack Bug in ZXB 1.2.5-r1489 ? - boriel - 2010-03-09

apenao Wrote:Here goes the .bas listing of the program. I'll post the custom library files following this. I have to think of a way to send the binary files.
You should be able to upload .zip files attached to the previous message (I'm enabling them). :wink: