diff options
Diffstat (limited to 'spout.c')
| -rw-r--r-- | spout.c | 819 | 
1 files changed, 819 insertions, 0 deletions
| @@ -0,0 +1,819 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#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; +} + | 
