/* ____________ _______________________________________________ / __ _ \ | / _| (_) | | | |_ _ _ ___ _ ___ _ __ | | | _| | | / __| |/ _ \| '_ \ | | | | | |_| \__ \ | (_) | | | | | | |_| \__,_|___/_|\___/|_| |_| * | | | | The MSX C Library for SDCC | | V1.3 | | | | | | T H E G H O S T C H A S E | | Mini Game EXAMPLE by Eric Boez | | April 2020 / December 2020 | | | \___________________________________________________________/ * (°□°) * Works on MSX2 * Demonstrate the use of Sprite, PT3 + FX Sounds, Pattern rotation, * * Game Rules : Use the Arrow keys to give a direction to your PacMan * You Must eat the Ghost. Each Time you Eat the ghost you win One Point */ #include "fusion-c/header/msx_fusion.h" #include "fusion-c/header/vdp_graph2.h" #include "fusion-c/header/vdp_sprites.h" #include "fusion-c/header/pt3replayer.h" #include #include #include // Compilation & SDK directives For 32K Rom Compilation #define __SDK_ADDRCODE__ 0x4050 #define __SDK_ADDRDATA__ 0xC000 #define __SDK_MSXVERSION__ 2 #define __SDK_CRT0__ crt0_MSX32k_ROM4000.rel #define __SDK_EXT__ ROM #define __SDK_ROMSIZE__ 8000 // Game Definitions // #define DIFFICULTY 50 // more this value is low more the enemy will move #define GAMESPEED 180 // more this value is low more the speed increase #define LITTLENBC 5 // Number of unleashed ghosts // Functions definitions void StartScreen(void); void EndScreen(void); void SpriteOnScreen(void); void MoveEnemy(void); char CheckApproach(void); void EnemyDirection (void); void FT_Wait(int cicles); void PlaySound(void); void PrintScore(void); signed int FT_RandomNumber (signed int a, signed int b); void WaitSpaceKey(void); void InitInterruptHandler(unsigned int Routine); void EndInterruptHandler(void); // io ports for vdp __sfr __at (0x98) VDP_port1; __sfr __at (0x99) VDP_port2; // Global variables volatile char vdp_status; unsigned int MyTimer; // Timer signed char sdirX,sdirY; char GameOn; // Game char score; // Score Variable char PatternStep; char mj,slittle; char RunStep; static FCB file; const char TxtTitle[]="THE GHOST CHASE"; const char TxtPressKey[]="PRESS SPACE TO CONTINUE"; const char TxtScore[]="SCORE: "; const char TxtTime[]="TIME:"; const char TxtYourScore[]="YOUR SCORE:"; const char TxtSub[]=" Ericb59 with Fusion-C 1.3"; const char rotdir[10]={0,8,0,16,0,24,0,0,0}; const signed char DirectionX[9]={0,0,0,1,0,0,0,-1,0}; // X direction Array const signed char DirectionY[9]={0,-1,0,0,0,1,0,0,0}; // Y Direction Array // Store the pattern number, depending of the joystick direction static const char PlayerColor[16]={10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10}; // Player Sprite colors static const char EnemyColor[16]={8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8}; // Enemy Sprite Colors static const char EnemyColor2[16]={4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4}; static const char LittleColor[16]={7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7}; // Enemy Sprite Colors Version 2 static const char LittleColor2[16]={13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13}; static const signed char Shake[]={-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}; static const unsigned int playerPatG1[]={ 0b0000011111000000, 0b0001111111110000, 0b0011111111111000, 0b0011111111111000, 0b0000111111111100, 0b0000001111111100, 0b0000000011111100, 0b0000001111111100, 0b0000111111111100, 0b0011111111111000, 0b0011111111111000, 0b0001111111110000, 0b0000011111000000, 0b0000000000000000, 0b0000000000000000, 0b0000000000000000}; static const unsigned int playerPatG2[]={ 0b0000011111000000, 0b0000011111110000, 0b0000001111111000, 0b0000000111111000, 0b0000000011111100, 0b0000000001111100, 0b0000000000111100, 0b0000000001111100, 0b0000000011111100, 0b0000000111111000, 0b0000001111111000, 0b0000011111110000, 0b0000011111000000, 0b0000000000000000, 0b0000000000000000, 0b0000000000000000}; static const unsigned int enemyPat[]={ 0b0000001111000000, 0b0000111111110000, 0b0001111111111000, 0b0011001111001100, 0b0010000110000100, 0b0110110110110110, 0b0110110110110110, 0b0111001111001110, 0b0111111111111110, 0b0111111111111110, 0b0111111111111110, 0b0111111111111110, 0b0111101111011110, 0b0011000110001100, 0b0000000000000000, 0b0000000000000000}; static const unsigned int enemyPat2[]={ 0b0000001111000000, 0b0000111111110000, 0b0001111111111000, 0b0011111111111100, 0b0011111111111100, 0b0011100110011100, 0b0111100110011110, 0b0111111111111110, 0b0111111111111110, 0b0110011001100110, 0b0101100110011010, 0b0111111111111110, 0b0111101111011110, 0b0011000110001100, 0b0000000000000000, 0b0000000000000000}; // Sound FX Data static const char chase[] = { 0x06, 0x0B, 0x00, 0x58, 0x01, 0x9D, 0x01, 0x03, 0x02, 0x58, 0x02, 0xB3, 0x02, 0xEE, 0xF2, 0x07, 0x0B, 0xAE, 0x01, 0x05, 0xAE, 0xC0, 0x03, 0xAE, 0x5C, 0x02, 0xAB, 0x67, 0x01, 0xAB, 0x53, 0x01, 0xAB, 0x67, 0x01, 0xAB, 0x53, 0x01, 0xA8, 0xB3, 0x00, 0xA8, 0xA9, 0x00, 0xA8, 0xB3, 0x00, 0xA8, 0xA9, 0x00, 0xAF, 0xB3, 0x00, 0xAF, 0xBE, 0x00, 0xAF, 0xC9, 0x00, 0xAF, 0xD5, 0x00, 0xAF, 0xE2, 0x00, 0xAF, 0xF0, 0x00, 0xAF, 0xE2, 0x00, 0xAF, 0xF0, 0x00, 0xAF, 0x0D, 0x01, 0xAF, 0x1D, 0x01, 0xAF, 0x0D, 0x01, 0xAF, 0x1D, 0x01, 0xAF, 0x40, 0x01, 0xAF, 0x53, 0x01, 0xAF, 0x40, 0x01, 0xAF, 0x53, 0x01, 0xAD, 0xB3, 0x00, 0xAD, 0xBE, 0x00, 0xAD, 0xC9, 0x00, 0xAD, 0xD5, 0x00, 0xAD, 0xE2, 0x00, 0xAD, 0xF0, 0x00, 0xAD, 0xE2, 0x00, 0xAD, 0xF0, 0x00, 0xAD, 0x0D, 0x01, 0xAD, 0x1D, 0x01, 0xAD, 0x0D, 0x01, 0xAD, 0x1D, 0x01, 0xAD, 0x40, 0x01, 0xAD, 0x53, 0x01, 0xAD, 0x40, 0x01, 0xAD, 0x53, 0x01, 0xAB, 0xB3, 0x00, 0xAB, 0xBE, 0x00, 0xAB, 0xC9, 0x00, 0xAB, 0xD5, 0x00, 0xAB, 0xE2, 0x00, 0xAB, 0xF0, 0x00, 0xAB, 0xE2, 0x00, 0xAB, 0xF0, 0x00, 0xAB, 0x0D, 0x01, 0xAB, 0x1D, 0x01, 0xAB, 0x0D, 0x01, 0xAB, 0x1D, 0x01, 0xAB, 0x40, 0x01, 0xAB, 0x53, 0x01, 0xAB, 0x40, 0x01, 0xAB, 0x53, 0x01, 0xA9, 0xCF, 0x02, 0xA9, 0xF9, 0x02, 0xA9, 0x27, 0x03, 0xA9, 0x57, 0x03, 0xA9, 0x8A, 0x03, 0xA9, 0xC0, 0x03, 0xA9, 0x8A, 0x03, 0xA9, 0xC0, 0x03, 0xA9, 0x35, 0x04, 0xA9, 0x75, 0x04, 0xA9, 0x35, 0x04, 0xA9, 0x75, 0x04, 0xA9, 0x01, 0x05, 0xA9, 0x4D, 0x05, 0xA9, 0x01, 0x05, 0xA9, 0x4D, 0x05, 0xA7, 0xCF, 0x02, 0xA7, 0xF9, 0x02, 0xA7, 0x27, 0x03, 0xA7, 0x57, 0x03, 0xA7, 0x8A, 0x03, 0xA7, 0xC0, 0x03, 0xA7, 0x8A, 0x03, 0xA7, 0xC0, 0x03, 0xA7, 0x35, 0x04, 0xA7, 0x75, 0x04, 0xA7, 0x35, 0x04, 0xA7, 0x75, 0x04, 0xA7, 0x01, 0x05, 0xA7, 0x4D, 0x05, 0xA7, 0x01, 0x05, 0xA7, 0x4D, 0x05, 0xA5, 0xCF, 0x02, 0xA5, 0xF9, 0x02, 0xA5, 0x27, 0x03, 0xA5, 0x57, 0x03, 0xA5, 0x8A, 0x03, 0xA5, 0xC0, 0x03, 0xA5, 0x8A, 0x03, 0xA5, 0xC0, 0x03, 0xA5, 0x35, 0x04, 0xA5, 0x75, 0x04, 0xA5, 0x35, 0x04, 0xA5, 0x75, 0x04, 0xA5, 0x01, 0x05, 0xA5, 0x4D, 0x05, 0xA5, 0x01, 0x05, 0xA5, 0x4D, 0x05, 0xD0, 0x20, 0x64, 0x72, 0x75, 0x69, 0x64, 0x5F, 0x35, 0x00, 0xEB, 0x01, 0x0A, 0x07, 0x8C, 0xAD, 0x02, 0x00, 0x8E, 0xAF, 0x01, 0x0E, 0x8F, 0x2E, 0x01, 0x04, 0x0D, 0xAC, 0x01, 0x0A, 0x8C, 0x2C, 0x01, 0x0C, 0x0C, 0x2B, 0xF0, 0x06, 0x0B, 0x2A, 0xF6, 0x06, 0x0A, 0x29, 0xF8, 0x06, 0x09, 0x28, 0x01, 0x0C, 0x08, 0x27, 0xFC, 0x06, 0x07, 0x26, 0xFE, 0x06, 0x06, 0x25, 0xFF, 0x06, 0x04, 0x03, 0x02, 0x02, 0xD0, 0x20, 0x63, 0x6C, 0x69, 0x63, 0x6B, 0x6D, 0x61, 0x6E, 0x69, 0x61, 0x5F, 0x32, 0x00, 0x6D, 0x00, 0x01, 0x0A, 0x2E, 0x00, 0x03, 0x2D, 0x00, 0x01, 0x2E, 0x00, 0x03, 0x2C, 0x80, 0x00, 0xB0, 0x08, 0x09, 0xAC, 0xA0, 0x02, 0xAC, 0x60, 0x01, 0xB0, 0x08, 0x09, 0x29, 0xF0, 0x03, 0x09, 0x09, 0x29, 0x80, 0x03, 0x09, 0x09, 0x2A, 0x20, 0x03, 0x0A, 0x0A, 0x2A, 0xB0, 0x02, 0x0A, 0x0A, 0x2B, 0xA0, 0x02, 0x0B, 0x0B, 0x2B, 0x70, 0x02, 0x0B, 0x0B, 0x2B, 0xA0, 0x02, 0x0B, 0x0B, 0x2A, 0x00, 0x03, 0x0A, 0x0A, 0x29, 0x00, 0x04, 0x09, 0x09, 0x28, 0x00, 0x05, 0x08, 0x08, 0x27, 0x00, 0x06, 0x07, 0x07, 0x26, 0x00, 0x07, 0x06, 0x06, 0xA8, 0x01, 0x00, 0xD0, 0x20, 0x66, 0x69, 0x72, 0x65, 0x62, 0x69, 0x72, 0x64, 0x5F, 0x36, 0x00, 0xEB, 0x70, 0x02, 0x0A, 0x6F, 0xA0, 0x00, 0x1E, 0xB0, 0x09, 0x09, 0x90, 0x90, 0xAB, 0xA0, 0x02, 0xAD, 0xC0, 0x01, 0xAC, 0x1A, 0x02, 0xAD, 0x40, 0x02, 0xAC, 0x6A, 0x02, 0xAB, 0xD0, 0x02, 0xAA, 0x00, 0x05, 0xA9, 0x60, 0x06, 0xA8, 0x00, 0x02, 0xA8, 0x00, 0x03, 0xB0, 0x09, 0x09, 0x90, 0xA9, 0x1A, 0x02, 0xAA, 0x40, 0x02, 0xAA, 0x6A, 0x02, 0xA9, 0xD0, 0x02, 0xA9, 0x00, 0x05, 0xA8, 0x60, 0x06, 0xA7, 0x00, 0x02, 0xA6, 0x00, 0x03, 0xA8, 0x01, 0x00, 0xD0, 0x20, 0x66, 0x69, 0x72, 0x65, 0x62, 0x69, 0x72, 0x64, 0x5F, 0x37, 0x00, 0x68, 0x18, 0x00, 0x00, 0x27, 0x10, 0x00, 0x29, 0x24, 0x00, 0x28, 0x10, 0x00, 0x2A, 0x24, 0x00, 0x29, 0x10, 0x00, 0x2B, 0x24, 0x00, 0x29, 0x10, 0x00, 0x2A, 0x24, 0x00, 0x29, 0x10, 0x00, 0x2A, 0x24, 0x00, 0x28, 0x10, 0x00, 0x29, 0x24, 0x00, 0x27, 0x10, 0x00, 0x28, 0x24, 0x00, 0x26, 0x10, 0x00, 0x27, 0x24, 0x00, 0x25, 0x10, 0x00, 0x26, 0x24, 0x00, 0x24, 0x10, 0x00, 0x25, 0x24, 0x00, 0x23, 0x10, 0x00, 0x24, 0x24, 0x00, 0x23, 0x10, 0x00, 0x23, 0x24, 0x00, 0xA8, 0x01, 0x00, 0xD0, 0x20, 0x66, 0x69, 0x72, 0x65, 0x62, 0x69, 0x72, 0x64, 0x5F, 0x31, 0x33, 0x00, 0xEB, 0x28, 0x00, 0x1E, 0x89, 0x88, 0x89, 0xA6, 0x29, 0x00, 0xA5, 0x28, 0x00, 0x84, 0x83, 0xA8, 0x01, 0x00, 0xD0, 0x20, 0x66, 0x69, 0x72, 0x65, 0x62, 0x69, 0x72, 0x64, 0x5F, 0x31, 0x32, 0x00 }; const unsigned char song[] = { 0x56, 0x6F, 0x72, 0x74, 0x65, 0x78, 0x20, 0x54, 0x72, 0x61, 0x63, 0x6B, 0x65, 0x72, 0x20, 0x49, 0x49, 0x20, 0x31, 0x2E, 0x30, 0x20, 0x6D, 0x6F, 0x64, 0x75, 0x6C, 0x65, 0x3A, 0x20, 0x75, 0x6E, 0x6E, 0x61, 0x6D, 0x65, 0x64, 0x31, 0x2E, 0x62, 0x61, 0x63, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x79, 0x20, 0x63, 0x68, 0x34, 0x31, 0x6E, 0x73, 0x34, 0x77, 0x2E, 0x64, 0x6C, 0x63, 0x6F, 0x72, 0x70, 0x2E, 0x32, 0x32, 0x2E, 0x61, 0x75, 0x67, 0x2E, 0x6F, 0x36, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x02, 0x08, 0x06, 0x00, 0xD0, 0x00, 0x00, 0x00, 0x80, 0x05, 0xBA, 0x05, 0xD8, 0x05, 0x00, 0x00, 0xFA, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x06, 0x09, 0x06, 0x0F, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x06, 0x00, 0x00, 0x03, 0x03, 0x06, 0x06, 0xFF, 0xE2, 0x00, 0xD5, 0x01, 0x67, 0x02, 0x6B, 0x02, 0x5E, 0x03, 0xE5, 0x03, 0x20, 0x04, 0x13, 0x05, 0xE5, 0x03, 0x1A, 0x00, 0x2F, 0x04, 0x40, 0xCC, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x2F, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x2F, 0xCF, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x2F, 0xCC, 0xB1, 0x02, 0x79, 0xBB, 0x00, 0x2F, 0xB1, 0x01, 0x79, 0xD2, 0xBB, 0x00, 0x2F, 0xB1, 0x02, 0x79, 0xD3, 0xBB, 0x00, 0x2F, 0xCF, 0x79, 0xD2, 0xBB, 0x00, 0x2F, 0xCC, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x2F, 0x79, 0xD2, 0xBB, 0x00, 0x3B, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x3B, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x3B, 0xCF, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x3B, 0xCC, 0xB1, 0x02, 0x79, 0xBB, 0x00, 0x3B, 0xB1, 0x01, 0x79, 0xD2, 0xBB, 0x00, 0x3B, 0xB1, 0x02, 0x79, 0xD3, 0xBB, 0x00, 0x3B, 0xCF, 0x79, 0xD2, 0xBB, 0x00, 0x3B, 0xCC, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x3B, 0x79, 0xD2, 0xBB, 0x00, 0x4E, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x4E, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x4E, 0xCF, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x4E, 0xCC, 0xB1, 0x02, 0x79, 0xBB, 0x00, 0x4E, 0xB1, 0x01, 0x79, 0xD2, 0xBB, 0x00, 0x4E, 0xB1, 0x02, 0x79, 0xD3, 0xBB, 0x00, 0x4E, 0xCF, 0x79, 0xD2, 0xBB, 0x00, 0x4E, 0xCC, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x01, 0x35, 0x79, 0xD2, 0xBB, 0x00, 0x34, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x34, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x34, 0xCF, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x34, 0xCC, 0xB1, 0x02, 0x79, 0xBB, 0x00, 0x34, 0xB1, 0x01, 0x79, 0xD2, 0xBB, 0x00, 0x34, 0xB1, 0x02, 0x79, 0xD3, 0xBB, 0x00, 0x34, 0xCF, 0x79, 0xD2, 0xBB, 0x00, 0x34, 0xCC, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x34, 0x79, 0x00, 0xD1, 0xCF, 0xB1, 0x02, 0x7D, 0xB1, 0x01, 0xC0, 0xCA, 0xB1, 0x02, 0x7D, 0xB1, 0x01, 0xC0, 0xC7, 0xB1, 0x02, 0x7D, 0xCF, 0xB1, 0x01, 0x82, 0xC4, 0x7D, 0xCF, 0x80, 0xCA, 0x82, 0xCF, 0x7D, 0xCA, 0x80, 0xCF, 0xB1, 0x02, 0x7E, 0xC7, 0xB1, 0x01, 0x80, 0xCA, 0xB1, 0x02, 0x7E, 0xC3, 0xB1, 0x01, 0x80, 0xC7, 0x7E, 0xC0, 0xCF, 0xB1, 0x02, 0x79, 0xB1, 0x01, 0xC0, 0xCA, 0xB1, 0x02, 0x79, 0xB1, 0x01, 0xC0, 0xC7, 0xB1, 0x03, 0x79, 0xC4, 0xB1, 0x01, 0x79, 0xCF, 0xB1, 0x02, 0x7E, 0xB1, 0x01, 0x7D, 0xCA, 0x7E, 0xCF, 0x79, 0xCA, 0x7D, 0xCF, 0x74, 0xCA, 0x79, 0xB1, 0x02, 0x7E, 0xB1, 0x01, 0x7D, 0xC7, 0x7E, 0xCA, 0x79, 0xC7, 0x7D, 0xCA, 0x74, 0x1C, 0x01, 0x35, 0x0A, 0x40, 0xCF, 0x7E, 0xD1, 0xB1, 0x02, 0x7E, 0xB1, 0x01, 0x7D, 0xCA, 0x7E, 0xCF, 0x79, 0xCA, 0x7D, 0xCF, 0x74, 0xCA, 0x79, 0xB1, 0x02, 0x7E, 0xB1, 0x01, 0x7D, 0xC7, 0x7E, 0xCF, 0x78, 0xC7, 0x7D, 0xCA, 0x74, 0xC7, 0x79, 0x00, 0xB1, 0x40, 0xD0, 0x00, 0x1A, 0x00, 0x2F, 0x04, 0x40, 0xCC, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x2F, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x2F, 0xCF, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x2F, 0xCC, 0xB1, 0x02, 0x79, 0xBB, 0x00, 0x2F, 0xB1, 0x01, 0x79, 0xD2, 0xBB, 0x00, 0x2F, 0xB1, 0x02, 0x79, 0xD3, 0xBB, 0x00, 0x2F, 0xCF, 0x79, 0xD2, 0xBB, 0x00, 0x2F, 0xCC, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x2F, 0x79, 0xD2, 0xBB, 0x00, 0x3B, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x3B, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x3B, 0xCF, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x3B, 0xCC, 0xB1, 0x02, 0x79, 0xBB, 0x00, 0x3B, 0xB1, 0x01, 0x79, 0xD2, 0xBB, 0x00, 0x3B, 0xB1, 0x02, 0x79, 0xD3, 0xBB, 0x00, 0x3B, 0xCF, 0x79, 0xD2, 0xBB, 0x00, 0x3B, 0xCC, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x3B, 0x79, 0xD2, 0xBB, 0x00, 0x34, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x34, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x34, 0xCF, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x34, 0xCC, 0xB1, 0x02, 0x79, 0xBB, 0x00, 0x34, 0xB1, 0x01, 0x79, 0xD2, 0xBB, 0x00, 0x34, 0xB1, 0x02, 0x79, 0xD3, 0xBB, 0x00, 0x34, 0xCF, 0x79, 0xD2, 0xBB, 0x00, 0x34, 0xCC, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x34, 0x79, 0xD2, 0xBB, 0x00, 0x2F, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x2F, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x2F, 0xCF, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x2F, 0xCC, 0xB1, 0x02, 0x79, 0xBB, 0x00, 0x34, 0xB1, 0x01, 0x79, 0xD2, 0xBB, 0x00, 0x1A, 0xB1, 0x02, 0x79, 0xD3, 0xBB, 0x00, 0x1F, 0xCF, 0x79, 0xD2, 0xBB, 0x00, 0x27, 0xCC, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x34, 0x79, 0x00, 0x4F, 0xCF, 0xB1, 0x02, 0x85, 0xB1, 0x01, 0xC0, 0xCA, 0xB1, 0x02, 0x85, 0xB1, 0x01, 0xC0, 0xC7, 0x85, 0xC0, 0x41, 0xCF, 0x85, 0xC0, 0x4F, 0x84, 0xCA, 0x85, 0xCF, 0x85, 0xCA, 0x84, 0xCF, 0xB1, 0x02, 0x89, 0xB1, 0x01, 0xC0, 0xCA, 0xB1, 0x02, 0x89, 0xB1, 0x01, 0xC0, 0xC7, 0x89, 0xC0, 0xCF, 0xB1, 0x02, 0x82, 0xB1, 0x01, 0xC0, 0xCA, 0xB1, 0x02, 0x82, 0xB1, 0x01, 0xC0, 0xC7, 0xB1, 0x03, 0x82, 0xB1, 0x01, 0xC0, 0xCF, 0xB1, 0x02, 0x80, 0xB1, 0x01, 0x7B, 0xCA, 0x80, 0xCF, 0x79, 0xCA, 0x7B, 0xCF, 0xB1, 0x03, 0x78, 0xCA, 0xB1, 0x01, 0x7B, 0xCF, 0xB1, 0x03, 0x74, 0xCA, 0xB1, 0x01, 0x74, 0xCF, 0x74, 0xCA, 0x74, 0xCF, 0x76, 0xCA, 0x74, 0xCF, 0x78, 0xCA, 0x76, 0xCF, 0x79, 0xCA, 0x78, 0xCF, 0xB1, 0x02, 0x7D, 0xB1, 0x01, 0xC0, 0xCA, 0xB1, 0x02, 0x7D, 0xB1, 0x01, 0xC0, 0xC7, 0xB1, 0x03, 0x7D, 0xB1, 0x01, 0xC0, 0x00, 0xD5, 0x42, 0xC1, 0xB1, 0x02, 0x76, 0xC2, 0xD0, 0xC3, 0xD0, 0xC4, 0xD0, 0xC5, 0xD0, 0xC6, 0xD0, 0xC7, 0xD0, 0xC8, 0xD0, 0xC9, 0xB1, 0x10, 0xD0, 0x43, 0x02, 0xB1, 0x0A, 0x74, 0x01, 0x2E, 0x00, 0x10, 0x00, 0xC8, 0xB1, 0x02, 0xD0, 0xC7, 0xD0, 0xC6, 0xD0, 0x42, 0xC8, 0x76, 0xC7, 0xD0, 0xC6, 0xD0, 0xC5, 0xD0, 0xC4, 0xD0, 0xC3, 0xD0, 0xC1, 0xD0, 0xC0, 0x00, 0x1A, 0x00, 0x2F, 0x04, 0x40, 0xCC, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x2F, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x2F, 0xCF, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x2F, 0xCC, 0xB1, 0x02, 0x79, 0xBB, 0x00, 0x2F, 0xB1, 0x01, 0x79, 0xD2, 0xBB, 0x00, 0x2F, 0xB1, 0x02, 0x79, 0xD3, 0xBB, 0x00, 0x2F, 0xCF, 0x79, 0xD2, 0xBB, 0x00, 0x2F, 0xCC, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x2F, 0x79, 0xD2, 0xBB, 0x00, 0x3B, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x3B, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x3B, 0xCF, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x3B, 0xCC, 0xB1, 0x02, 0x79, 0xBB, 0x00, 0x3B, 0xB1, 0x01, 0x79, 0xD2, 0xBB, 0x00, 0x3B, 0xB1, 0x02, 0x79, 0xD3, 0xBB, 0x00, 0x3B, 0xCF, 0x79, 0xD2, 0xBB, 0x00, 0x3B, 0xCC, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x3B, 0x79, 0xD2, 0xBB, 0x00, 0x34, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x34, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x34, 0xCF, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x34, 0xCC, 0xB1, 0x02, 0x79, 0xBB, 0x00, 0x34, 0xB1, 0x01, 0x79, 0xD2, 0xBB, 0x00, 0x34, 0xB1, 0x02, 0x79, 0xD3, 0xBB, 0x00, 0x34, 0xCF, 0x79, 0xD2, 0xBB, 0x00, 0x34, 0xCC, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x34, 0x79, 0xD2, 0xBB, 0x00, 0x3B, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x3B, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x3B, 0xCF, 0xB1, 0x03, 0x79, 0xBB, 0x00, 0x3B, 0xCC, 0xB1, 0x02, 0x79, 0xBB, 0x00, 0x34, 0xB1, 0x01, 0x79, 0xD2, 0xBB, 0x00, 0x34, 0xB1, 0x02, 0x79, 0xD3, 0xBB, 0x00, 0x34, 0xCF, 0x79, 0xD2, 0xBB, 0x00, 0x34, 0xCC, 0xB1, 0x01, 0x79, 0xD3, 0xBB, 0x00, 0x34, 0x79, 0x00, 0xD1, 0xCF, 0xB1, 0x01, 0x76, 0xC0, 0x7D, 0xCA, 0x76, 0xCF, 0x82, 0xCA, 0x7D, 0xCF, 0x76, 0x84, 0x85, 0xCA, 0x84, 0xCF, 0x84, 0xCA, 0x85, 0xCF, 0x80, 0x7D, 0x76, 0x79, 0x85, 0xCA, 0x79, 0xCF, 0x82, 0xCA, 0x79, 0xCF, 0x76, 0xCA, 0x82, 0xCF, 0x85, 0xCA, 0x76, 0xCF, 0x84, 0xCA, 0x85, 0xCF, 0x80, 0xCA, 0x84, 0xCF, 0x76, 0x79, 0x7D, 0x79, 0x74, 0xCA, 0x7D, 0xCF, 0x85, 0xCA, 0x74, 0xCF, 0x84, 0xCA, 0x85, 0xCF, 0x74, 0x7B, 0x80, 0xCA, 0x7B, 0xCF, 0x85, 0xCA, 0x80, 0xCF, 0x84, 0x80, 0x7B, 0x74, 0x72, 0xCA, 0x7B, 0xCF, 0x85, 0xCA, 0x72, 0xCF, 0x84, 0xCA, 0x85, 0xCF, 0x72, 0x79, 0x80, 0xCA, 0x74, 0xCF, 0x85, 0xCA, 0x74, 0xCF, 0x87, 0x85, 0x84, 0x80, 0x00, 0x06, 0x0E, 0x01, 0x8F, 0x00, 0x00, 0x01, 0x8F, 0x00, 0x00, 0x01, 0x8F, 0x00, 0x00, 0x01, 0x8F, 0x00, 0x00, 0x01, 0x8F, 0x00, 0x00, 0x01, 0x8F, 0x00, 0x00, 0x01, 0x8F, 0x01, 0x00, 0x01, 0x8F, 0x01, 0x00, 0x01, 0x8F, 0xFF, 0xFF, 0x81, 0x8F, 0xFF, 0xFF, 0x01, 0x8F, 0x01, 0x00, 0x01, 0x8F, 0x01, 0x00, 0x81, 0x8F, 0xFF, 0xFF, 0x01, 0x8F, 0xFF, 0xFF, 0x06, 0x07, 0xCD, 0x8F, 0x80, 0x01, 0xC1, 0x8F, 0x80, 0x02, 0xC1, 0x8E, 0xC0, 0x03, 0xC1, 0x8E, 0x00, 0x05, 0xC1, 0xED, 0x00, 0x06, 0xC1, 0xED, 0x00, 0x07, 0xC0, 0x92, 0x00, 0x00, 0x07, 0x08, 0xCF, 0x0F, 0xC0, 0x00, 0xC1, 0x8F, 0x80, 0x01, 0xCD, 0x0F, 0xC0, 0x01, 0xCB, 0x0E, 0x40, 0x02, 0x89, 0x19, 0x00, 0x00, 0x01, 0x16, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x04, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x03, 0x07, 0x0C, 0x00, 0x04, 0x00, 0x04, 0x07, 0x0C, 0x00, 0x01, 0x00 }; static FastSPRITE Player; // Init the Fast Sprite Structure for the Player Sprite static FastSPRITE Enemy; // Init the Fast Sprite Structure for the Enemy Sprite static FastSPRITE Little[5]; // Sprite Status Structure typedef struct { char w; // Width of the object (Used for approach detection) char h; // Heigth of the object (Used for approach detection) char collision; // This flag is set to 1 if collide char nbc; // Number of steps to go in the direction set (Used for Enemy) char index; // Current index inside NBC (Used for enemy) char life; // LIfe on screen (Used for little enemies) char shake; // Shake mode on/off flag char approach; signed char dirX; // Direction to go on X signed char dirY; // Direction to go on Y } SPRITEState; static SPRITEState EnemyState; // Init the State Structure for the Enemy static SPRITEState PlayerState; // Init the State Structure for the player static SPRITEState LittleState[5]; // Init the State Structure for the little enemies /////////////////////////////////////////////////////////////////////////////////////////// // Return a random number signed int FT_RandomNumber (signed int a, signed int b) { signed char random; random = rand()%(b-a)+a; // Random number between a and b-1 return(random); } // Print score on Screen void PrintScore(void) { char scoreText[5]; Itoa(score,scoreText,10); PutText(60,4,scoreText,0); } // Wait Routine void FT_Wait(int cicles) { unsigned int i; for(i=0;i=245 || max_x<5) { EnemyState.dirX=0; } if (max_y>=200 || max_y<10) { EnemyState.dirY=0; } EnemyState.index=0; } void LittleDirection (int x1, int y1, char obj) { Little[obj].x=x1; Little[obj].y=y1; LittleState[obj].dirX=FT_RandomNumber(-1,2); LittleState[obj].dirY=FT_RandomNumber(-1,2); LittleState[obj].nbc=LITTLENBC; LittleState[obj].index=0; } // Check approach routine between Player and Enemy. // This routine can also be used to check Collision between Objects or sprites char CheckApproach(void) { char ap; if((Player.x >= Enemy.x + EnemyState.w*3) || (Player.x + PlayerState.w*3 <= Enemy.x) || (Player.y >= Enemy.y + EnemyState.h*3) || (Player.y + PlayerState.h*3 <= Enemy.y)) { ap=0; // Not in the range of a possible collision } else { ap=1; // Collision/approach detected } return(ap); } char CheckCollision(void) { char ap1,ap2,i; ap1=ap2=0; if((Player.x >= Enemy.x + EnemyState.w) || (Player.x + PlayerState.w <= Enemy.x) || (Player.y >= Enemy.y + EnemyState.h) || (Player.y + PlayerState.h <= Enemy.y)) { ap1=0; // Not in the range of a possible collision } else { ap1=0b11110000; } // Test Little ghosts for (i = 0; i < 5; ++i) { if((Player.x >= Little[i].x + LittleState[i].w) || (Player.x + PlayerState.w <= Little[i].x) || (Player.y >= Little[i].y + LittleState[i].h) || (Player.y + PlayerState.h <= Little[i].y)) { ap2=0; // Not in the range of a possible collision } else { if (PlayerState.collision==0) { ap2=0b00001111; PlayerState.collision=1; PlayerState.nbc=40; PlayerState.index=0; sdirY=PlayerState.dirY; sdirX=PlayerState.dirX; LittleState[i].dirX=0; LittleState[i].dirY=0; LittleState[i].shake=1; slittle=i; SetSpriteColors(10+slittle,LittleColor2); } } } return(ap1 | ap2); } // Enemy Move Control Routine // Direction of the enemy is randomized void MoveEnemy(void) { char i,check; check=CheckCollision(); // Collision Detection if (check>200 && EnemyState.shake==0 && PlayerState.shake==0) // Check Collision With Enemy and Player { if (EnemyState.collision==0) // If Yes, score is incremented { score++; PT3FXPlay(5,10); EnemyState.collision=1; // The Player State control is set to 1. To avoid continuous collision detection PrintScore(); EnemyState.nbc=0; // Force to recalcultae new route EnemyState.index=10; } } else { EnemyState.collision=0; } // Approach Detection if (CheckApproach()==1) // If the player spirte is near the enemy sprite { Enemy.pat=104; // It change its pattern to a frightened ghost pattern SetSpriteColors(1,EnemyColor2); // It change also its color EnemyState.approach=1; } else { Enemy.pat=100; // Normal pattern and color if Player sprite is far away of the Enemy sprite SetSpriteColors(1,EnemyColor); EnemyState.approach=0; } // Shake or Not ? if (EnemyState.dirX==0 && EnemyState.dirY==0 && EnemyState.approach==1) { EnemyState.shake=1; EnemyState.index=0; EnemyState.nbc=40; PT3FXPlay(2,10); } // Movement if (EnemyState.index>EnemyState.nbc && EnemyState.shake==0) // CHeck if Enemy Movement ends { EnemyDirection(); // If yes, we choose another direction to go } Enemy.x += EnemyState.dirX; // Increment X and Y position of the Enemy and also the Index movement Enemy.y += EnemyState.dirY; EnemyState.index++; if (EnemyState.shake==1) { EnemyState.dirY=Shake[EnemyState.index]; EnemyState.dirX=0; if (EnemyState.index>EnemyState.nbc) { EnemyState.life=0; EnemyState.shake=0; for ( i = 0; i < 5; ++i) { if (LittleState[i].life==0) { LittleState[i].life=100; LittleDirection (Enemy.x, Enemy.y, i); EnemyDirection(); } } PT3FXPlay(1,0); } } } void MoveLittle(void) { char i; for ( i = 0; i < 5; ++i) { if (LittleState[i].life>0) { Little[i].x+=LittleState[i].dirX; Little[i].y+=LittleState[i].dirY; LittleState[i].index++; if (LittleState[i].dirX!=0 || LittleState[i].dirY!=0) LittleState[i].life--; } else { Little[i].x=0; Little[i].y=212; } if (LittleState[i].index>LittleState[i].nbc && LittleState[i].life>20 && LittleState[i].shake==0) { LittleDirection (Little[i].x, Little[i].y, i); LittleState[i].index=0; } } } // Put All sprites on Screen void SpriteOnScreen(void) { char i; fPutSprite(&Player); fPutSprite(&Enemy); for ( i = 0; i < 5; ++i) { fPutSprite(&Little[i]); } } // Timer Routine void Timer(void) { unsigned int CurrentTimer; CurrentTimer=RealTimer()>>4; if (CurrentTimer>MyTimer) { MyTimer=CurrentTimer; BoxFill(256-MyTimer,4,256-MyTimer,12,0,0); if (MyTimer>100) { GameOn=0; EndScreen(); } } } // Wait Space Key VColor Routine void WaitSpaceKey(void) { char c=2; while (Inkey()!=32) { SetColor(c); PutText(36,130,TxtPressKey,0); c=(c+1)%16; if (c<2) c=2; } } // End Game Screen void EndScreen(void) { char scoreText[5],i; Enemy.y=212; Player.y=212; for ( i = 0; i < 5; ++i) { Little[i].y=212; } SpriteOnScreen(); SetColor(14); PutText(76,100,TxtYourScore,0); SetColor(8); Itoa(score,scoreText,10); PutText(164,100,scoreText,0); WaitSpaceKey(); SetColor(9); StartScreen(); } // Game Starting Screen void StartScreen(void) { char i; BoxFill(0,0,255,212,0,0); // Clear All the Screen SetColor(14); PutText(10,4,TxtScore,0); PutText(115,4,TxtTime,0); BoxFill(155,4,255,12,3,0); PutText(4,204,TxtSub,0); SetColor(9); PutText(68,90,TxtTitle,0); SetColor(10); PutText(69,90,TxtTitle,8); GameOn=0; score=0; PrintScore(); PT3FXPlay(0,10); WaitSpaceKey(); SetColor(14); BoxFill(0,60,255,212,0,0); srand(RealTimer()); SetRealTimer(0); // Set the Real Time Timer to 0 // Init Player Sprite Player.x=FT_RandomNumber (50, 200); // Player start position X Player.y=FT_RandomNumber (30, 180); // Player start position Y Player.spr=0; // Player Sprite Number Player.pat=0; // Player Sprite Pattern PlayerState.dirX=-1; // Player Direction on X PlayerState.dirY=0; // Player Direction on Y PlayerState.w=14; // Width of Sprite X2 (used for Approach Detection not for collision detection) PlayerState.h=14; // Height of Sprite X2 (used for Approach Detection not for collision detection) PlayerState.collision=0; PlayerState.shake=0; // Init Enemy Sprite Enemy.x=FT_RandomNumber (50, 200); // Enemy Start position X Enemy.y=FT_RandomNumber (30, 180); // Enemy Start position Y Enemy.spr=1; // Enemy Sprite Numbver Enemy.pat=100; // Enemy Sprite Pattern EnemyState.dirX=0; // Enemy Direction on X EnemyState.dirY=-1; // Enemy Direction on Y EnemyState.nbc=20; // How many step to go in the direction EnemyState.index=0; // Index in the number of steps EnemyState.w=14; // Width of Sprite X2 (used for Approach Detection not for collision detection) EnemyState.h=14; // Height of Sprite X2 (used for Approach Detection not for collision detection) EnemyState.shake=0; for ( i = 0; i < 5; ++i) { Little[i].x=0; Little[i].y=212; Little[i].spr=10+i; Little[i].pat=108; Little[i].col=1; LittleState[i].dirX=0; LittleState[i].dirY=0; LittleState[i].nbc=LITTLENBC; LittleState[i].index=0; LittleState[i].w=14; LittleState[i].h=14; LittleState[i].life=0; LittleState[i].shake=0; SetSpriteColors(10+i,LittleColor); } MyTimer=0; mj=7; GameOn=1; } // Routine call at each interrupt void routing(void) __critical __interrupt(0) __preserves_regs(a,b,c,d,e,h,l,iyl,iyh) { vdp_status = VDP_port2; if (GameOn==1) { Timer(); } PT3Rout(); // Route the PT3 music to PSGPT3Rout PT3Play(); // Play/Update the music playing PT3FXRout(); } // Main routine void main (void) { char j=0; // Current Joystiock Move mj=7; // Previous Joystick Move KeySound(0); // No key blop SetColors(15,0,1); // Default colors Screen(5); // Screen 5 SpriteReset(); // Reset previous Memory Sprites data Sprite16(); // Set sprite to 16x16 sprites mode VDP60Hz(); // Sounds InitPSG(); PT3Init (&song, 1); // Init Sonh PT3FXInit(&chase,1); // Init FX Sounds // Creation of Player patterns SetSpritePattern(0,Sprite32Bytes(playerPatG1),32); // Left1:0 :Original pattern1 go to left is set to pattern 0,1,2,3 SetSpritePattern(4,Sprite32Bytes(playerPatG2),32); // Left2:4 :Original pattern2 go to left is set to pattern 4,5,6,7 Pattern16RotationVram(0, 90, 8); // UP1:8 :Rotation of the pattern 0(0,1,2,3) 90 degrees to create the Player going to UP, and save it to Pattern 8,9,10,11 Pattern16RotationVram(4, 90, 12); // UP2:12:Same for Player pattern 2. Saved to Pattern 12,13,14,15 Pattern16FlipVram(0, 0, 16); // RIGHT1:16: Pattern16FlipVram(4, 0, 20); // RIGHTR2:20: Pattern16FlipVram(8, 1, 24); // DOWN1:24 Pattern16FlipVram(12,1, 28); // DOWN2:28 // Enemy Patterns SetSpritePattern(100,Sprite32Bytes(enemyPat),32); SetSpritePattern(104,Sprite32Bytes(enemyPat2),32); SetSpritePattern(108,Sprite32Bytes(enemyPat),32); SetSpriteColors(0,PlayerColor); // Set the Sprite colors to Vram InitInterruptHandler((unsigned int)routing); // Initialized Interrupt StartScreen(); // Show Start Screen // Main Loop while (Inkey()!=27) { if (GameOn==1) { if (RunStep%16==0) { PatternStep=!PatternStep; RunStep=0; } if (PlayerState.collision==0) { j=JoystickRead(0); // Retrieve Joystick Direction } else { PlayerState.dirX=Shake[PlayerState.index]; PlayerState.shake=1; PlayerState.dirY=0; PlayerState.index++; if (PlayerState.index>PlayerState.nbc) { PlayerState.shake=0; PlayerState.dirX=sdirX; PlayerState.dirY=sdirY; PlayerState.collision=0; LittleState[slittle].life=0; LittleState[slittle].nbc=0; LittleState[slittle].shake=0; Little[slittle].y=212; SetSpriteColors(10+slittle,LittleColor); } } if ((j==1 || j==3 || j==5 || j==7) && j!=mj && PlayerState.collision==0) // If Joystick is used, and direction is not the same as previous direction { PlayerState.dirX=DirectionX[j]; // Modify Player X direction PlayerState.dirY=DirectionY[j]; // Modify Player Y Direction mj=j; // Save Joystick direction PT3FXPlay(4,5); } Player.pat=rotdir[mj]+PatternStep*4; // Set the Correct pattern to player. Depending of the Joystick direction Player.x+=PlayerState.dirX; // Move Player sprite to the direction X Player.y+=PlayerState.dirY; // Move Player spriote to direction Y if (PlayerState.dirY==1 && Player.y>210) Player.y=0; if (PlayerState.dirY==-1 && Player.y<1) Player.y=210; RunStep++; MoveEnemy(); // Check And Manage Enemy moves and Collision MoveLittle(); SpriteOnScreen(); // Put All sprites on scrren FT_Wait(GAMESPEED); // Wait routine } else { j=0; mj=7; } } Exit(0); }