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

This commit is contained in:
jonnosan 2009-06-21 09:30:11 +00:00
parent 6ab04aaac5
commit 0950fd8b89
18 changed files with 1027 additions and 26 deletions

View File

@ -1,5 +1,5 @@
0.9.8
- created stubs for TCP
- created stubs for TCP functions
- split nb65 cart images into 8k (UDP only - green) & 16k (UDP+TCP - purple) images
0.9.7
- tweak directory listing code in server so $ works by itself

48
client/cfg/a2rom.cfg Normal file
View File

@ -0,0 +1,48 @@
MEMORY {
ZP: start = $00, size = $08, type = rw, define = yes;
IP65ZP: start = $0f, size = $10, type = rw, define = yes;
C700_BANK: start = $c700, size = $100, file = %O;
C800_BANK_0: start = $c800, size = $800, file = %O, fill=yes, fillval=$F0;
C800_BANK_1: start = $c800, size = $800, file = %O, fill=yes, fillval=$F1;
C800_BANK_2: start = $c800, size = $800, file = %O, fill=yes, fillval=$F2;
C800_BANK_3: start = $c800, size = $800, file = %O, fill=yes, fillval=$F3;
C800_BANK_4: start = $c800, size = $800, file = %O, fill=yes, fillval=$F4;
C800_BANK_5: start = $c800, size = $800, file = %O, fill=yes, fillval=$F5;
C800_BANK_6: start = $c800, size = $800, file = %O, fill=yes, fillval=$F6;
C800_BANK_7: start = $c800, size = $800, file = %O, fill=yes, fillval=$F7;
C800_BANK_8: start = $c800, size = $800, file = %O, fill=yes, fillval=$F8;
C800_BANK_9: start = $c800, size = $800, file = %O, fill=yes, fillval=$F9;
C800_BANK_A: start = $c800, size = $800, file = %O, fill=yes, fillval=$FA;
C800_BANK_B: start = $c800, size = $800, file = %O, fill=yes, fillval=$FB;
C800_BANK_C: start = $c800, size = $800, file = %O, fill=yes, fillval=$FC;
C800_BANK_D: start = $c800, size = $800, file = %O, fill=yes, fillval=$FD;
C800_BANK_E: start = $c800, size = $800, file = %O, fill=yes, fillval=$FE;
RAM: start = $800, size = $8000, file = %O;
}
SEGMENTS {
C700: load=C700_BANK, type=ro,define=yes;
CODE: load=C700_BANK, type=ro,define=yes;
C800_0: load=C800_BANK_0, type=ro,define=yes;
C800_1: load=C800_BANK_1, type=ro,define=yes;
C800_2: load=C800_BANK_2, type=ro,define=yes;
C800_3: load=C800_BANK_3, type=ro,define=yes;
C800_4: load=C800_BANK_4, type=ro,define=yes;
C800_5: load=C800_BANK_5, type=ro,define=yes;
C800_6: load=C800_BANK_6, type=ro,define=yes;
C800_7: load=C800_BANK_7, type=ro,define=yes;
C800_8: load=C800_BANK_8, type=ro,define=yes;
C800_9: load=C800_BANK_9, type=ro,define=yes;
C800_A: load=C800_BANK_A, type=ro,define=yes;
C800_B: load=C800_BANK_B, type=ro,define=yes;
C800_C: load=C800_BANK_C, type=ro,define=yes;
C800_D: load=C800_BANK_D, type=ro,define=yes;
C800_E: load=C800_BANK_E, type=ro,define=yes;
DATA: load = RAM, run=RAM, type = rw , define = yes;
BSS: load=RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
IP65ZP: load = IP65ZP, type = zp;
}

View File

@ -0,0 +1,20 @@
# CA65 config for a 16KB cart
MEMORY {
IP65ZP: start = $A3, size = $0E, type = rw, define = yes;
HEADER: start = $8000, size = $18, file = %O;
DEFAULTS: start = $8018, size = $1E, file = %O;
ROM: start = $8036, size = $3FC8, define = yes, file = %O;
RAM: start = $C010, size = $0fE0, define = yes;
}
SEGMENTS {
CARTRIDGE_HEADER: load = HEADER, type = ro;
IP65_DEFAULTS: load = DEFAULTS, type = ro;
CODE: load = ROM, type = ro;
RODATA: load = ROM, run=ROM, type = ro;
DATA: load = ROM, run = RAM, type = rw, define = yes;
BSS: load = RAM, type = bss;
IP65ZP: load = IP65ZP, type = zp;
}

1
client/d64_test.bat Normal file
View File

@ -0,0 +1 @@
start c:\temp\WinVICE-2.1\x64.exe -cart8 nb65\nb65_std_cart.bin nb65\d64_upload.d64

View File

@ -0,0 +1,468 @@
;NB65 API example in DASM format (http://www.atari2600.org/DASM/)
processor 6502
include "../inc/nb65_constants.i"
;useful macros
mac ldax
lda [{1}]
ldx [{1}]+1
endm
mac ldaxi
lda #<[{1}]
ldx #>[{1}]
endm
mac stax
sta [{1}]
stx [{1}]+1
endm
mac cout
lda [{1}]
jsr print_a
endm
mac print_cr
cout #13
jsr print_a
endm
mac nb65call
ldy [{1}]
jsr NB65_DISPATCH_VECTOR
endm
mac print
ldaxi [{1}]
ldy #NB65_PRINT_ASCIIZ
jsr NB65_DISPATCH_VECTOR
endm
;some routines & zero page variables
print_a equ $ffd2
temp_ptr equ $FB ; scratch space in page zero
;######### KERNEL functions
CHKIN EQU $ffc6
CHKOUT EQU $ffc9
CHRIN EQU $ffcf
CHROUT EQU $ffd2
CLALL EQU $FFE7
CLOSE EQU $ffc3
OPEN EQU $ffc0
READST EQU $ffb7
SETNAM EQU $ffbd
SETLFS EQU $ffba
;start of code
;BASIC stub
org $801
dc.b $0b,$08,$d4,$07,$9e,$32,$30,$36,$31,$00,$00,$00
ldaxi #NB65_CART_SIGNATURE ;where signature should be in cartridge (if cart is banked in)
jsr look_for_signature
bcc found_nb65_signature
ldaxi #NB65_RAM_STUB_SIGNATURE ;where signature should be in a RAM stub
jsr look_for_signature
bcs nb65_signature_not_found
jsr NB65_RAM_STUB_ACTIVATE ;we need to turn on NB65 cartridge
jmp found_nb65_signature
nb65_signature_not_found
ldaxi #nb65_api_not_found_message
jsr print_ax
rts
found_nb65_signature
print #initializing
nb65call #NB65_INITIALIZE
bcc .init_ok
print_cr
print #failed
print_cr
jsr print_errorcode
jmp reset_after_keypress
.init_ok
;if we got here, we have found the NB65 API and initialised the IP stack
jsr CLALL
.send_1_image
lda #$93 ;cls
jsr print_a
print #signon_message
jsr reset_counters_to_first_sector
print #enter_filename
ldaxi #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
ldaxi #send_next_block
stax nb65_param_buffer+NB65_TFTP_POINTER
ldaxi #nb65_param_buffer
nb65call #NB65_TFTP_CALLBACK_UPLOAD
bcc .upload_ok
print_cr
print #failed
jmp print_nb65_errorcode
.upload_ok
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
ldaxi #$100
rts
.not_last_sector
inc sector_buffer_address+1
jsr read_sector
jsr move_to_next_sector
ldaxi #$200
rts
.past_last_track
ldaxi #$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
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
nb65call #NB65_PRINT_HEX
jmp .close
check_error_channel
ldx #$0F ; filenumber 15
jsr CHKIN ;(file 15 now used as input)
ldy #$00
.ecloop
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 .ecloop ; next byte
.eof
lda #0
sta error_buffer,y
ldx #$00 ; filenumber 0 = keyboard
jsr CHKIN ;(keyboard now input device again)
rts
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
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
reset_counters_to_first_sector
ldx #1
stx track
dex
stx sector
ldx #21
stx sectors_in_track
rts
;look for NB65 signature at location pointed at by AX
look_for_signature subroutine
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
print_ax subroutine
stax temp_ptr
ldy #0
.next_char
lda (temp_ptr),y
beq .done
jsr print_a
iny
jmp .next_char
.done
rts
get_key
jsr $ffe4
cmp #0
beq get_key
rts
reset_after_keypress
print #press_a_key_to_continue
jsr get_key
jmp $fce2 ;do a cold start
print_errorcode
print #error_code
nb65call #NB65_GET_LAST_ERROR
nb65call #NB65_PRINT_HEX
print_cr
rts
;constants
nb65_api_not_found_message dc.b "ERROR - NB65 API NOT FOUND.",13,0
nb65_signature dc.b $4E,$42,$36,$35 ; "NB65" - API signature
initializing dc.b "INITIALIZING ",13,0
error_code dc.b "ERROR CODE: $",0
press_a_key_to_continue dc.b "PRESS A KEY TO CONTINUE",13,0
failed dc.b "FAILED ", 0
ok dc.b "OK ", 0
;variables
nb65_param_buffer DS.B $20
current_byte DS.B 1
track DS.B 1
sector DS.B 1
sectors_in_track DS.B 1
error_buffer DS.B 128
command_buffer DS.B 128
sector_buffer DS.B 256
sector_buffer_address DS.B 2

View File

@ -2,7 +2,7 @@
;to use this file under CA65, then add " .define EQU =" to your code before this file is included.
NB65_API_VERSION_NUMBER EQU $01
NB65_API_VERSION_NUMBER EQU $02
NB65_CART_SIGNATURE EQU $8009
@ -28,10 +28,14 @@ NB65_GET_IP_CONFIG EQU $02 ;no inputs, outputs AX=pointer to IP conf
NB65_DEACTIVATE EQU $0F ;inputs: none, outputs: none (removes call to NB65_VBL_VECTOR on IRQ chain)
NB65_UDP_ADD_LISTENER EQU $10 ;inputs: AX points to a UDP listener parameter structure, outputs: none
NB65_GET_INPUT_PACKET_INFO EQU $11 ;inputs: AX points to a UDP packet parameter structure, outputs: UDP packet structure filled in
NB65_GET_INPUT_PACKET_INFO EQU $11 ;inputs: AX points to a UDP/TCP packet parameter structure, outputs: UDP/TCP packet structure filled in
NB65_SEND_UDP_PACKET EQU $12 ;inputs: AX points to a UDP packet parameter structure, outputs: none packet is sent
NB65_UDP_REMOVE_LISTENER EQU $13 ;inputs: AX contains UDP port number that listener will be removed from
NB65_TCP_CONNECT EQU $14 ;inputs: AX points to a TCP connect parameter structure, outputs: A = connection #
NB65_TCP_SEND_PACKET EQU $15 ;inputs: AX points to a TCP send parameter structure, outputs: none packet is sent
NB65_TCP_CLOSE_CONNECTION EQU $16 ;inputs: A = connection # to close, outputs: none
NB65_TFTP_SET_SERVER EQU $20 ;inputs: AX points to a TFTP server parameter structure, outputs: none
NB65_TFTP_DOWNLOAD EQU $22 ;inputs: AX points to a TFTP transfer parameter structure, outputs: TFTP param structure updated with
;NB65_TFTP_POINTER updated to reflect actual load address (if load address $0000 originally passed in)
@ -77,12 +81,25 @@ NB65_DNS_HOSTNAME_IP EQU $00 ;4 byte IP address (filled
NB65_UDP_LISTENER_PORT EQU $00 ;2 byte port number
NB65_UDP_LISTENER_CALLBACK EQU $02 ;2 byte address of routine to call when UDP packet arrives for specified port
;offsets in UDP packet parameter structure
;offsets in TCP connect parameter structure
NB65_TCP_REMOTE_IP EQU $00 ;4 byte IP address of remote host (0.0.0.0 means wait for inbound i.e. server mode)
NB65_TCP_PORT EQU $04 ;2 byte port number (to listen on, if ip address was 0.0.0.0, or connect to otherwise)
NB65_TCP_CALLBACK EQU $06 ;2 byte address of routine to be called whenever a new packet arrives
;offsets in TCP send parameter structure
NB65_TCP_CONNECTION_NUMBER EQU $00 ;1 byte connection number for previously set up connection
NB65_TCP_PAYLOAD_LENGTH EQU $01 ;2 byte length of payload of packet (after all ethernet,IP,UDP/TCP headers)
NB65_TCP_PAYLOAD_POINTER EQU $03 ;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)
NB65_LOCAL_PORT EQU $06 ;2 byte port number of local machine (src of outbound packets, dest of inbound packets)
NB65_PAYLOAD_LENGTH EQU $08 ;2 byte length of payload of packet (after all ethernet,IP,UDP headers)
NB65_PAYLOAD_LENGTH EQU $08 ;2 byte length of payload of packet (after all ethernet,IP,UDP/TCP headers)
; in a TCP connection, if the length is $FFFF, this actually means "end of connection"
NB65_PAYLOAD_POINTER EQU $0A ;2 byte pointer to payload of packet (after all headers)
NB65_CONNECTION_NUMBER EQU $0C ;1 byte "connection number" (valid for TCP connections only)
;error codes (as returned by NB65_GET_LAST_ERROR)
NB65_ERROR_PORT_IN_USE EQU $80

View File

@ -26,21 +26,27 @@ ETHOBJS= \
dns.o \
dottedquad.o \
output_buffer.o\
tftp.o \
tftp.o \
tcp.o \
function_dispatcher.o \
all: ip65.lib ip65_tcp.lib
ip65.lib: tcp_stub.o $(ETHOBJS)
ip65.lib: $(ETHOBJS)
$(AS) $(AFLAGS) function_dispatcher.s
$(AS) $(AFLAGS) ip.s
ar65 a ip65.lib $^
ip65_tcp.lib: tcp.o $(ETHOBJS)
$(AS) $(AFLAGS) function_dispatcher.s -DTCP
$(AS) $(AFLAGS) ip.s -DTCP
ar65 a ip65_tcp.lib $^
clean:
rm -f *.o
rm -f ip65.lib
rm -f ip65_tcp.lib
distclean: clean

View File

@ -53,9 +53,10 @@
.import udp_init
.import udp_process
.ifdef TCP
.import tcp_init
.import tcp_process
.endif
.importzp copy_src
@ -120,7 +121,9 @@ ip_init:
sta bad_addr + 1
jsr icmp_init
jsr tcp_init
.ifdef TCP
jsr tcp_init
.endif
jsr udp_init
rts
@ -146,10 +149,12 @@ ip_process:
lda ip_inp + ip_proto
cmp #ip_proto_icmp
bne :+
jmp icmp_process ; jump to icmp handler
jmp icmp_process ; jump to icmp handler
.ifdef TCP
: cmp #ip_proto_tcp
bne :+
jmp tcp_process ; jump to tcp handler
jmp tcp_process ; jump to tcp handler
.endif
: cmp #ip_proto_udp
bne :+
jmp udp_process ; jump to udp handler

View File

@ -18,7 +18,11 @@ tcp_add_listener:
tcp_remove_listener:
tcp_send:
tcp_process:
sec
inc $d020
lda #NB65_ERROR_FUNCTION_NOT_SUPPORTED
sta ip65_error
sec
tcp_init:
rts
rts
.res 2000 ;fixme

View File

@ -31,7 +31,7 @@ nb65_std_cart.o: nb65_c64.s $(INCFILES)
$(AS) -DBANKSWITCH_SUPPORT=1 $(AFLAGS) -o $@ $<
nb65_tcp_cart.o: nb65_c64.s $(INCFILES)
$(AS) -DBANKSWITCH_SUPPORT=1 -DTCP $(AFLAGS) -o $@ $<
$(AS) -DBANKSWITCH_SUPPORT=3 $(AFLAGS) -o $@ $<
nb65_rrnet.o: nb65_c64.s $(INCFILES)
$(AS) -DBANKSWITCH_SUPPORT=2 $(AFLAGS) -o $@ $<
@ -53,8 +53,8 @@ nb65_std_cart.bin: nb65_std_cart.o $(IP65LIB) $(C64NB65LIB) $(INCFILES) ../cfg/r
$(LD) -m nb65_std_cart.map -vm -C ../cfg/rrbin.cfg -o $@ $< $(IP65LIB) $(C64NB65LIB)
ruby fix_cart.rb $@ 8192
nb65_tcp_cart.bin: nb65_tcp_cart.o $(IP65TCPLIB) $(C64NB65LIB) $(INCFILES) ../cfg/rrbin.cfg
$(LD) -m nb65_tcp_cart.map -vm -C ../cfg/rrbin.cfg -o $@ $< $(IP65TCPLIB) $(C64NB65LIB)
nb65_tcp_cart.bin: nb65_tcp_cart.o $(IP65TCPLIB) $(C64NB65LIB) $(INCFILES) ../cfg/c64_16kcart.cfg
$(LD) -m nb65_tcp_cart.map -vm -C ../cfg/c64_16kcart.cfg -o $@ $< $(IP65TCPLIB) $(C64NB65LIB)
ruby fix_cart.rb $@ 16384
nb65_rrnet.bin: nb65_rrnet.o $(IP65LIB) $(C64NB65LIB) $(INCFILES) ../cfg/rrbin.cfg

View File

@ -11,9 +11,9 @@
;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)
;$01 = 8KB image with standard bankswitching (via HIRAM/LORAM)
;$02 = 8KB image with advanced bankswitching (via custom registers, e.g. $de00 on the Retro Replay cart)
;$03 = 16KB image with standard bankswitching (via HIRAM/LORAM) - BASIC is NOT avialable
.ifndef BANKSWITCH_SUPPORT
.error "must define BANKSWITCH_SUPPORT"
@ -141,7 +141,7 @@ init:
;set some funky colours
.ifdef TCP
.if (BANKSWITCH_SUPPORT=$03)
LDA #$04 ;purple
.else
LDA #$05 ;green
@ -150,7 +150,7 @@ init:
STA $D020 ;border
LDA #$00 ;black
STA $D021 ;background
.ifdef TCP
.if (BANKSWITCH_SUPPORT=$03)
lda #$9c ;petscii for purple text
.else
lda #$1E ;petscii for green text
@ -213,7 +213,7 @@ main_menu:
bne @not_tftp
jmp @tftp_boot
@not_tftp:
.ifndef TCP
.if !(BANKSWITCH_SUPPORT=$03)
cmp #KEYCODE_F3
beq @exit_to_basic
.endif
@ -489,7 +489,7 @@ cmp #KEYCODE_F7
cmp #$08
bne @not_a_basic_file
.ifdef TCP
.if (BANKSWITCH_SUPPORT=$03)
ldax #cant_boot_basic
jsr print
jsr wait_for_keypress
@ -587,7 +587,7 @@ netboot65_msg:
main_menu_msg:
.byte 13," MAIN MENU",13,13
.byte "F1: TFTP BOOT"
.ifndef TCP
.if !(BANKSWITCH_SUPPORT=$03)
.byte " F3: BASIC"
.endif
.byte 13
@ -639,7 +639,7 @@ press_a_key_to_continue:
resolving:
.byte "RESOLVING ",0
.ifdef TCP
.if (BANKSWITCH_SUPPORT=$03)
cant_boot_basic: .byte "BASIC FILE EXECUTION NOT SUPPORTED",13,0
.endif

1
client/tcp_test.bat Normal file
View File

@ -0,0 +1 @@
start c:\temp\WinVICE-2.1\x64.exe -cart16 nb65\nb65_tcp_cart.bin test\test_cart_api.prg

37
client/uthernet/Makefile Normal file
View File

@ -0,0 +1,37 @@
AS=ca65
LD=ld65
CFLAGS=-Oirs -t $(TARGET)
AFLAGS=
INCFILES=\
../inc/common.i\
../inc/commonprint.i\
../inc/simpleprint.i\
../inc/net.i\
../inc/menu.i\
../inc/nb65_constants.i\
nb65_version.i\
IP65LIB=../ip65/ip65.lib
APPLE2PROGLIB=../drivers/apple2prog.lib
%.o: %.s $(INCFILES) $(APPLE2PROGLIB)
$(AS) $(AFLAGS) $<
all: applewin.exe
c700_rom.bin: c700_rom.o ../cfg/a2rom.cfg
$(LD) -C ../cfg/a2rom.cfg -o $@ c700_rom.o $(APPLE2PROGLIB)
bankswitch_eeprom.bin: bankswitch_eeprom.o ../cfg/a2rom.cfg
$(LD) -C ../cfg/a2rom.cfg -o $@ bankswitch_eeprom.o $(APPLE2PROGLIB)
applewin.exe: c700_rom.bin bankswitch_eeprom.bin patch_applewin.rb
ruby patch_applewin.rb
clean:
rm -f *.o *.bin *.map *.prg *.pg2 *.dsk *.d64
distclean: clean
rm -f *~

View File

@ -0,0 +1,48 @@
.include "../inc/common.i"
.include "../inc/a2keycodes.i"
.import print_a
.import print_cr
pptr=$04 ;temp pointer for printing from
.segment "C700"
;Autostart 'signature' bytes - make this rom look like a Disk ][ controller card
.byte $c9,$20,$c9,$00,$c9,$03,$c9,$3c
ldax #hello_world
jsr print
rts
sta $cfff ;turn of all other expansion ROMs
sta $c0f4 ;set bank
ldax #$c800
jsr print
rts
print:
sta pptr
stx pptr + 1
@print_loop:
ldy #0
lda (pptr),y
beq @done_print
jsr print_a
inc pptr
bne @print_loop
inc pptr+1
bne @print_loop ;if we ever get to $ffff, we've probably gone far enough ;-)
@done_print:
rts
hello_world:
.byte "hello from autostart firmware land!",13,0

View File

@ -0,0 +1,32 @@
unpatched_applewin_filename='unpatched_applewin.exe'
patched_applewin_filename='applewin.exe'
c700_rom_filename='c700_rom.bin'
bankswitch_eeprom_filename="bankswitch_eeprom.bin"
[unpatched_applewin_filename,c700_rom_filename,bankswitch_eeprom_filename].each do |filename|
if !(FileTest.file?(filename)) then
puts "file '#{filename}' not found"
exit
end
end
filebytes=File.open(unpatched_applewin_filename,"rb").read
c700_sig=(07).chr*256
bankswitch_eeprom_sig=(0xF0).chr*256
c700_rom_offset=filebytes.index(c700_sig)
raise "C700 ROM signature not found in #{unpatched_applewin_filename}" if c700_rom_offset.nil?
bankswitch_eeprom_offset=filebytes.index(bankswitch_eeprom_sig)
raise "bankswitch EEPROM signature not found in #{unpatched_applewin_filename}" if bankswitch_eeprom_offset.nil?
c700_rom=File.open(c700_rom_filename,"rb").read
bankswitch_eeprom=File.open(bankswitch_eeprom_filename,"rb").read
filebytes[c700_rom_offset,c700_rom.length]=c700_rom
filebytes[bankswitch_eeprom_offset,bankswitch_eeprom.length]=bankswitch_eeprom
filehandle=File.open(patched_applewin_filename,"wb")
filehandle<<filebytes
filehandle.close

313
client/uthernet/utherboot.s Normal file
View 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

1
dist/version_number.txt vendored Normal file
View File

@ -0,0 +1 @@
0.9.8

Binary file not shown.