Skip to content

Commit

Permalink
PPU: fix horizontal WIN0/1 active flags
Browse files Browse the repository at this point in the history
  • Loading branch information
fleroviux committed Aug 24, 2022
1 parent 77221b9 commit b8b25c4
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 18 deletions.
13 changes: 3 additions & 10 deletions src/nba/src/hw/ppu/compose.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,6 @@ void PPU::SyncCompose(int cycles) {
int cycle = (hcounter - RENDER_DELAY) & 3;

if (cycle == 0) {
// Update windows horizontally
// TODO: should this also happen within V-blank? Does it matter?
for (int i = 0; i < 2; i++) {
if (x == mmio.winh[i].min) window_flag_h[i] = true;
if (x == mmio.winh[i].max) window_flag_h[i] = false;
}

const int* win_layer_enable;

int prio[2] { 4, 4 };
Expand All @@ -80,9 +73,9 @@ void PPU::SyncCompose(int cycles) {
// Find the highest-priority active window for this pixel
if (use_windows) {
// TODO: are the window enable bits delayed like the BG enable bits?
if (mmio.dispcnt.enable[ENABLE_WIN0] && window_flag_v[0] && window_flag_h[0]) win_layer_enable = mmio.winin.enable[0];
else if (mmio.dispcnt.enable[ENABLE_WIN1] && window_flag_v[1] && window_flag_h[1]) win_layer_enable = mmio.winin.enable[1];
else if (mmio.dispcnt.enable[ENABLE_OBJ] && mmio.dispcnt.enable[ENABLE_OBJWIN] && buffer_obj[x].window) win_layer_enable = mmio.winout.enable[1];
if (mmio.dispcnt.enable[ENABLE_WIN0] && window[0].flag_v && window[0].buffer[x]) win_layer_enable = mmio.winin.enable[0];
else if (mmio.dispcnt.enable[ENABLE_WIN1] && window[1].flag_v && window[1].buffer[x]) win_layer_enable = mmio.winin.enable[1];
else if (mmio.dispcnt.enable[ENABLE_OBJ] && mmio.dispcnt.enable[ENABLE_OBJWIN] && buffer_obj[x].window) win_layer_enable = mmio.winout.enable[1];
else win_layer_enable = mmio.winout.enable[0];
}

Expand Down
83 changes: 78 additions & 5 deletions src/nba/src/hw/ppu/ppu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ void PPU::Reset() {

mmio.winh[i].Reset();
mmio.winv[i].Reset();
window_flag_h[i] = false;
window_flag_v[i] = false;
window[i].last_sync_point = 0;
window[i].flag_h = false;
window[i].flag_v = false;
}

mmio.winin.Reset();
Expand Down Expand Up @@ -382,6 +383,11 @@ void PPU::SyncLineRender() {
}
}

for (int id = 0; id < 2; id++) {
// TODO: should we check if the window is enabled?
SyncWindow(id);
}

if (compose.engaged) {
SyncCompose(cycles);
}
Expand All @@ -392,10 +398,77 @@ void PPU::SyncLineRender() {
void PPU::UpdateWindows() {
int vcount = mmio.vcount;

for (int i = 0; i < 2; i++) {
if (vcount == mmio.winv[i].min) window_flag_v[i] = true;
if (vcount == mmio.winv[i].max) window_flag_v[i] = false;
// TODO: should we check if the window is enabled?
for (int id = 0; id < 2; id++) {
SyncWindow(id);

window[id].x = 0;
window[id].hcounter = 0;

if (vcount == mmio.winv[id].min) window[id].flag_v = true;
if (vcount == mmio.winv[id].max) window[id].flag_v = false;
}
}

void PPU::SyncWindow(int id) {
auto& window = this->window[id];

u64 sync_point = scheduler.GetTimestampNow();

int cycles = (int)(sync_point - window.last_sync_point);

// TODO: get rid of all the magic constants.
int hcounter_min = 48 + 4 * mmio.winh[id].min;
int hcounter_max = 48 + 4 * mmio.winh[id].max;
int hcounter_256 = 48 + 4 * 256;

int hcounter_sync[4] {
hcounter_min,
hcounter_max,
hcounter_256,
hcounter_256 + 1
};

if (hcounter_max < hcounter_min) {
std::swap(hcounter_sync[0], hcounter_sync[1]);
}

int hcounter = window.hcounter;
int hcounter_current = hcounter + cycles;
int hcounter_target = std::min(hcounter_current, hcounter_256);

window.hcounter = hcounter_current;

int x0 = window.x;

while (hcounter <= hcounter_target) {
bool active = window.flag_h;

if (hcounter == hcounter_min) window.flag_h = true;
if (hcounter == hcounter_max) window.flag_h = false;

for (int sync : hcounter_sync) {
if (hcounter == sync) {
int x1 = (hcounter - 48) >> 2;

// active &= window_flag_v[id];

for (int x = x0; x < x1; x++) {
window.buffer[x] = active;
}

x0 = x1;
}

if (hcounter < sync) {
hcounter = sync;
break;
}
}
}

window.x = x0;
window.last_sync_point = sync_point;
}

} // namespace nba::core
13 changes: 10 additions & 3 deletions src/nba/src/hw/ppu/ppu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ struct PPU {
auto Darken(u16 color) -> u16;
void RenderLayerOAM(bool bitmap_mode, int line);
void UpdateWindows();
void SyncWindow(int id);

#include "helper.inl"

Expand Down Expand Up @@ -272,6 +273,15 @@ struct PPU {
u32 buffer[256];
} bg[4];

struct Window {
int x;
int hcounter;
u64 last_sync_point;
bool flag_h;
bool flag_v;
bool buffer[256];
} window[2];

struct Compose {
bool engaged;
int x;
Expand All @@ -288,9 +298,6 @@ struct PPU {
unsigned mosaic : 1;
} buffer_obj[240];

bool window_flag_h[2];
bool window_flag_v[2];

bool pram_access;
bool vram_bg_access;

Expand Down

0 comments on commit b8b25c4

Please sign in to comment.