Make all file names lowercase

This fixes a zip/platform artifact.

Signed-off-by: Vegard Nossum <vegard.nossum@gmail.com>
This commit is contained in:
Vegard Nossum
2009-06-11 06:25:27 +02:00
parent e895832b2b
commit b53e170781
103 changed files with 0 additions and 0 deletions

570
src/link/assign.c Normal file
View File

@@ -0,0 +1,570 @@
#include <stdio.h>
#include <stdlib.h>
#include "mylink.h"
#include "main.h"
#include "symbol.h"
#include "assign.h"
struct sFreeArea
{
SLONG nOrg;
SLONG nSize;
struct sFreeArea *pPrev, *pNext;
};
struct sFreeArea *BankFree[MAXBANKS];
SLONG MaxAvail[MAXBANKS];
SLONG MaxBankUsed;
#define DOMAXBANK(x) {if( (x)>MaxBankUsed ) MaxBankUsed=(x);}
SLONG area_Avail( SLONG bank )
{
SLONG r;
struct sFreeArea *pArea;
r=0;
pArea=BankFree[bank];
while( pArea )
{
r+=pArea->nSize;
pArea=pArea->pNext;
}
return( r );
}
SLONG area_AllocAbs( struct sFreeArea **ppArea, SLONG org, SLONG size )
{
struct sFreeArea *pArea;
pArea=*ppArea;
while( pArea )
{
if( org>=pArea->nOrg && (org+size-1)<=(pArea->nOrg+pArea->nSize-1) )
{
if( org==pArea->nOrg )
{
pArea->nOrg+=size;
pArea->nSize-=size;
return( org );
}
else
{
if( (org+size-1)==(pArea->nOrg+pArea->nSize-1) )
{
pArea->nSize-=size;
return( org );
}
else
{
struct sFreeArea *pNewArea;
if( (pNewArea=(struct sFreeArea *)malloc(sizeof(struct sFreeArea)))!=NULL )
{
*pNewArea=*pArea;
pNewArea->pPrev=pArea;
pArea->pNext=pNewArea;
pArea->nSize=org-pArea->nOrg;
pNewArea->nOrg=org+size;
pNewArea->nSize-=size+pArea->nSize;
return( org );
}
else
fatalerror( "Out of memory!" );
}
}
}
ppArea=&(pArea->pNext);
pArea=*ppArea;
}
return( -1 );
}
SLONG area_AllocAbsCODEAnyBank( SLONG org, SLONG size )
{
SLONG i;
for( i=1; i<=255; i+=1 )
{
if( area_AllocAbs( &BankFree[i], org, size )==org )
return( i );
}
return( -1 );
}
SLONG area_Alloc( struct sFreeArea **ppArea, SLONG size )
{
struct sFreeArea *pArea;
pArea=*ppArea;
while( pArea )
{
if( size<=pArea->nSize )
{
SLONG r;
r=pArea->nOrg;
pArea->nOrg+=size;
pArea->nSize-=size;
return( r );
}
ppArea=&(pArea->pNext);
pArea=*ppArea;
}
return( -1 );
}
SLONG area_AllocCODEAnyBank( SLONG size )
{
SLONG i, org;
for( i=1; i<=255; i+=1 )
{
if( (org=area_Alloc(&BankFree[i],size))!=-1 )
return( (i<<16)|org );
}
return( -1 );
}
struct sSection *FindLargestCode( void )
{
struct sSection *pSection, *r=NULL;
SLONG nLargest=0;
pSection=pSections;
while( pSection )
{
if( pSection->oAssigned==0 && pSection->Type==SECT_CODE )
{
if( pSection->nByteSize > nLargest )
{
nLargest=pSection->nByteSize;
r=pSection;
}
}
pSection=pSection->pNext;
}
return( r );
}
void AssignCodeSections( void )
{
struct sSection *pSection;
while( pSection=FindLargestCode() )
{
SLONG org;
if( (org=area_AllocCODEAnyBank( pSection->nByteSize ))!=-1 )
{
pSection->nOrg=org&0xFFFF;
pSection->nBank=org>>16;
pSection->oAssigned=1;
DOMAXBANK(pSection->nBank);
}
else
fatalerror( "Unable to place CODE section anywhere" );
}
}
void GBROM_AssignSections( void )
{
SLONG i;
struct sSection *pSection;
MaxBankUsed=0;
/*
* Initialize the memory areas
*
*/
for( i=0; i<MAXBANKS; i+=1 )
{
if( BankFree[i]=(struct sFreeArea *)malloc(sizeof(struct sFreeArea)) )
{
if( i==0 )
{
BankFree[i]->nOrg=0x0000;
if( options&OPT_SMALL )
{
BankFree[i]->nSize=0x8000;
MaxAvail[i]=0x8000;
}
else
{
BankFree[i]->nSize=0x4000;
MaxAvail[i]=0x4000;
}
}
else if( i>=1 && i<=255 )
{
BankFree[i]->nOrg=0x4000;
/*
* Now, this shouldn't really be necessary... but for good
* measure we'll do it anyway
*
*/
if( options&OPT_SMALL )
{
BankFree[i]->nSize=0;
MaxAvail[i]=0;
}
else
{
BankFree[i]->nSize=0x4000;
MaxAvail[i]=0x4000;
}
}
else if( i==BANK_BSS )
{
BankFree[i]->nOrg =0xC000;
BankFree[i]->nSize=0x2000;
MaxAvail[i]=0x2000;
}
else if( i==BANK_VRAM )
{
BankFree[i]->nOrg =0x8000;
BankFree[i]->nSize=0x2000;
MaxAvail[i]=0x2000;
}
else if( i==BANK_HRAM )
{
BankFree[i]->nOrg =0xFF80;
BankFree[i]->nSize=0x007F;
MaxAvail[i]=0x007F;
}
BankFree[i]->pPrev=NULL;
BankFree[i]->pNext=NULL;
}
else
fatalerror( "Out of memory!" );
}
/*
* First, let's assign all the fixed sections...
* And all because of that Jens Restemeier character ;)
*
*/
pSection=pSections;
while( pSection )
{
if( (pSection->nOrg!=-1 || pSection->nBank!=-1) && pSection->oAssigned==0 )
{
/* User wants to have a say... */
switch( pSection->Type )
{
case SECT_BSS:
if( area_AllocAbs(&BankFree[BANK_BSS],pSection->nOrg,pSection->nByteSize)!=pSection->nOrg )
{
sprintf( temptext, "Unable to load fixed BSS section at $%X", pSection->nOrg );
fatalerror( temptext );
}
pSection->oAssigned=1;
pSection->nBank=BANK_BSS;
break;
case SECT_HRAM:
if( area_AllocAbs(&BankFree[BANK_HRAM],pSection->nOrg,pSection->nByteSize)!=pSection->nOrg )
{
sprintf( temptext, "Unable to load fixed HRAM section at $%X", pSection->nOrg );
fatalerror( temptext );
}
pSection->oAssigned=1;
pSection->nBank=BANK_HRAM;
break;
case SECT_VRAM:
if( area_AllocAbs(&BankFree[BANK_VRAM],pSection->nOrg,pSection->nByteSize)!=pSection->nOrg )
{
sprintf( temptext, "Unable to load fixed VRAM section at $%X", pSection->nOrg );
fatalerror( temptext );
}
pSection->oAssigned=1;
pSection->nBank=BANK_VRAM;
break;
case SECT_HOME:
if( area_AllocAbs(&BankFree[BANK_HOME],pSection->nOrg,pSection->nByteSize)!=pSection->nOrg )
{
sprintf( temptext, "Unable to load fixed HOME section at $%X", pSection->nOrg );
fatalerror( temptext );
}
pSection->oAssigned=1;
pSection->nBank=BANK_HOME;
break;
case SECT_CODE:
if( pSection->nBank==-1 )
{
/*
* User doesn't care which bank, so he must want to
* decide which position within that bank.
* We'll do that at a later stage when the really
* hardcoded things are allocated
*
*/
}
else
{
/*
* User wants to decide which bank we use
* Does he care about the position as well?
*
*/
if( pSection->nOrg==-1 )
{
/*
* Nope, any position will do
* Again, we'll do that later
*
*/
}
else
{
/*
* How hardcore can you possibly get? Why does
* he even USE this package? Yeah let's just
* direct address everything, shall we?
* Oh well, the customer is always right
*
*/
if( pSection->nBank>=1 && pSection->nBank<=255 )
{
if( area_AllocAbs(&BankFree[pSection->nBank],pSection->nOrg,pSection->nByteSize)!=pSection->nOrg )
{
sprintf( temptext, "Unable to load fixed CODE/DATA section at $%X in bank $%02X", pSection->nOrg, pSection->nBank );
fatalerror( temptext );
}
DOMAXBANK(pSection->nBank);
pSection->oAssigned=1;
}
else
{
sprintf( temptext, "Unable to load fixed CODE/DATA section at $%X in bank $%02X", pSection->nOrg, pSection->nBank );
fatalerror( temptext );
}
}
}
break;
}
}
pSection=pSection->pNext;
}
/*
* Next, let's assign all the bankfixed ONLY CODE sections...
*
*/
pSection=pSections;
while( pSection )
{
if( pSection->oAssigned==0
&& pSection->Type==SECT_CODE
&& pSection->nOrg==-1
&& pSection->nBank!=-1 )
{
/* User wants to have a say... and he's pissed */
if( pSection->nBank>=1 && pSection->nBank<=255 )
{
if( (pSection->nOrg=area_Alloc(&BankFree[pSection->nBank],pSection->nByteSize))==-1 )
{
sprintf( temptext, "Unable to load fixed CODE/DATA section into bank $%02X", pSection->nBank );
fatalerror( temptext );
}
pSection->oAssigned=1;
DOMAXBANK(pSection->nBank);
}
else
{
sprintf( temptext, "Unable to load fixed CODE/DATA section into bank $%02X", pSection->nBank );
fatalerror( temptext );
}
}
pSection=pSection->pNext;
}
/*
* Now, let's assign all the floating bank but fixed CODE sections...
*
*/
pSection=pSections;
while( pSection )
{
if( pSection->oAssigned==0
&& pSection->Type==SECT_CODE
&& pSection->nOrg!=-1
&& pSection->nBank==-1 )
{
/* User wants to have a say... and he's back with a vengeance */
if( (pSection->nBank=area_AllocAbsCODEAnyBank(pSection->nOrg,pSection->nByteSize))==-1 )
{
sprintf( temptext, "Unable to load fixed CODE/DATA section at $%X into any bank", pSection->nOrg );
fatalerror( temptext );
}
pSection->oAssigned=1;
DOMAXBANK(pSection->nBank);
}
pSection=pSection->pNext;
}
/*
* OK, all that nasty stuff is done so let's assign all the other
* sections
*
*/
pSection=pSections;
while( pSection )
{
if( pSection->oAssigned==0 )
{
switch( pSection->Type )
{
case SECT_BSS:
if( (pSection->nOrg=area_Alloc(&BankFree[BANK_BSS],pSection->nByteSize))==-1 )
{
fatalerror( "BSS section too large\n" );
}
pSection->nBank=BANK_BSS;
pSection->oAssigned=1;
break;
case SECT_HRAM:
if( (pSection->nOrg=area_Alloc(&BankFree[BANK_HRAM],pSection->nByteSize))==-1 )
{
fatalerror( "HRAM section too large" );
}
pSection->nBank=BANK_HRAM;
pSection->oAssigned=1;
break;
case SECT_VRAM:
if( (pSection->nOrg=area_Alloc(&BankFree[BANK_VRAM],pSection->nByteSize))==-1 )
{
fatalerror( "VRAM section too large" );
}
pSection->nBank=BANK_VRAM;
pSection->oAssigned=1;
break;
case SECT_HOME:
if( (pSection->nOrg=area_Alloc(&BankFree[BANK_HOME],pSection->nByteSize))==-1 )
{
fatalerror( "HOME section too large" );
}
pSection->nBank=BANK_HOME;
pSection->oAssigned=1;
break;
case SECT_CODE:
break;
default:
fatalerror( "(INTERNAL) Unknown section type!" );
break;
}
}
pSection=pSection->pNext;
}
AssignCodeSections();
}
void PSION2_AssignSections( void )
{
struct sSection *pSection;
if( BankFree[0]=(struct sFreeArea *)malloc(sizeof(struct sFreeArea)) )
{
BankFree[0]->nOrg=0x0000;
BankFree[0]->nSize=0x10000;
MaxAvail[0]=0x10000;
BankFree[0]->pPrev=NULL;
BankFree[0]->pNext=NULL;
pSection=pSections;
while( pSection )
{
if( pSection->oAssigned==0 && pSection->Type==SECT_CODE )
{
pSection->oAssigned=1;
pSection->nBank=0;
pSection->nOrg=BankFree[0]->nOrg;
BankFree[0]->nOrg+=pSection->nByteSize;
BankFree[0]->nSize-=pSection->nByteSize;
}
pSection=pSection->pNext;
}
pSection=pSections;
while( pSection )
{
if( pSection->oAssigned==0 && pSection->Type==SECT_BSS )
{
pSection->oAssigned=1;
pSection->nBank=0;
pSection->nOrg=BankFree[0]->nOrg;
BankFree[0]->nOrg+=pSection->nByteSize;
BankFree[0]->nSize-=pSection->nByteSize;
}
pSection=pSection->pNext;
}
}
else
fatalerror( "Out of memory!" );
}
void AssignSections( void )
{
switch( outputtype )
{
case OUTPUT_GBROM:
GBROM_AssignSections();
break;
case OUTPUT_PSION2:
PSION2_AssignSections();
break;
}
}
void CreateSymbolTable( void )
{
struct sSection *pSect;
sym_Init();
pSect=pSections;
while( pSect )
{
SLONG i;
i=pSect->nNumberOfSymbols;
while( i-- )
{
if( (pSect->tSymbols[i]->Type==SYM_EXPORT) &&
( (pSect->tSymbols[i]->pSection==pSect) ||
(pSect->tSymbols[i]->pSection==NULL)) )
{
if( pSect->tSymbols[i]->pSection==NULL )
sym_CreateSymbol( pSect->tSymbols[i]->pzName,
pSect->tSymbols[i]->nOffset,
-1 );
else
sym_CreateSymbol( pSect->tSymbols[i]->pzName,
pSect->nOrg+pSect->tSymbols[i]->nOffset,
pSect->nBank );
}
}
pSect=pSect->pNext;
}
}

22
src/link/include/assign.h Normal file
View File

@@ -0,0 +1,22 @@
#ifndef ASSIGN_H
#define ASSIGN_H
#include "types.h"
enum eBankDefine
{
BANK_HOME=0,
BANK_BSS=256,
BANK_VRAM,
BANK_HRAM
};
#define MAXBANKS 259
extern SLONG area_Avail( SLONG bank );
extern void AssignSections( void );
extern void CreateSymbolTable( void );
extern SLONG MaxBankUsed;
extern SLONG MaxAvail[MAXBANKS];
#endif

View File

@@ -0,0 +1,6 @@
#ifndef LIBRARY_H
#define LIBRARY_H
extern void AddNeededModules( void );
#endif

21
src/link/include/main.h Normal file
View File

@@ -0,0 +1,21 @@
#ifndef MAIN_H
#define MAIN_H
#include "types.h"
extern void PrintUsage( void );
extern void fatalerror( char *s );
extern char temptext[1024];
extern SLONG fillchar;
extern char smartlinkstartsymbol[256];
enum eOutputType
{
OUTPUT_GBROM,
OUTPUT_PSION2
};
extern enum eOutputType outputtype;
#endif

View File

@@ -0,0 +1,11 @@
#ifndef MAPFILE_H
#define MAPFILE_H
extern void SetMapfileName( char *name );
extern void SetSymfileName( char *name );
extern void CloseMapfile( void );
extern void MapfileWriteSection( struct sSection *pSect );
extern void MapfileInitBank( SLONG bank );
extern void MapfileCloseBank( SLONG slack );
#endif

119
src/link/include/mylink.h Normal file
View File

@@ -0,0 +1,119 @@
#ifndef LINK_H
#define LINK_H 1
#if defined(AMIGA) || defined(__GNUC__)
#define _MAX_PATH 512
#endif
#include "types.h"
extern SLONG options;
#define OPT_SMALL 0x01
#define OPT_SMART_C_LINK 0x02
enum eRpnData
{
RPN_ADD=0,
RPN_SUB,
RPN_MUL,
RPN_DIV,
RPN_MOD,
RPN_UNSUB,
RPN_OR,
RPN_AND,
RPN_XOR,
RPN_UNNOT,
RPN_LOGAND,
RPN_LOGOR,
RPN_LOGUNNOT,
RPN_LOGEQ,
RPN_LOGNE,
RPN_LOGGT,
RPN_LOGLT,
RPN_LOGGE,
RPN_LOGLE,
RPN_SHL,
RPN_SHR,
RPN_BANK,
RPN_HRAM,
RPN_PCEZP,
RPN_RANGECHECK,
RPN_CONST=0x80,
RPN_SYM=0x81
};
enum eSectionType
{
SECT_BSS,
SECT_VRAM,
SECT_CODE,
SECT_HOME,
SECT_HRAM
};
struct sSection
{
SLONG nBank;
SLONG nOrg;
BBOOL oAssigned;
SLONG nByteSize;
enum eSectionType Type;
UBYTE *pData;
SLONG nNumberOfSymbols;
struct sSymbol **tSymbols;
struct sPatch *pPatches;
struct sSection *pNext;
};
enum eSymbolType
{
SYM_LOCAL,
SYM_IMPORT,
SYM_EXPORT
};
struct sSymbol
{
char *pzName;
enum eSymbolType Type;
/* the following 3 items only valid when Type!=SYM_IMPORT */
SLONG nSectionID; /* internal to object.c */
struct sSection *pSection;
SLONG nOffset;
};
enum ePatchType
{
PATCH_BYTE=0,
PATCH_WORD_L,
PATCH_LONG_L,
PATCH_WORD_B,
PATCH_LONG_B
};
struct sPatch
{
char *pzFilename;
SLONG nLineNo;
SLONG nOffset;
enum ePatchType Type;
SLONG nRPNSize;
UBYTE *pRPN;
struct sPatch *pNext;
BBOOL oRelocPatch;
};
extern struct sSection *pSections;
extern struct sSection *pLibSections;
#endif

View File

@@ -0,0 +1,7 @@
#ifndef OBJECT_H
#define OBJECT_H
extern void obj_Readfile( char *tzObjectfile );
extern void lib_Readfile( char *tzLibfile );
#endif

View File

@@ -0,0 +1,7 @@
#ifndef OUTPUT_H
#define OUTPUT_H
void out_Setname( char *tzOutputfile );
void Output( void );
#endif

9
src/link/include/patch.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef PATCH_H
#define PATCH_H
#include "types.h"
void Patch( void );
extern SLONG nPC;
#endif

11
src/link/include/symbol.h Normal file
View File

@@ -0,0 +1,11 @@
#ifndef SYMBOL_H
#define SYMBOL_H
#include "types.h"
void sym_Init( void );
void sym_CreateSymbol( char *tzName, SLONG nValue, SBYTE nBank );
SLONG sym_GetValue( char *tzName );
SLONG sym_GetBank( char *tzName );
#endif

16
src/link/include/types.h Normal file
View File

@@ -0,0 +1,16 @@
#ifndef TYPES_H
#define TYPES_H 1
#if defined(AMIGA) || defined(__GNUC__)
#define _MAX_PATH 512
#endif
typedef unsigned char UBYTE;
typedef signed char SBYTE;
typedef unsigned short UWORD;
typedef signed short SWORD;
typedef unsigned long ULONG;
typedef signed long SLONG;
typedef signed char BBOOL;
#endif

127
src/link/library.c Normal file
View File

@@ -0,0 +1,127 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "types.h"
#include "mylink.h"
#include "main.h"
static BBOOL symboldefined( char *name )
{
struct sSection *pSect;
pSect=pSections;
while( pSect )
{
ULONG i;
for( i=0; i<pSect->nNumberOfSymbols; i+=1 )
{
if( (pSect->tSymbols[i]->Type==SYM_EXPORT)
|| ( (pSect->tSymbols[i]->Type==SYM_LOCAL)
&& (pSect==pSect->tSymbols[i]->pSection) ) )
{
if( strcmp(pSect->tSymbols[i]->pzName,name)==0 )
return( 1 );
}
}
pSect=pSect->pNext;
}
return( 0 );
}
static BBOOL addmodulecontaining( char *name )
{
struct sSection **ppLSect;
ppLSect=&pLibSections;
while( *ppLSect )
{
ULONG i;
for( i=0; i<(*ppLSect)->nNumberOfSymbols; i+=1 )
{
if( ((*ppLSect)->tSymbols[i]->Type==SYM_EXPORT)
|| ( ((*ppLSect)->tSymbols[i]->Type==SYM_LOCAL)
&& ((*ppLSect)==(*ppLSect)->tSymbols[i]->pSection) ) )
{
if( strcmp((*ppLSect)->tSymbols[i]->pzName,name)==0 )
{
struct sSection **ppSect;
ppSect=&pSections;
while( *ppSect )
ppSect=&((*ppSect)->pNext);
*ppSect = *ppLSect;
*ppLSect = (*ppLSect)->pNext;
(*ppSect)->pNext = NULL;
return( 1 );
}
}
}
ppLSect=&((*ppLSect)->pNext);
}
return( 0 );
}
void AddNeededModules( void )
{
struct sSection *pSect;
if( (options&OPT_SMART_C_LINK)==0 )
{
struct sSection **ppLSect;
ppLSect=&pLibSections;
while( *ppLSect )
{
struct sSection **ppSect;
ppSect=&pSections;
while( *ppSect )
ppSect=&((*ppSect)->pNext);
*ppSect = *ppLSect;
*ppLSect = (*ppLSect)->pNext;
(*ppSect)->pNext = NULL;
/*ppLSect=&((*ppLSect)->pNext);*/
}
return;
}
if( options&OPT_SMART_C_LINK )
{
if( !addmodulecontaining( smartlinkstartsymbol ) )
{
sprintf( temptext, "Can't find start symbol '%s'", smartlinkstartsymbol );
fatalerror( temptext );
}
else
printf( "Smart linking with symbol '%s'\n", smartlinkstartsymbol );
}
pSect=pSections;
while( pSect )
{
ULONG i;
for( i=0; i<pSect->nNumberOfSymbols; i+=1 )
{
if( (pSect->tSymbols[i]->Type==SYM_IMPORT)
|| (pSect->tSymbols[i]->Type==SYM_LOCAL) )
{
if( !symboldefined(pSect->tSymbols[i]->pzName) )
{
addmodulecontaining( pSect->tSymbols[i]->pzName );
}
}
}
pSect=pSect->pNext;
}
}

230
src/link/main.c Normal file
View File

@@ -0,0 +1,230 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "object.h"
#include "output.h"
#include "assign.h"
#include "patch.h"
#include "asmotor.h"
#include "mylink.h"
#include "mapfile.h"
#include "main.h"
#include "library.h"
// Quick and dirty...but it works
#ifdef __GNUC__
#define strcmpi strcasecmp
#endif
enum eBlockType
{
BLOCK_COMMENT,
BLOCK_OBJECTS,
BLOCK_LIBRARIES,
BLOCK_OUTPUT
};
SLONG options=0;
SLONG fillchar=-1;
enum eOutputType outputtype=OUTPUT_GBROM;
char temptext[1024];
char smartlinkstartsymbol[256];
/*
* Print out an errormessage
*
*/
void fatalerror( char *s )
{
printf( "*ERROR* : %s\n", s );
exit( 5 );
}
/*
* Print the usagescreen
*
*/
void PrintUsage( void )
{
printf( "xLink v" LINK_VERSION " (part of ASMotor " ASMOTOR_VERSION ")\n\n"
"Usage: xlink [options] linkfile\n"
"Options:\n\t-h\t\tThis text\n"
"\t-m<mapfile>\tWrite a mapfile\n"
"\t-n<symfile>\tWrite a NO$GMB compatible symfile\n"
"\t-z<hx>\t\tSet the byte value (hex format) used for uninitialised\n"
"\t\t\tdata (default is ? for random)\n"
"\t-s<symbol>\tPerform smart linking starting with <symbol>\n"
"\t-t\t\tOutput target\n"
"\t\t-tg\tGameboy ROM image(default)\n"
"\t\t-ts\tGameboy small mode (32kB)\n"
"\t\t-tp\tPsion2 reloc module\n" );
exit( 0 );
}
/*
* Parse the linkfile and load all the objectfiles
*
*/
void ProcessLinkfile( char *tzLinkfile )
{
FILE *pLinkfile;
enum eBlockType CurrentBlock=BLOCK_COMMENT;
if( pLinkfile=fopen(tzLinkfile,"rt") )
{
while( !feof(pLinkfile) )
{
char tzLine[256];
fscanf( pLinkfile, "%s\n", tzLine );
if( tzLine[0]!='#' )
{
if( tzLine[0]=='[' && tzLine[strlen(tzLine)-1]==']' )
{
if( strcmpi("[objects]",tzLine)==0 )
CurrentBlock=BLOCK_OBJECTS;
else if( strcmpi("[output]",tzLine)==0 )
CurrentBlock=BLOCK_OUTPUT;
else if( strcmpi("[libraries]",tzLine)==0 )
CurrentBlock=BLOCK_LIBRARIES;
else if( strcmpi("[comment]",tzLine)==0 )
CurrentBlock=BLOCK_COMMENT;
else
{
fclose( pLinkfile );
sprintf( temptext, "Unknown block '%s'\n", tzLine );
fatalerror( temptext );
}
}
else
{
switch( CurrentBlock )
{
case BLOCK_COMMENT:
break;
case BLOCK_OBJECTS:
obj_Readfile( tzLine );
break;
case BLOCK_LIBRARIES:
lib_Readfile( tzLine );
break;
case BLOCK_OUTPUT:
out_Setname( tzLine );
break;
}
}
}
}
fclose( pLinkfile );
}
else
{
sprintf( temptext, "Unable to find linkfile '%s'\n", tzLinkfile );
fatalerror( temptext );
}
}
/*
* The main routine
*
*/
int main( int argc, char *argv[] )
{
SLONG argn=0;
argc-=1;
argn+=1;
if( argc==0 )
PrintUsage();
while( *argv[argn]=='-' )
{
char opt;
argc-=1;
switch( opt=argv[argn++][1] )
{
case '?':
case 'h':
PrintUsage();
break;
case 'm':
SetMapfileName( argv[argn-1]+2 );
break;
case 'n':
SetSymfileName( argv[argn-1]+2 );
break;
case 't':
switch( opt=argv[argn-1][2] )
{
case 'g':
outputtype=OUTPUT_GBROM;
break;
case 's':
outputtype=OUTPUT_GBROM;
options|=OPT_SMALL;
break;
case 'p':
outputtype=OUTPUT_PSION2;
break;
default:
sprintf( temptext, "Unknown option 't%c'\n", opt );
fatalerror( temptext );
break;
}
break;
case 'z':
if( strlen(argv[argn-1]+2)<=2 )
{
if( strcmp(argv[argn-1]+2,"?")==0 )
{
fillchar=-1;
}
else
{
int result;
result=sscanf( argv[argn-1]+2, "%x", &fillchar );
if( !((result==EOF) || (result==1)) )
{
fatalerror("Invalid argument for option 'z'\n" );
}
}
}
else
{
fatalerror("Invalid argument for option 'z'\n" );
}
break;
case 's':
options|=OPT_SMART_C_LINK;
strcpy( smartlinkstartsymbol, argv[argn-1]+2 );
break;
default:
sprintf( temptext, "Unknown option '%c'\n", opt );
fatalerror( temptext );
break;
}
}
if( argc==1 )
{
ProcessLinkfile( argv[argn++] );
AddNeededModules();
AssignSections();
CreateSymbolTable();
Patch();
Output();
CloseMapfile();
}
else
PrintUsage();
return( 0 );
}

63
src/link/makefile Normal file
View File

@@ -0,0 +1,63 @@
.ERASE
.EXTENSIONS:
.EXTENSIONS: .obj .c .h
!ifndef TARGET
TARGET = DOS
!endif
!ifeq TARGET DOS
!else
!ifeq TARGET WIN95
!else
!error Invalid TARGET (must be DOS or WIN95)
!endif
!endif
!ifeq TARGET DOS
COPT = /zp4 /5s /fp3 /d2 /oneatx /i=include /i=.. /wx /bt=dos
OBJDIR = OBJS\
EXE = xlink.exe
!endif
!ifeq TARGET WIN95
COPT = /zp4 /5s /fp3 /d3 /oneatx /i=include /i=.. /d2 /wx /bt=nt
OBJDIR = OBJS95\
EXE = xlink95.exe
!endif
C = wcc386 $(COPT)
.c: .
.h: include
.obj: $(OBJDIR)
OBJS = main.obj object.obj assign.obj symbol.obj &
patch.obj output.obj mapfile.obj library.obj
$(EXE) : $(OBJS)
%create link.lnk
!ifeq TARGET DOS
%append link.lnk system pmodew
!endif
!ifeq TARGET WIN95
%append link.lnk system nt
!endif
%append link.lnk option map
%append link.lnk option stack=64k
%append link.lnk debug watcom all
%append link.lnk name $(EXE)
for %i in ($(OBJS)) do %append link.lnk file $(OBJDIR)\%i
wlink @link.lnk
!ifeq TARGET DOS
d:\code\pmodew\pmwsetup /B0 $(EXE)
!endif
.c.obj : .AUTODEPEND
$(C) -fo=$(OBJDIR)$^. $[.
clean: .SYMBOLIC
del $(OBJDIR)*.obj
del *.err
del $(EXE)
del *.map
del link.lnk

108
src/link/mapfile.c Normal file
View File

@@ -0,0 +1,108 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "asmotor.h"
#include "main.h"
#include "mylink.h"
#include "assign.h"
FILE *mf=NULL;
FILE *sf=NULL;
SLONG currentbank=0;
SLONG sfbank;
void SetMapfileName( char *name )
{
if( mf=fopen(name,"wt") )
return;
else
fatalerror( "Unable to open mapfile for writing" );
}
void SetSymfileName( char *name )
{
if( sf=fopen(name,"wt") )
{
fprintf( sf, ";File generated by xLink v" LINK_VERSION "\n\n" );
return;
}
else
fatalerror( "Unable to open symfile for writing" );
}
void CloseMapfile( void )
{
if( mf )
{
fclose( mf );
mf=NULL;
}
if( sf )
{
fclose( sf );
sf=NULL;
}
}
void MapfileInitBank( SLONG bank )
{
if( mf )
{
currentbank=bank;
if( bank==0 )
fprintf( mf, "Bank #0 (HOME):\n" );
else if( bank<=255 )
fprintf( mf, "Bank #%d:\n", bank );
else if( bank==BANK_BSS )
fprintf( mf, "BSS:\n" );
else if( bank==BANK_HRAM )
fprintf( mf, "HRAM:\n" );
else if( bank==BANK_VRAM )
fprintf( mf, "VRAM:\n" );
}
if( sf )
{
sfbank=(bank>=1&&bank<=255)?bank:0;
}
}
void MapfileWriteSection( struct sSection *pSect )
{
if( mf || sf )
{
SLONG i;
fprintf( mf, " SECTION: $%04X-$%04X ($%04X bytes)\n", pSect->nOrg, pSect->nOrg+pSect->nByteSize-1, pSect->nByteSize );
for( i=0; i<pSect->nNumberOfSymbols; i+=1 )
{
struct sSymbol *pSym;
pSym=pSect->tSymbols[i];
if( (pSym->pSection==pSect) && (pSym->Type!=SYM_IMPORT) )
{
if( mf )
{
fprintf( mf, " $%04X = %s\n", pSym->nOffset+pSect->nOrg, pSym->pzName );
}
if( sf )
{
fprintf( sf, "%02X:%04X %s\n", sfbank, pSym->nOffset+pSect->nOrg, pSym->pzName );
}
}
}
}
}
void MapfileCloseBank( SLONG slack )
{
if( mf )
{
if( slack==MaxAvail[currentbank] )
fprintf( mf, " EMPTY\n\n" );
else
fprintf( mf, " SLACK: $%04X bytes\n\n", slack );
}
}

546
src/link/object.c Normal file
View File

@@ -0,0 +1,546 @@
/*
* Here we have the routines that read an objectfile
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mylink.h"
#include "main.h"
struct sSymbol **tSymbols;
struct sSection *pSections=NULL;
struct sSection *pLibSections=NULL;
UBYTE dummymem;
BBOOL oReadLib=0;
/*
* The usual byte order stuff
*
*/
SLONG readlong( FILE *f )
{
SLONG r;
r =fgetc(f);
r|=fgetc(f)<<8;
r|=fgetc(f)<<16;
r|=fgetc(f)<<24;
return( r );
}
UWORD readword( FILE *f )
{
UWORD r;
r =fgetc(f);
r|=fgetc(f)<<8;
return( r );
}
/*
* Read a NULL terminated string from a file
*
*/
SLONG readasciiz( char *s, FILE *f )
{
SLONG r=0;
while( ((*s++)=fgetc(f))!=0 )
r+=1;
return( r+1 );
}
/*
* Allocate a new section and link it into the list
*
*/
struct sSection *AllocSection( void )
{
struct sSection **ppSections;
if( oReadLib==1 )
ppSections=&pLibSections;
else
ppSections=&pSections;
while( *ppSections )
ppSections=&((*ppSections)->pNext);
if( (*ppSections)=(struct sSection *)malloc(sizeof(struct sSection)) )
{
(*ppSections)->tSymbols=tSymbols;
(*ppSections)->pNext=NULL;
(*ppSections)->pPatches=NULL;
(*ppSections)->oAssigned=0;
return( *ppSections );
}
else
{
fatalerror( "Out of memory!" );
return( NULL );
}
}
/*
* Read a symbol from a file
*
*/
struct sSymbol *obj_ReadSymbol( FILE *f )
{
char s[256];
struct sSymbol *pSym;
if( pSym=(struct sSymbol *)malloc(sizeof(struct sSymbol)) )
{
readasciiz( s, f );
if( pSym->pzName=(char *)malloc(strlen(s)+1) )
{
strcpy( pSym->pzName, s );
if( (pSym->Type=(enum eSymbolType)fgetc(f))!=SYM_IMPORT )
{
pSym->nSectionID=readlong(f);
pSym->nOffset=readlong(f);
}
return( pSym );
}
else
fatalerror( "Out of memory!" );
}
else
fatalerror( "Out of memory!" );
return( NULL );
}
/*
* RGB0 object reader routines
*
*/
struct sSection *obj_ReadRGB0Section( FILE *f )
{
struct sSection *pSection;
pSection=AllocSection();
pSection->nByteSize=readlong( f );
pSection->Type=(enum eSectionType)fgetc( f );
pSection->nOrg=-1;
pSection->nBank=-1;
/* does the user want the -s mode? */
if( (options&OPT_SMALL) && (pSection->Type==SECT_CODE) )
{
pSection->Type=SECT_HOME;
}
if( (pSection->Type==SECT_CODE) || (pSection->Type==SECT_HOME) )
{
/*
* These sectiontypes contain data...
*
*/
if( pSection->nByteSize )
{
if( pSection->pData=(UBYTE *)malloc(pSection->nByteSize) )
{
SLONG nNumberOfPatches;
struct sPatch **ppPatch, *pPatch;
char s[256];
fread( pSection->pData, sizeof(UBYTE), pSection->nByteSize, f );
nNumberOfPatches=readlong(f);
ppPatch=&pSection->pPatches;
/*
* And patches...
*
*/
while( nNumberOfPatches-- )
{
if( pPatch=(struct sPatch *)malloc(sizeof(struct sPatch)) )
{
*ppPatch=pPatch;
readasciiz( s, f );
if( pPatch->pzFilename=(char *)malloc(strlen(s)+1) )
{
strcpy( pPatch->pzFilename, s );
pPatch->nLineNo=readlong( f );
pPatch->nOffset=readlong( f );
pPatch->Type=(enum ePatchType)fgetc( f );
if( (pPatch->nRPNSize=readlong(f))>0 )
{
if( pPatch->pRPN=(UBYTE *)malloc(pPatch->nRPNSize) )
fread( pPatch->pRPN, sizeof(UBYTE), pPatch->nRPNSize, f );
else
fatalerror( "Out of memory!" );
}
else
pPatch->pRPN=NULL;
pPatch->pNext=NULL;
ppPatch=&(pPatch->pNext);
}
else
fatalerror( "Out of memory!" );
}
else
fatalerror( "Out of memory!" );
}
}
else
fatalerror( "Out of memory!" );
}
else
{
readlong(f); // Skip number of patches
pSection->pData=&dummymem;
}
}
return( pSection );
}
void obj_ReadRGB0( FILE *pObjfile )
{
struct sSection *pFirstSection;
SLONG nNumberOfSymbols, nNumberOfSections, i;
nNumberOfSymbols=readlong( pObjfile );
nNumberOfSections=readlong( pObjfile );
/* First comes the symbols */
if( nNumberOfSymbols )
{
if( tSymbols=(struct sSymbol **)malloc(nNumberOfSymbols*sizeof(struct sSymbol *)) )
{
for( i=0; i<nNumberOfSymbols; i+=1 )
tSymbols[i]=obj_ReadSymbol( pObjfile );
}
else
fatalerror( "Out of memory!" );
}
else
tSymbols=(struct sSymbol **)&dummymem;
/* Next we have the sections */
pFirstSection=NULL;
while( nNumberOfSections-- )
{
struct sSection *pNewSection;
pNewSection=obj_ReadRGB0Section( pObjfile );
pNewSection->nNumberOfSymbols=nNumberOfSymbols;
if( pFirstSection==NULL )
pFirstSection=pNewSection;
}
/*
* Fill in the pSection entry in the symbolstructure.
* This REALLY needs some cleaning up... but, hey, it works
*
*/
for( i=0; i<nNumberOfSymbols; i+=1 )
{
struct sSection *pConvSect=pFirstSection;
if( tSymbols[i]->Type!=SYM_IMPORT && tSymbols[i]->nSectionID!=-1 )
{
SLONG j=0;
while( j != tSymbols[i]->nSectionID )
{
j+=1;
pConvSect=pConvSect->pNext;
}
tSymbols[i]->pSection=pConvSect;
}
else
tSymbols[i]->pSection=NULL;
}
}
/*
* RGB1 object reader routines
*
*/
struct sSection *obj_ReadRGB1Section( FILE *f )
{
struct sSection *pSection;
pSection=AllocSection();
pSection->nByteSize=readlong( f );
pSection->Type=(enum eSectionType)fgetc( f );
/*
* And because of THIS new feature I'll have to rewrite loads and
* loads of stuff... oh well it needed to be done anyway
*
*/
pSection->nOrg=readlong( f );
pSection->nBank=readlong( f );
/* does the user want the -s mode? */
if( (options&OPT_SMALL) && (pSection->Type==SECT_CODE) )
{
pSection->Type=SECT_HOME;
}
if( (pSection->Type==SECT_CODE) || (pSection->Type==SECT_HOME) )
{
/*
* These sectiontypes contain data...
*
*/
if( pSection->nByteSize )
{
if( pSection->pData=(UBYTE *)malloc(pSection->nByteSize) )
{
SLONG nNumberOfPatches;
struct sPatch **ppPatch, *pPatch;
char s[256];
fread( pSection->pData, sizeof(UBYTE), pSection->nByteSize, f );
nNumberOfPatches=readlong(f);
ppPatch=&pSection->pPatches;
/*
* And patches...
*
*/
while( nNumberOfPatches-- )
{
if( pPatch=(struct sPatch *)malloc(sizeof(struct sPatch)) )
{
*ppPatch=pPatch;
readasciiz( s, f );
if( pPatch->pzFilename=(char *)malloc(strlen(s)+1) )
{
strcpy( pPatch->pzFilename, s );
pPatch->nLineNo=readlong( f );
pPatch->nOffset=readlong( f );
pPatch->Type=(enum ePatchType)fgetc( f );
if( (pPatch->nRPNSize=readlong(f))>0 )
{
if( pPatch->pRPN=(UBYTE *)malloc(pPatch->nRPNSize) )
fread( pPatch->pRPN, sizeof(UBYTE), pPatch->nRPNSize, f );
else
fatalerror( "Out of memory!" );
}
else
pPatch->pRPN=NULL;
pPatch->pNext=NULL;
ppPatch=&(pPatch->pNext);
}
else
fatalerror( "Out of memory!" );
}
else
fatalerror( "Out of memory!" );
}
}
else
fatalerror( "Out of memory!" );
}
else
{
readlong(f); // Skip number of patches
pSection->pData=&dummymem;
}
}
return( pSection );
}
void obj_ReadRGB1( FILE *pObjfile )
{
struct sSection *pFirstSection;
SLONG nNumberOfSymbols, nNumberOfSections, i;
nNumberOfSymbols=readlong( pObjfile );
nNumberOfSections=readlong( pObjfile );
/* First comes the symbols */
if( nNumberOfSymbols )
{
if( tSymbols=(struct sSymbol **)malloc(nNumberOfSymbols*sizeof(struct sSymbol *)) )
{
for( i=0; i<nNumberOfSymbols; i+=1 )
tSymbols[i]=obj_ReadSymbol( pObjfile );
}
else
fatalerror( "Out of memory!" );
}
else
tSymbols=(struct sSymbol **)&dummymem;
/* Next we have the sections */
pFirstSection=NULL;
while( nNumberOfSections-- )
{
struct sSection *pNewSection;
pNewSection=obj_ReadRGB1Section( pObjfile );
pNewSection->nNumberOfSymbols=nNumberOfSymbols;
if( pFirstSection==NULL )
pFirstSection=pNewSection;
}
/*
* Fill in the pSection entry in the symbolstructure.
* This REALLY needs some cleaning up... but, hey, it works
*
*/
for( i=0; i<nNumberOfSymbols; i+=1 )
{
struct sSection *pConvSect=pFirstSection;
if( tSymbols[i]->Type!=SYM_IMPORT && tSymbols[i]->nSectionID!=-1 )
{
SLONG j=0;
while( j != tSymbols[i]->nSectionID )
{
j+=1;
pConvSect=pConvSect->pNext;
}
tSymbols[i]->pSection=pConvSect;
}
else
tSymbols[i]->pSection=NULL;
}
}
/*
* The main objectfileloadroutine (phew)
*
*/
void obj_ReadOpenFile( FILE *pObjfile, char *tzObjectfile )
{
char tzHeader[8];
fread( tzHeader, sizeof(char), 4, pObjfile );
tzHeader[4]=0;
if( strncmp(tzHeader,"RGB", 3)==0 )
{
switch( tzHeader[3] )
{
case '0':
obj_ReadRGB0( pObjfile );
break;
case '1':
case '2': // V2 is really the same but the are new patch types
obj_ReadRGB1( pObjfile );
break;
default:
sprintf( temptext, "'%s' is an unsupported version\n", tzObjectfile );
fatalerror( temptext );
break;
}
}
else
{
sprintf( temptext, "'%s' is not a valid object\n", tzObjectfile );
fatalerror( temptext );
}
}
void obj_Readfile( char *tzObjectfile )
{
FILE *pObjfile;
if( options&OPT_SMART_C_LINK )
oReadLib=1;
else
oReadLib=0;
if( pObjfile=fopen(tzObjectfile,"rb") )
{
obj_ReadOpenFile( pObjfile, tzObjectfile );
fclose( pObjfile );
}
else
{
sprintf( temptext, "Unable to open '%s'\n", tzObjectfile );
fatalerror( temptext );
}
oReadLib=0;
}
SLONG file_Length( FILE *f )
{
ULONG r,
p;
p=ftell( f );
fseek( f, 0, SEEK_END );
r=ftell( f );
fseek( f, p, SEEK_SET );
return( r );
}
void lib_ReadXLB0( FILE *f )
{
SLONG size;
size=file_Length( f )-4;
while( size )
{
char name[256];
size-=readasciiz( name, f );
readword( f ); size-=2;
readword( f ); size-=2;
size-=readlong( f ); size-=4;
obj_ReadOpenFile( f, name );
}
}
void lib_Readfile( char *tzLibfile )
{
FILE *pObjfile;
oReadLib=1;
if( pObjfile=fopen(tzLibfile,"rb") )
{
char tzHeader[5];
fread( tzHeader, sizeof(char), 4, pObjfile );
tzHeader[4]=0;
if( strcmp(tzHeader,"XLB0")==0 )
lib_ReadXLB0( pObjfile );
else
{
sprintf( temptext, "'%s' is an invalid library\n", tzLibfile );
fatalerror( temptext );
}
fclose( pObjfile );
}
else
{
sprintf( temptext, "Unable to open '%s'\n", tzLibfile );
fatalerror( temptext );
}
}

2
src/link/objs/delete.me Normal file
View File

@@ -0,0 +1,2 @@
You can safely delete me.
I'm just a dummy so pkzip will store this directory.

View File

@@ -0,0 +1,2 @@
You can safely delete me.
I'm just a dummy so pkzip will store this directory.

222
src/link/output.c Normal file
View File

@@ -0,0 +1,222 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mylink.h"
#include "mapfile.h"
#include "main.h"
#include "assign.h"
char tzOutname[_MAX_PATH];
BBOOL oOutput=0;
void writehome( FILE *f )
{
struct sSection *pSect;
UBYTE *mem;
if( mem=(UBYTE *)malloc(MaxAvail[BANK_HOME]) )
{
if( fillchar!=-1 )
{
memset( mem, fillchar, MaxAvail[BANK_HOME] );
}
MapfileInitBank( 0 );
pSect=pSections;
while( pSect )
{
if( pSect->Type==SECT_HOME )
{
memcpy( mem+pSect->nOrg, pSect->pData, pSect->nByteSize );
MapfileWriteSection( pSect );
}
pSect=pSect->pNext;
}
MapfileCloseBank( area_Avail(0) );
fwrite( mem, 1, MaxAvail[BANK_HOME], f );
free( mem );
}
}
void writebank( FILE *f, SLONG bank )
{
struct sSection *pSect;
UBYTE *mem;
if( mem=(UBYTE *)malloc(MaxAvail[bank]) )
{
if( fillchar!=-1 )
{
memset( mem, fillchar, MaxAvail[bank] );
}
MapfileInitBank( bank );
pSect=pSections;
while( pSect )
{
if( pSect->Type==SECT_CODE && pSect->nBank==bank )
{
memcpy( mem+pSect->nOrg-0x4000, pSect->pData, pSect->nByteSize );
MapfileWriteSection( pSect );
}
pSect=pSect->pNext;
}
MapfileCloseBank( area_Avail(bank) );
fwrite( mem, 1, MaxAvail[bank], f );
free( mem );
}
}
void out_Setname( char *tzOutputfile )
{
strcpy( tzOutname, tzOutputfile );
oOutput=1;
}
void GBROM_Output( void )
{
SLONG i;
FILE *f;
if( f=fopen(tzOutname,"wb") )
{
writehome( f );
for( i=1; i<=MaxBankUsed; i+=1 )
writebank( f, i );
fclose( f );
}
for( i=256; i<MAXBANKS; i+=1 )
{
struct sSection *pSect;
MapfileInitBank( i );
pSect=pSections;
while( pSect )
{
if( pSect->nBank==i )
{
MapfileWriteSection( pSect );
}
pSect=pSect->pNext;
}
MapfileCloseBank( area_Avail(i) );
}
}
void PSION2_Output( void )
{
FILE *f;
if( f=fopen(tzOutname,"wb") )
{
struct sSection *pSect;
UBYTE *mem;
ULONG size=MaxAvail[0]-area_Avail(0);
ULONG relocpatches;
fputc( size>>24, f );
fputc( size>>16, f );
fputc( size>>8, f );
fputc( size, f );
if( mem=(UBYTE *)malloc(MaxAvail[0]-area_Avail(0)) )
{
MapfileInitBank( 0 );
pSect=pSections;
while( pSect )
{
if( pSect->Type==SECT_CODE )
{
memcpy( mem+pSect->nOrg, pSect->pData, pSect->nByteSize );
MapfileWriteSection( pSect );
}
else
{
memset( mem+pSect->nOrg, 0, pSect->nByteSize );
}
pSect=pSect->pNext;
}
MapfileCloseBank( area_Avail(0) );
fwrite( mem, 1, MaxAvail[0]-area_Avail(0), f );
free( mem );
}
relocpatches=0;
pSect=pSections;
while( pSect )
{
struct sPatch *pPatch;
pPatch=pSect->pPatches;
while( pPatch )
{
if( pPatch->oRelocPatch )
{
relocpatches+=1;
}
pPatch=pPatch->pNext;
}
pSect=pSect->pNext;
}
fputc( relocpatches>>24, f );
fputc( relocpatches>>16, f );
fputc( relocpatches>>8, f );
fputc( relocpatches, f );
pSect=pSections;
while( pSect )
{
struct sPatch *pPatch;
pPatch=pSect->pPatches;
while( pPatch )
{
if( pPatch->oRelocPatch )
{
ULONG address;
address=pPatch->nOffset+pSect->nOrg;
fputc( address>>24, f );
fputc( address>>16, f );
fputc( address>>8, f );
fputc( address, f );
}
pPatch=pPatch->pNext;
}
pSect=pSect->pNext;
}
fclose( f );
}
}
void Output( void )
{
if( oOutput )
{
switch( outputtype )
{
case OUTPUT_GBROM:
GBROM_Output();
break;
case OUTPUT_PSION2:
PSION2_Output();
break;
}
}
}

300
src/link/patch.c Normal file
View File

@@ -0,0 +1,300 @@
#include <stdio.h>
#include <string.h>
#include "mylink.h"
#include "symbol.h"
#include "main.h"
struct sSection *pCurrentSection;
SLONG rpnstack[256];
SLONG rpnp;
SLONG nPC;
void rpnpush( SLONG i )
{
rpnstack[rpnp++]=i;
}
SLONG rpnpop( void )
{
return( rpnstack[--rpnp] );
}
SLONG getsymvalue( SLONG symid )
{
switch( pCurrentSection->tSymbols[symid]->Type )
{
case SYM_IMPORT:
return( sym_GetValue(pCurrentSection->tSymbols[symid]->pzName) );
break;
case SYM_EXPORT:
case SYM_LOCAL:
{
if( strcmp(pCurrentSection->tSymbols[symid]->pzName,"@")==0 )
{
return( nPC );
}
else
return( pCurrentSection->tSymbols[symid]->nOffset+pCurrentSection->tSymbols[symid]->pSection->nOrg );
}
default:
break;
}
fatalerror( "*INTERNAL* UNKNOWN SYMBOL TYPE" );
return( 0 );
}
SLONG getsymbank( SLONG symid )
{
switch( pCurrentSection->tSymbols[symid]->Type )
{
case SYM_IMPORT:
return( sym_GetBank(pCurrentSection->tSymbols[symid]->pzName) );
break;
case SYM_EXPORT:
case SYM_LOCAL:
return( pCurrentSection->tSymbols[symid]->pSection->nBank );
//return( pCurrentSection->nBank );
default:
break;
}
fatalerror( "*INTERNAL* UNKNOWN SYMBOL TYPE" );
return( 0 );
}
SLONG calcrpn( struct sPatch *pPatch )
{
SLONG t, size;
UBYTE *rpn;
rpnp=0;
size=pPatch->nRPNSize;
rpn=pPatch->pRPN;
pPatch->oRelocPatch=0;
while( size>0 )
{
size-=1;
switch( *rpn++ )
{
case RPN_ADD:
rpnpush( rpnpop()+rpnpop() );
break;
case RPN_SUB:
t=rpnpop();
rpnpush( rpnpop()-t );
break;
case RPN_MUL:
rpnpush( rpnpop()*rpnpop() );
break;
case RPN_DIV:
t=rpnpop();
rpnpush( rpnpop()/t );
break;
case RPN_MOD:
t=rpnpop();
rpnpush( rpnpop()%t );
break;
case RPN_UNSUB:
rpnpush( -rpnpop() );
break;
case RPN_OR:
rpnpush( rpnpop()|rpnpop() );
break;
case RPN_AND:
rpnpush( rpnpop()&rpnpop() );
break;
case RPN_XOR:
rpnpush( rpnpop()^rpnpop() );
break;
case RPN_UNNOT:
rpnpush( rpnpop()^0xFFFFFFFF );
break;
case RPN_LOGAND:
rpnpush( rpnpop()&&rpnpop() );
break;
case RPN_LOGOR:
rpnpush( rpnpop()||rpnpop() );
break;
case RPN_LOGUNNOT:
rpnpush( !rpnpop() );
break;
case RPN_LOGEQ:
rpnpush( rpnpop()==rpnpop() );
break;
case RPN_LOGNE:
rpnpush( rpnpop()!=rpnpop() );
break;
case RPN_LOGGT:
t=rpnpop();
rpnpush( rpnpop()>t );
break;
case RPN_LOGLT:
t=rpnpop();
rpnpush( rpnpop()<t );
break;
case RPN_LOGGE:
t=rpnpop();
rpnpush( rpnpop()>=t );
break;
case RPN_LOGLE:
t=rpnpop();
rpnpush( rpnpop()<=t );
break;
case RPN_SHL:
t=rpnpop();
rpnpush( rpnpop()<<t );
break;
case RPN_SHR:
t=rpnpop();
rpnpush( rpnpop()>>t );
break;
case RPN_HRAM:
t=rpnpop();
rpnpush(t&0xFF);
if( t<0 || (t>0xFF && t<0xFF00) || t>0xFFFF )
{
sprintf( temptext, "%s(%d) : Value must be in the HRAM area", pPatch->pzFilename, pPatch->nLineNo );
fatalerror( temptext );
}
break;
case RPN_PCEZP:
t=rpnpop();
rpnpush(t&0xFF);
if( t<0x2000 || t>0x20FF )
{
sprintf( temptext, "%s(%d) : Value must be in the ZP area", pPatch->pzFilename, pPatch->nLineNo );
fatalerror( temptext );
}
break;
case RPN_CONST:
/* constant */
t=(*rpn++);
t|=(*rpn++)<<8;
t|=(*rpn++)<<16;
t|=(*rpn++)<<24;
rpnpush( t );
size-=4;
break;
case RPN_SYM:
/* symbol */
t=(*rpn++);
t|=(*rpn++)<<8;
t|=(*rpn++)<<16;
t|=(*rpn++)<<24;
rpnpush( getsymvalue(t) );
pPatch->oRelocPatch|=(getsymbank(t)!=-1);
size-=4;
break;
case RPN_BANK:
/* symbol */
t=(*rpn++);
t|=(*rpn++)<<8;
t|=(*rpn++)<<16;
t|=(*rpn++)<<24;
rpnpush( getsymbank(t) );
size-=4;
break;
case RPN_RANGECHECK:
{
SLONG low,
high;
low =(*rpn++);
low|=(*rpn++)<<8;
low|=(*rpn++)<<16;
low|=(*rpn++)<<24;
high =(*rpn++);
high|=(*rpn++)<<8;
high|=(*rpn++)<<16;
high|=(*rpn++)<<24;
t=rpnpop();
if( t<low || t>high )
{
sprintf( temptext, "%s(%d) : Value must be in the range [%d;%d]", pPatch->pzFilename, pPatch->nLineNo, low, high );
fatalerror( temptext );
}
rpnpush(t);
size-=8;
break;
}
}
}
return( rpnpop() );
}
void Patch( void )
{
struct sSection *pSect;
pSect=pSections;
while( pSect )
{
struct sPatch *pPatch;
pCurrentSection=pSect;
pPatch=pSect->pPatches;
while( pPatch )
{
SLONG t;
nPC=pSect->nOrg+pPatch->nOffset;
t=calcrpn( pPatch );
switch( pPatch->Type )
{
case PATCH_BYTE:
if( t>=-128 && t<=255 )
{
t&=0xFF;
pSect->pData[pPatch->nOffset]=(UBYTE)t;
}
else
{
sprintf( temptext, "%s(%d) : Value must be 8-bit\n", pPatch->pzFilename, pPatch->nLineNo );
fatalerror( temptext );
}
break;
case PATCH_WORD_L:
case PATCH_WORD_B:
if( t>=-32768 && t<=65535 )
{
t&=0xFFFF;
if( pPatch->Type==PATCH_WORD_L )
{
pSect->pData[pPatch->nOffset]=t&0xFF;
pSect->pData[pPatch->nOffset+1]=(t>>8)&0xFF;
}
else
{
// Assume big endian
pSect->pData[pPatch->nOffset]=(t>>8)&0xFF;
pSect->pData[pPatch->nOffset+1]=t&0xFF;
}
}
else
{
sprintf( temptext, "%s(%d) : Value must be 16-bit\n", pPatch->pzFilename, pPatch->nLineNo );
fatalerror( temptext );
}
break;
case PATCH_LONG_L:
pSect->pData[pPatch->nOffset+0]=t&0xFF;
pSect->pData[pPatch->nOffset+1]=(t>>8)&0xFF;
pSect->pData[pPatch->nOffset+2]=(t>>16)&0xFF;
pSect->pData[pPatch->nOffset+3]=(t>>24)&0xFF;
break;
case PATCH_LONG_B:
pSect->pData[pPatch->nOffset+0]=(t>>24)&0xFF;
pSect->pData[pPatch->nOffset+1]=(t>>16)&0xFF;
pSect->pData[pPatch->nOffset+2]=(t>>8)&0xFF;
pSect->pData[pPatch->nOffset+3]=t&0xFF;
break;
}
pPatch=pPatch->pNext;
}
pSect=pSect->pNext;
}
}

125
src/link/symbol.c Normal file
View File

@@ -0,0 +1,125 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "main.h"
#include "patch.h"
#include "types.h"
#define HASHSIZE 73
struct ISymbol
{
char *pzName;
SLONG nValue;
SLONG nBank; // -1=const
struct ISymbol *pNext;
};
struct ISymbol *tHash[HASHSIZE];
SLONG calchash( char *s )
{
SLONG r=0;
while( *s )
r+=*s++;
return( r%HASHSIZE );
}
void sym_Init( void )
{
SLONG i;
for( i=0; i<HASHSIZE; i+=1 )
tHash[i]=NULL;
}
SLONG sym_GetValue( char *tzName )
{
if( strcmp(tzName,"@")==0 )
{
return( nPC );
}
else
{
struct ISymbol **ppSym;
ppSym=&(tHash[calchash(tzName)]);
while( *ppSym )
{
if( strcmp(tzName,(*ppSym)->pzName) )
{
ppSym=&((*ppSym)->pNext);
}
else
{
return( (*ppSym)->nValue );
}
}
sprintf( temptext, "Unknown symbol '%s'", tzName );
fatalerror( temptext );
return( 0 );
}
}
SLONG sym_GetBank( char *tzName )
{
struct ISymbol **ppSym;
ppSym=&(tHash[calchash(tzName)]);
while( *ppSym )
{
if( strcmp(tzName,(*ppSym)->pzName) )
{
ppSym=&((*ppSym)->pNext);
}
else
{
return( (*ppSym)->nBank );
}
}
sprintf( temptext, "Unknown symbol '%s'" );
fatalerror( temptext );
return( 0 );
}
void sym_CreateSymbol( char *tzName, SLONG nValue, SBYTE nBank )
{
if( strcmp(tzName,"@")==0 )
{
}
else
{
struct ISymbol **ppSym;
ppSym=&(tHash[calchash(tzName)]);
while( *ppSym )
{
if( strcmp(tzName,(*ppSym)->pzName) )
{
ppSym=&((*ppSym)->pNext);
}
else
{
if( nBank==-1 )
return;
sprintf( temptext, "Symbol '%s' defined more than once\n", tzName );
fatalerror( temptext );
}
}
if( *ppSym=(struct ISymbol *)malloc(sizeof(struct ISymbol)) )
{
if( (*ppSym)->pzName=(char *)malloc(strlen(tzName)+1) )
{
strcpy( (*ppSym)->pzName, tzName );
(*ppSym)->nValue=nValue;
(*ppSym)->nBank=nBank;
(*ppSym)->pNext=NULL;
}
}
}
}