fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 227 lines 4.2 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/drivers/block/blkraw.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 "blkraw.h" 24 25#include <stdlib.h> 26 27 28static 29int dsk_img_read (disk_t *dsk, void *buf, uint32_t i, uint32_t n) 30{ 31 disk_img_t *img; 32 uint64_t ofs, cnt; 33 34 if ((i + n) > dsk->blocks) { 35 return (1); 36 } 37 38 img = dsk->ext; 39 40 ofs = img->start + 512 * (uint64_t) i; 41 cnt = 512 * (uint64_t) n; 42 43 if (dsk_read (img->fp, buf, ofs, cnt)) { 44 return (1); 45 } 46 47 return (0); 48} 49 50static 51int dsk_img_write (disk_t *dsk, const void *buf, uint32_t i, uint32_t n) 52{ 53 disk_img_t *img; 54 uint64_t ofs, cnt; 55 56 if (dsk->readonly) { 57 return (1); 58 } 59 60 if ((i + n) > dsk->blocks) { 61 return (1); 62 } 63 64 img = dsk->ext; 65 66 ofs = img->start + 512 * (uint64_t) i; 67 cnt = 512 * (uint64_t) n; 68 69 if (dsk_write (img->fp, buf, ofs, cnt)) { 70 return (1); 71 } 72 73 fflush (img->fp); 74 75 return (0); 76} 77 78static 79void dsk_img_del (disk_t *dsk) 80{ 81 disk_img_t *img; 82 83 img = dsk->ext; 84 85 fclose (img->fp); 86 free (img); 87} 88 89static 90disk_t *dsk_img_open_size (FILE *fp, uint32_t n, uint64_t ofs, int ro) 91{ 92 disk_img_t *img; 93 94 img = malloc (sizeof (disk_img_t)); 95 96 if (img == NULL) { 97 return (NULL); 98 } 99 100 dsk_init (&img->dsk, img, n, 0, 0, 0); 101 102 dsk_set_type (&img->dsk, PCE_DISK_RAW); 103 104 dsk_set_readonly (&img->dsk, ro); 105 106 img->dsk.del = dsk_img_del; 107 img->dsk.read = dsk_img_read; 108 img->dsk.write = dsk_img_write; 109 110 img->start = ofs; 111 112 img->fp = fp; 113 114 return (&img->dsk); 115} 116 117disk_t *dsk_img_open_fp (FILE *fp, uint64_t ofs, int ro) 118{ 119 uint64_t cnt; 120 disk_t *dsk; 121 122 if (dsk_get_filesize (fp, &cnt)) { 123 return (NULL); 124 } 125 126 if (cnt <= ofs) { 127 return (NULL); 128 } 129 130 cnt = (cnt - ofs) / 512; 131 132 if (cnt == 0) { 133 return (NULL); 134 } 135 136 dsk = dsk_img_open_size (fp, cnt, ofs, ro); 137 138 if (dsk == NULL) { 139 return (NULL); 140 } 141 142 dsk_guess_geometry (dsk); 143 144 return (dsk); 145} 146 147disk_t *dsk_img_open (const char *fname, uint64_t ofs, int ro) 148{ 149 disk_t *dsk; 150 FILE *fp; 151 152 if (ro) { 153 fp = fopen (fname, "rb"); 154 } 155 else { 156 fp = fopen (fname, "r+b"); 157 158 if (fp == NULL) { 159 fp = fopen (fname, "rb"); 160 ro = 1; 161 } 162 } 163 164 if (fp == NULL) { 165 return (NULL); 166 } 167 168 dsk = dsk_img_open_fp (fp, ofs, ro); 169 170 if (dsk == NULL) { 171 fclose (fp); 172 return (NULL); 173 } 174 175 dsk_set_fname (dsk, fname); 176 177 return (dsk); 178} 179 180void dsk_img_set_offset (disk_t *dsk, uint64_t ofs) 181{ 182 disk_img_t *img; 183 184 img = dsk->ext; 185 186 img->start = ofs; 187} 188 189int dsk_img_create_fp (FILE *fp, uint32_t n, uint64_t ofs) 190{ 191 uint64_t cnt; 192 unsigned char buf; 193 194 cnt = 512 * (uint64_t) n; 195 196 if (cnt == 0) { 197 return (1); 198 } 199 200 buf = 0; 201 202 if (dsk_set_filesize (fp, ofs + cnt)) { 203 if (dsk_write (fp, &buf, ofs + cnt - 1, 1)) { 204 return (1); 205 } 206 } 207 208 return (0); 209} 210 211int dsk_img_create (const char *fname, uint32_t n, uint64_t ofs) 212{ 213 int r; 214 FILE *fp; 215 216 fp = fopen (fname, "wb"); 217 218 if (fp == NULL) { 219 return (1); 220 } 221 222 r = dsk_img_create_fp (fp, n, ofs); 223 224 fclose (fp); 225 226 return (r); 227}