#include "bios.h"
#include "../disk.h"
+#include "../harddisk.h"
// regs
#define AX regs[0]
#define BLOCK_SIZE 512
+namespace FMR50 {
+
static const int iotable[][2] = {
#ifdef _FMR30
{0x0100, 0x19}, // pic
{
// to increment timeout counter
register_frame_event(this);
-
- // check scsi drives
- FILEIO* fio = new FILEIO();
- for(int i = 0; i < MAX_SCSI; i++) {
- if(fio->Fopen(create_local_path(_T("SCSI%d.DAT"), i), FILEIO_READ_WRITE_BINARY)) {
- uint32_t file_size = fio->FileLength();
- if(file_size == 0) {
- // from ../scsi_hdd.cpp
- #define SCSI_BUFFER_SIZE 0x10000
- uint32_t remain = (file_size = 0x2800000); // 40MB
- void *tmp = calloc(1, SCSI_BUFFER_SIZE);
- while(remain > 0) {
- uint32_t length = min(remain, SCSI_BUFFER_SIZE);
- fio->Fwrite(tmp, length, 1);
- remain -= length;
- }
- free(tmp);
- #undef SCSI_BUFFER_SIZE
- }
- scsi_blocks[i] = file_size / BLOCK_SIZE;
- fio->Fclose();
- } else {
- scsi_blocks[i] = 0;
- }
- }
- delete fio;
}
void BIOS::reset()
{
for(int i = 0; i < MAX_DRIVE; i++) {
access_fdd[i] = false;
+ drive_mode1[i] = 0x03; // MFM, 2HD, 1024B
+ drive_mode2[i] = 0x208; // 2 Heads, 8 sectors
+ }
+ for(int i = 0; i < USE_HARD_DISK; i++) {
+ if(harddisk[i] != NULL && harddisk[i]->mounted()) {
+ scsi_blocks[i] = harddisk[i]->sector_size * harddisk[i]->sector_num / BLOCK_SIZE;
+ } else {
+ scsi_blocks[i] = 0;
+ }
}
- access_scsi = false;
secnum = 1;
timeout = 0;
}
timeout++;
}
-bool BIOS::bios_call_i86(uint32_t PC, uint16_t regs[], uint16_t sregs[], int32_t* ZeroFlag, int32_t* CarryFlag)
+bool BIOS::bios_call_far_i86(uint32_t PC, uint16_t regs[], uint16_t sregs[], int32_t* ZeroFlag, int32_t* CarryFlag)
{
uint8_t *regs8 = (uint8_t *)regs;
int drv = AL & 0xf;
if(PC == 0xfffc4) {
// disk bios
#ifdef _DEBUG_LOG
- emu->out_debug_log(_T("%6x\tDISK BIOS: AH=%2x,AL=%2x,CX=%4x,DX=%4x,BX=%4x,DS=%2x,DI=%2x\n"), get_cpu_pc(0), AH,AL,CX,DX,BX,DS,DI);
+ this->out_debug_log(_T("%6x\tDISK BIOS: AH=%2x,AL=%2x,CX=%4x,DX=%4x,BX=%4x,DS=%2x,DI=%2x\n"), get_cpu_pc(0), AH,AL,CX,DX,BX,DS,DI);
#endif
- if(AH == 2) {
+ if(AH == 0) {
+ // set drive mode
+ if(!(drv < MAX_DRIVE)) {
+ AH = 2;
+ *CarryFlag = 1;
+ return true;
+ }
+ AH = 0;
+ drive_mode1[drv] = DL;
+ drive_mode2[drv] = BX;
+ // ToDo: Trap when not resiztered disk[drv].
+ switch(DL & 0x30) {
+ case 0x00: disk[drv]->drive_type = DRIVE_TYPE_2HD; break;
+ case 0x10: disk[drv]->drive_type = DRIVE_TYPE_2DD; break;
+ case 0x20: disk[drv]->drive_type = DRIVE_TYPE_2D ; break;
+ }
+ *CarryFlag = 0;
+ return true;
+ } else if(AH == 1) {
+ // get drive mode
+ if(!(drv < MAX_DRIVE)) {
+ AH = 2;
+ *CarryFlag = 1;
+ return true;
+ }
+ AH = 0;
+ DL = drive_mode1[drv];
+ BX = drive_mode2[drv];
+ *CarryFlag = 0;
+ return true;
+ } else if(AH == 2) {
// drive status
if((AL & 0xf0) == 0x20) {
// floppy
+ // ToDo: Trap when not resiztered disk[drv].
if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
AH = 0x80;
CX = ERR_FDD_NOTREADY;
return true;
}
AH = 0;
- DL = 4;
+ if(disk[drv]->get_track(0, 0) && disk[drv]->get_sector(0, 0, 0)) {
+ switch(disk[drv]->sector_size.sd) {
+ case 128: AH = 0; break;
+ case 256: AH = 1; break;
+ case 512: AH = 2; break;
+ default : AH = 3; break; // 1024
+ }
+ }
+ DL = 0;
if(disk[drv]->write_protected) {
DL |= 2;
}
+ if(disk[drv]->two_side) {
+ DL |= 4;
+ }
+// if(disk[drv]->drive_type == DRIVE_TYPE_2D || disk[drv]->drive_type == DRIVE_TYPE_2DD) {
+ if(disk[drv]->media_type == MEDIA_TYPE_2D || disk[drv]->media_type == MEDIA_TYPE_2DD) {
+ DL |= 0x10;
+ }
CX = 0;
*CarryFlag = 0;
return true;
}
if((AL & 0xf0) == 0xb0) {
// scsi
- if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
+ if(!(drv < USE_HARD_DISK && scsi_blocks[drv])) {
AH = 0x80;
CX = ERR_SCSI_NOTCONNECTED;
*CarryFlag = 1;
// restore/seek
if((AL & 0xf0) == 0x20) {
// floppy
+ // ToDo: Trap when not resiztered disk[drv].
if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
AH = 0x80;
CX = ERR_FDD_NOTREADY;
}
if((AL & 0xf0) == 0xb0) {
// scsi
- if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
+ if(!(drv < USE_HARD_DISK && scsi_blocks[drv])) {
AH = 0x80;
CX = ERR_SCSI_NOTCONNECTED;
*CarryFlag = 1;
// read sectors
if((AL & 0xf0) == 0x20) {
// floppy
+ // ToDo: Trap when not resiztered disk[drv].
if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
AH = 0x80;
CX = ERR_FDD_NOTREADY;
int sct = DL;
while(BX > 0) {
// search sector
- disk[drv]->get_track(trk, hed);
+ // ToDo: Trap when not resiztered disk[drv].
+ if(!disk[drv]->get_track(trk, hed)) {
+ AH = 0x80;
+ CX = ERR_FDD_NOTFOUND;
+ *CarryFlag = 1;
+ return true;
+ }
access_fdd[drv] = true;
secnum = sct;
if(!disk[drv]->get_sector(trk, hed, sct - 1)) {
}
if((AL & 0xf0) == 0xb0) {
// scsi
- if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
+ if(!(drv < USE_HARD_DISK && scsi_blocks[drv])) {
AH = 0x80;
CX = ERR_SCSI_NOTCONNECTED;
*CarryFlag = 1;
return true;
}
- FILEIO* fio = new FILEIO();
- if(!fio->Fopen(create_local_path(_T("SCSI%d.DAT"), drv), FILEIO_READ_BINARY)) {
+ if(!(harddisk[drv] != NULL && harddisk[drv]->mounted())) {
AH = 0x80;
CX = ERR_SCSI_NOTREADY;
*CarryFlag = 1;
- delete fio;
return true;
}
// get params
int ofs = DS * 16 + DI;
int block = (CL << 16) | DX;
- fio->Fseek(block * BLOCK_SIZE, FILEIO_SEEK_SET);
+ long position = block * BLOCK_SIZE;
while(BX > 0) {
// check block
- access_scsi = true;
if(!(block++ < scsi_blocks[drv])) {
AH = 0x80;
CX = ERR_SCSI_PARAMERROR;
*CarryFlag = 1;
- fio->Fclose();
- delete fio;
return true;
}
// data transfer
- fio->Fread(buffer, BLOCK_SIZE, 1);
+ harddisk[drv]->read_buffer(position, BLOCK_SIZE, buffer);
+ position += BLOCK_SIZE;
for(int i = 0; i < BLOCK_SIZE; i++) {
d_mem->write_data8(ofs++, buffer[i]);
}
AH = 0;
CX = 0;
*CarryFlag = 0;
- fio->Fclose();
- delete fio;
return true;
}
AH = 2;
int hed = DH & 1;
int sct = DL;
while(BX > 0) {
+ // ToDo: Trap when not resiztered disk[drv].
// search sector
- disk[drv]->get_track(trk, hed);
+ if(!disk[drv]->get_track(trk, hed)) {
+ AH = 0x80;
+ CX = ERR_FDD_NOTFOUND;
+ *CarryFlag = 1;
+ return true;
+ }
access_fdd[drv] = true;
secnum = sct;
if(!disk[drv]->get_sector(trk, hed, sct - 1)) {
}
if((AL & 0xf0) == 0xb0) {
// scsi
- if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
+ if(!(drv < USE_HARD_DISK && scsi_blocks[drv])) {
AH = 0x80;
CX = ERR_SCSI_NOTCONNECTED;
*CarryFlag = 1;
return true;
}
- FILEIO* fio = new FILEIO();
- if(!fio->Fopen(create_local_path(_T("SCSI%d.DAT"), drv), FILEIO_READ_WRITE_BINARY)) {
+ if(!(harddisk[drv] != NULL && harddisk[drv]->mounted())) {
AH = 0x80;
CX = ERR_SCSI_NOTREADY;
*CarryFlag = 1;
- delete fio;
return true;
}
// get params
int ofs = DS * 16 + DI;
int block = (CL << 16) | DX;
- fio->Fseek(block * BLOCK_SIZE, FILEIO_SEEK_SET);
+ long position = block * BLOCK_SIZE;
while(BX > 0) {
// check block
- access_scsi = true;
if(!(block++ < scsi_blocks[drv])) {
AH = 0x80;
CX = ERR_SCSI_PARAMERROR;
*CarryFlag = 1;
- fio->Fclose();
- delete fio;
return true;
}
// data transfer
for(int i = 0; i < BLOCK_SIZE; i++) {
buffer[i] = d_mem->read_data8(ofs++);
}
- fio->Fwrite(buffer, BLOCK_SIZE, 1);
+ harddisk[drv]->write_buffer(position, BLOCK_SIZE, buffer);
+ position += BLOCK_SIZE;
BX--;
}
AH = 0;
CX = 0;
*CarryFlag = 0;
- fio->Fclose();
- delete fio;
return true;
}
AH = 2;
int sct = DL;
while(BX > 0) {
// search sector
- disk[drv]->get_track(trk, hed);
+ // ToDo: Trap when not resiztered disk[drv].
+ if(!disk[drv]->get_track(trk, hed)) {
+ AH = 0x80;
+ CX = ERR_FDD_NOTFOUND;
+ *CarryFlag = 1;
+ return true;
+ }
access_fdd[drv] = true;
secnum = sct;
if(!disk[drv]->get_sector(trk, hed, sct - 1)) {
}
if((AL & 0xf0) == 0xb0) {
// scsi
- if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
+ if(!(drv < USE_HARD_DISK && scsi_blocks[drv])) {
AH = 0x80;
CX = ERR_SCSI_NOTCONNECTED;
*CarryFlag = 1;
int block = (CL << 16) | DX;
while(BX > 0) {
// check block
- access_scsi = true;
if(!(block++ < scsi_blocks[drv])) {
AH = 0x80;
CX = ERR_SCSI_PARAMERROR;
// read id
if((AL & 0xf0) == 0x20) {
// floppy
+ // ToDo: Trap when not resiztered disk[drv].
if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
AH = 0x80;
CX = ERR_FDD_NOTREADY;
int trk = CX;
int hed = DH & 1;
// search sector
- disk[drv]->get_track(trk, hed);
+ if(!disk[drv]->get_track(trk, hed)) {
+ AH = 0x80;
+ CX = ERR_FDD_NOTFOUND;
+ *CarryFlag = 1;
+ return true;
+ }
access_fdd[drv] = true;
if(++secnum > disk[drv]->sector_num.sd) {
secnum = 1;
// format track
if((AL & 0xf0) == 0x20) {
// floppy
+ // ToDo: Trap when not resiztered disk[drv].
if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
AH = 0x80;
CX = ERR_FDD_NOTREADY;
int trk = CX;
int hed = DH & 1;
// format track
+ // ToDo: Trap when not resiztered disk[drv].
disk[drv]->format_track(trk, hed);
access_fdd[drv] = true;
bool id_written = false;
if(!id_written) {
// insert new sector with data crc error
write_id:
+ // ToDo: Trap when not resiztered disk[drv].
id_written = true;
sector_found = false;
uint8_t c = disk[drv]->track[index - 4];
} else if(id_written) {
if(sector_found) {
// sector data
+ // ToDo: Trap when not resiztered disk[drv].
if(sector_index < sector_length) {
disk[drv]->sector[sector_index] = datareg;
}
sector_index++;
} else if(datareg == 0xf8 || datareg == 0xfb) {
// data mark
+ // ToDo: Trap when not resiztered disk[drv].
disk[drv]->set_deleted(datareg == 0xf8);
sector_found = true;
}
// disk change ???
if((AL & 0xf0) == 0x20) {
// floppy
+ // ToDo: Trap when not resiztered disk[drv].
if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
AH = 0;
CX = 0;
}
if((AL & 0xf0) == 0xb0) {
// scsi
- if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
+ if(!(drv < USE_HARD_DISK && scsi_blocks[drv])) {
AH = 3; // ???
CX = 0;
*CarryFlag = 1;
}
if((AL & 0xf0) == 0xb0) {
// scsi
- if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
+ if(!(drv < USE_HARD_DISK && scsi_blocks[drv])) {
AH = 0x80;
CX = ERR_SCSI_NOTCONNECTED;
*CarryFlag = 1;
}
if((AL & 0xf0) == 0xb0) {
// scsi
- if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
+ if(!(drv < USE_HARD_DISK && scsi_blocks[drv])) {
AH = 0;
CX = 0x200; // ???
*CarryFlag = 0;
return true;
} else if(AH == 0x81) {
// pseudo bios: boot from fdd #0
+ // ToDo: Trap when not resiztered disk[drv].
*ZeroFlag = (timeout > (int)(FRAMES_PER_SEC * 4));
if(!disk[0]->inserted) {
*CarryFlag = 1;
return true;
}
// load ipl
- disk[0]->get_track(0, 0);
+ if(!disk[0]->get_track(0, 0)) {
+ *CarryFlag = 1;
+ return true;
+ }
access_fdd[0] = true;
if(!disk[0]->get_sector(0, 0, 0)) {
*CarryFlag = 1;
*CarryFlag = 1;
return true;
}
- FILEIO* fio = new FILEIO();
- if(!fio->Fopen(create_local_path(_T("SCSI%d.DAT"), drv), FILEIO_READ_BINARY)) {
+ if(!(harddisk[drv] != NULL && harddisk[drv]->mounted())) {
*CarryFlag = 1;
- delete fio;
return true;
}
// load ipl
- access_scsi = true;
- fio->Fread(buffer, BLOCK_SIZE * 4, 1);
- fio->Fclose();
- delete fio;
+ harddisk[drv]->read_buffer(0, BLOCK_SIZE * 4, buffer);
// check ipl
if(!(buffer[0] == 'I' && buffer[1] == 'P' && buffer[2] == 'L' && buffer[3] == IPL_ID)) {
*CarryFlag = 1;
} else if(PC == 0xfffc9) {
// cmos
#ifdef _DEBUG_LOG
- emu->out_debug_log(_T("%6x\tCMOS BIOS: AH=%2x,AL=%2x,CX=%4x,DX=%4x,BX=%4x,DS=%2x,DI=%2x\n"), get_cpu_pc(0), AH,AL,CX,DX,BX,DS,DI);
+ this->out_debug_log(_T("%6x\tCMOS BIOS: AH=%2x,AL=%2x,CX=%4x,DX=%4x,BX=%4x,DS=%2x,DI=%2x\n"), get_cpu_pc(0), AH,AL,CX,DX,BX,DS,DI);
#endif
if(AH == 0) {
// init cmos
} else if(PC == 0xfffd3) {
// wait
#ifdef _DEBUG_LOG
- emu->out_debug_log(_T("%6x\tWAIT BIOS: AH=%2x,AL=%2x,CX=%4x,DX=%4x,BX=%4x,DS=%2x,DI=%2x\n"), get_cpu_pc(0), AH,AL,CX,DX,BX,DS,DI);
+ this->out_debug_log(_T("%6x\tWAIT BIOS: AH=%2x,AL=%2x,CX=%4x,DX=%4x,BX=%4x,DS=%2x,DI=%2x\n"), get_cpu_pc(0), AH,AL,CX,DX,BX,DS,DI);
#endif
*CarryFlag = 0;
return true;
if(intnum == 0x93) {
// disk bios
- return bios_call_i86(0xfffc4, regs, sregs, ZeroFlag, CarryFlag);
+ return bios_call_far_i86(0xfffc4, regs, sregs, ZeroFlag, CarryFlag);
}
return false;
}
{
// get access status
uint32_t stat = 0;
- for(int i = 0; i < MAX_DRIVE; i++) {
- if(access_fdd[i]) {
- stat |= 1 << i;
+ if(ch == 0) {
+ for(int i = 0; i < MAX_DRIVE; i++) {
+ if(access_fdd[i]) {
+ stat |= 1 << i;
+ }
+ access_fdd[i] = false;
}
- access_fdd[i] = false;
}
- if(access_scsi) {
- stat |= 0x10;
- }
- access_scsi = false;
return stat;
}
-#define STATE_VERSION 3
+#define STATE_VERSION 5
-void BIOS::save_state(FILEIO* state_fio)
+bool BIOS::process_state(FILEIO* state_fio, bool loading)
{
- state_fio->FputUint32(STATE_VERSION);
- state_fio->FputInt32(this_device_id);
-
- for(int i = 0; i < MAX_DRIVE; i++) {
- disk[i]->save_state(state_fio);
- }
- state_fio->FputInt32(secnum);
- state_fio->FputInt32(timeout);
-}
-
-bool BIOS::load_state(FILEIO* state_fio)
-{
- if(state_fio->FgetUint32() != STATE_VERSION) {
+ if(!state_fio->StateCheckUint32(STATE_VERSION)) {
return false;
}
- if(state_fio->FgetInt32() != this_device_id) {
+ if(!state_fio->StateCheckInt32(this_device_id)) {
return false;
}
for(int i = 0; i < MAX_DRIVE; i++) {
- if(!disk[i]->load_state(state_fio)) {
+ if(!disk[i]->process_state(state_fio, loading)) {
return false;
}
}
- secnum = state_fio->FgetInt32();
- timeout = state_fio->FgetInt32();
+ state_fio->StateInt32(secnum);
+ state_fio->StateInt32(timeout);
+ state_fio->StateBuffer(drive_mode1, sizeof(drive_mode1), 1);
+ //state_fio->StateBuffer(drive_mode2, sizeof(drive_mode2), 1);
+ for(int i = 0; i < (sizeof(drive_mode2) / sizeof(uint16_t)); i++) {
+ state_fio->StateUint16(drive_mode2[i]);
+ }
+ //state_fio->StateBuffer(scsi_blocks, sizeof(scsi_blocks), 1);
+ for(int i = 0; i < (sizeof(scsi_blocks) / sizeof(int)); i++) {
+ state_fio->StateInt32(scsi_blocks[i]);
+ }
return true;
}
+}