Fatal error while printing a 2 dimensional array

226 views Asked by At

Im having this problem with a little chunk of code:

for(x = 0; x < 8; x++){
for(y = 0; y < 8; y++){
printf(" %d", occupy[x][y]);
}
printf(" \n");
}

I'm making a randomly generated maze game for the Gameboy, and I'm using a 2d array to know where each screen is in the maze. For testing I'm trying to print that array so I can see if its generating properly before I move on. When I try to compile with that little chunk of code I get an error on the top line of it, then says fatal Compiler internal error in file blah blah blah. Is there like a big no-no in that code that I didn't know of?

Full code:

#include <gb\gb.h>
#include <stdio.h>
#include <rand.h>


#define UP 0x01U
#define RIGHT 0x02U
#define DOWN 0x04U
#define LEFT 0x08U

int occupy[8][8]= {
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0}
};


void generate(){
int temp;
int x;
int y;
UBYTE restrict;
UBYTE direction;
for(x = 0; x < 8; x++){
for(y = 0; y < 8; y++){
occupy[x][y] = 0;
}
}
/* ========Occupy=Cleared========== */
restrict = 0x00U;
x = rand() & 7;
y = rand() & 7;

if(x == 6 || x == 7){ restrict += RIGHT;}
if(x == 0 || x == 1){ restrict += LEFT;}
if(y == 0 || y == 1){ restrict += UP;}
if(y == 6 || y == 7){ restrict += DOWN;}

/* in the rest of generation wrap this block in if(restrict != 0x0FU){ */

do{
temp = rand() & 3;
if(temp == 0){ direction = UP;}
if(temp == 1){ direction = RIGHT;}
if(temp == 2){ direction = DOWN;}
if(temp == 3){ direction = LEFT;}
}while(restrict & direction);


occupy[x][y] = 5;
if(direction == UP){ occupy[x][y-1] = 1;}
if(direction == RIGHT){ occupy[x+1][y] = 2;}
if(direction == DOWN){ occupy[x][y+1] = 3;}
if(direction == LEFT){ occupy[x-1][y] = 4;}

for(x = 0; x < 8; x++){
for(y = 0; y < 8; y++){
printf(" %d", occupy[x][y]);
}
printf(" \n");
}

}


void main(){
generate();

}
2

There are 2 answers

1
Pokechu22 On BEST ANSWER

This compiles under my version of GBDK fine, although I'm not sure why the changes I make are what fixes it.

Changes made:

  • occupy is now an array of unsigned int rather than just int (without this change sdcc crashes)
  • printf call inside of loop was changed from " %d" to " %u" (as the value is unsigned)
  • A printf showing the address of occupy has been added. If I remove it or change it to do something else, sdcc crashes. This is silly, but it seems to be required. I'm looking in to alternatives that don't need a pointless printf.

    • Note that the following can be used instead, which results in nothing being printed (as in it tries to write to address $0000, but that's read only and fails). It's still stupid but doesn't display anything. It might still cause some slowdown though.

      sprintf(0, "", &occupy);
      
  • I also improved indentation.

#include <gb\gb.h>
#include <stdio.h>
#include <rand.h>


#define UP 0x01U
#define RIGHT 0x02U
#define DOWN 0x04U
#define LEFT 0x08U

unsigned int occupy[8][8] = {
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0}
};

void generate(){
    int temp;
    int x;
    int y;
    UBYTE restrict;
    UBYTE direction;

    for(x = 0; x < 8; x++){
        for(y = 0; y < 8; y++){
            occupy[x][y] = 0;
        }
    }
    /* ========Occupy=Cleared========== */
    restrict = 0x00U;
    x = rand() & 7;
    y = rand() & 7;

    if(x == 6 || x == 7){ restrict += RIGHT;}
    if(x == 0 || x == 1){ restrict += LEFT;}
    if(y == 0 || y == 1){ restrict += UP;}
    if(y == 6 || y == 7){ restrict += DOWN;}

    /* in the rest of generation wrap this block in if(restrict != 0x0FU){ */

    do{
        temp = rand() & 3;
        if(temp == 0){ direction = UP;}
        if(temp == 1){ direction = RIGHT;}
        if(temp == 2){ direction = DOWN;}
        if(temp == 3){ direction = LEFT;}
    }while(restrict & direction);


    occupy[x][y] = 5;
    if(direction == UP){ occupy[x][y-1] = 1;}
    if(direction == RIGHT){ occupy[x+1][y] = 2;}
    if(direction == DOWN){ occupy[x][y+1] = 3;}
    if(direction == LEFT){ occupy[x-1][y] = 4;}

    printf(" %x\n", &occupy); //Strangely without this printf it doesn't compile???
    for(x = 0; x < 8; x++){
        for(y = 0; y < 8; y++){
            printf(" %u", occupy[x][y]);
        }
        printf(" \n");
    }

}


void main(){
    generate();
}

Here's a few other comments about the code:

  • You don't ever initialize the RNG, so the results will always be the same. There's a few ways to set the seed. Normally, you do it with time on the title screen, or you can have a seed chooser.

    //Seeds RNG by time taken to press start
    void seedRNG() {
        UINT16 seed = 0;
    
        printf("Press start\n");
        while (!(joypad() & J_START)) {
            seed++;
        }
        initrand(seed);
    }
    
    //Seeds RNG with a user-chosen number.
    //Requires inclusion of <gb\console.h>.
    void seedRNG() {
        UINT16 seed = 0x8000U; //In the middle to prevent over/underflow issues
    
        printf("Seed:");
    
        while (!(joypad() & J_START)) {
            if (joypad() & J_UP) { seed++; }
            if (joypad() & J_DOWN) { seed--; }
            gotoxy(0,1);
            printf("%x\n", seed);
            delay(10);
        }
        initrand(seed);
    }
    
  • You don't actually need to print stuff out to view it in this case, since you can use the "Memory Viewer" found in most emulators. The locations can be found in a RAM map generated with the -Wl-j or -Wl-m options.

  • I recommend using INT16 or WORD rather than int and UINT16 or UWORD rather than unsigned int, ect, as they include the sizes in their names. UBYTE and such are also nice to use.

1
user3629249 On
the following compiles



#include <stdio.h>
#include <stdlib.h> // contains rand and srand function prototypes
#include <time.h>
//#include "gb\gb.h"

void generate( void );

#define UP 0x01U
#define RIGHT 0x02U
#define DOWN 0x04U
#define LEFT 0x08U
typedef unsigned char UBYTE;

int occupy[8][8] =
{
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0}
};

int main()
{
    generate();
    return(0);
}


void generate()
{
    int temp;
    int x;
    int y;
    UBYTE block;
    UBYTE direction;

    for(x = 0; x < 8; x++)
    {
        for(y = 0; y < 8; y++)
        {
            occupy[x][y] = 0;
        }
    }
    /* ========Occupy=Cleared========== */
    block = 0x00U;
    srand(time(NULL) ); // initialize rand()
    x = rand() & 8;
    y = rand() & 8;

    if(x == 6 || x == 7){ block += RIGHT;}
    if(x == 0 || x == 1){ block += LEFT;}
    if(y == 0 || y == 1){ block += UP;}
    if(y == 6 || y == 7){ block += DOWN;}

    /* in the rest of generation wrap this block in if(block != 0x0FU){ */

    // NOTE:
    // in the following while loop if direction is not the same a block
    // then the loop will immediately exit
    // probably not what you want to do.
    do{
        temp = rand() & 4;
        if(temp == 0){ direction = UP;}
        if(temp == 1){ direction = RIGHT;}
        if(temp == 2){ direction = DOWN;}
        if(temp == 3){ direction = LEFT;}
    } while(block & direction);


    // NOTE:
    // in the following code,
    // 'x' and/or 'y' could be 0 or 7
    // in either case, one or more of the following statements
    // can/will cause accessing outside of the bounds
    // of the occupy[][] array
    occupy[x][y] = 5;
    if(direction == UP)   { occupy[x][y-1] = 1;}
    if(direction == RIGHT){ occupy[x+1][y] = 2;}
    if(direction == DOWN) { occupy[x][y+1] = 3;}
    if(direction == LEFT) { occupy[x-1][y] = 4;}

    for(x = 0; x < 8; x++)
    {
        for(y = 0; y < 8; y++)
        {
            printf(" %d", occupy[x][y]);
        }
        printf(" \n");
    }
}