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