Palette fix for the X68000
This commit is contained in:
parent
74bc0eca7a
commit
63e76f02e6
2 changed files with 82 additions and 1 deletions
|
|
@ -84,6 +84,22 @@
|
|||
#define X68K_GFX_PALETTE ((volatile uint16_t *)0xE82000L)
|
||||
#define X68K_PALETTE_ENTRIES (SURFACE_PALETTE_COUNT * SURFACE_COLORS_PER_PALETTE)
|
||||
|
||||
// Video Controller register 2 ($E82600) low byte = per-plane display enable (MAME x68k_v.cpp): bits 0-3
|
||||
// graphic layers, bit 4 graphic, bit 5 (0x20) TEXT plane, bit 6 sprite. _iocs_crtmod leaves the text
|
||||
// plane ON, so Human68k's desktop (Drv0-3, the kana/romaji status column) bleeds through the graphics;
|
||||
// clearing bit 5 hides it while keeping the graphic layers we draw into.
|
||||
#define X68K_VIDCTRL2 ((volatile uint16_t *)0xE82600L)
|
||||
#define X68K_VIDCTRL2_TEXT 0x0020u
|
||||
|
||||
// Video Controller register 0 ($E82400) low 2 bits select the graphic colour depth (MAME x68k_v.cpp
|
||||
// switch(reg[0] & 3)): 0 = 16-colour, 1 = 256-colour palette-indexed, 3 = 65536-colour DIRECT.
|
||||
// _iocs_crtmod(13) sets the 512x512 CRTC but leaves this at 3 (direct), whereas this port draws 8-bit
|
||||
// PALETTE INDICES into GVRAM and uploads a 256-entry palette at $E82000 -- so the mode MUST be forced to
|
||||
// 256-colour or every index is interpreted as a near-black direct colour (the "invisible/dim" bug).
|
||||
#define X68K_VIDCTRL0 ((volatile uint16_t *)0xE82400L)
|
||||
#define X68K_VIDCTRL0_DEPTH 0x0003u
|
||||
#define X68K_VIDCTRL0_256 0x0001u
|
||||
|
||||
|
||||
// ----- Millisecond clock -----------------------------------------------------
|
||||
//
|
||||
|
|
@ -161,6 +177,15 @@ bool jlpInit(const jlConfigT *config) {
|
|||
gPrevCrtMode = _iocs_crtmod(-1); // -1 queries without changing
|
||||
_iocs_crtmod(X68K_CRTMOD_512_256);
|
||||
_iocs_g_clr_on(); // clear graphics + enable the plane
|
||||
// crtmod 13 leaves the video controller in 65536-colour DIRECT mode (reg[0] & 3 == 3). This port
|
||||
// draws 8-bit palette indices, so force 256-colour palette-indexed mode or every colour renders
|
||||
// near-black. Root-caused + proven live on MAME (reg0 0x0003 -> 0x0001 turned a black frame into a
|
||||
// correct red/yellow/blue test pattern).
|
||||
X68K_VIDCTRL0[0] = (uint16_t)((X68K_VIDCTRL0[0] & (uint16_t)~X68K_VIDCTRL0_DEPTH) | X68K_VIDCTRL0_256);
|
||||
// jlpPresent draws into the GRAPHIC plane (GVRAM $C00000), NOT the text plane -- so Human68k's text
|
||||
// plane (the Drv0-3 + kana/romaji desktop that _iocs_crtmod leaves on) bleeds over our frame. A
|
||||
// reg[2] &= ~0x20 write to hide it did NOT take on MAME (the desktop stayed visible), so that cosmetic
|
||||
// bleed is left as a follow-up; it does not affect the graphic layers we draw into.
|
||||
// NOTE: installing vdispHandler via _iocs_vdispst HANGS the machine --
|
||||
// tested, no serial output at all, so it wedges before main() gets going.
|
||||
// IOCS does NOT wrap the handler: _VDISPST writes the pointer straight into
|
||||
|
|
|
|||
|
|
@ -200,6 +200,57 @@ class Xdf:
|
|||
struct.pack_into("<I", entry, 28, len(payload))
|
||||
self.data[slot:slot + DIR_ENTRY_SIZE] = entry
|
||||
|
||||
def _dir_entry(self, name11, attr, cluster, size):
|
||||
entry = bytearray(DIR_ENTRY_SIZE)
|
||||
entry[0:11] = name11
|
||||
entry[11] = attr
|
||||
struct.pack_into("<H", entry, 22, (12 << 11)) # 12:00:00
|
||||
struct.pack_into("<H", entry, 24, ((2026 - 1980) << 9) | (1 << 5) | 1) # 2026-01-01
|
||||
struct.pack_into("<H", entry, 26, cluster)
|
||||
struct.pack_into("<I", entry, 28, size)
|
||||
return entry
|
||||
|
||||
def add_file_in_subdir(self, dirname, name, payload):
|
||||
# Create a one-cluster subdirectory in root (with . and .. entries) and write `name` into it, so a
|
||||
# guest that reads e.g. SAVES/RN.CFG finds it. Fresh-template semantics: the subdir must not exist
|
||||
# yet (the callers copy a clean image per run). Human68k FAT12 is otherwise ordinary FAT12.
|
||||
dstem = dirname.upper()
|
||||
if len(dstem) > 8:
|
||||
raise ValueError(f"subdir '{dirname}' does not fit 8.3")
|
||||
cb = self.cluster_bytes
|
||||
need = max(1, (len(payload) + cb - 1) // cb)
|
||||
free = self.free_clusters()
|
||||
if len(free) < need + 1:
|
||||
raise OSError(f"{self.path}: need {need + 1} clusters, {len(free)} free")
|
||||
dir_cluster = free[0]
|
||||
data_chain = free[1:1 + need]
|
||||
# File data clusters.
|
||||
for idx, cluster in enumerate(data_chain):
|
||||
off = self.cluster_offset(cluster)
|
||||
chunk = payload[idx * cb:(idx + 1) * cb]
|
||||
self.data[off:off + len(chunk)] = chunk
|
||||
if len(chunk) < cb:
|
||||
self.data[off + len(chunk):off + cb] = bytes(cb - len(chunk))
|
||||
self.fat_set(cluster, 0xFFF if idx == need - 1 else data_chain[idx + 1])
|
||||
# The subdirectory's own cluster: '.', '..', then the file entry, rest free.
|
||||
doff = self.cluster_offset(dir_cluster)
|
||||
self.data[doff:doff + cb] = bytes(cb)
|
||||
self.data[doff:doff + 32] = self._dir_entry(b". ", ATTR_DIR, dir_cluster, 0)
|
||||
self.data[doff + 32:doff + 64] = self._dir_entry(b".. ", ATTR_DIR, 0, 0)
|
||||
self.data[doff + 64:doff + 96] = self._dir_entry(
|
||||
self.encode_name(name), ATTR_ARCHIVE, data_chain[0], len(payload))
|
||||
self.fat_set(dir_cluster, 0xFFF)
|
||||
# Root entry pointing at the subdirectory.
|
||||
slot = None
|
||||
for _, off, e in self._entries():
|
||||
if e[0] in (FREE_MARKER, DELETED_MARKER):
|
||||
slot = off
|
||||
break
|
||||
if slot is None:
|
||||
raise OSError(f"{self.path}: root directory full")
|
||||
self.data[slot:slot + DIR_ENTRY_SIZE] = self._dir_entry(
|
||||
dstem.ljust(8).encode("ascii") + b" ", ATTR_DIR, dir_cluster, 0)
|
||||
|
||||
def flush(self):
|
||||
if not self.writable:
|
||||
raise PermissionError("opened read-only")
|
||||
|
|
@ -235,7 +286,12 @@ def main(argv):
|
|||
name = argv[4] if len(argv) > 4 else os.path.basename(host)
|
||||
img = Xdf(image, writable=True)
|
||||
with open(host, "rb") as fp:
|
||||
img.add_file(name, fp.read())
|
||||
payload = fp.read()
|
||||
if "/" in name: # SAVES/RN.CFG -> a one-cluster subdirectory + the file
|
||||
sub, _, leaf = name.partition("/")
|
||||
img.add_file_in_subdir(sub, leaf, payload)
|
||||
else:
|
||||
img.add_file(name, payload)
|
||||
img.flush()
|
||||
print(f"added {name} ({os.path.getsize(host)} bytes) to {image}")
|
||||
return 0
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue