Friday, January 8, 2021

Dragon's Lair's software watchdog

I've been rewriting Daphne's Z80 emulator (from scratch) and testing it on Dragon's Lair.  I've got it far enough along so that it loops at the disc routine at 0x231 waiting for an LD-V1000 strobe.  While I had it looping, I was checking out some performance metrics to see how fast my new Z80 emu was running.  To my shock, after about 1 minute, program execution moved away from that endless loop.  After a few hours of tracking down why, I discovered this software watchdog that I never knew existed.


(my disassembly below)

ROM:19E3 DecrementWatchdog:                      ; CODE XREF: IRQ+1BC↑j
ROM:19E3                 ld      hl, A0DE_WatchDogCounter
ROM:19E6                 call    DecrementMem16  ; Decrements a 16-bit memory location
ROM:19E6                                         ; Flags are set according to SBC rules.
ROM:19E6                                         ; HL: pointer to 16-bit memory value
ROM:19E6                                         ; DE and BC are clobbered
ROM:19E9                 jr      nc, CheckSoundThenExitIrq
ROM:19EB                 jp      DoSoftReset     ; watchdog has not been fed. we're stuck in an endless loop.


ROM:1FCF DoSoftReset:                            ; CODE XREF: IRQ+1CB↑j
ROM:1FCF                 ld      sp, 0A3FFh      ; blow away all stack info; start over.
ROM:1FD2                 ld      hl, 0A030h
ROM:1FD5                 ld      de, 0A031h
ROM:1FD8                 ld      bc, 3CFh
ROM:1FDB                 ld      (hl), 0
ROM:1FDD                 ldir                    ; this appears to clear mosts of the game data except the boot-up stuff
ROM:1FDF                 call    ResetWatchdogCounter ; resets watchdog counter back to max value (about 70 seconds)
ROM:1FDF                                         ; (this must be called regularly to avoid a soft system reset)
ROM:1FE2                 ei
ROM:1FE3                 jp      loc_1244        ; this is an alternative to "RETI"; essentially giving up on recovering


ROM:1C2D ; =============== S U B R O U T I N E =======================================
ROM:1C2D
ROM:1C2D ; resets watchdog counter back to max value (about 70 seconds)
ROM:1C2D ; (this must be called regularly to avoid a soft system reset)
ROM:1C2D
ROM:1C2D ResetWatchdogCounter:                   ; CODE XREF: START+10↑p
ROM:1C2D                                         ; sub_15B4+F5↑p ...
ROM:1C2D                 ld      hl, 8AAh
ROM:1C30                 ld      (A0DE_WatchDogCounter), hl
ROM:1C33                 ret
ROM:1C33 ; End of function ResetWatchdogCounter
ROM:1C33
ROM:1C34
ROM:1C34 ; =============== S U B R O U T I N E =======================================