From 1a2bd8b70c12d497acb2eba548d161b2bfc4f9b6 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Fri, 24 Feb 2023 22:24:50 +0100 Subject: background sprites working in ppusim --- docs/architecture.md | 4 +-- src/main.c | 88 +++++++++++++++++++++++++++++++++++++++++++--------- src/ppu/internals.c | 17 +++------- src/ppu/internals.h | 5 +++ src/ppusim/pixel.c | 45 ++++++++++++++++++++++++++- 5 files changed, 129 insertions(+), 30 deletions(-) diff --git a/docs/architecture.md b/docs/architecture.md index 0c6fea7..5001eed 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -323,8 +323,8 @@ Word format: |Range (VHDL)|Description| |-|-| -|`15 downto 13`|(discarded)| -|`12 downto 8`|Red value| +|`15 downto 12`|(discarded)| +|`11 downto 8`|Red value| |`7 downto 4`|Green value| |`3 downto 0`|Blue value| diff --git a/src/main.c b/src/main.c index 8cb0450..b61f124 100644 --- a/src/main.c +++ b/src/main.c @@ -24,36 +24,94 @@ void hh_ppu_vblank_interrupt() { #ifdef HH_TARGET_DESKTOP // printf("frame %lu\n", frame); #endif -} - -void hh_setup() { - hh_ppu_init(); + unsigned shift = (double) sin((double) frame / 20) * 10 + 10; hh_ppu_update_aux((hh_s_ppu_loc_aux) { - .bg_shift_x = 24, + .bg_shift_x = shift, .bg_shift_y = 0, - .fg_fetch = 1, - .sysreset = 1, + .fg_fetch = 0, + .sysreset = 0, }); +} - hh_s_ppu_loc_sprite sprite = {0}; +void hh_setup() { + hh_ppu_init(); + + hh_s_ppu_loc_sprite sprite = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 + }; - for (int x = 0; x < HH_PPU_SPRITE_WIDTH; x++) - for (int y = 0; y < HH_PPU_SPRITE_HEIGHT; y++) - sprite[y * HH_PPU_SPRITE_WIDTH + x] = (pow(x - 8, 2) + pow(y - 8, 2) < 67) ? 1 : 0; + for (int x = 0; x < HH_PPU_SPRITE_WIDTH; x++) { + for (int y = 0; y < HH_PPU_SPRITE_HEIGHT; y++) { + // sprite[y * HH_PPU_SPRITE_WIDTH + x] = (pow(x - 8, 2) + pow(y - 8, 2) < 64) ? 1 : 0; + uint8_t p = sprite[y * HH_PPU_SPRITE_WIDTH + x]; + printf("%c%c%c", p ? 'X' : ' ', p ? 'X' : ' ', p ? 'X' : ' '); + } + printf("\n"); + } hh_ppu_update_sprite(0, sprite); - hh_ppu_update_foreground(0, (hh_s_ppu_loc_fam_entry) { + // hh_ppu_update_foreground(0, (hh_s_ppu_loc_fam_entry) { + // .horizontal_flip = false, + // .vertical_flip = false, + // .palette_index = 1, + // .tilemap_index = 0, + // .position_x = 30, + // .position_y = 40, + // }); + + hh_ppu_update_background(3, (hh_s_ppu_loc_bam_entry) { .horizontal_flip = false, .vertical_flip = false, .palette_index = 1, .tilemap_index = 0, - .position_x = 30, - .position_y = 40 + }); + hh_ppu_update_background(4, (hh_s_ppu_loc_bam_entry) { + .horizontal_flip = true, + .vertical_flip = false, + .palette_index = 2, + .tilemap_index = 0, + }); + hh_ppu_update_background(5, (hh_s_ppu_loc_bam_entry) { + .horizontal_flip = false, + .vertical_flip = false, + .palette_index = 3, + .tilemap_index = 0, + }); + hh_ppu_update_background(6, (hh_s_ppu_loc_bam_entry) { + .horizontal_flip = false, + .vertical_flip = true, + .palette_index = 4, + .tilemap_index = 0, + }); + hh_ppu_update_background(7, (hh_s_ppu_loc_bam_entry) { + .horizontal_flip = true, + .vertical_flip = true, + .palette_index = 5, + .tilemap_index = 0, }); - hh_ppu_update_color(1, 1, (hh_ppu_rgb_color_t) {15, 0, 15}); + hh_ppu_update_color(1, 1, (hh_ppu_rgb_color_t) {0xf, 0x0, 0xf}); + hh_ppu_update_color(2, 1, (hh_ppu_rgb_color_t) {0xf, 0xf, 0xf}); + hh_ppu_update_color(3, 1, (hh_ppu_rgb_color_t) {0xf, 0x0, 0x0}); + hh_ppu_update_color(4, 1, (hh_ppu_rgb_color_t) {0x0, 0xf, 0xf}); + hh_ppu_update_color(5, 1, (hh_ppu_rgb_color_t) {0x0, 0x0, 0xf}); } void hh_exit() { diff --git a/src/ppu/internals.c b/src/ppu/internals.c index 5b47b75..7826ece 100644 --- a/src/ppu/internals.c +++ b/src/ppu/internals.c @@ -3,11 +3,6 @@ #include "ppu/types.h" #include "ppu/internals.h" -/** @brief generate bitmask with `n` bits set to one from LSB */ -#define HH_MASK(n) ((1 << (n))-1) -/** @brief resize `in` to `upper downto lower` like in vhdl */ -#define HH_RESIZE(in, upper, lower) ((((hh_ppu_data_t)(in)) & HH_MASK(upper+1-lower)) >> lower) - bool hh_ppu_vram_valid_address(hh_ppu_addr_t addr) { (void) addr; // compiler bruh return true; // TODO @@ -72,13 +67,11 @@ hh_s_ppu_vram_data hh_ppu_2nat_aux(hh_s_ppu_loc_aux aux) { hh_s_ppu_vram_data hh_ppu_2nat_sprite(hh_ppu_loc_sprite_data_t sprite_data) { hh_ppu_data_t* data = malloc(sizeof(hh_ppu_data_t) * HH_PPU_VRAM_TMM_SPRITE_SIZE); - for (unsigned x = 0; x < HH_PPU_SPRITE_WIDTH; x++) { - for (unsigned y = 0; y < HH_PPU_SPRITE_HEIGHT; y++) { - unsigned i = y * HH_PPU_SPRITE_WIDTH + x; - unsigned word = i / 5; - unsigned pixel = i % 5; - data[word] |= HH_RESIZE(sprite_data[i], 2, 0) << pixel * 3; - } + for (unsigned i = 0; i < HH_PPU_SPRITE_WIDTH * HH_PPU_SPRITE_HEIGHT; i++) { + unsigned word = i / 5; + unsigned pixel = i % 5; + if (pixel == 0) data[word] = 0; + data[word] |= HH_RESIZE(sprite_data[i], 2, 0) << pixel * 3; } hh_s_ppu_vram_data out = { diff --git a/src/ppu/internals.h b/src/ppu/internals.h index 7b60255..6e9dda7 100644 --- a/src/ppu/internals.h +++ b/src/ppu/internals.h @@ -4,6 +4,11 @@ #include "ppu/types.h" +/** @brief generate bitmask with `n` bits set to one from LSB */ +#define HH_MASK(n) ((1 << (n))-1) +/** @brief resize `in` to `upper downto lower` like in vhdl */ +#define HH_RESIZE(in, upper, lower) ((((hh_ppu_data_t)(in)) & (HH_MASK(upper+1-lower) << lower)) >> lower) + typedef struct { hh_ppu_addr_t offset; hh_ppu_addr_t size; diff --git a/src/ppusim/pixel.c b/src/ppusim/pixel.c index 3a09ccd..96ee998 100644 --- a/src/ppusim/pixel.c +++ b/src/ppusim/pixel.c @@ -1,6 +1,10 @@ #include +#include +#include "ppu/internals.h" +#include "ppusim/mem.h" #include "ppusim/sim.h" +#include "ppu/consts.h" static void hh_ppusim_draw(SDL_Renderer* r, unsigned px, unsigned py, unsigned cr, unsigned cg, unsigned cb) { SDL_SetRenderDrawColor(r, cr, cg, cb, 255); @@ -12,11 +16,50 @@ static void hh_ppusim_draw(SDL_Renderer* r, unsigned px, unsigned py, unsigned c }); } +/* transform xy if tile is flipped */ +static uint16_t hh_ppusim_apply_transform(unsigned x, unsigned y, bool fliph, bool flipv) { + unsigned tx = fliph ? HH_PPU_SPRITE_WIDTH - x - 1 : x; + unsigned ty = flipv ? HH_PPU_SPRITE_HEIGHT - y - 1 : y; + return ty * HH_PPU_SPRITE_WIDTH + tx; +} + +/* @brief get current bg pixel cidx */ +static uint8_t hh_ppusim_bg_pixel(unsigned x, unsigned y) { + hh_ppu_data_t* aux = &g_hh_ppusim_vram[HH_PPU_VRAM_AUX_OFFSET]; + unsigned bg_shift_y = HH_RESIZE(aux[0], 7, 0); + unsigned bg_shift_x = HH_RESIZE(aux[0], 15, 8) | HH_RESIZE(aux[1], 0, 0) << 8; + unsigned abs_x = bg_shift_x + x; + unsigned abs_y = bg_shift_y + y; + unsigned grid_x = abs_x / HH_PPU_SPRITE_WIDTH; + unsigned grid_y = abs_y / HH_PPU_SPRITE_HEIGHT; + unsigned loc_x = abs_x - grid_x * HH_PPU_SPRITE_WIDTH; + unsigned loc_y = abs_y - grid_y * HH_PPU_SPRITE_HEIGHT; + unsigned bam_offset = grid_y * HH_PPU_BG_CANVAS_TILES_H + grid_x; + hh_ppu_data_t bam = g_hh_ppusim_vram[HH_PPU_VRAM_BAM_OFFSET + bam_offset]; + uint8_t cidx = 0; + uint16_t tile_pixel_idx = hh_ppusim_apply_transform(loc_x, loc_y, HH_RESIZE(bam, 14, 14), HH_RESIZE(bam, 13, 13)); + uint16_t tile_idx = HH_RESIZE(bam, 9, 0); + hh_ppu_addr_t ttm_addr = tile_idx + tile_pixel_idx / 5; + uint8_t word_bit_addr = (tile_pixel_idx % 5) * 3; + hh_ppu_data_t tmm = g_hh_ppusim_vram[HH_PPU_VRAM_TMM_OFFSET + ttm_addr]; + cidx |= HH_RESIZE(bam, 12, 10) << 3; + cidx |= HH_RESIZE(tmm, word_bit_addr+2, word_bit_addr) << 0; + return cidx; +} + void hh_ppusim_pixel(SDL_Renderer* r, unsigned x, unsigned y) { // loop through foreground sprites to get highest priority cidx - // get background cidx + uint8_t bg_cidx = hh_ppusim_bg_pixel(x, y); // check if palette color cidx of foreground is 0 // lookup color from PAL // hh_ppusim_draw + uint8_t cidx = bg_cidx; + hh_ppu_data_t pal_rgb = g_hh_ppusim_vram[HH_PPU_VRAM_PAL_OFFSET + cidx]; + hh_ppu_rgb_color_t rgb = { + HH_RESIZE(pal_rgb, 11, 8), + HH_RESIZE(pal_rgb, 7, 4), + HH_RESIZE(pal_rgb, 3, 0) + }; + hh_ppusim_draw(r, x, y, rgb[0] << 4, rgb[1] << 4, rgb[2] << 4); } -- cgit v1.2.3