git.y1.nz

gbdk-2020

GameBoy Development Kit
download: https://git.y1.nz/archives/gbdk.tar.gz
README | Files | Log | Refs | LICENSE

commit ca81d4f362c8ccbc0576fa7d59a347a980157ab1
parent 042489596d9098403f1258faaa3456ab40033017
Author: bbbbbr <reg+github@roughhousing.com>
Date:   Sat, 29 May 2021 13:00:47 -0700

Merge pull request #189 from bbbbbr/lcc_fixes

Lcc fixes and improvements: ihx -> gb, linkerfile, add linkerfile example, -nocrt
Diffstat:
Agbdk-lib/examples/gb/linkerfile/Makefile67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Agbdk-lib/examples/gb/linkerfile/Readme.md18++++++++++++++++++
Agbdk-lib/examples/gb/linkerfile/src/main.c14++++++++++++++
Mgbdk-lib/examples/gb/template_minimal/Makefile2+-
Mgbdk-lib/examples/gb/template_subfolders/Makefile2+-
Mgbdk-support/lcc/gb.c17++++++++++-------
Mgbdk-support/lcc/lcc.c165++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
7 files changed, 215 insertions(+), 70 deletions(-)

diff --git a/gbdk-lib/examples/gb/linkerfile/Makefile b/gbdk-lib/examples/gb/linkerfile/Makefile @@ -0,0 +1,67 @@ +# +# A Makefile that compiles all .c and .s files in "src" and "res" +# subdirectories and places the output in a "obj" subdirectory +# + +# If you move this project you can change the directory +# to match your GBDK root directory (ex: GBDK_HOME = "C:/GBDK/" +GBDK_HOME = ../../../ + +LCC = $(GBDK_HOME)bin/lcc + +# You can set flags for LCC here +# For example, you can uncomment the line below to turn on debug output +# LCCFLAGS = -debug +# LCCFLAGS = -v + +# You can set the name of the .gb ROM file here +PROJECTNAME = Example + +SRCDIR = src +OBJDIR = obj +RESDIR = res +BINS = $(OBJDIR)/$(PROJECTNAME).gb +CSOURCES = $(foreach dir,$(SRCDIR),$(notdir $(wildcard $(dir)/*.c))) $(foreach dir,$(RESDIR),$(notdir $(wildcard $(dir)/*.c))) +ASMSOURCES = $(foreach dir,$(SRCDIR),$(notdir $(wildcard $(dir)/*.s))) +OBJS = $(CSOURCES:%.c=$(OBJDIR)/%.o) $(ASMSOURCES:%.s=$(OBJDIR)/%.o) + +all: prepare $(BINS) + +make.bat: Makefile + @echo "REM Automatically generated from Makefile" > make.bat + @make -sn | sed y/\\//\\\\/ | grep -v make >> make.bat + +# Compile .c files in "src/" to .o object files +$(OBJDIR)/%.o: $(SRCDIR)/%.c + $(LCC) $(LCCFLAGS) -c -o $@ $< + +# Compile .c files in "res/" to .o object files +$(OBJDIR)/%.o: $(RESDIR)/%.c + $(LCC) $(LCCFLAGS) -c -o $@ $< + +# Compile .s assembly files in "src/" to .o object files +$(OBJDIR)/%.o: $(SRCDIR)/%.s + $(LCC) $(LCCFLAGS) -c -o $@ $< + +# If needed, compile .c files i n"src/" to .s assembly files +# (not required if .c is compiled directly to .o) +$(OBJDIR)/%.s: $(SRCDIR)/%.c + $(LCC) $(LCCFLAGS) -S -o $@ $< + + +$(OBJDIR)/linkfile.lk: $(OBJS) + rm -f $(OBJDIR)/linkfile.lk + $(foreach O,$(OBJS),echo $O >>$@;) + +# Link the compiled object files (via linkerfile) into a .gb ROM file +$(BINS): $(OBJDIR)/linkfile.lk + $(LCC) $(LCCFLAGS) -o $(BINS) -Wl-f$< + +prepare: + mkdir -p $(OBJDIR) + mkdir -p $(RESDIR) + +clean: +# rm -f *.gb *.ihx *.cdb *.adb *.noi *.map + rm -f $(OBJDIR)/*.* + diff --git a/gbdk-lib/examples/gb/linkerfile/Readme.md b/gbdk-lib/examples/gb/linkerfile/Readme.md @@ -0,0 +1,18 @@ + +# Example of how to use a linkerfile + +A linkerfile allows storing all the object files to be linked in a +file which is passed to the linker instead of a list of filenames on +the command line. This may be useful if your project has filenames +that use up more length than will fit on the command line for Windows +(8191 chars max). + +The typical extension for the linkerfile is ".lk". + +It is passed to sdldgb through lcc using `-Wl-f<pathtolinkerfile>` +If calling sdldgb directly, use `-f<pathtolinkerfile>` + +The Makefile is configured to store all the compiled ".o" object files +into `obj/linkerfile.lk`. + + diff --git a/gbdk-lib/examples/gb/linkerfile/src/main.c b/gbdk-lib/examples/gb/linkerfile/src/main.c @@ -0,0 +1,14 @@ +#include <gb/gb.h> + + +void main(void) +{ + // Loop forever + while(1) { + + // Game main loop processing goes here + + // Done processing, yield CPU and wait for start of next frame + wait_vbl_done(); + } +} diff --git a/gbdk-lib/examples/gb/template_minimal/Makefile b/gbdk-lib/examples/gb/template_minimal/Makefile @@ -4,7 +4,7 @@ # If you move this project you can change the directory # to match your GBDK root directory (ex: GBDK_HOME = "C:/GBDK/" -GBDK_HOME = "../../../" +GBDK_HOME = ../../../ LCC = $(GBDK_HOME)bin/lcc diff --git a/gbdk-lib/examples/gb/template_subfolders/Makefile b/gbdk-lib/examples/gb/template_subfolders/Makefile @@ -5,7 +5,7 @@ # If you move this project you can change the directory # to match your GBDK root directory (ex: GBDK_HOME = "C:/GBDK/" -GBDK_HOME = "../../../" +GBDK_HOME = ../../../ LCC = $(GBDK_HOME)bin/lcc diff --git a/gbdk-support/lcc/gb.c b/gbdk-support/lcc/gb.c @@ -68,7 +68,8 @@ static struct { { "bindir", GBDKBINDIR }, #endif { "ihxcheck", "%bindir%ihxcheck" }, - { "mkbin", "%sdccdir%makebin" } + { "mkbin", "%sdccdir%makebin" }, + { "crt0dir", "%libdir%%plat%/crt0.o"} }; #define NUM_TOKENS (sizeof(_tokens)/sizeof(_tokens[0])) @@ -111,7 +112,7 @@ static CLASS classes[] = { "%as% %asdefault% $1 $3 $2", "%bankpack% $1 $2", "%ld% -n -i $1 -k %libdir%%port%/ -l %port%.lib " - "-k %libdir%%plat%/ -l %plat%.lib $3 $2", + "-k %libdir%%plat%/ -l %plat%.lib $3 %crt0dir% $2", "%ihxcheck% $2 $1", "%mkbin% -Z $1 $2 $3" }, @@ -124,7 +125,7 @@ static CLASS classes[] = { "%as% %asdefault% $1 $3 $2", "%bankpack% $1 $2", "%ld% -n -- -i $1 -b_CODE=0x8100 -k%libdir%%port%/ -l%port%.lib " - "-k%libdir%%plat%/ -l%plat%.lib $3 $2", + "-k%libdir%%plat%/ -l%plat%.lib $3 %crt0dir% $2", "%ihxcheck% $2 $1", "%mkbin% -Z $1 $2 $3" }, @@ -137,7 +138,7 @@ static CLASS classes[] = { "%as% %asdefault% $1 $3 $2", "%bankpack% $1 $2", "%ld% -n -- -i $1 -b_DATA=0x8000 -b_CODE=0x200 -k%libdir%%port%/ -l%port%.lib " - "-k%libdir%%plat%/ -l%plat%.lib $3 $2", + "-k%libdir%%plat%/ -l%plat%.lib $3 %crt0dir% $2", "%ihxcheck% $2 $1", "%mkbin% -Z $1 $2 $3" } @@ -240,7 +241,7 @@ static void buildArgs(char **args, const char *template) *last = NULL; } -char *suffixes[] = { ".c", ".i", ".asm;.s", ".o;.obj", ".ihx;.gb", 0 }; +char *suffixes[] = { ".c", ".i", ".asm;.s", ".o;.obj", ".ihx", ".gb", 0 }; char inputs[256] = ""; char *cpp[256]; @@ -251,7 +252,6 @@ char *ihxcheck[256]; char *ld[256]; char *bankpack[256]; char *mkbin[256]; -char *crt0[256]; const char *starts_with(const char *s1, const char *s2) { @@ -286,6 +286,10 @@ int option(char *arg) { // When composing the compile stage, swap in of -S instead of default -c setTokenVal("comflag", "-S"); } + else if ((tail = starts_with(arg, "-nocrt"))) { + // When composing link stage, clear out crt0dir path + setTokenVal("crt0dir", ""); + } else if ((tail = starts_with(arg, "-m"))) { /* Split it up into a asm/port pair */ char *slash = strchr(tail, '/'); @@ -331,7 +335,6 @@ void finalise(void) buildArgs(ld, _class->ld); buildArgs(ihxcheck, _class->ihxcheck); buildArgs(mkbin, _class->mkbin); - buildArgs(crt0, "%libdir%%plat%/crt0.o"); } void set_gbdk_dir(char* argv_0) diff --git a/gbdk-support/lcc/lcc.c b/gbdk-support/lcc/lcc.c @@ -60,7 +60,7 @@ static void Fixllist(); static void list_rewrite_exts(List, char *, char *); static void list_duplicate_to_new_exts(List, char *, char *); -extern char *cpp[], *include[], *com[], *as[], *bankpack[], *ld[], *ihxcheck[], *mkbin[], inputs[], *suffixes[], *crt0[]; +extern char *cpp[], *include[], *com[], *as[], *bankpack[], *ld[], *ihxcheck[], *mkbin[], inputs[], *suffixes[]; extern int option(char *); extern void set_gbdk_dir(char*); @@ -71,13 +71,12 @@ static int Eflag; /* -E specified */ static int Sflag; /* -S specified */ static int cflag; /* -c specified */ static int Kflag; /* -K specified */ -static int fflag; /* -Wl-f specified */ static int autobankflag; /* -K specified */ static int verbose; /* incremented for each -v */ static List bankpack_flags; /* bankpack flags */ static List ihxchecklist; /* ihxcheck flags */ static List mkbinlist; /* loader files, flags */ -static List llist[3]; /* [1] = loader files, [0] = flags */ +static List llist[2]; /* [1] = loader files, [0] = flags */ static List alist; /* assembler flags */ List clist; /* compiler flags */ static List plist; /* preprocessor flags */ @@ -90,6 +89,8 @@ char *tempdir = TEMPDIR; /* directory for temporary files */ char *progname; static List lccinputs; /* list of input directories */ char bankpack_newext[1024] = {'\0'}; +static int ihx_inputs = 0; // Number of ihx files present in input list +static char ihxFile[256] = ""; int main(int argc, char *argv[]) { @@ -150,14 +151,33 @@ int main(int argc, char *argv[]) { opt(argv[i]); continue; } - else if (*argv[i] != '-' && suffix(argv[i], suffixes, 3) >= 0) - nf++; + else if (*argv[i] != '-') { + // Count number of (.ihx) files + if (suffix(argv[i], suffixes, 5) == 4) + ihx_inputs++; + // Count number of (.c, .i, .asm, .s) files + else if (suffix(argv[i], suffixes, 3) >= 0) + nf++; + } argv[j++] = argv[i]; } + + // Ignore -o output request if: + // * compile only (-c) *OR* compile to ASM (-S) is specified + // * and there are 2 or more source files (.c, .i, .asm, .s) in the input list (what "nf" seems to count) + // Instead, it will generate output matching each input filename if ((cflag || Sflag) && outfile && nf != 1) { fprintf(stderr, "%s: -o %s ignored\n", progname, outfile); outfile = 0; } + + // When .ihx is an input only ihxcheck and makebin will be called. + // Warn that all source files won't be processed + if ((ihx_inputs > 0) && (nf > 0)) { + fprintf(stderr, "%s: Warning: .ihx file present as input, all other input files ignored\n", progname); + } + + // Add includes argv[j] = 0; finalise(); for (i = 0; include[i]; i++) @@ -171,69 +191,89 @@ int main(int argc, char *argv[]) { } ilist = 0; for (i = 1; argv[i]; i++) + // Process arguments if (*argv[i] == '-') opt(argv[i]); else { + // Process filenames char *name = exists(argv[i]); if (name) { if (strcmp(name, argv[i]) != 0 || nf > 1 && suffix(name, suffixes, 3) >= 0) fprintf(stderr, "%s:\n", name); + // Send input filename argument to "filename processor" + // which will add them to llist[n] in some form most of the time filename(name, 0); } else error("can't find `%s'", argv[i]); } - // Perform Link stage unless some conditions prevent it - if (errcnt == 0 && !Eflag && !cflag && !Sflag && llist[1]) { - if(!outfile) - outfile = concat("a", first(suffixes[4])); - //file.gb to file.ihx (don't use tmpfile because maps and other stuffs are created there) + // Perform Link / ihxcheck / makebin stages (unless some conditions prevent it) + if (errcnt == 0 && !Eflag && !cflag && !Sflag && + (llist[1] || (ihxFile && ihx_inputs))) { - // Check to see if output is a .ihx file - char * ihx_suffix[1] = {".ihx"}; - int target_is_ihx = (suffix(outfile, ihx_suffix, 1) == 0); + int target_is_ihx = 0; - char ihxFile[255]; - int lastP = strrchr(outfile, '.') - outfile; - strncpy(ihxFile, outfile, lastP); - ihxFile[lastP] = '\0'; - strcat(ihxFile, ".ihx"); + // If an .ihx file is persent as input, only convert that + // and skip link related stages + if (ihx_inputs > 0) { - // Only remove .ihx from the delete-list if it's not the final target - if (!target_is_ihx) - append(ihxFile, rmlist); + // Only one .ihx can be used for input, warn that others will be ignored + if (ihx_inputs > 1) + fprintf(stderr, "%s: Warning: Multiple (%d) .ihx files present as input, only one (%s) will be used\n", progname, ihx_inputs, ihxFile); - // if auto bank assignment is enabled, modify obj files before linking - if (autobankflag) { - compose(bankpack, bankpack_flags, llist[1], 0); + // if outfile is not specified, set it to "a.gb" + if(!outfile) + outfile = concat("a", suffixes[5]); + } + else { + // if outfile is not specified, set it to "a.ihx" + if(!outfile) + outfile = concat("a", suffixes[4]); - if (callsys(av)) { - errcnt++; - } else { - // If bankpack has -ext= flag set to write obj files - // out to a new extension then rewrite the - // linker list (llist[1]) and delete list (rmlist). - // The delete list likely only has temp obj files such - // as from a single-pass build: lcc -o out.gb in1.c in2.c - if (bankpack_newext[0]) { - char * obj_suffix = ".o"; - list_rewrite_exts(llist[1], obj_suffix, bankpack_newext); - list_duplicate_to_new_exts(rmlist, obj_suffix, bankpack_newext); + //file.gb to file.ihx (don't use tmpfile because maps and other stuffs are created there) + // Check to see if output is a .ihx file + target_is_ihx = (suffix(outfile, suffixes, 5) == 4); + + // Build ihx file name from output name + int lastP = strrchr(outfile, '.') - outfile; + strncpy(ihxFile, outfile, lastP); + ihxFile[lastP] = '\0'; + strcat(ihxFile, ".ihx"); + + // Only remove .ihx from the delete-list if it's not the final target + if (!target_is_ihx) + append(ihxFile, rmlist); + + // if auto bank assignment is enabled, modify obj files before linking + if (autobankflag) { + compose(bankpack, bankpack_flags, llist[1], 0); + + if (callsys(av)) { + errcnt++; + } else { + // If bankpack has -ext= flag set to write obj files + // out to a new extension then rewrite the + // linker list (llist[1]) and delete list (rmlist). + // The delete list likely only has temp obj files such + // as from a single-pass build: lcc -o out.gb in1.c in2.c + if (bankpack_newext[0]) { + char * obj_suffix = ".o"; + list_rewrite_exts(llist[1], obj_suffix, bankpack_newext); + list_duplicate_to_new_exts(rmlist, obj_suffix, bankpack_newext); + } } } - } + + // Call linker (add output ihxfile in compose $3) + Fixllist(); // (fixlist adds required default linker vars if not added by user) + compose(ld, llist[0], llist[1], append(ihxFile, 0)); - // Call linker - // (fixlist adds required default linker vars if not added by user) - Fixllist(); - llist[2] = append(ihxFile, 0); - if (!fflag) llist[2] = append(*crt0, llist[2]); - compose(ld, llist[0], llist[1], llist[2]); - if (callsys(av)) - errcnt++; + if (callsys(av)) + errcnt++; + } // end: non-ihx input file handling // ihxcheck (test for multiple writes to the same ROM address) if (!Kflag) { @@ -633,7 +673,7 @@ static int filename(char *name, char *base) { if (base == 0) base = basepath(name); - switch (suffix(name, suffixes, 4)) { + switch (suffix(name, suffixes, 5)) { case 0: /* C source files */ { char *ofile; @@ -683,6 +723,10 @@ static int filename(char *name, char *base) { if (!find(name, llist[1])) llist[1] = append(name, llist[1]); break; + case 4: // .ihx files + // Append .ihx files (there can be only one as input) + strncpy(ihxFile, name, sizeof(ihxFile) - 1); + break; default: if (Eflag) { compose(cpp, plist, append(name, 0), 0); @@ -732,6 +776,7 @@ static void help(void) { "-lx search library `x'\n", "-N do not search the standard directories for #include files\n", "-n emit code to check for dereferencing zero pointers\n", +"-nocrt do not auto-include the gbdk crt0.o runtime in linker list\n", "-O is ignored\n", "-o file leave the output in `file'\n", "-P print ANSI-style declarations for globals\n", @@ -845,24 +890,17 @@ static void opt(char *arg) { if(arg[4] == 'y' && (arg[5] == 't' || arg[5] == 'o' || arg[5] == 'a' || arg[5] == 'p') && (arg[6] != '\0' && arg[6] != ' ')) goto makebinoption; //automatically pass -yo -ya -yt -yp options to makebin (backwards compatibility) { - if (arg[4] == 'f') { - char *tmp = malloc(256); - sprintf(tmp, "%c%c", arg[3], arg[4]); // we pass the list as the very last parameter - llist[1] = append(tmp, llist[1]); - if(arg[5]){ - char *tmp2 = malloc(256); - sprintf(tmp2, "%s", &arg[5]); - llist[1] = append(tmp2, llist[1]); - } - fflag++; + // If using linker file for sdldgb (-f file[.lk]). + // Starting at arg[5] should be name of the linkerfile + if ((arg[4] == 'f') && (arg[5])) { + llist[1] = append("-f", llist[1]); // Add -f to file link list + llist[1] = append(&arg[5], llist[1]); // Then add linkerfile as the very next parameter } else { char *tmp = malloc(256); sprintf(tmp, "%c%c", arg[3], arg[4]); //sdldgb requires spaces between -k and the path llist[0] = append(tmp, llist[0]); //splitting the args into 2 works on Win and Linux - if(arg[5]){ - char *tmp2 = malloc(256); - sprintf(tmp2, "%s", &arg[5]); - llist[0] = append(tmp2, llist[0]); + if (arg[5]) { + llist[0] = append(&arg[5], llist[0]); // Add filename separately if present } } } @@ -933,6 +971,11 @@ static void opt(char *arg) { autobankflag++; return; } + case 'n': + if (strcmp(arg, "-nocrt") == 0) { + option(arg); // Clear crt0 entry in linker compose string + return; + } case 'B': /* -Bdir -Bstatic -Bdynamic */ #ifdef sparc if (strcmp(arg, "-Bstatic") == 0 || strcmp(arg, "-Bdynamic") == 0) @@ -945,7 +988,7 @@ static void opt(char *arg) { error("-B overwrites earlier option", 0); path = arg + 2; if (strstr(com[1], "win32") != NULL) - com[0] = concat(replace(path, '/', '\\'), concat("rcc", first(suffixes[4]))); + com[0] = concat(replace(path, '/', '\\'), concat("rcc", suffixes[4])); else com[0] = concat(path, "rcc"); if (path[0] == 0)

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.