2 * This software is released into the public domain.
3 * See UNLICENSE file in top level directory.
8 #define u8 unsigned char
9 #define u16 unsigned short
10 #define u32 unsigned int
12 #define noinline __attribute__((noinline))
13 #define unused __attribute__((unused))
14 #define _packed __attribute__((packed))
16 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
20 #define GFX_DATA_PORT 0xC00000
21 #define GFX_CTRL_PORT 0xC00004
23 #define TILE_MEM_END 0xB000
26 #define TILE_FONT_BASE (TILE_MEM_END / 32 - FONT_LEN)
28 /* note: using ED menu's layout here.. */
29 #define WPLANE (TILE_MEM_END + 0x0000)
30 #define HSCRL (TILE_MEM_END + 0x0800)
31 #define SLIST (TILE_MEM_END + 0x0C00)
32 #define APLANE (TILE_MEM_END + 0x1000)
33 #define BPLANE (TILE_MEM_END + 0x3000)
36 *((volatile u8 *) (a))
38 *((volatile u16 *) (a))
40 *((volatile u32 *) (a))
41 #define write8(a, d) \
42 *((volatile u8 *) (a)) = (d)
43 #define write16(a, d) \
44 *((volatile u16 *) (a)) = (d)
45 #define write32(a, d) \
46 *((volatile u32 *) (a)) = (d)
48 #define GFX_WRITE_VRAM_ADDR(adr) \
49 (((0x4000 | ((adr) & 0x3FFF)) << 16) | ((adr) >> 14) | 0x00)
50 #define GFX_WRITE_VSRAM_ADDR(adr) \
51 (((0x4000 | ((adr) & 0x3FFF)) << 16) | ((adr) >> 14) | 0x10)
52 #define GFX_WRITE_CRAM_ADDR(adr) \
53 (((0xC000 | ((adr) & 0x3FFF)) << 16) | ((adr) >> 14) | 0x00)
55 #define VDP_setReg(r, v) \
56 write16(GFX_CTRL_PORT, 0x8000 | ((r) << 8) | (v))
61 VDP_NT_SCROLLA = 0x02,
63 VDP_NT_SCROLLB = 0x04,
74 #define LEFT_BORDER 1 /* lame TV */
81 static noinline void VDP_drawTextML(const char *str, u16 plane_base,
84 const u8 *src = (const u8 *)str;
85 u16 basetile = text_pal << 13;
86 int max_len = 40 - LEFT_BORDER;
92 for (len = 0; str[len] && len < max_len; len++)
94 if (len > (PLANE_W - x))
97 addr = plane_base + ((x + (PLANE_W * y)) << 1);
98 write32(GFX_CTRL_PORT, GFX_WRITE_VRAM_ADDR(addr));
101 write16(GFX_DATA_PORT,
102 basetile | ((*src++) - 32 + TILE_FONT_BASE / 32));
106 static int printf_ypos;
108 static void printf_line(int x, const char *buf)
113 VDP_drawTextML(buf, APLANE, x, printf_ypos++ & (PLANE_H - 1));
115 if (printf_ypos >= CSCREEN_H) {
116 /* clear next line */
118 addr += (PLANE_W * (printf_ypos & (PLANE_H - 1))) << 1;
119 write32(GFX_CTRL_PORT, GFX_WRITE_VRAM_ADDR(addr));
120 for (i = 0; i < 40 / 2; i++)
121 write32(GFX_DATA_PORT, 0);
124 write32(GFX_CTRL_PORT, GFX_WRITE_VSRAM_ADDR(0));
125 write16(GFX_DATA_PORT, (printf_ypos - CSCREEN_H + 1) * 8);
129 #define PRINTF_LEN 40
131 static int printf_xpos;
133 static noinline int printf(const char *fmt, ...)
135 static const char hexchars[] = "0123456789abcdef";
136 char c, buf[PRINTF_LEN + 11 + 1];
145 for (d = 0; *fmt; ) {
156 printf_line(printf_xpos, buf);
172 while ('1' <= *fmt && *fmt <= '9') {
173 fwidth = fwidth * 10 + *fmt - '0';
183 ival = va_arg(ap, int);
188 for (i = 1000000000; i >= 10; i /= 10)
191 for (; i >= 10; i /= 10) {
192 buf[d++] = '0' + ival / i;
195 buf[d++] = '0' + ival;
198 uval = va_arg(ap, int);
199 while (fwidth > 1 && uval < (1 << (fwidth - 1) * 4)) {
200 buf[d++] = prefix0 ? '0' : ' ';
203 for (j = 1; j < 8 && uval >= (1 << j * 4); j++)
205 for (j--; j >= 0; j--)
206 buf[d++] = hexchars[(uval >> j * 4) & 0x0f];
209 s = va_arg(ap, char *);
210 while (*s && d < PRINTF_LEN)
214 // don't handle, for now
225 VDP_drawTextML(buf, APLANE, printf_xpos,
226 printf_ypos & (PLANE_H - 1));
233 static const char *exc_names[] = {
238 "Illegal Instruction",
242 "Privilege Violation", /* 8 8 */
244 "Line 1010 Emulator",
245 "Line 1111 Emulator",
249 "Uninitialized Interrupt",
258 "Spurious Interrupt", /* 18 24 */
271 u16 ecxnum; // from handler
283 } bae _packed; // bus/address error frame
287 int xtttt(void) { return sizeof(struct exc_frame); }
289 void exception(const struct exc_frame *f)
293 while (read16(GFX_CTRL_PORT) & 2)
295 write16(GFX_CTRL_PORT, 0x8000 | (VDP_MODE1 << 8) | 0x04);
296 write16(GFX_CTRL_PORT, 0x8000 | (VDP_MODE2 << 8) | 0x44);
298 write32(GFX_CTRL_PORT, GFX_WRITE_VSRAM_ADDR(0));
299 write16(GFX_DATA_PORT,
300 printf_ypos >= CSCREEN_H ?
301 (printf_ypos - CSCREEN_H + 1) * 8 : 0);
303 printf("exception %i ", f->ecxnum);
304 if (f->ecxnum < ARRAY_SIZE(exc_names) && exc_names[f->ecxnum] != NULL)
305 printf("(%s)", exc_names[f->ecxnum]);
307 printf(" (%s)", (f->bae.fc & 0x10) ? "r" : "w");
311 printf(" PC: %08x SR: %04x \n", f->bae.pc, f->bae.sr);
312 printf("addr: %08x IR: %04x FC: %02x \n",
313 f->bae.addr, f->bae.ir, f->bae.fc);
316 printf(" PC: %08x SR: %04x \n", f->g.pc, f->g.sr);
318 for (i = 0; i < 8; i++)
319 printf(" D%d: %08x A%d: %08x \n", i, f->dr[i], i, f->ar[i]);
323 extern u32 font_base[];
324 extern u8 test_data[];
325 extern u8 test_data_end[];
327 static void simple_test(int *odd, int *even, int *rom)
329 u32 old, new, v0, v1;
331 *odd = *even = *rom = 0;
332 old = read16(0x200000);
334 write16(0x200000, new);
335 v0 = read16(0x200000);
336 write8(0x200000, ~new >> 8);
337 write8(0x200001, ~new);
338 //write16(0x200000, ~new);
339 v1 = read16(0x200000);
340 if (((v0 ^ new) & 0xff00) == 0 && ((v1 ^ ~new) & 0xff00) == 0) {
344 if (((v0 ^ new) & 0x00ff) == 0 && ((v1 ^ ~new) & 0x00ff) == 0) {
348 if (v0 == old && v1 == old) {
352 else if (!(*odd | *even)) {
354 printf(" bad value");
359 static int detect_size(u8 *a)
364 for (i = 2, v = 1; i < 0x200000; i <<= 1, v++) {
366 if (read8(a) || read8(a + i) != v)
369 return i > 2 ? i / 2 : 0;
372 static unused void fill(u8 *d, unsigned int size, u8 val)
376 for (i = 0; i < size * 2; i += 2)
380 static int check(u8 *d, unsigned int size, u8 val)
384 for (i = 0; i < size * 2; i += 2)
392 printf("\nfailed at byte %x, val %02x vs %02x\n",
398 static void do_test(u8 *d, unsigned int size)
400 int spos = printf_xpos;
403 for (i = 0; i < 0x100; i++) {
407 fillpx16(d, size / 16, i);
408 if (!checkpx4(d, size / 4, i)) {
409 check(d, size, i); // for log
417 volatile u32 *vptr32;
423 write16(0xa11100, 0x100);
424 write16(0xa11200, 0);
427 while (read16(GFX_CTRL_PORT) & 2)
430 VDP_setReg(VDP_MODE1, 0x04);
431 VDP_setReg(VDP_MODE2, 0x44);
432 VDP_setReg(VDP_MODE3, 0x00);
433 VDP_setReg(VDP_MODE4, 0x81);
434 VDP_setReg(VDP_NT_SCROLLA, APLANE >> 10);
435 VDP_setReg(VDP_NT_SCROLLB, BPLANE >> 13);
436 VDP_setReg(VDP_SAT_BASE, SLIST >> 9);
437 VDP_setReg(VDP_HSCROLL, HSCRL >> 10);
438 VDP_setReg(VDP_AUTOINC, 2);
439 VDP_setReg(VDP_SCROLLSZ, 0x01);
440 VDP_setReg(VDP_BACKDROP, 0);
443 write32(GFX_CTRL_PORT, GFX_WRITE_VRAM_ADDR(0));
444 for (i = 0; i < 32 / 4; i++)
445 write32(GFX_DATA_PORT, 0);
447 /* clear name tables */
448 write32(GFX_CTRL_PORT, GFX_WRITE_VRAM_ADDR(APLANE));
449 for (i = 0; i < PLANE_W * PLANE_H / 2; i++)
450 write32(GFX_DATA_PORT, 0);
452 write32(GFX_CTRL_PORT, GFX_WRITE_VRAM_ADDR(BPLANE));
453 for (i = 0; i < PLANE_W * PLANE_H / 2; i++)
454 write32(GFX_DATA_PORT, 0);
457 write32(GFX_CTRL_PORT, GFX_WRITE_VRAM_ADDR(SLIST));
458 write32(GFX_DATA_PORT, 0);
460 write32(GFX_CTRL_PORT, GFX_WRITE_VRAM_ADDR(HSCRL));
461 write32(GFX_DATA_PORT, 0);
463 /* scroll plane vscroll */
464 write32(GFX_CTRL_PORT, GFX_WRITE_VSRAM_ADDR(0));
465 write32(GFX_DATA_PORT, 0);
466 printf_xpos = printf_ypos = 0;
469 write32(GFX_CTRL_PORT, GFX_WRITE_VRAM_ADDR(TILE_FONT_BASE));
470 for (i = 0; i < FONT_LEN * 32 / 4; i++)
471 write32(GFX_DATA_PORT, font_base[i]);
474 write32(GFX_CTRL_PORT, GFX_WRITE_CRAM_ADDR(0));
475 write32(GFX_DATA_PORT, 0);
476 write32(GFX_CTRL_PORT, GFX_WRITE_CRAM_ADDR(15 * 2)); // font normal
477 write16(GFX_DATA_PORT, 0xeee);
478 write32(GFX_CTRL_PORT, GFX_WRITE_CRAM_ADDR(31 * 2)); // green
479 write16(GFX_DATA_PORT, 0x0e0);
480 write32(GFX_CTRL_PORT, GFX_WRITE_CRAM_ADDR(47 * 2)); // red
481 write16(GFX_DATA_PORT, 0x00e);
485 printf("MD version: %02x\n", read8(0xa10001));
486 printf("ROM writable? ");
488 vptr32 = (void *)0x120;
491 printf("%s\n", *vptr32 == old ? "no" : "yes");
493 printf("200000 initial state:");
494 simple_test(&odd, &even, &rom);
496 printf("\nenable with i0: ");
498 simple_test(&odd, &even, &rom);
500 printf("\ndisable with i0:");
502 simple_test(&odd, &even, &rom);
504 printf("\nenable with i1: ");
506 simple_test(&odd, &even, &rom);
508 printf("\ndisable with i1:");
510 simple_test(&odd, &even, &rom);
512 printf("\nenable with 16: ");
513 write16(0xa130f0, 1);
514 simple_test(&odd, &even, &rom);
518 even = detect_size((void *)0x200000);
519 printf("detected even size: %d\n", even);
522 odd = detect_size((void *)0x200001);
523 printf("detected odd size: %d\n", odd);
526 printf("testing even: ", even);
527 do_test((void *)0x200000, even);
531 printf("testing odd: ", odd);
532 do_test((void *)0x200001, odd);
550 // vim:ts=4:sw=4:expandtab