gigatron/rom/Apps/Apple-1/Apple-1_v1.gcl
2025-01-28 19:17:01 +03:00

681 lines
34 KiB
Plaintext

{-----------------------------------------------------------------------+
| |
| Apple-1 mockup |
| For testing original WozMon code on v6502 |
| |
+-----------------------------------------------------------------------}
gcl0x
{
Issues:
XXX Shift screen memory 96 pixels right
XXX NMI/IRQ/RESET to wozmon (through vector) without going through main menu
XXX We can win memory by sharing all black pixel lines in one page
But drawing characters then touches the top line
- Option 1: VDRawBits7
- Option 2: Always hide top line
- Option 3: New draw transparent plot function, clear with SetBytes
- Option 4: Vary which page is the black line, will be the bottom line
-> doesn't work at memory wrap-around
- Option 5: New videoTable-aware (character) plot function
- Option 6: use Sprite functions for plotting chars
Possible memory map with compressed video memory:
+--------------------------+
|30-7F,81-FF FREE ZP+STACK!|
|0100-01F9 VIDEO+SYSTEM |
|0200-0FFF FREE RAM | 1000-5FFF -> 80 scanlines
|E000-EFFF FREE RAM | F000-FBFF -> 12 scanlines --> total 13*7+1
|FC00-FD00 FREE RAM |
|FE00 KBD/DSP MOCKUP| Add entry points at D010-D013 = 5010-5013
|FF00 APPLE1 ROM |
| |
|C100R LOADER MENU |
|E000R BASIC COLD START|
|E2B3R BASIC WARM START|
+--------------------------+
XXX Emulate ACI Apple Cassete Interface? C100R --> 4100 = RAM (still ok)
XXX D010 60 KBD RTS <-- Or store keyboard value here
D011 80 KBDCR BRA $D037 NOK: (JMP $6024 = $E024)
D012 24 DSP BIT $60
D013 60 DSPCR RTS
D014 _DSP:
D037 _KBDCR:
https://www.sbprojects.net/projects/apple1/a1basic.php
Zero page usage:
$30-$31 Pos
$32-$33 PrintChar
$34-$3b WozMon variables
}
_i=$3c {2 bytes}
_j=$3e {2 bytes}
_k=$3a {1 bytes, share with wozmon YSAV}
{-----------------------------------------------------------------------+
| ROM type check |
+-----------------------------------------------------------------------}
*=\userCode
\romType, \romTypeValue_ROMv4- {Version check >= ROMv4, see Docs/GT1-files.txt}
[if<0 do _frameCount _vPCH: {https://forum.gigatron.io/viewtopic.php?f=4&t=130}
loop]
{-----------------------------------------------------------------------+
| Initialize |
+-----------------------------------------------------------------------}
{ This code runs once and is then reused as the input buffer for wozmon }
{ Setup video indirection table such that WozMon can be at $7F00/$FF00 }
\videoTable Pos= {First GCL variable at $30, later becomes Pos}
120 {7^127}
[do 127^ {Loop over 7..126 range}
Pos: <Pos++ <Pos++ {Y[y]=7+j and dX[y]=0}
1+ 127^ if<>0loop] {Next in range}
&_PrintChar PrintChar= {Forward reference}
&_Apple1 _vLR= {Prepare transfer to main loop}
&_FirstStart {Start address for 6502 program}
[ret] {Jump to Main (the brackets avoid the automatic vLR patch)}
_FirstStart=* #_LDXIM_ #15 {Clear screen}
_L0=* #_LDAIM_ #$8d
#_BRK_
#_DEX_
#_BNE_ #@_L0
#_BEQ_ #@_MUNCH {Always taken}
{-----------------------------------------------------------------------+
| Preloaded demo program |
+-----------------------------------------------------------------------}
*=$280
_MUNCH=* #_CLC_
#_ADCIM_ #23
#_STAZ_ #$40
#_LDAIM_ #$00
#_STAZ_ #$41
#_LDAIM_ #$10
#_STAZ_ #$42
_L1=* #_LDAIM_ #$07
#_STAZ_ #$43
_L2=* #_EORZ_ #$41
#_TAY_
#_LDAZ_ #$40
#_STAIY_ #$42
#_INCZ_ #$43
#_LDAZ_ #$43
#_CMPIM_ #$7f
#_BNE_ #@_L2
#_LDAZ_ #_serialRaw
#_CMPIM_ #$03
#_BEQ_ #@_L3
#_INCZ_ #$41
#_BPL_ #@_L1
#_LDAZ_ #$40
#_JMP_ ##_MUNCH
_L3=* #_LDXIM_ #66
_L4=* #_LDAAX_ ##_MSG
#_BRK_
#_DEX_
#_BPL_ #@_L4
#_JMP_ ##_RESET
_MSG=*
{ '600 Free\r' }
#$8d #$e5 #$e5 #$f2 #$c6 #$a0 #$a0 #$b0
#$b0 #$b6
{ '400R Disassemble 44.45\r' }
#$8d #$b5 #$b4 #$ae #$b4 #$b4 #$a0 #$e5
#$ec #$e2 #$ed #$e5 #$f3 #$f3 #$e1 #$f3
#$e9 #$c4 #$a0 #$d2 #$b0 #$b0 #$b4
{ '280R Munching6502\r' }
#$8d #$b2 #$b0 #$b5 #$b6 #$e7 #$ee #$e9
#$e8 #$e3 #$ee #$f5 #$cd #$a0 #$d2 #$b0
#$b8 #$b2
{ 'Apple-1 on TTL\r' }
#$8d #$cc #$d4 #$d4 #$a0 #$ee #$ef #$a0
#$b1 #$ad #$e5 #$ec #$f0 #$f0 #$c1
{ '\r\r' }
#$8d #$8d
{
Create message with:
s = 'Message text'
' '.join('#$%02x'%(ord(c)+128) for c in reversed(s))
}
{-----------------------------------------------------------------------+
| Main loop |
+-----------------------------------------------------------------------}
*=$300
_Apple1=*
_vLR= {Reset v6502 PC}
[do
\SYS_Run6502_v4_80 _sysFn=
\k, {ASCII code in A}
80!! {Run 6502 code until BRK}
push {Save v6502 PC}
[if=0 {A=0 reads from keyboard}
[do
\serialRaw, 255^ {Wait for idle keyboard}
if<>0loop]
[do
\frameCount, 15& [if=0 {4 Hz cursor redraw rate}
\frameCount, 48& {Flash at 1 Hz with 75% duty cycle}
[if=0 $a0 else $c0] {Select space or '@'}
PrintChar! Pos=] {Display cursor and move back}
\serialRaw, \k. 128& {Key ready?}
if<>0loop] {Loop until ready}
$a0 PrintChar! Pos= {Overwrite '@' with a space}
\k, $60- [if>=0 $40+ \k.] {Map to upper case, and DEL to rubout}
\k, 10^ [if=0 13 \k.] {Map LF to CR}
else {A<>0 for echo}
\k.
PrintChar!
]
pop {Restore v6502 PC}
loop] {Back to wozmon}
{-----------------------------------------------------------------------+
| Character output with automatic scrolling |
+-----------------------------------------------------------------------}
_PrintChar=*
[
{Minimalistic terminal output, with bit 7 set by WozMon}
%-2= {Park character in stack area}
\SYS_VDrawBits_134 _sysFn= {Prepare SYS calls}
$800 \sysArgs0: {Green on black}
%-2 {Get character back}
$8d^ [if<>0 {Test for CR...}
<Pos, 155- if>0 0] {...or line wrap}
[if=0
{-------------------------------------------------------------------+
| Newline |
+-------------------------------------------------------------------}
{Clear new line first}
$100 <Pos. peek >Pos. Pos {Go to start of next line}
\sysArgs4: {Set screen position}
\sysArgs2. {Set all-zero output pattern}
[do
134!! {SYS call to draw 8 pixels vertically}
<\sysArgs4++ {Step 1 pixel right}
\sysArgs4, 160^ {Test for end of line}
if<>0loop]
{Then scroll up by modifying videoTable}
$01ee _i= {Last entry in video table}
[do
_i, 119- [if<0 127+
else 7+] _i. {Rotate by 8 in 7..126 range}
_i 2- _i= {Move to previous entry in video table}
$fe^ if<>0loop] {Until all done}
]
%-2 $a0- {WozMon sends ASCII with bit 7 set}
[if>=0 {If printable}
{-------------------------------------------------------------------+
| PrintChar |
+-------------------------------------------------------------------}
{ Draw ASCII character (32..127) on screen in 5x8 pixels }
{ and advance cursor position }
50- {Map ASCII code to offset in font table}
[if<0 50+ _i= \font32up {ASCII 32..81}
else _i= \font82up] {ASCII 82..127}
_j= _i 2<< _i+ {Multiply char code by 5}
_j+ _j= {Add to page address to reach bitmap data}
Pos \sysArgs4: {Screen position for character}
%-2= {Remember this position}
6+ Pos= {Advance by 6 pixels}
5 [do _i= {Draw character as 5 vertical bit slices}
_j 0? \sysArgs2. {Get bit slice as byte from ROM table}
134!! {SYS call to draw 8 pixels vertically}
<_j++ <\sysArgs4++ {Advance to next byte}
_i 1- if>0loop] {Looping}
%-2 {Return position for backspace}
]
ret
]
{-----------------------------------------------------------------------+
| Disassembler |
+-----------------------------------------------------------------------}
{
WRITTEN BY STEVE WOZNIAK & ALLEN BAUM
AND PUBLISHED IN DOCTOR DOBBS JOURNAL
SEPT 1976
}
*=$400
_FORMAT=$40
_LENGTH=$41
_LMNEM=$42
_RMNEM=$43
_PCL=$44
_PCH=$45
_COUNT=$46
#_JSR_ ##_DSMBL { [Gigatron] Call disassembler as subroutine }
#_JMP_ ##_GETLINE { [Gigatron] Back to wozmon }
_DSMBL=* #_LDAIM_ #$d {was $13} { COUNT FOR 13 INSTR. DSMBLY }
#_STAZ_ #_COUNT
_DSMBL2=* #_JSR_ ##_INSTDS { DISASSEMBLE AND DISPLAY INSTR. }
#_JSR_ ##_PCADJ
#_STAZ_ #_PCL { UPDATE PCL,H TO NEXT INSTR. }
#_STYZ_ #_PCH
#_DECZ_ #_COUNT { DONE FIRST 19 INSTR?. }
#_BNE_ #@_DSMBL2 { * YES, LOOP. ELSE DSMBL 20TH. }
_INSTDS=* #_JSR_ ##_PRPC { PRINT PCL,H }
#_LDAIX_ #_PCL { GET OPCODE }
#_TAY_
#_LSRA_ { EVEN/ODD TEST }
#_BCC_ #@_IEVEN
#_LSRA_ { * TEST BIT 1 }
#_BCS_ #@_ERR { * XXXXXX11 INSTR. INVALID. }
#_CMPIM_ #$22
#_BEQ_ #@_ERR { * 10001001 INSTR. INVALID. }
#_ANDIM_ #$7 { MASK 3 BITS FOR ADDRESS MODE & }
#_ORAIM_ #$80 { * ADD INDEXING OFFSET. }
_IEVEN=* #_LSRA_ { * LSB INTO CARRY FOR }
#_TAX_ { * LEFT/RIGHT TEST BELOW. }
#_LDAAX_ ##_MODE1 { INDEX INTO ADDRESS MODE TABLE.}
#_BCS_ #@_RTMODE { IF CARRY SET USE LSD FOR }
#_LSRA_ { * PRINT FORMAT INDEX }
#_LSRA_
#_LSRA_ { * IF CARRY CLEAR USE MSD. }
#_LSRA_
_RTMODE=* #_ANDIM_ #$F { MASK FOR 4-BIT INDEX. }
#_BNE_ #@_GETFMT { $0 FOR INVALID OP CODES. }
_ERR=* #_LDYIM_ #$80 { SUBSTITUTE $80 FOR INVALID OP, }
#_LDAIM_ #$0 { SET PRINT FORMAT INDEX TO 0 }
_GETFMT=* #_TAX_
#_LDAAX_ ##_MODE2 { INDEX INTO PRINT FORMAT TABLE. }
#_STAZ_ #_FORMAT { SAVE FOR ADDRESS FIELD FORMAT. }
#_ANDIM_ #$3 { MASK 2-BIT LENGTH. 0=1-BYTE }
#_STAZ_ #_LENGTH { * 1=2-BYTE, 2=3-BYTE. }
#_TYA_ { * OP CODE. }
#_ANDIM_ #$8F { MASK IT FOR 1XXX1010 TEST. }
#_TAX_ { SAVE IT. }
#_TYA_ { * OP CODE TO 'A' AGAIN. }
#_LDYIM_ #$3
#_CPXIM_ #$8A
#_BEQ_ #@_MNNDX3
_MNNDX1=* #_LSRA_
#_BCC_ #@_MNNDX3 { FORM INDEX INTO MNEMONIC TABLE. }
#_LSRA_
_MNNDX2=* #_LSRA_ { * 1XXX1010 -> 00101XXX }
#_ORAIM_ #$20 { * XXXYYY01 -> 00111XXX }
#_DEY_ { * XXXYYY10 -> 00110XXX }
#_BNE_ #@_MNNDX2 { * XXXYY100 -> 00100XXX }
#_INY_ { * XXXXX000 -> 000XXXXX }
_MNNDX3=* #_DEY_
#_BNE_ #@_MNNDX1
#_PHA_ { * SAVE MNEMONIC TABLE INDEX. }
_PROP=* #_LDAIY_ #_PCL
#_JSR_ ##_PRBYTE
#_LDXIM_ #$1
_PROPBL=* #_JSR_ ##_PRBL2
#_CPYZ_ #_LENGTH { PRINT INSTR (1 TO 3 BYTES) }
#_INY_ { IN A 12 CHARACTYER FIELD. }
#_BCC_ #@_PROP
#_LDXIM_ #$3 { CHAR COUNT FOR MNEMONIC PRINT. }
#_CPYIM_ #$3
#_BCC_ #@_PROPBL
#_PLA_ { RECOVER MNEMONIC INDEX. }
#_TAY_
#_LDAAY_ ##_MNEML
#_STAZ_ #_LMNEM { FETCH 3-CHAR MNEMONIC }
#_LDAAY_ ##_MNEMR { * (PACKED IN TWO BYTES) }
#_STAZ_ #_RMNEM
_PRMN1=* #_LDAIM_ #$0
#_LDYIM_ #$5
_PRMN2=* #_ASLZ_ #_RMNEM
#_ROLZ_ #_LMNEM { SHIFT 5 BITS OF CHAR INTO 'A'. }
#_ROLA_ { * (CLEAR CARRY) }
#_DEY_
#_BNE_ #@_PRMN2
#_ADCIM_ #$BF { ADD '?' OFFSET. }
#_JSR_ ##_CHAROUT { OUTPUT A CHAR OR MNEMONIC }
#_DEX_
#_BNE_ #@_PRMN1
#_JSR_ ##_PRBLNK { OUTPUT 3 BLANKS. }
#_LDXIM_ #$6 { COUNT FOR 6 PRINT FORMAT BITS. }
_PRADR1=* #_CPXIM_ #$3
#_BNE_ #@_PRADR3 { IF X=3 THEN PRINT ADDRESS VAL. }
#_LDYZ_ #_LENGTH
#_BEQ_ #@_PRADR3 { NO PRINT IF LENGTH=0. }
_PRADR2=* #_LDAZ_ #_FORMAT
#_CMPIM_ #$E8 { HANDLE REL ADDRESSING MODE }
#_LDAIY_ #_PCL { SPECIAL (PRINT TARGET ADDR) }
#_BCS_ #@_RELADR { * (NOT DISPLACEMENT) }
#_JSR_ ##_PRBYTE { OUTPUT 1- OR 2- BYTE ADDRESS. }
#_DEY_ { MORE SIGNIFICANT BYTE FIRST. }
#_BNE_ #@_PRADR2
_PRADR3=* #_ASLZ_ #_FORMAT { TEST NEXT PRINT FORMAT BIT. }
#_BCC_ #@_PRADR4 { IF 0, DONT PRINT }
#_LDAAX_ ##_CHAR1_MINUS1 { CORRESPONDING CHAR. }
#_JSR_ ##_CHAROUT { OUTPUT 1 OR 2 CHARS. }
#_LDAAX_ ##_CHAR2_MINUS1 { * (IF CHAR FROM CHAR2 IS 0, }
#_BEQ_ #@_PRADR4 { * DON'T FRINT IT) }
#_JSR_ ##_CHAROUT
_PRADR4=* #_DEX_
#_BNE_ #@_PRADR1
#_RTS_ { *RETURN IF DONE 6 FORMAT BITS. }
_RELADR=* #_JSR_ ##_PCADJ3 { PCL,H + DISPL + 1 TO 'A','Y'. }
#_TAX_
#_INX_
#_BNE_ #@_PRNTYX { * +1 TO 'X','Y'. }
#_INY_
_PRNTYX=* #_TYA_
_PRNTAX=* #_JSR_ ##_PRBYTE { PRINT TARGET ADDRESS OF BRANCH }
_PRNTX=* #_TXA_ { AND RETURN }
#_JMP_ ##_PRBYTE
_PRPC=* #_LDAIM_ #$8D
#_JSR_ ##_CHAROUT { OUTPUT CARRIAGE RETURN. }
#_LDAZ_ #_PCH
#_LDXZ_ #_PCL
#_JSR_ ##_PRNTAX { OUTPUT PCL,H }
#_LDAIM_ #$AD
#_JSR_ ##_CHAROUT { OUTPUT '-' }
_PRBLNK=* #_LDXIM_ #$1 { BLANK COUNT [Gigatron] Was: #$3 }
_PRBL2=* #_LDAIM_ #$A0
_PRBL3=* #_JSR_ ##_CHAROUT { OUTPUT A BLANK }
#_DEX_
#_BNE_ #@_PRBL2 { LOOP UNTIL COUNT =0 }
#_RTS_
_PCADJ=* #_LDAZ_ #_LENGTH { 0=1-BYTE, 1=2-BYTE, 2=3-BYTE. }
_PCADJ2=* #_SEC_
_PCADJ3=* #_LDYZ_ #_PCH
#_TAX_ { * TEST DISPL SIGN (FOR REL }
#_BPL_ #@_PCADJ4 { * BRANCH). EXTEND NEG }
#_DEY_ { * BY DECREMENTING PCH. }
_PCADJ4=* #_ADCZ_ #_PCL
*=$500 { [Gigatron] Open next GT1 file segment }
#_BCC_ #@_RTS1 { PCL+LENGTH (OR DISPL) +1 TO A. }
#_INY_ { * CARRY INTO Y (PCH) }
_RTS1=* #_RTS_
_MODE1=* #$40 #$2 #$45 #$3
#$D0 #$8 #$40 #$9
#$30 { XXXXXXZ0 INSTRS.. }
#$22
#$45 { * Z=0, LEFT HALF-BYTE }
#$33 { * Z=1, RIGHT HALF-BYTE }
#$D0 #$8 #$40 #$9
#$40 #$2 #$45 #$33
#$D0 #$8 #$40 #$9
#$40 #$2 #$45 #$B3
#$D0 #$8 #$40 #$9
#$0 #$22 #$44 #$33
#$D0 #$8C #$44 #$0
#$11 #$22 #$44 #$33
#$D0 #$8C #$44 #$9A
#$10 #$22 #$44 #$33
#$D0 #$8 #$40 #$9
#$10 #$22 #$44 #$33
#$D0 #$8 #$40 #$9
#$62
#$13 { YYXXXZ01 INSTRS. }
#$78
#$A9
_MODE2=* #$0 { ERR }
#$21 { IMM }
#$81 { Z-PAG }
#$82 { ABS }
#$0 { IMPL }
#$0 { ACC }
#$59 { (Z-PAG,X) }
#$4D { (Z-PAG),Y }
#$91 { Z-PAG,X }
#$92 { ABS,X }
#$86 { ABS,Y }
#$4A { (ABS) }
#$85 { Z-PAG,Y }
_CHAR1_MINUS1=* #$9D { REL }
_CHAR1=* #$AC { ',' }
#$A9 { ')' }
#$AC { ',' }
#$A3 { '#' }
#$A8 { '(' }
_CHAR2_MINUS1=* #$A4 { '$' }
_CHAR2=* #$D9 { 'Y' }
#$0
#$D8 { 'X' }
#$A4 { '$' }
#$A4 { '$' }
#$0
_MNEML=* #$1C #$8A #$1C #$23 { XXXXX000 INSTRS. }
#$5D #$8B #$1B #$A1
#$9D #$8A #$1D #$23
#$9D #$8B #$1D #$A1
#$0 #$29 #$19 #$AE
#$69 #$A8 #$19 #$23
#$24 #$53 #$1B #$23
#$24 #$53 #$19 #$A1
#$0 #$1A #$5B #$5B { XXXYY100 INSTRS. }
#$A5 #$69 #$24 #$24
#$AE #$AE #$A8 #$AD { 1XXX1010 INSTRS. }
#$29 #$0 #$7C #$0
#$15 #$9C #$6D #$9C { XXXYYY10 INSTRS. }
#$A5 #$69 #$29 #$53
#$84 #$13 #$34 #$11 { XXXYYY01 INSTRS. }
#$A5 #$69 #$23 #$A0
_MNEMR=* #$D8 #$62 #$5A #$48 { XXXXX000 INSTRS }
#$26 #$62 #$94 #$88
#$54 #$44 #$C8 #$54
#$68 #$44 #$E8 #$94
#$0 #$B4 #$8 #$84
#$74 #$B4 #$28 #$6E
#$74 #$F4 #$CC #$4A
#$72 #$F2 #$A4 #$8A
#$0 #$AA #$A2 #$A2 { XXXYY100 INSTRS }
#$74 #$74 #$74 #$72
#$44 #$68 #$B2 #$32 { 1XXX1010 INSTRS. }
#$B2 #$0 #$22 #$26
#$1A #$1A #$26 #$26 { XXXYYY10 INSTRS. }
#$72 #$72 #$88 #$C8
#$C4 #$CA #$26 #$48 { XXXYYY01 INSTRS. }
#$44 #$44 #$A2 #$C8
{-----------------------------------------------------------------------+
| WozMon |
+-----------------------------------------------------------------------}
*=$ff00
{ Original ZP usage is 24.2B, but that's taken by Gigatron }
_XAML=$34 _XAML_MINUS1=$33
_XAMH=$35
_STL=$36 _STL_MINUS1=$35
_STH=$37
_L=$38 _L_MINUS1=$37
_H=$39
_YSAV=$3A
_MODE=$3B
{ Patches with respect to original are marked [Gigatron] }
_IN=$200
_KBD=$D010
_KBDCR=$D011
_DSP=$D012
_DSPCR=$D013
_RESET=* #_CLD_ { Clear decimal arithmetic mode. }
#_CLI_
#_LDYIM_ #$7F { Mask for DSP data direction register. }
#_STY_ ##_DSP
#_LDAIM_ #$A7 { KBD and DSP control register mask. }
#_STA_ ##_KBDCR
#_STA_ ##_DSPCR
_NOTCR=* #_CMPIM_ #$DF { "<-"? }
#_BEQ_ #@_BACKSPACE { Yes. }
#_CMPIM_ #$9B { ESC? }
#_BEQ_ #@_ESCAPE { Yes. }
#_INY_ { Advance text index. }
#_BPL_ #@_NEXTCHAR { Auto ESC if > 127. }
_ESCAPE=* #_LDAIM_ #$DC { "\". }
#_JSR_ ##_ECHO { Output it. }
_GETLINE=* #_LDAIM_ #$8D { CR. }
#_JSR_ ##_ECHO { Output it. }
#_LDYIM_ #$01 { Initiallize text index. }
_BACKSPACE=* #_DEY_ { Back up text index. }
#_BMI_ #@_GETLINE { Beyond start of line, reinitialize. }
_NEXTCHAR=* #_LDAIM_ #$00 { [Gigatron] A=0 to read keyboard. }
#_BRK_ { [Gigatron] Transfer to vCPU for input. }
#_ORAIM_ #$80 { [Gigatron] B7 should be '1'. }
#_BIT_ ##_KBD { [Gigatron] Was: LDA }
#_STAAY_ ##_IN { Add to text buffer. }
#_JSR_ ##_ECHO { Display character. }
#_CMPIM_ #$8D { CR? }
#_BNE_ #@_NOTCR { No. }
#_LDYIM_ #$FF { Reset text index. }
#_LDAIM_ #$00 { For XAM mode. }
#_TAX_ { 0->X. }
_SETSTOR=* #_ASLA_ { Leaves $7B if setting STOR mode. }
_SETMODE=* #_STAZ_ #_MODE { $00 = XAM, $7B= STOR,$AE= BLOK XAM }
_BLSKIP=* #_INY_ { Advance text index. }
_NEXTITEM=* #_LDAAY_ ##_IN { Get character. }
#_CMPIM_ #$8D { CR? }
#_BEQ_ #@_GETLINE { Yes, done this line. }
#_CMPIM_ #$AE { "."? }
#_BCC_ #@_BLSKIP { Skip delimiter. }
#_BEQ_ #@_SETMODE { Yes, BLOCK XAM mode. }
#_CMPIM_ #$BA { ":"? }
#_BEQ_ #@_SETSTOR { Yes, set STOR mode. }
#_CMPIM_ #$D2 { "R"? }
#_BEQ_ #@_RUN { Yes, run user program. }
#_STXZ_ #_L { $00->L. }
#_STXZ_ #_H { and H. }
#_STYZ_ #_YSAV { Save Y for comparison. }
_NEXTHEX=* #_LDAAY_ ##_IN { Get character for hex test. }
#_EORIM_ #$B0 { Map digits to $0-9. }
#_CMPIM_ #$0A { Digit? }
#_BCC_ #@_DIG { Yes. }
#_ADCIM_ #$88 { Map letter "A"-"F" to $FA-FF. }
#_CMPIM_ #$FA { Hex letter? }
#_BCC_ #@_NOTHEX { No, character not hex. }
_DIG=* #_ASLA_ { }
#_ASLA_ { Hex digit to MSD of A. }
#_ASLA_ { }
#_ASLA_ { }
#_LDXIM_ #$04 { Shift count. }
_HEXSHIFT=* #_ASLA_ { Hex digit left, MSB to carry. }
#_ROLZ_ #_L { Rotate into LSD. }
#_ROLZ_ #_H { Rotate into MSD's. }
#_DEX_ { Done 4 shifts? }
#_BNE_ #@_HEXSHIFT { No, loop. }
#_INY_ { Advance text index. }
#_BNE_ #@_NEXTHEX { Always taken. Check next character for hex.}
_NOTHEX=* #_CPYZ_ #_YSAV { Check if L, H empty (no hex digits). }
#_BEQ_ #@_ESCAPE { Yes, generate ESC sequence. }
#_BITZ_ #_MODE { Test MODE byte. }
#_BVC_ #@_NOTSTOR { B6 = 0 for STOR, 1 for XAM and BLOCK XAM}
#_LDAZ_ #_L { LSD's of hex data. }
#_STAIX_ #_STL { Store at current 'store index'. }
#_INCZ_ #_STL { Increment store index. }
#_BNE_ #@_NEXTITEM { Get next item. (no carry). }
#_INCZ_ #_STH { Add carry to 'store index' high order. }
_TONEXTITEM=* #_JMP_ ##_NEXTITEM { Get next command item. }
_RUN=* #_JMI_ ##_XAML { Run at current XAM index. }
_NOTSTOR=* #_BMI_ #@_XAMNEXT { B7 = 0 for XAM, 1 for BLOCK XAM. }
#_LDXIM_ #$02 { Byte count. }
_SETADR=* #_LDAZX_ #_L_MINUS1 { Copy hex data to }
#_STAZX_ #_STL_MINUS1 { 'store index'. }
#_STAZX_ #_XAML_MINUS1 { And to 'XAM index'. }
#_DEX_ { Next of 2 bytes. }
#_BNE_ #@_SETADR { Loop unless X = 0. }
_NXTPRNT=* #_BNE_ #@_PRDATA { NE means no address to print. }
#_LDAIM_ #$8D { CR. }
#_JSR_ ##_ECHO { Output it. }
#_LDAZ_ #_XAMH { 'Examine index' high-order byte. }
#_JSR_ ##_PRBYTE { Output it in hex format. }
#_LDAZ_ #_XAML { Low-order 'examine index' byte. }
#_JSR_ ##_PRBYTE { Output it in hex format. }
#_LDAIM_ #$BA { ":". }
#_JSR_ ##_ECHO { Output it. }
_PRDATA=* #_LDAIM_ #$04 { [Gigatron] 4 pixels wide blank. }
#_JSR_ ##_BLANK { [Gigatron] Output it. }
#_LDAIX_ #_XAML { Get data byte at 'examine index'. }
#_JSR_ ##_PRBYTE { Output it in hex format. }
_XAMNEXT=* #_STXZ_ #_MODE { 0->MODE (XAM mode). }
#_LDAZ_ #_XAML { }
#_CMPZ_ #_L { Compare 'examine index' to hex data. }
#_LDAZ_ #_XAMH { }
#_SBCZ_ #_H { }
#_BCS_ #@_TONEXTITEM { Not less, so no more data to output. }
#_INCZ_ #_XAML { }
#_BNE_ #@_MOD8CHK { Increment 'examine index'. }
#_INCZ_ #_XAMH { }
_MOD8CHK=* #_LDAZ_ #_XAML { Check low-order 'examine index' byte }
#_ANDIM_ #$07 { For MOD 8= 0 }
#_BPL_ #@_NXTPRNT { Always taken. }
_PRBYTE=* #_PHA_ { Save A for LSD. }
#_LSRA_ { }
#_LSRA_ { }
#_LSRA_ { MSD to LSD position. }
#_LSRA_ { }
#_JSR_ ##_PRHEX { Output hex digit. }
#_PLA_ { Restore A. }
_PRHEX=* #_ANDIM_ #$0F { Mask LSD for hex print. }
#_ORAIM_ #$B0 { Add "0". }
#_CMPIM_ #$BA { Digit? }
#_BCC_ #@_ECHO { Yes, output it. }
#_ADCIM_ #$06 { Add offset for letter. }
_CHAROUT=*
_ECHO=* #_PHA_ { [Gigatron] }
#_BRK_ { [Gigatron] Transfer to vCPU for display.}
#_PLA_ { [Gigatron] }
#_RTS_ { [Gigatron] Return. }
_BLANK=* #_CLC_ { [Gigatron] Advance few pixels so BLOCK }
#_ADCZ_ #<Pos { [Gigatron] XAM doesn't wrap around }
#_STAZ_ #<Pos { [Gigatron] the 160 pixel wide screen. }
#_RTS_ { [Gigatron] }
#$00 { (unused) }
{FFFA} ##$0000 { (NMI) }
{FFFC} ##_RESET { (RESET) }
{FFFE} ##$0000 { (IRQ) }
{-----------------------------------------------------------------------+
| |
+-----------------------------------------------------------------------}