#include #include #include #include "piece.h" #include "sintable.h" #define FRAMERATE 50 #define MAX_GRAIN 500 const unsigned char MATSUMI[] = { // 80, 77, 66, 80, 180, 0, 0, 0, 1, 0, 128, 0, 10, 0, 223, 119, // 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 56, 68, 10, 4, 80, 129, 202, 0, 0, 0, 0, 0, 8, 0, 8, 34, 73, 255, 127, 223, 241, 241, 95, 0, 0, 0, 0, 0, 8, 0, 0, 71, 72, 254, 10, 5, 67, 17, 68, 0, 1, 2, 59, 187, 137, 75, 136, 66, 164, 16, 81, 31, 84, 225, 155, 0, 2, 25, 10, 168, 138, 74, 72, 135, 33, 255, 49, 5, 97, 177, 78, 0, 2, 33, 58, 171, 142, 74, 72, 134, 32, 16, 23, 215, 86, 77, 117, 0, 2, 33, 34, 170, 9, 74, 73, 2, 73, 255, 49, 21, 176, 33, 78, 0, 1, 26, 59, 187, 137, 50, 73, 2, 76, 40, 81, 28, 0, 193, 181, 0, 0, 0, 0, 0, 0, 0, 0, 2, 245, 199, 23, 211, 240, 33, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; typedef struct { short x, y; } SVECTOR; typedef struct { long x, y; } VECTOR; typedef struct tagGRAIN { struct tagGRAIN *next; struct tagGRAIN *prev; SVECTOR s, v; short pos; unsigned char color; } GRAIN; GRAIN *grainUseLink, *grainFreeLink; unsigned char vbuff[128 * 88]; unsigned char vbuff2[128 * 128]; GRAIN grain[MAX_GRAIN]; GRAIN *v2g[128 * 128]; SVECTOR box; VECTOR mPos, mSpeed; int mR; int nGrain; int time = FRAMERATE * 60, score = 0, height = 0, dispscore = 0; int hiScore[2] = {0, 0}; int dispPos, upperLine, rollCount; void spout(int t, int x, int y); void sweep(unsigned char c1, unsigned char c2); void initGrain(void); GRAIN *allocGrain(void); GRAIN *freeGrain(GRAIN *current); void pceAppInit(void) { pceLCDDispStop(); pceLCDSetBuffer(vbuff); pceAppSetProcPeriod(1000 / FRAMERATE); memset(vbuff, 0, 128 * 88); pceLCDDispStart(); pceCPUSetSpeed(CPU_SPEED_NORMAL); { FILEACC fa; if(!pceFileOpen(&fa, "spout.sco", FOMD_RD)) { pceFileReadSct(&fa, (void *)hiScore, 0, 8); pceFileClose(&fa); } } pcePadSetTrigMode(PP_MODE_SINGLE); srand(pceTimerGetCount()); } void pceAppProc(int cnt) { static int gamePhase = 0, gameover; int pad = pcePadGet(); if( (pad & (PAD_C | TRG_D)) == (PAD_C | TRG_D) || (pad & (TRG_C | PAD_D)) == (TRG_C | PAD_D)) { if(gamePhase >= 2) { gamePhase = 0; } else { pceAppReqExit(0); } pad = 0; } if(gamePhase == 4) { if(pad & (TRG_C)) { gamePhase = 3; } return; } if(!(gamePhase & 1)) { if(gamePhase == 0) { if(score > hiScore[0] || (score == hiScore[0] && height > hiScore[1])) { FILEACC fa; hiScore[0] = score; hiScore[1] = height; if(!pceFileOpen(&fa, "spout.sco", FOMD_WR)) { pceFileWriteSct(&fa, (void *)hiScore, 0, 8); } else if(!pceFileCreate("spout.sco", 8)) { if(!pceFileOpen(&fa, "spout.sco", FOMD_WR)) { pceFileWriteSct(&fa, (void *)hiScore, 0, 8); } } pceFileClose(&fa); } } else { score = 0; dispscore = 0; height = - 58; time = 60 * FRAMERATE; } { int i; for(i = 0; i < 128 * 128; i ++) { v2g[i] = NULL; } initGrain(); nGrain = 0; } if(gamePhase & 2) { memset(vbuff2, 0xd2, 128 * 128); memset(vbuff2 + 128 * 0, 0, 128 * 78); memset(vbuff2 + 128 * (128 - 32), 0, 128 * 32); } else { memset(vbuff2, 0, 128 * 128); } memset(vbuff, 0, 128 * 88); { int i; unsigned char *pC; pC = vbuff2; for(i = 0; i < 128; i ++) { *pC++ = 0x0b; *pC++ = 0x0b; *pC++ = 0x0b; *pC++ = 0x0b; pC += 128 - 8; *pC++ = 0x0b; *pC++ = 0x0b; *pC++ = 0x0b; *pC++ = 0x0b; } } mPos.x = 40 * 256; mPos.y = 0 * 256; mSpeed.x = 0; mSpeed.y = 0; mR = 256 + (gamePhase & 2) * 224; dispPos = 0; upperLine = 0; gameover = 0; rollCount = 0; gamePhase ++; memset(vbuff + 128, 0x03, 128); pceFontSetType(2 + 128); pceFontSetPos(0, 82); if(height > 0) { pceFontPrintf("time:%2d height:%4d score:%6d", (time + FRAMERATE - 1) / FRAMERATE, height % 10000, score % 1000000); } else { pceFontPrintf("time:%2d height: 0 score:%6d", (time + FRAMERATE - 1) / FRAMERATE, score % 1000000); } pceFontSetType(0); } if((pad & TRG_C) && gamePhase == 3 && gameover == 0) { pceFontSetType(2 + 128); pceFontSetPos(64 - 7 * 4 / 2, 33); pceFontPrintf(" pause "); pceFontSetType(0); gamePhase = 4; pceLCDTrans(); return; } if(gamePhase & 2) { if(gameover == 0) { if((pad & PAD_RI)) { mR = (mR - 16) & 1023; } else if((pad & PAD_LF)) { mR = (mR + 16) & 1023; } if((pad & (PAD_A | PAD_B))) { mSpeed.x -= sintable[(256 + mR) & 1023] / 128; mSpeed.y += sintable[mR] / 128; } mSpeed.y += 8; if(mSpeed.x < -256 * 4) { mSpeed.x = -256 * 4; } else if(mSpeed.x > 256 * 4) { mSpeed.x = 256 * 4; } if(mSpeed.y < -256 * 4) { mSpeed.y = -256 * 4; } else if(mSpeed.y > 256 * 4) { mSpeed.y = 256 * 4; } mPos.x += mSpeed.x / 16; mPos.y += mSpeed.y / 16; if(mPos.x >= 125 * 256) { mPos.x = 124 * 256; gameover = 1; } else if(mPos.x <= 2 * 256) { mPos.x = 3 * 256; gameover = 1; } if(mPos.y >= 78 * 256) { mPos.y = 77 * 256; gameover = 1; } if(mPos.y < 40 * 256) { unsigned char *pC; int i, j, w, x1 , x2; mPos.y += 256; upperLine = (upperLine - 1) & 127; height ++; if(height > 0) { score ++; if((height & 127) == 0) { score += (time + FRAMERATE - 1) / FRAMERATE * 10; time += 60 * FRAMERATE; if(time > 99 * FRAMERATE) { time = 99 * FRAMERATE; } pceFontSetType(2 + 128); pceFontSetPos(4 * 5, 82); pceFontPrintf("%2d", (time + FRAMERATE - 1) / FRAMERATE); pceFontSetType(0); } pceFontSetType(2 + 128); pceFontSetPos(4 * 15, 82); pceFontPrintf("%4d", height % 10000); pceFontSetType(0); } if(upperLine == 111 && height > 0) { unsigned long *pL; pL = (unsigned long *)(vbuff2 + 128 * 108 + 4); while(pL < (unsigned long *)(vbuff2 + 128 * 109 - 4)) { *pL++ = 0; } pL += 2; while(pL < (unsigned long *)(vbuff2 + 128 * 110 - 4)) { *pL++ = 0xd3d3d3d3; } pL += 2; while(pL < (unsigned long *)(vbuff2 + 128 * 111 - 4)) { *pL++ = 0; } } box.x = 20 - (height + 40) / 64; if(box.x < 4) { box.x = 4; } box.y = 20 - (height + 40) / 64; if(box.y < 4) { box.y = 4; } for(j = 0; j < 1; j ++) { int x, y; x = 4 + (rand() % box.x); y = 4 + (rand() % box.y); pC = vbuff2 + ((upperLine - 20 - (rand() & 7)) & 127) * 128; x1 = 4 + (rand() % (120 - x)); x2 = x; i = y; while(i > 0) { if(pC < vbuff2) { pC += 128 * 128; } pC += x1; w = x2; while(w > 0) { *pC++ = 0; w --; } pC -= x1 + x2 + 128; i --; } } sweep(0x13, 0xd2); } } } else { mPos.x = 7 * 256; mPos.y = 60 * 256; mR = 0; if((rollCount & 7) == 0) { int i, j; if((upperLine & 31) == 0) { unsigned long *pL; pceLCDSetBuffer(vbuff2 + ((upperLine - 24) & 127) * 128); pceFontSetBkColor(0); switch(upperLine / 32) { case 0: pL = (unsigned long *)(vbuff2 + 12 + ((upperLine - 24) & 127) * 128); for(i = 0; i < 16; i ++) { for(j = 0; j < 26 / 2; j ++) { *pL = 0x91919191; pL += 2; } if((i & 7) == 3) { pL += 7; } else if((i & 7) == 7) { pL += 5; } else { pL += 6; } } pceFontSetTxColor(0x03); pceFontSetType(1 + 128); pceFontSetPos(64 - 4 * 5, 0); pceFontPrintf("spout"); break; case 2: pceFontSetTxColor(0xc3); pceFontSetType(2 + 128); pceFontSetPos(118 - 20 * 4, 0); pceFontPrintf(" height: %8d", hiScore[1] % 1000000); pceFontSetPos(118 - 20 * 4, 6); pceFontPrintf("high-score: %8d", hiScore[0] % 1000000); break; case 1: { const unsigned char *pS = MATSUMI; unsigned char *pD = vbuff2 + ((upperLine - 16) & 127) * 128; for(i = 0; i < 128 / 8 * 10; i ++) { unsigned char t = *pS++; for(j = 0; j < 8; j ++) { if(t & 0x80) { *pD = 0xc3; } pD ++; t <<= 1; } } } break; } pceFontSetType(0); pceFontSetTxColor(0x03); pceFontSetBkColor(0); pceLCDSetBuffer(vbuff); } upperLine = (upperLine - 1) & 127; sweep(0x13, 0x00); } } rollCount ++; { static int gx[] = {-2, 2, -1, 1, 0}; int r, t; r = rand() & 3; t = gx[r]; gx[r] = gx[r + 1]; gx[r + 1] = t; if(gamePhase & 2) { if(gameover == 0 && (pad & (PAD_A | PAD_B))) { int i, t, x, y; for(i = 0; i < 5; i ++) { t = mPos.x / 256 + gx[i] + ((mPos.y / 256 - 1 + abs(gx[i]) + dispPos) & 127) * 128; x = mSpeed.x / 16 + sintable[(256 + mR) & 1023] / 8; y = mSpeed.y / 16 - sintable[mR] / 8; spout(t, x, y); } } } else { int i, t; for(i = -1; i <= 2; i ++) { t = 7 + i + ((60 - 1 + dispPos) & 127) * 128; spout(t, 512, -384); } } } { GRAIN *pG, *pG2; SVECTOR svt; pG = grainUseLink; while(pG) { int f = 0; unsigned char *c; pG->v.y += 8; pG->s.x += pG->v.x; pG->s.y += pG->v.y; *(vbuff2 + pG->pos) = 0; *(v2g + pG->pos) = NULL; if(pG->s.y >= 256) { do { pG->s.y -= 256; pG->pos = (pG->pos + 128) & 16383; c = (vbuff2 + pG->pos); if(*c) { if(*c & 0x04) { int r; pG2 = *(v2g + pG->pos); r = 31 - (rand() & 63); svt = pG->v; pG->v = pG2->v; pG2->v = svt; pG->v.x += r; pG2->v.x -= r; } else { pG->v.y = -pG->v.y / 2; pG->v.x += 15 - (rand() & 31); if(*c & 0xc0) { *c -= 0x40; if(!(*c & 0xc0)) { *c = 0; } } if(pG->color & 0xc0) { pG->color -= 0x40; } else { pG->color = 0; f = 1; } } pG->pos = (pG->pos - 128) & 16383; break; } } while(pG->s.y >= 256); } else { while(pG->s.y <= -256) { pG->s.y += 256; pG->pos = (pG->pos - 128) & 16383; c = (vbuff2 + pG->pos); if(*c) { if(*c & 4) { pG2 = *(v2g + pG->pos); svt = pG->v; pG->v = pG2->v; pG2->v = svt; } else { pG->v.y = -pG->v.y / 2; if(*c & 0xc0) { *c -= 0x40; if(!(*c & 0xc0)) { *c = 0; } } if(pG->color & 0xc0) { pG->color -= 0x40; } else { pG->color = 0; f = 1; } } pG->pos = (pG->pos + 128) & 16383; break; } } } if(pG->s.x >= 256) { do { pG->s.x -= 256; pG->pos = (pG->pos + 1) & 16383; c = (vbuff2 + pG->pos); if(*c) { if(*c & 4) { pG2 = *(v2g + pG->pos); svt = pG->v; pG->v = pG2->v; pG2->v = svt; } else { pG->v.x = -pG->v.x / 2; if(*c & 0xc0) { *c -= 0x40; if(!(*c & 0xc0)) { *c = 0; } } if(pG->color & 0xc0) { pG->color -= 0x40; } else { pG->color = 0; f = 1; } } pG->pos = (pG->pos - 1) & 16383; break; } } while(pG->s.x >= 256); } else { while(pG->s.x <= -256) { pG->s.x += 256; pG->pos = (pG->pos - 1) & 16383; c = (vbuff2 + pG->pos); if(*c) { if(*c & 4) { pG2 = *(v2g + pG->pos); svt = pG->v; pG->v = pG2->v; pG2->v = svt; } else { pG->v.x = -pG->v.x / 2; if(*c & 0xc0) { *c -= 0x40; if(!(*c & 0xc0)) { *c = 0; } } if(pG->color & 0xc0) { pG->color -= 0x40; } else { pG->color = 0; f = 1; } } pG->pos = (pG->pos + 1) & 16383; break; } } } if(f) { *(vbuff2 + pG->pos) = pG->color; nGrain --; *(v2g + pG->pos) = NULL; pG = freeGrain(pG); } else { *(vbuff2 + pG->pos) = pG->color; *(v2g + pG->pos) = pG; pG = pG->next; } } } dispPos = upperLine; { unsigned long *pL, *pL2, *pLe; pL = (unsigned long *)(vbuff + 2 * 128); pL2 = (unsigned long *)(vbuff2 + dispPos * 128); pLe = pL2 + 128 * 78 / 4; if(pLe > (unsigned long *)(vbuff2 + 128 * 128)) { pLe = (unsigned long *)(vbuff2 + 128 * 128); } while(pL2 < pLe) { *pL = *pL2 & 0x03030303; pL ++; pL2 ++; } pL2 = (unsigned long *)(vbuff2); while(pL < (unsigned long *)(vbuff + 128 * (78 + 2))) { *pL = *pL2 & 0x03030303; pL ++; pL2 ++; } } { unsigned char *pC; pC = vbuff2 + mPos.x / 256 + ((mPos.y / 256 + dispPos) & 127) * 128; if(*pC != 0 && (*pC & 4) == 0) { gameover = *pC; } } { static int gPhase = 0; unsigned char *pC; int i, x, y; if(gameover == 0 && (gamePhase & 2)) { x = mPos.x + sintable[(256 + mR) & 1023] * gPhase / 64; y = mPos.y - sintable[mR] * gPhase / 64; for(i = 0; i < 3; i ++) { if(y >= 78 * 256) { break; } *(vbuff + x / 256 + (y / 256 + 2) * 128) = 3; x += sintable[(256 + mR) & 1023] / 16; y -= sintable[mR] / 16; if(y >= 78 * 256) { break; } *(vbuff + x / 256 + (y / 256 + 2) * 128) = 3; x += sintable[(256 + mR) & 1023] / 16; y -= sintable[mR] / 16; if(y >= 78 * 256) { break; } *(vbuff + x / 256 + (y / 256 + 2) * 128) = 3; x += sintable[(256 + mR) & 1023] * 2 / 16; y -= sintable[mR] * 2 / 16; } gPhase = (gPhase + 1) & 15; } pC = vbuff + mPos.x / 256 + (mPos.y / 256 + 2) * 128; *(pC - 129) = 0x03; *(pC - 128) = 0x03; *(pC - 127) = 0x03; *(pC - 1) = 0x03; *pC = 0x00; *(pC + 1) = 0x03; *(pC + 127) = 0x03; *(pC + 128) = 0x03; *(pC + 129) = 0x03; } if(gamePhase == 1) { if(pad & (TRG_A | TRG_B)) { gamePhase = 2; } } else if(gameover) { if(pad & (TRG_A | TRG_B)) { gamePhase = 0; } } if((gamePhase & 2) && time && gameover == 0) { time --; if((time % FRAMERATE) == 0) { pceFontSetType(2 + 128); pceFontSetPos(4 * 5, 82); pceFontPrintf("%2d", (time + FRAMERATE - 1) / FRAMERATE); pceFontSetType(0); } if(time == 0) { gameover = 1; } } if(dispscore < score) { dispscore ++; if(dispscore < score) { dispscore ++; } pceFontSetType(2 + 128); pceFontSetPos(4 * 26, 82); pceFontPrintf("%6d", dispscore % 1000000); pceFontSetType(0); } if(gamePhase == 3 && gameover != 0) { pceFontSetType(2 + 128); pceFontSetPos(64 - 11 * 4 / 2, 33); pceFontPrintf(" game over "); pceFontSetType(0); } pceLCDTrans(); } void pceAppExit( void ) { pceCPUSetSpeed(CPU_SPEED_NORMAL); } void spout(int t, int x, int y) { if(*(vbuff2 + t) == 0) { if(nGrain < MAX_GRAIN) { GRAIN *pG = allocGrain(); pG->v.x = x; pG->v.y = y; pG->s.x = 0; pG->s.y = 0; pG->color = (2 + (rand() & 1)) + 4 + 64 * 3; pG->pos = t; *(vbuff2 + t) = pG->color; v2g[t] = pG; nGrain ++; } } } void sweep(unsigned char c1, unsigned char c2) { int i; unsigned char *pC = vbuff2 + 4 + 128 * ((upperLine + 77) & 127); for(i = 0; i < 120; i ++) { if(*pC & 4) { GRAIN **ppG; ppG = v2g + (int)(pC - vbuff2); freeGrain(*ppG); *ppG = NULL; nGrain --; } *pC++ = c1; } pC += 8; if(pC >= vbuff2 + 128 * 128) { pC -= 128 * 128; } for(i = 0; i < 120; i ++) { *pC++ = c2; } } void initGrain(void) { int i; for(i = 0; i < MAX_GRAIN - 1; i ++) { grain[i].next = &grain[i + 1]; } grain[i].next = NULL; grainFreeLink = grain; grainUseLink = NULL; return; } GRAIN *allocGrain(void) { GRAIN *current = grainFreeLink; if(current) { grainFreeLink = current->next; current->next = grainUseLink; current->prev = NULL; if(current->next) { current->next->prev = current; } grainUseLink = current; } return current; } GRAIN *freeGrain(GRAIN *current) { GRAIN *next = current->next; if(next) { next->prev = current->prev; } if(current->prev) { current->prev->next = next; } else { grainUseLink = next; } current->next = grainFreeLink; grainFreeLink = current; return next; }