484 lines
9.6 KiB
C++
484 lines
9.6 KiB
C++
|
|
// ****************************************************************************
|
|
//
|
|
// Main code
|
|
//
|
|
// ****************************************************************************
|
|
|
|
#include "main.h"
|
|
#include "pico/printf.h"
|
|
#include <string.h>
|
|
|
|
// copy of tiles images
|
|
u8 TilesImg_Copy[sizeof(Tiles16Img)] __attribute__ ((aligned(4)));
|
|
|
|
// game board
|
|
u8 Board[MAPSIZE];
|
|
|
|
// neighbors
|
|
u8 Neigh[MAPSIZE];
|
|
|
|
// slots
|
|
u8 Slot[MAPSIZE*SLOTNUM];
|
|
int SelSlot;
|
|
|
|
// clipboard
|
|
u8 Clip[MAPSIZE];
|
|
|
|
// cursor
|
|
int CurX, CurY;
|
|
|
|
// samples (first 2 bytes = width, height)
|
|
const u8 Samples[] = {
|
|
|
|
// 0: Life
|
|
5,5,
|
|
1,1,1,1,1,
|
|
1,1,1,1,1,
|
|
1,1,1,1,1,
|
|
1,1,1,1,1,
|
|
1,1,1,1,1,
|
|
|
|
// 1: penta-decathlon
|
|
3,12,
|
|
1,1,1,
|
|
0,1,0,
|
|
0,1,0,
|
|
1,1,1,
|
|
0,0,0,
|
|
1,1,1,
|
|
1,1,1,
|
|
0,0,0,
|
|
1,1,1,
|
|
0,1,0,
|
|
0,1,0,
|
|
1,1,1,
|
|
|
|
// 2: R-pentomino
|
|
3,3,
|
|
0,1,1,
|
|
1,1,0,
|
|
0,1,0,
|
|
|
|
// 3: Diehard
|
|
8,3,
|
|
0,0,0,0,0,0,1,0,
|
|
1,1,0,0,0,0,0,0,
|
|
0,1,0,0,0,1,1,1,
|
|
|
|
// 4. Acorn
|
|
7,3,
|
|
0,1,0,0,0,0,0,
|
|
0,0,0,1,0,0,0,
|
|
1,1,0,0,1,1,1,
|
|
|
|
// 5: Glider
|
|
3,3,
|
|
0,0,1,
|
|
1,0,1,
|
|
0,1,1,
|
|
|
|
// 6: spaceship
|
|
5,4,
|
|
1,0,0,1,0,
|
|
0,0,0,0,1,
|
|
1,0,0,0,1,
|
|
0,1,1,1,1,
|
|
|
|
// 7: pulsar
|
|
15,15,
|
|
0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,
|
|
0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,
|
|
0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
1,1,1,0,0,1,1,0,1,1,0,0,1,1,1,
|
|
0,0,1,0,1,0,1,0,1,0,1,0,1,0,0,
|
|
0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,
|
|
0,0,1,0,1,0,1,0,1,0,1,0,1,0,0,
|
|
1,1,1,0,0,1,1,0,1,1,0,0,1,1,1,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,
|
|
0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,
|
|
0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,
|
|
|
|
// 8: Gosper glider gun
|
|
38, 9,
|
|
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,1,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,1,0,1,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,1,1,0,0,0,0,0, 0,1,1,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,1,0,0,0,1,0,0,0, 0,1,1,0,0,0,0,0,0,0, 0,0,0,0,0,1,1,0,
|
|
0,1,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,1,0,0, 0,1,1,0,0,0,0,0,0,0, 0,0,0,0,0,1,1,0,
|
|
0,1,1,0,0,0,0,0,0,0, 0,1,0,0,0,1,0,1,1,0, 0,0,0,1,0,1,0,0,0,0, 0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,1,0,0, 0,0,0,0,0,1,0,0,0,0, 0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0, 0,0,1,0,0,0,1,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,1,1,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
|
|
|
// 9: Simkin glider gun
|
|
33,21,
|
|
1,1,0,0,0,0,0,1,1,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,
|
|
1,1,0,0,0,0,0,1,1,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,1,1,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,1,1,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,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,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,1,1,0,1,1,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,1,0,0,0,0,0,1,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,1,0,0,0,0,0,0,1,0, 0,1,1,
|
|
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,1,1,1,0,0,0,1,0,0, 0,1,1,
|
|
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,1,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,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, 1,1,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, 1,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,1,1,1,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,1,0,0,0,0,0,0, 0,0,0,
|
|
};
|
|
|
|
/*
|
|
// initialize videomode
|
|
void VideoInit()
|
|
{
|
|
// setup videomode
|
|
VgaCfgDef(&Cfg); // get default configuration
|
|
Cfg.video = &DRV; // video timings
|
|
Cfg.width = WIDTH; // screen width
|
|
Cfg.height = HEIGHT; // screen height
|
|
VgaCfg(&Cfg, &Vmode); // calculate videomode setup
|
|
|
|
// initialize base layer 0 to tiles
|
|
ScreenClear(pScreen);
|
|
sStrip* t = ScreenAddStrip(pScreen, HEIGHT);
|
|
sSegm* g = ScreenAddSegm(t, WIDTH);
|
|
ScreenSegmTile2(g, Board, TilesImg_Copy, TILESIZE, TILESIZE, TILESIZE*TILE_NUM, MAPW);
|
|
|
|
// initialize system clock
|
|
set_sys_clock_pll(Vmode.vco*1000, Vmode.pd1, Vmode.pd2);
|
|
|
|
// initialize videomode
|
|
VgaInitReq(&Vmode);
|
|
}
|
|
*/
|
|
|
|
// display help
|
|
void DispHelp()
|
|
{
|
|
printf("\n");
|
|
printf("%c ... right\n", KEY_R);
|
|
printf("%c ... up\n", KEY_U);
|
|
printf("%c ... left\n", KEY_L);
|
|
printf("%c ... down\n", KEY_D);
|
|
printf("space ... flip state\n");
|
|
printf("Enter .. run life\n");
|
|
printf("0..9 ... select slot\n");
|
|
printf("%c ... copy to clipboard\n", KEY_COPY);
|
|
printf("%c ... paste from clipboard\n", KEY_PASTE);
|
|
printf("%c ... clear board\n", KEY_CLEAR);
|
|
printf("Selected slot: %u\n", SelSlot);
|
|
printf("Rules: 3->new, 2->stable, other->dead\n");
|
|
}
|
|
|
|
// get character from keyboard (0 = no key)
|
|
char GetChar()
|
|
{
|
|
char c = getchar_timeout_us(0);
|
|
if (c == (char)PICO_ERROR_TIMEOUT) c = 0;
|
|
if ((c >= 'a') && (c <= 'z')) c -= 32;
|
|
return c;
|
|
}
|
|
|
|
// flush characters from keyboard
|
|
void FlushChar()
|
|
{
|
|
while (GetChar() != 0) {}
|
|
}
|
|
|
|
// set cursor on
|
|
void CurOn()
|
|
{
|
|
u8* d = &Board[CurX + CurY*MAPW];
|
|
u8 b = *d;
|
|
if (b == TILE_FULL)
|
|
b = TILE_SELFULL;
|
|
else if (b == TILE_EMPTY)
|
|
b = TILE_SELEMPTY;
|
|
*d = b;
|
|
}
|
|
|
|
// set cursor off
|
|
void CurOff()
|
|
{
|
|
u8* d = &Board[CurX + CurY*MAPW];
|
|
u8 b = *d;
|
|
if (b == TILE_SELFULL)
|
|
b = TILE_FULL;
|
|
else if (b == TILE_SELEMPTY)
|
|
b = TILE_EMPTY;
|
|
*d = b;
|
|
}
|
|
|
|
// flip cursor
|
|
void CurFlip()
|
|
{
|
|
u8* d = &Board[CurX + CurY*MAPW];
|
|
u8 b = *d;
|
|
if (b == TILE_SELFULL)
|
|
b = TILE_SELEMPTY;
|
|
else if (b == TILE_SELEMPTY)
|
|
b = TILE_SELFULL;
|
|
*d = b;
|
|
}
|
|
|
|
// get cell on coordinates (0 or 1)
|
|
int Cell(int x, int y)
|
|
{
|
|
if ((x < 0) || (x >= MAPW) || (y < 0) || (y >= MAPH)) return 0;
|
|
u8* d = &Board[x + y*MAPW];
|
|
u8 b = *d;
|
|
return (b == TILE_FULL) ? 1 : 0;
|
|
}
|
|
|
|
// save to current slot
|
|
void SaveSlot()
|
|
{
|
|
memcpy(&Slot[MAPSIZE*SelSlot], Board, MAPSIZE);
|
|
}
|
|
|
|
// load from current slot
|
|
void LoadSlot()
|
|
{
|
|
memcpy(Board, &Slot[MAPSIZE*SelSlot], MAPSIZE);
|
|
}
|
|
|
|
// run life
|
|
void Run()
|
|
{
|
|
int x, y;
|
|
u8 b;
|
|
u8* d;
|
|
u8* s;
|
|
|
|
FlushChar();
|
|
|
|
// break with a key
|
|
while (GetChar() == 0)
|
|
{
|
|
// calculate neighbors
|
|
d = Neigh;
|
|
for (y = 0; y < MAPH; y++)
|
|
{
|
|
for (x = 0; x < MAPW; x++)
|
|
{
|
|
*d++ = Cell(x-1, y-1) +
|
|
Cell(x , y-1) +
|
|
Cell(x+1, y-1) +
|
|
|
|
Cell(x-1, y ) +
|
|
Cell(x+1, y ) +
|
|
|
|
Cell(x-1, y+1) +
|
|
Cell(x , y+1) +
|
|
Cell(x+1, y+1);
|
|
}
|
|
}
|
|
|
|
// update cells
|
|
s = Neigh;
|
|
d = Board;
|
|
for (x = MAPSIZE; x > 0; x--)
|
|
{
|
|
b = *s++;
|
|
|
|
// 3 -> new cell
|
|
if (b == 3)
|
|
*d = TILE_FULL;
|
|
|
|
// 2 -> unchanged
|
|
else if (b == 2)
|
|
;
|
|
// else -> dead
|
|
else
|
|
*d = TILE_EMPTY;
|
|
d++;
|
|
}
|
|
|
|
// delay
|
|
sleep_ms(SPEED);
|
|
}
|
|
}
|
|
|
|
// initialize slots by samples
|
|
void InitSlot()
|
|
{
|
|
int slot;
|
|
u8* d;
|
|
const u8* s = Samples;
|
|
int w, h;
|
|
for (slot = 0; slot < SLOTNUM; slot++)
|
|
{
|
|
// destination slot
|
|
d = &Slot[MAPSIZE*slot];
|
|
|
|
// sample dimension
|
|
w = *s++;
|
|
h = *s++;
|
|
|
|
// center image
|
|
d += (MAPW-w)/2 + (MAPH-h)/2*MAPW;
|
|
|
|
// copy sample
|
|
for (; h > 0; h--)
|
|
{
|
|
memcpy(d, s, w);
|
|
d += MAPW;
|
|
s += w;
|
|
}
|
|
}
|
|
}
|
|
|
|
int main()
|
|
{
|
|
// initialize stdio
|
|
stdio_init_all();
|
|
|
|
char ch;
|
|
|
|
// copy tiles images to RAM buffer (flash would be too slow)
|
|
memcpy(TilesImg_Copy, Tiles16Img, sizeof(Tiles16Img));
|
|
|
|
// clear buffer
|
|
memset(Board, TILE_EMPTY, MAPSIZE);
|
|
memset(Slot, TILE_EMPTY, MAPSIZE*SLOTNUM);
|
|
memset(Clip, TILE_EMPTY, MAPSIZE);
|
|
CurX = MAPW/2;
|
|
CurY = MAPH/2;
|
|
SelSlot = 1;
|
|
|
|
// fill slots with samples
|
|
InitSlot();
|
|
|
|
// load current slot
|
|
LoadSlot();
|
|
|
|
// run VGA core
|
|
// StartVgaCore();
|
|
|
|
// initialize videomode
|
|
// VideoInit();
|
|
Video(DEV_VGA, RES_VGA, FORM_TILE16, Board, TilesImg_Copy);
|
|
|
|
// display help
|
|
DispHelp();
|
|
|
|
// set cursor on
|
|
CurOn();
|
|
|
|
// loop with demo scene
|
|
while (True)
|
|
{
|
|
// keyboard
|
|
ch = GetChar();
|
|
if (ch != 0)
|
|
{
|
|
switch (ch)
|
|
{
|
|
// right
|
|
case KEY_R:
|
|
CurOff(); // set cursor off
|
|
CurX++;
|
|
if (CurX >= MAPW) CurX = 0;
|
|
CurOn(); // set cursor on
|
|
break;
|
|
|
|
// left
|
|
case KEY_L:
|
|
CurOff(); // set cursor off
|
|
CurX--;
|
|
if (CurX < 0) CurX = MAPW-1;
|
|
CurOn(); // set cursor on
|
|
break;
|
|
|
|
// down
|
|
case KEY_D:
|
|
CurOff(); // set cursor off
|
|
CurY++;
|
|
if (CurY >= MAPH) CurY = 0;
|
|
CurOn(); // set cursor on
|
|
break;
|
|
|
|
// up
|
|
case KEY_U:
|
|
CurOff(); // set cursor off
|
|
CurY--;
|
|
if (CurY < 0) CurY = MAPH-1;
|
|
CurOn(); // set cursor on
|
|
break;
|
|
|
|
// toggle
|
|
case ' ':
|
|
CurFlip(); // flip cursor
|
|
break;
|
|
|
|
// run
|
|
case 13:
|
|
CurOff(); // set cursor off
|
|
SaveSlot(); // save state
|
|
Run(); // run life
|
|
LoadSlot(); // restore state
|
|
CurOn(); // set cursor on
|
|
break;
|
|
|
|
// select slot
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
CurOff(); // set cursor off
|
|
SaveSlot();
|
|
SelSlot = ch - '0';
|
|
LoadSlot();
|
|
CurOn(); // set cursor on
|
|
printf("Selected slot: %u\n", SelSlot);
|
|
break;
|
|
|
|
// copy to clipboard
|
|
case KEY_COPY:
|
|
CurOff(); // set cursor off
|
|
memcpy(Clip, Board, MAPSIZE);
|
|
CurOn(); // set cursor on
|
|
break;
|
|
|
|
// paste from clipboard
|
|
case KEY_PASTE:
|
|
CurOff(); // set cursor off
|
|
memcpy(Board, Clip, MAPSIZE);
|
|
CurOn(); // set cursor on
|
|
break;
|
|
|
|
// clear board
|
|
case KEY_CLEAR:
|
|
CurOff(); // set cursor off
|
|
memset(Board, TILE_EMPTY, MAPSIZE);
|
|
CurOn(); // set cursor on
|
|
break;
|
|
|
|
// help
|
|
default:
|
|
DispHelp();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|