fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 440 lines 9.7 kB view raw
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}