mirror of
https://github.com/bobbimanners/emailler.git
synced 2024-11-18 21:07:03 +00:00
544 lines
9.5 KiB
ArmAsm
544 lines
9.5 KiB
ArmAsm
|
;use the NB65 API to send a d64 disk via TFTP
|
||
|
;
|
||
|
;
|
||
|
|
||
|
.ifndef NB65_API_VERSION_NUMBER
|
||
|
.define EQU =
|
||
|
.include "../inc/nb65_constants.i"
|
||
|
.endif
|
||
|
|
||
|
.include "../ip65/copymem.s"
|
||
|
.include "../inc/common.i"
|
||
|
|
||
|
.import print_a
|
||
|
.import get_key
|
||
|
.import get_filtered_input
|
||
|
.import filter_dns
|
||
|
.macro cout arg
|
||
|
lda arg
|
||
|
jsr print_a
|
||
|
.endmacro
|
||
|
|
||
|
;######### KERNEL functions
|
||
|
CHKIN = $ffc6
|
||
|
CHKOUT = $ffc9
|
||
|
CHRIN = $ffcf
|
||
|
CHROUT = $ffd2
|
||
|
CLALL = $FFE7
|
||
|
CLOSE = $ffc3
|
||
|
OPEN = $ffc0
|
||
|
READST = $ffb7
|
||
|
SETNAM = $ffbd
|
||
|
SETLFS = $ffba
|
||
|
|
||
|
.bss
|
||
|
current_byte: .res 1
|
||
|
track: .res 1
|
||
|
sector: .res 1
|
||
|
sectors_in_track: .res 1
|
||
|
error_buffer: .res 128
|
||
|
|
||
|
command_buffer: .res 128
|
||
|
sector_buffer: .res 256
|
||
|
nb65_param_buffer: .res $20
|
||
|
sector_buffer_address: .res 2
|
||
|
|
||
|
.zeropage
|
||
|
temp_ptr: .res 2
|
||
|
|
||
|
.segment "STARTUP" ;this is what gets put at the start of the file on the C64
|
||
|
|
||
|
.word basicstub ; load address
|
||
|
|
||
|
.macro print arg
|
||
|
ldax arg
|
||
|
ldy #NB65_PRINT_ASCIIZ
|
||
|
jsr NB65_DISPATCH_VECTOR
|
||
|
.endmacro
|
||
|
|
||
|
.macro print_cr
|
||
|
lda #13
|
||
|
jsr print_a
|
||
|
.endmacro
|
||
|
|
||
|
.macro call arg
|
||
|
ldy arg
|
||
|
jsr NB65_DISPATCH_VECTOR
|
||
|
.endmacro
|
||
|
|
||
|
basicstub:
|
||
|
.word @nextline
|
||
|
.word 2003
|
||
|
.byte $9e
|
||
|
.byte <(((init / 1000) .mod 10) + $30)
|
||
|
.byte <(((init / 100 ) .mod 10) + $30)
|
||
|
.byte <(((init / 10 ) .mod 10) + $30)
|
||
|
.byte <(((init ) .mod 10) + $30)
|
||
|
.byte 0
|
||
|
@nextline:
|
||
|
.word 0
|
||
|
|
||
|
|
||
|
;look for NB65 signature at location pointed at by AX
|
||
|
look_for_signature:
|
||
|
stax temp_ptr
|
||
|
ldy #3
|
||
|
@check_one_byte:
|
||
|
lda (temp_ptr),y
|
||
|
cmp nb65_signature,y
|
||
|
bne @bad_match
|
||
|
dey
|
||
|
bpl@check_one_byte
|
||
|
clc
|
||
|
rts
|
||
|
@bad_match:
|
||
|
sec
|
||
|
rts
|
||
|
init:
|
||
|
|
||
|
print #signon_message
|
||
|
|
||
|
ldax #NB65_CART_SIGNATURE ;where signature should be in cartridge
|
||
|
jsr look_for_signature
|
||
|
bcc @found_nb65_signature
|
||
|
|
||
|
ldax #NB65_RAM_STUB_SIGNATURE ;where signature should be in RAM
|
||
|
jsr look_for_signature
|
||
|
bcc :+
|
||
|
jmp nb65_signature_not_found
|
||
|
:
|
||
|
jsr NB65_RAM_STUB_ACTIVATE ;we need to turn on NB65 cartridge
|
||
|
|
||
|
@found_nb65_signature:
|
||
|
|
||
|
print #initializing
|
||
|
print #nb65_signature
|
||
|
ldy #NB65_INITIALIZE
|
||
|
jsr NB65_DISPATCH_VECTOR
|
||
|
bcc :+
|
||
|
print #failed
|
||
|
jsr print_nb65_errorcode
|
||
|
jmp bad_boot
|
||
|
:
|
||
|
print #ok
|
||
|
print_cr
|
||
|
|
||
|
; ########################
|
||
|
; main program goes here:
|
||
|
;
|
||
|
|
||
|
jsr CLALL
|
||
|
|
||
|
|
||
|
; ldx #18
|
||
|
; stx track
|
||
|
; ldx #1
|
||
|
; stx sector
|
||
|
; ldx #21
|
||
|
; stx sectors_in_track
|
||
|
; ldax #sector_buffer
|
||
|
; jsr send_next_block
|
||
|
; rts
|
||
|
|
||
|
|
||
|
@send_1_image:
|
||
|
lda #$93 ;cls
|
||
|
jsr print_a
|
||
|
print #signon_message
|
||
|
jsr reset_counters_to_first_sector
|
||
|
print #enter_filename
|
||
|
ldax #filter_dns ;this is pretty close to being a filter for legal chars in file names as well
|
||
|
jsr get_filtered_input
|
||
|
bcs @no_filename_entered
|
||
|
stax nb65_param_buffer+NB65_TFTP_FILENAME
|
||
|
print #position_cursor_for_track_display
|
||
|
ldax #send_next_block
|
||
|
stax nb65_param_buffer+NB65_TFTP_POINTER
|
||
|
ldax #nb65_param_buffer
|
||
|
call #NB65_TFTP_CALLBACK_UPLOAD
|
||
|
bcc :+
|
||
|
print_cr
|
||
|
print #failed
|
||
|
jmp print_nb65_errorcode
|
||
|
:
|
||
|
lda #15 ; filenumber 15 - command channel
|
||
|
jsr CLOSE
|
||
|
print_cr
|
||
|
print #ok
|
||
|
print #press_a_key_to_continue
|
||
|
jsr get_key
|
||
|
jmp @send_1_image ;done! so go again
|
||
|
@no_filename_entered:
|
||
|
rts
|
||
|
|
||
|
|
||
|
send_next_block:
|
||
|
;tftp upload callback routine
|
||
|
;AX will point to address to fill
|
||
|
stax sector_buffer_address
|
||
|
lda track
|
||
|
cmp #36
|
||
|
beq @past_last_track
|
||
|
print #position_cursor_for_track_display
|
||
|
jsr print_current_sector
|
||
|
jsr read_sector
|
||
|
lda #$30
|
||
|
cmp error_buffer
|
||
|
bne @was_an_error
|
||
|
@after_error_check:
|
||
|
jsr move_to_next_sector
|
||
|
bcc @not_last_sector
|
||
|
ldax #$100
|
||
|
rts
|
||
|
@not_last_sector:
|
||
|
|
||
|
; jsr dump_sector ;DEBUG
|
||
|
|
||
|
inc sector_buffer_address+1
|
||
|
jsr read_sector
|
||
|
jsr move_to_next_sector
|
||
|
ldax #$200
|
||
|
|
||
|
; jsr dump_sector ;DEBUG
|
||
|
|
||
|
rts
|
||
|
@past_last_track:
|
||
|
ldax #$0000
|
||
|
rts
|
||
|
|
||
|
@was_an_error:
|
||
|
print #position_cursor_for_error_display
|
||
|
print #drive_error
|
||
|
print_cr
|
||
|
jsr print_current_sector
|
||
|
print #error_buffer
|
||
|
jmp @after_error_check
|
||
|
|
||
|
print_current_sector:
|
||
|
print #track_no
|
||
|
lda track
|
||
|
jsr byte_to_ascii
|
||
|
pha
|
||
|
txa
|
||
|
jsr print_a
|
||
|
pla
|
||
|
jsr print_a
|
||
|
print #sector_no
|
||
|
lda sector
|
||
|
jsr byte_to_ascii
|
||
|
pha
|
||
|
txa
|
||
|
jsr print_a
|
||
|
pla
|
||
|
jsr print_a
|
||
|
print_cr
|
||
|
rts
|
||
|
|
||
|
|
||
|
|
||
|
dump_sector:
|
||
|
;hex dump sector
|
||
|
lda #0
|
||
|
sta current_byte
|
||
|
@dump_byte:
|
||
|
ldy current_byte
|
||
|
lda sector_buffer,y
|
||
|
call #NB65_PRINT_HEX
|
||
|
inc current_byte
|
||
|
bne @dump_byte
|
||
|
rts
|
||
|
|
||
|
read_sector:
|
||
|
;routine to read a sector cribbed from http://codebase64.org/doku.php?id=base:reading_a_sector_from_disk
|
||
|
; - requires track and sector values be set first
|
||
|
; sector will be written to address whos value is stored in sector_data
|
||
|
; open the channel file
|
||
|
|
||
|
jsr make_read_sector_command
|
||
|
|
||
|
lda #1
|
||
|
ldx #<cname
|
||
|
ldy #>cname
|
||
|
jsr SETNAM
|
||
|
lda #02
|
||
|
ldx #08
|
||
|
ldy #02
|
||
|
jsr SETLFS
|
||
|
jsr OPEN
|
||
|
bcs @error
|
||
|
ldx #<command_buffer
|
||
|
ldy #>command_buffer
|
||
|
lda #12
|
||
|
jsr SETNAM
|
||
|
lda #15
|
||
|
ldx $BA ;use whatever was last device #
|
||
|
ldy #15
|
||
|
jsr SETLFS
|
||
|
jsr OPEN
|
||
|
bcs @error
|
||
|
|
||
|
|
||
|
jsr check_error_channel
|
||
|
lda #$30
|
||
|
cmp error_buffer
|
||
|
beq @was_not_an_error
|
||
|
print #error_buffer
|
||
|
|
||
|
@was_not_an_error:
|
||
|
ldx #$02 ; filenumber 2
|
||
|
jsr CHKIN ;(file 2 now used as input)
|
||
|
|
||
|
lda sector_buffer_address
|
||
|
sta temp_ptr
|
||
|
lda sector_buffer_address+1
|
||
|
sta temp_ptr+1
|
||
|
ldy #$00
|
||
|
@loop:
|
||
|
jsr CHRIN ;(get a byte from file)
|
||
|
sta (temp_ptr),Y ; write byte to memory
|
||
|
iny
|
||
|
bne @loop ; next byte, end when 256 bytes are read
|
||
|
@close:
|
||
|
lda #15 ; filenumber 15
|
||
|
jsr CLOSE
|
||
|
lda #$02 ; filenumber 2
|
||
|
jsr CLOSE
|
||
|
ldx #$00 ; filenumber 0 = keyboard
|
||
|
jsr CHKIN ;(keyboard now input device again)
|
||
|
rts
|
||
|
@error:
|
||
|
pha
|
||
|
print #error_opening_channel
|
||
|
pla
|
||
|
call #NB65_PRINT_HEX
|
||
|
jmp @close
|
||
|
|
||
|
check_error_channel:
|
||
|
LDX #$0F ; filenumber 15
|
||
|
JSR CHKIN ;(file 15 now used as input)
|
||
|
LDY #$00
|
||
|
@loop:
|
||
|
JSR READST ;(read status byte)
|
||
|
BNE @eof ; either EOF or read error
|
||
|
JSR CHRIN ;(get a byte from file)
|
||
|
sta error_buffer,y
|
||
|
iny
|
||
|
JMP @loop ; next byte
|
||
|
|
||
|
@eof:
|
||
|
lda #0
|
||
|
sta error_buffer,y
|
||
|
LDX #$00 ; filenumber 0 = keyboard
|
||
|
JSR CHKIN ;(keyboard now input device again)
|
||
|
RTS
|
||
|
|
||
|
bad_boot:
|
||
|
print #press_a_key_to_continue
|
||
|
restart:
|
||
|
jsr get_key
|
||
|
jmp $fce2 ;do a cold start
|
||
|
|
||
|
|
||
|
print_a_as_errorcode:
|
||
|
pha
|
||
|
lda #' '
|
||
|
jsr print_a
|
||
|
print #error_code
|
||
|
pla
|
||
|
call #NB65_PRINT_HEX
|
||
|
rts
|
||
|
|
||
|
print_nb65_errorcode:
|
||
|
print #error_code
|
||
|
call #NB65_GET_LAST_ERROR
|
||
|
call #NB65_PRINT_HEX
|
||
|
print_cr
|
||
|
rts
|
||
|
|
||
|
nb65_signature_not_found:
|
||
|
|
||
|
ldy #0
|
||
|
:
|
||
|
lda nb65_signature_not_found_message,y
|
||
|
beq restart
|
||
|
jsr print_a
|
||
|
iny
|
||
|
jmp :-
|
||
|
|
||
|
|
||
|
|
||
|
make_read_sector_command:
|
||
|
;fill command buffer with command to read in track & sector
|
||
|
;returns length of command in Y
|
||
|
|
||
|
ldy #0
|
||
|
lda #85 ;"U"
|
||
|
sta command_buffer,y
|
||
|
iny
|
||
|
lda #$31 ;"1"
|
||
|
sta command_buffer,y
|
||
|
iny
|
||
|
lda #$20 ;" "
|
||
|
sta command_buffer,y
|
||
|
iny
|
||
|
lda #$32 ;"2" - file number
|
||
|
sta command_buffer,y
|
||
|
iny
|
||
|
lda #$20 ;" "
|
||
|
sta command_buffer,y
|
||
|
iny
|
||
|
lda #$30 ;"0" - drive number
|
||
|
sta command_buffer,y
|
||
|
iny
|
||
|
lda #$20 ;" "
|
||
|
sta command_buffer,y
|
||
|
iny
|
||
|
lda track
|
||
|
jsr byte_to_ascii
|
||
|
pha
|
||
|
txa
|
||
|
sta command_buffer,y
|
||
|
pla
|
||
|
iny
|
||
|
sta command_buffer,y
|
||
|
iny
|
||
|
lda #$20 ;" "
|
||
|
sta command_buffer,y
|
||
|
iny
|
||
|
lda sector
|
||
|
jsr byte_to_ascii
|
||
|
pha
|
||
|
txa
|
||
|
sta command_buffer,y
|
||
|
pla
|
||
|
iny
|
||
|
sta command_buffer,y
|
||
|
iny
|
||
|
|
||
|
lda #0
|
||
|
sta command_buffer,y ;make it ASCIIZ so we can print it
|
||
|
|
||
|
rts
|
||
|
|
||
|
byte_to_ascii:
|
||
|
cmp #30
|
||
|
bmi @not_30
|
||
|
ldx #$33
|
||
|
clc
|
||
|
adc #18
|
||
|
rts
|
||
|
@not_30:
|
||
|
cmp #20
|
||
|
bmi @not_20
|
||
|
ldx #$32
|
||
|
clc
|
||
|
adc #28
|
||
|
rts
|
||
|
@not_20:
|
||
|
cmp #10
|
||
|
bmi @not_10
|
||
|
ldx #$31
|
||
|
clc
|
||
|
adc #38
|
||
|
rts
|
||
|
@not_10:
|
||
|
ldx #$30
|
||
|
clc
|
||
|
adc #48
|
||
|
rts
|
||
|
|
||
|
|
||
|
reset_counters_to_first_sector:
|
||
|
ldx #1
|
||
|
stx track
|
||
|
dex
|
||
|
stx sector
|
||
|
ldx #21
|
||
|
stx sectors_in_track
|
||
|
rts
|
||
|
|
||
|
move_to_next_sector:
|
||
|
inc sector
|
||
|
lda sector
|
||
|
cmp sectors_in_track
|
||
|
beq @move_to_next_track
|
||
|
rts
|
||
|
@move_to_next_track:
|
||
|
lda #0
|
||
|
sta sector
|
||
|
inc track
|
||
|
lda track
|
||
|
cmp #18
|
||
|
bne @not_track_18
|
||
|
lda #19
|
||
|
sta sectors_in_track
|
||
|
clc
|
||
|
rts
|
||
|
@not_track_18:
|
||
|
cmp #25
|
||
|
bne @not_track_25
|
||
|
lda #18
|
||
|
sta sectors_in_track
|
||
|
clc
|
||
|
rts
|
||
|
@not_track_25:
|
||
|
cmp #31
|
||
|
bne @not_track_31
|
||
|
lda #17
|
||
|
sta sectors_in_track
|
||
|
clc
|
||
|
rts
|
||
|
@not_track_31:
|
||
|
lda track
|
||
|
cmp #36 ;carry will be set if hit track 36
|
||
|
rts
|
||
|
|
||
|
|
||
|
.rodata
|
||
|
|
||
|
error_code:
|
||
|
.byte "ERROR CODE: $",0
|
||
|
press_a_key_to_continue:
|
||
|
.byte "PRESS A KEY TO CONTINUE",13,0
|
||
|
|
||
|
failed:
|
||
|
.byte "FAILED ", 0
|
||
|
|
||
|
ok:
|
||
|
.byte "OK ", 0
|
||
|
|
||
|
initializing:
|
||
|
.byte "INITIALIZING ",0
|
||
|
track_no:
|
||
|
.byte "TRACK ",0
|
||
|
|
||
|
|
||
|
sector_no:
|
||
|
.byte " SECTOR ",0
|
||
|
|
||
|
signon_message:
|
||
|
.byte "D64 UPLOADER V0.1",13,0
|
||
|
|
||
|
enter_filename:
|
||
|
.byte "SEND AS: ",0
|
||
|
|
||
|
drive_error:
|
||
|
.byte "DRIVE ACCESS ERROR - ",0
|
||
|
nb65_signature_not_found_message:
|
||
|
.byte "NO NB65 API FOUND",13,"PRESS ANY KEY TO RESET", 0
|
||
|
error_opening_channel:
|
||
|
.byte "ERROR OPENING CHANNEL $",0
|
||
|
|
||
|
disk_access:
|
||
|
.byte 13,13,13,13,13,"SENDING TO CHANNEL $",0
|
||
|
|
||
|
nb65_signature:
|
||
|
.byte $4E,$42,$36,$35 ; "NB65" - API signature
|
||
|
.byte ' ',0 ; so we can use this as a string
|
||
|
position_cursor_for_track_display:
|
||
|
; .byte $13,13,13,13,13,13,13,13,13,13,13," SENDING ",0
|
||
|
.byte $13,13,13,"SENDING ",0
|
||
|
position_cursor_for_error_display:
|
||
|
.byte $13,13,13,13,"LAST ",0
|
||
|
|
||
|
cname: .byte '#'
|