找到了inline的漏网之鱼了,赶紧加上

This commit is contained in:
root 2024-05-13 00:35:16 +08:00
parent 5abde8b8c2
commit 27fc7c07df

View File

@ -101,18 +101,18 @@ void PPU::DrawSpriteFetchOAM(uint cycle) {
auto& drawer_state = sprite.drawer_state[sprite.state_wr]; auto& drawer_state = sprite.drawer_state[sprite.state_wr];
const auto Submit = [&]() { // const auto Submit = [&]() {
// Swap the draw states and engage the drawer unit. // // Swap the draw states and engage the drawer unit.
sprite.state_rd ^= 1; // sprite.state_rd ^= 1;
sprite.state_wr ^= 1; // sprite.state_wr ^= 1;
sprite.drawing = true; // sprite.drawing = true;
// Start fetching the next OAM entry // // Start fetching the next OAM entry
oam_fetch.index++; // oam_fetch.index++;
oam_fetch.step = 0; // oam_fetch.step = 0;
oam_fetch.wait = oam_fetch.pending_wait; // oam_fetch.wait = oam_fetch.pending_wait;
oam_fetch.delay_wait = true; // oam_fetch.delay_wait = true;
}; // };
const int step = oam_fetch.step; const int step = oam_fetch.step;
@ -237,7 +237,16 @@ void PPU::DrawSpriteFetchOAM(uint cycle) {
if(drawer_state.affine) { if(drawer_state.affine) {
oam_fetch.step = 2; oam_fetch.step = 2;
} else { } else {
Submit(); //Submit();
sprite.state_rd ^= 1;
sprite.state_wr ^= 1;
sprite.drawing = true;
// Start fetching the next OAM entry
oam_fetch.index++;
oam_fetch.step = 0;
oam_fetch.wait = oam_fetch.pending_wait;
oam_fetch.delay_wait = true;
} }
break; break;
} }
@ -257,13 +266,52 @@ void PPU::DrawSpriteFetchOAM(uint cycle) {
drawer_state.texture_x = (drawer_state.matrix[0] * x0 + drawer_state.matrix[1] * y0) + (drawer_state.width << 7); drawer_state.texture_x = (drawer_state.matrix[0] * x0 + drawer_state.matrix[1] * y0) + (drawer_state.width << 7);
drawer_state.texture_y = (drawer_state.matrix[2] * x0 + drawer_state.matrix[3] * y0) + (drawer_state.height << 7); drawer_state.texture_y = (drawer_state.matrix[2] * x0 + drawer_state.matrix[3] * y0) + (drawer_state.height << 7);
Submit(); //Submit();
{
sprite.state_rd ^= 1;
sprite.state_wr ^= 1;
sprite.drawing = true;
// Start fetching the next OAM entry
oam_fetch.index++;
oam_fetch.step = 0;
oam_fetch.wait = oam_fetch.pending_wait;
oam_fetch.delay_wait = true;
}
} }
break; break;
} }
} }
} }
ALWAYS_INLINE auto CalculateTileNumber4BPP(int cond, uint base_tile, int width, int block_x, int block_y) -> uint {
// @todo: can the OAM mapping be changed mid-scanline? what would that do?
//if(mmio.dispcnt.oam_mapping_1d) {
if( cond ){
return (base_tile + block_y * ((uint)width >> 3) + block_x) & 0x3FFU;
}
return ((base_tile + (block_y << 5)) & 0x3E0U) | ((base_tile + block_x) & 0x1FU);
}
ALWAYS_INLINE auto CalculateTileNumber8BPP(int cond, uint base_tile, int width, int block_x, int block_y) -> uint {
// @todo: can the OAM mapping be changed mid-scanline? what would that do?
// if(mmio.dispcnt.oam_mapping_1d) {
if( cond ){
return (base_tile + block_y * ((uint)width >> 2) + (block_x << 1)) & 0x3FFU;
}
return ((base_tile + (block_y << 5)) & 0x3E0U) | (((base_tile & ~1) + (block_x << 1)) & 0x1FU);
}
ALWAYS_INLINE auto CalculateAddress4BPP(uint tile, int tile_x, int tile_y) -> uint {
return 0x10000U + (tile << 5) + (tile_y << 2) + (tile_x >> 1);
}
ALWAYS_INLINE auto CalculateAddress8BPP(uint tile, int tile_x, int tile_y) -> uint {
return 0x10000U + (tile << 5) + (tile_y << 3) + tile_x;
}
void PPU::DrawSpriteFetchVRAM(uint cycle) { void PPU::DrawSpriteFetchVRAM(uint cycle) {
if(!sprite.drawing) { if(!sprite.drawing) {
return; return;
@ -276,57 +324,58 @@ void PPU::DrawSpriteFetchVRAM(uint cycle) {
const uint base_tile = drawer_state.tile_number; const uint base_tile = drawer_state.tile_number;
const auto CalculateTileNumber4BPP = [&](int block_x, int block_y) -> uint { // 这五个函数可以inline也应该inline的用lambda是暴殄天物
// @todo: can the OAM mapping be changed mid-scanline? what would that do? // const auto CalculateTileNumber4BPP = [&](int block_x, int block_y) -> uint {
if(mmio.dispcnt.oam_mapping_1d) { // // @todo: can the OAM mapping be changed mid-scanline? what would that do?
return (base_tile + block_y * ((uint)width >> 3) + block_x) & 0x3FFU; // if(mmio.dispcnt.oam_mapping_1d) {
} // return (base_tile + block_y * ((uint)width >> 3) + block_x) & 0x3FFU;
// }
return ((base_tile + (block_y << 5)) & 0x3E0U) | ((base_tile + block_x) & 0x1FU); // return ((base_tile + (block_y << 5)) & 0x3E0U) | ((base_tile + block_x) & 0x1FU);
}; // };
const auto CalculateTileNumber8BPP = [&](int block_x, int block_y) -> uint { // const auto CalculateTileNumber8BPP = [&](int block_x, int block_y) -> uint {
// @todo: can the OAM mapping be changed mid-scanline? what would that do? // // @todo: can the OAM mapping be changed mid-scanline? what would that do?
if(mmio.dispcnt.oam_mapping_1d) { // if(mmio.dispcnt.oam_mapping_1d) {
return (base_tile + block_y * ((uint)width >> 2) + (block_x << 1)) & 0x3FFU; // return (base_tile + block_y * ((uint)width >> 2) + (block_x << 1)) & 0x3FFU;
} // }
return ((base_tile + (block_y << 5)) & 0x3E0U) | (((base_tile & ~1) + (block_x << 1)) & 0x1FU); // return ((base_tile + (block_y << 5)) & 0x3E0U) | (((base_tile & ~1) + (block_x << 1)) & 0x1FU);
}; // };
const auto CalculateAddress4BPP = [&](uint tile, int tile_x, int tile_y) -> uint { // const auto CalculateAddress4BPP = [&](uint tile, int tile_x, int tile_y) -> uint {
return 0x10000U + (tile << 5) + (tile_y << 2) + (tile_x >> 1); // return 0x10000U + (tile << 5) + (tile_y << 2) + (tile_x >> 1);
}; // };
const auto CalculateAddress8BPP = [&](uint tile, int tile_x, int tile_y) -> uint { // const auto CalculateAddress8BPP = [&](uint tile, int tile_x, int tile_y) -> uint {
return 0x10000U + (tile << 5) + (tile_y << 3) + tile_x; // return 0x10000U + (tile << 5) + (tile_y << 3) + tile_x;
}; // };
const auto Plot = [&](int x, uint color) { // const auto Plot = [&](int x, uint color) {
if(x < 0 || x >= 240) return; // if(x < 0 || x >= 240) return;
auto& pixel = sprite.buffer_wr[x]; // auto& pixel = sprite.buffer_wr[x];
const bool opaque = color != 0U; // const bool opaque = color != 0U;
const auto mode = drawer_state.mode; // const auto mode = drawer_state.mode;
const uint priority = drawer_state.priority; // const uint priority = drawer_state.priority;
/** // /**
* Transparent/outside OBJ window pixels are treated the same as // * Transparent/outside OBJ window pixels are treated the same as
* normal/semi-transparent sprite pixels, meaning that (unlike opaque/inside OBJ window pixels) they // * normal/semi-transparent sprite pixels, meaning that (unlike opaque/inside OBJ window pixels) they
* update the mosaic and priority attributes. // * update the mosaic and priority attributes.
*/ // */
if(mode == OBJ_WINDOW && opaque) { // if(mode == OBJ_WINDOW && opaque) {
pixel.window = 1; // pixel.window = 1;
} else if(priority < pixel.priority || pixel.color == 0U) { // } else if(priority < pixel.priority || pixel.color == 0U) {
if(opaque) { // if(opaque) {
pixel.color = color; // pixel.color = color;
pixel.alpha = (mode == OBJ_SEMI) ? 1U : 0U; // pixel.alpha = (mode == OBJ_SEMI) ? 1U : 0U;
} // }
pixel.mosaic = drawer_state.mosaic ? 1U : 0U; // pixel.mosaic = drawer_state.mosaic ? 1U : 0U;
pixel.priority = priority; // pixel.priority = priority;
} // }
}; // };
if(drawer_state.affine) { if(drawer_state.affine) {
if(sprite.oam_fetch.delay_wait) { if(sprite.oam_fetch.delay_wait) {
@ -336,8 +385,9 @@ void PPU::DrawSpriteFetchVRAM(uint cycle) {
const int texture_x = drawer_state.texture_x >> 8; const int texture_x = drawer_state.texture_x >> 8;
const int texture_y = drawer_state.texture_y >> 8; const int texture_y = drawer_state.texture_y >> 8;
if(texture_x >= 0 && texture_x < width && // if(texture_x >= 0 && texture_x < width &&
texture_y >= 0 && texture_y < height) { // texture_y >= 0 && texture_y < height) {
if( (texture_x | (width-1-texture_x) | texture_y | (height-1-texture_y) ) > 0 ){
const int tile_x = texture_x & 7; const int tile_x = texture_x & 7;
const int tile_y = texture_y & 7; const int tile_y = texture_y & 7;
@ -347,11 +397,11 @@ void PPU::DrawSpriteFetchVRAM(uint cycle) {
uint color_index = 0U; uint color_index = 0U;
if(drawer_state.is_256) { if(drawer_state.is_256) {
const uint tile = CalculateTileNumber8BPP(block_x, block_y); const uint tile = CalculateTileNumber8BPP(mmio.dispcnt.oam_mapping_1d, base_tile, width, block_x, block_y);
color_index = FetchVRAM_OBJ<u8>(cycle, CalculateAddress8BPP(tile, tile_x, tile_y)); color_index = FetchVRAM_OBJ<u8>(cycle, CalculateAddress8BPP(tile, tile_x, tile_y));
} else { } else {
const uint tile = CalculateTileNumber4BPP(block_x, block_y); const uint tile = CalculateTileNumber4BPP(mmio.dispcnt.oam_mapping_1d, base_tile, width, block_x, block_y);
const u8 data = FetchVRAM_OBJ<u8>(cycle, CalculateAddress4BPP(tile, tile_x, tile_y)); const u8 data = FetchVRAM_OBJ<u8>(cycle, CalculateAddress4BPP(tile, tile_x, tile_y));
if(tile_x & 1U) { if(tile_x & 1U) {
@ -365,7 +415,34 @@ void PPU::DrawSpriteFetchVRAM(uint cycle) {
} }
} }
Plot(drawer_state.draw_x, color_index); // Plot(drawer_state.draw_x, color_index);
{
auto x = drawer_state.draw_x;
auto color = color_index;
if( ( x | ((int)239-x) ) > 0 ) {
auto& pixel = sprite.buffer_wr[x];
const bool opaque = color != 0U;
const auto mode = drawer_state.mode;
const uint priority = drawer_state.priority;
/**
* Transparent/outside OBJ window pixels are treated the same as
* normal/semi-transparent sprite pixels, meaning that (unlike opaque/inside OBJ window pixels) they
* update the mosaic and priority attributes.
*/
if(mode == OBJ_WINDOW && opaque) {
pixel.window = 1;
} else if(priority < pixel.priority || pixel.color == 0U) {
if(opaque) {
pixel.color = color;
pixel.alpha = (mode == OBJ_SEMI) ? 1U : 0U;
}
pixel.mosaic = drawer_state.mosaic ? 1U : 0U;
pixel.priority = priority;
}
}
}
} }
drawer_state.draw_x++; drawer_state.draw_x++;
@ -389,7 +466,7 @@ void PPU::DrawSpriteFetchVRAM(uint cycle) {
uint color_indices[2] {0, 0}; uint color_indices[2] {0, 0};
if(drawer_state.is_256) { if(drawer_state.is_256) {
const uint tile = CalculateTileNumber8BPP(block_x, block_y); const uint tile = CalculateTileNumber8BPP(mmio.dispcnt.oam_mapping_1d, base_tile, width, block_x, block_y);
const u16 data = FetchVRAM_OBJ<u16>(cycle, CalculateAddress8BPP(tile, tile_x, tile_y)); const u16 data = FetchVRAM_OBJ<u16>(cycle, CalculateAddress8BPP(tile, tile_x, tile_y));
if(flip_h) { if(flip_h) {
@ -402,7 +479,7 @@ void PPU::DrawSpriteFetchVRAM(uint cycle) {
palette = 0U; palette = 0U;
} else { } else {
const uint tile = CalculateTileNumber4BPP(block_x, block_y); const uint tile = CalculateTileNumber4BPP(mmio.dispcnt.oam_mapping_1d, base_tile, width, block_x, block_y);
const u8 data = FetchVRAM_OBJ<u8>(cycle, CalculateAddress4BPP(tile, tile_x, tile_y)); const u8 data = FetchVRAM_OBJ<u8>(cycle, CalculateAddress4BPP(tile, tile_x, tile_y));
if(flip_h) { if(flip_h) {
@ -423,7 +500,35 @@ void PPU::DrawSpriteFetchVRAM(uint cycle) {
color_index |= palette; color_index |= palette;
} }
Plot(drawer_state.draw_x++, color_index); //Plot(drawer_state.draw_x++, color_index);
{
auto x = drawer_state.draw_x++;
auto color = color_index;
if( ( x | ((int)239-x) ) > 0 ) {
auto& pixel = sprite.buffer_wr[x];
const bool opaque = color != 0U;
const auto mode = drawer_state.mode;
const uint priority = drawer_state.priority;
/**
* Transparent/outside OBJ window pixels are treated the same as
* normal/semi-transparent sprite pixels, meaning that (unlike opaque/inside OBJ window pixels) they
* update the mosaic and priority attributes.
*/
if(mode == OBJ_WINDOW && opaque) {
pixel.window = 1;
} else if(priority < pixel.priority || pixel.color == 0U) {
if(opaque) {
pixel.color = color;
pixel.alpha = (mode == OBJ_SEMI) ? 1U : 0U;
}
pixel.mosaic = drawer_state.mosaic ? 1U : 0U;
pixel.priority = priority;
}
}
}
} }
drawer_state.texture_x += 2; drawer_state.texture_x += 2;