10REM MMC 20REM by Martin Mather 30REM 2005 40: 50MODE 7 60*KEY0*BE|M 70: 80WE%=0 90MM%=0 100: 110MMC=&FE18 120: 130VIA=&FE60 140IORB=VIA 150DDRB=VIA+2 160SR=VIA+&A 170ACR=VIA+&B 180PCR=VIA+&C 190: 200bout=&70 210bin=&71 220: 230DIM cmd% 20 240DIM mem% 512 250DIM code% 200 260: 270IF MM% GOTO 340 280: 290clkpol%=0 300align%=0 310PROCass 320: 330PROCuv 340PROCMMCINIT 350: 360ON ERROR GOTO 550 370: 380act$="R" 390IF WE%=0 GOTO 410 400INPUT "(R)ead / (W)rite Sector ",act$ 410INPUT "Sector number ",sec% 420: 430IF act$="W" GOTO 490 440: 450PROCrdsec(sec%,mem%) 460PROCdump(mem%) 470GOTO 380 480: 490IF sec%<400 GOTO 380 500INPUT "From hex address ",F$ 510F%=EVAL("&"+F$) 520PROCwrsec(sec%,F%) 530GOTO 380 540: 550REPORT 560PRINT 570IF ERR<>17 GOTO 380 580END 590: 600: 610DEF FNMMC(C%,A%,K%) 620: 630REM Send command to MMC 640?cmd%=C% 650cmd%!1=A% 660cmd%?5=K% 670PROCw(&FF) 680PROCw(cmd%?0) 690PROCw(cmd%?4) 700PROCw(cmd%?3) 710PROCw(cmd%?2) 720PROCw(cmd%?1) 730PROCw(cmd%?5) 740PROCw(&FF) 750R%=FNrw(&FF) 760PRINT "MMC: ";~C%,~A%,~K%,"= ";~R% 770: 780=R% 790: 800: 810DEF PROCMMCINIT 820: 830REM 80 clocks 840FOR I=0 TO 9 850PROCw(&FF) 860NEXT 870: 880REM CMD0 890X%=FNMMC(&40,0,&95) 900IF X%=1 THEN GOTO 980 910PRINT "CMD 0 FAILED!" 920IF X%=&FF GOTO 840 930: 940align%=(align%+1) MOD 8 950PROCass 960GOTO 840 970: 980REM CMD1 990X%=FNMMC(&41,0,&FF) 1000IF X%=0 THEN GOTO 1040 1010PRINT "CMD 1 FAILED!" 1020GOTO 980 1030: 1040REM READ CARD ID 1050X%=FNMMC(&4A,0,&FF) 1060IF X%=0 GOTO 1100 1070PRINT "CID FAILED!" 1080GOTO 1170 1090: 1100PRINT "CID: "; 1110FOR I=0 TO 19 1120X%=FNrw(&FF) 1130PRINT ;~X%;" "; 1140NEXT 1150PRINT 1160: 1170ENDPROC 1180: 1190: 1200DEF PROCuv 1210: 1220REM Set up VIA 1230?DDRB=7 1240?IORB=0 1250?ACR=0 1260?SR=0 1270: 1280ENDPROC 1290: 1300: 1310DEF PROCrdsec(S%,D%) 1320: 1330REM Read 512 byte sector S% to 1340REM address D% 1350: 1360X%=FNMMC(&51,S%*512,&FF) 1370IF X%=0 GOTO 1420 1380PRINT "READ ERROR!" 1390GOTO 1570 1400: 1410REM wait for data token 1420X%=FNrw(&FF) 1430IF X%<>&FE THEN GOTO 1420 1440: 1450REM read data 1460FOR X%=0 TO 511 1470D%?X%=FNrw(&FF) 1480NEXT 1490: 1500REM read (ignore) CRC 1510PROCw(&FF) 1520PROCw(&FF) 1530: 1540REM 1 extra for safety 1550PROCw(&FF) 1560: 1570ENDPROC 1580: 1590: 1600DEF PROCwrsec(S%,D%) 1610: 1620REM Write sector S% with 1630REM data at D% 1640: 1650X%=FNMMC(&58,S%*512,&FF) 1660IF X%=0 GOTO 1700 1670PRINT "WRITE ERROR 1!" 1680GOTO 1880 1690: 1700PROCw(&FF) 1710PROCw(&FF) 1720PROCw(&FE) 1730: 1740FOR X%=0 TO 511 1750PROCw(D%?X%) 1760NEXT 1770: 1780PROCw(&FF) 1790PROCw(&FF) 1800: 1810X%=FNrw(&FF) AND &1F 1820IF X%=5 GOTO 1850 1830PRINT "WRITE ERROR 2!" 1840: 1850X%=FNrw(&FF) 1860IF X%<>&FF GOTO 1850 1870: 1880ENDPROC 1890: 1900: 1910REM send byte to MMC 1920: 1930DEF PROCw(A%):R%=FNrw(A%):ENDPROC 1940: 1950DEF FNrw(A%) 1960IF MM% THEN ?MMC=A%:=?MMC 1970CALL rwmmc:=?bin 1980: 1990: 2000DEF PROCass 2010: 2020FOR o%=0 TO 3 STEP 3 2030P%=code% 2040: 2050[OPT o% 2060.rwmmc 2070\ send/rec byte 2080\ MSB first 2090: 2100STA bout 2110] 2120FOR x=7 TO 0 STEP -1 2130[OPT o% 2140ROL bout 2150LDA #clkpol% 2160ROL A 2170STA IORB 2180] 2190IF clkpol%=1 [OPT o%:AND #1:] 2200IF clkpol%=0 [OPT o%:ORA #2:] 2210[OPT o% 2220STA IORB 2230] 2240IF x<>align% GOTO 2290 2250[OPT o% 2260LDA SR 2270STA bin 2280] 2290NEXT x 2300[OPT o% 2310RTS 2320] 2330NEXT o% 2340PRINT "SIZE=";P%-code% 2350: 2360ENDPROC 2370: 2380: 2390DEF PROCdump(D%) 2400S%=8 2410FOR X%=0 TO 511 STEP S% 2420PRINT FNx(X%,4); 2430L$="" 2440FOR Y%=0 TO S%-1 2450B%=D%?(X%+Y%) 2460PRINT ;" ";FNx(B%,2); 2470IF B%>=&20 AND B%<127 L$=L$+CHR$(B%) ELSE L$=L$+"." 2480NEXT 2490PRINT ;" ";L$ 2500NEXT 2510ENDPROC 2520: 2530: 2540DEF FNx(N%,Z%) 2550=RIGHT$("0000"+STR$~N%,Z%)