;************************************************************************* ; BOMBERMAN v.8 beta ; for USGARD ; ; by Doug Melton ; ; started : 2/01/97 ; last updated: 7/23/98 ; ; thanks to Jimmy Mardell, Andreas Ess ;************************************************************************* #include "usgard.h" .org 0 .db "Bomberman v.8¼ by DM",0 ;************************************************************************* ;;;Data Structures ;Moving Sprite Data Structure (15 bytes) ;to use, say for instance: ld hl, (SpriteName+YPos) YPos = 0 XPos = 1 SType = 2 MemLoc = 3 ;word Direction = 5 ;word Background = 7 ;8 bytes, what's behind the sprite ;************************************************************************* ;;;Game Variables randNum = TEXT_MEM ; Byte tmp = TEXT_MEM+1 ; Word } temporary storage Masks = TEXT_MEM+3 ; } AddDE = TEXT_MEM+5 ; } clipmask = TEXT_MEM+3 ; } rows2put = TEXT_MEM+4 ; } bitmask = TEXT_MEM+5 ; } Flags = TEXT_MEM+8 ; Byte ; Bit 0 set: death ; Bit 1 set: redraw screen *not implemented* EnemiesLeft = TEXT_MEM+9 ; byte CurrLevel = TEXT_MEM+10 ; Byte IntCount = TEXT_MEM+11 ; Byte KeyStatus = TEXT_MEM+12 ; Byte CurrPts = TEXT_MEM+13 ; Word ;;;Level Variables PosY = TEXT_MEM+15 ; Byte } these tell you where from 0,0 of the level PosX = TEXT_MEM+16 ; Byte } 0,0 on the screen is (in pixels) LevelPtr = TEXT_MEM+17 ; Word where level starts in mem LevelSizeY = TEXT_MEM+19 ; Byte size in bytes LevelSizeX = TEXT_MEM+20 ; Byte size in bytes WallType = TEXT_MEM+21 ; Byte TileType = TEXT_MEM+22 ; Byte BonusType = TEXT_MEM+23 ; Byte Enemy1Num = TEXT_MEM+24 ; Byte Enemy2Num = TEXT_MEM+25 ; Byte Enemy3Num = TEXT_MEM+26 ; Byte BonusPtr = TEXT_MEM+27 ; Word ExitPtr = TEXT_MEM+29 ; Word ;;;Player Variables Player = TEXT_MEM+31 ; (15 byte moving sprite data structure) BombsLeft = TEXT_MEM+46 ; Byte BombRadius = TEXT_MEM+47 ; Byte Score = TEXT_MEM+48 ; Word unused Lives = TEXT_MEM+50 ; Byte unused Time = TEXT_MEM+51 ; Byte MAXBOMBS = 8 MAXENEMIES = 8 ;can be |168 / 15| = 11 COUNTERS = MAXBOMBS+MAXENEMIES+1 ;;;Bombs BombPtrs = TEXT_MEM+52 ; number of bytes = MAXBOMBS * 2 (+ 2 for blank) ;;;Counters PlayrCtr = TEXT_MEM+70 ; Byte EnemyCtrs = TEXT_MEM+71 ; number of bytes = MAXENEMIES BombCtrs = TEXT_MEM+79 ; number of bytes = MAXBOMBS BOMBCOUNT = 180 EnemyTable = TEXT_MEM2 ; a bunch of enemy moving sprite data structures ;************************************************************************* ;main program top: xor a ld (CurrLevel), a inc a inc a ld (IntCount), a ld (BombRadius), a ;bomb spread ld (BombsLeft), a ld a, 3 ld (&bonusSpeedPlace+1), a ;reset player speed to normal ;;;allocate working mem. space ;put here if you want to restore level ld hl, &strLevelData call VAR_GET jr nc, initLevelPtr ;check if BombLvl already exists newVar: ld hl, &strLevelData ld bc, 1026 ld a, $0C ;string call VAR_NEW ;if not, make the var. ret c ;if there's not enough mem, exit initLevelPtr: ld (hl), $05 ;store "Bomberman Level" inc hl ld (hl), $00 inc hl ld (LevelPtr), hl InstallInterrupt: ld hl, &Int_Rout call INT_INSTALL ret c ;;;show title screen mainMenu: ld hl, &titleScreen call &ZCP20 ;draw title screen ; ld bc, $3A35 ; ld hl, strHiScore ; call &DisplayMenuTxt ;display "High Score:" ; ld hl, &HiScore ; call LD_HL_MHL ; ld de, $3A5A ; ld (CURSOR_X), de ; call DM_HL_DECI ;display their score ; ld bc, $3A70 ; ld hl, HiScrName ; call &DisplayMenuTxt ;display hi score name ld hl, $0906 res 3, (IY+5) menuChoice: ld a, $20 ld (CURSOR_ROW), hl call TX_CHARPUT ld a, l xor 2 ld l, a ld (CURSOR_ROW), hl ld a, $D7 call TX_CHARPUT menuLoop: push hl call GET_KEY pop hl cp K_EXIT jp z, &quit cp K_UP jr z, menuChoice cp K_DOWN jr z, menuChoice cp K_ENTER jr nz, menuLoop newLife: ld hl, &detonatePlace+1 ld (hl), 0 ;turn off detonate thingy newLevel: call CLEARLCD call &InitLevel jp c, &quit ;cf if beat last level drawScrn: call &drawEnemies call &drawGuy ld bc, 1024 ld de, VIDEO_MEM ld hl, GRAPH_MEM ldir ld a, (Flags) bit 0, a jp nz, &die ld hl, (Player+MemLoc) ld a, (hl) cp SPEXIT jr nz, notOnExit ld a, (EnemiesLeft) or a jr z, newLevel notOnExit: ld a, (hl) call &getSprite bit KILL, a jp nz, &die wait: halt call &eraseGuy call &eraseEnemies ;;;;;;;;;check enemies ld ix, EnemyTable ld hl, EnemyCtrs ld b, MAXENEMIES chkEnemies: ld a, (ix) or a jr z, chkEnemyNext killGuyY: ld e, (ix+YPos) ld a, (Player+YPos) sub e jr nc, kgAbsY neg kgAbsY: ld d, a killGuyX: ld e, (ix+XPos) ld a, (Player+XPos) sub e jr nc, kgAbsX neg kgAbsX: add a, d cp 8 jr nc, dontKillGuy ld a, (Flags) or 1 ld (Flags), a ;set flag that you're dead dontKillGuy: ld e, (ix+MemLoc) ld d, (ix+MemLoc+1) ld a, (de) cp FIRE jr nz, chkEnemyMove ;a bomb killed him ld (ix), 0 ld (ix+Direction), 0 ld (ix+Direction+1), 0 ld a, (EnemiesLeft) dec a ld (EnemiesLeft), a jr chkEnemyNext chkEnemyMove: ld a, (hl) or a jr nz, chkEnemyNext push bc push hl push ix call &moveEnemy pop ix pop hl pop bc chkEnemyNext: ld de, 15 add ix, de inc hl djnz chkEnemies ;;;;;;;;;check bombs chkBombs0: ld ix, BombPtrs ld de, BombCtrs ld b, MAXBOMBS chkBombs: ld a, (ix+1) or a jr z, noExplode ;stop if the bomb has detonated ld l, (ix) ld h, a ld a, (hl) cp FIRE ;if a bomb blew up another bomb jr z, yesExplode ld a, (de) or a jr z, yesExplode ;or if it blew up itself inc de inc ix inc ix djnz chkBombs jr noExplode yesExplode: push ix push de push bc call &Explode pop bc pop de pop ix ld a, (de) or a jr nz, chkBombs ;;;;;;;;;;;;;;; move all other bombs down 1 in bomb stack di ld a, b ld c, a ld b, 0 ld hl, BombCtrs+MAXBOMBS+1 or a sbc hl, bc ld d, h ld e, l dec de ldir ;for the counters... add a, a ; sla a ld c, a ;b's already 0 ld hl, BombPtrs+MAXBOMBS+MAXBOMBS+2 or a sbc hl, bc ld d, h ld e, l dec de dec de ldir ;for the ptrs ei ;;;;;;;;;;;;;;; done moving all other bombs down 1 in bomb stack noExplode: call &moveEnemiesInMem ld a, (PlayrCtr) or a jp nz, &drawScrn checkKeys: ld a, (KEY_0) cp K_MORE call z, &pause ld a, (KeyStatus) ld b, a call OTH_ARROW cpl ld (KeyStatus), a ld c, a xor b and c bit 6, a ;exit pressed jp nz, &quit bit 5, a ;2nd pressed push af call nz, &dropBomb pop af bit 4, a ;f1 pressed call nz, &detonateBomb call OTH_ARROW ;check for arrows cpl and %1111 jp z, &drawScrn call &moveGuy bonusSpeedPlace: ld a, 3 ld (PlayrCtr), a call &chgOffset ld hl, (Player+MemLoc) ld a, (hl) push hl call &getSprite bit BONUS, a pop hl jp z, &drawScrn getBonus1: ld a, (hl) push af xor a ld (hl), a ;change to (floor tile) eventually call &drawMem pop af cp BONUSSPEED jr z, getBonusSpeed cp BONUSDET jr z, getBonusDet cp BONUSBOMB jr z, getBonusBomb getBonusLen: ld hl, BombRadius inc (hl) jr getBonus2 getBonusSpeed: ld hl, &bonusSpeedPlace+1 ld a, (hl) or a jr z, getBonus2 dec (hl) jr getBonus2 getBonusDet: ld hl, &detonatePlace+1 ld (hl), BOMBCOUNT ;turn off detonate thingy ld ix, BombPtrs ;stop all existing bombs from detonating ld hl, BombCtrs ld b, MAXBOMBS+1 getBonusDetLoop: ld a, (hl) or a jr z, getBonus2 ld e, (ix) ld d, (ix+1) ld a, (de) cp BOMB jr nz, getBonusDet2 ld (hl), BOMBCOUNT getBonusDet2: inc ix inc ix inc hl djnz getBonusDetLoop jr getBonus2 getBonusBomb: ld hl, BombsLeft inc (hl) getBonus2: jp &drawScrn detonateBomb: ld hl, &detonatePlace+1 ld a, (hl) or a ret z ;if they don't have the bonus ld hl, BombCtrs ld bc, MAXBOMBS ld a, BOMBCOUNT cpir ret nz dec hl ld (hl), 0 call GET_KEY ret die: ld a, (CONTRAST) dieLoop: out (2), a ld b, a dieLoop2: halt djnz dieLoop2 dec a jr nz, dieLoop ld a, (CONTRAST) out (2), a call &HiScoreHand quit: ld hl, &strLevelData call GET_KEY ;take last key out of buffer call INT_REMOVE ld hl, &strLevelData call VAR_DELETE ret ;quit game dropBomb: ld hl, (Player+MemLoc) ld a, (hl) or a ;call getSprite ret nz ld a, (BombsLeft) ld b, a ld hl, BombPtrs+1 ld de, BombCtrs dropBomb2: ld a, (hl) ;needs some work, BombPtr could be $00 00 or a jr z, dropBomb3 inc hl inc hl inc de djnz dropBomb2 ret dropBomb3: ld a, BOMBCOUNT ld (de), a ld a, (Player+MemLoc+1) ld (hl), a ld a, (Player+MemLoc) dec hl ld (hl), a ;BombPtrX = Player+MemLoc ld hl, (Player+MemLoc) ld (hl), BOMB ;(Player+MemLoc) = BOMB ld a, (hl) call &drawMem ret ;************************************************************************* ;change level offset, if needed, and if possible chgOffset: ld bc, (PosY) ld a, (Player+XPos) sub b cp 56 jr c, scrollRight cp 65 jp nc, &scrollLeft chgOffsetY: ld a, (Player+YPos) sub c cp 24 jp c, &scrollDown cp 33 jp nc, &scrollUp ret scrollRight: ld a, (PosX) or a jr z, chgOffsetY ;return if level can't scroll right anymore dec a ld (PosX), a ; ld hl, VIDEO_MEM ld hl, GRAPH_MEM ld c, 64 srLoopY: ld b, 4 srLoopX: rr (hl) inc hl rr (hl) inc hl rr (hl) inc hl rr (hl) inc hl djnz srLoopX dec c jr nz, srLoopY ;********************************replace first column di ; Disable interrupts so IY can be used push iy ld h, 0 ld a, (PosY) and %11111000 ld l, a add hl, hl add hl, hl ld a, (PosX) srl a srl a srl a ld d, 0 ld e, a add hl, de ld de, (LevelPtr) add hl, de push hl pop iy ; iy -> level data of the blocks to be put to the right ld a, (PosX) and $07 ld hl, &ExpTable+1 ld d, 0 ld e, a add hl, de ld d, (hl) ; D = bit value to mask out of tile sprite data ld c, 8 ; 8 tiles to put ; ld ix, VIDEO_MEM ld ix, GRAPH_MEM srRepFillLeft: push de ld a, (iy) ; A = tile to put ld de, 32 add iy, de call &getSprite pop de ld b, 8 ; 8 rows in the sprite srFill: ld a, (hl) inc hl and d ; This masks out the only bit that will be put jr z, srRemPixel ; If bit cleared, remove the last pixel set 7, (ix) ; Else set it jr srNextY srRemPixel: res 7, (ix) ; Remove pixel srNextY: push de ld de, 16 add ix, de ; IX -> next row in video mem pop de djnz srFill ; Proceed with next row in tile dec c jr nz, srRepFillLeft ; And proceed with next tile pop iy ei ret scrollLeft: ld a, (LevelSizeX) sub 16 add a, a add a, a add a, a ; sla a ; sla a ; sla a ld b, a ld a, (PosX) cp b jp z, &chgOffsetY ;return if level can't scroll left anymore inc a ld (PosX), a ld hl, GRAPH_MEM+$3FF ;last byte of video_mem ld c, 64 slLoopY: ld b, 4 slLoopX: rl (hl) dec hl rl (hl) dec hl rl (hl) dec hl rl (hl) dec hl djnz slLoopX dec c jr nz, slLoopY ;********************************replace last column di ; Disable interrupts so IY can be used push iy ld h, 0 ld a, (PosY) and %11111000 ld l, a add hl, hl add hl, hl ld a, (PosX) and $7 ld a, (PosX) jr nz, slNotEven sub 8 slNotEven: srl a srl a srl a add a, 16 ld d, 0 ld e, a add hl, de ld de, (LevelPtr) add hl, de push hl pop iy ; iy -> level data of the blocks to be put to the right ld a, (PosX) and $07 ld hl, &ExpTable ld d, 0 ld e, a add hl, de ld d, (hl) ; D = bit value to mask out of tile sprite data ld c, 8 ; 8 tiles to put ; ld ix, $FC0F ld ix, GRAPH_MEM+$0F slRepFillRight: push de ld a, (iy) ; A = tile to put ld de, 32 add iy, de call &getSprite pop de ld b, 8 ; 8 rows in the sprite slFill: ld a, (hl) inc hl and d ; This masks out the only bit that will be put jr z, slRemPixel ; If bit cleared, remove the last pixel set 0, (ix) ; Else set it jr slNextY slRemPixel: res 0, (ix) ; Remove pixel slNextY: push de ld de, 16 add ix, de ; IX -> next row in video mem pop de djnz slFill ; Proceed with next row in tile dec c jr nz, slRepFillRight ; And proceed with next tile pop iy ei ret scrollDown: ld a, (PosY) or a ret z ;return if level can't scroll down anymore dec a ld (PosY), a ld bc, 16*63 ; ld hl, $FFFF-16 ld hl, GRAPH_MEM+$3EF ; ld de, $FFFF ;last byte of Video_mem ld de, GRAPH_MEM+$3FF lddr ;add top row here ld h, 0 ld a, (PosY) and %11111000 ld l, a add hl, hl add hl, hl di push iy ld a, (PosX) ;;;;;asdf fix the scrolling bug here?????...but umm... srl a srl a srl a ld d, 0 ld e, a add hl, de ld de, (LevelPtr) add hl, de push hl pop iy ; iy -> level data of the blocks to be put to the right ld a, (PosY) and $7 ld e, a ;de contains how many to add to (spriteLoc) ld d, 0 ; ld ix, VIDEO_MEM ld ix, GRAPH_MEM ld b, 16 sdLoop: ld a, (iy) inc iy call &getSprite add hl, de ld a, (hl) ld (ix), a inc ix djnz sdLoop pop iy ei ret scrollUp: ld a, (LevelSizeY) sub 8 add a, a add a, a add a, a ; sla a ; sla a ; sla a ld b, a ld a, (PosY) cp b ret z ;return if level can't scroll up anymore inc a ld (PosY), a ld bc, 16*63 ; ld hl, VIDEO_MEM+16 ld hl, GRAPH_MEM+16 ; ld de, VIDEO_MEM ld de, GRAPH_MEM ldir ;add bottom row here ; ld a, (PosY) and $7 ld a, (PosY) jr nz, suNotEven sub 8 suNotEven: add a, 64 and %11111000 ld h, 0 ld l, a add hl, hl add hl, hl di push iy ld a, (PosX) srl a srl a srl a ld d, 0 ld e, a add hl, de ld de, (LevelPtr) add hl, de push hl pop iy ; iy -> level data of the blocks to be put to the right ld a, (PosY) dec a and $7 ld e, a ;de contains how many to add to (spriteLoc) ld d, 0 ; ld ix, $FFFF-15 ld ix, GRAPH_MEM+$3F0 ld b, 16 jr sdLoop ; ret ;************************************************************************* ;;;Interrupt Routine Int_Rout: in a, (3) ;check for ON and %1000 jr nz, ONNotPressed ld hl, USG_BITS set 1, (hl) ;make usgard warpout call INT_REMOVE call OTH_EXIT ;quit game ONNotPressed: ld a, (IntCount) dec a ld (IntCount), a ret nz ld a, 3 ld (IntCount), a ; ld hl, 1 ; ld (CurrPts), hl ld b, COUNTERS ld hl, PlayrCtr IntCountLoop: ld a, (hl) or a jr z, IntCountLoopB detonatePlace: cp BOMBCOUNT jr z, IntCountLoopB dec (hl) IntCountLoopB: inc hl djnz IntCountLoop ret ;************************************************************************* InitLevel: ld hl, 0 ld (PosY), hl ;level offset is 0, 0 ld bc, MAXBOMBS*3 ld hl, BombPtrs call OTH_CLEAR ;reset all the counters & pointers ld a, (CurrLevel) inc a ld (CurrLevel), a cp MAXLEVELS+1 ccf ret c ld l, a dec l ld h, 8 ;size of each level in the level data call MUL_HL ld de, &Levels add hl, de ;hl = loc. of curr. level datar push hl ld bc, $182F ld hl, strStage call &DisplayMenuTxt ;display "Stage 1" (or 2 or 3 or 5 or whatever) ld l, a ld h, 0 ld a, (CURSOR_X) sub 11 ld (CURSOR_X), a call DM_HL_DECI pop hl ld a, 90 ld (PlayrCtr), a ;and wait a while ld bc, 8 ld de, LevelSizeY ldir ;copy level datar from program to memory ld a, 8 ld (Player+YPos), a ld (Player+XPos), a ld hl, (LevelPtr) ;************ ;fill var. with walls ILTopLoop: ld a, (WallType) ld (hl), a ld d, h ld e, l inc de ld bc, 1023 ldir ;************ ;fill inside with random tiles ld hl, (LevelPtr) ld de, 33 add hl, de ld a, (LevelSizeY) sub 2 ld c, a ILMidLoopY: ld a, (LevelSizeX) sub 2 ld b, a ld a, 32 sub b ld e, a ILMidLoopX: call &rand and 8 ld a, (TileType) jr nz, randTile xor a randTile: ld (hl), a inc hl djnz ILMidLoopX add hl, de dec c jr nz, ILMidLoopY ;************ ;fill in checkerboard walls ld hl, (LevelPtr) ld bc, 64 add hl, bc ex de, hl ld hl, (LevelPtr) ld bc, 1024-64 ILBotLoop: ld a, (WallType) cp (hl) jr nz, ILBotLoop2 ld (de), a ILBotLoop2: inc de inc de inc hl inc hl dec bc ld a, b or c jr nz, ILBotLoop ilBonusLoop: ;put bonus somewhere call &rand ld l, a call &rand and %00000011 ld h, a ld de, (LevelPtr) add hl, de ld a, (TileType) cp (hl) jr nz, ilBonusLoop ld (BonusPtr), hl ilExitLoop: ;put exit somewhere call &rand ld l, a call &rand and %00000011 ld h, a ld de, (LevelPtr) add hl, de ld a, (TileType) cp (hl) jr nz, ilExitLoop ld de, (BonusPtr) push hl call CP_HL_DE pop hl jr z, ilExitLoop ld (ExitPtr), hl ld hl, EnemyTable ld bc, 167 call OTH_CLEAR ld ix, EnemyTable ;;;asdf add here different numbers for different #'s of enemies... ld c, 3 ilDiffEnemies: ld hl, Enemy1Num-1 ld b, 0 add hl, bc ;hl = loc. to # of enemies ld a, (hl) or a jr z, ilDiffEnemiesBot ld b, a ilEnemies: ;init. enemies call &rand ld l, a call &rand and %00000011 ld h, a ld de, (LevelPtr) add hl, de ld a, (hl) or a jr nz, ilEnemies ;there's something there ld (ix+MemLoc), l ld (ix+MemLoc+1), h ;;; sbc hl, de add hl, hl add hl, hl add hl, hl sla h sla h sla h ld (ix+YPos), h ld (ix+XPos), l ld a, c ;this is what enemy ld (ix+SType), a ;;; ld hl, EnemiesLeft inc (hl) ld de, 15 add ix, de djnz ilEnemies ilDiffEnemiesBot: dec c ld a, c or a jr nz, ilDiffEnemies ld ix, (LevelPtr) push ix pop hl ld bc, 33 add hl, bc ld (Player+MemLoc), hl ;init. guy's position ld (ix+32+1), BLANK ld (ix+32+2), BLANK ld (ix+64+1), BLANK ilWait: halt ld a, (PlayrCtr) or a jr nz, ilWait ;************************************************************************* ;Description: Draws the visible part of the level ;Parameters: none ;Destroys: a, bc, de, hl DrawLevel: ld hl, (LevelPtr) ;hl contains pointer to level ld bc, 16*32 dlLoop: ld a, (hl) push bc push hl call &drawMem pop hl pop bc inc hl dec bc ld a, b or c jr nz, dlLoop ret ;************************************************************************* ;eraseGuy: remove the guy, and replace him with his background ;drawGuy: draw guy, with background saved ;parameters: nothing drawGuy: ld hl, &guyMemLoc+1 ld bc, (Player+YPos) ld de, Player+Background call &PutSprite_MSB ret eraseGuy: ld hl, Player+Background ld bc, (Player+YPos) call &PutSprite ret ;************************************************************************* drawEnemies: ld hl, EnemyTable ld b, MAXENEMIES de2: ld a, (hl) or a jr z, de3 push bc push hl ld c, a inc hl ;now hl=enemy+PosX ld b, (hl) push hl ld de, Background-1 add hl, de ex de, hl pop hl inc hl ;now hl=enemy+SType ;;;asdf this needs some work for different enemies too! push de ld a, (hl) dec a ld l, a ld h, 17 ;17=length of enemy datar push bc call MUL_HL pop bc ld de, &enemy1MemLoc+1 add hl, de pop de call &PutSprite_MSB pop hl pop bc de3: ld de, 15 add hl, de djnz de2 ret ;************************************************************************* eraseEnemies: ld hl, EnemyTable+(MAXENEMIES*15)-15 ld b, MAXENEMIES ee2: ld a, (hl) or a jr z, ee3 push bc push hl ld c, a inc hl ld b, (hl) ld de, Background-1 add hl, de call &PutSprite pop hl pop bc ee3: ld de, -15 add hl, de djnz ee2 ret ;************************************************************************* ;pause...pauses game pause: im 1 ; di ld c, 64 ld hl, VIDEO_MEM ld d, %10101010 pauseGrayY: ld b, 16 pauseGrayX: ld a, (hl) and d ld (hl), a inc hl djnz pauseGrayX rlc d dec c ld a, c or a jr nz, pauseGrayY ; ld bc, 1023 ; ld hl, VIDEO_MEM ; call OTH_CLEAR ; ld bc, $0566 ; ld hl, strScore ; call &DisplayMenuTxt ;display "score:" pauseGK: call GET_KEY cp K_EXIT jr z, pauseQuit cp K_ENTER jr nz, pauseGK ld bc, 1024 ld de, VIDEO_MEM ld hl, GRAPH_MEM ldir im 2 ; ei ret pauseQuit: call INT_REMOVE call OTH_EXIT ;quit game ;************************************************************************* ;drawMem: draw sprite (a) at memory location (hl) ;parameters: hl - memory location (LevelPtr+33 or whatever) drawMem: push hl push bc ld bc, (LevelPtr) or a sbc hl, bc add hl, hl add hl, hl add hl, hl sla h sla h sla h push hl call &getSprite pop bc ld a, b ld b, c ld c, a call &PutSprite pop bc pop hl ret ;************************************************************************* ;when the bomb explodes ;ix = BombPtr, de = BombCtr Explode: ld l, (ix) ld h, (ix+1) ld a, (BombRadius) ld b, a ld a, (hl) cp EXPBOMB jr z, ExpClear ExpFire: ld a, 30 ld (de), a ld a, EXPBOMB jr expLeft ExpClear: ld a, BLANK ld (ix+1), 0 ;reset counter expLeft: ld (hl), a call &drawMem ld c, (hl) ld de, -1 call &expDirection expDown: ld de, 32 call &expDirection expRight: ld de, 1 call &expDirection expUp: ld de, -32 ; call &expDirection ; ret expDirection: push bc push hl xor a cp c jr nz, expDirection1 expDirBlank: add hl, de ld a, (hl) cp FIRE jr nz, expDirection2 xor a ld (hl), a call &drawMem djnz expDirBlank jr expDirection2 expDirection1: add hl, de ld a, (hl) ld c, a ;if the piece is not a tile push hl call &getSprite pop hl bit DESTRUCT, a ;if the piece is indestructable jr z, expDirection2 ;don't destroy it ld a, (TileType) cp (hl) jr nz, noExit edCheckBonus: ld a, (BonusPtr) cp l jr nz, edCheckExit ld a, (BonusPtr+1) cp h jr nz, edCheckExit ld a, (BonusType) jr edSpecial edCheckExit: ld a, (ExitPtr) cp l jr nz, noExit ld a, (ExitPtr+1) cp h jr nz, noExit ld a, SPEXIT jr edSpecial noExit: ld a, FIRE edSpecial: ld (hl), a ;actually change the level data call &drawMem ld a, c or a jr nz, addScore ;don't go any farther djnz expDirection1 addScore: ; ld a, (TileType) ; cp c ; jr nz, expDirection2 ; ld hl, (CurrPts) ; add hl, hl ; ld (CurrPts), hl ; ld b, h ; ld c, l ; ld hl, (Score) ; add hl, bc ; ld (Score), hl expDirection2: pop hl pop bc ret ;************************************************************************* ;Description: Gets the memory position for and attributes of a sprite ;Parameters: a = which sprite ;Returns: a = attributes, hl = memLoc of sprite (in proggy) ;Destroys: a, hl getSprite: push bc push de ld h, 9 ld l, a call MUL_HL ld de, &Sprites add hl, de ld a, (hl) ;a contains attributes of sprite inc hl ;hl contains mem loc of sprite pop de pop bc ret ;************************************************************************* ;parameters: ix: sprite structure (must be Player for now), a: direction, b: which sprite ;destroys: a, de, hl moveGuy: ; push af ; push bc ; push de ; push hl ; ld hl, (Player+MemLoc) ; ld de, $3A62 ; ld (CURSOR_X), de ; res 3, (IY+5) ; call DM_HL_DECI ; pop hl ; pop de ; pop bc ; pop af ld bc, 0 bit 3, a jr nz, mgup bit 0, a jp nz, &mgdown bit 2, a jr nz, mgright bit 1, a ret z mgleft: ld a, (Player+XPos) and 7 jr nz, mgleft2 ld hl, (Player+MemLoc) ;check to see if he CAN move left dec hl ld a, (hl) ;he can't move if he can't step on it call &getSprite bit STEPON, a ret z ld a, (Player+YPos) and 7 or a jr z, mgleft2 cp 3 jr c, mgup2 cp 5 jp nc, &mgdown2 ret mgleft2: dec b ;change the x position adder jr mgbot mgright: ld a, (Player+XPos) and 7 jr nz, mgright2 ld hl, (Player+MemLoc) ;check to see if he CAN move right inc hl ld a, (hl) ;he can't move if he can't step on it call &getSprite bit STEPON, a ret z ld a, (Player+YPos) and 7 or a jr z, mgright2 cp 3 jr c, mgup2 cp 5 jr nc, mgdown2 ret mgright2: inc b ;change the x position adder jr mgbot mgup: ld a, (Player+YPos) and 7 jr nz, mgup2 ld hl, (Player+MemLoc) ;check to see if he CAN move up ld de, -32 add hl, de ld a, (hl) ;he can't move if he can't step on it call &getSprite bit STEPON, a ret z ld a, (Player+XPos) and 7 or a jr z, mgup2 cp 3 jr c, mgleft2 cp 5 jr nc, mgright2 ret mgup2: dec bc ;change the y position adder jr mgbot mgdown: ld a, (Player+YPos) and 7 jr nz, mgdown2 ld hl, (Player+MemLoc) ;check to see if he CAN move down ld de, 32 add hl, de ld a, (hl) ;he can't move if he can't step on it call &getSprite bit STEPON, a ret z ld a, (Player+XPos) and 7 or a jr z, mgdown2 cp 3 jr c, mgleft2 cp 5 jr nc, mgright2 ret mgdown2: inc c ;change the y position adder mgbot: ld (Player+Direction), bc ld a, (Player+YPos) ;find player's real memLoc add a, c add a, 4 and %11111000 ld h, 0 ld l, a add hl, hl add hl, hl ld a, (Player+XPos) add a, b add a, 3 srl a srl a srl a ld d, 0 ld e, a add hl, de ld de, (LevelPtr) add hl, de ld (Player+MemLoc), hl ld bc, (Player+Direction) ld hl, (Player+YPos) add hl, bc ld (Player+YPos), hl ret ;************************************************************************* ;parameters: ix: pointer to Enemy Data Struct, hl: ptr to Counter ;destroys: all registers i think moveEnemy: ld l, (ix+YPos) ld h, (ix+XPos) ld a, l or h and 7 ret nz ;if it's not at an intersection, keep goin' meRand: call &rand and 3 me2: ld bc, 0 ld l, (ix+MemLoc) ;ld hl with pointer to enemy ld h, (ix+MemLoc+1) cp 1 jr z, meright cp 2 jr z, meup cp 3 jp z, &medown meleft: dec hl ;check to see if he can move left ld a, (hl) ;he can't move if he can't step on it call &getSprite bit STEPON, a jr z, mebot dec b ;change the direction variable jr mebot meright: inc hl ld a, (hl) call &getSprite bit STEPON, a jr z, mebot inc b jr mebot meup: ld de, -32 add hl, de ld a, (hl) call &getSprite bit STEPON, a jr z, mebot dec bc jr mebot medown: ld de, 32 add hl, de ld a, (hl) ;he can't move if he can't step on it call &getSprite bit STEPON, a jr z, mebot inc c mebot: ld (ix+Direction), c ld (ix+Direction+1), b ret moveEnemiesInMem: ld ix, EnemyTable ld hl, EnemyCtrs ld b, MAXENEMIES meim2: ld a, (hl) or a jr nz, meim3 ;;asdf this place needs some work, like u know for different enemies... ld a, (&enemy1MemLoc) ld (hl), a ;reset enemy move counter ld e, (ix+Direction) ld d, (ix+Direction+1) ld a, d or e jr z, meim3 push hl ld l, (ix+YPos) ld h, (ix+XPos) add hl, de ld (ix+YPos), l ld (ix+XPos), h ld a, (ix+YPos) ;find enemy's real memLoc add a, 4 and %11111000 ld h, 0 ld l, a add hl, hl add hl, hl ld a, (ix+XPos) add a, 3 srl a srl a srl a ld d, 0 ld e, a add hl, de ld de, (LevelPtr) add hl, de ld (ix+MemLoc), l ld (ix+MemLoc+1), h pop hl meim3: ld de, 15 add ix, de inc hl djnz meim2 ret ; ld c, (ix+YPos) ; ld b, (ix+XPos) ; push ix ; pop hl ; ld de, Background ; add hl, de ; push hl ; call &PutSprite ; pop de ; ld c, (ix+Direction) ; ld b, (ix+Direction+1) ; ld l, (ix+YPos) ; ld h, (ix+XPos) ; add hl, bc ; ld (ix+YPos), l ; ld (ix+XPos), h ; push hl ; pop bc ; ld hl, &enemy1MemLoc+1 ; jp &PutSprite_MSB ;**************** Sprite Routines *********************************** ;by Jimmy Mardell #include "ascr.h" ;**************** Zshell Compressed Pictures ************************ ;The TI-based decoder source : zcp.asm ;------------------------------------- ;--- ;--- ZCP decoding routine for ZShell 4.0 ;--- original by Stephane Jantzen - 12/16/1995 ;--- ;--- This version by Pascal Bouron - 02/11/96 ;--- ;--- Please report all bugs to : ;--- Bouron@YOKO.ENS-cachan.fr, or ;--- Stephane.Jantzen@scinfo.u-nancy.fr ;--- ;paramaters: hl - relative loc. of picture data ZCP20: DI push hl ld HL, VIDEO_MEM+$03FF xor A ld (HL), A ld DE, $FFFE ld BC, $03FF lddr exx pop HL ld C, $80 Loop: ld A, (HL) inc HL ld D, A or A jr Z, EndDecode rlca jr C, Copy Stream: ld A, D and $3F ld B, A ld A, D and $40 StreamLoop: or A jr Z, SLSuite ex AF, AF' ld A, C exx or (HL) ld (HL), A exx ex AF, AF' SLSuite: srl C jr NC, DjnzSL exx inc HL exx ld C, $80 DjnzSL: djnz StreamLoop jr Loop Copy: ld B, $07 CopyLoop: rlca jr NC, CLSuite ex AF, AF' ld A, C exx or (HL) ld (HL), A exx ex AF, AF' CLSuite: srl C jr NC, DjnzCL exx inc HL exx ld C,$80 DjnzCL: djnz CopyLoop jr Loop EndDecode: exx EI ret ;******************** the random number routine ************************** ;Description: returns a, a random number ;Parameters: none ;Destroys: a rand: ;ld's a with a rnd # push de ld a, (randNum) ld d, a sla d sla d add a, d sla d sla d add a, d ld d, a ld a, r add a, d ld (randNum), a pop de ret ;******************* Display Text routines ************************** ;Description: Displays zero terminated text on the screen ; in menu format ;Parameters: hl - address of zero terminated string ; relative to top of program ; bc - location on screen ;Destroys: bc, de, hl DisplayMenuTxt: ld (CURSOR_X), bc ld de, (PROGRAM_ADDR) add hl, de set 3, (IY+5) ;make menu text invert screen call D_ZM_STR ret ;************************************************************************* Strings: strHiScore: .db "High " strScore: .db "Score:",0 ;strBombs: .db "Bombs:",0 strLevelData: .db "bombLvl",0 strStage: .db "Stage",0 ExpTable: .db $01,$80,$40,$20,$10,$08,$04,$02,$01 Levels: ; Y size (must be odd), X size (must be odd), sprite # walls, sprite # tiles ; bonustype, # of enemy1, # of enemy2, # of enemy3 ; Size Limit: 17