A2QR/QR.6502

909 lines
23 KiB
Plaintext

DSK QRCODE
**************************************************
* To Do:
* Switch from alphanumeric to byte mode, based
* on message length, or content
*
**************************************************
* Variables
**************************************************
LOBYTE EQU $00
HIBYTE EQU $01
BITCOUNTER EQU $02
BYTECOUNTER EQU $03
MESSAGELENGTH EQU $04
ROW EQU $05
COLUMN EQU $06
TEMP EQU $07
MODE EQU $08
MESSAGE EQU $200 ; string input from basic program
STORAGE EQU $3000 ; PUT THE WORKING BYTES HERE
MPINTS EQU $3100 ; QR MESSAGE BYTES
MPEXP EQU $3180
SCRATCH EQU $3200
XORRESULT EQU $3280
**************************************************
* Apple Standard Memory Locations
**************************************************
CLRLORES EQU $F832
LORES EQU $C050
TXTSET EQU $C051
MIXCLR EQU $C052
MIXSET EQU $C053
TXTPAGE1 EQU $C054
TXTPAGE2 EQU $C055
KEY EQU $C000
C80STOREOF EQU $C000
C80STOREON EQU $C001
STROBE EQU $C010
SPEAKER EQU $C030
VBL EQU $C02E
RDVBLBAR EQU $C019 ;not VBL (VBL signal low
WAIT EQU $FCA8
RAMWRTAUX EQU $C005
RAMWRTMAIN EQU $C004
SETAN3 EQU $C05E ;Set annunciator-3 output to 0
SET80VID EQU $C00D ;enable 80-column display mode (WR-only)
CLR80VID EQU $C00C
HOME EQU $FC58 ; clear the text screen
CH EQU $24 ; cursor Horiz
CV EQU $25 ; cursor Vert
VTAB EQU $FC22 ; Sets the cursor vertical position (from CV)
COUT EQU $FDED ; Calls the output routine whose address is stored in CSW,
; normally COUTI
STROUT EQU $DB3A ;Y=String ptr high, A=String ptr low
ALTTEXT EQU $C055
ALTTEXTOFF EQU $C054
RDPAGE2 EQU $C01C ; high bit set if on page2
ROMINIT EQU $FB2F
ROMSETKBD EQU $FE89
ROMSETVID EQU $FE93
SLOT3STATUS EQU $C017 ; bit 7 only
MACHINEID EQU $FBB3
80STOREOFF EQU $C000
80STOREON EQU $C001
80STORE EQU $C018 ; R7
80COLOFF EQU $C00C
80COLON EQU $C00D
80COL EQU $C01F ; R7
TEXTOFF EQU $C050
TEXTON EQU $C051
TEXT EQU $C01A ; R7
MIXEDOFF EQU $C052
MIXEDON EQU $C053
MIXED EQU $C01B ; R7
PAGE2OFF EQU $C054 ; MAIN
PAGE2ON EQU $C055 ; AUX
PAGE2 EQU $C01C ; R7
HIRESOFF EQU $C056
HIRESON EQU $C057
HIRES EQU $C01D ; R7
RAMRDOFF EQU $C002 ; MAIN
RAMRDON EQU $C003 ; AUX
RAMRD EQU $C013 ; R7
RAMWRTOFF EQU $C004 ; MAIN
RAMWRTON EQU $C005 ; AUX
RAMWR EQU $C014 ; R7
**************************************************
* Let's get this party started
**************************************************
ORG $2000 ; PROGRAM DATA STARTS AT $2000
JMP CHECKMESSAGE ; CHECKS CONTENT OF ALPHANUMERIC MESSAGE
SETUP JSR ROMINIT ; GR/HGR off, Text page 1
STA LORES
STA HIRESOFF
STA MIXCLR
JSR Has128K ; do we have DLR?
BCC SETUPDONE
STA SET80VID ; double low-res mode
STA SETAN3 ; double low-res mode
STA 80STOREON
STA PAGE2OFF ; write to MAIN mem, display MAIN DLR page
SETUPDONE JSR CLEARSCREEN ; BLANK SCREEN
**************************************************
* TO DO: Analyze message bytes. Max length of 78 characters
* for byte mode, 114 for alphanumeric mode.
* If >78 then check for non-alphanumeric characters.
**************************************************
; LDA #$40 ; MODE BYTE - #$20 FOR ALPHANUMERIC, #$40 FOR BYTE
; STA MODE
LDA MODE
CMP #$40
BEQ BYTEMODE
LDY #$FF
CONVERT44 ; FOR EACH CHARACTER OF THE MESSAGE, CONVERT TO ALPHANUMERIC 0-44
INY
LDX MESSAGE,Y
BEQ CONVERT11
LDA ALPHANUM,X
STA MESSAGE,Y
JMP CONVERT44
* break message into character pairs
* convert character pairs into numbers
CONVERT11 STY MESSAGELENGTH
LDY #$00
GETMESSAGE LDA MESSAGE,Y ; 0
STA $FC
JSR MULT45 ; RESULT IN FE,FD
CLC
LDA MESSAGE+1,Y
ADC $FD
STA STORAGE+1,Y ; LO BYTE
LDA $FE
ADC #0 ; RESULT IN FE,FD
STA STORAGE,Y ; HI BYTE
INY ; 1
INY ; 2
CPY MESSAGELENGTH
BCC GETMESSAGE
BEQ BUILDQR
* overrun, means last character is odd one out:
*** If you are encoding an odd number of characters, take the numeric representation
*** of the final character and convert it into a 6-bit binary string.
DEY ; Y=MESSAGELENGTH
DEY
LDA MESSAGE,Y ; LAST ACTUAL CHAR OF MESSAGE
TAX
LSR
LSR
LSR
AND #$07
STA STORAGE,Y ; HI 3 BITS
TXA
ASL
ASL
ASL
ASL
ASL
AND #$E0
STA STORAGE+1,Y ; LO 3 BITS
JMP BUILDQR
**************************************************
* Byte mode = ROR each byte in message 4x, append to mode/length bits.
**************************************************
BYTEMODE LDY #$FF
FINDLENGTH INY
LDX MESSAGE,Y
BNE FINDLENGTH
FOUNDLENGTH STY MESSAGELENGTH
LDA MESSAGE-1,Y ; LAST BYTE OF MESSAGE
ASL ; LO 4 BITS
ASL
ASL
ASL
STA STORAGE,Y ; 4 BITS AT END OF CONVERTED MESSAGE
COPYMSG LDX #$0 ; COPY THE MESSAGE TO STORAGE
COPYBYTE LDA MESSAGE,X
STA STORAGE,X
INX
CPX MESSAGELENGTH
BNE COPYBYTE
LDY #$04
RORMSG LDX #$0
CLC
RORBYTE ROR STORAGE,X
INX
TXA ; DON'T USE CPX, PRESERVES CARRY
EOR MESSAGELENGTH
BNE RORBYTE
DEY
BNE RORMSG
BUILDQR
**************************************************
* pad with mode/char count
* alphanumeric mode = 0010
* 0 0010 0000 9 bits character count (EG #$20)
* 0010 0001 0000 0
* Byte mode = 0100 & 8 bits CHARACTER COUNT
**************************************************
LDA MESSAGELENGTH ; NNNNXXXX
LDX MODE
CPX #$40
BEQ LSR4X
LSR5X LSR ; 5X FOR ALPHANUM MODE, 4X FOR BYTE MODE
LSR4X LSR
LSR
LSR ; -> 5X
LSR ; 0 0000 NNN
ORA MODE ; 0010 0NNN OR 0100 NNNN
LDY #$0
STA MPINTS,Y ; FIRST MESSAGE BYTE = 4 BITS MODE, PLUS 4 BITS LENGTH
LDA MESSAGELENGTH ; NNNNXXXX
CPX #$40
BNE DOALPHAMODE
JMP DOBYTEMODE
DOALPHAMODE ; 000NXXXX
ASL
ASL ; <- 3X
ASL ; NXXXX 000
ORA STORAGE ; 3 BITS OF FIRST HI BYTE
INY
STA MPINTS,Y
INY
LDA STORAGE+1 ; FIRST LO BYTE
JSR NEXTQRBYTE ; HOW CONVENIENT. FIRST PAIR OF BYTES ENDS ON AN 8X BOUNDARY.
; ALSO INITIALIZES BITCOUNTER
LDX #$02 ; WHICH BYTE OF MESSAGE
NEXTMBYTE ASL STORAGE,X ; HI BYTE - ROL 5X
ROL STORAGE,X
ROL STORAGE,X
ROL STORAGE,X
ROL STORAGE,X ; BIT 5 -> BIT 0
BIT0 ROL STORAGE,X ; BIT 0 INTO CARRY
ROL ; CARRY INTO NEXT BIT OF QR
DEC BITCOUNTER ; DONE WITH A FULL BYTE OF QR? 7
BNE BIT1
JSR NEXTQRBYTE
BIT1 ROL STORAGE,X ; BIT 1 INTO CARRY
ROL
DEC BITCOUNTER ; 6
BNE BIT2
JSR NEXTQRBYTE
BIT2 ROL STORAGE,X ; BIT 2 INTO CARRY
ROL
DEC BITCOUNTER ; 5
BNE BIT3
JSR NEXTQRBYTE
BIT3 INX ; FINISHED WITH HI BYTE
ROL STORAGE,X ; BIT 0 OF LO BYTE INTO CARRY
ROL
DEC BITCOUNTER ; 4
BNE BIT4
JSR NEXTQRBYTE
BIT4 ROL STORAGE,X ; AND SO ON...
ROL
DEC BITCOUNTER ; 3
BNE BIT5
JSR NEXTQRBYTE
BIT5 ROL STORAGE,X
ROL
DEC BITCOUNTER ; 2
BNE BIT6
JSR NEXTQRBYTE
BIT6 ROL STORAGE,X
ROL
DEC BITCOUNTER ; 1
BNE BIT7
JSR NEXTQRBYTE
BIT7 ROL STORAGE,X
ROL
DEC BITCOUNTER ; 0
BNE BIT8
JSR NEXTQRBYTE
BIT8 ROL STORAGE,X
ROL
DEC BITCOUNTER
BNE BIT9
JSR NEXTQRBYTE
BIT9 ROL STORAGE,X
ROL
DEC BITCOUNTER
BNE BIT10
JSR NEXTQRBYTE
BIT10 ROL STORAGE,X
ROL
DEC BITCOUNTER
BNE NEXTHIBYTE
JSR NEXTQRBYTE
NEXTHIBYTE INX
CPX MESSAGELENGTH ; up to 114 BYTES OF MESSAGE
BCS PADBYTES
JMP NEXTMBYTE ; 3 BITS OF HI BYTE AND 8 OF LO BYTE ROTATED INTO QR BYTESTREAM
DOBYTEMODE ; A=MESSAGELENGTH. 0000XXXX
ASL
ASL
ASL
ASL ; XXXX____
ORA STORAGE,Y
BYTEMODELOOP INY
STA MPINTS,Y
LDA STORAGE,Y
CPY MESSAGELENGTH
BCC BYTEMODELOOP
BEQ BYTEMODELOOP
BCS PADLOOP
* pad to 80 bytes with 0s and 11101100 00010001 (#$EC #$11)
PADBYTES LDX BITCOUNTER ; ALWAYS TERMINATE WITH 4 ZEROES
db $C9 ; MASK ASL
PADBYTES2 ASL
DEC BITCOUNTER
BPL PADBYTES2
PADBITS STA MPINTS,Y ; STORE INCOMPLETE BYTE WITH TRAILING ZEROS
CPX #$04 ; NEEDS TO BE AT LEAST 4 FOR TERMINATOR
BCS PADLOOP
LDA MESSAGELENGTH
AND #$01
BEQ PADLOOP
INY
PADLOOP INY ; NEXT QR BYTE
CPY #$50
BEQ DOECCBYTES ; ARE WE DONE HERE?
LDA #$EC
STA MPINTS,Y
INY ; NEXT QR BYTE
CPY #$50
BEQ DOECCBYTES ; ARE WE DONE HERE?
LDA #$11
STA MPINTS,Y
JMP PADLOOP
DOECCBYTES LDX #$50 ; OH, THIS GON' BE FUN.
STX BYTECOUNTER ; HOW MANY TIMES HAVE WE BEEN HERE BEFORE?
COPYBYTES LDA MPINTS,X ; COPY COMPLETE MESSAGE BYTES TO STORAGE SPACE AT $8000
STA STORAGE,X
ECCSTEP1
MSGTOEXP TAY ; convert integers in message to exponents
LDA INTTOEXP,Y
STA MPEXP,X
LDA #0
STA SCRATCH,X
DEX ; DONE ALL 80 BYTES
BPL COPYBYTES
STA XORRESULT+$50
STA XORRESULT+$51
STA XORRESULT+$52 ; SKIPZERO READS OOB
ECCSTEP2 LDX #$0 ; Multiply the Generator Polynomial by the Lead EXPONENT of the Message Polynomial
STEP2LOOP LDA MPEXP ; mp first exponent
CLC
ADC GENERATOR,X ; ADDED TO each gp exponent
ADC #0 ; MOD 255 ON ROLLOVER > FF ADDS CARRY
TAY
SCRATCHINT LDA EXPTOINT,Y ; convert EXPONENTS in RESULT to INTEGERS
STA SCRATCH,X ; STORE IN WORK AREA 2
ECCSTEP3 EOR MPINTS,X ; INTEGER TERMS OF MESSAGE
STA XORRESULT,X ; RESULT FEEDS INTO STEP 1
INX
CPX #$15
BNE STEP2LOOP ; INTEGER RESULTS IN SCRATCH
; XOR the result with the message polynomial (INTEGERS)
XORBYTE LDA MPINTS,X ; INTEGER TERMS OF MESSAGE
STA XORRESULT,X ; RESULT FEEDS INTO STEP 1
INX
CPX #$51
BNE XORBYTE
; XORRESULT CONTAINS INTEGER RESULT
******
* if the lead term of the xor result is also 0, you should discard it as well
*****
SKIPZERO LDX XORLO ; FIRST RESULT IS ALWAYS ZERO.
INX ; SO SKIP IT
STX LOBYTE
LDA XORHI
STA HIBYTE
LDY #$0 ; convert integers in RESULT to exponents
FINDZERO LDA (LOBYTE),Y ; FIND LEADING ZERO TERM(s)
BNE XORTOEXP
INC LOBYTE
DEC BYTECOUNTER
JMP FINDZERO
XORTOEXP STA MPINTS,Y ; RESULT INTEGERS IN MPINTS
TAX ; FIRST NONZERO RESULT -> X
LDA INTTOEXP,X
STA MPEXP,Y ; $9080 + Y
INY
LDA (LOBYTE),Y
CPY #$51
BNE XORTOEXP ; RESULT EXPONENTS IN MPEXP
DEC BYTECOUNTER ; DO ECC MATH UNTIL THERE'S 20 REMAINDERS
BNE ECCSTEP2
ECCDONE ; XORRESULT CONTAINS 20 ECC BYTES
LDX #$15
LDY #$64
BUILDMSG LDA XORRESULT,X
STA STORAGE,Y
DEY
DEX
BNE BUILDMSG ; STORAGE NOW HAS FULL 100 BYTES OF MESSAGE
RESETBYTE ;;LDA #$0 ; SET UP FOR BYTE/BIT TRACKING
;;STA BYTECOUNTER
RESETBIT LDA #$8
STA BITCOUNTER
LDA #$20 ; ROW=33 (0-#$20)
STA ROW ; COLUMN=33 (0-#$20)
STA COLUMN
NEXTZIG ; QRLINE=ROW/2
LDA ROW
LSR
PHP
TAX ; LINE NUM OF BLANK QR = ROW/2
LDA QRLINESLO,X
STA LOBYTE
LDA QRLINESHI,X
STA HIBYTE ; ADDRESS OF QRLINEX
LDY COLUMN ; Y=BYTE OF LINE
LDA (LOBYTE),Y ; GET THE BYTE THAT'S AT THAT SPOT IN THE QR
BCC LONIBBLE ; IT'S LATER. IF CARRY SET, THEN (HI) NIBBLE
AND #$F0 ;
CMP #$10 ; 1 IN HI NIBBLE MEANS BLANK AND READY FOR BIT
BNE ZAG
JSR SETPIXEL ; GET A BIT FROM THE MESSAGE, AND DEPOSIT INTO THE PIXEL
JMP ZAG ; DONE WITH RIGHT PIXEL, DO LEFT PIXEL
LONIBBLE AND #$0F
CMP #$01 ; 1 IN LO NIBBLE MEANS BLANK AND READY FOR BIT
BNE ZAG ; OCCUPIED?
JSR SETPIXEL ; GET A BIT FROM THE MESSAGE, AND DEPOSIT INTO THE PIXEL
ZAG DEY ; ZIG IS DONE/OCCUPIED, TIME TO ZAG - ONE COLUMN TO THE LEFT
PLP ; RESTORE THE CARRY
LDA (LOBYTE),Y ; GET CURRENT QR PIXEL
BCC LONIBBLE2
AND #$F0
CMP #$10 ; 1 IN HI NIBBLE MEANS BLANK AND READY FOR BIT
BNE NEXTROW
JSR SETPIXEL ; GET A BIT FROM THE MESSAGE, AND DEPOSIT INTO THE PIXEL
JMP NEXTROW
LONIBBLE2 AND #$0F
CMP #$01 ; 1 IN LO NIBBLE MEANS BLANK AND READY FOR BIT
BNE NEXTROW
JSR SETPIXEL ; GET A BIT FROM THE MESSAGE, AND DEPOSIT INTO THE PIXEL
NEXTROW LDA COLUMN ; GOING UP OR GOING DOWN? EG $20 UP $1E DOWN.
CMP #$06 ; *** EXCEPT IF THE COLUMN IS LESS THAN #$06 (TIMING PATTERN IN COL #$06)
; JFC. THIS IS COMPLICATED.
BCS DIVBY4
ADC #$1 ; CARRY CLEAR, COLUMN LESS THAN 7, ADD 1 THEN DO THE MATH
DIVBY4 LSR ; DIVIDE STARTING COLUMN BY 2
LSR ; DIVIDE AGAIN
BCS GOINGDOWN ; CARRY SET HERE MEANS GOING DOWN, CLEAR MEANS UP.
GOINGUP LDA ROW
BEQ UTURN ; TURN THE CORNER AT ROW 0
DEC ROW
JMP NEXTZIG ;
GOINGDOWN LDA ROW
CMP #$20 ; LAST ROW?
BEQ UTURN ; TURN THE CORNER, ROW 32
INC ROW ; OTHERWISE, NEXT ROW
JMP NEXTZIG
UTURN LDA COLUMN
CMP #$08 ; IS IT #$08? THEN SKIP THE TIMING COLUMN.
BNE CKCOLUMN
DEC COLUMN ; SKIP THE TIMING COLUMN.
CKCOLUMN CMP #$01 ; IS IT #$01? THEN WE'RE DONE HERE.
BEQ DODISPLAY
DEC COLUMN
DEC COLUMN ; TWO COLUMNS OVER FOR NEXT ZIG
JMP NEXTZIG
DODISPLAY BIT 80STORE ; 80 column mode, do double-lo-res
BMI DODLR
DOLR LDX #$0 ; COPY THE QR BYTES TO THE SCREEN.
NEXTLINE LDY #$20
LDA QRLINESHI,X ; QRLINESHI/LO,X INTO LO/HIBYTE
STA HIBYTE
LDA QRLINESLO,X
STA LOBYTE
INX ; LO RES SCREEN LO/HI INTO COLUMN/ROW
LDA LoLineTableL,X ; TARGET DOWN ONE ROW FOR WHITE SPACE AT TOP
STA ROW
LDA LoLineTableH,X
STA COLUMN
INC ROW
INC ROW ; WHITE SPACE ON LEFT
NEXTCOL LDA (LOBYTE),Y ; GET QR PIXEL
STA (ROW),Y ; STORE AT SCREEN PIXEL
DEY
BPL NEXTCOL
CPX #$11
BNE NEXTLINE
QRDONE JMP QRDONE
DODLR ; MOVE GENERATED PIXELS TO DOUBLE LO RES SCREEN
LDX #$0
PAGE1LINE
LDA QRLINESHI,X ; QRLINESHI/LO,X INTO LO/HIBYTE
STA HIBYTE
LDA QRLINESLO,X
STA LOBYTE
INX ; LO RES SCREEN LO/HI INTO COLUMN/ROW
LDA LoLineTableL,X ; TARGET DOWN ONE ROW FOR WHITE SPACE AT TOP
STA ROW
LDA LoLineTableH,X
STA COLUMN
INC ROW
INC ROW ; WHITE SPACE ON LEFT
LDY #$1F ; 33 COLUMNS
NEXTP1COL LDA (LOBYTE),Y ; GET QR PIXEL
PHA
TYA
LSR
TAY
PLA
STA (ROW),Y ; STORE AT SCREEN PIXEL
TYA
ROL
TAY
DEY
DEY
BPL NEXTP1COL
CPX #$11
BNE PAGE1LINE
LDX #$0
STA PAGE2ON
PAGE2LINE
LDA QRLINESHI,X ; QRLINESHI/LO,X INTO LO/HIBYTE
STA HIBYTE
LDA QRLINESLO,X
STA LOBYTE
INX ; LO RES SCREEN LO/HI INTO COLUMN/ROW
LDA LoLineTableL,X ; TARGET DOWN ONE ROW FOR WHITE SPACE AT TOP
STA ROW
LDA LoLineTableH,X
STA COLUMN
INC ROW
INC ROW ; WHITE SPACE ON LEFT
LDY #$20
NEXTP2COL LDA (LOBYTE),Y ; GET QR PIXEL
PHA
TYA
LSR
TAY
PLA
STA (ROW),Y ; STORE AT SCREEN PIXEL
TYA
ROL
TAY
DEY
DEY
BPL NEXTP2COL
CPX #$11
BNE PAGE2LINE
JMP QRDONE
*** NEXTQRBYTE
NEXTQRBYTE STA MPINTS,Y ; STORE COMPLETE BYTE
LDA #$08 ; RESET LOOP COUNT
STA BITCOUNTER
INY ; NEXT QR BYTE
LDA MPINTS,Y ; INTO ACC
RTS ; BACK INTO THE FRAY
*** NEXTQRBYTE
*** SETPIXEL
SETPIXEL CMP #$01 ; ACC IS GOING TO BE EITHER 01 OR 10
PHP
JSR GETNEXTBIT ; LOADS TEMP WITH PROPER F OR 0
; Y HAS COLUMN OFFSET
; (LOBYTE) HAS ROW
EOR (LOBYTE),Y ; MIX BITS
PLP
BEQ SETLONIBBLE
SETHINIBBLE AND #$F0 ; SEPARATE BITS
JMP SETNIBBLE
SETLONIBBLE AND #$0F ; SEPARATE BITS
SETNIBBLE EOR (LOBYTE),Y ; MERGE BITS
STA (LOBYTE),Y ; REPLACE QR PIXEL.
RTS
*** SETPIXEL
*** GETNEXTBIT
GETNEXTBIT LDA BITCOUNTER ; WHERE WERE WE IN THE ROL SHENANIGANS?
BNE NEXTBIT ; NOT DONE WITH CURRENT BYTE
LDA #$08 ; OR ARE WE?
STA BITCOUNTER ; IF SO...
INC BYTECOUNTER ; NEXT BYTE
NEXTBIT LDA TEMP
LDX BYTECOUNTER ; ARE WE DONE WITH ALL 100 BYTES?
CPX #$64
BEQ MASKDONE1
DEC BITCOUNTER
ASL STORAGE,X
WHITEPIXEL LDA #$FF
BLACKPIXEL ADC #$00
COLORPIXEL TAX
DOMASK ; JFC ON A POGO STICK! GOTTA MASK THE BITS!
; MASK PATTERN 1: IF (row) mod 2 == 0 THEN FLIP BIT.
LDA ROW
LSR
TXA
BCS MASKDONE ; ROW IS ODD, ALL DONE.
EOR #$FF ; ROW IS EVEN, FLIP THE BIT
MASKDONE STA TEMP
MASKDONE1 RTS
*** GETNEXTBIT
**************************************************
* blanks the screen quickly.
* CLOBBERS A,Y
**************************************************
CLEARSCREEN LDA #$FF
LDY #$78
FILL1 DEY
STA $400, Y
STA $480, Y
STA $500, Y
STA $580, Y
STA $600, Y
STA $680, Y
STA $700, Y
STA $780, Y
BNE FILL1
STA PAGE2ON ; go again on AUX400
LDY #$78
FILL2 DEY
STA $400, Y
STA $480, Y
STA $500, Y
STA $580, Y
STA $600, Y
STA $680, Y
STA $700, Y
STA $780, Y
BNE FILL2
STA PAGE2OFF ; back to MAIN
RTS
*** MULT45
MULT45 ; MULTIPLY BYTE IN $FC BY 45 FOR CONVERSION TO 11-BIT BINARY
; RESULT IN FE,FD
LDA #$0
STA $FD
STA $FE ; ZERO OUT TARGET BYTES
LDX #$2D ; X=45
LOOP45 CLC
LDA $FD
ADC $FC
STA $FD
BCC NEXTMULT
INC $FE
NEXTMULT DEX
BNE LOOP45
RTS
*** MULT45
CHECKMESSAGE LDA MODE
CMP #$20 ; ALPHANUMERIC MODE, LIMITED CHARACTERS IN ALPHANUM
BEQ CHECKBYTES
CHECKDONE JMP SETUP ; BYTE MODE, SKIP TO THE SETUP
CHECKBYTES LDY #$FF
CHECKCHAR ; FOR EACH CHARACTER OF THE MESSAGE, CHECK FOR FF
INY
LDX MESSAGE,Y
BEQ CHECKDONE
LDA ALPHANUM,X
BPL CHECKCHAR
RTS ; OOPS. INVALID CHARACTER.
**************************************************
* DO WE HAVE ACCESS TO 80 COLS/DLR MODE?
* ADAPTED FROM:
* https://github.com/a2-4am/4cade/blob/master/src/hw.memcheck.a
**************************************************
Has128K
bit $C082
sta 80STOREOFF
lda MACHINEID
cmp #$A0
beq IIE ; Spectrum ED
cmp #$06
bne @no ; earlier than //e -> no 128K
IIE lda SLOT3STATUS
bmi @no ; no 80-column card -> no 128K
ldx @checklen
LOOPC lda @checker,x
sta $80,x
dex
bpl LOOPC
jmp $80 ; check if auxmem actually works
@checker
lda #$EE
sta RAMWRTON
sta RAMRDON
sta $0C00
sta $0800
lda $0C00
cmp #$EE
bne @no
asl $0C00
asl
cmp $0C00
bne @no
cmp $0800
bne @yes
@no clc
db #$24
@yes sec
@finish sta RAMWRTOFF
sta RAMRDOFF
rts
@checklen db *-@checker
DS \
QRLINE0 HEX 00,F0,F0,F0,F0,F0,00,FF,00,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,FF,00,F0,F0,F0,F0,F0,00
QRLINE1 HEX 00,FF,00,00,00,FF,00,FF,FF,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,FF,00,FF,00,00,00,FF,00
QRLINE2 HEX 00,FF,F0,F0,F0,FF,00,FF,00,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,FF,00,FF,F0,F0,F0,FF,00
QRLINE3 HEX F0,F0,F0,F0,F0,F0,F0,FF,00,1F,10,1F,10,1F,10,1F,10,1F,10,1F,10,1F,10,1F,10,FF,F0,F0,F0,F0,F0,F0,F0
QRLINE4 HEX 10,10,10,1F,1F,10,F0,1F,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,10,10,10,1F,1F,10,10
QRLINE5 HEX 11,11,11,11,11,11,F0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11
QRLINE6 HEX 11,11,11,11,11,11,F0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11
QRLINE7 HEX 11,11,11,11,11,11,F0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11
QRLINE8 HEX 11,11,11,11,11,11,F0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11
QRLINE9 HEX 11,11,11,11,11,11,F0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11
QRLINEA HEX 11,11,11,11,11,11,F0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11
QRLINEB HEX 11,11,11,11,11,11,F0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11
QRLINEC HEX F1,F1,F1,F1,F1,F1,F0,F1,01,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,00,F0,F0,F0,00,11,11,11,11
QRLINED HEX 00,F0,F0,F0,F0,F0,00,FF,0F,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,00,FF,F0,FF,00,11,11,11,11
QRLINEE HEX 00,FF,00,00,00,FF,00,FF,FF,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,10,10,10,10,11,11,11,11
QRLINEF HEX 00,FF,F0,F0,F0,FF,00,FF,00,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11
QRLINE10 HEX F0,F0,F0,F0,F0,F0,F0,FF,F0,F1,F1,F1,F1,F1,F1,F1,F1,F1,F1,F1,F1,F1,F1,F1,F1,F1,F1,F1,F1,F1,F1,F1,F1
* format string bits
* 111001011110011 - v4, Low ECC
DS \
GENERATOR HEX 00,11,3C,4F,32,3D,A3,1A,BB,CA,B4,DD,E1,53,EF,9C,A4,D4,D4,BC,BE
* 0 17 60 79 50 61 163 26 187 202 180 221 225 83 239 156 164 212 212 188 190
DS \
ALPHANUM DS 32,$FF
HEX 24,FF,FF,FF,25,26,FF,FF,FF,FF,27,28,FF,29,2A,2B,00,01,02,03,04,05,06,07,08,09,2C,FF,FF,FF,FF,FF,FF,0A,0B,0C,0D,0E,0F,10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F,20,21,22,23
DS \,$FF
INTTOEXP HEX 00,00,01,19,02,32,1A,C6,03,DF,33,EE,1B,68,C7,4B,04,64,E0,0E,34,8D,EF,81,1C,C1,69,F8,C8,08,4C,71,05,8A,65,2F,E1,24,0F,21,35,93,8E,DA,F0,12,82,45,1D,B5,C2,7D,6A,27,F9,B9,C9,9A,09,78,4D,E4,72,A6,06,BF,8B,62,66,DD,30,FD,E2,98,25,B3,10,91,22,88,36,D0,94,CE,8F,96,DB,BD,F1,D2,13,5C,83,38,46,40,1E,42,B6,A3,C3,48,7E,6E,6B,3A,28,54,FA,85,BA,3D,CA,5E,9B,9F,0A,15,79,2B,4E,D4,E5,AC,73,F3,A7,57,07,70,C0,F7,8C,80,63,0D,67,4A,DE,ED,31,C5,FE,18,E3,A5,99,77,26,B8,B4,7C,11,44,92,D9,23,20,89,2E,37,3F,D1,5B,95,BC,CF,CD,90,87,97,B2,DC,FC,BE,61,F2,56,D3,AB,14,2A,5D,9E,84,3C,39,53,47,6D,41,A2,1F,2D,43,D8,B7,7B,A4,76,C4,17,49,EC,7F,0C,6F,F6,6C,A1,3B,52,29,9D,55,AA,FB,60,86,B1,BB,CC,3E,5A,CB,59,5F,B0,9C,A9,A0,51,0B,F5,16,EB,7A,75,2C,D7,4F,AE,D5,E9,E6,E7,AD,E8,74,D6,F4,EA,A8,50,58,AF
EXPTOINT HEX 01,02,04,08,10,20,40,80,1D,3A,74,E8,CD,87,13,26,4C,98,2D,5A,B4,75,EA,C9,8F,03,06,0C,18,30,60,C0,9D,27,4E,9C,25,4A,94,35,6A,D4,B5,77,EE,C1,9F,23,46,8C,05,0A,14,28,50,A0,5D,BA,69,D2,B9,6F,DE,A1,5F,BE,61,C2,99,2F,5E,BC,65,CA,89,0F,1E,3C,78,F0,FD,E7,D3,BB,6B,D6,B1,7F,FE,E1,DF,A3,5B,B6,71,E2,D9,AF,43,86,11,22,44,88,0D,1A,34,68,D0,BD,67,CE,81,1F,3E,7C,F8,ED,C7,93,3B,76,EC,C5,97,33,66,CC,85,17,2E,5C,B8,6D,DA,A9,4F,9E,21,42,84,15,2A,54,A8,4D,9A,29,52,A4,55,AA,49,92,39,72,E4,D5,B7,73,E6,D1,BF,63,C6,91,3F,7E,FC,E5,D7,B3,7B,F6,F1,FF,E3,DB,AB,4B,96,31,62,C4,95,37,6E,DC,A5,57,AE,41,82,19,32,64,C8,8D,07,0E,1C,38,70,E0,DD,A7,53,A6,51,A2,59,B2,79,F2,F9,EF,C3,9B,2B,56,AC,45,8A,09,12,24,48,90,3D,7A,F4,F5,F7,F3,FB,EB,CB,8B,0B,16,2C,58,B0,7D,FA,E9,CF,83,1B,36,6C,D8,AD,47,8E,01
XORLO db <XORRESULT
XORHI db >XORRESULT
QRLINESLO DB <QRLINE0,<QRLINE1,<QRLINE2,<QRLINE3,<QRLINE4,<QRLINE5,<QRLINE6,<QRLINE7,<QRLINE8,<QRLINE9,<QRLINEA,<QRLINEB,<QRLINEC,<QRLINED,<QRLINEE,<QRLINEF,<QRLINE10
QRLINESHI DB >QRLINE0,>QRLINE1,>QRLINE2,>QRLINE3,>QRLINE4,>QRLINE5,>QRLINE6,>QRLINE7,>QRLINE8,>QRLINE9,>QRLINEA,>QRLINEB,>QRLINEC,>QRLINED,>QRLINEE,>QRLINEF,>QRLINE10
Lo01 equ $400
Lo02 equ $480
Lo03 equ $500
Lo04 equ $580
Lo05 equ $600
Lo06 equ $680
Lo07 equ $700
Lo08 equ $780
Lo09 equ $428
Lo10 equ $4a8
Lo11 equ $528
Lo12 equ $5a8
Lo13 equ $628
Lo14 equ $6a8
Lo15 equ $728
Lo16 equ $7a8
Lo17 equ $450
Lo18 equ $4d0
Lo19 equ $550
Lo20 equ $5d0
LoLineTable DA Lo01,Lo02,Lo03,Lo04,Lo05,Lo06,Lo07,Lo08,Lo09,Lo10,Lo11,Lo12,Lo13,Lo14,Lo15,Lo16,Lo17,Lo18,Lo19,Lo20
LoLineTableH db >Lo01,>Lo02,>Lo03,>Lo04,>Lo05,>Lo06,>Lo07,>Lo08,>Lo09,>Lo10,>Lo11,>Lo12,>Lo13,>Lo14,>Lo15,>Lo16,>Lo17,>Lo18,>Lo19,>Lo20
LoLineTableL db <Lo01,<Lo02,<Lo03,<Lo04,<Lo05,<Lo06,<Lo07,<Lo08,<Lo09,<Lo10,<Lo11,<Lo12,<Lo13,<Lo14,<Lo15,<Lo16,<Lo17,<Lo18,<Lo19,<Lo20