Theory of Operation - Software

 

New Program Code

Kong Junior shares a lot of base code with Donkey Kong, this too made adding the high-score save much easier, some of the patches were exactly the same. Like Kong the high-score table could support 12 character names, but was limited to only 3, so it was expanded to take the full width ( hey ! if it's there why not just use it !! )

Size Constraints

The amount of free space in Kong Junior was a little less than Donkey Kong, I removed the checksum routine from the code to cut down the code a little more. I might revisit and see about squeezing it back in.

Patches

Patching this game is a little more interesting, the boardset uses a PAL or PROM to do the ROM decoding, so the ROMs don't appear in linear order. I've included the decoding table for which ROMs appear when in the memory map.

EEPROM routines fit at $3F39 and the save/restore code at $3565. For reference the location $3565 used to contain the default high-score table that was restored on power-up. Because this is now all done in code it could simply be removed and used to store the new routines.

Full Source + Patch Comments

The source was compiled using "TASM Z80 Assembler. Version 3.1 February, 1998.
Copyright (C) 1998 Squak Valley Software"

Features Added

; --------------------------------------------------------------
; Donkey Kong Jr. High-Score save & Serial EEPROM driver
; --------------------------------------------------------------
;
; - Version 1.0
; - Another JROK production
; - Feb 6st JAN 2001
;
; Note: this code has been written purely to keep size to a
; minimum, so some of it may appear a little bizarre but it
; saves bytes.. trust me on that ;-)
;
; --------------------------------------------------------------
; - code designed for STM - M93C56 / M93C66 - serial EEPROM
; - National NM93c56A / NM93c66A <- 'A' is very important !!
; - Microchip 93lc56A / 93lc66 <- not the 'B' part
; - any other 93C56/66 device 
; - which supports 8bit read/write
; --------------------------------------------------------------
;
; Notes: with 94C66
;
; A8 is always set to '1' on read/write, this address bit is unused on
; the 93C56, with the 93c66 the data is written to $100-$1AA

;
;
;
;
; --------------------------------------------------------------
; ROM decoding Notes:
; --------------------------------------------------------------
;
;
; ROM decoding is carried out via a PAL/PROM which means the
; memory map is not ROM contiguous.
;
; This is a breakdown of the decoding of linear memory address
; space and where each ROM appears in that space.
;
;
; --------------------------------------------------------------
; Memory Order
; --------------------------------------------------------------
;
; location ROM offset
;
; 0000-1000 - 5b - 0000-0FFF
; 1000-17FF - 5c - 1000-17FF
; 1800-1FFF - 5e - 1800-1FFF
; 2000-27FF - 5c - 0000-07FF
; 2800-2FFF - 5e - 0800-0FFF
; 3000-4000 - 5b - 1000-1FFF
; 4000-47FF - 5e - 0000-07FF
; 4800-4fff - 5c - 0800-1000
; 5000-57ff - 5e - 1000-17FF
; 5800-5fff - 5c - 1800-1FFF
;
; --------------------------------------------------------------
; ROM offset order
; --------------------------------------------------------------
;
; location ROM offset
; 0000-1000 - 5b - 0000-0FFF
; 3000-4000 - 5b - 1000-1FFF
;
; 2000-27FF - 5c - 0000-07FF
; 4800-4fff - 5c - 0800-1000
; 1000-17FF - 5c - 1000-17FF
; 5800-5fff - 5c - 1800-1FFF
;
; 1800-1FFF - 5e - 1800-1FFF
; 2800-2FFF - 5e - 0800-0FFF
; 4000-47FF 5e - 0000-07FF
; 5000-57ff - 5e - 1000-17FF
;
;
; --------------------------------------------------------------
; patch into ROM 5B
; --------------------------------------------------------------
;
; $1C6 - sets on screen "high score"
; - patch to call 'restore high-scores' @$25B
; - $cd 25 0b
;
; $1CA - start location of copy changed ( $1B2 -> $1b8 ) = $b8
; $1CD - length of copy changed ( 9 bytes -> 3 bytes ) = $03
;
; $25A - old initialize HS Table now just a return ( $C9 - ret )
; $25b - new call to restore high-scores and set on-screen HS

; $25a c9 ret
; $25b cd 65 35 call 3565h ; call restore or initialize
; $25e 21 1d 61 ld hl, 611Dh
; $261 c9 ret
;
;
; $3565 - Save Scores Code
; $3F39 - EEPROM routines
;
; --------------------------------------------------------------
; Patch in to 5C
; --------------------------------------------------------------
;
; $14A6: 1E 3C <- high-score time ( 60 seconds )
; $14CD: F3 <- subract to start of initials 
;
; $15d4 - number of initials to copy to high-score table
; changed to 12 digits
;
; $15F3 - calls save_inits (ROM 5B) - jp $3567
; c3 67 35
;
;
;
; $1557: 88 68 <- high-score data end of entry area
; $1558: 75 74 for 12 digits
;
; $373D: 3F 2D <- underscore characters
; $373E: 0 2D
; $373F: 0 2D
; $3740: 0 2D
; $3741: 0 2D
; $3742: 0 2D
; $3743: 0 2D
; $3744: 0 2D
; $3745: 0 2D
; $3746: 0 3F <- end of string marker
;
; --------------------------------------------------------------
 



; --------------------------------------------------------------
; Kong Jr High Score Saver 
; --------------------------------------------------------------


INo .EQU $7C00

; 7c82 = Q2 -clock 
; 7c83 = Q3 -serial data in 
; 7c87 = Q7 -Select (hl) 
; 7c00 = ( bit 7 ) serial data out read port


; note - only bit zero of latches are used to set
; output. 
; Within the EEPROM routines
; 'l' bit zero will always be high and
; 'h' bit zero will always be low

; to save a few byts 'h' and 'l' are written to
; the latches to set output ( high or low )


.DEFINE cs_active ld ( hl ), l 
.DEFINE cs_inactive ld ( hl ), h



.org $3565

jr CHECK_HST ; $3565
jr SAVE_INITS ; $3567


; ------------------------------------------------------------------------
CHECK_HST:
; ------------------------------------------------------------------------


call enable_write ; always enable the write


; check for 1p & 2p start + 1p JUMP held down
; if all held down then reset the high-score table


ld a, ( $7d00 ) 
and $0C
ld c,a
ld a, ( $7c00 )
and $10
or c
cp $1C
jr z, RESET_HST



ld c,0 ; read
call READ_WRITE_HST ; read in the HST
ld a, ( $6100 )
cp $94 ; first byte must be $94
ret z ; 


; no checksum on this version
; just the above check to set $94 is the
; first byte of the seriall EEPROM

; jr nz, RESET_HST
; ret




; ------------------------------------------------------------------------
RESET_HST:
; ------------------------------------------------------------------------


; free 7 bytes move to $259 ( call addy )

ld hl, $6100
ld a, 1
ld c, $94
ld e, $F4



chr_next_entry:


ld ( hl ), c
inc hl
ld ( hl ), $77 ; screen address
inc hl

ld ( hl ),a ; 1st
inc hl

ld b, 4 ; spaces
cht_l0: ld ( hl ) , $10
inc hl
djnz cht_l0
; score digits
ld b, 6
cht_l1: ld ( hl ) ,0 
inc hl
djnz cht_l1

ld b, 14 ; NAME
cht_l2:
ld (hl), $10
inc hl
djnz cht_l2

ld ( hl ), $3F ; end of text char
inc hl

ld b, 4
cht_l3: ld ( hl ) , 0 ; score value
inc hl
djnz cht_l3


ld ( hl ), e ; end address
inc hl
ld ( hl ), $76
inc hl


inc c
inc c
inc e
inc e


inc a
cp 6
jr nz, chr_next_entry


; now save the HST


; ------------------------------------------------------------------------
SAVE_HS_TABLE:
; ------------------------------------------------------------------------


ld c, 1 ; read/write
;c = 0 read
;c = 1 write

; ------------------------------------------------------------------------
READ_WRITE_HST:
; ------------------------------------------------------------------------

ld de, $6100

rw_hst_lop0:
ld b,e
ld a,c
and a
jr z, dord

dowr:
ld a, ( de )
call write_a_byte

jr cntn

dord:
call get_a_byte
ld ( de ),a

cntn:

inc de
ld a,e
cp $aa ; address 0 to $AA
jr nz, rw_hst_lop0



ld a,c
and a
ret z 


ret

; ------------------------------------------------------------------------
SAVE_INITS: 
; ------------------------------------------------------------------------

; called FROM #15F3

call SAVE_HS_TABLE
ld de, $31a ; Name has been registered

ret



; ------------------------------------------------------------------------
start_bit:
; ------------------------------------------------------------------------

ld ( ix + 01 ), l ; start bit !!

; ------------------------------------------------------------------------
do_clock:
; ------------------------------------------------------------------------

ld ( ix + 00 ), l ; clock high
ld ( ix + 00 ), h ; clock low
ret


; ------------------------------------------------------------------------
send_op_code:
; ------------------------------------------------------------------------


ld hl, $7c87 ; Select l=1 h=0
ld ix, $7c82 ; Clk/Data
cs_active
call start_bit ; A reg. bit 7 & 6 = opcode 
call send_opc

send_opc:

rlca
ld ( ix + 01 ), a
jr do_clock



; ------------------------------------------------------------------------
; UPPER SECTION OF CODE
; ------------------------------------------------------------------------
.org $3f39




; ------------------------------------------------------------------------
write_a_byte:
; ------------------------------------------------------------------------

; b = address (0-255)
; a = value to write



push af
ld a, $40 ; 12 345 
call send_op_and_address
pop af
wb_sb:
call send_8_bits
cs_inactive ; signal do write

jr wait_end



; ------------------------------------------------------------------------
get_a_byte:
; ------------------------------------------------------------------------
; b = address to read 
; a = value read



ld a, $80
call send_op_and_address
push bc

ld b,8 
gb_lop0:
call do_clock ; 1st bit = dummy bit
ld a, ( INo )
rlca
rl c
djnz gb_lop0

ld a,c
xor 255
pop bc

jr we_end

; cs_inactive ; signal done
; ret


; ------------------------------------------------------------------------
send_op_and_address:
; ------------------------------------------------------------------------

call send_op_code
call start_bit ; write A8 of address
; unused on 93c56 on 93C66
; data is stored at $100->$1AA

ld a,b ; 8 remaining bits of address


; ------------------------------------------------------------------------
send_8_bits:
; ------------------------------------------------------------------------
; a = byte to send

ld b, 8
sb_lop1:
rlca
ld ( ix + 01 ), a
call do_clock
djnz sb_lop1
ret


 ------------------------------------------------------------------------
enable_write:
; ------------------------------------------------------------------------

xor a
call send_op_code

dec a ; a= 11111111
ld b,9 ; enable opcode 
call sb_lop1 ; write 9 bits
jr we_end

; ** old code ** the above saves 2 bytes ;-)
;ld a, $C0
;call send_8_bits
;call do_clock ; do a clock - does not matter state of bit
;jr we_end

;------------------------------------------------------------------------
wait_end:
;------------------------------------------------------------------------

cs_active

; when Q = low ( data=high )
; Q = high ( data=low )

we_wait:

ld a, ( INo ) ; bit7 = (0=1) (1=0) 1= EEPROM write busy
rlca
jr c, we_wait ; loop while 1

we_end:
cs_inactive ; disable EEPROM
ret


.end