First public commit.
This commit is contained in:
parent
2a48f52979
commit
4bac9d83ed
288 changed files with 18417 additions and 1076 deletions
71
lenser/coco/viewer.py
Normal file
71
lenser/coco/viewer.py
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
"""Generates the CoCo cartridge viewer (Motorola 6809 machine code).
|
||||
|
||||
Runs from the Program Pak ROM at $C000 (the CoCo autostarts it). Sets the VDG
|
||||
graphics mode via PIA1 $FF22 and the SAM video registers (PMODE 3 and 4 are both
|
||||
6144-byte SAM mode 6; only the $FF22 byte differs), copies the 6144-byte image
|
||||
from cart ROM down to the video page at $0E00, then holds it.
|
||||
|
||||
display: forever (hold), key (poll the keyboard then reset), seconds (count 60 Hz
|
||||
field-syncs then reset). A Program Pak can't cleanly return to BASIC, so key and
|
||||
seconds reset the machine (which re-displays the picture).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from .mc6809 import Asm
|
||||
|
||||
CART_BASE = 0xC000
|
||||
VIDEO = 0x0E00
|
||||
SCREEN_BYTES = 6144
|
||||
RATE = 60 # NTSC field-syncs per second
|
||||
|
||||
|
||||
def build(data_src: int, vdg: int = 0xF8, display: str = "forever",
|
||||
seconds: int = 0) -> bytes:
|
||||
a = Asm(CART_BASE)
|
||||
a.orcc(0x50) # mask IRQ + FIRQ; we run standalone
|
||||
|
||||
a.lda_imm(vdg)
|
||||
a.sta_ext(0xFF22) # VDG graphics mode (PMODE 3 = $E0/$E8, PMODE 4 = $F8)
|
||||
|
||||
# SAM video mode 6 (V2=1, V1=1, V0=0). SAM regs toggle by address; data ignored.
|
||||
a.sta_ext(0xFFC5) # V2 set
|
||||
a.sta_ext(0xFFC3) # V1 set
|
||||
a.sta_ext(0xFFC0) # V0 clear
|
||||
|
||||
# SAM video offset = 7 ($0E00): F0,F1,F2 set; F3..F6 clear.
|
||||
a.sta_ext(0xFFC7); a.sta_ext(0xFFC9); a.sta_ext(0xFFCB)
|
||||
a.sta_ext(0xFFCC); a.sta_ext(0xFFCE); a.sta_ext(0xFFD0); a.sta_ext(0xFFD2)
|
||||
|
||||
# copy SCREEN_BYTES from cart ROM (data_src) to the video page
|
||||
a.ldx_imm(data_src)
|
||||
a.ldu_imm(VIDEO)
|
||||
a.label("copy")
|
||||
a.lda_postinc("x")
|
||||
a.sta_postinc("u")
|
||||
a.cmpu_imm(VIDEO + SCREEN_BYTES)
|
||||
a.bne("copy")
|
||||
|
||||
# ---- hold the picture ----
|
||||
if display == "key":
|
||||
a.clra()
|
||||
a.sta_ext(0xFF02) # drive all keyboard columns low
|
||||
a.label("kwait")
|
||||
a.lda_ext(0xFF00) # row sense
|
||||
a.ora_imm(0x80) # ignore the joystick-compare bit 7
|
||||
a.cmpa_imm(0xFF)
|
||||
a.beq("kwait") # all rows high -> no key, keep waiting
|
||||
a.jmp_ind(0xFFFE) # reset
|
||||
elif display == "seconds":
|
||||
a.ldd_imm(max(1, min(0xFFFF, int(seconds) * RATE)))
|
||||
a.label("swait")
|
||||
a.lda_ext(0xFF03) # PIA0 CB1 (field-sync) status
|
||||
a.bpl("swait") # bit 7 clear -> no new field yet
|
||||
a.lda_ext(0xFF02) # read PB data to clear the field-sync flag
|
||||
a.subd_imm(1)
|
||||
a.bne("swait")
|
||||
a.jmp_ind(0xFFFE) # reset
|
||||
else: # forever
|
||||
a.label("hang")
|
||||
a.bra("hang")
|
||||
return a.resolve()
|
||||
Loading…
Add table
Add a link
Reference in a new issue