Working Python version for Commodore.

This commit is contained in:
The Dust Council 2026-06-14 17:43:12 -07:00
commit 2a48f52979
51 changed files with 3095 additions and 0 deletions

64
c64view/convert/hires.py Normal file
View file

@ -0,0 +1,64 @@
"""Hires bitmap mode: 320x200, two colours per 8x8 cell.
Data file layout (PRG, load $2000), matched to viewer/hires.s:
$2000 bitmap 8000 bytes (VIC reads here directly)
$3F40 screen RAM 1000 bytes (viewer copies to $0400)
"""
from __future__ import annotations
import numpy as np
from .. import dither, palette as pal
from . import base
WIDTH, HEIGHT = 320, 200
CELL_W, CELL_H = 8, 8
PIXEL_ASPECT = 1.0
DATA_LOAD = 0x2000
def convert(img_rgb: np.ndarray, palette_name="colodore",
dither_mode="bayer", intensive=False) -> base.Conversion:
plab = pal.palette_lab(palette_name)
img_lab = pal.srgb_to_lab(img_rgb)
cells, rows, cols = base.cells_lab(img_lab, CELL_W, CELL_H)
dist = base.cell_distance(cells, plab)
sets, _ = base.select_cell_sets(dist, range(16), n_free=2)
allowed = base.per_pixel_allowed(sets, rows, cols, CELL_W, CELL_H, HEIGHT, WIDTH)
index_image = dither.quantize(img_lab, allowed, plab, dither_mode).astype(np.uint8)
bitmap, screen = _encode(index_image, sets, rows, cols)
payload = bytes(bitmap) + bytes(screen)
conv = base.Conversion(
mode="hires", width=WIDTH, height=HEIGHT, pixel_aspect=PIXEL_ASPECT,
index_image=index_image, data=payload, viewer="hires",
error=base.mean_error(index_image, img_lab, plab),
meta={"palette": palette_name, "dither": dither_mode},
)
# Standard OCP Art Studio hires file (load $2000): bitmap, screen, border.
conv.extra_files = [("picture.art", base.prg(0x2000, payload + b"\x00"))]
return conv
def _encode(index_image, sets, rows, cols):
"""Build the 8000-byte bitmap and 1000-byte screen RAM."""
bitmap = np.zeros(8000, dtype=np.uint8)
screen = np.zeros(1000, dtype=np.uint8)
for cr in range(rows):
for cc in range(cols):
ci = cr * cols + cc
bg_col, fg_col = int(sets[ci, 0]), int(sets[ci, 1])
screen[ci] = ((fg_col & 0x0F) << 4) | (bg_col & 0x0F)
base_addr = cr * 320 + cc * 8
block = index_image[cr * 8:cr * 8 + 8, cc * 8:cc * 8 + 8]
for r in range(8):
row = block[r]
byte = 0
for x in range(8):
byte = (byte << 1) | (1 if row[x] == fg_col else 0)
bitmap[base_addr + r] = byte
return bitmap, screen