From f5c8ae2f2d2074d483490e857db5aef8388f06c9 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Fri, 24 Feb 2023 19:11:59 +0100 Subject: c interface semi-done --- src/ppu/consts.h | 33 ++++++++++++++++- src/ppu/internals.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ppu/internals.h | 19 ++++++---- src/ppu/ppu.c | 52 ++++++++++++++++++++++++++ src/ppu/ppu.h | 14 ++++++- src/ppu/types.h | 14 ++++--- 6 files changed, 218 insertions(+), 17 deletions(-) create mode 100644 src/ppu/internals.c create mode 100644 src/ppu/ppu.c (limited to 'src/ppu') diff --git a/src/ppu/consts.h b/src/ppu/consts.h index ee94a69..0e8fba4 100644 --- a/src/ppu/consts.h +++ b/src/ppu/consts.h @@ -1,26 +1,57 @@ #pragma once +/** @brief amount of total palettes in PPU */ #define HH_PPU_PALETTE_COUNT 8 +/** @brief amount of colors in palette */ #define HH_PPU_PALETTE_COLOR_COUNT 8 +/** @brief address line width in bits */ #define HH_PPU_RAM_BUS_ADDR_WIDTH 16 +/** @brief data line width in bits */ #define HH_PPU_RAM_BUS_DATA_WIDTH 16 +/** @brief max amount of foreground sprites allowed */ #define HH_PPU_FG_SPRITE_COUNT 128 +/** @brief sprite width in pixel */ #define HH_PPU_SPRITE_WIDTH 16 +/** @brief sprite height in pixels */ #define HH_PPU_SPRITE_HEIGHT 16 +/** @brief screen width in pixels */ #define HH_PPU_SCREEN_WIDTH 320 +/** @brief screen height in pixels */ #define HH_PPU_SCREEN_HEIGHT 240 +/** @brief amount of horizontal backgorund tiles on background canvas */ #define HH_PPU_BG_CANVAS_TILES_H 40 +/** @brief amount of vertical backgorund tiles on background canvas */ #define HH_PPU_BG_CANVAS_TILES_V 30 -#include "types.h" +#include "ppu/types.h" +/** @brief tilemap memory address offset */ #define HH_PPU_VRAM_TMM_OFFSET ((hh_ppu_addr_t) 0x0000) +/** @brief tilemap memory size in words */ #define HH_PPU_VRAM_TMM_SIZE ((hh_ppu_addr_t) 0xd000) +/** @brief sprite size in words */ +#define HH_PPU_VRAM_TMM_SPRITE_SIZE 52 +/** @brief pixels per word for sprite */ +#define HH_PPU_VRAM_TMM_SPRITE_PPW 5 +/** @brief background attribute memory address offset */ #define HH_PPU_VRAM_BAM_OFFSET ((hh_ppu_addr_t) 0xd000) +/** @brief background attribute memory size in words */ #define HH_PPU_VRAM_BAM_SIZE ((hh_ppu_addr_t) 0x04b0) +/** @brief background attribute memory entry size in words */ +#define HH_PPU_VRAM_BAM_ENTRY_SIZE 1 +/** @brief foreground attribute memory address offset */ #define HH_PPU_VRAM_FAM_OFFSET ((hh_ppu_addr_t) 0xd800) +/** @brief foreground attribute memory size in words */ #define HH_PPU_VRAM_FAM_SIZE ((hh_ppu_addr_t) 0x0100) +/** @brief foreground attribute memory entry size in words */ +#define HH_PPU_VRAM_FAM_ENTRY_SIZE 2 +/** @brief palette memory address offset */ #define HH_PPU_VRAM_PAL_OFFSET ((hh_ppu_addr_t) 0xdc00) +/** @brief palette memory size in words */ #define HH_PPU_VRAM_PAL_SIZE ((hh_ppu_addr_t) 0x0040) +/** @brief palette entry size in words */ +#define HH_PPU_VRAM_PAL_ENTRY_SIZE 1 +/** @brief auxiliary memory address offset */ #define HH_PPU_VRAM_AUX_OFFSET ((hh_ppu_addr_t) 0xde00) +/** @brief auxiliary memory size in words */ #define HH_PPU_VRAM_AUX_SIZE ((hh_ppu_addr_t) 0x0002) diff --git a/src/ppu/internals.c b/src/ppu/internals.c new file mode 100644 index 0000000..5b47b75 --- /dev/null +++ b/src/ppu/internals.c @@ -0,0 +1,103 @@ +#include + +#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 +} + +void hh_ppu_vram_write(hh_s_ppu_vram_data data) { + for (unsigned i = 0; i < data.size; i++) + hh_ppu_vram_dwrite(data.offset + i, data.data[i]); +} + +hh_s_ppu_vram_data hh_ppu_2nat_bam(hh_s_ppu_loc_bam_entry e) { + hh_ppu_data_t* data = malloc(sizeof(hh_ppu_data_t) * HH_PPU_VRAM_BAM_ENTRY_SIZE); + + data[0] = HH_RESIZE(e.tilemap_index, 9, 0) << 0 | + HH_RESIZE(e.palette_index, 2, 0) << 10 | + e.vertical_flip << 13 | + e.horizontal_flip << 14; + + hh_s_ppu_vram_data out = { + .data = data, + .size = HH_PPU_VRAM_FAM_ENTRY_SIZE + }; + return out; +} + +hh_s_ppu_vram_data hh_ppu_2nat_fam(hh_s_ppu_loc_fam_entry e) { + hh_ppu_data_t* data = malloc(sizeof(hh_ppu_data_t) * HH_PPU_VRAM_FAM_ENTRY_SIZE); + + e.position_x += 16; + e.position_y += 16; + data[0] = HH_RESIZE(e.tilemap_index, 9, 0) << 0 | + HH_RESIZE(e.palette_index, 2, 0) << 10 | + HH_RESIZE(e.position_y, 2, 0) << 13; + data[1] = HH_RESIZE(e.position_y, 4, 0) << 0 | + HH_RESIZE(e.position_x, 8, 0) << 5 | + e.vertical_flip << 14 | + e.horizontal_flip << 15; + + hh_s_ppu_vram_data out = { + .data = data, + .size = HH_PPU_VRAM_FAM_ENTRY_SIZE + }; + return out; +} + +hh_s_ppu_vram_data hh_ppu_2nat_aux(hh_s_ppu_loc_aux aux) { + hh_ppu_data_t* data = malloc(sizeof(hh_ppu_data_t) * HH_PPU_VRAM_AUX_SIZE); + + data[0] = HH_RESIZE(aux.bg_shift_y, 7, 0) << 0 | + HH_RESIZE(aux.bg_shift_x, 7, 0) << 8; + data[1] = HH_RESIZE(aux.bg_shift_x, 8, 8) << 0 | + aux.fg_fetch << 1 | + aux.sysreset << 2; + + hh_s_ppu_vram_data out = { + .data = data, + .size = HH_PPU_VRAM_AUX_SIZE + }; + return out; +} + +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; + } + } + + hh_s_ppu_vram_data out = { + .data = data, + .size = HH_PPU_VRAM_TMM_SPRITE_SIZE + }; + return out; +} + +hh_s_ppu_vram_data hh_ppu_2nat_color(hh_ppu_rgb_color_t rgb) { + hh_ppu_data_t* data = malloc(sizeof(hh_ppu_data_t) * HH_PPU_VRAM_PAL_ENTRY_SIZE); + + data[0] = HH_RESIZE(rgb[0], 3, 0) << 0 | + HH_RESIZE(rgb[1], 3, 0) << 4 | + HH_RESIZE(rgb[2], 3, 0) << 8; + + hh_s_ppu_vram_data out = { + .data = data, + .size = HH_PPU_VRAM_PAL_ENTRY_SIZE + }; + return out; +} diff --git a/src/ppu/internals.h b/src/ppu/internals.h index ddb2196..7b60255 100644 --- a/src/ppu/internals.h +++ b/src/ppu/internals.h @@ -2,7 +2,7 @@ #include -#include "types.h" +#include "ppu/types.h" typedef struct { hh_ppu_addr_t offset; @@ -10,13 +10,16 @@ typedef struct { hh_ppu_data_t* data; } hh_s_ppu_vram_data; +/** @brief check if `addr` is a valid PPU address */ bool hh_ppu_vram_valid_address(hh_ppu_addr_t addr); -void hh_ppu_vram_write(hh_ppu_addr_t addr, hh_ppu_data_t data); -void hh_ppu_vram_memcpy(void* a, hh_s_ppu_vram_data b); +/** @brief direct write vram word (platform-specific implementation) */ +void hh_ppu_vram_dwrite(hh_ppu_addr_t addr, hh_ppu_data_t data); +/** @brief write data block into vram */ +void hh_ppu_vram_write(hh_s_ppu_vram_data data); -hh_s_ppu_vram_data* hh_ppu_2nat_bam(hh_s_ppu_loc_bam_entry); -hh_s_ppu_vram_data* hh_ppu_2nat_fam(hh_s_ppu_loc_fam_entry); -hh_s_ppu_vram_data* hh_ppu_2nat_aux(hh_s_ppu_loc_aux); -hh_s_ppu_vram_data* hh_ppu_2nat_sprite(hh_ppu_loc_sprite_data_t); -hh_s_ppu_vram_data* hh_ppu_2nat_pal(hh_ppu_loc_palette_data_t); +hh_s_ppu_vram_data hh_ppu_2nat_bam(hh_s_ppu_loc_bam_entry); +hh_s_ppu_vram_data hh_ppu_2nat_fam(hh_s_ppu_loc_fam_entry); +hh_s_ppu_vram_data hh_ppu_2nat_aux(hh_s_ppu_loc_aux); +hh_s_ppu_vram_data hh_ppu_2nat_sprite(hh_ppu_loc_sprite_data_t); +hh_s_ppu_vram_data hh_ppu_2nat_color(hh_ppu_rgb_color_t); diff --git a/src/ppu/ppu.c b/src/ppu/ppu.c new file mode 100644 index 0000000..e2fccb9 --- /dev/null +++ b/src/ppu/ppu.c @@ -0,0 +1,52 @@ +#include + +#include "ppu/ppu.h" +#include "ppu/internals.h" +#include "ppu/consts.h" + +void hh_ppu_update_foreground(unsigned index, hh_s_ppu_loc_fam_entry e) { + hh_s_ppu_vram_data s = hh_ppu_2nat_fam(e); + s.offset = HH_PPU_VRAM_FAM_OFFSET + HH_PPU_VRAM_FAM_ENTRY_SIZE * index; + hh_ppu_vram_write(s); + free(s.data); +} + +void hh_ppu_update_background(unsigned index, hh_s_ppu_loc_bam_entry e) { + hh_s_ppu_vram_data s = hh_ppu_2nat_bam(e); + s.offset = HH_PPU_VRAM_BAM_OFFSET + HH_PPU_VRAM_BAM_ENTRY_SIZE * index; + hh_ppu_vram_write(s); + free(s.data); +} + +void hh_ppu_update_sprite(unsigned tilemap_index, hh_s_ppu_loc_sprite sprite) { + hh_s_ppu_vram_data s = hh_ppu_2nat_sprite(sprite); + s.offset = HH_PPU_VRAM_TMM_OFFSET + HH_PPU_VRAM_TMM_SPRITE_SIZE * tilemap_index; + hh_ppu_vram_write(s); + free(s.data); +} + +void hh_ppu_update_aux(hh_s_ppu_loc_aux aux) { + hh_s_ppu_vram_data a = hh_ppu_2nat_aux(aux); + a.offset = HH_PPU_VRAM_AUX_OFFSET; + hh_ppu_vram_write(a); + free(a.data); +} + +void hh_ppu_update_palette_table(hh_ppu_loc_palette_table_t table) { + for(unsigned i = 0; i < HH_PPU_PALETTE_COUNT; i++) + hh_ppu_update_palette(i, table[i]); +} + +void hh_ppu_update_palette(unsigned palette_index, hh_ppu_loc_palette_data_t palette) { + for(unsigned i = 0; i < HH_PPU_PALETTE_COLOR_COUNT; i++) + hh_ppu_update_color(palette_index, i, palette[i]); +} + +void hh_ppu_update_color(unsigned palette_index, unsigned color_index, hh_ppu_rgb_color_t color) { + hh_s_ppu_vram_data c = hh_ppu_2nat_color(color); + c.offset = HH_PPU_VRAM_PAL_OFFSET + + palette_index * HH_PPU_VRAM_PAL_ENTRY_SIZE * HH_PPU_PALETTE_COLOR_COUNT + + color_index * HH_PPU_VRAM_PAL_ENTRY_SIZE; + hh_ppu_vram_write(c); + free(c.data); +} diff --git a/src/ppu/ppu.h b/src/ppu/ppu.h index 7aeb7c1..90f964e 100644 --- a/src/ppu/ppu.h +++ b/src/ppu/ppu.h @@ -1,12 +1,22 @@ #pragma once -#include "types.h" +#include "ppu/types.h" void hh_ppu_vblank_interrupt(); void hh_ppu_init(); void hh_ppu_deinit(); +/* @brief update single foreground sprite */ void hh_ppu_update_foreground(unsigned index, hh_s_ppu_loc_fam_entry e); +/* @brief update single background sprite */ void hh_ppu_update_background(unsigned index, hh_s_ppu_loc_bam_entry e); -void hh_ppu_update_sprite(unsigned tilemap_index, hh_s_ppu_loc_sprite sprite); +/* @brief update aux register */ void hh_ppu_update_aux(hh_s_ppu_loc_aux aux); +/* @brief update single sprite */ +void hh_ppu_update_sprite(unsigned tilemap_index, hh_s_ppu_loc_sprite sprite); +/* @brief update entire palette table */ +void hh_ppu_update_palette_table(hh_ppu_loc_palette_table_t table); +/* @brief update single palette */ +void hh_ppu_update_palette(unsigned palette_index, hh_ppu_loc_palette_data_t palette); +/* @brief update single color in palette */ +void hh_ppu_update_color(unsigned palette_index, unsigned color_index, hh_ppu_rgb_color_t color); diff --git a/src/ppu/types.h b/src/ppu/types.h index d7605a5..08bef13 100644 --- a/src/ppu/types.h +++ b/src/ppu/types.h @@ -3,16 +3,18 @@ #include #include -#include "consts.h" +#include "ppu/consts.h" typedef uint16_t hh_ppu_addr_t; typedef uint16_t hh_ppu_data_t; -typedef uint8_t hh_ppu_loc_sprite_data_t[HH_PPU_SPRITE_WIDTH * HH_PPU_SPRITE_HEIGHT]; -typedef uint8_t hh_ppu_loc_palette_data_t[HH_PPU_PALETTE_COLOR_COUNT]; +typedef uint8_t hh_ppu_rgb_color_t[3]; + +typedef hh_ppu_rgb_color_t hh_ppu_loc_palette_data_t[HH_PPU_PALETTE_COLOR_COUNT]; +typedef hh_ppu_loc_palette_data_t hh_ppu_loc_palette_table_t[HH_PPU_PALETTE_COUNT]; +typedef uint8_t hh_ppu_loc_sprite_data_t[HH_PPU_SPRITE_WIDTH * HH_PPU_SPRITE_HEIGHT]; typedef hh_ppu_loc_sprite_data_t hh_s_ppu_loc_sprite; -typedef hh_ppu_loc_palette_data_t hh_s_ppu_loc_palette; typedef struct { bool horizontal_flip; @@ -24,8 +26,8 @@ typedef struct { typedef struct { bool horizontal_flip; bool vertical_flip; - uint16_t position_x; - uint16_t position_y; + int32_t position_x; + int32_t position_y; uint8_t palette_index; uint8_t tilemap_index; } hh_s_ppu_loc_fam_entry; -- cgit v1.2.3