testpico: more on timer reload
[megadrive.git] / megaed-stop / main.c
CommitLineData
d2bfad8a 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#include "edos.h"
13
14#define GFX_DATA_PORT 0xC00000
15#define GFX_CTRL_PORT 0xC00004
16
17#define TILE_MEM_END 0xB000
18
19#define FONT_LEN 128
20#define TILE_FONT_BASE (TILE_MEM_END / 32 - FONT_LEN)
21
22/* note: using ED menu's layout here.. */
23#define WPLANE (TILE_MEM_END + 0x0000)
24#define HSCRL (TILE_MEM_END + 0x0800)
25#define SLIST (TILE_MEM_END + 0x0C00)
26#define APLANE (TILE_MEM_END + 0x1000)
27#define BPLANE (TILE_MEM_END + 0x3000)
28
29#define read8(a) \
30 *((volatile u8 *) (a))
31#define read16(a) \
32 *((volatile u16 *) (a))
33#define read32(a) \
34 *((volatile u32 *) (a))
35#define write16(a, d) \
36 *((volatile u16 *) (a)) = (d)
37#define write32(a, d) \
38 *((volatile u32 *) (a)) = (d)
39
40#define GFX_WRITE_VRAM_ADDR(adr) \
41 (((0x4000 | ((adr) & 0x3FFF)) << 16) | ((adr) >> 14) | 0x00)
42#define GFX_WRITE_VSRAM_ADDR(adr) \
43 (((0x4000 | ((adr) & 0x3FFF)) << 16) | ((adr) >> 14) | 0x10)
44
45enum {
46 VDP_MODE1 = 0x00,
47 VDP_MODE2 = 0x01,
48 VDP_BACKDROP = 0x07,
49 VDP_MODE3 = 0x0b,
50 VDP_MODE4 = 0x0c,
51 VDP_AUTOINC = 0x0f,
52 VDP_SCROLLSZ = 0x10,
53};
54
55/* cell counts */
56#define LEFT_BORDER 1 /* lame TV */
57#define PLANE_W 64
58#define PLANE_H 32
59#define CSCREEN_H 28
60
61static void VDP_drawTextML(const char *str, u16 plane_base,
62 u16 x, u16 y)
63{
64 const u8 *src = (const u8 *)str;
65 u16 basetile = 0;
66 int max_len = 40 - LEFT_BORDER;
67 int len;
68 u32 addr;
69
70 x += LEFT_BORDER;
71
72 for (len = 0; str[len] && len < max_len; len++)
73 ;
74 if (len > (PLANE_W - x))
75 len = PLANE_W - x;
76
77 addr = plane_base + ((x + (PLANE_W * y)) << 1);
78 write32(GFX_CTRL_PORT, GFX_WRITE_VRAM_ADDR(addr));
79
80 while (len-- > 0) {
81 write16(GFX_DATA_PORT,
3ee911dc 82 basetile | ((*src++) - 32 + TILE_FONT_BASE / 32));
d2bfad8a 83 }
84}
85
86static int printf_ypos;
87
88static void printf_line(int x, const char *buf)
89{
90 u32 addr;
91 int i;
92
93 VDP_drawTextML(buf, APLANE, x, printf_ypos++ & (PLANE_H - 1));
94
95 if (printf_ypos >= CSCREEN_H) {
96 /* clear next line */
97 addr = APLANE;
98 addr += (PLANE_W * (printf_ypos & (PLANE_H - 1))) << 1;
99 write32(GFX_CTRL_PORT, GFX_WRITE_VRAM_ADDR(addr));
100 for (i = 0; i < 40 / 2; i++)
101 write32(GFX_DATA_PORT, 0);
102
103 /* scroll plane */
104 write32(GFX_CTRL_PORT, GFX_WRITE_VSRAM_ADDR(0));
105 write16(GFX_DATA_PORT, (printf_ypos - CSCREEN_H + 1) * 8);
106 }
107}
108
109#define PRINTF_LEN 40
110
111static int printf(const char *fmt, ...)
112{
113 static const char hexchars[] = "0123456789abcdef";
114 static int printf_xpos;
115 char c, buf[PRINTF_LEN + 11 + 1];
116 const char *s;
117 va_list ap;
118 int ival;
119 u32 uval;
120 int d = 0;
121 int i, j;
122
123 va_start(ap, fmt);
124 for (d = 0; *fmt; ) {
125 int prefix0 = 0;
126 int fwidth = 0;
127
128 c = *fmt++;
129 if (d < PRINTF_LEN)
130 buf[d] = c;
131
132 if (c != '%') {
133 if (c == '\n') {
134 buf[d] = 0;
135 printf_line(printf_xpos, buf);
136 d = 0;
137 printf_xpos = 0;
138 continue;
139 }
140 d++;
141 continue;
142 }
143 if (d >= PRINTF_LEN)
144 continue;
145
146 if (*fmt == '0') {
147 prefix0 = 1;
148 fmt++;
149 }
150
151 while ('1' <= *fmt && *fmt <= '9') {
152 fwidth = fwidth * 10 + *fmt - '0';
153 fmt++;
154 }
155
156 switch (*fmt++) {
157 case '%':
158 d++;
159 break;
160 case 'd':
161 case 'i':
162 ival = va_arg(ap, int);
163 if (ival < 0) {
164 buf[d++] = '-';
165 ival = -ival;
166 }
167 for (i = 1000000000; i >= 10; i /= 10)
168 if (ival >= i)
169 break;
170 for (; i >= 10; i /= 10) {
171 buf[d++] = '0' + ival / i;
172 ival %= i;
173 }
174 buf[d++] = '0' + ival;
175 break;
176 case 'x':
177 uval = va_arg(ap, int);
178 while (fwidth > 1 && uval < (1 << (fwidth - 1) * 4)) {
179 buf[d++] = prefix0 ? '0' : ' ';
180 fwidth--;
181 }
182 for (j = 1; j < 8 && uval >= (1 << j * 4); j++)
183 ;
184 for (j--; j >= 0; j--)
185 buf[d++] = hexchars[(uval >> j * 4) & 0x0f];
186 break;
187 case 's':
188 s = va_arg(ap, char *);
189 while (*s && d < PRINTF_LEN)
190 buf[d++] = *s++;
191 break;
192 default:
193 // don't handle, for now
194 d++;
195 va_arg(ap, void *);
196 break;
197 }
198 }
199 buf[d] = 0;
200 va_end(ap);
201
202 if (d != 0) {
203 // line without \n
204 VDP_drawTextML(buf, APLANE, printf_xpos,
205 printf_ypos & (PLANE_H - 1));
206 printf_xpos += d;
207 }
208
209 return d; // wrong..
210}
211
212int main()
213{
214 OsRoutine *ed;
215 u8 seed, bad = 0;
216 u8 *p, val;
217 int i, t, len;
218
219 ed = (OsRoutine *) *(u32 *)0x1A0;
220 ed->memInitDmaCode();
221
222 ed->VDP_setReg(VDP_MODE1, 0x04);
223 ed->VDP_setReg(VDP_MODE2, 0x64);
224 ed->VDP_setReg(VDP_AUTOINC, 2);
225 ed->VDP_setReg(VDP_SCROLLSZ, 0x01);
226
227 /* clear name tables */
228 write32(GFX_CTRL_PORT, GFX_WRITE_VRAM_ADDR(APLANE));
229 for (i = 0; i < PLANE_W * PLANE_H / 2; i++)
230 write32(GFX_DATA_PORT, 0);
231
232 write32(GFX_CTRL_PORT, GFX_WRITE_VRAM_ADDR(BPLANE));
233 for (i = 0; i < PLANE_W * PLANE_H / 2; i++)
234 write32(GFX_DATA_PORT, 0);
235
236 /* scroll planes */
237 write32(GFX_CTRL_PORT, GFX_WRITE_VSRAM_ADDR(0));
238 write32(GFX_DATA_PORT, 0);
239
240 /* note: relying on ED menu's font setup here.. */
241
242 printf("\n");
243 printf("MD version: %02x\n", read8(0xa10001));
244 printf("ED os/fw: %d/%d\n\n", ed->osGetOsVersion(),
245 ed->osGetFirmVersion());
246
247 seed = read8(0xC00009);
248 p = (void *)0x200000;
249 len = 0x200000;
250 printf("filling SDRAM, seed=%02x.. ", seed);
251
252 val = seed;
253 for (i = 0; i < len; i++)
254 p[i] = val++;
255
256 printf("done.\n");
257
258 for (t = 1; ; t++) {
259 printf("executing stop.. ");
260 for (i = 0; i < 5 * 60; i++)
261 asm volatile("stop #0x2000");
262 printf("done\n");
263
264 printf("checking memory..\n");
265
266 val = seed;
267 for (i = 0; i < len; i++) {
268 if (p[i] != val) {
269 printf("bad: %06x: got %02x, expected %02x\n",
270 &p[i], p[i], val);
271 bad = 1;
272 }
273 val++;
274 }
275
276 printf("done. Try %d: test ", t);
277 if (bad) {
278 printf("FAILED\n");
279 break;
280 }
281 printf("PASSED\n");
282 }
283
284 /* there are not enough STOP opcodes in this world :D */
285 while (1)
286 asm volatile("stop #0x2000");
287
288 return 0;
289}
290
291// vim:ts=4:sw=4:expandtab