megadrive_test2
view src/vdp.h @ 6:df2c6b3c6f2e
added NTSC/PAL detection
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 21 Jun 2017 06:32:10 +0300 |
parents | 72ab63f262bf |
children | 403367d5df5a |
line source
1 #ifndef VDP_H_
2 #define VDP_H_
4 #include <stdint.h>
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)
13 #define VDP_PORT_STATUS *((volatile uint16_t*)0xc00004)
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,
37 VDP_NUM_REGS
38 };
40 uint16_t vdp_reg_shadow[VDP_NUM_REGS];
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 };
50 enum {
51 VDP_PLANE_A,
52 VDP_PLANE_B,
53 VDP_PLANE_WIN
54 };
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 };
63 static inline void vdp_setup_access(uint16_t addr, int rw, int memid)
64 {
65 uint32_t type;
66 if(rw == VDP_MEM_WRITE) {
67 type = (memid & 7) | 1;
68 } else {
69 type = memid & 0xc;
70 }
72 VDP_PORT_CTL32 = (((uint32_t)addr & 0x3fff) << 16) | ((addr >> 14) & 3) |
73 ((type << 2) & 0xf0) | (type << 30);
74 }
77 /* mode register 1 */
78 enum {
79 VDP_MODE1_BASE = 0x4,
80 VDP_MODE1_HVCNT = 0x2,
81 VDP_MODE1_HINTR = 0x10
82 };
84 /* mode register 2 */
85 enum {
86 VDP_MODE2_BASE = 0x4,
87 VDP_MODE2_V30CELL = 0x8,
88 VDP_MODE2_DMA = 0x10,
89 VDP_MODE2_VINTR = 0x20,
90 VDP_MODE2_DISP = 0x40
91 };
93 /* mode register 3 */
94 enum {
95 VDP_MODE3_BASE = 0,
96 VDP_MODE3_HSCROLL_CELL = 2,
97 VDP_MODE3_HSCROLL_LINE = 3,
98 VDP_MODE3_VSCROLL_2CELL = 4,
99 VDP_MODE3_EXTINTR = 8
100 };
102 /* mode register 4 */
103 enum {
104 VDP_MODE4_BASE = 0,
105 VDP_MODE4_H40CELL = 0x81,
106 VDP_MODE4_ILACE = 2,
107 VDP_MODE4_ILACE_2XRES = 6,
108 VDP_MODE4_SH = 8 /* shadow/highlight enable */
109 };
111 /* scroll size register */
112 enum {
113 VDP_SCROLL_H32 = 0,
114 VDP_SCROLL_H64 = 1,
115 VDP_SCROLL_H128 = 3,
116 VDP_SCROLL_V32 = 0,
117 VDP_SCROLL_V64 = 0x10,
118 VDP_SCROLL_V128 = 0x30
119 };
121 /* window X/Y position register */
122 enum {
123 VDP_WIN_LEFT = 0,
124 VDP_WIN_UP = 0,
125 VDP_WIN_RIGHT = 0x80,
126 VDP_WIN_DOWN = 0x80,
127 VDP_WIN_POSMASK = 0x1f
128 };
130 #define VDP_PACK_RGB(r, g, b) \
131 ((((uint16_t)(r) & 7) << 1) | (((uint16_t)(g) & 7) << 5) | (((uint16_t)(b) & 7) << 9))
134 static inline void vdp_setreg(int reg, uint8_t value)
135 {
136 vdp_reg_shadow[reg] = value;
137 VDP_PORT_CTL = (uint16_t)value | (reg << 8) | (uint16_t)0x8000;
138 }
140 static inline uint16_t vdp_getreg(int reg)
141 {
142 return vdp_reg_shadow[reg];
143 }
145 static inline uint16_t vdp_status(void)
146 {
147 return VDP_PORT_CTL;
148 }
150 static inline void vdp_set_bgcolor(int palidx, int colidx)
151 {
152 vdp_setreg(VDP_REG_BGCOL, (colidx & 0xf) | (palidx << 4));
153 }
155 static inline void vdp_set_autoinc(int stride)
156 {
157 vdp_setreg(VDP_REG_AUTOINC, stride);
158 }
160 static inline void vdp_begin_palette(int pidx, int cidx)
161 {
162 uint16_t paddr = (pidx << 5) | (cidx << 1);
163 vdp_setup_access(paddr, VDP_MEM_WRITE, VDP_MEM_CRAM);
164 }
166 static inline void vdp_set_pal_entry(int pidx, int cidx, int r, int g, int b)
167 {
168 vdp_begin_palette(pidx, cidx);
169 VDP_PORT_DATA = VDP_PACK_RGB(r, g, b);
170 }
172 static inline void vdp_enable_vintr(void)
173 {
174 vdp_setreg(VDP_REG_MODE2, vdp_getreg(VDP_REG_MODE2) | VDP_MODE2_VINTR);
175 }
177 static inline void vdp_disable_vintr(void)
178 {
179 vdp_setreg(VDP_REG_MODE2, vdp_getreg(VDP_REG_MODE2) & ~VDP_MODE2_VINTR);
180 }
182 static inline void vdp_enable_hintr(int counter)
183 {
184 vdp_setreg(VDP_REG_HINTR, counter);
185 vdp_setreg(VDP_REG_MODE1, vdp_getreg(VDP_REG_MODE1) | VDP_MODE1_HINTR);
186 }
188 static inline void vdp_disable_hintr(void)
189 {
190 vdp_setreg(VDP_REG_MODE1, vdp_getreg(VDP_REG_MODE1) & ~VDP_MODE1_HINTR);
191 }
193 static inline void vdp_set_nametab_addr(int plane, uint16_t addr)
194 {
195 switch(plane) {
196 case VDP_PLANE_A:
197 vdp_setreg(VDP_REG_NAMETAB_A, (addr >> 10) & 0x38);
198 break;
199 case VDP_PLANE_B:
200 vdp_setreg(VDP_REG_NAMETAB_B, (addr >> 13) & 7);
201 break;
202 case VDP_PLANE_WIN:
203 vdp_setreg(VDP_REG_NAMETAB_WIN, (addr >> 10) & 0x7e);
204 default:
205 break;
206 }
207 }
209 static inline uint16_t vdp_nametab_addr(int idx)
210 {
211 return (uint16_t)idx << 13;
212 }
214 static inline void vdp_set_nametab_idx(int plane, int idx)
215 {
216 vdp_set_nametab_addr(plane, vdp_nametab_addr(idx));
217 }
219 static inline void vdp_disable_layer(int plane)
220 {
221 switch(plane) {
222 case VDP_PLANE_A:
223 vdp_setreg(VDP_REG_NAMETAB_A, 0x40);
224 break;
225 case VDP_PLANE_B:
226 vdp_setreg(VDP_REG_NAMETAB_B, 0x08);
227 break;
228 case VDP_PLANE_WIN:
229 vdp_setreg(VDP_REG_NAMETAB_WIN, 0x40);
230 default:
231 break;
232 }
233 }
235 static inline uint16_t vdp_nametab_entry(int tileidx, int palidx, uint16_t flags)
236 {
237 return tileidx | (((uint16_t)palidx & 0x3) << 13) | flags;
238 }
240 static inline void vdp_set_sprite_table(uint16_t addr)
241 {
242 vdp_setreg(VDP_REG_SPRITE_TAB, addr >> 9);
243 }
245 static inline void vdp_set_scroll_table(uint16_t addr)
246 {
247 vdp_setreg(VDP_REG_SCROLL_TAB, addr >> 10);
248 }
250 void vdp_init(void);
252 #endif /* VDP_H_ */