#!/usr/bin/env python # # Patches and hooks for the binary translation of GAME.EXE. # Micah Elizabeth Scott <*****@*****.**> # import sys import sbt86 import bt_common b = sbt86.DOSBinary('build/game.exe') bt_common.patch(b) bt_common.patchChips(b) bt_common.patchLoadSave(b) b.decl("#include <stdio.h>") b.patchAndHook(b.findCode('2c01 :2f a2____ a2____ b12c 32ed'), 'nop', length=1, cCode=''' sassert(false, "Unimplemented DAS instruction\\n"); ''') b.writeCodeToFile('build/bt_game.cpp', 'GameEXE')
# # We want to start with GAME.EXE since it's the only binary that knows # about the fourth robot, but we trim out most of the code via # patching. Everything that modifies the world state can be removed, # since we're just rendering the state copied from another binary. # # Micah Elizabeth Scott <*****@*****.**> # import sbt86 import bt_common import os import sys basedir = sys.argv[1] b = sbt86.DOSBinary(os.path.join(basedir, 'game.exe')) bt_common.patch(b) bt_common.patchChips(b) # Skip command line parsing b.patch('0DAB:0005', 'jmp 0x005D') # Skip reading world data b.patch('0DAB:01A3', 'jmp 0x01CE') # Skip reading circuit data b.patch('0DAB:01F0', 'jmp 0x0219') # Statically remove all main loops other than Level 1, skip video mode # initialization, and skip chip loading. We still need to be sure to
#!/usr/bin/env python3 # # Patches and hooks for the binary translation of TUT.EXE. # Micah Elizabeth Scott <*****@*****.**> # import sbt86 import bt_common import os import sys basedir = sys.argv[1] b = sbt86.DOSBinary(os.path.join(basedir, 'tut.exe')) bt_common.patch(b) #bt_common.findSelfModifyingCode(b) # Debug: Trace all IPs which access memory (for diagnosing hangs) #b.trace('rw', 'return 1;', 'printf("%04x ", ip);') b.writeCodeToFile(os.path.join(basedir, 'bt_tutorial.rs'), 'TutorialEXE')
#!/usr/bin/env python3 # # Patches and hooks for the binary translation of PLAY.EXE. # Micah Elizabeth Scott <*****@*****.**> # import sys import os import sbt86 basedir = sys.argv[1] b = sbt86.DOSBinary(os.path.join(basedir, 'play.exe')) b.writeCodeToFile(os.path.join(basedir, 'bt_play.rs'), 'PlayEXE')
#!/usr/bin/env python3 # # Patches and hooks for the binary translation of MENU.EXE. # Micah Elizabeth Scott <*****@*****.**> # import os import sys import sbt86 basedir = sys.argv[1] b = sbt86.DOSBinary(os.path.join(basedir, 'menu.exe')) # XXX: Dynamic branch, looks sound related. b.patch('010E:0778', 'nop', 2) # XXX: For now, implement screen updates by tracing the framebuffer. # Ideally we'd hook all the drawing routines, but this isn't # actually that awful. Another approach would be to poll on # a separate thread. b.decl("#include <stdio.h>") b.trace( 'w', ''' return segment == 0xB800; ''', ''' static uint32_t hit = 0; hit++; if ((hit & 0x3F) == 0) { hw->drawScreen(proc, proc->memSeg(0xB800));
#!/usr/bin/env python # # Patches and hooks for the binary translation of PLAY.EXE. # Micah Elizabeth Scott <*****@*****.**> # import sys import sbt86 b = sbt86.DOSBinary('build/play.exe') b.writeCodeToFile('build/bt_play.cpp', "play_main")
#!/usr/bin/env python3 # # Patches and hooks for the binary translation of PLAY.EXE. # Micah Elizabeth Scott <*****@*****.**> # import sys import os import sbt86 basedir = sys.argv[1] # PLAY.EXE stays resident while the other game binaries run, put it lower in memory. b = sbt86.DOSBinary(os.path.join(basedir, 'play.exe'), relocSegment=0x70) # This is marked as a default place to return control on exit assert b.isDefault == False b.isDefault = True # Break control flow every time we would be exec()'ing another EXE file. # This is a wrapper that handles changing disks if necessary. BX is a pointer # to a nul-terminated list of nul-terminated strings, forming the argv[]. b.decl('#include <string.h>') for call_site in [ '0070:003E', '0070:0044', '0070:004E', '0070:0057', ]:
#!/usr/bin/env python # # Patches and hooks for the binary translation of LAB.EXE. # Micah Elizabeth Scott <*****@*****.**> # import sys import sbt86 import bt_common b = sbt86.DOSBinary('build/lab.exe') bt_common.patch(b) bt_common.patchChips(b) bt_common.patchLoadSave(b) b.writeCodeToFile('build/bt_lab.cpp', 'LabEXE')
#!/usr/bin/env python # # Patches and hooks for the binary translation of MENU.EXE. # Micah Elizabeth Scott <*****@*****.**> # import sys import sbt86 b = sbt86.DOSBinary('build/menu.exe') # XXX: Dynamic branch, looks sound related. b.patch('010E:0778', 'nop', 2) # XXX: For now, implement screen updates by tracing the framebuffer. # Ideally we'd hook all the drawing routines, but this isn't # actually that awful. Another approach would be to poll on # a separate thread. b.decl("#include <stdio.h>") b.trace( 'w', ''' return segment == 0xB800; ''', ''' static uint32_t hit = 0; hit++; if ((hit & 0x3F) == 0) { hw->drawScreen(proc, proc->memSeg(0xB800)); } ''')
#!/usr/bin/env python # # Patches and hooks for the binary translation of TUT.EXE. # Micah Elizabeth Scott <*****@*****.**> # import sbt86 import bt_common b = sbt86.DOSBinary('build/tut.exe') bt_common.patch(b) #bt_common.findSelfModifyingCode(b) # Debug: Trace all IPs which access memory (for diagnosing hangs) #b.trace('rw', 'return 1;', 'printf("%04x ", ip);') b.writeCodeToFile('build/bt_tutorial.cpp', 'TutorialEXE')