|
30 | 30 |
|
31 | 31 | import argparse
|
32 | 32 | import os
|
| 33 | +import time |
33 | 34 | from typing import Dict, List, Optional, Tuple
|
34 | 35 |
|
35 | 36 | os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = '1'
|
36 | 37 | import pygame
|
37 | 38 | from pygame.constants import KEYDOWN, KMOD_CTRL, KMOD_SHIFT, QUIT
|
38 |
| -from pygame.font import Font |
| 39 | +from pygame.freetype import Font |
39 | 40 | from pygame.rect import Rect
|
40 | 41 | from pygame.surface import Surface
|
41 | 42 |
|
@@ -204,9 +205,13 @@ def __init__(self, disk_images: List[str] = []):
|
204 | 205 | self.esc_sequence: bytes = b''
|
205 | 206 |
|
206 | 207 | pygame.init()
|
207 |
| - pygame.display.set_caption('8080 Emulator') |
208 |
| - self.screen: Surface = pygame.display.set_mode((80 * 10 + 10, 24 * 20 + 10)) |
209 |
| - self.font: Font = pygame.font.Font('ter-u20n.bdf', 20) |
| 208 | + pygame.display.set_caption('CP/M') |
| 209 | + pygame.key.set_repeat(1000, 100) |
| 210 | + |
| 211 | + self.screen: Surface = pygame.display.set_mode( |
| 212 | + (80 * 10 + 2 * self.margin, 24 * 20 + 2 * self.margin)) |
| 213 | + self.font: Font = Font('BmPlus_Rainbow100_re_80.otb', 24) |
| 214 | + self.blink_rate: int = 750 |
210 | 215 |
|
211 | 216 |
|
212 | 217 | def putch(self, ch: int) -> None:
|
@@ -253,20 +258,50 @@ def putch(self, ch: int) -> None:
|
253 | 258 |
|
254 | 259 |
|
255 | 260 | def render_buffer(self) -> List[Tuple[Surface, Rect]]:
|
256 |
| - img = self.font.render('█', False, self.foreground) |
257 |
| - col = self.cursor % 80 |
258 |
| - row = self.cursor // 80 |
259 |
| - rect = img.get_rect() |
260 |
| - rect.topleft = (col * 10 + self.margin, row * 20 + self.margin) |
261 |
| - rect.size = img.get_size() |
262 |
| - blits = [(img, rect)] |
263 |
| - |
264 |
| - for row in range(24): |
265 |
| - img = self.font.render(bytes(self.buffer[80*row:80*row+80]), False, self.foreground) |
266 |
| - rect = img.get_rect() |
| 261 | + cursor_on = (time.time_ns() // 1000000 // self.blink_rate) % 2 == 0 |
| 262 | + curs_col = self.cursor % 80 |
| 263 | + curs_row = self.cursor // 80 |
| 264 | + |
| 265 | + # Render the cursor |
| 266 | + if cursor_on: |
| 267 | + surface, rect = self.font.render(bytes([self.buffer[80*curs_row+curs_col]]), |
| 268 | + fgcolor=self.background, |
| 269 | + bgcolor=self.foreground) |
| 270 | + else: |
| 271 | + surface, rect = self.font.render(bytes([self.buffer[80*curs_row+curs_col]]), |
| 272 | + fgcolor=self.foreground, |
| 273 | + bgcolor=self.background) |
| 274 | + rect.topleft = (curs_col * 10 + self.margin, curs_row * 20 + self.margin) |
| 275 | + rect.size = surface.get_size() |
| 276 | + blits = [(surface, rect)] |
| 277 | + |
| 278 | + # Render rows up to the cursor row |
| 279 | + for row in range(0, curs_row): |
| 280 | + surface, rect = self.font.render(bytes(self.buffer[80*row:80*row+80]), |
| 281 | + fgcolor=self.foreground) |
| 282 | + rect.topleft = (self.margin, row * 20 + self.margin) |
| 283 | + rect.size = surface.get_size() |
| 284 | + blits += [(surface, rect)] |
| 285 | + |
| 286 | + # Render the cursor row, but not the cursor |
| 287 | + surface, rect = self.font.render(bytes(self.buffer[80*curs_row:80*curs_row+curs_col]), |
| 288 | + fgcolor=self.foreground) |
| 289 | + rect.topleft = (self.margin, curs_row * 20 + self.margin) |
| 290 | + rect.size = surface.get_size() |
| 291 | + blits += [(surface, rect)] |
| 292 | + surface, rect = self.font.render(bytes(self.buffer[80*curs_row+curs_col+1:80*curs_row+80]), |
| 293 | + fgcolor=self.foreground) |
| 294 | + rect.topleft = ((curs_col + 1) * 10 + self.margin, curs_row * 20 + self.margin) |
| 295 | + rect.size = surface.get_size() |
| 296 | + blits += [(surface, rect)] |
| 297 | + |
| 298 | + # Render rows after the cursor row |
| 299 | + for row in range(curs_row+1, 24): |
| 300 | + surface, rect = self.font.render(bytes(self.buffer[80*row:80*row+80]), |
| 301 | + fgcolor=self.foreground) |
267 | 302 | rect.topleft = (self.margin, row * 20 + self.margin)
|
268 |
| - rect.size = img.get_size() |
269 |
| - blits += [(img, rect)] |
| 303 | + rect.size = surface.get_size() |
| 304 | + blits += [(surface, rect)] |
270 | 305 | return blits
|
271 | 306 |
|
272 | 307 |
|
@@ -296,7 +331,8 @@ def run(self) -> None:
|
296 | 331 | if 97 <= key <= 122 and event.mod & KMOD_SHIFT: # A-Z
|
297 | 332 | key -= 32
|
298 | 333 | elif event.mod & KMOD_SHIFT: # Other
|
299 |
| - key = self.shift_keymap[key] |
| 334 | + if key in self.shift_keymap.keys(): |
| 335 | + key = self.shift_keymap[key] |
300 | 336 | elif 97 <= key <= 122 and event.mod & KMOD_CTRL: # ^A - ^Z
|
301 | 337 | key -= 96
|
302 | 338 | vm.io.input_buffer += bytes([key])
|
|
0 commit comments