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();
}
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.