; (c)opyright 2014-2017 ; Sven Oliver ("SvOlli") Moll ; and Individual Computers .define USE_CRC16 0 .define USE_32K_BIN 0 .include "../svnversion.inc" DEVADR := $BA IOBVEC := $AE DISCUR := $CC TEMP_A_16 := $FB ; $FC CURRENT_LINE := $D1 CURRENT_COLUMN := $D3 CIA_A_TIMER_A := $DC04 RRCTRL := $DE00 RREXTD := $DE01 RRNET_ENABLE := $DE80 RRNET_DISABLE := $DE88 RRNET_BOOTDEF := $9FCF RRNET_CONF_ROM := $9FFC RRNET_CONF_IO := $DE0C ERRMSG := $A43A VALFNC := $B7B5 FL2INT := $BC9B AXOUT := $BDCD READST := $FFB7 SETLFS := $FFBA SETNAM := $FFBD OPEN := $FFC0 CLOSE := $FFC3 CHKIN := $FFC6 CHKOUT := $FFC9 CLRCHN := $FFCC BASIN := $FFCF BSOUT := $FFD2 GETIN := $FFE4 PLOT := $FFF0 MAC_CHK_COPY := $033C IP_ON_SCREEN := $0506 MAC_ON_SCREEN := $0556 .segment "RODATA" scratch: .byte "s:" filename: .byte "rrnetmk3." extension: .byte " " filename_end: .byte $0d,$00 ext_rom: .byte "rom" .if USE_32K_BIN ext_bin: .byte "bin" .endif ext_crt: .byte "crt" icomp_mac: .byte $28,$cd,$4c,$ff CRT_START: ;1234567890123456 .byte "c64 cartridge " ; CRT file signature .byte $00,$00,$00,$40 ; header length .byte $01,$00 ; version .byte $00,36 ; type: retro replay .byte $00 ; exrom .byte $00 ; game .byte $00,$00,$00,$00,$00,$00 ; reserved ;12345678901234567890123456789012 .byte "retro replay net firmware " ; title of file CHIP_START: .byte "chip" ; CHIP bank signature .byte $00,$00,$20,$10 ; size of header + data .byte $00,$00 ; rom CHIP_NUM = * + 1 .byte $00,$00 ; bank# .byte $80,$00 ; bank load address .byte $20,$00 ; bank size FIRMWARE_START: .incbin "../firmware/firmware.bin" FIRMWARE_END: FW_BOOTDEF := FIRMWARE_START + $1FCF FW_IP_ADDR := FIRMWARE_START + $1FF4 FW_MAC_ADDR := FIRMWARE_START + $1FF8 FW_CHKSUM0 := FIRMWARE_START + $1FFE FW_CHKSUM1 := FIRMWARE_START + $1FFF spinner: .byte $40,$4d,$5d,$4e FILE_TYPE: .byte 0 .segment "CODE" jmp main ; crc-16 calculation taken from ; http://www.6502.org/source/integers/crc-more.html .if USE_CRC16 calc_crc16: ldy #$ff sty TEMP_A_16+0 sty TEMP_A_16+1 lda #FIRMWARE_START sta IOBVEC+1 ldy #$00 : lda (IOBVEC),y eor TEMP_A_16+1 ; A contained the data sta TEMP_A_16+1 ; XOR it into high byte lsr ; right shift A 4 bits lsr ; to make top of x^12 term lsr ; ($1...) lsr tax ; save it asl ; then make top of x^5 term eor TEMP_A_16+0 ; and XOR that with low byte sta TEMP_A_16+0 ; and save txa ; restore partial term eor TEMP_A_16+1 ; and update high byte sta TEMP_A_16+1 ; and save asl ; left shift three asl ; the rest of the terms asl ; have feedback from x^12 tax ; save bottom of x^12 asl ; left shift two more asl ; watch the carry flag eor TEMP_A_16+1 ; bottom of x^5 ($..2.) sta TEMP_A_16+1 ; save high byte txa ; fetch temp value rol ; bottom of x^12, middle of x^5! eor TEMP_A_16+0 ; finally update low byte ldx TEMP_A_16+1 ; then swap high and low bytes sta TEMP_A_16+1 stx TEMP_A_16+0 iny bne :- inc IOBVEC+1 lda IOBVEC+1 cmp #>FIRMWARE_END bne :- rts .endif advance_temp_a_1: inc IOBVEC+0 bne :+ inc IOBVEC+1 : rts print: pla sta IOBVEC+0 pla sta IOBVEC+1 @mainloop: ldy #$00 jsr advance_temp_a_1 lda (IOBVEC),y bne @evaluate lda IOBVEC+1 pha lda IOBVEC+0 pha rts @evaluate: cmp #$01 ; CTRL-A number char: print number of chars bne @norle jsr advance_temp_a_1 lda (IOBVEC),y tax jsr advance_temp_a_1 lda (IOBVEC),y @loopout: jsr BSOUT dex bne @loopout beq @mainloop @norle: cmp #$02 ; CTRL-B line column: position cursor bne @nopos jsr advance_temp_a_1 lda (IOBVEC),y tax jsr advance_temp_a_1 lda (IOBVEC),y tay clc jsr PLOT jmp @mainloop @nopos: jsr BSOUT jmp @mainloop ; always true send_command: sta IOBVEC+0 stx IOBVEC+1 lda #$02 ldx DEVADR cpx #$08 bcs :+ rts : ldy #$0F jsr SETLFS lda #$00 jsr SETNAM jsr OPEN bcc :+ jmp ERRMSG+1 ; skip the TAX : ldx #$02 jsr CHKOUT ldy #$00 @loop: jsr READST bne @done lda (IOBVEC),y beq @done jsr BSOUT iny bne @loop @done: lda #$02 jsr CLOSE jmp CLRCHN check_mac: ldx #$04 : lda icomp_mac-1,x cmp FW_MAC_ADDR-1,x bne :+ dex bne :- : rts write_crt: lda #CRT_START bne write_bank write_chip: lda #CHIP_START bne write_bank write_raw: lda #FIRMWARE_START write_bank: sty CHIP_NUM sta IOBVEC+0 stx IOBVEC+1 @loop: ldy #$00 jsr READST beq @ok ; pull return address from stack pla pla jmp writeerror @ok: lda (IOBVEC),y jsr BSOUT inc IOBVEC+0 bne :+ inc IOBVEC+1 lda IOBVEC+1 and #$03 tay lda spinner,y ldy CURRENT_COLUMN sta (CURRENT_LINE),y : lda IOBVEC+0 cmp #FIRMWARE_END bne @loop ldy CHIP_NUM rts write_file: lda #$01 ldx DEVADR cpx #$08 bcc @noscratch ldy #$0f jsr SETLFS lda #<(filename_end-scratch) ldx #scratch jsr SETNAM jsr OPEN bcc :+ jmp ERRMSG+1 ; skip the TAX : lda #$01 jsr CLOSE @noscratch: lda #$01 ldx DEVADR bne :+ ldx #$08 : ldy #$01 jsr SETLFS lda #<(filename_end-filename) ldx #filename jsr SETNAM jsr OPEN bcc :+ jmp ERRMSG+1 ; skip the TAX : ldx #$01 jsr CHKOUT lda FILE_TYPE ; a valid AR/RR crt file is at least 32k, so add 3 more banks cmp #'c' bne @nocrt ldy #$00 jsr write_crt iny @crtloop: jsr write_chip iny cpy #$04 bcc @crtloop bcs @writedone @nocrt: .if USE_32K_BIN ; 32k binary file cmp #'b' bne @nobin ldy #$00 @binloop: jsr write_raw iny cpy #$03 bcc @binloop @nobin: .endif ; 8k rom file jsr write_raw @writedone: jmp close writeerror: ; TODO: some better error handling close: lda #' ' ldy CURRENT_COLUMN sta (CURRENT_LINE),y lda #$01 jsr CLOSE jmp CLRCHN diskstatus: lda #$01 ldx DEVADR bne :+ ldx #$08 : ldy #$0F jsr SETLFS lda #$00 jsr SETNAM jsr OPEN bcs @error ldx #$01 jsr CHKIN @loop: jsr READST bne @done jsr BASIN jsr BSOUT jmp @loop @error: ; TODO @done: lda #$01 jsr CLOSE jmp CLRCHN hexbyte_out: pha lsr lsr lsr lsr jsr hexnib_out pla and #$0f hexnib_out: ora #$30 cmp #$3a bcc :+ adc #$06 : jmp BSOUT print_dec: tax lda #$30 cpx #$64 bcs :+ jsr BSOUT cpx #$0a bcs :+ jsr BSOUT : tya pha lda #$00 jsr AXOUT pla tay rts update_chksum: jsr rrnet_chksum sta FW_CHKSUM0 stx FW_CHKSUM1 rts verify_chksum: jsr rrnet_chksum cmp FW_CHKSUM0 bne :+ cpx FW_CHKSUM1 : rts rrnet_chksum: lda FW_MAC_ADDR+4 ; MAC_LO eor FW_MAC_ADDR+5 ; MAC_HI ^ MAC_LO eor #$55 ; ^ $55 pha ; == CHKSUM0 clc adc FW_MAC_ADDR+4 ; + MAC_LO clc adc FW_MAC_ADDR+5 ; + MAC_HI eor #$aa ; ^ $aa tax ; == CHKSUM1 pla rts setcurip: jsr print .byte $02,$06,$16,$00 rts setcurmac: jsr print .byte $02,$08,$16,$00 rts input_find_non_number: ldy #$00 : lda ($22),y cmp #$30 bcc :+ cmp #$3A bcs :+ iny bne :- : tya rts input_string_to_ax: ; convert input to 16-bit value jsr VALFNC jsr FL2INT ldx $64 lda $65 rts input_skip_spaces: lda #$20 ldy #$00 : cmp ($22),y bne :++ inc $22 bne :+ inc $23 : bne :-- : lda $22 ldx $23 rts move_input_vector: tax inx txa clc adc $22 sta $22 bcc :+ inc $23 : rts input_ip: jsr setcurip lda #$00 sta DISCUR @loop: jsr GETIN beq @loop sta IOBVEC ldy CURRENT_COLUMN lda (CURRENT_LINE),y and #$7f sta (CURRENT_LINE),y lda IOBVEC cmp #$0d beq @done cmp #$14 ; backspace bne :+ lda #$9d ; same as crsr<- sta IOBVEC : cmp #$1d ; crsr-> beq @ok cmp #$9d ; crsr<- beq @ok cmp #'0' bcc @loop cmp #'9'+1 bcs @loop @ok: jsr BSOUT ldy CURRENT_COLUMN cpy #$16 bcs :+ ldy #$16 : cpy #$24 bcc :+ ldy #$24 : sty CURRENT_COLUMN lda (CURRENT_LINE),y cmp #'.' bne @loop lda IOBVEC cmp #$9d beq :+ lda #$1d : jsr BSOUT jmp @loop @done: lda #$01 sta DISCUR lda #IP_ON_SCREEN sta $22 stx $23 jsr input_skip_spaces jsr input_find_non_number pha jsr input_string_to_ax sta FW_IP_ADDR+0 pla cpx #$00 bne @inputerror jsr move_input_vector jsr input_skip_spaces jsr input_find_non_number pha jsr input_string_to_ax sta FW_IP_ADDR+1 pla cpx #$00 bne @inputerror jsr move_input_vector jsr input_skip_spaces jsr input_find_non_number pha jsr input_string_to_ax sta FW_IP_ADDR+2 pla cpx #$00 bne @inputerror jsr move_input_vector jsr input_skip_spaces jsr input_find_non_number jsr input_string_to_ax sta FW_IP_ADDR+3 cpx #$00 bne @inputerror rts @inputerror: jmp input_ip input_mac: jsr setcurmac ldy #$22 sty CURRENT_COLUMN lda #$00 sta DISCUR @loop: jsr GETIN beq @loop sta IOBVEC ldy CURRENT_COLUMN lda (CURRENT_LINE),y and #$7f sta (CURRENT_LINE),y lda IOBVEC cmp #$0d beq @done cmp #$14 ; backspace bne :+ lda #$9d ; same as crsr<- sta IOBVEC : cmp #$1d ; crsr-> beq @ok cmp #$9d ; crsr<- beq @ok cmp #'a' bcc :+ cmp #'f'+1 bcc @ok : cmp #'0' bcc @loop cmp #'9'+1 bcs @loop @ok: jsr BSOUT ldy CURRENT_COLUMN cpy #$16 bcs :+ ldy #$16 : cpy #$26 bcc :+ ldy #$26 : sty CURRENT_COLUMN lda (CURRENT_LINE),y cmp #':' bne @loop lda IOBVEC cmp #$9d beq :+ lda #$1d : jsr BSOUT jmp @loop @done: lda #$01 sta DISCUR ldx #$00 ldy #$16 @hexloop: lda (CURRENT_LINE),y iny jsr screentohexnibble asl asl asl asl sta IOBVEC lda (CURRENT_LINE),y iny iny jsr screentohexnibble ora IOBVEC sta FW_MAC_ADDR,x inx cpx #$06 bcc @hexloop jmp update_chksum input_boot_default: lda FW_BOOTDEF clc adc #$0b tax lda #$00 ;clc jsr PLOT ldy #$26 : lda (CURRENT_LINE),y ora #$80 sta (CURRENT_LINE),y dey bne :- @getkey: jsr GETIN ldx FW_BOOTDEF cmp #$0d bne :+ rts : cmp #$11 bne :+ inx cpx #$06 bcs @getkey bne @move : cmp #$91 bne @getkey dex bmi @getkey @move: stx FW_BOOTDEF ldy #$26 : lda (CURRENT_LINE),y and #$7f sta (CURRENT_LINE),y dey bne :- beq input_boot_default screentohexnibble: cmp #'0' bcc :+ and #$0f rts : ;clc because of cmp adc #$09 rts main: jsr $E518 ; try clockport first lda RREXTD ora #$01 sta RREXTD lda #$00 sta RRCTRL ldy #$03 : lda icomp_mac,y sta FW_MAC_ADDR+0,y lda RRNET_CONF_IO,y sta FW_MAC_ADDR+4,y dey bpl :- lda #$0A sta RRCTRL jsr verify_chksum beq @rrnetmk3found ; try native mode sta RRNET_ENABLE ldy #$03 : lda RRNET_CONF_ROM,y sta FW_MAC_ADDR+4,y dey bpl :- sta RRNET_DISABLE jsr verify_chksum beq @rrnetmk3found ; set generic defaults and switching to local/private MAC lda FW_MAC_ADDR+0 and #$fe ora #$02 cmp FW_MAC_ADDR+0 beq :+ sta FW_MAC_ADDR+0 jsr print .byte $02,$04,$01,"changed mac address to local",$00 : lda CIA_A_TIMER_A+1 sta FW_MAC_ADDR+4 lda CIA_A_TIMER_A+0 sta FW_MAC_ADDR+5 jsr update_chksum jmp @rrnetmk3notfound @rrnetmk3found: jsr print .byte $02,$04,$01,"rr-net mk3 mac address detected",$00 @rrnetmk3notfound: jsr print .byte $08,$8e .byte $02,$01,$01,"* rr-net firmware creator (rev. " .byte SVNREVISION .byte ") *" .byte $02,$06,$01,"default ip address:" .byte $02,$08,$01,"mac address:" .byte $02,$0a,$01,"default reset function:" ; 1234567890123456789012345678901234567890 .byte $0d,$1d,"basic (recommended)" .byte $0d,$1d,"menu/help" .byte $0d,$1d,"server mode dhcp" .byte $0d,$1d,"server mode enter ip" .byte $0d,$1d,"server mode default ip" .byte $0d,$1d,"autostart first file from drive 8" .if 0 .byte $00 jsr print .endif .byte $02,$02,$01,"de0c:",$00 lda #$00 sta RRCTRL ldx #$00 : lda RRNET_CONF_IO,x jsr hexbyte_out inx cpx #$04 bcc :- jsr print .byte " 9ffc:",$00 sta RRNET_ENABLE ldx #$00 : lda RRNET_CONF_ROM,x jsr hexbyte_out inx cpx #$04 bcc :- sta RRNET_DISABLE lda #$0A sta RRCTRL jsr setcurip ldy #$00 : lda FW_IP_ADDR,y jsr print_dec iny cpy #$04 bcs :+ lda #'.' jsr BSOUT jmp :- : jsr setcurmac ldy #$00 : lda FW_MAC_ADDR,y jsr hexbyte_out iny cpy #$06 bcs :+ lda #':' jsr BSOUT jmp :- : jsr input_ip jsr input_mac jsr input_boot_default jsr check_mac beq :+ jsr print .byte $02,$07,$01 .byte "warning: mac address is not intended" .byte $0d,$1d,$01,$08,$a3 .byte " for use with an rr-net!" .byte $00 : .if USE_CRC16 jsr print .byte " crc16:",$00 jsr calc_crc16 lda TEMP_A_16+1 jsr hexbyte_out lda TEMP_A_16+0 jsr hexbyte_out .endif jsr print .byte $02,$12,$01,"save as 8k " .byte $12,"r",$92,"om" .if USE_32K_BIN .byte ",32k ",$12,"b",$92,"in" .endif .byte " or as ",$12,"c",$92,"rt file?" .byte $00 @rbcloop: jsr GETIN sta FILE_TYPE cmp #'r' bne @nor ldy #<(ext_rom-ext_rom) beq @save @nor: .if USE_32K_BIN cmp #'b' bne @nob ldy #<(ext_bin-ext_rom) bne @save @nob: .endif cmp #'c' bne @rbcloop ldy #<(ext_crt-ext_rom) @save: ldx #$00 : lda ext_rom,y sta extension,x iny inx cpx #$03 bcc :- jsr print .byte $02,$13,$01,"writing firmware file ",$00 jsr write_file jsr print .byte $02,$14,$01,"created ",$00 lda #filename jsr $AB1E jsr diskstatus jmp ($a002)