Stack Bug in ZXB 1.2.5-r1489 ? - britlion - 03-05-2010
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 - 03-07-2010
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 - 03-08-2010
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
Re: Stack Bug in ZXB 1.2.5-r1489 ? - boriel - 03-08-2010
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 - 03-08-2010
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 - 03-08-2010
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 - 03-08-2010
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 - 03-08-2010
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 - 03-09-2010
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 - 03-09-2010
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 - 03-09-2010
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
Re: Stack Bug in ZXB 1.2.5-r1489 ? - apenao - 03-09-2010
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 - 03-09-2010
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 - 03-09-2010
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 I'll post it when it's finished 
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 - 03-09-2010
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:
|