def __init__(self, cols=NUM_COLUMNS): logging.getLogger('MC6809').disabled = True fn = os.path.join(os.path.dirname(__file__), 'coco_raaka_tu.bin') with open(fn, 'rb') as f: self.binary = f.read() self.binary = list(b'\x00' * 0x600 + self.binary) CFG_DICT = { "verbosity": None, "trace": None, } class Config(BaseConfig): RAM_START = 0x0000 RAM_END = 0x7FFF ROM_START = 0x8000 ROM_END = 0xFFFF cfg = Config(CFG_DICT) # Memory management -- defer everything to our read/write functions # memory = Memory(cfg) memory.add_read_byte_callback(self.read_memory, 0, 0xFFFF) memory.add_write_byte_callback(self.write_memory, 0, 0xFFFF) # Start of program is 0x600 # self.cpu = CPU(memory, cfg) self.still_running = False self.buffer = '' self.cols = cols
def __init__(self, cfg, periphery_class, display_callback, user_input_queue): self.cfg = cfg self.machine_api = cfg.machine_api self.periphery_class = periphery_class # "write into Display RAM" for render them in DragonTextDisplayCanvas(): self.display_callback = display_callback # Queue to send keyboard inputs to CPU Thread: self.user_input_queue = user_input_queue memory = Memory(self.cfg) self.cpu = CPU(memory, self.cfg) memory.cpu = self.cpu # FIXME try: self.periphery = self.periphery_class(self.cfg, self.cpu, memory, self.display_callback, self.user_input_queue) except TypeError as err: raise TypeError("%s - class: %s" % (err, self.periphery_class.__name__)) self.cpu_init_state = self.cpu.get_state() # Used for hard reset # from dragonpy.tests.test_base import print_cpu_state_data # print_cpu_state_data(self.cpu_init_state) self.cpu.reset() self.max_ops = self.cfg.cfg_dict["max_ops"] self.op_count = 0
class BaseCPUTestCase(BaseTestCase): UNITTEST_CFG_DICT = { "verbosity": None, "display_cycle": False, "trace": None, "bus_socket_host": None, "bus_socket_port": None, "ram": None, "rom": None, "max_ops": None, "use_bus": False, } def setUp(self): cfg = TestCfg(self.UNITTEST_CFG_DICT) memory = Memory(cfg) self.cpu = CPU(memory, cfg) memory.cpu = self.cpu # FIXME self.cpu.cc.set(0x00) def cpu_test_run(self, start, end, mem): for cell in mem: self.assertLess(-1, cell, "$%x < 0" % cell) self.assertGreater(0x100, cell, "$%x > 0xff" % cell) log.debug("memory load at $%x: %s", start, ", ".join(["$%x" % i for i in mem])) self.cpu.memory.load(start, mem) if end is None: end = start + len(mem) self.cpu.test_run(start, end) cpu_test_run.__test__ = False # Exclude from nose def cpu_test_run2(self, start, count, mem): for cell in mem: self.assertLess(-1, cell, "$%x < 0" % cell) self.assertGreater(0x100, cell, "$%x > 0xff" % cell) self.cpu.memory.load(start, mem) self.cpu.test_run2(start, count) cpu_test_run2.__test__ = False # Exclude from nose def assertMemory(self, start, mem): for index, should_byte in enumerate(mem): address = start + index is_byte = self.cpu.memory.read_byte(address) msg = "$%02x is not $%02x at address $%04x (index: %i)" % ( is_byte, should_byte, address, index) self.assertEqual(is_byte, should_byte, msg)
class BaseCPUTestCase(BaseTestCase): UNITTEST_CFG_DICT = { "verbosity":None, "display_cycle":False, "trace":None, "bus_socket_host":None, "bus_socket_port":None, "ram":None, "rom":None, "max_ops":None, "use_bus":False, } def setUp(self): cfg = TestCfg(self.UNITTEST_CFG_DICT) memory = Memory(cfg) self.cpu = CPU(memory, cfg) memory.cpu = self.cpu # FIXME self.cpu.cc.set(0x00) def cpu_test_run(self, start, end, mem): for cell in mem: self.assertLess(-1, cell, "$%x < 0" % cell) self.assertGreater(0x100, cell, "$%x > 0xff" % cell) log.debug("memory load at $%x: %s", start, ", ".join(["$%x" % i for i in mem]) ) self.cpu.memory.load(start, mem) if end is None: end = start + len(mem) self.cpu.test_run(start, end) cpu_test_run.__test__=False # Exclude from nose def cpu_test_run2(self, start, count, mem): for cell in mem: self.assertLess(-1, cell, "$%x < 0" % cell) self.assertGreater(0x100, cell, "$%x > 0xff" % cell) self.cpu.memory.load(start, mem) self.cpu.test_run2(start, count) cpu_test_run2.__test__=False # Exclude from nose def assertMemory(self, start, mem): for index, should_byte in enumerate(mem): address = start + index is_byte = self.cpu.memory.read_byte(address) msg = "$%02x is not $%02x at address $%04x (index: %i)" % ( is_byte, should_byte, address, index ) self.assertEqual(is_byte, should_byte, msg)
def __init__(self, cfg, periphery_class, display_callback, user_input_queue): self.cfg = cfg self.machine_api = cfg.machine_api self.periphery_class = periphery_class # "write into Display RAM" for render them in DragonTextDisplayCanvas(): self.display_callback = display_callback # Queue to send keyboard inputs to CPU Thread: self.user_input_queue = user_input_queue memory = Memory(self.cfg) self.cpu = CPU(memory, self.cfg) memory.cpu = self.cpu # FIXME try: self.periphery = self.periphery_class( self.cfg, self.cpu, memory, self.display_callback, self.user_input_queue ) except TypeError as err: raise TypeError("%s - class: %s" % (err, self.periphery_class.__name__)) self.cpu_init_state = self.cpu.get_state() # Used for hard reset # from dragonpy.tests.test_base import print_cpu_state_data # print_cpu_state_data(self.cpu_init_state) self.cpu.reset() self.max_ops = self.cfg.cfg_dict["max_ops"] self.op_count = 0
class Machine(object): def __init__(self, cfg, periphery_class, display_callback, user_input_queue): self.cfg = cfg self.machine_api = cfg.machine_api self.periphery_class = periphery_class # "write into Display RAM" for render them in DragonTextDisplayCanvas(): self.display_callback = display_callback # Queue to send keyboard inputs to CPU Thread: self.user_input_queue = user_input_queue memory = Memory(self.cfg) self.cpu = CPU(memory, self.cfg) memory.cpu = self.cpu # FIXME try: self.periphery = self.periphery_class( self.cfg, self.cpu, memory, self.display_callback, self.user_input_queue ) except TypeError as err: raise TypeError("%s - class: %s" % (err, self.periphery_class.__name__)) self.cpu_init_state = self.cpu.get_state() # Used for hard reset # from dragonpy.tests.test_base import print_cpu_state_data # print_cpu_state_data(self.cpu_init_state) self.cpu.reset() self.max_ops = self.cfg.cfg_dict["max_ops"] self.op_count = 0 def get_basic_program(self): program_start = self.cpu.memory.read_word(self.machine_api.PROGRAM_START_ADDR) variables_start = self.cpu.memory.read_word(self.machine_api.VARIABLES_START_ADDR) array_start = self.cpu.memory.read_word(self.machine_api.ARRAY_START_ADDR) free_space_start = self.cpu.memory.read_word(self.machine_api.FREE_SPACE_START_ADDR) program_end = variables_start - 1 variables_end = array_start - 1 array_end = free_space_start - 1 log.critical("programm code: $%04x-$%04x", program_start, program_end) log.critical("variables....: $%04x-$%04x", variables_start, variables_end) log.critical("array........: $%04x-$%04x", array_start, array_end) dump = [ value for addr, value in self.cpu.memory.iter_bytes(program_start, program_end) ] log.critical("Dump: %s", repr(dump)) log_program_dump(dump) listing = self.machine_api.program_dump2ascii_lines(dump, program_start) log.critical("Listing in ASCII:\n%s", "\n".join(listing)) return listing def inject_basic_program(self, ascii_listing): """ save the given ASCII BASIC program listing into the emulator RAM. """ program_start = self.cpu.memory.read_word( self.machine_api.PROGRAM_START_ADDR ) tokens = self.machine_api.ascii_listing2program_dump(ascii_listing) self.cpu.memory.load(program_start, tokens) log.critical("BASIC program injected into Memory.") # Update the BASIC addresses: program_end = program_start + len(tokens) self.cpu.memory.write_word(self.machine_api.VARIABLES_START_ADDR, program_end) self.cpu.memory.write_word(self.machine_api.ARRAY_START_ADDR, program_end) self.cpu.memory.write_word(self.machine_api.FREE_SPACE_START_ADDR, program_end) log.critical("BASIC addresses updated.") def hard_reset(self): self.periphery.reset() # from dragonpy.tests.test_base import print_cpu_state_data # print_cpu_state_data(self.cpu_init_state) self.cpu.set_state(self.cpu_init_state) # print_cpu_state_data(self.cpu.get_state()) self.cpu.reset() def quit(self): self.cpu.running = False
InstructionClass = PrepagedInstructions instrution_class = InstructionClass(self.cpu, instr_func) func = getattr(instrution_class, func_name) self.opcode_dict[op_code] = (op_code_data["cycles"], func) if __name__ == "__main__": from MC6809.components.cpu6809 import CPU from MC6809.tests.test_base import BaseCPUTestCase from dragonpy.Dragon32.config import Dragon32Cfg from MC6809.components.memory import Memory cmd_args = BaseCPUTestCase.UNITTEST_CFG_DICT cfg = Dragon32Cfg(cmd_args) memory = Memory(cfg) cpu = CPU(memory, cfg) for op_code, data in sorted(cpu.opcode_dict.items()): cycles, func = data if op_code > 0xff: op_code = "$%04x" % op_code else: op_code = " $%02x" % op_code print("Op %s - cycles: %2i - func: %s" % (op_code, cycles, func.__name__)) print(" --- END --- ")
def setUp(self): cfg = TestCfg(self.UNITTEST_CFG_DICT) memory = Memory(cfg) self.cpu = CPU(memory, cfg) memory.cpu = self.cpu # FIXME self.cpu.cc.set(0x00)
def __init__(self): cfg = Config(CFG_DICT) memory = Memory(cfg) self.cpu = CPU(memory, cfg)
class Machine(object): def __init__(self, cfg, periphery_class, display_callback, user_input_queue): self.cfg = cfg self.machine_api = cfg.machine_api self.periphery_class = periphery_class # "write into Display RAM" for render them in DragonTextDisplayCanvas(): self.display_callback = display_callback # Queue to send keyboard inputs to CPU Thread: self.user_input_queue = user_input_queue memory = Memory(self.cfg) self.cpu = CPU(memory, self.cfg) memory.cpu = self.cpu # FIXME try: self.periphery = self.periphery_class(self.cfg, self.cpu, memory, self.display_callback, self.user_input_queue) except TypeError as err: raise TypeError("%s - class: %s" % (err, self.periphery_class.__name__)) self.cpu_init_state = self.cpu.get_state() # Used for hard reset # from dragonpy.tests.test_base import print_cpu_state_data # print_cpu_state_data(self.cpu_init_state) self.cpu.reset() self.max_ops = self.cfg.cfg_dict["max_ops"] self.op_count = 0 def get_basic_program(self): program_start = self.cpu.memory.read_word( self.machine_api.PROGRAM_START_ADDR) variables_start = self.cpu.memory.read_word( self.machine_api.VARIABLES_START_ADDR) array_start = self.cpu.memory.read_word( self.machine_api.ARRAY_START_ADDR) free_space_start = self.cpu.memory.read_word( self.machine_api.FREE_SPACE_START_ADDR) program_end = variables_start - 1 variables_end = array_start - 1 array_end = free_space_start - 1 log.critical("programm code: $%04x-$%04x", program_start, program_end) log.critical("variables....: $%04x-$%04x", variables_start, variables_end) log.critical("array........: $%04x-$%04x", array_start, array_end) dump = [ value for addr, value in self.cpu.memory.iter_bytes( program_start, program_end) ] log.critical("Dump: %s", repr(dump)) log_program_dump(dump) listing = self.machine_api.program_dump2ascii_lines( dump, program_start) log.critical("Listing in ASCII:\n%s", "\n".join(listing)) return listing def inject_basic_program(self, ascii_listing): """ save the given ASCII BASIC program listing into the emulator RAM. """ program_start = self.cpu.memory.read_word( self.machine_api.PROGRAM_START_ADDR) tokens = self.machine_api.ascii_listing2program_dump(ascii_listing) self.cpu.memory.load(program_start, tokens) log.critical("BASIC program injected into Memory.") # Update the BASIC addresses: program_end = program_start + len(tokens) self.cpu.memory.write_word(self.machine_api.VARIABLES_START_ADDR, program_end) self.cpu.memory.write_word(self.machine_api.ARRAY_START_ADDR, program_end) self.cpu.memory.write_word(self.machine_api.FREE_SPACE_START_ADDR, program_end) log.critical("BASIC addresses updated.") def hard_reset(self): self.periphery.reset() # from dragonpy.tests.test_base import print_cpu_state_data # print_cpu_state_data(self.cpu_init_state) self.cpu.set_state(self.cpu_init_state) # print_cpu_state_data(self.cpu.get_state()) self.cpu.reset() def quit(self): self.cpu.running = False
def setUp(self): cfg = TestCfg(self.UNITTEST_CFG_DICT) memory = Memory(cfg) self.cpu = CPU(memory, cfg)
return 0 else: print('Code at {:04X} read {:02X}'.format(b, addr)) memory = Memory(cfg) # The CoCo ROM will "accidentally" write to FFFF. Just ignore that as the hardware does. memory.add_write_byte_callback(lambda a, b, c, d: 0, 0xFFFF, 0xFFFF) memory.add_write_byte_callback(write_PIA, 0xFF00, 0xFFF0) memory.add_read_byte_callback(read_PIA, 0xFF00, 0xFFF0) with open('bas12.rom', 'rb') as f: basic_rom = f.read() memory.load(0xA000, basic_rom) memory.load(0xFFF0, basic_rom[-16:]) with open('extbas11.rom', 'rb') as f: ext_rom = f.read() memory.load(0x8000, ext_rom) cpu = CPU(memory, cfg) cpu.reset() print(cpu.program_counter) #print(memory.read_byte(0xFFFF )) while True: cpu.run() cpu.irq() print(cpu.get_state())
class MC6809Example(object): def __init__(self): cfg = Config(CFG_DICT) memory = Memory(cfg) self.cpu = CPU(memory, cfg) def cpu_test_run(self, start, end, mem): assert isinstance(mem, bytearray), "given mem is not a bytearray!" print("memory load at $%x: %s", start, ", ".join(["$%x" % i for i in mem]) ) self.cpu.memory.load(start, mem) if end is None: end = start + len(mem) self.cpu.test_run(start, end) def crc32(self, data): """ Calculate a ZIP 32-bit CRC from data in memory. Origin code by Johann E. Klasek, j AT klasek at """ data_address = 0x1000 # position of the test data self.cpu.memory.load(data_address, data) # write test data into RAM self.cpu.index_x.set(data_address + len(data)) # end address addr_hi, addr_lo = divmod(data_address, 0x100) # start address self.cpu_test_run(start=0x0100, end=None, mem=bytearray([ # 0100| .ORG $100 0x10, 0xCE, 0x40, 0x00, # 0100| LDS #$4000 # 0104| CRCHH: EQU $ED # 0104| CRCHL: EQU $B8 # 0104| CRCLH: EQU $83 # 0104| CRCLL: EQU $20 # 0104| CRCINITH: EQU $FFFF # 0104| CRCINITL: EQU $FFFF # 0104| ; CRC 32 bit in DP (4 bytes) # 0104| CRC: EQU $80 0xCE, addr_hi, addr_lo, # 0104| LDU #.... ; start address in u 0x34, 0x10, # 010C| PSHS x ; end address +1 to TOS 0xCC, 0xFF, 0xFF, # 010E| LDD #CRCINITL 0xDD, 0x82, # 0111| STD crc+2 0x8E, 0xFF, 0xFF, # 0113| LDX #CRCINITH 0x9F, 0x80, # 0116| STX crc # 0118| ; d/x contains the CRC # 0118| BL: 0xE8, 0xC0, # 0118| EORB ,u+ ; XOR with lowest byte 0x10, 0x8E, 0x00, 0x08, # 011A| LDY #8 ; bit counter # 011E| RL: 0x1E, 0x01, # 011E| EXG d,x # 0120| RL1: 0x44, # 0120| LSRA ; shift CRC right, beginning with high word 0x56, # 0121| RORB 0x1E, 0x01, # 0122| EXG d,x 0x46, # 0124| RORA ; low word 0x56, # 0125| RORB 0x24, 0x12, # 0126| BCC cl # 0128| ; CRC=CRC XOR polynomic 0x88, 0x83, # 0128| EORA #CRCLH ; apply CRC polynomic low word 0xC8, 0x20, # 012A| EORB #CRCLL 0x1E, 0x01, # 012C| EXG d,x 0x88, 0xED, # 012E| EORA #CRCHH ; apply CRC polynomic high word 0xC8, 0xB8, # 0130| EORB #CRCHL 0x31, 0x3F, # 0132| LEAY -1,y ; bit count down 0x26, 0xEA, # 0134| BNE rl1 0x1E, 0x01, # 0136| EXG d,x ; CRC: restore correct order 0x27, 0x04, # 0138| BEQ el ; leave bit loop # 013A| CL: 0x31, 0x3F, # 013A| LEAY -1,y ; bit count down 0x26, 0xE0, # 013C| BNE rl ; bit loop # 013E| EL: 0x11, 0xA3, 0xE4, # 013E| CMPU ,s ; end address reached? 0x26, 0xD5, # 0141| BNE bl ; byte loop 0xDD, 0x82, # 0143| STD crc+2 ; CRC low word 0x9F, 0x80, # 0145| STX crc ; CRC high word ])) d = self.cpu.accu_d.get() x = self.cpu.index_x.get() crc32 = x * 0x10000 + d return crc32 ^ 0xFFFFFFFF def compare_crc32(self, data): if sys.version_info > (3,): data = bytes(data, encoding="ASCII") print("Compare CRC32 with: %r" % data) print("\nCreate CRC32 with binascii:") start_time = time.time() excpected_crc32 = binascii.crc32(data) & 0xffffffff duration = time.time() - start_time print("\tbinascii crc32..: $%X calculated in %.6fsec" % (excpected_crc32, duration)) print("\nCreate CRC32 with Emulated 6809 CPU:") start_time = time.time() crc32_value = self.crc32(data) duration = time.time() - start_time print("\tMC6809 crc32..: $%X calculated in %.2fsec" % (crc32_value, duration)) print() if crc32_value==excpected_crc32: print(" *** CRC32 values from 6809 and binascii are the same, ok.\n") return True else: print(" *** ERROR: CRC32 are different!\n") return False
class CoCoRaakaTu: GAME_NAME = 'coco_raaka_tu' NUM_COLUMNS = 32 @staticmethod def print_banner(): print('Raaka-Tu - 1982 for the TRS-80 Color Computer') print( 'See the disassembly: http://computerarcheology.com/CoCo/RaakaTu/') print( 'Everything you need to know: http://www.figmentfly.com/raakatu/raakatu.html' ) def __init__(self, cols=NUM_COLUMNS): logging.getLogger('MC6809').disabled = True fn = os.path.join(os.path.dirname(__file__), 'coco_raaka_tu.bin') with open(fn, 'rb') as f: self.binary = f.read() self.binary = list(b'\x00' * 0x600 + self.binary) CFG_DICT = { "verbosity": None, "trace": None, } class Config(BaseConfig): RAM_START = 0x0000 RAM_END = 0x7FFF ROM_START = 0x8000 ROM_END = 0xFFFF cfg = Config(CFG_DICT) # Memory management -- defer everything to our read/write functions # memory = Memory(cfg) memory.add_read_byte_callback(self.read_memory, 0, 0xFFFF) memory.add_write_byte_callback(self.write_memory, 0, 0xFFFF) # Start of program is 0x600 # self.cpu = CPU(memory, cfg) self.still_running = False self.buffer = '' self.cols = cols def print_char(self, c): if c == '\r' or c == '\n': self.print_flush() else: self.buffer = self.buffer + c def print_flush(self): while True: self.buffer = self.buffer.strip() if len(self.buffer) <= self.cols: print(self.buffer) self.buffer = '' return if self.buffer[self.cols] == ' ': print(self.buffer[0:self.cols]) self.buffer = self.buffer[self.cols:] else: i = self.buffer[0:self.cols].rfind(' ') if i < 0: i = self.cols print(self.buffer[:i]) self.buffer = self.buffer[i:] def show_error_message(self): '''Instead of flashing in place ''' s = '' for y in range(32): c = self.binary[0x5E0 + y] if c < 32 or c > 127 or c == 96: c = 32 s = s + chr(c) print(s.strip()) def simulate_coco_input(self): '''Get input from the user and poke it into COCO screen memory ''' for y in range(32): self.binary[0x5E0 + y] = 96 user_input = input('> ') user_input = user_input.strip().upper() p = 0x5E0 # Start of the bottom row for c in user_input: c = ord(c) if c == 32: self.binary[p] = 96 p += 1 elif c >= 65 and c <= 90: self.binary[p] = c p += 1 if p >= 0x5FF: break #for p in range(0x5E0,0x5E0+32): # print(self.binary[p]) def simulate_coco_print(self, s): '''Print a character ''' #print('##',s) self.print_char(s) def read_memory(self, _cycles, frm, addr): # This is the "print character routine. We point it to C000 then handle the # print by intercepting the routine at C000. # if addr == 0xA002: return 0xC0 if addr == 0xA003: return 0x00 if addr == 0xC000: self.simulate_coco_print(chr(self.cpu.accu_a.value)) return 0x39 # The wait-for-key calls this routine to roll the random number. Since we # are eating that spin-wait, we'll provide random numbers here. # if addr == 0x12A8: self.binary[0x1338] = random.randint(0, 255) self.cpu.accu_a.set(random.randint(0, 255)) return 0x39 # This bypasses the built in 32-column management. We'll handle word-breaks in # the print routine, which allows for any size console. # if addr == 0x89: return 0 # This is where the error message is flashed. Instead, we'll just print the error. # if addr == 0x9A5: self.show_error_message() if addr == 0x9BB: return 0x21 # BRN to avoid a loop of flashes # This is where the game gets a line of input from the user. # if addr == 0xACC or addr == 0xA63: self.simulate_coco_input() return 0x39 # This is the infinite loop when the player does a QUIT. # We'll abort the running program # if addr == 0x10B5: self.still_running = False return 0x20 # This is in RAM. # if addr <= 0x3F17: # print('.. '+hex(addr)+' @'+hex(frm)+' <'+hex(self.binary[addr])) return self.binary[addr] raise Exception('## UNHANDLED READ from=' + hex(frm) + ' destination=' + hex(addr)) def write_memory(self, _cycles, frm, addr, value): # This is RAM. # if addr <= 0x3F17: self.binary[addr] = value return raise Exception('## UNHANDLED WRITE from' + hex(frm) + ' destination=' + hex(addr) + ' value=' + hex(value)) def run_forever(self): self.cpu.program_counter.set(0x600) self.still_running = True while self.still_running: self.cpu.run()
class MC6809Example(object): def __init__(self): cfg = Config(CFG_DICT) memory = Memory(cfg) self.cpu = CPU(memory, cfg) def cpu_test_run(self, start, end, mem): assert isinstance(mem, bytearray), "given mem is not a bytearray!" print("memory load at $%x: %s", start, ", ".join(["$%x" % i for i in mem])) self.cpu.memory.load(start, mem) if end is None: end = start + len(mem) self.cpu.test_run(start, end) def crc32(self, data): """ Calculate a ZIP 32-bit CRC from data in memory. Origin code by Johann E. Klasek, j AT klasek at """ data_address = 0x1000 # position of the test data self.cpu.memory.load(data_address, data) # write test data into RAM self.cpu.index_x.set(data_address + len(data)) # end address addr_hi, addr_lo = divmod(data_address, 0x100) # start address self.cpu_test_run( start=0x0100, end=None, mem=bytearray([ # 0100| .ORG $100 0x10, 0xCE, 0x40, 0x00, # 0100| LDS #$4000 # 0104| CRCHH: EQU $ED # 0104| CRCHL: EQU $B8 # 0104| CRCLH: EQU $83 # 0104| CRCLL: EQU $20 # 0104| CRCINITH: EQU $FFFF # 0104| CRCINITL: EQU $FFFF # 0104| ; CRC 32 bit in DP (4 bytes) # 0104| CRC: EQU $80 0xCE, addr_hi, addr_lo, # 0104| LDU #.... ; start address in u 0x34, 0x10, # 010C| PSHS x ; end address +1 to TOS 0xCC, 0xFF, 0xFF, # 010E| LDD #CRCINITL 0xDD, 0x82, # 0111| STD crc+2 0x8E, 0xFF, 0xFF, # 0113| LDX #CRCINITH 0x9F, 0x80, # 0116| STX crc # 0118| ; d/x contains the CRC # 0118| BL: 0xE8, 0xC0, # 0118| EORB ,u+ ; XOR with lowest byte 0x10, 0x8E, 0x00, 0x08, # 011A| LDY #8 ; bit counter # 011E| RL: 0x1E, 0x01, # 011E| EXG d,x # 0120| RL1: 0x44, # 0120| LSRA ; shift CRC right, beginning with high word 0x56, # 0121| RORB 0x1E, 0x01, # 0122| EXG d,x 0x46, # 0124| RORA ; low word 0x56, # 0125| RORB 0x24, 0x12, # 0126| BCC cl # 0128| ; CRC=CRC XOR polynomic 0x88, 0x83, # 0128| EORA #CRCLH ; apply CRC polynomic low word 0xC8, 0x20, # 012A| EORB #CRCLL 0x1E, 0x01, # 012C| EXG d,x 0x88, 0xED, # 012E| EORA #CRCHH ; apply CRC polynomic high word 0xC8, 0xB8, # 0130| EORB #CRCHL 0x31, 0x3F, # 0132| LEAY -1,y ; bit count down 0x26, 0xEA, # 0134| BNE rl1 0x1E, 0x01, # 0136| EXG d,x ; CRC: restore correct order 0x27, 0x04, # 0138| BEQ el ; leave bit loop # 013A| CL: 0x31, 0x3F, # 013A| LEAY -1,y ; bit count down 0x26, 0xE0, # 013C| BNE rl ; bit loop # 013E| EL: 0x11, 0xA3, 0xE4, # 013E| CMPU ,s ; end address reached? 0x26, 0xD5, # 0141| BNE bl ; byte loop 0xDD, 0x82, # 0143| STD crc+2 ; CRC low word 0x9F, 0x80, # 0145| STX crc ; CRC high word ])) d = self.cpu.accu_d.get() x = self.cpu.index_x.get() crc32 = x * 0x10000 + d return crc32 ^ 0xFFFFFFFF def compare_crc32(self, data): if sys.version_info > (3, ): data = bytes(data, encoding="ASCII") print("Compare CRC32 with: %r" % data) print("\nCreate CRC32 with binascii:") start_time = time.time() excpected_crc32 = binascii.crc32(data) & 0xffffffff duration = time.time() - start_time print("\tbinascii crc32..: $%X calculated in %.6fsec" % (excpected_crc32, duration)) print("\nCreate CRC32 with Emulated 6809 CPU:") start_time = time.time() crc32_value = self.crc32(data) duration = time.time() - start_time print("\tMC6809 crc32..: $%X calculated in %.2fsec" % (crc32_value, duration)) print() if crc32_value == excpected_crc32: print( " *** CRC32 values from 6809 and binascii are the same, ok.\n") return True else: print(" *** ERROR: CRC32 are different!\n") return False