Пример #1
0
void TextMessageParse( byte *pMemFile, int fileSize )
{
	char		buf[512], trim[512];
	char		*pCurrentText=0, *pNameHeap;
	char		 currentName[512], nameHeap[ NAME_HEAP_SIZE ];
	int			lastNamePos;

	int			mode = MSGFILE_NAME;	// Searching for a message name	
	int			lineNumber, filePos, lastLinePos;
	int			messageCount;

	client_textmessage_t	textMessages[ MAX_MESSAGES ];
	
	int			i, nameHeapSize, textHeapSize, messageSize, nameOffset;

	lastNamePos = 0;
	lineNumber = 0;
	filePos = 0;
	lastLinePos = 0;
	messageCount = 0;

	CharacterSetBuild( &g_WhiteSpace, " \r\n\t" );

	while( memfgets( pMemFile, fileSize, &filePos, buf, 512 ) != NULL )
	{
		if(messageCount>=MAX_MESSAGES)
		{
			Sys_Error("tmessage::TextMessageParse : messageCount>=MAX_MESSAGES");
		}

		TrimSpace( buf, trim );
		switch( mode )
		{
		case MSGFILE_NAME:
			if ( IsComment( trim ) )	// Skip comment lines
				break;
			
			if ( ParseDirective( trim ) )	// Is this a directive "$command"?, if so parse it and break
				break;

			if ( IsStartOfText( trim ) )
			{
				mode = MSGFILE_TEXT;
				pCurrentText = (char*)(pMemFile + filePos);
				break;
			}
			if ( IsEndOfText( trim ) )
			{
				Con_DPrintf("Unexpected '}' found, line %d\n", lineNumber );
				return;
			}
			strcpy( currentName, trim );
			break;
		
		case MSGFILE_TEXT:
			if ( IsEndOfText( trim ) )
			{
				int length = strlen(currentName);

				// Save name on name heap
				if ( lastNamePos + length > 8192 )
				{
					Con_DPrintf("Error parsing file!\n" );
					return;
				}
				strcpy( nameHeap + lastNamePos, currentName );

				// Terminate text in-place in the memory file (it's temporary memory that will be deleted)
				pMemFile[ lastLinePos - 1 ] = 0;

				// Save name/text on heap
				textMessages[ messageCount ] = gMessageParms;
				textMessages[ messageCount ].pName = nameHeap + lastNamePos;
				lastNamePos += strlen(currentName) + 1;
				textMessages[ messageCount ].pMessage = pCurrentText;
				messageCount++;

				// Reset parser to search for names
				mode = MSGFILE_NAME;
				break;
			}
			if ( IsStartOfText( trim ) )
			{
				Con_DPrintf("Unexpected '{' found, line %d\n", lineNumber );
				return;
			}
			break;
		}
		lineNumber++;
		lastLinePos = filePos;

		if ( messageCount >= MAX_MESSAGES )
		{
			Con_Printf("WARNING: TOO MANY MESSAGES IN TITLES.TXT, MAX IS %d\n", MAX_MESSAGES );
			break;
		}
	}

	Con_DPrintf("Parsed %d text messages\n", messageCount );
	nameHeapSize = lastNamePos;
	textHeapSize = 0;
	for ( i = 0; i < messageCount; i++ )
		textHeapSize += strlen( textMessages[i].pMessage ) + 1;


	messageSize = (messageCount * sizeof(client_textmessage_t));

	// Must malloc because we need to be able to clear it after initialization
	gMessageTable = (client_textmessage_t *)malloc( textHeapSize + nameHeapSize + messageSize );
	
	// Copy table over
	memcpy( gMessageTable, textMessages, messageSize );
	
	// Copy Name heap
	pNameHeap = ((char *)gMessageTable) + messageSize;
	memcpy( pNameHeap, nameHeap, nameHeapSize );
	nameOffset = pNameHeap - gMessageTable[0].pName;

	// Copy text & fixup pointers
	pCurrentText = pNameHeap + nameHeapSize;

	for ( i = 0; i < messageCount; i++ )
	{
		gMessageTable[i].pName += nameOffset;		// Adjust name pointer (parallel buffer)
		strcpy( pCurrentText, gMessageTable[i].pMessage );	// Copy text over
		gMessageTable[i].pMessage = pCurrentText;
		pCurrentText += strlen( pCurrentText ) + 1;
	}

#if _DEBUG
	if ( (pCurrentText - (char *)gMessageTable) != (textHeapSize + nameHeapSize + messageSize) )
		Con_Printf("Overflow text message buffer!!!!!\n");
#endif
	gMessageTableCount = messageCount;
}
Пример #2
0
NOXREF void TextMessageParse(unsigned char *pMemFile, int fileSize)
{
	NOXREFCHECK;
	char buf[512];
	char trim[512];
	char *pCurrentText;
	char *pNameHeap;
	char currentName[512];
	char nameHeap[NAME_HEAP_SIZE];
	int lastNamePos;
	int mode;
	int lineNumber;
	int filePos;
	int lastLinePos;
	int messageCount;
	client_textmessage_t textMessages[MAX_MESSAGES];
	int i;
	int nameHeapSize;
	int textHeapSize;
	int messageSize;
	int nameOffset;

	lastNamePos = 0;
	lineNumber = 0;
	filePos = 0;
	lastLinePos = 0;
	messageCount = 0;
	mode = MSGFILE_NAME;

	while (memfgets(pMemFile, fileSize, &filePos, buf, 512) != NULL)
	{
		if(messageCount >= MAX_MESSAGES)
			Sys_Error("%s: messageCount >= MAX_MESSAGES", __func__);

		TrimSpace(buf, trim);
		switch (mode)
		{
			case MSGFILE_NAME:
			{
				if (IsComment(trim))
					break;

				if (ParseDirective(trim))
					break;

				if (IsStartOfText(trim))
				{
					mode = MSGFILE_TEXT;
					pCurrentText = (char *)(pMemFile + filePos);
					break;
				}
				if (IsEndOfText(trim))
				{
					Con_DPrintf("Unexpected '}' found, line %d\n", lineNumber);
					return;
				}
				Q_strncpy(currentName, trim, 511);
				currentName[511] = 0;

				break;
			}
			case MSGFILE_TEXT:
			{
				if (IsEndOfText(trim))
				{
					int length = Q_strlen(currentName);
					if (lastNamePos + length > sizeof(nameHeap))
					{
						Con_DPrintf("Error parsing file!  length > %i bytes\n", sizeof(nameHeap));
						return;
					}

					Q_strcpy(nameHeap + lastNamePos, currentName);

					pMemFile[lastLinePos - 1] = 0;

					textMessages[messageCount] = gMessageParms;
					textMessages[messageCount].pName = nameHeap + lastNamePos;
					lastNamePos += Q_strlen(currentName) + 1;
					textMessages[messageCount].pMessage = pCurrentText;
					messageCount++;

					mode = MSGFILE_NAME;
					break;
				}
				if (IsStartOfText(trim))
				{
					Con_DPrintf("Unexpected '{' found, line %d\n", lineNumber);
					return;
				}
				break;
			}
		}

		lineNumber++;
		lastLinePos = filePos;
	}

	Con_DPrintf("Parsed %d text messages\n", messageCount);
	nameHeapSize = lastNamePos;
	textHeapSize = 0;

	for (i = 0; i < messageCount; i++)
		textHeapSize += Q_strlen(textMessages[i].pMessage) + 1;

	messageSize = (messageCount * sizeof(client_textmessage_t));

	gMessageTable = (client_textmessage_t *)Mem_Malloc(textHeapSize + nameHeapSize + messageSize);

	Q_memcpy(gMessageTable, textMessages, messageSize);

	pNameHeap = ((char *)gMessageTable) + messageSize;
	Q_memcpy(pNameHeap, nameHeap, nameHeapSize);
	nameOffset = pNameHeap - gMessageTable[0].pName;

	pCurrentText = pNameHeap + nameHeapSize;
	for (i = 0; i < messageCount; i++)
	{
		gMessageTable[i].pName += nameOffset;
		Q_strcpy(pCurrentText, gMessageTable[i].pMessage);
		gMessageTable[i].pMessage = pCurrentText;
		pCurrentText += Q_strlen(pCurrentText) + 1;
	}

	gMessageTableCount = messageCount;
}
Пример #3
0
// LoadPSF for Memory
static PSFINFO *memLoadPSF(char *addr, long size, int level, int type) // Type==1 for just info load.
{
    u8 *in,*out=0;
	u8 head[4];

    u32 reserved;
    u32 complen;
    u32 crc32;
    uLongf outlen;
	PSFINFO *psfi=NULL;
	PSFINFO *tmpi=NULL;
	u32 poffset, plength;
	u32 offset = 0;

	if( addr == NULL || size == 0 ) return(0);

	memread((void*)(head), 4, addr, size, &offset);
	if(memcmp(head,"PSF\x01",4)) return(0);

	psfi=malloc(sizeof(PSFINFO));
	memset(psfi,0,sizeof(PSFINFO));
    psfi->stop=~0;
    psfi->fade=0;

	memread((void*)(&reserved), 4, addr, size, &offset);
	memread((void*)(&complen), 4, addr, size, &offset);
	complen=BFLIP32(complen);

	memread((void*)(&crc32), 4, addr, size, &offset);
	crc32=BFLIP32(crc32);

	memseek(reserved, size, &offset);

	if(type) {
		memseek(complen, size, &offset);
	}
    else {
        in=malloc(complen);
        out=malloc(1024*1024*2+0x800);
		if( !in || !out ) { free(psfi); return (0); }
		memread((void*)(in), complen, addr, size, &offset);

        outlen=1024*1024*2;
        uncompress(out,&outlen,in,complen);
        free(in);

        psxRegs->pc = out[0x10] | out[0x11]<<8 | out[0x12]<<16 | out[0x13]<<24;
		psxRegs->GPR.n.gp = out[0x14] | out[0x15]<<8 | out[0x16]<<16 | out[0x17]<<24;
		psxRegs->GPR.n.sp = out[0x30] | out[0x31]<<8 | out[0x32]<<16 | out[0x33]<<24;

        if (psxRegs->GPR.n.sp == 0) psxRegs->GPR.n.sp = 0x801fff00;

#ifdef DEBUG
		fprintf(stderr, "%d Level: PC %x GP %x SP %x\n",
			level, psxRegs->pc, psxRegs->GPR.n.gp, psxRegs->GPR.n.sp);
#endif

 		if(level) {
			poffset = out[0x18] | out[0x19]<<8 | out[0x1a]<<16 | out[0x1b]<<24;
			poffset &= 0x3fffffff;	// kill any MIPS cache segment indicators
			plength = out[0x1c] | out[0x1d]<<8 | out[0x1e]<<16 | out[0x1f]<<24;

#ifdef DEBUG
			fprintf(stderr, "%d Level: offset %x plength: %d\n", level, poffset, plength);
#endif

			LoadPSXMem(poffset,plength,out+0x800);
			free(out);

			// I don't really know how does this
			// work, but apparently it breaks the
			// loop that makes ff6 and ct to take
			// several seconds to start ...
			if( crc32 == 0xEFDE8EEE || crc32 == 0x545D9F65 )
				psxMemWrite32(0x5A66C, 0);

			// Same as above for Popolocrois and Einhänder
			if( crc32 == 0xF535726 )
				psxMemWrite32(0x5A990, 0);
		}
	}

    {
		u8 tagdata[5];
		if( memread((void*)(tagdata), 5, addr, size, &offset) == 5 ) {
			if(!memcmp(tagdata,"[TAG]",5)) {
				char linebuf[1024];

				while( memfgets(linebuf, 1024, addr, size, &offset)>0 ) {
					int x;
					char *key=0,*value=0;

					if(!GetKeyVal(linebuf,&key,&value)) {
						if(key) free(key);
						if(value) free(value);
						continue;
					}

					AddKV(&psfi->tags,key,value);

					if(!level) {
       					static char *yoinks[8]={"title","artist","game","year","genre",
                                  "copyright","psfby","comment"};
						char **yoinks2[8]={&psfi->title,&psfi->artist,&psfi->game,&psfi->year,&psfi->genre,
                                    &psfi->copyright,&psfi->psfby,&psfi->comment};
						for(x=0;x<8;x++)
							if(!strcasecmp(key,yoinks[x]))
								*yoinks2[x]=value;
						if(!strcasecmp(key,"length"))
							psfi->stop=TimeToMS(value);
						else if(!strcasecmp(key,"fade"))
							psfi->fade=TimeToMS(value);
					}

					if(!strcasecmp(key,"_lib") && !type && __psflibs) {

						/* Search file name "value" from the __psflibs array */
						int n, found = 0;
						for(n=0;n<__psflibs->count;n++)
							if( !strcasecmp(value, __psflibs->libn[n].name) ) {
								found = 1;
								break;
							}

						if(!found || !(tmpi=memLoadPSF(__psflibs->libn[n].addr, __psflibs->libn[n].size, level+1,0))) {
							free(key);
							free(value);
							if(!level) free(out);

							FreeTags(psfi->tags);
							free(psfi);
							return(0);
						}

						FreeTags(tmpi->tags);
						free(tmpi);
					}
				}
			}
		}
	}

	/* Now, if we're at level 0(main PSF), load the main executable, and any libN stuff*/
    if(!level && !type) {
    	poffset = out[0x18] | out[0x19]<<8 | out[0x1a]<<16 | out[0x1b]<<24;
		poffset &= 0x3fffffff;	// kill any MIPS cache segment indicators
		plength = out[0x1c] | out[0x1d]<<8 | out[0x1e]<<16 | out[0x1f]<<24;

		// TODO - investigate: should i just make
		//        plength = outlen-0x800?

		// Philosoma has an illegal "plength".  *sigh*
		if (plength > (outlen-0x800))
		{
			plength = outlen-0x800;
		}

		if( psfi->game ) {
			// Suikoden Tenmei has an illegal "plength". *sigh sigh*
			if( !strncmp(psfi->game, "Suikoden: Tenmei no Chikai", 26) ) {
				plength = outlen-0x800;
			}

			// Einhänder has an illegal "plength". *sigh sigh sigh*
			if( !strncmp(psfi->game, "Einhänder", 9) ) {
				plength = outlen-0x800;
			}
		}

#ifdef DEBUG
		fprintf(stderr, "%d Level: offset %x plength: %d\n", level, poffset, plength);
#endif

		LoadPSXMem(poffset,plength,out+0x800);
		free(out);
    }

	if(!type && __psflibs)	/* Load libN */ {
		LIBNCACHE *cache;
		PSFTAG *tag;
		unsigned int libncount=0;
		unsigned int cur=0;

		tag=psfi->tags;
		while(tag) {
			if(!strncasecmp(tag->key,"_lib",4) && tag->key[4])
			libncount++;
			tag=tag->next;
		}

		if(libncount) {
			cache=malloc(sizeof(LIBNCACHE)*libncount);

			tag=psfi->tags;
			while(tag) {
				if(!strncasecmp(tag->key,"_lib",4) && tag->key[4]) {
					cache[cur].num=atoi(&tag->key[4]);
					cache[cur].value=tag->value;
					cur++;
				}
				tag=tag->next;
			}
			qsort(cache, libncount, sizeof(LIBNCACHE), ccomp);
			for(cur=0;cur<libncount;cur++) {
				u32 ba[3];

 				if(cache[cur].num < 2) continue;

				ba[0]=psxRegs->pc;
				ba[1]=psxRegs->GPR.n.gp;
				ba[2]=psxRegs->GPR.n.sp;

				/* Search file name "value" from the __psflibs array */
				int n, found = 0;
				for(n=0;n<__psflibs->count;n++)
					if( !strcasecmp(cache[cur].value, __psflibs->libn[n].name) ) {
						found = 1;
						break;
					}

				if(!found || !(tmpi=memLoadPSF(__psflibs->libn[n].addr,__psflibs->libn[n].size,level+1,0))) {
					//free(key);
					//free(value);
					//free(tmpfn);
					//fclose(fp);
					//return(0);
				}
				FreeTags(tmpi->tags);
				free(tmpi);

				psxRegs->pc=ba[0];
       			psxRegs->GPR.n.gp=ba[1];
				psxRegs->GPR.n.sp=ba[2];
			}
			free(cache);
		}	// if(libncount)

	}	// if(!type)

	return(psfi);
}