Graal Forums

Graal Forums (https://forums.graalonline.com/forums/index.php)
-   Level Design (https://forums.graalonline.com/forums/forumdisplay.php?f=6)
-   -   .graal level format (https://forums.graalonline.com/forums/showthread.php?t=134269373)

scriptless 07-13-2014 06:54 AM

.graal level format
 
5 Attachment(s)
So since everyone can pretty easily open and read .nw files why hasn't anyone tried to understand .graal files? Well for anyone thats interested in trying I figured we could start a thread. Below I attached an experiment I did. The levels are in order then the 5th picture shows the ASCII and the HEXIDECIMAL values for them.

PhantosP2P 07-13-2014 11:04 AM

This is one of those sleuthing projects, for sure!

scriptless 07-13-2014 03:45 PM

Well there is a graal version at the top followed by @. But this is different in other levels I took samples of. I think this is an interesting worthwhile project and if we all kinda combined are thoughts on it maybe it would be easier to understand. Or maybe just maybe Stefan can post and point us in the right direction? XD

Gos_pira 07-13-2014 04:09 PM

There are source code out there for reading the graal and zelda levels.

scriptless 07-13-2014 04:25 PM

Quote:

Originally Posted by Gos_pira (Post 1728711)
There are source code out there for reading the graal and zelda levels.

do you think you could help me find it? I think now that you mention it I remember there being .zelda files.. but no clue what version.

Ah. I see, I am not sure if we can link to the page the source came from but I do believe we can post the snippet here regarding .graal format.

PHP Code:

bool TLevel::loadGraal(const CStringpLevelName)
{
    
// Get the appropriate filesystem.
    
CFileSystemfileSystem server->getFileSystem();
    if (
server->getSettings()->getBool("nofoldersconfig"false) == false)
        
fileSystem server->getFileSystem(FS_LEVEL);

    
// Path-To-File
    
actualLevelName levelName pLevelName;
    
fileName fileSystem->find(pLevelName);
    
modTime fileSystem->getModTime(pLevelName);

    
// Load file
    
CString fileData;
    if (
fileData.load(fileName) == false) return false;

    
// Grab file version.
    
fileVersion fileData.readChars(8);
    
int v = -1;
    if (
fileVersion == "GR-V1.00"0;
    else if (
fileVersion == "GR-V1.01"1;
    else if (
fileVersion == "GR-V1.02"2;
    else if (
fileVersion == "GR-V1.03"3;
    if (
== -1) return false;

    
// Load tiles.
    
{
        
int bits = (13 12);
        
int read 0;
        
unsigned int buffer 0;
        
unsigned short code 0;
        
short tiles[2] = {-1,-1};
        
int boardIndex 0;
        
int count 1;
        
bool doubleMode false;

        
// Read the tiles.
        
while (boardIndex 64*64 && fileData.bytesLeft() != 0)
        {
            
// Every control code/tile is either 12 or 13 bits.  WTF.
            // Read in the bits.
            
while (read bits)
            {
                
buffer += ((unsigned char)fileData.readChar()) << read;
                
read += 8;
            }

            
// Pull out a single 12/13 bit code from the buffer.
            
code buffer & (bits == 12 0xFFF 0x1FFF);
            
buffer >>= bits;
            
read -= bits;

            
// See if we have an RLE control code.
            // Control codes determine how the RLE scheme works.
            
if (code & (bits == 12 0x800 0x1000))
            {
                
// If the 0x100 bit is set, we are in a double repeat mode.
                // {double 4}56 = 56565656
                
if (code 0x100doubleMode true;

                
// How many tiles do we count?
                
count code 0xFF;
                continue;
            }

            
// If our count is 1, just read in a tile.  This is the default mode.
            
if (count == 1)
            {
                
levelTiles[boardIndex++] = (short)code;
                continue;
            }

            
// If we reach here, we have an RLE scheme.
            // See if we are in double repeat mode or not.
            
if (doubleMode)
            {
                
// Read in our first tile.
                
if (tiles[0] == -1)
                {
                    
tiles[0] = (short)code;
                    continue;
                }

                
// Read in our second tile.
                
tiles[1] = (short)code;

                
// Add the tiles now.
                
for (int i 0count && boardIndex 64*64-1; ++i)
                {
                    
levelTiles[boardIndex++] = tiles[0];
                    
levelTiles[boardIndex++] = tiles[1];
                }

                
// Clean up.
                
tiles[0] = tiles[1] = -1;
                
doubleMode false;
                
count 1;
            }
            
// Regular RLE scheme.
            
else
            {
                for (
int i 0count && boardIndex 64*64; ++i)
                    
levelTiles[boardIndex++] = (short)code;
                
count 1;
            }
        }
    }

    
// Load the links.
    
{
        while (
fileData.bytesLeft())
        {
            
CString line fileData.readString("\n");
            if (
line.length() == || line == "#") break;

            
// Assemble the level string.
            
std::vector<CStringvline line.tokenize();
            
CString level vline[0];
            if (
vline.size() > 7)
            {
                for (
unsigned int i 0vline.size() - 7; ++i)
                    
level << " " << vline[i];
            }

            if (
fileSystem->find(level).isEmpty())
                continue;

            
levelLinks.push_back(new TLevelLink(vline));
        }
    }

    
// Load the baddies.
    
{
        while (
fileData.bytesLeft())
        {
            
signed char x fileData.readChar();
            
signed char y fileData.readChar();
            
signed char type fileData.readChar();

            
// Ends with an invalid baddy.
            
if (== -&& == -&& type == -1)
            {
                
fileData.readString("\n");    // Empty verses.
                
break;
            }

            
// Add the baddy.
            
TLevelBaddybaddy addBaddy((float)x, (float)ytype);
            if (
baddy == 0)
                continue;

            
// Load the verses.
            
std::vector<CStringbverse fileData.readString("\n").tokenize("\\");
            
CString props;
            for (
char j 0< (char)bverse.size(); ++j)
                
props >> (char)(BDPROP_VERSESIGHT j) >> (char)bverse[j].length() << bverse[j];
            if (
props.length() != 0baddy->setProps(props);
        }
    }

    
// Load NPCs.
    
{
        while (
fileData.bytesLeft())
        {
            
CString line fileData.readString("\n");
            if (
line.length() == || line == "#") break;

            
signed char x line.readGChar();
            
signed char y line.readGChar();
            
CString image line.readString("#");
            
CString code line.readString("");

            
TNPCnpc server->addNPC(imagecodexythistruefalse);
            
levelNPCs.push_back(npc);
        }
    }

    
// Load chests.
    
if (0)
    {
        while (
fileData.bytesLeft())
        {
            
CString line fileData.readString("\n");
            if (
line.length() == || line == "#") break;

            
signed char x line.readGChar();
            
signed char y line.readGChar();
            
signed char item line.readGChar();
            
signed char signindex line.readGChar();

            
levelChests.push_back(new TLevelChest(xyitemsignindex));
        }
    }

    
// Load signs.
    
{
        while (
fileData.bytesLeft())
        {
            
CString line fileData.readString("\n");
            if (
line.length() == 0) break;

            
signed char x line.readGChar();
            
signed char y line.readGChar();
            
CString text line.readString("");

            
levelSigns.push_back(new TLevelSign(xytexttrue));
        }
    }

    return 
true;


I would still like to visually see with a hex editor how this data read/write.

Cubical 07-14-2014 10:29 AM

He is probably talking about the old source code clients that actually used .graal files. They are honestly probably the same as .zelda files so you might me able to look in the old java source code.

Gos_pira 07-14-2014 10:41 AM

I know for a fact that above code works.

scriptless 07-14-2014 06:18 PM

Well, I managed to get the above to work and read a full level of tile data. I didn't use the part to load anything else quite yet. By the looks of this I think its reading 13 bits of data at a time. And the 1st bit would tell it if its repeating or not.. but I may be wrong. It's quite confusing.

Quote:

Originally Posted by Cubical (Post 1728754)
He is probably talking about the old source code clients that actually used .graal files. They are honestly probably the same as .zelda files so you might me able to look in the old java source code.

Actually there appears to be a slight difference. First change being the text for the version is slightly different. I thought I saw 1 other but I can't remember.


All times are GMT +2. The time now is 03:20 AM.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2025, vBulletin Solutions Inc.
Copyright (C) 1998-2019 Toonslab All Rights Reserved.