git @ Cat's Eye Technologies SixtyPical / 8ce787a
Inheritance hierarchy; binding is a little less awful. Chris Pressey 3 years ago
2 changed file(s) with 68 addition(s) and 48 deletion(s). Raw diff Collapse all Expand all
1919
2020 from sixtypical.parser import Parser, ParsingContext
2121 from sixtypical.analyzer import Analyzer
22 from sixtypical.outputter import Outputter
22 from sixtypical.outputter import outputter_class_for
2323 from sixtypical.compiler import Compiler
2424
2525
7878 if options.analyze_only:
7979 return
8080
81 outputter = Outputter(options.output_format)
82
81 start_addr = None
8382 if options.origin is not None:
8483 if options.origin.startswith('0x'):
85 outputter.set_start_addr(int(options.origin, 16))
84 start_addr = int(options.origin, 16)
8685 else:
87 outputter.set_start_addr(int(options.origin, 10))
86 start_addr = int(options.origin, 10)
8887
8988 with open(options.output, 'wb') as fh:
90 # this is *awful* binding
91 emitter = outputter.write_prelude(fh)
92 compiler = Compiler(emitter)
89 outputter = outputter_class_for(options.output_format)(fh, start_addr=start_addr)
90 outputter.write_prelude()
91 compiler = Compiler(outputter.emitter)
9392 compiler.compile_program(program, compilation_roster=compilation_roster)
94 outputter.write_postlude(emitter)
95
93 outputter.write_postlude()
9694 if options.debug:
97 pprint(emitter.accum)
95 pprint(outputter.emitter)
9896 else:
99 emitter.serialize_to(fh)
97 outputter.emitter.serialize_to(fh)
10098
10199
102100 if __name__ == '__main__':
33
44
55 class Outputter(object):
6 def __init__(self, output_format):
7 self.output_format = output_format
8 if output_format == 'raw':
9 self.start_addr = 0x0000
10 self.prelude = []
11 elif output_format == 'prg':
12 self.start_addr = 0xc000
13 self.prelude = []
14 elif output_format == 'c64-basic-prg':
15 self.start_addr = 0x0801
16 self.prelude = [0x10, 0x08, 0xc9, 0x07, 0x9e, 0x32,
17 0x30, 0x36, 0x31, 0x00, 0x00, 0x00]
18 elif output_format == 'vic20-basic-prg':
19 self.start_addr = 0x1001
20 self.prelude = [0x0b, 0x10, 0xc9, 0x07, 0x9e, 0x34,
21 0x31, 0x30, 0x39, 0x00, 0x00, 0x00]
22 elif output_format == 'atari2600-cart':
23 self.start_addr = 0xf000
24 self.prelude = [0x78, 0xd8, 0xa2, 0xff, 0x9a, 0xa9,
25 0x00, 0x95, 0x00, 0xca, 0xd0, 0xfb]
26 else:
27 raise NotImplementedError("Unknown output format: {}".format(output_format))
6 def __init__(self, fh, start_addr=None):
7 self.start_addr = self.__class__.start_addr
8 if start_addr is not None:
9 self.start_addr = start_addr
10 self.prelude = self.__class__.prelude
11 self.fh = fh
12 self.emitter = Emitter(self.start_addr)
2813
29 def set_start_addr(self, start_addr):
30 self.start_addr = start_addr
14 def write_header(self):
15 pass
3116
32 def write_prelude(self, fh):
17 def write_prelude(self):
18 self.write_header()
19 for byte in self.prelude:
20 self.emitter.emit(Byte(byte))
3321
22 def write_postlude(self):
23 pass
24
25
26 class RawOutputter(Outputter):
27 start_addr = 0x0000
28 prelude = []
29
30
31 class PrgOutputter(Outputter):
32 start_addr = 0xc000
33 prelude = []
34
35 def write_header(self):
3436 # If we are outputting a .PRG, we output the load address first.
3537 # We don't use the Emitter for this b/c not part of addr space.
36 if self.output_format in ('prg', 'c64-basic-prg', 'vic20-basic-prg'):
37 fh.write(bytearray(Word(self.start_addr).serialize(0)))
38 self.fh.write(bytearray(Word(self.start_addr).serialize(0)))
3839
39 emitter = Emitter(self.start_addr)
40 for byte in self.prelude:
41 emitter.emit(Byte(byte))
4240
43 return emitter
41 class C64BasicPrgOutputter(PrgOutputter):
42 start_addr = 0x0801
43 prelude = [0x10, 0x08, 0xc9, 0x07, 0x9e, 0x32,
44 0x30, 0x36, 0x31, 0x00, 0x00, 0x00]
4445
45 def write_postlude(self, emitter):
46
47 class Vic20BasicPrgOutputter(PrgOutputter):
48 start_addr = 0x1001
49 prelude = [0x0b, 0x10, 0xc9, 0x07, 0x9e, 0x34,
50 0x31, 0x30, 0x39, 0x00, 0x00, 0x00]
51
52
53 class Atari2600CartOutputter(Outputter):
54 start_addr = 0xf000
55 prelude = [0x78, 0xd8, 0xa2, 0xff, 0x9a, 0xa9,
56 0x00, 0x95, 0x00, 0xca, 0xd0, 0xfb]
57
58 def write_postlude(self):
4659 # If we are outputting a cartridge with boot and BRK address
4760 # at the end, pad to ROM size minus 4 bytes, and emit addresses.
48 if self.output_format == 'atari2600-cart':
49 emitter.pad_to_size(4096 - 4)
50 emitter.emit(Word(self.start_addr))
51 emitter.emit(Word(self.start_addr))
61 self.emitter.pad_to_size(4096 - 4)
62 self.emitter.emit(Word(self.start_addr))
63 self.emitter.emit(Word(self.start_addr))
64
65
66 def outputter_class_for(output_format):
67 return {
68 'raw': RawOutputter,
69 'prg': PrgOutputter,
70 'c64-basic-prg': C64BasicPrgOutputter,
71 'vic20-basic-prg': Vic20BasicPrgOutputter,
72 'atari2600-cart': Atari2600CartOutputter,
73 }[output_format]