megadrive_test2

annotate src/vdp.h @ 4:72ab63f262bf

tiles
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 19 Jun 2017 08:02:51 +0300
parents 2560a8be8cb8
children ea70f3da150f
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@0 160 static inline void vdp_set_pal_entry(int pidx, int cidx, int r, int g, int b)
nuclear@0 161 {
nuclear@0 162 uint16_t paddr = (pidx << 5) | (cidx << 1);
nuclear@0 163
nuclear@0 164 vdp_setup_access(paddr, VDP_MEM_WRITE, VDP_MEM_CRAM);
nuclear@0 165 VDP_PORT_DATA = VDP_PACK_RGB(r, g, b);
nuclear@0 166 }
nuclear@0 167
nuclear@1 168 static inline void vdp_enable_vintr(void)
nuclear@1 169 {
nuclear@1 170 vdp_setreg(VDP_REG_MODE2, vdp_getreg(VDP_REG_MODE2) | VDP_MODE2_VINTR);
nuclear@1 171 }
nuclear@1 172
nuclear@1 173 static inline void vdp_disable_vintr(void)
nuclear@1 174 {
nuclear@1 175 vdp_setreg(VDP_REG_MODE2, vdp_getreg(VDP_REG_MODE2) & ~VDP_MODE2_VINTR);
nuclear@1 176 }
nuclear@1 177
nuclear@1 178 static inline void vdp_enable_hintr(int counter)
nuclear@1 179 {
nuclear@1 180 vdp_setreg(VDP_REG_HINTR, counter);
nuclear@1 181 vdp_setreg(VDP_REG_MODE1, vdp_getreg(VDP_REG_MODE1) | VDP_MODE1_HINTR);
nuclear@1 182 }
nuclear@1 183
nuclear@1 184 static inline void vdp_disable_hintr(void)
nuclear@1 185 {
nuclear@1 186 vdp_setreg(VDP_REG_MODE1, vdp_getreg(VDP_REG_MODE1) & ~VDP_MODE1_HINTR);
nuclear@1 187 }
nuclear@1 188
nuclear@4 189 static inline void vdp_set_nametab_addr(int plane, uint16_t addr)
nuclear@4 190 {
nuclear@4 191 int reg;
nuclear@4 192 switch(plane) {
nuclear@4 193 case VDP_PLANE_A:
nuclear@4 194 reg = VDP_REG_NAMETAB_A;
nuclear@4 195 break;
nuclear@4 196 case VDP_PLANE_B:
nuclear@4 197 reg = VDP_REG_NAMETAB_B;
nuclear@4 198 break;
nuclear@4 199 case VDP_PLANE_WIN:
nuclear@4 200 reg = VDP_REG_NAMETAB_WIN;
nuclear@4 201 break;
nuclear@4 202 default:
nuclear@4 203 return;
nuclear@4 204 }
nuclear@4 205
nuclear@4 206 vdp_setreg(reg, (addr >> 10) & 0x38);
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@4 219 static inline uint16_t vdp_nametab_entry(int tileidx, int palidx, uint16_t flags)
nuclear@4 220 {
nuclear@4 221 return tileidx | (((uint16_t)palidx & 0x3) << 13) | flags;
nuclear@4 222 }
nuclear@4 223
nuclear@0 224 void vdp_init(void);
nuclear@0 225
nuclear@0 226 #endif /* VDP_H_ */