aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/architecture.md4
-rw-r--r--src/main.c88
-rw-r--r--src/ppu/internals.c17
-rw-r--r--src/ppu/internals.h5
-rw-r--r--src/ppusim/pixel.c45
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 <SDL2/SDL.h>
+#include <stdbool.h>
+#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);
}