Initial revision: imported RGBDS source code

The code comes from the RGBDS source and documentation zip files found
on this website:

http://www.otakunozoku.com/1999/08/01/rednex-gameboy-development-system/

The same website reports:

	"Best of all, it’s free! That’s right! Free! The executables
	are free to use, either for personal hobby use, or full blown
	commercial productions — I know of at least a dozen commercial
	games you can purchase that are written with RGBDS — and the
	source code is free to modify.

	"The only thing I ask is that you do not charge for either
	distributing the executables or source code, and any derivative
	works you give credit to the original authors of the tools.
	That means you have to say “Thanks” to the original authors
	SurfSmurf and Otaku."

Signed-off-by: Vegard Nossum <vegard.nossum@gmail.com>
This commit is contained in:
Carsten Sorensen
2009-06-11 06:00:24 +02:00
committed by Vegard Nossum
commit e895832b2b
103 changed files with 13891 additions and 0 deletions

497
src/ASM/ALLOCA.C Normal file
View File

@@ -0,0 +1,497 @@
/* alloca.c -- allocate automatically reclaimed memory
(Mostly) portable public-domain implementation -- D A Gwyn
This implementation of the PWB library alloca function,
which is used to allocate space off the run-time stack so
that it is automatically reclaimed upon procedure exit,
was inspired by discussions with J. Q. Johnson of Cornell.
J.Otto Tennant <jot@cray.com> contributed the Cray support.
There are some preprocessor constants that can
be defined when compiling for your specific system, for
improved efficiency; however, the defaults should be okay.
The general concept of this implementation is to keep
track of all alloca-allocated blocks, and reclaim any
that are found to be deeper in the stack than the current
invocation. This heuristic does not reclaim storage as
soon as it becomes invalid, but it will do so eventually.
As a special case, alloca(0) reclaims storage without
allocating any. It is a good idea to use alloca(0) in
your main control loop, etc. to force garbage collection. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef emacs
#include "blockinput.h"
#endif
/* If compiling with GCC 2, this file's not needed. */
#if !defined (__GNUC__) || __GNUC__ < 2
/* If someone has defined alloca as a macro,
there must be some other way alloca is supposed to work. */
#ifndef alloca
#ifdef emacs
#ifdef static
/* actually, only want this if static is defined as ""
-- this is for usg, in which emacs must undefine static
in order to make unexec workable
*/
#ifndef STACK_DIRECTION
you
lose
-- must know STACK_DIRECTION at compile-time
#endif /* STACK_DIRECTION undefined */
#endif /* static */
#endif /* emacs */
/* If your stack is a linked list of frames, you have to
provide an "address metric" ADDRESS_FUNCTION macro. */
#if defined (CRAY) && defined (CRAY_STACKSEG_END)
long i00afunc ();
#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
#else
#define ADDRESS_FUNCTION(arg) &(arg)
#endif
#if __STDC__
typedef void *pointer;
#else
typedef char *pointer;
#endif
#define NULL 0
/* Different portions of Emacs need to call different versions of
malloc. The Emacs executable needs alloca to call xmalloc, because
ordinary malloc isn't protected from input signals. On the other
hand, the utilities in lib-src need alloca to call malloc; some of
them are very simple, and don't have an xmalloc routine.
Non-Emacs programs expect this to call use xmalloc.
Callers below should use malloc. */
/* Carsten Sorensen 09/09/97
* Commented out the following, I want malloc!
#ifndef emacs
#define malloc xmalloc
#endif
extern pointer malloc ();
And added the following line:
*/
#include <stdlib.h>
/* Define STACK_DIRECTION if you know the direction of stack
growth for your system; otherwise it will be automatically
deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
#ifndef STACK_DIRECTION
#define STACK_DIRECTION 0 /* Direction unknown. */
#endif
#if STACK_DIRECTION != 0
#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
#else /* STACK_DIRECTION == 0; need run-time code. */
static int stack_dir; /* 1 or -1 once known. */
#define STACK_DIR stack_dir
static void
find_stack_direction ()
{
static char *addr = NULL; /* Address of first `dummy', once known. */
auto char dummy; /* To get stack address. */
if (addr == NULL)
{ /* Initial entry. */
addr = ADDRESS_FUNCTION (dummy);
find_stack_direction (); /* Recurse once. */
}
else
{
/* Second entry. */
if (ADDRESS_FUNCTION (dummy) > addr)
stack_dir = 1; /* Stack grew upward. */
else
stack_dir = -1; /* Stack grew downward. */
}
}
#endif /* STACK_DIRECTION == 0 */
/* An "alloca header" is used to:
(a) chain together all alloca'ed blocks;
(b) keep track of stack depth.
It is very important that sizeof(header) agree with malloc
alignment chunk size. The following default should work okay. */
#ifndef ALIGN_SIZE
#define ALIGN_SIZE sizeof(double)
#endif
typedef union hdr
{
char align[ALIGN_SIZE]; /* To force sizeof(header). */
struct
{
union hdr *next; /* For chaining headers. */
char *deep; /* For stack depth measure. */
} h;
} header;
static header *last_alloca_header = NULL; /* -> last alloca header. */
/* Return a pointer to at least SIZE bytes of storage,
which will be automatically reclaimed upon exit from
the procedure that called alloca. Originally, this space
was supposed to be taken from the current stack frame of the
caller, but that method cannot be made to work for some
implementations of C, for example under Gould's UTX/32. */
pointer
alloca (size)
unsigned size;
{
auto char probe; /* Probes stack depth: */
register char *depth = ADDRESS_FUNCTION (probe);
#if STACK_DIRECTION == 0
if (STACK_DIR == 0) /* Unknown growth direction. */
find_stack_direction ();
#endif
/* Reclaim garbage, defined as all alloca'd storage that
was allocated from deeper in the stack than currently. */
{
register header *hp; /* Traverses linked list. */
#ifdef emacs
BLOCK_INPUT;
#endif
for (hp = last_alloca_header; hp != NULL;)
if ((STACK_DIR > 0 && hp->h.deep > depth)
|| (STACK_DIR < 0 && hp->h.deep < depth))
{
register header *np = hp->h.next;
free ((pointer) hp); /* Collect garbage. */
hp = np; /* -> next header. */
}
else
break; /* Rest are not deeper. */
last_alloca_header = hp; /* -> last valid storage. */
#ifdef emacs
UNBLOCK_INPUT;
#endif
}
if (size == 0)
return NULL; /* No allocation required. */
/* Allocate combined header + user data storage. */
{
register pointer new = malloc (sizeof (header) + size);
/* Address of header. */
((header *) new)->h.next = last_alloca_header;
((header *) new)->h.deep = depth;
last_alloca_header = (header *) new;
/* User storage begins just after header. */
return (pointer) ((char *) new + sizeof (header));
}
}
#if defined (CRAY) && defined (CRAY_STACKSEG_END)
#ifdef DEBUG_I00AFUNC
#include <stdio.h>
#endif
#ifndef CRAY_STACK
#define CRAY_STACK
#ifndef CRAY2
/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
struct stack_control_header
{
long shgrow:32; /* Number of times stack has grown. */
long shaseg:32; /* Size of increments to stack. */
long shhwm:32; /* High water mark of stack. */
long shsize:32; /* Current size of stack (all segments). */
};
/* The stack segment linkage control information occurs at
the high-address end of a stack segment. (The stack
grows from low addresses to high addresses.) The initial
part of the stack segment linkage control information is
0200 (octal) words. This provides for register storage
for the routine which overflows the stack. */
struct stack_segment_linkage
{
long ss[0200]; /* 0200 overflow words. */
long sssize:32; /* Number of words in this segment. */
long ssbase:32; /* Offset to stack base. */
long:32;
long sspseg:32; /* Offset to linkage control of previous
segment of stack. */
long:32;
long sstcpt:32; /* Pointer to task common address block. */
long sscsnm; /* Private control structure number for
microtasking. */
long ssusr1; /* Reserved for user. */
long ssusr2; /* Reserved for user. */
long sstpid; /* Process ID for pid based multi-tasking. */
long ssgvup; /* Pointer to multitasking thread giveup. */
long sscray[7]; /* Reserved for Cray Research. */
long ssa0;
long ssa1;
long ssa2;
long ssa3;
long ssa4;
long ssa5;
long ssa6;
long ssa7;
long sss0;
long sss1;
long sss2;
long sss3;
long sss4;
long sss5;
long sss6;
long sss7;
};
#else /* CRAY2 */
/* The following structure defines the vector of words
returned by the STKSTAT library routine. */
struct stk_stat
{
long now; /* Current total stack size. */
long maxc; /* Amount of contiguous space which would
be required to satisfy the maximum
stack demand to date. */
long high_water; /* Stack high-water mark. */
long overflows; /* Number of stack overflow ($STKOFEN) calls. */
long hits; /* Number of internal buffer hits. */
long extends; /* Number of block extensions. */
long stko_mallocs; /* Block allocations by $STKOFEN. */
long underflows; /* Number of stack underflow calls ($STKRETN). */
long stko_free; /* Number of deallocations by $STKRETN. */
long stkm_free; /* Number of deallocations by $STKMRET. */
long segments; /* Current number of stack segments. */
long maxs; /* Maximum number of stack segments so far. */
long pad_size; /* Stack pad size. */
long current_address; /* Current stack segment address. */
long current_size; /* Current stack segment size. This
number is actually corrupted by STKSTAT to
include the fifteen word trailer area. */
long initial_address; /* Address of initial segment. */
long initial_size; /* Size of initial segment. */
};
/* The following structure describes the data structure which trails
any stack segment. I think that the description in 'asdef' is
out of date. I only describe the parts that I am sure about. */
struct stk_trailer
{
long this_address; /* Address of this block. */
long this_size; /* Size of this block (does not include
this trailer). */
long unknown2;
long unknown3;
long link; /* Address of trailer block of previous
segment. */
long unknown5;
long unknown6;
long unknown7;
long unknown8;
long unknown9;
long unknown10;
long unknown11;
long unknown12;
long unknown13;
long unknown14;
};
#endif /* CRAY2 */
#endif /* not CRAY_STACK */
#ifdef CRAY2
/* Determine a "stack measure" for an arbitrary ADDRESS.
I doubt that "lint" will like this much. */
static long
i00afunc (long *address)
{
struct stk_stat status;
struct stk_trailer *trailer;
long *block, size;
long result = 0;
/* We want to iterate through all of the segments. The first
step is to get the stack status structure. We could do this
more quickly and more directly, perhaps, by referencing the
$LM00 common block, but I know that this works. */
STKSTAT (&status);
/* Set up the iteration. */
trailer = (struct stk_trailer *) (status.current_address
+ status.current_size
- 15);
/* There must be at least one stack segment. Therefore it is
a fatal error if "trailer" is null. */
if (trailer == 0)
abort ();
/* Discard segments that do not contain our argument address. */
while (trailer != 0)
{
block = (long *) trailer->this_address;
size = trailer->this_size;
if (block == 0 || size == 0)
abort ();
trailer = (struct stk_trailer *) trailer->link;
if ((block <= address) && (address < (block + size)))
break;
}
/* Set the result to the offset in this segment and add the sizes
of all predecessor segments. */
result = address - block;
if (trailer == 0)
{
return result;
}
do
{
if (trailer->this_size <= 0)
abort ();
result += trailer->this_size;
trailer = (struct stk_trailer *) trailer->link;
}
while (trailer != 0);
/* We are done. Note that if you present a bogus address (one
not in any segment), you will get a different number back, formed
from subtracting the address of the first block. This is probably
not what you want. */
return (result);
}
#else /* not CRAY2 */
/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
Determine the number of the cell within the stack,
given the address of the cell. The purpose of this
routine is to linearize, in some sense, stack addresses
for alloca. */
static long
i00afunc (long address)
{
long stkl = 0;
long size, pseg, this_segment, stack;
long result = 0;
struct stack_segment_linkage *ssptr;
/* Register B67 contains the address of the end of the
current stack segment. If you (as a subprogram) store
your registers on the stack and find that you are past
the contents of B67, you have overflowed the segment.
B67 also points to the stack segment linkage control
area, which is what we are really interested in. */
stkl = CRAY_STACKSEG_END ();
ssptr = (struct stack_segment_linkage *) stkl;
/* If one subtracts 'size' from the end of the segment,
one has the address of the first word of the segment.
If this is not the first segment, 'pseg' will be
nonzero. */
pseg = ssptr->sspseg;
size = ssptr->sssize;
this_segment = stkl - size;
/* It is possible that calling this routine itself caused
a stack overflow. Discard stack segments which do not
contain the target address. */
while (!(this_segment <= address && address <= stkl))
{
#ifdef DEBUG_I00AFUNC
fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
#endif
if (pseg == 0)
break;
stkl = stkl - pseg;
ssptr = (struct stack_segment_linkage *) stkl;
size = ssptr->sssize;
pseg = ssptr->sspseg;
this_segment = stkl - size;
}
result = address - this_segment;
/* If you subtract pseg from the current end of the stack,
you get the address of the previous stack segment's end.
This seems a little convoluted to me, but I'll bet you save
a cycle somewhere. */
while (pseg != 0)
{
#ifdef DEBUG_I00AFUNC
fprintf (stderr, "%011o %011o\n", pseg, size);
#endif
stkl = stkl - pseg;
ssptr = (struct stack_segment_linkage *) stkl;
size = ssptr->sssize;
pseg = ssptr->sspseg;
result += size;
}
return (result);
}
#endif /* not CRAY2 */
#endif /* CRAY */
#endif /* no alloca */
#endif /* not GCC version 2 */

411
src/ASM/FSTACK.C Normal file
View File

@@ -0,0 +1,411 @@
/*
* RGBAsm - FSTACK.C (FileStack routines)
*
* INCLUDES
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "symbol.h"
#include "fstack.h"
#include "types.h"
#include "main.h"
#include "lexer.h"
/*
* RGBAsm - FSTACK.C (FileStack routines)
*
* VARIABLES
*
*/
struct sContext *pFileStack;
struct sSymbol *pCurrentMacro;
YY_BUFFER_STATE CurrentFlexHandle;
FILE *pCurrentFile;
ULONG nCurrentStatus;
char tzCurrentFileName[_MAX_PATH + 1];
char IncludePaths[MAXINCPATHS][_MAX_PATH + 1];
SLONG NextIncPath = 0;
ULONG nMacroCount;
char *pCurrentREPTBlock;
ULONG nCurrentREPTBlockSize;
ULONG nCurrentREPTBlockCount;
ULONG ulMacroReturnValue;
/*
* defines for nCurrentStatus
*/
#define STAT_isInclude 0
#define STAT_isMacro 1
#define STAT_isMacroArg 2
#define STAT_isREPTBlock 3
ULONG filesize (char *s)
{
FILE *f;
ULONG size = 0;
if( (f=fopen(s,"rt"))!=NULL )
{
fseek (f, 0, SEEK_END);
size = ftell (f);
fclose (f);
}
return (size);
}
/*
* RGBAsm - FSTACK.C (FileStack routines)
*
* Context push and pop
*
*/
void pushcontext (void)
{
struct sContext **ppFileStack;
ppFileStack = &pFileStack;
while (*ppFileStack)
ppFileStack = &((*ppFileStack)->pNext);
if( (*ppFileStack=(struct sContext *)malloc(sizeof (struct sContext)))!=NULL )
{
(*ppFileStack)->FlexHandle = CurrentFlexHandle;
(*ppFileStack)->pNext = NULL;
strcpy ( (char *)(*ppFileStack)->tzFileName, (char *)tzCurrentFileName);
(*ppFileStack)->nLine = nLineNo;
switch ((*ppFileStack)->nStatus = nCurrentStatus)
{
case STAT_isMacroArg:
case STAT_isMacro:
sym_SaveCurrentMacroArgs ((*ppFileStack)->tzMacroArgs);
(*ppFileStack)->pMacro = pCurrentMacro;
break;
case STAT_isInclude:
(*ppFileStack)->pFile = pCurrentFile;
break;
case STAT_isREPTBlock:
sym_SaveCurrentMacroArgs ((*ppFileStack)->tzMacroArgs);
(*ppFileStack)->pREPTBlock = pCurrentREPTBlock;
(*ppFileStack)->nREPTBlockSize = nCurrentREPTBlockSize;
(*ppFileStack)->nREPTBlockCount = nCurrentREPTBlockCount;
break;
}
nLineNo = 0;
}
else
fatalerror ("No memory for context");
}
int popcontext (void)
{
struct sContext *pLastFile,
**ppLastFile;
if (nCurrentStatus == STAT_isREPTBlock)
{
if (--nCurrentREPTBlockCount)
{
yy_delete_buffer (CurrentFlexHandle);
CurrentFlexHandle = yy_scan_bytes (pCurrentREPTBlock, nCurrentREPTBlockSize);
yy_switch_to_buffer (CurrentFlexHandle);
sym_UseCurrentMacroArgs ();
sym_SetMacroArgID (nMacroCount++);
sym_UseNewMacroArgs ();
return (0);
}
}
if( (pLastFile=pFileStack)!=NULL )
{
ppLastFile = &pFileStack;
while (pLastFile->pNext)
{
ppLastFile = &(pLastFile->pNext);
pLastFile = *ppLastFile;
}
yy_delete_buffer (CurrentFlexHandle);
nLineNo = pLastFile->nLine;
if (nCurrentStatus == STAT_isInclude)
fclose (pCurrentFile);
if (nCurrentStatus == STAT_isMacro)
{
sym_FreeCurrentMacroArgs ();
nLineNo += 1;
}
if (nCurrentStatus == STAT_isREPTBlock)
nLineNo += 1;
CurrentFlexHandle = pLastFile->FlexHandle;
strcpy ((char *)tzCurrentFileName, (char *)pLastFile->tzFileName);
switch (nCurrentStatus = pLastFile->nStatus)
{
case STAT_isMacroArg:
case STAT_isMacro:
sym_RestoreCurrentMacroArgs (pLastFile->tzMacroArgs);
pCurrentMacro = pLastFile->pMacro;
break;
case STAT_isInclude:
pCurrentFile = pLastFile->pFile;
break;
case STAT_isREPTBlock:
sym_RestoreCurrentMacroArgs (pLastFile->tzMacroArgs);
pCurrentREPTBlock = pLastFile->pREPTBlock;
nCurrentREPTBlockSize = pLastFile->nREPTBlockSize;
nCurrentREPTBlockCount = pLastFile->nREPTBlockCount;
break;
}
free (*ppLastFile);
*ppLastFile = NULL;
yy_switch_to_buffer (CurrentFlexHandle);
return (0);
}
else
return (1);
}
int yywrap (void)
{
return (popcontext ());
}
/*
* RGBAsm - FSTACK.C (FileStack routines)
*
* Dump the context stack to stdout
*
*/
void fstk_Dump (void)
{
struct sContext *pLastFile;
pLastFile = pFileStack;
while (pLastFile)
{
printf ("%s(%ld) -> ", pLastFile->tzFileName, pLastFile->nLine);
pLastFile = pLastFile->pNext;
}
printf ("%s(%ld)", tzCurrentFileName, nLineNo);
}
/*
* RGBAsm - FSTACK.C (FileStack routines)
*
* Extra includepath stuff
*
*/
void fstk_AddIncludePath (char *s)
{
strcpy (IncludePaths[NextIncPath++], s);
}
void fstk_FindFile (char *s)
{
char t[_MAX_PATH + 1];
SLONG i = -1;
strcpy (t, s);
while (i < NextIncPath)
{
FILE *f;
if( (f=fopen(t,"rb"))!=NULL )
{
fclose (f);
strcpy (s, t);
return;
}
i += 1;
if (i < NextIncPath)
{
strcpy (t, IncludePaths[i]);
strcat (t, s);
}
}
}
/*
* RGBAsm - FSTACK.C (FileStack routines)
*
* Set up an include file for parsing
*
*/
ULONG fstk_RunInclude (char *s)
{
FILE *f;
char tzFileName[_MAX_PATH + 1];
//printf( "INCLUDE: %s\n", s );
strcpy (tzFileName, s);
fstk_FindFile (tzFileName);
//printf( "INCLUDING: %s\n", tzFileName );
if( (f=fopen(tzFileName,"rt"))!=NULL )
{
pushcontext ();
nLineNo = 1;
nCurrentStatus = STAT_isInclude;
strcpy (tzCurrentFileName, tzFileName);
pCurrentFile = f;
CurrentFlexHandle = yy_create_buffer (pCurrentFile);
yy_switch_to_buffer (CurrentFlexHandle);
// Dirty hack to give the INCLUDE directive a linefeed
yyunput( '\n' );
nLineNo-=1;
return (1);
}
else
return (0);
}
/*
* RGBAsm - FSTACK.C (FileStack routines)
*
* Set up a macro for parsing
*
*/
ULONG fstk_RunMacro (char *s)
{
struct sSymbol *sym;
if( (sym=sym_FindMacro(s))!=NULL )
{
pushcontext ();
sym_SetMacroArgID (nMacroCount++);
nLineNo = -1;
sym_UseNewMacroArgs ();
nCurrentStatus = STAT_isMacro;
strcpy (tzCurrentFileName, s);
pCurrentMacro = sym;
CurrentFlexHandle = yy_scan_bytes (pCurrentMacro->pMacro, pCurrentMacro->ulMacroSize);
yy_switch_to_buffer (CurrentFlexHandle);
return (1);
}
else
return (0);
}
/*
* RGBAsm - FSTACK.C (FileStack routines)
*
* Set up a macroargument for parsing
*
*/
void fstk_RunMacroArg (SLONG s)
{
char *sym;
if (s == '@')
s = -1;
else
s -= '0';
if( (sym=sym_FindMacroArg(s))!=NULL )
{
pushcontext ();
nCurrentStatus = STAT_isMacroArg;
sprintf (tzCurrentFileName, "%c", (UBYTE)s);
CurrentFlexHandle = yy_scan_bytes (sym, strlen (sym));
yy_switch_to_buffer (CurrentFlexHandle);
}
else
fatalerror ("No such macroargument");
}
/*
* RGBAsm - FSTACK.C (FileStack routines)
*
* Set up a stringequate for parsing
*
*/
void fstk_RunString (char *s)
{
struct sSymbol *pSym;
if( (pSym=sym_FindSymbol(s))!=NULL )
{
pushcontext ();
nCurrentStatus = STAT_isMacroArg;
strcpy (tzCurrentFileName, s);
CurrentFlexHandle = yy_scan_bytes (pSym->pMacro, strlen (pSym->pMacro));
yy_switch_to_buffer (CurrentFlexHandle);
}
else
yyerror ("No such string symbol");
}
/*
* RGBAsm - FSTACK.C (FileStack routines)
*
* Set up a repeat block for parsing
*
*/
void fstk_RunRept (ULONG count)
{
if (count)
{
pushcontext ();
sym_UseCurrentMacroArgs ();
sym_SetMacroArgID (nMacroCount++);
sym_UseNewMacroArgs ();
nCurrentREPTBlockCount = count;
nCurrentStatus = STAT_isREPTBlock;
nCurrentREPTBlockSize = ulNewMacroSize;
pCurrentREPTBlock = tzNewMacro;
CurrentFlexHandle = yy_scan_bytes (pCurrentREPTBlock, nCurrentREPTBlockSize);
yy_switch_to_buffer (CurrentFlexHandle);
}
}
/*
* RGBAsm - FSTACK.C (FileStack routines)
*
* Initialize the filestack routines
*
*/
ULONG fstk_Init (char *s)
{
char tzFileName[_MAX_PATH + 1];
sym_AddString ("__FILE__", s);
strcpy (tzFileName, s);
fstk_FindFile (tzFileName);
pFileStack = NULL;
if( (pCurrentFile=fopen(tzFileName,"rt"))!=NULL )
{
nMacroCount = 0;
nCurrentStatus = STAT_isInclude;
strcpy (tzCurrentFileName, tzFileName);
CurrentFlexHandle = yy_create_buffer (pCurrentFile);
yy_switch_to_buffer (CurrentFlexHandle);
nLineNo = 1;
return (1);
}
else
return (0);
}

154
src/ASM/GAMEBOY/LOCALASM.H Normal file
View File

@@ -0,0 +1,154 @@
/* GB Z80 instruction groups
n3 = 3-bit
n = 8-bit
nn = 16-bit
*ADC A,n : 0xCE
*ADC A,r : 0x88|r
*ADD A,n : 0xC6
*ADD A,r : 0x80|r
*ADD HL,ss : 0x09|(ss<<4)
*ADD SP,n : 0xE8
*AND A,n : 0xE6
*AND A,r : 0xA0|r
*BIT n3,r : 0xCB 0x40|(n3<<3)|r
*CALL cc,nn : 0xC4|(cc<<3)
*CALL nn : 0xCD
*CCF : 0x3F
*CP A,n : 0xFE
*CP A,r : 0xB8|r
*CPL : 0x2F
*DAA : 0x27
*DEC r : 0x05|(r<<3)
*DEC ss : 0x0B|(ss<<4)
*DI : 0xF3
*EI : 0xFB
*EX HL,(SP) : 0xE3
*HALT : 0x76
*INC r : 0x04|(r<<3)
*INC ss : 0x03|(ss<<4)
*JP (HL) : 0xE9
*JP cc,nn : 0xC2|(cc<<3)
*JP nn : 0xC3|(cc<<3)
*JR n : 0x18
*JR cc,n : 0x20|(cc<<3)
*LD (nn),SP : 0x08
*LD ($FF00+C),A : 0xE2
*LD ($FF00+n),A : 0xE0
*LD (nn),A : 0xEA
*LD (rr),A : 0x02|(rr<<4)
*LD A,($FF00+C) : 0xF2
*LD A,($FF00+n) : 0xF0
*LD A,(nn) : 0xFA
*LD A,(rr) : 0x0A|(rr<<4)
*LD HL,(SP+n) : 0xF8
*LD SP,HL : 0xF9
*LD r,n : 0x06|(r<<3)
*LD r,r' : 0x40|(r<<3)|r' // NOTE: LD (HL),(HL) not allowed
*LD ss,nn : 0x01|(ss<<4)
*NOP : 0x00
*OR A,n : 0xF6
*OR A,r : 0xB0|r
*POP tt : 0xC1|(tt<<4)
*PUSH tt : 0xC5|(tt<<4)
*RES n3,r : 0xCB 0x80|(n3<<3)|r
*RET : 0xC9
*RET cc : 0xC0|(cc<<3)
*RETI : 0xD9
*RL r : 0xCB 0x10|r
*RLA : 0x17
*RLC r : 0xCB 0x00|r
*RLCA : 0x07
*RR r : 0xCB 0x18|r
*RRA : 0x1F
*RRC r : 0xCB 0x08|r
*RRCA : 0x0F
*RST n : 0xC7|n
*SBC A,n : 0xDE
*SBC A,r : 0x98|r
*SCF : 0x37
*SET n3,r : 0xCB 0xC0|(n8<<3)|r
*SLA r : 0xCB 0x20|r
*SRA r : 0xCB 0x28|r
*SRL r : 0xCB 0x38|r
*STOP : 0x10
*SUB A,n : 0xD6
*SUB A,r : 0x90|r
*SWAP r : 0xCB 0x30|r
*XOR A,n : 0xEE
*XOR A,r : 0xA8|r
*/
#define MAXSECTIONSIZE 0x4000
#define ASM_DEFAULT_ENDIAN ASM_LITTLE_ENDIAN
#define APPNAME "RGBAsm"
#define EXENAME "rgbasm"
#define NAME_DB "db"
#define NAME_DW "dw"
#define NAME_RB "rb"
#define NAME_RW "rw"
/* "r" defs */
enum
{
REG_B=0,
REG_C,
REG_D,
REG_E,
REG_H,
REG_L,
REG_HL_IND,
REG_A
};
/* "rr" defs */
enum
{
REG_BC_IND=0,
REG_DE_IND,
REG_HL_INDINC,
REG_HL_INDDEC,
};
/* "ss" defs */
enum
{
REG_BC=0,
REG_DE,
REG_HL,
REG_SP
};
/* "tt" defs */
/*
#define REG_BC 0
#define REG_DE 1
#define REG_HL 2
*/
#define REG_AF 3
/* "cc" defs */
enum
{
CC_NZ=0,
CC_Z,
CC_NC,
CC_C
};

View File

@@ -0,0 +1,89 @@
#include "symbol.h"
#include "lexer.h"
#include "rpn.h"
#include "asmy.h"
struct sLexInitString localstrings[] =
{
"adc", T_Z80_ADC,
"add", T_Z80_ADD,
"and", T_Z80_AND,
"bit", T_Z80_BIT,
"call", T_Z80_CALL,
"ccf", T_Z80_CCF,
"cpl", T_Z80_CPL,
"cp", T_Z80_CP,
"daa", T_Z80_DAA,
"dec", T_Z80_DEC,
"di", T_Z80_DI,
"ei", T_Z80_EI,
"ex", T_Z80_EX,
"halt", T_Z80_HALT,
"inc", T_Z80_INC,
"jp", T_Z80_JP,
"jr", T_Z80_JR,
"ld", T_Z80_LD,
"ldi", T_Z80_LDI,
"ldd", T_Z80_LDD,
"ldio", T_Z80_LDIO,
"ldh", T_Z80_LDIO,
"nop", T_Z80_NOP,
"or", T_Z80_OR,
"pop", T_Z80_POP,
"push", T_Z80_PUSH,
"res", T_Z80_RES,
"reti", T_Z80_RETI,
"ret", T_Z80_RET,
"rlca", T_Z80_RLCA,
"rlc", T_Z80_RLC,
"rla", T_Z80_RLA,
"rl", T_Z80_RL,
"rrc", T_Z80_RRC,
"rrca", T_Z80_RRCA,
"rra", T_Z80_RRA,
"rr", T_Z80_RR,
"rst", T_Z80_RST,
"sbc", T_Z80_SBC,
"scf", T_Z80_SCF,
// Handled by globallex.c
// "set" , T_POP_SET,
"sla", T_Z80_SLA,
"sra", T_Z80_SRA,
"srl", T_Z80_SRL,
"stop", T_Z80_STOP,
"sub", T_Z80_SUB,
"swap", T_Z80_SWAP,
"xor", T_Z80_XOR,
"nz", T_CC_NZ,
"z", T_CC_Z,
"nc", T_CC_NC,
// "c" , T_MODE_C
"[hl]", T_MODE_HL_IND,
"[hl+]", T_MODE_HL_INDINC,
"[hl-]", T_MODE_HL_INDDEC,
"[hli]", T_MODE_HL_INDINC,
"[hld]", T_MODE_HL_INDDEC,
"hl", T_MODE_HL,
"af", T_MODE_AF,
"[bc]", T_MODE_BC_IND,
"bc", T_MODE_BC,
"[de]", T_MODE_DE_IND,
"de", T_MODE_DE,
"[sp]", T_MODE_SP_IND,
"sp", T_MODE_SP,
"a", T_MODE_A,
"b", T_MODE_B,
"[$ff00+c]", T_MODE_C_IND,
"[c]", T_MODE_C_IND,
"c", T_MODE_C,
"d", T_MODE_D,
"e", T_MODE_E,
"h", T_MODE_H,
"l", T_MODE_L,
NULL, 0
};

18
src/ASM/GAMEBOY/MAKEFILE Normal file
View File

@@ -0,0 +1,18 @@
.ERASE
.EXTENSIONS:
.EXTENSIONS: .obj .c .l .y .h
!include ..\MAKEINIT
!ifeq TARGET DOS
EXE = rgbasm.exe
!endif
!ifeq TARGET WIN95
EXE = rgbasm95.exe
!endif
TARGET_SYSTEM = GAMEBOY
!include ..\STDMAKE

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.

View File

@@ -0,0 +1,41 @@
%token T_SECT_BSS T_SECT_VRAM T_SECT_CODE T_SECT_HOME T_SECT_HRAM
%token T_Z80_ADC T_Z80_ADD T_Z80_AND
%token T_Z80_BIT
%token T_Z80_CALL T_Z80_CCF T_Z80_CP T_Z80_CPL
%token T_Z80_DAA T_Z80_DEC T_Z80_DI
%token T_Z80_EI T_Z80_EX
%token T_Z80_HALT
%token T_Z80_INC
%token T_Z80_JP T_Z80_JR
%token T_Z80_LD
%token T_Z80_LDI
%token T_Z80_LDD
%token T_Z80_LDIO
%token T_Z80_NOP
%token T_Z80_OR
%token T_Z80_POP T_Z80_PUSH
%token T_Z80_RES T_Z80_RET T_Z80_RETI T_Z80_RST
%token T_Z80_RL T_Z80_RLA T_Z80_RLC T_Z80_RLCA
%token T_Z80_RR T_Z80_RRA T_Z80_RRC T_Z80_RRCA
%token T_Z80_SBC T_Z80_SCF T_Z80_STOP
%token T_Z80_SLA T_Z80_SRA T_Z80_SRL T_Z80_SUB T_Z80_SWAP
%token T_Z80_XOR
%token T_MODE_A T_MODE_B T_MODE_C T_MODE_C_IND T_MODE_D T_MODE_E T_MODE_H T_MODE_L
%token T_MODE_AF
%token T_MODE_BC T_MODE_BC_IND
%token T_MODE_DE T_MODE_DE_IND
%token T_MODE_SP T_MODE_SP_IND
%token T_MODE_HL T_MODE_HL_IND T_MODE_HL_INDDEC T_MODE_HL_INDINC
%token T_CC_NZ T_CC_Z T_CC_NC
%type <nConstValue> reg_r
%type <nConstValue> reg_ss
%type <nConstValue> reg_rr
%type <nConstValue> reg_tt
%type <nConstValue> ccode
%type <sVal> op_a_n
%type <nConstValue> op_a_r
%type <nConstValue> op_hl_ss
%type <sVal> op_mem_ind

498
src/ASM/GAMEBOY/YACCPRT4.Y Normal file
View File

@@ -0,0 +1,498 @@
section : T_POP_SECTION string ',' sectiontype
{ out_NewSection($2,$4); }
| T_POP_SECTION string ',' sectiontype '[' const ']'
{
if( $6>=0 && $6<0x10000 )
out_NewAbsSection($2,$4,$6,-1);
else
yyerror( "Address must be 16-bit" );
}
| T_POP_SECTION string ',' sectiontype ',' T_OP_BANK '[' const ']'
{
if( $4==SECT_CODE )
{
if( $8>=1 && $8<=255 )
out_NewAbsSection($2,$4,-1,$8);
else
yyerror( "BANK value out of range" );
}
else
yyerror( "BANK only allowed for CODE/DATA" );
}
| T_POP_SECTION string ',' sectiontype '[' const ']' ',' T_OP_BANK '[' const ']'
{
if( $4==SECT_CODE )
{
if( $6>=0 && $6<0x10000 )
{
if( $11>=1 && $11<=255 )
out_NewAbsSection($2,$4,$6,$11);
else
yyerror( "BANK value out of range" );
}
else
yyerror( "Address must be 16-bit" );
}
else
yyerror( "BANK only allowed for CODE/DATA" );
}
;
sectiontype : T_SECT_BSS { $$=SECT_BSS; }
| T_SECT_VRAM { $$=SECT_VRAM; }
| T_SECT_CODE { $$=SECT_CODE; }
| T_SECT_HOME { $$=SECT_HOME; }
| T_SECT_HRAM { $$=SECT_HRAM; }
;
cpu_command : z80_adc
| z80_add
| z80_and
| z80_bit
| z80_call
| z80_ccf
| z80_cp
| z80_cpl
| z80_daa
| z80_dec
| z80_di
| z80_ei
| z80_ex
| z80_halt
| z80_inc
| z80_jp
| z80_jr
| z80_ld
| z80_ldd
| z80_ldi
| z80_ldio
| z80_nop
| z80_or
| z80_pop
| z80_push
| z80_res
| z80_ret
| z80_reti
| z80_rl
| z80_rla
| z80_rlc
| z80_rlca
| z80_rr
| z80_rra
| z80_rrc
| z80_rrca
| z80_rst
| z80_sbc
| z80_scf
| z80_set
| z80_sla
| z80_sra
| z80_srl
| z80_stop
| z80_sub
| z80_swap
| z80_xor
;
z80_adc : T_Z80_ADC op_a_n { out_AbsByte(0xCE); out_RelByte(&$2); }
| T_Z80_ADC op_a_r { out_AbsByte(0x88|$2); }
;
z80_add : T_Z80_ADD op_a_n { out_AbsByte(0xC6); out_RelByte(&$2); }
| T_Z80_ADD op_a_r { out_AbsByte(0x80|$2); }
| T_Z80_ADD op_hl_ss { out_AbsByte(0x09|($2<<4)); }
| T_Z80_ADD T_MODE_SP comma const_8bit
{ out_AbsByte(0xE8); out_RelByte(&$4); }
;
z80_and : T_Z80_AND op_a_n { out_AbsByte(0xE6); out_RelByte(&$2); }
| T_Z80_AND op_a_r { out_AbsByte(0xA0|$2); }
;
z80_bit : T_Z80_BIT const_3bit comma reg_r
{ out_AbsByte(0xCB); out_AbsByte(0x40|($2<<3)|$4); }
;
z80_call : T_Z80_CALL const_16bit
{ out_AbsByte(0xCD); out_RelWord(&$2); }
| T_Z80_CALL ccode comma const_16bit
{ out_AbsByte(0xC4|($2<<3)); out_RelWord(&$4); }
;
z80_ccf : T_Z80_CCF
{ out_AbsByte(0x3F); }
;
z80_cp : T_Z80_CP op_a_n { out_AbsByte(0xFE); out_RelByte(&$2); }
| T_Z80_CP op_a_r { out_AbsByte(0xB8|$2); }
;
z80_cpl : T_Z80_CPL { out_AbsByte(0x2F); }
;
z80_daa : T_Z80_DAA { out_AbsByte(0x27); }
;
z80_dec : T_Z80_DEC reg_r
{ out_AbsByte(0x05|($2<<3)); }
| T_Z80_DEC reg_ss
{ out_AbsByte(0x0B|($2<<4)); }
;
z80_di : T_Z80_DI
{ out_AbsByte(0xF3); }
;
z80_ei : T_Z80_EI
{ out_AbsByte(0xFB); }
;
z80_ex : T_Z80_EX T_MODE_HL comma T_MODE_SP_IND
{ out_AbsByte(0xE3); }
| T_Z80_EX T_MODE_SP_IND comma T_MODE_HL
{ out_AbsByte(0xE3); }
;
z80_halt : T_Z80_HALT
{ out_AbsByte(0x76); out_AbsByte(0x00); }
;
z80_inc : T_Z80_INC reg_r
{ out_AbsByte(0x04|($2<<3)); }
| T_Z80_INC reg_ss
{ out_AbsByte(0x03|($2<<4)); }
;
z80_jp : T_Z80_JP const_16bit
{ out_AbsByte(0xC3); out_RelWord(&$2); }
| T_Z80_JP ccode comma const_16bit
{ out_AbsByte(0xC2|($2<<3)); out_RelWord(&$4); }
| T_Z80_JP T_MODE_HL_IND
{ out_AbsByte(0xE9); }
;
z80_jr : T_Z80_JR const_PCrel
{ out_AbsByte(0x18); out_PCRelByte(&$2); }
| T_Z80_JR ccode comma const_PCrel
{ out_AbsByte(0x20|($2<<3)); out_PCRelByte(&$4); }
;
z80_ldi : T_Z80_LDI T_MODE_HL_IND comma T_MODE_A
{ out_AbsByte(0x02|(2<<4)); }
| T_Z80_LDI T_MODE_A comma T_MODE_HL
{ out_AbsByte(0x0A|(2<<4)); }
;
z80_ldd : T_Z80_LDD T_MODE_HL_IND comma T_MODE_A
{ out_AbsByte(0x02|(3<<4)); }
| T_Z80_LDD T_MODE_A comma T_MODE_HL
{ out_AbsByte(0x0A|(3<<4)); }
;
z80_ldio : T_Z80_LDIO T_MODE_A comma op_mem_ind
{
rpn_CheckHRAM(&$4,&$4);
if( (!rpn_isReloc(&$4))
&& ($4.nVal<0 || ($4.nVal>0xFF && $4.nVal<0xFF00) || $4.nVal>0xFFFF) )
{
yyerror( "Source must be in the IO/HRAM area" );
}
out_AbsByte(0xF0);
$4.nVal&=0xFF;
out_RelByte(&$4);
}
| T_Z80_LDIO op_mem_ind comma T_MODE_A
{
rpn_CheckHRAM(&$2,&$2);
if( (!rpn_isReloc(&$2))
&& ($2.nVal<0 || ($2.nVal>0xFF && $2.nVal<0xFF00) || $2.nVal>0xFFFF) )
{
yyerror( "Destination must be in the IO/HRAM area" );
}
out_AbsByte(0xE0);
$2.nVal&=0xFF;
out_RelByte(&$2);
}
;
z80_ld : z80_ld_mem
| z80_ld_cind
| z80_ld_rr
| z80_ld_ss
| z80_ld_hl
| z80_ld_sp
| z80_ld_r
| z80_ld_a
;
z80_ld_hl : T_Z80_LD T_MODE_HL comma '[' T_MODE_SP const_8bit ']'
{ out_AbsByte(0xF8); out_RelByte(&$6); }
| T_Z80_LD T_MODE_HL comma const_16bit
{ out_AbsByte(0x01|(REG_HL<<4)); out_RelWord(&$4) }
;
z80_ld_sp : T_Z80_LD T_MODE_SP comma T_MODE_HL
{ out_AbsByte(0xF9); }
| T_Z80_LD T_MODE_SP comma const_16bit
{ out_AbsByte(0x01|(REG_SP<<4)); out_RelWord(&$4) }
;
z80_ld_mem : T_Z80_LD op_mem_ind comma T_MODE_SP
{ out_AbsByte(0x08); out_RelWord(&$2); }
| T_Z80_LD op_mem_ind comma T_MODE_A
{
if( (!rpn_isReloc(&$2)) && $2.nVal>=0xFF00)
{
out_AbsByte(0xE0);
out_AbsByte($2.nVal&0xFF);
}
else
{
out_AbsByte(0xEA);
out_RelWord(&$2);
}
}
;
z80_ld_cind : T_Z80_LD T_MODE_C_IND comma T_MODE_A
{ out_AbsByte(0xE2); }
;
z80_ld_rr : T_Z80_LD reg_rr comma T_MODE_A
{ out_AbsByte(0x02|($2<<4)); }
;
z80_ld_r : T_Z80_LD reg_r comma const_8bit
{ out_AbsByte(0x06|($2<<3)); out_RelByte(&$4); }
| T_Z80_LD reg_r comma reg_r
{
if( ($2==REG_HL_IND) && ($4==REG_HL_IND) )
{
yyerror( "LD (HL),(HL) not allowed" );
}
else
out_AbsByte(0x40|($2<<3)|$4);
}
;
z80_ld_a : T_Z80_LD reg_r comma T_MODE_C_IND
{
if( $2==REG_A )
out_AbsByte(0xF2);
else
{
yyerror( "Destination operand must be A" );
}
}
| T_Z80_LD reg_r comma reg_rr
{
if( $2==REG_A )
out_AbsByte(0x0A|($4<<4));
else
{
yyerror( "Destination operand must be A" );
}
}
| T_Z80_LD reg_r comma op_mem_ind
{
if( $2==REG_A )
{
if( (!rpn_isReloc(&$4)) && $4.nVal>=0xFF00 )
{
out_AbsByte(0xF0);
out_AbsByte($4.nVal&0xFF);
}
else
{
out_AbsByte(0xFA);
out_RelWord(&$4);
}
}
else
{
yyerror( "Destination operand must be A" );
}
}
;
z80_ld_ss : T_Z80_LD reg_ss comma const_16bit
{ out_AbsByte(0x01|($2<<4)); out_RelWord(&$4) }
;
z80_nop : T_Z80_NOP
{ out_AbsByte(0x00); }
;
z80_or : T_Z80_OR op_a_n
{ out_AbsByte(0xF6); out_RelByte(&$2); }
| T_Z80_OR op_a_r
{ out_AbsByte(0xB0|$2); }
;
z80_pop : T_Z80_POP reg_tt
{ out_AbsByte(0xC1|($2<<4)); }
;
z80_push : T_Z80_PUSH reg_tt
{ out_AbsByte(0xC5|($2<<4)); }
;
z80_res : T_Z80_RES const_3bit comma reg_r
{ out_AbsByte(0xCB); out_AbsByte(0x80|($2<<3)|$4); }
;
z80_ret : T_Z80_RET
{ out_AbsByte(0xC9); }
| T_Z80_RET ccode
{ out_AbsByte(0xC0|($2<<3)); }
;
z80_reti : T_Z80_RETI
{ out_AbsByte(0xD9); }
;
z80_rl : T_Z80_RL reg_r
{ out_AbsByte(0xCB); out_AbsByte(0x10|$2); }
;
z80_rla : T_Z80_RLA
{ out_AbsByte(0x17); }
;
z80_rlc : T_Z80_RLC reg_r
{ out_AbsByte(0xCB); out_AbsByte(0x00|$2); }
;
z80_rlca : T_Z80_RLCA
{ out_AbsByte(0x07); }
;
z80_rr : T_Z80_RR reg_r
{ out_AbsByte(0xCB); out_AbsByte(0x18|$2); }
;
z80_rra : T_Z80_RRA
{ out_AbsByte(0x1F); }
;
z80_rrc : T_Z80_RRC reg_r
{ out_AbsByte(0xCB); out_AbsByte(0x08|$2); }
;
z80_rrca : T_Z80_RRCA
{ out_AbsByte(0x0F); }
;
z80_rst : T_Z80_RST const_8bit
{
if( rpn_isReloc(&$2) )
{
yyerror( "Address for RST must be absolute" );
}
else if( ($2.nVal&0x38)!=$2.nVal )
{
yyerror( "Invalid address for RST" );
}
else
out_AbsByte(0xC7|$2.nVal);
}
;
z80_sbc : T_Z80_SBC op_a_n { out_AbsByte(0xDE); out_RelByte(&$2); }
| T_Z80_SBC op_a_r { out_AbsByte(0x98|$2); }
;
z80_scf : T_Z80_SCF
{ out_AbsByte(0x37); }
;
z80_set : T_POP_SET const_3bit comma reg_r
{ out_AbsByte(0xCB); out_AbsByte(0xC0|($2<<3)|$4); }
;
z80_sla : T_Z80_SLA reg_r
{ out_AbsByte(0xCB); out_AbsByte(0x20|$2); }
;
z80_sra : T_Z80_SRA reg_r
{ out_AbsByte(0xCB); out_AbsByte(0x28|$2); }
;
z80_srl : T_Z80_SRL reg_r
{ out_AbsByte(0xCB); out_AbsByte(0x38|$2); }
;
z80_stop : T_Z80_STOP
{ out_AbsByte(0x10); out_AbsByte(0x00); }
;
z80_sub : T_Z80_SUB op_a_n { out_AbsByte(0xD6); out_RelByte(&$2); }
| T_Z80_SUB op_a_r { out_AbsByte(0x90|$2); }
;
z80_swap : T_Z80_SWAP reg_r
{ out_AbsByte(0xCB); out_AbsByte(0x30|$2); }
;
z80_xor : T_Z80_XOR op_a_n { out_AbsByte(0xEE); out_RelByte(&$2); }
| T_Z80_XOR op_a_r { out_AbsByte(0xA8|$2); }
;
op_mem_ind : '[' const_16bit ']' { $$ = $2 }
;
op_hl_ss : reg_ss { $$ = $1 }
| T_MODE_HL comma reg_ss { $$ = $3 }
;
op_a_r : reg_r { $$ = $1 }
| T_MODE_A comma reg_r { $$ = $3 }
;
op_a_n : const_8bit { $$ = $1 }
| T_MODE_A comma const_8bit { $$ = $3 }
;
comma : ','
;
ccode : T_CC_NZ { $$ = CC_NZ }
| T_CC_Z { $$ = CC_Z }
| T_CC_NC { $$ = CC_NC }
| T_MODE_C { $$ = CC_C }
;
reg_r : T_MODE_B { $$ = REG_B }
| T_MODE_C { $$ = REG_C }
| T_MODE_D { $$ = REG_D }
| T_MODE_E { $$ = REG_E }
| T_MODE_H { $$ = REG_H }
| T_MODE_L { $$ = REG_L }
| T_MODE_HL_IND { $$ = REG_HL_IND }
| T_MODE_A { $$ = REG_A }
;
reg_tt : T_MODE_BC { $$ = REG_BC }
| T_MODE_DE { $$ = REG_DE }
| T_MODE_HL { $$ = REG_HL }
| T_MODE_AF { $$ = REG_AF }
;
reg_ss : T_MODE_BC { $$ = REG_BC }
| T_MODE_DE { $$ = REG_DE }
| T_MODE_HL { $$ = REG_HL }
| T_MODE_SP { $$ = REG_SP }
;
reg_rr : T_MODE_BC_IND { $$ = REG_BC_IND }
| T_MODE_DE_IND { $$ = REG_DE_IND }
| T_MODE_HL_INDINC { $$ = REG_HL_INDINC }
| T_MODE_HL_INDDEC { $$ = REG_HL_INDDEC }
;
%%

513
src/ASM/GLOBLEX.C Normal file
View File

@@ -0,0 +1,513 @@
#include "asm.h"
#include "symbol.h"
#include "rpn.h"
#include "asmy.h"
#include "symbol.h"
#include "main.h"
#include "lexer.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
UBYTE oDontExpandStrings=0;
SLONG nGBGfxID=-1;
SLONG nBinaryID=-1;
SLONG gbgfx2bin (char ch)
{
SLONG i;
for( i=0; i<=3; i+=1 )
{
if( CurrentOptions.gbgfx[i]==ch )
{
return( i );
}
}
return (0);
}
SLONG binary2bin (char ch)
{
SLONG i;
for( i=0; i<=1; i+=1 )
{
if( CurrentOptions.binary[i]==ch )
{
return( i );
}
}
return (0);
}
SLONG char2bin (char ch)
{
if (ch >= 'a' && ch <= 'f')
return (ch - 'a' + 10);
if (ch >= 'A' && ch <= 'F')
return (ch - 'A' + 10);
if (ch >= '0' && ch <= '9')
return (ch - '0');
return (0);
}
typedef SLONG (*x2bin)(char ch);
SLONG ascii2bin (char *s)
{
SLONG radix = 10;
SLONG result = 0;
x2bin convertfunc=char2bin;
switch (*s)
{
case '$':
radix = 16;
s += 1;
convertfunc=char2bin;
break;
case '&':
radix = 8;
s += 1;
convertfunc=char2bin;
break;
case '`':
radix = 4;
s += 1;
convertfunc=gbgfx2bin;
break;
case '%':
radix = 2;
s += 1;
convertfunc=binary2bin;
break;
}
if (radix == 4)
{
SLONG c;
while (*s != '\0')
{
c = convertfunc (*s++);
result = result * 2 + ((c & 1) << 8) + ((c & 2) >> 1);
}
}
else
{
while (*s != '\0')
result = result * radix + convertfunc (*s++);
}
return (result);
}
ULONG ParseFixedPoint (char *s, ULONG size)
{
char dest[256];
ULONG i = 0,
dot = 0;
while (size && dot != 2)
{
if (s[i] == '.')
dot += 1;
if (dot < 2)
{
dest[i] = s[i];
size -= 1;
i += 1;
}
}
dest[i] = 0;
yyunputbytes (size);
yylval.nConstValue = (SLONG) (atof (s) * 65536);
return (1);
}
ULONG ParseNumber (char *s, ULONG size)
{
char dest[256];
strncpy (dest, s, size);
dest[size] = 0;
yylval.nConstValue = ascii2bin (dest);
return (1);
}
ULONG ParseSymbol (char *src, ULONG size)
{
char dest[MAXSYMLEN + 1];
int copied = 0,
size_backup = size;
while (size && copied < MAXSYMLEN)
{
if (*src == '\\')
{
char *marg;
src += 1;
size -= 1;
if (*src == '@')
marg = sym_FindMacroArg (-1);
else if (*src >= '0' && *src <= '9')
marg = sym_FindMacroArg (*src);
else
{
fatalerror ("Malformed ID");
return(0);
}
src += 1;
size -= 1;
if (marg)
{
while (*marg)
dest[copied++] = *marg++;
}
}
else
{
dest[copied++] = *src++;
size -= 1;
}
}
if (copied > MAXSYMLEN)
fatalerror ("Symbol too long");
dest[copied] = 0;
if( oDontExpandStrings==0
&& sym_isString(dest) )
{
char *s;
yyskipbytes( size_backup );
yyunputstr( s=sym_GetStringValue(dest) );
while( *s )
{
if( *s++=='\n' )
{
nLineNo-=1;
}
}
return (0);
}
else
{
strcpy( yylval.tzString, dest );
return (1);
}
}
ULONG PutMacroArg (char *src, ULONG size)
{
char *s;
yyskipbytes (size);
if( (s=sym_FindMacroArg (src[1] - '0'))!=NULL )
{
yyunputstr(s);
}
else
{
yyerror( "Macro argument not defined" );
}
return (0);
}
ULONG PutUniqueArg (char *src, ULONG size)
{
src=src;
yyskipbytes (size);
yyunputstr (sym_FindMacroArg (-1));
return (0);
}
enum
{
T_LEX_MACROARG = 3000,
T_LEX_MACROUNIQUE
};
extern struct sLexInitString localstrings[];
struct sLexInitString staticstrings[] =
{
"||", T_OP_LOGICOR,
"&&", T_OP_LOGICAND,
"==", T_OP_LOGICEQU,
">", T_OP_LOGICGT,
"<", T_OP_LOGICLT,
">=", T_OP_LOGICGE,
"<=", T_OP_LOGICLE,
"!=", T_OP_LOGICNE,
"!", T_OP_LOGICNOT,
"|", T_OP_OR,
"^", T_OP_XOR,
"&", T_OP_AND,
"<<", T_OP_SHL,
">>", T_OP_SHR,
"+", T_OP_ADD,
"-", T_OP_SUB,
"*", T_OP_MUL,
"/", T_OP_DIV,
"%", T_OP_MOD,
"~", T_OP_NOT,
"def", T_OP_DEF,
"bank", T_OP_BANK,
"div", T_OP_FDIV,
"mul", T_OP_FMUL,
"sin", T_OP_SIN,
"cos", T_OP_COS,
"tan", T_OP_TAN,
"asin", T_OP_ASIN,
"acos", T_OP_ACOS,
"atan", T_OP_ATAN,
"atan2", T_OP_ATAN2,
"strcmp", T_OP_STRCMP,
"strin", T_OP_STRIN,
"strsub", T_OP_STRSUB,
"strlen", T_OP_STRLEN,
"strcat", T_OP_STRCAT,
"strupr", T_OP_STRUPR,
"strlwr", T_OP_STRLWR,
"include", T_POP_INCLUDE,
"printt", T_POP_PRINTT,
"printv", T_POP_PRINTV,
"printf", T_POP_PRINTF,
"export", T_POP_EXPORT,
"xdef", T_POP_EXPORT,
"import", T_POP_IMPORT,
"xref", T_POP_IMPORT,
"global", T_POP_GLOBAL,
"ds", T_POP_DS,
NAME_DB, T_POP_DB,
NAME_DW, T_POP_DW,
#ifdef NAME_DL
NAME_DL, T_POP_DL,
#endif
"section", T_POP_SECTION,
"purge", T_POP_PURGE,
"rsreset", T_POP_RSRESET,
"rsset", T_POP_RSSET,
"incbin", T_POP_INCBIN,
"fail", T_POP_FAIL,
"warn", T_POP_WARN,
"macro", T_POP_MACRO,
"endm", T_POP_ENDM, // Not needed but we have it here just to protect the name
"shift", T_POP_SHIFT,
"rept", T_POP_REPT,
"endr", T_POP_ENDR, // Not needed but we have it here just to protect the name
"if", T_POP_IF,
"else", T_POP_ELSE,
"endc", T_POP_ENDC,
"bss", T_SECT_BSS,
#if defined(GAMEBOY) || defined(PCENGINE)
"vram", T_SECT_VRAM,
#endif
"code", T_SECT_CODE,
"data", T_SECT_CODE,
#ifdef GAMEBOY
"home", T_SECT_HOME,
"hram", T_SECT_HRAM,
#endif
NAME_RB, T_POP_RB,
NAME_RW, T_POP_RW,
#ifdef NAME_RL
NAME_RL, T_POP_RL,
#endif
"equ", T_POP_EQU,
"equs", T_POP_EQUS,
"set", T_POP_SET,
"=", T_POP_SET,
"pushs", T_POP_PUSHS,
"pops", T_POP_POPS,
"pusho", T_POP_PUSHO,
"popo", T_POP_POPO,
"opt", T_POP_OPT,
NULL, 0
};
struct sLexFloat tNumberToken =
{
ParseNumber,
T_NUMBER
};
struct sLexFloat tFixedPointToken =
{
ParseFixedPoint,
T_NUMBER
};
struct sLexFloat tIDToken =
{
ParseSymbol,
T_ID
};
struct sLexFloat tMacroArgToken =
{
PutMacroArg,
T_LEX_MACROARG
};
struct sLexFloat tMacroUniqueToken =
{
PutUniqueArg,
T_LEX_MACROUNIQUE
};
void setuplex (void)
{
ULONG id;
lex_Init ();
lex_AddStrings (staticstrings);
lex_AddStrings (localstrings);
// Macro arguments
id = lex_FloatAlloc (&tMacroArgToken);
lex_FloatAddFirstRange (id, '\\', '\\');
lex_FloatAddSecondRange (id, '0', '9');
id = lex_FloatAlloc (&tMacroUniqueToken);
lex_FloatAddFirstRange (id, '\\', '\\');
lex_FloatAddSecondRange (id, '@', '@');
// Decimal constants
id = lex_FloatAlloc (&tNumberToken);
lex_FloatAddFirstRange (id, '0', '9');
lex_FloatAddSecondRange (id, '0', '9');
lex_FloatAddRange (id, '0', '9');
// Binary constants
nBinaryID = id = lex_FloatAlloc (&tNumberToken);
lex_FloatAddFirstRange (id, '%', '%');
lex_FloatAddSecondRange (id, CurrentOptions.binary[0], CurrentOptions.binary[0]);
lex_FloatAddSecondRange (id, CurrentOptions.binary[1], CurrentOptions.binary[1]);
lex_FloatAddRange (id, CurrentOptions.binary[0], CurrentOptions.binary[0]);
lex_FloatAddRange (id, CurrentOptions.binary[1], CurrentOptions.binary[1]);
// Octal constants
id = lex_FloatAlloc (&tNumberToken);
lex_FloatAddFirstRange (id, '&', '&');
lex_FloatAddSecondRange (id, '0', '7');
lex_FloatAddRange (id, '0', '7');
// Gameboy gfx constants
nGBGfxID = id = lex_FloatAlloc (&tNumberToken);
lex_FloatAddFirstRange (id, '`', '`');
lex_FloatAddSecondRange (id, CurrentOptions.gbgfx[0], CurrentOptions.gbgfx[0]);
lex_FloatAddSecondRange (id, CurrentOptions.gbgfx[1], CurrentOptions.gbgfx[1]);
lex_FloatAddSecondRange (id, CurrentOptions.gbgfx[2], CurrentOptions.gbgfx[2]);
lex_FloatAddSecondRange (id, CurrentOptions.gbgfx[3], CurrentOptions.gbgfx[3]);
lex_FloatAddRange (id, CurrentOptions.gbgfx[0], CurrentOptions.gbgfx[0]);
lex_FloatAddRange (id, CurrentOptions.gbgfx[1], CurrentOptions.gbgfx[1]);
lex_FloatAddRange (id, CurrentOptions.gbgfx[2], CurrentOptions.gbgfx[2]);
lex_FloatAddRange (id, CurrentOptions.gbgfx[3], CurrentOptions.gbgfx[3]);
// Hex constants
id = lex_FloatAlloc (&tNumberToken);
lex_FloatAddFirstRange (id, '$', '$');
lex_FloatAddSecondRange (id, '0', '9');
lex_FloatAddSecondRange (id, 'A', 'F');
lex_FloatAddSecondRange (id, 'a', 'f');
lex_FloatAddRange (id, '0', '9');
lex_FloatAddRange (id, 'A', 'F');
lex_FloatAddRange (id, 'a', 'f');
// ID's
id = lex_FloatAlloc (&tIDToken);
lex_FloatAddFirstRange (id, 'a', 'z');
lex_FloatAddFirstRange (id, 'A', 'Z');
lex_FloatAddFirstRange (id, '_', '_');
lex_FloatAddSecondRange (id, 'a', 'z');
lex_FloatAddSecondRange (id, 'A', 'Z');
lex_FloatAddSecondRange (id, '0', '9');
lex_FloatAddSecondRange (id, '_', '_');
lex_FloatAddSecondRange (id, '\\', '\\');
lex_FloatAddSecondRange (id, '@', '@');
lex_FloatAddSecondRange (id, '#', '#');
lex_FloatAddRange (id, 'a', 'z');
lex_FloatAddRange (id, 'A', 'Z');
lex_FloatAddRange (id, '0', '9');
lex_FloatAddRange (id, '_', '_');
lex_FloatAddRange (id, '\\', '\\');
lex_FloatAddRange (id, '@', '@');
lex_FloatAddRange (id, '#', '#');
// Local ID
id = lex_FloatAlloc (&tIDToken);
lex_FloatAddFirstRange (id, '.', '.');
lex_FloatAddSecondRange (id, 'a', 'z');
lex_FloatAddSecondRange (id, 'A', 'Z');
lex_FloatAddSecondRange (id, '_', '_');
lex_FloatAddRange (id, 'a', 'z');
lex_FloatAddRange (id, 'A', 'Z');
lex_FloatAddRange (id, '0', '9');
lex_FloatAddRange (id, '_', '_');
lex_FloatAddRange (id, '\\', '\\');
lex_FloatAddRange (id, '@', '@');
lex_FloatAddRange (id, '#', '#');
// @ ID
id = lex_FloatAlloc (&tIDToken);
lex_FloatAddFirstRange (id, '@', '@');
// Fixed point constants
id = lex_FloatAlloc (&tFixedPointToken);
lex_FloatAddFirstRange (id, '.', '.');
lex_FloatAddFirstRange (id, '0', '9');
lex_FloatAddSecondRange (id, '.', '.');
lex_FloatAddSecondRange (id, '0', '9');
lex_FloatAddRange (id, '.', '.');
lex_FloatAddRange (id, '0', '9');
}

33
src/ASM/INCLUDE/ASM.H Normal file
View File

@@ -0,0 +1,33 @@
/* asm.h
*
* Contains some assembler-wide defines and externs
*
* Copyright 1997 Carsten Sorensen
*
*/
#ifndef ASM_H
#define ASM_H
#include <stdlib.h>
#include <stdio.h>
#include "types.h"
#include "symbol.h"
#include "localasm.h"
#include "asmotor.h"
extern SLONG nLineNo;
extern ULONG nTotalLines;
extern ULONG nPC;
extern ULONG nPass;
extern ULONG nIFDepth;
extern char tzCurrentFileName[_MAX_PATH+1];
extern struct Section *pCurrentSection;
extern struct sSymbol *tHashedSymbols[HASHSIZE];
extern struct sSymbol *pPCSymbol;
extern UBYTE oDontExpandStrings;
#define MAXMACROARGS 9
#define MAXINCPATHS 16
#endif // ASM_H

42
src/ASM/INCLUDE/FSTACK.H Normal file
View File

@@ -0,0 +1,42 @@
/* fstack.h
*
* Contains some assembler-wide defines and externs
*
* Copyright 1997 Carsten Sorensen
*
*/
#ifndef FSTACK_H
#define FSTACK_H
#include "asm.h"
#include "types.h"
#include "lexer.h"
struct sContext
{
YY_BUFFER_STATE FlexHandle;
struct sSymbol *pMacro;
struct sContext *pNext;
char tzFileName[_MAX_PATH+1];
char *tzMacroArgs[MAXMACROARGS+1];
SLONG nLine;
ULONG nStatus;
FILE *pFile;
char *pREPTBlock;
ULONG nREPTBlockCount;
ULONG nREPTBlockSize;
};
extern ULONG fstk_RunInclude( char *s );
extern void fstk_RunMacroArg( SLONG s );
extern ULONG fstk_Init( char *s );
extern void fstk_Dump( void );
extern void fstk_AddIncludePath( char *s );
extern ULONG fstk_RunMacro( char *s );
extern void fstk_RunRept( ULONG count );
extern void fstk_FindFile( char *s );
extern int yywrap( void );
#endif

153
src/ASM/INCLUDE/GBASMY.H Normal file
View File

@@ -0,0 +1,153 @@
typedef union
{
char tzSym[MAXSYMLEN+1];
char tzString[256];
struct Expression sVal;
SLONG nConstValue;
} YYSTYPE;
#define T_NUMBER 258
#define T_STRING 259
#define T_OP_LOGICNOT 260
#define T_OP_LOGICOR 261
#define T_OP_LOGICAND 262
#define T_OP_LOGICEQU 263
#define T_OP_LOGICGT 264
#define T_OP_LOGICLT 265
#define T_OP_LOGICGE 266
#define T_OP_LOGICLE 267
#define T_OP_LOGICNE 268
#define T_OP_ADD 269
#define T_OP_SUB 270
#define T_OP_OR 271
#define T_OP_XOR 272
#define T_OP_AND 273
#define T_OP_SHL 274
#define T_OP_SHR 275
#define T_OP_MUL 276
#define T_OP_DIV 277
#define T_OP_MOD 278
#define T_OP_NOT 279
#define T_OP_DEF 280
#define T_OP_BANK 281
#define T_OP_SIN 282
#define T_OP_COS 283
#define T_OP_TAN 284
#define T_OP_ASIN 285
#define T_OP_ACOS 286
#define T_OP_ATAN 287
#define T_OP_ATAN2 288
#define T_OP_FDIV 289
#define T_OP_FMUL 290
#define T_OP_STRCMP 291
#define T_OP_STRIN 292
#define T_OP_STRSUB 293
#define T_OP_STRLEN 294
#define T_OP_STRCAT 295
#define T_OP_STRUPR 296
#define T_OP_STRLWR 297
#define NEG 298
#define T_LABEL 299
#define T_ID 300
#define T_POP_EQU 301
#define T_POP_SET 302
#define T_POP_EQUS 303
#define T_POP_INCLUDE 304
#define T_POP_PRINTF 305
#define T_POP_PRINTT 306
#define T_POP_PRINTV 307
#define T_POP_IF 308
#define T_POP_ELSE 309
#define T_POP_ENDC 310
#define T_POP_IMPORT 311
#define T_POP_EXPORT 312
#define T_POP_GLOBAL 313
#define T_POP_DB 314
#define T_POP_DS 315
#define T_POP_DW 316
#define T_POP_SECTION 317
#define T_POP_RB 318
#define T_POP_RW 319
#define T_POP_MACRO 320
#define T_POP_ENDM 321
#define T_POP_RSRESET 322
#define T_POP_RSSET 323
#define T_POP_INCBIN 324
#define T_POP_REPT 325
#define T_POP_SHIFT 326
#define T_POP_ENDR 327
#define T_POP_FAIL 328
#define T_POP_WARN 329
#define T_SECT_BSS 330
#define T_SECT_VRAM 331
#define T_SECT_CODE 332
#define T_SECT_HOME 333
#define T_SECT_HRAM 334
#define T_Z80_ADC 335
#define T_Z80_ADD 336
#define T_Z80_AND 337
#define T_Z80_BIT 338
#define T_Z80_CALL 339
#define T_Z80_CCF 340
#define T_Z80_CP 341
#define T_Z80_CPL 342
#define T_Z80_DAA 343
#define T_Z80_DEC 344
#define T_Z80_DI 345
#define T_Z80_EI 346
#define T_Z80_EX 347
#define T_Z80_HALT 348
#define T_Z80_INC 349
#define T_Z80_JP 350
#define T_Z80_JR 351
#define T_Z80_LD 352
#define T_Z80_LDIO 353
#define T_Z80_NOP 354
#define T_Z80_OR 355
#define T_Z80_POP 356
#define T_Z80_PUSH 357
#define T_Z80_RES 358
#define T_Z80_RET 359
#define T_Z80_RETI 360
#define T_Z80_RST 361
#define T_Z80_RL 362
#define T_Z80_RLA 363
#define T_Z80_RLC 364
#define T_Z80_RLCA 365
#define T_Z80_RR 366
#define T_Z80_RRA 367
#define T_Z80_RRC 368
#define T_Z80_RRCA 369
#define T_Z80_SBC 370
#define T_Z80_SCF 371
#define T_Z80_STOP 372
#define T_Z80_SLA 373
#define T_Z80_SRA 374
#define T_Z80_SRL 375
#define T_Z80_SUB 376
#define T_Z80_SWAP 377
#define T_Z80_XOR 378
#define T_MODE_A 379
#define T_MODE_B 380
#define T_MODE_C 381
#define T_MODE_C_IND 382
#define T_MODE_D 383
#define T_MODE_E 384
#define T_MODE_H 385
#define T_MODE_L 386
#define T_MODE_AF 387
#define T_MODE_BC 388
#define T_MODE_BC_IND 389
#define T_MODE_DE 390
#define T_MODE_DE_IND 391
#define T_MODE_SP 392
#define T_MODE_SP_IND 393
#define T_MODE_HL 394
#define T_MODE_HL_IND 395
#define T_MODE_HL_INDDEC 396
#define T_MODE_HL_INDINC 397
#define T_CC_NZ 398
#define T_CC_Z 399
#define T_CC_NC 400
extern YYSTYPE yylval;

68
src/ASM/INCLUDE/LEXER.H Normal file
View File

@@ -0,0 +1,68 @@
#ifndef LEXER_H
#define LEXER_H
#include "types.h"
#include <stdio.h>
#define LEXHASHSIZE 512
struct sLexInitString
{
char *tzName;
ULONG nToken;
};
struct sLexFloat
{
ULONG (*Callback)( char *s, ULONG size );
ULONG nToken;
};
struct yy_buffer_state
{
char *pBufferStart;
char *pBuffer;
ULONG nBufferSize;
ULONG oAtLineStart;
};
enum eLexerState
{
LEX_STATE_NORMAL,
LEX_STATE_MACROARGS
};
#define INITIAL 0
#define macroarg 3
typedef struct yy_buffer_state *YY_BUFFER_STATE;
extern void yy_set_state( enum eLexerState i );
extern YY_BUFFER_STATE yy_create_buffer( FILE *f );
extern YY_BUFFER_STATE yy_scan_bytes( char *mem, ULONG size );
extern void yy_delete_buffer( YY_BUFFER_STATE );
extern void yy_switch_to_buffer( YY_BUFFER_STATE );
extern ULONG lex_FloatAlloc( struct sLexFloat *tok );
extern void lex_FloatAddRange( ULONG id, UWORD start, UWORD end );
extern void lex_FloatDeleteRange( ULONG id, UWORD start, UWORD end );
extern void lex_FloatAddFirstRange( ULONG id, UWORD start, UWORD end );
extern void lex_FloatDeleteFirstRange( ULONG id, UWORD start, UWORD end );
extern void lex_FloatAddSecondRange( ULONG id, UWORD start, UWORD end );
extern void lex_FloatDeleteSecondRange( ULONG id, UWORD start, UWORD end );
extern void lex_Init( void );
extern void lex_AddStrings( struct sLexInitString *lex );
extern void lex_SetBuffer( char *buffer, ULONG len );
extern ULONG yylex( void );
extern void yyunput( char c );
extern void yyunputstr( char *s );
extern void yyskipbytes( ULONG count );
extern void yyunputbytes( ULONG count );
extern YY_BUFFER_STATE pCurrentBuffer;
#ifdef __GNUC__
extern void strupr( char *s );
extern void strlwr( char *s );
#endif
#endif

35
src/ASM/INCLUDE/MAIN.H Normal file
View File

@@ -0,0 +1,35 @@
#ifndef MAIN_H
#define MAIN_H
struct sOptions
{
ULONG endian;
char gbgfx[4];
char binary[2];
SLONG fillchar; // -1 == random
};
extern char *tzNewMacro;
extern ULONG ulNewMacroSize;
extern SLONG nGBGfxID;
extern SLONG nBinaryID;
extern struct sOptions DefaultOptions;
extern struct sOptions CurrentOptions;
extern void opt_Push( void );
extern void opt_Pop( void );
extern void opt_Parse( char *s );
void fatalerror( char *s );
void yyerror( char *s );
extern char temptext[1024];
#define YY_FATAL_ERROR fatalerror
#ifdef YYLMAX
#undef YYLMAX
#endif
#define YYLMAX 65536
#endif

123
src/ASM/INCLUDE/MYLINK.H Normal file
View File

@@ -0,0 +1,123 @@
#ifndef LINK_H
#define LINK_H 1
/* RGB0 .obj format:
*
* Header
* Symbols
* Sections
*
* Header:
* "RGB0"
* LONG NumberOfSymbols
* LONG NumberOfSections
*
* Symbols:
* Symbol[NumberOfSymbols]
*
* Symbol:
* char Name (NULL terminated)
* char nType
* if( nType!=SYM_IMPORT )
* {
* LONG SectionID
* LONG Offset
* }
*
* Sections:
* Section[NumberOfSections]
*
* Section:
* LONG SizeInBytes
* char Type
* if( Type!=BSS )
* {
* char Data[SizeInBytes]
* Patches
* }
*
* Patches:
* LONG NumberOfPatches
* Patch[NumberOfPatches]
*
* Patch:
* char Filename NULL-terminated
* LONG LineNo
* LONG Offset
* char Type
* LONG RpnByteSize
* Rpn[RpnByteSize]
*
* Rpn:
* Operators: 0x00-0x7F
* Constants: 0x80 0x00000000
* Symbols : 0x81 0x00000000
*
*/
enum
{
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
{
SECT_BSS=0,
SECT_VRAM,
SECT_CODE,
SECT_HOME,
SECT_HRAM
};
enum
{
SYM_LOCAL=0,
SYM_IMPORT,
SYM_EXPORT
};
enum
{
PATCH_BYTE=0,
PATCH_WORD_L,
PATCH_LONG_L,
PATCH_WORD_B,
PATCH_LONG_B
};
#endif

18
src/ASM/INCLUDE/MYMATH.H Normal file
View File

@@ -0,0 +1,18 @@
#ifndef MATH_H
#define MATH_H
#include "types.h"
void math_DefinePI( void );
void math_Print( SLONG i );
SLONG math_Sin( SLONG i );
SLONG math_Cos( SLONG i );
SLONG math_Tan( SLONG i );
SLONG math_ASin( SLONG i );
SLONG math_ACos( SLONG i );
SLONG math_ATan( SLONG i );
SLONG math_ATan2( SLONG i, SLONG j );
SLONG math_Mul( SLONG i, SLONG j );
SLONG math_Div( SLONG i, SLONG j );
#endif

35
src/ASM/INCLUDE/OUTPUT.H Normal file
View File

@@ -0,0 +1,35 @@
#ifndef OUTPUT_H
#define OUTPUT_H 1
#include "types.h"
struct Section
{
char *pzName;
UBYTE nType;
ULONG nPC;
ULONG nOrg;
ULONG nBank;
struct Section *pNext;
struct Patch *pPatches;
UBYTE *tData;
};
void out_PrepPass2( void );
void out_SetFileName( char *s );
void out_NewSection (char *pzName, ULONG secttype);
void out_NewAbsSection (char *pzName, ULONG secttype, SLONG org, SLONG bank);
void out_AbsByte( int b );
void out_RelByte( struct Expression *expr );
void out_RelWord( struct Expression *expr );
void out_PCRelByte( struct Expression *expr );
void out_WriteObject( void );
void out_Skip( int skip );
void out_BinaryFile( char *s );
void out_String( char *s );
void out_AbsLong (SLONG b);
void out_RelLong (struct Expression *expr);
void out_PushSection( void );
void out_PopSection( void );
#endif

51
src/ASM/INCLUDE/RPN.H Normal file
View File

@@ -0,0 +1,51 @@
#ifndef RPN_H
#define RPN_H 1
struct Expression
{
SLONG nVal;
UBYTE tRPN[256];
ULONG nRPNLength;
ULONG nRPNOut;
ULONG isReloc;
ULONG isPCRel;
};
ULONG rpn_isReloc( struct Expression *expr );
ULONG rpn_isPCRelative( struct Expression *expr );
void rpn_Symbol( struct Expression *expr, char *tzSym );
void rpn_Number( struct Expression *expr, ULONG i );
void rpn_LOGNOT( struct Expression *expr, struct Expression *src1 );
void rpn_LOGOR( struct Expression *expr, struct Expression *src1, struct Expression *src2 );
void rpn_LOGAND( struct Expression *expr, struct Expression *src1, struct Expression *src2 );
void rpn_LOGEQU( struct Expression *expr, struct Expression *src1, struct Expression *src2 );
void rpn_LOGGT( struct Expression *expr, struct Expression *src1, struct Expression *src2 );
void rpn_LOGLT( struct Expression *expr, struct Expression *src1, struct Expression *src2 );
void rpn_LOGGE( struct Expression *expr, struct Expression *src1, struct Expression *src2 );
void rpn_LOGLE( struct Expression *expr, struct Expression *src1, struct Expression *src2 );
void rpn_LOGNE( struct Expression *expr, struct Expression *src1, struct Expression *src2 );
void rpn_ADD( struct Expression *expr, struct Expression *src1, struct Expression *src2 );
void rpn_SUB( struct Expression *expr, struct Expression *src1, struct Expression *src2 );
void rpn_XOR( struct Expression *expr, struct Expression *src1, struct Expression *src2 );
void rpn_OR( struct Expression *expr, struct Expression *src1, struct Expression *src2 );
void rpn_AND( struct Expression *expr, struct Expression *src1, struct Expression *src2 );
void rpn_SHL( struct Expression *expr, struct Expression *src1, struct Expression *src2 );
void rpn_SHR( struct Expression *expr, struct Expression *src1, struct Expression *src2 );
void rpn_MUL( struct Expression *expr, struct Expression *src1, struct Expression *src2 );
void rpn_DIV( struct Expression *expr, struct Expression *src1, struct Expression *src2 );
void rpn_MOD( struct Expression *expr, struct Expression *src1, struct Expression *src2 );
void rpn_UNNEG( struct Expression *expr, struct Expression *src );
void rpn_UNNOT( struct Expression *expr, struct Expression *src );
UWORD rpn_PopByte( struct Expression *expr );
void rpn_Bank( struct Expression *expr, char *tzSym );
void rpn_Reset( struct Expression *expr );
int rpn_RangeCheck( struct Expression *expr, struct Expression *src, SLONG low, SLONG high );
#ifdef GAMEBOY
void rpn_CheckHRAM( struct Expression *expr,struct Expression *src1 );
#endif
#ifdef PCENGINE
void rpn_CheckZP( struct Expression *expr,struct Expression *src );
#endif
#endif

68
src/ASM/INCLUDE/SYMBOL.H Normal file
View File

@@ -0,0 +1,68 @@
#ifndef SYMBOL_H
#define SYMBOL_H 1
#include "types.h"
#define HASHSIZE 73
#define MAXSYMLEN 256
struct sSymbol
{
char tzName[MAXSYMLEN+1];
SLONG nValue;
ULONG nType;
struct sSymbol *pScope;
struct sSymbol *pNext;
struct Section *pSection;
ULONG ulMacroSize;
char *pMacro;
SLONG (*Callback)(struct sSymbol *);
};
#define SYMF_RELOC 0x001 /* symbol will be reloc'ed during linking, it's absolute value is unknown */
#define SYMF_EQU 0x002 /* symbol is defined using EQU, will not be changed during linking */
#define SYMF_SET 0x004 /* symbol is (re)defined using SET, will not be changed during linking */
#define SYMF_EXPORT 0x008 /* symbol should be exported */
#define SYMF_IMPORT 0x010 /* symbol is imported, it's value is unknown */
#define SYMF_LOCAL 0x020 /* symbol is a local symbol */
#define SYMF_DEFINED 0x040 /* symbol has been defined, not only referenced */
#define SYMF_MACRO 0x080 /* symbol is a macro */
#define SYMF_STRING 0x100 /* symbol is a stringsymbol */
#define SYMF_CONST 0x200 /* symbol has a constant value, will not be changed during linking */
void sym_PrepPass1( void );
void sym_PrepPass2( void );
void sym_AddLocalReloc( char *tzSym );
void sym_AddReloc( char *tzSym );
void sym_Export( char *tzSym );
void sym_PrintSymbolTable( void );
struct sSymbol *sym_FindMacro( char *s );
void sym_InitNewMacroArgs( void );
void sym_AddNewMacroArg( char *s );
void sym_SaveCurrentMacroArgs( char *save[] );
void sym_RestoreCurrentMacroArgs( char *save[] );
void sym_UseNewMacroArgs( void );
void sym_FreeCurrentMacroArgs( void );
void sym_AddEqu( char *tzSym, SLONG value );
void sym_AddSet( char *tzSym, SLONG value );
void sym_Init( void );
ULONG sym_GetConstantValue( char *s );
void sym_Import( char *tzSym );
ULONG sym_isConstant( char *s );
struct sSymbol *sym_FindSymbol( char *tzName );
void sym_Global( char *tzSym );
char *sym_FindMacroArg( SLONG i );
char *sym_GetStringValue( char *tzSym );
void sym_UseCurrentMacroArgs( void );
void sym_SetMacroArgID( ULONG nMacroCount );
ULONG sym_isString( char *tzSym );
void sym_AddMacro( char *tzSym );
void sym_ShiftCurrentMacroArgs( void );
void sym_AddString( char *tzSym, char *tzValue );
ULONG sym_GetValue( char *s );
ULONG sym_GetDefinedValue( char *s );
ULONG sym_isDefined( char *tzName );
void sym_Purge( char *tzName );
ULONG sym_isConstDefined (char *tzName);
#endif

18
src/ASM/INCLUDE/TYPES.H Normal file
View File

@@ -0,0 +1,18 @@
#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;
#define ASM_LITTLE_ENDIAN 0
#define ASM_BIG_ENDIAN 1
#endif

813
src/ASM/LEXER.C Normal file
View File

@@ -0,0 +1,813 @@
#include "asm.h"
#include "lexer.h"
#include "types.h"
#include "main.h"
#include "rpn.h"
#include "asmy.h"
#include "fstack.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
struct sLexString
{
char *tzName;
ULONG nToken;
ULONG nNameLength;
struct sLexString *pNext;
};
#define pLexBuffer (pCurrentBuffer->pBuffer)
#define nLexBufferLeng (pCurrentBuffer->nBufferSize)
#define SAFETYMARGIN 1024
extern ULONG symvaluetostring (char *dest, char *s);
struct sLexFloat tLexFloat[32];
struct sLexString *tLexHash[LEXHASHSIZE];
YY_BUFFER_STATE pCurrentBuffer;
ULONG yyleng;
ULONG nLexMaxLeng;
ULONG tFloatingSecondChar[256];
ULONG tFloatingFirstChar[256];
ULONG tFloatingChars[256];
ULONG nFloating;
enum eLexerState lexerstate=LEX_STATE_NORMAL;
#define AtLineStart pCurrentBuffer->oAtLineStart
#ifdef __GNUC__
void strupr( char *s )
{
while( *s )
{
*s=toupper(*s);
s+=1;
}
}
void strlwr( char *s )
{
while( *s )
{
*s=tolower(*s);
s+=1;
}
}
#endif
void yyskipbytes( ULONG count )
{
pLexBuffer+=count;
}
void yyunputbytes( ULONG count )
{
pLexBuffer-=count;
}
void yyunput( char c )
{
*(--pLexBuffer)=c;
}
void yyunputstr( char *s )
{
SLONG i;
i=strlen(s)-1;
while( i>=0 )
yyunput( s[i--] );
}
void yy_switch_to_buffer( YY_BUFFER_STATE buf )
{
pCurrentBuffer=buf;
}
void yy_set_state( enum eLexerState i )
{
lexerstate=i;
}
void yy_delete_buffer( YY_BUFFER_STATE buf )
{
free( buf->pBufferStart-SAFETYMARGIN );
free( buf );
}
YY_BUFFER_STATE yy_scan_bytes( char *mem, ULONG size )
{
YY_BUFFER_STATE pBuffer;
if( (pBuffer=(YY_BUFFER_STATE)malloc(sizeof(struct yy_buffer_state)))!=NULL )
{
if( (pBuffer->pBuffer=pBuffer->pBufferStart=(char *)malloc(size+1+SAFETYMARGIN))!=NULL )
{
pBuffer->pBuffer+=SAFETYMARGIN;
pBuffer->pBufferStart+=SAFETYMARGIN;
memcpy( pBuffer->pBuffer, mem, size );
pBuffer->nBufferSize=size;
pBuffer->oAtLineStart=1;
pBuffer->pBuffer[size]=0;
return( pBuffer );
}
}
fatalerror( "Out of memory!" );
return( NULL );
}
YY_BUFFER_STATE yy_create_buffer( FILE *f )
{
YY_BUFFER_STATE pBuffer;
if( (pBuffer=(YY_BUFFER_STATE)malloc(sizeof(struct yy_buffer_state)))!=NULL )
{
ULONG size;
fseek (f, 0, SEEK_END);
size = ftell (f);
fseek (f, 0, SEEK_SET);
if( (pBuffer->pBuffer=pBuffer->pBufferStart=(char *)malloc(size+2+SAFETYMARGIN))!=NULL )
{
char *mem;
ULONG instring = 0;
pBuffer->pBuffer+=SAFETYMARGIN;
pBuffer->pBufferStart+=SAFETYMARGIN;
size=fread( pBuffer->pBuffer, sizeof (UBYTE), size, f );
pBuffer->pBuffer[size]='\n';
pBuffer->pBuffer[size+1]=0;
pBuffer->nBufferSize=size+1;
mem=pBuffer->pBuffer;
while( *mem )
{
if( *mem=='\"' )
instring=1-instring;
if( instring )
{
mem+=1;
}
else
{
if( (mem[0]==10 && mem[1]==13)
|| (mem[0]==13 && mem[1]==10) )
{
mem[0]=' ';
mem[1]='\n';
mem+=2;
}
else if( mem[0]==10 || mem[0]==13 )
{
mem[0]='\n';
mem+=1;
}
else if( mem[0]=='\n' && mem[1]=='*' )
{
mem+=1;
while( !(*mem == '\n' || *mem == '\0') )
*mem++=' ';
}
else if( *mem==';' )
{
while( !(*mem == '\n' || *mem == '\0') )
*mem++=' ';
}
else
mem+=1;
}
}
pBuffer->oAtLineStart=1;
return( pBuffer );
}
}
fatalerror( "Out of memory!" );
return( NULL );
}
ULONG lex_FloatAlloc( struct sLexFloat *tok )
{
tLexFloat[nFloating]=(*tok);
return( 1<<(nFloating++) );
}
void lex_FloatDeleteRange( ULONG id, UWORD start, UWORD end )
{
while( start<=end )
{
tFloatingChars[start]&=~id;
start+=1;
}
}
void lex_FloatAddRange( ULONG id, UWORD start, UWORD end )
{
while( start<=end )
{
tFloatingChars[start]|=id;
start+=1;
}
}
void lex_FloatDeleteFirstRange( ULONG id, UWORD start, UWORD end )
{
while( start<=end )
{
tFloatingFirstChar[start]&=~id;
start+=1;
}
}
void lex_FloatAddFirstRange( ULONG id, UWORD start, UWORD end )
{
while( start<=end )
{
tFloatingFirstChar[start]|=id;
start+=1;
}
}
void lex_FloatDeleteSecondRange( ULONG id, UWORD start, UWORD end )
{
while( start<=end )
{
tFloatingSecondChar[start]&=~id;
start+=1;
}
}
void lex_FloatAddSecondRange( ULONG id, UWORD start, UWORD end )
{
while( start<=end )
{
tFloatingSecondChar[start]|=id;
start+=1;
}
}
struct sLexFloat *lexgetfloat( ULONG id )
{
ULONG r=0,
mask=1;
if( id==0 )
return( NULL );
while( (id&mask)==0 )
{
mask<<=1;
r+=1;
}
return( &tLexFloat[r] );
}
ULONG lexcalchash( char *s )
{
ULONG r=0;
while( *s )
{
r=((r<<1)+(toupper(*s)))%LEXHASHSIZE;
s+=1;
}
return( r );
}
void lex_Init( void )
{
ULONG i;
for( i=0; i<LEXHASHSIZE; i+=1)
{
tLexHash[i]=NULL;
}
for( i=0; i<256; i+=1 )
{
tFloatingFirstChar[i]=0;
tFloatingSecondChar[i]=0;
tFloatingChars[i]=0;
}
nLexMaxLeng=0;
nFloating=0;
}
void lex_AddStrings( struct sLexInitString *lex )
{
while( lex->tzName )
{
struct sLexString **ppHash;
ULONG hash;
ppHash = &tLexHash[hash=lexcalchash (lex->tzName)];
while (*ppHash)
ppHash = &((*ppHash)->pNext);
// printf( "%s has hashvalue %d\n", lex->tzName, hash );
if( ((*ppHash)=(struct sLexString *)malloc(sizeof(struct sLexString)))!=NULL )
{
if( ((*ppHash)->tzName=(char *)strdup(lex->tzName))!=NULL )
{
(*ppHash)->nNameLength = strlen (lex->tzName);
(*ppHash)->nToken = lex->nToken;
(*ppHash)->pNext = NULL;
strupr ((*ppHash)->tzName);
if ((*ppHash)->nNameLength > nLexMaxLeng)
nLexMaxLeng = (*ppHash)->nNameLength;
}
else
fatalerror ("Out of memory!");
}
else
fatalerror ("Out of memory!");
lex += 1;
}
}
ULONG yylex (void)
{
ULONG hash,
maxlen;
char *s;
struct sLexString *pLongestFixed = NULL;
ULONG nFloatMask,
nOldFloatMask,
nFloatLen;
ULONG linestart = AtLineStart;
switch( lexerstate )
{
case LEX_STATE_NORMAL:
AtLineStart = 0;
scanagain:
while (*pLexBuffer == ' ' || *pLexBuffer == '\t')
{
linestart = 0;
pLexBuffer += 1;
}
if (*pLexBuffer == 0)
{
if (yywrap () == 0)
{
linestart = AtLineStart;
AtLineStart = 0;
goto scanagain;
}
}
s = pLexBuffer;
nOldFloatMask = nFloatLen = 0;
nFloatMask = tFloatingFirstChar[*s++];
while (nFloatMask && nFloatLen < nLexBufferLeng)
{
nFloatLen += 1;
nOldFloatMask = nFloatMask;
if (nFloatLen == 1)
nFloatMask &= tFloatingSecondChar[*s++];
else
nFloatMask &= tFloatingChars[*s++];
}
maxlen = nLexBufferLeng;
if (nLexMaxLeng < maxlen)
maxlen = nLexMaxLeng;
yyleng = 0;
hash = 0;
s = pLexBuffer;
while (yyleng < nLexMaxLeng)
{
yyleng += 1;
hash = ((hash << 1) + (toupper (*s))) % LEXHASHSIZE;
s+=1;
if (tLexHash[hash])
{
struct sLexString *lex;
lex = tLexHash[hash];
while (lex)
{
if (lex->nNameLength == yyleng)
{
if (strnicmp (pLexBuffer, lex->tzName, yyleng) == 0)
{
pLongestFixed = lex;
}
}
lex = lex->pNext;
}
}
}
if (nFloatLen == 0 && pLongestFixed == NULL)
{
if (*pLexBuffer == '"')
{
ULONG index = 0;
pLexBuffer += 1;
while ((*pLexBuffer != '"') && (*pLexBuffer != '\n'))
{
char ch,
*marg;
if ((ch = *pLexBuffer++) == '\\')
{
switch (ch = (*pLexBuffer++))
{
case 'n':
ch = '\n';
break;
case 't':
ch = '\t';
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if( (marg=sym_FindMacroArg(ch-'0'))!=NULL )
{
while (*marg)
yylval.tzString[index++] = *marg++;
ch = 0;
}
break;
case '@':
if( (marg=sym_FindMacroArg(-1))!=NULL )
{
while (*marg)
yylval.tzString[index++] = *marg++;
ch = 0;
}
break;
}
}
else if (ch == '{')
{
char sym[MAXSYMLEN];
int i = 0;
while ((*pLexBuffer != '}') && (*pLexBuffer != '"') && (*pLexBuffer != '\n'))
{
if ((ch = *pLexBuffer++) == '\\')
{
switch (ch = (*pLexBuffer++))
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if( (marg=sym_FindMacroArg(ch-'0'))!=NULL )
{
while (*marg)
sym[i++] = *marg++;
ch = 0;
}
break;
case '@':
if( (marg=sym_FindMacroArg(-1))!=NULL )
{
while (*marg)
sym[i++] = *marg++;
ch = 0;
}
break;
}
}
else
sym[i++] = ch;
}
sym[i] = 0;
index += symvaluetostring (&yylval.tzString[index], sym);
if (*pLexBuffer == '}')
pLexBuffer += 1;
else
yyerror ("Missing }");
ch = 0;
}
if (ch)
yylval.tzString[index++] = ch;
}
yylval.tzString[index++] = 0;
if (*pLexBuffer == '\n')
yyerror ("Unterminated string");
else
pLexBuffer += 1;
return (T_STRING);
}
else if (*pLexBuffer == '{')
{
char sym[MAXSYMLEN],
ch,
*marg;
int i = 0;
pLexBuffer += 1;
while ((*pLexBuffer != '}') && (*pLexBuffer != '\n'))
{
if ((ch = *pLexBuffer++) == '\\')
{
switch (ch = (*pLexBuffer++))
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if( (marg=sym_FindMacroArg(ch-'0'))!=NULL )
{
while (*marg)
sym[i++] = *marg++;
ch = 0;
}
break;
case '@':
if( (marg=sym_FindMacroArg(-1))!=NULL )
{
while (*marg)
sym[i++] = *marg++;
ch = 0;
}
break;
}
}
else
sym[i++] = ch;
}
sym[i] = 0;
symvaluetostring (yylval.tzString, sym);
if (*pLexBuffer == '}')
pLexBuffer += 1;
else
yyerror ("Missing }");
return (T_STRING);
}
else
{
if (*pLexBuffer == '\n')
AtLineStart = 1;
yyleng = 1;
return (*pLexBuffer++);
}
}
if (nFloatLen == 0)
{
yyleng = pLongestFixed->nNameLength;
pLexBuffer += yyleng;
return (pLongestFixed->nToken);
}
if (pLongestFixed == NULL)
{
struct sLexFloat *tok;
tok = lexgetfloat (nOldFloatMask);
yyleng = nFloatLen;
if (tok->Callback)
{
if (tok->Callback (pLexBuffer, yyleng) == 0)
goto scanagain;
}
if (tok->nToken == T_ID && linestart)
{
pLexBuffer += yyleng;
return (T_LABEL);
}
else
{
pLexBuffer += yyleng;
return (tok->nToken);
}
}
if (nFloatLen > pLongestFixed->nNameLength)
{
struct sLexFloat *tok;
tok = lexgetfloat (nOldFloatMask);
yyleng = nFloatLen;
if (tok->Callback)
{
if (tok->Callback (pLexBuffer, yyleng) == 0)
goto scanagain;
}
if (tok->nToken == T_ID && linestart)
{
pLexBuffer += yyleng;
return (T_LABEL);
}
else
{
pLexBuffer += yyleng;
return (tok->nToken);
}
}
else
{
yyleng = pLongestFixed->nNameLength;
pLexBuffer += yyleng;
return (pLongestFixed->nToken);
}
break;
case LEX_STATE_MACROARGS:
{
ULONG index = 0;
while (*pLexBuffer == ' ' || *pLexBuffer == '\t')
{
linestart = 0;
pLexBuffer += 1;
}
while( (*pLexBuffer != ',')
&& (*pLexBuffer != '\n') )
{
char ch,
*marg;
if ((ch = *pLexBuffer++) == '\\')
{
switch (ch = (*pLexBuffer++))
{
case 'n':
ch = '\n';
break;
case 't':
ch = '\t';
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if( (marg=sym_FindMacroArg(ch-'0'))!=NULL )
{
while (*marg)
yylval.tzString[index++] = *marg++;
ch = 0;
}
break;
case '@':
if( (marg=sym_FindMacroArg(-1))!=NULL )
{
while (*marg)
yylval.tzString[index++] = *marg++;
ch = 0;
}
break;
}
}
else if (ch == '{')
{
char sym[MAXSYMLEN];
int i = 0;
while ((*pLexBuffer != '}') && (*pLexBuffer != '"') && (*pLexBuffer != '\n'))
{
if ((ch = *pLexBuffer++) == '\\')
{
switch (ch = (*pLexBuffer++))
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if( (marg=sym_FindMacroArg(ch-'0'))!=NULL )
{
while (*marg)
sym[i++] = *marg++;
ch = 0;
}
break;
case '@':
if( (marg=sym_FindMacroArg(-1))!=NULL )
{
while (*marg)
sym[i++] = *marg++;
ch = 0;
}
break;
}
}
else
sym[i++] = ch;
}
sym[i] = 0;
index += symvaluetostring (&yylval.tzString[index], sym);
if (*pLexBuffer == '}')
pLexBuffer += 1;
else
yyerror ("Missing }");
ch = 0;
}
if (ch)
yylval.tzString[index++] = ch;
}
if( index )
{
yyleng=index;
yylval.tzString[index] = 0;
if( *pLexBuffer=='\n' )
{
while( yylval.tzString[--index]==' ' )
{
yylval.tzString[index]=0;
yyleng-=1;
}
}
return (T_STRING);
}
else if( *pLexBuffer=='\n' )
{
pLexBuffer+=1;
AtLineStart = 1;
yyleng = 1;
return( '\n' );
}
else if( *pLexBuffer==',' )
{
pLexBuffer+=1;
yyleng = 1;
return( ',' );
}
else
{
yyerror( "INTERNAL ERROR IN YYLEX" );
return( 0 );
}
}
break;
}
yyerror( "INTERNAL ERROR IN YYLEX" );
return( 0 );
}

406
src/ASM/MAIN.C Normal file
View File

@@ -0,0 +1,406 @@
/*
* RGBAsm - MAIN.C
*
* INCLUDES
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <string.h>
#include "symbol.h"
#include "fstack.h"
#include "output.h"
#include "main.h"
int yyparse (void);
void setuplex (void);
#ifdef AMIGA
__near long __stack = 65536L;
#endif
/*
* RGBAsm - MAIN.C
*
* VARIABLES
*
*/
clock_t nStartClock,
nEndClock;
SLONG nLineNo;
ULONG nTotalLines,
nPass,
nPC,
nIFDepth,
nErrors;
extern int yydebug;
char temptext[1024];
/*
* RGBAsm - MAIN.C
*
* Option stack
*
*/
struct sOptions DefaultOptions;
struct sOptions CurrentOptions;
struct sOptionStackEntry
{
struct sOptions Options;
struct sOptionStackEntry *pNext;
};
struct sOptionStackEntry *pOptionStack=NULL;
void opt_SetCurrentOptions( struct sOptions *pOpt )
{
if( nGBGfxID!=-1 )
{
lex_FloatDeleteRange( nGBGfxID, CurrentOptions.gbgfx[0], CurrentOptions.gbgfx[0] );
lex_FloatDeleteRange( nGBGfxID, CurrentOptions.gbgfx[1], CurrentOptions.gbgfx[1] );
lex_FloatDeleteRange( nGBGfxID, CurrentOptions.gbgfx[2], CurrentOptions.gbgfx[2] );
lex_FloatDeleteRange( nGBGfxID, CurrentOptions.gbgfx[3], CurrentOptions.gbgfx[3] );
lex_FloatDeleteSecondRange( nGBGfxID, CurrentOptions.gbgfx[0], CurrentOptions.gbgfx[0] );
lex_FloatDeleteSecondRange( nGBGfxID, CurrentOptions.gbgfx[1], CurrentOptions.gbgfx[1] );
lex_FloatDeleteSecondRange( nGBGfxID, CurrentOptions.gbgfx[2], CurrentOptions.gbgfx[2] );
lex_FloatDeleteSecondRange( nGBGfxID, CurrentOptions.gbgfx[3], CurrentOptions.gbgfx[3] );
}
if( nBinaryID!=-1 )
{
lex_FloatDeleteRange( nBinaryID, CurrentOptions.binary[0], CurrentOptions.binary[0] );
lex_FloatDeleteRange( nBinaryID, CurrentOptions.binary[1], CurrentOptions.binary[1] );
lex_FloatDeleteSecondRange( nBinaryID, CurrentOptions.binary[0], CurrentOptions.binary[0] );
lex_FloatDeleteSecondRange( nBinaryID, CurrentOptions.binary[1], CurrentOptions.binary[1] );
}
CurrentOptions = *pOpt;
if( nGBGfxID!=-1 )
{
lex_FloatAddRange( nGBGfxID, CurrentOptions.gbgfx[0], CurrentOptions.gbgfx[0] );
lex_FloatAddRange( nGBGfxID, CurrentOptions.gbgfx[1], CurrentOptions.gbgfx[1] );
lex_FloatAddRange( nGBGfxID, CurrentOptions.gbgfx[2], CurrentOptions.gbgfx[2] );
lex_FloatAddRange( nGBGfxID, CurrentOptions.gbgfx[3], CurrentOptions.gbgfx[3] );
lex_FloatAddSecondRange( nGBGfxID, CurrentOptions.gbgfx[0], CurrentOptions.gbgfx[0] );
lex_FloatAddSecondRange( nGBGfxID, CurrentOptions.gbgfx[1], CurrentOptions.gbgfx[1] );
lex_FloatAddSecondRange( nGBGfxID, CurrentOptions.gbgfx[2], CurrentOptions.gbgfx[2] );
lex_FloatAddSecondRange( nGBGfxID, CurrentOptions.gbgfx[3], CurrentOptions.gbgfx[3] );
}
if( nBinaryID!=-1 )
{
lex_FloatAddRange( nBinaryID, CurrentOptions.binary[0], CurrentOptions.binary[0] );
lex_FloatAddRange( nBinaryID, CurrentOptions.binary[1], CurrentOptions.binary[1] );
lex_FloatAddSecondRange( nBinaryID, CurrentOptions.binary[0], CurrentOptions.binary[0] );
lex_FloatAddSecondRange( nBinaryID, CurrentOptions.binary[1], CurrentOptions.binary[1] );
}
}
void opt_Parse( char *s )
{
struct sOptions newopt;
newopt=CurrentOptions;
switch( s[0] )
{
case 'e':
switch( s[1] )
{
case 'b':
newopt.endian=ASM_BIG_ENDIAN;
printf( "*WARNING*\t :\n\tEndianness forced to BIG for destination CPU\n" );
break;
case 'l':
newopt.endian=ASM_LITTLE_ENDIAN;
printf( "*WARNING*\t :\n\tEndianness forced to LITTLE for destination CPU\n" );
break;
default:
printf ("*ERROR*\t :\n\tArgument to option -e must be 'b' or 'l'\n" );
exit (5);
}
break;
case 'g':
if( strlen(&s[1])==4 )
{
newopt.gbgfx[0]=s[1];
newopt.gbgfx[1]=s[2];
newopt.gbgfx[2]=s[3];
newopt.gbgfx[3]=s[4];
}
else
{
printf ("*ERROR*\t :\n\tMust specify exactly 4 characters for option 'g'\n" );
exit( 5 );
}
break;
case 'b':
if( strlen(&s[1])==2 )
{
newopt.binary[0]=s[1];
newopt.binary[1]=s[2];
}
else
{
printf ("*ERROR*\t :\n\tMust specify exactly 2 characters for option 'b'\n" );
exit( 5 );
}
break;
case 'z':
if( strlen(&s[1])<=2 )
{
if( strcmp(&s[1],"?")==0 )
{
newopt.fillchar=-1;
}
else
{
int result;
result=sscanf( &s[1], "%lx", &newopt.fillchar );
if( !((result==EOF) || (result==1)) )
{
printf ("*ERROR*\t :\n\tInvalid argument for option 'z'\n" );
exit( 5 );
}
}
}
else
{
printf ("*ERROR*\t :\n\tInvalid argument for option 'z'\n" );
exit( 5 );
}
break;
default:
fatalerror( "Unknown option" );
break;
}
opt_SetCurrentOptions( &newopt );
}
void opt_Push( void )
{
struct sOptionStackEntry *pOpt;
if( (pOpt=(struct sOptionStackEntry *)malloc(sizeof(struct sOptionStackEntry)))!=NULL )
{
pOpt->Options=CurrentOptions;
pOpt->pNext=pOptionStack;
pOptionStack=pOpt;
}
else
fatalerror( "No memory for option stack" );
}
void opt_Pop( void )
{
if( pOptionStack )
{
struct sOptionStackEntry *pOpt;
pOpt=pOptionStack;
opt_SetCurrentOptions( &(pOpt->Options) );
pOptionStack=pOpt->pNext;
free( pOpt );
}
else
fatalerror( "No entries in the option stack" );
}
/*
* RGBAsm - MAIN.C
*
* Error handling
*
*/
void yyerror (char *s)
{
printf ("*ERROR*\t");
fstk_Dump ();
printf (" :\n\t%s\n", s);
nErrors += 1;
}
void fatalerror (char *s)
{
yyerror (s);
exit (5);
}
/*
* RGBAsm - MAIN.C
*
* Help text
*
*/
void PrintUsage (void)
{
printf (APPNAME " v" ASM_VERSION " (part of ASMotor " ASMOTOR_VERSION ")\n\nUsage: " EXENAME " [options] asmfile\n");
printf ("Options:\n");
printf ("\t-h\t\tThis text\n");
printf ("\t-i<path>\tExtra include path\n");
printf ("\t-o<file>\tWrite objectoutput to <file>\n");
printf ("\t-e(l|b)\t\tChange endianness (CAUTION!)\n");
printf ("\t-g<ASCI>\tChange the four characters used for Gameboy graphics\n"
"\t\t\tconstants (default is 0123)\n" );
printf ("\t-b<AS>\t\tChange the two characters used for binary constants\n"
"\t\t\t(default is 01)\n" );
printf ("\t-z<hx>\t\tSet the byte value (hex format) used for uninitialised\n"
"\t\t\tdata (default is ? for random)\n" );
exit (0);
}
/*
* RGBAsm - MAIN.C
*
* main
*
*/
int main (int argc, char *argv[])
{
char *tzMainfile;
int argn = 1;
argc -= 1;
if (argc == 0)
PrintUsage ();
/* yydebug=1; */
DefaultOptions.endian=ASM_DEFAULT_ENDIAN;
DefaultOptions.gbgfx[0]='0';
DefaultOptions.gbgfx[1]='1';
DefaultOptions.gbgfx[2]='2';
DefaultOptions.gbgfx[3]='3';
DefaultOptions.binary[0]='0';
DefaultOptions.binary[1]='1';
DefaultOptions.fillchar=-1; // fill uninitialised data with random values
opt_SetCurrentOptions( &DefaultOptions );
while (argv[argn][0] == '-' && argc)
{
switch (argv[argn][1])
{
case 'h':
PrintUsage ();
break;
case 'i':
fstk_AddIncludePath (&(argv[argn][2]));
break;
case 'o':
out_SetFileName (&(argv[argn][2]));
break;
case 'e':
case 'g':
case 'b':
case 'z':
opt_Parse( &argv[argn][1] );
break;
default:
printf ("*ERROR*\t :\n\tUnknown option '%c'\n", argv[argn][1]);
exit (5);
break;
}
argn += 1;
argc -= 1;
}
DefaultOptions=CurrentOptions;
/*tzMainfile=argv[argn++];
* argc-=1; */
tzMainfile = argv[argn];
setuplex ();
printf ("Assembling %s\n", tzMainfile);
nStartClock = clock ();
nLineNo = 1;
nTotalLines = 0;
nIFDepth = 0;
nPC = 0;
nPass = 1;
nErrors = 0;
sym_PrepPass1 ();
if (fstk_Init (tzMainfile))
{
printf ("Pass 1...\n");
yy_set_state( LEX_STATE_NORMAL );
opt_SetCurrentOptions( &DefaultOptions );
if (yyparse () == 0 && nErrors == 0)
{
if (nIFDepth == 0)
{
nTotalLines = 0;
nLineNo = 1;
nIFDepth = 0;
nPC = 0;
nPass = 2;
nErrors = 0;
sym_PrepPass2 ();
out_PrepPass2 ();
fstk_Init (tzMainfile);
yy_set_state( LEX_STATE_NORMAL );
opt_SetCurrentOptions( &DefaultOptions );
printf ("Pass 2...\n");
if (yyparse () == 0 && nErrors == 0)
{
double timespent;
nEndClock = clock ();
timespent = ((double) (nEndClock - nStartClock)) / (double) CLOCKS_PER_SEC;
printf ("Success! %ld lines in %d.%02d seconds ", nTotalLines, (int) timespent, ((int) (timespent * 100.0)) % 100);
if (timespent == 0)
printf ("(INFINITY lines/minute)\n");
else
printf ("(%d lines/minute)\n", (int) (60 / timespent * nTotalLines));
out_WriteObject ();
}
else
{
printf ("Assembly aborted in pass 2 (%ld errors)!\n", nErrors);
//sym_PrintSymbolTable();
exit (5);
}
}
else
{
printf ("*ERROR*\t:\tUnterminated IF construct (%ld levels)!\n", nIFDepth);
exit (5);
}
}
else
{
printf ("Assembly aborted in pass 1 (%ld errors)!\n", nErrors);
exit (5);
}
}
else
{
printf ("File '%s' not found\n", tzMainfile);
exit (5);
}
return (0);
}

33
src/ASM/MAKEINIT Normal file
View File

@@ -0,0 +1,33 @@
!ifndef TARGET
TARGET = DOS
!endif
!ifeq TARGET DOS
!else
!ifeq TARGET WIN95
!else
!error Invalid TARGET (must be DOS or WIN95)
!endif
!endif
BISONOPT= --verbose -d
BISON = bison $(BISONOPT)
!ifeq TARGET DOS
OBJDIR = OBJS\
COPT = /zp4 /5s /fp3 /d2 /oneatx /i=..\include -i=..\.. /d2 /wx /bt=DOS
!endif
!ifeq TARGET WIN95
OBJDIR = OBJS95\
COPT = /zp4 /5s /fp3 /d2 /oneatx /i=..\include -i=..\.. /d2 /wx /bt=NT
ALLOCA = alloca.obj
!endif
.y: .;..
.c: .;..
.h: ..\include
.obj: $(OBJDIR)
OBJS = asmy.obj main.obj fstack.obj globlex.obj &
lexer.obj math.obj output.obj rpn.obj &
symbol.obj locallex.obj $(ALLOCA)

153
src/ASM/MATH.C Normal file
View File

@@ -0,0 +1,153 @@
/*
* RGBAsm - MATH.C (Fixedpoint math routines)
*
* INCLUDES
*
*/
#include <math.h>
#include <stdio.h>
#include "types.h"
#include "mymath.h"
#include "symbol.h"
#define fix2double(i) ((double)(i/65536.0))
#define double2fix(d) ((SLONG)(d*65536.0))
#ifndef PI
#define PI (acos(-1))
#endif
/*
* RGBAsm - MATH.C (Fixedpoint math routines)
*
* Define the _PI symbol
*
*/
void math_DefinePI (void)
{
sym_AddEqu ("_PI", double2fix (PI));
}
/*
* RGBAsm - MATH.C (Fixedpoint math routines)
*
* Print a fixed point value
*
*/
void math_Print (SLONG i)
{
if (i >= 0)
printf ("%ld.%05ld", i >> 16, ((SLONG) (fix2double (i) * 100000 + 0.5)) % 100000);
else
printf ("-%ld.%05ld", (-i) >> 16, ((SLONG) (fix2double (-i) * 100000 + 0.5)) % 100000);
}
/*
* RGBAsm - MATH.C (Fixedpoint math routines)
*
* Calculate sine
*
*/
SLONG math_Sin (SLONG i)
{
return (double2fix (sin (fix2double (i) * 2 * PI / 65536)));
}
/*
* RGBAsm - MATH.C (Fixedpoint math routines)
*
* Calculate cosine
*
*/
SLONG math_Cos (SLONG i)
{
return (double2fix (cos (fix2double (i) * 2 * PI / 65536)));
}
/*
* RGBAsm - MATH.C (Fixedpoint math routines)
*
* Calculate tangent
*
*/
SLONG math_Tan (SLONG i)
{
return (double2fix (tan (fix2double (i) * 2 * PI / 65536)));
}
/*
* RGBAsm - MATH.C (Fixedpoint math routines)
*
* Calculate sine^-1
*
*/
SLONG math_ASin (SLONG i)
{
return (double2fix (asin (fix2double (i)) / 2 / PI * 65536));
}
/*
* RGBAsm - MATH.C (Fixedpoint math routines)
*
* Calculate cosine^-1
*
*/
SLONG math_ACos (SLONG i)
{
return (double2fix (acos (fix2double (i)) / 2 / PI * 65536));
}
/*
* RGBAsm - MATH.C (Fixedpoint math routines)
*
* Calculate tangent^-1
*
*/
SLONG math_ATan (SLONG i)
{
return (double2fix (atan (fix2double (i)) / 2 / PI * 65536));
}
/*
* RGBAsm - MATH.C (Fixedpoint math routines)
*
* Calculate atan2
*
*/
SLONG math_ATan2 (SLONG i, SLONG j)
{
return (double2fix (atan2 (fix2double (i), fix2double (j)) / 2 / PI * 65536));
}
/*
* RGBAsm - MATH.C (Fixedpoint math routines)
*
* Multiplication
*
*/
SLONG math_Mul (SLONG i, SLONG j)
{
return (double2fix (fix2double (i) * fix2double (j)));
}
/*
* RGBAsm - MATH.C (Fixedpoint math routines)
*
* Division
*
*/
SLONG math_Div (SLONG i, SLONG j)
{
return (double2fix (fix2double (i) / fix2double (j)));
}

1027
src/ASM/OUTPUT.C Normal file

File diff suppressed because it is too large Load Diff

356
src/ASM/RPN.C Normal file
View File

@@ -0,0 +1,356 @@
/*
* RGBAsm - RPN.C - Controls RPN expressions for objectfiles
*
* INCLUDES
*
*/
#include "mylink.h"
#include "types.h"
#include "symbol.h"
#include "asm.h"
#include "main.h"
#include "rpn.h"
#include <stdio.h>
#include <string.h>
void mergetwoexpressions( struct Expression *expr, struct Expression *src1, struct Expression *src2 )
{
*expr = *src1;
memcpy( &(expr->tRPN[expr->nRPNLength]), src2->tRPN, src2->nRPNLength );
expr->nRPNLength += src2->nRPNLength;
expr->isReloc |= src2->isReloc;
expr->isPCRel |= src2->isPCRel;
}
#define joinexpr() mergetwoexpressions(expr,src1,src2)
/*
* RGBAsm - RPN.C - Controls RPN expressions for objectfiles
*
* VARIABLES
*
*/
//UBYTE rpnexpr[2048];
//ULONG rpnptr = 0;
//ULONG rpnoutptr = 0;
//ULONG reloc = 0;
//ULONG pcrel = 0;
/*
* RGBAsm - RPN.C - Controls RPN expressions for objectfiles
*
* Add a byte to the RPN expression
*
*/
void pushbyte (struct Expression *expr, int b)
{
expr->tRPN[expr->nRPNLength++] = b & 0xFF;
}
/*
* RGBAsm - RPN.C - Controls RPN expressions for objectfiles
*
* Reset the RPN module
*
*/
void rpn_Reset (struct Expression *expr)
{
expr->nRPNLength = expr->nRPNOut = expr->isReloc = expr->isPCRel = 0;
}
/*
* RGBAsm - RPN.C - Controls RPN expressions for objectfiles
*
* Returns the next rpn byte in expression
*
*/
UWORD rpn_PopByte (struct Expression *expr)
{
if (expr->nRPNOut == expr->nRPNLength)
{
return (0xDEAD);
}
else
return (expr->tRPN[expr->nRPNOut++]);
}
/*
* RGBAsm - RPN.C - Controls RPN expressions for objectfiles
*
* Determine if the current expression is relocatable
*
*/
ULONG rpn_isReloc (struct Expression *expr)
{
return (expr->isReloc);
}
/*
* RGBAsm - RPN.C - Controls RPN expressions for objectfiles
*
* Determine if the current expression can be pc-relative
*
*/
ULONG rpn_isPCRelative (struct Expression *expr)
{
return (expr->isPCRel);
}
/*
* RGBAsm - RPN.C - Controls RPN expressions for objectfiles
*
* Add symbols, constants and operators to expression
*
*/
void rpn_Number (struct Expression *expr, ULONG i)
{
rpn_Reset (expr);
pushbyte (expr, RPN_CONST);
pushbyte (expr, i);
pushbyte (expr, i >> 8);
pushbyte (expr, i >> 16);
pushbyte (expr, i >> 24);
expr->nVal = i;
}
void rpn_Symbol (struct Expression *expr, char *tzSym)
{
if (!sym_isConstant (tzSym))
{
struct sSymbol *psym;
rpn_Reset(expr);
psym = sym_FindSymbol (tzSym);
if (psym == NULL || psym->pSection == pCurrentSection || psym->pSection == NULL)
expr->isPCRel = 1;
expr->isReloc = 1;
pushbyte (expr,RPN_SYM);
while (*tzSym)
pushbyte (expr,*tzSym++);
pushbyte (expr,0);
}
else
rpn_Number (expr,sym_GetConstantValue (tzSym));
}
void rpn_Bank (struct Expression *expr,char *tzSym)
{
if (!sym_isConstant (tzSym))
{
struct sSymbol *psym;
rpn_Reset( expr );
psym = sym_FindSymbol (tzSym);
if (nPass == 2 && psym == NULL)
{
sprintf (temptext, "'%s' not defined", tzSym);
yyerror (temptext);
}
expr->isReloc = 1;
pushbyte (expr,RPN_BANK);
while (*tzSym)
pushbyte (expr,*tzSym++);
pushbyte (expr,0);
}
else
yyerror ("BANK argument must be a relocatable identifier");
}
int rpn_RangeCheck( struct Expression *expr, struct Expression *src, SLONG low, SLONG high )
{
*expr=*src;
if( rpn_isReloc(src) )
{
pushbyte( expr, RPN_RANGECHECK );
pushbyte( expr, low );
pushbyte( expr, low>>8 );
pushbyte( expr, low>>16 );
pushbyte( expr, low>>24 );
pushbyte( expr, high );
pushbyte( expr, high>>8 );
pushbyte( expr, high>>16 );
pushbyte( expr, high>>24 );
return( 1 );
}
else
{
return( expr->nVal>=low && expr->nVal<=high );
}
}
#ifdef GAMEBOY
void rpn_CheckHRAM (struct Expression *expr, struct Expression *src)
{
*expr = *src;
pushbyte (expr, RPN_HRAM);
}
#endif
#ifdef PCENGINE
void rpn_CheckZP (struct Expression *expr, struct Expression *src)
{
*expr = *src;
pushbyte (expr, RPN_PCEZP);
}
#endif
void rpn_LOGNOT (struct Expression *expr, struct Expression *src)
{
*expr = *src;
pushbyte (expr, RPN_LOGUNNOT);
}
void rpn_LOGOR (struct Expression *expr, struct Expression *src1, struct Expression *src2)
{
joinexpr();
expr->nVal = (expr->nVal||src2->nVal);
pushbyte (expr,RPN_LOGOR);
}
void rpn_LOGAND (struct Expression *expr, struct Expression *src1, struct Expression *src2)
{
joinexpr();
expr->nVal = (expr->nVal&&src2->nVal);
pushbyte (expr,RPN_LOGAND);
}
void rpn_LOGEQU (struct Expression *expr, struct Expression *src1, struct Expression *src2)
{
joinexpr();
expr->nVal = (expr->nVal==src2->nVal);
pushbyte (expr,RPN_LOGEQ);
}
void rpn_LOGGT (struct Expression *expr, struct Expression *src1, struct Expression *src2)
{
joinexpr();
expr->nVal = (expr->nVal>src2->nVal);
pushbyte (expr,RPN_LOGGT);
}
void rpn_LOGLT (struct Expression *expr, struct Expression *src1, struct Expression *src2)
{
joinexpr();
expr->nVal = (expr->nVal<src2->nVal);
pushbyte (expr,RPN_LOGLT);
}
void rpn_LOGGE (struct Expression *expr, struct Expression *src1, struct Expression *src2)
{
joinexpr();
expr->nVal = (expr->nVal>=src2->nVal);
pushbyte (expr,RPN_LOGGE);
}
void rpn_LOGLE (struct Expression *expr, struct Expression *src1, struct Expression *src2)
{
joinexpr();
expr->nVal = (expr->nVal<=src2->nVal);
pushbyte (expr,RPN_LOGLE);
}
void rpn_LOGNE (struct Expression *expr, struct Expression *src1, struct Expression *src2)
{
joinexpr();
expr->nVal = (expr->nVal!=src2->nVal);
pushbyte (expr,RPN_LOGNE);
}
void rpn_ADD (struct Expression *expr, struct Expression *src1, struct Expression *src2)
{
joinexpr();
expr->nVal = (expr->nVal+src2->nVal);
pushbyte (expr,RPN_ADD);
}
void rpn_SUB (struct Expression *expr, struct Expression *src1, struct Expression *src2)
{
joinexpr();
expr->nVal = (expr->nVal-src2->nVal);
pushbyte (expr,RPN_SUB);
}
void rpn_XOR (struct Expression *expr, struct Expression *src1, struct Expression *src2)
{
joinexpr();
expr->nVal = (expr->nVal^src2->nVal);
pushbyte (expr,RPN_XOR);
}
void rpn_OR (struct Expression *expr, struct Expression *src1, struct Expression *src2)
{
joinexpr();
expr->nVal = (expr->nVal|src2->nVal);
pushbyte (expr,RPN_OR);
}
void rpn_AND (struct Expression *expr, struct Expression *src1, struct Expression *src2)
{
joinexpr();
expr->nVal = (expr->nVal&src2->nVal);
pushbyte (expr,RPN_AND);
}
void rpn_SHL (struct Expression *expr, struct Expression *src1, struct Expression *src2)
{
joinexpr();
expr->nVal = (expr->nVal<<src2->nVal);
pushbyte (expr,RPN_SHL);
}
void rpn_SHR (struct Expression *expr, struct Expression *src1, struct Expression *src2)
{
joinexpr();
expr->nVal = (expr->nVal>>src2->nVal);
pushbyte (expr,RPN_SHR);
}
void rpn_MUL (struct Expression *expr, struct Expression *src1, struct Expression *src2)
{
joinexpr();
expr->nVal = (expr->nVal*src2->nVal);
pushbyte (expr,RPN_MUL);
}
void rpn_DIV (struct Expression *expr, struct Expression *src1, struct Expression *src2)
{
joinexpr();
expr->nVal = (expr->nVal/src2->nVal);
pushbyte (expr,RPN_DIV);
}
void rpn_MOD (struct Expression *expr, struct Expression *src1, struct Expression *src2)
{
joinexpr();
expr->nVal = (expr->nVal%src2->nVal);
pushbyte (expr,RPN_MOD);
}
void rpn_UNNEG (struct Expression *expr, struct Expression *src)
{
*expr = *src;
expr->nVal = -expr->nVal;
pushbyte (expr,RPN_UNSUB);
}
void rpn_UNNOT (struct Expression *expr, struct Expression *src)
{
*expr = *src;
expr->nVal = expr->nVal^0xFFFFFFFF;
pushbyte (expr,RPN_UNNOT);
}

40
src/ASM/STDMAKE Normal file
View File

@@ -0,0 +1,40 @@
CC = wcc386 $(COPT) /d$(TARGET_SYSTEM)
all: $(EXE)
$(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=256k
%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
$(CC) -fo=$(OBJDIR)$^. $[@
.y.c:
$(BISON) -o $^. $[.
asmy.y: ..\yaccprt1.y ..\yaccprt3.y yaccprt2.y yaccprt4.y
copy ..\yaccprt1.y+yaccprt2.y+..\yaccprt3.y+yaccprt4.y asmy.y
clean: .SYMBOLIC
del $(OBJDIR)*.obj
del asmy.*
del *.err
del $(EXE)
del *.map
del link.lnk

1073
src/ASM/SYMBOL.C Normal file

File diff suppressed because it is too large Load Diff

432
src/ASM/YACCPRT1.Y Normal file
View File

@@ -0,0 +1,432 @@
%{
#include "symbol.h"
#include "asm.h"
#include "output.h"
#include "mylink.h"
#include "fstack.h"
#include "mymath.h"
#include "rpn.h"
#include "main.h"
#include "lexer.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char *tzNewMacro;
ULONG ulNewMacroSize;
ULONG symvaluetostring( char *dest, char *sym )
{
if( sym_isString(sym) )
strcpy( dest, sym_GetStringValue(sym) );
else
sprintf( dest, "$%lX", sym_GetConstantValue(sym) );
return( strlen(dest) );
}
ULONG str2int( char *s )
{
ULONG r=0;
while( *s )
{
r<<=8;
r|=(UBYTE)(*s++);
}
return( r );
}
ULONG isWhiteSpace( char s )
{
return( s==' ' || s=='\t' || s=='\0' || s=='\n' );
}
ULONG isRept( char *s )
{
return( (strnicmp(s,"REPT",4)==0) && isWhiteSpace(*(s-1)) && isWhiteSpace(s[4]) );
}
ULONG isEndr( char *s )
{
return( (strnicmp(s,"Endr",4)==0) && isWhiteSpace(*(s-1)) && isWhiteSpace(s[4]) );
}
void copyrept( void )
{
SLONG level=1, len, instring=0;
char *src=pCurrentBuffer->pBuffer;
while( *src && level )
{
if( instring==0 )
{
if( isRept(src) )
{
level+=1;
src+=4;
}
else if( isEndr(src) )
{
level-=1;
src+=4;
}
else
{
if( *src=='\"' )
instring=1;
src+=1;
}
}
else
{
if( *src=='\\' )
{
src+=2;
}
else if( *src=='\"' )
{
src+=1;
instring=0;
}
else
{
src+=1;
}
}
}
len=src-pCurrentBuffer->pBuffer-4;
src=pCurrentBuffer->pBuffer;
ulNewMacroSize=len;
if( (tzNewMacro=(char *)malloc(ulNewMacroSize+1))!=NULL )
{
ULONG i;
tzNewMacro[ulNewMacroSize]=0;
for( i=0; i<ulNewMacroSize; i+=1 )
{
if( (tzNewMacro[i]=src[i])=='\n' )
nLineNo+=1;
}
}
else
fatalerror( "No mem for REPT block" );
yyskipbytes( ulNewMacroSize+4 );
}
ULONG isMacro( char *s )
{
return( (strnicmp(s,"MACRO",4)==0) && isWhiteSpace(*(s-1)) && isWhiteSpace(s[5]) );
}
ULONG isEndm( char *s )
{
return( (strnicmp(s,"Endm",4)==0) && isWhiteSpace(*(s-1)) && isWhiteSpace(s[4]) );
}
void copymacro( void )
{
SLONG level=1, len, instring=0;
char *src=pCurrentBuffer->pBuffer;
while( *src && level )
{
if( instring==0 )
{
if( isMacro(src) )
{
level+=1;
src+=4;
}
else if( isEndm(src) )
{
level-=1;
src+=4;
}
else
{
if( *src=='\"' )
instring=1;
src+=1;
}
}
else
{
if( *src=='\\' )
{
src+=2;
}
else if( *src=='\"' )
{
src+=1;
instring=0;
}
else
{
src+=1;
}
}
}
len=src-pCurrentBuffer->pBuffer-4;
src=pCurrentBuffer->pBuffer;
ulNewMacroSize=len;
if( (tzNewMacro=(char *)malloc(ulNewMacroSize+2))!=NULL )
{
ULONG i;
tzNewMacro[ulNewMacroSize]='\n';
tzNewMacro[ulNewMacroSize+1]=0;
for( i=0; i<ulNewMacroSize; i+=1 )
{
if( (tzNewMacro[i]=src[i])=='\n' )
nLineNo+=1;
}
}
else
fatalerror( "No mem for MACRO definition" );
yyskipbytes( ulNewMacroSize+4 );
}
ULONG isIf( char *s )
{
return( (strnicmp(s,"If",2)==0) && isWhiteSpace(*(s-1)) && isWhiteSpace(s[2]) );
}
ULONG isElse( char *s )
{
return( (strnicmp(s,"Else",4)==0) && isWhiteSpace(*(s-1)) && isWhiteSpace(s[4]) );
}
ULONG isEndc( char *s )
{
return( (strnicmp(s,"Endc",4)==0) && isWhiteSpace(*(s-1)) && isWhiteSpace(s[4]) );
}
void if_skip_to_else( void )
{
SLONG level=1, len, instring=0;
char *src=pCurrentBuffer->pBuffer;
while( *src && level )
{
if( *src=='\n' )
nLineNo+=1;
if( instring==0 )
{
if( isIf(src) )
{
level+=1;
src+=2;
}
else if( level==1 && isElse(src) )
{
level-=1;
src+=4;
}
else if( isEndc(src) )
{
level-=1;
if( level!=0 )
src+=4;
}
else
{
if( *src=='\"' )
instring=1;
src+=1;
}
}
else
{
if( *src=='\\' )
{
src+=2;
}
else if( *src=='\"' )
{
src+=1;
instring=0;
}
else
{
src+=1;
}
}
}
len=src-pCurrentBuffer->pBuffer;
yyskipbytes( len );
yyunput( '\n' );
nLineNo-=1;
}
void if_skip_to_endc( void )
{
SLONG level=1, len, instring=0;
char *src=pCurrentBuffer->pBuffer;
while( *src && level )
{
if( *src=='\n' )
nLineNo+=1;
if( instring==0 )
{
if( isIf(src) )
{
level+=1;
src+=2;
}
else if( isEndc(src) )
{
level-=1;
if( level!=0 )
src+=4;
}
else
{
if( *src=='\"' )
instring=1;
src+=1;
}
}
else
{
if( *src=='\\' )
{
src+=2;
}
else if( *src=='\"' )
{
src+=1;
instring=0;
}
else
{
src+=1;
}
}
}
len=src-pCurrentBuffer->pBuffer;
yyskipbytes( len );
yyunput( '\n' );
nLineNo-=1;
}
#ifdef PCENGINE
ULONG ZP( struct Expression *expr )
{
return( (!rpn_isReloc(expr)) && (expr->nVal>0x1FFF) && (expr->nVal<0x2100) );
}
void out_ZPByte( struct Expression *expr )
{
if( rpn_isReloc(expr) )
{
rpn_CheckZP(expr,expr);
out_RelByte(expr);
}
else
{
if( ZP(expr) )
out_AbsByte(expr->nVal-0x2000);
else
fatalerror( "Value not in zeropage");
}
}
#endif
%}
%union
{
char tzSym[MAXSYMLEN+1];
char tzString[256];
struct Expression sVal;
SLONG nConstValue;
}
%type <sVal> relocconst
%type <nConstValue> const
%type <nConstValue> const_3bit
%type <sVal> const_8bit
%type <sVal> const_16bit
%type <sVal> const_PCrel
%type <nConstValue> sectiontype
%type <tzString> string
%token <nConstValue> T_NUMBER
%token <tzString> T_STRING
%left T_OP_LOGICNOT
%left T_OP_LOGICOR T_OP_LOGICAND T_OP_LOGICEQU
%left T_OP_LOGICGT T_OP_LOGICLT T_OP_LOGICGE T_OP_LOGICLE T_OP_LOGICNE
%left T_OP_ADD T_OP_SUB
%left T_OP_OR T_OP_XOR T_OP_AND
%left T_OP_SHL T_OP_SHR
%left T_OP_MUL T_OP_DIV T_OP_MOD
%left T_OP_NOT
%left T_OP_DEF
%left T_OP_BANK
%left T_OP_SIN
%left T_OP_COS
%left T_OP_TAN
%left T_OP_ASIN
%left T_OP_ACOS
%left T_OP_ATAN
%left T_OP_ATAN2
%left T_OP_FDIV
%left T_OP_FMUL
%left T_OP_STRCMP
%left T_OP_STRIN
%left T_OP_STRSUB
%left T_OP_STRLEN
%left T_OP_STRCAT
%left T_OP_STRUPR
%left T_OP_STRLWR
%left NEG /* negation--unary minus */
%token <tzSym> T_LABEL
%token <tzSym> T_ID
%token <tzSym> T_POP_EQU
%token <tzSym> T_POP_SET
%token <tzSym> T_POP_EQUS
%token T_POP_INCLUDE T_POP_PRINTF T_POP_PRINTT T_POP_PRINTV T_POP_IF T_POP_ELSE T_POP_ENDC
%token T_POP_IMPORT T_POP_EXPORT T_POP_GLOBAL
%token T_POP_DB T_POP_DS T_POP_DW T_POP_DL
%token T_POP_SECTION
%token T_POP_RB
%token T_POP_RW
%token T_POP_RL
%token T_POP_MACRO
%token T_POP_ENDM
%token T_POP_RSRESET T_POP_RSSET
%token T_POP_INCBIN T_POP_REPT
%token T_POP_SHIFT
%token T_POP_ENDR
%token T_POP_FAIL
%token T_POP_WARN
%token T_POP_PURGE
%token T_POP_POPS
%token T_POP_PUSHS
%token T_POP_POPO
%token T_POP_PUSHO
%token T_POP_OPT

532
src/ASM/YACCPRT3.Y Normal file
View File

@@ -0,0 +1,532 @@
%start asmfile
%%
asmfile : lines lastline
;
lastline : /* empty */
| line
{ nLineNo+=1; nTotalLines+=1; }
;
lines : /* empty */
| lines line '\n'
{ nLineNo+=1; nTotalLines+=1; }
;
line : /* empty */
| label
| label cpu_command
| label macro
| label simple_pseudoop
| pseudoop
;
label : /* empty */
| T_LABEL { if( $1[0]=='.' )
sym_AddLocalReloc($1);
else
sym_AddReloc($1);
}
| T_LABEL ':' { if( $1[0]=='.' )
sym_AddLocalReloc($1);
else
sym_AddReloc($1);
}
| T_LABEL ':' ':' { sym_AddReloc($1); sym_Export($1); }
;
macro : T_ID
{
yy_set_state( LEX_STATE_MACROARGS );
}
macroargs
{
yy_set_state( LEX_STATE_NORMAL );
if( !fstk_RunMacro($1) )
{
yyerror( "No such macro" );
}
}
;
macroargs : /* empty */
| macroarg
| macroarg ',' macroargs
;
macroarg : T_STRING
{ sym_AddNewMacroArg( $1 ); }
;
pseudoop : equ
| set
| rb
| rw
| rl
| equs
| macrodef
;
simple_pseudoop : include
| printf
| printt
| printv
| if
| else
| endc
| import
| export
| global
| db
| dw
| dl
| ds
| section
| rsreset
| rsset
| incbin
| rept
| shift
| fail
| warn
| purge
| pops
| pushs
| popo
| pusho
| opt
;
opt : T_POP_OPT
{
yy_set_state( LEX_STATE_MACROARGS );
}
opt_list
{
yy_set_state( LEX_STATE_NORMAL );
}
;
opt_list : opt_list_entry
| opt_list_entry ',' opt_list
;
opt_list_entry : T_STRING
{
opt_Parse($1);
}
;
popo : T_POP_POPO
{ opt_Pop(); }
;
pusho : T_POP_PUSHO
{ opt_Push(); }
;
pops : T_POP_POPS
{ out_PopSection(); }
;
pushs : T_POP_PUSHS
{ out_PushSection(); }
;
fail : T_POP_FAIL string
{ fatalerror($2); }
;
warn : T_POP_WARN string
{ yyerror($2); }
;
shift : T_POP_SHIFT
{ sym_ShiftCurrentMacroArgs(); }
;
rept : T_POP_REPT const
{
copyrept();
fstk_RunRept( $2 );
}
;
macrodef : T_LABEL ':' T_POP_MACRO
{
copymacro();
sym_AddMacro($1);
}
;
equs : T_LABEL T_POP_EQUS string
{ sym_AddString( $1, $3 ); }
;
rsset : T_POP_RSSET const
{ sym_AddSet( "_RS", $2 ); }
;
rsreset : T_POP_RSRESET
{ sym_AddSet( "_RS", 0 ); }
;
rl : T_LABEL T_POP_RL const
{
sym_AddEqu( $1, sym_GetConstantValue("_RS") );
sym_AddSet( "_RS", sym_GetConstantValue("_RS")+4*$3 );
}
;
rw : T_LABEL T_POP_RW const
{
sym_AddEqu( $1, sym_GetConstantValue("_RS") );
sym_AddSet( "_RS", sym_GetConstantValue("_RS")+2*$3 );
}
;
rb : T_LABEL T_POP_RB const
{
sym_AddEqu( $1, sym_GetConstantValue("_RS") );
sym_AddSet( "_RS", sym_GetConstantValue("_RS")+$3 );
}
;
ds : T_POP_DS const
{ out_Skip( $2 ); }
;
db : T_POP_DB constlist_8bit
;
dw : T_POP_DW constlist_16bit
;
dl : T_POP_DL constlist_32bit
;
purge : T_POP_PURGE
{
oDontExpandStrings=1;
}
purge_list
{
oDontExpandStrings=0;
}
;
purge_list : purge_list_entry
| purge_list_entry ',' purge_list
;
purge_list_entry : T_ID { sym_Purge($1); }
;
import : T_POP_IMPORT import_list
;
import_list : import_list_entry
| import_list_entry ',' import_list
;
import_list_entry : T_ID { sym_Import($1); }
;
export : T_POP_EXPORT export_list
;
export_list : export_list_entry
| export_list_entry ',' export_list
;
export_list_entry : T_ID { sym_Export($1); }
;
global : T_POP_GLOBAL global_list
;
global_list : global_list_entry
| global_list_entry ',' global_list
;
global_list_entry : T_ID { sym_Global($1); }
;
equ : T_LABEL T_POP_EQU const
{ sym_AddEqu( $1, $3 ); }
;
set : T_LABEL T_POP_SET const
{ sym_AddSet( $1, $3 ); }
;
include : T_POP_INCLUDE string
{
if( !fstk_RunInclude($2) )
{
yyerror( "File not found" );
}
}
;
incbin : T_POP_INCBIN string
{ out_BinaryFile( $2 ); }
;
printt : T_POP_PRINTT string
{
if( nPass==1 )
printf( "%s", $2 );
}
;
printv : T_POP_PRINTV const
{
if( nPass==1 )
printf( "$%lX", $2 );
}
;
printf : T_POP_PRINTF const
{
if( nPass==1 )
math_Print( $2 );
}
;
if : T_POP_IF const
{
nIFDepth+=1;
if( !$2 )
{
if_skip_to_else(); /* will continue parsing just after ELSE or just at ENDC keyword */
}
}
else : T_POP_ELSE
{
if_skip_to_endc(); /* will continue parsing just at ENDC keyword */
}
;
endc : T_POP_ENDC
{
nIFDepth-=1;
}
;
const_3bit : const
{
if( ($1<0) || ($1>7) )
{
yyerror( "Immediate value must be 3-bit" );
}
else
$$=$1&0x7;
}
;
constlist_8bit : constlist_8bit_entry
| constlist_8bit_entry ',' constlist_8bit
;
constlist_8bit_entry : { out_Skip( 1 ); }
| const_8bit { out_RelByte( &$1 ); }
| string { out_String( $1 ); }
;
constlist_16bit : constlist_16bit_entry
| constlist_16bit_entry ',' constlist_16bit
;
constlist_16bit_entry : { out_Skip( 2 ); }
| const_16bit { out_RelWord( &$1 ); }
;
constlist_32bit : constlist_32bit_entry
| constlist_32bit_entry ',' constlist_32bit
;
constlist_32bit_entry : { out_Skip( 4 ); }
| relocconst { out_RelLong( &$1 ); }
;
const_PCrel : relocconst
{
$$ = $1;
if( !rpn_isPCRelative(&$1) )
yyerror( "Expression must be PC-relative" );
}
;
const_8bit : relocconst
{
if( (!rpn_isReloc(&$1)) && (($1.nVal<-128) || ($1.nVal>255)) )
{
yyerror( "Expression must be 8-bit" );
}
$$=$1;
}
;
const_16bit : relocconst
{
if( (!rpn_isReloc(&$1)) && (($1.nVal<-32768) || ($1.nVal>65535)) )
{
yyerror( "Expression must be 16-bit" );
}
$$=$1
}
;
relocconst : T_ID
{ rpn_Symbol(&$$,$1); $$.nVal = sym_GetValue($1); }
| T_NUMBER
{ rpn_Number(&$$,$1); $$.nVal = $1; }
| string
{ ULONG r; r=str2int($1); rpn_Number(&$$,r); $$.nVal=r; }
| T_OP_LOGICNOT relocconst %prec NEG
{ rpn_LOGNOT(&$$,&$2); }
| relocconst T_OP_LOGICOR relocconst
{ rpn_LOGOR(&$$,&$1,&$3); }
| relocconst T_OP_LOGICAND relocconst
{ rpn_LOGAND(&$$,&$1,&$3); }
| relocconst T_OP_LOGICEQU relocconst
{ rpn_LOGEQU(&$$,&$1,&$3); }
| relocconst T_OP_LOGICGT relocconst
{ rpn_LOGGT(&$$,&$1,&$3); }
| relocconst T_OP_LOGICLT relocconst
{ rpn_LOGLT(&$$,&$1,&$3); }
| relocconst T_OP_LOGICGE relocconst
{ rpn_LOGGE(&$$,&$1,&$3); }
| relocconst T_OP_LOGICLE relocconst
{ rpn_LOGLE(&$$,&$1,&$3); }
| relocconst T_OP_LOGICNE relocconst
{ rpn_LOGNE(&$$,&$1,&$3); }
| relocconst T_OP_ADD relocconst
{ rpn_ADD(&$$,&$1,&$3); }
| relocconst T_OP_SUB relocconst
{ rpn_SUB(&$$,&$1,&$3); }
| relocconst T_OP_XOR relocconst
{ rpn_XOR(&$$,&$1,&$3); }
| relocconst T_OP_OR relocconst
{ rpn_OR(&$$,&$1,&$3); }
| relocconst T_OP_AND relocconst
{ rpn_AND(&$$,&$1,&$3); }
| relocconst T_OP_SHL relocconst
{ rpn_SHL(&$$,&$1,&$3); }
| relocconst T_OP_SHR relocconst
{ rpn_SHR(&$$,&$1,&$3); }
| relocconst T_OP_MUL relocconst
{ rpn_MUL(&$$,&$1,&$3); }
| relocconst T_OP_DIV relocconst
{ rpn_DIV(&$$,&$1,&$3); }
| relocconst T_OP_MOD relocconst
{ rpn_MOD(&$$,&$1,&$3); }
| T_OP_ADD relocconst %prec NEG
{ $$ = $2; }
| T_OP_SUB relocconst %prec NEG
{ rpn_UNNEG(&$$,&$2); }
| T_OP_NOT relocconst %prec NEG
{ rpn_UNNOT(&$$,&$2); }
| T_OP_BANK '(' T_ID ')'
{ rpn_Bank(&$$,$3); $$.nVal = 0; }
| T_OP_DEF '(' T_ID ')'
{ rpn_Number(&$$,sym_isConstDefined($3)); }
| T_OP_FDIV '(' const ',' const ')' { rpn_Number(&$$,math_Div($3,$5)); }
| T_OP_FMUL '(' const ',' const ')' { rpn_Number(&$$,math_Mul($3,$5)); }
| T_OP_SIN '(' const ')' { rpn_Number(&$$,math_Sin($3)); }
| T_OP_COS '(' const ')' { rpn_Number(&$$,math_Cos($3)); }
| T_OP_TAN '(' const ')' { rpn_Number(&$$,math_Tan($3)); }
| T_OP_ASIN '(' const ')' { rpn_Number(&$$,math_ASin($3)); }
| T_OP_ACOS '(' const ')' { rpn_Number(&$$,math_ACos($3)); }
| T_OP_ATAN '(' const ')' { rpn_Number(&$$,math_ATan($3)); }
| T_OP_ATAN2 '(' const ',' const ')' { rpn_Number(&$$,math_ATan2($3,$5)); }
| T_OP_STRCMP '(' string ',' string ')' { rpn_Number(&$$,strcmp($3,$5)); }
| T_OP_STRIN '(' string ',' string ')'
{
char *p;
if( (p=strstr($3,$5))!=NULL )
{
rpn_Number(&$$,p-$3+1);
}
else
{
rpn_Number(&$$,0);
}
}
| T_OP_STRLEN '(' string ')' { rpn_Number(&$$,strlen($3)); }
| '(' relocconst ')'
{ $$ = $2; }
;
const : T_ID { $$ = sym_GetConstantValue($1); }
| T_NUMBER { $$ = $1; }
| string { $$ = str2int($1); }
| T_OP_LOGICNOT const %prec NEG { $$ = !$2; }
| const T_OP_LOGICOR const { $$ = $1 || $3; }
| const T_OP_LOGICAND const { $$ = $1 && $3; }
| const T_OP_LOGICEQU const { $$ = $1 == $3; }
| const T_OP_LOGICGT const { $$ = $1 > $3; }
| const T_OP_LOGICLT const { $$ = $1 < $3; }
| const T_OP_LOGICGE const { $$ = $1 >= $3; }
| const T_OP_LOGICLE const { $$ = $1 <= $3; }
| const T_OP_LOGICNE const { $$ = $1 != $3; }
| const T_OP_ADD const { $$ = $1 + $3; }
| const T_OP_SUB const { $$ = $1 - $3; }
| T_ID T_OP_SUB T_ID { $$ = sym_GetDefinedValue($1) - sym_GetDefinedValue($3); }
| const T_OP_XOR const { $$ = $1 ^ $3; }
| const T_OP_OR const { $$ = $1 | $3; }
| const T_OP_AND const { $$ = $1 & $3; }
| const T_OP_SHL const { $$ = $1 << $3; }
| const T_OP_SHR const { $$ = $1 >> $3; }
| const T_OP_MUL const { $$ = $1 * $3; }
| const T_OP_DIV const { $$ = $1 / $3; }
| const T_OP_MOD const { $$ = $1 % $3; }
| T_OP_ADD const %prec NEG { $$ = +$2; }
| T_OP_SUB const %prec NEG { $$ = -$2; }
| T_OP_NOT const %prec NEG { $$ = 0xFFFFFFFF^$2; }
| T_OP_FDIV '(' const ',' const ')' { $$ = math_Div($3,$5); }
| T_OP_FMUL '(' const ',' const ')' { $$ = math_Mul($3,$5); }
| T_OP_SIN '(' const ')' { $$ = math_Sin($3); }
| T_OP_COS '(' const ')' { $$ = math_Cos($3); }
| T_OP_TAN '(' const ')' { $$ = math_Tan($3); }
| T_OP_ASIN '(' const ')' { $$ = math_ASin($3); }
| T_OP_ACOS '(' const ')' { $$ = math_ACos($3); }
| T_OP_ATAN '(' const ')' { $$ = math_ATan($3); }
| T_OP_ATAN2 '(' const ',' const ')' { $$ = math_ATan2($3,$5); }
| T_OP_DEF '(' T_ID ')' { $$ = sym_isConstDefined($3); }
| T_OP_STRCMP '(' string ',' string ')' { $$ = strcmp( $3, $5 ); }
| T_OP_STRIN '(' string ',' string ')'
{
char *p;
if( (p=strstr($3,$5))!=NULL )
{
$$ = p-$3+1;
}
else
{
$$ = 0;
}
}
| T_OP_STRLEN '(' string ')' { $$ = strlen($3); }
| '(' const ')' { $$ = $2; }
;
string : T_STRING
{ strcpy($$,$1); }
| T_OP_STRSUB '(' string ',' const ',' const ')'
{ strncpy($$,$3+$5-1,$7); $$[$7]=0; }
| T_OP_STRCAT '(' string ',' string ')'
{ strcpy($$,$3); strcat($$,$5); }
| T_OP_STRUPR '(' string ')'
{ strcpy($$,$3); strupr($$); }
| T_OP_STRLWR '(' string ')'
{ strcpy($$,$3); strlwr($$); }
;

25
src/ASMOTOR.H Normal file
View File

@@ -0,0 +1,25 @@
/* asmotor.h
*
* Contains defines for every program in the ASMotor package
*
* Copyright 1997 Carsten Sorensen
*
*/
#ifndef ASMOTOR_H
#define ASMOTOR_H
#define ASMOTOR
#define ASMOTOR_VERSION "1.10"
#define ASM_VERSION "1.08c"
#define LINK_VERSION "1.06c"
#define RGBFIX_VERSION "1.02"
#define LIB_VERSION "1.00"
#ifdef __GNUC__
#define strnicmp strncasecmp
#endif
#endif // ASMOTOR_H

13
src/LIB/INCLUDE/LIBRARY.H Normal file
View File

@@ -0,0 +1,13 @@
#ifndef LIBRARY_H
#define LIBRARY_H
#include "libwrap.h"
extern sLibrary *lib_Read( char *filename );
extern BBOOL lib_Write( sLibrary *lib, char *filename );
extern sLibrary *lib_AddReplace( sLibrary *lib, char *filename );
extern void lib_Free( sLibrary *lib );
extern sLibrary *lib_DeleteModule( sLibrary *lib, char *filename );
extern sLibrary *lib_Find( sLibrary *lib, char *filename );
#endif

20
src/LIB/INCLUDE/LIBWRAP.H Normal file
View File

@@ -0,0 +1,20 @@
#ifndef LIBWRAP_H
#define LIBWRAP_H
#include "types.h"
#define MAXNAMELENGTH 256
struct LibraryWrapper
{
char tName[MAXNAMELENGTH];
UWORD uwTime;
UWORD uwDate;
SLONG nByteLength;
UBYTE *pData;
struct LibraryWrapper *pNext;
};
typedef struct LibraryWrapper sLibrary;
#endif

16
src/LIB/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

308
src/LIB/LIBRARY.C Normal file
View File

@@ -0,0 +1,308 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "types.h"
#include "libwrap.h"
extern void fatalerror( char *s );
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 );
}
SLONG file_ReadASCIIz( char *b, FILE *f )
{
SLONG r=0;
while( (*b++ = fgetc(f))!=0 )
r+=1;
return( r+1 );
}
void file_WriteASCIIz( char *b, FILE *f )
{
while( *b )
fputc(*b++,f);
fputc( 0, f );
}
UWORD file_ReadWord( FILE *f )
{
UWORD r;
r =fgetc( f );
r|=fgetc( f )<<8;
return( r );
}
void file_WriteWord( UWORD w, FILE *f )
{
fputc( w, f );
fputc( w>>8, f );
}
ULONG file_ReadLong( FILE *f )
{
ULONG r;
r =fgetc( f );
r|=fgetc( f )<<8;
r|=fgetc( f )<<16;
r|=fgetc( f )<<24;
return( r );
}
void file_WriteLong( UWORD w, FILE *f )
{
fputc( w, f );
fputc( w>>8, f );
fputc( w>>16, f );
fputc( w>>24, f );
}
sLibrary *lib_ReadLib0( FILE *f, SLONG size )
{
if( size )
{
sLibrary *l=NULL,
*first=NULL;
while( size>0 )
{
if( l==NULL )
{
if( (l=(sLibrary *)malloc(sizeof(sLibrary)))==NULL )
fatalerror( "Out of memory" );
first=l;
}
else
{
if( (l->pNext=(sLibrary *)malloc(sizeof(sLibrary)))==NULL )
fatalerror( "Out of memory" );
l=l->pNext;
}
size-=file_ReadASCIIz( l->tName, f );
l->uwTime=file_ReadWord( f ); size-=2;
l->uwDate=file_ReadWord( f ); size-=2;
l->nByteLength=file_ReadLong( f ); size-=4;
if( l->pData=(UBYTE *)malloc(l->nByteLength) )
{
fread( l->pData, sizeof(UBYTE), l->nByteLength, f );
size-=l->nByteLength;
}
else
fatalerror( "Out of memory" );
l->pNext=NULL;
}
return( first );
}
return( NULL );
}
sLibrary *lib_Read( char *filename )
{
FILE *f;
if( f=fopen(filename,"rb") )
{
SLONG size;
char ID[5];
size=file_Length( f );
if( size==0 )
{
fclose( f );
return( NULL );
}
fread( ID, sizeof(char), 4, f );
ID[4]=0;
size-=4;
if( strcmp(ID,"XLB0")==0 )
{
sLibrary *r;
r=lib_ReadLib0( f, size );
fclose( f );
printf( "Library '%s' opened\n", filename );
return( r );
}
else
{
fclose( f );
fatalerror( "Not a valid xLib library" );
return( NULL );
}
}
else
{
printf( "Library '%s' not found, it will be created if necessary\n", filename );
return( NULL );
}
}
BBOOL lib_Write( sLibrary *lib, char *filename )
{
FILE *f;
if( f=fopen(filename,"wb") )
{
fwrite( "XLB0", sizeof(char), 4, f );
while( lib )
{
file_WriteASCIIz( lib->tName, f );
file_WriteWord( lib->uwTime, f );
file_WriteWord( lib->uwDate, f );
file_WriteLong( lib->nByteLength, f );
fwrite( lib->pData, sizeof(UBYTE), lib->nByteLength,f );
lib=lib->pNext;
}
fclose( f );
printf( "Library '%s' closed\n", filename );
return( 1 );
}
return( 0 );
}
void TruncateFileName( char *dest, char *src )
{
SLONG l;
l=strlen( src )-1;
while( (l>=0) && (src[l]!='\\') && (src[l]!='/') )
l-=1;
strcpy( dest, &src[l+1] );
}
sLibrary *lib_Find( sLibrary *lib, char *filename )
{
char truncname[MAXNAMELENGTH];
TruncateFileName( truncname, filename );
while( lib )
{
if( strcmp(lib->tName,truncname)==0 )
break;
lib=lib->pNext;
}
return( lib );
}
sLibrary *lib_AddReplace( sLibrary *lib, char *filename )
{
FILE *f;
if( f=fopen(filename,"rb") )
{
sLibrary *module;
char truncname[MAXNAMELENGTH];
TruncateFileName( truncname, filename );
if( (module=lib_Find(lib,filename))==NULL )
{
if( module=(sLibrary *)malloc(sizeof(sLibrary)) )
{
module->pNext=lib;
lib=module;
}
else
fatalerror( "Out of memory" );
}
else
{
/* Module already exists */
free( module->pData );
}
module->nByteLength=file_Length( f );
strcpy( module->tName, truncname );
if( module->pData=(UBYTE *)malloc(module->nByteLength) )
{
fread( module->pData, sizeof(UBYTE), module->nByteLength, f );
}
printf( "Added module '%s'\n", truncname );
fclose( f );
}
return( lib );
}
sLibrary *lib_DeleteModule( sLibrary *lib, char *filename )
{
char truncname[MAXNAMELENGTH];
sLibrary **pp,
**first;
BBOOL found=0;
pp=&lib;
first=pp;
TruncateFileName( truncname, filename );
while( (*pp) && (!found) )
{
if( strcmp((*pp)->tName,truncname)==0 )
{
sLibrary *t;
t=*pp;
if( t->pData )
free( t->pData );
*pp = t->pNext;
free( t );
found=1;
}
pp=&((*pp)->pNext);
}
if( !found )
fatalerror( "Module not found" );
else
printf( "Module '%s' deleted from library\n", truncname );
return( *first );
}
void lib_Free( sLibrary *lib )
{
while( lib )
{
sLibrary *l;
if( lib->pData )
free( lib->pData );
l=lib;
lib=lib->pNext;
free( l );
}
}

143
src/LIB/MAIN.C Normal file
View File

@@ -0,0 +1,143 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "asmotor.h"
#include "types.h"
#include "library.h"
// Quick and dirty...but it works
#ifdef __GNUC__
#define strcmpi strcasecmp
#endif
/*
* Print out an errormessage
*
*/
void fatalerror( char *s )
{
printf( "*ERROR* : %s\n", s );
exit( 5 );
}
/*
* Print the usagescreen
*
*/
void PrintUsage( void )
{
printf( "xLib v" LIB_VERSION " (part of ASMotor " ASMOTOR_VERSION ")\n\n"
"Usage: xlib library command [module1 module2 ... modulen]\n"
"Commands:\n\ta\tAdd/replace modules to library\n"
"\td\tDelete modules from library\n"
"\tl\tList library contents\n"
"\tx\tExtract modules from library\n" );
exit( 0 );
}
/*
* The main routine
*
*/
int main( int argc, char *argv[] )
{
SLONG argn=0;
char *libname;
argc-=1;
argn+=1;
if( argc>=2 )
{
UBYTE command;
sLibrary *lib;
lib=lib_Read( libname=argv[argn++] );
argc-=1;
if( strlen(argv[argn])==1 )
{
command=argv[argn++][0];
argc-=1;
switch( tolower(command) )
{
case 'a':
while( argc )
{
lib=lib_AddReplace( lib, argv[argn++] );
argc-=1;
}
lib_Write( lib, libname );
lib_Free( lib );
break;
case 'd':
while( argc )
{
lib=lib_DeleteModule( lib, argv[argn++] );
argc-=1;
}
lib_Write( lib, libname );
lib_Free( lib );
break;
case 'l':
{
sLibrary *l;
l=lib;
while( l )
{
printf( "%10d %s\n", l->nByteLength, l->tName );
l=l->pNext;
}
}
break;
case 'x':
while( argc )
{
sLibrary *l;
l=lib_Find( lib, argv[argn] );
if( l )
{
FILE *f;
if( f=fopen(argv[argn],"wb") )
{
fwrite( l->pData, sizeof(UBYTE), l->nByteLength, f );
fclose( f );
printf( "Extracted module '%s'\n", argv[argn] );
}
else
fatalerror( "Unable to write module" );
}
else
fatalerror( "Module not found" );
argn+=1;
argc-=1;
}
lib_Free( lib );
break;
default:
fatalerror( "Invalid command" );
break;
}
}
else
{
fatalerror( "Invalid command" );
}
}
else
PrintUsage();
return( 0 );
}

62
src/LIB/MAKEFILE Normal file
View File

@@ -0,0 +1,62 @@
.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=.. /d2 /wx /bt=dos
OBJDIR = OBJS\
EXE = xlib.exe
!endif
!ifeq TARGET WIN95
COPT = /zp4 /5s /fp3 /d2 /oneatx /i=include /i=.. /d2 /wx /bt=nt
OBJDIR = OBJS95\
EXE = xlib95.exe
!endif
C = wcc386 $(COPT)
.c: .
.h: include
.obj: $(OBJDIR)
OBJS = main.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

2
src/LIB/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.

2
src/LIB/OBJS95/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.

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;
}
}
}
}

432
src/RGBFIX/MAIN.C Normal file
View File

@@ -0,0 +1,432 @@
/*
* RGBFix : Perform various tasks on a Gameboy image-file
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "asmotor.h"
/*
* Option defines
*
*/
#define OPTF_DEBUG 0x01L
#define OPTF_PAD 0x02L
#define OPTF_VALIDATE 0x04L
#define OPTF_TITLE 0x08L
#define OPTF_TRUNCATE 0x10L
unsigned long ulOptions;
/*
* Misc. variables
*
*/
unsigned char NintendoChar[48]=
{
0xCE,0xED,0x66,0x66,0xCC,0x0D,0x00,0x0B,0x03,0x73,0x00,0x83,0x00,0x0C,0x00,0x0D,
0x00,0x08,0x11,0x1F,0x88,0x89,0x00,0x0E,0xDC,0xCC,0x6E,0xE6,0xDD,0xDD,0xD9,0x99,
0xBB,0xBB,0x67,0x63,0x6E,0x0E,0xEC,0xCC,0xDD,0xDC,0x99,0x9F,0xBB,0xB9,0x33,0x3E
};
/*
* Misc. routines
*
*/
void PrintUsage( void )
{
printf( "RGBFix v" RGBFIX_VERSION " (part of ASMotor " ASMOTOR_VERSION ")\n\n" );
printf( "Usage: rgbfix [options] image[.gb]\n" );
printf( "Options:\n" );
printf( "\t-h\t\tThis text\n" );
printf( "\t-d\t\tDebug: Don't change image\n" );
printf( "\t-p\t\tPad image to valid size\n\t\t\tPads to 32/64/128/256/512kB as appropriate\n" );
printf( "\t-r\t\ttRuncate image to valid size\n\t\t\tTruncates to 32/64/128/256/512kB as appropriate\n" );
printf( "\t-t<name>\tChange cartridge title field (16 characters)\n" );
printf( "\t-v\t\tValidate header\n\t\t\tCorrects - Nintendo Character Area (0x0104)\n\t\t\t\t - ROM type (0x0147)\n\t\t\t\t - ROM size (0x0148)\n\t\t\t\t - Checksums (0x014D-0x014F)\n" );
exit( 0 );
}
void FatalError( char *s )
{
printf( "\n***ERROR: %s\n\n", s );
PrintUsage();
}
long int FileSize( FILE *f )
{
long prevpos;
long r;
fflush( f );
prevpos=ftell( f );
fseek( f, 0, SEEK_END );
r=ftell( f );
fseek( f, prevpos, SEEK_SET );
return( r );
}
int FileExists( char *s )
{
FILE *f;
if( (f=fopen(s,"rb"))!=NULL )
{
fclose( f );
return( 1 );
}
else
return( 0 );
}
/*
* Das main
*
*/
int main( int argc, char *argv[] )
{
int argn=1;
char filename[512];
char cartname[32];
FILE *f;
ulOptions=0;
if( (--argc)==0 )
PrintUsage();
while( *argv[argn]=='-' )
{
argc-=1;
switch( argv[argn++][1] )
{
case '?':
case 'h':
PrintUsage();
break;
case 'd':
ulOptions|=OPTF_DEBUG;
break;
case 'p':
ulOptions|=OPTF_PAD;
break;
case 'r':
ulOptions|=OPTF_TRUNCATE;
break;
case 'v':
ulOptions|=OPTF_VALIDATE;
break;
case 't':
strncpy( cartname, argv[argn-1]+2, 16 );
ulOptions|=OPTF_TITLE;
break;
}
}
strcpy( filename, argv[argn++] );
if( !FileExists(filename) )
strcat( filename, ".gb" );
if( (f=fopen(filename,"rb+"))!=NULL )
{
/*
* -d (Debug) option code
*
*/
if( ulOptions&OPTF_DEBUG )
{
printf( "-d (Debug) option enabled...\n" );
}
/*
* -p (Pad) option code
*
*/
if( ulOptions&OPTF_PAD )
{
long size, padto;
long bytesadded=0;
size=FileSize( f );
padto=0x8000L;
while( size>padto )
padto*=2;
printf( "Padding to %ldkB:\n", padto/1024 );
/*
if( padto<=0x80000L )
{
*/
if( size!=padto )
{
fflush( stdout );
fseek( f, 0, SEEK_END );
while( size<padto )
{
size+=1;
if( (ulOptions&OPTF_DEBUG)==0 )
fputc( 0, f );
bytesadded+=1;
}
fflush( f );
printf( "\tAdded %ld bytes\n", bytesadded );
}
else
printf( "\tNo padding needed\n" );
/*
}
else
FatalError( "Image size exceeds 512kB" );
*/
}
/*
* -r (Truncate) option code
*
*/
if( ulOptions&OPTF_TRUNCATE )
{
long size, padto;
char tempfile[512];
FILE *tf;
size=FileSize( f );
padto=256*32768;
while( size<padto )
padto/=2;
printf( "Truncating to %ldkB:\n", padto/1024 );
tmpnam( tempfile );
if( (ulOptions&OPTF_DEBUG)==0 )
{
if( (tf=fopen(tempfile,"wb"))!=NULL )
{
fseek( f, 0, SEEK_SET );
while( padto-- )
{
fputc( fgetc(f), tf );
}
fclose( f );
fclose( tf );
remove( filename );
rename( tempfile, filename );
f=fopen( filename, "rb+" );
}
}
}
/*
* -t (Set carttitle) option code
*
*/
if( ulOptions&OPTF_TITLE )
{
printf( "Setting cartridge title:\n" );
if( (ulOptions&OPTF_DEBUG)==0 )
{
fflush( f );
fseek( f, 0x0134L, SEEK_SET );
fwrite( cartname, 16, 1, f );
fflush( f );
}
printf( "\tTitle set to %s\n", cartname );
}
/*
* -v (Validate header) option code
*
*/
if( ulOptions&OPTF_VALIDATE )
{
long i, byteschanged=0;
long cartromsize, calcromsize=0, filesize;
long carttype;
unsigned short cartchecksum=0, calcchecksum=0;
unsigned char cartcompchecksum=0, calccompchecksum=0;
int ch;
printf( "Validating header:\n" );
fflush( stdout );
/* Nintendo Character Area */
fflush( f );
fseek( f, 0x0104L, SEEK_SET );
for( i=0; i<48; i+=1 )
{
int ch;
ch=fgetc( f );
if( ch==EOF )
ch=0x00;
if( ch!=NintendoChar[i] )
{
byteschanged+=1;
if( (ulOptions&OPTF_DEBUG)==0 )
{
fseek( f, -1, SEEK_CUR );
fputc( NintendoChar[i], f );
fflush( f );
}
}
}
fflush( f );
if( byteschanged )
printf( "\tChanged %ld bytes in the Nintendo Character Area\n", byteschanged );
else
printf( "\tNintendo Character Area is OK\n" );
/* ROM size */
fflush( f );
fseek( f, 0x0148L, SEEK_SET );
cartromsize=fgetc( f );
if( cartromsize==EOF )
cartromsize=0x00;
filesize=FileSize( f );
while( filesize>(0x8000L<<calcromsize) )
calcromsize+=1;
if( calcromsize!=cartromsize )
{
if( (ulOptions&OPTF_DEBUG)==0 )
{
fseek( f, -1, SEEK_CUR );
fputc( calcromsize, f );
fflush( f );
}
printf( "\tChanged ROM size byte from 0x%02lX (%ldkB) to 0x%02lX (%ldkB)\n",
cartromsize, (0x8000L<<cartromsize)/1024,
calcromsize, (0x8000L<<calcromsize)/1024 );
}
else
printf( "\tROM size byte is OK\n" );
/* Cartridge type */
fflush( f );
fseek( f, 0x0147L, SEEK_SET );
carttype=fgetc( f );
if( carttype==EOF )
carttype=0x00;
if( FileSize(f)>0x8000L )
{
/* carttype byte must != 0x00 */
if( carttype==0x00 )
{
if( (ulOptions&OPTF_DEBUG)==0 )
{
fseek( f, -1, SEEK_CUR );
fputc( 0x01, f );
fflush( f );
}
printf( "\tCartridge type byte changed to 0x01\n" );
}
else
printf( "\tCartridge type byte is OK\n" );
}
else
{
/* carttype byte can be anything? */
printf( "\tCartridge type byte is OK\n" );
}
/* Checksum */
fflush( f );
fseek( f, 0, SEEK_SET );
for( i=0; i<(0x8000L<<calcromsize); i+=1 )
{
ch=fgetc( f );
if( ch==EOF )
ch=0;
if( i<0x0134L )
calcchecksum+=ch;
else if( i<0x014DL )
{
calccompchecksum+=ch;
calcchecksum+=ch;
}
else if( i==0x014DL )
cartcompchecksum=ch;
else if( i==0x014EL )
cartchecksum=ch<<8;
else if( i==0x014FL )
cartchecksum|=ch;
else
calcchecksum+=ch;
}
calccompchecksum=0xE7-calccompchecksum;
calcchecksum+=calccompchecksum;
if( cartchecksum!=calcchecksum )
{
fflush( f );
fseek( f, 0x014EL, SEEK_SET );
if( (ulOptions&OPTF_DEBUG)==0 )
{
fputc( calcchecksum>>8, f );
fputc( calcchecksum&0xFF, f );
}
fflush( f );
printf( "\tChecksum changed from 0x%04lX to 0x%04lX\n", (long)cartchecksum, (long)calcchecksum );
}
else
printf( "\tChecksum is OK\n" );
if( cartcompchecksum!=calccompchecksum )
{
fflush( f );
fseek( f, 0x014DL, SEEK_SET );
if( (ulOptions&OPTF_DEBUG)==0 )
fputc( calccompchecksum, f );
fflush( f );
printf( "\tCompChecksum changed from 0x%02lX to 0x%02lX\n", (long)cartcompchecksum, (long)calccompchecksum );
}
else
printf( "\tCompChecksum is OK\n" );
}
fclose( f );
}
else
{
FatalError( "Unable to open file" );
}
return( 0 );
}

57
src/RGBFIX/MAKEFILE Normal file
View File

@@ -0,0 +1,57 @@
.ERASE
!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
OBJDIR = OBJS\
COPT = /zp4 /fp3 /d2 /oneatx /i=include -i=..\ /d2 /wx /bt=DOS
CC = wcc $(COPT)
EXE = rgbfix.exe
!endif
!ifeq TARGET WIN95
OBJDIR = OBJS95\
COPT = /zp4 /5s /fp3 /d2 /oneatx /i=include -i=..\ /d2 /wx /bt=NT
CC = wcc386 $(COPT)
EXE = rgbfix95.exe
!endif
OBJS = main.obj
.c:
.h: include
.obj: $(OBJDIR)
.exe:
$(EXE): $(OBJS)
%create link.lnk
!ifeq TARGET DOS
%append link.lnk system dos
!endif
!ifeq TARGET WIN95
%append link.lnk system nt
!endif
%append link.lnk option map
%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
.c.obj: .AUTODEPEND
$(CC) -fo=$(OBJDIR)$^. $[@
clean: .SYMBOLIC
del $(OBJDIR)*.obj
del *.err
del $(EXE)
del *.map
del link.lnk

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.