forgot romhdr.S
[megatris] / src / vdp.h
1 #ifndef VDP_H_
2 #define VDP_H_
3
4 #include <stdint.h>
5
6 #define VDP_PORT_DATA           *((volatile uint16_t*)0xc00000)
7 #define VDP_PORT_DATA32         *((volatile uint32_t*)0xc00000)
8 #define VDP_PORT_CTL            *((volatile uint16_t*)0xc00004)
9 #define VDP_PORT_CTL32          *((volatile uint32_t*)0xc00004)
10 #define VDP_PORT_HVCNT          *((volatile uint16_t*)0xc00008)
11 #define VDP_PORT_PSG            *((volatile uint16_t*)0xc00010)
12
13 #define VDP_PORT_STATUS         *((volatile uint16_t*)0xc00004)
14
15 enum {
16         VDP_REG_MODE1                   = 0,
17         VDP_REG_MODE2                   = 1,
18         VDP_REG_NAMETAB_A               = 2,
19         VDP_REG_NAMETAB_WIN             = 3,
20         VDP_REG_NAMETAB_B               = 4,
21         VDP_REG_SPRITE_TAB              = 5,
22         VDP_REG_BGCOL                   = 7,
23         VDP_REG_HINTR                   = 10,
24         VDP_REG_MODE3                   = 11,
25         VDP_REG_MODE4                   = 12,
26         VDP_REG_SCROLL_TAB              = 13,
27         VDP_REG_AUTOINC                 = 15,
28         VDP_REG_SCROLL_SIZE             = 16,
29         VDP_REG_WIN_XPOS                = 17,
30         VDP_REG_WIN_YPOS                = 18,
31         VDP_REG_DMA_LEN_LOW             = 19,
32         VDP_REG_DMA_LEN_HIGH    = 20,
33         VDP_REG_DMA_SRC_LOW             = 21,
34         VDP_REG_DMA_SRC_MID             = 22,
35         VDP_REG_DMA_SRC_HIGH    = 23,
36
37         VDP_NUM_REGS
38 };
39
40 uint16_t vdp_reg_shadow[VDP_NUM_REGS];
41
42 /* access VDP memory */
43 enum { VDP_MEM_READ, VDP_MEM_WRITE };
44 enum {
45         VDP_MEM_VRAM    = 0,
46         VDP_MEM_CRAM    = 0xa,  /* CD5->CD0: 0 0 r 0 w 0 */
47         VDP_MEM_VSRAM   = 4             /* CD5->CD0: 0 0 0 1 0 0 */
48 };
49
50 enum {
51         VDP_PLANE_A,
52         VDP_PLANE_B,
53         VDP_PLANE_WIN
54 };
55
56 enum {
57         VDP_TILE_LOW_PRIO       = 0,
58         VDP_TILE_HFLIP          = 0x0800,
59         VDP_TILE_VFLIP          = 0x1000,
60         VDP_TILE_HIGH_PRIO      = 0x8000
61 };
62
63 enum {
64         VDP_STAT_PAL            = 0x0001,
65         VDP_STAT_DMABUSY        = 0x0002,
66         VDP_STAT_HBLANK         = 0x0004,
67         VDP_STAT_VBLANK         = 0x0008,
68         VDP_STAT_ODDFIELD       = 0x0010,
69         VDP_STAT_SPRITE_COL     = 0x0020,
70         VDP_STAT_SPRITE_OVF = 0x0040,
71         VDP_STAT_VINTR          = 0x0080,
72         VDP_STAT_FIFO_FULL      = 0x0100,
73         VDP_STAT_FIFO_EMPTY     = 0x0200
74 };
75
76
77 static inline void vdp_setup_access(uint16_t addr, int rw, int memid)
78 {
79         uint32_t type;
80         if(rw == VDP_MEM_WRITE) {
81                 type = (memid & 7) | 1;
82         } else {
83                 type = memid & 0xc;
84         }
85
86         VDP_PORT_CTL32 = (((uint32_t)addr & 0x3fff) << 16) | ((addr >> 14) & 3) |
87                 ((type << 2) & 0xf0) | (type << 30);
88 }
89
90
91 /* mode register 1 */
92 enum {
93         VDP_MODE1_BASE  = 0x4,
94         VDP_MODE1_HVCNT = 0x2,
95         VDP_MODE1_HINTR = 0x10
96 };
97
98 /* mode register 2 */
99 enum {
100         VDP_MODE2_BASE          = 0x4,
101         VDP_MODE2_V30CELL       = 0x8,
102         VDP_MODE2_DMA           = 0x10,
103         VDP_MODE2_VINTR         = 0x20,
104         VDP_MODE2_DISP          = 0x40
105 };
106
107 /* mode register 3 */
108 enum {
109         VDP_MODE3_BASE                  = 0,
110         VDP_MODE3_HSCROLL_CELL  = 2,
111         VDP_MODE3_HSCROLL_LINE  = 3,
112         VDP_MODE3_VSCROLL_2CELL = 4,
113         VDP_MODE3_EXTINTR               = 8
114 };
115
116 /* mode register 4 */
117 enum {
118         VDP_MODE4_BASE                  = 0,
119         VDP_MODE4_H40CELL               = 0x81,
120         VDP_MODE4_ILACE                 = 2,
121         VDP_MODE4_ILACE_2XRES   = 6,
122         VDP_MODE4_SH                    = 8     /* shadow/highlight enable */
123 };
124
125 /* scroll size register */
126 enum {
127         VDP_SCROLL_H32          = 0,
128         VDP_SCROLL_H64          = 1,
129         VDP_SCROLL_H128         = 3,
130         VDP_SCROLL_V32          = 0,
131         VDP_SCROLL_V64          = 0x10,
132         VDP_SCROLL_V128         = 0x30
133 };
134
135 /* window X/Y position register */
136 enum {
137         VDP_WIN_LEFT    = 0,
138         VDP_WIN_UP              = 0,
139         VDP_WIN_RIGHT   = 0x80,
140         VDP_WIN_DOWN    = 0x80,
141         VDP_WIN_POSMASK = 0x1f
142 };
143
144 #define VDP_PACK_RGB(r, g, b)   \
145         ((((uint16_t)(r) & 7) << 1) | (((uint16_t)(g) & 7) << 5) | (((uint16_t)(b) & 7) << 9))
146
147
148 static inline void vdp_setreg(int reg, uint8_t value)
149 {
150         vdp_reg_shadow[reg] = value;
151         VDP_PORT_CTL = (uint16_t)value | (reg << 8) | (uint16_t)0x8000;
152 }
153
154 static inline uint16_t vdp_getreg(int reg)
155 {
156         return vdp_reg_shadow[reg];
157 }
158
159 static inline uint16_t vdp_status(void)
160 {
161         return VDP_PORT_CTL;
162 }
163
164 static inline void vdp_set_bgcolor(int palidx, int colidx)
165 {
166         vdp_setreg(VDP_REG_BGCOL, (colidx & 0xf) | (palidx << 4));
167 }
168
169 static inline void vdp_set_autoinc(int stride)
170 {
171         vdp_setreg(VDP_REG_AUTOINC, stride);
172 }
173
174 static inline void vdp_begin_palette(int pidx, int cidx)
175 {
176         uint16_t paddr = (pidx << 5) | (cidx << 1);
177         vdp_setup_access(paddr, VDP_MEM_WRITE, VDP_MEM_CRAM);
178 }
179
180 static inline void vdp_set_pal_entry(int pidx, int cidx, int r, int g, int b)
181 {
182         vdp_begin_palette(pidx, cidx);
183         VDP_PORT_DATA = VDP_PACK_RGB(r, g, b);
184 }
185
186 static inline void vdp_enable_vintr(void)
187 {
188         vdp_setreg(VDP_REG_MODE2, vdp_getreg(VDP_REG_MODE2) | VDP_MODE2_VINTR);
189 }
190
191 static inline void vdp_disable_vintr(void)
192 {
193         vdp_setreg(VDP_REG_MODE2, vdp_getreg(VDP_REG_MODE2) & ~VDP_MODE2_VINTR);
194 }
195
196 static inline void vdp_enable_hintr(int counter)
197 {
198         vdp_setreg(VDP_REG_HINTR, counter);
199         vdp_setreg(VDP_REG_MODE1, vdp_getreg(VDP_REG_MODE1) | VDP_MODE1_HINTR);
200 }
201
202 static inline void vdp_disable_hintr(void)
203 {
204         vdp_setreg(VDP_REG_MODE1, vdp_getreg(VDP_REG_MODE1) & ~VDP_MODE1_HINTR);
205 }
206
207 static inline void vdp_set_nametab_addr(int plane, uint16_t addr)
208 {
209         switch(plane) {
210         case VDP_PLANE_A:
211                 vdp_setreg(VDP_REG_NAMETAB_A, (addr >> 10) & 0x38);
212                 break;
213         case VDP_PLANE_B:
214                 vdp_setreg(VDP_REG_NAMETAB_B, (addr >> 13) & 7);
215                 break;
216         case VDP_PLANE_WIN:
217                 vdp_setreg(VDP_REG_NAMETAB_WIN, (addr >> 10) & 0x7e);
218         default:
219                 break;
220         }
221 }
222
223 static inline uint16_t vdp_nametab_addr(int idx)
224 {
225         return (uint16_t)idx << 13;
226 }
227
228 static inline void vdp_set_nametab_idx(int plane, int idx)
229 {
230         vdp_set_nametab_addr(plane, vdp_nametab_addr(idx));
231 }
232
233 static inline void vdp_disable_layer(int plane)
234 {
235         switch(plane) {
236         case VDP_PLANE_A:
237                 vdp_setreg(VDP_REG_NAMETAB_A, 0x40);
238                 break;
239         case VDP_PLANE_B:
240                 vdp_setreg(VDP_REG_NAMETAB_B, 0x08);
241                 break;
242         case VDP_PLANE_WIN:
243                 vdp_setreg(VDP_REG_NAMETAB_WIN, 0x40);
244         default:
245                 break;
246         }
247 }
248
249 static inline uint16_t vdp_nametab_entry(int tileidx, int palidx, uint16_t flags)
250 {
251         return tileidx | (((uint16_t)palidx & 0x3) << 13) | flags;
252 }
253
254 static inline void vdp_set_sprite_table(uint16_t addr)
255 {
256         vdp_setreg(VDP_REG_SPRITE_TAB, addr >> 9);
257 }
258
259 static inline void vdp_set_scroll_table(uint16_t addr)
260 {
261         vdp_setreg(VDP_REG_SCROLL_TAB, addr >> 10);
262 }
263
264 static inline void vdp_wait_vblank_start(void)
265 {
266         while(!(VDP_PORT_STATUS & VDP_STAT_VBLANK));
267 }
268
269 static inline void vdp_wait_vblank_end(void)
270 {
271         while(VDP_PORT_STATUS & VDP_STAT_VBLANK);
272 }
273
274 static inline void vdp_wait_vblank(void)
275 {
276         vdp_wait_vblank_start();
277         vdp_wait_vblank_end();
278 }
279
280 void vdp_init(void);
281
282 #endif  /* VDP_H_ */