diff --git a/CHANGES.txt b/CHANGES.txt index 226c782..51256ec 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -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 diff --git a/client/cfg/a2rom.cfg b/client/cfg/a2rom.cfg new file mode 100644 index 0000000..9775033 --- /dev/null +++ b/client/cfg/a2rom.cfg @@ -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; +} + + diff --git a/client/cfg/c64_16kcart.cfg b/client/cfg/c64_16kcart.cfg new file mode 100644 index 0000000..1da3c9c --- /dev/null +++ b/client/cfg/c64_16kcart.cfg @@ -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; +} diff --git a/client/d64_test.bat b/client/d64_test.bat new file mode 100644 index 0000000..68aee37 --- /dev/null +++ b/client/d64_test.bat @@ -0,0 +1 @@ +start c:\temp\WinVICE-2.1\x64.exe -cart8 nb65\nb65_std_cart.bin nb65\d64_upload.d64 \ No newline at end of file diff --git a/client/examples/dasm_d64_upload.asm b/client/examples/dasm_d64_upload.asm new file mode 100644 index 0000000..c1b99ed --- /dev/null +++ b/client/examples/dasm_d64_upload.asm @@ -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 + jsr SETNAM + lda #$02 + ldx #$08 + ldy #$02 + jsr SETLFS + jsr OPEN + bcs .error + ldx #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 + + diff --git a/client/inc/nb65_constants.i b/client/inc/nb65_constants.i index 0de4378..c3ebaaa 100644 --- a/client/inc/nb65_constants.i +++ b/client/inc/nb65_constants.i @@ -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 diff --git a/client/ip65/Makefile b/client/ip65/Makefile index 78827f1..2356328 100644 --- a/client/ip65/Makefile +++ b/client/ip65/Makefile @@ -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 diff --git a/client/ip65/ip.s b/client/ip65/ip.s index b4e3018..3e39ad4 100644 --- a/client/ip65/ip.s +++ b/client/ip65/ip.s @@ -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 diff --git a/client/ip65/tcp.s b/client/ip65/tcp.s index 6550ed5..c47ea59 100644 --- a/client/ip65/tcp.s +++ b/client/ip65/tcp.s @@ -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 \ No newline at end of file diff --git a/client/nb65/Makefile b/client/nb65/Makefile index 5999181..8422e36 100644 --- a/client/nb65/Makefile +++ b/client/nb65/Makefile @@ -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 diff --git a/client/nb65/nb65_c64.s b/client/nb65/nb65_c64.s index 54696c8..035b482 100644 --- a/client/nb65/nb65_c64.s +++ b/client/nb65/nb65_c64.s @@ -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 diff --git a/client/tcp_test.bat b/client/tcp_test.bat new file mode 100644 index 0000000..914ba1c --- /dev/null +++ b/client/tcp_test.bat @@ -0,0 +1 @@ +start c:\temp\WinVICE-2.1\x64.exe -cart16 nb65\nb65_tcp_cart.bin test\test_cart_api.prg \ No newline at end of file diff --git a/client/uthernet/Makefile b/client/uthernet/Makefile new file mode 100644 index 0000000..1aef290 --- /dev/null +++ b/client/uthernet/Makefile @@ -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 *~ diff --git a/client/uthernet/c700_rom.s b/client/uthernet/c700_rom.s new file mode 100644 index 0000000..821a94a --- /dev/null +++ b/client/uthernet/c700_rom.s @@ -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 + + diff --git a/client/uthernet/patch_applewin.rb b/client/uthernet/patch_applewin.rb new file mode 100644 index 0000000..40930ec --- /dev/null +++ b/client/uthernet/patch_applewin.rb @@ -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<