Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions libs/hardware/cia.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,7 @@ def set_numpad_mode(self, mode: NUMPAD_MODE):
for key in NUMPAD_NUMS:
KEYBOARD.pop(key, None)

def clock(self, keys_pressed: set):
# Save keys pressed
self.keys_pressed = keys_pressed

def clock(self):
# Note: should use super(), but it's quite slow
CIA.clock(self)

Expand Down Expand Up @@ -286,7 +283,7 @@ def __init__(self, memory, bus):
self.memory.write_watchers.append((0xDD00, 0xDDFF, self.set_registers))

def clock(self):
return False
pass

def get_registers(self, address):
match address & 0x0F:
Expand Down
22 changes: 11 additions & 11 deletions libs/hardware/machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,14 +246,18 @@ def run(self, address: Optional[int] = None) -> None:
while self.running:
self.clock()
self._clock_counter += 1
logging.info(
f"Run {self._clock_counter} clock cycles "
f"and {self._frame_counter} frames"
)
pygame.quit()

def clock(self):
"""
Clocks all devices
"""
# Run VIC-II
frame = self.screen.clock(self._clock_counter)
frame = self.screen.clock()

# Display complete frame
if frame is not None:
Expand Down Expand Up @@ -286,8 +290,8 @@ def clock(self):
patch()

# Run CIAs
self.ciaA.clock(self.keys_pressed)
self.ciaB.clock()
self.ciaA.clock()
# self.ciaB.clock() # TODO: reactivate me

def service(self):
self.signal = self.manage_events()
Expand Down Expand Up @@ -371,18 +375,18 @@ def manage_events(self):
elif event.key == pygame.K_CAPSLOCK:
self.caps_lock = not self.caps_lock
if not self.caps_lock:
self.keys_pressed.remove(pygame.K_LSHIFT)
self.ciaA.keys_pressed.remove(pygame.K_LSHIFT)
else:
self.keys_pressed.add(event.key)
self.ciaA.keys_pressed.add(event.key)

if self.caps_lock:
self.keys_pressed.add(pygame.K_LSHIFT)
self.ciaA.keys_pressed.add(pygame.K_LSHIFT)

elif event.type == pygame.KEYUP:
if event.key == pygame.K_PAGEDOWN:
self.bus.nmi_clear("restore_key")
else:
self.keys_pressed.discard(event.key)
self.ciaA.keys_pressed.discard(event.key)

elif event.type == pygame.VIDEORESIZE:
h, w = event.size
Expand All @@ -392,10 +396,6 @@ def manage_events(self):
)

elif event.type == pygame.WINDOWCLOSE:
logging.info(
f"Run {self._clock_counter} clock cycles "
f"and {self._frame_counter} frames "
)
self.running = False

return signal
Expand Down
30 changes: 17 additions & 13 deletions libs/hardware/screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,16 @@ def pixelate_bitmap_multicolor(self, char_color: int, colors, pixels):
color_pack[p3],
)

def clock(self, clock_counter: int):
def clock(self):
if (
self.raster_x == 0
and self.raster_y == self.irq_raster_line
and self.irq_raster_enabled
):
# Raster IRQ
self.irq_raster_occured = True
self.bus.irq_set("VIC-II")

if self.raster_x < VIDEO_SIZE_H and self.raster_y < VIDEO_SIZE_V:
# Raster is in the visible area
pixel_pointer = self.raster_y * VIDEO_SIZE_H + self.raster_x
Expand Down Expand Up @@ -514,22 +523,15 @@ def clock(self, clock_counter: int):
if self.raster_x >= SCAN_AREA_H:
self.raster_x = 0
self.raster_y += 1
frame = None
if self.raster_y >= SCAN_AREA_V:
self.raster_y = 0
self._frame_on = self.DEN
frame = (
return (
# Cut frame size to ignore out-of-frame pixels
np.array(self.frame, dtype=np.ubyte)
.reshape((VIDEO_SIZE_V, VIDEO_SIZE_H))
.T
)
if self.irq_raster_enabled and self.irq_raster_line == self.raster_y:
# Raster IRQ
self.irq_raster_occured = True
self.bus.irq_set("VIC-II")

return frame


class VirtualScreen(VIC_II):
Expand All @@ -539,7 +541,7 @@ class VirtualScreen(VIC_II):

__slots__ = []

def clock(self, clock_counter: int):
def clock(self):
pass


Expand All @@ -549,11 +551,12 @@ class FastScreen(VIC_II):
Text only, fast
"""

__slots__ = ["font_cache"]
__slots__ = ["font_cache", "clock_counter"]

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.font_cache = self.cache_fonts()
self.clock_counter: int = 0

def cache_fonts(self):
cache = []
Expand All @@ -565,8 +568,8 @@ def cache_fonts(self):
cache.append(font)
return cache

def clock(self, clock_counter: int) -> np.array:
if clock_counter % CLOCKS_PER_FRAME == 0:
def clock(self) -> np.array:
if self.clock_counter % CLOCKS_PER_FRAME == 0:
frame = np.ones(VIDEO_SIZE, dtype="uint8") * self.border_color

if self.DEN:
Expand Down Expand Up @@ -598,3 +601,4 @@ def clock(self, clock_counter: int) -> np.array:
frame[24:344, 51:251] = chars
self.memory[0xD012] = 0 # This lets the system boot (see $FF5E)
return frame
self.clock_counter += 1
2 changes: 1 addition & 1 deletion tests/test_cia.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ def test_CIA_tod(cia):
def test_CIA_A_keyboard(pressed, column, expected, cia_a):
# Test only keymap-indipendent keys
cia_a.set_registers(0x00, 0xFF - column)
cia_a.clock(pressed)
cia_a.keys_pressed = pressed
assert cia_a.get_registers(0x01) == 0xFF - expected


Expand Down
20 changes: 10 additions & 10 deletions tests/test_screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,10 +242,10 @@ def test_VIC_II_raster_irq_occurs(vic_ii_raster):
vic_ii_raster.bus = irq_mock
irq_mock.irq_set.assert_not_called()

for i in range(63 * 2 - 1): # 1 clock before IRQ
vic_ii_raster.clock(0)
for i in range(63 * 2): # 1 clock before IRQ
vic_ii_raster.clock()
irq_mock.irq_set.assert_not_called()
vic_ii_raster.clock(0) # IRQ here
vic_ii_raster.clock() # IRQ here
irq_mock.irq_set.assert_called()

# Ack irq
Expand All @@ -255,23 +255,23 @@ def test_VIC_II_raster_irq_occurs(vic_ii_raster):


def test_VIC_II_raster_clock(vic_ii_raster):
frame = vic_ii_raster.clock(0)
frame = vic_ii_raster.clock()
assert frame is None
assert vic_ii_raster.raster_x == 8
assert vic_ii_raster.raster_y == 0

# To the next line
for _ in range(62):
vic_ii_raster.clock(0)
vic_ii_raster.clock()

assert vic_ii_raster.raster_x == 0
assert vic_ii_raster.raster_y == 1

# To the end of frame (311 lines missing, 1 clock remaining)
for _ in range(63 * 311 - 1):
vic_ii_raster.clock(0)
vic_ii_raster.clock()
# End of frame now
frame = vic_ii_raster.clock(0)
frame = vic_ii_raster.clock()

assert vic_ii_raster.raster_x == 0
assert vic_ii_raster.raster_y == 0
Expand All @@ -282,7 +282,7 @@ def test_VIC_II_raster_text_mode(vic_ii_raster):
vic_ii_raster._frame_on = True
frame = None
while frame is None:
frame = vic_ii_raster.clock(0)
frame = vic_ii_raster.clock()
assert frame.shape == VIDEO_SIZE


Expand All @@ -295,7 +295,7 @@ def test_VIC_II_raster_bad_lines_occur(vic_ii_raster):
vic_ii_raster.raster_y = 48
vic_ii_raster._frame_on = True

vic_ii_raster.clock(0)
vic_ii_raster.clock()

assert vic_ii_raster.char_buffer == bytearray([0x00] * 40)
assert vic_ii_raster.color_buffer == bytearray([0x00] * 40)
Expand All @@ -309,7 +309,7 @@ def test_VIC_II_raster_bad_lines_lock_CPU(vic_ii_raster):
with mock.patch("libs.hardware.bus.Bus") as irq_mock:
vic_ii_raster.bus = irq_mock
irq_mock.require_memory_bus.assert_not_called()
vic_ii_raster.clock(0)
vic_ii_raster.clock()
irq_mock.require_memory_bus.assert_called_with(cycles=40)


Expand Down