timing 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 #define VDP_HV_COUNTER   0xC00008
26
27 #define TILE_MEM_END     0xB000
28
29 #define FONT_LEN         128
30 #define TILE_FONT_BASE   (TILE_MEM_END - FONT_LEN * 32)
31
32 /* note: using ED menu's layout here.. */
33 #define WPLANE           (TILE_MEM_END + 0x0000)
34 #define HSCRL            (TILE_MEM_END + 0x0800)
35 #define SLIST            (TILE_MEM_END + 0x0C00)
36 #define APLANE           (TILE_MEM_END + 0x1000)
37 #define BPLANE           (TILE_MEM_END + 0x3000)
38
39 #define read8(a) \
40     *((volatile u8 *) (a))
41 #define read16(a) \
42     *((volatile u16 *) (a))
43 #define read32(a) \
44     *((volatile u32 *) (a))
45 #define write8(a, d) \
46     *((volatile u8 *) (a)) = (d)
47 #define write16(a, d) \
48     *((volatile u16 *) (a)) = (d)
49 #define write32(a, d) \
50     *((volatile u32 *) (a)) = (d)
51
52 #define write16_z80le(a, d) \
53     ((volatile u8 *)(a))[0] = (u8)(d), \
54     ((volatile u8 *)(a))[1] = ((d) >> 8)
55
56 static inline u16 read16_z80le(const void *a_)
57 {
58     volatile const u8 *a = (volatile const u8 *)a_;
59     return a[0] | ((u16)a[1] << 8);
60 }
61
62 #define CTL_WRITE_VRAM(adr) \
63     (((0x4000 | ((adr) & 0x3FFF)) << 16) | ((adr) >> 14) | 0x00)
64 #define CTL_WRITE_VSRAM(adr) \
65     (((0x4000 | ((adr) & 0x3FFF)) << 16) | ((adr) >> 14) | 0x10)
66 #define CTL_WRITE_CRAM(adr) \
67     (((0xC000 | ((adr) & 0x3FFF)) << 16) | ((adr) >> 14) | 0x00)
68 #define CTL_READ_VRAM(adr) \
69     (((0x0000 | ((adr) & 0x3FFF)) << 16) | ((adr) >> 14) | 0x00)
70 #define CTL_READ_VSRAM(adr) \
71     (((0x0000 | ((adr) & 0x3FFF)) << 16) | ((adr) >> 14) | 0x10)
72 #define CTL_READ_CRAM(adr) \
73     (((0x0000 | ((adr) & 0x3FFF)) << 16) | ((adr) >> 14) | 0x20)
74
75 #define CTL_WRITE_DMA 0x80
76
77 #define VDP_setReg(r, v) \
78     write16(VDP_CTRL_PORT, 0x8000 | ((r) << 8) | ((v) & 0xff))
79
80 enum {
81     VDP_MODE1 = 0x00,
82     VDP_MODE2 = 0x01,
83     VDP_NT_SCROLLA = 0x02,
84     VDP_NT_WIN = 0x03,
85     VDP_NT_SCROLLB = 0x04,
86     VDP_SAT_BASE = 0x05,
87     VDP_BACKDROP = 0x07,
88     VDP_MODE3 = 0x0b,
89     VDP_MODE4 = 0x0c,
90     VDP_HSCROLL = 0x0d,
91     VDP_AUTOINC = 0x0f,
92     VDP_SCROLLSZ = 0x10,
93     VDP_DMA_LEN0 = 0x13,
94     VDP_DMA_LEN1 = 0x14,
95     VDP_DMA_SRC0 = 0x15,
96     VDP_DMA_SRC1 = 0x16,
97     VDP_DMA_SRC2 = 0x17,
98 };
99
100 #define VDP_MODE1_PS   0x04
101 #define VDP_MODE1_IE1  0x10 // h int
102 #define VDP_MODE2_MD   0x04
103 #define VDP_MODE2_PAL  0x08 // 30 col
104 #define VDP_MODE2_DMA  0x10
105 #define VDP_MODE2_IE0  0x20 // v int
106 #define VDP_MODE2_DISP 0x40
107 #define VDP_MODE2_128K 0x80
108
109 #define SR_PAL        (1 << 0)
110 #define SR_DMA        (1 << 1)
111 #define SR_HB         (1 << 2)
112 #define SR_VB         (1 << 3)
113 #define SR_ODD        (1 << 4)
114 #define SR_C          (1 << 5)
115 #define SR_SOVR       (1 << 6)
116 #define SR_F          (1 << 7)
117 #define SR_FULL       (1 << 8)
118 #define SR_EMPT       (1 << 9)
119
120 /* cell counts */
121 #define LEFT_BORDER 1   /* lame TV */
122 #define PLANE_W 64
123 #define PLANE_H 32
124 #define CSCREEN_H 28
125
126 /* data.s */
127 extern const u32 font_base[];
128 extern const u8 z80_test[];
129 extern const u8 z80_test_end[];
130
131 static int text_pal;
132
133 static noinline void VDP_drawTextML(const char *str, u16 plane_base,
134     u16 x, u16 y)
135 {
136     const u8 *src = (const u8 *)str;
137     u16 basetile = text_pal << 13;
138     int max_len = 40 - LEFT_BORDER;
139     int len;
140     u32 addr;
141
142     x += LEFT_BORDER;
143
144     for (len = 0; str[len] && len < max_len; len++)
145         ;
146     if (len > (PLANE_W - x))
147         len = PLANE_W - x;
148
149     addr = plane_base + ((x + (PLANE_W * y)) << 1);
150     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(addr));
151
152     while (len-- > 0) {
153         write16(VDP_DATA_PORT,
154             basetile | ((*src++) - 32 + TILE_FONT_BASE / 32));
155     }
156 }
157
158 static int printf_ypos;
159
160 static void printf_line(int x, const char *buf)
161 {
162     u32 addr;
163     int i;
164
165     VDP_drawTextML(buf, APLANE, x, printf_ypos++ & (PLANE_H - 1));
166
167     if (printf_ypos >= CSCREEN_H) {
168         /* clear next line */
169         addr = APLANE;
170         addr += (PLANE_W * (printf_ypos & (PLANE_H - 1))) << 1;
171         write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(addr));
172         for (i = 0; i < 40 / 2; i++)
173             write32(VDP_DATA_PORT, 0);
174
175         /* scroll plane */
176         write32(VDP_CTRL_PORT, CTL_WRITE_VSRAM(0));
177         write16(VDP_DATA_PORT, (printf_ypos - CSCREEN_H + 1) * 8);
178     }
179 }
180
181 #define PRINTF_LEN 40
182
183 static int printf_xpos;
184
185 static noinline int printf(const char *fmt, ...)
186 {
187     static const char hexchars[] = "0123456789abcdef";
188     char c, buf[PRINTF_LEN + 11 + 1];
189     const char *s;
190     va_list ap;
191     int ival;
192     u32 uval;
193     int d = 0;
194     int i, j;
195
196     va_start(ap, fmt);
197     for (d = 0; *fmt; ) {
198         int prefix0 = 0;
199         int fwidth = 0;
200
201         c = *fmt++;
202         if (d < PRINTF_LEN)
203             buf[d] = c;
204
205         if (c != '%') {
206             if (c == '\n') {
207                 buf[d] = 0;
208                 printf_line(printf_xpos, buf);
209                 d = 0;
210                 printf_xpos = 0;
211                 continue;
212             }
213             d++;
214             continue;
215         }
216         if (d >= PRINTF_LEN)
217             continue;
218
219         if (*fmt == '0') {
220             prefix0 = 1;
221             fmt++;
222         }
223
224         while ('1' <= *fmt && *fmt <= '9') {
225             fwidth = fwidth * 10 + *fmt - '0';
226             fmt++;
227         }
228
229         switch (*fmt++) {
230         case '%':
231             d++;
232             break;
233         case 'd':
234         case 'i':
235             ival = va_arg(ap, int);
236             if (ival < 0) {
237                 buf[d++] = '-';
238                 ival = -ival;
239             }
240             for (i = 1000000000; i >= 10; i /= 10)
241                 if (ival >= i)
242                     break;
243             for (; i >= 10; i /= 10) {
244                 buf[d++] = '0' + ival / i;
245                 ival %= i;
246             }
247             buf[d++] = '0' + ival;
248             break;
249         case 'x':
250             uval = va_arg(ap, int);
251             while (fwidth > 1 && uval < (1 << (fwidth - 1) * 4)) {
252                 buf[d++] = prefix0 ? '0' : ' ';
253                 fwidth--;
254             }
255             for (j = 1; j < 8 && uval >= (1 << j * 4); j++)
256                 ;
257             for (j--; j >= 0; j--)
258                 buf[d++] = hexchars[(uval >> j * 4) & 0x0f];
259             break;
260         case 's':
261             s = va_arg(ap, char *);
262             while (*s && d < PRINTF_LEN)
263                 buf[d++] = *s++;
264             break;
265         default:
266             // don't handle, for now
267             d++;
268             va_arg(ap, void *);
269             break;
270         }
271     }
272     buf[d] = 0;
273     va_end(ap);
274
275     if (d != 0) {
276         // line without \n
277         VDP_drawTextML(buf, APLANE, printf_xpos,
278             printf_ypos & (PLANE_H - 1));
279         printf_xpos += d;
280     }
281
282     return d; // wrong..
283 }
284
285 static const char *exc_names[] = {
286     NULL,
287     NULL,
288     "Bus Error",
289     "Address Error",
290     "Illegal Instruction",
291     "Zero Divide",
292     "CHK Instruction",
293     "TRAPV Instruction",
294     "Privilege Violation",  /*  8  8 */
295     "Trace",
296     "Line 1010 Emulator",
297     "Line 1111 Emulator",
298     NULL,
299     NULL,
300     NULL,
301     "Uninitialized Interrupt",
302     NULL,                   /* 10 16 */
303     NULL,
304     NULL,
305     NULL,
306     NULL,
307     NULL,
308     NULL,
309     NULL,
310     "Spurious Interrupt",   /* 18 24 */
311     "l1 irq",
312     "l2 irq",
313     "l3 irq",
314     "l4 irq",
315     "l5 irq",
316     "l6 irq",
317     "l7 irq",
318 };
319
320 struct exc_frame {
321     u32 dr[8];
322     u32 ar[8];
323     u16 ecxnum; // from handler
324     union {
325         struct {
326             u16 sr;
327             u32 pc;
328         } g _packed;
329         struct {
330             u16 fc;
331             u32 addr;
332             u16 ir;
333             u16 sr;
334             u32 pc;
335         } bae _packed; // bus/address error frame
336     };
337 } _packed;
338
339 int xtttt(void) { return sizeof(struct exc_frame); }
340
341 void exception(const struct exc_frame *f)
342 {
343     int i;
344
345     while (read16(VDP_CTRL_PORT) & 2)
346         ;
347     VDP_setReg(VDP_MODE1, VDP_MODE1_PS);
348     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DISP);
349     /* adjust scroll */
350     write32(VDP_CTRL_PORT, CTL_WRITE_VSRAM(0));
351     write16(VDP_DATA_PORT,
352       printf_ypos >= CSCREEN_H ?
353         (printf_ypos - CSCREEN_H + 1) * 8 : 0);
354
355     printf("exception %i ", f->ecxnum);
356     if (f->ecxnum < ARRAY_SIZE(exc_names) && exc_names[f->ecxnum] != NULL)
357         printf("(%s)", exc_names[f->ecxnum]);
358     if (f->ecxnum < 4)
359         printf(" (%s)", (f->bae.fc & 0x10) ? "r" : "w");
360     printf("    \n");
361
362     if (f->ecxnum < 4) {
363         printf("  PC: %08x SR: %04x    \n", f->bae.pc, f->bae.sr);
364         printf("addr: %08x IR: %04x FC: %02x   \n",
365                f->bae.addr, f->bae.ir, f->bae.fc);
366     }
367     else {
368         printf("  PC: %08x SR: %04x    \n", f->g.pc, f->g.sr);
369     }
370     for (i = 0; i < 8; i++)
371         printf("  D%d: %08x A%d: %08x    \n", i, f->dr[i], i, f->ar[i]);
372     printf("                       \n");
373 }
374
375 // ---
376
377 static void setup_default_palette(void)
378 {
379     write32(VDP_CTRL_PORT, CTL_WRITE_CRAM(0));
380     write32(VDP_DATA_PORT, 0);
381     write32(VDP_CTRL_PORT, CTL_WRITE_CRAM(15 * 2)); // font normal
382     write16(VDP_DATA_PORT, 0xeee);
383     write32(VDP_CTRL_PORT, CTL_WRITE_CRAM(31 * 2)); // green
384     write16(VDP_DATA_PORT, 0x0e0);
385     write32(VDP_CTRL_PORT, CTL_WRITE_CRAM(47 * 2)); // red
386     write16(VDP_DATA_PORT, 0x00e);
387 }
388
389 static void do_setup_dma(const void *src_, u16 words)
390 {
391     u32 src = (u32)src_;
392     // VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA);
393     VDP_setReg(VDP_DMA_LEN0, words);
394     VDP_setReg(VDP_DMA_LEN1, words >> 8);
395     VDP_setReg(VDP_DMA_SRC0, src >> 1);
396     VDP_setReg(VDP_DMA_SRC1, src >> 9);
397     VDP_setReg(VDP_DMA_SRC2, src >> 17);
398     // write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(addr) | CTL_WRITE_DMA);
399 }
400
401 static void vdp_wait_for_fifo_empty(void)
402 {
403     while (!(read16(VDP_CTRL_PORT) & 0x200))
404         /* fifo not empty */;
405 }
406
407 static void vdp_wait_for_dma_idle(void)
408 {
409     while (read16(VDP_CTRL_PORT) & 2)
410         /* dma busy */;
411 }
412
413 static void vdp_wait_for_line_0(void)
414 {
415     // in PAL vcounter reports 0 twice in a frame,
416     // so wait for vblank to clear first
417     while (!(read16(VDP_CTRL_PORT) & 8))
418         /* not blanking */;
419     while (read16(VDP_CTRL_PORT) & 8)
420         /* blanking */;
421     while (read8(VDP_HV_COUNTER) != 0)
422         ;
423 }
424
425 static void t_dma_zero_wrap_early(void)
426 {
427     const u32 *src = (const u32 *)0x3c0000;
428     u32 *ram = (u32 *)0xff0000;
429
430     do_setup_dma(src + 4, 2);
431     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0) | CTL_WRITE_DMA);
432     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0) | CTL_WRITE_DMA);
433
434     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0));
435     ram[0] = read32(VDP_DATA_PORT);
436     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0xfffc));
437     ram[1] = read32(VDP_DATA_PORT);
438 }
439
440 static void t_dma_zero_fill_early(void)
441 {
442     u32 *ram = (u32 *)0xff0000;
443
444     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0));
445     write32(VDP_DATA_PORT, 0);
446     write32(VDP_DATA_PORT, 0);
447     write32(VDP_DATA_PORT, 0);
448     write32(VDP_DATA_PORT, 0);
449
450     VDP_setReg(VDP_AUTOINC, 1);
451     VDP_setReg(VDP_DMA_SRC2, 0x80);
452     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(1) | CTL_WRITE_DMA);
453     write16(VDP_DATA_PORT, 0x1122);
454     ram[2] = read16(VDP_CTRL_PORT);
455     vdp_wait_for_dma_idle();
456
457     VDP_setReg(VDP_AUTOINC, 2);
458     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0));
459     ram[3] = read32(VDP_DATA_PORT);
460 }
461
462 #define expect(ok_, v0_, v1_) \
463 if ((v0_) != (v1_)) { \
464     printf("%s: %08x %08x\n", #v0_, v0_, v1_); \
465     ok_ = 0; \
466 }
467
468 #define expect_range(ok_, v0_, vmin_, vmax_) \
469 if ((v0_) < (vmin_) || (v0_) > (vmax_)) { \
470     printf("%s: %02x /%02x-%02x\n", #v0_, v0_, vmin_, vmax_); \
471     ok_ = 0; \
472 }
473
474 #define expect_bits(ok_, v0_, val_, mask_) \
475 if (((v0_) & (mask_)) != (val_)) { \
476     printf("%s: %04x & %04x != %04x\n", #v0_, v0_, mask_, val_); \
477     ok_ = 0; \
478 }
479
480 static int t_dma_zero_wrap(void)
481 {
482     const u32 *src = (const u32 *)0x3c0000;
483     const u32 *ram = (const u32 *)0xff0000;
484     int ok = 1;
485
486     expect(ok, ram[0], src[5 + 0x10000/4]);
487     expect(ok, ram[1], src[4]);
488     return ok;
489 }
490
491 static int t_dma_zero_fill(void)
492 {
493     const u32 *ram = (const u32 *)0xff0000;
494     u32 v0 = ram[2] & 2;
495     int ok = 1;
496
497     expect(ok, v0, 2);
498     expect(ok, ram[3], 0x11111111);
499     return ok;
500 }
501
502 static int t_dma_ram_wrap(void)
503 {
504     u32 *ram = (u32 *)0xff0000;
505     u32 saved, v0, v1;
506     int ok = 1;
507
508     saved = read32(&ram[0x10000/4 - 1]);
509     ram[0x10000/4 - 1] = 0x01020304;
510     ram[0] = 0x05060708;
511     do_setup_dma(&ram[0x10000/4 - 1], 4);
512     mem_barrier();
513     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100) | CTL_WRITE_DMA);
514
515     mem_barrier();
516     write32(&ram[0x10000/4 - 1], saved);
517
518     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x100));
519     v0 = read32(VDP_DATA_PORT);
520     v1 = read32(VDP_DATA_PORT);
521
522     expect(ok, v0, 0x01020304);
523     expect(ok, v1, 0x05060708);
524     return ok;
525 }
526
527 // test no src reprogram, only len0
528 static int t_dma_multi(void)
529 {
530     const u32 *src = (const u32 *)0x3c0000;
531     u32 v0, v1;
532     int ok = 1;
533
534     do_setup_dma(src, 2);
535     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100) | CTL_WRITE_DMA);
536     VDP_setReg(VDP_DMA_LEN0, 2);
537     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x104) | CTL_WRITE_DMA);
538
539     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x100));
540     v0 = read32(VDP_DATA_PORT);
541     v1 = read32(VDP_DATA_PORT);
542
543     expect(ok, v0, src[0]);
544     expect(ok, v1, src[1]);
545     return ok;
546 }
547
548 static int t_dma_cram_wrap(void)
549 {
550     u32 *ram = (u32 *)0xff0000;
551     u32 v0, v1;
552     int ok = 1;
553
554     write32(VDP_CTRL_PORT, CTL_WRITE_CRAM(0));
555     write32(VDP_DATA_PORT, 0);
556
557     ram[0] = 0x0ec20ec4;
558     ram[1] = 0x0ec60ec8;
559     mem_barrier();
560     do_setup_dma(ram, 4);
561     write32(VDP_CTRL_PORT, CTL_WRITE_CRAM(0x7c | 0xff81) | CTL_WRITE_DMA);
562
563     write32(VDP_CTRL_PORT, CTL_READ_CRAM(0x7c));
564     v0 = read32(VDP_DATA_PORT) & 0x0eee0eee;
565     write32(VDP_CTRL_PORT, CTL_READ_CRAM(0));
566     v1 = read32(VDP_DATA_PORT) & 0x0eee0eee;
567
568     setup_default_palette();
569
570     expect(ok, v0, ram[0]);
571     expect(ok, v1, ram[1]);
572     return ok;
573 }
574
575 static int t_dma_vsram_wrap(void)
576 {
577     u32 *ram32 = (u32 *)0xff0000;
578     u16 *ram16 = (u16 *)0xff0000;
579     u32 v0, v1;
580     int ok = 1;
581     int i;
582
583     write32(VDP_CTRL_PORT, CTL_WRITE_VSRAM(0));
584     write32(VDP_DATA_PORT, 0);
585
586     for (i = 0; i < 0x48/2; i++)
587         ram16[i] = i + 1;
588     mem_barrier();
589     do_setup_dma(ram16, 0x48/2);
590     write32(VDP_CTRL_PORT, CTL_WRITE_VSRAM(0x3c | 0xff81) | CTL_WRITE_DMA);
591
592     write32(VDP_CTRL_PORT, CTL_READ_VSRAM(0x3c));
593     v0 = read32(VDP_DATA_PORT) & 0x03ff03ff;
594     write32(VDP_CTRL_PORT, CTL_READ_VSRAM(0));
595     v1 = read32(VDP_DATA_PORT) & 0x03ff03ff;
596
597     write32(VDP_CTRL_PORT, CTL_WRITE_VSRAM(0));
598     write32(VDP_DATA_PORT, 0);
599
600     expect(ok, v0, ram32[0]);
601     expect(ok, v1, ram32[0x48/4 - 1]);
602     return ok;
603 }
604
605 static int t_dma_and_data(void)
606 {
607     const u32 *src = (const u32 *)0x3c0000;
608     u32 v0, v1;
609     int ok = 1;
610
611     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100));
612     write32(VDP_DATA_PORT, 0);
613
614     do_setup_dma(src, 2);
615     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0xfc) | CTL_WRITE_DMA);
616     write32(VDP_DATA_PORT, 0x5ec8a248);
617
618     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0xfc));
619     v0 = read32(VDP_DATA_PORT);
620     v1 = read32(VDP_DATA_PORT);
621
622     expect(ok, v0, src[0]);
623     expect(ok, v1, 0x5ec8a248);
624     return ok;
625 }
626
627 static int t_dma_short_cmd(void)
628 {
629     const u32 *src = (const u32 *)0x3c0000;
630     u32 v0, v1, v2;
631     int ok = 1;
632
633     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x3ff4));
634     write32(VDP_DATA_PORT, 0x10111213);
635     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0xfff0));
636     write32(VDP_DATA_PORT, 0x20212223);
637     write32(VDP_DATA_PORT, 0x30313233);
638     vdp_wait_for_fifo_empty();
639
640     do_setup_dma(src, 2);
641     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0xfff0) | CTL_WRITE_DMA);
642     write16(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x3ff4) >> 16);
643     write32(VDP_DATA_PORT, 0x40414243);
644
645     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x3ff4));
646     v0 = read32(VDP_DATA_PORT);
647     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0xfff0));
648     v1 = read32(VDP_DATA_PORT);
649     v2 = read32(VDP_DATA_PORT);
650
651     expect(ok, v0, 0x10111213);
652     expect(ok, v1, src[0]);
653     expect(ok, v2, 0x40414243);
654     return ok;
655 }
656
657 static int t_dma_fill3_odd(void)
658 {
659     u32 v0, v1, v2;
660     int ok = 1;
661
662     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100));
663     write32(VDP_DATA_PORT, 0);
664     write32(VDP_DATA_PORT, 0);
665     write32(VDP_DATA_PORT, 0);
666     vdp_wait_for_fifo_empty();
667
668     VDP_setReg(VDP_AUTOINC, 3);
669     VDP_setReg(VDP_DMA_LEN0, 3);
670     VDP_setReg(VDP_DMA_SRC2, 0x80);
671     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x101) | CTL_WRITE_DMA);
672     write16(VDP_DATA_PORT, 0x1122);
673     vdp_wait_for_dma_idle();
674
675     VDP_setReg(VDP_AUTOINC, 2);
676     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x100));
677     v0 = read32(VDP_DATA_PORT);
678     v1 = read32(VDP_DATA_PORT);
679     v2 = read32(VDP_DATA_PORT);
680
681     expect(ok, v0, 0x22110000);
682     expect(ok, v1, 0x00111100);
683     expect(ok, v2, 0x00000011);
684     return ok;
685 }
686
687 static int t_dma_fill3_even(void)
688 {
689     u32 v0, v1, v2;
690     int ok = 1;
691
692     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100));
693     write32(VDP_DATA_PORT, 0);
694     write32(VDP_DATA_PORT, 0);
695     write32(VDP_DATA_PORT, 0);
696     vdp_wait_for_fifo_empty();
697
698     VDP_setReg(VDP_AUTOINC, 3);
699     VDP_setReg(VDP_DMA_LEN0, 3);
700     VDP_setReg(VDP_DMA_SRC2, 0x80);
701     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100) | CTL_WRITE_DMA);
702     write16(VDP_DATA_PORT, 0x1122);
703     vdp_wait_for_dma_idle();
704
705     VDP_setReg(VDP_AUTOINC, 2);
706     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x100));
707     v0 = read32(VDP_DATA_PORT);
708     v1 = read32(VDP_DATA_PORT);
709     v2 = read32(VDP_DATA_PORT);
710
711     expect(ok, v0, 0x11221100);
712     expect(ok, v1, 0x00000011);
713     expect(ok, v2, 0x11000000);
714     return ok;
715 }
716
717 static unused int t_dma_fill3_vsram(void)
718 {
719     u32 v0, v1, v2;
720     int ok = 1;
721
722     write32(VDP_CTRL_PORT, CTL_WRITE_VSRAM(0));
723     write32(VDP_DATA_PORT, 0);
724     write32(VDP_DATA_PORT, 0);
725     write32(VDP_DATA_PORT, 0);
726
727     write16(VDP_DATA_PORT, 0x0111);
728     write16(VDP_DATA_PORT, 0x0222);
729     write16(VDP_DATA_PORT, 0x0333);
730     vdp_wait_for_fifo_empty();
731
732     VDP_setReg(VDP_AUTOINC, 3);
733     VDP_setReg(VDP_DMA_LEN0, 3);
734     VDP_setReg(VDP_DMA_SRC2, 0x80);
735     write32(VDP_CTRL_PORT, CTL_WRITE_VSRAM(1) | CTL_WRITE_DMA);
736     write16(VDP_DATA_PORT, 0x0102);
737     vdp_wait_for_dma_idle();
738
739     VDP_setReg(VDP_AUTOINC, 2);
740     write32(VDP_CTRL_PORT, CTL_READ_VSRAM(0));
741     v0 = read32(VDP_DATA_PORT);
742     v1 = read32(VDP_DATA_PORT);
743     v2 = read32(VDP_DATA_PORT);
744
745     write32(VDP_CTRL_PORT, CTL_WRITE_VSRAM(0));
746     write32(VDP_DATA_PORT, 0);
747
748     expect(ok, v0, 0x01020000);
749     expect(ok, v1, 0x01110111);
750     expect(ok, v2, 0x00000111);
751     return ok;
752 }
753
754 static int t_dma_fill_dis(void)
755 {
756     u32 v0, v1;
757     int ok = 1;
758
759     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100));
760     write32(VDP_DATA_PORT, 0);
761     write32(VDP_DATA_PORT, 0);
762
763     VDP_setReg(VDP_DMA_LEN0, 1);
764     VDP_setReg(VDP_DMA_SRC2, 0x80);
765     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100) | CTL_WRITE_DMA);
766     VDP_setReg(VDP_MODE2, VDP_MODE2_MD);
767     write16(VDP_DATA_PORT, 0x1122);
768     vdp_wait_for_dma_idle();
769
770     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_DISP);
771     write16(VDP_DATA_PORT, 0x3344);
772     vdp_wait_for_dma_idle();
773
774     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x100));
775     v0 = read32(VDP_DATA_PORT);
776     v1 = read32(VDP_DATA_PORT);
777
778     expect(ok, v0, 0);
779     expect(ok, v1, 0);
780     return ok;
781 }
782
783 static int t_dma_fill_src(void)
784 {
785     const u32 *src = (const u32 *)0x3c0000;
786     u32 v0, v1;
787     int ok = 1;
788
789     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100));
790     write32(VDP_DATA_PORT, 0);
791
792     // do_setup_dma(src, 2); // hang, can't write src2 twice
793     VDP_setReg(VDP_DMA_LEN0, 2);
794     VDP_setReg(VDP_DMA_SRC0, (u32)src >> 1);
795     VDP_setReg(VDP_DMA_SRC1, (u32)src >> 9);
796     VDP_setReg(VDP_DMA_SRC2, 0x80);
797     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100) | CTL_WRITE_DMA);
798     write16(VDP_DATA_PORT, 0x1122);
799     vdp_wait_for_dma_idle();
800
801     VDP_setReg(VDP_DMA_LEN0, 2);
802     VDP_setReg(VDP_DMA_SRC2, (u32)src >> 17);
803     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x104) | CTL_WRITE_DMA);
804
805     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x100));
806     v0 = read32(VDP_DATA_PORT);
807     v1 = read32(VDP_DATA_PORT);
808
809     expect(ok, v0, 0x11220011);
810     expect(ok, v1, src[1]);
811     return ok;
812 }
813
814 // (((a & 2) >> 1) ^ 1) | ((a & $400) >> 9) | (a & $3FC) | ((a & $1F800) >> 1)
815 static int t_dma_128k(void)
816 {
817     u16 *ram = (u16 *)0xff0000;
818     u32 v0, v1;
819     int ok = 1;
820
821     ram[0] = 0x5a11;
822     ram[1] = 0x5a22;
823     ram[2] = 0x5a33;
824
825     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100));
826     write32(VDP_DATA_PORT, 0x01020304);
827     write32(VDP_DATA_PORT, 0x05060708);
828     vdp_wait_for_fifo_empty();
829
830     mem_barrier();
831     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_128K);
832     do_setup_dma(ram, 3);
833     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100) | CTL_WRITE_DMA);
834     vdp_wait_for_fifo_empty();
835
836     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_DISP);
837     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x100));
838     v0 = read32(VDP_DATA_PORT);
839     v1 = read32(VDP_DATA_PORT);
840
841     expect(ok, v0, 0x22110304);
842     expect(ok, v1, 0x05330708);
843     return ok;
844 }
845
846 static int t_vdp_128k_b16(void)
847 {
848     u32 v0, v1;
849     int ok = 1;
850
851     VDP_setReg(VDP_AUTOINC, 0);
852     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x8100));
853     write32(VDP_DATA_PORT, 0x01020304);
854     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x10100));
855     write32(VDP_DATA_PORT, 0x05060708);
856     vdp_wait_for_fifo_empty();
857
858     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_128K);
859     write16(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100) >> 16); // note: upper cmd
860     write32(VDP_DATA_PORT, 0x11223344);
861     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x10102));
862     write32(VDP_DATA_PORT, 0x55667788);
863     vdp_wait_for_fifo_empty();
864
865     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_DISP);
866     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x8100));
867     v0 = read16(VDP_DATA_PORT);
868     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x0100));
869     v1 = read16(VDP_DATA_PORT);
870
871     VDP_setReg(VDP_AUTOINC, 2);
872
873     expect(ok, v0, 0x8844);
874     expect(ok, v1, 0x0708);
875     return ok;
876 }
877
878 static unused int t_vdp_128k_b16_inc(void)
879 {
880     u32 v0, v1;
881     int ok = 1;
882
883     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0));
884     write32(VDP_DATA_PORT, 0x01020304);
885     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x8000));
886     write32(VDP_DATA_PORT, 0x05060708);
887     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0xfffe));
888     write32(VDP_DATA_PORT, 0x090a0b0c);
889     vdp_wait_for_fifo_empty();
890
891     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_128K);
892     write16(VDP_CTRL_PORT, CTL_WRITE_VRAM(0) >> 16); // note: upper cmd
893     write16(VDP_DATA_PORT, 0x1122);
894     vdp_wait_for_fifo_empty();
895
896     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_DISP);
897     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0));
898     v0 = read32(VDP_DATA_PORT);
899     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x8000));
900     v1 = read32(VDP_DATA_PORT);
901     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0));
902     write32(VDP_DATA_PORT, 0);
903     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x8000));
904     write32(VDP_DATA_PORT, 0);
905
906     expect(ok, v0, 0x0b0c0304); // XXX: no 22 anywhere?
907     expect(ok, v1, 0x05060708);
908     return ok;
909 }
910
911 static int t_vdp_reg_cmd(void)
912 {
913     u32 v0;
914     int ok = 1;
915
916     VDP_setReg(VDP_AUTOINC, 0);
917     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100));
918     write32(VDP_DATA_PORT, 0x01020304);
919     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_DISP);
920     write32(VDP_DATA_PORT, 0x05060708);
921
922     VDP_setReg(VDP_AUTOINC, 2);
923     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x0100));
924     v0 = read16(VDP_DATA_PORT);
925
926     expect(ok, v0, 0x0304);
927     return ok;
928 }
929
930 static int t_vdp_sr_vb(void)
931 {
932     u16 sr[4];
933     int ok = 1;
934
935     while (read8(VDP_HV_COUNTER) != 242)
936         ;
937     sr[0] = read16(VDP_CTRL_PORT);
938     VDP_setReg(VDP_MODE2, VDP_MODE2_MD);
939     sr[1] = read16(VDP_CTRL_PORT);
940     while (read8(VDP_HV_COUNTER) != 4)
941         ;
942     sr[2] = read16(VDP_CTRL_PORT);
943     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_DISP);
944     sr[3] = read16(VDP_CTRL_PORT);
945
946     expect_bits(ok, sr[0], SR_VB, SR_VB);
947     expect_bits(ok, sr[1], SR_VB, SR_VB);
948     expect_bits(ok, sr[2], SR_VB, SR_VB);
949     expect_bits(ok, sr[3], 0, SR_VB);
950     return ok;
951 }
952
953 /* z80 tests assume busreq state */
954 static int t_z80mem_long_mirror(void)
955 {
956     u8 *zram = (u8 *)0xa00000;
957     int ok = 1;
958
959     write8(&zram[0x1100], 0x11);
960     write8(&zram[0x1101], 0x22);
961     write8(&zram[0x1102], 0x33);
962     write8(&zram[0x1103], 0x44);
963     mem_barrier();
964     write32(&zram[0x3100], 0x55667788);
965     mem_barrier();
966
967     expect(ok, zram[0x1100], 0x55);
968     expect(ok, zram[0x1101], 0x22);
969     expect(ok, zram[0x1102], 0x77);
970     expect(ok, zram[0x1103], 0x44);
971     return ok;
972 }
973
974 static int t_z80mem_noreq_w(void)
975 {
976     u8 *zram = (u8 *)0xa00000;
977     int ok = 1;
978
979     write8(&zram[0x1100], 0x11);
980     mem_barrier();
981     write16(0xa11100, 0x000);
982     write8(&zram[0x1100], 0x22);
983     mem_barrier();
984
985     write16(0xa11100, 0x100);
986     while (read16(0xa11100) & 0x100)
987         ;
988
989     expect(ok, zram[0x1100], 0x11);
990     return ok;
991 }
992
993 #define Z80_CP_CYCLES(b) (118 + ((b) - 1) * 21 + 26 + 17)
994
995 static int t_z80mem_vdp_r(void)
996 {
997     u8 *zram = (u8 *)0xa00000;
998     int ok = 1;
999
1000     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100));
1001     write32(VDP_DATA_PORT, 0x11223344);
1002     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x100));
1003
1004     zram[0x1000] = 1; // cp
1005     write16_z80le(&zram[0x1002], 0x7f00); // src
1006     write16_z80le(&zram[0x1004], 0x1100); // dst
1007     write16_z80le(&zram[0x1006], 2); // len
1008     zram[0x1100] = zram[0x1101] = zram[0x1102] = 0x5a;
1009     mem_barrier();
1010     write16(0xa11100, 0x000);
1011     burn10(Z80_CP_CYCLES(2) * 15 / 7 * 2 / 10);
1012
1013     write16(0xa11100, 0x100);
1014     while (read16(0xa11100) & 0x100)
1015         ;
1016
1017     expect(ok, zram[0x1000], 0);
1018     expect(ok, zram[0x1100], 0x11);
1019     expect(ok, zram[0x1101], 0x44);
1020     expect(ok, zram[0x1102], 0x5a);
1021     return ok;
1022 }
1023
1024 static unused int t_z80mem_vdp_w(void)
1025 {
1026     u8 *zram = (u8 *)0xa00000;
1027     u32 v0;
1028     int ok = 1;
1029
1030     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100));
1031     write32(VDP_DATA_PORT, 0x11223344);
1032     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100));
1033     vdp_wait_for_fifo_empty();
1034
1035     zram[0x1000] = 1; // cp
1036     write16_z80le(&zram[0x1002], 0x1100); // src
1037     write16_z80le(&zram[0x1004], 0x7f00); // dst
1038     write16_z80le(&zram[0x1006], 2); // len
1039     zram[0x1100] = 0x55;
1040     zram[0x1101] = 0x66;
1041     mem_barrier();
1042     write16(0xa11100, 0x000);
1043     burn10(Z80_CP_CYCLES(2) * 15 / 7 * 2 / 10);
1044
1045     write16(0xa11100, 0x100);
1046     while (read16(0xa11100) & 0x100)
1047         ;
1048
1049     write32(VDP_CTRL_PORT, CTL_READ_VRAM(0x100));
1050     v0 = read32(VDP_DATA_PORT);
1051
1052     expect(ok, zram[0x1000], 0);
1053     expect(ok, v0, 0x55556666);
1054     return ok;
1055 }
1056
1057 static int t_tim_loop(void)
1058 {
1059     u8 vcnt;
1060     int ok = 1;
1061
1062     vdp_wait_for_line_0();
1063     burn10(488*220/10);
1064     vcnt = read8(VDP_HV_COUNTER);
1065     mem_barrier();
1066
1067     //expect_range(ok, vcnt, 0x80, 0x80);
1068     expect(ok, vcnt, 223);
1069     return ok;
1070 }
1071
1072 #define Z80_RD_V_CYCLES(b) (132 + (b) * 38 + 50 + 17)
1073
1074 // 80 80 91 95-96
1075 static void z80_read_loop(u8 *zram, u16 src)
1076 {
1077     const int pairs = 512 + 256;
1078
1079     zram[0x1000] = 2; // read loop, save vcnt
1080     write16_z80le(&zram[0x1002], src); // src
1081     write16_z80le(&zram[0x1004], 0x1100); // vcnt dst
1082     write16_z80le(&zram[0x1006], pairs); // reads/2
1083     zram[0x1100] = 0;
1084     mem_barrier();
1085
1086     vdp_wait_for_line_0();
1087     write16(0xa11100, 0x000);
1088     burn10(Z80_RD_V_CYCLES(pairs) * 15 / 7 * 4 / 10);
1089
1090     write16(0xa11100, 0x100);
1091     while (read16(0xa11100) & 0x100)
1092         ;
1093 }
1094
1095 static int t_tim_z80_ram(void)
1096 {
1097     u8 *zram = (u8 *)0xa00000;
1098     int ok = 1;
1099
1100     z80_read_loop(zram, 0);
1101
1102     expect(ok, zram[0x1000], 0);
1103     expect_range(ok, zram[0x1100], 0x80, 0x80);
1104     return ok;
1105 }
1106
1107 static int t_tim_z80_ym(void)
1108 {
1109     u8 *zram = (u8 *)0xa00000;
1110     int ok = 1;
1111
1112     z80_read_loop(zram, 0x4000);
1113
1114     expect(ok, zram[0x1000], 0);
1115     expect_range(ok, zram[0x1100], 0x80, 0x80);
1116     return ok;
1117 }
1118
1119 static int t_tim_z80_vdp(void)
1120 {
1121     u8 *zram = (u8 *)0xa00000;
1122     int ok = 1;
1123
1124     z80_read_loop(zram, 0x7f08);
1125
1126     expect(ok, zram[0x1000], 0);
1127 #ifndef PICO
1128     expect_range(ok, zram[0x1100], 0x91, 0x91);
1129 #else
1130     expect_range(ok, zram[0x1100], 0x8e, 0x91);
1131 #endif
1132     return ok;
1133 }
1134
1135 static int t_tim_z80_bank_rom(void)
1136 {
1137     u8 *zram = (u8 *)0xa00000;
1138     int i, ok = 1;
1139
1140     for (i = 0; i < 17; i++)
1141         write8(0xa06000, 0); // bank 0
1142
1143     z80_read_loop(zram, 0x8000);
1144
1145     expect(ok, zram[0x1000], 0);
1146 #ifndef PICO
1147     expect_range(ok, zram[0x1100], 0x95, 0x96);
1148 #else
1149     expect_range(ok, zram[0x1100], 0x93, 0x96);
1150 #endif
1151     return ok;
1152 }
1153
1154 /* borderline too slow */
1155 #if 0
1156 static void test_vcnt_vb(void)
1157 {
1158     const u32 *srhv = (u32 *)0xc00006; // to read SR and HV counter
1159     u32 *ram = (u32 *)0xff0000;
1160     u16 vcnt, vcnt_expect = 0;
1161     u16 sr, count = 0;
1162     u32 val, old;
1163
1164     vdp_wait_for_line_0();
1165     old = read32(srhv);
1166     *ram++ = old;
1167     for (;;) {
1168         val = read32(srhv);
1169         vcnt = val & 0xff00;
1170         if (vcnt == vcnt_expect)
1171             continue;
1172         sr = val >> 16;
1173         if (vcnt == 0 && !(sr & SR_VB)) // not VB
1174             break; // wrapped to start of frame
1175 //        count++;
1176         vcnt_expect += 0x100;
1177         if (vcnt == vcnt_expect && !((sr ^ (old >> 16)) & SR_VB)) {
1178             old = val;
1179             continue;
1180         }
1181         // should have a vcnt jump here
1182         *ram++ = old;
1183         *ram++ = val;
1184         vcnt_expect = vcnt;
1185         old = val;
1186     }
1187     *ram++ = val;
1188     *ram = count;
1189     mem_barrier();
1190 }
1191 #endif
1192
1193 static int t_tim_vcnt(void)
1194 {
1195     const u32 *ram32 = (u32 *)0xff0000;
1196     const u8 *ram = (u8 *)0xff0000;
1197     u8 pal = read8(0xa10001) & 0x40;
1198     u8 vc_jmp_b = pal ? 0x02 : 0xea;
1199     u8 vc_jmp_a = pal ? 0xca : 0xe5;
1200     u16 lines = pal ? 313 : 262;
1201     int ok = 1;
1202
1203     test_vcnt_vb();
1204     expect(ok, ram[0*4+2], 0); // line 0
1205     expect_bits(ok, ram[0*4+1], 0, SR_VB);
1206     expect(ok, ram[1*4+2], 223); // last no blank
1207     expect_bits(ok, ram[1*4+1], 0, SR_VB);
1208     expect(ok, ram[2*4+2], 224); // 1st blank
1209     expect_bits(ok, ram[2*4+1], SR_VB, SR_VB);
1210     expect(ok, ram[3*4+2], vc_jmp_b); // before jump
1211     expect_bits(ok, ram[3*4+1], SR_VB, SR_VB);
1212     expect(ok, ram[4*4+2], vc_jmp_a); // after jump
1213     expect_bits(ok, ram[4*4+1], SR_VB, SR_VB);
1214     expect(ok, ram[5*4+2], 0xfe); // before vb clear
1215     expect_bits(ok, ram[5*4+1], SR_VB, SR_VB);
1216     expect(ok, ram[6*4+2], 0xff); // after vb clear
1217     expect_bits(ok, ram[6*4+1], 0, SR_VB);
1218     expect(ok, ram[7*4+2], 0); // next line 0
1219     expect_bits(ok, ram[7*4+1], 0, SR_VB);
1220     expect(ok, ram32[8], lines - 1);
1221     return ok;
1222 }
1223
1224 static int t_tim_hblank_h40(void)
1225 {
1226     const u8 *r = (u8 *)0xff0000;
1227     int ok = 1;
1228
1229     test_hb();
1230
1231     // set: 0-2
1232     expect_bits(ok, r[2], SR_HB, SR_HB);
1233     expect_bits(ok, r[5], SR_HB, SR_HB);
1234     // <wait>
1235     expect_bits(ok, r[7], SR_HB, SR_HB);
1236     // clear: 8-11
1237     expect_bits(ok, r[12], 0, SR_HB);
1238     return ok;
1239 }
1240
1241 static int t_tim_hblank_h32(void)
1242 {
1243     const u8 *r = (u8 *)0xff0000;
1244     int ok = 1;
1245
1246     VDP_setReg(VDP_MODE4, 0x00);
1247     test_hb();
1248     VDP_setReg(VDP_MODE4, 0x81);
1249
1250 #ifndef PICO
1251     expect_bits(ok, r[0], 0, SR_HB);
1252 #endif
1253     // set: 1-4
1254     expect_bits(ok, r[4], SR_HB, SR_HB);
1255     expect_bits(ok, r[5], SR_HB, SR_HB);
1256     // <wait>
1257     expect_bits(ok, r[8], SR_HB, SR_HB);
1258     // clear: 9-11
1259     expect_bits(ok, r[12], 0, SR_HB);
1260     return ok;
1261 }
1262
1263 static int t_tim_vdp_as_vram_w(void)
1264 {
1265     int ok = 1;
1266     u8 vcnt;
1267
1268     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100));
1269     vdp_wait_for_line_0();
1270     write16_x16(VDP_DATA_PORT, 112*18 / 16, 0);
1271     vcnt = read8(VDP_HV_COUNTER);
1272     mem_barrier();
1273
1274     expect(ok, vcnt, 112*2-1);
1275     return ok;
1276 }
1277
1278 static int t_tim_vdp_as_cram_w(void)
1279 {
1280     int ok = 1;
1281     u8 vcnt;
1282
1283     write32(VDP_CTRL_PORT, CTL_WRITE_CRAM(0));
1284     vdp_wait_for_line_0();
1285     write16_x16(VDP_DATA_PORT, 112*18 / 16, 0);
1286     vcnt = read8(VDP_HV_COUNTER);
1287     mem_barrier();
1288
1289     setup_default_palette();
1290
1291 #ifndef PICO
1292     expect(ok, vcnt, 112);
1293 #else
1294     expect_range(ok, vcnt, 111, 112);
1295 #endif
1296     return ok;
1297 }
1298
1299 static int t_irq_hint(void)
1300 {
1301     u16 *ram = (u16 *)0xfff000;
1302     u8 *ram8 = (u8 *)0xfff000;
1303     u16 v_p, cnt_p;
1304     int ok = 1;
1305
1306     // for more fun, disable the display
1307     VDP_setReg(VDP_MODE2, VDP_MODE2_MD);
1308
1309     ram[0] = ram[1] = ram[2] = 0;
1310     memcpy_((void *)0xff0100, test_hint, test_hint_end - test_hint);
1311     VDP_setReg(10, 0);
1312     while (read8(VDP_HV_COUNTER) != 100)
1313         ;
1314     while (read8(VDP_HV_COUNTER) != 229)
1315         ;
1316     // take the pending irq
1317     VDP_setReg(VDP_MODE1, VDP_MODE1_PS | VDP_MODE1_IE1);
1318     move_sr(0x2000);
1319     burn10(488 * 2 / 10);
1320     move_sr(0x2700);
1321     v_p = ram8[2];
1322     cnt_p = ram[0];
1323     ram[0] = ram[1] = ram[2] = 0;
1324     // count irqs
1325     move_sr(0x2000);
1326     while (read8(VDP_HV_COUNTER) != 4)
1327         ;
1328     while (read8(VDP_HV_COUNTER) != 228)
1329         ;
1330     move_sr(0x2700);
1331     VDP_setReg(VDP_MODE1, VDP_MODE1_PS);
1332     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_DISP);
1333
1334     expect(ok, v_p, 229);      // pending irq trigger
1335     expect(ok, cnt_p, 1);
1336     expect(ok, ram[0], 225);   // count
1337     expect(ok, ram8[2], 0);    // first line
1338     expect(ok, ram8[4], 224);  // last line
1339     return ok;
1340 }
1341
1342 static int t_irq_ack_v_h(void)
1343 {
1344     u16 *ram = (u16 *)0xfff000;
1345     u8 *ram8 = (u8 *)0xfff000;
1346     u16 s0, s1, s2;
1347     int ok = 1;
1348
1349     ram[0] = ram[1] = ram[2] =
1350     ram[4] = ram[5] = ram[6] = 0;
1351     memcpy_((void *)0xff0100, test_hint, test_hint_end - test_hint);
1352     memcpy_((void *)0xff0140, test_vint, test_vint_end - test_vint);
1353     VDP_setReg(10, 0);
1354     VDP_setReg(VDP_MODE1, VDP_MODE1_PS | VDP_MODE1_IE1);
1355     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_IE0);
1356     while (read8(VDP_HV_COUNTER) != 100)
1357         ;
1358     while (read8(VDP_HV_COUNTER) != 226)
1359         ;
1360     s0 = read16(VDP_CTRL_PORT);
1361     s1 = move_sr_and_read(0x2500, VDP_CTRL_PORT);
1362     burn10(666 / 10);
1363     s2 = move_sr_and_read(0x2000, VDP_CTRL_PORT);
1364     burn10(488 / 10);
1365     move_sr(0x2700);
1366     VDP_setReg(VDP_MODE1, VDP_MODE1_PS);
1367     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_DISP);
1368
1369     expect(ok, ram[4], 1);     // vint count
1370     expect(ok, ram8[10], 226); // vint line
1371     expect(ok, ram[0], 1);     // hint count
1372     expect(ok, ram8[2], 228);  // hint line
1373     expect_bits(ok, s0, SR_F, SR_F);
1374     expect_bits(ok, s1, 0, SR_F);
1375     expect_bits(ok, s2, 0, SR_F);
1376     return ok;
1377 }
1378
1379 static int t_irq_ack_v_h_2(void)
1380 {
1381     u16 *ram = (u16 *)0xfff000;
1382     u8 *ram8 = (u8 *)0xfff000;
1383     u16 s0, s1;
1384     int ok = 1;
1385
1386     ram[0] = ram[1] = ram[2] =
1387     ram[4] = ram[5] = ram[6] = 0;
1388     memcpy_((void *)0xff0100, test_hint, test_hint_end - test_hint);
1389     memcpy_((void *)0xff0140, test_vint, test_vint_end - test_vint);
1390     VDP_setReg(10, 0);
1391     while (read8(VDP_HV_COUNTER) != 100)
1392         ;
1393     while (read8(VDP_HV_COUNTER) != 226)
1394         ;
1395     s0 = read16(VDP_CTRL_PORT);
1396     test_v_h_2();
1397     s1 = read16(VDP_CTRL_PORT);
1398     VDP_setReg(VDP_MODE1, VDP_MODE1_PS);
1399     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_DISP);
1400
1401     expect(ok, ram[4], 2);     // vint count
1402     expect(ok, ram8[10], 226); // vint line
1403     expect(ok, ram[0], 1);     // hint count
1404     expect(ok, ram8[2], 227);  // hint line
1405     expect_bits(ok, s0, SR_F, SR_F);
1406     expect_bits(ok, s1, 0, SR_F);
1407     return ok;
1408 }
1409
1410 static int t_irq_ack_h_v(void)
1411 {
1412     u16 *ram = (u16 *)0xfff000;
1413     u8 *ram8 = (u8 *)0xfff000;
1414     u16 s0, s1, s[4];
1415     int ok = 1;
1416
1417     ram[0] = ram[1] = ram[2] =
1418     ram[4] = ram[5] = ram[6] = 0;
1419     memcpy_((void *)0xff0100, test_hint, test_hint_end - test_hint);
1420     memcpy_((void *)0xff0140, test_vint, test_vint_end - test_vint);
1421     VDP_setReg(10, 0);
1422     while (read8(VDP_HV_COUNTER) != 100)
1423         ;
1424     while (read8(VDP_HV_COUNTER) != 226)
1425         ;
1426     s0 = read16(VDP_CTRL_PORT);
1427     VDP_setReg(VDP_MODE1, VDP_MODE1_PS | VDP_MODE1_IE1);
1428     move_sr(0x2000);
1429     burn10(666 / 10);
1430     s1 = read16(VDP_CTRL_PORT);
1431     write_and_read1(VDP_CTRL_PORT, 0x8000 | (VDP_MODE2 << 8)
1432                      | VDP_MODE2_MD | VDP_MODE2_IE0, s);
1433     move_sr(0x2700);
1434     VDP_setReg(VDP_MODE1, VDP_MODE1_PS);
1435     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_DISP);
1436
1437     expect(ok, ram[0], 1);     // hint count
1438     expect(ok, ram8[2], 226);  // hint line
1439     expect(ok, ram[4], 1);     // vint count
1440     expect(ok, ram8[10], 228); // vint line
1441     expect_bits(ok, s0, SR_F, SR_F);
1442     expect_bits(ok, s1, SR_F, SR_F);
1443     expect_bits(ok, s[0], SR_F, SR_F);
1444     expect_bits(ok, s[1], SR_F, SR_F);
1445     expect_bits(ok, s[2], 0, SR_F);
1446     expect_bits(ok, s[3], 0, SR_F);
1447     return ok;
1448 }
1449
1450 static int t_irq_ack_h_v_2(void)
1451 {
1452     u16 *ram = (u16 *)0xfff000;
1453     u8 *ram8 = (u8 *)0xfff000;
1454     u16 s0, s1;
1455     int ok = 1;
1456
1457     ram[0] = ram[1] = ram[2] =
1458     ram[4] = ram[5] = ram[6] = 0;
1459     memcpy_((void *)0xff0100, test_hint, test_hint_end - test_hint);
1460     memcpy_((void *)0xff0140, test_vint, test_vint_end - test_vint);
1461     VDP_setReg(10, 0);
1462     while (read8(VDP_HV_COUNTER) != 100)
1463         ;
1464     while (read8(VDP_HV_COUNTER) != 226)
1465         ;
1466     s0 = read16(VDP_CTRL_PORT);
1467     test_h_v_2();
1468     s1 = read16(VDP_CTRL_PORT);
1469     VDP_setReg(VDP_MODE1, VDP_MODE1_PS);
1470     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_DISP);
1471
1472     expect(ok, ram[0], 2);     // hint count
1473     expect(ok, ram8[2], 226);  // hint first line
1474     expect(ok, ram8[4], 226);  // hint last line
1475     expect(ok, ram[4], 0);     // vint count
1476     expect(ok, ram8[10], 0);   // vint line
1477     expect_bits(ok, s0, SR_F, SR_F);
1478     expect_bits(ok, s1, 0, SR_F);
1479     return ok;
1480 }
1481
1482 static void t_irq_f_flag(void)
1483 {
1484     memcpy_((void *)0xff0140, test_f_vint, test_f_vint_end - test_f_vint);
1485     memset_((void *)0xff0000, 0, 10);
1486     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_IE0 | VDP_MODE2_DISP);
1487     test_f();
1488     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_DISP);
1489 }
1490
1491 static int t_irq_f_flag_h40(void)
1492 {
1493     u8 f, *r = (u8 *)0xff0000;
1494     int ok = 1;
1495
1496     t_irq_f_flag();
1497
1498     expect_bits(ok, r[0], 0, SR_F);
1499     expect_bits(ok, r[1], 0, SR_F);
1500     expect_bits(ok, r[2], 0, SR_F);
1501     // hits 1-3 times in range 3-9, usually ~5
1502     f = r[3] | r[4] | r[5] | r[6] | r[7];
1503
1504     expect_bits(ok, r[10], 0, SR_F);
1505     expect_bits(ok, r[11], 0, SR_F);
1506     expect_bits(ok, f, SR_F, SR_F);
1507     return ok;
1508 }
1509
1510 static int t_irq_f_flag_h32(void)
1511 {
1512     u8 f, *r = (u8 *)0xff0000;
1513     int ok = 1;
1514
1515     VDP_setReg(VDP_MODE4, 0x00);
1516     t_irq_f_flag();
1517     VDP_setReg(VDP_MODE4, 0x81);
1518
1519     expect_bits(ok, r[0], 0, SR_F);
1520     expect_bits(ok, r[1], 0, SR_F);
1521     // hits 1-3 times in range 2-7, usually 3
1522     f = r[2] | r[3] | r[4] | r[5] | r[6] | r[7];
1523
1524     expect_bits(ok, r[8], 0, SR_F);
1525     expect_bits(ok, r[9], 0, SR_F);
1526     expect_bits(ok, r[10], 0, SR_F);
1527     expect_bits(ok, r[11], 0, SR_F);
1528     expect_bits(ok, f, SR_F, SR_F);
1529     return ok;
1530 }
1531
1532 static const struct {
1533     int (*test)(void);
1534     const char *name;
1535 } g_tests[] = {
1536     { t_dma_zero_wrap,       "dma zero len + wrap" },
1537     { t_dma_zero_fill,       "dma zero len + fill" },
1538     { t_dma_ram_wrap,        "dma ram wrap" },
1539     { t_dma_multi,           "dma multi" },
1540     { t_dma_cram_wrap,       "dma cram wrap" },
1541     { t_dma_vsram_wrap,      "dma vsram wrap" },
1542     { t_dma_and_data,        "dma and data" },
1543     { t_dma_short_cmd,       "dma short cmd" },
1544     { t_dma_fill3_odd,       "dma fill3 odd" },
1545     { t_dma_fill3_even,      "dma fill3 even" },
1546 #ifndef PICO // later
1547     { t_dma_fill3_vsram,     "dma fill3 vsram" },
1548 #endif
1549     { t_dma_fill_dis,        "dma fill disabled" },
1550     { t_dma_fill_src,        "dma fill src incr" },
1551     { t_dma_128k,            "dma 128k mode" },
1552     { t_vdp_128k_b16,        "vdp 128k addr bit16" },
1553     // { t_vdp_128k_b16_inc,    "vdp 128k bit16 inc" }, // mystery
1554     { t_vdp_reg_cmd,         "vdp reg w cmd reset" },
1555     { t_vdp_sr_vb,           "vdp status reg vb" },
1556     { t_z80mem_long_mirror,  "z80 ram long mirror" },
1557     { t_z80mem_noreq_w,      "z80 ram noreq write" },
1558     { t_z80mem_vdp_r,        "z80 vdp read" },
1559     // { t_z80mem_vdp_w,        "z80 vdp write" }, // hang
1560     { t_tim_loop,            "time loop" },
1561     { t_tim_z80_ram,         "time z80 ram" },
1562     { t_tim_z80_ym,          "time z80 ym2612" },
1563     { t_tim_z80_vdp,         "time z80 vdp" },
1564     { t_tim_z80_bank_rom,    "time z80 bank rom" },
1565     { t_tim_vcnt,            "time V counter" },
1566     { t_tim_hblank_h40,      "time hblank h40" },
1567     { t_tim_hblank_h32,      "time hblank h32" },
1568     { t_tim_vdp_as_vram_w,   "time vdp vram w" },
1569     { t_tim_vdp_as_cram_w,   "time vdp cram w" },
1570     { t_irq_hint,            "irq4 / line" },
1571     { t_irq_ack_v_h,         "irq ack v-h" },
1572     { t_irq_ack_v_h_2,       "irq ack v-h 2" },
1573     { t_irq_ack_h_v,         "irq ack h-v" },
1574     { t_irq_ack_h_v_2,       "irq ack h-v 2" },
1575     { t_irq_f_flag_h40,      "irq f flag h40" },
1576     { t_irq_f_flag_h32,      "irq f flag h32" },
1577 };
1578
1579 static void setup_z80(void)
1580 {
1581     u8 *zram = (u8 *)0xa00000;
1582     int i, len;
1583
1584     /* z80 */
1585     write16(0xa11100, 0x100);
1586     write16(0xa11200, 0x100);
1587
1588     while (read16(0xa11100) & 0x100)
1589         ;
1590
1591     // load the default test program, clear it's data
1592     len = z80_test_end - z80_test;
1593     for (i = 0; i < len; i++)
1594         write8(&zram[i], z80_test[i]);
1595     for (i = 0x1000; i < 0x1007; i++)
1596         write8(&zram[i], 0);
1597
1598     // reset
1599     write16(0xa11200, 0x000);
1600     write16(0xa11100, 0x000);
1601     burn10(1);
1602     write16(0xa11200, 0x100);
1603     burn10(1);
1604
1605     // take back the bus
1606     write16(0xa11100, 0x100);
1607     while (read16(0xa11100) & 0x100)
1608         ;
1609 }
1610
1611 static void wait_next_vsync(void)
1612 {
1613     while (read16(VDP_CTRL_PORT) & 8)
1614         /* blanking */;
1615     while (!(read16(VDP_CTRL_PORT) & 8))
1616         /* not blanking */;
1617 }
1618
1619 static unused int hexinc(char *c)
1620 {
1621     (*c)++;
1622     if (*c > 'f') {
1623         *c = '0';
1624         return 1;
1625     }
1626     if (*c == '9' + 1)
1627         *c = 'a';
1628     return 0;
1629 }
1630
1631 int main()
1632 {
1633     int passed = 0;
1634     int ret;
1635     u8 v8;
1636     int i;
1637
1638     setup_z80();
1639
1640     /* io */
1641     write8(0xa10009, 0x40);
1642
1643     /* setup VDP */
1644     while (read16(VDP_CTRL_PORT) & 2)
1645         ;
1646
1647     VDP_setReg(VDP_MODE1, VDP_MODE1_PS);
1648     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA);
1649     VDP_setReg(VDP_MODE3, 0x00);
1650     VDP_setReg(VDP_MODE4, 0x81);
1651     VDP_setReg(VDP_NT_SCROLLA, APLANE >> 10);
1652     VDP_setReg(VDP_NT_SCROLLB, BPLANE >> 13);
1653     VDP_setReg(VDP_SAT_BASE, SLIST >> 9);
1654     VDP_setReg(VDP_HSCROLL, HSCRL >> 10);
1655     VDP_setReg(VDP_AUTOINC, 2);
1656     VDP_setReg(VDP_SCROLLSZ, 0x01);
1657     VDP_setReg(VDP_BACKDROP, 0);
1658
1659     // early tests
1660     t_dma_zero_wrap_early();
1661     t_dma_zero_fill_early();
1662
1663     /* pattern 0 */
1664     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0));
1665     for (i = 0; i < 32 / 4; i++)
1666         write32(VDP_DATA_PORT, 0);
1667
1668     /* clear name tables */
1669     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(APLANE));
1670     for (i = 0; i < PLANE_W * PLANE_H / 2; i++)
1671         write32(VDP_DATA_PORT, 0);
1672
1673     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(BPLANE));
1674     for (i = 0; i < PLANE_W * PLANE_H / 2; i++)
1675         write32(VDP_DATA_PORT, 0);
1676
1677     /* SAT, h. scroll */
1678     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(SLIST));
1679     write32(VDP_DATA_PORT, 0);
1680
1681     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(HSCRL));
1682     write32(VDP_DATA_PORT, 0);
1683
1684     /* scroll plane vscroll */
1685     write32(VDP_CTRL_PORT, CTL_WRITE_VSRAM(0));
1686     write32(VDP_DATA_PORT, 0);
1687     printf_ypos = 1;
1688
1689     /* load font */
1690     write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(TILE_FONT_BASE));
1691     for (i = 0; i < FONT_LEN * 32 / 4; i++)
1692         write32(VDP_DATA_PORT, font_base[i]);
1693
1694     /* set colors */
1695     setup_default_palette();
1696
1697     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_DISP);
1698
1699     v8 = read8(0xa10001);
1700     printf("MD version: %02x %s %s\n", v8,
1701         (v8 & 0x80) ? "world" : "jap",
1702         (v8 & 0x40) ? "pal" : "ntsc");
1703
1704     for (i = 0; i < ARRAY_SIZE(g_tests); i++) {
1705         // print test number if we haven't scrolled away
1706         if (printf_ypos < CSCREEN_H) {
1707             int old_ypos = printf_ypos;
1708             printf_ypos = 0;
1709             printf("%02d/%02d", i, ARRAY_SIZE(g_tests));
1710             printf_ypos = old_ypos;
1711             printf_xpos = 0;
1712         }
1713         ret = g_tests[i].test();
1714         if (ret != 1) {
1715             text_pal = 2;
1716             printf("failed %d: %s\n", i, g_tests[i].name);
1717             text_pal = 0;
1718         }
1719         else
1720             passed++;
1721     }
1722
1723     text_pal = 0;
1724     printf("%d/%d passed.\n", passed, ARRAY_SIZE(g_tests));
1725
1726     printf_ypos = 0;
1727     printf("     ");
1728
1729     while (!(get_input() & BTNM_A))
1730         wait_next_vsync();
1731
1732
1733     {
1734         char c[3] = { '0', '0', '0' };
1735         short hscroll = 0, vscroll = 0;
1736         short hsz = 1, vsz = 0;
1737         short cellmode = 0;
1738
1739         write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(APLANE));
1740
1741 #if 0
1742         for (i = 0, c[0] = 'a'; i < 8 * 1024 / 2; i++) {
1743             write16(VDP_DATA_PORT, (u16)c[0] - 32 + TILE_FONT_BASE / 32);
1744             c[0]++;
1745             if (c[0] == 'z' + 1)
1746                 c[0] = 'a';
1747         }
1748 #else
1749         for (i = 0; i < 8 * 1024 / 2 / 4; i++) {
1750             write16(VDP_DATA_PORT, (u16)'.'  - 32 + TILE_FONT_BASE / 32);
1751             write16(VDP_DATA_PORT, (u16)c[2] - 32 + TILE_FONT_BASE / 32);
1752             write16(VDP_DATA_PORT, (u16)c[1] - 32 + TILE_FONT_BASE / 32);
1753             write16(VDP_DATA_PORT, (u16)c[0] - 32 + TILE_FONT_BASE / 32);
1754             if (hexinc(&c[0]))
1755                 if (hexinc(&c[1]))
1756                     hexinc(&c[2]);
1757         }
1758 #endif
1759         while (get_input() & BTNM_A)
1760             wait_next_vsync();
1761
1762         wait_next_vsync();
1763         for (;;) {
1764             int b = get_input();
1765
1766             if (b & BTNM_C) {
1767                 hscroll = 1, vscroll = -1;
1768                 do {
1769                     wait_next_vsync();
1770                 } while (get_input() & BTNM_C);
1771                 cellmode ^= 1;
1772             }
1773             if (b & (BTNM_L | BTNM_R | BTNM_C)) {
1774                 hscroll += (b & BTNM_L) ? 1 : -1;
1775                 write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(HSCRL));
1776                 write16(VDP_DATA_PORT, hscroll);
1777             }
1778             if (b & (BTNM_U | BTNM_D | BTNM_C)) {
1779                 vscroll += (b & BTNM_U) ? -1 : 1;
1780                 write32(VDP_CTRL_PORT, CTL_WRITE_VSRAM(0));
1781                 if (cellmode) {
1782                     int end = (int)vscroll + 21;
1783                     for (i = vscroll; i < end; i++)
1784                         write32(VDP_DATA_PORT, i << 17);
1785                     VDP_setReg(VDP_MODE3, 0x04);
1786                 }
1787                 else {
1788                     write16(VDP_DATA_PORT, vscroll);
1789                     VDP_setReg(VDP_MODE3, 0x00);
1790                 }
1791             }
1792             if (b & BTNM_A) {
1793                 hsz = (hsz + 1) & 3;
1794                 do {
1795                     wait_next_vsync();
1796                 } while (get_input() & BTNM_A);
1797             }
1798             if (b & BTNM_B) {
1799                 vsz = (vsz + 1) & 3;
1800                 do {
1801                     wait_next_vsync();
1802                 } while (get_input() & BTNM_B);
1803             }
1804             VDP_setReg(VDP_SCROLLSZ, (vsz << 4) | hsz);
1805
1806             printf_xpos = 1;
1807             printf_ypos = 0;
1808             text_pal = 1;
1809             printf(" %d %d ", hsz, vsz);
1810
1811             wait_next_vsync();
1812         }
1813     }
1814
1815     for (;;)
1816         ;
1817
1818     return 0;
1819 }
1820
1821 // vim:ts=4:sw=4:expandtab