1
0
mirror of https://github.com/rzzzwilson/pymlac.git synced 2025-06-10 09:32:41 +00:00

Track tools created elsewhere

This commit is contained in:
Ross Wilson
2015-08-21 12:52:17 +07:00
parent 686d969499
commit 88ac796b22
2 changed files with 670 additions and 0 deletions

541
pymlac/idasm Executable file
View File

@@ -0,0 +1,541 @@
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
"""
GUI front-end to the IMLAC intelligent disassembler.
"""
import os
import os.path
import wx
import wx.grid
import pickle
import binimport
import disasmm
import disasmd
import disasmdata
import processmain
import processdisplay
import processdata
import mem
PROGRAMNAME = "idasm"
PROGRAMVERSION = "0.2"
objwildcard = "Papertape files (*.ptp)|*.ptp|All files (*.*)|*.*"
projwildcard = "Project files (*.idasm)|*.idasm|All files (*.*)|*.*"
grid = None
mem = None
frame = None
projectName = ""
DEFPROJSUFFIX = ".idasm"
DEFASMSUFFIX = ".asm"
DEFPTPSUFFIX = ".ptp"
def effAddr(address):
return address & 03777
def newCycleNumber():
cycle = 0
while True:
cycle += 1
yield cycle
newcycle = newCycleNumber()
def loadProject(filename):
f = open(filename, "rb")
result = pickle.Unpickler(f).load()
f.close()
return result
def saveProject(filename):
global mem, grid
f = open(filename, "wb")
p = pickle.Pickler(f, -1)
p.dump(mem)
del p
f.close()
def writeASM(filename):
global mem
if not filename.endswith('.asm'):
filename = filename + '.asm'
address = -1
lines = ""
addrlist = mem.keys()
addrlist.sort()
for addr in addrlist:
addrint = int(addr, 8)
code = mem.getCode(addrint)
opcode = mem.getOp(addrint)
field = mem.getFld(addrint)
lab = mem.getLabcount(addrint)
ref = mem.getRef(addrint)
label = ""
if lab > 0:
label = "L%05o" % effAddr(int(addr, 8))
if ref:
if field[0] == '*':
field = "*L%s" % field[1:]
else:
field = "L%s" % field
if addrint != address:
if addrint >= 0:
lines += "\t\t\t;\n"
lines += "\tORG\t%05o\t; addr code\n" % addrint
address = addrint
lines += "%s\t%s\t%s\t; %s %07o\n" % (label, opcode, field, addr, code)
address += 1
lines += "\tEND\t\t;\n"
f = open(filename, "w")
f.writelines(lines)
f.close
def fillGrid(grid, mem):
importrows = mem.len()
currentrows = grid.GetNumberRows()
if currentrows > importrows:
grid.DeleteRows(0, (currentrows - importrows))
elif importrows > currentrows:
grid.AppendRows(importrows - currentrows)
addrlist = mem.keys()
addrlist.sort()
importrows = len(addrlist)
currentrows = grid.GetNumberRows()
if currentrows > importrows:
grid.DeleteRows(0, (currentrows - importrows))
elif importrows > currentrows:
grid.AppendRows(importrows - currentrows)
i = 0
for address in addrlist:
addr = int(address, 8)
code = mem.getCode(addr)
opcode = mem.getOp(addr)
field = mem.getFld(addr)
lab = mem.getLabcount(addr)
ref = mem.getRef(addr)
label = ""
if lab > 0:
label = "L%05o" % effAddr(addr)
if ref:
if field[0] == '*':
field = "*L%s" % field[1:]
else:
field = "L%s" % field
grid.SetCellValue(i, 0, label)
grid.SetCellValue(i, 1, opcode)
grid.SetCellValue(i, 2, field)
grid.SetCellValue(i, 3, address)
grid.SetCellValue(i, 4, "%06o" % code)
i += 1
grid.ForceRefresh()
class MyPopupMenu(wx.Menu):
def __init__(self, WinName):
global grid
rows = grid.GetSelectedRows()
wx.Menu.__init__(self)
self.WinName = WinName
item = wx.MenuItem(self, wx.NewId(), "Process as MAIN instructions")
self.AppendItem(item)
self.Bind(wx.EVT_MENU, self.popupDoMain, item)
item = wx.MenuItem(self, wx.NewId(), "Process as DISPLAY instructions")
self.AppendItem(item)
self.Bind(wx.EVT_MENU, self.popupDoDisplay, item)
item = wx.MenuItem(self, wx.NewId(), "Process as DATA instructions")
self.AppendItem(item)
self.Bind(wx.EVT_MENU, self.popupDoData, item)
self.AppendSeparator()
item = wx.MenuItem(self, wx.NewId(), "Set reference")
self.AppendItem(item)
self.Bind(wx.EVT_MENU, self.popupSetRef, item)
if len(rows) > 1:
item.Enable(False)
item = wx.MenuItem(self, wx.NewId(), "Clear reference")
self.AppendItem(item)
self.Bind(wx.EVT_MENU, self.popupClearRef, item)
if len(rows) > 1:
item.Enable(False)
self.AppendSeparator()
item = wx.MenuItem(self, wx.NewId(), "DEBUG: print types")
self.AppendItem(item)
self.Bind(wx.EVT_MENU, self.popupDoType, item)
def popupDoMain(self, event):
global grid, mem, newcycle, frame
rows = grid.GetSelectedRows()
addrlist = []
for row in rows:
addrlist.append(int(grid.GetCellValue(row, 3), 8))
thiscycle = newcycle.next()
mem.setUndo()
processmain.process(mem, addrlist, thiscycle)
fillGrid(grid, mem)
grid.ClearSelection()
frame.enableUndo(True)
def popupDoDisplay(self, event):
global grid, mem, newcycle
rows = grid.GetSelectedRows()
addrlist = []
for row in rows:
addrlist.append(int(grid.GetCellValue(row, 3), 8))
thiscycle = newcycle.next()
mem.setUndo()
processdisplay.process(mem, addrlist, thiscycle)
fillGrid(grid, mem)
grid.ClearSelection()
frame.enableUndo(True)
def popupDoData(self, event):
global grid, mem, newcycle
thiscycle = newcycle.next()
mem.setUndo()
for row in grid.GetSelectedRows():
addr = int(grid.GetCellValue(row, 3), 8)
processdata.process(mem, addr, thiscycle)
fillGrid(grid, mem)
grid.ClearSelection()
frame.enableUndo(True)
def popupSetRef(self, event):
global grid, mem
row = grid.GetSelectedRows()[0]
addrstr = grid.GetCellValue(row, 3)
addr = int(addrstr, 8)
ref = mem.getRef(addr)
memref = int(mem.getFld(addr), 8)
mem.setUndo()
if ref:
mem.decLab(memref)
mem.incLab(memref)
mem.setRef(addr)
fillGrid(grid, mem)
grid.ClearSelection()
frame.enableUndo(True)
def popupClearRef(self, event):
global grid, mem
row = grid.GetSelectedRows()[0]
addrstr = grid.GetCellValue(row, 3)
addr = int(addrstr, 8)
ref = mem.getRef(addr)
memref = int(mem.getFld(addr), 8)
if ref:
mem.setUndo()
mem.decLab(memref)
mem.clearRef(addr)
fillGrid(grid, mem)
grid.ClearSelection()
frame.enableUndo(True)
def popupDoType(self, event):
global grid, mem
for row in grid.GetSelectedRows():
addrstr = grid.GetCellValue(row, 3)
addr = int(addrstr, 8)
word = mem.getCode(addr)
cycle = mem.getCycle(addr)
type = mem.getType(addr)
lab = mem.getLabcount(addr)
ref = mem.getRef(addr)
print "row %d, addr=%s, code=%05o, cycle=%d, type=%s, lab=%s, ref=%s" % \
(row, addrstr, word, cycle, type, lab, ref)
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
global grid
# kwds["style"] = wx.MINIMIZE_BOX | wx.SYSTEM_MENU | \
# wx.CLOSE_BOX | wx.CAPTION
wx.Frame.__init__(self, *args, **kwds)
self.grid = wx.grid.Grid(self, -1, size=(353, 800))
grid = self.grid
self.__set_properties()
self.__do_layout()
self.Centre()
self.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK, \
self.onGridCellRightClick, self.grid)
def __set_properties(self):
self.SetTitle(PROGRAMNAME + " " + PROGRAMVERSION)
status = self.CreateStatusBar(2, 0)
status.SetMinHeight(100)
self.SetStatusWidths([280, 70])
self.menu = self.initMenus()
self.initGrid()
def __do_layout(self):
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.grid, 1, wx.EXPAND, 0)
self.SetSizer(sizer)
sizer.Fit(self)
self.Layout()
def initMenus(self):
result = wx.MenuBar()
fileMenu = wx.Menu()
fileMenu.Append(100, "Load Project", "Load disassembly project")
self.saveMenuitem = fileMenu.Append(101, "Save Project", "Save disassembly project")
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", \
"Write an assembler source file")
fileMenu.AppendSeparator()
fileMenu.Append(199, "Exit", "Exit the program")
result.Append(fileMenu, "File")
editMenu = wx.Menu()
self.editMenu = editMenu.Append(309, "Undo", "Undo last change")
self.enableUndo(False)
result.Append(editMenu, "Edit")
helpMenu = wx.Menu()
self.helpMenu = helpMenu.Append(202, "Help", "Help on using this program")
self.helpMenu.Enable(False)
helpMenu.AppendSeparator()
helpMenu.Append(203, "About", "About this program")
result.Append(helpMenu, "Help")
self.SetMenuBar(result)
self.Bind(wx.EVT_MENU, self.Menu100, id=100)
self.Bind(wx.EVT_MENU, self.Menu101, id=101)
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.Menu199, id=199)
self.Bind(wx.EVT_MENU, self.Menu202, id=202)
self.Bind(wx.EVT_MENU, self.Menu203, id=203)
self.Bind(wx.EVT_MENU, self.Menu309, id=309)
self.enableSaveWrite(False)
return result
def enableSaveWrite(self, enable):
self.saveMenuitem.Enable(enable)
self.saveAsMenuitem.Enable(enable)
self.writeASMMenuitem.Enable(enable)
def enableUndo(self, enable):
self.editMenu.Enable(enable)
def initGrid(self):
self.grid.CreateGrid(0, 5)
self.grid.EnableGridLines(False)
self.grid.SetSelectionMode(1)
self.grid.SetDefaultRowSize(15)
self.grid.SetRowLabelSize(37)
self.grid.SetColLabelSize(20)
self.grid.SetDefaultCellAlignment(wx.ALIGN_LEFT, wx.ALIGN_CENTER)
self.grid.SetColLabelValue(0, "Label")
self.grid.SetColSize(0, 65)
self.grid.SetColLabelValue(1, "Op")
self.grid.SetColSize(1, 65)
self.grid.SetColLabelValue(2, "Field")
self.grid.SetColSize(2, 65)
self.grid.SetColLabelValue(3, "Address")
self.grid.SetColSize(3, 65)
self.grid.SetColLabelValue(4, "Code")
self.grid.SetColSize(4, 65)
self.grid.DisableDragColSize()
self.grid.DisableDragRowSize()
self.grid.DisableDragColMove()
self.grid.EnableEditing(False)
self.grid.SetColLabelAlignment(wx.ALIGN_LEFT, wx.ALIGN_BOTTOM)
self.grid.SetRowLabelAlignment(wx.ALIGN_RIGHT, wx.ALIGN_CENTER)
self.AddrAttr = wx.grid.GridCellAttr()
self.AddrAttr.SetBackgroundColour(wx.NamedColour('papayawhip'))
self.grid.SetColAttr(3, self.AddrAttr)
self.CodeAttr = wx.grid.GridCellAttr()
self.CodeAttr.SetBackgroundColour(wx.NamedColour('lightgrey'))
self.grid.SetColAttr(4, self.CodeAttr)
self.grid.ForceRefresh()
def onGridCellRightClick(self, event):
if self.grid.GetSelectedRows():
self.PopupMenu(MyPopupMenu("test"), event.GetPosition())
else:
self.grid.ClearSelection()
event.Skip()
def Menu100(self, event):
global mem, projectName
filename = None
dlg = wx.FileDialog(self, message="Choose a project file to load",
defaultDir=os.getcwd(), defaultFile=projectName,
wildcard=projwildcard,
style=wx.OPEN | wx.CHANGE_DIR)
if dlg.ShowModal() == wx.ID_OK:
filename = dlg.GetPaths()[0]
self.grid.ClearGrid()
mem = loadProject(filename)
fillGrid(self.grid, mem)
projectName = os.path.basename(filename)
if projectName.endswith(DEFPROJSUFFIX):
projectName = projectName[:-len(DEFPROJSUFFIX)]
dlg.Destroy()
self.enableSaveWrite(True)
mem.clearUndo()
self.enableUndo(False)
def Menu101(self, event):
global mem, projectName
filename = projectName + DEFPROJSUFFIX
if projectName == "":
dlg = wx.FileDialog(self,
message="Choose a project file to save to",
defaultDir=os.getcwd(), defaultFile="",
wildcard=projwildcard,
style=wx.SAVE | wx.CHANGE_DIR)
if dlg.ShowModal() == wx.ID_OK:
filename = dlg.GetPaths()[0]
if not filename.endswith(DEFPROJSUFFIX):
filename = filename + DEFPROJSUFFIX
projectName = os.path.basename(filename)
if projectName.endswith(DEFPROJSUFFIX):
projectName = projectName[:-len(DEFPROJSUFFIX)]
dlg.Destroy()
saveProject(filename)
def Menu102(self, event):
global mem, projectName
dlg = wx.FileDialog(self,
message="Choose a project file to save as",
defaultDir=os.getcwd(), defaultFile="",
wildcard=projwildcard,
style=wx.SAVE | wx.CHANGE_DIR)
if dlg.ShowModal() == wx.ID_OK:
filename = dlg.GetPaths()[0]
saveProject(filename)
projectName = os.path.basename(filename)
if projectName.endswith(DEFPROJSUFFIX):
projectName = projectName[:-len(DEFPROJSUFFIX)]
dlg.Destroy()
def Menu103(self, event):
global 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.GetPaths()[0]
self.grid.ClearGrid()
mem = binimport.ptpimport(filename)
addrlist = mem.keys()
addrlist.sort()
importrows = len(addrlist)
currentrows = self.grid.GetNumberRows()
if currentrows > importrows:
self.grid.DeleteRows(0, (currentrows - importrows))
elif importrows > currentrows:
self.grid.AppendRows(importrows - currentrows)
i = 0
for addr in addrlist:
(code, op, fld, labcount, ref, type, cycle) = mem.getMem(int(addr, 8))
self.grid.SetCellValue(i, 1, op)
self.grid.SetCellValue(i, 2, fld)
self.grid.SetCellValue(i, 3, addr)
self.grid.SetCellValue(i, 4, "%06o" % code)
i += 1
self.grid.ForceRefresh()
projectName = os.path.basename(filename)
if projectName.endswith(DEFPTPSUFFIX):
projectName = projectName[:-len(DEFPTPSUFFIX)]
dlg.Destroy()
self.enableSaveWrite(True)
mem.clearUndo()
self.enableUndo(False)
def Menu104(self, event):
global mem, grid, projectName
filename = None
dlg = wx.FileDialog(self,
message="Choose an IMLAC assembler file to write",
defaultDir=os.getcwd(),
defaultFile=projectName + DEFASMSUFFIX,
wildcard=objwildcard,
style=wx.SAVE | wx.CHANGE_DIR)
if dlg.ShowModal() == wx.ID_OK:
filename = dlg.GetPaths()[0]
writeASM(filename)
projectName = os.path.basename(filename)
if projectName.endswith(DEFASMSUFFIX):
projectName = projectName[:-len(DEFASMSUFFIX)]
dlg.Destroy()
def Menu199(self, event):
self.Close()
def Menu202(self, event):
print "Would show help here"
def Menu203(self, event):
from wx.lib.wordwrap import wordwrap
info = wx.AboutDialogInfo()
info.Name = PROGRAMNAME
info.Version = PROGRAMVERSION
info.Copyright = "\n(C) 2007 Autotelic Systems"
info.WebSite = ("http://www.manontroppo.org", "www.manontroppo.org")
info.Description = wordwrap("\nidasm is an interactive disassembler for "
"IMLAC object files\n",
350, wx.ClientDC(self))
info.License = wordwrap("Licenced under the GPL (version 2)", 500, wx.ClientDC(self))
wx.AboutBox(info)
def Menu309(self, event):
global mem, grid
mem.undoX()
fillGrid(grid, mem)
class MyApp(wx.App):
def OnInit(self):
global frame
wx.InitAllImageHandlers()
frame = MyFrame(None, -1, "")
self.SetTopWindow(frame)
frame.Show()
return 1
if __name__ == "__main__":
app = MyApp(0)
app.MainLoop()

129
pymlac/octdump Executable file
View File

@@ -0,0 +1,129 @@
#!/usr/bin/env python
"""
File octal dump program.
Tool used developinf pymlac.
"""
import sys
import getopt
import os.path
OCTLEN = 55
CHARLEN = 16
def octaldump(filename):
"""A function that generates an 'octal dump' of a file.
Calling this function for a file containing
'The quick brown fox\n\tjumps over the lazy dog.'
returns a string containing:
0000000 000001 002003 004005 006007 010011 012013 014015 016017 |The quick brown |
0000010 020021 022023 024025 026027 030031 032033 034035 036037 |fox..jumps over |
0000020 040041 042043 044045 046047 050051 052053 054055 |the lazy dog.|
+---------+---------+---------+---------+---------+---------+---------+---------+---------+--
0 1 2 3 4 5 6 7 8 9
0 0 0 0 0 0 0 0 0 0
Each line of the dump contains info about 16 bytes or less of the input string.
The 7 octal digits starting at column 0 are the offset of the first word of
the line from the start of the file.
The 8 octal words starting at column 9 and ending at column 63 are the
8 word values in octal.
The characters spanning columns 61-82 are the 16 printable characters. If a
character is not printable it is replaced by a '.' character.
"""
with open(filename, 'rb', 8192) as f:
offset = 0
while True:
data = f.read(16)
if len(data) == 0:
break
try:
print(octaldump_line(data, offset))
except IOError:
return
offset += 8
def octaldump_line(s, offset):
"""Generate one line of fdump output.
s string to convert (16 bytes or less)
offset offset from start of dump
"""
oct = ''
char = ''
# iterate over string 2 chars at a time
for (high, low) in zip(s[0::2], s[1::2]):
high_ord = ord(high)
low_ord = ord(low)
value = (high_ord << 8) + low_ord
oct += '%07o ' % value
if ord(' ') <= high_ord <= ord('~'):
char += high
else:
char += '.'
if ord(' ') <= low_ord <= ord('~'):
char += low
else:
char += '.'
oct = (oct + ' '*OCTLEN)[:OCTLEN]
char = (char + '|' + ' '*CHARLEN)[:CHARLEN+1]
return '%07o %s |%s' % (offset, oct, char)
################################################################################
ProgName = None
def usage():
print 'usage: %s <file>' % ProgName
print 'where <file> is the file to produce the octaldump of.'
def main(argv):
global ProgName
ProgName = os.path.basename(argv[0])
try:
opts, args = getopt.gnu_getopt(argv, "h", ["help"])
except getopt.GetoptError:
usage()
return 10
for opt, arg in opts:
if opt in ("-h", "--help"):
usage()
return 0
if len(args) != 2:
usage()
return 10
filename = args[1]
try:
f = open(filename)
except IOError:
print "Sorry, can't find file '%s'" % filename
return 10
f.close()
octaldump(filename)
if __name__ == "__main__":
sys.exit(main(sys.argv))