diff --git a/Makefile b/Makefile index fe7d593..ff1f0a6 100644 --- a/Makefile +++ b/Makefile @@ -7,11 +7,26 @@ all: raytracing.iso vdp2.iso LIB = ./saturn include $(LIB)/common.mk +define BUILD_BINARY_O + $(OBJCOPY) \ + -I binary -O elf32-sh -B sh2 \ + --rename-section .data=.data.$(basename $@) \ + $< $@ +endef + +%.data.o: %.data + $(BUILD_BINARY_O) + +%.data.pal.o: %.data.pal + $(BUILD_BINARY_O) + sh/lib1funcs.o: CFLAGS += -DL_ashiftrt -DL_movmem raytracing/raytracing.elf: CFLAGS += -Imath -DUSE_SH2_DVSR raytracing/raytracing.elf: raytracing/main-saturn.o raytracing/raytracing.o sh/lib1funcs.o +vdp2/vdp2.elf: vdp2/vdp2.o res/butterfly.data.o res/butterfly.data.pal.o + # clean clean: clean-sh clean-sh: diff --git a/res/butterfly.data b/res/butterfly.data new file mode 100644 index 0000000..33c2306 Binary files /dev/null and b/res/butterfly.data differ diff --git a/res/butterfly.data.pal b/res/butterfly.data.pal new file mode 100644 index 0000000..88fc184 Binary files /dev/null and b/res/butterfly.data.pal differ diff --git a/res/butterfly.txt b/res/butterfly.txt new file mode 100644 index 0000000..d86f997 --- /dev/null +++ b/res/butterfly.txt @@ -0,0 +1,2 @@ +data: 64x64 px, palettized, 1 byte per pixel +data.pal: 3 bytes per color, rgb24, red at index 0 diff --git a/vdp2/nbg0.cpp b/vdp2/nbg0.cpp new file mode 100644 index 0000000..2f2e2be --- /dev/null +++ b/vdp2/nbg0.cpp @@ -0,0 +1,161 @@ +/* + color data + + 255 colors, 3 bytes per channel, packed +*/ +/* + image data + + 64*64 px, 1 byte per palette index +*/ + +#include +#include + +extern void * _butterfly_data_pal_start __asm("_binary_res_butterfly_data_pal_start"); +extern void * _butterfly_data_pal_size __asm("_binary_res_butterfly_data_pal_size"); + +extern void * _butterfly_data_start __asm("_binary_res_butterfly_data_start"); +extern void * _butterfly_data_size __asm("_binary_res_butterfly_data_size"); + +inline constexpr uint16_t rgb15(const uint8_t * buf) +{ + return ((buf[2] >> 3) << 10) + | ((buf[1] >> 3) << 5) + | ((buf[0] >> 3) << 0); +} + +void palette_data() +{ + const uint32_t buf_size = reinterpret_cast(&_butterfly_data_pal_size); + const uint8_t * buf = reinterpret_cast(&_butterfly_data_pal_start); + uint32_t buf_ix = 0; + + for (uint32_t i = 0; i < (buf_size / 3); i++) { + vdp2.cram.u16[i] = rgb15(&buf[buf_ix]); + buf_ix += 3; + } +} + +void cell_data() +{ + constexpr int page_width = 64; + constexpr int pixel_width = 64; + + const uint8_t * buf = reinterpret_cast(&_butterfly_data_start); + + for (int j = 0; j < 8; j++) { + for (int i = 0; i < 8; i++) { + for (int y = 0; y < 8; y++) { + for (int x = 0; x < 8; x++) { + vdp2.vram.u16[(page_width * ((j * 8) + i)) + (y * 8 + x)] = + buf[(y + (j * 8)) * pixel_width + (x + (8 * i))]; + } + } + } + } +} + +template +void fill(T * buf, T v, int32_t n) noexcept +{ + while (n > 0) { + *buf++ = v; + n -= (sizeof (T)); + } +} + +void main() +{ + // 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__CRMD__RGB_5BIT_1024; + + /* enable display of NBG0 */ + vdp2.reg.BGON = BGON__N0ON; + + /* set character format for NBG0 to palettized 2048 color + set bitmap size for NBG0 to 512x256 + set character size for NBG0 to 1x1 cell */ + vdp2.reg.CHCTLA = CHCTLA__N0CHCN__2048_COLOR + | CHCTLA__N0BMEN__CELL_FORMAT + | CHCTLA__N0CHSZ__1x1_CELL; + /* "Note: In color RAM modes 0 and 2, 2048-color becomes 1024-color" */ + + /* use 2-word (16-bit) pattern names */ + vdp2.reg.PNCN0 = PNCN0__N0PNB__1WORD; + + /* 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 = 2; + 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.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 + + constexpr int cell_size = (8 * 8) * 2; // N0CHCN__2048_COLOR (16-bit) + constexpr int character_size = cell_size * (1 * 1); // N0CHSZ__1x1_CELL + constexpr int character_offset = character_size / 0x20; + + // zeroize character/cell data from 0 up to plane_a_offset + fill(&vdp2.vram.u32[(0 / 2)], 0, plane_a_offset); + + /* + set plane_a character index data to this (hex): + + | + 00 01 02 03 04 05 06 07 40 40 .. + 08 09 0a 0b 0c 0d 0e 0f 40 40 .. + 10 11 12 13 14 15 16 17 40 40 .. + 18 19 1a 1b 1c 1d 1e 1f 40 40 .. + 20 21 22 23 24 25 26 27 40 40 .. + 28 29 2a 2b 2c 2d 2e 2f 40 40 .. + 30 31 32 33 34 35 36 37 40 40 .. + -- 38 39 3a 3b 3c 3d 3e 3f 40 40 .. + 40 40 40 40 40 40 40 40 40 40 .. + 40 40 40 40 40 40 40 40 40 40 .. + .. .. .. .. .. .. .. .. .. .. .. + + (the above numbers are not pre-multiplied by character_offset) + */ + // "zeroize" plane_a to the 0x40th (64th) character index (an unused/transparent character) + // this creates the '40' indexes in the above picture + fill(&vdp2.vram.u16[(plane_a_offset / 2)], character_offset * 0x40, plane_size); + + constexpr int pixel_width = 64; + constexpr int pixel_height = 64; + constexpr int cell_horizontal = pixel_width / 8; + constexpr int cell_vertical = pixel_height / 8; + + constexpr int page_width = 64; + + for (int y = 0; y < cell_vertical; y++) { + for (int x = 0; x < cell_horizontal; x++) { + vdp2.vram.u16[(plane_a_offset / 2) + (y * page_width) + x] + = character_offset * ((y * cell_horizontal) + x); + } + } + + palette_data(); + cell_data(); +} + +extern "C" +void start(void) +{ + main(); + while (1) {} +}