; Big Baps. ; (C) Copyright 2007 Jonathan Cauldwell. ; An entry for the 2007 Minigame competition, 4k category. ; Project started 06.07.2007 @ 15:58. ; Project completed 10.07.2007 @ 14:24. ; Definitions. LADDER equ 14 ; Start address. As usual for 4K minigames it's in a BASIC REM statement. org 23769 ; Initialisation. ; Set up UDGs. ld hl,udgs ; UDG graphics. ld (23675),hl ; set the system variable to point to them. ; Set up the blank sprite. ld hl,blkspr ; blank sprite. ld (hl),255 ; write first byte. inc hl ; second byte. ld (hl),192 ; write second byte. dec hl ; start of sprite. ld de,blkspr+2 ; next line down. ld bc,18 ; 18 more bytes left. ldir ; set up first sprite. ; Screen colours. xor a ; zero is code for black. call 8859 ; set the border colour. ld hl,23693 ; permanent attributes system variable. ld (hl),71 ; set to bright white on black. ; Wait for player to start game. waitg call 654 ; fetch keypress. ld a,e ; result in accumulator. cp 33 ; ENTER key pressed? jr nz,waitg ; no, wait. ; Okay, let's play. call 3503 ; clear the screen. ; Display the extra lives icon at the side of the screen. ld hl,164+208*256 ; load coordinates of extra lives sprite into hl. ld (dispx),hl ; sprite routine coordinates. ld hl,psplr ; player sprite, left/right. call sprite ; show lives icon. ld de,pantxt ; panel text. ld bc,droom-pantxt ; length of string. call 8252 ; show string. ; Variable initialisation. ld a,3 ; default lives. ld (numlif),a ; initialise lives. ld hl,levdat ; level data. ld (levptr),hl ; set up level pointer. ld hl,xydat ; item position data. ld (xyptr),hl ; set up coords pointer. ld a,255 ; set all bits. ld (matrix+9),a ; enable ketchup bottle. ld hl,matrix ; grid. ld de,matrix+1 ; second byte. ld bc,9 ; 9 positions on grid + bonus. ld (hl),255 ; clear first position. ldir ; clear rest of grid. ld a,90 ; seconds required to complete level. ld (time),a ; set up time. ld a,5 ; dull cyan on black. ld (gcolou),a ; set initial girder colours. ld hl,23695 ; temporary attributes system variable. ld (hl),69 ; cyan ink on black background. ld hl,0 ; zero in hl pair. call sscor ; set and show score. newlev call assem ; assemble level. ld a,(gcolou) ; girder colours. xor 70 ; toggle magenta/cyan. ld (gcolou),a ; set new girder colours. ; Show status panel text. rstart call dlife ; show number of lives. call dtime ; show time. call droom ; show level. ; Initialise enemies. xor a ld (saus1),a ; enable first sausage. ld (saus2),a ; enable first sausage. ld hl,8+48*256 ; coordinates. ld (saus1+1),hl ; set sausage coords. ld ix,saus1 ; sausage pointer. call dsaus ; display sausage. ld hl,8+96*256 ; coordinates. ld (saus2+1),hl ; set sausage coords. ld ix,saus2 ; sausage pointer. call dsaus ; display sausage. ; Set up player. ld hl,128 ; coordinates. ld (playx),hl ; set up player starting position. call dplay ; display player. call onesec ; wait for one second. ld a,b ; zero in accumulator. ld (23672),a ; clear low byte of clock. ; Initialise collectables. call itoff ; remove item from screen. mloop ld hl,(playx) ; player coordinates. ld (oplayx),hl ; store old coordinates before we move. halt call dplay ; delete player. call getkey ; get key state in accumulator. and 2 ; test for left. call nz,mpl ; key is pressed, move that way. ld a,(joyval) ; keypress state. rra ; is right pressed? call c,mpr ; yes, go right. ld a,(joyval) ; keypress state. and 8 ; is up pressed? call nz,mpu ; yes, go up. ld a,(joyval) ; keypress state. and 4 ; is down pressed? call nz,mpd ; yes, go there. call dplay ; display at new position. ld hl,(playx) ; new player position. ld de,(oplayx) ; previous coordinates. and a ; clear carry flag. sbc hl,de ; are they identical? call nz,cbuf ; no - check blocks underfoot. ld a,(23672) ; clock low. cp 50 ; another second elapsed? call nc,second ; another second gone. ld ix,saus1 ; first sprite. halt call msaus ; move sausage. ld ix,saus2 ; second sausage. call msaus ; process it. ld ix,saus1 ; first sprite. call soscol ; check for collision with player. ld ix,saus2 ; second sausage. call soscol ; has he caught the player? call pitem ; process items. call emerge ; prevent sausages emerging together. jr mloop ; back to start of main loop. ; Collectable objects processing. pitem ld a,(itemno) ; present item on screen. inc a ; is there one? jr nz,itonsc ; yes, item on screen routine. ; No object on screen. ld hl,itcnt ; item counter. inc (hl) ; increment. ret nz ; not reached zero yet. call random ; random number. and 13 ; 1 in 8 chance. cp 9 ; is it the shot? jr z,newit0 ; yes, that'll do. newitm call ranitm ; get random item number. ld b,a ; store in b register. call getmat ; get matrix position address. ld a,(hl) ; find contents there. inc a ; is it empty? jr nz,newitm ; no, try another. ld a,b ; restore item number. newit0 ld (itemno),a ; set up that item no. call random ; random position. and 2 ; only 2 per level. ld hl,(xyptr) ; x and y positions. call addac1 ld de,itemxy ; item coordinates. ldi ; copy x coord. ldi ; same for y. ; Drop through into display/delete object routine. dobj ld a,(itemno) ; item number. ld hl,(itemxy) ; coordinates. ld (dispx),hl ; display position. jp ditem ; show sprite. itonsc ld hl,itcnt ; counter. inc (hl) ; keep going. jp z,itofsc ; timed out, remove item. ld bc,(playx) ; player coordinates. ld hl,(itemxy) ; item coordinates. ; Check (l, h) for collision with (c, b), strict enforcement. colx16 ld a,l ; x coord. sub c ; subtract x. add a,15 ; add maximum distance. cp 31 ; within x range? ret nc ; no - they've missed. ld a,h ; y coord. sub b ; subtract y. add a,15 ; add maximum distance. cp 31 ; within y range? ret nc ; there's no collision. ; Player has picked up the item. call dobj ; delete item. call tinkle ; sound effect. ld a,(itemno) ; item number. cp 9 ; is it the bonus item? call z,shot ; do grid shot routine. call getmat ; get matrix position address. ld a,(hl) ; present value. cpl ; toggle it. ld (hl),a ; new value. call filmat ; check for full matrix. ld hl,itcnt ; item counter. ld (hl),0 ; start counting from zero. inc hl ; item number. ld (hl),255 ; remove from screen. ret itofsc call dobj ; delete item. itoff ld a,255 ; all bits set = off. ld (itemno),a ; remove item. ret filmat ld (hl),a ; fill position. ld a,(itemno) ; item number. call dgridp ; display grid position. ; Now check if matrix lines are filled. cfill ld hl,matrix ; address of grid. ld b,9 ; items to check. film0 ld a,(hl) ; fetch current cell contents. inc a ; is it empty? ret z ; yes, so grid not full. inc hl ; next matrix position. djnz film0 ; repeat for rest of grid. ld hl,numlif ; number of lives. inc (hl) ; add 1. call remov ; remove items from grid. jp dlife ; show lives. shot call chirp ; play brief sound. call debou ; debounce keys. shot2 call ranitm ; random item number. ld hl,chosen ; last chosen position. cp (hl) ; are they the same? jr z,shot2 ; yes, try another. ld (chosen),a ; set new chosen value. call dblspr ; display sprite. ld b,12 ; shot skill time. shot0 push bc ; store loop counter. halt ; wait for interrupt. call getkey ; get keyboard input. pop bc ; restore loop counter. and a ; anything pressed? jr nz,shot1 ; yes, we've chosen this square. djnz shot0 ; repeat. ld a,(chosen) ; chosen square. call dblspr ; display sprite. jp shot2 shot1 call beep0 ; sound effect. ld a,(chosen) ; chosen square. ld (itemno),a ; set up item number. call dblspr ; delete block. ld a,(chosen) ; return with square in accumulator. ret ranitm call random ; random number. and 15 ; mask away unwanted bits. cp 9 ; only 9 positions. jr nc,ranitm ; not within range. ret ; Display blank square sprite. dblspr call gridc ; set up grid coordinates. ld hl,dispx ; x position. dec (hl) ; look up. dec (hl) ; look up. ld hl,dispy ; y position. dec (hl) ; look left. dec (hl) ; look left. ld hl,blkspr ; blank sprite. call sprite ; display sprite. ld a,(dispx) ; x coord. push af ; remember it. add a,10 ; 10 pixels down. ld (dispx),a ; new position. ld hl,blkspr ; blank sprite. call sprite ; display sprite. ld a,(dispy) ; y coord. add a,10 ; 10 pixels right. ld (dispy),a ; new position. ld hl,blkspr ; blank sprite. call sprite ; display sprite. pop af ; remember first x coord. ld (dispx),a ; restore coord. ld hl,blkspr ; blank sprite. call sprite ; display sprite. ret ; Remove filled positions. remov ld hl,matrix+8 ; grid. ld b,9 ; positions to check. remov0 push hl ; store position. push bc ; store counter. ld a,(hl) ; get cell contents. inc a ; is something there to be removed? call nz,remcel ; yes, remove cell. pop bc pop hl dec hl ; previous position. djnz remov0 ; repeat. ret remcel ld (hl),255 ; reset position. ld a,b ; position number. dec a ; one less. call dgridp ; display grid position. ret ; Play find the pea for time bonus. pea call spams ; screen parameters. ldir ; store screen.. call swap ; play find the pea. call spams ; screen parameters. ex de,hl ; switch back. ldir ; restore screen. call dtime ; restore new time setting. onesec ld b,50 ; one second. delay halt djnz delay ret ; Screen copy parameters. spams ld hl,16384 ; physical screen. ld de,tmpscr ; temp screen. ld bc,6912 ; data to copy. ret ; Display item at grid position held in accumulator. dgridp push af ; store item number. call gridc ; set up grid coordinates. pop af ; restore item number. jp ditem ; show item. ; Copy grid coordinates into dispx. gridc rlca ; multiple of 2. ld e,a ; low byte of table displacement. ld d,0 ; no high byte needed. ld hl,gridxy ; grid x and y positions. add hl,de ; point to coordinates. ld de,dispx ; display coords. ldi ; copy 2 bytes to coordinates. ldi ret ; Matrix coordinates. gridxy defb 12,196,12,216,12,236 defb 32,196,32,216,32,236 defb 52,196,52,216,52,236 ; Assemble next level. ; Clear the area. assem ld hl,screen ; screen area. ld de,screen+1 ; second byte. ld bc,24*32-1 ; size of screen. ld (hl),l ; clear first byte. ldir ; clear rest of buffer. ; Draw basic girders. ld b,4 ; number of platforms. ld hl,screen+3*24 ; first platform address. gird1 ld a,24 ; width of screen. gird0 ld (hl),1 ; draw girder. dec a ; one less to draw. inc hl ; next block along. jr nz,gird0 ; repeat for rest of girder. ld de,4*24 ; distance to next platform. add hl,de ; point there. djnz gird1 ; repeat for all levels. ; Draw the burgers. dfood ld a,8 ; default items needed = 2 burgers, 2 * 4. ld (numfel),a ; set burger bits remaining. ld hl,(levptr) ; level pointer. ld a,(hl) ; fetch byte. cp 48 ; end of data? jr nz,dfood0 ; no, not yet. ld hl,xydat ; item position data. ld (xyptr),hl ; set up coords pointer. ld hl,levdat ; restart at first level. ld a,(hl) ; get first byte. dfood0 inc hl ; next byte. push hl ; store pointer. ld bc,buntop ; bread top. ld hl,screen+3*24 ; first platform. ld e,a ; column number. ld d,0 ; no high byte. add hl,de ; point to address. call food ; transfer food to data. ld bc,cheese ; cheese. call food4 ; transfer it. pop hl ; restore pointer. ld a,(hl) ; fetch byte. inc hl ; next byte. push hl ; store pointer. ld bc,buntop ; bread top. ld hl,screen+3*24 ; first platform. ld e,a ; column number. ld d,0 ; no high byte. add hl,de ; point to address. call food2 ; transfer food to data. ld bc,burger ; burger. call food3 ; transfer burger. pop hl ; restore pointer. ld a,(hl) ; fetch byte. inc hl ; next byte. cp 24 ; beyond range of screen? jp nc,putlad ; yes, only 2 burgers. push hl ; store pointer. ld bc,buntop ; bread top. ld hl,screen+3*24 ; first platform. ld e,a ; column number. ld d,0 ; no high byte. add hl,de ; point to address. call food ; transfer food to data. ld bc,cheese ; cheese. call food4 ; transfer it. pop hl ; restore pointer. ld a,12 ; items needed to hit plates. ld (numfel),a ; set burger bits remaining. ; Now put ladders into level. putlad ld b,(hl) ; number of ladders. inc hl ; first ladder address low. putld0 push bc ; store number of ladders. ld e,(hl) ; ladder low address. inc hl ; second byte of address. ld d,(hl) ; ladder high address. inc hl ; point to next ladder. push hl ; store level data pointer. ex de,hl ; make hl screen buffer address. ld de,23 ; distance to next byte. ld bc,LADDER+5*256 ; ladder byte and height. putld1 ld (hl),c ; restore left side of ladder. inc hl ; next byte. ld (hl),c ; restore right side of ladder. add hl,de ; point to next line down. djnz putld1 pop hl ; restore decompression address. pop bc ; restore ladder count. djnz putld0 ; repeat for all ladders. ld (levptr),hl ; store next level position. ret food4 call food ; transfer 4 lines of burger data. food3 call food ; transfer 3 lines. food2 call food ; transfer 2 lines. ; Transfer burger data to level. food ld e,4 ; bytes to transfer. food0 ld a,(bc) ; source byte. ld (hl),a ; target area. inc bc ; next source. inc hl ; next target. dec e ; one less block to copy. jr nz,food0 ; repeat. ld de,4*24+20 ; distance to next line down. add hl,de ; next address. ret ; Player input and movement routines. ; Get keyboard input. getkey ld d,0 ; zeroise result. ld bc,63486 ; top row 6 - 0. call getbt2 ; put bit 2 into carry status. ld bc,64510 ; top row 1 - 5. call getbt2 ; put bit 2 into carry status. ld bc,61438 ; second row Q - T. call getbt2 ; put bit 2 into carry status. ld e,1 ; bit to test. call getbit ; carry status. ld a,d ; result in accumulator. ld (joyval),a ; store result. ret getbt2 ld e,2 ; bit to test. getbit in a,(c) ; read keyboard port. and e ; test relevant bit. cp e ; if not set then set carry flag. rl d ; rotate into d register. ret ; Debounce controls. debou call getkey ; read all control keys. and a ; anything pressed? jr nz,debou ; yes, wait for release. ret ; Divide hl by d and return in hl. ; Alas, we have to do this manually. idiv xor a ; HL = HL / D ld c,a ; zeroise c. ld e,a ; zeroise e. call idiv4 ; do 8-bit division. push af ; store result on stack. xor a ; zero in accumulator. ld c,a ; clear c register. ld d,a ; clear d register. call idiv4 ; second 8-bit division. pop hl ; restore first result. ld l,h ; low byte of result. ld h,a ; that's the high byte. ret idiv4 ld b,8 ; 8 bits per byte. idiv1 rr d ; divide de by 2. rr e rr c ex af,af' ; store flag. xor a ; zeroise accumulator. cp c ; is c zero? jr z,idiv2 ; yes. ex af,af' ; restore flags. idiv3 rla ; rotate into right of accumulator. and a ; reset carry. djnz idiv1 ; repeat 8 times. ret idiv2 ex af,af' ld (mtbuff),hl ; store number we're dividing. sbc hl,de ; do subtraction. ccf ; reverse carry. jr c,idiv3 ; carry set, bit ld hl,(mtbuff) ; subtracted too much so restore last value. jr idiv3 ; repeat. ; Align player with ladder. aligl ld a,(joyval) ; fetch control byte. and 3 ; moving left/right? ret nz ; yes, don't align. jp mpl ; align left. aligr inc hl ; look to next cell. ld a,(hl) ; examine contents. cp LADDER ; is it a ladder? ret nz ; no, don't move player. ld a,(joyval) ; fetch control byte. and 3 ; moving left/right? ret nz ; yes, don't align. jp mpr ; align right. ; Move player up. mpu ld bc,(playx) ; coordinates. ld a,15 ; distance to last pixel of sprite. add a,c ; find x coordinate. ld c,a ; new coord. call gsblk ; fetch character block. cp LADDER ; is it a ladder? jp nz,aligr ; no, can't go there then. inc hl ; look to next square. ld a,(hl) ; fetch block. cp LADDER ; is it a ladder? ret nz ; no, can't go there then. ld a,(playy) ; horizontal. and 7 ; is sprite on 8-pixel boundary? jp nz,aligl ; no, try to align horizontally. ld hl,playx ; coordinate. dec (hl) ; move up. dec (hl) xor a ; direction is up. ld (playd),a ; set facing direction. ret ; Move player down. mpd ld bc,(playx) ; coordinates. ld a,16 ; distance to pixel below sprite. add a,c ; find x coordinate. cp 144 ; past bottom girder? ret nc ; yes, can't go there. ld c,a ; new coord. call gsblk ; fetch character block. cp LADDER ; is it a ladder? jp nz,aligr ; no, can't move there then. inc hl ; look to next square. ld a,(hl) ; fetch block. cp LADDER ; is it a ladder? ret nz ; no, can't go there then. ld a,(playy) ; horizontal. and 7 ; is sprite on 8-pixel boundary? jp nz,aligl ; no, can't move vertically. ld hl,playx ; coordinate. inc (hl) ; move down. inc (hl) ld a,2 ; direction is down. ld (playd),a ; set facing direction. ret ; Move player left. mpl call checkx ; check x coord is valid. ret nz ; can't move left or right. ld hl,playy ; coordinate. ld a,(hl) ; present value. and a ; at left edge already? ret z ; yes, go no further. dec (hl) ; move left. dec (hl) ld a,3 ; direction is left. ld (playd),a ; set facing direction. ret checkx ld a,(playx) ; vertical coordinate. cp 8 ; is it the top platform? ret z ; that's okay. cp 48 ; second platform? ret z ; that's okay. cp 88 ; third platform? ret z ; that's okay. cp 128 ; fourth platform? ret ; return with zero flag indicating status. ; Move player right. mpr call checkx ; check x coord is valid. ret nz ; can't move left or right. mpr0 ld hl,playy ; coordinate. ld a,(hl) ; present value. cp 176 ; reached right edge? ret nc ; yes, go no further. inc (hl) ; move right. inc (hl) ld a,1 ; direction is right. ld (playd),a ; set facing direction. ret ; Check burger underfoot. cbuf ld bc,(playx) ; player position. ld a,16 ; platforms are 16 pixels below player. add a,c ; add to x position. ld c,a ; coordinate to check. call gsblk ; find block there. cp 2 ; is it before range? jr c,cbuf0 ; yes, try next block. cp LADDER ; is it past range? jr c,pbd ; no, push down. cbuf0 inc hl ; next cell. ld a,(hl) ; get block type. cp 2 ; is it before range? jr c,cbuf1 ; yes, try next block. cp LADDER ; is it past range? jr c,pbd ; no, push down. cbuf1 ld a,b ; y coordinate. and 7 ; straddling cells? ret z ; no, job done. inc hl ; final cell to check. ld a,(hl) ; get block type. cp 2 ; is it before range? ret c ; yes, nothing to do. cp LADDER ; is it past range? ret nc ; yes, job done. ; Push bit of burger down. pbd ld (hl),1 ; restore girder. ld de,24 ; distance to next cell down. add hl,de ; point there. ld (hl),a ; write item. push hl ; store address of block we've written. push af ; store block. call setbxy ; set x and y based on hl. pop af ; restore block address. call dchar ; display food at new pos. ld hl,(dispx) ; coordinates. dec l ; up one. dec h ; left one. ld (dispx),hl ; new coords. ld a,1 ; need a girder. call dchar ; show girder. ; Now check to see if whole item is detached. ; Find the left edge first. cbdet pop hl ; restore food block address. cbdet0 dec hl ; look left. ld a,(hl) ; get item there. and a ; is it space? jr z,cbdet1 ; yes, check for 4 detached blocks. cp LADDER ; is it a ladder? jr z,cbdet1 ; yes, found end. jr cbdet0 ; until we find start. cbdet1 ld b,4 ; number to check. cbdet2 inc hl ; look right. ld a,(hl) ; get block there. and a ; space? ret z ; end of block. cp LADDER ; ladder? ret z ; end of block. djnz cbdet2 ; until end of block. ; It's completely detached. ld de,21 ; distance to start of next row. add hl,de ; point to block start. push hl ; store address. call chirp ; noise. halt ; synch with display. pop hl ; restore block address. ; See what's below. ld b,4 ; block count. ld c,0 ; reset collision flag, block count 4. cbdet3 ld a,(hl) ; first block. and a ; space? jr z,cbdet4 ; that's okay. inc c ; got some sort of collision. cp 1 ; girder? jr z,cbdet4 ; that's fine. call setbxy ; find coordinate. ld a,(dispx) ; vertical position. cp 19 ; reached bottom bit? jr nc,cbdet6 ; yes, just land on plate. ld a,(hl) ; restore block. ld de,24 ; distance to third row. add hl,de ; point there. ld (hl),a ; knock it out. ld de,65512 ; distance back again. add hl,de ; point there. cbdet4 inc hl ; point to next square. djnz cbdet3 ; repeat. ld de,65532 ; distance to start of 2nd row. add hl,de ; point there. push hl ; store destination address. ld de,65512 ; distance to start of 1st row. add hl,de ; point there. pop de ; restore 2nd row address. ld a,c ; fetch "hit" flag. ld (tmp2),a ; store it. ld bc,4 ; bytes to copy. push de ; destination - 2nd row. push hl ; store source - 1st row. ldir ; do the copy. pop hl ; restore old position. push hl ; store again. ld b,4 ; spaces to write. cbdet5 ld (hl),0 ; write a space. inc hl ; next character. djnz cbdet5 ; repeat 4 times. pop hl ; restore top row. call dburg ; delete falling burger. pop hl ; restore 2nd row. push hl ; store for next line check. call dburg ; show falling burger. pop hl ; restore address of food. ld a,(tmp2) ; did we hit anything? and a ; zero means we didn't. jr z,cbdet0 ; no, just keep falling. ld a,(dispx) ; position. cp 19 ; reached bottom bit? ret nc ; yes, so stop. ld de,24 ; distance to start of next row. add hl,de ; point there. jr cbdet0 ; keep falling. cbdet6 call scor5 ; add to score. ld hl,numfel ; number of items needed to hit plate. dec (hl) ; decrement total remaining. ret nz ; not yet, keep playing. ; Completed last item, so move to next level. pop de ; remove return address from stack. ld hl,(xyptr) ; item positions. ld de,4 ; 2 * 2 bytes. add hl,de ; point to next positions. ld (xyptr),hl ; next pointer. call tinkle ; brief sound effect. call onesec ; short delay. call pea ; find the pea. jp newlev ; restart. ; Display piece of burger. dburg call setbxy ; set burger x and y based on address. ld a,(dispx) ; x coordinate. rlca ; multiply by 8. rlca rlca ld e,a ; pixel coordinate. ld a,(dispy) ; y coordinate. rlca ; multiply by 8. rlca rlca ld d,a ; pixel coordinate. ld ix,saus1 ; sausage. push de ; store burger pixel coords. call bscol ; check for burger/sausage collision. pop de ; restore coords in de. ld ix,saus2 ; sausage. call bscol ; check for burger/sausage collision. ld b,4 ; blocks to show. dburg0 ld a,(hl) ; piece to display. push bc ; store loop. push hl ; store position. call dchar ; show character. pop hl ; retrieve position. inc hl ; next piece. pop bc ; loop. djnz dburg0 ret ; Burger/sausage collision check. bscol ld a,(ix+1) ; sausage coordinate. cp e ; direct hit? ret nz ; no, missed sausage. ld a,(ix+2) ; sausage y. add a,15 ; look at rightmost edge. sub d ; is it to left of burger? ret c ; yes, burger has missed. cp 32+15 ; is it within range of burger? ret nc ; no, it's missed. push hl ; store details. push bc ; remember hit status. call scor10 ; add to score. ld hl,(dispx) ; burger display coords. push hl ; store them. call dsaus ; delete it. pop hl ; fetch display coords. ld (dispx),hl ; restore them. ld (ix),4 ; switch it off. ld (ix+1),200 ; set x coordinate off screen. pop bc ; restore hit flag. pop hl ; restore character string address. ret ; Set burger x and y based on hl address. setbxy push hl ; store address of blocks. push bc ; store bc pair. ld de,screen ; screen. and a ; clear carry. sbc hl,de ; find displacement. push hl ; store block address. ld d,24 ; block line length. call idiv ; find row number. ld a,l ; horizontal position. ld (dispx),a ; set cursor x. rlca ; multiply by 8. rlca rlca ld e,a ; low byte. ld d,0 ; zero high byte. pop hl ; restore displacement. and a ; clear carry. sbc hl,de ; subtract x * 8. sbc hl,de ; subtract x * 16. sbc hl,de ; subtract x * 24. ld a,l ; remainder is y. ld (dispy),a ; set up coordinate. pop bc ; restore bc. pop hl ; restore address. ret ; Get screen block address at (c, b). gsblk ld a,c ; x coordinate. and 248 ; only want multiples of 8. ld e,a ; low byte of displacement. ld d,0 ; no high byte. ld hl,screen ; screen blocks data. add hl,de ; 8 x coordinate. add hl,de ; 16 x coordinate. add hl,de ; 24 x coordinate. ld a,b ; y position. rra ; divide by 8. rra rra and 31 ; remove bits shifted in. ld e,a ; low byte of displacement. add hl,de ; point to address of block. ld a,(hl) ; fetch its contents. ret ; Enemy routines and AI. ; Move a sausage. msaus call getabc ; get direction and coordinates. cp 4 ; is it dead? jr c,msaus0 ; no - process normally. inc a ; count up. ld (ix),a ; new value. and a ; reached zero yet? ret nz ; no. call tinkle ; sound to reintroduce enemy. ld hl,screen+456 ; start of line below last girder. ld b,255 ; just before first column. msaus1 inc b ; next column ld a,(hl) ; get char there. cp LADDER ; is it the ladder? inc hl ; point to next char. jr nz,msaus1 ; no ladder, keep looking. ld a,b ; column number. rlca ; multiply by 8. rlca rlca ld (ix+1),160 ; set x coord at which to appear. ld (ix+2),a ; set y coord at which to appear. jp dsaus ; show sausage. msaus0 call dsaus ; delete sausage. call getabc ; restore details. and a ; going up? jp z,msosu dec a ; right? jr z,msosr dec a ; moving down? jp z,msosd msosl ld a,b ; fetch y again. and a ; at left edge? jp z,msoss ; yes, turn around. ld a,16 ; distance to blocks underfoot. add a,c ; add to x. ld c,a ; new x. dec b ; look left. dec b call gsblk ; get block there. and a ; is it space? jp z,msoss ; yes, change direction switch left/right. call getabc ; restore details. dec b ; move left. dec b call setabc ; set new direction. ; Ladder checking. ld a,b ; y position. and 7 ; on cell boundary? jp nz,dsaus ; no, display at new position and finish. call random ; random number. cp 80 ; chance we won't use it. jp c,dsaus ; don't bother with it. cp 160 ; chance we will use it. jr c,msosl0 ; use it. ld a,(playx) ; player x. cp c ; same as sausage x? jp z,dsaus ; yes, don't use ladder. ; Check for presence of ladders. msosl0 ld a,c ; x coord. add a,15 ; look at feet. ld c,a ; x coordinate to check. call gsblk ; find block type there. cp LADDER ; is it a ladder? jr nz,msosl1 ; no, can't go up. inc hl ; look to next cell. ld a,(hl) ; what's there? cp LADDER ; is it a ladder? jr nz,msosl1 ; no, can't go up. msosgu call getabc ; restore details. xor a ; direction up. jp sosdon ; set details and display. msosl1 call getabc ; get details. ld a,c ; x. add a,16 ; look below feet. cp 144 ; past bottom girder? jp nc,dsaus ; yes, can't go down. ld c,a ; x coordinate to check. call gsblk ; find block type there. cp LADDER ; is it a ladder? jp nz,dsaus ; no, can't go down. inc hl ; look to next cell. ld a,(hl) ; what's there? cp LADDER ; is it a ladder? jp nz,dsaus ; no, can't go down. msosgd call getabc ; restore details. ld a,2 ; direction down. jr sosdon ; set details and display. msosr ld a,b ; fetch y again. cp 176 ; at right edge? jp nc,msoss ; yes, turn around. ld a,16 ; distance to blocks underfoot. add a,c ; add to x. ld c,a ; new x. ld a,b ; y position. add a,16 ; look 16 pixels right. ld b,a ; y coord to check. call gsblk ; get block there. and a ; is it space? jp z,msoss ; yes, change direction switch left/right. call getabc ; restore details. inc b ; move right. inc b call setabc ; set new position. ; Ladder checking. ld a,b ; y position. and 7 ; on cell boundary? jp nz,dsaus ; no, display at new position and finish. call random ; random number. cp 80 ; chance we won't use it. jp c,dsaus ; don't bother with it. cp 160 ; chance we will use it. jr c,msosl0 ; use it. ld a,(playx) ; player x. cp c ; same as sausage x? jp z,dsaus ; yes, don't use ladder. ; Check for presence of ladders. msosr0 ld a,c ; x coord. add a,15 ; look at feet. ld c,a ; x coordinate to check. call gsblk ; find block type there. cp LADDER ; is it a ladder? jr nz,msosr1 ; no, can't go up. inc hl ; look to next cell. ld a,(hl) ; what's there? cp LADDER ; is it a ladder? jr nz,msosr1 ; no, can't go up. jr msosgu ; go up. msosr1 call getabc ; get details. ld a,c ; x. add a,16 ; look below feet. cp 144 ; past bottom girder? jp nc,dsaus ; yes, can't go down. ld c,a ; x coordinate to check. call gsblk ; find block type there. cp LADDER ; is it a ladder? jp nz,dsaus ; no, can't go up. inc hl ; look to next cell. ld a,(hl) ; what's there? cp LADDER ; is it a ladder? jp nz,dsaus ; no, can't go up. jr msosgd ; go down. msosu ld a,c ; x coordinate. add a,15 ; look at feet. ld c,a ; coordinate to check. call gsblk ; find block there. cp LADDER ; is it a ladder? jr nz,msosu0 ; no, switch direction. inc hl ; look right. ld a,(hl) ; fetch block there. cp LADDER ; is it a ladder? jr nz,msosu0 ; no, switch direction. call getabc ; fetch details again. dec c ; up. dec c sosdon call setabc ; set new details. jp dsaus ; display at new position. msosu0 call random ; random number. rra ; rotate lowest bit into carry. jr nc,msosgr ; no carry, so move right. msosgl call getabc ; fetch details again. ld a,3 ; direction left. jp sosdon ; job done. msosgr call getabc ; fetch details again. ld a,1 ; direction right. jp sosdon ; job done. msosd ld a,c ; x coordinate. add a,16 ; look below feet. ld c,a ; coordinate to check. call gsblk ; find block there. cp LADDER ; is it a ladder? jp nz,msosu0 ; no, switch direction. inc hl ; look right. ld a,(hl) ; fetch block there. cp LADDER ; is it a ladder? jr nz,msosu0 ; no, switch direction. call getabc ; fetch details again. inc c ; descend. inc c jp sosdon ; done. ; Switch sausage direction. msoss call getabc ; fetch details. xor 2 ; switch left/right. jp sosdon ; display at new point. ; Set coordinates and direction. setabc ld (ix),a ; get direction. setbc ld (ix+1),c ; x coordinate. ld (ix+2),b ; y position. ret ; Fetch coordinates and direction. getabc ld a,(ix) ; get direction. ld c,(ix+1) ; x coordinate. ld b,(ix+2) ; y position. ret ; Sausages emerging together check. emerge ld a,(saus1) ; sausage 1 dead check. cp 4 ; is it alive? ret c ; yes, nothing to do. cp 240 ; is it to emerge soon? ret c ; no. ld a,(saus2) ; sausage 2 flag. cp 4 ; is it alive? ret c ; yes, do nothing. cp 240 ; is it to emerge soon? ret c ; no. ld a,200 ; new total. ld (saus2),a ; reset counter to stagger them. ret ; Sausage collision detection. soscol call colc16 ; check for collision. ret nc ; no collision. ; Player is dead then. ; Remove return address from stack and deal with it here. ; Removing return addresses from the stack in this way isn't good ; practice generally, but with only 4K to play with things are tight. dead pop de ; remove return address from stack. call noisa ; sound effect. ld hl,numlif ; lives remaining. dec (hl) ; one less. jp z,waitg ; game over. ld a,90 ; seconds to complete level. ld (time),a ; set up time. jp rstart ; restart. ; Collision check with corner clipping. colc16 ld a,(ix) ; sausage status. cp 4 ; is it enabled? ret nc ; no, skip collision check. ld hl,(playx) ; get player's coords. ld a,l ; x coord. sub (ix+1) ; subtract sausage x. jr nc,colc1a ; result is positive. neg ; make negative positive. colc1a cp 16 ; within x range? ret nc ; no - they've missed. ld e,a ; store difference. ld a,h ; y coord. sub (ix+2) ; subtract y. jr nc,colc1b ; result is positive. neg ; make negative positive. colc1b cp 16 ; within y range? ret nc ; no - they've missed. add a,e ; add x difference. cp 26 ; only 5 corner pixels touching? ret ; carry set if there's a collision. ; Sprite routines. ; Display or delete the item. ditem rrca ; multiply by 32. rrca rrca ld e,a ; store in e. and 1 ; high bit. ld d,a ; high byte of displacement. ld a,e ; restore shift. and 224 ; multiple of 32. ld e,a ; that's the low byte. ld hl,objspr ; first item sprite. add hl,de ; add displacement for graphic address. jp sprite ; transfer sprite to display. ; Display sausage. dsaus ld a,(ix) ; enemy direction. rra ; moving up or down? jr nc,dsausv ; yes, display vertical sprite. ld hl,sauslr ; left/right sprites. dsaus1 ld c,(ix+1) ; x coordinate of sprite. ld a,(ix+2) ; y coordinate. ld b,a ; y coordinate. dsaus0 ld (dispx),bc ; set up sprite routine coords. rlca ; multiply by 32. rlca ; 6 is already a multiplication by 2, rlca ; so we need 4 shifts. rlca and 96 ; remove high bits. ld d,0 ; there's no high byte. ld e,a ; displacement should now be in de. add hl,de ; add displacement for this sprite. jr sprite ; call sprite routine. dsausv ld hl,sausud ; vertical sprites. ld a,(ix+1) ; x coordinate of sprite. ld b,(ix+2) ; y coordinate. ld c,a ; x coordinate. jr dsaus0 ; Display player sprite. dplay ld hl,(playx) ; player's coordinates. ld (dispx),hl ; coords used by sprite routine. ld a,(playd) ; player direction. rra ; moving up or down? jr nc,dplayv ; yes, display spud vertical. dplayh ld a,h ; y coordinate determines which frame to use. ld hl,psplr ; player sprite left/right. jr dplay0 dplayv ld a,l ; x coordinate determines which frame to use. ld hl,pspud ; player sprite left/right. dplay0 and 6 ; 0, 2, 4 or 6. rrca ; multiply by 32. rrca ; already a multiple of 2, rrca ; so we need 4 shifts instead of 5. rrca ld e,a ; low byte in e register. ld d,0 ; no high byte. add hl,de ; add to sprite address. jr sprite ; This is my main sprite routine and expects coordinates in (dispx,dispy) ; where dispx is the vertical coord from the top of the screen (0-176), and ; dispy 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. sprite ld a,(dispx) ; draws sprite (hl). ld (tmp1),a ; store vertical. call scadd ; calculate screen address. 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 (tmp0),hl ; store in tmp0 for later. 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 5 ; 5 or more right shifts needed? jr nc,sprit7 ; yes, shift from left as it's quicker. 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. xor c ; merge in image data. ld (hl),a ; place onto screen. inc l ; next character cell to right please. ld a,(hl) ; what's there already. xor d ; merge with middle bit of image. ld (hl),a ; put back onto screen. inc hl ; next bit of screen area. ld a,(hl) ; what's already there. xor e ; right edge of sprite image data. ld (hl),a ; plonk it on screen. ld a,(tmp1) ; temporary vertical coordinate. inc a ; next line down. ld (tmp1),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 hl ; 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,(tmp0) ; 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. ; Calculating a screen address from a pixel coordinate can be tricky! ; The Spectrum screen display is organized into 3 segments of 2048 bytes, ; all containing 8 rows of 32 character squares, each with 8 lines. ; Hence 8 * 32 * 8 * 3 = 6144 bytes. ; Low resolution colour filter = 32 * 8 character squares = 768 bytes. ; Total = 6144 + 768 = 6912 bytes, 16384 to 23295 inclusive. scadd ld a,(dispx) ; Returns screen address of coordinates ld b,a ; (dispx, dispy) in de. 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,b ; fetch x coord again. rrca ; divide pixel displacement by 8. rrca rrca and 24 ; Segment 0-2 multiplied by 8. add a,d ; Add to h (so multiply by 8 * 256 = 2048) ld d,a ld a,b ; 8 character squares per segment. rlca ; Divide x by 8 and multiply by 32, rlca ; net calculation: multiply by 4. and 224 ; Mask off bits we don't want. ld e,a ; Vertical coordinate calculation done. ld a,(dispy) ; y coordinate. ld b,a ; remember horizontal position for later. rrca ; now 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 ; de = address of screen. ret ; Player left/right. psplr defb 0,0,3,192,5,160,47,244,111,246,238,119,198,99,219,219 defb 236,55,239,247,15,240,127,254,63,252,3,192,123,222,120,30 defb 3,192,5,160,47,244,111,246,236,55,246,111,235,195,204,55 defb 247,246,247,240,55,252,79,252,63,248,7,128,247,188,240,60 defb 3,192,5,160,15,240,47,244,108,54,246,111,203,211,220,59 defb 239,247,239,247,15,240,127,252,63,248,3,192,123,222,120,30 defb 0,0,3,192,37,160,111,244,239,246,238,119,198,103,235,211 defb 108,47,15,239,127,236,127,242,63,252,1,224,61,239,60,15 ; Player up/down. pspud defb 3,198,7,231,111,243,239,243,207,247,135,230,235,212,236,56 defb 111,252,31,252,63,252,31,252,239,248,247,128,7,188,0,60 defb 3,192,103,230,239,247,207,243,207,247,231,231,235,215,108,54 defb 47,244,31,248,63,252,63,252,7,224,123,222,123,222,0,0 defb 99,192,231,224,207,246,207,247,239,243,103,225,43,215,28,55 defb 63,246,63,248,63,252,63,248,31,247,1,239,61,224,60,0 defb 3,192,103,230,239,247,207,243,239,243,231,231,107,215,44,54 defb 31,244,63,248,127,252,63,252,7,224,123,222,123,222,0,0 ; Sausage left/right. sauslr defb 67,128,55,197,103,226,39,229,19,228,15,248,1,240,1,240 defb 3,240,3,224,7,224,15,224,23,208,19,144,56,24,120,60 defb 0,0,3,128,7,192,87,229,39,226,83,237,15,241,1,240 defb 1,240,3,240,3,224,7,224,15,240,23,200,227,134,224,15 defb 3,128,7,192,7,224,7,224,67,224,35,241,253,250,33,247 defb 3,242,3,225,7,224,15,224,23,208,19,144,56,24,120,60 defb 3,128,7,192,7,224,87,229,35,226,83,253,13,241,1,240 defb 3,240,3,224,7,224,7,224,7,224,3,160,15,112,15,112 ; Sausage up/down. sausud defb 1,192,195,224,199,224,39,224,47,192,31,243,15,143,15,128 defb 15,192,7,216,7,246,7,247,59,224,33,192,224,0,224,0 defb 1,192,3,224,7,224,199,227,207,207,63,240,15,128,15,128 defb 15,192,7,192,55,232,47,244,227,231,225,199,0,0,0,0 defb 1,192,3,227,7,227,7,228,15,200,207,240,223,128,47,128 defb 15,192,63,192,231,224,231,240,3,232,1,196,0,7,0,7 defb 1,192,3,224,7,224,199,227,207,207,63,240,15,128,15,128 defb 15,192,7,192,55,232,47,244,227,231,225,199,0 ; Collectables. ; Mushroom. objspr defb 0,0,0,192,1,240,2,56,5,92,5,78,4,150,1,215 defb 7,227,31,235,127,211,223,139,239,38,246,28,116,0,56,0 ; Fish slice. defb 24,0,60,0,118,0,235,0,213,128,106,192,53,128,27,0 defb 14,128,4,64,0,32,0,24,0,28,0,14,0,5,0,3 ; Toast. defb 1,192,3,0,6,240,13,176,27,240,54,248,111,216,219,248 defb 191,108,187,254,47,246,61,188,7,248,0,240,0,96,0,0 ; Sausages. defb 0,240,1,216,57,236,125,244,116,254,244,122,252,127,244,61 defb 252,63,254,31,122,31,127,31,61,159,63,142,31,128,15,0 ; Cutlery. defb 42,32,42,48,42,56,62,56,62,60,28,60,8,60,8,60 defb 8,60,28,48,28,56,28,56,28,56,28,56,28,56,28,56 ; Cheese. defb 28,224,28,240,15,176,29,28,63,182,39,127,35,19,38,18 defb 63,60,125,248,119,224,35,224,35,192,119,128,126,0,0,0 ; Egg. defb 0,0,1,240,7,252,31,254,63,254,127,254,127,250,255,250 defb 255,246,255,244,127,252,127,232,63,216,31,112,7,192,0,0 ; Tea. defb 0,0,6,0,15,128,11,224,16,248,28,62,60,12,60,223 defb 120,251,121,249,241,243,243,246,63,252,15,224,3,192,0,192 ; Frying pan. defb 64,0,160,0,112,0,56,0,28,240,15,156,6,102,5,250 defb 13,251,11,253,11,253,13,251,5,250,6,102,3,156,0,240 ; Ketchup. defb 0,224,3,224,3,0,0,192,0,240,1,248,1,60,2,28 defb 2,30,2,14,2,15,2,31,3,255,3,254,1,248,0,96 udgs defb 62,0,0,0,62,0,0,0 defb 62,0,0,0,0,0,0,0 ; Short chirp. chirp ld hl,0 ; starting pitch. ld b,20 ; loop counter. chirp0 push hl ; store pitch. ld de,0 ; duration of note. call 949 ; call ROM sound routine. pop hl ; restore pitch. ld de,5 ; speed of pitch bend. add hl,de ; add to pitch. djnz chirp0 ; repeat. ret ; Quiet "tinkle" sound. tinkle ld b,192 ; outer loop counter. tinkl0 ld a,248 ; set all non-border bits. out (254),a ; write to speaker. ld a,r ; poor man's random number. or b ; combine with main loop counter. tinkl1 dec a ; decrement. jr nz,tinkl1 ; delay loop. ld a,r ; random number. and 248 ; mask off border colour information. out (254),a ; write to speaker port. djnz tinkl0 ; repeat. ret beep0 ld hl,806 ; pitch. ld de,33 ; duration. call 949 ; call beeper routine. ld hl,856 ; pitch. ld de,31 ; duration. jp 949 ; call beeper routine. beep1 ld hl,1643 ; pitch. ld de,4 ; duration. jp 949 ; Crash sound. noisa ld e,250 ; starting point. noisa2 ld b,32 ; length of step. noisa0 call random and 248 ; mask away border bits. out (254),a ; drive speaker. ld a,e cpl noisa1 dec a ; decrement counter. jr nz,noisa1 ; inner delay loop. djnz noisa0 ; end of middle loop. ld a,e sub 23 ; size of step. cp 32 ; end of range. ret c ; that's enough. ld e,a cpl ; toggle bits to find delay. noisa3 ld b,40 ; silent period. noisa4 djnz noisa4 ; inner delay. dec a ; decrement counter. jr nz,noisa3 ; repeat. jr noisa2 ; back to start of outer loop. ; Pseudo-random number generator. ; Steps a pointer through the ROM (held in seed), returning the contents ; of the byte at that location. random ld hl,(seed) ; pointer ld a,(hl) ; get "random" number from location. inc hl ; increment pointer. res 5,h ; stay within "random" part of ROM. ld (seed),hl ret ; Get matrix position address. getmat ld hl,matrix ; grid positions. addac1 ld e,a ; displacement in de. ld d,0 ; no high byte. add hl,de ; point to appropriate slot. ret scor5 ld de,5 ; amount to add. jr scorx scor10 ld de,10 ; amount to score. scorx ld hl,(score) ; player's score. add hl,de ; add to total. sscor ld (score),hl ; store new total. dscor ld bc,6*256+7 ; line and column. call 3545 ; set cursor position. ld hl,(score) ; score. ld a,l ; copy hl to lh for BASIC line number format. ld l,h ; high byte to low byte. ld h,a ; low byte to high byte. rjust ld (dnum),hl ; set up display number. ld hl,dnum ; display number. jp 6696 ; display score. ; Timer. second sub 50 ; subtract 1 second from clock. ld (23672),a ; new clock setting. ld hl,time ; time remaining. dec (hl) ; one second less. jp z,dead ; time up. dtime ld bc,9*256+7 ; 9 lines up, 7 from edge. call 3545 ; set cursor position. ld a,(time) ; seconds left. ld h,a ; put seconds into h. ld l,0 ; never more than 255 so no high byte. jr rjust ; call ROM routine to show right-justified. ; Display lives remaining. dlife ld bc,3*256+4 ; 3 from bottom, 4 from edge. call 3545 ; set cursor position. ld a,(numlif) ; number of lives remaining. add a,'0' ; add ASCII code for zero. rst 16 ; display character. ret pantxt defb 22,17,25,16,7 defb 'SCORE' defb 22,14,26 defb 'TIME' ; Draw character window. droom ld hl,screen ; point to this screen. xor a ; top coordinate. ld (dispx),a ; set coordinate. ld (numobj),a ; set number of objects. ld b,24 ; height in blocks. droom0 push bc ; store row counter. xor a ; left coordinate. ld (dispy),a ; set horizontal starting point. ld b,24 ; width in blocks. droom1 push bc ; store column counter. ld a,(hl) ; get character. push hl ; store character address. call dchar ; draw the character. pop hl ; restore pointer to address. inc hl ; next block. pop bc ; restore column count. djnz droom1 ld a,(dispx) ; vertical position. inc a ; move down. ld (dispx),a ; next line starts here. pop bc ; restore row count. djnz droom0 ret ; Draw character block in accumulator. dchar ld hl,chatts ; block attributes. ld e,a ; displacement to attribute. ld d,0 ; no high byte for attributes. add hl,de ; point to attribute value. ex af,af' ; store char number. call atadd ; get attribute address. ldi ; transfer to screen. ex af,af' ; restore char number. rlca ; multiply by 8. rlca rlca ld d,a ; store shift in d. and 248 ; mask away high byte bits. ld e,a ; place result in e. ld a,d ; restore shift. and 7 ; mask off the low byte bits. ld d,a ; set high byte for displacement. ld hl,chgfx ; character block graphics. add hl,de ; point to character graphics. call chadd ; get screen character address. ld bc,8*256+99 ; 8 lines to write. dchar0 ldi ; transfer to screen. dec de ; back one char. inc d ; next screen line down. djnz dchar0 ; repeat for all lines. ld hl,dispy ; horizontal position. inc (hl) ; move right one square. ret ; Return character cell screen address for (dispx, dispy). chadd ld a,(dispx) ; vertical position. ld e,a ; store in e. and 24 ; which segment, 1 to 3? add a,64 ; 64*256 = 16384, Spectrum's screen memory. ld d,a ; this is our high byte. ld a,e ; what was that vertical position again? and 7 ; which row within segment? rrca ; multiply row by 32. rrca rrca ld e,a ; low byte. ld a,(dispy) ; add on y coordinate. add a,e ; mix with low byte. ld e,a ; address of screen position in de. ret ; Calculate address of attribute for character at (dispx, dispy). atadd ld a,(dispx) ; x position. rrca ; multiply by 32. rrca rrca ld e,a ; store away in e. and 3 ; mask bits for high byte. add a,88 ; 88*256=22528, start of attributes. ld d,a ; high byte done. ld a,e ; get x*32 again. and 224 ; mask low byte. ld e,a ; put in l. ld a,(dispy) ; get y displacement. add a,e ; add to low byte. ld e,a ; hl=address of attributes. ret ; Character block graphics. chgfx defb 0,0,0,0,0,0,0,0 ; buns = 02 03 03 04 02 03 03 04 ; 05 05 05 05 10 11 12 13 ; 06 06 06 06 06 06 06 06 ; 07 08 08 09 07 08 08 09 defb 255,255,0,124,62,31,255,255 ; girder = 1. defb 7,30,55,127,127,255,255,255 ; bun top left = 2. defb 221,247,191,251,255,255,255,255 ; bun middle = 3. defb 224,184,236,254,254,255,255,255 ; bun top right = 4. defb 62,127,255,255,255,255,254,124 ; pickles = 5. defb 255,170,255,85,255,170,255,85 ; meat = 6. defb 255,255,255,127,127,63,31,7 ; base left = 7. defb 255,255,255,255,255,255,255,255 ; base middle = 8. defb 255,255,255,254,254,252,248,224 ; base right = 9. defb 255,255,255,207,207,255,252,248 ; cheese = 10-13. defb 255,231,195,195,231,255,255,127 defb 195,231,255,255,255,251,241,251 defb 255,255,243,225,225,243,255,255 defb 0,0,0,255,0,0,0,0 ; ladder = 14. defb 255,255,0,0,0,0,0,0 ; plate = 15. ; Character block attributes. chatts defb 71 gcolou defb 67 ; girder colour. defb 6,6,6,68 defb 2,6,6,6,70,70,70,70 defb 71,69 ; Find the Pea bonus game. swap ld de,swptx0 ; text. ld bc,swpbon-swptx0 ; length. call 8252 ; show text. ld hl,swpbon ; swap bonuses. ld a,4 ; number to display. swap0 push af ; store on stack. push hl ; store bonus pointer. call dswapb ; display swap bonus. call beep0 ; sound effect. ld b,7 ; fraction of a second. call delay ; short pause. pop hl ; restore bonus pointer. inc hl ; next bonus. pop af ; restore counter from stack. dec a ; one less value to show. jr nz,swap0 call onesec ; pause for one second. ld de,swpat ; at code. ld bc,swpbon-swpat ; length. call 8252 ; show text. ld a,4 ; number to display. swap1 push af ; store on stack. ld a,'-' ; hide character. rst 16 ; display it. ld a,'-' ; hide character. rst 16 ; display it. call d2spc ; display 2 spaces. call beep1 ; short sound. ld b,7 ; fraction of a second. call delay ; short pause. pop af ; restore counter from stack. dec a ; one less value to show. jr nz,swap1 call onesec ; pause for one second. ld b,11 ; number of swaps. swap2 push bc call swapv pop bc djnz swap2 ; Select bonus. xor a ld (chosen),a ; selected square. select call shosel ; show selected square. call debou ; debounce. selec0 call getkey ; get keyboard input. and a ; any input? jr z,selec0 ; no. call shosel ; unhighlight position. ld a,(joyval) ; result of keyboard input. cp 1 ; move right? jr z,selr ; move that way. cp 2 ; move left? jr z,sell ; move that way. and 12 ; up and/or down? jr z,select ; no, wait for up/down. call shosel ; show selected square. ld b,25 ; delay length. call delay ; pause. ; Show final positions. ld de,swpat ; at code. ld bc,swpbon-swpat ; length. call 8252 ; show text. ld a,4 ; number to display. ld hl,swpbon ; swap bonuses. selec1 push af ; store on stack. push hl ; store bonus pointer. call dswapb ; display swap bonus. pop hl ; restore bonus pointer. inc hl ; next bonus. pop af ; restore counter from stack. dec a ; one less value to show. jr nz,selec1 ld hl,23695 ; temporary attributes system variable. ld (hl),69 ; cyan ink on black background. call shosel ; show selected square. call tinkle ; sound effect. ld b,25 ; delay length. call delay ; short pause. ld a,(chosen) ; chosen square. ld hl,swpbon ; swap bonuses. call addac1 ; find value. ; Increase time visual. ld a,(hl) ; amount to transfer. ld b,a ; loop counter. uptim0 push bc ; store counter. ld hl,time ; time remaining. ld a,(hl) ; present value. inc a ; increment it. jr z,uptim1 ; reached max. ld (hl),a ; new value. uptim1 call dtime ; show time remaining. call beep1 ; sound effect. pop bc ; restore counter. djnz uptim0 ret sell ld a,(chosen) ; chosen square. and a ; at edge already? jr z,select ; yes, can't move again. dec a ; move to new square. ld (chosen),a ; new value. jp select selr ld a,(chosen) ; chosen square. cp 3 ; at edge already? jp z,select ; yes, can't move again. inc a ; move to new square. ld (chosen),a ; new value. jp select shosel ld a,(chosen) ; find selected. rlca ; multiply by 4. rlca add a,100 ; attribute low. ld l,a ; low byte. ld h,89 ; high byte of attribute. ld a,(hl) ; fetch attribute. xor 41 ; toggle attributes. ld (hl),a ; new value. inc l ; next cell. ld (hl),a ; colour that too. ret ; Display swap bonuses. dswapb ld c,(hl) ; fetch bonus value from table. ld b,0 ; no high byte. call 6683 ; show number. d2spc ld a,32 ; space character. rst 16 ; move along. ld a,32 ; space character. rst 16 ; move along. ret ; Choose right value to swap. swapv call random ; random number. and 3 ; in range 0-3. jr z,swapv ; only want 1-3. push af ; store value. ld hl,swpbon ; swap bonuses. call addac1 ; find table address. ld a,(hl) ; present value. dec hl ; point to left value. ld b,(hl) ; get its value. ld (hl),a ; new setting for left value. inc hl ; right value. ld (hl),b ; original left value. pop af ; restore right value. rlca ; multiply by 4. rlca ld (coly),a ; set column position. ld b,6 ld de,swaptx ; text pointer. swapv0 push bc ; store counter. ld a,22 ; at code. rst 16 ; write at code. ld a,11 ; line number. rst 16 ; send line code. ld a,(coly) ; column position. rst 16 ; set column. ld bc,6 ; length of string. call 8252 ; display animation frame. halt ; delay. halt pop bc ; restore counter. djnz swapv0 ; repeat. ret swptx0 defb 22,10,3,16,6,17,1 defb 23,20,99 defb 22,11,3,23,20,99 defb 22,12,3,23,20,99 swpat defb 22,11,4 swpbon defb 45,30,20,15 swaptx defb '-- ',145,145 defb ' --',145,145,' ' defb ' ',144,144,' ' defb ' ',145,145,'-- ' defb 145,145,' --' defb '-- --' levdat equ $ defb 15,4,99,8 defw screen+3*24+1,screen+3*24+12 defw screen+8*24+9,screen+8*24+20 defw screen+13*24,screen+13*24+12,screen+13*24+22 defw screen+18*24+10 defb 2,10,17,9 defw screen+3*24,screen+3*24+14,screen+3*24+22 defw screen+8*24+7,screen+8*24+21 defw screen+13*24,screen+13*24+8,screen+13*24+14 defw screen+18*24+22 defb 17,3,11,8 defw screen+3*24,screen+3*24+22 defw screen+8*24,screen+8*24+8,screen+8*24+15 defw screen+13*24+8,screen+13*24+22 defw screen+18*24+15 defb 10,17,3,8 defw screen+3*24+8,screen+3*24+15 defw screen+8*24,screen+8*24+14 defw screen+13*24,screen+13*24+7,screen+13*24+22 defw screen+18*24+8 defb 3,11,19,7 defw screen+3*24+8,screen+3*24+16 defw screen+8*24,screen+8*24+16 defw screen+13*24+8,screen+13*24+16 defw screen+18*24 defb 19,3,11,6 defw screen+3*24,screen+3*24+8 defw screen+8*24+16 defw screen+13*24,screen+13*24+8 defw screen+18*24+16 xydat defb 48,160,88,16 defb 8,56,128,176 defb 8,64,128,4 defb 8,172,128,116 defb 8,128,88,64 defb 8,4,128,128 ; Burger data. buntop defb 2,3,3,4 pickle defb 5,5,5,5 cheese defb 10,11,12,13 burger defb 6,6,6,6 bunbot defb 7,8,8,9 plate defb 15,15,15,15 ; Variables used by the game. tmp0 equ 32768 tmp1 equ tmp0 + 2 tmp2 equ tmp1 + 1 ; temporary, used in burger drop routine. numobj equ tmp2 + 1 ; number of objects. dispx equ numobj + 1 ; display x coord. dispy equ dispx + 1 ; display y coord. playx equ dispy + 1 ; player x coord. playy equ playx + 1 ; player y coord. playd equ playy + 1 ; player direction. saus1 equ playd + 1 ; first enemy sprite. saus2 equ saus1 + 3 ; second enemy sprite. numfel equ saus2 + 3 ; number of items fallen. score equ numfel + 1 ; player's score. joyval equ score + 2 ; controls. mtbuff equ joyval + 1 ; maths buffer. levnum equ mtbuff + 2 ; current level. oplayx equ levnum + 1 ; old player x coord. oplayy equ oplayx + 1 ; old player y coord. seed equ oplayy + 1 ; random number seed. numlif equ seed + 2 ; number of lives. levptr equ numlif + 1 ; level data pointer. itcnt equ levptr + 2 ; item counter. itemno equ itcnt + 1 ; item number. itemxy equ itemno + 1 ; item coords. xyptr equ itemxy + 2 ; item coords pointer. matrix equ xyptr + 2 ; grid. chosen equ matrix + 10 ; chosen grid position. time equ chosen + 1 ; time remaining. dnum equ time + 1 ; display number. coly equ dnum + 2 ; column position. screen equ 49152 blkspr equ screen + 1024 ; blank sprite. tmpscr equ blkspr + 256 ; temporary storage area for screen display.