;MMC64 Koala Plugin V1.0 ;(C)2007 by Oliver Achten ; Not optimized, but it helps to have a framework for your own plugins. ; Have fun! processor 6502 SEG.U variables ORG $02 fat32 .byte memptr .word filelength .ds 4 clusterlength .byte datstart .ds 3 fatstart .ds 3 tmpcount .byte fatptr .word sector .ds 4 startcluster .ds 3 filecluster .ds 3 secpercluster .byte cmdresp .byte cmd1 .byte cmd2 .byte cmd3 .byte cmd4 .byte cmd5 .byte cmd6 .byte cardsize .byte vidptr .word temp .ds 3 ;------------------------- SEG bank0 ORG $bffe ;------------------------- .byte $00,$c0 .start jmp .fat16start jmp .fat32start .byte "MMC64" .fat16start lda #$00 sta fat32 jmp .nofat32 .fat32start lda #$01 sta fat32 .nofat32 sei lda #$35 ;switching to RAM only sta $01 lda #$08 ;deactivate catridges plugged into the MMC64 sta $df11 ldy #$02 ;we have to save the MMC64 BIOS zeropage for later return .savebioszp lda $00,y sta $5f00,y iny bne .savebioszp ldy #$03 ; Copy bios parameters into variables .dwordcopy lda $cf87,y sta filelength,y dey bpl .dwordcopy ldy #$02 .ds3copy lda $cf80,y sta datstart,y lda $cf83,y sta fatstart,y dey bpl .ds3copy lda $cf86 sta secpercluster lda $cf8b sta filecluster sta startcluster lda $cf8c sta filecluster+1 sta startcluster+1 lda #$00 sta filecluster+2 sta startcluster+2 lda fat32 beq .nofat32param lda $cf8d sta filecluster+2 sta startcluster+2 .nofat32param jsr .gfxinit ;init screenmode jsr .preparefile ;prepare all pointers to load file jsr .readfile ;read file ldx #$00 ;copy video & color mem .copyloop lda $3f40,x sta $0400,x lda $4040,x sta $0500,x lda $4140,x sta $0600,x lda $4240,x sta $0700,x lda $4328,x sta $d800,x lda $4428,x sta $d900,x lda $4528,x sta $da00,x lda $4628,x sta $db00,x inx bne .copyloop lda $4710 sta $d021 lda #$3b ;switch screen on sta $d011 lda #$ff ;initialize keyboard sta $dc02 lda #$00 sta $dc03 lda #$00 sta $dc00 .keywait ;wait for any key lda $dc01 cmp #$ff beq .keywait ldy #$02 ;restore zp for BIOS .restorebioszp lda $5f00,y sta $00,y iny bne .restorebioszp lda #$00 ;enable MMC64 BIOS again sta $df11 lda #$e7 sta $01 lda #$ff ;set-up keyboard sta $dc02 lda #$00 sta $dc03 rts ;done! ;------------------------ .readfile ;check for zero file length lda filelength bne .noendreadfile lda filelength+1 bne .noendreadfile rts .noendreadfile ;we copy secpercluster * 512 bytes ldy secpercluster sty clusterlength .prgclustercopyloop jsr .initmmcdatatransfer ;set up data transfer jsr .waitformmcdata cpy #$00 beq .prgclustercopyloop lda $df11 ;enable read trigger mode ora #%01000000 sta $df11 lda $df10 ;preload buffer lda #$02 ;we copy 2*256 bytes sta tmpcount ldx filelength .prgsectorloop ldy #$00 .prgsectorcopyloop lda $df10 sta (vidptr),y dex cpx #$ff bne .noendfilecopy dec filelength+1 lda filelength+1 cmp #$ff bne .noendfilecopy jmp .prgendfileread .noendfilecopy iny bne .prgsectorcopyloop inc vidptr+1 dec tmpcount bne .prgsectorloop lda $df10 ;empty buffer lda $df11 ;disable read trigger mode and #%10111111 sta $df11 dec $d020 ;flash border inc $d020 jsr .incsector dec clusterlength beq .noprgclustercopyloop jmp .prgclustercopyloop .noprgclustercopyloop jsr .calculatefilepointers jmp .prgclustercopyloop .endprgsectorcopyloop lda $df10 .prgendfileread iny bne .endprgsectorcopyloop dec tmpcount bne .endprgsectorcopyloop lda $df10 lda $df11 and #%10111111 sta $df11 rts ;----------------------- .incsector ;increases 24bit sector adress inc sector bne .noincsector inc sector+1 bne .noincsector inc sector+2 .noincsector rts .calculatefilepointers ;file system handle jsr .readnextcluster jsr .clustertosector lda secpercluster sta clusterlength rts ;------------------------------- .cmdsend ;send command lda $df12 ror bcs .cmdsend lda $df11 ;enable CS line ora #%00000010 sta $df11 lda #$ff sta $df10 .cmdwait3 lda $df12 ror bcs .cmdwait3 lda $df11 ;enable CS line and #%11111101 sta $df11 ldx #$00 .cmdloop lda cmd1,x sta $df10 .cmdwait lda $df12 ror bcs .cmdwait inx cpx #$06 bne .cmdloop ldx #$ff stx $df10 .cmdwait4 lda $df12 ror bcs .cmdwait4 .cmdloop2 ldx #$ff stx $df10 .cmdwait2 lda $df12 ror bcs .cmdwait2 lda $df10 cmp #$ff beq .cmdloop2 sta cmdresp rts ;----------------------- .waitformmcdata ;wait until card is ready to send data ldy #$00 .waitformmcdataloop dey beq .endmmcdata lda #$ff sta $df10 lda $df10 cmp #$fe bne .waitformmcdataloop .endmmcdata rts ;----------------------- .readsector ;read one 512 byte sector jsr .initmmcdatatransfer jsr .waitformmcdata cpy #$00 beq .readsector lda $df11 ora #%01000000 sta $df11 lda $df10 ldx #$02 ldy #$00 .sectorcopyloop lda $df10 sta (memptr),y iny bne .sectorcopyloop inc memptr+1 dex bne .sectorcopyloop lda $df10 lda $df11 and #%10111111 sta $df11 .endreadsector rts ;------------------------------- .initmmcdatatransfer ;transfer sector into command register lda $df11 ora #%00000100 sta $df11 lda #$51 sta cmd1 lda sector asl sta cmd4 lda sector+1 rol sta cmd3 lda sector+2 rol sta cmd2 lda #$00 sta cmd5 lda #$ff sta cmd6 jmp .cmdsend ;------------------- .clustertosector ;converts a 24bit cluster into sector lda startcluster sec sbc #$02 sta startcluster lda startcluster+1 sbc #$00 sta startcluster+1 lda startcluster+2 sbc #$00 sta startcluster+2 .convertcluster jsr .findcardsize lda startcluster sta sector lda startcluster+1 sta sector+1 lda startcluster+2 sta sector+2 iny .convertshiftloop dey beq .endconvertcluster lda sector asl sta sector lda sector+1 rol sta sector+1 lda sector+2 rol sta sector+2 jmp .convertshiftloop .endconvertcluster .sectordatadd lda sector clc adc datstart sta sector lda sector+1 adc datstart+1 sta sector+1 lda sector+2 adc datstart+2 sta sector+2 rts ;---------------------- .findcardsize ;claculate chift value with respect to sector per cluster ldx secpercluster ldy #$00 lda #$01 sta cardsize .outputshiftloop cpx cardsize beq .cardsizefound asl cardsize iny bne .outputshiftloop .cardsizefound rts ;--------------------- .readnextcluster ;FAT16 / FAT32 cluster read routine lda fat32 ;do we have fat32? beq .fat16decoding jmp .fat32decoding .fat16decoding ; FAT 16 cluster handling lda filecluster+1 ;get next cluster of file clc adc fatstart ;add fat start value sta sector lda fatstart+1 adc #$00 sta sector+1 lda fatstart+2 adc #$00 sta sector+2 lda fatptr ;read FAT portion sta memptr lda fatptr+1 sta memptr+1 jsr .readsector .fatexists lda filecluster ;calculate memory position of next cluster asl sta memptr lda filecluster rol rol and #$01 clc adc fatptr+1 sta memptr+1 ldy #$01 .copyfat16cluster ;read the cluster lda (memptr),y sta startcluster,y sta filecluster,y dey bpl .copyfat16cluster rts ;----------------------- .fat32decoding ;FAT32 cluster decoding lda filecluster ;shift cluster value to read correct 512byte page of FAT rol lda filecluster+1 rol sta temp lda filecluster+2 rol sta temp+1 lda #$00 rol sta temp+2 lda temp ;add fat start to it clc adc fatstart sta sector lda temp+1 adc fatstart+1 sta sector+1 lda temp+2 adc fatstart+2 sta sector+2 .readnextfat32 ;read portion of the FAT lda fatptr sta memptr lda fatptr+1 sta memptr+1 jsr .readsector lda filecluster ;calculate memory position of next Cluster asl asl sta memptr lda filecluster rol rol rol and #$01 clc adc fatptr+1 sta memptr+1 ldy #$02 ;get cluster .copyfat32cluster lda (memptr),y sta startcluster,y sta filecluster,y dey bpl .copyfat32cluster rts .gfxinit ;initializes the vic to mc-bitmap mode lda #$00 ; bitmap mode ldx #$18 ; multi-colour mode ldy #$18 ; screen at $1c00, bitmap at $2000 sta $d011 stx $d016 sty $d018 lda #$00 sta $d020 sta $d021 rts .preparefile ;initialize pointers lda #$fe ;start of koala file sta vidptr lda #$1f sta vidptr+1 lda #$00 ;location of FAT buffer sta fatptr lda #$60 sta fatptr+1 jsr .clustertosector