megadrive_test2

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