/*UNIDRIVE 128 - v1.0 - 10 Nov 86 - Frank Prindle*/ #include "stdio.h" #define noskew 0 /*null skew table pointer*/ main() { int i; /*general purpose index*/ char ch; /*key pressed by user*/ int number_selected=7; /*counts number of formats picked*/ char limited=0; /*flag set if too many picked*/ int next_entry=0; /*keeps track of MFM table entry*/ char *load_skew_table(); /*forward reference*/ /*all possible skew tables for formats supported in main menu(s)*/ /*first byte is number of sectors/track, remainder skew values*/ static char skew0[] = {10,0,4,8,2,6,1,5,9,3,7}; static char skew1[] = {9,0,2,4,6,8,1,3,5,7}; static char skew2[] = {5,0,3,1,4,2}; static char skew3[] = {16,0,3,6,9,12,15,2,5,8,11,14,1,4,7,10,13}; static char skew4[] = {16,0,4,8,12,1,5,9,13,2,6,10,14,3,7,11,15}; static char skew5[] = {10,0,3,6,9,2,5,8,1,4,7}; static char skew6[] = {10,0,2,4,6,8,1,3,5,7,9}; /*template for an entry in the BIOS MFM format table*/ struct mfm_entry { char classification; /*encoded disk recognition factors*/ char format; /*encoded disk format*/ char *xlt; /*translate table pointer (skew table)*/ short spt; /*128 byte sectors per track*/ char bsh; /*block shift factor*/ char blm; /*block mask*/ char exm; /*extent mask*/ short dsm; /*number of blocks - 1*/ short drm; /*number of directory entries - 1*/ char al0; /*first directory block alloc vector*/ char al1; /*second directory block alloc vector*/ short cks; /*checksummed directory sectors*/ short off; /*reserved tracks*/ char psh; /*physical record shift factor*/ char phm; /*physical record mask*/ char pspt; /*physical sectors per track*/ char disktype[11]; /*disk type to be displayed plus \n and null*/ }; struct mfm_entry tempmfm; /*holds entry being loaded into BIOS*/ static struct /*main menu(s)*/ { char row; /*row for menu item*/ char col; /*column for menu item*/ char sel; /*non-zero if selected*/ char format[39]; /*menu item string*/ struct mfm_entry typeinfo; /*MFM table entry*/ } menu[26]= { 8,03,0,"A. Cromemco CDOS (SSDD)", 0x4d,0xa1,&skew0,40,3,7,0,189,63,0xc0,0x00,16,2,2,3,10, "CroCDOS SS", 9,03,0,"B. Cromemco Intl Term CP/M (SSDD)", 0x4d,0xa1,&skew5,40,4,15,1,94,127,0xc0,0x00,32,2,2,3,10, "CroIntl SS", 10,03,0,"C. Cromemco Intl Term CP/M (DSDD)", 0x4d,0xa3,&skew5,40,4,15,1,194,127,0xc0,0x00,32,2,2,3,10, "CroIntl DS", 11,03,0,"D. DEC VT-180 (SSDD)", 0x4b,0xa1,&skew1,36,3,7,0,170,63,0xc0,0x00,16,2,2,3,9, "VT-180 SS ", 12,03,1,"E. Epson QX-10 256 (DSDD)", 0x39,0x91,noskew,64,4,15,1,151,127,0xc0,0x00,32,2,1,1,16, "Epson QX10", 13,03,1,"F. Epson QX-10 512 (DSDD)", 0xcd,0xa1,noskew,80,4,15,1,189,127,0xc0,0x00,32,2,2,3,10, "Epson QX10", 14,03,0,"G. Heath w/Magnolia CP/M (SSDD)", 0x4b,0xa1,noskew,36,4,15,1,82,95,0xc0,0x00,24,3,2,3,9, "Heath Magn", 15,03,0,"H. Heath/Zenith Z90 (SSDD)", 0x39,0x91,noskew,32,3,7,0,151,127,0xf0,0x00,32,2,1,1,16, "H/Z-90 DS ", 16,03,0,"I. Heath/Zenith Z100 CP/M (SSDD)", 0x49,0xa1,noskew,32,3,7,0,151,127,0xf0,0x00,32,2,2,3,8, "H/Z-100 SS", 17,03,0,"J. Heath/Zenith Z100 CP/M (DSDD)", 0x49,0xa3,noskew,32,4,15,1,155,255,0xf0,0x00,64,2,2,3,8, "H/Z-100 DS", 18,03,1,"K. IBM-PC CP/M-86 (SSDD)", 0x49,0xa5,noskew,32,3,7,0,155,63,0xc0,0x00,16,1,2,3,8, " IBM-8 SS ", 19,03,1,"L. IBM-PC CP/M-86 (DSDD)", 0x49,0xa5,noskew,32,4,15,1,157,63,0x80,0x00,16,1,2,3,8, " IBM-8 DS ", 20,03,1,"M. Kaypro II (SSDD)", 0x4c,0xe0,noskew,40,3,7,0,194,63,0xc0,0x00,16,1,2,3,10, "KayPro II ", 8,43,1,"N. Kaypro 2x, 4, 10 (DSDD)", 0x4c,0xe2,noskew,40,4,15,1,196,127,0xc0,0x00,32,1,2,3,10, "KayPro IV ", 9,43,0,"O. Lobo MAX-80 256 (SSDD)", 0x3c,0x90,noskew,36,3,7,0,165,63,0xc0,0x00,16,3,1,1,18, "LoboMAX SS", 10,43,0,"P. Morrow MD 2 (SSDD)", 0x63,0xb1,&skew2,40,4,15,1,94,127,0xc0,0x00,32,2,3,7,5, "Morrow2 SS", 11,43,0,"Q. Morrow MD 3 (DSDD)", 0x63,0xb3,&skew2,40,4,15,1,194,191,0xe0,0x00,48,2,3,7,5, "Morrow3 DS", 12,43,0,"R. NCR Decision Mate (DSDD)", 0x49,0xa5,noskew,32,4,15,1,153,127,0xc0,0x00,32,3,2,3,8, "NCR-DM DS ", 13,43,0,"S. Olympia EX-100 (DSDD)", 0x4b,0xa3,noskew,36,4,15,1,174,127,0xc0,0x00,32,2,2,3,9, "Olym-EX DS", 14,43,1,"T. Osborne (SSDD)", 0x63,0xb1,noskew,40,3,7,0,184,63,0xc0,0x00,16,3,3,7,5, "Osborne DD", 15,43,0,"U. Osborne Osmosis (SSDD)", 0x4d,0xa1,&skew6,40,4,15,1,91,63,0xc0,0x00,16,3,2,3,10, "OsborneOsm", 16,43,0,"V. Sanyo MBC-1000 CP/M (DSDD)", 0x39,0x93,&skew3,32,4,15,1,155,63,0x80,0x00,16,2,1,1,16, " Sanyo DS ", 17,43,0,"W. Toshiba T100 (DSDD)", 0x39,0x93,&skew4,32,3,7,0,255,63,0xc0,0x00,16,6,1,1,16, "Tosh100 DS", 18,43,0,"X. TRS-80 IV CP/M Plus (SSDD)", 0x49,0xa1,noskew,32,3,7,0,155,63,0xc0,0x00,16,1,2,3,8, "TRS(4)CPM+", 20,43,0,"Y. SHOW PREVIOUS MENU", 0x00,0x00,noskew,00,0,00,0,000,000,0x00,0x00,00,0,0,0,00, " empty ", 21,43,0,"Z. SHOW NEXT MENU", 0x00,0x00,noskew,00,0,00,0,000,000,0x00,0x00,00,0,0,0,00, " empty " }; /*clear screen and display header*/ printf("\033:"); printf(" "); printf("UNIDRIVE-128 V1.0 (11/10/86) - COMMODORE 128\n"); printf(" "); printf("(c) Copyright 1986 Frank Prindle\n"); for(i=0;i<80;i++)putchar('-'); printf(" \n "); /*display menu*/ printf("MENU NUMBER 1 OF 1\n"); printf(" "); printf("======================"); for(i=0;i<26;i++) { printf("\033=%c%c%s%s%s",menu[i].row-1+' ',menu[i].col-1+' ', menu[i].sel?"\033G4":"",menu[i].format, menu[i].sel?"\033G0":""); } /*display prompt*/ printf("\033=%c%c",23-1+' ',' '); printf("Select up to 10 formats (by letter), then press RETURN.\n"); printf("To deselect any format, press letter again. ESC to abort."); printf("\033=%c%c[ ]\b\b",23-1+' ',77-1+' '); /*allow selections from this menu until CR or ESC*/ while((ch=get_key())!='\033' && ch!='\r') { if(ch>='a' && ch<='z') ch += 'A'-'a'; if(ch>='A' && ch<='Z') { if(ch=='Y' || ch=='Z') { printf("\007"); } else { i=ch-'A'; if(menu[i].sel) { if(limited)printf("\033=%c%cup to 10", 23-1+' ',8-1+' '); number_selected--; limited=0; } else { if(number_selected==10) { printf("\033=%c%c\033G4\033G2", 23-1+' ',8-1+' '); printf("UP TO 10"); printf("\033G0"); printf("\007"); limited++; menu[i].sel = !menu[i].sel; } else { number_selected++; } } menu[i].sel = !menu[i].sel; printf("\033=%c%c%s%s%s", menu[i].row-1+' ', menu[i].col-1+' ', menu[i].sel?"\033G4":"", menu[i].format, menu[i].sel?"\033G0":""); } } printf("\033=%c%c",23-1+' ',78-1+' '); /*give cursor a home*/ } /*abort if ESC entered, else load selected entries into MFM table*/ printf("\033:"); if(ch=='\033')exit(0); printf("CP/M BIOS now supports MFM disk format(s):\n\n"); clear_mfm_table(); /*clear first*/ for(i=0;i<26;i++) { if(menu[i].sel) { printf(" \033G4%s\033G0 ", menu[i].typeinfo.disktype); if(((next_entry-3)%4)==0)printf("\n"); blockmv(&tempmfm,&(menu[i].typeinfo),32); if(tempmfm.xlt) { tempmfm.xlt=load_skew_table(*(tempmfm.xlt), tempmfm.xlt+1); } load_mfm_table(next_entry++,&tempmfm); } } printf("\n"); exit(0); } /*get one character from keyboard (unbuffered)*/ int get_key() { int key; while(!(key=bdos(6,-1))); return (key & 0377); } /*execute a CP/M 3.0 Bios function*/ unsigned short bios3(fn,aReg,bcReg,deReg,hlReg) char fn, aReg; unsigned short bcReg,deReg,hlReg; { extern unsigned short bdos(), bdoshl(); struct BiosPB { char func; char aVal; unsigned short bcVal; unsigned short deVal; unsigned short hlVal; } biosPB; biosPB.func = fn; biosPB.aVal = aReg; biosPB.bcVal = bcReg; biosPB.deVal = deReg; biosPB.hlVal = hlReg; switch (fn) { case 9: /* SELDSK */ case 16: /* SECTRAN */ case 20: /* DEVTBL */ case 22: /* DRVTBL */ return bdoshl(50,(char *)&biosPB); default: return bdos (50,(char *)&biosPB); } } /*functions which manipulate Bios MFM/Skew table*/ #define USERFUN 30 /*call to bios specific functions */ #define WR_BNK0 1 /*sub function of USERFUN bios call*/ #define MFM_ENTRY_SIZE 32 /*bytes in an mfm table entry*/ #define MAX_MFM_ENTRIES 16 /*number of entries in BIOS MFM tbl*/ #define mfm_tbl_ptr *((char **)0xfd46) /*bios pointer in common memory*/ /*load an entry into skew table (at 11th MFM table entry + 1)*/ char *load_skew_table(howmany,entry) int howmany; /*how many skew table bytes*/ char *entry; /*pointer to data to be loaded*/ { int i; static char *bnk0_address=0; char *where_it_went; if(bnk0_address==0)bnk0_address=mfm_tbl_ptr + 32*10+1; where_it_went = bnk0_address; for(i=0; i