INCGFX: in-source arguments for gbagfx

'INCGFX' is like 'INCBIN' except that it specifies the arguments to pass
to 'gbagfx' which alleviates the user-unfriendliness caused by catch-all
rules.

Specifically, users frequently forget to add to 'spritesheet_rules.mk'
when adding object event graphics, and then the built '.4bpp' file is
not invalidated when the add their rule so they have to 'touch' the
source file or similar.

The built artifacts are placed in 'build/assets'.
This commit is contained in:
Martin Griffin
2026-03-30 13:29:25 +01:00
parent 84e8d23425
commit df02d49e9b
10 changed files with 377 additions and 54 deletions

View File

@@ -71,6 +71,7 @@ ROM_NAME := $(FILE_NAME).gba
OBJ_DIR_NAME := $(BUILD_DIR)/emerald
MODERN_ROM_NAME := $(FILE_NAME)_modern.gba
MODERN_OBJ_DIR_NAME := $(BUILD_DIR)/modern
ASSETS_DIR_NAME := $(BUILD_DIR)/assets
ELF_NAME := $(ROM_NAME:.gba=.elf)
MAP_NAME := $(ROM_NAME:.gba=.map)
@@ -234,6 +235,7 @@ clean: tidy clean-tools clean-generated clean-assets
@$(MAKE) clean -C libagbsyscall
clean-assets:
rm -rf $(ASSETS_DIR_NAME)
rm -f $(MID_SUBDIR)/*.s
rm -f $(DATA_ASM_SUBDIR)/layouts/layouts.inc $(DATA_ASM_SUBDIR)/layouts/layouts_table.inc
rm -f $(DATA_ASM_SUBDIR)/maps/connections.inc $(DATA_ASM_SUBDIR)/maps/events.inc $(DATA_ASM_SUBDIR)/maps/groups.inc $(DATA_ASM_SUBDIR)/maps/headers.inc
@@ -306,16 +308,16 @@ endif
$(C_BUILDDIR)/%.o: $(C_SUBDIR)/%.c
ifneq ($(KEEP_TEMPS),1)
@echo "$(CC1) <flags> -o $@ $<"
@$(CPP) $(CPPFLAGS) $< | $(PREPROC) -i $< charmap.txt | $(CC1) $(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $(AS) $(ASFLAGS) -o $@ -
@$(CPP) $(CPPFLAGS) $< | $(PREPROC) -i -g $(ASSETS_DIR_NAME) $< charmap.txt | $(CC1) $(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $(AS) $(ASFLAGS) -o $@ -
else
@$(CPP) $(CPPFLAGS) $< -o $(C_BUILDDIR)/$*.i
@$(PREPROC) $(C_BUILDDIR)/$*.i charmap.txt | $(CC1) $(CFLAGS) -o $(C_BUILDDIR)/$*.s
@$(PREPROC) -g $(ASSETS_DIR_NAME) $(C_BUILDDIR)/$*.i charmap.txt | $(CC1) $(CFLAGS) -o $(C_BUILDDIR)/$*.s
@echo -e ".text\n\t.align\t2, 0\n" >> $(C_BUILDDIR)/$*.s
$(AS) $(ASFLAGS) -o $@ $(C_BUILDDIR)/$*.s
endif
$(C_BUILDDIR)/%.d: $(C_SUBDIR)/%.c
$(SCANINC) -M $@ $(INCLUDE_SCANINC_ARGS) -I tools/agbcc/include $<
$(SCANINC) -M $@ -g $(ASSETS_DIR_NAME) $(INCLUDE_SCANINC_ARGS) -I tools/agbcc/include $<
ifneq ($(NODEP),1)
-include $(addprefix $(OBJ_DIR)/,$(C_SRCS:.c=.d))
@@ -325,7 +327,7 @@ $(ASM_BUILDDIR)/%.o: $(ASM_SUBDIR)/%.s
$(AS) $(ASFLAGS) -o $@ $<
$(ASM_BUILDDIR)/%.d: $(ASM_SUBDIR)/%.s
$(SCANINC) -M $@ $(INCLUDE_SCANINC_ARGS) -I "" $<
$(SCANINC) -M $@ -g $(ASSETS_DIR_NAME) $(INCLUDE_SCANINC_ARGS) -I "" $<
ifneq ($(NODEP),1)
-include $(addprefix $(OBJ_DIR)/,$(ASM_SRCS:.s=.d))
@@ -335,7 +337,7 @@ $(C_BUILDDIR)/%.o: $(C_SUBDIR)/%.s
$(PREPROC) $< charmap.txt | $(CPP) $(INCLUDE_SCANINC_ARGS) - | $(PREPROC) -ie $< charmap.txt | $(AS) $(ASFLAGS) -o $@
$(C_BUILDDIR)/%.d: $(C_SUBDIR)/%.s
$(SCANINC) -M $@ $(INCLUDE_SCANINC_ARGS) -I "" $<
$(SCANINC) -M $@ -g $(ASSETS_DIR_NAME) $(INCLUDE_SCANINC_ARGS) -I "" $<
ifneq ($(NODEP),1)
-include $(addprefix $(OBJ_DIR)/,$(C_ASM_SRCS:.s=.d))
@@ -345,7 +347,7 @@ $(DATA_ASM_BUILDDIR)/%.o: $(DATA_ASM_SUBDIR)/%.s
$(PREPROC) $< charmap.txt | $(CPP) $(INCLUDE_SCANINC_ARGS) - | $(PREPROC) -ie $< charmap.txt | $(AS) $(ASFLAGS) -o $@
$(DATA_ASM_BUILDDIR)/%.d: $(DATA_ASM_SUBDIR)/%.s
$(SCANINC) -M $@ $(INCLUDE_SCANINC_ARGS) -I "" $<
$(SCANINC) -M $@ -g $(ASSETS_DIR_NAME) $(INCLUDE_SCANINC_ARGS) -I "" $<
ifneq ($(NODEP),1)
-include $(addprefix $(OBJ_DIR)/,$(REGULAR_DATA_ASM_SRCS:.s=.d))

View File

@@ -18,6 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <cctype>
#include <cstdio>
#include <cstdarg>
#include <stdexcept>
@@ -32,7 +33,7 @@
#include "string_parser.h"
#include "io.h"
CFile::CFile(const char * filenameCStr, bool isStdin)
CFile::CFile(const char * filenameCStr, bool isStdin, const char * graphicsRootCStr)
{
if (isStdin)
m_filename = std::string{"<stdin>/"}.append(filenameCStr);
@@ -44,6 +45,9 @@ CFile::CFile(const char * filenameCStr, bool isStdin)
m_pos = 0;
m_lineNum = 1;
m_isStdin = isStdin;
m_graphicsRoot = graphicsRootCStr;
if (m_graphicsRoot.empty()) m_graphicsRoot = "./";
if (m_graphicsRoot[m_graphicsRoot.length() - 1] != '/') m_graphicsRoot.push_back('/');
}
CFile::CFile(CFile&& other) : m_filename(std::move(other.m_filename))
@@ -94,6 +98,7 @@ void CFile::Preproc()
{
TryConvertString();
TryConvertIncbin();
TryConvertIncgfx();
if (m_pos >= m_size)
break;
@@ -237,6 +242,37 @@ bool CFile::CheckIdentifier(const std::string& ident)
return (i == ident.length());
}
std::string CFile::ReadString()
{
if (m_buffer[m_pos] != '"')
RaiseError("expected '\"'");
m_pos++;
long startPos = m_pos;
while (m_buffer[m_pos] != '"')
{
if (m_buffer[m_pos] == 0)
{
if (m_pos >= m_size)
RaiseError("unexpected EOF in string");
else
RaiseError("unexpected null character in string");
}
if (m_buffer[m_pos] == '\r' || m_buffer[m_pos] == '\n')
RaiseError("unexpected end of line character in string");
if (m_buffer[m_pos] == '\\')
RaiseError("unexpected escape in string");
m_pos++;
}
m_pos++;
return std::string(&m_buffer[startPos], m_pos - 1 - startPos);
}
std::unique_ptr<unsigned char[]> CFile::ReadWholeFile(const std::string& path, int& size)
{
FILE* fp = std::fopen(path.c_str(), "rb");
@@ -319,36 +355,7 @@ void CFile::TryConvertIncbin()
while (true)
{
SkipWhitespace();
if (m_buffer[m_pos] != '"')
RaiseError("expected double quote");
m_pos++;
int startPos = m_pos;
while (m_buffer[m_pos] != '"')
{
if (m_buffer[m_pos] == 0)
{
if (m_pos >= m_size)
RaiseError("unexpected EOF in path string");
else
RaiseError("unexpected null character in path string");
}
if (m_buffer[m_pos] == '\r' || m_buffer[m_pos] == '\n')
RaiseError("unexpected end of line character in path string");
if (m_buffer[m_pos] == '\\')
RaiseError("unexpected escape in path string");
m_pos++;
}
std::string path(&m_buffer[startPos], m_pos - startPos);
m_pos++;
auto path = ReadString();
int fileSize;
std::unique_ptr<unsigned char[]> buffer = ReadWholeFile(path, fileSize);
@@ -382,6 +389,108 @@ void CFile::TryConvertIncbin()
std::printf("}");
}
void CFile::TryConvertIncgfx()
{
if (!CheckIdentifier("INCGFX_"))
return;
std::string idents[3] = { "INCGFX_U8", "INCGFX_U16", "INCGFX_U32" };
int incgfxType = -1;
for (int i = 0; i < 3; i++)
{
if (CheckIdentifier(idents[i]))
{
incgfxType = i;
break;
}
}
if (incgfxType == -1)
return;
int size = 1 << incgfxType;
long oldPos = m_pos;
long oldLineNum = m_lineNum;
m_pos += idents[incgfxType].length();
SkipWhitespace();
if (m_buffer[m_pos] != '(')
{
m_pos = oldPos;
m_lineNum = oldLineNum;
return;
}
m_pos++;
SkipWhitespace();
auto source = ReadString();
SkipWhitespace();
if (m_buffer[m_pos] != ',')
RaiseError("expected ','");
m_pos++;
SkipWhitespace();
auto extensions = ReadString();
SkipWhitespace();
std::string arguments;
if (m_buffer[m_pos] == ',')
{
m_pos++;
SkipWhitespace();
arguments = ReadString();
SkipWhitespace();
if (m_buffer[m_pos] != ')')
RaiseError("expected ')'");
m_pos++;
}
else if (m_buffer[m_pos] == ')')
{
m_pos++;
}
else
{
RaiseError("exected ')' or ','");
}
// WARNING: This must stay in-sync with 'tools/scaninc/source_file.cpp'.
std::string arguments_as_path;
for (auto c : arguments)
{
if (std::isalnum(c))
arguments_as_path += c;
else
arguments_as_path += '_';
}
// WARNING: This must stay in-sync with 'tools/scaninc/scaninc.cpp'.
auto converted = m_graphicsRoot + source + arguments_as_path + extensions;
int fileSize;
std::unique_ptr<unsigned char[]> buffer = ReadWholeFile(converted, fileSize);
if ((fileSize % size) != 0)
RaiseError("Size %d doesn't evenly divide file size %d.\n", size, fileSize);
std::printf("{");
int count = fileSize / size;
int offset = 0;
for (int i = 0; i < count; i++)
{
int data = ExtractData(buffer, offset, size);
offset += size;
std::printf("%uu,", data);
}
std::printf("}");
}
// Reports a diagnostic message.
void CFile::ReportDiagnostic(const char* type, const char* format, std::va_list args)
{

View File

@@ -30,7 +30,7 @@
class CFile
{
public:
CFile(const char * filenameCStr, bool isStdin);
CFile(const char * filenameCStr, bool isStdin, const char * graphicsRootCStr);
CFile(CFile&& other);
CFile(const CFile&) = delete;
~CFile();
@@ -43,6 +43,7 @@ private:
long m_lineNum;
std::string m_filename;
bool m_isStdin;
std::string m_graphicsRoot;
bool ConsumeHorizontalWhitespace();
bool ConsumeNewline();
@@ -50,7 +51,9 @@ private:
void TryConvertString();
std::unique_ptr<unsigned char[]> ReadWholeFile(const std::string& path, int& size);
bool CheckIdentifier(const std::string& ident);
std::string ReadString();
void TryConvertIncbin();
void TryConvertIncgfx();
void ReportDiagnostic(const char* type, const char* format, std::va_list args);
void RaiseError(const char* format, ...);
void RaiseWarning(const char* format, ...);

View File

@@ -118,9 +118,9 @@ void PreprocAsmFile(std::string filename, bool isStdin, bool doEnum)
}
}
void PreprocCFile(const char * filename, bool isStdin)
void PreprocCFile(const char * filename, bool isStdin, const char * graphicsRoot)
{
CFile cFile(filename, isStdin);
CFile cFile(filename, isStdin, graphicsRoot);
cFile.Preproc();
}
@@ -147,7 +147,7 @@ const char* GetFileExtension(const char* filename)
static void UsageAndExit(const char *program)
{
std::fprintf(stderr, "Usage: %s [-i] [-e] SRC_FILE CHARMAP_FILE\nwhere -i denotes if input is from stdin\n -e enables enum handling\n", program);
std::fprintf(stderr, "Usage: %s [-i] [-e] [-g PATH] SRC_FILE CHARMAP_FILE\nwhere -i denotes if input is from stdin\n -e enables enum handling\n-g specifies the root for INCGFX\n", program);
std::exit(EXIT_FAILURE);
}
@@ -158,9 +158,10 @@ int main(int argc, char **argv)
const char *charmap = NULL;
bool isStdin = false;
bool doEnum = false;
const char *graphicsRoot = "";
/* preproc [-i] [-e] SRC_FILE CHARMAP_FILE */
while ((opt = getopt(argc, argv, "ie")) != -1)
/* preproc [-i] [-e] [-g PATH] SRC_FILE CHARMAP_FILE */
while ((opt = getopt(argc, argv, "ieg:")) != -1)
{
switch (opt)
{
@@ -170,6 +171,9 @@ int main(int argc, char **argv)
case 'e':
doEnum = true;
break;
case 'g':
graphicsRoot = optarg;
break;
default:
UsageAndExit(argv[0]);
break;
@@ -202,7 +206,7 @@ int main(int argc, char **argv)
{
if (doEnum)
FATAL_ERROR("-e is invalid for C sources\n");
PreprocCFile(source, isStdin);
PreprocCFile(source, isStdin, graphicsRoot);
}
else
{

View File

@@ -18,6 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <cstring>
#include "c_file.h"
CFile::CFile(std::string path)
@@ -86,6 +87,7 @@ void CFile::FindIncbins()
SkipWhitespace();
CheckInclude();
CheckIncbin();
CheckIncgfx();
if (m_pos >= m_size)
break;
@@ -215,7 +217,7 @@ void CFile::CheckIncbin()
&& m_buffer[m_pos+5] == 'N'
&& m_buffer[m_pos+6] == '_'))
{
return;
return;
}
std::string idents[3] = { "INCBIN_U8", "INCBIN_U16", "INCBIN_U32" };
@@ -272,6 +274,86 @@ void CFile::CheckIncbin()
}
void CFile::CheckIncgfx()
{
// Optimization: assume most lines are not incgfxs
if (!(m_buffer[m_pos+0] == 'I'
&& m_buffer[m_pos+1] == 'N'
&& m_buffer[m_pos+2] == 'C'
&& m_buffer[m_pos+3] == 'G'
&& m_buffer[m_pos+4] == 'F'
&& m_buffer[m_pos+5] == 'X'
&& m_buffer[m_pos+6] == '_'))
{
return;
}
std::string idents[3] = { "INCGFX_U8", "INCGFX_U16", "INCGFX_U32" };
int incgfxType = -1;
for (int i = 0; i < 3; i++)
{
if (CheckIdentifier(idents[i]))
{
incgfxType = i;
break;
}
}
if (incgfxType == -1)
return;
long oldPos = m_pos;
long oldLineNum = m_lineNum;
m_pos += idents[incgfxType].length();
SkipWhitespace();
if (m_buffer[m_pos] != '(')
{
m_pos = oldPos;
m_lineNum = oldLineNum;
return;
}
m_pos++;
SkipWhitespace();
std::string path = ReadPath();
SkipWhitespace();
if (m_buffer[m_pos] != ',')
FATAL_INPUT_ERROR("expected ','");
m_pos++;
SkipWhitespace();
std::string extensions = ReadString();
SkipWhitespace();
std::string arguments;
if (m_buffer[m_pos] == ',')
{
m_pos++;
SkipWhitespace();
arguments = ReadString();
SkipWhitespace();
if (m_buffer[m_pos] != ')')
FATAL_INPUT_ERROR("expected ')'");
m_pos++;
}
else if (m_buffer[m_pos] == ')')
{
m_pos++;
}
else
{
FATAL_INPUT_ERROR("expected ')' or ','");
}
Incgfx incgfx = { path, extensions, arguments };
m_incgfxs.emplace(incgfx);
}
std::string CFile::ReadPath()
{
if (m_buffer[m_pos] != '"')
@@ -285,7 +367,7 @@ std::string CFile::ReadPath()
m_pos++;
int startPos = m_pos;
long startPos = m_pos;
while (m_buffer[m_pos] != '"')
{
@@ -310,3 +392,34 @@ std::string CFile::ReadPath()
return std::string(m_buffer + startPos, m_pos - 1 - startPos);
}
std::string CFile::ReadString()
{
if (m_buffer[m_pos] != '"')
FATAL_INPUT_ERROR("expected '\"', got: '%c'", m_buffer[m_pos]);
m_pos++;
long startPos = m_pos;
while (m_buffer[m_pos] != '"')
{
if (m_buffer[m_pos] == 0)
{
if (m_pos >= m_size)
FATAL_INPUT_ERROR("expected EOF in string");
else
FATAL_INPUT_ERROR("unexpected null character in string");
}
if (m_buffer[m_pos] == '\r' || m_buffer[m_pos] == '\n')
FATAL_INPUT_ERROR("unexpected end of line character in string");
if (m_buffer[m_pos] == '\\')
FATAL_INPUT_ERROR("unexpected escape in string");
m_pos++;
}
m_pos++;
return std::string(m_buffer + startPos, m_pos - 1 - startPos);
}

View File

@@ -21,9 +21,10 @@
#ifndef C_FILE_H
#define C_FILE_H
#include <string>
#include <set>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include "scaninc.h"
class CFile
@@ -33,6 +34,7 @@ public:
~CFile();
void FindIncbins();
const std::set<std::string>& GetIncbins() { return m_incbins; }
const std::set<Incgfx>& GetIncgfxs() { return m_incgfxs; }
const std::set<std::string>& GetIncludes() { return m_includes; }
private:
@@ -42,6 +44,7 @@ private:
int m_lineNum;
std::string m_path;
std::set<std::string> m_incbins;
std::set<Incgfx> m_incgfxs;
std::set<std::string> m_includes;
bool ConsumeHorizontalWhitespace();
@@ -51,7 +54,9 @@ private:
bool CheckIdentifier(const std::string& ident);
void CheckInclude();
void CheckIncbin();
void CheckIncgfx();
std::string ReadPath();
std::string ReadString();
};
#endif // C_FILE_H

View File

@@ -18,9 +18,11 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <string>
@@ -41,18 +43,20 @@ bool CanOpenFile(std::string path)
return true;
}
const char *const USAGE = "Usage: scaninc [-I INCLUDE_PATH] [-M DEPENDENCY_OUT_PATH] FILE_PATH\n";
const char *const USAGE = "Usage: scaninc [-I INCLUDE_PATH] [-M DEPENDENCY_OUT_PATH] [-g PATH] FILE_PATH\n";
int main(int argc, char **argv)
{
std::queue<std::string> filesToProcess;
std::set<std::string> dependencies;
std::set<std::string> dependencies_includes;
std::map<std::string, std::pair<std::string, std::string>> dependencies_gfx_rules;
std::vector<std::string> includeDirs;
bool makeformat = false;
std::string make_outfile;
std::string gfx_root;
argc--;
argv++;
@@ -82,6 +86,12 @@ int main(int argc, char **argv)
argv++;
make_outfile = std::string(argv[0]);
}
else if (arg.substr(0, 2) == "-g")
{
argc--;
argv++;
gfx_root = std::string(argv[0]);
}
else
{
FATAL_ERROR(USAGE);
@@ -94,6 +104,11 @@ int main(int argc, char **argv)
FATAL_ERROR(USAGE);
}
size_t ext_pos = make_outfile.find_last_of(".");
auto object_file = make_outfile.substr(0, ext_pos + 1) + "o";
if (gfx_root.empty()) gfx_root = "./";
if (gfx_root[gfx_root.length() - 1] != '/') gfx_root.push_back('/');
std::string initialPath(argv[0]);
filesToProcess.push(initialPath);
@@ -109,6 +124,34 @@ int main(int argc, char **argv)
{
dependencies.insert(incbin);
}
for (auto incgfx : file.GetIncgfxs())
{
// WARNING: This must stay in-sync with 'tools/preproc/c_file.cpp'.
std::string arguments_as_path;
for (auto c : incgfx.arguments)
{
if (std::isalnum(c))
arguments_as_path += c;
else
arguments_as_path += '_';
}
// WARNING: This must stay in-sync with 'tools/preproc/c_file.cpp'.
auto target = gfx_root + incgfx.source + arguments_as_path + incgfx.extensions;
size_t target_slash_pos = target.find_last_of('/');
auto mk_target_basedir = target_slash_pos == std::string::npos
? ""
: "\t@mkdir -p '" + target.substr(0, target_slash_pos) + "'\n";
auto rule = mk_target_basedir + "\t$(GFX) $< $@ " + incgfx.arguments + "\n";
dependencies.insert(target);
// If "foo.4bpp.lz" we want a rule for "foo.4bpp", the ".lz"
// doesn't require any arguments.
size_t dot_pos = incgfx.extensions.find_first_of('.', 1);
auto firstTarget = gfx_root + incgfx.source + arguments_as_path + incgfx.extensions.substr(0, dot_pos);
dependencies_gfx_rules[firstTarget] = std::make_pair(incgfx.source, rule);
}
for (auto include : file.GetIncludes())
{
bool exists = false;
@@ -141,7 +184,7 @@ int main(int argc, char **argv)
includeDirs.pop_back();
}
if(!makeformat)
if (!makeformat)
{
for (const std::string &path : dependencies)
{
@@ -155,8 +198,6 @@ int main(int argc, char **argv)
std::ofstream output(make_outfile);
// Print a make rule for the object file
size_t ext_pos = make_outfile.find_last_of(".");
auto object_file = make_outfile.substr(0, ext_pos + 1) + "o";
output << object_file.c_str() << ":";
for (const std::string &path : dependencies)
{
@@ -180,6 +221,27 @@ int main(int argc, char **argv)
output << path << ":\n";
}
// Graphics rules
// GNU make will issue a warning if there is more than one
// recipe for a target. This would occur whenever a target is
// 'INCGFX'ed multiple times, which is something that happens a
// few times in vanilla. As a workaround, we maintain a variable
// with all the 'INCGFX' targets and only emit the recipe if
// the target is not in that variable. This is safe, because
// targets with the same name necessarily have the same recipe.
output
<< "ifndef _INCGFX\n"
<< "_INCGFX :=\n"
<< "endif\n";
for (auto gfx_rule : dependencies_gfx_rules)
{
output
<< "ifeq (,$(findstring " << gfx_rule.first << ",$(_INCGFX)))\n"
<< "_INCGFX += " << gfx_rule.first << "\n"
<< gfx_rule.first << ": " << gfx_rule.second.first << "\n" << gfx_rule.second.second
<< "endif\n";
}
output.flush();
output.close();
}

View File

@@ -56,4 +56,18 @@ do { \
#define SCANINC_MAX_PATH 255
struct Incgfx
{
std::string source;
std::string extensions;
std::string arguments;
bool operator<(const struct Incgfx &rhs) const
{
return source < rhs.source
|| extensions < rhs.extensions
|| arguments < rhs.arguments;
}
};
#endif // SCANINC_H

View File

@@ -72,6 +72,7 @@ SourceFile::SourceFile(std::string path)
{
AsmFile file(path);
std::set<std::string> incbins;
std::set<Incgfx> incgfxs;
std::set<std::string> includes;
IncDirectiveType incDirectiveType;
@@ -85,7 +86,7 @@ SourceFile::SourceFile(std::string path)
incbins.insert(outputPath);
}
new (&m_source_file.asm_wrapper) SourceFile::InnerUnion::AsmWrapper{incbins, includes};
new (&m_source_file.asm_wrapper) SourceFile::InnerUnion::AsmWrapper{incbins, incgfxs, includes};
}
}
@@ -103,6 +104,7 @@ SourceFile::~SourceFile()
else
{
m_source_file.asm_wrapper.asm_incbins.~set();
m_source_file.asm_wrapper.asm_incgfxs.~set();
m_source_file.asm_wrapper.asm_includes.~set();
}
}
@@ -115,6 +117,14 @@ const std::set<std::string>& SourceFile::GetIncbins()
return m_source_file.asm_wrapper.asm_incbins;
}
const std::set<Incgfx>& SourceFile::GetIncgfxs()
{
if (m_file_type == SourceFileType::Cpp || m_file_type == SourceFileType::Header)
return m_source_file.c_file.GetIncgfxs();
else
return m_source_file.asm_wrapper.asm_incgfxs;
}
const std::set<std::string>& SourceFile::GetIncludes()
{
if (m_file_type == SourceFileType::Cpp || m_file_type == SourceFileType::Header)

View File

@@ -46,8 +46,8 @@ public:
SourceFile(SourceFile&&) = delete;
SourceFile& operator =(SourceFile const&) = delete;
SourceFile& operator =(SourceFile&&) = delete;
bool HasIncbins();
const std::set<std::string>& GetIncbins();
const std::set<Incgfx>& GetIncgfxs();
const std::set<std::string>& GetIncludes();
std::string& GetSrcDir();
SourceFileType FileType();
@@ -57,6 +57,7 @@ private:
CFile c_file;
struct AsmWrapper {
std::set<std::string> asm_incbins;
std::set<Incgfx> asm_incgfxs;
std::set<std::string> asm_includes;
} asm_wrapper;