diff --git a/idasm/binimport.py b/idasm/binimport.py index 6a7eff5..da07f27 100755 --- a/idasm/binimport.py +++ b/idasm/binimport.py @@ -27,21 +27,28 @@ MemSize = 04000 LoaderSize = 0100 -def doblockloader(f, word, mymem): +def doblockloader(f, word, mymem, save): """Read block loader into high memory. f file handle to read from word the word we have already read mymem Mem() object to store loader in + save True if blockloader is to be stored in 'mymem' + + 'mymem' is updated. """ ldaddr = MemSize - LoaderSize + print('doblockloader: word=%06o' % word) + mymem.add(ldaddr, word) + ldaddr += 1 numwords = LoaderSize - 1 # have already read one word in mymem.add(ldaddr, word) while numwords > 0: word = readword(f) -#JUST SKIP OVER, DON'T PUT INTO MEMORY -# mymem.add(ldaddr, word) + print('doblockloader: word=%06o' % word) + if save: + mymem.add(ldaddr, word) ldaddr += 1 numwords = numwords - 1 @@ -74,20 +81,23 @@ def pyword(word): return struct.unpack(">h", bstr)[0] -def dobody(f, mymem): +def dobody(f, mymem, save): """Read all of file after block loader. f input file handle mymem the mem.Mem() dict to store data in + save True if body code is to be saved in 'mymem' Returns an updated mem.Mem() object containing the input code - and a start address: - (mem, start, ac) + and a start address: (mem, start, ac). If a start address is not specified, 'start' and 'ac' are both None. If there was a checksum error, just return None. """ + if not save: + return (mymem, None, None) + start_address = None while True: @@ -124,11 +134,21 @@ def dobody(f, mymem): return (mymem, None, None) -def ptpimport(file): +def ptpimport(filename, blockloader, code): + """Import data from PTP file into memory. + + filename the PTP file to read + blockloader True if blockloader is returned + code True if body code is returned + + Returns a memory object containing blockloader data or body code + data, or both. + """ + global Dot try: - f = open(file, "rb") + f = open(filename, "rb") except IOError as e: print e return 3 @@ -141,10 +161,10 @@ def ptpimport(file): # find and read the block loader byte = skipzeros(f) word = (byte << 8) + readbyte(f) - doblockloader(f, word, mymem) + doblockloader(f, word, mymem, save=blockloader) # now read all the data blocks - result = dobody(f, mymem) + result = dobody(f, mymem, save=code) if result is None: return (mymem, None, None) diff --git a/idasm/idasm b/idasm/idasm index 1631a5d..2187f8a 100755 --- a/idasm/idasm +++ b/idasm/idasm @@ -338,9 +338,14 @@ class MyFrame(wx.Frame): self.saveAsMenuitem = fileMenu.Append(102, "Save Project As ...", \ "Save disassembly project to new file") fileMenu.AppendSeparator() - fileMenu.Append(103, "Import Binary File", \ - "Import an Imlac binary file") - self.writeASMMenuitem = fileMenu.Append(104, "Write Assembler", \ + fileMenu.Append(103, "Import PTP File", + "Import all of an Imlac PTP file") + fileMenu.Append(104, "Import only code of PTP File", + "Import only code of an Imlac PTP file") + fileMenu.Append(105, "Import only blockloader of PTP File", + "Import only blockloader of an Imlac binary file") + fileMenu.AppendSeparator() + self.writeASMMenuitem = fileMenu.Append(109, "Write Assembler", "Write an assembler source file") fileMenu.AppendSeparator() fileMenu.Append(199, "Exit", "Exit the program") @@ -364,6 +369,8 @@ class MyFrame(wx.Frame): self.Bind(wx.EVT_MENU, self.Menu102, id=102) self.Bind(wx.EVT_MENU, self.Menu103, id=103) self.Bind(wx.EVT_MENU, self.Menu104, id=104) + self.Bind(wx.EVT_MENU, self.Menu105, id=105) + self.Bind(wx.EVT_MENU, self.Menu109, id=109) self.Bind(wx.EVT_MENU, self.Menu199, id=199) self.Bind(wx.EVT_MENU, self.Menu202, id=202) @@ -479,6 +486,8 @@ class MyFrame(wx.Frame): dlg.Destroy() def Menu103(self, event): + """Choose PTP file to load blockloader and code from.""" + global grid, mem, projectName filename = None @@ -489,7 +498,7 @@ class MyFrame(wx.Frame): if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath() self.grid.ClearGrid() - result = binimport.ptpimport(filename) + result = binimport.ptpimport(filename, blockloader=True, code=True) if result is not None: (mem, start, ac) = result fillGrid(grid, mem) @@ -506,6 +515,64 @@ class MyFrame(wx.Frame): def Menu104(self, event): + """Choose PTP file to load code from.""" + + global grid, mem, projectName + + filename = None + dlg = wx.FileDialog(self, message="Choose an IMLAC object file to load", + defaultDir=os.getcwd(), defaultFile="", + wildcard=objwildcard, + style=wx.OPEN | wx.CHANGE_DIR) + if dlg.ShowModal() == wx.ID_OK: + filename = dlg.GetPath() + self.grid.ClearGrid() + result = binimport.ptpimport(filename, blockloader=False, code=True) + if result is not None: + (mem, start, ac) = result + fillGrid(grid, mem) + projectName = os.path.basename(filename) + if projectName.endswith(DEFPTPSUFFIX): + projectName = projectName[:-len(DEFPTPSUFFIX)] + self.enableSaveWrite(True) + mem.clearUndo() + self.enableUndo(False) + if start: + # mark start address as MAIN instructions + self.do_main_start(start & 077777) + dlg.Destroy() + + + def Menu105(self, event): + """Choose PTP file to load blockloader from.""" + + global grid, mem, projectName + + filename = None + dlg = wx.FileDialog(self, message="Choose an IMLAC object file to load", + defaultDir=os.getcwd(), defaultFile="", + wildcard=objwildcard, + style=wx.OPEN | wx.CHANGE_DIR) + if dlg.ShowModal() == wx.ID_OK: + filename = dlg.GetPath() + self.grid.ClearGrid() + result = binimport.ptpimport(filename, blockloader=True, code=False) + if result is not None: + (mem, start, ac) = result + fillGrid(grid, mem) + projectName = os.path.basename(filename) + if projectName.endswith(DEFPTPSUFFIX): + projectName = projectName[:-len(DEFPTPSUFFIX)] + self.enableSaveWrite(True) + mem.clearUndo() + self.enableUndo(False) + if start: + # mark start address as MAIN instructions + self.do_main_start(start & 077777) + dlg.Destroy() + + + def Menu109(self, event): global mem, grid, projectName filename = None dlg = wx.FileDialog(self, diff --git a/idasm/loadptp.py b/idasm/loadptp.py index 201928d..6d8b330 100755 --- a/idasm/loadptp.py +++ b/idasm/loadptp.py @@ -51,8 +51,6 @@ def get_byte(ptp_data, index): except IndexError: return None -# print('get_byte: %03o' % result) - return (result, index+1) def get_word(ptp_data, index): @@ -80,7 +78,6 @@ def get_word(ptp_data, index): word = (first_byte << 8) + second_byte -# print('get_word: %06o' % word) return (word, index) def skipzeros(ptp_data, index): @@ -141,6 +138,7 @@ def c8lds_handler(ptp_data, memory): ... data word 'count' (16 bits) checksum (16 bits) + Note that a data block may be preceded by a zero leader. The example on the last page of the doc has a example tape containing: 004 000770 001061 100011 023775 037765 165054 @@ -148,8 +146,9 @@ def c8lds_handler(ptp_data, memory): The 'checksum' is not well defined in the documentation: the checksum is the sum of all the contents modulo 077777. Yet the example tape has a checksum of 165054. It is assumed the doc is in error and the checksum - is the sum of all the data words, module 177777. + is the sum of all the data words, modulo 177777. + A load address of 0177777 indicates the end of the load. As there is no autostart mechanism, returns (None, None) on successful load. Returns None if there was nothing to load. """ @@ -160,11 +159,13 @@ def c8lds_handler(ptp_data, memory): index = skipzeros(ptp_data, index) if index is None: # empty tape + print('empty tape') return None index = read_blockloader(ptp_data, index, memory) if index is None: # short block loader? + print('short blockloader?') return None # now read data blocks @@ -173,23 +174,24 @@ def c8lds_handler(ptp_data, memory): index = skipzeros(ptp_data, index) if index is None: break - print('start of data block at %05o' % index) # get data word count result = get_byte(ptp_data, index) if result is None: # premature end of tape? + print('EOT in block getting count?') return None (count, index) = result - print('word count=%d (%03o)' % (count, count)) # get block load address result = get_word(ptp_data, index) if result is None: # premature end of tape? + print('EOT in block getting load address?') return None (address, index) = result - print('block load address=%05o' % address) + if address == 0177777: + break # read data words, store in memory and calculate checksum checksum = 0 @@ -197,26 +199,27 @@ def c8lds_handler(ptp_data, memory): result = get_word(ptp_data, index) if result is None: # premature end of tape? + print('EOT in block getting data word?') return None (data, index) = result - print('data word: %06o at address %05o' % (data, address)) memory[address] = data address += 1 - checksum = (checksum + data) & 0177777 + checksum += data + if checksum != (checksum & 0177777): + checksum = (checksum & 0177777) + 1 # check block checksum -# checksum = checksum & 0177777 result = get_word(ptp_data, index) if result is None: # premature end of tape? - print('EOT') + print('EOT in block getting checksum?') return None (ptp_checksum, index) = result - print('ptp_checksum=%06o, checksum=%06o' % (ptp_checksum, checksum)) if ptp_checksum != checksum: # bad checksum - print('bad checksum') + print('bad checksum, PTP checksum is %06o, expected %06o' + % (ptp_checksum, checksum)) return None # no auto-start mechanism, so @@ -246,8 +249,6 @@ def lc16sd_handler(ptp_data, memory): Returns None if there was nothing to load. """ -# print('lc16sd_handler:') - index = 0 # skip initial zero leader @@ -269,7 +270,6 @@ def lc16sd_handler(ptp_data, memory): # break # get this block load address -# print('block load address') result = get_word(ptp_data, index) if result is None: return None # premature end of tape? @@ -283,12 +283,11 @@ def lc16sd_handler(ptp_data, memory): if result is None: return None # premature end of tape? (start_ac, index) = result - return (address & 0x7ffff, ac) + return (address & 0x7ffff, start_ac) else: return (None, None) # read data block, calculating checksum -# print('block word count') csum = address # start checksum with base address result = get_word(ptp_data, index) if result is None: @@ -298,7 +297,6 @@ def lc16sd_handler(ptp_data, memory): neg_count = pyword(count) csum = (csum + count) & 0xffff # add neg word count -# print('block checksum') result = get_word(ptp_data, index) if result is None: return None # premature end of tape? @@ -306,7 +304,6 @@ def lc16sd_handler(ptp_data, memory): csum = (csum + csum_word) & 0xffff # add checksum word while neg_count < 0: -# print('data word') result = get_word(ptp_data, index) if result is None: return None # premature end of tape? @@ -370,6 +367,8 @@ def load(filename, memory=None): print('%s: %s successful!' % (filename, name)) return result + print('%s: not recognized!' % filename) + # if we get here, no loader was successful return None @@ -386,7 +385,7 @@ if __name__ == '__main__': print('Usage: loadptp ') sys.exit(10) - if len(sys.argv) != 2: + if len(sys.argv) < 2: usage() - filename = sys.argv[1] - load(filename) + for filename in sys.argv[1:]: + load(filename)