Skip to content

Commit

Permalink
Improve compatibility with newer test ROMs
Browse files Browse the repository at this point in the history
  • Loading branch information
GMH-Code committed Aug 2, 2022
1 parent 3fe4291 commit f40e564
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 36 deletions.
2 changes: 1 addition & 1 deletion scchip/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

# App identification
APP_NAME = "SuperChocChip Emulator"
APP_VERSION = "1.0.1"
APP_VERSION = "1.0.2"
APP_COPYRIGHT = "Copyright (C) 2022 Gregory Maynard-Hoare, licensed under GNU Affero General Public License v3.0"
APP_INTRO = "{} V{} -- ".format(APP_NAME, APP_VERSION)

Expand Down
36 changes: 18 additions & 18 deletions scchip/cpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from time import time
from random import randint
from math import ceil
from .constants import APP_INTRO, ARCH_SUPERCHIP_1_0, ARCH_CHIP48, ARCH_SUPERCHIP_1_1, ARCH_XO_CHIP
from .constants import APP_INTRO, ARCH_CHIP8, ARCH_SUPERCHIP_1_0, ARCH_CHIP48, ARCH_SUPERCHIP_1_1, ARCH_XO_CHIP

CPU_ENDIAN = "big" # CHIP-8 is big-endian
TIMER_FREQ = 60.0 # 60Hz emulated system timer refresh
Expand Down Expand Up @@ -47,7 +47,7 @@ def __init__(self, arch, ram, stack, framebuffer, inputs, debugger, clock_speed=

if clock_speed is None:
# Default clock speed
auto_clock_speed = 0 if arch >= ARCH_XO_CHIP else 1000
auto_clock_speed = 0 if arch >= ARCH_SUPERCHIP_1_0 else 1000
else:
# User-specified clock speed (user can specify 0 for infinite)
auto_clock_speed = clock_speed
Expand All @@ -58,23 +58,23 @@ def __init__(self, arch, ram, stack, framebuffer, inputs, debugger, clock_speed=
Quirks
------
- Load quirks should default to enabled if emulating Super-CHIP 1.1, or above, but not below that.
- Shift quirks should always default to enabled. Some say this should only be set if emulating beyond CHIP-8,
but that breaks too many games in regular CHIP-8 mode.
- Logic quirks should be enabled if emulating Super-CHIP 1.0, CHIP-48, or above.
- Index overflow quirks should be disabled by default. Some Super-CHIP games fail if enabled.
- Index increment quirks should be disabled by default, but enable for accurate CHIP-48 behaviour.
- Jump quirks should be disabled by default, unless emulating CHIP-48 (only).
- Load quirks : Enabled on XO-CHIP and CHIP-8 systems.
- Shift quirks : Enabled on Super-CHIP-based systems only.
- Logic quirks : Enabled on CHIP-8 systems only.
- Index overflow quirks : Disabled. Some Super-CHIP games fail if enabled.
- Index increment quirks: Enabled for accurate CHIP-48 behaviour only.
- Jump quirks : Enabled on Super-CHIP-based systems only.
"""

self.load_quirks = arch >= ARCH_SUPERCHIP_1_1 if load_quirks is None else load_quirks
self.shift_quirks = True if shift_quirks is None else shift_quirks
self.logic_quirks = arch >= ARCH_SUPERCHIP_1_0 if logic_quirks is None else logic_quirks
arch_is_schip = (arch >= ARCH_SUPERCHIP_1_0 and arch <= ARCH_SUPERCHIP_1_1) # Includes CHIP-48
self.load_quirks = (arch >= ARCH_XO_CHIP or arch == ARCH_CHIP8) if load_quirks is None else load_quirks
self.shift_quirks = arch_is_schip if shift_quirks is None else shift_quirks
self.logic_quirks = (arch == ARCH_CHIP8) if logic_quirks is None else logic_quirks
self.index_overflow_quirks = False if index_overflow_quirks is None else index_overflow_quirks
self.index_increment_quirks = (
(arch == ARCH_CHIP48) if index_increment_quirks is None else index_increment_quirks
)
self.jump_quirks = (arch == ARCH_CHIP48) if jump_quirks is None else jump_quirks # OFF by default
self.jump_quirks = arch_is_schip if jump_quirks is None else jump_quirks

# Define instruction pointers.
# n = Nibble
Expand Down Expand Up @@ -403,10 +403,10 @@ def _7xkk(self): # ADD Vx, byte
self.v[vx] = byte & 0xFF

def _post_8xy0_8xy1_8xy2_8xy3(self):
if not self.logic_quirks:
if self.logic_quirks:
self.v[0xF] = 0

# All 8 instructions set VF on original CHIP-8
# All 8 instructions set Vf on original CHIP-8
def _8xy0(self): # LD Vx, Vy
if self.live_debug:
self.debug("LD V{:01x}, V{:01x}".format(self.vx, self.vy))
Expand Down Expand Up @@ -459,7 +459,7 @@ def _8xy5(self): # SUB Vx, Vy
self._post_8xy5_8xy7(self.v[self.vx] - self.v[self.vy])

def _8xy6(self): # SHR Vx {, Vy}
# On original CHIP-8, Vy is used. On Super-CHIP 1.0 and above, Vx is used
# On Super-CHIP, Vx is used. On CHIP-8 and XO-CHIP, Vy is used.
vr = self.vx if self.shift_quirks else self.vy

if self.live_debug:
Expand All @@ -476,7 +476,7 @@ def _8xy7(self): # SUBN Vx, Vy
self._post_8xy5_8xy7(self.v[self.vy] - self.v[self.vx])

def _8xyE(self): # SHL Vx {, Vy}
# On original CHIP-8, Vy is used. On Super-CHIP 1.0 and above, Vx is used
# On Super-CHIP, Vx is used. On CHIP-8 and XO-CHIP, Vy is used.
vr = self.vx if self.shift_quirks else self.vy

if self.live_debug:
Expand Down Expand Up @@ -661,7 +661,7 @@ def _Fx33(self): # LD B, Vx
self.ram.write((i + 2) & self.i_bitmask, val % 10) # Least-signifiant digit

def _post_Fx55_Fx65(self):
if not self.load_quirks:
if self.load_quirks:
self.i += self.vx

if not self.index_increment_quirks:
Expand Down
2 changes: 1 addition & 1 deletion superchocchip.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
__author__ = "Gregory Maynard-Hoare"
__copyright__ = "Copyright (C) 2022 Gregory Maynard-Hoare"
__license__ = "GNU Affero General Public License v3.0"
__version__ = "1.0.1"
__version__ = "1.0.2"

from argparse import ArgumentParser
from scchip import main
Expand Down
32 changes: 16 additions & 16 deletions test/test_cpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,18 +181,18 @@ def test_cpu_8xy5_no_borrow(self): # SUB Vx, Vy (no borrow)
self.assertEqual(0x0, self.cpu.v[0xF])

def test_cpu_8xy6_borrow(self): # SHR Vx {, Vy}
self.cpu.v[0x1] = 0x1
self.cpu.v[0x2] = 0x4 # Use Vf as an input to check flag ordering too
self._check_opcode(0x8146)
self.cpu.v[0x1] = 0x4
self.cpu.v[0x2] = 0x1 # Use Vf as an input to check flag ordering too
self._check_opcode(0x8126)
self.assertEqual(0x0, self.cpu.v[0x1])
self.assertEqual(0x4, self.cpu.v[0x2])
self.assertEqual(0x1, self.cpu.v[0x2])
self.assertEqual(0x1, self.cpu.v[0xF])

def test_cpu_8xy6_no_borrow(self): # SHR Vx {, Vy}
self.cpu.v[0x1] = 0x1
self.cpu.v[0x2] = 0x2
self._check_opcode(0x8416)
self.assertEqual(0x1, self.cpu.v[0x1])
self.cpu.v[0x1] = 0x4
self.cpu.v[0x2] = 0x1
self._check_opcode(0x8216)
self.assertEqual(0x4, self.cpu.v[0x1])
self.assertEqual(0x2, self.cpu.v[0x2])
self.assertEqual(0x0, self.cpu.v[0xF])

Expand All @@ -207,18 +207,18 @@ def test_cpu_8xy7(self): # SUBN Vx, Vy (borrows already tested in SUB)
def test_cpu_8xye_carry(self): # SHL Vx {, Vy}
self.cpu.v[0x1] = 0x4
self.cpu.v[0x2] = 0x2
self._check_opcode(0x814E)
self.assertEqual(0x8, self.cpu.v[0x1])
self._check_opcode(0x812E)
self.assertEqual(0x4, self.cpu.v[0x1])
self.assertEqual(0x2, self.cpu.v[0x2])
self.assertEqual(0x0, self.cpu.v[0xF])

def test_cpu_8xye_no_carry(self): # SHL Vx {, Vy}
self.cpu.v[0x1] = 0xFE
self.cpu.v[0x2] = 0x1
self.cpu.v[0x4] = 0x1
self._check_opcode(0x814E)
self.assertEqual(0xFC, self.cpu.v[0x1])
self.assertEqual(0x1, self.cpu.v[0x2])
self.assertEqual(0x1, self.cpu.v[0xF])
self.assertEqual(0x2, self.cpu.v[0x1])
self.assertEqual(0x1, self.cpu.v[0x4])
self.assertEqual(0x0, self.cpu.v[0xF])

def test_cpu_9xy0(self): # SNE Vx, Vy
self.cpu.v[0x2] = 0x15
Expand Down Expand Up @@ -458,9 +458,9 @@ def test_cpu_fx3a(self): # XPR

def test_cpu_logic_quirks(self):
for logic_quirks in False, True:
self.cpu.v[0xF] = 1
self.cpu.v[0xF] = 0x2
self.cpu.logic_quirks = logic_quirks

for i in range(4):
self._check_opcode(0x8120 + i)
self.assertEqual(int(logic_quirks), self.cpu.v[0xF])
self.assertEqual(int(not logic_quirks) * 2, self.cpu.v[0xF])

0 comments on commit f40e564

Please sign in to comment.