From dca0e387ebc42371a03e892be4842b9b0798caa2 Mon Sep 17 00:00:00 2001 From: jonnosan Date: Sat, 7 Nov 2009 06:00:54 +0000 Subject: [PATCH] git-svn-id: http://svn.code.sf.net/p/netboot65/code@214 93682198-c243-4bdb-bd91-e943c89aac3b --- client/carts/Makefile | 1 + client/carts/kipperterm.s | 109 +++++++++------ client/examples/Makefile | 4 +- client/inc/commonprint.i | 2 +- client/inc/telnet.i | 47 ++++--- client/inc/version.i | 2 +- client/ip65/httpd.s | 2 +- client/ip65/telnet.s | 185 +++++++++++++++++++++---- client/ip65/vt100_c64.s | 6 +- dist/make_dist_ip65.rb | 8 +- dist/version_number.txt | 2 +- doc/ip65.html | 13 +- doc/kipper_api_technical_reference.doc | Bin 177152 -> 183296 bytes 13 files changed, 270 insertions(+), 111 deletions(-) diff --git a/client/carts/Makefile b/client/carts/Makefile index 03e8bcd..be1a3cc 100644 --- a/client/carts/Makefile +++ b/client/carts/Makefile @@ -45,6 +45,7 @@ netboot.bin: netboot.o $(IP65LIB) $(C64PROGLIB) $(INCFILES) ../cfg/c64_8kcart.cf kipperkart.bin: kipperkart.o $(IP65TCPLIB) $(C64PROGLIB) $(INCFILES) ../cfg/c64_16kcart.cfg $(LD) -m kipperkart.map -vm -C ../cfg/c64_16kcart.cfg -o $@ $< $(IP65TCPLIB) $(C64PROGLIB) ruby fix_cart.rb $@ 16384 + ruby set_ip_config.rb $@ mac auto ruby dupe_cart.rb kipperkart.bin kipperkart_29c040.bin 32 kipperterm.bin: kipperterm.o $(IP65TCPLIB) $(C64PROGLIB) $(INCFILES) ../cfg/c64_16kcart.cfg diff --git a/client/carts/kipperterm.s b/client/carts/kipperterm.s index 60010e1..377610f 100644 --- a/client/carts/kipperterm.s +++ b/client/carts/kipperterm.s @@ -98,6 +98,9 @@ warm_init: lda #$05 ;petscii for white text jsr print_a + lda #14 + jsr print_a ;switch to lower case + ;relocate our r/w data ldax #__DATA_LOAD__ stax copy_src @@ -116,9 +119,9 @@ warm_init: jsr copymem ldax #netboot65_msg - jsr print + jsr print_ascii_as_native ldax #init_msg+1 - jsr print + jsr print_ascii_as_native jsr ip65_init bcs init_failed @@ -133,13 +136,11 @@ init_failed: jmp exit_to_basic print_main_menu: - lda #21 ;make sure we are in upper case - sta $d018 jsr cls ldax #netboot65_msg - jsr print + jsr print_ascii_as_native ldax #main_menu_msg - jmp print + jmp print_ascii_as_native init_ok: @@ -153,20 +154,16 @@ main_menu: cmp #KEYCODE_F1 bne @not_f1 jsr cls - lda #14 - jsr print_a ;switch to lower case ldax #telnet_header - jsr print + jsr print_ascii_as_native jmp telnet_main_entry @not_f1: cmp #KEYCODE_F3 bne @not_f3 jsr cls - lda #14 - jsr print_a ;switch to lower case ldax #gopher_header - jsr print + jsr print_ascii_as_native jsr prompt_for_gopher_resource ;only returns if no server was entered. jmp exit_gopher @not_f3: @@ -174,8 +171,6 @@ main_menu: cmp #KEYCODE_F5 bne @not_f5 jsr cls - lda #14 - jsr print_a ;switch to lower case ldax #gopher_initial_location sta resource_pointer_lo @@ -187,15 +182,28 @@ main_menu: cmp #KEYCODE_F7 beq @change_config + cmp #KEYCODE_F8 + bne @not_f8 + + jsr cls + ldax #netboot65_msg + jsr print_ascii_as_native + ldax #credits + jsr print_ascii_as_native + ldax #press_a_key_to_continue + jsr print_ascii_as_native + jsr get_key_ip65 + jmp main_menu +@not_f8: jmp @get_key @change_config: jsr cls ldax #netboot65_msg - jsr print + jsr print_ascii_as_native ldax #config_menu_msg - jsr print + jsr print_ascii_as_native jsr print_ip_config jsr print_cr @get_key_config_menu: @@ -207,9 +215,9 @@ main_menu: cmp #KEYCODE_F1 bne @not_ip ldax #new - jsr print + jsr print_ascii_as_native ldax #ip_address_msg - jsr print + jsr print_ascii_as_native jsr print_cr ldax #filter_ip ldy #20 @@ -232,9 +240,9 @@ main_menu: cmp #KEYCODE_F2 bne @not_netmask ldax #new - jsr print + jsr print_ascii_as_native ldax #netmask_msg - jsr print + jsr print_ascii_as_native jsr print_cr ldax #filter_ip ldy #20 @@ -257,9 +265,9 @@ main_menu: cmp #KEYCODE_F3 bne @not_gateway ldax #new - jsr print + jsr print_ascii_as_native ldax #gateway_msg - jsr print + jsr print_ascii_as_native jsr print_cr ldax #filter_ip ldy #20 @@ -284,9 +292,9 @@ main_menu: cmp #KEYCODE_F4 bne @not_dns_server ldax #new - jsr print + jsr print_ascii_as_native ldax #dns_server_msg - jsr print + jsr print_ascii_as_native jsr print_cr ldax #filter_ip ldy #20 @@ -310,9 +318,9 @@ main_menu: cmp #KEYCODE_F5 bne @not_tftp_server ldax #new - jsr print + jsr print_ascii_as_native ldax #tftp_server_msg - jsr print + jsr print_ascii_as_native jsr print_cr ldax #filter_dns ldy #40 @@ -321,7 +329,7 @@ main_menu: stax temp_ax jsr print_cr ldax #resolving - jsr print + jsr print_ascii_as_native ldax temp_ax jsr dns_set_hostname bcs @resolve_error @@ -364,7 +372,7 @@ cmp #KEYCODE_F7 wait_for_keypress: ldax #press_a_key_to_continue - jsr print + jsr print_ascii_as_native @loop: jsr $ffe4 beq @loop @@ -384,48 +392,57 @@ cfg_get_configuration_ptr: exit_telnet: exit_gopher: - lda #142 - jsr print_a ;switch to upper case lda #$05 ;petscii for white text jsr print_a jmp main_menu .rodata netboot65_msg: -.byte 13,"KIPPERTERM V" +.byte 10,"KipperTerm V" .include "../inc/version.i" -.byte 13,0 +.byte 10,0 main_menu_msg: -.byte 13,"MAIN MENU",13,13 -.byte "F1: TELNET F3: GOPHER ",13 -.byte "F5: GOPHER (FLOODGAP.COM)",13 -.byte " F7: CONFIG",13,13 +.byte 10,"Main Menu",10,10 +.byte "F1: Telnet F3: Gopher ",10 +.byte "F5: Gopher (floodgap.com)",10 +.byte "F7: Config F8: Credits",10,10 .byte 0 config_menu_msg: -.byte 13,"CONFIGURATION",13,13 -.byte "F1: IP ADDRESS F2: NETMASK",13 -.byte "F3: GATEWAY F4: DNS SERVER",13 -.byte "F5: TFTP SERVER F6: RESET TO DEFAULT",13 -.byte "F7: MAIN MENU",13,13 +.byte 10,"Configuration",10,10 +.byte "F1: IP Address F2: Netmask",10 +.byte "F3: Gateway F4: DNS Server",10 +.byte "F5: TFTP Server F6: Reset To Default",10 +.byte "F7: Main Menu",10,10 .byte 0 + gopher_initial_location: .byte "1gopher.floodgap.com",$09,"/",$09,"gopher.floodgap.com",$09,"70",$0D,$0A,0 -gopher_header: .byte "gopher",13,0 -telnet_header: .byte "telnet",13,0 +gopher_header: .byte "gopher",10,0 +telnet_header: .byte "telnet",10,0 current: -.byte "CURRENT ",0 +.byte "current ",0 new: -.byte"NEW ",0 +.byte"new ",0 resolving: - .byte "RESOLVING ",0 + .byte "resolving ",0 +credits: +.byte 10,"License: Mozilla Public License v1.1",10,"http://www.mozilla.org/MPL/" +.byte 10 +.byte 10,"Contributors:",10 +.byte 10,"Jonno Downes" +.byte 10,"Glenn Holmmer" +.byte 10,"Per Olofsson" +.byte 10,"Lars Stollenwerk" +.byte 10,10 +.byte 0 ;-- LICENSE FOR kipperterm.s -- ; The contents of this file are subject to the Mozilla Public License diff --git a/client/examples/Makefile b/client/examples/Makefile index 3f17818..d6d7f5c 100644 --- a/client/examples/Makefile +++ b/client/examples/Makefile @@ -14,7 +14,7 @@ INCFILES=\ ../inc/commonprint.i\ ../inc/net.i\ -all: upnatom.prg upnatom.d64 httpd.d64 raster.prg sidplay.prg sidplay_zigzag.prg irc.d64 +all: upnatom.prg upnatom.d64 %.o: %.s $(AS) $(AFLAGS) $< @@ -27,7 +27,7 @@ sine_data.i: make_sine_data.rb upnatom.prg: upnatom.o nt2play.o $(IP65TCPLIB) $(C64PROGLIB) $(INCFILES) ../cfg/c64prg.cfg $(LD) -m upnatom.map -vm -C ../cfg/c64prg.cfg -o upnatom.prg $(AFLAGS) $< $(IP65TCPLIB) $(C64PROGLIB) $(NT2PLAY) - cp upnatom.prg ../../server/boot/ +# cp upnatom.prg ../../server/boot/ %.prg: %.o $(IP65TCPLIB) $(C64PROGLIB) $(INCFILES) ../cfg/c64prg.cfg $(LD) -m $*.map -vm -C ../cfg/c64prg.cfg -o $*.prg $(AFLAGS) $< $(IP65TCPLIB) $(C64PROGLIB) diff --git a/client/inc/commonprint.i b/client/inc/commonprint.i index ff49c89..d449c13 100644 --- a/client/inc/commonprint.i +++ b/client/inc/commonprint.i @@ -307,7 +307,7 @@ print_hex: print_errorcode: ldax #error_code - jsr print + jsr print_ascii_as_native lda ip65_error jsr print_hex jmp print_cr diff --git a/client/inc/telnet.i b/client/inc/telnet.i index 61cb7c8..56e32bd 100644 --- a/client/inc/telnet.i +++ b/client/inc/telnet.i @@ -20,7 +20,7 @@ telnet_main_entry: ;prompt for a hostname, then resolve to an IP address ldax #remote_host - jsr print + jsr print_ascii_as_native ldy #40 ;max chars ldax #filter_dns jsr get_filtered_input @@ -31,10 +31,11 @@ telnet_main_entry: stax temp_ax jsr print_cr ldax #resolving - jsr print + jsr print_ascii_as_native ldax temp_ax jsr print jsr print_cr + ldax temp_ax jsr dns_set_hostname bcs @resolve_error jsr dns_resolve @@ -53,7 +54,7 @@ telnet_main_entry: bpl @copy_telnet_ip_loop @get_port: ldax #remote_port - jsr print + jsr print_ascii_as_native ldy #5 ;max chars ldax #filter_number jsr get_filtered_input @@ -69,13 +70,13 @@ telnet_main_entry: jsr print_cr ldax #char_mode_prompt - jsr print + jsr print_ascii_as_native @char_mode_input: jsr get_key_ip65 - cmp #'A' - beq @ascii_mode - cmp #'a' - beq @ascii_mode + cmp #'V' + beq @vt100_mode + cmp #'v' + beq @vt100_mode cmp #'P' beq @petscii_mode @@ -88,7 +89,7 @@ telnet_main_entry: beq @line_mode jmp @char_mode_input -@ascii_mode: +@vt100_mode: lda #0 sta telnet_use_native_charset sta telnet_line_mode @@ -115,34 +116,34 @@ telnet_main_entry: jsr print_a ldax #connecting_in - jsr print + jsr print_ascii_as_native lda telnet_use_native_charset - beq @a_mode + beq @v_mode ldax #petscii jmp @c_mode -@a_mode: +@v_mode: lda telnet_line_mode bne @l_mode - ldax #ascii + ldax #vt100 jmp @c_mode @l_mode: ldax #line @c_mode: - jsr print + jsr print_ascii_as_native ldax #mode - jsr print + jsr print_ascii_as_native jsr telnet_connect jmp telnet_main_entry ;constants -connecting_in: .byte "CONNECTING IN ",0 -ascii: .byte "ASCII",0 -petscii: .byte "PETSCII",0 -line: .byte "LINE",0 -mode: .byte " MODE",13,0 -remote_host: .byte "HOSTNAME (LEAVE BLANK TO QUIT)",13,": ",0 -remote_port: .byte "PORT # (LEAVE BLANK FOR DEFAULT)",13,": ",0 -char_mode_prompt: .byte "MODE - A=ASCII, P=PETSCII, L=LINE",13,0 +connecting_in: .byte "connecting in ",0 +vt100: .byte "vt100",0 +petscii: .byte "petscii",0 +line: .byte "line",0 +mode: .byte " mode",10,0 +remote_host: .byte "hostname (leave blank to quit)",10,": ",0 +remote_port: .byte "port # (leave blank for default)",10,": ",0 +char_mode_prompt: .byte "mode - V=vt100, P=petscii, L=line",10,0 diff --git a/client/inc/version.i b/client/inc/version.i index 911eea2..80e827e 100644 --- a/client/inc/version.i +++ b/client/inc/version.i @@ -1 +1 @@ -.byte "1.0.9" +.byte "1.0.16" diff --git a/client/ip65/httpd.s b/client/ip65/httpd.s index f675693..506e6ca 100644 --- a/client/ip65/httpd.s +++ b/client/ip65/httpd.s @@ -56,7 +56,7 @@ temp_x: .res 1 .segment "HTTP_VARS" -httpd_io_buffer: .word $2000 ;by default, use a 2k buffer at $2000 for storing inbound requests. +httpd_io_buffer: .word $2000 ;by default, use a 3k buffer at $2000 for storing inbound requests. httpd_scratch_buffer: .word $2B00 ;by default, use a 1k buffer at $2b00 as a scratchpad httpd_port_number: .word 80 diff --git a/client/ip65/telnet.s b/client/ip65/telnet.s index f2f00d6..45e88e0 100644 --- a/client/ip65/telnet.s +++ b/client/ip65/telnet.s @@ -28,7 +28,7 @@ .import ip65_process - .import get_key_ip65 + .import get_key_if_available .import get_filtered_input .import ok_msg .import failed_msg @@ -52,7 +52,7 @@ buffer_ptr: .res 2 ; source pointer .code telnet_connect: lda telnet_use_native_charset - beq :+ + bne :+ jsr vt100_init_terminal : ldax #telnet_callback @@ -71,6 +71,7 @@ telnet_connect: jsr print_cr ldax #failed_msg jsr print + jsr print_cr jsr print_errorcode rts @connect_ok: @@ -79,7 +80,26 @@ telnet_connect: jsr print_cr lda #0 sta connection_closed + sta iac_response_buffer_length + + lda telnet_use_native_charset + bne @main_polling_loop + + lda telnet_line_mode + bne @main_polling_loop + +;if we get here, we are in VT100 'char at a time mode' +;so tell the other end that + + ldax #initial_telnet_options_length + stax tcp_send_data_len + ldax #initial_telnet_options + jsr tcp_send + + + @main_polling_loop: + jsr ip65_process lda connection_closed beq @not_disconnected @@ -117,7 +137,22 @@ telnet_connect: @not_line_mode: - jsr get_key_ip65 +@wait_for_keypress: + jsr ip65_process + lda iac_response_buffer_length + beq @no_iac_response + ldx #0 + stax tcp_send_data_len + stx iac_response_buffer_length + ldax #iac_response_buffer + jsr tcp_send +@no_iac_response: + + + + jsr get_key_if_available + beq @wait_for_keypress + tax ; beq @send_char cmp #KEYCODE_ABORT @@ -195,9 +230,8 @@ telnet_callback: bpl :+ dec buffer_length+1 : - ldy #0 - sty iac_response_buffer_length @next_byte: + ldy #0 lda (buffer_ptr),y tax lda telnet_use_native_charset @@ -212,9 +246,13 @@ telnet_callback: ;if we get here, we are in ASCII 'char at a time' mode, so look for (and process) Telnet style IAC bytes lda telnet_state cmp #telnet_state_got_command - beq @waiting_for_option + bne :+ + jmp @waiting_for_option +: cmp #telnet_state_got_iac beq @waiting_for_command + cmp #telnet_state_got_suboption + beq @waiting_for_suboption_end ; we must be in 'normal' mode txa cmp #255 @@ -224,9 +262,41 @@ telnet_callback: lda #telnet_state_got_iac sta telnet_state jmp @byte_processed + +@waiting_for_suboption_end: + txa + ldx iac_suboption_buffer_length + sta iac_suboption_buffer,x + inc iac_suboption_buffer_length + cmp #$f0 ;SE - suboption end + bne @exit_suboption + + lda #telnet_state_normal + sta telnet_state + lda iac_suboption_buffer + cmp #$18 + bne @not_terminal_type + + ldx #0 +: + lda terminal_type_response,x + ldy iac_response_buffer_length + inc iac_response_buffer_length + sta iac_response_buffer,y + inx + txa + cmp #terminal_type_response_length + bne :- + +@not_terminal_type: + +@exit_suboption: + jmp @byte_processed @waiting_for_command: txa sta telnet_command + cmp #$fa ; SB - suboption begin + beq @suboption cmp #$fb ;WILL beq @option cmp #$fc ;WONT @@ -239,6 +309,13 @@ telnet_callback: lda #telnet_state_normal sta telnet_state jmp @byte_processed +@suboption: + lda #telnet_state_got_suboption + sta telnet_state + lda #0 + sta iac_suboption_buffer + jmp @byte_processed + @option: lda #telnet_state_got_command sta telnet_state @@ -256,8 +333,21 @@ telnet_callback: cmp #$fc beq @iac_wont - ;if we get here, then it's a "do" or "don't", both of which we should send a "wont" back for - ;(since there are no "do" options we actually honour) + cmp #$fe + beq @iac_dont + + ;if we get here, then it's a "do" + + + lda telnet_option + cmp #$18 ;terminal type + beq @do_terminaltype + cmp #$1f + beq @do_naws + + ;if we get here, then it's a "do" command we don't honour + +@iac_dont: lda #$fc ;wont @add_iac_response: ldx iac_response_buffer_length @@ -297,22 +387,40 @@ telnet_callback: lda #$fd ;DO jmp @add_iac_response +@do_naws: + ldx #0 +: + lda naws_response,x + ldy iac_response_buffer_length + inc iac_response_buffer_length + sta iac_response_buffer,y + inx + txa + cmp #naws_response_length + bne :- + + + lda #telnet_state_normal + sta telnet_state + + jmp @byte_processed + + +@do_terminaltype: + lda #$fb ;WILL + jmp @add_iac_response + + @not_iac: @convert_to_native: - txa - cmp #$0a ;suppress LF (since it probably follows a CR which will have done the LF as well) - beq @byte_processed - jsr ascii_to_native - tax + txa + jsr vt100_process_inbound_char + jmp @byte_processed @no_conversion_req: - tya - pha txa jsr print_a - pla - tay @byte_processed: - iny + inc buffer_ptr bne :+ inc buffer_ptr+1 : @@ -328,13 +436,6 @@ telnet_callback: jmp @next_byte @finished: - lda iac_response_buffer_length - beq @no_iac_response - ldx #0 - stax tcp_send_data_len - ldax #iac_response_buffer - jsr tcp_send -@no_iac_response: rts ;constants @@ -342,6 +443,34 @@ closing_connection: .byte "CLOSING CONNECTION",13,0 disconnected: .byte 13,"CONNECTION CLOSED",13,0 transmission_error: .byte "ERROR WHILE SENDING ",0 +initial_telnet_options: + .byte $ff,$fb,$1F ;IAC WILL NAWS + .byte $ff,$fb,$18 ;IAC WILL TERMINAL TYPE + +initial_telnet_options_length=*-initial_telnet_options + +terminal_type_response: + .byte $ff ; IAC + .byte $fa; SB + .byte $18 ; TERMINAL TYPE + .byte $0 ; IS + .byte "xterm" ;we pretend to be a vt100 + .byte $ff ; IAC + .byte $f0 ; SE +terminal_type_response_length=*-terminal_type_response +naws_response: + .byte $ff ; IAC + .byte $fa; SB + .byte $1F ; NAWS + .byte $00 ; width (high byte) + .byte 40 ; width (low byte) + .byte $00 ; height (high byte) + .byte 25 ; height (low byte) + + .byte $ff ; IAC + .byte $f0 ; SE + +naws_response_length=*-naws_response ;variables .segment "APP_SCRATCH" telnet_ip: .res 4 ;ip address of remote server @@ -352,19 +481,23 @@ telnet_use_native_charset: .res 1 ; 0 means all data is translated to/from NVT A buffer_offset: .res 1 telnet_local_echo: .res 1 ;0 should mean local echo is disabled - in fact at the moment we never do local echo except in 'line mode' telnet_line_mode: .res 1 ;do characters get sent after each keypress, or can a line be created/edited and then sent only when return is pressed? -telnet_state: .res 1 telnet_command: .res 1 telnet_option: .res 1 telnet_state_normal = 0 telnet_state_got_iac = 1 telnet_state_got_command = 2 +telnet_state_got_suboption=3 buffer_length: .res 2 +telnet_state: .res 1 + iac_response_buffer: .res 64 iac_response_buffer_length: .res 1 scratch_buffer : .res 40 +iac_suboption_buffer: .res 64 +iac_suboption_buffer_length: .res 1 ;-- LICENSE FOR telnet.s -- diff --git a/client/ip65/vt100_c64.s b/client/ip65/vt100_c64.s index d25142f..904f08f 100644 --- a/client/ip65/vt100_c64.s +++ b/client/ip65/vt100_c64.s @@ -61,6 +61,10 @@ text_background_colour = col_gray_1 border_colour = col_gray_2 +.segment "APP_SCRATCH" +escape_buffer: .res $100 + + .zeropage ; --- esc mode --- @@ -121,8 +125,6 @@ Screen = $0400 ; --- escape buffer --- ; $0800 - $0bff -escape_buffer= $0800 - ; --- char --- ; $2000 - $27ff font_table = $2000 diff --git a/dist/make_dist_ip65.rb b/dist/make_dist_ip65.rb index 7aefaa8..20f9e86 100644 --- a/dist/make_dist_ip65.rb +++ b/dist/make_dist_ip65.rb @@ -8,7 +8,7 @@ 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"].each do |dir_suffix| +["","ip65","doc","cfg","drivers","inc","test","carts","examples"].each do |dir_suffix| dir_path="#{WORKING_DIR}/#{dir_suffix}" Dir.mkdir(dir_path) unless File.exist?(dir_path) end @@ -21,6 +21,12 @@ end ["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/"], diff --git a/dist/version_number.txt b/dist/version_number.txt index e5a4a5e..d941c12 100644 --- a/dist/version_number.txt +++ b/dist/version_number.txt @@ -1 +1 @@ -1.0.9 \ No newline at end of file +1.0.16 \ No newline at end of file diff --git a/doc/ip65.html b/doc/ip65.html index 77ebfd1..e9f04da 100644 --- a/doc/ip65.html +++ b/doc/ip65.html @@ -89,9 +89,11 @@ IP65 is a TCP/IP stack for 6502 based computers. Applications - Telnet - Gopher - + Telnet Client + Gopher Client + HTTP Client + HTTP Server + Ping @@ -160,6 +162,7 @@ IP65 is a TCP/IP stack for 6502 based computers.
   Release	Maintainer	Changes
   -------	----------	-------
+  2009-10-31	Jonno Downes	Added Web Application Server functions
   2009-08-02	Jonno Downes	More TCP functionality, includes telnet
   2009-07-12	Jonno Downes	Initial TCP implementation (use -DTCP to include)
   2009-03-21	Jonno Downes	Added technical reference documentation
@@ -213,10 +216,6 @@ copy:
         rts
 
-

Links

- -a2RetroSystems - home of the Uthernet Ethernet card for the Apple ][ -Vesilia - distributor for the RR-NET network adapter

License

diff --git a/doc/kipper_api_technical_reference.doc b/doc/kipper_api_technical_reference.doc index fb8d53f8a99e58ba595aa73ffb39e93a6d2960b5..7d9d6f15a10d9354ff41a3da35e08e39ee776f4e 100644 GIT binary patch delta 29127 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

$GFcm$}ALL5{L}g>w0W8aIzt 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 delta 27233 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