mirror of
https://github.com/flowenol/apple1serial.git
synced 2024-09-27 04:54:42 +00:00
337 lines
9.8 KiB
Plaintext
337 lines
9.8 KiB
Plaintext
;End address of dump block
|
|
#define hex1_l $34
|
|
#define hex1_h $35
|
|
|
|
;Begin address of dump block
|
|
#define hex2_l $36
|
|
#define hex2_h $37
|
|
|
|
#define last_command $28
|
|
#define last_command_none $00
|
|
#define last_command_read $01
|
|
#define last_command_write $02
|
|
|
|
;Input buffer
|
|
#define input $0200
|
|
#define kbd_data $D010 ;PIA.A keyboard input
|
|
#define kbd_cr $D011 ;PIA.A keyboard control register
|
|
#define monitor $FF1A ;Escape back to monitor
|
|
#define echo $FFEF ;Echo character to terminal
|
|
#define prbyte $FFDC
|
|
|
|
#define serial_ready $C000
|
|
#define serial_reset $C001
|
|
#define serial_read $C080
|
|
#define serial_write $C081
|
|
|
|
|
|
#define R_LETTER $D2
|
|
#define W_LETTER $D7
|
|
#define ZERO $B0
|
|
#define SEP $AE
|
|
#define CR $8D ;Carriage Return
|
|
#define ESC $9B ;ASCII ESC
|
|
#define SPACE $A0
|
|
|
|
; pad first 252 bytes with zeroes
|
|
.dsb 252, 0
|
|
|
|
; include identification bytes
|
|
.byt "A1SI"
|
|
|
|
; this section is almost identical to original WOZ ACI
|
|
; adapted from https://www.sbprojects.net/projects/apple1/aci.php
|
|
* = $C100
|
|
apple_serial
|
|
lda #CR ;Drop the cursor one line
|
|
jsr echo
|
|
lda #"*" ;Print prompt
|
|
jsr echo
|
|
lda #CR ;And drop the cursor one line
|
|
jsr echo
|
|
lda #$00 ;Set last command type to NONE
|
|
sta last_command
|
|
ldy #$FF ;Reset the input buffer index
|
|
|
|
next_char
|
|
iny
|
|
|
|
kbd_wait
|
|
lda kbd_cr ;Wait for a key
|
|
bpl kbd_wait ;Still no key!
|
|
|
|
lda kbd_data ;Read key from keyboard
|
|
sta input,Y ;Save it into buffer
|
|
jsr echo ;And type it on the screen
|
|
cmp #ESC
|
|
beq apple_serial ;Start from scratch if ESC!
|
|
cmp #CR
|
|
bne next_char ;Read keys until CR
|
|
|
|
ldx #$FF ;Initialize parse buffer pointer
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Start parsing command
|
|
;-------------------------------------------------------------------------
|
|
|
|
next_cmd
|
|
lda #$00 ;Clear begin and end values
|
|
sta hex1_l
|
|
sta hex1_h
|
|
sta hex2_l
|
|
sta hex2_h
|
|
|
|
next_chr
|
|
inx ;Increment input pointer
|
|
lda $0200,X ;Get next char from input lin
|
|
cmp #R_LETTER ;Read command?
|
|
beq read ;Yes!
|
|
cmp #W_LETTER ;Write command?
|
|
beq write ;Yes! (note: CY=1)
|
|
cmp #SEP ;Separator?
|
|
beq separator ;Yes!
|
|
cmp #CR ;End of line?
|
|
beq to_monitor ;Escape to monitor! We're done
|
|
cmp #SPACE ;Ignore spaces
|
|
beq next_chr
|
|
eor #ZERO ;Map digits to 0-9
|
|
cmp #$0A ;Is it a decimal digit?
|
|
bcc digit ;Yes!
|
|
clc
|
|
adc #$89 ;Map letter "A"-"F" to $FA-$FF
|
|
cmp #$FA ;Hex letter?
|
|
bcc apple_serial ;No! Character not hex!
|
|
|
|
digit
|
|
asl ;Hex digit to MSD of A
|
|
asl
|
|
asl
|
|
asl
|
|
|
|
ldy #4 ;Shift count
|
|
|
|
hexshift
|
|
asl ;Hex digit left, MSB to carry
|
|
rol hex1_l ;Rotate into LSD
|
|
rol hex1_h ;Rotate into MSD
|
|
dey ;Done 4 shifts?
|
|
bne hexshift ;No! Loop
|
|
beq next_chr ;Handle next character
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Return to monitor, prints \ first
|
|
;-------------------------------------------------------------------------
|
|
|
|
to_monitor
|
|
;jmp monitor ;Escape back to monitor
|
|
jmp apple_serial
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Separating . found. Copy HEX1 to Hex2. Doesn't clear HEX1!!!
|
|
;-------------------------------------------------------------------------
|
|
|
|
separator
|
|
lda hex1_l ;Copy hex value 1 to hex value 2
|
|
sta hex2_l
|
|
lda hex1_h
|
|
sta hex2_h
|
|
lda #$00 ;Original ACI bug (not enough ROM space?) fix
|
|
sta hex1_l
|
|
sta hex1_h
|
|
jmp next_chr
|
|
|
|
;-------------------------------------------------------------------------
|
|
; In-monitor read procedure
|
|
;-------------------------------------------------------------------------
|
|
|
|
read
|
|
lda last_command
|
|
cmp #last_command_read
|
|
beq read_ready
|
|
lda serial_read ;Enable read mode, this can be done quick, without reset
|
|
read_ready
|
|
txa ;Preserve X on stack
|
|
pha
|
|
ldy #$00
|
|
ldx #hex2_l
|
|
|
|
read_byte
|
|
lda serial_ready
|
|
beq read_byte ;No data arrived
|
|
lda serial_read ;Read byte
|
|
sta (hex2_l),Y ;Store byte under address, this should be hex2_l but macro substitution doesn't work
|
|
|
|
lda hex2_l
|
|
cmp hex1_l ;Compare lower destination address half with lower end address half
|
|
bne read_next ;If not equal then increment destination address
|
|
|
|
lda hex2_h
|
|
cmp hex1_h ;Compare upper destination address half with upper end address half
|
|
bne read_next ;If not equal then proceed to read next byte
|
|
|
|
lda #last_command_read ;Set last command to READ
|
|
sta last_command
|
|
|
|
pla ;Restore X from stack
|
|
tax
|
|
|
|
jmp next_cmd ;Read is completed, proceed to next command
|
|
|
|
read_next
|
|
jsr increment_16bit ;Increment destination address
|
|
jmp read_byte
|
|
|
|
;-------------------------------------------------------------------------
|
|
; In-monitor Write procedure
|
|
;-------------------------------------------------------------------------
|
|
|
|
write
|
|
lda last_command
|
|
cmp #last_command_write
|
|
beq write_ready
|
|
jsr reset_serial ;Reset serial and give some time to stabilize
|
|
;This is required due to inability to guess what is the current device mode
|
|
;and prevents from polluting the output while setting the write mode
|
|
sta serial_write ;Enable write mode
|
|
write_ready
|
|
txa ;Preserve X on stack
|
|
pha
|
|
ldx #hex2_l
|
|
ldy #$00
|
|
|
|
write_byte
|
|
lda serial_ready
|
|
beq write_byte ;Not yet ready to write data
|
|
lda (hex2_l),Y ;Read byte from source address, this should be hex2_l but macro substitution doesn't work
|
|
sta serial_write ;Write byte
|
|
|
|
lda hex2_l
|
|
cmp hex1_l ;Compare lower source address half with lower end address half
|
|
bne write_next ;If not equal then increment source address
|
|
|
|
lda hex2_h
|
|
cmp hex1_h ;Compare upper source address half with upper end address half
|
|
bne write_next ;If not equal then proceed to write next byte
|
|
|
|
lda #last_command_write ;Set last command to WRITE
|
|
sta last_command
|
|
|
|
pla ;Restore X from stack
|
|
tax
|
|
|
|
jmp next_cmd ;Write is completed, proceed to next command
|
|
|
|
write_next
|
|
jsr increment_16bit ;Increment destination address
|
|
jmp write_byte
|
|
|
|
|
|
;-------------------------------------------------------------------------
|
|
; API read procedure
|
|
;-------------------------------------------------------------------------
|
|
|
|
api_read
|
|
jsr reset_serial
|
|
lda serial_read ;Enable read mode
|
|
ldy #$00
|
|
ldx #hex2_l
|
|
|
|
api_read_byte
|
|
lda serial_ready
|
|
beq api_read_byte ;No data arrived
|
|
lda serial_read ;Read byte
|
|
sta (hex2_l),Y ;Store byte under address, this should be hex2_l but macro substitution doesn't work
|
|
|
|
lda hex2_l
|
|
cmp hex1_l ;Compare lower destination address half with lower end address half
|
|
bne api_read_next ;If not equal then increment destination address
|
|
|
|
lda hex2_h
|
|
cmp hex1_h ;Compare upper destination address half with upper end address half
|
|
bne api_read_next ;If not equal then proceed to read next byte
|
|
|
|
rts ;Read is completed, return
|
|
|
|
api_read_next
|
|
jsr increment_16bit ;Increment destination address
|
|
jmp api_read_byte
|
|
|
|
;-------------------------------------------------------------------------
|
|
; API write procedure
|
|
;-------------------------------------------------------------------------
|
|
|
|
api_write
|
|
jsr reset_serial ;Reset serial and give some time to stabilize
|
|
;This is required due to inability to guess what is the current device mode
|
|
;and prevents from polluting the output while setting the write mode
|
|
sta serial_write ;Enable write mode
|
|
api_write_ready
|
|
ldx #hex2_l
|
|
ldy #$00
|
|
|
|
api_write_byte
|
|
lda serial_ready
|
|
beq api_write_byte ;Not yet ready to write data
|
|
lda (hex2_l),Y ;Read byte from source address, this should be hex2_l but macro substitution doesn't work
|
|
sta serial_write ;Write byte
|
|
|
|
lda hex2_l
|
|
cmp hex1_l ;Compare lower source address half with lower end address half
|
|
bne api_write_next ;If not equal then increment source address
|
|
|
|
lda hex2_h
|
|
cmp hex1_h ;Compare upper source address half with upper end address half
|
|
bne api_write_next ;If not equal then proceed to write next byte
|
|
|
|
rts ;Write is completed, return
|
|
|
|
api_write_next
|
|
jsr increment_16bit ;Increment destination address
|
|
jmp api_write_byte
|
|
|
|
|
|
;-------------------------------------------------------------------------
|
|
; tool routines
|
|
;-------------------------------------------------------------------------
|
|
|
|
reset_serial
|
|
txa ;Preserve X on stack
|
|
pha
|
|
|
|
tya ;Preserve Y on stack
|
|
pha
|
|
|
|
lda serial_reset ;Reset
|
|
ldx #$00
|
|
ldy #$00
|
|
reset_loop ; ~((2 + 2 + 3) * 255 + 2 + 3) * 255 =
|
|
nop ; 2 cycles
|
|
iny ; 2 cycles
|
|
bne reset_loop ; 3 cycles
|
|
inx ; 2 cycles
|
|
bne reset_loop ; 3 cycles
|
|
|
|
pla ;Restore Y from stack
|
|
tay
|
|
|
|
pla ;Restore X from stack
|
|
tax
|
|
rts
|
|
|
|
increment_16bit
|
|
txa
|
|
inc $00,X
|
|
bne increment_16bit_done
|
|
inx
|
|
inc $00,X
|
|
increment_16bit_done
|
|
tax
|
|
rts
|
|
|
|
;-------------------------------------------------------------------------
|
|
|
|
end_of_apple1serial
|
|
|
|
#include "src/tests.a65"
|
|
#include "src/serialmonitor.a65"
|