Problem with my file opener

This is a discussion on Problem with my file opener within the C Programming forums, part of the General Programming Boards category; I have some code to load map files into memory. It was working fine for a simple map I made, ...

  1. #1
    Registered User
    Join Date
    May 2004
    Posts
    114

    Unhappy Problem with my file opener

    I have some code to load map files into memory. It was working fine for a simple map I made, but when I tried loading a larger more complicated one it crashed. Now I have been looking at it for ages to fix the problem and haven't managed to solve it.

    The structure of the map file is like this:

    map header
    board header
    tiles
    board information
    objects
    next board header and so on..

    I have narrowed down what is going wrong. The first board is loading fine, the tiles look fine etc. The second board starts off well, the board title (in the board header) is correct, but then there are some tiles missing which then messes everything else up.

    Now as the board title on the second board loads ok, it surely meens that everything before that has been read correctly. In other words it meens that the second board is not loading right even though it is being given the right place in the file! So I think the reading of the board header the second time around is going wrong but I can't see how.

    Its probably going to be impossible for anyone here to actualy solve my problem because you would have to learn how the zzt files work and stuff but what I could use is suggestions about what to do / check next because I am totaly stuck!

    Anyway I might as well paste the relevent code in incase I have written somthing in a bad way that could cause an intermitant problem.

    Thanks

    Code:
    bool load_world(char *file_name)
    {
        FILE *file_pointer;
        char buffer[512];
        int i, title_length;
    
        file_pointer = fopen(file_name, "rb");
        if (file_pointer == NULL)
        {
            perror("FAILED opening world file");
            system("PAUSE");
            return false;
        }
        else
            perror("Opened world file");
    
        for (i = 0; i < 512; i++)
            buffer[i] = getc(file_pointer);
    
        /* Get the World Header stuff */
        world.board_count = (unsigned short)buffer[2] + buffer[3] * 256;
        world.board_count ++;
        world.start_ammo = (unsigned short)buffer[4] + buffer[5] * 256;
        world.start_gems = (unsigned short)buffer[6] + buffer[7] * 256;
        world.blue_key = buffer[8];
        world.green_key = buffer[9];
        world.cyan_key = buffer[10];
        world.red_key = buffer[11];
        world.purple_key = buffer[12];
        world.yellow_key = buffer[13];
        world.white_key = buffer[14];
        world.start_health = (unsigned short)buffer[15] + buffer[16] * 256;
        world.start_board = (unsigned short)buffer[17] + buffer[18] * 256;
        world.start_torches = (unsigned short)buffer[19] + buffer[20] * 256;
        world.torch_cycles_left = (unsigned short)buffer[21] + buffer[22] * 256;
        world.energiser_cycles_left = (unsigned short)buffer[23] + buffer[24] * 256;
        world.start_score = (unsigned short)buffer[27] + buffer[28] * 256;
    
        /* Get the title of the world */
        title_length = buffer[29];
        world.title = malloc(title_length + 1);
        for (i = 0; i < title_length; i++)
            world.title[i] = buffer[30 + i];
        world.title[i] = '\0';
    
        /* Is the world file a saved game? */
        world.saved_game = buffer[264];
    
        /* Load the boards */
        world.board = malloc( sizeof(struct Sboard) * world.board_count);
        
        for (i = 0; i < world.board_count; i++)
            load_board(file_pointer, &world.board[i]);
    
        /* Close the file and return */
        fclose(file_pointer);
    
        return true;
    }
    
    void load_board(FILE *file_pointer, struct Sboard *board)
    {
        char *buffer;
        unsigned char title_length;
        int i, board_size, message_length;
        int current_tile = 0;
    
        /* Read the board header into the buffer */
        buffer = malloc(53);
    
        for (i = 0; i < 53; i++)
            buffer[i] = getc(file_pointer);
    
        /* Get the board size */
        board_size = (unsigned short)buffer[0] + buffer[1] * 256;
    
        /* Get the title */
        title_length = buffer[2];
    
        board->title = malloc(title_length + 1);
        for (i = 0; i < title_length; i++)
            board->title[i] = buffer[3 + i];
        board->title[i] = '\0';
    
        free(buffer);
    
        /* Get all the tiles put into the board.tile array */
        buffer = malloc(3);
        
        printw("current tile: %d\n", current_tile);
        
        while (current_tile < 1500)
        {
            for (i = 0; i < 3; i++)
                buffer[i] = getc(file_pointer);
    
            for (i = 0; i <= buffer[0]; i++)
            {
                board->tile[current_tile + i].code = buffer[1];
                board->tile[current_tile + i].colour = buffer[2];
            }
            
            current_tile += buffer[0];
            for (i = 0; i < current_tile; i++)
                draw_zzt_char(i % 60, i / 60, board->tile[i].code, board->tile[i].colour);
                printw("board title: %s\n", board->title);
            getch();
            clear();
        }
        
        free(buffer);
        
        /* Get the board information */
        buffer = malloc(88);
        
        for (i = 0; i < 88; i++)
            buffer[i] = getc(file_pointer);
        
        board->maximum_shots_fired = buffer[0];
        board->dark = buffer[1];
        board->board_north = buffer[2];
        board->board_south = buffer[3];
        board->board_west = buffer[4];
        board->board_east = buffer[5];
        board->teleport_when_hurt = buffer[6];
    
        message_length = buffer[7];
            board->message = malloc(message_length + 1);
        for (i = 0; i < message_length; i++)
            board->message[i] = buffer[8 + i];
        board->message[i] = '\0';
        
        board->time_limit = (unsigned short)buffer[68] + buffer[69] * 256;
        board->object_count = (unsigned short)buffer[86] + buffer[87] * 256;
        board->object_count ++;
        
        printw("board title: %s\n", board->title);
        printw("Object Count: %d\n", board->object_count);
        printw("Object Count: %d\n", (unsigned short)buffer[86+10] + buffer[87+10] * 256);
        printw("Dark?: %d\n", buffer[1+10]);
        
        free(buffer);
        
    
        refresh();    
        getch();
        clear();
        
        /* Load all of the objects */
        board->object = malloc(board->object_count);
        
        for (i = 0; i < board->object_count; i++)
            load_object(file_pointer, &board->object[i]);
    }
    
    void load_object(FILE *file_pointer, struct Sobject *object)
    {
        int i, code_length;
        char *buffer;
        
        /* Load the object's information */
        buffer = malloc(33);
        
        for (i = 0; i < 33; i++)
            buffer[i] = getc(file_pointer);
        
        object->x_pos = buffer[0] - 1;
        object->y_pos = buffer[1] - 1;
        object->x_step = (unsigned short)buffer[2] + buffer[3] * 256;
        object->y_step = (unsigned short)buffer[4] + buffer[5] * 256;
        object->cycle_speed = (unsigned short)buffer[6] + buffer[7] * 256;
        object->parameter1 = buffer[8];
        object->parameter2 = buffer[9];
        object->parameter3 = buffer[10];
        object->below_tile_code = buffer[15];
        object->below_tile_colour = buffer[16];
        object->cursor_instruction = (unsigned short)buffer[21]  + buffer[22] * 256;
        code_length = (unsigned short)buffer[23] + buffer[24] * 256;
        
        /* Load the object's code if it has some */
        if (code_length > 0)
        {
            object->code = malloc(code_length + 1);
            for (i = 0; i < code_length; i++)
                object->code[i] = getc(file_pointer);
                
            object->code[i] = '\0'; 
        }    
        
        free(buffer); 
    }
    Last edited by kzar; 04-17-2005 at 01:51 PM.

  2. #2
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,590
    Can you zip/attach a ZZT file which causes it to crash?

    Also, add the structures you're using (the typedefs), or ideally, a stripped down program which demonstrate the problem.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  3. #3
    Registered User
    Join Date
    May 2004
    Posts
    114
    Sure thing Here . It is the CITY.ZZT file it is using, the BOB.ZZT file loads fine. I have stuck a load of prints in there that gives some nice feedback for the time being, so you should be able to see what is going on. Thanks

  4. #4
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,164
    Hmm, are you paying attention to Order Of Operations? For instance, this line:
    Code:
    object->x_step = (unsigned short)buffer[2] + buffer[3] * 256;
    ...multiplies buffer[3] by 256 and then adds buffer[2] to the result. Is that what you intended? I think getting the details on the ZZT file format would help me figure this out a lot better. For instance, what's at the first 2 bytes of the file? I notice that it's just 0xFFFF. Is it just a magic number for sanity?
    If you understand what you're doing, you're not learning anything.

  5. #5
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,164
    One little tangent here...I noticed that in one of your structs you have a whole series of bools that keeps track of different keys...something like bool green_key; bool yellow_key;, etc...

    You might want to look at some sort of "flags" implementation there. Right now, if you added a key to your game you'd have to change the whole database format to make room for it. You could do something like this instead:
    Code:
    #define YELLOW_KEY 1
    #define BLUE_KEY     2
    #define PURPLE_KEY 4
    #define ORANGE_KEY 8
    #define GREEN_KEY  16
    
    unsigned int keys = 0;
    Now each key represents a single bit in the keys variable. So to remember that a player has the green key for instance, you could do:
    Code:
    keys |= GREEN_KEY;
    And to check if the player has the geen key you'd do something like:
    Code:
    if(keys & GREEN_KEY)
    Or say they drop the green key:
    Code:
    keys &= ~GREEN_KEY;
    That way you only have to write 1 int to the database to keep track of all the keys and you can easily add a new one.
    If you understand what you're doing, you're not learning anything.

  6. #6
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    > board->object = malloc(board->object_count);
    Are you sure this is right? I'm guessing it should be:
    board->object = malloc(sizeof(struct Sobject) * board->object_count);

  7. #7
    Registered User
    Join Date
    May 2004
    Posts
    114
    Quote Originally Posted by swoopy
    > board->object = malloc(board->object_count);
    Are you sure this is right? I'm guessing it should be:
    board->object = malloc(sizeof(struct Sobject) * board->object_count);
    Wooops! good point, changed that now. The funny thing is it doesn't seem to have made a difference but I don't understand why that didn't cause it to crash or somthing.

    Quote Originally Posted by itsme86
    > .... That way you only have to write 1 int to the database to keep track of all the keys and you can easily add a new one.
    I will definately try this out once I have got the basic stuff working.

    Quote Originally Posted by itsme86
    > I think getting the details on the ZZT file format would help me figure this out a lot better.
    Here is the file format document and here is someone else's zzt clone's CVS. (The bm.cpp and bm.hpp are the relevant ones.) I think that the specification is wrong about the Board Header, it says the Title string space is 33 but the example program leaves a 34 long space!

    Thanks for the suggestions

    Edit: I have re-uploaded the zip file. It has that malloc bug fixed and it now displays the board as well as all the information. Its quite interesting because it shows how the second board is missing some tiles to start with. I don't know whats causing it but because of the way the file format works the loop will carry on trying to read tiles untill it has enough which is probably why everything after the tiles is totaly buggered.

    Now the board information seems fine, and the tiles start off buggered so somthing in between them is messing up. The really weird thing is that there isnt anything between them, so I don't have a clue what I have done wrong!

    Edit 2: I had an idea how to check that the second board was definately missing tiles to start with. I edited the second board to make all the tiles are the same. This means that the whole board's tiles is all in 3 bytes and if some extra had been read from the file, the 3 bytes would be lost and the tiles wouldn't get read at all. When I tried it did loose the tiles which meens somthing before the tiles is definately reading too much.
    Last edited by kzar; 04-19-2005 at 10:26 AM.

  8. #8
    Registered User
    Join Date
    May 2004
    Posts
    114
    HURAY , I BLODY FIXED IT AFTER 3 DAYS! The problem was that I had not used unsigned char's for my buffer's and of course if they where too large they flipped to negative and messed everything up. Huzah

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Can we have vector of vector?
    By ketu1 in forum C++ Programming
    Replies: 24
    Last Post: 01-03-2008, 04:02 AM
  2. gcc link external library
    By spank in forum C Programming
    Replies: 6
    Last Post: 08-08-2007, 03:44 PM
  3. File I/O problem
    By 81N4RY_DR460N in forum C++ Programming
    Replies: 12
    Last Post: 09-03-2005, 12:14 PM
  4. Encryption program
    By zeiffelz in forum C Programming
    Replies: 1
    Last Post: 06-15-2005, 03:39 AM
  5. Rename file problem
    By Emporio in forum C Programming
    Replies: 2
    Last Post: 06-05-2002, 09:36 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21