Monday, July 17, 2017

Esh bug explained

In my previous blog post, I mentioned that there is a bug on Esh's Aurunmilla stage 7.  The bug is that if you lose all of your lives, the game over screen does not play properly.

The reason for this is that the game over screen starts at picture number 23253, and Esh's mistakenly tells the laserdisc player to autostop once it reaches picture number 23247 which is before the game over section starts.

The incorrect autostop picture number, 23247, is stored as hex 0x5ACF at memory location $215E in the Esh ROM.

Friday, July 14, 2017

Where Esh's Aurunmilla stores its 'current stage'

There's been some discussion about an Esh's Aurunmilla bug that shows up on stage 7.

Out of curiosity, I dug into the ROM program a little bit to see how hard it would be to modify the program to start on stage 7 to make testing easier.  After all, no one wants to play all the way to stage 7 just to test a fix!

I found that the stage value is stored at 0xE424 + whatever value is at 0xE3C1.  Here is code at 0x3d06 that prints out the current stage (before each stage):

seg000:3D06 print_current_stage:                    ; CODE XREF: seg000:3B4C p
seg000:3D06                 push    af
seg000:3D07                 push    bc
seg000:3D08                 push    de
seg000:3D09                 push    hl
seg000:3D0A                 call    sub_0_BC7
seg000:3D0D                 ld      a, 1
seg000:3D0F                 call    sub_0_3AAC
seg000:3D12                 ld      b, 1
seg000:3D14                 ld      hl, stage_number_txt
seg000:3D17                 call    pre_print_text
seg000:3D1A                 ld      hl, 0E424h      ; prepare to load current stage data
seg000:3D1D                 ld      a, (0E3C1h)     ; load optional offset
seg000:3D20                 ld      c, a
seg000:3D21                 ld      b, 0
seg000:3D23                 add     hl, bc          ; HL now contains address that contains stage value
seg000:3D24                 ld      l, (hl)         ; load stage value into L
seg000:3D25                 ld      h, 0
seg000:3D27                 ld      b, 14h
seg000:3D29                 ld      c, 0Eh
seg000:3D2B                 ld      e, 3            ; 3 digits for the stage number
seg000:3D2D while_stage_not_printed:                ; CODE XREF: print_current_stage+3D j
seg000:3D2D                 push    bc
seg000:3D2E                 ld      b, 10           ; base 10 conversion
seg000:3D30                 call    hex2dec         ; Hex conversion
seg000:3D30                                         ; Src number is in HL.
seg000:3D30                                         ; Base will in B (ie 10 for base 10 conversion).
seg000:3D30                                         ; Returns the lowermost digit in A and HL will be have been divided by the base (ie if HL originally contained 3387 decimal, it will return as 338 decimal with 7 in A).
seg000:3D30                                         ;
seg000:3D33                 pop     bc
seg000:3D34                 push    de
seg000:3D35                 add     a, 30h ; '0'    ; convert to ASCII?
seg000:3D37                 ld      d, a
seg000:3D38                 ld      e, 9
seg000:3D3A                 ld      a, 1
seg000:3D3C                 call    print_letter    ; prints one letter to the screen
seg000:3D3F                 pop     de
seg000:3D40                 dec     b
seg000:3D41                 dec     b
seg000:3D42                 dec     e               ; decrement digits left count
seg000:3D43                 jr      nz, while_stage_not_printed
seg000:3D45                 pop     hl
seg000:3D46                 pop     de
seg000:3D47                 pop     bc
seg000:3D48                 pop     af
seg000:3D49                 ret

The stage value is incremented around 0xD7D:

seg000:0D7D loc_0_D7D:                              ; CODE XREF: seg000:0D6A j
seg000:0D7D                                         ; seg000:0D79 j
seg000:0D7D                 ld      hl, 0E424h      ; base address where current stage lives
seg000:0D80                 ld      a, (0E3C1h)
seg000:0D83                 and     a
seg000:0D84                 jr      z, loc_0_D87    ; this can increment the current stage
seg000:0D86                 inc     hl
seg000:0D87 loc_0_D87:                              ; CODE XREF: seg000:0D84 j
seg000:0D87                 inc     (hl)            ; this can increment the current stage

The stage value is initially set at:

seg000:0E69                 ld      hl, 0
seg000:0E6C                 ld      (0E424h), hl    ; set current stage to be 0

So to force the game to start on stage 7 instead of 0, one must do this:

Change the "ld hl,0" at 0xE69 to "ld hl,7".  Or change 0x21 0x00 0x00 to 0x21 0x07 0x00.