mirror of
https://github.com/zeldaret/tmc
synced 2026-07-12 07:38:02 -04:00
Extract dungeon maps
This commit is contained in:
+1
-1
@@ -49,7 +49,7 @@ class BaseAsset {
|
||||
}
|
||||
|
||||
// Returns the base of the filename of the asset.
|
||||
[[nodiscard]] std::string getSymbol() const {
|
||||
[[nodiscard]] virtual std::string getSymbol() const {
|
||||
// Need to get the stem twice to remove both of the .4bpp.lz extensions.
|
||||
return (path.stem()).stem();
|
||||
}
|
||||
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
#include "dungeonmap.h"
|
||||
#include "util.h"
|
||||
#include <fmt/format.h>
|
||||
#include <fstream>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <util/file.h>
|
||||
|
||||
std::filesystem::path DungeonMapAsset::generateAssetPath() {
|
||||
std::filesystem::path txtPath = path;
|
||||
txtPath.replace_extension(".txt");
|
||||
return txtPath;
|
||||
}
|
||||
|
||||
void DungeonMapAsset::convertToHumanReadable(const std::vector<char>& baserom) {
|
||||
(void)baserom;
|
||||
const char characters[] = {' ', '#', '.', '-'};
|
||||
|
||||
std::ifstream file(path.string(), std::ios::binary | std::ios::ate);
|
||||
auto fileSize = file.tellg();
|
||||
file.seekg(0, std::ios::beg);
|
||||
|
||||
std::vector<char> data(static_cast<size_t>(fileSize));
|
||||
if (!file.read(data.data(), fileSize)) {
|
||||
fmt::print(stderr, "Can not read dungeon map {}\n", path.string());
|
||||
std::exit(1);
|
||||
}
|
||||
file.close();
|
||||
|
||||
auto output_file = util::open_file(assetPath, "w");
|
||||
|
||||
size_t width = asset["options"]["width"];
|
||||
width *= 4;
|
||||
size_t height = asset["options"]["height"];
|
||||
size_t bytesPerRow = (width + 3) / 4;
|
||||
|
||||
for (size_t y = 0; y < height; y++) {
|
||||
for (size_t x = 0; x < width; x +=4) {
|
||||
size_t offset = y * bytesPerRow + x / 4;
|
||||
char byte = data[offset];
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
int color = (byte >> (6 - i*2)) & 3;
|
||||
std::fputc(characters[color], output_file.get());
|
||||
}
|
||||
}
|
||||
std::fputc('\n', output_file.get());
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonMapAsset::buildToBinary() {
|
||||
std::ifstream file(assetPath.string(), std::ios::binary | std::ios::ate);
|
||||
auto fileSize = file.tellg();
|
||||
file.seekg(0, std::ios::beg);
|
||||
|
||||
std::vector<char> data(static_cast<size_t>(fileSize));
|
||||
if (!file.read(data.data(), fileSize)) {
|
||||
fmt::print(stderr, "Can not read dungeon map {}\n", assetPath.string());
|
||||
std::exit(1);
|
||||
}
|
||||
file.close();
|
||||
|
||||
auto output_file = util::open_file(buildPath, "w");
|
||||
char byte = 0;
|
||||
size_t pixels = 0;
|
||||
for (size_t i = 0; i < static_cast<size_t>(fileSize); i++) {
|
||||
switch (data[i]) {
|
||||
case '\n':
|
||||
continue;
|
||||
case ' ':
|
||||
byte <<= 2;
|
||||
pixels++;
|
||||
break;
|
||||
case '#':
|
||||
byte <<= 2;
|
||||
byte |= 1;
|
||||
pixels++;
|
||||
break;
|
||||
case '.':
|
||||
byte <<= 2;
|
||||
byte |= 2;
|
||||
pixels++;
|
||||
break;
|
||||
case '-':
|
||||
byte <<= 2;
|
||||
byte |= 3;
|
||||
pixels++;
|
||||
break;
|
||||
default:
|
||||
fmt::print(stderr, "Unexpected character {}\n", data[i]);
|
||||
std::exit(1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (pixels % 4 == 0) {
|
||||
std::fputc(byte, output_file.get());
|
||||
byte = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Pad to two bytes.
|
||||
while ((pixels / 4) % 4 != 0) {
|
||||
std::fputc(0, output_file.get());
|
||||
pixels += 4;
|
||||
}
|
||||
}
|
||||
|
||||
std::string DungeonMapAsset::getSymbol() const {
|
||||
return asset["name"];
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
#ifndef DUNGEONMAP_H
|
||||
#define DUNGEONMAP_H
|
||||
|
||||
#include "asset.h"
|
||||
|
||||
class DungeonMapAsset : public BaseAsset {
|
||||
public:
|
||||
using BaseAsset::BaseAsset;
|
||||
virtual void convertToHumanReadable(const std::vector<char>& baserom);
|
||||
virtual void buildToBinary();
|
||||
virtual std::string getSymbol() const;
|
||||
|
||||
private:
|
||||
virtual std::filesystem::path generateAssetPath();
|
||||
};
|
||||
|
||||
#endif // DUNGEONMAP_H
|
||||
+1
@@ -56,6 +56,7 @@ void GfxAsset::buildToBinary() {
|
||||
check_call(cmd);
|
||||
|
||||
if (isCompressed()) {
|
||||
cmd.clear();
|
||||
// Compress.
|
||||
cmd.push_back(toolsPath / "bin" / "gbagfx");
|
||||
cmd.push_back(decompressedPath);
|
||||
|
||||
@@ -53,6 +53,7 @@ void TilesetAsset::buildToBinary() {
|
||||
|
||||
if (isCompressed()) {
|
||||
// Compress.
|
||||
cmd.clear();
|
||||
cmd.push_back(toolsPath / "bin" / "gbagfx");
|
||||
cmd.push_back(decompressedPath);
|
||||
cmd.push_back(path);
|
||||
|
||||
Vendored
+4
-1
@@ -1,6 +1,7 @@
|
||||
#include "main.h"
|
||||
#include "assets/aif.h"
|
||||
#include "assets/animation.h"
|
||||
#include "assets/dungeonmap.h"
|
||||
#include "assets/frameobjlists.h"
|
||||
#include "assets/gfx.h"
|
||||
#include "assets/map.h"
|
||||
@@ -284,6 +285,8 @@ std::unique_ptr<BaseAsset> getAssetHandlerByType(const std::filesystem::path& pa
|
||||
type == "map_mapping1" || type == "map_mapping2" || type == "tileset_mapping3" ||
|
||||
type == "map_collision") {
|
||||
assetHandler = std::make_unique<MapAsset>(path, start, size, asset);
|
||||
} else if (type == "dungeon_map") {
|
||||
assetHandler = std::make_unique<DungeonMapAsset>(path, start, size, asset);
|
||||
} else if (type == "unknown") {
|
||||
// TODO implement conversions
|
||||
assetHandler = std::make_unique<BaseAsset>(path, start, size, asset);
|
||||
@@ -291,7 +294,7 @@ std::unique_ptr<BaseAsset> getAssetHandlerByType(const std::filesystem::path& pa
|
||||
// Unknown binary asset
|
||||
assetHandler = std::make_unique<BaseAsset>(path, start, size, asset);
|
||||
} else {
|
||||
fmt::print(stderr, "Error: Unimplemented asset type \"{}\"", type);
|
||||
fmt::print(stderr, "Error: Unimplemented asset type \"{}\"\n", type);
|
||||
std::exit(1);
|
||||
}
|
||||
assetHandler->setup();
|
||||
|
||||
Reference in New Issue
Block a user