1 /*****************************************************************************
2 ** $Source: /cygdrive/d/Private/_SVNROOT/bluemsx/blueMSX/Src/IoDevice/DirAsDisk.c,v $
3 **
4 ** $Revision: 1.15 $
5 **
6 ** $Date: 2008-06-24 20:10:38 $
7 **
8 ** More info: http://www.bluemsx.com
9 **
10 ** Copyright (C) 2003-2007 Daniel Vik, Tomas Karlsson
11 **
12 ** This program is free software; you can redistribute it and/or modify
13 ** it under the terms of the GNU General Public License as published by
14 ** the Free Software Foundation; either version 2 of the License, or
15 ** (at your option) any later version.
16 **
17 ** This program is distributed in the hope that it will be useful,
18 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ** GNU General Public License for more details.
21 **
22 ** You should have received a copy of the GNU General Public License
23 ** along with this program; if not, write to the Free Software
24 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 **
26 ******************************************************************************
27 */
28 #define USE_ARCH_GLOB
29
30 #include "DirAsDisk.h"
31
32 #pragma warning(disable: 4996)
33 #if defined(WIN32) || defined (WINDOWS_HOST)
34 #include <io.h> // not on Linux
35 #endif
36
37 #ifdef _WIN32
38 #include <direct.h>
39 #else
40 #include <unistd.h>
41 #endif
42
43 #include <fcntl.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <stdlib.h>
47 #include <math.h>
48 #include <string.h>
49 #include <stdio.h>
50 #include <time.h>
51 #include <ctype.h>
52 #ifdef USE_ARCH_GLOB
53 #include "ArchGlob.h"
54 #else
55 #include <windows.h>
56 #endif
57
58 #if defined(WIN32) || defined (WINDOWS_HOST)
59 #include <io.h>
60 #else
61 #ifndef O_BINARY
62 #define O_BINARY 0
63 #endif
64 #endif
65
66 static const unsigned char msxboot[] = {
67 0xeb,0xfe,0x90,0x44,0x53,0x4b,0x54,0x4f,
68 0x4f,0x4c,0x20,0x00,0x02,0x02,0x01,0x00,
69 0x02,0x70,0x00,0xa0,0x05,0xf9,0x03,0x00,
70 0x09,0x00,0x02,0x00,0x00,0x00,0xd0,0xed,
71 0x53,0x59,0xc0,0x32,0xc4,0xc0,0x36,0x56,
72 0x23,0x36,0xc0,0x31,0x1f,0xf5,0x11,0x79,
73 0xc0,0x0e,0x0f,0xcd,0x7d,0xf3,0x3c,0xca,
74 0x63,0xc0,0x11,0x00,0x01,0x0e,0x1a,0xcd,
75 0x7d,0xf3,0x21,0x01,0x00,0x22,0x87,0xc0,
76 0x21,0x00,0x3f,0x11,0x79,0xc0,0x0e,0x27,
77 0xcd,0x7d,0xf3,0xc3,0x00,0x01,0x58,0xc0,
78 0xcd,0x00,0x00,0x79,0xe6,0xfe,0xfe,0x02,
79 0xc2,0x6a,0xc0,0x3a,0xc4,0xc0,0xa7,0xca,
80 0x22,0x40,0x11,0x9e,0xc0,0x0e,0x09,0xcd,
81 0x7d,0xf3,0x0e,0x07,0xcd,0x7d,0xf3,0x18,
82 0xb2,0x00,0x4d,0x53,0x58,0x44,0x4f,0x53,
83 0x20,0x20,0x53,0x59,0x53,0x00,0x00,0x00,
84 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
85 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
86 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x6f,
87 0x6f,0x74,0x20,0x65,0x72,0x72,0x6f,0x72,
88 0x0d,0x0a,0x50,0x72,0x65,0x73,0x73,0x20,
89 0x61,0x6e,0x79,0x20,0x6b,0x65,0x79,0x20,
90 0x66,0x6f,0x72,0x20,0x72,0x65,0x74,0x72,
91 0x79,0x0d,0x0a,0x24,0x00,0x00,0x00,0x00,
92 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
93 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
94 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
95 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
96 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
97 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
98 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
99 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
100 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
101 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
102 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
103 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
104 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
105 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
106 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
107 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
108 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
109 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
110 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
111 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
112 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
113 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
114 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
115 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
116 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
117 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
118 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
119 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
120 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
121 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
122 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
123 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
124 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
125 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
126 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
127 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
128 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
129 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
130 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
131 };
132 static unsigned char svi738CpmBoot[512] = {
133 0xEB,0xFE,0x90,0x41,0x53,0x43,0x20,0x20,
134 0x32,0x2E,0x32,0x00,0x00,0x00,0x00,0x00,
135 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
136 0x00,0x00,0x00,0x00,0x00,0x00,0xD0,0x21,
137 0x2D,0xC0,0x11,0x00,0x80,0x01,0x24,0x00,
138 0xED,0xB0,0xC3,0x00,0x80,0xF3,0x11,0x00,
139 0x90,0x0E,0x1A,0xCD,0x7D,0xF3,0x11,0x01,
140 0x00,0x26,0x10,0x2E,0x00,0x0E,0x2F,0xCD,
141 0x7D,0xF3,0xF3,0x21,0x00,0x90,0x11,0x00,
142 0xE2,0x01,0xD0,0x1D,0xED,0xB0,0xC3,0x00,
143 0xE2,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,
144 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,
145 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,
146 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,
147 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,
148 0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0x00,
149 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
150 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
151 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
152 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
153 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
154 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
155 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
156 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
157 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
158 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
159 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
160 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
161 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
162 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
163 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
164 0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0xFF,
165 0xE1,0xC3,0x29,0xE1,0x3A,0x42,0xD7,0xC3,
166 0x01,0xD7,0xEB,0x22,0xB1,0xE1,0xC3,0xDA,
167 0xD9,0x2A,0xBF,0xE1,0xC3,0x29,0xE1,0x2A,
168 0xAD,0xE1,0xC3,0x29,0xE1,0xCD,0x51,0xE0,
169 0xCD,0x3B,0xDC,0xC3,0x01,0xDB,0x2A,0xBB,
170 0xE1,0x22,0x45,0xD7,0xC9,0x3A,0xD6,0xE1,
171 0xFE,0xFF,0xC2,0x3B,0xE1,0x3A,0x41,0xD7,
172 0xC3,0x01,0xD7,0xE6,0x1F,0x32,0x41,0xD7,
173 0xC9,0xCD,0x51,0xE0,0xC3,0x93,0xDF,0xCD,
174 0x51,0xE0,0xC3,0x9C,0xDF,0xCD,0x51,0xE0,
175 0xC3,0xD2,0xDF,0x2A,0x43,0xD7,0x7D,0x2F,
176 0x5F,0x7C,0x2F,0x2A,0xAF,0xE1,0xA4,0x57,
177 0x7D,0xA3,0x5F,0x2A,0xAD,0xE1,0xEB,0x22,
178 0xAF,0xE1,0x7D,0xA3,0x6F,0x7C,0xA2,0x67,
179 0x22,0xAD,0xE1,0xC9,0x3A,0xDE,0xE1,0xB7,
180 0xCA,0x91,0xE1,0x2A,0x43,0xD7,0x36,0x00,
181 0x3A,0xE0,0xE1,0xB7,0xCA,0x91,0xE1,0x77,
182 0x3A,0xDF,0xE1,0x32,0xD6,0xE1,0xCD,0x45,
183 0xE0,0x2A,0x0F,0xD7,0xF9,0x2A,0x45,0xD7,
184 0x7D,0x44,0xC9,0xCD,0x51,0xE0,0x3E,0x02,
185 0x32,0xD5,0xE1,0x0E,0x00,0xCD,0x07,0xDF,
186 0xCC,0x03,0xDE,0xC9,0xE5,0x00,0x00,0x00,
187 0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
188 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
189 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
190 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
191 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
192 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
193 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
194 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
195 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
196 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
197 };
198 static unsigned char msx2cpm3boot[512] = {
199 0xE9,0x00,0x00,0x52,0x56,0x53,0x20,0x64,
200 0x61,0x74,0x61,0x00,0x02,0x02,0x01,0x00,
201 0x02,0x70,0x00,0xD0,0x02,0xF8,0x02,0x00,
202 0x09,0x00,0x01,0x00,0x00,0x00,0xD0,0xF3,
203 0x31,0x1F,0xF5,0x21,0x00,0xC0,0x11,0x00,
204 0x80,0x01,0xFF,0x3F,0xED,0xB0,0xC3,0x31,
205 0x80,0x21,0x00,0xC1,0x06,0x00,0xDB,0xA8,
206 0xE6,0x3F,0x57,0xD3,0xA8,0x3A,0xFF,0xFF,
207 0x2F,0x4F,0xE6,0x3F,0x5F,0x32,0xFF,0xFF,
208 0x97,0x3D,0xD3,0xFF,0x77,0x20,0xFA,0xD3,
209 0xFF,0xBE,0x20,0x04,0x3C,0x20,0xF8,0x3D,
210 0xB8,0xDA,0x61,0x80,0xED,0x53,0x70,0x80,
211 0x47,0x7B,0xC6,0x40,0x30,0xDE,0x79,0x32,
212 0xFF,0xFF,0x7A,0xC6,0x40,0x30,0xCB,0x11,
213 0x00,0x00,0x7A,0xD3,0xA8,0x7B,0x32,0xFF,
214 0xFF,0x78,0x32,0xFF,0x00,0xD9,0x3E,0x03,
215 0xD3,0xFF,0x21,0x00,0x00,0x11,0x00,0xC0,
216 0x01,0x00,0x01,0xED,0xB0,0x3E,0x00,0xD3,
217 0xFF,0x21,0x00,0x80,0x11,0x00,0xC0,0x01,
218 0xFF,0x3F,0xED,0xB0,0xD9,0xC3,0xA0,0xC0,
219 0x7A,0xCD,0xE5,0xC0,0xD3,0xA8,0x7B,0xCD,
220 0xE5,0xC0,0x32,0xFF,0xFF,0x57,0xE6,0x03,
221 0x4F,0x06,0x00,0x21,0xC5,0xFC,0x09,0x72,
222 0x3E,0x50,0x32,0xAE,0xF3,0xFD,0x2A,0xC0,
223 0xFC,0xDD,0x21,0x6C,0x00,0xCD,0x1C,0x00,
224 0x1E,0x01,0x0E,0x1B,0xCD,0x7D,0xF3,0x11,
225 0x00,0x02,0x0E,0x1A,0xCD,0x7D,0xF3,0x11,
226 0x03,0x00,0x21,0x00,0x06,0x0E,0x2F,0xCD,
227 0x7D,0xF3,0xC3,0x00,0x02,0xE6,0xC0,0x47,
228 0x0F,0x0F,0xB0,0x47,0x0F,0x0F,0x0F,0x0F,
229 0xB0,0xC9,0x00,0x00,0x00,0x00,0x00,0x00,
230 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
231 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
232 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
233 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
234 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
235 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
236 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
237 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
238 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
239 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
240 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
241 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
242 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
243 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
244 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
245 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
246 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
247 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
248 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
249 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
250 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
251 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
252 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
253 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
254 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
255 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
256 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
257 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
258 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
259 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
260 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
261 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
262 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
263 };
264
265 typedef unsigned char byte;
266 typedef unsigned short word;
267 typedef struct {
268 char name[9];
269 char ext[4];
270 int size;
271 int hour,min,sec;
272 int day,month,year;
273 int first;
274 int pos;
275 int attr;
276 } fileinfo;
277
278 static int dskimagesize = 0;
279 static byte *dskimage=NULL;
280 static byte *fat;
281 static byte *direc;
282 static byte *cluster;
283 static int sectorsperfat,numberoffats,reservedsectors;
284 static int bytespersector,direlements,fatelements;
285 static int availsectors;
286
287 static int alBlockNo;
288
load_dsk_svi(int diskType)289 static void load_dsk_svi(int diskType)
290 {
291 int imageSize = 0;
292 int dirOff = 0;
293 byte fatData = 0;
294
295 switch (diskType) {
296 case 7: // MSX2 CP/M 3 DSDD
297 imageSize = 720;
298 alBlockNo = 1;
299 break;
300 case 6: // MSX2 CP/M 3 SSDD
301 imageSize = 360;
302 alBlockNo = 1;
303 break;
304 case 3: // SVI-738 CP/M SSDD
305 imageSize = 360;
306 alBlockNo = 1;
307 break;
308 case 5: // SVI-328 Disk Basic DSDD
309 dirOff = 0x2A000;
310 fatData = 0xFF;
311 case 2: // SVI-328 CP/M DSDD
312 imageSize = 338;
313 alBlockNo = 1;
314 break;
315 case 4: // SVI-328 Disk Basic SSDD
316 dirOff = 0x14C00;
317 fatData = 0xFE;
318 case 1: // SVI-328 CP/M SSDD
319 imageSize = 168;
320 alBlockNo = 2;
321 break;
322 }
323
324 dskimage = (byte *) calloc (1, imageSize * 1024);
325 memset(dskimage, 0xe5, imageSize * 1024);
326 dskimagesize = imageSize * 1024;
327
328 if (diskType == 3) {
329 memcpy(dskimage, svi738CpmBoot, 512);
330 }
331 if (diskType == 6 || diskType == 7) {
332 memcpy(dskimage, msx2cpm3boot, 512);
333 if (diskType == 7) {
334 dskimage[dirOff + 0x13] = 0xA0;
335 }
336 }
337
338 if (diskType == 4 || diskType == 5) {
339 memset(dskimage + dirOff, 0xFF, 17 * 256);
340 memset(dskimage + dirOff + 13 * 256, 0x00, 256);
341
342 memset(dskimage + dirOff + 14 * 256, 0xFF, 40);
343 memset(dskimage + dirOff + 14 * 256 + 40, fatData, 40);
344 memset(dskimage + dirOff + 14 * 256, 0xFE, 3);
345 dskimage[dirOff + 14 * 256 + 20] = 0xFE;
346 memset(dskimage + dirOff + 14 * 256 + 80, 0x20, 48);
347 memset(dskimage + dirOff + 14 * 256 + 128, 0x00, 128);
348
349 memcpy(dskimage + dirOff + 15 * 256, dskimage + dirOff + 14 * 256, 256);
350 memcpy(dskimage + dirOff + 16 * 256, dskimage + dirOff + 14 * 256, 256);
351 }
352 }
353
load_dsk_msx(void)354 static void load_dsk_msx(void) {
355 dskimagesize = 720*1024;
356 dskimage=(byte *) calloc (1,720*1024);
357 memset (dskimage,0,720*1024);
358 memcpy (dskimage,msxboot,512);
359 reservedsectors=*(word *)(dskimage+0x0E);
360 numberoffats=*(dskimage+0x10);
361 sectorsperfat=*(word *)(dskimage+0x16);
362 bytespersector=*(word *)(dskimage+0x0B);
363 direlements=*(word *)(dskimage+0x11);
364 fat=dskimage+bytespersector*reservedsectors;
365 direc=fat+bytespersector*(sectorsperfat*numberoffats);
366 cluster=direc+direlements*32;
367 availsectors=80*9*2-reservedsectors-sectorsperfat*numberoffats;
368 availsectors-=direlements*32/bytespersector;
369 fatelements=availsectors/2;
370 fat[0]=0xF9;
371 fat[1]=0xFF;
372 fat[2]=0xFF;
373 }
374
getfileinfo(int pos)375 static fileinfo *getfileinfo(int pos) {
376 fileinfo *file;
377 byte *dir;
378 int i;
379
380 dir=direc+pos*32;
381 if (*dir<0x20 || *dir>=0x80) return NULL;
382
383 file=(fileinfo *) malloc (sizeof (fileinfo));
384 for (i=0; i<8; i++)
385 file->name[i]=dir[i]==0x20?0:dir[i];
386 file->name[8]=0;
387
388 for (i=0; i<3; i++)
389 file->ext[i]=dir[i+8]==0x20?0:dir[i+8];
390 file->ext[3]=0;
391
392 file->size=*(int *)(dir+0x1C);
393
394 i=*(word *)(dir+0x16);
395 file->sec=(i&0x1F)<<1;
396 file->min=(i>>5)&0x3F;
397 file->hour=i>>11;
398
399 i=*(word *)(dir+0x18);
400 file->day=i&0x1F;
401 file->month=(i>>5)&0xF;
402 file->year=1980+(i>>9);
403
404 file->first=*(word *)(dir+0x1A);
405 file->pos=pos;
406 file->attr=*(dir+0xB);
407
408 return file;
409 }
410
getfilelength(int fd)411 static int getfilelength(int fd) {
412 int cur = lseek(fd, 0, SEEK_CUR);
413 int length = lseek(fd, 0, SEEK_END);
414 lseek(fd, cur, SEEK_SET);
415 return length;
416 }
417
match(fileinfo * file,char * name)418 static int match(fileinfo *file, char *name) {
419 char *p=file->name;
420 int status=0,i;
421
422 for (i=0; i<8; i++) {
423 if (!*name)
424 break;
425 if (*name=='*') {
426 status=1;
427 name++;
428 break;
429 }
430 if (*name=='.')
431 break;
432 if (toupper (*name++)!=toupper (*p++))
433 return 0;
434 }
435 if (!status && i<8 && *p!=0)
436 return 0;
437 p=file->ext;
438 if (!*name && !*p) return 1;
439 if (*name++!='.') return 0;
440 for (i=0; i<3; i++) {
441 if (*name=='*')
442 return 1;
443 if (toupper (*name++)!=toupper (*p++))
444 return 0;
445 }
446 return 1;
447 }
448
next_link(int link)449 static int next_link(int link) {
450 int pos;
451
452 pos=(link>>1)*3;
453 if (link&1)
454 return (((int)(fat[pos+2]))<<4)+(fat[pos+1]>>4);
455 else
456 return (((int)(fat[pos+1]&0xF))<<8)+fat[pos];
457 }
458
bytes_free(void)459 static int bytes_free(void) {
460 int i,avail=0;
461
462 for (i=2; i<2+fatelements; i++)
463 if (!next_link (i)) avail++;
464 return avail*1024;
465 }
466
remove_link(int link)467 static int remove_link(int link) {
468 int pos;
469 int current;
470
471 pos=(link>>1)*3;
472 if (link&1) {
473 current=(((int)(fat[pos+2]))<<4)+(fat[pos+1]>>4);
474 fat[pos+2]=0;
475 fat[pos+1]&=0xF;
476 return current;
477 }
478 else {
479 current=(((int)(fat[pos+1]&0xF))<<8)+fat[pos];
480 fat[pos]=0;
481 fat[pos+1]&=0xF0;
482 return current;
483 }
484 }
485
wipe(fileinfo * file)486 static void wipe(fileinfo *file) {
487 int current;
488
489 current=file->first;
490 do {
491 current=remove_link (current);
492 } while (current!=0xFFF);
493 direc[file->pos*32]=0xE5;
494 }
495
get_free(void)496 static int get_free(void) {
497 int i;
498
499 for (i=2; i<2+fatelements; i++)
500 if (!next_link (i)) return i;
501 //printf ("Internal error\n");
502 //exit (5);
503 return 0;
504 }
505
get_next_free(void)506 static int get_next_free(void) {
507 int i,status=0;
508
509 for (i=2; i<2+fatelements; i++)
510 if (!next_link (i))
511 if (status)
512 return i;
513 else
514 status=1;
515 //printf ("Internal error\n");
516 //exit (5);
517 return 0;
518 }
519
store_fat(int link,int next)520 static void store_fat(int link, int next) {
521 int pos;
522
523 pos=(link>>1)*3;
524 if (link&1) {
525 fat[pos+2]=next>>4;
526 fat[pos+1]&=0xF;
527 fat[pos+1]|=(next&0xF)<<4;
528 }
529 else {
530 fat[pos]=next&0xFF;
531 fat[pos+1]&=0xF0;
532 fat[pos+1]|=next>>8;
533 }
534 }
535
add_single_file(char * name,const char * pathname)536 static int add_single_file(char *name, const char *pathname) {
537 int i,total;
538 fileinfo *file;
539 int fileid;
540 byte *buffer;
541 byte *b;
542 int size;
543 struct stat s;
544 struct tm *t;
545 int first;
546 int current;
547 int next;
548 int pos;
549 char *p;
550 char fullname[250];
551 int result;
552
553 strcpy (fullname,pathname);
554 strcat (fullname,"/");
555 strcat (fullname,name);
556 fileid=open (fullname,O_BINARY|O_RDONLY);
557
558 if (fileid < 0) {
559 return -1;
560 }
561
562 for (i=0; i<direlements; i++) {
563 if ((file=getfileinfo (i))!=NULL) {
564 if (match (file,name)) {
565 wipe (file);
566 }
567 free (file);
568 }
569 }
570
571 if ((size=getfilelength(fileid))>bytes_free())
572 {
573 close (fileid);
574 return 1;
575 }
576
577 for (i=0; i<direlements; i++)
578 if (direc[i*32]<0x20 || direc[i*32]>=0x80)
579 break;
580 if (i==direlements)
581 {
582 close (fileid);
583 return 2;
584 }
585
586 pos=i;
587
588 b = buffer=(byte *) malloc ((size+1023)&(~1023));
589 read (fileid,buffer,size);
590
591 close (fileid);
592
593 total=(size+1023)>>10;
594 current=first=get_free ();
595
596 for (i=0; i<total;) {
597 memcpy (cluster+(current-2)*1024,buffer,1024);
598 buffer+=1024;
599 if (++i==total)
600 next=0xFFF;
601 else
602 next=get_next_free ();
603 store_fat (current,next);
604 current=next;
605 }
606
607 memset (direc+pos*32,0,32);
608 memset (direc+pos*32,0x20,11);
609 i=0;
610 for (p=name;*p;p++) {
611 if (*p=='.') {
612 i=8;
613 continue;
614 }
615 direc[pos*32+i++]=toupper (*p);
616 }
617
618 result = stat(fullname, &s);
619
620 t = localtime(&s.st_mtime);
621 if (t == NULL) {
622 time_t tmp = time(NULL);
623 t = localtime(&tmp);
624 }
625 ;
626 if (t == NULL) {
627 result = -1;
628 }
629 else {
630 *(word *)(direc+pos*32+0x1A)=first;
631 *(int *)(direc+pos*32+0x1C)=size;
632 *(word *)(direc+pos*32+0x16)=
633 (t->tm_sec>>1)+(t->tm_min<<5)+(t->tm_hour<<11);
634 *(word *)(direc+pos*32+0x18)=
635 (t->tm_mday)+(t->tm_mon<<5)+((t->tm_year-1980)<<9);
636 }
637 free (b);
638 return result;
639 }
640
641 /* strupr is not a standard ANSI function, so define our own version */
my_strupr(char * s)642 static char* my_strupr(char* s)
643 {
644 char* p = s;
645 while (*p) {
646 *p = toupper(*p);
647 ++p;
648 }
649 return s;
650 }
651
add_single_file_svi(int diskType,char * name,const char * pathname)652 static int add_single_file_svi(int diskType, char *name, const char *pathname)
653 {
654 typedef struct
655 {
656 char name[6];
657 char ext[3];
658 byte attrib;
659 byte fatpointer;
660 byte reserved[5];
661 } DirectoryEntry;
662
663 FILE *fpImport;
664 char fullname[250];
665 char filename[80];
666 char extension[10];
667 char *pname;
668 char *pext;
669 char myname[250];
670 byte fileBuf[17 * 256];
671 int bytesRead;
672 int fileDone;
673 int dirOff;
674 int dirEntryNo = 0;
675 int dirFound = 0;
676 DirectoryEntry myDir;
677 int fatCounter = 0;
678 int fatFound = 0;
679 int nextTrack;
680 int sides;
681 int side = 0;
682 int track = 0;
683 int offset;
684
685 switch (diskType) {
686 case 5:
687 dirOff = 0x2A000;
688 sides = 2;
689 break;
690 case 4:
691 dirOff = 0x14C00;
692 sides = 1;
693 break;
694 }
695
696 strcpy(fullname, pathname);
697 strcat(fullname, "/");
698 strcat(fullname, name);
699
700 strcpy(myname, name);
701 memset(&filename, 0x20, sizeof(filename));
702 memset(&extension, 0x20, sizeof(extension));
703 pname = strtok(name, ".");
704 if (pname != NULL) {
705 memcpy(filename, pname, strlen(pname));
706 pext = strrchr(myname, '.');
707 if (pext != NULL) {
708 memcpy(extension, pext + 1, strlen(pext));
709 }
710 }
711 else {
712 memcpy(filename, myname, strlen(myname));
713 }
714
715 do {
716 if (dskimage[dirOff + 16 * dirEntryNo] == 0xff) {
717 dirFound = 1;
718 }
719 else {
720 dirEntryNo++;
721 }
722 }
723 while (dirEntryNo < 16 * 13 && !dirFound);
724
725 if (!dirFound) {
726 return 1;
727 }
728
729 do {
730 if (dskimage[dirOff + 14 * 256 + fatCounter] == 0xff) {
731 fatFound = 1;
732 }
733 else {
734 fatCounter++;
735 }
736 }
737 while (fatCounter < 80 && !fatFound);
738
739 if (!fatFound) {
740 return 1;
741 }
742
743 fpImport = fopen(fullname, "rb");
744 if (!fpImport) {
745 return 1;
746 }
747
748 memset(&myDir, 0xff, sizeof(myDir));
749 memcpy(&myDir.name, filename, 6);
750 memcpy(&myDir.ext, extension, 3);
751 myDir.fatpointer = fatCounter;
752 myDir.attrib = 0;
753
754 pext = my_strupr(extension);
755 if (0 == strncmp(extension, "BAS ", 3))
756 myDir.attrib = 0x80;
757 else if (0 == strncmp(extension, "BIN ", 3))
758 myDir.attrib = 0x01;
759 else if (0 == strncmp(extension, "DAT ", 3))
760 myDir.attrib = 0x40;
761 else if (0 == strncmp(extension, "SCR ", 3))
762 myDir.attrib = 0xA0;
763 else
764 myDir.attrib = 0;
765
766 do {
767 memset(&fileBuf, 0x00, sizeof(fileBuf));
768
769 bytesRead = fread(fileBuf, 1, sizeof(fileBuf), fpImport);
770 fileDone = (bytesRead != sizeof(fileBuf));
771
772 track = fatCounter;
773 if (track > 39) {
774 side = 1;
775 track = 80 - fatCounter;
776 }
777 offset = ((track * sides + side) * 17 + 1 - 1) * 256 - 2048;
778 memcpy(dskimage + offset, &fileBuf, bytesRead);
779
780 if (!fileDone) {
781 nextTrack = fatCounter;
782 nextTrack++;
783 if (nextTrack == 20) {
784 nextTrack++;
785 }
786 dskimage[dirOff + 14 * 256 + fatCounter] = nextTrack;
787 fatCounter = nextTrack;
788 }
789 }
790 while (!fileDone);
791
792 memcpy(dskimage + dirOff + dirEntryNo * 16, &myDir, sizeof(myDir));
793
794 dskimage[dirOff + 14 * 256 + fatCounter] = 0xC0 | (int)ceil(bytesRead / 256.00);
795
796 memcpy(dskimage + dirOff + 15 * 256, dskimage + dirOff + 14 * 256, 256);
797 memcpy(dskimage + dirOff + 16 * 256, dskimage + dirOff + 14 * 256, 256);
798
799 fclose(fpImport);
800 return 0;
801 }
802
add_single_file_cpm(int diskType,char * name,const char * pathname)803 static int add_single_file_cpm(int diskType, char *name, const char *pathname)
804 {
805 typedef struct
806 {
807 byte status; // UU
808 char name[8]; // Fn
809 char ext[3]; // Tn
810 byte extnol; // EX
811 byte lrc; // S2
812 byte extnoh; // S1
813 byte blkcnt; // RC
814 byte pointers[16]; // AL
815 } DirectoryEntry;
816
817 DirectoryEntry myDir;
818 FILE *fpImport;
819 char fullname[250];
820 int drm = 0;
821 int drmFound = 0;
822 byte fileBuf[2048];
823 int fileSize;
824 char myname[250];
825 char filename[80];
826 char extension[10];
827 char *pname;
828 char *pext;
829 int fileDone;
830 int dskDataOffset;
831 int alCount = 0;
832 int extent = 0;
833 int fileRead;
834 word dirOffset;
835 int dpbBLS;
836 int sides;
837 int trackOffset;
838 switch (diskType) {
839 case 7: // MSX2 CP/M 3 DSDD
840 dirOffset = 0x2400;
841 dpbBLS = 2048;
842 sides = 1;
843 break;
844 case 6: // MSX2 CP/M 3 SSDD
845 dirOffset = 0x2400;
846 dpbBLS = 2048;
847 sides = 0;
848 break;
849 case 3: // SVI-738 CP/M SSDD
850 dirOffset = 0x3600;
851 dpbBLS = 2048;
852 sides = 0;
853 break;
854 case 2: // SVI-328 CP/M DSDD
855 dirOffset = 0x5E00;
856 dpbBLS = 2048;
857 sides = 1;
858 break;
859 case 1: // SVI-328 CP/M SSDD
860 default:
861 dirOffset = 0x2B00;
862 dpbBLS = 1024;
863 sides = 0;
864 break;
865 }
866
867 strcpy(fullname, pathname);
868 strcat(fullname, "/");
869 strcat(fullname, name);
870
871 name = my_strupr(name);
872 strcpy(myname, name);
873
874 memset(filename, 0x20, sizeof(filename));
875 memset(extension, 0x20, sizeof(extension));
876
877 pname = strtok(name, ".");
878 if (pname != NULL) {
879 memcpy(filename, pname, strlen(pname));
880 pext = strrchr(myname, '.');
881 if (pext != NULL) {
882 memcpy(extension, pext + 1, strlen(pext));
883 }
884 }
885 else {
886 memcpy(filename, myname, strlen(myname));
887 }
888
889 fpImport = fopen(fullname, "rb");
890 if (!fpImport) {
891 return 1;
892 }
893
894 fseek(fpImport, 0, SEEK_END);
895 fileSize = ftell(fpImport);
896 if (fileSize > 0x27500) {
897 fclose(fpImport);
898 return 1;
899 }
900
901 do {
902 if (dskimage[dirOffset + drm * 0x20] == 0xe5) {
903 drmFound = 1;
904 }
905 else {
906 drm++;
907 }
908 }
909 while (drm < 0x40 && !drmFound);
910
911 if (!drmFound)
912 {
913 fclose(fpImport);
914 return 1;
915 }
916
917 memset(&myDir, 0, sizeof(myDir));
918 memcpy(&myDir.name, filename, 8);
919 memcpy(&myDir.ext, extension, 3);
920
921 rewind(fpImport);
922 do {
923 memset(&fileBuf, 0, dpbBLS);
924 myDir.pointers[alCount] = alBlockNo;
925
926 // trackOffset = ((alBlockNo - 1) & 0x02) ? (4352 * sides) : (4352 * sides + 4352);
927 trackOffset = ((alBlockNo - 1) & 0x02) ? (4352 * sides) : (4352 * sides);
928 dskDataOffset = (dirOffset + (alBlockNo * dpbBLS)) + trackOffset;
929 // dskDataOffset = dirOffset + (alBlockNo * dpbBLS);
930
931 fileRead = fread(fileBuf, 1, dpbBLS, fpImport);
932 fileDone = (fileRead != dpbBLS);
933
934 memcpy(&dskimage[dskDataOffset], &fileBuf, dpbBLS);
935
936 alBlockNo++;
937 alCount++;
938 if (alCount > 15) {
939 myDir.blkcnt = 0x80;
940 memcpy(&dskimage[dirOffset + drm * sizeof(myDir)], &myDir, sizeof(myDir));
941 memset(&myDir.pointers, 0, sizeof(myDir.pointers));
942 alCount = 0;
943 extent++;
944 myDir.extnol = extent;
945 drm++;
946 }
947 }
948 while (!fileDone);
949
950 fclose(fpImport);
951
952 myDir.blkcnt = (int)ceil((alCount * dpbBLS - (dpbBLS - fileRead)) / 128.00);
953
954 memcpy(&dskimage[dirOffset + drm * sizeof(myDir)], &myDir, sizeof(myDir));
955
956 return 0;
957 }
958
959 #ifdef USE_ARCH_GLOB
dirLoadFile(DirDiskType diskType,const char * directory,int * size)960 void* dirLoadFile(DirDiskType diskType, const char* directory, int* size)
961 {
962 ArchGlob* glob;
963 static char filename[512];
964
965 if (diskType == 0) {
966 load_dsk_msx();
967 }
968 else {
969 load_dsk_svi(diskType);
970 }
971
972 sprintf(filename, "%s/*", directory);
973
974 glob = archGlob(filename, ARCH_GLOB_FILES);
975
976 if (glob != NULL) {
977 int rv;
978 int i;
979 for (i = 0; i < glob->count; i++) {
980 char* fileName = strrchr(glob->pathVector[i], '/');
981 if (fileName == NULL) {
982 fileName = strrchr(glob->pathVector[i], '\\');
983 }
984 if (fileName == NULL) {
985 continue;
986 }
987 fileName++;
988 if (diskType == 0) {
989 rv = add_single_file(fileName, directory);
990 }
991 else if (diskType == 4 || diskType == 5) {
992 rv = add_single_file_svi(diskType, fileName, directory);
993 }
994 else {
995 rv = add_single_file_cpm(diskType, fileName, directory);
996 }
997
998 if (rv) {
999 free(dskimage);
1000 dskimage = NULL;
1001 break;
1002 }
1003 }
1004
1005 archGlobFree(glob);
1006 }
1007
1008 *size = dskimagesize;
1009
1010 return dskimage;
1011 }
1012 #else
dirLoadFile(DirDiskType diskType,const char * directory,int * size)1013 void* dirLoadFile(DirDiskType diskType, const char* directory, int* size)
1014 {
1015 WIN32_FIND_DATA fileData;
1016 HANDLE hFile;
1017 static char filename[512];
1018 int success;
1019 int rv;
1020
1021 if (diskType == 0) {
1022 load_dsk_msx();
1023 }
1024 else {
1025 load_dsk_svi(diskType);
1026 }
1027
1028 sprintf(filename, "%s" DIR_SEPARATOR "*.*", directory);
1029
1030 hFile = FindFirstFile(filename,&fileData);
1031 success = hFile != INVALID_HANDLE_VALUE;
1032 while (success) {
1033 if (fileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) {
1034 if (diskType == 0) {
1035 rv = add_single_file(fileName, directory);
1036 }
1037 else if (diskType == 4 || diskType == 5) {
1038 rv = add_single_file_svi(diskType, fileName, directory);
1039 }
1040 else {
1041 rv = add_single_file_cpm(diskType, fileName, directory);
1042 }
1043
1044 if (rv) {
1045 free(dskimage);
1046 dskimage = NULL;
1047 break;
1048 }
1049 }
1050 success = FindNextFile(hFile, &fileData);
1051 }
1052
1053 if (hFile != INVALID_HANDLE_VALUE) {
1054 FindClose(hFile);
1055 }
1056
1057 *size = dskimagesize;
1058
1059 return dskimage;
1060 }
1061 #endif
1062