From 1f9bf2d1a0457fe5f7ad0f0539563ca995d90aad Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Fri, 27 Jan 2023 00:06:34 -0800 Subject: [PATCH] add vdp2/nbg0 example --- Makefile | 15 ++++ res/butterfly.data | Bin 0 -> 4096 bytes res/butterfly.data.pal | Bin 0 -> 765 bytes res/butterfly.txt | 2 + vdp2/nbg0.cpp | 161 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 178 insertions(+) create mode 100644 res/butterfly.data create mode 100644 res/butterfly.data.pal create mode 100644 res/butterfly.txt create mode 100644 vdp2/nbg0.cpp 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 0000000000000000000000000000000000000000..33c230664866994b815fc700edf81098da5e83ac GIT binary patch literal 4096 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 literal 0 HcmV?d00001 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) {} +}