fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 253 lines 4.8 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/drivers/block/blkdosem.c * 7 * Created: 2004-09-17 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2004-2012 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 "blkdosem.h" 24 25#include <stdlib.h> 26#include <string.h> 27 28 29static 30int dsk_dosemu_read (disk_t *dsk, void *buf, uint32_t i, uint32_t n) 31{ 32 disk_dosemu_t *img; 33 uint64_t ofs, cnt; 34 35 if ((i + n) > dsk->blocks) { 36 return (1); 37 } 38 39 img = dsk->ext; 40 41 ofs = img->start + 512 * (uint64_t) i; 42 cnt = 512 * (uint64_t) n; 43 44 if (dsk_read (img->fp, buf, ofs, cnt)) { 45 return (1); 46 } 47 48 return (0); 49} 50 51static 52int dsk_dosemu_write (disk_t *dsk, const void *buf, uint32_t i, uint32_t n) 53{ 54 disk_dosemu_t *img; 55 uint64_t ofs, cnt; 56 57 if (dsk->readonly) { 58 return (1); 59 } 60 61 if ((i + n) > dsk->blocks) { 62 return (1); 63 } 64 65 img = dsk->ext; 66 67 ofs = img->start + 512 * (uint64_t) i; 68 cnt = 512 * (uint64_t) n; 69 70 if (dsk_write (img->fp, buf, ofs, cnt)) { 71 return (1); 72 } 73 74 fflush (img->fp); 75 76 return (0); 77} 78 79static 80void dsk_dosemu_del (disk_t *dsk) 81{ 82 disk_dosemu_t *img; 83 84 img = dsk->ext; 85 86 fclose (img->fp); 87 free (img); 88} 89 90disk_t *dsk_dosemu_open_fp (FILE *fp, int ro) 91{ 92 disk_dosemu_t *img; 93 unsigned char buf[32]; 94 uint32_t c, h, s; 95 uint64_t start; 96 97 if (dsk_read (fp, buf, 0, 23)) { 98 return (NULL); 99 } 100 101 if (memcmp (buf, "DOSEMU\x00", 7) != 0) { 102 return (NULL); 103 } 104 105 c = dsk_get_uint32_le (buf, 15); 106 h = dsk_get_uint32_le (buf, 7); 107 s = dsk_get_uint32_le (buf, 11); 108 start = dsk_get_uint32_le (buf, 19); 109 110 if (start < 23) { 111 return (NULL); 112 } 113 114 img = malloc (sizeof (disk_dosemu_t)); 115 if (img == NULL) { 116 return (NULL); 117 } 118 119 dsk_init (&img->dsk, img, 0, c, h, s); 120 121 dsk_set_type (&img->dsk, PCE_DISK_DOSEMU); 122 123 dsk_set_readonly (&img->dsk, ro); 124 125 img->dsk.del = dsk_dosemu_del; 126 img->dsk.read = dsk_dosemu_read; 127 img->dsk.write = dsk_dosemu_write; 128 129 img->start = start; 130 131 img->fp = fp; 132 133 return (&img->dsk); 134} 135 136disk_t *dsk_dosemu_open (const char *fname, int ro) 137{ 138 disk_t *dsk; 139 FILE *fp; 140 141 if (ro) { 142 fp = fopen (fname, "rb"); 143 } 144 else { 145 fp = fopen (fname, "r+b"); 146 147 if (fp == NULL) { 148 fp = fopen (fname, "rb"); 149 ro = 1; 150 } 151 } 152 153 if (fp == NULL) { 154 return (NULL); 155 } 156 157 dsk = dsk_dosemu_open_fp (fp, ro); 158 159 if (dsk == NULL) { 160 fclose (fp); 161 return (NULL); 162 } 163 164 dsk_set_fname (dsk, fname); 165 166 return (dsk); 167} 168 169int dsk_dosemu_create_fp (FILE *fp, uint32_t c, uint32_t h, uint32_t s, 170 uint32_t ofs) 171{ 172 uint64_t cnt; 173 unsigned char buf[32]; 174 175 cnt = 512 * (uint64_t) c * (uint64_t) h * (uint64_t) s; 176 177 if (cnt == 0) { 178 return (1); 179 } 180 181 if (ofs < 23) { 182 ofs = 128; 183 } 184 185 memcpy (buf, "DOSEMU\x00", 7); 186 187 dsk_set_uint32_le (buf, 7, h); 188 dsk_set_uint32_le (buf, 11, s); 189 dsk_set_uint32_le (buf, 15, c); 190 dsk_set_uint32_le (buf, 19, ofs); 191 192 if (dsk_write (fp, buf, 0, 23)) { 193 return (1); 194 } 195 196 buf[0] = 0; 197 if (dsk_write (fp, buf, ofs + cnt - 1, 1)) { 198 return (1); 199 } 200 201 return (0); 202} 203 204int dsk_dosemu_create (const char *fname, uint32_t c, uint32_t h, uint32_t s, 205 uint32_t ofs) 206{ 207 int r; 208 FILE *fp; 209 210 fp = fopen (fname, "w+b"); 211 if (fp == NULL) { 212 return (1); 213 } 214 215 r = dsk_dosemu_create_fp (fp, c, h, s, ofs); 216 217 fclose (fp); 218 219 return (r); 220} 221 222int dsk_dosemu_probe_fp (FILE *fp) 223{ 224 unsigned char buf[8]; 225 226 if (dsk_read (fp, buf, 0, 8)) { 227 return (0); 228 } 229 230 if (memcmp (buf, "DOSEMU\x00", 7) != 0) { 231 return (0); 232 } 233 234 return (1); 235} 236 237int dsk_dosemu_probe (const char *fname) 238{ 239 int r; 240 FILE *fp; 241 242 fp = fopen (fname, "rb"); 243 244 if (fp == NULL) { 245 return (0); 246 } 247 248 r = dsk_dosemu_probe_fp (fp); 249 250 fclose (fp); 251 252 return (r); 253}