{-----------------------------------------------------------------------+ | | | 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: 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...} 0 0] {...or line wrap} [if=0 {-------------------------------------------------------------------+ | Newline | +-------------------------------------------------------------------} {Clear new line first} $100 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_ #