apple2_hgrbyte/src_ca65/hgrbyte.s

552 lines
15 KiB
ArmAsm

; ca65
.feature c_comments
.linecont +
.feature labels_without_colons
.feature leading_dot_in_identifiers
.PC02 ; 65C02
; HGR Byte Inspector
; Michael Pohoreski
; Version 16
; Ctrl-IJKL to move
; 0..9, A..F enter nibble into cursor byte
;
; Keys:
;
; ESC Quit
; G Toggle fullscreen
;
; I Move cursor up
; J Move cursor left
; K Move cursor right
; L Move cursor down
;
; ^I Move cursor to col 0
; ^J Move cursor to col 39
; ^K Move cursor to row 0
; ^L Move cursor to row 191
; RET Center cursor
;
; 0..9 "Append" hex nibble to cursor byte
; A..F
;
; ! Toggle bit 0
; @ Toggle bit 1
; # Toggle bit 2
; $ Toggle bit 3
; % Toggle bit 4
; ^ Toggle bit 5
; & Toggle bit 6
; * Toggle bit 7 (high bit)
; SPC Toggle high bit of byte (bit 7)
; ( Set byte to $FF (Shift-9)
; ) Clear byte to $00 (Shift-0)
; ` Flip all bits
; ~ Flip all bits
;
; , Shift byte left (with zero)
; . Shift byte right (with one )
; < Shift byte left (with zero)
; > Shift byte right (with one )
; [ Rotate byte left
; ] Rotate byte right
;
; - Save cursor byte to temporary
; = Set cursor byte from temporary
; Force APPLE 'text' to have high bit on
; Will display as NORMAL characters
.macro APPLE text
.repeat .strlen(text), I
.byte .strat(text, I) | $80
.endrep
.endmacro
; Force ASCII 'text' to be control chars: $00..$1F
; Will display as INVERSE characters
.macro CTRL text
.repeat .strlen(text), I
.byte .strat(text, I) & $1F
.endrep
.endmacro
; Force ASCII 'text' to be control chars: $00..$3F
; Will display as INVERSE characters
.macro INV text
.repeat .strlen(text), I
.byte .strat(text, I) & $3F
.endrep
.endmacro
GBASL = $26
GBASH = $27
CH = $24 ; text cursor column
CV = $25 ; text cursor row
ROW_20 = $0550 ; VTAB 21 TEXT address
ROW_21 = $06D0 ; VTAB 22 TEXT address
ROW_22 = $0750 ; VTAB 23 TEXT address
ROW_23 = $07D0 ; VTAB 24 TEXT address
HPOSN = $F411 ; A=row, Y,X=col update GBASL GBASH
TABV = $FB5B ; A=row, ALL STA $25, JMP $FC22
VTAB = $FC22 ; $25=row //e LDA $25, STA$28
HOME = $FC58
COUT = $FDED
PR_HEX = $FDD3
PRBYTE = $FDDA
KEYBOARD = $C000
KEYSTROBE = $C010
TXTCLR = $C050 ; Mode Graphics
MIXCLR = $C052 ; Full screen
MIXSET = $C053 ; Split screen
PAGE1 = $C054
HIRES = $C057 ; Mode HGR
lastkey = $F9
cursor_row = $E2 ; used by Applesoft HGR.row
cursor_org = $FA ; When cursor is saved
cursor_tmp = $FB ; Flashing cursor byte
cursor_val = $FC ; Current byte under cursor
flags = $FD ;
temp = $FE
cursor_col = $FF
FLAG_FULL = $01 ; == $1 -> $C052 MIXCLR
; ; == $0 -> $C053 MIXSET
HGRPAGE = $E6 ; used by Applesoft HGR.page
__MAIN= $0900
.word __MAIN ; 2 byte BLOAD address
.word __END - __MAIN ; 2 byte BLOAD size
.org __MAIN ; .org must come after header else offsets are wrong
HgrByte:
LDA #16 ; Version
BIT PAGE1 ; Page 1
BIT TXTCLR ; not text, but graphics
BIT MIXSET ; Split screen text/graphics
BIT HIRES ; HGR, no GR
LDX #0 ; also used by PrintFooter
STX flags
STX cursor_col
STX cursor_row
STX cursor_org
STX GBASL
LDA #$20
STA GBASH
STA HGRPAGE
PrintFooter:
LDA TextFooter, X
BEQ _Center ; Default to center of screen
STA ROW_21,X ; 4 line text window, 2nd row
INX
BNE PrintFooter ; (almost) always
; Funcs that JMP to GetByte before GotKey()
; Funcs that JMP to PutByte after GotKey()
_Screen: ; Toggle mixed/full screen
LDA flags ; A = %????_????
AND #FLAG_FULL ; A = %0000_000f
TAX ; f=0 f=1
STA MIXCLR,X ; C052 C053
LDA flags ; FULL MIX
EOR #FLAG_FULL ; mode is based on old leading edge
STA flags ; not new trailing edge
BRA FlashByte
_HighBit:
EOR #$80
BRA PutByte
_MoveL: DEC cursor_col
BPL GetByte
_MoveR: INC cursor_col
LDA cursor_col
CMP #40
BCC GetByte ; intentional fall into _EdgeR
_EdgeR: LDA #39
.byte $2C ; BIT $ABS skip next instruction
_EdgeL: LDA #0
STA cursor_col
BPL GetByte ; always
_MoveU: DEC cursor_row
LDA cursor_row
CMP #$FF
BNE GetByte ; INTENTIONAL fall into if Y < 0
_MoveD: INC cursor_row
LDA cursor_row
CMP #192
BCC GetByte ; intentional fall into
_EdgeD: LDA #$BF
.byte $2C
_EdgeU: LDA #00
STA cursor_row
ADC #1
BNE GetByte ; always
_Center:
LDA #40/2
STA cursor_col
LDA #192/2
STA cursor_row ; intentional fall into GetByte
GetByte: ; Cursor position changed
LDY #0 ; Update pointer to screen
LDX #0
LDA cursor_row
JSR HPOSN ; A=row, Y,X=col X->E0 Y->E1
JSR GetCursorByte
PutByte:
STA cursor_val ; current value
STA cursor_tmp ; flashing cursor
JSR DrawStatus
FlashByte:
JSR FlashCursorByte
GetKey:
LDA KEYBOARD
BPL FlashByte
STA KEYSTROBE
AND #$7F ; Force ASCII
STA lastkey
CMP #'0' ; key < '0'
BCC @TestHex
CMP #'9'+1 ; key < '9'+1
BCC _Nibble
@TestHex
CMP #'A'
BCC @LoadKeys
CMP #'F'+1
BCC _Nibble
@LoadKeys
LDX #nKeys
FindKey:
DEX
BMI FlashByte
CMP aKeys, X
BNE FindKey
GotKey:
; If code doesn't fit withing +/-127 bytes
; LDA aFuncHi, X
LDA #>HgrByte ; FuncAddressHi
PHA
LDA aFuncLo, X ; FuncAddressLo
PHA
LDA cursor_val ; Last displayed byte may be cursor_tmp
JSR SetCursorByte ; restore current val in case cursor moves
; Also pre-load for ROL/R SHL/R
LDX #0 ; for Toggle Bit #
_Exit: RTS ; And call function assigned to key
; To BRUN under DOS.3 change above RTS to
; RTS
;_Exit: JMP $3D0 ; DOS 3.3 Warmstart vector
; Functions starting with _ are invoked via keys
.out .sprintf( "_ByteFF: %X", * )
_ByteFF:
LDA #$FF
BNE PutByte ; always
.out .sprintf( "_Byte00: %X", * )
_Byte00:
LDA #$00
BEQ PutByte ; always
.out .sprintf( "_FlipBy: %X", * )
_FlipByte:
LDX #$FF
BNE TogBit
_Rol: CMP #$80 ; C=a A=%abcd_efgh
_SHL1: ROL ; C=b A=%bcde_fgha C<-bit7, bit0<-C
BRA PutByte ; force branch always
_SHR1: ORA #$01 ; Force C=1 via ROR (SHR, OR #$80)
; Intentional fall into _Ror
; Using LSR instead of ROR to save a byte
; 8 Byte version
; CLC
; ROR
; BCC PutByte
; ORA #$80
; BCS PutByte
_Ror: LSR ; C=h A=%0abc_defg 0->bit7, bit0->C
BCC PutByte
ORA #$80
BCS PutByte ; always
_ShiftL:ASL ; C=a A=%bcde_fgh0
.byte $A2 ; skip next LSR instruction; LDX dummy imm val
_ShiftR:LSR ; C=h A=%0abc_defg
BRA PutByte
.out .sprintf( "_Bits# : %X", * )
_Bit7: INX ; intentional fall into
_Bit6: INX
_Bit5: INX
_Bit4: INX
_Bit3: INX
_Bit2: INX
_Bit1: INX
_Bit0: INX
TAY ; save cursor_val
SEC ;
LDA #0 ; X=? A=0 C=1
_TogBit:ROL
DEX
BNE _TogBit
TAX
TYA ; load cursor_val
; common _Bit# code
TogBit: STX temp
EOR temp
GotoPutByte:
BRA PutByte ; code is too far to directly branch
.out .sprintf( "_Save : %X", * )
_SaveByte:
STA cursor_org ; intentional fall into
_LoadByte:
.out .sprintf( "_Load : %X", * )
LDA cursor_org
CLC
BCC GotoPutByte ; always
.out .sprintf( "_Nibble: %X", * )
_Nibble:
LDY #3
@CursorSHL:
ASL cursor_val
DEY
BPL @CursorSHL
LDA lastkey
CMP #$41
BCC @Digit
SBC #7 ; $41 - 6 - (C=1) = $3A
@Digit:
AND #$0F ; Key to Hex
CLC
ADC cursor_val
BCC GotoPutByte ; always
TextFooter:
; "X=## Y=## $=####:## %%%%%%%%~%%%%%%%%"
APPLE " SAVE:?? 76543210 "
INV "12345678" ;1-8 INVERSE
.byte $00
DrawStatus:
LDA #0 ; Cursor.X = 0
STA CH
LDA #20 ; Cursor.Y = Top of 4 line split TEXT/HGR window
JSR TABV ; update CV
PrintStatus:
LDA #'X'+$80 ; X=## Y=## $=####:##
JSR COUT
LDA cursor_col
JSR PR_HEX
LDA #' '+$80
JSR COUT
LDA #'Y'+$80
JSR COUT
LDA cursor_row
JSR PR_HEX
LDA #' '+$80
JSR COUT
LDA #'$'+$80
JSR COUT
LDA GBASH
JSR PR_HEX
LDA GBASL
CLC
ADC cursor_col
JSR PRBYTE
LDA #':'+$80
JSR COUT
LDA cursor_val
JSR PRBYTE
LDA #' '+$80
JSR COUT
ReverseByte:
LDX #8
LDA cursor_val
STA temp
ReverseBit:
ASL temp
ROR
DEX
BNE ReverseBit
STA temp
PHA ; save reverse byte
LDX #8
PrintBitsNormal:
LDA temp
JSR Bit2Asc
ROR temp
DEX
BNE PrintBitsNormal
LDA #'~'+$80
JSR COUT
LDX #8
LDA cursor_val
PrintBitsReverse:
TAY
JSR Bit2Asc
TYA
LSR
DEX
BNE PrintBitsReverse
LDA #'$'+$80
JSR COUT
PLA ; restore reverse byte
JSR PRBYTE
LDA cursor_org ; X=0
PHA
LSR
LSR
LSR
LSR
JSR NibToInvTxt
PLA
; Display nibble as inverse text
; 0 -> '0' $30
; 9 -> '9' $39
; A -> ^A $01
; F -> ^F $06
NibToInvTxt:
AND #$F
ORA #'0'+$00 ; ASCII: +$80
CMP #'9'+$01 ; ASCII: +$81
BCC PrintSave
SBC #$39 ; C=1, $3A ':' -> $01 'A', $3F '?' -> $06
PrintSave:
STA ROW_21+17,X
INX
RTS
Bit2Asc:
AND #$01 ; 0 -> B0
BEQ FlipBit
LDA #$81 ; 1 -> 31
FlipBit:
EOR #$B0
JMP COUT
; A = byte
GetCursorByte:
LDY cursor_col
LDA (GBASL),Y
STA cursor_val
SetCursorByte:
LDY cursor_col
STA (GBASL),Y
RTS
FlashCursorByte:
LDA cursor_tmp
EOR #$FF
STA cursor_tmp
JMP SetCursorByte
; Keys are searched in reverse order
; Sorted by least used to most used
aKeys:
CTRL "[" ; _Exit ESC Quit
.byte "G" ; _Screen G Toggle fullscreen
CTRL "H" ; _MoveL <- Ctrl-H $08
CTRL "U" ; _MoveR -> Ctrl-U $15
CTRL "I" ; _EdgeU ^I Ctrl-I $09 Move cursor to row 0
CTRL "J" ; _EdgeL ^J Ctrl-J $0A Move cursor to col 0
CTRL "K" ; _EdgeD ^K Ctrl-K $0B Move cursor to row 191
CTRL "L" ; _EdgeR ^L Ctrl-L $0C Move cursor to col 39
CTRL "M" ; _Center Center cursor
.byte "I" ; _moveU Move cursor Up
.byte "J" ; _moveL Move cursor Left
.byte "K" ; _MoveD Move cursor Down
.byte "L" ; _MoveR Move cursor Right
.byte "!" ; _Bit0 Toggle bit 0
.byte "@" ; _Bit1 Toggle bit 1
.byte "#" ; _Bit2 Toggle bit 2
.byte "$" ; _Bit3 Toggle bit 3
.byte "%" ; _Bit4 Toggle bit 4
.byte "^" ; _Bit5 Toggle bit 5
.byte "&" ; _Bit6 Toggle bit 6
.byte "*" ; _Bit7 Toggle bit 7
.byte " " ; _HighBit Toggle high bit of byte (bit 7)
.byte "(" ; _ByteFF Set byte to FF (Shift-9)
.byte ")" ; _Byte00 Set byte to 00 (Shift-0)
.byte "`" ; _FlipByte Toggle all bits
.byte "~" ; _FlipByte
.byte "," ; _ShiftL (with zero)
.byte "<" ; _ShiftL (with one )
.byte "." ; _ShiftR (with zero)
.byte ">" ; _ShiftR (with one )
.byte "[" ; _Rol
.byte "]" ; _Ror
.byte "-" ; _SaveByte Save cursor byte
.byte "=" ; _LoadByte Load cursor byte
eKeys:
nKeys = eKeys - aKeys ;
; Table of function pointers
; *Note*: Must match aKeys order!
aFuncLo:
.byte <_Exit -1 ; ESC
.byte <_Screen -1 ; G
.byte <_MoveL -1 ; <-
.byte <_MoveR -1 ; ->
.byte <_EdgeU -1 ; ^I
.byte <_EdgeL -1 ; ^J
.byte <_EdgeD -1 ; ^K
.byte <_EdgeR -1 ; ^L
.byte <_Center -1 ; RET
.byte <_MoveU -1 ; 'I'
.byte <_MoveL -1 ; 'J'
.byte <_MoveD -1 ; 'K'
.byte <_MoveR -1 ; 'L'
.byte <_Bit0 -1 ; '1'
.byte <_Bit1 -1 ; '2'
.byte <_Bit2 -1 ; '3'
.byte <_Bit3 -1 ; '4'
.byte <_Bit4 -1 ; '5'
.byte <_Bit5 -1 ; '6'
.byte <_Bit6 -1 ; '7'
.byte <_Bit7 -1 ; '8'
.byte <_HighBit -1 ; SPC
.byte <_ByteFF -1 ; '('
.byte <_Byte00 -1 ; ')'
.byte <_FlipByte-1 ; '`'
.byte <_FlipByte-1 ; '~' not a dup mistake
.byte <_ShiftL -1 ; `,`
.byte <_SHL1 -1 ; `<`
.byte <_ShiftR -1 ; `.`
.byte <_SHR1 -1 ; `>`
.byte <_Rol -1 ; '['
.byte <_Ror -1 ; ']
.byte <_SaveByte-1 ; '='
.byte <_LoadByte-1 ; '-'
__END: