mirror of
https://github.com/zeldaret/mm.git
synced 2024-11-23 12:59:44 +00:00
ZAPD fixes in sys_initial_check
, update subrepos (#507)
* git subrepo pull --force tools/ZAPD subrepo: subdir: "tools/ZAPD" merged: "a3363333d" upstream: origin: "https://github.com/zeldaret/ZAPD.git" branch: "master" commit: "a3363333d" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" * git subrepo pull tools/asm-differ --force subrepo: subdir: "tools/asm-differ" merged: "70c33cc12" upstream: origin: "https://github.com/simonlindholm/asm-differ.git" branch: "main" commit: "70c33cc12" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" * git subrepo pull (merge) tools/z64compress --force subrepo: subdir: "tools/z64compress" merged: "ac5b1a0d0" upstream: origin: "https://github.com/z64me/z64compress.git" branch: "main" commit: "ac5b1a0d0" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" * Use defines for texture sizes in sys_initial_check * Update extract_assets.py * Add null check * git subrepo pull --force tools/ZAPD subrepo: subdir: "tools/ZAPD" merged: "50242eca9" upstream: origin: "https://github.com/zeldaret/ZAPD.git" branch: "master" commit: "50242eca9" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596"
This commit is contained in:
parent
ff231e093a
commit
9ca4ec7604
@ -1,8 +1,10 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse, json, os, signal, time
|
||||
import argparse, json, os, signal, time, colorama
|
||||
from multiprocessing import Pool, Event, Manager
|
||||
|
||||
colorama.init();
|
||||
|
||||
EXTRACTED_ASSETS_NAMEFILE = ".extracted-assets.json"
|
||||
|
||||
def SignalHandler(sig, frame):
|
||||
@ -15,10 +17,10 @@ def ExtractFile(xmlPath, outputPath, outputSourcePath):
|
||||
# Don't extract if another file wasn't extracted properly.
|
||||
return
|
||||
|
||||
execStr = "tools/ZAPD/ZAPD.out e -eh -i %s -b baserom/ -o %s -osf %s -gsf 1 -rconf tools/ZAPDConfigs/MM/Config.xml" % (xmlPath, outputPath, outputSourcePath)
|
||||
execStr = f"tools/ZAPD/ZAPD.out e -eh -i {xmlPath} -b baserom/ -o {outputPath} -osf {outputSourcePath} -gsf 1 -rconf tools/ZAPDConfigs/MM/Config.xml {ZAPDArgs}"
|
||||
|
||||
if globalUnaccounted:
|
||||
execStr += " -wu"
|
||||
execStr += " -Wunaccounted"
|
||||
|
||||
print(execStr)
|
||||
exitValue = os.system(execStr)
|
||||
@ -72,8 +74,27 @@ def main():
|
||||
parser.add_argument("-t", "--threads", help="Number of cpu cores to extract with.")
|
||||
parser.add_argument("-f", "--force", help="Force the extraction of every xml instead of checking the touched ones.", action="store_true")
|
||||
parser.add_argument("-u", "--unaccounted", help="Enables ZAPD unaccounted detector warning system.", action="store_true")
|
||||
parser.add_argument("-Z", help="Pass the argument on to ZAPD, e.g. `-ZWunaccounted` to warn about unaccounted blocks in XMLs. Each argument should be passed separately, *without* the leading dash.", metavar="ZAPD_ARG", action="append")
|
||||
args = parser.parse_args()
|
||||
|
||||
global ZAPDArgs;
|
||||
ZAPDArgs = "";
|
||||
if args.Z is not None:
|
||||
badZAPDArg = False;
|
||||
for i in range(len(args.Z)):
|
||||
z = args.Z[i]
|
||||
if z[0] == '-':
|
||||
print(f"{colorama.Fore.LIGHTRED_EX}error{colorama.Fore.RESET}: argument \"{z}\" starts with \"-\", which is not supported.", file=os.sys.stderr);
|
||||
badZAPDArg = True;
|
||||
else:
|
||||
args.Z[i] = "-" + z;
|
||||
|
||||
if badZAPDArg:
|
||||
exit(1);
|
||||
|
||||
ZAPDArgs = " ".join(args.Z);
|
||||
print("Using extra ZAPD arguments: " + ZAPDArgs);
|
||||
|
||||
global mainAbort
|
||||
mainAbort = Event()
|
||||
manager = Manager()
|
||||
@ -88,7 +109,7 @@ def main():
|
||||
if asset_path is not None:
|
||||
fullPath = os.path.join("assets", "xml", asset_path + ".xml")
|
||||
if not os.path.exists(fullPath):
|
||||
print(f"Error. File {fullPath} doesn't exists.", file=os.sys.stderr)
|
||||
print(f"Error. File {fullPath} does not exist.", file=os.sys.stderr)
|
||||
exit(1)
|
||||
|
||||
initializeWorker(mainAbort, args.unaccounted, extractedAssetsTracker, manager)
|
||||
@ -107,7 +128,7 @@ def main():
|
||||
numCores = int(args.threads or 0)
|
||||
if numCores <= 0:
|
||||
numCores = 1
|
||||
print("Extracting assets with " + str(numCores) + " CPU cores.")
|
||||
print("Extracting assets with " + str(numCores) + " CPU core" + ("s" if numCores > 1 else "") + ".")
|
||||
with Pool(numCores, initializer=initializeWorker, initargs=(mainAbort, args.unaccounted, extractedAssetsTracker, manager)) as p:
|
||||
p.map(ExtractFunc, xmlFiles)
|
||||
|
||||
|
@ -10,8 +10,16 @@
|
||||
#include "misc/locerrmsg/locerrmsg.h"
|
||||
#include "misc/memerrmsg/memerrmsg.h"
|
||||
|
||||
#define SIZEOF_LOCERRMSG (sizeof(gNotDesignedForSystemErrorTex))
|
||||
#define SIZEOF_MEMERRMSG (sizeof(gExpansionPakNotInstalledErrorTex) + sizeof(gSeeInstructionBookletErrorTex))
|
||||
#define LOCERRMSG_WIDTH 208
|
||||
#define LOCERRMSG_HEIGHT 16
|
||||
#define NUMBEROF_LOCERRMSGS 1
|
||||
|
||||
#define MEMERRMSG_WIDTH 128
|
||||
#define MEMERRMSG_HEIGHT 37
|
||||
#define NUMBEROF_MEMERRMSGS 2
|
||||
|
||||
#define SIZEOF_LOCERRMSG (LOCERRMSG_WIDTH * LOCERRMSG_HEIGHT / 2 * NUMBEROF_LOCERRMSGS)
|
||||
#define SIZEOF_MEMERRMSG (MEMERRMSG_WIDTH * MEMERRMSG_HEIGHT / 2 * NUMBEROF_MEMERRMSGS)
|
||||
|
||||
// Address with enough room after to load either of the error message image files before the fault screen buffer at the
|
||||
// end of RDRAM
|
||||
@ -64,9 +72,9 @@ void Check_ClearRGBA16(u16* buffer) {
|
||||
void Check_DrawExpansionPakErrorMessage(void) {
|
||||
DmaMgr_SendRequest0(CHECK_ERRMSG_STATIC_SEGMENT, SEGMENT_ROM_START(memerrmsg), SEGMENT_SIZE(memerrmsg));
|
||||
Check_ClearRGBA16((u16*)FAULT_FB_ADDRESS);
|
||||
Check_DrawI4Texture((u16*)FAULT_FB_ADDRESS, 96, 71, 128, 37, CHECK_ERRMSG_STATIC_SEGMENT);
|
||||
Check_DrawI4Texture((u16*)FAULT_FB_ADDRESS, 96, 127, 128, 37,
|
||||
CHECK_ERRMSG_STATIC_SEGMENT + sizeof(gExpansionPakNotInstalledErrorTex));
|
||||
Check_DrawI4Texture((u16*)FAULT_FB_ADDRESS, 96, 71, MEMERRMSG_WIDTH, MEMERRMSG_HEIGHT, CHECK_ERRMSG_STATIC_SEGMENT);
|
||||
Check_DrawI4Texture((u16*)FAULT_FB_ADDRESS, 96, 127, MEMERRMSG_WIDTH, MEMERRMSG_HEIGHT,
|
||||
CHECK_ERRMSG_STATIC_SEGMENT + MEMERRMSG_WIDTH * MEMERRMSG_HEIGHT / 2);
|
||||
osWritebackDCacheAll();
|
||||
osViSwapBuffer((u16*)FAULT_FB_ADDRESS);
|
||||
osViBlack(false);
|
||||
@ -78,7 +86,8 @@ void Check_DrawExpansionPakErrorMessage(void) {
|
||||
void Check_DrawRegionLockErrorMessage(void) {
|
||||
DmaMgr_SendRequest0(CHECK_ERRMSG_STATIC_SEGMENT, SEGMENT_ROM_START(locerrmsg), SEGMENT_SIZE(locerrmsg));
|
||||
Check_ClearRGBA16((u16*)FAULT_FB_ADDRESS);
|
||||
Check_DrawI4Texture((u16*)FAULT_FB_ADDRESS, 56, 112, 208, 16, CHECK_ERRMSG_STATIC_SEGMENT);
|
||||
Check_DrawI4Texture((u16*)FAULT_FB_ADDRESS, 56, 112, LOCERRMSG_WIDTH, LOCERRMSG_HEIGHT,
|
||||
CHECK_ERRMSG_STATIC_SEGMENT);
|
||||
osWritebackDCacheAll();
|
||||
osViSwapBuffer((u16*)FAULT_FB_ADDRESS);
|
||||
osViBlack(false);
|
||||
|
@ -6,7 +6,7 @@
|
||||
[subrepo]
|
||||
remote = https://github.com/zeldaret/ZAPD.git
|
||||
branch = master
|
||||
commit = 4f7b8393ec8a3abd59649c2ba669e951fb61f3d2
|
||||
parent = 346df1bbc8ca21673fe63d884b6734c23a4d9f4b
|
||||
commit = 50242eca96a9c36fd84f438bab24548e73b42303
|
||||
parent = 744955732b1fc9e8a835c62440aa97799cfe8940
|
||||
method = merge
|
||||
cmdver = 0.4.3
|
||||
|
@ -79,7 +79,7 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(SolutionDir)\ZAPD\;$(SolutionDir)ZAPDUtils;$(SolutionDir)lib\tinyxml2;$(SolutionDir)lib\libgfxd;$(SolutionDir)lib\elfio;$(SolutionDir)lib\stb;$(ProjectDir);$(IncludePath)</IncludePath>
|
||||
<IncludePath>$(ProjectDir)..\ZAPD\;$(ProjectDir)..\ZAPDUtils;$(ProjectDir)..\lib\tinyxml2;$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\lib\elfio;$(ProjectDir)..\lib\stb;$(ProjectDir);$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
@ -120,6 +120,7 @@
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<LanguageStandard_C>stdc11</LanguageStandard_C>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@ -156,4 +157,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
@ -1,7 +1,7 @@
|
||||
#include <CollisionExporter.h>
|
||||
#include <Globals.h>
|
||||
#include <RoomExporter.h>
|
||||
#include <TextureExporter.h>
|
||||
#include "CollisionExporter.h"
|
||||
#include "Globals.h"
|
||||
#include "RoomExporter.h"
|
||||
#include "TextureExporter.h"
|
||||
|
||||
enum class ExporterFileMode
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Only used for standalone compilation, usually inherits these from the main makefile
|
||||
CXXFLAGS ?= -Wall -Wextra -O2 -g -std=c++17
|
||||
|
||||
SRC_DIRS := $(shell find -type d -not -path "*build*")
|
||||
SRC_DIRS := $(shell find . -type d -not -path "*build*")
|
||||
CPP_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.cpp))
|
||||
H_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.h))
|
||||
|
||||
|
@ -1,24 +1,24 @@
|
||||
#include "RoomExporter.h"
|
||||
#include <CollisionExporter.h>
|
||||
#include <Utils/BinaryWriter.h>
|
||||
#include <Utils/File.h>
|
||||
#include <Utils/MemoryStream.h>
|
||||
#include <ZRoom/Commands/SetCameraSettings.h>
|
||||
#include <ZRoom/Commands/SetCollisionHeader.h>
|
||||
#include <ZRoom/Commands/SetCsCamera.h>
|
||||
#include <ZRoom/Commands/SetEchoSettings.h>
|
||||
#include <ZRoom/Commands/SetEntranceList.h>
|
||||
#include <ZRoom/Commands/SetLightingSettings.h>
|
||||
#include <ZRoom/Commands/SetMesh.h>
|
||||
#include <ZRoom/Commands/SetRoomBehavior.h>
|
||||
#include <ZRoom/Commands/SetRoomList.h>
|
||||
#include <ZRoom/Commands/SetSkyboxModifier.h>
|
||||
#include <ZRoom/Commands/SetSkyboxSettings.h>
|
||||
#include <ZRoom/Commands/SetSoundSettings.h>
|
||||
#include <ZRoom/Commands/SetSpecialObjects.h>
|
||||
#include <ZRoom/Commands/SetStartPositionList.h>
|
||||
#include <ZRoom/Commands/SetTimeSettings.h>
|
||||
#include <ZRoom/Commands/SetWind.h>
|
||||
#include "CollisionExporter.h"
|
||||
#include "Utils/BinaryWriter.h"
|
||||
#include "Utils/File.h"
|
||||
#include "Utils/MemoryStream.h"
|
||||
#include "ZRoom/Commands/SetCameraSettings.h"
|
||||
#include "ZRoom/Commands/SetCollisionHeader.h"
|
||||
#include "ZRoom/Commands/SetCsCamera.h"
|
||||
#include "ZRoom/Commands/SetEchoSettings.h"
|
||||
#include "ZRoom/Commands/SetEntranceList.h"
|
||||
#include "ZRoom/Commands/SetLightingSettings.h"
|
||||
#include "ZRoom/Commands/SetMesh.h"
|
||||
#include "ZRoom/Commands/SetRoomBehavior.h"
|
||||
#include "ZRoom/Commands/SetRoomList.h"
|
||||
#include "ZRoom/Commands/SetSkyboxModifier.h"
|
||||
#include "ZRoom/Commands/SetSkyboxSettings.h"
|
||||
#include "ZRoom/Commands/SetSoundSettings.h"
|
||||
#include "ZRoom/Commands/SetSpecialObjects.h"
|
||||
#include "ZRoom/Commands/SetStartPositionList.h"
|
||||
#include "ZRoom/Commands/SetTimeSettings.h"
|
||||
#include "ZRoom/Commands/SetWind.h"
|
||||
|
||||
void ExporterExample_Room::Save(ZResource* res, fs::path outPath, BinaryWriter* writer)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <Utils/BinaryWriter.h>
|
||||
#include "Utils/BinaryWriter.h"
|
||||
#include "ZResource.h"
|
||||
#include "ZTexture.h"
|
||||
|
||||
|
58
tools/ZAPD/Jenkinsfile
vendored
58
tools/ZAPD/Jenkinsfile
vendored
@ -7,7 +7,7 @@ pipeline {
|
||||
// Non-parallel ZAPD stage
|
||||
stage('Build ZAPD') {
|
||||
steps {
|
||||
sh 'make -j'
|
||||
sh 'make -j WERROR=1'
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,13 +22,13 @@ pipeline {
|
||||
}
|
||||
}
|
||||
|
||||
stage('Checkout mm') {
|
||||
steps{
|
||||
dir('mm') {
|
||||
git url: 'https://github.com/zeldaret/mm.git'
|
||||
}
|
||||
}
|
||||
}
|
||||
// stage('Checkout mm') {
|
||||
// steps{
|
||||
// dir('mm') {
|
||||
// git url: 'https://github.com/zeldaret/mm.git'
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,20 +51,20 @@ pipeline {
|
||||
}
|
||||
}
|
||||
|
||||
stage('Setup MM') {
|
||||
steps {
|
||||
dir('mm') {
|
||||
sh 'cp /usr/local/etc/roms/mm.us.rev1.z64 baserom.mm.us.rev1.z64'
|
||||
// stage('Setup MM') {
|
||||
// steps {
|
||||
// dir('mm') {
|
||||
// sh 'cp /usr/local/etc/roms/mm.us.rev1.z64 baserom.mm.us.rev1.z64'
|
||||
|
||||
// Identical to `make setup` except for copying our newer ZAPD.out into mm
|
||||
sh 'make -C tools'
|
||||
sh 'cp ../ZAPD.out tools/ZAPD/'
|
||||
sh 'python3 tools/fixbaserom.py'
|
||||
sh 'python3 tools/extract_baserom.py'
|
||||
sh 'python3 extract_assets.py -t 4'
|
||||
}
|
||||
}
|
||||
}
|
||||
// // Identical to `make setup` except for copying our newer ZAPD.out into mm
|
||||
// sh 'make -C tools'
|
||||
// sh 'cp ../ZAPD.out tools/ZAPD/'
|
||||
// sh 'python3 tools/fixbaserom.py'
|
||||
// sh 'python3 tools/extract_baserom.py'
|
||||
// sh 'python3 extract_assets.py -t 4'
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,14 +78,14 @@ pipeline {
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Build mm') {
|
||||
steps {
|
||||
dir('mm') {
|
||||
sh 'make -j disasm'
|
||||
sh 'make -j all'
|
||||
}
|
||||
}
|
||||
}
|
||||
// stage('Build mm') {
|
||||
// steps {
|
||||
// dir('mm') {
|
||||
// sh 'make -j disasm'
|
||||
// sh 'make -j all'
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ DEPRECATION_ON ?= 1
|
||||
DEBUG ?= 0
|
||||
COPYCHECK_ARGS ?=
|
||||
LLD ?= 0
|
||||
WERROR ?= 0
|
||||
|
||||
# Use clang++ if available, else use g++
|
||||
ifeq ($(shell command -v clang++ >/dev/null 2>&1; echo $$?),0)
|
||||
@ -23,14 +24,16 @@ ifneq ($(DEBUG),0)
|
||||
CXXFLAGS += -g3 -DDEVELOPMENT -D_DEBUG
|
||||
COPYCHECK_ARGS += --devel
|
||||
DEPRECATION_ON = 0
|
||||
else
|
||||
endif
|
||||
|
||||
ifneq ($(WERROR),0)
|
||||
CXXFLAGS += -Werror
|
||||
endif
|
||||
|
||||
ifeq ($(OPTIMIZATION_ON),0)
|
||||
OPTFLAGS := -O0
|
||||
else
|
||||
OPTFLAGS := -O2 -march=native -mtune=native
|
||||
OPTFLAGS := -O2
|
||||
endif
|
||||
|
||||
ifneq ($(ASAN),0)
|
||||
@ -53,10 +56,23 @@ ifneq ($(LLD),0)
|
||||
endif
|
||||
|
||||
UNAME := $(shell uname)
|
||||
UNAMEM := $(shell uname -m)
|
||||
ifneq ($(UNAME), Darwin)
|
||||
LDFLAGS += -Wl,-export-dynamic -lstdc++fs
|
||||
LDFLAGS += -Wl,-export-dynamic -lstdc++fs
|
||||
EXPORTERS := -Wl,--whole-archive ExporterTest/ExporterTest.a -Wl,--no-whole-archive
|
||||
else
|
||||
EXPORTERS := -Wl,-force_load ExporterTest/ExporterTest.a
|
||||
ifeq ($(UNAMEM),arm64)
|
||||
ifeq ($(shell brew list libpng > /dev/null 2>&1; echo $$?),0)
|
||||
LDFLAGS += -L $(shell brew --prefix)/lib
|
||||
INC += -I $(shell brew --prefix)/include
|
||||
else
|
||||
$(error Please install libpng via Homebrew)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
ZAPD_SRC_DIRS := $(shell find ZAPD -type d)
|
||||
SRC_DIRS = $(ZAPD_SRC_DIRS) lib/tinyxml2
|
||||
|
||||
@ -115,4 +131,4 @@ ZAPDUtils:
|
||||
|
||||
# Linking
|
||||
ZAPD.out: $(O_FILES) lib/libgfxd/libgfxd.a ExporterTest ZAPDUtils
|
||||
$(CXX) $(CXXFLAGS) $(O_FILES) lib/libgfxd/libgfxd.a ZAPDUtils/ZAPDUtils.a -Wl,--whole-archive ExporterTest/ExporterTest.a -Wl,--no-whole-archive $(LDFLAGS) $(OUTPUT_OPTION)
|
||||
$(CXX) $(CXXFLAGS) $(O_FILES) lib/libgfxd/libgfxd.a ZAPDUtils/ZAPDUtils.a $(EXPORTERS) $(LDFLAGS) $(OUTPUT_OPTION)
|
||||
|
@ -16,6 +16,14 @@ In a Debian/Ubuntu based environment, those could be installed with the followin
|
||||
sudo apt install libpng-dev
|
||||
```
|
||||
|
||||
On a Mac, you will need to install libpng with Homebrew or MacPorts; we currently only support Homebrew. You can run
|
||||
|
||||
```bash
|
||||
brew install libpng
|
||||
```
|
||||
|
||||
to install it via Homebrew.
|
||||
|
||||
### Building
|
||||
|
||||
#### Linux / *nix
|
||||
@ -109,11 +117,51 @@ ZAPD also accepts the following list of extra parameters:
|
||||
- Could be useful for looking at raw data or testing.
|
||||
- Can be used only in `e` or `bsf` modes.
|
||||
- `-tm MODE`: Test Mode (enables certain experimental features). To enable it, set `MODE` to `1`.
|
||||
- `-wno` / `--warn-no-offsets` : Enable warnings for nodes that dont have offsets specified. Takes priority over `-eno`/ `--error-no-offsets`.
|
||||
- `-eno` / `--error-no-offsets` : Enable errors for nodes that dont have offsets specified.
|
||||
- `-se` / `--set-exporter` : Sets which exporter to use.
|
||||
- `--gcc-compat` : Enables GCC compatible mode. Slower.
|
||||
- `--gcc-compat` : Enables GCC compatibly mode. Slower.
|
||||
- `-s` / `--static` : Mark every asset as `static`.
|
||||
- This behaviour can be overridden per asset using `Static=` in the respective XML node.
|
||||
- `-W...`: warning flags, see below
|
||||
|
||||
Additionally, you can pass the flag `--version` to see the current ZAPD version. If that flag is passed, ZAPD will ignore any other parameter passed.
|
||||
|
||||
### Warning flags
|
||||
|
||||
ZAPD contains a variety of warning types, with similar syntax to GCC or Clang's compiler warnings. Warnings can have three levels:
|
||||
|
||||
- Off (does not display anything)
|
||||
- Warn (print a warning but continue processing)
|
||||
- Err (behave like an error, i.e. print and throw an exception to crash ZAPD when occurs)
|
||||
|
||||
Each warning type uses one of these by default, but can be modified with flags, similarly to GCC or Clang:
|
||||
|
||||
- `-Wfoo` enables warnings of type `foo`
|
||||
- `-Wno-foo` disables warnings of type `foo`
|
||||
- `-Werror=foo` escalates `foo` to behave like an error
|
||||
- `-Weverything` enables all warnings (they may be turned off using `-Wno-` flags afterwards)
|
||||
- `-Werror` escalates all enabled warnings to errors
|
||||
|
||||
All warning types currently implemented, with their default levels:
|
||||
|
||||
| Warning type | Default level | Description |
|
||||
| --------------------------- | ------------- | ------------------------------------------------------------------------ |
|
||||
| `-Wdeprecated` | Warn | Deprecated features |
|
||||
| `-Whardcoded-pointer` | Warn | ZAPD lacks the info to make a symbol, so must output a hardcoded pointer |
|
||||
| `-Wintersection` | Warn | Two assets intersect |
|
||||
| `-Winvalid-attribute-value` | Err | Attribute declared in XML is wrong |
|
||||
| `-Winvalid-extracted-data` | Err | Extracted data does not have correct form |
|
||||
| `-Winvalid-jpeg` | Err | JPEG file does not conform to the game's format requirements |
|
||||
| `-Winvalid-png` | Err | Issues arising when processing PNG data |
|
||||
| `-Winvalid-xml` | Err | XML has syntax errors |
|
||||
| `-Wmissing-attribute` | Warn | Required attribute missing in XML tag |
|
||||
| `-Wmissing-offsets` | Warn | Offset attribute missing in XML tag |
|
||||
| `-Wmissing-segment` | Warn | Segment not given in File tag in XML |
|
||||
| `-Wnot-implemented` | Warn | ZAPD does not currently support this feature |
|
||||
| `-Wunaccounted` | Off | Large blocks of unaccounted |
|
||||
| `-Wunknown-attribute` | Warn | Unknown attribute in XML entry tag |
|
||||
|
||||
There are also errors that do not have a type, and cannot be disabled.
|
||||
|
||||
For example, here we have invoked ZAPD in the usual way to extract using a (rather badly-written) XML, but escalating `-Wintersection` to an error:
|
||||
|
||||
![ZAPD warnings example](docs/zapd_warning_example.png?raw=true)
|
||||
|
@ -92,20 +92,20 @@ std::string Declaration::GetNormalDeclarationStr() const
|
||||
|
||||
if (isArray)
|
||||
{
|
||||
if (arrayItemCntStr != "")
|
||||
if (arrayItemCntStr != "" && (IsStatic() || forceArrayCnt))
|
||||
{
|
||||
output += StringHelper::Sprintf("%s %s[%s];\n", varType.c_str(), varName.c_str(),
|
||||
arrayItemCntStr.c_str());
|
||||
}
|
||||
else if (arrayItemCnt == 0)
|
||||
{
|
||||
output += StringHelper::Sprintf("%s %s[] = {\n", varType.c_str(), varName.c_str());
|
||||
}
|
||||
else
|
||||
else if (arrayItemCnt != 0 && (IsStatic() || forceArrayCnt))
|
||||
{
|
||||
output += StringHelper::Sprintf("%s %s[%i] = {\n", varType.c_str(), varName.c_str(),
|
||||
arrayItemCnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
output += StringHelper::Sprintf("%s %s[] = {\n", varType.c_str(), varName.c_str());
|
||||
}
|
||||
|
||||
output += text + "\n";
|
||||
}
|
||||
@ -145,16 +145,16 @@ std::string Declaration::GetExternalDeclarationStr() const
|
||||
output += "static ";
|
||||
}
|
||||
|
||||
if (arrayItemCntStr != "")
|
||||
if (arrayItemCntStr != "" && (IsStatic() || forceArrayCnt))
|
||||
output += StringHelper::Sprintf("%s %s[%s] = ", varType.c_str(), varName.c_str(),
|
||||
arrayItemCntStr.c_str());
|
||||
else if (arrayItemCnt != 0 && (IsStatic() || forceArrayCnt))
|
||||
output +=
|
||||
StringHelper::Sprintf("%s %s[%s] = {\n#include \"%s\"\n};", varType.c_str(),
|
||||
varName.c_str(), arrayItemCntStr.c_str(), includePath.c_str());
|
||||
else if (arrayItemCnt != 0)
|
||||
output += StringHelper::Sprintf("%s %s[%i] = {\n#include \"%s\"\n};", varType.c_str(),
|
||||
varName.c_str(), arrayItemCnt, includePath.c_str());
|
||||
StringHelper::Sprintf("%s %s[%i] = ", varType.c_str(), varName.c_str(), arrayItemCnt);
|
||||
else
|
||||
output += StringHelper::Sprintf("%s %s[] = {\n#include \"%s\"\n};", varType.c_str(),
|
||||
varName.c_str(), includePath.c_str());
|
||||
output += StringHelper::Sprintf("%s %s[] = ", varType.c_str(), varName.c_str());
|
||||
|
||||
output += StringHelper::Sprintf("{\n#include \"%s\"\n};", includePath.c_str());
|
||||
|
||||
if (rightText != "")
|
||||
output += " " + rightText + "";
|
||||
@ -178,14 +178,16 @@ std::string Declaration::GetExternStr() const
|
||||
|
||||
if (isArray)
|
||||
{
|
||||
if (arrayItemCntStr != "")
|
||||
if (arrayItemCntStr != "" && (IsStatic() || forceArrayCnt))
|
||||
{
|
||||
return StringHelper::Sprintf("extern %s %s[%s];\n", varType.c_str(), varName.c_str(),
|
||||
arrayItemCntStr.c_str());
|
||||
}
|
||||
else if (arrayItemCnt != 0)
|
||||
else if (arrayItemCnt != 0 && (IsStatic() || forceArrayCnt))
|
||||
{
|
||||
return StringHelper::Sprintf("extern %s %s[%i];\n", varType.c_str(), varName.c_str(),
|
||||
arrayItemCnt);
|
||||
}
|
||||
else
|
||||
return StringHelper::Sprintf("extern %s %s[];\n", varType.c_str(), varName.c_str());
|
||||
}
|
||||
|
@ -38,10 +38,12 @@ public:
|
||||
std::string varType;
|
||||
std::string varName;
|
||||
std::string includePath;
|
||||
|
||||
bool isExternal = false;
|
||||
bool isArray = false;
|
||||
bool forceArrayCnt = false;
|
||||
size_t arrayItemCnt = 0;
|
||||
std::string arrayItemCntStr;
|
||||
std::string arrayItemCntStr = "";
|
||||
std::vector<segptr_t> references;
|
||||
bool isUnaccounted = false;
|
||||
bool isPlaceholder = false;
|
||||
|
@ -25,7 +25,7 @@ GameConfig::~GameConfig()
|
||||
void GameConfig::ReadTexturePool(const fs::path& texturePoolXmlPath)
|
||||
{
|
||||
tinyxml2::XMLDocument doc;
|
||||
tinyxml2::XMLError eResult = doc.LoadFile(texturePoolXmlPath.c_str());
|
||||
tinyxml2::XMLError eResult = doc.LoadFile(texturePoolXmlPath.string().c_str());
|
||||
|
||||
if (eResult != tinyxml2::XML_SUCCESS)
|
||||
{
|
||||
@ -155,7 +155,7 @@ void GameConfig::ReadConfigFile(const fs::path& argConfigFilePath)
|
||||
{"ExternalFile", &GameConfig::ConfigFunc_ExternalFile},
|
||||
};
|
||||
|
||||
configFilePath = argConfigFilePath;
|
||||
configFilePath = argConfigFilePath.string();
|
||||
tinyxml2::XMLDocument doc;
|
||||
tinyxml2::XMLError eResult = doc.LoadFile(configFilePath.c_str());
|
||||
|
||||
|
@ -3,8 +3,9 @@
|
||||
#include <algorithm>
|
||||
#include <string_view>
|
||||
|
||||
#include <Utils/File.h>
|
||||
#include <Utils/Path.h>
|
||||
#include "Utils/File.h"
|
||||
#include "Utils/Path.h"
|
||||
#include "WarningHandler.h"
|
||||
#include "tinyxml2.h"
|
||||
|
||||
Globals* Globals::Instance;
|
||||
|
@ -20,6 +20,7 @@ typedef bool (*ExporterSetFuncBool)(ZFileMode fileMode);
|
||||
typedef void (*ExporterSetFuncVoid)(int argc, char* argv[], int& i);
|
||||
typedef void (*ExporterSetFuncVoid2)(const std::string& buildMode, ZFileMode& fileMode);
|
||||
typedef void (*ExporterSetFuncVoid3)();
|
||||
typedef void (*ExporterSetResSave)(ZResource* res, BinaryWriter& writer);
|
||||
|
||||
class ExporterSet
|
||||
{
|
||||
@ -34,6 +35,7 @@ public:
|
||||
ExporterSetFunc endFileFunc = nullptr;
|
||||
ExporterSetFuncVoid3 beginXMLFunc = nullptr;
|
||||
ExporterSetFuncVoid3 endXMLFunc = nullptr;
|
||||
ExporterSetResSave resSaveFunc = nullptr;
|
||||
};
|
||||
|
||||
class Globals
|
||||
@ -53,9 +55,6 @@ public:
|
||||
TextureType texType;
|
||||
ZGame game;
|
||||
GameConfig cfg;
|
||||
bool warnUnaccounted = false;
|
||||
bool warnNoOffset = false;
|
||||
bool errorNoOffset = false;
|
||||
bool verboseUnaccounted = false;
|
||||
bool gccCompat = false;
|
||||
bool forceStatic = false;
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <stdexcept>
|
||||
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "WarningHandler.h"
|
||||
|
||||
/* ImageBackend */
|
||||
|
||||
@ -20,19 +21,28 @@ void ImageBackend::ReadPng(const char* filename)
|
||||
|
||||
FILE* fp = fopen(filename, "rb");
|
||||
if (fp == nullptr)
|
||||
throw std::runtime_error(StringHelper::Sprintf(
|
||||
"ImageBackend::ReadPng: Error.\n\t Couldn't open file '%s'.", filename));
|
||||
{
|
||||
std::string errorHeader = StringHelper::Sprintf("could not open file '%s'", filename);
|
||||
HANDLE_ERROR(WarningType::InvalidPNG, errorHeader, "");
|
||||
}
|
||||
|
||||
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!png)
|
||||
throw std::runtime_error("ImageBackend::ReadPng: Error.\n\t Couldn't create png struct.");
|
||||
if (png == nullptr)
|
||||
{
|
||||
HANDLE_ERROR(WarningType::InvalidPNG, "could not create png struct", "");
|
||||
}
|
||||
|
||||
png_infop info = png_create_info_struct(png);
|
||||
if (!info)
|
||||
throw std::runtime_error("ImageBackend::ReadPng: Error.\n\t Couldn't create png info.");
|
||||
if (info == nullptr)
|
||||
{
|
||||
HANDLE_ERROR(WarningType::InvalidPNG, "could not create png info", "");
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png)))
|
||||
throw std::runtime_error("ImageBackend::ReadPng: Error.\n\t setjmp(png_jmpbuf(png)).");
|
||||
{
|
||||
// TODO: better warning explanation
|
||||
HANDLE_ERROR(WarningType::InvalidPNG, "setjmp(png_jmpbuf(png))", "");
|
||||
}
|
||||
|
||||
png_init_io(png, fp);
|
||||
|
||||
@ -145,20 +155,30 @@ void ImageBackend::WritePng(const char* filename)
|
||||
assert(hasImageData);
|
||||
|
||||
FILE* fp = fopen(filename, "wb");
|
||||
if (!fp)
|
||||
throw std::runtime_error(StringHelper::Sprintf(
|
||||
"ImageBackend::WritePng: Error.\n\t Couldn't open file '%s' in write mode.", filename));
|
||||
if (fp == nullptr)
|
||||
{
|
||||
std::string errorHeader =
|
||||
StringHelper::Sprintf("could not open file '%s' in write mode", filename);
|
||||
HANDLE_ERROR(WarningType::InvalidPNG, errorHeader, "");
|
||||
}
|
||||
|
||||
png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!png)
|
||||
throw std::runtime_error("ImageBackend::WritePng: Error.\n\t Couldn't create png struct.");
|
||||
if (png == nullptr)
|
||||
{
|
||||
HANDLE_ERROR(WarningType::InvalidPNG, "could not create png struct", "");
|
||||
}
|
||||
|
||||
png_infop info = png_create_info_struct(png);
|
||||
if (!info)
|
||||
throw std::runtime_error("ImageBackend::WritePng: Error.\n\t Couldn't create png info.");
|
||||
if (info == nullptr)
|
||||
{
|
||||
HANDLE_ERROR(WarningType::InvalidPNG, "could not create png info", "");
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png)))
|
||||
throw std::runtime_error("ImageBackend::WritePng: Error.\n\t setjmp(png_jmpbuf(png)).");
|
||||
{
|
||||
// TODO: better warning description
|
||||
HANDLE_ERROR(WarningType::InvalidPNG, "setjmp(png_jmpbuf(png))", "");
|
||||
}
|
||||
|
||||
png_init_io(png, fp);
|
||||
|
||||
@ -441,7 +461,7 @@ double ImageBackend::GetBytesPerPixel() const
|
||||
return 1 * bitDepth / 8;
|
||||
|
||||
default:
|
||||
throw std::invalid_argument("ImageBackend::GetBytesPerPixel():\n\t Invalid color type.");
|
||||
HANDLE_ERROR(WarningType::InvalidPNG, "invalid color type", "");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
#include <Utils/Directory.h>
|
||||
#include <Utils/File.h>
|
||||
#include <Utils/Path.h>
|
||||
#include "Globals.h"
|
||||
#include "Overlays/ZOverlay.h"
|
||||
#include "Utils/Directory.h"
|
||||
#include "Utils/File.h"
|
||||
#include "Utils/Path.h"
|
||||
#include "WarningHandler.h"
|
||||
#include "ZAnimation.h"
|
||||
#include "ZBackground.h"
|
||||
#include "ZBlob.h"
|
||||
@ -12,10 +13,10 @@
|
||||
#if !defined(_MSC_VER) && !defined(__CYGWIN__)
|
||||
#include <csignal>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <cxxabi.h> // for __cxa_demangle
|
||||
#include <dlfcn.h> // for dladdr
|
||||
#include <execinfo.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
@ -47,6 +48,7 @@ void ErrorHandler(int sig)
|
||||
const char* crashEasterEgg[] = {
|
||||
"\tYou've met with a terrible fate, haven't you?",
|
||||
"\tSEA BEARS FOAM. SLEEP BEARS DREAMS. \n\tBOTH END IN THE SAME WAY: CRASSSH!",
|
||||
"ZAPD has fallen and cannot get up."
|
||||
};
|
||||
|
||||
srand(time(nullptr));
|
||||
@ -97,6 +99,9 @@ int main(int argc, char* argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
Globals* g = new Globals();
|
||||
WarningHandler::Init(argc, argv);
|
||||
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if (!strcmp(argv[i], "--version"))
|
||||
@ -109,12 +114,12 @@ int main(int argc, char* argv[])
|
||||
printf("Congratulations!\n");
|
||||
printf("You just found the (unimplemented and undocumented) ZAPD's help message.\n");
|
||||
printf("Feel free to implement it if you want :D\n");
|
||||
|
||||
WarningHandler::PrintHelp();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Globals* g = new Globals;
|
||||
|
||||
// Parse other "commands"
|
||||
for (int32_t i = 2; i < argc; i++)
|
||||
{
|
||||
@ -186,26 +191,15 @@ int main(int argc, char* argv[])
|
||||
signal(SIGSEGV, ErrorHandler);
|
||||
signal(SIGABRT, ErrorHandler);
|
||||
#else
|
||||
fprintf(stderr,
|
||||
"Warning: Tried to set error handler, but this build lacks support for one.\n");
|
||||
HANDLE_WARNING(WarningType::Always,
|
||||
"tried to set error handler, but this ZAPD build lacks support for one",
|
||||
"");
|
||||
#endif
|
||||
}
|
||||
else if (arg == "-v") // Verbose
|
||||
{
|
||||
Globals::Instance->verbosity = static_cast<VerbosityLevel>(strtol(argv[++i], NULL, 16));
|
||||
}
|
||||
else if (arg == "-wu" || arg == "--warn-unaccounted") // Warn unaccounted
|
||||
{
|
||||
Globals::Instance->warnUnaccounted = true;
|
||||
}
|
||||
else if (arg == "-wno" || arg == "--warn-no-offset")
|
||||
{
|
||||
Globals::Instance->warnNoOffset = true;
|
||||
}
|
||||
else if (arg == "-eno" || arg == "--error-no-offset")
|
||||
{
|
||||
Globals::Instance->errorNoOffset = true;
|
||||
}
|
||||
else if (arg == "-vu" || arg == "--verbose-unaccounted") // Verbose unaccounted
|
||||
{
|
||||
Globals::Instance->verboseUnaccounted = true;
|
||||
@ -262,6 +256,11 @@ int main(int argc, char* argv[])
|
||||
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO)
|
||||
printf("ZAPD: Zelda Asset Processor For Decomp: %s\n", gBuildHash);
|
||||
|
||||
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG)
|
||||
{
|
||||
WarningHandler::PrintWarningsDebugInfo();
|
||||
}
|
||||
|
||||
// TODO: switch
|
||||
if (fileMode == ZFileMode::Extract || fileMode == ZFileMode::BuildSourceFile)
|
||||
{
|
||||
@ -334,7 +333,9 @@ bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path
|
||||
|
||||
if (eResult != tinyxml2::XML_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Invalid xml file: '%s'\n", xmlFilePath.c_str());
|
||||
// TODO: use XMLDocument::ErrorIDToName to get more specific error messages here
|
||||
HANDLE_ERROR(WarningType::InvalidXML,
|
||||
StringHelper::Sprintf("invalid XML file: '%s'", xmlFilePath.c_str()), "");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -342,7 +343,9 @@ bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path
|
||||
|
||||
if (root == nullptr)
|
||||
{
|
||||
fprintf(stderr, "Missing Root tag in xml file: '%s'\n", xmlFilePath.c_str());
|
||||
HANDLE_WARNING(
|
||||
WarningType::InvalidXML,
|
||||
StringHelper::Sprintf("missing Root tag in xml file: '%s'", xmlFilePath.c_str()), "");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -392,10 +395,11 @@ bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error(StringHelper::Sprintf(
|
||||
"Parse: Fatal error in '%s'.\n\t A resource was found outside of "
|
||||
"a File element: '%s'\n",
|
||||
xmlFilePath.c_str(), child->Name()));
|
||||
std::string errorHeader =
|
||||
StringHelper::Sprintf("when parsing file '%s'", xmlFilePath.c_str());
|
||||
std::string errorBody = StringHelper::Sprintf(
|
||||
"Found a resource outside a File element: '%s'", child->Name());
|
||||
HANDLE_ERROR(WarningType::InvalidXML, errorHeader, errorBody);
|
||||
}
|
||||
}
|
||||
|
||||
|
0
tools/ZAPD/ZAPD/NuGet/libpng.static.txt
Normal file
0
tools/ZAPD/ZAPD/NuGet/libpng.static.txt
Normal file
@ -1,13 +1,13 @@
|
||||
#include "ZOverlay.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <cassert>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <Utils/Directory.h>
|
||||
#include <Utils/File.h>
|
||||
#include <Utils/Path.h>
|
||||
#include <Utils/StringHelper.h>
|
||||
#include "Globals.h"
|
||||
#include "Utils/Directory.h"
|
||||
#include "Utils/File.h"
|
||||
#include "Utils/Path.h"
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "WarningHandler.h"
|
||||
|
||||
using namespace ELFIO;
|
||||
|
||||
@ -90,7 +90,7 @@ ZOverlay* ZOverlay::FromBuild(fs::path buildPath, fs::path cfgFolderPath)
|
||||
std::vector<elfio*> readers;
|
||||
for (size_t i = 1; i < cfgLines.size(); i++)
|
||||
{
|
||||
std::string elfPath = buildPath / (cfgLines[i].substr(0, cfgLines[i].size() - 2) + ".o");
|
||||
std::string elfPath = (buildPath / (cfgLines[i].substr(0, cfgLines[i].size() - 2) + ".o")).string();
|
||||
elfio* reader = new elfio();
|
||||
|
||||
if (!reader->load(elfPath))
|
||||
@ -128,7 +128,9 @@ ZOverlay* ZOverlay::FromBuild(fs::path buildPath, fs::path cfgFolderPath)
|
||||
SectionType sectionType = GetSectionTypeFromStr(pSec->get_name());
|
||||
|
||||
if (sectionType == SectionType::ERROR)
|
||||
fprintf(stderr, "WARNING: One of the section types returned ERROR\n");
|
||||
{
|
||||
HANDLE_WARNING(WarningType::Always, "one of the section types returned ERROR", "");
|
||||
}
|
||||
|
||||
relocation_section_accessor relocs(*curReader, pSec);
|
||||
for (Elf_Xword j = 0; j < relocs.get_entries_num(); j++)
|
||||
|
443
tools/ZAPD/ZAPD/WarningHandler.cpp
Normal file
443
tools/ZAPD/ZAPD/WarningHandler.cpp
Normal file
@ -0,0 +1,443 @@
|
||||
/**
|
||||
* ZAPD Warning- and Error-handling system
|
||||
* =======================================
|
||||
*
|
||||
* This provides a common standard way to write ZAPD warnings/errors, which should be used for all
|
||||
* such. It will pretty-print them in a uniform way, with styles defined in the header.
|
||||
*
|
||||
* Warnings/errors should be constructed using the macros given in the header; there are now plenty
|
||||
* of examples in the codebase of how to do this. Their purposes are noted above each category in
|
||||
* the header. Each warning has a type, one of the ones in warningStringToInitMap, or
|
||||
* WarningType::Always, which is used for warnings that cannot be disabled and do not display a
|
||||
* type.
|
||||
*
|
||||
* Currently there are three levels of alert a warning can have:
|
||||
* - Off (does not display anything)
|
||||
* - Warn (print a warning but continue processing)
|
||||
* - Err (behave like an error, i.e. print and throw an exception to crash ZAPD when occurs)
|
||||
*
|
||||
* Flag use:
|
||||
* - -Wfoo enables warnings of type foo
|
||||
* - -Wno-foo disables warnings of type foo
|
||||
* - -Werror=foo escalates foo to behave like an error
|
||||
* - -Weverything enables all warnings
|
||||
* - -Werror escalates all enabled warnings to errors
|
||||
*
|
||||
* Errors do not have types, and will always throw an exception; they cannot be disabled.
|
||||
*
|
||||
* Format
|
||||
* ===
|
||||
* Each printed warning/error contains the same three sections:
|
||||
* - Preamble: automatically generated; the content varies depending on category. It will print the
|
||||
* file and function that the warning is from, and information about the files being processed
|
||||
* or extracted.
|
||||
* - Header: begins with 'warning: ' or 'error:', should contain essential information about the
|
||||
* warning/error, ends with the warning type if applicable. Printed with emphasis to make it
|
||||
* stand out. Does not start with a capital letter or end with a '.'
|
||||
* - Body (optional): indented, should contain further diagnostic information useful for identifying
|
||||
* and fixing the warning/error. Can be a sentence with captialisation and '.' on the end.
|
||||
*
|
||||
* Please think of what the end user will find most useful when writing the header and body, and try
|
||||
* to keep it brief without sacrificing important information! Also remember that if the user is
|
||||
* only looking at stderr, they will normally have no other context.
|
||||
*
|
||||
* Warning vs error
|
||||
* ===
|
||||
* The principle that we have operated on so far is
|
||||
* - issue a warning if ZAPD will still be able to produce a valid, compilable C file that will
|
||||
* match
|
||||
* - if this cannot happen, use an error.
|
||||
* but at the end of the day, it is up to the programmer's discretion what it should be possible to
|
||||
* disable.
|
||||
*
|
||||
* Documentation
|
||||
* ===
|
||||
* Remember that all warnings also need to be documented in the README.md. The help is generated
|
||||
* automatically.
|
||||
*/
|
||||
#include "WarningHandler.h"
|
||||
|
||||
#include <cassert>
|
||||
#include "Globals.h"
|
||||
#include "Utils/StringHelper.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WarningType type;
|
||||
WarningLevel defaultLevel;
|
||||
std::string description;
|
||||
} WarningInfoInit;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WarningLevel level;
|
||||
std::string name;
|
||||
std::string description;
|
||||
} WarningInfo;
|
||||
|
||||
/**
|
||||
* Master list of all default warning types and features
|
||||
*
|
||||
* To add a warning type, fill in a new row of this map. Think carefully about what its default
|
||||
* level should be, and try and make the description both brief and informative: it is used in the
|
||||
* help message, so again, think about what the end user needs to know.
|
||||
*/
|
||||
// clang-format off
|
||||
static const std::unordered_map<std::string, WarningInfoInit> warningStringToInitMap = {
|
||||
{"deprecated", {WarningType::Deprecated,
|
||||
#ifdef DEPRECATION_ON
|
||||
WarningLevel::Warn,
|
||||
#else
|
||||
WarningLevel::Off,
|
||||
#endif
|
||||
"Deprecated features"}},
|
||||
{"unaccounted", {WarningType::Unaccounted, WarningLevel::Off, "Large blocks of unaccounted"}},
|
||||
{"missing-offsets", {WarningType::MissingOffsets, WarningLevel::Warn, "Offset attribute missing in XML tag"}},
|
||||
{"intersection", {WarningType::Intersection, WarningLevel::Warn, "Two assets intersect"}},
|
||||
{"missing-attribute", {WarningType::MissingAttribute, WarningLevel::Warn, "Required attribute missing in XML tag"}},
|
||||
{"invalid-attribute-value", {WarningType::InvalidAttributeValue, WarningLevel::Err, "Attribute declared in XML is wrong"}},
|
||||
{"unknown-attribute", {WarningType::UnknownAttribute, WarningLevel::Warn, "Unknown attribute in XML entry tag"}},
|
||||
{"invalid-xml", {WarningType::InvalidXML, WarningLevel::Err, "XML has syntax errors"}},
|
||||
{"invalid-jpeg", {WarningType::InvalidJPEG, WarningLevel::Err, "JPEG file does not conform to the game's format requirements"}},
|
||||
{"invalid-png", {WarningType::InvalidPNG, WarningLevel::Err, "Issues arising when processing PNG data"}},
|
||||
{"invalid-extracted-data", {WarningType::InvalidExtractedData, WarningLevel::Err, "Extracted data does not have correct form"}},
|
||||
{"missing-segment", {WarningType::MissingSegment, WarningLevel::Warn, "Segment not given in File tag in XML"}},
|
||||
{"hardcoded-pointer", {WarningType::HardcodedPointer, WarningLevel::Warn, "ZAPD lacks the info to make a symbol, so must output a hardcoded pointer"}},
|
||||
{"not-implemented", {WarningType::NotImplemented, WarningLevel::Warn, "ZAPD does not currently support this feature"}},
|
||||
};
|
||||
|
||||
/**
|
||||
* Map constructed at runtime to contain the warning features as set by the user using -W flags.
|
||||
*/
|
||||
static std::unordered_map<WarningType, WarningInfo> warningTypeToInfoMap;
|
||||
|
||||
void WarningHandler::ConstructTypeToInfoMap() {
|
||||
for (auto& entry : warningStringToInitMap) {
|
||||
warningTypeToInfoMap[entry.second.type] = {entry.second.defaultLevel, entry.first, entry.second.description};
|
||||
}
|
||||
warningTypeToInfoMap[WarningType::Always] = {WarningLevel::Warn, "always", "you shouldn't be reading this"};
|
||||
assert(warningTypeToInfoMap.size() == static_cast<size_t>(WarningType::Max));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises the main warning type map and reads flags passed to set each warning type's level.
|
||||
*/
|
||||
void WarningHandler::Init(int argc, char* argv[]) {
|
||||
ConstructTypeToInfoMap();
|
||||
|
||||
bool werror = false;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
// If it doesn't start with "-W" skip it.
|
||||
if (argv[i][0] != '-' || argv[i][1] != 'W' || argv[i][2] == '\0') {
|
||||
continue;
|
||||
}
|
||||
|
||||
WarningLevel warningTypeOn = WarningLevel::Warn;
|
||||
size_t startingIndex = 2;
|
||||
|
||||
// "-Wno-"
|
||||
if (argv[i][2] == 'n' && argv[i][3] == 'o' && argv[i][4] == '-' && argv[i][5] != '\0') {
|
||||
warningTypeOn = WarningLevel::Off;
|
||||
startingIndex = 5;
|
||||
}
|
||||
|
||||
// Read starting after the "-W" or "-Wno-"
|
||||
std::string_view currentArgv = &argv[i][startingIndex];
|
||||
|
||||
if (currentArgv == "error") {
|
||||
werror = warningTypeOn != WarningLevel::Off;
|
||||
} else if (currentArgv == "everything") {
|
||||
for (auto& it: warningTypeToInfoMap) {
|
||||
if (it.second.level <= WarningLevel::Warn) {
|
||||
it.second.level = warningTypeOn;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// "-Werror=" / "-Wno-error=" parser
|
||||
if (currentArgv.rfind("error=", 0) == 0) {
|
||||
// Read starting after the "error=" part
|
||||
currentArgv = &argv[i][startingIndex + 6];
|
||||
warningTypeOn = warningTypeOn != WarningLevel::Off ? WarningLevel::Err : WarningLevel::Warn;
|
||||
}
|
||||
|
||||
auto it = warningStringToInitMap.find(std::string(currentArgv));
|
||||
if (it != warningStringToInitMap.end()) {
|
||||
warningTypeToInfoMap[it->second.type].level = warningTypeOn;
|
||||
}
|
||||
else {
|
||||
HANDLE_WARNING(WarningType::Always, StringHelper::Sprintf("unknown warning flag '%s'", argv[i]), "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (werror) {
|
||||
for (auto& it: warningTypeToInfoMap) {
|
||||
if (it.second.level >= WarningLevel::Warn) {
|
||||
it.second.level = WarningLevel::Err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool WarningHandler::IsWarningEnabled(WarningType warnType) {
|
||||
assert(static_cast<size_t>(warnType) >= 0 && warnType < WarningType::Max);
|
||||
|
||||
return warningTypeToInfoMap.at(warnType).level != WarningLevel::Off;
|
||||
}
|
||||
|
||||
bool WarningHandler::WasElevatedToError(WarningType warnType) {
|
||||
assert(static_cast<size_t>(warnType) >= 0 && warnType < WarningType::Max);
|
||||
|
||||
if (!IsWarningEnabled(warnType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return warningTypeToInfoMap.at(warnType).level >= WarningLevel::Err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print file/line/function info for debugging
|
||||
*/
|
||||
void WarningHandler::FunctionPreamble(const char* filename, int32_t line, const char* function) {
|
||||
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG) {
|
||||
fprintf(stderr, "%s:%i: in function %s:\n", filename, line, function);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the information about the file(s) being processed (XML for extraction, png etc. for building)
|
||||
*/
|
||||
void WarningHandler::ProcessedFilePreamble() {
|
||||
if (Globals::Instance->inputPath != "") {
|
||||
fprintf(stderr, "When processing file %s: ", Globals::Instance->inputPath.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print information about the binary file being extracted
|
||||
*/
|
||||
void WarningHandler::ExtractedFilePreamble(const ZFile *parent, const ZResource* res, const uint32_t offset) {
|
||||
fprintf(stderr, "in input binary file %s, ", parent->GetName().c_str());
|
||||
if (res != nullptr) {
|
||||
fprintf(stderr, "resource '%s' at ", res->GetName().c_str());
|
||||
}
|
||||
fprintf(stderr, "offset 0x%06X: \n\t", offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the rest of the message, after warning:/error. The message is filled in one character at a time, with indents added after newlines
|
||||
*/
|
||||
std::string WarningHandler::ConstructMessage(std::string message, const std::string& header, const std::string& body) {
|
||||
message.reserve(message.size() + header.size() + body.size() + 10 * (sizeof(HANG_INDT) - 1));
|
||||
message += StringHelper::Sprintf(HILITE("%s"), header.c_str());
|
||||
message += "\n";
|
||||
|
||||
if (body == "") {
|
||||
return message;
|
||||
}
|
||||
|
||||
message += HANG_INDT;
|
||||
for (const char* ptr = body.c_str(); *ptr != '\0'; ptr++) {
|
||||
message += *ptr;
|
||||
if (*ptr == '\n') {
|
||||
message += HANG_INDT;
|
||||
}
|
||||
}
|
||||
message += "\n";
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/* Error module functions */
|
||||
|
||||
void WarningHandler::PrintErrorAndThrow(const std::string& header, const std::string& body) {
|
||||
std::string errorMsg = ERR_FMT("error: ");
|
||||
throw std::runtime_error(ConstructMessage(errorMsg, header, body));
|
||||
}
|
||||
|
||||
/* Error types, to be used via the macros */
|
||||
|
||||
void WarningHandler::ErrorType(WarningType warnType, const std::string& header, const std::string& body) {
|
||||
std::string headerMsg = header;
|
||||
|
||||
for (const auto& iter: warningStringToInitMap) {
|
||||
if (iter.second.type == warnType) {
|
||||
headerMsg += StringHelper::Sprintf(" [%s]", iter.first.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
PrintErrorAndThrow(headerMsg, body);
|
||||
}
|
||||
|
||||
void WarningHandler::Error_Plain(const char* filename, int32_t line, const char* function, WarningType warnType, const std::string& header, const std::string& body) {
|
||||
FunctionPreamble(filename, line, function);
|
||||
|
||||
ErrorType(warnType, header, body);
|
||||
}
|
||||
|
||||
void WarningHandler::Error_Process(const char* filename, int32_t line, const char* function, WarningType warnType, const std::string& header, const std::string& body) {
|
||||
FunctionPreamble(filename, line, function);
|
||||
ProcessedFilePreamble();
|
||||
|
||||
ErrorType(warnType, header, body);
|
||||
}
|
||||
|
||||
void WarningHandler::Error_Resource(const char* filename, int32_t line, const char* function, WarningType warnType, const ZFile *parent, const ZResource* res, const uint32_t offset, const std::string& header, const std::string& body) {
|
||||
assert(parent != nullptr);
|
||||
|
||||
FunctionPreamble(filename, line, function);
|
||||
ProcessedFilePreamble();
|
||||
ExtractedFilePreamble(parent, res, offset);
|
||||
|
||||
ErrorType(warnType, header, body);
|
||||
}
|
||||
|
||||
/* Warning module functions */
|
||||
|
||||
void WarningHandler::PrintWarningBody(const std::string& header, const std::string& body) {
|
||||
std::string errorMsg = WARN_FMT("warning: ");
|
||||
fprintf(stderr, "%s", ConstructMessage(errorMsg, header, body).c_str());
|
||||
}
|
||||
|
||||
void WarningHandler::WarningTypeAndChooseEscalate(WarningType warnType, const std::string& header, const std::string& body) {
|
||||
std::string headerMsg = header;
|
||||
|
||||
for (const auto& iter: warningStringToInitMap) {
|
||||
if (iter.second.type == warnType) {
|
||||
headerMsg += StringHelper::Sprintf(" [-W%s]", iter.first.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (WasElevatedToError(warnType)) {
|
||||
PrintErrorAndThrow(headerMsg, body);
|
||||
} else {
|
||||
PrintWarningBody(headerMsg, body);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Warning types, to be used via the macros */
|
||||
|
||||
void WarningHandler::Warning_Plain(const char* filename, int32_t line, const char* function, WarningType warnType, const std::string& header, const std::string& body) {
|
||||
if (!IsWarningEnabled(warnType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
FunctionPreamble(filename, line, function);
|
||||
|
||||
WarningTypeAndChooseEscalate(warnType, header, body);
|
||||
}
|
||||
|
||||
void WarningHandler::Warning_Process(const char* filename, int32_t line, const char* function, WarningType warnType, const std::string& header, const std::string& body) {
|
||||
if (!IsWarningEnabled(warnType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
FunctionPreamble(filename, line, function);
|
||||
ProcessedFilePreamble();
|
||||
|
||||
WarningTypeAndChooseEscalate(warnType, header, body);
|
||||
}
|
||||
|
||||
void WarningHandler::Warning_Resource(const char* filename, int32_t line, const char* function, WarningType warnType, const ZFile *parent, const ZResource* res, const uint32_t offset, const std::string& header, const std::string& body) {
|
||||
assert(parent != nullptr);
|
||||
|
||||
if (!IsWarningEnabled(warnType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
FunctionPreamble(filename, line, function);
|
||||
ProcessedFilePreamble();
|
||||
ExtractedFilePreamble(parent, res, offset);
|
||||
|
||||
WarningTypeAndChooseEscalate(warnType, header, body);
|
||||
}
|
||||
|
||||
|
||||
/* Help-related functions */
|
||||
|
||||
#include <set>
|
||||
|
||||
/**
|
||||
* Print each warning name, default status, and description using the init map
|
||||
*/
|
||||
void WarningHandler::PrintHelp() {
|
||||
std::set<std::string> sortedKeys;
|
||||
WarningInfoInit warningInfo;
|
||||
uint32_t columnWidth = 25;
|
||||
std::string dt;
|
||||
|
||||
// Sort keys through the magic of `set`, to print in alphabetical order
|
||||
for (auto& it : warningStringToInitMap) {
|
||||
sortedKeys.insert(it.first);
|
||||
}
|
||||
|
||||
printf("\nWarning types ( * means enabled by default)\n");
|
||||
for (auto& key : sortedKeys) {
|
||||
warningInfo = warningStringToInitMap.at(key);
|
||||
if (warningInfo.defaultLevel <= WarningLevel::Warn) {
|
||||
dt = "-W";
|
||||
dt += key;
|
||||
if (warningInfo.defaultLevel == WarningLevel::Warn) {
|
||||
dt += " *";
|
||||
}
|
||||
printf(HELP_DT_INDT "%-*s", columnWidth, dt.c_str());
|
||||
|
||||
if (dt.length() + 2 > columnWidth) {
|
||||
printf("\n" HELP_DT_INDT "%-*s", columnWidth, "");
|
||||
}
|
||||
printf("%s\n", warningInfo.description.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
printf("\nDefault errors\n");
|
||||
for (auto& key : sortedKeys) {
|
||||
if (warningInfo.defaultLevel > WarningLevel::Warn) {
|
||||
dt = "-W";
|
||||
dt += key;
|
||||
printf(HELP_DT_INDT "%-*s", columnWidth, dt.c_str());
|
||||
|
||||
if (dt.length() + 2 > columnWidth) {
|
||||
printf("\n" HELP_DT_INDT "%*s", columnWidth, "");
|
||||
}
|
||||
printf("%s\n", warningInfo.description.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
printf("Other\n" HELP_DT_INDT "-Weverything will enable all existing warnings.\n" HELP_DT_INDT "-Werror will promote all warnings to errors.\n");
|
||||
|
||||
printf("\n");
|
||||
printf("Warnings can be disabled using -Wno-... instead of -W...; -Weverything will override any -Wno-... flags passed before it.\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Print which warnings are currently enabled
|
||||
*/
|
||||
void WarningHandler::PrintWarningsDebugInfo()
|
||||
{
|
||||
std::string dt;
|
||||
|
||||
printf("Warnings status:\n");
|
||||
for (auto& it: warningTypeToInfoMap) {
|
||||
dt = it.second.name;
|
||||
dt += ": ";
|
||||
|
||||
printf(HELP_DT_INDT "%-25s", dt.c_str());
|
||||
switch (it.second.level)
|
||||
{
|
||||
case WarningLevel::Off:
|
||||
printf(VT_FGCOL(LIGHTGRAY) "Off" VT_RST);
|
||||
break;
|
||||
case WarningLevel::Warn:
|
||||
printf(VT_FGCOL(YELLOW) "Warn" VT_RST);
|
||||
break;
|
||||
case WarningLevel::Err:
|
||||
printf(VT_FGCOL(RED) "Err" VT_RST);
|
||||
break;
|
||||
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
145
tools/ZAPD/ZAPD/WarningHandler.h
Normal file
145
tools/ZAPD/ZAPD/WarningHandler.h
Normal file
@ -0,0 +1,145 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "Utils/vt.h"
|
||||
#include "ZFile.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define __PRETTY_FUNCTION__ __FUNCSIG__
|
||||
#elif not defined(__GNUC__)
|
||||
#define __PRETTY_FUNCTION__ __func__
|
||||
#endif
|
||||
|
||||
// =======================================
|
||||
/* Formatting macros */
|
||||
|
||||
// TODO: move this somewhere else so it can be used by other help
|
||||
#define HELP_DT_INDT " "
|
||||
|
||||
/* Macros for formatting warnings/errors */
|
||||
#define VT_HILITE VT_BOLD_FGCOL(WHITE)
|
||||
#define VT_WARN VT_BOLD_FGCOL(PURPLE)
|
||||
#define VT_ERR VT_BOLD_FGCOL(RED)
|
||||
|
||||
#define HILITE(string) (VT_HILITE string VT_RST)
|
||||
#define WARN_FMT(string) (VT_WARN string VT_RST)
|
||||
#define ERR_FMT(string) (VT_ERR string VT_RST)
|
||||
|
||||
// Maybe make WARN_LF instead
|
||||
// Currently 8 spaces
|
||||
#define WARN_INDT " "
|
||||
// Currently 16 spaces
|
||||
#define HANG_INDT " "
|
||||
|
||||
// =======================================
|
||||
/* Warning and error macros */
|
||||
// TODO: better names
|
||||
|
||||
// General-purpose, plain style (only prints function,file,line in the preamble)
|
||||
#define HANDLE_ERROR(warningType, header, body) \
|
||||
WarningHandler::Error_Plain(__FILE__, __LINE__, __PRETTY_FUNCTION__, warningType, header, body)
|
||||
#define HANDLE_WARNING(warningType, header, body) \
|
||||
WarningHandler::Warning_Plain(__FILE__, __LINE__, __PRETTY_FUNCTION__, warningType, header, \
|
||||
body)
|
||||
|
||||
// For processing XMLs or textures/blobs (preamble contains function,file,line; processed file)
|
||||
#define HANDLE_ERROR_PROCESS(warningType, header, body) \
|
||||
WarningHandler::Error_Process(__FILE__, __LINE__, __PRETTY_FUNCTION__, warningType, header, \
|
||||
body)
|
||||
#define HANDLE_WARNING_PROCESS(warningType, header, body) \
|
||||
WarningHandler::Warning_Process(__FILE__, __LINE__, __PRETTY_FUNCTION__, warningType, header, \
|
||||
body)
|
||||
|
||||
// For ZResource-related stuff (preamble contains function,file,line; processed file; extracted file
|
||||
// and offset)
|
||||
#define HANDLE_ERROR_RESOURCE(warningType, parent, resource, offset, header, body) \
|
||||
WarningHandler::Error_Resource(__FILE__, __LINE__, __PRETTY_FUNCTION__, warningType, parent, \
|
||||
resource, offset, header, body)
|
||||
#define HANDLE_WARNING_RESOURCE(warningType, parent, resource, offset, header, body) \
|
||||
WarningHandler::Warning_Resource(__FILE__, __LINE__, __PRETTY_FUNCTION__, warningType, parent, \
|
||||
resource, offset, header, body)
|
||||
|
||||
// =======================================
|
||||
|
||||
enum class WarningType
|
||||
{
|
||||
Always, // Warnings of this type are always printed, cannot be disabled.
|
||||
Deprecated,
|
||||
Unaccounted,
|
||||
MissingOffsets,
|
||||
Intersection,
|
||||
MissingAttribute,
|
||||
InvalidAttributeValue,
|
||||
UnknownAttribute,
|
||||
InvalidXML,
|
||||
InvalidJPEG,
|
||||
InvalidPNG,
|
||||
InvalidExtractedData,
|
||||
MissingSegment,
|
||||
HardcodedPointer,
|
||||
NotImplemented,
|
||||
Max,
|
||||
};
|
||||
|
||||
enum class WarningLevel
|
||||
{
|
||||
Off,
|
||||
Warn,
|
||||
Err,
|
||||
};
|
||||
|
||||
class WarningHandler
|
||||
{
|
||||
public:
|
||||
static void ConstructTypeToInfoMap();
|
||||
|
||||
static void Init(int argc, char* argv[]);
|
||||
|
||||
static bool IsWarningEnabled(WarningType warnType);
|
||||
static bool WasElevatedToError(WarningType warnType);
|
||||
|
||||
static void FunctionPreamble(const char* filename, int32_t line, const char* function);
|
||||
static void ProcessedFilePreamble();
|
||||
static void ExtractedFilePreamble(const ZFile* parent, const ZResource* res,
|
||||
const uint32_t offset);
|
||||
static std::string ConstructMessage(std::string message, const std::string& header,
|
||||
const std::string& body);
|
||||
|
||||
[[noreturn]] static void PrintErrorAndThrow(const std::string& header, const std::string& body);
|
||||
static void PrintWarningBody(const std::string& header, const std::string& body);
|
||||
|
||||
[[noreturn]] static void ErrorType(WarningType warnType, const std::string& header,
|
||||
const std::string& body);
|
||||
[[noreturn]] static void Error_Plain(const char* filename, int32_t line, const char* function,
|
||||
WarningType warnType, const std::string& header,
|
||||
const std::string& body);
|
||||
[[noreturn]] static void Error_Process(const char* filename, int32_t line, const char* function,
|
||||
WarningType warnType, const std::string& header,
|
||||
const std::string& body);
|
||||
[[noreturn]] static void Error_Resource(const char* filename, int32_t line,
|
||||
const char* function, WarningType warnType,
|
||||
const ZFile* parent, const ZResource* res,
|
||||
const uint32_t offset, const std::string& header,
|
||||
const std::string& body);
|
||||
|
||||
static void WarningTypeAndChooseEscalate(WarningType warnType, const std::string& header,
|
||||
const std::string& body);
|
||||
|
||||
static void Warning_Plain(const char* filename, int32_t line, const char* function,
|
||||
WarningType warnType, const std::string& header,
|
||||
const std::string& body);
|
||||
static void Warning_Process(const char* filename, int32_t line, const char* function,
|
||||
WarningType warnType, const std::string& header,
|
||||
const std::string& body);
|
||||
static void Warning_Resource(const char* filename, int32_t line, const char* function,
|
||||
WarningType warnType, const ZFile* parent, const ZResource* res,
|
||||
const uint32_t offset, const std::string& header,
|
||||
const std::string& body);
|
||||
|
||||
static void PrintHelp();
|
||||
static void PrintWarningsDebugInfo();
|
||||
};
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\packages\YY.NuGet.Import.Helper.1.0.0.4\build\native\YY.NuGet.Import.Helper.props" Condition="Exists('..\packages\YY.NuGet.Import.Helper.1.0.0.4\build\native\YY.NuGet.Import.Helper.props')" />
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
@ -71,8 +72,8 @@
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LibraryPath>$(SolutionDir)lib\libgfxd;$(SolutionDir)x64\Debug;$(SolutionDir)packages\libpng.1.6.28.1\build\native\lib\x64\v140\dynamic\Debug;$(LibraryPath)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)ZAPDUtils;$(SolutionDir)lib\tinyxml2;$(SolutionDir)lib\libgfxd;$(SolutionDir)lib\elfio;$(SolutionDir)lib\stb;$(ProjectDir);$(IncludePath)</IncludePath>
|
||||
<LibraryPath>$(OutDir);$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\packages\libpng-v142.1.6.37.2\build\native\lib\x64\v142\Debug\;$(LibraryPath)</LibraryPath>
|
||||
<IncludePath>$(ProjectDir)..\ZAPDUtils;$(ProjectDir)..\lib\tinyxml2;$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\lib\elfio;$(ProjectDir)..\lib\stb;$(ProjectDir);$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
@ -105,13 +106,16 @@
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<LanguageStandard_C>stdc11</LanguageStandard_C>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<Profile>true</Profile>
|
||||
<AdditionalDependencies>libpng16.lib;ZAPDUtils.lib;/WHOLEARCHIVE:ExporterExample.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>ZAPDUtils.lib;/WHOLEARCHIVE:ExporterExample.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>cd ..
|
||||
mkdir build\ZAPD
|
||||
python3 ZAPD/genbuildinfo.py</Command>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
@ -146,6 +150,7 @@ python3 ZAPD/genbuildinfo.py</Command>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\build\ZAPD\BuildInfo.cpp" />
|
||||
<ClCompile Include="..\lib\libgfxd\gfxd.c" />
|
||||
<ClCompile Include="..\lib\libgfxd\uc.c" />
|
||||
<ClCompile Include="..\lib\libgfxd\uc_f3d.c" />
|
||||
@ -153,19 +158,22 @@ python3 ZAPD/genbuildinfo.py</Command>
|
||||
<ClCompile Include="..\lib\libgfxd\uc_f3dex.c" />
|
||||
<ClCompile Include="..\lib\libgfxd\uc_f3dex2.c" />
|
||||
<ClCompile Include="..\lib\libgfxd\uc_f3dexb.c" />
|
||||
<ClCompile Include="..\lib\tinyxml2\tinyxml2.cpp" />
|
||||
<ClCompile Include="Declaration.cpp" />
|
||||
<ClCompile Include="GameConfig.cpp" />
|
||||
<ClCompile Include="Globals.cpp" />
|
||||
<ClCompile Include="ImageBackend.cpp" />
|
||||
<ClCompile Include="Main.cpp" />
|
||||
<ClCompile Include="OtherStructs\SkinLimbStructs.cpp" />
|
||||
<ClCompile Include="OutputFormatter.cpp" />
|
||||
<ClCompile Include="Overlays\ZOverlay.cpp" />
|
||||
<ClCompile Include="WarningHandler.cpp" />
|
||||
<ClCompile Include="ZArray.cpp" />
|
||||
<ClCompile Include="ZBackground.cpp" />
|
||||
<ClCompile Include="ZCutsceneMM.cpp" />
|
||||
<ClCompile Include="ZLimb.cpp" />
|
||||
<ClCompile Include="ZMtx.cpp" />
|
||||
<ClCompile Include="ZPath.cpp" />
|
||||
<ClCompile Include="ZPlayerAnimationData.cpp" />
|
||||
<ClCompile Include="ZRoom\Commands\SetActorCutsceneList.cpp" />
|
||||
<ClCompile Include="ZRoom\Commands\SetAnimatedMaterialList.cpp" />
|
||||
<ClCompile Include="ZRoom\Commands\SetCsCamera.cpp" />
|
||||
@ -213,6 +221,7 @@ python3 ZAPD/genbuildinfo.py</Command>
|
||||
<ClCompile Include="ZString.cpp" />
|
||||
<ClCompile Include="ZSymbol.cpp" />
|
||||
<ClCompile Include="ZTexture.cpp" />
|
||||
<ClCompile Include="ZTextureAnimation.cpp" />
|
||||
<ClCompile Include="ZVector.cpp" />
|
||||
<ClCompile Include="ZVtx.cpp" />
|
||||
</ItemGroup>
|
||||
@ -237,10 +246,13 @@ python3 ZAPD/genbuildinfo.py</Command>
|
||||
<ClInclude Include="..\lib\stb\tinyxml2.h" />
|
||||
<ClInclude Include="CRC32.h" />
|
||||
<ClInclude Include="Declaration.h" />
|
||||
<ClInclude Include="GameConfig.h" />
|
||||
<ClInclude Include="Globals.h" />
|
||||
<ClInclude Include="ImageBackend.h" />
|
||||
<ClInclude Include="OtherStructs\SkinLimbStructs.h" />
|
||||
<ClInclude Include="OutputFormatter.h" />
|
||||
<ClInclude Include="Overlays\ZOverlay.h" />
|
||||
<ClInclude Include="WarningHandler.h" />
|
||||
<ClInclude Include="ZAnimation.h" />
|
||||
<ClInclude Include="ZArray.h" />
|
||||
<ClInclude Include="ZBackground.h" />
|
||||
@ -253,6 +265,7 @@ python3 ZAPD/genbuildinfo.py</Command>
|
||||
<ClInclude Include="ZLimb.h" />
|
||||
<ClInclude Include="ZMtx.h" />
|
||||
<ClInclude Include="ZPath.h" />
|
||||
<ClInclude Include="ZPlayerAnimationData.h" />
|
||||
<ClInclude Include="ZRoom\Commands\SetActorCutsceneList.h" />
|
||||
<ClInclude Include="ZRoom\Commands\SetAnimatedMaterialList.h" />
|
||||
<ClInclude Include="ZRoom\Commands\SetCsCamera.h" />
|
||||
@ -294,6 +307,7 @@ python3 ZAPD/genbuildinfo.py</Command>
|
||||
<ClInclude Include="ZString.h" />
|
||||
<ClInclude Include="ZSymbol.h" />
|
||||
<ClInclude Include="ZTexture.h" />
|
||||
<ClInclude Include="ZTextureAnimation.h" />
|
||||
<ClInclude Include="ZVector.h" />
|
||||
<ClInclude Include="ZVtx.h" />
|
||||
</ItemGroup>
|
||||
@ -301,24 +315,29 @@ python3 ZAPD/genbuildinfo.py</Command>
|
||||
<Text Include="..\SymbolMap_OoTMqDbg.txt">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</Text>
|
||||
<Text Include="any\any\zlib.static.txt" />
|
||||
<Text Include="NuGet\libpng.static.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\packages\libpng.redist.1.6.28.1\build\native\libpng.redist.targets" Condition="Exists('..\packages\libpng.redist.1.6.28.1\build\native\libpng.redist.targets')" />
|
||||
<Import Project="..\packages\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.targets" Condition="Exists('..\packages\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.targets')" />
|
||||
<Import Project="..\packages\zlib.v140.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\zlib.v140.windesktop.msvcstl.dyn.rt-dyn.targets" Condition="Exists('..\packages\zlib.v140.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\zlib.v140.windesktop.msvcstl.dyn.rt-dyn.targets')" />
|
||||
<Import Project="..\packages\libpng.1.6.28.1\build\native\libpng.targets" Condition="Exists('..\packages\libpng.1.6.28.1\build\native\libpng.targets')" />
|
||||
<Import Project="..\packages\YY.NuGet.Import.Helper.1.0.0.4\build\native\YY.NuGet.Import.Helper.targets" Condition="Exists('..\packages\YY.NuGet.Import.Helper.1.0.0.4\build\native\YY.NuGet.Import.Helper.targets')" />
|
||||
<Import Project="..\packages\zlib.static.1.2.5\build\native\zlib.static.targets" Condition="Exists('..\packages\zlib.static.1.2.5\build\native\zlib.static.targets')" />
|
||||
<Import Project="..\packages\libpng.static.1.6.37\build\native\libpng.static.targets" Condition="Exists('..\packages\libpng.static.1.6.37\build\native\libpng.static.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\libpng.redist.1.6.28.1\build\native\libpng.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\libpng.redist.1.6.28.1\build\native\libpng.redist.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\zlib.v140.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\zlib.v140.windesktop.msvcstl.dyn.rt-dyn.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\zlib.v140.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\zlib.v140.windesktop.msvcstl.dyn.rt-dyn.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\libpng.1.6.28.1\build\native\libpng.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\libpng.1.6.28.1\build\native\libpng.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\YY.NuGet.Import.Helper.1.0.0.4\build\native\YY.NuGet.Import.Helper.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\YY.NuGet.Import.Helper.1.0.0.4\build\native\YY.NuGet.Import.Helper.props'))" />
|
||||
<Error Condition="!Exists('..\packages\YY.NuGet.Import.Helper.1.0.0.4\build\native\YY.NuGet.Import.Helper.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\YY.NuGet.Import.Helper.1.0.0.4\build\native\YY.NuGet.Import.Helper.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\zlib.static.1.2.5\build\native\zlib.static.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\zlib.static.1.2.5\build\native\zlib.static.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\libpng.static.1.6.37\build\native\libpng.static.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\libpng.static.1.6.37\build\native\libpng.static.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
@ -49,6 +49,15 @@
|
||||
<Filter Include="Header Files\Libraries\libgfxd">
|
||||
<UniqueIdentifier>{85600275-99fe-491d-8189-bcc3dc1a8903}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="any">
|
||||
<UniqueIdentifier>{ba9990b0-1082-48bb-874c-6108534b5455}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="any\any">
|
||||
<UniqueIdentifier>{ce9d91b0-ba20-4296-bc2d-8630965bb392}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="NuGet">
|
||||
<UniqueIdentifier>{730beb67-6d59-4849-9d9b-702c4a565fc0}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Main.cpp">
|
||||
@ -135,9 +144,6 @@
|
||||
<ClCompile Include="ZRoom\Commands\SetCutscenes.cpp">
|
||||
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lib\tinyxml2\tinyxml2.cpp">
|
||||
<Filter>Source Files\Libraries</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZAnimation.cpp">
|
||||
<Filter>Source Files\Z64</Filter>
|
||||
</ClCompile>
|
||||
@ -258,6 +264,24 @@
|
||||
<ClCompile Include="ZString.cpp">
|
||||
<Filter>Source Files\Z64</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GameConfig.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZTextureAnimation.cpp">
|
||||
<Filter>Source Files\Z64</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="OtherStructs\SkinLimbStructs.cpp">
|
||||
<Filter>Source Files\Z64</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\build\ZAPD\BuildInfo.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZPlayerAnimationData.cpp">
|
||||
<Filter>Source Files\Z64</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="WarningHandler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ZRoom\ZRoom.h">
|
||||
@ -497,11 +521,32 @@
|
||||
<ClInclude Include="ZString.h">
|
||||
<Filter>Header Files\Z64</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GameConfig.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ZTextureAnimation.h">
|
||||
<Filter>Header Files\Z64</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="OtherStructs\SkinLimbStructs.h">
|
||||
<Filter>Header Files\Z64</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ZPlayerAnimationData.h">
|
||||
<Filter>Header Files\Z64</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="WarningHandler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="..\SymbolMap_OoTMqDbg.txt">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Text>
|
||||
<Text Include="any\any\zlib.static.txt">
|
||||
<Filter>any\any</Filter>
|
||||
</Text>
|
||||
<Text Include="NuGet\libpng.static.txt">
|
||||
<Filter>NuGet</Filter>
|
||||
</Text>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "Utils/BitConverter.h"
|
||||
#include "Utils/File.h"
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "WarningHandler.h"
|
||||
#include "ZFile.h"
|
||||
|
||||
REGISTER_ZFILENODE(Animation, ZNormalAnimation);
|
||||
@ -218,11 +219,9 @@ void ZCurveAnimation::ParseXML(tinyxml2::XMLElement* reader)
|
||||
std::string skelOffsetXml = registeredAttributes.at("SkelOffset").value;
|
||||
if (skelOffsetXml == "")
|
||||
{
|
||||
throw std::runtime_error(
|
||||
StringHelper::Sprintf("ZCurveAnimation::ParseXML: Fatal error in '%s'.\n"
|
||||
"\t Missing 'SkelOffset' attribute in ZCurveAnimation.\n"
|
||||
"\t You need to provide the offset of the curve skeleton.",
|
||||
name.c_str()));
|
||||
HANDLE_ERROR_RESOURCE(WarningType::MissingAttribute, parent, this, rawDataIndex,
|
||||
"missing 'SkelOffset' attribute in <ZCurveAnimation>",
|
||||
"You need to provide the offset of the curve skeleton.");
|
||||
}
|
||||
skelOffset = StringHelper::StrToL(skelOffsetXml, 0);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "Vec3s.h"
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "Globals.h"
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "WarningHandler.h"
|
||||
#include "ZFile.h"
|
||||
|
||||
REGISTER_ZFILENODE(Array, ZArray);
|
||||
@ -25,13 +26,18 @@ void ZArray::ParseXML(tinyxml2::XMLElement* reader)
|
||||
ZResource::ParseXML(reader);
|
||||
|
||||
arrayCnt = reader->IntAttribute("Count", 0);
|
||||
// TODO: do a better check.
|
||||
assert(arrayCnt > 0);
|
||||
if (arrayCnt <= 0)
|
||||
{
|
||||
HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
|
||||
"invalid value found for 'Count' attribute", "");
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement* child = reader->FirstChildElement();
|
||||
if (child == nullptr)
|
||||
throw std::runtime_error(
|
||||
StringHelper::Sprintf("Error! Array needs at least one sub-element.\n"));
|
||||
{
|
||||
HANDLE_ERROR_RESOURCE(WarningType::InvalidXML, parent, this, rawDataIndex,
|
||||
"<Array> needs one sub-element", "");
|
||||
}
|
||||
|
||||
childName = child->Name();
|
||||
|
||||
@ -42,9 +48,10 @@ void ZArray::ParseXML(tinyxml2::XMLElement* reader)
|
||||
ZResource* res = nodeMap->at(childName)(parent);
|
||||
if (!res->DoesSupportArray())
|
||||
{
|
||||
throw std::runtime_error(StringHelper::Sprintf(
|
||||
"Error! Resource %s does not support being wrapped in an array!\n",
|
||||
childName.c_str()));
|
||||
std::string errorHeader = StringHelper::Sprintf(
|
||||
"resource <%s> does not support being wrapped in an <Array>", childName.c_str());
|
||||
HANDLE_ERROR_RESOURCE(WarningType::InvalidXML, parent, this, rawDataIndex, errorHeader,
|
||||
"");
|
||||
}
|
||||
res->parent = parent;
|
||||
res->SetInnerNode(true);
|
||||
@ -87,7 +94,7 @@ Declaration* ZArray::DeclareVar(const std::string& prefix, const std::string& bo
|
||||
|
||||
std::string ZArray::GetBodySourceCode() const
|
||||
{
|
||||
std::string output;
|
||||
std::string output = "";
|
||||
|
||||
for (size_t i = 0; i < arrayCnt; i++)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "ZResource.h"
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "Utils/File.h"
|
||||
#include "Utils/Path.h"
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "WarningHandler.h"
|
||||
#include "ZFile.h"
|
||||
|
||||
REGISTER_ZFILENODE(Background, ZBackground);
|
||||
@ -63,52 +64,46 @@ void ZBackground::CheckValidJpeg(const std::string& filepath)
|
||||
uint32_t jpegMarker = BitConverter::ToUInt32BE(data, 0);
|
||||
if (jpegMarker != JPEG_MARKER)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ZBackground::CheckValidJpeg: Warning.\n"
|
||||
"\t Missing jpeg marker at the beginning of file: '%s'.\n"
|
||||
"\t The game will skip this jpeg.\n",
|
||||
filename.c_str());
|
||||
HANDLE_WARNING_PROCESS(
|
||||
WarningType::InvalidJPEG,
|
||||
StringHelper::Sprintf("missing jpeg marker at beginning of file: '%s'",
|
||||
filename.c_str()),
|
||||
"The game will skip this jpeg.");
|
||||
}
|
||||
if (data.at(6) != 'J' || data.at(7) != 'F' || data.at(8) != 'I' || data.at(9) != 'F' ||
|
||||
data.at(10) != '\0')
|
||||
{
|
||||
std::string jfifIdentifier(data.begin() + 6, data.begin() + 6 + 5);
|
||||
fprintf(stderr,
|
||||
"ZBackground::CheckValidJpeg: Warning.\n"
|
||||
"\t Missing 'JFIF' identifier. File: '%s'.\n"
|
||||
"\t This image may be corrupted or not be a jpeg iamge.\n"
|
||||
"\t The identifier found was '%s'.\n",
|
||||
filename.c_str(), jfifIdentifier.c_str());
|
||||
HANDLE_WARNING_PROCESS(
|
||||
WarningType::InvalidJPEG, "missing 'JFIF' identifier",
|
||||
StringHelper::Sprintf(
|
||||
"This image may be corrupted, or not a jpeg. The identifier found was: '%s'",
|
||||
jfifIdentifier.c_str()));
|
||||
}
|
||||
uint8_t majorVersion = data.at(11);
|
||||
uint8_t minorVersion = data.at(12);
|
||||
if (majorVersion != 0x01 || minorVersion != 0x01)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ZBackground::CheckValidJpeg: Warning.\n"
|
||||
"\t Wrong JFIF version '%i.%02i'. File: '%s'.\n"
|
||||
"\t The expected version is '1.01'. The game may not be able to decode this image "
|
||||
"properly.\n",
|
||||
majorVersion, minorVersion, filename.c_str());
|
||||
HANDLE_WARNING_PROCESS(
|
||||
WarningType::InvalidJPEG,
|
||||
StringHelper::Sprintf("wrong JFIF version '%i.%02i'", majorVersion, minorVersion),
|
||||
"The expected version is '1.01'. The game may be unable to decode this image "
|
||||
"correctly.");
|
||||
}
|
||||
if (BitConverter::ToUInt16BE(data, 20) != MARKER_DQT)
|
||||
{
|
||||
// This may happen when creating a custom image with Exif, XMP, thumbnail, progressive, etc.
|
||||
// enabled.
|
||||
fprintf(stderr,
|
||||
"ZBackground::CheckValidJpeg: Warning.\n"
|
||||
"\t There seems to be extra data before the image data in file: '%s'.\n"
|
||||
"\t The game may not be able to decode this image properly.\n",
|
||||
filename.c_str());
|
||||
HANDLE_WARNING_PROCESS(WarningType::InvalidJPEG,
|
||||
"there seems to be extra data before the image data in this file",
|
||||
"The game may not be able to decode this image correctly.");
|
||||
}
|
||||
if (data.size() > GetRawDataSize())
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ZBackground::CheckValidJpeg: Warning.\n"
|
||||
"\t The image is bigger than the screen buffer. File: '%s'.\n"
|
||||
"\t Image size: %zu bytes.\n"
|
||||
"\t Screen buffer size: %zu bytes.\n",
|
||||
filename.c_str(), data.size(), GetRawDataSize());
|
||||
HANDLE_WARNING_PROCESS(
|
||||
WarningType::InvalidJPEG, "the image is bigger than the screen buffer",
|
||||
StringHelper::Sprintf("Image size: %zu bytes\nScreen buffer size: %zu bytes",
|
||||
data.size(), GetRawDataSize()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,6 +133,7 @@ Declaration* ZBackground::DeclareVar(const std::string& prefix,
|
||||
Declaration* decl = parent->AddDeclarationIncludeArray(rawDataIndex, incStr, GetRawDataSize(),
|
||||
GetSourceTypeName(), auxName, 0);
|
||||
decl->arrayItemCntStr = "SCREEN_WIDTH * SCREEN_HEIGHT / 4";
|
||||
decl->forceArrayCnt = true;
|
||||
decl->staticConf = staticConf;
|
||||
return decl;
|
||||
}
|
||||
|
@ -83,11 +83,6 @@ std::string ZBlob::GetBodySourceCode() const
|
||||
return sourceOutput;
|
||||
}
|
||||
|
||||
std::string ZBlob::GetSourceOutputHeader([[maybe_unused]] const std::string& prefix)
|
||||
{
|
||||
return StringHelper::Sprintf("extern u8 %s[];\n", name.c_str());
|
||||
}
|
||||
|
||||
void ZBlob::Save(const fs::path& outFolder)
|
||||
{
|
||||
File::WriteAllBytes((outFolder / (name + ".bin")).string(), blobData);
|
||||
|
@ -16,7 +16,6 @@ public:
|
||||
Declaration* DeclareVar(const std::string& prefix, const std::string& bodyStr) override;
|
||||
std::string GetBodySourceCode() const override;
|
||||
|
||||
std::string GetSourceOutputHeader(const std::string& prefix) override;
|
||||
void Save(const fs::path& outFolder) override;
|
||||
|
||||
bool IsExternalResource() const override;
|
||||
|
@ -88,7 +88,7 @@ void ZCollisionHeader::ParseRawData()
|
||||
|
||||
void ZCollisionHeader::DeclareReferences(const std::string& prefix)
|
||||
{
|
||||
std::string declaration;
|
||||
std::string declaration = "";
|
||||
std::string auxName = name;
|
||||
|
||||
if (name == "")
|
||||
@ -174,7 +174,7 @@ void ZCollisionHeader::DeclareReferences(const std::string& prefix)
|
||||
|
||||
std::string ZCollisionHeader::GetBodySourceCode() const
|
||||
{
|
||||
std::string declaration;
|
||||
std::string declaration = "";
|
||||
|
||||
declaration += "\n";
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "Utils/BitConverter.h"
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "WarningHandler.h"
|
||||
#include "ZResource.h"
|
||||
|
||||
REGISTER_ZFILENODE(Cutscene, ZCutscene);
|
||||
@ -87,7 +88,7 @@ CutsceneCommandSceneTransFX::~CutsceneCommandSceneTransFX()
|
||||
|
||||
std::string ZCutscene::GetBodySourceCode() const
|
||||
{
|
||||
std::string output;
|
||||
std::string output = "";
|
||||
uint32_t curPtr = 0;
|
||||
|
||||
output += StringHelper::Sprintf(" CS_BEGIN_CUTSCENE(%i, %i),\n", commands.size(), endFrame);
|
||||
@ -225,8 +226,9 @@ void ZCutscene::ParseRawData()
|
||||
cmd = new CutsceneCommandEnd(rawData, currentPtr);
|
||||
break;
|
||||
case CutsceneCommands::Error:
|
||||
fprintf(stderr, "Cutscene command error %d %s %d\n", (int32_t)cmdID, __FILE__,
|
||||
__LINE__);
|
||||
HANDLE_WARNING_RESOURCE(WarningType::NotImplemented, parent, this, rawDataIndex,
|
||||
StringHelper::Sprintf("cutscene command error %d", cmdID),
|
||||
"");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -404,7 +406,9 @@ CutsceneCommands ZCutscene::GetCommandFromID(int32_t id)
|
||||
return CutsceneCommands::Unknown;
|
||||
}
|
||||
|
||||
fprintf(stderr, "WARNING: Could not identify cutscene command ID 0x%04X\n", id);
|
||||
HANDLE_WARNING_RESOURCE(
|
||||
WarningType::NotImplemented, parent, this, rawDataIndex,
|
||||
StringHelper::Sprintf("could not identify cutscene command. ID 0x%04X", id), "");
|
||||
|
||||
return CutsceneCommands::Error;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "ZFile.h"
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "ZCutscene.h"
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <cinttypes>
|
||||
#include <cmath>
|
||||
|
||||
#include "Globals.h"
|
||||
@ -11,6 +12,7 @@
|
||||
#include "Utils/File.h"
|
||||
#include "Utils/Path.h"
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "WarningHandler.h"
|
||||
#include "gfxd.h"
|
||||
|
||||
REGISTER_ZFILENODE(DList, ZDisplayList);
|
||||
@ -105,7 +107,7 @@ void ZDisplayList::ParseF3DZEX(F3DZEXOpcode opcode, uint64_t data, int32_t i,
|
||||
switch (opcode)
|
||||
{
|
||||
case F3DZEXOpcode::G_NOOP:
|
||||
sprintf(line, "gsDPNoOpTag(0x%08lX),", data & 0xFFFFFFFF);
|
||||
sprintf(line, "gsDPNoOpTag(0x%08" PRIX64 "),", data & 0xFFFFFFFF);
|
||||
break;
|
||||
case F3DZEXOpcode::G_DL:
|
||||
Opcode_G_DL(data, prefix, line);
|
||||
@ -220,7 +222,7 @@ void ZDisplayList::ParseF3DZEX(F3DZEXOpcode opcode, uint64_t data, int32_t i,
|
||||
break;
|
||||
case F3DZEXOpcode::G_POPMTX:
|
||||
{
|
||||
sprintf(line, "gsSPPopMatrix(%li),", data);
|
||||
sprintf(line, "gsSPPopMatrix(%" PRIi64 "),", data);
|
||||
}
|
||||
break;
|
||||
case F3DZEXOpcode::G_LOADTLUT:
|
||||
@ -297,7 +299,7 @@ void ZDisplayList::ParseF3DEX(F3DEXOpcode opcode, uint64_t data, const std::stri
|
||||
switch (opcode)
|
||||
{
|
||||
case F3DEXOpcode::G_NOOP:
|
||||
sprintf(line, "gsDPNoOpTag(0x%08lX),", data & 0xFFFFFFFF);
|
||||
sprintf(line, "gsDPNoOpTag(0x%08" PRIX64 "),", data & 0xFFFFFFFF);
|
||||
break;
|
||||
case F3DEXOpcode::G_VTX:
|
||||
Opcode_G_VTX(data, line);
|
||||
@ -445,11 +447,12 @@ int32_t ZDisplayList::GetDListLength(const std::vector<uint8_t>& rawData, uint32
|
||||
{
|
||||
if (ptr >= rawDataSize)
|
||||
{
|
||||
throw std::runtime_error(StringHelper::Sprintf(
|
||||
"%s: Fatal error.\n"
|
||||
"\t End of file found when trying to find the end of the "
|
||||
"DisplayList at offset: '0x%X'.\n",
|
||||
"Raw data size: 0x%zX.\n", __PRETTY_FUNCTION__, rawDataIndex, rawDataSize));
|
||||
std::string errorHeader =
|
||||
StringHelper::Sprintf("reached end of file when trying to find the end of the "
|
||||
"DisplayList starting at offset 0x%X",
|
||||
rawDataIndex);
|
||||
std::string errorBody = StringHelper::Sprintf("Raw data size: 0x%zX.", rawDataSize);
|
||||
HANDLE_ERROR_PROCESS(WarningType::Always, errorHeader, errorBody);
|
||||
}
|
||||
|
||||
uint8_t opcode = rawData.at(ptr);
|
||||
@ -686,20 +689,20 @@ void ZDisplayList::Opcode_G_DL(uint64_t data, const std::string& prefix, char* l
|
||||
if (pp != 0)
|
||||
{
|
||||
if (!Globals::Instance->HasSegment(segNum))
|
||||
sprintf(line, "gsSPBranchList(0x%08lX),", data & 0xFFFFFFFF);
|
||||
sprintf(line, "gsSPBranchList(0x%08" PRIX64 "),", data & 0xFFFFFFFF);
|
||||
else if (dListDecl != nullptr)
|
||||
sprintf(line, "gsSPBranchList(%s),", dListDecl->varName.c_str());
|
||||
else
|
||||
sprintf(line, "gsSPBranchList(%sDlist0x%06lX),", prefix.c_str(), GETSEGOFFSET(data));
|
||||
sprintf(line, "gsSPBranchList(%sDlist0x%06" PRIX64 "),", prefix.c_str(), GETSEGOFFSET(data));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Globals::Instance->HasSegment(segNum))
|
||||
sprintf(line, "gsSPDisplayList(0x%08lX),", data & 0xFFFFFFFF);
|
||||
sprintf(line, "gsSPDisplayList(0x%08" PRIX64 "),", data & 0xFFFFFFFF);
|
||||
else if (dListDecl != nullptr)
|
||||
sprintf(line, "gsSPDisplayList(%s),", dListDecl->varName.c_str());
|
||||
else
|
||||
sprintf(line, "gsSPDisplayList(%sDlist0x%06lX),", prefix.c_str(), GETSEGOFFSET(data));
|
||||
sprintf(line, "gsSPDisplayList(%sDlist0x%06" PRIX64 "),", prefix.c_str(), GETSEGOFFSET(data));
|
||||
}
|
||||
|
||||
// if (segNum == 8 || segNum == 9 || segNum == 10 || segNum == 11 || segNum == 12 || segNum ==
|
||||
@ -707,9 +710,9 @@ void ZDisplayList::Opcode_G_DL(uint64_t data, const std::string& prefix, char* l
|
||||
if (!Globals::Instance->HasSegment(segNum))
|
||||
{
|
||||
if (pp != 0)
|
||||
sprintf(line, "gsSPBranchList(0x%08lX),", data & 0xFFFFFFFF);
|
||||
sprintf(line, "gsSPBranchList(0x%08" PRIX64 "),", data & 0xFFFFFFFF);
|
||||
else
|
||||
sprintf(line, "gsSPDisplayList(0x%08lX),", data & 0xFFFFFFFF);
|
||||
sprintf(line, "gsSPDisplayList(0x%08" PRIX64 "),", data & 0xFFFFFFFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -941,7 +944,7 @@ void ZDisplayList::Opcode_G_SETTIMG(uint64_t data, const std::string& prefix, ch
|
||||
sprintf(texStr, "%sTex_%06X", prefix.c_str(), texAddress);
|
||||
else
|
||||
{
|
||||
sprintf(texStr, "0x%08lX", data & 0xFFFFFFFF);
|
||||
sprintf(texStr, "0x%08" PRIX64, data & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
sprintf(line, "gsDPSetTextureImage(%s, %s, %i, %s),", fmtTbl[fmt], sizTbl[siz], www + 1,
|
||||
@ -1522,11 +1525,6 @@ void ZDisplayList::Opcode_G_ENDDL([[maybe_unused]] const std::string& prefix, ch
|
||||
TextureGenCheck();
|
||||
}
|
||||
|
||||
std::string ZDisplayList::GetSourceOutputHeader([[maybe_unused]] const std::string& prefix)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
static int32_t GfxdCallback_FormatSingleEntry()
|
||||
{
|
||||
ZDisplayList* self = static_cast<ZDisplayList*>(gfxd_udata_get());
|
||||
@ -1737,7 +1735,7 @@ static int32_t GfxdCallback_Matrix(uint32_t seg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string ZDisplayList::GetSourceOutputCode(const std::string& prefix)
|
||||
void ZDisplayList::DeclareReferences(const std::string& prefix)
|
||||
{
|
||||
std::string sourceOutput;
|
||||
|
||||
@ -1750,7 +1748,7 @@ std::string ZDisplayList::GetSourceOutputCode(const std::string& prefix)
|
||||
if (vertices.size() > 0)
|
||||
{
|
||||
std::vector<std::pair<uint32_t, std::vector<ZVtx>>> verticesSorted(vertices.begin(),
|
||||
vertices.end());
|
||||
vertices.end());
|
||||
|
||||
for (size_t i = 0; i < verticesSorted.size() - 1; i++)
|
||||
{
|
||||
@ -1775,15 +1773,13 @@ std::string ZDisplayList::GetSourceOutputCode(const std::string& prefix)
|
||||
// Generate Vertex Declarations
|
||||
for (auto& item : vertices)
|
||||
{
|
||||
std::string declaration;
|
||||
std::string declaration = "";
|
||||
|
||||
offset_t curAddr = item.first;
|
||||
auto& firstVtx = item.second.at(0);
|
||||
|
||||
for (auto vtx : item.second)
|
||||
{
|
||||
declaration += StringHelper::Sprintf("\t%s,\n", vtx.GetBodySourceCode().c_str());
|
||||
}
|
||||
|
||||
Declaration* decl = parent->AddDeclarationArray(
|
||||
curAddr, firstVtx.GetDeclarationAlignment(),
|
||||
@ -1800,7 +1796,7 @@ std::string ZDisplayList::GetSourceOutputCode(const std::string& prefix)
|
||||
if (vertices.size() > 0)
|
||||
{
|
||||
std::vector<std::pair<uint32_t, std::vector<ZVtx>>> verticesSorted(vertices.begin(),
|
||||
vertices.end());
|
||||
vertices.end());
|
||||
|
||||
for (size_t i = 0; i < verticesSorted.size() - 1; i++)
|
||||
{
|
||||
@ -1863,11 +1859,6 @@ std::string ZDisplayList::GetSourceOutputCode(const std::string& prefix)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (parent != nullptr)
|
||||
return "";
|
||||
|
||||
return sourceOutput;
|
||||
}
|
||||
|
||||
std::string ZDisplayList::ProcessLegacy(const std::string& prefix)
|
||||
@ -1899,10 +1890,10 @@ std::string ZDisplayList::ProcessLegacy(const std::string& prefix)
|
||||
}
|
||||
|
||||
auto end = std::chrono::steady_clock::now();
|
||||
auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
||||
int64_t diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
||||
|
||||
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG && diff > 5)
|
||||
printf("F3DOP: 0x%02X, TIME: %lims\n", opcode, diff);
|
||||
printf("F3DOP: 0x%02X, TIME: %" PRIi64 "ms\n", opcode, diff);
|
||||
|
||||
sourceOutput += line;
|
||||
|
||||
@ -1983,7 +1974,7 @@ bool ZDisplayList::TextureGenCheck(int32_t texWidth, int32_t texHeight, uint32_t
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to find a non-external file (ie, one we are actually extracting)
|
||||
// Try to find a non-external file (i.e., one we are actually extracting)
|
||||
// which has the same segment number we are looking for.
|
||||
for (auto& otherFile : Globals::Instance->cfg.segmentRefFiles[segmentNumber])
|
||||
{
|
||||
|
@ -363,8 +363,7 @@ public:
|
||||
|
||||
size_t GetRawDataSize() const override;
|
||||
DeclarationAlignment GetDeclarationAlignment() const override;
|
||||
std::string GetSourceOutputHeader(const std::string& prefix) override;
|
||||
std::string GetSourceOutputCode(const std::string& prefix) override;
|
||||
void DeclareReferences(const std::string& prefix) override;
|
||||
std::string ProcessLegacy(const std::string& prefix);
|
||||
std::string ProcessGfxDis(const std::string& prefix);
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "Utils/MemoryStream.h"
|
||||
#include "Utils/Path.h"
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "WarningHandler.h"
|
||||
#include "ZAnimation.h"
|
||||
#include "ZArray.h"
|
||||
#include "ZBackground.h"
|
||||
@ -73,19 +74,13 @@ ZFile::ZFile(ZFileMode nMode, tinyxml2::XMLElement* reader, const fs::path& nBas
|
||||
ZFile::~ZFile()
|
||||
{
|
||||
for (ZResource* res : resources)
|
||||
{
|
||||
delete res;
|
||||
}
|
||||
|
||||
for (auto d : declarations)
|
||||
{
|
||||
delete d.second;
|
||||
}
|
||||
|
||||
for (auto sym : symbolResources)
|
||||
{
|
||||
delete sym.second;
|
||||
}
|
||||
}
|
||||
|
||||
void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
|
||||
@ -114,8 +109,11 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
|
||||
else if (std::string_view(gameStr) == "OOT")
|
||||
Globals::Instance->game = ZGame::OOT_RETAIL;
|
||||
else
|
||||
throw std::runtime_error(
|
||||
StringHelper::Sprintf("Error: Game type %s not supported.", gameStr));
|
||||
{
|
||||
std::string errorHeader =
|
||||
StringHelper::Sprintf("'Game' type '%s' is not supported.", gameStr);
|
||||
HANDLE_ERROR_PROCESS(WarningType::InvalidAttributeValue, errorHeader, "");
|
||||
}
|
||||
}
|
||||
|
||||
if (reader->Attribute("BaseAddress") != nullptr)
|
||||
@ -128,16 +126,22 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
|
||||
rangeEnd = StringHelper::StrToL(reader->Attribute("RangeEnd"), 16);
|
||||
|
||||
if (rangeStart > rangeEnd)
|
||||
throw std::runtime_error("Error: RangeStart must be before than RangeEnd.");
|
||||
HANDLE_ERROR_PROCESS(
|
||||
WarningType::Always,
|
||||
StringHelper::Sprintf("'RangeStart' 0x%06X must be before 'RangeEnd' 0x%06X",
|
||||
rangeStart, rangeEnd),
|
||||
"");
|
||||
|
||||
const char* segmentXml = reader->Attribute("Segment");
|
||||
if (segmentXml != nullptr)
|
||||
{
|
||||
if (!StringHelper::HasOnlyDigits(segmentXml))
|
||||
{
|
||||
throw std::runtime_error(StringHelper::Sprintf(
|
||||
"error: Invalid segment value '%s': must be a decimal between 0 and 15 inclusive",
|
||||
segmentXml));
|
||||
HANDLE_ERROR_PROCESS(WarningType::Always,
|
||||
StringHelper::Sprintf("error: Invalid segment value '%s': must be "
|
||||
"a decimal between 0 and 15 inclusive",
|
||||
segmentXml),
|
||||
"");
|
||||
}
|
||||
|
||||
segment = StringHelper::StrToL(segmentXml, 10);
|
||||
@ -146,16 +150,19 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
|
||||
if (segment == 128)
|
||||
{
|
||||
#ifdef DEPRECATION_ON
|
||||
fprintf(stderr, "warning: segment 128 is deprecated.\n\tRemove "
|
||||
"'Segment=\"128\"' from the xml to use virtual addresses\n");
|
||||
HANDLE_WARNING_PROCESS(
|
||||
WarningType::Always, "warning: segment 128 is deprecated.",
|
||||
"Remove 'Segment=\"128\"' from the xml to use virtual addresses\n");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error(
|
||||
HANDLE_ERROR_PROCESS(
|
||||
WarningType::Always,
|
||||
StringHelper::Sprintf("error: invalid segment value '%s': must be a decimal "
|
||||
"number between 0 and 15 inclusive",
|
||||
segmentXml));
|
||||
segmentXml),
|
||||
"");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -176,18 +183,16 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
|
||||
if (mode == ZFileMode::Extract || mode == ZFileMode::ExternalFile)
|
||||
{
|
||||
if (!File::Exists((basePath / name).string()))
|
||||
throw std::runtime_error(
|
||||
StringHelper::Sprintf("Error! File %s does not exist.", (basePath / name).c_str()));
|
||||
{
|
||||
std::string errorHeader = StringHelper::Sprintf("binary file '%s' does not exist.",
|
||||
(basePath / name).c_str());
|
||||
HANDLE_ERROR_PROCESS(WarningType::Always, errorHeader, "");
|
||||
}
|
||||
|
||||
rawData = File::ReadAllBytes((basePath / name).string());
|
||||
|
||||
/*
|
||||
* TODO: In OoT repo ovl_Boss_Sst has a wrong RangeEnd (0xAD40 instead of 0xAD70),
|
||||
* so uncommenting the following produces wrong behavior.
|
||||
* If somebody fixes that in OoT repo, uncomment this. I'm too tired of fixing XMLs.
|
||||
*/
|
||||
// if (reader->Attribute("RangeEnd") == nullptr)
|
||||
// rangeEnd = rawData.size();
|
||||
if (reader->Attribute("RangeEnd") == nullptr)
|
||||
rangeEnd = rawData.size();
|
||||
}
|
||||
|
||||
std::unordered_set<std::string> nameSet;
|
||||
@ -211,20 +216,17 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
|
||||
|
||||
if (offsetSet.find(offsetXml) != offsetSet.end())
|
||||
{
|
||||
throw std::runtime_error(StringHelper::Sprintf(
|
||||
"ZFile::ParseXML: Error in '%s'.\n\t Repeated 'Offset' attribute: %s \n",
|
||||
name.c_str(), offsetXml));
|
||||
std::string errorHeader =
|
||||
StringHelper::Sprintf("repeated 'Offset' attribute: %s", offsetXml);
|
||||
HANDLE_ERROR_PROCESS(WarningType::InvalidXML, errorHeader, "");
|
||||
}
|
||||
offsetSet.insert(offsetXml);
|
||||
}
|
||||
else if (Globals::Instance->warnNoOffset)
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Warning No offset specified for: %s", nameXml);
|
||||
}
|
||||
else if (Globals::Instance->errorNoOffset)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
StringHelper::Sprintf("Error no offset specified for %s", nameXml));
|
||||
HANDLE_WARNING_RESOURCE(WarningType::MissingOffsets, this, nullptr, rawDataIndex,
|
||||
StringHelper::Sprintf("no offset specified for %s.", nameXml),
|
||||
"");
|
||||
}
|
||||
|
||||
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO)
|
||||
@ -234,9 +236,9 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
|
||||
{
|
||||
if (outNameSet.find(outNameXml) != outNameSet.end())
|
||||
{
|
||||
throw std::runtime_error(StringHelper::Sprintf(
|
||||
"ZFile::ParseXML: Error in '%s'.\n\t Repeated 'OutName' attribute: %s \n",
|
||||
name.c_str(), outNameXml));
|
||||
std::string errorHeader =
|
||||
StringHelper::Sprintf("repeated 'OutName' attribute: %s", outNameXml);
|
||||
HANDLE_ERROR_PROCESS(WarningType::InvalidXML, errorHeader, "");
|
||||
}
|
||||
outNameSet.insert(outNameXml);
|
||||
}
|
||||
@ -244,9 +246,9 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
|
||||
{
|
||||
if (nameSet.find(nameXml) != nameSet.end())
|
||||
{
|
||||
throw std::runtime_error(StringHelper::Sprintf(
|
||||
"ZFile::ParseXML: Error in '%s'.\n\t Repeated 'Name' attribute: %s \n",
|
||||
name.c_str(), nameXml));
|
||||
std::string errorHeader =
|
||||
StringHelper::Sprintf("repeated 'Name' attribute: %s", nameXml);
|
||||
HANDLE_ERROR_PROCESS(WarningType::InvalidXML, errorHeader, "");
|
||||
}
|
||||
nameSet.insert(nameXml);
|
||||
}
|
||||
@ -279,16 +281,14 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
|
||||
}
|
||||
else if (std::string_view(child->Name()) == "File")
|
||||
{
|
||||
throw std::runtime_error(StringHelper::Sprintf(
|
||||
"ZFile::ParseXML: Error in '%s'.\n\t Can't declare a File inside a File.\n",
|
||||
name.c_str()));
|
||||
std::string errorHeader = "Can't declare a <File> inside a <File>";
|
||||
HANDLE_ERROR_PROCESS(WarningType::InvalidXML, errorHeader, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error(
|
||||
StringHelper::Sprintf("ZFile::ParseXML: Error in '%s'.\n\t Unknown element found "
|
||||
"inside a File element: '%s'.\n",
|
||||
name.c_str(), nodeName.c_str()));
|
||||
std::string errorHeader = StringHelper::Sprintf(
|
||||
"Unknown element found inside a <File> element: %s", nodeName.c_str());
|
||||
HANDLE_ERROR_PROCESS(WarningType::InvalidXML, errorHeader, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -307,7 +307,7 @@ void ZFile::BuildSourceFile()
|
||||
return;
|
||||
|
||||
if (!Directory::Exists(outputPath))
|
||||
Directory::CreateDirectory(outputPath);
|
||||
Directory::CreateDirectory(outputPath.string());
|
||||
|
||||
GenerateSourceFiles();
|
||||
}
|
||||
@ -317,6 +317,11 @@ std::string ZFile::GetName() const
|
||||
return name;
|
||||
}
|
||||
|
||||
std::string ZFile::GetOutName() const
|
||||
{
|
||||
return outName.string();
|
||||
}
|
||||
|
||||
ZFileMode ZFile::GetMode() const
|
||||
{
|
||||
return mode;
|
||||
@ -338,10 +343,10 @@ void ZFile::ExtractResources()
|
||||
return;
|
||||
|
||||
if (!Directory::Exists(outputPath))
|
||||
Directory::CreateDirectory(outputPath);
|
||||
Directory::CreateDirectory(outputPath.string());
|
||||
|
||||
if (!Directory::Exists(GetSourceOutputFolderPath()))
|
||||
Directory::CreateDirectory(GetSourceOutputFolderPath());
|
||||
Directory::CreateDirectory(GetSourceOutputFolderPath().string());
|
||||
|
||||
for (size_t i = 0; i < resources.size(); i++)
|
||||
resources[i]->ParseRawDataLate();
|
||||
@ -351,8 +356,8 @@ void ZFile::ExtractResources()
|
||||
if (Globals::Instance->genSourceFile)
|
||||
GenerateSourceFiles();
|
||||
|
||||
MemoryStream* memStream = new MemoryStream();
|
||||
BinaryWriter writer = BinaryWriter(memStream);
|
||||
auto memStreamFile = std::shared_ptr<MemoryStream>(new MemoryStream());
|
||||
BinaryWriter writerFile = BinaryWriter(memStreamFile);
|
||||
|
||||
ExporterSet* exporterSet = Globals::Instance->GetExporterSet();
|
||||
|
||||
@ -361,6 +366,9 @@ void ZFile::ExtractResources()
|
||||
|
||||
for (ZResource* res : resources)
|
||||
{
|
||||
auto memStreamRes = std::shared_ptr<MemoryStream>(new MemoryStream());
|
||||
BinaryWriter writerRes = BinaryWriter(memStreamRes);
|
||||
|
||||
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO)
|
||||
printf("Saving resource %s\n", res->GetName().c_str());
|
||||
|
||||
@ -369,18 +377,24 @@ void ZFile::ExtractResources()
|
||||
// Check if we have an exporter "registered" for this resource type
|
||||
ZResourceExporter* exporter = Globals::Instance->GetExporter(res->GetResourceType());
|
||||
if (exporter != nullptr)
|
||||
exporter->Save(res, Globals::Instance->outputPath.string(), &writer);
|
||||
{
|
||||
//exporter->Save(res, Globals::Instance->outputPath.string(), &writerFile);
|
||||
exporter->Save(res, Globals::Instance->outputPath.string(), &writerRes);
|
||||
}
|
||||
|
||||
if (exporterSet != nullptr && exporterSet->resSaveFunc != nullptr)
|
||||
exporterSet->resSaveFunc(res, writerRes);
|
||||
}
|
||||
|
||||
if (memStream->GetLength() > 0)
|
||||
if (memStreamFile->GetLength() > 0)
|
||||
{
|
||||
File::WriteAllBytes(StringHelper::Sprintf("%s%s.bin",
|
||||
Globals::Instance->outputPath.string().c_str(),
|
||||
GetName().c_str()),
|
||||
memStream->ToVector());
|
||||
memStreamFile->ToVector());
|
||||
}
|
||||
|
||||
writer.Close();
|
||||
writerFile.Close();
|
||||
|
||||
if (exporterSet != nullptr && exporterSet->endFileFunc != nullptr)
|
||||
exporterSet->endFileFunc(this);
|
||||
@ -1070,8 +1084,6 @@ std::string ZFile::ProcessDeclarations()
|
||||
}
|
||||
}
|
||||
|
||||
output += "\n";
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@ -1234,11 +1246,12 @@ bool ZFile::HandleUnaccountedAddress(uint32_t currentAddress, uint32_t lastAddr,
|
||||
{
|
||||
Declaration* currentDecl = declarations.at(currentAddress);
|
||||
|
||||
fprintf(stderr,
|
||||
"WARNING: Intersection detected from 0x%06X:0x%06X (%s), conflicts with "
|
||||
"0x%06X (%s)\n",
|
||||
lastAddr, lastAddr + lastSize, lastDecl->varName.c_str(), currentAddress,
|
||||
currentDecl->varName.c_str());
|
||||
std::string intersectionInfo = StringHelper::Sprintf(
|
||||
"Resource from 0x%06X:0x%06X (%s) conflicts with 0x%06X (%s).", lastAddr,
|
||||
lastAddr + lastSize, lastDecl->varName.c_str(), currentAddress,
|
||||
currentDecl->varName.c_str());
|
||||
HANDLE_WARNING_RESOURCE(WarningType::Intersection, this, nullptr, currentAddress,
|
||||
"intersection detected", intersectionInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1309,25 +1322,17 @@ bool ZFile::HandleUnaccountedAddress(uint32_t currentAddress, uint32_t lastAddr,
|
||||
diff, src);
|
||||
decl->isUnaccounted = true;
|
||||
|
||||
if (Globals::Instance->warnUnaccounted)
|
||||
if (nonZeroUnaccounted)
|
||||
{
|
||||
if (nonZeroUnaccounted)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Warning in file: %s (%s)\n"
|
||||
"\t A non-zero unaccounted block was found at offset '0x%06X'.\n"
|
||||
"\t Block size: '0x%X'.\n",
|
||||
xmlFilePath.c_str(), name.c_str(), unaccountedAddress, diff);
|
||||
}
|
||||
else if (diff >= 16)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Warning in file: %s (%s)\n"
|
||||
"\t A big (size>=0x10) zero-only unaccounted block was found "
|
||||
"at offset '0x%06X'.\n"
|
||||
"\t Block size: '0x%X'.\n",
|
||||
xmlFilePath.c_str(), name.c_str(), unaccountedAddress, diff);
|
||||
}
|
||||
HANDLE_WARNING_RESOURCE(WarningType::Unaccounted, this, nullptr, unaccountedAddress,
|
||||
"a non-zero unaccounted block was found",
|
||||
StringHelper::Sprintf("Block size: '0x%X'", diff));
|
||||
}
|
||||
else if (diff >= 16)
|
||||
{
|
||||
HANDLE_WARNING_RESOURCE(WarningType::Unaccounted, this, nullptr, unaccountedAddress,
|
||||
"a big (size>=0x10) zero-only unaccounted block was found",
|
||||
StringHelper::Sprintf("Block size: '0x%X'", diff));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <Utils/Directory.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -46,6 +45,7 @@ public:
|
||||
~ZFile();
|
||||
|
||||
std::string GetName() const;
|
||||
std::string GetOutName() const;
|
||||
ZFileMode GetMode() const;
|
||||
const fs::path& GetXmlFilePath() const;
|
||||
const std::vector<uint8_t>& GetRawData() const;
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include "Globals.h"
|
||||
#include "Utils/BitConverter.h"
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "WarningHandler.h"
|
||||
|
||||
REGISTER_ZFILENODE(Limb, ZLimb);
|
||||
|
||||
@ -37,17 +37,15 @@ void ZLimb::ParseXML(tinyxml2::XMLElement* reader)
|
||||
|
||||
if (limbType == "")
|
||||
{
|
||||
throw std::runtime_error(StringHelper::Sprintf("ZLimb::ParseXML: Error in '%s'.\n"
|
||||
"\t Missing 'LimbType' attribute in xml.\n",
|
||||
name.c_str()));
|
||||
HANDLE_ERROR_RESOURCE(WarningType::MissingAttribute, parent, this, rawDataIndex,
|
||||
"missing 'LimbType' attribute in <Limb>", "");
|
||||
}
|
||||
|
||||
type = GetTypeByAttributeName(limbType);
|
||||
if (type == ZLimbType::Invalid)
|
||||
{
|
||||
throw std::runtime_error(StringHelper::Sprintf("ZLimb::ParseXML: Error in '%s'.\n"
|
||||
"\t Invalid 'LimbType' found: '%s'.\n",
|
||||
name.c_str(), limbType.c_str()));
|
||||
HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
|
||||
"invalid value found for 'LimbType' attribute", "");
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,8 +107,12 @@ void ZLimb::ParseRawData()
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::runtime_error("Invalid ZLimb type");
|
||||
case ZLimbType::Curve:
|
||||
case ZLimbType::Legacy:
|
||||
break;
|
||||
|
||||
case ZLimbType::Invalid:
|
||||
assert(!"whoops");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "Globals.h"
|
||||
#include "Utils/BitConverter.h"
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "WarningHandler.h"
|
||||
#include "ZFile.h"
|
||||
|
||||
REGISTER_ZFILENODE(Path, ZPath);
|
||||
@ -20,10 +21,12 @@ void ZPath::ParseXML(tinyxml2::XMLElement* reader)
|
||||
numPaths = StringHelper::StrToL(registeredAttributes.at("NumPaths").value);
|
||||
|
||||
if (numPaths < 1)
|
||||
throw std::runtime_error(
|
||||
StringHelper::Sprintf("ZPath::ParseXML: Fatal error in '%s'.\n"
|
||||
"\t Invalid value for attribute 'NumPaths': '%i'\n",
|
||||
name.c_str(), numPaths));
|
||||
{
|
||||
HANDLE_ERROR_RESOURCE(
|
||||
WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
|
||||
StringHelper::Sprintf("invalid value '%d' found for 'NumPaths' attribute", numPaths),
|
||||
"Should be at least '1'");
|
||||
}
|
||||
}
|
||||
|
||||
void ZPath::ParseRawData()
|
||||
@ -144,7 +147,7 @@ void PathwayEntry::DeclareReferences(const std::string& prefix)
|
||||
if (addressFound)
|
||||
return;
|
||||
|
||||
std::string declaration;
|
||||
std::string declaration = "";
|
||||
|
||||
size_t index = 0;
|
||||
for (const auto& point : points)
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <regex>
|
||||
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "WarningHandler.h"
|
||||
#include "ZFile.h"
|
||||
|
||||
ZResource::ZResource(ZFile* nParent)
|
||||
@ -85,29 +86,33 @@ void ZResource::ParseXML(tinyxml2::XMLElement* reader)
|
||||
}
|
||||
|
||||
if (!attrDeclared)
|
||||
fprintf(stderr,
|
||||
"ZResource::ParseXML: Warning while parsing '%s'.\n"
|
||||
"\t Unexpected '%s' attribute in resource '%s'.\n",
|
||||
parent->GetName().c_str(), attrName.c_str(), reader->Name());
|
||||
{
|
||||
HANDLE_WARNING_RESOURCE(
|
||||
WarningType::UnknownAttribute, parent, this, rawDataIndex,
|
||||
StringHelper::Sprintf("unexpected '%s' attribute in resource <%s>",
|
||||
attrName.c_str(), reader->Name()),
|
||||
"");
|
||||
}
|
||||
attrs = attrs->Next();
|
||||
}
|
||||
|
||||
if (!canHaveInner && !reader->NoChildren())
|
||||
{
|
||||
throw std::runtime_error(
|
||||
StringHelper::Sprintf("ZResource::ParseXML: Fatal error in '%s'.\n"
|
||||
"\t Resource '%s' with inner element/child detected.\n",
|
||||
name.c_str(), reader->Name()));
|
||||
std::string errorHeader = StringHelper::Sprintf(
|
||||
"resource '%s' with inner element/child detected", reader->Name());
|
||||
HANDLE_ERROR_PROCESS(WarningType::InvalidXML, errorHeader, "");
|
||||
}
|
||||
|
||||
for (const auto& attr : registeredAttributes)
|
||||
{
|
||||
if (attr.second.isRequired && attr.second.value == "")
|
||||
throw std::runtime_error(StringHelper::Sprintf(
|
||||
"ZResource::ParseXML: Fatal error while parsing '%s'.\n"
|
||||
"\t Missing required attribute '%s' in resource '%s'.\n"
|
||||
"\t Aborting...",
|
||||
parent->GetName().c_str(), attr.first.c_str(), reader->Name()));
|
||||
{
|
||||
std::string headerMsg =
|
||||
StringHelper::Sprintf("missing required attribute '%s' in resource <%s>",
|
||||
attr.first.c_str(), reader->Name());
|
||||
HANDLE_ERROR_RESOURCE(WarningType::MissingAttribute, parent, this, rawDataIndex,
|
||||
headerMsg, "");
|
||||
}
|
||||
}
|
||||
|
||||
name = registeredAttributes.at("Name").value;
|
||||
@ -118,10 +123,8 @@ void ZResource::ParseXML(tinyxml2::XMLElement* reader)
|
||||
{
|
||||
if (!std::regex_match(name, r))
|
||||
{
|
||||
throw std::domain_error(
|
||||
StringHelper::Sprintf("ZResource::ParseXML: Fatal error in '%s'.\n"
|
||||
"\t Resource with invalid 'Name' attribute.\n",
|
||||
name.c_str()));
|
||||
HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this,
|
||||
rawDataIndex, "invalid value found for 'Name' attribute", "");
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,7 +149,9 @@ void ZResource::ParseXML(tinyxml2::XMLElement* reader)
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("Invalid value for 'Static' attribute.");
|
||||
HANDLE_ERROR_RESOURCE(
|
||||
WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
|
||||
StringHelper::Sprintf("invalid value '%s' for 'Static' attribute", staticConf), "");
|
||||
}
|
||||
|
||||
declaredInXml = true;
|
||||
@ -253,18 +258,21 @@ std::string ZResource::GetDefaultName(const std::string& prefix) const
|
||||
rawDataIndex);
|
||||
}
|
||||
|
||||
std::string ZResource::GetSourceOutputCode([[maybe_unused]] const std::string& prefix)
|
||||
void ZResource::GetSourceOutputCode([[maybe_unused]] const std::string& prefix)
|
||||
{
|
||||
std::string bodyStr = GetBodySourceCode();
|
||||
|
||||
Declaration* decl = parent->GetDeclaration(rawDataIndex);
|
||||
if (decl == nullptr || decl->isPlaceholder)
|
||||
decl = DeclareVar(prefix, bodyStr);
|
||||
else
|
||||
decl->text = bodyStr;
|
||||
decl->staticConf = staticConf;
|
||||
if (bodyStr != "ERROR")
|
||||
{
|
||||
Declaration* decl = parent->GetDeclaration(rawDataIndex);
|
||||
|
||||
return "";
|
||||
if (decl == nullptr || decl->isPlaceholder)
|
||||
decl = DeclareVar(prefix, bodyStr);
|
||||
else
|
||||
decl->text = bodyStr;
|
||||
|
||||
decl->staticConf = staticConf;
|
||||
}
|
||||
}
|
||||
|
||||
std::string ZResource::GetSourceOutputHeader([[maybe_unused]] const std::string& prefix)
|
||||
@ -312,13 +320,13 @@ offset_t Seg2Filespace(segptr_t segmentedAddress, uint32_t parentBaseAddress)
|
||||
uint32_t parentBaseOffset = GETSEGOFFSET(parentBaseAddress);
|
||||
if (parentBaseOffset > currentPtr)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
StringHelper::Sprintf("\nSeg2Filespace: Segmented address is smaller than "
|
||||
"'BaseAddress'. Maybe your 'BaseAddress' is wrong?\n"
|
||||
"\t SegmentedAddress: 0x%08X\n"
|
||||
"\t BaseAddress: 0x%08X\n",
|
||||
segmentedAddress, parentBaseAddress));
|
||||
HANDLE_ERROR(WarningType::Always,
|
||||
StringHelper::Sprintf(
|
||||
"resource address 0x%08X is smaller than 'BaseAddress' 0x%08X",
|
||||
segmentedAddress, parentBaseAddress),
|
||||
"Maybe your 'BaseAddress' is wrong?");
|
||||
}
|
||||
|
||||
currentPtr -= parentBaseOffset;
|
||||
}
|
||||
|
||||
|
@ -1,16 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <Utils/BinaryWriter.h>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "Declaration.h"
|
||||
#include "Utils/BinaryWriter.h"
|
||||
#include "Utils/Directory.h"
|
||||
#include "tinyxml2.h"
|
||||
|
||||
#include <Utils/Directory.h>
|
||||
|
||||
#define SEGMENT_SCENE 2
|
||||
#define SEGMENT_ROOM 3
|
||||
#define SEGMENT_KEEP 4
|
||||
@ -113,7 +112,7 @@ public:
|
||||
*/
|
||||
[[nodiscard]] virtual std::string GetDefaultName(const std::string& prefix) const;
|
||||
|
||||
virtual std::string GetSourceOutputCode(const std::string& prefix);
|
||||
virtual void GetSourceOutputCode(const std::string& prefix);
|
||||
virtual std::string GetSourceOutputHeader(const std::string& prefix);
|
||||
virtual void CalcHash();
|
||||
/**
|
||||
|
@ -1,8 +1,10 @@
|
||||
#include "SetMesh.h"
|
||||
#include <Globals.h>
|
||||
#include <Utils/Path.h>
|
||||
|
||||
#include "Globals.h"
|
||||
#include "Utils/BitConverter.h"
|
||||
#include "Utils/Path.h"
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "WarningHandler.h"
|
||||
#include "ZBackground.h"
|
||||
#include "ZFile.h"
|
||||
#include "ZRoom/ZRoom.h"
|
||||
@ -34,9 +36,8 @@ void SetMesh::ParseRawData()
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::runtime_error(StringHelper::Sprintf("Error in SetMesh::ParseRawData\n"
|
||||
"\t Unknown meshHeaderType: %i\n",
|
||||
meshHeaderType));
|
||||
HANDLE_ERROR(WarningType::InvalidExtractedData,
|
||||
StringHelper::Sprintf("unknown meshHeaderType: %i", meshHeaderType), "");
|
||||
}
|
||||
|
||||
polyType->ParseRawData();
|
||||
@ -53,11 +54,9 @@ void SetMesh::DeclareReferences(const std::string& prefix)
|
||||
void GenDListDeclarations(ZRoom* zRoom, ZFile* parent, ZDisplayList* dList)
|
||||
{
|
||||
if (dList == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::string sourceOutput = dList->GetSourceOutputCode(zRoom->GetName());
|
||||
dList->DeclareReferences(zRoom->GetName());
|
||||
|
||||
for (ZDisplayList* otherDList : dList->otherDLists)
|
||||
GenDListDeclarations(zRoom, parent, otherDList);
|
||||
@ -143,21 +142,17 @@ std::string PolygonDlist::GetBodySourceCode() const
|
||||
return bodyStr;
|
||||
}
|
||||
|
||||
std::string PolygonDlist::GetSourceOutputCode(const std::string& prefix)
|
||||
void PolygonDlist::GetSourceOutputCode(const std::string& prefix)
|
||||
{
|
||||
std::string bodyStr = StringHelper::Sprintf("\n\t%s\n", GetBodySourceCode().c_str());
|
||||
|
||||
Declaration* decl = parent->GetDeclaration(rawDataIndex);
|
||||
if (decl == nullptr)
|
||||
{
|
||||
DeclareVar(prefix, bodyStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
decl->text = bodyStr;
|
||||
}
|
||||
|
||||
return "";
|
||||
if (decl == nullptr)
|
||||
DeclareVar(prefix, bodyStr);
|
||||
else
|
||||
decl->text = bodyStr;
|
||||
|
||||
}
|
||||
|
||||
std::string PolygonDlist::GetSourceTypeName() const
|
||||
@ -472,8 +467,8 @@ void PolygonType1::DeclareReferences(const std::string& prefix)
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::runtime_error(StringHelper::Sprintf(
|
||||
"Error in PolygonType1::PolygonType1\n\t Unknown format: %i\n", format));
|
||||
HANDLE_ERROR(WarningType::InvalidExtractedData,
|
||||
StringHelper::Sprintf("unknown format: %i", format), "");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -582,9 +577,11 @@ void PolygonType2::DeclareReferences(const std::string& prefix)
|
||||
polyDListName = StringHelper::Sprintf("%s%s_%06X", prefix.c_str(), polyDlistType.c_str(),
|
||||
GETSEGOFFSET(start));
|
||||
|
||||
parent->AddDeclarationArray(GETSEGOFFSET(start), DeclarationAlignment::Align4,
|
||||
polyDLists.size() * polyDLists.at(0).GetRawDataSize(),
|
||||
polyDlistType, polyDListName, polyDLists.size(), declaration);
|
||||
Declaration* decl = parent->AddDeclarationArray(
|
||||
GETSEGOFFSET(start), DeclarationAlignment::Align4,
|
||||
polyDLists.size() * polyDLists.at(0).GetRawDataSize(), polyDlistType, polyDListName,
|
||||
polyDLists.size(), declaration);
|
||||
decl->forceArrayCnt = true;
|
||||
}
|
||||
|
||||
parent->AddDeclaration(GETSEGOFFSET(end), DeclarationAlignment::Align4, 4, "s32",
|
||||
|
@ -28,7 +28,7 @@ public:
|
||||
|
||||
std::string GetBodySourceCode() const override;
|
||||
|
||||
std::string GetSourceOutputCode(const std::string& prefix) override;
|
||||
void GetSourceOutputCode(const std::string& prefix) override;
|
||||
|
||||
std::string GetSourceTypeName() const override;
|
||||
ZResourceType GetResourceType() const override;
|
||||
|
@ -115,11 +115,9 @@ std::string RomFile::GetBodySourceCode() const
|
||||
return declaration;
|
||||
}
|
||||
|
||||
std::string RomFile::GetSourceOutputCode(const std::string& prefix)
|
||||
void RomFile::GetSourceOutputCode(const std::string& prefix)
|
||||
{
|
||||
DeclareVar(prefix, GetBodySourceCode());
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string RomFile::GetSourceTypeName() const
|
||||
|
@ -24,7 +24,7 @@ public:
|
||||
|
||||
Declaration* DeclareVar(const std::string& prefix, const std::string& body) override;
|
||||
std::string GetBodySourceCode() const override;
|
||||
std::string GetSourceOutputCode(const std::string& prefix) override;
|
||||
void GetSourceOutputCode(const std::string& prefix) override;
|
||||
|
||||
std::string GetSourceTypeName() const override;
|
||||
virtual ZResourceType GetResourceType() const override;
|
||||
|
@ -2,7 +2,9 @@
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <cinttypes>
|
||||
#include <string_view>
|
||||
|
||||
#include "Commands/EndMarker.h"
|
||||
#include "Commands/SetActorCutsceneList.h"
|
||||
#include "Commands/SetActorList.h"
|
||||
@ -40,6 +42,7 @@
|
||||
#include "Utils/File.h"
|
||||
#include "Utils/Path.h"
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "WarningHandler.h"
|
||||
#include "ZBlob.h"
|
||||
#include "ZCutscene.h"
|
||||
#include "ZFile.h"
|
||||
@ -123,10 +126,12 @@ void ZRoom::ParseXML(tinyxml2::XMLElement* reader)
|
||||
{
|
||||
hackMode = std::string(reader->Attribute("HackMode"));
|
||||
if (hackMode != "syotes_room")
|
||||
throw std::runtime_error(
|
||||
StringHelper::Sprintf("ZRoom::ParseXML: Fatal error in '%s'.\n"
|
||||
"\t Invalid value for attribute 'HackMode': '%s'\n",
|
||||
name.c_str(), hackMode.c_str()));
|
||||
{
|
||||
std::string headerError = StringHelper::Sprintf(
|
||||
"invalid value found for 'HackMode' attribute: '%s'", hackMode.c_str());
|
||||
HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
|
||||
headerError, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -256,9 +261,9 @@ void ZRoom::ParseRawData()
|
||||
if (Globals::Instance->profile)
|
||||
{
|
||||
auto end = std::chrono::steady_clock::now();
|
||||
auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
||||
int64_t diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
||||
if (diff > 50)
|
||||
printf("OP: %s, TIME: %lims\n", cmd->GetCommandCName().c_str(), diff);
|
||||
printf("OP: %s, TIME: %" PRIi64 "ms\n", cmd->GetCommandCName().c_str(), diff);
|
||||
}
|
||||
|
||||
cmd->cmdIndex = currentIndex;
|
||||
@ -392,14 +397,10 @@ size_t ZRoom::GetCommandSizeFromNeighbor(ZRoomCommand* cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string ZRoom::GetSourceOutputCode([[maybe_unused]] const std::string& prefix)
|
||||
void ZRoom::GetSourceOutputCode([[maybe_unused]] const std::string& prefix)
|
||||
{
|
||||
if (hackMode == "syotes_room")
|
||||
return "";
|
||||
|
||||
DeclareVar(prefix, GetBodySourceCode());
|
||||
|
||||
return "";
|
||||
if (hackMode != "syotes_room")
|
||||
DeclareVar(prefix, GetBodySourceCode());
|
||||
}
|
||||
|
||||
size_t ZRoom::GetRawDataSize() const
|
||||
|
@ -34,7 +34,7 @@ public:
|
||||
Declaration* DeclareVar(const std::string& prefix, const std::string& body) override;
|
||||
std::string GetBodySourceCode() const override;
|
||||
|
||||
std::string GetSourceOutputCode(const std::string& prefix) override;
|
||||
void GetSourceOutputCode(const std::string& prefix) override;
|
||||
|
||||
std::string GetDefaultName(const std::string& prefix) const override;
|
||||
size_t GetDeclarationSizeFromNeighbor(uint32_t declarationAddress);
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "Utils/BitConverter.h"
|
||||
#include "Utils/File.h"
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "WarningHandler.h"
|
||||
#include "ZFile.h"
|
||||
|
||||
REGISTER_ZFILENODE(Scalar, ZScalar);
|
||||
@ -207,8 +208,8 @@ void ZScalar::ParseRawData()
|
||||
scalarData.f64 = BitConverter::ToDoubleBE(rawData, rawDataIndex);
|
||||
break;
|
||||
case ZScalarType::ZSCALAR_NONE:
|
||||
fprintf(stderr, "Warning in ZScalar: Invalid type. %d %s %d\n", (int32_t)scalarType,
|
||||
__FILE__, __LINE__);
|
||||
HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
|
||||
"invalid value found for 'Type' attribute", "Defaulting to ''");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "ZResource.h"
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "Globals.h"
|
||||
#include "Utils/BitConverter.h"
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "WarningHandler.h"
|
||||
|
||||
REGISTER_ZFILENODE(Skeleton, ZSkeleton);
|
||||
REGISTER_ZFILENODE(LimbTable, ZLimbTable);
|
||||
@ -27,18 +28,19 @@ void ZSkeleton::ParseXML(tinyxml2::XMLElement* reader)
|
||||
type = ZSkeletonType::Curve;
|
||||
else if (skelTypeXml != "Normal")
|
||||
{
|
||||
throw std::runtime_error(StringHelper::Sprintf("ZSkeleton::ParseXML: Error in '%s'.\n"
|
||||
"\t Invalid Type found: '%s'.\n",
|
||||
name.c_str(), skelTypeXml.c_str()));
|
||||
HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
|
||||
"invalid value found for 'Type' attribute", "");
|
||||
}
|
||||
|
||||
std::string limbTypeXml = registeredAttributes.at("LimbType").value;
|
||||
limbType = ZLimb::GetTypeByAttributeName(limbTypeXml);
|
||||
if (limbType == ZLimbType::Invalid)
|
||||
{
|
||||
throw std::runtime_error(StringHelper::Sprintf("ZSkeleton::ParseXML: Error in '%s'.\n"
|
||||
"\t Invalid LimbType found: '%s'.\n",
|
||||
name.c_str(), limbTypeXml.c_str()));
|
||||
HANDLE_ERROR_RESOURCE(
|
||||
WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
|
||||
StringHelper::Sprintf("invalid value '%s' found for 'LimbType' attribute",
|
||||
limbTypeXml.c_str()),
|
||||
"Defaulting to 'Standard'.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,11 +172,9 @@ void ZLimbTable::ParseXML(tinyxml2::XMLElement* reader)
|
||||
limbType = ZLimb::GetTypeByAttributeName(limbTypeXml);
|
||||
if (limbType == ZLimbType::Invalid)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ZLimbTable::ParseXML: Warning in '%s'.\n"
|
||||
"\t Invalid LimbType found: '%s'.\n"
|
||||
"\t Defaulting to 'Standard'.\n",
|
||||
name.c_str(), limbTypeXml.c_str());
|
||||
HANDLE_WARNING_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
|
||||
"invalid value found for 'LimbType' attribute.",
|
||||
"Defaulting to 'Standard'.");
|
||||
limbType = ZLimbType::Standard;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "ZSymbol.h"
|
||||
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "WarningHandler.h"
|
||||
#include "ZFile.h"
|
||||
|
||||
REGISTER_ZFILENODE(Symbol, ZSymbol);
|
||||
@ -20,11 +21,8 @@ void ZSymbol::ParseXML(tinyxml2::XMLElement* reader)
|
||||
|
||||
if (typeXml == "")
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ZSymbol::ParseXML: Warning in '%s'.\n"
|
||||
"\t Missing 'Type' attribute in xml.\n"
|
||||
"\t Defaulting to 'void*'.\n",
|
||||
name.c_str());
|
||||
HANDLE_WARNING_RESOURCE(WarningType::MissingAttribute, parent, this, rawDataIndex,
|
||||
"missing 'Type' attribute in <Symbol>", "Defaulting to 'void*'.");
|
||||
type = "void*";
|
||||
}
|
||||
else
|
||||
@ -35,11 +33,8 @@ void ZSymbol::ParseXML(tinyxml2::XMLElement* reader)
|
||||
std::string typeSizeXml = registeredAttributes.at("TypeSize").value;
|
||||
if (typeSizeXml == "")
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ZSymbol::ParseXML: Warning in '%s'.\n"
|
||||
"\t Missing 'TypeSize' attribute in xml.\n"
|
||||
"\t Defaulting to '4'.\n",
|
||||
name.c_str());
|
||||
HANDLE_WARNING_RESOURCE(WarningType::MissingAttribute, parent, this, rawDataIndex,
|
||||
"missing 'TypeSize' attribute in <Symbol>", "Defaulting to '4'.");
|
||||
typeSize = 4; // Size of a word.
|
||||
}
|
||||
else
|
||||
@ -58,7 +53,9 @@ void ZSymbol::ParseXML(tinyxml2::XMLElement* reader)
|
||||
|
||||
if (registeredAttributes.at("Static").value == "On")
|
||||
{
|
||||
fprintf(stderr, "A <Symbol> can't be marked as static.\n\t Disabling static\n");
|
||||
HANDLE_WARNING_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
|
||||
"a <Symbol> cannot be marked as static",
|
||||
"Disabling static for this resource.");
|
||||
}
|
||||
staticConf = StaticConfig::Off;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "Utils/Directory.h"
|
||||
#include "Utils/File.h"
|
||||
#include "Utils/Path.h"
|
||||
#include "WarningHandler.h"
|
||||
|
||||
REGISTER_ZFILENODE(Texture, ZTexture);
|
||||
|
||||
@ -57,17 +58,17 @@ void ZTexture::ParseXML(tinyxml2::XMLElement* reader)
|
||||
|
||||
if (!StringHelper::HasOnlyDigits(widthXml))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
StringHelper::Sprintf("ZTexture::ParseXML: Error in %s\n"
|
||||
"\t Value of 'Width' attribute has non-decimal digits: '%s'.\n",
|
||||
name.c_str(), widthXml.c_str()));
|
||||
std::string errorHeader = StringHelper::Sprintf(
|
||||
"value of 'Width' attribute has non-decimal digits: '%s'", widthXml.c_str());
|
||||
HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
|
||||
errorHeader, "");
|
||||
}
|
||||
if (!StringHelper::HasOnlyDigits(heightXml))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
StringHelper::Sprintf("ZTexture::ParseXML: Error in %s\n"
|
||||
"\t Value of 'Height' attribute has non-decimal digits: '%s'.\n",
|
||||
name.c_str(), heightXml.c_str()));
|
||||
std::string errorHeader = StringHelper::Sprintf(
|
||||
"value of 'Height' attribute has non-decimal digits: '%s'", heightXml.c_str());
|
||||
HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
|
||||
errorHeader, "");
|
||||
}
|
||||
|
||||
width = StringHelper::StrToL(widthXml);
|
||||
@ -77,7 +78,10 @@ void ZTexture::ParseXML(tinyxml2::XMLElement* reader)
|
||||
format = GetTextureTypeFromString(formatStr);
|
||||
|
||||
if (format == TextureType::Error)
|
||||
throw std::runtime_error("Format " + formatStr + " is not supported!");
|
||||
{
|
||||
HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
|
||||
"invalid value found for 'Format' attribute", "");
|
||||
}
|
||||
|
||||
const auto& tlutOffsetAttr = registeredAttributes.at("TlutOffset");
|
||||
if (tlutOffsetAttr.wasSet)
|
||||
@ -90,10 +94,9 @@ void ZTexture::ParseXML(tinyxml2::XMLElement* reader)
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::runtime_error(StringHelper::Sprintf(
|
||||
"ZTexture::ParseXML: Error in %s\n"
|
||||
"\t 'TlutOffset' declared in non color-indexed (ci4 or ci8) texture.\n",
|
||||
name.c_str()));
|
||||
HANDLE_ERROR_RESOURCE(WarningType::InvalidXML, parent, this, rawDataIndex,
|
||||
"'TlutOffset' declared in non color-indexed (ci4 or ci8) texture",
|
||||
"");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -102,10 +105,10 @@ void ZTexture::ParseXML(tinyxml2::XMLElement* reader)
|
||||
void ZTexture::ParseRawData()
|
||||
{
|
||||
if (rawDataIndex % 8 != 0)
|
||||
fprintf(stderr,
|
||||
"ZTexture::ParseXML: Warning in '%s'.\n"
|
||||
"\t This texture is not 64-bit aligned.\n",
|
||||
name.c_str());
|
||||
{
|
||||
HANDLE_WARNING_RESOURCE(WarningType::NotImplemented, parent, this, rawDataIndex,
|
||||
"this texture is not 64-bit aligned", "");
|
||||
}
|
||||
|
||||
switch (format)
|
||||
{
|
||||
@ -136,8 +139,11 @@ void ZTexture::ParseRawData()
|
||||
case TextureType::Palette8bpp:
|
||||
PrepareBitmapPalette8();
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Format is not supported!");
|
||||
case TextureType::Error:
|
||||
HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
|
||||
StringHelper::Sprintf("Invalid texture format", format), "");
|
||||
assert(!"TODO");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -375,8 +381,9 @@ void ZTexture::PrepareRawDataFromFile(const fs::path& pngFilePath)
|
||||
case TextureType::Palette8bpp:
|
||||
PrepareRawDataPalette8(pngFilePath);
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Format is not supported!");
|
||||
case TextureType::Error:
|
||||
HANDLE_ERROR_PROCESS(WarningType::InvalidPNG, "Input PNG file has invalid format type", "");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -860,13 +867,9 @@ TextureType ZTexture::GetTextureTypeFromString(const std::string& str)
|
||||
else if (str == "rgb5a1")
|
||||
{
|
||||
texType = TextureType::RGBA16bpp;
|
||||
#ifdef DEPRECATION_ON
|
||||
fprintf(stderr, "ZTexture::GetTextureTypeFromString: Deprecation warning.\n"
|
||||
"\t The texture format 'rgb5a1' is currently deprecated, and will be "
|
||||
"removed in a future "
|
||||
"version.\n"
|
||||
"\t Use the format 'rgba16' instead.\n");
|
||||
#endif
|
||||
HANDLE_WARNING(WarningType::Deprecated,
|
||||
"the texture format 'rgb5a1' is currently deprecated",
|
||||
"It will be removed in a future version. Use the format 'rgba16' instead.");
|
||||
}
|
||||
else if (str == "i4")
|
||||
texType = TextureType::Grayscale4bpp;
|
||||
@ -883,7 +886,9 @@ TextureType ZTexture::GetTextureTypeFromString(const std::string& str)
|
||||
else if (str == "ci8")
|
||||
texType = TextureType::Palette8bpp;
|
||||
else
|
||||
fprintf(stderr, "Encountered Unknown Texture format %s \n", str.c_str());
|
||||
// TODO: handle this case in a more coherent way
|
||||
HANDLE_WARNING(WarningType::InvalidAttributeValue,
|
||||
"invalid value found for 'Type' attribute", "Defaulting to ''.");
|
||||
return texType;
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
* File: ZTextureAnimation.cpp
|
||||
* ZResources defined: ZTextureAnimation, ZTextureAnimationParams (XML declaration not supported for
|
||||
* the latter)
|
||||
* Purpose: extracting texture animating structures from asset files Note: data type is exclusive to
|
||||
* Majora's Mask
|
||||
* Purpose: extracting texture animating structures from asset files
|
||||
* Note: data type is exclusive to Majora's Mask
|
||||
*
|
||||
* Structure of data:
|
||||
* A texture animation consists of a main array of data of the form
|
||||
@ -82,6 +82,7 @@
|
||||
|
||||
#include "Globals.h"
|
||||
#include "Utils/BitConverter.h"
|
||||
#include "WarningHandler.h"
|
||||
#include "ZFile.h"
|
||||
#include "ZResource.h"
|
||||
#include "tinyxml2.h"
|
||||
@ -115,7 +116,7 @@ void ZTextureAnimationParams::ExtractFromBinary(uint32_t nRawDataIndex)
|
||||
ParseRawData();
|
||||
}
|
||||
|
||||
// Implemented by TextureScrollingParams only[
|
||||
// Implemented by TextureScrollingParams only
|
||||
void ZTextureAnimationParams::ExtractFromBinary([[maybe_unused]] uint32_t nRawDataIndex,
|
||||
[[maybe_unused]] int count)
|
||||
{
|
||||
@ -217,19 +218,8 @@ void TextureColorChangingParams::ParseRawData()
|
||||
((type == TextureAnimationParamsType::ColorChange) ? animLength : colorListCount);
|
||||
|
||||
if (listLength == 0)
|
||||
throw std::runtime_error(StringHelper::Sprintf(
|
||||
"When processing file %s: in input binary file %s, offset 0x%06X:"
|
||||
"\n\t"
|
||||
"\033[97m"
|
||||
"TextureColorChangingParams::ParseRawData:"
|
||||
"\033[0m"
|
||||
"\033[91m"
|
||||
" error: "
|
||||
"\033[0m"
|
||||
"\033[97m"
|
||||
"color list length cannot be 0\n"
|
||||
"\033[0m",
|
||||
Globals::Instance->inputPath.c_str(), parent->GetName().c_str(), rawDataIndex));
|
||||
HANDLE_ERROR_RESOURCE(WarningType::Always, parent, this, rawDataIndex,
|
||||
"color list length cannot be 0", "");
|
||||
|
||||
primColorListAddress = BitConverter::ToUInt32BE(rawData, rawDataIndex + 4);
|
||||
envColorListAddress = BitConverter::ToUInt32BE(rawData, rawDataIndex + 8);
|
||||
@ -378,20 +368,8 @@ void TextureCyclingParams::ParseRawData()
|
||||
|
||||
cycleLength = BitConverter::ToUInt16BE(rawData, rawDataIndex);
|
||||
if (cycleLength == 0)
|
||||
throw std::runtime_error(
|
||||
StringHelper::Sprintf("When processing file %s: in input binary file %s, offset 0x%06X:"
|
||||
"\n\t"
|
||||
"\033[97m"
|
||||
"TextureCyclingParams::ParseRawData:"
|
||||
"\033[0m"
|
||||
"\033[91m"
|
||||
" error: "
|
||||
"\033[0m"
|
||||
"\033[97m"
|
||||
"cycleLength cannot be 0\n"
|
||||
"\033[0m",
|
||||
Globals::Instance->inputPath.c_str(), parent->GetName().c_str(),
|
||||
Seg2Filespace(rawDataIndex, 0)));
|
||||
HANDLE_ERROR_RESOURCE(WarningType::Always, parent, this, rawDataIndex,
|
||||
"cycle length cannot be 0", "");
|
||||
|
||||
textureListAddress = BitConverter::ToUInt32BE(rawData, rawDataIndex + 4);
|
||||
textureIndexListAddress = BitConverter::ToUInt32BE(rawData, rawDataIndex + 8);
|
||||
@ -454,21 +432,12 @@ void TextureCyclingParams::DeclareReferences([[maybe_unused]] const std::string&
|
||||
{
|
||||
comment = " // Raw pointer, declare texture in XML to use proper symbol";
|
||||
|
||||
fprintf(stderr,
|
||||
"When processing file %s: in input binary file %s, offset 0x%06X:"
|
||||
"\n\t"
|
||||
"\033[97m"
|
||||
"TextureCyclingParams::DeclareReferences:"
|
||||
"\033[0m"
|
||||
"\033[95m"
|
||||
" warning: "
|
||||
"\033[0m"
|
||||
"\033[97m"
|
||||
"TexCycle declared here points to unknown texture at address %s. "
|
||||
"Please declare the texture in the XML to use the proper symbol.\n"
|
||||
"\033[0m",
|
||||
Globals::Instance->inputPath.c_str(), parent->GetName().c_str(),
|
||||
Seg2Filespace(textureListAddress, parent->baseAddress), texName.c_str());
|
||||
auto msgHeader = StringHelper::Sprintf(
|
||||
"TexCycle texture array declared here points to unknown texture at address %s",
|
||||
texName.c_str());
|
||||
HANDLE_WARNING_RESOURCE(
|
||||
WarningType::HardcodedPointer, parent, this, rawDataIndex, msgHeader,
|
||||
"Please declare the texture in the XML to use the proper symbol.");
|
||||
}
|
||||
texturesBodyStr += StringHelper::Sprintf("\t%s,%s\n", texName.c_str(), comment.c_str());
|
||||
}
|
||||
@ -546,22 +515,14 @@ void ZTextureAnimation::ParseRawData()
|
||||
|
||||
if ((type < 0) || (type > 6))
|
||||
{
|
||||
throw std::runtime_error(StringHelper::Sprintf(
|
||||
"When processing file %s: in input binary file %s, offset 0x%06X:"
|
||||
"\n\t"
|
||||
"\033[97m"
|
||||
"ZTextureAnimation::ParseRawData:"
|
||||
"\033[0m"
|
||||
"\033[91m"
|
||||
" error: "
|
||||
"\033[0m"
|
||||
"\033[97m"
|
||||
"unknown TextureAnimationParams type 0x%02X in TextureAnimation: entry reads\n\t{ "
|
||||
"0x%02X, 0x%02X, 0x%08X }\n(type should be between "
|
||||
"0x00 and 0x06)\n"
|
||||
"\033[0m",
|
||||
Globals::Instance->inputPath.c_str(), parent->GetName().c_str(), rawDataIndex, type,
|
||||
currentEntry.segment, type, currentEntry.paramsPtr));
|
||||
HANDLE_ERROR_RESOURCE(
|
||||
WarningType::Always, parent, this, rawDataIndex,
|
||||
StringHelper::Sprintf(
|
||||
"unknown TextureAnimationParams type 0x%02X in TextureAnimation", type),
|
||||
StringHelper::Sprintf(
|
||||
"Entry reads { 0x%02X, 0x%02X, 0x%08X } , but type should be "
|
||||
"between 0x00 and 0x06 inclusive.",
|
||||
currentEntry.segment, type, currentEntry.paramsPtr));
|
||||
}
|
||||
|
||||
if (currentEntry.segment <= 0)
|
||||
@ -589,13 +550,24 @@ void ZTextureAnimation::DeclareReferences(const std::string& prefix)
|
||||
if (!parent->HasDeclaration(paramsOffset))
|
||||
{
|
||||
ZTextureAnimationParams* params;
|
||||
int count = 2;
|
||||
int count;
|
||||
switch (entry.type)
|
||||
{
|
||||
case TextureAnimationParamsType::SingleScroll:
|
||||
count = 1;
|
||||
[[fallthrough]];
|
||||
case TextureAnimationParamsType::DualScroll:
|
||||
if (true)
|
||||
{
|
||||
count = 1;
|
||||
// The else now allows SingleScroll to fall through to params = ... without
|
||||
// touching the code in the else block
|
||||
}
|
||||
else
|
||||
{
|
||||
// The contents of this block can only be run by jumping into it with the
|
||||
// case label
|
||||
[[fallthrough]];
|
||||
case TextureAnimationParamsType::DualScroll:
|
||||
count = 2;
|
||||
}
|
||||
params = new TextureScrollingParams(parent);
|
||||
params->ExtractFromBinary(paramsOffset, count);
|
||||
break;
|
||||
@ -614,22 +586,12 @@ void ZTextureAnimation::DeclareReferences(const std::string& prefix)
|
||||
break;
|
||||
|
||||
case TextureAnimationParamsType::Empty:
|
||||
fprintf(stderr,
|
||||
"When processing file %s: in input binary file %s: offset 0x%06X:"
|
||||
"\n\t"
|
||||
"\033[97m"
|
||||
"ZTextureAnimation::DeclareReferences:"
|
||||
"\033[0m"
|
||||
"\033[95m"
|
||||
" warning: "
|
||||
"\033[0m"
|
||||
"\033[97m"
|
||||
"TextureAnimationParams entry has empty type (6), but params pointer "
|
||||
"is not NULL. Params read\n\t\t"
|
||||
"{ 0x%02X, 0x%02X, 0x%08X }\n"
|
||||
"\033[0m",
|
||||
Globals::Instance->inputPath.c_str(), parent->GetName().c_str(),
|
||||
rawDataIndex, entry.segment, (int)entry.type, entry.paramsPtr);
|
||||
HANDLE_WARNING_RESOURCE(
|
||||
WarningType::InvalidExtractedData, parent, this, rawDataIndex,
|
||||
"TextureAnimationParams entry has empty type (6), but params pointer is "
|
||||
"not NULL",
|
||||
StringHelper::Sprintf("Params read { 0x%02X, 0x%02X, 0x%08X } .",
|
||||
entry.segment, (int)entry.type, entry.paramsPtr));
|
||||
return;
|
||||
default:
|
||||
// Because GCC is worried this could happen
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "Utils/BitConverter.h"
|
||||
#include "Utils/File.h"
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "WarningHandler.h"
|
||||
#include "ZFile.h"
|
||||
|
||||
REGISTER_ZFILENODE(Vector, ZVector);
|
||||
@ -86,20 +87,18 @@ std::string ZVector::GetSourceTypeName() const
|
||||
return "Vec3i";
|
||||
else
|
||||
{
|
||||
std::string output = StringHelper::Sprintf(
|
||||
"Encountered unsupported vector type: %d dimensions, %s type", dimensions,
|
||||
std::string msgHeader = StringHelper::Sprintf(
|
||||
"encountered unsupported vector type: %d dimensions, %s type", dimensions,
|
||||
ZScalar::MapScalarTypeToOutputType(scalarType).c_str());
|
||||
|
||||
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG)
|
||||
printf("%s\n", output.c_str());
|
||||
|
||||
throw std::runtime_error(output);
|
||||
HANDLE_ERROR_RESOURCE(WarningType::NotImplemented, parent, this, rawDataIndex, msgHeader,
|
||||
"");
|
||||
}
|
||||
}
|
||||
|
||||
std::string ZVector::GetBodySourceCode() const
|
||||
{
|
||||
std::string body;
|
||||
std::string body = "";
|
||||
|
||||
for (size_t i = 0; i < scalars.size(); i++)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "ZResource.h"
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "ZResource.h"
|
||||
|
0
tools/ZAPD/ZAPD/any/any/zlib.static.txt
Normal file
0
tools/ZAPD/ZAPD/any/any/zlib.static.txt
Normal file
@ -1,8 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="libpng" version="1.6.28.1" targetFramework="native" />
|
||||
<package id="libpng.redist" version="1.6.28.1" targetFramework="native" />
|
||||
<package id="libpng.static" version="1.6.37" targetFramework="native" />
|
||||
<package id="YY.NuGet.Import.Helper" version="1.0.0.4" targetFramework="native" />
|
||||
<package id="zlib" version="1.2.8.8" targetFramework="native" />
|
||||
<package id="zlib.static" version="1.2.5" targetFramework="native" />
|
||||
<package id="zlib.v120.windesktop.msvcstl.dyn.rt-dyn" version="1.2.8.8" targetFramework="native" />
|
||||
<package id="zlib.v140.windesktop.msvcstl.dyn.rt-dyn" version="1.2.8.8" targetFramework="native" />
|
||||
</packages>
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
|
||||
struct Color3b
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Only used for standalone compilation, usually inherits these from the main makefile
|
||||
CXXFLAGS ?= -Wall -Wextra -O2 -g -std=c++17
|
||||
|
||||
SRC_DIRS := $(shell find -type d -not -path "*build*")
|
||||
SRC_DIRS := $(shell find . -type d -not -path "*build*")
|
||||
CPP_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.cpp))
|
||||
H_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.h))
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
typedef uint32_t strhash;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "BinaryReader.h"
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
#include <stdexcept>
|
||||
#include "Stream.h"
|
||||
|
||||
@ -89,7 +89,7 @@ float BinaryReader::ReadSingle()
|
||||
|
||||
stream->Read((char*)&result, sizeof(float));
|
||||
|
||||
if (isnan(result))
|
||||
if (std::isnan(result))
|
||||
throw std::runtime_error("BinaryReader::ReadSingle(): Error reading stream");
|
||||
|
||||
return result;
|
||||
@ -100,7 +100,7 @@ double BinaryReader::ReadDouble()
|
||||
double result = NAN;
|
||||
|
||||
stream->Read((char*)&result, sizeof(double));
|
||||
if (isnan(result))
|
||||
if (std::isnan(result))
|
||||
throw std::runtime_error("BinaryReader::ReadDouble(): Error reading stream");
|
||||
|
||||
return result;
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
class BitConverter
|
||||
|
@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "Directory.h"
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "MemoryStream.h"
|
||||
#include <string.h>
|
||||
#include <cstring>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#define memcpy_s(dest, destSize, source, sourceSize) memcpy(dest, source, destSize)
|
||||
|
@ -18,13 +18,13 @@ public:
|
||||
static std::string GetFileName(const fs::path& input)
|
||||
{
|
||||
// https://en.cppreference.com/w/cpp/filesystem/path/filename
|
||||
return input.filename();
|
||||
return input.filename().string();
|
||||
};
|
||||
|
||||
static std::string GetFileNameWithoutExtension(const fs::path& input)
|
||||
{
|
||||
// https://en.cppreference.com/w/cpp/filesystem/path/stem
|
||||
return input.stem();
|
||||
return input.stem().string();
|
||||
};
|
||||
|
||||
static std::string GetFileNameExtension(const std::string& input)
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
|
||||
enum class SeekOffsetType
|
||||
{
|
||||
|
@ -1,18 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <numeric>
|
||||
#include <stdarg.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define __PRETTY_FUNCTION__ __FUNCSIG__
|
||||
#elif not defined(__GNUC__)
|
||||
#define __PRETTY_FUNCTION__ __func__
|
||||
#endif
|
||||
|
||||
class StringHelper
|
||||
{
|
||||
public:
|
||||
@ -111,4 +105,10 @@ public:
|
||||
{
|
||||
return std::all_of(str.begin(), str.end(), ::isdigit);
|
||||
}
|
||||
|
||||
static bool IEquals(const std::string& a, const std::string& b)
|
||||
{
|
||||
return std::equal(a.begin(), a.end(), b.begin(), b.end(),
|
||||
[](char a, char b) { return tolower(a) == tolower(b); });
|
||||
}
|
||||
};
|
||||
|
45
tools/ZAPD/ZAPDUtils/Utils/vt.h
Normal file
45
tools/ZAPD/ZAPDUtils/Utils/vt.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef VT_H
|
||||
#define VT_H
|
||||
|
||||
// clang-format off
|
||||
#define VT_COLOR_BLACK 0
|
||||
#define VT_COLOR_RED 1
|
||||
#define VT_COLOR_GREEN 2
|
||||
#define VT_COLOR_YELLOW 3
|
||||
#define VT_COLOR_BLUE 4
|
||||
#define VT_COLOR_PURPLE 5
|
||||
#define VT_COLOR_CYAN 6
|
||||
#define VT_COLOR_WHITE 7
|
||||
#define VT_COLOR_LIGHTGRAY 8
|
||||
#define VT_COLOR_DARKGRAY 9
|
||||
|
||||
#define VT_COLOR_FOREGROUND 3
|
||||
#define VT_COLOR_BACKGROUND 4
|
||||
// clang-format on
|
||||
|
||||
#define VT_COLOR_EXPAND0(type, color) #type #color
|
||||
#define VT_COLOR_EXPAND1(type, color) VT_COLOR_EXPAND0(type, color)
|
||||
#define VT_COLOR(type, color) VT_COLOR_EXPAND1(VT_COLOR_##type, VT_COLOR_##color)
|
||||
|
||||
#define VT_ESC "\x1b"
|
||||
#define VT_CSI "["
|
||||
#define VT_CUP(x, y) VT_ESC VT_CSI y ";" x "H"
|
||||
#define VT_ED(n) VT_ESC VT_CSI #n "J"
|
||||
#define VT_SGR(n) VT_ESC VT_CSI n "m"
|
||||
|
||||
// Add more macros if necessary
|
||||
#define VT_COL(back, fore) VT_SGR(VT_COLOR(BACKGROUND, back) ";" VT_COLOR(FOREGROUND, fore))
|
||||
#define VT_FGCOL(color) VT_SGR(VT_COLOR(FOREGROUND, color))
|
||||
#define VT_BGCOL(color) VT_SGR(VT_COLOR(BACKGROUND, color))
|
||||
|
||||
// Bold
|
||||
#define VT_BOLD "1"
|
||||
|
||||
// Bold color support
|
||||
#define VT_BOLD_FGCOL(color) VT_SGR(VT_BOLD ";" VT_COLOR(FOREGROUND, color))
|
||||
#define VT_BOLD_BGCOL(color) VT_SGR(VT_BOLD ";" VT_COLOR(BACKGROUND, color))
|
||||
|
||||
#define VT_RST VT_SGR("")
|
||||
#define VT_CLS VT_ED(2)
|
||||
|
||||
#endif
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
|
||||
struct Vec2f
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
|
||||
struct Vec3f
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
|
||||
struct Vec3s
|
||||
{
|
||||
|
@ -43,7 +43,7 @@
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
@ -116,6 +116,8 @@
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<LanguageStandard_C>Default</LanguageStandard_C>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@ -155,6 +157,7 @@
|
||||
<ClInclude Include="Vec3s.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\lib\tinyxml2\tinyxml2.cpp" />
|
||||
<ClCompile Include="Utils\BinaryReader.cpp" />
|
||||
<ClCompile Include="Utils\BinaryWriter.cpp" />
|
||||
<ClCompile Include="Utils\MemoryStream.cpp" />
|
||||
|
@ -19,6 +19,9 @@
|
||||
<Filter Include="Source Files\Utils">
|
||||
<UniqueIdentifier>{e047919d-7186-49ca-b115-e48fbb5c8743}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Libraries">
|
||||
<UniqueIdentifier>{3de9dd46-0dfd-4d48-9f20-9f24e5b80fe0}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Utils\BinaryWriter.h">
|
||||
@ -74,5 +77,8 @@
|
||||
<ClCompile Include="Utils\BinaryReader.cpp">
|
||||
<Filter>Source Files\Utils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lib\tinyxml2\tinyxml2.cpp">
|
||||
<Filter>Source Files\Libraries</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
BIN
tools/ZAPD/docs/zapd_warning_example.png
Normal file
BIN
tools/ZAPD/docs/zapd_warning_example.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 46 KiB |
@ -6,7 +6,7 @@
|
||||
[subrepo]
|
||||
remote = https://github.com/simonlindholm/asm-differ.git
|
||||
branch = main
|
||||
commit = f30d43aceba6291aa3c08b7317b0458b6d734321
|
||||
parent = e977dfeb374c6de4076ca9a0f44ba5a6a701d849
|
||||
commit = 70c33cc125666495f84f8c7bee60d3158b4b1164
|
||||
parent = 62341d8db0c29d1d4f0c360196e428309ac373b6
|
||||
method = merge
|
||||
cmdver = 0.4.3
|
||||
|
@ -640,6 +640,7 @@ class Text:
|
||||
class TableMetadata:
|
||||
headers: Tuple[Text, ...]
|
||||
current_score: int
|
||||
max_score: int
|
||||
previous_score: Optional[int]
|
||||
|
||||
|
||||
@ -832,6 +833,7 @@ class JsonFormatter(Formatter):
|
||||
for h, name in zip(meta.headers, ("base", "current", "previous"))
|
||||
}
|
||||
output["current_score"] = meta.current_score
|
||||
output["max_score"] = meta.max_score
|
||||
if meta.previous_score is not None:
|
||||
output["previous_score"] = meta.previous_score
|
||||
output_rows: List[Dict[str, Any]] = []
|
||||
@ -1184,8 +1186,9 @@ def parse_elf_data_references(data: bytes) -> List[Tuple[int, int, str]]:
|
||||
assert len(symtab_sections) == 1
|
||||
symtab = sections[symtab_sections[0]]
|
||||
|
||||
text_sections = [i for i in range(e_shnum) if sec_names[i] == b".text"]
|
||||
assert len(text_sections) == 1
|
||||
text_sections = [i for i in range(e_shnum) if sec_names[i] == b".text" and sections[i].sh_size != 0]
|
||||
if len(text_sections) != 1:
|
||||
return []
|
||||
text_section = text_sections[0]
|
||||
|
||||
ret: List[Tuple[int, int, str]] = []
|
||||
@ -1327,11 +1330,23 @@ def dump_binary(
|
||||
(objdump_flags + flags2, project.myimg, None),
|
||||
)
|
||||
|
||||
DATA_POOL_PLACEHOLDER = "DATA_POOL_PLACEHOLDER-OFFSET_{}"
|
||||
DATA_POOL_PLACEHOLDER_PATTERN = re.compile(
|
||||
r"DATA_POOL_PLACEHOLDER-OFFSET_([a-zA-z0-9]+)"
|
||||
)
|
||||
|
||||
class DifferenceNormalizer:
|
||||
# Example: "ldr r4, [pc, #56] ; (4c <AddCoins+0x4c>)"
|
||||
ARM32_LOAD_POOL_PATTERN = r"(ldr\s+r([0-9]|1[0-3]),\s+\[pc,.*;\s*)(\([a-fA-F0-9]+.*\))"
|
||||
|
||||
|
||||
# The base class is a no-op.
|
||||
class AsmProcessor:
|
||||
def __init__(self, config: Config) -> None:
|
||||
self.config = config
|
||||
|
||||
def process_reloc(self, row: str, prev: str) -> str:
|
||||
return prev
|
||||
|
||||
def normalize(self, mnemonic: str, row: str) -> str:
|
||||
"""This should be called exactly once for each line."""
|
||||
arch = self.config.arch
|
||||
@ -1342,9 +1357,143 @@ class DifferenceNormalizer:
|
||||
|
||||
def _normalize_arch_specific(self, mnemonic: str, row: str) -> str:
|
||||
return row
|
||||
|
||||
def post_process(self, lines: List["Line"]) -> None:
|
||||
return
|
||||
|
||||
|
||||
class DifferenceNormalizerAArch64(DifferenceNormalizer):
|
||||
class AsmProcessorMIPS(AsmProcessor):
|
||||
def process_reloc(self, row: str, prev: str) -> str:
|
||||
arch = self.config.arch
|
||||
if "R_MIPS_NONE" in row:
|
||||
# GNU as emits no-op relocations immediately after real ones when
|
||||
# assembling with -mabi=64. Return without trying to parse 'imm' as an
|
||||
# integer.
|
||||
return prev
|
||||
before, imm, after = parse_relocated_line(prev)
|
||||
repl = row.split()[-1]
|
||||
if imm != "0":
|
||||
# MIPS uses relocations with addends embedded in the code as immediates.
|
||||
# If there is an immediate, show it as part of the relocation. Ideally
|
||||
# we'd show this addend in both %lo/%hi, but annoyingly objdump's output
|
||||
# doesn't include enough information to pair up %lo's and %hi's...
|
||||
# TODO: handle unambiguous cases where all addends for a symbol are the
|
||||
# same, or show "+???".
|
||||
mnemonic = prev.split()[0]
|
||||
if (
|
||||
mnemonic in arch.instructions_with_address_immediates
|
||||
and not imm.startswith("0x")
|
||||
):
|
||||
imm = "0x" + imm
|
||||
repl += "+" + imm if int(imm, 0) > 0 else imm
|
||||
if "R_MIPS_LO16" in row:
|
||||
repl = f"%lo({repl})"
|
||||
elif "R_MIPS_HI16" in row:
|
||||
# Ideally we'd pair up R_MIPS_LO16 and R_MIPS_HI16 to generate a
|
||||
# correct addend for each, but objdump doesn't give us the order of
|
||||
# the relocations, so we can't find the right LO16. :(
|
||||
repl = f"%hi({repl})"
|
||||
elif "R_MIPS_26" in row:
|
||||
# Function calls
|
||||
pass
|
||||
elif "R_MIPS_PC16" in row:
|
||||
# Branch to glabel. This gives confusing output, but there's not much
|
||||
# we can do here.
|
||||
pass
|
||||
else:
|
||||
assert False, f"unknown relocation type '{row}' for line '{prev}'"
|
||||
return before + repl + after
|
||||
|
||||
|
||||
class AsmProcessorPPC(AsmProcessor):
|
||||
def process_reloc(self, row: str, prev: str) -> str:
|
||||
arch = self.config.arch
|
||||
assert any(
|
||||
r in row for r in ["R_PPC_REL24", "R_PPC_ADDR16", "R_PPC_EMB_SDA21"]
|
||||
), f"unknown relocation type '{row}' for line '{prev}'"
|
||||
before, imm, after = parse_relocated_line(prev)
|
||||
repl = row.split()[-1]
|
||||
if "R_PPC_REL24" in row:
|
||||
# function calls
|
||||
pass
|
||||
elif "R_PPC_ADDR16_HI" in row:
|
||||
# absolute hi of addr
|
||||
repl = f"{repl}@h"
|
||||
elif "R_PPC_ADDR16_HA" in row:
|
||||
# adjusted hi of addr
|
||||
repl = f"{repl}@ha"
|
||||
elif "R_PPC_ADDR16_LO" in row:
|
||||
# lo of addr
|
||||
repl = f"{repl}@l"
|
||||
elif "R_PPC_ADDR16" in row:
|
||||
# 16-bit absolute addr
|
||||
if "+0x7" in repl:
|
||||
# remove the very large addends as they are an artifact of (label-_SDA(2)_BASE_)
|
||||
# computations and are unimportant in a diff setting.
|
||||
if int(repl.split("+")[1], 16) > 0x70000000:
|
||||
repl = repl.split("+")[0]
|
||||
elif "R_PPC_EMB_SDA21" in row:
|
||||
# small data area
|
||||
pass
|
||||
return before + repl + after
|
||||
|
||||
|
||||
class AsmProcessorARM32(AsmProcessor):
|
||||
def process_reloc(self, row: str, prev: str) -> str:
|
||||
arch = self.config.arch
|
||||
before, imm, after = parse_relocated_line(prev)
|
||||
repl = row.split()[-1]
|
||||
return before + repl + after
|
||||
|
||||
def _normalize_arch_specific(self, mnemonic: str, row: str) -> str:
|
||||
if self.config.ignore_addr_diffs:
|
||||
row = self._normalize_bl(mnemonic, row)
|
||||
row = self._normalize_data_pool(row)
|
||||
return row
|
||||
|
||||
def _normalize_bl(self, mnemonic: str, row: str) -> str:
|
||||
if mnemonic != "bl":
|
||||
return row
|
||||
|
||||
row, _ = split_off_address(row)
|
||||
return row + "<ignore>"
|
||||
|
||||
def _normalize_data_pool(self, row: str) -> str:
|
||||
pool_match = re.search(ARM32_LOAD_POOL_PATTERN, row)
|
||||
if pool_match:
|
||||
offset = pool_match.group(3).split(" ")[0][1:]
|
||||
repl = DATA_POOL_PLACEHOLDER.format(offset)
|
||||
return pool_match.group(1) + repl
|
||||
return row
|
||||
|
||||
def post_process(self, lines: List["Line"]) -> None:
|
||||
lines_by_line_number = {}
|
||||
for line in lines:
|
||||
lines_by_line_number[line.line_num] = line
|
||||
for line in lines:
|
||||
reloc_match = re.search(
|
||||
DATA_POOL_PLACEHOLDER_PATTERN, line.normalized_original
|
||||
)
|
||||
if reloc_match is None:
|
||||
continue
|
||||
|
||||
# Get value at relocation
|
||||
reloc = reloc_match.group(0)
|
||||
line_number = re.search(
|
||||
DATA_POOL_PLACEHOLDER_PATTERN, reloc).group(1)
|
||||
line_original = lines_by_line_number[int(line_number, 16)].original
|
||||
value = line_original.split()[1]
|
||||
|
||||
# Replace relocation placeholder with value
|
||||
replaced = re.sub(
|
||||
DATA_POOL_PLACEHOLDER_PATTERN,
|
||||
f"={value} ({line_number})",
|
||||
line.normalized_original,
|
||||
)
|
||||
line.original = replaced
|
||||
|
||||
|
||||
class AsmProcessorAArch64(AsmProcessor):
|
||||
def __init__(self, config: Config) -> None:
|
||||
super().__init__(config)
|
||||
self._adrp_pair_registers: Set[str] = set()
|
||||
@ -1394,23 +1543,6 @@ class DifferenceNormalizerAArch64(DifferenceNormalizer):
|
||||
return row
|
||||
|
||||
|
||||
class DifferenceNormalizerARM32(DifferenceNormalizer):
|
||||
def __init__(self, config: Config) -> None:
|
||||
super().__init__(config)
|
||||
|
||||
def _normalize_arch_specific(self, mnemonic: str, row: str) -> str:
|
||||
if self.config.ignore_addr_diffs:
|
||||
row = self._normalize_bl(mnemonic, row)
|
||||
return row
|
||||
|
||||
def _normalize_bl(self, mnemonic: str, row: str) -> str:
|
||||
if mnemonic != "bl":
|
||||
return row
|
||||
|
||||
row, _ = split_off_address(row)
|
||||
return row + "<ignore>"
|
||||
|
||||
|
||||
@dataclass
|
||||
class ArchSettings:
|
||||
name: str
|
||||
@ -1420,14 +1552,15 @@ class ArchSettings:
|
||||
re_sprel: Pattern[str]
|
||||
re_large_imm: Pattern[str]
|
||||
re_imm: Pattern[str]
|
||||
re_reloc: Pattern[str]
|
||||
branch_instructions: Set[str]
|
||||
instructions_with_address_immediates: Set[str]
|
||||
forbidden: Set[str] = field(default_factory=lambda: set(string.ascii_letters + "_"))
|
||||
arch_flags: List[str] = field(default_factory=list)
|
||||
branch_likely_instructions: Set[str] = field(default_factory=set)
|
||||
difference_normalizer: Type[DifferenceNormalizer] = DifferenceNormalizer
|
||||
proc: Type[AsmProcessor] = AsmProcessor
|
||||
big_endian: Optional[bool] = True
|
||||
|
||||
delay_slot_instructions: Set[str] = field(default_factory=set)
|
||||
|
||||
MIPS_BRANCH_LIKELY_INSTRUCTIONS = {
|
||||
"beql",
|
||||
@ -1543,10 +1676,13 @@ MIPS_SETTINGS = ArchSettings(
|
||||
re_sprel=re.compile(r"(?<=,)([0-9]+|0x[0-9a-f]+)\(sp\)"),
|
||||
re_large_imm=re.compile(r"-?[1-9][0-9]{2,}|-?0x[0-9a-f]{3,}"),
|
||||
re_imm=re.compile(r"(\b|-)([0-9]+|0x[0-9a-fA-F]+)\b(?!\(sp)|%(lo|hi)\([^)]*\)"),
|
||||
re_reloc=re.compile(r"R_MIPS_"),
|
||||
arch_flags=["-m", "mips:4300"],
|
||||
branch_likely_instructions=MIPS_BRANCH_LIKELY_INSTRUCTIONS,
|
||||
branch_instructions=MIPS_BRANCH_INSTRUCTIONS,
|
||||
instructions_with_address_immediates=MIPS_BRANCH_INSTRUCTIONS.union({"jal", "j"}),
|
||||
delay_slot_instructions=MIPS_BRANCH_INSTRUCTIONS.union({"j", "jal", "jr", "jalr"}),
|
||||
proc=AsmProcessorMIPS,
|
||||
)
|
||||
|
||||
MIPSEL_SETTINGS = replace(MIPS_SETTINGS, name="mipsel", big_endian=False)
|
||||
@ -1566,9 +1702,10 @@ ARM32_SETTINGS = ArchSettings(
|
||||
re_sprel=re.compile(r"sp, #-?(0x[0-9a-fA-F]+|[0-9]+)\b"),
|
||||
re_large_imm=re.compile(r"-?[1-9][0-9]{2,}|-?0x[0-9a-f]{3,}"),
|
||||
re_imm=re.compile(r"(?<!sp, )#-?(0x[0-9a-fA-F]+|[0-9]+)\b"),
|
||||
re_reloc=re.compile(r"R_ARM_"),
|
||||
branch_instructions=ARM32_BRANCH_INSTRUCTIONS,
|
||||
instructions_with_address_immediates=ARM32_BRANCH_INSTRUCTIONS.union({"adr"}),
|
||||
difference_normalizer=DifferenceNormalizerARM32,
|
||||
proc=AsmProcessorARM32,
|
||||
)
|
||||
|
||||
AARCH64_SETTINGS = ArchSettings(
|
||||
@ -1581,9 +1718,10 @@ AARCH64_SETTINGS = ArchSettings(
|
||||
re_sprel=re.compile(r"sp, #-?(0x[0-9a-fA-F]+|[0-9]+)\b"),
|
||||
re_large_imm=re.compile(r"-?[1-9][0-9]{2,}|-?0x[0-9a-f]{3,}"),
|
||||
re_imm=re.compile(r"(?<!sp, )#-?(0x[0-9a-fA-F]+|[0-9]+)\b"),
|
||||
re_reloc=re.compile(r"R_AARCH64_"),
|
||||
branch_instructions=AARCH64_BRANCH_INSTRUCTIONS,
|
||||
instructions_with_address_immediates=AARCH64_BRANCH_INSTRUCTIONS.union({"bl", "adrp"}),
|
||||
difference_normalizer=DifferenceNormalizerAArch64,
|
||||
proc=AsmProcessorAArch64,
|
||||
)
|
||||
|
||||
PPC_SETTINGS = ArchSettings(
|
||||
@ -1594,8 +1732,10 @@ PPC_SETTINGS = ArchSettings(
|
||||
re_sprel=re.compile(r"(?<=,)(-?[0-9]+|-?0x[0-9a-f]+)\(r1\)"),
|
||||
re_large_imm=re.compile(r"-?[1-9][0-9]{2,}|-?0x[0-9a-f]{3,}"),
|
||||
re_imm=re.compile(r"(\b|-)([0-9]+|0x[0-9a-fA-F]+)\b(?!\(r1)|[^@]*@(ha|h|lo)"),
|
||||
re_reloc=re.compile(r"R_PPC_"),
|
||||
branch_instructions=PPC_BRANCH_INSTRUCTIONS,
|
||||
instructions_with_address_immediates=PPC_BRANCH_INSTRUCTIONS.union({"bl"}),
|
||||
proc=AsmProcessorPPC,
|
||||
)
|
||||
|
||||
ARCH_SETTINGS = [
|
||||
@ -1639,84 +1779,6 @@ def parse_relocated_line(line: str) -> Tuple[str, str, str]:
|
||||
return before, imm, after
|
||||
|
||||
|
||||
def process_mips_reloc(row: str, prev: str, arch: ArchSettings) -> str:
|
||||
if "R_MIPS_NONE" in row:
|
||||
# GNU as emits no-op relocations immediately after real ones when
|
||||
# assembling with -mabi=64. Return without trying to parse 'imm' as an
|
||||
# integer.
|
||||
return prev
|
||||
before, imm, after = parse_relocated_line(prev)
|
||||
repl = row.split()[-1]
|
||||
if imm != "0":
|
||||
# MIPS uses relocations with addends embedded in the code as immediates.
|
||||
# If there is an immediate, show it as part of the relocation. Ideally
|
||||
# we'd show this addend in both %lo/%hi, but annoyingly objdump's output
|
||||
# doesn't include enough information to pair up %lo's and %hi's...
|
||||
# TODO: handle unambiguous cases where all addends for a symbol are the
|
||||
# same, or show "+???".
|
||||
mnemonic = prev.split()[0]
|
||||
if (
|
||||
mnemonic in arch.instructions_with_address_immediates
|
||||
and not imm.startswith("0x")
|
||||
):
|
||||
imm = "0x" + imm
|
||||
repl += "+" + imm if int(imm, 0) > 0 else imm
|
||||
if "R_MIPS_LO16" in row:
|
||||
repl = f"%lo({repl})"
|
||||
elif "R_MIPS_HI16" in row:
|
||||
# Ideally we'd pair up R_MIPS_LO16 and R_MIPS_HI16 to generate a
|
||||
# correct addend for each, but objdump doesn't give us the order of
|
||||
# the relocations, so we can't find the right LO16. :(
|
||||
repl = f"%hi({repl})"
|
||||
elif "R_MIPS_26" in row:
|
||||
# Function calls
|
||||
pass
|
||||
elif "R_MIPS_PC16" in row:
|
||||
# Branch to glabel. This gives confusing output, but there's not much
|
||||
# we can do here.
|
||||
pass
|
||||
else:
|
||||
assert False, f"unknown relocation type '{row}' for line '{prev}'"
|
||||
return before + repl + after
|
||||
|
||||
|
||||
def process_ppc_reloc(row: str, prev: str) -> str:
|
||||
assert any(
|
||||
r in row for r in ["R_PPC_REL24", "R_PPC_ADDR16", "R_PPC_EMB_SDA21"]
|
||||
), f"unknown relocation type '{row}' for line '{prev}'"
|
||||
before, imm, after = parse_relocated_line(prev)
|
||||
repl = row.split()[-1]
|
||||
if "R_PPC_REL24" in row:
|
||||
# function calls
|
||||
pass
|
||||
elif "R_PPC_ADDR16_HI" in row:
|
||||
# absolute hi of addr
|
||||
repl = f"{repl}@h"
|
||||
elif "R_PPC_ADDR16_HA" in row:
|
||||
# adjusted hi of addr
|
||||
repl = f"{repl}@ha"
|
||||
elif "R_PPC_ADDR16_LO" in row:
|
||||
# lo of addr
|
||||
repl = f"{repl}@l"
|
||||
elif "R_PPC_ADDR16" in row:
|
||||
# 16-bit absolute addr
|
||||
if "+0x7" in repl:
|
||||
# remove the very large addends as they are an artifact of (label-_SDA(2)_BASE_)
|
||||
# computations and are unimportant in a diff setting.
|
||||
if int(repl.split("+")[1], 16) > 0x70000000:
|
||||
repl = repl.split("+")[0]
|
||||
elif "R_PPC_EMB_SDA21" in row:
|
||||
# small data area
|
||||
pass
|
||||
return before + repl + after
|
||||
|
||||
|
||||
def process_arm_reloc(row: str, prev: str, arch: ArchSettings) -> str:
|
||||
before, imm, after = parse_relocated_line(prev)
|
||||
repl = row.split()[-1]
|
||||
return before + repl + after
|
||||
|
||||
|
||||
def pad_mnemonic(line: str) -> str:
|
||||
if "\t" not in line:
|
||||
return line
|
||||
@ -1741,7 +1803,7 @@ class Line:
|
||||
|
||||
def process(dump: str, config: Config) -> List[Line]:
|
||||
arch = config.arch
|
||||
normalizer = arch.difference_normalizer(config)
|
||||
processor = arch.proc(config)
|
||||
skip_next = False
|
||||
source_lines = []
|
||||
source_filename = None
|
||||
@ -1783,7 +1845,7 @@ def process(dump: str, config: Config) -> List[Line]:
|
||||
)
|
||||
break
|
||||
|
||||
if not re.match(r"^ +[0-9a-f]+:\t", row):
|
||||
if not re.match(r"^\s+[0-9a-f]+:\s+", row):
|
||||
# This regex is conservative, and assumes the file path does not contain "weird"
|
||||
# characters like colons, tabs, or angle brackets.
|
||||
if re.match(
|
||||
@ -1797,10 +1859,11 @@ def process(dump: str, config: Config) -> List[Line]:
|
||||
m_comment = re.search(arch.re_comment, row)
|
||||
comment = m_comment[0] if m_comment else None
|
||||
row = re.sub(arch.re_comment, "", row)
|
||||
line_num_str = row.split(":")[0]
|
||||
row = row.rstrip()
|
||||
tabs = row.split("\t")
|
||||
row = "\t".join(tabs[2:])
|
||||
line_num = eval_line_num(tabs[0].strip())
|
||||
line_num = eval_line_num(line_num_str.strip())
|
||||
|
||||
if line_num in data_refs:
|
||||
refs = data_refs[line_num]
|
||||
@ -1835,20 +1898,13 @@ def process(dump: str, config: Config) -> List[Line]:
|
||||
|
||||
while i < len(lines):
|
||||
reloc_row = lines[i]
|
||||
if "R_AARCH64_" in reloc_row:
|
||||
# TODO: handle relocation
|
||||
pass
|
||||
elif "R_MIPS_" in reloc_row:
|
||||
original = process_mips_reloc(reloc_row, original, arch)
|
||||
elif "R_PPC_" in reloc_row:
|
||||
original = process_ppc_reloc(reloc_row, original)
|
||||
elif "R_ARM_" in reloc_row:
|
||||
original = process_arm_reloc(reloc_row, original, arch)
|
||||
if re.search(arch.re_reloc, reloc_row):
|
||||
original = processor.process_reloc(reloc_row, original)
|
||||
else:
|
||||
break
|
||||
i += 1
|
||||
|
||||
normalized_original = normalizer.normalize(mnemonic, original)
|
||||
normalized_original = processor.normalize(mnemonic, original)
|
||||
|
||||
scorable_line = normalized_original
|
||||
if not config.score_stack_differences:
|
||||
@ -1904,6 +1960,7 @@ def process(dump: str, config: Config) -> List[Line]:
|
||||
elif stop_after_delay_slot:
|
||||
break
|
||||
|
||||
processor.post_process(output)
|
||||
return output
|
||||
|
||||
|
||||
@ -2123,8 +2180,15 @@ class OutputLine:
|
||||
class Diff:
|
||||
lines: List[OutputLine]
|
||||
score: int
|
||||
max_score: int
|
||||
|
||||
|
||||
def trim_nops(lines: List[Line], arch: ArchSettings) -> List[Line]:
|
||||
lines = lines[:]
|
||||
while lines and lines[-1].mnemonic == "nop" and (len(lines) == 1 or lines[-2].mnemonic not in arch.delay_slot_instructions):
|
||||
lines.pop()
|
||||
return lines
|
||||
|
||||
def do_diff(lines1: List[Line], lines2: List[Line], config: Config) -> Diff:
|
||||
if config.show_source:
|
||||
import cxxfilt
|
||||
@ -2152,8 +2216,12 @@ def do_diff(lines1: List[Line], lines2: List[Line], config: Config) -> Diff:
|
||||
btset.add(bt)
|
||||
sc(str(bt))
|
||||
|
||||
lines1 = trim_nops(lines1, arch)
|
||||
lines2 = trim_nops(lines2, arch)
|
||||
|
||||
diffed_lines = diff_lines(lines1, lines2, config.algorithm)
|
||||
score = score_diff_lines(diffed_lines, config)
|
||||
max_score = len(lines1) * config.penalty_deletion
|
||||
|
||||
line_num_base = -1
|
||||
line_num_offset = 0
|
||||
@ -2385,7 +2453,7 @@ def do_diff(lines1: List[Line], lines2: List[Line], config: Config) -> Diff:
|
||||
)
|
||||
|
||||
output = output[config.skip_lines :]
|
||||
return Diff(lines=output, score=score)
|
||||
return Diff(lines=output, score=score, max_score=max_score)
|
||||
|
||||
|
||||
def chunk_diff_lines(
|
||||
@ -2461,6 +2529,7 @@ def align_diffs(
|
||||
Text(f"{padding}PREVIOUS ({old_diff.score})"),
|
||||
),
|
||||
current_score=new_diff.score,
|
||||
max_score=new_diff.max_score,
|
||||
previous_score=old_diff.score,
|
||||
)
|
||||
old_chunks = chunk_diff_lines(old_diff.lines)
|
||||
@ -2504,6 +2573,7 @@ def align_diffs(
|
||||
Text(f"{padding}CURRENT ({new_diff.score})"),
|
||||
),
|
||||
current_score=new_diff.score,
|
||||
max_score=new_diff.max_score,
|
||||
previous_score=None,
|
||||
)
|
||||
diff_lines = [(line, line) for line in new_diff.lines]
|
||||
|
@ -6,7 +6,7 @@
|
||||
[subrepo]
|
||||
remote = https://github.com/z64me/z64compress.git
|
||||
branch = main
|
||||
commit = 98ef0ac25f7adb47235c839838e29496d3546917
|
||||
parent = 69cc19eea8c30e50e280f400e8cf06fe66efca60
|
||||
commit = ac5b1a0d0b23346362a68a107da3478227f8e703
|
||||
parent = 33e3aa92181a0543826adc10a5f3304d60b391dd
|
||||
method = merge
|
||||
cmdver = 0.4.3
|
||||
|
@ -221,7 +221,7 @@ wow_main
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(printer, "welcome to z64compress 1.0.1 <z64.me>\n");
|
||||
fprintf(printer, "welcome to z64compress 1.0.2 <z64.me>\n");
|
||||
|
||||
if (argc <= 1)
|
||||
{
|
||||
@ -356,7 +356,6 @@ wow_main
|
||||
|
||||
ARG_ZERO_TEST(Ain , "--in" );
|
||||
ARG_ZERO_TEST(Aout , "--out" );
|
||||
ARG_ZERO_TEST(Amb , "--mb" );
|
||||
ARG_ZERO_TEST(Acodec, "--codec");
|
||||
|
||||
#undef ARG_ZERO_TEST
|
||||
|
@ -68,7 +68,9 @@ for (dma = rom->dma; (unsigned)(dma - rom->dma) < rom->dma_num; ++dma)
|
||||
|
||||
#define PROGRESS_A_B (int)(dma - rom->dma), rom->dma_num
|
||||
|
||||
#define ALIGN16(x) (((x) + 0xF) & ~0xF)
|
||||
#define ALIGN(x, n) (((x) + ((n)-1)) & ~((n)-1))
|
||||
#define ALIGN16(x) ALIGN(x, 16)
|
||||
#define ALIGN8MB(x) ALIGN(x, 8 * 0x100000)
|
||||
|
||||
/*
|
||||
*
|
||||
@ -936,7 +938,7 @@ void rom_compress(struct rom *rom, int mb, int numThreads, bool matching)
|
||||
|
||||
cache = rom->cache;
|
||||
|
||||
if (compsz > rom->data_sz || mb <= 0)
|
||||
if (compsz > rom->data_sz || mb < 0)
|
||||
die("invalid mb argument %d", mb);
|
||||
|
||||
/* get encoding functions */
|
||||
@ -1057,31 +1059,13 @@ void rom_compress(struct rom *rom, int mb, int numThreads, bool matching)
|
||||
/* sort by original start, ascending */
|
||||
DMASORT(rom, sortfunc_dma_start_ascend);
|
||||
|
||||
if (matching)
|
||||
{
|
||||
/* fill the entire (compressed) rom space with 00010203...FF...
|
||||
in order to match retail rom padding */
|
||||
unsigned char n = 0; // will intentionally overflow
|
||||
for (unsigned int j = 0; j < compsz; j++, n++)
|
||||
{
|
||||
rom->data[j] = n;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* zero the entire (compressed) rom space */
|
||||
memset(rom->data, 0, compsz);
|
||||
}
|
||||
|
||||
/* go through dma table, injecting compressed files */
|
||||
/* determine physical addresses for each segment */
|
||||
comp_total = 0;
|
||||
DMA_FOR_EACH
|
||||
{
|
||||
unsigned char *dst;
|
||||
char *fn = dma->compname;
|
||||
unsigned int sz;
|
||||
unsigned int sz16;
|
||||
fprintf(printer, "\r""injecting file %d/%d: ", PROGRESS_A_B);
|
||||
|
||||
if (dma->deleted)
|
||||
continue;
|
||||
@ -1114,9 +1098,6 @@ void rom_compress(struct rom *rom, int mb, int numThreads, bool matching)
|
||||
if (sz16 & 15)
|
||||
sz16 += 16 - (sz16 & 15);
|
||||
|
||||
/* put the files in */
|
||||
dst = rom->data + comp_total;
|
||||
|
||||
dma->Pstart = comp_total;
|
||||
if (dma->compress)
|
||||
{
|
||||
@ -1130,26 +1111,66 @@ void rom_compress(struct rom *rom, int mb, int numThreads, bool matching)
|
||||
dma->Pend = 0;
|
||||
comp_total += sz16;
|
||||
|
||||
if (dma->Pend > compsz)
|
||||
if (mb != 0 && dma->Pend > compsz)
|
||||
die("ran out of compressed rom space");
|
||||
}
|
||||
|
||||
/* adaptive final size */
|
||||
if (mb == 0)
|
||||
compsz = ALIGN8MB(comp_total);
|
||||
|
||||
if (matching)
|
||||
{
|
||||
/* fill the entire (compressed) rom space with 00010203...FF...
|
||||
in order to match retail rom padding */
|
||||
unsigned char n = 0; /* will intentionally overflow */
|
||||
for (unsigned int j = 0; j < compsz; j++, n++)
|
||||
{
|
||||
rom->data[j] = n;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* zero the entire (compressed) rom space */
|
||||
memset(rom->data, 0, compsz);
|
||||
}
|
||||
|
||||
/* inject compressed files */
|
||||
comp_total = 0;
|
||||
DMA_FOR_EACH
|
||||
{
|
||||
unsigned char *dst;
|
||||
char *fn = dma->compname;
|
||||
unsigned int sz;
|
||||
fprintf(printer, "\r""injecting file %d/%d: ", PROGRESS_A_B);
|
||||
|
||||
if (dma->deleted)
|
||||
continue;
|
||||
|
||||
dst = rom->data + dma->Pstart;
|
||||
|
||||
/* external cached file logic */
|
||||
if (cache)
|
||||
{
|
||||
/* skip entries that don't reference compressed files */
|
||||
if (!fn)
|
||||
continue;
|
||||
|
||||
/* load file into rom at offset */
|
||||
dst = file_load_into(cache_codec, fn, &sz, dst);
|
||||
}
|
||||
|
||||
/* otherwise, a simple memcpy */
|
||||
else
|
||||
{
|
||||
memcpy(dst, dma->compbuf, dma->compSz);
|
||||
if (matching)
|
||||
{
|
||||
// since matching rom padding is not zero but file padding is zero,
|
||||
// fill file padding space with zeros
|
||||
memset(dst + dma->compSz, 0, ALIGN16(dma->compSz) - dma->compSz);
|
||||
}
|
||||
sz = dma->compSz;
|
||||
}
|
||||
|
||||
if (matching)
|
||||
{
|
||||
/* since matching rom padding is not zero but file padding is zero,
|
||||
fill file padding space with zeros */
|
||||
memset(dst + sz, 0, ALIGN16(sz) - sz);
|
||||
}
|
||||
}
|
||||
fprintf(printer, "\r""injecting file %d/%d: ", dma_num, dma_num);
|
||||
|
Loading…
Reference in New Issue
Block a user