563 lines
27 KiB
Python
563 lines
27 KiB
Python
"""Platform abstraction so the GUI (and anything else) can treat C64 and Atari
|
|
uniformly: which modes/palettes/formats exist, and how to convert/export/run.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import tempfile
|
|
|
|
from . import crt, imageprep, mame
|
|
from .apple.convert import MODES as APPLE_MODES, convert_image as _apple_convert
|
|
from .apple.exporter import export_dsk
|
|
from .atari.convert import MODES as ATARI_MODES, convert_image as _atari_convert
|
|
from .atari.exporter import export_atr, export_car
|
|
from .atari.palette import nearest_hue
|
|
from .bbc.convert import MODES as BBC_MODES, convert_image as _bbc_convert
|
|
from .bbc.exporter import export_ssd
|
|
from .coco.convert import MODES as COCO_MODES, convert_image as _coco_convert
|
|
from .coco.exporter import export_ccc
|
|
from .coleco.convert import MODES as COLECO_MODES, convert_image as _coleco_convert
|
|
from .coleco.exporter import export_col
|
|
from .a2600.convert import MODES as A2600_MODES, convert_image as _a2600_convert
|
|
from .a2600.exporter import export_a26
|
|
from .convert import MODES as C64_MODES, convert_image as _c64_convert
|
|
from .diskimage import FORMATS
|
|
from .exporter import export_cart, export_disk
|
|
from .palette import COLOR_NAMES, get_palette
|
|
from .ti99.convert import MODES as TI99_MODES, convert_image as _ti99_convert
|
|
from .ti99.exporter import export_rpk
|
|
from .intv.convert import MODES as INTV_MODES, convert_image as _intv_convert
|
|
from .intv.exporter import export_int
|
|
from .vic20.convert import MODES as VIC20_MODES, convert_image as _vic20_convert
|
|
from .vic20.exporter import export_a0
|
|
from .spectrum.convert import MODES as SPECTRUM_MODES, convert_image as _spectrum_convert
|
|
from .spectrum.exporter import export_sna
|
|
from .a5200.convert import MODES as A5200_MODES, convert_image as _a5200_convert
|
|
from .a5200.exporter import export_a52
|
|
from .a7800.convert import MODES as A7800_MODES, convert_image as _a7800_convert
|
|
from .a7800.exporter import export_a78
|
|
from .c128.convert import MODES as C128_MODES, convert_image as _c128_convert
|
|
from .c128.exporter import export_d64 as _c128_export_d64
|
|
from .c16.convert import MODES as C16_MODES, convert_image as _c16_convert
|
|
from .c16.exporter import export_prg as _c16_export_prg
|
|
from .plus4.convert import MODES as PLUS4_MODES, convert_image as _plus4_convert
|
|
from .plus4.exporter import export_prg as _plus4_export_prg
|
|
from .cpc.convert import MODES as CPC_MODES, convert_image as _cpc_convert
|
|
from .cpc.exporter import export_sna as _cpc_export_sna
|
|
from .coco3.convert import MODES as COCO3_MODES, convert_image as _coco3_convert
|
|
from .coco3.exporter import export_ccc as _coco3_export_ccc
|
|
from .nes.convert import MODES as NES_MODES, convert_image as _nes_convert
|
|
from .nes.exporter import export_nes as _nes_export_nes
|
|
from .iigs.convert import MODES as IIGS_MODES, convert_image as _iigs_convert
|
|
from .iigs.exporter import export_dsk as _iigs_export_dsk
|
|
from .pet.convert import convert_image as _pet_convert
|
|
from .pet.exporter import export_prg as _pet_export_prg
|
|
from .sms.convert import MODES as SMS_MODES, convert_image as _sms_convert
|
|
from .sms.exporter import export_sms as _sms_export_sms
|
|
from .amiga.convert import MODES as AMIGA_MODES, convert_image as _amiga_convert
|
|
from .amiga.exporter import export_adf as _amiga_export_adf
|
|
from .ansi.convert import MODES as ANSI_MODES, convert_image as _ansi_convert
|
|
from .ansi.exporter import export_ans as _ansi_export_ans
|
|
|
|
# PET/CBM families -> (MAME machine, screen columns). 40-col models share the
|
|
# 80x50 quadrant-block encoder; 80-col models share 160x50.
|
|
PET_CFG = {"pet2001": ("pet2001n", 40), "pet4032": ("pet4032", 40),
|
|
"pet8032": ("pet8032", 80), "superpet": ("cbm8032", 80)}
|
|
# (MAME's `superpet` driver is incomplete; the SuperPET's display is identical to
|
|
# the CBM 8032 it is built on, so the working cbm8032 machine is used.)
|
|
|
|
PLATFORMS = ["c64", "atari", "apple", "ti99", "coco", "bbc", "coleco", "a2600",
|
|
"intv", "vic20", "spectrum", "a5200", "a7800", "c128", "c16",
|
|
"plus4", "cpc", "coco3", "nes", "iigs",
|
|
"pet2001", "pet4032", "pet8032", "superpet", "sms", "amiga", "ansi"]
|
|
# Apple modes needing a //e (auxiliary memory) rather than a II+.
|
|
_APPLE_IIE_MODES = {"dhgr"}
|
|
|
|
|
|
def modes(platform: str) -> list[str]:
|
|
if platform == "c64":
|
|
return ["auto", *C64_MODES]
|
|
if platform == "atari":
|
|
return list(ATARI_MODES)
|
|
if platform == "ti99":
|
|
return list(TI99_MODES)
|
|
if platform == "coco":
|
|
return list(COCO_MODES)
|
|
if platform == "bbc":
|
|
return list(BBC_MODES)
|
|
if platform == "coleco":
|
|
return list(COLECO_MODES)
|
|
if platform == "a2600":
|
|
return list(A2600_MODES)
|
|
if platform == "intv":
|
|
return list(INTV_MODES)
|
|
if platform == "vic20":
|
|
return list(VIC20_MODES)
|
|
if platform == "spectrum":
|
|
return list(SPECTRUM_MODES)
|
|
if platform == "a5200":
|
|
return list(A5200_MODES)
|
|
if platform == "a7800":
|
|
return list(A7800_MODES)
|
|
if platform == "c128":
|
|
return list(C128_MODES)
|
|
if platform == "c16":
|
|
return list(C16_MODES)
|
|
if platform == "plus4":
|
|
return list(PLUS4_MODES)
|
|
if platform == "cpc":
|
|
return list(CPC_MODES)
|
|
if platform == "coco3":
|
|
return list(COCO3_MODES)
|
|
if platform == "nes":
|
|
return list(NES_MODES)
|
|
if platform == "iigs":
|
|
return list(IIGS_MODES)
|
|
if platform in PET_CFG:
|
|
return ["mono"]
|
|
if platform == "sms":
|
|
return list(SMS_MODES)
|
|
if platform == "amiga":
|
|
return list(AMIGA_MODES)
|
|
if platform == "ansi":
|
|
return list(ANSI_MODES)
|
|
return list(APPLE_MODES)
|
|
|
|
|
|
def palettes(platform: str) -> list[str]:
|
|
if platform == "c64":
|
|
return ["colodore", "pepto"]
|
|
if platform == "atari":
|
|
return ["ntsc"]
|
|
if platform == "ti99":
|
|
return ["tms9918"]
|
|
if platform == "coco":
|
|
return ["mc6847"]
|
|
if platform == "bbc":
|
|
return ["bbc"]
|
|
if platform == "coleco":
|
|
return ["tms9918"]
|
|
if platform == "a2600":
|
|
return ["tia"]
|
|
if platform == "intv":
|
|
return ["stic"]
|
|
if platform == "vic20":
|
|
return ["vic"]
|
|
if platform == "spectrum":
|
|
return ["spectrum"]
|
|
if platform == "a5200":
|
|
return ["ntsc"]
|
|
if platform == "a7800":
|
|
return ["ntsc"]
|
|
if platform == "c128":
|
|
return ["vdc"]
|
|
if platform in ("c16", "plus4"):
|
|
return ["ted"]
|
|
if platform == "cpc":
|
|
return ["cpc"]
|
|
if platform == "coco3":
|
|
return ["gime"]
|
|
if platform == "nes":
|
|
return ["nes"]
|
|
if platform == "iigs":
|
|
return ["iigs"]
|
|
if platform in PET_CFG:
|
|
return ["pet"]
|
|
if platform == "sms":
|
|
return ["sms"]
|
|
if platform == "amiga":
|
|
return ["amiga"]
|
|
if platform == "ansi":
|
|
return ["vga"]
|
|
return ["mono"]
|
|
|
|
|
|
def disk_formats(platform: str) -> list[str]:
|
|
if platform == "c64":
|
|
return [*FORMATS.keys(), "crt"] # disks + 16K cartridge
|
|
if platform == "atari":
|
|
return ["atr", "car"] # disk + 16K cartridge
|
|
if platform == "ti99":
|
|
return ["rpk"]
|
|
if platform == "coco":
|
|
return ["ccc"] # Program Pak cartridge
|
|
if platform == "bbc":
|
|
return ["ssd"] # DFS disk
|
|
if platform == "coleco":
|
|
return ["col"] # ColecoVision cartridge (runs on Adam too)
|
|
if platform == "a2600":
|
|
return ["a26"] # Atari 2600 cartridge
|
|
if platform == "intv":
|
|
return ["int"] # Intellivision cartridge (.int/.bin/.rom)
|
|
if platform == "vic20":
|
|
return ["a0"] # VIC-20 autostart cartridge ($A000)
|
|
if platform == "spectrum":
|
|
return ["sna"] # 48K snapshot (also drops a .scr)
|
|
if platform == "a5200":
|
|
return ["a52"] # Atari 5200 cartridge
|
|
if platform == "a7800":
|
|
return ["a78"] # Atari 7800 cartridge
|
|
if platform == "c128":
|
|
return ["d64"] # C128 autobooting disk (VDC 80-col)
|
|
if platform in ("c16", "plus4"):
|
|
return ["prg"] # TED program (quickload / LOAD+RUN)
|
|
if platform == "cpc":
|
|
return ["sna"] # Amstrad CPC snapshot
|
|
if platform == "coco3":
|
|
return ["ccc"] # CoCo 3 cartridge
|
|
if platform == "nes":
|
|
return ["nes"] # iNES cartridge
|
|
if platform == "iigs":
|
|
return ["dsk"] # bootable 5.25" SHR disk
|
|
if platform in PET_CFG:
|
|
return ["prg"] # PET program (quickload / LOAD+RUN)
|
|
if platform == "sms":
|
|
return ["sms"] # Master System cartridge
|
|
if platform == "amiga":
|
|
return ["adf"] # Amiga bootable floppy
|
|
if platform == "ansi":
|
|
return ["ans"] # ANSI/CP437 BBS art (plain text file)
|
|
return ["dsk"]
|
|
|
|
|
|
def _base_color(platform: str, base_name: str):
|
|
if base_name == "grayscale":
|
|
return None
|
|
idx = COLOR_NAMES.index(base_name)
|
|
if platform == "atari":
|
|
return nearest_hue(get_palette("colodore")[idx])
|
|
return idx
|
|
|
|
|
|
def convert(platform, path, mode, palette, dither, intensive, prep_opt, base_name):
|
|
base = _base_color(platform, base_name)
|
|
if platform == "ti99":
|
|
if mode not in TI99_MODES:
|
|
mode = "gm2"
|
|
return _ti99_convert(path, mode=mode, palette_name="tms9918",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
if platform == "apple":
|
|
if mode not in APPLE_MODES:
|
|
mode = "hgr_mono"
|
|
return _apple_convert(path, mode=mode, dither_mode=dither,
|
|
intensive=intensive, prep_opt=prep_opt, base_color=base)
|
|
if platform == "atari":
|
|
if mode not in ATARI_MODES:
|
|
mode = "gr15"
|
|
return _atari_convert(path, mode=mode, palette_name="ntsc",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
if platform == "coco":
|
|
if mode not in COCO_MODES:
|
|
mode = "pmode4"
|
|
return _coco_convert(path, mode=mode, palette_name="mc6847",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
if platform == "bbc":
|
|
if mode not in BBC_MODES:
|
|
mode = "mode2"
|
|
return _bbc_convert(path, mode=mode, palette_name="bbc",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
if platform == "coleco":
|
|
if mode not in COLECO_MODES:
|
|
mode = "gm2"
|
|
return _coleco_convert(path, mode=mode, palette_name="tms9918",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
if platform == "a2600":
|
|
if mode not in A2600_MODES:
|
|
mode = "pf"
|
|
return _a2600_convert(path, mode=mode, palette_name="tia",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
if platform == "intv":
|
|
if mode not in INTV_MODES:
|
|
mode = "stic"
|
|
return _intv_convert(path, mode=mode, palette_name="stic",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
if platform == "vic20":
|
|
if mode not in VIC20_MODES:
|
|
mode = "multicolor"
|
|
return _vic20_convert(path, mode=mode, palette_name="vic",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
if platform == "spectrum":
|
|
if mode not in SPECTRUM_MODES:
|
|
mode = "hires"
|
|
return _spectrum_convert(path, mode=mode, palette_name="spectrum",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
if platform == "a5200":
|
|
if mode not in A5200_MODES:
|
|
mode = "gr15"
|
|
return _a5200_convert(path, mode=mode, palette_name="ntsc",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
if platform == "a7800":
|
|
if mode not in A7800_MODES:
|
|
mode = "c160"
|
|
return _a7800_convert(path, mode=mode, palette_name="ntsc",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
if platform == "c128":
|
|
c128_mode = mode if mode in C128_MODES else "mono"
|
|
return _c128_convert(path, mode=c128_mode, palette_name="vdc",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
if platform == "c16":
|
|
c16_mode = mode if mode in C16_MODES else "hires"
|
|
return _c16_convert(path, mode=c16_mode, palette_name="ted",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
if platform == "plus4":
|
|
p4_mode = mode if mode in PLUS4_MODES else "hires"
|
|
return _plus4_convert(path, mode=p4_mode, palette_name="ted",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
if platform == "cpc":
|
|
cpc_mode = mode if mode in CPC_MODES else "mode0"
|
|
return _cpc_convert(path, mode=cpc_mode, palette_name="cpc",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
if platform == "coco3":
|
|
c3_mode = mode if mode in COCO3_MODES else "gr16"
|
|
return _coco3_convert(path, mode=c3_mode, palette_name="gime",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
if platform == "nes":
|
|
nes_mode = mode if mode in NES_MODES else "bg"
|
|
return _nes_convert(path, mode=nes_mode, palette_name="nes",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
if platform == "iigs":
|
|
gs_mode = mode if mode in IIGS_MODES else "shr"
|
|
return _iigs_convert(path, mode=gs_mode, palette_name="iigs",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
if platform in PET_CFG:
|
|
return _pet_convert(path, cols=PET_CFG[platform][1], dither_mode=dither,
|
|
intensive=intensive, prep_opt=prep_opt, base_color=base)
|
|
if platform == "sms":
|
|
sms_mode = mode if mode in SMS_MODES else "bg"
|
|
return _sms_convert(path, mode=sms_mode, palette_name="sms",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
if platform == "amiga":
|
|
am_mode = mode if mode in AMIGA_MODES else "lowres"
|
|
return _amiga_convert(path, mode=am_mode, palette_name="amiga",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
if platform == "ansi":
|
|
ansi_mode = mode if mode in ANSI_MODES else "80x25"
|
|
return _ansi_convert(path, mode=ansi_mode, palette_name="vga",
|
|
dither_mode=dither, intensive=intensive,
|
|
prep_opt=prep_opt, base_color=base)
|
|
return _c64_convert(path, mode=mode, palette_name=palette, dither_mode=dither,
|
|
intensive=intensive, prep_opt=prep_opt, base_color=base)
|
|
|
|
|
|
def export(platform, conv, path, fmt, source_path, video,
|
|
display="key", seconds=0, layout="unified"):
|
|
if platform == "ti99":
|
|
return export_rpk(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds, video=video)
|
|
if platform == "coco":
|
|
return export_ccc(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds)
|
|
if platform == "bbc":
|
|
return export_ssd(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds, video=video)
|
|
if platform == "coleco":
|
|
return export_col(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds)
|
|
if platform == "a2600":
|
|
return export_a26(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds)
|
|
if platform == "intv":
|
|
return export_int(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds, video=video)
|
|
if platform == "vic20":
|
|
return export_a0(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds, video=video)
|
|
if platform == "spectrum":
|
|
return export_sna(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds, video=video)
|
|
if platform == "a5200":
|
|
return export_a52(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds, video=video)
|
|
if platform == "a7800":
|
|
return export_a78(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds, video=video)
|
|
if platform == "c128":
|
|
return _c128_export_d64(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds, video=video)
|
|
if platform == "c16":
|
|
return _c16_export_prg(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds, video=video)
|
|
if platform == "plus4":
|
|
return _plus4_export_prg(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds, video=video)
|
|
if platform == "cpc":
|
|
return _cpc_export_sna(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds, video=video)
|
|
if platform == "coco3":
|
|
return _coco3_export_ccc(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds, video=video)
|
|
if platform == "nes":
|
|
return _nes_export_nes(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds, video=video)
|
|
if platform == "iigs":
|
|
return _iigs_export_dsk(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds, video=video)
|
|
if platform in PET_CFG:
|
|
return _pet_export_prg(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds, video=video)
|
|
if platform == "sms":
|
|
return _sms_export_sms(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds, video=video)
|
|
if platform == "amiga":
|
|
return _amiga_export_adf(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds, video=video)
|
|
if platform == "ansi":
|
|
return _ansi_export_ans(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds, video=video)
|
|
if platform == "apple":
|
|
return export_dsk(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds)
|
|
if platform == "atari":
|
|
if fmt == "car" or str(path).lower().endswith(".car"):
|
|
return export_car(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds, video=video)
|
|
return export_atr(conv, path, source_path=source_path,
|
|
display=display, seconds=seconds, video=video)
|
|
if fmt == "crt" or str(path).lower().endswith(".crt"):
|
|
return export_cart(conv, path, source_path=source_path, video=video,
|
|
display=display, seconds=seconds)
|
|
return export_disk(conv, path, disk_format=fmt, source_path=source_path,
|
|
video=video, display=display, seconds=seconds, layout=layout)
|
|
|
|
|
|
def has_emulator(platform: str) -> bool:
|
|
if platform == "ansi":
|
|
return False # a text file has nothing to "run"
|
|
return mame.have_mame()
|
|
|
|
|
|
def run_emulator(platform, path, mode, standard):
|
|
"""Launch the generated image under MAME (every platform uses MAME)."""
|
|
pal = standard != "ntsc"
|
|
if platform == "ti99":
|
|
# cartridge auto-listed on the TI menu as item 2.
|
|
return mame.launch("ti99_4a", [("cart", path)], autoboot="2",
|
|
autoboot_delay=5)
|
|
if platform == "apple":
|
|
machine = "apple2ee" if mode in _APPLE_IIE_MODES else "apple2p"
|
|
return mame.launch(machine, [("flop1", path)], throttle=False)
|
|
if platform == "coco":
|
|
# Color Computer 2; the Program Pak autostarts at $C000.
|
|
return mame.launch("coco2b", [("cart", path)])
|
|
if platform == "bbc":
|
|
# BBC Model B; a Lua script types *RUN PIC once DFS has booted.
|
|
return mame.launch("bbcb", [("flop1", path)],
|
|
autoboot_script_text=mame.bbc_autorun_lua())
|
|
if platform == "coleco":
|
|
# ColecoVision; the cartridge autostarts (the same .col runs on the Adam).
|
|
return mame.launch("coleco", [("cart", path)])
|
|
if platform == "a2600":
|
|
# interlace flickers two banks at 60Hz -> needs real-time, not warp.
|
|
return mame.launch("a2600", [("cart", path)], throttle=(mode == "pf_il"))
|
|
if platform == "intv":
|
|
return mame.launch("intv", [("cart", path)])
|
|
if platform == "vic20":
|
|
# The autostart cartridge programs the VIC itself. MAME raises an
|
|
# "imperfect emulation" warning the user dismisses with a key.
|
|
return mame.launch("vic20p" if pal else "vic20", [("cart", path)])
|
|
if platform == "spectrum":
|
|
# The .sna snapshot bakes the picture into screen RAM + an idle loop, so
|
|
# it appears instantly; the ULA holds it with no further CPU work.
|
|
return mame.launch("spectrum", [("snapshot", path)])
|
|
if platform == "a5200":
|
|
# The cartridge programs ANTIC/GTIA directly; the BIOS jumps straight in.
|
|
return mame.launch("a5200", [("cart", path)])
|
|
if platform == "a7800":
|
|
# The cartridge programs MARIA directly; the BIOS validates + jumps in.
|
|
return mame.launch("a7800", [("cart", path)])
|
|
if platform == "c128":
|
|
# Disk holds a viewer that drives the 80-column VDC; RUN"PIC" loads + runs
|
|
# it. The image appears on the VDC (80-col) screen. -nothrottle for the load.
|
|
return mame.launch("c128", [("flop", path)], autoboot='run"pic"\\n',
|
|
autoboot_delay=5, throttle=False)
|
|
if platform == "c16":
|
|
# quickload loads the PRG into RAM; a Lua script SYSes the viewer (MAME's
|
|
# c16 quickload doesn't set BASIC pointers, so RUN won't, but SYS does).
|
|
return mame.launch("c16", [("quik", path)],
|
|
autoboot_script_text=mame.c16_autorun_lua(),
|
|
autoboot_delay=4, throttle=False)
|
|
if platform == "plus4":
|
|
# Same TED + BASIC 3.5 as the C16, so the identical .prg + SYS autorun runs
|
|
# on the Plus/4 (just a different MAME machine, with 64K RAM).
|
|
return mame.launch("plus4", [("quik", path)],
|
|
autoboot_script_text=mame.c16_autorun_lua(),
|
|
autoboot_delay=4, throttle=False)
|
|
if platform == "cpc":
|
|
# The .sna snapshot bakes the screen, palette, mode and an idle CPU, so
|
|
# the picture appears instantly with no loader (like the ZX Spectrum).
|
|
return mame.launch("cpc6128", [("snapshot", path)])
|
|
if platform == "coco3":
|
|
# The cartridge autostarts a 6809 viewer that programs the GIME; a Lua
|
|
# script forces the RGB monitor (MAME defaults to the composite palette).
|
|
return mame.launch("coco3", [("cart", path)],
|
|
autoboot_script_text=mame.coco3_rgb_lua())
|
|
if platform == "nes":
|
|
# The cartridge resets into a 6502 viewer that programs the PPU; MAME
|
|
# shows an "imperfect graphics" warning the user dismisses with a key.
|
|
return mame.launch("nes", [("cart", path)])
|
|
if platform == "iigs":
|
|
# Boots a 5.25" disk (slot 6) into a loader that fills the Super Hi-Res
|
|
# screen ($E1) and turns SHR on. The 32K load takes ~30s; -nothrottle
|
|
# makes it appear as fast as possible.
|
|
return mame.launch("apple2gs", [("flop1", path)], throttle=False)
|
|
if platform in PET_CFG:
|
|
# quickload the .prg; a Lua script SYSes the viewer, which pokes the
|
|
# quadrant-block screen codes into the PET screen RAM at $8000.
|
|
return mame.launch(PET_CFG[platform][0], [("quik", path)],
|
|
autoboot_script_text=mame.pet_autorun_lua(),
|
|
autoboot_delay=3)
|
|
if platform == "sms":
|
|
# The cartridge resets into a Z80 viewer that programs the VDP and
|
|
# uploads tiles/name table/palette, then idles.
|
|
return mame.launch("sms", [("cart", path)])
|
|
if platform == "amiga":
|
|
# Bootable floppy: a 68000 boot block loads the bitplanes into chip RAM
|
|
# and points the Copper at them. MAME shows an "imperfect graphics"
|
|
# warning the user dismisses with a key.
|
|
return mame.launch("a500", [("flop", path)])
|
|
if platform == "atari":
|
|
# a800xl(p): the XL ROMs only raise MAME's soft "imperfect" notice, not the
|
|
# bad-dump notice the plain Atari 800 OS-B ROM triggers. The .atr self-boots.
|
|
machine = "a800xlp" if pal else "a800xl"
|
|
if str(path).lower().endswith(".car"):
|
|
return mame.launch(machine, [("cart", path)], throttle=False)
|
|
return mame.launch(machine, [("flop1", path)], throttle=False)
|
|
# C64: attach the .d64 to the 1541, then LOAD"*",8,1 + RUN. Run unthrottled so
|
|
# the (cycle-accurate, slow) 1541 load finishes fast; keep real-time for the
|
|
# interlace mode whose 50 Hz field-flip must not run faster than the display.
|
|
machine = "c64p" if pal else "c64"
|
|
if str(path).lower().endswith(".crt"):
|
|
# The exported .crt is one 16K CHIP (VICE's format); MAME needs two 8K
|
|
# CHIPs, so re-pack the ROM into a temp .crt just for the preview.
|
|
rom = crt.read_rom(path)
|
|
fd, mpath = tempfile.mkstemp(suffix=".crt", prefix="lenser_mame_")
|
|
os.close(fd)
|
|
crt.write_crt(rom, mpath, split=True)
|
|
return mame.launch(machine, [("cart", mpath)], # cartridge autostarts
|
|
throttle=(mode == "interlace"))
|
|
# Disk: a Lua script types LOAD, waits for the stock-1541 load to finish,
|
|
# then RUN (a single autoboot command loses the RUN during the slow load).
|
|
return mame.launch(machine, [("flop", path)],
|
|
autoboot_script_text=mame.c64_autorun_lua(),
|
|
throttle=(mode == "interlace"))
|