mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-02-23 22:52:34 +01:00
byuu says: This WIP removes nall/input.hpp entirely, and implements the new universal cheat format for FC/SFC/GB/GBC/SGB. GBA is going to be tricky since there's some consternation around byte/word/dword overrides. It's also not immediately obvious to me how to implement the code search in logarithmic time, due to the optional compare value. Lastly, the cheat values inside cheats.bml seem to be broken for the SFC. Likely there's a bug somewhere in the conversion process. Obviously I'll have to fix that before v094. I received no feedback on the universal cheat format. If nobody adds anything before v094, then I don't want to hear any complaining about the formatting :P
96 lines
3.3 KiB
C++
96 lines
3.3 KiB
C++
#ifndef NALL_IMAGE_UTILITY_HPP
|
|
#define NALL_IMAGE_UTILITY_HPP
|
|
|
|
namespace nall {
|
|
|
|
bool image::crop(unsigned outputX, unsigned outputY, unsigned outputWidth, unsigned outputHeight) {
|
|
if(outputX + outputWidth > width) return false;
|
|
if(outputY + outputHeight > height) return false;
|
|
|
|
uint8_t* outputData = allocate(outputWidth, outputHeight, stride);
|
|
unsigned outputPitch = outputWidth * stride;
|
|
|
|
#pragma omp parallel for
|
|
for(unsigned y = 0; y < outputHeight; y++) {
|
|
const uint8_t* sp = data + pitch * (outputY + y) + stride * outputX;
|
|
uint8_t* dp = outputData + outputPitch * y;
|
|
for(unsigned x = 0; x < outputWidth; x++) {
|
|
write(dp, read(sp));
|
|
sp += stride;
|
|
dp += stride;
|
|
}
|
|
}
|
|
|
|
delete[] data;
|
|
data = outputData;
|
|
width = outputWidth;
|
|
height = outputHeight;
|
|
pitch = outputPitch;
|
|
size = width * pitch;
|
|
return true;
|
|
}
|
|
|
|
void image::alphaBlend(uint64_t alphaColor) {
|
|
uint64_t alphaR = (alphaColor & red.mask ) >> red.shift;
|
|
uint64_t alphaG = (alphaColor & green.mask) >> green.shift;
|
|
uint64_t alphaB = (alphaColor & blue.mask ) >> blue.shift;
|
|
|
|
#pragma omp parallel for
|
|
for(unsigned y = 0; y < height; y++) {
|
|
uint8_t* dp = data + pitch * y;
|
|
for(unsigned x = 0; x < width; x++) {
|
|
uint64_t color = read(dp);
|
|
|
|
uint64_t colorA = (color & alpha.mask) >> alpha.shift;
|
|
uint64_t colorR = (color & red.mask ) >> red.shift;
|
|
uint64_t colorG = (color & green.mask) >> green.shift;
|
|
uint64_t colorB = (color & blue.mask ) >> blue.shift;
|
|
double alphaScale = (double)colorA / (double)((1 << alpha.depth) - 1);
|
|
|
|
colorA = (1 << alpha.depth) - 1;
|
|
colorR = (colorR * alphaScale) + (alphaR * (1.0 - alphaScale));
|
|
colorG = (colorG * alphaScale) + (alphaG * (1.0 - alphaScale));
|
|
colorB = (colorB * alphaScale) + (alphaB * (1.0 - alphaScale));
|
|
|
|
write(dp, (colorA << alpha.shift) | (colorR << red.shift) | (colorG << green.shift) | (colorB << blue.shift));
|
|
dp += stride;
|
|
}
|
|
}
|
|
}
|
|
|
|
void image::transform(bool outputEndian, unsigned outputDepth, uint64_t outputAlphaMask, uint64_t outputRedMask, uint64_t outputGreenMask, uint64_t outputBlueMask) {
|
|
if(endian == outputEndian && depth == outputDepth && alpha.mask == outputAlphaMask && red.mask == outputRedMask && green.mask == outputGreenMask && blue.mask == outputBlueMask) return;
|
|
|
|
image output(outputEndian, outputDepth, outputAlphaMask, outputRedMask, outputGreenMask, outputBlueMask);
|
|
output.allocate(width, height);
|
|
|
|
#pragma omp parallel for
|
|
for(unsigned y = 0; y < height; y++) {
|
|
const uint8_t* sp = data + pitch * y;
|
|
uint8_t* dp = output.data + output.pitch * y;
|
|
for(unsigned x = 0; x < width; x++) {
|
|
uint64_t color = read(sp);
|
|
sp += stride;
|
|
|
|
uint64_t a = (color & alpha.mask) >> alpha.shift;
|
|
uint64_t r = (color & red.mask) >> red.shift;
|
|
uint64_t g = (color & green.mask) >> green.shift;
|
|
uint64_t b = (color & blue.mask) >> blue.shift;
|
|
|
|
a = normalize(a, alpha.depth, output.alpha.depth);
|
|
r = normalize(r, red.depth, output.red.depth);
|
|
g = normalize(g, green.depth, output.green.depth);
|
|
b = normalize(b, blue.depth, output.blue.depth);
|
|
|
|
output.write(dp, (a << output.alpha.shift) | (r << output.red.shift) | (g << output.green.shift) | (b << output.blue.shift));
|
|
dp += output.stride;
|
|
}
|
|
}
|
|
|
|
operator=(std::move(output));
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|