/* life.c - demonstrator for later Mips+LCD game of life * * 23.03.06 - MACRO-based version * 22.02.06 - new file */ //#include "ks0108.h" #include #include #include #include "system.h" extern uint64_t *pPixelBuf; extern uint32_t screen_nx; extern uint32_t screen_ny; #define NX (screen_nx/4) // 70 // 128 // 48 // 128 #define NY (3*NX/4) // 31 // 64 // 27 // 64 #define SCREEN_X screen_nx #define SCREEN_Y screen_ny #define SCALE_X (2) #define SCALE_Y (2) #define OFFSET_X ((SCREEN_X-(SCALE_X*NX))/1) #define OFFSET_Y ((SCREEN_Y-(SCALE_Y*NY))/1) // OCCUPIED must be uneven, EMPTY even. #define OCCUPIED 0x77771111 #define EMPTY 0xeeee0000 #define MATRIX( row, col ) (*(matrix + (NX*col) + row )) #define FUTURE( row, col ) (*(future + (NX*col) + row )) static uint32_t *g_gx_buff; int clock_lfsr32() { return rand(); } /* return a pseudo-random integer in the range 0..1023 */ int random1023() { int tmp; tmp = clock_lfsr32(); return tmp & 0x000003ff; } typedef struct _scolor_t { uint8_t r, g, b, a; } __attribute__ ((__packed__)) color_t; void DrawPixel(uint32_t x, uint32_t y, color_t *pColor) { int i, j; for (i=0; i < SCALE_Y; i++) for (j=0; j < SCALE_X; j++) g_gx_buff[(OFFSET_X+SCALE_X*x+j) + SCREEN_X*(OFFSET_Y+SCALE_Y*y+i)] = *((uint32_t*)pColor); } /* MSB/LSB in y-Richtung vertauscht */ void displayBoard1( int* matrix ) { int x, y; int mask, accu; uint32_t color; for( x=0; x < NX; x++ ) { mask = 0x80; accu = 0x00; for( y=0; y < NY; y++ ) { color = (uint32_t)-(MATRIX(x,y) & 0x1); DrawPixel(x, y, (color_t*)&color); // if (MATRIX( x, y ) != OCCUPIED) // { // accu |= mask; // } // mask = mask >> 1; // color = 0; // DrawPixel(x, (y>>3), (color_t*)&color); // if (mask == 0) // { // color = accu; // DrawPixel(x, (y>>3), (color_t*)&color); // mask = 0x80; // accu = 0x00; // } } // color = accu; // DrawPixel(x, (y>>3), (color_t*)&color); } // *(matrix-15) = 0xdead0000; // *(matrix-16) = *(matrix-16) + 1; } void initializeBoard( int* matrix ) { int x, y; for( x=0; x < NX; x++ ) { for( y=0; y < NY; y++ ) { int d = random1023(); if (d > 920) MATRIX( x, y ) = OCCUPIED; else MATRIX( x, y ) = EMPTY; } } } int countNeighbors( int* matrix, int i, int j ) { int im = i-1; int ip = i+1; int jm = j-1; int jp = j+1; int n = 0; // wrap-around if (ip >= NX) ip = 0; if (jp >= NY) jp = 0; if (im < 0) im = NX-1; if (jm < 0) jm = NY-1; // check eight neighbors n += MATRIX(im, jm ) & 0x1; // nw n += MATRIX(im, j ) & 0x1; // west n += MATRIX(im, jp ) & 0x1; // sw n += MATRIX(i, jm ) & 0x1; // north // n += MATRIX(i, j ) & 0x1; // center n += MATRIX(i, jp ) & 0x1; // south n += MATRIX(ip, jm ) & 0x1; // ne n += MATRIX(ip, j ) & 0x1; // east n += MATRIX(ip, jp ) & 0x1; // se return n; } /** * the actual game of life algorithm: cell is born when three neighbors, * survives when exactly two live neighbors, dies otherwise. */ void nextGeneration( int* matrix, int* future ) { int i, j; int lifes = 0; for( i=0; i < NX; i++ ) { for( j=0; j < NY; j++ ) { // count neighbors int n = countNeighbors( matrix, i, j ); //if ((n != 0) && (random1023() > 990)) { // some slight random offset // if (random1023() > 500) FUTURE(i,j) = OCCUPIED; // else FUTURE(i,j) = EMPTY; //} // else if (n == 3) FUTURE(i,j) = OCCUPIED; if (n == 3) FUTURE(i,j) = OCCUPIED; else if ((n == 2) && (MATRIX(i,j) == OCCUPIED)) FUTURE(i,j) = OCCUPIED; else FUTURE(i,j) = EMPTY; if (FUTURE(i,j) == OCCUPIED) lifes++; } } // generation ++; // avoid extinction :-) if (lifes < 10) { // printf( "CREATING A NEW POPULATION\n\n\n" ); initializeBoard( matrix ); } else { // swap buffers: C PROHIBITS ASSIGNING TO ARRAY TYPES for( i=0; i < NX; i++ ) { for( j=0; j < NY; j++ ) { MATRIX(i,j) = FUTURE(i,j); } } } } void life(uint32_t seed) { int matrix[320*240]; int future[320*240]; g_gx_buff = (uint32_t*)pPixelBuf; srand(seed); initializeBoard( matrix ); while( 1 ) { displayBoard1( matrix ); nextGeneration( matrix, future ); rtems_task_wake_after(50); } }