summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ops.yaml204
-rw-r--r--test.c12
2 files changed, 120 insertions, 96 deletions
diff --git a/ops.yaml b/ops.yaml
index 29fe351..26c1a87 100644
--- a/ops.yaml
+++ b/ops.yaml
@@ -8089,12 +8089,14 @@ templates:
#define UNUSED(a) ((void) (a))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+ // cpu flags
#define FLAG(ctx, f) (cpu_rb(ctx, RB_F) & (F_##f))
#define F_Z (1 << 7)
#define F_N (1 << 6)
#define F_H (1 << 5)
#define F_C (1 << 4)
+ // interrupts
#define IRQ_VBLANK (1)
#define IRQ_LCDC (1 << 1)
#define IRQ_TIMER (1 << 2)
@@ -8830,10 +8832,9 @@ templates:
const gb_t * const ctx,
const uint16_t addr
) {
- switch (gpu_get_mode(ctx)) {
- case GPU_MODE_VRAM:
+ if (gpu_is_active(ctx) && gpu_get_mode(ctx) == GPU_MODE_VRAM) {
return 0xFF;
- default:
+ } else {
// return vram (8k)
return ctx->mmu.vram[addr & 0x1FFF];
}
@@ -8844,13 +8845,18 @@ templates:
const gb_t * const ctx,
const uint16_t addr
) {
- switch (gpu_get_mode(ctx)) {
- case GPU_MODE_HBLANK:
- case GPU_MODE_VBLANK:
+ if (gpu_is_active(ctx)) {
+ switch (gpu_get_mode(ctx)) {
+ case GPU_MODE_HBLANK:
+ case GPU_MODE_VBLANK:
+ // oam memory (160 bytes):
+ return ctx->mmu.oam[addr & 0xFF];
+ default:
+ return 0;
+ }
+ } else {
// oam memory (160 bytes):
return ctx->mmu.oam[addr & 0xFF];
- default:
- return 0;
}
}
@@ -8964,16 +8970,21 @@ templates:
const uint16_t addr,
const uint8_t val
) {
- switch (gpu_get_mode(ctx)) {
- case GPU_MODE_HBLANK:
- case GPU_MODE_VBLANK:
- case GPU_MODE_OAM:
+ if (gpu_is_active(ctx)) {
+ switch (gpu_get_mode(ctx)) {
+ case GPU_MODE_HBLANK:
+ case GPU_MODE_VBLANK:
+ case GPU_MODE_OAM:
+ // vram (8k)
+ ctx->mmu.vram[addr & 0x1FFF] = val;
+ break;
+ default:
+ // do nothing
+ break;
+ }
+ } else {
// vram (8k)
ctx->mmu.vram[addr & 0x1FFF] = val;
- break;
- default:
- // do nothing
- break;
}
}
@@ -8983,19 +8994,21 @@ templates:
const uint16_t addr,
const uint8_t val
) {
- switch (gpu_get_mode(ctx) & 0x3) {
- case GPU_MODE_HBLANK:
- case GPU_MODE_VBLANK:
- // oam memory (160 bytes):
- ctx->mmu.oam[addr & 0xFF] = val;
+ if (gpu_is_active(ctx)) {
+ switch (gpu_get_mode(ctx) & 0x3) {
+ case GPU_MODE_HBLANK:
+ case GPU_MODE_VBLANK:
+ // oam memory (160 bytes):
+ ctx->mmu.oam[addr & 0xFF] = val;
- // invalidate oam cache
- ctx->gpu.oam_dirty = true;
+ // invalidate oam cache
+ ctx->gpu.oam_dirty = true;
- break;
- default:
- // do nothing
- break;
+ break;
+ default:
+ // do nothing
+ break;
+ }
}
}
@@ -10180,7 +10193,7 @@ templates:
// trigger vblank interrupt
cpu_irq(ctx, IRQ_VBLANK);
- if (ctx->cpu.ime && (mmu_rb(ctx, PORT_IE) & 1)) {
+ if (gpu_is_active(ctx) && ctx->cpu.ime && (mmu_rb(ctx, PORT_IE) & 1)) {
if (ctx->config && ctx->config->on_vblank) {
ctx->config->on_vblank(ctx);
}
@@ -10200,11 +10213,11 @@ templates:
// decode oam
for (uint8_t i = 0; i < 40; i++) {
- ctx->gpu.oam_cache[i].y = (ctx->mmu.oam[i * 4 + 0] + 16) & 0xFF;
- ctx->gpu.oam_cache[i].x = (ctx->mmu.oam[i * 4 + 1] + 8) & 0xFF;
- ctx->gpu.oam_cache[i].tile = ctx->mmu.oam[i * 4 + 2];
+ 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].tile = ctx->mmu.oam[4 * i + 2];
- const uint8_t flags = ctx->mmu.oam[i * 4 + 3];
+ const uint8_t flags = ctx->mmu.oam[4 * i + 3];
ctx->gpu.oam_cache[i].priority = flags & (1 << 7);
ctx->gpu.oam_cache[i].y_flip = flags & (1 << 6);
ctx->gpu.oam_cache[i].x_flip = flags & (1 << 5);
@@ -10219,68 +10232,77 @@ templates:
gpu_draw_line(
gb_t * const ctx
) {
- gpu_oam_cache(ctx);
+ if (gpu_is_active(ctx)) {
+ gpu_oam_cache(ctx);
- // draw sprites behind bg
- for (uint8_t i = 0; i < 40; i++) {
- if (
- // sprite is below bg
- ctx->gpu.oam_cache[i].priority &&
-
- // sprite is on screen
- ctx->gpu.oam_cache[i].y < 144 &&
- ctx->gpu.oam_cache[i].x < 160 &&
-
- // sprite is on current line
- ctx->gpu.line >= ctx->gpu.oam_cache[i].y &&
- ctx->gpu.line <= ctx->gpu.oam_cache[i].y
- ) {
- const uint8_t max_j = MIN(8, 160 - ctx->gpu.oam_cache[i].x);
-
- for (uint8_t j = 0; j < max_j; j++) {
- const uint32_t ofs = 3 * (ctx->gpu.oam_cache[i].y * 160 + ctx->gpu.oam_cache[i].x + j);
-
- // TODO: draw sprite scanline
- ctx->gpu.fb[ofs + 0] = 0xff;
- ctx->gpu.fb[ofs + 1] = 0xff;
- ctx->gpu.fb[ofs + 2] = 0xff;
+ // draw sprites behind bg
+ for (uint8_t i = 0; i < 40; i++) {
+ if (
+ // sprite is below bg
+ ctx->gpu.oam_cache[i].priority &&
+
+ // sprite is on screen
+ ctx->gpu.oam_cache[i].y < 144 &&
+ ctx->gpu.oam_cache[i].x < 160 &&
+
+ // sprite is on current line
+ ctx->gpu.line >= ctx->gpu.oam_cache[i].y &&
+ ctx->gpu.line <= ctx->gpu.oam_cache[i].y
+ ) {
+ const uint8_t max_j = MIN(8, 160 - ctx->gpu.oam_cache[i].x);
+
+ for (uint8_t j = 0; j < max_j; j++) {
+ const uint32_t ofs = 3 * (ctx->gpu.oam_cache[i].y * 160 + ctx->gpu.oam_cache[i].x + j);
+
+ // TODO: draw sprite scanline
+ ctx->gpu.fb[ofs + 0] = 0xff;
+ ctx->gpu.fb[ofs + 1] = 0xff;
+ ctx->gpu.fb[ofs + 2] = 0xff;
+ }
}
}
- }
- // 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;
- }
+ // 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;
+ }
- // draw foreground sprites
- for (uint8_t i = 0; i < 40; i++) {
- if (
- // sprite is above bg
- !ctx->gpu.oam_cache[i].priority &&
-
- // sprite is on screen
- ctx->gpu.oam_cache[i].y < 144 &&
- ctx->gpu.oam_cache[i].x < 160 &&
-
- // sprite is on current line
- ctx->gpu.line >= ctx->gpu.oam_cache[i].y &&
- ctx->gpu.line <= ctx->gpu.oam_cache[i].y
- ) {
- const uint8_t max_j = MIN(8, 160 - ctx->gpu.oam_cache[i].x);
-
- for (int j = 0; j < max_j; j++) {
- const uint32_t ofs = 3 * (ctx->gpu.oam_cache[i].y * 160 + ctx->gpu.oam_cache[i].x + j);
-
- // TODO: draw sprite scanline
- ctx->gpu.fb[ofs + 0] = 0xff;
- ctx->gpu.fb[ofs + 1] = 0xff;
- ctx->gpu.fb[ofs + 2] = 0xff;
+ // draw foreground sprites
+ for (uint8_t i = 0; i < 40; i++) {
+ if (
+ // sprite is above bg
+ !ctx->gpu.oam_cache[i].priority &&
+
+ // sprite is on screen
+ ctx->gpu.oam_cache[i].y < 144 &&
+ ctx->gpu.oam_cache[i].x < 160 &&
+
+ // sprite is on current line
+ ctx->gpu.line >= ctx->gpu.oam_cache[i].y &&
+ ctx->gpu.line <= ctx->gpu.oam_cache[i].y
+ ) {
+ const uint8_t max_j = MIN(8, 160 - ctx->gpu.oam_cache[i].x);
+
+ for (int j = 0; j < max_j; j++) {
+ const uint32_t ofs = 3 * (ctx->gpu.oam_cache[i].y * 160 + ctx->gpu.oam_cache[i].x + j);
+
+ // TODO: draw sprite scanline
+ ctx->gpu.fb[ofs + 0] = 0xff;
+ ctx->gpu.fb[ofs + 1] = 0xff;
+ ctx->gpu.fb[ofs + 2] = 0xff;
+ }
}
}
+ } else {
+ // write blank line
+ for (uint8_t i = 0; i < 160; i++) {
+ ctx->gpu.fb[3 * (ctx->gpu.line * 160 + i) + 0] = 0xff;
+ ctx->gpu.fb[3 * (ctx->gpu.line * 160 + i) + 1] = 0xff;
+ ctx->gpu.fb[3 * (ctx->gpu.line * 160 + i) + 2] = 0xff;
+ }
}
}
@@ -10289,10 +10311,6 @@ templates:
gb_t * const ctx,
const uint16_t clock
) {
- if (!gpu_is_active(ctx)) {
- return;
- }
-
// increment clock
ctx->gpu.clock += clock;
@@ -10326,7 +10344,7 @@ templates:
gpu_draw_line(ctx);
gpu_set_line(ctx, ctx->gpu.line + 1);
- if (ctx->gpu.line < 144) {
+ if (ctx->gpu.line < 143) {
// set mode
gpu_set_mode(ctx, GPU_MODE_OAM);
} else {
@@ -10344,7 +10362,7 @@ templates:
// clear clock
ctx->gpu.clock -= 204;
- if (ctx->gpu.line < 154) {
+ if (ctx->gpu.line < 153) {
// increment line
gpu_set_line(ctx, ctx->gpu.line + 1);
} else {
diff --git a/test.c b/test.c
index 929bdd5..c74bf28 100644
--- a/test.c
+++ b/test.c
@@ -9,7 +9,8 @@
#include "lodepng.h"
#include "gb.h"
-#define NUM_FRAMES 600
+#define SKIP_FRAMES 600
+#define NUM_FRAMES 60
// #define SKIP_STEPS 1000000
#define NUM_STEPS 300000
#define UNUSED(a) ((void) (a))
@@ -187,13 +188,18 @@ test_render_frames(
gb_init(&ctx, NULL, rom_data, rom_size);
fprintf(stderr, "gb context initialized\n");
+ for (size_t i = 0; i < SKIP_FRAMES; i++) {
+ // render frame
+ gb_frame(&ctx);
+ }
+
// render frames
- for (size_t j = 0; j < NUM_FRAMES; j++) {
+ for (size_t i = 0; i < NUM_FRAMES; i++) {
// render frame
gb_frame(&ctx);
// copy frame to buffer
- memcpy(frames + GB_FB_SIZE * j, gb_get_frame(&ctx), GB_FB_SIZE);
+ memcpy(frames + GB_FB_SIZE * i, gb_get_frame(&ctx), GB_FB_SIZE);
}
// save png