Compare commits

...

39 Commits
0.1 ... master

Author SHA1 Message Date
James Tauber 934bf1a495 PEP8 compliance 2014-07-15 11:29:11 -04:00
James Tauber d340d9cb5f whitespace 2014-07-15 11:07:17 -04:00
James Tauber fe80bc897d added note about exact pip and brew commands I used 2013-03-08 07:00:00 -05:00
James Tauber 0d41f951b9 improved hires colour, fixed non-ASCII key crash, fixed to work with later pygame/numpy 2013-03-08 06:56:52 -05:00
James Tauber e9c9581857 added explicit mention of License in README 2012-07-23 04:18:55 -04:00
James Tauber 6a818ae8ac added mention of numpy requirement 2012-07-23 04:18:42 -04:00
James Tauber 1de396334e added MIT license 2012-07-23 04:15:26 -04:00
James Tauber 82de64b000 treat README as Markdown 2012-07-23 04:14:42 -04:00
James Tauber 2492947e1d made applepy.py executable 2012-04-18 07:36:57 -04:00
James Tauber bdbc60e6e5 Merge pull request #16 from ghewgill/startpc
Startup option to support running binary images
2012-04-18 03:21:09 -07:00
Greg Hewgill 9ff2dbb70e add --pc switch for starting run at specific program counter 2012-04-18 07:43:19 +12:00
Greg Hewgill 4ee9b846f9 initialise display state variables in constructor 2011-10-01 08:17:38 +13:00
James Tauber c9ecb5f31e Merge pull request #15 from ghewgill/control
Control channel as HTTP/REST/JSON server
2011-08-22 10:51:03 -07:00
Greg Hewgill 60acf37150 add console control utility 2011-08-21 18:30:49 +12:00
Greg Hewgill 6782a1d268 implement post to /memory in control requests 2011-08-21 18:29:42 +12:00
Greg Hewgill 80e95d114b control channel is now HTTP/REST/JSON 2011-08-20 21:46:14 +12:00
James Tauber fad0de8cc9 Merge pull request #13 from ghewgill/socket
Change comms to use sockets instead of stdio
2011-08-20 01:50:43 -07:00
James Tauber aac75ef1cb Merge pull request #14 from ghewgill/windows
open memory files in binary mode
2011-08-20 01:49:38 -07:00
Greg Hewgill 0604bd1515 add fileno() method to ControlHandler for better compatiblity with select() 2011-08-20 18:22:33 +12:00
Greg Hewgill 0b86a8693f disassemble show instruction bytes 2011-08-20 15:37:55 +12:00
Greg Hewgill 29b1342a47 reincarnate disassembler on control channel 2011-08-20 14:23:51 +12:00
Greg Hewgill aee0bba7aa add dump memory command 2011-08-20 13:59:36 +12:00
Greg Hewgill 8b62860152 refactor control command processing 2011-08-20 13:59:22 +12:00
Greg Hewgill 19693bc905 start of cpu core control channel
Currently this listens on TCP port 6502 on localhost. The protocol
is a simple text protocol, type "help" for a list of commands.
2011-08-19 21:48:46 +12:00
Greg Hewgill a673f8a4d4 graceful shutdown if cpu core exits 2011-08-19 21:43:12 +12:00
Greg Hewgill 9f09818aa0 abandon startup if cpu module does not start 2011-08-19 21:07:19 +12:00
Greg Hewgill 15e174c02a rename --ui switch to --bus 2011-08-19 20:30:55 +12:00
Greg Hewgill 9ffbf63716 open memory files in binary mode 2011-08-18 21:21:42 +12:00
Greg Hewgill dcc8e9d8ce update curses UI for socket comms 2011-08-18 21:14:49 +12:00
Greg Hewgill cd692af6f3 use sockets for comms instead of stdio 2011-08-18 21:04:11 +12:00
James Tauber c36ad8b662 Merge pull request #12 from ghewgill/patch-1
Mention the minimal applepy_curses.py in README
2011-08-17 21:12:17 -07:00
Greg Hewgill a73ab29be2 Edited README via GitHub 2011-08-19 11:40:19 +12:00
Greg Hewgill 338f8962fd Mention the minimal applepy_curses.py in README 2011-08-19 11:37:00 +12:00
James Tauber 6f1005693c Merge pull request #11 from ghewgill/cassette
Cassette
2011-08-16 03:59:27 -07:00
Greg Hewgill b8c7949d8e attempt to skip to data part of tape 2011-08-16 18:22:41 +12:00
Greg Hewgill 6951db69ad finish cassette support 2011-08-16 16:41:15 +12:00
Greg Hewgill 4963eeca9d initial cassette input 2011-08-16 15:49:48 +12:00
James Tauber 360f415fc9 Merge pull request #10 from ghewgill/splitcore
Separate CPU core and UI processes
2011-08-15 20:10:14 -07:00
Greg Hewgill c9c609be1d Separate CPU core and UI processes
This is a first step toward separating the CPU core and UI.  The UI program
starts the CPU core as a subprocess and communicates through its standard input
and output. The protocol is deliberately simple at this point. Each bus request
from the core is exactly eight bytes:

    +-------------------------+
    | cpu cycle counter high  |
    +-------------------------+
    | cpu cycle counter       |
    +-------------------------+
    | cpu cycle counter       |
    +-------------------------+
    | cpu cycle counter low   |
    +-------------------------+
    | 0x00=read / 0x01=write  |
    +-------------------------+
    | address high            |
    +-------------------------+
    | address low             |
    +-------------------------+
    | value (unused for read) |
    +-------------------------+

A single-byte response from the UI is required for a read request, and a
response must not be sent for a write request.

The above protocol is expected to change. For example:

    - the UI should tell the CPU core which address ranges are of interest
    - needs ability to send memory images to the core (both ROM and RAM)

The stream communications is currently buggy because it expects that all eight
bytes will be read when requested (that is, partial reads are not handled). In
practice, this seems to work okay for the moment.

To improve portability, it may be better to communicate over TCP sockets
instead of stdin/stdout.
2011-08-16 12:54:23 +12:00
9 changed files with 1913 additions and 1187 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.pyc

19
LICENSE Normal file
View 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.

View File

@ -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.

1151
applepy.py Normal file → Executable file

File diff suppressed because it is too large Load Diff

133
applepy_curses.py Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

380
tests.py
View File

@ -1,34 +1,34 @@
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])
self.assertEqual(self.memory.read_byte(None, 0x1000), 0x01)
self.assertEqual(self.memory.read_byte(None, 0x1001), 0x02)
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)
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])
def test_LDA(self):
self.cpu.LDA(0x1000)
self.assertEqual(self.cpu.accumulator, 0x00)
@ -50,7 +50,7 @@ class TestLoadStoreOperations(unittest.TestCase):
self.assertEqual(self.cpu.accumulator, 0xFF)
self.assertEqual(self.cpu.sign_flag, 1)
self.assertEqual(self.cpu.zero_flag, 0)
def test_LDX(self):
self.cpu.LDX(0x1000)
self.assertEqual(self.cpu.x_index, 0x00)
@ -72,7 +72,7 @@ class TestLoadStoreOperations(unittest.TestCase):
self.assertEqual(self.cpu.x_index, 0xFF)
self.assertEqual(self.cpu.sign_flag, 1)
self.assertEqual(self.cpu.zero_flag, 0)
def test_LDY(self):
self.cpu.LDY(0x1000)
self.assertEqual(self.cpu.y_index, 0x00)
@ -94,17 +94,17 @@ class TestLoadStoreOperations(unittest.TestCase):
self.assertEqual(self.cpu.y_index, 0xFF)
self.assertEqual(self.cpu.sign_flag, 1)
self.assertEqual(self.cpu.zero_flag, 0)
def test_STA(self):
self.cpu.accumulator = 0x37
self.cpu.STA(0x2000)
self.assertEqual(self.memory.read_byte(None, 0x2000), 0x37)
def test_STX(self):
self.cpu.x_index = 0x38
self.cpu.STX(0x2000)
self.assertEqual(self.memory.read_byte(None, 0x2000), 0x38)
def test_STY(self):
self.cpu.y_index = 0x39
self.cpu.STY(0x2000)
@ -112,11 +112,11 @@ 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):
self.cpu.accumulator = 0x00
self.cpu.TAX()
@ -133,7 +133,7 @@ class TestRegisterTransferOperations(unittest.TestCase):
self.assertEqual(self.cpu.x_index, 0xFF)
self.assertEqual(self.cpu.sign_flag, 1)
self.assertEqual(self.cpu.zero_flag, 0)
def test_TAY(self):
self.cpu.accumulator = 0x00
self.cpu.TAY()
@ -150,7 +150,7 @@ class TestRegisterTransferOperations(unittest.TestCase):
self.assertEqual(self.cpu.y_index, 0xFF)
self.assertEqual(self.cpu.sign_flag, 1)
self.assertEqual(self.cpu.zero_flag, 0)
def test_TXA(self):
self.cpu.x_index = 0x00
self.cpu.TXA()
@ -167,7 +167,7 @@ class TestRegisterTransferOperations(unittest.TestCase):
self.assertEqual(self.cpu.accumulator, 0xFF)
self.assertEqual(self.cpu.sign_flag, 1)
self.assertEqual(self.cpu.zero_flag, 0)
def test_TYA(self):
self.cpu.y_index = 0x00
self.cpu.TYA()
@ -187,22 +187,22 @@ 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):
s = self.cpu.stack_pointer
self.cpu.TSX()
self.assertEqual(self.cpu.x_index, s)
# @@@ check NZ?
def test_TXS(self):
x = self.cpu.x_index
self.cpu.TXS()
self.assertEqual(self.cpu.stack_pointer, x)
def test_PHA_and_PLA(self):
self.cpu.accumulator = 0x00
self.cpu.PHA()
@ -225,7 +225,7 @@ class TestStackOperations(unittest.TestCase):
self.assertEqual(self.cpu.accumulator, 0x00)
self.assertEqual(self.cpu.zero_flag, 1)
self.assertEqual(self.cpu.sign_flag, 0)
def test_PHP_and_PLP(self):
p = self.cpu.status_as_byte()
self.cpu.PHP()
@ -235,13 +235,13 @@ 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)
@ -252,9 +252,9 @@ class TestLogicalOperations(unittest.TestCase):
self.assertEqual(self.cpu.accumulator, 0x00)
self.assertEqual(self.cpu.zero_flag, 1)
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)
@ -270,9 +270,9 @@ class TestLogicalOperations(unittest.TestCase):
self.assertEqual(self.cpu.accumulator, 0x00)
self.assertEqual(self.cpu.zero_flag, 1)
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)
@ -288,33 +288,33 @@ class TestLogicalOperations(unittest.TestCase):
self.assertEqual(self.cpu.accumulator, 0x00)
self.assertEqual(self.cpu.zero_flag, 1)
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)
@ -323,247 +323,247 @@ 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):
## test cases from http://www.6502.org/tutorials/vflag.html
# 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)
self.assertEqual(self.cpu.overflow_flag, 0)
# 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)
self.assertEqual(self.cpu.overflow_flag, 0)
# 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.accumulator, 0x80) # @@@
self.assertEqual(self.cpu.carry_flag, 0)
self.assertEqual(self.cpu.overflow_flag, 1)
# -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.accumulator, 0x7F) # @@@
self.assertEqual(self.cpu.carry_flag, 1)
self.assertEqual(self.cpu.overflow_flag, 1)
# 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)
self.assertEqual(self.cpu.overflow_flag, 1)
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)
self.assertEqual(self.cpu.overflow_flag, 0) # @@@
self.assertEqual(self.cpu.overflow_flag, 0) # @@@
## test cases from http://www.6502.org/tutorials/vflag.html
# 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)
self.assertEqual(self.cpu.overflow_flag, 0) # @@@
self.assertEqual(self.cpu.overflow_flag, 0) # @@@
# -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)
self.assertEqual(self.cpu.overflow_flag, 1)
# 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)
self.assertEqual(self.cpu.overflow_flag, 1)
# -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)
self.assertEqual(self.cpu.overflow_flag, 1) # @@@
self.assertEqual(self.cpu.overflow_flag, 1) # @@@
## @@@ BCD versions still to do
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.sign_flag, 0) # @@@
self.assertEqual(self.cpu.zero_flag, 0)
self.assertEqual(self.cpu.carry_flag, 0)
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.sign_flag, 0) # @@@
self.assertEqual(self.cpu.zero_flag, 0)
self.assertEqual(self.cpu.carry_flag, 0)
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.sign_flag, 0) # @@@
self.assertEqual(self.cpu.zero_flag, 0)
self.assertEqual(self.cpu.carry_flag, 0)
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)
self.assertEqual(self.cpu.zero_flag, 1)
def test_INX(self):
self.cpu.x_index = 0x00
self.cpu.INX()
@ -580,7 +580,7 @@ class TestIncrementDecrementOperations(unittest.TestCase):
self.assertEqual(self.cpu.x_index, 0x00)
self.assertEqual(self.cpu.sign_flag, 0)
self.assertEqual(self.cpu.zero_flag, 1)
def test_INY(self):
self.cpu.y_index = 0x00
self.cpu.INY()
@ -597,24 +597,24 @@ class TestIncrementDecrementOperations(unittest.TestCase):
self.assertEqual(self.cpu.y_index, 0x00)
self.assertEqual(self.cpu.sign_flag, 0)
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)
self.assertEqual(self.cpu.zero_flag, 0)
def test_DEX(self):
self.cpu.x_index = 0x01
self.cpu.DEX()
@ -631,7 +631,7 @@ class TestIncrementDecrementOperations(unittest.TestCase):
self.assertEqual(self.cpu.x_index, 0xFF)
self.assertEqual(self.cpu.sign_flag, 1)
self.assertEqual(self.cpu.zero_flag, 0)
def test_DEY(self):
self.cpu.y_index = 0x01
self.cpu.DEY()
@ -651,11 +651,11 @@ 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):
self.cpu.accumulator = 0x01
self.cpu.ASL()
@ -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)
@ -675,7 +675,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)
def test_LSR(self):
self.cpu.accumulator = 0x01
self.cpu.LSR()
@ -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)
@ -695,7 +695,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)
def test_ROL(self):
self.cpu.carry_flag = 0
self.cpu.accumulator = 0x80
@ -709,92 +709,92 @@ class TestShiftOperations(unittest.TestCase):
self.cpu.ROL()
self.assertEqual(self.cpu.accumulator, 0x01)
self.assertEqual(self.cpu.sign_flag, 0)
self.assertEqual(self.cpu.zero_flag, 0) # @@@
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.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)
self.assertEqual(self.cpu.zero_flag, 0) # @@@
self.assertEqual(self.cpu.zero_flag, 0) # @@@
self.assertEqual(self.cpu.carry_flag, 1)
def test_ROR(self):
self.cpu.carry_flag = 0
self.cpu.accumulator = 0x01
self.cpu.ROR()
self.assertEqual(self.cpu.accumulator, 0x00)
self.assertEqual(self.cpu.sign_flag, 0)
self.assertEqual(self.cpu.zero_flag, 1) # @@@
self.assertEqual(self.cpu.zero_flag, 1) # @@@
self.assertEqual(self.cpu.carry_flag, 1)
self.cpu.carry_flag = 1
self.cpu.accumulator = 0x01
self.cpu.ROR()
self.assertEqual(self.cpu.accumulator, 0x80)
self.assertEqual(self.cpu.sign_flag, 1) # @@@
self.assertEqual(self.cpu.zero_flag, 0) # @@@
self.assertEqual(self.cpu.sign_flag, 1) # @@@
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.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) # @@@
self.assertEqual(self.cpu.zero_flag, 0) # @@@
self.assertEqual(self.cpu.sign_flag, 1) # @@@
self.assertEqual(self.cpu.zero_flag, 0) # @@@
self.assertEqual(self.cpu.carry_flag, 1)
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):
self.cpu.JMP(0x1000)
self.assertEqual(self.cpu.program_counter, 0x1000)
def test_JSR(self):
self.cpu.program_counter = 0x1000
self.cpu.JSR(0x2000)
self.assertEqual(self.cpu.program_counter, 0x2000)
self.assertEqual(self.memory.read_byte(None, self.cpu.STACK_PAGE + self.cpu.stack_pointer + 1), 0xFF)
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)
def test_JSR_and_RTS(self):
self.cpu.program_counter = 0x1000
self.cpu.JSR(0x2000)
self.assertEqual(self.cpu.program_counter, 0x2000)
self.cpu.RTS()
self.assertEqual(self.cpu.program_counter, 0x1000) # @@@
self.assertEqual(self.cpu.program_counter, 0x1000) # @@@
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):
self.cpu.program_counter = 0x1000
self.cpu.carry_flag = 1
@ -804,7 +804,7 @@ class TestBranchOperations(unittest.TestCase):
self.cpu.carry_flag = 0
self.cpu.BCC(0x2000)
self.assertEqual(self.cpu.program_counter, 0x2000)
def test_BCS(self):
self.cpu.program_counter = 0x1000
self.cpu.carry_flag = 0
@ -814,7 +814,7 @@ class TestBranchOperations(unittest.TestCase):
self.cpu.carry_flag = 1
self.cpu.BCS(0x2000)
self.assertEqual(self.cpu.program_counter, 0x2000)
def test_BEQ(self):
self.cpu.program_counter = 0x1000
self.cpu.zero_flag = 0
@ -824,7 +824,7 @@ class TestBranchOperations(unittest.TestCase):
self.cpu.zero_flag = 1
self.cpu.BEQ(0x2000)
self.assertEqual(self.cpu.program_counter, 0x2000)
def test_BMI(self):
self.cpu.program_counter = 0x1000
self.cpu.sign_flag = 0
@ -834,7 +834,7 @@ class TestBranchOperations(unittest.TestCase):
self.cpu.sign_flag = 1
self.cpu.BMI(0x2000)
self.assertEqual(self.cpu.program_counter, 0x2000)
def test_BNE(self):
self.cpu.program_counter = 0x1000
self.cpu.zero_flag = 1
@ -844,7 +844,7 @@ class TestBranchOperations(unittest.TestCase):
self.cpu.zero_flag = 0
self.cpu.BNE(0x2000)
self.assertEqual(self.cpu.program_counter, 0x2000)
def test_BPL(self):
self.cpu.program_counter = 0x1000
self.cpu.sign_flag = 1
@ -854,7 +854,7 @@ class TestBranchOperations(unittest.TestCase):
self.cpu.sign_flag = 0
self.cpu.BPL(0x2000)
self.assertEqual(self.cpu.program_counter, 0x2000)
def test_BVC(self):
self.cpu.program_counter = 0x1000
self.cpu.overflow_flag = 1
@ -864,7 +864,7 @@ class TestBranchOperations(unittest.TestCase):
self.cpu.overflow_flag = 0
self.cpu.BVC(0x2000)
self.assertEqual(self.cpu.program_counter, 0x2000)
def test_BVS(self):
self.cpu.program_counter = 0x1000
self.cpu.overflow_flag = 0
@ -877,41 +877,41 @@ 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):
self.cpu.carry_flag = 1
self.cpu.CLC()
self.assertEqual(self.cpu.carry_flag, 0)
def test_CLD(self):
self.cpu.decimal_mode_flag = 1
self.cpu.CLD()
self.assertEqual(self.cpu.decimal_mode_flag, 0)
def test_CLI(self):
self.cpu.interrupt_disable_flag = 1
self.cpu.CLI()
self.assertEqual(self.cpu.interrupt_disable_flag, 0)
def test_CLV(self):
self.cpu.overflow_flag = 1
self.cpu.CLV()
self.assertEqual(self.cpu.overflow_flag, 0)
def test_SEC(self):
self.cpu.carry_flag = 0
self.cpu.SEC()
self.assertEqual(self.cpu.carry_flag, 1)
def test_SED(self):
self.cpu.decimal_mode_flag = 0
self.cpu.SED()
self.assertEqual(self.cpu.decimal_mode_flag, 1)
def test_SEI(self):
self.cpu.interrupt_disable_flag = 0
self.cpu.SEI()
@ -919,11 +919,11 @@ 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):
self.cpu.program_counter = 0x1000
self.memory.rom.load(0xFFFE, [0x00, 0x20])
@ -934,26 +934,26 @@ class TestSystemFunctionOperations(unittest.TestCase):
self.assertEqual(self.memory.read_byte(None, self.cpu.STACK_PAGE + self.cpu.stack_pointer + 1), status)
self.assertEqual(self.memory.read_byte(None, self.cpu.STACK_PAGE + self.cpu.stack_pointer + 2), 0x01)
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)
self.assertEqual(self.cpu.status_as_byte(), 0x20)
def test_NOP(self):
self.cpu.NOP()
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):
self.cpu.x_index = 0x01
self.memory.load(0x1000, [0x00, 0x7F, 0xFF])
@ -961,7 +961,7 @@ class Test6502Bugs(unittest.TestCase):
self.assertEqual(self.cpu.zero_page_x_mode(), 0x01)
self.assertEqual(self.cpu.zero_page_x_mode(), 0x80)
self.assertEqual(self.cpu.zero_page_x_mode(), 0x00)
def test_indirect(self):
self.memory.load(0x20, [0x00, 0x20])
self.memory.load(0x00, [0x12])
@ -971,29 +971,29 @@ class Test6502Bugs(unittest.TestCase):
self.memory.load(0x2000, [0x05])
self.memory.load(0x1234, [0x05])
self.memory.load(0x2345, [0x00, 0xF0])
self.cpu.program_counter = 0x1000
self.cpu.x_index = 0x00
self.cpu.LDA(self.cpu.indirect_x_mode())
self.assertEqual(self.cpu.accumulator, 0x05)
self.cpu.y_index = 0x00
self.cpu.LDA(self.cpu.indirect_y_mode())
self.assertEqual(self.cpu.accumulator, 0x05)
self.cpu.y_index = 0x00
self.cpu.LDA(self.cpu.indirect_y_mode())
self.assertEqual(self.cpu.accumulator, 0x05)
self.cpu.x_index = 0x00
self.cpu.LDA(self.cpu.indirect_x_mode())
self.assertEqual(self.cpu.accumulator, 0x05)
self.cpu.x_index = 0xFF
self.cpu.LDA(self.cpu.indirect_x_mode())
self.assertEqual(self.cpu.accumulator, 0x05)
self.assertEqual(self.cpu.indirect_mode(), 0xF000)

2
tox.ini Normal file
View File

@ -0,0 +1,2 @@
[flake8]
ignore = E265,E501