Donkey Kong (NES) -- Kill Screen Fixes?

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

Post Reply
SMB2J-2Q
Posts: 154
Joined: Thu Jul 27, 2017 5:13 pm

Donkey Kong (NES) -- Kill Screen Fixes?

Post by SMB2J-2Q »

http://www.donhodges.com/how_high_can_you_get.htm (arcade version fix)
http://metopal.com/2012/03/24/porting-the-kill-screen/ (NES version)

What I would like to do is to be able to fix the NES Donkey Kong's kill screen, but what I wish to do is to base my fix on how Don Hodges did so for the arcade version which went like so, so that in the event of an overflow, such a result will not be written back to memory:

Code: Select all

000F7A  3A2962  LD A,(#6229)  ; load A with the level number
000F7D  FE04    CP #04        ; is the level number >= 4?
000F7F  3802    JR C,#0F83    ; if not, jump ahead and compute bonus normally
000F81  3E04    LD A,#04      ; if it is, then set A = 4
000F83  47      LD B,A        ; copy A into B
000F84  A7      AND A         ; clear the carry flag
000F85  17      RLA           ; rotate left the bits in A
000F86  A7      AND A         ; clear the carry flag
000F87  17      RLA           ; rotate left the bits in A
000F88  A7      AND A         ; clear the carry flag
000F89  17      RLA           ; rotate left the bits in A
000F8A  80      ADD A,B       ; A = A + B
000F8B  80      ADD A,B       ; A = A + B
000F8C  C628    ADD A,#28     ; A = A + #28 (40 decimal)
000F8E  21B062  LD HL,#62B0   ; load HL address to store the result
What his fix does, compared to the original routine: the maximum value for the bonus timer is now based on the current level number. After initially loading the level number into the A register, it now directly checks to see if said number is at, or greater than, 4. If not there yet, then the rest of the original code coming after the next three instructions that perform the new check is run like business as usual. If the level number is 4 or greater, the routine ends and the value in A will always be 4, and the bonus timer for levels 4 and beyond will always start with 8,000 points.

For your information, here is the relevant code for the NES version:

Code: Select all

; Set Y = level number, append single-tile BKG write of the level number
00CB7E  A4 54     LDY $54
00CB80  C8        INY
00CB81  20 D1 F4  JSR $F4D1
; Set sign of BCD bonus as positive (#00 - positive)
00CB84  A9 00     LDA #$00
00CB86  85 2C     STA $2C
; Set initial bonus value
; If the level number (Y) is lower than 4, load the bonus value from memory (C207[Y])
; Else, cap it at 8000 (#80 is the BCD value of the hundreds and thousands digits)
00CB88  A9 80     LDA #$80
00CB8A  88        DEY
00CB8B  C0 04     CPY #$04
00CB8D  10 03     BPL $CB92
00CB8F  B9 07 C2  LDA $C207,Y
00CB92  85 2E     STA $2E 
My idea would be to have the game check the level number before doing the calculation, in order to prevent the overflow that causes level 133 ($84) to freak out, and only use INY until we get to level 4 ($03). It may look like this:

Code: Select all

; Set Y = level number
00CB7E  A4 54     LDY $54   ; load Y with the level number
; Set initial bonus value derived from level number
; If the level number (Y) is lower than 4 ($03), load the bonus value from memory
00CB80  C9 03     CMP #03   ; are we on level 4 ($03) yet?
00CB82  B0 04     BCS $CB88 ; if not, continue with calculation
00CB84  A0 03     LDY #03   ; otherwise, load Y with 3 (for level 4)
00CB86  84 54     STY $54   ; store in $0054 to make permanent
; append single-tile BKG write of the level number
00CB88  C8        INY       ; increment level number
00CB89  20 D1 F4  JSR $F4D1
; set sign of BCD bonus as positive (#00 - positive)
00CB8C  A9 00     LDA #$00
00CB8E  85 2C     STA $2C
; set initial bonus value
00CB90  A9 80     LDA #$80
00CB92  88        DEY
00CB93  B9 07 C2  LDA $C207,Y
00CB96  85 2E     STA $2E

My question is this: which of the existing checks in the NES version's code should I get rid of to make this new fix work properly, please?

~Ben
SMB2J-2Q
Posts: 154
Joined: Thu Jul 27, 2017 5:13 pm

Re: Donkey Kong (NES) -- Kill Screen Fixes?

Post by SMB2J-2Q »

I think I have a better idea now for this kill screen fix, which now closely matches up with Hodges' fix for the arcade version:

Code: Select all

; Set Y = level number, check bonus timer value against level number (increment only if we're on level 1, 2 or 3), append single-tile BKG write of the level number
00CB7E  A4 54     LDY $54   ; load level number into Y
00CB80  C0 03     CPY #$03  ; have we reached level 4 ($03) yet?
00CB82  90 05     BCC $CB89 ; if level 1, 2 or 3 (variable $00 thru $02 in Y), continue to rest of code
00CB84  A0 03     LDY #$03  ; otherwise load Y with $03 (level 4)
00CB86  4C AC CB  JMP $CBAC ; jump to next routine without further incrementing bonus timer against level number
00CB89  C8        INY       ; increment current level number (only if we're on level 1, 2 or 3)
00CB8A  20 D3 F4  JSR $F4D3
; Set sign of BCD bonus as positive (#00 - positive)
00CB8D  A9 00     LDA #$00
00CB8F  85 2C     STA $2C
; Set initial bonus value
; If the level number (Y) is lower than 4 ($03), load the bonus value from memory (C207,Y)
; Else, cap it at 8000 (derived from level 4's variable loaded into Y)
00CB91  B9 07 C2  LDA $C207,Y
00CB94  85 2E     STA $2E
What this fixes: it takes out the original bonus timer value routine that checks it against the maximum possible value of #$80 via a negative vs. positive flag (the BPL branch), since we're now doing it based on the level number. The CPY value is one less than originally written, since the INY was written after the level number compare instructions.

~Ben
SMB2J-2Q
Posts: 154
Joined: Thu Jul 27, 2017 5:13 pm

Re: Donkey Kong (NES) -- Kill Screen Fixes?

Post by SMB2J-2Q »

I forgot that I have to respect the JSR that goes to the code for the level number display tileset, so now I have to re-write this:

Code: Select all

; Set Y = level number, check bonus timer value against level number (increment only if we're on level 1, 2 or 3), append single-tile BKG write of the level number
00CB7E  A4 54     LDY $54   ; load level number into Y
00CB80  C8        INY       ; increment current level number (only if we're on levels 1 thru 9)
00CB81  20 CE F4  JSR $F4CE ; jump to routine to check level number display tileset
00CB84  C0 04     CPY #$04  ; check if we're on level 4 yet
00CB86  B0 1F     BCS $CBA6 ; jump to end of routine if condition met
; Set sign of BCD bonus as positive (#00 - positive)
00CB88  A9 00     LDA #$00
00CB8A  85 2C     STA $2C
; Set initial bonus value
; If the level number (Y) is lower than 4 ($04), load the bonus value from memory (C207,Y)
; Else, cap it at 8000 (derived from level 4's variable loaded into Y)
00CB8C  B9 07 C2  LDA $C207,Y
00CB8F  85 2E     STA $2E
~Ben
SMB2J-2Q
Posts: 154
Joined: Thu Jul 27, 2017 5:13 pm

Re: Donkey Kong (NES) -- Kill Screen Fixes?

Post by SMB2J-2Q »

I think I might have finally provided a decent fix for the NES Donkey Kong's kill screen, again, with respect to the level number computation.

What I did this time involves: level number computation applicable only to levels 1 thru 9; and to keep checking the level number if bonus timer not yet at 8000 points (level 4+) via a backwards BCC branch. Please review these changes.

Code: Select all

; Set Y = level number, check bonus timer value against level number (increment only if we're on level 1, 2 or 3), append single-tile BKG write of the level number
00CB7E  A4 54     LDY $54   ; load level number into Y
00CB80  C8        INY       ; increment current level number (only if we're on levels 1 thru 9)
00CB84  C0 09     CPY #$09  ; check if we're on level 9 yet
00CB86  B0 15     BCS $CB9D ; jump to next part if condition met
00CB88  20 CE F4  JSR $F4D0 ; if not, jump to routine to check level number display tileset
; Set sign of BCD bonus as positive (#00 - positive)
00CB8B  A9 00     LDA #$00
00CB8D  85 2C     STA $2C
; Set initial bonus value
; If the level number (Y) is lower than 4 ($04), load the bonus value from memory (C207,Y)
; Else, cap it at 8000 (derived from level 4's variable loaded into Y)
00CB8F  A9 80     LDA #$80    ; set maximum starting bonus timer value to 8000 points
00CB91  88        DEY         ; decrement Y by one from level number variable
00CB92  C0 04     CPY #$04    ; check if we're on level 4 yet
00CB94  90 EB     BCC $CB7E   ; if not, jump back to compute different start for level number
00CB96  A0 04     LDY #$04    ; else, load 4 into Y to treat levels 4 and up as if being level 4
00CB98  B9 07 C2  LDA $C207,Y
00CB9B  85 2E     STA $2E
Thank you,



Ben
SMB2J-2Q
Posts: 154
Joined: Thu Jul 27, 2017 5:13 pm

Re: Donkey Kong (NES) -- Kill Screen Fixes?

Post by SMB2J-2Q »

I think I may have solved the bonus timer issue... perhaps we should move the DEY to after the BPL instead of it coming before CPY?

Code: Select all

; Set initial bonus value
; If the level number (Y) is lower than 4 ($04), load the bonus value from memory (C207,Y)
; Else, cap it at 8000 (derived from level 4's variable loaded into Y)
00CB8F  A9 80     LDA #$80    ; set maximum starting bonus timer value to 8000 points
00CB91  C0 03     CPY #$03    ; check if we're on level 4 yet (result zero)
00CB93  10 04     BPL $CB99   ; test N flag and branch to $CB99 if result positive
00CB95  88        DEY         ; decrement Y by one from level number variable until we're at zero (03=L1; 02=L2; 01=L3; 00=L4)
00CB96  B9 07 C2  LDA $C207,Y ; load appropriate bonus timer variable from table in $C207
00CB99  85 2E     STA $2E
The reason being, it might work just like this following argument:

Code: Select all

LDY $54    ; what is current level number?
CPY #$08   ; is it > 8?
BCS END    ; if so, skip the rest of this code
INY        ; otherwise continue incrementing (levels 1 to 7)
~Ben
Post Reply