diff --git a/client/inc/char_conv.i b/client/inc/char_conv.i new file mode 100644 index 0000000..3a5e7aa --- /dev/null +++ b/client/inc/char_conv.i @@ -0,0 +1,24 @@ +;ASCII/PETSCII conversion tables +;cribbed from http://www.ffd2.com/fridge/misc/petcom.c + + +.rodata +ascii_to_petscii_table: +.byte $00,$01,$02,$03,$04,$05,$06,$07,$14,$09,$0d,$11,$93,$0a,$0e,$0f +.byte $10,$0b,$12,$13,$08,$15,$16,$17,$18,$19,$1a,$1b,$1c,$1d,$1e,$1f +.byte $20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$2a,$2b,$2c,$2d,$2e,$2f +.byte $30,$31,$32,$33,$34,$35,$36,$37,$38,$39,$3a,$3b,$3c,$3d,$3e,$3f +.byte $40,$c1,$c2,$c3,$c4,$c5,$c6,$c7,$c8,$c9,$ca,$cb,$cc,$cd,$ce,$cf +.byte $d0,$d1,$d2,$d3,$d4,$d5,$d6,$d7,$d8,$d9,$da,$5b,$5c,$5d,$5e,$5f +.byte $c0,$41,$42,$43,$44,$45,$46,$47,$48,$49,$4a,$4b,$4c,$4d,$4e,$4f +.byte $50,$51,$52,$53,$54,$55,$56,$57,$58,$59,$5a,$db,$dc,$dd,$de,$df +.byte $80,$81,$82,$83,$84,$85,$86,$87,$88,$89,$8a,$8b,$8c,$8d,$8e,$8f +.byte $90,$91,$92,$0c,$94,$95,$96,$97,$98,$99,$9a,$9b,$9c,$9d,$9e,$9f +.byte $a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7,$a8,$a9,$aa,$ab,$ac,$ad,$ae,$af +.byte $b0,$b1,$b2,$b3,$b4,$b5,$b6,$b7,$b8,$b9,$ba,$bb,$bc,$bd,$be,$bf +.byte $60,$61,$62,$63,$64,$65,$66,$67,$68,$69,$6a,$6b,$6c,$6d,$6e,$6f +.byte $70,$71,$72,$73,$74,$75,$76,$77,$78,$79,$7a,$7b,$7c,$7d,$7e,$7f +.byte $e0,$e1,$e2,$e3,$e4,$e5,$e6,$e7,$e8,$e9,$ea,$eb,$ec,$ed,$ee,$ef +.byte $f0,$f1,$f2,$f3,$f4,$f5,$f6,$f7,$f8,$f9,$fa,$fb,$fc,$fd,$fe,$ff + + diff --git a/client/ip65/tcp.s b/client/ip65/tcp.s index 3f7e1df..9a02cdf 100644 --- a/client/ip65/tcp.s +++ b/client/ip65/tcp.s @@ -19,6 +19,10 @@ MAX_TCP_PACKETS_SENT=8 ;timeout after sending 8 messages will be about 7 sec .export tcp_send_data_len .export tcp_send +.export tcp_inbound_data_ptr +.export tcp_inbound_data_length +.export tcp_ack_number + .import ip_calc_cksum .import ip_send .import ip_create_packet @@ -113,6 +117,10 @@ tcp_send_data_len: .res 2 tcp_callback: .res 2 tcp_flags: .res 1 + +tcp_inbound_data_ptr: .res 2 +tcp_inbound_data_length: .res 2 + tcp_connect_sequence_number: .res 4 ;the seq number we will next send out tcp_connect_expected_ack_number: .res 4 ;what we expect to see in the next inbound ack tcp_connect_ack_number: .res 4 ;what we will next ack @@ -133,6 +141,10 @@ tcp_init: rts + +jmp_to_callback: + jmp (tcp_callback) + ;make outbound tcp connection ;inputs: ; tcp_connect_ip: destination ip address (4 bytes) @@ -522,6 +534,12 @@ tcp_process: sta tcp_state lda #NB65_ERROR_CONNECTION_RESET_BY_PEER sta ip65_error + + lda #$ff + sta tcp_inbound_data_length + sta tcp_inbound_data_length+1 + jsr jmp_to_callback ;let the caller see the connection has closed + @not_current_connection_on_rst: ;if we get a reset for a closed or nonexistent connection, then ignore it rts @@ -532,7 +550,11 @@ tcp_process: ;it's a SYN/ACK jsr check_current_connection - bcs @not_current_connection_on_syn_ack + bcc @current_connection_on_syn_ack + ;if we get a SYN/ACK for something that aint the connection we're expecting, + ;terminate with extreme prejudice + jmp @send_rst +@current_connection_on_syn_ack: lda tcp_state cmp #tcp_cxn_state_syn_sent bne @not_expecting_syn_ack @@ -553,22 +575,29 @@ tcp_process: lda #tcp_cxn_state_established sta tcp_state + @not_expecting_syn_ack: +;we get a SYN/ACK for the current connection, +;but we're not expecting it, it's probably +;a retransmist - just ACK it jmp @send_ack -@not_current_connection_on_syn_ack: - ;just ignore - rts + + @not_syn_ack: ;is it an ACK - alone or with PSH/URGENT but not a SYN/ACK? lda #tcp_flag_ACK bit tcp_inp+tcp_flags_field - beq @not_ack - + bne @ack + jmp @not_ack +@ack: ;is this the current connection? jsr check_current_connection - bcs @not_current_connection_on_ack - + bcc @current_connection_on_ack + ;if we get an ACK for something that is not the current connection + ;we should send a RST + jmp @send_rst +@current_connection_on_ack: ;if it's an ACK, then record the last ACK (reorder the bytes in the process) ldx #3 ; copy seq & ack fields (in reverse order) ldy #0 @@ -594,33 +623,112 @@ tcp_process: sta acc16 lda ip_inp+ip_len ;payload length (hi byte) sta acc16+1 - lda tcp_inp+tcp_header_length ;high 4 bites is header length in 32 bit words + lda tcp_inp+tcp_header_length ;high 4 bits is header length in 32 bit words lsr ; A=A/2 lsr ; A=A/2 clc ; A now equal to tcp header length in bytes adc #20 ;add 20 bytes for IP header. this gives length of IP +TCP headers ldx #0 + sta tcp_header_length jsr sub_16_16 - ;acc16 now contains the length of data in this TCP packet + + ;acc16 now contains the length of data in this TCP packet + lda acc16 - bne @not_empty_packet + beq @empty_packet lda acc16+1 beq @empty_packet @not_empty_packet: - .byte $92 - jmp @send_ack -@empty_packet: - rts -;FIXME -; - move ack ptr along -; - send ack -; - do a callback + sta tcp_inbound_data_length+1 + lda acc16 + sta tcp_inbound_data_length -@not_expected_seq_number: -@not_current_connection_on_ack: - rts + ;calculate ptr to tcp data + clc + lda tcp_header_length + adc #ip_inp + adc #0 + sta tcp_inbound_data_ptr+1 + + ; do a callback + jsr jmp_to_callback + + + ; move ack ptr along + ldax #tcp_connect_ack_number + stax acc32 + ldax tcp_inbound_data_length + jsr add_16_32 +@not_expected_seq_number: ;send an ACK with the sequence number we expect + + + ;send the ACK for any data in this packet, then return to check for FIN flag + jsr @send_ack + +@empty_packet: @not_ack: + +;is it a FIN? + lda #tcp_flag_FIN + bit tcp_inp+tcp_flags_field + bne @fin + jmp @not_fin +@fin: + + ;is this the current connection? + jsr check_current_connection + bcc :+ + jmp @send_rst ;reset if not current connection +: + ldx #3 ; copy seq field (in reverse order) + ldy #0 +: lda tcp_inp + tcp_seq,y + sta tcp_connect_last_received_seq_number,x + iny + dex + bpl :- + + ;was this the next sequence number we're waiting for? + ldax #tcp_connect_ack_number + stax acc32 + ldax #tcp_connect_last_received_seq_number + stax op32 + jsr cmp_32_32 + + beq :+ + rts ;bail if not expected sequence number +: + + ;set the length to $ffff + lda #$ff + sta tcp_inbound_data_length + sta tcp_inbound_data_length+1 + jsr jmp_to_callback ;let the caller see the connection has closed + + ; move ack ptr along + ldax #tcp_connect_ack_number + stax acc32 + ldax #$01 + jsr add_16_32 + + lda #tcp_cxn_state_closed + sta tcp_state + + ;send an ACK + jsr @send_ack + + ;send a FIN + lda #tcp_flag_FIN + jmp @send_packet + +@not_expected_seq_number_in_fin: ;send an ACK with the sequence number we expect + rts + +@not_fin: + lda tcp_inp+tcp_flags_field cmp #tcp_flag_SYN bne @not_syn @@ -672,6 +780,8 @@ tcp_process: @send_ack: ;create an ACK packet lda #tcp_flag_ACK + +@send_packet: sta tcp_flags ldax #0 stax tcp_data_len @@ -690,5 +800,4 @@ tcp_process: stax tcp_remote_port - jsr tcp_send_packet - rts + jmp tcp_send_packet diff --git a/client/test/Makefile b/client/test/Makefile index e4ba863..ba2d971 100644 --- a/client/test/Makefile +++ b/client/test/Makefile @@ -39,7 +39,7 @@ all: \ $(LD) -m $*.map -vm -C ../cfg/c64prg.cfg -o $*.prg $(AFLAGS) $< $(IP65LIB) $(C64PROGLIB) test_tcp.prg: test_tcp.o $(IP65TCPLIB) $(C64PROGLIB) $(INCFILES) ../cfg/c64prg.cfg - $(LD) -m $*.map -vm -C ../cfg/c64prg.cfg -o test_tcp.prg $(AFLAGS) $< $(IP65TCPLIB) $(C64PROGLIB) + $(LD) -m test_tcp.map -vm -C ../cfg/c64prg.cfg -o test_tcp.prg $(AFLAGS) $< $(IP65TCPLIB) $(C64PROGLIB) %.pg2: %.o $(IP65LIB) $(APPLE2PROGLIB) $(INCFILES) ../cfg/a2bin.cfg $(LD) -C ../cfg/a2bin.cfg -o $*.pg2 $(AFLAGS) $< $(IP65LIB) $(APPLE2PROGLIB) diff --git a/client/test/test_tcp.s b/client/test/test_tcp.s index 7521c66..487396a 100644 --- a/client/test/test_tcp.s +++ b/client/test/test_tcp.s @@ -1,6 +1,7 @@ .include "../inc/common.i" .include "../inc/commonprint.i" .include "../inc/net.i" + .include "../inc/char_conv.i" .import exit_to_basic @@ -15,6 +16,9 @@ .import tcp_connect .import tcp_connect_ip + .import tcp_inbound_data_ptr + .import tcp_inbound_data_length + .import tcp_send .import tcp_send_data_len @@ -56,6 +60,15 @@ basicstub: .word __CODE_SIZE__+__RODATA_SIZE__+__DATA_SIZE__+4 ; Size jmp init +.bss +cxn_closed: .res 1 +byte_counter: .res 1 + +.data +get_next_byte: + lda $ffff + rts + .code init: @@ -226,8 +239,9 @@ init: ldax tcp_dest_ip+2 stax tcp_connect_ip+2 - - jmp @skip_past_normal_http + + lda #0 + sta cxn_closed ldax #80 jsr tcp_connect jsr check_for_error @@ -238,6 +252,14 @@ init: jsr tcp_send jsr check_for_error +@loop_till_end: + jsr ip65_process + lda cxn_closed + cmp #1 + beq @loop_till_end + + + ldax #tcp_callback_routine stax tcp_callback ldax tcp_dest_ip @@ -246,9 +268,6 @@ init: stax tcp_connect_ip+2 -@skip_past_normal_http: - ; connect to port 80 again, and send GET in 2 parts - ldax #80 jsr tcp_connect @@ -265,7 +284,6 @@ init: jsr tcp_send jsr check_for_error -; .byte $92 ldax #looping jsr print @@ -275,7 +293,50 @@ init: rts tcp_callback_routine: + + + lda tcp_inbound_data_length + cmp #$ff + bne @not_end_of_file + lda #1 + sta cxn_closed rts + +@not_end_of_file: + lda #14 + jsr print_a ;switch to lower case + + + ldax tcp_inbound_data_ptr + stax get_next_byte+1 + + lda #0 + sta byte_counter + sta byte_counter+1 + +@print_one_byte: + jsr get_next_byte + tax + lda ascii_to_petscii_table,x + + jsr print_a + inc get_next_byte+1 + bne :+ + inc get_next_byte+2 +: + + inc byte_counter + bne :+ + inc byte_counter+1 +: + ldax byte_counter + stax acc16 + ldax tcp_inbound_data_length + jsr cmp_16_16 + bne @print_one_byte + + rts + check_for_error: @@ -511,7 +572,7 @@ number16: tcp_dest_ip: -; .byte 10,5,1,1 + ; .byte 10,5,1,1 .byte 74,207,242,229 error_code: .asciiz "ERROR CODE: $" @@ -519,6 +580,8 @@ looping: .asciiz "LOOPING..." http_get_msg: - .byte "GET / HTTP/1.0",13,10,13,10 + .byte "GET /blogx/ HTTP/1.0",13,10,13,10 http_get_msg_end: - http_get_length=http_get_msg_end-http_get_msg \ No newline at end of file + http_get_length=http_get_msg_end-http_get_msg + + \ No newline at end of file diff --git a/client/uthernet/bankswitch_eeprom.s b/client/uthernet/bankswitch_eeprom.s new file mode 100644 index 0000000..6de6b95 --- /dev/null +++ b/client/uthernet/bankswitch_eeprom.s @@ -0,0 +1,30 @@ +.segment "C800_0" +.asciiz "BANK $00" +.segment "C800_1" +.asciiz "BANK $01" +.segment "C800_2" +.asciiz "BANK $02" +.segment "C800_3" +.asciiz "BANK $03" +.segment "C800_4" +.asciiz "BANK $04" +.segment "C800_5" +.asciiz "BANK $05" +.segment "C800_6" +.asciiz "BANK $06" +.segment "C800_7" +.asciiz "BANK $07" +.segment "C800_8" +.asciiz "BANK $08" +.segment "C800_9" +.asciiz "BANK $09" +.segment "C800_A" +.asciiz "BANK $0A" +.segment "C800_B" +.asciiz "BANK $0B" +.segment "C800_C" +.asciiz "BANK $0C" +.segment "C800_D" +.asciiz "BANK $0D" +.segment "C800_E" +.asciiz "BANK $0E" diff --git a/dist/update_netboot65_web.bat b/dist/update_netboot65_web.bat new file mode 100644 index 0000000..9916fdf --- /dev/null +++ b/dist/update_netboot65_web.bat @@ -0,0 +1 @@ +pscp netboot65/doc/* jonnosan,netboot65@web.sourceforge.net:htdocs/