OSDN Git Service

[VM][General] Merge Upstream 20180530.
[csp-qt/common_source_project-fm7.git] / source / src / vm / harddisk.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2006.09.16-
6
7         [ d88 handler ]
8 */
9
10 #include "harddisk.h"
11 #include "../fileio.h"
12
13 void HARDDISK::open(const _TCHAR* file_path, int default_sector_size)
14 {
15         uint8_t header[512];
16         pair_t tmp;
17         
18         close();
19         
20         if(FILEIO::IsFileExisting(file_path)) {
21                 fio = new FILEIO();
22                 
23                 if(fio->Fopen(file_path, FILEIO_READ_WRITE_BINARY)) {
24                         // from NP2 sxsihdd.c
25                         const char sig_vhd[8] = "VHD1.00";
26                         const char sig_nhd[15] = "T98HDDIMAGE.R0";
27                         
28                         fio->Fread(header, 256, 1);
29                         
30                         if(check_file_extension(file_path, _T(".thd"))) {
31                                 // T98
32 /*
33                                 typedef struct thd_header_s {
34                                         int16_t cylinders;
35                                 } thd_header_s;
36 */
37                                 header_size = 256;
38                                 tmp.read_2bytes_le_from(header + 0);
39                                 int cylinders = tmp.sd;
40                                 surfaces = 8;
41                                 int sectors = 33;
42                                 sector_size = 256;
43                                 sector_num = cylinders * surfaces * sectors;
44                         } else if(check_file_extension(file_path, _T(".nhd")) && memcmp(header, sig_nhd, 15) == 0) {
45                                 // T98Next
46 /*
47                                 typedef struct nhd_header_s {
48                                         char sig[16];
49                                         char comment[256];
50                                         int32_t header_size;    // +272
51                                         int32_t cylinders;      // +276
52                                         int16_t surfaces;       // +280
53                                         int16_t sectors;        // +282
54                                         int16_t sector_size;    // +284
55                                         uint8_t reserved[0xe2];
56                                 } nhd_header_t;
57 */
58                                 tmp.read_4bytes_le_from(header + 272);
59                                 header_size = tmp.sd;
60                                 tmp.read_4bytes_le_from(header + 276);
61                                 int cylinders = tmp.sd;
62                                 tmp.read_2bytes_le_from(header + 280);
63                                 surfaces = tmp.sd;
64                                 tmp.read_2bytes_le_from(header + 282);
65                                 int sectors = tmp.sd;
66                                 tmp.read_2bytes_le_from(header + 284);
67                                 sector_size = tmp.sd;
68                                 sector_num = cylinders * surfaces * sectors;
69                         } else if(check_file_extension(file_path, _T(".hdi"))) {
70                                 // ANEX86
71 /*
72                                 typedef struct hdi_header_s {
73                                         int32_t dummy;          // + 0
74                                         int32_t hdd_type;       // + 4
75                                         int32_t header_size;    // + 8
76                                         int32_t hdd_size;       // +12
77                                         int32_t sector_size;    // +16
78                                         int32_t sectors;        // +20
79                                         int32_t surfaces;       // +24
80                                         int32_t cylinders;      // +28
81                                 } hdi_header_t;
82 */
83                                 tmp.read_4bytes_le_from(header + 8);
84                                 header_size = tmp.sd;
85                                 tmp.read_4bytes_le_from(header + 16);
86                                 sector_size = tmp.sd;
87                                 tmp.read_4bytes_le_from(header + 20);
88                                 int sectors = tmp.sd;
89                                 tmp.read_4bytes_le_from(header + 24);
90                                 surfaces = tmp.sd;
91                                 tmp.read_4bytes_le_from(header + 28);
92                                 int cylinders = tmp.sd;
93                                 sector_num = cylinders * surfaces * sectors;
94                         } else if(check_file_extension(file_path, _T(".hdd")) && memcmp(header, sig_vhd, 5) == 0) {
95                                 // Virtual98
96 /*
97                                 typedef struct {
98                                         char    sig[3];         // +  0
99                                         char    ver[4];         // +  3
100                                         char    delimita;       // +  7
101                                         char    comment[128];   // +  8
102                                         uint8_t pad1[4];        // +136
103                                         int16_t mbsize;         // +140
104                                         int16_t sectorsize;     // +142
105                                         uint8_t sectors;        // +144
106                                         uint8_t surfaces;       // +145
107                                         int16_t cylinders;      // +146
108                                         int32_t totals;         // +148
109                                         uint8_t pad2[0x44];     // +152
110                                 } virtual98_header_t;
111 */
112                                 header_size = 288;
113                                 tmp.read_2bytes_le_from(header + 142);
114                                 sector_size = tmp.sd;
115 //                              int sectors = header[144];
116                                 surfaces = header[145];
117 //                              tmp.read_2bytes_le_from(header + 146);
118 //                              int cylinders = tmp.sd;
119                                 tmp.read_4bytes_le_from(header + 148);
120                                 sector_num = tmp.sd;
121 //                              sector_num = cylinders * surfaces * sectors;
122                         } else {
123                                 // solid
124                                 header_size = 0;
125                                 // sectors = 33, surfaces = 4, cylinders = 153, sector_size = 256       // 5MB
126                                 // sectors = 33, surfaces = 4, cylinders = 310, sector_size = 256       // 10MB
127                                 surfaces = (default_sector_size == 256 && fio->FileLength() <= 33 * 4 * 310 * 256) ? 4 : 8;
128                                 sector_size = default_sector_size;
129                                 sector_num = fio->FileLength() / sector_size;
130                         }
131                 }
132         }
133 }
134
135 void HARDDISK::close()
136 {
137         // write disk image
138         if(fio != NULL) {
139                 if(fio->IsOpened()) {
140                         fio->Fclose();
141                 }
142                 delete fio;
143                 fio = NULL;
144         }
145 }
146
147 bool HARDDISK::mounted()
148 {
149         return (fio != NULL && fio->IsOpened());
150 }
151
152 bool HARDDISK::accessed()
153 {
154         bool value = access;
155         access = false;
156         return value;
157 }
158
159 bool HARDDISK::read_buffer(long position, int length, uint8_t *buffer)
160 {
161         if(mounted()) {
162                 if(fio->Fseek(header_size + position, FILEIO_SEEK_SET) == 0) {
163                         access = true;
164                         return (fio->Fread(buffer, length, 1) == 1);
165                 }
166         }
167         return false;
168 }
169
170 bool HARDDISK::write_buffer(long position, int length, uint8_t *buffer)
171 {
172         if(mounted()) {
173                 if(fio->Fseek(header_size + position, FILEIO_SEEK_SET) == 0) {
174                         access = true;
175                         return (fio->Fwrite(buffer, length, 1) == 1);
176                 }
177         }
178         return false;
179 }
180
181 /*
182 #define STATE_VERSION   1
183
184 void HARDDISK::save_state(FILEIO* state_fio)
185 {
186         state_fio->FputUint32(STATE_VERSION);
187         
188         state_fio->Fwrite(image_path, sizeof(image_path), 1);
189         if(mounted()) {
190                 uint8_t *buffer = (uint8_t *)malloc(0x100000); // 1MB
191                 long remain = fio->FileLength();
192                 state_fio->FputInt32(remain);
193                 fio->Fseek(0, FILEIO_SEEK_SET);
194                 while(remain > 0) {
195                         long size = min(remain, 0x100000);
196                         fio->Fread(buffer, size, 1);
197                         state_fio->Fwrite(buffer, size, 1);
198                         remain -= size;
199                 }
200                 free(buffer);
201         } else {
202                 state_fio->FputInt32(0);
203         }
204         state_fio->FputInt32(header_size);
205 //      state_fio->FputInt32(cylinders);
206         state_fio->FputInt32(surfaces);
207 //      state_fio->FputInt32(sectors);
208         state_fio->FputInt32(sector_size);
209         state_fio->FputInt32(sector_num);
210 }
211
212 bool HARDDISK::load_state(FILEIO* state_fio)
213 {
214         close();
215         
216         if(state_fio->FgetUint32() != STATE_VERSION) {
217                 return false;
218         }
219         state_fio->Fread(image_path, sizeof(image_path), 1);
220         long remain = state_fio->FgetInt32();
221         if(remain > 0) {
222                 fio = new FILEIO();
223                 if(!fio->Fopen(image_path, FILEIO_READ_WRITE_NEW_BINARY)) {
224                         if(check_file_extension(image_path, _T(".thd"))) {
225                                 create_local_path(image_path, _MAX_PATH, _T("temporary_saved_hard_disk_#%d.thd"), drive_num);
226                         } else if(check_file_extension(image_path, _T(".nhd"))) {
227                                 create_local_path(image_path, _MAX_PATH, _T("temporary_saved_hard_disk_#%d.nhd"), drive_num);
228                         } else if(check_file_extension(image_path, _T(".hdi"))) {
229                                 create_local_path(image_path, _MAX_PATH, _T("temporary_saved_hard_disk_#%d.hdi"), drive_num);
230                         } else {
231                                 create_local_path(image_path, _MAX_PATH, _T("temporary_saved_hard_disk_#%d.dat"), drive_num);
232                         }
233                         fio->Fopen(image_path, FILEIO_READ_WRITE_NEW_BINARY);
234                 }
235                 if(fio->IsOpened()) {
236                         uint8_t *buffer = (uint8_t *)malloc(0x100000); // 1MB
237                         fio->Fseek(0, FILEIO_SEEK_SET);
238                         while(remain > 0) {
239                                 long size = min(remain, 0x100000);
240                                 state_fio->Fread(buffer, size, 1);
241                                 fio->Fwrite(buffer, size, 1);
242                                 remain -= size;
243                         }
244                         free(buffer);
245                 } else {
246                         state_fio->Fseek(remain, FILEIO_SEEK_CUR);
247                 }
248         }
249         header_size = state_fio->FgetInt32();
250 //      cylinders = state_fio->FgetInt32();
251         surfaces = state_fio->FgetInt32();
252 //      sectors = state_fio->FgetInt32();
253         sector_size = state_fio->FgetInt32();
254         sector_num = state_fio->FgetInt32();
255         return true;
256 }
257 */