megadrive_test2

annotate src/vdp.h @ 12:54caa2b214ca

TMSS code
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 26 Dec 2018 04:39:09 +0200
parents 403367d5df5a
children
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@9 63 enum {
nuclear@9 64 VDP_STAT_PAL = 0x0001,
nuclear@9 65 VDP_STAT_DMABUSY = 0x0002,
nuclear@9 66 VDP_STAT_HBLANK = 0x0004,
nuclear@9 67 VDP_STAT_VBLANK = 0x0008,
nuclear@9 68 VDP_STAT_ODDFIELD = 0x0010,
nuclear@9 69 VDP_STAT_SPRITE_COL = 0x0020,
nuclear@9 70 VDP_STAT_SPRITE_OVF = 0x0040,
nuclear@9 71 VDP_STAT_VINTR = 0x0080,
nuclear@9 72 VDP_STAT_FIFO_FULL = 0x0100,
nuclear@9 73 VDP_STAT_FIFO_EMPTY = 0x0200
nuclear@9 74 };
nuclear@9 75
nuclear@9 76
nuclear@0 77 static inline void vdp_setup_access(uint16_t addr, int rw, int memid)
nuclear@0 78 {
nuclear@0 79 uint32_t type;
nuclear@0 80 if(rw == VDP_MEM_WRITE) {
nuclear@0 81 type = (memid & 7) | 1;
nuclear@0 82 } else {
nuclear@0 83 type = memid & 0xc;
nuclear@0 84 }
nuclear@0 85
nuclear@0 86 VDP_PORT_CTL32 = (((uint32_t)addr & 0x3fff) << 16) | ((addr >> 14) & 3) |
nuclear@0 87 ((type << 2) & 0xf0) | (type << 30);
nuclear@0 88 }
nuclear@0 89
nuclear@0 90
nuclear@0 91 /* mode register 1 */
nuclear@0 92 enum {
nuclear@0 93 VDP_MODE1_BASE = 0x4,
nuclear@0 94 VDP_MODE1_HVCNT = 0x2,
nuclear@0 95 VDP_MODE1_HINTR = 0x10
nuclear@0 96 };
nuclear@0 97
nuclear@0 98 /* mode register 2 */
nuclear@0 99 enum {
nuclear@0 100 VDP_MODE2_BASE = 0x4,
nuclear@0 101 VDP_MODE2_V30CELL = 0x8,
nuclear@0 102 VDP_MODE2_DMA = 0x10,
nuclear@0 103 VDP_MODE2_VINTR = 0x20,
nuclear@0 104 VDP_MODE2_DISP = 0x40
nuclear@0 105 };
nuclear@0 106
nuclear@0 107 /* mode register 3 */
nuclear@0 108 enum {
nuclear@0 109 VDP_MODE3_BASE = 0,
nuclear@0 110 VDP_MODE3_HSCROLL_CELL = 2,
nuclear@0 111 VDP_MODE3_HSCROLL_LINE = 3,
nuclear@0 112 VDP_MODE3_VSCROLL_2CELL = 4,
nuclear@0 113 VDP_MODE3_EXTINTR = 8
nuclear@0 114 };
nuclear@0 115
nuclear@0 116 /* mode register 4 */
nuclear@0 117 enum {
nuclear@0 118 VDP_MODE4_BASE = 0,
nuclear@0 119 VDP_MODE4_H40CELL = 0x81,
nuclear@0 120 VDP_MODE4_ILACE = 2,
nuclear@0 121 VDP_MODE4_ILACE_2XRES = 6,
nuclear@0 122 VDP_MODE4_SH = 8 /* shadow/highlight enable */
nuclear@0 123 };
nuclear@0 124
nuclear@0 125 /* scroll size register */
nuclear@0 126 enum {
nuclear@0 127 VDP_SCROLL_H32 = 0,
nuclear@0 128 VDP_SCROLL_H64 = 1,
nuclear@0 129 VDP_SCROLL_H128 = 3,
nuclear@0 130 VDP_SCROLL_V32 = 0,
nuclear@0 131 VDP_SCROLL_V64 = 0x10,
nuclear@0 132 VDP_SCROLL_V128 = 0x30
nuclear@0 133 };
nuclear@0 134
nuclear@0 135 /* window X/Y position register */
nuclear@0 136 enum {
nuclear@0 137 VDP_WIN_LEFT = 0,
nuclear@0 138 VDP_WIN_UP = 0,
nuclear@0 139 VDP_WIN_RIGHT = 0x80,
nuclear@0 140 VDP_WIN_DOWN = 0x80,
nuclear@0 141 VDP_WIN_POSMASK = 0x1f
nuclear@0 142 };
nuclear@0 143
nuclear@0 144 #define VDP_PACK_RGB(r, g, b) \
nuclear@0 145 ((((uint16_t)(r) & 7) << 1) | (((uint16_t)(g) & 7) << 5) | (((uint16_t)(b) & 7) << 9))
nuclear@0 146
nuclear@0 147
nuclear@0 148 static inline void vdp_setreg(int reg, uint8_t value)
nuclear@0 149 {
nuclear@1 150 vdp_reg_shadow[reg] = value;
nuclear@0 151 VDP_PORT_CTL = (uint16_t)value | (reg << 8) | (uint16_t)0x8000;
nuclear@0 152 }
nuclear@0 153
nuclear@0 154 static inline uint16_t vdp_getreg(int reg)
nuclear@0 155 {
nuclear@0 156 return vdp_reg_shadow[reg];
nuclear@0 157 }
nuclear@0 158
nuclear@0 159 static inline uint16_t vdp_status(void)
nuclear@0 160 {
nuclear@0 161 return VDP_PORT_CTL;
nuclear@0 162 }
nuclear@0 163
nuclear@0 164 static inline void vdp_set_bgcolor(int palidx, int colidx)
nuclear@0 165 {
nuclear@0 166 vdp_setreg(VDP_REG_BGCOL, (colidx & 0xf) | (palidx << 4));
nuclear@0 167 }
nuclear@0 168
nuclear@0 169 static inline void vdp_set_autoinc(int stride)
nuclear@0 170 {
nuclear@0 171 vdp_setreg(VDP_REG_AUTOINC, stride);
nuclear@0 172 }
nuclear@0 173
nuclear@5 174 static inline void vdp_begin_palette(int pidx, int cidx)
nuclear@5 175 {
nuclear@5 176 uint16_t paddr = (pidx << 5) | (cidx << 1);
nuclear@5 177 vdp_setup_access(paddr, VDP_MEM_WRITE, VDP_MEM_CRAM);
nuclear@5 178 }
nuclear@5 179
nuclear@0 180 static inline void vdp_set_pal_entry(int pidx, int cidx, int r, int g, int b)
nuclear@0 181 {
nuclear@5 182 vdp_begin_palette(pidx, cidx);
nuclear@0 183 VDP_PORT_DATA = VDP_PACK_RGB(r, g, b);
nuclear@0 184 }
nuclear@0 185
nuclear@1 186 static inline void vdp_enable_vintr(void)
nuclear@1 187 {
nuclear@1 188 vdp_setreg(VDP_REG_MODE2, vdp_getreg(VDP_REG_MODE2) | VDP_MODE2_VINTR);
nuclear@1 189 }
nuclear@1 190
nuclear@1 191 static inline void vdp_disable_vintr(void)
nuclear@1 192 {
nuclear@1 193 vdp_setreg(VDP_REG_MODE2, vdp_getreg(VDP_REG_MODE2) & ~VDP_MODE2_VINTR);
nuclear@1 194 }
nuclear@1 195
nuclear@1 196 static inline void vdp_enable_hintr(int counter)
nuclear@1 197 {
nuclear@1 198 vdp_setreg(VDP_REG_HINTR, counter);
nuclear@1 199 vdp_setreg(VDP_REG_MODE1, vdp_getreg(VDP_REG_MODE1) | VDP_MODE1_HINTR);
nuclear@1 200 }
nuclear@1 201
nuclear@1 202 static inline void vdp_disable_hintr(void)
nuclear@1 203 {
nuclear@1 204 vdp_setreg(VDP_REG_MODE1, vdp_getreg(VDP_REG_MODE1) & ~VDP_MODE1_HINTR);
nuclear@1 205 }
nuclear@1 206
nuclear@4 207 static inline void vdp_set_nametab_addr(int plane, uint16_t addr)
nuclear@4 208 {
nuclear@4 209 switch(plane) {
nuclear@4 210 case VDP_PLANE_A:
nuclear@5 211 vdp_setreg(VDP_REG_NAMETAB_A, (addr >> 10) & 0x38);
nuclear@4 212 break;
nuclear@4 213 case VDP_PLANE_B:
nuclear@5 214 vdp_setreg(VDP_REG_NAMETAB_B, (addr >> 13) & 7);
nuclear@4 215 break;
nuclear@4 216 case VDP_PLANE_WIN:
nuclear@5 217 vdp_setreg(VDP_REG_NAMETAB_WIN, (addr >> 10) & 0x7e);
nuclear@5 218 default:
nuclear@4 219 break;
nuclear@4 220 }
nuclear@4 221 }
nuclear@4 222
nuclear@4 223 static inline uint16_t vdp_nametab_addr(int idx)
nuclear@4 224 {
nuclear@4 225 return (uint16_t)idx << 13;
nuclear@4 226 }
nuclear@4 227
nuclear@4 228 static inline void vdp_set_nametab_idx(int plane, int idx)
nuclear@4 229 {
nuclear@4 230 vdp_set_nametab_addr(plane, vdp_nametab_addr(idx));
nuclear@4 231 }
nuclear@4 232
nuclear@5 233 static inline void vdp_disable_layer(int plane)
nuclear@5 234 {
nuclear@5 235 switch(plane) {
nuclear@5 236 case VDP_PLANE_A:
nuclear@5 237 vdp_setreg(VDP_REG_NAMETAB_A, 0x40);
nuclear@5 238 break;
nuclear@5 239 case VDP_PLANE_B:
nuclear@5 240 vdp_setreg(VDP_REG_NAMETAB_B, 0x08);
nuclear@5 241 break;
nuclear@5 242 case VDP_PLANE_WIN:
nuclear@5 243 vdp_setreg(VDP_REG_NAMETAB_WIN, 0x40);
nuclear@5 244 default:
nuclear@5 245 break;
nuclear@5 246 }
nuclear@5 247 }
nuclear@5 248
nuclear@4 249 static inline uint16_t vdp_nametab_entry(int tileidx, int palidx, uint16_t flags)
nuclear@4 250 {
nuclear@4 251 return tileidx | (((uint16_t)palidx & 0x3) << 13) | flags;
nuclear@4 252 }
nuclear@4 253
nuclear@5 254 static inline void vdp_set_sprite_table(uint16_t addr)
nuclear@5 255 {
nuclear@5 256 vdp_setreg(VDP_REG_SPRITE_TAB, addr >> 9);
nuclear@5 257 }
nuclear@5 258
nuclear@5 259 static inline void vdp_set_scroll_table(uint16_t addr)
nuclear@5 260 {
nuclear@5 261 vdp_setreg(VDP_REG_SCROLL_TAB, addr >> 10);
nuclear@5 262 }
nuclear@5 263
nuclear@9 264 static inline void vdp_wait_vblank_start(void)
nuclear@9 265 {
nuclear@9 266 while(!(VDP_PORT_STATUS & VDP_STAT_VBLANK));
nuclear@9 267 }
nuclear@9 268
nuclear@9 269 static inline void vdp_wait_vblank_end(void)
nuclear@9 270 {
nuclear@9 271 while(VDP_PORT_STATUS & VDP_STAT_VBLANK);
nuclear@9 272 }
nuclear@9 273
nuclear@8 274 static inline void vdp_wait_vblank(void)
nuclear@8 275 {
nuclear@9 276 vdp_wait_vblank_start();
nuclear@9 277 vdp_wait_vblank_end();
nuclear@8 278 }
nuclear@8 279
nuclear@0 280 void vdp_init(void);
nuclear@0 281
nuclear@0 282 #endif /* VDP_H_ */