/*============================================================================== * main.c: Entry point of the program. * * $Id: main.c,v 1.4 2004/07/15 13:09:26 Olivier Exp $ * * - GhostBuster for TI89 Titanium - * Copyright (C) 2004 Olivier Armand * and Kevin Kofler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307, USA. * * In addition, as a special exception, Olivier Armand and Kevin Kofler give * permission to link the code of this program with the ttunpack decompression * library by the TI-Chess Team, and distribute linked combinations including * the two. You must obey the GNU General Public License in all respects for * all of the code used other than the ttunpack decompression library. If you * modify this program, you may extend this exception to your version of the * program, but you are not obligated to do so. If you do not wish to do so, * delete this exception statement from your version. * *==============================================================================*/ #include "common.h" #include "files.h" #include "patch.h" BOOL OptRam = FALSE; /* TRUE if "ram" is in the command-line options */ BOOL OptAll = FALSE; /* TRUE if "all" is in the command-line options */ BOOL OptReplace = FALSE; /* TRUE if "replace" is in the command-line options */ char *Outfile; /* Pointer to the outfile name */ HANDLE NextFileHandle; __attribute__ ((noreturn)) static inline void PrintUsage(void) { fatal ("Usage: ghostb(\"in\",\"out\"[,\"ram|all\"])"); } /* Get the program command-line options. */ static inline __attribute__((always_inline)) void GetOptions(void) { ESI argptr = top_estack; unsigned short argn; char *infile, *outfile, *options; char charbuf[50]; /* For error messages, ROM Calls, ... */ BOOL firstloop; argn = RemainingArgCnt(argptr); if ((argn != 2 && argn != 3) || GetArgType(argptr) != STR_TAG) PrintUsage(); infile = (char*)GetStrnArg(argptr); if (GetArgType(argptr) != STR_TAG) PrintUsage(); outfile = (char*)GetStrnArg(argptr); OptRam = OptAll = FALSE; if (argn == 3) { if (GetArgType(argptr) != STR_TAG) PrintUsage(); options = strtok((char*)GetStrnArg(argptr), "|"); /* As long as there are options to read. */ for (firstloop = TRUE; options; options = strtok(NULL, "|")) { if (!firstloop) { /* Clean the '\0' written by strtok(). */ char *tempptr = options; /* More than one '|' may have been eaten by strtok(). */ while (*tempptr) tempptr--; *tempptr = '|'; } if (!strcmp(options, "ram")) OptRam = TRUE; else if (!strcmp (options, "all")) OptAll = TRUE; else PrintUsage(); } /* for ... */ } /* if (argn == 3) */ if (!OptAll) { SYM_ENTRY *symptr; if ((TokenizeName(infile, charbuf))) PrintUsage(); if (!(symptr = SymFindPtr(charbuf + MAX_SYM_LEN, 0))) { sprintf(charbuf, "\'%s\' not found...", infile); fatal(charbuf); } NextFileHandle = symptr->handle; Outfile = outfile; if ((OptReplace = (outfile[0] == '\0'))) Outfile = infile; else { if ((TokenizeName(outfile, charbuf))) fatal("Invalid outfile name."); else if (SymFindPtr(charbuf + MAX_SYM_LEN, 0)) { sprintf(charbuf, "\'%s\' already exists...", outfile); fatal(charbuf); } } } /* if (!OptAll) */ else Outfile = infile; } void _main(void) { PRGM_T prgm_type; unsigned long prgm_len; unsigned short patches_nb; GetOptions(); PatchLoopInit(); for (patches_nb = 0; (prgm_type = GetNextFile()) != PRGM_NULL;) { unsigned char *prgm = PatchAlloc(prgm_type, &prgm_len); patches_nb += ApplyPatches(prgm, prgm_len); FinalizePatch(patches_nb ? TRUE : FALSE); } if (!OptAll && !patches_nb) fatal("The program doesn't need to be patched."); else { char charbuf[sizeof("Done! Patches applied: 9999")]; sprintf(charbuf, "Done! Patches applied: %i", patches_nb); xST_helpMsg(charbuf); } }