From bcab6bde9fc6fd09d3a25628d6872f44a1b04505 Mon Sep 17 00:00:00 2001 From: Chen Yifeng <648616375@qq.com> Date: Sun, 10 Jul 2022 19:00:57 +0800 Subject: [PATCH 1/4] some broken code cannot work --- Dialog/GraphicManagerDialog.cpp | 91 ++++++++++++++++++++++++--------- FileIOUtils.cpp | 60 ++++++++++++++++++++++ FileIOUtils.h | 1 + 3 files changed, 128 insertions(+), 24 deletions(-) diff --git a/Dialog/GraphicManagerDialog.cpp b/Dialog/GraphicManagerDialog.cpp index 7701b9c9..b735f1a6 100644 --- a/Dialog/GraphicManagerDialog.cpp +++ b/Dialog/GraphicManagerDialog.cpp @@ -554,25 +554,27 @@ void GraphicManagerDialog::DeltmpEntryTile(int tileId) } QByteArray data; int old_tilenum = tmpEntry.TileDataSizeInByte / 32; - data = tmpEntry.tileData.mid(0, 32 * (tileId - startid)) + - tmpEntry.tileData.mid(32 * (tileId + 1 - startid), 32 * (old_tilenum + startid - tileId - 1)); + data = tmpEntry.tileData.left(32 * (tileId - startid)) + tmpEntry.tileData.right(32 * (old_tilenum + startid - tileId - 1)); tmpEntry.tileData = data; tmpEntry.TileDataRAMOffsetNum += 1; tmpEntry.TileDataSizeInByte -= 32; // update mapping data - int width = tmpEntry.optionalGraphicWidth; - for (int h = 0; h < tmpEntry.optionalGraphicHeight; h++) + for (int w = 0; w < tmpEntry.mappingData.size(); w++) { - for (int w = 0; w < width; w++) + unsigned short data = tmpEntry.mappingData[w]; + unsigned short id = data & 0x3FF; + if (id < tileId) { - unsigned short data = tmpEntry.mappingData[w + h * width]; - int id = data & 0x3FF; - if ((tmpEntry.mappingData[w + h * width] & 0x3FF) <= tileId) - { - tmpEntry.mappingData[w + h * width] = (data & 0xFC00) | ((id + 1) & 0x3FF); - } + tmpEntry.mappingData[w] = (data & 0xFC00) | ((id + 1) & 0x3FF); + } + else if (id == tileId) + { + // something went wrong in the previous code + // there should be no existance of the current tile when calling this function + // we just set it to use the default 0x3FF Tile8x8 and use the palette 0xF + tmpEntry.mappingData[w] = 0xF000 | 0x3FF; } } @@ -1558,46 +1560,86 @@ void GraphicManagerDialog::on_pushButton_ReduceTiles_clicked() int result2 = FileIOUtils::quasi_memcmp(newtmpYFlipdata, tile_data, 32); int result3 = FileIOUtils::quasi_memcmp(newtmpXYFlipdata, tile_data, 32); bool find_eqaul = false; - int tileid = j + constoffset; + int find_tileid = j + constoffset; + + int reserved_tileid = find_tileid; + int discard_tileid = old_tileid; + + int x_flip = 0; + int y_flip = 0; unsigned short mappingdata; if (result0 <= diff_upbound) { find_eqaul = true; - mappingdata = 0xF << 12 | (0 << 11) | (0 << 10) | (tileid & 0x3FF); + if (newtmpdata == FileIOUtils::find_less_feature_buff(newtmpdata, tile_data, 32)) + { + reserved_tileid = old_tileid; + discard_tileid = find_tileid; + } } else if (result1 <= diff_upbound) { find_eqaul = true; - mappingdata = 0xF << 12 | (0 << 11) | (1 << 10) | (tileid & 0x3FF); + if (newtmpXFlipdata == FileIOUtils::find_less_feature_buff(newtmpXFlipdata, tile_data, 32)) + { + reserved_tileid = old_tileid; + discard_tileid = find_tileid; + } + x_flip = 1 << 10; } else if (result2 <= diff_upbound) { find_eqaul = true; - mappingdata = 0xF << 12 | (1 << 11) | (0 << 10) | (tileid & 0x3FF); + if (newtmpYFlipdata == FileIOUtils::find_less_feature_buff(newtmpYFlipdata, tile_data, 32)) + { + reserved_tileid = old_tileid; + discard_tileid = find_tileid; + } + y_flip = 1 << 11; } else if (result3 <= diff_upbound) { find_eqaul = true; - mappingdata = 0xF << 12 | (1 << 11) | (1 << 10) | (tileid & 0x3FF); + if (newtmpXYFlipdata == FileIOUtils::find_less_feature_buff(newtmpXYFlipdata, tile_data, 32)) + { + reserved_tileid = old_tileid; + discard_tileid = find_tileid; + } + x_flip = 1 << 10; + y_flip = 1 << 11; } if (find_eqaul) { - int width = tmpEntry.optionalGraphicWidth; - for (int h = 0; h < tmpEntry.optionalGraphicHeight; h++) + for (int w = 0; w < tmpEntry.mappingData.size(); w++) { - for (int w = 0; w < width; w++) + if ((tmpEntry.mappingData[w] & 0x3FF) == discard_tileid) { - if ((tmpEntry.mappingData[w + h * width] & 0x3FF) == old_tileid) - { - tmpEntry.mappingData[w + h * width] = mappingdata; - } + int old_x_flip_state = tmpEntry.mappingData[w] & (1 << 10); + int old_y_flip_state = tmpEntry.mappingData[w] & (1 << 11); + mappingdata = 0xF << 12 | + (y_flip ^ old_y_flip_state) | + (x_flip ^ old_x_flip_state) | + (reserved_tileid & 0x3FF); + tmpEntry.mappingData[w] = mappingdata; + } + } + + // change the tmp_current_tile8x8_data + if (reserved_tileid == old_tileid) + { + memcpy(&tmp_current_tile8x8_data[32 * j], newtmpdata, 32); + + int startid = tmpEntry.TileDataRAMOffsetNum; + for (int k = 0; k < 32; k++) + { + tmpEntry.tileData[32 * (reserved_tileid - startid) + k] = newtmpdata[k]; } } // delete the Tile8x8 from the Tile8x8 set - DeltmpEntryTile(old_tileid); + DeltmpEntryTile(discard_tileid); break; } } @@ -1608,6 +1650,7 @@ void GraphicManagerDialog::on_pushButton_ReduceTiles_clicked() // set tmpEntry if everything looks correct tmpEntry.TileDataAddress = 0; tmpEntry.MappingDataAddress = 0; + tmpEntry.MappingDataSizeAfterCompressionInByte = 0; // UI reset CleanTilesInstances(); diff --git a/FileIOUtils.cpp b/FileIOUtils.cpp index c76f46ac..b1480a2f 100644 --- a/FileIOUtils.cpp +++ b/FileIOUtils.cpp @@ -542,3 +542,63 @@ int FileIOUtils::quasi_memcmp(unsigned char *_Buf1, unsigned char *_Buf2, size_t } return diff_counter; } + +/// +/// find the Tile8x8 data with less features by any means +/// +/// +/// The pointer point to the first buff. +/// +/// +/// The pointer point to the second buff. +/// +/// +/// The byte number to compare. +/// +/// +/// the different byte number. +/// +unsigned char *FileIOUtils::find_less_feature_buff(unsigned char *_Buf1, unsigned char *_Buf2, size_t _Size) +{ + // test method, find the buff changed less time thru the whole data array + size_t change_counter_1 = 0; + size_t change_counter_2 = 0; + unsigned char last_id_1 = -1; + unsigned char last_id_2 = -1; + for (size_t i = 0; i < _Size; i++) + { + // process buff 1 + if (unsigned char cur_id = ((_Buf1[i] & 0xF0) >> 4) & 0xF; last_id_1 != cur_id) + { + last_id_1 = cur_id; + change_counter_1++; + } + if (unsigned char cur_id = _Buf1[i] & 0xF; last_id_1 != cur_id) + { + last_id_1 = cur_id; + change_counter_1++; + } + + // process buff 2 + if (unsigned char cur_id = ((_Buf2[i] & 0xF0) >> 4) & 0xF; last_id_2 != cur_id) + { + last_id_2 = cur_id; + change_counter_2++; + } + if (unsigned char cur_id = _Buf2[i] & 0xF; last_id_2 != cur_id) + { + last_id_2 = cur_id; + change_counter_2++; + } + } + + // return the buff pointer with less changed time in pixel index + if (change_counter_1 >= change_counter_2) + { + return _Buf2; + } + else + { + return _Buf1; + } +} diff --git a/FileIOUtils.h b/FileIOUtils.h index eed0565c..3392b131 100644 --- a/FileIOUtils.h +++ b/FileIOUtils.h @@ -21,6 +21,7 @@ namespace FileIOUtils // helper functions int quasi_memcmp(unsigned char *_Buf1, unsigned char *_Buf2, size_t _Size); + unsigned char *find_less_feature_buff(unsigned char *_Buf1, unsigned char *_Buf2, size_t _Size); } // namespace FileIOUtils #endif // FILEIOUTILS_H From f33e7be1d00d1559a117688bc8bd059b13a7f702 Mon Sep 17 00:00:00 2001 From: Chen Yifeng <648616375@qq.com> Date: Mon, 11 Jul 2022 08:40:44 +0800 Subject: [PATCH 2/4] several bugfixes to the aggressive tile reduce logic in Graphic Manager --- Dialog/GraphicManagerDialog.cpp | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/Dialog/GraphicManagerDialog.cpp b/Dialog/GraphicManagerDialog.cpp index b735f1a6..2cec33fe 100644 --- a/Dialog/GraphicManagerDialog.cpp +++ b/Dialog/GraphicManagerDialog.cpp @@ -1,4 +1,4 @@ -#include "GraphicManagerDialog.h" +#include "GraphicManagerDialog.h" #include "ui_GraphicManagerDialog.h" #include @@ -571,7 +571,7 @@ void GraphicManagerDialog::DeltmpEntryTile(int tileId) } else if (id == tileId) { - // something went wrong in the previous code + // something went wrong in the previous code if this part of code gets executed // there should be no existance of the current tile when calling this function // we just set it to use the default 0x3FF Tile8x8 and use the palette 0xF tmpEntry.mappingData[w] = 0xF000 | 0x3FF; @@ -1521,9 +1521,10 @@ void GraphicManagerDialog::on_pushButton_ReduceTiles_clicked() bool ok; int diff_upbound = QInputDialog::getInt(this, tr("WL4Editor"), - tr("Input a number to eliminate similar tiles to reducing tiles aggressively.\n" - "use a bigger number to reduce more tiles. but Tile16s' quality will drop more.\n" - "do strictly tile reduce by set 0 here."), + tr("Input a tolerance value for the number of different pixels between 2 Tile8x8.\n" + "The editor will merge similar Tile8x8s to reduce tile count aggressively.\n" + "Use a bigger value to reduce more tiles. However, the quality of the combined tiles will drop.\n" + "To perform regular tile reduction, use a value of 0."), 0, 0, 64, 1, &ok); if (!ok) return; @@ -1563,7 +1564,6 @@ void GraphicManagerDialog::on_pushButton_ReduceTiles_clicked() int find_tileid = j + constoffset; int reserved_tileid = find_tileid; - int discard_tileid = old_tileid; int x_flip = 0; int y_flip = 0; @@ -1575,7 +1575,6 @@ void GraphicManagerDialog::on_pushButton_ReduceTiles_clicked() if (newtmpdata == FileIOUtils::find_less_feature_buff(newtmpdata, tile_data, 32)) { reserved_tileid = old_tileid; - discard_tileid = find_tileid; } } else if (result1 <= diff_upbound) @@ -1584,7 +1583,6 @@ void GraphicManagerDialog::on_pushButton_ReduceTiles_clicked() if (newtmpXFlipdata == FileIOUtils::find_less_feature_buff(newtmpXFlipdata, tile_data, 32)) { reserved_tileid = old_tileid; - discard_tileid = find_tileid; } x_flip = 1 << 10; } @@ -1594,7 +1592,6 @@ void GraphicManagerDialog::on_pushButton_ReduceTiles_clicked() if (newtmpYFlipdata == FileIOUtils::find_less_feature_buff(newtmpYFlipdata, tile_data, 32)) { reserved_tileid = old_tileid; - discard_tileid = find_tileid; } y_flip = 1 << 11; } @@ -1604,7 +1601,6 @@ void GraphicManagerDialog::on_pushButton_ReduceTiles_clicked() if (newtmpXYFlipdata == FileIOUtils::find_less_feature_buff(newtmpXYFlipdata, tile_data, 32)) { reserved_tileid = old_tileid; - discard_tileid = find_tileid; } x_flip = 1 << 10; y_flip = 1 << 11; @@ -1614,19 +1610,20 @@ void GraphicManagerDialog::on_pushButton_ReduceTiles_clicked() { for (int w = 0; w < tmpEntry.mappingData.size(); w++) { - if ((tmpEntry.mappingData[w] & 0x3FF) == discard_tileid) + if ((tmpEntry.mappingData[w] & 0x3FF) == old_tileid) { int old_x_flip_state = tmpEntry.mappingData[w] & (1 << 10); int old_y_flip_state = tmpEntry.mappingData[w] & (1 << 11); mappingdata = 0xF << 12 | (y_flip ^ old_y_flip_state) | (x_flip ^ old_x_flip_state) | - (reserved_tileid & 0x3FF); + (find_tileid & 0x3FF); tmpEntry.mappingData[w] = mappingdata; } } - // change the tmp_current_tile8x8_data + // we need to change the tmp_current_tile8x8_data and tmpEntry.tileData + // if the old_tileid needs to be reserved if (reserved_tileid == old_tileid) { memcpy(&tmp_current_tile8x8_data[32 * j], newtmpdata, 32); @@ -1634,12 +1631,12 @@ void GraphicManagerDialog::on_pushButton_ReduceTiles_clicked() int startid = tmpEntry.TileDataRAMOffsetNum; for (int k = 0; k < 32; k++) { - tmpEntry.tileData[32 * (reserved_tileid - startid) + k] = newtmpdata[k]; + tmpEntry.tileData[32 * (find_tileid - startid) + k] = newtmpdata[k]; } } - // delete the Tile8x8 from the Tile8x8 set - DeltmpEntryTile(discard_tileid); + // delete the Tile8x8 from the tmpEntry's Tile8x8 set + DeltmpEntryTile(old_tileid); break; } } From 87af038b0ef3f7aaba5906071e0c37cf68f3f7f0 Mon Sep 17 00:00:00 2001 From: Chen Yifeng <648616375@qq.com> Date: Tue, 12 Jul 2022 08:14:44 +0800 Subject: [PATCH 3/4] aggressive tile reduce in Tileset Editor works --- Dialog/GraphicManagerDialog.cpp | 12 +++---- Dialog/TilesetEditDialog.cpp | 60 ++++++++++++++++++++++++++------- 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/Dialog/GraphicManagerDialog.cpp b/Dialog/GraphicManagerDialog.cpp index 2cec33fe..30e2bc38 100644 --- a/Dialog/GraphicManagerDialog.cpp +++ b/Dialog/GraphicManagerDialog.cpp @@ -1520,11 +1520,11 @@ void GraphicManagerDialog::on_pushButton_ReduceTiles_clicked() // ask user if eliminate similar tiles to reduce more tiles bool ok; int diff_upbound = QInputDialog::getInt(this, - tr("WL4Editor"), - tr("Input a tolerance value for the number of different pixels between 2 Tile8x8.\n" - "The editor will merge similar Tile8x8s to reduce tile count aggressively.\n" - "Use a bigger value to reduce more tiles. However, the quality of the combined tiles will drop.\n" - "To perform regular tile reduction, use a value of 0."), + tr("WL4Editor"), + tr("Input a tolerance value for the number of different pixels between 2 Tile8x8s.\n" + "The editor will merge similar Tile8x8s to reduce tile count aggressively.\n" + "Use a bigger value to reduce more tiles. However, the quality of the combined tiles will drop.\n" + "To perform regular tile reduction, use a value of 0."), 0, 0, 64, 1, &ok); if (!ok) return; @@ -1562,7 +1562,6 @@ void GraphicManagerDialog::on_pushButton_ReduceTiles_clicked() int result3 = FileIOUtils::quasi_memcmp(newtmpXYFlipdata, tile_data, 32); bool find_eqaul = false; int find_tileid = j + constoffset; - int reserved_tileid = find_tileid; int x_flip = 0; @@ -1608,6 +1607,7 @@ void GraphicManagerDialog::on_pushButton_ReduceTiles_clicked() if (find_eqaul) { + // always replace the old_tileid instance with the find_tileid instance for (int w = 0; w < tmpEntry.mappingData.size(); w++) { if ((tmpEntry.mappingData[w] & 0x3FF) == old_tileid) diff --git a/Dialog/TilesetEditDialog.cpp b/Dialog/TilesetEditDialog.cpp index e7bd06c3..2a5483ab 100644 --- a/Dialog/TilesetEditDialog.cpp +++ b/Dialog/TilesetEditDialog.cpp @@ -1125,11 +1125,12 @@ void TilesetEditDialog::on_pushButton_CleanUpDuplicatedTile8x8_clicked() // ask user if eliminate similar tiles to reduce more tiles bool ok; int diff_upbound = QInputDialog::getInt(this, - tr("WL4Editor"), - tr("Input a number to eliminate similar tiles to reducing tiles aggressively.\n" - "use a bigger number to reduce more tiles. but Tile16s' quality will drop more.\n" - "do strictly tile reduce by set 0 here."), - 0, 0, 64, 1, &ok); + tr("WL4Editor"), + tr("Input a tolerance value for the number of different pixels between 2 Tile8x8s.\n" + "The editor will merge similar Tile8x8s to reduce tile count aggressively.\n" + "Use a bigger value to reduce more tiles. However, the quality of the Tile16s will drop.\n" + "To perform regular tile reduction, use a value of 0."), + 0, 0, 64, 1, &ok); if (!ok) return; LevelComponents::Tileset *tmp_newTilesetPtr = tilesetEditParams->newTileset; @@ -1157,43 +1158,78 @@ void TilesetEditDialog::on_pushButton_CleanUpDuplicatedTile8x8_clicked() ROMUtils::Tile8x8DataXFlip(newtmpdata, newtmpXFlipdata); ROMUtils::Tile8x8DataYFlip(newtmpdata, newtmpYFlipdata); ROMUtils::Tile8x8DataYFlip(newtmpXFlipdata, newtmpXYFlipdata); + int old_tileid = i + 0x40; // loop from the first blank tile to the tile right before the current tile being checked, excluding those animated tiles for (int j = 0; j < i; j++) { - int result0 = FileIOUtils::quasi_memcmp(newtmpdata, &tmp_current_tile8x8_data[j * 32], 32); - int result1 = FileIOUtils::quasi_memcmp(newtmpXFlipdata, &tmp_current_tile8x8_data[j * 32], 32); - int result2 = FileIOUtils::quasi_memcmp(newtmpYFlipdata, &tmp_current_tile8x8_data[j * 32], 32); - int result3 = FileIOUtils::quasi_memcmp(newtmpXYFlipdata, &tmp_current_tile8x8_data[j * 32], 32); + unsigned char tile_data[32]; + memcpy(tile_data, &tmp_current_tile8x8_data[32 * j], 32); + + int result0 = FileIOUtils::quasi_memcmp(newtmpdata, tile_data, 32); + int result1 = FileIOUtils::quasi_memcmp(newtmpXFlipdata, tile_data, 32); + int result2 = FileIOUtils::quasi_memcmp(newtmpYFlipdata, tile_data, 32); + int result3 = FileIOUtils::quasi_memcmp(newtmpXYFlipdata, tile_data, 32); bool find_eqaul = false; bool xflip = false; bool yflip = false; auto tile16array = tmp_newTilesetPtr->GetMap16arrayPtr(); auto tile8x8array = tmp_newTilesetPtr->GetTile8x8arrayPtr(); + int find_tileid = j + 0x40; + int reserved_tileid = find_tileid; + if (result0 <= diff_upbound) { find_eqaul = true; + if (newtmpdata == FileIOUtils::find_less_feature_buff(newtmpdata, tile_data, 32)) + { + reserved_tileid = old_tileid; + } } else if (result1 <= diff_upbound) { find_eqaul = true; + if (newtmpXFlipdata == FileIOUtils::find_less_feature_buff(newtmpXFlipdata, tile_data, 32)) + { + reserved_tileid = old_tileid; + } xflip = true; } else if (result2 <= diff_upbound) { find_eqaul = true; + if (newtmpYFlipdata == FileIOUtils::find_less_feature_buff(newtmpYFlipdata, tile_data, 32)) + { + reserved_tileid = old_tileid; + } yflip = true; } else if (result3 <= diff_upbound) { find_eqaul = true; + if (newtmpXYFlipdata == FileIOUtils::find_less_feature_buff(newtmpXYFlipdata, tile_data, 32)) + { + reserved_tileid = old_tileid; + } xflip = true; yflip = true; } if (find_eqaul) { + // we need to change the tmp_current_tile8x8_data and tile8x8array + // if the old_tileid needs to be reserved + if (reserved_tileid == old_tileid) + { + memcpy(&tmp_current_tile8x8_data[32 * j], newtmpdata, 32); + + LevelComponents::Tile8x8 *tmptile = tile8x8array[old_tileid]; + tile8x8array[old_tileid] = tile8x8array[find_tileid]; + tile8x8array[find_tileid] = tmptile; + } + + // always replace the old_tileid instance with the find_tileid instance for (int k = 0; k < Tile16DefaultNum; k++) { for (int pos = 0; pos < 4; pos++) @@ -1201,7 +1237,7 @@ void TilesetEditDialog::on_pushButton_CleanUpDuplicatedTile8x8_clicked() bool tmp_xflip = xflip; bool tmp_yflip = yflip; auto tile8 = tile16array[k]->GetTile8X8(pos); - if (tile8->GetIndex() == (i + 0x40)) + if (tile8->GetIndex() == old_tileid) { if (tile8->GetFlipX()) { @@ -1211,14 +1247,14 @@ void TilesetEditDialog::on_pushButton_CleanUpDuplicatedTile8x8_clicked() { tmp_yflip = !yflip; } - tile16array[k]->ResetTile8x8(tile8x8array[j + 0x40], pos, j + 0x40, + tile16array[k]->ResetTile8x8(tile8x8array[find_tileid], pos, find_tileid, tile8->GetPaletteIndex(), tmp_xflip, tmp_yflip); } } } // delete the Tile8x8 from the Tile8x8 set - tilesetEditParams->newTileset->DelTile8x8(i + 0x40); + tilesetEditParams->newTileset->DelTile8x8(old_tileid); break; } } From 796bb77fbc1c6a7a09c1ae4bad490a562d787e55 Mon Sep 17 00:00:00 2001 From: Chen Yifeng <648616375@qq.com> Date: Sat, 16 Jul 2022 08:43:25 +0800 Subject: [PATCH 4/4] pop up warning dialog for one exception routine --- Dialog/GraphicManagerDialog.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Dialog/GraphicManagerDialog.cpp b/Dialog/GraphicManagerDialog.cpp index 30e2bc38..cee0e42a 100644 --- a/Dialog/GraphicManagerDialog.cpp +++ b/Dialog/GraphicManagerDialog.cpp @@ -561,6 +561,7 @@ void GraphicManagerDialog::DeltmpEntryTile(int tileId) tmpEntry.TileDataSizeInByte -= 32; // update mapping data + bool find_bug = false; for (int w = 0; w < tmpEntry.mappingData.size(); w++) { unsigned short data = tmpEntry.mappingData[w]; @@ -575,8 +576,14 @@ void GraphicManagerDialog::DeltmpEntryTile(int tileId) // there should be no existance of the current tile when calling this function // we just set it to use the default 0x3FF Tile8x8 and use the palette 0xF tmpEntry.mappingData[w] = 0xF000 | 0x3FF; + find_bug = true; } } + if (find_bug) + { + QMessageBox::critical(this, tr("Warning"), tr("Something went wrong when reducing tiles.\n" + "Contact developers for more details.")); + } } case AssortedGraphicUtils::AssortedGraphicTileDataType::Tile8x8_4bpp_no_comp: