0100 ; 96K RAMDISK CONTROLLER FOR 256K ATARI 800XL (version 2)›0110 ; by Claus Buchholz, Oct., 1985›0120 ;›0130 ; OPTION: Drive number›0140 ;›0150 DRIVE=3›0160 ;›0170 ; Equates›0180 ;›0190 DDEVIC=$300 SIO Device Control Block›0200 DUNIT=$301›0210 DCOMND=$302›0220 DSTATS=$303›0230 DBUFLO=$304›0240 DBYTLO=$308›0250 DAUX1=$30A›0260 DOSINI=$0C Access to RESET initialization›0270 CHKSUM=$31 Temporary checksum›0280 BUFRLO=$32 Temporary pointer to user's buffer›0290 ZTEMP=$34 Temporary miscellaneous use›0300 ZTEM2=$38 Temporary miscellaneous use›0310 STACKP=$318 Stack pointer save›0320 PORTB=$D301 PIA port B - memory control register›0330 ;›0340 ; Load-time code - Copy OS into RAM›0350 ;›0360 *=$3800›0370 GO›0380 LDA PORTB Enable Bank #3›0390 AND #$83›0400 ORA #$0C›0410 STA PORTB›0420 LDA #$C0 Zero page pointer›0430 STA $CC›0440 LDA #$40›0450 STA $CE›0460 LDA #0›0470 STA $CB›0480 STA $CD›0490 TAY›0500 LOOP›0510 LDA ($CB),Y Copy OS›0520 STA ($CD),Y›0530 INY›0540 BNE LOOP›0550 LDX $CC›0560 CPX #$CB Skip pages $CC to $D7›0570 BNE NXPG›0580 LDX #$57›0590 STX $CE›0600 LDX #$D7›0610 NXPG›0620 INC $CE›0630 INX›0640 STX $CC›0650 BNE LOOP›0660 LDA PORTB›0670 ORA #$7C Disable bank›0680 AND #$FE Enable RAM OS›0690 STA PORTB›0700 RTS Continue load›0710 *=$2E2›0720 .WORD GO Execute preliminary load-time code›0730 ;›0740 ; Ramdisk controller code›0750 ;›0760 *=$CC00 Permanent code - in place of alt. char. set›0770 HOOK›0780 CLC Hook into all SIO calls›0790 LDA DDEVIC›0800 ADC DUNIT›0810 CMP #$31+DRIVE Right drive number?›0820 BEQ HOOKED›0830 OLDVEC=*+1›0840 JMP * If not, go to SIO›0850 HOOKED›0860 TSX If so, intercept›0870 STX STACKP Save stack pointer›0880 LDA DCOMND Examine command›0890 CMP #'! Format?›0900 BNE NOFMT›0910 JMP FORMAT›0920 NOFMT›0930 CMP #'P Put sector?›0940 BNE NOPUT›0950 JMP PUTSEC›0960 NOPUT›0970 CMP #'R Read sector?›0980 BNE NOGET›0990 JMP GETSEC›1000 NOGET›1010 CMP #'S Read status?›1020 BNE NOSTT›1030 JMP STATUS›1040 NOSTT›1050 CMP #'W Write sector?›1060 BNE NAKRET›1070 JMP PUTSEC›1080 ;›1090 ; Returns - Restore stack pointer, report error status and return›1100 ;›1110 NAKRET›1120 LDX STACKP›1130 TXS›1140 LDY #139 NAK error for improper command›1150 STY DSTATS›1160 RTS›1170 ERRRET›1180 LDX STACKP›1190 TXS›1200 LDY #144 Bad sector error›1210 STY DSTATS›1220 RTS›1230 SUCRET›1240 LDX STACKP›1250 TXS›1260 LDY #1 No error›1270 STY DSTATS›1280 RTS›1290 ;›1300 ; Subroutine - Set pointer to user buffer›1310 ;›1320 SETBUF›1330 LDA DBUFLO Move from DCB to zero page›1340 STA BUFRLO›1350 LDA DBUFLO+1›1360 STA BUFRLO+1›1370 RTS›1380 ;›1390 ; Subroutine - Prepare to access sector of ramdisk›1400 ;›1410 SETSEC›1420 LDA DAUX1+1 Check sector #›1430 BNE NOTZ›1440 LDA DAUX1›1450 BNE INRNG Sector 0 invalid›1460 OUTRG›1470 JMP NAKRET Sector # out of range›1480 NOTZ›1490 CMP #2 Check for sector # > $2D0›1500 BCC INRNG›1510 BNE OUTRG›1520 LDA #$D0›1530 CMP DAUX1›1540 BCC OUTRG›1550 INRNG›1560 LDA DAUX1 Sector # valid›1570 ASL A›1580 LDA DAUX1+1›1590 ROL A Divide # by 128 - Result is bank #, remainder is page #›1600 ADC #4 Bank #›1610 TAX›1620 LDA DAUX1›1630 ORA #$80 Remainder+128›1640 ;›1650 ; Subroutine - Prepare to switch banks:›1660 ; X is bank #, A is 2*page #›1670 ;›1680 SETBNK›1690 LSR A›1700 STA ZTEM2+1 Save page #›1710 LDA #0›1720 ROR A›1730 STA ZTEM2›1740 LDA PORTB›1750 STA PBN Normal bank›1760 AND #$83›1770 STA PB Bank 0›1780 TXA›1790 ASL A›1800 ASL A›1810 PHA›1820 AND #$0C›1830 ORA PB›1840 STA PB›1850 PLA›1860 ASL A›1870 AND #$60›1880 ORA PB›1890 STA PB Bank X›1900 LDA $FFFA NMI vector›1910 STA ZTEMP›1920 LDA $FFFB›1930 STA ZTEMP+1›1940 LDY #0›1950 LDA #$40 RTI opcode›1960 SEI Disable IRQ›1970 STA (ZTEMP),Y Place RTI in NMI routine - disables NMI›1980 RTS Leave 0 in Y, bank # in X›1990 ;›2000 ; Format routine›2010 ;›2020 FORMAT›2030 LDX #4 Clear banks 4 to 9›2040 CLOOP1›2050 LDA #$80›2060 JSR SETBNK Prepare for switch›2070 LDA PB›2080 STA PORTB Switch bank in›2090 TYA›2100 CLOOP2›2110 STA (ZTEM2),Y Zero entire page›2120 INY›2130 BNE CLOOP2›2140 INC ZTEM2+1 Next page›2150 BPL CLOOP2›2160 LDA PBN›2170 STA PORTB Switch bank out›2180 LDA NMI›2190 STA (ZTEMP),Y Enable interrupts›2200 CLI›2210 INX Next bank›2220 CPX #$A Done?›2230 BCC CLOOP1›2240 JSR SETBUF›2250 LDA #$FF Return a sector with 2 $FFs and the rest 0s›2260 LDY #0›2270 FLOOP›2280 CPY #2›2290 BNE NOTFF›2300 LDA #0›2310 NOTFF›2320 STA (BUFRLO),Y›2330 INY›2340 BPL FLOOP›2350 JMP SUCRET Done›2360 ;›2370 ; Write sector routine›2380 ;›2390 PUTSEC›2400 JSR SETBUF›2410 LDA #0›2420 STA CHKSUM Zero checksum›2430 JSR SETSEC Point to ramdisk sector›2440 PLOOP›2450 LDA (BUFRLO),Y Get byte from user's buffer›2460 LDX PB›2470 STX PORTB Switch bank›2480 STA (ZTEM2),Y Put byte into ramdisk›2490 LDX PBN›2500 STX PORTB Normal bank›2510 CLC›2520 ADC CHKSUM Add byte to checksum›2530 STA CHKSUM›2540 INY Next byte›2550 BPL PLOOP›2560 LDX #9 Bank 9 holds checksum table›2570 LDA DAUX1+1›2580 ORA #$70 Sector # indexes checksum table›2590 ASL A›2600 JSR SETBNK›2610 LDY DAUX1›2620 LDA CHKSUM›2630 LDX PB›2640 STX PORTB Switch bank›2650 STA (ZTEM2),Y Store checksum›2660 LDX PBN›2670 STX PORTB Normal bank›2680 LDY #0›2690 LDA NMI›2700 STA (ZTEMP),Y Enable interrupts›2710 CLI›2720 JMP SUCRET Done›2730 ;›2740 ; Read sector routine›2750 ;›2760 GETSEC›2770 JSR SETBUF›2780 LDA #0›2790 STA CHKSUM Zero checksum›2800 JSR SETSEC›2810 GLOOP›2820 LDX PB›2830 STX PORTB Switch bank›2840 LDA (ZTEM2),Y Get byte from ramdisk›2850 LDX PBN›2860 STX PORTB Normal bank›2870 STA (BUFRLO),Y Put byte into user's buffer›2880 CLC›2890 ADC CHKSUM Add to checksum›2900 STA CHKSUM›2910 INY Next byte›2920 BPL GLOOP›2930 LDX #9 Bank 9 holds checksum table›2940 LDA DAUX1+1›2950 ORA #$70 Sector # indexes checksum table›2960 ASL A›2970 JSR SETBNK›2980 LDY DAUX1›2990 LDX PB›3000 STX PORTB Switch bank›3010 LDA (ZTEM2),Y Get original checksum›3020 LDX PBN›3030 STX PORTB Normal bank›3040 TAX›3050 LDY #0›3060 LDA NMI›3070 STA (ZTEMP),Y Enable interrupts›3080 CLI›3090 CPX CHKSUM Compare checksums›3100 BEQ GCSOK›3110 JMP ERRRET If different, bad sector›3120 GCSOK›3130 JMP SUCRET If same, done›3140 ;›3150 ; Read status routine›3160 ;›3170 STATUS›3180 JSR SETBUF›3190 LDY #3 Return 4 bytes›3200 LDA #0 All 0s›3210 SLOOP›3220 STA (BUFRLO),Y›3230 DEY›3240 BPL SLOOP›3250 JMP SUCRET Done›3260 ;›3270 ; Variable storage area›3280 ;›3290 PB *=*+1 Value of memory control register for selected bank›3300 PBN *=*+1 Value of memory control register for normal bank›3310 NMI *=*+1 First opcode in NMI routine - Used to restore NMI›3320 ;›3330 ; RESET initialization routine›3340 ;›3350 *=$100 Hidden (hopefully)›3360 NEWINI›3370 DEC PORTB Enable RAM OS›3380 OLDINI=*+1›3390 JSR * Call original DOSINI routine›3400 MODINI›3410 LDA #NEWINI&$FF Set hook for next RESET›3420 STA DOSINI›3430 LDA #NEWINI/$100›3440 STA DOSINI+1›3450 RTS›3460 ;›3470 ; Load-time code - Install ramdisk›3480 ;›3490 *=$3800›3500 DO›3510 LDA $E45A Save original SIO vector›3520 STA OLDVEC›3530 LDA $E45B›3540 STA OLDVEC+1›3550 LDA #HOOK&$FF Install new SIO vector›3560 STA $E45A›3570 LDA #HOOK/$100›3580 STA $E45B›3590 LDA $FFFA Save first opcode in NMI routine›3600 STA $CB›3610 LDA $FFFB›3620 STA $CC›3630 LDY #0›3640 LDA ($CB),Y›3650 STA NMI›3660 LDA DOSINI Save original DOSINI vector›3670 STA OLDINI›3680 LDA DOSINI+1›3690 STA OLDINI+1›3700 JSR MODINI Install new one›3710 JSR $7E0 Re-initialize FMS to show ramdisk present›3720 RTS Done›3730 *=$2E2›3740 .WORD DO Execute final load-time code›