From bcdf8745571675069c6eb29cd740cbb63480dea7 Mon Sep 17 00:00:00 2001 From: agg23 Date: Wed, 24 Feb 2021 16:59:55 -0800 Subject: [PATCH] Fixed #13: Properly buffer screen transitions to prevent memory corruption --- main.mfk | 46 +++++++++++++++++++++++++++------------------- ui/screen.mfk | 15 +++++++++++---- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/main.mfk b/main.mfk index 08c2dea..8e7996e 100644 --- a/main.mfk +++ b/main.mfk @@ -54,12 +54,15 @@ void main() { while(true) { // Wait for NMI to complete rendering frame - while (new_frame) {} - - sprite_tick() - input_and_screen_tick() - clear_remaining_oam() - + while (new_frame && not(buffer_screen_draw)) {} + + if (buffer_screen_draw) { + screen_draw_tick() + } else { + sprite_tick() + input_and_screen_tick() + clear_remaining_oam() + } // wait_for_sprite0_clear() new_frame = true @@ -68,17 +71,6 @@ void main() { } void nmi() { - if (buffer_screen_draw) { - screen_transfer_tick() - nmi_always_run() - return - } - - if (not(drawing_enabled)) { - nmi_always_run() - return - } - if in_nmi != 0 { // Overran NMI nmi_fail = 1 @@ -89,6 +81,24 @@ void nmi() { in_nmi = 1 + nmi_work() + + in_nmi = 0 +} + +inline void nmi_work() { + if (buffer_screen_blank) { + screen_transfer_tick() + nmi_always_run() + new_frame = false + return + } + + if (not(drawing_enabled)) { + nmi_always_run() + return + } + if (new_frame) { nmi_frame() @@ -96,8 +106,6 @@ void nmi() { } nmi_always_run() - - in_nmi = 0 } void nmi_frame() { diff --git a/ui/screen.mfk b/ui/screen.mfk index 2f3a7df..8513163 100644 --- a/ui/screen.mfk +++ b/ui/screen.mfk @@ -19,6 +19,7 @@ enum Screen { } bool buffer_screen_draw = false +bool buffer_screen_blank = false Screen current_screen bool screen_tick() { @@ -47,7 +48,7 @@ void draw_screen() { void set_screen_forcibly(Screen new_screen) { current_screen = new_screen - buffer_screen_draw = true + buffer_screen_blank = true } void set_screen(Screen new_screen) { @@ -56,18 +57,24 @@ void set_screen(Screen new_screen) { } current_screen = new_screen - buffer_screen_draw = true + buffer_screen_blank = true } void screen_transfer_tick() { // Wait for NMI to disable rendering and NMIs - // Draw new screen drawing_enabled = false - buffer_screen_draw = false + buffer_screen_blank = false read_ppu_status() ppu_ctrl = standard_ppu_ctrl ppu_mask = 0 + buffer_screen_draw = true +} + +void screen_draw_tick() { + // NMI has cleared screen, now write it + // Draw new screen + buffer_screen_draw = false ppu_wait_vblank() clear_buffer()