#ifndef BASE #define BASE $C000 #endif #ifndef OFFSET #define OFFSET 0 #endif ;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 BASE + OFFSET #define serial_reset BASE + $1 + OFFSET #define serial_read BASE + $80 + OFFSET #define serial_write BASE + $81 + OFFSET #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 + OFFSET, 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 * = BASE + $100 + OFFSET 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"