mirror of https://github.com/AbePralle/FGB.git
4716 lines
118 KiB
NASM
4716 lines
118 KiB
NASM
;Class.asm
|
|
;Gfx.asm
|
|
;Map.asm
|
|
;Object.asm
|
|
;Music.asm
|
|
;---------------------------------------------------------------------
|
|
; user.asm
|
|
; 12.18.99 by Abe Pralle
|
|
;---------------------------------------------------------------------
|
|
|
|
INCLUDE "Source/Defs.inc"
|
|
INCLUDE "Source/Start.inc"
|
|
INCLUDE "Source/Items.inc"
|
|
|
|
MIN_VBLANKS EQU 2
|
|
|
|
INTCLK EQU $83
|
|
EXTCLK EQU $82
|
|
|
|
|
|
|
|
|
|
SECTION "User",ROM0
|
|
|
|
;---------------------------------------------------------------------
|
|
; Subroutine: UserMain
|
|
; Description: Sets up game then goes into main loop
|
|
;---------------------------------------------------------------------
|
|
UserMain::
|
|
call InitGfx
|
|
|
|
;set up initial location + hero
|
|
;initial L0009 (demo intro)
|
|
ld a,LEVELSTATEBANK
|
|
ld [$ff70],a
|
|
xor a
|
|
ld [curLevelStateIndex],a
|
|
|
|
xor a
|
|
ldio [mapState],a
|
|
ldio [mapState+1],a
|
|
|
|
;initial level index
|
|
ld a,((INITIALMAP>>8) & $ff)
|
|
ld [curLevelIndex+1],a
|
|
ld a,(INITIALMAP & $ff)
|
|
ld [curLevelIndex],a
|
|
|
|
ld hl,$1102
|
|
call SetJoinMap
|
|
call SetRespawnMap
|
|
|
|
ld a,[heroesUsed]
|
|
or INITTYPE0
|
|
ld [heroesUsed],a
|
|
|
|
;hero 0 initial setup
|
|
ld a,(INITHERO0 & $ff)
|
|
ld [hero0_class],a
|
|
ld a,((INITHERO0>>8)&$ff)
|
|
ld [hero0_class+1],a
|
|
ld a,(INITLOC0 & $ff)
|
|
ld [hero0_enterLevelLocation],a
|
|
ld a,((INITLOC0>>8) & $ff)
|
|
ld [hero0_enterLevelLocation+1],a
|
|
ld a,INITEXIT0
|
|
ld [hero0_enterLevelFacing],a
|
|
ld a,INITTYPE0
|
|
ld [hero0_type],a
|
|
xor a
|
|
ld [hero0_health],a
|
|
|
|
;hero 1 initial setup
|
|
ld a,(INITHERO1 & $ff)
|
|
ld [hero1_class],a
|
|
ld a,((INITHERO1>>8)&$ff)
|
|
ld [hero1_class+1],a
|
|
ld a,(INITLOC1 & $ff)
|
|
ld [hero1_enterLevelLocation],a
|
|
ld a,((INITLOC1>>8) & $ff)
|
|
ld [hero1_enterLevelLocation+1],a
|
|
ld a,INITEXIT1
|
|
ld [hero1_enterLevelFacing],a
|
|
ld a,INITTYPE1
|
|
ld [hero1_type],a
|
|
xor a
|
|
ld [hero1_health],a
|
|
|
|
ld a,1
|
|
ld [timeToChangeLevel],a
|
|
|
|
jr .loadNextLevel
|
|
|
|
.game ld a,[timeToChangeLevel]
|
|
or a
|
|
jr z,.continue
|
|
|
|
;switch levels
|
|
ld b,METHOD_DIE
|
|
call IterateAllLists
|
|
ld a,15
|
|
call SetupFadeToBlack
|
|
call WaitFade
|
|
|
|
.loadNextLevel
|
|
call LoadNextLevel
|
|
call UpdateObjects
|
|
call GentleCameraAdjust
|
|
call levelCheckRAM
|
|
call RedrawMap
|
|
ld a,15
|
|
call SetupFadeFromBlack
|
|
call WaitFade
|
|
;call LighteningIn
|
|
|
|
.continue
|
|
call MainLoopUpdateObjects
|
|
call GentleCameraAdjust
|
|
|
|
call levelCheckRAM
|
|
.afterLevelCheck
|
|
call RedrawMap
|
|
jr .game
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: SetActiveROM
|
|
; Argument: a - desired ROM bank
|
|
; Returns: Nothing.
|
|
; Alters: af
|
|
; Description: Switches to a new ROM bank by writing the new bank
|
|
; number to [$2100]. Also saves the bank in
|
|
; [curROMBank].
|
|
;---------------------------------------------------------------------
|
|
SetActiveROM::
|
|
ldio [curROMBank],a
|
|
ld [$2100],a
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: LongCall
|
|
; Arguments: stack:
|
|
; +0: parameter de
|
|
; +2: parameter af
|
|
; +4: empty (for addr of routine)
|
|
; +6: empty (return addr from routine)
|
|
; +8: af - old ROM bank
|
|
; +10: return addr from LongCall
|
|
; a - bank of routine
|
|
; de - address of routine
|
|
; Returns: Whatever routine normally returns (excluding F).
|
|
; Alters: af, hl
|
|
; Description:
|
|
;---------------------------------------------------------------------
|
|
LongCall::
|
|
ldio [curROMBank],a ;switch to ROM containing routine
|
|
ld [$2100],a
|
|
|
|
push hl
|
|
ld hl,sp+6 ;point hl to empty spot in stack
|
|
ld [hl],e
|
|
inc hl
|
|
ld [hl],d ;save addr of method
|
|
inc hl
|
|
ld de,.returnAddress
|
|
ld [hl],e ;save return addr of method
|
|
inc hl
|
|
ld [hl],d
|
|
pop hl
|
|
pop de
|
|
pop af
|
|
ret ;call method
|
|
|
|
.returnAddress
|
|
ld [longCallTempA],a
|
|
pop af ;get old ROM bank
|
|
ldio [curROMBank],a
|
|
ld [$2100],a
|
|
ld a,[longCallTempA]
|
|
|
|
ret ;return from this routine
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: LongCallNoArgs
|
|
; Arguments: a - RAM bank of routine
|
|
; hl - address of routine
|
|
; Returns: Nothing.
|
|
; Alters: af
|
|
; Description: Quick & dirty long call (handles bank swapping)
|
|
; for routines that don't require arguments or return
|
|
; values.
|
|
;---------------------------------------------------------------------
|
|
LongCallNoArgs::
|
|
push bc
|
|
|
|
ld b,a
|
|
ld a,[curROMBank]
|
|
push af ;save old bank
|
|
|
|
ld a,b
|
|
ld [curROMBank],a ;swap in new bank
|
|
ld [$2100],a
|
|
|
|
ld bc,.returnAddress
|
|
push bc
|
|
|
|
jp hl
|
|
.returnAddress
|
|
|
|
pop af ;retrieve old bank & swap it in
|
|
ld [curROMBank],a
|
|
ld [$2100],a
|
|
|
|
pop bc
|
|
ret
|
|
|
|
WaitFade::
|
|
call FadeStep
|
|
|
|
;took out distorts synchronization
|
|
;send a null control byte
|
|
;ld a,LNULL
|
|
;call ExchangeByte
|
|
;call HandleRemoteInput
|
|
|
|
call CheckSkip
|
|
ld a,[specialFX]
|
|
and FX_FADE
|
|
jr nz,WaitFade
|
|
|
|
;allow last palette to install
|
|
.waitInstall
|
|
ldio a,[paletteBufferReady] ;wait for vblank
|
|
or a
|
|
jr nz,.waitInstall
|
|
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: CheckSpecialFX
|
|
; Alters: af
|
|
; Description: Performs any special effects upkeep
|
|
;---------------------------------------------------------------------
|
|
CheckSpecialFX:
|
|
ld a,[specialFX]
|
|
and FX_FADE
|
|
jr z,.done
|
|
|
|
call FadeStep
|
|
ret
|
|
|
|
.done
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Subroutine: UpdateObjTimers
|
|
; Alters: af
|
|
; Description: Updates timers used for object movement
|
|
;---------------------------------------------------------------------
|
|
UpdateObjTimers::
|
|
ld a,[objTimerBase]
|
|
inc a
|
|
ld [objTimerBase],a
|
|
|
|
;put 2 LSB bits in 4:3
|
|
rlca
|
|
rlca
|
|
rlca
|
|
and %00011000
|
|
ld [objTimer60ths],a
|
|
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Subroutine: UpdateHeroTimers
|
|
; Alters: af
|
|
; Description: Updates timers used for hero/hero bullet movement
|
|
;---------------------------------------------------------------------
|
|
UpdateHeroTimers:
|
|
ld a,[heroTimerBase]
|
|
inc a
|
|
ld [heroTimerBase],a
|
|
|
|
;put 2 LSB bits in 4:3
|
|
rlca
|
|
rlca
|
|
rlca
|
|
and %00011000
|
|
ld [heroTimer60ths],a
|
|
|
|
ret
|
|
|
|
|
|
;---------------------------------------------------------------------
|
|
; Subroutine: VWait
|
|
; Description: Waits until a vertical blank occurs and then returns
|
|
;---------------------------------------------------------------------
|
|
VWait::
|
|
.vwait halt ;stop processor until interrupt
|
|
nop ;pad to prevent weird stuff after halt
|
|
|
|
;interrupt happened, let's look at our flag
|
|
ldio a,[vblankFlag]
|
|
or a ;a=a|a; tells us if vblankFlag is 1 or 0
|
|
jr z,.vwait ;not the vblank flag after all
|
|
|
|
;If we're here then a vblank has occurred. Get on with our lives.
|
|
xor a ;clear vblank flag
|
|
ldio [vblankFlag],a
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Subroutine: OnVBlank
|
|
; Description: Called every vertical blank. Sets "vblankFlag" to
|
|
; 1 to indicate a vertical blank has occurred
|
|
;---------------------------------------------------------------------
|
|
OnVBlank::
|
|
push af ;save all registers on stack
|
|
push bc
|
|
push de
|
|
push hl
|
|
|
|
ld a,1 ;set "vblankFlag" to 1
|
|
ldio [vblankFlag],a
|
|
|
|
;store current VRAM bank in use
|
|
ld a,[$ff00+$4f]
|
|
push af
|
|
|
|
;update timers
|
|
ld hl,vblankTimer
|
|
inc [hl]
|
|
|
|
;is the backBuffer ready for DMA blit to screen?
|
|
ldio a,[backBufferReady]
|
|
or a
|
|
jr z,.checkDMALoad ;wasn't ready
|
|
|
|
ld a,[displayType]
|
|
or a
|
|
jr nz,.afterVblankCheck ;cinema type
|
|
|
|
ldio a,[vblankTimer]
|
|
ld hl,vblankTemp
|
|
sub [hl]
|
|
ldio [vblanksPerUpdate],a
|
|
|
|
;update no faster than 1-frame-every-so-many-blanks clocks
|
|
cp MIN_VBLANKS
|
|
jr c,.checkDMALoad ;too soon to update
|
|
|
|
;MUST SYNCHRONIZE WITH REMOTE TO DYNAMICALLY CHANGE THIS
|
|
;jr z,.rightOn ;exactly right
|
|
;updating too many objects; decrease iterateNumObjects
|
|
;ld hl,iterateNumObjects
|
|
;ld a,[hl]
|
|
;cp 17
|
|
;jr c,.rightOn ;don't risk going below 16 per update
|
|
|
|
;dec [hl]
|
|
|
|
.rightOn
|
|
ldio a,[vblankTimer] ;save time of this screen update
|
|
ldio [vblankTemp],a
|
|
|
|
.afterVblankCheck
|
|
ld hl,updateTimer
|
|
inc [hl]
|
|
|
|
xor a
|
|
ldio [backBufferReady],a ;signal we've blitted backbuffer
|
|
|
|
;set VRAM bank to 0
|
|
xor a
|
|
ld [$ff00+$4f],a
|
|
|
|
;use DMA to transfer sprite OAM buffer to VRAM
|
|
call SpriteDMAHandler
|
|
|
|
;Initiate DMA transfer of backbuffer to VRAM
|
|
|
|
ld hl,backBuffer
|
|
ld a,h
|
|
ld [$ff00+$51],a ;high byte of source
|
|
ld a,l
|
|
ld [$ff00+$52],a ;low byte of source
|
|
ldio a,[backBufferDestHighByte]
|
|
ld [$ff00+$53],a ;high byte of dest
|
|
xor a
|
|
ld [$ff00+$54],a ;low byte of dest
|
|
ld a,37 ;copy (37+1)*16 = 608 bytes
|
|
ld [$ff00+$55],a ;store length to start DMA
|
|
|
|
;set VRAM bank to 1 (tile attributes)
|
|
ld a,1
|
|
ld [$ff00+$4f],a
|
|
|
|
;Initiate DMA transfer of tile attributes to VRAM
|
|
ld hl,attributeBuffer
|
|
ld a,h
|
|
ld [$ff00+$51],a ;high byte of source
|
|
ld a,l
|
|
ld [$ff00+$52],a ;low byte of source
|
|
ldio a,[backBufferDestHighByte]
|
|
ld [$ff00+$53],a ;high byte of dest
|
|
xor a
|
|
ld [$ff00+$54],a ;low byte of dest
|
|
ld a,37 ;copy (37+1)*16 = 608 bytes
|
|
ld [$ff00+$55],a ;store length to start DMA
|
|
|
|
ld a,[desiredPixelOffset_x]
|
|
ld [curPixelOffset_x],a
|
|
ld a,[desiredPixelOffset_y]
|
|
ld [curPixelOffset_y],a
|
|
jr .scroll
|
|
|
|
.checkDMALoad
|
|
ldio a,[dmaLoad]
|
|
or a
|
|
jr z,.scroll
|
|
|
|
.checkLoadBank0
|
|
bit 0,a
|
|
jr z,.checkLoadBank1
|
|
|
|
.loadBank0
|
|
res 0,a
|
|
ldio [dmaLoad],a ;indicate we've loaded it
|
|
xor a
|
|
ld [$ff4f],a
|
|
|
|
;Initiate DMA transfer to bank 0 VRAM
|
|
ld a,[dmaLoadSrc0+1]
|
|
ld [$ff00+$51],a ;high byte of source
|
|
ld a,[dmaLoadSrc0]
|
|
ld [$ff00+$52],a ;low byte of source
|
|
ld a,[dmaLoadDest0+1]
|
|
ld [$ff00+$53],a ;high byte of dest
|
|
ld a,[dmaLoadDest0]
|
|
ld [$ff00+$54],a ;low byte of dest
|
|
ld a,[dmaLoadLen0] ;copy (N+1)*16 bytes
|
|
ld [$ff00+$55],a ;store length to start DMA
|
|
|
|
.checkLoadBank1
|
|
ldio a,[dmaLoad]
|
|
bit 1,a
|
|
jr z,.scroll
|
|
|
|
.loadBank1
|
|
res 1,a
|
|
ldio [dmaLoad],a ;indicate we've loaded it
|
|
ld a,1
|
|
ld [$ff4f],a
|
|
|
|
;Initiate DMA transfer to bank 1 VRAM
|
|
ld a,[dmaLoadSrc1+1]
|
|
ld [$ff00+$51],a ;high byte of source
|
|
ld a,[dmaLoadSrc1]
|
|
ld [$ff00+$52],a ;low byte of source
|
|
ld a,[dmaLoadDest1+1]
|
|
ld [$ff00+$53],a ;high byte of dest
|
|
ld a,[dmaLoadDest1]
|
|
ld [$ff00+$54],a ;low byte of dest
|
|
ld a,[dmaLoadLen1] ;copy (N+1)*16 bytes
|
|
ld [$ff00+$55],a ;store length to start DMA
|
|
|
|
.scroll ;Adjust scroll coordinates
|
|
ld hl,lineZeroHorizontalOffset
|
|
ldio a,[jiggleDuration]
|
|
or a
|
|
jr z,.useNormalScreenOffsets
|
|
|
|
;jiggle the screen!
|
|
dec a
|
|
ldio [jiggleDuration],a
|
|
|
|
;determine jiggle type
|
|
ld a,[jiggleType]
|
|
or a
|
|
jr nz,.takeoffJiggle
|
|
|
|
.normalJiggle
|
|
;pick a "random value"
|
|
ld a,[jiggleLoc]
|
|
add 17
|
|
ld [jiggleLoc],a
|
|
ld b,a ;store random value in b
|
|
and %00000111 ;random x offset
|
|
ldio [baseHorizontalOffset],a
|
|
add [hl] ;add lineZeroHorizontalOffset
|
|
ldio [$ff43],a
|
|
swap b
|
|
ld a,%00000111 ;random y offset
|
|
and b
|
|
ldio [$ff42],a
|
|
jr .done
|
|
|
|
.takeoffJiggle
|
|
ld a,[jiggleLoc]
|
|
add 17
|
|
ld [jiggleLoc],a
|
|
ld b,a ;store random value in b
|
|
and %11 ;x offset
|
|
ldio [$ff43],a
|
|
swap b
|
|
ld a,%11
|
|
and b
|
|
ld b,a
|
|
ld a,[curPixelOffset_y]
|
|
add b
|
|
cp 8
|
|
jr c,.takeoffVOkay
|
|
|
|
ld a,7
|
|
|
|
.takeoffVOkay
|
|
ldio [$ff42],a
|
|
jr .done
|
|
|
|
.useNormalScreenOffsets
|
|
ld a,[curPixelOffset_x]
|
|
ldio [baseHorizontalOffset],a
|
|
add [hl] ;add lineZeroHorizontalOffset
|
|
ldio [$ff43],a
|
|
ld a,[curPixelOffset_y]
|
|
ldio [$ff42],a
|
|
|
|
;new palette to copy?
|
|
ldio a,[paletteBufferReady]
|
|
or a
|
|
jr z,.afterPaletteCopy
|
|
|
|
ld c,16 ;c is count
|
|
ld hl,fadeCurPalette
|
|
ld a,%10000000
|
|
ld [$ff68],a
|
|
ld [$ff6a],a
|
|
.paletteCopyBG
|
|
ld a,[hl+] ;copy sets of 4 bytes to avoid minute but
|
|
ld [$ff69],a ;killer delays decrementing the counter
|
|
ld a,[hl+]
|
|
ld [$ff69],a
|
|
ld a,[hl+]
|
|
ld [$ff69],a
|
|
ld a,[hl+]
|
|
ld [$ff69],a
|
|
dec c
|
|
jr nz,.paletteCopyBG
|
|
|
|
ld c,16 ;c is count
|
|
.paletteCopyFG
|
|
ld a,[hl+]
|
|
ld [$ff6b],a
|
|
ld a,[hl+]
|
|
ld [$ff6b],a
|
|
ld a,[hl+]
|
|
ld [$ff6b],a
|
|
ld a,[hl+]
|
|
ld [$ff6b],a
|
|
dec c
|
|
jr nz,.paletteCopyFG
|
|
|
|
xor a
|
|
ldio [paletteBufferReady],a
|
|
|
|
.afterPaletteCopy
|
|
|
|
.done
|
|
;update music
|
|
ldio a,[musicEnabled]
|
|
and %10000
|
|
jr z,.doneMusic
|
|
|
|
ld hl,musicNoteCountdown
|
|
dec [hl]
|
|
call z,PlayMusic
|
|
|
|
.doneMusic
|
|
;restore VRAM bank that was in use
|
|
pop af
|
|
ld [$ff00+$4f],a
|
|
|
|
pop hl ;restore all regs from stack
|
|
pop de
|
|
pop bc
|
|
pop af
|
|
reti ;return from interrupt
|
|
|
|
|
|
;---------------------------------------------------------------------
|
|
; Subroutine: OnHBlank
|
|
; Description: Called after every line is drawn.
|
|
;---------------------------------------------------------------------
|
|
OnHBlank::
|
|
push af
|
|
push bc
|
|
push hl
|
|
|
|
OnHBlank_afterPush:
|
|
ldio a,[$ff41] ;get stat register
|
|
bit 2,a ;equal to lyc?
|
|
jp z,FinishHBlankPlayingSample
|
|
|
|
.continue
|
|
ld hl,hblankFlag
|
|
bit 0,[hl] ;turning window on or off?
|
|
jr nz,OnHBlank_turnOffWindow
|
|
|
|
;turn on window
|
|
bit 1,[hl] ;allowed to?
|
|
jr nz,.turnOn
|
|
jp z,FinishHBlankPlayingSample
|
|
.turnOn
|
|
set 0,[hl]
|
|
ldio a,[hblankWinOff]
|
|
ld [$ff45],a ;reset lyc to win off pos
|
|
ld hl,$ff40 ;turn window on
|
|
set 5,[hl]
|
|
|
|
OnHBlank_SetBGColorBlack:
|
|
;set background palette 0, color zero to black
|
|
ld b,0
|
|
ld c,$68
|
|
ld hl,$ff69
|
|
ld a,%10000000 ;specification 0
|
|
ld [c],a
|
|
ld [hl],b
|
|
ld [hl],b
|
|
|
|
;ld a,%10000110 ;white
|
|
;ld [c],a
|
|
;ld [hl],h
|
|
;ld [hl],h
|
|
|
|
ld a,%10001000 ;palette 1
|
|
ld [c],a
|
|
ld [hl],b
|
|
ld [hl],b
|
|
|
|
ld a,%10010000 ;palette 2
|
|
ld [c],a
|
|
ld [hl],b
|
|
ld [hl],b
|
|
|
|
ld a,%10011000 ;palette 3
|
|
ld [c],a
|
|
ld [hl],b
|
|
ld [hl],b
|
|
|
|
ld a,%10100000 ;palette 4
|
|
ld [c],a
|
|
ld [hl],b
|
|
ld [hl],b
|
|
|
|
ld a,%10101000 ;palette 5
|
|
ld [c],a
|
|
ld [hl],b
|
|
ld [hl],b
|
|
|
|
ld a,%10110000 ;palette 6
|
|
ld [c],a
|
|
ld [hl],b
|
|
ld [hl],b
|
|
|
|
ld a,%10111000 ;palette 7
|
|
ld [c],a
|
|
ld [hl],b
|
|
ld [hl],b
|
|
|
|
jp FinishHBlankPlayingSample
|
|
|
|
OnHBlank_turnOffWindow:
|
|
res 0,[hl]
|
|
ldio a,[hblankWinOn]
|
|
ld [$ff45],a ;reset lyc to win on pos
|
|
ld hl,$ff40 ;turn window off
|
|
res 5,[hl]
|
|
|
|
;restore background palette 0, color zero
|
|
push de
|
|
ld c,$68
|
|
ld hl,mapColor
|
|
ld a,[hl+]
|
|
ld d,[hl]
|
|
ld e,a
|
|
ld hl,$ff69
|
|
|
|
HBlankSetBGColorCDEHL_DEPushed:
|
|
ld a,%10000000 ;specification 0
|
|
ld [c],a
|
|
ld [hl],e
|
|
ld [hl],d
|
|
|
|
ld a,%10001000 ;specification 1
|
|
ld [c],a
|
|
ld [hl],e
|
|
ld [hl],d
|
|
|
|
ld a,%10010000 ;specification 2
|
|
ld [c],a
|
|
ld [hl],e
|
|
ld [hl],d
|
|
|
|
ld a,%10011000 ;specification 3
|
|
ld [c],a
|
|
ld [hl],e
|
|
ld [hl],d
|
|
|
|
ld a,%10100000 ;specification 4
|
|
ld [c],a
|
|
ld [hl],e
|
|
ld [hl],d
|
|
|
|
ld a,%10101000 ;specification 5
|
|
ld [c],a
|
|
ld [hl],e
|
|
ld [hl],d
|
|
|
|
ld a,%10110000 ;specification 6
|
|
ld [c],a
|
|
ld [hl],e
|
|
ld [hl],d
|
|
|
|
ld a,%10111000 ;specification 7
|
|
ld [c],a
|
|
ld [hl],e
|
|
ld [hl],d
|
|
|
|
;ld a,%10000110 ;white
|
|
;ld [c],a
|
|
;ld a,[fadeCurPalette+6]
|
|
;ld [hl],a
|
|
;ld a,[fadeCurPalette+7]
|
|
;ld [hl],a
|
|
|
|
pop de
|
|
|
|
.done
|
|
jp FinishHBlankPlayingSample
|
|
|
|
;---------------------------------------------------------------------
|
|
; Subroutine: CinemaOnHBlank
|
|
; Description: Called after every line is drawn.
|
|
;---------------------------------------------------------------------
|
|
CinemaOnHBlank::
|
|
push af
|
|
push bc
|
|
push hl
|
|
|
|
ldio a,[$ff41] ;get stat register
|
|
bit 2,a ;equal to lyc?
|
|
jp z,FinishHBlankPlayingSample
|
|
|
|
.continue
|
|
ld hl,hblankFlag
|
|
bit 0,[hl] ;turning window on or off?
|
|
jr nz,.turnOff
|
|
|
|
;turn on window
|
|
bit 1,[hl] ;allowed to?
|
|
jr nz,.turnOn
|
|
jp z,FinishHBlankPlayingSample
|
|
.turnOn
|
|
set 0,[hl]
|
|
ldio a,[hblankWinOff]
|
|
ld [$ff45],a ;reset lyc to win off pos
|
|
ld hl,$ff40 ;turn window on
|
|
set 5,[hl]
|
|
jp FinishHBlankPlayingSample
|
|
|
|
.turnOff
|
|
res 0,[hl]
|
|
ldio a,[hblankWinOn]
|
|
ld [$ff45],a ;reset lyc to win on pos
|
|
ld hl,$ff40 ;turn window off
|
|
res 5,[hl]
|
|
|
|
.done
|
|
jp FinishHBlankPlayingSample
|
|
|
|
;---------------------------------------------------------------------
|
|
; Subroutine: HOffsetOnHBlank
|
|
; Description: Called after every line is drawn. Sets each line's
|
|
; horizontal offset from horizontalOffset[144]
|
|
;---------------------------------------------------------------------
|
|
HOffsetOnHBlank::
|
|
push af
|
|
push bc
|
|
push hl
|
|
|
|
;save current RAM bank
|
|
ldio a,[$ff70]
|
|
push af
|
|
|
|
ld a,TILEINDEXBANK
|
|
ldio [$ff70],a
|
|
;add to the horizontal offset for next line
|
|
ld c,$44 ;get $ff44
|
|
ld a,[c] ;ypos of refresh (index to array)
|
|
dec c ;c=$43 ($ff43)
|
|
inc a
|
|
ld l,a
|
|
ld h,((horizontalOffset>>8)&$ff)
|
|
ldio a,[baseHorizontalOffset]
|
|
add [hl]
|
|
ld [c],a ;xpos of screen
|
|
|
|
.afterAdjustOffsets
|
|
pop af
|
|
ldio [$ff70],a
|
|
jp OnHBlank_afterPush
|
|
|
|
;---------------------------------------------------------------------
|
|
; Subroutine: SeasonsOnHBlank
|
|
; Description: Called after every line is drawn. Sets color 0 (all
|
|
; bg palettes) to white on line 143 and to brown ($888)
|
|
; on line 39.
|
|
;---------------------------------------------------------------------
|
|
SeasonsOnHBlank::
|
|
push af
|
|
push bc
|
|
push hl
|
|
|
|
ld a,[amShowingDialog]
|
|
or a
|
|
jr nz,.seasonsWindow
|
|
|
|
;jr z,.normal
|
|
;ld a,[hblankFlag]
|
|
;and %11
|
|
;jr nz,.seasonsWindow
|
|
|
|
.normal
|
|
ldio a,[$ff44] ;ypos
|
|
cp 143
|
|
jr z,.toWhite
|
|
cp 39
|
|
jp nz,.seasonsWindow
|
|
|
|
.toBrown
|
|
push de
|
|
ld c,$68
|
|
ld hl,fadeCurPalette+62
|
|
ld a,[hl+]
|
|
ld d,[hl]
|
|
ld e,a
|
|
ld hl,$ff69
|
|
jp HBlankSetBGColorCDEHL_DEPushed
|
|
|
|
.toWhite
|
|
push de
|
|
ld c,$68
|
|
ld hl,mapColor
|
|
ld a,[hl+]
|
|
ld d,[hl]
|
|
ld e,a
|
|
ld hl,$ff69
|
|
jp HBlankSetBGColorCDEHL_DEPushed
|
|
|
|
.seasonsWindow
|
|
ldio a,[$ff41] ;get stat register
|
|
bit 2,a ;equal to lyc?
|
|
jp z,FinishHBlankPlayingSample
|
|
|
|
.continue
|
|
ld hl,hblankFlag
|
|
bit 0,[hl] ;turning window on or off?
|
|
jr nz,.turnOff
|
|
|
|
;turn on window
|
|
bit 1,[hl] ;allowed to?
|
|
jr z,.toBrown
|
|
;jr nz,.turnOn
|
|
;jp FinishHBlankPlayingSample
|
|
.turnOn
|
|
set 0,[hl]
|
|
ldio a,[hblankWinOff]
|
|
ld [$ff45],a ;reset lyc to win off pos
|
|
ld hl,$ff40 ;turn window on
|
|
set 5,[hl]
|
|
jp OnHBlank_SetBGColorBlack
|
|
|
|
.turnOff
|
|
res 0,[hl]
|
|
ldio a,[hblankWinOn]
|
|
ld [$ff45],a ;reset lyc to win on pos
|
|
ld hl,$ff40 ;turn window off
|
|
res 5,[hl]
|
|
|
|
jr .toBrown
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: GetInput
|
|
; Description: Swaps in the link code bank, passes the work along to
|
|
; HandleInput, and swaps in the object bank before
|
|
; ending.
|
|
;---------------------------------------------------------------------
|
|
GetInput::
|
|
LONGCALLNOARGS HandleInput
|
|
|
|
;if the heroes are idle then set both inputs to zero
|
|
ld a,[heroesIdle]
|
|
or a
|
|
ret z
|
|
|
|
xor a
|
|
ld [curJoy0],a
|
|
ld [curJoy1],a
|
|
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: CheckPause
|
|
; Description: Checks for pause button being pressed
|
|
;---------------------------------------------------------------------
|
|
CheckPause:
|
|
ld hl,dialogJoyIndex
|
|
ld a,[hl]
|
|
push af
|
|
|
|
ld a,[heroesPresent]
|
|
cp %11
|
|
jr z,.checkBoth
|
|
|
|
dec a
|
|
ld [hl],a
|
|
ld a,[myJoy]
|
|
bit JOY_START_BIT,a
|
|
jr z,.done
|
|
jr .checkModes
|
|
|
|
.checkBoth
|
|
ld [hl],0
|
|
ld a,[curInput0]
|
|
bit JOY_START_BIT,a
|
|
jr nz,.checkModes
|
|
|
|
ld [hl],1
|
|
ld a,[curInput1]
|
|
bit JOY_START_BIT,a
|
|
jr z,.done
|
|
|
|
.checkModes
|
|
ld a,[amShowingDialog]
|
|
or a
|
|
jr nz,.done
|
|
|
|
ld a,[displayType]
|
|
or a
|
|
jr nz,.done
|
|
|
|
ld a,[amChangingMap]
|
|
or a
|
|
jr nz,.done
|
|
|
|
ld a,[heroesIdle]
|
|
or a
|
|
jr nz,.done
|
|
|
|
;(show as dialog)
|
|
ld a,[dialogSettings]
|
|
push af
|
|
call SetPressBDialog
|
|
call SaveIdle
|
|
|
|
ld de,.afterPause
|
|
call SetDialogSkip
|
|
|
|
ld a,BANK(GeneratePauseMessage)
|
|
ld hl,GeneratePauseMessage
|
|
call LongCallNoArgs
|
|
|
|
ld a,1
|
|
ld [amShowingDialog],a
|
|
ld de,backBuffer+63
|
|
|
|
call ShowDialogAtTopCommon
|
|
call DialogWaitInputZero
|
|
|
|
.wait
|
|
call UpdateObjects
|
|
call RedrawMap
|
|
call SetDialogJoy
|
|
bit JOY_SELECT_BIT,[hl]
|
|
jr nz,.selectPressed
|
|
call CheckDialogContinue
|
|
or a
|
|
jr z,.wait
|
|
|
|
.afterPause
|
|
call ClearDialog
|
|
|
|
call RestoreIdle
|
|
pop af
|
|
ld [dialogSettings],a
|
|
.done
|
|
pop af
|
|
ld [dialogJoyIndex],a
|
|
ret
|
|
|
|
.selectPressed
|
|
call ClearDialog
|
|
call RestoreIdle
|
|
pop af
|
|
ld [dialogSettings],a
|
|
pop af
|
|
ld [dialogJoyIndex],a
|
|
|
|
ld a,EXIT_D
|
|
ld [hero0_enterLevelFacing],a
|
|
ld [hero1_enterLevelFacing],a
|
|
|
|
ld hl,respawnMap
|
|
ld a,[hl+]
|
|
ld [curLevelIndex],a
|
|
ld a,[hl+]
|
|
ld [curLevelIndex+1],a
|
|
ld a,1
|
|
ld [timeToChangeLevel],a
|
|
ret
|
|
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: UpdateObjects
|
|
; Description: Waits for a vertical blank and then updates the
|
|
; objects
|
|
;---------------------------------------------------------------------
|
|
MainLoopUpdateObjects:
|
|
call VWait ;wait for a vertical blank
|
|
ld a,1
|
|
ld [checkInputInMainLoop],a
|
|
call GetInput
|
|
call CheckPause
|
|
xor a
|
|
ld [checkInputInMainLoop],a
|
|
jr .doneWithInput
|
|
|
|
.vwait call VWait ;wait for a vertical blank
|
|
|
|
.doneWithInput
|
|
call CheckSpecialFX
|
|
|
|
;wait for previous frame to be drawn
|
|
ldio a,[backBufferReady]
|
|
or a
|
|
jp nz,.vwait
|
|
jr UpdateObjectsCommon
|
|
|
|
UpdateObjects::
|
|
call VWait ;wait for a vertical blank
|
|
call GetInput
|
|
|
|
.vwait call VWait ;wait for a vertical blank
|
|
|
|
.doneWithInput
|
|
call CheckSpecialFX
|
|
|
|
;wait for previous frame to be drawn
|
|
ldio a,[backBufferReady]
|
|
or a
|
|
jp nz,.vwait
|
|
|
|
UpdateObjectsCommon:
|
|
ld a,[displayType]
|
|
or a
|
|
ret nz ;done if cinema type
|
|
|
|
;check each object
|
|
ld b,METHOD_CHECK
|
|
ld a,[iterateNumObjects]
|
|
ld c,a
|
|
call IterateMaxObjects
|
|
|
|
;update the timers that hero/hero bullets base moves off of
|
|
call UpdateHeroTimers
|
|
|
|
;make sure we check the hero & hero's bullets each time
|
|
ld hl,hero0_index
|
|
call .checkHeroObjects
|
|
ld hl,hero1_index
|
|
call .checkHeroObjects
|
|
|
|
ret
|
|
|
|
.checkHeroObjects
|
|
ld a,[hl+] ;heroX_index
|
|
or a
|
|
ret z ;this hero doesn't exist
|
|
|
|
ld c,a
|
|
call GetFirst
|
|
ld b,METHOD_CHECK
|
|
;ld e,[hl] ;heroX_objectL
|
|
;inc hl
|
|
;ld d,[hl] ;heroX_objectH
|
|
;inc hl
|
|
call CallMethod
|
|
|
|
inc hl
|
|
inc hl
|
|
|
|
ld a,[hl] ;heroX_bulletIndex
|
|
ld c,a
|
|
call GetFirst
|
|
call IterateList
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: RedrawMap
|
|
; Description: Redraws the map for the next vblank
|
|
;---------------------------------------------------------------------
|
|
RedrawMap::
|
|
call RestrictCameraToBounds
|
|
call ScrollToCamera
|
|
|
|
call DrawMapToBackBuffer
|
|
call UpdateEnvEffect
|
|
|
|
ld a,1
|
|
ldio [backBufferReady],a ;signal we're ready for DMA
|
|
|
|
ret
|
|
|
|
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: HandleRemoteInput
|
|
; Arguments: a - remoteInput
|
|
; Returns: a - remoteInput
|
|
; zflag - set if must repeat
|
|
; Alters: af
|
|
;---------------------------------------------------------------------
|
|
HandleRemoteInput::
|
|
bit 7,a ;test bit 7
|
|
ret z ;got the BCB
|
|
|
|
;handle the link command code we received.
|
|
call HandleLCC
|
|
|
|
;indicate we need to try exchanging our control bytes again
|
|
ld a,1
|
|
or a ;don't set zero flag
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: HandleLCC
|
|
; Arguments: a - value of the Link Command Code.
|
|
; Returns: nothing.
|
|
; Alters: af
|
|
;---------------------------------------------------------------------
|
|
HandleLCC:
|
|
.checkLGETGAMESTATE
|
|
cp LGETGAMESTATE
|
|
jr nz,.checkLGETMAPINDEX
|
|
|
|
;LGETGAMESTATE
|
|
LONGCALLNOARGS TransmitGameState
|
|
ret
|
|
|
|
.checkLGETMAPINDEX
|
|
cp LGETMAPINDEX
|
|
jr nz,.checkLUPDATESTATE
|
|
|
|
;LGETMAPINDEX
|
|
ld a,[displayType]
|
|
or a
|
|
jr nz,.returnDifferentMapCode ;cinema type
|
|
ld a,[amChangingMap]
|
|
or a
|
|
jr nz,.returnWaitCode
|
|
ld a,[canJoinMap]
|
|
;or a
|
|
;jr z,.returnWaitCode
|
|
cp 2
|
|
jr z,.returnDifferentMapCode ;do this map independently
|
|
|
|
ld a,[curLevelStateIndex]
|
|
jr .returnMapIndex
|
|
.returnWaitCode
|
|
ld a,$ff
|
|
jr .returnMapIndex
|
|
.returnDifferentMapCode
|
|
ld a,$fe
|
|
.returnMapIndex
|
|
call TransmitByte
|
|
ret
|
|
|
|
.checkLUPDATESTATE
|
|
cp LUPDATESTATE
|
|
jr nz,.checkLUPDATEHERO
|
|
|
|
;LUPDATESTATE
|
|
push hl
|
|
ld a,LEVELSTATEBANK
|
|
ld [$ff70],a
|
|
call ReceiveByte
|
|
ld h,((levelState>>8) & $ff)
|
|
ld l,a
|
|
call ReceiveByte
|
|
ld [hl],a
|
|
pop hl
|
|
|
|
ret
|
|
|
|
.checkLUPDATEHERO
|
|
cp LUPDATEHERO
|
|
jr nz,.checkLYANKPLAYER
|
|
|
|
;LUPDATEHERO
|
|
call ReceiveByte
|
|
ld [heroesUsed],a
|
|
ret
|
|
|
|
.checkLYANKPLAYER
|
|
cp LYANKPLAYER
|
|
jr nz,.checkLRESYNCHRONIZE
|
|
|
|
;LYANKPLAYER
|
|
;get exit direction
|
|
call ReceiveByte
|
|
ld [hero0_enterLevelFacing],a
|
|
|
|
;get new map coordinates
|
|
push bc
|
|
push af
|
|
call ReceiveByte
|
|
ld c,a
|
|
call ReceiveByte
|
|
ld b,a
|
|
ld a,[hero0_enterLevelFacing]
|
|
and 7
|
|
ld [hero0_enterLevelFacing],a
|
|
ld [hero1_enterLevelFacing],a
|
|
pop af
|
|
cp 8
|
|
jr nc,.changeMap
|
|
|
|
ld a,[curLevelIndex]
|
|
cp c
|
|
jr nz,.changeMap
|
|
ld a,[curLevelIndex+1]
|
|
cp b
|
|
jr z,.noChangeMap
|
|
|
|
.changeMap
|
|
ld a,c
|
|
ld [curLevelIndex],a ;map index lobyte
|
|
ld a,b
|
|
ld [curLevelIndex+1],a ;map index lobyte
|
|
ld a,1
|
|
ld [timeToChangeLevel],a
|
|
|
|
.noChangeMap ;already on this map
|
|
pop bc
|
|
ret
|
|
|
|
.checkLRESYNCHRONIZE
|
|
cp LRESYNCHRONIZE
|
|
jr nz,.checkLGETRANDOMSEED
|
|
|
|
LONGCALLNOARGS GuestContinueSynchronization
|
|
ret
|
|
|
|
.checkLGETRANDOMSEED
|
|
cp LGETRANDOMSEED
|
|
jr nz,.checkLTERMINATE
|
|
|
|
ldio a,[randomLoc]
|
|
call TransmitByte
|
|
ret
|
|
|
|
.checkLTERMINATE
|
|
cp LTERMINATE
|
|
jr nz,.checkLSYNCHRONIZE
|
|
|
|
ld a,[amLinkMaster]
|
|
cp 1
|
|
jr z,.terminateMaster
|
|
|
|
;terminate slave
|
|
rst $00
|
|
.terminateMaster
|
|
ld a,$fe
|
|
ld [amLinkMaster],a
|
|
ret
|
|
|
|
.checkLSYNCHRONIZE
|
|
cp LSYNCHRONIZE
|
|
jr nz,.checkLLOCKHEROES
|
|
|
|
;LSYNCHRONIZE
|
|
;am I ready to synchronize?
|
|
ld a,[checkInputInMainLoop]
|
|
or a
|
|
jr z,.notReadyToSync
|
|
ld a,[amShowingDialog]
|
|
or a
|
|
jr nz,.readyIfCinema
|
|
ld a,[canJoinMap]
|
|
or a
|
|
jr z,.notReadyToSync
|
|
jr .readyToSynchronize
|
|
|
|
.readyIfCinema
|
|
ld a,[displayType]
|
|
or a
|
|
jr nz,.readyToSynchronize
|
|
|
|
;not ready
|
|
.notReadyToSync
|
|
ld a,LSYNCHWAIT
|
|
call TransmitByte
|
|
ret
|
|
|
|
.readyToSynchronize
|
|
ld a,LSYNCHREADY
|
|
call TransmitByte
|
|
LONGCALLNOARGS HostSynchronize
|
|
ret
|
|
|
|
.checkLLOCKHEROES
|
|
cp LLOCKHEROES
|
|
jr nz,.checkLNOLINK
|
|
|
|
call ReceiveByte ;receive lock or unlock from remote
|
|
ld [heroesLocked],a
|
|
ret
|
|
|
|
.checkLNOLINK
|
|
cp LNOLINK
|
|
jr nz,.checkLLINKTEST
|
|
ret
|
|
|
|
.checkLLINKTEST
|
|
cp LLINKTEST
|
|
jr nz,.checkLCHANGEAPPXMAP
|
|
|
|
LONGCALLNOARGS LinkTest
|
|
ret
|
|
|
|
.checkLCHANGEAPPXMAP
|
|
cp LCHANGEAPPXMAP
|
|
jr nz,.checkLADDINVITEM
|
|
|
|
LONGCALLNOARGS NewAppxLocation
|
|
ret
|
|
|
|
.checkLADDINVITEM
|
|
cp LADDINVITEM
|
|
jr nz,.checkLREMINVITEM
|
|
|
|
push bc
|
|
call ReceiveByte ;get bc (inventory item)
|
|
ld c,a
|
|
call ReceiveByte
|
|
ld b,a
|
|
|
|
;duplicate code also in Map.asm
|
|
push hl
|
|
call PointHLToInventory
|
|
or c
|
|
ld [hl],a
|
|
pop hl
|
|
pop bc
|
|
ret
|
|
|
|
.checkLREMINVITEM
|
|
cp LREMINVITEM
|
|
jr nz,.checkLUPDATEMEMORY
|
|
|
|
;duplicate code also in Map.asm
|
|
push bc
|
|
call ReceiveByte ;get bc (inventory item)
|
|
ld c,a
|
|
call ReceiveByte
|
|
ld b,a
|
|
|
|
;duplicate code also in Map.asm
|
|
push hl
|
|
call PointHLToInventory
|
|
xor $ff
|
|
or c
|
|
xor $ff
|
|
ld [hl],a
|
|
pop hl
|
|
pop bc
|
|
ret
|
|
|
|
.checkLUPDATEMEMORY
|
|
cp LUPDATEMEMORY
|
|
jr nz,.unknown
|
|
|
|
push hl
|
|
call ReceiveByte ;memory bank of data
|
|
ldio [$ff70],a
|
|
call ReceiveByte ;address
|
|
ld l,a
|
|
call ReceiveByte
|
|
ld h,a
|
|
call ReceiveByte ;new value
|
|
ld [hl],a
|
|
pop hl
|
|
ret
|
|
|
|
.unknown
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routines: LLTransmitByte
|
|
; Arguments: a - byte to send
|
|
; [amLinkMaster] - should be set to 1 or 0
|
|
; Returns: Nothing.
|
|
; Alters: af
|
|
; Note: DON'T CALL THIS DIRECTLY. It should only be called
|
|
; via TransmitByte and ReceiveByte.
|
|
; Description: Low-level routine to transmit a byte via the link
|
|
; cable.
|
|
;---------------------------------------------------------------------
|
|
LLTransmitByte:
|
|
di ;be sure we're not interrupted
|
|
ldio [$ff01],a ;store the data to transfer
|
|
ld a,INTCLK
|
|
ldio [$ff02],a ;let's do it
|
|
.waitForCompletion
|
|
ldio a,[$ff02] ;12
|
|
and $80 ; 8
|
|
jr nz,.waitForCompletion ; 8
|
|
|
|
;go into slave mode to await next byte
|
|
ld a,EXTCLK ; 8
|
|
ldio [$ff02],a ;12 TOTAL = 48
|
|
|
|
;clear pending interrupts
|
|
xor a
|
|
ei
|
|
ld [$ff0f],a
|
|
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routines: LLReceiveByte
|
|
; Arguments: [amLinkMaster] - should be set to 1 or 0
|
|
; Returns: a - byte received from linked GameBoy.
|
|
; Alters: af
|
|
; Note: DON'T CALL THIS DIRECTLY. It should only be called
|
|
; via TransmitByte and ReceiveByte.
|
|
; Description: Low-level routine to receive a byte via the link
|
|
; cable. If no signal within nine seconds aborts link
|
|
; connection and:
|
|
; Master - continues game as slaveless master ($fe).
|
|
; Slave - restarts game.
|
|
;---------------------------------------------------------------------
|
|
LLReceiveByte:
|
|
push bc
|
|
push de
|
|
|
|
ld de,$0C00 ;abort timer counts down $C00 * 256 times
|
|
ld c,0 ;(about 1.25 sec per $100)
|
|
.waitForCompletion
|
|
ldio a,[$ff02]
|
|
and $80
|
|
jr z,.gotValue
|
|
|
|
;update our abort timer
|
|
dec c
|
|
jr nz,.waitForCompletion
|
|
|
|
dec de
|
|
xor a
|
|
cp d
|
|
jr nz,.waitForCompletion
|
|
cp e
|
|
jr nz,.waitForCompletion
|
|
jr .linkLost
|
|
|
|
.gotValue
|
|
ldio a,[$ff01] ;return the value we received
|
|
|
|
;kill some time before we let ourselves change to master
|
|
;to give the current master time to change to slave
|
|
push af
|
|
.killOuter
|
|
ld a,6
|
|
.killTime
|
|
dec a ; 4
|
|
jr nz,.killTime ; 4/8 TOTAL = 8, *6=48
|
|
pop af
|
|
jr .done
|
|
|
|
.linkLost
|
|
ld a,[amLinkMaster]
|
|
or a
|
|
jr z,.amSlave
|
|
|
|
cp 1
|
|
jr z,.amMaster
|
|
|
|
;link already lost, restore stack & jump to bail-out address
|
|
;if not 0
|
|
ld a,[linkBailOut] ;get bail-out address
|
|
ld e,a
|
|
ld a,[linkBailOut+1]
|
|
ld d,a
|
|
xor a
|
|
cp d
|
|
jr nz,.bail
|
|
cp e
|
|
jr nz,.bail
|
|
|
|
;null bail address; just quit
|
|
jr .done
|
|
|
|
.bail
|
|
;restore the stack before jumping to the bail address
|
|
ld a,[linkBailOut+2]
|
|
ld l,a
|
|
ld a,[linkBailOut+3]
|
|
ld h,a
|
|
ld sp,hl
|
|
push de
|
|
ret
|
|
|
|
.amMaster
|
|
ld a,$fe
|
|
ld [amLinkMaster],a
|
|
|
|
call RemoveRemoteHero
|
|
jr .done
|
|
|
|
.amSlave
|
|
rst $00 ;restart the game
|
|
|
|
.done
|
|
pop de
|
|
pop bc
|
|
ret
|
|
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: TransmitByte
|
|
; Argument: a - byte to send
|
|
; Returns: Nothing.
|
|
; Alters: af
|
|
; Description: Transmits a byte via the link cable to a remote GBC.
|
|
;---------------------------------------------------------------------
|
|
TransmitByte::
|
|
push bc
|
|
ld b,a
|
|
|
|
;If I was the last one to transmit, receive a byte as an
|
|
;acknowledgement.
|
|
ld a,[lastLinkAction]
|
|
or a
|
|
jr z,.afterOrientStream
|
|
|
|
call LLReceiveByte
|
|
|
|
.afterOrientStream
|
|
ld a,1 ;our action this time is to transmit
|
|
ld [lastLinkAction],a
|
|
|
|
ld a,b
|
|
call LLTransmitByte
|
|
|
|
.done
|
|
pop bc
|
|
ret
|
|
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: ReceiveByte
|
|
; Arguments: None.
|
|
; Returns: a - byte received.
|
|
; Alters: af
|
|
; Description: Receives a byte from a remote machine.
|
|
;---------------------------------------------------------------------
|
|
ReceiveByte::
|
|
;If necessary we'll transmit a value to avoid receiving twice
|
|
;in a row.
|
|
ld a,[lastLinkAction]
|
|
or a
|
|
jr nz,.afterOrientStream
|
|
|
|
ld a,1
|
|
call LLTransmitByte
|
|
|
|
.afterOrientStream
|
|
xor a ;our action this time is to receive
|
|
ld [lastLinkAction],a
|
|
|
|
call LLReceiveByte
|
|
ret
|
|
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: ExchangeByte
|
|
; Argument: a - byte to send
|
|
; Returns: a - byte received in return
|
|
; Alters: af
|
|
; Description: Uses value of [amLinkMaster] (Master should be $01 and
|
|
; Slave should be $00) to determine sequencing of
|
|
; TransmitByte and ReceiveByte.
|
|
;---------------------------------------------------------------------
|
|
ExchangeByte::
|
|
push bc
|
|
ld b,a
|
|
|
|
ld a,[amLinkMaster]
|
|
or a
|
|
jr z,.slaveExchange
|
|
|
|
;masterExchange
|
|
ld a,b
|
|
call TransmitByte
|
|
call ReceiveByte
|
|
jr .done
|
|
|
|
.slaveExchange
|
|
call ReceiveByte
|
|
ld c,a
|
|
ld a,b
|
|
call TransmitByte
|
|
ld a,c
|
|
|
|
.done
|
|
pop bc
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: TransmitData
|
|
; Arguments: a - RAM bank to switch to (may/may not make a diff)
|
|
; bc - number of bytes to transmit
|
|
; hl - starting address of data to transmit
|
|
; Returns: Nothing.
|
|
; Alters: af
|
|
;---------------------------------------------------------------------
|
|
TransmitData::
|
|
push bc
|
|
push hl
|
|
|
|
ldio [$ff70],a
|
|
|
|
.loop ld a,[hl+]
|
|
call TransmitByte
|
|
dec bc
|
|
xor a
|
|
cp b
|
|
jr nz,.loop
|
|
cp c
|
|
jr nz,.loop
|
|
|
|
pop hl
|
|
pop bc
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: ReceiveData
|
|
; Arguments: a - RAM bank to switch to (may/may not make a diff)
|
|
; bc - number of bytes to receive
|
|
; hl - starting address to store data
|
|
; Returns: Nothing.
|
|
; Alters: af
|
|
;---------------------------------------------------------------------
|
|
ReceiveData::
|
|
push bc
|
|
push hl
|
|
|
|
ldio [$ff70],a ;change RAM bank
|
|
|
|
.loop call ReceiveByte
|
|
ld [hl+],a
|
|
dec bc
|
|
xor a
|
|
cp b
|
|
jr nz,.loop
|
|
cp c
|
|
jr nz,.loop
|
|
|
|
pop hl
|
|
pop bc
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: TransmitCompressedData
|
|
; Arguments: a - RAM bank to switch to (may/may not make a diff)
|
|
; bc - number of bytes to transmit
|
|
; hl - starting address of data to transmit
|
|
; Returns: Nothing.
|
|
; Alters: af
|
|
; Description: Packs bytes 8:1 into the backBuffer by combining
|
|
; bit[0] from every eight bytes into one byte. The
|
|
; left-most bit will be from byte[0] and the right-most
|
|
; from byte[7].
|
|
;---------------------------------------------------------------------
|
|
TransmitCompressedData::
|
|
push bc
|
|
push de
|
|
push hl
|
|
|
|
ldio [$ff70],a
|
|
|
|
;divide len by 8 (>>3)
|
|
srl b
|
|
rr c
|
|
srl b
|
|
rr c
|
|
srl b
|
|
rr c
|
|
|
|
push bc ;save length
|
|
|
|
;----Compress the data into backBuffer------------------------
|
|
ld de,backBuffer ;compression buffer
|
|
.nextByte
|
|
push de ;push destination
|
|
ld de,8 ;d is compressed (0), e is times to loop
|
|
|
|
.nextBit
|
|
ld a,[hl+] ;get the next byte
|
|
rrca ;shift out bit[0] into the carry flag
|
|
rl d ;rotate onto right side of result
|
|
dec e
|
|
jr nz,.nextBit
|
|
|
|
ld a,d ;a has compressed byte
|
|
pop de ;pop destination
|
|
ld [de],a ;store the compressed byte
|
|
inc de
|
|
|
|
dec bc
|
|
xor a
|
|
cp b
|
|
jr nz,.nextByte
|
|
cp c
|
|
jr nz,.nextByte
|
|
|
|
pop bc ;done with compression, retrieve len
|
|
|
|
ld hl,backBuffer ;transmit the compressed data
|
|
xor a
|
|
call TransmitData
|
|
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: ReceiveCompressedData
|
|
; Arguments: a - RAM bank to switch to (may/may not make a diff)
|
|
; bc - number of bytes to receive
|
|
; hl - starting address of data to receive
|
|
; Returns: Nothing.
|
|
; Alters: af
|
|
; Description: Receives numBytes/8 into the backBuffer, then unpacks
|
|
; each byte 1:8 to the data address.
|
|
;---------------------------------------------------------------------
|
|
ReceiveCompressedData::
|
|
push bc
|
|
push de
|
|
push hl
|
|
|
|
push af ;save original RAM bank
|
|
push hl ;save original dest
|
|
|
|
;----Calculate numBytes/8 (>>3)-------------------------------
|
|
srl b
|
|
rr c
|
|
srl b
|
|
rr c
|
|
srl b
|
|
rr c
|
|
|
|
ld hl,backBuffer ;receive the compressed data
|
|
xor a
|
|
call ReceiveData
|
|
|
|
pop hl ;retrieve original dest
|
|
pop af ;retrieve original RAM bank
|
|
ldio [$ff70],a
|
|
|
|
;----Decompress the data into the destination buffer----------
|
|
ld de,backBuffer ;decompression buffer
|
|
.nextByte
|
|
ld a,[de] ;get a byte from the buffer
|
|
inc de
|
|
push de ;push source
|
|
ld d,a ;store compressed byte in d
|
|
ld e,8 ;e is times to loop
|
|
|
|
.nextBit
|
|
xor a
|
|
rl d ;get a bit off left side of compressed
|
|
rla ;shift onto right side of uncompressed
|
|
ld [hl+],a ;store in final destination
|
|
dec e
|
|
jr nz,.nextBit
|
|
|
|
pop de ;pop source
|
|
|
|
dec bc
|
|
xor a
|
|
cp b
|
|
jr nz,.nextByte
|
|
cp c
|
|
jr nz,.nextByte
|
|
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: CheckSimultaneousLCC
|
|
; Argument: a - byte received from link exchange
|
|
; Returns: not z flag - this machine must repeat its command
|
|
; z flag set - everything is okay
|
|
; Alters: af
|
|
; Description: Called after one machine has sent the first byte of
|
|
; a Link Command Code. If the remote machine
|
|
; coincidentally sent its own LCC at the same time then
|
|
; the Slave must delay its own LCC until the Master's
|
|
; LCC has been handled.
|
|
;---------------------------------------------------------------------
|
|
CheckSimultaneousLCC::
|
|
bit 7,a ;see if we got a LCC or a BCB.
|
|
ret z ;Got a BCB, everything's cool.
|
|
|
|
;Got a LCC. If I'm the Master then the other machine must
|
|
;yield to me so everything's still cool.
|
|
push af
|
|
ld a,[amLinkMaster]
|
|
or a
|
|
jr z,.amSlave
|
|
pop af
|
|
xor a
|
|
ret
|
|
|
|
.amSlave
|
|
;I must yield to the Master. Handle his request and then
|
|
;return a value indicating I must repeat my own request.
|
|
pop af
|
|
call HandleLCC
|
|
ld a,1
|
|
or a
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: YankRemotePlayer
|
|
; Arguments: a - exit to set to (>7 means &7 and don't check
|
|
; to see if you're on the map)
|
|
;
|
|
; hl - map to set to in BCD (e.g. $0205)
|
|
; Returns: Nothing.
|
|
; Alters: af
|
|
; Description: Interrupts whatever the other player is doing and
|
|
; sets him to come to the specified map. Also sets
|
|
; the join/respawn map to the map to set to.
|
|
;---------------------------------------------------------------------
|
|
YankRemotePlayer::
|
|
push af
|
|
call UpdateState
|
|
call SetJoinMap
|
|
call SetRespawnMap
|
|
pop af
|
|
|
|
;verify link established
|
|
push hl
|
|
ld hl,amLinkMaster
|
|
bit 7,[hl]
|
|
pop hl
|
|
ret nz
|
|
|
|
push af
|
|
push hl
|
|
ld a,2 ;two additional things on stack
|
|
ld hl,.linkBailAddress
|
|
call SetLinkBailOutAddress
|
|
|
|
pop hl
|
|
|
|
.sendYank
|
|
ld a,LYANKPLAYER
|
|
call ExchangeByte
|
|
call CheckSimultaneousLCC
|
|
jr nz,.sendYank
|
|
pop af
|
|
|
|
;remote machine is listening; send map coords
|
|
call TransmitByte ;exit dir
|
|
ld a,l
|
|
call TransmitByte
|
|
ld a,h
|
|
call TransmitByte
|
|
.linkBailAddress
|
|
push hl
|
|
ld hl,0
|
|
xor a
|
|
call SetLinkBailOutAddress
|
|
pop hl
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: RemoveRemoteHero
|
|
; Arguments: None.
|
|
; Returns: Nothing.
|
|
; Alters: af
|
|
; Description: Deletes the remote hero and removes traces of its
|
|
; presence.
|
|
;---------------------------------------------------------------------
|
|
RemoveRemoteHero::
|
|
push bc
|
|
push de
|
|
push hl
|
|
|
|
;determine which is the remote hero
|
|
ld a,[amLinkMaster]
|
|
or a
|
|
jr z,.amSlave
|
|
|
|
.amMaster
|
|
ld hl,hero1_index
|
|
jr .determinedRemoteHero
|
|
|
|
.amSlave
|
|
ld hl,hero0_index
|
|
|
|
.determinedRemoteHero
|
|
;remove remote hero from map if present
|
|
ld a,[hl] ;heroX_index
|
|
or a
|
|
jr z,.done ;not here
|
|
|
|
;save the current ROM & switch in the object ROM
|
|
ldio a,[curROMBank]
|
|
push af
|
|
ld a,CLASSROM
|
|
call SetActiveROM
|
|
|
|
;----remove this one's heroesPresent flag----
|
|
ld a,[hl] ;heroX_index
|
|
push af
|
|
|
|
ld a,l
|
|
and 16
|
|
IF HERODATASIZE!=16
|
|
fix this
|
|
ENDC
|
|
swap a ;a is now 1 or 0
|
|
add 1 ;now 2 or 1
|
|
xor $ff ;now ~2 or ~1
|
|
ld b,a
|
|
ld a,[heroesPresent]
|
|
and b
|
|
ld [heroesPresent],a
|
|
|
|
;push hl
|
|
;ld de,(HERODATA_TYPE - HERODATA_INDEX)
|
|
;add hl,de
|
|
;ld a,[hl] ;heroX_type
|
|
;xor $ff
|
|
;ld b,a
|
|
;ld a,[heroesPresent]
|
|
;and b
|
|
;ld [heroesPresent],a
|
|
;pop hl
|
|
xor a
|
|
ld [hl],a ;heroX_index
|
|
pop af
|
|
|
|
ld c,a
|
|
call GetFirst
|
|
ld b,METHOD_DIE
|
|
call CallMethod
|
|
|
|
;restore the old ROM
|
|
pop af
|
|
call SetActiveROM
|
|
|
|
.done
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: DebugMesg
|
|
; Argument: hl - pointer to a gtx structure
|
|
; Returns: Nothing.
|
|
; Alters: af
|
|
; Description: Displays the given gtx string in a window for a
|
|
; brief period.
|
|
;---------------------------------------------------------------------
|
|
DebugMesg::
|
|
push bc
|
|
push de
|
|
push hl
|
|
|
|
ldio a,[$ff40]
|
|
and %10000000
|
|
jr z,.done
|
|
|
|
ld d,h
|
|
ld e,l
|
|
xor a
|
|
|
|
;-------Show Dialog At Top-------------------
|
|
push af
|
|
push bc
|
|
push de
|
|
push hl
|
|
|
|
ld b,0 ;lines to skip at top
|
|
ld a,[curROMBank]
|
|
call ShowDialogCommon
|
|
|
|
xor a
|
|
ldh [$ff4a], a ;set window y position
|
|
|
|
ld a,[de] ;number of lines
|
|
rlca ;times 8 = pixels for window
|
|
rlca
|
|
rlca
|
|
add 7
|
|
ld [hblankWinOff],a
|
|
|
|
ld a,143
|
|
ld [hblankWinOn],a
|
|
|
|
ld a,[hblankFlag]
|
|
bit 1,a
|
|
jr nz,.afterSetLYC
|
|
|
|
ld a,143
|
|
ld [$ff45],a ;lyc
|
|
ld a,[hblankFlag]
|
|
|
|
.afterSetLYC
|
|
or %10 ;allow window to show
|
|
ld [hblankFlag],a
|
|
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
pop af
|
|
;-------Show Dialog At Top-------------------
|
|
|
|
ld bc,16384
|
|
call TimerDelay
|
|
call ClearDialog
|
|
|
|
.done
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: DebugVal
|
|
; Argument: a - byte to show as a hex value
|
|
; Returns: Nothing.
|
|
; Alters: Nothing.
|
|
; Description: Displays the given value in hex using a Dialog
|
|
; window for a brief period. Game must be on.
|
|
;---------------------------------------------------------------------
|
|
DebugVal::
|
|
push af
|
|
push bc
|
|
push de
|
|
push hl
|
|
|
|
ld b,a ;save byte
|
|
|
|
ldio a,[$ff40]
|
|
and %10000000
|
|
jr z,.done
|
|
|
|
ld hl,$c200
|
|
ld [hl],1
|
|
inc hl
|
|
ld [hl],1
|
|
inc hl
|
|
ld [hl],2
|
|
inc hl
|
|
ld a,b
|
|
ld c,0
|
|
swap a
|
|
and $0f
|
|
add 200
|
|
ld [hl+],a
|
|
ld a,b
|
|
and $0f
|
|
add 200
|
|
ld [hl+],a
|
|
ld de,$c200
|
|
xor a
|
|
|
|
;-------Show Dialog At Top-------------------
|
|
push af
|
|
push bc
|
|
push de
|
|
push hl
|
|
|
|
ld b,0 ;lines to skip at top
|
|
ld a,[curROMBank]
|
|
call ShowDialogCommon
|
|
|
|
xor a
|
|
ldh [$ff4a], a ;set window y position
|
|
|
|
ld a,[de] ;number of lines
|
|
rlca ;times 8 = pixels for window
|
|
rlca
|
|
rlca
|
|
add 7
|
|
ld [hblankWinOff],a
|
|
|
|
ld a,143
|
|
ld [hblankWinOn],a
|
|
|
|
ld a,[hblankFlag]
|
|
bit 1,a
|
|
jr nz,.afterSetLYC
|
|
|
|
ld a,143
|
|
ld [$ff45],a ;lyc
|
|
ld a,[hblankFlag]
|
|
|
|
.afterSetLYC
|
|
or %10 ;allow window to show
|
|
ld [hblankFlag],a
|
|
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
pop af
|
|
;-------Show Dialog At Top-------------------
|
|
|
|
ld bc,8192 ;16384
|
|
call TimerDelay
|
|
call ClearDialog
|
|
|
|
.done
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
pop af
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: TimerDelay
|
|
; Argument: bc - number of 16384's of a second to delay
|
|
; Alters: af
|
|
;---------------------------------------------------------------------
|
|
TimerDelay::
|
|
push bc
|
|
push de
|
|
push hl
|
|
|
|
ld hl,$ff04
|
|
ld d,0 ;prev value of time
|
|
ld [hl],0
|
|
.wait
|
|
ld a,[hl]
|
|
ld e,a
|
|
xor d ;equal to prev value?
|
|
jr z,.wait
|
|
|
|
ld d,e
|
|
dec bc
|
|
xor a
|
|
cp b
|
|
jr nz,.wait
|
|
cp c
|
|
jr nz,.wait
|
|
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
ret
|
|
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: SetDialogSkip
|
|
; SetDialogForward
|
|
; Arguments: de - position to skip or fast forward to
|
|
; Alters: af
|
|
; Description: Saves the stack pointer (minus the space that this
|
|
; function call is taking up) and sets the go-to
|
|
; address for fast forwarding (any button pressed)
|
|
; or skipping (start button pressed).
|
|
;---------------------------------------------------------------------
|
|
SetDialogSkip::
|
|
push hl
|
|
ld hl,sp+4 ;stack ptr pos once returned from this fn
|
|
ld a,e
|
|
ld [levelCheckSkip+2],a ;set skip forward addr
|
|
ld a,d
|
|
ld [levelCheckSkip+3],a
|
|
jr SetDialogCommon
|
|
|
|
SetDialogForward::
|
|
push hl
|
|
ld hl,sp+4 ;stack ptr pos once returned from this fn
|
|
ld a,e ;set fast forward addr
|
|
ld [levelCheckSkip],a
|
|
ld a,d
|
|
ld [levelCheckSkip+1],a
|
|
jr SetDialogCommon
|
|
|
|
SetSkipStackPos::
|
|
push hl
|
|
ld hl,sp+4 ;stack ptr pos once returned from this fn
|
|
|
|
SetDialogCommon:
|
|
ld a,l
|
|
ld [levelCheckStackPos],a
|
|
ld a,h
|
|
ld [levelCheckStackPos+1],a
|
|
pop hl
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: ClearDialogSkipForward
|
|
; Arguments: None.
|
|
; Alters: af,hl
|
|
;---------------------------------------------------------------------
|
|
ClearDialogSkipForward::
|
|
call ClearDialog
|
|
call ClearSkipForward
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: ClearSkipForward
|
|
; Arguments: None.
|
|
; Alters: af,hl
|
|
;---------------------------------------------------------------------
|
|
ClearSkipForward::
|
|
ld de,0
|
|
call SetDialogSkip
|
|
call SetDialogForward
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: SetRespawnMap
|
|
; Arguments: hl - map to go to after hero dies
|
|
; Returns: Nothing.
|
|
; Alters: af
|
|
;---------------------------------------------------------------------
|
|
SetRespawnMap::
|
|
ld a,l
|
|
ld [respawnMap],a
|
|
ld a,h
|
|
ld [respawnMap+1],a
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: SetJoinMap
|
|
; Arguments: hl - map to join from 2nd player title screen
|
|
; Returns: Nothing.
|
|
; Alters: af
|
|
;---------------------------------------------------------------------
|
|
SetJoinMap::
|
|
ld a,l
|
|
ld [joinMap],a
|
|
ld a,h
|
|
ld [joinMap+1],a
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: SetLinkBailOutAddress
|
|
; Arguments: a - number of additional words to add to stack
|
|
; pointer
|
|
; hl - saves stack pointer and bailout address into
|
|
; [linkBailOut0...3].
|
|
; Returns: Nothing.
|
|
; Alters: af
|
|
;---------------------------------------------------------------------
|
|
SetLinkBailOutAddress::
|
|
push hl
|
|
push af
|
|
;save bail out address
|
|
ld a,l
|
|
ld [linkBailOut],a
|
|
ld a,h
|
|
ld [linkBailOut+1],a
|
|
|
|
;save stack pointer (plus a*2 + 6 for things pushed on stack)
|
|
ld hl,sp+6
|
|
pop af
|
|
or a
|
|
jr z,.afterAdjustStackPointer
|
|
|
|
.adjustStackPointer
|
|
inc hl
|
|
inc hl
|
|
dec a
|
|
jr nz,.adjustStackPointer
|
|
|
|
.afterAdjustStackPointer
|
|
ld a,l
|
|
ld [linkBailOut+2],a
|
|
ld a,h
|
|
ld [linkBailOut+3],a
|
|
|
|
pop hl
|
|
ret
|
|
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: RemoveSpriteObjectsFromMap
|
|
;---------------------------------------------------------------------
|
|
RemoveSpriteObjectsFromMap:
|
|
;----remove all objects from the map--------------------------
|
|
ld a,OBJLISTBANK
|
|
ldio [$ff70],a
|
|
ld hl,objExists+1
|
|
.removeObjectsLoop
|
|
push hl
|
|
ld a,[hl]
|
|
or a
|
|
jr z,.removeObjects_continue
|
|
ld a,l
|
|
call IndexToPointerDE
|
|
ld a,[numClasses]
|
|
ld b,a
|
|
inc b
|
|
ld h,((objClassLookup>>8) & $ff)
|
|
ld a,[hl]
|
|
cp b ;this obj a regular creature?
|
|
jr nc,.removeObjects_continue
|
|
|
|
call GetFacing
|
|
bit 7,a ;sprite?
|
|
jr z,.restoreObjListBank ;no
|
|
ld c,a
|
|
call RemoveFromMap
|
|
.restoreObjListBank
|
|
ld a,OBJLISTBANK
|
|
ldio [$ff70],a
|
|
.removeObjects_continue
|
|
pop hl
|
|
inc hl
|
|
ld a,h
|
|
cp ((objExists>>8) & $ff) + 1
|
|
jr nz,.removeObjectsLoop
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: GetMethodAddrFromPointer
|
|
; Arguments: hl - pointer to method address
|
|
; Returns: hl - pointer to method
|
|
; Alters: af
|
|
;---------------------------------------------------------------------
|
|
GetMethodAddrFromPointer::
|
|
PUSHROM
|
|
ld a,BANK(classTable)
|
|
call SetActiveROM
|
|
|
|
ld a,[hl+]
|
|
ld h,[hl]
|
|
ld l,a
|
|
|
|
POPROM
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: InstallHBlankHandler
|
|
; Arguments: hl - pointer to hblank handler
|
|
; Returns: Nothing.
|
|
; Alters: af
|
|
;---------------------------------------------------------------------
|
|
InstallHBlankHandler::
|
|
di
|
|
ld a,l
|
|
ld [hblankVector+1],a ;+0 is opcode "jp"
|
|
ld a,h
|
|
ld [hblankVector+2],a
|
|
ei
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: LockRemoteHeroesUsed
|
|
; Arguments: None.
|
|
; Returns: z - lock attempt unsuccessful
|
|
; nz - success
|
|
; Alters: af
|
|
; Description: Informs the remote machine that this machine is
|
|
; messing with the heroes to prevent collisions
|
|
;---------------------------------------------------------------------
|
|
LockRemoteHeroesUsed::
|
|
ld a,[amLinkMaster]
|
|
bit 7,a
|
|
jr nz,.lockOkay
|
|
|
|
.sendLock
|
|
ld a,[heroesLocked]
|
|
or a
|
|
jr nz,.returnFailure
|
|
ld a,LLOCKHEROES
|
|
call ExchangeByte
|
|
call CheckSimultaneousLCC
|
|
jr nz,.sendLock
|
|
|
|
ld a,1 ;send "locked" to remote
|
|
call TransmitByte
|
|
|
|
.lockOkay
|
|
ld a,1
|
|
ld [heroesLocked],a
|
|
or a
|
|
ret
|
|
|
|
.returnFailure
|
|
xor a
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: UpdateRemoteHeroesUsed
|
|
; Arguments: None.
|
|
; Returns: Nothing.
|
|
; Alters: af
|
|
; Description: Sends current [heroesUsed] to the remote machine
|
|
; if present. Also unlocks heroesUsed if locked.
|
|
;---------------------------------------------------------------------
|
|
UpdateRemoteHeroesUsed::
|
|
ld a,[amLinkMaster]
|
|
bit 7,a
|
|
jr z,.updateHeroesUsed
|
|
|
|
;no link, free lock
|
|
xor a
|
|
ld [heroesLocked],a
|
|
ret
|
|
|
|
.updateHeroesUsed
|
|
ld a,LUPDATEHERO
|
|
call ExchangeByte
|
|
call CheckSimultaneousLCC
|
|
jr nz,.updateHeroesUsed ;must repeat
|
|
|
|
ld a,[heroesUsed]
|
|
call TransmitByte
|
|
|
|
ld a,[heroesLocked]
|
|
or a
|
|
ret z ;not locked don't bother
|
|
|
|
.sendLock
|
|
ld a,LLOCKHEROES
|
|
call ExchangeByte
|
|
call CheckSimultaneousLCC
|
|
jr nz,.sendLock
|
|
|
|
xor a ;send "unlocked" to remote
|
|
ld [heroesLocked],a
|
|
call TransmitByte
|
|
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: PlaySample
|
|
; Arguments: a - bank of sample
|
|
; hl - start address of sample
|
|
; Alters: af,hl
|
|
; Description:
|
|
;---------------------------------------------------------------------
|
|
PlaySample::
|
|
;start sample playing
|
|
di
|
|
ldio [sampleBank],a
|
|
xor a
|
|
ldio [samplePlaying],a
|
|
ei
|
|
|
|
ld a,l
|
|
ldio [sampleAddress],a
|
|
ld a,h
|
|
ldio [sampleAddress+1],a
|
|
ld a,$0f
|
|
ldio [sampleMask],a
|
|
ld a,$86
|
|
ldio [$ff1a],a ;sound 3 enable
|
|
ld hl,$ff26
|
|
set 2,[hl]
|
|
ld a,1
|
|
ldio [samplePlaying],a
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; FinishHBlankPlayingSample
|
|
;---------------------------------------------------------------------
|
|
FinishHBlankPlayingSample::
|
|
ldio a,[samplePlaying]
|
|
or a
|
|
jr z,.done
|
|
|
|
.nextSample
|
|
ld hl,sampleAddress
|
|
ld a,[hl+]
|
|
ld h,[hl]
|
|
ld l,a
|
|
.loadNextSample
|
|
ldio a,[sampleBank]
|
|
ld [$2100],a
|
|
ldio a,[sampleMask]
|
|
xor $ff
|
|
ldio [sampleMask],a
|
|
cp $0f
|
|
jr nz,.getLeftNibble
|
|
|
|
.getRightNibble
|
|
and a,[hl]
|
|
inc hl
|
|
jr .normalData ;will never be special code
|
|
|
|
.getLeftNibble
|
|
and a,[hl] ;next sample byte
|
|
|
|
.checkForSpecialCodes
|
|
cp $80
|
|
jr nz,.normalData
|
|
|
|
;code indicating termination or link follows
|
|
inc hl
|
|
ld a,[hl+]
|
|
or a
|
|
jr nz,.link
|
|
|
|
ld [samplePlaying],a
|
|
ld a,$ff
|
|
ld [$ff24],a ;full volume both channels
|
|
jr .restoreBank
|
|
|
|
.link ld a,[hl+]
|
|
ld [sampleBank],a
|
|
ld a,[hl+]
|
|
ld h,[hl]
|
|
ld l,a
|
|
jr .loadNextSample
|
|
|
|
.normalData
|
|
ld b,a
|
|
swap a
|
|
or b
|
|
or $88
|
|
ldio [$ff24],a ;sound enabled/volume
|
|
|
|
.saveNewAddress
|
|
ld a,l
|
|
ldio [sampleAddress],a
|
|
ld a,h
|
|
ldio [sampleAddress+1],a
|
|
|
|
.restoreBank
|
|
ldio a,[curROMBank]
|
|
ld [$2100],a
|
|
|
|
.done
|
|
pop hl
|
|
pop bc
|
|
pop af
|
|
reti
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: Lookup8
|
|
; Arguments: a - index
|
|
; hl - start lookup table
|
|
; Alters: af,hl
|
|
; Returns: a - table[a]
|
|
;---------------------------------------------------------------------
|
|
Lookup8::
|
|
add l
|
|
ld l,a
|
|
ld a,h
|
|
adc 0
|
|
ld h,a
|
|
ld a,[hl]
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: Lookup16
|
|
; Arguments: a - index
|
|
; hl - start lookup table
|
|
; Alters: af,hl
|
|
; Returns: hl - table[a*2]
|
|
;---------------------------------------------------------------------
|
|
Lookup16::
|
|
push de
|
|
ld e,a
|
|
ld d,0
|
|
sla e
|
|
rl d
|
|
add hl,de
|
|
ld a,[hl+]
|
|
ld h,[hl]
|
|
ld l,a
|
|
pop de
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: LookupIndexOfData8
|
|
; Arguments: a - data
|
|
; hl - start of lookup table
|
|
; Alters: af,hl
|
|
; Returns: a - where table[a] is original data a.
|
|
; Data must exist!
|
|
;---------------------------------------------------------------------
|
|
LookupIndexOfData8::
|
|
push bc
|
|
|
|
ld c,0
|
|
.findLoop
|
|
cp [hl]
|
|
jr z,.done
|
|
|
|
inc c
|
|
inc hl
|
|
jr .findLoop
|
|
|
|
.done
|
|
ld a,c
|
|
pop bc
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: FindFirstBGLoc
|
|
; Arguments: hl - bg class to find (e.g. classClearanceBG)
|
|
; Returns: hl - first location of class
|
|
; a - 0 on failure
|
|
; zflag - or a
|
|
; Alters: af
|
|
;---------------------------------------------------------------------
|
|
FindFirstBGLoc::
|
|
push bc
|
|
push de
|
|
|
|
push hl
|
|
pop bc
|
|
call FindClassIndex
|
|
ld b,a
|
|
|
|
ld a,MAPBANK
|
|
ld [$ff70],a
|
|
|
|
;setup de with first out-of-bounds index
|
|
ld a,[mapTotalSize]
|
|
ld e,a
|
|
ld a,[mapTotalSize+1]
|
|
ld d,a
|
|
|
|
ld hl,map
|
|
.lookForFirst
|
|
ld a,[hl+]
|
|
cp b
|
|
jr z,.foundIt
|
|
|
|
;hl < de?
|
|
ld a,h
|
|
cp d
|
|
jr c,.lookForFirst
|
|
|
|
ld a,l
|
|
cp e
|
|
jr c,.lookForFirst
|
|
|
|
;not found
|
|
xor a
|
|
jr .done
|
|
|
|
.foundIt
|
|
dec hl
|
|
ld a,1
|
|
or a
|
|
|
|
.done
|
|
pop de
|
|
pop bc
|
|
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: LinkTransmitMemoryLocation
|
|
; Arguments: a - RAM bank
|
|
; hl - memory location to transmit to the remote
|
|
; GameBoy
|
|
; Alters: af
|
|
;---------------------------------------------------------------------
|
|
LinkTransmitMemoryLocation::
|
|
push bc
|
|
ld b,a
|
|
|
|
ld a,[amLinkMaster]
|
|
bit 7,a
|
|
jr nz,.done ;not linked
|
|
|
|
.requestTransmit
|
|
ld a,LUPDATEMEMORY
|
|
call ExchangeByte
|
|
call CheckSimultaneousLCC
|
|
jr nz,.requestTransmit
|
|
|
|
ld a,b
|
|
ldio [$ff70],a
|
|
call TransmitByte
|
|
ld a,l
|
|
call TransmitByte
|
|
ld a,h
|
|
call TransmitByte
|
|
ld a,[hl]
|
|
call TransmitByte
|
|
|
|
.done
|
|
pop bc
|
|
ret
|
|
|
|
|
|
;---------------------------------------------------------------------
|
|
; Link Code
|
|
;---------------------------------------------------------------------
|
|
SECTION "LinkCodeSection",ROMX
|
|
linkCode:
|
|
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: HandleInput
|
|
; Description: Polls the buttons and stores the input in [curInput0].
|
|
; Then performs some network code and sets up [curJoy0],
|
|
; [curJoy1], [curInput0], and [curInput1]. curJoyX may
|
|
; be set to zero elsewhere to prevent the heroes from
|
|
; moving but curInput0 and curInput1 will always be the
|
|
; original values.
|
|
;
|
|
; $80 - 7:Start
|
|
; $40 - 6:Select
|
|
; $20 - 5:B
|
|
; $10 - 4:A
|
|
; $08 - 3:Down
|
|
; $04 - 2:Up
|
|
; $02 - 1:Left
|
|
; $01 - 0:Right
|
|
;
|
|
; A linked Master should read its input from [curJoy0].
|
|
; A linked Slave should read its input from [curJoy1].
|
|
; To make this easier [myJoy] is set up to be the
|
|
; appropriate one.
|
|
;
|
|
; If no link connection established, attempt a link
|
|
; connection.
|
|
;
|
|
; If no link:
|
|
; Convert curInput0->Joy1 (result will be same as
|
|
; encoding then decoding curInput).
|
|
;
|
|
; If link connection established:
|
|
; Exchange Control Byte with linked machine. If
|
|
; Command Code gotten in return, perform requested
|
|
; action and then repeat attempt to exchange control
|
|
; byte.
|
|
;
|
|
; If Master: curInput0->Joy1, remoteInput->Joy2
|
|
; If Slave: curInput0->Joy2, remoteInput->Joy1
|
|
;---------------------------------------------------------------------
|
|
HandleInput:
|
|
ld a,$20
|
|
ldio [$ff00],a ;select P14
|
|
ldio a,[$ff00]
|
|
ldio a,[$ff00] ;wait a few cycles
|
|
cpl
|
|
and $0f
|
|
ld b,a ;b has direction info
|
|
ld a,$10 ;select P15
|
|
ld [$ff00],a
|
|
ldio a,[$ff00] ;wait mo
|
|
ldio a,[$ff00] ;wait mo
|
|
ldio a,[$ff00] ;wait mo
|
|
ldio a,[$ff00] ;wait mo
|
|
ldio a,[$ff00] ;wait mo
|
|
ldio a,[$ff00] ;wait mo
|
|
cpl
|
|
and $0f
|
|
swap a
|
|
or b ;a has all buttons
|
|
ld [curInput0],a
|
|
ld a,$30 ;deselect P14 and P15
|
|
ldio [$ff00],a
|
|
|
|
;--if no link, attempt link connection ----------------------
|
|
ld a,[amLinkMaster]
|
|
cp $ff
|
|
jr z,.afterLinkAttempt ;L1101 attempts link as slave
|
|
cp $fe ;attempt link as master?
|
|
jr nz,.afterLinkAttempt
|
|
|
|
.attemptLinkAsMaster
|
|
ld a,$55
|
|
ldio [$ff01],a ;exchange data = $55
|
|
ld a,INTCLK ;ready to xchg, use my clock
|
|
ldio [$ff02],a
|
|
|
|
.waitMasterLinkAttempt
|
|
ldio a,[$ff02]
|
|
and $80
|
|
jr nz,.waitMasterLinkAttempt
|
|
|
|
;see what we got
|
|
ldio a,[$ff01]
|
|
cp $aa
|
|
jr nz,.afterLinkAttempt
|
|
|
|
;found a Slave! That means I'm the Master!
|
|
ld a,EXTCLK ;switch to receive mode
|
|
ldio [$ff02],a
|
|
ld a,1
|
|
ld [amLinkMaster],a
|
|
ld [lastLinkAction],a
|
|
|
|
.afterLinkAttempt
|
|
ld a,[amLinkMaster]
|
|
bit 7,a
|
|
jr z,.amLinked
|
|
|
|
;no link, convert curInput->curJoy0.
|
|
ld a,[curInput0]
|
|
call ConvertInput
|
|
ld [curInput0],a
|
|
ld [curJoy0],a
|
|
ld [myJoy],a
|
|
xor a
|
|
ld [curJoy1],a
|
|
ld [curInput1],a
|
|
ret
|
|
|
|
.amLinked
|
|
|
|
IF 0
|
|
;----every second or so, get the remote machine's
|
|
;----random seed and make sure it matches ours.
|
|
;----Resynchronize the machines if not
|
|
ld a,[amLinkMaster]
|
|
cp 1
|
|
jr nz,.exchangeBCB ;only master can initiate
|
|
|
|
ld a,[updateTimer] ;not time yet
|
|
and 31
|
|
cp 31
|
|
jr nz,.exchangeBCB
|
|
|
|
;don't do it if can't join map
|
|
ld a,[canJoinMap]
|
|
or a
|
|
jr z,.exchangeBCB
|
|
|
|
.getRandomSeed
|
|
ld a,LGETRANDOMSEED ;send the request
|
|
call ExchangeByte
|
|
call CheckSimultaneousLCC
|
|
jr nz,.getRandomSeed ;must repeat
|
|
|
|
;get the actual seed
|
|
call ReceiveByte
|
|
ld b,a
|
|
ld a,[randomLoc]
|
|
cp b ;got same in return?
|
|
jr z,.exchangeBCB ;continue if yes
|
|
|
|
;on same map?
|
|
ld a,[heroesPresent]
|
|
cp %11
|
|
jr nz,.exchangeBCB ;not on same map
|
|
|
|
.resynchronize
|
|
;resynchronize machines
|
|
ld a,LRESYNCHRONIZE
|
|
call ExchangeByte
|
|
call CheckSimultaneousLCC
|
|
jr nz,.resynchronize
|
|
LONGCALLNOARGS HostResynchronize
|
|
ENDC
|
|
|
|
.exchangeBCB
|
|
;----exchange Button Control Bytes with remote machine--------
|
|
ld a,[curInput0]
|
|
call EncodeInput
|
|
call ExchangeByte
|
|
call HandleRemoteInput
|
|
jr nz,.exchangeBCB ;must repeat
|
|
|
|
;--Decode Button Control Bytes--------------------------------
|
|
push af ;save remoteInput
|
|
ld a,[amLinkMaster]
|
|
or a
|
|
jr z,.amLinkSlave
|
|
|
|
;I am the master. curInput0->curJoy0, remoteInput->curJoy1
|
|
pop af ;retrieve remoteInput
|
|
call DecodeInput
|
|
ld [curInput1],a
|
|
ld [curJoy1],a
|
|
ld a,[curInput0]
|
|
call ConvertInput
|
|
ld [curInput0],a
|
|
ld [curJoy0],a
|
|
ld [myJoy],a
|
|
ret
|
|
|
|
.amLinkSlave
|
|
ld a,[curInput0]
|
|
call ConvertInput
|
|
ld [curInput1],a
|
|
ld [curJoy1],a
|
|
ld [myJoy],a
|
|
|
|
pop af ;retrieve remoteInput
|
|
call DecodeInput
|
|
ld [curInput0],a
|
|
ld [curJoy0],a
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: ConvertInput
|
|
; Argument: a - uncoded button control byte
|
|
; Returns: a - converted BCB, same as calling Encode then
|
|
; Decode but quicker
|
|
; Description: To simulate uncoded->encoded->decoded, forces buttons
|
|
; 7:4 to have A/B or Start/Select info but not both
|
|
; (A/B has priority).
|
|
; Alters: af
|
|
;---------------------------------------------------------------------
|
|
ConvertInput:
|
|
push bc
|
|
|
|
ld b,a ;save original
|
|
and %00110000 ;has A/B info?
|
|
ld a,b ;restore original
|
|
jr z,.done ;if no AB info then conv. complete
|
|
and %00111111 ;has AB info; clear out start/sel
|
|
|
|
.done
|
|
pop bc
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: EncodeInput
|
|
; Argument: a - uncoded button control byte
|
|
; 7:st 6:se 5:b 4:a 3:0=DULR
|
|
; Returns: a - coded button control byte
|
|
; 7=0
|
|
; 6=0 - 5:4 = ba
|
|
; =1 - 5:4 = te (start, select)
|
|
; 3:0 = DULR
|
|
; Alters: af
|
|
;---------------------------------------------------------------------
|
|
EncodeInput:
|
|
push bc
|
|
push hl
|
|
|
|
ld b,a ;save original
|
|
and %00001111
|
|
ld c,a ;save D-PAD
|
|
|
|
ld h,((encodeControlByteTable>>8) & $ff)
|
|
ld a,b
|
|
swap a
|
|
and %00001111
|
|
add (encodeControlByteTable & $ff)
|
|
ld l,a
|
|
|
|
ld a,[hl] ;get encoded buttons
|
|
or c ;combine with D-PAD
|
|
|
|
pop hl
|
|
pop bc
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: DecodeInput
|
|
; Argument: a - coded Control Byte
|
|
; Returns: a - uncoded button Control Byte
|
|
; Alters: af
|
|
;---------------------------------------------------------------------
|
|
DecodeInput:
|
|
push bc
|
|
push hl
|
|
|
|
ld b,a ;save original
|
|
and %00001111
|
|
ld c,a ;save D-PAD
|
|
|
|
ld h,((decodeControlByteTable>>8) & $ff)
|
|
ld a,b
|
|
swap a
|
|
and %00000111
|
|
add (decodeControlByteTable & $ff)
|
|
ld l,a
|
|
|
|
ld a,[hl] ;get decoded buttons
|
|
or c ;combine with D-PAD
|
|
|
|
pop hl
|
|
pop bc
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: TransmitGameState
|
|
; Arguments: none
|
|
; Returns: none
|
|
; Alters: af
|
|
; Description: Transmits relevant game state data to Slave
|
|
; Includes hero data so slave's classes will be set
|
|
; appropriately
|
|
;---------------------------------------------------------------------
|
|
TransmitGameState:
|
|
push bc
|
|
push hl
|
|
|
|
ld hl,.linkBailAddress
|
|
xor a
|
|
call SetLinkBailOutAddress
|
|
|
|
ld hl,gameState
|
|
ld bc,5
|
|
xor a ;RAM bank doesn't matter
|
|
call TransmitData
|
|
|
|
ld hl,levelState
|
|
ld bc,256
|
|
ld a,LEVELSTATEBANK
|
|
call TransmitData
|
|
|
|
ld hl,inventory
|
|
ld bc,16
|
|
xor a
|
|
call TransmitData
|
|
|
|
ld hl,flightCode
|
|
ld bc,256
|
|
ld a,FLIGHTCODEBANK
|
|
call TransmitData
|
|
|
|
ld hl,hero0_data
|
|
ld bc,HERODATASIZE * 2
|
|
xor a
|
|
call TransmitData
|
|
|
|
ld a,[appomattoxMapIndex]
|
|
call TransmitByte
|
|
|
|
;send the joinMap
|
|
ld a,[joinMap]
|
|
call TransmitByte
|
|
ld a,[joinMap+1]
|
|
call TransmitByte
|
|
|
|
.linkBailAddress
|
|
ld hl,0
|
|
xor a
|
|
call SetLinkBailOutAddress
|
|
|
|
pop hl
|
|
pop bc
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: HostSynchronize
|
|
; Arguments: none
|
|
; Returns: none
|
|
; Alters: af
|
|
; Description: Transmits relevant map data to Guest
|
|
;---------------------------------------------------------------------
|
|
HostResynchronize:
|
|
push bc
|
|
push hl
|
|
jr HostSynchronizeCommon
|
|
|
|
HostSynchronize:
|
|
push bc
|
|
push hl
|
|
|
|
ld hl,.nogo
|
|
xor a
|
|
call SetLinkBailOutAddress
|
|
|
|
ld a,1 ;make sure it's looking at 1x1
|
|
ldio [curObjWidthHeight],a
|
|
call ReceiveByte ;guest's requested exit direction
|
|
ld hl,$0101 ;start looking at (1,1)
|
|
call FindExitLocation
|
|
xor a ;didn't find it if $0000
|
|
cp h
|
|
jr nz,.goAhead
|
|
cp l
|
|
jr nz,.goAhead
|
|
|
|
;nogo
|
|
xor a
|
|
call TransmitByte
|
|
.nogo
|
|
ld hl,0
|
|
xor a
|
|
call SetLinkBailOutAddress
|
|
|
|
pop hl
|
|
pop bc
|
|
ret
|
|
|
|
.goAhead
|
|
call ConvertLocHLToXY
|
|
ld a,1
|
|
call TransmitByte
|
|
|
|
ldio a,[mapState] ;level state
|
|
call TransmitByte
|
|
ldio a,[mapState+1]
|
|
call TransmitByte
|
|
|
|
;make sure backbuffer doesn't redraw during hero loading
|
|
xor a
|
|
ldio [backBufferReady],a
|
|
|
|
;activate heroes 0 and 1
|
|
ld a,[hero0_index]
|
|
or a
|
|
jr nz,.hero0_active
|
|
|
|
ld a,1
|
|
ld [hero0_index],a
|
|
|
|
.hero0_active
|
|
ld a,[hero1_index]
|
|
or a
|
|
jr nz,.hero1_active
|
|
|
|
ld a,1
|
|
ld [hero1_index],a
|
|
.hero1_active
|
|
call HostExchangeHeroData
|
|
|
|
;set hero 1 to joystick 1
|
|
push hl
|
|
ld a,[hero1_type]
|
|
ld hl,heroJoyIndex
|
|
or [hl]
|
|
ld [hl],a
|
|
pop hl
|
|
|
|
inc hl
|
|
ld b,h
|
|
ld c,l
|
|
PREPLONGCALL .afterSetupHero
|
|
LONGCALL PrepSetupHeroBC ;bc is correct hero data
|
|
.afterSetupHero
|
|
|
|
HostSynchronizeCommon:
|
|
xor a
|
|
ld [backBufferReady],a
|
|
|
|
;wait on ready signal from guest
|
|
.waitReady
|
|
call ReceiveByte
|
|
cp LSYNCHREADY
|
|
jr nz,.waitReady
|
|
|
|
;send all my hero data ;re-send all my hero data
|
|
ld hl,hero0_data
|
|
ld bc,HERODATASIZE*2
|
|
xor a
|
|
call TransmitData
|
|
|
|
ld a,[randomLoc] ;current random value/seed
|
|
call TransmitByte
|
|
|
|
ld a,[heroesIdle]
|
|
call TransmitByte
|
|
|
|
LONGCALLNOARGS RemoveSpriteObjectsFromMap
|
|
|
|
;----transmit map---------------------------------------------
|
|
ld hl,map
|
|
ld bc,4096
|
|
ld a,MAPBANK
|
|
call TransmitData
|
|
|
|
;fadeCurPalette
|
|
ld hl,fadeCurPalette
|
|
ld bc,128
|
|
xor a
|
|
call TransmitData
|
|
|
|
;gamePalette
|
|
ld hl,gamePalette
|
|
ld bc,128
|
|
ld a,FADEBANK
|
|
call TransmitData
|
|
|
|
;first 16 bytes of level check RAM
|
|
ld hl,levelCheckRAM
|
|
ld bc,16
|
|
xor a
|
|
call TransmitData
|
|
|
|
;spriteOAMdata
|
|
ld hl,spriteOAMBuffer
|
|
ld bc,160
|
|
xor a
|
|
call TransmitData
|
|
|
|
ld hl,headTable ;headTable - linked list head
|
|
ld bc,256
|
|
ld a,OBJLISTBANK
|
|
call TransmitData
|
|
|
|
ld hl,objExists ;objExists, FOF table
|
|
ld bc,512
|
|
ld a,OBJLISTBANK
|
|
call TransmitCompressedData
|
|
|
|
ld a,[numClasses]
|
|
call TransmitByte
|
|
|
|
;bc = numClasses times two + 2
|
|
ld a,[numClasses]
|
|
ld b,0
|
|
ld c,a
|
|
sla c
|
|
rl b
|
|
inc bc
|
|
inc bc
|
|
|
|
ld hl,classLookup ;objExists, FOF table
|
|
;ld bc,512 numClasses * 2
|
|
ld a,OBJLISTBANK
|
|
call TransmitData
|
|
|
|
ld hl,fgTileMap
|
|
ld a,[numClasses]
|
|
ld b,0
|
|
ld c,a
|
|
ld a,OBJLISTBANK
|
|
call TransmitData
|
|
|
|
ld hl,objClassLookup ;class indices for each obj
|
|
ld bc,256
|
|
ld a,OBJLISTBANK
|
|
call TransmitData
|
|
|
|
ld hl,associatedIndex
|
|
ld bc,256
|
|
ld a,OBJLISTBANK
|
|
call TransmitData
|
|
|
|
ld hl,spritesUsed
|
|
ld bc,40
|
|
ld a,OBJLISTBANK
|
|
call TransmitCompressedData
|
|
|
|
;---------------transmit used objects-------------------------
|
|
ld a,OBJLISTBANK
|
|
ld [$ff70],a
|
|
ld de,objExists+1
|
|
.transmitUsedObject
|
|
ld a,[de] ;is this object used?
|
|
or a
|
|
jr z,.afterTransmitUsedObject ;not used
|
|
|
|
PREPLONGCALL .afterCvtToPtr
|
|
ld a,e ;get object index
|
|
LONGCALL IndexToPointerHL ;cvt to ptr
|
|
.afterCvtToPtr
|
|
ld bc,16
|
|
ld a,OBJBANK
|
|
call TransmitData
|
|
ld a,OBJLISTBANK
|
|
ld [$ff70],a
|
|
|
|
.afterTransmitUsedObject
|
|
inc de
|
|
ld a,e
|
|
or a
|
|
jr nz,.transmitUsedObject
|
|
|
|
ld a,[numFreeSprites]
|
|
call TransmitByte
|
|
|
|
ld a,[firstFreeObj]
|
|
call TransmitByte
|
|
|
|
ld a,[randomLoc]
|
|
call TransmitByte
|
|
|
|
ld a,[guardAlarm]
|
|
call TransmitByte
|
|
|
|
;ld a,[dialogBank]
|
|
;call TransmitByte
|
|
|
|
ld a,[respawnMap]
|
|
call TransmitByte
|
|
ld a,[respawnMap+1]
|
|
call TransmitByte
|
|
|
|
ldio a,[mapState] ;level state
|
|
call TransmitByte
|
|
ldio a,[mapState+1]
|
|
call TransmitByte
|
|
|
|
ld hl,levelVars
|
|
ld bc,64
|
|
xor a ;RAM bank doesn't matter
|
|
call TransmitData
|
|
|
|
ld hl,musicBank
|
|
ld bc,64
|
|
xor a ;RAM bank doesn't matter
|
|
call TransmitData
|
|
|
|
ld hl,musicStack
|
|
ld bc,128
|
|
ld a,MUSICBANK
|
|
call TransmitData
|
|
|
|
ldio a,[musicEnabled]
|
|
call TransmitByte
|
|
|
|
LONGCALLNOARGS LinkRemakeLists
|
|
|
|
.done
|
|
pop hl
|
|
pop bc
|
|
ret
|
|
|
|
HostExchangeHeroData:
|
|
;send out my hero data
|
|
ld a,[amLinkMaster]
|
|
or a
|
|
jr z,.slave_sendHero1_recvHero0
|
|
|
|
.master_sendHero0_recvHero1
|
|
ld hl,hero1_data
|
|
push hl
|
|
ld hl,hero0_data
|
|
jr .setHeroSequence
|
|
|
|
.slave_sendHero1_recvHero0
|
|
ld hl,hero0_data
|
|
push hl
|
|
ld hl,hero1_data
|
|
|
|
.setHeroSequence
|
|
;send my hero data
|
|
ld bc,HERODATASIZE
|
|
xor a
|
|
call TransmitData
|
|
|
|
;get remote hero data
|
|
pop hl
|
|
xor a
|
|
call ReceiveData
|
|
|
|
ret
|
|
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: LinkTest
|
|
; Arguments: none
|
|
; Returns: none
|
|
; Alters: af
|
|
; Description: Fills 4k of memory with repeating pattern $00-$ff,
|
|
; transmits that data to Slave, receives that data
|
|
; back, compares it to the original pattern, and
|
|
; finally prints out a Debug message of 1 for equal
|
|
; or 0 for not equal.
|
|
;---------------------------------------------------------------------
|
|
LinkTest:
|
|
push bc
|
|
push de
|
|
push hl
|
|
|
|
di
|
|
;fill $d000-$cfff with repeating pattern $00-$ff
|
|
ld a,1
|
|
ld [$ff70],a
|
|
|
|
ld hl,$d000
|
|
xor a
|
|
.fill
|
|
ld [hl+],a
|
|
inc a
|
|
jr nz,.fill
|
|
ld a,h
|
|
cp $e0
|
|
ld a,0 ;avoid setting z flag here
|
|
jr nz,.fill
|
|
|
|
ld a,4
|
|
.transfer32k
|
|
push af
|
|
ld a,1
|
|
ld bc,$1000
|
|
ld hl,$d000
|
|
call TransmitData
|
|
|
|
ld a,1
|
|
call ReceiveData
|
|
pop af
|
|
dec a
|
|
jr nz,.transfer32k
|
|
|
|
;compare received data to original pattern
|
|
ld b,0 ;comparing to $00
|
|
ld hl,$d000
|
|
.compare
|
|
ld a,[hl+]
|
|
cp b
|
|
jr nz,.notEqual
|
|
inc b
|
|
ld a,h
|
|
cp $e0
|
|
jr nz,.compare
|
|
|
|
.equal
|
|
xor a
|
|
ldio [$ff0f],a
|
|
ei
|
|
ld a,1
|
|
call DebugVal
|
|
jr .infi
|
|
|
|
.notEqual
|
|
xor a
|
|
ldio [$ff0f],a
|
|
ei
|
|
xor a
|
|
call DebugVal
|
|
|
|
dec hl
|
|
ld a,h
|
|
call DebugVal
|
|
ld a,l
|
|
call DebugVal
|
|
di
|
|
.infi jr .infi
|
|
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: GeneratePauseMessage
|
|
; Arguments: none
|
|
; Returns: none
|
|
; Alters: all
|
|
; Description: Creates appropriate Pause Message
|
|
;---------------------------------------------------------------------
|
|
GeneratePauseMessage:
|
|
ld a,[dialogBank]
|
|
push af
|
|
|
|
;wait until the backbuffer is blitted
|
|
.waitBackBuffer
|
|
ldio a,[backBufferReady]
|
|
or a
|
|
jr z,.canMessWithBackBuffer
|
|
|
|
call VWait
|
|
jr .waitBackBuffer
|
|
|
|
.canMessWithBackBuffer
|
|
;generate gtx at backbuffer+$800
|
|
|
|
;de = level name index
|
|
ld a,[curLevelStateIndex]
|
|
ld d,0
|
|
ld e,a ;level index * 2
|
|
sla e
|
|
rl d
|
|
ld hl,levelNames
|
|
add hl,de
|
|
ld a,[hl+]
|
|
ld e,a
|
|
ld a,[hl+]
|
|
ld d,a
|
|
ld hl,backBuffer
|
|
ld a,BANK(levelNames)
|
|
ld [dialogBank],a
|
|
call ClearGTXLine
|
|
call WriteGTXLine
|
|
|
|
;write char name
|
|
push hl
|
|
push hl
|
|
LDHL_CURHERODATA HERODATA_TYPE
|
|
ld a,[hl]
|
|
ld c,$ff
|
|
.findCharIndex
|
|
inc c
|
|
rrca
|
|
bit 7,a
|
|
jr z,.findCharIndex
|
|
ld a,c
|
|
ld hl,heroNames
|
|
call .lookupIndexAToHLToDE
|
|
pop hl
|
|
call ClearGTXLine
|
|
call WriteGTXLine
|
|
pop hl
|
|
|
|
;write map coordinates
|
|
add sp,-24 ;create temporary buffer on stack
|
|
push hl
|
|
ld hl,sp+2
|
|
ld d,h
|
|
ld e,l
|
|
ld [hl],16 ;spaces to center
|
|
inc hl
|
|
ld [hl],4 ;number of chars
|
|
inc hl
|
|
ld a,[curLevelStateIndex]
|
|
push af
|
|
and $f
|
|
add 210 ;'A' character
|
|
ld [hl+],a
|
|
pop af
|
|
ld [hl],$f9 ;hyphen
|
|
inc hl
|
|
swap a
|
|
and $f
|
|
cp 10
|
|
jr c,.oneDigit
|
|
ld [hl],201 ;'1'
|
|
inc hl
|
|
sub 10
|
|
.oneDigit
|
|
add 200 ;get digit '0'-'9'
|
|
ld [hl+],a
|
|
ld [hl],0 ;blank space may or may not be used
|
|
pop hl
|
|
push de
|
|
call WriteGTXLine ;de is line to write
|
|
pop de
|
|
|
|
;write map coordinates if landing zone------------------------
|
|
ld c,2 ;# of items in inventory screen
|
|
|
|
push bc ;see if we're at an LZ
|
|
ld a,[curLevelStateIndex]
|
|
call .getFlightCodeBCFromMapA
|
|
pop bc
|
|
jr z,.afterWriteCoords
|
|
|
|
push hl
|
|
ld h,d
|
|
ld l,e
|
|
ld [hl],8 ;spaces to center
|
|
inc hl
|
|
ld [hl],4 ;number of chars
|
|
inc hl
|
|
push bc
|
|
ld a,[curLevelStateIndex]
|
|
call .getFlightCodeBCFromMapA
|
|
call .writeCoordsBC
|
|
pop bc
|
|
pop hl
|
|
call ClearGTXLine
|
|
call WriteGTXLine ;de is line to write
|
|
inc c
|
|
.afterWriteCoords
|
|
add sp,24 ;free up temporary stack space
|
|
|
|
;write inventory
|
|
call GetFirstInventoryIndex
|
|
cp $ff
|
|
jr z,.afterWriteInventory
|
|
|
|
;blank line
|
|
push af
|
|
ld de,blankLine
|
|
call ClearGTXLine
|
|
call WriteGTXLine
|
|
inc c
|
|
pop af
|
|
|
|
;remaining inventory
|
|
.nextInventoryItem
|
|
ld b,a ;obj index in b
|
|
push af
|
|
push hl
|
|
ld hl,itemNames
|
|
call .lookupIndexAToHLToDE
|
|
pop hl
|
|
|
|
inc de
|
|
ld a,[de]
|
|
dec de
|
|
or a
|
|
jr z,.skipItem ;an upgrade or something
|
|
|
|
call ClearGTXLine
|
|
push hl
|
|
call WriteGTXLine
|
|
|
|
;write object color
|
|
ld a,b
|
|
add (itemColors&$ff)
|
|
ld e,a
|
|
ld a,((itemColors>>8)&$ff)
|
|
adc 0
|
|
ld d,a
|
|
ld a,[de]
|
|
or 8
|
|
pop de
|
|
push hl
|
|
ld hl,$300
|
|
add hl,de
|
|
ld [hl],a
|
|
pop hl
|
|
inc c
|
|
.skipItem
|
|
pop af
|
|
call GetNextInventoryIndex
|
|
cp $ff
|
|
jr nz,.nextInventoryItem
|
|
|
|
.afterWriteInventory
|
|
inc c
|
|
ld de,restart_message
|
|
call ClearGTXLine
|
|
call WriteGTXLine
|
|
|
|
ld a,c
|
|
ld [backBuffer+63],a ;#lines
|
|
|
|
pop af
|
|
ld [dialogBank],a
|
|
ret
|
|
|
|
.getFlightCodeBCFromMapA
|
|
;returns flight code in bc, zflag
|
|
push de
|
|
push hl
|
|
ld de,3
|
|
|
|
ld b,a
|
|
ld a,FLIGHTCODEBANK
|
|
ldio [$ff70],a
|
|
ld hl,flightCode
|
|
ld c,[hl] ;number of flight codes
|
|
add hl,de ;start at byte 2/3 (map index)
|
|
.findFlightCode
|
|
ld a,[hl]
|
|
cp b
|
|
jr z,.getFlightCodeMatch
|
|
add hl,de
|
|
dec c
|
|
jr nz,.findFlightCode
|
|
|
|
xor a ;not found
|
|
pop hl
|
|
pop de
|
|
ret
|
|
|
|
.getFlightCodeMatch
|
|
dec hl
|
|
ld b,[hl]
|
|
dec hl
|
|
ld c,[hl]
|
|
pop hl
|
|
pop de
|
|
ld a,1
|
|
or a
|
|
ret
|
|
|
|
.lookupIndexAToHLToDE
|
|
rlca
|
|
add l
|
|
ld l,a
|
|
ld a,h
|
|
adc 0
|
|
ld h,a
|
|
ld a,[hl+]
|
|
ld d,[hl]
|
|
ld e,a
|
|
ret
|
|
|
|
.writeCoordsBC
|
|
ld a,b
|
|
swap a
|
|
call .writeCoordA
|
|
ld a,b
|
|
call .writeCoordA
|
|
ld a,c
|
|
swap a
|
|
call .writeCoordA
|
|
ld a,c
|
|
call .writeCoordA
|
|
ret
|
|
|
|
.writeCoordA
|
|
and $f
|
|
add $c0 ;first of 8 coordinate symbols
|
|
ld [hl+],a
|
|
ret
|
|
|
|
restart_message:
|
|
GTXSTRINGC "SELECTgoRESTART"
|
|
blankLine:
|
|
DB 0,0
|
|
|
|
;---------------------------------------------------------------------
|
|
; Routine: CopyMessageDEToHL
|
|
; Arguments: de - pointer to message
|
|
; hl - pointer to dest
|
|
; Returns: none
|
|
; Alters: all
|
|
; Description: First byte at [de] is number of bytes to copy from
|
|
; [de] to [hl]. Must be >= 1!
|
|
;---------------------------------------------------------------------
|
|
CopyMessageDEToHL:
|
|
ld a,[de]
|
|
inc de
|
|
ld c,a
|
|
.loop ld a,[de]
|
|
inc de
|
|
ld [hl+],a
|
|
dec c
|
|
jr nz,.loop
|
|
ret
|
|
|
|
levelNames:
|
|
DW L0000_Name,L0100_Name,L0200_Name,L0300_Name
|
|
DW L0400_Name,L0500_Name,L0600_Name,L0700_Name
|
|
DW L0800_Name,L0900_Name,L1000_Name,L1100_Name
|
|
DW L1200_Name,L1300_Name,L1400_Name,L1500_Name
|
|
|
|
DW L0001_Name,L0101_Name,L0201_Name,L0301_Name
|
|
DW L0401_Name,L0501_Name,L0601_Name,L0701_Name
|
|
DW L0801_Name,L0901_Name,L1001_Name,L1101_Name
|
|
DW L1201_Name,L1301_Name,L1401_Name,L1501_Name
|
|
|
|
DW L0002_Name,L0102_Name,L0202_Name,L0302_Name
|
|
DW L0402_Name,L0502_Name,L0602_Name,L0702_Name
|
|
DW L0802_Name,L0902_Name,L1002_Name,L1102_Name
|
|
DW L1202_Name,L1302_Name,L1402_Name,L1502_Name
|
|
|
|
DW L0003_Name,L0103_Name,L0203_Name,L0303_Name
|
|
DW L0403_Name,L0503_Name,L0603_Name,L0703_Name
|
|
DW L0803_Name,L0903_Name,L1003_Name,L1103_Name
|
|
DW L1203_Name,L1303_Name,L1403_Name,L1503_Name
|
|
|
|
DW L0004_Name,L0104_Name,L0204_Name,L0304_Name
|
|
DW L0404_Name,L0504_Name,L0604_Name,L0704_Name
|
|
DW L0804_Name,L0904_Name,L1004_Name,L1104_Name
|
|
DW L1204_Name,L1304_Name,L1404_Name,L1504_Name
|
|
|
|
DW L0005_Name,L0105_Name,L0205_Name,L0305_Name
|
|
DW L0405_Name,L0505_Name,L0605_Name,L0705_Name
|
|
DW L0805_Name,L0905_Name,L1005_Name,L1105_Name
|
|
DW L1205_Name,L1305_Name,L1405_Name,L1505_Name
|
|
|
|
DW L0006_Name,L0106_Name,L0206_Name,L0306_Name
|
|
DW L0406_Name,L0506_Name,L0606_Name,L0706_Name
|
|
DW L0806_Name,L0906_Name,L1006_Name,L1106_Name
|
|
DW L1206_Name,L1306_Name,L1406_Name,L1506_Name
|
|
|
|
DW L0007_Name,L0107_Name,L0207_Name,L0307_Name
|
|
DW L0407_Name,L0507_Name,L0607_Name,L0707_Name
|
|
DW L0807_Name,L0907_Name,L1007_Name,L1107_Name
|
|
DW L1207_Name,L1307_Name,L1407_Name,L1507_Name
|
|
|
|
DW L0008_Name,L0108_Name,L0208_Name,L0308_Name
|
|
DW L0408_Name,L0508_Name,L0608_Name,L0708_Name
|
|
DW L0808_Name,L0908_Name,L1008_Name,L1108_Name
|
|
DW L1208_Name,L1308_Name,L1408_Name,L1508_Name
|
|
|
|
DW L0009_Name,L0109_Name,L0209_Name,L0309_Name
|
|
DW L0409_Name,L0509_Name,L0609_Name,L0709_Name
|
|
DW L0809_Name,L0909_Name,L1009_Name,L1109_Name
|
|
DW L1209_Name,L1309_Name,L1409_Name,L1509_Name
|
|
|
|
DW L0010_Name,L0110_Name,L0210_Name,L0310_Name
|
|
DW L0410_Name,L0510_Name,L0610_Name,L0710_Name
|
|
DW L0810_Name,L0910_Name,L1010_Name,L1110_Name
|
|
DW L1210_Name,L1310_Name,L1410_Name,L1510_Name
|
|
|
|
DW L0011_Name,L0111_Name,L0211_Name,L0311_Name
|
|
DW L0411_Name,L0511_Name,L0611_Name,L0711_Name
|
|
DW L0811_Name,L0911_Name,L1011_Name,L1111_Name
|
|
DW L1211_Name,L1311_Name,L1411_Name,L1511_Name
|
|
|
|
DW L0012_Name,L0112_Name,L0212_Name,L0312_Name
|
|
DW L0412_Name,L0512_Name,L0612_Name,L0712_Name
|
|
DW L0812_Name,L0912_Name,L1012_Name,L1112_Name
|
|
DW L1212_Name,L1312_Name,L1412_Name,L1512_Name
|
|
|
|
DW L0013_Name,L0113_Name,L0213_Name,L0313_Name
|
|
DW L0413_Name,L0513_Name,L0613_Name,L0713_Name
|
|
DW L0813_Name,L0913_Name,L1013_Name,L1113_Name
|
|
DW L1213_Name,L1313_Name,L1413_Name,L1513_Name
|
|
|
|
DW L0014_Name,L0114_Name,L0214_Name,L0314_Name
|
|
DW L0414_Name,L0514_Name,L0614_Name,L0714_Name
|
|
DW L0814_Name,L0914_Name,L1014_Name,L1114_Name
|
|
DW L1214_Name,L1314_Name,L1414_Name,L1514_Name
|
|
|
|
DW L0015_Name,L0115_Name,L0215_Name,L0315_Name
|
|
DW L0415_Name,L0515_Name,L0615_Name,L0715_Name
|
|
DW L0815_Name,L0915_Name,L1015_Name,L1115_Name
|
|
DW L1215_Name,L1315_Name,L1415_Name,L1515_Name
|
|
|
|
L0000_Name:
|
|
GTXSTRINGC "THEoHIVE"
|
|
L0001_Name:
|
|
GTXSTRINGC "MADoBEEoPASS"
|
|
L0002_Name:
|
|
GTXSTRINGC "BEEoCOUNTRY"
|
|
L0003_Name:
|
|
GTXSTRINGC "BIGoEDaSoSHEEPoFARM"
|
|
L0004_Name:
|
|
GTXSTRINGC "HILLoBROTHERSoRANCH"
|
|
L0005_Name:
|
|
GTXSTRINGC "TRAKKTORoCOUNTRY"
|
|
L0006_Name:
|
|
GTXSTRINGC "SUNSEToVILLAGE"
|
|
L0007_Name:
|
|
GTXSTRINGC "CRAZYoCROWoGULCH"
|
|
L0008_Name:
|
|
GTXSTRINGC "SNEAKYoTREEoVALLEY"
|
|
L0009_Name:
|
|
GTXSTRINGC "PROVOLONE"
|
|
L0010_Name:
|
|
GTXSTRINGC "MUENSTER"
|
|
L0011_Name:
|
|
GTXSTRINGC "HOUSEoOFoSEASONS"
|
|
L0012_Name:
|
|
GTXSTRINGC "COMMANDoCORE"
|
|
L0013_Name:
|
|
GTXSTRINGC "ITCHYoTRIGGER"
|
|
L0014_Name:
|
|
GTXSTRINGC "THEoFAULT"
|
|
L0015_Name:
|
|
GTXSTRINGC "LOOSEoJARGON"
|
|
|
|
L0100_Name:
|
|
L0101_Name:
|
|
L0102_Name:
|
|
GTXSTRINGC "RIVER"
|
|
L0103_Name:
|
|
GTXSTRINGC "LILoEDaSoSHEEPoFARM"
|
|
L0104_Name:
|
|
GTXSTRINGC "SPRING"
|
|
L0105_Name:
|
|
GTXSTRINGC "DARKERoFOREST"
|
|
L0106_Name:
|
|
GTXSTRINGC "DARKISHoFOREST"
|
|
L0107_Name:
|
|
GTXSTRINGC "KIDNAPoCORNERoeLZf"
|
|
L0108_Name:
|
|
GTXSTRINGC "SNAKEoPIToeLZf"
|
|
L0109_Name:
|
|
GTXSTRINGC "CHEDDAR"
|
|
L0110_Name:
|
|
GTXSTRINGC "HAVARTI"
|
|
L0111_Name:
|
|
GTXSTRINGC "GOBLINoPIT"
|
|
L0112_Name:
|
|
GTXSTRINGC "HIVEoENTRANCE"
|
|
L0113_Name:
|
|
GTXSTRINGC "FRIENDLYoFIRE"
|
|
L0114_Name:
|
|
GTXSTRINGC "PATHoOFoSHADOWS"
|
|
L0115_Name:
|
|
GTXSTRINGC "DOUBLEoENTENDRE"
|
|
|
|
L0200_Name:
|
|
GTXSTRINGC "FORBIDDENoVILLAGE"
|
|
L0201_Name:
|
|
GTXSTRINGC "STRANGEoMIST"
|
|
L0202_Name:
|
|
L0203_Name:
|
|
L0204_Name:
|
|
GTXSTRINGC "RIVER"
|
|
L0205_Name:
|
|
GTXSTRINGC "JACOBaSoBRIDGE"
|
|
L0206_Name:
|
|
L0207_Name:
|
|
L0208_Name:
|
|
L0209_Name:
|
|
L0210_Name:
|
|
GTXSTRINGC "RIVER"
|
|
L0211_Name:
|
|
GTXSTRINGC "THEoBLOWERS"
|
|
L0212_Name:
|
|
GTXSTRINGC "THEoBELFRY"
|
|
L0213_Name:
|
|
GTXSTRINGC "CLOSEoQUARTERS"
|
|
L0214_Name:
|
|
GTXSTRINGC "JAILoBREAK"
|
|
L0215_Name:
|
|
GTXSTRINGC "BRAINIAC"
|
|
|
|
L0300_Name:
|
|
GTXSTRINGC "WEIRDoMIST"
|
|
L0301_Name:
|
|
GTXSTRINGC "ODDoMIST"
|
|
L0302_Name:
|
|
GTXSTRINGC "BIZARREoMISToeLZf"
|
|
L0303_Name:
|
|
GTXSTRINGC "MISToGATE"
|
|
L0304_Name:
|
|
GTXSTRINGC "MUNGAoFUNGA"
|
|
L0305_Name:
|
|
GTXSTRINGC "TRILINGoBURROW"
|
|
L0306_Name:
|
|
GTXSTRINGC "TWOoGUNS"
|
|
L0307_Name:
|
|
GTXSTRINGC "OUTPOSTgoDESOLATION"
|
|
L0308_Name:
|
|
GTXSTRINGC "DRYoGULCH"
|
|
L0309_Name:
|
|
GTXSTRINGC "SHOOToOUT"
|
|
L0310_Name:
|
|
GTXSTRINGC "REDoBENDoeLZf"
|
|
L0311_Name:
|
|
GTXSTRINGC "HIGHoGROUND"
|
|
L0312_Name:
|
|
GTXSTRINGC "THEoSTING"
|
|
L0313_Name:
|
|
GTXSTRINGC "INSOMNIAC"
|
|
L0314_Name:
|
|
GTXSTRINGC "RUNAWAY"
|
|
L0315_Name:
|
|
GTXSTRINGC "INSOMNIAC"
|
|
|
|
L0400_Name:
|
|
GTXSTRINGC "OUTPOSTgoDARKFROST"
|
|
L0401_Name:
|
|
GTXSTRINGC "PITCHoBLACK"
|
|
L0402_Name:
|
|
GTXSTRINGC "WYRMoDUSK"
|
|
L0403_Name:
|
|
GTXSTRINGC "GROMMOLD"
|
|
L0404_Name:
|
|
GTXSTRINGC "MILDEWoSTIRRING"
|
|
L0405_Name:
|
|
GTXSTRINGC "WESTGATE"
|
|
L0406_Name:
|
|
GTXSTRINGC "PIGSoINoAoBLANKET"
|
|
L0407_Name:
|
|
GTXSTRINGC "BIOS"
|
|
L0408_Name:
|
|
GTXSTRINGC "HOToVALLEYoOFoDEATH"
|
|
L0409_Name:
|
|
GTXSTRINGC "TUMBLEWEED"
|
|
L0410_Name:
|
|
GTXSTRINGC "OUTPOSTgoDRAGON"
|
|
L0411_Name:
|
|
GTXSTRINGC "THEoCELL"
|
|
L0412_Name:
|
|
GTXSTRINGC "STONEHEADoHOUSE"
|
|
L0413_Name:
|
|
L0414_Name:
|
|
L0415_Name:
|
|
GTXSTRINGC "FGB"
|
|
|
|
L0500_Name:
|
|
GTXSTRINGC "PENGUINoSMACKDOWN"
|
|
L0501_Name:
|
|
GTXSTRINGC "WINTER"
|
|
L0502_Name:
|
|
GTXSTRINGC "CHILLVILLE"
|
|
L0503_Name:
|
|
GTXSTRINGC "OLDoHOSS"
|
|
L0504_Name:
|
|
GTXSTRINGC "NORTHGATE"
|
|
L0505_Name:
|
|
GTXSTRINGC "FLOWERoTOWER"
|
|
L0506_Name:
|
|
GTXSTRINGC "SOUTHGATE"
|
|
L0507_Name:
|
|
GTXSTRINGC "WETLANDS"
|
|
L0508_Name:
|
|
GTXSTRINGC "LAaSHANDAaS"
|
|
L0509_Name:
|
|
GTXSTRINGC "OUTBACK"
|
|
L0510_Name:
|
|
GTXSTRINGC "SUMMER"
|
|
L0511_Name:
|
|
L0512_Name:
|
|
GTXSTRINGC "LAaSHANDA"
|
|
L0513_Name:
|
|
L0514_Name:
|
|
L0515_Name:
|
|
GTXSTRINGC "FGB"
|
|
|
|
L0600_Name:
|
|
GTXSTRINGC "ICEoPLAINSoeLZf"
|
|
L0601_Name:
|
|
GTXSTRINGC "ICEWOLFoRUN"
|
|
L0602_Name:
|
|
GTXSTRINGC "KINGoCHUBBAaSoHALL"
|
|
L0603_Name:
|
|
GTXSTRINGC "IGNORANToHILLoPEOPLE"
|
|
L0604_Name:
|
|
GTXSTRINGC "TOWERoOFoPAIN"
|
|
L0605_Name:
|
|
GTXSTRINGC "EASTGATE"
|
|
L0606_Name:
|
|
GTXSTRINGC "ROCKoBOTTOMoBENDeLZf"
|
|
L0607_Name:
|
|
GTXSTRINGC "SWAMPYaSoLAIR"
|
|
L0608_Name:
|
|
GTXSTRINGC "GOONoHILL"
|
|
L0609_Name:
|
|
GTXSTRINGC "LASToRESORT"
|
|
L0610_Name:
|
|
GTXSTRINGC "BITTERoROCKoPARK"
|
|
L0611_Name:
|
|
L0612_Name:
|
|
GTXSTRINGC "TELEPORToCHAMBER"
|
|
L0613_Name:
|
|
L0614_Name:
|
|
L0615_Name:
|
|
GTXSTRINGC "FGB"
|
|
|
|
L0700_Name:
|
|
GTXSTRINGC "THEoPLANEoOFoNOTHING"
|
|
L0701_Name:
|
|
GTXSTRINGC "KIWIoKEEP"
|
|
L0702_Name:
|
|
GTXSTRINGC "BAToCAVE"
|
|
L0703_Name:
|
|
GTXSTRINGC "UNDERLAKEoCAVERNS"
|
|
L0704_Name:
|
|
GTXSTRINGC "STONEHEADoCANYONeLZf"
|
|
L0705_Name:
|
|
GTXSTRINGC "MONKEYoHOLLER"
|
|
L0706_Name:
|
|
GTXSTRINGC "SWAMPLACE"
|
|
L0707_Name:
|
|
GTXSTRINGC "THEoBARROWS"
|
|
L0708_Name:
|
|
GTXSTRINGC "BLACKoSWAMPoPASSAGE"
|
|
L0709_Name:
|
|
GTXSTRINGC "HERDoLANDS"
|
|
L0710_Name:
|
|
GTXSTRINGC "DONaToSHOOToTHEoCROC"
|
|
L0711_Name:
|
|
GTXSTRINGC "SPACEoSTNoAPOCALYPSE"
|
|
L0712_Name:
|
|
GTXSTRINGC "HICKoLANDINGoeLZf"
|
|
L0713_Name:
|
|
L0714_Name:
|
|
L0715_Name:
|
|
GTXSTRINGC "FGB"
|
|
|
|
L0800_Name:
|
|
GTXSTRINGC "JACOBaSoOTHERoBRIDGE"
|
|
L0801_Name:
|
|
GTXSTRINGC "KIWIoROAD"
|
|
L0802_Name:
|
|
GTXSTRINGC "WINDYoPASS"
|
|
L0803_Name:
|
|
GTXSTRINGC "DJINNoLAKE"
|
|
L0804_Name:
|
|
GTXSTRINGC "ELDERoROCKoCANYON"
|
|
L0805_Name:
|
|
GTXSTRINGC "MONKEYoSURPRISE"
|
|
L0806_Name:
|
|
GTXSTRINGC "SCAREDIEoRUN"
|
|
L0807_Name:
|
|
GTXSTRINGC "SPIDERoMOORE"
|
|
L0808_Name:
|
|
GTXSTRINGC "CROUTONoWARoCAMP"
|
|
L0809_Name:
|
|
GTXSTRINGC "GRAPESHOT"
|
|
L0810_Name:
|
|
GTXSTRINGC "CROUTONoGRAVESoeLZf"
|
|
L0811_Name:
|
|
GTXSTRINGC "GOBLINoMODULE"
|
|
L0812_Name:
|
|
GTXSTRINGC "WARPoZONE"
|
|
L0813_Name:
|
|
L0814_Name:
|
|
L0815_Name:
|
|
GTXSTRINGC "FGB"
|
|
|
|
L0900_Name:
|
|
GTXSTRINGC "OUTPOSTgoDELTA"
|
|
L0901_Name:
|
|
GTXSTRINGC "CROUTONoSLAVEoCAMP"
|
|
L0902_Name:
|
|
GTXSTRINGC "WIZARDaSoPASSoeLZf"
|
|
L0903_Name:
|
|
GTXSTRINGC "CORNVILLE"
|
|
L0904_Name:
|
|
GTXSTRINGC "SPIDERWEEDoCANYON"
|
|
L0905_Name:
|
|
GTXSTRINGC "MONKEYoLANDINGoeLZf"
|
|
L0906_Name:
|
|
GTXSTRINGC "MOOREoGATE"
|
|
L0907_Name:
|
|
GTXSTRINGC "ARROWHEADoCITY"
|
|
L0908_Name:
|
|
GTXSTRINGC "CANNONBALL"
|
|
L0909_Name:
|
|
GTXSTRINGC "CROSSROADS"
|
|
L0910_Name:
|
|
GTXSTRINGC "WARZONE"
|
|
L0911_Name:
|
|
GTXSTRINGC "ARTILLERYoMODULE"
|
|
L0912_Name:
|
|
GTXSTRINGC "MONKEYoHOMEWORLD"
|
|
L0913_Name:
|
|
L0914_Name:
|
|
L0915_Name:
|
|
GTXSTRINGC "FGB"
|
|
|
|
L1000_Name:
|
|
GTXSTRINGC "GYROaSoBASEoCAMPeLZf"
|
|
L1001_Name:
|
|
GTXSTRINGC "CACTUSoPETE"
|
|
L1002_Name:
|
|
GTXSTRINGC "OUTPOSTgoDINGLE"
|
|
L1003_Name:
|
|
GTXSTRINGC "THEoBEACHoeLZf"
|
|
L1004_Name:
|
|
GTXSTRINGC "PUMPKINoPATCH"
|
|
L1005_Name:
|
|
GTXSTRINGC "AUTUMN"
|
|
L1006_Name:
|
|
GTXSTRINGC "OUTPOSTgoDESPAIR"
|
|
L1007_Name:
|
|
GTXSTRINGC "BUBoANDoJEB"
|
|
L1008_Name:
|
|
GTXSTRINGC "GRENADIERoGRAVEYARD"
|
|
L1009_Name:
|
|
GTXSTRINGC "BLACKoMAGIC"
|
|
L1010_Name:
|
|
GTXSTRINGC "GRENADIERoCASTLE"
|
|
L1011_Name:
|
|
GTXSTRINGC "DOCKINGoBAY"
|
|
L1012_Name:
|
|
GTXSTRINGC "MONKEYoLIBRARY"
|
|
L1013_Name:
|
|
L1014_Name:
|
|
L1015_Name:
|
|
GTXSTRINGC "FGB"
|
|
|
|
L1100_Name:
|
|
L1101_Name:
|
|
L1102_Name:
|
|
L1103_Name:
|
|
L1104_Name:
|
|
L1105_Name:
|
|
L1106_Name:
|
|
L1107_Name:
|
|
L1108_Name:
|
|
L1109_Name:
|
|
L1110_Name:
|
|
GTXSTRINGC "FGB"
|
|
L1111_Name:
|
|
GTXSTRINGC "HULKoMODULE"
|
|
L1112_Name:
|
|
GTXSTRINGC "DUKEaSoDISCO"
|
|
L1113_Name:
|
|
L1114_Name:
|
|
L1115_Name:
|
|
|
|
L1200_Name:
|
|
L1201_Name:
|
|
L1202_Name:
|
|
L1203_Name:
|
|
L1204_Name:
|
|
L1205_Name:
|
|
L1206_Name:
|
|
L1207_Name:
|
|
L1208_Name:
|
|
L1209_Name:
|
|
L1210_Name:
|
|
L1211_Name:
|
|
GTXSTRINGC "FGB"
|
|
L1212_Name:
|
|
GTXSTRINGC "THEoBESToLAIDoPLANS`"
|
|
L1213_Name:
|
|
L1214_Name:
|
|
L1215_Name:
|
|
|
|
L1300_Name:
|
|
GTXSTRINGC "BCSoAPPOMATTOX"
|
|
L1301_Name:
|
|
GTXSTRINGC "FGB"
|
|
L1302_Name:
|
|
L1303_Name:
|
|
L1304_Name:
|
|
L1305_Name:
|
|
L1306_Name:
|
|
L1307_Name:
|
|
L1308_Name:
|
|
L1309_Name:
|
|
L1310_Name:
|
|
L1311_Name:
|
|
GTXSTRINGC "FGB"
|
|
L1312_Name:
|
|
GTXSTRINGC "GOBLINoCOUNTRY"
|
|
L1313_Name:
|
|
L1314_Name:
|
|
L1315_Name:
|
|
|
|
L1400_Name:
|
|
L1401_Name:
|
|
L1402_Name:
|
|
L1403_Name:
|
|
L1404_Name:
|
|
L1405_Name:
|
|
L1406_Name:
|
|
L1407_Name:
|
|
L1408_Name:
|
|
L1409_Name:
|
|
L1410_Name:
|
|
L1411_Name:
|
|
GTXSTRINGC "FGB"
|
|
L1412_Name:
|
|
GTXSTRINGC "HIGHoNOON"
|
|
L1413_Name:
|
|
L1414_Name:
|
|
L1415_Name:
|
|
|
|
L1500_Name:
|
|
L1501_Name:
|
|
L1502_Name:
|
|
L1503_Name:
|
|
L1504_Name:
|
|
;THE KIDNAPPING!
|
|
DB ((20-STRLEN("THEoKIDNAPPING "))/2),STRLEN("THEoKIDNAPPING ")
|
|
COUNTER = 1
|
|
REPT STRLEN("THEoKIDNAPPING")
|
|
DB ((STRSUB("THEoKIDNAPPING",COUNTER,1)+145) & $ff)
|
|
COUNTER = COUNTER+1
|
|
ENDR
|
|
DB 237 ;!
|
|
L1505_Name:
|
|
GTXSTRINGC "FGB"
|
|
L1506_Name:
|
|
L1507_Name:
|
|
L1508_Name:
|
|
L1509_Name:
|
|
L1510_Name:
|
|
L1511_Name:
|
|
GTXSTRINGC "FGB"
|
|
L1512_Name:
|
|
GTXSTRINGC "GENERATORoCORE"
|
|
L1513_Name:
|
|
L1514_Name:
|
|
L1515_Name:
|
|
GTXSTRINGC "FGB"
|
|
|
|
heroNames:
|
|
DW ba_name,bs_name,haiku_name,flour_name,flower_name,grenade_name
|
|
|
|
ba_name:
|
|
GTXSTRING "BA"
|
|
bs_name:
|
|
GTXSTRING "BS"
|
|
haiku_name:
|
|
GTXSTRING "HAIKU"
|
|
flour_name:
|
|
GTXSTRING "CAPTAINoFLOUR"
|
|
flower_name:
|
|
GTXSTRING "LADYoFLOWER"
|
|
grenade_name:
|
|
GTXSTRING "KINGoGRENADE"
|
|
|
|
itemNames:
|
|
DW item000_Name,item001_Name,item002_Name,item003_Name,item004_Name
|
|
DW item005_Name,item006_Name,item007_Name,item008_Name,item009_Name
|
|
DW item010_Name,item011_Name,item012_Name,item013_Name,item014_Name
|
|
DW item015_Name,item016_Name,item017_Name,item018_Name,item019_Name
|
|
DW item020_Name,item021_Name,item022_Name
|
|
|
|
itemColors:
|
|
DB 1,1,0,0,0,0,0,1,3,1 ; 0- 9
|
|
DB 5,0,0,5,0,0,1,6,5,3 ;10-19
|
|
DB 2,4,5,0,0,0,0,0,0,0 ;20-29
|
|
;0=Grey, 1=Red, 2=Blue, 3=Green, 4=Purple, 5=Yellow, 6=Brown/Orange, 7=Fuscia
|
|
|
|
item000_Name:
|
|
ITEMSTRING 246,"SNAKEoBITEoKIT"
|
|
item001_Name:
|
|
ITEMSTRING 254,"SPOREoMASK"
|
|
item002_Name:
|
|
;ITEMSTRING 250,"CODE0400"
|
|
DB 0,0
|
|
item003_Name:
|
|
;ITEMSTRING 250,"CODE0900"
|
|
DB 0,0
|
|
item004_Name:
|
|
;ITEMSTRING 250,"CODE1002"
|
|
DB 0,0
|
|
item005_Name:
|
|
;ITEMSTRING 250,"CODE1006"
|
|
DB 0,0
|
|
item006_Name:
|
|
;ITEMSTRING 250,"CODE0410"
|
|
DB 0,0
|
|
item007_Name:
|
|
ITEMSTRING 249,"BAToJUICE"
|
|
item008_Name:
|
|
ITEMSTRING 248,"SPACEoMONEY"
|
|
item009_Name:
|
|
ITEMSTRING 247,"SPACEoSODA"
|
|
item010_Name:
|
|
ITEMSTRING 247,"HONEY"
|
|
item011_Name:
|
|
ITEMSTRING 254,"WRANGLINGoIRON"
|
|
item012_Name:
|
|
DB 0,0 ;BS Shoot Fast
|
|
item013_Name:
|
|
ITEMSTRING 253,"BUGoSPRAY"
|
|
item014_Name:
|
|
DB 0,0 ;BA High Impact Bullets
|
|
item015_Name:
|
|
;ITEMSTRING 250,"CODE0307"
|
|
DB 0,0
|
|
item016_Name:
|
|
ITEMSTRING 250,"ALPHAoCLEARANCE"
|
|
item017_Name:
|
|
ITEMSTRING 250,"BETAoCLEARANCE"
|
|
item018_Name:
|
|
ITEMSTRING 250,"GAMMAoCLEARANCE"
|
|
item019_Name:
|
|
ITEMSTRING 250,"DELTAoCLEARANCE"
|
|
item020_Name:
|
|
ITEMSTRING 250,"EPSILONoCLEARANCE"
|
|
item021_Name:
|
|
ITEMSTRING 250,"ZETAoCLEARANCE"
|
|
item022_Name:
|
|
ITEMSTRING 251,"APPOMATTOXoKEY"
|
|
|
|
|
|
SECTION "MiscSection",ROMX
|
|
;---------------------------------------------------------------------
|
|
; Routine: NewAppxLocation
|
|
; Arguments: None.
|
|
; Returns: none
|
|
; Alters: af
|
|
; Description:
|
|
;---------------------------------------------------------------------
|
|
NewAppxLocation:
|
|
push bc
|
|
push de
|
|
push hl
|
|
|
|
ld a,[curLevelStateIndex]
|
|
ld b,a
|
|
ld a,[appomattoxMapIndex]
|
|
cp b
|
|
jr nz,.checkAppear
|
|
|
|
;remove appomattox from current map
|
|
call ReceiveByte ;new map location
|
|
ld [appomattoxMapIndex],a
|
|
ld a,190
|
|
ldio [jiggleDuration],a
|
|
|
|
call FindFirstLight ;remove appx
|
|
ld c,a ;invisible wall index
|
|
ld d,0
|
|
ld a,[mapPitch]
|
|
ld e,a
|
|
ld a,b ;light index
|
|
call .drawLightRowTop
|
|
call .drawLightRowMiddle
|
|
call .drawLightRowMiddle
|
|
call .drawLightRowMiddle
|
|
call .drawLightRowMiddle
|
|
call .drawLightRowBottom
|
|
|
|
ld hl,EngineSound
|
|
call PlaySound
|
|
|
|
;link up exit to $4040 (+0 +0)
|
|
ld hl,mapExitLinks+EXIT_U*2
|
|
ld a,$40
|
|
ld [hl+],a
|
|
ld [hl],a
|
|
|
|
jr .done
|
|
|
|
.checkAppear
|
|
call ReceiveByte ;new map location
|
|
ld [appomattoxMapIndex],a
|
|
cp b ;appearing on my map
|
|
jr nz,.checkInAppx
|
|
|
|
;place appomattox on current map
|
|
ld a,190
|
|
ldio [jiggleDuration],a
|
|
|
|
call AddAppomattox
|
|
ld hl,EngineSound
|
|
call PlaySound
|
|
|
|
jr .done
|
|
|
|
.checkInAppx
|
|
ld a,b
|
|
cp $0d
|
|
jr nz,.checkAtAppxControls
|
|
|
|
;I'm inside the Appomattox!
|
|
ld a,190
|
|
ldio [jiggleDuration],a
|
|
|
|
ld hl,EngineSound
|
|
call PlaySound
|
|
|
|
ld a,[appomattoxMapIndex]
|
|
or a
|
|
jr nz,.landing
|
|
|
|
.takingOff
|
|
;link down exit to $4040 (+0 +0)
|
|
ld hl,mapExitLinks+EXIT_D*2
|
|
ld a,$40
|
|
ld [hl+],a
|
|
ld [hl],a
|
|
jr .done
|
|
|
|
.landing
|
|
;convert map index to 16-bit BCD index
|
|
ld b,a
|
|
and %1111
|
|
call NumberToBCD
|
|
ld d,a
|
|
ld a,b
|
|
swap a
|
|
and %1111
|
|
call NumberToBCD
|
|
ld e,a
|
|
|
|
ld hl,mapExitLinks+EXIT_D*2
|
|
ld [hl],e
|
|
inc hl
|
|
ld [hl],d
|
|
jr .done
|
|
|
|
.checkAtAppxControls
|
|
;if I was at the controls when my buddy took off, kick me off
|
|
cp $1e
|
|
jr nz,.done
|
|
|
|
ld hl,EngineSound
|
|
call PlaySound
|
|
|
|
ld a,$ff
|
|
ld [levelVars+6],a ;VAR_SELSTAGE in $1401
|
|
|
|
.done
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
ret
|
|
|
|
.drawLightRowTop
|
|
push hl
|
|
ld [hl+],a
|
|
inc a
|
|
ld [hl+],a
|
|
inc a
|
|
ld [hl+],a
|
|
inc a
|
|
ld [hl+],a
|
|
sub 3
|
|
pop hl
|
|
add hl,de
|
|
ret
|
|
|
|
.drawLightRowMiddle
|
|
push hl
|
|
push af
|
|
sub b
|
|
add 3
|
|
and 3
|
|
add b
|
|
ld [hl+],a
|
|
;xor a
|
|
ld a,c
|
|
ld [hl+],a
|
|
ld [hl+],a
|
|
pop af
|
|
ld [hl+],a
|
|
sub b
|
|
add 3
|
|
and 3
|
|
add b
|
|
pop hl
|
|
add hl,de
|
|
ret
|
|
|
|
.drawLightRowBottom
|
|
push hl
|
|
add 3
|
|
ld [hl+],a
|
|
dec a
|
|
ld [hl+],a
|
|
dec a
|
|
ld [hl+],a
|
|
dec a
|
|
ld [hl+],a
|
|
dec a
|
|
pop hl
|
|
add hl,de
|
|
ret
|
|
|
|
FindFirstLight:
|
|
;leaves hl at mem location of first landing light
|
|
;b = first light index, c=first appx index
|
|
;a = invisible wall index
|
|
;must exist or infinite loop!
|
|
ld bc,classInvisibleWallBG
|
|
call FindClassIndex
|
|
|
|
push af
|
|
ld bc,classLandingLightsBG
|
|
call FindClassIndex
|
|
ld b,a ;index to look for
|
|
|
|
push bc
|
|
ld bc,classAppomattoxBG
|
|
call FindClassIndex
|
|
pop bc
|
|
ld c,a
|
|
|
|
ld a,MAPBANK
|
|
ld [$ff70],a
|
|
|
|
;setup de with first out-of-bounds index
|
|
;ld a,[mapTotalSize]
|
|
;ld e,a
|
|
;ld a,[mapTotalSize+1]
|
|
;ld d,a
|
|
|
|
ld hl,map
|
|
.lookForFirstLight
|
|
ld a,[hl+]
|
|
cp b
|
|
jr nz,.lookForFirstLight
|
|
|
|
dec hl
|
|
pop af
|
|
|
|
ret
|
|
|
|
AddAppomattoxIfPresent::
|
|
push bc
|
|
ld a,[curLevelStateIndex]
|
|
ld b,a
|
|
ld a,[appomattoxMapIndex]
|
|
cp b
|
|
jr nz,.done
|
|
|
|
call AddAppomattox
|
|
|
|
.done
|
|
pop bc
|
|
ret
|
|
|
|
EngineSound:
|
|
DB 4,$00,$d7,$a9,$80
|
|
|
|
AddAppomattox:
|
|
push bc
|
|
push de
|
|
push hl
|
|
|
|
call FindFirstLight ;draw appx
|
|
ld d,0
|
|
ld a,[mapPitch]
|
|
ld e,a
|
|
ld a,c ;appx index
|
|
call .drawAppxMiddle
|
|
call .drawAppxMiddle
|
|
call .drawAppxMiddle
|
|
call .drawAppxRow
|
|
call .drawAppxRow
|
|
call .drawAppxRow
|
|
|
|
;link exit up to $1300 (appomattox interior)
|
|
ld hl,mapExitLinks+EXIT_U*2
|
|
xor a
|
|
ld [hl+],a
|
|
ld [hl],$13
|
|
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
ret
|
|
|
|
.drawAppxMiddle
|
|
push hl
|
|
inc hl
|
|
inc a
|
|
ld [hl+],a
|
|
inc a
|
|
ld [hl],a
|
|
add 2
|
|
pop hl
|
|
add hl,de
|
|
ret
|
|
|
|
.drawAppxRow
|
|
push hl
|
|
ld [hl+],a
|
|
inc a
|
|
ld [hl+],a
|
|
inc a
|
|
ld [hl+],a
|
|
inc a
|
|
ld [hl],a
|
|
inc a
|
|
pop hl
|
|
add hl,de
|
|
|
|
ret
|
|
|
|
;WARNING not in HOME section
|
|
|
|
;---------------------------------------------------------------------
|
|
; Variables
|
|
;---------------------------------------------------------------------
|
|
SECTION "UserVarsHRAM",HRAM
|
|
vblankFlag: DS 1 ;0=no interrupt, 1=vblank
|
|
vblankTemp: DS 1
|
|
vblankTimer:: DS 1
|
|
vblanksPerUpdate: DS 1
|
|
backBufferReady:: DS 1
|
|
backBufferDestHighByte:: DS 1
|
|
paletteBufferReady:: DS 1
|
|
dmaLoad:: DS 1 ;1=load bank 0, 2=load bank 1
|
|
randomLoc:: DS 1 ;ff92
|
|
jiggleDuration:: DS 1 ;ff93
|
|
temp:: DS 1 ;ff94
|
|
drawMapTemp:: DS 2 ;ff95
|
|
hblankFlag:: DS 1 ;ff97 :0 top/bottom, :1 show, :2 wave
|
|
hblankWinOn:: DS 1 ;ff98
|
|
hblankWinOff:: DS 1 ;ff99
|
|
firstMonster:: DS 1 ;ff9a
|
|
curROMBank:: DS 1 ;ff9b
|
|
updateTimer:: DS 1 ;ff9c
|
|
curObjWidthHeight:: DS 1 ;7:4 width, 3:0 height
|
|
scrollSpeed:: DS 1 ;7:4 fast speed (0,2,4,8) 3:0 slow speed
|
|
mapState:: DS 2 ;ff9f
|
|
transmitACK:: DS 1 ;ffa1
|
|
musicEnabled:: DS 1 ;ffa2
|
|
baseHorizontalOffset: DS 1 ;ffa3
|
|
|
|
samplePlaying: DS 1 ;ffa4
|
|
sampleBank: DS 1 ;ffa5
|
|
sampleAddress: DS 2 ;ffa6
|
|
sampleMask: DS 1 ;ffa8
|
|
jiggleType:: DS 1 ;ffa9
|
|
asyncRandLoc:: DS 1 ;ffaa
|
|
|
|
|
|
IF 0
|
|
;clear memory to ff
|
|
ld hl,$c000
|
|
ld bc,$0f00
|
|
;ld d,$ff
|
|
ld d,0
|
|
xor a
|
|
call MemSet
|
|
|
|
ld hl,$d000
|
|
ld bc,$1000
|
|
ld a,1
|
|
call MemSet
|
|
|
|
ld hl,$d000
|
|
ld bc,$1000
|
|
ld a,2
|
|
call MemSet
|
|
|
|
ld hl,$d000
|
|
ld bc,$1000
|
|
ld a,3
|
|
call MemSet
|
|
|
|
ld hl,$d000
|
|
ld bc,$1000
|
|
ld a,4
|
|
call MemSet
|
|
|
|
ld hl,$d000
|
|
ld bc,$1000
|
|
ld a,5
|
|
call MemSet
|
|
|
|
ld hl,$d000
|
|
ld bc,$1000
|
|
ld a,6
|
|
call MemSet
|
|
|
|
ld hl,$d000
|
|
ld bc,$0020
|
|
ld a,7
|
|
call MemSet
|
|
|
|
ld d,0
|
|
ld hl,$d020
|
|
ld bc,$0fe0
|
|
ld a,7
|
|
call MemSet
|
|
ENDC
|
|
|