diff --git a/client/cfg/c64_16kcart.cfg b/client/cfg/c64_16kcart.cfg
index b3dc4bf..e0d661e 100644
--- a/client/cfg/c64_16kcart.cfg
+++ b/client/cfg/c64_16kcart.cfg
@@ -1,7 +1,7 @@
# CA65 config for a 16KB cart
MEMORY {
- IP65ZP: start = $A3, size = $13, type = rw, define = yes;
+ IP65ZP: start = $20, size = $13, type = rw, define = yes; #this cart replaces BASIC so ok to use that space
HEADER: start = $8000, size = $18, file = %O;
DEFAULTS: start = $8018, size = $1E, file = %O;
ROM: start = $8036, size = $3FC8, define = yes, file = %O;
diff --git a/client/drivers/c64_disk_access.s b/client/drivers/c64_disk_access.s
index 53a88f4..fd79bc2 100644
--- a/client/drivers/c64_disk_access.s
+++ b/client/drivers/c64_disk_access.s
@@ -14,15 +14,17 @@
.export io_read_sector
.export io_read_catalogue
.export io_read_catalogue_ex
-
+.export io_read_file
.export io_read_file_with_callback
.export io_filename
+.export io_filesize
+.export io_load_address
.export io_callback
.importzp copy_src
.import ip65_error
.import output_buffer
-;.importzp copy_dest
+.importzp copy_dest
;reuse the copy_src zero page location
buffer_ptr = copy_src
@@ -45,6 +47,8 @@ SETLFS = $ffba
io_sector_no: .res 1
io_device_no: .byte 0
io_filename: .res 2
+ io_filesize: .res 2 ;although a file on disk can be >64K, io_filesize is only used when loading into RAM hence file must be <64K
+ io_load_address: .res 2
error_buffer = output_buffer + 256
command_buffer = error_buffer+128
sector_buffer_address: .res 2
@@ -71,6 +75,63 @@ tmp_buffer_ptr=write_byte_to_buffer+1
.code
+;routine to read a file
+; inputs:
+; io_device_number - specifies drive to use ($00 = same as last time, $01 = first disk (i.e. #8), $02 = 2nd disk (drive #9))
+; io_filename - specifies filename to open
+; AX - address of buffer to read file into (set to $0000 to treat first 2 bytes as load address)
+; outputs:
+; on errror, carry flag is set
+; otherwise, io_filesize will be set to size of file and io_load_address will be set to actual load address used.
+;
+io_read_file:
+ stax io_load_address
+ sta sector_buffer_address
+ stx sector_buffer_address+1 ;this also sets the Z flag
+ bne @sector_buffer_address_set
+ ;if we get here, X was $00 so we need to use first 2 bytes of file as load address
+ ldax #output_buffer
+ stax sector_buffer_address
+
+@sector_buffer_address_set:
+ ldax #read_file_callback
+ stax io_callback
+ lda #0
+ sta io_filesize
+ sta io_filesize+1
+ ldax sector_buffer_address
+ jsr io_read_file_with_callback
+ rts
+
+read_file_callback:
+ sty io_filesize ;only 1 (the last) sector can ever be !=$100 bytes
+ bne @not_full_sector
+ inc io_filesize+1
+ inc sector_buffer_address +1
+@not_full_sector:
+ lda io_load_address+1 ;is the high byte of the address $00?
+ bne @done
+ ldax output_buffer ;if we get here we must have used downloaded into the static output buffer, so the
+ ;first 2 bytes there are the real load address
+ stax copy_dest ;now copy the rest of the sector
+ stax sector_buffer_address
+ stax io_load_address
+ dey
+ dey
+@copy_one_byte:
+ dey
+ lda output_buffer+2,y
+ sta (copy_dest),y
+ inc sector_buffer_address
+ bne :+
+ inc sector_buffer_address+1
+:
+ tya
+ bne @copy_one_byte
+
+@done:
+ rts
+
;routine to read a file with a callback after each 256 byte sector
; inputs:
; io_device_number - specifies drive to use ($00 = same as last time, $01 = first disk (i.e. #8), $02 = 2nd disk (drive #9))
@@ -132,8 +193,8 @@ io_read_file_with_callback:
sta (buffer_ptr),y
inc buffer_counter
bne @get_next_byte
-
ldy #$00;= 256 bytes
+
jsr jmp_to_callback
jmp @get_next_sector
diff --git a/client/examples/Makefile b/client/examples/Makefile
index 6663bd4..f456e0f 100644
--- a/client/examples/Makefile
+++ b/client/examples/Makefile
@@ -13,8 +13,7 @@ INCFILES=\
../inc/commonprint.i\
../inc/net.i\
-all: \
- upnatom.prg \
+all: upnatom.prg upnatom.d64
%.o: %.s
$(AS) $(AFLAGS) $<
@@ -27,9 +26,15 @@ 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/
+
+upnatom.d64: upnatom.prg url.cfg
+ cp upnatom.prg autoexec.prg
+ ripxplore.rb --init CbmDos upnatom.d64 -a autoexec.prg
+ ripxplore.rb upnatom.d64 -a url.cfg -t C64Seq
+
clean:
- rm -f *.o *.pg2 *.prg *.map
+ rm -f *.o *.pg2 *.prg *.map upnatom.d64
distclean: clean
rm -f *~
diff --git a/client/examples/upnatom.s b/client/examples/upnatom.s
index efdd8e9..a285f20 100644
--- a/client/examples/upnatom.s
+++ b/client/examples/upnatom.s
@@ -139,9 +139,19 @@ init:
@init_ok:
;if we got here, we have found the NB65 API and initialised the IP stack
-
- jsr setup_static_scroll_text
+;try and load the config file
+ ldax #read_url_file_param_buffer
+ nb65call #NB65_FILE_LOAD
+ bcs @use_default_url
+ clc
+ lda #0
+ ldy read_url_file_param_buffer+NB65_FILE_ACCESS_FILESIZE
+ sta feed_url,y ;put a zero at the end of the URL
+
+@use_default_url:
+ jsr setup_static_scroll_text
+
lda #0
jsr clear_screen
lda #DARK_GRAY
@@ -243,9 +253,12 @@ init:
jsr reset_input_buffer
+ lda #0
+ sta scroll_buffer_1 ;set this buffer to be an empty string, in case we try to scroll it
+
;now download the feed
@download_feed:
-
+
ldax #feed_url
stax nb65_param_buffer+NB65_URL
ldax #download_buffer
@@ -334,7 +347,7 @@ setup_sprites:
tay
lda sprite_x_pos,x
sta $d000,y ;sprite 0 X pos (LSB)
- lda 0
+ lda #0
sta $d001,y ;sprite 0 Y pos
;colour sprite 0
@@ -534,6 +547,7 @@ setup_static_scroll_text:
stax current_input_ptr
@next_byte:
jsr get_a
+ beq @next_byte
cmp #'%'
beq @operator
pha
@@ -564,7 +578,8 @@ setup_static_scroll_text:
ldy #0
@copy_feed_url_loop:
lda feed_url,y
- beq @next_byte
+ cmp #$20
+ bcc @next_byte ;any control char (including CR,LF, and $00) should be treated as end of URL
jsr emit_a
iny
bne @copy_feed_url_loop
@@ -840,10 +855,11 @@ sprite_x_msb:
.byte $80
sprite_y_pos:
-.include "sine_data.i"
.repeat 128
.byte 0
.endrep
+.include "sine_data.i"
+
;.include "sine_data.i"
@@ -859,8 +875,22 @@ scroll_template:
feed_url:
-;.byte "http://search.twitter.com/search.atom?q=kipper",0
-.byte "http://static.cricinfo.com/rss/livescores.xml",0
+.byte "http://search.twitter.com/search.atom?q=kipper",0
+;leave space for whatever we read in from disk
+.repeat 128
+.byte 0
+.endrep
+
+url_config_file:
+
+.byte "URL.CFG",0
+
+read_url_file_param_buffer:
+ .word url_config_file ;NB65_FILE_ACCESS_FILENAME
+ .word feed_url ;B65_FILE_ACCESS_POINTER
+ .word $0000 ;NB65_FILE_ACCESS_FILESIZE - should be filled in
+ .byte $00 ;NB65_FILE_ACCESS_DEVICE
+
title:
.byte "
",0
diff --git a/client/examples/url.cfg b/client/examples/url.cfg
new file mode 100644
index 0000000..8fa7f64
--- /dev/null
+++ b/client/examples/url.cfg
@@ -0,0 +1 @@
+http://static.cricinfo.com/rss/livescores.xml
\ No newline at end of file
diff --git a/client/inc/nb65_constants.i b/client/inc/nb65_constants.i
index 0573ce4..a4bfc4f 100644
--- a/client/inc/nb65_constants.i
+++ b/client/inc/nb65_constants.i
@@ -48,6 +48,8 @@ NB65_DNS_RESOLVE EQU $30 ;inputs: AX points to a DNS parameter str
NB65_DOWNLOAD_RESOURCE EQU $31 ;inputs: AX points to a URL download structure, outputs: none
NB65_PING_HOST EQU $32 ;inputs: AX points to destination IP address for ping, outputs: AX=time (in milliseconds) to get response
+NB65_FILE_LOAD EQU $40 ;inputs: AX points to a file access parameter structure, outputs: none
+
NB65_PRINT_ASCIIZ EQU $80 ;inputs: AX=pointer to null terminated string to be printed to screen, outputs: none
NB65_PRINT_HEX EQU $81 ;inputs: A=byte digit to be displayed on screen as (zero padded) hex digit, outputs: none
NB65_PRINT_DOTTED_QUAD EQU $82 ;inputs: AX=pointer to 4 bytes that will be displayed as a decimal dotted quad (e.g. 192.168.1.1)
@@ -83,6 +85,7 @@ NB65_TFTP_FILESIZE EQU $04 ;2 byte file length (filled in
;offsets in TFTP Server parameter structure (used by NB65_TFTP_SET_SERVER)
NB65_TFTP_SERVER_IP EQU $00 ;4 byte IP address of TFTP server
+
;offsets in DNS parameter structure (used by NB65_DNS_RESOLVE)
NB65_DNS_HOSTNAME EQU $00 ;2 byte pointer to asciiz hostname to resolve (can also be a dotted quad string)
NB65_DNS_HOSTNAME_IP EQU $00 ;4 byte IP address (filled in on succesful resolution of hostname)
@@ -106,6 +109,8 @@ NB65_TCP_CALLBACK EQU $06 ;2 byte address of routine
NB65_TCP_PAYLOAD_LENGTH EQU $00 ;2 byte length of payload of packet (after all ethernet,IP,UDP/TCP headers)
NB65_TCP_PAYLOAD_POINTER EQU $02 ;2 byte pointer to payload of packet (after all headers)
+
+
;offsets in TCP/UDP packet parameter structure
NB65_REMOTE_IP EQU $00 ;4 byte IP address of remote machine (src of inbound packets, dest of outbound packets)
NB65_REMOTE_PORT EQU $04 ;2 byte port number of remote machine (src of inbound packets, dest of outbound packets)
@@ -125,6 +130,13 @@ NB65_URL EQU $00 ;2 byte pointer to null te
NB65_URL_DOWNLOAD_BUFFER EQU $02 ;2 byte pointer to buffer that resource specified by URL will be downloaded into
NB65_URL_DOWNLOAD_BUFFER_LENGTH EQU $04 ;2 byte length of buffer (download will truncate when buffer is full)
+
+;offsets in file access parameter structure (used by NB65_FILE_LOAD)
+NB65_FILE_ACCESS_FILENAME EQU $00 ;2 byte pointer to asciiz filename (or filemask)
+NB65_FILE_ACCESS_POINTER EQU $02 ;2 byte pointer to memory location data to be stored in OR address of callback function
+NB65_FILE_ACCESS_FILESIZE EQU $04 ;2 byte file length (filled in by NB65_FILE_ACCESS)
+NB65_FILE_ACCESS_DEVICE EQU $06 ;1 byte device number (set to $00 to use last accessed device)
+
;error codes (as returned by NB65_GET_LAST_ERROR)
NB65_ERROR_PORT_IN_USE EQU $80
NB65_ERROR_TIMEOUT_ON_RECEIVE EQU $81
diff --git a/client/inc/version.i b/client/inc/version.i
index 6e356b6..7189cc2 100644
--- a/client/inc/version.i
+++ b/client/inc/version.i
@@ -1 +1 @@
-.byte "0.9.25"
+.byte "0.9.30"
diff --git a/client/ip65/function_dispatcher.s b/client/ip65/function_dispatcher.s
index db51f24..1fc86a8 100644
--- a/client/ip65/function_dispatcher.s
+++ b/client/ip65/function_dispatcher.s
@@ -62,7 +62,7 @@ ip_configured_flag:
.code
irq_handler:
- jsr NB65_VBL_VECTOR
+ jsr NB65_VBL_VECTOR
jmp jmp_old_irq
@@ -473,7 +473,54 @@ ip_configured:
jmp url_download
:
-
+ cpy #NB65_FILE_LOAD
+bne :+
+.import io_device_no
+.import io_read_file
+.import io_filename
+.import io_filesize
+.import io_load_address
+ phax
+ ldy #NB65_FILE_ACCESS_FILENAME
+ lda (nb65_params),y
+ sta io_filename
+ iny
+ lda (nb65_params),y
+ sta io_filename+1
+
+ ldy #NB65_FILE_ACCESS_DEVICE
+ lda (nb65_params),y
+ sta io_device_no
+
+ ldy #NB65_FILE_ACCESS_POINTER+1
+ lda (nb65_params),y
+ tax
+ dey
+ lda (nb65_params),y
+ jsr io_read_file
+ plax
+ bcc @read_file_ok
+ rts
+
+@read_file_ok:
+ stax nb65_params
+
+ ldy #NB65_FILE_ACCESS_POINTER
+ lda io_load_address
+ sta (nb65_params),y
+ iny
+ lda io_load_address+1
+ sta (nb65_params),y
+
+ ldy #NB65_FILE_ACCESS_FILESIZE
+ lda io_filesize
+ sta (nb65_params),y
+ iny
+ lda io_filesize+1
+ sta (nb65_params),y
+ rts
+:
+
cpy #NB65_PING_HOST
.import icmp_echo_ip
.import icmp_ping
diff --git a/client/ip65/url.s b/client/ip65/url.s
index d977566..a8e709c 100644
--- a/client/ip65/url.s
+++ b/client/ip65/url.s
@@ -76,6 +76,7 @@ selector_buffer=output_buffer
;parses a URL into a form that makes it easy to retrieve the specified resource
;inputs:
;AX = address of URL string
+;any control character (i.e. <$20) is treated as 'end of string', e.g. a CR or LF, as well as $00
;outputs:
; sec if a malformed url, otherwise:
; url_ip = ip address of host in url
@@ -107,7 +108,7 @@ url_parse:
cmp #'H'
beq @http
@exit_with_error:
- lda #NB65_ERROR_MALFORMED_URL
+ lda #NB65_ERROR_MALFORMED_URL
sta ip65_error
@exit_with_sec:
sec
@@ -195,7 +196,8 @@ lda #url_type_gopher
@copy_one_byte:
ldy src_ptr
lda (copy_src),y
- beq @end_of_selector
+ cmp #$20
+ bcc @end_of_selector ;any control char (including CR,LF, and $00) should be treated as end of URL
inc src_ptr
@save_first_byte_of_selector:
ldy dest_ptr
diff --git a/client/nb65/nb65_c64.s b/client/nb65/nb65_c64.s
index 6ffddb0..467441d 100644
--- a/client/nb65/nb65_c64.s
+++ b/client/nb65/nb65_c64.s
@@ -111,8 +111,8 @@
.import __SELF_MODIFIED_CODE_SIZE__
.import cfg_tftp_server
- tftp_dir_buffer = $6020
nb65_param_buffer = $6000
+ directory_buffer = $6020
.data
exit_cart:
@@ -219,12 +219,14 @@ init:
ldax #$2000
jsr copymem
.endif
-
-ldax #init_msg
+
+ ldax #netboot65_msg
+ jsr print
+ ldax #init_msg+1
jsr print
nb65call #NB65_INITIALIZE
- bcc main_menu
+ bcc init_ok
print_failed
jsr print_errorcode
jsr wait_for_keypress
@@ -239,6 +241,26 @@ print_main_menu:
ldax #main_menu_msg
jmp print
+init_ok:
+.if (BANKSWITCH_SUPPORT=$03)
+;look for an 'autoexec' file
+ jsr print_cr
+ ldax #loading_msg
+ jsr print
+ ldax #autoexec_filename
+ stax io_filename
+ jsr print
+ jsr print_cr
+ ldax #$0000
+ jsr io_read_file
+ bcs main_menu
+@file_read_ok:
+ ldax #load_ok_msg
+ jsr print
+ ldax io_load_address
+ jmp boot_into_file
+.endif
+
main_menu:
jsr print_main_menu
jsr print_ip_config
@@ -250,6 +272,12 @@ main_menu:
bne @not_tftp
jmp @tftp_boot
@not_tftp:
+.if (BANKSWITCH_SUPPORT=$03)
+ cmp #KEYCODE_F2
+ bne @not_disk
+ jmp disk_boot
+ @not_disk:
+.endif
cmp #KEYCODE_F3
.if (BANKSWITCH_SUPPORT=$03)
@@ -441,17 +469,15 @@ cmp #KEYCODE_F7
jsr wait_for_keypress
jsr @change_config
-
@tftp_boot:
-
ldax #tftp_dir_filemask
@get_tftp_directory_listing:
stax nb65_param_buffer+NB65_TFTP_FILENAME
- ldax #tftp_dir_buffer
+ ldax #directory_buffer
stax nb65_param_buffer+NB65_TFTP_POINTER
ldax #getting_dir_listing_msg
@@ -462,7 +488,7 @@ cmp #KEYCODE_F7
bcs @dir_failed
- lda tftp_dir_buffer ;get the first byte that was downloaded
+ lda directory_buffer ;get the first byte that was downloaded
bne :+
jmp @no_files_on_server
:
@@ -472,7 +498,7 @@ cmp #KEYCODE_F7
sta $d018
- ldax #tftp_dir_buffer
+ ldax #directory_buffer
jsr select_option_from_menu
bcc @tftp_filename_set
@@ -513,7 +539,7 @@ cmp #KEYCODE_F7
@dir_failed:
- ldax #tftp_dir_listing_fail_msg
+ ldax #dir_listing_fail_msg
jsr print
jsr print_errorcode
jsr print_cr
@@ -522,22 +548,27 @@ cmp #KEYCODE_F7
jmp @tftp_filename_set
@no_files_on_server:
- ldax #no_files_on_server
+ ldax #no_files
jsr print
jmp @tftp_boot_failed
-@file_downloaded_ok:
+@file_downloaded_ok:
+ldax nb65_param_buffer+NB65_TFTP_POINTER
+boot_into_file:
+ stax nb65_param_buffer ;use the param buffer as a temp holding place for the load address
;get ready to bank out
nb65call #NB65_DEACTIVATE
+
+ jsr $ffe7 ; make sure all files have been closed.
;check whether the file we just downloaded was a BASIC prg
- lda nb65_param_buffer+NB65_TFTP_POINTER
+ lda nb65_param_buffer
cmp #01
bne @not_a_basic_file
- lda nb65_param_buffer+NB65_TFTP_POINTER+1
+ lda nb65_param_buffer+1
cmp #$08
bne @not_a_basic_file
@@ -545,6 +576,7 @@ cmp #KEYCODE_F7
lda $805
cmp #$9e ;opcode for 'SYS'
bne @not_a_basic_stub
+
ldax #$806 ;should point to ascii string containing address that was to be SYSed
jsr parse_integer
jmp exit_cart_via_ax ;good luck!
@@ -569,14 +601,75 @@ cmp #KEYCODE_F7
jmp exit_cart_via_ax
.endif
-@not_a_basic_file:
- ldax nb65_param_buffer+NB65_TFTP_POINTER
+@not_a_basic_file:
+ ldax nb65_param_buffer
exit_cart_via_ax:
sta call_downloaded_prg+1
stx call_downloaded_prg+2
jmp exit_cart
.if (BANKSWITCH_SUPPORT=$03)
+disk_boot:
+ .import io_read_catalogue
+ .import io_device_no
+ .import io_filename
+ .import io_read_file
+ .import io_load_address
+ lda #00 ;use default drive
+ sta io_device_no
+
+ ldax #directory_buffer
+ jsr io_read_catalogue
+
+ lda directory_buffer ;get the first byte that was downloaded
+ bne :+
+ jmp @no_files_on_disk
+:
+
+ ;switch to lower case charset
+; lda #23
+; sta $d018
+
+
+ ldax #directory_buffer
+
+ jsr select_option_from_menu
+ bcc @disk_filename_set
+ jmp main_menu
+
+@dir_failed:
+ ldax #dir_listing_fail_msg
+@print_error:
+ jsr print
+ jsr print_errorcode
+ jsr print_cr
+ jmp @wait_keypress_then_return_to_main
+
+@no_files_on_disk:
+ ldax #no_files
+ jsr print
+@wait_keypress_then_return_to_main:
+ jsr wait_for_keypress
+ jmp main_menu
+
+@disk_filename_set:
+ stax io_filename
+ ldax #loading_msg
+ jsr print
+ ldax io_filename
+ jsr print
+ jsr print_cr
+ ldax #$0000
+ jsr io_read_file
+ bcc @file_read_ok
+ ldax #file_read_error
+ jmp @print_error
+@file_read_ok:
+ ldax #load_ok_msg
+ jsr print
+ ldax io_load_address
+ jmp boot_into_file
+
net_apps_menu:
jsr cls
ldax #netboot65_msg
@@ -706,24 +799,29 @@ exit_gopher:
jsr print_a
jmp net_apps_menu
.endif
- .rodata
+
+
+.rodata
netboot65_msg:
.byte 13,"NB65 - V"
.include "../inc/version.i"
+.if (BANKSWITCH_SUPPORT=$03)
+.byte " (TCP)"
+.endif
.byte 13,0
main_menu_msg:
.byte 13,"MAIN MENU",13,13
-.byte "F1: TFTP BOOT"
.if (BANKSWITCH_SUPPORT=$03)
-.byte " F3: NET APPS"
-.else
-.byte " F3: BASIC"
-.endif
-.byte 13
+.byte "F1: TFTP BOOT F2: DISK BOOT",13
+.byte "F3: NET APPS F4: TBA",13
.byte "F5: ARP TABLE F7: CONFIG",13,13
-.byte 0
+.else
+.byte "F1: TFTP BOOT F3: BASIC",13
+.byte "F5: ARP TABLE F7: CONFIG",13,13
+.endif
+.byte 0
config_menu_msg:
.byte 13,"CONFIGURATION",13,13
@@ -751,20 +849,26 @@ ping_header: .byte "ping",13,0
gopher_header: .byte "gopher",13,0
telnet_header: .byte "telnet",13,0
+file_read_error: .asciiz "ERROR READING FILE"
+autoexec_filename: .byte "AUTOEXEC.PRG",0
+
.endif
-downloading_msg: .asciiz "DOWNLOADING "
+downloading_msg: .byte "DOWN"
+loading_msg: .asciiz "LOADING "
getting_dir_listing_msg: .byte "FETCHING DIRECTORY",13,0
-tftp_dir_listing_fail_msg:
- .byte "DIR LISTING FAILED",13,0
+dir_listing_fail_msg:
+ .byte "DIR FAILED",13,0
tftp_download_fail_msg:
.byte "DOWNLOAD FAILED", 13, 0
tftp_download_ok_msg:
- .byte "DOWNLOAD OK", 13, 0
-
+ .byte "DOWN"
+load_ok_msg:
+ .byte "LOAD OK", 13, 0
+
current:
.byte "CURRENT ",0
@@ -777,9 +881,8 @@ tftp_dir_filemask:
tftp_file:
.asciiz "BOOTC64.PRG"
-no_files_on_server:
- .byte "NO MATCHING FILES",13,0
-
+no_files:
+ .byte "NO FILES",13,0
resolving:
.byte "RESOLVING ",0
diff --git a/client/tcp_test.bat b/client/tcp_test.bat
index 914ba1c..02ac029 100644
--- a/client/tcp_test.bat
+++ b/client/tcp_test.bat
@@ -1 +1 @@
-start c:\temp\WinVICE-2.1\x64.exe -cart16 nb65\nb65_tcp_cart.bin test\test_cart_api.prg
\ No newline at end of file
+start c:\temp\WinVICE-2.1\x64.exe -cart16 nb65\nb65_tcp_cart.bin
\ No newline at end of file
diff --git a/client/test/Makefile b/client/test/Makefile
index 6702896..1a5e14d 100644
--- a/client/test/Makefile
+++ b/client/test/Makefile
@@ -67,8 +67,10 @@ ip65test.dsk: testdns.pg2 testdottedquad.pg2 testtftp.pg2
ripxplore.rb ip65test.dsk -a testdns.pg2 -t AppleBinary
test_disk_io.d64: test_disk_io.prg
- ripxplore.rb --init CbmDos test_disk_io.d64 -a test_disk_io.prg
-
+ ripxplore.rb --init CbmDos test_disk_io.d64 -a test_disk_io.prg
+ cp screen_prg.bin screen.prg
+ ripxplore.rb test_disk_io.d64 -a screen.prg
+
clean:
rm -f *.o *.pg2 *.prg
rm -f ip65test.dsk
diff --git a/client/test/test_disk_io.s b/client/test/test_disk_io.s
index b5d84de..eb699ef 100644
--- a/client/test/test_disk_io.s
+++ b/client/test/test_disk_io.s
@@ -13,7 +13,10 @@
.import io_track_no
.import io_read_sector
.import io_read_file_with_callback
+.import io_read_file
.import io_filename
+.import io_filesize
+.import io_load_address
.import io_callback
.import get_key
.import ip65_error
@@ -54,15 +57,15 @@ basicstub:
init:
+ ;switch to lower case charset
+ lda #23
+ sta $d018
+ ;test we can read the catalogue
ldax #read_catalogue
jsr print
-; ldax #dummy_catalogue
-; jsr print_catalogue
-; rts
-
lda #01
sta io_device_no
@@ -75,8 +78,73 @@ init:
@no_error_on_catalogue:
ldax #directory_buffer
jsr print_catalogue
+
+ ;test we can read without callbacks to fixed buffer
+ ldax #loading
+ jsr print
+ ldax #fname
+ stax io_filename
+ jsr print
+
+
+ jsr print_cr
+ lda #01
+ sta io_device_no
+
+ ldax #readfile_callback
+ stax io_callback
+ ldax #$3000
+ jsr io_read_file
+ bcc :+
+ jsr print_error_code
rts
+:
+
+ ldax io_filesize
+ jsr print_integer
+ ldax #bytes_to
+ jsr print
+ lda io_load_address+1
+ jsr print_hex
+ lda io_load_address
+ jsr print_hex
+ jsr print_cr
+
+
+;test we can read without callbacks to address in file
+ ldax #loading
+ jsr print
+ ldax #fname2
+ stax io_filename
+ jsr print
+
+
+ jsr print_cr
+ lda #01
+ sta io_device_no
+
+ ldax #readfile_callback
+ stax io_callback
+ ldax #$0000
+ jsr io_read_file
+ bcc :+
+ jsr print_error_code
+ rts
+:
+
+ ldax io_filesize
+ jsr print_integer
+ ldax #bytes_to
+ jsr print
+ lda io_load_address+1
+ jsr print_hex
+ lda io_load_address
+ jsr print_hex
+ jsr print_cr
+
+ jsr wait_for_keypress
+ ;test we can read via callbacks
ldax #loading
jsr print
@@ -93,53 +161,15 @@ init:
ldax #sector_buffer
jsr io_read_file_with_callback
- bcc @no_error_on_file_read
+ bcc :+
jsr print_error_code
-@no_error_on_file_read:
+:
+
+
rts
-
- lda #01
- sta io_track_no
- lda #01
- sta io_sector_no
- lda #01
- sta io_device_no
- ldax #sector_buffer
- jsr io_read_sector
- bcs @error
-
- ; jsr dump_sector ;DEBUG
-
- lda #$12
- sta io_track_no
- lda #01
- sta io_sector_no
- lda #01
- sta io_device_no
- ldax #sector_buffer
- jsr io_read_sector
-
- bcs @error
-; jsr dump_sector ;DEBUG
-
-
-
- lda #$12
- sta io_track_no
- lda #01
- sta io_sector_no
- lda #01
- sta io_device_no
- ldax #sector_buffer
- jsr io_read_sector
-
- bcs @error
- jsr dump_sector ;DEBUG
-
- rts
-
+
@error:
jsr print_cr
lda ip65_error
@@ -160,7 +190,7 @@ print_catalogue:
beq @end_of_filename
jmp @print_one_char
@end_of_filename:
- jsr print_cr
+ jsr print_cr
ldax #filetype
jsr print
jsr read_byte_from_buffer
@@ -286,6 +316,9 @@ read_catalogue:
fname:
.byte "TEST_DISK_IO.PRG",0
+fname2:
+ .byte "SCREEN.PRG",0
+
loading: .byte "LOADING ",0
.rodata
@@ -304,9 +337,8 @@ ok:
.byte "OK ", 0
bytes:
- .byte "BYTES.",13, 0
+ .byte " BYTES.", 0
+
+bytes_to:
+ .byte " BYTES TO $", 0
-dummy_catalogue:
-.byte"FILE 1",0,$81,$34,$12
-.byte "FILE 2",0,$82,$f0,$0d
-.byte 0
diff --git a/client/test/test_parser.s b/client/test/test_parser.s
index d7bbf34..e697f43 100644
--- a/client/test/test_parser.s
+++ b/client/test/test_parser.s
@@ -49,6 +49,9 @@ init:
ldax #url_1
jsr test_url_parse
+ jsr wait_key
+
+
ldax #url_2
jsr test_url_parse
ldax #url_3
@@ -137,10 +140,8 @@ print_parsed_url:
jsr print_dotted_quad
ldax #port
jsr print
- lda url_port+1
- jsr print_hex
- lda url_port
- jsr print_hex
+ ldax url_port
+ jsr print_integer
ldax #type
jsr print
lda url_resource_type
@@ -165,7 +166,7 @@ title:
.byte "",0
url_1:
-.byte "http://www.jamtronix.com/",0
+.byte "http://www.jamtronix.com/",13,"not part of URL!",0
url_2:
.byte "http://www.jamtronix.com/goober",0
@@ -203,7 +204,7 @@ url_c:
parsing: .asciiz "PARSING "
ip: .asciiz "IP: "
-port: .asciiz " PORT: $"
+port: .asciiz " PORT: "
type: .asciiz " TYPE:"
selector: .asciiz "SELECTOR: "
press_a_key: .byte "PRESS ANY KEY TO CONTINUE",13,0
diff --git a/dist/make_dist.rb b/dist/make_dist.rb
index 4dbeaa9..57f6484 100644
--- a/dist/make_dist.rb
+++ b/dist/make_dist.rb
@@ -41,7 +41,7 @@ end
["client/inc/common.i","inc"],
["client/inc/nb65_constants.i","inc"],
["client/examples/dasm_example.asm","examples/"],
-
+["client/examples/upnatom.d64","c64/"],
#["client/nb65/d64_upload.s","examples/"],
#["client/nb65/nb65_skeleton.s","examples/"],
].each do |args|
diff --git a/dist/version_number.txt b/dist/version_number.txt
index f5b38be..f1bf126 100644
--- a/dist/version_number.txt
+++ b/dist/version_number.txt
@@ -1 +1 @@
-0.9.25
\ No newline at end of file
+0.9.30
\ No newline at end of file
diff --git a/doc/README.C64.html b/doc/README.C64.html
index bf5c18a..a77fbce 100644
--- a/doc/README.C64.html
+++ b/doc/README.C64.html
@@ -28,7 +28,8 @@ 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.
-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".
+Once the IP stack is initialised, an attempt to boot from disk will take place (on the 16KB image only - see autoexec section for more). If this fails, or the 8KB cartridge is being used,
+the "main menu" screen will be displayed. There are slight variations between the menus shown on the 2 "flavours".
Main Menu - UDP only carts
- 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
@@ -41,7 +42,11 @@ Once the IP stack is initialised, the "main menu" screen will be displayed. Ther
- 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
+
+ - F2 : DISK BOOT. This will display a catalogue of files in drive #8 and allow the selection of a file to be executed. This version of DISK 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).
+
+
- F3 : NET APPS. This will bring up another menu of network-orientated applications (see below for more details).
- F5 : ARP TABLE. This will show a table of the current mapping of IP and MAC addresses
- F7 : CONFIG. This brings up a menu where the IP configuration can be modified. Changes made here will be persistent until the next reboot.
@@ -78,6 +83,10 @@ starting with a highlighted letter (e.g. the first link on a page will have an i
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.
+AUTOEXEC
+Once the 16KB cartridge image has initialised the IP stack, it will look for a file called "autoexec.prg" on the default drive. If this file is found it will be loaded (using the load address specified by the first 2
+bytes of the file) and executed. NB - since BASIC is not available only 100% Machine Language programs can be executed, although if there is a BASIC stub consisting of a single line that does a SYS
+call, the target of the SYS call will be used as the address to start execution from.
IP CONFIGURATION
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
diff --git a/doc/nb65_api_technical_reference.doc b/doc/nb65_api_technical_reference.doc
index 8738964..1a2fd29 100644
Binary files a/doc/nb65_api_technical_reference.doc and b/doc/nb65_api_technical_reference.doc differ