some tests
[megadrive.git] / testpico / main.c
1 /*
2  * This software is released into the public domain.
3  * See UNLICENSE file in top level directory.
4  */
5 #include <stdlib.h>
6 #include <stdarg.h>
7
8 #define u8      unsigned char
9 #define u16     unsigned short
10 #define u32     unsigned int
11
12 #define noinline __attribute__((noinline))
13 #define unused   __attribute__((unused))
14 #define _packed  __attribute__((packed))
15
16 #define mem_barrier() \
17     asm volatile("":::"memory")
18
19 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
20
21 #include "asmtools.h"
22
23 #define VDP_DATA_PORT    0xC00000
24 #define VDP_CTRL_PORT    0xC00004
25
26 #define TILE_MEM_END     0xB000
27
28 #define FONT_LEN         128
29 #define TILE_FONT_BASE   (TILE_MEM_END / 32  - FONT_LEN)
30
31 /* note: using ED menu's layout here.. */
32 #define WPLANE           (TILE_MEM_END + 0x0000)
33 #define HSCRL            (TILE_MEM_END + 0x0800)
34 #define SLIST            (TILE_MEM_END + 0x0C00)
35 #define APLANE           (TILE_MEM_END + 0x1000)
36 #define BPLANE           (TILE_MEM_END + 0x3000)
37
38 #define read8(a) \
39     *((volatile u8 *) (a))
40 #define read16(a) \
41     *((volatile u16 *) (a))
42 #define read32(a) \
43     *((volatile u32 *) (a))
44 #define write8(a, d) \
45     *((volatile u8 *) (a)) = (d)
46 #define write16(a, d) \
47     *((volatile u16 *) (a)) = (d)
48 #define write32(a, d) \
49     *((volatile u32 *) (a)) = (d)
50
51 #define write16_z80le(a, d) \
52     ((volatile u8 *)(a))[0] = (u8)(d), \
53     ((volatile u8 *)(a))[1] = ((d) >> 8)
54
55 static inline u16 read16_z80le(const void *a_)
56 {
57     volatile const u8 *a = (volatile const u8 *)a_;
58     return a[0] | ((u16)a[1] << 8);
59 }
60
61 #define CTL_WRITE_VRAM(adr) \
62     (((0x4000 | ((adr) & 0x3FFF)) << 16) | ((adr) >> 14) | 0x00)
63 #define CTL_WRITE_VSRAM(adr) \
64     (((0x4000 | ((adr) & 0x3FFF)) << 16) | ((adr) >> 14) | 0x10)
65 #define CTL_WRITE_CRAM(adr) \
66     (((0xC000 | ((adr) & 0x3FFF)) << 16) | ((adr) >> 14) | 0x00)
67 #define CTL_READ_VRAM(adr) \
68     (((0x0000 | ((adr) & 0x3FFF)) << 16) | ((adr) >> 14) | 0x00)
69 #define CTL_READ_VSRAM(adr) \
70     (((0x0000 | ((adr) & 0x3FFF)) << 16) | ((adr) >> 14) | 0x10)
71 #define CTL_READ_CRAM(adr) \
72     (((0x0000 | ((adr) & 0x3FFF)) << 16) | ((adr) >> 14) | 0x20)
73
74 #define CTL_WRITE_DMA 0x80
75
76 #define VDP_setReg(r, v) \
77     write16(VDP_CTRL_PORT, 0x8000 | ((r) << 8) | ((v) & 0xff))
78
79 enum {
80     VDP_MODE1 = 0x00,
81     VDP_MODE2 = 0x01,
82     VDP_NT_SCROLLA = 0x02,
83     VDP_NT_WIN = 0x03,
84     VDP_NT_SCROLLB = 0x04,
85     VDP_SAT_BASE = 0x05,
86     VDP_BACKDROP = 0x07,
87     VDP_MODE3 = 0x0b,
88     VDP_MODE4 = 0x0c,
89     VDP_HSCROLL = 0x0d,
90     VDP_AUTOINC = 0x0f,
91     VDP_SCROLLSZ = 0x10,
92     VDP_DMA_LEN0 = 0x13,
93     VDP_DMA_LEN1 = 0x14,
94     VDP_DMA_SRC0 = 0x15,
95     VDP_DMA_SRC1 = 0x16,
96     VDP_DMA_SRC2 = 0x17,
97 };
98
99 #define VDP_MODE1_PS   0x04
100 #define VDP_MODE1_IE1  0x10 // h int
101 #define VDP_MODE2_MD   0x04
102 #define VDP_MODE2_PAL  0x08 // 30 col
103 #define VDP_MODE2_DMA  0x10
104 #define VDP_MODE2_IE0  0x20 // v int
105 #define VDP_MODE2_DISP 0x40
106
107 /* cell counts */
108 #define LEFT_BORDER 1   /* lame TV */
109 #define PLANE_W 64
110 #define PLANE_H 32
111 #define CSCREEN_H 28
112
113 /* data.s */
114 extern const u32 font_base[];
115 extern const u8 z80_test[];
116 extern const u8 z80_test_end[];
117
118 static int text_pal;
119
120 static noinline void VDP_drawTextML(const char *str, u16 plane_base,
121     u16 x, u16 y)
122 {
123     const u8 *src = (const u8 *)str;
124     u16 basetile = text_pal << 13;
125     int max_len = 40 - LEFT_BORDER;
126     int len;
127     u32 addr;
128
129     x += LEFT_BORDER;
130
131     for (len = 0; str[len] && len < max_len; len++)
132         ;
133     if (len > (PLANE_W - x))
134         len = PLANE_W - x;
135
136     addr = plane_base + ((x + (PLANE_W * y)) << 1);
137     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(addr));
138
139     while (len-- > 0) {
140         write16(VDP_DATA_PORT,
141             basetile | ((*src++) - 32 + TILE_FONT_BASE / 32));
142     }
143 }
144
145 static int printf_ypos;
146
147 static void printf_line(int x, const char *buf)
148 {
149     u32 addr;
150     int i;
151
152     VDP_drawTextML(buf, APLANE, x, printf_ypos++ & (PLANE_H - 1));
153
154     if (printf_ypos >= CSCREEN_H) {
155         /* clear next line */
156         addr = APLANE;
157         addr += (PLANE_W * (printf_ypos & (PLANE_H - 1))) << 1;
158         write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(addr));
159         for (i = 0; i < 40 / 2; i++)
160             write32(VDP_DATA_PORT, 0);
161
162         /* scroll plane */
163         write32(VDP_CTRL_PORT, CTL_WRITE_VSRAM(0));
164         write16(VDP_DATA_PORT, (printf_ypos - CSCREEN_H + 1) * 8);
165     }
166 }
167
168 #define PRINTF_LEN 40
169
170 static int printf_xpos;
171
172 static noinline int printf(const char *fmt, ...)
173 {
174     static const char hexchars[] = "0123456789abcdef";
175     char c, buf[PRINTF_LEN + 11 + 1];
176     const char *s;
177     va_list ap;
178     int ival;
179     u32 uval;
180     int d = 0;
181     int i, j;
182
183     va_start(ap, fmt);
184     for (d = 0; *fmt; ) {
185         int prefix0 = 0;
186         int fwidth = 0;
187
188         c = *fmt++;
189         if (d < PRINTF_LEN)
190             buf[d] = c;
191
192         if (c != '%') {
193             if (c == '\n') {
194                 buf[d] = 0;
195                 printf_line(printf_xpos, buf);
196                 d = 0;
197                 printf_xpos = 0;
198                 continue;
199             }
200             d++;
201             continue;
202         }
203         if (d >= PRINTF_LEN)
204             continue;
205
206         if (*fmt == '0') {
207             prefix0 = 1;
208             fmt++;
209         }
210
211         while ('1' <= *fmt && *fmt <= '9') {
212             fwidth = fwidth * 10 + *fmt - '0';
213             fmt++;
214         }
215
216         switch (*fmt++) {
217         case '%':
218             d++;
219             break;
220         case 'd':
221         case 'i':
222             ival = va_arg(ap, int);
223             if (ival < 0) {
224                 buf[d++] = '-';
225                 ival = -ival;
226             }
227             for (i = 1000000000; i >= 10; i /= 10)
228                 if (ival >= i)
229                     break;
230             for (; i >= 10; i /= 10) {
231                 buf[d++] = '0' + ival / i;
232                 ival %= i;
233             }
234             buf[d++] = '0' + ival;
235             break;
236         case 'x':
237             uval = va_arg(ap, int);
238             while (fwidth > 1 && uval < (1 << (fwidth - 1) * 4)) {
239                 buf[d++] = prefix0 ? '0' : ' ';
240                 fwidth--;
241             }
242             for (j = 1; j < 8 && uval >= (1 << j * 4); j++)
243                 ;
244             for (j--; j >= 0; j--)
245                 buf[d++] = hexchars[(uval >> j * 4) & 0x0f];
246             break;
247         case 's':
248             s = va_arg(ap, char *);
249             while (*s && d < PRINTF_LEN)
250                 buf[d++] = *s++;
251             break;
252         default:
253             // don't handle, for now
254             d++;
255             va_arg(ap, void *);
256             break;
257         }
258     }
259     buf[d] = 0;
260     va_end(ap);
261
262     if (d != 0) {
263         // line without \n
264         VDP_drawTextML(buf, APLANE, printf_xpos,
265             printf_ypos & (PLANE_H - 1));
266         printf_xpos += d;
267     }
268
269     return d; // wrong..
270 }
271
272 static const char *exc_names[] = {
273     NULL,
274     NULL,
275     "Bus Error",
276     "Address Error",
277     "Illegal Instruction",
278     "Zero Divide",
279     "CHK Instruction",
280     "TRAPV Instruction",
281     "Privilege Violation",  /*  8  8 */
282     "Trace",
283     "Line 1010 Emulator",
284     "Line 1111 Emulator",
285     NULL,
286     NULL,
287     NULL,
288     "Uninitialized Interrupt",
289     NULL,                   /* 10 16 */
290     NULL,
291     NULL,
292     NULL,
293     NULL,
294     NULL,
295     NULL,
296     NULL,
297     "Spurious Interrupt",   /* 18 24 */
298     "l1 irq",
299     "l2 irq",
300     "l3 irq",
301     "l4 irq",
302     "l5 irq",
303     "l6 irq",
304     "l7 irq",
305 };
306
307 struct exc_frame {
308     u32 dr[8];
309     u32 ar[8];
310     u16 ecxnum; // from handler
311     union {
312         struct {
313             u16 sr;
314             u32 pc;
315         } g _packed;
316         struct {
317             u16 fc;
318             u32 addr;
319             u16 ir;
320             u16 sr;
321             u32 pc;
322         } bae _packed; // bus/address error frame
323     };
324 } _packed;
325
326 int xtttt(void) { return sizeof(struct exc_frame); }
327
328 void exception(const struct exc_frame *f)
329 {
330     int i;
331
332     while (read16(VDP_CTRL_PORT) & 2)
333         ;
334     VDP_setReg(VDP_MODE1, VDP_MODE1_PS);
335     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DISP);
336     /* adjust scroll */
337     write32(VDP_CTRL_PORT, CTL_WRITE_VSRAM(0));
338     write16(VDP_DATA_PORT,
339       printf_ypos >= CSCREEN_H ?
340         (printf_ypos - CSCREEN_H + 1) * 8 : 0);
341
342     printf("exception %i ", f->ecxnum);
343     if (f->ecxnum < ARRAY_SIZE(exc_names) && exc_names[f->ecxnum] != NULL)
344         printf("(%s)", exc_names[f->ecxnum]);
345     if (f->ecxnum < 4)
346         printf(" (%s)", (f->bae.fc & 0x10) ? "r" : "w");
347     printf("    \n");
348
349     if (f->ecxnum < 4) {
350         printf("  PC: %08x SR: %04x    \n", f->bae.pc, f->bae.sr);
351         printf("addr: %08x IR: %04x FC: %02x   \n",
352                f->bae.addr, f->bae.ir, f->bae.fc);
353     }
354     else {
355         printf("  PC: %08x SR: %04x    \n", f->g.pc, f->g.sr);
356     }
357     for (i = 0; i < 8; i++)
358         printf("  D%d: %08x A%d: %08x    \n", i, f->dr[i], i, f->ar[i]);
359     printf("                       \n");
360 }
361
362 // ---
363
364 static void setup_default_palette(void)
365 {
366     write32(VDP_CTRL_PORT, CTL_WRITE_CRAM(0));
367     write32(VDP_DATA_PORT, 0);
368     write32(VDP_CTRL_PORT, CTL_WRITE_CRAM(15 * 2)); // font normal
369     write16(VDP_DATA_PORT, 0xeee);
370     write32(VDP_CTRL_PORT, CTL_WRITE_CRAM(31 * 2)); // green
371     write16(VDP_DATA_PORT, 0x0e0);
372     write32(VDP_CTRL_PORT, CTL_WRITE_CRAM(47 * 2)); // red
373     write16(VDP_DATA_PORT, 0x00e);
374 }
375
376 static void do_setup_dma(const void *src_, u16 words)
377 {
378     u32 src = (u32)src_;
379     // VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA);
380     VDP_setReg(VDP_DMA_LEN0, words);
381     VDP_setReg(VDP_DMA_LEN1, words >> 8);
382     VDP_setReg(VDP_DMA_SRC0, src >> 1);
383     VDP_setReg(VDP_DMA_SRC1, src >> 9);
384     VDP_setReg(VDP_DMA_SRC2, src >> 17);
385     // write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(addr) | CTL_WRITE_DMA);
386 }
387
388 static void t_dma_zero_wrap_early(void)
389 {
390     const u32 *src = (const u32 *)0x3c0000;
391     u32 *ram = (u32 *)0xff0000;
392
393     do_setup_dma(src + 4, 2);
394     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0) | CTL_WRITE_DMA);
395     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0) | CTL_WRITE_DMA);
396
397     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0));
398     ram[0] = read32(VDP_DATA_PORT);
399     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0xfffc));
400     ram[1] = read32(VDP_DATA_PORT);
401 }
402
403 static void t_dma_zero_fill_early(void)
404 {
405     u32 *ram = (u32 *)0xff0000;
406
407     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0));
408     write32(VDP_DATA_PORT, 0);
409     write32(VDP_DATA_PORT, 0);
410     write32(VDP_DATA_PORT, 0);
411     write32(VDP_DATA_PORT, 0);
412
413     VDP_setReg(VDP_AUTOINC, 1);
414     VDP_setReg(VDP_DMA_SRC2, 0x80);
415     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(1) | CTL_WRITE_DMA);
416     write16(VDP_DATA_PORT, 0x1122);
417     ram[2] = read16(VDP_CTRL_PORT);
418     while (read16(VDP_CTRL_PORT) & 2)
419         ;
420
421     VDP_setReg(VDP_AUTOINC, 2);
422     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0));
423     ram[3] = read32(VDP_DATA_PORT);
424 }
425
426 #define expect(ok_, v0_, v1_) \
427 if ((v0_) != (v1_)) { \
428     printf("%s: %08x %08x\n", #v0_, v0_, v1_); \
429     ok_ = 0; \
430 }
431
432 static int t_dma_zero_wrap(void)
433 {
434     const u32 *src = (const u32 *)0x3c0000;
435     const u32 *ram = (const u32 *)0xff0000;
436     int ok = 1;
437
438     expect(ok, ram[0], src[5 + 0x10000/4]);
439     expect(ok, ram[1], src[4]);
440     return ok;
441 }
442
443 static int t_dma_zero_fill(void)
444 {
445     const u32 *ram = (const u32 *)0xff0000;
446     u32 v0 = ram[2] & 2;
447     int ok = 1;
448
449     expect(ok, v0, 2);
450     expect(ok, ram[3], 0x11111111);
451     return ok;
452 }
453
454 static int t_dma_ram_wrap(void)
455 {
456     u32 *ram = (u32 *)0xff0000;
457     u32 saved, v0, v1;
458     int ok = 1;
459
460     saved = read32(&ram[0x10000/4 - 1]);
461     ram[0x10000/4 - 1] = 0x01020304;
462     ram[0] = 0x05060708;
463     do_setup_dma(&ram[0x10000/4 - 1], 4);
464     mem_barrier();
465     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100) | CTL_WRITE_DMA);
466
467     mem_barrier();
468     write32(&ram[0x10000/4 - 1], saved);
469
470     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x100));
471     v0 = read32(VDP_DATA_PORT);
472     v1 = read32(VDP_DATA_PORT);
473
474     expect(ok, v0, 0x01020304);
475     expect(ok, v1, 0x05060708);
476     return ok;
477 }
478
479 // test no src reprogram, only len0
480 static int t_dma_multi(void)
481 {
482     const u32 *src = (const u32 *)0x3c0000;
483     u32 v0, v1;
484     int ok = 1;
485
486     do_setup_dma(src, 2);
487     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100) | CTL_WRITE_DMA);
488     VDP_setReg(VDP_DMA_LEN0, 2);
489     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x104) | CTL_WRITE_DMA);
490
491     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x100));
492     v0 = read32(VDP_DATA_PORT);
493     v1 = read32(VDP_DATA_PORT);
494
495     expect(ok, v0, src[0]);
496     expect(ok, v1, src[1]);
497     return ok;
498 }
499
500 static int t_dma_cram_wrap(void)
501 {
502     u32 *ram = (u32 *)0xff0000;
503     u32 v0, v1;
504     int ok = 1;
505
506     write32(VDP_CTRL_PORT, CTL_WRITE_CRAM(0));
507     write32(VDP_DATA_PORT, 0);
508
509     ram[0] = 0x0ec20ec4;
510     ram[1] = 0x0ec60ec8;
511     mem_barrier();
512     do_setup_dma(ram, 4);
513     write32(VDP_CTRL_PORT, CTL_WRITE_CRAM(0x7c | 0xff81) | CTL_WRITE_DMA);
514
515     write32(VDP_CTRL_PORT, CTL_READ_CRAM(0x7c));
516     v0 = read32(VDP_DATA_PORT) & 0x0eee0eee;
517     write32(VDP_CTRL_PORT, CTL_READ_CRAM(0));
518     v1 = read32(VDP_DATA_PORT) & 0x0eee0eee;
519
520     setup_default_palette();
521
522     expect(ok, v0, ram[0]);
523     expect(ok, v1, ram[1]);
524     return ok;
525 }
526
527 static int t_dma_vsram_wrap(void)
528 {
529     u32 *ram32 = (u32 *)0xff0000;
530     u16 *ram16 = (u16 *)0xff0000;
531     u32 v0, v1;
532     int ok = 1;
533     int i;
534
535     write32(VDP_CTRL_PORT, CTL_WRITE_VSRAM(0));
536     write32(VDP_DATA_PORT, 0);
537
538     for (i = 0; i < 0x48/2; i++)
539         ram16[i] = i + 1;
540     mem_barrier();
541     do_setup_dma(ram16, 0x48/2);
542     write32(VDP_CTRL_PORT, CTL_WRITE_VSRAM(0x3c | 0xff81) | CTL_WRITE_DMA);
543
544     write32(VDP_CTRL_PORT, CTL_READ_VSRAM(0x3c));
545     v0 = read32(VDP_DATA_PORT) & 0x03ff03ff;
546     write32(VDP_CTRL_PORT, CTL_READ_VSRAM(0));
547     v1 = read32(VDP_DATA_PORT) & 0x03ff03ff;
548
549     write32(VDP_CTRL_PORT, CTL_WRITE_VSRAM(0));
550     write32(VDP_DATA_PORT, 0);
551
552     expect(ok, v0, ram32[0]);
553     expect(ok, v1, ram32[0x48/4 - 1]);
554     return ok;
555 }
556
557 static int t_dma_and_data(void)
558 {
559     const u32 *src = (const u32 *)0x3c0000;
560     u32 v0;
561     int ok = 1;
562
563     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100));
564     write32(VDP_DATA_PORT, 0);
565
566     do_setup_dma(src, 2);
567     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0xfc) | CTL_WRITE_DMA);
568     write32(VDP_DATA_PORT, 0x5ec8a248);
569
570     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x100));
571     v0 = read32(VDP_DATA_PORT);
572
573     expect(ok, v0, 0x5ec8a248);
574     return ok;
575 }
576
577 static int t_dma_fill3_odd(void)
578 {
579     u32 v0, v1, v2;
580     int ok = 1;
581
582     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100));
583     write32(VDP_DATA_PORT, 0);
584     write32(VDP_DATA_PORT, 0);
585     write32(VDP_DATA_PORT, 0);
586
587     VDP_setReg(VDP_AUTOINC, 3);
588     VDP_setReg(VDP_DMA_LEN0, 3);
589     VDP_setReg(VDP_DMA_SRC2, 0x80);
590     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x101) | CTL_WRITE_DMA);
591     write16(VDP_DATA_PORT, 0x1122);
592     while (read16(VDP_CTRL_PORT) & 2)
593         ;
594
595     VDP_setReg(VDP_AUTOINC, 2);
596     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x100));
597     v0 = read32(VDP_DATA_PORT);
598     v1 = read32(VDP_DATA_PORT);
599     v2 = read32(VDP_DATA_PORT);
600
601     expect(ok, v0, 0x22110000);
602     expect(ok, v1, 0x00111100);
603     expect(ok, v2, 0x00000011);
604     return ok;
605 }
606
607 static int t_dma_fill3_even(void)
608 {
609     u32 v0, v1, v2;
610     int ok = 1;
611
612     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100));
613     write32(VDP_DATA_PORT, 0);
614     write32(VDP_DATA_PORT, 0);
615     write32(VDP_DATA_PORT, 0);
616
617     VDP_setReg(VDP_AUTOINC, 3);
618     VDP_setReg(VDP_DMA_LEN0, 3);
619     VDP_setReg(VDP_DMA_SRC2, 0x80);
620     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100) | CTL_WRITE_DMA);
621     write16(VDP_DATA_PORT, 0x1122);
622     while (read16(VDP_CTRL_PORT) & 2)
623         ;
624
625     VDP_setReg(VDP_AUTOINC, 2);
626     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x100));
627     v0 = read32(VDP_DATA_PORT);
628     v1 = read32(VDP_DATA_PORT);
629     v2 = read32(VDP_DATA_PORT);
630
631     expect(ok, v0, 0x11221100);
632     expect(ok, v1, 0x00000011);
633     expect(ok, v2, 0x11000000);
634     return ok;
635 }
636
637 static unused int t_dma_fill3_vsram(void)
638 {
639     u32 v0, v1, v2;
640     int ok = 1;
641
642     write32(VDP_CTRL_PORT, CTL_WRITE_VSRAM(0));
643     write32(VDP_DATA_PORT, 0);
644     write32(VDP_DATA_PORT, 0);
645     write32(VDP_DATA_PORT, 0);
646
647     write16(VDP_DATA_PORT, 0x0111);
648     write16(VDP_DATA_PORT, 0x0222);
649     write16(VDP_DATA_PORT, 0x0333);
650
651     VDP_setReg(VDP_AUTOINC, 3);
652     VDP_setReg(VDP_DMA_LEN0, 3);
653     VDP_setReg(VDP_DMA_SRC2, 0x80);
654     write32(VDP_CTRL_PORT, CTL_WRITE_VSRAM(1) | CTL_WRITE_DMA);
655     write16(VDP_DATA_PORT, 0x0102);
656     while (read16(VDP_CTRL_PORT) & 2)
657         ;
658
659     VDP_setReg(VDP_AUTOINC, 2);
660     write32(VDP_CTRL_PORT, CTL_READ_VSRAM(0));
661     v0 = read32(VDP_DATA_PORT);
662     v1 = read32(VDP_DATA_PORT);
663     v2 = read32(VDP_DATA_PORT);
664
665     write32(VDP_CTRL_PORT, CTL_WRITE_VSRAM(0));
666     write32(VDP_DATA_PORT, 0);
667
668     expect(ok, v0, 0x01020000);
669     expect(ok, v1, 0x01110111);
670     expect(ok, v2, 0x00000111);
671     return ok;
672 }
673
674 static int t_dma_fill_dis(void)
675 {
676     u32 v0, v1;
677     int ok = 1;
678
679     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100));
680     write32(VDP_DATA_PORT, 0);
681     write32(VDP_DATA_PORT, 0);
682
683     VDP_setReg(VDP_DMA_LEN0, 1);
684     VDP_setReg(VDP_DMA_SRC2, 0x80);
685     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100) | CTL_WRITE_DMA);
686     VDP_setReg(VDP_MODE2, VDP_MODE2_MD);
687     write16(VDP_DATA_PORT, 0x1122);
688     while (read16(VDP_CTRL_PORT) & 2)
689         ;
690
691     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_DISP);
692     write16(VDP_DATA_PORT, 0x3344);
693     while (read16(VDP_CTRL_PORT) & 2)
694         ;
695
696     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x100));
697     v0 = read32(VDP_DATA_PORT);
698     v1 = read32(VDP_DATA_PORT);
699
700     expect(ok, v0, 0);
701     expect(ok, v1, 0);
702     return ok;
703 }
704
705 static int t_dma_fill_src(void)
706 {
707     const u32 *src = (const u32 *)0x3c0000;
708     u32 v0, v1;
709     int ok = 1;
710
711     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100));
712     write32(VDP_DATA_PORT, 0);
713
714     // do_setup_dma(src, 2); // hang, can't write src2 twice
715     VDP_setReg(VDP_DMA_LEN0, 2);
716     VDP_setReg(VDP_DMA_SRC0, (u32)src >> 1);
717     VDP_setReg(VDP_DMA_SRC1, (u32)src >> 9);
718     VDP_setReg(VDP_DMA_SRC2, 0x80);
719     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100) | CTL_WRITE_DMA);
720     write16(VDP_DATA_PORT, 0x1122);
721     while (read16(VDP_CTRL_PORT) & 2)
722         ;
723
724     VDP_setReg(VDP_DMA_LEN0, 2);
725     VDP_setReg(VDP_DMA_SRC2, (u32)src >> 17);
726     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x104) | CTL_WRITE_DMA);
727
728     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x100));
729     v0 = read32(VDP_DATA_PORT);
730     v1 = read32(VDP_DATA_PORT);
731
732     expect(ok, v0, 0x11220011);
733     expect(ok, v1, src[1]);
734     return ok;
735 }
736
737 /* z80 tests assume busreq state */
738 static int t_z80mem_long_mirror(void)
739 {
740     u8 *zram = (u8 *)0xa00000;
741     int ok = 1;
742
743     write8(&zram[0x1100], 0x11);
744     write8(&zram[0x1101], 0x22);
745     write8(&zram[0x1102], 0x33);
746     write8(&zram[0x1103], 0x44);
747     mem_barrier();
748     write32(&zram[0x3100], 0x55667788);
749     mem_barrier();
750
751     expect(ok, zram[0x1100], 0x55);
752     expect(ok, zram[0x1101], 0x22);
753     expect(ok, zram[0x1102], 0x77);
754     expect(ok, zram[0x1103], 0x44);
755     return ok;
756 }
757
758 static int t_z80mem_vdp_r(void)
759 {
760     u8 *zram = (u8 *)0xa00000;
761     int ok = 1;
762
763     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100));
764     write32(VDP_DATA_PORT, 0x11223344);
765     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x100));
766
767     zram[0x1000] = 1; // cp
768     zram[0x1001] = 2; // len
769     write16_z80le(&zram[0x1002], 0x7f00); // src
770     write16_z80le(&zram[0x1004], 0x1006); // dst
771     zram[0x1006] = zram[0x1007] = zram[0x1008] = 0x5a;
772     mem_barrier();
773     write16(0xa11100, 0x000);
774     burn10((98 + 40*2 + 27) * 15 / 7 * 2 / 10);
775
776     write16(0xa11100, 0x100);
777     while (read16(0xa11100) & 0x100)
778         ;
779
780     expect(ok, zram[0x1000], 0);
781     expect(ok, zram[0x1006], 0x11);
782     expect(ok, zram[0x1007], 0x44);
783     expect(ok, zram[0x1008], 0x5a);
784     return ok;
785 }
786
787 static unused int t_z80mem_vdp_w(void)
788 {
789     u8 *zram = (u8 *)0xa00000;
790     u32 v0;
791     int ok = 1;
792
793     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100));
794     write32(VDP_DATA_PORT, 0x11223344);
795     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100));
796
797     zram[0x1000] = 1; // cp
798     zram[0x1001] = 2; // len
799     write16_z80le(&zram[0x1002], 0x1006); // src
800     write16_z80le(&zram[0x1004], 0x7f00); // dst
801     zram[0x1006] = 0x55;
802     zram[0x1007] = 0x66;
803     mem_barrier();
804     write16(0xa11100, 0x000);
805     burn10((98 + 40*2 + 27) * 15 / 7 * 2 / 10);
806
807     write16(0xa11100, 0x100);
808     while (read16(0xa11100) & 0x100)
809         ;
810
811     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x100));
812     v0 = read32(VDP_DATA_PORT);
813
814     expect(ok, zram[0x1000], 0);
815     expect(ok, v0, 0x55556666);
816     return ok;
817 }
818
819 static const struct {
820     int (*test)(void);
821     const char *name;
822 } g_tests[] = {
823     { t_dma_zero_wrap,       "dma zero len + wrap" },
824     { t_dma_zero_fill,       "dma zero len + fill" },
825     { t_dma_ram_wrap,        "dma ram wrap" },
826     { t_dma_multi,           "dma multi" },
827     { t_dma_cram_wrap,       "dma cram wrap" },
828     { t_dma_vsram_wrap,      "dma vsram wrap" },
829     { t_dma_and_data,        "dma and data" },
830     { t_dma_fill3_odd,       "dma fill3 odd" },
831     { t_dma_fill3_even,      "dma fill3 even" },
832     // { t_dma_fill3_vsram,     "dma fill3 vsram" }, // later
833     { t_dma_fill_dis,        "dma fill disabled" },
834     { t_dma_fill_src,        "dma fill src incr" },
835     { t_z80mem_long_mirror,  "z80 ram long mirror" },
836     { t_z80mem_vdp_r,        "z80 vdp read" },
837     // { t_z80mem_vdp_w,        "z80 vdp write" }, // hang
838 };
839
840 static void setup_z80(void)
841 {
842     u8 *zram = (u8 *)0xa00000;
843     int i, len;
844
845     /* z80 */
846     write16(0xa11100, 0x100);
847     write16(0xa11200, 0x100);
848
849     while (read16(0xa11100) & 0x100)
850         ;
851
852     // load the default test program, clear it's data
853     len = z80_test_end - z80_test;
854     for (i = 0; i < len; i++)
855         write8(&zram[i], z80_test[i]);
856     for (i = 0x1000; i < 0x1007; i++)
857         write8(&zram[i], 0);
858 }
859
860 int main()
861 {
862     int passed = 0;
863     int ret;
864     int i;
865
866     setup_z80();
867
868     /* setup VDP */
869     while (read16(VDP_CTRL_PORT) & 2)
870         ;
871
872     VDP_setReg(VDP_MODE1, VDP_MODE1_PS);
873     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA);
874     VDP_setReg(VDP_MODE3, 0x00);
875     VDP_setReg(VDP_MODE4, 0x81);
876     VDP_setReg(VDP_NT_SCROLLA, APLANE >> 10);
877     VDP_setReg(VDP_NT_SCROLLB, BPLANE >> 13);
878     VDP_setReg(VDP_SAT_BASE, SLIST >> 9);
879     VDP_setReg(VDP_HSCROLL, HSCRL >> 10);
880     VDP_setReg(VDP_AUTOINC, 2);
881     VDP_setReg(VDP_SCROLLSZ, 0x01);
882     VDP_setReg(VDP_BACKDROP, 0);
883
884     // early tests
885     t_dma_zero_wrap_early();
886     t_dma_zero_fill_early();
887
888     /* pattern 0 */
889     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0));
890     for (i = 0; i < 32 / 4; i++)
891         write32(VDP_DATA_PORT, 0);
892
893     /* clear name tables */
894     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(APLANE));
895     for (i = 0; i < PLANE_W * PLANE_H / 2; i++)
896         write32(VDP_DATA_PORT, 0);
897
898     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(BPLANE));
899     for (i = 0; i < PLANE_W * PLANE_H / 2; i++)
900         write32(VDP_DATA_PORT, 0);
901
902     /* SAT, h. scroll */
903     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(SLIST));
904     write32(VDP_DATA_PORT, 0);
905
906     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(HSCRL));
907     write32(VDP_DATA_PORT, 0);
908
909     /* scroll plane vscroll */
910     write32(VDP_CTRL_PORT, CTL_WRITE_VSRAM(0));
911     write32(VDP_DATA_PORT, 0);
912     printf_ypos = 1;
913
914     /* load font */
915     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(TILE_FONT_BASE));
916     for (i = 0; i < FONT_LEN * 32 / 4; i++)
917         write32(VDP_DATA_PORT, font_base[i]);
918
919     /* set colors */
920     setup_default_palette();
921
922     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_DISP);
923
924     printf("\n");
925     printf("MD version: %02x\n", read8(0xa10001));
926
927     for (i = 0; i < ARRAY_SIZE(g_tests); i++) {
928         // print test number if we haven't scrolled away
929         if (printf_ypos < CSCREEN_H) {
930             int old_ypos = printf_ypos;
931             printf_ypos = 0;
932             text_pal = 0;
933             printf("%02d/%02d", i, ARRAY_SIZE(g_tests));
934             printf_ypos = old_ypos;
935             printf_xpos = 0;
936         }
937         text_pal = 2;
938         ret = g_tests[i].test();
939         if (ret != 1)
940             printf("failed %d: %s\n", i, g_tests[i].name);
941         else
942             passed++;
943     }
944
945     text_pal = 0;
946     printf("%d/%d passed.\n", passed, ARRAY_SIZE(g_tests));
947
948     printf_ypos = 0;
949     printf("     ");
950
951     for (;;)
952         ;
953
954     return 0;
955 }
956
957 // vim:ts=4:sw=4:expandtab