Skip to content
This repository has been archived by the owner on Sep 11, 2023. It is now read-only.

New feature for HD Pack #111

Merged
merged 4 commits into from
Jul 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 40 additions & 2 deletions Core/HdData.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,9 @@ struct HdPpuPixelInfo
{
HdPpuTileInfo Tile;
vector<HdPpuTileInfo> Sprite;
vector<HdPpuTileInfo> SprAddition;
int SpriteCount;

uint16_t TmpVideoRamAddr;
uint8_t XScroll;
uint8_t EmphasisBits;
Expand All @@ -110,7 +111,8 @@ struct HdPpuPixelInfo
{
for(int i = 0; i < 4; i++) {
Sprite.push_back(HdPpuTileInfo());
}
SprAddition.push_back(HdPpuTileInfo());
}
}
};

Expand Down Expand Up @@ -141,6 +143,7 @@ struct HdSpriteFrameRangeInfo
struct HdScreenInfo
{
HdPpuPixelInfo* ScreenTiles;
uint8_t AdditionCount[PPU::PixelCount];
std::unordered_map<uint32_t, uint8_t> WatchedAddressValues;
uint32_t FrameNumber;
HdSpriteFrameRangeInfo* spriteFrameRanges;
Expand Down Expand Up @@ -318,6 +321,40 @@ struct HdPackTileInfo : public HdTileKey
}
};

struct HdPackAdditionInfo : public HdTileKey
{
int16_t OffsetX;
int16_t OffsetY;
HdTileKey additionSpr;

string ToString(int pngIndex)
{
stringstream out;
out << "<tile>" << pngIndex << ",";
if (IsChrRamTile) {
for (int i = 0; i < 16; i++) {
out << HexUtilities::ToHex(TileData[i]);
}
}
else {
out << HexUtilities::ToHex(TileIndex);
}
out << "," << HexUtilities::ToHex(PaletteColors, true) << "," <<
OffsetX << "," <<
OffsetY << ",";
if (IsChrRamTile) {
for (int i = 0; i < 16; i++) {
out << HexUtilities::ToHex(additionSpr.TileData[i]);
}
}
else {
out << HexUtilities::ToHex(additionSpr.TileIndex);
}
out << "," << HexUtilities::ToHex(PaletteColors, true);
return out.str();
}
};

struct HdPackBitmapInfo
{
vector<uint32_t> PixelData;
Expand Down Expand Up @@ -388,6 +425,7 @@ struct HdPackData
vector<unique_ptr<HdBackgroundFileData>> BackgroundFileData;
vector<unique_ptr<HdPackTileInfo>> Tiles;
vector<unique_ptr<HdPackCondition>> Conditions;
vector<unique_ptr<HdPackAdditionInfo>> Additions;
std::unordered_set<uint32_t> WatchedMemoryAddresses;
std::unordered_map<HdTileKey, vector<HdPackTileInfo*>> TileByKey;
std::unordered_map<string, string> PatchesByHash;
Expand Down
25 changes: 25 additions & 0 deletions Core/HdNesPack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ void HdNesPack::GetPixels(uint32_t x, uint32_t y, HdPpuPixelInfo &pixelInfo, uin
HdPackTileInfo *hdPackSpriteInfo = nullptr;

bool hasSprite = pixelInfo.SpriteCount > 0;
uint8_t additionCount = (_hdData->Additions.size() > 0 ? _hdScreenInfo->AdditionCount[y * 256 + x] : 0);
bool renderOriginalTiles = ((_hdData->OptionFlags & (int)HdPackOptions::DontRenderOriginalTiles) == 0);
if(pixelInfo.Tile.TileIndex != HdPpuTileInfo::NoTile) {
hdPackTileInfo = GetCachedMatchingTile(x, y, &pixelInfo.Tile);
Expand All @@ -394,6 +395,17 @@ void HdNesPack::GetPixels(uint32_t x, uint32_t y, HdPpuPixelInfo &pixelInfo, uin
DrawBackgroundLayer(HdNesPack::BehindBgSpritesPriority+i, x, y, outputBuffer, screenWidth);
}

if (additionCount > 0) {
for (int k = additionCount - 1; k >= 0; k--) {
if (pixelInfo.SprAddition[k].BackgroundPriority) {
hdPackSpriteInfo = GetMatchingTile(x, y, &pixelInfo.SprAddition[k]);
if (hdPackSpriteInfo) {
DrawSpriteTile(pixelInfo.SprAddition[k], *hdPackSpriteInfo, outputBuffer, screenWidth, k);
}
}
}
}

if(hasSprite) {
for(int k = pixelInfo.SpriteCount - 1; k >= 0; k--) {
if(pixelInfo.Sprite[k].BackgroundPriority) {
Expand Down Expand Up @@ -424,6 +436,19 @@ void HdNesPack::GetPixels(uint32_t x, uint32_t y, HdPpuPixelInfo &pixelInfo, uin
DrawBackgroundLayer(HdNesPack::BehindFgSpritesPriority+i, x, y, outputBuffer, screenWidth);
}


if (additionCount > 0) {
for (int k = additionCount - 1; k >= 0; k--) {
if (!pixelInfo.SprAddition[k].BackgroundPriority) {
hdPackSpriteInfo = GetMatchingTile(x, y, &pixelInfo.SprAddition[k]);
if (hdPackSpriteInfo) {
DrawSpriteTile(pixelInfo.SprAddition[k], *hdPackSpriteInfo, outputBuffer, screenWidth, k);
}
}
}
}


if(hasSprite) {
for(int k = pixelInfo.SpriteCount - 1; k >= 0; k--) {
if(!pixelInfo.Sprite[k].BackgroundPriority) {
Expand Down
41 changes: 41 additions & 0 deletions Core/HdPackLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,10 @@ bool HdPackLoader::LoadPack()
tokens = StringUtilities::Split(lineContent.substr(5), ',');
convertPathToNativeVector(tokens, 2);
ProcessSfxTag(tokens);
} else if (lineContent.substr(0, 10) == "<addition>") {
tokens = StringUtilities::Split(lineContent.substr(10), ',');
convertPathToNativeVector(tokens, 2);
ProcessAdditionTag(tokens);
}
}
MessageManager::DisplayMessage("Pack Loader", std::to_string(lineCnt) + " lines processed in total");
Expand Down Expand Up @@ -458,6 +462,43 @@ void HdPackLoader::ProcessOptionTag(vector<string> &tokens)
}
}

void HdPackLoader::ProcessAdditionTag(vector<string>& tokens)
{
HdPackAdditionInfo* additionInfo = new HdPackAdditionInfo();
size_t index = 0;
string tileData = tokens[index++];
if (tileData.size() >= 32) {
//CHR RAM tile, read the tile data
for (int i = 0; i < 16; i++) {
additionInfo->TileData[i] = HexUtilities::FromHex(tileData.substr(i * 2, 2));
}
additionInfo->IsChrRamTile = true;
additionInfo->TileIndex = -1;
}
else {
additionInfo->TileIndex = HexUtilities::FromHex(tileData);
additionInfo->IsChrRamTile = false;
}
additionInfo->PaletteColors = HexUtilities::FromHex(tokens[index++]);

additionInfo->OffsetX = std::stoi(tokens[index++]);
additionInfo->OffsetY = std::stoi(tokens[index++]);

string addTileData = tokens[index++];
if (addTileData.size() >= 32) {
//CHR RAM tile, read the tile data
for (int i = 0; i < 16; i++) {
additionInfo->additionSpr.TileData[i] = HexUtilities::FromHex(addTileData.substr(i * 2, 2));
}
}
else {
additionInfo->additionSpr.TileIndex = HexUtilities::FromHex(addTileData);
}
additionInfo->additionSpr.PaletteColors = HexUtilities::FromHex(tokens[index++]);

_data->Additions.push_back(unique_ptr<HdPackAdditionInfo>(additionInfo));
}

void HdPackLoader::ProcessConditionTag(vector<string> &tokens, bool createInvertedCondition)
{
checkConstraint(tokens.size() >= 4, "[HDPack] Condition tag should contain at least 4 parameters");
Expand Down
1 change: 1 addition & 0 deletions Core/HdPackLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class HdPackLoader
void ProcessTileTag(vector<string> &tokens, vector<HdPackCondition*> conditions);
void ProcessBackgroundTag(vector<string> &tokens, vector<HdPackCondition*> conditions);
void ProcessOptionTag(vector<string>& tokens);
void ProcessAdditionTag(vector<string>& tokens);

//Audio
int ProcessSoundTrack(string albumString, string trackString, string filename);
Expand Down
43 changes: 42 additions & 1 deletion Core/HdPpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ void HdPpu::DrawPixel()
uint16_t &pixel = _currentOutputBuffer[bufferOffset];
_lastSprite = nullptr;

//init sprite frame ranges at screen start
if (bufferOffset == 0) {
//init sprite frame ranges at screen start
uint8_t spriteCnt = (_flags.LargeSprites ? 128 : 64);
for (int i = 0; i < spriteCnt; i++) {
_spriteFrameRanges[i].lastUpdated = _spriteFrameRanges[i].updated;
Expand All @@ -28,6 +28,11 @@ void HdPpu::DrawPixel()
_spriteFrameRanges[i].lastStartFrameNumber = _spriteFrameRanges[i].startFrameNumber;
}
}

//init sprite addition counter
if (_hdData->Additions.size() > 0) {
memset(_info->AdditionCount, 0, PPU::PixelCount);
}
}

if(IsRenderingEnabled() || ((_state.VideoRamAddr & 0x3F00) != 0x3F00)) {
Expand Down Expand Up @@ -119,6 +124,42 @@ void HdPpu::DrawPixel()
_spriteFrameRanges[tileInfo.Sprite[j].OAMIndex].updated = true;
}

//check for valid addition
for (uint8_t k = 0; k < _hdData->Additions.size(); k++) {
if (*(_hdData->Additions[k]) == tileInfo.Sprite[j]) {
int16_t addX = _cycle + (tileInfo.Sprite[j].HorizontalMirroring ? -_hdData->Additions[k]->OffsetX : _hdData->Additions[k]->OffsetX) - 1;
int16_t addY = _scanline + (tileInfo.Sprite[j].VerticalMirroring ? -_hdData->Additions[k]->OffsetY : _hdData->Additions[k]->OffsetY);
if (addX >= 0 && addX < 256 && addY >= 0 && addY < 240) {
uint16_t addBufferOffset = (addY << 8) + addX;
HdPpuPixelInfo& addTileInfo = _info->ScreenTiles[addBufferOffset];
uint8_t insertIdx = _info->AdditionCount[addBufferOffset];
for (int8_t l = _info->AdditionCount[addBufferOffset] - 1; l >=0; l--) {
if (addTileInfo.SprAddition[l].OAMIndex >= sprite.OAMIndex) {
if (l < 3) {
//shift back item
addTileInfo.SprAddition[l + 1] = addTileInfo.SprAddition[l];
}
insertIdx = l;
}
}
if (insertIdx < 4) {
addTileInfo.SprAddition[insertIdx] = tileInfo.Sprite[j];
addTileInfo.SprAddition[insertIdx].PaletteColors = _hdData->Additions[k]->additionSpr.PaletteColors;
if (isChrRam) {
memcpy(addTileInfo.SprAddition[insertIdx].TileData, _hdData->Additions[k]->additionSpr.TileData, 16);
}
else {
addTileInfo.SprAddition[insertIdx].TileIndex = _hdData->Additions[k]->additionSpr.TileIndex;
}
addTileInfo.SprAddition[insertIdx].OAMIndex = sprite.OAMIndex;
if (_info->AdditionCount[addBufferOffset] < 4) {
_info->AdditionCount[addBufferOffset]++;
}
}
}
}
}

j++;
if(j >= 4) {
break;
Expand Down
14 changes: 14 additions & 0 deletions Docs/content/hdpacks/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,20 @@ The `tile data` and `palette data` are used to identify the original tile, while
`brightness` can be used to reuse the same HD tile for multiple original tiles -- this can be useful when a game has fade in and out effects (the brightness can be set to values above 1.0 to increase the PNG's normal brightness level).
When `default tile` is enabled (with `Y`), the tile is marked as the `default tile` for all palettes. Whenever a tile appears on the screen that matches the tile data, but has no rules matching its palette data, the default tile will be used instead.


### &lt;addition&gt; tag ###

**Syntax**: `<addition>[tile data], [palette data], [distance x - integer], [distance y - integer], [additional tile data], [additional palette data]`
**Example (CHR ROM)**: `<addition>2E,FF16360F,12,-10,FF,FF000000`
**Example (CHR RAM)**: `<addition>0E0E079C1E3EA7076101586121010000,0F100017,0,30,00000000000000000000000000000000,FF123456`

For CHR ROM games, `tile data` is an integer (in hexadecimal) representing the position of the original tile in CHR ROM.
For CHR RAM games, `tile data` is a 32-character hexadecimal string representing all 16 bytes of the tile.
`palette data` is always an 8-character hexadecimal string representing all 4 bytes of the palette used for the tile. For sprites, the first byte is always "FF".

`<addition>` define one additional tile to be shown when a matching sprite tile is found. The `distance x` and `distance y` parameters define where it will be shown. The `additional tile data` and `additional palette data` parameters define how the additional tile is identified. The tile can only be shown by using `<tile>` tag to specify the replacement.


### &lt;background&gt; tag ###

**Syntax**: `<background>[name - text], [brightness level - float (default: 1.0)], [horizontal scroll ratio (optional) - float], [vertical scroll ratio (optional) - float], [priority level (optional) - int, 0 to 39 (default 10)], [image left offset (optional) - int], [image top offset (optional) - int]`
Expand Down
14 changes: 7 additions & 7 deletions Libretro/libretro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,27 +384,27 @@ extern "C" {
_console->GetSettings()->SetVideoFilterType(VideoFilterType::None);
} else if(value == "Composite (Blargg)") {
_console->GetSettings()->SetVideoFilterType(VideoFilterType::NTSC);
_console->GetSettings()->SetNtscFilterSettings(0, 0, 0, 0, 0, 0, false, 0, 0, 0, false, true);
_console->GetSettings()->SetNtscFilterSettings(0, 0, 0, 0, 0, 0, false, 0, 0, 0, false, true, true);
} else if(value == "S-Video (Blargg)") {
_console->GetSettings()->SetVideoFilterType(VideoFilterType::NTSC);
_console->GetSettings()->SetNtscFilterSettings(-1.0, 0, -1.0, 0, 0.2, 0.2, false, 0, 0, 0, false, true);
_console->GetSettings()->SetNtscFilterSettings(-1.0, 0, -1.0, 0, 0.2, 0.2, false, 0, 0, 0, false, true, true);
} else if(value == "RGB (Blargg)") {
_console->GetSettings()->SetVideoFilterType(VideoFilterType::NTSC);
_console->GetSettings()->SetPictureSettings(0, 0, 0, 0, 0);
_console->GetSettings()->SetNtscFilterSettings(-1.0, -1.0, -1.0, 0, 0.7, 0.2, false, 0, 0, 0, false, true);
_console->GetSettings()->SetNtscFilterSettings(-1.0, -1.0, -1.0, 0, 0.7, 0.2, false, 0, 0, 0, false, true, true);
} else if(value == "Monochrome (Blargg)") {
_console->GetSettings()->SetVideoFilterType(VideoFilterType::NTSC);
_console->GetSettings()->SetPictureSettings(0, 0, -1.0, 0, 0);
_console->GetSettings()->SetNtscFilterSettings(-0.2, -0.1, -0.2, 0, 0.7, 0.2, false, 0, 0, 0, false, true);
_console->GetSettings()->SetNtscFilterSettings(-0.2, -0.1, -0.2, 0, 0.7, 0.2, false, 0, 0, 0, false, true, true);
} else if(value == "Bisqwit 2x") {
_console->GetSettings()->SetVideoFilterType(VideoFilterType::BisqwitNtscQuarterRes);
_console->GetSettings()->SetNtscFilterSettings(0, 0, 0, 0, 0, 0, false, 0, 0, 0, false, true);
_console->GetSettings()->SetNtscFilterSettings(0, 0, 0, 0, 0, 0, false, 0, 0, 0, false, true, true);
} else if(value == "Bisqwit 4x") {
_console->GetSettings()->SetVideoFilterType(VideoFilterType::BisqwitNtscHalfRes);
_console->GetSettings()->SetNtscFilterSettings(0, 0, 0, 0, 0, 0, false, 0, 0, 0, false, true);
_console->GetSettings()->SetNtscFilterSettings(0, 0, 0, 0, 0, 0, false, 0, 0, 0, false, true, true);
} else if(value == "Bisqwit 8x") {
_console->GetSettings()->SetVideoFilterType(VideoFilterType::BisqwitNtsc);
_console->GetSettings()->SetNtscFilterSettings(0, 0, 0, 0, 0, 0, false, 0, 0, 0, false, true);
_console->GetSettings()->SetNtscFilterSettings(0, 0, 0, 0, 0, 0, false, 0, 0, 0, false, true, true);
}
}

Expand Down