fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/drivers/block/blkpce.c *
7 * Created: 2004-11-28 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 "blkpce.h"
24
25#include <stdlib.h>
26#include <string.h>
27
28
29#define DSK_PCE_MAGIC 0x50494d47UL
30
31
32/*
33 * PCE image file format
34 *
35 * 0 4 Magic (PIMG)
36 * 4 4 version (0)
37 * 8 4 image offset
38 * 12 4 block count
39 * 16 4 cylinders
40 * 20 4 heads
41 * 24 4 sectors
42 * 28 4 block size
43 */
44
45
46static
47int dsk_pce_read (disk_t *dsk, void *buf, uint32_t i, uint32_t n)
48{
49 disk_pce_t *img;
50 uint64_t ofs, cnt;
51
52 img = dsk->ext;
53
54 if ((i + n) > img->dsk.blocks) {
55 return (1);
56 }
57
58 ofs = img->blk_ofs + 512 * (uint64_t) i;
59 cnt = 512 * (uint64_t) n;
60
61 if (dsk_read (img->fp, buf, ofs, cnt)) {
62 return (1);
63 }
64
65 return (0);
66}
67
68static
69int dsk_pce_write (disk_t *dsk, const void *buf, uint32_t i, uint32_t n)
70{
71 disk_pce_t *img;
72 uint64_t ofs, cnt;
73
74 img = dsk->ext;
75
76 if (dsk->readonly) {
77 return (1);
78 }
79
80 if ((i + n) > dsk->blocks) {
81 return (1);
82 }
83
84 ofs = img->blk_ofs + 512 * (uint64_t) i;
85 cnt = 512 * (uint64_t) n;
86
87 if (dsk_write (img->fp, buf, ofs, cnt)) {
88 return (1);
89 }
90
91 fflush (img->fp);
92
93 return (0);
94}
95
96
97static
98int dsk_pce_get_msg (disk_t *dsk, const char *msg, char *val, unsigned max)
99{
100 return (1);
101}
102
103static
104int dsk_pce_set_msg (disk_t *dsk, const char *msg, const char *val)
105{
106 if (strcmp (msg, "commit") == 0) {
107 return (0);
108 }
109
110 return (1);
111}
112
113
114static
115void dsk_pce_del (disk_t *dsk)
116{
117 disk_pce_t *img;
118
119 img = dsk->ext;
120
121 if (img->fp != NULL) {
122 fclose (img->fp);
123 }
124
125 free (img);
126}
127
128disk_t *dsk_pce_open_fp (FILE *fp, int ro)
129{
130 disk_pce_t *img;
131 uint32_t c, h, s, n;
132 unsigned char buf[32];
133
134 if (fread (buf, 1, 32, fp) != 32) {
135 return (NULL);
136 }
137
138 if (dsk_get_uint32_be (buf, 0) != DSK_PCE_MAGIC) {
139 return (NULL);
140 }
141
142 /* format version */
143 if (dsk_get_uint32_be (buf, 4) != 0) {
144 return (NULL);
145 }
146
147 if (dsk_get_uint32_be (buf, 28) != 512) {
148 return (NULL);
149 }
150
151 n = dsk_get_uint32_be (buf, 12);
152 c = dsk_get_uint32_be (buf, 16);
153 h = dsk_get_uint32_be (buf, 20);
154 s = dsk_get_uint32_be (buf, 24);
155
156 img = malloc (sizeof (disk_pce_t));
157 if (img == NULL) {
158 return (NULL);
159 }
160
161 dsk_init (&img->dsk, img, n, c, h, s);
162
163 dsk_set_type (&img->dsk, PCE_DISK_PCE);
164
165 dsk_set_readonly (&img->dsk, ro);
166
167 img->fp = fp;
168
169 img->dsk.del = dsk_pce_del;
170 img->dsk.read = dsk_pce_read;
171 img->dsk.write = dsk_pce_write;
172 img->dsk.get_msg = dsk_pce_get_msg;
173 img->dsk.set_msg = dsk_pce_set_msg;
174
175 img->blk_ofs = dsk_get_uint32_be (buf, 8);
176 img->blk_size = dsk_get_uint32_be (buf, 28);
177
178 return (&img->dsk);
179}
180
181disk_t *dsk_pce_open (const char *fname, int ro)
182{
183 disk_t *dsk;
184 FILE *fp;
185
186 if (ro) {
187 fp = fopen (fname, "rb");
188 }
189 else {
190 fp = fopen (fname, "r+b");
191
192 if (fp == NULL) {
193 fp = fopen (fname, "rb");
194 ro = 1;
195 }
196 }
197
198 if (fp == NULL) {
199 return (NULL);
200 }
201
202 dsk = dsk_pce_open_fp (fp, ro);
203
204 if (dsk == NULL) {
205 fclose (fp);
206 return (NULL);
207 }
208
209 dsk_set_fname (dsk, fname);
210
211 return (dsk);
212}
213
214int dsk_pce_create_fp (FILE *fp, uint32_t n, uint32_t c, uint32_t h, uint32_t s,
215 uint32_t ofs)
216{
217 unsigned char buf[32];
218
219 if (dsk_adjust_chs (&n, &c, &h, &s)) {
220 return (1);
221 }
222
223 if (ofs < 32) {
224 ofs = 512;
225 }
226
227 dsk_set_uint32_be (buf, 0, DSK_PCE_MAGIC);
228 dsk_set_uint32_be (buf, 4, 0);
229 dsk_set_uint32_be (buf, 8, ofs);
230 dsk_set_uint32_be (buf, 12, n);
231 dsk_set_uint32_be (buf, 16, c);
232 dsk_set_uint32_be (buf, 20, h);
233 dsk_set_uint32_be (buf, 24, s);
234 dsk_set_uint32_be (buf, 28, 512);
235
236 if (dsk_write (fp, buf, 0, 32)) {
237 return (1);
238 }
239
240 if (dsk_set_filesize (fp, ofs + 512 * (uint64_t) n)) {
241 buf[0] = 0;
242 if (dsk_write (fp, buf, ofs + 512 * (uint64_t) n - 1, 1)) {
243 return (1);
244 }
245 }
246
247 return (0);
248}
249
250int dsk_pce_create (const char *fname, uint32_t n, uint32_t c, uint32_t h, uint32_t s,
251 uint32_t ofs)
252{
253 int r;
254 FILE *fp;
255
256 fp = fopen (fname, "wb");
257 if (fp == NULL) {
258 return (1);
259 }
260
261 r = dsk_pce_create_fp (fp, n, c, h, s, ofs);
262
263 fclose (fp);
264
265 return (r);
266}
267
268int dsk_pce_probe_fp (FILE *fp)
269{
270 unsigned char buf[4];
271
272 if (dsk_read (fp, buf, 0, 4)) {
273 return (0);
274 }
275
276 if (dsk_get_uint32_be (buf, 0) != DSK_PCE_MAGIC) {
277 return (0);
278 }
279
280 return (1);
281}
282
283int dsk_pce_probe (const char *fname)
284{
285 int r;
286 FILE *fp;
287
288 fp = fopen (fname, "rb");
289
290 if (fp == NULL) {
291 return (0);
292 }
293
294 r = dsk_pce_probe_fp (fp);
295
296 fclose (fp);
297
298 return (r);
299}