diff --git a/client/Makefile b/client/Makefile index 3099b42..67e88a1 100644 --- a/client/Makefile +++ b/client/Makefile @@ -1,5 +1,3 @@ -TARGET=c64 - .PHONY: ip65 drivers test clean distclean kipperterm2 examples carts basic wiznet diff --git a/client/basic/Makefile b/client/basic/Makefile index e676dab..62c3a66 100644 --- a/client/basic/Makefile +++ b/client/basic/Makefile @@ -13,8 +13,9 @@ INCFILES=\ IP65LIB=../ip65/ip65_tcp.lib C64RRNETLIB=../drivers/c64rrnet.lib +VIC20RRNETLIB=../drivers/vic20rrnet.lib -all: ip65 kipperbas.d64 bails.d64 +all: ip65 kipperbas.d64 bails.d64 kipperbasv20.prg ip65: make -C ../ip65 all @@ -24,6 +25,9 @@ ip65: %.prg: %.o $(IP65LIB) $(C64RRNETLIB) $(INCFILES) ../cfg/kipperbas.cfg $(LD) -m $*.map -vm -C ../cfg/kipperbas.cfg -o $*.prg $(AFLAGS) $< $(IP65LIB) $(C64RRNETLIB) + +kipperbasv20.prg: kipperbasv20.o $(IP65LIB) $(VIC20RRNETLIB) $(INCFILES) ../cfg/kipperbasv20.cfg + $(LD) -m kipperbasv20.map -vm -C ../cfg/kipperbasv20.cfg -o kipperbasv20.prg $(AFLAGS) $< $(IP65LIB) $(VIC20RRNETLIB) bails.d64: bails.prg diff --git a/client/basic/bails.d64 b/client/basic/bails.d64 index 27ce143..db8a795 100644 Binary files a/client/basic/bails.d64 and b/client/basic/bails.d64 differ diff --git a/client/basic/kipperbas.d64 b/client/basic/kipperbas.d64 index 9e4d311..89e9b36 100644 Binary files a/client/basic/kipperbas.d64 and b/client/basic/kipperbas.d64 differ diff --git a/client/basic/kipperbasv20.s b/client/basic/kipperbasv20.s new file mode 100644 index 0000000..8e4f0ee --- /dev/null +++ b/client/basic/kipperbasv20.s @@ -0,0 +1,1658 @@ + +.ifndef SCREEN_WIDTH + SCREEN_WIDTH = 22 +.endif + +.include "../inc/common.i" +.ifndef KPR_API_VERSION_NUMBER + .define EQU = + .include "../inc/kipper_constants.i" +.endif + +VARTAB = $2D ;BASIC variable table storage +ARYTAB = $2F ;BASIC array table storage +FREETOP = $33 ;bottom of string text storage area +MEMSIZ = $37 ;highest address used by BASIC +VARNAM = $45 ;current BASIC variable name +VARPNT = $47 ; pointer to current BASIC variable value + +SETNAM = $FFBD +SETLFS = $FFBA +OPEN = $FFC0 +CHKIN = $FFC6 +READST = $FFB7 ; read status byte +CHRIN = $FFCF ; get a byte from file +CLOSE = $FFC3 +MEMTOP = $FE25 +TXTPTR = $7A ;BASIC text pointer +IERROR = $0300 +ICRUNCH = $0304 ;Crunch ASCII into token +IQPLOP = $0306 ;List +IGONE = $0308 ;Execute next BASIC token +IEVAL = $30A ; evaluate expression +CHRGET = $73 +CHRGOT = $79 +CHROUT = $FFD2 +GETBYT = $D79E ;BASIC routine +GETPAR = $D7EB ;Get a 16,8 pair of numbers +CHKCOM = $CEFD +NEW = $C642 +CLR = $C65E +NEWSTT = $C7AE +GETVAR = $D0E7 ;find or create a variable +FRMEVL = $CD9E ;evaluate expression +FRESTR = $D6A3 ;free temporary string +FRMNUM = $CD8A ;get a number +GETADR = $D7F7 ;convert number to 16 bit integer +INLIN = $C560 ; read a line from keyboard + +VALTYP=$0D ;00=number, $FF=string + +LINNUM = $14 ;Number returned by GETPAR + +crunched_line = $0200 ;Input buffer + +.import copymem +.importzp copy_src +.importzp copy_dest +.import dhcp_init +.import ip65_init +.import cfg_get_configuration_ptr +.import tcp_listen +.import tcp_callback +.import tcp_connect_ip +.import tcp_send +.import tcp_connect +.import tcp_close +.import tcp_send_data_len +.import tcp_inbound_data_ptr +.import tcp_inbound_data_length +.import dns_set_hostname +.import dns_resolve +.import dns_ip +.import ip65_process +.import ip65_error +.import cfg_ip +.import cfg_dns +.import cfg_gateway +.import cfg_netmask +.import cfg_tftp_server +.import icmp_ping +.import icmp_echo_ip +.import print_a +.import print_cr +.import dhcp_server +.import cfg_mac +.import cfg_mac_default +.import eth_driver_name +.importzp tftp_filename +.import tftp_ip +.import tftp_download +.import tftp_set_callback_vector +.import tftp_data_block_length +.import tftp_upload +.import get_key_if_available +.import tcp_send_keep_alive +.import timer_read +.import native_to_ascii +.import ascii_to_native +.zeropage +temp: .res 2 +temp2: .res 2 +pptr=temp +.segment "STARTUP" ;this is what gets put at the start of the file on the Vic 20 +.word basicstub ; load address +basicstub: + .word @nextline + .word 10 ;line number + .byte $9e ;SYS + .byte <(((relocate / 1000) .mod 10) + $30) + .byte <(((relocate / 100 ) .mod 10) + $30) + .byte <(((relocate / 10 ) .mod 10) + $30) + .byte <(((relocate ) .mod 10) + $30) +; .byte ":" +; .byte "D" +; .byte $b2 ;= +; .byte $c2 ;PEEK +; .byte "(186):" +; .byte $93 ;LOAD +; .byte $22,"AUTOEXEC.BAS",$22,",D" + .byte 0 +@nextline: + .word 0 +relocate: + lda MEMSIZ+1 + cmp #$80 ;standard end of memory + beq ok_to_install + ldy #0 +@loop: + lda not_installing,y + beq @done + jsr $ffd2 + iny + bne @loop +@done: + rts +not_installing: + .byte "INSUFFICIENT FREE MEMORY",13,0 +ok_to_install: + + ldax #end_of_loader + stax copy_src + ldax #main_start + stax copy_dest + stax MEMSIZ + FS= $3FC9 ;how much data to relocate? + ldax #FS + +;copy memory + sta end + ldy #0 + + cpx #0 + beq @tail + +: lda (copy_src),y + sta (copy_dest),y + iny + bne :- + inc copy_src+1 ;next page + inc copy_dest+1 ;next page + dex + bne :- + +@tail: + lda end + beq @done + +: lda (copy_src),y + sta (copy_dest),y + iny + cpy end + bne :- + +@done: + ldax #welcome_banner + + jsr print + + + ldx #7 ;Copy CURRENT vectors +@copy_old_vectors_loop: + lda ICRUNCH,x + sta oldcrunch,x + dex + bpl @copy_old_vectors_loop + + ldx #7 ;Copy CURRENT vectors +install_new_vectors_loop: + lda vectors,x + sta ICRUNCH,x + dex + bpl install_new_vectors_loop + + ;BASIC keywords installed, now bring up the ip65 stack + + jsr ip65_init + bcc @init_ok + bcs @init_ok ;FIXME + ldax #@no_nic + jsr print +@reboot: + + ldax #$8000 + stax MEMSIZ + + jsr $e45b ;reset vectors + + jsr $c642 ;NEW + jsr $c65e ;CLR + jsr $e3a4 ;init RAM + jmp $e467 ;BASIC warm start + +@no_nic: + .byte "NO RR-NET FOUND!",13,0 + +@init_ok: + + lda #0 + sta ip65_error + sta connection_state + jsr set_error + +@exit: + + ; jsr $C644 ;do a "NEW" + ; jmp $C474 ;"READY" prompt + jmp $e467 ;BASIC warm start + rts + +welcome_banner: +.byte "** KIPPER BASIC 1.1 **" +.byte 0 +end: .res 1 +end_of_loader: + +.segment "MAINSTART" +main_start: + +safe_getvar: ;if GETVAR doesn't find the desired variable name in the VARTABLE, a routine at $D11D will create it + ;however that routine checks if the low byte of the return address of the caller is $2A. if it is, + ;it assumes the caller is the routine at $CF28 which just wants to get the variable value, and + ;returns a pointer to a dummy 'zero' pointer. + ;so if user code that is calling GETVAR happens to be compiled to an address $xx28, it will + ;trigger this check, and not create a new variable, which (from painful experience) will create + ;a really nasty condition to debug! + ;so vector to GETVAR via here, so the return address seen by $D11D is here, and never $xx28 + jsr GETVAR + rts +.code + + +; CRUNCH -- If this is one of our keywords, then tokenize it +; +crunch: + jsr jmp_crunch ;First crunch line normally + ldy #05 ;Offset for KERNAL + ;Y will contain line length+5 +@loop: + sty temp + jsr isword ;Are we at a keyword? + bcs @gotcha +@next: + jsr nextchar + bne @loop ;Null byte marks end + sta crunched_line-3,Y ;00 line number + lda #$FF ;'tis what A should be + rts ;Buh-bye + +; Insert token and crunch line +@gotcha: + ldx temp ;If so, A contains opcode + sta crunched_line-5,X +@move: + inx + lda crunched_line-5,Y + sta crunched_line-5,X ;Move text backwards + beq @next + iny + bpl @move + + +; ISWORD -- Checks to see if word is +; in table. If a word is found, then +; C is set, Y is one past the last char +; and A contains opcode. Otherwise, +; carry is clear. +; +; On entry, TEMP must contain current +; character position. +; +isword: + ldx #00 +@loop: + ldy temp +@loop2: + lda keywords,x + beq @notmine + cmp #$E0 + bcs @done ;Tokens are >=$E0 + cmp crunched_line-5,Y + bne @next + iny ;Success! Go to next char + inx + bne @loop2 +@next: + inx + lda keywords,x ;Find next keyword + cmp #$E0 + bcc @next + inx + bne @loop ;And check again +@notmine: + clc +@done: + rts + + +; NEXTCHAR finds the next char +; in the buffer, skipping +; spaces and quotes. On +; entry, TEMP contains the +; position of the last spot +; read. On exit, Y contains +; the index to the next char, +; A contains that char, and Z is set if at end of line. + +nextchar: + ldy temp +@loop: + iny + lda crunched_line-5,Y + beq @done + cmp #$8F ;REM + bne @cont + lda #00 +@skip: + sta temp2 ;Find matching character +@loop2: + iny + lda crunched_line-5,Y + beq @done + cmp temp2 + bne @loop2 ;Skip to end of line + beq @loop +@cont: + cmp #$20 ;space + beq @loop + cmp #$22 ;quote + beq @skip +@done: + rts + + +; +; LIST -- patches the LIST routine +; to list our new tokens correctly. +; + +list: + cmp #$E0 + bcc @notmine ;Not my token + cmp #HITOKEN + bcs @notmine + bit $0F ;Check for quote mode + bmi @notmine + sec + sbc #$DF ;Find the corresponding text + tax + sty $49 + ldy #00 +@loop: + dex + beq @done +@loop2: + iny + lda keywords,y + cmp #$E0 + bcc @loop2 + iny + bne @loop +@done: + lda keywords,y + cmp #$91 ;is it "ON"? + bne @not_on + lda #'O' + jsr CHROUT + lda #'N' + bne @skip + +@not_on: + cmp #$9B ;is it "LIST"? + + bne @not_list + lda #'L' + jsr CHROUT + lda #'I' + jsr CHROUT + lda #'S' + jsr CHROUT + lda #'T' + bne @skip +@not_list: + lda keywords,y + bmi @out ;is it >=$80? +@skip: + jsr CHROUT + iny + bne @done +@out: + cmp #$E0 ;It might be BASIC token + bcs @cont + ldy $49 +@notmine: + and #$FF + jmp (oldlist) +@cont: + ldy $49 + jmp $C700 ;Normal exit + + + +; +; EXECUTE -- if this is one of our new +; tokens, then execute it. +execute: + jsr CHRGET +execute_a: + php + cmp #':' ;is it a colon? + beq execute;if so, skip over and go to next token + cmp #$8B ;is it 'IF'? + bne @not_if + lda #$E0 ;our dummy IF token +@not_if: + cmp #$E0 + bcc @notmine + cmp #HITOKEN + bcs @notmine + plp + jsr @disp + jmp NEWSTT +@disp: + eor #$E0 + asl ;multiply by 2 + tax + lda token_routines+1,x + pha + lda token_routines,x + pha + jmp CHRGET ;exit to routine (via RTS) +@notmine: + plp + cmp #0 ;reset flags + jmp $C7E7 + +;the standard BASIC IF routine calls the BASIC EXECUTE routine directly, +;without going through the vector. That means an extended keyword following THEN +;will lead to a syntax error. So we have to reimpliment IF here +;this is taken from TransBASIC - The Transactor, vol 5, Issue 04 (March 1985) page 34 +if_keyword: + jsr FRMEVL ;evaluate expression + jsr CHRGOT + cmp #$89 ;is next token GOTO? + beq @ok + lda #$A7 ;is next token THEN + jsr $CEFF ;will generate SYNTAX ERROR if not +@ok: + jsr CHRGOT + ldx $61 ;result of expression : 0 means false + bne @expression_was_true + jmp $C93B ;go to REM implementation - skips rest of line +@expression_was_true: + bcs @not_numeric;CHRGOT clears carry flag if current char is a number + jmp $C8A0 ;do a GOTO +@not_numeric: + pla + pla ;pop the return address off the stack + jsr CHRGOT + jmp execute_a ;execute current token + + + +find_var: + sta VARNAM + stx VARNAM+1 + jsr safe_getvar + ldy #0 + rts + +set_connection_state: + lda #'C'+$80 + ldx #'O'+$80 + jsr find_var + tya + sta (VARPNT),y + iny + lda connection_state + sta (VARPNT),y + +set_error: + lda #'E'+$80 + ldx #'R'+$80 + sta VARNAM+1 + jsr find_var + lda #0 + sta (VARPNT),y + iny + lda ip65_error + sta (VARPNT),y + + rts + + +;emit the 4 bytes pointed at by AX as dotted decimals +emit_dotted_quad: + sta pptr + stx pptr + 1 + ldy #0 + lda (pptr),y + jsr emit_decimal + lda #'.' + jsr emit_a + + ldy #1 + lda (pptr),y + jsr emit_decimal + lda #'.' + jsr emit_a + + ldy #2 + lda (pptr),y + jsr emit_decimal + lda #'.' + jsr emit_a + + ldy #3 + lda (pptr),y + jsr emit_decimal + + rts + +emit_decimal: ;emit byte in A as a decimal number + pha + sta temp_bin ;save + sed ; Switch to decimal mode + lda #0 ; Ensure the result is clear + sta temp_bcd + sta temp_bcd+1 + ldx #8 ; The number of source bits + : + asl temp_bin+0 ; Shift out one bit + lda temp_bcd+0 ; And add into result + adc temp_bcd+0 + sta temp_bcd+0 + lda temp_bcd+1 ; propagating any carry + adc temp_bcd+1 + sta temp_bcd+1 + dex ; And repeat for next bit + bne :- + + cld ;back to binary + + pla ;get back the original passed in number + bmi @emit_hundreds ; if N is set, the number is >=128 so emit all 3 digits + cmp #10 + bmi @emit_units + cmp #100 + bmi @emit_tens +@emit_hundreds: + lda temp_bcd+1 ;get the most significant digit + and #$0f + clc + adc #'0' + jsr emit_a + +@emit_tens: + lda temp_bcd + lsr + lsr + lsr + lsr + clc + adc #'0' + jsr emit_a +@emit_units: + lda temp_bcd + and #$0f + clc + adc #'0' + jsr emit_a + + rts + +print: + sta pptr + stx pptr + 1 + +@print_loop: + ldy #0 + lda (pptr),y + beq @done_print + jsr print_a + inc pptr + bne @print_loop + inc pptr+1 + bne @print_loop ;if we ever get to $ffff, we've probably gone far enough ;-) +@done_print: + rts + + +extract_string: + + jsr FRMEVL + + jsr FRESTR ;if not string, will create type mismatch error + + sta param_length + tay + lda #0 + sta transfer_buffer,y + dey +@loop: + lda ($22),y + sta transfer_buffer,y + dey + bpl @loop + jmp FRESTR ;free up the temp string created by FRMEVL + +;get a string value from BASIC command, turn into a 32 bit IP address,save it in the 4 bytes pointed at by AX +get_ip_parameter: + stax temp2 + jsr extract_string + ldax #transfer_buffer + jsr dns_set_hostname + + bcs @error + jsr dns_resolve + bcc @ok +@error: + ldax #address_resolution + jmp print_error + +@ok: + ldax #dns_ip + ldx #4 +@copy_dns_ip: + lda dns_ip,y + sta (temp2),y + iny + dex + bne @copy_dns_ip + rts + + +reset_string: + ldy #string_buffer + sty current_output_ptr+1 + rts + +print_dotted_quad: + jsr reset_string + jsr emit_dotted_quad +make_null_terminated_and_print: + lda #0 + jsr emit_a + ldax #string_buffer + jmp print + +print_mac: + jsr reset_string + jsr emit_mac + jmp make_null_terminated_and_print + +;print 6 bytes printed at by AX as a MAC address +emit_mac: + stax pptr + ldy #0 +@one_mac_digit: + tya ;just to set the Z flag + pha + beq @dont_print_colon + lda #':' + jsr emit_a +@dont_print_colon: + pla + tay + lda (pptr),y + jsr emit_hex + iny + cpy #06 + bne @one_mac_digit + rts + +emit_hex: + pha + pha + lsr + lsr + lsr + lsr + tax + lda hexdigits,x + jsr emit_a + pla + and #$0F + tax + lda hexdigits,x + jsr emit_a + pla + rts + +print_hex: + jsr reset_string + jsr emit_hex + jmp make_null_terminated_and_print + +print_error: + jsr print + ldax #error + jsr print + lda ip65_error + jsr print_hex + jsr print_cr + jsr set_error + sec + rts + +get_optional_byte: + jsr CHRGOT + beq @no_param ;leave X as it was + jsr CHKCOM ;make sure next char is a comma (and skip it) + jsr CHRGOT + beq @eol + jsr GETBYT +@no_param: + rts +@eol: + jmp $CF08 ;SYNTAX ERROR + +ipcfg_keyword: + + ldax #interface_type + jsr print + + ldax #eth_driver_name + jsr print + jsr print_cr + + ldax #mac_address_msg + jsr print + ldax #cfg_mac + jsr print_mac + jsr print_cr + + ldax #ip_address_msg + jsr print + ldax #cfg_ip + jsr print_dotted_quad + jsr print_cr + + ldax #netmask_msg + jsr print + ldax #cfg_netmask + jsr print_dotted_quad + jsr print_cr + + ldax #gateway_msg + jsr print + ldax #cfg_gateway + jsr print_dotted_quad + jsr print_cr + + ldax #dns_server_msg + jsr print + ldax #cfg_dns + jsr print_dotted_quad + jsr print_cr + + + ldax #dhcp_server_msg + jsr print + ldax #dhcp_server + jsr print_dotted_quad + jsr print_cr + + ldax #tftp_server_msg + jsr print + ldax #cfg_tftp_server + jsr print_dotted_quad + jsr print_cr + +clear_error: + lda #0 + sta ip65_error + jmp set_error + +dhcp_keyword: + jsr dhcp_init + bcc @init_ok + jsr ip65_init ;if DHCP failed, then reinit the IP stack (which will reset IP address etc that DHCP messed with to default values) + +@init_failed: + jsr set_error + ldax #dhcp + jmp print_error +@init_ok: + jmp clear_error + rts + +mac_keyword: + jsr extract_string + ldy #2 +: + lda transfer_buffer,y + sta cfg_mac_default+3,y + dey + bpl:- + jsr ip65_init + rts + +ping_keyword: + ldax #icmp_echo_ip + jsr get_ip_parameter + bcc @no_error + rts +@no_error: + + ;is there an optional parameter? + ldx #3 + jsr get_optional_byte + stx ping_counter + + ldax #pinging + jsr print + ldax #dns_ip + jsr print_dotted_quad + jsr print_cr + +@ping_loop: + + jsr icmp_ping + bcs @error + lda #'.' +@print_and_loop: + jsr print_a + lda $cb ;current key pressed + cmp #$18 ;RUN/STOP? + beq @done + lda ping_counter + beq @ping_loop + dec ping_counter + cmp #1 + bne @ping_loop +@done: + jsr print_cr + jmp set_error +@error: + lda #'!' + jmp @print_and_loop + + +myip_keyword: + ldax #cfg_ip + jmp get_ip_parameter + +dns_keyword: + ldax #cfg_dns + jmp get_ip_parameter + +gateway_keyword: + ldax #cfg_gateway + jmp get_ip_parameter + +netmask_keyword: + ldax #cfg_netmask + jmp get_ip_parameter + +tftp_keyword: + ldax #cfg_tftp_server + jmp get_ip_parameter + + +tf_param_setup: + jsr print + jsr extract_string + ldax #transfer_buffer + stax tftp_filename + jsr print + lda #' ' + jsr print_a + lda #'(' + jsr print_a + ldax #cfg_tftp_server + jsr print_dotted_quad + lda #')' + jsr print_a + + jsr print_cr + + ldx #$03 +: + lda cfg_tftp_server,x + sta tftp_ip,x + dex + bpl :- + rts + +tfget_keyword: + ldax #get_msg + jsr tf_param_setup + ldax #tftp_download_callback + jsr tftp_set_callback_vector + lda #0 + sta file_opened +;make file output name + lda #'@' + sta string_buffer + lda #':' + sta string_buffer+1 + ldy #$FF +@loop: + iny + lda transfer_buffer,y + sta string_buffer+2,y + bne @loop + iny + iny + lda #',' + sta string_buffer,y + iny + lda #'P' + sta string_buffer,y + iny + lda #',' + sta string_buffer,y + iny + lda #'W' + sta string_buffer,y + iny + sta string_length + + jsr tftp_download +after_tftp_xfer: + bcc @no_error + ldax #tftp +@error_set: + jsr print_error +@no_error: + jsr close_file + jmp set_error + +close_file: + lda #$02 ; filenumber 2 + jsr $FFC3 ; call CLOSE + rts + +open_file: + ;A,X,Y set up ready for a call to SETNAM for file #2 + jsr $FFBD ; call SETNAM + lda #$02 ; file number 2 + ldx $BA ; last used drive + + ldy #$02 ; secondary address 2 + jsr $FFBA ; call SETLFS + + jmp $FFC0 ; call OPEN + + +tftp_download_callback: + + ;buffer pointed at by AX now contains "tftp_data_block_length" bytes + stax temp + + lda #'.' + jsr print_a + lda file_opened + bne @already_opened + lda string_length + ldx #string_buffer + jsr open_file + +@already_opened: + + ldx #$02 ; filenumber 2 = output file + jsr $FFC9 ; call CHKOUT + +@copy_one_byte: + lda tftp_data_block_length + bne @not_done + lda tftp_data_block_length+1 + beq @done + +@not_done: + ldy #2 ;we want to skip the first 2 bytes in the buffer + lda (temp),y + jsr $ffd2 ;write byte + inc temp + bne :+ + inc temp+1 +: + lda tftp_data_block_length + dec tftp_data_block_length + cmp #0 + bne @copy_one_byte + dec tftp_data_block_length+1 + jmp @copy_one_byte +@done: + + ldx #$00 ; filenumber 0 = console + jmp $FFC9 ; call CHKOUT + + +tfput_keyword: + ldax #put_msg + jsr tf_param_setup + + lda param_length + ldx #transfer_buffer + jsr open_file + bcs @error + lda $90 ;get ST + beq @ok +@error: + + ldx #4 ;"FILE NOT FOUND" error + jmp $C437 ;error +@ok: + ldax #tftp_upload_callback + jsr tftp_set_callback_vector + jsr tftp_upload + jmp after_tftp_xfer + + +tftp_upload_callback: + stax copy_dest + lda #'.' + jsr print_a + lda #0 + sta bytes_read + sta bytes_read+1 + + ldx #$02 ; filenumber 2 = output file + jsr $FFC6 ; call CHKIN (file 2 now used as input) +@loop: + jsr $FFCF ; call CHRIN (get a byte from file) + ldy #0 + sta (copy_dest),y + inc copy_dest + bne :+ + inc copy_dest+1 +: + inc bytes_read + bne :+ + inc bytes_read+1 +: + lda bytes_read+1 + cmp #2 + beq @done + jsr $FFB7 ; call READST (read status byte) + beq @loop ; nonzero mean either EOF or read error + +@done: + ldx #$00 ; filenumber 0 = console + jsr $FFC6 ; call CHKIN (console now used as input) + ldax bytes_read + rts + +skip_comma_get_integer: + jsr CHRGOT + jsr CHKCOM ;make sure next char is a comma (and skip it) +get_integer: + jsr CHRGOT + beq @eol + jsr FRMNUM + jsr GETADR + ldax LINNUM +@no_param: + rts +@eol: + jmp $CF08 ;SYNTAX ERROR + + +make_tcp_connection: + lda #0 + sta connection_state + jsr set_connection_state + ldax #tcp_connect_ip + jsr get_ip_parameter + bcc @no_error + rts +@no_error: + jsr skip_comma_get_integer + jsr tcp_connect + bcc :+ +@connect_error: + ldax #connect + jmp print_error +: + ldax #connected_msg + jsr print + lda #1 + sta connection_state + lda #0 + sta ip65_error + jsr set_connection_state + clc + rts + +netcat_keyword: + lda $CC + sta cursor_state + lda #$0 + sta $CC ;enable blinking cursor + ldax #netcat_callback + stax tcp_callback + jsr make_tcp_connection + bcs @exit + + ;is there an optional parameter? + ldx #0 + jsr get_optional_byte + stx netcat_mode +@main_polling_loop: + + jsr timer_read + txa + adc #$20 ;32 x 1/4 = ~ 8seconds + sta netcat_timeout +@wait_for_keypress: + jsr timer_read + cpx netcat_timeout + bne @no_timeout + jsr tcp_send_keep_alive + jmp @main_polling_loop +@no_timeout: + jsr ip65_process + lda connection_state + bne @not_disconnected +@disconnected: + ldax #disconnected + jsr print +@exit: + lda cursor_state + sta $CC + rts +@not_disconnected: + + lda netcat_mode + beq @not_line_mode + + lda #$00 + sta string_length + +;process inbound ip packets while waiting for a keypress +@read_line: + lda $cb ;current key pressed + cmp #$18 ;RUN/STOP? + beq @runstop + jsr ip65_process + lda connection_state + beq @disconnected + + jsr $f142 ;not officially documented - where F13E (GETIN) falls through to if device # is 0 (KEYBD) + + beq @read_line + + cmp #$14 ;Delete + beq @delete + + cmp #$0d ;Return + beq @input_done + + ;End reached? + ldy string_length + cpy #$FF + beq @read_line + + jsr $ffd2 ;Print it + jsr native_to_ascii + sta transfer_buffer,y ;Add it to string + + inc string_length + + ;Not yet. + jmp @read_line + + +@delete: + ;First, check if we're at the beginning. + lda string_length + bne @delete_ok + jmp @read_line + + ;At least one character entered. +@delete_ok: + ;Move pointer back. + dec string_length + + ;Print the delete char + lda #$14 + jsr $ffd2 + + ;Wait for next char + jmp @read_line + +@input_done: + jsr reset_cursor + lda #$0d + jsr $ffd2 ;print a newline + ldy string_length + lda #$0d + sta transfer_buffer,y + iny + lda #$0a + sta transfer_buffer,y + iny + sty tcp_send_data_len + jmp @send_buffer +@not_line_mode: + + ;is there anything in the input buffer? + lda $c6 ;NDX - chars in keyboard buffer + bne :+ + jmp @wait_for_keypress +: + lda #0 + sta tcp_send_data_len + sta tcp_send_data_len+1 +@get_next_char: + lda $cb ;current key pressed + cmp #$18 ;RUN/STOP? + bne @not_runstop +@runstop: + lda #0 + sta $cb ;overwrite "current key pressed" else it's seen by the tcp stack and the close aborts + lda cursor_state + sta $CC + + jmp tcp_close +@not_runstop: + jsr $ffe4 ;getkey - 0 means no input + tax + beq @no_more_input + txa + + ldy tcp_send_data_len + sta transfer_buffer,y + inc tcp_send_data_len + jmp @get_next_char +@no_more_input: +@send_buffer: + ldax #transfer_buffer + jsr tcp_send + bcs @error_on_send + jmp @main_polling_loop + +@error_on_send: + lda cursor_state + sta $CC + + ldax #transmission + jmp print_error + +reset_cursor: + lda $cf ;0 means last cursor blink set char to be reversed + beq @done + lda $ce ;original value of cursor char + ldx $287 ;original colour + ldy #$0 ;blink phase + sty $cf + jsr $ea13 ;restore char & colour +@done: + rts +netcat_callback: + jsr reset_cursor + lda tcp_inbound_data_length+1 + cmp #$ff + bne @not_eof + lda #0 + sta connection_state + rts +@not_eof: + + ldax tcp_inbound_data_ptr + stax temp2 + lda tcp_inbound_data_length + sta buffer_length + lda tcp_inbound_data_length+1 + sta buffer_length+1 + +@next_byte: + lda $cb ;current key pressed + cmp #$18 ;RUN/STOP? + beq @finished + + ldy #0 + lda (temp2),y + ldx netcat_mode + beq @no_transform + jsr ascii_to_native +@no_transform: + jsr print_a + inc temp2 + bne :+ + inc temp2+1 +: + lda buffer_length+1 + beq @last_page + lda buffer_length + bne @not_end_of_page + dec buffer_length+1 +@not_end_of_page: + dec buffer_length + jmp @next_byte +@last_page: + dec buffer_length + beq @finished + + jmp @next_byte + +@finished: + + rts + + +tcpconnect_keyword: + ldax #tcpconnect_callback + stax tcp_callback + jmp make_tcp_connection + +tcpconnect_callback: + + ldax #transfer_buffer + stax copy_dest + ldax tcp_inbound_data_ptr + stax copy_src + lda tcp_inbound_data_length + ldx tcp_inbound_data_length+1 + beq @short_packet + cpx #$ff + bne @not_end_packet + lda #0 + sta connection_state + rts +@not_end_packet: + lda #$ff +@short_packet: + +set_input_string: + pha + lda #'I' + ldx #'N'+$80 + jsr find_var + ldy #0 + pla + pha + sta (VARPNT),y + iny + lda #transfer_buffer + sta (VARPNT),y + pla + beq :+ + ldx #0 + jsr copymem +: + rts + +poll_keyword: + lda #0 + jsr set_input_string + jsr set_connection_state + jsr ip65_process + lda ip65_error + beq @no_error + jmp set_error +@no_error: + jmp set_connection_state + +tcplisten_keyword: + lda #0 + sta connection_state + sta ip65_error + ldax #tcpconnect_callback + stax tcp_callback + jsr get_integer + jsr tcp_listen + bcs :+ + inc connection_state +: + jmp set_connection_state + +tcpsend_keyword: + jsr extract_string + ldy param_length + sty tcp_send_data_len + ldy #0 + sty tcp_send_data_len+1 + ldax #transfer_buffer + jsr tcp_send + jmp set_connection_state + +tcpclose_keyword: + lda #0 + sta connection_state + jsr tcp_close + jmp set_connection_state + +tcpblat_keyword: + + jsr extract_string + + ldx #transfer_buffer + lda param_length + jsr SETNAM + lda #$02 ; file number 2 + ldx $BA ; last used device number + bne @skip + ldx #$08 ; default to device 8 +@skip: + ldy #$02 ; secondary address 2 + jsr SETLFS + jsr OPEN + bcs @error ; if carry set, the file could not be opened + ldx #$02 ; filenumber 2 + jsr CHKIN + ldy #$00 +@loop: + jsr READST + bne @eof ; either EOF or read error + jsr CHRIN + sta transfer_buffer,y + iny + bne @loop + ldax #$100 + stax tcp_send_data_len + ldax #transfer_buffer + jsr tcp_send + bcs @error_stored + ldy #0 + jmp @loop +@eof: + and #$40 ; end of file? + beq @readerror + lda #$00 + sty tcp_send_data_len + sta tcp_send_data_len+1 + ldax #transfer_buffer + jsr tcp_send + bcs @error_stored + +@close: + lda #0 +@store_error: + sta ip65_error +@error_stored: + lda #$02 ; filenumber 2 + jsr CLOSE + ldx #$00 ; filenumber 0 = keyboard + jsr CHKIN ;keyboard now input device again + jmp set_error + +@error: + lda #KPR_ERROR_DEVICE_FAILURE + jmp @store_error +@readerror: + lda #KPR_ERROR_FILE_ACCESS_FAILURE + jmp @store_error + +evaluate: + lda $00 + sta $0D ;set string flag to not string + jsr CHRGET + cmp #$E3 ; PING keyword + bne @done + + jsr CHRGET ;take PING command off stack + + ldax #icmp_echo_ip + jsr get_ip_parameter + lda #$00 + sta $0D ;set string flag to not string + + bcs @error + jsr icmp_ping + bcc @no_error +@error: + lda #$ff + tax +@no_error: + tay + txa + jmp $D395 ;signed 16 bit number to floating point + rts + +@done: + jsr CHRGOT + jmp $CE8D ;inside original EVAL routine + +.rodata +vectors: + .word crunch + .word list + .word execute + .word evaluate +; Keyword list +; Keywords are stored as normal text, +; followed by the token number. +; All tokens are >$80, +; so they easily mark the end of the keyword +hexdigits: +.byte "0123456789ABCDEF" + +pinging: +.byte"PINGING ",0 +interface_type: +.byte $12,"INTERFACE",$92,13,0 + +mac_address_msg: +.byte $12,"MAC ADDRESS",$92,13,0 + +ip_address_msg: +.byte $12,"IP ADDRESS",$92,13,0 + +netmask_msg: +.byte $12,"NETMASK",$92,13,0 + +gateway_msg: +.byte $12,"GATEWAY",$92,13,0 + +dns_server_msg: +.byte $12,"DNS SERVER",$92,13,0 + +dhcp_server_msg: +.byte $12,"DHCP SERVER",$92,13,0 + +tftp_server_msg: +.byte $12,"TFTP SERVER",$92,13,0 + +address_resolution: +.byte "ADDRESS RESOLUTION",0 + +get_msg: +.byte "GETTING ",0 +put_msg: +.byte "PUTTING ",0 + +tftp: +.byte "TFTP",0 +dhcp: +.byte "DHCP",0 + +connect: +.byte "CONNECT",0 + +transmission: +.byte "TRANSMISSION",0 + +error: +.byte " ERROR $",0 + +disconnected: +.byte 13,"DIS" +connected_msg: +.byte "CONNECTED",13,0 + +keywords: + .byte "IF",$E0 ;our dummy 'IF' entry takes $E0 + .byte "IPCFG",$E1 + .byte "DHCP",$E2 + .byte "PING",$E3 + .byte "MYIP",$E4 + .byte "NETMASK",$E5 + .byte "GATEWAY",$E6 + .byte "DNS",$E7 + .byte "TFTP",$E8 + .byte "TF",$A1,$E9 ;TFGET - BASIC will replace GET with A1 + .byte "TFPUT",$EA + .byte "NETCAT",$EB + .byte "TCPC",$91,"NECT",$EC ; TCPCONNECT - BASIC will replace ON with $91 + .byte "POLL",$ED + .byte "TCP",$9B,"EN",$EE ;TCPLISTEN - BASIC will replace LIST with $9b + .byte "TCPS",$80,$EF ;TCPSEND - BASIC will replace END with $80 + .byte "TCP",$A0,$F0 ;TCPLOSE - BASIC will replace CLOSE with $A0 + .byte "TCPBLAT",$F1 + .byte "MAC",$F2 + .byte $00 ;end of list +HITOKEN=$F3 + +; +; Table of token locations-1 +; +token_routines: +E0: .word if_keyword-1 +E1: .word ipcfg_keyword-1 +E2: .word dhcp_keyword-1 +E3: .word ping_keyword-1 +E4: .word myip_keyword-1 +E5: .word netmask_keyword-1 +E6: .word gateway_keyword-1 +E7: .word dns_keyword-1 +E8: .word tftp_keyword-1 +E9: .word tfget_keyword-1 +EA: .word tfput_keyword-1 +EB: .word netcat_keyword-1 +EC: .word tcpconnect_keyword-1 +ED: .word poll_keyword-1 +EE: .word tcplisten_keyword-1 +EF: .word tcpsend_keyword-1 +FO: .word tcpclose_keyword-1 +F1: .word tcpblat_keyword-1 +F2: .word mac_keyword-1 + +.segment "SELF_MODIFIED_CODE" + + +jmp_crunch: .byte $4C ;JMP +oldcrunch: .res 2 ;Old CRUNCH vector +oldlist: .res 2 +oldexec: .res 2 +oldeval: .res 2 +emit_a: +current_output_ptr=emit_a+1 + sta $ffff + inc string_length + inc current_output_ptr + bne :+ + inc current_output_ptr+1 +: + rts + + +.bss +netcat_mode: .res 1 +bytes_read: .res 2 +string_length: .res 1 +param_length: .res 1 +ip_string: .res 15 +netmask_string: .res 15 +dns_string: .res 15 +gateway_string: .res 15 + temp_bin: .res 1 +temp_bcd: .res 2 +ping_counter: .res 1 +string_buffer: .res 128 +transfer_buffer: .res 256 +file_opened: .res 1 +connection_state: .res 1 +netcat_timeout: .res 1 +buffer_length: .res 2 +cursor_state: .res 1 diff --git a/client/cfg/a2bin.cfg b/client/cfg/a2bin.cfg index d2d2176..7303024 100644 --- a/client/cfg/a2bin.cfg +++ b/client/cfg/a2bin.cfg @@ -7,14 +7,14 @@ MEMORY { } SEGMENTS { EXEHDR: load = HEADER, type = ro; - STARTUP: load = RAM,run=RAM, type = ro, define = yes; + STARTUP: load = RAM,run=RAM, type = ro, define = yes, optional=yes; CODE: load = RAM, run=RAM, type = ro, define = yes; RODATA: load = RAM, run=RAM, type = ro , define = yes; IP65_DEFAULTS: load = RAM, run=RAM, type = ro , define = yes; DATA: load = RAM, run=RAM, type = rw , define = yes; BSS: load=RAM, type = bss, define = yes; - TCP_VARS: load = RAM, type = bss; - APP_SCRATCH: load = RAM, type = bss; + TCP_VARS: load = RAM, type = bss, optional=yes; + APP_SCRATCH: load = RAM, type = bss , optional=yes; ZEROPAGE: load = ZP, type = zp; IP65ZP: load = IP65ZP, type = zp; } diff --git a/client/cfg/kipperbasv20.cfg b/client/cfg/kipperbasv20.cfg new file mode 100644 index 0000000..7416480 --- /dev/null +++ b/client/cfg/kipperbasv20.cfg @@ -0,0 +1,26 @@ + +MEMORY { + IP65ZP: start = $A3, size = $12, type = rw; + STARTRAM: start = $11FF, size = $1000, file = %O; + MAINRAM: start = $4000, size = $3FC9, define = yes, file = %O; + HIRAM: start = $A000, size = $1fE0; +} + SEGMENTS { + STARTUP: load = STARTRAM, type = rw; + MAINSTART: load = MAINRAM, type = rw; + + IP65_DEFAULTS: load = MAINRAM, type = ro; + CODE: load = MAINRAM, type = ro; + SELF_MODIFIED_CODE: load = MAINRAM, type = rw; + RODATA: load = MAINRAM, type = ro; + DATA: load = MAINRAM, type = rw, define = yes; + HTTP_VARS: load = MAINRAM, type = rw, define = yes; + BSS: load = MAINRAM, type = bss; + + IP65ZP: load = IP65ZP, type = zp; + + ZEROPAGE: load = IP65ZP, type = zp; + + TCP_VARS: load = HIRAM, type = bss; + + } diff --git a/client/cfg/vic20prg.cfg b/client/cfg/vic20prg.cfg index 83e2c0b..7c6c198 100644 --- a/client/cfg/vic20prg.cfg +++ b/client/cfg/vic20prg.cfg @@ -1,23 +1,23 @@ #assumes a fully expanded VIC 20 -MEMORY { - ZP: start = $02, size = $1A, type = rw ; - IP65ZP: start = $5f, size = $10, type = rw; +MEMORY { + ZP: start = $02, size = $1A, type = rw ; + IP65ZP: start = $5f, size = $10, type = rw; RAM: start = $11FF, size = $6e00, file = %O; -} -SEGMENTS { - STARTUP: load = RAM, type = ro ,define = yes, optional=yes; - CODE: load = RAM, type = ro,define = yes; +} +SEGMENTS { + STARTUP: load = RAM, type = ro ,define = yes, optional=yes; + CODE: load = RAM, type = ro,define = yes; DATA: load = RAM, type = rw,define = yes; SELF_MODIFIED_CODE: load = RAM, type = rw,define = yes, optional=yes; - VIC_DATA: load = RAM, type = rw,align = $800, optional=yes; + VIC_DATA: load = RAM, type = rw,align = $800, optional=yes; RODATA: load = RAM, type = ro,define = yes, optional=yes; IP65_DEFAULTS: load = RAM, type = rw,define = yes, optional=yes; BSS: load = RAM, type = bss, optional=yes; # SAFE_BSS: load = RAM3000, type = bss, optional=yes; - APP_SCRATCH: load = RAM, type = bss, optional=yes; - ZEROPAGE: load = ZP, type = zp, optional=yes; + APP_SCRATCH: load = RAM, type = bss, optional=yes; + ZEROPAGE: load = ZP, type = zp, optional=yes; IP65ZP: load = IP65ZP, type = zp, optional=yes; TCP_VARS: load = RAM, type = bss, optional=yes; HTTP_VARS: load = RAM, type = bss, optional=yes; - -} + +} diff --git a/client/drivers/Makefile b/client/drivers/Makefile index b34b02b..69d3774 100644 --- a/client/drivers/Makefile +++ b/client/drivers/Makefile @@ -10,19 +10,27 @@ AFLAGS= $(AS) $(AFLAGS) $< +# a2uther.lib Apple //, with an Uthernet card (cs8900a chipset) in slot #3 +# a2lancegs.lib Apple //, with a LANceGS card (lan91c96) +# c64rrnet.lib C64 with RR-NET or clone at $de0x +# c64wiznet.lib C64 with Wiznet W5100 addressed at $df2x +# vic20rrnet.lib C64 with RR-NET or clone at $980x + DRIVERS=\ - apple2prog.lib \ + a2uther.lib \ + a2lancegs.lib \ c64rrnet.lib \ c64wiznet.lib \ vic20rrnet.lib \ - all: $(DRIVERS) +a2lancegs.lib: a2print.o lan91c96.o a2timer.o a2kernal.o a2input.o a2charconv.o + ar65 a $@ $^ -apple2prog.lib: a2print.o uthernet.o a2timer.o a2kernal.o a2input.o a2charconv.o cs8900a.o +a2uther.lib: a2print.o uthernet.o a2timer.o a2kernal.o a2input.o a2charconv.o cs8900a.o ar65 a $@ $^ c64rrnet.lib: c64print.o rr-net.o c64timer.o c64kernal.o c64inputs.o cbm_disk_access.o petscii_charconv.o c64_vt100.o cs8900a.o @@ -31,9 +39,7 @@ c64rrnet.lib: c64print.o rr-net.o c64timer.o c64kernal.o c64inputs.o cbm_disk_ac c64wiznet.lib: w5100.o c64print.o c64timer.o c64kernal.o c64inputs.o cbm_disk_access.o petscii_charconv.o c64_vt100.o ar65 a $@ $^ - vic20rrnet.lib: vic20print.o vic20-rr-net.o vic20timer.o vic20input.o cbm_disk_access.o petscii_charconv.o cs8900a.o - ar65 a $@ $^ diff --git a/client/drivers/lan91c96.s b/client/drivers/lan91c96.s new file mode 100644 index 0000000..b6529cc --- /dev/null +++ b/client/drivers/lan91c96.s @@ -0,0 +1,75 @@ +; Ethernet driver for W5100 W5100 chip +; + +.ifndef KPR_API_VERSION_NUMBER + .define EQU = + .include "../inc/kipper_constants.i" +.endif + +.include "../inc/common.i" + + .export eth_init + .export eth_rx + .export eth_tx + .export eth_driver_name + + .import eth_inp + .import eth_inp_len + .import eth_outp + .import eth_outp_len + + + .code + +;initialize the ethernet adaptor +;inputs: none +;outputs: carry flag is set if there was an error, clear otherwise +eth_init: + sec ;FIX ME ! + rts + + +;receive a packet +;inputs: none +;outputs: +; if there was an error receiving the packet (or no packet was ready) then carry flag is set +; if packet was received correctly then carry flag is clear, +; eth_inp contains the received packet, +; and eth_inp_len contains the length of the packet +eth_rx: + sec ;FIX ME ! + rts + + +; send a packet +;inputs: +; eth_outp: packet to send +; eth_outp_len: length of packet to send +;outputs: +; if there was an error sending the packet then carry flag is set +; otherwise carry flag is cleared +eth_tx: + sec ;FIX ME ! + rts + + +.rodata +eth_driver_name: + .asciiz "LANceGS (91C96)" + +; 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 <## TBD ##> +; Portions created by the Initial Developer is Copyright (C) 2010 +; All Rights Reserved. +; -- LICENSE END -- diff --git a/client/inc/version.i b/client/inc/version.i index 27e2123..99e6447 100644 --- a/client/inc/version.i +++ b/client/inc/version.i @@ -1 +1 @@ -.byte "1.0.36" +.byte "1.0.38" diff --git a/client/ip65/Makefile b/client/ip65/Makefile index 9b10f1d..b856361 100644 --- a/client/ip65/Makefile +++ b/client/ip65/Makefile @@ -3,6 +3,11 @@ LD=ld65 AFLAGS= +# ip65.lib : minimal IP stack (UDP only) +# ip65_tcp.lib : full featured TCP/IP stack +# ip65_wiznet.lib : hybrid stack for use with the w5100 chip : UDP,ICMP & ARP is done on host, TCP is on w5100 + + %.o: %.c $(CC) -c $(CFLAGS) $< @@ -26,7 +31,6 @@ ETHOBJS= \ dottedquad.o \ output_buffer.o\ tftp.o \ - sntp.o \ parser.o \ string_utils.o \ telnet.o \ diff --git a/client/ip65/ip65.s b/client/ip65/ip65.s index 0f4540b..3f47618 100644 --- a/client/ip65/ip65.s +++ b/client/ip65/ip65.s @@ -52,7 +52,7 @@ ip65_error: .res 1 ;last error code ;outputs: AX set to a pseudo-random 16 bit number ip65_random_word: jsr timer_read ;sets AX -; adc $d018 ;on a c64, this is the raster register + adc $9004 ;on a VIC 20, this is the raster register adc $d41b; on a c64, this is a 'random' number from the SID pha adc ip65_ctr_arp diff --git a/client/ip65/sntp.s b/client/ip65/sntp.s deleted file mode 100644 index 948f23d..0000000 --- a/client/ip65/sntp.s +++ /dev/null @@ -1,210 +0,0 @@ -; Simple Network Time Protocol implementation - per RFC 2030 - -MAX_SNTP_MESSAGES_SENT=8 -.include "../inc/common.i" -.ifndef KPR_API_VERSION_NUMBER - .define EQU = - .include "../inc/kipper_constants.i" -.endif - - .export sntp_ip - .export sntp_utc_timestamp - .export sntp_get_time - - .import ip65_process - .import ip65_error - - - .import udp_add_listener - .import udp_remove_listener - - .import udp_callback - .import udp_send - - .import udp_inp - .import output_buffer - .importzp udp_data - - .import udp_send_dest - .import udp_send_src_port - .import udp_send_dest_port - .import udp_send_len - .import check_for_abort_key - .import timer_read - - .segment "IP65ZP" : zeropage - - - .data - sntp_ip: .byte $ff,$ff,$ff,$ff ;can be set to ip address of server that will be queried via sntp (default is a local LAN broadcast) - - .bss - -; sntp packet offsets -sntp_inp = udp_inp + udp_data - -sntp_server_port=123 -sntp_client_port=55123 - -sntp_utc_timestamp: .res 4 ; will be set to seconds (only) part of utc timestamp (seconds since 00:00 on Jan 1, 1900) - -; sntp state machine -sntp_initializing = 1 ; initial state -sntp_query_sent = 2 ; sent a query, waiting for a response -sntp_completed = 3 ; got a good response - -sntp_timer: .res 1 -sntp_loop_count: .res 1 -sntp_break_polling_loop: .res 1 - -sntp_state: .res 1 -sntp_message_sent_count: .res 1 - - - .code - -; query an sntp server for current UTC time -; inputs: -; sntp_ip must point to an SNTP server -; outputs: -; carry flag is set if there was an error, clear otherwise -; sntp_utc_timestamp: set to the number of seconds (seconds since 00:00 on Jan 1, 1900) - timezone is UTC -sntp_get_time: - ldax #sntp_in - stax udp_callback - ldax #sntp_client_port - jsr udp_add_listener - bcc :+ - rts -: - - lda #sntp_initializing - sta sntp_state - lda #0 ;reset the "message sent" counter - sta sntp_message_sent_count - - jsr send_sntp_query - -@sntp_polling_loop: - lda sntp_message_sent_count - adc #1 - sta sntp_loop_count ;we wait a bit longer between each resend -@outer_delay_loop: - lda #0 - sta sntp_break_polling_loop - jsr timer_read - stx sntp_timer ;we only care about the high byte - -@inner_delay_loop: - jsr ip65_process - jsr check_for_abort_key - bcc @no_abort - lda #KPR_ERROR_ABORTED_BY_USER - sta ip65_error - rts -@no_abort: - - lda sntp_state - cmp #sntp_completed - beq @complete - - lda sntp_break_polling_loop - bne @break_polling_loop - jsr timer_read - cpx sntp_timer ;this will tick over after about 1/4 of a second - beq @inner_delay_loop - - dec sntp_loop_count - bne @outer_delay_loop - -@break_polling_loop: - jsr send_sntp_query - inc sntp_message_sent_count - lda sntp_message_sent_count - cmp #MAX_SNTP_MESSAGES_SENT-1 - bpl @too_many_messages_sent - jmp @sntp_polling_loop - -@complete: - - ldax #sntp_client_port - jsr udp_remove_listener - rts - -@too_many_messages_sent: -@failed: - ldax #sntp_client_port - jsr udp_remove_listener - lda #KPR_ERROR_TIMEOUT_ON_RECEIVE - sta ip65_error - sec ;signal an error - rts - - - -send_sntp_query: - - lda #$1B ;LI=00, VN=011,MODE=011 - stax output_buffer - lda #$0 - ldx #$30 ;pad remainder of query packet with 0 bytes - stx udp_send_len - sta udp_send_len+1 -: - sta output_buffer+1,x - dex - bpl :- - ldax #sntp_client_port - stax udp_send_src_port - ldax #sntp_server_port - stax udp_send_dest_port - ldx #3 ; set destination address -: lda sntp_ip,x - sta udp_send_dest,x - dex - bpl :- - - ldax #output_buffer - jsr udp_send - bcs @error_on_send - lda #sntp_query_sent - sta sntp_state -@error_on_send: - rts - - -sntp_in: - - ldx #3 - ldy #0 -: - lda sntp_inp+$28,x ;the 'transmit' timestamp (in big end order) - sta sntp_utc_timestamp,y - iny - dex - bpl :- - - inc sntp_break_polling_loop - lda #sntp_completed - sta sntp_state - rts - - -;-- LICENSE FOR sntp.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 -- diff --git a/client/kipperterm2/timestamp.i b/client/kipperterm2/timestamp.i index 26472d8..b440265 100644 --- a/client/kipperterm2/timestamp.i +++ b/client/kipperterm2/timestamp.i @@ -1 +1 @@ -.byte "2011-01-08" +.byte "2011-01-15" diff --git a/client/test/Makefile b/client/test/Makefile index 4ec62ad..5ad2717 100644 --- a/client/test/Makefile +++ b/client/test/Makefile @@ -11,8 +11,10 @@ IP65TCPLIB=../ip65/ip65_tcp.lib C64RRNETLIB=../drivers/c64rrnet.lib C64WIZNETLIB=../drivers/c64wiznet.lib IP65WIZNETLIB=../ip65/ip65_wiznet.lib -APPLE2PROGLIB=../drivers/apple2prog.lib -VIC20RRNETLIB=../drivers/vic20rrnet.lib +A2UTHERLIB=../drivers/a2uther.lib +A2LANCEGSLIB=../drivers/a2lancegs.lib +VIC20RRNETLIB=../drivers/vic20rrnet.lib + INCFILES=\ ../inc/common.i\ @@ -34,15 +36,15 @@ all: \ testdottedquad.pg2 \ testdottedquad.prg \ test_tcp.prg \ - test_xmodem.prg \ + test_xmodem.prg \ test_vic20.prg \ test_httpd.prg \ test_parser.prg \ test_ping.prg \ - test_sntp.prg \ test_get_url.prg \ - test_wiznet.prg \ - test_parse_querystring.prg \ + test_wiznet.prg \ + test_parse_querystring.prg \ + test_lancegs.pg2 \ # test_xmodem.d64 \ # httpd_test.d64 \ # ip65test.dsk \ @@ -86,19 +88,21 @@ test_ping.prg: test_ping.o $(IP65TCPLIB) $(C64RRNETLIB) $(INCFILES) ../cfg/c64pr test_wiznet.prg: test_wiznet.o $(C64WIZNETLIB) $(IP65WIZNETLIB) $(INCFILES) ../cfg/c64prg.cfg $(LD) -m test_wiznet.map -vm -C ../cfg/c64prg.cfg -o test_wiznet.prg $(AFLAGS) $< $(IP65WIZNETLIB) $(C64WIZNETLIB) - cp test_wiznet.prg ../../server/boot/autoexec.prg - - -test_cifs.prg: test_cifs.o $(IP65TCPLIB) $(C64RRNETLIB) $(INCFILES) ../cfg/c64prg.cfg - $(LD) -m test_cifs.map -vm -C ../cfg/c64prg.cfg -o test_cifs.prg $(AFLAGS) $< $(IP65TCPLIB) $(C64RRNETLIB) - -test_vic20.prg: test_vic20.o $(IP65TCPLIB) $(VIC20RRNETLIB) $(INCFILES) ../cfg/vic20prg.cfg - $(LD) -m test_vic20.map -vm -C ../cfg/vic20prg.cfg -o test_vic20.prg $(AFLAGS) $< $(IP65TCPLIB) $(VIC20RRNETLIB) - -%.pg2: %.o $(IP65LIB) $(APPLE2PROGLIB) $(INCFILES) ../cfg/a2bin.cfg - $(LD) -C ../cfg/a2bin.cfg -o $*.pg2 $(AFLAGS) $< $(IP65LIB) $(APPLE2PROGLIB) +test_cifs.prg: test_cifs.o $(IP65TCPLIB) $(C64RRNETLIB) $(INCFILES) ../cfg/c64prg.cfg + $(LD) -m test_cifs.map -vm -C ../cfg/c64prg.cfg -o test_cifs.prg $(AFLAGS) $< $(IP65TCPLIB) $(C64RRNETLIB) + + +test_vic20.prg: test_vic20.o $(IP65TCPLIB) $(VIC20RRNETLIB) $(INCFILES) ../cfg/vic20prg.cfg + $(LD) -m test_vic20.map -vm -C ../cfg/vic20prg.cfg -o test_vic20.prg $(AFLAGS) $< $(IP65TCPLIB) $(VIC20RRNETLIB) + + +%.pg2: %.o $(IP65LIB) $(A2UTHERLIB) $(INCFILES) ../cfg/a2bin.cfg + $(LD) -C ../cfg/a2bin.cfg -o $*.pg2 $(AFLAGS) $< $(IP65LIB) $(A2UTHERLIB) + +test_lancegs.pg2: test_lancegs.o $(IP65LIB) $(A2LANCEGSLIB) $(INCFILES) ../cfg/a2bin.cfg + $(LD) -C ../cfg/a2bin.cfg -o test_lancegs.pg2 $(AFLAGS) $< $(IP65LIB) $(A2LANCEGSLIB) httpd_test.d64: test_httpd.prg index.html file1.html diff --git a/client/test/test_lancegs.s b/client/test/test_lancegs.s new file mode 100644 index 0000000..16ca16c --- /dev/null +++ b/client/test/test_lancegs.s @@ -0,0 +1,47 @@ + .include "../inc/common.i" + .include "../inc/commonprint.i" + .include "../inc/net.i" + + .import cfg_get_configuration_ptr + .import copymem + .importzp copy_src + .importzp copy_dest + + + .import __CODE_LOAD__ + .import __CODE_SIZE__ + .import __RODATA_SIZE__ + .import __DATA_SIZE__ + +.segment "EXEHDR" ;this is what gets put an the start of the file on the Apple 2 + .addr __CODE_LOAD__-$11 ; Start address + .word __CODE_SIZE__+__RODATA_SIZE__+__DATA_SIZE__+4 ; Size + jmp init + +.code + +init: + jsr print_cr + init_ip_via_dhcp + jsr print_ip_config + jsr print_cr + rts + +;-- LICENSE FOR test_ping.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 -- diff --git a/client/test/test_sntp.s b/client/test/test_sntp.s deleted file mode 100644 index 4281618..0000000 --- a/client/test/test_sntp.s +++ /dev/null @@ -1,215 +0,0 @@ - .include "../inc/common.i" - .include "../inc/commonprint.i" - .include "../inc/net.i" - - .import exit_to_basic - .import cfg_get_configuration_ptr - .import dns_set_hostname - .import dns_resolve - .import dns_ip - .import dns_status - .import sntp_ip - .import sntp_utc_timestamp - .import sntp_get_time - - .import __CODE_LOAD__ - .import __CODE_SIZE__ - .import __RODATA_SIZE__ - .import __DATA_SIZE__ - - - .segment "STARTUP" ;this is what gets put at the start of the file on the C64 - - .word basicstub ; load address - -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 - -.segment "EXEHDR" ;this is what gets put an the start of the file on the Apple 2 - .addr __CODE_LOAD__-$11 ; Start address - .word __CODE_SIZE__+__RODATA_SIZE__+__DATA_SIZE__+4 ; Size - jmp init - -.code - -init: - - jsr test_vlb - jsr print_cr - init_ip_via_dhcp - jsr print_ip_config - - ldax #time_server_msg - jsr print - ldax #time_server_host - jsr print - jsr print_cr - ldax #time_server_host - jsr dns_set_hostname - bcs @dns_error - jsr dns_resolve - bcs @dns_error - ldx #3 ; set destination address -: lda dns_ip,x - sta sntp_ip,x - dex - bpl :- - - - ldax #sending_query - jsr print - ldax #sntp_ip - jsr print_dotted_quad - jsr print_cr - jsr sntp_get_time - bcc @ok - ldax #sntp_error - jmp @print_error -@ok: - ldy #3 -: - lda sntp_utc_timestamp,y - jsr print_hex - dey - bpl :- - jmp exit_to_basic - -@dns_error: - ldax #dns_error -@print_error: - jsr print - jsr print_errorcode - jmp exit_to_basic - - -.bss -vla: .res 4 -vlb: .res 4 -quotient: .res 4 -remainder: .res 4 - -.code -div_32_32: - lda #0 - sta remainder - sta remainder+1 - sta remainder+2 - sta remainder+3 - ldx #32 -@loop: - asl vla - rol vla+1 - rol vla+2 - rol vla+3 - - rol remainder - rol remainder+1 - rol remainder+2 - rol remainder+3 - - sec - lda remainder+0 - sbc vlb+0 - sta remainder+0 - - lda remainder+1 - sbc vlb+1 - sta remainder+1 - - lda remainder+2 - sbc vlb+2 - sta remainder+2 - - lda remainder+3 - sbc vlb+3 - sta remainder+3 - - bcs @next - lda remainder - adc vlb - sta remainder - - lda remainder+1 - adc vlb+1 - sta remainder+1 - - lda remainder+2 - adc vlb+2 - sta remainder+2 - - lda remainder+3 - adc vlb+3 - sta remainder+3 -@next: - rol quotient - rol quotient+1 - rol quotient+2 - rol quotient+3 - dex - bpl @loop - rts - .rodata - -test_vlb: - ldx #7 -: - lda divs,x - sta vla,x - dex - bpl :- - - jsr div_32_32 - .byte $92 - - - - -time_server_msg: - .byte "TIME SERVER : ",0 - -time_server_host: - .byte "202.174.101.10",0 - .byte "1.AU.POOL.SNTP.ORG",0 - -sending_query: - .byte "SENDING SNTP QUERY TO ",0 -sntp_error: - .byte "ERROR DURING SNTP QUERY",13,0 - -dns_error: - .byte "ERROR RESOLVING HOSTNAME",13,0 - - divs: - .byte $02,$30,$00,$00 - .byte $05,$00,$00,$00 - - - - -;-- LICENSE FOR test_sntp.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 -- diff --git a/client/test/test_vic20.s b/client/test/test_vic20.s index df23063..524b667 100644 --- a/client/test/test_vic20.s +++ b/client/test/test_vic20.s @@ -41,18 +41,22 @@ init: jsr print jsr print_ip_config - jsr beep -@loop: - jsr timer_seconds - cmp last_seconds - beq @loop - sta last_seconds - jsr print_hex - jsr check_for_abort_key - bcc @loop -; jsr get_key_if_available +; jsr beep +;@loop: +; jsr timer_seconds +; cmp last_seconds ; beq @loop +; sta last_seconds +; jsr print_hex +; jsr check_for_abort_key +; bcc @loop +@loop2: + + jsr get_key_if_available + beq @loop2 jsr print_hex + jsr check_for_abort_key + bcc @loop2 rts diff --git a/client/test/testdns.s b/client/test/testdns.s index b0394bd..5d9e0d6 100644 --- a/client/test/testdns.s +++ b/client/test/testdns.s @@ -111,7 +111,6 @@ overwrite_with_hardcoded_dns_server: .rodata -buffer1: .res 256 hostname_1: .byte "SLASHDOT.ORG",0 ;this should be an A record diff --git a/client/wiznet/kipperwizdisk.d64 b/client/wiznet/kipperwizdisk.d64 index 88a0e9f..c66a543 100644 Binary files a/client/wiznet/kipperwizdisk.d64 and b/client/wiznet/kipperwizdisk.d64 differ diff --git a/dist/make_dist.rb b/dist/make_dist.rb index a2d0a0d..4a51959 100644 --- a/dist/make_dist.rb +++ b/dist/make_dist.rb @@ -1,8 +1,7 @@ $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__))) - -gem 'archive-zip' +require 'RubyGems' require 'archive/zip' require 'ftools' diff --git a/dist/make_dist_ip65.rb b/dist/make_dist_ip65.rb index 20f9e86..ca78663 100644 --- a/dist/make_dist_ip65.rb +++ b/dist/make_dist_ip65.rb @@ -1,14 +1,14 @@ $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__))) - +require 'RubyGems' gem 'archive-zip' require 'archive/zip' require 'ftools' WORKING_DIR=File.expand_path(File.dirname(__FILE__)+"/ip65") SRC_DIR=File.expand_path(File.dirname(__FILE__)+"/../") -["","ip65","doc","cfg","drivers","inc","test","carts","examples"].each do |dir_suffix| +["","ip65","doc","cfg","drivers","inc","test"].each do |dir_suffix| dir_path="#{WORKING_DIR}/#{dir_suffix}" Dir.mkdir(dir_path) unless File.exist?(dir_path) end @@ -16,17 +16,6 @@ end [ ["client/ip65/*.[s|i]","ip65/"], ["client/ip65/Makefile","ip65/"], - ["client/carts/*.[s|i]","carts/"], - ["client/carts/Makefile","carts/"], - ["client/carts/*.rb","carts/"], - ["client/carts/*.obj","carts/"], - ["client/carts/*.src","carts/"], - ["client/examples/*.[s|i]","examples/"], - ["client/examples/Makefile","examples/"], - ["client/examples/*.bin","examples/"], - ["client/examples/*.spr","examples/"], - ["client/examples/*.rb","examples/"], - ["client/examples/*.cfg","examples/"], ["client/inc/*.i","inc/"], ["client/inc/vt100_font.bin","inc/"], ["client/test/*.[s|i]","test/"], @@ -38,7 +27,6 @@ end ["doc/ca65-doc*.*","doc/"], ["doc/CONTRIBUTORS.txt","doc/"], ["doc/LICENSE.txt","doc/"], - ["client/Makefile","/"], ].each do |args| dest="#{WORKING_DIR}/#{args[1]}" Dir["#{SRC_DIR}/#{args[0]}"].each do |src| @@ -47,9 +35,6 @@ end end end -#dummy_makefile=File.new("#{WORKING_DIR}/carts/Makefile","w") -#dummy_makefile<<"#dummy makefile, so we can reuse the top level Makefile from the netboot65/client directory\nall:\n" -#dummy_makefile.close require 'document_ca65_source_as_html.rb' codebase_dir=WORKING_DIR diff --git a/dist/version_number.txt b/dist/version_number.txt index d1c66e6..9cc0a9d 100644 --- a/dist/version_number.txt +++ b/dist/version_number.txt @@ -1 +1 @@ -1.0.36 \ No newline at end of file +1.0.38 \ No newline at end of file diff --git a/doc/ip65.html b/doc/ip65.html index c83fabc..d86a279 100644 --- a/doc/ip65.html +++ b/doc/ip65.html @@ -121,19 +121,18 @@ IP65 is a TCP/IP stack for 6502 based computers. Ethernet driver - CS8900A + CS8900A (RR-NET/Uthernet) + Wiznet W5100 + - - Ethernet interface - RR-Net / TFE - Uthernet - Host computer - C64/C128 - Apple ][ + C64/C128 + Apple ][ + VIC-20 + @@ -162,6 +161,7 @@ IP65 is a TCP/IP stack for 6502 based computers.
   Release	Maintainer	Changes
   -------	----------	-------
+  2011-01-15	Jonno Downes	drivers for Wiznet W5100 ethernet, VIC-20 host
   2009-12-23	Jonno Downes	TCP and telnet bugfixes, vt100 emulation, XMODEM support
   2009-10-31	Jonno Downes	Added Web Application Server functions
   2009-08-02	Jonno Downes	More TCP functionality, includes telnet