mirror of
https://github.com/mnaberez/py65.git
synced 2024-12-28 00:29:19 +00:00
PEP8
This commit is contained in:
parent
e8565a6e81
commit
8f284a8e58
@ -6,6 +6,8 @@
|
||||
- Fixed assembling 65C02 opcodes whose mnemonics have a digit
|
||||
such as "RMB3".
|
||||
|
||||
- Reformatted source code to comply with PEP8.
|
||||
|
||||
0.13 (2012-11-15)
|
||||
|
||||
- Fixed a bug where negative numbers could be entered
|
||||
|
23
docs/conf.py
23
docs/conf.py
@ -3,15 +3,18 @@
|
||||
# test documentation build configuration file, created by
|
||||
# sphinx-quickstart on Sun Nov 30 14:39:06 2008.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its containing dir.
|
||||
# This file is execfile()d with the current dir set to its containing
|
||||
# directory.
|
||||
#
|
||||
# The contents of this file are pickled, so don't put values in the namespace
|
||||
# that aren't pickleable (module imports are okay, they're removed automatically).
|
||||
# that aren't pickleable (module imports are okay, they're removed
|
||||
# automatically).
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys, os
|
||||
import os
|
||||
import sys
|
||||
|
||||
# If your extensions are in another directory, add it here. If the directory
|
||||
# is relative to the documentation root, use os.path.abspath to make it
|
||||
@ -21,8 +24,8 @@ import sys, os
|
||||
# General configuration
|
||||
# ---------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = ['sphinx.ext.autodoc']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
@ -67,7 +70,8 @@ release = '0.14-dev'
|
||||
# for source files.
|
||||
exclude_trees = []
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
@ -163,10 +167,11 @@ htmlhelp_basename = 'testdoc'
|
||||
#latex_font_size = '10pt'
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, document class [howto/manual]).
|
||||
# (source start file, target name, title, author, document class
|
||||
# [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'test.tex', ur'test Documentation',
|
||||
ur'foo', 'manual'),
|
||||
('index', 'test.tex', ur'test Documentation',
|
||||
ur'foo', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
|
@ -2,44 +2,76 @@ import re
|
||||
from py65.devices.mpu6502 import MPU
|
||||
from py65.utils.addressing import AddressParser
|
||||
|
||||
|
||||
class Assembler:
|
||||
Statement = re.compile(r'^([A-z]{3}[0-7]?\s+'
|
||||
r'\(?\s*)([^,\s\)]+)(\s*[,xXyY\s]*\)?'
|
||||
r'[,xXyY\s]*)$')
|
||||
|
||||
Addressing8 = [
|
||||
['zpi', re.compile(r'^\(\$00([0-9A-F]{2})\)$')], # "($0012)"
|
||||
['zpx', re.compile(r'^\$00([0-9A-F]{2}),X$')], # "$0012,X"
|
||||
['zpy', re.compile(r'^\$00([0-9A-F]{2}),Y$')], # "$0012,Y"
|
||||
['zpg', re.compile(r'^\$00([0-9A-F]{2})$')], # "$0012"
|
||||
['inx', re.compile(r'^\(\$00([0-9A-F]{2}),X\)$')], # "($0012,X)"
|
||||
['iny', re.compile(r'^\(\$00([0-9A-F]{2})\),Y$')], # "($0012),Y"
|
||||
['ind', re.compile(r'^\(\$([0-9A-F]{2})([0-9A-F]{2})\)$')], # "($1234)"
|
||||
['abx', re.compile(r'^\$([0-9A-F]{2})([0-9A-F]{2}),X$')], # "$1234,X"
|
||||
['aby', re.compile(r'^\$([0-9A-F]{2})([0-9A-F]{2}),Y$')], # "$1234,Y"
|
||||
['abs', re.compile(r'^\$([0-9A-F]{2})([0-9A-F]{2})$')], # "$1234"
|
||||
['rel', re.compile(r'^\$([0-9A-F]{2})([0-9A-F]{2})$')], # "$1234"
|
||||
['imp', re.compile(r'^$')], # ""
|
||||
['acc', re.compile(r'^$')], # ""
|
||||
['acc', re.compile(r'^A$')], # "A"
|
||||
['imm', re.compile(r'^#\$([0-9A-F]{2})$')] # "#$12"
|
||||
['zpi', # "($0012)"
|
||||
re.compile(r'^\(\$00([0-9A-F]{2})\)$')],
|
||||
['zpx', # "$0012,X"
|
||||
re.compile(r'^\$00([0-9A-F]{2}),X$')],
|
||||
['zpy', # "$0012,Y"
|
||||
re.compile(r'^\$00([0-9A-F]{2}),Y$')],
|
||||
['zpg', # "$0012"
|
||||
re.compile(r'^\$00([0-9A-F]{2})$')],
|
||||
['inx', # "($0012,X)
|
||||
re.compile(r'^\(\$00([0-9A-F]{2}),X\)$')],
|
||||
['iny', # "($0012),Y"
|
||||
re.compile(r'^\(\$00([0-9A-F]{2})\),Y$')],
|
||||
['ind', # "($1234)"
|
||||
re.compile(r'^\(\$([0-9A-F]{2})([0-9A-F]{2})\)$')],
|
||||
['abx', # "$1234,X"
|
||||
re.compile(r'^\$([0-9A-F]{2})([0-9A-F]{2}),X$')],
|
||||
['aby', # "$1234,Y"
|
||||
re.compile(r'^\$([0-9A-F]{2})([0-9A-F]{2}),Y$')],
|
||||
['abs', # "$1234"
|
||||
re.compile(r'^\$([0-9A-F]{2})([0-9A-F]{2})$')],
|
||||
['rel', # "$1234"
|
||||
re.compile(r'^\$([0-9A-F]{2})([0-9A-F]{2})$')],
|
||||
['imp', # ""
|
||||
re.compile(r'^$')],
|
||||
['acc', # ""
|
||||
re.compile(r'^$')],
|
||||
['acc', # "A"
|
||||
re.compile(r'^A$')],
|
||||
['imm', # "#$12"
|
||||
re.compile(r'^#\$([0-9A-F]{2})$')]
|
||||
]
|
||||
|
||||
Addressing16 = [
|
||||
['zpi', re.compile(r'^\(\$0000([0-9A-F]{4})\)$')], # "($00001234)"
|
||||
['zpx', re.compile(r'^\$0000([0-9A-F]{4}),X$')], # "$00001234,X"
|
||||
['zpy', re.compile(r'^\$0000([0-9A-F]{4}),Y$')], # "$00001234,Y"
|
||||
['zpg', re.compile(r'^\$0000([0-9A-F]{4})$')], # "$00001234"
|
||||
['inx', re.compile(r'^\(\$0000([0-9A-F]{4}),X\)$')], # "($00001234,X)"
|
||||
['iny', re.compile(r'^\(\$0000([0-9A-F]{4})\),Y$')], # "($00001234),Y"
|
||||
['ind', re.compile(r'^\(\$([0-9A-F]{4})([0-9A-F]{4})\)$')], # "($12345678)"
|
||||
['abx', re.compile(r'^\$([0-9A-F]{4})([0-9A-F]{4}),X$')], # "$12345678,X"
|
||||
['aby', re.compile(r'^\$([0-9A-F]{4})([0-9A-F]{4}),Y$')], # "$12345678,Y"
|
||||
['abs', re.compile(r'^\$([0-9A-F]{4})([0-9A-F]{4})$')], # "$12345678"
|
||||
['rel', re.compile(r'^\$([0-9A-F]{4})([0-9A-F]{4})$')], # "$12345678"
|
||||
['imp', re.compile(r'^$')], # ""
|
||||
['acc', re.compile(r'^$')], # ""
|
||||
['acc', re.compile(r'^A$')], # "A"
|
||||
['imm', re.compile(r'^#\$([0-9A-F]{4})$')] # "#$1234"
|
||||
['zpi', # "($00001234)"
|
||||
re.compile(r'^\(\$0000([0-9A-F]{4})\)$')],
|
||||
['zpx', # "$00001234,X"
|
||||
re.compile(r'^\$0000([0-9A-F]{4}),X$')],
|
||||
['zpy', # "$00001234,Y"
|
||||
re.compile(r'^\$0000([0-9A-F]{4}),Y$')],
|
||||
['zpg', # "$00001234"
|
||||
re.compile(r'^\$0000([0-9A-F]{4})$')],
|
||||
['inx', # "($00001234,X)"
|
||||
re.compile(r'^\(\$0000([0-9A-F]{4}),X\)$')],
|
||||
['iny', # "($00001234),Y"
|
||||
re.compile(r'^\(\$0000([0-9A-F]{4})\),Y$')],
|
||||
['ind', # "($12345678)"
|
||||
re.compile(r'^\(\$([0-9A-F]{4})([0-9A-F]{4})\)$')],
|
||||
['abx', # "$12345678,X"
|
||||
re.compile(r'^\$([0-9A-F]{4})([0-9A-F]{4}),X$')],
|
||||
['aby', # "$12345678,Y"
|
||||
re.compile(r'^\$([0-9A-F]{4})([0-9A-F]{4}),Y$')],
|
||||
['abs', # "$12345678"
|
||||
re.compile(r'^\$([0-9A-F]{4})([0-9A-F]{4})$')],
|
||||
['rel', # "$12345678"
|
||||
re.compile(r'^\$([0-9A-F]{4})([0-9A-F]{4})$')],
|
||||
['imp', # ""
|
||||
re.compile(r'^$')],
|
||||
['acc', # ""
|
||||
re.compile(r'^$')],
|
||||
['acc', # "A"
|
||||
re.compile(r'^A$')],
|
||||
['imm', # "#$1234"
|
||||
re.compile(r'^#\$([0-9A-F]{4})$')]
|
||||
]
|
||||
Addressing = Addressing8
|
||||
|
||||
@ -77,7 +109,7 @@ class Assembler:
|
||||
|
||||
if match:
|
||||
try:
|
||||
bytes = [ self._mpu.disassemble.index((opcode, mode)) ]
|
||||
bytes = [self._mpu.disassemble.index((opcode, mode))]
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
@ -88,13 +120,13 @@ class Assembler:
|
||||
absolute = int(''.join(operands), 16)
|
||||
relative = (absolute - pc) - 2
|
||||
relative = relative & self.byteMask
|
||||
operands = [ (self.byteFmt % relative) ]
|
||||
operands = [(self.byteFmt % relative)]
|
||||
|
||||
elif len(operands) == 2:
|
||||
# swap bytes
|
||||
operands = (operands[1], operands[0])
|
||||
|
||||
operands = [ int(hex, 16) for hex in operands ]
|
||||
operands = [int(hex, 16) for hex in operands]
|
||||
bytes.extend(operands)
|
||||
return bytes
|
||||
|
||||
|
@ -1,34 +1,35 @@
|
||||
from py65.utils.conversions import convert_to_bin, convert_to_bcd, itoa
|
||||
from py65.utils.devices import make_instruction_decorator
|
||||
|
||||
|
||||
class MPU:
|
||||
# vectors
|
||||
ResetTo = 0xfffc
|
||||
IrqTo = 0xfffe
|
||||
NMITo = 0xfffa
|
||||
IrqTo = 0xfffe
|
||||
NMITo = 0xfffa
|
||||
|
||||
# processor flags
|
||||
NEGATIVE = 128
|
||||
OVERFLOW = 64
|
||||
UNUSED = 32
|
||||
BREAK = 16 # there is no BREAK flag, but this position indicates BREAK
|
||||
DECIMAL = 8
|
||||
NEGATIVE = 128
|
||||
OVERFLOW = 64
|
||||
UNUSED = 32
|
||||
BREAK = 16 # there is no actual BREAK flag but this indicates BREAK
|
||||
DECIMAL = 8
|
||||
INTERRUPT = 4
|
||||
ZERO = 2
|
||||
CARRY = 1
|
||||
ZERO = 2
|
||||
CARRY = 1
|
||||
|
||||
BYTE_WIDTH = 8
|
||||
BYTE_WIDTH = 8
|
||||
BYTE_FORMAT = "%02x"
|
||||
ADDR_WIDTH = 16
|
||||
ADDR_WIDTH = 16
|
||||
ADDR_FORMAT = "%04x"
|
||||
|
||||
def __init__(self, memory=None, pc=0x0000):
|
||||
# config
|
||||
self.name = '6502'
|
||||
self.byteMask = ((1<<self.BYTE_WIDTH)-1)
|
||||
self.addrMask = ((1<<self.ADDR_WIDTH)-1)
|
||||
self.addrHighMask = (self.byteMask<<self.BYTE_WIDTH)
|
||||
self.spBase = 1<<self.BYTE_WIDTH
|
||||
self.byteMask = ((1 << self.BYTE_WIDTH) - 1)
|
||||
self.addrMask = ((1 << self.ADDR_WIDTH) - 1)
|
||||
self.addrHighMask = (self.byteMask << self.BYTE_WIDTH)
|
||||
self.spBase = 1 << self.BYTE_WIDTH
|
||||
|
||||
# vm status
|
||||
self.excycles = 0
|
||||
@ -44,16 +45,15 @@ class MPU:
|
||||
self.reset()
|
||||
|
||||
def reprformat(self):
|
||||
return ("%s PC AC XR YR SP NV-BDIZC\n" + \
|
||||
"%s: %04x %02x %02x %02x %02x %s"
|
||||
)
|
||||
return ("%s PC AC XR YR SP NV-BDIZC\n"
|
||||
"%s: %04x %02x %02x %02x %02x %s")
|
||||
|
||||
def __repr__(self):
|
||||
flags = itoa(self.p, 2).rjust(self.BYTE_WIDTH, '0')
|
||||
flags = itoa(self.p, 2).rjust(self.BYTE_WIDTH, '0')
|
||||
indent = ' ' * (len(self.name) + 2)
|
||||
|
||||
return self.reprformat() % (indent, self.name,
|
||||
self.pc, self.a, self.x, self.y, self.sp, flags)
|
||||
return self.reprformat() % (indent, self.name, self.pc, self.a,
|
||||
self.x, self.y, self.sp, flags)
|
||||
|
||||
def step(self):
|
||||
instructCode = self.memory[self.pc]
|
||||
@ -61,7 +61,7 @@ class MPU:
|
||||
self.excycles = 0
|
||||
self.addcycles = self.extracycles[instructCode]
|
||||
self.instruct[instructCode](self)
|
||||
self.processorCycles += self.cycletime[instructCode]+self.excycles
|
||||
self.processorCycles += self.cycletime[instructCode] + self.excycles
|
||||
return self
|
||||
|
||||
def reset(self):
|
||||
@ -103,20 +103,20 @@ class MPU:
|
||||
return self.byteMask & (self.y + self.ByteAt(self.pc))
|
||||
|
||||
def IndirectXAddr(self):
|
||||
return self.WrapAt( self.byteMask & (self.ByteAt(self.pc) + self.x))
|
||||
return self.WrapAt(self.byteMask & (self.ByteAt(self.pc) + self.x))
|
||||
|
||||
def IndirectYAddr(self):
|
||||
if self.addcycles:
|
||||
a1 = self.WrapAt(self.ByteAt(self.pc))
|
||||
a2 = (a1+self.y) & self.addrMask
|
||||
a2 = (a1 + self.y) & self.addrMask
|
||||
if (a1 & self.addrHighMask) != (a2 & self.addrHighMask):
|
||||
self.excycles += 1
|
||||
return a2
|
||||
else:
|
||||
return (self.WrapAt(self.ByteAt(self.pc))+self.y)&self.addrMask
|
||||
return (self.WrapAt(self.ByteAt(self.pc)) + self.y) & self.addrMask
|
||||
|
||||
def AbsoluteAddr(self):
|
||||
return self.WordAt(self.pc)
|
||||
return self.WordAt(self.pc)
|
||||
|
||||
def AbsoluteXAddr(self):
|
||||
if self.addcycles:
|
||||
@ -126,7 +126,7 @@ class MPU:
|
||||
self.excycles += 1
|
||||
return a2
|
||||
else:
|
||||
return (self.WordAt(self.pc)+self.x)&self.addrMask
|
||||
return (self.WordAt(self.pc) + self.x) & self.addrMask
|
||||
|
||||
def AbsoluteYAddr(self):
|
||||
if self.addcycles:
|
||||
@ -136,7 +136,7 @@ class MPU:
|
||||
self.excycles += 1
|
||||
return a2
|
||||
else:
|
||||
return (self.WordAt(self.pc)+self.y)&self.addrMask
|
||||
return (self.WordAt(self.pc) + self.y) & self.addrMask
|
||||
|
||||
def BranchRelAddr(self):
|
||||
self.excycles += 1
|
||||
@ -155,23 +155,23 @@ class MPU:
|
||||
|
||||
# stack
|
||||
|
||||
def stPush(self,z):
|
||||
self.memory[self.sp+self.spBase] = z&self.byteMask
|
||||
def stPush(self, z):
|
||||
self.memory[self.sp + self.spBase] = z & self.byteMask
|
||||
self.sp -= 1
|
||||
self.sp &= self.byteMask
|
||||
|
||||
def stPop(self):
|
||||
self.sp += 1
|
||||
self.sp &= self.byteMask
|
||||
return self.ByteAt(self.sp+self.spBase)
|
||||
return self.ByteAt(self.sp + self.spBase)
|
||||
|
||||
def stPushWord(self, z):
|
||||
self.stPush((z>>self.BYTE_WIDTH)&self.byteMask)
|
||||
self.stPush(z&self.byteMask)
|
||||
self.stPush((z >> self.BYTE_WIDTH) & self.byteMask)
|
||||
self.stPush(z & self.byteMask)
|
||||
|
||||
def stPopWord(self):
|
||||
z = self.stPop()
|
||||
z += self.stPop()<<self.BYTE_WIDTH
|
||||
z += self.stPop() << self.BYTE_WIDTH
|
||||
return z
|
||||
|
||||
def FlagsNZ(self, value):
|
||||
@ -217,34 +217,34 @@ class MPU:
|
||||
addr = x()
|
||||
tbyte = self.ByteAt(addr)
|
||||
|
||||
self.p &=~(self.CARRY+self.NEGATIVE+self.ZERO)
|
||||
self.p |=tbyte&1
|
||||
self.p &= ~(self.CARRY + self.NEGATIVE + self.ZERO)
|
||||
self.p |= tbyte & 1
|
||||
|
||||
tbyte = tbyte >> 1
|
||||
if tbyte:
|
||||
pass # {}
|
||||
pass
|
||||
else:
|
||||
self.p |= self.ZERO
|
||||
|
||||
if x is None:
|
||||
self.a = tbyte
|
||||
else:
|
||||
self.memory[addr]=tbyte
|
||||
self.memory[addr] = tbyte
|
||||
|
||||
def opBCL(self, x):
|
||||
if self.p & x:
|
||||
self.pc += 1
|
||||
else:
|
||||
self.BranchRelAddr()
|
||||
if self.p & x:
|
||||
self.pc += 1
|
||||
else:
|
||||
self.BranchRelAddr()
|
||||
|
||||
def opBST(self, x):
|
||||
if self.p & x:
|
||||
self.BranchRelAddr()
|
||||
else:
|
||||
self.pc += 1
|
||||
if self.p & x:
|
||||
self.BranchRelAddr()
|
||||
else:
|
||||
self.pc += 1
|
||||
|
||||
def opCLR(self, x):
|
||||
self.p &=~x
|
||||
self.p &= ~x
|
||||
|
||||
def opSET(self, x):
|
||||
self.p |= x
|
||||
@ -255,10 +255,10 @@ class MPU:
|
||||
|
||||
def opBIT(self, x):
|
||||
tbyte = self.ByteAt(x())
|
||||
self.p &=~(self.ZERO+self.NEGATIVE+self.OVERFLOW)
|
||||
self.p &= ~(self.ZERO + self.NEGATIVE + self.OVERFLOW)
|
||||
if (self.a & tbyte) == 0:
|
||||
self.p |= self.ZERO
|
||||
self.p |= tbyte&(self.NEGATIVE+self.OVERFLOW)
|
||||
self.p |= tbyte & (self.NEGATIVE + self.OVERFLOW)
|
||||
|
||||
def opROL(self, x):
|
||||
if x is None:
|
||||
@ -281,7 +281,7 @@ class MPU:
|
||||
self.FlagsNZ(tbyte)
|
||||
|
||||
if x is None:
|
||||
self.a = tbyte
|
||||
self.a = tbyte
|
||||
else:
|
||||
self.memory[addr] = tbyte
|
||||
|
||||
@ -314,14 +314,14 @@ class MPU:
|
||||
# the final A contents will be decimally adjusted
|
||||
nibble0 = (nibble0 + adjust0) & 0xf
|
||||
nibble1 = (nibble1 + adjust1) & 0xf
|
||||
self.p &= ~(self.CARRY+self.OVERFLOW+self.NEGATIVE+self.ZERO)
|
||||
self.p &= ~(self.CARRY + self.OVERFLOW + self.NEGATIVE + self.ZERO)
|
||||
if aluresult == 0:
|
||||
self.p |= self.ZERO
|
||||
else:
|
||||
self.p |= aluresult & self.NEGATIVE
|
||||
if decimalcarry == 1:
|
||||
self.p |= self.CARRY
|
||||
if ( ~(self.a ^ data) & (self.a ^ aluresult) ) & self.NEGATIVE:
|
||||
if (~(self.a ^ data) & (self.a ^ aluresult)) & self.NEGATIVE:
|
||||
self.p |= self.OVERFLOW
|
||||
self.a = (nibble1 << 4) + nibble0
|
||||
else:
|
||||
@ -330,13 +330,13 @@ class MPU:
|
||||
else:
|
||||
tmp = 0
|
||||
result = data + self.a + tmp
|
||||
self.p &= ~(self.CARRY+self.OVERFLOW+self.NEGATIVE+self.ZERO)
|
||||
if ( ~(self.a ^ data) & (self.a ^ result) ) & self.NEGATIVE:
|
||||
self.p &= ~(self.CARRY + self.OVERFLOW + self.NEGATIVE + self.ZERO)
|
||||
if (~(self.a ^ data) & (self.a ^ result)) & self.NEGATIVE:
|
||||
self.p |= self.OVERFLOW
|
||||
data = result
|
||||
if data > self.byteMask:
|
||||
self.p |= self.CARRY
|
||||
data &=self.byteMask
|
||||
data &= self.byteMask
|
||||
if data == 0:
|
||||
self.p |= self.ZERO
|
||||
else:
|
||||
@ -347,19 +347,19 @@ class MPU:
|
||||
if x is None:
|
||||
tbyte = self.a
|
||||
else:
|
||||
addr=x()
|
||||
addr = x()
|
||||
tbyte = self.ByteAt(addr)
|
||||
|
||||
if self.p & self.CARRY:
|
||||
if tbyte & 1:
|
||||
pass # {}
|
||||
pass
|
||||
else:
|
||||
self.p &=~ self.CARRY
|
||||
tbyte=(tbyte>>1)|self.NEGATIVE
|
||||
self.p &= ~self.CARRY
|
||||
tbyte = (tbyte >> 1) | self.NEGATIVE
|
||||
else:
|
||||
if tbyte & 1:
|
||||
self.p |= self.CARRY
|
||||
tbyte=tbyte>>1
|
||||
if tbyte & 1:
|
||||
self.p |= self.CARRY
|
||||
tbyte = tbyte >> 1
|
||||
self.FlagsNZ(tbyte)
|
||||
|
||||
if x is None:
|
||||
@ -378,7 +378,7 @@ class MPU:
|
||||
|
||||
def opCMPR(self, get_address, register_value):
|
||||
tbyte = self.ByteAt(get_address())
|
||||
self.p &= ~(self.CARRY+self.ZERO+self.NEGATIVE)
|
||||
self.p &= ~(self.CARRY + self.ZERO + self.NEGATIVE)
|
||||
if register_value == tbyte:
|
||||
self.p |= self.CARRY + self.ZERO
|
||||
elif register_value > tbyte:
|
||||
@ -386,59 +386,61 @@ class MPU:
|
||||
self.p |= (register_value - tbyte) & self.NEGATIVE
|
||||
|
||||
def opSBC(self, x):
|
||||
data = self.ByteAt(x())
|
||||
data = self.ByteAt(x())
|
||||
|
||||
if self.p & self.DECIMAL:
|
||||
halfcarry = 1
|
||||
decimalcarry = 0
|
||||
adjust0 = 0
|
||||
adjust1 = 0
|
||||
if self.p & self.DECIMAL:
|
||||
halfcarry = 1
|
||||
decimalcarry = 0
|
||||
adjust0 = 0
|
||||
adjust1 = 0
|
||||
|
||||
nibble0 = (self.a & 0xf) + (~data & 0xf) + (self.p & self.CARRY)
|
||||
if nibble0 <= 0xf:
|
||||
halfcarry = 0
|
||||
adjust0 = 10
|
||||
nibble1 = ((self.a >> 4) & 0xf) + ((~data >> 4) & 0xf) + halfcarry
|
||||
if nibble1 <= 0xf:
|
||||
adjust1 = 10 << 4
|
||||
nibble0 = (self.a & 0xf) + (~data & 0xf) + (self.p & self.CARRY)
|
||||
if nibble0 <= 0xf:
|
||||
halfcarry = 0
|
||||
adjust0 = 10
|
||||
nibble1 = ((self.a >> 4) & 0xf) + ((~data >> 4) & 0xf) + halfcarry
|
||||
if nibble1 <= 0xf:
|
||||
adjust1 = 10 << 4
|
||||
|
||||
# the ALU outputs are not decimally adjusted
|
||||
aluresult = self.a + (~data & self.byteMask) + (self.p & self.CARRY)
|
||||
if aluresult > self.byteMask:
|
||||
decimalcarry = 1
|
||||
aluresult &= self.byteMask
|
||||
# the ALU outputs are not decimally adjusted
|
||||
aluresult = self.a + (~data & self.byteMask) + \
|
||||
(self.p & self.CARRY)
|
||||
|
||||
# but the final result will be adjusted
|
||||
nibble0 = (aluresult + adjust0) & 0xf
|
||||
nibble1 = ((aluresult + adjust1) >> 4) & 0xf
|
||||
if aluresult > self.byteMask:
|
||||
decimalcarry = 1
|
||||
aluresult &= self.byteMask
|
||||
|
||||
self.p &= ~(self.CARRY + self.ZERO + self.NEGATIVE + self.OVERFLOW)
|
||||
if aluresult == 0:
|
||||
self.p |= self.ZERO
|
||||
else:
|
||||
self.p |= aluresult & self.NEGATIVE
|
||||
if decimalcarry == 1:
|
||||
self.p |= self.CARRY
|
||||
if ( (self.a ^ data) & (self.a ^ aluresult) ) & self.NEGATIVE:
|
||||
self.p |= self.OVERFLOW
|
||||
self.a = (nibble1 << 4) + nibble0
|
||||
else:
|
||||
if self.p & self.CARRY:
|
||||
borrow = 0
|
||||
else:
|
||||
borrow = 1
|
||||
# but the final result will be adjusted
|
||||
nibble0 = (aluresult + adjust0) & 0xf
|
||||
nibble1 = ((aluresult + adjust1) >> 4) & 0xf
|
||||
|
||||
result = self.a + (~data & self.byteMask) + (self.p & self.CARRY)
|
||||
self.p &= ~(self.CARRY + self.ZERO + self.OVERFLOW + self.NEGATIVE)
|
||||
if ( (self.a ^ data) & (self.a ^ result) ) & self.NEGATIVE:
|
||||
self.p |= self.OVERFLOW
|
||||
data = result & self.byteMask
|
||||
if data == 0:
|
||||
self.p |= self.ZERO
|
||||
if result > self.byteMask:
|
||||
self.p |= self.CARRY
|
||||
self.p |= data & self.NEGATIVE
|
||||
self.a = data
|
||||
self.p &= ~(self.CARRY + self.ZERO + self.NEGATIVE + self.OVERFLOW)
|
||||
if aluresult == 0:
|
||||
self.p |= self.ZERO
|
||||
else:
|
||||
self.p |= aluresult & self.NEGATIVE
|
||||
if decimalcarry == 1:
|
||||
self.p |= self.CARRY
|
||||
if ((self.a ^ data) & (self.a ^ aluresult)) & self.NEGATIVE:
|
||||
self.p |= self.OVERFLOW
|
||||
self.a = (nibble1 << 4) + nibble0
|
||||
else:
|
||||
if self.p & self.CARRY:
|
||||
borrow = 0
|
||||
else:
|
||||
borrow = 1
|
||||
|
||||
result = self.a + (~data & self.byteMask) + (self.p & self.CARRY)
|
||||
self.p &= ~(self.CARRY + self.ZERO + self.OVERFLOW + self.NEGATIVE)
|
||||
if ((self.a ^ data) & (self.a ^ result)) & self.NEGATIVE:
|
||||
self.p |= self.OVERFLOW
|
||||
data = result & self.byteMask
|
||||
if data == 0:
|
||||
self.p |= self.ZERO
|
||||
if result > self.byteMask:
|
||||
self.p |= self.CARRY
|
||||
self.p |= data & self.NEGATIVE
|
||||
self.a = data
|
||||
|
||||
def opDECR(self, x):
|
||||
if x is None:
|
||||
@ -495,8 +497,8 @@ class MPU:
|
||||
def inst_not_implemented(self):
|
||||
self.pc += 1
|
||||
|
||||
instruct = [inst_not_implemented] * 256
|
||||
cycletime = [0] * 256
|
||||
instruct = [inst_not_implemented] * 256
|
||||
cycletime = [0] * 256
|
||||
extracycles = [0] * 256
|
||||
disassemble = [('???', 'imp')] * 256
|
||||
|
||||
@ -505,7 +507,8 @@ class MPU:
|
||||
|
||||
@instruction(name="BRK", mode="imp", cycles=7)
|
||||
def inst_0x00(self):
|
||||
pc = (self.pc + 1) & self.addrMask # The pc has already been increased one
|
||||
# pc has already been increased one
|
||||
pc = (self.pc + 1) & self.addrMask
|
||||
self.stPushWord(pc)
|
||||
|
||||
self.p |= self.BREAK
|
||||
@ -592,8 +595,8 @@ class MPU:
|
||||
|
||||
@instruction(name="JSR", mode="abs", cycles=6)
|
||||
def inst_0x20(self):
|
||||
self.stPushWord((self.pc+1)&self.addrMask)
|
||||
self.pc=self.WordAt(self.pc)
|
||||
self.stPushWord((self.pc + 1) & self.addrMask)
|
||||
self.pc = self.WordAt(self.pc)
|
||||
|
||||
@instruction(name="AND", mode="inx", cycles=6)
|
||||
def inst_0x21(self):
|
||||
@ -716,7 +719,7 @@ class MPU:
|
||||
|
||||
@instruction(name="JMP", mode="abs", cycles=3)
|
||||
def inst_0x4c(self):
|
||||
self.pc=self.WordAt(self.pc)
|
||||
self.pc = self.WordAt(self.pc)
|
||||
|
||||
@instruction(name="EOR", mode="abs", cycles=4)
|
||||
def inst_0x4d(self):
|
||||
@ -754,7 +757,7 @@ class MPU:
|
||||
@instruction(name="EOR", mode="aby", cycles=4, extracycles=1)
|
||||
def inst_0x59(self):
|
||||
self.opEOR(self.AbsoluteYAddr)
|
||||
self.pc +=2
|
||||
self.pc += 2
|
||||
|
||||
@instruction(name="EOR", mode="abx", cycles=4, extracycles=1)
|
||||
def inst_0x5d(self):
|
||||
@ -768,7 +771,7 @@ class MPU:
|
||||
|
||||
@instruction(name="RTS", mode="imp", cycles=6)
|
||||
def inst_0x60(self):
|
||||
self.pc=self.stPopWord()
|
||||
self.pc = self.stPopWord()
|
||||
self.pc += 1
|
||||
|
||||
@instruction(name="ADC", mode="inx", cycles=6)
|
||||
@ -808,7 +811,7 @@ class MPU:
|
||||
@instruction(name="ADC", mode="abs", cycles=4)
|
||||
def inst_0x6d(self):
|
||||
self.opADC(self.AbsoluteAddr)
|
||||
self.pc +=2
|
||||
self.pc += 2
|
||||
|
||||
@instruction(name="ROR", mode="abs", cycles=6)
|
||||
def inst_0x6e(self):
|
||||
@ -876,12 +879,12 @@ class MPU:
|
||||
@instruction(name="DEY", mode="imp", cycles=2)
|
||||
def inst_0x88(self):
|
||||
self.y -= 1
|
||||
self.y&=self.byteMask
|
||||
self.y &= self.byteMask
|
||||
self.FlagsNZ(self.y)
|
||||
|
||||
@instruction(name="TXA", mode="imp", cycles=2)
|
||||
def inst_0x8a(self):
|
||||
self.a=self.x
|
||||
self.a = self.x
|
||||
self.FlagsNZ(self.a)
|
||||
|
||||
@instruction(name="STY", mode="abs", cycles=4)
|
||||
@ -935,7 +938,7 @@ class MPU:
|
||||
|
||||
@instruction(name="TXS", mode="imp", cycles=2)
|
||||
def inst_0x9a(self):
|
||||
self.sp=self.x
|
||||
self.sp = self.x
|
||||
|
||||
@instruction(name="STA", mode="abx", cycles=5)
|
||||
def inst_0x9d(self):
|
||||
@ -1089,7 +1092,7 @@ class MPU:
|
||||
@instruction(name="CMP", mode="imm", cycles=2)
|
||||
def inst_0xc9(self):
|
||||
self.opCMPR(self.ProgramCounter, self.a)
|
||||
self.pc +=1
|
||||
self.pc += 1
|
||||
|
||||
@instruction(name="DEX", mode="imp", cycles=2)
|
||||
def inst_0xca(self):
|
||||
@ -1177,8 +1180,8 @@ class MPU:
|
||||
|
||||
@instruction(name="INX", mode="imp", cycles=2)
|
||||
def inst_0xe8(self):
|
||||
self.x+=1
|
||||
self.x&=self.byteMask
|
||||
self.x += 1
|
||||
self.x &= self.byteMask
|
||||
self.FlagsNZ(self.x)
|
||||
|
||||
@instruction(name="SBC", mode="imm", cycles=2)
|
||||
|
@ -1,6 +1,7 @@
|
||||
from py65.devices import mpu6502
|
||||
from py65.utils.devices import make_instruction_decorator
|
||||
|
||||
|
||||
class MPU(mpu6502.MPU):
|
||||
def __init__(self, *args, **kwargs):
|
||||
mpu6502.MPU.__init__(self, *args, **kwargs)
|
||||
@ -15,18 +16,18 @@ class MPU(mpu6502.MPU):
|
||||
return self
|
||||
|
||||
# Make copies of the lists
|
||||
instruct = mpu6502.MPU.instruct[:]
|
||||
cycletime = mpu6502.MPU.cycletime[:]
|
||||
instruct = mpu6502.MPU.instruct[:]
|
||||
cycletime = mpu6502.MPU.cycletime[:]
|
||||
extracycles = mpu6502.MPU.extracycles[:]
|
||||
disassemble = mpu6502.MPU.disassemble[:]
|
||||
|
||||
instruction = make_instruction_decorator(instruct, disassemble,
|
||||
cycletime, extracycles)
|
||||
cycletime, extracycles)
|
||||
|
||||
# addressing modes
|
||||
|
||||
def ZeroPageIndirectAddr(self):
|
||||
return self.WordAt( 255 & (self.ByteAt(self.pc)))
|
||||
return self.WordAt(255 & (self.ByteAt(self.pc)))
|
||||
|
||||
def AccumulatorAddr(self):
|
||||
return self.a
|
||||
@ -267,4 +268,3 @@ class MPU(mpu6502.MPU):
|
||||
def inst_0xf2(self):
|
||||
self.opSBC(self.ZeroPageIndirectAddr)
|
||||
self.pc += 1
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
from py65.devices import mpu6502
|
||||
from py65.utils.devices import make_instruction_decorator
|
||||
|
||||
|
||||
class MPU(mpu6502.MPU):
|
||||
"""
|
||||
The 65Org16 is a derivative of the 6502 architecture
|
||||
@ -10,21 +11,22 @@ class MPU(mpu6502.MPU):
|
||||
- and otherwise all opcodes and addressing modes are like the NMOS 6502
|
||||
- sign bit is bit 15, overflow bit is bit 14
|
||||
|
||||
One implementation can be found here: https://github.com/BigEd/verilog-6502/wiki
|
||||
One implementation can be found here:
|
||||
https://github.com/BigEd/verilog-6502/wiki
|
||||
"""
|
||||
|
||||
BYTE_WIDTH = 16
|
||||
BYTE_WIDTH = 16
|
||||
BYTE_FORMAT = "%04x"
|
||||
ADDR_WIDTH = 32
|
||||
ADDR_WIDTH = 32
|
||||
ADDR_FORMAT = "%08x"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
mpu6502.MPU.__init__(self, *args, **kwargs)
|
||||
self.name = '65Org16'
|
||||
self.waiting = False
|
||||
self.IrqTo = (1<<self.ADDR_WIDTH)-2
|
||||
self.ResetTo = (1<<self.ADDR_WIDTH)-4
|
||||
self.NMITo = (1<<self.ADDR_WIDTH)-6
|
||||
self.IrqTo = (1 << self.ADDR_WIDTH) - 2
|
||||
self.ResetTo = (1 << self.ADDR_WIDTH) - 4
|
||||
self.NMITo = (1 << self.ADDR_WIDTH) - 6
|
||||
self.NEGATIVE = 1 << 15
|
||||
self.OVERFLOW = 1 << 14
|
||||
|
||||
@ -36,12 +38,11 @@ class MPU(mpu6502.MPU):
|
||||
return self
|
||||
|
||||
# Make copies of the lists
|
||||
instruct = mpu6502.MPU.instruct[:]
|
||||
cycletime = mpu6502.MPU.cycletime[:]
|
||||
instruct = mpu6502.MPU.instruct[:]
|
||||
cycletime = mpu6502.MPU.cycletime[:]
|
||||
extracycles = mpu6502.MPU.extracycles[:]
|
||||
disassemble = mpu6502.MPU.disassemble[:]
|
||||
|
||||
def reprformat(self):
|
||||
return ("%s PC AC XR YR SP NV---------BDIZC\n" + \
|
||||
"%s: %08x %04x %04x %04x %04x %s"
|
||||
)
|
||||
return ("%s PC AC XR YR SP NV---------BDIZC\n" +
|
||||
"%s: %08x %04x %04x %04x %04x %s")
|
||||
|
@ -1,5 +1,6 @@
|
||||
from py65.utils.addressing import AddressParser
|
||||
|
||||
|
||||
class Disassembler:
|
||||
def __init__(self, mpu, address_parser=None):
|
||||
if address_parser is None:
|
||||
@ -29,22 +30,22 @@ class Disassembler:
|
||||
|
||||
elif addressing == 'abs':
|
||||
address = self._mpu.WordAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(address,
|
||||
'$' + self.addrFmt % address)
|
||||
address_or_label = self._address_parser.label_for(
|
||||
address, '$' + self.addrFmt % address)
|
||||
disasm += ' ' + address_or_label
|
||||
length = 3
|
||||
|
||||
elif addressing == 'abx':
|
||||
address = self._mpu.WordAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(address,
|
||||
'$' + self.addrFmt % address)
|
||||
address_or_label = self._address_parser.label_for(
|
||||
address, '$' + self.addrFmt % address)
|
||||
disasm += ' %s,X' % address_or_label
|
||||
length = 3
|
||||
|
||||
elif addressing == 'aby':
|
||||
address = self._mpu.WordAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(address,
|
||||
'$' + self.addrFmt % address)
|
||||
address_or_label = self._address_parser.label_for(
|
||||
address, '$' + self.addrFmt % address)
|
||||
disasm += ' %s,Y' % address_or_label
|
||||
length = 3
|
||||
|
||||
@ -58,64 +59,64 @@ class Disassembler:
|
||||
|
||||
elif addressing == 'ind':
|
||||
address = self._mpu.WordAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(address,
|
||||
'$' + self.addrFmt % address)
|
||||
address_or_label = self._address_parser.label_for(
|
||||
address, '$' + self.addrFmt % address)
|
||||
disasm += ' (%s)' % address_or_label
|
||||
length = 3
|
||||
|
||||
elif addressing == 'iny':
|
||||
zp_address = self._mpu.ByteAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(zp_address,
|
||||
'$' + self.byteFmt % zp_address)
|
||||
address_or_label = self._address_parser.label_for(
|
||||
zp_address, '$' + self.byteFmt % zp_address)
|
||||
disasm += ' (%s),Y' % address_or_label
|
||||
length = 2
|
||||
|
||||
elif addressing == 'inx':
|
||||
zp_address = self._mpu.ByteAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(zp_address,
|
||||
'$' + self.byteFmt % zp_address)
|
||||
address_or_label = self._address_parser.label_for(
|
||||
zp_address, '$' + self.byteFmt % zp_address)
|
||||
disasm += ' (%s,X)' % address_or_label
|
||||
length = 2
|
||||
|
||||
elif addressing == 'rel':
|
||||
opv = self._mpu.ByteAt(pc + 1)
|
||||
targ = pc + 2
|
||||
if opv & (1<<(self.byteWidth-1)):
|
||||
if opv & (1 << (self.byteWidth - 1)):
|
||||
targ -= (opv ^ self.byteMask) + 1
|
||||
else:
|
||||
targ += opv
|
||||
targ &= self.addrMask
|
||||
|
||||
address_or_label = self._address_parser.label_for(targ,
|
||||
'$' + self.addrFmt % targ)
|
||||
address_or_label = self._address_parser.label_for(
|
||||
targ, '$' + self.addrFmt % targ)
|
||||
disasm += ' ' + address_or_label
|
||||
length = 2
|
||||
|
||||
elif addressing == 'zpi':
|
||||
zp_address = self._mpu.ByteAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(zp_address,
|
||||
'($' + self.byteFmt % zp_address + ')' )
|
||||
address_or_label = self._address_parser.label_for(
|
||||
zp_address, '($' + self.byteFmt % zp_address + ')')
|
||||
disasm += ' %s' % address_or_label
|
||||
length = 2
|
||||
|
||||
elif addressing == 'zpg':
|
||||
zp_address = self._mpu.ByteAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(zp_address,
|
||||
'$' + self.byteFmt % zp_address)
|
||||
address_or_label = self._address_parser.label_for(
|
||||
zp_address, '$' + self.byteFmt % zp_address)
|
||||
disasm += ' %s' % address_or_label
|
||||
length = 2
|
||||
|
||||
elif addressing == 'zpx':
|
||||
zp_address = self._mpu.ByteAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(zp_address,
|
||||
'$' + self.byteFmt % zp_address)
|
||||
address_or_label = self._address_parser.label_for(
|
||||
zp_address, '$' + self.byteFmt % zp_address)
|
||||
disasm += ' %s,X' % address_or_label
|
||||
length = 2
|
||||
|
||||
elif addressing == 'zpy':
|
||||
zp_address = self._mpu.ByteAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(zp_address,
|
||||
'$' + self.byteFmt % zp_address)
|
||||
address_or_label = self._address_parser.label_for(
|
||||
zp_address, '$' + self.byteFmt % zp_address)
|
||||
disasm += ' %s,Y' % address_or_label
|
||||
length = 2
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
class ObservableMemory:
|
||||
def __init__(self, subject=None, addrWidth=16):
|
||||
self.physMask = 0xffff
|
||||
@ -8,10 +9,10 @@ class ObservableMemory:
|
||||
self.physMask = 0x3ffff
|
||||
|
||||
if subject is None:
|
||||
subject = (self.physMask+1) * [0x00]
|
||||
subject = (self.physMask + 1) * [0x00]
|
||||
self._subject = subject
|
||||
|
||||
self._read_subscribers = defaultdict(list)
|
||||
self._read_subscribers = defaultdict(list)
|
||||
self._write_subscribers = defaultdict(list)
|
||||
|
||||
def __setitem__(self, address, value):
|
||||
@ -59,4 +60,4 @@ class ObservableMemory:
|
||||
|
||||
def write(self, start_address, bytes):
|
||||
start_address &= self.physMask
|
||||
self._subject[start_address:start_address+len(bytes)] = bytes
|
||||
self._subject[start_address:start_address + len(bytes)] = bytes
|
||||
|
108
py65/monitor.py
108
py65/monitor.py
@ -30,12 +30,15 @@ from py65.utils import console
|
||||
from py65.utils.conversions import itoa
|
||||
from py65.memory import ObservableMemory
|
||||
|
||||
|
||||
class Monitor(cmd.Cmd):
|
||||
|
||||
Microprocessors = {'6502': NMOS6502, '65C02': CMOS65C02, '65Org16': V65Org16}
|
||||
Microprocessors = {'6502': NMOS6502, '65C02': CMOS65C02,
|
||||
'65Org16': V65Org16}
|
||||
|
||||
def __init__(self, mpu_type=NMOS6502, completekey='tab', stdin=None, stdout=None, argv=None):
|
||||
self.mpu_type=mpu_type
|
||||
def __init__(self, mpu_type=NMOS6502, completekey='tab', stdin=None,
|
||||
stdout=None, argv=None):
|
||||
self.mpu_type = mpu_type
|
||||
if argv is None:
|
||||
argv = sys.argv
|
||||
self._reset(self.mpu_type)
|
||||
@ -47,37 +50,44 @@ class Monitor(cmd.Cmd):
|
||||
|
||||
def _parse_args(self, argv):
|
||||
try:
|
||||
options, args = getopt.getopt(argv[1:], 'hm:l:r:g:',
|
||||
['help', 'mpu=', 'load=', 'rom=', 'goto='])
|
||||
shortopts = 'hm:l:r:g:'
|
||||
longopts = ['help', 'mpu=', 'load=', 'rom=', 'goto=']
|
||||
options, args = getopt.getopt(argv[1:], shortopts, longopts)
|
||||
except getopt.GetoptError, err:
|
||||
self._output(str(err))
|
||||
self._usage()
|
||||
self._exit(1)
|
||||
|
||||
for opt, value in options:
|
||||
if opt in ('-l','--load'):
|
||||
if opt in ('-l', '--load'):
|
||||
cmd = "load %s" % value
|
||||
self.onecmd(cmd)
|
||||
if opt in ('-r','--rom'):
|
||||
|
||||
if opt in ('-r', '--rom'):
|
||||
# load a ROM and run from the reset vector
|
||||
cmd = "load %s %d" % (value, -1)
|
||||
self.onecmd(cmd)
|
||||
physMask = self._mpu.memory.physMask
|
||||
reset = self._mpu.ResetTo & physMask
|
||||
dest = self._mpu.memory[reset] + (self._mpu.memory[reset+1] << self.byteWidth)
|
||||
dest = self._mpu.memory[reset] + \
|
||||
(self._mpu.memory[reset + 1] << self.byteWidth)
|
||||
cmd = "goto %08x" % dest
|
||||
self.onecmd(cmd)
|
||||
if opt in ('-g','--goto'):
|
||||
|
||||
if opt in ('-g', '--goto'):
|
||||
cmd = "goto %s" % value
|
||||
self.onecmd(cmd)
|
||||
if opt in ('-m','--mpu'):
|
||||
|
||||
if opt in ('-m', '--mpu'):
|
||||
if self._get_mpu(value) is None:
|
||||
mpus = self.Microprocessors.keys()
|
||||
mpus.sort()
|
||||
self._output("Fatal: no such MPU. Available MPUs: %s" % ', '.join(mpus))
|
||||
msg = "Fatal: no such MPU. Available MPUs: %s"
|
||||
self._output(msg % ', '.join(mpus))
|
||||
sys.exit(1)
|
||||
cmd = "mpu %s" % value
|
||||
self.onecmd(cmd)
|
||||
|
||||
elif opt in ("-h", "--help"):
|
||||
self._usage()
|
||||
self._exit(1)
|
||||
@ -94,7 +104,7 @@ class Monitor(cmd.Cmd):
|
||||
result = cmd.Cmd.onecmd(self, line)
|
||||
except KeyboardInterrupt:
|
||||
self._output("Interrupt")
|
||||
except Exception,e:
|
||||
except Exception, e:
|
||||
(file, fun, line), t, v, tbinfo = compact_traceback()
|
||||
error = 'Error: %s, %s: file: %s line: %s' % (t, v, file, line)
|
||||
self._output(error)
|
||||
@ -152,7 +162,7 @@ class Monitor(cmd.Cmd):
|
||||
|
||||
# special case for vice compatibility
|
||||
if line.startswith('~'):
|
||||
line = self._shortcuts['~'] + ' ' + line[1:]
|
||||
line = self._shortcuts['~'] + ' ' + line[1:]
|
||||
|
||||
# command shortcuts
|
||||
for shortcut, command in self._shortcuts.iteritems():
|
||||
@ -279,7 +289,8 @@ class Monitor(cmd.Cmd):
|
||||
|
||||
end = start + len(bytes)
|
||||
self._mpu.memory[start:end] = bytes
|
||||
self.do_disassemble((self.addrFmt+":"+self.addrFmt) % (start, end))
|
||||
rangestr = (self.addrFmt + ":" + self.addrFmt) % (start, end)
|
||||
self.do_disassemble(rangestr)
|
||||
except KeyError:
|
||||
self._output("Bad label: %s" % args)
|
||||
except OverflowError:
|
||||
@ -304,9 +315,11 @@ class Monitor(cmd.Cmd):
|
||||
return
|
||||
|
||||
while True:
|
||||
prompt = "\r$" + ( self.addrFmt % start ) + " " + (" " * (1 + self.byteWidth/4) * 3)
|
||||
prompt = "\r$" + (self.addrFmt % start) + " " + \
|
||||
(" " * (1 + self.byteWidth / 4) * 3)
|
||||
|
||||
line = console.line_input(prompt,
|
||||
stdin=self.stdin, stdout=self.stdout)
|
||||
stdin=self.stdin, stdout=self.stdout)
|
||||
|
||||
if not line.strip():
|
||||
self.stdout.write("\n")
|
||||
@ -322,16 +335,20 @@ class Monitor(cmd.Cmd):
|
||||
# print disassembly
|
||||
bytes, disasm = self._disassembler.instruction_at(start)
|
||||
disassembly = self._format_disassembly(start, bytes, disasm)
|
||||
self.stdout.write("\r" + (' ' * (len(prompt+line) + 5) ) + "\r")
|
||||
indent = ' ' * (len(prompt + line) + 5)
|
||||
self.stdout.write("\r" + indent + "\r")
|
||||
self.stdout.write(disassembly + "\n")
|
||||
|
||||
start += bytes
|
||||
except KeyError:
|
||||
self.stdout.write("\r$" + (self.addrFmt % start) + " ?Label\n")
|
||||
addr = self.addrFmt % start
|
||||
self.stdout.write("\r$%s ?Label\n" % addr)
|
||||
except OverflowError:
|
||||
self.stdout.write("\r$" + (self.addrFmt % start) + " ?Overflow\n")
|
||||
addr = self.addrFmt % start
|
||||
self.stdout.write("\r$%s ?Overflow\n" % addr)
|
||||
except SyntaxError:
|
||||
self.stdout.write("\r$" + (self.addrFmt % start) + " ?Syntax\n")
|
||||
addr = self.addrFmt % start
|
||||
self.stdout.write("\r$%s ?Syntax\n" % addr)
|
||||
|
||||
def do_disassemble(self, args):
|
||||
split = shlex.split(args)
|
||||
@ -350,10 +367,10 @@ class Monitor(cmd.Cmd):
|
||||
|
||||
def _format_disassembly(self, address, bytes, disasm):
|
||||
mem = ''
|
||||
for byte in self._mpu.memory[address:address+bytes]:
|
||||
for byte in self._mpu.memory[address:address + bytes]:
|
||||
mem += self.byteFmt % byte + " "
|
||||
|
||||
fieldwidth = 1 + (1 + self.byteWidth/4) * 3
|
||||
fieldwidth = 1 + (1 + self.byteWidth / 4) * 3
|
||||
fieldfmt = "%%-%ds" % fieldwidth
|
||||
return "$" + self.addrFmt % address + " " + fieldfmt % mem + disasm
|
||||
|
||||
@ -376,7 +393,7 @@ class Monitor(cmd.Cmd):
|
||||
self._output("before the next RTS or RTI is executed.")
|
||||
|
||||
def do_return(self, args):
|
||||
returns = [0x60, 0x40] # RTS, RTI
|
||||
returns = [0x60, 0x40] # RTS, RTI
|
||||
self._run(stopcodes=returns)
|
||||
|
||||
def help_goto(self):
|
||||
@ -385,7 +402,7 @@ class Monitor(cmd.Cmd):
|
||||
|
||||
def do_goto(self, args):
|
||||
self._mpu.pc = self._address_parser.number(args)
|
||||
brks = [0x00] # BRK
|
||||
brks = [0x00] # BRK
|
||||
self._run(stopcodes=brks)
|
||||
|
||||
def _run(self, stopcodes=[]):
|
||||
@ -396,7 +413,7 @@ class Monitor(cmd.Cmd):
|
||||
|
||||
def help_radix(self):
|
||||
self._output("radix [H|D|O|B]")
|
||||
self._output("Set the default radix to hex, decimal, octal, or binary.")
|
||||
self._output("Set default radix to hex, decimal, octal, or binary.")
|
||||
self._output("With no argument, the current radix is printed.")
|
||||
|
||||
def help_cycles(self):
|
||||
@ -424,7 +441,7 @@ class Monitor(cmd.Cmd):
|
||||
|
||||
def help_tilde(self):
|
||||
self._output("~ <number>")
|
||||
self._output("Display the specified number in decimal, hex, octal, and binary.")
|
||||
self._output("Display a number in decimal, hex, octal, and binary.")
|
||||
|
||||
def do_tilde(self, args):
|
||||
try:
|
||||
@ -439,7 +456,7 @@ class Monitor(cmd.Cmd):
|
||||
self._output(itoa(num, 2).zfill(8))
|
||||
|
||||
def help_registers(self):
|
||||
self._output("registers[<reg_name> = <number> [, <reg_name> = <number>]*]")
|
||||
self._output("registers[<name>=<value> [, <name>=<value>]*]")
|
||||
self._output("Assign respective registers. With no parameters,")
|
||||
self._output("display register values.")
|
||||
|
||||
@ -487,7 +504,7 @@ class Monitor(cmd.Cmd):
|
||||
|
||||
def help_load(self):
|
||||
self._output("load \"filename\" <address>")
|
||||
self._output("Load the specified file into memory at the specified address.")
|
||||
self._output("Load a file into memory at the specified address.")
|
||||
self._output("Commodore-style load address bytes are ignored.")
|
||||
|
||||
def do_load(self, args):
|
||||
@ -524,12 +541,15 @@ class Monitor(cmd.Cmd):
|
||||
|
||||
# if the start address was -1, we load to top of memory
|
||||
if start == -1:
|
||||
start = self.addrMask - len(bytes)/(self.byteWidth/8) + 1
|
||||
start = self.addrMask - len(bytes) / (self.byteWidth / 8) + 1
|
||||
|
||||
if self.byteWidth==8:
|
||||
bytes=map(ord, bytes)
|
||||
elif self.byteWidth==16:
|
||||
bytes=map(lambda msb,lsb: (ord(msb)<<8)+ord(lsb),bytes[0::2],bytes[1::2])
|
||||
if self.byteWidth == 8:
|
||||
bytes = map(ord, bytes)
|
||||
|
||||
elif self.byteWidth == 16:
|
||||
def format(msb, lsb):
|
||||
return (ord(msb) << 8) + ord(lsb)
|
||||
bytes = map(format, bytes[0::2], bytes[1::2])
|
||||
|
||||
self._fill(start, start, bytes)
|
||||
|
||||
@ -541,15 +561,15 @@ class Monitor(cmd.Cmd):
|
||||
|
||||
filename = split[0]
|
||||
start = self._address_parser.number(split[1])
|
||||
end = self._address_parser.number(split[2])
|
||||
end = self._address_parser.number(split[2])
|
||||
|
||||
bytes = self._mpu.memory[start:end+1]
|
||||
bytes = self._mpu.memory[start:end + 1]
|
||||
try:
|
||||
f = open(filename, 'wb')
|
||||
for byte in bytes:
|
||||
# output each octect from msb first
|
||||
for shift in range (self.byteWidth-8,-1,-8):
|
||||
f.write(chr((byte>>shift) & 0xff))
|
||||
for shift in range(self.byteWidth - 8, -1, -8):
|
||||
f.write(chr((byte >> shift) & 0xff))
|
||||
f.close()
|
||||
except (OSError, IOError), why:
|
||||
msg = "Cannot save file: [%d] %s" % (why[0], why[1])
|
||||
@ -560,14 +580,15 @@ class Monitor(cmd.Cmd):
|
||||
|
||||
def help_save(self):
|
||||
self._output("save \"filename\" <start> <end>")
|
||||
self._output("Save the specified memory range to disk as a binary file.")
|
||||
self._output("Save the specified memory range as a binary file.")
|
||||
self._output("Commodore-style load address bytes are not written.")
|
||||
|
||||
def help_fill(self):
|
||||
self._output("fill <address_range> <data_list>")
|
||||
self._output("Fill memory in the specified address range with the data in")
|
||||
self._output("<data_list>. If the size of the address range is greater")
|
||||
self._output("than the size of the data_list, the data_list is repeated.")
|
||||
self._output("Fill memory in the address range with the data in")
|
||||
self._output("<data_list>. If the size of the address range is")
|
||||
self._output("greater than the size of the data_list, the data_list ")
|
||||
self._output("is repeated.")
|
||||
|
||||
def do_fill(self, args):
|
||||
split = shlex.split(args)
|
||||
@ -613,7 +634,7 @@ class Monitor(cmd.Cmd):
|
||||
start, end = self._address_parser.range(split[0])
|
||||
|
||||
line = self.addrFmt % start + ":"
|
||||
for address in range(start, end+1):
|
||||
for address in range(start, end + 1):
|
||||
byte = self._mpu.memory[address]
|
||||
more = " " + self.byteFmt % byte
|
||||
|
||||
@ -635,7 +656,7 @@ class Monitor(cmd.Cmd):
|
||||
return self.help_add_label()
|
||||
|
||||
address = self._address_parser.number(split[0])
|
||||
label = split[1]
|
||||
label = split[1]
|
||||
|
||||
self._address_parser.labels[label] = address
|
||||
|
||||
@ -681,6 +702,7 @@ class Monitor(cmd.Cmd):
|
||||
self._output("Set the width used by some commands to wrap output.")
|
||||
self._output("With no argument, the current width is printed.")
|
||||
|
||||
|
||||
def main(args=None):
|
||||
c = Monitor()
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,7 @@ from py65.devices.mpu65c02 import MPU as MPU65C02
|
||||
from py65.assembler import Assembler
|
||||
from py65.utils.addressing import AddressParser
|
||||
|
||||
|
||||
class AssemblerTests(unittest.TestCase):
|
||||
def test_assemble_bad_syntax_raises_syntaxerror(self):
|
||||
self.assertRaises(SyntaxError,
|
||||
@ -955,6 +956,7 @@ class AssemblerTests(unittest.TestCase):
|
||||
assembler = Assembler(mpu, address_parser)
|
||||
return assembler.assemble(statement, pc)
|
||||
|
||||
|
||||
def test_suite():
|
||||
return unittest.findTestCases(sys.modules[__name__])
|
||||
|
||||
|
@ -5,6 +5,7 @@ from py65.devices.mpu65c02 import MPU as MPU65C02
|
||||
from py65.disassembler import Disassembler
|
||||
from py65.utils.addressing import AddressParser
|
||||
|
||||
|
||||
class DisassemblerTests(unittest.TestCase):
|
||||
def test_disassembles_00(self):
|
||||
length, disasm = self.disassemble([0x00])
|
||||
@ -1304,9 +1305,10 @@ class DisassemblerTests(unittest.TestCase):
|
||||
mpu = MPU()
|
||||
address_parser = AddressParser()
|
||||
disasm = Disassembler(mpu, address_parser)
|
||||
mpu.memory[pc:len(bytes)-1] = bytes
|
||||
mpu.memory[pc:len(bytes) - 81] = bytes
|
||||
return disasm.instruction_at(pc)
|
||||
|
||||
|
||||
def test_suite():
|
||||
return unittest.findTestCases(sys.modules[__name__])
|
||||
|
||||
|
@ -4,6 +4,7 @@ import re
|
||||
import os
|
||||
from py65.memory import ObservableMemory
|
||||
|
||||
|
||||
class ObservableMemoryTests(unittest.TestCase):
|
||||
|
||||
# __setitem__
|
||||
@ -56,7 +57,7 @@ class ObservableMemoryTests(unittest.TestCase):
|
||||
def read_subscriber(address, value):
|
||||
return 0xAB
|
||||
|
||||
mem.subscribe_to_read(xrange(0xC000, 0xC001+1), read_subscriber)
|
||||
mem.subscribe_to_read(xrange(0xC000, 0xC001 + 1), read_subscriber)
|
||||
|
||||
mem[0xC000] = 0xAB
|
||||
mem[0xC001] = 0xAB
|
||||
@ -68,6 +69,7 @@ class ObservableMemoryTests(unittest.TestCase):
|
||||
mem = ObservableMemory(subject=subject)
|
||||
|
||||
calls = []
|
||||
|
||||
def read_subscriber(address):
|
||||
calls.append('read_subscriber')
|
||||
|
||||
@ -107,6 +109,7 @@ class ObservableMemoryTests(unittest.TestCase):
|
||||
mem = ObservableMemory(subject=subject)
|
||||
|
||||
calls = []
|
||||
|
||||
def read_subscriber_1(address):
|
||||
calls.append('read_subscriber_1')
|
||||
return 0x01
|
||||
@ -139,7 +142,7 @@ class ObservableMemoryTests(unittest.TestCase):
|
||||
|
||||
def write_subscriber(address, value):
|
||||
return 0xFF
|
||||
mem.subscribe_to_write([0xC000,0xC001], write_subscriber)
|
||||
mem.subscribe_to_write([0xC000, 0xC001], write_subscriber)
|
||||
|
||||
mem.write(0xC000, [0x01, 002])
|
||||
self.assertEqual(0x01, subject[0xC000])
|
||||
|
@ -6,6 +6,7 @@ import tempfile
|
||||
from py65.monitor import Monitor
|
||||
from StringIO import StringIO
|
||||
|
||||
|
||||
class MonitorTests(unittest.TestCase):
|
||||
|
||||
# line processing
|
||||
@ -213,7 +214,7 @@ class MonitorTests(unittest.TestCase):
|
||||
def test_do_cycles_shows_count_after_step(self):
|
||||
stdout = StringIO()
|
||||
mon = Monitor(stdout=stdout)
|
||||
mon._mpu.memory[0x0000] = 0xEA #=> NOP (2 cycles)
|
||||
mon._mpu.memory[0x0000] = 0xEA # => NOP (2 cycles)
|
||||
mon._mpu.step()
|
||||
mon.do_cycles("")
|
||||
|
||||
@ -249,7 +250,7 @@ class MonitorTests(unittest.TestCase):
|
||||
mon = Monitor(stdout=stdout)
|
||||
mon._address_parser.labels['foo'] = 0xc000
|
||||
mon.do_delete_label('foo')
|
||||
self.assertFalse(mon._address_parser.labels.has_key('foo'))
|
||||
self.assertFalse('foo' in mon._address_parser.labels)
|
||||
out = stdout.getvalue()
|
||||
self.assertEqual('', out)
|
||||
|
||||
@ -280,7 +281,7 @@ class MonitorTests(unittest.TestCase):
|
||||
def test_disassemble_will_disassemble_one_address(self):
|
||||
stdout = StringIO()
|
||||
mon = Monitor(stdout=stdout)
|
||||
mon._mpu.memory[0xc000] = 0xEA #=> NOP
|
||||
mon._mpu.memory[0xc000] = 0xEA # => NOP
|
||||
mon._mpu.step()
|
||||
mon.do_disassemble("c000")
|
||||
|
||||
@ -291,8 +292,8 @@ class MonitorTests(unittest.TestCase):
|
||||
def test_disassemble_will_disassemble_an_address_range(self):
|
||||
stdout = StringIO()
|
||||
mon = Monitor(stdout=stdout)
|
||||
mon._mpu.memory[0xc000] = 0xEA #=> NOP
|
||||
mon._mpu.memory[0xc001] = 0xEA #=> NOP
|
||||
mon._mpu.memory[0xc000] = 0xEA # => NOP
|
||||
mon._mpu.memory[0xc001] = 0xEA # => NOP
|
||||
mon._mpu.step()
|
||||
mon.do_disassemble("c000:c002")
|
||||
|
||||
@ -462,7 +463,8 @@ class MonitorTests(unittest.TestCase):
|
||||
mon.do_load("'%s' a600" % filename)
|
||||
self.assertEqual('Wrote +3 bytes from $a600 to $a602\n',
|
||||
stdout.getvalue())
|
||||
self.assertEqual([0xAA, 0xBB, 0xCC], mon._mpu.memory[0xA600:0xA603])
|
||||
self.assertEqual([0xAA, 0xBB, 0xCC],
|
||||
mon._mpu.memory[0xA600:0xA603])
|
||||
finally:
|
||||
os.unlink(filename)
|
||||
|
||||
@ -632,7 +634,6 @@ class MonitorTests(unittest.TestCase):
|
||||
out = stdout.getvalue()
|
||||
self.assertEqual("%s\n" % os.getcwd(), out)
|
||||
|
||||
|
||||
def test_help_pwd(self):
|
||||
stdout = StringIO()
|
||||
mon = Monitor(stdout=stdout)
|
||||
@ -714,7 +715,7 @@ class MonitorTests(unittest.TestCase):
|
||||
mon = Monitor(stdout=stdout)
|
||||
mon.help_registers()
|
||||
out = stdout.getvalue()
|
||||
self.assertTrue(out.startswith("registers[<reg_name>"))
|
||||
self.assertTrue(out.startswith("registers[<name>"))
|
||||
|
||||
# return
|
||||
|
||||
|
@ -2,6 +2,7 @@ import unittest
|
||||
import sys
|
||||
from py65.utils.addressing import AddressParser
|
||||
|
||||
|
||||
class AddressParserTests(unittest.TestCase):
|
||||
def test_maxwidth_can_be_set_in_constructor(self):
|
||||
parser = AddressParser(maxwidth=24)
|
||||
@ -122,7 +123,7 @@ class AddressParserTests(unittest.TestCase):
|
||||
self.assertRaises(OverflowError, parser.number, 'foo+5')
|
||||
|
||||
def test_label_for_returns_label(self):
|
||||
parser = AddressParser(labels={'chrout':0xFFD2})
|
||||
parser = AddressParser(labels={'chrout': 0xFFD2})
|
||||
self.assertEqual('chrout', parser.label_for(0xFFD2))
|
||||
|
||||
def test_label_for_returns_none_by_default(self):
|
||||
|
@ -2,6 +2,7 @@ import sys
|
||||
import unittest
|
||||
from py65.utils.console import getch
|
||||
|
||||
|
||||
class ConsoleTopLevelTests(unittest.TestCase):
|
||||
pass
|
||||
|
||||
|
@ -2,6 +2,7 @@ import sys
|
||||
import unittest
|
||||
from py65.utils.conversions import itoa
|
||||
|
||||
|
||||
class ConversionsTopLevelTests(unittest.TestCase):
|
||||
def test_itoa_decimal_output(self):
|
||||
self.assertEqual('10', itoa(10, base=10))
|
||||
|
@ -2,6 +2,7 @@ import unittest
|
||||
import sys
|
||||
from py65.utils.hexdump import load, Loader
|
||||
|
||||
|
||||
class TopLevelHexdumpTests(unittest.TestCase):
|
||||
def test_load(self):
|
||||
text = 'c000: aa bb'
|
||||
@ -9,6 +10,7 @@ class TopLevelHexdumpTests(unittest.TestCase):
|
||||
self.assertEqual(0xC000, start)
|
||||
self.assertEqual([0xAA, 0xBB], data)
|
||||
|
||||
|
||||
class HexdumpLoaderTests(unittest.TestCase):
|
||||
def test_empty_string_does_nothing(self):
|
||||
text = ''
|
||||
@ -126,7 +128,6 @@ class HexdumpLoaderTests(unittest.TestCase):
|
||||
self.assertEqual([0xAA, 0xBB], load.data)
|
||||
|
||||
|
||||
|
||||
def test_suite():
|
||||
return unittest.findTestCases(sys.modules[__name__])
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import re
|
||||
|
||||
|
||||
class AddressParser(object):
|
||||
"""Parse user input into addresses or ranges of addresses.
|
||||
"""
|
||||
|
@ -4,11 +4,11 @@ if sys.platform[:3] == "win":
|
||||
import msvcrt
|
||||
|
||||
def getch(stdin):
|
||||
""" Read one character from the Windows console, blocking until one
|
||||
is available. Does not echo the character. The stdin argument is
|
||||
for function signature compatibility and is ignored.
|
||||
"""
|
||||
return msvcrt.getch()
|
||||
""" Read one character from the Windows console, blocking until one
|
||||
is available. Does not echo the character. The stdin argument is
|
||||
for function signature compatibility and is ignored.
|
||||
"""
|
||||
return msvcrt.getch()
|
||||
|
||||
def getch_noblock(stdin):
|
||||
""" Read one character from the Windows console without blocking.
|
||||
@ -26,19 +26,19 @@ else:
|
||||
import fcntl
|
||||
|
||||
def getch(stdin):
|
||||
""" Read one character from stdin, blocking until one is available.
|
||||
Does not echo the character.
|
||||
"""
|
||||
fd = stdin.fileno()
|
||||
oldattr = termios.tcgetattr(fd)
|
||||
newattr = oldattr[:]
|
||||
newattr[3] &= ~termios.ICANON & ~termios.ECHO
|
||||
try:
|
||||
termios.tcsetattr(fd, termios.TCSANOW, newattr)
|
||||
char = stdin.read(1)
|
||||
finally:
|
||||
termios.tcsetattr(fd, termios.TCSAFLUSH, oldattr)
|
||||
return char
|
||||
""" Read one character from stdin, blocking until one is available.
|
||||
Does not echo the character.
|
||||
"""
|
||||
fd = stdin.fileno()
|
||||
oldattr = termios.tcgetattr(fd)
|
||||
newattr = oldattr[:]
|
||||
newattr[3] &= ~termios.ICANON & ~termios.ECHO
|
||||
try:
|
||||
termios.tcsetattr(fd, termios.TCSANOW, newattr)
|
||||
char = stdin.read(1)
|
||||
finally:
|
||||
termios.tcsetattr(fd, termios.TCSAFLUSH, oldattr)
|
||||
return char
|
||||
|
||||
def getch_noblock(stdin):
|
||||
""" Read one character from stdin without blocking. Does not echo the
|
||||
@ -63,7 +63,7 @@ else:
|
||||
if char == "\n":
|
||||
char = "\r"
|
||||
else:
|
||||
char = ''
|
||||
char = ''
|
||||
finally:
|
||||
termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
|
||||
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)
|
||||
@ -79,18 +79,18 @@ def line_input(prompt='', stdin=sys.stdin, stdout=sys.stdout):
|
||||
stdout.write(prompt)
|
||||
line = ''
|
||||
while True:
|
||||
char = getch(stdin)
|
||||
code = ord(char)
|
||||
if char in ("\n", "\r"):
|
||||
break
|
||||
elif code in (0x7f, 0x08): # backspace
|
||||
if len(line) > 0:
|
||||
line = line[:-1]
|
||||
stdout.write("\r%s\r%s%s" % \
|
||||
(' ' * (len(prompt+line) +5), prompt, line))
|
||||
elif code == 0x1b: # escape
|
||||
pass
|
||||
else:
|
||||
line += char
|
||||
stdout.write(char)
|
||||
char = getch(stdin)
|
||||
code = ord(char)
|
||||
if char in ("\n", "\r"):
|
||||
break
|
||||
elif code in (0x7f, 0x08): # backspace
|
||||
if len(line) > 0:
|
||||
line = line[:-1]
|
||||
stdout.write("\r%s\r%s%s" %
|
||||
(' ' * (len(prompt + line) + 5), prompt, line))
|
||||
elif code == 0x1b: # escape
|
||||
pass
|
||||
else:
|
||||
line += char
|
||||
stdout.write(char)
|
||||
return line
|
||||
|
@ -1,53 +1,59 @@
|
||||
|
||||
|
||||
def itoa(num, base=10):
|
||||
""" Convert a decimal number to its equivalent in another base.
|
||||
This is essentially the inverse of int(num, base).
|
||||
"""
|
||||
negative = num < 0
|
||||
if negative:
|
||||
num = -num
|
||||
num = -num
|
||||
digits = []
|
||||
while num > 0:
|
||||
num, last_digit = divmod(num, base)
|
||||
digits.append('0123456789abcdefghijklmnopqrstuvwxyz'[last_digit])
|
||||
num, last_digit = divmod(num, base)
|
||||
digits.append('0123456789abcdefghijklmnopqrstuvwxyz'[last_digit])
|
||||
if negative:
|
||||
digits.append('-')
|
||||
digits.append('-')
|
||||
digits.reverse()
|
||||
return ''.join(digits)
|
||||
|
||||
|
||||
def convert_to_bin(bcd):
|
||||
return bcd2bin[bcd]
|
||||
|
||||
|
||||
def convert_to_bcd(bin):
|
||||
return bin2bcd[bin]
|
||||
|
||||
|
||||
bcd2bin = [
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, # 0x00
|
||||
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, # 0x10
|
||||
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, # 0x20
|
||||
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, # 0x30
|
||||
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, # 0x40
|
||||
50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, # 0x50
|
||||
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, # 0x60
|
||||
70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, # 0x70
|
||||
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, # 0x80
|
||||
90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105, # 0x90
|
||||
100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115, # 0xA0
|
||||
110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125, # 0xB0
|
||||
120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135, # 0xC0
|
||||
130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145, # 0xD0
|
||||
140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155, # 0xE0
|
||||
150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165 # 0xF0
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 10, 11, 12, 13,
|
||||
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 20, 21, 22, 23, 24, 25,
|
||||
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 30, 31, 32, 33, 34, 35, 36, 37,
|
||||
38, 39, 40, 41, 42, 43, 44, 45, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
|
||||
50, 51, 52, 53, 54, 55, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
|
||||
62, 63, 64, 65, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
|
||||
74, 75, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
|
||||
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 90, 91,
|
||||
92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 100, 101,
|
||||
102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
|
||||
110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
|
||||
124, 125, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
|
||||
132, 133, 134, 135, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
|
||||
140, 141, 142, 143, 144, 145, 140, 141, 142, 143, 144, 145, 146, 147,
|
||||
148, 149, 150, 151, 152, 153, 154, 155, 150, 151, 152, 153, 154, 155,
|
||||
156, 157, 158, 159, 160, 161, 162, 163, 164, 165
|
||||
]
|
||||
|
||||
|
||||
bin2bcd = [
|
||||
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
|
||||
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,
|
||||
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,
|
||||
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,
|
||||
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
|
||||
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
|
||||
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
|
||||
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,
|
||||
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
|
||||
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99
|
||||
]
|
||||
|
@ -1,4 +1,5 @@
|
||||
|
||||
|
||||
def make_instruction_decorator(instruct, disasm, allcycles, allextras):
|
||||
def instruction(name, mode, cycles, extracycles=0):
|
||||
def decorate(f):
|
||||
@ -7,6 +8,6 @@ def make_instruction_decorator(instruct, disasm, allcycles, allextras):
|
||||
disasm[opcode] = (name, mode)
|
||||
allcycles[opcode] = cycles
|
||||
allextras[opcode] = extracycles
|
||||
return f # Return the original function
|
||||
return f # Return the original function
|
||||
return decorate
|
||||
return instruction
|
||||
|
@ -1,9 +1,11 @@
|
||||
from binascii import a2b_hex
|
||||
|
||||
|
||||
def load(text):
|
||||
load = Loader(text)
|
||||
return (load.start_address, load.data)
|
||||
|
||||
|
||||
class Loader:
|
||||
def __init__(self, text):
|
||||
self.load(text)
|
||||
@ -42,15 +44,15 @@ class Loader:
|
||||
|
||||
def _parse_address(self, piece):
|
||||
try:
|
||||
addr_bytes = [ ord(c) for c in a2b_hex(piece) ]
|
||||
addr_bytes = [ord(c) for c in a2b_hex(piece)]
|
||||
except (TypeError, ValueError):
|
||||
msg = "Could not parse address: %s" % piece
|
||||
raise ValueError, msg
|
||||
raise ValueError(msg)
|
||||
|
||||
if len(addr_bytes) != 2:
|
||||
msg = "Expected address to be 2 bytes, got %d" % (
|
||||
len(addr_bytes))
|
||||
raise ValueError, msg
|
||||
len(addr_bytes))
|
||||
raise ValueError(msg)
|
||||
|
||||
address = (addr_bytes[0] << 8) + addr_bytes[1]
|
||||
|
||||
@ -61,20 +63,20 @@ class Loader:
|
||||
elif address != (self.current_address):
|
||||
msg = "Non-contigous block detected. Expected next address " \
|
||||
"to be $%04x, label was $%04x" % (self.current_address,
|
||||
address)
|
||||
raise ValueError, msg
|
||||
address)
|
||||
raise ValueError(msg)
|
||||
|
||||
def _parse_bytes(self, piece):
|
||||
if self.start_address is None:
|
||||
msg = "Start address was not found in data"
|
||||
raise ValueError, msg
|
||||
raise ValueError(msg)
|
||||
|
||||
else:
|
||||
try:
|
||||
bytes = [ ord(c) for c in a2b_hex(piece) ]
|
||||
bytes = [ord(c) for c in a2b_hex(piece)]
|
||||
except (TypeError, ValueError):
|
||||
msg = "Could not parse data: %s" % piece
|
||||
raise ValueError, msg
|
||||
raise ValueError(msg)
|
||||
|
||||
self.current_address += len(bytes)
|
||||
self.data.extend(bytes)
|
||||
|
50
setup.py
50
setup.py
@ -30,31 +30,31 @@ CLASSIFIERS = [
|
||||
'Topic :: Software Development :: Interpreters',
|
||||
'Topic :: System :: Emulators',
|
||||
'Topic :: System :: Hardware'
|
||||
]
|
||||
]
|
||||
|
||||
setup(
|
||||
name = 'py65',
|
||||
version = __version__,
|
||||
license = 'License :: OSI Approved :: BSD License',
|
||||
url = 'https://github.com/mnaberez/py65',
|
||||
description = '6502 microprocessor simulation package',
|
||||
long_description= DESC,
|
||||
classifiers = CLASSIFIERS,
|
||||
author = "Mike Naberezny",
|
||||
author_email = "mike@naberezny.com",
|
||||
maintainer = "Mike Naberezny",
|
||||
maintainer_email = "mike@naberezny.com",
|
||||
packages = find_packages(),
|
||||
install_requires = [],
|
||||
extras_require = {},
|
||||
tests_require = [],
|
||||
include_package_data = True,
|
||||
zip_safe = False,
|
||||
namespace_packages = ['py65'],
|
||||
test_suite = "py65.tests",
|
||||
entry_points = {
|
||||
'console_scripts': [
|
||||
'py65mon = py65.monitor:main',
|
||||
],
|
||||
},
|
||||
name='py65',
|
||||
version=__version__,
|
||||
license='License :: OSI Approved :: BSD License',
|
||||
url='https://github.com/mnaberez/py65',
|
||||
description='6502 microprocessor simulation package',
|
||||
long_description=DESC,
|
||||
classifiers=CLASSIFIERS,
|
||||
author="Mike Naberezny",
|
||||
author_email="mike@naberezny.com",
|
||||
maintainer="Mike Naberezny",
|
||||
maintainer_email="mike@naberezny.com",
|
||||
packages=find_packages(),
|
||||
install_requires=[],
|
||||
extras_require={},
|
||||
tests_require=[],
|
||||
include_package_data=True,
|
||||
zip_safe=False,
|
||||
namespace_packages=['py65'],
|
||||
test_suite="py65.tests",
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
'py65mon = py65.monitor:main',
|
||||
],
|
||||
},
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user