mud++0.35/etc/
mud++0.35/etc/guilds/
mud++0.35/help/propert/
mud++0.35/mudC/
mud++0.35/player/
mud++0.35/src/interface/
mud++0.35/src/os/cygwin32/
mud++0.35/src/os/win32/
mud++0.35/src/os/win32/bcppbuilder/
mud++0.35/src/osaddon/
mud++0.35/src/util/
/*
....[@@@..[@@@..............[@.................. MUD++ is a written from
....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and
....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++.
....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing
....[@......[@..[@@@@@..[@@@@@.................. development project.  All 
................................................ contributions are welcome. 
....Copyright(C).1995.Melvin.Smith.............. Enjoy. 
------------------------------------------------------------------------------
Melvin Smith (aka Fusion)         msmith@hom.net
MUD++ development mailing list    mudpp@van.ml.org
------------------------------------------------------------------------------
asmobjfile.cc
*/

#include <string.h>
#include "config.h"
#include "io.h"
#include "asmobjfile.h"
#include "llist.h"

#define MEM_DELTA	100

int AsmObjFile::readFrom( StaticInput & in )
{
	asmobjheader head;
	
	constants_def.clr();
	
	// HEADER
	in.read( &head, sizeof(asmobjheader) );
	if ( strncmp(head.magic, ASMOBJ_MAGIC, 4 ) )
	{
		in.error( "Bad magic number.\n\r");
		return 1;
	}

	allocMemBlock(head.code_length);
	constants.allocMemBlock(head.consts_length);


	// EXEC CODE
	in.read( getMem(), head.code_length * sizeof(memorycell) );
	setOffset( head.code_length );

	// CONST TABLE

	constants_def.readFrom(in);

	// RELOCATION TABLE

	relocation_table.readFrom(in);

	
	// CONSTS
	in.read(constants.getMem(), head.consts_length);
	constants.setOffset( head.consts_length );

	return 0;
}

char emptybuf[] = "\0\0\0\0\0\0";

int AsmObjFile::writeTo( Output & out ) const
{
	asmobjheader head;

	// HEADER
	strncpy( head.magic, ASMOBJ_MAGIC, 4);
	head.code_length = getUsedSize();
	head.consts_length = constants.getUsedSize();
	out.write( &head, sizeof(asmobjheader) );

	// CODE PART
	out.write(getConstMem(), getUsedBytesize());

	// CONST DEF TABLE
	constants_def.writeTo( out );


	// RELOCATION TABLE
	relocation_table.writeTo( out );

	// CONSTS
	out.write(constants.getConstMem(), constants.getUsedBytesize() );

	return 0;
}


int AsmObjFile::addConstant( vmtype type, const void * src_ptr, int size )
{
	asmobjconst oconst;
	int i;
	if ( 
		(type == VMT_IMPORT_INTERFACE) ||
		(type == VMT_IMPORT_FUN ) ||
		(type == VMT_IMPORT_STATIC) ||
		(type == VMT_CLASS_TYPE) 
	   )
	{
		if ( (i = importLookup( type, (const char*)src_ptr) ) > 0)
		{
//			Cout << "Reduced import constant for " << (const char*)src_ptr <<endl;
			return i;
		}
	}

	oconst.type = type;
	oconst.offset = constants.getOffset();
	constants.putStruct( src_ptr, size );
	constants_def.add( oconst );
	return (constants_def.length() - 1);
}

int AsmObjFile::importLookup( vmtype type, const char * name )
{
	int i,size;
	size = constants_def.length();
	for ( i=0; i < size; i++ )
	{
		if ( constants_def[i].type == type )
			if ( !strcmp( name, constants.getMem() + constants_def[i].offset ) )
				return i;
	}
	return -1;
}


/*
 *	we have unsigned 16-bit constants numbers in object files
 *	it is one 16-bit numberspace for all types of constants
 *	after loading to mud it grows to 16-bit space for every main type of
 *	reference - normal, mudasm fun, interface fun, static
 */	

bool AsmObjFile::canLink( AsmObjFile & linkee )
{

	if ( (constants_def.length() + linkee.constants_def.length()) > 64000 )
		return false;
	return true;
}


void AsmObjFile::link( AsmObjFile & linkee )
{
	int i,size,tmp;
	int code_offset;
	int consts_count;
	asmobjconst oconst;
	vmfilefun vmff;
	int * reloc_now = new int[linkee.constants_def.length()];
	char * cptr;

	code_offset = getOffset();
	consts_count = constants_def.length();

	// copy code block
	canCarryMore( linkee.getUsedSize() );
	memcpy( getPtr(), linkee.getMem(), linkee.getUsedBytesize() );
	movePtr( linkee.getUsedSize() );


	// copy and update both constants definitions and constants themselves
	size = linkee.constants_def.length();

	for ( i=0; i < size; i++ )
	{
		oconst = linkee.constants_def[i];
		switch ( oconst.type )
		{
			case VMT_CONST_STRING:
			case VMT_IMPORT_FUN:
			case VMT_IMPORT_INTERFACE:
			case VMT_IMPORT_STATIC:
			case VMT_CLASS_TYPE:
			case VMT_IMPORT_FUN_OR_INTERFACE:
				cptr = linkee.constants.getMem() + oconst.offset;
				reloc_now[i] = addConstant( oconst.type, 
					cptr, strlen(cptr) + 1);
				break;

			case VMT_FIELD_DATA:
				cptr = linkee.constants.getMem() + oconst.offset;
				tmp = strlen( cptr );
				tmp += strlen( &cptr[tmp+1] );
				reloc_now[i] = addConstant( oconst.type,
					cptr, tmp + 2);
				break;

			case VMT_EXPORT_FUN:
				vmff = *((vmfilefun*)linkee.constants.getStruct(oconst.offset));
				vmff.start += code_offset;
				vmff.end += code_offset;
				vmff.name = reloc_now[vmff.name];
				reloc_now[i] = addConstant( oconst.type,
					&vmff, sizeof(vmfilefun));
				break;

			default:
				Cout << "Unknown type of asmobjfile constant" <<endl;
				break;
		}
	}

	
	// copy and update relocation table
	// also update references in code
	
	size = linkee.relocation_table.length();
	for ( i=0; i < size; i++ )
	{
		tmp = linkee.relocation_table[i] + code_offset;
		mem[tmp].s.u.number = reloc_now[mem[tmp].s.u.number];
		relocation_table.add(tmp);
	}


	delete [] reloc_now;
}