#include #include "vdp2.h" #include "common/copy.hpp" #include "common/vdp2_func.hpp" #include "test.cpp" constexpr inline uint16_t rgb15(int32_t r, int32_t g, int32_t b) { return ((b & 31) << 10) | ((g & 31) << 5) | ((r & 31) << 0); } void palette_data() { vdp2.cram.u16[0] = rgb15( 0, 0, 0); vdp2.cram.u16[1] = rgb15(10, 10, 10); vdp2.cram.u16[2] = rgb15(21, 21, 21); vdp2.cram.u16[3] = rgb15(31, 31, 31); } uint32_t cell_data(const start_size_t& buf, const uint32_t top) { // round to nearest multiple of 32 const uint32_t table_size = ((buf.size * 2) + 0x20 - 1) & (-0x20); const uint32_t base_address = top - table_size; // in bytes uint32_t * vram = &vdp2.vram.u32[(base_address / 4)]; for (uint32_t ix = 0; ix < buf.size / 4; ix += 1) { const uint32_t pixels = reinterpret_cast(buf.start)[ix]; const uint32_t px0 = pixels >> 16 & 0xffff; const uint32_t px1 = pixels >> 0 & 0xffff; #define lshift(n) ((7 - n) * 2) #define rshift(n) ((7 - n) * 4) #define px(p, n) (((p >> lshift(n)) & 0b11) << rshift(n)) #define p0(n) (px(px0, n)) #define p1(n) (px(px1, n)) vram[ix * 2 + 0] = p0(7) | p0(6) | p0(5) | p0(4) | p0(3) | p0(2) | p0(1) | p0(0); vram[ix * 2 + 1] = p1(7) | p1(6) | p1(5) | p1(4) | p1(3) | p1(2) | p1(1) | p1(0); #undef p1 #undef p0 #undef px #undef lshift #undef rshift } return base_address; } constexpr inline void render_block(const uint32_t base_pattern, const tileset_t& tileset, const uint32_t map_x, const uint32_t map_y, const uint8_t block) { for (uint32_t block_y = 0; block_y < 4; block_y++) { for (uint32_t block_x = 0; block_x < 4; block_x++) { const uint32_t block_ix = 4 * block_y + block_x; const uint8_t tile_xy = tileset.blockset.start[block * 4 * 4 + block_ix]; const uint8_t tile_x = (tile_xy >> 0) & 0xf; const uint8_t tile_y = (tile_xy >> 4) & 0xf; const uint32_t tile_ix = tile_y * 16 + tile_x; const uint32_t cell_y = map_y * 4 + block_y; const uint32_t cell_x = map_x * 4 + block_x; vdp2.vram.u16[64 * cell_y + cell_x] = (base_pattern & 0xfff) + tile_ix; //vdp2.vram.u32[64 * cell_y + cell_x] = base_pattern + tile_ix; } } } void render(const uint32_t base_pattern) { const map_t& map = maps[map_t::pallet_town]; for (uint32_t map_y = 0; map_y < map.height; map_y++) { for (uint32_t map_x = 0; map_x < map.width; map_x++) { const uint8_t block = map.blocks.start[map.width * map_y + map_x]; render_block(base_pattern, tilesets[map.tileset], map_x, map_y, block); } } } void main() { v_blank_in(); // DISP: Please make sure to change this bit from 0 to 1 during V blank. vdp2.reg.TVMD = ( TVMD__DISP | TVMD__LSMD__NON_INTERLACE | TVMD__VRESO__240 | TVMD__HRESO__NORMAL_320); /* set the color mode to 5bits per channel, 1024 colors */ vdp2.reg.RAMCTL = RAMCTL__CRKTE | RAMCTL__CRMD__RGB_5BIT_1024 | RAMCTL__VRAMD | RAMCTL__VRBMD; /* enable display of NBG0 */ vdp2.reg.BGON = BGON__N0ON; /* set character format for NBG0 to palettized 16 color set enable "cell format" for NBG0 set character size for NBG0 to 1x1 cell */ vdp2.reg.CHCTLA = CHCTLA__N0CHCN__16_COLOR | CHCTLA__N0BMEN__CELL_FORMAT | CHCTLA__N0CHSZ__1x1_CELL; /* plane size */ vdp2.reg.PLSZ = PLSZ__N0PLSZ__1x1; /* map plane offset 1-word: value of bit 6-0 * 0x2000 2-word: value of bit 5-0 * 0x4000 */ constexpr int plane_a = 0; constexpr int plane_a_offset = plane_a * 0x2000; constexpr int page_size = 64 * 64 * 2; // N0PNB__1WORD (16-bit) constexpr int plane_size = page_size * 1; vdp2.reg.CYCA0 = 0xeeeeeeee; vdp2.reg.CYCA1 = 0xeeeeeeee; vdp2.reg.CYCB0 = 0xeeeeeeee; vdp2.reg.CYCB1 = 0xeeeeeeee; vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6 vdp2.reg.MPABN0 = MPABN0__N0MPB(0) | MPABN0__N0MPA(plane_a); // bits 5~0 vdp2.reg.MPCDN0 = MPABN0__N0MPD(0) | MPABN0__N0MPC(0); // bits 5~0 uint32_t top = (sizeof (union vdp2_vram)); palette_data(); uint32_t base_address = top = cell_data(tilesets[tileset_t::overworld].tileset, top); uint32_t base_pattern = base_address / 32; /* use 1-word (16-bit) pattern names */ vdp2.reg.PNCN0 = PNCN0__N0PNB__1WORD | PNCN0__N0CNSM | PNCN0__N0SCN((base_pattern >> 10) & 0x1f); //vdp2.reg.PNCN0 = PNCN0__N0PNB__2WORD | PNCN0__N0CNSM; render(base_pattern); vdp2.reg.CYCA0 = 0x0fff'ffff; vdp2.reg.CYCA1 = 0xffff'ffff; vdp2.reg.CYCB0 = 0xffff'ffff; vdp2.reg.CYCB1 = 0x4fff'ffff; }