fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
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}