nuclear@0: #ifndef VDP_H_ nuclear@0: #define VDP_H_ nuclear@0: nuclear@0: #include nuclear@0: nuclear@0: #define VDP_PORT_DATA *((volatile uint16_t*)0xc00000) nuclear@0: #define VDP_PORT_DATA32 *((volatile uint32_t*)0xc00000) nuclear@0: #define VDP_PORT_CTL *((volatile uint16_t*)0xc00004) nuclear@0: #define VDP_PORT_CTL32 *((volatile uint32_t*)0xc00004) nuclear@0: #define VDP_PORT_HVCNT *((volatile uint16_t*)0xc00008) nuclear@0: #define VDP_PORT_PSG *((volatile uint16_t*)0xc00010) nuclear@0: nuclear@0: #define VDP_PORT_STATUS *((volatile uint16_t*)0xc00004) nuclear@0: nuclear@0: enum { nuclear@0: VDP_REG_MODE1 = 0, nuclear@0: VDP_REG_MODE2 = 1, nuclear@0: VDP_REG_NAMETAB_A = 2, nuclear@0: VDP_REG_NAMETAB_WIN = 3, nuclear@0: VDP_REG_NAMETAB_B = 4, nuclear@0: VDP_REG_SPRITE_TAB = 5, nuclear@0: VDP_REG_BGCOL = 7, nuclear@1: VDP_REG_HINTR = 10, nuclear@0: VDP_REG_MODE3 = 11, nuclear@0: VDP_REG_MODE4 = 12, nuclear@0: VDP_REG_SCROLL_TAB = 13, nuclear@0: VDP_REG_AUTOINC = 15, nuclear@0: VDP_REG_SCROLL_SIZE = 16, nuclear@0: VDP_REG_WIN_XPOS = 17, nuclear@0: VDP_REG_WIN_YPOS = 18, nuclear@0: VDP_REG_DMA_LEN_LOW = 19, nuclear@0: VDP_REG_DMA_LEN_HIGH = 20, nuclear@0: VDP_REG_DMA_SRC_LOW = 21, nuclear@0: VDP_REG_DMA_SRC_MID = 22, nuclear@0: VDP_REG_DMA_SRC_HIGH = 23, nuclear@0: nuclear@0: VDP_NUM_REGS nuclear@0: }; nuclear@0: nuclear@0: uint16_t vdp_reg_shadow[VDP_NUM_REGS]; nuclear@0: nuclear@0: /* access VDP memory */ nuclear@0: enum { VDP_MEM_READ, VDP_MEM_WRITE }; nuclear@0: enum { nuclear@0: VDP_MEM_VRAM = 0, nuclear@0: VDP_MEM_CRAM = 0xa, /* CD5->CD0: 0 0 r 0 w 0 */ nuclear@0: VDP_MEM_VSRAM = 4 /* CD5->CD0: 0 0 0 1 0 0 */ nuclear@0: }; nuclear@0: nuclear@0: static inline void vdp_setup_access(uint16_t addr, int rw, int memid) nuclear@0: { nuclear@0: uint32_t type; nuclear@0: if(rw == VDP_MEM_WRITE) { nuclear@0: type = (memid & 7) | 1; nuclear@0: } else { nuclear@0: type = memid & 0xc; nuclear@0: } nuclear@0: nuclear@0: VDP_PORT_CTL32 = (((uint32_t)addr & 0x3fff) << 16) | ((addr >> 14) & 3) | nuclear@0: ((type << 2) & 0xf0) | (type << 30); nuclear@0: } nuclear@0: nuclear@0: nuclear@0: /* mode register 1 */ nuclear@0: enum { nuclear@0: VDP_MODE1_BASE = 0x4, nuclear@0: VDP_MODE1_HVCNT = 0x2, nuclear@0: VDP_MODE1_HINTR = 0x10 nuclear@0: }; nuclear@0: nuclear@0: /* mode register 2 */ nuclear@0: enum { nuclear@0: VDP_MODE2_BASE = 0x4, nuclear@0: VDP_MODE2_V30CELL = 0x8, nuclear@0: VDP_MODE2_DMA = 0x10, nuclear@0: VDP_MODE2_VINTR = 0x20, nuclear@0: VDP_MODE2_DISP = 0x40 nuclear@0: }; nuclear@0: nuclear@0: /* mode register 3 */ nuclear@0: enum { nuclear@0: VDP_MODE3_BASE = 0, nuclear@0: VDP_MODE3_HSCROLL_CELL = 2, nuclear@0: VDP_MODE3_HSCROLL_LINE = 3, nuclear@0: VDP_MODE3_VSCROLL_2CELL = 4, nuclear@0: VDP_MODE3_EXTINTR = 8 nuclear@0: }; nuclear@0: nuclear@0: /* mode register 4 */ nuclear@0: enum { nuclear@0: VDP_MODE4_BASE = 0, nuclear@0: VDP_MODE4_H40CELL = 0x81, nuclear@0: VDP_MODE4_ILACE = 2, nuclear@0: VDP_MODE4_ILACE_2XRES = 6, nuclear@0: VDP_MODE4_SH = 8 /* shadow/highlight enable */ nuclear@0: }; nuclear@0: nuclear@0: /* scroll size register */ nuclear@0: enum { nuclear@0: VDP_SCROLL_H32 = 0, nuclear@0: VDP_SCROLL_H64 = 1, nuclear@0: VDP_SCROLL_H128 = 3, nuclear@0: VDP_SCROLL_V32 = 0, nuclear@0: VDP_SCROLL_V64 = 0x10, nuclear@0: VDP_SCROLL_V128 = 0x30 nuclear@0: }; nuclear@0: nuclear@0: /* window X/Y position register */ nuclear@0: enum { nuclear@0: VDP_WIN_LEFT = 0, nuclear@0: VDP_WIN_UP = 0, nuclear@0: VDP_WIN_RIGHT = 0x80, nuclear@0: VDP_WIN_DOWN = 0x80, nuclear@0: VDP_WIN_POSMASK = 0x1f nuclear@0: }; nuclear@0: nuclear@0: #define VDP_PACK_RGB(r, g, b) \ nuclear@0: ((((uint16_t)(r) & 7) << 1) | (((uint16_t)(g) & 7) << 5) | (((uint16_t)(b) & 7) << 9)) nuclear@0: nuclear@0: nuclear@0: static inline void vdp_setreg(int reg, uint8_t value) nuclear@0: { nuclear@1: vdp_reg_shadow[reg] = value; nuclear@0: VDP_PORT_CTL = (uint16_t)value | (reg << 8) | (uint16_t)0x8000; nuclear@0: } nuclear@0: nuclear@0: static inline uint16_t vdp_getreg(int reg) nuclear@0: { nuclear@0: return vdp_reg_shadow[reg]; nuclear@0: } nuclear@0: nuclear@0: static inline uint16_t vdp_status(void) nuclear@0: { nuclear@0: return VDP_PORT_CTL; nuclear@0: } nuclear@0: nuclear@0: static inline void vdp_set_bgcolor(int palidx, int colidx) nuclear@0: { nuclear@0: vdp_setreg(VDP_REG_BGCOL, (colidx & 0xf) | (palidx << 4)); nuclear@0: } nuclear@0: nuclear@0: static inline void vdp_set_autoinc(int stride) nuclear@0: { nuclear@0: vdp_setreg(VDP_REG_AUTOINC, stride); nuclear@0: } nuclear@0: nuclear@0: static inline void vdp_set_pal_entry(int pidx, int cidx, int r, int g, int b) nuclear@0: { nuclear@0: uint16_t paddr = (pidx << 5) | (cidx << 1); nuclear@0: nuclear@0: vdp_setup_access(paddr, VDP_MEM_WRITE, VDP_MEM_CRAM); nuclear@0: VDP_PORT_DATA = VDP_PACK_RGB(r, g, b); nuclear@0: } nuclear@0: nuclear@1: static inline void vdp_enable_vintr(void) nuclear@1: { nuclear@1: vdp_setreg(VDP_REG_MODE2, vdp_getreg(VDP_REG_MODE2) | VDP_MODE2_VINTR); nuclear@1: } nuclear@1: nuclear@1: static inline void vdp_disable_vintr(void) nuclear@1: { nuclear@1: vdp_setreg(VDP_REG_MODE2, vdp_getreg(VDP_REG_MODE2) & ~VDP_MODE2_VINTR); nuclear@1: } nuclear@1: nuclear@1: static inline void vdp_enable_hintr(int counter) nuclear@1: { nuclear@1: vdp_setreg(VDP_REG_HINTR, counter); nuclear@1: vdp_setreg(VDP_REG_MODE1, vdp_getreg(VDP_REG_MODE1) | VDP_MODE1_HINTR); nuclear@1: } nuclear@1: nuclear@1: static inline void vdp_disable_hintr(void) nuclear@1: { nuclear@1: vdp_setreg(VDP_REG_MODE1, vdp_getreg(VDP_REG_MODE1) & ~VDP_MODE1_HINTR); nuclear@1: } nuclear@1: nuclear@0: void vdp_init(void); nuclear@0: nuclear@0: #endif /* VDP_H_ */