ef421bde57e132c2b7d69c1255e21215ecb9c3d0
[megadrive.git] / megaed-sv / main.c
1 #include <stdarg.h>
2
3 #define u8      unsigned char
4 #define u16     unsigned short
5 #define u32     unsigned int
6
7 #define noinline __attribute__((noinline))
8
9 #include "edos.h"
10
11 #define GFX_DATA_PORT    0xC00000
12 #define GFX_CTRL_PORT    0xC00004
13
14 #define TILE_MEM_END     0xB000
15
16 #define FONT_LEN         128
17 #define TILE_FONT_BASE   (TILE_MEM_END / 32  - FONT_LEN)
18
19 /* note: using ED menu's layout here.. */
20 #define WPLAN            (TILE_MEM_END + 0x0000)
21 #define HSCRL            (TILE_MEM_END + 0x0800)
22 #define SLIST            (TILE_MEM_END + 0x0C00)
23 #define APLANE           (TILE_MEM_END + 0x1000)
24 #define BPLANE           (TILE_MEM_END + 0x3000)
25
26 #define write16(a, d) \
27     *((volatile u16 *) (a)) = (d)
28 #define write32(a, d) \
29     *((volatile u32 *) (a)) = (d)
30
31 #define GFX_WRITE_VRAM_ADDR(adr) \
32     (((0x4000 | ((adr) & 0x3FFF)) << 16) | ((adr) >> 14) | 0x00)
33 #define GFX_WRITE_VSRAM_ADDR(adr) \
34     (((0x4000 | ((adr) & 0x3FFF)) << 16) | ((adr) >> 14) | 0x10)
35
36 enum {
37     VDP_MODE1 = 0x00,
38     VDP_MODE2 = 0x01,
39     VDP_BACKDROP = 0x07,
40     VDP_MODE3 = 0x0b,
41     VDP_MODE4 = 0x0c,
42     VDP_AUTOINC = 0x0f,
43     VDP_SCROLLSZ = 0x10,
44 };
45
46 /* cell counts */
47 #define LEFT_BORDER 1   /* lame TV */
48 #define PLANE_W 64
49 #define PLANE_H 32
50 #define CSCREEN_H 28
51
52 static noinline void VDP_drawTextML(const char *str, u16 plane_base,
53     u16 x, u16 y)
54 {
55     const u8 *src = (const u8 *)str;
56     u16 basetile = 0;
57     int max_len = 40 - LEFT_BORDER;
58     int len;
59     u32 addr;
60
61     x += LEFT_BORDER;
62
63     for (len = 0; str[len] && len < max_len; len++)
64         ;
65     if (len > (PLANE_W - x))
66         len = PLANE_W - x;
67
68     addr = plane_base + ((x + (PLANE_W * y)) << 1);
69     write32(GFX_CTRL_PORT, GFX_WRITE_VRAM_ADDR(addr));
70
71     while (len-- > 0) {
72         write16(GFX_DATA_PORT,
73             basetile | ((*src++) - 32 + TILE_FONT_BASE));
74     }
75 }
76
77 static int printf_ypos;
78
79 static void printf_line(int x, const char *buf)
80 {
81     u32 addr;
82     int i;
83
84     if (printf_ypos >= CSCREEN_H) {
85     }
86
87     VDP_drawTextML(buf, APLANE, x, printf_ypos++ & (PLANE_H - 1));
88
89     if (printf_ypos >= CSCREEN_H) {
90         /* clear next line */
91         addr = APLANE;
92         addr += (PLANE_W * (printf_ypos & (PLANE_H - 1))) << 1;
93         write32(GFX_CTRL_PORT, GFX_WRITE_VRAM_ADDR(addr));
94         for (i = 0; i < 40 / 2; i++)
95             write32(GFX_DATA_PORT, 0);
96
97         /* scroll plane */
98         write32(GFX_CTRL_PORT, GFX_WRITE_VSRAM_ADDR(0));
99         write16(GFX_DATA_PORT, (printf_ypos - 27) * 8);
100     }
101 }
102
103 static noinline int printf(const char *fmt, ...)
104 {
105     static int printf_xpos;
106     char buf[40+11];
107     va_list ap;
108     int ival;
109     int d = 0;
110     int i;
111
112     va_start(ap, fmt);
113     for (d = 0; *fmt; ) {
114         buf[d] = *fmt++;
115         if (buf[d] != '%') {
116             if (buf[d] == '\n') {
117                 buf[d] = 0;
118                 if (d != 0)
119                     printf_line(printf_xpos, buf);
120                 d = 0;
121                 printf_xpos = 0;
122                 continue;
123             }
124             d++;
125             continue;
126         }
127
128         switch (*fmt++) {
129         case '%':
130             d++;
131             break;
132         case 'd':
133         case 'i':
134             ival = va_arg(ap, int);
135             if (ival < 0) {
136                 buf[d++] = '-';
137                 ival = -ival;
138             }
139             for (i = 1000000000; i >= 10; i /= 10)
140                 if (ival >= i)
141                     break;
142             for (; i >= 10; i /= 10) {
143                 buf[d++] = '0' + ival / i;
144                 ival %= i;
145             }
146             buf[d++] = '0' + ival;
147             break;
148         case 's':
149             // s = va_arg(ap, char *);
150         default:
151             // don't handle, for now
152             d++;
153             buf[d++] = *fmt++;
154             va_arg(ap, void *);
155             break;
156         }
157     }
158     buf[d] = 0;
159     va_end(ap);
160
161     if (d != 0) {
162         // line without \n
163         VDP_drawTextML(buf, APLANE, printf_xpos,
164             printf_ypos & (PLANE_H - 1));
165         printf_xpos += d;
166     }
167
168     return d; // wrong..
169 }
170
171 void exception(void)
172 {
173     VDP_drawTextML("============", APLANE, 0, 0);
174     VDP_drawTextML(" exception! ", APLANE, 0, 1);
175     VDP_drawTextML("============", APLANE, 0, 2);
176     while (1)
177         ;
178 }
179
180 void vbl(void)
181 {
182 }
183
184 int main()
185 {
186     OsRoutine *ed;
187     int i, j = 0;
188
189     ed = (OsRoutine *) *(u32 *)0x1A0;
190     ed->memInitDmaCode(); 
191
192     ed->VDP_setReg(VDP_MODE1, 0x04); 
193     ed->VDP_setReg(VDP_MODE2, 0x64); 
194     ed->VDP_setReg(VDP_AUTOINC, 2); 
195     ed->VDP_setReg(VDP_SCROLLSZ, 0x01); 
196
197     /* clear name tables */
198     write32(GFX_CTRL_PORT, GFX_WRITE_VRAM_ADDR(APLANE));
199     for (i = 0; i < PLANE_W * PLANE_H / 2; i++)
200         write32(GFX_DATA_PORT, 0);
201
202     write32(GFX_CTRL_PORT, GFX_WRITE_VRAM_ADDR(BPLANE));
203     for (i = 0; i < PLANE_W * PLANE_H / 2; i++)
204         write32(GFX_DATA_PORT, 0);
205
206     /* note: relying on ED menu's font setup here.. */
207
208     // VDP_drawTextML("hello", APLANE, 0, 0);
209     printf("hello1");
210     printf(" hello2\n");
211     printf("hello3\n");
212
213     for (;;) {
214         for (i = 0; i < 30; i++)
215             asm volatile("stop #0x2000");
216
217         printf("hello %d\n", j++);
218     }
219
220     return 0;
221 }
222
223 // vim:ts=4:sw=4:expandtab