summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gb.h3
-rw-r--r--ops.yaml118
2 files changed, 103 insertions, 18 deletions
diff --git a/gb.h b/gb.h
index e027ee7..358c1f2 100644
--- a/gb.h
+++ b/gb.h
@@ -124,7 +124,8 @@ struct gb_t_ {
uint32_t frame;
struct {
- uint8_t x, y, tile;
+ int16_t x, y;
+ uint8_t tile;
bool priority,
y_flip,
x_flip,
diff --git a/ops.yaml b/ops.yaml
index 26c1a87..a88e9e4 100644
--- a/ops.yaml
+++ b/ops.yaml
@@ -8088,6 +8088,7 @@ templates:
#define UNUSED(a) ((void) (a))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+ #define BETWEEN(v, a, b) (((v) >= (a)) && ((v) <= (b)))
// cpu flags
#define FLAG(ctx, f) (cpu_rb(ctx, RB_F) & (F_##f))
@@ -10211,10 +10212,10 @@ templates:
return;
}
- // decode oam
+ // decode and cache oam
for (uint8_t i = 0; i < 40; i++) {
- ctx->gpu.oam_cache[i].y = (ctx->mmu.oam[4 * i + 0] + 16) & 0xFF;
- ctx->gpu.oam_cache[i].x = (ctx->mmu.oam[4 * i + 1] + 8) & 0xFF;
+ ctx->gpu.oam_cache[i].y = ctx->mmu.oam[4 * i + 0] - 10;
+ ctx->gpu.oam_cache[i].x = ctx->mmu.oam[4 * i + 1] - 8;
ctx->gpu.oam_cache[i].tile = ctx->mmu.oam[4 * i + 2];
const uint8_t flags = ctx->mmu.oam[4 * i + 3];
@@ -10228,6 +10229,87 @@ templates:
ctx->gpu.oam_dirty = false;
}
+ static uint8_t
+ bg_get_tile(
+ gb_t * const ctx,
+ const uint8_t ty,
+ const uint8_t tx
+ ) {
+ // calculate tile offset
+ return mmu_rb(ctx, (
+ // get bg tile map base
+ // (lcdc & (1 << 3))
+ ((ctx->gpu.lcdc & (1 << 3)) ? 0x9C00 : 0x9800) +
+
+ // calculate tile offset
+ ty * 32 + tx
+ ));
+ }
+
+ static uint16_t
+ bg_get_tile_addr(
+ gb_t * const ctx,
+ const uint8_t ty,
+ const uint8_t tx
+ ) {
+ // get tile
+ const uint8_t tile = bg_get_tile(ctx, ty, tx);
+
+ if (ctx->gpu.lcdc & (1 << 4)) {
+ // base: 0x8000, tile is unsigned
+ return 0x8000 + 16 * tile;
+ } else {
+ // base: 0x9000, tile is signed
+ return 0x9000 + 16 * ((int8_t) tile);
+ }
+ }
+
+ static uint8_t
+ bg_get_color(
+ gb_t * const ctx,
+ const uint8_t sy,
+ const uint8_t sx
+ ) {
+ // TODO: draw background
+ const uint8_t y = (ctx->gpu.scy + sy) & 0xFF,
+ ty = y >> 3,
+ py = y - (ty << 3);
+
+ const uint8_t x = (ctx->gpu.scx + sx) & 0xFF,
+ tx = x >> 3,
+ px = x - (tx << 3);
+
+ // get tile data address
+ const uint16_t addr = bg_get_tile_addr(ctx, ty, tx);
+
+ // get tile data
+ const uint16_t data = mmu_rw(ctx, addr + (2 * py));
+
+ // get bg palette entry
+ const uint8_t p_ofs = (
+ ((data >> (8 + (7 - px)) & 0x01) << 1) |
+ ((data >> (7 - px)) & 0x01)
+ );
+
+ // get pixel color
+ const uint8_t pc = (ctx->gpu.bgp >> (2 * p_ofs)) & 0x03;
+
+ // convert from 0-3 to RGB
+ switch (pc) {
+ case 0:
+ return 0xFF;
+ case 1:
+ return 0xC0;
+ case 2:
+ return 0x40;
+ case 3:
+ return 0x00;
+ }
+
+ // never reached
+ return 0xA0;
+ }
+
static void
gpu_draw_line(
gb_t * const ctx
@@ -10242,12 +10324,11 @@ templates:
ctx->gpu.oam_cache[i].priority &&
// sprite is on screen
- ctx->gpu.oam_cache[i].y < 144 &&
- ctx->gpu.oam_cache[i].x < 160 &&
+ BETWEEN(ctx->gpu.oam_cache[i].y, 0, 144) &&
+ BETWEEN(ctx->gpu.oam_cache[i].x, 0, 160) &&
// sprite is on current line
- ctx->gpu.line >= ctx->gpu.oam_cache[i].y &&
- ctx->gpu.line <= ctx->gpu.oam_cache[i].y
+ BETWEEN(ctx->gpu.line, ctx->gpu.oam_cache[i].y, ctx->gpu.oam_cache[i].y + 8)
) {
const uint8_t max_j = MIN(8, 160 - ctx->gpu.oam_cache[i].x);
@@ -10262,12 +10343,16 @@ templates:
}
}
- // TODO: draw background
- for (uint8_t i = 0; i < 160; i++) {
- // interim: set line to red
- ctx->gpu.fb[3 * (ctx->gpu.line * 160 + i) + 0] = 0xff;
- ctx->gpu.fb[3 * (ctx->gpu.line * 160 + i) + 1] = 0x00;
- ctx->gpu.fb[3 * (ctx->gpu.line * 160 + i) + 2] = 0x00;
+ if (ctx->gpu.lcdc & 1) {
+ for (uint8_t i = 0; i < 160; i++) {
+ // get pixel color
+ const uint8_t c = bg_get_color(ctx, ctx->gpu.line, i);
+
+ // populate framebuffer
+ ctx->gpu.fb[3 * (ctx->gpu.line * 160 + i) + 0] = c;
+ ctx->gpu.fb[3 * (ctx->gpu.line * 160 + i) + 1] = c;
+ ctx->gpu.fb[3 * (ctx->gpu.line * 160 + i) + 2] = c;
+ }
}
// draw foreground sprites
@@ -10277,12 +10362,11 @@ templates:
!ctx->gpu.oam_cache[i].priority &&
// sprite is on screen
- ctx->gpu.oam_cache[i].y < 144 &&
- ctx->gpu.oam_cache[i].x < 160 &&
+ BETWEEN(ctx->gpu.oam_cache[i].y, 0, 144) &&
+ BETWEEN(ctx->gpu.oam_cache[i].x, 0, 160) &&
// sprite is on current line
- ctx->gpu.line >= ctx->gpu.oam_cache[i].y &&
- ctx->gpu.line <= ctx->gpu.oam_cache[i].y
+ BETWEEN(ctx->gpu.line, ctx->gpu.oam_cache[i].y, ctx->gpu.oam_cache[i].y + 8)
) {
const uint8_t max_j = MIN(8, 160 - ctx->gpu.oam_cache[i].x);