Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement scroll up operation #46

Merged
merged 2 commits into from
Jul 13, 2024
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
4 changes: 4 additions & 0 deletions chip8/cpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,10 @@ def clear_return(self):
num_lines = self.operand & 0x000F
self.screen.scroll_down(num_lines, self.bitplane)
self.last_op = f"Scroll Down {num_lines:01X}"
elif sub_operation == 0x00D0:
num_lines = self.operand & 0x000F
self.screen.scroll_up(num_lines, self.bitplane)
self.last_op = f"Scroll Up {num_lines:01X}"
else:
try:
self.clear_routines[operation]()
Expand Down
48 changes: 47 additions & 1 deletion chip8/screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ def scroll_down(self, num_lines, bitplane):
for y in range(max_y - num_lines, max_y):
self.draw_pixel(x, y, False, bitplane)

# Start copying pixels from the top to the bottom and shift by 4 pixels
# Start copying pixels from the top to the bottom and shift by n pixels
for x in range(max_x):
for y in range(max_y - num_lines - 1, -1, -1):
current_pixel = self.get_pixel(x, y, bitplane)
Expand All @@ -220,6 +220,52 @@ def scroll_down(self, num_lines, bitplane):
for y in range(num_lines):
self.draw_pixel(x, y, False, bitplane)

def scroll_up(self, num_lines, bitplane):
"""
Scroll the screen up by num_lines.

:param num_lines: the number of lines to scroll up
:param bitplane: the bitplane to scroll
"""
if bitplane == 0:
return

mode_scale = 1 if self.mode == SCREEN_MODE_EXTENDED else 2
actual_lines = num_lines * mode_scale * self.scale_factor
if bitplane == 3:
self.surface.scroll(0, -actual_lines)
self.surface.fill(
self.pixel_colors[0],
(
0,
self.height * mode_scale * self.scale_factor - actual_lines,
self.width * mode_scale * self.scale_factor,
self.height * mode_scale * self.scale_factor
)
)
self.update()
return

max_x = self.get_width()
max_y = self.get_height()

# Blank out any pixels in the top n lines that we will copy to
for x in range(max_x):
for y in range(num_lines):
self.draw_pixel(x, y, False, bitplane)

# Start copying pixels from the top to the bottom and shift up by n pixels
for x in range(max_x):
for y in range(num_lines, max_y):
current_pixel = self.get_pixel(x, y, bitplane)
self.draw_pixel(x, y, False, bitplane)
self.draw_pixel(x, y - num_lines, current_pixel, bitplane)

# Blank out any pixels in the bottom num_lines horizontal lines
for x in range(max_x):
for y in range(max_y - num_lines, max_y):
self.draw_pixel(x, y, False, bitplane)

def scroll_left(self, bitplane):
"""
Scroll the screen left 4 pixels.
Expand Down
5 changes: 5 additions & 0 deletions test/test_chip8cpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,11 @@ def test_scroll_down_called(self):
self.cpu.clear_return()
self.screen.scroll_down.assert_called_with(4, 1)

def test_scroll_up_called(self):
self.cpu.operand = 0x00D4
self.cpu.clear_return()
self.screen.scroll_up.assert_called_with(4, 1)

def test_scroll_right_called(self):
self.cpu.operand = 0x00FB
self.cpu.clear_return()
Expand Down
47 changes: 47 additions & 0 deletions test/test_chip8screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,18 @@ def test_scroll_down_bitplane_0_does_nothing(self):
self.assertFalse(self.screen.get_pixel(0, 1, 1))
self.assertFalse(self.screen.get_pixel(0, 1, 2))

def test_scroll_up_bitplane_0_does_nothing(self):
self.screen.init_display()
self.screen.draw_pixel(0, 1, 1, 1)
self.screen.draw_pixel(0, 1, 1, 2)
self.assertTrue(self.screen.get_pixel(0, 1, 1))
self.assertTrue(self.screen.get_pixel(0, 1, 2))
self.screen.scroll_up(1, 0)
self.assertFalse(self.screen.get_pixel(0, 0, 1))
self.assertFalse(self.screen.get_pixel(0, 0, 2))
self.assertTrue(self.screen.get_pixel(0, 1, 1))
self.assertTrue(self.screen.get_pixel(0, 1, 2))

def test_scroll_down_bitplane_1(self):
self.screen.init_display()
self.screen.draw_pixel(0, 0, 1, 1)
Expand All @@ -134,6 +146,17 @@ def test_scroll_down_bitplane_1(self):
self.assertTrue(self.screen.get_pixel(0, 1, 1))
self.assertFalse(self.screen.get_pixel(0, 1, 2))

def test_scroll_up_bitplane_1(self):
self.screen.init_display()
self.screen.draw_pixel(0, 1, 1, 1)
self.assertTrue(self.screen.get_pixel(0, 1, 1))
self.assertFalse(self.screen.get_pixel(0, 1, 2))
self.screen.scroll_up(1, 1)
self.assertTrue(self.screen.get_pixel(0, 0, 1))
self.assertFalse(self.screen.get_pixel(0, 0, 2))
self.assertFalse(self.screen.get_pixel(0, 1, 1))
self.assertFalse(self.screen.get_pixel(0, 1, 2))

def test_scroll_down_bitplane_1_both_pixels_active(self):
self.screen.init_display()
self.screen.draw_pixel(0, 0, 1, 1)
Expand All @@ -146,6 +169,18 @@ def test_scroll_down_bitplane_1_both_pixels_active(self):
self.assertTrue(self.screen.get_pixel(0, 1, 1))
self.assertFalse(self.screen.get_pixel(0, 1, 2))

def test_scroll_up_bitplane_1_both_pixels_active(self):
self.screen.init_display()
self.screen.draw_pixel(0, 1, 1, 1)
self.screen.draw_pixel(0, 1, 1, 2)
self.assertTrue(self.screen.get_pixel(0, 1, 1))
self.assertTrue(self.screen.get_pixel(0, 1, 2))
self.screen.scroll_up(1, 1)
self.assertTrue(self.screen.get_pixel(0, 0, 1))
self.assertFalse(self.screen.get_pixel(0, 0, 2))
self.assertFalse(self.screen.get_pixel(0, 1, 1))
self.assertTrue(self.screen.get_pixel(0, 1, 2))

def test_scroll_down_bitplane_3_both_pixels_active(self):
self.screen.init_display()
self.screen.draw_pixel(0, 0, 1, 1)
Expand All @@ -158,6 +193,18 @@ def test_scroll_down_bitplane_3_both_pixels_active(self):
self.assertTrue(self.screen.get_pixel(0, 1, 1))
self.assertTrue(self.screen.get_pixel(0, 1, 2))

def test_scroll_up_bitplane_3_both_pixels_active(self):
self.screen.init_display()
self.screen.draw_pixel(0, 1, 1, 1)
self.screen.draw_pixel(0, 1, 1, 2)
self.assertTrue(self.screen.get_pixel(0, 1, 1))
self.assertTrue(self.screen.get_pixel(0, 1, 2))
self.screen.scroll_up(1, 3)
self.assertTrue(self.screen.get_pixel(0, 0, 1))
self.assertTrue(self.screen.get_pixel(0, 0, 2))
self.assertFalse(self.screen.get_pixel(0, 1, 1))
self.assertFalse(self.screen.get_pixel(0, 1, 2))

def test_scroll_right_bitplane_0_does_nothing(self):
self.screen.init_display()
self.screen.draw_pixel(0, 0, 1, 1)
Expand Down
Loading