diff --git a/.gitignore b/.gitignore index 045dba1..75271df 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ bin/ *.exe opentitus *.dge +*.swp +tags diff --git a/include/audio.h b/include/audio.h index 2f7988b..9ea60d1 100644 --- a/include/audio.h +++ b/include/audio.h @@ -33,13 +33,13 @@ //#include "SDL/SDL_mixer.h" int initaudio(); -int freeaudio(); +void freeaudio(); int SELECT_MUSIC(int song_number); int WAIT_SONG(); int FX_START(int fx_number); int RETURN_MUSIC(); int startmusic(); -int refreshaudio(); +void refreshaudio(); /* diff --git a/include/backbuffer.h b/include/backbuffer.h index bfa627d..fb30499 100644 --- a/include/backbuffer.h +++ b/include/backbuffer.h @@ -31,7 +31,7 @@ #include "SDL/SDL.h" -SDL_Surface *screen; //Backbuffer -SDL_Surface *tilescreen; //Tile screen +extern SDL_Surface *screen; //Backbuffer +extern SDL_Surface *tilescreen; //Tile screen #endif diff --git a/include/draw.h b/include/draw.h index 159dc0f..5f51909 100644 --- a/include/draw.h +++ b/include/draw.h @@ -52,6 +52,7 @@ int view_password(TITUS_level *level, uint8 level_index); int loadpixelformat(SDL_PixelFormat **pixelformat); int loadpixelformat_font(SDL_PixelFormat **pixelformat); int freepixelformat(SDL_PixelFormat **pixelformat); +void DISPLAY_SPRITES(TITUS_level *level); #endif diff --git a/include/enemies.h b/include/enemies.h index 4069566..d1282ed 100644 --- a/include/enemies.h +++ b/include/enemies.h @@ -37,9 +37,11 @@ #include "SDL/SDL.h" #include "level.h" +extern uint8 INVULNERABLE_FLAG; //When non-zero, boss is invulnerable int MOVE_NMI(TITUS_level *level); int SET_NMI(TITUS_level *level); int MOVE_TRASH(TITUS_level *level); +int updateenemysprite(TITUS_level *level, TITUS_enemy *enemy, int16 number, bool clearflags); #endif diff --git a/include/engine.h b/include/engine.h index b26ca45..40a9f7d 100644 --- a/include/engine.h +++ b/include/engine.h @@ -31,6 +31,9 @@ #include "SDL/SDL.h" +extern bool GAMEOVER_FLAG; //triggers a game over +extern uint16 IMAGE_COUNTER; //Increased every loop in game loop (0 to 0x0FFF) + int playtitus(int firstlevel); #endif diff --git a/include/fonts.h b/include/fonts.h index 5d06800..3396897 100644 --- a/include/fonts.h +++ b/include/fonts.h @@ -53,9 +53,6 @@ struct _TITUS_font { void *sub[256]; //May be malloced }; -TITUS_font *font; //Malloced -SDL_Surface *font_undefined; //Pointer - int loadfonts(void); int freefonts(void); diff --git a/include/gates.h b/include/gates.h index 729d8e0..f0d4dbd 100644 --- a/include/gates.h +++ b/include/gates.h @@ -32,6 +32,8 @@ #include "SDL/SDL.h" #include "level.h" +extern int16 XLIMIT; //The engine will not scroll past this tile before the player have crossed the line (X) + int CROSSING_GATE(TITUS_level *level); //Check and handle level completion, and if the player does a kneestand on a secret entrance int CLOSE_SCREEN(); int OPEN_SCREEN(); diff --git a/include/globals.h b/include/globals.h index 97cb331..6f92d65 100644 --- a/include/globals.h +++ b/include/globals.h @@ -149,88 +149,31 @@ #define int16 signed short int -uint8 RESETLEVEL_FLAG; -bool GAMEOVER_FLAG; //triggers a game over -uint8 BAR_FLAG; //timer for health bar -bool X_FLAG; //true if left or right key is pressed -bool Y_FLAG; //true if up or down key is pressed -uint8 CHOC_FLAG; //headache timer -uint8 action; //player sprite array -uint8 KICK_FLAG; //hit/burn timer -bool GRANDBRULE_FLAG; //If set, player will be "burned" when hit (fireballs) -bool LADDER_FLAG; //True if in a ladder -bool PRIER_FLAG; //True if player is forced into kneestanding because of low ceiling -uint8 SAUT_FLAG; //6 if free fall or in the middle of a jump, decremented if on solid surface. Must be 0 to initiate a jump. -uint8 LAST_ORDER; //Last action (kneestand + jump = silent walk) -uint8 FURTIF_FLAG; //Silent walk timer -bool DROP_FLAG; //True if an object is throwed forward -bool DROPREADY_FLAG; -bool CARRY_FLAG; //true if carrying something (add 16 to player sprite) -bool POSEREADY_FLAG; -uint8 ACTION_TIMER; //Frames since last action change -//TITUS_sprite sprite; //Player sprite -//TITUS_sprite sprite2; //Secondary player sprite (throwed objects, "hit" when object hits an enemy, smoke when object hits the floor) -uint8 INVULNERABLE_FLAG; //When non-zero, boss is invulnerable -uint8 TAPISFLY_FLAG; //When non-zero, the flying carpet is flying -uint8 CROSS_FLAG; //When non-zero, fall through certain floors (after key down) -uint8 GRAVITY_FLAG; //When zero, skip object gravity function -uint8 FUME_FLAG; //Smoke when object hits the floor -Uint8 *keystate; //Keyboard state -uint8 LIFE; //Lives -uint8 YFALL; -bool POCKET_FLAG; -bool PERMUT_FLAG; //If false, there are no animated tiles on the screen? -uint8 loop_cycle; //Increased every loop in game loop -uint8 tile_anim; //Current tile animation (0-1-2), changed every 4th game loop cycle -uint8 BITMAP_X; //Screen offset (X) in tiles -uint8 BITMAP_XM; //Point to the left tile in the tile screen (0 to 19) -uint8 BITMAP_Y; //Screen offset (Y) in tiles -uint8 BITMAP_YM; //Point to the top tile in the tile screen (0 to 11) -bool XSCROLL_CENTER; //If true, the screen will scroll in X -int16 XLIMIT_SCROLL; //If scrolling: scroll until player is in this tile (X) -int16 XLIMIT; //The engine will not scroll past this tile before the player have crossed the line (X) -bool YSCROLL_CENTER; //If true, the screen will scroll in Y -uint8 YLIMIT_SCROLL; //If scrolling: scroll until player is in this tile (Y) -uint8 ALTITUDE_ZERO; //The engine will not scroll below this tile before the player have gone below (Y) -int LAST_CLOCK; //Used for fixed framerate -uint16 IMAGE_COUNTER; //Increased every loop in game loop (0 to 0x0FFF) -int8 SENSX; //1: walk right, 0: stand still, -1: walk left, triggers the ACTION_TIMER if it changes -uint8 SAUT_COUNT; //Incremented from 0 to 3 when accelerating while jumping, stop acceleration upwards if >= 3 -bool NOSCROLL_FLAG; -bool NEWLEVEL_FLAG; //Finish a level -uint8 BIGNMI_NBR; //Number of bosses that needs to be killed to finish -uint8 TAUPE_FLAG; //Used for enemies walking and popping up -uint8 TAPISWAIT_FLAG; //Flying carpet state -uint8 SEECHOC_FLAG; //Counter when hit -bool NFC_FLAG; //Skip NO_FAST_CPU -uint8 BIGNMI_POWER; //Lives of the boss -bool boss_alive; //True if the boss is alive -uint8 AUDIOMODE; - -bool GODMODE; //If true, the player will not interfere with the enemies -bool NOCLIP; //If true, the player will move noclip -bool DISPLAYLOOPTIME; //If true, display loop time in milliseconds -uint8 LOOPTIME; //Loop time -uint8 SUBTIME[16]; //Sub time -uint16 FPS; //Frames pr second -uint16 FPS_LAST; //Frames pr second -uint16 LAST_CLOCK_CORR; //Correction to LAST_CLOCK +extern bool NOSCROLL_FLAG; +extern uint8 TAUPE_FLAG; //Used for enemies walking and popping up +extern uint8 TAPISWAIT_FLAG; //Flying carpet state +extern uint8 SEECHOC_FLAG; //Counter when hit +extern uint8 BIGNMI_POWER; //Lives of the boss +extern bool boss_alive; //True if the boss is alive +extern uint8 AUDIOMODE; + +extern bool GODMODE; //If true, the player will not interfere with the enemies +extern bool NOCLIP; //If true, the player will move noclip +extern bool DISPLAYLOOPTIME; //If true, display loop time in milliseconds typedef struct { bool enabled; uint16 NUM; } SPRITE; -SPRITE sprites[256]; +//SPRITE sprites[256]; typedef struct { bool enabled; uint16 NUM; } SPRITEDATA; -SPRITEDATA spritedata[256]; - -uint16 level_code[16]; +//SPRITEDATA spritedata[256]; #endif diff --git a/include/level.h b/include/level.h index bb5fe05..b313009 100644 --- a/include/level.h +++ b/include/level.h @@ -231,6 +231,8 @@ struct _TITUS_level { }; +extern uint8 ALTITUDE_ZERO; //The engine will not scroll below this tile before the player have gone below (Y) + int loadlevel(TITUS_level *level, unsigned char *leveldata, int leveldatasize, TITUS_spritedata **spritedata, TITUS_spritecache *spritecache, TITUS_objectdata **objectdata); int freelevel(TITUS_level *level); uint8 get_horizflag(TITUS_level *level, int16 tileY, int16 tileX); diff --git a/include/objects.h b/include/objects.h index 369f1fb..98c3662 100644 --- a/include/objects.h +++ b/include/objects.h @@ -32,7 +32,10 @@ #include "SDL/SDL.h" #include "level.h" -int move_objects(TITUS_level *level); +extern uint8 TAPISFLY_FLAG; //When non-zero, the flying carpet is flying +extern uint8 GRAVITY_FLAG; //When zero, skip object gravity function + +void move_objects(TITUS_level *level); bool SPRITES_VS_SPRITES (TITUS_level *level, TITUS_sprite *sprite1, TITUS_sprite *sprite1ref, TITUS_object **object2); //check if there is an object below that can support the input object int updateobjectsprite(TITUS_level *level, TITUS_object *obj, int16 number, bool clearflags); int loadobjects(TITUS_objectdata ***objects, uint16 *count); diff --git a/include/original.h b/include/original.h index 57b87b2..b51d628 100644 --- a/include/original.h +++ b/include/original.h @@ -44,32 +44,32 @@ int initoriginal(); int16 getlevelid(int16 levelnumber); -SDL_Color orig_palette_colour[16]; -SDL_Color orig_palette_level_colour[16]; -SDL_Color orig_palette_font_colour[16]; +extern SDL_Color orig_palette_colour[16]; +extern SDL_Color orig_palette_level_colour[16]; +extern SDL_Color orig_palette_font_colour[16]; -uint8 spritewidth[SPRITECOUNT]; -uint8 spriteheight[SPRITECOUNT]; -uint8 spritecollwidth[SPRITECOUNT]; -uint8 spritecollheight[SPRITECOUNT]; -uint8 spriterefwidth[SPRITECOUNT]; -uint8 spriterefheight[SPRITECOUNT]; +extern uint8 spritewidth[SPRITECOUNT]; +extern uint8 spriteheight[SPRITECOUNT]; +extern uint8 spritecollwidth[SPRITECOUNT]; +extern uint8 spritecollheight[SPRITECOUNT]; +extern uint8 spriterefwidth[SPRITECOUNT]; +extern uint8 spriterefheight[SPRITECOUNT]; -int16 anim_player[ANIM_PLAYER_COUNT][ANIM_PLAYER_MAX]; -int16 anim_enemy[NMI_ANIM_TABLE_COUNT]; -uint8 NMI_POWER[ORIG_LEVEL_COUNT]; -uint8 LEVEL_MUSIC[ORIG_LEVEL_COUNT]; +extern int16 anim_player[ANIM_PLAYER_COUNT][ANIM_PLAYER_MAX]; +extern int16 anim_enemy[NMI_ANIM_TABLE_COUNT]; +extern uint8 NMI_POWER[ORIG_LEVEL_COUNT]; +extern uint8 LEVEL_MUSIC[ORIG_LEVEL_COUNT]; -int16 anim_zoubida[ORIG_ANIM_MAX]; -int16 anim_moktar[ORIG_ANIM_MAX]; -int16 anim_smoke[ORIG_ANIM_MAX]; -int16 COEUR_POS[ORIG_ANIM_MAX * 2]; +extern int16 anim_zoubida[ORIG_ANIM_MAX]; +extern int16 anim_moktar[ORIG_ANIM_MAX]; +extern int16 anim_smoke[ORIG_ANIM_MAX]; +extern int16 COEUR_POS[ORIG_ANIM_MAX * 2]; -uint8 object_maxspeedY[ORIG_OBJECT_COUNT]; -bool object_support[ORIG_OBJECT_COUNT]; //not support/support -bool object_bounce[ORIG_OBJECT_COUNT]; //not bounce/bounce against floor + player bounces (ball, all spring, yellow stone, squeezed ball, skateboard) -bool object_gravity[ORIG_OBJECT_COUNT]; //no gravity on throw/gravity (ball, all carpet, trolley, squeezed ball, garbage, grey stone, scooter, yellow bricks between the statues, skateboard, cage) -bool object_droptobottom[ORIG_OBJECT_COUNT]; //on drop, lands on ground/continue below ground(cave spikes, rolling rock, ambolt, safe, dead man with helicopter) -bool object_no_damage[ORIG_OBJECT_COUNT]; //weapon/not weapon(cage) +extern uint8 object_maxspeedY[ORIG_OBJECT_COUNT]; +extern bool object_support[ORIG_OBJECT_COUNT]; //not support/support +extern bool object_bounce[ORIG_OBJECT_COUNT]; //not bounce/bounce against floor + player bounces (ball, all spring, yellow stone, squeezed ball, skateboard) +extern bool object_gravity[ORIG_OBJECT_COUNT]; //no gravity on throw/gravity (ball, all carpet, trolley, squeezed ball, garbage, grey stone, scooter, yellow bricks between the statues, skateboard, cage) +extern bool object_droptobottom[ORIG_OBJECT_COUNT]; //on drop, lands on ground/continue below ground(cave spikes, rolling rock, ambolt, safe, dead man with helicopter) +extern bool object_no_damage[ORIG_OBJECT_COUNT]; //weapon/not weapon(cage) #endif diff --git a/include/player.h b/include/player.h index fc8a5cd..497ee9d 100644 --- a/include/player.h +++ b/include/player.h @@ -32,9 +32,35 @@ #include "SDL/SDL.h" #include "level.h" +extern uint8 RESETLEVEL_FLAG; +extern uint8 BAR_FLAG; //timer for health bar +extern bool X_FLAG; //true if left or right key is pressed +extern bool Y_FLAG; //true if up or down key is pressed +extern uint8 CHOC_FLAG; //headache timer +extern uint8 action; //player sprite array +extern uint8 KICK_FLAG; //hit/burn timer +extern bool GRANDBRULE_FLAG; //If set, player will be "burned" when hit (fireballs) +extern bool LADDER_FLAG; //True if in a ladder +extern bool PRIER_FLAG; //True if player is forced into kneestanding because of low ceiling +extern uint8 SAUT_FLAG; //6 if free fall or in the middle of a jump, decremented if on solid surface. Must be 0 to initiate a jump. +extern uint8 LAST_ORDER; //Last action (kneestand + jump = silent walk) +extern uint8 FURTIF_FLAG; //Silent walk timer +extern bool DROP_FLAG; //True if an object is throwed forward +extern bool DROPREADY_FLAG; +extern bool CARRY_FLAG; //true if carrying something (add 16 to player sprite) +extern bool POSEREADY_FLAG; +extern uint8 ACTION_TIMER; //Frames since last action change +extern uint8 CROSS_FLAG; //When non-zero, fall through certain floors (after key down) +extern uint8 FUME_FLAG; //Smoke when object hits the floor +extern Uint8 *keystate; //Keyboard state +extern uint8 YFALL; +extern bool POCKET_FLAG; +extern int8 SENSX; //1: walk right, 0: stand still, -1: walk left, triggers the ACTION_TIMER if it changes +extern uint8 SAUT_COUNT; //Incremented from 0 to 3 when accelerating while jumping, stop acceleration upwards if >= 3 + int move_player(TITUS_level *level); TITUS_object *FORCE_POSE(TITUS_level *level); - +void DEC_ENERGY(TITUS_level *level); #endif diff --git a/include/reset.h b/include/reset.h index 26e0368..8280de1 100644 --- a/include/reset.h +++ b/include/reset.h @@ -32,8 +32,11 @@ #include "SDL/SDL.h" #include "level.h" +extern bool NEWLEVEL_FLAG; + int INIT_SCREENM(TITUS_level *level); int CLEAR_DATA(TITUS_level *level); +uint8 RESET_LEVEL(TITUS_level *level); #endif diff --git a/include/scroll.h b/include/scroll.h index d70a07a..7be0cf0 100644 --- a/include/scroll.h +++ b/include/scroll.h @@ -31,8 +31,24 @@ #include "SDL/SDL.h" +extern bool PERMUT_FLAG; //If false, there are no animated tiles on the screen? +extern uint8 loop_cycle; //Increased every loop in game loop +extern uint8 tile_anim; //Current tile animation (0-1-2), changed every 4th game loop cycle +extern uint8 BITMAP_X; //Screen offset (X) in tiles +extern uint8 BITMAP_XM; //Point to the left tile in the tile screen (0 to 19) +extern uint8 BITMAP_Y; //Screen offset (Y) in tiles +extern uint8 BITMAP_YM; //Point to the top tile in the tile screen (0 to 11) +extern bool XSCROLL_CENTER; //If true, the screen will scroll in X +extern int16 XLIMIT_SCROLL; //If scrolling: scroll until player is in this tile (X) +extern bool YSCROLL_CENTER; //If true, the screen will scroll in Y +extern uint8 YLIMIT_SCROLL; //If scrolling: scroll until player is in this tile (Y) + int scroll(TITUS_level *level); int DISPLAY_CHAR(TITUS_level *level, uint8 tile, uint8 y, uint8 x); +bool L_SCROLL(TITUS_level *level); +bool R_SCROLL(TITUS_level *level); +bool U_SCROLL(TITUS_level *level); +bool D_SCROLL(TITUS_level *level); #endif diff --git a/include/settings.h b/include/settings.h index 7f3fcba..6a1214a 100644 --- a/include/settings.h +++ b/include/settings.h @@ -45,38 +45,38 @@ int initcodes(); int initleveltitles(); -char spritefile[256]; -char levelfiles[16][256]; //16 levels in moktar, 15 levels in titus -char tituslogofile[256]; -int tituslogoformat; -char titusintrofile[256]; -int titusintroformat; -char titusmenufile[256]; -int titusmenuformat; -char titusfinishfile[256]; -int titusfinishformat; -char fontfile[256]; -int levelcount; -int devmode; -int reswidth; -int resheight; -int bitdepth; -int ingamewidth; -int ingameheight; -int videomode; -int game; +extern char spritefile[256]; +extern char levelfiles[16][256]; //16 levels in moktar, 15 levels in titus +extern char tituslogofile[256]; +extern int tituslogoformat; +extern char titusintrofile[256]; +extern int titusintroformat; +extern char titusmenufile[256]; +extern int titusmenuformat; +extern char titusfinishfile[256]; +extern int titusfinishformat; +extern char fontfile[256]; +extern int levelcount; +extern int devmode; +extern int reswidth; +extern int resheight; +extern int bitdepth; +extern int ingamewidth; +extern int ingameheight; +extern int videomode; +extern int game; -char levelcode[16][5]; -char leveltitle[16][41]; +extern char levelcode[16][5]; +extern char leveltitle[16][41]; -char moduleintrofile[256]; //.mod file -int moduleintrofileloop; //loop info -char moduleprelevelfile[256]; -int moduleprelevelfileloop; -char modulelevelfile[6][256]; //6 different level files -int modulelevelfileloop[6]; -char modulegameoverfile[256]; -int modulegameoverfileloop; -char modulelevel[16]; //Link to modulelevelfiles +extern char moduleintrofile[256]; //.mod file +extern int moduleintrofileloop; //loop info +extern char moduleprelevelfile[256]; +extern int moduleprelevelfileloop; +extern char modulelevelfile[6][256]; //6 different level files +extern int modulelevelfileloop[6]; +extern char modulegameoverfile[256]; +extern int modulegameoverfileloop; +extern char modulelevel[16]; //Link to modulelevelfiles #endif diff --git a/include/sprites.h b/include/sprites.h index a8fcfcc..0225f57 100644 --- a/include/sprites.h +++ b/include/sprites.h @@ -43,6 +43,7 @@ int updatesprite(TITUS_level *level, TITUS_sprite *spr, int16 number, bool clear int copysprite(TITUS_level *level, TITUS_sprite *dest, TITUS_sprite *src); int initspritecache(TITUS_spritecache *spritecache, uint16 count, uint16 tmpcount); int freespritecache(TITUS_spritecache *spritecache); +void SPRITES_ANIMATION(TITUS_level *level); #endif diff --git a/include/tile_animation.h b/include/tile_animation.h new file mode 100644 index 0000000..1b53755 --- /dev/null +++ b/include/tile_animation.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2008 - 2011 The OpenTitus team + * + * Authors: + * Eirik Stople + * + * "Titus the Fox: To Marrakech and Back" (1992) and + * "Lagaf': Les Aventures de Moktar - Vol 1: La Zoubida" (1991) + * was developed by, and is probably copyrighted by Titus Software, + * which, according to Wikipedia, stopped buisness in 2005. + * + * OpenTitus is not affiliated with Titus Software. + * + * OpenTitus is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 3 of the License, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ +#ifndef TILE_ANIMATION +#define TILE_ANIMATION + +void BLOC_ANIMATION(TITUS_level *level); +#endif diff --git a/include/tituserror.h b/include/tituserror.h index 687ce25..f069144 100644 --- a/include/tituserror.h +++ b/include/tituserror.h @@ -36,8 +36,8 @@ #define TITUS_ERROR_SDL_ERROR -5 #define TITUS_ERROR_AUDIO_ERROR -6 #define TITUS_ERROR_INVALID_UTF8 -4 -char lasterror[200]; -int lasterrornr; //Only to be used when needed, f.ex. when return value is not int (f.ex. in function SDL_Text) (maybe this always should be used?) +extern char lasterror[200]; +extern int lasterrornr; //Only to be used when needed, f.ex. when return value is not int (f.ex. in function SDL_Text) (maybe this always should be used?) void checkerror(void); #endif diff --git a/opentitus.c b/opentitus.c index 9ed5d0d..b054461 100644 --- a/opentitus.c +++ b/opentitus.c @@ -66,64 +66,8 @@ #include "original.h" #include "objects.h" -int main(int argc, char *argv[]) { - - int retval; - int state = 1; //View the menu when the main loop starts - retval = init(); - if (retval < 0) - state = 0; - - if (state) { - retval = viewintrotext(); - if (retval < 0) - state = 0; - } - - if (state) { - retval = viewimage(tituslogofile, tituslogoformat, 0, 4000); - if (retval < 0) - state = 0; - } - -#ifdef AUDIO_ENABLED - SELECT_MUSIC(15); -#endif - - if (state) { - retval = viewimage(titusintrofile, titusintroformat, 0, 6500); - if (retval < 0) - state = 0; - } - - while (state) { - retval = viewmenu(titusmenufile, titusmenuformat); - - if (retval <= 0) - state = 0; - - if (state && (retval <= levelcount)) { - retval = playtitus(retval - 1); - if (retval < 0) - state = 0; - } - } - - freefonts(); - -#ifdef AUDIO_ENABLED - freeaudio(); -#endif - - SDL_Quit(); - - checkerror(); - - if (retval == -1) - retval = 0; - - return retval; -} +char lasterror[200]; +int lasterrornr; //Only to be used when needed, f.ex. when return value is not int (f.ex. in function SDL_Text) (maybe this always should be used?) int init() { @@ -208,6 +152,65 @@ int init() { } +int main(int argc, char *argv[]) { + + int retval; + int state = 1; //View the menu when the main loop starts + retval = init(); + if (retval < 0) + state = 0; + + if (state) { + retval = viewintrotext(); + if (retval < 0) + state = 0; + } + + if (state) { + retval = viewimage(tituslogofile, tituslogoformat, 0, 4000); + if (retval < 0) + state = 0; + } + +#ifdef AUDIO_ENABLED + SELECT_MUSIC(15); +#endif + + if (state) { + retval = viewimage(titusintrofile, titusintroformat, 0, 6500); + if (retval < 0) + state = 0; + } + + while (state) { + retval = viewmenu(titusmenufile, titusmenuformat); + + if (retval <= 0) + state = 0; + + if (state && (retval <= levelcount)) { + retval = playtitus(retval - 1); + if (retval < 0) + state = 0; + } + } + + freefonts(); + +#ifdef AUDIO_ENABLED + freeaudio(); +#endif + + SDL_Quit(); + + checkerror(); + + if (retval == -1) + retval = 0; + + return retval; +} + void checkerror(void) { printf("%s\n", lasterror); } diff --git a/src/audio.c b/src/audio.c index 275426b..ce44434 100644 --- a/src/audio.c +++ b/src/audio.c @@ -35,6 +35,7 @@ #include "tituserror.h" #include "opl.h" #include "common.h" +#include "player.h" #define ADLIB_DATA_COUNT 10 @@ -50,6 +51,7 @@ #define ADLIB_PORT 0x388 +uint8_t AUDIOMODE; char playing; int rate; @@ -132,7 +134,6 @@ int SELECT_MUSIC(int song_number); void all_vox_zero(); void TimerCallback(void *data); -int FX_DRIVER(); int FX_STOP(); void updatechip(int reg, int val) @@ -140,6 +141,21 @@ void updatechip(int reg, int val) OPL_WriteRegister(reg, val); } +void FX_DRIVER() { + ADLIB_DATA *aad = &(sdl_player_data.aad); + if (!FX_ON) return; + updatechip(0xBD, 0xEF & aad->perc_stat); + updatechip(0xA6, 0x57); + updatechip(0xB6, 1); + updatechip(0xB6, 5); + updatechip(0xBD, 0x10 | aad->perc_stat); + FX_TIME--; + if (FX_TIME == 0) { + FX_STOP(); + } + return; +} + int fillchip(ADLIB_DATA *aad) { int i; @@ -552,14 +568,14 @@ int startmusic() { return 0; } -int refreshaudio() { +void refreshaudio() { if (AUDIOMODE != 1) { return; } int tick = SDL_GetTicks(); if (tick - lastaudiotick < audiodelay) { - return 0; + return; } //Update the chip! lastaudiotick += audiodelay; @@ -570,7 +586,30 @@ int refreshaudio() { audiodelay--; } sdl_player_data.playing = fillchip(&(sdl_player_data.aad)); - return 0; + return; +} + +int initsfx() { + ADLIB_DATA *aad = &(sdl_player_data.aad); + unsigned char *raw_data = aad->data; + FX_ON = false; + FX_TIME = 0; + uint16 tmp1; + int i, k; + + tmp1 = SFX_OFFSET; + + for (i = 0; i < ADLIB_SFX_COUNT; i++) { + for (k = 0; k < 5; k++) + aad->sfx[i].op[0][k] = raw_data[tmp1++]; + + for (k = 0; k < 5; k++) + aad->sfx[i].op[1][k] = raw_data[tmp1++]; + + aad->sfx[i].fb_alg = raw_data[tmp1++]; + } + + return 0; } int initaudio(){ @@ -644,7 +683,7 @@ int initaudio(){ return 0; } -int freeaudio(){ +void freeaudio(){ free (sdl_player_data.aad.data); OPL_Shutdown(); @@ -653,30 +692,7 @@ int freeaudio(){ SDL_CloseAudio(); - return 0; -} - -int initsfx() { - ADLIB_DATA *aad = &(sdl_player_data.aad); - unsigned char *raw_data = aad->data; - FX_ON = false; - FX_TIME = 0; - uint16 tmp1; - int i, k; - - tmp1 = SFX_OFFSET; - - for (i = 0; i < ADLIB_SFX_COUNT; i++) { - for (k = 0; k < 5; k++) - aad->sfx[i].op[0][k] = raw_data[tmp1++]; - - for (k = 0; k < 5; k++) - aad->sfx[i].op[1][k] = raw_data[tmp1++]; - - aad->sfx[i].fb_alg = raw_data[tmp1++]; - } - - return 0; + return; } int WAIT_SONG(){ @@ -724,21 +740,6 @@ int FX_START(int fx_number){ return 0; } -int FX_DRIVER() { - ADLIB_DATA *aad = &(sdl_player_data.aad); - if (!FX_ON) return; - updatechip(0xBD, 0xEF & aad->perc_stat); - updatechip(0xA6, 0x57); - updatechip(0xB6, 1); - updatechip(0xB6, 5); - updatechip(0xBD, 0x10 | aad->perc_stat); - FX_TIME--; - if (FX_TIME == 0) { - FX_STOP(); - } - return 0; -} - int FX_STOP() { unsigned char tmpins1[] = {0xF5, 0x7F, 0x00, 0x11, 0x00}; unsigned char tmpins2[] = {0xF8, 0xFF, 0x04, 0x30, 0x00}; diff --git a/src/draw.c b/src/draw.c index c3ea8fb..a4d72fd 100644 --- a/src/draw.c +++ b/src/draw.c @@ -46,6 +46,20 @@ #include "common.h" #include "tituserror.h" #include "original.h" +#include "scroll.h" +#include "player.h" +#include "audio.h" +#include "gates.h" +#include "keyboard.h" +#include "fonts.h" + +bool DISPLAYLOOPTIME; //If true, display loop time in milliseconds +static uint8_t LOOPTIME; //Loop time +static uint8_t SUBTIME[16]; //Sub time +static uint16_t FPS; //Frames pr second +static uint16_t FPS_LAST; //Frames pr second +static uint16_t LAST_CLOCK_CORR; //Correction to LAST_CLOCK +static int LAST_CLOCK; //Used for fixed framerate SDL_Surface *sprite_from_cache(TITUS_level *level, TITUS_sprite *spr); @@ -114,71 +128,7 @@ int TFR_SCREENM() { //Draw tiles on the backbuffer (copy from the tile screen) SDL_BlitSurface(tilescreen, &src, screen, &dest); } - -//Loop through all sprites, and draw the sprites that should be visible on the screen (NOT by using the visible flag, it uses the coordinates) -//If the flash bit is set, the first 3 planes will be 0, the last plane will be normal (colour & 0x01, odd colors gets white, even colours gets black) - - -DISPLAY_SPRITES(TITUS_level *level) { - int16 i; - char buffer[7]; //xxx ms - - for (i = level->elevatorcount - 1; i >= 0; i--) { - display_sprite(level, &(level->elevator[i].sprite)); - } - - for (i = level->trashcount - 1; i >= 0; i--) { - display_sprite(level, &(level->trash[i])); - } - - for (i = level->enemycount - 1; i >= 0; i--) { - display_sprite(level, &(level->enemy[i].sprite)); - } - - for (i = level->objectcount - 1; i >= 0; i--) { - display_sprite(level, &(level->object[i].sprite)); - } - - display_sprite(level, &(level->player.sprite3)); - display_sprite(level, &(level->player.sprite2)); - display_sprite(level, &(level->player.sprite)); - - if (GODMODE) { - SDL_Print_Text("GODMODE", 30 * 8, 0 * 12); - } - if (NOCLIP) { - SDL_Print_Text("NOCLIP", 30 * 8, 1 * 12); - } - -#ifdef DEBUG_VERSION - if (DISPLAYLOOPTIME) { - sprintf(buffer, "%3u ms", LOOPTIME); - SDL_Print_Text(buffer, 30 * 8, 2 * 12); //Loop time in ms - - sprintf(buffer, "FPS %u", FPS_LAST); - SDL_Print_Text(buffer, 30 * 8, 4 * 12); //Last second's FPS count - - sprintf(buffer, "CL %d", LAST_CLOCK); - SDL_Print_Text(buffer, 30 * 8, 6 * 12); //Clock - - sprintf(buffer, "CORR %d", LAST_CLOCK_CORR); - SDL_Print_Text(buffer, 30 * 8, 8 * 12); //Correction to the clock - - - for (i = 0; i <= 15; i++) { - sprintf(buffer, "%d %3u", i, SUBTIME[i]); - SDL_Print_Text(buffer, 0 * 8, i * 12); //Sub times from main loop in ms - } - - sprintf(buffer, "%d %3u", i, SUBTIME[i]); - SDL_Print_Text(buffer, 0 * 8, i * 12); - } - -#endif - -} - -display_sprite(TITUS_level *level, TITUS_sprite *spr) { +void display_sprite(TITUS_level *level, TITUS_sprite *spr) { SDL_Surface *image; SDL_Rect src, dest; if (!spr->enabled) { @@ -248,6 +198,68 @@ display_sprite(TITUS_level *level, TITUS_sprite *spr) { } +//Loop through all sprites, and draw the sprites that should be visible on the screen (NOT by using the visible flag, it uses the coordinates) +//If the flash bit is set, the first 3 planes will be 0, the last plane will be normal (colour & 0x01, odd colors gets white, even colours gets black) + +void DISPLAY_SPRITES(TITUS_level *level) { + int16 i; + char buffer[7]; //xxx ms + + for (i = level->elevatorcount - 1; i >= 0; i--) { + display_sprite(level, &(level->elevator[i].sprite)); + } + + for (i = level->trashcount - 1; i >= 0; i--) { + display_sprite(level, &(level->trash[i])); + } + + for (i = level->enemycount - 1; i >= 0; i--) { + display_sprite(level, &(level->enemy[i].sprite)); + } + + for (i = level->objectcount - 1; i >= 0; i--) { + display_sprite(level, &(level->object[i].sprite)); + } + + display_sprite(level, &(level->player.sprite3)); + display_sprite(level, &(level->player.sprite2)); + display_sprite(level, &(level->player.sprite)); + + if (GODMODE) { + SDL_Print_Text("GODMODE", 30 * 8, 0 * 12); + } + if (NOCLIP) { + SDL_Print_Text("NOCLIP", 30 * 8, 1 * 12); + } + +#ifdef DEBUG_VERSION + if (DISPLAYLOOPTIME) { + sprintf(buffer, "%3u ms", LOOPTIME); + SDL_Print_Text(buffer, 30 * 8, 2 * 12); //Loop time in ms + + sprintf(buffer, "FPS %u", FPS_LAST); + SDL_Print_Text(buffer, 30 * 8, 4 * 12); //Last second's FPS count + + sprintf(buffer, "CL %d", LAST_CLOCK); + SDL_Print_Text(buffer, 30 * 8, 6 * 12); //Clock + + sprintf(buffer, "CORR %d", LAST_CLOCK_CORR); + SDL_Print_Text(buffer, 30 * 8, 8 * 12); //Correction to the clock + + + for (i = 0; i <= 15; i++) { + sprintf(buffer, "%d %3u", i, SUBTIME[i]); + SDL_Print_Text(buffer, 0 * 8, i * 12); //Sub times from main loop in ms + } + + sprintf(buffer, "%d %3u", i, SUBTIME[i]); + SDL_Print_Text(buffer, 0 * 8, i * 12); + } + +#endif + +} + SDL_Surface *sprite_from_cache(TITUS_level *level, TITUS_sprite *spr) { TITUS_spritecache *cache = level->spritecache; TITUS_spritedata *spritedata = level->spritedata[spr->number]; @@ -298,53 +310,7 @@ SDL_Surface *sprite_from_cache(TITUS_level *level, TITUS_sprite *spr) { } } - -int flip_screen(bool slow) { - int tick = SDL_GetTicks(); - SDL_Flip(screen); - int oldtick = tick; - tick = SDL_GetTicks(); - SUBTIME[14] = tick - oldtick; - - //if (slow) { - NO_FAST_CPU(slow); //TODO: - //} -} - -/* -NO_FAST_CPU(bool slow) { - int tick, duration, delay, tick2; - tick = SDL_GetTicks(); - if (slow) { - delay = 29; //28.53612, fps: 70.09Hz/2 - } else { - delay = 10; - } - LOOPTIME = (tick - LAST_CLOCK); - delay = delay - (tick - LAST_CLOCK); - if ((delay < 0) || (delay > 40)) { - delay = 1; - } - SDL_Delay(delay); - //do { - //SDL_Delay(1); - // tick = SDL_GetTicks(); - // duration = abs(LAST_CLOCK - tick); - //} while (duration < delay); - tick2 = SDL_GetTicks(); - if ((tick2 / 1000) != (LAST_CLOCK / 1000)) { - FPS_LAST = FPS; - FPS = 0; - } - FPS++; - LAST_CLOCK_CORR = tick2 - tick - delay; - - LAST_CLOCK = tick2; - SUBTIME[15] = LAST_CLOCK - tick; -} -*/ - -NO_FAST_CPU(bool slow) { +void NO_FAST_CPU(bool slow) { int tick, duration, delay, tick2; tick = SDL_GetTicks(); if (slow) { @@ -402,7 +368,51 @@ NO_FAST_CPU(bool slow) { SUBTIME[15] = LAST_CLOCK - tick; } + +int flip_screen(bool slow) { + int tick = SDL_GetTicks(); + SDL_Flip(screen); + int oldtick = tick; + tick = SDL_GetTicks(); + SUBTIME[14] = tick - oldtick; + + //if (slow) { + NO_FAST_CPU(slow); //TODO: + //} +} +/* +NO_FAST_CPU(bool slow) { + int tick, duration, delay, tick2; + tick = SDL_GetTicks(); + if (slow) { + delay = 29; //28.53612, fps: 70.09Hz/2 + } else { + delay = 10; + } + LOOPTIME = (tick - LAST_CLOCK); + delay = delay - (tick - LAST_CLOCK); + if ((delay < 0) || (delay > 40)) { + delay = 1; + } + SDL_Delay(delay); + //do { + //SDL_Delay(1); + // tick = SDL_GetTicks(); + // duration = abs(LAST_CLOCK - tick); + //} while (duration < delay); + tick2 = SDL_GetTicks(); + if ((tick2 / 1000) != (LAST_CLOCK / 1000)) { + FPS_LAST = FPS; + FPS = 0; + } + FPS++; + LAST_CLOCK_CORR = tick2 - tick - delay; + + LAST_CLOCK = tick2; + SUBTIME[15] = LAST_CLOCK - tick; +} +*/ int viewstatus(TITUS_level *level, bool countbonus){ int retval, i, j; @@ -486,15 +496,7 @@ int INIT_SCREENM(TITUS_level *level) { } -int DISPLAY_COUNT(TITUS_level *level) { - subto0(&(BAR_FLAG)); - if (BAR_FLAG != 0) { - DISPLAY_ENERGY(level); - } -} - - -DISPLAY_ENERGY(TITUS_level *level) { +void DISPLAY_ENERGY(TITUS_level *level) { uint8 offset = 96; uint8 i; SDL_Rect dest; @@ -516,6 +518,14 @@ DISPLAY_ENERGY(TITUS_level *level) { } } +int DISPLAY_COUNT(TITUS_level *level) { + subto0(&(BAR_FLAG)); + if (BAR_FLAG != 0) { + DISPLAY_ENERGY(level); + } +} + + int fadeout() { SDL_Surface *image; int activedelay = 1; diff --git a/src/elevators.c b/src/elevators.c index 62410fb..058ff92 100644 --- a/src/elevators.c +++ b/src/elevators.c @@ -36,6 +36,16 @@ #include "globals.h" #include "definitions.h" #include "elevators.h" +#include "scroll.h" + +void MTSBR(TITUS_elevator *elevator) { + elevator->counter++; + if (elevator->counter >= elevator->range) { + elevator->counter = 0; + elevator->sprite.speedX = 0 - elevator->sprite.speedX; + elevator->sprite.speedY = 0 - elevator->sprite.speedY; + } +} int MOVE_TRP(TITUS_level *level) { TITUS_elevator *elevator = level->elevator; @@ -58,12 +68,3 @@ int MOVE_TRP(TITUS_level *level) { } } } - -MTSBR(TITUS_elevator *elevator) { - elevator->counter++; - if (elevator->counter >= elevator->range) { - elevator->counter = 0; - elevator->sprite.speedX = 0 - elevator->sprite.speedX; - elevator->sprite.speedY = 0 - elevator->sprite.speedY; - } -} diff --git a/src/enemies.c b/src/enemies.c index 1ca1cc4..08e4f72 100644 --- a/src/enemies.c +++ b/src/enemies.c @@ -41,12 +41,104 @@ #include "common.h" #include "player.h" #include "settings.h" +#include "engine.h" +#include "scroll.h" +#include "objects.h" +#include "audio.h" +#include "sprites.h" -int updateenemysprite(TITUS_level *level, TITUS_enemy *enemy, int16 number, bool clearflags); +uint8 INVULNERABLE_FLAG; //When non-zero, boss is invulnerable +uint8 TAUPE_FLAG; //Used for enemies walking and popping up +uint8 BIGNMI_POWER; //Lives of the boss +bool boss_alive; //True if the boss is alive bool NMI_VS_DROP(TITUS_sprite *enemysprite, TITUS_sprite *sprite); int KICK_ASH(TITUS_level *level, TITUS_sprite *enemysprite, int16 power); bool FIND_TRASH(TITUS_level *level, TITUS_sprite **trash); +void PUT_BULLET(TITUS_level *level, TITUS_enemy *enemy, TITUS_sprite *bullet) { + bullet->x = enemy->sprite.x; + bullet->y = enemy->sprite.y - (int8)(*(enemy->sprite.animation - 1) & 0x00FF); + updatesprite(level, bullet, (*(enemy->sprite.animation - 2) & 0x1FFF) + FIRST_OBJET, true); + if (enemy->sprite.x < level->player.sprite.x) { + bullet->speedX = 16*11; + bullet->flipped = true; + } else { + bullet->speedX = -16*11; + bullet->flipped = false; + } + bullet->speedY = 0; + bullet->x += bullet->speedX >> 4; +} + +void UP_ANIMATION(TITUS_sprite *sprite) { + do { + sprite->animation++; + } while (*sprite->animation >= 0); + sprite->animation++; +} + +void DOWN_ANIMATION(TITUS_sprite *sprite) { + do { + sprite->animation--; + } while (*sprite->animation >= 0); + sprite->animation--; +} + +void GAL_FORM(TITUS_level *level, TITUS_enemy *enemy) { //Enemy animation + int16 *image; + enemy->sprite.invisible = false; + if ((enemy->dying & 0x03) != 0) { + enemy->sprite.visible = false; + enemy->visible = true; + return; + } + enemy->trigger = false; + image = enemy->sprite.animation; //Animation pointer + while (*image < 0) { + image += (*image >> 1); //jump back to start of animation + } + if (*image == 0x55AA) { + enemy->sprite.invisible = true; + return; + } + enemy->trigger = *image & 0x2000; + updateenemysprite(level, enemy, (*image & 0x00FF) + FIRST_NMI, true); + enemy->sprite.flipped = (enemy->sprite.speedX < 0) ? true : false; + image++; + if (*image < 0) { + image += (*image >> 1); //jump back to start of animation + } + enemy->sprite.animation = image; + enemy->visible = true; +} + +void DEAD1(TITUS_level *level, TITUS_enemy *enemy) { + if (((enemy->dying & 0x01) != 0) || //00000001 or 00000011 + (enemy->dead_sprite == -1)) { + if ((enemy->dying & 0x01) == 0) { + enemy->dying = enemy->dying | 0x01; + enemy->sprite.speedY = -10; + enemy->phase = 0; + } + if (enemy->phase != 0xFF) { + enemy->sprite.y += enemy->sprite.speedY; + if (SEECHOC_FLAG != 0) { + level->player.sprite2.y += enemy->sprite.speedY; + } + if (enemy->sprite.speedY < MAX_SPEED_DEAD) { + enemy->sprite.speedY++; + } + } + } else { + enemy->dying = enemy->dying | 0x01; + updateenemysprite(level, enemy, enemy->dead_sprite, false); + enemy->sprite.flash = false; + enemy->sprite.visible = false; + enemy->sprite.speedY = 0; + enemy->phase = -1; + } +} + int MOVE_NMI(TITUS_level *level) { TITUS_sprite *bullet; int i, j; @@ -1006,33 +1098,6 @@ int MOVE_NMI(TITUS_level *level) { } //for (i = 0; i < NMI_BY_LEVEL; i++) } -DEAD1(TITUS_level *level, TITUS_enemy *enemy) { - if (((enemy->dying & 0x01) != 0) || //00000001 or 00000011 - (enemy->dead_sprite == -1)) { - if ((enemy->dying & 0x01) == 0) { - enemy->dying = enemy->dying | 0x01; - enemy->sprite.speedY = -10; - enemy->phase = 0; - } - if (enemy->phase != 0xFF) { - enemy->sprite.y += enemy->sprite.speedY; - if (SEECHOC_FLAG != 0) { - level->player.sprite2.y += enemy->sprite.speedY; - } - if (enemy->sprite.speedY < MAX_SPEED_DEAD) { - enemy->sprite.speedY++; - } - } - } else { - enemy->dying = enemy->dying | 0x01; - updateenemysprite(level, enemy, enemy->dead_sprite, false); - enemy->sprite.flash = false; - enemy->sprite.visible = false; - enemy->sprite.speedY = 0; - enemy->phase = -1; - } -} - int updateenemysprite(TITUS_level *level, TITUS_enemy *enemy, int16 number, bool clearflags){ updatesprite(level, &(enemy->sprite), number, clearflags); @@ -1084,6 +1149,48 @@ int updateenemysprite(TITUS_level *level, TITUS_enemy *enemy, int16 number, bool return (0); } +void SEE_CHOC(TITUS_level *level) { + updatesprite(level, &(level->player.sprite2), FIRST_OBJET + 15, true); //Hit (a throw hits an enemy) + level->player.sprite2.speedX = 0; + level->player.sprite2.speedY = 0; + SEECHOC_FLAG = 5; +} + +void ACTIONC_NMI(TITUS_level *level, TITUS_enemy *enemy) { + switch (enemy->type) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 18: + if (NMI_VS_DROP(&(enemy->sprite), &(level->player.sprite))) { + if (enemy->type != 11) { //Walk and shoot + if (enemy->sprite.number != 178) { //Periscope + enemy->sprite.speedX = 0 - enemy->sprite.speedX; + } + } + if ((enemy->sprite.number >= FIRST_NMI + 53) && + (enemy->sprite.number <= FIRST_NMI + 55)) { //Fireball + GRANDBRULE_FLAG = 1; + } + if (enemy->power != 0) { + KICK_ASH(level, &(enemy->sprite), enemy->power); + } + } + break; + } +} int SET_NMI(TITUS_level *level) { //Clear enemy sprites @@ -1182,72 +1289,6 @@ int SET_NMI(TITUS_level *level) { } -GAL_FORM(TITUS_level *level, TITUS_enemy *enemy) { //Enemy animation - int16 *image; - enemy->sprite.invisible = false; - if ((enemy->dying & 0x03) != 0) { - enemy->sprite.visible = false; - enemy->visible = true; - return; - } - enemy->trigger = false; - image = enemy->sprite.animation; //Animation pointer - while (*image < 0) { - image += (*image >> 1); //jump back to start of animation - } - if (*image == 0x55AA) { - enemy->sprite.invisible = true; - return; - } - enemy->trigger = *image & 0x2000; - updateenemysprite(level, enemy, (*image & 0x00FF) + FIRST_NMI, true); - enemy->sprite.flipped = (enemy->sprite.speedX < 0) ? true : false; - image++; - if (*image < 0) { - image += (*image >> 1); //jump back to start of animation - } - enemy->sprite.animation = image; - enemy->visible = true; -} - - -ACTIONC_NMI(TITUS_level *level, TITUS_enemy *enemy) { - switch (enemy->type) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 18: - if (NMI_VS_DROP(&(enemy->sprite), &(level->player.sprite))) { - if (enemy->type != 11) { //Walk and shoot - if (enemy->sprite.number != 178) { //Periscope - enemy->sprite.speedX = 0 - enemy->sprite.speedX; - } - } - if ((enemy->sprite.number >= FIRST_NMI + 53) && - (enemy->sprite.number <= FIRST_NMI + 55)) { //Fireball - GRANDBRULE_FLAG = 1; - } - if (enemy->power != 0) { - KICK_ASH(level, &(enemy->sprite), enemy->power); - } - } - break; - } -} - - int KICK_ASH(TITUS_level *level, TITUS_sprite *enemysprite, int16 power) { #ifdef AUDIO_ENABLED FX_START(4); @@ -1299,13 +1340,6 @@ bool NMI_VS_DROP(TITUS_sprite *enemysprite, TITUS_sprite *sprite) { } -SEE_CHOC(TITUS_level *level) { - updatesprite(level, &(level->player.sprite2), FIRST_OBJET + 15, true); //Hit (a throw hits an enemy) - level->player.sprite2.speedX = 0; - level->player.sprite2.speedY = 0; - SEECHOC_FLAG = 5; -} - int MOVE_TRASH(TITUS_level *level) { int16 i, tmp; for (i = 0; i < level->trashcount; i++) { @@ -1345,32 +1379,3 @@ bool FIND_TRASH(TITUS_level *level, TITUS_sprite **trash) { } return false; } - -PUT_BULLET(TITUS_level *level, TITUS_enemy *enemy, TITUS_sprite *bullet) { - bullet->x = enemy->sprite.x; - bullet->y = enemy->sprite.y - (int8)(*(enemy->sprite.animation - 1) & 0x00FF); - updatesprite(level, bullet, (*(enemy->sprite.animation - 2) & 0x1FFF) + FIRST_OBJET, true); - if (enemy->sprite.x < level->player.sprite.x) { - bullet->speedX = 16*11; - bullet->flipped = true; - } else { - bullet->speedX = -16*11; - bullet->flipped = false; - } - bullet->speedY = 0; - bullet->x += bullet->speedX >> 4; -} - -UP_ANIMATION(TITUS_sprite *sprite) { - do { - sprite->animation++; - } while (*sprite->animation >= 0); - sprite->animation++; -} - -DOWN_ANIMATION(TITUS_sprite *sprite) { - do { - sprite->animation--; - } while (*sprite->animation >= 0); - sprite->animation--; -} diff --git a/src/engine.c b/src/engine.c index 81515ba..6f8453d 100644 --- a/src/engine.c +++ b/src/engine.c @@ -50,6 +50,8 @@ #include "elevators.h" #include "objects.h" #include "enemies.h" +#include "tile_animation.h" +#include "viewimage.h" //Probably not the best way, but it works... #define HAVE_CONFIG_H 1 @@ -62,6 +64,10 @@ #include "audio.h" #endif +SDL_Surface *tilescreen; //Tile screen +bool GAMEOVER_FLAG; //triggers a game over +uint16 IMAGE_COUNTER; //Increased every loop in game loop (0 to 0x0FFF) + static int playlevel(TITUS_level *level); static int displaylevel(TITUS_level *level); static int movescreen(TITUS_level *level); @@ -71,6 +77,95 @@ static int collision_detection_player(TITUS_level *level); static int getpolarity(int number); int gettick(int *tick, uint8 index); +int SCREEN_5C() { + uint16 key; + int retval; + if (keystate[SDLK_LCTRL] && //LCtrl + keystate[SDLK_LALT] && //LAlt + keystate[SDLK_e]) { //E + for (key = SDLK_FIRST; key <= SDLK_LAST; key++) { + if (key == SDLK_LCTRL) continue; + if (key == SDLK_LALT) continue; + if (key == SDLK_e) continue; + if (keystate[key]) return 0; + } + if (game == 0) { //Titus + retval = viewimage(titusfinishfile, titusfinishformat, 1, 0); + if (retval < 0) + return retval; + } +#ifdef AUDIO_ENABLED + SELECT_MUSIC(9); +#endif + } + + return 0; +} + +int gameover(TITUS_level *level) { + TITUS_player *player = &(level->player); + int i, retval; +#ifdef AUDIO_ENABLED + SELECT_MUSIC(2); +#endif + updatesprite(level, &(player->sprite), 13, true); //Death + updatesprite(level, &(player->sprite2), 333, true); //Game + player->sprite2.x = (BITMAP_X << 4) - (120-2); + player->sprite2.y = (BITMAP_Y << 4) + 100; + //over + updatesprite(level, &(player->sprite3), 334, true); //Over + player->sprite3.x = (BITMAP_X << 4) + (320+120-2); + player->sprite3.y = (BITMAP_Y << 4) + 100; + for (i = 0; i < 31; i++) { + TFR_SCREENM(); + DISPLAY_SPRITES(level); + flip_screen(true); + player->sprite2.x += 8; + player->sprite3.x -= 8; + } + SCREEN_5C(); //Secret: display picture if LCtrl+LAlt+E is pressed + retval = waitforbutton(); + if (retval < 0) + return retval; + + fadeout(); +} + +int death(TITUS_level *level) { + TITUS_player *player = &(level->player); + int i; +#ifdef AUDIO_ENABLED + SELECT_MUSIC(1); +#endif + FORCE_POSE(level); + updatesprite(level, &(player->sprite), 13, true); //Death + player->sprite.speedY = 15; + for (i = 0; i < 60; i++) { + TFR_SCREENM(); + //TODO! GRAVITY(); + DISPLAY_SPRITES(level); + flip_screen(true); + player->sprite.speedY--; + if (player->sprite.speedY < -16) { + player->sprite.speedY = -16; + } + player->sprite.y -= player->sprite.speedY; + } + +#ifdef AUDIO_ENABLED + WAIT_SONG(); + SELECT_MUSIC(0); +#endif + + /* TODO: remove because REPLACED + SCREEN_1(); + //TODO: SELECT_MUSIC(LEVEL_MUSIC[FNAMEB]); + INIT_SCREENM(level); + return 3; //Do not break main loop + */ + CLOSE_SCREEN(); +} + int playtitus(int firstlevel){ int startx, starty; int retval; @@ -374,90 +469,3 @@ static int getpolarity(int number){ return (1); return (0); } - -int death(TITUS_level *level) { - TITUS_player *player = &(level->player); - int i; -#ifdef AUDIO_ENABLED - SELECT_MUSIC(1); -#endif - FORCE_POSE(level); - updatesprite(level, &(player->sprite), 13, true); //Death - player->sprite.speedY = 15; - for (i = 0; i < 60; i++) { - TFR_SCREENM(); - //TODO! GRAVITY(); - DISPLAY_SPRITES(level); - flip_screen(true); - player->sprite.speedY--; - if (player->sprite.speedY < -16) { - player->sprite.speedY = -16; - } - player->sprite.y -= player->sprite.speedY; - } - -#ifdef AUDIO_ENABLED - WAIT_SONG(); - SELECT_MUSIC(0); -#endif - - /* TODO: remove because REPLACED - SCREEN_1(); - //TODO: SELECT_MUSIC(LEVEL_MUSIC[FNAMEB]); - INIT_SCREENM(level); - return 3; //Do not break main loop - */ - CLOSE_SCREEN(); -} - -int gameover(TITUS_level *level) { - TITUS_player *player = &(level->player); - int i, retval; -#ifdef AUDIO_ENABLED - SELECT_MUSIC(2); -#endif - updatesprite(level, &(player->sprite), 13, true); //Death - updatesprite(level, &(player->sprite2), 333, true); //Game - player->sprite2.x = (BITMAP_X << 4) - (120-2); - player->sprite2.y = (BITMAP_Y << 4) + 100; - //over - updatesprite(level, &(player->sprite3), 334, true); //Over - player->sprite3.x = (BITMAP_X << 4) + (320+120-2); - player->sprite3.y = (BITMAP_Y << 4) + 100; - for (i = 0; i < 31; i++) { - TFR_SCREENM(); - DISPLAY_SPRITES(level); - flip_screen(true); - player->sprite2.x += 8; - player->sprite3.x -= 8; - } - SCREEN_5C(); //Secret: display picture if LCtrl+LAlt+E is pressed - retval = waitforbutton(); - if (retval < 0) - return retval; - - fadeout(); -} - -int SCREEN_5C() { - uint16 key; - int retval; - if (keystate[SDLK_LCTRL] && //LCtrl - keystate[SDLK_LALT] && //LAlt - keystate[SDLK_e]) { //E - for (key = SDLK_FIRST; key <= SDLK_LAST; key++) { - if (key == SDLK_LCTRL) continue; - if (key == SDLK_LALT) continue; - if (key == SDLK_e) continue; - if (keystate[key]) return; - } - if (game == 0) { //Titus - retval = viewimage(titusfinishfile, titusfinishformat, 1, 0); - if (retval < 0) - return retval; - } -#ifdef AUDIO_ENABLED - SELECT_MUSIC(9); -#endif - } -} diff --git a/src/fonts.c b/src/fonts.c index d1b08f0..214b582 100644 --- a/src/fonts.c +++ b/src/fonts.c @@ -38,6 +38,10 @@ #include "keyboard.h" #include "draw.h" #include +#include "sprites.h" + +TITUS_font *font; //Malloced +SDL_Surface *font_undefined; //Pointer SDL_Surface * SDL_LoadChar(unsigned char * fontdata, int offset, SDL_PixelFormat * pixelformat); int freesubfont(TITUS_font *f_sub); diff --git a/src/gates.c b/src/gates.c index 251cec9..ec7e4c7 100644 --- a/src/gates.c +++ b/src/gates.c @@ -33,43 +33,19 @@ #include "backbuffer.h" #include "sprites.h" #include "settings.h" +#include "draw.h" +#include "gates.h" +#include "scroll.h" +#include "audio.h" +#include "reset.h" +#include "level.h" +#include "player.h" -int copytiles(int16 destX, int16 destY, int16 width, int16 height); +int16 XLIMIT; //The engine will not scroll past this tile before the player have crossed the line (X) -int CROSSING_GATE(TITUS_level *level) { //Check and handle level completion, and if the player does a kneestand on a secret entrance - check_finish(level); - check_gates(level); -} - - -check_finish(TITUS_level *level) { - TITUS_player *player = &(level->player); - if (boss_alive) { //There is still a boss that needs to be killed! - return; - } - if (level->levelid == 9) { //The level with a cage - if ((level->player.sprite2.number != FIRST_OBJET + 26) && - (level->player.sprite2.number != FIRST_OBJET + 27)) { - return; - } - } - if (((player->sprite.x & 0xFFF0) != level->finishX) && - ((player->sprite.x & 0xFFF0) - 16 != level->finishX)) { - return; - } - if (((player->sprite.y & 0xFFF0) != level->finishY) && - ((player->sprite.y & 0xFFF0) - 16 != level->finishY)) { - return; - } -#ifdef AUDIO_ENABLED - SELECT_MUSIC(4); - WAIT_SONG(); -#endif - CLOSE_SCREEN(); - NEWLEVEL_FLAG = true; -} +int copytiles(int16 destX, int16 destY, int16 width, int16 height); -check_gates(TITUS_level *level) { +void check_gates(TITUS_level *level) { TITUS_player *player = &(level->player); uint8 i; if ((CROSS_FLAG == 0) || //not kneestanding @@ -110,6 +86,39 @@ check_gates(TITUS_level *level) { OPEN_SCREEN(); } +void check_finish(TITUS_level *level) { + TITUS_player *player = &(level->player); + if (boss_alive) { //There is still a boss that needs to be killed! + return; + } + if (level->levelid == 9) { //The level with a cage + if ((level->player.sprite2.number != FIRST_OBJET + 26) && + (level->player.sprite2.number != FIRST_OBJET + 27)) { + return; + } + } + if (((player->sprite.x & 0xFFF0) != level->finishX) && + ((player->sprite.x & 0xFFF0) - 16 != level->finishX)) { + return; + } + if (((player->sprite.y & 0xFFF0) != level->finishY) && + ((player->sprite.y & 0xFFF0) - 16 != level->finishY)) { + return; + } +#ifdef AUDIO_ENABLED + SELECT_MUSIC(4); + WAIT_SONG(); +#endif + CLOSE_SCREEN(); + NEWLEVEL_FLAG = true; +} + +int CROSSING_GATE(TITUS_level *level) { //Check and handle level completion, and if the player does a kneestand on a secret entrance + check_finish(level); + check_gates(level); +} + + int CLOSE_SCREEN() { SDL_Rect dest; diff --git a/src/level.c b/src/level.c index f2aa0d7..9ac1057 100644 --- a/src/level.c +++ b/src/level.c @@ -40,7 +40,10 @@ #include "sprites.h" #include "level.h" #include "globals.h" +#include "gates.h" +#include "scroll.h" +uint8 ALTITUDE_ZERO; //The engine will not scroll below this tile before the player have gone below (Y) unsigned int loaduint16(unsigned char c1, unsigned char c2); int loadint16(unsigned char c1, unsigned char c2); diff --git a/src/menu.c b/src/menu.c index 9d5ae04..d9cfd35 100644 --- a/src/menu.c +++ b/src/menu.c @@ -38,6 +38,7 @@ #include "audio.h" #include "globals.h" #include "common.h" +#include "keyboard.h" //Probably not the best way, but it works... #define HAVE_CONFIG_H 1 @@ -50,6 +51,142 @@ #include "audio.h" #endif +SDL_Surface *screen; //Backbuffer + +int enterpassword(){ + int retval; + char code[] = "____"; + int i; + SDL_Event event; + char tmpchar; + + SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0)); + SDL_Flip(screen); + + SDL_Print_Text("CODE", 111, 80); + +#ifdef _DINGUX + int index = 0; + int counter = 0; +#endif + + for (i = 0; i < 4; ) { + while(SDL_PollEvent(&event)) { //Check all events + if (event.type == SDL_QUIT) { + return (-1); + } + + if (event.type == SDL_KEYDOWN) { + if (event.key.keysym.sym == SDLK_ESCAPE) { + return (-1); + } +#ifdef _DINGUX + if (event.key.keysym.sym == KEY_UP) { + index++; + if (index > 15) { + index = 0; + } + } else if (event.key.keysym.sym == KEY_DOWN) { + index--; + if (index < 0) { + index = 15; + } + } else if (event.key.keysym.sym == KEY_SPACE) { + if (index < 10) { + code[i] = index + CHAR_0; + } else { + code[i] = index - 10 + CHAR_A; + } + i++; + index = 0; + } +#else + + if ((event.key.keysym.unicode & 0xFF80) == 0) { + tmpchar = (char)(event.key.keysym.unicode & 0x007F); + + if ((tmpchar >= CHAR_0) && (tmpchar <= CHAR_9)) + code[i++] = tmpchar; + + if ((tmpchar >= CHAR_a) && (tmpchar <= CHAR_f)) + tmpchar -= (CHAR_a - CHAR_A); + + if ((tmpchar >= CHAR_A) && (tmpchar <= CHAR_F)) + code[i++] = tmpchar; + + } +#endif + +#ifdef AUDIO_ENABLED + if (event.key.keysym.sym == KEY_MUSIC) { + AUDIOMODE++; + if (AUDIOMODE > 1) { + AUDIOMODE = 0; + } + if (AUDIOMODE == 1) { + startmusic(); + } + } +#endif + } + } +#ifdef _DINGUX + if (i < 4) { + counter++; + if (counter > 10) { + counter = 0; + } else if (counter > 5) { + code[i] = *"_"; + } else { + if (index < 10) { + code[i] = index + CHAR_0; + } else { + code[i] = index - 10 + CHAR_A; + } + } + } +#endif + SDL_Print_Text(code, 159, 80); + SDL_Flip(screen); + titus_sleep(); + +#ifdef AUDIO_MIKMOD_SINGLETHREAD + checkmodule(); +#endif + +#ifdef AUDIO_SDL_MIXER + checkaudio(); +#endif + + } + + for (i = 0; i < levelcount; i++) { + if (strcmp (code, levelcode[i]) == 0) { + SDL_Print_Text("LEVEL", 103, 104); + sprintf(code, "%d", i + 1); + SDL_Print_Text(code, 199 - 8 * strlen(code), 104); + SDL_Flip(screen); + retval = waitforbutton(); + + if (retval < 0) + return retval; + + SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0)); + SDL_Flip(screen); + + return (i + 1); + } + } + + SDL_Print_Text("! WRONG CODE !", 87, 104); + SDL_Flip(screen); + retval = waitforbutton(); + + SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0)); + SDL_Flip(screen); + return (retval); +} + int viewmenu(char * menufile, int menuformat) { SDL_Surface *surface; SDL_Palette *palette; @@ -332,137 +469,3 @@ int viewmenu(char * menufile, int menuformat) { return (curlevel); } - -int enterpassword(){ - int retval; - char code[] = "____"; - int i; - SDL_Event event; - char tmpchar; - - SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0)); - SDL_Flip(screen); - - SDL_Print_Text("CODE", 111, 80); - -#ifdef _DINGUX - int index = 0; - int counter = 0; -#endif - - for (i = 0; i < 4; ) { - while(SDL_PollEvent(&event)) { //Check all events - if (event.type == SDL_QUIT) { - return (-1); - } - - if (event.type == SDL_KEYDOWN) { - if (event.key.keysym.sym == SDLK_ESCAPE) { - return (-1); - } -#ifdef _DINGUX - if (event.key.keysym.sym == KEY_UP) { - index++; - if (index > 15) { - index = 0; - } - } else if (event.key.keysym.sym == KEY_DOWN) { - index--; - if (index < 0) { - index = 15; - } - } else if (event.key.keysym.sym == KEY_SPACE) { - if (index < 10) { - code[i] = index + CHAR_0; - } else { - code[i] = index - 10 + CHAR_A; - } - i++; - index = 0; - } -#else - - if ((event.key.keysym.unicode & 0xFF80) == 0) { - tmpchar = (char)(event.key.keysym.unicode & 0x007F); - - if ((tmpchar >= CHAR_0) && (tmpchar <= CHAR_9)) - code[i++] = tmpchar; - - if ((tmpchar >= CHAR_a) && (tmpchar <= CHAR_f)) - tmpchar -= (CHAR_a - CHAR_A); - - if ((tmpchar >= CHAR_A) && (tmpchar <= CHAR_F)) - code[i++] = tmpchar; - - } -#endif - -#ifdef AUDIO_ENABLED - if (event.key.keysym.sym == KEY_MUSIC) { - AUDIOMODE++; - if (AUDIOMODE > 1) { - AUDIOMODE = 0; - } - if (AUDIOMODE == 1) { - startmusic(); - } - } -#endif - } - } -#ifdef _DINGUX - if (i < 4) { - counter++; - if (counter > 10) { - counter = 0; - } else if (counter > 5) { - code[i] = *"_"; - } else { - if (index < 10) { - code[i] = index + CHAR_0; - } else { - code[i] = index - 10 + CHAR_A; - } - } - } -#endif - SDL_Print_Text(code, 159, 80); - SDL_Flip(screen); - titus_sleep(); - -#ifdef AUDIO_MIKMOD_SINGLETHREAD - checkmodule(); -#endif - -#ifdef AUDIO_SDL_MIXER - checkaudio(); -#endif - - } - - for (i = 0; i < levelcount; i++) { - if (strcmp (code, levelcode[i]) == 0) { - SDL_Print_Text("LEVEL", 103, 104); - sprintf(code, "%d", i + 1); - SDL_Print_Text(code, 199 - 8 * strlen(code), 104); - SDL_Flip(screen); - retval = waitforbutton(); - - if (retval < 0) - return retval; - - SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0)); - SDL_Flip(screen); - - return (i + 1); - } - } - - SDL_Print_Text("! WRONG CODE !", 87, 104); - SDL_Flip(screen); - retval = waitforbutton(); - - SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0)); - SDL_Flip(screen); - return (retval); -} diff --git a/src/objects.c b/src/objects.c index 9fb6358..1c6a010 100644 --- a/src/objects.c +++ b/src/objects.c @@ -34,8 +34,59 @@ #include "objects.h" #include "tituserror.h" #include "settings.h" +#include "engine.h" +#include "audio.h" +#include "sprites.h" -int move_objects(TITUS_level *level) { +uint8 TAPISFLY_FLAG; //When non-zero, the flying carpet is flying +uint8 GRAVITY_FLAG; //When zero, skip object gravity function +uint8 TAPISWAIT_FLAG; //Flying carpet state + +void shock(TITUS_level *level, TITUS_object *object) { //Falling object versus player + + TITUS_player *player = &(level->player); + + //Quick test + if (object->mass < 10) return; + if (player->sprite.speedY >= MAX_Y*16) return; + if (abs(player->sprite.y - object->sprite.y) >= 32) { + return; + } + if (abs(player->sprite.x - object->sprite.x) >= 32) { + return; + } + + //Test X + if (object->sprite.x > player->sprite.x) { //Object center is right for player + if (object->sprite.x > player->sprite.x + 24) return; //Object is too far right + } else { //Object center is left for center + if (object->sprite.x + object->sprite.spritedata->collwidth < player->sprite.x) return; //Return if object is too far left + } + + //Test Y + + if (object->sprite.y < player->sprite.y) { //Object bottom is above player bottom + if (object->sprite.y <= player->sprite.y - 32) return; //Return if object is completely above the player + } else { //Object bottom is below player bottom + if (object->sprite.y - object->sprite.spritedata->collheight + 1 >= player->sprite.y) return; //Return if object is completely below the player + } + + //Hit! + +#ifdef AUDIO_ENABLED + FX_START(5); //Sound effect +#endif + CHOC_FLAG = 24; + if (object->sprite.killing) { + if (!GODMODE) { + DEC_ENERGY(level); + } + object->sprite.killing = false; + } +} + + +void move_objects(TITUS_level *level) { if (GRAVITY_FLAG == 0) return; //Skip execution if there are no active objects @@ -318,50 +369,6 @@ int move_objects(TITUS_level *level) { } } -int shock(TITUS_level *level, TITUS_object *object) { //Falling object versus player - - TITUS_player *player = &(level->player); - - //Quick test - if (object->mass < 10) return; - if (player->sprite.speedY >= MAX_Y*16) return; - if (abs(player->sprite.y - object->sprite.y) >= 32) { - return; - } - if (abs(player->sprite.x - object->sprite.x) >= 32) { - return; - } - - //Test X - if (object->sprite.x > player->sprite.x) { //Object center is right for player - if (object->sprite.x > player->sprite.x + 24) return; //Object is too far right - } else { //Object center is left for center - if (object->sprite.x + object->sprite.spritedata->collwidth < player->sprite.x) return; //Return if object is too far left - } - - //Test Y - - if (object->sprite.y < player->sprite.y) { //Object bottom is above player bottom - if (object->sprite.y <= player->sprite.y - 32) return; //Return if object is completely above the player - } else { //Object bottom is below player bottom - if (object->sprite.y - object->sprite.spritedata->collheight + 1 >= player->sprite.y) return; //Return if object is completely below the player - } - - //Hit! - -#ifdef AUDIO_ENABLED - FX_START(5); //Sound effect -#endif - CHOC_FLAG = 24; - if (object->sprite.killing) { - if (!GODMODE) { - DEC_ENERGY(level); - } - object->sprite.killing = false; - } -} - - bool SPRITES_VS_SPRITES (TITUS_level *level, TITUS_sprite *sprite1, TITUS_sprite *sprite1ref, TITUS_object **object2) { //check if there is an object below that can support the input object uint8 i; diff --git a/src/original.c b/src/original.c index 33835d2..7f4f316 100644 --- a/src/original.c +++ b/src/original.c @@ -34,6 +34,34 @@ #include "settings.h" #include "definitions.h" +SDL_Color orig_palette_colour[16]; +SDL_Color orig_palette_level_colour[16]; +SDL_Color orig_palette_font_colour[16]; + +uint8 spritewidth[SPRITECOUNT]; +uint8 spriteheight[SPRITECOUNT]; +uint8 spritecollwidth[SPRITECOUNT]; +uint8 spritecollheight[SPRITECOUNT]; +uint8 spriterefwidth[SPRITECOUNT]; +uint8 spriterefheight[SPRITECOUNT]; + +int16 anim_player[ANIM_PLAYER_COUNT][ANIM_PLAYER_MAX]; +int16 anim_enemy[NMI_ANIM_TABLE_COUNT]; +uint8 NMI_POWER[ORIG_LEVEL_COUNT]; +uint8 LEVEL_MUSIC[ORIG_LEVEL_COUNT]; + +int16 anim_zoubida[ORIG_ANIM_MAX]; +int16 anim_moktar[ORIG_ANIM_MAX]; +int16 anim_smoke[ORIG_ANIM_MAX]; +int16 COEUR_POS[ORIG_ANIM_MAX * 2]; + +uint8 object_maxspeedY[ORIG_OBJECT_COUNT]; +bool object_support[ORIG_OBJECT_COUNT]; //not support/support +bool object_bounce[ORIG_OBJECT_COUNT]; //not bounce/bounce against floor + player bounces (ball, all spring, yellow stone, squeezed ball, skateboard) +bool object_gravity[ORIG_OBJECT_COUNT]; //no gravity on throw/gravity (ball, all carpet, trolley, squeezed ball, garbage, grey stone, scooter, yellow bricks between the statues, skateboard, cage) +bool object_droptobottom[ORIG_OBJECT_COUNT]; //on drop, lands on ground/continue below ground(cave spikes, rolling rock, ambolt, safe, dead man with helicopter) +bool object_no_damage[ORIG_OBJECT_COUNT]; //weapon/not weapon(cage) + int initoriginal() { int i, j; diff --git a/src/player.c b/src/player.c index 264f329..d2101a7 100644 --- a/src/player.c +++ b/src/player.c @@ -38,13 +38,49 @@ #include "original.h" #include "common.h" #include "settings.h" - -static int TAKE_BLK_AND_YTEST(TITUS_level *level, int16 tileY, uint8 tileX); +#include "scroll.h" +#include "audio.h" +#include "objects.h" +#include "sprites.h" +#include "reset.h" +#include "enemies.h" +#include "engine.h" + +uint8 RESETLEVEL_FLAG; +uint8 BAR_FLAG; //timer for health bar +bool X_FLAG; //true if left or right key is pressed +bool Y_FLAG; //true if up or down key is pressed +uint8 CHOC_FLAG; //headache timer +uint8 action; //player sprite array +uint8 KICK_FLAG; //hit/burn timer +bool GRANDBRULE_FLAG; //If set, player will be "burned" when hit (fireballs) +bool LADDER_FLAG; //True if in a ladder +bool PRIER_FLAG; //True if player is forced into kneestanding because of low ceiling +uint8 SAUT_FLAG; //6 if free fall or in the middle of a jump, decremented if on solid surface. Must be 0 to initiate a jump. +uint8 LAST_ORDER; //Last action (kneestand + jump = silent walk) +uint8 FURTIF_FLAG; //Silent walk timer +bool DROP_FLAG; //True if an object is throwed forward +bool DROPREADY_FLAG; +bool CARRY_FLAG; //true if carrying something (add 16 to player sprite) +bool POSEREADY_FLAG; +uint8 ACTION_TIMER; //Frames since last action change +uint8 CROSS_FLAG; //When non-zero, fall through certain floors (after key down) +uint8 FUME_FLAG; //Smoke when object hits the floor +Uint8 *keystate; //Keyboard state +uint8 YFALL; +bool POCKET_FLAG; +uint8 SEECHOC_FLAG; //Counter when hit +bool GODMODE; //If true, the player will not interfere with the enemies +bool NOCLIP; //If true, the player will move noclip +uint8 SAUT_COUNT; +int8 SENSX; //1: walk right, 0: stand still, -1: walk left, triggers the ACTION_TIMER if it changes + +static void TAKE_BLK_AND_YTEST(TITUS_level *level, int16 tileY, uint8 tileX); static int BLOCK_YYPRGD(TITUS_level *level, uint8 ceil, uint8 tileY, uint8 tileX); static int BLOCK_XXPRG(TITUS_level *level, uint8 horiz, uint8 tileY, uint8 tileX); static int XACCELERATION(TITUS_player *player, int16 maxspeed); static int YACCELERATION(TITUS_player *player, int16 maxspeed); -static int BLOCK_YYPRG(TITUS_level *level, uint8 floor, uint8 floor_above, uint8 tileY, uint8 tileX); +static void BLOCK_YYPRG(TITUS_level *level, uint8 floor, uint8 floor_above, uint8 tileY, uint8 tileX); static int CASE_BONUS(TITUS_level *level, uint8 tileY, uint8 tileX); static int CASE_PASS(TITUS_level *level, uint8 viewlevel, uint8 tileY, uint8 tileX); static int CASE_SECU(TITUS_level *level, uint8 tileY, uint8 tileX); @@ -54,6 +90,327 @@ static int YACCELERATION_NEG(TITUS_player *player, int16 maxspeed); static int ACTION_PRG(TITUS_level *level, uint8 action); int16 add_carry(); +void ARAB_TOMBE(TITUS_level *level) { + //No wall under the player; fall down! + TITUS_player *player = &(level->player); + SAUT_FLAG = 6; + if (KICK_FLAG != 0) { + return; + } + XACCELERATION(player, MAX_X*16); + YACCELERATION(player, MAX_Y*16); + if (CHOC_FLAG != 0) { + updatesprite(level, &(player->sprite), 15, true); //sprite when hit + } else if (CARRY_FLAG == 0) { + updatesprite(level, &(player->sprite), 10, true); //position while falling (jump sprite?) + } else { + updatesprite(level, &(player->sprite), 21, true); //position falling and carry (jump and carry sprite?) + } + player->sprite.flipped = (SENSX < 0); +} + +void COLLISION_TRP(TITUS_level *level) { + //Player versus elevators + //Change player's location according to the elevator + uint8 i; + TITUS_player *player = &(level->player); + TITUS_elevator *elevator = level->elevator; + if ((player->sprite.speedY >= 0) && (CROSS_FLAG == 0)) { + for (i = 0; i < level->elevatorcount; i++) { + //Quick test + if (!(elevator[i].enabled) || + !(elevator[i].sprite.visible) || + (abs(elevator[i].sprite.x - player->sprite.x) >= 64) || + (abs(elevator[i].sprite.y - player->sprite.y) >= 16)) { + continue; + } + + //Real test + if (player->sprite.x - level->spritedata[0]->refwidth < elevator[i].sprite.x) { //The elevator is right + if (player->sprite.x - level->spritedata[0]->refwidth + level->spritedata[0]->collwidth <= elevator[i].sprite.x) { //player->sprite must be 0 + continue; //The elevator is too far right + } + } else { //The elevator is left + if (player->sprite.x - level->spritedata[0]->refwidth >= elevator[i].sprite.x + elevator[i].sprite.spritedata->collwidth) { + continue; //The elevator is too far left + } + } + + if (player->sprite.y - 6 < elevator[i].sprite.y) { //The elevator is below + if (player->sprite.y - 6 + 8 <= elevator[i].sprite.y) { + continue; //The elevator is too far below + } + } else { //The elevator is above + if (player->sprite.y - 6 >= elevator[i].sprite.y + elevator[i].sprite.spritedata->collheight) { + continue; //The elevator is too far above + } + } + + //Skip fall-through-tile action (ACTION_TIMER == 15) + if (ACTION_TIMER == 14) { + ACTION_TIMER = 16; + } + + YFALL = 0; + player->sprite.y = elevator[i].sprite.y; + + player->sprite.speedY = 0; + subto0(&(SAUT_FLAG)); + SAUT_COUNT = 0; + YFALL = 2; + + player->sprite.x += elevator[i].sprite.speedX; + if (elevator[i].sprite.speedY > 0) { //Going down + player->sprite.y += elevator[i].sprite.speedY; + } + return; + } + } +} + +void COLLISION_OBJET(TITUS_level *level) { + //Player versus objects + //Collision, spring state, speed up carpet/scooter/skateboard, bounce bouncy objects + TITUS_player *player = &(level->player); + TITUS_object *off_object; + if (player->sprite.speedY < 0) { + return; + } + //Collision with a sprite + if (!(SPRITES_VS_SPRITES(level, &(player->sprite), &(level->spritedata[0]), &off_object))) { //check if player stands on an object, use sprite[0] (rest) as collision size (first player tile) + return; + } + player->sprite.y = off_object->sprite.y - off_object->sprite.spritedata->collheight; + //If the foot is placed on a spring, it must be soft! + if ((off_object->sprite.number == FIRST_OBJET + 24) || (off_object->sprite.number == FIRST_OBJET + 25)) { + off_object->sprite.UNDER = off_object->sprite.UNDER | 0x02; + off_object->sprite.ONTOP = &(player->sprite); + } + //If we jump on the flying carpet, let it fly + if ((off_object->sprite.number == FIRST_OBJET + 21) || (off_object->sprite.number == FIRST_OBJET + 22)) { //Flying carpet + if (!(player->sprite.flipped)) { + off_object->sprite.speedX = 6 * 16; + } else { + off_object->sprite.speedX = 0 - 6 * 16; + } + off_object->sprite.flipped = player->sprite.flipped; + GRAVITY_FLAG = 4; + TAPISWAIT_FLAG = 0; + } else if ((ACTION_TIMER > 10) && //delay + ((LAST_ORDER & 0x0F) == 0) && //Player rests + (player->sprite.speedY == 0) && //stable Y + ((off_object->sprite.number == 83) || //scooter + (off_object->sprite.number == 94))) { //skateboard + + //If you put your foot on a scooter or a skateboard + if (!(player->sprite.flipped)) { + off_object->sprite.speedX = 16 * 3; + } else { + off_object->sprite.speedX = 0 - 16 * 3; + } + off_object->sprite.flipped = player->sprite.flipped; + GRAVITY_FLAG = 4; + } + + if (off_object->sprite.speedX < 0) { + player->sprite.speedX = off_object->sprite.speedX; + } else if (off_object->sprite.speedX > 0) { + player->sprite.speedX = off_object->sprite.speedX + 16; + } + + //If we want to CROSS (cross) it does not bounce + if ((CROSS_FLAG == 0) && //No long kneestand + (player->sprite.speedY > (16 * 3)) && + (off_object->objectdata->bounce)) { + //Bounce on a ball if no long kneestand (down key) + if (keystate[KEY_DOWN]) { + player->sprite.speedY = 0; + } else { + if (keystate[KEY_UP] || keystate[KEY_JUMP]) { + player->sprite.speedY += 16 * 3; //increase speed + } else { + player->sprite.speedY -= 16; //reduce speed + } + player->sprite.speedY = 0 - player->sprite.speedY; + if (player->sprite.speedY > 0) { + player->sprite.speedY = 0; + } + } + ACTION_TIMER = 0; + + //If the ball lies on the ground + if (off_object->sprite.speedY == 0) { +#ifdef AUDIO_ENABLED + FX_START(12); //Sound effect +#endif + off_object->sprite.speedY = 0 - player->sprite.speedY; + off_object->sprite.y -= off_object->sprite.speedY >> 4; + GRAVITY_FLAG = 4; + } + } else { + if (off_object->sprite.speedY != 0) { + player->sprite.speedY = off_object->sprite.speedY; + } else { + player->sprite.speedY = 0; + } + subto0(&(SAUT_FLAG)); + SAUT_COUNT = 0; + YFALL = 2; + } +} + +void DEC_LIFE (TITUS_level *level) { + //Kill the player, check for gameover, hide the energy bar + RESETLEVEL_FLAG = 10; + BAR_FLAG = 0; + if (level->lives == 0) { + GAMEOVER_FLAG = true; + } +} + +void CASE_DEAD_IM (TITUS_level *level) { + //Kill the player immediately (spikes/water/flames etc. + //Sets RESET_FLAG to 2, in opposite to being killed as a result of 0 HP (then RESET_FLAG is 10) + DEC_LIFE(level); + RESETLEVEL_FLAG = 2; +} + +void BRK_COLLISION(TITUS_level *level) { //Collision detection between player and tiles/objects/elevators + //Point the foot on the block! + TITUS_player *player = &(level->player); + int16 changeX; + int16 height; + int16 initY; + uint8 tileX; + int16 tileY; + int16 colltest; + uint8 left_tileX; + bool first; + uint8 hflag; + + tileX = (player->sprite.x >> 4); + tileY = (player->sprite.y >> 4) - 1; + initY = tileY; + + //if too low then die! + if ((player->sprite.y > ((level->height + 1) << 4)) && !NOCLIP) { + CASE_DEAD_IM(level); + } + + + //Test under the feet of the hero and on his head! (In y) + YFALL = 0; + //Find the left tile + //colltest can be 0 to 15 +- 8 (-1 to -8 will change into 255 to 248) + colltest = player->sprite.x & 0x0F; + if (colltest < TEST_ZONE) { + colltest += 256; + tileX--; + } + colltest -= TEST_ZONE; + + left_tileX = tileX; + TAKE_BLK_AND_YTEST(level, tileY, tileX); //Test the tile for vertical blocking + if (YFALL == 1) { //Have the fall stopped? + //No! Is it necessary to test the right tile? + colltest += TEST_ZONE * 2; //4 * 2 +// if (colltest > 255) { +// colltest -= 256; +// tileX++; +// } elseif + if (colltest > 15) { + tileX++; + } + if (tileX != left_tileX) { + TAKE_BLK_AND_YTEST(level, tileY, tileX); //Also test the left tile + } + if (YFALL == 1) { + if ((CROSS_FLAG == 0) && (CHOC_FLAG == 0)) { + COLLISION_TRP(level); //Player versus elevators + if (YFALL == 1) { + COLLISION_OBJET(level); //Player versus objects + if (YFALL == 1) { + ARAB_TOMBE(level); //No wall/elevator/object under the player; fall down! + } else { + player->GLISSE = 0; + } + } + } else { + ARAB_TOMBE(level); //Fall down! + } + } + } + + //How will the player move in X? + changeX = TEST_ZONE + MAX_X; //4 + 4 ??? + max_speed_x + if (player->sprite.speedX < 0) { + changeX = 0 - changeX; + } else if (player->sprite.speedX == 0) { + changeX = 0; + } + + //Test the hero (in x) + height = player->sprite.spritedata->collheight; + if ((player->sprite.y > MAP_LIMIT_Y + 1) && (initY >= 0) && (initY < level->height)) { + tileX = ((player->sprite.x + changeX) >> 4); + tileY = initY; + first = true; + do { + hflag = get_horizflag(level, tileY, tileX); + if (first) { + BLOCK_XXPRG(level, hflag, tileY, tileX); + first = false; + } else if ((hflag == HFLAG_CODE) || (hflag == HFLAG_BONUS)) { //level code or HP + BLOCK_XXPRG(level, hflag, tileY, tileX); + } + if (tileY == 0) { + return; + } + tileY--; + height -= 16; + } while (height > 0); + } +} + +int t_pause (TITUS_level *level) { + bool pass; + TITUS_player *player = &(level->player); + SDL_Event event; + TITUS_sprite tmp; + //tmp.buffer = NULL; + + TFR_SCREENM(); //Draw tiles + copysprite(level, &(tmp), &(player->sprite)); + updatesprite(level, &(player->sprite), 29, true); //Pause tile + DISPLAY_SPRITES(level); //Draw sprites + flip_screen(true); //Display it + copysprite(level, &(player->sprite), &(tmp)); //Reset player sprite + //SDL_FreeSurface(tmp.buffer); + do { + titus_sleep(); + keystate = SDL_GetKeyState(NULL); + while(SDL_PollEvent(&event)) { //Check all events + if (event.type == SDL_QUIT) { + return TITUS_ERROR_QUIT; + } else if (event.type == SDL_KEYDOWN) { + if (event.key.keysym.sym == KEY_ESC) { + return TITUS_ERROR_QUIT; + } else if (event.key.keysym.sym == KEY_MUSIC) { + AUDIOMODE++; + if (AUDIOMODE > 1) { + AUDIOMODE = 0; + } + if (AUDIOMODE == 1) { + startmusic(); + } + } else if (event.key.keysym.sym == KEY_P) { + return 0; + } + } + } + } while (1); +} + int move_player(TITUS_level *level) { //Part 1: Check keyboard input //Part 2: Determine the player's action, and execute action dependent code @@ -141,11 +498,11 @@ int move_player(TITUS_level *level) { if (keystate[KEY_F1] && (RESETLEVEL_FLAG == 0)) { //F1 = suicide CASE_DEAD_IM(level); RESETLEVEL_FLAG--; - return; + return 0; } if (keystate[KEY_F2]) { //F2 = game over GAMEOVER_FLAG = true; - return; + return 0; } if (keystate[KEY_E]) { //E = display energy BAR_FLAG = 50; @@ -187,7 +544,7 @@ int move_player(TITUS_level *level) { } player->sprite.x += (player->sprite.speedX >> 4); player->sprite.y += (player->sprite.speedY >> 4); - return; + return 0; } if (CHOC_FLAG != 0) { @@ -363,160 +720,8 @@ int move_player(TITUS_level *level) { } } -CASE_DEAD_IM (TITUS_level *level) { - //Kill the player immediately (spikes/water/flames etc. - //Sets RESET_FLAG to 2, in opposite to being killed as a result of 0 HP (then RESET_FLAG is 10) - DEC_LIFE(level); - RESETLEVEL_FLAG = 2; -} - - -DEC_LIFE (TITUS_level *level) { - //Kill the player, check for gameover, hide the energy bar - RESETLEVEL_FLAG = 10; - BAR_FLAG = 0; - if (level->lives == 0) { - GAMEOVER_FLAG = true; - } -} - -t_pause (TITUS_level *level) { - bool pass; - TITUS_player *player = &(level->player); - SDL_Event event; - TITUS_sprite tmp; - //tmp.buffer = NULL; - TFR_SCREENM(); //Draw tiles - copysprite(level, &(tmp), &(player->sprite)); - updatesprite(level, &(player->sprite), 29, true); //Pause tile - DISPLAY_SPRITES(level); //Draw sprites - flip_screen(true); //Display it - copysprite(level, &(player->sprite), &(tmp)); //Reset player sprite - //SDL_FreeSurface(tmp.buffer); - do { - titus_sleep(); - keystate = SDL_GetKeyState(NULL); - while(SDL_PollEvent(&event)) { //Check all events - if (event.type == SDL_QUIT) { - return TITUS_ERROR_QUIT; - } else if (event.type == SDL_KEYDOWN) { - if (event.key.keysym.sym == KEY_ESC) { - return TITUS_ERROR_QUIT; - } else if (event.key.keysym.sym == KEY_MUSIC) { - AUDIOMODE++; - if (AUDIOMODE > 1) { - AUDIOMODE = 0; - } - if (AUDIOMODE == 1) { - startmusic(); - } - } else if (event.key.keysym.sym == KEY_P) { - return 0; - } - } - } - } while (1); -} - -BRK_COLLISION(TITUS_level *level) { //Collision detection between player and tiles/objects/elevators - //Point the foot on the block! - TITUS_player *player = &(level->player); - int16 changeX; - int16 height; - int16 initY; - uint8 tileX; - int16 tileY; - int16 colltest; - uint8 left_tileX; - bool first; - uint8 hflag; - - tileX = (player->sprite.x >> 4); - tileY = (player->sprite.y >> 4) - 1; - initY = tileY; - - //if too low then die! - if ((player->sprite.y > ((level->height + 1) << 4)) && !NOCLIP) { - CASE_DEAD_IM(level); - } - - - //Test under the feet of the hero and on his head! (In y) - YFALL = 0; - //Find the left tile - //colltest can be 0 to 15 +- 8 (-1 to -8 will change into 255 to 248) - colltest = player->sprite.x & 0x0F; - if (colltest < TEST_ZONE) { - colltest += 256; - tileX--; - } - colltest -= TEST_ZONE; - - left_tileX = tileX; - TAKE_BLK_AND_YTEST(level, tileY, tileX); //Test the tile for vertical blocking - if (YFALL == 1) { //Have the fall stopped? - //No! Is it necessary to test the right tile? - colltest += TEST_ZONE * 2; //4 * 2 -// if (colltest > 255) { -// colltest -= 256; -// tileX++; -// } elseif - if (colltest > 15) { - tileX++; - } - if (tileX != left_tileX) { - TAKE_BLK_AND_YTEST(level, tileY, tileX); //Also test the left tile - } - if (YFALL == 1) { - if ((CROSS_FLAG == 0) && (CHOC_FLAG == 0)) { - COLLISION_TRP(level); //Player versus elevators - if (YFALL == 1) { - COLLISION_OBJET(level); //Player versus objects - if (YFALL == 1) { - ARAB_TOMBE(level); //No wall/elevator/object under the player; fall down! - } else { - player->GLISSE = 0; - } - } - } else { - ARAB_TOMBE(level); //Fall down! - } - } - } - - //How will the player move in X? - changeX = TEST_ZONE + MAX_X; //4 + 4 ??? + max_speed_x - if (player->sprite.speedX < 0) { - changeX = 0 - changeX; - } else if (player->sprite.speedX == 0) { - changeX = 0; - } - - //Test the hero (in x) - height = player->sprite.spritedata->collheight; - if ((player->sprite.y > MAP_LIMIT_Y + 1) && (initY >= 0) && (initY < level->height)) { - tileX = ((player->sprite.x + changeX) >> 4); - tileY = initY; - first = true; - do { - hflag = get_horizflag(level, tileY, tileX); - if (first) { - BLOCK_XXPRG(level, hflag, tileY, tileX); - first = false; - } else if ((hflag == HFLAG_CODE) || (hflag == HFLAG_BONUS)) { //level code or HP - BLOCK_XXPRG(level, hflag, tileY, tileX); - } - if (tileY == 0) { - return; - } - tileY--; - height -= 16; - } while (height > 0); - } -} - -static int TAKE_BLK_AND_YTEST(TITUS_level *level, int16 tileY, uint8 tileX) { +static void TAKE_BLK_AND_YTEST(TITUS_level *level, int16 tileY, uint8 tileX) { //Test the current tile for vertical blocking TITUS_player *player = &(level->player); @@ -633,6 +838,17 @@ static int BLOCK_YYPRGD(TITUS_level *level, uint8 ceil, uint8 tileY, uint8 tileX } } +void ARAB_BLOCKX(TITUS_level *level) { + TITUS_player *player = &(level->player); + //Horizontal hit (wall), stop the player + player->sprite.x -= player->sprite.speedX >> 4; + player->sprite.speedX = 0; + if ((KICK_FLAG != 0) && (SAUT_FLAG != 6)) { + CHOC_FLAG = 20; + KICK_FLAG = 0; + } +} + static int BLOCK_XXPRG(TITUS_level *level, uint8 horiz, uint8 tileY, uint8 tileX) { //Action on different horizontal flags switch (horiz) { @@ -660,23 +876,12 @@ static int BLOCK_XXPRG(TITUS_level *level, uint8 horiz, uint8 tileY, uint8 tileX break; case 5: //Padlock - CASE_SECU(level, tileY, tileX); - break; - - case 6: //Level 14 code - CASE_PASS(level, 14 - 1, tileY, tileX); - break; - } -} - -ARAB_BLOCKX(TITUS_level *level) { - TITUS_player *player = &(level->player); - //Horizontal hit (wall), stop the player - player->sprite.x -= player->sprite.speedX >> 4; - player->sprite.speedX = 0; - if ((KICK_FLAG != 0) && (SAUT_FLAG != 6)) { - CHOC_FLAG = 20; - KICK_FLAG = 0; + CASE_SECU(level, tileY, tileX); + break; + + case 6: //Level 14 code + CASE_PASS(level, 14 - 1, tileY, tileX); + break; } } @@ -722,27 +927,6 @@ TITUS_object *FORCE_POSE(TITUS_level *level) { } } - - -ARAB_TOMBE(TITUS_level *level) { - //No wall under the player; fall down! - TITUS_player *player = &(level->player); - SAUT_FLAG = 6; - if (KICK_FLAG != 0) { - return; - } - XACCELERATION(player, MAX_X*16); - YACCELERATION(player, MAX_Y*16); - if (CHOC_FLAG != 0) { - updatesprite(level, &(player->sprite), 15, true); //sprite when hit - } else if (CARRY_FLAG == 0) { - updatesprite(level, &(player->sprite), 10, true); //position while falling (jump sprite?) - } else { - updatesprite(level, &(player->sprite), 21, true); //position falling and carry (jump and carry sprite?) - } - player->sprite.flipped = (SENSX < 0); -} - static int XACCELERATION(TITUS_player *player, int16 maxspeed) { //Sideway acceleration int16 changeX; @@ -771,7 +955,27 @@ static int YACCELERATION(TITUS_player *player, int16 maxspeed) { } -static int BLOCK_YYPRG(TITUS_level *level, uint8 floor, uint8 floor_above, uint8 tileY, uint8 tileX) { +void ARAB_BLOCK_YU(TITUS_player *player) { + //Floor; the player will not fall through + POCKET_FLAG = true; + player->GLISSE = 0; + if (player->sprite.speedY < 0) { + YFALL = YFALL | 0x01; + return; + } + player->sprite.y = player->sprite.y & 0xFFF0; + player->sprite.speedY = 0; + subto0(&SAUT_FLAG); + SAUT_COUNT = 0; + YFALL = 2; +} + +void ARAB_TOMBE_F() { + //Player free fall (doesn't touch floor) + YFALL = YFALL | 0x01; +} + +static void BLOCK_YYPRG(TITUS_level *level, uint8 floor, uint8 floor_above, uint8 tileY, uint8 tileX) { //Action on different floor flags TITUS_player *player = &(level->player); uint8 order; @@ -875,24 +1079,14 @@ static int BLOCK_YYPRG(TITUS_level *level, uint8 floor, uint8 floor_above, uint8 } } -ARAB_TOMBE_F() { - //Player free fall (doesn't touch floor) - YFALL = YFALL | 0x01; -} - -ARAB_BLOCK_YU(TITUS_player *player) { - //Floor; the player will not fall through - POCKET_FLAG = true; - player->GLISSE = 0; - if (player->sprite.speedY < 0) { - YFALL = YFALL | 0x01; - return; +void INC_ENERGY(TITUS_level *level) { + TITUS_player *player = &(level->player); + BAR_FLAG = 50; + player->hp++; + if (player->hp > MAXIMUM_ENERGY) { + player->hp = MAXIMUM_ENERGY; + level->extrabonus++; } - player->sprite.y = player->sprite.y & 0xFFF0; - player->sprite.speedY = 0; - subto0(&SAUT_FLAG); - SAUT_COUNT = 0; - YFALL = 2; } static int CASE_BONUS(TITUS_level *level, uint8 tileY, uint8 tileX) { @@ -949,17 +1143,7 @@ static int CASE_SECU(TITUS_level *level, uint8 tileY, uint8 tileX) { } } -INC_ENERGY(TITUS_level *level) { - TITUS_player *player = &(level->player); - BAR_FLAG = 50; - player->hp++; - if (player->hp > MAXIMUM_ENERGY) { - player->hp = MAXIMUM_ENERGY; - level->extrabonus++; - } -} - -DEC_ENERGY(TITUS_level *level) { +void DEC_ENERGY(TITUS_level *level) { TITUS_player *player = &(level->player); BAR_FLAG = 50; if (RESETLEVEL_FLAG == 0) { @@ -971,6 +1155,24 @@ DEC_ENERGY(TITUS_level *level) { } } +void DECELERATION(TITUS_player *player) { + //Stop acceleration + uint8 friction = (3 * 4) >> player->GLISSE; + int16 speed; + if (player->sprite.speedX < 0) { + speed = player->sprite.speedX + friction; + if (speed > 0) { + speed = 0; + } + } else { + speed = player->sprite.speedX - friction; + if (speed < 0) { + speed = 0; + } + } + player->sprite.speedX = speed; +} + static int ACTION_PRG(TITUS_level *level, uint8 action) { //Action dependent code TITUS_player *player = &(level->player); @@ -1419,24 +1621,6 @@ static int ACTION_PRG(TITUS_level *level, uint8 action) { } -DECELERATION(TITUS_player *player) { - //Stop acceleration - uint8 friction = (3 * 4) >> player->GLISSE; - int16 speed; - if (player->sprite.speedX < 0) { - speed = player->sprite.speedX + friction; - if (speed > 0) { - speed = 0; - } - } else { - speed = player->sprite.speedX - friction; - if (speed < 0) { - speed = 0; - } - } - player->sprite.speedX = speed; -} - static int NEW_FORM(TITUS_player *player, uint8 action) { //if the order is changed, change player animation if ((LAST_ORDER != action) || (player->sprite.animation == NULL)) { @@ -1477,153 +1661,3 @@ int16 add_carry() { return 0; } } - -COLLISION_TRP(TITUS_level *level) { - //Player versus elevators - //Change player's location according to the elevator - uint8 i; - TITUS_player *player = &(level->player); - TITUS_elevator *elevator = level->elevator; - if ((player->sprite.speedY >= 0) && (CROSS_FLAG == 0)) { - for (i = 0; i < level->elevatorcount; i++) { - //Quick test - if (!(elevator[i].enabled) || - !(elevator[i].sprite.visible) || - (abs(elevator[i].sprite.x - player->sprite.x) >= 64) || - (abs(elevator[i].sprite.y - player->sprite.y) >= 16)) { - continue; - } - - //Real test - if (player->sprite.x - level->spritedata[0]->refwidth < elevator[i].sprite.x) { //The elevator is right - if (player->sprite.x - level->spritedata[0]->refwidth + level->spritedata[0]->collwidth <= elevator[i].sprite.x) { //player->sprite must be 0 - continue; //The elevator is too far right - } - } else { //The elevator is left - if (player->sprite.x - level->spritedata[0]->refwidth >= elevator[i].sprite.x + elevator[i].sprite.spritedata->collwidth) { - continue; //The elevator is too far left - } - } - - if (player->sprite.y - 6 < elevator[i].sprite.y) { //The elevator is below - if (player->sprite.y - 6 + 8 <= elevator[i].sprite.y) { - continue; //The elevator is too far below - } - } else { //The elevator is above - if (player->sprite.y - 6 >= elevator[i].sprite.y + elevator[i].sprite.spritedata->collheight) { - continue; //The elevator is too far above - } - } - - //Skip fall-through-tile action (ACTION_TIMER == 15) - if (ACTION_TIMER == 14) { - ACTION_TIMER = 16; - } - - YFALL = 0; - player->sprite.y = elevator[i].sprite.y; - - player->sprite.speedY = 0; - subto0(&(SAUT_FLAG)); - SAUT_COUNT = 0; - YFALL = 2; - - player->sprite.x += elevator[i].sprite.speedX; - if (elevator[i].sprite.speedY > 0) { //Going down - player->sprite.y += elevator[i].sprite.speedY; - } - return; - } - } -} - -COLLISION_OBJET(TITUS_level *level) { - //Player versus objects - //Collision, spring state, speed up carpet/scooter/skateboard, bounce bouncy objects - TITUS_player *player = &(level->player); - TITUS_object *off_object; - if (player->sprite.speedY < 0) { - return; - } - //Collision with a sprite - if (!(SPRITES_VS_SPRITES(level, &(player->sprite), &(level->spritedata[0]), &off_object))) { //check if player stands on an object, use sprite[0] (rest) as collision size (first player tile) - return; - } - player->sprite.y = off_object->sprite.y - off_object->sprite.spritedata->collheight; - //If the foot is placed on a spring, it must be soft! - if ((off_object->sprite.number == FIRST_OBJET + 24) || (off_object->sprite.number == FIRST_OBJET + 25)) { - off_object->sprite.UNDER = off_object->sprite.UNDER | 0x02; - off_object->sprite.ONTOP = &(player->sprite); - } - //If we jump on the flying carpet, let it fly - if ((off_object->sprite.number == FIRST_OBJET + 21) || (off_object->sprite.number == FIRST_OBJET + 22)) { //Flying carpet - if (!(player->sprite.flipped)) { - off_object->sprite.speedX = 6 * 16; - } else { - off_object->sprite.speedX = 0 - 6 * 16; - } - off_object->sprite.flipped = player->sprite.flipped; - GRAVITY_FLAG = 4; - TAPISWAIT_FLAG = 0; - } else if ((ACTION_TIMER > 10) && //delay - ((LAST_ORDER & 0x0F) == 0) && //Player rests - (player->sprite.speedY == 0) && //stable Y - ((off_object->sprite.number == 83) || //scooter - (off_object->sprite.number == 94))) { //skateboard - - //If you put your foot on a scooter or a skateboard - if (!(player->sprite.flipped)) { - off_object->sprite.speedX = 16 * 3; - } else { - off_object->sprite.speedX = 0 - 16 * 3; - } - off_object->sprite.flipped = player->sprite.flipped; - GRAVITY_FLAG = 4; - } - - if (off_object->sprite.speedX < 0) { - player->sprite.speedX = off_object->sprite.speedX; - } else if (off_object->sprite.speedX > 0) { - player->sprite.speedX = off_object->sprite.speedX + 16; - } - - //If we want to CROSS (cross) it does not bounce - if ((CROSS_FLAG == 0) && //No long kneestand - (player->sprite.speedY > (16 * 3)) && - (off_object->objectdata->bounce)) { - //Bounce on a ball if no long kneestand (down key) - if (keystate[KEY_DOWN]) { - player->sprite.speedY = 0; - } else { - if (keystate[KEY_UP] || keystate[KEY_JUMP]) { - player->sprite.speedY += 16 * 3; //increase speed - } else { - player->sprite.speedY -= 16; //reduce speed - } - player->sprite.speedY = 0 - player->sprite.speedY; - if (player->sprite.speedY > 0) { - player->sprite.speedY = 0; - } - } - ACTION_TIMER = 0; - - //If the ball lies on the ground - if (off_object->sprite.speedY == 0) { -#ifdef AUDIO_ENABLED - FX_START(12); //Sound effect -#endif - off_object->sprite.speedY = 0 - player->sprite.speedY; - off_object->sprite.y -= off_object->sprite.speedY >> 4; - GRAVITY_FLAG = 4; - } - } else { - if (off_object->sprite.speedY != 0) { - player->sprite.speedY = off_object->sprite.speedY; - } else { - player->sprite.speedY = 0; - } - subto0(&(SAUT_FLAG)); - SAUT_COUNT = 0; - YFALL = 2; - } -} diff --git a/src/reset.c b/src/reset.c index 5c99e2e..a8cd9e2 100644 --- a/src/reset.c +++ b/src/reset.c @@ -41,6 +41,23 @@ #include "player.h" #include "objects.h" #include "enemies.h" +#include "tile_animation.h" +#include "engine.h" +#include "audio.h" +#include "keyboard.h" + +bool NOSCROLL_FLAG; +bool NEWLEVEL_FLAG; //Finish a level +bool NFC_FLAG; //Skip NO_FAST_CPU + +void MOVE_HIM(TITUS_level *level, TITUS_sprite *spr) { + int16 *pointer = spr->animation + 1; + while (*pointer < 0) { + pointer += (*pointer / 2); //End of animation, jump back + } + updatesprite(level, spr, *pointer, true); + spr->animation = pointer; +} //Possible return states: @@ -49,7 +66,6 @@ //2 - Game over //3 - Death - uint8 RESET_LEVEL(TITUS_level *level) { TITUS_player *player = &(level->player); bool pass; @@ -179,102 +195,7 @@ uint8 RESET_LEVEL(TITUS_level *level) { return 0; } - -MOVE_HIM(TITUS_level *level, TITUS_sprite *spr) { - int16 *pointer = spr->animation + 1; - while (*pointer < 0) { - pointer += (*pointer / 2); //End of animation, jump back - } - updatesprite(level, spr, *pointer, true); - spr->animation = pointer; -} - - -int CLEAR_DATA(TITUS_level *level) { - loop_cycle = 0; - tile_anim = 0; - BIGNMI_NBR = 0; - IMAGE_COUNTER = 0; - TAUPE_FLAG = 0; - GRANDBRULE_FLAG = 0; - NOSCROLL_FLAG = 0; - TAPISWAIT_FLAG = 0; - TAPISFLY_FLAG = 0; - FUME_FLAG = 0; - BAR_FLAG = 0; - X_FLAG = 0; - Y_FLAG = 0; - CARRY_FLAG = 0; - DROP_FLAG = 0; - DROPREADY_FLAG = 0; - POSEREADY_FLAG = 0; - LADDER_FLAG = 0; - PRIER_FLAG = 0; - SAUT_FLAG = 0; - CROSS_FLAG = 0; - GRAVITY_FLAG = 0; - FURTIF_FLAG = 0; - CHOC_FLAG = 0; - KICK_FLAG = 0; - SEECHOC_FLAG = 0; - RESETLEVEL_FLAG = 0; - GAMEOVER_FLAG = false; - NEWLEVEL_FLAG = false; - NFC_FLAG = false; - INVULNERABLE_FLAG = 0; - POCKET_FLAG = 0; - SAUT_COUNT = 0; - ACTION_TIMER = 0; - XSCROLL_CENTER = 0; - YSCROLL_CENTER = 0; - XLIMIT_SCROLL = 0; - YLIMIT_SCROLL = 0; - YFALL = 0; - - TAPISFLY_FLAG = 0; - CROSS_FLAG = 0; - GRAVITY_FLAG = 4; - LADDER_FLAG = 0; - FURTIF_FLAG = 0; - KICK_FLAG = 0; - CHOC_FLAG = 0; - FUME_FLAG = 0; - DROP_FLAG = 0; - CARRY_FLAG = 0; - NOSCROLL_FLAG = 0; - GAMEOVER_FLAG = 0; - NEWLEVEL_FLAG = false; - RESETLEVEL_FLAG = 0; - INVULNERABLE_FLAG = 0; - TAUPE_FLAG = 0; - SENSX = 0; - LAST_ORDER = 0; - - SET_ALL_SPRITES(level); - - SET_DATA_NMI(level); - -} - - -SET_DATA_NMI(TITUS_level *level) { - boss_alive = false; - int i, anim; - for (i = 0; i < level->enemycount; i++) { - anim = -1; - if (!level->enemy[i].init_enabled) continue; - do { - anim++; - } while (anim_enemy[anim] + FIRST_NMI != level->enemy[i].sprite.number); - level->enemy[i].sprite.animation = &(anim_enemy[anim]); - if (level->enemy[i].boss) { - boss_alive = true; - } - } - BIGNMI_POWER = NMI_POWER[level->levelid]; -} - -clearsprite(TITUS_sprite *spr){ +void clearsprite(TITUS_sprite *spr){ //SDL_FreeSurface(spr->buffer); //spr->buffer = NULL; spr->enabled = false; @@ -295,11 +216,9 @@ clearsprite(TITUS_sprite *spr){ spr->droptobottom = false; spr->killing = false; spr->invisible = false; - return (0); } - -SET_ALL_SPRITES(TITUS_level *level) { +void SET_ALL_SPRITES(TITUS_level *level) { int16 i; TITUS_player *player = &(level->player); @@ -369,3 +288,87 @@ SET_ALL_SPRITES(TITUS_level *level) { level->player.animcycle = 0; updatesprite(level, &(level->player.sprite), 0, true); } + +void SET_DATA_NMI(TITUS_level *level) { + boss_alive = false; + int i, anim; + for (i = 0; i < level->enemycount; i++) { + anim = -1; + if (!level->enemy[i].init_enabled) continue; + do { + anim++; + } while (anim_enemy[anim] + FIRST_NMI != level->enemy[i].sprite.number); + level->enemy[i].sprite.animation = &(anim_enemy[anim]); + if (level->enemy[i].boss) { + boss_alive = true; + } + } + BIGNMI_POWER = NMI_POWER[level->levelid]; +} + +int CLEAR_DATA(TITUS_level *level) { + loop_cycle = 0; + tile_anim = 0; + IMAGE_COUNTER = 0; + TAUPE_FLAG = 0; + GRANDBRULE_FLAG = 0; + NOSCROLL_FLAG = 0; + TAPISWAIT_FLAG = 0; + TAPISFLY_FLAG = 0; + FUME_FLAG = 0; + BAR_FLAG = 0; + X_FLAG = 0; + Y_FLAG = 0; + CARRY_FLAG = 0; + DROP_FLAG = 0; + DROPREADY_FLAG = 0; + POSEREADY_FLAG = 0; + LADDER_FLAG = 0; + PRIER_FLAG = 0; + SAUT_FLAG = 0; + CROSS_FLAG = 0; + GRAVITY_FLAG = 0; + FURTIF_FLAG = 0; + CHOC_FLAG = 0; + KICK_FLAG = 0; + SEECHOC_FLAG = 0; + RESETLEVEL_FLAG = 0; + GAMEOVER_FLAG = false; + NEWLEVEL_FLAG = false; + NFC_FLAG = false; + INVULNERABLE_FLAG = 0; + POCKET_FLAG = 0; + SAUT_COUNT = 0; + ACTION_TIMER = 0; + XSCROLL_CENTER = 0; + YSCROLL_CENTER = 0; + XLIMIT_SCROLL = 0; + YLIMIT_SCROLL = 0; + YFALL = 0; + + TAPISFLY_FLAG = 0; + CROSS_FLAG = 0; + GRAVITY_FLAG = 4; + LADDER_FLAG = 0; + FURTIF_FLAG = 0; + KICK_FLAG = 0; + CHOC_FLAG = 0; + FUME_FLAG = 0; + DROP_FLAG = 0; + CARRY_FLAG = 0; + NOSCROLL_FLAG = 0; + GAMEOVER_FLAG = 0; + NEWLEVEL_FLAG = false; + RESETLEVEL_FLAG = 0; + INVULNERABLE_FLAG = 0; + TAUPE_FLAG = 0; + SENSX = 0; + LAST_ORDER = 0; + + SET_ALL_SPRITES(level); + + SET_DATA_NMI(level); + +} + + diff --git a/src/scroll.c b/src/scroll.c index 68cc897..b0730fa 100644 --- a/src/scroll.c +++ b/src/scroll.c @@ -34,35 +34,26 @@ #include "definitions.h" #include "backbuffer.h" #include "scroll.h" +#include "level.h" +#include "gates.h" +#include "player.h" +bool PERMUT_FLAG; //If false, there are no animated tiles on the screen? +uint8 loop_cycle; //Increased every loop in game loop +uint8 tile_anim; //Current tile animation (0-1-2), changed every 4th game loop cycle +uint8 BITMAP_X; //Screen offset (X) in tiles +uint8 BITMAP_XM; //Point to the left tile in the tile screen (0 to 19) +uint8 BITMAP_Y; //Screen offset (Y) in tiles +uint8 BITMAP_YM; //Point to the top tile in the tile screen (0 to 11) +bool XSCROLL_CENTER; //If true, the screen will scroll in X +int16 XLIMIT_SCROLL; //If scrolling: scroll until player is in this tile (X) +bool YSCROLL_CENTER; //If true, the screen will scroll in Y +uint8 YLIMIT_SCROLL; //If scrolling: scroll until player is in this tile (Y) static uint8 BARRYCENTRE(TITUS_level *level); static int REFRESH_COLUMNS(TITUS_level *level, int8 column); static int REFRESH_LINE(TITUS_level *level, int8 line); -bool L_SCROLL(TITUS_level *level); -bool R_SCROLL(TITUS_level *level); -bool U_SCROLL(TITUS_level *level); -bool D_SCROLL(TITUS_level *level); - -int scroll(TITUS_level *level) { - //Scroll screen and update tile animation - loop_cycle++; //Cycle from 0 to 3 - if (loop_cycle > 3) { - loop_cycle = 0; - } - if (loop_cycle == 0) { //Every 4th call - tile_anim++; //Cycle tile animation (0-1-2) - if (tile_anim > 2) { - tile_anim = 0; - } - } - //Scroll - if (!NOSCROLL_FLAG) { - X_ADJUST(level); - Y_ADJUST(level); - } -} -X_ADJUST(TITUS_level *level) { +void X_ADJUST(TITUS_level *level) { bool block; TITUS_player *player = &(level->player); int16 pstileX = (player->sprite.x >> 4) - BITMAP_X; //Player screen tile X (0 to 19) @@ -133,7 +124,7 @@ X_ADJUST(TITUS_level *level) { } } -Y_ADJUST(TITUS_level *level) { +void Y_ADJUST(TITUS_level *level) { TITUS_player *player = &(level->player); if (player->sprite.speedY == 0) { YSCROLL_CENTER = false; @@ -189,6 +180,25 @@ Y_ADJUST(TITUS_level *level) { } } +int scroll(TITUS_level *level) { + //Scroll screen and update tile animation + loop_cycle++; //Cycle from 0 to 3 + if (loop_cycle > 3) { + loop_cycle = 0; + } + if (loop_cycle == 0) { //Every 4th call + tile_anim++; //Cycle tile animation (0-1-2) + if (tile_anim > 2) { + tile_anim = 0; + } + } + //Scroll + if (!NOSCROLL_FLAG) { + X_ADJUST(level); + Y_ADJUST(level); + } +} + static uint8 BARRYCENTRE(TITUS_level *level) { //If an enemy is behind the player, max. 12.5 tiles away horizontally, scroll until player is in the middle diff --git a/src/settings.c b/src/settings.c index a606475..16b6941 100644 --- a/src/settings.c +++ b/src/settings.c @@ -38,6 +38,40 @@ #include "config.h" #endif +char spritefile[256]; +char levelfiles[16][256]; //16 levels in moktar, 15 levels in titus +char tituslogofile[256]; +int tituslogoformat; +char titusintrofile[256]; +int titusintroformat; +char titusmenufile[256]; +int titusmenuformat; +char titusfinishfile[256]; +int titusfinishformat; +char fontfile[256]; +int levelcount; +int devmode; +int reswidth; +int resheight; +int bitdepth; +int ingamewidth; +int ingameheight; +int videomode; +int game; + +char levelcode[16][5]; +char leveltitle[16][41]; + +char moduleintrofile[256]; //.mod file +int moduleintrofileloop; //loop info +char moduleprelevelfile[256]; +int moduleprelevelfileloop; +char modulelevelfile[6][256]; //6 different level files +int modulelevelfileloop[6]; +char modulegameoverfile[256]; +int modulegameoverfileloop; +char modulelevel[16]; //Link to modulelevelfiles + int readconfig(char *configfile) { char line[300], tmp[256]; int retval, i, j, tmpcount = 0; diff --git a/src/sprites.c b/src/sprites.c index 6368766..64c4fb6 100644 --- a/src/sprites.c +++ b/src/sprites.c @@ -36,6 +36,9 @@ #include "tituserror.h" #include "globals.h" #include "definitions.h" +#include "engine.h" +#include "player.h" +#include "objects.h" SDL_Surface * copysurface(SDL_Surface * original, bool flip, bool flash){ int i, j; @@ -244,37 +247,7 @@ int copypixelformat(SDL_PixelFormat * destformat, SDL_PixelFormat * srcformat) { return 0; } -SPRITES_ANIMATION(TITUS_level *level) { - int16 i; - //Animate player - if ((LAST_ORDER == 0) && - (POCKET_FLAG) && - (ACTION_TIMER >= 35*4)) { - updatesprite(level, &(level->player.sprite), 29, false); //"Pause"-sprite - if (ACTION_TIMER >= 35*5) { - updatesprite(level, &(level->player.sprite), 0, false); //Normal player sprite - ACTION_TIMER = 0; - } - } - //Animate other objects - - animate_sprite(level, &(level->player.sprite2)); - animate_sprite(level, &(level->player.sprite3)); - - for (i = 0; i < level->objectcount; i++) { - animate_sprite(level, &(level->object[i].sprite)); - } - - for (i = 0; i < level->enemycount; i++) { - animate_sprite(level, &(level->enemy[i].sprite)); - } - - for (i = 0; i < level->elevatorcount; i++) { - animate_sprite(level, &(level->elevator[i].sprite)); - } -} - -animate_sprite(TITUS_level *level, TITUS_sprite *spr) { +void animate_sprite(TITUS_level *level, TITUS_sprite *spr) { if (!spr->visible) return; //Not on screen? if (!spr->enabled) return; if (spr->number == (FIRST_OBJET+26)) { //Cage @@ -319,6 +292,36 @@ animate_sprite(TITUS_level *level, TITUS_sprite *spr) { } } +void SPRITES_ANIMATION(TITUS_level *level) { + int16 i; + //Animate player + if ((LAST_ORDER == 0) && + (POCKET_FLAG) && + (ACTION_TIMER >= 35*4)) { + updatesprite(level, &(level->player.sprite), 29, false); //"Pause"-sprite + if (ACTION_TIMER >= 35*5) { + updatesprite(level, &(level->player.sprite), 0, false); //Normal player sprite + ACTION_TIMER = 0; + } + } + //Animate other objects + + animate_sprite(level, &(level->player.sprite2)); + animate_sprite(level, &(level->player.sprite3)); + + for (i = 0; i < level->objectcount; i++) { + animate_sprite(level, &(level->object[i].sprite)); + } + + for (i = 0; i < level->enemycount; i++) { + animate_sprite(level, &(level->enemy[i].sprite)); + } + + for (i = 0; i < level->elevatorcount; i++) { + animate_sprite(level, &(level->elevator[i].sprite)); + } +} + int updatesprite(TITUS_level *level, TITUS_sprite *spr, int16 number, bool clearflags){ spr->number = number; diff --git a/src/tile_animation.c b/src/tile_animation.c index 093bf0f..674cdc7 100644 --- a/src/tile_animation.c +++ b/src/tile_animation.c @@ -32,8 +32,9 @@ #include "level.h" #include "globals.h" #include "definitions.h" +#include "scroll.h" -BLOC_ANIMATION(TITUS_level *level) { +void BLOC_ANIMATION(TITUS_level *level) { //Draw animated sprites on OFS_SCREENM uint8 tmp_ym, curY, tmp_xm, curX; uint8 i, j; diff --git a/src/viewimage.c b/src/viewimage.c index a49c774..c89b076 100644 --- a/src/viewimage.c +++ b/src/viewimage.c @@ -35,6 +35,7 @@ #include "backbuffer.h" #include "globals.h" #include "common.h" +#include "keyboard.h" //Probably not the best way, but it works... #define HAVE_CONFIG_H 1