• Welcome to Smashboards, the world's largest Super Smash Brothers community! Over 250,000 Smash Bros. fans from around the world have come to discuss these great games in over 19 million posts!

    You are currently viewing our boards as a visitor. Click here to sign up right now and start on your path in the Smash community!

Important Melee, Hacks, and You -- New Hackers Start Here, in the OP!

L-a-t-e-r-a-l-u-s

Smash Ace
Joined
Dec 18, 2009
Messages
811
@L-a-t-e-r-a-l-u-s:

I'd add ya, but I don't use MSN...

I use chatango though ;)
I dont even know what a chatango is x_x. Anyway, due to my *****y art teacher and her ridiculous amounts of homework (I'm never taking an AP art course again... it's not that its out of my ability, it's that shes a ***** and I hate her.), drawing up concept art for each of the characters might take a while. Bare with me.
 

Milun

Smash Ace
Joined
Oct 29, 2009
Messages
516
Location
Australia
...Sigh. Hey you guys remember that Porygon hack of MK I showed you a while back?

Well... It's almost finished, I just need a pretty background. I tried the Saffron City 64 background and... it looks pretty bad in contrast with the pink/blue of Porygon.

(btw I'm not showing a picture cos lololol spoilers).

Anyway... now I'm stumped. I guess having a digital background i.e. that internet place they (Ash and co.) go to in the banned episode. If anyone has suggestions please let me hear them, because I suck at making textures from scratch.

Um... and ironically the stage won't allow you to use Pokeballs. Well you can but...
 

Dragoon Fighter

Smash Lord
Joined
May 23, 2010
Messages
1,915
look what i found with the pause screen. oh the possibilities



so far i can only change the left side of the screen and those little rectangles on the top right. The dolphin doesn't dump the other stuff
Can I have the download link to Rage quit pause screen?
 

Milun

Smash Ace
Joined
Oct 29, 2009
Messages
516
Location
Australia


Almost done people! The background just needs that little extra something...

BTW, that weird white line segment to the left is a Koopa I've yet to de-texture.
 

TheDekuNut

Smash Journeyman
Joined
May 27, 2010
Messages
413
Location
NJ
^ this is really cool. i have no idea how you did that background

Nube's clear pause was **** but it froze event matches. these don't. I haven't thoroughly tested them but i think they are good. the offsets are really weird in this file, curious.
this is the rage quit one and i also included the fixed clear pause
http://www.megaupload.com/?d=3OAIOW3X
 

Milun

Smash Ace
Joined
Oct 29, 2009
Messages
516
Location
Australia
Ok here's how:

I took a Print Screen of the banned Porygon episode (at one part they conveniently show the background like that). Unfortunately I couldn't find one of a higher definition than that, but I'm sure it'll turn up soon (notice how on both sides the BG wraps poorly). The two pipes that are in the foreground are just texture hacked Mushrooms.

Also, meesa need to get that pause screen. It'll serve well as a trolling device to my tournament playing friend, who goes out of his way to deny things like that. Mwa-diddly-hah.
 

GodFed

Smash Apprentice
Joined
Mar 25, 2009
Messages
160
Location
Hendrick House, Urbana, IL
source code

Hey, what's up.
Here are those source code files I promised way back. I decided not to do filesharing, it's just simpler to post the whole code here. If there's an issue with this, tell me and I'll fix it.

First is hps_insert.cpp, then tpl_insert.cpp
I wrote and compiled them in Dev-C++. It's kinda sloppy c++, but hey. It works.

I have a hitbox analyzer program that I just wrote, but it's a bit messy right now. I'll refine it and post it soon. Maybe it'll be a Christmas present for you fine people. What it does so far is look in a character file and analyze every single action that the character makes (like nair, upB, jab, dtilt, spot-dodge, taunt, etc). It checks for hitboxes, grab-boxes, whatever, then at the individual values (damage, angle, knockback, sound fx, etc). It spits it all into a txt file. So yeah.


Code:
/*
hps_insert.exe
--creates HPS files from a supplied HPS file and two channels of audio
--will fit the new HPS to the supplied HPS structure and size

--you need to have dspadpcm.exe in the same directory as hps_insert.exe
--you need to have soundfile.dll and dsptool.dll in the directory, too

Parameters
>>hps_insert (hps_name r_wav l_wav)
hps_name is the name of the HPS file you're going to supply as a model.
r_wav is the name of the mono WAV file that is the right channel that you want.
l_wav is the name of the mono WAV file that is the left channel that you want.

Example of use
C:\Documents and Settings\Admin>hps_insert hyaku.hps battleR.wav battleL.wav
--this will create an HPS file called "temp.hps", which will have the exact
same structure as the hyaku.hps file, while having the audio from battleL.wav
and battleR.wav

Program written by GodFed of smashboards.com, with HPS structure info from 
hcs of halley's comet software. Permission is given to copy, distribute, 
etc as long as you don't make any money from it. 

10/11/2010
*/

#include <stdio.h>
#include <string.h>
#include <process.h>
#include <inttypes.h>

int get32bit(unsigned char * p);

int main(int argc, char *argv[])
{
	FILE *hps, *dsp1, *dsp2, *tmp, *infile;						//FILE stuff..
	long start_offset, current_offset, next_offset;				//offset variables for fseek() and fgetc() in FILE *hps 
	long l_count, r_count;										//keep track of where I am when copying left DSP and right DSP to HPS
	int block_length, channel_length, chanlen_check, chans, block_nibbles;		//variables for HPS audio blocks
	int sam0, sam1, sam2;										//sample rate checker variables
	int x, test, counter;										//loops, I think
	float time, total_time;										//time for each block, total time for all of the blocks to that point
	char ch;													//for copying files character by character
	unsigned char readbuf[128];									//for get32bit() 
	char hpsname[80], wavLname[80], wavRname[80], txtname[80];	//arguments for various functions in string form - they're just necessary
	char coef_L[32], coef_R[32];								//coefficient data for L and R DSPs
	char arg1[80], arg2[80], arg3[80];							//argument strings in case all parameters are not met
	bool loop_flag = false;										//does the HPS loop? initially set to false
	
	printf("hps_insert v1.2 by GodFed\nwith help from hcs\n");
	printf("-updated 10/11/10\n");
	
	if(argc == 1){
		printf("\nPlease provide the HPS name.\n");
		gets(arg1);
		argc++;
		argv[1] = arg1;
	}
	if(argc == 2){
		printf("\nPlease provide the WAV left channel name.\n");
		gets(arg2);
		argc++;
		argv[2] = arg2;
	}
	if(argc == 3){
		printf("\nPlease provide the WAV right channel name.\n");
		gets(arg3);
		argc++;
		argv[3] = arg3;
	}
	if(argc == 4){
		printf("\nAll necessary parameters are in place.\n***\n");
	}
	
	strcpy(hpsname, argv[1]);
	strcpy(wavLname, argv[2]);
	strcpy(wavRname, argv[3]);
	
	spawnl(P_WAIT, "dspadpcm.exe", "dspadpcm.exe", "-e", wavLname, NULL);
	spawnl(P_WAIT, "dspadpcm.exe", "dspadpcm.exe", "-e", wavRname, NULL);
	//this creates info files...delete them?
	
//clear the original WAV names.
//Basically, it looks for the ".wav" at the end of the name
//and cuts it out so that the name can be used for the DSP name a few
//lines below.
	test = strlen(wavLname)-4;
	if(wavLname[test] == '.') wavLname[test] = 0;
	if(wavLname[test+1] == 0) printf("Looking for L WAV channel file.\n");
	test = strlen(wavRname)-4;
	if(wavRname[test] == '.') wavRname[test] = 0;
	if(wavRname[test+1] == 0) printf("Looking for R WAV channel file.\n");
	
//make string with WAV L and R names to pass to be DSPs
	strcat(wavLname, ".dsp"); 	//adding the previous wav names that we cut up
	strcat(wavRname, ".dsp");
	
	//open the files for work
	if((hps = fopen(hpsname , "rb")) == NULL){
			printf("Error: Cannot open HPS file.\n");
			return 1;
	}
	if((dsp1 = fopen(wavLname , "rb")) == NULL){
			printf("Error: Cannot open DSP left channel file.\n");
			return 1;
	}
	if((dsp2 = fopen(wavRname , "rb")) == NULL){
			printf("Error: Cannot open DSP right channel file.\n");
			return 1;
	}
	if((tmp = fopen("temp.hps" , "wb")) == NULL){
			printf("Error: Cannot create temp file .\n");
			return 1;
	}
	printf("Reading HPS and new DSPs...\n");
	
//read header of the header into readbuf - only 0x20 bytes
	fseek(hps, 0, 0);
	for(x=0; x<0x20; x++){				
		readbuf[x] = getc(hps);
	}	
	sam0 = get32bit(readbuf+0x8);
	printf("HPS Sample rate: %i\n", get32bit(readbuf+0x8));
	printf("HPS Channels:    %i\n", get32bit(readbuf+0x0c));
	
//DSP L
	fseek(dsp1, 0, 0);
	for(x=0; x<0x1c; x++){				
		readbuf[x] = getc(dsp1);
	}	
	for(x=0x0; x<0x20; x++){				
		coef_L[x] = getc(dsp1);
		//printf("%08x\n", coef_L[x]);
	}	
	sam1 = get32bit(readbuf+0x8);
	printf("L DSP Sample rate: %i\n", sam1);
	
//DSP R
	fseek(dsp2, 0, 0);
	for(x=0; x<0x1c; x++){				
		readbuf[x] = getc(dsp2);
	}
	for(x=0x0; x<0x20; x++){				
		coef_R[x] = getc(dsp2);
	}	
	sam2 = get32bit(readbuf+0x8);
	printf("R DSP Sample rate: %i\n\n", sam2);
	if(sam1 != sam2){
		printf("Sample rates for left and right DSP channels don't match\n");
		return 1;
	}
	if((sam0 != sam1)|| (sam0 != sam2)){
		printf("Sample rate for HPS doesn't match that for the DSP channels.\n");
		return 1;
	}
	
//copy header and coefficient data to TMP.
//total of 0x80 bytes copied.
	//" HALPST"
	fseek(hps, 0, 0);
	for(x=0;x<0x20;x++){
		ch = getc(hps);
		putc(ch, tmp);	
	}	
	
	//L coefficients
	fseek(hps, 0x20, 0);
	for(x=0;x<0x20;x++){
		putc(coef_L[x], tmp);
		//printf("%08x\n", coef_L[x]);
	}
	
	//inter-coefficient data
	fseek(hps, 0x40, 0);
	for(x=0;x<0x18;x++){
		ch = getc(hps);
		putc(ch, tmp);
	}
	
	//R coefficients
	for(x=0;x<0x20;x++){
		putc(coef_R[x], tmp);
	}
	
	//last 8 bytes
	fseek(hps, 0x78, 0);
	for(x=0;x<8;x++){
		ch = getc(hps);
		putc(ch, tmp);
	}
	
	//set variables for the upcoming loop
	chans = 2;
	start_offset = 0x80;
	l_count = 0x60;
	r_count = 0x60;
	counter = 0;
	total_time = 0;
	
//Start while loop for block data.
//This loops through the blocks and copies them
//one by one to the temp.hps file.
	while(1){
		fseek(hps, start_offset, 0); //offset for the block header
		for(x=0; x<0x20; x++){				
			readbuf[x] = getc(hps);
			ch = readbuf[x];
			putc(ch, tmp);
		}	
		block_length = get32bit(readbuf); 
		channel_length = (block_length/2);
		time = (channel_length*1.792)/32776;
		printf("offset:%08x  length:%08x   secs:%5.3f   total secs:%5.3f\n", start_offset, channel_length, time, total_time); 
		total_time += time;
		block_nibbles = get32bit(readbuf+0x4)+1;
		next_offset = get32bit(readbuf+0x8); 
		//chanlen_check = (next_offset - (start_offset+0x10))/2;
		//printf("check:%08x\n", chanlen_check);
		/*if (chanlen_check != channel_length){
			printf("Channel checks don't match, check program math.\n");
			return 1;
		}*/
		if(next_offset<start_offset){
			printf("Loop in %s from offset %08x back to %08x\n", argv[1], start_offset, next_offset);
			loop_flag = true;
		}			
		else start_offset = next_offset;
		
		fseek(dsp1, l_count, 0);
		for(x=0;x<channel_length;x++) {
			ch = getc(dsp1);
			putc(ch, tmp);
			l_count++;
		}
		//printf("%08x\n", l_count);
		
		fseek(dsp2, r_count, 0);
		for(x=0;x<channel_length;x++) {
			ch = getc(dsp2);
			putc(ch, tmp);
			r_count++;
		}
		//printf("%08x\n", r_count);
		counter++;
		if(loop_flag){
			printf("%i audio blocks, %5.3f seconds\n", counter, total_time);
			break;
		}			
	}
	printf("closing files...\n");
	
	
//Clean up
	fseek(hps, 0,0);
	fclose(hps);
	fclose(dsp1);
	fclose(dsp2);
	fclose(tmp);	
	
	/*
GENERAL STEPS TO THE PROGRAM
	1. create HPSname, WAVLname, WAVRname
	2.	a. run "dspadpcm -e WAVLname" , then run "dspadpcm -e WAVRname"
	 	b. delete info files that it creates, or disable them somehow??? yes or no??
	3. fopen() HPS, DSP1, DSP2, TMP
	4. make sure that
		a. channels == 2
		b. DSP1 sample rate == DSP2 sample rate
	5.get 
		a. DSP1 and DSP2 coefs into HPS file. 
		b. DSP1 and DSP2 sample rates into HPS file.
	6.start data copy
		a. start_offset = 0x80;
		b. while(!feof(HPS))
			a. fseek(HPS, start_offset, 0);
			b. read header into readbuf
				1. int block_length = get32bit(readbuf); 
				2. int channel_length = (block_length/2)+8;
					a. int chanlen_check = (next_offset - current_offset)/2;
					b. if(chanlen_check != channel_length) throw error, and double check math
				3. int next_offset = get32bit(readbuf+0x8); 
				4. if(next_offset<start_offset) throw loop flag;
				5. else start_offset = next_offset;
			b. for(x=0;x<channel_length;x++) 
				1. keep a l_count and a r_count for advancing the fseek on the DSPs
				2. copy data from channel 1 (L) DSP to TMP to start of data, after header 
				2. repeat for second channel (R) DSP
			c. if loop flag thrown -> last block....break out of while loop;
			d. else loop back to while
	7. clean up
		a. fclose HPS, DSP1, DSP2, TMP
		b. keep TMP file
	*/
	
	return 0;	//end of program
}

int get32bit(unsigned char* p)
{
	//this is from hcs (Halley's Comet Software)
	//I got this idea from their in_cube winamp plugin
	//it transforms char[] values into their hex data equivalent
	//for 32 bits, or four bytes, of hex data
	return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
}


Code:
/*  
tpl_insert.exe - makes TPLs and inserts them in the right places given a DAT to edit

This program can read image and palette data 
from TPL files (which it can also generate), 
and insert them in the proper places in their
corresponding DAT files.

It can read offset data from "offsets.txt", 
hopefully provided in the same directory. 

Parameters
>>tpl_insert(DAT ## [-v] [-t])
where DAT is the dat to edit, and ## is the 
texture number in the directory.
-v is the optional verbose flag, default to false - if true, will spit out extra info to the console
-t is the optional TexConv flag, default to false - if true, will run TexConv to make the TPL file

Example of Use
C:\Documents and Settings\Admin>tpl_insert PlCaNr.dat 10 -t
--this will look for PlCaNr.dat, check the TCS file named 
"10.tcs", and then run TexConv.exe. Then, it will look 
for "offsets.txt" to find the correct offset for texture 
number 10, and then insert the TPL in a new PlCaNr.dat 
at that offest.

Program written by GodFed of smashboards.com, with many thanks
to S. of Stack Smash. Permission is granted to copy, modify,
distribute, etc. as long as no personal profit is made. That's all. 

Last updated 12/14/10 
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <process.h>

void changeToHex(char *offset, long& location);
int replaceMagenta(FILE *tmpt, FILE *tpl, char *tplname, long offset);
int get16bit(unsigned char * p);
int get32bit(unsigned char * p);
int parse_args(char* filename, char* filenum);


int main(int argc, char *argv[])
{
    FILE *dat, *tpl, *tmp, *off, *tcs, *tmpt;		//for file I/O
    unsigned char readbuf[0x400];					//for bitwise functions get16bit() and get32bit()
	char ch;                        				//for copying and appending to file
    char str[80];									//I use scanf(str) as a makeshift 'pause' function
	char filename[80], tplname[80], tcsname[80];	//for names of files to open
	char filenum[3], cmp[3], offset[9], splat[2]; 	//for various input operations
    int counter, x;                 				//for iterations
    long tplhead, paldata, magenta;					//recipients of get32bit() and get16bit() returns
    long donde, w, y;                  				//for fseek
    bool verboseflag, texflag;						//parameter flags for verbose mode and TexConv.exe call
    bool argd;                      				//now being used for checking if offset points to _9 or _8 textures
    
    verboseflag = false;
    texflag = false;
    argd = true;
    
    

	if(argc >= 4){ //check for flags
		for(x=0; x<argc; x++){		
			if(argv[x][0] == '-'){
				if(argv[x][1] == 'v') verboseflag = true;
				if(argv[x][1] == 't') texflag = true;		
			}
		}
	}
	printf("tpl_insert v0.93 (updated 9/12/09)\n\n");	
    if(verboseflag){
 		printf("*******************************\n");
 		printf("**Melee: TPL Texture Inserter**\n");
 		printf("*******************************\n\n");
 		printf("This program will replace  TPL \nfiles in the DAT based on their number.\n***\n");
	}


    if(argc <= 1){
            printf("\nPlease provide the DAT file to be edited (including extension)\n");
            gets(filename);
            argc++;
            argv[1] = filename;
    }
    if(argc == 2){
            printf("\nPlease provide the ## of the TPL.\n");
            gets(filenum);
            argc++;
            argv[2] = filenum;
            argd = true;
    }    
    if(argc >= 3){
            printf("All necessary parameters are in place.\n***\n");
            argd = true;
    }
    for(x=0;x<80;x++){
		tplname[x] =0;
		tcsname[x]=0;
	}
    
    strcpy(tplname, argv[2]);
    strcpy(tcsname, tplname);
    strcat(tplname, ".tpl");
    strcat(tcsname, ".tcs");    

  
//find which offset to go to.
    if((off = fopen("offsets.txt", "rb")) == NULL){
           printf("Error: Cannot open offsets.txt for read.\n");
           return 1;
    }
    donde = 0;
    w = 0;
    while(1){
           fseek(off, w, 0); //fseek to location W of offset txt file
           fgets(cmp, 3, off); //read the next two chars, plus one null byte
           //printf("cmp: %s\n", cmp); //debug info
           if((cmp[0] == argv[2][0]) && (cmp[1] == argv[2][1])){ 
                //printf("successss");
                w+=4;
                fseek(off, w, 0);   //fseek 4 bytes farther
                fgets(splat, 2, off); //fgets the next byte, plus one null byte
                if(splat[0] == '*'){  //check if the byte is an asterisk, denoting more complex formats
                     argd = false;
                }
                w+=1;
                fseek(off, w, 0); //fseek one byte farther
                fgets(offset, 9, off); //fgets offset data in char bytes, 8 chars plus one null byte
                //printf("Data Offset: %s\n", offset);
                changeToHex(offset, donde);
                break;
           }
           w+=15;	//this should instead search for the 0D 0A for the newline characters
		   if(w > 1000*15){
				printf("Error: The number requested is not in the offsets.txt file.\n");
				return 1;
			}           
    }
    //printf("decimal offset: %i\n", donde);
    fclose(off); 

//make TPL
    if(texflag) spawnl(P_WAIT, "TexConv.exe", "TexConv.exe", tcsname, tplname, NULL);
    
//delete whatever's in tmp, create it if it doesn't exist
	if((tmp = fopen("tmp.dat" , "wb")) == NULL){
			printf("Error: Cannot reset temp file usage.\n");
			return 1;
		}
	if(verboseflag) printf("Created tmp.dat for temporary data storage.\n");
	fclose(tmp);
	
//if statements for opening the files
    if((dat = fopen(argv[1], "rb")) == NULL){
           printf("Error: Cannot open DAT file for read.\n");
           return 1;
    }
    if((tpl = fopen(tplname, "rb")) == NULL){
           printf("Error: Cannot open TPL file for read.\n");           
           return 1;
    }
    if((tmp = fopen("tmp.dat", "ab")) == NULL){
           printf("Error: Cannot open temp file for append.\n");
           return 1;
    }
    if(verboseflag) printf("Data Offset: %s\n", offset);
    
//Actual reading and writing to files goes here.
	//if _8 or _9 format
	if(!argd) {
	if(verboseflag) printf("Type: _8 or _9\n");
	/*
	future - - - check for magenta palette data, replace it 
	to check for magenta
	0. place this code after tplhead and paldata are given values
	1. read just the palette data from the paldata offset until you hit the tplhead offset
	2. for loop to get16bit() at every offset between readbuf[0] abd readbuf[(tplhead-paldata)-2]
	3. during that loop, check if the get16bit returns fc1f 
		if yes..
		a. create a tmpt.tpl file
		b. make sure that the offset of the magenta value is recorded
		c. copy up to that offset to tmpt.tpl
		d. append 00 00
		e. copy/append from two after the offset until eof
		f. copy tmpt.tpl to the original
	NEXT
		check next offset point? check if data is less than 32 lines...maybe for another time
	
	*/
	
		counter = 0;						//the counter keeps track of how long the TPL data is
	
		fseek(tpl, 0x0, 0); 				//start at beginning of file
		for(x=0; x<0x400; x++){				//copy first 1024 bits from TPL to readbuf
			readbuf[x] = getc(tpl);
		}	
		
		tplhead = get32bit(readbuf + 0xc);	//get tpl header location, which is 0x40 before the actual data
		paldata = get32bit(readbuf + 0x1c);	//get palette data location
		
		fseek(tpl, paldata, 0);
		for(x=0; x<tplhead-2; x++){
			readbuf[x] = getc(tpl);			
		}
		for(x=0; x<(tplhead-paldata)-2; x++){
			magenta = get16bit(readbuf + x);	
			if (magenta == 0xfc1f){
				y = x+0x20;
				if(verboseflag) printf("Magenta found at offset: %i\n", y);
				magenta = replaceMagenta(tmpt, tpl, tplname, y);
				if(magenta == 1) return 1;	
				break;
			}
		}
		
		
		fseek(dat, 0, 0);
		for(x=0; x<donde; x++){				//copy DAT info to TMP (append)
    	    ch = getc(dat);
    	    putc(ch, tmp);        
    	}    
    	
    	fseek(tpl, tplhead + 0x40, 0);		//fseek to TPL image data
    	while(!feof(tpl)){					//copy TPL image data to TMP (append)
			ch = getc(tpl);
			if(!feof(tpl)) putc(ch, tmp);
			counter++;						//keep track of length of data
		}
		
		fseek(tpl, paldata, 0);
		for(x=paldata; x<tplhead; x++){		//copy TPL palette data to TMP (append)
			ch = getc(tpl);					//this loop iterates from paldata to tplhead
			if(!feof(tpl)) putc(ch, tmp);	
			counter++;						//keeping track of length of both datas added together
		}
		
		donde = counter + donde - 1;		//update the end-of-data location in DAT 
    	fseek(dat, donde, 0);
    	while(!feof(dat)){					//copy rest of DAT to TMP (append)
    	    ch = getc(dat);
    	    if(!feof(dat)) putc(ch, tmp);                            
    	}     	
	//if _14 CMPR format
	}else if(argd){
	if(verboseflag) printf("Type: _14 CMPR\n");
	/* no comment */
    	counter = 0;  
    	fseek(dat, 0, 0);
    	for(x=0; x<donde; x++){
    	    ch = getc(dat);
    	    putc(ch, tmp);        
    	}    
    	fseek(tpl, 0x40, 0);         //offset start for tpl data
    	while(!feof(tpl)){
    	    ch = getc(tpl);
    	    if(!feof(tpl)) putc(ch, tmp);
    	    counter ++;
    	}    
    	donde = counter + donde - 1;
    	fseek(dat, donde, 0);
    	while(!feof(dat)){
    	    ch = getc(dat);
    	    if(!feof(dat)) putc(ch, tmp);                            
    	} 
	}	
 	
    fclose(dat);
    fclose(tpl);
    fclose(tmp); 
    
    
//Copy TMP contents to DAT and delete TMP
    if((dat = fopen(argv[1], "wb")) == NULL){
        printf("Error: Cannot open DAT file for rewrite.\n");
        return 1;
    }
    if((tmp = fopen("tmp.dat", "rb")) == NULL){
        printf("Error: Cannot open temp file for reread.\n");
        return 1;
    }
    
    fseek(tmp, 0, 0);
    while(!feof(tmp)){
        ch = getc(tmp);
        if(!feof(tmp)) putc(ch, dat);
    }
    fclose(dat);
    fclose(tmp);
    if(remove("tmp.dat")==-1) {
        printf("Error: Cannot delete tmp.dat");
        return 1;
    }
    if(verboseflag) printf("Copied tmp.dat to %s and deleted tmp.dat successfully.\n", argv[1]);
 	//scanf(str);
//  system("PAUSE"); wtf. this made the program like 465 kb. I hate iostream.
    return 0;
}



void changeToHex(char *offset, long& location)
{
//This function multiplies the nth digit from the right by 16^(n-1)
//and then adds all these values together until n <= 0,
//effectively converting hex to decimal, but really just
//converting from char[] to long
    int p, q, r;
    long base;
    location = 0;
    for(p=7; p>0; p--){
           base = 16;
           for(q=(p-1); q>0; q--){
                  base *= 16;
                 // printf("base: %i\n", base); debug info
           }
           switch(*offset){
                  case '0':r=0; break;
                  case '1':r=1; break;
                  case '2':r=2; break;
                  case '3':r=3; break;
                  case '4':r=4; break;
                  case '5':r=5; break;
                  case '6':r=6; break;
                  case '7':r=7; break;
                  case '8':r=8; break;
                  case '9':r=9; break;
                  case 'a':
                  case 'A':r=10; break;
                  case 'b':
                  case 'B':r=11; break;
                  case 'c':
                  case 'C':r=12; break;
                  case 'd':
                  case 'D':r=13; break;
                  case 'e':
                  case 'E':r=14; break;
                  case 'f':
                  case 'F':r=15; break;
           }
           //printf("offset: %i\n", r);
           *offset ++;
           location = location + (base*r);
           //printf("location: %i\n\n", location);     
    }
     
}

int replaceMagenta(FILE *tmpt, FILE *tpl, char *tplname, long offset)
{
	int z;
	char ch;
	/*if yes..
		*/	

	if((tmpt = fopen("tmpt.tpl", "ab")) == NULL){
		printf("Error: Cannot create tmpt.tpl for append.\n");
		return 1;
	}
	
	fseek(tpl, 0, 0);				//seek to 0 for offset with MAGENTA
	for(z=0; z<offset; z++){		//copy up to that point, add it to tmpt
		ch = getc(tpl);
		putc(ch, tmpt);		
	} 
	fseek(tpl, 0x4, 0);				//seek to offset 0x4, whose two bytes are always 00 00
	for(z=0;z<2;z++){				//copy them to where the MAGENTA used to be
		ch = getc(tpl);
		putc(ch, tmpt);	
	}
	fseek(tpl, offset+2, 0);		//seek 2 past the original offset, aka, right after the MAGENTA change
	while(!feof(tpl)){				//copy/append from there to eof
   	    ch = getc(tpl);
   	    if(!feof(tpl)) putc(ch, tmpt);                            
   	} 
	
	fclose(tmpt);
	fclose(tpl);					//close the tpl that was open for read
	if((tpl = fopen(tplname, "wb")) == NULL){//open it again for write, which clears it
		printf("Error: Cannot open %s to replace MAGENTA value.\n", tplname);	
		return 1;
	}
	if((tmpt = fopen("tmpt.tpl", "rb")) == NULL){
		printf("Error: Cannot open tmpt.tpl for reread and copy.\n");
		return 1;	
	}
	fseek(tmpt, 0, 0);				//copying tmpt.tpl over original TPL
	while(!feof(tmpt)){
        ch = getc(tmpt);
        if(!feof(tmpt)) putc(ch, tpl);
    }
    fclose(tpl);
    fclose(tmpt);
    if(remove("tmpt.tpl")==-1) {
        printf("Error: Cannot delete tmpt.tpl");
        return 1;
    }
    
    //since TPL was open before the funtion call, reopen it the way it was before
    if((tpl = fopen(tplname, "rb")) == NULL){
		printf("Error: Cannot open %s for read.\n", tplname);
		return 1;		
	}
	
	
}

int get16bit(unsigned char* p) 
{
	//this is from hcs (Halley's Comet Software)
	//I got this idea from their in_cube winamp plugin
	//it transforms char[] values into their hex data equivalent
	//for 16 bits, or two bytes, of hex data
	return (p[0] << 8) | p[1];
}

int get32bit(unsigned char* p)
{
	//this is from hcs (Halley's Comet Software)
	//I got this idea from their in_cube winamp plugin
	//it transforms char[] values into their hex data equivalent
	//for 32 bits, or four bytes, of hex data
	return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
}

int parse_args(char* filename, char* filenum)
{
	/*
	This will switch() the args with the filename and ##, and 
	use stored values to return the offset
	
	
	*/
	
	
	
}
Oh and by the way, I went to GSG2 in Concord this weekend and met some awesome people. I only stayed for one day, but it was fun. There was a station set up with hacked Melee, and all the cool people played on it :D
 

Tcll

Smash Lord
Joined
Jul 10, 2010
Messages
1,780
Location
The Gates of Darkness
NNID
Tcll5850
@GodFed:

what do your proggs do exactly??

they work with HPS files I know...
but what do they "do"

and DevC++ :o
nice :D

screw microsoft and all it's glory
I have DevC++ too :)

eat that microsoft XDD
 

nube

Smash Apprentice
Joined
Jun 20, 2010
Messages
166
Back. My whole "colour change" thing should be ready tonight. Should I start a new thread for it? I think I might need to. Someone start nagging me to get going before I get lazy XD
 

GodFed

Smash Apprentice
Joined
Mar 25, 2009
Messages
160
Location
Hendrick House, Urbana, IL
hps_insert takes the audio from two WAV channels and puts that inside an existing HPS file, essentially overwriting the previous audio data in that HPS file.

tpl_insert was the first program I made for melee. It opens a DAT file, creates a TPL file (depending on the parameters) and then reads a text file to find the right offset for that TPL file.

In other news, I was looking through Magus' posts, and I have to say, he is a god.
 

Tcll

Smash Lord
Joined
Jul 10, 2010
Messages
1,780
Location
The Gates of Darkness
NNID
Tcll5850
:o
like that HPS program

does it loop from a specific point??

aperently alot of melee music does that :p

EDIT:
hey...
do you understand the relocation table by chance??

I basically need to know how to tell the different data's from it...
can you provide a well commented code if you do please :|
 

Steelia

Smash Champion
Joined
Sep 23, 2007
Messages
2,523
Location
Home.
Back. My whole "colour change" thing should be ready tonight. Should I start a new thread for it? I think I might need to. Someone start nagging me to get going before I get lazy XD
NEW THREAD :D
Just be sure to link in here. I keep forgetting to check out the other topics in this new subforum thing. >_>
 

GodFed

Smash Apprentice
Joined
Mar 25, 2009
Messages
160
Location
Hendrick House, Urbana, IL
@tcll
Yes, I understand the relocation table, more or less. It's really important for finding the attack attributes in the Pl**.dat files, apart from other things. I'll be sure to explain it in some code when I post it.

@libertyernie
No problem. It's fairly basic c++, but I'm glad to help. I'm looking forward to your finished meleetool.
 

WarriorKnight

Smash Ace
Joined
Sep 10, 2004
Messages
933
Location
Queens, NY
Back. My whole "colour change" thing should be ready tonight. Should I start a new thread for it? I think I might need to. Someone start nagging me to get going before I get lazy XD

Do it do it!!!

Posting it here should be good enough.

I have some exclusive unlreleased stuff I wanna share with you guys myself :)
Will start providing links soon :)
 

Tcll

Smash Lord
Joined
Jul 10, 2010
Messages
1,780
Location
The Gates of Darkness
NNID
Tcll5850
hey...
jsyk,
I'll have to perfect a few things in my tmp format before an export method to dat's can be achived...

so yea...
I'll just make the dat to *** converter for now

I'll add the export part in a later version...

that goes for mdl0 as well
at least I have some code there though :bee:

right now the only method taking place is mdl0 to obj
(obj for testing)

once I can get some info on the other formats, I'll work on those too :)
 

L-a-t-e-r-a-l-u-s

Smash Ace
Joined
Dec 18, 2009
Messages
811
Drew up my concepts for Peach, starting on some for Samus. When I get a chance to scan my drawings, I'll post them if anyone is interested.
 

GawdImFoxy

Smash Journeyman
Joined
Jul 6, 2007
Messages
262
Location
West Frankfort, IL
I don't understand steps 6 and 7 in the texture hacking. I loaded the Pl***.dat file and did a search for the string in Steelia's placement file and it didn't return any results. I figured I just misunderstood what it meant, so I tried loading the .tpl file and searching for that same string. Did I miss something? Also, in the Pl***.dat files, how do I know which files refer to which texture?

I get the feeling I'm WAY off. Any advice? I've never modded or hacked anything so I'm sorry for being noobsauce. :(

Edit: The hex editor I'm using is called XVI32. Not sure if that matters or not.

Edit2: Can I just download premodded textures and replace a file one-for-one and have it run fine? If so, how do I know which file(s) to replace?
 

Steelia

Smash Champion
Joined
Sep 23, 2007
Messages
2,523
Location
Home.
Merry Christmas :)

I don't understand steps 6 and 7 in the texture hacking. I loaded the Pl***.dat file and did a search for the string in Steelia's placement file and it didn't return any results. I figured I just misunderstood what it meant, so I tried loading the .tpl file and searching for that same string. Did I miss something? Also, in the Pl***.dat files, how do I know which files refer to which texture?

I get the feeling I'm WAY off. Any advice? I've never modded or hacked anything so I'm sorry for being noobsauce. :(

Edit: The hex editor I'm using is called XVI32. Not sure if that matters or not.

Edit2: Can I just download premodded textures and replace a file one-for-one and have it run fine? If so, how do I know which file(s) to replace?
Mm, here's the problem with searching for strings: the .TPL file does not copy the string in the .DAT file word-for-word. There are SLIGHT changes that throw it off... You have to guess 'n check it; that's how I found my placements. (You'll know you screwed up when the final product doesn't look very pretty after hexing. :p )

http://www.youtube.com/watch?v=Bg8Rbf0Te4g

Made that for non-indexed textures. Hopefully that helps out, if you haven't already seen it. >.>
While it would be easier to have the hex editor mentioned, if you have an idea of how to put two and two together, it's... pretty much the same process. Copy-paste. ;)
 

GodFed

Smash Apprentice
Joined
Mar 25, 2009
Messages
160
Location
Hendrick House, Urbana, IL
Relocation Tables

Each value in the relocation table is an offset that points to some place in the DAT file. When we go to that place (plus 0x20), we find another offset that points somewhere else in the DAT file. When we go to that place (plus 0x20), we find the data.
In lieu of posting commented code, I think I'll just explain what the relocation tables are. My code is getting a bit more complex now that I understand DAT files more, and I couldn't quite finish it as soon as I wanted to. So here is an explanation of relocation tables and how to use them.

First off, revel8n has very detailed and useful information HERE about DAT files. Revel8n explains the structure of DAT files, the various data structures that you encounter in them, and code to complement it. It’s aimed toward programmers. I don’t want to undercut his work with this post, he’s done a great job pooling together a lot of dense information. I guess this post is an explanation of what to do with relocation tables, not so much what they are.

I use 010 Hex Editor as my hex editor. It supports templates, just like HexEdit, but I like 010 better than HexEdit. It’s not free, but I just use the trial version anyway. I use revel8n’s DATTemplate.bt as my template. I don’t remember how I got hold of it, but revel8n made it.

As revel8n stated in his post, DAT files are broken up as follows
-Header
-Data
-Relocation Table
-Root Nodes
-String

The relocation table apparently is the confusing bit. Basically, it’s a list of offsets inside the DAT file. Each value in the relocation table is an offset pointing somewhere in the file. An important thing to remember is that the Header is 0x20 bytes long, though. Every offset that’s pointed to by the relocation table should be added to 0x20 to get the real offset. So if the relocation table value you’re looking at is “0x00000004,” then the offset that it’s pointing to is actually 0x00000024. If you don’t understand anything so far, just bear with me and keep reading.




So let’s go to 0x00000024 and see what’s there. What we have is another offset. This points somewhere else in the file (plus 0x20 bytes of course). The place that this offset points to is actually important data. In the picture, the value at 0x00000024 is “0x00006EEC,” so I’ll add 0x20. Now I know that the data that was coded for at that one spot on the relocation table is at offset 0x00006F0C.



Let’s recap. Each value in the relocation table is an offset that points to some place in the DAT file. When we go to that place (plus 0x20), we find another offset that points somewhere else in the DAT file. When we go to that place (plus 0x20), we find the data. Now, the data is different depending on the file, and on the order of the relocation offsets.

Here’s an example using TPL files:
I’m using PlCaNr.dat, which has all CMPR textures, I think. I have PlCaNr.dat open, and I have some TPL files that I created with TexConv that correspond to the CaNr textures. I also have a list of offsets for each texture, courtesy of Steelia. I’ll use Hex Edit, since 010 makes it super easy, and I want to do it step by step here instead of all at once.



So here we go. I open PlCaNr.dat in HexEdit. I go to the relocation table at the end, and find that it’s at offset 0x0007EC60 (you can usually just look near the end for similar looking values and know that that’s the relocation table). The first one has a value of “0x00008998”. Add 0x20, and I get 0x000089B8. I go to that offset, and see the value there is “0x0007DC40”. Plus 0x20 is 0x0007DC60. I go to that offset, and guess what, that’s the start of some texture data! In fact, it’s the start of texture number 44 in Steelia’s texture pack. Isn’t that interesting…
Also check out the picture below. Right after the offset value at 0x000089B8, there are some familiar looking values. In fact, it’s the width and height of the corresponding TPL – number 44. Hmmm.




If you happen to have 010 Hex Editor and the DATTemplate.bt file, then it’s a bit easier for you. Open up PlCaNr.dat, and DATTemplate will color all the necessary bits and pieces for you in the hex data. At the bottom of the screen, all the stuff is laid out for you – the relocation table, the offsets pointed to, and the final data locations. Just click and go. That’s about it.

Now you know what the relocation table is good for – it shows where important data is in the DAT file. It’s up to you people to find that data and interpret it. If you look at revel8n’s post about DAT files, he has a bunch of info about the different types of data in DAT files, and what they look like. For instance, I just talked about TPL data briefly above. There’s also hitbox data, joint data, and a bunch of other stuff. So get going.

EDIT: The second image is a bit messed up, it seems. Idk. Nevermind, just my browser.
EDIT2: Fun stuff - Change the value at 0x37CC in PlCa.dat for infinite jumps on Captain Falcon. It's normally 00000002, if you change it to higher values, you get infinite jumps no matter what.
 

Tcll

Smash Lord
Joined
Jul 10, 2010
Messages
1,780
Location
The Gates of Darkness
NNID
Tcll5850
I had 010E but I stopped using it because I couldn't use it for over 30 days and wasn't getting nowhere with it...

was getting little help without it...
^why I know so little now...
all those wasted years... DX>

I've gotten the offsets figured out...

but I cant get no further than that...

EDIT:
reading your post

EDIT2:
so what Revel didn't tell me was there was a 2nd offset...
THAT WOULD'VE BEEN NICE TO KNOW!!

gawd...
stuff like that just P's me off...

he told me everything else but that D:<
geeze
and just think...
I could've been where he's at now...

whatever...
it's not what I could've done...
but what I can do now...

thank you GF
 

Tcll

Smash Lord
Joined
Jul 10, 2010
Messages
1,780
Location
The Gates of Darkness
NNID
Tcll5850
look what I found:
http://lh3.ggpht.com/_IteXPmeC6ek/TRZzdz25WSI/AAAAAAAACP8/wLA9XFWUEls/discovery.jpg

I think the relocation table cantains offsets to the object data...
I originally thought that was bone data -.-

anyways notice a patteren with the offsets ;)

I'll have to figure out what those are through the reading and what not...

thanx again :)

EDIT:
I'll continue the discussion on the other thread...

after I yell at revel for not telling me XDD
 

revel8n

Smash Cadet
Joined
Dec 1, 2009
Messages
51
@GodFed:
Thanks for the further clarification. i have specified details in this manner on other sites and in emails, but i don't think i have done the same here on these forums yet. i am glad to see the breakdown has hopefully cleared things up.

-----------------------

i saw these posts after i responded in my other thread, heh. As such i will just respond, briefly, and edit the one in my thread as needed to further clarify things.

- The relocation table serves two purposes from my research, convenience and validation.
- Although there are patterns at times, there is no reliable order or other structure related information given by this table.
- Following root nodes is a far more reliable method of gaining access to desired information once the various data structures are known.

Although, i will mention that the relocation table becomes very important if adding, moving or resizing data is desired.

-------------------------

i guess, it may also help me if you re-state, or link me to any lingering questions and other issues you have on the format information presented to far. i'll try and see if can step out of my own mindset and explain them as clear as i can.
 

nuro

Smash Lord
Joined
Jan 1, 2006
Messages
1,101
Location
Somerville/Lowell, Massachusetts USA
Hey, what's up.
Here are those source code files I promised way back. I decided not to do filesharing, it's just simpler to post the whole code here. If there's an issue with this, tell me and I'll fix it.

First is hps_insert.cpp, then tpl_insert.cpp
I wrote and compiled them in Dev-C++. It's kinda sloppy c++, but hey. It works.

I have a hitbox analyzer program that I just wrote, but it's a bit messy right now. I'll refine it and post it soon. Maybe it'll be a Christmas present for you fine people. What it does so far is look in a character file and analyze every single action that the character makes (like nair, upB, jab, dtilt, spot-dodge, taunt, etc). It checks for hitboxes, grab-boxes, whatever, then at the individual values (damage, angle, knockback, sound fx, etc). It spits it all into a txt file. So yeah.


Code:
/*
hps_insert.exe
--creates HPS files from a supplied HPS file and two channels of audio
--will fit the new HPS to the supplied HPS structure and size

--you need to have dspadpcm.exe in the same directory as hps_insert.exe
--you need to have soundfile.dll and dsptool.dll in the directory, too

Parameters
>>hps_insert (hps_name r_wav l_wav)
hps_name is the name of the HPS file you're going to supply as a model.
r_wav is the name of the mono WAV file that is the right channel that you want.
l_wav is the name of the mono WAV file that is the left channel that you want.

Example of use
C:\Documents and Settings\Admin>hps_insert hyaku.hps battleR.wav battleL.wav
--this will create an HPS file called "temp.hps", which will have the exact
same structure as the hyaku.hps file, while having the audio from battleL.wav
and battleR.wav

Program written by GodFed of smashboards.com, with HPS structure info from 
hcs of halley's comet software. Permission is given to copy, distribute, 
etc as long as you don't make any money from it. 

10/11/2010
*/

#include <stdio.h>
#include <string.h>
#include <process.h>
#include <inttypes.h>

int get32bit(unsigned char * p);

int main(int argc, char *argv[])
{
    FILE *hps, *dsp1, *dsp2, *tmp, *infile;                        //FILE stuff..
    long start_offset, current_offset, next_offset;                //offset variables for fseek() and fgetc() in FILE *hps 
    long l_count, r_count;                                        //keep track of where I am when copying left DSP and right DSP to HPS
    int block_length, channel_length, chanlen_check, chans, block_nibbles;        //variables for HPS audio blocks
    int sam0, sam1, sam2;                                        //sample rate checker variables
    int x, test, counter;                                        //loops, I think
    float time, total_time;                                        //time for each block, total time for all of the blocks to that point
    char ch;                                                    //for copying files character by character
    unsigned char readbuf[128];                                    //for get32bit() 
    char hpsname[80], wavLname[80], wavRname[80], txtname[80];    //arguments for various functions in string form - they're just necessary
    char coef_L[32], coef_R[32];                                //coefficient data for L and R DSPs
    char arg1[80], arg2[80], arg3[80];                            //argument strings in case all parameters are not met
    bool loop_flag = false;                                        //does the HPS loop? initially set to false
    
    printf("hps_insert v1.2 by GodFed\nwith help from hcs\n");
    printf("-updated 10/11/10\n");
    
    if(argc == 1){
        printf("\nPlease provide the HPS name.\n");
        gets(arg1);
        argc++;
        argv[1] = arg1;
    }
    if(argc == 2){
        printf("\nPlease provide the WAV left channel name.\n");
        gets(arg2);
        argc++;
        argv[2] = arg2;
    }
    if(argc == 3){
        printf("\nPlease provide the WAV right channel name.\n");
        gets(arg3);
        argc++;
        argv[3] = arg3;
    }
    if(argc == 4){
        printf("\nAll necessary parameters are in place.\n***\n");
    }
    
    strcpy(hpsname, argv[1]);
    strcpy(wavLname, argv[2]);
    strcpy(wavRname, argv[3]);
    
    spawnl(P_WAIT, "dspadpcm.exe", "dspadpcm.exe", "-e", wavLname, NULL);
    spawnl(P_WAIT, "dspadpcm.exe", "dspadpcm.exe", "-e", wavRname, NULL);
    //this creates info files...delete them?
    
//clear the original WAV names.
//Basically, it looks for the ".wav" at the end of the name
//and cuts it out so that the name can be used for the DSP name a few
//lines below.
    test = strlen(wavLname)-4;
    if(wavLname[test] == '.') wavLname[test] = 0;
    if(wavLname[test+1] == 0) printf("Looking for L WAV channel file.\n");
    test = strlen(wavRname)-4;
    if(wavRname[test] == '.') wavRname[test] = 0;
    if(wavRname[test+1] == 0) printf("Looking for R WAV channel file.\n");
    
//make string with WAV L and R names to pass to be DSPs
    strcat(wavLname, ".dsp");     //adding the previous wav names that we cut up
    strcat(wavRname, ".dsp");
    
    //open the files for work
    if((hps = fopen(hpsname , "rb")) == NULL){
            printf("Error: Cannot open HPS file.\n");
            return 1;
    }
    if((dsp1 = fopen(wavLname , "rb")) == NULL){
            printf("Error: Cannot open DSP left channel file.\n");
            return 1;
    }
    if((dsp2 = fopen(wavRname , "rb")) == NULL){
            printf("Error: Cannot open DSP right channel file.\n");
            return 1;
    }
    if((tmp = fopen("temp.hps" , "wb")) == NULL){
            printf("Error: Cannot create temp file .\n");
            return 1;
    }
    printf("Reading HPS and new DSPs...\n");
    
//read header of the header into readbuf - only 0x20 bytes
    fseek(hps, 0, 0);
    for(x=0; x<0x20; x++){                
        readbuf[x] = getc(hps);
    }    
    sam0 = get32bit(readbuf+0x8);
    printf("HPS Sample rate: %i\n", get32bit(readbuf+0x8));
    printf("HPS Channels:    %i\n", get32bit(readbuf+0x0c));
    
//DSP L
    fseek(dsp1, 0, 0);
    for(x=0; x<0x1c; x++){                
        readbuf[x] = getc(dsp1);
    }    
    for(x=0x0; x<0x20; x++){                
        coef_L[x] = getc(dsp1);
        //printf("%08x\n", coef_L[x]);
    }    
    sam1 = get32bit(readbuf+0x8);
    printf("L DSP Sample rate: %i\n", sam1);
    
//DSP R
    fseek(dsp2, 0, 0);
    for(x=0; x<0x1c; x++){                
        readbuf[x] = getc(dsp2);
    }
    for(x=0x0; x<0x20; x++){                
        coef_R[x] = getc(dsp2);
    }    
    sam2 = get32bit(readbuf+0x8);
    printf("R DSP Sample rate: %i\n\n", sam2);
    if(sam1 != sam2){
        printf("Sample rates for left and right DSP channels don't match\n");
        return 1;
    }
    if((sam0 != sam1)|| (sam0 != sam2)){
        printf("Sample rate for HPS doesn't match that for the DSP channels.\n");
        return 1;
    }
    
//copy header and coefficient data to TMP.
//total of 0x80 bytes copied.
    //" HALPST"
    fseek(hps, 0, 0);
    for(x=0;x<0x20;x++){
        ch = getc(hps);
        putc(ch, tmp);    
    }    
    
    //L coefficients
    fseek(hps, 0x20, 0);
    for(x=0;x<0x20;x++){
        putc(coef_L[x], tmp);
        //printf("%08x\n", coef_L[x]);
    }
    
    //inter-coefficient data
    fseek(hps, 0x40, 0);
    for(x=0;x<0x18;x++){
        ch = getc(hps);
        putc(ch, tmp);
    }
    
    //R coefficients
    for(x=0;x<0x20;x++){
        putc(coef_R[x], tmp);
    }
    
    //last 8 bytes
    fseek(hps, 0x78, 0);
    for(x=0;x<8;x++){
        ch = getc(hps);
        putc(ch, tmp);
    }
    
    //set variables for the upcoming loop
    chans = 2;
    start_offset = 0x80;
    l_count = 0x60;
    r_count = 0x60;
    counter = 0;
    total_time = 0;
    
//Start while loop for block data.
//This loops through the blocks and copies them
//one by one to the temp.hps file.
    while(1){
        fseek(hps, start_offset, 0); //offset for the block header
        for(x=0; x<0x20; x++){                
            readbuf[x] = getc(hps);
            ch = readbuf[x];
            putc(ch, tmp);
        }    
        block_length = get32bit(readbuf); 
        channel_length = (block_length/2);
        time = (channel_length*1.792)/32776;
        printf("offset:%08x  length:%08x   secs:%5.3f   total secs:%5.3f\n", start_offset, channel_length, time, total_time); 
        total_time += time;
        block_nibbles = get32bit(readbuf+0x4)+1;
        next_offset = get32bit(readbuf+0x8); 
        //chanlen_check = (next_offset - (start_offset+0x10))/2;
        //printf("check:%08x\n", chanlen_check);
        /*if (chanlen_check != channel_length){
            printf("Channel checks don't match, check program math.\n");
            return 1;
        }*/
        if(next_offset<start_offset){
            printf("Loop in %s from offset %08x back to %08x\n", argv[1], start_offset, next_offset);
            loop_flag = true;
        }            
        else start_offset = next_offset;
        
        fseek(dsp1, l_count, 0);
        for(x=0;x<channel_length;x++) {
            ch = getc(dsp1);
            putc(ch, tmp);
            l_count++;
        }
        //printf("%08x\n", l_count);
        
        fseek(dsp2, r_count, 0);
        for(x=0;x<channel_length;x++) {
            ch = getc(dsp2);
            putc(ch, tmp);
            r_count++;
        }
        //printf("%08x\n", r_count);
        counter++;
        if(loop_flag){
            printf("%i audio blocks, %5.3f seconds\n", counter, total_time);
            break;
        }            
    }
    printf("closing files...\n");
    
    
//Clean up
    fseek(hps, 0,0);
    fclose(hps);
    fclose(dsp1);
    fclose(dsp2);
    fclose(tmp);    
    
    /*
GENERAL STEPS TO THE PROGRAM
    1. create HPSname, WAVLname, WAVRname
    2.    a. run "dspadpcm -e WAVLname" , then run "dspadpcm -e WAVRname"
         b. delete info files that it creates, or disable them somehow??? yes or no??
    3. fopen() HPS, DSP1, DSP2, TMP
    4. make sure that
        a. channels == 2
        b. DSP1 sample rate == DSP2 sample rate
    5.get 
        a. DSP1 and DSP2 coefs into HPS file. 
        b. DSP1 and DSP2 sample rates into HPS file.
    6.start data copy
        a. start_offset = 0x80;
        b. while(!feof(HPS))
            a. fseek(HPS, start_offset, 0);
            b. read header into readbuf
                1. int block_length = get32bit(readbuf); 
                2. int channel_length = (block_length/2)+8;
                    a. int chanlen_check = (next_offset - current_offset)/2;
                    b. if(chanlen_check != channel_length) throw error, and double check math
                3. int next_offset = get32bit(readbuf+0x8); 
                4. if(next_offset<start_offset) throw loop flag;
                5. else start_offset = next_offset;
            b. for(x=0;x<channel_length;x++) 
                1. keep a l_count and a r_count for advancing the fseek on the DSPs
                2. copy data from channel 1 (L) DSP to TMP to start of data, after header 
                2. repeat for second channel (R) DSP
            c. if loop flag thrown -> last block....break out of while loop;
            d. else loop back to while
    7. clean up
        a. fclose HPS, DSP1, DSP2, TMP
        b. keep TMP file
    */
    
    return 0;    //end of program
}

int get32bit(unsigned char* p)
{
    //this is from hcs (Halley's Comet Software)
    //I got this idea from their in_cube winamp plugin
    //it transforms char[] values into their hex data equivalent
    //for 32 bits, or four bytes, of hex data
    return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
}
Code:
/*  
tpl_insert.exe - makes TPLs and inserts them in the right places given a DAT to edit

This program can read image and palette data 
from TPL files (which it can also generate), 
and insert them in the proper places in their
corresponding DAT files.

It can read offset data from "offsets.txt", 
hopefully provided in the same directory. 

Parameters
>>tpl_insert(DAT ## [-v] [-t])
where DAT is the dat to edit, and ## is the 
texture number in the directory.
-v is the optional verbose flag, default to false - if true, will spit out extra info to the console
-t is the optional TexConv flag, default to false - if true, will run TexConv to make the TPL file

Example of Use
C:\Documents and Settings\Admin>tpl_insert PlCaNr.dat 10 -t
--this will look for PlCaNr.dat, check the TCS file named 
"10.tcs", and then run TexConv.exe. Then, it will look 
for "offsets.txt" to find the correct offset for texture 
number 10, and then insert the TPL in a new PlCaNr.dat 
at that offest.

Program written by GodFed of smashboards.com, with many thanks
to S. of Stack Smash. Permission is granted to copy, modify,
distribute, etc. as long as no personal profit is made. That's all. 

Last updated 12/14/10 
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <process.h>

void changeToHex(char *offset, long& location);
int replaceMagenta(FILE *tmpt, FILE *tpl, char *tplname, long offset);
int get16bit(unsigned char * p);
int get32bit(unsigned char * p);
int parse_args(char* filename, char* filenum);


int main(int argc, char *argv[])
{
    FILE *dat, *tpl, *tmp, *off, *tcs, *tmpt;        //for file I/O
    unsigned char readbuf[0x400];                    //for bitwise functions get16bit() and get32bit()
    char ch;                                        //for copying and appending to file
    char str[80];                                    //I use scanf(str) as a makeshift 'pause' function
    char filename[80], tplname[80], tcsname[80];    //for names of files to open
    char filenum[3], cmp[3], offset[9], splat[2];     //for various input operations
    int counter, x;                                 //for iterations
    long tplhead, paldata, magenta;                    //recipients of get32bit() and get16bit() returns
    long donde, w, y;                                  //for fseek
    bool verboseflag, texflag;                        //parameter flags for verbose mode and TexConv.exe call
    bool argd;                                      //now being used for checking if offset points to _9 or _8 textures
    
    verboseflag = false;
    texflag = false;
    argd = true;
    
    

    if(argc >= 4){ //check for flags
        for(x=0; x<argc; x++){        
            if(argv[x][0] == '-'){
                if(argv[x][1] == 'v') verboseflag = true;
                if(argv[x][1] == 't') texflag = true;        
            }
        }
    }
    printf("tpl_insert v0.93 (updated 9/12/09)\n\n");    
    if(verboseflag){
         printf("*******************************\n");
         printf("**Melee: TPL Texture Inserter**\n");
         printf("*******************************\n\n");
         printf("This program will replace  TPL \nfiles in the DAT based on their number.\n***\n");
    }


    if(argc <= 1){
            printf("\nPlease provide the DAT file to be edited (including extension)\n");
            gets(filename);
            argc++;
            argv[1] = filename;
    }
    if(argc == 2){
            printf("\nPlease provide the ## of the TPL.\n");
            gets(filenum);
            argc++;
            argv[2] = filenum;
            argd = true;
    }    
    if(argc >= 3){
            printf("All necessary parameters are in place.\n***\n");
            argd = true;
    }
    for(x=0;x<80;x++){
        tplname[x] =0;
        tcsname[x]=0;
    }
    
    strcpy(tplname, argv[2]);
    strcpy(tcsname, tplname);
    strcat(tplname, ".tpl");
    strcat(tcsname, ".tcs");    

  
//find which offset to go to.
    if((off = fopen("offsets.txt", "rb")) == NULL){
           printf("Error: Cannot open offsets.txt for read.\n");
           return 1;
    }
    donde = 0;
    w = 0;
    while(1){
           fseek(off, w, 0); //fseek to location W of offset txt file
           fgets(cmp, 3, off); //read the next two chars, plus one null byte
           //printf("cmp: %s\n", cmp); //debug info
           if((cmp[0] == argv[2][0]) && (cmp[1] == argv[2][1])){ 
                //printf("successss");
                w+=4;
                fseek(off, w, 0);   //fseek 4 bytes farther
                fgets(splat, 2, off); //fgets the next byte, plus one null byte
                if(splat[0] == '*'){  //check if the byte is an asterisk, denoting more complex formats
                     argd = false;
                }
                w+=1;
                fseek(off, w, 0); //fseek one byte farther
                fgets(offset, 9, off); //fgets offset data in char bytes, 8 chars plus one null byte
                //printf("Data Offset: %s\n", offset);
                changeToHex(offset, donde);
                break;
           }
           w+=15;    //this should instead search for the 0D 0A for the newline characters
           if(w > 1000*15){
                printf("Error: The number requested is not in the offsets.txt file.\n");
                return 1;
            }           
    }
    //printf("decimal offset: %i\n", donde);
    fclose(off); 

//make TPL
    if(texflag) spawnl(P_WAIT, "TexConv.exe", "TexConv.exe", tcsname, tplname, NULL);
    
//delete whatever's in tmp, create it if it doesn't exist
    if((tmp = fopen("tmp.dat" , "wb")) == NULL){
            printf("Error: Cannot reset temp file usage.\n");
            return 1;
        }
    if(verboseflag) printf("Created tmp.dat for temporary data storage.\n");
    fclose(tmp);
    
//if statements for opening the files
    if((dat = fopen(argv[1], "rb")) == NULL){
           printf("Error: Cannot open DAT file for read.\n");
           return 1;
    }
    if((tpl = fopen(tplname, "rb")) == NULL){
           printf("Error: Cannot open TPL file for read.\n");           
           return 1;
    }
    if((tmp = fopen("tmp.dat", "ab")) == NULL){
           printf("Error: Cannot open temp file for append.\n");
           return 1;
    }
    if(verboseflag) printf("Data Offset: %s\n", offset);
    
//Actual reading and writing to files goes here.
    //if _8 or _9 format
    if(!argd) {
    if(verboseflag) printf("Type: _8 or _9\n");
    /*
    future - - - check for magenta palette data, replace it 
    to check for magenta
    0. place this code after tplhead and paldata are given values
    1. read just the palette data from the paldata offset until you hit the tplhead offset
    2. for loop to get16bit() at every offset between readbuf[0] abd readbuf[(tplhead-paldata)-2]
    3. during that loop, check if the get16bit returns fc1f 
        if yes..
        a. create a tmpt.tpl file
        b. make sure that the offset of the magenta value is recorded
        c. copy up to that offset to tmpt.tpl
        d. append 00 00
        e. copy/append from two after the offset until eof
        f. copy tmpt.tpl to the original
    NEXT
        check next offset point? check if data is less than 32 lines...maybe for another time
    
    */
    
        counter = 0;                        //the counter keeps track of how long the TPL data is
    
        fseek(tpl, 0x0, 0);                 //start at beginning of file
        for(x=0; x<0x400; x++){                //copy first 1024 bits from TPL to readbuf
            readbuf[x] = getc(tpl);
        }    
        
        tplhead = get32bit(readbuf + 0xc);    //get tpl header location, which is 0x40 before the actual data
        paldata = get32bit(readbuf + 0x1c);    //get palette data location
        
        fseek(tpl, paldata, 0);
        for(x=0; x<tplhead-2; x++){
            readbuf[x] = getc(tpl);            
        }
        for(x=0; x<(tplhead-paldata)-2; x++){
            magenta = get16bit(readbuf + x);    
            if (magenta == 0xfc1f){
                y = x+0x20;
                if(verboseflag) printf("Magenta found at offset: %i\n", y);
                magenta = replaceMagenta(tmpt, tpl, tplname, y);
                if(magenta == 1) return 1;    
                break;
            }
        }
        
        
        fseek(dat, 0, 0);
        for(x=0; x<donde; x++){                //copy DAT info to TMP (append)
            ch = getc(dat);
            putc(ch, tmp);        
        }    
        
        fseek(tpl, tplhead + 0x40, 0);        //fseek to TPL image data
        while(!feof(tpl)){                    //copy TPL image data to TMP (append)
            ch = getc(tpl);
            if(!feof(tpl)) putc(ch, tmp);
            counter++;                        //keep track of length of data
        }
        
        fseek(tpl, paldata, 0);
        for(x=paldata; x<tplhead; x++){        //copy TPL palette data to TMP (append)
            ch = getc(tpl);                    //this loop iterates from paldata to tplhead
            if(!feof(tpl)) putc(ch, tmp);    
            counter++;                        //keeping track of length of both datas added together
        }
        
        donde = counter + donde - 1;        //update the end-of-data location in DAT 
        fseek(dat, donde, 0);
        while(!feof(dat)){                    //copy rest of DAT to TMP (append)
            ch = getc(dat);
            if(!feof(dat)) putc(ch, tmp);                            
        }         
    //if _14 CMPR format
    }else if(argd){
    if(verboseflag) printf("Type: _14 CMPR\n");
    /* no comment */
        counter = 0;  
        fseek(dat, 0, 0);
        for(x=0; x<donde; x++){
            ch = getc(dat);
            putc(ch, tmp);        
        }    
        fseek(tpl, 0x40, 0);         //offset start for tpl data
        while(!feof(tpl)){
            ch = getc(tpl);
            if(!feof(tpl)) putc(ch, tmp);
            counter ++;
        }    
        donde = counter + donde - 1;
        fseek(dat, donde, 0);
        while(!feof(dat)){
            ch = getc(dat);
            if(!feof(dat)) putc(ch, tmp);                            
        } 
    }    
     
    fclose(dat);
    fclose(tpl);
    fclose(tmp); 
    
    
//Copy TMP contents to DAT and delete TMP
    if((dat = fopen(argv[1], "wb")) == NULL){
        printf("Error: Cannot open DAT file for rewrite.\n");
        return 1;
    }
    if((tmp = fopen("tmp.dat", "rb")) == NULL){
        printf("Error: Cannot open temp file for reread.\n");
        return 1;
    }
    
    fseek(tmp, 0, 0);
    while(!feof(tmp)){
        ch = getc(tmp);
        if(!feof(tmp)) putc(ch, dat);
    }
    fclose(dat);
    fclose(tmp);
    if(remove("tmp.dat")==-1) {
        printf("Error: Cannot delete tmp.dat");
        return 1;
    }
    if(verboseflag) printf("Copied tmp.dat to %s and deleted tmp.dat successfully.\n", argv[1]);
     //scanf(str);
//  system("PAUSE"); wtf. this made the program like 465 kb. I hate iostream.
    return 0;
}



void changeToHex(char *offset, long& location)
{
//This function multiplies the nth digit from the right by 16^(n-1)
//and then adds all these values together until n <= 0,
//effectively converting hex to decimal, but really just
//converting from char[] to long
    int p, q, r;
    long base;
    location = 0;
    for(p=7; p>0; p--){
           base = 16;
           for(q=(p-1); q>0; q--){
                  base *= 16;
                 // printf("base: %i\n", base); debug info
           }
           switch(*offset){
                  case '0':r=0; break;
                  case '1':r=1; break;
                  case '2':r=2; break;
                  case '3':r=3; break;
                  case '4':r=4; break;
                  case '5':r=5; break;
                  case '6':r=6; break;
                  case '7':r=7; break;
                  case '8':r=8; break;
                  case '9':r=9; break;
                  case 'a':
                  case 'A':r=10; break;
                  case 'b':
                  case 'B':r=11; break;
                  case 'c':
                  case 'C':r=12; break;
                  case 'd':
                  case 'D':r=13; break;
                  case 'e':
                  case 'E':r=14; break;
                  case 'f':
                  case 'F':r=15; break;
           }
           //printf("offset: %i\n", r);
           *offset ++;
           location = location + (base*r);
           //printf("location: %i\n\n", location);     
    }
     
}

int replaceMagenta(FILE *tmpt, FILE *tpl, char *tplname, long offset)
{
    int z;
    char ch;
    /*if yes..
        */    

    if((tmpt = fopen("tmpt.tpl", "ab")) == NULL){
        printf("Error: Cannot create tmpt.tpl for append.\n");
        return 1;
    }
    
    fseek(tpl, 0, 0);                //seek to 0 for offset with MAGENTA
    for(z=0; z<offset; z++){        //copy up to that point, add it to tmpt
        ch = getc(tpl);
        putc(ch, tmpt);        
    } 
    fseek(tpl, 0x4, 0);                //seek to offset 0x4, whose two bytes are always 00 00
    for(z=0;z<2;z++){                //copy them to where the MAGENTA used to be
        ch = getc(tpl);
        putc(ch, tmpt);    
    }
    fseek(tpl, offset+2, 0);        //seek 2 past the original offset, aka, right after the MAGENTA change
    while(!feof(tpl)){                //copy/append from there to eof
           ch = getc(tpl);
           if(!feof(tpl)) putc(ch, tmpt);                            
       } 
    
    fclose(tmpt);
    fclose(tpl);                    //close the tpl that was open for read
    if((tpl = fopen(tplname, "wb")) == NULL){//open it again for write, which clears it
        printf("Error: Cannot open %s to replace MAGENTA value.\n", tplname);    
        return 1;
    }
    if((tmpt = fopen("tmpt.tpl", "rb")) == NULL){
        printf("Error: Cannot open tmpt.tpl for reread and copy.\n");
        return 1;    
    }
    fseek(tmpt, 0, 0);                //copying tmpt.tpl over original TPL
    while(!feof(tmpt)){
        ch = getc(tmpt);
        if(!feof(tmpt)) putc(ch, tpl);
    }
    fclose(tpl);
    fclose(tmpt);
    if(remove("tmpt.tpl")==-1) {
        printf("Error: Cannot delete tmpt.tpl");
        return 1;
    }
    
    //since TPL was open before the funtion call, reopen it the way it was before
    if((tpl = fopen(tplname, "rb")) == NULL){
        printf("Error: Cannot open %s for read.\n", tplname);
        return 1;        
    }
    
    
}

int get16bit(unsigned char* p) 
{
    //this is from hcs (Halley's Comet Software)
    //I got this idea from their in_cube winamp plugin
    //it transforms char[] values into their hex data equivalent
    //for 16 bits, or two bytes, of hex data
    return (p[0] << 8) | p[1];
}

int get32bit(unsigned char* p)
{
    //this is from hcs (Halley's Comet Software)
    //I got this idea from their in_cube winamp plugin
    //it transforms char[] values into their hex data equivalent
    //for 32 bits, or four bytes, of hex data
    return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
}

int parse_args(char* filename, char* filenum)
{
    /*
    This will switch() the args with the filename and ##, and 
    use stored values to return the offset
    
    
    */
    
    
    
}
Oh and by the way, I went to GSG2 in Concord this weekend and met some awesome people. I only stayed for one day, but it was fun. There was a station set up with hacked Melee, and all the cool people played on it :D
sick .
 
Top Bottom