引き続きDISK関連を実装しました。しかし、RS232C関連はMSX1だと何に使えばいいんだろうか。
fMSXを参考にZ80未定義命令を使った、かなりトリッキーな実装です。
z80.cpp
(省略) case 0xbb: OTDR(); break; /* OTDR */ default: #ifdef _CPU_DEBUG_LOG if(debug_count) { emu->out_debug(_T("%4x\tDB ED\n"), prevpc); } #endif #ifdef _MSX1 #include "./msx1/memory.cpp" #else OP(code); break; } } #endif (省略)
memory.cpp
#ifndef _Z80_H_ /* ASCII MSX1 Emulator 'yaMSX1' Skelton for retropc emulator Author : tanam Date : 2013.06.29- [ memory ] */ #include "memory.h" #include "../../fileio.h" /** Places in DiskROM to be patched with ED FE C9 ************/ uint16 DiskPatches[] = { 0x4010,0x4013,0x4016,0x401C,0x401F,0 }; void MEMORY::initialize() { int I,J,K; byte *R; ROMData[0]=ROMData[1]=NULL; CCount = 0; RAMPages=4; /* Number of RAM pages */ RAMMask=3; /* Initialize ROMMasks to zeroes for now */ ROMMask[0]=ROMMask[1]=0; /* Allocate 16kB for the empty space (scratch RAM) */ if(!(EmptyRAM=(byte *)malloc(0x4000))) return; memset(EmptyRAM,0xff,0x4000); Chunks[CCount++]=EmptyRAM; /* Reset memory map to the empty space */ for(I=0;I<4;I++) for(J=0;J<4;J++) for(K=0;K<8;K++) MemMap[I][J][K]=EmptyRAM; /* Allocate RAMPages*16kB for RAM */ if(!(RAMData=(byte *)malloc(RAMPages*0x4000))) return; memset(RAMData,0xff,RAMPages*0x4000); Chunks[CCount++]=RAMData; P=(byte *)malloc(0x8000); FILEIO* fio = new FILEIO(); if(fio->Fopen(emu->bios_path(_T("MSX1.ROM")), FILEIO_READ_BINARY)) { fio->Fread(P, 0x8000, 1); fio->Fclose(); } MemMap[0][0][0]=P; MemMap[0][0][1]=P+0x2000; MemMap[0][0][2]=P+0x4000; MemMap[0][0][3]=P+0x6000; /* Try loading DiskROM */ Q=(byte *)malloc(0x4000); if(fio->Fopen(emu->bios_path(_T("DISK.ROM")), FILEIO_READ_BINARY)) { fio->Fread(Q, 0x4000, 1); fio->Fclose(); MemMap[3][1][2]=Q; MemMap[3][1][3]=Q+0x2000; /* Apply patches to BDOS */ for (J=0;DiskPatches[J];J++) { R=MemMap[3][1][2]+DiskPatches[J]-0x4000; R[0]=0xED;R[1]=0xFE;R[2]=0xC9; } } delete fio; for(J=0;J<4;J++) { EnWrite[J] = 0; /* Write protect ON for all slots */ PSL[J]=SSL[J] = 0; /* PSL=0:0:0:0, SSL=0:0:0:0 */ MemMap[3][2][J*2] = RAMData+(3-J)*0x4000; /* RAMMap=3:2:1:0 */ MemMap[3][2][J*2+1] = MemMap[3][2][J*2]+0x2000; RAMMapper[J] = 3-J; RAM[J*2] = MemMap[0][0][J*2]; /* Setting RAM */ RAM[J*2+1] = MemMap[0][0][J*2+1]; } PSLReg=0x00; SSLReg=0x00; PS=0; SS=0; inserted = false; } void MEMORY::write_data8(uint32 addr, uint32 data) { byte I,J; if (addr!=0xFFFF) { if (EnWrite[addr>>14]) RAM[addr>>13][addr&0x1FFF]=data; else if ((addr>0x3FFF)&&(addr<0xC000)) { /* J contains 16kB page number 0-3 */ J=addr>>14; /* I contains slot number 0/1 */ if(PSL[J]==1) I=0; else if(PSL[J]==2) I=1; /* If no cartridge or no mapper, exit */ return; } } else { if (PSL[3]==3) { if (SSLReg!=data) { SSLReg=data; for (J=0;J<4;J++,data>>=2) { SSL[J]=data&3; if (PSL[J]==3) { I=J<<1; EnWrite[J]=(SSL[J]==2)&&(MemMap[3][2][I]!=EmptyRAM); RAM[I]=MemMap[3][SSL[J]][I]; RAM[I+1]=MemMap[3][SSL[J]][I+1]; } } } } else if (EnWrite[3]) RAM[7][addr&0x1FFF]=data; } } uint32 MEMORY::read_data8(uint32 addr) { if (addr==0x4011) { // Save slot states PS=PSLReg;SS=SSLReg; // Turn on RAM in all slots write_signal(0xA8,0xFF,0xFF); SSLReg=0xAA; } if (SS!=0 && PS !=0) { // Restore slot states SSLReg=SS; write_signal(0xA8,PS,0xFF); SS=0; PS=0; } if (addr!=0xFFFF) return(RAM[addr>>13][addr&0x1FFF]); else return (PSL[3]==3? ~SSLReg:RAM[7][0x1FFF]); } void MEMORY::write_signal(int id, uint32 data, uint32 mask) { byte I,J,K,Value; for (J=0,PSLReg=Value=data;J<4;J++,Value>>=2) { PSL[J]=Value&3;I=J<<1; K=PSL[J]==3? SSL[J]:0; EnWrite[J]=(K==2)&&(MemMap[3][2][I]!=EmptyRAM); RAM[I]=MemMap[PSL[J]][K][I]; RAM[I+1]=MemMap[PSL[J]][K][I+1]; } } void MEMORY::open_cart(_TCHAR* file_path) { int C1,C2,C3,ROM64,LastFirst; FILE *F; int Slot=0; /* Check slot #, try to open file */ if(!(F=fopen(file_path,"rb"))) return; /* Check "AB" signature in a file */ ROM64=LastFirst=0; C1=fgetc(F); C2=fgetc(F); /* Maybe this is a flat 64kB ROM? */ if((C1!='A')||(C2!='B')) if(fseek(F,0x4000,SEEK_SET)>=0) { C1=fgetc(F); C2=fgetc(F); ROM64=(C1=='A')&&(C2=='B'); } /* Maybe it is the last page that contains "AB" signature? */ if((C1!='A')||(C2!='B')) if(fseek(F,-0x4000,SEEK_END)>=0) { C1=fgetc(F); C2=fgetc(F); LastFirst=(C1=='A')&&(C2=='B'); } /* If we can't find "AB" signature, drop out */ if((C1!='A')||(C2!='B')) { fclose(F); return; } /* Determine file length via fseek()/ftell() */ if (fseek(F,0,SEEK_END)>=0) C1=ftell(F); else { /* Determine file length by reading entire [GZIPped] stream */ fseek(F,0,SEEK_SET); for(C1=0;(C2=fread(EmptyRAM,1,0x4000,F))==0x4000;C1+=C2); if(C2>=0) C1+=C2; } /* Done with the file */ fclose(F); /* Length must be a multiple of 8kB */ /* Flat 64kB ROM must be 40..64kB */ if (C1&0x1FFF) return; if (ROM64&&(C1<0xA000)) return; if (ROM64&&(C1>0x10000)) return; /* Compute size in 8kB pages */ C1>>=13; /* Calculate 2^n closest to number of pages */ for(C3=1;C3<C1;C3<<=1); /* Assign ROMMask for MegaROMs */ ROMMask[Slot]=!ROM64&&(C1>4)? C3-1:0x00; /* Allocate space for the ROM */ ROMData[Slot]=(byte *)malloc(C3*0x2000); if (!ROMData[Slot]) return; Chunks[CCount++]=ROMData[Slot]; /* Try loading ROM */ FILEIO* fio = new FILEIO(); if(fio->Fopen(file_path, FILEIO_READ_BINARY)) { fio->Fread(ROMData[Slot], C1*0x2000, 1); fio->Fclose(); } delete fio; /* Mirror ROM if it is smaller than 2^n pages */ if(C1<C3) memcpy(ROMData[Slot]+C1*0x2000, ROMData[Slot]+(C1-C3/2)*0x2000, (C3-C1)*0x2000); /* Set memory map depending on the ROM size */ switch (C1) { case 1: /* 8kB ROMs are mirrored 8 times: 0:0:0:0:0:0:0:0 */ MemMap[Slot+1][0][0]=ROMData[Slot]; MemMap[Slot+1][0][1]=ROMData[Slot]; MemMap[Slot+1][0][2]=ROMData[Slot]; MemMap[Slot+1][0][3]=ROMData[Slot]; MemMap[Slot+1][0][4]=ROMData[Slot]; MemMap[Slot+1][0][5]=ROMData[Slot]; MemMap[Slot+1][0][6]=ROMData[Slot]; MemMap[Slot+1][0][7]=ROMData[Slot]; break; case 2: /* 16kB ROMs are mirrored 4 times: 0:1:0:1:0:1:0:1 */ MemMap[Slot+1][0][0]=ROMData[Slot]; MemMap[Slot+1][0][1]=ROMData[Slot]+0x2000; MemMap[Slot+1][0][2]=ROMData[Slot]; MemMap[Slot+1][0][3]=ROMData[Slot]+0x2000; MemMap[Slot+1][0][4]=ROMData[Slot]; MemMap[Slot+1][0][5]=ROMData[Slot]+0x2000; MemMap[Slot+1][0][6]=ROMData[Slot]; MemMap[Slot+1][0][7]=ROMData[Slot]+0x2000; break; case 3: case 4: /* 24kB and 32kB ROMs are mirrored twice: 0:1:0:1:2:3:2:3 */ MemMap[Slot+1][0][0]=ROMData[Slot]; MemMap[Slot+1][0][1]=ROMData[Slot]+0x2000; MemMap[Slot+1][0][2]=ROMData[Slot]; MemMap[Slot+1][0][3]=ROMData[Slot]+0x2000; MemMap[Slot+1][0][4]=ROMData[Slot]+0x4000; MemMap[Slot+1][0][5]=ROMData[Slot]+0x6000; MemMap[Slot+1][0][6]=ROMData[Slot]+0x4000; MemMap[Slot+1][0][7]=ROMData[Slot]+0x6000; break; default: /* 64kB ROMs are loaded to fill slot: 0:1:2:3:4:5:6:7 */ MemMap[Slot+1][0][0]=ROMData[Slot]; MemMap[Slot+1][0][1]=ROMData[Slot]+0x2000; MemMap[Slot+1][0][2]=ROMData[Slot]+0x4000; MemMap[Slot+1][0][3]=ROMData[Slot]+0x6000; MemMap[Slot+1][0][4]=ROMData[Slot]+0x8000; MemMap[Slot+1][0][5]=ROMData[Slot]+0xA000; MemMap[Slot+1][0][6]=ROMData[Slot]+0xC000; MemMap[Slot+1][0][7]=ROMData[Slot]+0xE000; break; } inserted = true; } void MEMORY::close_cart() { int J; /* Free alocated memory */ for(J=0;J<CCount;J++) free(Chunks[J]); if (P) free(P); if (Q) free(Q); initialize(); } #else uint8 DiskPresent(uint8 ID); byte DiskRead(byte ID,byte *Buf, int N); byte DiskWrite(byte ID,byte *Buf,int N); #define C_FLAG 0x01 /* 1: Carry/Borrow occured */ static byte BootBlock[] = { 0xEB,0xFE,0x90,0x56,0x46,0x42,0x2D,0x31,0x39,0x38,0x39,0x00,0x02,0x02,0x01,0x00, 0x02,0x70,0x00,0xA0,0x05,0xF9,0x03,0x00,0x09,0x00,0x02,0x00,0x00,0x00,0xD0,0xED, 0x53,0x58,0xC0,0x32,0xC2,0xC0,0x36,0x55,0x23,0x36,0xC0,0x31,0x1F,0xF5,0x11,0x9D, 0xC0,0x0E,0x0F,0xCD,0x7D,0xF3,0x3C,0x28,0x28,0x11,0x00,0x01,0x0E,0x1A,0xCD,0x7D, 0xF3,0x21,0x01,0x00,0x22,0xAB,0xC0,0x21,0x00,0x3F,0x11,0x9D,0xC0,0x0E,0x27,0xCD, 0x7D,0xF3,0xC3,0x00,0x01,0x57,0xC0,0xCD,0x00,0x00,0x79,0xE6,0xFE,0xFE,0x02,0x20, 0x07,0x3A,0xC2,0xC0,0xA7,0xCA,0x22,0x40,0x11,0x77,0xC0,0x0E,0x09,0xCD,0x7D,0xF3, 0x0E,0x07,0xCD,0x7D,0xF3,0x18,0xB4,0x42,0x6F,0x6F,0x74,0x20,0x65,0x72,0x72,0x6F, 0x72,0x0D,0x0A,0x50,0x72,0x65,0x73,0x73,0x20,0x61,0x6E,0x79,0x20,0x6B,0x65,0x79, 0x20,0x66,0x6F,0x72,0x20,0x72,0x65,0x74,0x72,0x79,0x0D,0x0A,0x24,0x00,0x4D,0x53, 0x58,0x44,0x4F,0x53,0x20,0x20,0x53,0x59,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF3,0x2A, 0x51,0xF3,0x11,0x00,0x01,0x19,0x01,0x00,0x01,0x11,0x00,0xC1,0xED,0xB0,0x3A,0xEE, 0xC0,0x47,0x11,0xEF,0xC0,0x21,0x00,0x00,0xCD,0x51,0x52,0xF3,0x76,0xC9,0x18,0x64, 0x3A,0xAF,0x80,0xF9,0xCA,0x6D,0x48,0xD3,0xA5,0x0C,0x8C,0x2F,0x9C,0xCB,0xE9,0x89, 0xD2,0x00,0x32,0x26,0x40,0x94,0x61,0x19,0x20,0xE6,0x80,0x6D,0x8A,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; static const struct { int Sectors;byte Heads,Names,PerTrack,PerFAT,PerCluster; } Info[8] = { { 720,1,112,9,2,2 }, { 1440,2,112,9,3,2 }, { 640,1,112,8,1,2 }, { 1280,2,112,8,2,2 }, { 360,1, 64,9,2,1 }, { 720,2,112,9,2,2 }, { 320,1, 64,8,1,1 }, { 640,2,112,8,1,2 } }; byte Buf[512],Count,N,*P; int Sector, i, j; uint16 Addr; /** PHYDIO: Read/write sectors to disk ************************** *** Input: *** *** [F] CARRY=WRITE [A] Drive number (0=A:) *** *** [B] Number of sectors to write [C] Media descriptor *** *** [DE] Logical sector number (starts at 0) *** *** [HL] Transfer address *** *** Output: *** *** [F] CARRY=ERROR [A] If error: errorcode *** *** [B] Number of sectors remaining (not read/written) *** *** Error codes in [A] can be: *** *** 0 Write protected 8 Record not found *** *** 2 Not ready 10 Write fault *** *** 4 Data (CRC) error 12 Other errors *** *** 6 Seek error *** ****************************************************************/ if (prevpc==0x4010) { iff1|=1; /// R->IFF|=1; Addr = HL; /// R->HL.W; Count = B; /// R->BC.B.h; if (!DiskPresent(A)) { AF=0x0201; ///R->AF.W=0x0201; return; } // No disk -> "Not ready" if (DE+Count>Info[C-0xF8].Sectors) { AF=0x0801; return; } // Wrong sector -> "Record not found" // If data does not fit into 64kB address space, trim it if (HL+Count*512>0x10000) Count=(0x10000-HL)/512; // Save slot states // Turn on RAM in all slots if (F&C_FLAG) for (Sector=DE;Count--;Sector++) { // WRITE for (j=0;j<512;j++) Buf[j]=RM8(Addr++); if (DiskWrite(A,Buf,Sector)) B--; else { AF=0x0A01; return; } } else for(Sector=DE;Count--;Sector++) { // READ if (DiskRead(A,Buf,Sector)) { B--; } else { AF=0x0401; return; } for(j=0;j<512;j++) WM8(Addr++,Buf[j]); } F&=~C_FLAG; return; /** DSKCHG: Check if the disk was changed *********************** *** Input: *** *** [A] Drive number (0=A:) [B] Media descriptor *** *** [C] Media descriptor [HL] Base address of DPB *** *** Output: *** *** [F] CARRY=ERROR [A] If error: errorcode (see DSKIO) *** *** [B] If success: 1=Unchanged, 0=Unknown, -1=Changed *** *** Note: *** *** If the disk has been changed or may have been changed *** *** (unknown) read the boot sector or the FAT sector for disk *** *** media descriptor and transfer a new DPB as with GETDPB. *** ****************************************************************/ } else if (prevpc==0x4013) { iff1|=1; // If no disk, return "Not ready": if(!DiskPresent(A)) { AF=0x0201; return; } // This requires some major work to be done: B=0; F &= ~C_FLAG; // We continue with GETDPB now... /** GETDPB: Disk format ***************************************** *** Input: *** *** [A] Drive number [B] 1st byte of FAT (media descriptor) *** *** [C] Media descriptor [HL] Base address of DPB *** *** Output: *** *** [HL+1] .. [HL+18] = DPB for specified drive *** *** DPB consists of: *** *** Name Offset Size Description *** *** MEDIA 0 1 Media type (F8..FF) *** *** SECSIZ 1 2 Sector size (must be 2^n) *** *** DIRMSK 3 1 (SECSIZE/32)-1 *** *** DIRSHFT 4 1 Number of one bits in DIRMSK *** *** CLUSMSK 5 1 (Sectors per cluster)-1 *** *** CLUSSHFT 6 1 (Number of one bits in CLUSMSK)+1 *** *** FIRFAT 7 2 Logical sector number of first FAT *** *** FATCNT 8 1 Number of FATs *** *** MAXENT A 1 Number of directory entries (max 254) *** *** FIRREC B 2 Logical sector number of first data *** *** MAXCLUS D 2 Number of clusters (not including *** *** reserved, FAT and directory sectors)+1 *** *** FATSIZ F 1 Number of sectors used *** *** FIRDIR 10 2 FAT logical sector number of start of *** *** directory *** ****************************************************************/ } else if (prevpc==0x4016) { int BytesPerSector,SectorsPerDisk,SectorsPerFAT,ReservedSectors; // If no disk, return "Not ready": if (!DiskPresent(A)) { AF=0x0201; return; } // If can't read, return "Other error": if (!DiskRead(A, Buf , 0)) { AF=0x0C01; return; } BytesPerSector = (int)Buf[0x0C]*256+Buf[0x0B]; SectorsPerDisk = (int)Buf[0x14]*256+Buf[0x13]; SectorsPerFAT = (int)Buf[0x17]*256+Buf[0x16]; ReservedSectors = (int)Buf[0x0F]*256+Buf[0x0E]; Addr=HL+1; WM8(Addr++,Buf[0x15]); // Format ID [F8h-FFh] WM8(Addr++,Buf[0x0B]); // Sector size WM8(Addr++,Buf[0x0C]); j=(BytesPerSector>>5)-1; for(i=0;j&(1<<i);i++); WM8(Addr++,j); // Directory mask/shft WM8(Addr++,i); j=Buf[0x0D]-1; for(i=0;j&(1<<i);i++); WM8(Addr++,j); // Cluster mask/shift WM8(Addr++,i+1); WM8(Addr++,Buf[0x0E]); // Sector # of 1st FAT WM8(Addr++,Buf[0x0F]); WM8(Addr++,Buf[0x10]); // Number of FATs WM8(Addr++,Buf[0x11]); // Number of dirent-s j=ReservedSectors+Buf[0x10]*SectorsPerFAT; j+=32*Buf[0x11]/BytesPerSector; WM8(Addr++,j&0xFF); // Sector # of data WM8(Addr++,(j>>8)&0xFF); j=(SectorsPerDisk-j)/Buf[0x0D]; WM8(Addr++,j&0xFF); // Number of clusters WM8(Addr++,(j>>8)&0xFF); WM8(Addr++,Buf[0x16]); // Sectors per FAT j=ReservedSectors+Buf[0x10]*SectorsPerFAT; WM8(Addr++,j&0xFF); // Sector # of dir. WM8(Addr,(j>>8)&0xFF); // Return success F&=~C_FLAG; return; /** DSKFMT: Disk format ***************************************** *** Input: *** *** [A] Specified choice (1-9) [D] Drive number (0=A:) *** *** [HL] Begin address of work area [BC] Length of work area *** *** Output: *** *** [F] CARRY=ERROR *** *** Notes: *** *** 1) Also writes a MSX boot sector at sector 0, clears all *** *** FATs (media descriptor at first byte, 0FFh at second/ *** *** third byte and rest zero) and clears the directory *** *** filling it with zeros. *** *** 2) Error codes are: *** *** 0 Write protected 10 Write fault *** *** 2 Not ready 12 Bad parameter *** *** 4 Data (CRC) error 14 Insufficient memory *** *** 6 Seek error 16 Other errors *** *** 8 Record not found *** ****************************************************************/ } else if (prevpc==0x401c) { iff1|=1; // If invalid choice, return "Bad parameter": if (!A || A>2) { AF=0x0C01; return; } // If no disk, return "Not ready": if (!DiskPresent(D)) { AF=0x0201; return; } // Fill bootblock with data: P=BootBlock+3; N=2-A; memcpy(P,"fMSXdisk",8);P+=10; // Manufacturer's ID *P=Info[N].PerCluster;P+=4; // Sectors per cluster *P++=Info[N].Names;*P++=0x00; // Number of names *P++=Info[N].Sectors // Number of sectors *P++=(Info[N].Sectors>>8) *P++=N+0xF8; // Format ID [F8h-FFh] *P++=Info[N].PerFAT;*P++=0x00; // Sectors per FAT *P++=Info[N].PerTrack;*P++=0x00; // Sectors per track *P++=Info[N].Heads;*P=0x00; // Number of heads // If can't write bootblock, return "Write protected": if (!DiskWrite(D, BootBlock, 0)) { AF=0x0001; return; } // Writing FATs: for (Sector=1,j=0;j<2;j++) { Buf[0]=N+0xF8; Buf[1]=Buf[2]=0xFF; memset(Buf+3,0x00,509); if (!DiskWrite(D, Buf, Sector++)) { AF=0x0A01; return; } memset(Buf,0x00,512); for (i=Info[N].PerFAT;i>1;i--) if (!DiskWrite(D, Buf, Sector++)) { AF=0x0A01; return; } } j=Info[N].Names/16; // Directory size i=Info[N].Sectors-2*Info[N].PerFAT-j-1; // Data size for (memset(Buf,0x00,512);j;j--) if (!DiskWrite(D, Buf, Sector++)) { AF=0x0A01; return; } for (memset(Buf,0xFF,512);I;I--) if (!DiskWrite(D, Buf, Sector++)) { AF=0x0A01; return; } // Return success F&=~C_FLAG; return; /*** DRVOFF: Stop drives ***************************************** *** Input: None *** *** Output: None *** ****************************************************************/ } else if (prevpc==0x401f) { return; } break; } } #define MAXDRIVES 2 #define O_BINARY 0 static FILE *Drives[2]={NULL,NULL}; /* Disk image files */ static int RdOnly[2]; /* 1 = read-only */ /** ChangeDisk() *********************************************/ /** Change disk image in a given drive. Closes current disk **/ /** image if Name=0 was given. Returns 1 on success or 0 on **/ /** failure. **/ /*************************************************************/ byte ChangeDisk(byte ID,char *Name) { /* We only have MAXDRIVES drives */ if (ID >= MAXDRIVES) return(0); /* Close previous disk image */ if (Drives[ID] != NULL) { fclose(Drives[ID]); Drives[ID] = NULL; } if (Name == NULL) return (0); /* If no disk image given, consider drive empty */ if (!Name) return(1); /* Open new disk image */ Drives[ID]=fopen(Name,"r+b"); RdOnly[ID]=0; /* If failed to open for writing, open read-only */ if (Drives[ID] == NULL) { Drives[ID]=fopen(Name,"rb"); RdOnly[ID]=1; } /* Return operation result */ return (Drives[ID] != NULL); } /** DiskPresent() ********************************************/ /** Return 1 if disk drive with a given ID is present. **/ /*************************************************************/ uint8 DiskPresent(uint8 ID) { return((ID<MAXDRIVES)&&(Drives[ID] != NULL)); } /** DiskRead() ***********************************************/ /** Read requested sector from the drive into a buffer. **/ /*************************************************************/ byte DiskRead(byte ID,byte *Buf, int N) { if ((ID<MAXDRIVES) && (Drives[ID] != NULL)) if (0 == fseek(Drives[ID], N*512L, SEEK_SET)) { int tmp=fread(Buf, 1, 512, Drives[ID]); return (tmp==512); } return (0); } /** DiskWrite() **********************************************/ /** Write contents of the buffer into a given sector of the **/ /** disk. **/ /*************************************************************/ byte DiskWrite(byte ID,byte *Buf,int N) { if ((ID<MAXDRIVES) && (Drives[ID] != NULL) && !RdOnly[ID]) if (0 == fseek(Drives[ID], N*512L, SEEK_SET)) return(fwrite(Buf, 1, 512, Drives[ID]) == 512); return (0); } #endif
未実装な機能(実装予定)