From b056e5bb96aede325659aff3aff411b7aeb86de0 Mon Sep 17 00:00:00 2001 From: jonnosan Date: Thu, 20 Aug 2009 14:03:02 +0000 Subject: [PATCH] git-svn-id: http://svn.code.sf.net/p/netboot65/code@184 93682198-c243-4bdb-bd91-e943c89aac3b --- client/cfg/c64prg.cfg | 2 +- client/examples/Makefile | 10 +-- client/examples/{comatomx.s => upnatom.s} | 60 +++++++-------- client/inc/nb65_constants.i | 4 +- client/inc/version.i | 2 +- client/ip65/function_dispatcher.s | 13 ++++ client/ip65/parser.s | 1 - client/nb65/Makefile | 2 +- client/nb65/set_ip_config.rb | 6 +- dist/make_dist.rb | 8 +- dist/version_number.txt | 2 +- doc/README.C64.html | 86 ++++++++++++++++++---- doc/nb65_api_technical_reference.doc | Bin 143360 -> 146432 bytes doc/netboot65.html | 6 +- 14 files changed, 134 insertions(+), 68 deletions(-) rename client/examples/{comatomx.s => upnatom.s} (90%) diff --git a/client/cfg/c64prg.cfg b/client/cfg/c64prg.cfg index b660650..f9884e3 100644 --- a/client/cfg/c64prg.cfg +++ b/client/cfg/c64prg.cfg @@ -9,7 +9,7 @@ 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; + SELF_MODIFIED_CODE: load = RAM, type = rw,define = yes, 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; diff --git a/client/examples/Makefile b/client/examples/Makefile index b82bd4c..6663bd4 100644 --- a/client/examples/Makefile +++ b/client/examples/Makefile @@ -14,20 +14,20 @@ INCFILES=\ ../inc/net.i\ all: \ - comatomx.prg \ + upnatom.prg \ %.o: %.s $(AS) $(AFLAGS) $< -comatomx.o: comatomx.s sine_data.i +upnatom.o: upnatom.s sine_data.i $(AS) $(AFLAGS) $< sine_data.i: make_sine_data.rb ruby make_sine_data.rb -comatomx.prg: comatomx.o nt2play.o $(IP65TCPLIB) $(C64PROGLIB) $(INCFILES) ../cfg/c64prg.cfg - $(LD) -m comatomx.map -vm -C ../cfg/c64prg.cfg -o comatomx.prg $(AFLAGS) $< $(IP65TCPLIB) $(C64PROGLIB) $(NT2PLAY) - cp comatomx.prg ../../server/boot/ +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/ clean: rm -f *.o *.pg2 *.prg *.map diff --git a/client/examples/comatomx.s b/client/examples/upnatom.s similarity index 90% rename from client/examples/comatomx.s rename to client/examples/upnatom.s index 560b6c2..20c0f6e 100644 --- a/client/examples/comatomx.s +++ b/client/examples/upnatom.s @@ -8,8 +8,6 @@ print_a = $ffd2 -.import parser_init -.import parser_skip_next SCREEN_RAM = $0400 COLOUR_RAM = $d800 @@ -260,23 +258,34 @@ init: nb65call #NB65_DOWNLOAD_RESOURCE bcs @download_feed ;if at first we don't succeed, try try again + + inc BORDER_COLOR ;little marker of success - lda #1 - sta scroll_state ldax #scroll_buffer_1 stax current_output_ptr -; jsr emit_titles + jsr emit_titles ldax #scroll_buffer_1 stax current_input_ptr_ptr ;will get picked up once we have finished going through the message once - + + lda #1 + sta scroll_state + @endless_loop: jsr NB65_PERIODIC_PROCESSING_VECTOR + lda scroll_state + beq @download_feed jmp @endless_loop reset_input_buffer: ldax current_input_ptr_ptr stax current_input_ptr + + ldax scroll_buffer_0 + stax current_input_ptr_ptr + lda #0 + sta scroll_state + rts ;look for NB65 signature at location pointed at by AX @@ -661,22 +670,6 @@ print_errorcode: -top_sprite_color_irq: - start_irq - wait_next_raster - dec $d025 ;sprite multicolor register 0 - dec $d026 ;sprite multicolor register 1 - - jmp exit_from_irq - -bottom_sprite_color_irq: - start_irq - wait_next_raster - inc $d025 ;sprite multicolor register 0 - inc $d026 ;sprite multicolor register 1 - jmp exit_from_irq - - update_nb65_counters_irq: start_irq jsr NB65_VBL_VECTOR @@ -684,18 +677,18 @@ update_nb65_counters_irq: play_music_irq: - inc BORDER_COLOR +; inc BORDER_COLOR start_irq jsr MUSIC_BASE+PLAYER_PLAY - dec BORDER_COLOR +; dec BORDER_COLOR jmp exit_from_irq emit_titles: ldax #download_buffer - jsr parser_init + nb65call #NB65_PARSER_INIT @next_title: ldax #title - jsr parser_skip_next + nb65call #NB65_PARSER_SKIP_NEXT bcs @done jsr emit_tag_contents @@ -821,7 +814,6 @@ raster_jump_table: .byte $0,$80 .word play_music_irq - .byte $80,$05 .word move_sprites_irq @@ -831,7 +823,7 @@ jump_counter: .byte 0 sprite_x_pos: -.byte $38,$58,$78,$98,$B8,$D8,$F8,$18 +.byte $34,$54,$78,$90,$Bb,$Db,$Fb,$1b sprite_x_msb: .byte $80 @@ -840,18 +832,20 @@ sprite_y_pos: .include "sine_data.i" .include "sine_data.i" -scroll_template: + sprite_text: -.byte "COMATOMX" -.byte " / ip: %i / gateway: %g / dns server %d / polling %f /" +.byte "UP\NATOM" ;options are A-Z, "[\]^_" + +scroll_template: +.byte " ip: %i / gateway: %g / dns server %d / polling %f /" .byte " ",0 feed_url: .byte "http://search.twitter.com/search.atom?q=kipper",0 -.byte "http://static.cricinfo.com/rss/livescores.xml",0 +;.byte "http://static.cricinfo.com/rss/livescores.xml",0 title: .byte "",0 @@ -902,7 +896,7 @@ scroll_state: .res 1 nb65_param_buffer: .res $20 download_buffer: -download_buffer_length=4000 +download_buffer_length=8000 .res download_buffer_length scroll_buffer_0: diff --git a/client/inc/nb65_constants.i b/client/inc/nb65_constants.i index 36b7486..b8e17fd 100644 --- a/client/inc/nb65_constants.i +++ b/client/inc/nb65_constants.i @@ -60,7 +60,9 @@ NB65_INPUT_HOSTNAME EQU $91 ;no inputs, outputs: AX = pointer to host NB65_INPUT_PORT_NUMBER EQU $92 ;no inputs, outputs: AX = port number entered ($0000..$FFFF) NB65_BLOCK_COPY EQU $A0 ;inputs: AX points to a block copy structure, outputs: none - +NB65_PARSER_INIT EQU $A1 ;inputs: AX points to a null terminated string, outputs: none +NB65_PARSER_SKIP_NEXT EQU $A2 ;inputs: AX points to a null terminated substring, outputs: AX points to + ;previously loaded string that is just past the next occurance of substring NB65_GET_LAST_ERROR EQU $FF ;no inputs, outputs A EQU error code (from last function that set the global error value, not necessarily the ;last function that was called) diff --git a/client/inc/version.i b/client/inc/version.i index a99521c..433ab7a 100644 --- a/client/inc/version.i +++ b/client/inc/version.i @@ -1 +1 @@ -.byte "0.9.21" +.byte "0.9.24" diff --git a/client/ip65/function_dispatcher.s b/client/ip65/function_dispatcher.s index 1a13832..2d11e6a 100644 --- a/client/ip65/function_dispatcher.s +++ b/client/ip65/function_dispatcher.s @@ -603,6 +603,19 @@ cpy #NB65_BLOCK_COPY ldax tmp_copy_length jmp copymem : + + cpy #NB65_PARSER_INIT + bne :+ + .import parser_init + jmp parser_init +: + + cpy #NB65_PARSER_SKIP_NEXT + bne :+ + .import parser_skip_next + jmp parser_skip_next +: + .endif .endif diff --git a/client/ip65/parser.s b/client/ip65/parser.s index b880579..21c7e62 100644 --- a/client/ip65/parser.s +++ b/client/ip65/parser.s @@ -7,7 +7,6 @@ .importzp copy_src .importzp copy_dest - target_string=copy_src search_string=copy_dest diff --git a/client/nb65/Makefile b/client/nb65/Makefile index 735475f..f9ee1e6 100644 --- a/client/nb65/Makefile +++ b/client/nb65/Makefile @@ -22,7 +22,7 @@ APPLE2PROGLIB=../drivers/apple2prog.lib BOOTA2.PG2=../../server/boot/BOOTA2.PG2 #all: utherboot.dsk $(BOOTA2.PG2) nb65_rrnet.bin nb65_std_cart.bin nb65_c64_ram.prg d64_upload.prg c64boot.d64 d64_upload.d64 -all: nb65_std_cart.bin nb65_tcp_cart.bin nb65_tcp_cart_rr.bin +all: nb65_std_cart.bin nb65_tcp_cart.bin nb65_tcp_cart_rr.bin nb65_c64_ram.prg nb65_c64_ram.o: nb65_c64.s $(INCFILES) $(AS) -DBANKSWITCH_SUPPORT=0 $(AFLAGS) -o $@ $< diff --git a/client/nb65/set_ip_config.rb b/client/nb65/set_ip_config.rb index 730a686..acfb4af 100644 --- a/client/nb65/set_ip_config.rb +++ b/client/nb65/set_ip_config.rb @@ -41,11 +41,13 @@ end filebytes=File.open(filename,"rb").read - if !(filebytes[0x09,4]=="NB65") then +start_of_nb65_cart_image=filebytes.index("80NB65") + if start_of_nb65_cart_image.nil? then puts "file '#{filename}' does not appear to be a netboot65 cartridge image" exit end + (number_of_options/2).times do |i| option=ARGV[i*2+1] value=ARGV[i*2+2] @@ -56,7 +58,7 @@ end show_options exit end - option_offset=offsets[0] + option_offset=start_of_nb65_cart_image+offsets[0]-7 option_length=offsets[1] if option_length==6 then diff --git a/dist/make_dist.rb b/dist/make_dist.rb index 6477987..4dbeaa9 100644 --- a/dist/make_dist.rb +++ b/dist/make_dist.rb @@ -18,19 +18,21 @@ version_string=File.open(VERSION_FILE).read end [ -["client/nb65/utherboot.dsk","a2/"], +#["client/nb65/utherboot.dsk","a2/"], ["client/nb65/set_ip_config.rb","bin/"], #["client/nb65/nb65_rrnet.bin","c64/"], ["client/nb65/nb65_c64_ram.prg","c64/"], ["client/nb65/nb65_std_cart.bin","c64/"], ["client/nb65/nb65_tcp_cart.bin","c64/"], +["client/nb65/nb65_tcp_cart_rr.bin","c64/"], ["client/nb65/d64_upload.prg","boot/"], +["client/examples/upnatom.prg","boot/"], ["server/lib/tftp_server.rb","lib"], ["server/lib/file_list.rb","lib"], ["server/bin/tftp_only_server.rb","bin/tftp_server.rb"], -["server/bin/import_ags_games.rb","bin"], +#["server/bin/import_ags_games.rb","bin"], #["server/boot/BOOTA2.PG2","boot"], -["doc/README.Apple2.html","a2"], +#["doc/README.Apple2.html","a2"], ["doc/README.C64.html","c64"], ["doc/netboot65.html","doc/index.html"], #["doc/README.Apple2.html","doc"], diff --git a/dist/version_number.txt b/dist/version_number.txt index fc6d9f6..f76e5a8 100644 --- a/dist/version_number.txt +++ b/dist/version_number.txt @@ -1 +1 @@ -0.9.21 \ No newline at end of file +0.9.24 \ No newline at end of file diff --git a/doc/README.C64.html b/doc/README.C64.html index 02515c3..265d3ce 100644 --- a/doc/README.C64.html +++ b/doc/README.C64.html @@ -1,20 +1,26 @@ <h1>NETBOOT65 FOR THE C64</h1> -<h2>STARTING THE SERVER</h2> -<ol> - <li> unzip the archive somewhere on your local hard drive</li> - <li>start the bin/tftp_server.rb script (e.g. by double-clicking on it)</li> -</ol> +There are 2 major 'flavours' of the NB65 client, the major difference being whether the cart supports UDP only (but allows access to BASIC), or UDP + TCP (but loses access to BASIC). The +reason for this is the UDP only version of the client fits into an 8KB cartridge, whereas the TCP code pushes the cartridge size up to 16KB, and the upper half of a 16KB cartridge sits in the same +memory location as BASIC. +<p> +Within the major flavours, there are also variations in media - the majority of code is identical between the different media but there are different headers etc. The supported media are: +<p> +<ul> + <li> A prg that can be loaded from disk </li> + <li>'ordinary' cartridge images (that can be burned into an eeprom on e.g. a 64NIC+ card)</li> + <li>'Retro Replay' cartridge images - these are actually 'ordinary' cartridge images that have been converted into a form suitable for use in a Retro Replay using Doc Bacardi's + <a href=http://freenet-homepage.de/LittleDreamLand/CRT8040.html>CRT8040</a> tool</li> +</ul> -<h2>TO USE WITH VICE</h2> -Run <a href=http://www.viceteam.org/>VICE</a> with the nb65_std_cart.bin cartridge image attached (e.g. "x64.exe -cart8 nb65_std_cart.bin") +<table> +<tr><th>filename</th><th>flavour</th><th>media</th><th>command to use in VICE</th></tr> +<tr><td>nb65_c64_ram.prg</td><td>UDP only (+ BASIC)</td><td>RAM</td><td> x64.exe nb65_c64_ram.prg</td></tr> +<tr><td>nb65_std_cart.bin</td><td>UDP only (+ BASIC)</td><td>standard 8KB cart</td><td>x64.exe -cart8 nb65_std_cart.bin</td></tr> +<tr><td>nb65_tcp_cart.bin</td><td>UDP/TCP (no BASIC)</td><td>standard 16KB cart</td><td>x64.exe -cart16 nb65_tcp_cart.bin</td></tr> +<tr><td>nb65_tcp_cart_rr.bin</td><td>UDP/TCP (no BASIC)</td><td>Retro Replay cart image</td><td>x64.exe -cartrr nb65_tcp_cart_rr.bin</td></tr> +</table> -<h2>TO USE WITH A REAL C64</h2> -<h3>Option 1 - Hardcore</h3> - burn the nb65_std_cart.bin cartridge to an EPROM and insert in an 8KB cartridge (which should be set up to have EXROM=0, GAME=1) - -<h3>Option 2 - Just dabbling</h3> -You can just run the nb65_c64_ram.prg program (which is essentially the cartridge image plus a loader prg to insert the image into the right place in RAM). <h2>USING THE CARTRIDGE</h2> @@ -22,23 +28,71 @@ When the cartridge starts, it will attempt to configure the IP stack via DHCP. I then the IP stack will fall back to using the IP configuration built into the cartridge. See the section "IP CONFIGURATION" for info on how to modify the cartridge defaults prior to burning an image. <p> -Once the IP stack is initialised, the "main menu" screen will be displayed. From the main menu, the following options are available: +Once the IP stack is initialised, the "main menu" screen will be displayed. There are slight variations between the menus shown on the 2 "flavours". +<h3>Main Menu - UDP only carts</h3> <ul> - <li>F1 : TFTP BOOT. THis will query a TFTP server for a list of PRG files, and allow the selection of a file to be downloaded and executed.</li> + <li>F1 : TFTP BOOT. This will query a TFTP server for a list of PRG files, and allow the selection of a file to be downloaded and executed. Most 'single load' applications should work</li> <li>F3 : BASIC. This will exit to BASIC (with IP stack still configured, so NB65 aware apps can be loaded from disk and run)</li> <li>F5 : ARP TABLE. This will show a table of the current mapping of IP and MAC addresses </li> <li>F7 : CONFIG. This brings up a menu where the IP configuration can be modified. Changes made here will be persistent until the next reboot.</li> </ul> + +<h3>Main Menu - UDP/TCP carts</h3> +<ul> + <li>F1 : TFTP BOOT. This will query a TFTP server for a list of PRG files, and allow the selection of a file to be downloaded and executed. This version of TFTP BOOT is restricted to running only + pure machine language programs, since BASIC is not available when this cart is active. (NB - programs that are pure M/L except for a BASIC stub consisting of a single SYS call will be executed). + be loaded </li> + <li>F3 : NET APPS. This will bring up another menu of network-orientated applications (see below for more details). + <li>F5 : ARP TABLE. This will show a table of the current mapping of IP and MAC addresses </li> + <li>F7 : CONFIG. This brings up a menu where the IP configuration can be modified. Changes made here will be persistent until the next reboot.</li> +</ul> + +<h3>Net Apps - UDP/TCP carts</h3> +<ul> + <li>F1 : TELNET. You will be prompted to enter a hostname, a port number, and a connection mode. Connection mode is either + <ul> + <li>ASCII - . keypresses are converted to ASCII before being sent out, and incoming data is converted to PETSCII before being displayed. + There is no terminal emulation, and keystrokes are sent a character at a time.</li> + <li>PETSCII - no translation is done on data coming in or out. This mode is suitable for connecting to PETSCII BBSs</li> + <li>Line - Data is converted to/from ASCII, but each line of input can be edited and is not sent until the RETURN key is pressed.</li> + </ul> + Once a connection is made, it can be terminated by hitting RUN/STOP + <li>F3 : GOPHER.FLOODGAP.COM. This will launch the Gopher client, and connect to the gopher portal at gopher://gopher.floodgap.com/</li> + <li>F5 : GOPHER. You will be prompted to enter the hostname (only - no port number can be specified) of a gopher server, and the gopher client will be launched connecting to the specified server. + <li>F7 : MAIN MENU. This will return to the main menu.</li> +</ul> + +<h3>Gopher Client - UDP/TCP carts</h3> +Once a gopher resource is loaded, the following keys are active: +<ul> +<li>SPACE, F7 or down arrow : scroll down to next page +<li>F1 or up arror : scroll up to previous page +<li>F2 : show recently visited resource +<li>F3 or left arrow : go back to last visited resource +<li>F5 : prompt to enter a new server (nb server name only - not resource or port) +<li>RUN/STOP : quit +</ul> +If the page currently being displayed has links to further resources in it, each link will be displayed +starting with a highlighted letter (e.g. the first link on a page will have an inverse "A" next to it, +the 2nd link on a page will have an inverse "B" next to it etc). Press the letter assigned to the link +to load up that resource. + + <h2>IP CONFIGURATION</h2> There is a script in the "bin" folder called "set_ip_config.rb" that can be used to modify the MAC address and IP config details in the cart image before it is burned. For example, to set the MAC address and DNS servers, use this command: <pre>set_ip_config.rb nb65_std_cart.bin mac ab:cd:ef:12:34:56 dns 10.5.1.1</pre> run "set_ip_config.rb" with no parameters to see all the options for what can be configured. +<h2>STARTING THE SERVER</h2> +<ol> + <li> unzip the archive somewhere on your local hard drive</li> + <li>start the bin/tftp_server.rb script (e.g. by double-clicking on it)</li> +</ol> <h2>ADDING MORE FILES</h2> -Only single-load files can be used (this may change in a future release). The files need to be in "PRG" format, i.e.the first 2 bytes of the file must be +Only single-load files can be used. The files need to be in "PRG" format, i.e.the first 2 bytes of the file must be the load address (little-endian, i.e. low/high). The files also need to have a file extension of ".PRG" (in upper case, if your operating system of choice is case sensitive). <p> diff --git a/doc/nb65_api_technical_reference.doc b/doc/nb65_api_technical_reference.doc index be2acc31256149e41900262e84c0b36f031c4b97..79088115180361e699df1ee8b4b82dcf005910ef 100644 GIT binary patch delta 15182 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 BzdQf{ delta 13721 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 A9RL6T diff --git a/doc/netboot65.html b/doc/netboot65.html index a8502b2..8fa316c 100644 --- a/doc/netboot65.html +++ b/doc/netboot65.html @@ -79,10 +79,10 @@ td { <h1>netboot65</h1> <p> -netboot65 is a project to support network booting C64 and Apple ][computers. It is based on the <a href=http://ip65.sourceforge.net/>IP65 TCP/IP stack</a>. Current components are: +netboot65 is a project to support network booting Commodore 64 computers. It is based on the <a href=http://ip65.sourceforge.net/>IP65 TCP/IP stack</a>. Current components are: <ul> <li>a server (written in <a href=http://www.ruby-lang.org/>ruby</a> for maximum portability) that provides a TFTP server with some proprietary extensions to allow clients to request a directory listing. -<li>clients (currently available as a disk image for Apple ][, and either a cartridge or a standalone prg file for C64) that initialises an IP stack, acquires an IP address via DHCP, queries the local LAN for a TFTP server, +<li>clients (currently <!--available as a disk image for Apple ][, and either--> a cartridge or a standalone prg file for C64) that initialises an IP stack, acquires an IP address via DHCP, queries the local LAN for a TFTP server, and then allows a program file to be downloaded via TFTP and executed. Currently only 'single load' programs are supported, but many old games and utility programs can be run in this way. <li>the NB65 API (currently for C64 only) that allows for IP aware applications to be developed without being tied to a specific MAC address, IP address or network device, as is the case with most existing IP libraries for 6502 computers. @@ -95,7 +95,7 @@ IP libraries for 6502 computers. <h2>Documentation</h2> <ul> <li><a href=README.C64.html>C64 documentation</a> -<li><a href=README.Apple2.html>Apple ][ documentation</a> +<!--<li><a href=README.Apple2.html>Apple ][ documentation</a>--> <li><a href="nb65_api_technical_reference.doc">NB65 API Technical Reference (word doc)</a> </ul>