source: thomson/code/C/HxCHost/main.c@ 7cabd49

main
Last change on this file since 7cabd49 was 7cabd49, checked in by Adrien Destugues <pulkomandy@…>, 12 years ago

HxC host software : work at Forever XIII party

  • Switch to lwtools gcc toolchain
  • Fix some bugs.
  • Editing the HxC settings works
  • Selecting a floppy image works (sometimes)

git-svn-id: svn://localhost/thomson@24 85ae3b6b-dc8f-4344-a89d-598714f2e4e5

  • Property mode set to 100644
File size: 6.9 KB
Line 
1/* HcX floppy Emulator Host Software for TO8 and MO5
2 * Copyright 2011, Adrien Destugues <pulkomandy@pulkomandy.ath.cx>
3 * Distributed under the terms of the MIT Licence
4 */
5
6#include "pff/pff.h"
7#include "macros.h"
8
9void asm_write();
10
11FILINFO DIRECTORY_BUFFER[23];
12
13unsigned char mark[512 + 16] = "HxCFEDA";
14unsigned char* secbuf = mark+16;
15
16const char* HXCSDFECFG = "HXCSDFE.CFG";
17
18void printhex(unsigned char n)
19{
20 unsigned char a = n >> 4;
21 a += '0';
22 if (a > '9')
23 a += 'A'-10-'0';
24 mon_putc(a)
25 a = (n&0xF) + '0';
26 if (a > '9')
27 a += 'A'-10-'0';
28 mon_putc(a)
29}
30
31// Program exit point (required by compiler...)
32void __attribute__((noreturn)) exit(int a)
33{
34 for(;;);
35}
36
37// Error exit (required by compiler ...)
38void __attribute__((noreturn)) abort()
39{
40 for(;;);
41}
42
43void my_puts(char* s)
44{
45 int j = 0;
46 while(s[j]) mon_putc(s[j++]);
47}
48
49DIR d;
50char path[256] = "";
51char* pathend = path;
52
53void chdir(char* dirname)
54{
55 *(pathend++) = '/';
56
57 do {
58 *(pathend++) = *(dirname++);
59 } while(*(dirname) != 0);
60
61 *(pathend) = 0;
62
63 FRESULT r = pf_opendir(&d, path);
64
65 if (r != 0) my_puts("directory error");
66}
67
68void parent(void)
69{
70 while(*(pathend) != '/' && pathend > path) pathend--;
71
72 *(pathend) = 0;
73 FRESULT r = pf_opendir(&d, path);
74 if (r != 0) my_puts("directory error");
75}
76
77void ls(FILINFO* fp)
78{
79 for(int i = 23; i > 0; --i) {
80 FRESULT r = pf_readdir(&d, fp);
81 if (r != 0) my_puts("File error");
82 if (*fp->fname == 0) break;
83
84 fp ++;
85 }
86}
87
88struct opt
89{
90 char* name;
91 BYTE off;
92 BYTE type;
93};
94
95static const struct opt options[7] =
96{
97 {"\x1B\x50\x0CHxC floppy emulator setup\r\n"
98 "UP/DOWN move - +/- change\r\n"
99 "space save - left quit\r\n\n"
100 "Step sound ", 16, 0},
101 {"\r\nGUI sound ", 17, 0},
102 {"\r\nBacklight delay ", 18, 1},
103 {"\r\nStandby delay ", 19, 1},
104 {"\r\nDrive selector ", 20, 0},
105 {"\r\nLoad last floppy ", 26, 0},
106 {"\r\nLCD scroll speed ", 28, 1},
107};
108
109#define getcfg(off) *(char*)((int)confbuf+off)
110#define putcfg(off, val) *(char*)((int)confbuf+off) = val
111
112inline static void config()
113{
114 char confbuf[29];
115 // If it's HXCSDFE.CFG, enter config mode
116 // Read the config part of the file
117 WORD byteCount = 29;
118 FRESULT r = pf_read(confbuf, byteCount, &byteCount);
119 if (r != 0 || byteCount != 29)
120 {
121 my_puts("read error ");
122 printhex(r);
123 abort();
124 }
125
126 BYTE selected;
127 for(;;) {
128 for (int j = 0; j < 7; j++)
129 {
130 my_puts(options[j].name);
131 mon_putc(0x1B); // Select back color
132 mon_putc(selected == j ? 0x54: 0x50) // Blue
133 if(options[j].type)
134 printhex(getcfg(options[j].off));
135 else
136 my_puts(getcfg(options[j].off) ? "ON":"OFF");
137 mon_putc(0x1B); // Select back color
138 mon_putc(0x50); // Select back color
139 }
140
141 do {
142 asm(" SWI\n"
143 " FCB 0x0A\n");
144 } while(KEY == 0);
145
146 switch(KEY)
147 {
148 case 0x08: // UP
149 // select next file
150 if (selected != 0) --selected;
151 // TODO next page ?
152 break;
153
154 case 0x19: // SPACE
155 // save configuration
156 pf_lseek(0);
157 byteCount = 29;
158 r = pf_write(confbuf, byteCount, &byteCount);
159 if (r || byteCount != 29) {
160 my_puts("can't write cfg");
161 printhex(r);
162 abort();
163 }
164 r = pf_write(0, 0, &byteCount); // flush sector
165 if (r) {
166 my_puts("can't close cfg");
167 printhex(r);
168 abort();
169 }
170 // fall through
171 case 0x10: // LEFT
172 // Quit (without saving)
173 return;
174
175 case 0x18: // DOWN
176 // select previous file
177 if (++selected > 6) selected = 6;
178 // TODO previous page ?
179 break;
180 case 0x13: // -
181 // decrease current option value
182 if(options[selected].type)
183 --*(char*)((int)confbuf+options[selected].off);
184 else
185 putcfg(options[selected].off, 0);
186 break;
187 case 0x0B: // +
188 if(options[selected].type)
189 ++*(char*)((int)confbuf+options[selected].off);
190 else
191 putcfg(options[selected].off, 0xFF);
192 break;
193 }
194 }
195}
196
197int __attribute__((noreturn)) main(void)
198{
199 // Detect HxC and print version code
200 seek();
201 read(255, 0, secbuf);
202 my_puts("Firmware ");
203 my_puts(secbuf + 8);
204
205 // Read FAT / Init card
206 FATFS fs;
207 FRESULT r = pf_mount(&fs);
208
209 if (r != 0) {
210 my_puts("mount error ");
211 printhex(r);
212 exit(0);
213 }
214
215 // Enter "fixed timings" mode - make sure track 255 sends index pulses
216 // every 200ms. Makes everything a bit slower, but the CD90-640 ROM
217 // requires it.
218 int j = 8;
219 mark[j++] = 3;
220 mark[j++] = 0xFF;
221 for(; j <512; j++) mark[j] = 0;
222 write(255,0,mark);
223
224 // Open root directory
225 pf_opendir(&d, "");
226
227 // List files
228 ls(DIRECTORY_BUFFER);
229
230 int selected = 0;
231 // Main input loop
232 for(;;) {
233 // TODO : refresh only the changed items ?
234 mon_putc(0x1B) // Select back color
235 mon_putc(0x50) // Black
236 mon_putc(0x0C) // clear screen
237
238 FILINFO* fp = DIRECTORY_BUFFER;
239 int i = 0;
240 while(*fp->fname != 0) {
241 mon_putc(0x1B); // Select back color
242 if (i++ == selected)
243 mon_putc(0x54) // Blue
244 else
245 mon_putc(0x50) // Black
246
247 mon_putc(0x1B); // Select front color
248 if (fp->fattrib & AM_DIR)
249 mon_putc(0x41) // Red
250 else
251 mon_putc(0x47) // white
252
253 my_puts(fp->fname);
254 mon_putc('\n');
255 mon_putc('\r');
256
257 fp++;
258 }
259 if (selected > i) selected = i;
260
261 // Allow the user to select a file
262 do {
263 asm(" SWI \n"
264 " fcb 0x0A\n");
265 } while(KEY == 0);
266
267 switch(KEY)
268 {
269 case 0x08: // UP
270 // select next file
271 if (selected != 0) --selected;
272 // TODO next page ?
273 break;
274
275 case 0x10: // LEFT
276 parent();
277 ls(DIRECTORY_BUFFER);
278 break;
279
280 case 0x18: // DOWN
281 // select previous file
282 if (selected++ >= i) selected = i-1;
283 // TODO previous page ?
284 break;
285
286 case 0x19: // SPACE
287 fp = DIRECTORY_BUFFER;
288 fp += selected; // Point on the current direntry
289
290 if(fp->fattrib & AM_DIR)
291 {
292 // If it's a dir, enter it
293 chdir(fp->fname);
294 selected = 0;
295 ls(DIRECTORY_BUFFER);
296 } else {
297 const char* cmp = HXCSDFECFG;
298 if (*(long*)(fp->fname) == *(long*)(cmp)
299 && *(long*)(fp->fname + 4) == *(long*)(cmp+4)
300 && *(long*)(fp->fname + 8) == *(long*)(cmp+8)
301 )
302 {
303 FRESULT res = pf_open(cmp);
304 if (res) {
305 my_puts("Can't open CFG file: ");
306 printhex(res);
307 exit(0);
308 }
309 config();
310 } else {
311 my_puts("LOADING FILE");
312 // If it's an HFE file, load it in HxCSDFE.CFG, then reboot
313
314 // We need to open the file to get the starting cluster.
315 // This is a PFF "limitation".
316 pf_open(fp->fname);
317 long off = LD_DWORD(&fs.org_clust);
318
319 FRESULT res = pf_open(cmp);
320 if (res) {
321 my_puts("Can't open CFG file: ");
322 printhex(res);
323 exit(0);
324 }
325 pf_lseek(0x200);
326
327 int count = 12;
328 pf_write(fp->fname, count, &count);
329 count = 1;
330 pf_write(&fp->fattrib, count, &count);
331 count = 4;
332 pf_write(&off, count, &count);
333 off = LD_DWORD(&fp->fsize);
334 pf_write(&off, count, &count);
335 count = 17;
336 pf_write(fp->fname, count, &count);
337 pf_write(0,0,&count);
338
339 // reboot
340 asm(" SWI\n"
341 " FCB 0");
342 }
343 }
344 break;
345
346 default:
347 printhex(KEY);
348 break;
349 }
350 }
351}
Note: See TracBrowser for help on using the repository browser.