mirror of
https://github.com/bobbimanners/emailler.git
synced 2024-09-08 21:54:28 +00:00
git-svn-id: http://svn.code.sf.net/p/netboot65/code@195 93682198-c243-4bdb-bd91-e943c89aac3b
This commit is contained in:
parent
57764c5791
commit
bf2545ddee
59
client/carts/Makefile
Normal file
59
client/carts/Makefile
Normal file
@ -0,0 +1,59 @@
|
||||
AS=ca65
|
||||
LD=ld65
|
||||
CFLAGS=-Oirs -t $(TARGET)
|
||||
AFLAGS=
|
||||
|
||||
INCFILES=\
|
||||
../inc/common.i\
|
||||
../inc/commonprint.i\
|
||||
../inc/net.i\
|
||||
../inc/menu.i\
|
||||
../inc/kipper_constants.i\
|
||||
../inc/version.i\
|
||||
|
||||
TCP_INCFILES=../inc/gopher.i ../inc/telnet.i ../inc/ping.i
|
||||
IP65LIB=../ip65/ip65.lib
|
||||
|
||||
IP65TCPLIB=../ip65/ip65_tcp.lib
|
||||
|
||||
C64PROGLIB=../drivers/c64prog.lib
|
||||
C64NB65LIB=../drivers/c64nb65.lib
|
||||
|
||||
all: kipperkart.bin kipperkart_rr.bin netboot.bin
|
||||
|
||||
kipperkart.o: kipperkart.s $(INCFILES) $(TCP_INCFILES)
|
||||
$(AS) $(AFLAGS) -o $@ $<
|
||||
|
||||
%.o: %.s $(INCFILES)
|
||||
$(AS) $(AFLAGS) $<
|
||||
|
||||
%.prg: %.o $(IP65LIB) $(C64PROGLIB) $(INCFILES) ../cfg/c64prg.cfg
|
||||
$(LD) -m $*.map -vm -C ../cfg/c64prg.cfg -o $*.prg $(AFLAGS) $< $(IP65LIB) $(C64PROGLIB)
|
||||
|
||||
netboot.bin: netboot.o $(IP65LIB) $(C64PROGLIB) $(INCFILES) ../cfg/c64_8kcart.cfg
|
||||
$(LD) -m netboot.map -vm -C ../cfg/c64_8kcart.cfg -o $@ $< $(IP65LIB) $(C64PROGLIB)
|
||||
ruby fix_cart.rb $@ 8192
|
||||
|
||||
kipperkart.bin: kipperkart.o $(IP65TCPLIB) $(C64NB65LIB) $(INCFILES) ../cfg/c64_16kcart.cfg
|
||||
$(LD) -m kipperkart.map -vm -C ../cfg/c64_16kcart.cfg -o $@ $< $(IP65TCPLIB) $(C64NB65LIB)
|
||||
ruby fix_cart.rb $@ 16384
|
||||
ruby dupe_cart.rb kipperkart.bin kipperkart_29c040.bin 32
|
||||
|
||||
kipperkart_rr.bin: kipperkart.bin
|
||||
cp crt8040.obj rrnet_header.bin
|
||||
cat rrnet_header.bin kipperkart.bin > kipperkart_rr.bin
|
||||
ruby fix_cart.rb $@ 32768
|
||||
|
||||
c64boot.d64: netboot_ram.prg
|
||||
ripxplore.rb --init CbmDos $@ -a netboot_ram.prg
|
||||
ripxplore.rb $@ -a ..\test\test_cart_api.prg
|
||||
|
||||
d64_upload.d64: d64_upload.prg
|
||||
cp d64_upload.prg ../../server/boot/
|
||||
ripxplore.rb --init CbmDos $@ -a d64_upload.prg
|
||||
|
||||
clean:
|
||||
rm -f *.o *.bin *.map *.prg *.pg2 *.dsk *.d64
|
||||
|
||||
distclean: clean
|
||||
rm -f *~
|
145
client/carts/bootmenu.s
Normal file
145
client/carts/bootmenu.s
Normal 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
|
||||
|
||||
|
107
client/carts/crt8040.src
Normal file
107
client/carts/crt8040.src
Normal file
@ -0,0 +1,107 @@
|
||||
;taken from DocBacardi's CRT8040 tool - http://freenet-homepage.de/LittleDreamLand/CRT8040.html
|
||||
|
||||
#segdef "zp", $57-$72
|
||||
#segdef "bank0", $8000-$9f10, force, fillup
|
||||
#segdef "common", $df10-$e000, force, fillup
|
||||
|
||||
#outfile @, $00, "bank0", "common"
|
||||
|
||||
;--------------------------------------
|
||||
; init the startadr of all segments
|
||||
|
||||
.segment "zp"
|
||||
* = $57
|
||||
|
||||
.segment "bank0"
|
||||
* = $8000
|
||||
|
||||
.segment "common"
|
||||
* = $df10
|
||||
|
||||
;--------------------------------------
|
||||
; init the rr registers and copy
|
||||
; bank 3 to ram
|
||||
|
||||
.segment "bank0"
|
||||
|
||||
.DW Bank0_Reset ;Reset vector
|
||||
.DW $fe5e ;NMI vector is not used here, points to system
|
||||
.PET "CBM80" ;Reset Magic
|
||||
|
||||
Bank0_Reset:
|
||||
lda #%01000111 ;Standard Memory Map, No Freeze, No Banking in $DF00 (+ allow access to accessory connector - Jonno 2009-08-20)
|
||||
sta $de01
|
||||
|
||||
ldx #kickStack_len-1
|
||||
copyKickStack:
|
||||
lda kickStack_org,x
|
||||
sta kickStack,x
|
||||
dex
|
||||
bpl copyKickStack
|
||||
jmp kickStack
|
||||
|
||||
kickStack_org:
|
||||
.pseudopc $0900
|
||||
kickStack:
|
||||
|
||||
ldx #$1f
|
||||
ldy #0
|
||||
copyCrt:
|
||||
lda #%00101011 ; switch to bank 1
|
||||
sta $de00
|
||||
delay0:
|
||||
nop
|
||||
iny
|
||||
bne delay0
|
||||
copyPage0:
|
||||
smod0:
|
||||
lda $e000,y
|
||||
sta $0400,y
|
||||
iny
|
||||
bne copyPage0
|
||||
lda #%00110011 ; switch to bank 2
|
||||
sta $de00
|
||||
delay1:
|
||||
nop
|
||||
iny
|
||||
bne delay1
|
||||
copyPage1:
|
||||
lda $0400,y
|
||||
smod1:
|
||||
sta $8000,y
|
||||
iny
|
||||
bne copyPage1
|
||||
inc smod0+2
|
||||
inc smod1+2
|
||||
inc $d020
|
||||
dex
|
||||
bpl copyCrt
|
||||
|
||||
lda #%00110001 ; switch to 8040
|
||||
sta $de00
|
||||
delay2:
|
||||
nop
|
||||
iny
|
||||
bne delay2
|
||||
|
||||
|
||||
; during the copy process occured some irqs, clear them
|
||||
lda $dc0d
|
||||
lda $dd0d
|
||||
asl $d019
|
||||
|
||||
; set registers
|
||||
; NV-BDIZC
|
||||
lda #%00110111
|
||||
pha
|
||||
lda #$c3
|
||||
ldx #$00
|
||||
plp
|
||||
|
||||
jmp ($8000)
|
||||
|
||||
kickStack_len = *-kickStack
|
||||
.realpc
|
||||
|
||||
;--------------------------------------
|
||||
|
544
client/carts/d64_upload.s
Normal file
544
client/carts/d64_upload.s
Normal file
@ -0,0 +1,544 @@
|
||||
;use the NB65 API to send a d64 disk via TFTP
|
||||
;
|
||||
;
|
||||
|
||||
.ifndef NB65_API_VERSION_NUMBER
|
||||
.define EQU =
|
||||
.include "../inc/nb65_constants.i"
|
||||
.endif
|
||||
|
||||
.include "../ip65/copymem.s"
|
||||
.include "../inc/common.i"
|
||||
|
||||
.import print_a
|
||||
.import get_key
|
||||
.import get_filtered_input
|
||||
.import filter_dns
|
||||
.macro cout arg
|
||||
lda arg
|
||||
jsr print_a
|
||||
.endmacro
|
||||
|
||||
;######### KERNEL functions
|
||||
CHKIN = $ffc6
|
||||
CHKOUT = $ffc9
|
||||
CHRIN = $ffcf
|
||||
CHROUT = $ffd2
|
||||
CLALL = $FFE7
|
||||
CLOSE = $ffc3
|
||||
OPEN = $ffc0
|
||||
READST = $ffb7
|
||||
SETNAM = $ffbd
|
||||
SETLFS = $ffba
|
||||
|
||||
.bss
|
||||
current_byte: .res 1
|
||||
track: .res 1
|
||||
sector: .res 1
|
||||
sectors_in_track: .res 1
|
||||
error_buffer: .res 128
|
||||
|
||||
command_buffer: .res 128
|
||||
sector_buffer: .res 256
|
||||
nb65_param_buffer: .res $20
|
||||
sector_buffer_address: .res 2
|
||||
|
||||
.zeropage
|
||||
temp_ptr: .res 2
|
||||
|
||||
.segment "STARTUP" ;this is what gets put at the start of the file on the C64
|
||||
|
||||
.word basicstub ; load address
|
||||
|
||||
.macro print arg
|
||||
ldax arg
|
||||
ldy #NB65_PRINT_ASCIIZ
|
||||
jsr NB65_DISPATCH_VECTOR
|
||||
.endmacro
|
||||
|
||||
.macro print_cr
|
||||
lda #13
|
||||
jsr print_a
|
||||
.endmacro
|
||||
|
||||
.macro call arg
|
||||
ldy arg
|
||||
jsr NB65_DISPATCH_VECTOR
|
||||
.endmacro
|
||||
|
||||
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
|
||||
|
||||
|
||||
;look for NB65 signature at location pointed at by AX
|
||||
look_for_signature:
|
||||
stax temp_ptr
|
||||
ldy #3
|
||||
@check_one_byte:
|
||||
lda (temp_ptr),y
|
||||
cmp nb65_signature,y
|
||||
bne @bad_match
|
||||
dey
|
||||
bpl@check_one_byte
|
||||
clc
|
||||
rts
|
||||
@bad_match:
|
||||
sec
|
||||
rts
|
||||
init:
|
||||
|
||||
print #signon_message
|
||||
|
||||
ldax #NB65_CART_SIGNATURE ;where signature should be in cartridge
|
||||
jsr look_for_signature
|
||||
bcc @found_nb65_signature
|
||||
|
||||
ldax #NB65_RAM_STUB_SIGNATURE ;where signature should be in RAM
|
||||
jsr look_for_signature
|
||||
bcc :+
|
||||
jmp nb65_signature_not_found
|
||||
:
|
||||
jsr NB65_RAM_STUB_ACTIVATE ;we need to turn on NB65 cartridge
|
||||
|
||||
@found_nb65_signature:
|
||||
|
||||
print #initializing
|
||||
print #nb65_signature
|
||||
ldy #NB65_INITIALIZE
|
||||
jsr NB65_DISPATCH_VECTOR
|
||||
bcc :+
|
||||
print #failed
|
||||
jsr print_nb65_errorcode
|
||||
jmp bad_boot
|
||||
:
|
||||
print #ok
|
||||
print_cr
|
||||
|
||||
; ########################
|
||||
; main program goes here:
|
||||
;
|
||||
|
||||
jsr CLALL
|
||||
|
||||
|
||||
; ldx #18
|
||||
; stx track
|
||||
; ldx #1
|
||||
; stx sector
|
||||
; ldx #21
|
||||
; stx sectors_in_track
|
||||
; ldax #sector_buffer
|
||||
; jsr send_next_block
|
||||
; rts
|
||||
|
||||
|
||||
@send_1_image:
|
||||
lda #$93 ;cls
|
||||
jsr print_a
|
||||
print #signon_message
|
||||
jsr reset_counters_to_first_sector
|
||||
print #enter_filename
|
||||
ldax #filter_dns ;this is pretty close to being a filter for legal chars in file names as well
|
||||
jsr get_filtered_input
|
||||
bcs @no_filename_entered
|
||||
stax nb65_param_buffer+NB65_TFTP_FILENAME
|
||||
print #position_cursor_for_track_display
|
||||
ldax #send_next_block
|
||||
stax nb65_param_buffer+NB65_TFTP_POINTER
|
||||
ldax #nb65_param_buffer
|
||||
call #NB65_TFTP_CALLBACK_UPLOAD
|
||||
bcc :+
|
||||
print_cr
|
||||
print #failed
|
||||
jmp print_nb65_errorcode
|
||||
:
|
||||
lda #15 ; filenumber 15 - command channel
|
||||
jsr CLOSE
|
||||
print_cr
|
||||
print #ok
|
||||
print #press_a_key_to_continue
|
||||
jsr get_key
|
||||
jmp @send_1_image ;done! so go again
|
||||
@no_filename_entered:
|
||||
rts
|
||||
|
||||
|
||||
send_next_block:
|
||||
;tftp upload callback routine
|
||||
;AX will point to address to fill
|
||||
stax sector_buffer_address
|
||||
lda track
|
||||
cmp #36
|
||||
beq @past_last_track
|
||||
print #position_cursor_for_track_display
|
||||
jsr print_current_sector
|
||||
jsr read_sector
|
||||
lda #$30
|
||||
cmp error_buffer
|
||||
bne @was_an_error
|
||||
@after_error_check:
|
||||
jsr move_to_next_sector
|
||||
bcc @not_last_sector
|
||||
ldax #$100
|
||||
rts
|
||||
@not_last_sector:
|
||||
|
||||
; jsr dump_sector ;DEBUG
|
||||
|
||||
inc sector_buffer_address+1
|
||||
jsr read_sector
|
||||
jsr move_to_next_sector
|
||||
ldax #$200
|
||||
|
||||
; jsr dump_sector ;DEBUG
|
||||
|
||||
rts
|
||||
@past_last_track:
|
||||
ldax #$0000
|
||||
rts
|
||||
|
||||
@was_an_error:
|
||||
print #position_cursor_for_error_display
|
||||
print #drive_error
|
||||
print_cr
|
||||
jsr print_current_sector
|
||||
print #error_buffer
|
||||
jmp @after_error_check
|
||||
|
||||
print_current_sector:
|
||||
print #track_no
|
||||
lda track
|
||||
jsr byte_to_ascii
|
||||
pha
|
||||
txa
|
||||
jsr print_a
|
||||
pla
|
||||
jsr print_a
|
||||
print #sector_no
|
||||
lda sector
|
||||
jsr byte_to_ascii
|
||||
pha
|
||||
txa
|
||||
jsr print_a
|
||||
pla
|
||||
jsr print_a
|
||||
print_cr
|
||||
rts
|
||||
|
||||
|
||||
|
||||
dump_sector:
|
||||
;hex dump sector
|
||||
lda #0
|
||||
sta current_byte
|
||||
@dump_byte:
|
||||
ldy current_byte
|
||||
lda sector_buffer,y
|
||||
call #NB65_PRINT_HEX
|
||||
inc current_byte
|
||||
bne @dump_byte
|
||||
rts
|
||||
|
||||
read_sector:
|
||||
;routine to read a sector cribbed from http://codebase64.org/doku.php?id=base:reading_a_sector_from_disk
|
||||
; - requires track and sector values be set first
|
||||
; sector will be written to address whos value is stored in sector_data
|
||||
; open the channel file
|
||||
|
||||
jsr make_read_sector_command
|
||||
|
||||
lda #1
|
||||
ldx #<cname
|
||||
ldy #>cname
|
||||
jsr SETNAM
|
||||
lda #02
|
||||
ldx #08
|
||||
ldy #02
|
||||
jsr SETLFS
|
||||
jsr OPEN
|
||||
bcs @error
|
||||
ldx #<command_buffer
|
||||
ldy #>command_buffer
|
||||
lda #12
|
||||
jsr SETNAM
|
||||
lda #15
|
||||
ldx $BA ;use whatever was last device #
|
||||
ldy #15
|
||||
jsr SETLFS
|
||||
jsr OPEN
|
||||
bcs @error
|
||||
|
||||
|
||||
jsr check_error_channel
|
||||
lda #$30
|
||||
cmp error_buffer
|
||||
beq @was_not_an_error
|
||||
print #error_buffer
|
||||
|
||||
@was_not_an_error:
|
||||
ldx #$02 ; filenumber 2
|
||||
jsr CHKIN ;(file 2 now used as input)
|
||||
|
||||
lda sector_buffer_address
|
||||
sta temp_ptr
|
||||
lda sector_buffer_address+1
|
||||
sta temp_ptr+1
|
||||
ldy #$00
|
||||
@loop:
|
||||
jsr CHRIN ;(get a byte from file)
|
||||
sta (temp_ptr),Y ; write byte to memory
|
||||
iny
|
||||
bne @loop ; next byte, end when 256 bytes are read
|
||||
@close:
|
||||
lda #15 ; filenumber 15
|
||||
jsr CLOSE
|
||||
lda #$02 ; filenumber 2
|
||||
jsr CLOSE
|
||||
ldx #$00 ; filenumber 0 = keyboard
|
||||
jsr CHKIN ;(keyboard now input device again)
|
||||
rts
|
||||
@error:
|
||||
pha
|
||||
print #error_opening_channel
|
||||
pla
|
||||
call #NB65_PRINT_HEX
|
||||
jmp @close
|
||||
|
||||
check_error_channel:
|
||||
LDX #$0F ; filenumber 15
|
||||
JSR CHKIN ;(file 15 now used as input)
|
||||
LDY #$00
|
||||
@loop:
|
||||
JSR READST ;(read status byte)
|
||||
BNE @eof ; either EOF or read error
|
||||
JSR CHRIN ;(get a byte from file)
|
||||
sta error_buffer,y
|
||||
iny
|
||||
JMP @loop ; next byte
|
||||
|
||||
@eof:
|
||||
lda #0
|
||||
sta error_buffer,y
|
||||
LDX #$00 ; filenumber 0 = keyboard
|
||||
JSR CHKIN ;(keyboard now input device again)
|
||||
RTS
|
||||
|
||||
bad_boot:
|
||||
print #press_a_key_to_continue
|
||||
restart:
|
||||
jsr get_key
|
||||
jmp $fce2 ;do a cold start
|
||||
|
||||
|
||||
print_a_as_errorcode:
|
||||
pha
|
||||
lda #' '
|
||||
jsr print_a
|
||||
print #error_code
|
||||
pla
|
||||
call #NB65_PRINT_HEX
|
||||
rts
|
||||
|
||||
print_nb65_errorcode:
|
||||
print #error_code
|
||||
call #NB65_GET_LAST_ERROR
|
||||
call #NB65_PRINT_HEX
|
||||
print_cr
|
||||
rts
|
||||
|
||||
nb65_signature_not_found:
|
||||
|
||||
ldy #0
|
||||
:
|
||||
lda nb65_signature_not_found_message,y
|
||||
beq restart
|
||||
jsr print_a
|
||||
iny
|
||||
jmp :-
|
||||
|
||||
|
||||
|
||||
make_read_sector_command:
|
||||
;fill command buffer with command to read in track & sector
|
||||
;returns length of command in Y
|
||||
|
||||
ldy #0
|
||||
lda #85 ;"U"
|
||||
sta command_buffer,y
|
||||
iny
|
||||
lda #$31 ;"1"
|
||||
sta command_buffer,y
|
||||
iny
|
||||
lda #$20 ;" "
|
||||
sta command_buffer,y
|
||||
iny
|
||||
lda #$32 ;"2" - file number
|
||||
sta command_buffer,y
|
||||
iny
|
||||
lda #$20 ;" "
|
||||
sta command_buffer,y
|
||||
iny
|
||||
lda #$30 ;"0" - drive number
|
||||
sta command_buffer,y
|
||||
iny
|
||||
lda #$20 ;" "
|
||||
sta command_buffer,y
|
||||
iny
|
||||
lda track
|
||||
jsr byte_to_ascii
|
||||
pha
|
||||
txa
|
||||
sta command_buffer,y
|
||||
pla
|
||||
iny
|
||||
sta command_buffer,y
|
||||
iny
|
||||
lda #$20 ;" "
|
||||
sta command_buffer,y
|
||||
iny
|
||||
lda sector
|
||||
jsr byte_to_ascii
|
||||
pha
|
||||
txa
|
||||
sta command_buffer,y
|
||||
pla
|
||||
iny
|
||||
sta command_buffer,y
|
||||
iny
|
||||
|
||||
lda #0
|
||||
sta command_buffer,y ;make it ASCIIZ so we can print it
|
||||
|
||||
rts
|
||||
|
||||
byte_to_ascii:
|
||||
cmp #30
|
||||
bmi @not_30
|
||||
ldx #$33
|
||||
clc
|
||||
adc #18
|
||||
rts
|
||||
@not_30:
|
||||
cmp #20
|
||||
bmi @not_20
|
||||
ldx #$32
|
||||
clc
|
||||
adc #28
|
||||
rts
|
||||
@not_20:
|
||||
cmp #10
|
||||
bmi @not_10
|
||||
ldx #$31
|
||||
clc
|
||||
adc #38
|
||||
rts
|
||||
@not_10:
|
||||
ldx #$30
|
||||
clc
|
||||
adc #48
|
||||
rts
|
||||
|
||||
|
||||
reset_counters_to_first_sector:
|
||||
ldx #1
|
||||
stx track
|
||||
dex
|
||||
stx sector
|
||||
ldx #21
|
||||
stx sectors_in_track
|
||||
rts
|
||||
|
||||
move_to_next_sector:
|
||||
inc sector
|
||||
lda sector
|
||||
cmp sectors_in_track
|
||||
beq @move_to_next_track
|
||||
rts
|
||||
@move_to_next_track:
|
||||
lda #0
|
||||
sta sector
|
||||
inc track
|
||||
lda track
|
||||
cmp #18
|
||||
bne @not_track_18
|
||||
lda #19
|
||||
sta sectors_in_track
|
||||
clc
|
||||
rts
|
||||
@not_track_18:
|
||||
cmp #25
|
||||
bne @not_track_25
|
||||
lda #18
|
||||
sta sectors_in_track
|
||||
clc
|
||||
rts
|
||||
@not_track_25:
|
||||
cmp #31
|
||||
bne @not_track_31
|
||||
lda #17
|
||||
sta sectors_in_track
|
||||
clc
|
||||
rts
|
||||
@not_track_31:
|
||||
lda track
|
||||
cmp #36 ;carry will be set if hit track 36
|
||||
rts
|
||||
|
||||
|
||||
.rodata
|
||||
|
||||
error_code:
|
||||
.byte "ERROR CODE: $",0
|
||||
press_a_key_to_continue:
|
||||
.byte "PRESS A KEY TO CONTINUE",13,0
|
||||
|
||||
failed:
|
||||
.byte "FAILED ", 0
|
||||
|
||||
ok:
|
||||
.byte "OK ", 0
|
||||
|
||||
initializing:
|
||||
.byte "INITIALIZING ",0
|
||||
track_no:
|
||||
.byte "TRACK ",0
|
||||
|
||||
|
||||
sector_no:
|
||||
.byte " SECTOR ",0
|
||||
|
||||
signon_message:
|
||||
.byte "D64 UPLOADER V0.1",13,0
|
||||
|
||||
enter_filename:
|
||||
.byte "SEND AS: ",0
|
||||
|
||||
drive_error:
|
||||
.byte "DRIVE ACCESS ERROR - ",0
|
||||
nb65_signature_not_found_message:
|
||||
.byte "NO NB65 API FOUND",13,"PRESS ANY KEY TO RESET", 0
|
||||
error_opening_channel:
|
||||
.byte "ERROR OPENING CHANNEL $",0
|
||||
|
||||
disk_access:
|
||||
.byte 13,13,13,13,13,"SENDING TO CHANNEL $",0
|
||||
|
||||
nb65_signature:
|
||||
.byte $4E,$42,$36,$35 ; "NB65" - API signature
|
||||
.byte ' ',0 ; so we can use this as a string
|
||||
position_cursor_for_track_display:
|
||||
; .byte $13,13,13,13,13,13,13,13,13,13,13," SENDING ",0
|
||||
.byte $13,13,13,"SENDING ",0
|
||||
position_cursor_for_error_display:
|
||||
.byte $13,13,13,13,"LAST ",0
|
||||
|
||||
cname: .byte '#'
|
15
client/carts/dupe_cart.rb
Normal file
15
client/carts/dupe_cart.rb
Normal file
@ -0,0 +1,15 @@
|
||||
infilename=ARGV[0]
|
||||
outfilename=ARGV[1]
|
||||
duplication=ARGV[2].to_i
|
||||
|
||||
if duplication.nil? then
|
||||
puts "usage: dupe_cart.rb [input filename] [output filename] [number of duplications]"
|
||||
exit
|
||||
end
|
||||
|
||||
|
||||
infile=File.open(infilename,"rb").read
|
||||
puts "copying #{infilename} to #{outfilename} #{duplication} times"
|
||||
outfile=File.open(outfilename,"wb")
|
||||
duplication.times {outfile<<infile}
|
||||
outfile.close
|
26
client/carts/fix_cart.rb
Normal file
26
client/carts/fix_cart.rb
Normal 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/carts/hello
Normal file
BIN
client/carts/hello
Normal file
Binary file not shown.
812
client/carts/kipperkart.s
Normal file
812
client/carts/kipperkart.s
Normal file
@ -0,0 +1,812 @@
|
||||
; #############
|
||||
; KIPPER KART - A C64 TCP/IP stack as a 16KB cartridge
|
||||
; jonno@jamtronix.com
|
||||
|
||||
.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 kippercall arg
|
||||
ldy arg
|
||||
jsr KPR_DISPATCH_VECTOR
|
||||
.endmacro
|
||||
|
||||
.ifndef KPR_API_VERSION_NUMBER
|
||||
.define EQU =
|
||||
.include "../inc/kipper_constants.i"
|
||||
.endif
|
||||
.include "../inc/common.i"
|
||||
.include "../inc/c64keycodes.i"
|
||||
.include "../inc/menu.i"
|
||||
|
||||
KEY_NEXT_PAGE=KEYCODE_F7
|
||||
KEY_PREV_PAGE=KEYCODE_F1
|
||||
KEY_SHOW_HISTORY=KEYCODE_F2
|
||||
KEY_BACK_IN_HISTORY=KEYCODE_F3
|
||||
KEY_NEW_SERVER=KEYCODE_F5
|
||||
|
||||
|
||||
.include "../inc/gopher.i"
|
||||
.include "../inc/telnet.i"
|
||||
.include "../inc/ping.i"
|
||||
|
||||
.import cls
|
||||
.import beep
|
||||
.import exit_to_basic
|
||||
.import timer_vbl_handler
|
||||
.import kipper_dispatcher
|
||||
.import ip65_process
|
||||
.import ip65_init
|
||||
.import get_filtered_input
|
||||
.import filter_text
|
||||
.import filter_dns
|
||||
.import filter_ip
|
||||
.import print_arp_cache
|
||||
.import arp_calculate_gateway_mask
|
||||
.import parse_dotted_quad
|
||||
.import dotted_quad_value
|
||||
.import parse_integer
|
||||
.import print_integer
|
||||
.import get_key_ip65
|
||||
.import cfg_ip
|
||||
.import cfg_netmask
|
||||
.import cfg_gateway
|
||||
.import cfg_dns
|
||||
.import cfg_tftp_server
|
||||
|
||||
.import print_ascii_as_native
|
||||
.import print_dotted_quad
|
||||
.import print_hex
|
||||
.import print_errorcode
|
||||
.import print_ip_config
|
||||
.import ok_msg
|
||||
.import failed_msg
|
||||
.import init_msg
|
||||
.import ip_address_msg
|
||||
.import netmask_msg
|
||||
.import gateway_msg
|
||||
.import dns_server_msg
|
||||
.import tftp_server_msg
|
||||
.import press_a_key_to_continue
|
||||
|
||||
.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 __SELF_MODIFIED_CODE_LOAD__
|
||||
.import __SELF_MODIFIED_CODE_RUN__
|
||||
.import __SELF_MODIFIED_CODE_SIZE__
|
||||
|
||||
.import cfg_tftp_server
|
||||
kipper_param_buffer = $6000
|
||||
directory_buffer = $6020
|
||||
|
||||
.data
|
||||
|
||||
call_downloaded_prg:
|
||||
jsr $0000 ;overwritten when we load a file
|
||||
jmp init
|
||||
|
||||
get_value_of_axy: ;some more self-modifying code
|
||||
lda $ffff,y
|
||||
rts
|
||||
|
||||
|
||||
.segment "CARTRIDGE_HEADER"
|
||||
.word init ;cold start vector
|
||||
.word $FE47 ;warm start vector
|
||||
.byte $C3,$C2,$CD,$38,$30 ; "CBM80"
|
||||
.byte "KIPPER" ; API signature
|
||||
jmp kipper_dispatcher ; KPR_DISPATCH_VECTOR : entry point for KIPPER functions
|
||||
jmp ip65_process ;KPR_PERIODIC_PROCESSING_VECTOR : routine to be periodically called to check for arrival of ethernet packets
|
||||
jmp timer_vbl_handler ;KPR_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
|
||||
|
||||
;set some funky colours
|
||||
|
||||
LDA #$04 ;purple
|
||||
|
||||
STA $D020 ;border
|
||||
LDA #$00 ;black
|
||||
STA $D021 ;background
|
||||
lda #$05 ;petscii for white text
|
||||
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
|
||||
|
||||
|
||||
;relocate the self-modifying code (if necessary)
|
||||
ldax #__SELF_MODIFIED_CODE_LOAD__
|
||||
stax copy_src
|
||||
ldax #__SELF_MODIFIED_CODE_RUN__
|
||||
stax copy_dest
|
||||
ldax #__SELF_MODIFIED_CODE_SIZE__
|
||||
jsr copymem
|
||||
|
||||
ldax #netboot65_msg
|
||||
jsr print
|
||||
ldax #init_msg+1
|
||||
jsr print
|
||||
|
||||
kippercall #KPR_INITIALIZE
|
||||
bcc init_ok
|
||||
print_failed
|
||||
jsr print_errorcode
|
||||
jsr wait_for_keypress
|
||||
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
|
||||
ldax #main_menu_msg
|
||||
jmp print
|
||||
|
||||
init_ok:
|
||||
|
||||
;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
|
||||
|
||||
main_menu:
|
||||
jsr print_main_menu
|
||||
jsr print_ip_config
|
||||
jsr print_cr
|
||||
|
||||
@get_key:
|
||||
jsr get_key_ip65
|
||||
cmp #KEYCODE_F1
|
||||
bne @not_tftp
|
||||
jmp @tftp_boot
|
||||
@not_tftp:
|
||||
cmp #KEYCODE_F2
|
||||
bne @not_disk
|
||||
jmp disk_boot
|
||||
@not_disk:
|
||||
|
||||
cmp #KEYCODE_F3
|
||||
bne @not_f3
|
||||
jmp net_apps_menu
|
||||
@not_f3:
|
||||
cmp #KEYCODE_F4
|
||||
bne @not_download_d64
|
||||
jmp d64_download
|
||||
@not_download_d64:
|
||||
|
||||
cmp #KEYCODE_F5
|
||||
bne @not_util_menu
|
||||
jsr print_main_menu
|
||||
jsr print_arp_cache
|
||||
jmp @get_key
|
||||
@not_util_menu:
|
||||
cmp #KEYCODE_F7
|
||||
beq @change_config
|
||||
|
||||
jmp @get_key
|
||||
|
||||
@exit_to_prog:
|
||||
ldax #$fe66 ;do a wam start
|
||||
jmp call_downloaded_prg
|
||||
|
||||
|
||||
@change_config:
|
||||
jsr cls
|
||||
ldax #netboot65_msg
|
||||
jsr print
|
||||
ldax #config_menu_msg
|
||||
jsr print
|
||||
jsr print_ip_config
|
||||
jsr print_cr
|
||||
@get_key_config_menu:
|
||||
jsr get_key_ip65
|
||||
cmp #KEYCODE_ABORT
|
||||
bne @not_abort
|
||||
jmp main_menu
|
||||
@not_abort:
|
||||
cmp #KEYCODE_F1
|
||||
bne @not_ip
|
||||
ldax #new
|
||||
jsr print
|
||||
ldax #ip_address_msg
|
||||
jsr print
|
||||
jsr print_cr
|
||||
ldax #filter_ip
|
||||
ldy #20
|
||||
jsr get_filtered_input
|
||||
bcs @no_ip_address_entered
|
||||
jsr parse_dotted_quad
|
||||
bcc @no_ip_resolve_error
|
||||
jmp @change_config
|
||||
@no_ip_resolve_error:
|
||||
ldax #dotted_quad_value
|
||||
stax copy_src
|
||||
ldax #cfg_ip
|
||||
stax copy_dest
|
||||
ldax #4
|
||||
jsr copymem
|
||||
@no_ip_address_entered:
|
||||
jmp @change_config
|
||||
|
||||
@not_ip:
|
||||
cmp #KEYCODE_F2
|
||||
bne @not_netmask
|
||||
ldax #new
|
||||
jsr print
|
||||
ldax #netmask_msg
|
||||
jsr print
|
||||
jsr print_cr
|
||||
ldax #filter_ip
|
||||
ldy #20
|
||||
jsr get_filtered_input
|
||||
bcs @no_netmask_entered
|
||||
jsr parse_dotted_quad
|
||||
bcc @no_netmask_resolve_error
|
||||
jmp @change_config
|
||||
@no_netmask_resolve_error:
|
||||
ldax #dotted_quad_value
|
||||
stax copy_src
|
||||
ldax #cfg_netmask
|
||||
stax copy_dest
|
||||
ldax #4
|
||||
jsr copymem
|
||||
@no_netmask_entered:
|
||||
jmp @change_config
|
||||
|
||||
@not_netmask:
|
||||
cmp #KEYCODE_F3
|
||||
bne @not_gateway
|
||||
ldax #new
|
||||
jsr print
|
||||
ldax #gateway_msg
|
||||
jsr print
|
||||
jsr print_cr
|
||||
ldax #filter_ip
|
||||
ldy #20
|
||||
jsr get_filtered_input
|
||||
bcs @no_gateway_entered
|
||||
jsr parse_dotted_quad
|
||||
bcc @no_gateway_resolve_error
|
||||
jmp @change_config
|
||||
@no_gateway_resolve_error:
|
||||
ldax #dotted_quad_value
|
||||
stax copy_src
|
||||
ldax #cfg_gateway
|
||||
stax copy_dest
|
||||
ldax #4
|
||||
jsr copymem
|
||||
jsr arp_calculate_gateway_mask ;we have modified our netmask, so we need to recalculate gw_test
|
||||
@no_gateway_entered:
|
||||
jmp @change_config
|
||||
|
||||
|
||||
@not_gateway:
|
||||
cmp #KEYCODE_F4
|
||||
bne @not_dns_server
|
||||
ldax #new
|
||||
jsr print
|
||||
ldax #dns_server_msg
|
||||
jsr print
|
||||
jsr print_cr
|
||||
ldax #filter_ip
|
||||
ldy #20
|
||||
jsr get_filtered_input
|
||||
bcs @no_dns_server_entered
|
||||
jsr parse_dotted_quad
|
||||
bcc @no_dns_resolve_error
|
||||
jmp @change_config
|
||||
@no_dns_resolve_error:
|
||||
ldax #dotted_quad_value
|
||||
stax copy_src
|
||||
ldax #cfg_dns
|
||||
stax copy_dest
|
||||
ldax #4
|
||||
jsr copymem
|
||||
@no_dns_server_entered:
|
||||
|
||||
jmp @change_config
|
||||
|
||||
@not_dns_server:
|
||||
cmp #KEYCODE_F5
|
||||
bne @not_tftp_server
|
||||
ldax #new
|
||||
jsr print
|
||||
ldax #tftp_server_msg
|
||||
jsr print
|
||||
jsr print_cr
|
||||
ldax #filter_dns
|
||||
ldy #40
|
||||
jsr get_filtered_input
|
||||
bcs @no_server_entered
|
||||
stax kipper_param_buffer
|
||||
jsr print_cr
|
||||
ldax #resolving
|
||||
jsr print
|
||||
ldax #kipper_param_buffer
|
||||
kippercall #KPR_DNS_RESOLVE
|
||||
bcs @resolve_error
|
||||
ldax #kipper_param_buffer
|
||||
stax copy_src
|
||||
ldax #cfg_tftp_server
|
||||
stax copy_dest
|
||||
ldax #4
|
||||
jsr copymem
|
||||
@no_server_entered:
|
||||
jmp @change_config
|
||||
|
||||
@not_tftp_server:
|
||||
|
||||
|
||||
cmp #KEYCODE_F6
|
||||
bne @not_reset
|
||||
jsr ip65_init ;this will reset everything
|
||||
jmp @change_config
|
||||
@not_reset:
|
||||
cmp #KEYCODE_F7
|
||||
bne @not_main_menu
|
||||
jmp main_menu
|
||||
|
||||
@not_main_menu:
|
||||
jmp @get_key_config_menu
|
||||
|
||||
|
||||
@resolve_error:
|
||||
print_failed
|
||||
jsr wait_for_keypress
|
||||
jsr @change_config
|
||||
|
||||
@tftp_boot:
|
||||
|
||||
ldax #tftp_dir_filemask
|
||||
jsr get_tftp_directory_listing
|
||||
bcs return_to_main
|
||||
|
||||
@boot_filename_set:
|
||||
;AX now points to filename
|
||||
jsr download
|
||||
bcc file_downloaded_ok
|
||||
tftp_boot_failed:
|
||||
jsr wait_for_keypress
|
||||
return_to_main:
|
||||
jmp main_menu
|
||||
|
||||
file_downloaded_ok:
|
||||
ldax kipper_param_buffer+KPR_TFTP_POINTER
|
||||
|
||||
boot_into_file:
|
||||
stax kipper_param_buffer ;use the param buffer as a temp holding place for the load address
|
||||
;get ready to bank out
|
||||
kippercall #KPR_DEACTIVATE
|
||||
|
||||
jsr $ffe7 ; make sure all files have been closed.
|
||||
|
||||
;check whether the file we just downloaded was a BASIC prg
|
||||
lda kipper_param_buffer
|
||||
cmp #01
|
||||
bne @not_a_basic_file
|
||||
|
||||
lda kipper_param_buffer+1
|
||||
cmp #$08
|
||||
bne @not_a_basic_file
|
||||
|
||||
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!
|
||||
@not_a_basic_stub:
|
||||
ldax #cant_boot_basic
|
||||
jsr print
|
||||
jsr wait_for_keypress
|
||||
jmp init
|
||||
|
||||
@not_a_basic_file:
|
||||
ldax kipper_param_buffer
|
||||
exit_cart_via_ax:
|
||||
sta call_downloaded_prg+1
|
||||
stx call_downloaded_prg+2
|
||||
jmp call_downloaded_prg
|
||||
|
||||
get_tftp_directory_listing:
|
||||
stax kipper_param_buffer+KPR_TFTP_FILENAME
|
||||
|
||||
ldax #directory_buffer
|
||||
stax kipper_param_buffer+KPR_TFTP_POINTER
|
||||
|
||||
ldax #getting_dir_listing_msg
|
||||
jsr print
|
||||
|
||||
ldax #kipper_param_buffer
|
||||
kippercall #KPR_TFTP_DOWNLOAD
|
||||
|
||||
bcs @dir_failed
|
||||
|
||||
lda directory_buffer ;get the first byte that was downloaded
|
||||
bne :+
|
||||
jmp @no_files_on_server
|
||||
:
|
||||
|
||||
;switch to lower case charset
|
||||
lda #23
|
||||
sta $d018
|
||||
|
||||
|
||||
ldax #directory_buffer
|
||||
|
||||
jsr select_option_from_menu
|
||||
bcc @tftp_filename_set
|
||||
rts
|
||||
@tftp_filename_set:
|
||||
stax copy_dest
|
||||
stax get_value_of_axy+1
|
||||
ldy #0
|
||||
jsr get_value_of_axy ;A now == first char in string we just downloaded
|
||||
cmp #'$'
|
||||
bne @not_directory_name
|
||||
;it's a directory name, so we need to append the file mask to end of it
|
||||
;this will fail if the file path is more than 255 characters long
|
||||
@look_for_trailing_zero:
|
||||
iny
|
||||
inc copy_dest
|
||||
bne :+
|
||||
inc copy_dest+1
|
||||
:
|
||||
jsr get_value_of_axy ;A now == next char in string we just downloaded
|
||||
bne @look_for_trailing_zero
|
||||
|
||||
; got trailing zero
|
||||
ldax #tftp_dir_filemask+1 ;skip the leading '$'
|
||||
stax copy_src
|
||||
ldax #$07
|
||||
jsr copymem
|
||||
ldax get_value_of_axy+1
|
||||
jmp get_tftp_directory_listing
|
||||
|
||||
@not_directory_name:
|
||||
ldax get_value_of_axy+1
|
||||
clc
|
||||
rts
|
||||
|
||||
|
||||
@dir_failed:
|
||||
ldax #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
|
||||
jsr print
|
||||
|
||||
jmp tftp_boot_failed
|
||||
|
||||
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
|
||||
|
||||
d64_download:
|
||||
|
||||
ldax #d64_filemask
|
||||
jsr get_tftp_directory_listing
|
||||
bcc @d64_filename_set
|
||||
jmp main_menu
|
||||
@d64_filename_set:
|
||||
;AX now points to filename
|
||||
.byte $92
|
||||
jmp main_menu
|
||||
|
||||
|
||||
net_apps_menu:
|
||||
jsr cls
|
||||
ldax #netboot65_msg
|
||||
jsr print
|
||||
ldax #net_apps_menu_msg
|
||||
jsr print
|
||||
@get_key:
|
||||
jsr get_key_ip65
|
||||
cmp #KEYCODE_ABORT
|
||||
bne @not_abort
|
||||
jmp main_menu
|
||||
@not_abort:
|
||||
cmp #KEYCODE_F1
|
||||
bne @not_telnet
|
||||
jsr cls
|
||||
lda #14
|
||||
jsr print_a ;switch to lower case
|
||||
ldax #telnet_header
|
||||
jsr print
|
||||
jmp telnet_main_entry
|
||||
@not_telnet:
|
||||
cmp #KEYCODE_F2
|
||||
bne @not_gopher
|
||||
jsr cls
|
||||
lda #14
|
||||
jsr print_a ;switch to lower case
|
||||
ldax #gopher_header
|
||||
jsr print
|
||||
jsr prompt_for_gopher_resource ;only returns if no server was entered.
|
||||
jmp exit_gopher
|
||||
@not_gopher:
|
||||
|
||||
cmp #KEYCODE_F3
|
||||
bne @not_gopher_floodgap_com
|
||||
jsr cls
|
||||
lda #14
|
||||
jsr print_a ;switch to lower case
|
||||
|
||||
ldax #gopher_initial_location
|
||||
sta resource_pointer_lo
|
||||
stx resource_pointer_hi
|
||||
ldx #0
|
||||
jsr select_resource_from_current_directory
|
||||
jmp exit_gopher
|
||||
@not_gopher_floodgap_com:
|
||||
|
||||
cmp #KEYCODE_F5
|
||||
bne @not_ping
|
||||
jsr cls
|
||||
lda #14
|
||||
jsr print_a ;switch to lower case
|
||||
ldax #ping_header
|
||||
jsr print
|
||||
jsr ping_loop
|
||||
jmp exit_ping
|
||||
@not_ping:
|
||||
|
||||
cmp #KEYCODE_F7
|
||||
bne @not_main
|
||||
jmp main_menu
|
||||
@not_main:
|
||||
jmp @get_key
|
||||
|
||||
|
||||
|
||||
bad_boot:
|
||||
jsr wait_for_keypress
|
||||
jmp $fe66 ;do a wam start
|
||||
|
||||
download: ;AX should point at filename to download
|
||||
stax kipper_param_buffer+KPR_TFTP_FILENAME
|
||||
ldax #$0000 ;load address will be first 2 bytes of file we download (LO/HI order)
|
||||
stax kipper_param_buffer+KPR_TFTP_POINTER
|
||||
|
||||
ldax #downloading_msg
|
||||
jsr print
|
||||
ldax kipper_param_buffer+KPR_TFTP_FILENAME
|
||||
jsr print
|
||||
jsr print_cr
|
||||
|
||||
ldax #kipper_param_buffer
|
||||
kippercall #KPR_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 KPR_PERIODIC_PROCESSING_VECTOR
|
||||
jsr $ffe4
|
||||
beq @loop
|
||||
rts
|
||||
|
||||
|
||||
cfg_get_configuration_ptr:
|
||||
ldax #kipper_param_buffer
|
||||
kippercall #KPR_GET_IP_CONFIG
|
||||
rts
|
||||
|
||||
exit_ping:
|
||||
exit_telnet:
|
||||
exit_gopher:
|
||||
lda #142
|
||||
jsr print_a ;switch to upper case
|
||||
lda #$05 ;petscii for white text
|
||||
jsr print_a
|
||||
jmp net_apps_menu
|
||||
.rodata
|
||||
|
||||
netboot65_msg:
|
||||
.byte 13,"KIPPERNET V"
|
||||
.include "../inc/version.i"
|
||||
.byte 13,0
|
||||
main_menu_msg:
|
||||
.byte 13,"MAIN MENU",13,13
|
||||
.byte "F1: TFTP BOOT F2: DISK BOOT",13
|
||||
.byte "F3: NET APPS F4: DOWNLOAD D64",13
|
||||
.byte "F5: ARP TABLE F7: CONFIG",13,13
|
||||
|
||||
.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 0
|
||||
|
||||
|
||||
net_apps_menu_msg:
|
||||
.byte 13,"NET APPS",13,13
|
||||
.byte "F1: TELNET F2: GOPHER ",13
|
||||
.byte "F3: GOPHER (FLOODGAP.COM)",13
|
||||
.byte "F5: PING F7: MAIN MENU",13,13
|
||||
.byte 0
|
||||
|
||||
cant_boot_basic:
|
||||
.byte "BASIC FILE EXECUTION NOT SUPPORTED",13,0
|
||||
gopher_initial_location:
|
||||
.byte "1gopher.floodgap.com",$09,"/",$09,"gopher.floodgap.com",$09,"70",$0D,$0A,0
|
||||
|
||||
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
|
||||
|
||||
downloading_msg: .byte "DOWN"
|
||||
loading_msg: .asciiz "LOADING "
|
||||
|
||||
getting_dir_listing_msg: .byte "FETCHING DIRECTORY",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 "DOWN"
|
||||
load_ok_msg:
|
||||
.byte "LOAD OK", 13, 0
|
||||
|
||||
current:
|
||||
.byte "CURRENT ",0
|
||||
|
||||
new:
|
||||
.byte"NEW ",0
|
||||
|
||||
tftp_dir_filemask:
|
||||
.asciiz "$/*.prg"
|
||||
|
||||
d64_filemask:
|
||||
.asciiz "$/*.d64"
|
||||
|
||||
tftp_file:
|
||||
.asciiz "BOOTC64.PRG"
|
||||
|
||||
no_files:
|
||||
.byte "NO FILES",13,0
|
||||
|
||||
resolving:
|
||||
.byte "RESOLVING ",0
|
||||
|
73
client/carts/nb65_c64_ram_header.s
Normal file
73
client/carts/nb65_c64_ram_header.s
Normal 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:
|
||||
|
||||
|
||||
|
155
client/carts/nb65_skeleton.s
Normal file
155
client/carts/nb65_skeleton.s
Normal file
@ -0,0 +1,155 @@
|
||||
;use the NB65 API to send a d64 disk via TFTP
|
||||
|
||||
.ifndef NB65_API_VERSION_NUMBER
|
||||
.define EQU =
|
||||
.include "../inc/nb65_constants.i"
|
||||
.endif
|
||||
|
||||
.include "../ip65/copymem.s"
|
||||
.include "../inc/common.i"
|
||||
|
||||
.import print_a
|
||||
.import get_key
|
||||
.macro cout arg
|
||||
lda arg
|
||||
jsr print_a
|
||||
.endmacro
|
||||
|
||||
.zeropage
|
||||
temp_ptr: .res 2
|
||||
|
||||
.bss
|
||||
nb65_param_buffer: .res $20
|
||||
block_number: .res $0
|
||||
|
||||
.segment "STARTUP" ;this is what gets put at the start of the file on the C64
|
||||
|
||||
.word basicstub ; load address
|
||||
|
||||
.macro print arg
|
||||
ldax arg
|
||||
ldy #NB65_PRINT_ASCIIZ
|
||||
jsr NB65_DISPATCH_VECTOR
|
||||
.endmacro
|
||||
|
||||
.macro print_cr
|
||||
lda #13
|
||||
jsr print_a
|
||||
.endmacro
|
||||
|
||||
.macro call arg
|
||||
ldy arg
|
||||
jsr NB65_DISPATCH_VECTOR
|
||||
.endmacro
|
||||
|
||||
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
|
||||
|
||||
|
||||
;look for NB65 signature at location pointed at by AX
|
||||
look_for_signature:
|
||||
stax temp_ptr
|
||||
ldy #3
|
||||
@check_one_byte:
|
||||
lda (temp_ptr),y
|
||||
cmp nb65_signature,y
|
||||
bne @bad_match
|
||||
dey
|
||||
bpl@check_one_byte
|
||||
clc
|
||||
rts
|
||||
@bad_match:
|
||||
sec
|
||||
rts
|
||||
init:
|
||||
|
||||
print #signon_message
|
||||
|
||||
ldax #NB65_CART_SIGNATURE ;where signature should be in cartridge
|
||||
jsr look_for_signature
|
||||
bcc @found_nb65_signature
|
||||
|
||||
ldax #NB65_RAM_STUB_SIGNATURE ;where signature should be in RAM
|
||||
jsr look_for_signature
|
||||
bcc :+
|
||||
jmp nb65_signature_not_found
|
||||
:
|
||||
jsr NB65_RAM_STUB_ACTIVATE ;we need to turn on NB65 cartridge
|
||||
|
||||
@found_nb65_signature:
|
||||
|
||||
print #initializing
|
||||
print #nb65_signature
|
||||
ldy #NB65_INITIALIZE
|
||||
jsr NB65_DISPATCH_VECTOR
|
||||
bcc :+
|
||||
print #failed
|
||||
jsr print_errorcode
|
||||
jmp bad_boot
|
||||
:
|
||||
print #ok
|
||||
print_cr
|
||||
|
||||
; ########################
|
||||
; main program goes here:
|
||||
;
|
||||
rts
|
||||
|
||||
bad_boot:
|
||||
print #press_a_key_to_continue
|
||||
restart:
|
||||
jsr get_key
|
||||
jmp $fce2 ;do a cold start
|
||||
|
||||
|
||||
print_errorcode:
|
||||
print #error_code
|
||||
call #NB65_GET_LAST_ERROR
|
||||
call #NB65_PRINT_HEX
|
||||
print_cr
|
||||
rts
|
||||
|
||||
nb65_signature_not_found:
|
||||
|
||||
ldy #0
|
||||
:
|
||||
lda nb65_signature_not_found_message,y
|
||||
beq restart
|
||||
jsr print_a
|
||||
iny
|
||||
jmp :-
|
||||
|
||||
.rodata
|
||||
|
||||
error_code:
|
||||
.asciiz "ERROR CODE: $"
|
||||
press_a_key_to_continue:
|
||||
.byte "PRESS A KEY TO CONTINUE",13,0
|
||||
|
||||
failed:
|
||||
.byte "FAILED ", 0
|
||||
|
||||
ok:
|
||||
.byte "OK ", 0
|
||||
|
||||
initializing:
|
||||
.byte "INITIALIZING ",0
|
||||
|
||||
signon_message:
|
||||
.byte "NB65 UNNAMED TOOL V0.1",13,0
|
||||
|
||||
nb65_signature_not_found_message:
|
||||
.byte "NO NB65 API FOUND",13,"PRESS ANY KEY TO RESET", 0
|
||||
|
||||
nb65_signature:
|
||||
.byte $4E,$42,$36,$35 ; "NB65" - API signature
|
||||
.byte ' ',0 ; so we can use this as a string
|
352
client/carts/netboot.s
Normal file
352
client/carts/netboot.s
Normal file
@ -0,0 +1,352 @@
|
||||
; #############
|
||||
;
|
||||
; 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'.
|
||||
;
|
||||
; jonno@jamtronix.com - January 2009
|
||||
;
|
||||
|
||||
|
||||
.include "../inc/common.i"
|
||||
.include "../inc/commonprint.i"
|
||||
.include "../inc/c64keycodes.i"
|
||||
.include "../inc/menu.i"
|
||||
|
||||
.import ip65_init
|
||||
.import dhcp_init
|
||||
.import tftp_ip
|
||||
.importzp tftp_filename
|
||||
.import tftp_load_address
|
||||
.import tftp_download
|
||||
|
||||
.import cls
|
||||
.import beep
|
||||
.import exit_to_basic
|
||||
.import timer_vbl_handler
|
||||
.import get_key_ip65
|
||||
.import cfg_ip
|
||||
.import cfg_netmask
|
||||
.import cfg_gateway
|
||||
.import cfg_dns
|
||||
.import cfg_tftp_server
|
||||
.import cfg_get_configuration_ptr
|
||||
|
||||
|
||||
.import copymem
|
||||
.importzp copy_src
|
||||
.importzp copy_dest
|
||||
.import get_filtered_input
|
||||
.import __DATA_LOAD__
|
||||
.import __DATA_RUN__
|
||||
.import __DATA_SIZE__
|
||||
.import __SELF_MODIFIED_CODE_LOAD__
|
||||
.import __SELF_MODIFIED_CODE_RUN__
|
||||
.import __SELF_MODIFIED_CODE_SIZE__
|
||||
|
||||
|
||||
directory_buffer = $6020
|
||||
.bss
|
||||
tmp_load_address: .res 2
|
||||
|
||||
.data
|
||||
exit_cart:
|
||||
|
||||
lda #$02
|
||||
sta $de00 ;turns off RR cartridge by modifying GROUND and EXROM
|
||||
call_downloaded_prg:
|
||||
jsr $0000 ;overwritten when we load a file
|
||||
jmp init
|
||||
|
||||
get_value_of_axy: ;some more self-modifying code
|
||||
lda $ffff,y
|
||||
rts
|
||||
|
||||
|
||||
.segment "CARTRIDGE_HEADER"
|
||||
.word init ;cold start vector
|
||||
.word $FE47 ;warm start vector
|
||||
.byte $C3,$C2,$CD,$38,$30 ; "CBM80"
|
||||
.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
|
||||
|
||||
|
||||
;we need to set up BASIC as well
|
||||
jsr $e453 ;set BASIC vectors
|
||||
jsr $e3bf ;initialize zero page
|
||||
|
||||
|
||||
;set some funky colours
|
||||
LDA #$05 ;green
|
||||
STA $D020 ;border
|
||||
LDA #$00 ;black
|
||||
STA $D021 ;background
|
||||
|
||||
lda #$05 ;petscii for white text
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
ldax #netboot_msg
|
||||
jsr print
|
||||
ldax #init_msg+1
|
||||
jsr print
|
||||
|
||||
|
||||
jsr ip65_init
|
||||
bcs @init_failed
|
||||
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 cartridge default values)
|
||||
bcc init_ok
|
||||
@init_failed:
|
||||
print_failed
|
||||
jsr print_errorcode
|
||||
jsr wait_for_keypress
|
||||
jmp exit_to_basic
|
||||
|
||||
|
||||
init_ok:
|
||||
ldx #$03
|
||||
:
|
||||
lda cfg_tftp_server,x
|
||||
sta tftp_ip,x
|
||||
dex
|
||||
bpl :-
|
||||
|
||||
jsr print_cr
|
||||
jsr print_ip_config
|
||||
tftp_boot:
|
||||
|
||||
ldax #tftp_dir_filemask
|
||||
jsr get_tftp_directory_listing
|
||||
bcs return_to_main
|
||||
|
||||
@boot_filename_set:
|
||||
;AX now points to filename
|
||||
jsr download
|
||||
bcc file_downloaded_ok
|
||||
tftp_boot_failed:
|
||||
jsr wait_for_keypress
|
||||
return_to_main:
|
||||
jmp tftp_boot
|
||||
|
||||
file_downloaded_ok:
|
||||
ldax tftp_load_address
|
||||
|
||||
boot_into_file:
|
||||
stax tmp_load_address ;use the param buffer as a temp holding place for the load address
|
||||
;get ready to bank out
|
||||
|
||||
jsr $ffe7 ; make sure all files have been closed.
|
||||
|
||||
;check whether the file we just downloaded was a BASIC prg
|
||||
lda tmp_load_address
|
||||
cmp #01
|
||||
bne @not_a_basic_file
|
||||
|
||||
lda tmp_load_address+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 tmp_load_address
|
||||
exit_cart_via_ax:
|
||||
sta call_downloaded_prg+1
|
||||
stx call_downloaded_prg+2
|
||||
jmp exit_cart
|
||||
|
||||
get_tftp_directory_listing:
|
||||
stax tftp_filename
|
||||
|
||||
ldax #directory_buffer
|
||||
stax tftp_load_address
|
||||
|
||||
ldax #getting_dir_listing_msg
|
||||
jsr print
|
||||
|
||||
jsr tftp_download
|
||||
|
||||
bcs @dir_failed
|
||||
|
||||
lda directory_buffer ;get the first byte that was downloaded
|
||||
bne :+
|
||||
jmp @no_files_on_server
|
||||
:
|
||||
|
||||
;switch to lower case charset
|
||||
lda #23
|
||||
sta $d018
|
||||
|
||||
@loop_till_filename_entered:
|
||||
ldax #directory_buffer
|
||||
jsr select_option_from_menu
|
||||
bcs @loop_till_filename_entered
|
||||
@tftp_filename_set:
|
||||
stax copy_dest
|
||||
stax get_value_of_axy+1
|
||||
ldy #0
|
||||
jsr get_value_of_axy ;A now == first char in string we just downloaded
|
||||
cmp #'$'
|
||||
bne @not_directory_name
|
||||
;it's a directory name, so we need to append the file mask to end of it
|
||||
;this will fail if the file path is more than 255 characters long
|
||||
@look_for_trailing_zero:
|
||||
iny
|
||||
inc copy_dest
|
||||
bne :+
|
||||
inc copy_dest+1
|
||||
:
|
||||
jsr get_value_of_axy ;A now == next char in string we just downloaded
|
||||
bne @look_for_trailing_zero
|
||||
|
||||
; got trailing zero
|
||||
ldax #tftp_dir_filemask+1 ;skip the leading '$'
|
||||
stax copy_src
|
||||
ldax #$07
|
||||
jsr copymem
|
||||
ldax get_value_of_axy+1
|
||||
jmp get_tftp_directory_listing
|
||||
|
||||
@not_directory_name:
|
||||
ldax get_value_of_axy+1
|
||||
clc
|
||||
rts
|
||||
|
||||
|
||||
@dir_failed:
|
||||
ldax #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
|
||||
jsr print
|
||||
|
||||
jmp tftp_boot_failed
|
||||
|
||||
|
||||
|
||||
bad_boot:
|
||||
jsr wait_for_keypress
|
||||
jmp $fe66 ;do a wam start
|
||||
|
||||
download: ;AX should point at filename to download
|
||||
stax tftp_filename
|
||||
|
||||
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_filename
|
||||
jsr print
|
||||
jsr print_cr
|
||||
|
||||
jsr 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 $ffe4
|
||||
beq @loop
|
||||
rts
|
||||
|
||||
|
||||
.rodata
|
||||
|
||||
netboot_msg:
|
||||
.byte 13,"NETBOOT - V"
|
||||
.include "../inc/version.i"
|
||||
.byte 13,0
|
||||
downloading_msg: .byte "DOWN"
|
||||
loading_msg: .asciiz "LOADING "
|
||||
|
||||
getting_dir_listing_msg: .byte "FETCHING DIRECTORY",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 "DOWN"
|
||||
load_ok_msg:
|
||||
.byte "LOAD OK", 13, 0
|
||||
|
||||
current:
|
||||
.byte "CURRENT ",0
|
||||
|
||||
new:
|
||||
.byte"NEW ",0
|
||||
|
||||
tftp_dir_filemask:
|
||||
.asciiz "$/*.prg"
|
||||
|
||||
tftp_file:
|
||||
.asciiz "BOOTC64.PRG"
|
||||
|
||||
no_files:
|
||||
.byte "NO FILES",13,0
|
105
client/carts/set_ip_config.rb
Normal file
105
client/carts/set_ip_config.rb
Normal file
@ -0,0 +1,105 @@
|
||||
#cartridge offsets:
|
||||
# $18=MAC address (6 bytes)
|
||||
# $1E=IP address (4 bytes)
|
||||
# $22=netmask (4 bytes)
|
||||
# $26=gateway (4 bytes)
|
||||
# $2A=DNS (4 bytes)
|
||||
# $2E=TFTP server (4 bytes)
|
||||
|
||||
|
||||
@cartridge_offsets={
|
||||
#symobol => offset, length
|
||||
:mac=>[0x18,6],
|
||||
:ip=>[0x1e,4],
|
||||
:netmask=>[0x22,4],
|
||||
:gateway=>[0x26,4],
|
||||
:dns=>[0x2a,4],
|
||||
:tftp=>[0x2e,4],
|
||||
}
|
||||
|
||||
@progname=File.basename($0)
|
||||
def show_options
|
||||
puts "valid options are: #{@cartridge_offsets.keys.join(", ")}"
|
||||
puts "mac auto will automagically generate a pseudorandom MAC"
|
||||
end
|
||||
def usage
|
||||
puts "#{@progname} <image> <option> <value> [<option> <value> ..]"
|
||||
puts "multiple options may be set"
|
||||
show_options
|
||||
true
|
||||
end
|
||||
|
||||
number_of_options=ARGV.length
|
||||
usage && exit unless number_of_options>=3
|
||||
usage && exit unless (number_of_options%2) ==1 #must be an odd number of options
|
||||
filename=ARGV[0]
|
||||
if !(FileTest.file?(filename)) then
|
||||
puts "file '#{filename}' not found"
|
||||
exit
|
||||
end
|
||||
|
||||
|
||||
filebytes=File.open(filename,"rb").read
|
||||
|
||||
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]
|
||||
# puts "#{option} : #{value}"
|
||||
offsets=@cartridge_offsets[option.to_sym]
|
||||
if offsets.nil? then
|
||||
puts "invalid option #{option}"
|
||||
show_options
|
||||
exit
|
||||
end
|
||||
option_offset=start_of_nb65_cart_image+offsets[0]-7
|
||||
option_length=offsets[1]
|
||||
|
||||
if option_length==6 then
|
||||
if value.downcase=="auto" then
|
||||
require 'digest/md5'
|
||||
digest = Digest::MD5.digest(Time.now.to_s)
|
||||
mac=[0x00,0x80,0x10,digest[0],digest[1],Kernel.rand(255)]
|
||||
else
|
||||
split_values=value.split(":")
|
||||
if (split_values.length!=6) || (split_values[5].nil?) then
|
||||
puts "'#{value}' is not a valid MAC address. (e.g. 12:34:56:78:ab:cd)"
|
||||
exit
|
||||
end
|
||||
mac=[]
|
||||
6.times do |j|
|
||||
mac[j]=split_values[j].hex
|
||||
# puts "#{split_values[j]}->#{"%02X" % mac[j]}"
|
||||
end
|
||||
end
|
||||
packed_option=mac.pack("cccccc")
|
||||
else #it must be an IP
|
||||
split_values=value.split(".")
|
||||
if (split_values.length!=4) || (split_values[3].nil?) then
|
||||
puts "'#{value}' is not a valid IP format. (e.g. 192.168.1.64)"
|
||||
exit
|
||||
end
|
||||
ip=[]
|
||||
4.times do |j|
|
||||
ip[j]=split_values[j].to_i
|
||||
# puts "#{split_values[j]}->#{ip[j]}"
|
||||
if (ip[j]<0) || (ip[j]>255) then
|
||||
puts "'#{value}' is not a valid IP format. (e.g. 192.168.1.64)"
|
||||
exit
|
||||
end
|
||||
|
||||
end
|
||||
packed_option=ip.pack("cccc")
|
||||
end
|
||||
filebytes[option_offset,option_length]=packed_option
|
||||
end
|
||||
|
||||
filehandle=File.open(filename,"wb")
|
||||
filehandle<<filebytes
|
||||
filehandle.close
|
313
client/carts/utherboot.s
Normal file
313
client/carts/utherboot.s
Normal file
@ -0,0 +1,313 @@
|
||||
;#############
|
||||
;
|
||||
; 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/a2keycodes.i"
|
||||
.include "../inc/menu.i"
|
||||
.import cls
|
||||
.import get_key
|
||||
.import beep
|
||||
|
||||
.importzp tftp_filename
|
||||
.import tftp_load_address
|
||||
.import tftp_ip
|
||||
.import tftp_download
|
||||
|
||||
.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__
|
||||
.import __IP65_DEFAULTS_LOAD__
|
||||
.import __IP65_DEFAULTS_RUN__
|
||||
.import __IP65_DEFAULTS_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
|
||||
|
||||
|
||||
;@fixme: jmp @fixme
|
||||
|
||||
;relocate the DATA segment
|
||||
ldax #__DATA_LOAD__
|
||||
stax copy_src
|
||||
ldax #__DATA_RUN__
|
||||
stax copy_dest
|
||||
ldax #__DATA_SIZE__
|
||||
jsr startup_copymem
|
||||
|
||||
;relocate the IP65_DEFAULTS segment
|
||||
ldax #__IP65_DEFAULTS_LOAD__
|
||||
stax copy_src
|
||||
ldax #__IP65_DEFAULTS_RUN__
|
||||
stax copy_dest
|
||||
ldax #__IP65_DEFAULTS_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_download
|
||||
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 V"
|
||||
.include "nb65_version.i"
|
||||
.byte 0
|
Loading…
Reference in New Issue
Block a user