You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

210 lines
4.2 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "drive/drive.h"
int drive_io_penality = 1;
void drive_set(int id, char *name)
{
int qi;
if ((id >= 0) && (id <256))
{
if(drives[id].name)
free(drives[id].name);
drives[id].name = strdup(name);
memset(drives[id].serial,0x00,sizeof(drives[id].serial));
if (drives[id].name)
{
if (!strncasecmp(drives[id].name,"disk_",5))
{
qi = 0;
while ( (qi<16) &&
( ((toupper(drives[id].name[5+qi]) >='A') &&
(toupper(drives[id].name[5+qi]) <='Z')) ||
((toupper(drives[id].name[5+qi]) >='0') &&
(toupper(drives[id].name[5+qi]) <='9')) ) )
{
drives[id].serial[qi] = drives[id].name[5+qi];
}
}
}
else
{
// printf("strdup() failed\n");
}
}
}
void drive(int id)
{
FILE *diskfile;
int sector, size;
unsigned char dummy[0x80];
char tempstring[256];
switch (drives[id].command)
{
case 0x01:
memset(drives[id].buffer, 0x00, 128);
if (drives[id].name)
strncpy(drives[id].buffer,drives[id].name,127);
drives[id].command = 0x00;
break;
case 0x02:
snprintf(tempstring,256,"%s.img",drives[id].buffer);
drive_set(id, tempstring);
drives[id].type = 0;
drives[id].command = 0x00;
break;
case 0x03:
memset(drives[id].buffer, 0x00, 128);
if (drives[id].type)
{
strcpy(drives[id].buffer,"System Disk");
}
else
{
if (drives[id].serial)
memcpy(drives[id].buffer, drives[id].serial, sizeof(drives[id].serial));
else if (drives[id].name)
strncpy(drives[id].buffer, drives[id].name,127);
}
drives[id].command = 0x00;
break;
case 0x04:
if (drives[id].sector >= 2048)
drives[id].command = 0xff;
else if (drives[id].name)
{
// printf("drive %d name %s\n", id, drives[id].name);
if ((diskfile = fopen(drives[id].name, "rb")) == NULL)
{
// printf("open failed\n");
drives[id].command = 0xff;
break;
}
fseek(diskfile, drives[id].sector << 7, SEEK_SET);
size = fread(drives[id].buffer, 1, 0x80, diskfile);
fclose(diskfile);
// printf("drive %d read sector %d success, size = %d\n",id,drives[id].sector,size);
if (size != 0x80)
drives[id].command = 0xff;
else
drives[id].command = 0x00;
}
else
{
drives[id].command = 0xff;
}
break;
case 0x05:
if (drives[id].sector >= 2048)
drives[id].command = 0xff;
else if (drives[id].name && !drives[id].type)
{
if ((diskfile = fopen(drives[id].name, "rb+")) == NULL)
{
if ((diskfile = fopen(drives[id].name, "wb")) == NULL)
{
drives[id].command = 0xff;
break;
}
}
memset(dummy,0x00,sizeof(dummy));
fseek(diskfile, 0, SEEK_END);
size = ftell(diskfile);
while (size < (drives[id].sector << 7))
{
size += fwrite(&dummy, 1, 0x80, diskfile);
}
fseek(diskfile, drives[id].sector << 7, SEEK_SET);
size = fwrite(&drives[id].buffer, 1, 0x80, diskfile);
fclose(diskfile);
if (size != 0x80)
drives[id].command = 0xff;
else
drives[id].command = 0x00;
}
else
drives[id].command = 0xff;
break;
default:
break;
}
}
void drive_store(int id, int ptr, unsigned char value)
{
if ((id >= 0) && (id <256))
{
if ((ptr >= 0) && (ptr < 0x80))
drives[id].buffer[ptr] = value;
else if (ptr == 0x80)
drives[id].sector = (drives[id].sector & 0xff00) | value;
else if (ptr == 0x81)
drives[id].sector = (drives[id].sector & 0xff) | (value << 8);
else if (ptr == 0x82)
{
drives[id].command = value;
if (!drive_io_penality)
drive(id);
}
}
}
unsigned char drive_load(int id, int ptr)
{
if ((id >= 0) && (id < 256))
{
if ((ptr >= 0) && (ptr < 0x80))
return drives[id].buffer[ptr];
else if (ptr == 0x80)
return drives[id].sector & 0xff;
else if (ptr == 0x81)
return (drives[id].sector >> 8) & 0xff;
else if (ptr == 0x82)
return drives[id].command;
}
return 0;
}
void drive_type(int id, int type)
{
if ((id >= 0) && (id <256))
drives[id].type = type;
}