; ; ; ; F A L D O W N F O R E V E R ; ; by fikee 2004 ; ; this game is optimalized for lenght ; but i stopped with it exactly when i was sure that it was shorter than 1024B (including basic ;loader) ... so there are some places in the code which can be shorter (say -30 bytes) but i ;don't care... ; wallatr .EQU 64+8 ;bright blue emptatr .EQU 64+7*8 ;bright white shadatr .EQU 7*8 ;white prntbuf .EQU 23296 ;print buffer, should be unused cause i have my work space there ;here are data ;font, 5 pixels for a letter, unused letters are not present .ORG 34048 font .BYTE 0,0,0,0,0 ;space .BYTE 11111110b .BYTE 10000010b .BYTE 10000010b .BYTE 10000010b .BYTE 11111110b .BYTE 11110000b ;1 .BYTE 00010000b .BYTE 00010000b .BYTE 00010000b .BYTE 11111110b .BYTE 11111110b .BYTE 00000010b .BYTE 11111110b .BYTE 10000000b .BYTE 11111110b .BYTE 11111110b .BYTE 00000010b .BYTE 11111110b .BYTE 00000010b .BYTE 11111110b .BYTE 10000000b .BYTE 10000000b .BYTE 11111110b .BYTE 00000010b .BYTE 00000010b .BYTE 11111110b .BYTE 10000000b .BYTE 11111110b .BYTE 00000010b .BYTE 11111110b .BYTE 11111110b .BYTE 10000000b .BYTE 11111110b .BYTE 10000010b .BYTE 11111110b .BYTE 11111110b .BYTE 00000010b .BYTE 00000010b .BYTE 00000010b .BYTE 00000010b .BYTE 11111110b .BYTE 10000010b .BYTE 11111110b .BYTE 10000010b .BYTE 11111110b .BYTE 11111110b .BYTE 10000010b .BYTE 11111110b .BYTE 00000010b .BYTE 11111110b .BYTE 11111110b ;A .BYTE 10000010b .BYTE 11111110b .BYTE 10000010b .BYTE 10000010b .BYTE 11111110b ;B .BYTE 10000010b .BYTE 11111110b .BYTE 10000100b .BYTE 11111100b .BYTE 11111110b ;C .BYTE 10000000b .BYTE 10000000b .BYTE 10000000b .BYTE 11111110b .BYTE 11111100b .BYTE 10000110b .BYTE 10000010b .BYTE 10000110b .BYTE 11111100b .BYTE 11111110b .BYTE 10000000b .BYTE 11111110b .BYTE 10000000b .BYTE 11111110b .BYTE 11111110b .BYTE 10000000b .BYTE 11111110b .BYTE 10000000b .BYTE 10000000b .BYTE 11111110b .BYTE 10000000b .BYTE 10000010b .BYTE 10000010b .BYTE 11111110b .BYTE 11111110b .BYTE 00010000b .BYTE 00010000b .BYTE 00010000b .BYTE 11111110b .BYTE 10000010b .BYTE 10001110b .BYTE 11111000b .BYTE 10001110b .BYTE 10000010b .BYTE 10000000b .BYTE 10000000b .BYTE 10000000b .BYTE 10000000b .BYTE 11111110b .BYTE 11101110b .BYTE 10101010b .BYTE 10111010b .BYTE 10000010b .BYTE 10000010b .BYTE 10000010b .BYTE 11100010b .BYTE 10010010b .BYTE 10001110b .BYTE 10000010b .BYTE 11111110b .BYTE 10000010b .BYTE 11111110b .BYTE 10000000b .BYTE 10000000b .BYTE 11111110b .BYTE 10000010b .BYTE 11111110b .BYTE 10000100b .BYTE 10000010b .BYTE 10000010b .BYTE 10000010b .BYTE 10000010b .BYTE 10000010b .BYTE 11111110b .BYTE 10000010b .BYTE 10000010b .BYTE 11101110b .BYTE 00101000b .BYTE 00111000b .BYTE 10000010b .BYTE 10000010b .BYTE 10111010b .BYTE 10101010b .BYTE 11101110b .BYTE 10000010b .BYTE 10000010b .BYTE 11111110b .BYTE 00010000b .BYTE 00010000b .BYTE 00010000b ;arrow .BYTE 00010000b .BYTE 01111100b .BYTE 00111000b .BYTE 00010000b .BYTE 0 .BYTE 0 .BYTE 0 .BYTE 00110000b .BYTE 00110000b ;six frames of ball animation, only seven bytes for frame, the 8th is not drawed ballgfx .BYTE 00110000b .BYTE 00101111b .BYTE 00100001b .BYTE 00101010b .BYTE 01000010b .BYTE 01111010b .BYTE 00000100b .BYTE 00010000b .BYTE 00011100b .BYTE 00100011b .BYTE 00101010b .BYTE 01100010b .BYTE 00011100b .BYTE 00000100b .BYTE 00001000b .BYTE 00010100b .BYTE 00100010b .BYTE 01001001b .BYTE 00100010b .BYTE 00010100b .BYTE 00001000b .BYTE 00000100b .BYTE 00011100b .BYTE 01100010b .BYTE 00101010b .BYTE 00100011b .BYTE 00011100b .BYTE 00010000b .BYTE 00000110b .BYTE 01111010b .BYTE 01000010b .BYTE 00101010b .BYTE 00100001b .BYTE 00101111b .BYTE 00110000b .BYTE 0 .BYTE 00111110b .BYTE 00100010b .BYTE 00101010b .BYTE 00100010b .BYTE 00111110b .BYTE 0 ;skull gfx data 8 bytes skull .BYTE 11111111b .BYTE 11011011b .BYTE 11111111b .BYTE 00011000b .BYTE 11000011b .BYTE 00111100b .BYTE 11000011b .BYTE 0 ;values for color effect, it will be unpacked and stored at $8900 colrsdt .BYTE 122,126,124,125,121,123 .BYTE 11101100b, 10011111b, 11001011b, 11110001b, 10001001b .BYTE 11111001b, 00011011b, 11111101b, 11110001b, 10011101b, 11111111b, .BYTE 10100110b ;------------------------------------------------------- ;init part, some unpacking and moving data xor a ;border is black out (254), a ld b,6 ;"unpack" of attrinutes for menu color effect ld de,$8900 ld hl, colrsdt cldt1 ld a, (hl) inc hl push bc ld b, 6 cldt2 ld (de), a inc de djnz cldt2 pop bc djnz cldt1 ld de, $9000 ;move data for generating walls ld c, 10 ;to $9000 for simpler adressing ldir ; ;here starts game menu , programm will jump here after game over repeat call cls ld hl, 16520 ;print menu screen ld de, text ld b, 16 call print ld hl, 18443 ld b, 10 call print ld l, $4B ld b, 10 call print ld l, $8B ld b, 10 call print ld hl, 20483 ld b, 26 call print ld l, $4B ld b, 10 call print ;main game loop: color effect and checking keys colrs halt halt halt ld hl, 22528+32 ;menu color effect ld de, 22528 ld bc, 736 ldir ld e,255 ld b, 33 ;b is decremented one time by ldd and 32 times by djnz colrs2 ld hl, $8923 colrs1 ldd ld a, l or a jr nz, colrs3 ld l, 35 colrs3 djnz colrs1 ld (colrs2+1), hl ld a, $f7 ;check for keys 1-2-3 in a, (254) ld c, a and 1 jr nz, no1prss ld hl, kop jr gmeinit no1prss ld a,c and 2 jr nz, n2prss ld hl, kmn jr gmeinit n2prss ld a,c and 4 jr nz, colrs ld hl, ksn gmeinit ld (chckkey+1), hl ;modify CALL argument for checking in-game keys ld hl, initdat ld de, score ld c, 14 ldir ;set all game variables to start values call cls ;------------------------------------------------------ ;main game loop main halt halt ld hl, (ballpix) ;store old pixel adress ld (oballpix), hl ld de, score ld hl, 20705 ld b, 4 call print ;print score chckkey call kop ;return bit 0 of B for right ; bit 1 of B for left ld hl, (ballatr) ld c, 31 ld a, b and 1 jr z, norght ; RIGHT pressed? inc l ld a, (hl) cp wallatr ;is there wall? jr z, nomove ld a, l and c ;x position overflow ? jr z, nomove ld (ballatr), hl ;everything is ok, store new position ld hl, ballpix inc (hl) jr nomove norght ld a,b and 2 jr z, nomove ;LEFT pressed? ld a, l and c jr z, nomove ;x position underflow ? dec l ld a, (hl) cp wallatr ;is there wall ? jr z, nomove ld (ballatr), hl ;ok..... ld hl, ballpix dec (hl) nomove ld hl, timer3 dec (hl) jr z, scroll call updball ;if screen will not scroll then update ball only jp logic scroll ld (hl), 2 ld hl, (ballatr) ;check for collision ld de, 32 add hl, de ld a, (hl) cp wallatr jr nz, nowall sbc hl, de sbc hl, de ld a, h cp 88 jp c, gameovr ;yep, we are out of screen ld (ballatr),hl ;else move ball up ld hl, (ballpix) ;do it for pixel adress too ld a, l cp 32 ;check for crossing 256b boundary jr nc, sameprt ;same part of videoram ld h, 64 ;upper part add a, 224 ld l, a jr skipsub sameprt sbc hl, de skipsub ld (ballpix), hl ;update pixel adress nowall call updball ;show ball at new position and delete old position ld bc, 768+64 ;all attributes without top row and WITH 3 rows of buffer ld hl, 22528+32 ld de, 22528 ldir ;scroll walls up ld a, (timer) dec a jp nz, nonewpd ;time for new walls? ld hl, score + 3 ;increment score call incdig ;actually i have not a real number for score dec hl call nc, incdig ;i just modify 4-chars string dec hl ;so i dont need number to string subroutine call nc, incdig dec hl call nc, incdig ld hl, delay ld a, (hl) dec hl ld (hl), a ;refresh timer1 dec hl inc (hl) ;add one to padno (wall counter) ld a, r ;generating "random" walls ld b, a and 00111000b ;i get number from register R rra ;as it looks nearly random rra rra ;lower 6 bits are pointer to bit (!) based table ld l, a ; of predefined walls (the binaries after color table) ld h, $90 ld a, b and 7 ld b, a ld a, (hl) inc l ld d, (hl) inc l ld e, (hl) genrt rra ;and put 16 bits from table to register DE rr d rr e djnz genrt ld hl, prntbuf ld b, 96 ld a, 120 clrbuf ld (hl), a inc l djnz clrbuf ;clear work space by attributes for empty places ld ix, prntbuf ld b,16 ld hl, $4838 ;H=attr for wall, L=attr for shadow shad1 rl e rl d jr nc, shd1 ;skip rendering if bit is 0 ld (ix+0), h ;render wall (2x2) ld (ix+1), h ld (ix+32),h ld (ix+33), h ld (ix+34), l ;render shadow ld (ix+65), l ld (ix+66), l shd1 inc ix ;next adress inc ix djnz shad1 ld (prntbuf + 64 ), a ;to avoid shade overflow from second to third line sound ld c,16 ;simply noise sound routine ld h, b ;get bytes from begining of ROM snd1 ld a, (hl) and 16 ;mask out (254), a ;play it inc l ;next byte djnz snd1 jr logic ;go to game logic part nonewpd ld (timer), a ;store timer ld hl, prntbuf+64 ;new row in buffer ld a, 120 ld b, 32 nnwp ld (hl), a inc l djnz nnwp ;here i do something about delays and so logic ld hl, delay ;if padno=16 ld a, (padno) ;then decrease delay between walls ;and reset padno ;delay is to short (<5) and 16 ;then left it unchanged jr z, tim1 ld a, 1 ld (padno), a ld a, (hl) cp 5 jr c, tim1 dec a ld (hl), a tim1 jp main ;game over gameovr ld hl, 23008 ld b, 128 gamvr1 ld (hl), 114 inc hl djnz gamvr1 ;create yellow area with red ink ld hl, 20491 ld b, 10 ld de, ovrtxt call print ;print "GAME OVER" ld b, 4 ld hl, 20491+32+3 ld de, score call print ;print "SCORE" ld hl, (ballpix) ;and show skull at position of ball ld de, skull ;(there is an error and sometimes it is placed somewhere ld b, 8 ;else) gamvr2 ld a, (de) inc de ld (hl), a inc h djnz gamvr2 ld hl, (ballatr) ld b, 200 gamvr3 halt ;waiting for 200*2/50= 8 sec halt ld a, 7 and b or 120 ld (hl), a ;changing of skull ink djnz gamvr3 jp repeat ;go to menu ;-------------------------------------------- updball ld hl, (oballpix) xor a ld b, 7 ;clear old ball position clrball ld (hl),a inc h djnz clrball ld b, 7 ld hl, (ballpix) frm ld de, ballgfx shwball ld a, (de) ;showball inc e ld (hl),a inc h djnz shwball ld a, e cp $C5 ;the last frame of animation? jr nz, nextfra ld a, $9B ;then go back at first frame nextfra ld (frm+1), a ;store pointer to next frame ret ;-------------------------------------------- ;-------------------------------------------- ;simply increase char at (hl) ;if value is too high ;then set CY=1 and set char to "0" incdig ld a, (hl) inc a cp 11 jr nz, incdig1 ld a, 1 incdig1 ld (hl), a ret ;***opt ;-------------------------------------------- ;check keys O,P ;set port for reading ;and mask for keys kop ld a, 223 ld de, $0102 jr allkeys ;-------------------------------------------- ;check keys M,N kmn ld a, 127 ld de, $0408 jr allkeys ;--------------------------------------------- ;check sinclair 2 ksn ld a, 239 ld de, $0810 allkeys in a, (254) ;this is part shared for all types of control ld c, a ;read port 254 ld b, 0 ;and set bit 0 and 1 of reg B and d ;according key pressed jr nz, allk1 inc b allk1 ld a, c and e ret nz inc b inc b ret ;***/opt ;------------------------------------------ ;print b chars from (de) at (hl) print ld a, (de) ;get char ld c, a add a, a add a, a add a, c ;a=a*5 push hl push de push bc ld d, $85 ;high byte of font ld e, a ;low byte from a ld b,5 print1 ld a, (de) inc e ld (hl), a inc h djnz print1 ;print 5 rows of pixel pop bc pop de pop hl inc de ;next char adress inc l ;adress on the screen where next char will be placed djnz print ret ;--------------------------------------------- cls ld hl, 16384 ;clear pixels ld de, 16385 ld bc, 6144 xor a ld (hl), a ldir ld bc, 864 ;clear attr and attr buffer ld (hl), 120 ldir ret ;--------------------------------------------- ;constants ;initial values for variables used at start of every game initdat .BYTE 1,1,1,1 ;score = 0000 .BYTE 1 ;number of passed walls .BYTE 14, 14 ;timer for pads and starting delay .BYTE 2 ;timer3 screen frames without scroll .WORD 18671 ;pixel adress of ball .WORD 23023 ;attr adress of ball .WORD 18671 ;old pixel adress ;texts are not in ascii, it is just offset to font area ; text .BYTE 16,11,20,20,14,1,27,22,29,16,1,24,15,26,15,24 ;"FALLDOWN FOREVER" .BYTE 2,0,0,19,15,28,6,0,1,23 ;"1 KEYS OP" .BYTE 3,0,0,19,15,28,6,0,21,22 ;"2 KEYS MN" .BYTE 4,0,0,6,18,22,13,20,0,3 ;"3 SINCL 2" .BYTE 19,15,15,23,0,28,1,25,24,0,12,11,20,20,0 ;"KEEP YOUR BALL " .BYTE 16,11,20,20,18,22,17,30,30,30,30 ;"FALLING...." .BYTE 16,18,19,15,15,0,3,1,1,5 ;"FIKEE 2004" ovrtxt .BYTE 17,11,21,15,0,0,1,26,15,24 ;"GAME OVER" ;--------------------------------------------- ;variables, these zeroes are not present in code, it is here ;just for easier adressing score .BYTE 0,0,0,0 padno .BYTE 0 timer .BYTE 0 delay .BYTE 0 timer3 .BYTE 0 ballpix .WORD 0 ballatr .WORD 0 oballpix .WORD 0 seed .WORD 0 .END