* WriteFrameToTextureMemory ****************************************************************************/
| 1113 | * WriteFrameToTextureMemory |
| 1114 | ****************************************************************************/ |
| 1115 | static void WriteFrameToTextureMemory(u8* srcBuffer, void* textureBase, int width, int height) |
| 1116 | { |
| 1117 | int borderWidth = InitialBorder ? InitialBorderWidth : width; |
| 1118 | int borderHeight = InitialBorder ? InitialBorderHeight : height; |
| 1119 | |
| 1120 | ProcessSGBBorder(srcBuffer, width, height); |
| 1121 | long long int* dst_ptr = DrawBorderAndGetDest(textureBase, width, height, borderWidth, borderHeight); |
| 1122 | |
| 1123 | int gbPitch = width * 2 + 4; |
| 1124 | int dst_gap_bytes = ((borderWidth - width) / 4) * 32; |
| 1125 | |
| 1126 | // Route to the statically optimized ASM based on console resolution width |
| 1127 | switch (width) { |
| 1128 | case 160: // GB / GBC (Pitch = 324) |
| 1129 | MakeTextureVBA_Impl<324>(srcBuffer, dst_ptr, width, height, dst_gap_bytes); |
| 1130 | break; |
| 1131 | case 240: // GBA (Pitch = 484) |
| 1132 | MakeTextureVBA_Impl<484>(srcBuffer, dst_ptr, width, height, dst_gap_bytes); |
| 1133 | break; |
| 1134 | case 256: // SGB (Pitch = 516) |
| 1135 | MakeTextureVBA_Impl<516>(srcBuffer, dst_ptr, width, height, dst_gap_bytes); |
| 1136 | break; |
| 1137 | default: // Fallback for custom borders/resolutions |
| 1138 | MakeTextureVBA_Dynamic(srcBuffer, dst_ptr, width, height, gbPitch, dst_gap_bytes); |
| 1139 | break; |
| 1140 | } |
| 1141 | |
| 1142 | // High-efficiency targeted data cache flushing |
| 1143 | if (InitialBorder && !borderJustChanged) { |
| 1144 | // Normal Frame: Flush ONLY the game screen cache lines (Saves ~87% bus bandwidth) |
| 1145 | u8* flush_ptr = (u8*)dst_ptr; |
| 1146 | u32 row_bytes = width * 8; // bytes per tile row for game screen |
| 1147 | u32 stride_bytes = borderWidth * 8; // full texture pitch stride bytes |
| 1148 | int tile_rows = height / 4; |
| 1149 | for (int i = 0; i < tile_rows; i++) { |
| 1150 | DCStoreRange(flush_ptr, row_bytes); |
| 1151 | flush_ptr += stride_bytes; |
| 1152 | } |
| 1153 | } else { |
| 1154 | // Flush everything if borderless, OR if the border was just copied this frame |
| 1155 | DCStoreRange(textureBase, borderWidth * borderHeight * 2); |
| 1156 | } |
| 1157 | } |
| 1158 | |
| 1159 | /**************************************************************************** |
| 1160 | * GX_Render |
no test coverage detected