1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2024-06-02 18:41:35 +00:00

Inheritance hierarchy; binding is a little less awful.

This commit is contained in:
Chris Pressey 2018-09-07 09:10:20 +01:00
parent 0b6a66fdbb
commit 8ce787a797
2 changed files with 68 additions and 48 deletions

View File

@ -20,7 +20,7 @@ import traceback
from sixtypical.parser import Parser, ParsingContext
from sixtypical.analyzer import Analyzer
from sixtypical.outputter import Outputter
from sixtypical.outputter import outputter_class_for
from sixtypical.compiler import Compiler
@ -79,25 +79,23 @@ def process_input_files(filenames, options):
if options.analyze_only:
return
outputter = Outputter(options.output_format)
start_addr = None
if options.origin is not None:
if options.origin.startswith('0x'):
outputter.set_start_addr(int(options.origin, 16))
start_addr = int(options.origin, 16)
else:
outputter.set_start_addr(int(options.origin, 10))
start_addr = int(options.origin, 10)
with open(options.output, 'wb') as fh:
# this is *awful* binding
emitter = outputter.write_prelude(fh)
compiler = Compiler(emitter)
outputter = outputter_class_for(options.output_format)(fh, start_addr=start_addr)
outputter.write_prelude()
compiler = Compiler(outputter.emitter)
compiler.compile_program(program, compilation_roster=compilation_roster)
outputter.write_postlude(emitter)
outputter.write_postlude()
if options.debug:
pprint(emitter.accum)
pprint(outputter.emitter)
else:
emitter.serialize_to(fh)
outputter.emitter.serialize_to(fh)
if __name__ == '__main__':

View File

@ -4,49 +4,71 @@ from sixtypical.emitter import Emitter, Byte, Word
class Outputter(object):
def __init__(self, output_format):
self.output_format = output_format
if output_format == 'raw':
self.start_addr = 0x0000
self.prelude = []
elif output_format == 'prg':
self.start_addr = 0xc000
self.prelude = []
elif output_format == 'c64-basic-prg':
self.start_addr = 0x0801
self.prelude = [0x10, 0x08, 0xc9, 0x07, 0x9e, 0x32,
0x30, 0x36, 0x31, 0x00, 0x00, 0x00]
elif output_format == 'vic20-basic-prg':
self.start_addr = 0x1001
self.prelude = [0x0b, 0x10, 0xc9, 0x07, 0x9e, 0x34,
0x31, 0x30, 0x39, 0x00, 0x00, 0x00]
elif output_format == 'atari2600-cart':
self.start_addr = 0xf000
self.prelude = [0x78, 0xd8, 0xa2, 0xff, 0x9a, 0xa9,
0x00, 0x95, 0x00, 0xca, 0xd0, 0xfb]
else:
raise NotImplementedError("Unknown output format: {}".format(output_format))
def __init__(self, fh, start_addr=None):
self.start_addr = self.__class__.start_addr
if start_addr is not None:
self.start_addr = start_addr
self.prelude = self.__class__.prelude
self.fh = fh
self.emitter = Emitter(self.start_addr)
def set_start_addr(self, start_addr):
self.start_addr = start_addr
def write_header(self):
pass
def write_prelude(self, fh):
def write_prelude(self):
self.write_header()
for byte in self.prelude:
self.emitter.emit(Byte(byte))
def write_postlude(self):
pass
class RawOutputter(Outputter):
start_addr = 0x0000
prelude = []
class PrgOutputter(Outputter):
start_addr = 0xc000
prelude = []
def write_header(self):
# If we are outputting a .PRG, we output the load address first.
# We don't use the Emitter for this b/c not part of addr space.
if self.output_format in ('prg', 'c64-basic-prg', 'vic20-basic-prg'):
fh.write(bytearray(Word(self.start_addr).serialize(0)))
self.fh.write(bytearray(Word(self.start_addr).serialize(0)))
emitter = Emitter(self.start_addr)
for byte in self.prelude:
emitter.emit(Byte(byte))
return emitter
class C64BasicPrgOutputter(PrgOutputter):
start_addr = 0x0801
prelude = [0x10, 0x08, 0xc9, 0x07, 0x9e, 0x32,
0x30, 0x36, 0x31, 0x00, 0x00, 0x00]
def write_postlude(self, emitter):
class Vic20BasicPrgOutputter(PrgOutputter):
start_addr = 0x1001
prelude = [0x0b, 0x10, 0xc9, 0x07, 0x9e, 0x34,
0x31, 0x30, 0x39, 0x00, 0x00, 0x00]
class Atari2600CartOutputter(Outputter):
start_addr = 0xf000
prelude = [0x78, 0xd8, 0xa2, 0xff, 0x9a, 0xa9,
0x00, 0x95, 0x00, 0xca, 0xd0, 0xfb]
def write_postlude(self):
# If we are outputting a cartridge with boot and BRK address
# at the end, pad to ROM size minus 4 bytes, and emit addresses.
if self.output_format == 'atari2600-cart':
emitter.pad_to_size(4096 - 4)
emitter.emit(Word(self.start_addr))
emitter.emit(Word(self.start_addr))
self.emitter.pad_to_size(4096 - 4)
self.emitter.emit(Word(self.start_addr))
self.emitter.emit(Word(self.start_addr))
def outputter_class_for(output_format):
return {
'raw': RawOutputter,
'prg': PrgOutputter,
'c64-basic-prg': C64BasicPrgOutputter,
'vic20-basic-prg': Vic20BasicPrgOutputter,
'atari2600-cart': Atari2600CartOutputter,
}[output_format]