diff --git a/pymlac/Display.py b/pymlac/Display.py index 73487d6..ce67fbb 100644 --- a/pymlac/Display.py +++ b/pymlac/Display.py @@ -54,6 +54,9 @@ class _BufferedCanvas(wx.Panel): style wxPython style """ + print('__init__: self=%s' % str(self)) + print('__init__: parent=%s' % str(parent)) + wx.Panel.__init__(self, parent, id, pos, size, style) # Bind events diff --git a/pymlac/DisplayCPU.py b/pymlac/DisplayCPU.py index fdb702d..4dc19de 100644 --- a/pymlac/DisplayCPU.py +++ b/pymlac/DisplayCPU.py @@ -11,320 +11,289 @@ from Globals import * import Trace -# display CPU constants -MODE_NORMAL = 0 -MODE_DEIM = 1 +class DisplayCPU(object): -###### -# The Display CPU registers -###### + # display CPU constants + MODE_NORMAL = 0 + MODE_DEIM = 1 -DPC = 0 # display CPU program counter -DRS = [0, 0, 0, 0, 0, 0, 0, 0] # display CPU ??? -DRSindex = 0 # display CPU ??? -DIB = 0 # display CPU ??? -DX = 0 # display CPU draw X register -DY = 0 # display CPU draw Y register + ###### + # The Display CPU registers + ###### -# global state variables -Mode = MODE_NORMAL -Running = False - - -def init(): - global Mode, Running + DPC = 0 # display CPU program counter + DRS = [0, 0, 0, 0, 0, 0, 0, 0] # display CPU ??? + DRSindex = 0 # display CPU ??? + DIB = 0 # display CPU ??? + DX = 0 # display CPU draw X register + DY = 0 # display CPU draw Y register + # global state variables Mode = MODE_NORMAL Running = False -def DEIMdecode(byte): - """Decode a DEIM byte""" - result = '' - if byte & 0x80: - if byte & 0x40: result += 'B' - else: result += 'D' - if byte & 0x20: result += '-' - result += '%d' % ((byte >> 3) & 0x03) - if byte & 0x04: result += '-' - result += '%d' % (byte & 0x03) - else: - if byte == 0111: result += 'N' - elif byte == 0151: result += 'R' - elif byte == 0171: result += 'F' - elif byte == 0200: result += 'P' - else: result += 'A%3.3o' % byte - return result + def __init__(self, display, memory): + self.Mode = self.MODE_NORMAL + self.Running = False -def doDEIMByte(byte): - global DPC, DX, DY, DRSindex - global Mode + self.display = display + self.memory = memory - if byte & 0x80: # increment? - prevDX = DX - prevDY = DY - if byte & 0x20: - DX -= (byte & 0x18) >> 3 + def DEIMdecode(self, byte): + """Decode a DEIM byte""" + + result = '' + if byte & 0x80: + if byte & 0x40: result += 'B' + else: result += 'D' + if byte & 0x20: result += '-' + result += '%d' % ((byte >> 3) & 0x03) + if byte & 0x04: result += '-' + result += '%d' % (byte & 0x03) else: - DX += (byte & 0x18) >> 3 - if byte & 0x04: - DY -= (byte & 0x03) - else: - DY += (byte & 0x03) + if byte == 0111: result += 'N' + elif byte == 0151: result += 'R' + elif byte == 0171: result += 'F' + elif byte == 0200: result += 'P' + else: result += 'A%3.3o' % byte + return result + + def doDEIMByte(self, byte): + if byte & 0x80: # increment? + prevDX = self.DX + prevDY = self.DY + if byte & 0x20: + self.DX -= (byte & 0x18) >> 3 + else: + self.DX += (byte & 0x18) >> 3 + if byte & 0x04: + self.DY -= (byte & 0x03) + else: + self.DY += (byte & 0x03) + if byte & 0x40: + self.display.draw(prevDX, prevDY, self.DX, self.DY) + else: # micro instructions if byte & 0x40: - display.draw(prevDX, prevDY, DX, DY) - else: # micro instructions - if byte & 0x40: - Mode = MODE_NORMAL - if byte & 0x20: # DRJM - if DRSindex <= 0: - Trace.comment('\nDRS stack underflow at display address %6.6o' - % (DPC - 1)) - illegal() - DRSindex -= 1 - DPC = DRS[DRSindex] - if byte & 0x10: - DX += 0x08 - if byte & 0x08: - DX &= 0xfff8 - if byte & 0x02: - DY += 0x10 - if byte & 0x01: - DY &= 0xfff0 + self.Mode = self.self.MODE_NORMAL + if byte & 0x20: # DRJM + if self.DRSindex <= 0: + Trace.comment('\nDRS stack underflow at display address %6.6o' + % (self.DPC - 1)) + self.illegal() + self.DRSindex -= 1 + self.DPC = DRS[DRSindex] + if byte & 0x10: + self.DX += 0x08 + if byte & 0x08: + self.DX &= 0xfff8 + if byte & 0x02: + self.DY += 0x10 + if byte & 0x01: + self.DY &= 0xfff0 -def execute_one_instruction(): - global DPC - global Mode + def execute_one_instruction(self): + if not self.Running: + Trace.dtrace('') + return 0 - if not Running: - Trace.dtrace('') - return 0 + instruction = self.memory.get(self.DPC, 0) + self.DPC = MASK_MEM(self.DPC + 1) - instruction = Memory.get(DPC, 0) - DPC = MASK_MEM(DPC + 1) + if self.Mode == self.MODE_DEIM: + Trace.trace(self.DEIMdecode(instruction >> 8) + '\t') + self.doDEIMByte(instruction >> 8) + if self.Mode == self.MODE_DEIM: + Trace.trace(self.DEIMdecode(instruction & 0xff) + '\t') + self.doDEIMByte(instruction & 0xff) + else: + Trace.trace('\t') + return 1 - if Mode == MODE_DEIM: - Trace.trace(DEIMdecode(instruction >> 8) + '\t') - doDEIMByte(instruction >> 8) - if Mode == MODE_DEIM: - Trace.trace(DEIMdecode(instruction & 0xff) + '\t') - doDEIMByte(instruction & 0xff) + opcode = instruction >> 12 + address = instruction & 007777 + + if opcode == 000: return self.page00(instruction) + elif opcode == 001: return self.i_DLXA(address) + elif opcode == 002: return self.i_DLYA(address) + elif opcode == 003: return self.i_DEIM(address) + elif opcode == 004: return self.i_DLVH(address) + elif opcode == 005: return self.i_DJMS(address) + elif opcode == 006: return self.i_DJMP(address) + elif opcode == 007: self.illegal(instruction) + else: self.illegal(instruction) + + def illegal(self, instruction=None): + if instruction: + Trace.comment('Illegal display instruction (%6.6o) at address %6.6o' + % (instruction, (self.DPC - 1))) else: - Trace.trace('\t') + Trace.comment('Illegal display instruction at address %6.6o' + % (self.DPC - 1)) + sys.exit(0) + + def ison(self): + return self.Running + + def i_DDXM(self): + self.DX -= 040 + Trace.dtrace('DDXM') + + def i_DDYM(self): + self.DY -= 040 + Trace.dtrace('DDYM') + + def i_DEIM(self, address): + self.Mode = self.MODE_DEIM + Trace.deimtrace('DEIM', self.DEIMdecode(address & 0377)) + self.doDEIMByte(address & 0377) return 1 - opcode = instruction >> 12 - address = instruction & 007777 + def i_DHLT(self): + self.Running = False + Trace.dtrace('DHLT') - if opcode == 000: return page00(instruction) - elif opcode == 001: return i_DLXA(address) - elif opcode == 002: return i_DLYA(address) - elif opcode == 003: return i_DEIM(address) - elif opcode == 004: return i_DLVH(address) - elif opcode == 005: return i_DJMS(address) - elif opcode == 006: return i_DJMP(address) - elif opcode == 007: illegal(instruction) - else: illegal(instruction) + def i_DHVC(self): + Trace.dtrace('DHVC') -def illegal(instruction=None): - if instruction: - Trace.comment('Illegal display instruction (%6.6o) at address %6.6o' - % (instruction, (DPC - 1))) - else: - Trace.comment('Illegal display instruction at address %6.6o' - % (DPC - 1)) - sys.exit(0) + def i_DIXM(self): + self.DX += 04000 + Trace.dtrace('DIXM') -def ison(): - return Running + def i_DIYM(self): + self.DY += 04000 + Trace.dtrace('DIYM') -def i_DDXM(): - global DX + def i_DJMP(self, address): + self.DPC = MASK_MEM(address + (self.DIB << 12)) + Trace.dtrace('DJMP', address) + return 1 - DX -= 040 - Trace.dtrace('DDXM') + def i_DJMS(self, address): + if self.DRSindex >= 8: + Trace.comment('DRS stack overflow at display address %6.6o' + % (self.DPC - 1)) + self.illegal() + self.DRS[self.DRSindex] = self.DPC + self.DRSindex += 1 + self.DPC = MASK_MEM(address + (self.DIB << 12)) + Trace.dtrace('DJMS', address) + return 1 -def i_DDYM(): - global DY + def i_DLXA(self, address): + self.DX = address + Trace.dtrace('DLXA', address) + return 1 - DY -= 040 - Trace.dtrace('DDYM') + def i_DLYA(self, address): + self.DY = address + Trace.dtrace('DLYA', address) + return 1 -def i_DEIM(address): - global Mode + def i_DLVH(self, word1): + word2 = self.memory.get(self, DPC, 0) + self.DPC = MASK_MEM(self.DPC + 1) + word3 = self.memory.get(self.DPC, 0) + self.DPC = MASK_MEM(self.DPC + 1) - Mode = MODE_DEIM - Trace.deimtrace('DEIM', DEIMdecode(address & 0377)) - doDEIMByte(address & 0377) - return 1 + dotted = word2 & 040000 + beamon = word2 & 020000 + negx = word3 & 040000 + negy = word3 & 020000 + ygtx = word3 & 010000 -def i_DHLT(): - Running = False - Trace.dtrace('DHLT') + M = word2 & 007777 + N = word3 & 007777 -def i_DHVC(): - Trace.dtrace('DHVC') + prevDX = self.DX + prevDY = self.DY -def i_DIXM(): - global DX + if ygtx: # M is y, N is x + if negx: + self.DX -= N + else: + self.DX += N + if negy: + self.DY -= M + else: + self.DY += M + else: # M is x, N is y + if negx: + self.DX -= M + else: + self.DX += M + if negy: + self.DY -= N + else: + self.DY += N - DX += 04000 - Trace.dtrace('DIXM') + self.display.draw(prevDX, prevDY, self.DX, self.DY, dotted) + Trace.dtrace('DLVH') + return 3 -def i_DIYM(): - global DY + def i_DRJM(self): + if self.DRSindex <= 0: + Trace.comment('DRS stack underflow at display address %6.6o' + % (self.DPC - 1)) + self.illegal() + self.DRSindex -= 1 + self.DPC = self.DRS[self.DRSindex] + Trace.dtrace('DRJM') + return 1 # FIXME check # cycles used - DY += 04000 - Trace.dtrace('DIYM') + def i_DSTB(self, block): + self.DIB = block + Trace.dtrace('DSTB\t%d' % block) -def i_DJMP(address): - global DPC, DIB - - DPC = MASK_MEM(address + (DIB << 12)) - Trace.dtrace('DJMP', address) - return 1 - -def i_DJMS(address): - global DPC, DRSindex, DIB - - if DRSindex >= 8: - Trace.comment('DRS stack overflow at display address %6.6o' - % (DPC - 1)) - illegal() - DRS[DRSindex] = DPC - DRSindex += 1 - DPC = MASK_MEM(address + (DIB << 12)) - Trace.dtrace('DJMS', address) - return 1 - -def i_DLXA(address): - global DX - - DX = address - Trace.dtrace('DLXA', address) - return 1 - -def i_DLYA(address): - global DY - - DY = address - Trace.dtrace('DLYA', address) - return 1 - -def i_DLVH(word1): - global DPC, DX, DY - - word2 = Memory.get(DPC, 0) - DPC = MASK_MEM(DPC + 1) - word3 = Memory.get(DPC, 0) - DPC = MASK_MEM(DPC + 1) - - dotted = word2 & 040000 - beamon = word2 & 020000 - negx = word3 & 040000 - negy = word3 & 020000 - ygtx = word3 & 010000 - - M = word2 & 007777 - N = word3 & 007777 - - prevDX = DX - prevDY = DY - - if ygtx: # M is y, N is x - if negx: - DX -= N + def i_DSTS(self, scale): + if scale == 0: + self.Scale = 0.5 + elif scale == 1: + self.Scale = 1.0 + elif scale == 2: + self.Scale = 2.0 + elif scale == 3: + self.Scale = 3.0 else: - DX += N - if negy: - DY -= M + self.illegal() + Trace.dtrace('DSTS', scale) + return 1 # FIXME check # cycles used + + def page00(self, instruction): + if instruction == 000000: # DHLT + self.i_DHLT() + elif instruction == 004000: # DNOP + Trace.dtrace('DNOP') + elif instruction == 004004: # DSTS 0 + self.i_DSTS(0) + elif instruction == 004005: # DSTS 1 + self.i_DSTS(1) + elif instruction == 004006: # DSTS 2 + self.i_DSTS(2) + elif instruction == 004007: # DSTS 3 + self.i_DSTS(3) + elif instruction == 004010: # DSTB 0 + self.i_DSTB(0) + elif instruction == 004011: # DSTB 1 + self.i_DSTB(1) + elif instruction == 004040: # DRJM + self.i_DRJM() + elif instruction == 004100: # DDYM + self.i_DDYM() + elif instruction == 004200: # DDXM + self.i_DDXM() + elif instruction == 004400: # DIYM + self.i_DIYM() + elif instruction == 005000: # DIXM + self.i_DIXM() + elif instruction == 006000: # DHVC + self.i_DHVC() else: - DY += M - else: # M is x, N is y - if negx: - DX -= M - else: - DX += M - if negy: - DY -= N - else: - DY += N + self.illegal(instruction) + return 1 - display.draw(prevDX, prevDY, DX, DY, dotted) - Trace.dtrace('DLVH') - return 3 + def start(self): + self.Running = True -def i_DRJM(): - global DPC, DRSindex - - if DRSindex <= 0: - Trace.comment('DRS stack underflow at display address %6.6o' - % (DPC - 1)) - illegal() - DRSindex -= 1 - DPC = DRS[DRSindex] - Trace.dtrace('DRJM') - -def i_DSTB(block): - global DIB - - DIB = block - Trace.dtrace('DSTB\t%d' % block) - -def i_DSTS(scale): - global Scale - - if scale == 0: - Scale = 0.5 - elif scale == 1: - Scale = 1.0 - elif scale == 2: - Scale = 2.0 - elif scale == 3: - Scale = 3.0 - else: - illegal() - Trace.dtrace('DSTS', scale) - -def page00(instruction): - if instruction == 000000: # DHLT - i_DHLT() - elif instruction == 004000: # DNOP - Trace.dtrace('DNOP') - elif instruction == 004004: # DSTS 0 - i_DSTS(0) - elif instruction == 004005: # DSTS 1 - i_DSTS(1) - elif instruction == 004006: # DSTS 2 - i_DSTS(2) - elif instruction == 004007: # DSTS 3 - i_DSTS(3) - elif instruction == 004010: # DSTB 0 - i_DSTB(0) - elif instruction == 004011: # DSTB 1 - i_DSTB(1) - elif instruction == 004040: # DRJM - i_DRJM() - elif instruction == 004100: # DDYM - i_DDYM() - elif instruction == 004200: # DDXM - i_DDXM() - elif instruction == 004400: # DIYM - i_DIYM() - elif instruction == 005000: # DIXM - i_DIXM() - elif instruction == 006000: # DHVC - i_DHVC() - else: - illegal(instruction) - return 1 - -def start(): - global Running - - Running = True - -def stop(): - global Running - - Running = False + def stop(self): + self.Running = False diff --git a/pymlac/Memory.py b/pymlac/Memory.py index 0374225..2df58bc 100644 --- a/pymlac/Memory.py +++ b/pymlac/Memory.py @@ -101,7 +101,7 @@ class Memory(object): if self.corefile: try: - loadcore(self.corefile) + self.loadcore(self.corefile) except IOError: self.clear_core() else: diff --git a/pymlac/Trace.py b/pymlac/Trace.py index e4dd3da..dd68b28 100644 --- a/pymlac/Trace.py +++ b/pymlac/Trace.py @@ -8,16 +8,16 @@ The Imlac trace stuff. import time from Globals import * -import MainCPU -import DisplayCPU # module-level state variables tracing = False tracefile = None +cpu = None +dcpu = None -def init(filename): - global tracing, tracefile +def init(filename, maincpu, displaycpu): + global tracing, tracefile, cpu, dcpu tracing = True tracefile = open(filename, 'w') @@ -25,6 +25,9 @@ def init(filename): tracing = False comment = None + cpu = maincpu + dcpu = displaycpu + def close(): import tracing, tracefile @@ -58,9 +61,9 @@ def itrace(opcode, indirect=False, address=None): def itraceend(dispon): if dispon: trace('L=%1.1o AC=%6.6o DX=%5.5o DY=%6.6o\n' % - (MainCPU.L, MainCPU.AC, DisplayCPU.DX, DisplayCPU.DY)) + (cpu.L, cpu.AC, dcpu.DX, dcpu.DY)) else: - trace('L=%1.1o AC=%6.6o\n' % (MainCPU.L, MainCPU.AC)) + trace('L=%1.1o AC=%6.6o\n' % (cpu.L, cpu.AC)) def comment(msg): tracefile.write(msg+'\n') diff --git a/pymlac/log.py b/pymlac/log.py index 42dad42..99ffbab 100644 --- a/pymlac/log.py +++ b/pymlac/log.py @@ -169,7 +169,7 @@ class Log(object): except ValueError: mod_name = __name__ for (fpath, lnum, mname, _) in frames: - (fname, _) = os.path.basename(fpath).rsplit('.', 1) + fname = os.path.basename(fpath).rsplit('.', 1)[0] if fname != mod_name: break diff --git a/pymlac/xyzzy b/pymlac/xyzzy index 573d104..c2545ca 100755 --- a/pymlac/xyzzy +++ b/pymlac/xyzzy @@ -30,8 +30,9 @@ from threading import * import wx import Display +import DisplayCPU from Globals import * -import Imlac +#import Imlac import Memory import Ptr @@ -251,15 +252,15 @@ def main(): # Initialize the emulator. boot_rom = 'ptr' # default ROM loader - Imlac.init(0, TRACE_FILENAME, None, None, boot_rom, CORE_FILENAME) +# Imlac.init(0, TRACE_FILENAME, None, None, boot_rom, CORE_FILENAME) # now perform operations for (operation, args) in ops: if operation == 'boot': - Memory.set_ROM(args) + self.memory.set_ROM(args) Trace.comment('Bootstrap ROM set to %s' % args.upper()) elif operation == 'clear': - Memory.clear_core() + self.memory.clear_core() Trace.comment('Core cleared') elif operation == 'load_ptp': Ptp.mount(args) @@ -273,29 +274,31 @@ def main(): elif operation == 'run': MainCPU.PC = args Trace.comment('Running from address %06o' % args) - if Imlac.tracestart: - Trace.comment('DPC\tDisplay\t\tPC\tMain\t\tRegs') - Trace.comment('------ ------------- ------ -------------- ' +# if Imlac.tracestart: + Trace.comment('DPC\tDisplay\t\tPC\tMain\t\tRegs') + Trace.comment('------ ------------- ------ -------------- ' '-----------------------') - Imlac.run() + self.run() +# Imlac.run() Trace.comment('Imlac halted') elif operation == 'set': Trace.comment("Setting memory from file '%s'" % args) elif operation == 'trace': if args == 'off': - Imlac.tracestart = None - Imlac.traceend = None +# Imlac.tracestart = None +# Imlac.traceend = None + pass else: (start, end) = args - Imlac.tracestart = start - Imlac.traceend = end - tstart = Imlac.tracestart - if tstart is not None: - tstart = '%06o' % tstart - tend = Imlac.traceend - if tend is not None: - tend = '%06o' % tend - Trace.comment('Trace set to (%s, %s)' % (tstart, tend)) +# Imlac.tracestart = start +# Imlac.traceend = end +# tstart = Imlac.tracestart +# if tstart is not None: +# tstart = '%06o' % tstart +# tend = Imlac.traceend +# if tend is not None: +# tend = '%06o' % tend +# Trace.comment('Trace set to (%s, %s)' % (tstart, tend)) elif operation == 'ttyin': TtyIn.mount(args) Trace.comment("File '%s' mounted on TTYIN" % args) @@ -306,16 +309,16 @@ def main(): Trace.comment("Viewing memory from file '%s'" % args) elif operation == 'write': if args == 'on': - Memory.using_rom = True + self.memory.using_rom = True elif args == 'off': - Memory.using_rom = False + self.memory.using_rom = False else: abort("Invalid view arg: %s" % args) Trace.comment('ROM write protect set %s' % args.upper()) else: abort('Invalid internal operation: %s' % operation) - Imlac.close(CORE_FILENAME) +# Imlac.close(CORE_FILENAME) class Led_1(object): def __init__(self, parent, label, x, y, off, on): @@ -364,255 +367,255 @@ class Led_16(object): mask = mask >> 1 -class PymlacFrame(wx.Frame): - """a frame with two panels""" - - WIDTH_SCREEN = 1024 - HEIGHT_SCREEN = 1024 - WIDTH_CONSOLE = 330 # 400 # 256 - HEIGHT_CONSOLE = HEIGHT_SCREEN - - SCREEN_COLOUR = (0, 0, 0) - CONSOLE_COLOUR = (255, 223, 169) - PHOSPHOR_COLOUR = '#F0F000' # yellow - #PHOSPHOR_COLOUR = '#40FF40' # green - - V_MARGIN = 20 - CTL_MARGIN = 15 - LED_MARGIN = 5 - - IMAGE_LED_OFF = 'images/led_off.png' - IMAGE_LED_ON = 'images/led_on.png' - - INC = 0.01 - - def __init__(self, parent=None, id=-1, title=None): - wx.Frame.__init__(self, parent, id, title) - - self.make_gui() - self.run() - - def make_gui(self): - self.screen = wx.Panel(self, - size=(self.WIDTH_SCREEN, self.HEIGHT_SCREEN), - pos=(0,0)) - self.screen.SetBackgroundColour(self.SCREEN_COLOUR) - self.console = wx.Panel(self, style=wx.SIMPLE_BORDER, - size=(self.WIDTH_CONSOLE, self.HEIGHT_SCREEN), - pos=(self.WIDTH_SCREEN,0)) - self.console.SetBackgroundColour(self.CONSOLE_COLOUR) - - python_png = wx.Image('images/PythonPowered.png', - wx.BITMAP_TYPE_PNG).ConvertToBitmap() - python_height = python_png.GetHeight() - python_width = python_png.GetWidth() - - wxpython_png = wx.Image('images/wxPython2.png', - wx.BITMAP_TYPE_PNG).ConvertToBitmap() - wxpython_height = wxpython_png.GetHeight() - wxpython_width = wxpython_png.GetWidth() - - h_margin = (self.WIDTH_CONSOLE - wxpython_width - python_width) / 3 - - png_height = max(python_height, wxpython_height) + self.V_MARGIN - - v_margin = (png_height - python_height)/2 - python_ypos = self.HEIGHT_CONSOLE - png_height + v_margin - v_margin = (png_height - wxpython_height)/2 - wxpython_ypos = self.HEIGHT_CONSOLE - png_height + v_margin - - wx.StaticBitmap(self.console, -1, python_png, - pos=(h_margin, python_ypos)) - wx.StaticBitmap(self.console, -1, wxpython_png, - pos=(python_width + 2*h_margin, wxpython_ypos)) - - self.png_height = png_height - - led_off = wx.Image('images/led_off.png', - wx.BITMAP_TYPE_PNG).ConvertToBitmap() - led_on = wx.Image('images/led_on.png', - wx.BITMAP_TYPE_PNG).ConvertToBitmap() - - y_pos = 8 - self.led_l = Led_1(self.console, 'l', self.CTL_MARGIN, y_pos, - led_off, led_on) - self.led_ac = Led_16(self.console, 'ac', 3*self.CTL_MARGIN, y_pos, - led_off, led_on) - y_pos += 35 - self.led_pc = Led_16(self.console, 'pc', 3*self.CTL_MARGIN, y_pos, - led_off, led_on) - - - y_pos = 305 - wx.StaticText(self.console, -1, 'ptr', pos=(self.CTL_MARGIN, y_pos)) - y_pos += 15 - self.txt_ptrFile = wx.TextCtrl(self.console, -1, - pos=(self.CTL_MARGIN, y_pos), - size=(self.WIDTH_CONSOLE-2*self.CTL_MARGIN, 25)) - y_pos += 30 - - wx.StaticText(self.console, -1, 'ptp', pos=(self.CTL_MARGIN, y_pos)) - y_pos += 15 - self.txt_ptpFile = wx.TextCtrl(self.console, -1, - pos=(self.CTL_MARGIN, y_pos), - size=(self.WIDTH_CONSOLE-2*self.CTL_MARGIN, 25)) - y_pos += 15 - - dc = wx.PaintDC(self.console) - dc.SetPen(wx.Pen('black', 1)) - dc.DrawLine(0, self.HEIGHT_CONSOLE - self.png_height, - self.WIDTH_CONSOLE-1, self.HEIGHT_CONSOLE - self.png_height) - - for (x, y) in self.led_ac.ticks: - dc.DrawLine(x, y, x, y+5) - first = self.led_ac.ticks[0] - last = self.led_ac.ticks[-1] - (x1, y1) = first - (x2, y2) = last - dc.DrawLine(x1, y2+5, x2, y2+5) - - for (x, y) in self.led_pc.ticks: - dc.DrawLine(x, y, x, y+5) - first = self.led_pc.ticks[0] - last = self.led_pc.ticks[-1] - (x1, y1) = first - (x2, y2) = last - dc.DrawLine(x1, y2+5, x2, y2+5) - - self.y_offset = 0 - self.y_sign = +1 - - self.Fit() - - def run_machine(self, ops): - """Run the console options.""" - - for (operation, args) in ops: - if operation == 'boot': - Memory.set_ROM(args) - Trace.comment('Bootstrap ROM set to %s' % args.upper()) - self.on_paint() - elif operation == 'clear': - Memory.clear_core() - Trace.comment('Core cleared') - self.on_paint() - elif operation == 'load_ptp': - Ptp.mount(args) - Trace.comment("File '%s' mounted on PTP" % args) - self.on_paint() - elif operation == 'load_ptr': - Ptr.mount(args) - Trace.comment("File '%s' mounted on PTR" % args) - self.on_paint() - elif operation == 'data': - MainCPU.DS = args - Trace.comment('Dataswitch value set to %06o' % args) - self.on_paint() - elif operation == 'run': - MainCPU.PC = args - Trace.comment('Running from address %06o' % args) - if Imlac.tracestart: - Trace.comment('DPC\tDisplay\t\tPC\tMain\t\tRegs') - Trace.comment('------ ------------- ------ -------------- ' - '-----------------------') - self.on_paint() - Imlac.run() - self.on_paint() - Trace.comment('Imlac halted') - self.on_paint() - elif operation == 'set': - Trace.comment("Setting memory from file '%s'" % args) - self.on_paint() - elif operation == 'trace': - if args == 'off': - Imlac.tracestart = None - Imlac.traceend = None - else: - (start, end) = args - Imlac.tracestart = start - Imlac.traceend = end - tstart = Imlac.tracestart - if tstart is not None: - tstart = '%06o' % tstart - tend = Imlac.traceend - if tend is not None: - tend = '%06o' % tend - Trace.comment('Trace set to (%s, %s)' % (tstart, tend)) - self.on_paint() - elif operation == 'ttyin': - TtyIn.mount(args) - Trace.comment("File '%s' mounted on TTYIN" % args) - self.on_paint() - elif operation == 'ttyout': - TtyOut.mount(args) - Trace.comment("File '%s' mounted on TTYOUT" % args) - self.on_paint() - elif operation == 'view': - Trace.comment("Viewing memory from file '%s'" % args) - self.on_paint() - elif operation == 'write': - if args == 'on': - Memory.using_rom = True - elif args == 'off': - Memory.using_rom = False - else: - abort("Invalid view arg: %s" % args) - Trace.comment('ROM write protect set %s' % args.upper()) - self.on_paint() - else: - abort('Invalid internal operation: %s' % operation) - - Imlac.close(CORE_FILENAME) - - - def on_paint(self, event=None): - global count - - # establish the painting surface - dc = wx.PaintDC(self.screen) - dc.SetBackground(wx.Brush(self.SCREEN_COLOUR, 1)) - dc.SetPen(wx.Pen(self.PHOSPHOR_COLOUR, 1)) - dc.Clear() - if self.y_sign > 0: - self.y_offset = self.y_offset + self.INC - if self.y_offset > self.HEIGHT_SCREEN-1: - self.y_sign = -1 - self.y_offset = self.HEIGHT_SCREEN-1 - else: - self.y_offset = self.y_offset - self.INC - if self.y_offset < 0: - self.y_sign = +1 - self.y_offset = 0 - dc.DrawLine(0, int(self.y_offset), self.WIDTH_SCREEN-1, int(self.HEIGHT_SCREEN-self.y_offset-1)) - dc.DrawLine(0, int(self.HEIGHT_SCREEN-self.y_offset-1), self.WIDTH_SCREEN-1, int(self.y_offset)) - - dc = wx.PaintDC(self.console) - #dc.SetPen(wx.Pen('black', wx.DOT)) - dc.SetPen(wx.Pen('black', 1)) - dc.DrawLine(0, self.HEIGHT_CONSOLE - self.png_height, - self.WIDTH_CONSOLE-1, self.HEIGHT_CONSOLE - self.png_height) - - for (x, y) in self.led_ac.ticks: - dc.DrawLine(x, y, x, y+5) - first = self.led_ac.ticks[0] - last = self.led_ac.ticks[-1] - (x1, y1) = first - (x2, y2) = last - dc.DrawLine(x1, y2+5, x2, y2+5) - - for (x, y) in self.led_pc.ticks: - dc.DrawLine(x, y, x, y+5) - first = self.led_pc.ticks[0] - last = self.led_pc.ticks[-1] - (x1, y1) = first - (x2, y2) = last - dc.DrawLine(x1, y2+5, x2, y2+5) - - count += 1 - self.led_ac.set_value(count) - - - pass +#class PymlacFrame(wx.Frame): +# """a frame with two panels""" +# +# WIDTH_SCREEN = 1024 +# HEIGHT_SCREEN = 1024 +# WIDTH_CONSOLE = 330 # 400 # 256 +# HEIGHT_CONSOLE = HEIGHT_SCREEN +# +# SCREEN_COLOUR = (0, 0, 0) +# CONSOLE_COLOUR = (255, 223, 169) +# PHOSPHOR_COLOUR = '#F0F000' # yellow +# #PHOSPHOR_COLOUR = '#40FF40' # green +# +# V_MARGIN = 20 +# CTL_MARGIN = 15 +# LED_MARGIN = 5 +# +# IMAGE_LED_OFF = 'images/led_off.png' +# IMAGE_LED_ON = 'images/led_on.png' +# +# INC = 0.01 +# +# def __init__(self, parent=None, id=-1, title=None): +# wx.Frame.__init__(self, parent, id, title) +# +# self.make_gui() +# self.run() +# +# def make_gui(self): +# self.screen = wx.Panel(self, +# size=(self.WIDTH_SCREEN, self.HEIGHT_SCREEN), +# pos=(0,0)) +# self.screen.SetBackgroundColour(self.SCREEN_COLOUR) +# self.console = wx.Panel(self, style=wx.SIMPLE_BORDER, +# size=(self.WIDTH_CONSOLE, self.HEIGHT_SCREEN), +# pos=(self.WIDTH_SCREEN,0)) +# self.console.SetBackgroundColour(self.CONSOLE_COLOUR) +# +# python_png = wx.Image('images/PythonPowered.png', +# wx.BITMAP_TYPE_PNG).ConvertToBitmap() +# python_height = python_png.GetHeight() +# python_width = python_png.GetWidth() +# +# wxpython_png = wx.Image('images/wxPython2.png', +# wx.BITMAP_TYPE_PNG).ConvertToBitmap() +# wxpython_height = wxpython_png.GetHeight() +# wxpython_width = wxpython_png.GetWidth() +# +# h_margin = (self.WIDTH_CONSOLE - wxpython_width - python_width) / 3 +# +# png_height = max(python_height, wxpython_height) + self.V_MARGIN +# +# v_margin = (png_height - python_height)/2 +# python_ypos = self.HEIGHT_CONSOLE - png_height + v_margin +# v_margin = (png_height - wxpython_height)/2 +# wxpython_ypos = self.HEIGHT_CONSOLE - png_height + v_margin +# +# wx.StaticBitmap(self.console, -1, python_png, +# pos=(h_margin, python_ypos)) +# wx.StaticBitmap(self.console, -1, wxpython_png, +# pos=(python_width + 2*h_margin, wxpython_ypos)) +# +# self.png_height = png_height +# +# led_off = wx.Image('images/led_off.png', +# wx.BITMAP_TYPE_PNG).ConvertToBitmap() +# led_on = wx.Image('images/led_on.png', +# wx.BITMAP_TYPE_PNG).ConvertToBitmap() +# +# y_pos = 8 +# self.led_l = Led_1(self.console, 'l', self.CTL_MARGIN, y_pos, +# led_off, led_on) +# self.led_ac = Led_16(self.console, 'ac', 3*self.CTL_MARGIN, y_pos, +# led_off, led_on) +# y_pos += 35 +# self.led_pc = Led_16(self.console, 'pc', 3*self.CTL_MARGIN, y_pos, +# led_off, led_on) +# +# +# y_pos = 305 +# wx.StaticText(self.console, -1, 'ptr', pos=(self.CTL_MARGIN, y_pos)) +# y_pos += 15 +# self.txt_ptrFile = wx.TextCtrl(self.console, -1, +# pos=(self.CTL_MARGIN, y_pos), +# size=(self.WIDTH_CONSOLE-2*self.CTL_MARGIN, 25)) +# y_pos += 30 +# +# wx.StaticText(self.console, -1, 'ptp', pos=(self.CTL_MARGIN, y_pos)) +# y_pos += 15 +# self.txt_ptpFile = wx.TextCtrl(self.console, -1, +# pos=(self.CTL_MARGIN, y_pos), +# size=(self.WIDTH_CONSOLE-2*self.CTL_MARGIN, 25)) +# y_pos += 15 +# +# dc = wx.PaintDC(self.console) +# dc.SetPen(wx.Pen('black', 1)) +# dc.DrawLine(0, self.HEIGHT_CONSOLE - self.png_height, +# self.WIDTH_CONSOLE-1, self.HEIGHT_CONSOLE - self.png_height) +# +# for (x, y) in self.led_ac.ticks: +# dc.DrawLine(x, y, x, y+5) +# first = self.led_ac.ticks[0] +# last = self.led_ac.ticks[-1] +# (x1, y1) = first +# (x2, y2) = last +# dc.DrawLine(x1, y2+5, x2, y2+5) +# +# for (x, y) in self.led_pc.ticks: +# dc.DrawLine(x, y, x, y+5) +# first = self.led_pc.ticks[0] +# last = self.led_pc.ticks[-1] +# (x1, y1) = first +# (x2, y2) = last +# dc.DrawLine(x1, y2+5, x2, y2+5) +# +# self.y_offset = 0 +# self.y_sign = +1 +# +# self.Fit() +# +# def run_machine(self, ops): +# """Run the console options.""" +# +# for (operation, args) in ops: +# if operation == 'boot': +# Memory.set_ROM(args) +# Trace.comment('Bootstrap ROM set to %s' % args.upper()) +# self.on_paint() +# elif operation == 'clear': +# Memory.clear_core() +# Trace.comment('Core cleared') +# self.on_paint() +# elif operation == 'load_ptp': +# Ptp.mount(args) +# Trace.comment("File '%s' mounted on PTP" % args) +# self.on_paint() +# elif operation == 'load_ptr': +# Ptr.mount(args) +# Trace.comment("File '%s' mounted on PTR" % args) +# self.on_paint() +# elif operation == 'data': +# MainCPU.DS = args +# Trace.comment('Dataswitch value set to %06o' % args) +# self.on_paint() +# elif operation == 'run': +# MainCPU.PC = args +# Trace.comment('Running from address %06o' % args) +# if Imlac.tracestart: +# Trace.comment('DPC\tDisplay\t\tPC\tMain\t\tRegs') +# Trace.comment('------ ------------- ------ -------------- ' +# '-----------------------') +# self.on_paint() +# Imlac.run() +# self.on_paint() +# Trace.comment('Imlac halted') +# self.on_paint() +# elif operation == 'set': +# Trace.comment("Setting memory from file '%s'" % args) +# self.on_paint() +# elif operation == 'trace': +# if args == 'off': +# Imlac.tracestart = None +# Imlac.traceend = None +# else: +# (start, end) = args +# Imlac.tracestart = start +# Imlac.traceend = end +# tstart = Imlac.tracestart +# if tstart is not None: +# tstart = '%06o' % tstart +# tend = Imlac.traceend +# if tend is not None: +# tend = '%06o' % tend +# Trace.comment('Trace set to (%s, %s)' % (tstart, tend)) +# self.on_paint() +# elif operation == 'ttyin': +# TtyIn.mount(args) +# Trace.comment("File '%s' mounted on TTYIN" % args) +# self.on_paint() +# elif operation == 'ttyout': +# TtyOut.mount(args) +# Trace.comment("File '%s' mounted on TTYOUT" % args) +# self.on_paint() +# elif operation == 'view': +# Trace.comment("Viewing memory from file '%s'" % args) +# self.on_paint() +# elif operation == 'write': +# if args == 'on': +# Memory.using_rom = True +# elif args == 'off': +# Memory.using_rom = False +# else: +# abort("Invalid view arg: %s" % args) +# Trace.comment('ROM write protect set %s' % args.upper()) +# self.on_paint() +# else: +# abort('Invalid internal operation: %s' % operation) +# +# Imlac.close(CORE_FILENAME) +# +# +# def on_paint(self, event=None): +# global count +# +# # establish the painting surface +# dc = wx.PaintDC(self.screen) +# dc.SetBackground(wx.Brush(self.SCREEN_COLOUR, 1)) +# dc.SetPen(wx.Pen(self.PHOSPHOR_COLOUR, 1)) +# dc.Clear() +# if self.y_sign > 0: +# self.y_offset = self.y_offset + self.INC +# if self.y_offset > self.HEIGHT_SCREEN-1: +# self.y_sign = -1 +# self.y_offset = self.HEIGHT_SCREEN-1 +# else: +# self.y_offset = self.y_offset - self.INC +# if self.y_offset < 0: +# self.y_sign = +1 +# self.y_offset = 0 +# dc.DrawLine(0, int(self.y_offset), self.WIDTH_SCREEN-1, int(self.HEIGHT_SCREEN-self.y_offset-1)) +# dc.DrawLine(0, int(self.HEIGHT_SCREEN-self.y_offset-1), self.WIDTH_SCREEN-1, int(self.y_offset)) +# +# dc = wx.PaintDC(self.console) +# #dc.SetPen(wx.Pen('black', wx.DOT)) +# dc.SetPen(wx.Pen('black', 1)) +# dc.DrawLine(0, self.HEIGHT_CONSOLE - self.png_height, +# self.WIDTH_CONSOLE-1, self.HEIGHT_CONSOLE - self.png_height) +# +# for (x, y) in self.led_ac.ticks: +# dc.DrawLine(x, y, x, y+5) +# first = self.led_ac.ticks[0] +# last = self.led_ac.ticks[-1] +# (x1, y1) = first +# (x2, y2) = last +# dc.DrawLine(x1, y2+5, x2, y2+5) +# +# for (x, y) in self.led_pc.ticks: +# dc.DrawLine(x, y, x, y+5) +# first = self.led_pc.ticks[0] +# last = self.led_pc.ticks[-1] +# (x1, y1) = first +# (x2, y2) = last +# dc.DrawLine(x1, y2+5, x2, y2+5) +# +# count += 1 +# self.led_ac.set_value(count) +# +# +# pass @@ -652,11 +655,15 @@ class _InterpreterEvent(wx.PyCommandEvent): class InterpreterThread(Thread): """Worker Thread Class.""" - def __init__(self, parent): + def __init__(self, parent, cpu, dcpu): """Init Worker Thread Class.""" + Thread.__init__(self) self.parent = parent self._want_abort = 0 + self.cpu = cpu + self.dcpu = dcpu + # This starts the thread running on creation, but you could # also make the GUI thread responsible for calling this self.start() @@ -679,10 +686,39 @@ class InterpreterThread(Thread): def run(self): """Run the interpreter.""" + + self.cpu.running = True + while self.execute_once() > 0: pass + self.cpu.running = False - Imlac.run() self.RaiseInterpreterStop() + def execute_once(): + if traceend is None: + if self.cpu.PC == tracestart: + Trace.settrace(True) + else: + Trace.settrace(self.cpu.PC >= tracestart and self.cpu.PC <= traceend) + + if self.dcpu.ison(): + Trace.trace('%6.6o' % self.dcpu.DPC) + Trace.trace('\t') + + instruction_cycles = self.dcpu.execute_one_instruction() + + Trace.trace('%6.6o\t' % self.cpu.PC) + + instruction_cycles += self.cpu.execute_one_instruction() + + Trace.itraceend(self.dcpu.ison()) + + self.__tick_all(instruction_cycles) + + if not self.dcpu.ison() and not self.cpu.running: + return 0 + + return instruction_cycles + def abort(self): """abort worker thread.""" # Method for use by main thread to signal an abort @@ -744,14 +780,21 @@ class DisplayFrame(wx.Frame): def run_machine(self): """Run the interpreter.""" -# FIXME create all devices, build the Imlac machine - self.memory = Memory.Memory(boot_rom=DefaultBootROM, corefile=DefaultCoreFile) + # create device, construct machine + self.kbd = None # Kbd.Kbd() + self.ttyin = None # TtyIn.TtyIn() + self.ttyout = None # TtyOut.TtyOut() + self.memory = Memory.Memory(boot_rom=DefaultBootROM, core=DefaultCoreFile) self.ptr = Ptr.Ptr() self.ptp = Ptp.Ptp() - self.display = Display.Display(self.memory) + self.display = Display.Display(self) self.dcpu = DisplayCPU.DisplayCPU(self.display, self.memory) - self.cpu = MainCPU.MainCPU(self.ptr, self.ptp, - self.display, self.dcpu, self.memory) + self.cpu = MainCPU.MainCPU(self.memory, self.display, self.dcpu, + self.kbd, self.ttyin, self.ttyout, + self.ptr, self.ptp) + + Trace.init(TRACE_FILENAME, self.cpu, self.dcpu) + tracestart = traceend = None # get and execute the operations list ops = get_options() @@ -760,66 +803,66 @@ class DisplayFrame(wx.Frame): time.sleep(1) if operation == 'boot': - Memory.set_ROM(args) + self.memory.set_ROM(args) Trace.comment('Bootstrap ROM set to %s' % args.upper()) elif operation == 'clear': - Memory.clear_core() + self.memory.clear_core() Trace.comment('Core cleared') elif operation == 'load_ptp': Ptp.mount(args) Trace.comment("File '%s' mounted on PTP" % args) elif operation == 'load_ptr': - Ptr.mount(args) + self.ptr.mount(args) Trace.comment("File '%s' mounted on PTR" % args) elif operation == 'data': - MainCPU.DS = args + self.cpu.DS = args Trace.comment('Dataswitch value set to %06o' % args) elif operation == 'run': - MainCPU.PC = args + self.cpu.PC = args Trace.comment('Running from address %06o' % args) - if Imlac.tracestart: + if tracestart: Trace.comment('DPC\tDisplay\t\tPC\tMain\t\tRegs') Trace.comment('------ ------------- ------ -------------- ' '-----------------------') - self.interpreter = InterpreterThread(self) + self.interpreter = InterpreterThread(self, self.cpu, self.dcpu) self.running = True elif operation == 'set': Trace.comment("Setting memory from file '%s'" % args) elif operation == 'trace': if args == 'off': - Imlac.tracestart = None - Imlac.traceend = None + tracestart = None + traceend = None else: (start, end) = args - Imlac.tracestart = start - Imlac.traceend = end - tstart = Imlac.tracestart + tracestart = start + traceend = end + tstart = tracestart if tstart is not None: tstart = '%06o' % tstart - tend = Imlac.traceend + tend = traceend if tend is not None: tend = '%06o' % tend Trace.comment('Trace set to (%s, %s)' % (tstart, tend)) elif operation == 'ttyin': - TtyIn.mount(args) + self.ttyin.mount(args) Trace.comment("File '%s' mounted on TTYIN" % args) elif operation == 'ttyout': - TtyOut.mount(args) + self.ttyout.mount(args) Trace.comment("File '%s' mounted on TTYOUT" % args) elif operation == 'view': Trace.comment("Viewing memory from file '%s'" % args) elif operation == 'write': if args == 'on': - Memory.using_rom = True + self.memory.using_rom = True elif args == 'off': - Memory.using_rom = False + self.memory.using_rom = False else: abort("Invalid view arg: %s" % args) Trace.comment('ROM write protect set %s' % args.upper()) else: abort('Invalid internal operation: %s' % operation) - Imlac.close(CORE_FILENAME) +# Imlac.close(CORE_FILENAME) def excepthook(type, value, tb): """Handler for uncaught exceptions."""