213 lines
4.6 KiB
C
213 lines
4.6 KiB
C
/* 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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#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);
|
|
}
|
|
|
|
}
|