source: buchla-emu/emu/mkdisk.c

0.1
Last change on this file was c5b6c90, checked in by Thomas Lopatic <thomas@…>, 7 years ago

Successfully loaded midas.abs from disk.

  • Property mode set to 100644
File size: 5.7 KB
Line 
1/*
2 * Copyright (C) 2017 The Contributors
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or (at
7 * your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * A copy of the GNU General Public License can be found in the file
15 * "gpl.txt" in the top directory of this repository.
16 */
17
18#include <stdbool.h>
19#include <stddef.h>
20#include <stdint.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25#include <sys/types.h>
26
27#define DISK_FILE_NAME "buchla.disk"
28#define MIDAS_FILE_NAME "midas.abs"
29
30#define N_CYL 80
31#define N_SID 2
32#define N_SEC 9
33#define SZ_SEC 512
34
35#define N_SEC_CLU 2
36#define SZ_CLU (SZ_SEC * N_SEC_CLU)
37
38#define N_BOOT_SEC 1
39#define N_FAT_SEC 3
40#define N_ROOT_SEC 7
41
42#define N_FAT 2
43#define SZ_DIR_ENT 32
44
45#define ROOT_SEC (N_BOOT_SEC + N_FAT_SEC * N_FAT)
46#define N_META_SEC (ROOT_SEC + N_ROOT_SEC)
47
48static uint8_t midas[1024 * 1024];
49static int32_t sz_midas;
50
51static uint8_t disk[N_CYL * N_SID * N_SEC][SZ_SEC];
52
53static int32_t put_sec_8(int32_t sec, int32_t off, int32_t val)
54{
55 disk[sec][off] = (uint8_t)val;
56 return off + 1;
57}
58
59static int32_t put_sec_16(int32_t sec, int32_t off, int32_t val)
60{
61 disk[sec][off + 0] = (uint8_t)(val >> 0);
62 disk[sec][off + 1] = (uint8_t)(val >> 8);
63 return off + 2;
64}
65
66static int32_t put_sec_32(int32_t sec, int32_t off, int32_t val)
67{
68 off = put_sec_16(sec, off, val & 65535);
69 off = put_sec_16(sec, off, val >> 16);
70 return off;
71}
72
73static int32_t put_sec_str(int32_t sec, int32_t off, const char *str, int32_t len)
74{
75 int32_t i;
76
77 for (i = 0; str[i] != 0 && i < len; ++i) {
78 disk[sec][off + i] = (uint8_t)str[i];
79 }
80
81 while (i < len) {
82 disk[sec][off + i] = ' ';
83 ++i;
84 }
85
86 return off + i;
87}
88
89static int32_t put_fat_12(int32_t sec, int32_t ent, int32_t val)
90{
91 uint8_t *fat = disk[sec];
92
93 int32_t off = ent / 2 * 3;
94 int32_t bit = (ent % 2) * 12;
95
96 int32_t tmp = 0;
97
98 tmp |= fat[off + 0] << 0;
99 tmp |= fat[off + 1] << 8;
100 tmp |= fat[off + 2] << 16;
101
102 tmp = (tmp & ~(0xfff << bit)) | (val << bit);
103
104 fat[off + 0] = (uint8_t)(tmp >> 0);
105 fat[off + 1] = (uint8_t)(tmp >> 8);
106 fat[off + 2] = (uint8_t)(tmp >> 16);
107
108 return ent + 1;
109}
110
111static void init_boot_sector(void)
112{
113 int32_t off = 0;
114
115 // magic number
116 off = put_sec_8(0, off, 0xe9);
117 off = put_sec_8(0, off, 0x00);
118
119 // OEM
120 off = put_sec_str(0, off, "EMUL", 6);
121
122 // serial number
123 off = put_sec_8(0, off, 0x01);
124 off = put_sec_8(0, off, 0x02);
125 off = put_sec_8(0, off, 0x03);
126
127 // bytes per sector
128 off = put_sec_16(0, off, SZ_SEC);
129
130 // sectors per cluster
131 off = put_sec_8(0, off, N_SEC_CLU);
132
133 // number of reserved sectors
134 off = put_sec_16(0, off, N_BOOT_SEC);
135
136 // number of FATs
137 off = put_sec_8(0, off, N_FAT);
138
139 // maximum number of root directory entries
140 off = put_sec_16(0, off, N_ROOT_SEC * SZ_SEC / SZ_DIR_ENT);
141
142 // total number of sectors
143 off = put_sec_16(0, off, N_CYL * N_SID * N_SEC);
144
145 // media descriptor (floppy disk, 720k)
146 off = put_sec_8(0, off, 0xf9);
147
148 // sectors per FAT (9 * 512 / 3 * 2 = 3072)
149 off = put_sec_16(0, off, N_FAT_SEC);
150
151 // sectors per track
152 off = put_sec_16(0, off, N_SEC);
153
154 // number of sides
155 off = put_sec_16(0, off, N_SID);
156
157 // number of hidden sectors
158 off = put_sec_16(0, off, 0);
159
160 put_sec_8(0, SZ_SEC - 2, 0x55);
161 put_sec_8(0, SZ_SEC - 1, 0xaa);
162}
163
164static void init_fat(int32_t sec)
165{
166 int32_t ent = 0;
167
168 ent = put_fat_12(sec, ent, 0xff9);
169 ent = put_fat_12(sec, ent, 0xfff);
170
171 int32_t n_clu = (sz_midas + SZ_CLU - 1) / SZ_CLU;
172
173 for (int32_t i = 0; i < n_clu - 1; ++i) {
174 ent = put_fat_12(sec, ent, ent + 1);
175 }
176
177 put_fat_12(sec, ent, 0xfff);
178}
179
180static void init_midas(void)
181{
182 int32_t off = 0;
183
184 // file name
185 off = put_sec_str(ROOT_SEC, off, "MIDAS", 8);
186
187 // extension
188 off = put_sec_str(ROOT_SEC, off, "ABS", 3);
189
190 // file attributes (0x20 = archive)
191 off = put_sec_8(ROOT_SEC, off, 0x20);
192
193 // unused
194 for (int32_t i = 0; i < 10; ++i) {
195 off = put_sec_8(ROOT_SEC, off, 0x00);
196 }
197
198 // last modified time (12:34:56)
199 off = put_sec_16(ROOT_SEC, off, (12 << 11) | (34 << 5) | (56 / 2));
200
201 // last modified date (1988-06-20)
202 off = put_sec_16(ROOT_SEC, off, (8 << 9) | (6 << 5) | 20);
203
204 // start cluster
205 off = put_sec_16(ROOT_SEC, off, 2);
206
207 // file size
208 off = put_sec_32(ROOT_SEC, off, sz_midas);
209
210 int32_t n_sec = (sz_midas + SZ_SEC - 1) / SZ_SEC;
211 memcpy(disk[N_META_SEC], midas, (size_t)n_sec * SZ_SEC);
212}
213
214static void write_disk(void)
215{
216 FILE *fh = fopen(DISK_FILE_NAME, "wb");
217
218 if (fh == NULL || fwrite(disk, sizeof disk, 1, fh) != 1) {
219 fprintf(stderr, "error while writing disk file " DISK_FILE_NAME "\n");
220 exit(1);
221 }
222
223 fclose(fh);
224}
225
226static void load_midas(void)
227{
228 FILE *fh = fopen(MIDAS_FILE_NAME, "rb");
229
230 if (fh == NULL) {
231 fprintf(stderr, "error while opening MIDAS file " MIDAS_FILE_NAME "\n");
232 exit(1);
233 }
234
235 if (fseek(fh, 0, SEEK_END) < 0) {
236 fprintf(stderr, "error while seeking in MIDAS file " MIDAS_FILE_NAME "\n");
237 exit(1);
238 }
239
240 ssize_t len = ftell(fh);
241
242 if (len < 0) {
243 fprintf(stderr, "error while determining size of MIDAS file " MIDAS_FILE_NAME "\n");
244 exit(1);
245 }
246
247 sz_midas = (int32_t)len;
248 rewind(fh);
249
250 if (fread(midas, (size_t)sz_midas, 1, fh) != 1) {
251 fprintf(stderr, "error while reading MIDAS file " MIDAS_FILE_NAME "\n");
252 exit(1);
253 }
254
255 fclose(fh);
256}
257
258int32_t main(int32_t argc, char *argv[])
259{
260 (void)argc;
261 (void)argv;
262
263 load_midas();
264 init_boot_sector();
265
266 for (int32_t i = 0; i < N_FAT; ++i) {
267 init_fat(N_BOOT_SEC + i * N_FAT_SEC);
268 }
269
270 init_midas();
271 write_disk();
272 return 0;
273}
Note: See TracBrowser for help on using the repository browser.