找到了inline的漏网之鱼了,赶紧加上
This commit is contained in:
parent
5abde8b8c2
commit
27fc7c07df
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user