-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathEmuDisk.cpp
More file actions
141 lines (131 loc) · 4.89 KB
/
Copy pathEmuDisk.cpp
File metadata and controls
141 lines (131 loc) · 4.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include "GimeBus.h"
#include "EmuDisk.h"
EmuDisk::EmuDisk()
{
nextLogicalSector.zeroByte = 0; // By the least significant byte always being zero, this effectively multiplies our LSN sector number by 256 which is our sector size in bytes
isEnabled = false;
}
uint8_t EmuDisk::vhdMountDisk(uint8_t driveNum, std::string diskImageFilePath)
{
// If HDD image already mounted, close it and try to mount new one
if (emuDiskDrive[driveNum].imageMounted)
vhdEjectDisk(driveNum);
emuDiskDrive[driveNum].vhdImageFile = fopen(diskImageFilePath.c_str(), "rb+");
if (emuDiskDrive[driveNum].vhdImageFile == NULL)
return EMUDISK_ERROR_OPENING_DISK_IMAGE;
fseek(emuDiskDrive[driveNum].vhdImageFile, 0, SEEK_END);
emuDiskDrive[driveNum].diskImageFilesize = ftell(emuDiskDrive[driveNum].vhdImageFile);
emuDiskDrive[driveNum].imageMounted = true;
emuDiskDrive[driveNum].imgFilePathname = diskImageFilePath;
return EMUDISK_OPERATION_COMPLETE;
}
uint8_t EmuDisk::vhdEjectDisk(uint8_t driveNum)
{
if (!isEnabled)
return EMUDISK_ERROR_NOT_ENABLED;
if (!emuDiskDrive[driveNum].imageMounted)
return EMUDISK_ERROR_NO_DISK_MOUNTED;
fclose(emuDiskDrive[driveNum].vhdImageFile);
emuDiskDrive[driveNum].imgFilePathname.clear();
emuDiskDrive[driveNum].diskImageFilesize = 0;
emuDiskDrive[driveNum].imageMounted = false;
return EMUDISK_OPERATION_COMPLETE;
}
void EmuDisk::registerWrite(uint16_t regAddress, uint8_t paramByte)
{
switch (regAddress)
{
case 0xFF80:
// Logical Sector Number (1 of 3 bytes)
nextLogicalSector.highByte = paramByte;
break;
case 0xFF81:
// Logical Sector Number (2 of 3 bytes)
nextLogicalSector.middleByte = paramByte;
break;
case 0xFF82:
// Logical Sector Number (3 of 3 bytes)
nextLogicalSector.lowByte = paramByte;
break;
case 0xFF83:
// Command/Status Register
switch (paramByte)
{
case 0x00:
// Read Sector Command
statusCode = readSector();
break;
case 0x01:
// Write Sector Command
statusCode = writeSector();
break;
case 0x02:
// Close
break;
default:
statusCode = EMUDISK_STATUS_ERROR_INVALID_CMD;
break;
}
break;
case 0xFF84:
// Pointer to Read/Write Buffer
dataBufferPtr.highByte = paramByte;
break;
case 0xFF85:
dataBufferPtr.lowByte = paramByte;
break;
case 0xFF86:
vhdDriveNum = paramByte;
break;
}
}
uint8_t EmuDisk::readSector()
{
if (vhdDriveNum > 0x01)
return EMUDISK_STATUS_ERROR_INVALID_DRV_NUM; // Invalid Virtual HDD drive number
else if (!emuDiskDrive[vhdDriveNum].imageMounted)
return EMUDISK_STATUS_ERROR_NOT_ENABLED;
else
{
if (nextLogicalSector.byteOffset <= (emuDiskDrive[vhdDriveNum].diskImageFilesize - 256))
{
// Requested LSN is not greater than our filesize and therefore valid. Seek to it and grab the 256-byte sector from .VHD file
fseek(emuDiskDrive[vhdDriveNum].vhdImageFile, nextLogicalSector.byteOffset, SEEK_SET);
fread(§orBuffer, 1, 256, emuDiskDrive[vhdDriveNum].vhdImageFile);
snprintf(textBuffer, sizeof(textBuffer), "EmuDisk: Read from Logical Sector Number %02X%02X%02X", nextLogicalSector.highByte, nextLogicalSector.middleByte, nextLogicalSector.lowByte);
gimeBus->statusBarText = textBuffer;
// Now copy our populated internal sectorBuffer data to it's destination within CoCo memory space
for (uint16_t i = 0; i < 256; i++)
gimeBus->writePhysicalByte(dataBufferPtr.bufferPtr + i, sectorBuffer[i]);
}
else
{
// If the requested LSN does not exist within our .VHD file, return a zero-ed out sector (This is the behavoir i've observed MAME doing in this situation)
for (uint16_t i = 0; i < 256; i++)
gimeBus->writePhysicalByte(dataBufferPtr.bufferPtr + i, 0x00);
}
return EMUDISK_STATUS_SUCCESSFUL;
}
}
uint8_t EmuDisk::writeSector()
{
if (vhdDriveNum > 0x01)
return EMUDISK_STATUS_ERROR_INVALID_DRV_NUM; // Invalid Virtual HDD drive number
else if (!emuDiskDrive[vhdDriveNum].imageMounted)
return EMUDISK_STATUS_ERROR_NOT_ENABLED;
else
{
if (nextLogicalSector.byteOffset <= (emuDiskDrive[vhdDriveNum].diskImageFilesize - 256))
{
// First copy our source sector data from CoCo memory space to our temp sectorBuffer
for (uint16_t i = 0; i < 256; i++)
sectorBuffer[i] = gimeBus->readPhysicalByte(dataBufferPtr.bufferPtr + i);
// Requested LSN is not greater than our filesize and therefore valid. Seek to it's position and write the 256-byte sector to the .VHD file
fseek(emuDiskDrive[vhdDriveNum].vhdImageFile, nextLogicalSector.byteOffset, SEEK_SET);
fwrite(§orBuffer, 1, 256, emuDiskDrive[vhdDriveNum].vhdImageFile);
snprintf(textBuffer, sizeof(textBuffer), "EmuDisk: Wrote to Logical Sector Number %02X%02X%02X", nextLogicalSector.highByte, nextLogicalSector.middleByte, nextLogicalSector.lowByte);
gimeBus->statusBarText = textBuffer;
}
return EMUDISK_STATUS_SUCCESSFUL;
}
}