Project: UnLockRay ( ULR / REL )

Right, this software lays it out a bit more clearly for me, so now I can see that these patterns appear to be little-endian in terms of byte order, even though the map names at the top are written the right way around.

EDIT: The numbers seem to switch between four-byte, six-byte and eight-byte representation, which is kind of weird. Also, the start of one of the six-byte sections has the word "CACA" repeated, in at least two files. Coincidence? :lol:

EDIT2: It's just part of a number. DADA, EAEA, FAFA, etc. appear further down. Still, these patterns do seem quite long. If I could figure out how it signals the change in number length maybe I could write a little C programme that lists them all in decimal.
 
'kay, guys I was watching through the Rayman Arena textures and saw that:
6sq61UW.png


That means there was a demo of Rayman M ?
 
There probably was one for use in gaming conventions before the game came out, I remember IGN or similar play one and uploaded a small realplayer clip of it (which is now gone of course).
 
Cairnie said:
There probably was one for use in gaming conventions before the game came out, I remember IGN or similar play one and uploaded a small realplayer clip of it (which is now gone of course).
Ah. If only we could get it :mryellow:
 
Maybe they planned a demo but never released it?

That other texture looks like a very frustrated developer tried to get his message across to early testers by actually scanning in a post-it! :lol:

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
As for my C programme to read the patterns, here's what I have so far:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#define BITS 4

int CompareWith(char *name, unsigned char *buffer1, int bytes, unsigned long stopAfter) {
	FILE *file;
	unsigned char *buffer2;
	unsigned long fileLen;

	//Open file
	file = fopen(name, "rb");
	if (!file)
	{
		fprintf(stderr, "Unable to open file %s\n", name);
		return -1;
	}
	
	//Get file length
	fseek(file, 0, SEEK_END);
	fileLen=ftell(file);
	fseek(file, 0, SEEK_SET);

	//Allocate memory
	buffer2=(unsigned char *)malloc(fileLen+1);
	if (!buffer2)
	{
		fprintf(stderr, "Memory error!\n");
                                fclose(file);
		return -1;
	}

	//Read file contents into buffer2
	fread(buffer2, fileLen, 1, file);
	fclose(file);
	
	int i;
	int j;
	unsigned long long number1;
	unsigned long long number2;
	unsigned long long diff;
	for(i=0;i<stopAfter;i+=bytes) {
		number1 = number2 = 0;
		for(j=0;j<bytes;j++) {
			number1 += (unsigned long long)(buffer1[i+j]) << j*8;
			number2 += (unsigned long long)(buffer2[i+j]) << j*8;
		}
		diff = (number1>number2) ? (number1-number2) : (number2-number1);
		printf("%i: %llu\n", i/bytes + 1, diff);
	}

	free(buffer1);
	free(buffer2);
	return i/bytes;
}

int main(int argc, char **argv)
{
	if(argc < 2)
	{
		printf("Error! No filename specified!\n");
		return 1;
	}
	
	int bytes = BITS;
	if(argc > 2) {
		int ai = 0;
		for(ai=0;ai<argc;ai++) {
			if(!strcmp("--bytes", argv[ai]) && argc > ai) {
				bytes = atoi(argv[ai+1]);
			}
		}
	}
	int maxBytes = sizeof(long long);
	if(bytes > maxBytes) {
		printf("Too many bytes!\nAutosetting to %i...\n", maxBytes);
		bytes = maxBytes;
	}
	
	FILE *file;
	unsigned char *buffer;
	unsigned long fileLen;

	//Open file
	file = fopen(argv[1], "rb");
	if (!file)
	{
		fprintf(stderr, "Unable to open file %s\n", argv[1]);
		return 1;
	}
	
	//Get file length
	fseek(file, 0, SEEK_END);
	fileLen=ftell(file);
	fseek(file, 0, SEEK_SET);

	//Allocate memory
	buffer=(unsigned char *)malloc(fileLen+1);
	if (!buffer)
	{
		fprintf(stderr, "Memory error!\n");
                                fclose(file);
		return 1;
	}

	//Read file contents into buffer
	fread(buffer, fileLen, 1, file);
	fclose(file);
	
	unsigned long stopAfter = fileLen;
	if(argc > 2) {
		int aj = 0;
		for(aj=0;aj<argc;aj++) {
			if(!strcmp("--numbers", argv[aj]) && argc > aj) {
				stopAfter = atoi(argv[aj+1]) * bytes;
			}
		}
	}
	if(stopAfter > fileLen) {
		stopAfter = fileLen;
	}
	
	int signalsOnly = 0;
	if(argc > 2) {
		int ak = 0;
		for(ak=0;ak<argc;ak++) {
			if(!strcmp("--compare", argv[ak]) && argc > ak) {
				int bytesCompared = CompareWith(argv[ak+1], buffer, bytes, stopAfter);
				if(bytesCompared > 0) {
					printf("\nCompared %i %i-bit numbers from %s and %s\n", bytesCompared, bytes * 8, argv[1], argv[ak+1]);
					return 0;
				} else {
					return 1;
				}
			} else if(!strcmp("--signals", argv[ak])) {
				signalsOnly = 1;
			}
		}
	}

	int i;
	int j;
	unsigned long long number;
	int skippingList;
	for(i=0;i<stopAfter;i+=bytes) {
		if( i>1416 && i<3496 ) {
			if(!skippingList) {
				printf("(Skipped maplist)\n");
				skippingList = 1;
			}
		} else {
			skippingList = 0;
			number = 0;
			for(j=0;j<bytes;j++) {
				number += (unsigned long long)(buffer[i+j]) << j*8;
			}
			if(bytes == 4 && number == ('C' + ('A'<<8) + ('C'<<16) + ('A'<<24))) {
				//CACA seems to change it :P
				printf("Found possible signaling number %llu @ %i\n", number, i/bytes);
				i -= 2; //Offset slightly
				bytes = 6;
			}
			if(bytes == 6 && number == (0xA0UL + (0xBDUL<<8) + (0xE5UL<<16) + (0x07UL<<24) + (0x07UL<<32))) {
				printf("Found possible signaling number %llu @ %i\n", number, i/bytes);
				bytes = 8;
			}
			if( !signalsOnly ) {
				printf("%i: %llu (%i-bit)\n", i/bytes + 1, number, bytes * 8);
			}
		}
	}
	printf("\nRead %i %i-bit numbers from %s\n", i/bytes, bytes * 8, argv[1]);

	free(buffer);
	return 0;
}

If anyone's interested in compiling and running it, here's what you should know:
It can compare two different files, or take one individually. The first argument must be the name of a file. Other acceptable arguments (all optional) are:
  • --bytes <number> Read the numbers as being <number> bytes wide (defaults to 4)
  • --numbers <number> Stop after reading <number> numbers from the file (defaults to reading the whole file)
  • --compare <filename> Compare the file specified as the first argument with <filename> by showing the differences between the numbers
  • --signals Don't show every number, just those that have been programmed in as "signalling numbers" to change the number width

At the moment, the only two signalling numbers are "CACA" (1094926659) to switch from four-byte numbers to six-byte and 30197267872 to switch from six-byte to eight-byte. The former works in every file, but the latter works only in Whale_05.gpt, meaning that the files use some other way to signal a change in number size.

I was looking back through the archives and noticed CheatCat and LunaVorax were discussing the use of a disassembler on Rayman 2 back in 2009. I think that could still be a viable option, unless it gets us into trouble (of which there is a slim chance).

EDIT: Here's what I got from Whale_05.gpt. I feel I may be on a wild goose chase here.

EDIT2: A counting pattern starts at number 37478. There are other counting patterns that are more difficult to see because of the different numbers between them. Those are probably part of some kind of table.
 
PluMGMK said:
Maybe they planned a demo but never released it?

That other texture looks like a very frustrated developer tried to get his message across to early testers by actually scanning in a post-it! :lol:

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
As for my C programme to read the patterns, here's what I have so far:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#define BITS 4

int CompareWith(char *name, unsigned char *buffer1, int bytes, unsigned long stopAfter) {
	FILE *file;
	unsigned char *buffer2;
	unsigned long fileLen;

	//Open file
	file = fopen(name, "rb");
	if (!file)
	{
		fprintf(stderr, "Unable to open file %s\n", name);
		return -1;
	}
	
	//Get file length
	fseek(file, 0, SEEK_END);
	fileLen=ftell(file);
	fseek(file, 0, SEEK_SET);

	//Allocate memory
	buffer2=(unsigned char *)malloc(fileLen+1);
	if (!buffer2)
	{
		fprintf(stderr, "Memory error!\n");
                                fclose(file);
		return -1;
	}

	//Read file contents into buffer2
	fread(buffer2, fileLen, 1, file);
	fclose(file);
	
	int i;
	int j;
	unsigned long long number1;
	unsigned long long number2;
	unsigned long long diff;
	for(i=0;i<stopAfter;i+=bytes) {
		number1 = number2 = 0;
		for(j=0;j<bytes;j++) {
			number1 += (unsigned long long)(buffer1[i+j]) << j*8;
			number2 += (unsigned long long)(buffer2[i+j]) << j*8;
		}
		diff = (number1>number2) ? (number1-number2) : (number2-number1);
		printf("%i: %llu\n", i/bytes + 1, diff);
	}

	free(buffer1);
	free(buffer2);
	return i/bytes;
}

int main(int argc, char **argv)
{
	if(argc < 2)
	{
		printf("Error! No filename specified!\n");
		return 1;
	}
	
	int bytes = BITS;
	if(argc > 2) {
		int ai = 0;
		for(ai=0;ai<argc;ai++) {
			if(!strcmp("--bytes", argv[ai]) && argc > ai) {
				bytes = atoi(argv[ai+1]);
			}
		}
	}
	int maxBytes = sizeof(long long);
	if(bytes > maxBytes) {
		printf("Too many bytes!\nAutosetting to %i...\n", maxBytes);
		bytes = maxBytes;
	}
	
	FILE *file;
	unsigned char *buffer;
	unsigned long fileLen;

	//Open file
	file = fopen(argv[1], "rb");
	if (!file)
	{
		fprintf(stderr, "Unable to open file %s\n", argv[1]);
		return 1;
	}
	
	//Get file length
	fseek(file, 0, SEEK_END);
	fileLen=ftell(file);
	fseek(file, 0, SEEK_SET);

	//Allocate memory
	buffer=(unsigned char *)malloc(fileLen+1);
	if (!buffer)
	{
		fprintf(stderr, "Memory error!\n");
                                fclose(file);
		return 1;
	}

	//Read file contents into buffer
	fread(buffer, fileLen, 1, file);
	fclose(file);
	
	unsigned long stopAfter = fileLen;
	if(argc > 2) {
		int aj = 0;
		for(aj=0;aj<argc;aj++) {
			if(!strcmp("--numbers", argv[aj]) && argc > aj) {
				stopAfter = atoi(argv[aj+1]) * bytes;
			}
		}
	}
	if(stopAfter > fileLen) {
		stopAfter = fileLen;
	}
	
	int signalsOnly = 0;
	if(argc > 2) {
		int ak = 0;
		for(ak=0;ak<argc;ak++) {
			if(!strcmp("--compare", argv[ak]) && argc > ak) {
				int bytesCompared = CompareWith(argv[ak+1], buffer, bytes, stopAfter);
				if(bytesCompared > 0) {
					printf("\nCompared %i %i-bit numbers from %s and %s\n", bytesCompared, bytes * 8, argv[1], argv[ak+1]);
					return 0;
				} else {
					return 1;
				}
			} else if(!strcmp("--signals", argv[ak])) {
				signalsOnly = 1;
			}
		}
	}

	int i;
	int j;
	unsigned long long number;
	int skippingList;
	for(i=0;i<stopAfter;i+=bytes) {
		if( i>1416 && i<3496 ) {
			if(!skippingList) {
				printf("(Skipped maplist)\n");
				skippingList = 1;
			}
		} else {
			skippingList = 0;
			number = 0;
			for(j=0;j<bytes;j++) {
				number += (unsigned long long)(buffer[i+j]) << j*8;
			}
			if(bytes == 4 && number == ('C' + ('A'<<8) + ('C'<<16) + ('A'<<24))) {
				//CACA seems to change it :P
				printf("Found possible signaling number %llu @ %i\n", number, i/bytes);
				i -= 2; //Offset slightly
				bytes = 6;
			}
			if(bytes == 6 && number == (0xA0UL + (0xBDUL<<8) + (0xE5UL<<16) + (0x07UL<<24) + (0x07UL<<32))) {
				printf("Found possible signaling number %llu @ %i\n", number, i/bytes);
				bytes = 8;
			}
			if( !signalsOnly ) {
				printf("%i: %llu (%i-bit)\n", i/bytes + 1, number, bytes * 8);
			}
		}
	}
	printf("\nRead %i %i-bit numbers from %s\n", i/bytes, bytes * 8, argv[1]);

	free(buffer);
	return 0;
}

If anyone's interested in compiling and running it, here's what you should know:
It can compare two different files, or take one individually. The first argument must be the name of a file. Other acceptable arguments (all optional) are:
  • --bytes <number> Read the numbers as being <number> bytes wide (defaults to 4)
  • --numbers <number> Stop after reading <number> numbers from the file (defaults to reading the whole file)
  • --compare <filename> Compare the file specified as the first argument with <filename> by showing the differences between the numbers
  • --signals Don't show every number, just those that have been programmed in as "signalling numbers" to change the number width

At the moment, the only two signalling numbers are "CACA" (1094926659) to switch from four-byte numbers to six-byte and 30197267872 to switch from six-byte to eight-byte. The former works in every file, but the latter works only in Whale_05.gpt, meaning that the files use some other way to signal a change in number size.

I was looking back through the archives and noticed CheatCat and LunaVorax were discussing the use of a disassembler on Rayman 2 back in 2009. I think that could still be a viable option, unless it gets us into trouble (of which there is a slim chance).

EDIT: Here's what I got from Whale_05.gpt. I feel I may be on a wild goose chase here.
Nice! can you get on Skype? I'm gonna eat but I'll get back
 
I think so.

In case anyone didn't notice from my second edit to my last post: A counting pattern starts at number 37478. There are other counting patterns that are more difficult to see because of the different numbers between them. Those are probably part of some kind of table.
 
Well that certainly looks thrown together in an hour or so doesn't it? :P Otherwise very nice find!
 
Good news, I found some early stages name of R3 on a website.
Code:
Final = Early
Clearleaf Forest =  Forest of Clear Leaves
Bog of Murk = The Umber Swamp
Land of The Livid Dead =  Moor of Mad Spirits
Hoodlum Headquarters=  Hoodlum Meddleworks
 
Humm, the Umber Swamp. I would've loved to have seen what that would've entailed. Perhaps a re-encounter of the stout statue?
 
Back
Top