git-svn-id: http://svn.code.sf.net/p/netboot65/code@103 93682198-c243-4bdb-bd91-e943c89aac3b

This commit is contained in:
jonnosan 2009-04-15 12:39:43 +00:00
parent 52053dcca6
commit 71d8767ef9
7 changed files with 1099 additions and 0 deletions

68
client/nb65/Makefile Normal file
View File

@ -0,0 +1,68 @@
AS=ca65
LD=ld65
CFLAGS=-Oirs -t $(TARGET)
AFLAGS=
INCFILES=\
../inc/common.i\
../inc/commonprint.i\
../inc/net.i\
../inc/menu.i\
../inc/nb65_constants.i\
IP65LIB=../ip65/ip65.lib
C64PROGLIB=../drivers/c64prog.lib
C64NB65LIB=../drivers/c64nb65.lib
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 c64boot.d64
nb65_c64_ram.o: nb65_c64.s $(INCFILES)
$(AS) -DBANKSWITCH_SUPPORT=0 $(AFLAGS) -o $@ $<
nb65_std_cart.o: nb65_c64.s $(INCFILES)
$(AS) -DBANKSWITCH_SUPPORT=1 $(AFLAGS) -o $@ $<
nb65_rrnet.o: nb65_c64.s $(INCFILES)
$(AS) -DBANKSWITCH_SUPPORT=2 $(AFLAGS) -o $@ $<
%.o: %.s $(INCFILES)
$(AS) $(AFLAGS) $<
nb65_c64_ram_header.bin: nb65_c64_ram_header.o ../cfg/c64prg.cfg
$(LD) -C ../cfg/c64prg.cfg -o $@ nb65_c64_ram_header.o
nb65_c64_ram.prg: nb65_c64_ram_header.bin nb65_c64_ram.o $(IP65LIB) $(C64NB65LIB) $(INCFILES) ../cfg/rrbin.cfg
$(LD) -m nb65_c64_ram.map -vm -C ../cfg/rrbin.cfg -o nb65_c64_ram.bin nb65_c64_ram.o $(IP65LIB) $(C64NB65LIB)
cat nb65_c64_ram_header.bin nb65_c64_ram.bin> nb65_c64_ram.prg
nb65_std_cart.bin: nb65_std_cart.o $(IP65LIB) $(C64NB65LIB) $(INCFILES) ../cfg/rrbin.cfg
$(LD) -m nb65_std_cart.map -vm -C ../cfg/rrbin.cfg -o $@ $< $(IP65LIB) $(C64NB65LIB)
ruby fix_cart.rb $@ 8192
nb65_rrnet.bin: nb65_rrnet.o $(IP65LIB) $(C64NB65LIB) $(INCFILES) ../cfg/rrbin.cfg
$(LD) -m nb65_rrnet.map -vm -C ../cfg/rrbin.cfg -o $@ $< $(IP65LIB) $(C64NB65LIB)
ruby fix_cart.rb $@ 8193
utherboot.pg2: utherboot.o $(IP65LIB) $(APPLE2PROGLIB) $(INCFILES) ../cfg/a2language_card.cfg
$(LD) -m utherboot.map -C ../cfg/a2language_card.cfg -o $@ $< $(IP65LIB) $(APPLE2PROGLIB)
utherboot.dsk: utherboot.pg2
ripxplore.rb --init AppleDos utherboot.dsk -a utherboot.pg2 -t AppleBinary
ripxplore.rb utherboot.dsk -a hello -t Applesoft
c64boot.d64: nb65_c64_ram.prg
ripxplore.rb --init CbmDos $@ -a nb65_c64_ram.prg
$(BOOTA2.PG2): bootmenu.o $(IP65LIB) $(APPLE2PROGLIB) $(INCFILES) ../cfg/a2language_card.cfg
$(LD) -m bootmenu.map -C ../cfg/a2language_card.cfg -o $(BOOTA2.PG2) $< $(IP65LIB) $(APPLE2PROGLIB)
clean:
rm -f *.o *.bin *.map *.prg *.pg2 *.dsk *.d64
rm -f $(BOOTA2.PG2)
distclean: clean
rm -f *~

145
client/nb65/bootmenu.s Normal file
View File

@ -0,0 +1,145 @@
;#############
;
; This program looks for a TNDP server on the network, presents a catalog of volumes on that server, and allows a volume to be attached
;
; jonno@jamtronix.com - January 2009
;
.include "../inc/common.i"
.include "../inc/commonprint.i"
.include "../inc/net.i"
.import cls
.import exit_to_basic
.import copymem
.importzp copy_src
.importzp copy_dest
.import __STARTUP_LOAD__
.import __STARTUP_SIZE__
.import __BSS_LOAD__
.import __DATA_LOAD__
.import __DATA_RUN__
.import __DATA_SIZE__
.import __RODATA_LOAD__
.import __RODATA_RUN__
.import __RODATA_SIZE__
.import __CODE_LOAD__
.import __CODE_RUN__
.import __CODE_SIZE__
.segment "PAGE3"
disable_language_card: .res 3
bin_file_jmp: .res 3
; ------------------------------------------------------------------------
.segment "EXEHDR"
.addr __STARTUP_LOAD__ ; Start address
.word __STARTUP_SIZE__+__CODE_SIZE__+__RODATA_SIZE__+__DATA_SIZE__+4 ; Size
; ------------------------------------------------------------------------
.segment "STARTUP"
lda $c089 ;enable language : card read ROM, write RAM, BANK 1
;copy the monitor rom on to the language card
ldax #$f800
stax copy_src
stax copy_dest
ldax #$0800
jsr startup_copymem
lda $c08b ;enable language : card read RAM, write RAM, BANK 1
lda $c08b ;this soft switch needs to be read twice
;relocate the CODE segment
ldax #__CODE_LOAD__
stax copy_src
ldax #__CODE_RUN__
stax copy_dest
ldax #__CODE_SIZE__
jsr startup_copymem
;relocate the RODATA segment
ldax #__RODATA_LOAD__
stax copy_src
ldax #__RODATA_RUN__
stax copy_dest
ldax #__RODATA_SIZE__
jsr startup_copymem
;relocate the DATA segment
ldax #__DATA_LOAD__
stax copy_src
ldax #__DATA_RUN__
stax copy_dest
ldax #__DATA_SIZE__
jsr startup_copymem
jmp init
; copy memory
; set copy_src and copy_dest, length in A/X
end: .res 1
startup_copymem:
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:
rts
.code
init:
jsr cls
ldax #startup_msg
jsr print
jsr print_cr
jmp exit_to_basic
.rodata
startup_msg: .byte "NETBOOT65 FOR APPLE 2 V0.1",13
.byte "SEE README.TXT FOR MORE INFO (INCLUDING",13
.byte "HOW TO RUN SOMETHING MORE INTERESTING)",13
.byte 0

26
client/nb65/fix_cart.rb Normal file
View File

@ -0,0 +1,26 @@
#
# Vice will treat a cartridge bin file that is of an even length as if the first 2 bytes in the file are a load address to be skipped over
# so we want to make sure the bin file is an odd length - specifically 8193 bytes
#
PAD_BYTE=0xff.chr
filename=ARGV[0]
if filename.nil? then
puts "no filename specified"
exit
end
if ARGV[1].nil? then
puts "no padding length specified"
exit
end
file_length=ARGV[1].to_i
infile=File.open(filename,"rb").read
puts "fixing length of #{filename} from #{infile.length} to #{file_length} bytes"
outfile=File.open(filename,"wb")
outfile<<infile
outfile<<PAD_BYTE*(file_length-infile.length)
outfile.close

BIN
client/nb65/hello Normal file

Binary file not shown.

490
client/nb65/nb65_c64.s Normal file
View File

@ -0,0 +1,490 @@
; #############
;
; This will boot a C64 with an RR-NET compatible cs8900a from the network
; requires
; 1) a DHCP server, and
; 2) a TFTP server that responds to requests on the broadcast address (255.255.255.255) and that will serve a file called 'BOOTC64.PRG'.
; the prg file can be either BASIC or M/L, and up to 22K in length.
;
; jonno@jamtronix.com - January 2009
;
;possible bankswitch values are:
;$00 = no bankswitching (i.e. NB65 API in RAM only)
;$01 = standard bankswitching (via HIRAM/LORAM)
;$02 = advanced bankswitching (via custom registers, e.g. $de00 on the Retro Replay cart)
.ifndef BANKSWITCH_SUPPORT
.error "must define BANKSWITCH_SUPPORT"
.endif
.macro print_failed
ldax #failed_msg
jsr print
jsr print_cr
.endmacro
.macro print_ok
ldax #ok_msg
jsr print
jsr print_cr
.endmacro
.macro nb65call arg
ldy arg
jsr NB65_DISPATCH_VECTOR
.endmacro
.ifndef NB65_API_VERSION_NUMBER
.define EQU =
.include "../inc/nb65_constants.i"
.endif
.include "../inc/common.i"
.include "../inc/menu.i"
.include "../inc/c64keycodes.i"
.import cls
.import beep
.import exit_to_basic
.import timer_vbl_handler
.import nb65_dispatcher
.import ip65_process
.import get_filtered_input
.import filter_text
.import filter_dns
.import print_arp_cache
.import print_dotted_quad
.import print_hex
.import print_ip_config
.import ok_msg
.import failed_msg
.import init_msg
.import print_a
.import print_cr
.import print
.import copymem
.importzp copy_src
.importzp copy_dest
.import get_filtered_input
.import __DATA_LOAD__
.import __DATA_RUN__
.import __DATA_SIZE__
.import cfg_tftp_server
tftp_dir_buffer = $6000
.data
exit_cart:
.if (BANKSWITCH_SUPPORT=$02)
lda #$02
sta $de00 ;turns off RR cartridge by modifying GROUND and EXROM
.elseif (BANKSWITCH_SUPPORT=$01)
lda #$36
sta $0001 ;turns off ordinary cartridge by modifying HIRAM/LORAM (this will also bank out BASIC)
.endif
call_downloaded_prg:
jsr $0000 ;overwritten when we load a file
jmp init
.bss
nb65_param_buffer: .res $20
.segment "CARTRIDGE_HEADER"
.word init ;cold start vector
.word $FE47 ;warm start vector
.byte $C3,$C2,$CD,$38,$30 ; "CBM80"
.byte $4E,$42,$36,$35 ; "NB65" - API signature
.byte $01 ;NB65_API_VERSION
.byte BANKSWITCH_SUPPORT ;
jmp nb65_dispatcher ; NB65_DISPATCH_VECTOR : entry point for NB65 functions
jmp ip65_process ;NB65_PERIODIC_PROCESSING_VECTOR : routine to be periodically called to check for arrival of ethernet packects
jmp timer_vbl_handler ;NB65_VBL_VECTOR : routine to be called during each vertical blank interrupt
.code
init:
;first let the kernal do a normal startup
sei
jsr $fda3 ;initialize CIA I/O
jsr $fd50 ;RAM test, set pointers
jsr $fd15 ;set vectors for KERNAL
jsr $ff5B ;init. VIC
cli ;KERNAL init. finished
jsr $e453 ;set BASIC vectors
jsr $e3bf ;initialize zero page
;set some funky colours
LDA #$05 ;green
STA $D020 ;background
LDA #$00 ;black
STA $D021 ;background
lda #$1E
jsr print_a
;relocate our r/w data
ldax #__DATA_LOAD__
stax copy_src
ldax #__DATA_RUN__
stax copy_dest
ldax #__DATA_SIZE__
jsr copymem
;copy the RAM stub to RAM
ldax #nb65_ram_stub
stax copy_src
ldax #NB65_RAM_STUB_SIGNATURE
stax copy_dest
ldax #nb65_ram_stub_length
jsr copymem
;if this is a 'normal' cart then we will end up swapping BASIC out, so copy it to the RAM under ROM
.if (BANKSWITCH_SUPPORT=$01)
ldax #$A000
stax copy_src
stax copy_dest
ldax #$2000
jsr copymem
.endif
ldax #init_msg
jsr print
nb65call #NB65_INITIALIZE
main_menu:
jsr cls
ldax #netboot65_msg
jsr print
ldax #main_menu_msg
jsr print
jsr print_ip_config
jsr print_cr
@get_key:
jsr get_key
cmp #KEYCODE_F1
bne @not_tftp
jmp @tftp_boot
@not_tftp:
cmp #KEYCODE_F3
beq @exit_to_basic
cmp #KEYCODE_F5
beq @util_menu
cmp #KEYCODE_F7
beq @change_config
jmp @get_key
@exit_to_basic:
ldax #$fe66 ;do a wam start
jmp exit_cart_via_ax
@util_menu_header:
jsr cls
ldax #netboot65_msg
jsr print
ldax #util_menu_msg
jsr print
rts
@util_menu:
jsr @util_menu_header
@get_key_util_menu:
jsr get_key
cmp #KEYCODE_F1
bne @not_arp_cache
jsr @util_menu_header
jsr print_arp_cache
jmp @get_key_util_menu
@not_arp_cache:
cmp #KEYCODE_F7
beq main_menu
jmp @get_key_util_menu
@change_config:
jsr cls
ldax #netboot65_msg
jsr print
ldax #config_menu_msg
jsr print
ldax #current
jsr print
ldax #tftp_server
jsr print
ldax #cfg_tftp_server
jsr print_dotted_quad
jsr print_cr
ldax #enter_new_tftp_server
jsr print
jsr print_cr
ldax #filter_dns
jsr get_filtered_input
bcs @no_server_entered
stax nb65_param_buffer
jsr print_cr
ldax #resolving
jsr print
ldax #nb65_param_buffer
nb65call #NB65_DNS_RESOLVE
bcs @resolve_error
ldax #nb65_param_buffer
stax copy_src
ldax #cfg_tftp_server
stax copy_dest
ldax #4
jsr copymem
@no_server_entered:
jmp main_menu
@resolve_error:
print_failed
jsr wait_for_keypress
jmp main_menu
@tftp_boot:
jsr setup_param_buffer_for_tftp_call
ldax #tftp_dir_buffer
stax nb65_param_buffer+NB65_TFTP_POINTER
ldax #getting_dir_listing_msg
jsr print
ldax #tftp_dir_filemask
stax nb65_param_buffer+NB65_TFTP_FILENAME
jsr print
jsr print_cr
ldax #nb65_param_buffer
nb65call #NB65_TFTP_DIRECTORY_LISTING
bcs @dir_failed
lda tftp_dir_buffer ;get the first byte that was downloaded
bne :+
jmp @no_files_on_server
:
;switch to lower case charset
lda #23
sta $d018
ldax #tftp_dir_buffer
jsr select_option_from_menu
bcc @tftp_filename_set
lda #21 ;switch back to upper case
sta $d018
jmp main_menu
@tftp_filename_set:
jsr download
bcc @file_downloaded_ok
jmp bad_boot
@dir_failed:
ldax #tftp_dir_listing_fail_msg
jsr print
jsr print_errorcode
jsr print_cr
ldax #tftp_file
jmp @tftp_filename_set
@no_files_on_server:
ldax #no_files_on_server
jsr print
jmp bad_boot
@file_downloaded_ok:
;get ready to bank out
nb65call #NB65_DEACTIVATE
;check whether the file we just downloaded was a BASIC prg
lda nb65_param_buffer+NB65_TFTP_POINTER
cmp #01
bne @not_a_basic_file
lda nb65_param_buffer+NB65_TFTP_POINTER+1
cmp #$08
bne @not_a_basic_file
jsr $e453 ;set BASIC vectors
jsr $e3bf ;initialize BASIC
jsr $a86e
jsr $a533 ; re-bind BASIC lines
ldx $22 ;load end-of-BASIC pointer (lo byte)
ldy $23 ;load end-of-BASIC pointer (hi byte)
stx $2d ;save end-of-BASIC pointer (lo byte)
sty $2e ;save end-of-BASIC pointer (hi byte)
jsr $a659 ; CLR (reset variables)
ldax #$a7ae ; jump to BASIC interpreter loop
jmp exit_cart_via_ax
@not_a_basic_file:
ldax nb65_param_buffer+NB65_TFTP_POINTER
exit_cart_via_ax:
sta call_downloaded_prg+1
stx call_downloaded_prg+2
jmp exit_cart
print_errorcode:
ldax #error_code
jsr print
nb65call #NB65_GET_LAST_ERROR
jsr print_hex
jmp print_cr
setup_param_buffer_for_tftp_call:
ldx #3
lda cfg_tftp_server,x
:
sta nb65_param_buffer+NB65_TFTP_IP,x
dex
bpl :-
rts
bad_boot:
jsr wait_for_keypress
jmp $fe66 ;do a wam start
download: ;AX should point at filename to download
stax nb65_param_buffer+NB65_TFTP_FILENAME
ldax #$0000 ;load address will be first 2 bytes of file we download (LO/HI order)
stax nb65_param_buffer+NB65_TFTP_POINTER
ldax #downloading_msg
jsr print
ldax nb65_param_buffer+NB65_TFTP_FILENAME
jsr print
jsr print_cr
jsr setup_param_buffer_for_tftp_call
ldax #nb65_param_buffer
nb65call #NB65_TFTP_DOWNLOAD
bcc :+
ldax #tftp_download_fail_msg
jsr print
jsr print_errorcode
sec
rts
:
ldax #tftp_download_ok_msg
jsr print
clc
rts
wait_for_keypress:
ldax #press_a_key_to_continue
jsr print
@loop:
jsr $ffe4
beq @loop
rts
get_key:
@loop:
jsr NB65_PERIODIC_PROCESSING_VECTOR
jsr $ffe4
beq @loop
rts
cfg_get_configuration_ptr:
ldax #nb65_param_buffer
nb65call #NB65_GET_IP_CONFIG
rts
.rodata
netboot65_msg:
.byte "NETBOOT65 - C64 NETWORK BOOT CLIENT V0.4",13
.byte 0
main_menu_msg:
.byte "F1: TFTP BOOT F3: BASIC",13
.byte "F5: UTILITIES F7: CONFIG",13,13
.byte 0
util_menu_msg:
.byte "F1: ARP TABLE",13
.byte " F7: MAIN MENU",13,13
.byte 0
config_menu_msg:
.byte "NETBOOT65 CONFIGURATION",13,0
downloading_msg: .asciiz "DOWNLOADING "
getting_dir_listing_msg: .asciiz "FETCHING TFTP DIRECTORY FOR "
tftp_dir_listing_fail_msg:
.byte "DIR LISTING FAILED",13,0
tftp_download_fail_msg:
.byte "DOWNLOAD FAILED", 13, 0
tftp_download_ok_msg:
.byte "DOWNLOAD OK", 13, 0
error_code:
.asciiz "ERROR CODE: "
current:
.byte "CURRENT ",0
enter_new_tftp_server:
.byte"ENTER "
new_tftp_server:
.byte "NEW "
tftp_server:
.byte "TFTP SERVER: ",0
tftp_dir_filemask:
.asciiz "*.PRG"
tftp_file:
.asciiz "BOOTC64.PRG"
no_files_on_server:
.byte "TFTP SERVER HAS NO MATCHING FILES",13,0
press_a_key_to_continue:
.byte "PRESS A KEY TO CONTINUE",13,0
resolving:
.byte "RESOLVING ",0
nb65_ram_stub: ; this gets copied to $C000 so programs can bank in the cartridge
.byte $4E,$42,$36,$35 ; "NB65" - API signature
.if (BANKSWITCH_SUPPORT=$02)
lda #$01
sta $de00 ;turns on RR cartridge (since it will have been banked out when exiting to BASIC)
.elseif (BANKSWITCH_SUPPORT=$01)
lda #$37
sta $0001 ;turns on ordinary cartridge by modifying HIRAM/LORAM (this will also bank in BASIC)
.endif
rts
nb65_ram_stub_end:
nb65_ram_stub_length=nb65_ram_stub_end-nb65_ram_stub

View File

@ -0,0 +1,73 @@
.segment "IP65ZP" : zeropage
; pointers for copying
copy_src: .res 2 ; source pointer
copy_dest: .res 2 ; destination pointer
end: .res 1
.segment "STARTUP" ;this is what gets put at the start of the file on the C64
.word basicstub ; load address
.include "../inc/common.i"
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
init:
ldax #cart_data
stax copy_src
ldax #$8000
stax copy_dest
ldax #$2000
jsr copymem
jmp ($8000) ;cold start vector
;copy memory
;inputs:
; copy_src is address of buffer to copy from
; copy_dest is address of buffer to copy to
; AX = number of bytes to copy
;outputs: none
copymem:
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:
rts
;this is where the cart data will be appended to:
cart_data:

297
client/nb65/utherboot.s Normal file
View File

@ -0,0 +1,297 @@
;#############
;
; This will boot an Apple 2 with uthernet in slot 3 from the network
; requires
; 1) a DHCP server, and
; 2) a TFTP server that responds to requests on the broadcast address (255.255.255.255) and that will serve a file called 'BOOTA2.BIN'.
;
; jonno@jamtronix.com - January 2009
;
.include "../inc/common.i"
.include "../inc/commonprint.i"
.include "../inc/net.i"
.include "../inc/menu.i"
.include "../inc/a2keycodes.i"
.import cls
.import get_key
.import beep
.importzp tftp_filename
.import tftp_load_address
.import tftp_ip
.import tftp_download
.import tftp_directory_listing
.import copymem
.importzp copy_src
.importzp copy_dest
.import __STARTUP_LOAD__
.import __STARTUP_SIZE__
.import __BSS_LOAD__
.import __DATA_LOAD__
.import __DATA_RUN__
.import __DATA_SIZE__
.import __RODATA_LOAD__
.import __RODATA_RUN__
.import __RODATA_SIZE__
.import __CODE_LOAD__
.import __CODE_RUN__
.import __CODE_SIZE__
;.segment "PAGE3"
;disable_language_card: .res 3
;bin_file_jmp: .res 3
disable_language_card = $101
bin_file_jmp = $104
; ------------------------------------------------------------------------
.segment "EXEHDR"
.addr __STARTUP_LOAD__ ; Start address
.word __STARTUP_SIZE__+__CODE_SIZE__+__RODATA_SIZE__+__DATA_SIZE__+4 ; Size
; ------------------------------------------------------------------------
tftp_dir_buffer = $4000
.segment "STARTUP"
lda $c089 ;enable language : card read ROM, write RAM, BANK 1
;copy the monitor rom on to the language card
ldax #$f800
stax copy_src
stax copy_dest
ldax #$0800
jsr startup_copymem
lda $c08b ;enable language : card read RAM, write RAM, BANK 1
lda $c08b ;this soft switch needs to be read twice
;relocate the CODE segment
ldax #__CODE_LOAD__
stax copy_src
ldax #__CODE_RUN__
stax copy_dest
ldax #__CODE_SIZE__
jsr startup_copymem
;relocate the RODATA segment
ldax #__RODATA_LOAD__
stax copy_src
ldax #__RODATA_RUN__
stax copy_dest
ldax #__RODATA_SIZE__
jsr startup_copymem
;relocate the DATA segment
ldax #__DATA_LOAD__
stax copy_src
ldax #__DATA_RUN__
stax copy_dest
ldax #__DATA_SIZE__
jsr startup_copymem
jmp init
; copy memory
; set copy_src and copy_dest, length in A/X
end: .res 1
startup_copymem:
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:
rts
.code
init:
jsr cls
ldax #startup_msg
jsr print
jsr print_cr
init_ip_via_dhcp
bcc :+
jmp bad_boot
:
jsr print_ip_config
ldx #3
:
lda cfg_tftp_server,x
sta tftp_ip,x
dex
bpl :-
ldax #tftp_dir_buffer
stax tftp_load_address
ldax #getting_dir_listing_msg
jsr print
ldax #tftp_dir_filemask
stax tftp_filename
jsr print
jsr print_cr
jsr tftp_directory_listing
bcs @dir_failed
ldax #$0000 ;load address will be first 2 bytes of file we download (LO/HI order)
stax tftp_load_address
ldax #tftp_dir_buffer
jsr select_option_from_menu
bcc @option_selected
jmp bad_boot
@option_selected:
stax tftp_filename
ldax #downloading_msg
jsr print
ldax tftp_filename
jsr download
bcc @file_downloaded_ok
jmp bad_boot
@dir_failed:
ldax #tftp_dir_listing_fail_msg
jsr print
jsr print_cr
ldax #$0000 ;load address will be first 2 bytes of file we download (LO/HI order)
stax tftp_load_address
ldax #downloading_msg
jsr print
ldax #tftp_file
jsr download
bcc @file_downloaded_ok
jmp bad_boot
@file_downloaded_ok:
;set up to jump to where we just d/led the file to
lda #$4C ;opcode for JMP
sta bin_file_jmp
ldax tftp_load_address
stax bin_file_jmp+1
;but before we go, we need to shift the file down by 2 bytes (to skip over the file length)
ldax tftp_load_address
stax copy_dest
clc
adc #02
bcc :+
inx
:
stax copy_src
ldy #1
lda (copy_dest),y ;currently this is the high byte of the length
tax
dey
lda (copy_dest),y ;currently this is the low byte of the length
jsr copymem
;now make the 'turn off language card' routine
lda #$AD ;$AD=LDA
sta disable_language_card
lda #$82 ;low byte of soft switch
sta disable_language_card+1
lda #$c0 ;high byte of soft switch
sta disable_language_card+2
jmp disable_language_card
bad_boot:
jmp $3d0
download:
stax tftp_filename
jsr print
jsr print_cr
jsr tftp_download
bcc :+
ldax #tftp_download_fail_msg
jsr print
sec
rts
:
ldax #tftp_download_ok_msg
jsr print
clc
rts
.rodata
downloading_msg: .asciiz "DOWNLOADING "
getting_dir_listing_msg: .asciiz "FETCHING TFTP DIRECTORY FOR "
tftp_dir_listing_fail_msg:
.asciiz "DIR LISTING FAILED"
tftp_file:
.asciiz "BOOTA2.PG2"
tftp_dir_filemask:
.asciiz "*.PG2"
tftp_download_fail_msg:
.asciiz "DOWNLOAD FAILED"
tftp_download_ok_msg:
.asciiz "DOWNLOAD OK"
startup_msg: .byte "UTHERNET NETWORK BOOT CLIENT V0.1",0