mirror of
https://github.com/bobbimanners/emailler.git
synced 2024-09-12 02:54:54 +00:00
git-svn-id: http://svn.code.sf.net/p/netboot65/code@223 93682198-c243-4bdb-bd91-e943c89aac3b
343 lines
6.4 KiB
ArmAsm
343 lines
6.4 KiB
ArmAsm
; XMODEM file transfer
|
|
|
|
.include "../inc/common.i"
|
|
.ifndef KPR_API_VERSION_NUMBER
|
|
.define EQU =
|
|
.include "../inc/kipper_constants.i"
|
|
.endif
|
|
|
|
|
|
XMODEM_BLOCK_SIZE=$80 ;how many bytes (excluding header & checksum) in each block?
|
|
XMODEM_TIMEOUT_SECONDS=5
|
|
XMODEM_MAX_ERRORS=10
|
|
SOH = $01
|
|
EOT = $04
|
|
ACK = $06
|
|
NAK = $15
|
|
CAN = $18
|
|
|
|
.export xmodem_receive
|
|
|
|
.import ip65_process
|
|
.import ip65_error
|
|
.import tcp_callback
|
|
.import copymem
|
|
.importzp copy_src
|
|
.importzp copy_dest
|
|
.import tcp_send
|
|
.import tcp_send_data_len
|
|
.import tcp_inbound_data_ptr
|
|
.import tcp_inbound_data_length
|
|
.import check_for_abort_key
|
|
.import print_a
|
|
.import print_cr
|
|
.import print_ascii_as_native
|
|
.import print_hex
|
|
|
|
.segment "SELF_MODIFIED_CODE"
|
|
got_byte:
|
|
jmp $ffff
|
|
|
|
next_char:
|
|
lda buffer_length
|
|
bne @not_eof
|
|
lda buffer_length+1
|
|
bne @not_eof
|
|
sec
|
|
rts
|
|
@not_eof:
|
|
next_char_ptr=*+1
|
|
lda $ffff
|
|
pha
|
|
inc next_char_ptr
|
|
bne :+
|
|
inc next_char_ptr+1
|
|
:
|
|
sec
|
|
lda buffer_length
|
|
sbc #1
|
|
sta buffer_length
|
|
lda buffer_length+1
|
|
sbc #0
|
|
sta buffer_length+1
|
|
pla
|
|
clc
|
|
|
|
rts
|
|
.bss
|
|
|
|
original_tcp_callback: .res 2
|
|
getc_timeout_end: .res 1
|
|
getc_timeout_seconds: .res 1
|
|
buffer_length: .res 2
|
|
|
|
.code
|
|
|
|
xmodem_receive:
|
|
;recieve a file via XMODEM (checksum mode only, not CRC)
|
|
;assumes that a tcp connection has already been set up, and that the other end is waiting to start sending
|
|
;inputs: AX points to routine to call once for each byte in downloaded file (e.g. save to disk, print to screen, whatever) - byte will be in A
|
|
;outputs: none
|
|
|
|
|
|
stax got_byte+1
|
|
lda #0
|
|
sta buffer_length
|
|
sta buffer_length+1
|
|
sta error_number
|
|
sta user_abort
|
|
lda #1
|
|
sta expected_block_number
|
|
|
|
|
|
ldax tcp_callback
|
|
stax original_tcp_callback
|
|
ldax #xmodem_receive_callback
|
|
stax tcp_callback
|
|
jsr send_nak
|
|
|
|
|
|
@next_block:
|
|
lda #0
|
|
sta block_ptr
|
|
sta checksum
|
|
ldax #expecting
|
|
jsr print_ascii_as_native
|
|
|
|
ldax #block_number_msg
|
|
jsr print_ascii_as_native
|
|
lda expected_block_number
|
|
jsr print_hex
|
|
jsr print_cr
|
|
|
|
@wait_for_block_start:
|
|
lda #XMODEM_TIMEOUT_SECONDS
|
|
jsr getc
|
|
bcc @got_block_start
|
|
lda user_abort
|
|
beq @no_user_abort
|
|
jmp @exit
|
|
@no_user_abort:
|
|
jsr send_nak
|
|
inc error_number
|
|
ldax #timeout_msg
|
|
jsr print_ascii_as_native
|
|
lda error_number
|
|
jsr print_hex
|
|
jsr print_cr
|
|
lda error_number
|
|
cmp #XMODEM_MAX_ERRORS
|
|
bcc @wait_for_block_start
|
|
lda #KPR_ERROR_TOO_MANY_ERRORS
|
|
sta ip65_error
|
|
jmp @exit
|
|
@got_block_start:
|
|
cmp #EOT
|
|
bne :+
|
|
jsr send_ack
|
|
clc
|
|
jmp @exit
|
|
:
|
|
cmp #SOH
|
|
bne @wait_for_block_start
|
|
|
|
;now get block number
|
|
lda #XMODEM_TIMEOUT_SECONDS
|
|
jsr getc
|
|
bcc :+
|
|
jsr send_nak
|
|
jmp @wait_for_block_start
|
|
:
|
|
sta actual_block_number
|
|
|
|
;now get block number check
|
|
lda #XMODEM_TIMEOUT_SECONDS
|
|
jsr getc
|
|
bcc :+
|
|
jsr send_nak
|
|
jmp @wait_for_block_start
|
|
:
|
|
adc actual_block_number
|
|
cmp #$ff
|
|
bne @wait_for_block_start
|
|
ldax #receiving
|
|
jsr print_ascii_as_native
|
|
|
|
ldax #block_number_msg
|
|
jsr print_ascii_as_native
|
|
lda actual_block_number
|
|
jsr print_hex
|
|
jsr print_cr
|
|
|
|
@next_byte:
|
|
lda #XMODEM_TIMEOUT_SECONDS
|
|
jsr getc
|
|
bcs @exit
|
|
ldx block_ptr
|
|
sta xmodem_block_buffer,x
|
|
adc checksum
|
|
sta checksum
|
|
|
|
inc block_ptr
|
|
lda block_ptr
|
|
bpl @next_byte
|
|
|
|
ldax #checksum_msg
|
|
jsr print_ascii_as_native
|
|
lda checksum
|
|
jsr print_hex
|
|
|
|
lda #'/'
|
|
jsr print_a
|
|
|
|
lda #XMODEM_TIMEOUT_SECONDS
|
|
jsr getc
|
|
bcs @exit
|
|
sta received_checksum
|
|
jsr print_hex
|
|
jsr print_cr
|
|
|
|
lda received_checksum
|
|
cmp checksum
|
|
beq @checksum_ok
|
|
jsr send_nak
|
|
jmp @next_block
|
|
|
|
@checksum_ok:
|
|
lda expected_block_number
|
|
cmp actual_block_number
|
|
bne @skip_block_output
|
|
|
|
lda #0
|
|
sta block_ptr
|
|
|
|
@output_byte:
|
|
ldx block_ptr
|
|
lda xmodem_block_buffer,x
|
|
jsr got_byte
|
|
inc block_ptr
|
|
lda block_ptr
|
|
bpl @output_byte
|
|
|
|
inc expected_block_number
|
|
|
|
@skip_block_output:
|
|
jsr send_ack
|
|
jmp @next_block
|
|
|
|
clc
|
|
@exit:
|
|
ldax original_tcp_callback
|
|
stax tcp_callback
|
|
|
|
rts
|
|
|
|
xmodem_receive_callback:
|
|
lda tcp_inbound_data_length+1
|
|
cmp #$ff
|
|
bne @not_eof
|
|
rts
|
|
@not_eof:
|
|
|
|
ldax tcp_inbound_data_ptr
|
|
stax copy_src
|
|
ldax #xmodem_stream_buffer
|
|
stax copy_dest
|
|
stax next_char_ptr
|
|
|
|
ldax tcp_inbound_data_length
|
|
stax buffer_length
|
|
jmp copymem
|
|
|
|
|
|
send_nak:
|
|
ldax #1
|
|
stax tcp_send_data_len
|
|
ldax #nak_packet
|
|
jmp tcp_send
|
|
|
|
send_ack:
|
|
ldax #1
|
|
stax tcp_send_data_len
|
|
ldax #ack_packet
|
|
jmp tcp_send
|
|
|
|
|
|
getc:
|
|
sta getc_timeout_seconds
|
|
|
|
clc
|
|
lda $dc09 ;time of day clock: seconds (in BCD)
|
|
sed
|
|
adc getc_timeout_seconds
|
|
cmp #$60
|
|
bcc @timeout_set
|
|
sec
|
|
sbc #$60
|
|
@timeout_set:
|
|
cld
|
|
sta getc_timeout_end
|
|
|
|
@poll_loop:
|
|
; inc $d021
|
|
jsr next_char
|
|
bcs @no_char
|
|
rts ;done!
|
|
@no_char:
|
|
jsr check_for_abort_key
|
|
bcc @no_abort
|
|
lda #KPR_ERROR_ABORTED_BY_USER
|
|
sta ip65_error
|
|
inc user_abort
|
|
rts
|
|
@no_abort:
|
|
jsr ip65_process
|
|
lda $dc09 ;time of day clock: seconds
|
|
cmp getc_timeout_end
|
|
bne @poll_loop
|
|
sec
|
|
rts
|
|
|
|
|
|
|
|
.rodata
|
|
ack_packet: .byte ACK
|
|
nak_packet: .byte NAK
|
|
|
|
block_number_msg: .byte " block $",0
|
|
expecting: .byte "expecting",0
|
|
receiving: .byte "receiving",0
|
|
bad_block_number: .byte "bad block number",0
|
|
checksum_msg: .byte "checksum $",0
|
|
timeout_msg: .byte "timeout $",0
|
|
|
|
.segment "APP_SCRATCH"
|
|
xmodem_stream_buffer: .res 1600
|
|
xmodem_block_buffer: .res 128
|
|
expected_block_number: .res 1
|
|
actual_block_number: .res 1
|
|
checksum: .res 1
|
|
received_checksum: .res 1
|
|
block_ptr: .res 1
|
|
error_number: .res 1
|
|
user_abort: .res 1
|
|
|
|
;-- LICENSE FOR xmodem.s --
|
|
; The contents of this file are subject to the Mozilla Public License
|
|
; Version 1.1 (the "License"); you may not use this file except in
|
|
; compliance with the License. You may obtain a copy of the License at
|
|
; http://www.mozilla.org/MPL/
|
|
;
|
|
; Software distributed under the License is distributed on an "AS IS"
|
|
; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
|
; License for the specific language governing rights and limitations
|
|
; under the License.
|
|
;
|
|
; The Original Code is ip65.
|
|
;
|
|
; The Initial Developer of the Original Code is Jonno Downes,
|
|
; jonno@jamtronix.com.
|
|
; Portions created by the Initial Developer are Copyright (C) 2009
|
|
; Jonno Downes. All Rights Reserved.
|
|
; -- LICENSE END --
|