fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/lib/inidsk.c *
7 * Created: 2004-12-13 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2004-2025 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22
23#include <config.h>
24
25#include <stdlib.h>
26#include <string.h>
27
28#include <lib/inidsk.h>
29#include <lib/log.h>
30#include <lib/path.h>
31#include <lib/sysdep.h>
32
33#include <drivers/block/blkchd.h>
34#include <drivers/block/blkcow.h>
35#include <drivers/block/blkdosem.h>
36#include <drivers/block/blkpart.h>
37#include <drivers/block/blkpbi.h>
38#include <drivers/block/blkpce.h>
39#include <drivers/block/blkpri.h>
40#include <drivers/block/blkpsi.h>
41#include <drivers/block/blkqed.h>
42#include <drivers/block/blkram.h>
43#include <drivers/block/blkraw.h>
44#include <drivers/pri/pri-img.h>
45#include <drivers/psi/psi-img.h>
46
47
48int dsk_insert (disks_t *dsks, const char *str, int eject)
49{
50 unsigned i;
51 unsigned drv;
52 char buf[16];
53 disk_t *dsk;
54 char *path;
55
56 i = 0;
57 while ((i < 16) && (str[i] != 0)) {
58 if (str[i] == ':') {
59 buf[i] = 0;
60 break;
61 }
62
63 buf[i] = str[i];
64
65 i += 1;
66 }
67
68 if ((i >= 16) || (i == 0) || (str[i] == 0)) {
69 return (1);
70 }
71
72 drv = strtoul (buf, NULL, 0);
73 str = str + i + 1;
74
75 path = pce_path_get (str);
76
77 dsk = dsk_auto_open (path, 0, 0);
78 if (dsk == NULL) {
79 free (path);
80 return (1);
81 }
82
83 free (path);
84
85 dsk_set_drive (dsk, drv);
86
87 if (eject) {
88 disk_t *old;
89
90 old = dsks_get_disk (dsks, drv);
91 if (old != NULL) {
92 dsks_rmv_disk (dsks, old);
93 dsk_del (old);
94 }
95 }
96
97 if (dsks_add_disk (dsks, dsk)) {
98 dsk_del (dsk);
99 return (1);
100 }
101
102 return (0);
103}
104
105disk_t *ini_get_cow (ini_sct_t *sct, disk_t *dsk)
106{
107 disk_t *cow;
108 ini_val_t *val;
109 const char *cname;
110
111 val = NULL;
112 while ((val = ini_next_val (sct, val, "cow")) != NULL) {
113 cname = ini_val_get_str (val);
114 if (cname == NULL) {
115 dsk_del (dsk);
116 return (NULL);
117 }
118
119 if (pce_file_exists (cname) == 0) {
120 cow = dsk_create_cow (dsk, cname, 16384);
121 }
122 else {
123 cow = dsk_open_cow (dsk, cname);
124 }
125
126 if (cow == NULL) {
127 pce_log_tag (MSG_ERR,
128 "DISK:", "*** cow failed (drive=%u file=%s)\n",
129 dsk_get_drive (dsk), cname
130 );
131
132 dsk_del (dsk);
133
134 return (NULL);
135 }
136 else {
137 dsk_set_readonly (cow, 0);
138
139 dsk = cow;
140 }
141
142 pce_log_tag (MSG_INF,
143 "DISK:", "drive=%u type=cow file=%s\n",
144 dsk_get_drive (dsk), cname
145 );
146 }
147
148 return (dsk);
149}
150
151static
152void ini_get_vchs (ini_sct_t *sct, disk_t *dsk)
153{
154 unsigned long vc, vh, vs;
155
156 ini_get_uint32 (sct, "visible_c", &vc, 0);
157 ini_get_uint32 (sct, "visible_h", &vh, 0);
158 ini_get_uint32 (sct, "visible_s", &vs, 0);
159
160 vc = (vc == 0) ? dsk->c : vc;
161 vh = (vh == 0) ? dsk->h : vh;
162 vs = (vs == 0) ? dsk->s : vs;
163
164 dsk_set_visible_chs (dsk, vc, vh, vs);
165
166 if ((dsk->c != vc) || (dsk->h != vh) || (dsk->s != vs)) {
167 pce_log_tag (MSG_INF,
168 "DISK:", "drive=%u vchs=%lu/%lu/%lu\n",
169 dsk_get_drive (dsk),
170 (unsigned long) dsk->visible_c,
171 (unsigned long) dsk->visible_h,
172 (unsigned long) dsk->visible_s
173 );
174 }
175}
176
177static
178disk_t *ini_get_disk_part (ini_sct_t *sct,
179 unsigned long c, unsigned long h, unsigned long s, int ro)
180{
181 disk_t *dsk;
182 ini_sct_t *p;
183 unsigned long start;
184 unsigned long blk_i, blk_n;
185 const char *fname;
186 char *path;
187
188 dsk = dsk_part_open (c, h, s, ro);
189
190 if (dsk == NULL) {
191 return (NULL);
192 }
193
194 p = NULL;
195 while ((p = ini_next_sct (sct, p, "partition")) != NULL) {
196 ini_get_uint32 (p, "offset", &start, 0);
197 ini_get_uint32 (p, "block_start", &blk_i, 0);
198 ini_get_uint32 (p, "block_count", &blk_n, 0);
199 ini_get_string (p, "file", &fname, NULL);
200 ini_get_bool (p, "readonly", &ro, 0);
201
202 if (fname == NULL) {
203 dsk_del (dsk);
204 return (NULL);
205 }
206
207 path = pce_path_get (fname);
208
209 if (dsk_part_add_partition (dsk, path, start, blk_i, blk_n, ro)) {
210 free (path);
211 dsk_del (dsk);
212 return (NULL);
213 }
214
215 free (path);
216 }
217
218 return (dsk);
219}
220
221int ini_get_disk (ini_sct_t *sct, disk_t **ret)
222{
223 disk_t *dsk;
224 ini_val_t *val;
225 FILE *fp;
226 unsigned drive;
227 unsigned long c, h, s, n;
228 unsigned long ofs;
229 int ro;
230 int optional;
231 const char *type, *fname;
232 char *path;
233
234 ini_get_uint16 (sct, "drive", &drive, 0);
235 ini_get_string (sct, "type", &type, "auto");
236 ini_get_uint32 (sct, "offset", &ofs, 0);
237
238 ini_get_uint32 (sct, "c", &c, 0);
239 ini_get_uint32 (sct, "h", &h, 0);
240 ini_get_uint32 (sct, "s", &s, 0);
241
242 if (ini_get_uint32 (sct, "blocks", &n, 0) == 0) {
243 ;
244 }
245 else if (ini_get_uint32 (sct, "size", &n, 0) == 0) {
246 n = n & ~511UL;
247 }
248 else if (ini_get_uint32 (sct, "sizek", &n, 0) == 0) {
249 n = 2 * n;
250 }
251 else if (ini_get_uint32 (sct, "sizem", &n, 0) == 0) {
252 n = 2048 * n;
253 }
254 else if (ini_get_uint32 (sct, "sizeg", &n, 0) == 0) {
255 n = 2048UL * 1024UL * n;
256 }
257 else {
258 n = 0;
259 }
260
261 ini_get_bool (sct, "readonly", &ro, 0);
262 ini_get_bool (sct, "optional", &optional, 0);
263
264 val = NULL;
265 dsk = NULL;
266 path = NULL;
267
268 while ((val = ini_next_val (sct, val, "file")) != NULL) {
269 fname = ini_val_get_str (val);
270
271 if (fname == NULL) {
272 continue;
273 }
274
275 free (path);
276 path = pce_path_get (fname);
277
278 if (path == NULL) {
279 continue;
280 }
281
282 fp = fopen (path, "rb");
283
284 if (fp == NULL) {
285 continue;
286 }
287
288 fclose (fp);
289
290 if (strcmp (type, "auto") == 0) {
291 dsk = dsk_auto_open (path, ofs, ro);
292 }
293 else if (strcmp (type, "ram") == 0) {
294 dsk = dsk_ram_open (path, n, c, h, s, ro);
295 }
296 else if (strcmp (type, "image") == 0) {
297 dsk = dsk_img_open (path, ofs, ro);
298 }
299 else if (strcmp (type, "dosemu") == 0) {
300 dsk = dsk_dosemu_open (path, ro);
301 }
302 else if (strcmp (type, "pbi") == 0) {
303 dsk = dsk_pbi_open (path, ro);
304 }
305 else if (strcmp (type, "pce") == 0) {
306 dsk = dsk_pce_open (path, ro);
307 }
308 else if (strcmp (type, "qed") == 0) {
309 dsk = dsk_qed_open (path, ro);
310 }
311 else if (strcmp (type, "chd") == 0) {
312 dsk = dsk_chd_open (path, ro);
313 }
314 else if (strcmp (type, "partition") == 0) {
315 dsk = ini_get_disk_part (sct, c, h, s, ro);
316 }
317 else if (strcmp (type, "anadisk") == 0) {
318 dsk = dsk_psi_open (path, PSI_FORMAT_ANADISK, ro);
319 }
320 else if (strcmp (type, "cp2") == 0) {
321 dsk = dsk_psi_open (path, PSI_FORMAT_CP2, ro);
322 }
323 else if (strcmp (type, "dc42") == 0) {
324 dsk = dsk_psi_open (path, PSI_FORMAT_DC42, ro);
325 }
326 else if (strcmp (type, "imagedisk") == 0) {
327 dsk = dsk_psi_open (path, PSI_FORMAT_IMD, ro);
328 }
329 else if (strcmp (type, "imd") == 0) {
330 dsk = dsk_psi_open (path, PSI_FORMAT_IMD, ro);
331 }
332 else if (strcmp (type, "pfdc") == 0) {
333 dsk = dsk_psi_open (path, PSI_FORMAT_PFDC, ro);
334 }
335 else if (strcmp (type, "pfdc-auto") == 0) {
336 dsk = dsk_psi_open (path, PSI_FORMAT_NONE, ro);
337 }
338 else if (strcmp (type, "pri") == 0) {
339 dsk = dsk_pri_open (path, PRI_FORMAT_PRI, ro);
340 }
341 else if (strcmp (type, "psi") == 0) {
342 dsk = dsk_psi_open (path, PSI_FORMAT_PSI, ro);
343 }
344 else if (strcmp (type, "tc") == 0) {
345 dsk = dsk_pri_open (path, PRI_FORMAT_TC, ro);
346 }
347 else if (strcmp (type, "teledisk") == 0) {
348 dsk = dsk_psi_open (path, PSI_FORMAT_TD0, ro);
349 }
350 else if (strcmp (type, "woz") == 0) {
351 dsk = dsk_pri_open (path, PRI_FORMAT_WOZ, ro);
352 }
353
354 if (dsk != NULL) {
355 break;
356 }
357 }
358
359 if (dsk == NULL) {
360 *ret = NULL;
361
362 free (path);
363
364 if (optional == 0) {
365 pce_log (MSG_ERR, "*** loading drive 0x%02x failed\n", drive);
366 return (1);
367 }
368
369 return (0);
370 }
371
372 dsk_set_drive (dsk, drive);
373
374 if ((c != 0) || (h != 0) || (s != 0)) {
375 dsk_set_geometry (dsk, dsk_get_block_cnt (dsk), c, h, s);
376 }
377
378 pce_log_tag (MSG_INF,
379 "DISK:", "drive=%u type=%s blocks=%lu chs=%lu/%lu/%lu %s file=%s\n",
380 drive, type,
381 (unsigned long) dsk->blocks,
382 (unsigned long) dsk->c,
383 (unsigned long) dsk->h,
384 (unsigned long) dsk->s,
385 (ro ? "ro" : "rw"),
386 (path != NULL) ? path : "<>"
387 );
388
389 free (path);
390
391 ini_get_vchs (sct, dsk);
392
393 dsk = ini_get_cow (sct, dsk);
394
395 if (dsk == NULL) {
396 *ret = NULL;
397
398 if (optional == 0) {
399 pce_log (MSG_ERR,
400 "*** loading drive 0x%02x failed (cow)\n",
401 drive
402 );
403
404 return (1);
405 }
406
407 return (0);
408 }
409
410 *ret = dsk;
411
412 return (0);
413}
414
415disks_t *ini_get_disks (ini_sct_t *ini)
416{
417 ini_sct_t *sct;
418 disk_t *dsk;
419 disks_t *dsks;
420 unsigned drive;
421
422 dsks = dsks_new();
423
424 sct = NULL;
425 while ((sct = ini_next_sct (ini, sct, "disk")) != NULL) {
426 ini_get_uint16 (sct, "drive", &drive, 0);
427
428 if (dsks_get_disk (dsks, drive) != NULL) {
429 continue;
430 }
431
432 if (ini_get_disk (sct, &dsk) == 0) {
433 if (dsk != NULL) {
434 dsks_add_disk (dsks, dsk);
435 }
436 }
437 }
438
439 return (dsks);
440}