This repository was archived by the owner on Jan 27, 2026. It is now read-only.
forked from boriel-basic/zxbasic
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathscrview.py
More file actions
executable file
·124 lines (88 loc) · 2.64 KB
/
scrview.py
File metadata and controls
executable file
·124 lines (88 loc) · 2.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
from typing import List, Tuple
import pygame
import src.arch.z80.optimizer.main
WIDTH = 256 # ZX Spectrum screen width in pixels
HEIGHT = 192 # ZX Spectrum screen height in pixels
SCALE = 4 # Scale
# Colors
BLACK = 0
BLUE = 1
RED = 2
MAGENTA = 3
GREEN = 4
CYAN = 5
YELLOW = 6
WHITE = 7
BRIGHT_OFFSET = 20
SCREEN_AREA_SIZE = 6144
# PALETTE[<color>] will return the expected color. Add 0x28 to increase bright
PALETTE = [
(0, 0, 0),
(0, 0, 0xD7),
(0xD7, 0, 0),
(0xD7, 0, 0xD7),
(0, 0xD7, 0),
(0, 0xD7, 0xD7),
(0xD7, 0xD7, 0),
(0xD7, 0xD7, 0xD7),
]
TABLE = None # Table of bytes to tuple of binaries
def to_bin(x: int):
result = []
for i in range(8):
result.insert(0, x & 1)
x >>= 1
return result
def get_attr(data: List[int], offset) -> int:
"""For a given offset in the drawing region, return the attribute.
This is a bit tricky for the speccy as the screen memory is not linear
"""
k = (offset >> 3) & 0x300
r = offset & 0xFF
return data[SCREEN_AREA_SIZE + k + r]
def get_xy_coord(offset: int) -> Tuple[int, int]:
"""Given an offset, return the x, y coordinate
of that byte in the display"""
x = (offset & 0x1F) << 3 # mod 32
y0 = (offset >> 5) & 0xC0 # offset / 2048
y1 = (offset >> 8) & 0x07 # offset / 256
y2 = (offset >> 2) & 0x38 # offset / 8
y = y0 + y1 + y2
return x * SCALE, y * SCALE
def plot_byte(screen, data: List[int], offset: int):
"""Draws a pixel at the given X, Y coordinate"""
global TABLE
# FIXME
byte_ = TABLE[data[offset]] # type: ignore[index]
attr = get_attr(data, offset)
ink_ = attr & 0x7
paper_ = (attr >> 3) & 0x7
bright = (attr >> 6) & 0x1
paper = tuple(x + bright for x in PALETTE[paper_])
ink = tuple(x + bright for x in PALETTE[ink_])
palette = [paper, ink]
x0, y0 = get_xy_coord(offset)
for x, bit_ in enumerate(byte_):
screen.fill(palette[bit_], pygame.Rect(x0 + x * SCALE, y0, SCALE, SCALE))
def paint(data: List[int]):
src.arch.z80.optimizer.main.init()
screen = pygame.display.set_mode([WIDTH * SCALE, HEIGHT * SCALE])
for i in range(SCREEN_AREA_SIZE):
plot_byte(screen, data, i)
pygame.display.flip()
# Wait for quit
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
if __name__ == "__main__":
# initialize Table
TABLE = [to_bin(x) for x in range(256)]
with open(sys.argv[1], "rb") as f:
data = f.read()
paint(data)