diff --git a/client/carts/Makefile b/client/carts/Makefile new file mode 100644 index 0000000..7f423ef --- /dev/null +++ b/client/carts/Makefile @@ -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 *~ diff --git a/client/carts/bootmenu.s b/client/carts/bootmenu.s new file mode 100644 index 0000000..a54c934 --- /dev/null +++ b/client/carts/bootmenu.s @@ -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 + + diff --git a/client/carts/crt8040.src b/client/carts/crt8040.src new file mode 100644 index 0000000..f7f31bb --- /dev/null +++ b/client/carts/crt8040.src @@ -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 + +;-------------------------------------- + diff --git a/client/carts/d64_upload.s b/client/carts/d64_upload.s new file mode 100644 index 0000000..80d996b --- /dev/null +++ b/client/carts/d64_upload.s @@ -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 + 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 + 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 '#' \ No newline at end of file diff --git a/client/carts/dupe_cart.rb b/client/carts/dupe_cart.rb new file mode 100644 index 0000000..53359e0 --- /dev/null +++ b/client/carts/dupe_cart.rb @@ -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< 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}