def test_word_formats_hex(self): snapshot = [240] * 8 ctl = '\n'.join(( 'w 00000', ' 00000,8,b2,d2,h2,2', 'i 00008' )) ctl_parser = CtlParser() ctl_parser.parse_ctl(self.write_text_file(ctl)) disassembly = Disassembly(snapshot, ctl_parser, True, asm_hex=True) entries = disassembly.entries self.assertEqual(len(entries), 2) entry = entries[0] self.assertEqual(entry.address, 0) instructions = entry.instructions actual_instructions = [(i.address, i.operation) for i in instructions] exp_instructions = [ (0, 'DEFW %1111000011110000'), (2, 'DEFW 61680'), (4, 'DEFW $F0F0'), (6, 'DEFW $F0F0') ] self.assertEqual(exp_instructions, actual_instructions)
def test_invalid_lines(self): ctl_specs = [ (' 30000,1', 'blank directive with no containing block'), ('B 30745,15,5:X10', 'invalid integer'), ('T 30760,5,2:Y3', 'invalid integer'), ('W 30765,5,1:B4', 'invalid integer'), ('S 30770,10,T8:2', 'invalid integer'), ('C 40000,Q', 'invalid integer'), ('; @label:EDCBA=Z', 'invalid ASM directive address'), ('; @label=Z', 'invalid ASM directive declaration'), ('b 50000,20', 'extra parameters after address'), ('d 50020', 'invalid directive'), ('! 50030', 'invalid directive') ] ctls = [spec[0] for spec in ctl_specs] ctl_parser = CtlParser() ctlfile = self.write_text_file('\n'.join(ctls)) ctl_parser.parse_ctl(ctlfile) exp_warnings = [] for line_no, (ctl, error_msg) in enumerate(ctl_specs, 1): if error_msg: exp_warnings.append('WARNING: Ignoring line {} in {} ({}):'.format(line_no, ctlfile, error_msg)) warnings = self.err.getvalue().split('\n')[:-1] self.assertEqual(exp_warnings, warnings[0::2]) invalid_ctls = [spec[0] for spec in ctl_specs if spec[1]] self.assertEqual(invalid_ctls, warnings[1::2])
def test_word_formats(self): ctl = '\n'.join(( 'w 40000 Test word formats', ' 40000,10 5 default', ' 40010,b10 5 words in binary format', 'W 40020,b10,6,d2,h2 3 binary, 1 decimal, 1 hex', 'W 40030,b10,4:d4:h2 2 binary, 2 decimal, 1 hex, one line', ' 40040,10,b2,4,h4 1 binary, 2 default, 2 hex', ' 40050,10,b2:6:h2 1 binary, 3 default, 1 hex, one line', )) ctl_parser = CtlParser() ctlfile = self.write_text_file(ctl) ctl_parser.parse_ctl(ctlfile) exp_lengths = { 40010: [(None, [(None, 'b')])], 40020: [ (6, [(6, 'b')]), (2, [(2, 'd')]), (2, [(2, 'h')]) ], 40030: [(10, [(4, 'b'), (4, 'd'), (2, 'h')])], 40040: [ (2, [(2, 'b')]), (4, None), (4, [(4, 'h')]) ], 40050: [(10, [(2, 'b'), (6, None), (2, 'h')])] } self.assertEqual(exp_lengths, ctl_parser.lengths)
def test_s_directives(self): snapshot = [] ctl = '\n'.join(( 's 00000', ' 00000,4', ' 00004,b4', 'S 00008,d4', ' 00012,h8', ' 00020,40,b10,10,h10', 'S 00060,b40,10,d10,h10', ' 00100,d40,b10,10,h10', ' 00140,h60,b10,d10,40', 'S 00200,768,b256,d256,h256', ' 00968,56,16:b%10101010,40:h17', 'i 01024' )) ctl_parser = CtlParser() ctl_parser.parse_ctl(self.write_text_file(ctl)) disassembly = Disassembly(snapshot, ctl_parser, True) entries = disassembly.entries self.assertEqual(len(entries), 2) entry = entries[0] self.assertEqual(entry.address, 0) instructions = entry.instructions actual_instructions = [(i.address, i.operation) for i in instructions] exp_instructions = [ ( 0, 'DEFS 4'), ( 4, 'DEFS %00000100'), ( 8, 'DEFS 4'), ( 12, 'DEFS 8'), ( 20, 'DEFS %00001010'), ( 30, 'DEFS 10'), ( 40, 'DEFS $0A'), ( 50, 'DEFS $0A'), ( 60, 'DEFS %00001010'), ( 70, 'DEFS 10'), ( 80, 'DEFS $0A'), ( 90, 'DEFS $0A'), (100, 'DEFS %00001010'), (110, 'DEFS 10'), (120, 'DEFS $0A'), (130, 'DEFS $0A'), (140, 'DEFS %00001010'), (150, 'DEFS 10'), (160, 'DEFS $28'), (200, 'DEFS %0000000100000000'), (456, 'DEFS 256'), (712, 'DEFS $0100'), (968, 'DEFS 16,%10101010'), (984, 'DEFS 40,$11') ] self.assertEqual(exp_instructions, actual_instructions)
def test_byte_formats(self): snapshot = [42] * 75 ctl = '\n'.join(( 'b 00000', ' 00000,b5', ' 00005,b15', ' 00020,b5,2,d2,h1', 'B 00025,b5,2:d2:h1', ' 00030,h10,5:d3:b2', 'B 00040,5,b1,h2', ' 00045,5,h1,T4', ' 00050,5,b2:T3', 'T 00055,5,h2,3', 'T 00060,5,2:d3', 'T 00065,5,3,B1', 'T 00070,5,B2:h3', 'i 00075' )) ctl_parser = CtlParser() ctl_parser.parse_ctl(self.write_text_file(ctl)) disassembly = Disassembly(snapshot, ctl_parser, True) entries = disassembly.entries self.assertEqual(len(entries), 2) entry = entries[0] self.assertEqual(entry.address, 0) instructions = entry.instructions actual_instructions = [(i.address, i.operation) for i in instructions] exp_instructions = [ ( 0, 'DEFB %00101010,%00101010,%00101010,%00101010,%00101010'), ( 5, 'DEFB %00101010,%00101010,%00101010,%00101010,%00101010,%00101010,%00101010,%00101010'), (13, 'DEFB %00101010,%00101010,%00101010,%00101010,%00101010,%00101010,%00101010'), (20, 'DEFB %00101010,%00101010'), (22, 'DEFB 42,42'), (24, 'DEFB $2A'), (25, 'DEFB %00101010,%00101010,42,42,$2A'), (30, 'DEFB $2A,$2A,$2A,$2A,$2A,42,42,42,%00101010,%00101010'), (40, 'DEFB %00101010'), (41, 'DEFB $2A,$2A'), (43, 'DEFB $2A,$2A'), (45, 'DEFB $2A'), (46, 'DEFB "****"'), (50, 'DEFB %00101010,%00101010,"***"'), (55, 'DEFM $2A,$2A'), (57, 'DEFM "***"'), (60, 'DEFM "**",42,42,42'), (65, 'DEFM "***"'), (68, 'DEFM 42'), (69, 'DEFM 42'), (70, 'DEFM 42,42,$2A,$2A,$2A') ] self.assertEqual(actual_instructions, exp_instructions)
def test_s_directives(self): ctl = '\n'.join(( 's 50000 Test s/S directives', ' 50000,10', ' 50010,b10', ' 50020,d10', ' 50030,h10', 'S 50040,b20,5,d5,h5', 'S 50060,d20,b5,5,h5', 'S 50080,h20,b5,d5,5', ' 50100,20,b5,d5,5', ' 50120,20,d20:b%10001000', ' 50140,20,20:h$44', ' 50160,12,10:h10,h2:2' )) ctl_parser = CtlParser() ctlfile = self.write_text_file(ctl) ctl_parser.parse_ctl(ctlfile) exp_lengths = { 50010: [(None, [(None, 'b')])], 50020: [(None, [(None, 'd')])], 50030: [(None, [(None, 'h')])], 50040: [ (5, [(5, 'b')]), (5, [(5, 'd')]), (5, [(5, 'h')]) ], 50060: [ (5, [(5, 'b')]), (5, [(5, 'd')]), (5, [(5, 'h')]) ], 50080: [ (5, [(5, 'b')]), (5, [(5, 'd')]), (5, [(5, 'h')]) ], 50100: [ (5, [(5, 'b')]), (5, [(5, 'd')]), (5, None) ], 50120: [(20, [(20, 'd'), (136, 'b')])], 50140: [(20, [(20, None), (68, 'h')])], 50160: [ (10, [(10, None), (10, 'h')]), (2, [(2, 'h'), (2, None)]), ] } self.assertEqual(exp_lengths, ctl_parser.lengths)
def test_comments(self): ctl = '\n'.join(( '# This is a comment', 'b 32768', '% This is also a comment', 'w 32769', '; This is a comment too' )) ctl_parser = CtlParser() ctlfile = self.write_text_file(ctl) ctl_parser.parse_ctl(ctlfile) self.assertEqual(self.err.getvalue(), '') self.assertEqual({32768: 'b', 32769: 'w'}, ctl_parser.ctls)
def test_word_formats(self): snapshot = [170, 53] * 32 ctl = '\n'.join(( 'w 00000', ' 00000,4', ' 00004,b4', ' 00008,d4', 'W 00012,h4', 'W 00016,b8,2,d2,h4', ' 00024,d8,b4:2:h2', ' 00032,h8,b2:d4:2', ' 00040,8,b2,4,h2', 'W 00048,8,b2:2:h4', ' 00056,8,4', 'i 00064' )) ctl_parser = CtlParser() ctl_parser.parse_ctl(self.write_text_file(ctl)) disassembly = Disassembly(snapshot, ctl_parser, True) entries = disassembly.entries self.assertEqual(len(entries), 2) entry = entries[0] self.assertEqual(entry.address, 0) instructions = entry.instructions actual_instructions = [(i.address, i.operation) for i in instructions] exp_instructions = [ ( 0, 'DEFW 13738'), ( 2, 'DEFW 13738'), ( 4, 'DEFW %0011010110101010'), ( 6, 'DEFW %0011010110101010'), ( 8, 'DEFW 13738'), (10, 'DEFW 13738'), (12, 'DEFW $35AA'), (14, 'DEFW $35AA'), (16, 'DEFW %0011010110101010'), (18, 'DEFW 13738'), (20, 'DEFW $35AA,$35AA'), (24, 'DEFW %0011010110101010,%0011010110101010,13738,$35AA'), (32, 'DEFW %0011010110101010,13738,13738,$35AA'), (40, 'DEFW %0011010110101010'), (42, 'DEFW 13738,13738'), (46, 'DEFW $35AA'), (48, 'DEFW %0011010110101010,13738,$35AA,$35AA'), (56, 'DEFW 13738,13738'), (60, 'DEFW 13738,13738') ] self.assertEqual(actual_instructions, exp_instructions)
def test_byte_formats(self): ctl = '\n'.join(( 'b 40000 Test byte formats', ' 40000,b10 10 bytes in binary format', 'B 40010,b10,5,d3,h2 5 binary, 3 decimal, 2 hex', 'B 40020,b10,2:d3:h5 2 binary, 3 decimal, 5 hex, one line', ' 40030,10,b6,3,h1 6 binary, 3 default, 1 hex', ' 40040,10,b5:2:h3 5 binary, 2 default, 3 hex, one line', ' 40050,10,1,T9 1 default, 9 text', ' 40060,10,h4:T6 4 hex, 6 text, one line', 'T 40070,10,3,b7 3 text, 7 binary', 'T 40080,10,2:h8 2 text, 8 hex, one line', 'T 40090,10,5,B5 5 text, 5 default' )) ctl_parser = CtlParser() ctlfile = self.write_text_file(ctl) ctl_parser.parse_ctl(ctlfile) exp_lengths = { 40000: [(None, [(None, 'b')])], 40010: [ (5, [(5, 'b')]), (3, [(3, 'd')]), (2, [(2, 'h')]) ], 40020: [(10, [(2, 'b'), (3, 'd'), (5, 'h')])], 40030: [ (6, [(6, 'b')]), (3, None), (1, [(1, 'h')]) ], 40040: [(10, [(5, 'b'), (2, None), (3, 'h')])], 40050: [ (1, None), (9, [(9, 'T')]) ], 40060: [(10, [(4, 'h'), (6, 'T')])], 40070: [ (3, None), (7, [(7, 'b')]) ], 40080: [(10, [(2, None), (8, 'h')])], 40090: [ (5, None), (5, [(5, 'B')]) ], } self.assertEqual(exp_lengths, ctl_parser.lengths)
def test_invalid_lines(self): ctl_specs = [ (' 30000,1', 'blank directive with no containing block'), ('B 30745,15,5:X10', 'invalid integer'), ('T 30760,5,2:Y3', 'invalid integer'), ('W 30765,5,1:B4', 'invalid integer'), ('S 30770,10,T8:2', 'invalid integer'), ('B 30780,10,h,5', 'invalid integer'), ('C 40000,Q', 'invalid integer'), ('@ FEDCB label=Z', 'invalid ASM directive address'), ('@ 49152', 'invalid ASM directive declaration'), ('b 50000,20', 'extra parameters after address'), ('c 50000,20', 'extra parameters after address'), ('g 50000,20', 'extra parameters after address'), ('i 50000,20', 'extra parameters after address'), ('s 50000,20', 'extra parameters after address'), ('t 50000,20', 'extra parameters after address'), ('u 50000,20', 'extra parameters after address'), ('w 50000,20', 'extra parameters after address'), ('D 50000,20 Desc.', 'extra parameters after address'), ('E 50000,20 End.', 'extra parameters after address'), ('N 50000,20 Note.', 'extra parameters after address'), ('R 50000,20 A 10', 'extra parameters after address'), ('b b50010', 'invalid address'), ('d 50020', 'invalid directive'), ('! 50030', 'invalid directive'), ('@ 50000 ignoreua:g', "invalid @ignoreua directive suffix: 'g'"), ('L 51000', 'loop length not specified'), ('L 51000,10', 'loop count not specified') ] ctls = [spec[0] for spec in ctl_specs] ctl_parser = CtlParser() ctlfile = self.write_text_file('\n'.join(ctls)) ctl_parser.parse_ctl(ctlfile) exp_warnings = [] for line_no, (ctl, error_msg) in enumerate(ctl_specs, 1): if error_msg: exp_warnings.append('WARNING: Ignoring line {} in {} ({}):'.format(line_no, ctlfile, error_msg)) warnings = self.err.getvalue().split('\n')[:-1] self.assertEqual(exp_warnings, warnings[0::2]) invalid_ctls = [spec[0] for spec in ctl_specs if spec[1]] self.assertEqual(invalid_ctls, warnings[1::2])
def test_byte_formats_hex(self): snapshot = [85] * 4 ctl = '\n'.join(( 'b 00000', ' 00000,4,b1:d1:h1:1', 'i 00004' )) ctl_parser = CtlParser() ctl_parser.parse_ctl(self.write_text_file(ctl)) disassembly = Disassembly(snapshot, ctl_parser, True, asm_hex=True) entries = disassembly.entries self.assertEqual(len(entries), 2) entry = entries[0] self.assertEqual(entry.address, 0) instructions = entry.instructions self.assertEqual(len(instructions), 1) defb = instructions[0] self.assertEqual(defb.operation, 'DEFB %01010101,85,$55,$55')
def run(snafile, options): # Read the snapshot file if snafile[-4:].lower() in ('.sna', '.szx', '.z80'): snapshot = get_snapshot(snafile, options.page) start = max(START, options.start) else: ram = read_bin_file(snafile) if options.org is None: org = 65536 - len(ram) else: org = options.org snapshot = [0] * org snapshot.extend(ram) start = max(org, options.start) end = min(options.end, len(snapshot)) # Pad out the end of the snapshot to avoid disassembly errors when an # instruction crosses the 64K boundary snapshot += [0] * (65539 - len(snapshot)) if options.sftfile: # Use a skool file template info('Using skool file template: {}'.format(options.sftfile)) writer = SftParser(snapshot, options.sftfile, options.zfill, options.asm_hex, options.asm_lower) writer.write_skool(options.start, options.end) return if options.genctlfile: # Generate a control file ctls = generate_ctls(snapshot, start, end, options.code_map) write_ctl(options.genctlfile, ctls, options.ctl_hex) ctl_parser = CtlParser(ctls) elif options.ctlfile: # Use a control file info('Using control file: {}'.format(options.ctlfile)) ctl_parser = CtlParser() ctl_parser.parse_ctl(options.ctlfile, options.start, options.end) else: ctl_parser = CtlParser({start: 'c', end: 'i'}) writer = SkoolWriter(snapshot, ctl_parser, options) writer.write_skool(options.write_refs, options.text)
def run(snafile, options, config): # Read the snapshot file if snafile[-4:].lower() in ('.sna', '.szx', '.z80'): snapshot = get_snapshot(snafile, options.page) start = max(START, options.start) else: ram = read_bin_file(snafile, 65536) if options.org is None: org = 65536 - len(ram) else: org = options.org snapshot = [0] * org snapshot.extend(ram) start = max(org, options.start) end = min(options.end, len(snapshot)) snapshot += [0] * (65536 - len(snapshot)) if options.sftfile: # Use a skool file template info('Using skool file template: {}'.format(options.sftfile)) writer = SftParser(snapshot, options.sftfile, options.zfill, options.base == 16, options.case == 1) writer.write_skool(options.start, options.end) return if options.genctlfile: # Generate a control file ctls = generate_ctls(snapshot, start, end, options.code_map) write_ctl(options.genctlfile, ctls, options.ctl_hex) ctl_parser = CtlParser(ctls) elif options.ctlfile: # Use a control file info('Using control file: {}'.format(options.ctlfile)) ctl_parser = CtlParser() ctl_parser.parse_ctl(options.ctlfile, options.start, options.end) else: ctl_parser = CtlParser({start: 'c', end: 'i'}) writer = SkoolWriter(snapshot, ctl_parser, options, config) writer.write_skool(options.write_refs, options.text)
def test_s_directives_hex(self): snapshot = [] ctl = '\n'.join(( 's 00000', ' 00000,14,d2:b1,h2:128,h10:2', 'i 00014' )) ctl_parser = CtlParser() ctl_parser.parse_ctl(self.write_text_file(ctl)) disassembly = Disassembly(snapshot, ctl_parser, True, asm_hex=True) entries = disassembly.entries self.assertEqual(len(entries), 2) entry = entries[0] self.assertEqual(entry.address, 0) instructions = entry.instructions actual_instructions = [(i.address, i.operation) for i in instructions] exp_instructions = [ (0, 'DEFS 2,%00000001'), (2, 'DEFS 2,$80'), (4, 'DEFS $0A,2') ] self.assertEqual(exp_instructions, actual_instructions)
def test_parse_ctl(self): ctl_parser = CtlParser() ctlfile = self.write_text_file(CTL) ctl_parser.parse_ctl(ctlfile) exp_ctls = { 30000: 'b', 30100: 'c', 30200: 'g', 30300: 'i', 30400: 't', 30500: 'u', 30600: 'w', 30700: 's' } self.assertEqual(exp_ctls, ctl_parser.ctls) exp_subctls = { 30002: 't', 30012: 'w', 30020: 'c', 30027: None, 30050: 'b', 30055: None, 30100: None, 30200: 'b', 30210: None, 30450: 't', 30457: None, 30500: 'b', 30502: 'b', 30505: None, 30510: 'b', 30522: None, 30530: 'b', 30550: None, 30560: 'b', 30581: None, 30620: 's', 30627: None, 30720: 'b', 30730: 't', 30745: None } self.assertEqual(exp_subctls, ctl_parser.subctls) exp_titles = { 30000: 'Data at 30000', 30100: 'Routine at 30100', 30200: 'Game status buffer entry at 30200', 30300: 'Ignored block at 30300', 30400: 'Message at 30400', 30500: 'Unused block at 30500', 30600: 'Words at 30600', 30700: 'Zeroes at 30700' } self.assertEqual(exp_titles, ctl_parser.titles) exp_instruction_comments = { 30002: 'Message in the data block', 30012: None, 30020: None, 30050: 'Complex DEFB with a blank directive', 30200: "Blank directive in a 'g' block", 30450: 'Complex DEFM with a blank directive', 30500: "Blank directive in a 'u' block", 30502: None, 30510: None, 30530: None, 30560: None, 30620: None, 30720: None, 30730: None } self.assertEqual(exp_instruction_comments, ctl_parser.instruction_comments) exp_comments = { 30100: ['Description of routine at 30100'] } self.assertEqual(exp_comments, ctl_parser.comments) exp_registers = { 30100: [['A', 'Some value'], ['BC', 'Some other value']] } self.assertEqual(exp_registers, ctl_parser.registers) exp_end_comments = { 30100: ['First paragraph of the end comment for the routine at 30100', 'Second paragraph of the end comment for the routine at 30100'] } self.assertEqual(exp_end_comments, ctl_parser.end_comments) exp_lengths = { 30050: [(5, [(3, None), (2, 'T')])], 30200: [(1, None)], 30450: [(7, [(4, None), (3, 'B')])], 30510: [(3, None)], 30530: list(zip([2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 3], [None] * 11)), 30560: list(zip([6, 5, 4, 3, 2, 1], [None] * 6)), 30720: [ (1, None), (5, [(3, 'T'), (2, None)]), (2, [(1, None), (1, 'T')]), (2, [(1, None), (1, 'T')]) ], 30730: [(15, [(10, None), (5, 'B')])] } self.assertEqual(exp_lengths, ctl_parser.lengths) exp_multiline_comments = { 30012: (30026, 'This comment covers the following two sub-blocks') } self.assertEqual(exp_multiline_comments, ctl_parser.multiline_comments) exp_entry_asm_directives = { 30000: [('start', None)] } self.assertEqual(exp_entry_asm_directives, ctl_parser.entry_asm_directives) exp_instruction_asm_directives = { 30101: [('label', 'LOOP')] } self.assertEqual(exp_instruction_asm_directives, ctl_parser.instruction_asm_directives)
def _get_writer(self, snapshot, ctl, defb_size=8, defb_mod=1, zfill=False, defm_width=66, asm_hex=False, asm_lower=False): ctl_parser = CtlParser() ctl_parser.parse_ctl(self.write_text_file(ctl)) return SkoolWriter(snapshot, ctl_parser, defb_size, defb_mod, zfill, defm_width, asm_hex, asm_lower)
def test_disassembly(self): ctl_parser = CtlParser() ctl_parser.parse_ctl(self.write_text_file(DISASSEMBLY_CTL)) disassembly = Disassembly(DISASSEMBLY_SNAPSHOT, ctl_parser, True) entries = disassembly.entries self.assertEqual(len(entries), 16) # Entry #1 (32768) entry = entries[0] self.assertEqual(entry.address, 32768) self.assertEqual(entry.title, 'Routine at 32768') self.assertEqual(entry.description, ['Routine description paragraph 1.', 'Routine description paragraph 2.']) self.assertEqual(entry.ctl, 'c') self.assertEqual(entry.registers, [['A', 'Some value'], ['B', 'Some other value']]) self.assertEqual(entry.end_comment, ['Routine end comment.']) self.assertEqual(entry.start, True) self.assertEqual(entry.end, True) self.assertEqual(entry.writer, 'skoolkit.game.GameAsmWriter') self.assertEqual(entry.org, '32768') blocks = entry.blocks self.assertEqual(len(blocks), 1) block = blocks[0] self.assertEqual(block.header, None) self.assertEqual(block.comment, 'This is an instruction-level comment that spans two instructions') self.assertEqual(block.instructions, entry.instructions) self.assertEqual(block.end, 32770) instructions = entry.instructions self.assertEqual(len(instructions), 2) instruction = instructions[0] self.assertEqual(instruction.address, 32768) self.assertEqual(instruction.operation, 'XOR A') self.assertEqual(instruction.bytes, [175]) self.assertEqual(instruction.referrers, [entries[13]]) self.assertEqual(instruction.entry, entry) self.assertEqual(instruction.ctl, 'c') self.assertEqual(instruction.comment, None) self.assertEqual(instruction.asm_directives, [('label', 'START')]) # Entry #2 (32770) entry = entries[1] self.assertEqual(entry.address, 32770) self.assertEqual(entry.title, 'Message at {0}'.format(entry.address)) instructions = entry.instructions self.assertEqual(len(instructions), 2) self.assertEqual(instructions[0].operation, 'DEFM "Hi"') self.assertEqual(instructions[1].operation, 'DEFM "Lo"') # Entry #3 (32774) entry = entries[2] self.assertEqual(entry.address, 32774) self.assertEqual(entry.title, 'Yo') # Entry #4 (32776) entry = entries[3] self.assertEqual(entry.address, 32776) self.assertEqual(entry.title, 'Data block at {0}'.format(entry.address)) instructions = entry.instructions self.assertEqual(len(instructions), 4) self.assertEqual(instructions[0].operation, 'DEFB 0,0,0') self.assertEqual(instructions[3].operation, 'DEFB 0,0,0') # Entry #5 (32788) entry = entries[4] self.assertEqual(entry.address, 32788) self.assertEqual(entry.title, 'Important byte') # Entry #6 (32789) entry = entries[5] self.assertEqual(entry.address, 32789) self.assertEqual(entry.title, 'Data block at {0}'.format(entry.address)) instructions = entry.instructions self.assertEqual(len(instructions), 1) self.assertEqual(instructions[0].operation, 'DEFW 0,0') # Entry #7 (32793) entry = entries[6] self.assertEqual(entry.address, 32793) self.assertEqual(entry.title, 'Important word') # Entry #8 (32795) entry = entries[7] self.assertEqual(entry.address, 32795) self.assertEqual(entry.title, 'Game status buffer entry at {0}'.format(entry.address)) # Entry #9 (32796) entry = entries[8] self.assertEqual(entry.address, 32796) self.assertEqual(entry.title, 'Important game status buffer byte') # Entry #10 (32797) entry = entries[9] self.assertEqual(entry.address, 32797) self.assertEqual(entry.title, 'Unused') # Entry #11 (32798) entry = entries[10] self.assertEqual(entry.address, 32798) self.assertEqual(entry.title, 'Unimportant unused byte') # Entry #12 (32799) entry = entries[11] self.assertEqual(entry.address, 32799) self.assertEqual(entry.title, 'Unused') instructions = entry.instructions self.assertEqual(len(instructions), 2) self.assertEqual(instructions[0].operation, 'DEFS 5') self.assertEqual(instructions[1].operation, 'DEFS 5') # Entry #13 (32809) entry = entries[12] self.assertEqual(entry.address, 32809) self.assertEqual(entry.title, 'Block of zeroes') instructions = entry.instructions self.assertEqual(len(instructions), 3) self.assertEqual(instructions[0].operation, 'DEFS 3') self.assertEqual(instructions[1].operation, 'NOP') self.assertEqual(instructions[2].operation, 'NOP') blocks = entry.blocks self.assertEqual(len(blocks), 1) block = blocks[0] self.assertEqual(block.comment, 'A DEFS followed by two NOPs') # Entry #14 (32814) entry = entries[13] self.assertEqual(entry.address, 32814) self.assertEqual(entry.title, 'Refers to the routine at 32768') # Entry #15 (32817) entry = entries[14] self.assertEqual(entry.address, 32817) instructions = entry.instructions self.assertEqual(len(instructions), 6) self.assertEqual(instructions[0].operation, 'DEFM "Hi",1,2,3') self.assertEqual(instructions[1].operation, 'DEFB 4,5,"Lo",6') self.assertEqual(instructions[2].operation, 'DEFM "ab",1') self.assertEqual(instructions[3].operation, 'DEFM "cd",2') self.assertEqual(instructions[4].operation, 'DEFM "e",3') self.assertEqual(instructions[5].operation, 'DEFM "f",4') # Entry #16 (32837) entry = entries[15] self.assertEqual(entry.address, 32837)
def _get_ctl_parser(self, ctl, min_address=0, max_address=65536): ctl_parser = CtlParser() ctlfile = self.write_text_file(ctl) ctl_parser.parse_ctl(ctlfile, min_address, max_address) return ctl_parser