main.cFgP:I[Fmain.c"ɗɘɗ0TEXTCWIEFg:I[F{// Flood // David Johnston - Programming, Level design, Concept, Graphics // 8/5/99 // v1.0 #include #include #include #include #include #include "pad.h" #include "asssert.h" #include "dump.h" #include "message.h" #define MAINSPRS_ADDRESS 0x80090000 #define YOUSPRS_ADDRESS 0x80093000 #define VANISHSPRS_ADDRESS 0x80094000 #define FONTSPRS_ADDRESS 0x80097000 #define DIGITSPRS_ADDRESS 0x80099000 #define LEVELS_ADDRESS 0x800D0000 #define CODES_ADDRESS 0x800D0C80 #define PAL 1 // 0 - NTSC mode, 1 - PAL mode #define PACKETMAX 2048 /* Max GPU packets */ #define PACKETMAX2 (PACKETMAX*24) #define OT_LENGTH 5 static GsOT Wot[2]; /* Handler of OT */ static GsOT_TAG wtags[2][1<>1) & 8128),(cy) & 7936); \ sprite.u = ((cx) % 128); \ sprite.v = ((cy) % 256) #define CalcSprPos2(sprite,cx,cy) \ sprite->tpage = GetTPage(1,0,(((cx)>>1) & 8128),(cy) & 7936); \ sprite->u = ((cx) % 128); \ sprite->v = ((cy) % 256) u_char coldata[16][16][4] = { {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, {0,0,0,0},{0,0,0,0},{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,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,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,1},{1,1,1,1},{1,1,1,1}}, {{0,1,0,1},{0,0,0,0},{1,0,1,0},{0,0,0,0}, {0,1,0,1},{0,0,0,0},{1,0,1,0},{0,0,0,0}, {0,1,0,1},{0,0,0,0},{1,0,1,0},{0,0,0,0}, {0,1,0,1},{0,0,0,0},{1,0,1,0},{0,0,0,0}}, {{0,1,0,1},{0,1,0,1},{0,1,0,1},{0,1,0,1}, {0,1,0,1},{0,1,0,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,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}}, {{1,0,0,0},{1,0,0,0},{1,1,0,0},{1,1,0,0}, {1,1,1,0},{1,1,1,0},{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,1,1},{1,1,1,1},{1,1,1,1},{1,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},{1,0,0,0},{1,1,0,0},{1,1,0,0}, {1,1,1,0},{1,1,1,0},{1,1,1,1},{1,1,1,1}}, {{0,0,0,1},{0,0,0,1},{0,0,1,1},{0,0,1,1}, {0,1,1,1},{0,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,1}, {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,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}, {0,0,0,1},{0,0,0,1},{0,0,1,1},{0,0,1,1}, {0,1,1,1},{0,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,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,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,0},{0,0,0,0},{0,1,1,1},{0,0,0,0}, {1,1,1,0},{0,0,0,0},{0,1,1,1},{0,0,0,0}, {1,1,1,0},{0,0,0,0},{0,1,1,1},{0,0,0,0}, {1,1,1,0},{0,0,0,0},{0,1,1,1},{0,0,0,0}}, {{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,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},{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,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},{1,1,1,1},{1,1,1,1}, {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,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}, {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}, {{2,2,2,2},{2,2,2,2},{2,2,2,2},{2,2,2,2}, {2,2,2,2},{2,2,2,2},{2,2,2,2},{2,2,2,2}, {2,2,2,2},{2,2,2,2},{2,2,2,2},{2,2,2,2}, {2,2,2,2},{2,2,2,2},{2,2,2,2},{2,2,2,2}}, {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, {0,0,0,0},{0,0,0,0},{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,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,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,1},{1,1,1,1},{1,1,1,1}} }; u_char colmap[80][256]; char* passmess[10] = { "well done password for level 2 is 5812", "well done password for level 3 is 1932", "well done password for level 4 is 1554", "well done password for level 5 is 8521", "well done password for level 6 is 9364", "well done password for level 7 is 7496", "well done password for level 8 is 0460", "well done password for level 9 is 6892", "well done password for level 10 is 5814", "congratulations"}; int codes[9][4] = {{5,8,1,2},{1,9,3,2},{1,5,5,4},{8,5,2,1}, {9,3,6,4},{7,4,9,6},{0,4,6,0},{6,8,9,2},{5,8,1,4}}; // Global vars extern DISPENV GsDISPENV; int side; u_char level = 0; u_char quit, done, fail, reset; u_char map[20][16]; //The current map u_char state; // 0 - Normal // 1 - Vanishing u_char youx,youy,youdirn; char youxdis,youydis; u_char youstep,youstepdel,moving; int target, watercoll; u_long water[1024][2]; /**************************************************************************** prototypes ****************************************************************************/ void main (void); void ShowLevelMess (void); void BuildCollisionMap(void); void MoveWater (void); void PlotWater (void); void FindWater (void); void MoveBloke (void); void PlotBloke (void); void PlotMap (void); void SetUpMap (u_char map_no); void DealWithControllerPad (void); void EnterCode (void); void PlotCode (void); void EntCodePad (int* entcodeptr); u_char Shoveable (u_char tile); u_char Solid (u_char tile); void WaterFlowingPad (void); void InitialiseAll (void); /**************************************************************************** functions ****************************************************************************/ void main (void) { int hsync; int nytitledel = 320; int scrsize = 0; u_char levelmess; InitialiseAll(); side = GsGetActiveBuff(); quit = 0; done = 0; while (level<10 && quit==0) { SetUpMap(level); levelmess = done = reset = 0; // Main game loop hsync = VSync(0); while(quit==0 && done==0 && reset==0) { GsSetWorkBase((PACKET*)packetArea[side]); GsClearOt(0,0,&Wot[side]); PlotMap(); PlotBloke(); PlotMessage(&Wot[side]); MoveBloke(); if (Message() && !levelmess) {levelmess = 1; ShowLevelMess();} DealWithControllerPad(); hsync = VSync(0); ResetGraph(1); GsSwapDispBuff(); GsSortClear(0,0,4,&Wot[side]); GsDrawOt(&Wot[side]); side ^= 1; FntFlush(-1); } BuildCollisionMap(); FindWater(); done = 0; fail = 0; // Water flowing loop while(quit==0 && done<2 && fail==0 && reset==0) { GsSetWorkBase((PACKET*)packetArea[side]); GsClearOt(0,0,&Wot[side]); PlotMap(); PlotWater(); PlotMessage(&Wot[side]); MoveWater(); if (watercoll>=target*64 && done==0) {done = 1; StartMessage(passmess[level]);} if (Message() && done==1) done = 2; WaterFlowingPad(); hsync = VSync(0); if (hsync > 312) { MoveWater(); if (Message() && done==1) done = 2; } ResetGraph(1); GsSwapDispBuff(); GsSortClear(0,0,4,&Wot[side]); GsDrawOt(&Wot[side]); side ^= 1; FntFlush(-1); } if (done==2) level++; } if (level==10) printf("Good ending huh?\n"); ResetGraph(3); } char* messgs[6] = { "shove the blocks to create a path for the water", "the brown stuff disappears when hit from above with water", "only you can pass through the yellow mesh", "the blue block is ice it will turn into water", "you can push ice blocks", "last level good luck" }; void ShowLevelMess() { int showmessage = -1; switch (level) { case 0: showmessage = 0; break; case 1: showmessage = 1; break; case 3: showmessage = 2; break; case 4: showmessage = 3; break; case 7: showmessage = 4; break; case 9: showmessage = 5; break; } if (showmessage!=-1) StartMessage(messgs[showmessage]); } void BuildCollisionMap() { int x,y,x2,y2; u_char tile; for (y=0;y<16;y++) { for (x=0;x<20;x++) { tile = map[x][y]; for (y2=0;y2<16;y2++) { for (x2=0;x2<4;x2++) { if (tile==255) colmap[x*4 + x2][y*16 + y2] = 0; else colmap[x*4 + x2][y*16 + y2] = coldata[tile][y2][x2]; } } } } } asm void MoveWater() { // s0 - water .set reorder addiu sp,sp,-24 sw s0,4(sp) sw s1,8(sp) sw s2,12(sp) sw s3,16(sp) sw s4,20(sp) sw ra,24(sp) la s0,water li t8,0 li t9,1 movewaterlp: lw t0,0(s0) // water x beq t0,255,skipwater lw t1,4(s0) // water y sll t2,t0,8 // Get pointer to entry in collision map add t2,t2,t1 // the water drop is at. la t3,colmap add t2,t2,t3 beq t1,255,collected // Check if water has dropped // off bottom of screen lb t3,1(t2) // Check area below droplet beq t3,1,notdown // If solid then can't move down sb t8,0(t2) // Move.. add t1,t1,1 // ..droplet.. sw t1,4(s0) // ..down sb t9,1(t2) bne t3,2,skipwater srl t4,t0,2 srl t5,t1,4 sll t4,t4,4 add t4,t5,t4 la t5,map add t4,t5,t4 lb t5,0(t4) beq t5,-1,skipwater bgt t5,13,notcomplete li t5,15 notcomplete: sub t5,t5,15 and t6,t0,3 li t7,1 sllv t6,t7,t6 or t5,t5,t6 add t5,t5,15 bne t5,30,notempty li t5,255 notempty: sb t5,0(t4) b skipwater notdown: jal rand // Move left or right? and t4,v0,1 beqz t4,waterleft lb t3,256(t2) // Check area right of droplet bne t3,0,skipwater // If solid then can't move right sb t8,0(t2) // Move.. add t0,t0,1 // ..droplet.. sw t0,0(s0) // ..right sb t9,256(t2) b skipwater waterleft: lb t3,-256(t2) // Check area right of droplet bne t3,0,skipwater // If solid then can't move left sb t8,0(t2) // Move.. sub t0,t0,1 // ..droplet.. sw t0,0(s0) // ..left sb t9,-256(t2) skipwater: add s0,s0,2*sizeof(long) // Loop back if there are more droplets la t0,water add t0,t0,2048*sizeof(u_long) blt s0,t0,movewaterlp lw s0,4(sp) lw s1,8(sp) lw s2,12(sp) lw s3,16(sp) lw s4,20(sp) lw ra,24(sp) addiu sp,sp,24 jr ra collected: sb t8,0(t2) li t0,255 sw t0,0(s0) lw t4,watercoll add t4,t4,1 sw t4,watercoll b skipwater } void PlotWater () { GsLINE drop; int i; drop.attribute = 0; drop.r = 0; drop.g = 0; drop.b = 255; for (i=0;i<1024;i++) { if (water[i][0]!=255) { drop.x0 = water[i][0]*4; drop.x1 = drop.x0 + 3; drop.y0 = drop.y1 = water[i][1]; GsSortLine(&drop, &Wot[side], 7); } } } void FindWater () { u_int waterptr = 0; int x,x2,y,y2; for (y=0;y<16;y++) { for (x=0;x<20;x++) { if (map[x][y] == 0 || map[x][y] == 14) { for (y2=0;y2<16;y2++) { for (x2=0;x2<4;x2++) { water[waterptr][0]=(x*4)+x2; water[waterptr][1]=(y*16)+y2; waterptr++; assert(waterptr<=1024); } } map[x][y] = 255; } if (map[x][y] == 12) map[x][y] = 255; } } } void MoveBloke () { switch (state) { case 0: if (moving) { if ((youstepdel--) == 0) { youstepdel = 5; youstep^=1; } switch (youdirn) { case 0: if ((youydis-=2) < 0) {youydis+=16; youy--;} break; case 1: if ((youxdis+=2) == 16) {youxdis-=16; youx++;} break; case 2: if ((youydis+=2) == 16) {youydis-=16; youy++;} break; case 3: if ((youxdis-=2) < 0) {youxdis+=16; youx--;} break; } if (youxdis==0 && youydis==0) moving = 0; } break; case 1: if (youstepdel-- == 0) { youstepdel = 2; if (youstep-- == 0) done = 1; } break; case 2: if (youstepdel-- == 0) { youstepdel = 2; if (++youstep == 32) {state = 0; youstep = 0;} } break; } } void PlotBloke () { GsSPRITE youspr; InitGsSprite(&youspr); youspr.x = youx*16 + youxdis; youspr.y = youy*16 + youydis; switch (state) { case 0: CalcSprPos(youspr, 640+(youdirn*2 + youstep)*16, 16); break; case 1: case 2: CalcSprPos(youspr, 640+(youstep % 16)*16, 32+16*(youstep/16)); break; } GsSortFastSprite(&youspr, &Wot[side], 11); } void PlotMap () { int x,y,tile; GsSPRITE tilespr; InitGsSprite(&tilespr); for (y=0;y<16;y++) { for (x=0;x<20;x++) { tile = map[x][y]; if (tile!=255) { CalcSprPos(tilespr,640+(tile*16),0); tilespr.x = x*16; tilespr.y = y*16; GsSortFastSprite(&tilespr, &Wot[side], 10); } } } } void SetUpMap (u_char map_no) { u_char x,y; static char* mess = "collect xx units of water"; u_char* baseaddr = (u_char*)LEVELS_ADDRESS+(320*map_no); u_char* stuffaddr = (u_char*)CODES_ADDRESS+(4*map_no); for (y=0;y<16;y++) { for (x=0;x<20;x++) { map[x][y] = *(baseaddr+(y*20)+x); } } youx = *(stuffaddr); youy = *(stuffaddr+1); youxdis = youydis = youstep = youstepdel = moving = watercoll = 0; youdirn = state = 2; target = *(stuffaddr+2)-1; *(mess+8)=48+(target / 10); *(mess+9)=48+(target % 10); StartMessage(mess); } void DealWithControllerPad (void) { u_char storemove = 0; long pad; u_char tile, tile2; pad = PadRead(); if (state==0) { if (pad & PADRleft) reset = 1; if (pad & PADRup) EnterCode(); if (pad & PADRdown) {state=1; youstep=31; youstepdel=2;} if (pad & PADLleft && !moving) { tile = map[youx-1][youy]; if (youx==1) tile2 = 0; else tile2 = map[youx-2][youy]; if (Shoveable(tile) && !Solid(tile2)) { map[youx-2][youy] = tile; map[youx-1][youy] = 255; } if (!Solid(tile) || tile==10) { youdirn = 3; moving = 1; } } if (pad & PADLright && !moving) { tile = map[youx+1][youy]; if (youx==18) tile2 = 0; else tile2 = map[youx+2][youy]; if (Shoveable(tile) && !Solid(tile2)) { map[youx+2][youy] = tile; map[youx+1][youy] = 255; } if (!Solid(tile) || tile==10) { youdirn = 1; moving = 1; } } if (pad & PADLup && !moving) { tile = map[youx][youy-1]; if (youy==1) tile2 = 0; else tile2 = map[youx][youy-2]; if (Shoveable(tile) && !Solid(tile2)) { map[youx][youy-2] = tile; map[youx][youy-1] = 255; } if (!Solid(tile) || tile==10) { youdirn = 0; moving = 1; } } if (pad & PADLdown && !moving) { tile = map[youx][youy+1]; if (youy==14) tile2 = 0; else tile2 = map[youx][youy+2]; if (Shoveable(tile) && !Solid(tile2)) { map[youx][youy+2] = tile; map[youx][youy+1] = 255; } if (!Solid(tile) || tile==10) { youdirn = 2; moving = 1; } } } // quit program if (pad & PADselect) { while (pad & PADselect) pad = PadRead(); quit = 1; } // pause if (pad & PADstart) { while (pad & PADstart) { pad = PadRead(); } while (!(pad & PADstart)) { pad = PadRead(); } while (pad & PADstart) { pad = PadRead(); } VSync(0); } } int code[4]; int selectedlet; void EnterCode (void) { int entcode = 0; int hsync, i, lev; selectedlet = 0; side = GsGetActiveBuff(); while(entcode==0) { GsSetWorkBase((PACKET*)packetArea[side]); GsClearOt(0,0,&Wot[side]); PlotMap(); PlotBloke(); PlotMessage(&Wot[side]); PlotCode(); EntCodePad(&entcode); hsync = VSync(0); ResetGraph(1); GsSwapDispBuff(); GsSortClear(0,0,4,&Wot[side]); GsDrawOt(&Wot[side]); side ^= 1; FntFlush(-1); } if (entcode==1) { lev = -1; for (i=0;i<10;i++) { if (codes[i][0]==code[0] && codes[i][1]==code[1] && codes[i][2]==code[2] && codes[i][3]==code[3]) lev = i; } if (lev!=-1) {level = lev+1; reset = 1;} } } void PlotCode() { GsBOXF border; GsSPRITE digit; int i; static int flashdel = 0; border.attribute = 0; border.x = 96; border.y = 112; border.w = 128; border.h = 32; border.r = border.g = 0; border.b = 220; GsSortBoxFill(&border, &Wot[side], 2); border.x = 100; border.y = 116; border.w = 120; border.h = 24; border.b = 32; GsSortBoxFill(&border, &Wot[side], 1); if ((flashdel--) == 0) flashdel = 31; InitGsSprite(&digit); digit.x = 116; digit.y = 120; for (i=0;i<4;i++) { CalcLetterPos(&digit, (char)(code[i]+48)); if (selectedlet!=i || flashdel<24) GsSortSprite(&digit, &Wot[side], 0); digit.x+=24; } } void EntCodePad (int* entcodeptr) { long pad; static int pressed = 0; pad = PadRead(); if (pad & PADRdown) { while (pad & PADRdown) pad = PadRead(); *(entcodeptr) = 1; } if (pad & PADselect || pad & PADRleft) { while (pad & PADselect || pad & PADRleft) pad = PadRead(); *(entcodeptr) = 2; } if (pressed==0) { if (pad & PADLleft && selectedlet>0) {pressed = 1; selectedlet--;} if (pad & PADLright && selectedlet<3) {pressed = 1; selectedlet++;} if (pad & PADLup && code[selectedlet]<9) {pressed = 1; code[selectedlet]++;} if (pad & PADLdown && code[selectedlet]>0) {pressed = 1; code[selectedlet]--;} } else if (!(pad & PADLup) && !(pad & PADLdown) && !(pad & PADLleft) && !(pad & PADLright)) pressed = 0; } u_char Shoveable (u_char tile) { if (tile==11 || tile==14) return 1; else return 0; } u_char Solid (u_char tile) { if (tile==0 || tile==255 || tile==15) return 0; else return 1; } void WaterFlowingPad (void) { long pad; pad = PadRead(); if (pad & PADRleft) fail = 1; // quit program if (pad & PADselect) { while (pad & PADselect) pad = PadRead(); quit = 1; } // pause if (pad & PADstart) { while (pad & PADstart) { pad = PadRead(); } while (!(pad & PADstart)) { pad = PadRead(); } while (pad & PADstart) { pad = PadRead(); } VSync(0); } } void InitialiseAll() { if (PAL) { SetVideoMode(MODE_PAL); GsInitGraph(320,256,GsOFSGPU,0,0); GsDefDispBuff(0,0,0,256); GsDISPENV.screen.x = 5; GsDISPENV.screen.y = 20; GsDISPENV.screen.h = 256; } else { SetVideoMode(MODE_NTSC); GsInitGraph(320,240,GsOFSGPU,0,0); GsDefDispBuff(0,0,0,240); GsDISPENV.screen.x = 5; GsDISPENV.screen.y = 10; GsDISPENV.screen.h = 240; } Wot[0].length=OT_LENGTH; Wot[0].org=wtags[0]; Wot[1].length=OT_LENGTH; Wot[1].org=wtags[1]; GsClearOt(0,0,&Wot[0]); GsClearOt(0,0,&Wot[1]); InitSpr(MAINSPRS_ADDRESS); InitSpr(YOUSPRS_ADDRESS); InitSpr(VANISHSPRS_ADDRESS); InitSpr(FONTSPRS_ADDRESS); InitSpr(DIGITSPRS_ADDRESS); PadInit(); } ZZRmain.crrior IDE 2.0.3szenrulderATEXTCWIE*6:IFg@M8ݲM8prefApprH Monaco;`;`[MwZZR (4&RMPSRMWBB*LR