Pure Pure Translation: (Photo Thread) (Last Update: Jan 29)

Post about your projects or talk about mirror moon projects that haven't been announced yet... or something.

Moderator: Staffers

Unread postby furyoftheskies » November 13th, 2008, 8:47 pm

phib wrote:Thanks for the offer, but I prefer 'teaching to fish' which is more entertaining than 'fishing for others'. Also I already have my hands full with other projects.
But I don't mind helping from time to time if you encounter any technical difficulties.


Okay then phib ^_^ If I run into something that baffles me and I can't figure it out, I'll ask you for your assistance then.

Thanks for teaching me how to fish lol, now I'm trying to learn how to automate the fishing. (Creating a tool doesn't seem too hard, I just need to know which programming language to use [I think its python that people use to make tools] so hopefully if I learn that, things can speed up a bit)

If worse comes to worse, I can try writing a tool in C++ or C#, I just have to figure out how to write in binary though lol. I need a guide that teaches how to read bytes in a file or something.

Edit 1: Would you happen to know of a program that can create an .exe installer? So that I don't have to release a manual one?
User avatar
furyoftheskies
Might just like this board
 
Posts: 37
Joined: November 2nd, 2008, 1:21 pm

Unread postby Balcerzak » November 14th, 2008, 11:04 am

furyoftheskies wrote:If worse comes to worse, I can try writing a tool in C++ or C#, I just have to figure out how to write in binary though lol. I need a guide that teaches how to read bytes in a file or something.

I've never played around with actual binary in C++, but maybe the following is helpful?
Dealing with bits: http://www.cplusplus.com/reference/stl/bitset/
Dealing with files: http://www.cplusplus.com/reference/iostream/fstream/
User avatar
Balcerzak
Crack Addic!
 
Posts: 174
Joined: October 29th, 2007, 8:21 pm
Location: Michigan, USA

Unread postby furyoftheskies » November 14th, 2008, 4:13 pm

Balcerzak wrote:I've never played around with actual binary in C++, but maybe the following is helpful?
Dealing with bits: http://www.cplusplus.com/reference/stl/bitset/
Dealing with files: http://www.cplusplus.com/reference/iostream/fstream/


Thanks, but I already have a bit of knowledge on that.

I know that if I open the file in binary, hexadecimal numbers are in binary sets of 4. (Ex. 1011 is the hex 0xA, 1111 would be 0xF, etc etc)

I need to read specifically the first 2 bytes, so its 16 binary bits, They have to be read in sets of 4 and translated to hex, and they also have to be read as little endian (backwards)

Ex. Let's say 1011 1101 0011 1000 are the first 2 bytes. This comes out as 0xAD38. Now, I need to read this backwards (Little endian) in bytes to get the actual value I'm looking for, so it becomes 0x38AD. So I guess the logic of the program would go something like this:

Open file in binary mode.
Get the first 2 bytes (16 bits)
Group bits into 4, then get the equivalent hex number.
Switch the first 2 hex numbers with the last 2 hex numbers.
Output the number obtained to the screen.
Determine the header by converting the number to decimal, then subtract it from the actual size of the file, then reconvert back to hex.
Output the size of the header to the screen.

That's pretty much all the logic I want to implement. I don't know if there is a function that can determine the size of a file or not, I have to explore that a bit more.

On a side note: I've translated and implemented 2/7 Scripts for the Intro. Lol, slow, I know, but I'm trying my best.
User avatar
furyoftheskies
Might just like this board
 
Posts: 37
Joined: November 2nd, 2008, 1:21 pm

Unread postby Balcerzak » November 14th, 2008, 7:29 pm

Code: Select all
#include <fstream>

void main(){
  fstream file("charaprof.scn",ios::binary | ios::in | ios::out);
  char bytes[2];
  file.get(bytes[0]);
  file.get(bytes[1]);
  short* foo = &bytes;
  char revbytes[2];
  revbytes[0] = bytes[1];
  revbytes[1] = bytes[0];
  short* bar = &revbytes;

  std::cout << "Hex values of the first two bytes: " << hex << (short) bytes[0] << " " << hex << (short) bytes[1] <<std::endl;
  std::cout << "Hex values of the first two bytes (reversed): " << hex << (short) revbytes[0] << " " << hex << (short) revbytes[1] <<std::endl;
  std::cout << *foo << std::endl;
  std::cout << "Hex values of the first two bytes: " << hex << *bar << std::endl;
  std::cout << "Hex values of the first two bytes (reversed): " << hex << *foo << std::endl;
  std::cout << *foo << std::endl;
  std::cout << "Dec value of the first two bytes: " << dec << *bar <<std::endl;
  std::cout << "Dec value of the first two bytes (reversed): " << dec << *foo <<std::endl;
  std::cout << *foo << std::endl;


  file.seekg(0,ios::beg);
  int filebegin = file.tellg();
  file.seekg(0,ios::end);
  int fileend = file.tellg();
  int filesize = fileend - filebegin;
  short* headersize = new short;
  *headersize = filesize - *foo;
  std::cout << "File size is " << filesize << " bytes" << std::endl;
  std::cout << "Header size is " << *headersize << " bytes" << std::endl;
  std::cout << "Header size is (hex) " << hex << *headersize << " bytes" << std::endl;

  unsigned char* finalbytes = headersize;
  std::cout << "Hex values of the manipulated two bytes: " << hex << (short) finalbytes[0] << " " << hex << (short) finalbytes[1] <<std::endl;
}

gave the following output:
stdout wrote:Hex values of the first two bytes: fff0 b
Hex values of the first two bytes (reversed): b fff0
bf0
Hex values of the first two bytes: f00b
Hex values of the first two bytes (reversed): bf0
bf0
Dec value of the first two bytes: -4085
Dec value of the first two bytes reversed: 3056
3056
File size is 3284 bytes
Header size is 228 bytes
Header size is (hex) e4 bytes
Hex values of the manipulated two bytes: e4 0


Is this doing anything like what you were hoping it to? [Note charaprof.scn was obtained from http://www.megaupload.com/?d=B6BTMJ42 that you posted in this thread, as I needed something actually worth testing this on.]

The bar variable is included in case the endianness of the system your running on is not little endian, as otherwise it will misinterpret things when it creates a short value out of the character array.

This is just the result of a couple hours idle fiddling and looking at the references I linked you earlier [turned out that you didn't need individual bits at all, dealing in whole bytes (or equivalently chars) seems to be good enough].

You could probably even go ahead and actually replace the bytes here too, adding
Code: Select all
file.seekg(0,ios::beg);
file.put(finalbytes[0]);
file.put(finalbytes[1]);

to the very end of the code, if that's what you ultimately hope to do.

Sorry, I haven't been paying full attention to the conversation thus far, only got my curiousity aroused when you mentioned C++.

Edit: There may or may not be problems with signed vs unsigned characters. From what little I can guess from the results here, I don't think it will be a problem, but I'm making no guarantees about this piece of code. It's strictly use at your own risk.

Also, I forgot to delete headersize, which means as it stands there's a (currently inconsequential) memory leak in the function.
User avatar
Balcerzak
Crack Addic!
 
Posts: 174
Joined: October 29th, 2007, 8:21 pm
Location: Michigan, USA

Unread postby furyoftheskies » November 15th, 2008, 3:07 am

Holy cow Balcerzak, you've done pretty much the basic thing that I want to do lol. I meet another genius now lol.

What C++ program are you using? Dev-C? Visual C++?

Your program does what I want to do with the file. It specifically does almost all of what I want to do.

From your code, I want to change this:

Code: Select all
void main()
{
   fstream file("charaprof.scn",ios::binary | ios::in | ios::out);
   char bytes[2];
   file.get(bytes[0]);
   file.get(bytes[1]);
   short* foo = &bytes;
   char revbytes[2];
   revbytes[0] = bytes[1];
   revbytes[1] = bytes[0];
   short* bar = &revbytes;
}


and add this on to it:

Code: Select all
void main()
{
   fstream oldFile("X:\script\filename.scn", ios::binary | ios::in | ios::out);
   char oldBytes[2];
   oldFile.get(oldBytes[0]);
   oldFile.get(oldBytes[1]);
   short* foo = &oldBytes;
   char oldRevbytes[2];
   oldRevbytes[0] = oldBytes[1];
   oldRevbytes[1] = oldBytes[0];
   short* bar = &oldRevbytes;

   fstream newFile("X:\newScript\filename.scn", ios::binary | ios::in | ios::out);
   char newBytes[2];
   newFile.get(newBytes[0]);
   newFile.get(newBytes[1]);
   short* foo = &newBytes;
   char newRevbytes[2];
   newRevbytes[0] = newBytes[1];
   newRevbytes[1] = newBytes[0];
   short* bar = &newRevbytes; 
}


As you can see, filename.scn is the same file in terms of name, but the location (and most likely size) will be different. The original one is located in x:\script\, while the modified one will be located in x:\newScript\

After that, I determine the size and header of the original. From there, I compare those values obtained to the new script. If the new script's header size:

1) Does not correct match the file of the original (As in, if the file size minus the little endian bytes DOES NOT equal the header) then the program will fix it and output it for verification by using the data of the original. (In other words, it will show me what it will do, with a Y/N question confirming if I want to do it.)

I'll go and write the code and see if I can get it done. Believe it or not, I'm actually going to try and convert this to C# (C Sharp) since I've been using it a bit often. But I can always write it in C++ thanks to you Balcerzak.

Quick question: Is this how to skip to a certain byte? For example, I know that the offset of a file is located 76 bytes after the beginning, and every successive 76 bytes there is an offset read little endian. Would the code go something like this?

Code: Select all
   file.get(bytes[0+76x]);
   file.get(bytes[1+76x]);


x is a variable integer. The program should run until it hits an offset that is too large. Ex if the filesize is 4500 bytes, if the program hits an offset that is lets say 6000, it will stop and then output x, which would tell me the number of offsets in the file.
User avatar
furyoftheskies
Might just like this board
 
Posts: 37
Joined: November 2nd, 2008, 1:21 pm

Unread postby Balcerzak » November 15th, 2008, 3:27 pm

furyoftheskies wrote:Holy cow Balcerzak, you've done pretty much the basic thing that I want to do lol. I meet another genius now lol.

What C++ program are you using? Dev-C? Visual C++?

Far from a genius, to be perfectly honest I'm really an amateur with little to no formal computer programming education (I took a one-month course on Intro to C++). I do use a lot of programming at work, so I do have a fair bit of practical experience, but I'm really more of a physicist that codes, rather than an actual computer programmer, and thus I may not always fully understand what's going on behind the scenes (though I do try to learn).

That said, as far as what I work with, I use the version of CINT that comes bundled with ROOT, as that's what I do most of my programming in for work, though it does have a standalone version. See wikipedia's entry on it or the project's homepage for more information. So that means most of what I do is interpreted C++, and I'm a little shakier when it comes to designing makefiles and compiling executables, so probably can't be of a whole lot of help there. There's also some nuance differences when feeding macros to ROOT to be interpreted, that I cleaned out already for you, to leave it in more generic C++. (For instance, ROOT tends to want the name of the main function to be executed to match the filename of the macro file you feed it for execution, and it uses that to build some sort of internal "main", as far as I'm aware.)

I'm going to rearrange your post and reply to it in a different order, so I hope that doesn't cause any confusion. Just FYI.

fury wrote:I'll go and write the code and see if I can get it done. Believe it or not, I'm actually going to try and convert this to C# (C Sharp) since I've been using it a bit often. But I can always write it in C++ thanks to you Balcerzak.

I encourage you to do this, actually. While I don't honestly know any C# myself, nor even much about it, so wouldn't be able to offer any language specific advice, it's really best to work in the framework you're most familiar with. This also means you don't have to worry about downloading new unfamiliar software or packages in order to make or run the tools you need or want.

On the other hand, some problems lend themselves to easier solutions in different environments, so sometimes it's not always feasible to do this, but when it is, and you're able to work with something you're familiar with, you tend to understand it better, and can then in the future apply it to solving similar puzzles. I honestly don't think there will be any issues here, though, as from what little I do know about C# leads me to believe that's is very closely related to C and C++, which means a simple transition should be possible, and easily workable.

Also, like phib (or at least how I understood what he said) I don't have any immediate or long term interest in the project, at this point, but I don't like seeing people struggle if I think I can help out. Ultimately though, I hope I can help you learn to help yourself. I am fully aware from my own personal experiences, however, of how much more convenient it is to be shown a complete working example of code. Also, I got a little intrigued by your particular problem and have a hard time resisting a well-defined challenge, just as a test of my own skills and understanding. :wink:

Now, onto the actual code part of the discussion. I suppose it would be helpful if I explained exactly what did what, so that you can do conversions more easily. First though, I'm going to answer your quick question from the end.

fury wrote:Quick question: Is this how to skip to a certain byte? For example, I know that the offset of a file is located 76 bytes after the beginning, and every successive 76 bytes there is an offset read little endian. Would the code go something like this?

Code: Select all
   file.get(bytes[0+76x]);
   file.get(bytes[1+76x]);


x is a variable integer. The program should run until it hits an offset that is too large. Ex if the filesize is 4500 bytes, if the program hits an offset that is lets say 6000, it will stop and then output x, which would tell me the number of offsets in the file.


This will not work, for a couple of different reasons. First of all, you haven't properly defined x, and you're going to need some sort of external control structure to do what you're ultimately intending here (if it was me, I'd probably choose a for loop, I like for loops). Secondly, when we declared the bytes variable, we declared it as a static array with only enough room for two entries, meaning we can only properly use bytes[0] and bytes[1], anything else is asking for trouble (most likely unexpected runtime behaviour, segmentation faults, etc.).

Detailed TL;DR explanation: What you're actually asking the code to do here is to retrieve the amount of data from file that fills the same amount of space as a member of the bytes array, and to store that information at the memory address found by following the pointer to the beginning of the bytes array, and then continuing along until you're reached the specified offset (in the case of x == 1, that is putting things into bytes[76]). This is highly dangerous, as the bytes[76] may point to memory the program doesn't have access to, it may be a different variable that's important to the program running that now gets over-written, but doesn't end up crashing it, leading to unexpected behaviour, or any of a number of other things could go wrong.

I'd deal more with a couple of ways to try to do what you want to do here later, but I think I should now go ahead and actually explain step-by-step, how the various pieces go together. If I over-explain things you already know or understand, forgive me for being thorough, I don't mean it as disrespect. (Spoilered to save on visible space.)
Code: Select all
  fstream file("charaprof.scn",ios::binary | ios::in | ios::out);

This creates the basic interface for manipulating files, creating a variable named "file" with the access modes of "binary", "in", and "out" all enabled.
Code: Select all
  char bytes[2];

This creates an array of two char objects. It needs to be an array, because the memory they inhabit needs to be contiguous in order for some of the tricks I use later on in the code. It does not necessarily need to be limited to two objects, as far as I'm aware. This means that you do have the distinct alternative of creating an array large enough to hold the entire file and reading it all in at once if you so choose. I'll discuss this option in more detail later on if you'd like.
Code: Select all
  file.get(bytes[0]);

This tells the program to read in from the file enough data to fill an object the size of a char (in this case this means a byte), and to place it into the location of the first entry of the character array we created earlier. Worth noting is that this operation proceeds from the current value of the offset for the file being accessed, and finishes with this offset being advanced by an amount equal to the information read. The default behaviour is that the offset for newly opened files is at the beginning, but if say option "ios::ate" was specified, or other manipulation had been done prior, this might not be the case.

I did do some rudimentary experimentation with trying to do file.get() on shorts, unsigned characters, and other objects, as I thought that that might be a more efficient way to do what we want done (in the case of shorts), or a less ambiguous way (in the case of unsigned characters) but it only seemed to work with the default char. :shrug: C'est la vie, right? So I make due with what works.
Code: Select all
  file.get(bytes[1]);

Same thing as above.
Code: Select all
  short* foo = &bytes;

This creates a pointer to a short integer (an integer using two bytes), and assigns it to point at the address of the beginning of the bytes array. This means that "foo" and "char bytes[2]" are looking at exactly the same thing, just interpreting it differently. This is also why it needed to be an array, as if we'd simply created two char values using "char firstbyte, secondbyte;" there would be no guaranteed that when we pointed foo to firstbyte that secondbyte would be in the right place. At any rate, foo interprets the object at that address as a short integer (and apparently on my machine does so by treating the bytes as little endians), while bytes treats it as an (ordered) array of two characters. (NB: The & is the reference operator, telling the program to look at the reference, or address, of the thing it operates on, which in this case is bytes.)
Code: Select all
  char revbytes[2];
  revbytes[0] = bytes[1];
  revbytes[1] = bytes[0];
  short* bar = &revbytes;

This is exactly the same implementation as before, only storing the bytes in a different (in this case, reverse) order. Nothing really new or exciting.
Code: Select all
  std::cout << "Hex values of the first two bytes: " << hex << (short) bytes[0] << " " << hex << (short) bytes[1] <<std::endl;

A printout statement. The only thing worth noting here, is the following: " << hex << (short) bytes[0] <<". Let me explain what I'm doing here. This was the quickest, easiest way I could come up with, to do hex conversion. The hex arguement, tells standard out to treat integers in their hex representation. Well, unfortunately, a char is not an integer, so when I tried just using "<< hex << bytes[0]<<" it gave me the same thing as if I were doing "<
Code: Select all
  std::cout << "Hex values of the first two bytes (reversed): " << hex << (short) revbytes[0] << " " << hex << (short) revbytes[1] <<std::endl;
  std::cout << *foo << std::endl;
  std::cout << "Hex values of the first two bytes: " << hex << *bar << std::endl;
  std::cout << "Hex values of the first two bytes (reversed): " << hex << *foo << std::endl;
  std::cout << *foo << std::endl;
  std::cout << "Dec value of the first two bytes: " << dec << *bar <<std::endl;
  std::cout << "Dec value of the first two bytes (reversed): " << dec << *foo <<std::endl;
  std::cout << *foo << std::endl;

More printouts. Mostly boring. The only thing worth mentioning is something you probably already know, but that's the use of the *, the dereference operator. What *foo means is to look at the value that is stored in the location pointed to by foo. If I'd just said "<< foo <<" it would print out the memory address of foo, which would be different every run, and mean absolutely nothing to us (being something like "0xaeff08bb" or similar).
Code: Select all
  file.seekg(0,ios::beg);

This is the command that tells the file's internal pointer I mentioned earlier to go to the beginning. Specifically it says, go to offset of 0, as specified considering the beginning of the file as the direction of reference.
Code: Select all
  int filebegin = file.tellg();

This creates an int and stores the current value of the file's internal offset pointer (which by all rights should be '0', but this is a just in case measure to be sure).
Code: Select all
  file.seekg(0,ios::end);

Go to the offset of 0, when considering the end of the file to be the reference direction.
Code: Select all
  int fileend = file.tellg();
  int filesize = fileend - filebegin;

Store the offset value for the end of the file, and calculate the file size as the offset of the end minus the offset of the beginning.
Code: Select all
  short* headersize = new short;
  *headersize = filesize - *foo;

Here I'm declaring a new object, and making space for in memory. Then I assign the value of that object to be equal to the filesize minus the size of the value of what's pointed at by foo. The only reason I did this with the new command, is because I wanted it's address, so I could feed it to finalbytes later. I actually probably could have done this cleaner, by doing the following
Code: Select all
unsigned char finalbytes[2];
short* headersize = &finalbytes;
  *headersize = filesize - *foo;
in analogy with how we did the first things, but I guess I didn't think of it. Maybe even
Code: Select all
short headersize = filesize - *foo;
unsigned char finalbytes = &headersize;

Needless to say, there are usually a number of different ways to go about doing the same thing when programming. Quite often you don't hit upon the best one the first time around, and like I said, the first code creates a potentially problematic memory leak. ^^; What I do with it is also slightly dangerous, but I'll explain why later, and why it's actually okay as written.

Code: Select all
  std::cout << "File size is " << filesize << " bytes" << std::endl;
  std::cout << "Header size is " << *headersize << " bytes" << std::endl;
  std::cout << "Header size is (hex) " << hex << *headersize << " bytes" << std::endl;

More boring printouts.

Code: Select all
  unsigned char* finalbytes = headersize;
  std::cout << "Hex values of the manipulated two bytes: " << hex << (short) finalbytes[0] << " " << hex << (short) finalbytes[1] <<std::endl;

Here I make an unsigned character pointer (I chose unsigned, because we're accessing it in binary mode, so it just seemed weird to me to think about negative hex values and such, but maybe that's just prejudice and me not completely understanding things. I don't claim to be an expert by any means. It may have been just fine to use the default signed characters, as it didn't seem to cause any problems earlier on. :shrug:), and have it point to the same place that headersize is pointing at. NB This is not an array, explicitly, so you need to make sure that when you're using the offset operators [] to look at a value, that you've actually got something there. Everything I've written thus far means that I have a short integer (worth two bytes) at that location, so I'm able to get away with looking at finalbytes[0] and finalbytes[1], but if I tried to look at finalbytes[2] or something else, it could be disaster.



So that's the detailed summary of everything I had written for you earlier, so hopefully knowing the concepts behind the code will make your C# transition easier. For further reference, a look at http://www.cplusplus.com/doc/tutorial/files.html couldn't hurt, as it seems to lay out the basics very well, though if you need more information on any of the specific methods for fstream the link I provided earlier is probably a better bet.

furyoftheskies wrote:Your program does what I want to do with the file. It specifically does almost all of what I want to do.

From your code, I want to change to this:

Code: Select all
void main()
{
   fstream oldFile("X:\script\filename.scn", ios::binary | ios::in | ios::out);
   char oldBytes[2];
   oldFile.get(oldBytes[0]);
   oldFile.get(oldBytes[1]);
   short* foo = &oldBytes;
   char oldRevbytes[2];
   oldRevbytes[0] = oldBytes[1];
   oldRevbytes[1] = oldBytes[0];
   short* bar = &oldRevbytes;

   fstream newFile("X:\newScript\filename.scn", ios::binary | ios::in | ios::out);
   char newBytes[2];
   newFile.get(newBytes[0]);
   newFile.get(newBytes[1]);
   short* foo = &newBytes;
   char newRevbytes[2];
   newRevbytes[0] = newBytes[1];
   newRevbytes[1] = newBytes[0];
   short* bar = &newRevbytes; 
}


You're going to need to make sure to use different variables for the shorts for oldFile and newFile. oldfoo/newfoo might work, or you could actually give them a real descriptive name. I was just being lazy originally.

fury wrote:As you can see, filename.scn is the same file in terms of name, but the location (and most likely size) will be different. The original one is located in x:\script\, while the modified one will be located in x:\newScript\

After that, I determine the size and header of the original. From there, I compare those values obtained to the new script. If the new script's header size:

1) Does not correct match the file of the original (As in, if the file size minus the little endian bytes DOES NOT equal the header) then the program will fix it and output it for verification by using the data of the original. (In other words, it will show me what it will do, with a Y/N question confirming if I want to do it.)

Mmm, intriguing. I think I could figure out most of that, with the possible exception of the user prompt. I've not done a lot of work with user input. I may have to do a little more tinkering around just for fun here.
User avatar
Balcerzak
Crack Addic!
 
Posts: 174
Joined: October 29th, 2007, 8:21 pm
Location: Michigan, USA

Unread postby furyoftheskies » November 16th, 2008, 1:46 am

Ugh

First of all, I'm having a problem dealing with your short byte declaration:

Code: Select all
short* foo = &bytes;


My compiler says it can't convert short* int to a char*[2] lol.

Edit 1: I've managed to write the code on C#. I'll paste it later.

Edit 2: Heres the code on C#. This one actually replaces the file size given that the user inputs a decimal! This will be the first part of the program. The second part will compare the two and make the neccesary changes ^_^.

Code: Select all

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
//Standard C# declarations

namespace Checker
{
    class Program
    {
        static void Main(string[] args)
        {
            FileStream opener = new FileStream("e:\\charaprof.scn", FileMode.Open, FileAccess.ReadWrite);
            //Open original file
            byte[] bytes = new byte[2];
            bytes[0] = (byte)opener.ReadByte();
            bytes[1] = (byte)opener.ReadByte();
            //Get the first 2 bytes
            string oldByte1 = string.Format("{0:X}", bytes[0]);
            string oldByte2 = string.Format("{0:X}", bytes[1]);
            //Convert them to their hexadecimal equivalents
            if (oldByte1.Length % 2 != 0)
            {
                oldByte1 = "0" + oldByte1;
            }
            if (oldByte2.Length % 2 != 0)
            {
                oldByte2 = "0" + oldByte2;
            }
            //If they are not 2 digit hexadecimal numbers (Number started with 0) then fix it so it is.
            Console.WriteLine("First bytes non reversed are: " +
                oldByte1 + oldByte2);
            //How its supposed to be written in the file
            Console.WriteLine("First bytes reversed are: " + oldByte2 + oldByte1);
            //How its supposed to read by the user
            int decimalValue = Convert.ToInt32(oldByte2 + oldByte1, 16);
            //This is the decimal value of the bytes when they are converted from hex to decimal
            Console.WriteLine("This value is " + decimalValue);
            Console.WriteLine("The header size is " + (opener.Length - decimalValue));
            //opener.Length is a special feature that gets the size of the file, so I subtract it from decimal
            //value and bam, you get the header size no problem.
            Console.Write("Enter the value to change (Decimal): ");
            //User enters a decimal value, this part will be changed, but this is just proof of concept right now.
            int newValue = Convert.ToInt32(Console.ReadLine());
            string newHex = string.Format("{0:X}", newValue);
            //Convert it to hexadecimal format
            if (newHex.Length % 2 != 0)
            {
                newHex = "0" + newHex;
            }
            //If its not a 4 digit hex, then fix it (number starts with 0)
            Console.Write("The code will change from " + oldByte2 + oldByte1 +
                " to " + newHex + ". Will try to replace now...");
            //Will be changed to a prompt
            bytes[0] = Convert.ToByte(newHex.Substring(2, 2), 16);
            bytes[1] = Convert.ToByte(newHex.Substring(0, 2), 16);
            //Get the substrings, 2 hexa digits long, and assign them back
            opener.Position = 0;
            //Set position back to beginning
            opener.Write(bytes, 0, 2);
            //Write the 2 bytes
            opener.Close();
            Console.WriteLine("\nReplace successful!");
            //Show confirmation.
            Console.Read();
        }
    }
}




Spoiled to save space. Comments are in there lol.
User avatar
furyoftheskies
Might just like this board
 
Posts: 37
Joined: November 2nd, 2008, 1:21 pm

Unread postby Balcerzak » November 16th, 2008, 5:55 pm

furyoftheskies wrote:Ugh

First of all, I'm having a problem dealing with your short byte declaration:

Code: Select all
short* foo = &bytes;


My compiler says it can't convert short* int to a char*[2] lol.

Ooh, yeah, good call on that. As I say, I mostly run interpretted C++ and CINT is fairly forgiving on dealing with strict syntax. When I tried to compile the macro, it gave me the same errors. I've since developed a much cleaner implementation which fixes this. I've also added a lot of functionality and some other neat things in the latest iteration of the code. Also, I've been having the damnedest time trying to get it to work on windows, while it runs fine on linux, which boggles my mind...

Anyway, the new code (with added in-line commentary)

Code: Select all
#include <fstream> //for file in-out
#include <iostream> //for basic in-out
#include <iomanip> //may not be necessary
#include <climits> //for user input protection (it defines INT_MAX)
#include <string> //strings are good
#include <sstream> //so are stringstreams

/*  A union is the official c++ way to implement my previous hack of mixing and matching
     differently typed pointers see http://www.cplusplus.com/doc/tutorial/other_data_types.html
     for more information.  I'm defining it at global scope so all functions can access it. */
union twobyte{
  char one[2]; 
  short two;     
};

/*  The following function converts a short integer into a string containing its hex
     representation.  It makes use of stringstream, which is incredibly convenient. */
std::string hex_itos(short i){
  std::stringstream s;
  s << hex << i;
  return s.str();
}

/*  The following function is for padding a string with leading zeros.  */
void padwithzero(std::string& s) {s="0"+s;}

/*  I found myself performing these conversions quite frequently, so I made a function
     to do it for me, and save on space.  The function has no return value, but since the
     three strings it takes as input are given as pass by reference any modification done
     at this scope persists to higher scope.  */
void twobyte_to_strings(twobyte mytwobyte, string& byteone, string& bytetwo, string& both){
  // the multiple typecasts are to get rid of unsightly effects that come as a result of
  // using signed character
  byteone = hex_itos((short)(unsigned char) mytwobyte.one[0]); 
  bytetwo = hex_itos((short)(unsigned char) mytwobyte.one[1]);
  both = hex_itos(mytwobyte.two);
  //makes sure the string containing the individual bytes are two long
  while(byteone.size() < 2) padwithzero(byteone); 
  while(bytetwo.size() < 2) padwithzero(bytetwo);
  //makes sure the string containing the short is four long
  while(both.size() < 4) padwithzero(both); 
}

/*  The following function does essentially the same thing as the function I previously showed,
     but has been re-written using the new tools to be cleaner, and actually compiles, as well as
     extending its usability.  It's inputs are a fstream file, pass by reference ints to hold the
     headersize and filesize, and an integer defining what offset in the file you want to examine
     the bytes at (default arguement of zero).  */
void findheader(fstream& file, short& headersize, int& filesize, int offset = 0){
  //The file may not currently point where you want it, explicitly send it to the desired offset
  file.seekg(offset,ios::beg);   
  twobyte mytwobyte;  //make a twobyte
  file.get(mytwobyte.one[0]); //use the character members access to fill the twobyte with value
  file.get(mytwobyte.one[1]);

  //create raw strings to hold the results of the pass-by-reference function
  std::string byteone, bytetwo, both;
  twobyte_to_strings(mytwobyte, byteone, bytetwo, both); //convert the twobyte into strings

  //some basic output, to tell the user what's going on.
  std::cout << "Inside findheader: " << std::endl;
  std::cout << "Starting at offset: " << hex << offset << std::endl;
  std::cout << "Hex values of the first two bytes: ";
  std::cout << byteone << bytetwo << std::endl;
  std::cout << "Hex values of the first two bytes (reversed): ";
  std::cout << both << std::endl;
  std::cout << "Dec values of the first two bytes (reversed): ";
  std::cout << dec << mytwobyte.two << std::endl;

  // find the filesize
  file.seekg(0,ios::beg);
  int filebegin = file.tellg();
  file.seekg(0,ios::end);
  int fileend = file.tellg();
  filesize = fileend - filebegin;
 
  // find the headersize
  headersize = filesize - mytwobyte.two;
  std::cout << "Exit findheader:" << std::endl;
}

/*  This function is the function that handles calculating what the new bytes should be, and
     doing the overwriting.  It takes file2 (the one to be written) as input, as well as the header
     and file sizes for both files (mostly for the sake of giving enough feedback to the user so
     they can make an informed decision), as well as the offset of the bytes being examined.  */
void fixbytes(fstream& file2, short header1, short filesize1, short header2, short filesize2, int offset){
  // make three twobytes, one for each of the files as-is, and one for the results of the manipulations
  twobyte mytwobyte, foo, bar;
  // this time we're filling the twobyte by using the short member access method
  mytwobyte.two = filesize2 - header1;
  foo.two = filesize1 - header1;
  bar.two = filesize2 - header2;

   //a bunch of strings to hold the conversions
  std::string byteone, bytetwo, both, dummy1, dummy2;
  twobyte_to_strings(foo, byteone, bytetwo, both);
  // a bunch of print-out statements
  std::cout << "Inside fixbytes:" << std::endl;
  std::cout << "Hex values of file1 two bytes: ";
  std::cout << byteone << bytetwo << std::endl;
  twobyte_to_strings(bar, byteone, bytetwo, both);
  std::cout << "Hex values of file2 two bytes: ";
  std::cout << byteone << bytetwo << std::endl;
  twobyte_to_strings(mytwobyte, dummy1, dummy2, both);
  std::cout << "Hex values of the manipulated two bytes: ";
  std::cout << dummy1 << dummy2 << std::endl;
  // Print-outs asking the user for input to make a decision
  std::cout << "\nReplace file2's "  << byteone << bytetwo;
  std::cout << " with " << dummy1 << dummy2 << "?" << std::endl;
  std::cout << "[y]/n" << std::endl;
  char input;  // a place to put the user input
  int failcount = 0; // a record of how many times the user has failed
  while(true){ // a nice infinite loop.  The user _will_ make a decision
    std::cin.get(input);  // read-in the input
    // I'm allowing either 'y', 'Y', or no input to be interpreted as assent
    if (input == 'y' || input == 'Y' || input == '\n'){
      std::cout << "Replacing at offset: " << hex << offset << std::endl;
      // make sure the file is pointing where we want to overwrite the bytes
      file2.seekg(offset, ios::beg);
      // write the new bytes into the file
      file2.put(mytwobyte.one[0]);
      file2.put(mytwobyte.one[1]);
      // return to the beginning to verify the write performed correctly
      file2.seekg(offset,ios::beg);
      // read in the new byte values, reusing foo (we're not going to need the old foo)
      file2.get(foo.one[0]);
      file2.get(foo.one[1]);
      // informative printouts
      std::cout << "Replacement done!" << std::endl;
      twobyte_to_strings(foo, byteone, bytetwo, both);
      std::cout << "New hex values of the first two bytes: ";
      std::cout << byteone << bytetwo << std::endl;
      // make sure to cleanup the input stream
      std::cin.ignore(INT_MAX,'\n');
      std::cout << "Exit fixbytes:" << std::endl;
      return;
    }
    else if (input == 'n'){
      // User didn't want to replace so we won't.  Cleanup the input stream and return
      std::cin.ignore(INT_MAX,'\n');
      std::cout << "Exit fixbytes:" << std::endl;
      return;
    }
    else if (failcount > 1){
      // user was being retarded, make sure that we'll get out of the loop
      // and move on with our lives
      std::cerr << "Three strikes, you're out!" << std::endl;
      std::cerr << "Assuming input of \'n\' and proceeding." << std::endl;
      std::cin.ignore(INT_MAX,'\n');
      std::cout << "Exit fixbytes:" << std::endl;
      return;
    }
    else{
      // Politely inform the user they've made a mistake and reprompt them for input
      std::cerr << "Error! Improper user input." << std::endl;
      std::cerr << "You typed: " << input << std::endl;
      std::cerr << "Please type \'y\' or \'n\'" << std::endl;
      // if they somehow managed to put the input stream into a failed state,
      // reset it and clean it up
      if (std::cin.fail()) std::cin.clear();
      std::cin.ignore(INT_MAX,'\n');
      // increment the failcounter
      failcount++;
    }
  }
}

/*  This is the main program, doing all our dirty work.  */
void main(){
  // define the two files we'll be looking at, opening them both in binary read/write mode
  fstream file1("charaprofOLD.scn", ios::binary | ios::in | ios::out);
  fstream file2("charaprof.scn", ios::binary | ios::in | ios::out);
  // make some variables to hold the pass-by-reference values the functions will be giving us
  short header1, header2;
  int filesize1, filesize2;
 
  // define an initial offset value
  int i = 0;
  //loop over known headers, until one of the files goes into a failed state,
  //or until a break statement is reached.
  while(!file1.fail() && !file2.fail()){
    std::cout << "\nUsing subfunction on file 1: " << std::endl;
    findheader(file1, header1, filesize1, i);
    std::cout << "Filesize of file 1: " << dec << filesize1 << std::endl;
    std::cout << "Headersize of file 1: \n(hex) " << hex << header1 << std::endl;
    std::cout << "(dec) " << dec << header1 << std::endl;
   
    std::cout << "\nUsing subfunction on file 2: " << std::endl;
    findheader(file2, header2, filesize2, i);
    std::cout << "Filesize of file 2: " << dec << filesize2 << std::endl;
    std::cout << "Headersize of file 2: \n(hex) " << hex << header2 << std::endl;
    std::cout << "(dec) " << dec << header1 << std::endl;
   
    // if the headers are unequal, go into the fixbytes function.
    if (header1 != header2){
      fixbytes(file2, header1, filesize1, header2, filesize2, i);
    }
    // Hardcoded in offset jumps to look at some of the relevent areas of interest in these files
    if (i == 0) i += 44;
    else if (i < 0xE4) i += 36;
    else break;
  }
  std::cout << "End main:" << std::endl;
}


I ran the code on two versions of charaprof.scn, the unmodified one, and the one that was two bytes different (obtained from megaupload). I did two passes, the first where I was prompted to make the replacements, replacing them in all cases (mostly using default enter, but once each for 'y' and 'Y') but the last, where I demonstrate the use of 'n', and bad input protection. The output is included here:
root [0] gSystem->CompileMacro("bitplay.C")
Info in : creating shared library /home/jpurdham/root/oldmacrocosmos/compile/bitplay_C.so
(int)1
root [1] bitplay()

Using subfunction on file 1:
Inside findheader:
Starting at offset: 0
Hex values of the first two bytes: 6f0b
Hex values of the first two bytes (reversed): 0b6f
Dec values of the first two bytes (reversed): 2927
Exit findheader:
Filesize of file 1: 3155
Headersize of file 1:
(hex) e4
(dec) 228

Using subfunction on file 2:
Inside findheader:
Starting at offset: 0
Hex values of the first two bytes: 710b
Hex values of the first two bytes (reversed): 0b71
Dec values of the first two bytes (reversed): 2929
Exit findheader:
Filesize of file 2: 3157
Headersize of file 2:
(hex) e4
(dec) 228

Using subfunction on file 1:
Inside findheader:
Starting at offset: 2c
Hex values of the first two bytes: 8008
Hex values of the first two bytes (reversed): 0880
Dec values of the first two bytes (reversed): 2176
Exit findheader:
Filesize of file 1: 3155
Headersize of file 1:
(hex) 3d3
(dec) 979

Using subfunction on file 2:
Inside findheader:
Starting at offset: 2c
Hex values of the first two bytes: 8008
Hex values of the first two bytes (reversed): 0880
Dec values of the first two bytes (reversed): 2176
Exit findheader:
Filesize of file 2: 3157
Headersize of file 2:
(hex) 3d5
(dec) 979
Inside fixbytes:
Hex values of file1 two bytes: 8008
Hex values of file2 two bytes: 8008
Hex values of the manipulated two bytes: 8208

Replace file2's 8008 with 8208?
[y]/n

Replacing at offset: 2c
Replacement done!
New hex values of the first two bytes: 8208

Exit fixbytes:

Using subfunction on file 1:
Inside findheader:
Starting at offset: 50
Hex values of the first two bytes: 930a
Hex values of the first two bytes (reversed): 0a93
Dec values of the first two bytes (reversed): 2707
Exit findheader:
Filesize of file 1: 3155
Headersize of file 1:
(hex) 1c0
(dec) 448

Using subfunction on file 2:
Inside findheader:
Starting at offset: 50
Hex values of the first two bytes: 930a
Hex values of the first two bytes (reversed): 0a93
Dec values of the first two bytes (reversed): 2707
Exit findheader:
Filesize of file 2: 3157
Headersize of file 2:
(hex) 1c2
(dec) 448
Inside fixbytes:
Hex values of file1 two bytes: 930a
Hex values of file2 two bytes: 930a
Hex values of the manipulated two bytes: 950a

Replace file2's 930a with 950a?
[y]/n

Replacing at offset: 50
Replacement done!
New hex values of the first two bytes: 950a

Exit fixbytes:

Using subfunction on file 1:
Inside findheader:
Starting at offset: 74
Hex values of the first two bytes: be0a
Hex values of the first two bytes (reversed): 0abe
Dec values of the first two bytes (reversed): 2750
Exit findheader:
Filesize of file 1: 3155
Headersize of file 1:
(hex) 195
(dec) 405

Using subfunction on file 2:
Inside findheader:
Starting at offset: 74
Hex values of the first two bytes: be0a
Hex values of the first two bytes (reversed): 0abe
Dec values of the first two bytes (reversed): 2750
Exit findheader:
Filesize of file 2: 3157
Headersize of file 2:
(hex) 197
(dec) 405
Inside fixbytes:
Hex values of file1 two bytes: be0a
Hex values of file2 two bytes: be0a
Hex values of the manipulated two bytes: c00a

Replace file2's be0a with c00a?
[y]/n

Replacing at offset: 74
Replacement done!
New hex values of the first two bytes: c00a

Exit fixbytes:

Using subfunction on file 1:
Inside findheader:
Starting at offset: 98
Hex values of the first two bytes: ed0a
Hex values of the first two bytes (reversed): 0aed
Dec values of the first two bytes (reversed): 2797
Exit findheader:
Filesize of file 1: 3155
Headersize of file 1:
(hex) 166
(dec) 358

Using subfunction on file 2:
Inside findheader:
Starting at offset: 98
Hex values of the first two bytes: ed0a
Hex values of the first two bytes (reversed): 0aed
Dec values of the first two bytes (reversed): 2797
Exit findheader:
Filesize of file 2: 3157
Headersize of file 2:
(hex) 168
(dec) 358
Inside fixbytes:
Hex values of file1 two bytes: ed0a
Hex values of file2 two bytes: ed0a
Hex values of the manipulated two bytes: ef0a

Replace file2's ed0a with ef0a?
[y]/n

Replacing at offset: 98
Replacement done!
New hex values of the first two bytes: ef0a

Exit fixbytes:

Using subfunction on file 1:
Inside findheader:
Starting at offset: bc
Hex values of the first two bytes: 190b
Hex values of the first two bytes (reversed): 0b19
Dec values of the first two bytes (reversed): 2841
Exit findheader:
Filesize of file 1: 3155
Headersize of file 1:
(hex) 13a
(dec) 314

Using subfunction on file 2:
Inside findheader:
Starting at offset: bc
Hex values of the first two bytes: 190b
Hex values of the first two bytes (reversed): 0b19
Dec values of the first two bytes (reversed): 2841
Exit findheader:
Filesize of file 2: 3157
Headersize of file 2:
(hex) 13c
(dec) 314
Inside fixbytes:
Hex values of file1 two bytes: 190b
Hex values of file2 two bytes: 190b
Hex values of the manipulated two bytes: 1b0b

Replace file2's 190b with 1b0b?
[y]/n
y
Replacing at offset: bc
Replacement done!
New hex values of the first two bytes: 1b0b
Exit fixbytes:

Using subfunction on file 1:
Inside findheader:
Starting at offset: e0
Hex values of the first two bytes: 450b
Hex values of the first two bytes (reversed): 0b45
Dec values of the first two bytes (reversed): 2885
Exit findheader:
Filesize of file 1: 3155
Headersize of file 1:
(hex) 10e
(dec) 270

Using subfunction on file 2:
Inside findheader:
Starting at offset: e0
Hex values of the first two bytes: 450b
Hex values of the first two bytes (reversed): 0b45
Dec values of the first two bytes (reversed): 2885
Exit findheader:
Filesize of file 2: 3157
Headersize of file 2:
(hex) 110
(dec) 270
Inside fixbytes:
Hex values of file1 two bytes: 450b
Hex values of file2 two bytes: 450b
Hex values of the manipulated two bytes: 470b

Replace file2's 450b with 470b?
[y]/n
Y
Replacing at offset: e0
Replacement done!
New hex values of the first two bytes: 470b
Exit fixbytes:

Using subfunction on file 1:
Inside findheader:
Starting at offset: 104
Hex values of the first two bytes: f020
Hex values of the first two bytes (reversed): 20f0
Dec values of the first two bytes (reversed): 8432
Exit findheader:
Filesize of file 1: 3155
Headersize of file 1:
(hex) eb63
(dec) -5277

Using subfunction on file 2:
Inside findheader:
Starting at offset: 104
Hex values of the first two bytes: f020
Hex values of the first two bytes (reversed): 20f0
Dec values of the first two bytes (reversed): 8432
Exit findheader:
Filesize of file 2: 3157
Headersize of file 2:
(hex) eb65
(dec) -5277
Inside fixbytes:
Hex values of file1 two bytes: f020
Hex values of file2 two bytes: f020
Hex values of the manipulated two bytes: f220

Replace file2's f020 with f220?
[y]/n
n
Exit fixbytes:
End main:

-----------

Replace file2's f020 with f220?
[y]/n
b
Error! Improper user input.
You typed: b
Please type 'y' or 'n'
t
Error! Improper user input.
You typed: t
Please type 'y' or 'n'
B
Three strikes, you're out!
Assuming input of 'n' and proceeding.
Exit fixbytes:
End main:

----------

Replacing at offset: 104
Replacement done!
New hex values of the first two bytes: f220

Exit fixbytes:
End main:


The second time, I ran it over, just to demonstrate that yes, the file was actually changed. This can be see here:

Processing bitplay.C...

Using subfunction on file 1:
Inside findheader:
Starting at offset: 0
Hex values of the first two bytes: 6f0b
Hex values of the first two bytes (reversed): 0b6f
Dec values of the first two bytes (reversed): 2927
Exit findheader:
Filesize of file 1: 3155
Headersize of file 1:
(hex) e4
(dec) 228

Using subfunction on file 2:
Inside findheader:
Starting at offset: 0
Hex values of the first two bytes: 710b
Hex values of the first two bytes (reversed): 0b71
Dec values of the first two bytes (reversed): 2929
Exit findheader:
Filesize of file 2: 3157
Headersize of file 2:
(hex) e4
(dec) 228

Using subfunction on file 1:
Inside findheader:
Starting at offset: 2c
Hex values of the first two bytes: 8008
Hex values of the first two bytes (reversed): 0880
Dec values of the first two bytes (reversed): 2176
Exit findheader:
Filesize of file 1: 3155
Headersize of file 1:
(hex) 3d3
(dec) 979

Using subfunction on file 2:
Inside findheader:
Starting at offset: 2c
Hex values of the first two bytes: 8208
Hex values of the first two bytes (reversed): 0882
Dec values of the first two bytes (reversed): 2178
Exit findheader:
Filesize of file 2: 3157
Headersize of file 2:
(hex) 3d3
(dec) 979

Using subfunction on file 1:
Inside findheader:
Starting at offset: 50
Hex values of the first two bytes: 930a
Hex values of the first two bytes (reversed): 0a93
Dec values of the first two bytes (reversed): 2707
Exit findheader:
Filesize of file 1: 3155
Headersize of file 1:
(hex) 1c0
(dec) 448

Using subfunction on file 2:
Inside findheader:
Starting at offset: 50
Hex values of the first two bytes: 950a
Hex values of the first two bytes (reversed): 0a95
Dec values of the first two bytes (reversed): 2709
Exit findheader:
Filesize of file 2: 3157
Headersize of file 2:
(hex) 1c0
(dec) 448

Using subfunction on file 1:
Inside findheader:
Starting at offset: 74
Hex values of the first two bytes: be0a
Hex values of the first two bytes (reversed): 0abe
Dec values of the first two bytes (reversed): 2750
Exit findheader:
Filesize of file 1: 3155
Headersize of file 1:
(hex) 195
(dec) 405

Using subfunction on file 2:
Inside findheader:
Starting at offset: 74
Hex values of the first two bytes: c00a
Hex values of the first two bytes (reversed): 0ac0
Dec values of the first two bytes (reversed): 2752
Exit findheader:
Filesize of file 2: 3157
Headersize of file 2:
(hex) 195
(dec) 405

Using subfunction on file 1:
Inside findheader:
Starting at offset: 98
Hex values of the first two bytes: ed0a
Hex values of the first two bytes (reversed): 0aed
Dec values of the first two bytes (reversed): 2797
Exit findheader:
Filesize of file 1: 3155
Headersize of file 1:
(hex) 166
(dec) 358

Using subfunction on file 2:
Inside findheader:
Starting at offset: 98
Hex values of the first two bytes: ef0a
Hex values of the first two bytes (reversed): 0aef
Dec values of the first two bytes (reversed): 2799
Exit findheader:
Filesize of file 2: 3157
Headersize of file 2:
(hex) 166
(dec) 358

Using subfunction on file 1:
Inside findheader:
Starting at offset: bc
Hex values of the first two bytes: 190b
Hex values of the first two bytes (reversed): 0b19
Dec values of the first two bytes (reversed): 2841
Exit findheader:
Filesize of file 1: 3155
Headersize of file 1:
(hex) 13a
(dec) 314

Using subfunction on file 2:
Inside findheader:
Starting at offset: bc
Hex values of the first two bytes: 1b0b
Hex values of the first two bytes (reversed): 0b1b
Dec values of the first two bytes (reversed): 2843
Exit findheader:
Filesize of file 2: 3157
Headersize of file 2:
(hex) 13a
(dec) 314

Using subfunction on file 1:
Inside findheader:
Starting at offset: e0
Hex values of the first two bytes: 450b
Hex values of the first two bytes (reversed): 0b45
Dec values of the first two bytes (reversed): 2885
Exit findheader:
Filesize of file 1: 3155
Headersize of file 1:
(hex) 10e
(dec) 270

Using subfunction on file 2:
Inside findheader:
Starting at offset: e0
Hex values of the first two bytes: 470b
Hex values of the first two bytes (reversed): 0b47
Dec values of the first two bytes (reversed): 2887
Exit findheader:
Filesize of file 2: 3157
Headersize of file 2:
(hex) 10e
(dec) 270

Using subfunction on file 1:
Inside findheader:
Starting at offset: 104
Hex values of the first two bytes: f020
Hex values of the first two bytes (reversed): 20f0
Dec values of the first two bytes (reversed): 8432
Exit findheader:
Filesize of file 1: 3155
Headersize of file 1:
(hex) eb63
(dec) -5277

Using subfunction on file 2:
Inside findheader:
Starting at offset: 104
Hex values of the first two bytes: f220
Hex values of the first two bytes (reversed): 20f2
Dec values of the first two bytes (reversed): 8434
Exit findheader:
Filesize of file 2: 3157
Headersize of file 2:
(hex) eb63
(dec) -5277
End main:


fury wrote:Edit 1: I've managed to write the code on C#. I'll paste it later.

Edit 2: Heres the code on C#. This one actually replaces the file size given that the user inputs a decimal! This will be the first part of the program. The second part will compare the two and make the neccesary changes ^_^.

Code: Select all

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
//Standard C# declarations

namespace Checker
{
    class Program
    {
        static void Main(string[] args)
        {
            FileStream opener = new FileStream("e:\\charaprof.scn", FileMode.Open, FileAccess.ReadWrite);
            //Open original file
            byte[] bytes = new byte[2];
            bytes[0] = (byte)opener.ReadByte();
            bytes[1] = (byte)opener.ReadByte();
            //Get the first 2 bytes
            string oldByte1 = string.Format("{0:X}", bytes[0]);
            string oldByte2 = string.Format("{0:X}", bytes[1]);
            //Convert them to their hexadecimal equivalents
            if (oldByte1.Length % 2 != 0)
            {
                oldByte1 = "0" + oldByte1;
            }
            if (oldByte2.Length % 2 != 0)
            {
                oldByte2 = "0" + oldByte2;
            }
            //If they are not 2 digit hexadecimal numbers (Number started with 0) then fix it so it is.
            Console.WriteLine("First bytes non reversed are: " +
                oldByte1 + oldByte2);
            //How its supposed to be written in the file
            Console.WriteLine("First bytes reversed are: " + oldByte2 + oldByte1);
            //How its supposed to read by the user
            int decimalValue = Convert.ToInt32(oldByte2 + oldByte1, 16);
            //This is the decimal value of the bytes when they are converted from hex to decimal
            Console.WriteLine("This value is " + decimalValue);
            Console.WriteLine("The header size is " + (opener.Length - decimalValue));
            //opener.Length is a special feature that gets the size of the file, so I subtract it from decimal
            //value and bam, you get the header size no problem.
            Console.Write("Enter the value to change (Decimal): ");
            //User enters a decimal value, this part will be changed, but this is just proof of concept right now.
            int newValue = Convert.ToInt32(Console.ReadLine());
            string newHex = string.Format("{0:X}", newValue);
            //Convert it to hexadecimal format
            if (newHex.Length % 2 != 0)
            {
                newHex = "0" + newHex;
            }
            //If its not a 4 digit hex, then fix it (number starts with 0)
            Console.Write("The code will change from " + oldByte2 + oldByte1 +
                " to " + newHex + ". Will try to replace now...");
            //Will be changed to a prompt
            bytes[0] = Convert.ToByte(newHex.Substring(2, 2), 16);
            bytes[1] = Convert.ToByte(newHex.Substring(0, 2), 16);
            //Get the substrings, 2 hexa digits long, and assign them back
            opener.Position = 0;
            //Set position back to beginning
            opener.Write(bytes, 0, 2);
            //Write the 2 bytes
            opener.Close();
            Console.WriteLine("\nReplace successful!");
            //Show confirmation.
            Console.Read();
        }
    }
}




Spoiled to save space. Comments are in there lol.

Looking nice! I don't follow a lot of the technical details, but the basic structure is definitely there, and it looks like C# has some convenient utilities built-in for you as well, so you don't have to do a lot of defining your own functions. Let me know if there's anything else I can help with, but for the most part, I think you've got the general scheme of things going quite well, now. (I borrowed some ideas from this code to use in mine, namely using strings to represent the bytes in the print-out statements. It was too good an idea to pass up. :3)
User avatar
Balcerzak
Crack Addic!
 
Posts: 174
Joined: October 29th, 2007, 8:21 pm
Location: Michigan, USA

Unread postby furyoftheskies » November 16th, 2008, 9:23 pm

Yowza, interesting C++ code, haven't seen a union being used before. I'm mostly used to structures and classes lol.

After looking through your code, I got some ideas to use. I'm going to make this into a GUI tool lol, so I'll show you the progress I get along with the basic code implementation.

I like your fail counter lol, normally I don't use that and just use a try catch statement within a do while loop. When I make the GUI, I'll just make it so it has 2 buttons lol, the only other way for them to fail is if they decide to press ALT + F4 :shock: .

Oh yeah, theres also one more thing I'll need to add to the code by the way.

The first header is an offset that leads to the checkers of the file (the ones that offset to the other files).

In charaprof, its 0x880 + 0xE4 = 2404 or offset 0x964. From pretty much the offset to the end, I'll need to use another 2 byte array. I'll use the seeker to check for all F2 bytes. The same if else statement would look like this (In words, I'll write the language code for it later and paste it).
Code: Select all
file.position = firstHexHeader + headerSize
while (file.position < fileSize)
{
   look at the next byte;
   if (byte value == F2)
   {
      Look at the next two values afterwords, read little endian.
      if (next two bytes greater than firstHexHeader)
      {
         change it.
      }
   }
    file.position++
}


We'll see what happens lol.

Edit 1: REJOICE! MY GUI PROGRAM WORKS! Heres a picture of it, and heres the log it created for me! (I used a purposed messed up header on a file to verify it!

ImageImage

EDIT 2: This is the new log type, Its quite detailed actually, I hope it makes sense.

Attempting to open Original File: E:\charaprofORIGINAL.scn
File Successfully Opened!

Attempting to open Modified File: E:\charaprofMODDED.scn
File Successfully Opened!

Ready to check files!
Press the Check Offsets button to start!

Original File:
First bytes written as: 6F0B
First bytes reversed are: 0B6F
This value is 2927
The filesize is 3155
The header size is 228

Modified File:
First bytes written as: 3344
First bytes reversed are: 4433
This value is 17459
The filesize is 3158
The header size is -14301

Original Header: 228
Modified Header: -14301

Headers do not match! Press Fix Header Size button to fix this!

Original File, 1st Offset:
Original Offset Written: 8008
Original Offset Reversed: 0880

Modified File, 1st Offset:
Modified Offset Written: 8208
Modified Offset Reversed: 0882

Difference in Size: 3

First Offset is incorrect! Press Fix Offsets to fix this!

Replacing Modified File with Correct Header Size...
Original Value: 0B6F
New Value: 0B72

Header Size Replace Successful!


Offset 1 written as: 8008
Offset 1 reversed: 0880

Changing Offset 1 to correct value...
Previous Value: 964
New Value: 967
Offset Written Successfully!

Offset 2 written as: 930A
Offset 2 reversed: 0A93

Changing Offset 2 to correct value...
Previous Value: B77
New Value: B7A
Offset Written Successfully!

Offset 3 written as: BE0A
Offset 3 reversed: 0ABE

Changing Offset 3 to correct value...
Previous Value: BA2
New Value: BA5
Offset Written Successfully!

Offset 4 written as: ED0A
Offset 4 reversed: 0AED

Changing Offset 4 to correct value...
Previous Value: BD1
New Value: BD4
Offset Written Successfully!

Offset 5 written as: 190B
Offset 5 reversed: 0B19

Changing Offset 5 to correct value...
Previous Value: BFD
New Value: C00
Offset Written Successfully!

Offset 6 written as: 450B
Offset 6 reversed: 0B45

Changing Offset 6 to correct value...
Previous Value: C29
New Value: C2C
Offset Written Successfully!


Man Balcerzak, I gotta thank you very much for helping me out with the initial code. For now, I've got down the basic change the first 2 bytes. My next step would be to check the offsets and make sure they point to the correct byte (which isn't going to be too bad, since I know what value they have to point to) so I'll keep updating this till I have a tool I can rely on. That way, all I have to do is translation and nothing more!
User avatar
furyoftheskies
Might just like this board
 
Posts: 37
Joined: November 2nd, 2008, 1:21 pm

Unread postby Balcerzak » November 17th, 2008, 1:17 pm

furyoftheskies wrote:Yowza, interesting C++ code, haven't seen a union being used before. I'm mostly used to structures and classes lol.

After looking through your code, I got some ideas to use. I'm going to make this into a GUI tool lol, so I'll show you the progress I get along with the basic code implementation.

I like your fail counter lol, normally I don't use that and just use a try catch statement within a do while loop. When I make the GUI, I'll just make it so it has 2 buttons lol, the only other way for them to fail is if they decide to press ALT + F4 :shock: .

Yeah, to be perfectly honest, I'd never seen a union used ever before either. Nor really for that matter structures, it's mostly just been classes or nothing. But hey, this gave me a chance to learn something new, which was cool, whether or not it will ever prove useful again for me.

Like I said, I usually don't work with user input, and had completely forgotten about try/catch to be honest. I was pretty much making things up there as I went along.
fury wrote:Oh yeah, theres also one more thing I'll need to add to the code by the way.

The first header is an offset that leads to the checkers of the file (the ones that offset to the other files).

In charaprof, its 0x880 + 0xE4 = 2404 or offset 0x964. From pretty much the offset to the end, I'll need to use another 2 byte array. I'll use the seeker to check for all F2 bytes. The same if else statement would look like this (In words, I'll write the language code for it later and paste it).
Code: Select all
file.position = firstHexHeader + headerSize
while (file.position < fileSize)
{
   look at the next byte;
   if (byte value == F2)
   {
      Look at the next two values afterwords, read little endian.
      if (next two bytes greater than firstHexHeader)
      {
         change it.
      }
   }
    file.position++
}


We'll see what happens lol.

Yeah, I sort of noticed that when I went back and actually re-read the first page in more detail. The last time I'd actually tried much in the way of hex manipulation was back in the summer of '06 in an ill-fated attempt to do a rom-hack translation, in which I quickly found myself completely in over my head (mostly due to very similar pointer problems), so I wanted to make sure I could follow and understand what phib and you had been discussing, and make sure the way I was interpreting what was said correctly, and thus how I was designing the program actually made any sense.

(This was spearheaded in earnest when I had just blindly copied the offsets to look at from phibs image, and while the first several worked, a lot of the later ones did not; these being the ones after e4 + 880, where the two bytes to be looked at didn't live in the same place.)

I then gave up and left out implementing that part of the code, mostly because I was too lazy to try to figure out the best way to seek through and look for the F2 bits, and also because it wasn't really necessary for the demonstration of successful execution in simple cases. Also, there's the fact that I don't actually own a copy of the game, so all I've had to go on were the few test scripts you'd uploaded, and I couldn't just test to see whether or not what I was doing fixed any crashing problems. This lead me to desire a simple finished product, that while it may not completely do what was needed, at least did what it was supposed to do, and did that well.

fury wrote:Edit 1: REJOICE! MY GUI PROGRAM WORKS! Heres a picture of it, and heres the log it created for me! (I used a purposed messed up header on a file to verify it!



Heres the log that I implemented that comes out (I made it so you can save it to a text file! Woot!)

Attempting to open Original File: E:\charaprofORIGINAL.scn
File Successfully Opened!

Attempting to open Modified File: E:\charaprof.scn
File Successfully Opened!

Ready to check files!
Press the Check Offsets button to start!

Original File:

First bytes written as: 6F0B
First bytes reversed are: 0B6F
This value is 2927
The filesize is 3155
The header size is 228

Modified File:

First bytes written as: 4567
First bytes reversed are: 6745
This value is 26437
The filesize is 3284
The header size is -23153

Original Header: 228
Modified Header: -23153

Headers do not match!
Press Fix Offsets button to fix this!

Replacing Modified File with Correct Header Size...

Replace successful! Verifying...

Original File:

First bytes written as: 6F0B
First bytes reversed are: 0B6F
This value is 2927
The filesize is 3155
The header size is 228

Modified File:

First bytes written as: F00B
First bytes reversed are: 0BF0
This value is 3056
The filesize is 3284
The header size is 228

File was successfully fixed!


Man Balcerzak, I gotta thank you very much for helping me out with the initial code. For now, I've got down the basic change the first 2 bytes. My next step would be to check the offsets and make sure they point to the correct byte (which isn't going to be too bad, since I know what value they have to point to) so I'll keep updating this till I have a tool I can rely on. That way, all I have to do is translation and nothing more!

That's awesome news. Glad to hear my tinkering has been of some help. I must admit I had been a little skeptical the first time I read this topic when you basically said that you were going to hex-edit the whole game by hand, but I must say now that there's been some real progress on tool development I think the outlook is a lot more positive. At least, I see it that way.

I'll keep checking up on how things are going here. Maybe if you get stuck again, I can try to help out, though I can't make any guarantees. (I must warn you, I've no experience in making GUIs whatsoever, nor [as previously mentioned] C sharp. But if there's a well-defined challenge that's stumping you, I could probably try to work through a C++ approach, which would at least give you something to look at.)
User avatar
Balcerzak
Crack Addic!
 
Posts: 174
Joined: October 29th, 2007, 8:21 pm
Location: Michigan, USA

Unread postby furyoftheskies » November 18th, 2008, 12:05 pm

Balcerzak wrote: I'll keep checking up on how things are going here. Maybe if you get stuck again, I can try to help out, though I can't make any guarantees. (I must warn you, I've no experience in making GUIs whatsoever, nor [as previously mentioned] C sharp. But if there's a well-defined challenge that's stumping you, I could probably try to work through a C++ approach, which would at least give you something to look at.)

Yes, I'd appreciate your help in the future should I need it ^_^

As of right now, the offset checker is working very smoothly! Heres a sample log of what is going on when the program runs. I added comments denoted by // so you can tell what the log produced and what I entered so you can understand.

//This is just opening the two files to compare
Attempting to open Original File: D:\Pure Pure [KLEIN] [1.29GB]\script\prof_s_hinata.scn
File Successfully Opened!

Attempting to open Modified File: D:\Pure Pure [KLEIN] [1.29GB]\Finished Scripts\prof_s_hinata.scn
File Successfully Opened!

//This enables the check files button
Ready to check files!
Press the Check Offsets button to start!

//This looks the first two bytes, rewrites them backwards, and makes sure they are OK.
//The correct header is dependent upon the original scripts, so you need them to check the offsets.
Original File:
First bytes written as: AA37
First bytes reversed are: 37AA
This value is 14250
The filesize is 14766
The header size is 516

Modified File:
First bytes written as: 5D39
First bytes reversed are: 395D
This value is 14685
The filesize is 15201
The header size is 516


//Since these two match, then the file is ok for the header.
Original Header: 516
Modified Header: 516

Headers match! Moving on to Offset Checks!

//This next part is actually a bit interesting. What I did was, I obtained the offset listed in the original and modified files,
/*Then, instead of using a size difference to check if they both matched (Because this file actually has size differences that vary from 42-435!) I instead implemented a byte reader. It gets 3 bytes, specifically, the byte BEFORE the offset location (Usually 00 or 1D), the byte at the offset location (Usually F0), and finally, the byte afterwards (which vary widely, as you can see below). Using these 3 bytes, we compare the 3 bytes at the offset of the original file and the 3 bytes of the offset in the modified file, and see if they match.*/

/*I used 3 bytes because the offset usually points to a location that only has 2 bytes leeway each way (so 5 bytes in between that are the same before the hex is different (Japanese > English hex changes)), but I just slimmed it down to 3, and as you can see, all the offsets match!*/

/*This was a file manually hex edited BEFORE I MADE THIS TOOL, so apparently, if my tool isn't lying, I'm doing this right. This file is weird mainly because it has a choice point in the MIDDLE of the script, and then it freaking branches into the 3 choices, and at the end of each of those choices, there was (guess what!) another offset! Thankfully, I know where the offset points to, so its easy to change it (it points to the first offset that contains the F2 offsets). And when I searched it, it was the only one there, so its easy to find with a brute checker. */

/*Anyways, there is another log that tells me what I have to manually edit, so not only can I use the program to see what I have to manually hex, but I can also use it again to recheck the file so that the offsets are right!*/

Original File, Offset 1:
Original Offset Written: FD16
Original Offset Reversed: 16FD

Modified File, Offset 1:
Modified Offset Written: A617
Modified Offset Reversed: 17A6
Bytes around original file offset 16FD: 00 F0 1C
Bytes around modified file offset 17A6: 00 F0 1C

Offset is correct!

Original File, Offset 2:
Original Offset Written: 6717
Original Offset Reversed: 1767

Modified File, Offset 2:
Modified Offset Written: 1D18
Modified Offset Reversed: 181D
Bytes around original file offset 1767: 1D F0 1C
Bytes around modified file offset 181D: 1D F0 1C

Offset is correct!

Original File, Offset 3:
Original Offset Written: AF17
Original Offset Reversed: 17AF

Modified File, Offset 3:
Modified Offset Written: 6918
Modified Offset Reversed: 1869
Bytes around original file offset 17AF: 1D F0 1C
Bytes around modified file offset 1869: 1D F0 1C

Offset is correct!

Original File, Offset 4:
Original Offset Written: FD17
Original Offset Reversed: 17FD

Modified File, Offset 4:
Modified Offset Written: C018
Modified Offset Reversed: 18C0
Bytes around original file offset 17FD: 1D F0 1C
Bytes around modified file offset 18C0: 1D F0 1C

Offset is correct!

Original File, Offset 5:
Original Offset Written: 3D18
Original Offset Reversed: 183D

Modified File, Offset 5:
Modified Offset Written: 0D19
Modified Offset Reversed: 190D
Bytes around original file offset 183D: 1D F0 1C
Bytes around modified file offset 190D: 1D F0 1C

Offset is correct!

Original File, Offset 6:
Original Offset Written: 6918
Original Offset Reversed: 1869

Modified File, Offset 6:
Modified Offset Written: 3919
Modified Offset Reversed: 1939
Bytes around original file offset 1869: 1D F0 1C
Bytes around modified file offset 1939: 1D F0 1C

Offset is correct!

Original File, Offset 7:
Original Offset Written: 8718
Original Offset Reversed: 1887

Modified File, Offset 7:
Modified Offset Written: 5B19
Modified Offset Reversed: 195B
Bytes around original file offset 1887: 1D F0 1C
Bytes around modified file offset 195B: 1D F0 1C

Offset is correct!

Original File, Offset 8:
Original Offset Written: AB18
Original Offset Reversed: 18AB

Modified File, Offset 8:
Modified Offset Written: 8819
Modified Offset Reversed: 1988
Bytes around original file offset 18AB: 1D F0 00
Bytes around modified file offset 1988: 1D F0 00

Offset is correct!

Original File, Offset 9:
Original Offset Written: 7A32
Original Offset Reversed: 327A

Modified File, Offset 9:
Modified Offset Written: 1834
Modified Offset Reversed: 3418
Bytes around original file offset 327A: 00 F0 0F
Bytes around modified file offset 3418: 00 F0 0F

Offset is correct!

Original File, Offset 10:
Original Offset Written: AB22
Original Offset Reversed: 22AB

Modified File, Offset 10:
Modified Offset Written: CF23
Modified Offset Reversed: 23CF
Bytes around original file offset 22AB: 00 F0 00
Bytes around modified file offset 23CF: 00 F0 00

Offset is correct!

Original File, Offset 11:
Original Offset Written: 002D
Original Offset Reversed: 2D00

Modified File, Offset 11:
Modified Offset Written: 472E
Modified Offset Reversed: 2E47
Bytes around original file offset 2D00: 00 F0 00
Bytes around modified file offset 2E47: 00 F0 00

Offset is correct!

Original File, Offset 12:
Original Offset Written: 9634
Original Offset Reversed: 3496

Modified File, Offset 12:
Modified Offset Written: 3436
Modified Offset Reversed: 3634
Bytes around original file offset 3496: 00 F0 16
Bytes around modified file offset 3634: 00 F0 16

Offset is correct!

Original File, Offset 13:
Original Offset Written: A434
Original Offset Reversed: 34A4

Modified File, Offset 13:
Modified Offset Written: 4236
Modified Offset Reversed: 3642
Bytes around original file offset 34A4: 00 F0 46
Bytes around modified file offset 3642: 00 F0 46

Offset is correct!

Original File, Offset 14:
Original Offset Written: 9D34
Original Offset Reversed: 349D

Modified File, Offset 14:
Modified Offset Written: 3B36
Modified Offset Reversed: 363B
Bytes around original file offset 349D: 00 F0 16
Bytes around modified file offset 363B: 00 F0 16

Offset is correct!

All Offsets are Correct!

File bytes are all ok!


Edit1: Well, the tool is nearly complete. Now what I need to figure out is how to hack the images of the pak file.

The problem with the pak file is that the files are compressed (There are 3 little endian hexes, one that states its size uncompressed, its size compressed, and then its offset location). I'm not sure how to decompress a file like that, so if someone could lead me to figuring out what type of compression its using, I would appreciate it.

I know that it must be possible, since the CG's are floating around the internet, so I want to know how so that I can try my hand at replacing bytes and image hacking.

Edit 2: Tool is 90% complete! I'm just fixing the ending header checker so that it fixes properly! After that, I'll have a working tool that will check ALL offsets and values for me! I'm going back to translating once I get this one done (unless someone teaches me to image hack first lol)

Edit 3: Tool 100% Complete! I'm going back to translation now! Hopefully I'll release an intro patch before mid december!

Heres the pic of the final tool. Its a whopping 64 KB file size exe.

ImageImage
User avatar
furyoftheskies
Might just like this board
 
Posts: 37
Joined: November 2nd, 2008, 1:21 pm

Unread postby phib » November 23rd, 2008, 7:15 pm

furyoftheskies wrote:Edit1: Well, the tool is nearly complete. Now what I need to figure out is how to hack the images of the pak file.

The problem with the pak file is that the files are compressed (There are 3 little endian hexes, one that states its size uncompressed, its size compressed, and then its offset location). I'm not sure how to decompress a file like that, so if someone could lead me to figuring out what type of compression its using, I would appreciate it.

I know that it must be possible, since the CG's are floating around the internet, so I want to know how so that I can try my hand at replacing bytes and image hacking.


You're lucky, I checked the decompression algorithm and it turns out it's exactly the same used in another game I coded an unpacker for.
http://www.megaupload.com/?d=W8GCE8LN
(Usage: purepak cg.pak outfolder)

If you create a folder named 'cg' and drop in the edited bmps, the game will read them first from there instead of the cg.pak.
User avatar
phib
Addict
 
Posts: 104
Joined: May 9th, 2007, 12:25 am

Unread postby furyoftheskies » November 24th, 2008, 10:39 am

phib wrote:You're lucky, I checked the decompression algorithm and it turns out it's exactly the same used in another game I coded an unpacker for.
http://www.megaupload.com/?d=W8GCE8LN
(Usage: purepak cg.pak outfolder)

If you create a folder named 'cg' and drop in the edited bmps, the game will read them first from there instead of the cg.pak.


Oh. My. Gosh. phib, you are definitely an expert in this field. Argh, as much as I love the fact that you gave me the program to decompress the files, and the knowledge that the game will read a CG folder before cg.pak, I'd love to figure out how you got the decompression code (I'd like to make a miniature GUI). Would you be willing to teach that, or is that secret stuff I shouldn't touch yet?

Also, how did you know about the cg folder drop? Was that by chance or something?

One more question: These .bmp's have some transparency black channel don't they? I'm guessing I need to save alpha channels, but I don't know what the heck those are =(. Could someone direct me somewhere? I have photoshop, so I can do something.
Currently Translating: Pure Pure The Story of Ears and Tails AKA Pyua Pyua Mimi to Shippo no Monogatari
User avatar
furyoftheskies
Might just like this board
 
Posts: 37
Joined: November 2nd, 2008, 1:21 pm

Unread postby phib » November 24th, 2008, 1:07 pm

furyoftheskies wrote:I'd love to figure out how you got the decompression code (I'd like to make a miniature GUI).

Debugging. The algorithm is the typical lz variation with a sliding window.
http://purepure.pastebin.com/f2ff73105

Also, how did you know about the cg folder drop? Was that by chance or something?

Debugging.

One more question: These .bmp's have some transparency black channel don't they? I'm guessing I need to save alpha channels, but I don't know what the heck those are =(. Could someone direct me somewhere? I have photoshop, so I can do something.


They're 32bit bmp's, you'll need something better than paint to edit them, like gimp or probably photoshop.
User avatar
phib
Addict
 
Posts: 104
Joined: May 9th, 2007, 12:25 am

Unread postby furyoftheskies » November 24th, 2008, 9:35 pm

phib wrote:Debugging. The algorithm is the typical lz variation with a sliding window.
http://purepure.pastebin.com/f2ff73105


Oh dang. I'm trying to understand what you gave me, but I have no clue what the heck a lz variation with a sliding window is :(

I can slightly understand the code, but it is a bit confusing.

I see the declaration of the dictionary obtained by the decoder for back referencing (I think?) but then I get lost after a few lines.

Would anyone out there care to explain?
Currently Translating: Pure Pure The Story of Ears and Tails AKA Pyua Pyua Mimi to Shippo no Monogatari
User avatar
furyoftheskies
Might just like this board
 
Posts: 37
Joined: November 2nd, 2008, 1:21 pm

Unread postby phib » November 24th, 2008, 11:37 pm

User avatar
phib
Addict
 
Posts: 104
Joined: May 9th, 2007, 12:25 am

Unread postby furyoftheskies » November 25th, 2008, 2:45 am

I wonder how many thanks I'm going to owe you after this.

P.S. I've solved the japanese problems now. I just changed their names to hold the brackets, thanks for the idea.

Usually, the name is typed like this:

【Midou】

To get rid of the stupid brackets showing up on the tildes, I simply replaced the name to hold the brackets only:

「Midou」

This way, the program doesn't produce the annoying brackets if I decide to use full width tilde(~) or the music sign (♪).
Currently Translating: Pure Pure The Story of Ears and Tails AKA Pyua Pyua Mimi to Shippo no Monogatari
User avatar
furyoftheskies
Might just like this board
 
Posts: 37
Joined: November 2nd, 2008, 1:21 pm

Unread postby Randy1919 » January 13th, 2009, 5:15 pm

Hi.Great project keep up the good work.
Randy1919
Totally hardly posted
 
Posts: 1
Joined: December 24th, 2008, 3:17 pm

Pure Pure PS2

Unread postby Shadetale » January 21st, 2009, 8:36 pm

I'm curious if you're thinking about adding the PS2 bonuses(I.E. Midou as well as the random characters(like the teachers) being voiced, the ending song as well as the bonus CGs). I personally think Midou being voiced adds a LOT to the game. Plus the song they chose for Sachi's (Spoiler: Death scene /Spoiler)is rather poor compared to SA-CHI, the song they added for the PS2 release.
Shadetale
Totally hardly posted
 
Posts: 2
Joined: January 21st, 2009, 8:27 pm

Re: Pure Pure PS2

Unread postby furyoftheskies » January 27th, 2009, 8:05 am

Shadetale wrote:I'm curious if you're thinking about adding the PS2 bonuses(I.E. Midou as well as the random characters(like the teachers) being voiced, the ending song as well as the bonus CGs). I personally think Midou being voiced adds a LOT to the game. Plus the song they chose for Sachi's
(Death Scene)
is rather poor compared to SA-CHI, the song they added for the PS2 release.


Well, if I could only find that song. I reviewed the scene, and while it is true the song might sound a bit too happy, it IS Sachi's character song.

I can change the BGMs of the song. Actually, if I really wanted, I make the game use a custom song that you can't access in the gallery.

I don't have access to a copy of the PS2 version of pure pure, either.
Currently Translating: Pure Pure The Story of Ears and Tails AKA Pyua Pyua Mimi to Shippo no Monogatari
User avatar
furyoftheskies
Might just like this board
 
Posts: 37
Joined: November 2nd, 2008, 1:21 pm

PreviousNext

Return to General Translation Projects

Who is online

Users browsing this forum: No registered users and 2 guests