Skip to content

Commit

Permalink
Rework and simplify the LUA/MAME interface. Score tracking uses best …
Browse files Browse the repository at this point in the history
…score for the session and is no longer related to high score table. Simply reads P1 score from top of screen.

Remove high score table and player RAM/ROM updating.
Remove COIN end game logic.  Player can simply exit when best score achieved. Name registration no longer necessary.
  • Loading branch information
10yard committed Aug 11, 2022
1 parent 89835e8 commit 35d3b60
Show file tree
Hide file tree
Showing 15 changed files with 72 additions and 260 deletions.
1 change: 1 addition & 0 deletions build.bat
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ xcopy dkwolf\*.txt dist\dkwolf\ /Y
xcopy dkwolf\*.md dist\dkwolf\ /Y
xcopy dkwolf\plugins dist\dkwolf\plugins /S /i /Y
xcopy dkwolf\changes dist\dkwolf\changes /S /i /Y
rmdir dist\dkwolf\inp /s /Q

echo **** build the exe in virtual environment ****
venv\Scripts\pyinstaller launch.py --onefile --clean --console --icon artwork\dkafe.ico
Expand Down
1 change: 1 addition & 0 deletions build32.bat
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ xcopy dkwolf\*.txt dist\dkwolf\ /Y
xcopy dkwolf\*.md dist\dkwolf\ /Y
xcopy dkwolf\plugins dist\dkwolf\plugins /S /i /Y
xcopy dkwolf\changes dist\dkwolf\changes /S /i /Y
rmdir dist\dkwolf\inp /s /Q

echo **** build the exe in virtual environment ****
venv32\Scripts\pyinstaller launch.py --onefile --clean --console --icon artwork\dkafe.ico --name launch32
Expand Down
1 change: 1 addition & 0 deletions buildxp.bat
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ xcopy dkwolf\*.txt dist\launchxp\dkwolf\ /Y
xcopy dkwolf\*.md dist\launchxp\dkwolf\ /Y
xcopy dkwolf\plugins dist\launchxp\dkwolf\plugins /S /i /Y
xcopy dkwolf\changes dist\launchxp\dkwolf\changes /S /i /Y
rmdir dist\dkwolf\inp /s /Q

echo **** clean up
rmdir build /s /Q
Expand Down
1 change: 0 additions & 1 deletion dk_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@
CREDITS = 1 # Automatically set credits in MAME at start of game - when using interface
AUTOSTART = 1 # Automatically start the game in MAME (by simulating P1 start) when using interface
ALLOW_SKIP_INTRO = 1 # Allow the DK climb scene to be quickly skipped in game by pressing Jump button
ALLOW_COIN_TO_END_GAME = 1 # Allow push of coin during gameplay to end game immediately so score can be registered
SHOW_AWARD_PROGRESS = 1 # Show award progress when playing game (appears top of screen replacing high score)
SHOW_AWARD_TARGETS = 1 # Show award targets when playing game (appears during the DK intro/climb scene)
SHOW_HUD = 1 # Show in game HUD by default (in top right corner) and use P2 to toggle data
Expand Down
108 changes: 7 additions & 101 deletions dk_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,14 @@

COMPETE_FILE = os.path.join(ROOT_DIR, "interface", "compete.dat")

# Memory addresses for scores and players data
# 6 Bytes per score
ROM_SCORES = "0xc356c,0xc356d,0xc356e,0xc356f,0xc3570,0xc3571,0xc358e,0xc358f,0xc3590,0xc3591,0xc3592,0xc3593,0xc35b0,0xc35b1,0xc35b2,0xc35b3,0xc35b4,0xc35b5,0xc35d2,0xc35d3,0xc35d4,0xc35d5,0xc35d6,0xc35d7,0xc35f4,0xc35f5,0xc35f6,0xc35f7,0xc35f8,0xc35f9"
RAM_SCORES = "0xc6107,0xc6108,0xc6109,0xc610a,0xc610b,0xc610c,0xc6129,0xc612a,0xc612b,0xc612c,0xc612d,0xc612e,0xc614b,0xc614c,0xc614d,0xc614e,0xc614f,0xc6150,0xc616d,0xc616e,0xc616f,0xc6170,0xc6171,0xc6172,0xc618f,0xc6190,0xc6191,0xc6192,0xc6193,0xc6194"
RAM_HIGH = "0xc7641,0xc7621,0xc7601,0xc75e1,0xc75c1,0xc75a1"

# 7 bytes per score
RAM_SCORES_LONG = "0xc6107,0xc6108,0xc6109,0xc610a,0xc610b,0xc610c,0xc610d,0xc6129,0xc612a,0xc612b,0xc612c,0xc612d,0xc612e,0xc612f,0xc614b,0xc614c,0xc614d,0xc614e,0xc614f,0xc6150,0xc6151,0xc616d,0xc616e,0xc616f,0xc6170,0xc6171,0xc6172,0xc6173,0xc618f,0xc6190,0xc6191,0xc6192,0xc6193,0xc6194,0xc6194"

# 3 bytes per score with 2 digits per byte
RAM_SCORES_DOUBLE = "0xc611f,0xc611e,0xc611d,0xc6141,0xc6140,0xc613f,0xc6163,0xc6162,0xc6161,0xc6185,0xc6184,0xc6183,0xc61A7,0xc61A6,0xc61A5"
RAM_HIGH_DOUBLE = "0xc60ba,0xc60b9,0xc60b8"

# 4 bytes per score with 2 digits per byte
RAM_SCORES_DOUBLE_LONG = "0xc611f,0xc611e,0xc611d,0xc611c,0xc6141,0xc6140,0xc613f,0xc613e,0xc6163,0xc6162,0xc6161,0xc6160,0xc6185,0xc6184,0xc6183,0xc6182,0xc61a7,0xc61a6,0xc61a5,0xc61a4"
RAM_HIGH_DOUBLE_LONG = "0xc60ba,0xc60b9,0xc60b8,0xc60b7"


def lua_interface(emulator=None, rom=None, subfolder=None, score3=None, score2=None, score1=None, basic=0):
# Logic is driven by the rom name but there are exceptions were the subfolder name of a specific rom is needed.
script = None
if score3:
if rom in ("dkong", "dkongjr", "dkongpe", "dkongf", "dkongx", "dkongx11", "dkonghrd", "dkongj") and not basic:
script = "dkong.lua"

if script and score3:
if os.path.exists(COMPETE_FILE):
os.remove(COMPETE_FILE)

Expand All @@ -56,68 +42,9 @@ def lua_interface(emulator=None, rom=None, subfolder=None, score3=None, score2=N
os.environ[f"DATA_{award[0]}_K"] = format_K(str(award[1]))
os.environ[f"DATA_{award[0]}_AWARD"] = str(AWARDS[i])

# Award prizes
os.environ["DATA_AWARD1"] = str(AWARDS[2])
os.environ["DATA_AWARD2"] = str(AWARDS[1])
os.environ["DATA_AWARD3"] = str(AWARDS[0])

# Clear exising addresses
os.environ["RAM_HIGH"] = ""
os.environ["RAM_HIGH_DOUBLE"] = ""
os.environ["RAM_SCORES"] = ""
os.environ["RAM_SCORES_DOUBLE"] = ""
os.environ["ROM_SCORES"] = ""

# We are concerned with 3rd score to set the game highscore and to later establish if it was beaten.
if rom in ("dkong", "dkongjr", "dkongpe", "dkongf", "dkongx", "dkongx11", "dkonghrd", "dkongj") and not basic:

script = "dkong.lua"
score_width, double_width = 6, 6
if rom == "dkongx" or rom == "dkongx11" or subfolder == "dkongrdemo":
score_width, double_width = 7, 8
scores = [score3.zfill(score_width)] * 5

# Default memory addresses
os.environ["RAM_HIGH"] = RAM_HIGH
os.environ["RAM_HIGH_DOUBLE"] = RAM_HIGH_DOUBLE
os.environ["RAM_SCORES"] = RAM_SCORES
os.environ["RAM_SCORES_DOUBLE"] = RAM_SCORES_DOUBLE
os.environ["ROM_SCORES"] = ROM_SCORES

# Default data
os.environ["DATA_HIGH"] = format_numeric_data(scores, first_only=True)
os.environ["DATA_HIGH_DOUBLE"] = format_double_data(scores, width=double_width, first_only=True)
os.environ["DATA_SCORES"] = format_numeric_data(scores, width=score_width)
os.environ["DATA_SCORES_DOUBLE"] = format_double_data(scores, width=double_width)

# Adjustments based on ROM
if rom == "dkongf":
os.environ["ROM_SCORES"] = ""
if rom == "dkongx":
os.environ["DATA_SCORES_DOUBLE"] = \
format_double_data(scores, width=double_width, justify_single_digit_right=True)
os.environ["RAM_SCORES"] = offset_addresses(RAM_SCORES_LONG, -1)
os.environ["RAM_SCORES_DOUBLE"] = offset_addresses(RAM_SCORES_DOUBLE_LONG, 1)
os.environ["RAM_HIGH_DOUBLE"] = ""
os.environ["ROM_SCORES"] = ""
os.environ["RAM_HIGH"] = ""
if rom == "dkongx11" or subfolder == "dkongrdemo":
os.environ["RAM_HIGH_DOUBLE"] = RAM_HIGH_DOUBLE_LONG
os.environ["RAM_SCORES"] = RAM_SCORES_LONG
os.environ["RAM_SCORES_DOUBLE"] = RAM_SCORES_DOUBLE_LONG
os.environ["ROM_SCORES"] = ""
os.environ["RAM_HIGH"] = ""
return script


def offset_addresses(array, offset):
# adjust all the memory addresses in the array by a given offset
new_array = ""
for address in array.replace("\n", "").split(","):
new_array += str(int(address, 16) + offset) + ","
return new_array.strip(",")


def get_award(rom, score3, score2, score1):
# Read data from the compete.dat file to detemine if coins should be awarded to Jumpman.
try:
Expand All @@ -126,11 +53,11 @@ def get_award(rom, score3, score2, score1):
score = cf.readline().replace("\n", "")
os.remove(COMPETE_FILE)
if rom == name and score.isnumeric():
if int(score) > int(score1):
if int(score) >= int(score1):
return AWARDS[2] # Got 1st prize award
elif int(score) > int(score2):
elif int(score) >= int(score2):
return AWARDS[1] # Got 2nd prize award
elif int(score) > int(score3):
elif int(score) >= int(score3):
return AWARDS[0] # Got 3rd prize award
else:
return 0 # Got nothing
Expand All @@ -139,27 +66,6 @@ def get_award(rom, score3, score2, score1):
return 0


def format_double_data(scores, width=6, first_only=False, justify_single_digit_right=False):
data = ""
for score in scores:
score_text = (score.ljust(width), score.rjust(width))[int(justify_single_digit_right)].replace(" ", "0")
for i in range(0, width, 2):
data += str(int(score_text[i:i+2], 16)) + ","
if first_only:
break
return data.strip(",")


def format_numeric_data(top_scores, width=6, first_only=False):
data = ""
for score in top_scores:
for char in score.zfill(width)[:width]:
data += char + ","
if first_only:
break
return data.strip(",")


def format_K(number):
num = float('{:.3g}'.format(float(number)))
magnitude = 0
Expand Down
11 changes: 5 additions & 6 deletions dk_patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,16 @@ def apply_patches():
applied_patches_list = []

if is_pi():
# For Raspberry Pi, look for DK roms (and Crazy Kong) in the /boot partition
# Look for DK roms (and Crazy Kong) on the /boot partition of Pi when not found in the roms folder
# User may not have provided them at install time
for rom in DKONG_ZIP, DKONGJR_ZIP, DKONG3_ZIP, CKONG_ZIP:
if not os.path.exists(rom):
for rom_file in glob('/boot/dk*.zip'):
copy(rom_file, ROM_DIR)
for rom_file in glob('/boot/ck*.zip'):
copy(rom_file, ROM_DIR)
break
copy(f'/boot/{os.path.basename}', ROM_DIR)
if not os.path.exists(rom):
copy(f'/boot/dkafe_bin/{os.path.basename}', ROM_DIR)

if os.path.exists(DKONG_ZIP):
# Proceed with the patching
ips_files = glob(os.path.join(PATCH_DIR, "dkong*.ips"))
if ips_files:
# Read the original ZIP binary
Expand Down
1 change: 0 additions & 1 deletion dk_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,6 @@ def build_launch_command(info, basic_mode=False, launch_plugin=None, playback=Fa
# Update options
os.environ["DATA_CREDITS"] = str(CREDITS)
os.environ["DATA_AUTOSTART"] = str(AUTOSTART) if CREDITS > 0 else "0" # need credits to autostart
os.environ["DATA_ALLOW_COIN_TO_END_GAME"] = str(ALLOW_COIN_TO_END_GAME)
os.environ["DATA_ALLOW_SKIP_INTRO"] = str(ALLOW_SKIP_INTRO)
if subfolder in AUTOSTART_UNFRIENDLY:
os.environ["DATA_AUTOSTART"] = "0"
Expand Down
3 changes: 1 addition & 2 deletions dkwolf/readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ o888ooo88 o888o o888o o88o o888o o888o o888ooo8888
Notes on DKWolf
---------------

DKWolf is a custom build of WolfMAME built for DKAFE which supports only Donkey Kong drivers.
It a lightweight emulator with reduced size and functionality removed for save and load states, cheats, throttling etc.
DKWolf is a custom lightweight build of WolfMAME which supports only Donkey Kong drivers.

The code changes for WolfMAME 0.196, 0.236 and 0.241 are included in the "changes" folder.

Expand Down
67 changes: 26 additions & 41 deletions interface/dkong.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ ooooooooo oooo oooo o ooooooooooo ooooooooooo
o888ooo88 o888o o888o o88o o888o o888o o888ooo8888
by Jon Wilson (10yard)
Interface routine for Donkey Kong
--------------------------------------------------------------
Set target score and player scores.
Dump highscore to file when finished.
Show prizes and progress in the game (optional).
DKAFE Interface routine for Donkey Kong
--------------------------------------------------------------
]]

Expand All @@ -25,75 +21,64 @@ emu.register_frame(function()
_, loaded = pcall(get_loaded)

if loaded == nil then
-- Update ROM on start
emu["loaded"] = 1
for key, value in pairs(rom_scores) do
mem:write_direct_u8(value, data_scores[key])
-- Wait for ROM to start
if emu.romname() == "dkongx" and mem:read_u8(0xc600a) ~= 1 then
-- Speed through the power up self test
max_frameskip(true)
else
emu["loaded"] = 1
end
end

if loaded == 1 then
-- Skip past startup screen of DK2 when required
max_frameskip(data_allow_skip_intro == "1" and emu.romname() == "dkongx")
max_frameskip(false)

-- Update RAM when ready
if emu.romname() ~= "dkongx" or mem:read_u8("0xc0000") < 0 then
emu["loaded"] = 2
for key, value in pairs(ram_high) do
mem:write_u8(value, data_high[key])
end
for key, value in pairs(ram_high_DOUBLE) do
mem:write_u8(value, data_high_DOUBLE[key])
end
for key, value in pairs(ram_scores) do
mem:write_u8(value, data_scores[key])
end
for key, value in pairs(ram_scores_DOUBLE) do
mem:write_u8(value, data_scores_DOUBLE[key])
end
end
end
-- Reset P1 best score for this session
best_score = 0

if loaded == 2 then
-- Insert coins automatically when required
if tonumber(data_credits) > 0 and tonumber(data_credits) < 90 then
mem:write_u8(0x6001, data_credits)
end

-- Start game automatically when required
if data_autostart == "1" then
ports[":IN2"].fields["1 Player Start"]:set_value(1)
end
emu["loaded"] = 3
emu["loaded"] = 2
emu.register_frame_done(dkong_overlay, "frame")
end

if loaded == 3 then
if loaded == 2 then
mode1 = mem:read_u8(0xc6005) -- 1-attract mode, 2-credits entered waiting to start, 3-when playing game
mode2 = mem:read_u8(0xc600a) -- Status of note: 7-climb scene, 10-how high, 15-dead, 16-game over
stage = mem:read_u8(0xc6227) -- 1-girders, 2-pie, 3-elevator, 4-rivets, 5-extra/bonus
score = get_score()

-- Release P1 START button (after autostart)
if data_autostart == "1" and mode1 == 3 then
ports[":IN2"].fields["1 Player Start"]:set_value(0)
data_autostart = "0"
if mode1 == 3 and last_mode1 == 3 then
-- Keep track of best P1 score achieved this session
if score > best_score then
best_score = score
end

-- Release P1 START button (after autostart)
if data_autostart == "1" then
ports[":IN2"].fields["1 Player Start"]:set_value(0)
data_autostart = "0"
end
end

-- Player can skip through the DK climb scene by pressing JUMP button
fast_skip_intro()

-- Player can end game early by pressing COIN button
if mode1 == 3 and data_coin_ends == "1" and string.sub(int_to_bin(mem:read_u8(0xc7d00)), 1, 1) == "1" then
mem:write_u8(0xc6228, 1)
mem:write_u8(0xc6200, 0)
end
last_mode1 = mode1
end
end)

-- Callback function for frame updates
------------------------------------------------------------------------------------------------
function dkong_overlay()
-- Show award targets and progress during gameplay (optional)
-- Show award targets and progress during gameplay
display_awards()
end

Expand Down
Loading

0 comments on commit 35d3b60

Please sign in to comment.