mirror of
https://github.com/jtauber/applepy.git
synced 2024-06-01 13:41:28 +00:00
Compare commits
39 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
934bf1a495 | ||
|
d340d9cb5f | ||
|
fe80bc897d | ||
|
0d41f951b9 | ||
|
e9c9581857 | ||
|
6a818ae8ac | ||
|
1de396334e | ||
|
82de64b000 | ||
|
2492947e1d | ||
|
bdbc60e6e5 | ||
|
9ff2dbb70e | ||
|
4ee9b846f9 | ||
|
c9ecb5f31e | ||
|
60acf37150 | ||
|
6782a1d268 | ||
|
80e95d114b | ||
|
fad0de8cc9 | ||
|
aac75ef1cb | ||
|
0604bd1515 | ||
|
0b86a8693f | ||
|
29b1342a47 | ||
|
aee0bba7aa | ||
|
8b62860152 | ||
|
19693bc905 | ||
|
a673f8a4d4 | ||
|
9f09818aa0 | ||
|
15e174c02a | ||
|
9ffbf63716 | ||
|
dcc8e9d8ce | ||
|
cd692af6f3 | ||
|
c36ad8b662 | ||
|
a73ab29be2 | ||
|
338f8962fd | ||
|
6f1005693c | ||
|
b8c7949d8e | ||
|
6951db69ad | ||
|
4963eeca9d | ||
|
360f415fc9 | ||
|
c9c609be1d |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
*.pyc
|
19
LICENSE
Normal file
19
LICENSE
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Copyright (c) 2001-2013 James Tauber and contributors
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
|
@ -31,4 +31,18 @@ runs all the programs I've tried so far.
|
|||
The only I/O supported is the keyboard and screen but 40-column text, LORES
|
||||
and HIRES graphics are all supported.
|
||||
|
||||
ApplePy currently requires Pygame.
|
||||
ApplePy currently requires Pygame (although there is a minimal applepy_curses.py
|
||||
that uses curses to display text mode only) and numpy (just for an array for
|
||||
speaker sounds)
|
||||
|
||||
Here's how I set up the dependencies (on Mac OS X 10.8):
|
||||
|
||||
pip install numpy
|
||||
brew install sdl sdl_image sdl_mixer sdl_ttf portmidi hg
|
||||
pip install hg+http://bitbucket.org/pygame/pygame
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
This code is made available under an MIT License. See LICENSE.
|
1035
applepy.py
Normal file → Executable file
1035
applepy.py
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
133
applepy_curses.py
Normal file
133
applepy_curses.py
Normal file
|
@ -0,0 +1,133 @@
|
|||
# ApplePy - an Apple ][ emulator in Python
|
||||
# James Tauber / http://jtauber.com/
|
||||
# originally written 2001, updated 2011
|
||||
|
||||
|
||||
import curses
|
||||
import socket
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
kbd = 0
|
||||
|
||||
|
||||
def write_screen(win, address, value):
|
||||
base = address - 0x400
|
||||
hi, lo = divmod(base, 0x80)
|
||||
row_group, column = divmod(lo, 0x28)
|
||||
row = hi + 8 * row_group
|
||||
|
||||
# skip if writing to row group 3
|
||||
if row_group == 3:
|
||||
return
|
||||
|
||||
c = chr(0x20 + ((value + 0x20) % 0x40))
|
||||
|
||||
if value < 0x40:
|
||||
attr = curses.A_DIM
|
||||
elif value < 0x80:
|
||||
attr = curses.A_REVERSE
|
||||
elif value < 0xA0:
|
||||
attr = curses.A_UNDERLINE
|
||||
else:
|
||||
attr = curses.A_DIM
|
||||
|
||||
try:
|
||||
win.addch(row, column, c, attr)
|
||||
except curses.error:
|
||||
pass
|
||||
|
||||
|
||||
def read(addr, val):
|
||||
global kbd
|
||||
if addr == 0xC000:
|
||||
return kbd
|
||||
elif addr == 0xC010:
|
||||
kbd = kbd & 0x7F
|
||||
return 0x00
|
||||
|
||||
|
||||
def write(win, addr, val):
|
||||
if 0x400 <= addr <= 0x800:
|
||||
write_screen(win, addr, val)
|
||||
|
||||
|
||||
def run(win):
|
||||
global kbd
|
||||
|
||||
listener = socket.socket()
|
||||
listener.bind(("127.0.0.1", 0))
|
||||
listener.listen(0)
|
||||
|
||||
args = [
|
||||
sys.executable,
|
||||
"cpu6502.py",
|
||||
"--bus", str(listener.getsockname()[1]),
|
||||
"--rom", options.rom,
|
||||
]
|
||||
|
||||
subprocess.Popen(args)
|
||||
cpu, _ = listener.accept()
|
||||
|
||||
win.clear()
|
||||
curses.noecho()
|
||||
win.nodelay(True)
|
||||
while True:
|
||||
op = cpu.recv(8)
|
||||
cycle, rw, addr, val = struct.unpack("<IBHB", op)
|
||||
if rw == 0:
|
||||
cpu.send(chr(read(addr, val)))
|
||||
elif rw == 1:
|
||||
write(win, addr, val)
|
||||
else:
|
||||
break
|
||||
try:
|
||||
key = ord(win.getkey())
|
||||
if key == 0xA:
|
||||
key = 0xD
|
||||
elif key == 0x7F:
|
||||
key = 0x8
|
||||
# win.addstr(15, 50, hex(key))
|
||||
kbd = 0x80 | key
|
||||
except curses.error:
|
||||
pass
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
|
||||
def usage():
|
||||
print >>sys.stderr, "ApplePy - an Apple ][ emulator in Python"
|
||||
print >>sys.stderr, "James Tauber / http://jtauber.com/"
|
||||
print >>sys.stderr
|
||||
print >>sys.stderr, "Usage: applepy_curses.py [options]"
|
||||
print >>sys.stderr
|
||||
print >>sys.stderr, " -R, --rom ROM file to use (default A2ROM.BIN)"
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def get_options():
|
||||
class Options:
|
||||
def __init__(self):
|
||||
self.rom = "A2ROM.BIN"
|
||||
|
||||
options = Options()
|
||||
a = 1
|
||||
while a < len(sys.argv):
|
||||
if sys.argv[a].startswith("-"):
|
||||
if sys.argv[a] in ("-R", "--rom"):
|
||||
a += 1
|
||||
options.rom = sys.argv[a]
|
||||
else:
|
||||
usage()
|
||||
else:
|
||||
usage()
|
||||
a += 1
|
||||
|
||||
return options
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
options = get_options()
|
||||
curses.wrapper(run)
|
169
control.py
Normal file
169
control.py
Normal file
|
@ -0,0 +1,169 @@
|
|||
import json
|
||||
import sys
|
||||
import urllib
|
||||
|
||||
URL_PREFIX = "http://localhost:6502"
|
||||
|
||||
|
||||
def get(url):
|
||||
return json.loads(urllib.urlopen(URL_PREFIX + url).read())
|
||||
|
||||
|
||||
def post(url, data=None):
|
||||
return urllib.urlopen(URL_PREFIX + url, json.dumps(data) if data is not None else "")
|
||||
|
||||
|
||||
def value(s):
|
||||
if s.startswith("$"):
|
||||
return int(s[1:], 16)
|
||||
if s.startswith("0x"):
|
||||
return int(s[2:], 16)
|
||||
return int(s)
|
||||
|
||||
|
||||
def format_disassemble(dis):
|
||||
r = "%04X- " % dis["address"]
|
||||
for i in range(3):
|
||||
if i < len(dis["bytes"]):
|
||||
r += "%02X " % dis["bytes"][i]
|
||||
else:
|
||||
r += " "
|
||||
r += " %s" % dis["mnemonic"]
|
||||
if "operand" in dis:
|
||||
r += " %-10s" % dis["operand"]
|
||||
if "memory" in dis:
|
||||
r += "[%04X] = %0*X" % tuple(dis["memory"])
|
||||
return r
|
||||
|
||||
|
||||
def cmd_disassemble(a):
|
||||
"""Disassemble"""
|
||||
if len(a) > 1:
|
||||
addr = value(a[1])
|
||||
else:
|
||||
status = get("/status")
|
||||
addr = status["program_counter"]
|
||||
disasm = get("/disassemble/%d" % addr)
|
||||
for d in disasm:
|
||||
print format_disassemble(d)
|
||||
|
||||
|
||||
def cmd_dump(a):
|
||||
"""Dump memory"""
|
||||
start = value(a[1])
|
||||
if len(a) > 2:
|
||||
end = value(a[2])
|
||||
else:
|
||||
end = start + 15
|
||||
data = get("/memory/%d-%d" % (start, end))
|
||||
addr = start & ~0xF
|
||||
while addr <= end:
|
||||
s = "%04X-" % addr
|
||||
for i in range(16):
|
||||
if start <= addr + i <= end:
|
||||
s += " %02X" % data[addr + i - start]
|
||||
else:
|
||||
s += " "
|
||||
s += " "
|
||||
for i in range(16):
|
||||
if start <= addr + i <= end:
|
||||
c = data[addr + i - start]
|
||||
|
||||
# adjust for apple character set
|
||||
c &= 0x3f
|
||||
if c < 0x20:
|
||||
c += 0x40
|
||||
|
||||
if 0x20 <= c < 0x7f:
|
||||
s += chr(c)
|
||||
else:
|
||||
s += "."
|
||||
else:
|
||||
s += " "
|
||||
print s
|
||||
addr += 16
|
||||
|
||||
|
||||
def cmd_help(a):
|
||||
"""Help commands"""
|
||||
if len(a) > 1:
|
||||
f = Commands.get(a[1])
|
||||
if f is not None:
|
||||
print f.__doc__
|
||||
else:
|
||||
print "Unknown command:", a[1]
|
||||
else:
|
||||
print "Commands:"
|
||||
for c in sorted(Commands):
|
||||
print " ", c
|
||||
|
||||
|
||||
def cmd_peek(a):
|
||||
"""Peek memory location"""
|
||||
addr = value(a[1])
|
||||
dump = get("/memory/%d" % addr)
|
||||
print "%04X: %02X" % (addr, dump[0])
|
||||
|
||||
|
||||
def cmd_poke(a):
|
||||
"""Poke memory location"""
|
||||
addr = value(a[1])
|
||||
val = value(a[2])
|
||||
post("/memory/%d" % addr, [val])
|
||||
|
||||
|
||||
def cmd_status(a):
|
||||
"""CPU status"""
|
||||
status = get("/status")
|
||||
print "A=%02X X=%02X Y=%02X S=%02X PC=%04X F=%c%c0%c%c%c%c%c" % (
|
||||
status["accumulator"],
|
||||
status["x_index"],
|
||||
status["y_index"],
|
||||
status["stack_pointer"],
|
||||
status["program_counter"],
|
||||
"N" if status["sign_flag"] else "n",
|
||||
"V" if status["overflow_flag"] else "v",
|
||||
"B" if status["break_flag"] else "b",
|
||||
"D" if status["decimal_mode_flag"] else "d",
|
||||
"I" if status["interrupt_disable_flag"] else "i",
|
||||
"Z" if status["zero_flag"] else "z",
|
||||
"C" if status["carry_flag"] else "c",
|
||||
)
|
||||
disasm = get("/disassemble/%d" % status["program_counter"])
|
||||
print format_disassemble(disasm[0])
|
||||
|
||||
|
||||
def cmd_quit(a):
|
||||
"""Quit"""
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def cmd_reset(a):
|
||||
"""Reset"""
|
||||
post("/reset")
|
||||
|
||||
Commands = {
|
||||
"disassemble": cmd_disassemble,
|
||||
"dump": cmd_dump,
|
||||
"help": cmd_help,
|
||||
"peek": cmd_peek,
|
||||
"poke": cmd_poke,
|
||||
"status": cmd_status,
|
||||
"quit": cmd_quit,
|
||||
"reset": cmd_reset,
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
print "ApplePy control console"
|
||||
while True:
|
||||
s = raw_input("6502> ")
|
||||
a = s.strip().split()
|
||||
f = Commands.get(a[0])
|
||||
if f is not None:
|
||||
f(a)
|
||||
else:
|
||||
print "Unknown command:", s
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
1229
cpu6502.py
Normal file
1229
cpu6502.py
Normal file
File diff suppressed because it is too large
Load Diff
136
tests.py
136
tests.py
|
@ -1,11 +1,11 @@
|
|||
import unittest
|
||||
from applepy import Memory, CPU
|
||||
from cpu6502 import Memory, CPU
|
||||
|
||||
|
||||
class TestMemory(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.memory = Memory()
|
||||
self.memory = Memory(use_bus=False)
|
||||
|
||||
def test_load(self):
|
||||
self.memory.load(0x1000, [0x01, 0x02, 0x03])
|
||||
|
@ -14,9 +14,9 @@ class TestMemory(unittest.TestCase):
|
|||
self.assertEqual(self.memory.read_byte(None, 0x1002), 0x03)
|
||||
|
||||
def test_write(self):
|
||||
self.memory.write_byte(0x1000, 0x11)
|
||||
self.memory.write_byte(0x1001, 0x12)
|
||||
self.memory.write_byte(0x1002, 0x13)
|
||||
self.memory.write_byte(None, 0x1000, 0x11)
|
||||
self.memory.write_byte(None, 0x1001, 0x12)
|
||||
self.memory.write_byte(None, 0x1002, 0x13)
|
||||
self.assertEqual(self.memory.read_byte(None, 0x1000), 0x11)
|
||||
self.assertEqual(self.memory.read_byte(None, 0x1001), 0x12)
|
||||
self.assertEqual(self.memory.read_byte(None, 0x1002), 0x13)
|
||||
|
@ -25,7 +25,7 @@ class TestMemory(unittest.TestCase):
|
|||
class TestLoadStoreOperations(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.memory = Memory()
|
||||
self.memory = Memory(use_bus=False)
|
||||
self.cpu = CPU(self.memory)
|
||||
self.memory.load(0x1000, [0x00, 0x01, 0x7F, 0x80, 0xFF])
|
||||
|
||||
|
@ -114,7 +114,7 @@ class TestLoadStoreOperations(unittest.TestCase):
|
|||
class TestRegisterTransferOperations(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.memory = Memory()
|
||||
self.memory = Memory(use_bus=False)
|
||||
self.cpu = CPU(self.memory)
|
||||
|
||||
def test_TAX(self):
|
||||
|
@ -189,7 +189,7 @@ class TestRegisterTransferOperations(unittest.TestCase):
|
|||
class TestStackOperations(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.memory = Memory()
|
||||
self.memory = Memory(use_bus=False)
|
||||
self.cpu = CPU(self.memory)
|
||||
|
||||
def test_TSX(self):
|
||||
|
@ -237,11 +237,11 @@ class TestStackOperations(unittest.TestCase):
|
|||
class TestLogicalOperations(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.memory = Memory()
|
||||
self.memory = Memory(use_bus=False)
|
||||
self.cpu = CPU(self.memory)
|
||||
|
||||
def test_AND(self):
|
||||
self.memory.write_byte(0x1000, 0x37)
|
||||
self.memory.write_byte(None, 0x1000, 0x37)
|
||||
self.cpu.accumulator = 0x34
|
||||
self.cpu.AND(0x1000)
|
||||
self.assertEqual(self.cpu.accumulator, 0x34)
|
||||
|
@ -254,7 +254,7 @@ class TestLogicalOperations(unittest.TestCase):
|
|||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
|
||||
def test_EOR(self):
|
||||
self.memory.write_byte(0x1000, 0x37)
|
||||
self.memory.write_byte(None, 0x1000, 0x37)
|
||||
self.cpu.accumulator = 0x34
|
||||
self.cpu.EOR(0x1000)
|
||||
self.assertEqual(self.cpu.accumulator, 0x03)
|
||||
|
@ -272,7 +272,7 @@ class TestLogicalOperations(unittest.TestCase):
|
|||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
|
||||
def test_ORA(self):
|
||||
self.memory.write_byte(0x1000, 0x37)
|
||||
self.memory.write_byte(None, 0x1000, 0x37)
|
||||
self.cpu.accumulator = 0x34
|
||||
self.cpu.ORA(0x1000)
|
||||
self.assertEqual(self.cpu.accumulator, 0x37)
|
||||
|
@ -290,31 +290,31 @@ class TestLogicalOperations(unittest.TestCase):
|
|||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
|
||||
def test_BIT(self):
|
||||
self.memory.write_byte(0x1000, 0x00)
|
||||
self.memory.write_byte(None, 0x1000, 0x00)
|
||||
self.cpu.accumulator = 0x00
|
||||
self.cpu.BIT(0x1000)
|
||||
self.assertEqual(self.cpu.overflow_flag, 0)
|
||||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
self.assertEqual(self.cpu.zero_flag, 1)
|
||||
self.memory.write_byte(0x1000, 0x40)
|
||||
self.memory.write_byte(None, 0x1000, 0x40)
|
||||
self.cpu.accumulator = 0x00
|
||||
self.cpu.BIT(0x1000)
|
||||
self.assertEqual(self.cpu.overflow_flag, 1)
|
||||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
self.assertEqual(self.cpu.zero_flag, 1)
|
||||
self.memory.write_byte(0x1000, 0x80)
|
||||
self.memory.write_byte(None, 0x1000, 0x80)
|
||||
self.cpu.accumulator = 0x00
|
||||
self.cpu.BIT(0x1000)
|
||||
self.assertEqual(self.cpu.overflow_flag, 0)
|
||||
self.assertEqual(self.cpu.sign_flag, 1)
|
||||
self.assertEqual(self.cpu.zero_flag, 1)
|
||||
self.memory.write_byte(0x1000, 0xC0)
|
||||
self.memory.write_byte(None, 0x1000, 0xC0)
|
||||
self.cpu.accumulator = 0x00
|
||||
self.cpu.BIT(0x1000)
|
||||
self.assertEqual(self.cpu.overflow_flag, 1)
|
||||
self.assertEqual(self.cpu.sign_flag, 1)
|
||||
self.assertEqual(self.cpu.zero_flag, 1)
|
||||
self.memory.write_byte(0x1000, 0xC0)
|
||||
self.memory.write_byte(None, 0x1000, 0xC0)
|
||||
self.cpu.accumulator = 0xC0
|
||||
self.cpu.BIT(0x1000)
|
||||
self.assertEqual(self.cpu.overflow_flag, 1)
|
||||
|
@ -325,7 +325,7 @@ class TestLogicalOperations(unittest.TestCase):
|
|||
class TestArithmeticOperations(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.memory = Memory()
|
||||
self.memory = Memory(use_bus=False)
|
||||
self.cpu = CPU(self.memory)
|
||||
|
||||
def test_ADC_without_BCD(self):
|
||||
|
@ -335,7 +335,7 @@ class TestArithmeticOperations(unittest.TestCase):
|
|||
# 1 + 1 = 2 (C = 0; V = 0)
|
||||
self.cpu.carry_flag = 0
|
||||
self.cpu.accumulator = 0x01
|
||||
self.memory.write_byte(0x1000, 0x01)
|
||||
self.memory.write_byte(None, 0x1000, 0x01)
|
||||
self.cpu.ADC(0x1000)
|
||||
self.assertEqual(self.cpu.accumulator, 0x02)
|
||||
self.assertEqual(self.cpu.carry_flag, 0)
|
||||
|
@ -344,7 +344,7 @@ class TestArithmeticOperations(unittest.TestCase):
|
|||
# 1 + -1 = 0 (C = 1; V = 0)
|
||||
self.cpu.carry_flag = 0
|
||||
self.cpu.accumulator = 0x01
|
||||
self.memory.write_byte(0x1000, 0xFF)
|
||||
self.memory.write_byte(None, 0x1000, 0xFF)
|
||||
self.cpu.ADC(0x1000)
|
||||
self.assertEqual(self.cpu.accumulator, 0x00)
|
||||
self.assertEqual(self.cpu.carry_flag, 1)
|
||||
|
@ -353,7 +353,7 @@ class TestArithmeticOperations(unittest.TestCase):
|
|||
# 127 + 1 = 128 (C = 0; V = 1)
|
||||
self.cpu.carry_flag = 0
|
||||
self.cpu.accumulator = 0x7F
|
||||
self.memory.write_byte(0x1000, 0x01)
|
||||
self.memory.write_byte(None, 0x1000, 0x01)
|
||||
self.cpu.ADC(0x1000)
|
||||
self.assertEqual(self.cpu.accumulator, 0x80) # @@@
|
||||
self.assertEqual(self.cpu.carry_flag, 0)
|
||||
|
@ -362,7 +362,7 @@ class TestArithmeticOperations(unittest.TestCase):
|
|||
# -128 + -1 = -129 (C = 1; V = 1)
|
||||
self.cpu.carry_flag = 0
|
||||
self.cpu.accumulator = 0x80
|
||||
self.memory.write_byte(0x1000, 0xFF)
|
||||
self.memory.write_byte(None, 0x1000, 0xFF)
|
||||
self.cpu.ADC(0x1000)
|
||||
self.assertEqual(self.cpu.accumulator, 0x7F) # @@@
|
||||
self.assertEqual(self.cpu.carry_flag, 1)
|
||||
|
@ -371,7 +371,7 @@ class TestArithmeticOperations(unittest.TestCase):
|
|||
# 63 + 64 + 1 = 128 (C = 0; V = 1)
|
||||
self.cpu.carry_flag = 1
|
||||
self.cpu.accumulator = 0x3F
|
||||
self.memory.write_byte(0x1000, 0x40)
|
||||
self.memory.write_byte(None, 0x1000, 0x40)
|
||||
self.cpu.ADC(0x1000)
|
||||
self.assertEqual(self.cpu.accumulator, 0x80)
|
||||
self.assertEqual(self.cpu.carry_flag, 0)
|
||||
|
@ -379,14 +379,14 @@ class TestArithmeticOperations(unittest.TestCase):
|
|||
|
||||
def test_SBC_without_BCD(self):
|
||||
self.cpu.accumulator = 0x02
|
||||
self.memory.write_byte(0x1000, 0x01)
|
||||
self.memory.write_byte(None, 0x1000, 0x01)
|
||||
self.cpu.SBC(0x1000)
|
||||
self.assertEqual(self.cpu.accumulator, 0x00)
|
||||
self.assertEqual(self.cpu.carry_flag, 1)
|
||||
self.assertEqual(self.cpu.overflow_flag, 0)
|
||||
|
||||
self.cpu.accumulator = 0x01
|
||||
self.memory.write_byte(0x1000, 0x02)
|
||||
self.memory.write_byte(None, 0x1000, 0x02)
|
||||
self.cpu.SBC(0x1000)
|
||||
self.assertEqual(self.cpu.accumulator, 0xFF)
|
||||
self.assertEqual(self.cpu.carry_flag, 0)
|
||||
|
@ -397,7 +397,7 @@ class TestArithmeticOperations(unittest.TestCase):
|
|||
# 0 - 1 = -1 (V = 0)
|
||||
self.cpu.carry_flag = 1
|
||||
self.cpu.accumulator = 0x00
|
||||
self.memory.write_byte(0x1000, 0x01)
|
||||
self.memory.write_byte(None, 0x1000, 0x01)
|
||||
self.cpu.SBC(0x1000)
|
||||
self.assertEqual(self.cpu.accumulator, 0xFF)
|
||||
self.assertEqual(self.cpu.carry_flag, 0)
|
||||
|
@ -406,7 +406,7 @@ class TestArithmeticOperations(unittest.TestCase):
|
|||
# -128 - 1 = -129 (V = 1)
|
||||
self.cpu.carry_flag = 1
|
||||
self.cpu.accumulator = 0x80
|
||||
self.memory.write_byte(0x1000, 0x01)
|
||||
self.memory.write_byte(None, 0x1000, 0x01)
|
||||
self.cpu.SBC(0x1000)
|
||||
self.assertEqual(self.cpu.accumulator, 0x7F)
|
||||
self.assertEqual(self.cpu.carry_flag, 1)
|
||||
|
@ -415,7 +415,7 @@ class TestArithmeticOperations(unittest.TestCase):
|
|||
# 127 - -1 = 128 (V = 1)
|
||||
self.cpu.carry_flag = 1
|
||||
self.cpu.accumulator = 0x7F
|
||||
self.memory.write_byte(0x1000, 0xFF)
|
||||
self.memory.write_byte(None, 0x1000, 0xFF)
|
||||
self.cpu.SBC(0x1000)
|
||||
self.assertEqual(self.cpu.accumulator, 0x80)
|
||||
self.assertEqual(self.cpu.carry_flag, 0)
|
||||
|
@ -424,7 +424,7 @@ class TestArithmeticOperations(unittest.TestCase):
|
|||
# -64 -64 -1 = -129 (V = 1)
|
||||
self.cpu.carry_flag = 0
|
||||
self.cpu.accumulator = 0xC0
|
||||
self.memory.write_byte(0x1000, 0x40)
|
||||
self.memory.write_byte(None, 0x1000, 0x40)
|
||||
self.cpu.SBC(0x1000)
|
||||
self.assertEqual(self.cpu.accumulator, 0x7F)
|
||||
self.assertEqual(self.cpu.carry_flag, 1)
|
||||
|
@ -434,35 +434,35 @@ class TestArithmeticOperations(unittest.TestCase):
|
|||
|
||||
def test_CMP(self):
|
||||
self.cpu.accumulator = 0x0A
|
||||
self.memory.write_byte(0x1000, 0x09)
|
||||
self.memory.write_byte(None, 0x1000, 0x09)
|
||||
self.cpu.CMP(0x1000)
|
||||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
self.assertEqual(self.cpu.zero_flag, 0)
|
||||
self.assertEqual(self.cpu.carry_flag, 1)
|
||||
|
||||
self.cpu.accumulator = 0x0A
|
||||
self.memory.write_byte(0x1000, 0x0B)
|
||||
self.memory.write_byte(None, 0x1000, 0x0B)
|
||||
self.cpu.CMP(0x1000)
|
||||
self.assertEqual(self.cpu.sign_flag, 1)
|
||||
self.assertEqual(self.cpu.zero_flag, 0)
|
||||
self.assertEqual(self.cpu.carry_flag, 0)
|
||||
|
||||
self.cpu.accumulator = 0x0A
|
||||
self.memory.write_byte(0x1000, 0x0A)
|
||||
self.memory.write_byte(None, 0x1000, 0x0A)
|
||||
self.cpu.CMP(0x1000)
|
||||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
self.assertEqual(self.cpu.zero_flag, 1)
|
||||
self.assertEqual(self.cpu.carry_flag, 1)
|
||||
|
||||
self.cpu.accumulator = 0xA0
|
||||
self.memory.write_byte(0x1000, 0x0A)
|
||||
self.memory.write_byte(None, 0x1000, 0x0A)
|
||||
self.cpu.CMP(0x1000)
|
||||
self.assertEqual(self.cpu.sign_flag, 1)
|
||||
self.assertEqual(self.cpu.zero_flag, 0)
|
||||
self.assertEqual(self.cpu.carry_flag, 1)
|
||||
|
||||
self.cpu.accumulator = 0x0A
|
||||
self.memory.write_byte(0x1000, 0xA0)
|
||||
self.memory.write_byte(None, 0x1000, 0xA0)
|
||||
self.cpu.CMP(0x1000)
|
||||
self.assertEqual(self.cpu.sign_flag, 0) # @@@
|
||||
self.assertEqual(self.cpu.zero_flag, 0)
|
||||
|
@ -470,35 +470,35 @@ class TestArithmeticOperations(unittest.TestCase):
|
|||
|
||||
def test_CPX(self):
|
||||
self.cpu.x_index = 0x0A
|
||||
self.memory.write_byte(0x1000, 0x09)
|
||||
self.memory.write_byte(None, 0x1000, 0x09)
|
||||
self.cpu.CPX(0x1000)
|
||||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
self.assertEqual(self.cpu.zero_flag, 0)
|
||||
self.assertEqual(self.cpu.carry_flag, 1)
|
||||
|
||||
self.cpu.x_index = 0x0A
|
||||
self.memory.write_byte(0x1000, 0x0B)
|
||||
self.memory.write_byte(None, 0x1000, 0x0B)
|
||||
self.cpu.CPX(0x1000)
|
||||
self.assertEqual(self.cpu.sign_flag, 1)
|
||||
self.assertEqual(self.cpu.zero_flag, 0)
|
||||
self.assertEqual(self.cpu.carry_flag, 0)
|
||||
|
||||
self.cpu.x_index = 0x0A
|
||||
self.memory.write_byte(0x1000, 0x0A)
|
||||
self.memory.write_byte(None, 0x1000, 0x0A)
|
||||
self.cpu.CPX(0x1000)
|
||||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
self.assertEqual(self.cpu.zero_flag, 1)
|
||||
self.assertEqual(self.cpu.carry_flag, 1)
|
||||
|
||||
self.cpu.x_index = 0xA0
|
||||
self.memory.write_byte(0x1000, 0x0A)
|
||||
self.memory.write_byte(None, 0x1000, 0x0A)
|
||||
self.cpu.CPX(0x1000)
|
||||
self.assertEqual(self.cpu.sign_flag, 1)
|
||||
self.assertEqual(self.cpu.zero_flag, 0)
|
||||
self.assertEqual(self.cpu.carry_flag, 1)
|
||||
|
||||
self.cpu.x_index = 0x0A
|
||||
self.memory.write_byte(0x1000, 0xA0)
|
||||
self.memory.write_byte(None, 0x1000, 0xA0)
|
||||
self.cpu.CPX(0x1000)
|
||||
self.assertEqual(self.cpu.sign_flag, 0) # @@@
|
||||
self.assertEqual(self.cpu.zero_flag, 0)
|
||||
|
@ -506,35 +506,35 @@ class TestArithmeticOperations(unittest.TestCase):
|
|||
|
||||
def test_CPY(self):
|
||||
self.cpu.y_index = 0x0A
|
||||
self.memory.write_byte(0x1000, 0x09)
|
||||
self.memory.write_byte(None, 0x1000, 0x09)
|
||||
self.cpu.CPY(0x1000)
|
||||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
self.assertEqual(self.cpu.zero_flag, 0)
|
||||
self.assertEqual(self.cpu.carry_flag, 1)
|
||||
|
||||
self.cpu.y_index = 0x0A
|
||||
self.memory.write_byte(0x1000, 0x0B)
|
||||
self.memory.write_byte(None, 0x1000, 0x0B)
|
||||
self.cpu.CPY(0x1000)
|
||||
self.assertEqual(self.cpu.sign_flag, 1)
|
||||
self.assertEqual(self.cpu.zero_flag, 0)
|
||||
self.assertEqual(self.cpu.carry_flag, 0)
|
||||
|
||||
self.cpu.y_index = 0x0A
|
||||
self.memory.write_byte(0x1000, 0x0A)
|
||||
self.memory.write_byte(None, 0x1000, 0x0A)
|
||||
self.cpu.CPY(0x1000)
|
||||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
self.assertEqual(self.cpu.zero_flag, 1)
|
||||
self.assertEqual(self.cpu.carry_flag, 1)
|
||||
|
||||
self.cpu.y_index = 0xA0
|
||||
self.memory.write_byte(0x1000, 0x0A)
|
||||
self.memory.write_byte(None, 0x1000, 0x0A)
|
||||
self.cpu.CPY(0x1000)
|
||||
self.assertEqual(self.cpu.sign_flag, 1)
|
||||
self.assertEqual(self.cpu.zero_flag, 0)
|
||||
self.assertEqual(self.cpu.carry_flag, 1)
|
||||
|
||||
self.cpu.y_index = 0x0A
|
||||
self.memory.write_byte(0x1000, 0xA0)
|
||||
self.memory.write_byte(None, 0x1000, 0xA0)
|
||||
self.cpu.CPY(0x1000)
|
||||
self.assertEqual(self.cpu.sign_flag, 0) # @@@
|
||||
self.assertEqual(self.cpu.zero_flag, 0)
|
||||
|
@ -544,21 +544,21 @@ class TestArithmeticOperations(unittest.TestCase):
|
|||
class TestIncrementDecrementOperations(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.memory = Memory()
|
||||
self.memory = Memory(use_bus=False)
|
||||
self.cpu = CPU(self.memory)
|
||||
|
||||
def test_INC(self):
|
||||
self.memory.write_byte(0x1000, 0x00)
|
||||
self.memory.write_byte(None, 0x1000, 0x00)
|
||||
self.cpu.INC(0x1000)
|
||||
self.assertEqual(self.memory.read_byte(None, 0x1000), 0x01)
|
||||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
self.assertEqual(self.cpu.zero_flag, 0)
|
||||
self.memory.write_byte(0x1000, 0x7F)
|
||||
self.memory.write_byte(None, 0x1000, 0x7F)
|
||||
self.cpu.INC(0x1000)
|
||||
self.assertEqual(self.memory.read_byte(None, 0x1000), 0x80)
|
||||
self.assertEqual(self.cpu.sign_flag, 1)
|
||||
self.assertEqual(self.cpu.zero_flag, 0)
|
||||
self.memory.write_byte(0x1000, 0xFF)
|
||||
self.memory.write_byte(None, 0x1000, 0xFF)
|
||||
self.cpu.INC(0x1000)
|
||||
self.assertEqual(self.memory.read_byte(None, 0x1000), 0x00)
|
||||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
|
@ -599,17 +599,17 @@ class TestIncrementDecrementOperations(unittest.TestCase):
|
|||
self.assertEqual(self.cpu.zero_flag, 1)
|
||||
|
||||
def test_DEC(self):
|
||||
self.memory.write_byte(0x1000, 0x01)
|
||||
self.memory.write_byte(None, 0x1000, 0x01)
|
||||
self.cpu.DEC(0x1000)
|
||||
self.assertEqual(self.memory.read_byte(None, 0x1000), 0x00)
|
||||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
self.assertEqual(self.cpu.zero_flag, 1)
|
||||
self.memory.write_byte(0x1000, 0x80)
|
||||
self.memory.write_byte(None, 0x1000, 0x80)
|
||||
self.cpu.DEC(0x1000)
|
||||
self.assertEqual(self.memory.read_byte(None, 0x1000), 0x7F)
|
||||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
self.assertEqual(self.cpu.zero_flag, 0)
|
||||
self.memory.write_byte(0x1000, 0x00)
|
||||
self.memory.write_byte(None, 0x1000, 0x00)
|
||||
self.cpu.DEC(0x1000)
|
||||
self.assertEqual(self.memory.read_byte(None, 0x1000), 0xFF)
|
||||
self.assertEqual(self.cpu.sign_flag, 1)
|
||||
|
@ -653,7 +653,7 @@ class TestIncrementDecrementOperations(unittest.TestCase):
|
|||
class TestShiftOperations(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.memory = Memory()
|
||||
self.memory = Memory(use_bus=False)
|
||||
self.cpu = CPU(self.memory)
|
||||
|
||||
def test_ASL(self):
|
||||
|
@ -663,7 +663,7 @@ class TestShiftOperations(unittest.TestCase):
|
|||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
self.assertEqual(self.cpu.zero_flag, 0)
|
||||
self.assertEqual(self.cpu.carry_flag, 0)
|
||||
self.memory.write_byte(0x1000, 0x02)
|
||||
self.memory.write_byte(None, 0x1000, 0x02)
|
||||
self.cpu.ASL(0x1000)
|
||||
self.assertEqual(self.memory.read_byte(None, 0x1000), 0x04)
|
||||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
|
@ -683,7 +683,7 @@ class TestShiftOperations(unittest.TestCase):
|
|||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
self.assertEqual(self.cpu.zero_flag, 1)
|
||||
self.assertEqual(self.cpu.carry_flag, 1)
|
||||
self.memory.write_byte(0x1000, 0x01)
|
||||
self.memory.write_byte(None, 0x1000, 0x01)
|
||||
self.cpu.LSR(0x1000)
|
||||
self.assertEqual(self.memory.read_byte(None, 0x1000), 0x00)
|
||||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
|
@ -712,14 +712,14 @@ class TestShiftOperations(unittest.TestCase):
|
|||
self.assertEqual(self.cpu.zero_flag, 0) # @@@
|
||||
self.assertEqual(self.cpu.carry_flag, 1)
|
||||
self.cpu.carry_flag = 0
|
||||
self.memory.write_byte(0x1000, 0x80)
|
||||
self.memory.write_byte(None, 0x1000, 0x80)
|
||||
self.cpu.ROL(0x1000)
|
||||
self.assertEqual(self.memory.read_byte(None, 0x1000), 0x00)
|
||||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
self.assertEqual(self.cpu.zero_flag, 1) # @@@
|
||||
self.assertEqual(self.cpu.carry_flag, 1)
|
||||
self.cpu.carry_flag = 1
|
||||
self.memory.write_byte(0x1000, 0x80)
|
||||
self.memory.write_byte(None, 0x1000, 0x80)
|
||||
self.cpu.ROL(0x1000)
|
||||
self.assertEqual(self.memory.read_byte(None, 0x1000), 0x01)
|
||||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
|
@ -742,14 +742,14 @@ class TestShiftOperations(unittest.TestCase):
|
|||
self.assertEqual(self.cpu.zero_flag, 0) # @@@
|
||||
self.assertEqual(self.cpu.carry_flag, 1)
|
||||
self.cpu.carry_flag = 0
|
||||
self.memory.write_byte(0x1000, 0x01)
|
||||
self.memory.write_byte(None, 0x1000, 0x01)
|
||||
self.cpu.ROR(0x1000)
|
||||
self.assertEqual(self.memory.read_byte(None, 0x1000), 0x00)
|
||||
self.assertEqual(self.cpu.sign_flag, 0)
|
||||
self.assertEqual(self.cpu.zero_flag, 1) # @@@
|
||||
self.assertEqual(self.cpu.carry_flag, 1)
|
||||
self.cpu.carry_flag = 1
|
||||
self.memory.write_byte(0x1000, 0x01)
|
||||
self.memory.write_byte(None, 0x1000, 0x01)
|
||||
self.cpu.ROR(0x1000)
|
||||
self.assertEqual(self.memory.read_byte(None, 0x1000), 0x80)
|
||||
self.assertEqual(self.cpu.sign_flag, 1) # @@@
|
||||
|
@ -760,7 +760,7 @@ class TestShiftOperations(unittest.TestCase):
|
|||
class TestJumpCallOperations(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.memory = Memory()
|
||||
self.memory = Memory(use_bus=False)
|
||||
self.cpu = CPU(self.memory)
|
||||
|
||||
def test_JMP(self):
|
||||
|
@ -775,8 +775,8 @@ class TestJumpCallOperations(unittest.TestCase):
|
|||
self.assertEqual(self.memory.read_byte(None, self.cpu.STACK_PAGE + self.cpu.stack_pointer + 2), 0x0F)
|
||||
|
||||
def test_RTS(self):
|
||||
self.memory.write_byte(self.cpu.STACK_PAGE + 0xFF, 0x12)
|
||||
self.memory.write_byte(self.cpu.STACK_PAGE + 0xFE, 0x33)
|
||||
self.memory.write_byte(None, self.cpu.STACK_PAGE + 0xFF, 0x12)
|
||||
self.memory.write_byte(None, self.cpu.STACK_PAGE + 0xFE, 0x33)
|
||||
self.cpu.stack_pointer = 0xFD
|
||||
self.cpu.RTS()
|
||||
self.assertEqual(self.cpu.program_counter, 0x1234)
|
||||
|
@ -792,7 +792,7 @@ class TestJumpCallOperations(unittest.TestCase):
|
|||
class TestBranchOperations(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.memory = Memory()
|
||||
self.memory = Memory(use_bus=False)
|
||||
self.cpu = CPU(self.memory)
|
||||
|
||||
def test_BCC(self):
|
||||
|
@ -879,7 +879,7 @@ class TestBranchOperations(unittest.TestCase):
|
|||
class TestStatusFlagOperations(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.memory = Memory()
|
||||
self.memory = Memory(use_bus=False)
|
||||
self.cpu = CPU(self.memory)
|
||||
|
||||
def test_CLC(self):
|
||||
|
@ -921,7 +921,7 @@ class TestStatusFlagOperations(unittest.TestCase):
|
|||
class TestSystemFunctionOperations(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.memory = Memory()
|
||||
self.memory = Memory(use_bus=False)
|
||||
self.cpu = CPU(self.memory)
|
||||
|
||||
def test_BRK(self):
|
||||
|
@ -936,9 +936,9 @@ class TestSystemFunctionOperations(unittest.TestCase):
|
|||
self.assertEqual(self.memory.read_byte(None, self.cpu.STACK_PAGE + self.cpu.stack_pointer + 3), 0x10)
|
||||
|
||||
def test_RTI(self):
|
||||
self.memory.write_byte(self.cpu.STACK_PAGE + 0xFF, 0x12)
|
||||
self.memory.write_byte(self.cpu.STACK_PAGE + 0xFE, 0x33)
|
||||
self.memory.write_byte(self.cpu.STACK_PAGE + 0xFD, 0x20)
|
||||
self.memory.write_byte(None, self.cpu.STACK_PAGE + 0xFF, 0x12)
|
||||
self.memory.write_byte(None, self.cpu.STACK_PAGE + 0xFE, 0x33)
|
||||
self.memory.write_byte(None, self.cpu.STACK_PAGE + 0xFD, 0x20)
|
||||
self.cpu.stack_pointer = 0xFC
|
||||
self.cpu.RTI()
|
||||
self.assertEqual(self.cpu.program_counter, 0x1233)
|
||||
|
@ -951,7 +951,7 @@ class TestSystemFunctionOperations(unittest.TestCase):
|
|||
class Test6502Bugs(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.memory = Memory()
|
||||
self.memory = Memory(use_bus=False)
|
||||
self.cpu = CPU(self.memory)
|
||||
|
||||
def test_zero_page_x(self):
|
||||
|
|
Loading…
Reference in New Issue
Block a user