;============== ; DETimes8 ;=============== DETimes8: ld a,e add a,a add a,a add a,a ld c,a ld a,d add a,a add a,a add a,a ld e,a ld d,c ret ;===================== ; UpdateSpriteTable ;===================== UpdateSpriteTable: ld hl,SpriteGTable ld a,(frame) add a,$80 ld (hl),a ld b,8 UpdateLoop: push bc ld hl,SpriteGTable ld a,b dec a ld b,0 ld c,a add hl,bc ld a,(hl) cp $80 jr nc,UpdateCharGfx ld hl,items call calcoffset UpdateSpriteTable2: ex de,hl ld hl,SpriteGFXTable pop bc push bc ld a,b dec a add a,a ld c,a ld b,0 add hl,bc ld (hl),e inc hl ld (hl),d inc hl pop bc djnz UpdateLoop ret UpdateCharGfx: ld hl,player and $7F call calcoffset12 jr UpdateSpriteTable2 calcoffset: ;Multiply by 16 to get sprite offset add a,a add a,a add a,a add a,a ;Add to hl ld c,a ld b,0 add hl,bc ret calcoffset12: ;Multiply by 24 to get sprite offset ld c,a add a,a add a,c add a,a add a,a add a,a ;Add to hl ld c,a ld b,0 add hl,bc ret ;============================================ ; CalcCoords- Calculates X and Y positions of everything ;============================================ CalcCoords: ;Multiply X position by 8 and store it ld a,(xpos) add a,a add a,a add a,a ld (PlayPos+1),a ;Multiply Y position by 8 and store it ld a,(ypos) add a,a add a,a add a,a sub 4 ld (PlayPos),a ret ;======================================== ; FixBack - Fixes Animated Backgrounds ;======================================== FixBack: ld a,(animback) cp $81 ret nc and 1 call z,AnimateBack ret ;======================================= ; DoEvents - Handles background stuff ;======================================= DoEvents: ;Save Regs push bc push hl push de call UpdateSpriteTable call AnimateBack call RenderScreen pop de pop hl pop bc ret ;================================== ; RenderScreen- Draws the screen ;================================== RenderScreen: ;Restore Screen call displaycave ;Draw All Sprites! ld b,0 ld c,7 RenderSpritesLoop: push bc ld hl,SpriteGTable add hl,bc ld a,(hl) cp $80 ld a,8 jr c,$+4 ld a,12 call SetSpriteHeight ld hl,SpritePosTable sla c add hl,bc ld e,(hl) inc hl ld d,(hl) ld hl,SpriteGFXTable add hl,bc icall(_ldhlind) push de pop bc call PutSprClp pop bc ld a,c sub 1 ld c,a jr nc,RenderSpritesLoop jp FastCopy ; ;Draw item: ; ;Get item sprite offset in hl ; ld hl,(ItemGfx) ; ;Get sprite position in BC ; ld bc,(ItemPos) ; ;Draw Sprite ; call PutSprClp ; ; ;Draw Player: ; ld a,12 ; call setspriteheight ; ;Get player address ; ld hl,(PlayGfx) ; ;Get sprite position in BC ; ld bc,(PlayPos) ; ;Draw Sprite ; call PutSprClp ; ld a,8 ; call setspriteheight ; ;==================================== ; Checkde- Checks if @de is a wall ;==================================== ;in: e=x, d=y ;out: hl=Byte in Caveram, a=Byte at hl Checkde: ;force a=d ld a,d ;Multiply Y by 12 and add X add a,a add a,d add a,a add a,a add a,e ;Store a into c ld c,a ;Clear B ld b,0 ;Add to caveram's location ld hl,caveram add hl,bc ;Load the byte there ld a,(hl) ret ;==================================================== ; PlaceIt- Gets unblocked random coordinates in de ;==================================================== PlaceIt: ;X=Random 2-9 ld b,8 call Random add a,2 ;Store Xpos into e ld e,a ;Y=Random 2-5 ld b,4 call Random add a,2 ;Store Ypos into d ld d,a ;Check under call CheckDe ;If a wall or other thing and $F4 ;Restart. jr nz,PlaceIt ret ;========================================== ; NewMap- Calls some stuff for a new map ;========================================== NewMap: call FixBack ;Fix Tiles call decompcave ;Load New Cave ;Clear Sprite Table ld hl,SpritePosTable ld b,40 ld (hl),0 inc hl djnz $-3 ;Check for Stairs Down: call GetMapByte push af and 16 ;Skip if no stairs down jr z,NMSkip1 call placeit ld a,(hl) or $10 ld (hl),a call detimes8 ld (StairsDownPos),de ld a,$10 ld (SpriteTable+1),a ld a,$2 ld (SpriteGTable+1),a NMSkip1: pop af push af and 64 ;Skip if no stairs up jr z,NMSkip2 call placeit ld a,(hl) or $20 ld (hl),a call DETimes8 ld (StairsUpPos),de ld a,$11 ld (SpriteTable+2),a ld a,$3 ld (SpriteGTable+2),a NMSkip2: pop af push af and 32 ;Skip if no item jr z,NMSkip3 call placeit ld a,(hl) or $30 ld (hl),a call DETimes8 ld (ItemPos),de ld a,$6 ld (spriteTable+3),a ld a,$9 ld (spriteGTable+3),a NMSkip3: pop af push af and 128 ;Skip if no portal jr z,NMSkip4 call placeit ld a,(hl) or $40 ld (hl),a call DETimes8 ld (PortalPos),de ld a,$7 ld (spriteTable+4),a ld a,$C ld (spriteGTable+4),a NMSkip4: pop af call UpdateSpriteTable ret ;======================================= ; Movearound- Move around in the cave ;======================================= MoveAround: call NewMap ;Place Player call placeit ld (xpos),de ;Start Loop ;============== ; Move Loop: ;============== MoveLoop: ;Draw Screen call calccoords call awaitkey ld de,(xpos) ;=============== ; Check Keys: ;=============== ;Down? cp GDown jr z,MoveDown ;Up? cp GLeft jr z,MoveLeft ;Left? cp GRight jr z,MoveRight ;Right? cp GUp jr z,MoveUp ;Clear quits cp GClear ;Clear quits ret z ;Mode induces battles cp GMode call z,ImpendingBattle ;Plus skips levels cp GAdd call z,GoPortal ;Go back to moveloop jr MoveLoop ;================= ; Keys pressed: ;================= MoveDown: ;inc ypos inc d ;down frame ld a,6 jr MoveCheck MoveUp: ;dec ypos dec d ;up frame ld a,2 jr MoveCheck MoveLeft: ;dec xpos dec e ;down frame xor a jr MoveCheck MoveRight: ;inc xpos inc e ;Right frame ld a,4 ;=================== ; After movement: ;=================== MoveCheck: ;Set new animation frame ld b,a ld a,(frame) and 1 xor 1 or b ld (frame),a ; call UpdatePlayerGfx ;================================= ; Check to see if off the edge: ;================================= ;Check Y position: ld a,d ;If -1, inc a ;Up a room jr z,roomup ;If 8 cp 8+1 ;Down a room jr z,roomdown ;Check X position: ld a,e ;If -1, inc a ;Left a room jr z,roomLeft ;If 12 cp 12+1 ;Right a room jr z,roomRight ;===================================== ; Check what's at player's position ;===================================== ;Check at de call checkde ;Check bit %00000100 (Wall bit) and 4 ;If wall, Go back. jr nz,MoveLoop ;Otherwise: ;Set new position call smoothmove ;========================= ; Check if on an object ;========================= call checkde rra rra rra rra and $0F jr nz,onitem ;Check if should get into a battle ld a,(fight) dec a ld (fight),a call z,battle ;Go back to loop if there's no item jr MoveLoop ;===================================== ; Code that handles switching rooms ;===================================== ;Each Room___ code consists of the following: ;Set the new x/y position ;Inc or dec MAP row or column respectively ;Go to RoomDif RoomUp: ld d,7 ld hl,row dec (hl) jr RoomDif RoomDown: ld d,0 ld hl,row inc (hl) jr RoomDif RoomLeft: ld e,11 ld hl,col dec (hl) jr RoomDif RoomRight: ld e,0 ld hl,col inc (hl) RoomDif: ;Set new position ld (xpos),de ;Get new map call newMap ;Back to movement jp MoveLoop ;====================== ; Item Handling Code ;====================== OnItem: ;You stepped on an item... ;Get Item Type: ld hl,SpriteTable ld c,a ld b,0 add hl,bc ld a,(hl) ;Item checks+jumps ld hl,afteritem push hl Itemcheck: ;A bunch of checks for different items: ;it decs a and jumps if true. cp $10 ;Stairs Down jp z,getStairsDown cp $11 ;Stairs Up jp z,getStairsUp dec a ;$1 jr z,getherb ; dec a ;$2 jr z,getgold ; dec a ;$3 jr z,getsword ; dec a ;$4 jp z,getshield ; dec a ;$5 jp z,getscroll ; dec a ;$6 jp z,getchest ; dec a ;$7 jp z,goportal ; dec a ;$8 jp z,getboss ; ret ; getherb: ld hl,herbs inc (hl) call textbox1 ld hl,$091E ld (pencol),hl ld hl,tgot bcall(_vputs) ld hl,tgotanherb bcall(_vputs) call waitkey ret getgold: ;Set a to (room) ld a,(room) ;multiply a by 2 add a,a ;Force min 1 add a,9 ;a=random up to a ld b,a call random ;add 13 add a,13 ;Set hl=a ld l,a ld h,0 ;Save gold gained push hl ;Add gained gold to existing gold ld bc,(gold) add hl,bc ;If it's greater than 64k, jr nc,NotTooMuchGold ;Set gold to 64k. ld hl,65535 NotTooMuchGold: ;Store gold ld (gold),hl ;Draw the box call textbox1 ;Load text address ld hl,tgotgold ;Display text in small font bcall(_vputs) ;Get gold gained pop hl ;Display that in small font call vdisphl ;Load rest of text address ld hl,tgotgold2 ;Display that bcall(_vputs) ;Wait for a key call waitkey ;Jump ahead :) ret GetSword: ;Calculate the random weapon power call CalculateWeapon ;Compare to your weapon ld de,(Sword) icall(_cphlde) ;Worse weapon? Jump toGetUselessSword jr c,GetUselessSword ld (Sword),hl push hl ld hl,tGotSword push hl jr DispGetWeapon GetShield: ;Calculate the random shield power call CalculateWeapon ;Compare to your shield ld de,(Shield) icall(_cphlde) ;Worse shield? Jump toGetUselessShield jr c,GetUselessShield ld (Shield),hl push hl ld hl,tGotShield push hl jr DispGetWeapon GetUselessSword: ld hl,tSword push hl jr DispGetUselessWeapon GetUselessShield: ld hl,tShield push hl jr DispGetUselessWeapon DispGetUselessWeapon: call textbox1 ld hl,tGotUseless bcall(_vputs) pop hl bcall(_vputs) ld hl,texclaim bcall(_vputs) call waitkey ret DispGetWeapon: call textbox1 ld hl,tGot bcall(_vputs) pop hl bcall(_vputs) pop hl call vdisphl ld hl,tExclaim bcall(_vputs) call waitkey ret getchest: ;Treasure chests have random treasure 1-5 ld b,5 call random inc a ;New item in, now recheck it. jp Itemcheck getscroll: ;Get scroll 0-7 randomly ld b,8 call random ;Prepare offset to write to ld b,0 ld c,a ;Get offset of scrolls ld hl,scrolls ;Add offset of scroll# add hl,bc ;Increase that value inc (hl) ;Save scroll# push af ;Draw text box call textbox1 ;Display "Found " ld hl,tGotScroll bcall(_vputs) ;Get back scroll# pop af ;Double for word pointers add a,a ;Get offset for name ld b,0 ld c,a ;Get offset of ScrollNames ld ix,scrollnames ;Add to offset of scrollnames add ix,bc ld h,(ix+1) ld l,(ix+0) ;Display name of scroll bcall(_vputs) ;Display rest of message " Scroll!" ld hl,tGotScroll2 bcall(_vputs) ;Wait for key call waitkey ret afteritem: call getmapbyte ld a,(hl) and $DF ld (hl),a xor a ld (SpriteGTable+3),a ld (SpriteTable+3),a jp moveloop goportal: ;Ditch stack pop hl ;Increment room# ld hl,room inc (hl) ;Make new dungeon call makedung ;Start in center of dungeon ld a,7 ld (row),a ld (col),a ;Kewl transition call transition ;Restart Movearound jp movearound getboss: jr goportal getStairsDown: ld a,(row) add a,16 ld (row),a call newmap ld hl,(StairsUpPos) getStairs2: ld a,h ld h,l rra rra rra and 15 ld l,a ld a,h rra rra rra and 15 ld h,a ld (xPos),hl pop hl jp moveloop getStairsUp: ld a,(row) sub 16 ld (row),a call newmap ld hl,(StairsDownPos) jr GetStairs2 multiply: ; de goes in ; b is the multiplicand ld hl,0 ret z multLoop: add hl,de djnz multLoop ; hl = answer ret ;======================================================= ; CalculateWeapon- Does r*(r/4) + rand(2r)*2 + 2r + 6 ;======================================================= CalculateWeapon: ;Do A^2/4 which is (a/4)*a ld a,(room) ld d,0 ld e,a ld b,a srl b srl b srl b call multiply ;Save result push hl ;Do rand(2*(a+1)) inc a add a,a ld b,a call random or a ;Do *2 ld d,0 ld e,a ld b,2 call multiply ;add 2a+3 ld bc,1 add hl,bc ld de,(room) ld d,0 sla e add hl,de ;add first calculation pop de add hl,de ret ;================================================== ; Smoothmove- Moves the player 1 pixel at a time ;================================================== smoothmove: ;Get delta X and delta Y by subracting old values (de is YX) ;Xpos and Ypos get updated with de, ;hl conatins the ld hl,(xpos) ld (xpos),de sbc hl,de ld a,l inc a jr nz,sm_skipadd inc h sm_skipadd: ;Save old values for movement ex de,hl ld b,8 smth1: ld hl,(playpos) ld a,l sub d ld l,a ld a,h sub e ld h,a ld (playpos),hl ld a,b and 1 call z,DoEvents djnz smth1 ld de,(xpos) ret ;====================================== ; MakeDung- Random dungeon generator ;====================================== MakeDung: ;=================== ; Choose Tileset: ;=================== ld a,(room) ;Get room rra ;Divide by 4 rra and 00111111b and 7 ;Mod 8, 8 tilesets in all add a,a ;Multiply a by 32 add a,a add a,a add a,a add a,a ld b,0 ;Add 64*tileset to tile pointer ld c,a ld hl,sprites add hl,bc add hl,bc ld (spritepoint),hl ;Set the new tileset ;=================== ; Other prep work ;=================== ld ixh,$80 ;Set first map on so portal can be generated ; ld a,(room) ;Boss every 4th level ; inc a ;...... ; and %11111100 ;.... ; jr nz,skipprepboss ;.. ; ld ixh,$8F ;. skipprepboss: ;================= ; Clear the map ;================= ; ld hl,map ;Load map loaction ld de,map+1 ;Load alt map location ld bc,766 ;Load size (767) ld (hl),0 ;Clear the first byte ldir ;Clear the map! ;============================= ; Make the map initilzation ;============================= ; ld hl,7*16+7+map ;Set number of tunnels (room/4+3) ld a,(room) rla rla and %00111111 add a,3 ;Load it into b ld b,a ;===================== ; Make the map loop ;===================== MakeLoop1: ;Set length of tunnel (room*2+15) ld a,(room) add a,a add a,15 ;Load it into c ld c,a ;=========== ; subloop ;=========== MakeLoop2: push bc ;Save Tunnel Progress ld b,1 call dqrand ;Get seeded random number and %00001110 ;Filter 0-7 (times 2!) cp 7 ld c,a jr nc,MakeLoop3 call dqrand and %00000001 add a,2 ld b,a ld a,c MakeLoop3: push bc ;Save Hall Progress push hl ;Save Map offset ;=========== ; Get HL ;=========== ld hl,DeltaT ;Load Table Address ld e,a ;Load table change ld d,0 ;" add hl,de ;Get the delta! ld e,(hl) ;.... inc hl ;... ld d,(hl) ;.. ;============= ; Get Masks ;============= rra push de ld hl,Mask1T ld d,0 ld e,a add hl,de ld c,(hl) ld e,8 add hl,de ld b,(hl) ;============== ; Setup Loop ;============== pop de pop hl push hl push de add hl,de ld de,Map sbc hl,de jr c,BadDir_Skip1 ld de,768 sbc hl,de jr c,BadDir_Skip2 BadDir_Skip1: pop de pop hl pop bc pop bc jr MakeLoop2 BadDir_Skip2: pop de pop hl ;============ ; Do It!!! ;============ ld a,(hl) or c ld (hl),a add hl,de ld a,(hl) or b ld (hl),a pop bc djnz MakeLoop3 pop bc dec c xor a or c jr nz,Makeloop2 ld a,ixh and a jr z,MakeExit_Skip ld a,(hl) or ixh ld (hl),a ld ixh,0 MakeExit_Skip: call DQRand ld e,a ld d,0 ld hl,Map+64 add hl,de djnz MakeLoop1 ret ;==================================== ; GetMapByte- Gets a byte from map ;==================================== ;Input: none ;Output: a=map value hl=map address ;Destroys: af,bc,hl GetMapByte: ;clear h ld h,0 ld b,h ;get row ld a,(row) ld l,a ;multiply row by 16 add hl,hl add hl,hl add hl,hl add hl,hl ;add the column ld a,(col) ld c,a add hl,bc ;add the map loaction ld bc,map add hl,bc ;get the map value ld a,(hl) ret ;================================================= ; DecompCave- Decompresses RLE compressed caves ;================================================= decompcave: ;================================== ; Step 1: Get cave byte from map ;================================== call GetMapByte ;Remove top bits and 15 ;Finally store it into c ld c,a ;=============================== ; Step 2: Get pointer to cave ;=============================== ; ;clear b ld b,0 ;Multiply c by 2 sla c ;load address of cavetable ld hl,cavetable ;calculate final pointer to cave in hl add hl,bc ;ld hl,(hl) icall(_ldhlind) ;====================================== ; Step 3: Do the real decompression! ;====================================== ; ;Prepare for loop ld de,caveram ld c,0 ;Start a loop rleloop1: ;Get the byte at hl ld a,(hl) ;Exit on FF cp 255 ret z ;Copy that to b ld b,a ;move top nib of b to bottom srl b srl b srl b srl b ;Increment b inc b ;Remove first 4 bits from a and 15 ;Start a loop rleloop2: ;Store the data ld (de),a ;Increase the destination address inc de ;repeat b times djnz rleloop2 ;Increase source offset inc hl ;Do it again jr rleloop1 ;======================================================================== ; DisplayCave- Displays cave on graph buffer ;======================================================================== ;Following code by tcpa.calc.org, modified for use in Dragonquest Dungeon ;"This draws a 8x12 screen tile map pointed to by de, ;with offsets from tiles. The routine is 58 bytes." ;======================================================================== Displaycave: ld de, caveram ld hl, plotsscreen ld bc, 8*256+0 DrawmapLoop: ld a, (de) and 15 push de push hl ld l, a ld h, 0 add hl, hl add hl, hl add hl, hl ld de, (spritepoint) add hl, de ex de, hl pop hl push bc ld b, 8 push hl DrawmapLoop2: ld a, (de) ld (hl),a inc de push bc ld bc, 12 add hl, bc pop bc djnz DrawmapLoop2 pop hl pop bc pop de inc de inc hl inc c ld a, c cp 12 jr nz, Drawmaploop ld c,0 push de ld de, 7*12 add hl, de pop de djnz Drawmaploop ret