From 5ba7f2d9a3f07f342afdf215a3307d5487cb6d43 Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Tue, 23 Jun 2009 02:13:06 +0200 Subject: [PATCH] rnd-20090623-1-src * started with integration of native Supaplex engine, using source code of Megaplex from Frank Schindler, based on original Supaplex engine * version number set to 3.2.6.2 --- ChangeLog | 7 + src/Makefile | 21 +- src/conftime.h | 2 +- src/engines.h | 1 + src/files.c | 3 + src/game.c | 27 + src/game.h | 1 + src/game_em/Makefile | 2 +- src/game_em/export.h | 6 +- src/game_em/main_em.h | 1 - src/game_sp/ASM.c | 205 ++ src/game_sp/ASM.h | 38 + src/game_sp/BitMapObject.c | 588 +++++ src/game_sp/BitMapObject.h | 72 + src/game_sp/BugsTerminals.c | 183 ++ src/game_sp/BugsTerminals.h | 23 + src/game_sp/Capture.c | 529 +++++ src/game_sp/Capture.h | 147 ++ src/game_sp/DDScrollBuffer.c | 382 ++++ src/game_sp/DDScrollBuffer.h | 29 + src/game_sp/DDSpriteBuffer.c | 232 ++ src/game_sp/DDSpriteBuffer.h | 28 + src/game_sp/Demo.c | 83 + src/game_sp/Demo.h | 22 + src/game_sp/DemoBufferObject.c | 240 ++ src/game_sp/DemoBufferObject.h | 24 + src/game_sp/DirectDrawGlobals.c | 47 + src/game_sp/DirectDrawGlobals.h | 23 + src/game_sp/DirectXGlobals.c | 94 + src/game_sp/DirectXGlobals.h | 26 + src/game_sp/Display.c | 160 ++ src/game_sp/Display.h | 33 + src/game_sp/DoGameStuff.c | 150 ++ src/game_sp/DoGameStuff.h | 20 + src/game_sp/Electrons.c | 653 ++++++ src/game_sp/Electrons.h | 30 + src/game_sp/ErrorReporting.c | 78 + src/game_sp/ErrorReporting.h | 19 + src/game_sp/Explosions.c | 337 +++ src/game_sp/Explosions.h | 21 + src/game_sp/FakeDeclares.c | 114 + src/game_sp/FakeDeclares.h | 69 + src/game_sp/FancyRestore.c | 22 + src/game_sp/FancyRestore.h | 17 + src/game_sp/GeneralTricks.c | 149 ++ src/game_sp/GeneralTricks.h | 21 + src/game_sp/Globals.c | 423 ++++ src/game_sp/Globals.h | 152 ++ src/game_sp/Infotrons.c | 449 ++++ src/game_sp/Infotrons.h | 18 + src/game_sp/InitGameConditions.c | 370 ++++ src/game_sp/InitGameConditions.h | 24 + src/game_sp/Input.c | 155 ++ src/game_sp/Input.h | 23 + src/game_sp/LevelSetPreviewForm.c | 41 + src/game_sp/LevelSetPreviewForm.h | 15 + src/game_sp/MainForm.c | 3362 +++++++++++++++++++++++++++++ src/game_sp/MainForm.h | 31 + src/game_sp/MainGameLoop.c | 233 ++ src/game_sp/MainGameLoop.h | 28 + src/game_sp/Makefile | 131 ++ src/game_sp/Marker.c | 274 +++ src/game_sp/Marker.h | 27 + src/game_sp/Murphy.c | 2344 ++++++++++++++++++++ src/game_sp/Murphy.h | 21 + src/game_sp/OrangeDisk.c | 86 + src/game_sp/OrangeDisk.h | 17 + src/game_sp/PathTools.c | 300 +++ src/game_sp/PathTools.h | 31 + src/game_sp/SettingsObject.c | 40 + src/game_sp/SettingsObject.h | 18 + src/game_sp/SnikSnaks.c | 703 ++++++ src/game_sp/SnikSnaks.h | 18 + src/game_sp/Sound.c | 178 ++ src/game_sp/Sound.h | 28 + src/game_sp/TickCountObject.c | 215 ++ src/game_sp/TickCountObject.h | 25 + src/game_sp/TopMost.c | 51 + src/game_sp/TopMost.h | 38 + src/game_sp/Zonk.c | 476 ++++ src/game_sp/Zonk.h | 18 + src/game_sp/export.h | 80 + src/game_sp/game_sp.h | 21 + src/game_sp/global.h | 47 + src/game_sp/main.c | 17 + src/game_sp/main_sp.h | 64 + src/game_sp/modAnimations.c | 69 + src/game_sp/modAnimations.h | 64 + src/game_sp/modGeneralTricks.c | 69 + src/game_sp/modGeneralTricks.h | 21 + src/game_sp/modMPX.c | 451 ++++ src/game_sp/modMPX.h | 40 + src/game_sp/vb_defs.h | 83 + src/game_sp/vb_lib.c | 146 ++ src/game_sp/vb_lib.h | 63 + src/game_sp/vb_types.h | 281 +++ src/game_sp/vb_vars.c | 15 + src/game_sp/vb_vars.h | 23 + src/main.h | 8 +- 99 files changed, 16890 insertions(+), 14 deletions(-) create mode 100644 src/game_sp/ASM.c create mode 100644 src/game_sp/ASM.h create mode 100644 src/game_sp/BitMapObject.c create mode 100644 src/game_sp/BitMapObject.h create mode 100644 src/game_sp/BugsTerminals.c create mode 100644 src/game_sp/BugsTerminals.h create mode 100644 src/game_sp/Capture.c create mode 100644 src/game_sp/Capture.h create mode 100644 src/game_sp/DDScrollBuffer.c create mode 100644 src/game_sp/DDScrollBuffer.h create mode 100644 src/game_sp/DDSpriteBuffer.c create mode 100644 src/game_sp/DDSpriteBuffer.h create mode 100644 src/game_sp/Demo.c create mode 100644 src/game_sp/Demo.h create mode 100644 src/game_sp/DemoBufferObject.c create mode 100644 src/game_sp/DemoBufferObject.h create mode 100644 src/game_sp/DirectDrawGlobals.c create mode 100644 src/game_sp/DirectDrawGlobals.h create mode 100644 src/game_sp/DirectXGlobals.c create mode 100644 src/game_sp/DirectXGlobals.h create mode 100644 src/game_sp/Display.c create mode 100644 src/game_sp/Display.h create mode 100644 src/game_sp/DoGameStuff.c create mode 100644 src/game_sp/DoGameStuff.h create mode 100644 src/game_sp/Electrons.c create mode 100644 src/game_sp/Electrons.h create mode 100644 src/game_sp/ErrorReporting.c create mode 100644 src/game_sp/ErrorReporting.h create mode 100644 src/game_sp/Explosions.c create mode 100644 src/game_sp/Explosions.h create mode 100644 src/game_sp/FakeDeclares.c create mode 100644 src/game_sp/FakeDeclares.h create mode 100644 src/game_sp/FancyRestore.c create mode 100644 src/game_sp/FancyRestore.h create mode 100644 src/game_sp/GeneralTricks.c create mode 100644 src/game_sp/GeneralTricks.h create mode 100644 src/game_sp/Globals.c create mode 100644 src/game_sp/Globals.h create mode 100644 src/game_sp/Infotrons.c create mode 100644 src/game_sp/Infotrons.h create mode 100644 src/game_sp/InitGameConditions.c create mode 100644 src/game_sp/InitGameConditions.h create mode 100644 src/game_sp/Input.c create mode 100644 src/game_sp/Input.h create mode 100644 src/game_sp/LevelSetPreviewForm.c create mode 100644 src/game_sp/LevelSetPreviewForm.h create mode 100644 src/game_sp/MainForm.c create mode 100644 src/game_sp/MainForm.h create mode 100644 src/game_sp/MainGameLoop.c create mode 100644 src/game_sp/MainGameLoop.h create mode 100644 src/game_sp/Makefile create mode 100644 src/game_sp/Marker.c create mode 100644 src/game_sp/Marker.h create mode 100644 src/game_sp/Murphy.c create mode 100644 src/game_sp/Murphy.h create mode 100644 src/game_sp/OrangeDisk.c create mode 100644 src/game_sp/OrangeDisk.h create mode 100644 src/game_sp/PathTools.c create mode 100644 src/game_sp/PathTools.h create mode 100644 src/game_sp/SettingsObject.c create mode 100644 src/game_sp/SettingsObject.h create mode 100644 src/game_sp/SnikSnaks.c create mode 100644 src/game_sp/SnikSnaks.h create mode 100644 src/game_sp/Sound.c create mode 100644 src/game_sp/Sound.h create mode 100644 src/game_sp/TickCountObject.c create mode 100644 src/game_sp/TickCountObject.h create mode 100644 src/game_sp/TopMost.c create mode 100644 src/game_sp/TopMost.h create mode 100644 src/game_sp/Zonk.c create mode 100644 src/game_sp/Zonk.h create mode 100644 src/game_sp/export.h create mode 100644 src/game_sp/game_sp.h create mode 100644 src/game_sp/global.h create mode 100644 src/game_sp/main.c create mode 100644 src/game_sp/main_sp.h create mode 100644 src/game_sp/modAnimations.c create mode 100644 src/game_sp/modAnimations.h create mode 100644 src/game_sp/modGeneralTricks.c create mode 100644 src/game_sp/modGeneralTricks.h create mode 100644 src/game_sp/modMPX.c create mode 100644 src/game_sp/modMPX.h create mode 100644 src/game_sp/vb_defs.h create mode 100644 src/game_sp/vb_lib.c create mode 100644 src/game_sp/vb_lib.h create mode 100644 src/game_sp/vb_types.h create mode 100644 src/game_sp/vb_vars.c create mode 100644 src/game_sp/vb_vars.h diff --git a/ChangeLog b/ChangeLog index 41f88faf..094e442b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-06-20 + * started with integration of native Supaplex engine, using source code + of Megaplex from Frank Schindler, based on original Supaplex engine + +2009-06-16 + * version number set to 3.2.6.2 + 2009-06-15 * version 3.2.6.1 released diff --git a/src/Makefile b/src/Makefile index bd5538ea..20b8f367 100644 --- a/src/Makefile +++ b/src/Makefile @@ -144,7 +144,7 @@ CONFIG_GAME_DIR = $(CONFIG_RO_GAME_DIR) $(CONFIG_RW_GAME_DIR) CONFIG_GAME = $(CONFIG_GAME_DIR) $(CONFIG_SCORE_ENTRIES) $(CONFIG_SPECIAL) CONFIG = $(CONFIG_GAME) $(JOYSTICK) -# DEBUG = -DDEBUG -g +DEBUG = -DDEBUG -g # PROFILING = $(PROFILING_FLAGS) # OPTIONS = $(DEBUG) -Wall # only for debugging purposes @@ -228,7 +228,10 @@ LIBGAME = $(LIBGAME_DIR)/libgame.a GAME_EM_DIR = game_em GAME_EM = $(GAME_EM_DIR)/game_em.a -RNDLIBS = $(LIBGAME) $(GAME_EM) +GAME_SP_DIR = game_sp +GAME_SP = $(GAME_SP_DIR)/game_sp.a + +RNDLIBS = $(LIBGAME) $(GAME_EM) $(GAME_SP) ICONBASE = windows_icon ifeq ($(PLATFORM),cross-win32) @@ -246,7 +249,7 @@ endif # build targets # ----------------------------------------------------------------------------- -all: libgame_dir game_em_dir $(PROGNAME) +all: libgame_dir game_em_dir game_sp_dir $(PROGNAME) $(PROGNAME): $(RNDLIBS) $(TIMESTAMP_FILE) $(OBJS) $(ICON) $(CC) $(PROFILING) $(OBJS) $(ICON) $(RNDLIBS) $(LDFLAGS) -o $(PROGNAME) @@ -261,6 +264,11 @@ game_em_dir: $(GAME_EM): @$(MAKE) -C $(GAME_EM_DIR) +game_sp_dir: + @$(MAKE) -C $(GAME_SP_DIR) +$(GAME_SP): + @$(MAKE) -C $(GAME_SP_DIR) + auto-conf: @for i in $(CNFS); do \ echo "$(CNFS_CMD) $$i > $$i"; \ @@ -276,7 +284,7 @@ conf_snd.h: conf_snd.c conf_mus.h: conf_mus.c @$(MAKE) auto-conf -$(TIMESTAMP_FILE): $(SRCS) $(LIBGAME) $(GAME_EM) +$(TIMESTAMP_FILE): $(SRCS) $(LIBGAME) $(GAME_EM) $(GAME_SP) @date '+"%Y-%m-%d %H:%M"' \ | sed -e 's/^/#define COMPILE_DATE_STRING /' \ > $(TIMESTAMP_FILE) @@ -291,9 +299,11 @@ $(ICON): clean-obj: $(MAKE) -C $(LIBGAME_DIR) clean $(MAKE) -C $(GAME_EM_DIR) clean + $(MAKE) -C $(GAME_SP_DIR) clean $(RM) $(OBJS) $(RM) $(LIBGAME) $(RM) $(GAME_EM) + $(RM) $(GAME_SP) clean-ico: $(RM) $(ICONBASE).ico @@ -327,11 +337,12 @@ valgrind: all dist-clean: clean-obj tags: - $(ETAGS) *.[ch] $(LIBGAME_DIR)/*.[ch] $(GAME_EM_DIR)/*.[ch] + $(ETAGS) *.[ch] $(LIBGAME_DIR)/*.[ch] $(GAME_EM_DIR)/*.[ch] $(GAME_SP_DIR)/*.[ch] depend: $(MAKE) -C $(LIBGAME_DIR) depend $(MAKE) -C $(GAME_EM_DIR) depend + $(MAKE) -C $(GAME_SP_DIR) depend for i in $(SRCS); do $(CPP) $(CFLAGS) -M $$i; done > .depend ifeq (.depend,$(wildcard .depend)) diff --git a/src/conftime.h b/src/conftime.h index e3b6bfc9..7d13d780 100644 --- a/src/conftime.h +++ b/src/conftime.h @@ -1 +1 @@ -#define COMPILE_DATE_STRING "2009-06-15 22:46" +#define COMPILE_DATE_STRING "2009-06-23 02:12" diff --git a/src/engines.h b/src/engines.h index 156a6398..715edef3 100644 --- a/src/engines.h +++ b/src/engines.h @@ -16,6 +16,7 @@ #include "libgame/libgame.h" #include "game_em/export.h" +#include "game_sp/export.h" /* ========================================================================= */ diff --git a/src/files.c b/src/files.c index bfa49881..239b85ec 100644 --- a/src/files.c +++ b/src/files.c @@ -6160,6 +6160,9 @@ void LoadLevelFromFileInfo(struct LevelInfo *level, case LEVEL_FILE_TYPE_SP: LoadLevelFromFileInfo_SP(level, level_file_info); +#if 1 + level->game_engine_type = GAME_ENGINE_TYPE_SP; +#endif break; case LEVEL_FILE_TYPE_DC: diff --git a/src/game.c b/src/game.c index d4e4cf3f..daf96fe5 100644 --- a/src/game.c +++ b/src/game.c @@ -4468,6 +4468,13 @@ void InitGame() /* blit playfield from scroll buffer to normal back buffer for fading in */ BlitScreenToBitmap_EM(backbuffer); } + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + { + InitGameEngine_SP(); + + /* blit playfield from scroll buffer to normal back buffer for fading in */ + BlitScreenToBitmap_SP(backbuffer); + } else { DrawLevel(); @@ -12341,6 +12348,10 @@ void GameActions() { GameActions_EM_Main(); } + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + { + GameActions_SP_Main(); + } else { GameActions_RND(); @@ -12363,6 +12374,22 @@ void GameActions_EM_Main() AdvanceFrameAndPlayerCounters(-1); /* advance counters for all players */ } +void GameActions_SP_Main() +{ + byte effective_action[MAX_PLAYERS]; + boolean warp_mode = (tape.playing && tape.warp_forward && !tape.pausing); + int i; + + for (i = 0; i < MAX_PLAYERS; i++) + effective_action[i] = stored_player[i].effective_action; + + GameActions_SP(effective_action, warp_mode); + + CheckLevelTime(); + + AdvanceFrameAndPlayerCounters(-1); /* advance counters for all players */ +} + void GameActions_RND() { int magic_wall_x = 0, magic_wall_y = 0; diff --git a/src/game.h b/src/game.h index 7a9bf984..c957974c 100644 --- a/src/game.h +++ b/src/game.h @@ -331,6 +331,7 @@ void StartGameActions(boolean, boolean, long); void GameActions(void); void GameActions_EM_Main(); +void GameActions_SP_Main(); void GameActions_RND(); void ScrollLevel(int, int); diff --git a/src/game_em/Makefile b/src/game_em/Makefile index aec69d09..4fc21cd0 100644 --- a/src/game_em/Makefile +++ b/src/game_em/Makefile @@ -1,7 +1,7 @@ # ============================================================================= # Rocks'n'Diamonds Makefile (game_em) # ----------------------------------------------------------------------------- -# (c) 1995-2005 Holger Schemel +# (c) 1995-2006 Holger Schemel # ----------------------------------------------------------------------------- # Emerald Mine for X11 © 2000,2001 David Tritscher # ============================================================================= diff --git a/src/game_em/export.h b/src/game_em/export.h index 05e7ae65..f1657123 100644 --- a/src/game_em/export.h +++ b/src/game_em/export.h @@ -1,5 +1,5 @@ -#ifndef EXPORT_H -#define EXPORT_H +#ifndef GAME_SP_EXPORT_H +#define GAME_SP_EXPORT_H /* ========================================================================= */ /* functions and definitions exported from game_em to main program */ @@ -743,4 +743,4 @@ extern void DrawGameDoorValues_EM(); extern void LoadEngineSnapshotValues_EM(); extern void SaveEngineSnapshotValues_EM(); -#endif /* EXPORT_H */ +#endif /* GAME_SP_EXPORT_H */ diff --git a/src/game_em/main_em.h b/src/game_em/main_em.h index 87e9d952..add5ae09 100644 --- a/src/game_em/main_em.h +++ b/src/game_em/main_em.h @@ -77,7 +77,6 @@ /* often used screen positions */ #define ORIG_MENU_SX ((ORIG_SCR_MENUX - SCR_MENUX) * TILEX / 2) #define ORIG_MENU_SY 0 -#define SY 8 #define SX 8 #define SY 8 #define SXSIZE (SCR_FIELDX * TILEX) diff --git a/src/game_sp/ASM.c b/src/game_sp/ASM.c new file mode 100644 index 00000000..6ef27ee3 --- /dev/null +++ b/src/game_sp/ASM.c @@ -0,0 +1,205 @@ +// ---------------------------------------------------------------------------- +// ASM.c +// ---------------------------------------------------------------------------- + +#include "ASM.h" + +static char *VB_Name = "modASM"; +// --- Option Explicit + +// PseudoRegisters: +// Public ax%, bx% +// --- const int ByteMask = 0xFF; +int cmpFlag; + +void Neg(int *Val) +{ + *Val = -*Val; +} + +void Mov(int *Var, int Val) +{ + *Var = Val; +} + +void MovLowByte(int *Var, int Val) +{ + *Var = (*Var & 0xFF00) | (Val & 0xFF); +} + +void MovHighByte(int *Var, int Val) +{ + int Tmp; + + Tmp = Val & 0x7F; + Tmp = 0x100 * Tmp; + if ((Val & 0x80) != 0) + Tmp = Tmp | 0x8000; + + *Var = (*Var & 0xFF) | Tmp; +} + +int LowByte(int Var) +{ + int LowByte; + + // Dim Tmp As Byte + LowByte = (Var & 0xFF); + // LowByte = ByteToInt(Tmp) + + return LowByte; +} + +int HighByte(int Var) +{ + int HighByte; + + if (Var & 0x8000) + { + HighByte = ((Var & 0x7FFF) / 0x100) | 0x80; + } + else + { + HighByte = Var / 0x100; + } + + return HighByte; +} + +int SgnHighByte(int Var) // extends the signum to 16 bit +{ + int SgnHighByte; + + if (Var & 0x8000) + { + SgnHighByte = ((Var & 0x7FFF) / 0x100) | 0xFF80; + } + else + { + SgnHighByte = Var / 0x100; + } + + return SgnHighByte; +} + +boolean Less() +{ + boolean Less; + + Less = (cmpFlag < 0); + + return Less; +} + +boolean GreaterOrEqual() +{ + boolean GreaterOrEqual; + + GreaterOrEqual = (0 <= cmpFlag); + + return GreaterOrEqual; +} + +boolean Equal() +{ + boolean Equal; + + Equal = (0 == cmpFlag); + + return Equal; +} + +void CMP(int A, int B) +{ + cmpFlag = A - B; +} + +void Add(int *A, int B) +{ + *A = *A + B; +} + +void MySub(int *A, int B) +{ + *A = *A - B; +} + +int SHR(int Var, int Count) +{ + int SHR; + + int i; + + if (Var & 0x8000) + { + Var = ((Var & 0x7FFF) / 2) | 0x4000; + } + else + { + Var = Var / 2; + } + + for (i = 2; i <= Count; i++) + { + Var = Var / 2; + } + + return SHR; +} + +int SHL(int Var, int Count) +{ + int SHL; + + int i; + + for (i = 1; i <= Count; i++) + { + Var = Var & 0x7FFF; + if ((Var & 0x4000) != 0) + { + Var = (2 * (Var & 0x3FFF)) | 0x8000; + } + else + { + Var = 2 * Var; + } + } + + return SHL; +} + +int ByteToInt(byte B) +{ + int ByteToInt; + + if ((B & 0x80) == 0x80) + { + ByteToInt = -(0xFF - B + 1); + } + else + { + ByteToInt = B; + } + + return ByteToInt; +} + +byte IntToByte(int i) +{ + byte IntToByte; + + // IntToByte = CByte(i & 0xFF); + IntToByte = (byte)(i & 0xFF); + + return IntToByte; +} + +void XCHG(int A, int B) +{ + int Tmp; + + Tmp = B; + B = A; + A = Tmp; +} diff --git a/src/game_sp/ASM.h b/src/game_sp/ASM.h new file mode 100644 index 00000000..3b277322 --- /dev/null +++ b/src/game_sp/ASM.h @@ -0,0 +1,38 @@ +// ---------------------------------------------------------------------------- +// ASM.h +// ---------------------------------------------------------------------------- + +#ifndef ASM_H +#define ASM_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +#define ByteMask (0xFF) + +extern void Add(int *A, int B); +extern int ByteToInt(byte B); +extern void CMP(int A, int B); +extern boolean Equal(); +extern boolean GreaterOrEqual(); +extern int HighByte(int Var); +extern byte IntToByte(int i); +extern boolean Less(); +extern int LowByte(int Var); +extern void Mov(int *Var, int Val); +extern void MovHighByte(int *Var, int Val); +extern void MovLowByte(int *Var, int Val); +extern void MySub(int *A, int B); +extern void Neg(int *Val); +extern int SHL(int Var, int Count); +extern int SHR(int Var, int Count); +extern int SgnHighByte(int Var); +extern void XCHG(int A, int B); + +extern int cmpFlag; + +#endif /* ASM_H */ diff --git a/src/game_sp/BitMapObject.c b/src/game_sp/BitMapObject.c new file mode 100644 index 00000000..dafb9658 --- /dev/null +++ b/src/game_sp/BitMapObject.c @@ -0,0 +1,588 @@ +// ---------------------------------------------------------------------------- +// BitMapObject.c +// ---------------------------------------------------------------------------- + +#include "BitMapObject.h" + +static void ConvertToVBPalette(); +static long Get_ByteWidth(); +static long Get_LineLength(); +static void ReDimArrays(); + +// --- VERSION 1.0 CLASS +// --- BEGIN +// --- MultiUse = -1 'True // True +// --- Persistable = 0 'NotPersistable // NotPersistable +// --- DataBindingBehavior = 0 'vbNone // vbNone +// --- DataSourceBehavior = 0 'vbNone // vbNone +// --- MTSTransactionMode = 0 'NotAnMTSObject // NotAnMTSObject +// --- END + +static char *VB_Name = "BitMapObject"; +static boolean VB_GlobalNameSpace = False; +static boolean VB_Creatable = True; +static boolean VB_PredeclaredId = False; +static boolean VB_Exposed = False; +// --- Option Explicit + +// info von http://web.usxchange.net/elmo/bmp.htm + +// A BMP file consists of the four following parts: +// +// 1.BITMAPFILEHEADER +// 2.BITMAPINFOHEADER +// 3.A color table of RGBQUAD structures (1, 4 & 8 bit only) +// 4.An array of bytes for the actual image data + +// 1.BITMAPFILEHEADER +// 1.bfType +// Declared an unsigned integer. But, this is just to reserve space for 2 bytes. +// The 2 bytes must be the 2 characters BM to indicate a BitMap file. +// 2.bfSize +// Total size of file in bytes. +// 3.bfReserved1 +// Always zero (ignore). +// 4.bfReserved2 +// Always zero (ignore). +// 5.bfOffBits +// Specifies the byte offset from the BITMAPFILEHEADER structure to the actual bitmap data in the file. +// ::: #ifndef HAS_BitmapFileHeaderType +// ::: typedef struct // { /* bmfh */ +// ::: { +// ::: byte bfTypeB; +// ::: byte bfTypeM; +// ::: long bfSize; +// ::: int bfReserved1; +// ::: int bfReserved2; +// ::: long bfOffBits; +// ::: } BitmapFileHeaderType; +// ::: #define HAS_BitmapFileHeaderType +// ::: #endif + +// 2.BITMAPINFOHEADER +// 1.biSize +// Size of BITMAPINFOHEADER structure (should always be 40). +// 2.biWidth +// Width of image in pixels. +// 3.biHeight +// Height of image in pixels. +// 4.biPlanes +// Always one (ignore). +// 5.biBitCount +// Specifies the number of bits per pixel. This value must be 1, 4, 8, or 24. +// 6.biCompression +// Specifies the type of compression. +// 1.BI_RGB No compression. +// 2.BI_RLE8 8 bit RLE +// 3.BI_RLE4 4 bit RLE +// 7.biSizeImage +// Specifies the size, in bytes, of the image data. May be zero if the bitmap is in the BI_RGB format. +// 8.biXPelsPerMeter +// Ignore. +// 9.biYPelsPerMeter +// Ignore. +// 10.biClrUsed +// Specifies the number of color indices in the color table. Zero indicaes the bitmap uses the maximum number of colors corresponding to the value of the +// biBitCount member e.g. 8 bit -> 256 colors. +// +// The maximum number of colors = 2N. Where N = biBitCount. 2N is the same as 1 << N. The same as you can get powers of 10 by shifting the decimal point +// in a decimal number, only it is binary. +// 11.biClrImportant +// Ignore. +// ::: #ifndef HAS_BitmapInfoHeaderType +// ::: typedef struct // { /* bmih */ +// ::: { +// ::: long biSize; +// ::: long biWidth; +// ::: long biHeight; +// ::: int biPlanes; +// ::: int biBitCount; +// ::: long biCompression; +// ::: long biSizeImage; +// ::: long biXPelsPerMeter; +// ::: long biYPelsPerMeter; +// ::: long biClrUsed; +// ::: long biClrImportant; +// ::: } BitmapInfoHeaderType; +// ::: #define HAS_BitmapInfoHeaderType +// ::: #endif + +// 3.A color table of RGBQUAD structures (1, 4 & 8 bit only) +// RGBQUAD structure is self explanatory. +// ::: #ifndef HAS_RGBQUADType +// ::: typedef struct // { /* rgbq */ +// ::: { +// ::: byte rgbBlue; +// ::: byte rgbGreen; +// ::: byte rgbRed; +// ::: byte rgbReserved; +// ::: } RGBQUADType; +// ::: #define HAS_RGBQUADType +// ::: #endif + +RGBQUADType *ColorTable; +long *VBPalette; + +// 4.An array of bytes for the actual image data +// Bits per pixel & compression determined by biBitCount & biCompression. + +byte *ImageDataBytes; + +// ###################################################################################################### + +BitmapFileHeaderType BMFH; +BitmapInfoHeaderType BMIH; + +static long Get_LineLength() +{ + static long LineLength; + + LineLength = 4 * (((Get_ByteWidth() - 1) / 4) + 1); + + return LineLength; +} + +static long Get_ByteWidth() +{ + static long ByteWidth; + + ByteWidth = BMIH.biWidth * BMIH.biBitCount / 8; + + return ByteWidth; +} + +void BitMapObject_CreateAtSize(long XPixels, long YPixels, long BitsPerPixel) +{ + { + BMIH.biWidth = XPixels; + BMIH.biHeight = YPixels; + BMIH.biSize = 40; + BMIH.biBitCount = BitsPerPixel; + BMIH.biClrUsed = (1 << BMIH.biBitCount); + BMIH.biPlanes = 1; + BMIH.biClrImportant = BMIH.biClrUsed; + BMIH.biCompression = 0; + } + { + BMFH.bfTypeB = 0x42; // B' + BMFH.bfTypeM = 0x4D; // M' + } + ReDimArrays(); +} + +void BitMapObject_CreateFromFile(char *Path) +{ + long FNum; + + FNum = FreeFile(); + if (! FileExists(Path)) + return; + + if (FileLen(Path) < (Len(BMFH) + Len(BMIH))) + return; + + FNum = fopen(Path, "rb"); + FILE_GET(FNum, -1, &BMFH, sizeof(BMFH)); + FILE_GET(FNum, -1, &BMIH, sizeof(BMIH)); + ReDimArrays(); + { + if (BMIH.biCompression != 0) + { + Err.Raise(600, "BitMapObject", "Cannot read compressed BMP files"); + fclose(FNum); + return; + } + + if (BMIH.biBitCount < 9) + { + FILE_GET(FNum, -1, &ColorTable, sizeof(ColorTable)); + } + + } + FILE_GET(FNum, 1 + BMFH.bfOffBits, &ImageDataBytes, sizeof(ImageDataBytes)); + fclose(FNum); + if (BMIH.biBitCount < 9) + ConvertToVBPalette(); +} + +void BitMapObject_SaveToFile(char *Path) +{ + long FNum; + + BMFH.bfOffBits = Len(BMFH) + Len(BMIH); + if (BMIH.biBitCount < 9) + BMFH.bfOffBits = BMFH.bfOffBits + ((1 << BMIH.biBitCount)) * Len(ColorTable[0]); + + BMIH.biSizeImage = Get_LineLength() * BMIH.biHeight; + BMFH.bfSize = BMFH.bfOffBits + BMIH.biSizeImage; + FNum = FreeFile(); + FNum = fopen(Path, "wb"); + FILE_PUT(FNum, -1, &BMFH, sizeof(BMFH)); + FILE_PUT(FNum, -1, &BMIH, sizeof(BMIH)); + if (BMIH.biBitCount < 9) + { + FILE_PUT(FNum, -1, &ColorTable, sizeof(ColorTable)); + } + + FILE_PUT(FNum, -1, &ImageDataBytes, sizeof(ImageDataBytes)); + fclose(FNum); +} + +static void ConvertToVBPalette() +{ + long ColMax, i; + + ColMax = UBound(ColorTable); + for (i = 0; i <= ColMax; i++) + { + { + VBPalette[i] = RGB(ColorTable[i].rgbRed, ColorTable[i].rgbGreen, ColorTable[i].rgbBlue); + } + } +} + +static void ReDimArrays() +{ + { + if (BMIH.biBitCount < 9) + { + BMIH.biClrUsed = (1 << BMIH.biBitCount); + ColorTable = REDIM_1D(sizeof(RGBQUADType), 0, BMIH.biClrUsed - 1); + VBPalette = REDIM_1D(sizeof(long), 0, BMIH.biClrUsed - 1); + } + + if (0 < Get_LineLength() && 0 < BMIH.biHeight) + { + ImageDataBytes = REDIM_2D(sizeof(byte), 0, Get_LineLength() - 1, 0, BMIH.biHeight - 1); + } + + } +} + +long BitMapObject_Get_Palette(long Index) +{ + long Palette; + + Palette = VBPalette[Index]; + + return Palette; +} + +void BitMapObject_Let_Palette(long Index, long NewVal) +{ + VBPalette[Index] = NewVal & 0xFFFFFF; + { + ColorTable[Index].rgbRed = (NewVal & 0xFF) / 0x1; + ColorTable[Index].rgbGreen = (NewVal & 0xFF00) / 0x100; + ColorTable[Index].rgbBlue = (NewVal & 0xFF0000) / 0x10000; + } +} + +long BitMapObject_Get_ColorsUsed() +{ + long ColorsUsed; + + if (BMIH.biBitCount < 9) + { + ColorsUsed = (1 << BMIH.biBitCount); + } + else + { + ColorsUsed = 0; + } + + return ColorsUsed; +} + +long BitMapObject_Get_ColorIndex(long X, long Y) +{ + long ColorIndex; + + long ColIndex, NewX, BitPos, nY; + + if (8 < BMIH.biBitCount) + { + Err.Raise(600, "BitmapObject", "I have ! Palette in this ColorDepthMode"); + ColorIndex = -1; + return ColorIndex; + } + + nY = BMIH.biHeight - 1 - Y; + switch (BMIH.biBitCount) + { + case 1: + ColIndex = ImageDataBytes[X / 8, nY]; + BitPos = 7 - (X % 8); + NewX = (1 << BitPos); + if ((NewX && ColIndex) == 0) + { + ColorIndex = 0; + } + else + { + ColorIndex = 1; + } + + break; + + case 4: + ColIndex = ImageDataBytes[X / 2, nY]; + if ((X % 2) == 0) + { + ColorIndex = (ColIndex & 0xF0) / 0x10; + } + else + { + ColorIndex = (ColIndex & 0xF); + } + + break; + + case 8: + ColorIndex = ImageDataBytes[X, nY]; + break; + + default: + Err.Raise(600, "BitmapObject", "Invalid bpx value"); + break; + } + + return ColorIndex; +} + +void BitMapObject_Let_ColorIndex(long X, long Y, long ColorIndex) +{ + long ColIndex, ByteVal, NewX, BitPos, nY; + + if (8 < BMIH.biBitCount) + { + Err.Raise(600, "BitmapObject", "I have ! Palette in this ColorDepthMode"); + return; + } + + nY = BMIH.biHeight - 1 - Y; + switch (BMIH.biBitCount) + { + case 1: + ByteVal = ImageDataBytes[X / 8, nY]; + BitPos = 7 - (X % 8); + NewX = (1 << BitPos); + ColIndex = ColorIndex * NewX; + if (ColIndex == 0) + { + ByteVal = (ByteVal & (! NewX)); + } + else + { + ByteVal = (ByteVal | NewX); + } + + ImageDataBytes[X / 8, nY] = ByteVal; + break; + + case 4: + ByteVal = ImageDataBytes[X / 2, nY]; + if ((X % 2) == 0) + { + ByteVal = (ByteVal & 0xF) + ColorIndex * 0x10; + } + else + { + ByteVal = (ByteVal & 0xF0) + ColorIndex; + } + + ImageDataBytes[X / 2, nY] = ByteVal; + break; + + case 8: + ImageDataBytes[X, nY] = ColorIndex; + break; + + case 24: + Err.Raise(600, "BitmapObject", "Invalid bpx value"); + break; + } +} + +long BitMapObject_Get_Point(long X, long Y) +{ + long Point; + + long ColIndex, NewX, BitPos, nY; + + nY = BMIH.biHeight - 1 - Y; + switch (BMIH.biBitCount) + { + case 1: + ColIndex = ImageDataBytes[X / 8, nY]; + BitPos = 7 - (X % 8); + NewX = (1 << BitPos); + if ((NewX && ColIndex) == 0) + { + ColIndex = 0; + } + else + { + ColIndex = 1; + } + + Point = VBPalette[ColIndex]; + break; + + case 4: + ColIndex = ImageDataBytes[X / 2, nY]; + if ((X % 2) == 0) + { + ColIndex = (ColIndex & 0xF0) / 0x10; + } + else + { + ColIndex = (ColIndex & 0xF); + } + + Point = VBPalette[ColIndex]; + break; + + case 8: + ColIndex = ImageDataBytes[X, nY]; + Point = VBPalette[ColIndex]; + break; + + case 24: + NewX = 3 * X; + Point = ImageDataBytes[NewX, nY] * 0x10000; + Point = Point + ImageDataBytes[NewX + 1, nY] * 0x100; + Point = Point + ImageDataBytes[NewX + 2, nY]; + break; + + default: + Err.Raise(600, "BitmapObject", "Invalid bpx value"); + break; + } + + return Point; +} + +void BitMapObject_Let_Point(long X, long Y, long NewColor) +{ + long ColIndex, ByteVal, NewX, BitPos, nY; + + nY = BMIH.biHeight - 1 - Y; + switch (BMIH.biBitCount) + { + case 1: + ColIndex = GetPaletteIndex(NewColor); + ByteVal = ImageDataBytes[X / 8, nY]; + BitPos = 7 - (X % 8); + NewX = (1 << BitPos); + ColIndex = ColIndex * NewX; + if (ColIndex == 0) + { + ByteVal = (ByteVal & (! NewX)); + } + else + { + ByteVal = (ByteVal | NewX); + } + + ImageDataBytes[X / 8, nY] = ByteVal; + break; + + case 4: + ColIndex = GetPaletteIndex(NewColor); + ByteVal = ImageDataBytes[X / 2, nY]; + if ((X % 2) == 0) + { + ByteVal = (ByteVal & 0xF) + ColIndex * 0x10; + } + else + { + ByteVal = (ByteVal & 0xF0) + ColIndex; + } + + ImageDataBytes[X / 2, nY] = ByteVal; + break; + + case 8: + ImageDataBytes[X, nY] = GetPaletteIndex(NewColor); + break; + + case 24: + NewX = 3 * X; + ImageDataBytes[NewX, nY] = (NewColor & 0xFF0000) / 0x10000; // B + ImageDataBytes[NewX + 1, nY] = (NewColor & 0xFF00) / 0x100; // G + ImageDataBytes[NewX + 2, nY] = (NewColor & 0xFF); // R + break; + + default: + Err.Raise(600, "BitmapObject", "Invalid bpx value"); + break; + } +} + +int BitMapObject_GetPaletteIndex(long Color) +{ + int GetPaletteIndex; + + long i, ColMax; + + ColMax = UBound(VBPalette); + for (i = 0; i <= ColMax; i++) + { + if (VBPalette[i] == Color) + break; + } + + if (ColMax < i) // Error - Color not in Palette! + i = -1; + + GetPaletteIndex = i; + + return GetPaletteIndex; +} + +long BitMapObject_Get_Width() +{ + long Width; + + Width = BMIH.biWidth; + + return Width; +} + +long BitMapObject_Get_Height() +{ + long Height; + + Height = BMIH.biHeight; + + return Height; +} + +BitMapObject BitMapObject_GetStretchCopy(float StretchVal) +{ + BitMapObject GetStretchCopy; + + long nWidth, nHeight, iX, iY; + + // GetStretchCopy = New BitMapObject; // (handle this later, if needed) + nWidth = StretchVal * BMIH.biWidth; + nHeight = StretchVal * BMIH.biHeight; + GetStretchCopy.CreateAtSize(nWidth, nHeight, CLng(BMIH.biBitCount)); + nWidth = nWidth - 1; + nHeight = nHeight - 1; + for (iX = 0; iX <= BMIH.biClrUsed - 1; iX++) + { + GetStretchCopy.Let_Palette(iX, Palette(iX)); + } + + for (iY = 0; iY <= nHeight; iY++) + { + for (iX = 0; iX <= nWidth; iX++) + { + GetStretchCopy.Let_ColorIndex(iX, iY, ColorIndex(Int(iX / StretchVal), Int(iY / StretchVal))); + } + } + + return GetStretchCopy; +} diff --git a/src/game_sp/BitMapObject.h b/src/game_sp/BitMapObject.h new file mode 100644 index 00000000..64c10d94 --- /dev/null +++ b/src/game_sp/BitMapObject.h @@ -0,0 +1,72 @@ +// ---------------------------------------------------------------------------- +// BitMapObject.h +// ---------------------------------------------------------------------------- + +#ifndef BITMAPOBJECT_H +#define BITMAPOBJECT_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +#ifndef HAS_BitmapFileHeaderType +typedef struct // { /* bmfh */ +{ + byte bfTypeB; + byte bfTypeM; + long bfSize; + int bfReserved1; + int bfReserved2; + long bfOffBits; +} BitmapFileHeaderType; +#define HAS_BitmapFileHeaderType +#endif + +#ifndef HAS_BitmapInfoHeaderType +typedef struct // { /* bmih */ +{ + long biSize; + long biWidth; + long biHeight; + int biPlanes; + int biBitCount; + long biCompression; + long biSizeImage; + long biXPelsPerMeter; + long biYPelsPerMeter; + long biClrUsed; + long biClrImportant; +} BitmapInfoHeaderType; +#define HAS_BitmapInfoHeaderType +#endif + +#ifndef HAS_RGBQUADType +typedef struct // { /* rgbq */ +{ + byte rgbBlue; + byte rgbGreen; + byte rgbRed; + byte rgbReserved; +} RGBQUADType; +#define HAS_RGBQUADType +#endif + +extern void BitMapObject_CreateAtSize(long XPixels, long YPixels, long BitsPerPixel); +extern void BitMapObject_CreateFromFile(char *Path); +extern int BitMapObject_GetPaletteIndex(long Color); +extern BitMapObject BitMapObject_GetStretchCopy(float StretchVal); +extern long BitMapObject_Get_ColorIndex(long X, long Y); +extern long BitMapObject_Get_ColorsUsed(); +extern long BitMapObject_Get_Height(); +extern long BitMapObject_Get_Palette(long Index); +extern long BitMapObject_Get_Point(long X, long Y); +extern long BitMapObject_Get_Width(); +extern void BitMapObject_Let_ColorIndex(long X, long Y, long ColorIndex); +extern void BitMapObject_Let_Palette(long Index, long NewVal); +extern void BitMapObject_Let_Point(long X, long Y, long NewColor); +extern void BitMapObject_SaveToFile(char *Path); + +#endif /* BITMAPOBJECT_H */ diff --git a/src/game_sp/BugsTerminals.c b/src/game_sp/BugsTerminals.c new file mode 100644 index 00000000..f5603959 --- /dev/null +++ b/src/game_sp/BugsTerminals.c @@ -0,0 +1,183 @@ +// ---------------------------------------------------------------------------- +// BugsTerminals.c +// ---------------------------------------------------------------------------- + +#include "BugsTerminals.h" + +static char *VB_Name = "modBugTerminal"; +// --- Option Explicit + +long GetTickCount(); + +byte *TerminalState; +int TerminalMaxCycles; +#define aniTerminal (0x80) + +// ========================================================================== +// SUBROUTINE +// Animate bugs +// ========================================================================== + +int subAnimateBugs(int si) +{ + int subAnimateBugs; + + int ax, bx, cx, dx, di; + int ah, bh, ch, dh, al, bl, cl, dl; + + if (fiBug != LowByte(PlayField16[si])) + return subAnimateBugs; + + if (0 != (TimerVar & 3)) + return subAnimateBugs; + + bl = SgnHighByte(PlayField16[si]); // get and increment sequence# + bl = bl + 1; + if (bl >= 0xE) + { + bl = subGetRandomNumber(); // generate new random number + bl = -((bl & 0x3F) + 0x20); + } + + MovHighByte(&PlayField16[si], bl); // save sequence# + if (bl < 0) // bug sleeps / is inactive + return subAnimateBugs; + + // now the bug is active! Beware Murphy! + if ((ByteMask && PlayField16[si - FieldWidth - 1]) == fiMurphy) + goto markPlaySound; + + if ((ByteMask && PlayField16[si - FieldWidth]) == fiMurphy) + goto markPlaySound; + + if ((ByteMask && PlayField16[si - FieldWidth + 1]) == fiMurphy) + goto markPlaySound; + + if ((ByteMask && PlayField16[si - 1]) == fiMurphy) + goto markPlaySound; + + if ((ByteMask && PlayField16[si + 1]) == fiMurphy) + goto markPlaySound; + + if ((ByteMask && PlayField16[si + FieldWidth - 1]) == fiMurphy) + goto markPlaySound; + + if ((ByteMask && PlayField16[si + FieldWidth]) == fiMurphy) + goto markPlaySound; + + if ((ByteMask && PlayField16[si + FieldWidth + 1]) == fiMurphy) + goto markPlaySound; + + goto markDisplay; + +markPlaySound: + subSoundFXBug(); // play dangerous sound + +markDisplay: + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + cx = aniBug[bl]; + StretchedSprites.BltEx(GetStretchX(si), GetStretchY(si), cx); + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + return subAnimateBugs; +} // subAnimateBugs + +// ========================================================================== +// SUBROUTINE +// Animate terminals +// ========================================================================== +int subAnimateTerminals(int si) +{ + int subAnimateTerminals; + + int bl, ax, al, X, Y; + + if (LowByte(PlayField16[si]) != fiTerminal) + return subAnimateTerminals; + + bl = HighByte(PlayField16[si]); + if ((bl & 0x80) == 0x80) + bl = (bl | 0xFF00); + + bl = bl + 1; + if (bl <= 0) + { + MovHighByte(&PlayField16[si], bl); + return subAnimateTerminals; + } + + bl = -(subGetRandomNumber() & TerminalMaxCycles); // generate new random number + MovHighByte(&PlayField16[si], bl); // save new sequence# + bl = TerminalState[si] + 1; + if (bl == 8) + { + bl = 0; + } + else if (15 < bl) + { + bl = 8; + } + + TerminalState[si] = bl; + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + al = aniTerminal + bl; + X = GetStretchX(si); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, al); + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + return subAnimateTerminals; +} // subAnimateElectrons + +// ========================================================================== +// SUBROUTINE +// Randomize random number generator +// ========================================================================== + +int subRandomize() +{ + int subRandomize; + + long Tick, Tmp; + + Tick = GetTickCount(); + Tmp = ((Tick ^ (long)(Tick / (1 << 16))) & 0xFFFF); + RandomSeed = 0x7FFF & Tmp; + if ((Tmp & 0x8000) != 0) + RandomSeed = RandomSeed | 0x8000; + + return subRandomize; +} // subRandomize + + +// ========================================================================== +// SUBROUTINE +// Generate new random number, first method (see also sub_g_8580) +// ========================================================================== + +int subGetRandomNumber() +{ + int subGetRandomNumber; + + long Tmp, RSeed; + + RSeed = (long)(0x7FFF & RandomSeed); + if (0x8000 == (RandomSeed & 0x8000)) + RSeed = RSeed | 0x8000; + + Tmp = 0xFFFF & (((0x5E5 * RandomSeed) & 0xFFFF) + 0x31); + RandomSeed = 0x7FFF & Tmp; + if ((Tmp & 0x8000) != 0) + RandomSeed = RandomSeed | 0x8000; + + subGetRandomNumber = Tmp / 2; + // Mov ax, randomseed + // Mov bx, &H5E5 + // mul bx ' dx:ax = reg * ax + // Add ax, &H31 + // Mov randomseed, ax + // shr ax,1 + + return subGetRandomNumber; +} // subGetRandomNumber + diff --git a/src/game_sp/BugsTerminals.h b/src/game_sp/BugsTerminals.h new file mode 100644 index 00000000..4ec01cd4 --- /dev/null +++ b/src/game_sp/BugsTerminals.h @@ -0,0 +1,23 @@ +// ---------------------------------------------------------------------------- +// BugsTerminals.h +// ---------------------------------------------------------------------------- + +#ifndef BUGSTERMINALS_H +#define BUGSTERMINALS_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern int subAnimateBugs(int si); +extern int subAnimateTerminals(int si); +extern int subGetRandomNumber(); +extern int subRandomize(); + +extern byte *TerminalState; +extern int TerminalMaxCycles; + +#endif /* BUGSTERMINALS_H */ diff --git a/src/game_sp/Capture.c b/src/game_sp/Capture.c new file mode 100644 index 00000000..96997f67 --- /dev/null +++ b/src/game_sp/Capture.c @@ -0,0 +1,529 @@ +// ---------------------------------------------------------------------------- +// Capture.c +// ---------------------------------------------------------------------------- + +#include "Capture.h" + +static char *VB_Name = "CaptureModule"; +// -------------------------------------------------------------------- +// '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +// +// Visual Basic 4.0 16/32 Capture Routines +// +// This module contains several routines for capturing windows into a +// picture. All the routines work on both 16 and 32 bit Windows +// platforms. +// The routines also have palette support. +// +// CreateBitmapPicture - Creates a picture object from a bitmap and +// palette. +// CaptureWindow - Captures any window given a window handle. +// CaptureActiveWindow - Captures the active window on the desktop. +// CaptureForm - Captures the entire form. +// CaptureClient - Captures the client area of a form. +// CaptureScreen - Captures the entire screen. +// PrintPictureToFitPage - prints any picture as big as possible on +// the page. +// +// NOTES +// - No error trapping is included in these routines. +// '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +// +// --- Option Explicit +// --- Option Base 0 + +// ::: #ifndef HAS_PALETTEENTRY +// ::: typedef struct +// ::: { +// ::: byte peRed; +// ::: byte peGreen; +// ::: byte peBlue; +// ::: byte peFlags; +// ::: } PALETTEENTRY; +// ::: #define HAS_PALETTEENTRY +// ::: #endif + +// ::: #ifndef HAS_LOGPALETTE +// ::: typedef struct +// ::: { +// ::: int palVersion; +// ::: int palNumEntries; +// ::: PALETTEENTRY palPalEntry[255]; // Enough for 256 colors. +// ::: } LOGPALETTE; +// ::: #define HAS_LOGPALETTE +// ::: #endif + +// ::: #ifndef HAS_GUID +// ::: typedef struct +// ::: { +// ::: long Data1; +// ::: int Data2; +// ::: int Data3; +// ::: byte Data4[7]; +// ::: } GUID; +// ::: #define HAS_GUID +// ::: #endif + +#if Win32 + +#define RASTERCAPS (38) +#define RC_PALETTE (0x100) +#define SIZEPALETTE (104) + +// ::: #ifndef HAS_RECT +// ::: typedef struct +// ::: { +// ::: long left; +// ::: long top; +// ::: long right; +// ::: long bottom; +// ::: } RECT; +// ::: #define HAS_RECT +// ::: #endif + +long CreateCompatibleDC(long hDC); +long CreateCompatibleBitmap(long hDC, long nWidth, long nHeight); +long GetDeviceCaps(long hDC, long iCapabilitiy); +long GetSystemPaletteEntries(long hDC, long wStartIndex, long wNumEntries, PALETTEENTRY lpPaletteEntries); +long CreatePalette(LOGPALETTE lpLogPalette); +long SelectObject(long hDC, long hObject); +long BitBlt(long hDCDest, long XDest, long YDest, long nWidth, long nHeight, long hDCSrc, long XSrc, long YSrc, long dwRop); +long DeleteDC(long hDC); +long GetForegroundWindow(); +long SelectPalette(long hDC, long hPalette, long bForceBackground); +long RealizePalette(long hDC); +long GetWindowDC(long hWnd); +long GetDC(long hWnd); +long GetWindowRect(long hWnd, RECT lpRect); +long ReleaseDC(long hWnd, long hDC); +long GetDesktopWindow(); + +// ::: #ifndef HAS_PicBmp +// ::: typedef struct +// ::: { +// ::: long Size; +// ::: long Type; +// ::: long hBmp; +// ::: long hPal; +// ::: long Reserved; +// ::: } PicBmp; +// ::: #define HAS_PicBmp +// ::: #endif + +long OleCreatePictureIndirect(PicBmp PicDesc, GUID RefIID, long fPictureOwnsHandle, IPicture IPic); + +#elif Win16 + +#define RASTERCAPS (38) +#define RC_PALETTE (0x100) +#define SIZEPALETTE (104) + +// ::: #ifndef HAS_RECT +// ::: typedef struct +// ::: { +// ::: int left; +// ::: int top; +// ::: int right; +// ::: int bottom; +// ::: } RECT; +// ::: #define HAS_RECT +// ::: #endif + +int CreateCompatibleDC(int hDC); +int CreateCompatibleBitmap(int hDC, int nWidth, int nHeight); +int GetDeviceCaps(int hDC, int iCapabilitiy); +int GetSystemPaletteEntries(int hDC, int wStartIndex, int wNumEntries, PALETTEENTRY lpPaletteEntries); +int CreatePalette(LOGPALETTE lpLogPalette); +int SelectObject(int hDC, int hObject); +int BitBlt(int hDCDest, int XDest, int YDest, int nWidth, int nHeight, int hDCSrc, int XSrc, int YSrc, long dwRop); +int DeleteDC(int hDC); +int GetForegroundWindow(); +int SelectPalette(int hDC, int hPalette, int bForceBackground); +int RealizePalette(int hDC); +int GetWindowDC(int hWnd); +int GetDC(int hWnd); +int GetWindowRect(int hWnd, RECT lpRect); +int ReleaseDC(int hWnd, int hDC); +int GetDesktopWindow(); + +// ::: #ifndef HAS_PicBmp +// ::: typedef struct +// ::: { +// ::: int Size; +// ::: int Type; +// ::: int hBmp; +// ::: int hPal; +// ::: int Reserved; +// ::: } PicBmp; +// ::: #define HAS_PicBmp +// ::: #endif + +int OleCreatePictureIndirect(PicBmp PictDesc, GUID RefIID, int fPictureOwnsHandle, IPicture IPic); + +#endif + +// '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +// +// CreateBitmapPicture +// - Creates a bitmap type Picture object from a bitmap and +// palette. +// +// hBmp +// - Handle to a bitmap. +// +// hPal +// - Handle to a Palette. +// - Can be null if the bitmap doesn't use a palette. +// +// Returns +// - Returns a Picture object containing the bitmap. +// '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +// +#if Win32 +Picture CreateBitmapPicture(long hBmp, long hPal) +{ + Picture CreateBitmapPicture; + + long r; + +#elif Win16 +Picture CreateBitmapPicture(int hBmp, int hPal) +{ + Picture CreateBitmapPicture; + + int r; + +#endif + PicBmp pic; + + // IPicture requires a reference to "Standard OLE Types." + IPicture IPic; + GUID IID_IDispatch; + + // Fill in with IDispatch Interface ID. + { + IID_IDispatch.Data1 = 0x20400; + IID_IDispatch.Data4[0] = 0xC0; + IID_IDispatch.Data4[7] = 0x46; + } + + // Fill Pic with necessary parts. + { + pic.Size = Len(pic); // Length of structure. + pic.Type = vbPicTypeBitmap; // Type of Picture (bitmap). + pic.hBmp = hBmp; // Handle to bitmap. + pic.hPal = hPal; // Handle to palette (may be null). + } + + // Create Picture object. + r = OleCreatePictureIndirect(pic, IID_IDispatch, 1, IPic); + + // Return the new Picture object. + CreateBitmapPicture = IPic; + + return CreateBitmapPicture; +} + +// '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +// +// CaptureWindow +// - Captures any portion of a window. +// +// hWndSrc +// - Handle to the window to be captured. +// +// Client +// - If True CaptureWindow captures from the client area of the +// window. +// - If False CaptureWindow captures from the entire window. +// +// LeftSrc, TopSrc, WidthSrc, HeightSrc +// - Specify the portion of the window to capture. +// - Dimensions need to be specified in pixels. +// +// Returns +// - Returns a Picture object containing a bitmap of the specified +// portion of the window that was captured. +// '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +// ''''' +// +#if Win32 +Picture CaptureWindow(long hWndSrc, boolean Client, long LeftSrc, long TopSrc, long WidthSrc, long HeightSrc) +{ + Picture CaptureWindow; + + long hDCMemory; + long hBmp; + long hBmpPrev; + long r; + long hDCSrc; + long hPal; + long hPalPrev; + long RasterCapsScrn; + long HasPaletteScrn; + long PaletteSizeScrn; + +#elif Win16 +Picture CaptureWindow(int hWndSrc, boolean Client, int LeftSrc, int TopSrc, long WidthSrc, long HeightSrc) +{ + Picture CaptureWindow; + + int hDCMemory; + int hBmp; + int hBmpPrev; + int r; + int hDCSrc; + int hPal; + int hPalPrev; + int RasterCapsScrn; + int HasPaletteScrn; + int PaletteSizeScrn; + +#endif + LOGPALETTE LogPal; + + // Depending on the value of Client get the proper device context. + if (Client) + { + hDCSrc = GetDC(hWndSrc); // Get device context for client area. + } + else + { + hDCSrc = GetWindowDC(hWndSrc); // Get device context for entire + // window. + } + + // Create a memory device context for the copy process. + hDCMemory = CreateCompatibleDC(hDCSrc); + // Create a bitmap and place it in the memory DC. + hBmp = CreateCompatibleBitmap(hDCSrc, WidthSrc, HeightSrc); + hBmpPrev = SelectObject(hDCMemory, hBmp); + + // Get screen properties. + RasterCapsScrn = GetDeviceCaps(hDCSrc, RASTERCAPS); // Raster + // capabilities. + HasPaletteScrn = RasterCapsScrn & RC_PALETTE; // Palette + // support. + PaletteSizeScrn = GetDeviceCaps(hDCSrc, SIZEPALETTE); // Size of + // palette. + + // If the screen has a palette make a copy and realize it. + if (HasPaletteScrn && (PaletteSizeScrn == 256)) + { + // Create a copy of the system palette. + LogPal.palVersion = 0x300; + LogPal.palNumEntries = 256; + r = GetSystemPaletteEntries(hDCSrc, 0, 256, LogPal.palPalEntry[0]); + hPal = CreatePalette(LogPal); + // Select the new palette into the memory DC and realize it. + hPalPrev = SelectPalette(hDCMemory, hPal, 0); + r = RealizePalette(hDCMemory); + } + + // Copy the on-screen image into the memory DC. + r = BitBlt(hDCMemory, 0, 0, WidthSrc, HeightSrc, hDCSrc, LeftSrc, TopSrc, vbSrcCopy); + + // Remove the new copy of the on-screen image. + hBmp = SelectObject(hDCMemory, hBmpPrev); + + // If the screen has a palette get back the palette that was + // selected in previously. + if (HasPaletteScrn && (PaletteSizeScrn == 256)) + { + hPal = SelectPalette(hDCMemory, hPalPrev, 0); + } + + // Release the device context resources back to the system. + r = DeleteDC(hDCMemory); + r = ReleaseDC(hWndSrc, hDCSrc); + + // Call CreateBitmapPicture to create a picture object from the + // bitmap and palette handles. Then return the resulting picture + // object. + + CaptureWindow = CreateBitmapPicture(hBmp, hPal); + + return CaptureWindow; +} + +// '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +// +// CaptureScreen +// - Captures the entire screen. +// +// Returns +// - Returns a Picture object containing a bitmap of the screen. +// '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +// +Picture CaptureScreen() +{ + Picture CaptureScreen; + +#if Win32 + long hWndScreen; + +#elif Win16 + int hWndScreen; + +#endif + + // Get a handle to the desktop window. + hWndScreen = GetDesktopWindow(); + + // Call CaptureWindow to capture the entire desktop give the handle + // and return the resulting Picture object. + + CaptureScreen = CaptureWindow(hWndScreen, False, 0, 0, Screen.Width / Screen.TwipsPerPixelX, Screen.Height / Screen.TwipsPerPixelY); + + return CaptureScreen; +} + +// '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +// +// CaptureForm +// - Captures an entire form including title bar and border. +// +// frmSrc +// - The Form object to capture. +// +// Returns +// - Returns a Picture object containing a bitmap of the entire +// form. +// '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +// +Picture CaptureForm(Form frmSrc) +{ + Picture CaptureForm; + + // Call CaptureWindow to capture the entire form given its window + // handle and then return the resulting Picture object. + CaptureForm = CaptureWindow(frmSrc.hWnd, False, 0, 0, frmSrc.ScaleX(frmSrc.Width, vbTwips, vbPixels), frmSrc.ScaleY(frmSrc.Height, vbTwips, vbPixels)); + + return CaptureForm; +} + +// '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +// +// CaptureClient +// - Captures the client area of a form. +// +// frmSrc +// - The Form object to capture. +// +// Returns +// - Returns a Picture object containing a bitmap of the form's +// client area. +// '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +// +Picture CaptureClient(Form frmSrc) +{ + Picture CaptureClient; + + // Call CaptureWindow to capture the client area of the form given + // its window handle and return the resulting Picture object. + CaptureClient = CaptureWindow(frmSrc.hWnd, True, 0, 0, frmSrc.ScaleX(frmSrc.ScaleWidth, frmSrc.ScaleMode, vbPixels), frmSrc.ScaleY(frmSrc.ScaleHeight, frmSrc.ScaleMode, vbPixels)); + + return CaptureClient; +} + +// '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +// +// CaptureActiveWindow +// - Captures the currently active window on the screen. +// +// Returns +// - Returns a Picture object containing a bitmap of the active +// window. +// '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +// +Picture CaptureActiveWindow() +{ + Picture CaptureActiveWindow; + +#if Win32 + long hWndActive; + long r; + +#elif Win16 + int hWndActive; + int r; + +#endif + RECT RectActive; + + // Get a handle to the active/foreground window. + hWndActive = GetForegroundWindow(); + + // Get the dimensions of the window. + r = GetWindowRect(hWndActive, RectActive); + + // Call CaptureWindow to capture the active window given its + // handle and return the Resulting Picture object. + CaptureActiveWindow = CaptureWindow(hWndActive, False, 0, 0, RectActive.right - RectActive.left, RectActive.bottom - RectActive.top); + + return CaptureActiveWindow; +} + +// '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +// +// PrintPictureToFitPage +// - Prints a Picture object as big as possible. +// +// Prn +// - Destination Printer object. +// +// Pic +// - Source Picture object. +// '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +// +void PrintPictureToFitPage(Printer Prn, Picture pic) +{ + #define vbHiMetric (8) + double PicRatio; + double PrnWidth; + double PrnHeight; + double PrnRatio; + double PrnPicWidth; + double PrnPicHeight; + + // Determine if picture should be printed in landscape or portrait + // and set the orientation. + if (pic.Height >= pic.Width) + { + Prn.Orientation = vbPRORPortrait; // Taller than wide. + } + else + { + Prn.Orientation = vbPRORLandscape; // Wider than tall. + } + + // Calculate device independent Width-to-Height ratio for picture. + PicRatio = pic.Width / pic.Height; + + // Calculate the dimentions of the printable area in HiMetric. + PrnWidth = Prn.ScaleX(Prn.ScaleWidth, Prn.ScaleMode, vbHiMetric); + PrnHeight = Prn.ScaleY(Prn.ScaleHeight, Prn.ScaleMode, vbHiMetric); + // Calculate device independent Width to Height ratio for printer. + PrnRatio = PrnWidth / PrnHeight; + + // Scale the output to the printable area. + if (PicRatio >= PrnRatio) + { + // Scale picture to fit full width of printable area. + PrnPicWidth = Prn.ScaleX(PrnWidth, vbHiMetric, Prn.ScaleMode); + PrnPicHeight = Prn.ScaleY(PrnWidth / PicRatio, vbHiMetric, Prn.ScaleMode); + } + else + { + // Scale picture to fit full height of printable area. + PrnPicHeight = Prn.ScaleY(PrnHeight, vbHiMetric, Prn.ScaleMode); + PrnPicWidth = Prn.ScaleX(PrnHeight * PicRatio, vbHiMetric, Prn.ScaleMode); + } + + // Print the picture using the PaintPicture method. + Prn_PaintPicture(pic, 0, 0, PrnPicWidth, PrnPicHeight); +} + +// -------------------------------------------------------------------- + diff --git a/src/game_sp/Capture.h b/src/game_sp/Capture.h new file mode 100644 index 00000000..f2b8e1b5 --- /dev/null +++ b/src/game_sp/Capture.h @@ -0,0 +1,147 @@ +// ---------------------------------------------------------------------------- +// Capture.h +// ---------------------------------------------------------------------------- + +#ifndef CAPTURE_H +#define CAPTURE_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +#ifndef HAS_PALETTEENTRY +typedef struct +{ + byte peRed; + byte peGreen; + byte peBlue; + byte peFlags; +} PALETTEENTRY; +#define HAS_PALETTEENTRY +#endif + +#ifndef HAS_LOGPALETTE +typedef struct +{ + int palVersion; + int palNumEntries; + PALETTEENTRY palPalEntry[255]; // Enough for 256 colors. +} LOGPALETTE; +#define HAS_LOGPALETTE +#endif + +#ifndef HAS_GUID +typedef struct +{ + long Data1; + int Data2; + int Data3; + byte Data4[7]; +} GUID; +#define HAS_GUID +#endif + +#if Win32 + +#ifndef HAS_RECT +typedef struct +{ + long left; + long top; + long right; + long bottom; +} RECT; +#define HAS_RECT +#endif + +#ifndef HAS_PicBmp +typedef struct +{ + long Size; + long Type; + long hBmp; + long hPal; + long Reserved; +} PicBmp; +#define HAS_PicBmp +#endif + +#elif Win16 + +#ifndef HAS_RECT +typedef struct +{ + int left; + int top; + int right; + int bottom; +} RECT; +#define HAS_RECT +#endif + +#ifndef HAS_PicBmp +typedef struct +{ + int Size; + int Type; + int hBmp; + int hPal; + int Reserved; +} PicBmp; +#define HAS_PicBmp +#endif + +#endif + +#if Win32 + + + +#elif Win16 + + + +#endif + +#if Win32 + + + +#elif Win16 + + + +#endif + +#if Win32 + + + +#elif Win16 + + + +#endif + +#if Win32 + + + +#elif Win16 + + + +#endif + +extern Picture CaptureActiveWindow(); +extern Picture CaptureClient(Form frmSrc); +extern Picture CaptureForm(Form frmSrc); +extern Picture CaptureScreen(); +extern Picture CaptureWindow(int hWndSrc, boolean Client, int LeftSrc, int TopSrc, long WidthSrc, long HeightSrc); +extern Picture CreateBitmapPicture(int hBmp, int hPal); +extern void PrintPictureToFitPage(Printer Prn, Picture pic); + +#endif /* CAPTURE_H */ diff --git a/src/game_sp/DDScrollBuffer.c b/src/game_sp/DDScrollBuffer.c new file mode 100644 index 00000000..1734aa8b --- /dev/null +++ b/src/game_sp/DDScrollBuffer.c @@ -0,0 +1,382 @@ +// ---------------------------------------------------------------------------- +// DDScrollBuffer.c +// ---------------------------------------------------------------------------- + +#include "DDScrollBuffer.h" + +#include + + +// --- VERSION 1.0 CLASS +// --- BEGIN +// --- MultiUse = -1 'True // True +// --- Persistable = 0 'NotPersistable // NotPersistable +// --- DataBindingBehavior = 0 'vbNone // vbNone +// --- DataSourceBehavior = 0 'vbNone // vbNone +// --- MTSTransactionMode = 0 'NotAnMTSObject // NotAnMTSObject +// --- END + +static char *VB_Name = "DDScrollBuffer"; +static boolean VB_GlobalNameSpace = False; +static boolean VB_Creatable = True; +static boolean VB_PredeclaredId = False; +static boolean VB_Exposed = False; +// --- Option Explicit + +// needs reference to: DirectX7 for Visual Basic Type Library + +DirectDrawSurface7 Buffer; +DirectDrawSurface7 mPrimary; +long mWidth, mHeight; +long mhWnd; +long mScrollX, mScrollY; +long mDestXOff, mDestYOff; + +void DDScrollBuffer_Let_DestXOff(long NewVal) +{ + mDestXOff = NewVal; +} + +long DDScrollBuffer_Get_DestXOff() +{ + long DestXOff; + + DestXOff = mDestXOff; + + return DestXOff; +} + +void DDScrollBuffer_Let_DestYOff(long NewVal) +{ + mDestYOff = NewVal; +} + +long DDScrollBuffer_Get_DestYOff() +{ + long DestYOff; + + DestYOff = mDestYOff; + + return DestYOff; +} + +DirectDrawSurface7 DDScrollBuffer_Get_Surface() +{ + DirectDrawSurface7 Surface; + + Surface = Buffer; + + return Surface; +} + +long DDScrollBuffer_Get_Width() +{ + long Width; + + Width = mWidth; + + return Width; +} + +int DDScrollBuffer_Get_Height() +{ + int Height; + + Height = mHeight; + + return Height; +} + +long DDScrollBuffer_CreateAtSize(long Width, long Height, long hWndViewPort) +{ + long CreateAtSize; + + DDSURFACEDESC2 SD; + + CreateAtSize = 0; + mhWnd = hWndViewPort; + // Create ScrollBuffer: + { + SD.lFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + SD.ddsCaps.lCaps = DDSCAPS_VIDEOMEMORY; + // SD.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN + SD.LWidth = Width; + SD.LHeight = Height; + } + + // --- On Error Resume Next + Buffer = DDraw.CreateSurface(SD); + if (Err.Number != 0) + return CreateAtSize; + + // --- On Error GoTo 0 + + mWidth = Width; + mHeight = Height; + mScrollX = 0; + mScrollY = 0; + CreateAtSize = -1; + + return CreateAtSize; +} + +void DDScrollBuffer_Cls(int BackColor) +{ + RECT EmptyRect; + + if (NoDisplayFlag) + return; + + Buffer.BltColorFill(EmptyRect, BackColor); +} + +void DDScrollBuffer_Blt() +{ + RECT DR, SR; + long tX, tY, L; + // RECT ERect; + // long Restore; + + if (NoDisplayFlag) + return; + + + // --- On Error GoTo BltEH + DirectX.GetWindowRect(mhWnd, DR); + // --- On Error GoTo 0 + + { + tX = (DR.right - DR.left) / Stretch; + tY = (DR.bottom - DR.top) / Stretch; + } + { + SR.left = mScrollX + mDestXOff; + SR.top = mScrollY + mDestYOff; + SR.right = SR.left + tX; + SR.bottom = SR.top + tY; + // If mWidth < SR.right Then + // SR.right = mWidth + // DR.right = DR.left + Stretch * (SR.right - SR.left) + // End If + // If mHeight < SR.bottom Then + // SR.bottom = mHeight + // DR.bottom = DR.top + Stretch * (SR.bottom - SR.top) + // End If + // If (mScrollX + mDestXOff) < 0 Then + // SR.left = 0 + // DR.left = DR.left - Stretch * (mScrollX + mDestXOff) + // End If + // If (mScrollY + mDestYOff) < 0 Then + // SR.top = 0 + // DR.top = DR.top - Stretch * (mScrollY + mDestYOff) + // End If + } + // DDraw.WaitForVerticalBlank DDWAITVB_BLOCKBEGIN, 0 + if (IS_NOTHING(&Buffer, sizeof(Buffer))) + return; + + if (IS_NOTHING(&PrimarySurface, sizeof(PrimarySurface))) + return; + + L = PrimarySurface_Blt(DR, Buffer, SR, DDBLT_WAIT); + if (L != DD_OK) + { + switch (L) + { + case DDERR_GENERIC: + Debug.Assert(False); + break; + + case DDERR_INVALIDCLIPLIST: + Debug.Assert(False); + break; + + case DDERR_INVALIDOBJECT: + Debug.Assert(False); + break; + + case DDERR_INVALIDPARAMS: + Debug.Assert(False); + break; + + case DDERR_INVALIDRECT: + Debug.Assert(False); + break; + + case DDERR_NOALPHAHW: + Debug.Assert(False); + break; + + case DDERR_NOBLTHW: + Debug.Assert(False); + break; + + case DDERR_NOCLIPLIST: + Debug.Assert(False); + break; + + case DDERR_NODDROPSHW: + Debug.Assert(False); + break; + + case DDERR_NOMIRRORHW: + Debug.Assert(False); + break; + + case DDERR_NORASTEROPHW: + Debug.Assert(False); + break; + + case DDERR_NOROTATIONHW: + Debug.Assert(False); + break; + + case DDERR_NOSTRETCHHW: + Debug.Assert(False); + break; + + case DDERR_NOZBUFFERHW: + Debug.Assert(False); + break; + + case DDERR_SURFACEBUSY: + Debug.Assert(False); + break; + + case DDERR_SURFACELOST: + DDraw.RestoreAllSurfaces(); + if (! PrimarySurface.isLost()) + { + subDisplayLevel(); + // Blt(); + } + + // RestorePrimarySurface + // ClipToWindow 0 + break; + + case DDERR_UNSUPPORTED: + Debug.Assert(False); + break; + + case DDERR_WASSTILLDRAWING: + Debug.Assert(False); + break; + + default: + Debug.Assert(False); + break; + } + } + +#if 0 + // Buffer.UpdateOverlay SR, PrimarySurface, DR, DDOVER_SHOW + if (EditFlag) + FMark.RefreshMarker(); +#endif + + // BltEH: +} + +void DDScrollBuffer_ScrollTo(int X, int Y) +{ + if (NoDisplayFlag) + return; + + X = X / Stretch; + Y = Y / Stretch; + mScrollX = X; + mScrollY = Y; + ScrollX = mScrollX; + ScrollY = mScrollY; +} + +void DDScrollBuffer_ScrollTowards(int X, int Y, double Step) +{ + double dx, dY, r; + + if (NoDisplayFlag) + return; + + X = X / Stretch; + Y = Y / Stretch; + dx = X - mScrollX; + dY = Y - mScrollY; + r = Sqr(dx * dx + dY * dY); + if (r == 0) // we are there already + return; + + if (Step < r) + r = Step / r; + else + r = 1; + + mScrollX = mScrollX + dx * r; + mScrollY = mScrollY + dY * r; + ScrollX = mScrollX; + ScrollY = mScrollY; +} + +void DDScrollBuffer_SoftScrollTo(int X, int Y, long TimeMS, int FPS) +{ + double dx, dY; + TickCountObject Tick; + long dT, StepCount; + double T, tStep; + long oldX, oldY, maxD; + boolean AlreadyRunning; + + if (NoDisplayFlag) + return; + + if (AlreadyRunning) + { + return; + } + + AlreadyRunning = True; + X = X / Stretch; + Y = Y / Stretch; + dx = X - mScrollX; + dY = Y - mScrollY; + maxD = (Abs(dx) < Abs(dY) ? Abs(dY) : Abs(dY)); + StepCount = FPS * (TimeMS / (double)1000); + if (StepCount > maxD) + StepCount = maxD; + + if (StepCount == 0) + StepCount = 1; + + dT = 1000 / FPS; + tStep = (double)1 / StepCount; + oldX = mScrollX; + oldY = mScrollY; + // R = Sqr(dX * dX + dY * dY) + // If R = 0 Then Exit Sub 'we are there already + for (T = (double)tStep; T <= (double)1; T += tStep) + { + if (UserDragFlag) + goto SoftScrollEH; + + // If Claim Then Exit For + Tick.DelayMS(dT, False); + mScrollX = oldX + T * dx; + mScrollY = oldY + T * dY; + ScrollX = mScrollX; + ScrollY = mScrollY; + // Blt(); + } + + if (UserDragFlag) + goto SoftScrollEH; + + Tick.DelayMS(dT, False); + mScrollX = X; + mScrollY = Y; + ScrollX = mScrollX; + ScrollY = mScrollY; + // Blt(); + +SoftScrollEH: + AlreadyRunning = False; +} diff --git a/src/game_sp/DDScrollBuffer.h b/src/game_sp/DDScrollBuffer.h new file mode 100644 index 00000000..cc77cf89 --- /dev/null +++ b/src/game_sp/DDScrollBuffer.h @@ -0,0 +1,29 @@ +// ---------------------------------------------------------------------------- +// DDScrollBuffer.h +// ---------------------------------------------------------------------------- + +#ifndef DDSCROLLBUFFER_H +#define DDSCROLLBUFFER_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern void DDScrollBuffer_Blt(); +extern void DDScrollBuffer_Cls(int BackColor); +extern long DDScrollBuffer_CreateAtSize(long Width, long Height, long hWndViewPort); +extern long DDScrollBuffer_Get_DestXOff(); +extern long DDScrollBuffer_Get_DestYOff(); +extern int DDScrollBuffer_Get_Height(); +extern DirectDrawSurface7 DDScrollBuffer_Get_Surface(); +extern long DDScrollBuffer_Get_Width(); +extern void DDScrollBuffer_Let_DestXOff(long NewVal); +extern void DDScrollBuffer_Let_DestYOff(long NewVal); +extern void DDScrollBuffer_ScrollTo(int X, int Y); +extern void DDScrollBuffer_ScrollTowards(int X, int Y, double Step); +extern void DDScrollBuffer_SoftScrollTo(int X, int Y, long TimeMS, int FPS); + +#endif /* DDSCROLLBUFFER_H */ diff --git a/src/game_sp/DDSpriteBuffer.c b/src/game_sp/DDSpriteBuffer.c new file mode 100644 index 00000000..1384a38f --- /dev/null +++ b/src/game_sp/DDSpriteBuffer.c @@ -0,0 +1,232 @@ +// ---------------------------------------------------------------------------- +// DDSpriteBuffer.c +// ---------------------------------------------------------------------------- + +#include "DDSpriteBuffer.h" + +static void Blt(int pX, int pY, int SpriteX, int SpriteY); + +// --- VERSION 1.0 CLASS +// --- BEGIN +// --- MultiUse = -1 'True // True +// --- Persistable = 0 'NotPersistable // NotPersistable +// --- DataBindingBehavior = 0 'vbNone // vbNone +// --- DataSourceBehavior = 0 'vbNone // vbNone +// --- MTSTransactionMode = 0 'NotAnMTSObject // NotAnMTSObject +// --- END + +static char *VB_Name = "DDSpriteBuffer"; +static boolean VB_GlobalNameSpace = False; +static boolean VB_Creatable = True; +static boolean VB_PredeclaredId = False; +static boolean VB_Exposed = False; +// --- Option Explicit + +// needs reference to: DirectX7 for Visual Basic Type Library + +DirectDrawSurface7 Buffer; +DirectDrawSurface7 mDest; +long mXSpriteCount, mYSpriteCount; +long mSpriteWidth, mSpriteHeight; +long mDestXOff, mDestYOff; + +void DDSpriteBuffer_Let_DestXOff(long NewVal) +{ + mDestXOff = NewVal; +} + +long DDSpriteBuffer_Get_DestXOff() +{ + long DestXOff; + + DestXOff = mDestXOff; + + return DestXOff; +} + +void DDSpriteBuffer_Let_DestYOff(long NewVal) +{ + mDestYOff = NewVal; +} + +long DDSpriteBuffer_Get_DestYOff() +{ + long DestYOff; + + DestYOff = mDestYOff; + + return DestYOff; +} + +int DDSpriteBuffer_Set_DestinationSurface(DirectDrawSurface7 DSurface) +{ + int DestinationSurface; + + mDest = DSurface; + + return DestinationSurface; +} + +DirectDrawSurface7 DDSpriteBuffer_Get_Surface() +{ + DirectDrawSurface7 Surface; + + Surface = Buffer; + + return Surface; +} + +long DDSpriteBuffer_Get_Width() +{ + long Width; + + Width = mSpriteWidth * mXSpriteCount; + + return Width; +} + +int DDSpriteBuffer_Get_Height() +{ + int Height; + + Height = mSpriteHeight * mYSpriteCount; + + return Height; +} + +boolean DDSpriteBuffer_CreateFromFile(char *Path, long xSprites, long ySprites) +{ + boolean CreateFromFile; + + DDSURFACEDESC2 SD; + + { + SD.lFlags = DDSD_CAPS; // Or DDSD_WIDTH Or DDSD_HEIGHT + SD.ddsCaps.lCaps = DDSCAPS_VIDEOMEMORY; // DDSCAPS_SYSTEMMEMORY 'DDSCAPS_OFFSCREENPLAIN + } + + // --- On Error GoTo CreateFromFileEH + Buffer = DDraw.CreateSurfaceFromFile(Path, SD); + // --- On Error GoTo 0 + + Buffer.GetSurfaceDesc(SD); + mSpriteWidth = SD.LWidth / xSprites; + mSpriteHeight = SD.LHeight / ySprites; + mXSpriteCount = xSprites; + mYSpriteCount = ySprites; + CreateFromFile = True; + return CreateFromFile; + +CreateFromFileEH: + CreateFromFile = False; + + return CreateFromFile; +} + +boolean DDSpriteBuffer_CreateAtSize(long Width, long Height, long xSprites, long ySprites) +{ + boolean CreateAtSize; + + DDSURFACEDESC2 SD; + + { + SD.lFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + SD.ddsCaps.lCaps = DDSCAPS_VIDEOMEMORY; + // SD.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN + SD.LWidth = Width; + SD.LHeight = Height; + } + + // --- On Error GoTo CreateAtSizeEH + Buffer = DDraw.CreateSurface(SD); + // --- On Error GoTo 0 + + mSpriteWidth = Width / xSprites; + mSpriteHeight = Height / ySprites; + mXSpriteCount = xSprites; + mYSpriteCount = ySprites; + CreateAtSize = True; + return CreateAtSize; + +CreateAtSizeEH: + CreateAtSize = False; + + return CreateAtSize; +} + +void DDSpriteBuffer_Cls(int BackColor) +{ + RECT EmptyRect; + + Buffer.BltColorFill(EmptyRect, BackColor); +} + +static void Blt(int pX, int pY, int SpriteX, int SpriteY) +{ + RECT DR, SR; + long Tmp; + + if (NoDisplayFlag) + return; + + { + DR.left = pX + mDestXOff; + DR.top = pY + mDestYOff; + DR.right = pX + mSpriteWidth + mDestXOff; + DR.bottom = pY + mSpriteHeight + mDestYOff; + } + { + SR.left = mSpriteWidth * (SpriteX - 1); + SR.top = mSpriteHeight * (SpriteY - 1); + SR.right = SR.left + mSpriteWidth; + SR.bottom = SR.top + mSpriteHeight; + } + Tmp = mDest_Blt(DR, Buffer, SR, DDBLT_WAIT); +} + +void DDSpriteBuffer_BltEx(int pX, int pY, int SpritePos) +{ + int XPos, YPos; + + if (NoDisplayFlag) + return; + + XPos = (SpritePos % mXSpriteCount) + 1; + YPos = (SpritePos / mXSpriteCount) + 1; + Blt(pX, pY, XPos, YPos); +} + +// Public Function GetStretchCopy(Stretch!) As DDSpriteBuffer +// Dim SR As RECT, DR As RECT, Y%, X%, pX%, pY%, Tmp& +// // Set GetStretchCopy = New DDSpriteBuffer // (handle this later, if needed) +// If Not GetStretchCopy.CreateAtSize(Stretch * Width, Stretch * Height, mXSpriteCount, mYSpriteCount) Then +// Set GetStretchCopy = Nothing +// Else +// For Y = 0 To mYSpriteCount - 1 +// pY = Y * Stretch * mSpriteHeight +// For X = 0 To mXSpriteCount - 1 +// pX = X * Stretch * mSpriteWidth +// With DR +// .left = pX +// .top = pY +// .right = pX + mSpriteWidth * Stretch +// .bottom = pY + mSpriteHeight * Stretch +// End With +// With SR +// .left = mSpriteWidth * X +// .top = mSpriteHeight * Y +// .right = .left + mSpriteWidth +// .bottom = .top + mSpriteHeight +// End With +// Tmp = GetStretchCopy.Surface.Blt(DR, Buffer, SR, DDBLT_WAIT) +// Next X +// Next Y +// 'GetStretchCopy.Surface.Blt DR, Buffer, DR, DDBLT_WAIT +// End If +// End Function + +static void Class_Initialize() +{ + mDestXOff = 0; + mDestYOff = 0; +} diff --git a/src/game_sp/DDSpriteBuffer.h b/src/game_sp/DDSpriteBuffer.h new file mode 100644 index 00000000..64a8daa0 --- /dev/null +++ b/src/game_sp/DDSpriteBuffer.h @@ -0,0 +1,28 @@ +// ---------------------------------------------------------------------------- +// DDSpriteBuffer.h +// ---------------------------------------------------------------------------- + +#ifndef DDSPRITEBUFFER_H +#define DDSPRITEBUFFER_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern void DDSpriteBuffer_BltEx(int pX, int pY, int SpritePos); +extern void DDSpriteBuffer_Cls(int BackColor); +extern boolean DDSpriteBuffer_CreateAtSize(long Width, long Height, long xSprites, long ySprites); +extern boolean DDSpriteBuffer_CreateFromFile(char *Path, long xSprites, long ySprites); +extern long DDSpriteBuffer_Get_DestXOff(); +extern long DDSpriteBuffer_Get_DestYOff(); +extern int DDSpriteBuffer_Get_Height(); +extern DirectDrawSurface7 DDSpriteBuffer_Get_Surface(); +extern long DDSpriteBuffer_Get_Width(); +extern void DDSpriteBuffer_Let_DestXOff(long NewVal); +extern void DDSpriteBuffer_Let_DestYOff(long NewVal); +extern int DDSpriteBuffer_Set_DestinationSurface(DirectDrawSurface7 DSurface); + +#endif /* DDSPRITEBUFFER_H */ diff --git a/src/game_sp/Demo.c b/src/game_sp/Demo.c new file mode 100644 index 00000000..7bbf90f0 --- /dev/null +++ b/src/game_sp/Demo.c @@ -0,0 +1,83 @@ +// ---------------------------------------------------------------------------- +// Demo.c +// ---------------------------------------------------------------------------- + +#include "Demo.h" + +static char *VB_Name = "modDemo"; +// --- Option Explicit +// +// Public Function subCloseDemoRecordingFile() +// +// End Function +int RecDemoRandomSeed; +byte FirstDemoByte; +char *MySignature; + +void subGetNextDemoKey() +{ + int ax; + + if (0 < DemoKeyRepeatCounter) + { + DemoKeyRepeatCounter = DemoKeyRepeatCounter - 1; + } + else + { + DemoOffset = DemoOffset + 1; + if (DemoOffset <= FileMax) + { + ax = PlayField8[DemoOffset]; + if (ax == 0xFF) + { + demo_stopped = 1; + ExitToMenuFlag = 1; + } + else + { + DemoKeyCode = ax & 0xF; + DemoKeyRepeatCounter = (ax & 0xF0) / 0x10; + } + + } + else + { + ExitToMenuFlag = 1; + } + } +} + +currency GetTotalFramesOfDemo() +{ + currency GetTotalFramesOfDemo; + + long i; + currency nFrames; + byte db; + + GetTotalFramesOfDemo = 0; + if (! DemoAvailable) + return GetTotalFramesOfDemo; + + nFrames = 1; + i = DemoPointer + 1; + + // --- On Error GoTo GetTotalFramesOfDemoEH + db = PlayField8[i]; + while (db != 0xFF) + { + nFrames = nFrames + (db & 0xF0) / 0x10 + 1; + i = i + 1; + db = PlayField8[i]; + } + + GetTotalFramesOfDemo = nFrames; + return GetTotalFramesOfDemo; + +GetTotalFramesOfDemoEH: + // ReportError "GetTotalFramesOfDemo()", "invalid data detected in file " & OrigPath + GetTotalFramesOfDemo = 0; + DemoAvailable = False; + + return GetTotalFramesOfDemo; +} diff --git a/src/game_sp/Demo.h b/src/game_sp/Demo.h new file mode 100644 index 00000000..a9daa14f --- /dev/null +++ b/src/game_sp/Demo.h @@ -0,0 +1,22 @@ +// ---------------------------------------------------------------------------- +// Demo.h +// ---------------------------------------------------------------------------- + +#ifndef DEMO_H +#define DEMO_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern currency GetTotalFramesOfDemo(); +extern void subGetNextDemoKey(); + +extern byte FirstDemoByte; +extern char *MySignature; +extern int RecDemoRandomSeed; + +#endif /* DEMO_H */ diff --git a/src/game_sp/DemoBufferObject.c b/src/game_sp/DemoBufferObject.c new file mode 100644 index 00000000..37e758e8 --- /dev/null +++ b/src/game_sp/DemoBufferObject.c @@ -0,0 +1,240 @@ +// ---------------------------------------------------------------------------- +// DemoBufferObject.c +// ---------------------------------------------------------------------------- + +#include "DemoBufferObject.h" + +static void Class_Terminate(); +static int RemoveLastDemoKey(); + +// --- VERSION 1.0 CLASS +// --- BEGIN +// --- MultiUse = -1 'True // True +// --- Persistable = 0 'NotPersistable // NotPersistable +// --- DataBindingBehavior = 0 'vbNone // vbNone +// --- DataSourceBehavior = 0 'vbNone // vbNone +// --- MTSTransactionMode = 0 'NotAnMTSObject // NotAnMTSObject +// --- END + +static char *VB_Name = "DemoBufferObject"; +static boolean VB_GlobalNameSpace = False; +static boolean VB_Creatable = True; +static boolean VB_PredeclaredId = False; +static boolean VB_Exposed = False; +// --- Option Explicit + +#define MaxPos ((long)1024) + +// Private Const MaxPos& = 20& 'debug only +byte DemoByte[MaxPos + 1]; +DemoBufferObject SubBuffer; + +byte nFirstByte; + +char *mSignature; +boolean bSignatureAvailable; + +long WritePos; +int LastKey; +int CheckSum; +long nSize; + +static void Class_Initialize() +{ + int lSize; + + Trace("DemoBufferObject", "Construction"); + DemoBufferObject_Reset(); + if (! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer))) + { + lSize = DemoBuffer_Size(); + Trace("DemoBufferObject", "Size == ..."); + Trace("DemoBufferObject", "BufferCount == ..."); + Trace("DemoBufferObject", "TimerVar == ..."); + } +} + +static void Class_Terminate() +{ + SET_TO_NOTHING(&SubBuffer, sizeof(SubBuffer)); +} + +void DemoBufferObject_Reset() +{ + nSize = 0; + nFirstByte = 0x81; + WritePos = 0; + LastKey = -1; + CheckSum = 0; + bSignatureAvailable = False; + mSignature = ""; + SET_TO_NOTHING(&SubBuffer, sizeof(SubBuffer)); +} + +long DemoBufferObject_Get_Size() +{ + long Size; + + Size = (nSize < 1 ? 0 : 0); + if (! IS_NOTHING(&SubBuffer, sizeof(SubBuffer))) + Size = Size + SubBuffer_Size(); + + return Size; +} + +byte DemoBufferObject_Get_CheckSumByte() +{ + byte CheckSumByte; + + CheckSumByte = CheckSum & 0xFF; + + return CheckSumByte; +} + +byte DemoBufferObject_Get_FirstByte() +{ + byte FirstByte; + + FirstByte = nFirstByte; + + return FirstByte; +} + +void DemoBufferObject_Let_FirstByte(byte NewVal) +{ + nFirstByte = NewVal; +} + +// +// Public Property Get DemoAvailable() As Boolean +// DemoAvailable = (0 < nSize) +// End Property +// +// Public Property Get Signature() As String +// If SubBuffer Is Nothing Then +// Signature = mSignature +// Else +// Signature = SubBuffer.Signature +// End If +// End Property + +// Public Property Let Signature(NewSig$) +// If SubBuffer Is Nothing Then +// Signature = NewSig +// Else +// SubBuffer.Signature = NewSig +// End If +// End Property +// +// Public Property Get SignatureAvailable() As Boolean +// If SubBuffer Is Nothing Then +// SignatureAvailable = (mSignature <> "") +// Else +// SignatureAvailable = SubBuffer +// End If +// End Property + +boolean DemoBufferObject_Serialize(int FNum) +{ + boolean Serialize; + + int i; // , LKey% + + Serialize = True; + if (! IS_NOTHING(&SubBuffer, sizeof(SubBuffer))) + Serialize = SubBuffer_Serialize(FNum); + + if (nSize == 0) + return Serialize; + + // LKey = RemoveLastDemoKey() + if (! nSize < MaxPos) // this buffer is full + { + + // --- On Error GoTo SerializeEH + FILE_PUT(FNum, -1, &DemoByte, sizeof(DemoByte)); + // --- On Error GoTo 0 + + } + else // this is the last buffer in the recursive chain + { + + // --- On Error GoTo SerializeEH + for (i = 1; i <= WritePos; i++) + { + FILE_PUT(FNum, -1, &DemoByte[i], sizeof(DemoByte[i])); + } + + // --- On Error GoTo 0 + + } + + // AddDemoKey LKey + return Serialize; + +SerializeEH: + Serialize = False; + + return Serialize; +} + +void DemoBufferObject_AddDemoKey(int KeyCode) +{ + CheckSum = (CheckSum + 1) & 0xFF; // increment checksum + // If Not SubBuffer Is Nothing Then 'delegate + // Debug.Assert False + // 'SubBuffer.AddDemoKey KeyCode + // Exit Sub + // End If + if (LastKey == KeyCode) + { + DemoByte[WritePos] = DemoByte[WritePos] + 0x10; + if (0xEF < DemoByte[WritePos]) + LastKey = -1; + + } + else // LastKey <> KeyCode + { + WritePos = WritePos + 1; + + if (MaxPos < WritePos) // if overflow then create new buffer, hang myself in list + { + DemoBufferObject Tmp; + + // Tmp = New DemoBufferObject; // (handle this later, if needed) + Tmp.SetSubBuffer(&VB_OBJECT_SELF); + Tmp.AddDemoKey(KeyCode); // and delegate + DemoBuffer = Tmp; + } + else + { + nSize = nSize + 1; // increment size + DemoByte[WritePos] = KeyCode; + LastKey = KeyCode; + } + } +} + +void DemoBufferObject_SetSubBuffer(DemoBufferObject SBuf) +{ + SubBuffer = SBuf; +} + +static int RemoveLastDemoKey() +{ + static int RemoveLastDemoKey; + + RemoveLastDemoKey = (DemoByte[WritePos] & 0xF); + if (DemoByte[WritePos] < 0x10) + { + WritePos = WritePos - 1; + nSize = nSize - 1; + LastKey = -1; + } + else + { + DemoByte[WritePos] = DemoByte[WritePos] - 0x10; + } + + return RemoveLastDemoKey; +} diff --git a/src/game_sp/DemoBufferObject.h b/src/game_sp/DemoBufferObject.h new file mode 100644 index 00000000..464db73e --- /dev/null +++ b/src/game_sp/DemoBufferObject.h @@ -0,0 +1,24 @@ +// ---------------------------------------------------------------------------- +// DemoBufferObject.h +// ---------------------------------------------------------------------------- + +#ifndef DEMOBUFFEROBJECT_H +#define DEMOBUFFEROBJECT_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern void DemoBufferObject_AddDemoKey(int KeyCode); +extern byte DemoBufferObject_Get_CheckSumByte(); +extern byte DemoBufferObject_Get_FirstByte(); +extern long DemoBufferObject_Get_Size(); +extern void DemoBufferObject_Let_FirstByte(byte NewVal); +extern void DemoBufferObject_Reset(); +extern boolean DemoBufferObject_Serialize(int FNum); +extern void DemoBufferObject_SetSubBuffer(DemoBufferObject SBuf); + +#endif /* DEMOBUFFEROBJECT_H */ diff --git a/src/game_sp/DirectDrawGlobals.c b/src/game_sp/DirectDrawGlobals.c new file mode 100644 index 00000000..4b96d9e3 --- /dev/null +++ b/src/game_sp/DirectDrawGlobals.c @@ -0,0 +1,47 @@ +// ---------------------------------------------------------------------------- +// DirectDrawGlobals.c +// ---------------------------------------------------------------------------- + +#include "DirectDrawGlobals.h" + +static char *VB_Name = "DirectDrawGlobals"; +// --- Option Explicit + +DirectX7 DirectX; +DirectDraw7 DirectDraw; +DirectDrawSurface7 PrimarySurface; + +void InitDirectDraw(long hWndClip) +{ + DDSURFACEDESC2 SD; + + // DirectX = New DirectX7; // (handle this later, if needed) + DirectDraw = DirectX.DirectDrawCreate(""); + DirectDraw.SetCooperativeLevel(0, DDSCL_NORMAL); + // Create PrimarySurface: + { + SD.lFlags = DDSD_CAPS; + SD.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE; + } + PrimarySurface = DirectDraw.CreateSurface(SD); + if (hWndClip != 0) + ClipToWindow(hWndClip); +} + +void ReleaseDirectDraw() +{ + SET_TO_NOTHING(&PrimarySurface, sizeof(PrimarySurface)); + SET_TO_NOTHING(&DirectDraw, sizeof(DirectDraw)); + SET_TO_NOTHING(&DirectX, sizeof(DirectX)); +} + +void ClipToWindow(long hWnd) +{ + DirectDrawClipper Clipper; + + // create clipper + Clipper = DirectDraw.CreateClipper(0); + Clipper.SetHWnd(hWnd); + PrimarySurface.SetClipper(Clipper); + SET_TO_NOTHING(&Clipper, sizeof(Clipper)); +} diff --git a/src/game_sp/DirectDrawGlobals.h b/src/game_sp/DirectDrawGlobals.h new file mode 100644 index 00000000..71cc763f --- /dev/null +++ b/src/game_sp/DirectDrawGlobals.h @@ -0,0 +1,23 @@ +// ---------------------------------------------------------------------------- +// DirectDrawGlobals.h +// ---------------------------------------------------------------------------- + +#ifndef DIRECTDRAWGLOBALS_H +#define DIRECTDRAWGLOBALS_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern void ClipToWindow(long hWnd); +extern void InitDirectDraw(long hWndClip); +extern void ReleaseDirectDraw(); + +extern DirectDraw7 DirectDraw; +extern DirectDrawSurface7 PrimarySurface; +extern DirectX7 DirectX; + +#endif /* DIRECTDRAWGLOBALS_H */ diff --git a/src/game_sp/DirectXGlobals.c b/src/game_sp/DirectXGlobals.c new file mode 100644 index 00000000..3e2b0f79 --- /dev/null +++ b/src/game_sp/DirectXGlobals.c @@ -0,0 +1,94 @@ +// ---------------------------------------------------------------------------- +// DirectXGlobals.c +// ---------------------------------------------------------------------------- + +#include "DirectXGlobals.h" + +static char *VB_Name = "DirectXGlobals"; +// --- Option Explicit + +DirectX7 DirectX; +DirectX7 DirectXS; +DirectDraw7 DDraw; +DirectSound DSound; + +// Public DInput As DirectInput +// Public DKeyboard As DirectInputDevice +DirectDrawSurface7 PrimarySurface; + +void InitDirectX(long hWndForm, long hWndClip) +{ + // DirectX = New DirectX7; // (handle this later, if needed) + // DirectXS = New DirectX7; // (handle this later, if needed) + + // DirectSound: + + // --- On Error Resume Next + DSound = DirectXS.DirectSoundCreate(""); + if (Err.Number != 0) + { + ReportError("InitDirectX()", "Unable to start DirectSound."); + } + else + { + DSound.SetCooperativeLevel(hWndForm, DSSCL_PRIORITY); + LoadSoundFX(); + } + + // DirectDraw: + DDraw = DirectX.DirectDrawCreate(""); + DDraw.SetCooperativeLevel(0, DDSCL_NORMAL); + RestorePrimarySurface(); + if (hWndClip != 0) + ClipToWindow(hWndClip); + + // 'DirectInput: + // Set DInput = DirectX.DirectInputCreate() + // Set DKeyboard = DInput.CreateDevice("GUID_SysKeyboard") + // Call DKeyboard.SetCommonDataFormat(DIFORMAT_KEYBOARD) + // Call DKeyboard.SetCooperativeLevel(hWndForm, DISCL_NONEXCLUSIVE Or DISCL_BACKGROUND) + // Call DKeyboard.Acquire +} + +void RestorePrimarySurface() +{ + DDSURFACEDESC2 SD; + + // Create PrimarySurface: + { + SD.lFlags = DDSD_CAPS; + SD.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE; + } + + // --- On Error Resume Next + SET_TO_NOTHING(&PrimarySurface, sizeof(PrimarySurface)); + PrimarySurface = DDraw.CreateSurface(SD); +} + +void ReleaseDirectDraw() +{ + SET_TO_NOTHING(&PrimarySurface, sizeof(PrimarySurface)); + SET_TO_NOTHING(&DDraw, sizeof(DDraw)); + SET_TO_NOTHING(&DirectX, sizeof(DirectX)); +} + +void ClipToWindow(long hWnd) +{ + DirectDrawClipper Clipper; + long shWnd; + + if (hWnd != 0) + shWnd = hWnd; + + // create clipper + Clipper = DDraw.CreateClipper(0); + Clipper.SetHWnd(shWnd); + PrimarySurface.SetClipper(Clipper); + SET_TO_NOTHING(&Clipper, sizeof(Clipper)); +} + +// Public Sub DimPrimary(Brightness&) +// Dim Pal As DirectDrawPalette +// Set Pal = PrimarySurface.GetPalette() +// End Sub + diff --git a/src/game_sp/DirectXGlobals.h b/src/game_sp/DirectXGlobals.h new file mode 100644 index 00000000..4615d91e --- /dev/null +++ b/src/game_sp/DirectXGlobals.h @@ -0,0 +1,26 @@ +// ---------------------------------------------------------------------------- +// DirectXGlobals.h +// ---------------------------------------------------------------------------- + +#ifndef DIRECTXGLOBALS_H +#define DIRECTXGLOBALS_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern void ClipToWindow(long hWnd); +extern void InitDirectX(long hWndForm, long hWndClip); +extern void ReleaseDirectDraw(); +extern void RestorePrimarySurface(); + +extern DirectDraw7 DDraw; +extern DirectDrawSurface7 PrimarySurface; +extern DirectSound DSound; +extern DirectX7 DirectX; +extern DirectX7 DirectXS; + +#endif /* DIRECTXGLOBALS_H */ diff --git a/src/game_sp/Display.c b/src/game_sp/Display.c new file mode 100644 index 00000000..b34ffa53 --- /dev/null +++ b/src/game_sp/Display.c @@ -0,0 +1,160 @@ +// ---------------------------------------------------------------------------- +// Display.c +// ---------------------------------------------------------------------------- + +#include "Display.h" + +static char *VB_Name = "modDisplay"; +// --- Option Explicit + +int ScreenScrollXPos, ScreenScrollYPos; +int ScreenPosition, data_h_Xtmp, data_h_Ytmp; + +int ShowRedDiskCounter, ShowPanel; +int ExplosionShake; +boolean NoDisplayFlag; + +long DisplayMinX, DisplayMaxX, DisplayWidth; +long DisplayMinY, DisplayMaxY, DisplayHeight; + + +int subDisplayInfotronsNeeded() +{ + int subDisplayInfotronsNeeded; + + if (NoDisplayFlag) + return subDisplayInfotronsNeeded; + + { +#if 0 + MainForm.lblInfoCount.Caption = InfotronsNeeded; + MainForm.lblInfoCount.Refresh; +#endif + } + + return subDisplayInfotronsNeeded; +} + +int subDisplayPlayingTime() +{ + int subDisplayPlayingTime; + + + return subDisplayPlayingTime; +} + +int subDisplayLevel() +{ + int subDisplayLevel; + + if (NoDisplayFlag || ! LevelLoaded) + return subDisplayLevel; + +#if 0 + MainForm.DisplayLevel(); +#endif + + return subDisplayLevel; +} + +void subDisplayPanel() +{ +} + +int subCheckRestoreRedDiskCountDisplay() +{ + int subCheckRestoreRedDiskCountDisplay; + + if (NoDisplayFlag) + return subCheckRestoreRedDiskCountDisplay; + + if (ShowRedDiskCounter == 0) + return subCheckRestoreRedDiskCountDisplay; + + ShowRedDiskCounter = ShowRedDiskCounter - 1; + if (ShowRedDiskCounter == 0) + { + { +#if 0 + MainForm.lblRedDiskCount.Caption = 0; + MainForm.lblRedDiskCount.Refresh; +#endif + } + } + + return subCheckRestoreRedDiskCountDisplay; +} + +void subDisplayRedDiskCount() +{ + if (NoDisplayFlag) + return; + + { +#if 0 + MainForm.lblRedDiskCount.Caption = RedDiskCount; + MainForm.lblRedDiskCount.Refresh; +#endif + } + ShowRedDiskCounter = 0x46; +} + +void ScrollTo(int X, int Y) +{ + long oldX, oldY; + + if (NoDisplayFlag) + return; + + oldX = ScrollX; + oldY = ScrollY; + X = ScrollDelta * (X / ScrollDelta); + X = Max(X, ScrollMinX); + X = Min(X, ScrollMaxX); + Y = ScrollDelta * (Y / ScrollDelta); + Y = Max(Y, ScrollMinY); + Y = Min(Y, ScrollMaxY); + // ScrollX = X + // ScrollY = Y + Stage.ScrollTo(X, Y); +} + +void ScrollTowards(int X, int Y) +{ + long oldX, oldY; + + if (NoDisplayFlag) + return; + + oldX = ScrollX; + oldY = ScrollY; + X = ScrollDelta * (X / ScrollDelta); + X = Max(X, ScrollMinX); + X = Min(X, ScrollMaxX); + Y = ScrollDelta * (Y / ScrollDelta); + Y = Max(Y, ScrollMinY); + Y = Min(Y, ScrollMaxY); + // ScrollX = X + // ScrollY = Y + Stage.ScrollTowards(X, Y, 2 * Stretch); +} + +void SoftScrollTo(int X, int Y, long TimeMS, int FPS) +{ + long oldX, oldY; + + if (NoDisplayFlag) + return; + + oldX = ScrollX; + oldY = ScrollY; + X = ScrollDelta * (X / ScrollDelta); + X = Max(X, ScrollMinX); + X = Min(X, ScrollMaxX); + Y = ScrollDelta * (Y / ScrollDelta); + Y = Max(Y, ScrollMinY); + Y = Min(Y, ScrollMaxY); + // ScrollX = X + // ScrollY = Y + Stage.SoftScrollTo(X, Y, TimeMS, FPS); +} diff --git a/src/game_sp/Display.h b/src/game_sp/Display.h new file mode 100644 index 00000000..e1dec9e7 --- /dev/null +++ b/src/game_sp/Display.h @@ -0,0 +1,33 @@ +// ---------------------------------------------------------------------------- +// Display.h +// ---------------------------------------------------------------------------- + +#ifndef DISPLAY_H +#define DISPLAY_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern void ScrollTo(int X, int Y); +extern void ScrollTowards(int X, int Y); +extern void SoftScrollTo(int X, int Y, long TimeMS, int FPS); +extern int subCheckRestoreRedDiskCountDisplay(); +extern int subDisplayInfotronsNeeded(); +extern int subDisplayLevel(); +extern void subDisplayPanel(); +extern int subDisplayPlayingTime(); +extern void subDisplayRedDiskCount(); + +extern boolean NoDisplayFlag; +extern int ExplosionShake; +extern int ScreenPosition, data_h_Xtmp, data_h_Ytmp; +extern int ScreenScrollXPos, ScreenScrollYPos; +extern int ShowRedDiskCounter, ShowPanel; +extern long DisplayMinX, DisplayMaxX, DisplayWidth; +extern long DisplayMinY, DisplayMaxY, DisplayHeight; + +#endif /* DISPLAY_H */ diff --git a/src/game_sp/DoGameStuff.c b/src/game_sp/DoGameStuff.c new file mode 100644 index 00000000..baa11022 --- /dev/null +++ b/src/game_sp/DoGameStuff.c @@ -0,0 +1,150 @@ +// ---------------------------------------------------------------------------- +// DoGameStuff.c +// ---------------------------------------------------------------------------- + +#include "DoGameStuff.h" + +static void CallAnimation(int si, byte bl); +static boolean IsToBeAnimated(int bl); + +static char *VB_Name = "modDoGameStuff"; +// --- Option Explicit + +int *AnimationPosTable; +byte *AnimationSubTable; + +// ========================================================================== +// SUBROUTINE +// Do game stuff +// ========================================================================== + +int subDoGameStuff() +{ + int subDoGameStuff; + + int si, cx, dx, bl; + + subAnimateMurphy(MurphyPosIndex); // move Murphy in any direction + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Build a database of locations and subs-to-call of animatable fields only: + // Make a snapshot from the field before the animation cycle starts. + // first and last line are not animated. + si = FieldWidth + 1; + cx = LevelMax - 2 * FieldWidth - 1; + dx = 0; + do // locloop_g_2282: + { + bl = LowByte(PlayField16[si]); + if (((bl & 0xD) != 0) && (bl < 0x20)) // all animatables have 1's in &H0D' above &H1F? (&H1F=explosion!) + { + if (IsToBeAnimated(bl)) + { + AnimationPosTable[dx] = si; + AnimationSubTable[dx] = bl; + dx = dx + 1; // count database entries + } + } + + si = si + 1; // next field + cx = cx - 1; + } + while (0 < cx); // locloop_g_2282' until all lines scanned(not top- and bottom edge) + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Now use the database to animate all animatables the fastest way. + // All the other fields are not checked anymore: those have no database entry. + // The field from before animation is frozen in the database in order not to + // do follow-up animations in the same loop. + if (dx != 0) // any database entries? + { + dx = dx - 1; + for (cx = 0; cx <= dx; cx++) + { + CallAnimation(AnimationPosTable[cx], AnimationSubTable[cx]); + } // loop locloop_g_22B8 ' until all animatables done + } + + // All animations are done now + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + if (KillMurphyFlag == 1 || MurphyMoveCounter == 0) + { + if (LeadOutCounter == 0) + { + KillMurphyFlag = 0; // no more "kill Murphy" + ExplodeFieldSP(MurphyExplodePos); // Explode + LeadOutCounter = 0x40; // quit: start lead-out + } + } // loc_g_22FB: + + + return subDoGameStuff; +} // subDoGameStuff + +static boolean IsToBeAnimated(int bl) +{ + static boolean IsToBeAnimated; + + switch (bl) + { + case fiZonk: + case fiInfotron: + case fiOrangeDisk: + case fiSnikSnak: + case fiTerminal: + case fiElectron: + case fiBug: + case fiExplosion: + IsToBeAnimated = True; + break; + + default: + IsToBeAnimated = False; + break; + } + + return IsToBeAnimated; +} + +static void CallAnimation(int si, byte bl) +{ + switch (bl) + { + case fiZonk: + subAnimateZonks(si); + break; + + case fiInfotron: + subAnimateInfotrons(si); + break; + + case fiOrangeDisk: + subAnimateOrangeDisks(si); + break; + + case fiSnikSnak: + subAnimateSnikSnaks(si); + break; + + case fiTerminal: + subAnimateTerminals(si); + break; + + case fiElectron: + subAnimateElectrons(si); + break; + + case fiBug: + subAnimateBugs(si); + break; + + case fiExplosion: + subAnimateExplosion(si); + break; + + default: + // Debug.Assert(False); + break; + } +} + diff --git a/src/game_sp/DoGameStuff.h b/src/game_sp/DoGameStuff.h new file mode 100644 index 00000000..5d97153c --- /dev/null +++ b/src/game_sp/DoGameStuff.h @@ -0,0 +1,20 @@ +// ---------------------------------------------------------------------------- +// DoGameStuff.h +// ---------------------------------------------------------------------------- + +#ifndef DOGAMESTUFF_H +#define DOGAMESTUFF_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern int subDoGameStuff(); + +extern byte *AnimationSubTable; +extern int *AnimationPosTable; + +#endif /* DOGAMESTUFF_H */ diff --git a/src/game_sp/Electrons.c b/src/game_sp/Electrons.c new file mode 100644 index 00000000..709583cf --- /dev/null +++ b/src/game_sp/Electrons.c @@ -0,0 +1,653 @@ +// ---------------------------------------------------------------------------- +// Electrons.c +// ---------------------------------------------------------------------------- + +#include "Electrons.h" + +static char *VB_Name = "modElectron"; +// --- Option Explicit +// ========================================================================== +// SUBROUTINE +// Animate/move Electrons +// ========================================================================== + +int subAnimateElectrons(int si) +{ + int subAnimateElectrons; + + int bx, Tmp; + + if (SnikSnaksElectronsFrozen == 1) + return subAnimateElectrons; + + if (LowByte(PlayField16[si]) != fiElectron) + return subAnimateElectrons; + + bx = HighByte(PlayField16[si]); + Tmp = bx / 8; + switch (Tmp) + { + case 0: + subElectronTurnLeft(si, bx); // turning, bx=0 -> point N, bx = 1 -> point NW etc. + break; + + case 1: + subElectronTurnRight(si, bx); // turn right + break; + + case 2: + subElectronFromBelow(si, bx); // access si from below + break; + + case 3: + subElectronFromRight(si, bx); // access si from right + break; + + case 4: + subElectronFromAbove(si, bx); // access si from above + break; + + case 5: + subElectronFromLeft(si, bx); // access si from left + break; + } + + return subAnimateElectrons; +} // subAnimateElectrons + +int subDrawAnimatedElectrons(int si) +{ + int subDrawAnimatedElectrons; + + int bx, Tmp; + + // If SnikSnaksElectronsFrozen = 1 Then Exit Function + if (LowByte(PlayField16[si]) != fiElectron) + return subDrawAnimatedElectrons; + + bx = HighByte(PlayField16[si]); + Tmp = bx / 8; + switch (Tmp) + { + case 0: + subDrawElectronTurnLeft(si, bx); // turning, bx=0 -> point N, bx = 1 -> point NW etc. + break; + + case 1: + subDrawElectronTurnRight(si, bx); // turn right + break; + + case 2: + subDrawElectronFromBelow(si, bx); // access si from below + break; + + case 3: + subDrawElectronFromRight(si, bx); // access si from right + break; + + case 4: + subDrawElectronFromAbove(si, bx); // access si from above + break; + + case 5: + subDrawElectronFromLeft(si, bx); // access si from left + break; + } + + return subDrawAnimatedElectrons; +} // subDrawAnimatedElectrons + +int subElectronTurnLeft(int si, int bx) +{ + int subElectronTurnLeft; + + int ax, ah, bl, dx, X, Y; + + ax = (TimerVar & 3); + if (ax != 0) + { + if (ax == 3) + goto loc_g_7ACD; + + return subElectronTurnLeft; + } // loc_g_7A9F: + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, aniElectron[bx]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bx = (bx + 1) & 0x7; + MovHighByte(&PlayField16[si], bx); + return subElectronTurnLeft; + +loc_g_7ACD: + bl = HighByte(PlayField16[si]); + if (bl == 0) + goto loc_g_7AE6; + + if (bl == 2) + goto loc_g_7B05; + + if (bl == 4) + goto loc_g_7B24; + + if (bl == 6) + goto loc_g_7B43; + + return subElectronTurnLeft; + +loc_g_7AE6: // pointing up + ax = PlayField16[si - FieldWidth]; + if (ax == 0) // above is empty -> go up + goto loc_g_7AF5; + + if (LowByte(ax) == fiMurphy) // above is murphy -> explode + ExplodeFieldSP(si); + + return subElectronTurnLeft; + +loc_g_7AF5: // above is empty -> go up + PlayField16[si] = 0x1BB; + si = si - FieldWidth; // 1 field up + PlayField16[si] = 0x1018; + return subElectronTurnLeft; + +loc_g_7B05: // pointing left + ax = PlayField16[si - 1]; + if (ax == 0) // left is empty -> go there + goto loc_g_7B14; + + if (LowByte(ax) == fiMurphy) // left is murphy -> explode + ExplodeFieldSP(si); + + return subElectronTurnLeft; + +loc_g_7B14: // left is empty -> go there + PlayField16[si] = 0x2BB; + si = si - 1; // 1 field left + PlayField16[si] = 0x1818; + return subElectronTurnLeft; + +loc_g_7B24: // pointing down + ax = PlayField16[si + FieldWidth]; + if (ax == 0) // below is empty -> go down + goto loc_g_7B33; + + if (LowByte(ax) == fiMurphy) // below is murphy -> explode + ExplodeFieldSP(si); + + return subElectronTurnLeft; + +loc_g_7B33: // below is empty -> go down + PlayField16[si] = 0x3BB; + si = si + FieldWidth; // 1 field down + PlayField16[si] = 0x2018; + return subElectronTurnLeft; + +loc_g_7B43: // pointing Right + ax = PlayField16[si + 1]; + if (ax == 0) // right is empty -> go there + goto loc_g_7B55; + + if (LowByte(ax) == fiMurphy) // right is murphy -> explode + ExplodeFieldSP(si); + + return subElectronTurnLeft; + +loc_g_7B55: // right is empty -> go there + PlayField16[si] = 0x4BB; + si = si + 1; // 1 field right + PlayField16[si] = 0x2818; + + return subElectronTurnLeft; +} // subElectronTurnLeft + +int subElectronTurnRight(int si, int bx) +{ + int subElectronTurnRight; + + int ax, ah, bl, dx, X, Y; + + ax = (TimerVar & 3); + if (ax != 0) + { + if (ax == 3) + goto loc_g_7BA3; + + return subElectronTurnRight; + } // loc_g_7B73: + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, aniElectron[0x10 - bx]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bx = ((bx + 1) & 0x7) | 8; + MovHighByte(&PlayField16[si], bx); + return subElectronTurnRight; + +loc_g_7BA3: + bl = HighByte(PlayField16[si]); + if (bl == 0x8) + goto loc_g_7BBC; + + if (bl == 0xA) + goto loc_g_7C19; + + if (bl == 0xC) + goto loc_g_7BFA; + + if (bl == 0xE) + goto loc_g_7BDB; + + return subElectronTurnRight; + +loc_g_7BBC: // pointing up + ax = PlayField16[si - FieldWidth]; + if (ax == 0) // above is empty -> go up + goto loc_g_7BCB; + + if (LowByte(ax) == fiMurphy) // above is murphy -> explode + ExplodeFieldSP(si); + + return subElectronTurnRight; + +loc_g_7BCB: // above is empty -> go up + PlayField16[si] = 0x1BB; + si = si - FieldWidth; // 1 field up + PlayField16[si] = 0x1018; + return subElectronTurnRight; + +loc_g_7BDB: // pointing left + ax = PlayField16[si - 1]; + if (ax == 0) // left is empty -> go there + goto loc_g_7BEA; + + if (LowByte(ax) == fiMurphy) // left is murphy -> explode + ExplodeFieldSP(si); + + return subElectronTurnRight; + +loc_g_7BEA: // left is empty -> go there + PlayField16[si] = 0x2BB; + si = si - 1; // 1 field left + PlayField16[si] = 0x1818; + return subElectronTurnRight; + +loc_g_7BFA: // pointing down + ax = PlayField16[si + FieldWidth]; + if (ax == 0) // below is empty -> go down + goto loc_g_7C09; + + if (LowByte(ax) == fiMurphy) // below is murphy -> explode + ExplodeFieldSP(si); + + return subElectronTurnRight; + +loc_g_7C09: // below is empty -> go down + PlayField16[si] = 0x3BB; + si = si + FieldWidth; // 1 field down + PlayField16[si] = 0x2018; + return subElectronTurnRight; + +loc_g_7C19: // pointing Right + ax = PlayField16[si + 1]; + if (ax == 0) // right is empty -> go there + goto loc_g_7C2B; + + if (LowByte(ax) == fiMurphy) // right is murphy -> explode + ExplodeFieldSP(si); + + return subElectronTurnRight; + +loc_g_7C2B: // right is empty -> go there + PlayField16[si] = 0x4BB; + si = si + 1; // 1 field right + PlayField16[si] = 0x2818; + + return subElectronTurnRight; +} // subElectronTurnRight + +int subElectronFromBelow(int si, int bx) +{ + int subElectronFromBelow; + + int ax, ah, bl, dx, X, Y; + + bx = bx - 0xF; // get and increment sequence# + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si + FieldWidth); + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X, Y - bx * TwoPixels, aniElectron[bx]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bl = LowByte(bx); + if (bl == 7 && LowByte(PlayField16[si + FieldWidth]) != fiExplosion) + { + PlayField16[si + FieldWidth] = 0; // electron left that field + } + + if (bl < 8) // electron still goes up + { + bl = bl + 0x10; + MovHighByte(&PlayField16[si], bl); + return subElectronFromBelow; + } // loc_g_7C84 + + PlayField16[si] = 0x18; // sequence#=8 -> arrived at the new field + ax = PlayField16[si - 1]; // check left field + if (ax == 0 || LowByte(ax) == fiMurphy) // check for empty or murphy + { + MovHighByte(&PlayField16[si], 1); // start to turn left + return subElectronFromBelow; + } // loc_g_7CA4: + + ax = PlayField16[si - FieldWidth]; // cannot turn left -> check above + if (ax == 0) // check if empty + { + PlayField16[si] = 0x1BB; // mark as "electron leaving" + si = si - FieldWidth; // go up! + PlayField16[si] = 0x1018; + return subElectronFromBelow; + } + + if (LowByte(ax) == fiMurphy) // check for murphy above + { + ExplodeFieldSP(si); // Explode + return subElectronFromBelow; + } // loc_g_7CC6: + + ax = PlayField16[si + 1]; // check right field + if (ax == 0 || LowByte(ax) == fiMurphy) // check for empty or murphy + { + MovHighByte(&PlayField16[si], 9); // start to turn right + return subElectronFromBelow; + } // loc_g_7CE0: + + // else: no way to go, start turning around + MovHighByte(&PlayField16[si], 1); + + return subElectronFromBelow; +} // subElectronFromBelow + +int subElectronFromRight(int si, int bx) +{ + int subElectronFromRight; + + int ax, ah, bl, dx, X, Y; + + bx = bx - 0x17; // get and increment sequence# + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si + 1); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X - bx * TwoPixels, Y, aniElectron[bx]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bl = LowByte(bx); + if (bl == 7 && LowByte(PlayField16[si + 1]) != fiExplosion) + { + PlayField16[si + 1] = 0; // electron left that field + } // loc_g_7D1D: + + if (bl < 8) // sniksnak still goes left + { + bl = bl + 0x18; + MovHighByte(&PlayField16[si], bl); + return subElectronFromRight; + } // loc_g_7D2A: + + PlayField16[si] = 0x18; // sequence#=8 -> arrived at the new field + ax = PlayField16[si + FieldWidth]; // check below + if (ax == 0 || LowByte(ax) == fiMurphy) // empty or murphy? + { + MovHighByte(&PlayField16[si], 3); // yes -> turn left down + return subElectronFromRight; + } // loc_g_7D4A: + + ax = PlayField16[si - 1]; // check left, etc ... see the comments on subElectronFromBelow() + if (ax == 0) + { + PlayField16[si] = 0x2BB; + si = si - 1; // 1 field left + PlayField16[si] = 0x1818; + return subElectronFromRight; + } // loc_g_7D61: + + if (LowByte(ax) == fiMurphy) + { + ExplodeFieldSP(si); // Explode + return subElectronFromRight; + } // loc_g_7D6C: + + ax = PlayField16[si - FieldWidth]; // check above + if (ax == 0 || LowByte(ax) == fiMurphy) + { + MovHighByte(&PlayField16[si], 0xF); + return subElectronFromRight; + } // loc_g_7D86: + + MovHighByte(&PlayField16[si], 3); + + return subElectronFromRight; +} // subElectronFromRight + +int subElectronFromAbove(int si, int bx) +{ + int subElectronFromAbove; + + int ax, ah, bl, dx, X, Y; + + bx = bx - 0x1F; // get and increment sequence# + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si - FieldWidth); + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X, Y + bx * TwoPixels, aniElectron[bx]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bl = LowByte(bx); + if (bl == 7 && LowByte(PlayField16[si - FieldWidth]) != fiExplosion) + { + PlayField16[si - FieldWidth] = 0; // electron left that field + } + + if (bl < 8) // electron still goes down + { + bl = bl + 0x20; + MovHighByte(&PlayField16[si], bl); + return subElectronFromAbove; + } // loc_g_7DD7 + + PlayField16[si] = 0x18; // sequence#=8 -> arrived at the new field + ax = PlayField16[si + 1]; // check right + if (ax == 0 || LowByte(ax) == fiMurphy) + { + MovHighByte(&PlayField16[si], 5); + return subElectronFromAbove; + } // loc_g_7DF7: + + ax = PlayField16[si + FieldWidth]; // check below + if (ax == 0) + { + PlayField16[si] = 0x3BB; + si = si + FieldWidth; // 1 field down + PlayField16[si] = 0x2018; + return subElectronFromAbove; + } // loc_g_7E0E: + + if (LowByte(ax) == fiMurphy) + { + ExplodeFieldSP(si); // Explode + return subElectronFromAbove; + } // loc_g_7E19: + + ax = PlayField16[si - 1]; // check left + if (ax == 0 || LowByte(ax) == fiMurphy) + { + MovHighByte(&PlayField16[si], 0xD); + return subElectronFromAbove; + } // loc_g_7E33: + + MovHighByte(&PlayField16[si], 5); + + return subElectronFromAbove; +} // subElectronFromAbove + +int subElectronFromLeft(int si, int bx) +{ + int subElectronFromLeft; + + int ax, ah, bl, dx, X, Y; + + bx = bx - 0x27; // get and increment sequence# + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si - 1); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X + bx * TwoPixels, Y, aniElectron[bx]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bl = LowByte(bx); + if (bl == 7 && LowByte(PlayField16[si - 1]) != fiExplosion) + { + PlayField16[si - 1] = 0; // electron left that field + } + + if (bl < 8) // electron still goes right + { + bl = bl + 0x28; + MovHighByte(&PlayField16[si], bl); + return subElectronFromLeft; + } // loc_g_7E7E: + + PlayField16[si] = 0x18; // sequence#=8 -> arrived at the new field + ax = PlayField16[si - FieldWidth]; // check above + if (ax == 0 || LowByte(ax) == fiMurphy) + { + MovHighByte(&PlayField16[si], 7); + return subElectronFromLeft; + } // loc_g_7E9E: + + ax = PlayField16[si + 1]; // check right(straight on) + if (ax == 0) + { + PlayField16[si] = 0x4BB; + si = si + 1; // 1 field right + PlayField16[si] = 0x2818; + return subElectronFromLeft; + } // loc_g_7EB5: + + if (LowByte(ax) == fiMurphy) + { + ExplodeFieldSP(si); // Explode + return subElectronFromLeft; + } // loc_g_7EC0: + + ax = PlayField16[si + FieldWidth]; // check below + if (ax == 0 || LowByte(ax) == fiMurphy) + { + MovHighByte(&PlayField16[si], 0xB); + return subElectronFromLeft; + } // loc_g_7A69: + + MovHighByte(&PlayField16[si], 7); + + return subElectronFromLeft; +} // subElectronFromLeft + +int subDrawElectronTurnLeft(int si, int bx) +{ + int subDrawElectronTurnLeft; + + int X, Y; + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, aniElectron[bx]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + return subDrawElectronTurnLeft; +} + +int subDrawElectronTurnRight(int si, int bx) +{ + int subDrawElectronTurnRight; + + int X, Y; + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, aniElectron[0x10 - bx]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + return subDrawElectronTurnRight; +} + +int subDrawElectronFromBelow(int si, int bx) +{ + int subDrawElectronFromBelow; + + int X, Y; + + bx = bx - 0xF; // get and increment sequence# + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si + FieldWidth); + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X, Y - bx * TwoPixels, aniElectron[bx]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + return subDrawElectronFromBelow; +} + +int subDrawElectronFromRight(int si, int bx) +{ + int subDrawElectronFromRight; + + int X, Y; + + bx = bx - 0x17; // get and increment sequence# + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si + 1); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X - bx * TwoPixels, Y, aniElectron[bx]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + return subDrawElectronFromRight; +} + +int subDrawElectronFromAbove(int si, int bx) +{ + int subDrawElectronFromAbove; + + int X, Y; + + bx = bx - 0x1F; // get and increment sequence# + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si - FieldWidth); + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X, Y + bx * TwoPixels, aniElectron[bx]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + return subDrawElectronFromAbove; +} + +int subDrawElectronFromLeft(int si, int bx) +{ + int subDrawElectronFromLeft; + + int X, Y; + + bx = bx - 0x27; // get and increment sequence# + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si - 1); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X + bx * TwoPixels, Y, aniElectron[bx]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + return subDrawElectronFromLeft; +} diff --git a/src/game_sp/Electrons.h b/src/game_sp/Electrons.h new file mode 100644 index 00000000..5eaf289c --- /dev/null +++ b/src/game_sp/Electrons.h @@ -0,0 +1,30 @@ +// ---------------------------------------------------------------------------- +// Electrons.h +// ---------------------------------------------------------------------------- + +#ifndef ELECTRONS_H +#define ELECTRONS_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern int subAnimateElectrons(int si); +extern int subDrawAnimatedElectrons(int si); +extern int subDrawElectronFromAbove(int si, int bx); +extern int subDrawElectronFromBelow(int si, int bx); +extern int subDrawElectronFromLeft(int si, int bx); +extern int subDrawElectronFromRight(int si, int bx); +extern int subDrawElectronTurnLeft(int si, int bx); +extern int subDrawElectronTurnRight(int si, int bx); +extern int subElectronFromAbove(int si, int bx); +extern int subElectronFromBelow(int si, int bx); +extern int subElectronFromLeft(int si, int bx); +extern int subElectronFromRight(int si, int bx); +extern int subElectronTurnLeft(int si, int bx); +extern int subElectronTurnRight(int si, int bx); + +#endif /* ELECTRONS_H */ diff --git a/src/game_sp/ErrorReporting.c b/src/game_sp/ErrorReporting.c new file mode 100644 index 00000000..8cd7457d --- /dev/null +++ b/src/game_sp/ErrorReporting.c @@ -0,0 +1,78 @@ +// ---------------------------------------------------------------------------- +// ErrorReporting.c +// ---------------------------------------------------------------------------- + +#include "ErrorReporting.h" + +static char * GetErrLogPath(); +static char * GetTraceLogPath(); + +static char *VB_Name = "modErrorReporting"; +// --- Option Explicit + +static char *GetErrLogPath() +{ + static char *GetErrLogPath; + + // GetErrLogPath = GET_PATH(WithSlash(App.Path), "Error.log"); + GetErrLogPath = "Error.log"; + + return GetErrLogPath; +} + +static char *GetTraceLogPath() +{ + static char *GetTraceLogPath; + + // GetTraceLogPath = GET_PATH(WithSlash(App.Path), "Trace.log"); + GetTraceLogPath = "Trace.log"; + + return GetTraceLogPath; +} + +void Trace(char *Source, char *Message) +{ + // Dim Path$, FNum%, bIsOpen As Boolean + // Path = GetTraceLogPath() + // FNum = FreeFile + // bIsOpen = False + // On Error GoTo TraceEH + // Open Path For Append Access Write As FNum + // bIsOpen = True + // ' --- Print #FNum, Now & " " & Source & " : " & Message + // On Error GoTo 0 + // TraceEH: + // If bIsOpen Then Close FNum +} + +void ReportError(char *Source, char *Message) +{ + char *Path; + int FNum; + boolean bIsOpen; + + Path = GetErrLogPath(); + // FNum = FreeFile(); + bIsOpen = False; + + // --- On Error GoTo ReportErrorEH + FNum = fopen(Path, "ab"); + bIsOpen = True; + // --- Print #FNum, Now & " SOURCE = " & Source & " ErrMessage = " & Message + // --- On Error GoTo 0 + + +ReportErrorEH: + if (bIsOpen) + fclose(FNum); +} + +void InitErrorReporting() +{ + char *Path; + + Path = GetErrLogPath(); + MayKill(Path); + Path = GetTraceLogPath(); + MayKill(Path); +} diff --git a/src/game_sp/ErrorReporting.h b/src/game_sp/ErrorReporting.h new file mode 100644 index 00000000..b5c0f512 --- /dev/null +++ b/src/game_sp/ErrorReporting.h @@ -0,0 +1,19 @@ +// ---------------------------------------------------------------------------- +// ErrorReporting.h +// ---------------------------------------------------------------------------- + +#ifndef ERRORREPORTING_H +#define ERRORREPORTING_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern void InitErrorReporting(); +extern void ReportError(char *Source, char *Message); +extern void Trace(char *Source, char *Message); + +#endif /* ERRORREPORTING_H */ diff --git a/src/game_sp/Explosions.c b/src/game_sp/Explosions.c new file mode 100644 index 00000000..b6b6ca80 --- /dev/null +++ b/src/game_sp/Explosions.c @@ -0,0 +1,337 @@ +// ---------------------------------------------------------------------------- +// Explosions.c +// ---------------------------------------------------------------------------- + +#include "Explosions.h" + +static void LetExplodeFieldSP(int tsi, int cx, int dh); +static int subExplodeInfotron(int tsi, int cx); +static int subExplodeZonk(int tsi, int cx); + +static char *VB_Name = "modExplosions"; +// --- Option Explicit + +// ========================================================================== +// SUBROUTINE +// Animate explosion +// ========================================================================== +int subAnimateExplosion(int si) +{ + int subAnimateExplosion; + + int ax, bx, bl, X, Y; + + if (LowByte(PlayField16[si]) != fiExplosion) + return subAnimateExplosion; + + ax = (TimerVar & 3); + if (ax != 0) + return subAnimateExplosion; + + bl = HighByte(PlayField16[si]); + if ((bl & 0x80) != 0) // infotron explosion! + goto loc_g_28D0; + + bl = bl + 1; + MovHighByte(&PlayField16[si], bl); + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, aniExplosion[bl]); + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + if (bl == 8) + { + PlayField16[si] = 0; + ExplosionShake = 0; // nothing explodes + } // loc_ret_g_28CF: + + return subAnimateExplosion; + +loc_g_28D0: // explosion produces infotron + bl = bl + 1; + if (bl == 0x89) + { + PlayField16[si] = fiInfotron; + MovLowByte(&ExplosionShake, 0); // nothing explodes + return subAnimateExplosion; + } // loc_g_28E3: + + MovHighByte(&PlayField16[si], bl); + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, aniExplosionInfo + bl - 0x80); + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + return subAnimateExplosion; +} // subAnimateExplosion + +// ========================================================================== +// SUBROUTINE +// Explode +// ========================================================================== + +void ExplodeFieldSP(int si) +{ + int ax, al, cx, dl, dh; + + ax = LowByte(PlayField16[si]); + if (ax == fiHardWare) + return; + + ExplosionShake = 1; // something explodes + if (ax == fiMurphy) + KillMurphyFlag = 1; + + if (ax == fiElectron) + { + cx = 0x801F; // produce infotrons + dl = 0xF3; + } + else // loc_g_2977: + { + cx = 0x1F; // normal explosion + dl = 0xD; + } // loc_g_297C: + + LetExplodeFieldSP(si - FieldWidth - 1, cx, dl); + LetExplodeFieldSP(si - FieldWidth, cx, dl); + LetExplodeFieldSP(si - FieldWidth + 1, cx, dl); + LetExplodeFieldSP(si - 1, cx, dl); + PlayField16[si] = cx; + LetExplodeFieldSP(si + 1, cx, dl); + LetExplodeFieldSP(si + FieldWidth - 1, cx, dl); + LetExplodeFieldSP(si + FieldWidth, cx, dl); + LetExplodeFieldSP(si + FieldWidth + 1, cx, dl); + +loc_g_2C3B: + subSoundFXExplosion(); +} // ExplodeFieldSP + +static void LetExplodeFieldSP(int tsi, int cx, int dh) +{ + int al; + + if (tsi < (-FieldWidth)) + return; + + al = LowByte(PlayField16[tsi]); + switch (al) + { + case fiHardWare: + return; + + break; + + case fiOrangeDisk: + case fiYellowDisk: + case fiSnikSnak: + PlayField8[tsi] = dh; + PlayField16[tsi] = cx; + break; + + case fiZonk: + subExplodeZonk(tsi, cx); + break; + + case fiInfotron: + subExplodeInfotron(tsi, cx); + break; + + case fiElectron: + PlayField8[tsi] = (-dh) & 0xFF; + PlayField16[tsi] = 0x801F; + break; + + case fiMurphy: + KillMurphyFlag = 1; + PlayField8[tsi] = dh; + PlayField16[tsi] = cx; + break; + + default: + PlayField16[tsi] = cx; + break; + } +} + +static int subExplodeZonk(int tsi, int cx) +{ + static int subExplodeZonk; + + int ah; + + ah = HighByte(PlayField16[tsi]) & 0xF0; + PlayField16[tsi] = cx; + switch (ah) + { + case 0x10: + case 0x70: + subClearFieldDueToExplosion(tsi - FieldWidth); + tsi = tsi + FieldWidth; + if (PlayField16[tsi] == 0x9999) + subClearFieldDueToExplosion(tsi); + + break; + + case 0x20: + subClearFieldDueToExplosion(tsi + 1); + subClearFieldDueToExplosion(tsi + FieldWidth); + break; + + case 0x30: + subClearFieldDueToExplosion(tsi - 1); + subClearFieldDueToExplosion(tsi + FieldWidth); + break; + + case 0x50: + subClearFieldDueToExplosion(tsi - 1); + break; + + case 0x60: + subClearFieldDueToExplosion(tsi + 1); + break; + + case 0xFF000070: // !!! 0x70; this will never be reached! ...?? + subClearFieldDueToExplosion(tsi + FieldWidth); + break; + } + + return subExplodeZonk; +} // subExplodeZonk + +static int subExplodeInfotron(int tsi, int cx) +{ + static int subExplodeInfotron; + + int ah; + + ah = HighByte(PlayField16[tsi]) & 0xF0; + PlayField16[tsi] = cx; + switch (ah) + { + case 0x10: + case 0x70: + subClearFieldDueToExplosion(tsi - FieldWidth); + tsi = tsi + FieldWidth; + if (PlayField16[tsi] == 0x9999) + subClearFieldDueToExplosion(tsi); + + break; + + case 0x20: + subClearFieldDueToExplosion(tsi + 1); + tsi = tsi + FieldWidth; // differnt from zonk version + if (PlayField16[tsi] == 0x9999) + subClearFieldDueToExplosion(tsi); + + break; + + case 0x30: + subClearFieldDueToExplosion(tsi - 1); + tsi = tsi + FieldWidth; // differnt from zonk version + if (PlayField16[tsi] == 0x9999) + subClearFieldDueToExplosion(tsi); + + break; + + case 0x50: + subClearFieldDueToExplosion(tsi - 1); + break; + + case 0x60: + subClearFieldDueToExplosion(tsi + 1); + break; + + case 0xFF000070: // !!! 0x70; this will never be reached! ...?? + subClearFieldDueToExplosion(tsi + FieldWidth); + break; + } + + return subExplodeInfotron; +} // subExplodeInfotron + +int subClearFieldDueToExplosion(int si) +{ + int subClearFieldDueToExplosion; + + int X, Y; + + if (LowByte(PlayField16[si]) == fiExplosion) + return subClearFieldDueToExplosion; + + PlayField16[si] = 0; + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, fiSpace); + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + return subClearFieldDueToExplosion; +} // subClearFieldDueToExplosion + +int subRedDiskReleaseExplosion() +{ + int subRedDiskReleaseExplosion; + + int al, X, Y, si; + + al = RedDiskReleasePhase; // Red disk release phase + if (al <= 1) + return subRedDiskReleaseExplosion; + + si = RedDiskReleaseMurphyPos; + if (PlayField16[si] == 0) // Release red disk + PlayField16[si] = fiRedDisk; + + // +++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, fiRedDisk); + // +++++++++++++++++++++++++++++++++++++++++ + RedDiskReleasePhase = RedDiskReleasePhase + 1; + if (RedDiskReleasePhase >= 0x28) + { + // si = RedDiskReleaseMurphyPos ' Red disk was released here + ExplodeFieldSP(si); // Explode + RedDiskReleasePhase = 0; + } + + return subRedDiskReleaseExplosion; +} + +int subFollowUpExplosions() +{ + int subFollowUpExplosions; + + int ax, si; + +locloop_g_2919: + for (si = 0; si <= LevelMax; si++) + { + ax = ByteToInt(PlayField8[si]); + if (ax != 0) + { + if (ax < 0) + { + ax = ax + 1; + PlayField8[si] = ax & 0xFF; + if (ax == 0) + { + PlayField16[si] = 0xFF18; + ExplodeFieldSP(si); // Explode + } + + } + else + { + ax = ax - 1; + PlayField8[si] = ax; + if (ax == 0) + ExplodeFieldSP(si); + } + } + } + + return subFollowUpExplosions; +} // subFollowUpExplosions diff --git a/src/game_sp/Explosions.h b/src/game_sp/Explosions.h new file mode 100644 index 00000000..16e41d5e --- /dev/null +++ b/src/game_sp/Explosions.h @@ -0,0 +1,21 @@ +// ---------------------------------------------------------------------------- +// Explosions.h +// ---------------------------------------------------------------------------- + +#ifndef EXPLOSIONS_H +#define EXPLOSIONS_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern void ExplodeFieldSP(int si); +extern int subAnimateExplosion(int si); +extern int subClearFieldDueToExplosion(int si); +extern int subFollowUpExplosions(); +extern int subRedDiskReleaseExplosion(); + +#endif /* EXPLOSIONS_H */ diff --git a/src/game_sp/FakeDeclares.c b/src/game_sp/FakeDeclares.c new file mode 100644 index 00000000..c6ed578e --- /dev/null +++ b/src/game_sp/FakeDeclares.c @@ -0,0 +1,114 @@ +// ---------------------------------------------------------------------------- +// FakeDeclares.c +// ---------------------------------------------------------------------------- + +#include "FakeDeclares.h" + +static void subUpdateHallOfFame(); + +static char *VB_Name = "FakeDeclares"; +// --- Option Explicit +// --- Option Compare Binary + +int MurphyPosIndex, MurphyXPos, MurphyYPos; +int MurphyScreenXPos, MurphyScreenYPos; +int MurphyExplodePos, SplitMoveFlag, RedDiskReleaseMurphyPos; +int KillMurphyFlag, MurphyMoveCounter; +long YawnSleepCounter; +int MurphyVar0DAC; +int MurphyVar0DAE; +int MurphyVarFaceLeft; +int ScratchGravity, GravityFlag; +int RedDiskReleaseFlag, MovingPictureSequencePhase; +int data_h_DemoDone, LevelStatus; + +int data_h_0DA7; +int data_h_0DA8; +int data_h_0DA9; +int data_h_0D9E; +int data_h_0D9F; +int data_h_0DA0; +int data_h_0DA1; +int data_h_0DA2; +int data_h_0DA4; +int data_h_0DA5; +int data_h_0DA6; + +int data_h_165A; +int YellowDisksExploded; +int AllowRedDiskCheat, AllowEatRightRedDiskBug; + +int GameBusyFlag; +int InfotronsNeeded, TotalInfotronsNeeded; +int RedDiskCount; +int SnikSnaksElectronsFrozen; + +boolean EditFlag; +int EditMode; +// --- const int edDraw = 1; +int edSelect = 2; +int edMove = 3; + +int DemoFlag, data_scr_demo, demo_stopped; +int WasDemoFlag; +int EP_GameDemoVar0DAA; +int RecordDemoFlag; // , DemoRecordingFlag% +int DemoKeyCode, DemoPointer; +long DemoOffset; +int DemoKeyRepeatCounter; + +int RedDiskReleasePhase; +int UpdatedFlag; + +int DebugVersionFlag, D_ModeFlag; +int Data_SubRest, Data_SubRstFlg; +int keyEnter; + +int data_SPtorunavail; // ??????? + +int UpdateTimeFlag; + +// boolean bModified; +boolean ModifiedFlag; + +static void subUpdateHallOfFame() +{ +} + +boolean Get_ModifiedFlag() +{ + // boolean ModifiedFlag; + + // Let_ModifiedFlag(bModified); + Let_ModifiedFlag(ModifiedFlag); + + return ModifiedFlag; +} + +void Let_ModifiedFlag(boolean NewVal) +{ + // If bModified = NewVal Then Exit Property + char *Cap; + + // bModified = NewVal; + ModifiedFlag = NewVal; + if (! LevelLoaded) + return; + + if (NewVal) + { + Cap = ""; // !!! Cap = "MegaPlex - " & StripFileName(OrigPath) & "*" + gSignature = ""; + bSignatureAvailable = False; + } + else + { + Cap = ""; // !!! Cap = "MegaPlex - " & StripFileName(OrigPath) + } + +#if 0 + if (MainForm.Caption != Cap) + MainForm.Caption = Cap; +#endif +} + diff --git a/src/game_sp/FakeDeclares.h b/src/game_sp/FakeDeclares.h new file mode 100644 index 00000000..327587f5 --- /dev/null +++ b/src/game_sp/FakeDeclares.h @@ -0,0 +1,69 @@ +// ---------------------------------------------------------------------------- +// FakeDeclares.h +// ---------------------------------------------------------------------------- + +#ifndef FAKEDECLARES_H +#define FAKEDECLARES_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +#define edDraw (1) + +extern boolean ModifiedFlag; +extern boolean Get_ModifiedFlag(); +extern void Let_ModifiedFlag(boolean NewVal); + +extern boolean EditFlag; +extern int AllowRedDiskCheat, AllowEatRightRedDiskBug; +extern int Data_SubRest, Data_SubRstFlg; +extern int DebugVersionFlag, D_ModeFlag; +extern int DemoFlag, data_scr_demo, demo_stopped; +extern int DemoKeyCode, DemoPointer; +extern int DemoKeyRepeatCounter; +extern int EP_GameDemoVar0DAA; +extern int EditMode; +extern int GameBusyFlag; +extern int InfotronsNeeded, TotalInfotronsNeeded; +extern int KillMurphyFlag, MurphyMoveCounter; +extern int MurphyExplodePos, SplitMoveFlag, RedDiskReleaseMurphyPos; +extern int MurphyPosIndex, MurphyXPos, MurphyYPos; +extern int MurphyScreenXPos, MurphyScreenYPos; +extern int MurphyVar0DAC; +extern int MurphyVar0DAE; +extern int MurphyVarFaceLeft; +extern int RecordDemoFlag; +extern int RedDiskCount; +extern int RedDiskReleaseFlag, MovingPictureSequencePhase; +extern int RedDiskReleasePhase; +extern int ScratchGravity, GravityFlag; +extern int SnikSnaksElectronsFrozen; +extern int UpdateTimeFlag; +extern int UpdatedFlag; +extern int WasDemoFlag; +extern int YellowDisksExploded; +extern int data_SPtorunavail; +extern int data_h_0D9E; +extern int data_h_0D9F; +extern int data_h_0DA0; +extern int data_h_0DA1; +extern int data_h_0DA2; +extern int data_h_0DA4; +extern int data_h_0DA5; +extern int data_h_0DA6; +extern int data_h_0DA7; +extern int data_h_0DA8; +extern int data_h_0DA9; +extern int data_h_165A; +extern int data_h_DemoDone, LevelStatus; +extern int edMove; +extern int edSelect; +extern int keyEnter; +extern long DemoOffset; +extern long YawnSleepCounter; + +#endif /* FAKEDECLARES_H */ diff --git a/src/game_sp/FancyRestore.c b/src/game_sp/FancyRestore.c new file mode 100644 index 00000000..e31dfeb9 --- /dev/null +++ b/src/game_sp/FancyRestore.c @@ -0,0 +1,22 @@ +// ---------------------------------------------------------------------------- +// FancyRestore.c +// ---------------------------------------------------------------------------- + +#include "FancyRestore.h" + +static char *VB_Name = "modFancy"; +// --- Option Explicit + +// ========================================================================== +// SUBROUTINE +// Restore fancy stuff from sparelevel (and destroy registers ...) +// ========================================================================== + + +int subRestoreFancy() +{ + int subRestoreFancy; + + + return subRestoreFancy; +} diff --git a/src/game_sp/FancyRestore.h b/src/game_sp/FancyRestore.h new file mode 100644 index 00000000..3edb6d7f --- /dev/null +++ b/src/game_sp/FancyRestore.h @@ -0,0 +1,17 @@ +// ---------------------------------------------------------------------------- +// FancyRestore.h +// ---------------------------------------------------------------------------- + +#ifndef FANCYRESTORE_H +#define FANCYRESTORE_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern int subRestoreFancy(); + +#endif /* FANCYRESTORE_H */ diff --git a/src/game_sp/GeneralTricks.c b/src/game_sp/GeneralTricks.c new file mode 100644 index 00000000..19de0d6c --- /dev/null +++ b/src/game_sp/GeneralTricks.c @@ -0,0 +1,149 @@ +// ---------------------------------------------------------------------------- +// GeneralTricks.c +// ---------------------------------------------------------------------------- + +#include "GeneralTricks.h" + +static char *VB_Name = "GeneralTricks_Module"; +// --- Option Explicit +// --- Option Compare Text + +double ValEx(char *TS) +{ + double ValEx; + + // Extends the Val() function for + // german-style number-representing strings + int i; + char *LS, *RS; + + i = InStr(1, TS, ","); + if (i != 0) + { + LS = Left(TS, i - 1); + RS = Right(TS, Len(TS) - i); + ValEx = Val(CAT(LS, ".", RS)); + } + else + { + ValEx = Val(TS); + } + + return ValEx; +} + +void INC(int *VAR, int Delta) +{ + *VAR = *VAR + Delta; +} + +void DEC(int *VAR, int Delta) +{ + *VAR = *VAR - Delta; +} + +char *MySplit(char *TS, char *Sep, long SCount) +{ + char *MySplit; + + char *T; + long i, J, k, q, L, SL; + char *RA; + + T = TS; + L = Len(TS); + SL = Len(Sep); + J = SCount; + if (J < 1) + { + J = 0; + i = 1; + while (i <= L) + { + k = InStr(i, T, Sep); + if (k < i) + break; + + if (i < k) + J = J + 1; + + i = k + SL; + } + + if (i <= L) + J = J + 1; + } + + if (0 < J) + RA = REDIM_1D(sizeof(char), 0, J + 1 - 1); + else + return MySplit; + + i = 1; + q = 0; + while (i <= L) + { + k = InStr(i, T, Sep); + if (k < i) + break; + + if (i < k) + { + if (J <= q + 1) + break; + + q = q + 1; + RA[q] = Mid(T, i, k - i); + } + + i = k + SL; + } + + if (i <= L) + { + q = q + 1; + T = Right(T, L - i + 1); + do + { + if (Len(T) <= SL) + break; + + if (Right(T, SL) == Sep) + { + T = Left(T, Len(T) - SL); + } + else + { + break; + } + } + while (1); + + strcpy(&RA[q], T); // RA(q) = T + } + + MySplit = RA; + + return MySplit; +} + +void MyReplace(char *TS, char *Pat1, char *Pat2) +{ + long k, SL1, SL2, TL; + + TL = Len(TS); + SL1 = Len(Pat1); + SL2 = Len(Pat2); + k = InStr(1, TS, Pat1); + if (k == 0) + return; + + do + { + TS = CAT(Left(TS, k - 1), Pat2, Right(TS, TL - k - SL1 + 1)); + TL = TL + SL2 - SL1; + k = InStr(k + SL2, TS, Pat1); + } + while (!(k == 0)); +} + diff --git a/src/game_sp/GeneralTricks.h b/src/game_sp/GeneralTricks.h new file mode 100644 index 00000000..e0ad48f7 --- /dev/null +++ b/src/game_sp/GeneralTricks.h @@ -0,0 +1,21 @@ +// ---------------------------------------------------------------------------- +// GeneralTricks.h +// ---------------------------------------------------------------------------- + +#ifndef GENERALTRICKS_H +#define GENERALTRICKS_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern void DEC(int *VAR, int Delta); +extern void INC(int *VAR, int Delta); +extern void MyReplace(char *TS, char *Pat1, char *Pat2); +extern char *MySplit(char *TS, char *Sep, long SCount); +extern double ValEx(char *TS); + +#endif /* GENERALTRICKS_H */ diff --git a/src/game_sp/Globals.c b/src/game_sp/Globals.c new file mode 100644 index 00000000..abba5793 --- /dev/null +++ b/src/game_sp/Globals.c @@ -0,0 +1,423 @@ +// ---------------------------------------------------------------------------- +// Globals.c +// ---------------------------------------------------------------------------- + +#include "Globals.h" + +static void ReadDemo(); +void ReadLevel(); + +static char *VB_Name = "modGlobals"; +// --- Option Explicit +// --- Option Compare Text +// --- Option Base 0 + +// --- const long StretchWidth = 16; +// --- const long StretchWidth2 = StretchWidth / 2; +// --- const long BaseWidth = 16; +// --- const int TwoPixels = 2; + +boolean Original; +boolean Cracked; +boolean Level_Arg; +boolean EGA_Arg; +boolean Record_Fix; +boolean SpeedKeys; +boolean Level_Fix; +boolean Dead_Code; +boolean Redundant; +boolean Alignments; +boolean Ctrl_Alt_Fix; +boolean Protection; +boolean EP_ENHANCE; +boolean EP_DEMO; +boolean EP_DEBUG; +boolean EXTRASPEED; +boolean TIMINGFIX; +boolean SafeRecord; +boolean Norm_Time; +boolean EP_OLD8; +boolean SAVEGAME; +boolean HP_DEMO; +boolean ScreenFix; +boolean DemoRecordFix; +boolean DebugSwitch; +boolean Ver62; +boolean Ver62test; +boolean Ver63; +boolean Ver64; + +int LevelNumber; +char *CurPath, *OrigPath, *TmpPath; +boolean LevelLoaded; +long SignatureDelay; + +boolean bCapturePane; + +int FieldWidth; // = 60 +int FieldHeight; // = 24 +int HeaderSize; // = 96 +int FieldMax, LevelMax; +long FileMax; +int *PlayField16; +byte *PlayField8; +byte *DisPlayField; + +// Public DisplayMin%, DisplayMax%, DisplayWidth%, DisplayHeight% + +int TimerVar, RandomSeed; +currency DeltaT; // Interval between two frames (in ms) +long DeltaTPlay, DeltaTDemo; +boolean BlockingSpeed; + +// --- const int posFrameCorner = 55; +// --- const int posFrameVertical = 110; +// --- const int posFrameHorizontal = 111; + +int FreezeZonks; + +// constants for Fixed Fields: +// --- const int fiSpace = 0; // &H00 space(28 = wall space ...) +// --- const int fiZonk = 1; // &H01 zonk +// --- const int fiBase = 2; // &H02 base +// --- const int fiMurphy = 3; // &H03 Murphy +// --- const int fiInfotron = 4; // &H04 infotron +// --- const int fiRAM = 5; // &H05 small RAM chip +// --- const int fiHardWare = 6; // &H06 hardware (square, standard pyramid shape) +// --- const int fiExit = 7; // &H07 exit +// --- const int fiOrangeDisk = 8; // &H08 brown/orange utility disk +// --- const int fiPortRight = 9; // &H09 port 1 left to right +// --- const int fiPortDown = 10; // &H0A port 1 up to down +// --- const int fiPortLeft = 11; // &H0B port 1 right to left +// --- const int fiPortUp = 12; // &H0C port 1 down to up +// --- const int fiSpPortRight = 13; // &H0D port 2 left to right (gravity change) +// --- const int fiSpPortDown = 14; // &H0E port 2 up to down (gravity change) +// --- const int fiSpPortLeft = 15; // &H0F port 2 right to left (gravity change) +// --- const int fiSpPortUp = 16; // &H10 port 2 down to up (gravity change) +// --- const int fiSnikSnak = 17; // &H11 snik snak +// --- const int fiYellowDisk = 18; // &H12 yellow utility disk +// --- const int fiTerminal = 19; // &H13 terminal +// --- const int fiRedDisk = 20; // &H14 red utility disk +// --- const int fiPortUpAndDown = 21; // &H15 vertical port +// --- const int fiPortLeftAndRight = 22; // &H16 horizontal port +// --- const int fiPortAllDirections = 23; // &H17 horizontal + vertical port +// --- const int fiElectron = 24; // &H18 electron +// --- const int fiBug = 25; // &H19 bug +// --- const int fiRAMLeft = 26; // &H1A horizontal RAM chip, left (pin 1) +// --- const int fiRAMRight = 27; // &H1B horizontal RAM chip, right +// --- const int fiHWFirst = 28; // &H1C hardware (radial blue circular cap + coloured shapes) + +// Public Const fiHW1% = 29 ' 29 = 1D hardware (green signal lamp) +// Public Const fiHW2% = 30 ' 30 = 1E hardware (blue signal lamp) +// Public Const fiHW3% = 31 ' 31 = 1F hardware (red signal lamp) +// Public Const fiHW4% = 32 ' 32 = 20 hardware (yellow/black diagonal stripes) +// Public Const fiHW5% = 33 ' 33 = 21 hardware (yellow resistor + blue + red shapes) +// Public Const fiHW6% = 34 ' 34 = 22 hardware (horizontal red capacitor + smd shape) +// Public Const fiHW7% = 35 ' 35 = 23 hardware (red + yellow + blue horizontal resistors) +// Public Const fiHW8% = 36 ' 36 = 24 hardware (3 red vertical resistors) +// --- const int fiHWLast = 37; // 37 = 25 hardware (3 yellow horizontal resistors) +// --- const int fiRAMTop = 38; // 38 = 26 vertical RAM chip, top (pin 1) +// --- const int fiRAMBottom = 39; // 39 = 27 vertical RAM chip, bottom + +// Specials to experiment with ... +// --- const int fiWallSpace = 40; // 40 = 28 invisible wall (can explode, zonks don't roll off) +// --- const int fiHWTrash1 = 41; // 41 = 29 hardware trash +// --- const int fiHWTrash2 = 42; // 42 = 2A hardware trash +// --- const int fiHWMurphy = 43; // 43 = 2B hardware inverted Murphy ... (maybe nice for use?) + +// --- const int fiExplosion = 0x1F; + +// --- const int keyNone = 0; +// --- const int keyUp = 1; +// --- const int keyLeft = 2; +// --- const int keyDown = 3; +// --- const int keyRight = 4; +// --- const int keySpaceUp = 5; +// --- const int keySpaceLeft = 6; +// --- const int keySpaceDown = 7; +// --- const int keySpaceRight = 8; +// --- const int keySpace = 9; + +int *aniBug, *aniZonkRollRight, *aniZonkRollLeft; +int *aniInfotronRollRight, *aniInfotronRollLeft; +int *aniSnikSnak, *aniElectron, *aniExplosion; +int *aniTouchBase, *aniTouchInfotron, *aniTouchRedDisk; +// --- const int aniExplosionInfo = 111; +// --- const int aniSnikSnakUp = 159; +// --- const int aniSnikSnakDown = 167; +// --- const int aniSnikSnakLeft = 239; +// --- const int aniSnikSnakRight = 247; +// --- const int aniMurphyYawn = 56; +// --- const int aniMurphySleepLeft = 71; +// --- const int aniMurphySleepRight = 68; +int *aniMurphyExit; // , aniMurphyFaceLeft%, aniMurphyFaceRight% +int *aniMurphyEatLeft, *aniMurphyEatRight; // , aniMurphyEatRightRedDisk +int *aniMurphyEatUpLeft, *aniMurphyEatUpRight, *aniSplitUpDown; +int *aniYellowDisk, *aniOrangeDisk, *aniRedDisk; +// --- const int aniMurphyTouchUp = 46; +// --- const int aniMurphyTouchLeft = 95; +// --- const int aniMurphyTouchDown = 47; +// --- const int aniMurphyTouchRight = 94; +int *aniEatInfotronLeft, *aniEatInfotronRight; +// --- const int aniPushLeft = 45; +// --- const int aniPushRight = 44; +// --- const int aniPushUpDown = 79; + +void InitGlobals() +{ + aniBug = Array(74, 75, 76, 77, 78, 77, 76, 77, 78, 77, 76, 75, 74, 25); + aniZonkRollRight = Array(198, 197, 196, 195, 194, 193, 192, 1, -1); + aniZonkRollLeft = Array(192, 193, 194, 195, 196, 197, 198, 1, -1); + aniInfotronRollRight = Array(206, 205, 204, 203, 202, 201, 200, 4); + aniInfotronRollLeft = Array(200, 201, 202, 203, 204, 205, 206, 4); + aniSnikSnak = Array(121, 122, 123, 124, 125, 126, 127, 120, 121); + aniElectron = Array(144, 145, 146, 147, 148, 149, 150, 151, 144); + aniExplosion = Array(3, 103, 104, 105, 106, 107, 108, 109, 0); + aniTouchBase = Array(80, 81, 82, 83, 84, 85, 86, 0, -1); + aniTouchInfotron = Array(87, 88, 89, 91, 92, 93, 0, -1); // Only seven frames!!!! + aniTouchRedDisk = Array(96, 97, 98, 99, 100, 101, 102, 0, -1); + aniMurphyExit = Array(46, 46, 46, 46, 47, 47, 47, 47, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51, 52, 52, 52, 52, 53, 53, 53, 53, 54, 54, 54, 54, 0, 0, 0, 0, -1); + aniMurphyEatLeft = Array(176, 177, 178, 179, 180, 181, 182, 183, -1); + aniMurphyEatRight = Array(184, 185, 186, 187, 188, 189, 190, 191, -1); + aniMurphyEatUpLeft = Array(183, 182, 181, 180, 179, 178, 177, 176, -1); + aniMurphyEatUpRight = Array(191, 190, 189, 188, 187, 186, 185, 184, -1); + // aniMurphyEatRightRedDisk = Array(184, 184, 185, 186, 187, 188, 189, 190, 191, -1) '9 frames! + aniEatInfotronLeft = Array(209, 211, 213, 215, 217, 219, 221, 223, -1); + aniEatInfotronRight = Array(224, 226, 228, 230, 232, 234, 236, 238, -1); + aniSplitUpDown = Array(3, 3, 3, 3, 3, 3, 3, 3, -1); + aniYellowDisk = Array(18, 18, 18, 18, 18, 18, 18, 18, -1); + aniOrangeDisk = Array(8, 8, 8, 8, 8, 8, 8, 8, -1); + aniRedDisk = Array(20, -1); + InitPseudoCompileFlags(); + UserDragFlag = False; + AutoScrollFlag = True; + FreezeZonks = 0; + BlockingSpeed = False; + LevelLoaded = False; + FieldWidth = 60; + FieldHeight = 24; + HeaderSize = 96; + FieldMax = (FieldWidth * FieldHeight) + HeaderSize - 1; + LevelMax = (FieldWidth * FieldHeight) - 1; + Let_ModifiedFlag(False); + bPlaying = False; + gSignature = ""; + bSignatureAvailable = False; + FirstDemoByte = 0x81; + MySignature = ""; + InitErrorReporting(); +} + +void InitPseudoCompileFlags() +{ + Cracked = 1; // If protection Then crack it + Level_Arg = 1; // :number is cmd line option + // Level_Arg = 0 ' Remove Level cmd line option + EGA_Arg = 1; // EGA is command line option + Record_Fix = 1; // Assemble with fixed Demo rec + SpeedKeys = 0; // Remove Speed Keys fix + Level_Fix = 1; // Assemble with Level Fix + Dead_Code = 0; // Remove dead code + Redundant = 0; // Remove redundant code + Alignments = 1; // Assemble with alignments + Ctrl_Alt_Fix = 1; // Assemble with Ctrl/Alt fix + Protection = 0; // Remove protection code,do HP + // EP added by EP for version 5. + EP_ENHANCE = 1; // Some more nice things (EP) + EP_DEMO = 1; // Use .SP files for demos (EP) + // Including record demo! + EP_DEBUG = 0; // little cmdline debugging + EXTRASPEED = 1; // '@' option, superfast! + TIMINGFIX = 1; // "Fixed" the timing problem.. + // Inactive If DemoRecordFix Then1 + SafeRecord = 1; // skip debug keys in recording + Norm_Time = 1; // force automatic speed test, + // save result and then do as + // requested from cmd line. + EP_OLD8 = 1; // call old int8 from current. + SAVEGAME = 1; // Allow saving to SUPAPLEX.SAV + HP_DEMO = 1; // Use fixed demo routines 5.5 + ScreenFix = 1; // No menu-write to gamy field + DemoRecordFix = 1; // Demo record timing fix on + DebugSwitch = 1; // Allow Ctrl/Alt-ScrollLock + Ver62 = 1; // Version 6.2 stuff + Ver62test = 0; // Version 6.2 test stuff + Ver63 = 1; // Version 6.3 stuff + Ver64 = 1; // Version 6.4 stuff + +} + +int GetSI(int X, int Y) +{ + int GetSI; + + GetSI = Y * FieldWidth + X; + + return GetSI; +} + +int GetX(int si) +{ + int GetX; + + GetX = si % FieldWidth; + + return GetX; +} + +int GetY(int si) +{ + int GetY; + + GetY = si / FieldWidth; + + return GetY; +} + +int GetStretchX(int si) +{ + int GetStretchX; + + GetStretchX = StretchWidth * (si % FieldWidth); + + return GetStretchX; +} + +int GetStretchY(int si) +{ + int GetStretchY; + + GetStretchY = StretchWidth * (si / FieldWidth); + + return GetStretchY; +} + +void ReadLevel() +{ + // int FNum; + FILE *FNum; + long i; + // byte T; + + DemoAvailable = False; + if (STRING_IS_LIKE(CurPath, "*.mpx")) + { + ReadMPX(); + return; + } + + if (STRING_IS_LIKE(CurPath, "*.sp")) + { + ReadDemo(); + return; + } + + if (DemoFlag != 0) + { + ReadDemo(); + return; + } + + FileMax = 0; + FieldWidth = 60; + FieldHeight = 24; + HeaderSize = 96; + FieldMax = (FieldWidth * FieldHeight) + HeaderSize - 1; + LevelMax = (FieldWidth * FieldHeight) - 1; + PlayField8 = REDIM_1D(sizeof(byte), 0, FieldMax + 1 - 1); + DisPlayField = REDIM_1D(sizeof(byte), 0, FieldMax + 1 - 1); + // FNum = FreeFile(); + + // --- On Error GoTo ReadLevelEH + FNum = fopen(CurPath, "rb"); + i = (LevelNumber - 1) * ((long)(FieldMax) + 1) + 1; + FILE_GET(FNum, i, &PlayField8, sizeof(PlayField8)); + i = (LevelNumber) * ((long)(FieldMax) + 1) + 1 - HeaderSize; + FILE_GET(FNum, i, &LInfo, sizeof(LInfo)); // store level info in an extra structure + fclose(FNum); + // --- On Error GoTo 0 + + if (FieldMax < FileMax) + DemoAvailable = True; + + ReadSignature(); + PlayField16 = REDIM_1D(sizeof(int), -FieldWidth, FieldMax); + for (i = 0; i <= FieldMax; i++) + { + PlayField16[i] = PlayField8[i]; + DisPlayField[i] = PlayField8[i]; + PlayField8[i] = 0; + } + + AnimationPosTable = REDIM_1D(sizeof(int), 0, LevelMax - 2 *FieldWidth); + AnimationSubTable = REDIM_1D(sizeof(byte), 0, LevelMax - 2 *FieldWidth); + TerminalState = REDIM_1D(sizeof(byte), FieldWidth, LevelMax - FieldWidth); + GravityFlag = LInfo.InitialGravity; + FreezeZonks = LInfo.InitialFreezeZonks; + subRandomize(); + LevelLoaded = True; + return; + +#if 0 +ReadLevelEH: + Close(); +#endif +} + +static void ReadDemo() +{ + // int FNum, i; + FILE *FNum; + int i; + // byte T; + + FieldWidth = 60; + FieldHeight = 24; + HeaderSize = 96; + FieldMax = (FieldWidth * FieldHeight) + HeaderSize - 1; + LevelMax = (FieldWidth * FieldHeight) - 1; + + // --- On Error GoTo ReadDemoEH + FileMax = FileLen(CurPath) - 1; + PlayField8 = REDIM_1D(sizeof(byte), 0, FileMax + 1 - 1); + DisPlayField = REDIM_1D(sizeof(byte), 0, FieldMax + 1 - 1); + // FNum = FreeFile(); + FNum = fopen(CurPath, "rb"); + i = (LevelNumber - 1) * ((long)(FieldMax) + 1) + 1; + FILE_GET(FNum, i, &PlayField8, sizeof(PlayField8)); + i = (LevelNumber) * ((long)(FieldMax) + 1) + 1 - HeaderSize; + FILE_GET(FNum, i, &LInfo, sizeof(LInfo)); // store level info in an extra structure + fclose(FNum); + // --- On Error GoTo 0 + + if (FieldMax < FileMax) + DemoAvailable = True; + + ReadSignature(); + PlayField16 = REDIM_1D(sizeof(int), -FieldWidth, FieldMax); + for (i = 0; i <= FieldMax; i++) + { + PlayField16[i] = PlayField8[i]; + DisPlayField[i] = PlayField8[i]; + PlayField8[i] = 0; + } + + AnimationPosTable = REDIM_1D(sizeof(int), 0, LevelMax - 2 *FieldWidth); + AnimationSubTable = REDIM_1D(sizeof(byte), 0, LevelMax - 2 *FieldWidth); + TerminalState = REDIM_1D(sizeof(byte), 0, FieldMax + 1 - 1); + DemoPointer = FieldMax + 1; + DemoOffset = DemoPointer; + DemoKeyRepeatCounter = 0; + // DemoFlag = 1 + // DemoAvailable = True + GravityFlag = LInfo.InitialGravity; + FreezeZonks = LInfo.InitialFreezeZonks; + RandomSeed = LInfo.DemoRandomSeed; + LevelLoaded = True; + return; + +#if 0 +ReadDemoEH: + Close(); +#endif +} diff --git a/src/game_sp/Globals.h b/src/game_sp/Globals.h new file mode 100644 index 00000000..64f3230c --- /dev/null +++ b/src/game_sp/Globals.h @@ -0,0 +1,152 @@ +// ---------------------------------------------------------------------------- +// Globals.h +// ---------------------------------------------------------------------------- + +#ifndef GLOBALS_H +#define GLOBALS_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +#define BaseWidth (16) +#define StretchWidth (16) +#define StretchWidth2 (StretchWidth / 2) +#define TwoPixels (2) +#define aniExplosionInfo (111) +#define aniMurphySleepLeft (71) +#define aniMurphySleepRight (68) +#define aniMurphyTouchDown (47) +#define aniMurphyTouchLeft (95) +#define aniMurphyTouchRight (94) +#define aniMurphyTouchUp (46) +#define aniMurphyYawn (56) +#define aniPushLeft (45) +#define aniPushRight (44) +#define aniPushUpDown (79) +#define aniSnikSnakDown (167) +#define aniSnikSnakLeft (239) +#define aniSnikSnakRight (247) +#define aniSnikSnakUp (159) +#define fiBase (2) +#define fiBug (25) +#define fiElectron (24) +#define fiExit (7) +#define fiExplosion (0x1F) +#define fiHWFirst (28) +#define fiHWLast (37) +#define fiHWMurphy (43) +#define fiHWTrash1 (41) +#define fiHWTrash2 (42) +#define fiHardWare (6) +#define fiInfotron (4) +#define fiMurphy (3) +#define fiOrangeDisk (8) +#define fiPortAllDirections (23) +#define fiPortDown (10) +#define fiPortLeft (11) +#define fiPortLeftAndRight (22) +#define fiPortRight (9) +#define fiPortUp (12) +#define fiPortUpAndDown (21) +#define fiRAM (5) +#define fiRAMBottom (39) +#define fiRAMLeft (26) +#define fiRAMRight (27) +#define fiRAMTop (38) +#define fiRedDisk (20) +#define fiSnikSnak (17) +#define fiSpPortDown (14) +#define fiSpPortLeft (15) +#define fiSpPortRight (13) +#define fiSpPortUp (16) +#define fiSpace (0) +#define fiTerminal (19) +#define fiWallSpace (40) +#define fiYellowDisk (18) +#define fiZonk (1) +#define keyDown (3) +#define keyLeft (2) +#define keyNone (0) +#define keyRight (4) +#define keySpace (9) +#define keySpaceDown (7) +#define keySpaceLeft (6) +#define keySpaceRight (8) +#define keySpaceUp (5) +#define keyUp (1) +#define posFrameCorner (55) +#define posFrameHorizontal (111) +#define posFrameVertical (110) + +extern int GetSI(int X, int Y); +extern int GetStretchX(int si); +extern int GetStretchY(int si); +extern int GetX(int si); +extern int GetY(int si); +extern void InitGlobals(); +extern void InitPseudoCompileFlags(); + +extern void ReadLevel(); + +extern boolean Alignments; +extern boolean BlockingSpeed; +extern boolean Cracked; +extern boolean Ctrl_Alt_Fix; +extern boolean Dead_Code; +extern boolean DebugSwitch; +extern boolean DemoRecordFix; +extern boolean EGA_Arg; +extern boolean EP_DEBUG; +extern boolean EP_DEMO; +extern boolean EP_ENHANCE; +extern boolean EP_OLD8; +extern boolean EXTRASPEED; +extern boolean HP_DEMO; +extern boolean LevelLoaded; +extern boolean Level_Arg; +extern boolean Level_Fix; +extern boolean Norm_Time; +extern boolean Original; +extern boolean Protection; +extern boolean Record_Fix; +extern boolean Redundant; +extern boolean SAVEGAME; +extern boolean SafeRecord; +extern boolean ScreenFix; +extern boolean SpeedKeys; +extern boolean TIMINGFIX; +extern boolean Ver62; +extern boolean Ver62test; +extern boolean Ver63; +extern boolean Ver64; +extern boolean bCapturePane; +extern byte *DisPlayField; +extern byte *PlayField8; +extern char *CurPath, *OrigPath, *TmpPath; +extern currency DeltaT; +extern int *PlayField16; +extern int *aniBug, *aniZonkRollRight, *aniZonkRollLeft; +extern int *aniEatInfotronLeft, *aniEatInfotronRight; +extern int *aniInfotronRollRight, *aniInfotronRollLeft; +extern int *aniMurphyEatLeft, *aniMurphyEatRight; +extern int *aniMurphyEatUpLeft, *aniMurphyEatUpRight, *aniSplitUpDown; +extern int *aniMurphyExit; +extern int *aniSnikSnak, *aniElectron, *aniExplosion; +extern int *aniTouchBase, *aniTouchInfotron, *aniTouchRedDisk; +extern int *aniYellowDisk, *aniOrangeDisk, *aniRedDisk; +extern int FieldHeight; +extern int FieldMax, LevelMax; +extern int FieldWidth; +extern int FreezeZonks; +extern int HeaderSize; +extern int LevelNumber; +extern int TimerVar, RandomSeed; +extern long DeltaTPlay, DeltaTDemo; +extern long FileMax; +extern long SignatureDelay; + +#endif /* GLOBALS_H */ diff --git a/src/game_sp/Infotrons.c b/src/game_sp/Infotrons.c new file mode 100644 index 00000000..bcede9d4 --- /dev/null +++ b/src/game_sp/Infotrons.c @@ -0,0 +1,449 @@ +// ---------------------------------------------------------------------------- +// Infotrons.c +// ---------------------------------------------------------------------------- + +#include "Infotrons.h" + +static char *VB_Name = "modInfotron"; +// --- Option Explicit + +// ========================================================================== +// SUBROUTINE +// Animate Infotrons (falling) +// ========================================================================== + +int subAnimateInfotrons(int si) +{ + int subAnimateInfotrons; + + int tFld; + + // PseudoRegisters: + int ax, bx, cx, dx, di, X, Y; + int ah, bh, ch, dh, al, bl, cl, dl; + + tFld = PlayField16[si]; + if ((tFld & 0xFF) != fiInfotron) + return subAnimateInfotrons; + + if (tFld == fiInfotron) + { + ax = PlayField16[si + FieldWidth]; // select case playfield16(si+60) + if (ax == 0) + goto loc_g_11D5; + + if (ax == fiZonk) + goto loc_g_11A6; + + if (ax == fiInfotron) + goto loc_g_11A6; + + if (ax == fiRAM) + goto loc_g_11A6; + + return subAnimateInfotrons; + +loc_g_11A6: // Case fiZonk, fiInfotron, fiRAM + ax = PlayField16[si + FieldWidth - 1]; + if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) + goto loc_g_11DC; + +loc_g_11BD: + ax = PlayField16[si + FieldWidth + 1]; + if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) + goto loc_g_11F2; + + return subAnimateInfotrons; + +loc_g_11D5: // Case fiSpace + MovHighByte(&PlayField16[si], 0x40); + goto loc_g_1207; + +loc_g_11DC: // roll left? + if (PlayField16[si - 1] == 0) + goto loc_g_11E5; + + goto loc_g_11BD; + +loc_g_11E5: + MovHighByte(&PlayField16[si], 0x50); + PlayField16[si - 1] = 0x8888; + goto loc_g_1207; + +loc_g_11F2: // roll right? + if (PlayField16[si + 1] == 0) + goto loc_g_11FA; + + return subAnimateInfotrons; + +loc_g_11FA: + MovHighByte(&PlayField16[si], 0x60); + PlayField16[si + 1] = 0x8888; + } // tFld = fiInfotron + +loc_g_1207: + // from now on the infotron is definitely moving, + // maybe the sequence is in an advanced frame + // or just beeing initialized due to the code above + bl = HighByte(PlayField16[si]); + bx = 0; + MovLowByte(&bx, bl); + al = bl & 0xF0; + if (al == 0x10) // infotron comes falling from above + goto loc_g_1242; + + if (al == 0x20) // infotron comes rolling from right to left + goto loc_g_138D; + + if (al == 0x30) // infotron comes rolling from left to right + goto loc_g_13E9; + + if (al == 0x40) // infotron falls straight down + goto loc_g_1444; + + if (al == 0x50) // infotron rolls left + goto loc_g_1472; + + if (al == 0x60) // infotron rolls right + goto loc_g_14E0; + + if (al == 0x70) // intermediate state + goto loc_g_154E; + + return subAnimateInfotrons; + +loc_g_1242: // infotron comes falling from above + // To Do: draw infotron falling from above + // according to position in (bl And &H07) + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si - FieldWidth); + dx = bl & 0x7; + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X, Y + TwoPixels * (dx + 1), fiInfotron); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bl = HighByte(PlayField16[si]) + 1; + if (bl == 0x16) + { + MovHighByte(&PlayField16[si], bl); + subCleanUpForInfotronsAbove(si - FieldWidth); + return subAnimateInfotrons; + } // loc_g_1285: + + if (bl < 0x18) + { + MovHighByte(&PlayField16[si], bl); + return subAnimateInfotrons; + } // loc_g_128F: + + MovHighByte(&PlayField16[si], 0); // infotron arrived at the field + + // now check if the zonk may go on falling somehow + ax = PlayField16[si + FieldWidth]; + if (ax == 0) // below is empty!-> go on falling + goto loc_g_132D; + + if (ax == 0x9999) // below is only temporarily used + goto loc_g_132D; + + if ((ax & 0xFF) == fiMurphy) // Murphy dies + goto loc_g_1364; + + if (ax == fiRedDisk) // red disk hit + goto loc_g_1386; + + if ((ax & 0xFF) == fiSnikSnak) // SnikSnak dies + goto loc_g_1386; + + + if ((ax & 0xFF) == fiElectron) // Electron cracked! + goto loc_g_1386; + + if (ax == fiYellowDisk) // yellow disk hit + goto loc_g_1386; + + if (ax == fiOrangeDisk) // orange disk hit + goto loc_g_1386; + + subSoundFXZonk(); // play the zonk sound,'cause zonk hits something "hard" + + if (! (ax == fiZonk || ax == fiInfotron || ax == fiRAM)) + return subAnimateInfotrons; + + // infotron rolls somewhere + ax = PlayField16[si + FieldWidth - 1]; + if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) // may roll left + goto loc_g_133A; + + ax = PlayField16[si + FieldWidth + 1]; + if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) // may roll right + goto loc_g_1350; + + return subAnimateInfotrons; + +loc_g_132D: // go on falling down? + PlayField16[si] = 0x7004; // go into intermediate waitstate + PlayField16[si + FieldWidth] = 0x9999; // mark as "zonk waiting to access" + return subAnimateInfotrons; + +loc_g_133A: // test if infotron may roll left + // This if(if true) jumps up far above + // to the according rountine for fixed infotrons! + if (PlayField16[si - 1] != 0) // Remarkable!!! ' loc_g_0EF4: + goto loc_g_11BD; + + MovHighByte(&PlayField16[si], 0x50); // infotron rolls left + Mov(&PlayField16[si - 1], 0x8888); + return subAnimateInfotrons; + +loc_g_1350: // test if infotron may roll right + if (PlayField16[si + 1] != 0) + return subAnimateInfotrons; + + MovHighByte(&PlayField16[si], 0x60); // infotron rolls right + Mov(&PlayField16[si + 1], 0x8888); + return subAnimateInfotrons; + +loc_g_1364: // Murphy dies, but not in any case + bl = HighByte(PlayField16[si + FieldWidth]); + if (bl == 0xE || bl == 0xF || bl == 0x28) + return subAnimateInfotrons; + + if (bl == 0x29 || bl == 0x25 || bl == 0x26) + return subAnimateInfotrons; + + + + + + + + + + + +loc_g_1386: // someone dies/explodes immediately + si = si + FieldWidth; // 1 field down + ExplodeFieldSP(si); // Explode + return subAnimateInfotrons; + + + + + +loc_g_138D: // infotron comes rolling from right to left + // To Do: draw infotron rolling from right + // according to position in (bl And &H07) + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si + 1); + Y = GetStretchY(si); + dx = (bl & 0x7) + 1; + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X - (TwoPixels * dx), Y, aniInfotronRollLeft[dx - 1]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bl = HighByte(PlayField16[si]) + 1; // get and increment sequence# + if (bl == 0x24) + PlayField16[si + 1] = 0xAAAA; + + if (bl == 0x26) + { + MovHighByte(&PlayField16[si], bl); + subCleanUpForInfotronsAbove(si + 1); + } + else if (bl < 0x28) + { + MovHighByte(&PlayField16[si], bl); + } + else + { + PlayField16[si] = 0x7004; // go into intermediate state + } + + return subAnimateInfotrons; + +loc_g_13E9: // infotron comes rolling from left to right + // To Do: draw infotron rolling from left + // according to position in (bl And &H07) + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si - 1); + Y = GetStretchY(si); + dx = (bl & 0x7) + 1; + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X + (TwoPixels * dx), Y, aniInfotronRollRight[dx - 1]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bl = HighByte(PlayField16[si]) + 1; + if (bl == 0x34) + PlayField16[si - 1] = 0xAAAA; + + if (bl == 0x36) + { + MovHighByte(&PlayField16[si], bl); + subCleanUpForInfotronsAbove(si - 1); + } + else if (bl < 0x38) + { + MovHighByte(&PlayField16[si], bl); + } + else + { + PlayField16[si] = 0x7004; // go into intermediate state + } + + return subAnimateInfotrons; + +loc_g_1444: // infotron falls straight down + bl = bl + 1; + if (bl < 0x42) + { + MovHighByte(&PlayField16[si], bl); + } + else if (PlayField16[si + FieldWidth] != 0) + { + bl = bl - 1; // stay waiting + MovHighByte(&PlayField16[si], bl); + } + else + { + PlayField16[si] = 0xFFFF; + si = si + FieldWidth; // 1 field down + PlayField16[si] = 0x1004; // go falling + } + + return subAnimateInfotrons; + +loc_g_1472: // infotron rolls left + // To Do: draw infotron rolling to left + // according to position in (bl And &H0F) + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + dx = (bl & 0xF) + 1; + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X - (TwoPixels * dx), Y, aniInfotronRollLeft[dx - 1]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bl = HighByte(PlayField16[si]) + 1; // retrieve and increment sequence# + if (bl < 0x52) + { + MovHighByte(&PlayField16[si], bl); + return subAnimateInfotrons; + } + + if (PlayField16[si + FieldWidth - 1] != 0) + goto loc_g_14D9; + + if (PlayField16[si - 1] != 0) + { + if (PlayField16[si - 1] != 0x8888) + goto loc_g_14D9; + } + + PlayField16[si] = 0xFFFF; + si = si - 1; // 1 field left + PlayField16[si] = 0x2204; + PlayField16[si + FieldWidth] = 0x9999; + return subAnimateInfotrons; + +loc_g_14D9: // stay waiting + bl = bl - 1; + MovHighByte(&PlayField16[si], bl); + return subAnimateInfotrons; + +loc_g_14E0: // infotron rolls right + // To Do: draw infotron rolling to right + // according to position in (bl And &H07) + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + dx = (bl & 0x7) + 1; + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X + (TwoPixels * dx), Y, aniInfotronRollRight[dx - 1]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bl = HighByte(PlayField16[si]) + 1; + if (bl < 0x62) + { + MovHighByte(&PlayField16[si], bl); + return subAnimateInfotrons; + } + + if (PlayField16[si + FieldWidth + 1] != 0) + goto loc_g_1547; + + if (PlayField16[si + 1] != 0) + { + if (PlayField16[si + 1] != 0x8888) + goto loc_g_1547; + } + + PlayField16[si] = 0xFFFF; + si = si + 1; + PlayField16[si] = 0x3204; + PlayField16[si + FieldWidth] = 0x9999; + return subAnimateInfotrons; + +loc_g_1547: // stay waiting + bl = bl - 1; + MovHighByte(&PlayField16[si], bl); + return subAnimateInfotrons; + +loc_g_154E: // intermediate state + ax = PlayField16[si + FieldWidth]; + if (ax == 0 || ax == 0x9999) + { + PlayField16[si] = 0xFFFF; + si = si + FieldWidth; // 1 field down + PlayField16[si] = 0x1004; // start falling down + goto loc_g_1242; + } + + return subAnimateInfotrons; +} // subAnimateInfotrons + +int subCleanUpForInfotronsAbove(int si) +{ + int subCleanUpForInfotronsAbove; + + int ax; + + if (LowByte(PlayField16[si]) != fiExplosion) + PlayField16[si] = 0; + + if (PlayField16[si - FieldWidth] != 0) + { + if (PlayField16[si - FieldWidth] != 0x9999) + return subCleanUpForInfotronsAbove; + + if (LowByte(PlayField16[si - 2 * FieldWidth]) != fiZonk) + return subCleanUpForInfotronsAbove; + } + + if (PlayField16[si - FieldWidth - 1] == fiInfotron) + goto loc_g_16FE; + +loc_g_16F6: + if (PlayField16[si - FieldWidth + 1] == fiInfotron) + goto loc_g_1722; + + return subCleanUpForInfotronsAbove; + +loc_g_16FE: + ax = PlayField16[si - 1]; + if (ax == fiZonk || ax == fiInfotron || ax == fiRAM) + { + PlayField16[si - FieldWidth - 1] = 0x6004; + PlayField16[si - FieldWidth] = 0x8888; + return subCleanUpForInfotronsAbove; + } + + goto loc_g_16F6; + +loc_g_1722: + ax = PlayField16[si + 1]; + if (ax == fiZonk || ax == fiInfotron || ax == fiRAM) + { + PlayField16[si - FieldWidth + 1] = 0x5004; + PlayField16[si - FieldWidth] = 0x8888; + } + + return subCleanUpForInfotronsAbove; +} // subCleanUpForInfotronsAbove + diff --git a/src/game_sp/Infotrons.h b/src/game_sp/Infotrons.h new file mode 100644 index 00000000..7bce7599 --- /dev/null +++ b/src/game_sp/Infotrons.h @@ -0,0 +1,18 @@ +// ---------------------------------------------------------------------------- +// Infotrons.h +// ---------------------------------------------------------------------------- + +#ifndef INFOTRONS_H +#define INFOTRONS_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern int subAnimateInfotrons(int si); +extern int subCleanUpForInfotronsAbove(int si); + +#endif /* INFOTRONS_H */ diff --git a/src/game_sp/InitGameConditions.c b/src/game_sp/InitGameConditions.c new file mode 100644 index 00000000..f1c0f2e1 --- /dev/null +++ b/src/game_sp/InitGameConditions.c @@ -0,0 +1,370 @@ +// ---------------------------------------------------------------------------- +// InitGameConditions.c +// ---------------------------------------------------------------------------- + +#include "InitGameConditions.h" + +static char *VB_Name = "modInitGameConditions"; +// --- Option Explicit + +// ========================================================================== +// SUBROUTINE +// Init game conditions (variables) +// ========================================================================== + +int subInitGameConditions() +{ + int subInitGameConditions; + + bCapturePane = False; + + MurphyVar0DAC = MurphyYPos; + MurphyVar0DAE = MurphyXPos; + MurphyVarFaceLeft = 0; + KillMurphyFlag = 0; // no "kill Murphy" + ExitToMenuFlag = 0; + LeadOutCounter = 0; // quit flag: lead-out counter + RedDiskCount = 0; // Red disk counter + ShowRedDiskCounter = 0; // show-red-disk time-out + + YawnSleepCounter = 0; // Wake up sleeping Murphy + + data_h_0DA7 = 0xFF; + data_h_0DA8 = 0xFF; + data_h_0DA9 = 0xFF; + data_h_0D9E = 1; + data_h_0D9F = 0; + data_h_0DA0 = 0; + data_h_0DA1 = 0; + data_h_0DA2 = 0; + data_h_0DA4 = 0; + data_h_0DA5 = 0; + data_h_0DA6 = 0; + + ExplosionShake = 0; // Force explosion flag off + + TerminalMaxCycles = 0x7F; + YellowDisksExploded = 0; + + TimerVar = 0; + // ShowPanel = 1 ' Force Panel on + // MainForm.PanelVisible = True; + EnterRepeatCounter = 0; // restart Enter repeat counter + SnikSnaksElectronsFrozen = 0; // Snik-Snaks and Electr. move! + + SplitMoveFlag = 0; // Reset Split-through-ports + RedDiskReleasePhase = 0; // (re-)enable red disk release + RedDiskReleaseMurphyPos = 0; // Red disk was released here + + + return subInitGameConditions; +} // subInitGameConditions + + +// ========================================================================== +// SUBROUTINE +// Locate Murphy and init location. +// ========================================================================== + +int InitMurphyPos() +{ + int InitMurphyPos; + + int si; + + for (si = 0; si <= LevelMax - 1; si++) + { + if (PlayField16[si] == fiMurphy) + break; + } + + InitMurphyPosB(si); + MurphyPosIndex = si; + + return InitMurphyPos; +} // InitMurphyPos + +int InitMurphyPosB(int si) +{ + int InitMurphyPosB; + + MurphyYPos = GetStretchY(si) / Stretch; + MurphyXPos = GetStretchX(si) / Stretch; + + MurphyScreenXPos = GetStretchX(si); // Murphy's screen x-position + MurphyScreenYPos = GetStretchY(si); // Murphy's screen y-position + + // To Do: draw Murphy in location ax + StretchedSprites.BltEx(MurphyScreenXPos, MurphyScreenYPos, fiMurphy); + + MurphyScreenXPos = MurphyScreenXPos / Stretch; + MurphyScreenYPos = MurphyScreenYPos / Stretch; + + subCalculateScreenScrollPos(); // calculate screen start addrs + if (AutoScrollFlag) + { + if (bPlaying) + { + SoftScrollTo(ScreenScrollXPos, ScreenScrollYPos, 1000, 25); + } + else + { + ScrollTo(ScreenScrollXPos, ScreenScrollYPos); + } + } + + return InitMurphyPosB; +} // InitMurphyPosB + +// ========================================================================== +// SUBROUTINE +// Convert to easy symbols and reset Infotron count If not ThenVer62 +// ========================================================================== + +int subConvertToEasySymbols() +{ + int subConvertToEasySymbols; + + int ax, bx, cx, dx, di, X, Y, i; + int ah, bh, ch, dh, al, bl, cl, dl, ZF; + + bx = 0; + dx = 0; + cx = LevelMax + 1; + i = 0; + +loc_g_26C9: + ax = PlayField16[i]; + al = LowByte(ax); + if (al == 0xF1) // converted explosion? + { + MovLowByte(&PlayField16[i], 0x1F); // restore explosions + goto loc_g_2778; + } + + if (LowByte(GameBusyFlag) != 1) // free screen write? + { + if (ax == fiInfotron) // Infotron? -> yes--count! + goto loc_g_2704; + + if (ax == fiSnikSnak) // Snik Snak? -> yes--rearrange + goto loc_g_2713; + + if (ax == fiElectron) // Electron? -> yes--rearrange + goto loc_g_2741; + } + + // test for fancy RAM Chips: + if (ax == fiRAMLeft || ax == fiRAMRight) + goto loc_g_2707; + + if (ax == fiRAMTop || ax == fiRAMBottom) + goto loc_g_2707; + + if (ax < fiHWFirst) // All but deco hardware? + goto loc_g_26F8; + + if (ax < fiRAMTop) // Decorative hardware? + goto loc_g_270D; + +loc_g_26F8: + if (ax < fiSpPortRight) // Gravity change ports only? + goto loc_g_2778; + + if (ax < fiSnikSnak) // Gravity change port! 'loc_g_2702: + goto loc_g_276F; + + goto loc_g_2778; + +loc_g_2704: // INFOTRON + dx = dx + 1; // Count Infotrons + goto loc_g_2778; + +loc_g_2707: // DECO RAM CHIPS + PlayField16[i] = fiRAM; // Convert to standard RAM chip + goto loc_g_2778; + +loc_g_270D: // DECO HARDWARE + PlayField16[i] = fiHardWare; // Convert to standard hardware + goto loc_g_2778; + +loc_g_2713: // SNIK-SNAK + if (PlayField16[i - 1] != 0) // 1 field left empty? -> no--try up + goto loc_g_271F; + + MovHighByte(&PlayField16[i], 1); // turn left, step = NorthWest + goto loc_g_2778; + +loc_g_271F: + if (PlayField16[i - FieldWidth] != 0) // 1 field up empty? -> no--try right + goto loc_g_2730; + + PlayField16[i - FieldWidth] = 0x1011; // SnikSnak accessing from below, step = 0 + PlayField16[i] = 0xFFFF; + goto loc_g_2778; + +loc_g_2730: + if (PlayField16[i + 1] != 0) // 1 field right empty? -> point up + goto loc_g_2778; + + PlayField16[i + 1] = 0x2811; // SnikSnak accessing from left, step = 0 + PlayField16[i] = 0xFFFF; + goto loc_g_2778; + +loc_g_2741: // ELECTRON + if (PlayField16[i - 1] != 0) // 1 field left empty? -> no--try up + goto loc_g_274D; + + MovHighByte(&PlayField16[i], 1); + goto loc_g_2778; + +loc_g_274D: + if (PlayField16[i - FieldWidth] != 0) // 1 field up empty? -> no--try right + goto loc_g_275E; + + PlayField16[i - FieldWidth] = 0x1018; // 1 field up + PlayField16[i] = 0xFFFF; + goto loc_g_2778; + +loc_g_275E: + if (PlayField16[i + 1] != 0) // 1 field right empty? -> no--point down + goto loc_g_2778; + + PlayField16[i + 1] = 0x2818; + PlayField16[i] = 0xFFFF; + goto loc_g_2778; + +loc_g_276F: // GRAVITY CHANGING PORTS + PlayField16[i] = (ax - 4) | 0x100; // Convert to standard ports + goto loc_g_2778; + +loc_g_2778: + i = i + 1; // Next field + bx = bx + 1; + cx = cx - 1; + if (0 < cx) // Until all done 'loc_g_2782: + goto loc_g_26C9; + + subConvertToEasySymbols = dx; // return InfotronCount + + return subConvertToEasySymbols; +} // subConvertToEasySymbols + +// ========================================================================== +// SUBROUTINE +// Reset Infotron count. Call immediately after subConvertToEasySymbols +// ========================================================================== + +int ResetInfotronsNeeded(int dx) +{ + int ResetInfotronsNeeded; + + if (LInfo.InfotronsNeeded != 0) // Jump If equal (autodetect) + { + dx = LInfo.InfotronsNeeded; + } // loc_g_278D: + + InfotronsNeeded = LowByte(dx); // Remaining Infotrons needed + TotalInfotronsNeeded = InfotronsNeeded; // Number of Infotrons needed + subDisplayInfotronsNeeded(); + + return ResetInfotronsNeeded; +} // ResetInfotronsNeeded + + +// ========================================================================== +// SUBROUTINE +// Fetch and initialize a level +// ========================================================================== + +int subFetchAndInitLevelB() +{ + int subFetchAndInitLevelB; + + boolean UpdatePlayTime; + + MovLowByte(&data_SPtorunavail, 0); // no SP file + data_scr_demo = 0; + UpdatePlayTime = (0 == demo_stopped ? True : True); + demo_stopped = 0; + subFetchAndInitLevelA(UpdatePlayTime); + + return subFetchAndInitLevelB; +} // subFetchAndInitLevelb + +int subFetchAndInitLevelA(boolean UpdatePlayTime) +{ + int subFetchAndInitLevelA; + + if (UpdatePlayTime && (0 == demo_stopped)) + { + subUpdatePlayingTime(); // update playing time + } + + D_ModeFlag = 0; // 1=debug D pressed (CPU use) + if (0 != demo_stopped) // 1=demo, 0=game + DemoFlag = 1; + + GameBusyFlag = 0; // restore scissors too + subFetchAndInitLevel(); // Fetch and initialize a level + GameBusyFlag = 1; // no free screen write + if (1 <= demo_stopped) + { + if (1 == demo_stopped) + { + DemoFlag = 0; // 1=demo, 0=game + demo_stopped = demo_stopped + 1; + } + else + { + DemoFlag = 0; // 1=demo, 0=game + } + } + + DemoKeyCode = 0; // delete last demo key! + if (DemoFlag != 0) // don't allow during game! only in Demo + { + DemoOffset = DemoPointer; // init demo pointer + DemoKeyRepeatCounter = 1; + subGetNextDemoKey(); // get next demo byte + } + + return subFetchAndInitLevelA; +} // subFetchAndInitLevela + +int subFetchAndInitLevel() +{ + int subFetchAndInitLevel; + + int InfoCountInLevel; + + Trace("modInitGameConditions", "--> subFetchAndInitLevel"); + Trace("modInitGameConditions", "Call ReadLevel"); + ReadLevel(); // Read LEVELS.DAT + Trace("modInitGameConditions", "ReadLevel return subFetchAndInitLeveled"); + + if (RecordDemoFlag == 1) + { + RecDemoRandomSeed = RandomSeed; + // Debug.Print "FetchRec: " & Hex(RandomSeed) + } + + // If DemoFlag = 1 Then + // Debug.Print "FetchPlay: " & Hex(RandomSeed) + // End If + GameBusyFlag = -GameBusyFlag; // make <>1 + Trace("modInitGameConditions", "subConvertToEasySymbols"); + InfoCountInLevel = subConvertToEasySymbols(); // Convert to easy symbols + GameBusyFlag = -GameBusyFlag; // restore + Trace("modInitGameConditions", "subDisplayLevel"); + subDisplayLevel(); // Paint (Init) game field + subDisplayPanel(); // Paint (Init) Panel + ResetInfotronsNeeded(InfoCountInLevel); // and reset Infotron count + Data_SubRstFlg = 1; + Trace("modInitGameConditions", "subInitGameConditions"); + subInitGameConditions(); // Init game conditions (vars) + InitMurphyPos(); // Locate Murphy + screen pos + Trace("modInitGameConditions", "<-- subFetchAndInitLevel"); + + return subFetchAndInitLevel; +} // subFetchAndInitLevel diff --git a/src/game_sp/InitGameConditions.h b/src/game_sp/InitGameConditions.h new file mode 100644 index 00000000..6c3de557 --- /dev/null +++ b/src/game_sp/InitGameConditions.h @@ -0,0 +1,24 @@ +// ---------------------------------------------------------------------------- +// InitGameConditions.h +// ---------------------------------------------------------------------------- + +#ifndef INITGAMECONDITIONS_H +#define INITGAMECONDITIONS_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern int InitMurphyPos(); +extern int InitMurphyPosB(int si); +extern int ResetInfotronsNeeded(int dx); +extern int subConvertToEasySymbols(); +extern int subFetchAndInitLevel(); +extern int subFetchAndInitLevelA(boolean UpdatePlayTime); +extern int subFetchAndInitLevelB(); +extern int subInitGameConditions(); + +#endif /* INITGAMECONDITIONS_H */ diff --git a/src/game_sp/Input.c b/src/game_sp/Input.c new file mode 100644 index 00000000..24438057 --- /dev/null +++ b/src/game_sp/Input.c @@ -0,0 +1,155 @@ +// ---------------------------------------------------------------------------- +// Input.c +// ---------------------------------------------------------------------------- + +#include "Input.h" + +static char *VB_Name = "modInput"; +// --- Option Explicit + +boolean KeyState[255 + 1]; +DemoBufferObject DemoBuffer; + +// +// Public KeyFlagSpace As Boolean +// Public KeyFlagUp As Boolean +// Public KeyFlagLeft As Boolean +// Public KeyFlagDown As Boolean +// Public KeyFlagRight As Boolean +// Public KeyFlagEnter As Boolean +// Public KeyFlagESC As Boolean +// Public KeyFlagR As Boolean +// Public KeyFlagRShift As Boolean + +int KeyScanCode7; + +void subCheckJoystick() +{ +} + +int subCheckRightMouseButton() +{ + int subCheckRightMouseButton; + + // return button state + + return subCheckRightMouseButton; +} + +int subProcessKeyboardInput() +{ + int subProcessKeyboardInput; + + int LastKey; + + // On Error GoTo NoKeyboardAccessEH + // Call DKeyboard.Acquire + // On Error GoTo 0 + // Call DKeyboard.GetDeviceStateKeyboard(KeyState) + // With KeyState + if (DemoFlag != 0) + { + subGetNextDemoKey(); + if (ExitToMenuFlag != 0) + return subProcessKeyboardInput; + + } + else + { + if (KeyState[vbKeySpace]) + { + if (KeyState[vbKeyUp]) + { + DemoKeyCode = keySpaceUp; + } + else if (KeyState[vbKeyLeft]) + { + DemoKeyCode = keySpaceLeft; + } + else if (KeyState[vbKeyDown]) + { + DemoKeyCode = keySpaceDown; + } + else if (KeyState[vbKeyRight]) + { + DemoKeyCode = keySpaceRight; + } + else + { + DemoKeyCode = keySpace; + } + + } + else + { + if (KeyState[vbKeyUp]) + { + DemoKeyCode = keyUp; + } + else if (KeyState[vbKeyLeft]) + { + DemoKeyCode = keyLeft; + } + else if (KeyState[vbKeyDown]) + { + DemoKeyCode = keyDown; + } + else if (KeyState[vbKeyRight]) + { + DemoKeyCode = keyRight; + } + else + { + DemoKeyCode = keyNone; + } + } + } + + // demo recording + if (RecordDemoFlag == 1) + DemoBuffer.AddDemoKey(DemoKeyCode); + + if (DemoKeyCode != LastKey && ! NoDisplayFlag) + { +#if 0 + MainForm.ShowKey(DemoKeyCode); +#endif + LastKey = DemoKeyCode; + } + + if (KeyState[vbKeyEscape]) + { + if (BlockingSpeed) + { + // Call MainForm.menSpeed_Click(4) + } + else + { + KillMurphyFlag = 1; + // ExplodeFieldSP MurphyPosIndex + // LeadOutCounter = &H20 + } + } + + if (KeyState[vbKeyR]) + { + subFetchAndInitLevelB(); + } + + if (KeyState[vbKeyShift]) + subDisplayRedDiskCount(); + +#if 0 + if (KeyState[vbKeyReturn]) + MainForm.PanelVisible = (ShowPanel == 0); +#endif + + // End With + // Call DKeyboard.Unacquire + return subProcessKeyboardInput; + +NoKeyboardAccessEH: + Debug.Print("! Keyboard access"); + + return subProcessKeyboardInput; +} diff --git a/src/game_sp/Input.h b/src/game_sp/Input.h new file mode 100644 index 00000000..2762b305 --- /dev/null +++ b/src/game_sp/Input.h @@ -0,0 +1,23 @@ +// ---------------------------------------------------------------------------- +// Input.h +// ---------------------------------------------------------------------------- + +#ifndef INPUT_H +#define INPUT_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern void subCheckJoystick(); +extern int subCheckRightMouseButton(); +extern int subProcessKeyboardInput(); + +extern DemoBufferObject DemoBuffer; +extern boolean KeyState[255 + 1]; +extern int KeyScanCode7; + +#endif /* INPUT_H */ diff --git a/src/game_sp/LevelSetPreviewForm.c b/src/game_sp/LevelSetPreviewForm.c new file mode 100644 index 00000000..b5d0b599 --- /dev/null +++ b/src/game_sp/LevelSetPreviewForm.c @@ -0,0 +1,41 @@ +// ---------------------------------------------------------------------------- +// LevelSetPreviewForm.c +// ---------------------------------------------------------------------------- + +#include "LevelSetPreviewForm.h" + +// --- VERSION 5.00 +// --- Begin VB.Form LevelSetPreviewForm +// --- BorderStyle = 4 'Fixed ToolWindow // Fixed ToolWindow +// --- Caption = "Level Set Preview" +// --- ClientHeight = 10860 +// --- ClientLeft = 4890 +// --- ClientTop = 2760 +// --- ClientWidth = 6585 +// --- LinkTopic = "Form1" +// --- MaxButton = 0 'False // False +// --- MinButton = 0 'False // False +// --- ScaleHeight = 724 +// --- ScaleMode = 3 'Pixel // Pixel +// --- ScaleWidth = 439 +// --- ShowInTaskbar = 0 'False // False +// --- Begin VB.PictureBox pic +// --- BackColor = &H00000000& +// --- Height = 2475 +// --- Left = 480 +// --- ScaleHeight = 161 +// --- ScaleMode = 3 'Pixel // Pixel +// --- ScaleWidth = 349 +// --- TabIndex = 0 +// --- Top = 360 +// --- Width = 5295 +// --- End +// --- End + +static char *VB_Name = "LevelSetPreviewForm"; +static boolean VB_GlobalNameSpace = False; +static boolean VB_Creatable = False; +static boolean VB_PredeclaredId = True; +static boolean VB_Exposed = False; +// --- Option Explicit + diff --git a/src/game_sp/LevelSetPreviewForm.h b/src/game_sp/LevelSetPreviewForm.h new file mode 100644 index 00000000..0cc8bc75 --- /dev/null +++ b/src/game_sp/LevelSetPreviewForm.h @@ -0,0 +1,15 @@ +// ---------------------------------------------------------------------------- +// LevelSetPreviewForm.h +// ---------------------------------------------------------------------------- + +#ifndef LEVELSETPREVIEWFORM_H +#define LEVELSETPREVIEWFORM_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +#endif /* LEVELSETPREVIEWFORM_H */ diff --git a/src/game_sp/MainForm.c b/src/game_sp/MainForm.c new file mode 100644 index 00000000..f2fe86fd --- /dev/null +++ b/src/game_sp/MainForm.c @@ -0,0 +1,3362 @@ +// ---------------------------------------------------------------------------- +// MainForm.c +// ---------------------------------------------------------------------------- + +#include "MainForm.h" + +#if 1 + +static void DrawFrame(int Delta); + +#else + +static void CleanTempDir(char *TmpDir); +static void CountDown(long HalfSeconds, int bDisplayBar); +static void DrawFrame(int Delta); +static void DrawPauseLayer(long Layer); +static void FillFileList(char *Path); +static void FillLevelList(char *Path, int LevelIndex); +static void FocusTim_Timer(); +static void Form_KeyDown(int KeyCode, int Shift); +static void Form_KeyUp(int KeyCode, int Shift); +static void Form_Paint(); +static int GetFileNameToSave(); +static long GetHwndFromTempFileName(char *TmpFile); +static char * GetMyTempFileName(); +static void GetSettings(); +static char * GetSpeedDescriptionFPS(currency FrameDelayUS); +static int GetSpeedIndex(long DelayUS); +static char * GetValidTempPath(); +static long Get_LastOpenFilter(); +static long Get_LastSaveFilter(); +static int InitSpeeds(); +static boolean InstanceStillRunning(char *TmpFile); +static void Let_LastOpenFilter(long NewVal); +static void Let_LastSaveFilter(long NewVal); +static void LoadKeyIndicators(); +static void LoadMenus(); +static void PanelTim_Timer(); +static void ReStretch(float NewStretch); +static void RestoreFrame(); +static boolean SaveAs(); +static void SaveSettings(); +static void SetScrollEdges(); +static void UpdateDeltaT(); +static void cmbFile_Click(); +static void cmbFile_KeyDown(int KeyCode, int Shift); +static void cmbFile_KeyUp(int KeyCode, int Shift); +static void cmbLevel_Click(); +static void cmbLevel_KeyUp(int KeyCode, int Shift); +static void cmblevel_KeyDown(int KeyCode, int Shift); +static void cmdPause_Click(); +static void cmdPause_MouseUp(int Button, int Shift, float X, float Y); +static void cmdPlayAll_Click(); +static void cmdPlayAll_MouseUp(int Button, int Shift, float X, float Y); +static void cmdPlayDemo_Click(); +static void cmdPlayDemo_MouseUp(int Button, int Shift, float X, float Y); +static void cmdPlay_Click(); +static void cmdPlay_MouseUp(int Button, int Shift, float X, float Y); +static void cmdRecordDemo_Click(); +static void cmdRecordDemo_MouseUp(int Button, int Shift, float X, float Y); +static void cmdStop_Click(); +static void cmdStop_MouseUp(int Button, int Shift, float X, float Y); +static void fpsTim_Timer(); +static void menAbout_Click(); +static void menAutoScroll_Click(); +static void menBorder_Click(); +static void menCopy_Click(); +static void menEnOff_Click(); +static void menEnOn_Click(); +static void menExit_Click(); +static void menFaster_Click(); +static void menGravOff_Click(); +static void menGravOn_Click(); +static void menNewStd_Click(); +static void menNew_Click(); +static void menOpen_Click(); +static void menOptions_Click(); +static void menPanel_Click(); +static void menPaste_Click(); +static void menPause_Click(); +static void menPlayAll_Click(); +static void menPlayDemo_Click(); +static void menPlay_Click(); +static void menReRecordDemo_Click(); +static void menRec_Click(); +static void menRemSP_Click(); +static void menRestoreBorder_Click(); +static void menSaveAs_Click(); +static void menSave_Click(); +static void menSelectAll_Click(); +static void menShowLInfo_Click(); +static void menSlower_Click(); +static void menSoundFX_Click(); +static void menStretch_Click(int Index); +static void menToolTips_Click(); +static void menTrim_Click(); +static void menZonkOff_Click(); +static void menZonkOn_Click(); +static void picKeys_MouseUp(int Button, int Shift, float X, float Y); +static void picMenu_Click(); +static void picPane_KeyDown(int KeyCode, int Shift); +static void picPane_KeyUp(int KeyCode, int Shift); +static void picPane_MouseDown(int Button, int Shift, float X, float Y); +static void picPane_MouseMove(int Button, int Shift, float X, float Y); +static void picPane_MouseUp(int Button, int Shift, float X, float Y); +static void picPane_Paint(); +static void picViewPort_MouseUp(int Button, int Shift, float X, float Y); +static void picViewPort_Paint(); +static void picViewPort_Resize(); + +#endif + +void DrawField(int X, int Y); +void DrawFieldAnimated(int X, int Y); +void DrawFieldNoAnimated(int X, int Y); + +// --- VERSION 5.00 +// --- Object = "{F9043C88-F6F2-101A-A3C9-08002B2F49FB}#1.2#0"; "COMDLG32.OCX" +// --- Begin VB.Form MainForm +// --- AutoRedraw = -1 'True // True +// --- Caption = "MegaPlex" +// --- ClientHeight = 5850 +// --- ClientLeft = 2580 +// --- ClientTop = 2205 +// --- ClientWidth = 9285 +// --- Icon = "MainForm.frx":0000 +// --- LinkTopic = "Form1" +// --- ScaleHeight = 390 +// --- ScaleMode = 3 'Pixel // Pixel +// --- ScaleWidth = 619 +// --- Begin VB.Timer fpsTim +// --- Enabled = 0 'False // False +// --- Interval = 200 +// --- Left = 1380 +// --- Top = 2940 +// --- End +// --- Begin VB.Timer FocusTim +// --- Interval = 50 +// --- Left = 1920 +// --- Top = 2940 +// --- End +// --- Begin MSComDlg.CommonDialog cmDlg +// --- Left = 240 +// --- Top = 2880 +// --- _ExtentX = 847 +// --- _ExtentY = 847 +// --- _Version = 393216 +// --- CancelError = -1 'True // True +// --- End +// --- Begin VB.Timer PanelTim +// --- Enabled = 0 'False // False +// --- Interval = 5 +// --- Left = 840 +// --- Top = 2940 +// --- End +// --- Begin VB.Frame Panel +// --- Height = 1140 +// --- Left = 180 +// --- TabIndex = 2 +// --- Top = 3540 +// --- Width = 9015 +// --- Begin VB.CommandButton cmdPlay +// --- DisabledPicture = "MainForm.frx":0442 +// --- DownPicture = "MainForm.frx":058C +// --- Height = 345 +// --- Left = 5820 +// --- Picture = "MainForm.frx":06D6 +// --- Style = 1 'Graphical // Graphical +// --- TabIndex = 16 +// --- TabStop = 0 'False // False +// --- Top = 240 +// --- Width = 495 +// --- End +// --- Begin VB.CommandButton cmdStop +// --- DisabledPicture = "MainForm.frx":0820 +// --- DownPicture = "MainForm.frx":096A +// --- Enabled = 0 'False // False +// --- Height = 345 +// --- Left = 7020 +// --- Picture = "MainForm.frx":0AB4 +// --- Style = 1 'Graphical // Graphical +// --- TabIndex = 15 +// --- TabStop = 0 'False // False +// --- Top = 240 +// --- Width = 495 +// --- End +// --- Begin VB.CommandButton cmdPlayDemo +// --- DisabledPicture = "MainForm.frx":0BFE +// --- DownPicture = "MainForm.frx":0D48 +// --- Enabled = 0 'False // False +// --- Height = 345 +// --- Left = 7740 +// --- Picture = "MainForm.frx":0E92 +// --- Style = 1 'Graphical // Graphical +// --- TabIndex = 14 +// --- TabStop = 0 'False // False +// --- Top = 240 +// --- Width = 495 +// --- End +// --- Begin VB.CommandButton cmdPause +// --- DisabledPicture = "MainForm.frx":0FDC +// --- DownPicture = "MainForm.frx":1126 +// --- Enabled = 0 'False // False +// --- Height = 345 +// --- Left = 6420 +// --- Picture = "MainForm.frx":1270 +// --- Style = 1 'Graphical // Graphical +// --- TabIndex = 13 +// --- TabStop = 0 'False // False +// --- Top = 240 +// --- Width = 495 +// --- End +// --- Begin VB.CommandButton cmdRecordDemo +// --- DisabledPicture = "MainForm.frx":13BA +// --- DownPicture = "MainForm.frx":1504 +// --- Height = 345 +// --- Left = 8340 +// --- Picture = "MainForm.frx":164E +// --- Style = 1 'Graphical // Graphical +// --- TabIndex = 12 +// --- TabStop = 0 'False // False +// --- Top = 240 +// --- Width = 495 +// --- End +// --- Begin VB.ComboBox cmbFile +// --- BackColor = &H00000000& +// --- BeginProperty Font +// --- Name = "Fixedsys" +// --- Size = 9 +// --- Charset = 0 +// --- Weight = 400 +// --- Underline = 0 'False // False +// --- Italic = 0 'False // False +// --- Strikethrough = 0 'False // False +// --- EndProperty +// --- ForeColor = &H00FF8080& +// --- Height = 345 +// --- Left = 120 +// --- Sorted = -1 'True // True +// --- Style = 2 'Dropdown List // Dropdown List +// --- TabIndex = 9 +// --- Top = 240 +// --- Width = 3015 +// --- End +// --- Begin VB.ComboBox cmbLevel +// --- BackColor = &H00000000& +// --- BeginProperty Font +// --- Name = "Fixedsys" +// --- Size = 9 +// --- Charset = 0 +// --- Weight = 400 +// --- Underline = 0 'False // False +// --- Italic = 0 'False // False +// --- Strikethrough = 0 'False // False +// --- EndProperty +// --- ForeColor = &H00FF8080& +// --- Height = 345 +// --- Left = 840 +// --- Sorted = -1 'True // True +// --- Style = 2 'Dropdown List // Dropdown List +// --- TabIndex = 5 +// --- Top = 660 +// --- Width = 4035 +// --- End +// --- Begin VB.PictureBox picKeys +// --- BackColor = &H00008080& +// --- BorderStyle = 0 'None // None +// --- Height = 330 +// --- Left = 5400 +// --- ScaleHeight = 22 +// --- ScaleMode = 3 'Pixel // Pixel +// --- ScaleWidth = 22 +// --- TabIndex = 4 +// --- TabStop = 0 'False // False +// --- Top = 240 +// --- Width = 330 +// --- Begin VB.Shape shpKey +// --- FillColor = &H00008000& +// --- FillStyle = 0 'Solid // Solid +// --- Height = 120 +// --- Index = 1 +// --- Left = 0 +// --- Shape = 5 'Rounded Square // Rounded Square +// --- Top = 0 +// --- Width = 120 +// --- End +// --- End +// --- Begin VB.CommandButton cmdPlayAll +// --- Caption = "Play All Demos" +// --- Enabled = 0 'False // False +// --- Height = 345 +// --- Left = 7380 +// --- TabIndex = 3 +// --- TabStop = 0 'False // False +// --- Top = 960 +// --- Visible = 0 'False // False +// --- Width = 1395 +// --- End +// --- Begin VB.Shape shpProgress +// --- BackColor = &H00800000& +// --- BackStyle = 1 'Opaque // Opaque +// --- Height = 75 +// --- Left = 120 +// --- Top = 1020 +// --- Visible = 0 'False // False +// --- Width = 7515 +// --- End +// --- Begin VB.Label lblStatus +// --- Alignment = 2 'Center // Center +// --- BorderStyle = 1 'Fixed Single // Fixed Single +// --- Caption = "MegaPlex" +// --- BeginProperty Font +// --- Name = "Fixedsys" +// --- Size = 9 +// --- Charset = 0 +// --- Weight = 400 +// --- Underline = 0 'False // False +// --- Italic = 0 'False // False +// --- Strikethrough = 0 'False // False +// --- EndProperty +// --- Height = 345 +// --- Left = 3240 +// --- TabIndex = 11 +// --- Top = 240 +// --- Width = 2055 +// --- End +// --- Begin VB.Image Image2 +// --- Height = 240 +// --- Left = 6780 +// --- Picture = "MainForm.frx":1BD8 +// --- Top = 720 +// --- Width = 240 +// --- End +// --- Begin VB.Image Image1 +// --- Height = 240 +// --- Left = 5880 +// --- Picture = "MainForm.frx":1D22 +// --- Top = 720 +// --- Width = 240 +// --- End +// --- Begin VB.Label lblFps +// --- Alignment = 2 'Center // Center +// --- BackColor = &H00000000& +// --- BorderStyle = 1 'Fixed Single // Fixed Single +// --- BeginProperty Font +// --- Name = "Fixedsys" +// --- Size = 9 +// --- Charset = 0 +// --- Weight = 400 +// --- Underline = 0 'False // False +// --- Italic = 0 'False // False +// --- Strikethrough = 0 'False // False +// --- EndProperty +// --- ForeColor = &H0000C0C0& +// --- Height = 345 +// --- Left = 120 +// --- TabIndex = 10 +// --- Top = 660 +// --- Width = 615 +// --- End +// --- Begin VB.Label lblInfoCount +// --- Alignment = 2 'Center // Center +// --- BackColor = &H00000000& +// --- BorderStyle = 1 'Fixed Single // Fixed Single +// --- BeginProperty Font +// --- Name = "Fixedsys" +// --- Size = 9 +// --- Charset = 0 +// --- Weight = 400 +// --- Underline = 0 'False // False +// --- Italic = 0 'False // False +// --- Strikethrough = 0 'False // False +// --- EndProperty +// --- ForeColor = &H00FF8080& +// --- Height = 345 +// --- Left = 5040 +// --- TabIndex = 8 +// --- Top = 660 +// --- Width = 795 +// --- End +// --- Begin VB.Label lblRedDiskCount +// --- Alignment = 2 'Center // Center +// --- BackColor = &H00000000& +// --- BorderStyle = 1 'Fixed Single // Fixed Single +// --- BeginProperty Font +// --- Name = "Fixedsys" +// --- Size = 9 +// --- Charset = 0 +// --- Weight = 400 +// --- Underline = 0 'False // False +// --- Italic = 0 'False // False +// --- Strikethrough = 0 'False // False +// --- EndProperty +// --- ForeColor = &H000000FF& +// --- Height = 345 +// --- Left = 6240 +// --- TabIndex = 7 +// --- Top = 660 +// --- Width = 495 +// --- End +// --- Begin VB.Label lblFrameCount +// --- Alignment = 2 'Center // Center +// --- BorderStyle = 1 'Fixed Single // Fixed Single +// --- Caption = "0" +// --- BeginProperty Font +// --- Name = "Fixedsys" +// --- Size = 9 +// --- Charset = 0 +// --- Weight = 400 +// --- Underline = 0 'False // False +// --- Italic = 0 'False // False +// --- Strikethrough = 0 'False // False +// --- EndProperty +// --- Height = 345 +// --- Left = 7200 +// --- TabIndex = 6 +// --- Top = 660 +// --- Width = 1635 +// --- End +// --- End +// --- Begin VB.PictureBox picViewPort +// --- BorderStyle = 0 'None // None +// --- Height = 2535 +// --- Left = 180 +// --- ScaleHeight = 169 +// --- ScaleMode = 3 'Pixel // Pixel +// --- ScaleWidth = 265 +// --- TabIndex = 0 +// --- TabStop = 0 'False // False +// --- Top = 180 +// --- Width = 3975 +// --- Begin VB.PictureBox picPane +// --- AutoSize = -1 'True // True +// --- BackColor = &H00000000& +// --- BorderStyle = 0 'None // None +// --- DrawWidth = 3 +// --- Height = 1635 +// --- Left = 240 +// --- ScaleHeight = 109 +// --- ScaleMode = 3 'Pixel // Pixel +// --- ScaleWidth = 129 +// --- TabIndex = 1 +// --- Top = 180 +// --- Width = 1935 +// --- End +// --- Begin VB.PictureBox picFrame +// --- Height = 915 +// --- Left = 1320 +// --- ScaleHeight = 57 +// --- ScaleMode = 3 'Pixel // Pixel +// --- ScaleWidth = 81 +// --- TabIndex = 17 +// --- TabStop = 0 'False // False +// --- Top = 1200 +// --- Width = 1275 +// --- End +// --- End +// --- Begin VB.Menu menFile +// --- Caption = "&File" +// --- Begin VB.Menu menNewStd +// --- Caption = "New S&tandard Level" +// --- End +// --- Begin VB.Menu menNew +// --- Caption = "&New Level" +// --- End +// --- Begin VB.Menu menDash5 +// --- Caption = "-" +// --- End +// --- Begin VB.Menu menOpen +// --- Caption = "&Open" +// --- End +// --- Begin VB.Menu menSave +// --- Caption = "&Save" +// --- Shortcut = ^S +// --- End +// --- Begin VB.Menu menSaveAs +// --- Caption = "Save &As ..." +// --- End +// --- Begin VB.Menu menDash4 +// --- Caption = "-" +// --- End +// --- Begin VB.Menu menExit +// --- Caption = "E&xit" +// --- Shortcut = ^Q +// --- End +// --- End +// --- Begin VB.Menu menEditMain +// --- Caption = "&Edit" +// --- Begin VB.Menu menEdit +// --- Caption = "&Edit Level" +// --- End +// --- Begin VB.Menu menDash3 +// --- Caption = "-" +// --- End +// --- Begin VB.Menu menCopy +// --- Caption = "&Copy" +// --- Shortcut = ^C +// --- End +// --- Begin VB.Menu menPaste +// --- Caption = "&Paste" +// --- Shortcut = ^V +// --- End +// --- Begin VB.Menu menTrim +// --- Caption = "&Trim" +// --- Shortcut = ^T +// --- End +// --- Begin VB.Menu menDash8 +// --- Caption = "-" +// --- Index = 1 +// --- End +// --- Begin VB.Menu menSelectAll +// --- Caption = "Select &All" +// --- Shortcut = ^A +// --- End +// --- Begin VB.Menu menDash6 +// --- Caption = "-" +// --- End +// --- Begin VB.Menu menRestoreBorder +// --- Caption = "Restore &border" +// --- Shortcut = ^B +// --- End +// --- Begin VB.Menu menSp +// --- Caption = "Special Port" +// --- Begin VB.Menu menGravOn +// --- Caption = "&Gravity On" +// --- End +// --- Begin VB.Menu menZonkOn +// --- Caption = "Freeze &Zonks On" +// --- End +// --- Begin VB.Menu menEnOn +// --- Caption = "Freeze &Enemies On" +// --- End +// --- Begin VB.Menu menDash7 +// --- Caption = "-" +// --- End +// --- Begin VB.Menu menGravOff +// --- Caption = "Gravity &Off" +// --- End +// --- Begin VB.Menu menZonkOff +// --- Caption = "Freeze Zon&ks Off" +// --- End +// --- Begin VB.Menu menEnOff +// --- Caption = "Freeze E&nemies Off" +// --- End +// --- Begin VB.Menu menDash10 +// --- Caption = "-" +// --- End +// --- Begin VB.Menu menRemSP +// --- Caption = "&Remove (Make Normal Port)" +// --- End +// --- End +// --- End +// --- Begin VB.Menu menView +// --- Caption = "&View" +// --- Begin VB.Menu menZoom +// --- Caption = "&Zoom" +// --- Begin VB.Menu menStretch +// --- Caption = "0.25 : 1" +// --- Index = 1 +// --- End +// --- End +// --- Begin VB.Menu menBorder +// --- Caption = "Show &Border" +// --- Checked = -1 'True // True +// --- End +// --- Begin VB.Menu menPanel +// --- Caption = "Show &Panel" +// --- Checked = -1 'True // True +// --- End +// --- Begin VB.Menu menAutoScroll +// --- Caption = "&Autoscroll" +// --- Checked = -1 'True // True +// --- End +// --- Begin VB.Menu menDash9 +// --- Caption = "-" +// --- End +// --- Begin VB.Menu menShowLInfo +// --- Caption = "Show Level &Info" +// --- End +// --- End +// --- Begin VB.Menu menSound +// --- Caption = "&Sound" +// --- Begin VB.Menu menSoundFX +// --- Caption = "&FX" +// --- End +// --- Begin VB.Menu menMusic +// --- Caption = "&Music" +// --- Enabled = 0 'False // False +// --- End +// --- End +// --- Begin VB.Menu menSpeed +// --- Caption = "Speed" +// --- Begin VB.Menu menSpeedPlay +// --- Caption = "Game play" +// --- Index = 11 +// --- Begin VB.Menu menPlaySpeed +// --- Caption = "1" +// --- Index = 1 +// --- End +// --- End +// --- Begin VB.Menu menSpeedDemo +// --- Caption = "Demo playback" +// --- Begin VB.Menu menDemoSpeed +// --- Caption = "1" +// --- Index = 1 +// --- End +// --- End +// --- Begin VB.Menu menSpeedDash +// --- Caption = "-" +// --- End +// --- Begin VB.Menu menFaster +// --- Caption = "Faster (Pg Up)" +// --- End +// --- Begin VB.Menu menSlower +// --- Caption = "Slower (Pg Down)" +// --- End +// --- End +// --- Begin VB.Menu menRun +// --- Caption = "&Play" +// --- Begin VB.Menu menPlay +// --- Caption = "P&lay Game (Space)" +// --- End +// --- Begin VB.Menu menPause +// --- Caption = "&Pause (P)" +// --- Enabled = 0 'False // False +// --- End +// --- Begin VB.Menu menStop +// --- Caption = "&Stop (Q)" +// --- Enabled = 0 'False // False +// --- End +// --- Begin VB.Menu menDash0 +// --- Caption = "-" +// --- End +// --- Begin VB.Menu menRec +// --- Caption = "&Record Demo (Ctrl+R)" +// --- End +// --- Begin VB.Menu menPlayDemo +// --- Caption = "Play &Demo (Ctrl+Space)" +// --- End +// --- Begin VB.Menu menPlayAll +// --- Caption = "Play &All Demos" +// --- End +// --- End +// --- Begin VB.Menu menOptionsMain +// --- Caption = "&Options" +// --- Begin VB.Menu menOptions +// --- Caption = "&Options ..." +// --- End +// --- End +// --- Begin VB.Menu menHelp +// --- Caption = "Help" +// --- Begin VB.Menu menToolTips +// --- Caption = "Show &ToolTips" +// --- End +// --- Begin VB.Menu menDash1 +// --- Caption = "-" +// --- End +// --- Begin VB.Menu menAbout +// --- Caption = "&About MegaPlex" +// --- End +// --- End +// --- End + +static char *VB_Name = "MainForm"; +static boolean VB_GlobalNameSpace = False; +static boolean VB_Creatable = False; +static boolean VB_PredeclaredId = True; +static boolean VB_Exposed = False; +// --- Option Explicit +// --- Option Compare Text + +long SetParent(long hWndChild, long hWndNewParent); +long SetWindowLong(long hWnd, long nIndex, long dwNewLong); +long GetWindowLong(long hWnd, long nIndex); +long GetTempPath(long nBufferLength, char *lpBuffer); +long GetWindowText(long hWnd, char *lpString, long cch); + +#define GWL_STYLE ((-16)) +#define WS_CHILD (0x40000000) +#define WS_POPUP (0x80000000) + +// [UNCOMMENTED] Dim StretchWidth2& + +char *MpxBmp; +int OldPointer; +long OSX, OSY, MDX, MDY; +int MouseButton; + +int PanelSeq; + +boolean Loaded, DemosAvailable; + +#define nSpeedCount (17) +int SpeedsByDelayUS[nSpeedCount + 1]; +#define DefaultSpeedIndex (12) + +currency LastTick, LastFrame; +TickCountObject T; + +const char *AppTitle = "MegaPlex"; + +static char *GetSpeedDescriptionFPS(currency FrameDelayUS) +{ + static char *GetSpeedDescriptionFPS; + + long FPS; + + if (FrameDelayUS == 0) + { + GetSpeedDescriptionFPS = "Fastest possible"; + return GetSpeedDescriptionFPS; + } + + if (FrameDelayUS < 0) + { + GetSpeedDescriptionFPS = "! display (even faster)"; + return GetSpeedDescriptionFPS; + } + + FPS = 1000000 / FrameDelayUS; + GetSpeedDescriptionFPS = CAT(INT_TO_STR(FPS), " fps"); + if (35 == FPS) + GetSpeedDescriptionFPS = CAT(GetSpeedDescriptionFPS, "(Default)"); + + return GetSpeedDescriptionFPS; +} + +static int InitSpeeds() +{ + static int InitSpeeds; + + SpeedsByDelayUS[1] = -1; // no display + SpeedsByDelayUS[2] = 0; // fastest possible + SpeedsByDelayUS[3] = 1000000 / 700; // 700 fps + SpeedsByDelayUS[4] = 1000000 / 500; // 500 fps + SpeedsByDelayUS[5] = 1000000 / 350; // 350 fps + SpeedsByDelayUS[6] = 1000000 / 250; // 250 fps + SpeedsByDelayUS[7] = 1000000 / 200; // etc. + SpeedsByDelayUS[8] = 1000000 / 150; + SpeedsByDelayUS[9] = 1000000 / 100; + SpeedsByDelayUS[10] = 1000000 / 70; + SpeedsByDelayUS[11] = 1000000 / 50; + SpeedsByDelayUS[12] = 1000000 / 35; // default + SpeedsByDelayUS[13] = 1000000 / 25; + SpeedsByDelayUS[14] = 1000000 / 20; + SpeedsByDelayUS[15] = 1000000 / 10; + SpeedsByDelayUS[16] = 1000000 / 5; + SpeedsByDelayUS[17] = 1000000 / 1; + + return InitSpeeds; +} + +static int GetSpeedIndex(long DelayUS) +{ + static int GetSpeedIndex; + + int i; + long Diff, MinDiff; + int MinIdx; + + MinIdx = DefaultSpeedIndex; + MinDiff = 1000000; + for (i = 1; i <= nSpeedCount; i++) + { + Diff = Abs(DelayUS - SpeedsByDelayUS[i]); + if (Diff < MinDiff) + { + MinDiff = Diff; + MinIdx = i; + } + } + + GetSpeedIndex = MinIdx; + + return GetSpeedIndex; +} + +#if 0 + +static long Get_LastOpenFilter() +{ + static long LastOpenFilter; + + SettingsObject s; + + LastOpenFilter = s.Read("LastOpenFilter", 1); + + return LastOpenFilter; +} + +static void Let_LastOpenFilter(long NewVal) +{ + SettingsObject s; + + SettingsObject_Save("LastOpenFilter", NewVal); +} + +static long Get_LastSaveFilter() +{ + static long LastSaveFilter; + + SettingsObject s; + + LastSaveFilter = s.Read("LastSaveFilter", 1); + + return LastSaveFilter; +} + +static void Let_LastSaveFilter(long NewVal) +{ + SettingsObject s; + + SettingsObject_Save("LastSaveFilter", NewVal); +} + +#endif + +static void CountDown(long HalfSeconds, int bDisplayBar) +{ + long i; + int k; + long dT, Delta; + long LeftPos, TopPos, RightPos, MaxWidth; // , MaxHeight& + + dT = HalfSeconds * 500; + Delta = dT / 200; + LeftPos = cmbFile.left; + TopPos = cmbFile.top - shpProgress.Height - cmbFile.top / 8; + RightPos = lblFrameCount.left + lblFrameCount.Width; + MaxWidth = RightPos - LeftPos; + // MaxHeight = lblFrameCount.Top - TopPos + lblFrameCount.Height + 4 + if (bDisplayBar) + { + shpProgress.Move(LeftPos, TopPos, 0); // , MaxHeight + shpProgress.Visible = True; + } + + for (i = 1; i <= 200; i++) + { + // lblFrameCount = i + if (bDisplayBar) + { + if (i < 101) + { + shpProgress.Width = MaxWidth * i / 100; + } + else + { + k = MaxWidth * (i - 100) / 100; + shpProgress.Move(k, TopPos, RightPos - k); + } + } + + T.DelayMS(Delta, False); + } + + shpProgress.Visible = False; + // lblFrameCount = 0 +} + +static char *GetValidTempPath() +{ + static char *GetValidTempPath; + + char *TP; + long nSize, L; + + GetValidTempPath = ""; + nSize = 255; + TP = String(nSize, Chr(32)); + L = GetTempPath(nSize, TP); + if (nSize < L) + { + // buffer was too small, retry with a properly sized buffer: + nSize = L; + TP = String(nSize, Chr(32)); + L = GetTempPath(nSize, TP); + } + + TP = SlashLess(left(TP, L)); + if ((0 == L) || (! IsDir(TP))) + { + // no valid temp path can be retrieved from the system --> create our own + TP = CAT(WithSlash(App.Path), "Temp"); + if (! IsDir(TP)) + { + + // --- On Error Resume Next + MkDir(TP); + if (! IS_NOTHING(&Err, sizeof(Err))) + { + MESSAGE_BOX("an error occured"); // MsgBox "cannot create directory for temporary files " & TP, vbCritical, "MegaPlex - Error"; + return GetValidTempPath; + } + + // --- On Error GoTo 0 + + } + } + + if (IsDir(TP)) + GetValidTempPath = TP; + + return GetValidTempPath; +} + +#if 0 + +static char *GetMyTempFileName() +{ + static char *GetMyTempFileName; + + char *T; + + (char *)T = Hex(hWnd); + while (Len(T) < 8) + { + T = CAT("0", T); + } + + GetMyTempFileName = CAT("tmp0x", CAT((char *)T, ".mpx")); + + return GetMyTempFileName; +} + +static long GetHwndFromTempFileName(char *TmpFile) +{ + static long GetHwndFromTempFileName; + + char *FN; + long LP; + int L; + char *NumString; + + GetHwndFromTempFileName = 0; + FN = StripFileName(TmpFile); + LP = Len("tmp0x"); + L = Len(TmpFile); + if (LP < L) + return GetHwndFromTempFileName; + + L = L - LP; + NumString = right(FN, L - LP); + if (8 < L) + NumString = left(NumString, 8); + + NumString = CAT("&H", NumString); + GetHwndFromTempFileName = Val(NumString); + + return GetHwndFromTempFileName; +} + +static void CleanTempDir(char *TmpDir) +{ + char *FN, *MFN; + + MFN = GetMyTempFileName(); + MayKill(CAT(WithSlash(TmpDir), MFN)); + FN = Dir(CAT(WithSlash(TmpDir), "tmp0x*.mpx")); + while (FN != "") + { + if (STRING_IS_LIKE(FN, "tmp0x*.mpx")) + { + if (! InstanceStillRunning(FN)) + MayKill(CAT(WithSlash(TmpDir), FN)); + } + + FN = Dir_Without_Args(); + } +} + +static boolean InstanceStillRunning(char *TmpFile) +{ + static boolean InstanceStillRunning; + + long OtherHwnd, nSize, L; + char *Cap; + + InstanceStillRunning = False; + OtherHwnd = GetHwndFromTempFileName(TmpFile); + nSize = 255; + Cap = String(nSize, Chr(32)); + L = GetWindowText(OtherHwnd, Cap, nSize); + if ((L == 0) || (nSize < L)) + return InstanceStillRunning; + + if (STRING_IS_LIKE(Cap, CAT(AppTitle, "*"))) + InstanceStillRunning = True; + + return InstanceStillRunning; +} + +#endif + +void DisplayLevel() +{ + int X, Y; + + if (! Loaded) + return; + + if (! LevelLoaded) + return; + +#if 0 + SetDisplayRegion(); +#endif + + DrawFrame(0); + +#if 0 + if (! menBorder.Checked) + DrawFrame(1); +#endif + + if (bPlaying) + { + for (Y = DisplayMinY; Y <= DisplayMaxY; Y++) + { + for (X = DisplayMinX; X <= DisplayMaxX; X++) + { + DrawFieldNoAnimated(X, Y); + } + } + + for (Y = DisplayMinY; Y <= DisplayMaxY; Y++) + { + for (X = DisplayMinX; X <= DisplayMaxX; X++) + { + DrawFieldAnimated(X, Y); + } + } + + } + else + { + for (Y = DisplayMinY; Y <= DisplayMaxY; Y++) + { + for (X = DisplayMinX; X <= DisplayMaxX; X++) + { + DrawField(X, Y); + } + } + } +} + +#if 0 + +static void cmbFile_Click() +{ + CurPath = CAT(StripDir(OrigPath), CAT("/", cmbFile.List(cmbFile.ListIndex))); + OrigPath = CurPath; + FillLevelList(CurPath, LevelNumber); + if (STRING_IS_LIKE(OrigPath, "*.mpx") || STRING_IS_LIKE(OrigPath, "*.sp")) + { + menSave.Enabled = True; + } + else + { + menSave.Enabled = False; + } +} + +static void cmbFile_KeyDown(int KeyCode, int Shift) +{ + picPane_KeyDown(KeyCode, Shift); +} + +static void cmbFile_KeyUp(int KeyCode, int Shift) +{ + picPane_KeyUp(KeyCode, Shift); +} + +static int GetFileNameToSave() +{ + static int GetFileNameToSave; + + char *T; + + (char *)T = StripFileName(OrigPath); + if (STRING_IS_LIKE(T, "*.dat") || STRING_IS_LIKE(T, "*.d##")) + { + T = "Level" & Format(LevelNumber, "#000"); + } + + GetFileNameToSave = T; + + return GetFileNameToSave; +} + +static void cmbLevel_Click() +{ + long InfoCount; + boolean Oldflag; + int Msg; + long LastIndex; + boolean bBlock; + + if (bBlock) + return; + + // ////////////////////////////////////////////////////////////////// + if (ModifiedFlag) + { + VbMsgBoxResult Res; + + Msg = "Save changes to " & GetFileNameToSave() & " ?"; + Res = MsgBox(Msg, vbYesNoCancel, AppTitle & " - close level"); + if (Res == vbCancel) // fallback + { + bBlock = True; + + // --- On Error Resume Next + cmbLevel.ListIndex = LastIndex; + // --- On Error GoTo 0 + + bBlock = False; + Debug.Assert cmbLevel.ListIndex = LastIndex; + return; + } + + if (Res == vbYes) + { + // Dim oldCurPath$ + // oldCurPath = CurPath + if (FileExists(OrigPath) && menSave.Enabled) + { + menSave_Click(); + } + else + { + if (! SaveAs()) // fallback + { + bBlock = True; + + // --- On Error Resume Next + cmbLevel.ListIndex = LastIndex; + // --- On Error GoTo 0 + + bBlock = False; + Debug.Assert cmbLevel.ListIndex = LastIndex; + return; + } + } + + // CurPath = oldCurPath + } + + Let_ModifiedFlag(False); + CurPath = OrigPath; + } + + // ////////////////////////////////////////////////////////////////// + { + LevelNumber = cmbLevel.ListIndex + 1; + DemoFlag = False; + if (Loaded) + { + Oldflag = NoDisplayFlag; + NoDisplayFlag = False; + subFetchAndInitLevel(); + if ((0 < SignatureDelay) && ! (WindowState == vbMinimized)) + { + Msg = LInfo.LevelTitle & vbNewLine & "(" & FieldWidth & " x " & FieldHeight & ")"; + if (DemoAvailable && bSignatureAvailable) + Msg = Msg & vbNewLine & vbNewLine & gSignature; + + SignatureForm.Signature = Msg; + SignatureForm.DelayMS = SignatureDelay; + int X, Y; + + X = left + (Width - SignatureForm.Width) / 2; + Y = top + (Height - SignatureForm.Height) / 2; + SignatureForm.Move X, Y; + SignatureForm.Show vbModeless, Me; + Me.SetFocus; + } + + lblStatus = "MegaPlex"; + lblFrameCount = GetTotalFramesOfDemo(); + if (EditFlag) + EdAll(); + + ReStretch(Stretch); + // picPane_Paint + Stage.Blt(); + NoDisplayFlag = Oldflag; + LastIndex = cmbLevel.ListIndex; + } + + } + menPlayDemo.Enabled = DemoAvailable; + cmdPlayDemo.Enabled = DemoAvailable; +} + +static void cmblevel_KeyDown(int KeyCode, int Shift) +{ + if (GameLoopRunning != 0) + return; + + switch (KeyCode) + { + case vbKeySpace: + if (menPlay.Enabled == True) + menPlay_Click(); + + break; + + default: + picPane_KeyDown(KeyCode, Shift); + break; + } +} + +static void cmbLevel_KeyUp(int KeyCode, int Shift) +{ + picPane_KeyUp(KeyCode, Shift); +} + +static void cmdPause_Click() +{ + menPause_Click(); +} + +static void cmdPause_MouseUp(int Button, int Shift, float X, float Y) +{ + FocusTim.Enabled = True; +} + +static void cmdPlay_Click() +{ + if (menPlay.Enabled) + menPlay_Click(); +} + +static void cmdPlay_MouseUp(int Button, int Shift, float X, float Y) +{ + FocusTim.Enabled = True; +} + +static void cmdPlayAll_Click() +{ + menPlayAll_Click(); +} + +static void cmdPlayAll_MouseUp(int Button, int Shift, float X, float Y) +{ + FocusTim.Enabled = True; +} + +static void cmdPlayDemo_Click() +{ + menPlayDemo_Click(); +} + +static void cmdPlayDemo_MouseUp(int Button, int Shift, float X, float Y) +{ + FocusTim.Enabled = True; +} + +static void cmdRecordDemo_Click() +{ + if (menRec.Enabled) + menRec_Click(); +} + +static void cmdRecordDemo_MouseUp(int Button, int Shift, float X, float Y) +{ + FocusTim.Enabled = True; +} + +static void cmdStop_Click() +{ + if (menStop.Enabled) + menStop_Click(); +} + +static void cmdStop_MouseUp(int Button, int Shift, float X, float Y) +{ + FocusTim.Enabled = True; +} + +static void FocusTim_Timer() +{ + FocusTim.Enabled = False; + + // --- On Error Resume Next + picPane.SetFocus; +} + +static void Form_KeyDown(int KeyCode, int Shift) +{ + picPane_KeyDown(KeyCode, Shift); +} + +static void Form_KeyUp(int KeyCode, int Shift) +{ + picPane_KeyUp(KeyCode, Shift); +} + +#endif + +static void Form_Load() +{ +#if 0 + + long i; + SettingsObject s; + +#endif + + Loaded = False; + DemoFlag = 0; + PanelSeq = 0; + EditFlag = False; + EditMode = edMove; + // FMark = New MarkerObject; // (handle this later, if needed) + InitGlobals(); + +#if 0 + + LoadMenus(); + + TmpPath = GetValidTempPath(); + if (TmpPath == "") + exit(-1); + + CleanTempDir(TmpPath); + TmpPath = CAT(WithSlash(TmpPath), GetMyTempFileName()); + GetSettings(); + ShowPanel = 1; + + InitDirectX(hWnd, picPane.hWnd); + + // AllowRedDiskCheat = 1 + MpxBmp = CAT(App.Path, "/mpx.bmp"); + // // Set NormalSprites = New DDSpriteBuffer // (handle this later, if needed) + // NormalSprites.CreateFromFile MPXBMP, 16, 16 + + Field = REDIM_2D(sizeof(int), 0, 2 + 1 - 1, 0, 2 + 1 - 1); + + picViewPort.ScaleMode = vbPixels; + + PauseMode = 0; + // BaseWidth = 16 + menBorder_Click(); + Loaded = True; + ReStretch(Stretch); + LoadKeyIndicators(); + + Show; + + FillFileList(CurPath); + if (s.Read("ShowSplash", True)) + { + // frmSplash.EnableTimer + frmSplash.Show vbModal, Me; + } + +#endif +} + +#if 0 + +static void FillLevelList(char *Path, int LevelIndex) +{ + long FNum, LevLen, i, iMax; + char *TFile; + + cmbLevel.Clear; + if (! FileExists(Path)) + return; + + if ((STRING_IS_LIKE(Path, "*.D??")) || (STRING_IS_LIKE(Path, "*.sp"))) + { + FNum = FreeFile(); + LevLen = 1536; + FNum = fopen(Path, "rb"); + { + i = 0; + FILE_GET(FNum, (long)1441 + i * LevLen, &LInfo, sizeof(LInfo)); + cmbLevel.AddItem Format(i + 1, "#000") & " " & LInfo.LevelTitle, i; + if (STRING_IS_LIKE(Path, "*.D??")) + { + while (!(EOF(FNum))) + { + i = i + 1; + FILE_GET(FNum, (long)1441 + i * LevLen, &LInfo, sizeof(LInfo)); + if (EOF(FNum)) + break; + + cmbLevel.AddItem Format(i + 1, "#000") & " " & LInfo.LevelTitle, i; + } + } + + if (LevelIndex <= i && 0 < LevelIndex) + i = LevelIndex - 1; + else + i = 0; + + cmbLevel.ListIndex = i; + } + fclose(FNum); + } + else if (STRING_IS_LIKE(Path, "*.mpx")) + { + FNum = FreeFile(); + LevLen = 1536; + FNum = fopen(Path, "rb"); + { + i = 0; + if (MpxOpen(Path)) + { + for (i = 1; i <= LevelCount; i++) + { + if (! MpxLoadLInfo(CInt(i))) + break; + + cmbLevel.AddItem Format(i, "#000") & " " & LInfo.LevelTitle, i - 1; + } + + MpxClose(); + } + + if (LevelIndex < i && 0 < LevelIndex) + i = LevelIndex - 1; + else + i = 0; + + if (i < cmbLevel.ListCount) + cmbLevel.ListIndex = i; + + } + fclose(FNum); + } +} + +static void FillFileList(char *Path) +{ + long FNum, LevLen, i; + int nDemoCount; + char *TFile, *TPath, *OFile; + + cmbFile.Clear; + i = 0; + nDemoCount = 0; + TPath = WithSlash(StripDir(Path)); + OFile = StripFileName(Path); + TFile = Dir(TPath & "*.D??"); + while (TFile != "") + { + if (FileLen(TPath & TFile) == 170496) + { + cmbFile.AddItem TFile; + } + + TFile = Dir; + } + + TFile = Dir(TPath & "*.SP"); + while (TFile != "") + { + nDemoCount = nDemoCount + 1; + cmbFile.AddItem TFile; + TFile = Dir; + } + + TFile = Dir(TPath & "*.mpx"); + while (TFile != "") + { + nDemoCount = nDemoCount + 1; + cmbFile.AddItem TFile; + TFile = Dir; + } + + i = cmbFile.ListCount - 1; + if (0 < cmbFile.ListCount) + { + do + { + if ((cmbFile.List(i) Like OFile) || i == 0) + break; + + i = i - 1; + } + while (!(i < 1)); + + cmbFile.ListIndex = i; + } + + DemosAvailable = (1 < nDemoCount); + menPlayAll.Enabled = DemosAvailable; + cmdPlayAll.Enabled = DemosAvailable; +} + +static void LoadMenus() +{ + long i; + + // speeds + menFaster.Enabled = False; + menSlower.Enabled = False; + InitSpeeds(); + for (i = 1; i <= nSpeedCount; i++) + { + if (1 < i) + { + Load menPlaySpeed(i); + Load menDemoSpeed(i); + } + + menPlaySpeed(i).Caption = GetSpeedDescriptionFPS(SpeedsByDelayUS[i]); + menDemoSpeed(i).Caption = GetSpeedDescriptionFPS(SpeedsByDelayUS[i]); + } + + // zoom + menStretch(1).Caption = Format(0.25, "#0.00") & "; + 1"; + if (Stretch == 0.25) + menStretch(1).Checked = True; + + for (i = 2; i <= 20; i++) + { + Load menStretch(i); + menStretch(i).Caption = Format(0.25 * i, "#0.00") & "; + 1"; + menStretch(i).Checked = ((i * 0.25) == Stretch); + } + + menSp.Enabled = False; +} + +// +// Function DisplayShift&() +// Dim X&, Y&, A&, B&, iX&, iiX&, LD& +// Dim Sprite& +// DisplayShift = 0 +// For A = 0 To picPane.ScaleWidth +// For Y = DisplayMinY To DisplayMaxY +// For X = DisplayMinX To DisplayMaxX +// iX = StretchWidth * X + A +// Sprite = Field(X, Y).SpritePos +// If picPane.ScaleWidth < (iX + 1) Then +// iX = iX - picPane.ScaleWidth +// Else +// If picPane.ScaleWidth < (iX + 1 + BaseWidth) Then +// iiX = iX - picPane.ScaleWidth +// Sprites.BitBltSprite picPane.hdc, iiX, StretchWidth * Y, Sprite +// End If +// End If +// Sprites.BitBltSprite picPane.hdc, iX, StretchWidth * Y, Sprite +// Next X +// Next Y +// DisplayShift = DisplayShift + 1 +// 'DoEvents +// Next A +// End Function + +static void Form_Paint() +{ + // Debug.Print "Form_Paint()" +} + +static void Form_Resize() +{ + long Space, NW, NH; + int Tmp; + + if (WindowState == vbMinimized || ! Loaded) + return; + + Space = Panel.left; + // NW = ScaleWidth - 2 * Space: If NW < 0 Then NW = 0 + // NH = ScaleHeight - 3 * Space - cmbLevel.Height: If NH < 0 Then NH = 0 + // picViewPort.Move Space, Space, NW, NH + Tmp = (ShowPanel != 0 ? ScaleHeight - Panel.Height : ScaleHeight - Panel.Height); + if (Tmp < 0) + Tmp = 0; + + picViewPort.Move 0, 0, ScaleWidth, Tmp; + // Tmp = 2 * Space + picViewPort.Height + Panel.top = Tmp; + Panel.left = (ScaleWidth - Panel.Width) / 2; + // 'cmdNormal.Top = 2 * Space + picViewPort.Height + // cmbLevel.Top = Tmp + // lblRedDiskCount.Top = Tmp + // lblInfoCount.Top = Tmp + // picKeys.Top = Tmp + // lblFrameCount.Top = Tmp + // cmdPlayAll.Top = Tmp +} + +#endif + +static void DrawFrame(int Delta) +{ + int i, LX, tY, RX, BY; + + LX = -1 + Delta; + tY = -1 + Delta; + RX = FieldWidth - Delta; + BY = FieldHeight - Delta; + DrawSprite(LX, tY, posFrameCorner); + DrawSprite(LX, BY, posFrameCorner); + DrawSprite(RX, tY, posFrameCorner); + DrawSprite(RX, BY, posFrameCorner); + for (i = LX + 1; i <= RX - 1; i++) + { + DrawSprite(i, tY, posFrameHorizontal); + DrawSprite(i, BY, posFrameHorizontal); + } + + for (i = tY + 1; i <= BY - 1; i++) + { + DrawSprite(LX, i, posFrameVertical); + DrawSprite(RX, i, posFrameVertical); + } +} + +static void RestoreFrame() +{ + int i, LX, tY, RX, BY; + + LX = 0; + tY = 0; + RX = FieldWidth - 1; + BY = FieldHeight - 1; + for (i = LX; i <= RX; i++) + { + DrawField(i, tY); + DrawField(i, BY); + } + + for (i = tY + 1; i <= BY - 1; i++) + { + DrawField(LX, i); + DrawField(RX, i); + } +} + +#if 0 + +static void Form_Unload(int Cancel) +{ + EndFlag = True; + ExitToMenuFlag = 1; + if (cmdPlayAll.STRING_IS_LIKE(Caption, "Quit*")) + { + cmdPlayAll_Click(); + } + + if (menEdit.Checked) + menEdit_Click(); + + if (ModifiedFlag) + { + char *Msg; + VbMsgBoxResult Res; + + Msg = "Save changes to " & GetFileNameToSave() & " ?"; + Res = MsgBox(Msg, vbYesNoCancel, AppTitle & " - closing"); + if (Res == vbCancel) + { + Cancel = -1; + return; + } + + if (Res == vbYes) + { + if (FileExists(OrigPath) && menSave.Enabled) + { + menSave_Click(); + } + else + { + menSaveAs_Click(); + } + } + } + + if (FileExists(TmpPath) || ModifiedFlag) + { + MayKill(TmpPath); + CurPath = OrigPath; + } + + ReleaseDirectDraw(); + SaveSettings(); + End; +} + +static void fpsTim_Timer() +{ + currency TickDiff; + int count5; + + count5 = count5 + 1; + if (4 < count5) + { + TickDiff = T.TickDiffUS(LastTick); + lblFps.Caption = CLng(Round((1000000 * (TimerVar - LastFrame)) / (TickDiff), 0)); + LastFrame = TimerVar; + LastTick = T.TickNow(); + count5 = 0; + } + + // If NoDisplayFlag Then lblFrameCount = TimerVar + lblFrameCount = TimerVar; +} + +static void menAbout_Click() +{ + frmSplash.Show vbModal, Me; +} + +static void menAutoScroll_Click() +{ + { + menAutoScroll.Checked = ! menAutoScroll.Checked; + AutoScrollFlag = menAutoScroll.Checked; + } +} + +static void menBorder_Click() +{ + if (menBorder.Checked) + { + menBorder.Checked = False; + DisplayMinX = 1; + DisplayMaxX = FieldWidth - 2; + DisplayWidth = FieldWidth; + DisplayMinY = 1; + DisplayMaxY = FieldHeight - 2; + DisplayHeight = FieldHeight; + if (Loaded && LevelLoaded) + DrawFrame(1); + + } + else + { + menBorder.Checked = True; + DisplayMinX = 0; + DisplayMaxX = FieldWidth - 1; + DisplayWidth = FieldWidth + 2; + DisplayMinY = 0; + DisplayMaxY = FieldHeight - 1; + DisplayHeight = FieldHeight + 2; + if (Loaded && LevelLoaded) + RestoreFrame(); + } + + ReStretch(Stretch); + // DisplayLevel True +} + +void SetDisplayRegion() +{ + if (! menBorder.Checked) + { + DisplayMinX = 1; + DisplayMaxX = FieldWidth - 2; + DisplayWidth = FieldWidth; + DisplayMinY = 1; + DisplayMaxY = FieldHeight - 2; + DisplayHeight = FieldHeight; + if (LevelLoaded) + DrawFrame(1); + + } + else + { + DisplayMinX = 0; + DisplayMaxX = FieldWidth - 1; + DisplayWidth = FieldWidth + 2; + DisplayMinY = 0; + DisplayMaxY = FieldHeight - 1; + DisplayHeight = FieldHeight + 2; + if (LevelLoaded) + RestoreFrame(); + } +} + +static void menCopy_Click() +{ + FMark.Copy; +} + +void menEdit_Click() +{ + long L; + + if (menEdit.Checked) + { + menEdit.Checked = False; + // leave edit mode + if (EditFlag) + Unload ToolBox; + + EditFlag = False; + UnEdAll(); + FMark.ShowMarker False; + picViewPort.MousePointer = 0; + if (ModifiedFlag) + { + if (! STRING_IS_LIKE(CurPath, TmpPath)) + { + OrigPath = CurPath; + CurPath = TmpPath; + } + + SaveMPX(TmpPath); + } + + DisplayLevel(); + Stage.Blt(); + } + else + { + if (! LevelLoaded) + { + Beep(); + return; + } + + if (ModifiedFlag) + { + if (! STRING_IS_LIKE(CurPath, TmpPath)) + { + OrigPath = CurPath; + CurPath = TmpPath; + } + + SaveMPX(TmpPath); + } + + subFetchAndInitLevel(); + menEdit.Checked = True; + // enter edit mode + EditFlag = True; + // ScaleMode = vbTwips + ToolBox.Move (Width - ToolBox.Width) / 2, Height - ToolBox.Height; + // ScaleMode = vbPixels + // L = GetWindowLong(ToolBox.hWnd, GWL_STYLE) + // L = L And (Not WS_POPUP) + // L = L Or WS_CHILD + // SetWindowLong ToolBox.hWnd, GWL_STYLE, L + // SetParent ToolBox.hWnd, hWnd + ToolBox.Show vbModeless, Me; + EdAll(); + DisplayLevel(); + Stage.Blt(); + FMark.ShowMarker True; + } +} + +static void menEnOff_Click() +{ + menEnOn.Checked = False; + menEnOff.Checked = True; + SpSaveMenu(); + SpLoadMenu(); +} + +static void menEnOn_Click() +{ + menEnOn.Checked = True; + menEnOff.Checked = False; + SpSaveMenu(); + SpLoadMenu(); +} + +static void menExit_Click() +{ + Unload Me; +} + +static void menFaster_Click() +{ + int i; + + if (! bPlaying) + { + Debug.Assert(False); + return; + } + + if (DemoFlag != 0) // demoplayback + { + i = GetSpeedIndex(DeltaTDemo); + i = i - 1; + If i < 2 Then i = 2; + menDemoSpeed_Click (i); + } + else + { + i = GetSpeedIndex(DeltaTPlay); + i = i - 1; + If i < 2 Then i = 2; + menPlaySpeed_Click (i); + } +} + +static void menSlower_Click() +{ + int i; + + if (! bPlaying) + { + Debug.Assert(False); + return; + } + + if (DemoFlag != 0) // demoplayback + { + i = GetSpeedIndex(DeltaTDemo); + i = i + 1; + If nSpeedCount < i Then i = nSpeedCount; + menDemoSpeed_Click (i); + } + else + { + i = GetSpeedIndex(DeltaTPlay); + i = i + 1; + If nSpeedCount < i Then i = nSpeedCount; + menPlaySpeed_Click (i); + } +} + +void menPlaySpeed_Click(int Index) +{ + int i; + + // If NoDisplayFlag And (GameLoopRunning <> 0) Then + // NoDisplayFlag = False + // DisplayLevel + // End If + // NoDisplayFlag = False + for (i = menPlaySpeed.LBound; i <= menPlaySpeed.UBound; i++) + { + { + menPlaySpeed(i).Checked = (Index == i); + } + } + + BlockingSpeed = False; + DeltaTPlay = SpeedsByDelayUS[Index]; + UpdateDeltaT(); + // If DeltaTPlay < 0 Then + // Stage.Blt + // DeltaT = 0 + // NoDisplayFlag = True + // End If +} + +void menDemoSpeed_Click(int Index) +{ + int i; + + // If NoDisplayFlag And (GameLoopRunning <> 0) Then + // NoDisplayFlag = False + // DisplayLevel + // End If + NoDisplayFlag = False; + for (i = menDemoSpeed.LBound; i <= menDemoSpeed.UBound; i++) + { + { + menDemoSpeed(i).Checked = (Index == i); + } + } + + BlockingSpeed = False; + DeltaTDemo = SpeedsByDelayUS[Index]; + UpdateDeltaT(); + // If DeltaTPlay < 0 Then + // Stage.Blt + // DeltaT = 0 + // NoDisplayFlag = True + // End If +} + +static void UpdateDeltaT() +{ + if (! bPlaying) + return; + + DeltaT = (DemoFlag != 0 ? DeltaTDemo : DeltaTDemo); + if (DeltaT < 0) + { + Stage.Blt(); + DeltaT = 0; + NoDisplayFlag = True; + } + else + { + if (NoDisplayFlag && GameLoopRunning != 0) + { + NoDisplayFlag = False; + DisplayLevel(); + } + else + { + NoDisplayFlag = False; + } + } +} + +static void menGravOff_Click() +{ + menGravOn.Checked = False; + menGravOff.Checked = True; + SpSaveMenu(); + SpLoadMenu(); +} + +static void menGravOn_Click() +{ + menGravOn.Checked = True; + menGravOff.Checked = False; + SpSaveMenu(); + SpLoadMenu(); +} + +static void menNew_Click() +{ + NewForm.Show vbModal, Me; + CreateLevel(FieldWidth, FieldHeight); + ReStretch(Stretch); +} + +static void menNewStd_Click() +{ + CreateLevel(60, 24); + ReStretch(Stretch); +} + +static void menOpen_Click() +{ + long LFilt; + + { + // cmDlg.DefaultExt = "sp" + + /* + + (prevent compiler warning here due to suspected use of trigraph) + + cmDlg.Filter = "All Levels (*.DAT;*.D??;*.sp;*.mpx)|*.DAT;*.D??;*.sp;*.mpx|MegaPlex Levels (*.mpx)|*.mpx" & "|Supaplex Level Sets (*.DAT;*.D??)|*.DAT;*.D??|SpeedFix Demos (*.sp)|*.sp"; + */ + + LFilt = LastOpenFilter; + cmDlg.FilterIndex = (0 < LFilt & LFilt < 5 ? LFilt : LFilt); + if (FileExists(CurPath)) + cmDlg.InitDir = WithSlash(StripDir(CurPath)); + + cmDlg.flags = cdlOFNHideReadOnly | cdlOFNLongNames; + } + + // --- On Error GoTo menOpenEH + cmDlg.ShowOpen; + // --- On Error GoTo 0 + + LFilt = cmDlg.FilterIndex; + LastOpenFilter = LFilt; + CurPath = cmDlg.FileName; + OrigPath = CurPath; + FillFileList (CurPath); + +menOpenEH: +} + +static void menOptions_Click() +{ + OptionsForm oFrm; + + oFrm.Show vbModal, Me; + SaveSettings(); + picViewPort_Resize(); +} + +static void menPanel_Click() +{ + { + PanelVisible = ! menPanel.Checked; + } +} + +void Let_PanelVisible(boolean NewVal) +{ + boolean HidePanel; + + if (HidePanel != NewVal) + return; + + HidePanel = ! NewVal; + PanelTim.Enabled = True; +} + +static void DrawPauseLayer(long Layer) +{ + DirectDrawPalette Pal; + PALETTEENTRY *Val; + long i; + + // Dim X&, Y& + // For Y = 0 To bmpStage.Height Step BaseWidth + // For X = 0 To bmpStage.Width Step BaseWidth + // Pause.TransparentDraw bmpStageHDC, X, Y, Layer + // Next X + // Next Y + // With Stage.Surface + // Set Pal = .GetPalette + // for i=1 to pal.GetEntries( + // Stage.Surface.SetPalette +} + +static void menPaste_Click() +{ + FMark.Paste; + DisplayLevel(); + Stage.Blt(); +} + +static void menPause_Click() +{ + StdPicture OldPic; + char *OldText; + + PauseMode = (PauseMode != 0 ? 0 : 0); + if (PauseMode != 0) + { + if (IS_NOTHING(&OldPic, sizeof(OldPic))) + OldPic = cmdPause.Picture; + + cmdPause.Picture = cmdPause.DownPicture; + OldText = lblStatus.Caption; + lblStatus = "Paused ..."; + } + else + { + cmdPause.Picture = OldPic; + lblStatus.Caption = OldText; + } +} + +static void menPlayAll_Click() +{ + long iMin, iMax, i; + int FNum; + char *LogPath, *OutStr, *ReRecPath, *SPPath; + boolean bEqual; + boolean QuitFlag; + + if (cmdPlayAll.STRING_IS_LIKE(Caption, "Play) All Demos") + { + cmdPlayAll.Caption = "Quit All"; + menPlayAll.Caption = "Quit All"; + FocusTim.Enabled = True; + QuitFlag = False; + iMin = 0; + iMax = cmbFile.ListCount - 1; + LogPath = StripDir(CurPath) & "/Error.Log"; + if (Dir(LogPath) != "") + Kill(LogPath); + + for (i = iMin; i <= iMax; i++) + { + cmbFile.ListIndex = i; + // If CurPath Like "*.sp" Or CurPath Like "*.mpx" Then + if (DemoAvailable) + { + SPPath = CurPath; + ReRecPath = SPPath & ".ReRec"; + menPlayDemo_Click(); + // SaveSP ReRecPath + // bEqual = FilesEqual(ReRecPath, SPPath) + // If bEqual Then MayKill ReRecPath + bEqual = True; + OutStr = cmbFile.List(i) & " -> "; + // + if (Val(lblFrameCount) != GetTotalFramesOfDemo()) + { + OutStr = OutStr & "Error in GetTotalFramesOfDemo()! "; + Debug.Assert(False); + } + + // + if ((LevelStatus == 1) && bEqual) + { + OutStr = OutStr & "Success"; + } + else if (QuitFlag) + { + OutStr = OutStr & "All Demos (float)Canceled"; + } + else + { + if (LevelStatus != 1) + { + OutStr = OutStr & "### Level Failed ### (TimerVar == " & TimerVar & ")"; + } + + if (! bEqual) + { + OutStr = OutStr & "### ReRecording is binary different ###"; + } + } + + FNum = FreeFile(); + FNum = fopen(LogPath, "ab"); + Print #FNum, OutStr; + fclose(FNum); + if (QuitFlag) + break; + } + } + + cmdPlayAll.Caption = "Play All Demos"; + menPlayAll.Caption = "Play All Demos"; + SettingsObject Settings; + + MySignature = Settings.Read("MySignature", ""); + FirstDemoByte = 0x81; + } + else + { + QuitFlag = True; + if (menStop.Enabled) + menStop_Click(); + } +} + +static void menRemSP_Click() +{ + RemoveSP(); + SpLoadMenu(); +} + +static void menRestoreBorder_Click() +{ + RestoreBorder(); +} + +static void menSave_Click() +{ + if (! ModifiedFlag) + return; + + if (STRING_IS_LIKE(CurPath, TmpPath)) + CurPath = OrigPath; + + if (STRING_IS_LIKE(CurPath, "") || STRING_IS_LIKE(CurPath, "*.dat")) + { + menSaveAs_Click(); + return; + } + + if (STRING_IS_LIKE(CurPath, "*.sp")) + { + menSaveAs_Click(); + return; + } + + if (! FileExists(CurPath) || STRING_IS_LIKE(CurPath, "Untitled")) + { + menSaveAs_Click(); + return; + } + + SaveMPX(CurPath); + Let_ModifiedFlag(False); +} + +static void menSaveAs_Click() +{ + if (SaveAs()) + FillFileList (CurPath); +} + +static boolean SaveAs() +{ + static boolean SaveAs; + + char *FN; + SettingsObject s; + + SaveAs = False; + { + // cmDlg.DefaultExt = "sp" + cmDlg.Filter = "MegaPlex Level (*.mpx)|*.mpx|SpeedFix Demo (*.sp)|*.sp"; + cmDlg.FilterIndex = LastSaveFilter; + // If OrigPath Like "*.sp" Then cmDlg.FilterIndex = 1 Else cmDlg.FilterIndex = 0 + if (FileExists(OrigPath)) + { + cmDlg.InitDir = WithSlash(StripDir(OrigPath)); + cmDlg.InitDir = s.Read("LastSaveDir", cmDlg.InitDir); + cmDlg.FileName = StripExtensionlessFileName(GetFileNameToSave()); + } + + cmDlg.flags = cdlOFNHideReadOnly | cdlOFNLongNames; + } + + // --- On Error GoTo SaveAsEH + cmDlg.ShowSave; + // --- On Error GoTo 0 + + LastSaveFilter = cmDlg.FilterIndex; + FN = cmDlg.FileName; + SettingsObject_Save("LastSaveDir", WithSlash(StripDir(FN))); + if (STRING_IS_LIKE(FN, "*.sp")) + { + SaveSP(FN); + } + else if (STRING_IS_LIKE(FN, "*.mpx")) + { + SaveMPX(FN); + } + + Let_ModifiedFlag(False); + SaveAs = True; + +SaveAsEH: + + return SaveAs; +} + +static void menSelectAll_Click() +{ + FMark.SetPoint1 0, 0; + FMark.SetPoint2 FieldWidth - 1, FieldHeight - 1; +} + +static void menShowLInfo_Click() +{ + char *Msg; + + Msg = LInfo.LevelTitle & vbNewLine & "(" & FieldWidth & " x " & FieldHeight & ")"; + if (DemoAvailable && bSignatureAvailable) + Msg = Msg & vbNewLine & vbNewLine & gSignature; + + SignatureForm.Signature = Msg; + SignatureForm.DelayMS = 5000; + int X, Y; + + X = left + (Width - SignatureForm.Width) / 2; + Y = top + (Height - SignatureForm.Height) / 2; + SignatureForm.Move X, Y; + SignatureForm.Show vbModeless, Me; + Me.SetFocus; +} + +static void menSoundFX_Click() +{ + { + menSoundFX.Checked = ! menSoundFX.Checked; + FXOnFlag = (menSoundFX.Checked ? -1 : -1); + } +} + +#endif + +// static void menPlay_Click() +void menPlay_Click() +{ + +#if 0 + + boolean OldEditFlag; + + // Trace "MainForm", "--> menPlay_Click()" + if (! LevelLoaded) + { + Beep(); + return; + } + + SignatureForm.DelayMS = 1; + menPlay.Enabled = False; + menPause.Enabled = True; + menStop.Enabled = True; + cmdPlay.Enabled = False; + cmdPause.Enabled = True; + cmdStop.Enabled = True; + cmdPlayDemo.Enabled = False; + menPlayDemo.Enabled = False; + cmdRecordDemo.Enabled = False; + menRec.Enabled = False; + menFaster.Enabled = True; + menSlower.Enabled = True; + if (cmdPlayAll.STRING_IS_LIKE(Caption, "Play*")) + { + cmdPlayAll.Enabled = False; + menPlayAll.Enabled = False; + } + + cmbFile.Enabled = False; + cmbLevel.Enabled = False; + OldEditFlag = EditFlag; + if (EditFlag) + menEdit_Click(); + + menEditMain.Enabled = False; + if (DemoFlag == 0 && RecordDemoFlag == 0) + lblStatus = "Playing"; + + lblFrameCount = 0; + +#endif + + LastFrame = 0; + LastTick = T.TickNow; + +#if 0 + + fpsTim.Enabled = True; + +#endif + + // DimPrimary 100 + bPlaying = True; + +#if 0 + + UpdateDeltaT(); + +#endif + + subFetchAndInitLevelB(); + // Trace "MainForm", "CountDown 1" + CountDown(2, (0 == DemoFlag)); + // Trace "MainForm", "Call GoPlay" + GoPlay(); + // Trace "MainForm", "GoPlay returned" + +#if 0 + + if (LevelStatus == 1) + { + lblStatus = "(float)Success"; + } + else + { + lblStatus = "Try (float)again"; + } + +#endif + + // Trace "MainForm", "CountDown 1" + CountDown(1, False); + RecordDemoFlag = 0; + +#if 0 + ShowKey(0); +#endif + + bPlaying = False; + // Trace "MainForm", "Call subFetchAndInitLevel" + subFetchAndInitLevel(); + // Trace "MainForm", "subFetchAndInitLevel returned" + Stage.Blt(); + +#if 0 + + menEditMain.Enabled = True; + if (OldEditFlag) + menEdit_Click(); + + // Trace "MainForm", "<-- menPlay_Click()" + +#endif + +} + +#if 0 + +static void menPlayDemo_Click() +{ + DemoFlag = 1; + RecordDemoFlag = 0; + lblStatus = "Demo Playback"; + menPlay_Click(); + if (LevelStatus != 1) + lblStatus = "Demo Failed"; + + DemoFlag = 0; +} + +static void menRec_Click() +{ + Trace("MainForm", "--> menRec_Click()"); + if (! LevelLoaded) + { + Beep(); + return; + } + + RecordDemoFlag = 1; + DemoFlag = 0; + lblStatus.ForeColor = vbRed; + lblStatus = "Recording Demo"; + // DemoBuffer = New DemoBufferObject; // (handle this later, if needed) + Debug.Assert(! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer))); + Trace("MainForm", "Call menPlayClick"); + menPlay_Click(); + Trace("MainForm", "menPlayClick returned"); + + lblStatus.ForeColor = vbButtonText; + RecordDemoFlag = 0; + Let_ModifiedFlag(True); + if (! STRING_IS_LIKE(CurPath, TmpPath)) + { + OrigPath = CurPath; + CurPath = TmpPath; + } + + LInfo.DemoRandomSeed = RecDemoRandomSeed; + Trace("MainForm", "Call SaveMPX(TmpPath)"); + SaveMPX(TmpPath); + Trace("MainForm", "Set DemoBuffer == Nothing"); + SET_TO_NOTHING(&DemoBuffer, sizeof(DemoBuffer)); + Trace("MainForm", "Call subFetchAndInitLevel"); + subFetchAndInitLevel(); + cmdPlayDemo.Enabled = DemoAvailable; + Trace("MainForm", "<-- menRec_Click()"); +} + +static void menReRecordDemo_Click() +{ + if (! LevelLoaded) + { + Beep(); + return; + } + + RecordDemoFlag = 1; + DemoFlag = 1; + lblStatus.ForeColor = vbRed; + lblStatus = "ReRecording Demo"; + // DemoBuffer = New DemoBufferObject; // (handle this later, if needed) + Debug.Assert(! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer))); + menPlay_Click(); + lblStatus.ForeColor = vbButtonText; + RecordDemoFlag = 0; + Let_ModifiedFlag(True); + if (! STRING_IS_LIKE(CurPath, TmpPath)) + { + OrigPath = CurPath; + CurPath = TmpPath; + } + + LInfo.DemoRandomSeed = RecDemoRandomSeed; + SaveMPX(TmpPath); + SET_TO_NOTHING(&DemoBuffer, sizeof(DemoBuffer)); + subFetchAndInitLevel(); +} + +void menStop_Click() +{ + EndFlag = True; + LeadOutCounter = 1; + if (PauseMode != 0) + menPause_Click(); + + fpsTim.Enabled = False; + fpsTim_Timer(); + lblFps.Caption = ""; + menRec.Enabled = True; + menPlay.Enabled = True; + menPause.Enabled = False; + menStop.Enabled = False; + cmdPlay.Enabled = True; + cmdPause.Enabled = False; + cmdStop.Enabled = False; + cmdRecordDemo.Enabled = True; + cmdPlayDemo.Enabled = DemoAvailable; + cmdPlayAll.Enabled = DemosAvailable; + menPlayDemo.Enabled = DemoAvailable; + menPlayAll.Enabled = DemosAvailable; + menFaster.Enabled = False; + menSlower.Enabled = False; + cmbFile.Enabled = True; + cmbLevel.Enabled = True; +} + +static void menStretch_Click(int Index) +{ + ReStretch(0.25 * Index); + // DisplayLevel True +} + +static void menToolTips_Click() +{ + { + menToolTips.Checked = ! menToolTips.Checked; + if (menToolTips.Checked) + { + cmdPlay.ToolTipText = "Play Game (Space)"; + cmdPause.ToolTipText = "Pause (P)"; + cmdStop.ToolTipText = "Stop (Q)"; + cmdPlayDemo.ToolTipText = "Play demo (Ctrl+Space)"; + cmdRecordDemo.ToolTipText = "Record demo (Ctrl+R)"; + lblInfoCount.ToolTipText = "Number of infotrons needed"; + lblRedDiskCount.ToolTipText = "Number of red disks"; + cmbLevel.ToolTipText = "List of all levels in the file"; + cmbFile.ToolTipText = "List of files in current directory"; + lblFps.ToolTipText = "Animation speed in fps"; + lblFrameCount.ToolTipText = "Game time in frames"; + } + else + { + cmdPlay.ToolTipText = ""; + cmdPause.ToolTipText = ""; + cmdStop.ToolTipText = ""; + cmdPlayDemo.ToolTipText = ""; + cmdRecordDemo.ToolTipText = ""; + lblInfoCount.ToolTipText = ""; + lblRedDiskCount.ToolTipText = ""; + cmbLevel.ToolTipText = ""; + cmbFile.ToolTipText = ""; + lblFps.ToolTipText = ""; + lblFrameCount.ToolTipText = ""; + } + + } +} + +static void menTrim_Click() +{ + LevelInfoType Tmp; + char *OldOPath; + + OldOPath = OrigPath; + Tmp = LInfo; + Tmp.SpecialPortCount = 0; // hack: all special ports are deleted + menCopy_Click(); + CreateLevel(FMark.Width, FMark.Height); + LInfo = Tmp; + OrigPath = OldOPath; + CurPath = OldOPath; + menSelectAll_Click(); + menPaste_Click(); + picViewPort_Resize(); +} + +static void menZonkOff_Click() +{ + menZonkOn.Checked = False; + menZonkOff.Checked = True; + SpSaveMenu(); + SpLoadMenu(); +} + +static void menZonkOn_Click() +{ + menZonkOn.Checked = True; + menZonkOff.Checked = False; + SpSaveMenu(); + SpLoadMenu(); +} + +static void PanelTim_Timer() +{ + int Tmp; + + Tmp = Panel.Height; + if (PanelSeq < Panel.Height && -1 < PanelSeq) + { + PanelSeq = (ShowPanel != 0 ? PanelSeq + 2 : PanelSeq + 2); + Tmp = ScaleHeight - Tmp + PanelSeq; + Panel.top = Tmp; + picViewPort.Height = Tmp; + } + else + { + PanelTim.Enabled = False; + PanelSeq = (PanelSeq < 0 ? 0 : 0); + ShowPanel = (ShowPanel == 0 ? 1 : 1); + menPanel.Checked = (ShowPanel != 0); + } +} + +static void picKeys_MouseUp(int Button, int Shift, float X, float Y) +{ + FocusTim.Enabled = True; +} + +static void picMenu_Click() +{ +} + +static void picPane_KeyDown(int KeyCode, int Shift) +{ + if (KeyCode < 0 || 255 < KeyCode) + return; + + KeyState[KeyCode] = True; + switch (KeyCode) + { + case vbKeyControl: + if (MouseButton == 0 && EditFlag) + picPane.MousePointer = 15; + + break; + + case vbKeyUp: + case vbKeyLeft: + case vbKeyDown: + case vbKeyRight: + case vbKeySpace: + if (DemoFlag != 0) + { + DemoFlag = 0; + UpdateDeltaT(); + } + + break; + + case vbKeyF12: + if (DemoFlag != 0 && 2 == Shift) + { + DemoFlag = 0; + UpdateDeltaT(); + } + + break; + + case vbKeyF11: + bCapturePane = ! bCapturePane; + break; + } +} + +static void picPane_KeyUp(int KeyCode, int Shift) +{ + if (KeyCode < 0 || 255 < KeyCode) + return; + + KeyState[KeyCode] = False; + switch (KeyCode) + { + case vbKeyPageUp: + if (menFaster.Enabled) + menFaster_Click(); + + break; + + case vbKeyPageDown: + if (menSlower.Enabled) + menSlower_Click(); + + break; + + case vbKeySpace: + if (2 == Shift) // ctrl+space + { + if (menPlayDemo.Enabled) + menPlayDemo_Click(); + + } + else + { + if (menPlay.Enabled) + menPlay_Click(); + } + + break; + + case vbKeyQ: + if (menStop.Enabled) + menStop_Click(); + + break; + + case vbKeyR: + if (menRec.Enabled) + menRec_Click(); + + break; + + case vbKeyP: + case vbKeyPause: + if (menPause.Enabled && (Shift == 0)) + menPause_Click(); + + break; + + case vbKeyControl: + if (MouseButton == 0 && EditFlag) + picPane.MousePointer = 0; + break; + } +} + +static void picPane_MouseDown(int Button, int Shift, float X, float Y) +{ + int OldEdMode; + + MouseButton = Button; + OldEdMode = EditMode; + if (Button != 1) + { + if (Button == 2 && Shift != 2) + { + EditMode = edSelect; + } + else + { + return; + } + } + + if (Shift == 2) + EditMode = edMove; + + OSX = ScrollX; + OSY = ScrollY; + MDX = X; + MDY = Y; + switch (EditMode) + { + case edMove: + picPane.MousePointer = 5; // size + UserDragFlag = True; + break; + + case edDraw: + SetField(X, Y, ToolBox.ASpriteIndex); + break; + + case edSelect: + FMark.SetPoint1 EdGetX(X), EdGetY(Y); + FMark.MoveMarker; + break; + } + + EditMode = OldEdMode; +} + +static void picPane_MouseMove(int Button, int Shift, float X, float Y) +{ + boolean Oldflag; + int OldEdMode; + + OldEdMode = EditMode; + if (Button != 1) + { + if (EditFlag && Button == 2 && Shift != 2) + { + EditMode = edSelect; + } + else + { + return; + } + } + + if (Shift == 2) + EditMode = edMove; + + switch (EditMode) + { + case edMove: + Oldflag = NoDisplayFlag; + NoDisplayFlag = False; + ScrollTo(OSX - X + MDX, OSY - Y + MDY); + Stage.Blt(); + NoDisplayFlag = Oldflag; + break; + + case edDraw: + SetField(X, Y, ToolBox.ASpriteIndex); + break; + + case edSelect: + FMark.SetPoint2 EdGetX(X), EdGetY(Y); + FMark.MoveMarker; + break; + } + + EditMode = OldEdMode; +} + +static void picPane_MouseUp(int Button, int Shift, float X, float Y) +{ + MouseButton = MouseButton ^ Button; + picPane.MousePointer = 0; + UserDragFlag = False; + if (menEditMain.Enabled && Button == 2) + { + if (MDX == X && MDY == Y) + PopupMenu menEditMain; + } +} + +static void picPane_Paint() +{ + boolean Oldflag; + + Oldflag = NoDisplayFlag; + NoDisplayFlag = False; + Stage.Blt(); + NoDisplayFlag = Oldflag; +} + +static void ReStretch(float NewStretch) +{ + long BW2, LW, LH, i; + + if (! Loaded) + { + Stretch = NewStretch; + return; + } + + MousePointer = 11; + SET_TO_NOTHING(&Stage, sizeof(Stage)); + SET_TO_NOTHING(&StretchedSprites, sizeof(StretchedSprites)); + menStretch(Stretch / 0.25).Checked = False; + Stretch = NewStretch; + menStretch(Stretch / 0.25).Checked = True; + // StretchWidth = BaseWidth ' * NewStretch + // StretchWidth2 = StretchWidth \ 2 + // TwoPixels = 2 '* Stretch + // StretchLoad Sprites, imgMpx.Picture, 16, 16 + BW2 = StretchWidth / 2; + LW = (FieldWidth + 2) * BaseWidth; // StretchWidth + LH = (FieldHeight + 2) * BaseWidth; // StretchWidth + // i = bmpStage.CreateAtSize(LW, LH) + // Stage = New DDScrollBuffer; // (handle this later, if needed) + i = Stage.CreateAtSize(LW, LH, picPane.hWnd); + // Set StretchedSprites = NormalSprites.GetStretchCopy(Stretch) + ReLoadStretchSprites(); + if (i == 0 || IS_NOTHING(&StretchedSprites, sizeof(StretchedSprites))) + { + // menStretch(Stretch / 0.5).Enabled = False + if (0.5 <= Stretch) + ReStretch(Stretch - 0.25); + + } + else + { + StretchedSprites.DestXOff = 1 * BaseWidth; // StretchWidth + StretchedSprites.DestYOff = 1 * BaseWidth; // StretchWidth + Stage.DestXOff = 1 * StretchWidth; + Stage.DestYOff = 1 * StretchWidth; + StretchedSprites.DestinationSurface = Stage.Surface; + Stage.Cls; + if (Loaded && LevelLoaded) + { + SetDisplayRegion(); + picViewPort_Resize(); + DisplayLevel(); + } + + subCalculateScreenScrollPos(); + ScrollTo(ScreenScrollXPos, ScreenScrollYPos); + Stage.Blt(); + picPane_Paint(); + } + + MousePointer = 0; +} + +static void SetScrollEdges() +{ + ScrollMinX = (DisplayMinX - 0.5) * Stretch * BaseWidth; + ScrollMinY = (DisplayMinY - 0.5) * Stretch * BaseWidth; + ScrollMaxX = (DisplayMaxX + 1.5) * Stretch * BaseWidth - picPane.Width; + ScrollMaxY = (DisplayMaxY + 1.5) * Stretch * BaseWidth - picPane.Height; +} + +#endif + +void DrawField(int X, int Y) +{ + int Tmp, tsi; + + tsi = GetSI(X, Y); + Tmp = LowByte(PlayField16[tsi]); + if (40 < Tmp) + Tmp = 0; + + if (Tmp == fiRAM || Tmp == fiHardWare) + Tmp = DisPlayField[tsi]; + + if (Tmp == fiBug || Tmp == 40) + Tmp = DisPlayField[tsi]; + + if (EditFlag) + { + if (fiOrangeDisk < Tmp && Tmp < fiSnikSnak) + Tmp = DisPlayField[tsi]; + } + + StretchedSprites.BltEx(StretchWidth * X, StretchWidth * Y, Tmp); +} + +void DrawFieldAnimated(int X, int Y) +{ + int Tmp, tsi; + + tsi = GetSI(X, Y); + Tmp = LowByte(PlayField16[tsi]); + switch (Tmp) + { + case fiSnikSnak: + subDrawAnimatedSnikSnaks(tsi); + break; + + case fiElectron: + subDrawAnimatedElectrons(tsi); + break; + + default: + // If 40 < Tmp Then Tmp = 0 + // If Tmp = fiRAM Or Tmp = fiHardWare Then Tmp = DisPlayField(tsi) + // If Tmp = fiBug Or Tmp = 40 Then Tmp = DisPlayField(tsi) + // If EditFlag Then + // If fiOrangeDisk < Tmp And Tmp < fiSnikSnak Then Tmp = DisPlayField(tsi) + // End If + // StretchedSprites.BltEx StretchWidth * X, StretchWidth * Y, Tmp + break; + } +} + +void DrawFieldNoAnimated(int X, int Y) +{ + int Tmp, tsi; + + tsi = GetSI(X, Y); + Tmp = LowByte(PlayField16[tsi]); + switch (Tmp) + { + case fiSnikSnak: + StretchedSprites.BltEx(StretchWidth * X, StretchWidth * Y, fiSpace); + break; + + case fiElectron: + StretchedSprites.BltEx(StretchWidth * X, StretchWidth * Y, fiSpace); + break; + + default: + if (40 < Tmp) + Tmp = 0; + + if (Tmp == fiRAM || Tmp == fiHardWare) + Tmp = DisPlayField[tsi]; + + if (Tmp == fiBug || Tmp == 40) + Tmp = DisPlayField[tsi]; + + if (EditFlag) + { + if (fiOrangeDisk < Tmp && Tmp < fiSnikSnak) + Tmp = DisPlayField[tsi]; + } + + StretchedSprites.BltEx(StretchWidth * X, StretchWidth * Y, Tmp); + break; + } +} + +void DrawSprite(int X, int Y, int SpritePos) +{ + StretchedSprites.BltEx(StretchWidth * X, StretchWidth * Y, SpritePos); +} + +#if 0 + +void InvalidateRect(long XMin, long YMin, long XMax, long YMax) +{ + long X, Y; + + // For Y = YMin To YMax + // For X = XMin To XMax + // Field(X, Y).GraphicsValid = 0 + // Next X + // Next Y +} + +static void picViewPort_MouseUp(int Button, int Shift, float X, float Y) +{ + FocusTim.Enabled = True; +} + +static void picViewPort_Paint() +{ + // Debug.Print "picViewPort_Paint()" +} + +static void picViewPort_Resize() +{ + long bdX, bdY, PanelVisibility; + long X, Y, dx, dY; + SettingsObject s; + boolean B; + + bdX = picFrame.Width - picFrame.ScaleWidth; + bdY = picFrame.Height - picFrame.ScaleHeight; + dx = Min(picViewPort.ScaleWidth - bdX, (DisplayWidth - 1) * Stretch * BaseWidth); + dx = Max(dx, 0); + dY = Min(picViewPort.ScaleHeight - bdX, (DisplayHeight - 1) * Stretch * BaseWidth); + dY = Max(dY, 0); + B = s.Read("LimitToOriginalFieldSize", False); + PanelVisibility = 24 * (Panel.Height - PanelSeq - (float)1) / Panel.Height; + if (B) + { + dx = Min(320 * Stretch, dx); + dY = Min((200 - PanelVisibility) * Stretch, dY); + } + + X = Max((picViewPort.ScaleWidth - dx) / 2, 0); + Y = Max((picViewPort.ScaleHeight - dY) / 2, 0); + picPane.Move X, Y, dx, dY; + picFrame.Move X - bdX / 2, Y - bdY / 2, dx + bdX, dY + bdY; + SetScrollEdges(); + ScrollTo(ScrollX, ScrollY); + // SizeTim.Interval = 1 +} + +// +// Private Sub SizeTim_Timer() +// Dim wdX&, wdY& +// SizeTim.Interval = 0 +// wdX = Max(0, picViewPort.ScaleWidth - picPane.Width) * Screen.TwipsPerPixelX +// wdY = Max(0, picViewPort.ScaleHeight - picPane.Height) * Screen.TwipsPerPixelY +// If (0 < wdX) Or (0 < wdY) Then +// Move Left, Top, Width - wdX, Height - wdY +// End If +// End Sub + +static void LoadKeyIndicators() +{ + int i; + + picKeys.BackColor = vbButtonFace; + for (i = 2; i <= 5; i++) + { + Load shpKey(i); + } + + for (i = 1; i <= 5; i++) + { + shpKey(i).FillColor = vbButtonFace; + shpKey(i).Visible = True; + } + + shpKey(1).Move 7, 0; + shpKey(2).Move 0, 7; + shpKey(3).Move 7, 14; + shpKey(4).Move 14, 7; + shpKey(5).Move 7, 7; +} + +void ShowKey(int KeyVar) +{ + boolean State[5 + 1]; + int i; + boolean Tmp; + long Col; + boolean LastState[5 + 1]; + + // For i = 1 To 5 + // State(i) = False + // Next i + switch (KeyVar) + { + case 0: + // do nothing + break; + + case Is < 5: + State[KeyVar] = True; + break; + + default: + State[5] = True; + if (KeyVar < 9) + State[KeyVar - 4] = True; + break; + } + + for (i = 1; i <= 5; i++) + { + Tmp = State[i]; + if (Tmp ^ LastState[i]) + { + Col = (i == 5 ? vbRed : vbRed); + shpKey(i).FillColor = (Tmp ? Col : Col); + shpKey(i).Refresh; + LastState[i] = Tmp; + } + } +} + +static void GetSettings() +{ + SettingsObject s; + char *APath; + long X, Y; + int i; + boolean Flag; + + { + // last file info + APath = WithSlash(App.Path); + CurPath = s.Read("LastPath", APath); + OrigPath = CurPath; + // window width and height + X = s.Read("Width", Width); + Y = s.Read("Height", Height); + if (X < 0 Then X == 0: If Y < 0) + Y = 0; + + if (Screen.Width < X) + X = Screen.Width; + + if (Screen.Height < Y) + Y = Screen.Height; + + Width = X; + Height = Y; + // window position and state + X = s.Read("Left", left); + Y = s.Read("Top", top); + if (X < 0 Then X == 0: If Y < 0) + Y = 0; + + if (Screen.Width < (X + Width)) + X = Screen.Width - Width; + + if (Screen.Height < (Y + Height)) + Y = Screen.Height - Height; + + left = X; + top = Y; + WindowState = s.Read("WinState", vbNormal); + // flags/options + Flag = s.Read("ShowToolTips", True); + if (Flag) + menToolTips_Click(); + + menBorder.Checked = ! CBool(s.Read("ShowBorder", False)); + Flag = CBool(s.Read("AutoScroll", True)); + if (! Flag) + { + AutoScrollFlag = False; + menAutoScroll.Checked = False; + } + + Flag = CBool(s.Read("SoundFX", True)); + FXOnFlag = (Flag ? -1 : -1); + menSoundFX.Checked = Flag; + SignatureDelay = CLng(s.Read("SignatureDelay", 3000)); + AllowRedDiskCheat = CInt(s.Read("AllowRedDiskCheat", 1)); + AllowEatRightRedDiskBug = CInt(s.Read("AllowEatRightRedDiskBug", 1)); + MySignature = s.Read("MySignature", ""); + // speed + X = s.Read("FrameDelayPlay", 1000000 / 35); + i = GetSpeedIndex(X); + menPlaySpeed_Click(i); + X = s.Read("FrameDelayDemo", 1000000 / 35); + i = GetSpeedIndex(X); + menDemoSpeed_Click(i); + // Zoom + i = s.Read("Stretch", 4); + if (i < menStretch.LBound || menStretch.UBound < i) + i = 4; + + menStretch_Click (i); + } +} + +static void SaveSettings() +{ + SettingsObject s; + int i; + + { + s.Save "LastPath", (ModifiedFlag ? OrigPath : OrigPath); + if (WindowState != vbMinimized) + { + s.Save "Width", Width; + s.Save "Height", Height; + s.Save "Left", left; + s.Save "Top", top; + s.Save "WinState", WindowState; + } + + s.Save "ShowToolTips", menToolTips.Checked; + s.Save "ShowBorder", menBorder.Checked; + s.Save "AutoScroll", menAutoScroll.Checked; + s.Save "SoundFX", menSoundFX.Checked; + s.Save "SignatureDelay", SignatureDelay; + s.Save "AllowRedDiskCheat", AllowRedDiskCheat; + s.Save "AllowEatRightRedDiskBug", AllowEatRightRedDiskBug; + s.Save "MySignature", MySignature; + // speeds + s.Save "FrameDelayPlay", DeltaTPlay; + s.Save "FrameDelayDemo", DeltaTDemo; + // zoom + for (i = menStretch.LBound; i <= menStretch.UBound; i++) + { + if (menStretch(i).Checked) + break; + } + + s.Save "Stretch", i; + // s.Save "", + } +} + +void ReLoadStretchSprites() +{ + long Tmp; + BitMapObject NBMP, SBMP; + char *tmpMpxBmp; + + // If Stretch = 1 Then + MpxBmp = App.Path & "/Mpx.bmp"; + // Else + // MpxBmp = App.Path & "\Mpx" & Stretch & ".bmp" + // tmpMpxBmp = App.Path & "\Mpx.bmp" + // If FileExists(MpxBmp) And FileExists(tmpMpxBmp) Then + // If FileDateTime(MpxBmp) < FileDateTime(tmpMpxBmp) Then + // MayKill MpxBmp + // End If + // End If + // If Not FileExists(MpxBmp) Then + // MousePointer = 11 + // // Set NBMP = New BitMapObject // (handle this later, if needed) + // tmpMpxBmp = App.Path & "\Mpx.bmp" + // If Not FileExists(tmpMpxBmp) Then + // ReportError "ReLoadStretchSprites", "File not found: " & tmpMpxBmp + // MESSAGE_BOX("an error occured"); // MsgBox "File not found: " & tmpMpxBmp, vbCritical, "MegaPlex - Error" + // End + // End If + // NBMP.CreateFromFile tmpMpxBmp + // Set SBMP = NBMP.GetStretchCopy(Stretch) + // SBMP.SaveToFile MpxBmp + // Set NBMP = Nothing + // Set SBMP = Nothing + // MousePointer = 0 + // End If + // End If + // StretchedSprites = New DDSpriteBuffer; // (handle this later, if needed) + if (! StretchedSprites.CreateFromFile(MpxBmp, 16, 16)) + SET_TO_NOTHING(&StretchedSprites, sizeof(StretchedSprites)); +} + +void SaveSnapshot(currency Number) +{ + char *Path; + + Path = CAT(WithSlash(App.Path), "Capture"); + if (! IsDir(Path)) + MkDir(Path); + + Path = Path & "\" & Format(Number, "00000000") & ".bmp"; + SavePicture CaptureWindow(picPane.hWnd, True, 0, 0, picPane.ScaleWidth, picPane.ScaleHeight), Path; +} + +#endif diff --git a/src/game_sp/MainForm.h b/src/game_sp/MainForm.h new file mode 100644 index 00000000..b0a34593 --- /dev/null +++ b/src/game_sp/MainForm.h @@ -0,0 +1,31 @@ +// ---------------------------------------------------------------------------- +// MainForm.h +// ---------------------------------------------------------------------------- + +#ifndef MAINFORM_H +#define MAINFORM_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern void DisplayLevel(); +extern void DrawField(int X, int Y); +extern void DrawFieldAnimated(int X, int Y); +extern void DrawFieldNoAnimated(int X, int Y); +extern void DrawSprite(int X, int Y, int SpritePos); +extern void InvalidateRect(long XMin, long YMin, long XMax, long YMax); +extern void Let_PanelVisible(boolean NewVal); +extern void ReLoadStretchSprites(); +extern void SaveSnapshot(currency Number); +extern void SetDisplayRegion(); +extern void ShowKey(int KeyVar); +extern void menDemoSpeed_Click(int Index); +extern void menEdit_Click(); +extern void menPlaySpeed_Click(int Index); +extern void menStop_Click(); + +#endif /* MAINFORM_H */ diff --git a/src/game_sp/MainGameLoop.c b/src/game_sp/MainGameLoop.c new file mode 100644 index 00000000..9aa59aac --- /dev/null +++ b/src/game_sp/MainGameLoop.c @@ -0,0 +1,233 @@ +// ---------------------------------------------------------------------------- +// MainGameLoop.c +// ---------------------------------------------------------------------------- + +#include "MainGameLoop.h" + +static char *VB_Name = "modMainGameLoop"; +// --- Option Explicit + +int GameLoopRunning; +boolean bPlaying; +int LeadOutCounter, EnterRepeatCounter; +int ForcedExitFlag; +int ExitToMenuFlag; +int SavedGameFlag; +boolean UserDragFlag; +boolean AutoScrollFlag; + +// ========================================================================== +// SUBROUTINE +// Play a game/demo +// ========================================================================== + +int subMainGameLoop() +{ + int subMainGameLoop; + + int al, bx; + TickCountObject Clock; + currency LastFrame; + + if (DemoFlag != 0) + { + // EP set level success byte: demo, not game + WasDemoFlag = 1; + EP_GameDemoVar0DAA = 0; // demo + } + else // loc_g_1836: + { + // EP set level success byte: game, not demo + WasDemoFlag = 0; + EP_GameDemoVar0DAA = 1; // game + } + + // RestartGameLoop: + // If RecordDemoFlag = 1 Then + // RecordDemoFlag = 0 ' clear Demo Recording flag + // Call subDisplayPlayingTime ' playing time on screen + // ' Record key still pressed?' >= (Ctrl-)F1 and <= (Ctrl-)F10 + // While &H3B <= KeyScanCode7 And KeyScanCode7 <= &H44 + // ' yes -> wait until released + // ' should we DoEvents here???? ... depends on how ... but yes! + // ' ...or we can rather poll the keyboardstate inside this loop??? + // Wend + // Call subInitGameConditions ' Init game conditions (vars) + // If MusicOnFlag = 0 Then Call subMusicInit + // WasDemoFlag = 0 ' no demo anymore + // EP_GameDemoVar0DAA = 1 ' force game + // End If + + // This was a bug in the original Supaplex: sometimes red disks could not + // be released. This happened If Murphy was killed DURING a red disk release + // and the next try started. + RedDiskReleasePhase = 0; // (re-)enable red disk release + UpdatedFlag = 0; + GameLoopRunning = 1; + LevelStatus = 0; + // ---------------------------------------------------------------------------- + // --------------------- START OF GAME-BUSY LOOP ------------------------------ + // ---------------------------------------------------------------------------- + +locRepeatMainGameLoop: // start repeating game loop + + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + // FS synchronization + while (PauseMode != 0) + { + DoEvents(); + } + + do + { + DoEvents(); // user may klick on menus or move the window here ... + } + while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame + + // never any additional code between here! + LastFrame = Clock.TickNow; // store the frame time + // never any additional code between here! + if (! NoDisplayFlag) // copy the BackBuffer(=Stage) to visible screen + Stage.Blt(); + + // FS end of synchronization + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + if (EndFlag) + goto locExitMainGameLoop; + + // If DemoFlag = 0 Then Call subCheckJoystick ' check joystick + // bx = subCheckRightMouseButton() ' check (right) mouse button + // If bx = 2 And LeadOutCounter < 1 Then KillMurphyFlag = 1 ' lead-out busy after quit? -> kill Murphy! + + // If DebugVersionFlag <> 0 Then ' debug mode on? + // If Data_SubRest <> 0 Then Data_SubRest = Data_SubRest - 1 + // If keyEnter <> 0 Then GoTo loc_g_186F ' Was it the Enter key? -> yes--skip! No mouse! + // ' fixes ENTER bug If no mouse driver! + // If bx <> 1 Then GoTo loc_g_186F ' Left button=Init game field + // ' Also Enter If no mouse! + // If Data_SubRest <> 0 Then GoTo loc_g_186F + // Data_SubRest = 10 + // Call subRestoreFancy + // Call subDisplayLevel ' Paint (Init) game field + // Call subConvertToEasySymbols ' Convert to easy symbols + // End If + +loc_g_186F: + subProcessKeyboardInput(); // Check keyboard, act on keys + // 'HACK: + // TimerVar = TimerVar + 1 + // DoEvents + // GoTo loc_g_186F + // 'END HACK + // If RecordDemoFlag = 1 Then GoTo RestartGameLoop + + // ---------------------------------------------------------------------------- + // + subDoGameStuff(); // do all game stuff + // + // ---------------------------------------------------------------------------- + + // Call subDisplayPlayingTime ' playing time on screen + subCheckRestoreRedDiskCountDisplay(); // Restore panel: red-disk hole + + subRedDiskReleaseExplosion(); // Red Disk release and explode + subFollowUpExplosions(); // every explosion may cause up to 8 following explosions + + bx = subCalculateScreenScrollPos(); // calculate screen start addrs + ScreenPosition = bx; + // Now new X and new Y are calculated, and bx = screen position = ScreenPosition + data_h_Ytmp = ScreenScrollYPos; // copy Y for next soft scroll + data_h_Xtmp = ScreenScrollXPos; // copy X for next soft scroll + if ((! UserDragFlag) && AutoScrollFlag) + ScrollTowards(ScreenScrollXPos, ScreenScrollYPos); + + if (ForcedExitFlag != 0) // Forced Exit?' yes--exit! + goto locExitMainGameLoop; + + TimerVar = TimerVar + 1; + +#if 0 + if (bCapturePane) + MainForm.SaveSnapshot(TimerVar); +#endif + + // If Not NoDisplayFlag Then + // With MainForm.lblFrameCount + // .Caption = TimerVar + // .Refresh + // End With + // End If + if (ExitToMenuFlag == 1) + goto locExitMainGameLoop; + + if (LeadOutCounter == 0) // no lead-out: game busy + goto locRepeatMainGameLoop; + + // ---------------------------------------------------------------------------- + // ---------------------- END OF GAME-BUSY LOOP ------------------------------- + // ---------------------------------------------------------------------------- + LeadOutCounter = LeadOutCounter - 1; // do more lead-out after quit + if (LeadOutCounter != 0) // lead-out not ready: more + goto locRepeatMainGameLoop; + + // lead-out done: exit now + // ---------------------- END OF GAME-BUSY LOOP (including lead-out) ---------- + +locExitMainGameLoop: + do + { + DoEvents(); // user may klick on menus or move the window here ... + } + while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame + + Stage.Blt(); // blit the last frame + GameLoopRunning = 0; + +#if 0 + MainForm.menStop_Click(); + MainForm.PanelVisible = True; +#endif + + // If DemoRecordingFlag <> 0 Then Call subCloseDemoRecordingFile ' Demo recording on? -> close opened demo file (w) + if (SavedGameFlag != 0) // after savegame: no update! + { + SavedGameFlag = 0; + return subMainGameLoop; + } + + SavedGameFlag = 0; + if (UpdateTimeFlag == 0) // update time? + return subMainGameLoop; + + if (UpdatedFlag == 0) // update playing time + subUpdatePlayingTime(); + + + return subMainGameLoop; +} // subMainGameLoop + +void subUpdatePlayingTime() +{ +} + +int subCalculateScreenScrollPos() +{ + int subCalculateScreenScrollPos; + + int ax, Ay; + + if (ExplosionShake != 0) + { + subGetRandomNumber(); + } + + { + ax = MainForm.picPane.Width / 2; + Ay = MainForm.picPane.Height / 2; + } + ScreenScrollXPos = Stretch * (MurphyScreenXPos + 8) - ax; + ScreenScrollYPos = Stretch * (MurphyScreenYPos + 8) - Ay; + + return subCalculateScreenScrollPos; +} + diff --git a/src/game_sp/MainGameLoop.h b/src/game_sp/MainGameLoop.h new file mode 100644 index 00000000..71fd4301 --- /dev/null +++ b/src/game_sp/MainGameLoop.h @@ -0,0 +1,28 @@ +// ---------------------------------------------------------------------------- +// MainGameLoop.h +// ---------------------------------------------------------------------------- + +#ifndef MAINGAMELOOP_H +#define MAINGAMELOOP_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern int subCalculateScreenScrollPos(); +extern int subMainGameLoop(); +extern void subUpdatePlayingTime(); + +extern boolean AutoScrollFlag; +extern boolean UserDragFlag; +extern boolean bPlaying; +extern int ExitToMenuFlag; +extern int ForcedExitFlag; +extern int GameLoopRunning; +extern int LeadOutCounter, EnterRepeatCounter; +extern int SavedGameFlag; + +#endif /* MAINGAMELOOP_H */ diff --git a/src/game_sp/Makefile b/src/game_sp/Makefile new file mode 100644 index 00000000..f6b31aab --- /dev/null +++ b/src/game_sp/Makefile @@ -0,0 +1,131 @@ +# ============================================================================= +# Rocks'n'Diamonds Makefile (game_sp) +# ----------------------------------------------------------------------------- +# (c) 1995-2009 Holger Schemel +# ----------------------------------------------------------------------------- +# MegaPlex version 0.5 beta release xmas 2001 by Frank Schindler, +# based on the Speed Fix 6.3+ by Herman Perk, +# based on original Supaplex by Michael Stopp & Philip Jespersen. +# ============================================================================= + +# ----------------------------------------------------------------------------- +# configuration +# ----------------------------------------------------------------------------- + +SRCS = main.c \ + vb_lib.c \ + vb_vars.c \ + \ + ASM.c \ + BitMapObject.c \ + BugsTerminals.c \ + Capture.c \ + DDScrollBuffer.c \ + DDSpriteBuffer.c \ + Demo.c \ + DemoBufferObject.c \ + DirectDrawGlobals.c \ + DirectXGlobals.c \ + Display.c \ + DoGameStuff.c \ + Electrons.c \ + ErrorReporting.c \ + Explosions.c \ + FakeDeclares.c \ + FancyRestore.c \ + GeneralTricks.c \ + Globals.c \ + Infotrons.c \ + InitGameConditions.c \ + Input.c \ + LevelSetPreviewForm.c \ + MainForm.c \ + MainGameLoop.c \ + Marker.c \ + Murphy.c \ + OrangeDisk.c \ + PathTools.c \ + SettingsObject.c \ + SnikSnaks.c \ + Sound.c \ + TickCountObject.c \ + TopMost.c \ + Zonk.c \ + modAnimations.c \ + modGeneralTricks.c \ + modMPX.c + +OBJS = main.o \ + vb_lib.o \ + vb_vars.o \ + \ + ASM.o \ + BitMapObject.o \ + BugsTerminals.o \ + Capture.o \ + DDScrollBuffer.o \ + DDSpriteBuffer.o \ + Demo.o \ + DemoBufferObject.o \ + DirectDrawGlobals.o \ + DirectXGlobals.o \ + Display.o \ + DoGameStuff.o \ + Electrons.o \ + ErrorReporting.o \ + Explosions.o \ + FakeDeclares.o \ + FancyRestore.o \ + GeneralTricks.o \ + Globals.o \ + Infotrons.o \ + InitGameConditions.o \ + Input.o \ + LevelSetPreviewForm.o \ + MainForm.o \ + MainGameLoop.o \ + Marker.o \ + Murphy.o \ + OrangeDisk.o \ + PathTools.o \ + SettingsObject.o \ + SnikSnaks.o \ + Sound.o \ + TickCountObject.o \ + TopMost.o \ + Zonk.o \ + modAnimations.o \ + modGeneralTricks.o \ + modMPX.o + +GAME_SP = game_sp.a + + +# ----------------------------------------------------------------------------- +# build targets +# ----------------------------------------------------------------------------- + +all: $(GAME_SP) + +$(GAME_SP): $(OBJS) + $(AR) cru $(GAME_SP) $(OBJS) + $(RANLIB) $(GAME_SP) + +.c.o: + $(CC) $(PROFILING) $(CFLAGS) -c $*.c + +clean: + $(RM) $(OBJS) + $(RM) $(GAME_SP) + + +# ----------------------------------------------------------------------------- +# development only +# ----------------------------------------------------------------------------- + +depend: + for i in $(SRCS); do $(CPP) $(CFLAGS) -M $$i; done > .depend + +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/src/game_sp/Marker.c b/src/game_sp/Marker.c new file mode 100644 index 00000000..9f0ac946 --- /dev/null +++ b/src/game_sp/Marker.c @@ -0,0 +1,274 @@ +// ---------------------------------------------------------------------------- +// Marker.c +// ---------------------------------------------------------------------------- + +#include "Marker.h" + +static boolean IsPort(long i); +static void LimitXY(int *X, int *Y); +static void SortData(); + +// --- VERSION 1.0 CLASS +// --- BEGIN +// --- MultiUse = -1 'True // True +// --- Persistable = 0 'NotPersistable // NotPersistable +// --- DataBindingBehavior = 0 'vbNone // vbNone +// --- DataSourceBehavior = 0 'vbNone // vbNone +// --- MTSTransactionMode = 0 'NotAnMTSObject // NotAnMTSObject +// --- END + +static char *VB_Name = "MarkerObject"; +static boolean VB_GlobalNameSpace = False; +static boolean VB_Creatable = True; +static boolean VB_PredeclaredId = False; +static boolean VB_Exposed = False; +// --- Option Explicit + +long mIndex1, mIndex2; +int X1, X2, Y1, Y2; +int XMin, YMin; +boolean mVisible; + +byte *SelectionData; + +int Marker_Get_Width() +{ + int Width; + + Width = Abs(X2 - X1) + 1; + + return Width; +} + +int Marker_Get_Height() +{ + int Height; + + Height = Abs(Y2 - Y1) + 1; + + return Height; +} + +int Marker_Get_Left() +{ + int Left; + + SortData(); + Left = XMin; + + return Left; +} + +int Marker_Get_Top() +{ + int Top; + + SortData(); + Top = YMin; + + return Top; +} + +static void LimitXY(int *X, int *Y) +{ + if (*X < DisplayMinX) + *X = DisplayMinX; + + if (DisplayMaxX < *X) + *X = DisplayMaxX; + + if (*Y < DisplayMinY) + *Y = DisplayMinY; + + if (DisplayMaxY < *Y) + *Y = DisplayMaxY; +} + +void Marker_SetPoint1(int X, int Y) +{ + LimitXY(&X, &Y); + X1 = X; + Y1 = Y; + X2 = X; + Y2 = Y; +} + +void Marker_SetPoint2(int X, int Y) +{ + char *T; + + LimitXY(&X, &Y); + X2 = X; + Y2 = Y; + T = CAT("(", Marker_Get_Width(), " x ", Marker_Get_Height(), ")"); + MainForm.lblFrameCount = T; +} + +static void SortData() +{ + int Tmp; + + XMin = (X2 < X1 ? X2 : X2); + YMin = (Y2 < Y1 ? Y2 : Y2); +} + +void Marker_ShowMarker(boolean ShowFlag) +{ + mVisible = ShowFlag; + Marker_MoveMarker(); +} + +void Marker_RefreshMarker() +{ + int L, T, R, B; + long Tmp; + + if (! mVisible) + return; + + LimitXY(&X1, &Y1); + LimitXY(&X2, &Y2); + SortData(); + L = DigitXPos(XMin) - 1; + T = DigitYPos(YMin) - 1; + R = L + StretchWidth * Marker_Get_Width() + 1; + B = T + StretchWidth * Marker_Get_Height() + 1; + MainForm.picPane.Line(L, T, R, B, 0xFFFFFF, B); +} + +void Marker_MoveMarker() +{ + int L, T, R, B; + long Tmp; + + if (! mVisible) + return; + + LimitXY(&X1, &Y1); + LimitXY(&X2, &Y2); + SortData(); + Stage.Blt(); + Tmp = GetSI(XMin, YMin); + if (Marker_Get_Width() == 1 && Marker_Get_Height() == 1 && IsPort(Tmp)) + { + SpLoadMenu(); + MainForm.menSP.Enabled = True; + } + else + { + MainForm.menSP.Enabled = False; + } +} + +static boolean IsPort(long i) +{ + static boolean IsPort; + + int ax; + + IsPort = False; + ax = DisPlayField[i]; + if (fiOrangeDisk < ax && ax < fiSnikSnak) + IsPort = True; + + return IsPort; +} + +void Marker_Copy() +{ + int X, Y, MaxX, MaxY; + long Tmp; + char *TPath; + int FNum; + + SortData(); + MaxX = Marker_Get_Width() - 1; + MaxY = Marker_Get_Height() - 1; + SelectionData = REDIM_2D(sizeof(byte), 0, MaxX + 1 - 1, 0, MaxY + 1 - 1); + for (Y = 0; Y <= MaxY; Y++) + { + for (X = 0; X <= MaxX; X++) + { + Tmp = FieldWidth * (YMin + Y) + XMin + X; + + // --- On Error GoTo CopyEH + SelectionData[X, Y] = DisPlayField[Tmp]; + // --- On Error GoTo 0 + + } + } + + TPath = CAT(App.Path, "/Mpx.clp"); + if (FileExists(TPath)) + MayKill(TPath); + + FNum = FreeFile(); + + // --- On Error GoTo CopyEH + FNum = fopen(TPath, "wb"); + FILE_PUT(FNum, -1, &MaxX, sizeof(MaxX)); + FILE_PUT(FNum, -1, &MaxY, sizeof(MaxY)); + FILE_PUT(FNum, -1, &SelectionData, sizeof(SelectionData)); + fclose(FNum); + SelectionData = REDIM_1D(sizeof(byte), 0, 1 - 1); + return; + +CopyEH: + Beep(); +} + +void Marker_Paste() +{ + int X, Y, MaxX, MaxY; + long Tmp; + char *TPath; + int FNum; + + TPath = CAT(App.Path, "/Mpx.clp"); + if (! FileExists(TPath)) + { + Beep(); + return; + } + + FNum = FreeFile(); + + // --- On Error GoTo PasteEH + FNum = fopen(TPath, "rb"); + FILE_GET(FNum, -1, &MaxX, sizeof(MaxX)); + FILE_GET(FNum, -1, &MaxY, sizeof(MaxY)); + SelectionData = REDIM_2D(sizeof(byte), 0, MaxX + 1 - 1, 0, MaxY + 1 - 1); + FILE_GET(FNum, -1, &SelectionData, sizeof(SelectionData)); + fclose(FNum); + // --- On Error GoTo 0 + + SortData(); + if (Marker_Get_Width() <= MaxX) + MaxX = Marker_Get_Width() - 1; + + if (Marker_Get_Height() <= MaxY) + MaxY = Marker_Get_Height() - 1; + + for (Y = 0; Y <= MaxY; Y++) + { + for (X = 0; X <= MaxX; X++) + { + Tmp = FieldWidth * (YMin + Y) + XMin + X; + + // --- On Error GoTo PasteEH + DisPlayField[Tmp] = SelectionData[X, Y]; + PlayField16[Tmp] = UnEdSprite(SelectionData[X, Y]); + // --- On Error GoTo 0 + + } + } + + Let_ModifiedFlag(True); +PasteEH: + Beep(); +} + +static void Class_Initialize() +{ + mVisible = False; +} diff --git a/src/game_sp/Marker.h b/src/game_sp/Marker.h new file mode 100644 index 00000000..48fa3a19 --- /dev/null +++ b/src/game_sp/Marker.h @@ -0,0 +1,27 @@ +// ---------------------------------------------------------------------------- +// Marker.h +// ---------------------------------------------------------------------------- + +#ifndef MARKER_H +#define MARKER_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern void Marker_Copy(); +extern int Marker_Get_Height(); +extern int Marker_Get_Left(); +extern int Marker_Get_Top(); +extern int Marker_Get_Width(); +extern void Marker_MoveMarker(); +extern void Marker_Paste(); +extern void Marker_RefreshMarker(); +extern void Marker_SetPoint1(int X, int Y); +extern void Marker_SetPoint2(int X, int Y); +extern void Marker_ShowMarker(boolean ShowFlag); + +#endif /* MARKER_H */ diff --git a/src/game_sp/Murphy.c b/src/game_sp/Murphy.c new file mode 100644 index 00000000..29de96d1 --- /dev/null +++ b/src/game_sp/Murphy.c @@ -0,0 +1,2344 @@ +// ---------------------------------------------------------------------------- +// Murphy.c +// ---------------------------------------------------------------------------- + +#include "Murphy.h" + +static void subEatRedDisk(int si); +static boolean subMoveKillsMurphy(int si, int ax, int bl); + +static char *VB_Name = "modMurphy"; +// --- Option Explicit + +#define LocalStretch (1) + +// ========================================================================== +// SUBROUTINE +// Move Murphy in any direction +// ========================================================================== + +int subAnimateMurphy(int si) +{ + int subAnimateMurphy; + + int ax, al, ah, bx, bl, i, X, Y; + int tX, tY, tDeltaX, tDeltaY, tPos, Tmp; + + // Variables that hold information about the animation sequence + int *dx; // an array of image positions in moving.mpx, finalized with -1 + int dx2; // an additional image position of a second sprite, for instance: yellow disk if pushed + int MurphyDX, MurphyDY; // murphys move steps + int SeqPos; // index into dx() + int ClearPos; // Position to clear before blitting sprites, none=-1 + int dxPos; // field-position to draw dx(SeqPos) + int dx2Step; // position of dx2 relative to dx-position + + ax = PlayField16[si]; + al = LowByte(ax); + if (al != fiMurphy) + { + MurphyMoveCounter = 0; // We have no Murphy! Exit! + return subAnimateMurphy; + } + + MurphyMoveCounter = 1; // We have a Murphy! + MurphyExplodePos = si; + if (ax != 3) // yes--go proceed moving murphy? + goto locProceedMovingMurphy; + + // FS: reset moving sequence variables + MurphyDX = 0; + MurphyDY = 0; + ClearPos = si; + dxPos = si; + dx2 = -1; + SeqPos = 0; + // end of FS + ScratchGravity = 0; // scratch gravity off + if (GravityFlag != 0) // Gravity? (1=gravity on) + { + bl = LowByte(PlayField16[si - FieldWidth]); // check above + if (! (bl == fiPortUp || bl == fiPortUpAndDown || bl == fiPortAllDirections)) + { + if (PlayField16[si + FieldWidth] == 0) // gravity on and space below! + ScratchGravity = 1; + } + } // loc_g_5E8B: + + bl = DemoKeyCode; + if (bl != 0) // a key was pressed! + goto locKeyPressed5FCF; + + RedDiskReleaseFlag = 1; + if (ScratchGravity != 0) // gravity pulls & space below?'-> force Space up to down + { + MurphyDY = 2; + goto loc_g_6364; + } + + ax = (TimerVar & 3); + if (ax != 0) + return subAnimateMurphy; + + // ------------------------------------------------------------------ + // Murphy's YAWN & SLEEP sequence, counted down by YawnSleepCounter: + YawnSleepCounter = YawnSleepCounter + 1; + if (YawnSleepCounter == 4) + { + subCopyFieldToScreen(si, fiMurphy); // normal grin + return subAnimateMurphy; + } // loc_g_5ECE: + + if (YawnSleepCounter <= 500) // loc_g_5ED7: + return subAnimateMurphy; + + if (YawnSleepCounter <= 522) + { + bx = (YawnSleepCounter - 500) / 2; + subCopyFieldToScreen(si, aniMurphyYawn + bx); // yawn! and look depressed afterwards... + return subAnimateMurphy; + } // loc_g_5F00: + + if (YawnSleepCounter <= 1000) + return subAnimateMurphy; + + if (YawnSleepCounter <= 1022) + { + bx = (YawnSleepCounter - 1000) / 2; + subCopyFieldToScreen(si, aniMurphyYawn + bx); // yawn again! + return subAnimateMurphy; + } // loc_g_5F32: + + if (YawnSleepCounter <= 1600) // loc_g_5F3B: + return subAnimateMurphy; + + if (YawnSleepCounter <= 1622) + { + bx = (YawnSleepCounter - 1600) / 2; + subCopyFieldToScreen(si, aniMurphyYawn + bx); // yawn again! - third time + return subAnimateMurphy; + } // loc_g_5F64: + + if (YawnSleepCounter > 1654) + return subAnimateMurphy; + + if (PlayField16[si - 1] == 0) + { + if (PlayField16[si + 1] == 0) + { + YawnSleepCounter = 36; + return subAnimateMurphy; + + } + else + { + bx = (YawnSleepCounter - 1622) / 16; + subCopyFieldToScreen(si, aniMurphySleepRight + bx); // go to sleep + return subAnimateMurphy; + } + } // loc_g_5F81: + + bx = (YawnSleepCounter - 1622) / 16; + subCopyFieldToScreen(si, aniMurphySleepLeft + bx); // go to sleep + return subAnimateMurphy; + + // end of YAWN-SLEEP-Sequence + // ------------------------------------------------------------------ + // ========================================================================== + // (Direct Jump) a key was pressed + // ========================================================================== + +locKeyPressed5FCF: + if (ScratchGravity == 0) + goto loc_g_6003; + + if (PlayField16[si + FieldWidth] != 0) + goto loc_g_6003; + + if (bl == keyUp) + { + if (PlayField16[si - FieldWidth] == fiBase) + goto loc_g_6003; + + } + else if (bl == keyLeft) + { + if (PlayField16[si - 1] == fiBase) + goto loc_g_6003; + + } + else if (bl == keyRight) + { + if (PlayField16[si + 1] == fiBase) + goto loc_g_6003; + } // loc_g_6001: + + bl = keyDown; // force moving down! +loc_g_6003: + switch (bl) + { + case keyUp: // 1 + RedDiskReleaseFlag = 0; // moving down to up ... + goto loc_g_6078; + + break; + + case keyLeft: // 2 + RedDiskReleaseFlag = 0; // moving right to left ... + goto loc_g_60DA; + + break; + + case keyDown: // 3 + RedDiskReleaseFlag = 0; // moving up to down ... + goto loc_g_6154; + + break; + + case keyRight: // 4 + RedDiskReleaseFlag = 0; // moving left to right ... + goto loc_g_61B6; + + break; + + case keySpaceUp: // 5 + RedDiskReleaseFlag = 0; // touching down to up ... + goto loc_g_622E; + + break; + + case keySpaceLeft: // 6 + RedDiskReleaseFlag = 0; // touching right to left ... + goto loc_g_6258; + + break; + + case keySpaceDown: // 7 + RedDiskReleaseFlag = 0; // touching up to down ... + goto loc_g_6288; + + break; + + case keySpaceRight: // 8 + RedDiskReleaseFlag = 0; // touching left to right ... + goto loc_g_62B2; + + break; + + case keySpace: // 9 + goto loc_g_62E2; // no move ... + + break; + + default: + RedDiskReleaseFlag = 0; + return subAnimateMurphy; + break; + } + + // ========================================================================== + // moving down to up ... + // ========================================================================== + +loc_g_6078: + // FS: + MurphyDY = -2; + // end of FS + ax = PlayField16[si - FieldWidth]; + al = LowByte(ax); + if (ax == fiSpace) + goto loc_g_6312; + + if (ax == fiBase) + goto loc_g_63D3; + + if (al == fiBug) + goto loc_g_63C2; + + if (ax == fiInfotron) + goto loc_g_65C6; + + if (ax == fiExit) + goto loc_g_6756; + + if (al == fiTerminal) + goto loc_g_6817; + + if (al == fiPortUp || al == fiPortUpAndDown || al == fiPortAllDirections) + goto loc_g_6916; + + if (al == fiRedDisk) + goto loc_g_69A6; + + if (al == fiYellowDisk) + goto loc_g_6AB8; + + if (! subMoveKillsMurphy(si - FieldWidth, ax, bl)) + goto loc_g_6078; + + return subAnimateMurphy; + + // ========================================================================== + // moving right to left ... + // ========================================================================== + +loc_g_60DA: + // FS: + MurphyDX = -2; + // end of FS + MurphyVarFaceLeft = 1; + ax = PlayField16[si - 1]; + al = LowByte(ax); + if (ax == fiSpace) + goto loc_g_6341; + + if (ax == fiBase) + goto loc_g_641C; + + if (al == fiBug) + goto loc_g_640B; + + if (ax == fiInfotron) + goto loc_g_65FE; + + if (ax == fiExit) + goto loc_g_6756; + + if (ax == fiZonk) + goto loc_g_679B; + + if (al == fiTerminal) + goto loc_g_684E; + + if (al == fiPortLeft || al == fiPortLeftAndRight || al == fiPortAllDirections) + goto loc_g_693A; + + if (ax == fiRedDisk) + goto loc_g_69CE; + + if (ax == fiYellowDisk) + goto loc_g_6AF1; + + if (ax == fiOrangeDisk) + goto loc_g_6B9B; + + if (! subMoveKillsMurphy(si - 1, ax, bl)) + goto loc_g_60DA; + + return subAnimateMurphy; + + // ========================================================================== + // moving up to down ... + // ========================================================================== + +loc_g_6154: + // FS: + MurphyDY = 2; + // end of FS + ax = PlayField16[si + FieldWidth]; + al = LowByte(ax); + if (ax == fiSpace) + goto loc_g_6364; + + if (ax == fiBase) + goto loc_g_6459; + + if (al == fiBug) + goto loc_g_6448; + + if (ax == fiInfotron) + goto loc_g_662A; + + if (ax == fiExit) + goto loc_g_6756; + + if (al == fiTerminal) + goto loc_g_6884; + + if (al == fiPortDown || al == fiPortUpAndDown || al == fiPortAllDirections) + goto loc_g_695E; + + if (al == fiRedDisk) + goto loc_g_69F7; + + if (al == fiYellowDisk) + goto loc_g_6B2A; + + if (! subMoveKillsMurphy(si + FieldWidth, ax, bl)) + goto loc_g_6154; + + return subAnimateMurphy; + + // ========================================================================== + // moving left to right ... + // ========================================================================== + +loc_g_61B6: + // FS: + MurphyDX = 2; + // end of FS + MurphyVarFaceLeft = 0; + ax = PlayField16[si + 1]; + al = LowByte(ax); + if (ax == fiSpace) + goto loc_g_6399; + + if (ax == fiBase) + goto loc_g_64A2; + + if (al == fiBug) + goto loc_g_6491; + + if (ax == fiInfotron) + goto loc_g_6662; + + if (ax == fiExit) + goto loc_g_6756; + + if (ax == fiZonk) + goto loc_g_67D4; + + if (al == fiTerminal) + goto loc_g_68BA; + + if (al == fiPortRight || al == fiPortLeftAndRight || al == fiPortAllDirections) + goto loc_g_6982; + + if (al == fiRedDisk) + goto loc_g_6A1F; + + if (al == fiYellowDisk) + goto loc_g_6B63; + + if (ax == fiOrangeDisk) + goto loc_g_6BD3; + + if (! subMoveKillsMurphy(si + 1, ax, bl)) + goto loc_g_61B6; + + return subAnimateMurphy; + + // ========================================================================== + // touching down to up ... + // ========================================================================== + +loc_g_622E: + // FS: + ClearPos = -1; + dxPos = si - FieldWidth; + // end of FS + ax = PlayField16[si - FieldWidth]; + al = LowByte(ax); + al = LowByte(ax); + if (ax == fiBase) + goto loc_g_64DF; + + if (al == fiBug) + goto loc_g_64CE; + + if (ax == fiInfotron) + goto loc_g_668E; + + if (al == fiTerminal) + goto loc_g_6817; + + if (al == fiRedDisk) + goto loc_g_6A48; + + return subAnimateMurphy; + + // ========================================================================== + // touching right to left ... + // ========================================================================== + +loc_g_6258: + // FS: + ClearPos = -1; + dxPos = si - 1; + // end of FS + MurphyVarFaceLeft = 1; + ax = PlayField16[si - 1]; + al = LowByte(ax); + if (ax == fiBase) + goto loc_g_651D; + + if (al == fiBug) + goto loc_g_650C; + + if (ax == fiInfotron) + goto loc_g_66C0; + + if (al == fiTerminal) + goto loc_g_684E; + + if (al == fiRedDisk) + goto loc_g_6A64; + + return subAnimateMurphy; + + // ========================================================================== + // touching up to down ... + // ========================================================================== + +loc_g_6288: + // FS: + ClearPos = -1; + dxPos = si + FieldWidth; + // end of FS + ax = PlayField16[si + FieldWidth]; + al = LowByte(ax); + if (ax == fiBase) + goto loc_g_655B; + + if (al == fiBug) + goto loc_g_654A; + + if (ax == fiInfotron) + goto loc_g_66F2; + + if (al == fiTerminal) + goto loc_g_6884; + + if (al == fiRedDisk) + goto loc_g_6A80; + + return subAnimateMurphy; + + // ========================================================================== + // touching left to right ... + // ========================================================================== + +loc_g_62B2: + // FS: + ClearPos = -1; + dxPos = si + 1; + // end of FS + MurphyVarFaceLeft = 0; + ax = PlayField16[si + 1]; + al = LowByte(ax); + if (ax == fiBase) + goto loc_g_6599; + + if (al == fiBug) + goto loc_g_6588; + + if (ax == fiInfotron) + goto loc_g_6724; + + if (al == fiTerminal) + goto loc_g_68BA; + + if (al == fiRedDisk) + goto loc_g_6A9C; + + return subAnimateMurphy; + + // ========================================================================== + // Release Red disk: no move ... + // ========================================================================== + +loc_g_62E2: + // FS: + ClearPos = -1; + // end of FS + if (LowByte(RedDiskCount) == 0) + return subAnimateMurphy; + + if (LowByte(RedDiskReleasePhase) != 0) + return subAnimateMurphy; + + if (LowByte(RedDiskReleaseFlag) != 1) + return subAnimateMurphy; + + MovHighByte(&PlayField16[si], 0x2A); + MovingPictureSequencePhase = 0x40; // init picture move sequence + dx = aniRedDisk; + MovLowByte(&RedDiskReleasePhase, 1); + Mov(&RedDiskReleaseMurphyPos, si); // remember Murphy's location + goto loc_Split; + + // ========================================================================== + // SPACE moving down to up + // ========================================================================== + +loc_g_6312: + dx = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpRight); + PlayField16[si - FieldWidth] = 0x103; + PlayField16[si] = 0x300; + si = si - FieldWidth; + goto loc_StopNoSplit; + + // ========================================================================== + // SPACE moving right to left + // ========================================================================== + +loc_g_6341: + dx = aniMurphyEatLeft; + PlayField16[si - 1] = 0x203; + PlayField16[si] = 0x300; + si = si - 1; + goto loc_StopNoSplit; + + // ========================================================================== + // SPACE moving up to down, and when gravity is pulling! + // ========================================================================== + +loc_g_6364: + dx = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpRight); + PlayField16[si + FieldWidth] = 0x303; + PlayField16[si] = 0x300; + si = si + FieldWidth; + goto loc_StopNoSplit; + + // ========================================================================== + // SPACE moving left to right + // ========================================================================== + +loc_g_6399: + dx = aniMurphyEatRight; + PlayField16[si + 1] = 0x403; + PlayField16[si] = 0x300; + si = si + 1; + goto loc_StopNoSplit; + + // ========================================================================== + // BUG moving down to up + // ========================================================================== + +loc_g_63C2: + if (SgnHighByte(PlayField16[si - FieldWidth]) >= 0) + { + ExplodeFieldSP(si); // Explode + return subAnimateMurphy; + } + + PlayField16[si - FieldWidth] = fiBase; + // ========================================================================== + // BASE moving down to up + // ========================================================================== + +loc_g_63D3: + subSoundFXBase(); + dx = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpRight); + PlayField16[si - FieldWidth] = 0x503; + PlayField16[si] = 0x300; + si = si - FieldWidth; + goto loc_StopNoSplit; + + // ========================================================================== + // BUG moving right to left + // ========================================================================== + +loc_g_640B: + if (SgnHighByte(PlayField16[si - 1]) >= 0) + { + ExplodeFieldSP(si); // Explode + return subAnimateMurphy; + } + + PlayField16[si - 1] = fiBase; + // ========================================================================== + // BASE moving right to left + // ========================================================================== + +loc_g_641C: + subSoundFXBase(); + dx = aniMurphyEatLeft; + PlayField16[si - 1] = 0x203; + PlayField16[si] = 0x300; + si = si - 1; + goto loc_StopNoSplit; + + // ========================================================================== + // BUG moving up to down + // ========================================================================== + +loc_g_6448: + if (SgnHighByte(PlayField16[si + FieldWidth]) >= 0) + { + ExplodeFieldSP(si); // Explode + return subAnimateMurphy; + } + + PlayField16[si + FieldWidth] = fiBase; + // ========================================================================== + // BASE moving up to down + // ========================================================================== + +loc_g_6459: + subSoundFXBase(); + dx = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpRight); + PlayField16[si + FieldWidth] = 0x703; + PlayField16[si] = 0x300; + si = si + FieldWidth; + goto loc_StopNoSplit; + + // ========================================================================== + // BUG moving left to right + // ========================================================================== + +loc_g_6491: + if (SgnHighByte(PlayField16[si + 1]) >= 0) + { + ExplodeFieldSP(si); // Explode + return subAnimateMurphy; + } + + PlayField16[si + 1] = fiBase; + // ========================================================================== + // BASE moving left to right + // ========================================================================== + +loc_g_64A2: + subSoundFXBase(); + dx = aniMurphyEatRight; + PlayField16[si + 1] = 0x803; + PlayField16[si] = 0x300; + si = si + 1; + goto loc_StopNoSplit; + + // ========================================================================== + // BUG touching down to up + // ========================================================================== + +loc_g_64CE: + if (SgnHighByte(PlayField16[si - FieldWidth]) >= 0) + { + ExplodeFieldSP(si); // Explode + return subAnimateMurphy; + } + + PlayField16[si - FieldWidth] = fiBase; + // ========================================================================== + // BASE touching down to up + // ========================================================================== + +loc_g_64DF: + subCopyFieldToScreen(si, aniMurphyTouchUp); + subSoundFXBase(); + dx = aniTouchBase; + dxPos = si - FieldWidth; + MovHighByte(&PlayField16[si], 0x10); + goto loc_StopNoSplit; + + // ========================================================================== + // BUG touching right to left + // ========================================================================== + +loc_g_650C: + if (SgnHighByte(PlayField16[si - 1]) >= 0) + { + ExplodeFieldSP(si); // Explode + return subAnimateMurphy; + } + + PlayField16[si - 1] = fiBase; + // ========================================================================== + // BASE touching right to left + // ========================================================================== + +loc_g_651D: + subCopyFieldToScreen(si, aniMurphyTouchLeft); + subSoundFXBase(); + dx = aniTouchBase; + dxPos = si - 1; + MovHighByte(&PlayField16[si], 0x11); + goto loc_StopNoSplit; + + // ========================================================================== + // BUG touching up to down + // ========================================================================== + +loc_g_654A: + if (SgnHighByte(PlayField16[si + FieldWidth]) >= 0) + { + ExplodeFieldSP(si); // Explode + return subAnimateMurphy; + } + + PlayField16[si + FieldWidth] = fiBase; + // ========================================================================== + // BASE touching up to down + // ========================================================================== + +loc_g_655B: + subCopyFieldToScreen(si, aniMurphyTouchDown); + subSoundFXBase(); + dx = aniTouchBase; + dxPos = si + FieldWidth; + MovHighByte(&PlayField16[si], 0x12); + goto loc_StopNoSplit; + + // ========================================================================== + // BUG touching left to right + // ========================================================================== + +loc_g_6588: + if (SgnHighByte(PlayField16[si + 1]) >= 0) + { + ExplodeFieldSP(si); // Explode + return subAnimateMurphy; + } + + PlayField16[si + 1] = fiBase; + // ========================================================================== + // BASE touching left to right + // ========================================================================== + +loc_g_6599: + subCopyFieldToScreen(si, aniMurphyTouchRight); + subSoundFXBase(); + dx = aniTouchBase; + dxPos = si + 1; + MovHighByte(&PlayField16[si], 0x13); + goto loc_StopNoSplit; + + // ========================================================================== + // INFOTRON moving down to up + // ========================================================================== + +loc_g_65C6: + subSoundFXInfotron(); + dx = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpRight); + PlayField16[si - FieldWidth] = 0x903; + PlayField16[si] = 0x300; + si = si - FieldWidth; + goto loc_StopNoSplit; + + // ========================================================================== + // INFOTRON moving right to left + // ========================================================================== + +loc_g_65FE: + subSoundFXInfotron(); + dx = aniEatInfotronLeft; + dx2 = fiInfotron; + dx2Step = -1; + ClearPos = -1; + PlayField16[si - 1] = 0xA03; + PlayField16[si] = 0x300; + si = si - 1; + goto loc_StopNoSplit; + + // ========================================================================== + // INFOTRON moving up to down + // ========================================================================== + +loc_g_662A: + subSoundFXInfotron(); + dx = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpRight); + PlayField16[si + FieldWidth] = 0xB03; + PlayField16[si] = 0x300; + si = si + FieldWidth; + goto loc_StopNoSplit; + + // ========================================================================== + // INFOTRON moving left to right + // ========================================================================== + +loc_g_6662: + subSoundFXInfotron(); + dx = aniEatInfotronRight; + dx2 = fiInfotron; + dx2Step = 1; + ClearPos = -1; + PlayField16[si + 1] = 0xC03; + PlayField16[si] = 0x300; + si = si + 1; + goto loc_StopNoSplit; + + // ========================================================================== + // INFOTRON touching down to up + // ========================================================================== + +loc_g_668E: + subCopyFieldToScreen(si, aniMurphyTouchUp); + subSoundFXInfotron(); + dx = aniTouchInfotron; + MovHighByte(&PlayField16[si], 0x14); + MovHighByte(&PlayField16[si - FieldWidth], 0xFF); + goto loc_StopNoSplit; + + // ========================================================================== + // INFOTRON touching right to left + // ========================================================================== + +loc_g_66C0: + subCopyFieldToScreen(si, aniMurphyTouchLeft); + subSoundFXInfotron(); + dx = aniTouchInfotron; + MovHighByte(&PlayField16[si], 0x15); + MovHighByte(&PlayField16[si - 1], 0xFF); + goto loc_StopNoSplit; + + // ========================================================================== + // INFOTRON touching up to down + // ========================================================================== + +loc_g_66F2: + subCopyFieldToScreen(si, aniMurphyTouchDown); + subSoundFXInfotron(); + dx = aniTouchInfotron; + MovHighByte(&PlayField16[si], 0x16); + MovHighByte(&PlayField16[si + FieldWidth], 0xFF); + goto loc_StopNoSplit; + + // ========================================================================== + // INFOTRON touching left to right + // ========================================================================== + +loc_g_6724: + subCopyFieldToScreen(si, aniMurphyTouchRight); + subSoundFXInfotron(); + dx = aniTouchInfotron; + MovHighByte(&PlayField16[si], 0x17); + MovHighByte(&PlayField16[si + 1], 0xFF); + goto loc_StopNoSplit; + + // ========================================================================== + // EXIT pressed from any direction + // ========================================================================== + +loc_g_6756: + // FS + ClearPos = -1; + MurphyDX = 0; + MurphyDY = 0; + // end of FS + if (LowByte(InfotronsNeeded) != 0) + return subAnimateMurphy; + + subSoundFXExit(); + data_h_DemoDone = 1; // EP set level success bytes + LevelStatus = 1; // set Level Status DONE + EP_GameDemoVar0DAA = 0; // force demo for lead-out + if (SavedGameFlag == 0) // saved game running? + { + if (UpdateTimeFlag != 0) // update time? + { + UpdatedFlag = 1; // prevent double update + subUpdatePlayingTime(); // update playing time + } + } + +#if 0 + subUpdateHallOfFame(); // update time + Hall-Of-Fame +#endif + + LeadOutCounter = 0x40; // quit: start lead-out + dx = aniMurphyExit; + MovHighByte(&PlayField16[si], 0xD); + goto loc_StopNoSplit; + + // ========================================================================== + // ZONK moving right to left + // ========================================================================== + +loc_g_679B: + ax = PlayField16[si - 2]; + if (ax != 0) + return subAnimateMurphy; + + MovHighByte(&PlayField16[si - 2], 1); + subCopyFieldToScreen(si, aniPushLeft); // draw pushing murphy + dx = aniZonkRollLeft; + dxPos = si - 1; + dx2 = aniPushLeft; + dx2Step = 1; + MovHighByte(&PlayField16[si], 0xE); + goto loc_MoveNoSplit; + + // ========================================================================== + // ZONK moving left to right + // ========================================================================== + +loc_g_67D4: + ax = PlayField16[si + 2]; + if (ax != 0) + return subAnimateMurphy; + + ax = PlayField16[si + FieldWidth + 1]; + if (ax == 0) // zonk falls + return subAnimateMurphy; + + MovHighByte(&PlayField16[si + 2], 1); + subCopyFieldToScreen(si, aniPushRight); // draw pushing murphy + dx = aniZonkRollRight; + dxPos = si + 1; + dx2 = aniPushRight; + dx2Step = -1; + MovHighByte(&PlayField16[si], 0xF); + goto loc_MoveNoSplit; + + // ========================================================================== + // TERMINAL moving/touching down to up + // ========================================================================== + +loc_g_6817: + subCopyFieldToScreen(si, aniMurphyTouchUp); + if (YellowDisksExploded != 0) + { + YawnSleepCounter = 10; // stay hypnotized + return subAnimateMurphy; + } // loc_g_6838: + + subCopyFieldToScreen(si - FieldWidth, 0x88); // draw new terminal type + TerminalState[si - FieldWidth] = 8; + goto loc_g_68F0; + + // ========================================================================== + // TERMINAL moving/touching right to left + // ========================================================================== + +loc_g_684E: + subCopyFieldToScreen(si, aniMurphyTouchLeft); + if (YellowDisksExploded != 0) + { + YawnSleepCounter = 10; // stay hypnotized + return subAnimateMurphy; + } // loc_g_6838: + + subCopyFieldToScreen(si - 1, 0x88); // draw new terminal type + TerminalState[si - 1] = 8; + goto loc_g_68F0; + + // ========================================================================== + // TERMINAL moving/touching up to down + // ========================================================================== + +loc_g_6884: + subCopyFieldToScreen(si, aniMurphyTouchDown); + if (YellowDisksExploded != 0) + { + YawnSleepCounter = 10; // stay hypnotized + return subAnimateMurphy; + } // loc_g_6838: + + subCopyFieldToScreen(si + FieldWidth, 0x88); // draw new terminal type + TerminalState[si + FieldWidth] = 8; + goto loc_g_68F0; + + // ========================================================================== + // TERMINAL moving/touching left to right + // ========================================================================== + +loc_g_68BA: + subCopyFieldToScreen(si, aniMurphyTouchRight); + if (YellowDisksExploded != 0) + { + YawnSleepCounter = 10; // stay hypnotized + return subAnimateMurphy; + } // loc_g_6838: + + subCopyFieldToScreen(si + 1, 0x88); // draw new terminal type + TerminalState[si + 1] = 8; + // ========================================================================== + // common TERMINAL stuff moving/touching from all directions + // ========================================================================== + +loc_g_68F0: + TerminalMaxCycles = 7; + YellowDisksExploded = 1; + for (i = 0; i <= LevelMax; i++) + { + if (PlayField16[i] == fiYellowDisk) + ExplodeFieldSP (i); + } + + return subAnimateMurphy; + + // ========================================================================== + // PORT down to up, VERTICAL PORT, CROSS PORT all moving down to up + // ========================================================================== + +loc_g_6916: + if (PlayField16[si - 2 * FieldWidth] != 0) + return subAnimateMurphy; + + dx = aniSplitUpDown; + dx2Step = -FieldWidth; + PlayField16[si] = 0x1803; + PlayField16[si - 2 * FieldWidth] = 0x300; + goto loc_StopSplit; + + // ========================================================================== + // PORT right to left, HORIZONTAL PORT, CROSS PORT all moving right to left + // ========================================================================== + +loc_g_693A: + if (PlayField16[si - 2] != 0) + return subAnimateMurphy; + + dx = aniMurphyEatLeft; + dx2Step = -1; + PlayField16[si] = 0x1903; + PlayField16[si - 2] = 0x300; + goto loc_StopSplit; + + // ========================================================================== + // PORT up to down, VERTICAL PORT, CROSS PORT all moving up to down + // ========================================================================== + +loc_g_695E: + if (PlayField16[si + 2 * FieldWidth] != 0) + return subAnimateMurphy; + + dx = aniSplitUpDown; + dx2Step = FieldWidth; + PlayField16[si] = 0x1A03; + PlayField16[si + 2 * FieldWidth] = 0x300; + goto loc_StopSplit; + + // ========================================================================== + // PORT left to right, HORIZONTAL PORT, CROSS PORT all moving left to right + // ========================================================================== + +loc_g_6982: + if (PlayField16[si + 2] != 0) + return subAnimateMurphy; + + dx = aniMurphyEatRight; + dx2Step = 1; + PlayField16[si] = 0x1B03; + PlayField16[si + 2] = 0x300; + +loc_StopSplit: + MovingPictureSequencePhase = 0; // stop picture move sequence + SplitMoveFlag = 1; // port: split movement + goto loc_Split; + + // ========================================================================== + // RED DISK moving down to up + // ========================================================================== + +loc_g_69A6: + dx = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpRight); + PlayField16[si] = 0x1C03; + PlayField16[si - FieldWidth] = 0x300; + goto loc_StopNoSplit; + + // ========================================================================== + // RED DISK moving right to left + // ========================================================================== + +loc_g_69CE: + dx = aniMurphyEatLeft; + PlayField16[si] = 0x300; // !!!!!! this time we move murphy at sequence-start! + PlayField16[si - 1] = 0x1D03; + si = si - 1; + goto loc_StopNoSplit; + + // ========================================================================== + // RED DISK moving up to down + // ========================================================================== + +loc_g_69F7: + dx = (MurphyVarFaceLeft == 0 ? aniMurphyEatUpRight : aniMurphyEatUpRight); + PlayField16[si] = 0x1E03; + PlayField16[si + FieldWidth] = 0x300; + goto loc_StopNoSplit; + + // ========================================================================== + // RED DISK moving left to right + // ========================================================================== + +loc_g_6A1F: + // dx = aniMurphyEatRightRedDisk 'this sequence is 9 steps long! + dx = aniMurphyEatRight; + // -------------------------------------------------------------------------- + // BugFix + // Table data_h_145A, pointed to by table data_h_105E, has a severe bug: + // The Red Disk sequence is 8 pictures long, but 9 are displayed, because it + // has 1 extra entry, which causes Murphy to end slightly shifted to the left! + // We may not fix the table, because then the timing of the game changes + // and several existing demo's do not run properly anymore. + // We only correct Murphies x-location here, when the sequence starts. + // Remember that this is not the real bug-fix, but we must live with + // this existing bug and correct for the consequences of it. + if (0 == AllowEatRightRedDiskBug) // Murphy's screen x-position + MurphyScreenXPos = MurphyScreenXPos - 2; + + SeqPos = -1; + // FS: for me this means to blit the first animation frame twice + // end of BugFix + // -------------------------------------------------------------------------- + PlayField16[si] = 0x300; // !!!!!! this time we move murphy at sequence-start! + PlayField16[si + 1] = 0x1F03; + si = si + 1; + goto loc_StopNoSplit; + + // ========================================================================== + // RED DISK touching down to up + // ========================================================================== + +loc_g_6A48: + dx = aniTouchRedDisk; + MovHighByte(&PlayField16[si], 0x20); + MovHighByte(&PlayField16[si - FieldWidth], 3); + goto loc_StopNoSplit; + + // ========================================================================== + // RED DISK touching right to left + // ========================================================================== + +loc_g_6A64: + dx = aniTouchRedDisk; + MovHighByte(&PlayField16[si], 0x21); + MovHighByte(&PlayField16[si - 1], 3); + goto loc_StopNoSplit; + + // ========================================================================== + // RED DISK touching up to down + // ========================================================================== + +loc_g_6A80: + dx = aniTouchRedDisk; + MovHighByte(&PlayField16[si], 0x22); + MovHighByte(&PlayField16[si + FieldWidth], 3); + goto loc_StopNoSplit; + + // ========================================================================== + // RED DISK touching left to right + // ========================================================================== + +loc_g_6A9C: + dx = aniTouchRedDisk; + MovHighByte(&PlayField16[si], 0x23); + MovHighByte(&PlayField16[si + 1], 3); + +loc_StopNoSplit: + MovingPictureSequencePhase = 0; // stop picture move sequence + goto loc_NoSplit; + + // ========================================================================== + // YELLOW DISK moving down to up + // ========================================================================== + +loc_g_6AB8: + if (PlayField16[si - 2 * FieldWidth] != 0) + return subAnimateMurphy; + + PlayField16[si - 2 * FieldWidth] = 0x1200; + subCopyFieldToScreen(si, aniPushRight); + dx = aniYellowDisk; + dxPos = si - FieldWidth; + dx2 = aniPushUpDown; + dx2Step = FieldWidth; + PlayField16[si] = 0x2403; + goto loc_MoveNoSplit; + + // ========================================================================== + // YELLOW DISK moving right to left + // ========================================================================== + +loc_g_6AF1: + if (PlayField16[si - 2] != 0) + return subAnimateMurphy; + + PlayField16[si - 2] = 0x1200; + subCopyFieldToScreen(si, aniPushLeft); + dx = aniYellowDisk; + dxPos = si - 1; + dx2 = aniPushLeft; + dx2Step = 1; + PlayField16[si] = 0x2503; + goto loc_MoveNoSplit; + + // ========================================================================== + // YELLOW DISK moving up to down + // ========================================================================== + +loc_g_6B2A: + if (PlayField16[si + 2 * FieldWidth] != 0) + return subAnimateMurphy; + + PlayField16[si + 2 * FieldWidth] = 0x1200; + subCopyFieldToScreen(si, aniPushRight); + dx = aniYellowDisk; + dxPos = si + FieldWidth; + dx2 = aniPushUpDown; + dx2Step = -FieldWidth; + PlayField16[si] = 0x2703; + goto loc_MoveNoSplit; + + // ========================================================================== + // YELLOW DISK moving left to right + // ========================================================================== + +loc_g_6B63: + if (PlayField16[si + 2] != 0) + return subAnimateMurphy; + + PlayField16[si + 2] = 0x1200; + subCopyFieldToScreen(si, aniPushRight); + dx = aniYellowDisk; + dxPos = si + 1; + dx2 = aniPushRight; + dx2Step = -1; + PlayField16[si] = 0x2603; + goto loc_MoveNoSplit; + + // ========================================================================== + // ORANGE DISK moving right to left + // ========================================================================== + +loc_g_6B9B: + if (PlayField16[si - 2] != 0) + return subAnimateMurphy; + + PlayField16[si - 2] = 0x800; + subCopyFieldToScreen(si, aniPushLeft); + dx = aniOrangeDisk; + dxPos = si - 1; + dx2 = aniPushLeft; + dx2Step = 1; + PlayField16[si] = 0x2803; + goto loc_MoveNoSplit; + + // ========================================================================== + // ORANGE DISK moving left to right + // ========================================================================== + +loc_g_6BD3: + if (PlayField16[si + 2] != 0) + return subAnimateMurphy; + + if (PlayField16[si + FieldWidth + 1] == 0) // falling goes before pushing + return subAnimateMurphy; + + PlayField16[si + 2] = 0x100; + subCopyFieldToScreen(si, aniPushRight); + dx = aniOrangeDisk; + dxPos = si + 1; + dx2 = aniPushRight; + dx2Step = -1; + PlayField16[si] = 0x2903; + // ========================================================================== + // Copy screen animation action table to action work space + // (To paint sequence: Push Zonk/Disk / release red disk / Port passing) + // ========================================================================== + +loc_MoveNoSplit: + MovingPictureSequencePhase = 8; // init picture move sequence + +loc_NoSplit: + SplitMoveFlag = 0; // no port: no split movement + +loc_Split: + // copy/store global move sequence info???????????????????????????????????? + // ... dont think so ...(FS) + // ========================================================================== + // Proceed with all movements + // ========================================================================== + +locProceedMovingMurphy: // proceed moving murphy + YawnSleepCounter = 0; // Wake up sleeping Murphy + ax = MovingPictureSequencePhase; // sequence busy? + if (ax == 0) // no -- start sequence! + goto loc_g_6C8F; + + ax = ax - 1; // next picture of sequence + MovingPictureSequencePhase = ax; // store for later + if (ax == 0) // Sound effects + subSoundFXPush(); + + bl = HighByte(PlayField16[si]); + if (bl == 0xE) // Push Zonk to left + goto loc_g_6F7E; + + if (bl == 0xF) // Push Zonk to right + goto loc_g_6FBC; + + if (bl == 0x28) // Push orange disk to left + goto loc_g_6FFA; + + if (bl == 0x29) // Push orange disk to right + goto loc_g_7038; + + if (bl == 0x24) // Push yellow disk up + goto loc_g_7076; + + if (bl == 0x25) // Push yellow disk to left + goto loc_g_70B4; + + if (bl == 0x27) // Push yellow disk down + goto loc_g_70F2; + + if (bl == 0x26) // Push yellow disk to right + goto loc_g_7130; + + if (bl == 0x2A) // Red disk release timer + goto loc_g_716E; + + return subAnimateMurphy; + + // ========================================================================== + // Paint frame of MOVING.DAT sequence + // ========================================================================== + +loc_g_6C8F: + if (SplitMoveFlag == 0) + { + // ++++++++++++++++++++++++++ + // Begin of normal movement + MurphyScreenXPos = MurphyScreenXPos + MurphyDX; + MurphyScreenYPos = MurphyScreenYPos + MurphyDY; + if (! ClearPos < 0) // clear field that murphy is leaving + subCopyFieldToScreen(ClearPos, 0); + + if (dx2 == fiInfotron) // special case of infotron moving left or right + { + tDeltaX = 0; + tDeltaY = 0; + } + else + { + tDeltaX = MurphyDX * LocalStretch * (SeqPos + 1); + tDeltaY = MurphyDY * LocalStretch * (SeqPos + 1); + } + + X = GetStretchX(dxPos) + tDeltaX; + Y = GetStretchY(dxPos) + tDeltaY; + Tmp = (SeqPos < 0 ? 0 : 0); // 9StepBugFix!(red disk move right) + StretchedSprites.BltEx(X, Y, dx[Tmp]); + if (! dx2 < 0) + { + tPos = dxPos + dx2Step; + X = GetStretchX(tPos); + Y = GetStretchY(tPos); + if (dx2 == fiInfotron) // special case of infotron moving left or right + { + StretchedSprites.BltEx(X, Y, dx[SeqPos] + dx2Step); + } + else // pushing something + { + StretchedSprites.BltEx(X + tDeltaX, Y + tDeltaY, dx2); + } + } + + // End of normal movement + // ------------------------ + } + else + { + // ++++++++++++++++++++++++++++++++ + // Begin of split movement (port) + MurphyScreenXPos = MurphyScreenXPos + 2 * MurphyDX; + MurphyScreenYPos = MurphyScreenYPos + 2 * MurphyDY; + subCopyFieldToScreen(ClearPos, 0); // clear the field that murphy leaves + tDeltaX = MurphyDX * LocalStretch * (SeqPos + 1); + tDeltaY = MurphyDY * LocalStretch * (SeqPos + 1); + X = GetStretchX(dxPos) + tDeltaX; + Y = GetStretchY(dxPos) + tDeltaY; + StretchedSprites.BltEx(X, Y, dx[SeqPos]); // plot first murphy + tPos = dxPos + dx2Step; + X = GetStretchX(tPos); + Y = GetStretchY(tPos); + StretchedSprites.BltEx(X + tDeltaX, Y + tDeltaY, dx[SeqPos]); // plot second murphy + StretchedSprites.BltEx(X, Y, LowByte(PlayField16[tPos])); // replot the port on top + // End of split movement (port) + // ------------------------------ + } // loc_g_6D1E:'loc_g_6D28: + + SeqPos = SeqPos + 1; + if (dx[SeqPos] > -1) + return subAnimateMurphy; + + // Follow-up after movement completed 'loc_g_6D35: + MurphyXPos = MurphyXPos + MurphyDX; + MurphyYPos = MurphyYPos + MurphyDY; + bl = HighByte(PlayField16[si]); // animation phase + MovHighByte(&PlayField16[si], 0); + + if (bl == 0x1) // space, moving up + goto loc_g_6EC8; + + if (bl == 0x2) // space, moving left + goto loc_g_6EE6; + + if (bl == 0x3) // space, moving down + goto loc_g_6F04; + + if (bl == 0x4) // space, moving right + goto loc_g_71C4; + + if (bl == 0x5) // base , moving up + goto loc_g_6EC8; + + if (bl == 0x6) // base , moving left -> 6 is not used, value is set to 2 instead of 6! + goto loc_g_6EE6; + + if (bl == 0x7) // base , moving down + goto loc_g_6F04; + + if (bl == 0x8) // base , moving right + goto loc_g_71C4; + + if (bl == 0x9) // infotron, moving up + goto loc_g_6EBA; + + if (bl == 0xA) // infotron, moving left + goto loc_g_6ED8; + + if (bl == 0xB) // infotron, moving down + goto loc_g_6EF6; + + if (bl == 0xC) // infotron, moving right + goto loc_g_71B6; + + if (bl == 0xD) // exit + goto loc_g_6F77; + + if (bl == 0xE) // zonk, pushing left + goto loc_g_6F18; + + if (bl == 0xF) // zonk, pushing right + goto loc_g_6F3B; + + if (bl == 0x10) // base , touching up + goto loc_g_71E2; + + if (bl == 0x11) // base , touching left + goto loc_g_71FE; + + if (bl == 0x12) // base , touching down + goto loc_g_721A; + + if (bl == 0x13) // base , touching right + goto loc_g_7236; + + if (bl == 0x14) // infotron touching up + goto loc_g_71D4; + + if (bl == 0x15) // infotron touching left + goto loc_g_71F0; + + if (bl == 0x16) // infotron touching down + goto loc_g_720C; + + if (bl == 0x17) // infotron touching right + goto loc_g_7228; + + if (bl == 0x18) // port up + goto loc_g_7244; + + if (bl == 0x19) // port left + goto loc_g_7272; + + if (bl == 0x1A) // port down + goto loc_g_729F; + + if (bl == 0x1B) // port right + goto loc_g_72CD; + + if (bl == 0x1C) // red disk, moving up + goto loc_g_72FA; + + if (bl == 0x1D) // red disk, moving left + goto loc_g_7318; + + if (bl == 0x1E) // red disk, moving down + goto loc_g_7333; + + if (bl == 0x1F) // red disk, moving right -> 9-Step-Bug! + goto loc_g_7351; + + if (bl == 0x20) // red disk, touching up + goto loc_g_736C; + + if (bl == 0x21) // red disk, touching left + goto loc_g_7381; + + if (bl == 0x22) // red disk, touching down + goto loc_g_7396; + + if (bl == 0x23) // red disk, touching right + goto loc_g_73AB; + + if (bl == 0x24) // yellow disk, pushing up + goto loc_g_73C0; + + if (bl == 0x25) // yellow disk, pushing left + goto loc_g_73DD; + + if (bl == 0x26) // yellow disk, pushing right -> order of "down" exchanged with "right"! + goto loc_g_7417; + + if (bl == 0x27) // yellow disk, pushing down -> order of "down" exchanged with "right"! + goto loc_g_73FA; + + if (bl == 0x28) // orange disk, pushing left + goto loc_g_7434; + + if (bl == 0x29) // orange disk, pushing right + goto loc_g_7451; + + if (bl == 0x2A) // red disk, release + goto loc_g_747F; + + ExitToMenuFlag = 1; + return subAnimateMurphy; + + // ========================================================================== + // infotron, moving up + // ========================================================================== + +loc_g_6EBA: + if (0 < LowByte(InfotronsNeeded)) + InfotronsNeeded = InfotronsNeeded - 1; + + subDisplayInfotronsNeeded(); +loc_g_6EC8: // space, base + PlayField16[si] = fiMurphy; + subAdjustZonksInfotronsAboveMurphy(si + FieldWidth); + return subAnimateMurphy; + + // ========================================================================== + // infotron, moving left + // ========================================================================== + +loc_g_6ED8: + if (0 < LowByte(InfotronsNeeded)) + InfotronsNeeded = InfotronsNeeded - 1; + + subDisplayInfotronsNeeded(); +loc_g_6EE6: // space, base + PlayField16[si] = fiMurphy; + subAdjustZonksInfotronsAboveMurphy(si + 1); + return subAnimateMurphy; + + // ========================================================================== + // infotron, moving down + // ========================================================================== + +loc_g_6EF6: + if (0 < LowByte(InfotronsNeeded)) + InfotronsNeeded = InfotronsNeeded - 1; + + subDisplayInfotronsNeeded(); +loc_g_6F04: // space, base + if (LowByte(PlayField16[si - FieldWidth]) != fiExplosion) + PlayField16[si - FieldWidth] = 0; + + PlayField16[si] = fiMurphy; + return subAnimateMurphy; + + // ========================================================================== + // infotron, moving right + // ========================================================================== + +loc_g_71B6: + if (0 < LowByte(InfotronsNeeded)) + InfotronsNeeded = InfotronsNeeded - 1; + + subDisplayInfotronsNeeded(); +loc_g_71C4: // space, base + subAdjustZonksInfotronsAboveMurphy(si - 1); + PlayField16[si] = fiMurphy; + return subAnimateMurphy; + + // ========================================================================== + // infotron, touching up + // ========================================================================== + +loc_g_71D4: + if (0 < LowByte(InfotronsNeeded)) + InfotronsNeeded = InfotronsNeeded - 1; + + subDisplayInfotronsNeeded(); +loc_g_71E2: // base + if (LowByte(PlayField16[si - FieldWidth]) != fiExplosion) + PlayField16[si - FieldWidth] = 0; + + return subAnimateMurphy; + + // ========================================================================== + // infotron, touching left + // ========================================================================== + +loc_g_71F0: + if (0 < LowByte(InfotronsNeeded)) + InfotronsNeeded = InfotronsNeeded - 1; + + subDisplayInfotronsNeeded(); +loc_g_71FE: // base + if (LowByte(PlayField16[si - 1]) != fiExplosion) + PlayField16[si - 1] = 0; + + return subAnimateMurphy; + + // ========================================================================== + // infotron, touching down + // ========================================================================== + +loc_g_720C: + if (0 < LowByte(InfotronsNeeded)) + InfotronsNeeded = InfotronsNeeded - 1; + + subDisplayInfotronsNeeded(); +loc_g_721A: // base + if (LowByte(PlayField16[si + FieldWidth]) != fiExplosion) + PlayField16[si + FieldWidth] = 0; + + return subAnimateMurphy; + + // ========================================================================== + // infotron, touching right + // ========================================================================== + +loc_g_7228: + if (0 < LowByte(InfotronsNeeded)) + InfotronsNeeded = InfotronsNeeded - 1; + + subDisplayInfotronsNeeded(); +loc_g_7236: // base + if (LowByte(PlayField16[si + 1]) != fiExplosion) + PlayField16[si + 1] = 0; + + return subAnimateMurphy; + + // ========================================================================== + // zonk, pushing left + // ========================================================================== + +loc_g_6F18: + if (LowByte(PlayField16[si]) != fiExplosion) + PlayField16[si] = 0; + + PlayField16[si - 1] = fiMurphy; + PlayField16[si - 2] = fiZonk; + subExplodeSnikSnaksBelow(si - 2); + si = si - 1; + return subAnimateMurphy; + + // ========================================================================== + // zonk, pushing right + // ========================================================================== + +loc_g_6F3B: + if (LowByte(PlayField16[si]) != fiExplosion) + PlayField16[si] = 0; + + PlayField16[si + 1] = fiMurphy; + PlayField16[si + 2] = fiZonk; + subExplodeSnikSnaksBelow(si + 2); + si = si + 1; + return subAnimateMurphy; + + // ========================================================================== + // exit + // ========================================================================== + +loc_g_6F77: + ExitToMenuFlag = 1; + return subAnimateMurphy; + + // ========================================================================== + // Push Zonk from right to left + // ========================================================================== + +loc_g_6F7E: + if (DemoKeyCode == keyLeft && PlayField16[si - 1] == fiZonk) + return subAnimateMurphy; + + PlayField16[si] = fiMurphy; // else restore - no more zonk pushing! + PlayField16[si - 1] = fiZonk; + if (LowByte(PlayField16[si - 2]) != fiExplosion) + PlayField16[si - 2] = 0; + + subCopyFieldToScreen(si, fiMurphy); + return subAnimateMurphy; + + // ========================================================================== + // Push Zonk from left to right + // ========================================================================== + +loc_g_6FBC: + if (DemoKeyCode == keyRight && PlayField16[si + 1] == fiZonk) + return subAnimateMurphy; + + PlayField16[si] = fiMurphy; // else restore - no more zonk pushing! + PlayField16[si + 1] = fiZonk; + if (LowByte(PlayField16[si + 2]) != fiExplosion) + PlayField16[si + 2] = 0; + + subCopyFieldToScreen(si, fiMurphy); + return subAnimateMurphy; + + // ========================================================================== + // Push orange disk from right to left + // ========================================================================== + +loc_g_6FFA: + if (DemoKeyCode == keyLeft && PlayField16[si - 1] == fiOrangeDisk) + return subAnimateMurphy; + + PlayField16[si] = fiMurphy; // else restore - no more pushing! + PlayField16[si - 1] = fiOrangeDisk; + if (LowByte(PlayField16[si - 2]) != fiExplosion) + PlayField16[si - 2] = 0; + + subCopyFieldToScreen(si, fiMurphy); + return subAnimateMurphy; + + // ========================================================================== + // Push orange disk from left to right + // ========================================================================== + +loc_g_7038: + if (DemoKeyCode == keyRight && PlayField16[si + 1] == fiOrangeDisk) + return subAnimateMurphy; + + PlayField16[si] = fiMurphy; // else restore - no more pushing! + PlayField16[si + 1] = fiOrangeDisk; + if (LowByte(PlayField16[si + 2]) != fiExplosion) + PlayField16[si + 2] = 0; + + subCopyFieldToScreen(si, fiMurphy); + return subAnimateMurphy; + + // ========================================================================== + // Push yellow disk from down to up + // ========================================================================== + +loc_g_7076: + if (DemoKeyCode == keyUp && PlayField16[si - FieldWidth] == fiYellowDisk) + return subAnimateMurphy; + + PlayField16[si] = fiMurphy; // else restore - no more pushing! + PlayField16[si - FieldWidth] = fiYellowDisk; + if (LowByte(PlayField16[si - 2 * FieldWidth]) != fiExplosion) + PlayField16[si - 2 * FieldWidth] = 0; + + subCopyFieldToScreen(si, fiMurphy); + return subAnimateMurphy; + + // ========================================================================== + // Push yellow disk from right to left + // ========================================================================== + +loc_g_70B4: + if (DemoKeyCode == keyLeft && PlayField16[si - 1] == fiYellowDisk) + return subAnimateMurphy; + + PlayField16[si] = fiMurphy; // else restore - no more pushing! + PlayField16[si - 1] = fiYellowDisk; + if (LowByte(PlayField16[si - 2]) != fiExplosion) + PlayField16[si - 2] = 0; + + subCopyFieldToScreen(si, fiMurphy); + return subAnimateMurphy; + + // ========================================================================== + // Push yellow disk from up to down + // ========================================================================== + +loc_g_70F2: + if (DemoKeyCode == keyDown && PlayField16[si + FieldWidth] == fiYellowDisk) + return subAnimateMurphy; + + PlayField16[si] = fiMurphy; // else restore - no more pushing! + PlayField16[si + FieldWidth] = fiYellowDisk; + if (LowByte(PlayField16[si + 2 * FieldWidth]) != fiExplosion) + PlayField16[si + 2 * FieldWidth] = 0; + + subCopyFieldToScreen(si, fiMurphy); + return subAnimateMurphy; + + // ========================================================================== + // Push yellow disk from left to right + // ========================================================================== + +loc_g_7130: + if (DemoKeyCode == keyRight && PlayField16[si + 1] == fiYellowDisk) + return subAnimateMurphy; + + PlayField16[si] = fiMurphy; // else restore - no more pushing! + PlayField16[si + 1] = fiYellowDisk; + if (LowByte(PlayField16[si + 2]) != fiExplosion) + PlayField16[si + 2] = 0; + + subCopyFieldToScreen(si, fiMurphy); + return subAnimateMurphy; + + // ========================================================================== + // time red disk release (space) + // ========================================================================== + +loc_g_716E: + if (DemoKeyCode != keySpace) + { + PlayField16[si] = fiMurphy; + subCopyFieldToScreen(si, fiMurphy); + RedDiskReleasePhase = 0; + } + else if (MovingPictureSequencePhase == 0x20) + { + subCopyFieldToScreen(si, 43); // anxious murphy + RedDiskReleasePhase = 1; + } + + return subAnimateMurphy; + + // ========================================================================== + // Special port down to up + // ========================================================================== + +loc_g_7244: + if (LowByte(PlayField16[si]) != fiExplosion) + PlayField16[si] = 0; + + PlayField16[si - 2 * FieldWidth] = fiMurphy; + SplitMoveFlag = 0; + si = si - FieldWidth; + if (HighByte(PlayField16[si]) == 1) + subSpPortTest(si); + + si = si - FieldWidth; + return subAnimateMurphy; + + // ========================================================================== + // Special port right to left + // ========================================================================== + +loc_g_7272: + if (LowByte(PlayField16[si]) != fiExplosion) + PlayField16[si] = 0; + + PlayField16[si - 2] = fiMurphy; + SplitMoveFlag = 0; + si = si - 1; + if (HighByte(PlayField16[si]) == 1) + subSpPortTest(si); + + si = si - 1; + return subAnimateMurphy; + + // ========================================================================== + // Special port up to down + // ========================================================================== + +loc_g_729F: + if (LowByte(PlayField16[si]) != fiExplosion) + PlayField16[si] = 0; + + PlayField16[si + 2 * FieldWidth] = fiMurphy; + SplitMoveFlag = 0; + si = si + FieldWidth; + if (HighByte(PlayField16[si]) == 1) + subSpPortTest(si); + + si = si + FieldWidth; + return subAnimateMurphy; + + // ========================================================================== + // Special port left to right + // ========================================================================== + +loc_g_72CD: + if (LowByte(PlayField16[si]) != fiExplosion) + PlayField16[si] = 0; + + PlayField16[si + 2] = fiMurphy; + SplitMoveFlag = 0; + si = si + 1; + if (HighByte(PlayField16[si]) == 1) + subSpPortTest(si); + + si = si + 1; + return subAnimateMurphy; + + // ========================================================================== + // Move Red Disk up + // ========================================================================== + +loc_g_72FA: + if (LowByte(PlayField16[si]) != fiExplosion) + PlayField16[si] = 0; + + si = si - FieldWidth; + PlayField16[si] = fiMurphy; + subEatRedDisk(si); // inc+show Murphy's red disks + return subAnimateMurphy; + + // ========================================================================== + // Move Red Disk left + // ========================================================================== + +loc_g_7318: + if (LowByte(PlayField16[si + 1]) != fiExplosion) + PlayField16[si + 1] = 0; + + PlayField16[si] = fiMurphy; + subEatRedDisk(si); // inc+show Murphy's red disks + return subAnimateMurphy; + + // ========================================================================== + // Move Red Disk down + // ========================================================================== + +loc_g_7333: + if (LowByte(PlayField16[si]) != fiExplosion) + PlayField16[si] = 0; + + si = si + FieldWidth; + PlayField16[si] = fiMurphy; + subEatRedDisk(si); // inc+show Murphy's red disks + return subAnimateMurphy; + + // ========================================================================== + // Move Red Disk right + // ========================================================================== + +loc_g_7351: + if (LowByte(PlayField16[si - 1]) != fiExplosion) + PlayField16[si - 1] = 0; + + PlayField16[si] = fiMurphy; + subEatRedDisk(si); // inc+show Murphy's red disks + return subAnimateMurphy; + + // ========================================================================== + // Eat Red Disk up + // ========================================================================== + +loc_g_736C: + if (LowByte(PlayField16[si - FieldWidth]) != fiExplosion) + PlayField16[si - FieldWidth] = 0; + + subEatRedDisk(si - FieldWidth); // inc+show Murphy's red disks + return subAnimateMurphy; + + // ========================================================================== + // Eat Red Disk left + // ========================================================================== + +loc_g_7381: + if (LowByte(PlayField16[si - 1]) != fiExplosion) + PlayField16[si - 1] = 0; + + subEatRedDisk(si - 1); // inc+show Murphy's red disks + return subAnimateMurphy; + + // ========================================================================== + // Eat Red Disk down + // ========================================================================== + +loc_g_7396: + if (LowByte(PlayField16[si + FieldWidth]) != fiExplosion) + PlayField16[si + FieldWidth] = 0; + + subEatRedDisk(si + FieldWidth); // inc+show Murphy's red disks + return subAnimateMurphy; + + // ========================================================================== + // Eat Red Disk right + // ========================================================================== + +loc_g_73AB: + if (LowByte(PlayField16[si + 1]) != fiExplosion) + PlayField16[si + 1] = 0; + + subEatRedDisk(si + 1); // inc+show Murphy's red disks + return subAnimateMurphy; + + // ========================================================================== + // yellow disk, pushing up + // ========================================================================== + +loc_g_73C0: + if (LowByte(PlayField16[si]) != fiExplosion) + PlayField16[si] = 0; + + si = si - FieldWidth; + PlayField16[si] = fiMurphy; + PlayField16[si - FieldWidth] = fiYellowDisk; + return subAnimateMurphy; + + // ========================================================================== + // yellow disk, pushing left + // ========================================================================== + +loc_g_73DD: + if (LowByte(PlayField16[si]) != fiExplosion) + PlayField16[si] = 0; + + si = si - 1; + PlayField16[si] = fiMurphy; + PlayField16[si - 1] = fiYellowDisk; + return subAnimateMurphy; + + // ========================================================================== + // yellow disk, pushing down + // ========================================================================== + +loc_g_73FA: + if (LowByte(PlayField16[si]) != fiExplosion) + PlayField16[si] = 0; + + si = si + FieldWidth; + PlayField16[si] = fiMurphy; + PlayField16[si + FieldWidth] = fiYellowDisk; + return subAnimateMurphy; + + // ========================================================================== + // yellow disk pushing right + // ========================================================================== + +loc_g_7417: + if (LowByte(PlayField16[si]) != fiExplosion) + PlayField16[si] = 0; + + si = si + 1; + PlayField16[si] = fiMurphy; + PlayField16[si + 1] = fiYellowDisk; + return subAnimateMurphy; + + // ========================================================================== + // orange disk, pushing left + // ========================================================================== + +loc_g_7434: + if (LowByte(PlayField16[si]) != fiExplosion) + PlayField16[si] = 0; + + si = si - 1; + PlayField16[si] = fiMurphy; + PlayField16[si - 1] = fiOrangeDisk; + return subAnimateMurphy; + + // ========================================================================== + // orange disk, pushing right + // ========================================================================== + +loc_g_7451: + if (LowByte(PlayField16[si]) != fiExplosion) + PlayField16[si] = 0; + + si = si + 1; + PlayField16[si] = fiMurphy; + PlayField16[si + 1] = fiOrangeDisk; + if (PlayField16[si + FieldWidth + 1] == 0) // make it fall down if below is empty + { + MovHighByte(&PlayField16[si + 1], 0x20); + MovHighByte(&PlayField16[si + FieldWidth + 1], fiOrangeDisk); + } + + return subAnimateMurphy; + + // ========================================================================== + // Release a red disk + // ========================================================================== + +loc_g_747F: + PlayField16[si] = fiMurphy; + RedDiskReleasePhase = 2; + RedDiskCount = RedDiskCount - 1; + subDisplayRedDiskCount(); + subSoundFXPush(); // Sound effects + + return subAnimateMurphy; +} // subAnimateMurphy + +// ========================================================================== +// SUBROUTINE +// ========================================================================== +int subExplodeSnikSnaksBelow(int si) +{ + int subExplodeSnikSnaksBelow; + + int ax; + + ax = LowByte(PlayField16[si + FieldWidth]); + if (ax == 0x11 || ax == 0xBB) + ExplodeFieldSP(si + FieldWidth); + + return subExplodeSnikSnaksBelow; +} // subExplodeSnikSnaksBelow + +// ========================================================================== +// SUBROUTINE +// Does pushing against an object kill Murphy? +// ========================================================================== +static boolean subMoveKillsMurphy(int si, int ax, int bl) +{ + static boolean subMoveKillsMurphy; + + int al, ah; + + al = LowByte(ax); + ah = HighByte(ax); + if (ax == 0xFFFF || ax == 0xAAAA || ah == 0) + goto loc_g_752E; + + if (al == fiZonk) + goto loc_g_74E7; + + if (al == fiExplosion) + goto loc_g_7530; + + if (fiOrangeDisk <= al && al <= fiPortUp) + goto loc_g_752E; + + ExplodeFieldSP(si); // Explode + subMoveKillsMurphy = True; + return subMoveKillsMurphy; + +loc_g_74E7: // zonk + if (bl == keyLeft) + goto loc_g_74F6; + + if (bl == keyRight) + goto loc_g_7512; + + ExplodeFieldSP(si); // Explode + subMoveKillsMurphy = True; + return subMoveKillsMurphy; + +loc_g_74F6: // zonk left + ah = ah & 0xF0; + if (! (ah == 0x20 || ah == 0x40 || ah == 0x50 || ah == 0x70)) + ExplodeFieldSP(si); + + subMoveKillsMurphy = True; // Set carry flag + return subMoveKillsMurphy; + +loc_g_7512: // zonk right + ah = ah & 0xF0; + if (! (ah == 0x30 || ah == 0x40 || ah == 0x60 || ah == 0x70)) + ExplodeFieldSP(si); + +loc_g_752E: // Marked fields and Ports + subMoveKillsMurphy = True; // Set carry flag + return subMoveKillsMurphy; + +loc_g_7530: // explosion + if ((ah & 0x80) != 0) + goto loc_g_753A; + + if (ah >= 4) + goto loc_g_753F; + +loc_g_753A: + ExplodeFieldSP(si); // Explode + subMoveKillsMurphy = True; // Set carry flag + return subMoveKillsMurphy; + +loc_g_753F: + PlayField16[si] = 0; + subMoveKillsMurphy = False; + + return subMoveKillsMurphy; +} // subMoveKillsMurphy + +// ========================================================================== +// SUBROUTINE +// Test If si 's a special (grav) port and If so Then fetch new values (see below) +// change conditions to port specs +// The 10-port data base is at data_h_0D28, 10 entries of 6 bytes each: +// (hi),(lo),(gravity),(freeze zonks),(freeze enemies),(unused) +// ========================================================================== +int subSpPortTest(int si) +{ + int subSpPortTest; + + int i, cx, bx; + + cx = LInfo.SpecialPortCount; // number of special ports + for (i = 1; i <= cx; i++) + { + { + bx = HighByte(LInfo.SpecialPort[i].PortLocation); + MovHighByte(&bx, LowByte(LInfo.SpecialPort[i].PortLocation)); + if (bx / 2 == si) + { + GravityFlag = LInfo.SpecialPort[i].Gravity; + FreezeZonks = LInfo.SpecialPort[i].FreezeZonks; + SnikSnaksElectronsFrozen = LInfo.SpecialPort[i].FreezeEnemies; + // RandomTime = RandomTime Xor RandomSeed 'is RandomTime used at all? no! + i = cx + 1; + } + + } + } + + return subSpPortTest; +} // subSpPortTest + +void subCopyFieldToScreen(int si, int fi) +{ + int X, Y; + + // +++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, fi); + // +++++++++++++++++++++++++++++++++++++++++ +} + +static void subEatRedDisk(int si) +{ + if (AllowRedDiskCheat == 0) + { + if (RedDiskReleasePhase != 0) + { + if (RedDiskReleaseMurphyPos == si) + return; + } + } + + RedDiskCount = (RedDiskCount + 1) % 256; + subDisplayRedDiskCount(); +} + +int subAdjustZonksInfotronsAboveMurphy(int si) +{ + int subAdjustZonksInfotronsAboveMurphy; + + int ax; + + if (LowByte(PlayField16[si]) != fiExplosion) + PlayField16[si] = 0; + + ax = PlayField16[si - FieldWidth]; + if (ax == 0 || ax == 0x9999) + goto loc_g_15A8; + + if (ax == fiZonk || ax == fiInfotron) + { + MovHighByte(&PlayField16[si - FieldWidth], 0x40); // make falling straigt down + } + + return subAdjustZonksInfotronsAboveMurphy; + +loc_g_15A8: // empty above + ax = PlayField16[si - FieldWidth - 1]; + if (ax == fiZonk || ax == fiInfotron) + goto loc_g_15C5; + +loc_g_15B6: + ax = PlayField16[si - FieldWidth + 1]; + if (ax == fiZonk || ax == fiInfotron) + goto loc_g_15E8; + + return subAdjustZonksInfotronsAboveMurphy; + +loc_g_15C5: // zonk/infotron above left + ax = PlayField16[si - 1]; + if (! (ax == fiZonk || ax == fiInfotron || ax == fiRAM)) // continue testing right above + goto loc_g_15B6; + + MovHighByte(&PlayField16[si - FieldWidth - 1], 0x60); // make roll right + PlayField16[si - FieldWidth] = 0x8888; + return subAdjustZonksInfotronsAboveMurphy; + +loc_g_15E8: // zonk/infotron above right + ax = PlayField16[si + 1]; + if (ax == fiZonk || ax == fiInfotron || ax == fiRAM) + { + MovHighByte(&PlayField16[si - FieldWidth + 1], 0x50); // make roll left + PlayField16[si - FieldWidth] = 0x8888; + } + + return subAdjustZonksInfotronsAboveMurphy; +} // subAdjustZonksInfotronsAboveMurphy diff --git a/src/game_sp/Murphy.h b/src/game_sp/Murphy.h new file mode 100644 index 00000000..0fdafeb7 --- /dev/null +++ b/src/game_sp/Murphy.h @@ -0,0 +1,21 @@ +// ---------------------------------------------------------------------------- +// Murphy.h +// ---------------------------------------------------------------------------- + +#ifndef MURPHY_H +#define MURPHY_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern int subAdjustZonksInfotronsAboveMurphy(int si); +extern int subAnimateMurphy(int si); +extern void subCopyFieldToScreen(int si, int fi); +extern int subExplodeSnikSnaksBelow(int si); +extern int subSpPortTest(int si); + +#endif /* MURPHY_H */ diff --git a/src/game_sp/OrangeDisk.c b/src/game_sp/OrangeDisk.c new file mode 100644 index 00000000..3a383b32 --- /dev/null +++ b/src/game_sp/OrangeDisk.c @@ -0,0 +1,86 @@ +// ---------------------------------------------------------------------------- +// OrangeDisk.c +// ---------------------------------------------------------------------------- + +#include "OrangeDisk.h" + +static char *VB_Name = "modOrangeDisk"; +// --- Option Explicit +// ========================================================================== +// SUBROUTINE +// Animate/move orange disks (falling) +// ========================================================================== + +int subAnimateOrangeDisks(int si) +{ + int subAnimateOrangeDisks; + + int ax, bl, dx, X, Y; + + ax = PlayField16[si]; + if (LowByte(ax) != fiOrangeDisk) + return subAnimateOrangeDisks; + + if (ax >= 0x3008) // disk is falling + goto loc_g_2804; + + if (ax >= 0x2008) // disk is in wait state before falling + goto loc_g_27DA; + + if (PlayField16[si + FieldWidth] == 0) + goto loc_g_27CF; + + return subAnimateOrangeDisks; + +loc_g_27CF: // below is empty -> disk may start to fall + MovHighByte(&PlayField16[si], 0x20); + MovHighByte(&PlayField16[si + FieldWidth], fiOrangeDisk); + return subAnimateOrangeDisks; + +loc_g_27DA: + if (PlayField16[si + FieldWidth] == 0) + { + PlayField16[si] = fiOrangeDisk; + return subAnimateOrangeDisks; + } // loc_g_27E8: + + bl = HighByte(PlayField16[si]) + 1; + if (bl == 0x22) // wait phase is finished + bl = 0x30; + + MovHighByte(&PlayField16[si], bl); + return subAnimateOrangeDisks; + +loc_g_2804: // disk is falling + // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + dx = HighByte(PlayField16[si]) & 0x7; + X = GetStretchX(si); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X, Y + TwoPixels * (dx + 1), fiOrangeDisk); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + bl = HighByte(PlayField16[si]) + 1; + if ((bl & 0x7) != 0) + { + MovHighByte(&PlayField16[si], bl); + return subAnimateOrangeDisks; + } + + PlayField16[si] = 0; + PlayField16[si + FieldWidth] = fiOrangeDisk; + si = si + FieldWidth; + if (PlayField16[si + FieldWidth] == 0) + { + MovHighByte(&PlayField16[si], 0x30); // go on falling down + MovHighByte(&PlayField16[si + FieldWidth], fiOrangeDisk); + return subAnimateOrangeDisks; + } // loc_g_2867: + + if (LowByte(PlayField16[si + FieldWidth]) == fiExplosion) + return subAnimateOrangeDisks; + + ExplodeFieldSP(si); // Explode + + return subAnimateOrangeDisks; +} // subAnimateOrangeDisks + diff --git a/src/game_sp/OrangeDisk.h b/src/game_sp/OrangeDisk.h new file mode 100644 index 00000000..2910b1db --- /dev/null +++ b/src/game_sp/OrangeDisk.h @@ -0,0 +1,17 @@ +// ---------------------------------------------------------------------------- +// OrangeDisk.h +// ---------------------------------------------------------------------------- + +#ifndef ORANGEDISK_H +#define ORANGEDISK_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern int subAnimateOrangeDisks(int si); + +#endif /* ORANGEDISK_H */ diff --git a/src/game_sp/PathTools.c b/src/game_sp/PathTools.c new file mode 100644 index 00000000..c1aafcb4 --- /dev/null +++ b/src/game_sp/PathTools.c @@ -0,0 +1,300 @@ +// ---------------------------------------------------------------------------- +// PathTools.c +// ---------------------------------------------------------------------------- + +#include "PathTools.h" + +static char *VB_Name = "PathTools_Module"; +// --- Option Explicit +// --- Option Compare Text + +// ########### Quote & UnQuote ################################################## + +void UnQuote(char *ST) +{ + long L; + + L = strlen(ST); + while (STRING_IS_LIKE(ST, "\"*")) + { + ST = Right(ST, L - 1); + L = L - 1; + } + + while (STRING_IS_LIKE(ST, "*\"")) + { + ST = Left(ST, L - 1); + } +} + +void Quote(char *ST) +{ + if (! STRING_IS_LIKE(ST, "\"*")) + ST = CAT("\"", ST); + + if (! STRING_IS_LIKE(ST, "*\"")) + ST = CAT(ST, "\""); +} + +char *UnQuoted(char *STRG) +{ + char *UnQuoted; + + long L; + char *ST; + + ST = STRG; + L = strlen(ST); + while (STRING_IS_LIKE(ST, "\"*")) + { + ST = Right(ST, L - 1); + L = L - 1; + } + + while (STRING_IS_LIKE(ST, "*\"")) + { + ST = Left(ST, L - 1); + } + + UnQuoted = ST; + + return UnQuoted; +} + +char *Quoted(char *STRG) +{ + char *Quoted; + + char *ST; + + ST = STRG; + if (! STRING_IS_LIKE(ST, "\"*")) + ST = CAT("\"", ST); + + if (! STRING_IS_LIKE(ST, "*\"")) + ST = CAT(ST, "\""); + + Quoted = ST; + + return Quoted; +} + +// ############ Path-/FileName-Extraction and concatanation ###################### + +char *StripDir(char *Path) +{ + char *StripDir; + + char *T; + long i; + + T = StrReverse(Path); + i = InStr(1, T, "/"); + if (i == 0) + StripDir = ""; + else + StripDir = StrReverse(Right(T, strlen(T) - i)); + + return StripDir; +} + +char *StripFileName(char *Path) +{ + char *StripFileName; + + char *T; + long i; + + T = StrReverse(Path); + if (STRING_IS_LIKE(T, "/*")) + T = Right(T, strlen(T) - 1); + + i = InStr(1, T, "/"); + if (i == 0) + i = strlen(T) + 1; + + if (i < 2) + StripFileName = ""; + else + StripFileName = StrReverse(Left(T, i - 1)); + + return StripFileName; +} + +char *StripExtension(char *Path) +{ + char *StripExtension; + + char *T; + long i, iSlash; + + T = StrReverse(Path); + iSlash = InStr(1, T, "/"); + i = InStr(1, T, "."); + if ((i < 2) || (iSlash < i)) + StripExtension = ""; + else + StripExtension = StrReverse(Left(T, i - 1)); + + return StripExtension; +} + +char *NewExtension(char *Path, char *NewExt) +{ + char *NewExtension; + + // NewExtension("C:\MyPath\MyFile.Old","New") returns "C:\MyPath\MyFile.New" + // NewExtension("C:\MyPath.dir\MyFile","New") returns "C:\MyPath\MyFile.New" + char *T; + long i, iSlash, ELen; + + T = StrReverse(Path); + iSlash = InStr(1, T, "/"); + i = InStr(1, T, "."); + if ((i < 1) || (iSlash < i)) + ELen = 0; + else + ELen = i; + + NewExtension = CAT(Left(StrReverse(T), strlen(T) - i), ".", NewExt); + + return NewExtension; +} + +char *StripExtensionlessFileName(char *Path) +{ + char *StripExtensionlessFileName; + + char *T, *T2; + long i, iSlash; + + T = StripFileName(Path); + T2 = StripExtension(Path); + StripExtensionlessFileName = Left(T, strlen(T) - strlen(T2) - (0 < strlen(T2) ? 1 : 1)); + + return StripExtensionlessFileName; +} + +char *WithSlash(char *Path) +{ + char *WithSlash; + + if (STRING_IS_LIKE(Path, "*/")) + { + WithSlash = Path; + } + else + { + WithSlash = CAT(Path, "/"); + } + + return WithSlash; +} + +char *SlashLess(char *Path) +{ + char *SlashLess; + + SlashLess = Path; + while (STRING_IS_LIKE(SlashLess, "*/")) + { + SlashLess = Left(Path, strlen(Path) - 1); + } + + return SlashLess; +} + +// ############ File-/Diresctory-Operations ###################################### + +boolean FileExists(char *Path) +{ + boolean FileExists; + + if ((STRING_IS_LIKE(Dir(Path), "")) || (STRING_IS_LIKE(Path, ""))) + FileExists = False; + else + FileExists = True; + + return FileExists; +} + +void MayKill(char *Path) +{ + + // --- On Error GoTo MayKillEH + Kill(Path); + // MayKillEH: +} + +boolean IsDir(char *Path) +{ + boolean IsDir; + + + // --- On Error Resume Next + IsDir = (vbDirectory == (GetAttr(Path) & vbDirectory)); + if (Err.Number != 0) + IsDir = False; + + return IsDir; +} + +// ######### binary comparison of files ########################################## + +boolean FilesEqual(char *Path1, char *Path2) +{ + boolean FilesEqual; + + int FNum1, FNum2; + long nSize, i; + boolean b1Open, b2Open; + byte *bin1, *bin2; + + FilesEqual = False; + // Debug.Assert(FileExists(Path1)); + // Debug.Assert(FileExists(Path2)); + if (! (FileExists(Path1) && FileExists(Path2))) + return FilesEqual; + + nSize = FileLen(Path1); + if (nSize != FileLen(Path2)) + return FilesEqual; + + bin1 = REDIM_1D(sizeof(byte), 0, nSize + 1 - 1); + bin2 = REDIM_1D(sizeof(byte), 0, nSize + 1 - 1); + b1Open = False; + b2Open = False; + + // --- On Error GoTo FilesEqualEH + // FNum1 = FreeFile(); + FNum1 = fopen(Path1, "rb"); + b1Open = True; + FILE_GET(FNum1, -1, &bin1, sizeof(bin1)); + fclose(FNum1); + b1Open = False; + // FNum2 = FreeFile(); + FNum2 = fopen(Path2, "rb"); + b2Open = True; + FILE_GET(FNum2, -1, &bin2, sizeof(bin2)); + fclose(FNum2); + b2Open = False; + // --- On Error GoTo 0 + + for (i = 1; i <= nSize; i++) + { + if (bin1[i] != bin2[i]) // return false + return FilesEqual; + } + + FilesEqual = True; + return FilesEqual; + +FilesEqualEH: + if (b1Open) + Close(FNum1); + + if (b2Open) + Close(FNum2); + + return FilesEqual; +} diff --git a/src/game_sp/PathTools.h b/src/game_sp/PathTools.h new file mode 100644 index 00000000..ce8fda49 --- /dev/null +++ b/src/game_sp/PathTools.h @@ -0,0 +1,31 @@ +// ---------------------------------------------------------------------------- +// PathTools.h +// ---------------------------------------------------------------------------- + +#ifndef PATHTOOLS_H +#define PATHTOOLS_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern boolean FileExists(char *Path); +extern boolean FilesEqual(char *Path1, char *Path2); +extern boolean IsDir(char *Path); +extern void MayKill(char *Path); +extern char *NewExtension(char *Path, char *NewExt); +extern void Quote(char *ST); +extern char *Quoted(char *STRG); +extern char *SlashLess(char *Path); +extern char *StripDir(char *Path); +extern char *StripExtension(char *Path); +extern char *StripExtensionlessFileName(char *Path); +extern char *StripFileName(char *Path); +extern void UnQuote(char *ST); +extern char *UnQuoted(char *STRG); +extern char *WithSlash(char *Path); + +#endif /* PATHTOOLS_H */ diff --git a/src/game_sp/SettingsObject.c b/src/game_sp/SettingsObject.c new file mode 100644 index 00000000..06c656b9 --- /dev/null +++ b/src/game_sp/SettingsObject.c @@ -0,0 +1,40 @@ +// ---------------------------------------------------------------------------- +// SettingsObject.c +// ---------------------------------------------------------------------------- + +#include "SettingsObject.h" + +// --- VERSION 1.0 CLASS +// --- BEGIN +// --- MultiUse = -1 'True // True +// --- Persistable = 0 'NotPersistable // NotPersistable +// --- DataBindingBehavior = 0 'vbNone // vbNone +// --- DataSourceBehavior = 0 'vbNone // vbNone +// --- MTSTransactionMode = 0 'NotAnMTSObject // NotAnMTSObject +// --- END + +static char *VB_Name = "SettingsObject"; +static boolean VB_GlobalNameSpace = False; +static boolean VB_Creatable = True; +static boolean VB_PredeclaredId = False; +static boolean VB_Exposed = False; +// --- Option Explicit +// --- Option Compare Text + +const char *AppName = "MegaPlex"; +const char *Config = "Config"; + +void SettingsObject_Save(char *ValName, int Val) +{ + SaveSetting(AppName, Config, ValName, Val); +} + +int SettingsObject_Read(char *ValName, int Default) +{ + int Read; + + Read = GetSetting(AppName, Config, ValName, Default); + + return Read; +} + diff --git a/src/game_sp/SettingsObject.h b/src/game_sp/SettingsObject.h new file mode 100644 index 00000000..a25e4f28 --- /dev/null +++ b/src/game_sp/SettingsObject.h @@ -0,0 +1,18 @@ +// ---------------------------------------------------------------------------- +// SettingsObject.h +// ---------------------------------------------------------------------------- + +#ifndef SETTINGSOBJECT_H +#define SETTINGSOBJECT_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern int SettingsObject_Read(char *ValName, int Default); +extern void SettingsObject_Save(char *ValName, int Val); + +#endif /* SETTINGSOBJECT_H */ diff --git a/src/game_sp/SnikSnaks.c b/src/game_sp/SnikSnaks.c new file mode 100644 index 00000000..13214817 --- /dev/null +++ b/src/game_sp/SnikSnaks.c @@ -0,0 +1,703 @@ +// ---------------------------------------------------------------------------- +// SnikSnaks.c +// ---------------------------------------------------------------------------- + +#include "SnikSnaks.h" + +static int subDrawSnikSnakFromAbove(int si, int bx); +static int subDrawSnikSnakFromBelow(int si, int bx); +static int subDrawSnikSnakFromLeft(int si, int bx); +static int subDrawSnikSnakFromRight(int si, int bx); +static int subDrawSnikSnakTurnLeft(int si, int bx); +static int subDrawSnikSnakTurnRight(int si, int bx); +static int subSnikSnakFromAbove(int si, int bx); +static int subSnikSnakFromBelow(int si, int bx); +static int subSnikSnakFromLeft(int si, int bx); +static int subSnikSnakFromRight(int si, int bx); +static int subSnikSnakTurnLeft(int si, int bx); +static int subSnikSnakTurnRight(int si, int bx); + +static char *VB_Name = "modSnikSnak"; +// --- Option Explicit +// ========================================================================== +// SUBROUTINE +// Animate/move Snik-Snaks +// ========================================================================== + +int subAnimateSnikSnaks(int si) +{ + int subAnimateSnikSnaks; + + int bx, Tmp; + + if (SnikSnaksElectronsFrozen == 1) + return subAnimateSnikSnaks; + + // If LowByte(PlayField16(si)) <> fiSnikSnak Then Exit Function + // Debug.Assert (LowByte(PlayField16[si]) == fiSnikSnak); + bx = HighByte(PlayField16[si]); + Tmp = bx / 8; + switch (Tmp) + { + case 0: + subSnikSnakTurnLeft(si, bx); // turning, bx=0 -> point N, bx = 1 -> point NW etc. + break; + + case 1: + subSnikSnakTurnRight(si, bx); // turn right + break; + + case 2: + subSnikSnakFromBelow(si, bx); // access si from below + break; + + case 3: + subSnikSnakFromRight(si, bx); // access si from right + break; + + case 4: + subSnikSnakFromAbove(si, bx); // access si from above + break; + + case 5: + subSnikSnakFromLeft(si, bx); // access si from left + break; + + default: + // Debug.Assert(False); + break; + } + + return subAnimateSnikSnaks; +} // subAnimateSnikSnaks + +int subDrawAnimatedSnikSnaks(int si) +{ + int subDrawAnimatedSnikSnaks; + + int bx, Tmp; + + // If SnikSnaksElectronsFrozen = 1 Then Exit Function + if (LowByte(PlayField16[si]) != fiSnikSnak) + return subDrawAnimatedSnikSnaks; + + bx = HighByte(PlayField16[si]); + Tmp = bx / 8; + switch (Tmp) + { + case 0: + subDrawSnikSnakTurnLeft(si, bx); // turning, bx=0 -> point N, bx = 1 -> point NW etc. + break; + + case 1: + subDrawSnikSnakTurnRight(si, bx); // turn right + break; + + case 2: + subDrawSnikSnakFromBelow(si, bx); // access si from below + break; + + case 3: + subDrawSnikSnakFromRight(si, bx); // access si from right + break; + + case 4: + subDrawSnikSnakFromAbove(si, bx); // access si from above + break; + + case 5: + subDrawSnikSnakFromLeft(si, bx); // access si from left + break; + } + + return subDrawAnimatedSnikSnaks; +} // subAnimateSnikSnaks + +static int subSnikSnakTurnLeft(int si, int bx) +{ + static int subSnikSnakTurnLeft; + + int ax, ah, bl, dx, X, Y; + + ax = (TimerVar & 3); + if (ax != 0) + { + if (ax == 3) + goto loc_g_7622; + + return subSnikSnakTurnLeft; + } // loc_g_75E0: + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, aniSnikSnak[bx]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bx = (bx + 1) & 0x7; + MovHighByte(&PlayField16[si], bx); + return subSnikSnakTurnLeft; + +locMayExplode760A: + ah = HighByte(ax); + if (ah == 0x1B) + return subSnikSnakTurnLeft; + + if (ah == 0x19) + return subSnikSnakTurnLeft; + + if (ah == 0x18) + return subSnikSnakTurnLeft; + + if (ah == 0x1A) + return subSnikSnakTurnLeft; + + ExplodeFieldSP(si); // Explode + return subSnikSnakTurnLeft; + +loc_g_7622: + bl = HighByte(PlayField16[si]); + if (bl == 0) + goto loc_g_763B; + + if (bl == 2) + goto loc_g_765E; + + if (bl == 4) + goto loc_g_7681; + + if (bl == 6) + goto loc_g_76A7; + + return subSnikSnakTurnLeft; + +loc_g_763B: // pointing up + ax = PlayField16[si - FieldWidth]; + if (ax == 0) // above is empty -> go up + goto loc_g_764E; + + if (LowByte(ax) == fiMurphy) // above is murphy -> explode + goto locMayExplode760A; + + return subSnikSnakTurnLeft; + +loc_g_764E: // above is empty -> go up + PlayField16[si] = 0x1BB; + si = si - FieldWidth; + PlayField16[si] = 0x1011; + return subSnikSnakTurnLeft; + +loc_g_765E: // pointing left + ax = PlayField16[si - 1]; + if (ax == 0) // left is empty -> go there + goto loc_g_7671; + + if (LowByte(ax) == fiMurphy) // left is murphy -> explode + goto locMayExplode760A; + + return subSnikSnakTurnLeft; + +loc_g_7671: // left is empty -> go there + PlayField16[si] = 0x2BB; + si = si - 1; + PlayField16[si] = 0x1811; + return subSnikSnakTurnLeft; + +loc_g_7681: // pointing down + ax = PlayField16[si + FieldWidth]; + if (ax == 0) // below is empty -> go down + goto loc_g_7697; + + if (LowByte(ax) == fiMurphy) // below is murphy -> explode + goto locMayExplode760A; + + return subSnikSnakTurnLeft; + +loc_g_7697: // below is empty -> go down + PlayField16[si] = 0x3BB; + si = si + FieldWidth; + PlayField16[si] = 0x2011; + return subSnikSnakTurnLeft; + +loc_g_76A7: // pointing Right + ax = PlayField16[si + 1]; + if (ax == 0) // right is empty -> go there + goto loc_g_76BD; + + if (LowByte(ax) == fiMurphy) // right is murphy -> explode + goto locMayExplode760A; + + return subSnikSnakTurnLeft; + +loc_g_76BD: // right is empty -> go there + PlayField16[si] = 0x4BB; + si = si + 1; + PlayField16[si] = 0x2811; + + return subSnikSnakTurnLeft; +} // subSnikSnakTurnLeft + +static int subSnikSnakTurnRight(int si, int bx) +{ + static int subSnikSnakTurnRight; + + int ax, ah, bl, dx, X, Y; + + ax = (TimerVar & 3); + if (ax != 0) + { + if (ax == 3) + goto loc_g_771F; + + return subSnikSnakTurnRight; + } // loc_g_76DB: + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, aniSnikSnak[0x10 - bx]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bx = ((bx + 1) & 0x7) | 8; + MovHighByte(&PlayField16[si], bx); + return subSnikSnakTurnRight; + +locMayExplode7707: + ah = HighByte(ax); + if (ah == 0x1B) + return subSnikSnakTurnRight; + + if (ah == 0x19) + return subSnikSnakTurnRight; + + if (ah == 0x18) + return subSnikSnakTurnRight; + + if (ah == 0x1A) + return subSnikSnakTurnRight; + + ExplodeFieldSP(si); // Explode + return subSnikSnakTurnRight; + +loc_g_771F: + bl = HighByte(PlayField16[si]); + if (bl == 0x8) + goto loc_g_7738; + + if (bl == 0xA) + goto loc_g_77A4; + + if (bl == 0xC) + goto loc_g_777E; + + if (bl == 0xE) + goto loc_g_775B; + + return subSnikSnakTurnRight; + +loc_g_7738: // pointing up + ax = PlayField16[si - FieldWidth]; + if (ax == 0) // above is empty -> go up + goto loc_g_774B; + + if (LowByte(ax) == fiMurphy) // above is murphy -> explode + goto locMayExplode7707; + + return subSnikSnakTurnRight; + +loc_g_774B: // above is empty -> go up + PlayField16[si] = 0x1BB; + si = si - FieldWidth; + PlayField16[si] = 0x1011; + return subSnikSnakTurnRight; + +loc_g_775B: // pointing left + ax = PlayField16[si - 1]; + if (ax == 0) // left is empty -> go there + goto loc_g_776E; + + if (LowByte(ax) == fiMurphy) // left is murphy -> explode + goto locMayExplode7707; + + return subSnikSnakTurnRight; + +loc_g_776E: // left is empty -> go there + PlayField16[si] = 0x2BB; + si = si - 1; + PlayField16[si] = 0x1811; + return subSnikSnakTurnRight; + +loc_g_777E: // pointing down + ax = PlayField16[si + FieldWidth]; + if (ax == 0) // below is empty -> go down + goto loc_g_7794; + + if (LowByte(ax) == fiMurphy) // below is murphy -> explode + goto locMayExplode7707; + + return subSnikSnakTurnRight; + +loc_g_7794: // below is empty -> go down + PlayField16[si] = 0x3BB; + si = si + FieldWidth; + PlayField16[si] = 0x2011; + return subSnikSnakTurnRight; + +loc_g_77A4: // pointing Right + ax = PlayField16[si + 1]; + if (ax == 0) // right is empty -> go there + goto loc_g_77BA; + + if (LowByte(ax) == fiMurphy) // right is murphy -> explode + goto locMayExplode7707; + + return subSnikSnakTurnRight; + +loc_g_77BA: // right is empty -> go there + PlayField16[si] = 0x4BB; + si = si + 1; + PlayField16[si] = 0x2811; + + return subSnikSnakTurnRight; +} // subSnikSnakTurnRight + +static int subSnikSnakFromBelow(int si, int bx) +{ + static int subSnikSnakFromBelow; + + int ax, ah, bl, dx, X, Y; + + bx = bx - 0xF; // get and increment sequence# + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si + FieldWidth); + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X, Y - bx * TwoPixels, aniSnikSnakUp + bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bl = LowByte(bx); + if (bl == 7 && LowByte(PlayField16[si + FieldWidth]) != fiExplosion) + { + PlayField16[si + FieldWidth] = 0; // sniknak left that field + } + + if (bl < 8) // sniksnak still goes up + { + bl = bl + 0x10; + MovHighByte(&PlayField16[si], bl); + return subSnikSnakFromBelow; + } // loc_g_7813 + + PlayField16[si] = 0x11; // sequence#=8 -> arrived at the new field + ax = PlayField16[si - 1]; // check left field + if (ax == 0 || LowByte(ax) == fiMurphy) // check for empty or murphy + { + MovHighByte(&PlayField16[si], 1); // start to turn left + return subSnikSnakFromBelow; + } // loc_g_7826: and 'loc_g_7833: + + ax = PlayField16[si - FieldWidth]; // cannot turn left -> check above + if (ax == 0) // check if empty + { + PlayField16[si] = 0x1BB; // mark as "sniksnak leaving" + si = si - FieldWidth; // go up! + PlayField16[si] = 0x1011; + return subSnikSnakFromBelow; + } // loc_g_784A: + + if (LowByte(ax) == fiMurphy) // check for murphy above + { + ExplodeFieldSP(si); // Explode + return subSnikSnakFromBelow; + } // loc_g_7855: + + ax = PlayField16[si + 1]; // check right field + if (ax == 0 || LowByte(ax) == fiMurphy) // check for empty or murphy + { + MovHighByte(&PlayField16[si], 9); // start to turn right + return subSnikSnakFromBelow; + } // loc_g_7862: and 'loc_g_786F: + + // else: no way to go, start turning around + MovHighByte(&PlayField16[si], 1); + + return subSnikSnakFromBelow; +} // subSnikSnakFromBelow + +static int subSnikSnakFromRight(int si, int bx) +{ + static int subSnikSnakFromRight; + + int ax, ah, bl, dx, X, Y; + + bx = bx - 0x17; // get and increment sequence# + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si + 1); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X - bx * TwoPixels, Y, aniSnikSnakLeft + bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bl = LowByte(bx); + if (bl == 7 && LowByte(PlayField16[si + 1]) != fiExplosion) + { + PlayField16[si + 1] = 0; // sniknak left that field + } // loc_g_78AC: + + if (bl < 8) // sniksnak still goes left + { + bl = bl + 0x18; + MovHighByte(&PlayField16[si], bl); + return subSnikSnakFromRight; + } // loc_g_78B9: + + PlayField16[si] = 0x11; // sequence#=8 -> arrived at the new field + ax = PlayField16[si + FieldWidth]; // check below + if (ax == 0 || LowByte(ax) == fiMurphy) // empty or murphy? + { + MovHighByte(&PlayField16[si], 3); // yes -> turn left down + return subSnikSnakFromRight; + } // loc_g_78CC: and 'loc_g_78D9: + + ax = PlayField16[si - 1]; // check left, etc ... see the comments on subSnikSnakFromBelow() + if (ax == 0) + { + PlayField16[si] = 0x2BB; + si = si - 1; // 1 field left + PlayField16[si] = 0x1811; + return subSnikSnakFromRight; + } // loc_g_78F0: + + if (LowByte(ax) == fiMurphy) + { + ExplodeFieldSP(si); // Explode + return subSnikSnakFromRight; + } // loc_g_78FB: + + ax = PlayField16[si - FieldWidth]; // check above + if (ax == 0 || LowByte(ax) == fiMurphy) + { + MovHighByte(&PlayField16[si], 0xF); + return subSnikSnakFromRight; + } // loc_g_7908:loc_g_7915: + + MovHighByte(&PlayField16[si], 3); + + return subSnikSnakFromRight; +} // subSnikSnakFromRight + +static int subSnikSnakFromAbove(int si, int bx) +{ + static int subSnikSnakFromAbove; + + int ax, ah, bl, dx, X, Y; + + bx = bx - 0x1F; // get and increment sequence# + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si - FieldWidth); + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X, Y + bx * TwoPixels, aniSnikSnakDown + bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bl = LowByte(bx); + if (bl == 7 && LowByte(PlayField16[si - FieldWidth]) != fiExplosion) + { + PlayField16[si - FieldWidth] = 0; // sniknak left that field + } + + if (bl < 8) // sniksnak still goes down + { + bl = bl + 0x20; + MovHighByte(&PlayField16[si], bl); + return subSnikSnakFromAbove; + } // loc_g_7813 + + PlayField16[si] = 0x11; // sequence#=8 -> arrived at the new field + ax = PlayField16[si + 1]; // check right + if (ax == 0 || LowByte(ax) == fiMurphy) + { + MovHighByte(&PlayField16[si], 5); + return subSnikSnakFromAbove; + } // loc_g_7986: + + ax = PlayField16[si + FieldWidth]; // check below + if (ax == 0) + { + PlayField16[si] = 0x3BB; + si = si + FieldWidth; // 1 field down + PlayField16[si] = 0x2011; + return subSnikSnakFromAbove; + } // loc_g_799D: + + if (LowByte(ax) == fiMurphy) + { + ExplodeFieldSP(si); // Explode + return subSnikSnakFromAbove; + } // loc_g_79A8: + + ax = PlayField16[si - 1]; // check left + if (ax == 0 || LowByte(ax) == fiMurphy) + { + MovHighByte(&PlayField16[si], 0xD); + return subSnikSnakFromAbove; + } // loc_g_79C2: + + MovHighByte(&PlayField16[si], 5); + + return subSnikSnakFromAbove; +} // subSnikSnakFromAbove + +static int subSnikSnakFromLeft(int si, int bx) +{ + static int subSnikSnakFromLeft; + + int ax, ah, bl, dx, X, Y; + + bx = bx - 0x27; // get and increment sequence# + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si - 1); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X + bx * TwoPixels, Y, aniSnikSnakRight + bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bl = LowByte(bx); + if (bl == 7 && LowByte(PlayField16[si - 1]) != fiExplosion) + { + PlayField16[si - 1] = 0; // sniknak left that field + } + + if (bl < 8) // sniksnak still goes right + { + bl = bl + 0x28; + MovHighByte(&PlayField16[si], bl); + return subSnikSnakFromLeft; + } // loc_g_78B9: + + PlayField16[si] = 0x11; // sequence#=8 -> arrived at the new field + ax = PlayField16[si - FieldWidth]; // check above + if (ax == 0 || LowByte(ax) == fiMurphy) + { + MovHighByte(&PlayField16[si], 7); + return subSnikSnakFromLeft; + } // loc_g_7A2D: + + ax = PlayField16[si + 1]; // check right(straight on) + if (ax == 0) + { + PlayField16[si] = 0x4BB; + si = si + 1; // 1 field right + PlayField16[si] = 0x2811; + return subSnikSnakFromLeft; + } // loc_g_7A44: + + if (LowByte(ax) == fiMurphy) + { + ExplodeFieldSP(si); // Explode + return subSnikSnakFromLeft; + } // loc_g_7A4F: + + ax = PlayField16[si + FieldWidth]; // check below + if (ax == 0 || LowByte(ax) == fiMurphy) + { + MovHighByte(&PlayField16[si], 0xB); + return subSnikSnakFromLeft; + } // loc_g_7A69: + + MovHighByte(&PlayField16[si], 7); + + return subSnikSnakFromLeft; +} // subSnikSnakFromLeft + +static int subDrawSnikSnakTurnLeft(int si, int bx) +{ + static int subDrawSnikSnakTurnLeft; + + int X, Y; + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, aniSnikSnak[bx]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + return subDrawSnikSnakTurnLeft; +} + +static int subDrawSnikSnakTurnRight(int si, int bx) +{ + static int subDrawSnikSnakTurnRight; + + int X, Y; + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, aniSnikSnak[0x10 - bx]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + return subDrawSnikSnakTurnRight; +} + +static int subDrawSnikSnakFromBelow(int si, int bx) +{ + static int subDrawSnikSnakFromBelow; + + int X, Y; + + bx = bx - 0xF; // get and anti-increment sequence# + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si + FieldWidth); + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X, Y - bx * TwoPixels, aniSnikSnakUp + bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + return subDrawSnikSnakFromBelow; +} + +static int subDrawSnikSnakFromRight(int si, int bx) +{ + static int subDrawSnikSnakFromRight; + + int X, Y; + + bx = bx - 0x17; // get and increment sequence# + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si + 1); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X - bx * TwoPixels, Y, aniSnikSnakLeft + bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + return subDrawSnikSnakFromRight; +} + +static int subDrawSnikSnakFromAbove(int si, int bx) +{ + static int subDrawSnikSnakFromAbove; + + int X, Y; + + bx = bx - 0x1F; // get and increment sequence# + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si - FieldWidth); + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X, Y + bx * TwoPixels, aniSnikSnakDown + bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + return subDrawSnikSnakFromAbove; +} + +static int subDrawSnikSnakFromLeft(int si, int bx) +{ + static int subDrawSnikSnakFromLeft; + + int X, Y; + + bx = bx - 0x27; // get and increment sequence# + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si - 1); + Y = GetStretchY(si); + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X + bx * TwoPixels, Y, aniSnikSnakRight + bx); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + + return subDrawSnikSnakFromLeft; +} diff --git a/src/game_sp/SnikSnaks.h b/src/game_sp/SnikSnaks.h new file mode 100644 index 00000000..ddebccfe --- /dev/null +++ b/src/game_sp/SnikSnaks.h @@ -0,0 +1,18 @@ +// ---------------------------------------------------------------------------- +// SnikSnaks.h +// ---------------------------------------------------------------------------- + +#ifndef SNIKSNAKS_H +#define SNIKSNAKS_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern int subAnimateSnikSnaks(int si); +extern int subDrawAnimatedSnikSnaks(int si); + +#endif /* SNIKSNAKS_H */ diff --git a/src/game_sp/Sound.c b/src/game_sp/Sound.c new file mode 100644 index 00000000..3965e752 --- /dev/null +++ b/src/game_sp/Sound.c @@ -0,0 +1,178 @@ +// ---------------------------------------------------------------------------- +// Sound.c +// ---------------------------------------------------------------------------- + +#include "Sound.h" + +static char *VB_Name = "modSound"; +// --- Option Explicit + +int MusicOnFlag; +int FXOnFlag; + +DirectSoundBuffer ZonkFX[1 + 1]; +DirectSoundBuffer InfotronFX[1 + 1]; +DirectSoundBuffer BugFX[1 + 1]; +DirectSoundBuffer ExplosionFX[1 + 1]; +DirectSoundBuffer PushFX; +DirectSoundBuffer ExitFX; +DirectSoundBuffer BaseFX; + +#if 0 + +void LoadSoundFX() +{ + DSBUFFERDESC bufferDesc; + WAVEFORMATEX waveFormat; + char *FName; + int i; + + bufferDesc.lFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_STATIC; + waveFormat.nFormatTag = WAVE_FORMAT_PCM; + waveFormat.nChannels = 1; + waveFormat.lSamplesPerSec = 8000; + waveFormat.nBitsPerSample = 8; + waveFormat.nBlockAlign = waveFormat.nBitsPerSample / 8 * waveFormat.nChannels; + waveFormat.lAvgBytesPerSec = waveFormat.lSamplesPerSec * waveFormat.nBlockAlign; + FName = CAT(App.Path, "/Sound/"); + for (i = 0; i <= 1; i++) + { + ZonkFX[i] = DSound.CreateSoundBufferFromFile(CAT(FName, "Zonk.wav"), bufferDesc, waveFormat); + InfotronFX[i] = DSound.CreateSoundBufferFromFile(CAT(FName, "Infotron.wav"), bufferDesc, waveFormat); + BugFX[i] = DSound.CreateSoundBufferFromFile(CAT(FName, "Bug.wav"), bufferDesc, waveFormat); + ExplosionFX[i] = DSound.CreateSoundBufferFromFile(CAT(FName, "Explosion.wav"), bufferDesc, waveFormat); + } + + BaseFX = DSound.CreateSoundBufferFromFile(CAT(FName, "Base.wav"), bufferDesc, waveFormat); + ExitFX = DSound.CreateSoundBufferFromFile(CAT(FName, "Exit.wav"), bufferDesc, waveFormat); + PushFX = DSound.CreateSoundBufferFromFile(CAT(FName, "Push.wav"), bufferDesc, waveFormat); + // FXOnFlag = 0 +} + +#endif + +void subSoundFXZonk() +{ + int i; + + if (FXOnFlag == 0) + return; + + for (i = 0; i <= 1; i++) + { + if (! IS_NOTHING(&ZonkFX[i], sizeof(ZonkFX[i]))) + { + if (ZonkFX[i].GetStatus() != DSBSTATUS_PLAYING) + { + ZonkFX[i].Play DSBPLAY_DEFAULT; + break; + } + } + } +} + +void subSoundFXBug() +{ + int i; + + if (FXOnFlag == 0) + return; + + for (i = 0; i <= 1; i++) + { + if (! IS_NOTHING(&BugFX[i], sizeof(BugFX[i]))) + { + if (BugFX[i].GetStatus() != DSBSTATUS_PLAYING) + { + BugFX[i].Play DSBPLAY_DEFAULT; + break; + } + } + } +} + +void subSoundFXInfotron() +{ + int i; + + if (FXOnFlag == 0) + return; + + for (i = 0; i <= 1; i++) + { + if (! IS_NOTHING(&InfotronFX[i], sizeof(InfotronFX[i]))) + { + if (InfotronFX[i].GetStatus() != DSBSTATUS_PLAYING) + { + InfotronFX[i].Play DSBPLAY_DEFAULT; + break; + } + } + } +} + +void subSoundFXExplosion() +{ + int i; + + if (FXOnFlag == 0) + return; + + for (i = 0; i <= 1; i++) + { + if (! IS_NOTHING(&ExplosionFX[i], sizeof(ExplosionFX[i]))) + { + if (ExplosionFX[i].GetStatus() != DSBSTATUS_PLAYING) + { + ExplosionFX[i].Play DSBPLAY_DEFAULT; + break; + } + } + } +} + +void subSoundFXBase() +{ + if (FXOnFlag == 0) + return; + + if (IS_NOTHING(&BaseFX, sizeof(BaseFX))) + return; + + if (BaseFX.GetStatus() != DSBSTATUS_PLAYING) + { + BaseFX.Play DSBPLAY_DEFAULT; + } +} + +void subSoundFXPush() +{ + if (FXOnFlag == 0) + return; + + if (IS_NOTHING(&PushFX, sizeof(PushFX))) + return; + + if (PushFX.GetStatus() != DSBSTATUS_PLAYING) + { + PushFX.Play DSBPLAY_DEFAULT; + } +} + +void subSoundFXExit() +{ + if (FXOnFlag == 0) + return; + + if (IS_NOTHING(&ExitFX, sizeof(ExitFX))) + return; + + if (ExitFX.GetStatus() != DSBSTATUS_PLAYING) + { + ExitFX.Play DSBPLAY_DEFAULT; + } +} + +void subMusicInit() +{ +} diff --git a/src/game_sp/Sound.h b/src/game_sp/Sound.h new file mode 100644 index 00000000..ad337a3b --- /dev/null +++ b/src/game_sp/Sound.h @@ -0,0 +1,28 @@ +// ---------------------------------------------------------------------------- +// Sound.h +// ---------------------------------------------------------------------------- + +#ifndef SOUND_H +#define SOUND_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern void LoadSoundFX(); +extern void subMusicInit(); +extern void subSoundFXBase(); +extern void subSoundFXBug(); +extern void subSoundFXExit(); +extern void subSoundFXExplosion(); +extern void subSoundFXInfotron(); +extern void subSoundFXPush(); +extern void subSoundFXZonk(); + +extern int FXOnFlag; +extern int MusicOnFlag; + +#endif /* SOUND_H */ diff --git a/src/game_sp/TickCountObject.c b/src/game_sp/TickCountObject.c new file mode 100644 index 00000000..ed9c50ef --- /dev/null +++ b/src/game_sp/TickCountObject.c @@ -0,0 +1,215 @@ +// ---------------------------------------------------------------------------- +// TickCountObject.c +// ---------------------------------------------------------------------------- + +#include "TickCountObject.h" + +// --- VERSION 1.0 CLASS +// --- BEGIN +// --- MultiUse = -1 'True // True +// --- Persistable = 0 'NotPersistable // NotPersistable +// --- DataBindingBehavior = 0 'vbNone // vbNone +// --- DataSourceBehavior = 0 'vbNone // vbNone +// --- MTSTransactionMode = 0 'NotAnMTSObject // NotAnMTSObject +// --- END + +// static char *VB_Name = "TickCountObject"; +// static boolean VB_GlobalNameSpace = False; +// static boolean VB_Creatable = True; +// static boolean VB_PredeclaredId = False; +// static boolean VB_Exposed = False; +// --- Option Explicit + +#define LongMin (-(double)2147483648) // the "#" sign is a bug of the VB environment AutoFormat function but causes no real problems; don't worry 'bout it! +#define LongMax (2147483647) + +long GetTickCount(); +long QueryPerformanceCounter(currency lpPerformanceCount); +long QueryPerformanceFrequency(currency lpFrequency); + +boolean DelayLoopActive; + +boolean MPause, bHighPerf; +currency PFreq; // LARGE_INTEGER +double sFactor, msFactor, usFactor; + +boolean TickCountObject_Get_Active() +{ + boolean Active; + + Active = DelayLoopActive; + + return Active; +} + +boolean TickCountObject_Get_Pause() +{ + boolean Pause; + + Pause = MPause; + + return Pause; +} + +void TickCountObject_Let_Pause(boolean NewVal) +{ + MPause = NewVal; +} + +void TickCountObject_DelayMS(long MSInterval, boolean DoEventsFlag) // in ms +{ + currency Start; + + Start = TickNow(); + DelayLoopActive = True; + do + { + if (DoEventsFlag) + DoEvents(); + + if (MSInterval <= TickDiffMS(Start) && ! MPause) + break; + } + while (1); + + DelayLoopActive = False; +} + +// for compatibility with old code: +void TickCountObject_DelayS(long SInterval, boolean DoEventsFlag) // in s +{ + // check if SInterval is less than 25 days ... + if ((int)(LongMax / 1000) <= SInterval) + { + Err.Raise(513, "Delay()", "Value Overflow"); + } + else + { + TickCountObject_DelayMS((long)1000 * SInterval, DoEventsFlag); + } +} + +currency TickCountObject_Get_TickNow() +{ + currency TickNow; + + if (bHighPerf) + { + QueryPerformanceCounter(TickNow); + } + else + { + TickNow = GetTickCount(); + } + + return TickNow; +} + +long TickCountObject_TickDiffS(currency TickStart) +{ + long TickDiffS; + + currency NewTick, TD; + + if (bHighPerf) + { + QueryPerformanceCounter(NewTick); + TD = (NewTick - TickStart); + TickDiffS = sFactor * TD; + } + else + { + NewTick = GetTickCount(); + if (NewTick < TickStart) + { + // Overflow occured and needs to be handled + TickDiffS = (LongMax - TickStart) + (NewTick - LongMin) + 1; + } + else + { + TickDiffS = NewTick - TickStart; + } + + TickDiffS = Int(TickDiffS / 1000); + } + + return TickDiffS; +} + +long TickCountObject_TickDiffMS(currency TickStart) +{ + long TickDiffMS; + + currency NewTick, TD; + + if (bHighPerf) + { + QueryPerformanceCounter(NewTick); + TD = (NewTick - TickStart); + TickDiffMS = msFactor * TD; + } + else + { + NewTick = GetTickCount(); + if (NewTick < TickStart) + { + // Overflow occured and needs to be handled + TickDiffMS = (LongMax - TickStart) + (NewTick - LongMin) + 1; + } + else + { + TickDiffMS = NewTick - TickStart; + } + } + + return TickDiffMS; +} + +currency TickCountObject_TickDiffUS(currency TickStart) +{ + currency TickDiffUS; + + currency NewTick, TD; + + if (bHighPerf) + { + QueryPerformanceCounter(NewTick); + TD = (NewTick - TickStart); + TickDiffUS = usFactor * TD; + } + else + { + NewTick = GetTickCount(); + if (NewTick < TickStart) + { + // Overflow occured and needs to be handled + TickDiffUS = ((LongMax - TickStart) + (NewTick - LongMin) + 1) * (currency)1000; + } + else + { + TickDiffUS = (NewTick - TickStart) * (currency)1000; + } + } + + return TickDiffUS; +} + +#if 0 + +static void Class_Initialize() +{ + long L; + + bHighPerf = (0 != QueryPerformanceFrequency(PFreq)); + if (bHighPerf) + { + sFactor = (double)1 / PFreq; + msFactor = (double)1000 / PFreq; + usFactor = (double)1000000 / PFreq; + } + + DelayLoopActive = False; + TickCountObject_Let_Pause(False); +} + +#endif diff --git a/src/game_sp/TickCountObject.h b/src/game_sp/TickCountObject.h new file mode 100644 index 00000000..50a34545 --- /dev/null +++ b/src/game_sp/TickCountObject.h @@ -0,0 +1,25 @@ +// ---------------------------------------------------------------------------- +// TickCountObject.h +// ---------------------------------------------------------------------------- + +#ifndef TICKCOUNTOBJECT_H +#define TICKCOUNTOBJECT_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern void TickCountObject_DelayMS(long MSInterval, boolean DoEventsFlag); +extern void TickCountObject_DelayS(long SInterval, boolean DoEventsFlag); +extern boolean TickCountObject_Get_Active(); +extern boolean TickCountObject_Get_Pause(); +extern currency TickCountObject_Get_TickNow(); +extern void TickCountObject_Let_Pause(boolean NewVal); +extern long TickCountObject_TickDiffMS(currency TickStart); +extern long TickCountObject_TickDiffS(currency TickStart); +extern currency TickCountObject_TickDiffUS(currency TickStart); + +#endif /* TICKCOUNTOBJECT_H */ diff --git a/src/game_sp/TopMost.c b/src/game_sp/TopMost.c new file mode 100644 index 00000000..319f0ea0 --- /dev/null +++ b/src/game_sp/TopMost.c @@ -0,0 +1,51 @@ +// ---------------------------------------------------------------------------- +// TopMost.c +// ---------------------------------------------------------------------------- + +#include "TopMost.h" + +// static char *VB_Name = "TopMost_Module"; +// --- Option Explicit +// --- const int SWP_FRAMECHANGED = 0x20; +// --- const int SWP_HIDEWINDOW = 0x80; +// --- const int SWP_NOACTIVATE = 0x10; +// --- const int SWP_NOCOPYBITS = 0x100; +// --- const int SWP_NOMOVE = 0x2; +// --- const int SWP_NOOWNERZORDER = 0x200; +// --- const int SWP_NOREDRAW = 0x8; +// --- const int SWP_NOSIZE = 0x1; +// --- const int SWP_NOZORDER = 0x4; +// --- const int SWP_SHOWWINDOW = 0x40; +// --- const int SWP_DRAWFRAME = SWP_FRAMECHANGED; +// --- const int SWP_NOREPOSITION = SWP_NOOWNERZORDER; + +// --- const int HWND_BOTTOM = 1; +// --- const int HWND_BROADCAST = 0xFFFF; +// --- const int HWND_DESKTOP = 0; +// --- const int HWND_NOTOPMOST = - 2; +// --- const int HWND_TOP = 0; +// --- const int HWND_TOPMOST = - 1; + +int SetWindowPos(long h, long hb, int X, int Y, int cx, int cy, int f); + +void TopMost(Object obj) +{ + int i; + + i = SetWindowPos(obj.hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE + SWP_NOMOVE); +} + +void UnTopMost(Object obj) +{ + int i; + + i = SetWindowPos(obj.hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE + SWP_NOMOVE); +} + +void HideWindow(long hWnd) +{ + int i; + + i = SetWindowPos(hWnd, HWND_BOTTOM, 100, 100, 200, 200, SWP_HIDEWINDOW); +} + diff --git a/src/game_sp/TopMost.h b/src/game_sp/TopMost.h new file mode 100644 index 00000000..3543239a --- /dev/null +++ b/src/game_sp/TopMost.h @@ -0,0 +1,38 @@ +// ---------------------------------------------------------------------------- +// TopMost.h +// ---------------------------------------------------------------------------- + +#ifndef TOPMOST_H +#define TOPMOST_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +#define HWND_BOTTOM (1) +#define HWND_BROADCAST (0xFFFF) +#define HWND_DESKTOP (0) +#define HWND_NOTOPMOST (- 2) +#define HWND_TOP (0) +#define HWND_TOPMOST (- 1) +#define SWP_DRAWFRAME (SWP_FRAMECHANGED) +#define SWP_FRAMECHANGED (0x20) +#define SWP_HIDEWINDOW (0x80) +#define SWP_NOACTIVATE (0x10) +#define SWP_NOCOPYBITS (0x100) +#define SWP_NOMOVE (0x2) +#define SWP_NOOWNERZORDER (0x200) +#define SWP_NOREDRAW (0x8) +#define SWP_NOREPOSITION (SWP_NOOWNERZORDER) +#define SWP_NOSIZE (0x1) +#define SWP_NOZORDER (0x4) +#define SWP_SHOWWINDOW (0x40) + +extern void HideWindow(long hWnd); +extern void TopMost(Object obj); +extern void UnTopMost(Object obj); + +#endif /* TOPMOST_H */ diff --git a/src/game_sp/Zonk.c b/src/game_sp/Zonk.c new file mode 100644 index 00000000..fc6f5d96 --- /dev/null +++ b/src/game_sp/Zonk.c @@ -0,0 +1,476 @@ +// ---------------------------------------------------------------------------- +// Zonk.c +// ---------------------------------------------------------------------------- + +#include "Zonk.h" + +// static char *VB_Name = "modZonk"; +// --- Option Explicit + +// ========================================================================== +// SUBROUTINE +// Animate Zonks (falling) +// ========================================================================== + +int subAnimateZonks(int si) +{ + int subAnimateZonks; + + int tFld; + + // PseudoRegisters: + // int ax, bx, cx, dx, di, X, Y; + int ax, bx, dx, X, Y; + // int ah, bh, ch, dh, al, bl, cl, dl; + int al, bl; + + tFld = PlayField16[si]; + if ((tFld & 0xFF) != fiZonk) + return subAnimateZonks; + + if (tFld == fiZonk) + { + if (FreezeZonks == 2) // Do Zonks fall? (debug) + return subAnimateZonks; + + ax = PlayField16[si + FieldWidth]; // select case playfield16(si+60) + if (ax == 0) + goto loc_g_0D64; + + if (ax == fiZonk) + goto loc_g_0D35; + + if (ax == fiInfotron) + goto loc_g_0D35; + + if (ax == fiRAM) + goto loc_g_0D35; + + return subAnimateZonks; + +loc_g_0D35: // Case fiZonk, fiInfotron, fiRAM + ax = PlayField16[si + FieldWidth - 1]; + if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) + goto loc_g_0D6B; + +loc_g_0D4C: + ax = PlayField16[si + FieldWidth + 1]; + if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) + goto loc_g_0D81; + + return subAnimateZonks; + +loc_g_0D64: // Case fiSpace + MovHighByte(&PlayField16[si], 0x40); + goto loc_g_0DA5; + +loc_g_0D6B: // roll left? + if (PlayField16[si - 1] == 0) + goto loc_g_0D74; + + goto loc_g_0D4C; + +loc_g_0D74: + MovHighByte(&PlayField16[si], 0x50); + PlayField16[si - 1] = 0x8888; + goto loc_g_0DA5; + +loc_g_0D81: // roll right? + if (PlayField16[si + 1] == 0) + goto loc_g_0D98; + + if (PlayField16[si + 1] != 0x9999) // wow right is different from left! + return subAnimateZonks; + + if (LowByte(PlayField16[si - FieldWidth + 1]) != 1) + return subAnimateZonks; + +loc_g_0D98: + MovHighByte(&PlayField16[si], 0x60); + PlayField16[si + 1] = 0x8888; + } // tFld = fiZonk + +loc_g_0DA5: + // from now on the zonk is definitely moving, + // maybe the sequence is in an advanced frame + // or just beeing initialized due to the code above + bl = HighByte(PlayField16[si]); + bx = 0; + MovLowByte(&bx, bl); + al = bl & 0xF0; + if (al == 0x10) // zonk comes falling from above + goto loc_g_0DE8; + + if (al == 0x20) // zonk comes rolling from right to left + goto loc_g_0F83; + + if (al == 0x30) // zonk comes rolling from left to right + goto loc_g_0FE8; + + if (FreezeZonks == 2) + return subAnimateZonks; + + if (al == 0x40) // zonk falls straight down + goto loc_g_104D; + + if (al == 0x50) // zonk rolls left + goto loc_g_107B; + + if (al == 0x60) // zonk rolls right + goto loc_g_10E9; + + if (al == 0x70) // intermediate state + goto loc_g_1157; + + return subAnimateZonks; + +loc_g_0DE8: // zonk comes falling from above + // To Do: draw zonk falling from above + // according to position in (bl And &H07) + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si - FieldWidth); + dx = bl & 0x7; + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X, Y + TwoPixels * (dx + 1), fiZonk); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bl = HighByte(PlayField16[si]) + 1; + if (bl == 0x16) + { + MovHighByte(&PlayField16[si], bl); + subCleanUpForZonksAbove(si - FieldWidth); + return subAnimateZonks; + } // loc_g_0E2B: + + if (bl < 0x18) + { + MovHighByte(&PlayField16[si], bl); + return subAnimateZonks; + } // loc_g_0E35: + + MovHighByte(&PlayField16[si], 0); // zonk arrived at the field + if ((FreezeZonks & 0xFF) == 2) + return subAnimateZonks; + + // loc_g_0E42: // now check if the zonk may go on falling somehow + ax = PlayField16[si + FieldWidth]; + if (ax == 0) // below is empty!-> go on falling 'loc_g_0E4C: + goto loc_g_0EDD; + + if (ax == 0x9999) // below is only temporarily used ' loc_g_0E57: + goto loc_g_0EDD; + + if ((ax & 0xFF) == fiMurphy) // Murphy dies 'loc_g_0E61: + goto loc_g_0F14; + + if ((ax & 0xFF) == fiSnikSnak) // SnikSnak dies 'loc_g_0E6B: + goto loc_g_0F6E; + + if (ax == 0x2BB) // loc_g_0E76: + goto loc_g_0F36; + + if (ax == 0x4BB) // loc_g_0E81: + goto loc_g_0F52; + + if ((ax & 0xFF) == fiElectron) // Electron cracked! 'loc_g_0E8B: + goto loc_g_0F6E; + + if (ax == fiOrangeDisk) // OrangeDisk explodes 'loc_g_0E95: + goto loc_g_0F75; + + subSoundFXZonk(); // play the zonk sound,'cause zonk hits something "hard" + + if (! (ax == fiZonk || ax == fiInfotron || ax == fiRAM)) + return subAnimateZonks; + + // loc_g_0EAE: ' Zonk rolls somewhere + ax = PlayField16[si + FieldWidth - 1]; + if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) // may roll left + goto loc_g_0EEA; + + ax = PlayField16[si + FieldWidth + 1]; + if (ax == 0 || ax == 0x8888 || ax == 0xAAAA) // may roll right + goto loc_g_0F00; + + return subAnimateZonks; + +loc_g_0EDD: // go on falling down? + PlayField16[si] = 0x7001; // go into intermediate waitstate + PlayField16[si + FieldWidth] = 0x9999; // mark as "zonk waiting to access" + return subAnimateZonks; + +loc_g_0EEA: // test if zonk may roll left + // This if(if true) jumps up far above + // to the according rountine for fixed zonks! + if (PlayField16[si - 1] != 0) // Remarkable!!! ' loc_g_0EF4: + goto loc_g_0D4C; + + MovHighByte(&PlayField16[si], 0x50); // zonk rolls left + Mov(&PlayField16[si - 1], 0x8888); // mark as zonk accessing? + return subAnimateZonks; + +loc_g_0F00: // test if zonk may roll right + if (PlayField16[si + 1] != 0) // loc_g_0F08: + return subAnimateZonks; + + MovHighByte(&PlayField16[si], 0x60); // zonk rolls right + Mov(&PlayField16[si + 1], 0x8888); // mark as zonk accessing? + return subAnimateZonks; + +loc_g_0F14: // Murphy dies, but not in any case + bl = HighByte(PlayField16[si + FieldWidth]); + if (bl == 0xE || bl == 0xF || bl == 0x28) + return subAnimateZonks; + + if (bl == 0x29 || bl == 0x25 || bl == 0x26) + return subAnimateZonks; + +loc_g_0F36: // ?? + ax = LowByte(PlayField16[si + FieldWidth - 1]); + if (ax == fiElectron) // loc_g_0F43: + PlayField16[si + FieldWidth] = fiElectron; + + if (ax != 0x1F) + PlayField16[si + FieldWidth - 1] = 0; + + goto loc_g_0F6E; + +loc_g_0F52: // ?? + ax = LowByte(PlayField16[si + FieldWidth + 1]); + if (ax == fiElectron) // loc_g_0F5F: + PlayField16[si + FieldWidth] = fiElectron; + + if (ax != 0x1F) + PlayField16[si + FieldWidth + 1] = 0; + + goto loc_g_0F6E; + +loc_g_0F6E: // someone dies/explodes + si = si + FieldWidth; // 1 field down + ExplodeFieldSP(si); // Explode + return subAnimateZonks; + +loc_g_0F75: // OrangeDisk explodes next cycle + si = si + FieldWidth; // 1 field down + PlayField8[si] = fiHardWare; + return subAnimateZonks; + +loc_g_0F83: // zonk comes rolling from right to left + // To Do: draw zonk rolling from right + // according to position in (bl And &H07) + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si + 1); + Y = GetStretchY(si); + dx = (bl & 0x7) + 1; + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X - (TwoPixels * dx), Y, aniZonkRollLeft[dx - 1]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bl = HighByte(PlayField16[si]) + 1; // get and increment sequence# + if (bl == 0x24) + PlayField16[si + 1] = 0xAAAA; + + if (bl == 0x26) + { + MovHighByte(&PlayField16[si], bl); + subCleanUpForZonksAbove(si + 1); + } + else if (bl < 0x28) + { + MovHighByte(&PlayField16[si], bl); + } + else + { + PlayField16[si] = 0xFFFF; + si = si + FieldWidth; // 1 field down + PlayField16[si] = 0x1001; // convert rolling zonk to a falling zonk + } + + return subAnimateZonks; + +loc_g_0FE8: // zonk comes rolling from left to right + // To Do: draw zonk rolling from left + // according to position in (bl And &H07) + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si - 1); + Y = GetStretchY(si); + dx = (bl & 0x7) + 1; + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X + (TwoPixels * dx), Y, aniZonkRollRight[dx - 1]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bl = HighByte(PlayField16[si]) + 1; + if (bl == 0x34) + PlayField16[si - 1] = 0xAAAA; + + if (bl == 0x36) + { + MovHighByte(&PlayField16[si], bl); + subCleanUpForZonksAbove(si - 1); + } + else if (bl < 0x38) + { + MovHighByte(&PlayField16[si], bl); + } + else + { + PlayField16[si] = 0xFFFF; + si = si + FieldWidth; // 1 field down + PlayField16[si] = 0x1001; // convert rolling zonk to a falling zonk + } + + return subAnimateZonks; + +loc_g_104D: // zonk falls straight down + bl = bl + 1; + if (bl < 0x42) + { + MovHighByte(&PlayField16[si], bl); + } + else if (PlayField16[si + FieldWidth] != 0) + { + bl = bl - 1; // stay waiting + MovHighByte(&PlayField16[si], bl); + } + else + { + PlayField16[si] = 0xFFFF; // mark as "zonk leaving" + si = si + FieldWidth; // 1 field down + PlayField16[si] = 0x1001; // go falling + } + + return subAnimateZonks; + +loc_g_107B: // zonk rolls left + // To Do: draw zonk rolling to left + // according to position in (bl And &H0F) + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + dx = (bl & 0xF) + 1; + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X - (TwoPixels * dx), Y, aniZonkRollLeft[dx - 1]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bl = HighByte(PlayField16[si]) + 1; // retrieve and increment sequence# + if (bl < 0x52) + { + MovHighByte(&PlayField16[si], bl); + return subAnimateZonks; + } + + if (PlayField16[si + FieldWidth - 1] != 0) + goto loc_g_10E2; + + if (PlayField16[si - 1] != 0) + { + if (PlayField16[si - 1] != 0x8888) + goto loc_g_10E2; + } // loc_g_10C8: + + PlayField16[si] = 0xFFFF; + si = si - 1; // 1 field left + PlayField16[si] = 0x2201; + PlayField16[si + FieldWidth] = 0xFFFF; + return subAnimateZonks; + +loc_g_10E2: // stay waiting + bl = bl - 1; + MovHighByte(&PlayField16[si], bl); + return subAnimateZonks; + +loc_g_10E9: // zonk rolls right + // To Do: draw zonk rolling to right + // according to position in (bl And &H07) + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + X = GetStretchX(si); + Y = GetStretchY(si); + dx = (bl & 0x7) + 1; + StretchedSprites.BltEx(X, Y, 0); + StretchedSprites.BltEx(X + (TwoPixels * dx), Y, aniZonkRollRight[dx - 1]); + // +++++++++++++++++++++++++++++++++++++++++++++++++++++ + bl = HighByte(PlayField16[si]) + 1; + if (bl < 0x62) + { + MovHighByte(&PlayField16[si], bl); + return subAnimateZonks; + } + + if (PlayField16[si + FieldWidth + 1] != 0) + goto loc_g_1150; + + if (PlayField16[si + 1] != 0) + { + if (PlayField16[si + 1] != 0x8888) + goto loc_g_1150; + } + + PlayField16[si] = 0xFFFF; + si = si + 1; + PlayField16[si] = 0x3201; + PlayField16[si + FieldWidth] = 0xFFFF; + return subAnimateZonks; + +loc_g_1150: // stay waiting + bl = bl - 1; + MovHighByte(&PlayField16[si], bl); + return subAnimateZonks; + +loc_g_1157: // intermediate state + ax = PlayField16[si + FieldWidth]; + if (ax == 0 || ax == 0x9999) + { + PlayField16[si] = 0xFFFF; + si = si + FieldWidth; // 1 field down + PlayField16[si] = 0x1001; // start falling down + goto loc_g_0DE8; + } + + return subAnimateZonks; +} // subAnimateZonks endp + +int subCleanUpForZonksAbove(int si) +{ + int subCleanUpForZonksAbove; + + int ax; + + if (LowByte(PlayField16[si]) != fiExplosion) + PlayField16[si] = 0; + + if (PlayField16[si - FieldWidth] != 0) + { + if (PlayField16[si - FieldWidth] != 0x9999) + return subCleanUpForZonksAbove; + + if (LowByte(PlayField16[si - 2 * FieldWidth]) != fiInfotron) + return subCleanUpForZonksAbove; + } // loc_g_1674: + + if (PlayField16[si - FieldWidth - 1] != fiZonk) + { + if (PlayField16[si - FieldWidth + 1] != fiZonk) + return subCleanUpForZonksAbove; + + goto loc_g_16A7; + } + + ax = PlayField16[si - 1]; + if (ax == fiZonk || ax == fiInfotron || ax == fiRAM) + { + PlayField16[si - FieldWidth - 1] = 0x6001; + PlayField16[si - FieldWidth] = 0x8888; + return subCleanUpForZonksAbove; + } + + if (PlayField16[si - FieldWidth + 1] != fiZonk) + return subCleanUpForZonksAbove; + +loc_g_16A7: + ax = PlayField16[si + 1]; + if (ax == fiZonk || ax == fiInfotron || ax == fiRAM) + { + PlayField16[si - FieldWidth + 1] = 0x5001; + PlayField16[si - FieldWidth] = 0x8888; + } + + return subCleanUpForZonksAbove; +} // subCleanUpForZonksAbove + diff --git a/src/game_sp/Zonk.h b/src/game_sp/Zonk.h new file mode 100644 index 00000000..7e6022f8 --- /dev/null +++ b/src/game_sp/Zonk.h @@ -0,0 +1,18 @@ +// ---------------------------------------------------------------------------- +// Zonk.h +// ---------------------------------------------------------------------------- + +#ifndef ZONK_H +#define ZONK_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern int subAnimateZonks(int si); +extern int subCleanUpForZonksAbove(int si); + +#endif /* ZONK_H */ diff --git a/src/game_sp/export.h b/src/game_sp/export.h new file mode 100644 index 00000000..8b86c166 --- /dev/null +++ b/src/game_sp/export.h @@ -0,0 +1,80 @@ +#ifndef EXPORT_H +#define EXPORT_H + +/* ========================================================================= */ +/* functions and definitions exported from game_sp to main program */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* constant definitions */ +/* ------------------------------------------------------------------------- */ + + +/* ------------------------------------------------------------------------- */ +/* data structure definitions */ +/* ------------------------------------------------------------------------- */ + +struct GlobalInfo_SP +{ +}; + +struct GameInfo_SP +{ +}; + +struct LevelInfo_SP +{ + int file_version; +}; + +struct GraphicInfo_SP +{ + Bitmap *bitmap; + int src_x, src_y; + int src_offset_x, src_offset_y; + int dst_offset_x, dst_offset_y; + int width, height; + + Bitmap *crumbled_bitmap; + int crumbled_src_x, crumbled_src_y; + int crumbled_border_size; + + boolean has_crumbled_graphics; + boolean preserve_background; + + int unique_identifier; /* used to identify needed screen updates */ +}; + +struct EngineSnapshotInfo_SP +{ + struct GameInfo_SP game_sp; +}; + + +/* ------------------------------------------------------------------------- */ +/* exported functions */ +/* ------------------------------------------------------------------------- */ + +extern struct GlobalInfo_SP global_sp_info; +extern struct LevelInfo_SP native_sp_level; +extern struct GraphicInfo_SP graphic_info_sp_object[TILE_MAX][8]; +extern struct GraphicInfo_SP graphic_info_sp_player[MAX_PLAYERS][SPR_MAX][8]; +extern struct EngineSnapshotInfo_SP engine_snapshot_sp; + +extern void InitGameEngine_SP(); +extern void GameActions_SP(byte *, boolean); + +extern unsigned int InitEngineRandom_SP(long); + +extern void setLevelInfoToDefaults_SP(); +extern boolean LoadNativeLevel_SP(char *); + +extern void BackToFront_SP(void); +extern void BlitScreenToBitmap_SP(Bitmap *); +extern void RedrawPlayfield_SP(boolean); +extern void DrawGameDoorValues_SP(); + +extern void LoadEngineSnapshotValues_SP(); +extern void SaveEngineSnapshotValues_SP(); + +#endif /* EXPORT_H */ diff --git a/src/game_sp/game_sp.h b/src/game_sp/game_sp.h new file mode 100644 index 00000000..9551e84e --- /dev/null +++ b/src/game_sp/game_sp.h @@ -0,0 +1,21 @@ +/*********************************************************** +* Artsoft Retro-Game Library * +*----------------------------------------------------------* +* (c) 1994-2006 Artsoft Entertainment * +* Holger Schemel * +* Detmolder Strasse 189 * +* 33604 Bielefeld * +* Germany * +* e-mail: info@artsoft.org * +*----------------------------------------------------------* +* game_sp.h * +***********************************************************/ + +#ifndef GAME_SP_H +#define GAME_SP_H + +#define GAME_SP_VERSION_1_0_0 + +#include "export.h" + +#endif /* GAME_SP_H */ diff --git a/src/game_sp/global.h b/src/game_sp/global.h new file mode 100644 index 00000000..f6f1d538 --- /dev/null +++ b/src/game_sp/global.h @@ -0,0 +1,47 @@ +// ---------------------------------------------------------------------------- +// global.h +// ---------------------------------------------------------------------------- + +#ifndef GAME_SP_GLOBAL_H +#define GAME_SP_GLOBAL_H + +#include "ASM.h" +#include "BitMapObject.h" +#include "BugsTerminals.h" +#include "Capture.h" +#include "DDScrollBuffer.h" +#include "DDSpriteBuffer.h" +#include "Demo.h" +#include "DemoBufferObject.h" +#include "DirectDrawGlobals.h" +#include "DirectXGlobals.h" +#include "Display.h" +#include "DoGameStuff.h" +#include "Electrons.h" +#include "ErrorReporting.h" +#include "Explosions.h" +#include "FakeDeclares.h" +#include "FancyRestore.h" +#include "GeneralTricks.h" +#include "Globals.h" +#include "Infotrons.h" +#include "InitGameConditions.h" +#include "Input.h" +#include "LevelSetPreviewForm.h" +#include "MainForm.h" +#include "MainGameLoop.h" +#include "Marker.h" +#include "Murphy.h" +#include "OrangeDisk.h" +#include "PathTools.h" +#include "SettingsObject.h" +#include "SnikSnaks.h" +#include "Sound.h" +#include "TickCountObject.h" +#include "TopMost.h" +#include "Zonk.h" +#include "modAnimations.h" +#include "modGeneralTricks.h" +#include "modMPX.h" + +#endif /* GAME_SP_GLOBAL_H */ diff --git a/src/game_sp/main.c b/src/game_sp/main.c new file mode 100644 index 00000000..74902a0c --- /dev/null +++ b/src/game_sp/main.c @@ -0,0 +1,17 @@ + +#include "main_sp.h" +#include "global.h" + + +void InitGameEngine_SP() +{ + menPlay_Click(); +} + +void BlitScreenToBitmap_SP(Bitmap *target_bitmap) +{ +} + +void GameActions_SP(byte action[MAX_PLAYERS], boolean warp_mode) +{ +} diff --git a/src/game_sp/main_sp.h b/src/game_sp/main_sp.h new file mode 100644 index 00000000..127445a0 --- /dev/null +++ b/src/game_sp/main_sp.h @@ -0,0 +1,64 @@ +#ifndef MAIN_SP_H +#define MAIN_SP_H + +/* ========================================================================= */ +/* external functions and definitions imported from main program to game_sp */ +/* ========================================================================= */ + +#include "../engines.h" + + +/* ========================================================================= */ +/* functions and definitions that are exported from game_sp to main program */ +/* ========================================================================= */ + +#include "export.h" + + +/* ========================================================================= */ +/* internal functions and definitions that are not exported to main program */ +/* ========================================================================= */ + + +/* ------------------------------------------------------------------------- */ +/* constant definitions */ +/* ------------------------------------------------------------------------- */ + +/* screen sizes and positions for SP engine */ + +#define ORIG_TILEX 16 +#define ORIG_TILEY 16 + +#define ZOOM_FACTOR 2 + +#define TILEX (ORIG_TILEX * ZOOM_FACTOR) +#define TILEY (ORIG_TILEY * ZOOM_FACTOR) + +#define SCR_FIELDX 17 +#define SCR_FIELDY 17 + +/* often used screen positions */ +#define SX 8 +#define SY 8 +#define SXSIZE (SCR_FIELDX * TILEX) +#define SYSIZE (SCR_FIELDY * TILEY) + + +/* ------------------------------------------------------------------------- */ +/* data structure definitions */ +/* ------------------------------------------------------------------------- */ + +/* ------------------------------------------------------------------------- */ +/* exported variables */ +/* ------------------------------------------------------------------------- */ + +extern struct LevelInfo_SP native_sp_level; + +extern struct GameInfo_SP game_sp; + + +/* ------------------------------------------------------------------------- */ +/* exported functions */ +/* ------------------------------------------------------------------------- */ + +#endif /* MAIN_SP_H */ diff --git a/src/game_sp/modAnimations.c b/src/game_sp/modAnimations.c new file mode 100644 index 00000000..5cb66433 --- /dev/null +++ b/src/game_sp/modAnimations.c @@ -0,0 +1,69 @@ +// ---------------------------------------------------------------------------- +// modAnimations.c +// ---------------------------------------------------------------------------- + +#include "modAnimations.h" + +// static char *VB_Name = "modAnimations"; +// --- Option Explicit + +// ::: #ifndef HAS_SpecialPortType +// ::: typedef struct +// ::: { +// ::: int PortLocation; // = 2*(x+(y*60)) +// ::: byte Gravity; // 1 = turn on, anything else (0) = turn off +// ::: byte FreezeZonks; // 2 = turn on, anything else (0) = turn off (1=off!) +// ::: byte FreezeEnemies; // 1 = turn on, anything else (0) = turn off +// ::: byte UnUsed; +// ::: } SpecialPortType; +// ::: #define HAS_SpecialPortType +// ::: #endif + +// ::: #ifndef HAS_LevelInfoType +// ::: typedef struct +// ::: { +// ::: byte UnUsed[4 + 1]; +// ::: byte InitialGravity; // 1=on, anything else (0) = off +// ::: byte Version; // SpeedFixVersion XOR &H20 +// ::: char LevelTitle[23]; +// ::: byte InitialFreezeZonks; // 2=on, anything else (0) = off. (1=off too!) +// ::: byte InfotronsNeeded; + +// ::: // Number of Infotrons needed. 0 means that Supaplex will count the total +// ::: // amount of Infotrons in the level, and use the low byte of that number. +// ::: // (A multiple of 256 Infotrons will then result in 0-to-eat, etc.!) +// ::: byte SpecialPortCount; // Maximum 10 allowed! +// ::: SpecialPortType SpecialPort[10 + 1]; +// ::: byte SpeedByte; // = Speed XOR Highbyte(RandomSeed) +// ::: byte CheckSumByte; // = CheckSum XOR SpeedByte +// ::: int DemoRandomSeed; +// ::: } LevelInfoType; +// ::: #define HAS_LevelInfoType +// ::: #endif + +DDSpriteBuffer NormalSprites; +DDSpriteBuffer StretchedSprites; +DDScrollBuffer Stage; + +byte LData[59 + 1][23 + 1]; +LevelInfoType LInfo; + +float Stretch; // , StretchWidth%, TwoPixels! + +int ScrollMinX, ScrollMaxX, ScrollMinY, ScrollMaxY; +int ScrollX, ScrollY; +// --- const long ScrollDelta = 1&; + +// Public FieldWidth&, FieldHeight& +boolean EndFlag; +long PauseMode; + +TickCountObject Clock; +long MurphyX, MurphyY; + +void GoPlay() +{ + // Call subFetchAndInitLevelB + EndFlag = False; + subMainGameLoop(); +} diff --git a/src/game_sp/modAnimations.h b/src/game_sp/modAnimations.h new file mode 100644 index 00000000..c0de60e1 --- /dev/null +++ b/src/game_sp/modAnimations.h @@ -0,0 +1,64 @@ +// ---------------------------------------------------------------------------- +// modAnimations.h +// ---------------------------------------------------------------------------- + +#ifndef MODANIMATIONS_H +#define MODANIMATIONS_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +#ifndef HAS_SpecialPortType +typedef struct +{ + int PortLocation; // = 2*(x+(y*60)) + byte Gravity; // 1 = turn on, anything else (0) = turn off + byte FreezeZonks; // 2 = turn on, anything else (0) = turn off (1=off!) + byte FreezeEnemies; // 1 = turn on, anything else (0) = turn off + byte UnUsed; +} SpecialPortType; +#define HAS_SpecialPortType +#endif + +#ifndef HAS_LevelInfoType +typedef struct +{ + byte UnUsed[4 + 1]; + byte InitialGravity; // 1=on, anything else (0) = off + byte Version; // SpeedFixVersion XOR &H20 + char LevelTitle[23]; + byte InitialFreezeZonks; // 2=on, anything else (0) = off. (1=off too!) + byte InfotronsNeeded; + + // Number of Infotrons needed. 0 means that Supaplex will count the total + // amount of Infotrons in the level, and use the low byte of that number. + // (A multiple of 256 Infotrons will then result in 0-to-eat, etc.!) + byte SpecialPortCount; // Maximum 10 allowed! + SpecialPortType SpecialPort[10 + 1]; + byte SpeedByte; // = Speed XOR Highbyte(RandomSeed) + byte CheckSumByte; // = CheckSum XOR SpeedByte + int DemoRandomSeed; +} LevelInfoType; +#define HAS_LevelInfoType +#endif + +#define ScrollDelta ((long)1) + +extern void GoPlay(); + +extern DDScrollBuffer Stage; +extern DDSpriteBuffer NormalSprites; +extern DDSpriteBuffer StretchedSprites; +extern LevelInfoType LInfo; +extern boolean EndFlag; +extern byte LData[59 + 1][23 + 1]; +extern float Stretch; +extern int ScrollMinX, ScrollMaxX, ScrollMinY, ScrollMaxY; +extern int ScrollX, ScrollY; +extern long PauseMode; + +#endif /* MODANIMATIONS_H */ diff --git a/src/game_sp/modGeneralTricks.c b/src/game_sp/modGeneralTricks.c new file mode 100644 index 00000000..712ff1b1 --- /dev/null +++ b/src/game_sp/modGeneralTricks.c @@ -0,0 +1,69 @@ +// ---------------------------------------------------------------------------- +// modGeneralTricks.c +// ---------------------------------------------------------------------------- + +#include "modGeneralTricks.h" + +// static char *VB_Name = "modGeneralTricks"; +// --- Option Explicit + +void Inc(int *i) +{ + *i = *i + 1; +} + +void Dec(int *i) +{ + *i = *i - 1; +} + +/* +double ValEx(char *TS) +{ + double ValEx; + + // Extends the Val() function for + // german-style number-representing strings + int i; + char *LS, *RS; + + i = InStr(1, TS, ","); + if (i != 0) + { + LS = Left(TS, i - 1); + RS = Right(TS, Len(TS) - i); + ValEx = ValCAT(LS, ".", RS); + } + else + { + ValEx = Val(TS); + } + + return ValEx; +} +*/ + +int Min(int A, int B) +{ + int Min; + + if (A < B) + Min = A; + else + Min = B; + + return Min; +} + +int Max(int A, int B) +{ + int Max; + + if (A < B) + Max = B; + else + Max = A; + + return Max; +} + diff --git a/src/game_sp/modGeneralTricks.h b/src/game_sp/modGeneralTricks.h new file mode 100644 index 00000000..23bb8683 --- /dev/null +++ b/src/game_sp/modGeneralTricks.h @@ -0,0 +1,21 @@ +// ---------------------------------------------------------------------------- +// modGeneralTricks.h +// ---------------------------------------------------------------------------- + +#ifndef MODGENERALTRICKS_H +#define MODGENERALTRICKS_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +extern void Dec(int *i); +extern void Inc(int *i); +extern int Max(int A, int B); +extern int Min(int A, int B); +extern double ValEx(char *TS); + +#endif /* MODGENERALTRICKS_H */ diff --git a/src/game_sp/modMPX.c b/src/game_sp/modMPX.c new file mode 100644 index 00000000..fcb564f0 --- /dev/null +++ b/src/game_sp/modMPX.c @@ -0,0 +1,451 @@ +// ---------------------------------------------------------------------------- +// modMPX.c +// ---------------------------------------------------------------------------- + +#include "modMPX.h" + +void ReadMPX(); +#if 0 +static void SaveMPX(char *Path); +static void SaveSP(char *Path); +#endif + +// static char *VB_Name = "modMPX"; +// --- Option Explicit + +char *gSignature; +boolean bSignatureAvailable; + +const char MPX_ID[4] = "MPX "; + +// ::: #ifndef HAS_LevelDescriptor +// ::: typedef struct +// ::: { +// ::: int Width; +// ::: int Height; +// ::: long OffSet; +// ::: long Size; +// ::: } LevelDescriptor; +// ::: #define HAS_LevelDescriptor +// ::: #endif + +int MPXVersion; +int LevelCount; +boolean DemoAvailable; +LevelDescriptor *LDesc; +// int OFile; +FILE *OFile; + +boolean MpxOpen(char *Path) +{ + boolean MpxOpen; + + // int i; + // byte T; + char readID[4]; + + MpxOpen = False; + + // --- On Error GoTo OpenMPXEH + // OFile = FreeFile(); + OFile = fopen(CurPath, "rb"); + FILE_GET(OFile, -1, &readID, sizeof(readID)); + if (readID != MPX_ID) + goto OpenMPXEH; + + FILE_GET(OFile, -1, &MPXVersion, sizeof(MPXVersion)); + FILE_GET(OFile, -1, &LevelCount, sizeof(LevelCount)); + LDesc = REDIM_1D(sizeof(LevelDescriptor), 0, LevelCount + 1 - 1); + FILE_GET(OFile, -1, &LDesc, sizeof(LDesc)); + MpxOpen = True; + return MpxOpen; + +OpenMPXEH: + fclose(OFile); + OFile = 0; + + return MpxOpen; +} + +boolean MpxLoadLInfo(int i) +{ + boolean MpxLoadLInfo; + + long Off; + + MpxLoadLInfo = False; + // if (OFile < 1) + if (OFile == 0) + return MpxLoadLInfo; + + Off = LDesc[i].OffSet; + Off = Off + LDesc[i].Width * LDesc[i].Height; + + // --- On Error GoTo MpxLoadLInfoEH + FILE_GET(OFile, Off, &LInfo, sizeof(LInfo)); + MpxLoadLInfo = True; + return MpxLoadLInfo; + + // MpxLoadLInfoEH: + fclose(OFile); + OFile = 0; + + return MpxLoadLInfo; +} + +void MpxClose() +{ + if (0 < OFile) + { + fclose(OFile); + OFile = 0; + } +} + +void ReadMPX() +{ + // int FNum, i; + FILE *FNum; + int i; + // byte T; + char readID[4]; + + Trace("modMPX", "--> ReadMPX"); + + // --- On Error GoTo ReadMPXEH + // FNum = FreeFile(); + Trace("modMPX", "open file"); + FNum = fopen(CurPath, "rb"); + FILE_GET(FNum, -1, &readID, sizeof(readID)); + if (readID != MPX_ID) + goto ReadMPXEH; + + FILE_GET(FNum, -1, &MPXVersion, sizeof(MPXVersion)); + if (MPXVersion != 1) + goto ReadMPXEH; + + FILE_GET(FNum, -1, &LevelCount, sizeof(LevelCount)); + if (LevelCount < 1) + goto ReadMPXEH; + + LDesc = REDIM_1D(sizeof(LevelDescriptor), 0, LevelCount + 1 - 1); + Trace("modMPX", "--> read LevelDescriptor"); + FILE_GET(FNum, -1, &LDesc, sizeof(LDesc)); + FieldWidth = LDesc[LevelNumber].Width; + FieldHeight = LDesc[LevelNumber].Height; + HeaderSize = 96; + FieldMax = (FieldWidth * FieldHeight) + HeaderSize - 1; + LevelMax = (FieldWidth * FieldHeight) - 1; + FileMax = LDesc[LevelNumber].Size - 1; + if (FileMax < FieldMax) + FileMax = FieldMax; + + Trace("modMPX", "ReDim PlayField8"); + PlayField8 = REDIM_1D(sizeof(byte), 0, FileMax + 1 - 1); + DisPlayField = REDIM_1D(sizeof(byte), 0, FieldMax + 1 - 1); + i = LDesc[LevelNumber].OffSet; + FILE_GET(FNum, i, &PlayField8, sizeof(PlayField8)); + i = i + LevelMax + 1; + FILE_GET(FNum, i, &LInfo, sizeof(LInfo)); // store level info in an extra structure + fclose(FNum); + // --- On Error GoTo 0 + + Trace("modMPX", "file closed"); + if (FieldMax < FileMax) + DemoAvailable = True; + + Trace("modMPX", "read signature"); + ReadSignature(); + Trace("modMPX", "ReDim PlayField16"); + PlayField16 = REDIM_1D(sizeof(int), -FieldWidth, FieldMax); + for (i = 0; i <= FieldMax; i++) + { + PlayField16[i] = PlayField8[i]; + DisPlayField[i] = PlayField8[i]; + PlayField8[i] = 0; + } + + AnimationPosTable = REDIM_1D(sizeof(int), 0, LevelMax - 2 *FieldWidth); + AnimationSubTable = REDIM_1D(sizeof(byte), 0, LevelMax - 2 *FieldWidth); + TerminalState = REDIM_1D(sizeof(byte), 0, FieldMax + 1 - 1); + GravityFlag = LInfo.InitialGravity; + FreezeZonks = LInfo.InitialFreezeZonks; + DemoPointer = FieldMax + 1; + DemoOffset = DemoPointer; + DemoKeyRepeatCounter = 0; + if (DemoFlag != 0) + { + // Debug.Print "ReadMPX: " & Hex(LInfo.DemoRandomSeed) + RandomSeed = LInfo.DemoRandomSeed; + DemoFlag = 1; + } + else + { + subRandomize(); + } + + MainForm.SetDisplayRegion(); + LevelLoaded = True; + if (CurPath != TmpPath) + Let_ModifiedFlag(False); + + Trace("modMPX", "--> ReadMPX"); + return; + +ReadMPXEH: + // Close(); + fclose(FNum); + ReportError("modMPX", CAT("Error reading MPX file ", CurPath)); + Trace("modMPX", "Error reading MPX file"); + Trace("modMPX", "--> ReadMPX"); +} + +#if 0 + +static void SaveMPX(char *Path) +{ + // int FNum, i; + FILE *FNum; + int i; + // byte T; + byte FF; + + FF = 0xFF; + LevelNumber = 1; + LevelCount = 1; + MPXVersion = 1; + if ((FileMax < FieldMax) || ! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer))) + FileMax = FieldMax; + + LDesc = REDIM_1D(sizeof(LevelDescriptor), 0, LevelCount + 1 - 1); + { + LDesc[LevelNumber].Width = FieldWidth; + LDesc[LevelNumber].Height = FieldHeight; + LDesc[LevelNumber].OffSet = 4 + 2 * strlen(INT_TO_STR(LevelCount)) + + LevelCount * sizeof(LDesc[1]) + 1; + LDesc[LevelNumber].Size = FileMax + 1; + if (! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer))) + { + LDesc[LevelNumber].Size = LDesc[LevelNumber].Size + DemoBuffer.Size + 2; + if (0 < strlen(MySignature)) + LDesc[LevelNumber].Size = LDesc[LevelNumber].Size + strlen(MySignature) + 1; + } + + } + + // UnEdAll(); + + // --- On Error GoTo SaveMPXEH + // FNum = FreeFile(); + if (FileExists(Path)) + MayKill(Path); + + FNum = fopen(Path, "wb"); + FILE_PUT(FNum, -1, &MPX_ID, sizeof(MPX_ID)); + FILE_PUT(FNum, -1, &MPXVersion, sizeof(MPXVersion)); + FILE_PUT(FNum, -1, &LevelCount, sizeof(LevelCount)); + FILE_PUT(FNum, -1, &LDesc, sizeof(LDesc)); + i = LDesc[LevelNumber].OffSet; + FILE_PUT(FNum, i, &PlayField8, sizeof(PlayField8)); + FILE_PUT(FNum, i, &DisPlayField, sizeof(DisPlayField)); + i = i + LevelMax + 1; + FILE_PUT(FNum, i, &LInfo, sizeof(LInfo)); // store level info + if (! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer))) // demo was recorded + { + // Debug.Print "SaveMPX: " & Hex(LInfo.DemoRandomSeed) + FILE_PUT(FNum, -1, &FirstDemoByte, sizeof(FirstDemoByte)); + if (! DemoBuffer.Serialize(FNum)) + goto SaveMPXEH; + + FILE_PUT(FNum, -1, &FF, sizeof(FF)); + if (0 < strlen(MySignature)) + { + FILE_PUT(FNum, -1, &MySignature, sizeof(MySignature)); + FILE_PUT(FNum, -1, &FF, sizeof(FF)); + } + } + + fclose(FNum); + // --- On Error GoTo 0 + + CurPath = Path; + + // EdAll(); + + if (Path != TmpPath) + Let_ModifiedFlag(False); + + return; + +SaveMPXEH: + // Close(); + fclose(FNum); +} + +#endif + +#if 0 + +static void SaveSP(char *Path) +{ + // int FNum, i; + FILE *FNum; + int i; + // byte T; + + LevelNumber = 1; + LevelCount = 1; + if (! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer))) + LInfo.CheckSumByte = DemoBuffer.CheckSumByte; + + if ((FileMax < FieldMax) || ! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer))) + FileMax = FieldMax; + + // UnEdAll(); + + // --- On Error GoTo SaveSPEH + // FNum = FreeFile(); + FNum = fopen(Path, "wb"); + FILE_PUT(FNum, 1, &PlayField8, sizeof(PlayField8)); + FILE_PUT(FNum, 1, &DisPlayField, sizeof(DisPlayField)); + i = LevelMax + 2; + FILE_PUT(FNum, i, &LInfo, sizeof(LInfo)); // store level info + if (! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer))) // demo was recorded + { + // Debug.Print "SaveMPX: " & Hex(LInfo.DemoRandomSeed) + // If Not DemoBuffer.Serialize(FNum) Then GoTo SaveSPEH + + // Debug.Assert(False); + } + + fclose(FNum); + // --- On Error GoTo 0 + + CurPath = Path; + + // EdAll(); + + if (Path != TmpPath) + Let_ModifiedFlag(False); + + return; + + // SaveSPEH: + // Close(); +} + +#endif + +void CreateLevel(int LWidth, int LHeight) +{ + long Tmp, i; + // byte T; + + CurPath = "Untitled"; + OrigPath = CurPath; + LevelNumber = 1; + FieldWidth = LWidth; + FieldHeight = LHeight; + HeaderSize = 96; + FieldMax = (FieldWidth * FieldHeight) + HeaderSize - 1; + LevelMax = (FieldWidth * FieldHeight) - 1; + FileMax = FieldMax; + PlayField8 = REDIM_1D(sizeof(byte), 0, FileMax + 1 - 1); + DisPlayField = REDIM_1D(sizeof(byte), 0, FieldMax + 1 - 1); + Tmp = FieldWidth * (FieldHeight - 1); + for (i = 0; i <= FieldWidth - 1; i++) + { + PlayField8[i] = fiHardWare; + PlayField8[Tmp + i] = fiHardWare; + } + + Tmp = Tmp; + for (i = FieldWidth; i <= Tmp; i += FieldWidth) + { + PlayField8[i] = fiHardWare; + PlayField8[i - 1] = fiHardWare; + } + + { + LInfo.DemoRandomSeed = 0; + LInfo.InfotronsNeeded = 0; + LInfo.InitialFreezeZonks = 0; + LInfo.InitialGravity = 0; + strcpy(LInfo.LevelTitle, "------ New Level ------");; + LInfo.SpecialPortCount = 0; + LInfo.Version = 0x74; // immitate speedfix version 5.4 + } + PlayField16 = REDIM_1D(sizeof(int), -FieldWidth, FieldMax); + for (i = 0; i <= FieldMax; i++) + { + PlayField16[i] = PlayField8[i]; + DisPlayField[i] = PlayField8[i]; + PlayField8[i] = 0; + } + + AnimationPosTable = REDIM_1D(sizeof(int), 0, LevelMax - 2 *FieldWidth); + AnimationSubTable = REDIM_1D(sizeof(byte), 0, LevelMax - 2 *FieldWidth); + TerminalState = REDIM_1D(sizeof(byte), 0, FieldMax + 1 - 1); + GravityFlag = LInfo.InitialGravity; + FreezeZonks = LInfo.InitialFreezeZonks; + RandomSeed = LInfo.DemoRandomSeed; + DemoAvailable = False; + SET_TO_NOTHING(&DemoBuffer, sizeof(DemoBuffer)); + LevelLoaded = True; + Let_ModifiedFlag(True); +} + +void ReadSignature() +{ + long i, iMin, iMax; + + Trace("modMPX", "--> ReadSignature"); + bSignatureAvailable = False; + gSignature = ""; + + // ##################################################### ReRecording-Test + if ((DemoFlag == 1) && (RecordDemoFlag == 1)) + { + FirstDemoByte = PlayField8[DemoPointer]; + MySignature = gSignature; + } + + // ##################################################### ReRecording-Test + + // gSignature = String(511, "A"): bSignatureAvailable = False: Exit Sub 'test + if (! (FieldMax < FileMax)) + return; + + // !!! Debug.Assert PlayField8(FileMax) = &HFF + Trace("modMPX", "settin iMin/Max"); + iMin = FileMax - 512; + if (iMin < (FieldMax + 2)) + iMin = FieldMax + 2; + + iMax = FileMax - 1; + Trace("modMPX", " For i == iMax To iMin Step -1"); + for (i = iMax; i <= iMin; i += -1) + { + if (PlayField8[i] == 0xFF) + break; + } + + if (i < iMin) + return; + + for (i = i + 1; i <= iMax; i++) + { + gSignature = CAT(gSignature, (char)(PlayField8[i])); + } + + // ##################################################### ReRecording-Test + if ((DemoFlag == 1) && (RecordDemoFlag == 1)) + MySignature = gSignature; + + // ##################################################### ReRecording-Test + + if (iMin <= iMax) + bSignatureAvailable = True; + + Trace("modMPX", "<-- ReadSignature"); +} diff --git a/src/game_sp/modMPX.h b/src/game_sp/modMPX.h new file mode 100644 index 00000000..bd707e21 --- /dev/null +++ b/src/game_sp/modMPX.h @@ -0,0 +1,40 @@ +// ---------------------------------------------------------------------------- +// modMPX.h +// ---------------------------------------------------------------------------- + +#ifndef MODMPX_H +#define MODMPX_H + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +#include "global.h" + +#ifndef HAS_LevelDescriptor +typedef struct +{ + int Width; + int Height; + long OffSet; + long Size; +} LevelDescriptor; +#define HAS_LevelDescriptor +#endif + +extern void CreateLevel(int LWidth, int LHeight); +extern void MpxClose(); +extern boolean MpxLoadLInfo(int i); +extern boolean MpxOpen(char *Path); +extern void ReadSignature(); + +extern void ReadMPX(); + +extern LevelDescriptor *LDesc; +extern boolean DemoAvailable; +extern boolean bSignatureAvailable; +extern char *gSignature; +extern int LevelCount; + +#endif /* MODMPX_H */ diff --git a/src/game_sp/vb_defs.h b/src/game_sp/vb_defs.h new file mode 100644 index 00000000..47ea35be --- /dev/null +++ b/src/game_sp/vb_defs.h @@ -0,0 +1,83 @@ +// ---------------------------------------------------------------------------- +// vb_defs.h +// ---------------------------------------------------------------------------- + +#ifndef VB_DEFS_H +#define VB_DEFS_H + +#define Win16 1 + +#ifndef False +#define False 0 +#define True (!False) +#endif + +#ifndef NULL +#define NULL ((void *)0) +#endif + +/* these are just dummy values to prevent the compiler from complaining */ +#define VALUE_START_VB 100 +#define VALUE_START_VB_KEY 200 +#define VALUE_START_DD 300 +#define VALUE_START_DD_ERR 400 +#define VALUE_START_DS 500 + +#define vbPicTypeBitmap (VALUE_START_VB + 1) +#define vbSrcCopy (VALUE_START_VB + 2) +#define vbTwips (VALUE_START_VB + 3) +#define vbPixels (VALUE_START_VB + 4) +#define vbPRORPortrait (VALUE_START_VB + 5) +#define vbPRORLandscape (VALUE_START_VB + 6) +#define vbDirectory (VALUE_START_VB + 7) + +#define vbKeySpace (VALUE_START_VB_KEY + 1) +#define vbKeyLeft (VALUE_START_VB_KEY + 2) +#define vbKeyRight (VALUE_START_VB_KEY + 3) +#define vbKeyUp (VALUE_START_VB_KEY + 4) +#define vbKeyDown (VALUE_START_VB_KEY + 5) +#define vbKeyEscape (VALUE_START_VB_KEY + 6) +#define vbKeyR (VALUE_START_VB_KEY + 7) +#define vbKeyReturn (VALUE_START_VB_KEY + 8) +#define vbKeyShift (VALUE_START_VB_KEY + 9) + +#define DD_OK (VALUE_START_DD + 0) + +#define DDSD_CAPS (VALUE_START_DD + 1) +#define DDSD_WIDTH (VALUE_START_DD + 2) +#define DDSD_HEIGHT (VALUE_START_DD + 3) +#define DDSCL_NORMAL (VALUE_START_DD + 4) +#define DDBLT_WAIT (VALUE_START_DD + 5) +#define DDSCAPS_VIDEOMEMORY (VALUE_START_DD + 6) +#define DDSCAPS_OFFSCREENPLAIN (VALUE_START_DD + 7) +#define DDSCAPS_PRIMARYSURFACE (VALUE_START_DD + 8) + +#define DDERR_GENERIC (VALUE_START_DD_ERR + 1) +#define DDERR_INVALIDCLIPLIST (VALUE_START_DD_ERR + 2) +#define DDERR_INVALIDOBJECT (VALUE_START_DD_ERR + 3) +#define DDERR_INVALIDPARAMS (VALUE_START_DD_ERR + 4) +#define DDERR_INVALIDRECT (VALUE_START_DD_ERR + 5) +#define DDERR_NOALPHAHW (VALUE_START_DD_ERR + 6) +#define DDERR_NOBLTHW (VALUE_START_DD_ERR + 7) +#define DDERR_NOCLIPLIST (VALUE_START_DD_ERR + 8) +#define DDERR_NODDROPSHW (VALUE_START_DD_ERR + 9) +#define DDERR_NOMIRRORHW (VALUE_START_DD_ERR + 10) +#define DDERR_NORASTEROPHW (VALUE_START_DD_ERR + 11) +#define DDERR_NOROTATIONHW (VALUE_START_DD_ERR + 12) +#define DDERR_NOSTRETCHHW (VALUE_START_DD_ERR + 13) +#define DDERR_NOZBUFFERHW (VALUE_START_DD_ERR + 14) +#define DDERR_SURFACEBUSY (VALUE_START_DD_ERR + 15) +#define DDERR_SURFACELOST (VALUE_START_DD_ERR + 16) +#define DDERR_UNSUPPORTED (VALUE_START_DD_ERR + 17) +#define DDERR_WASSTILLDRAWING (VALUE_START_DD_ERR + 18) + +#define DSSCL_PRIORITY (VALUE_START_DS + 1) +#define DSBCAPS_CTRLFREQUENCY (VALUE_START_DS + 2) +#define DSBCAPS_CTRLPAN (VALUE_START_DS + 3) +#define DSBCAPS_CTRLVOLUME (VALUE_START_DS + 4) +#define DSBCAPS_STATIC (VALUE_START_DS + 5) +#define WAVE_FORMAT_PCM (VALUE_START_DS + 6) +#define DSBSTATUS_PLAYING (VALUE_START_DS + 7) +#define DSBPLAY_DEFAULT (VALUE_START_DS + 8) + +#endif /* VB_DEFS_H */ diff --git a/src/game_sp/vb_lib.c b/src/game_sp/vb_lib.c new file mode 100644 index 00000000..4b1e5cfc --- /dev/null +++ b/src/game_sp/vb_lib.c @@ -0,0 +1,146 @@ +// ---------------------------------------------------------------------------- +// vb_lib.c +// ---------------------------------------------------------------------------- + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + + +/* helper functions for constructs not supported by C */ +void *REDIM_1D(int a, int b, int c) +{ +} + +void *REDIM_2D(int a, int b, int c, int d, int e) +{ +} + +boolean IS_NOTHING(void *a, int b) +{ +} + +void SET_TO_NOTHING(void *a, int b) +{ +} + +void MESSAGE_BOX(char *a) +{ +} + + +char *CAT(const char *a, ...) +{ +} + +char *GET_PATH(char *a, ...) +{ +} + +char *INT_TO_STR(int a) +{ +} + + +boolean STRING_IS_LIKE(char *a, char *b) +{ +} + + +int FILE_GET(FILE *a, int b, void *c, int d) +{ +} + +int FILE_PUT(FILE *a, int b, void *c, int d) +{ +} + + +/* this is just a workaround -- handle array definitions later */ +void *Array(int a, ...) +{ +} + + +/* VB functions that do not return "int" (and would cause compiler errors) */ +double Val(char *a) +{ +} + +char *Left(char *a, int b) +{ +} + +char *left(char *a, int b) +{ +} + +char *Right(char *a, int b) +{ +} + +char *right(char *a, int b) +{ +} + +char *StrReverse(char *a) +{ +} + +int InStr(int a, char *b, char *c) +{ +} + +char *Dir(char *a) +{ +} + +char *Dir_Without_Args() +{ +} + +void Kill(char *a) +{ +} + +char *Chr(int a) +{ +} + +char *String(int a, char *b) +{ +} + +void MkDir(char *a) +{ +} + +char *Hex(int a) +{ +} + + +int FileLen(char *a) +{ +} + +long GetTickCount() +{ +} + +int GetAttr(char *a) +{ +} + +void DoEvents() +{ +} + +void SaveSetting(const char * a, const char *b, char *c, int d) +{ +} + +long GetTempPath(long a, char *b) +{ +} diff --git a/src/game_sp/vb_lib.h b/src/game_sp/vb_lib.h new file mode 100644 index 00000000..d68de81d --- /dev/null +++ b/src/game_sp/vb_lib.h @@ -0,0 +1,63 @@ +// ---------------------------------------------------------------------------- +// vb_lib.h +// ---------------------------------------------------------------------------- + +#ifndef VB_LIB_H +#define VB_LIB_H + +#define Abs(x) ABS(x) +#define Sqr(x) sqrt(x) + + +/* helper functions for constructs not supported by C */ +extern void *REDIM_1D(int, int, int); +extern void *REDIM_2D(int, int, int, int, int); + +extern boolean IS_NOTHING(void *, int); + +extern void SET_TO_NOTHING(void *, int); + +extern void MESSAGE_BOX(char *); + +extern char *CAT(const char *, ...); +extern char *GET_PATH(char *, ...); +extern char *INT_TO_STR(int); + +extern boolean STRING_IS_LIKE(char *, char *); + +extern int FILE_GET(FILE *, int, void *, int); +extern int FILE_PUT(FILE *, int, void *, int); + +/* this is just a workaround -- handle array definitions later */ +extern void *Array(int, ...); + +/* VB functions that do not return "int" (and would cause compiler errors) */ +extern double Val(char *); +extern char *Left(char *, int); +extern char *left(char *, int); +extern char *Right(char *, int); +extern char *right(char *, int); +extern char *StrReverse(char *); +extern int InStr(int, char *, char *); +extern char *Dir(char *); +extern char *Dir_Without_Args(); +extern void Kill(char *); +extern char *Chr(int); +extern char *String(int, char *); +extern void MkDir(char *); +extern char *SlashLess(char *); +extern char *Hex(int); + +extern int FileLen(char *); + +extern long GetTickCount(); + +extern int GetAttr(char *); + +extern void DoEvents(); + +extern void SaveSetting(const char *, const char *, char *, int); + +extern long GetTempPath(long, char *); + +#endif /* VB_LIB_H */ diff --git a/src/game_sp/vb_types.h b/src/game_sp/vb_types.h new file mode 100644 index 00000000..02758feb --- /dev/null +++ b/src/game_sp/vb_types.h @@ -0,0 +1,281 @@ +// ---------------------------------------------------------------------------- +// vb_types.h +// ---------------------------------------------------------------------------- + +#ifndef VB_TYPES_H +#define VB_TYPES_H + +#include "../libgame/types.h" + + +#if 0 +typedef unsigned char boolean; +#endif + +typedef double currency; + +#if 0 +#if !defined(PLATFORM_WIN32) +typedef unsigned char byte; +#endif +#endif + +typedef int Variant; + +typedef struct +{ + int hWnd; +} Object; + +#ifndef HAS_RECT +typedef struct +{ + int left; + int top; + int right; + int bottom; +} RECT; +#define HAS_RECT +#endif + +typedef struct +{ + char *Path; +} vb_App; + +typedef struct +{ + void (*Assert)(boolean); + void (*Print)(char *); +} vb_Debug; + +typedef struct +{ + int Number; + void (*Raise)(int, char *, char *); +} vb_Err; + +typedef struct +{ + int Width; + int Height; + + int ScaleWidth; + int ScaleHeight; + int ScaleMode; + + int Orientation; + + int TwipsPerPixelX; + int TwipsPerPixelY; + + int hWnd; + + int (*ScaleX)(int, int, int); + int (*ScaleY)(int, int, int); +} vb_Generic_Device; + +typedef vb_Generic_Device vb_Screen; + +typedef vb_Generic_Device Form; +typedef vb_Generic_Device Picture; +typedef vb_Generic_Device IPicture; +typedef vb_Generic_Device Printer; + +typedef struct +{ + int lCaps; +} vb_Caps; + +typedef struct +{ + int LWidth; + int LHeight; + int lFlags; + vb_Caps ddsCaps; +} DDSURFACEDESC2; + +typedef struct +{ + void (*SetHWnd)(long); +} DirectDrawClipper; + +typedef struct +{ + boolean (*isLost)(void); + void (*GetSurfaceDesc)(DDSURFACEDESC2); + void (*SetClipper)(DirectDrawClipper); + // long (*Blt)(RECT, DirectDrawSurface7, RECT, int); + void (*BltColorFill)(RECT, int); +} DirectDrawSurface7; + +typedef struct +{ + DirectDrawSurface7 (*CreateSurface)(DDSURFACEDESC2); + DirectDrawSurface7 (*CreateSurfaceFromFile)(char *, DDSURFACEDESC2); + void (*SetCooperativeLevel)(int, int); + DirectDrawClipper (*CreateClipper)(int); + void (*RestoreAllSurfaces)(void); +} DirectDraw7; + +typedef struct +{ + int lFlags; +} DSBUFFERDESC; + +typedef struct +{ + int nFormatTag; + int nChannels; + int lSamplesPerSec; + int nBitsPerSample; + int nBlockAlign; + int lAvgBytesPerSec; +} WAVEFORMATEX; + +typedef struct +{ + int (*GetStatus)(void); + void (*Play)(int); +} DirectSoundBuffer; + +typedef struct +{ + void (*SetCooperativeLevel)(long, int); + DirectSoundBuffer (*CreateSoundBufferFromFile)(char *, DSBUFFERDESC, WAVEFORMATEX); +} DirectSound; + +typedef struct +{ + DirectDraw7 (*DirectDrawCreate)(char *); + DirectSound (*DirectSoundCreate)(char *); + void (*GetWindowRect)(long, RECT); +} DirectX7; + +typedef struct +{ + int Left; + int Top; + void (*RefreshMarker)(void); +} MarkerObject; + +typedef struct +{ + void (*DelayMS)(long, boolean); + double (*TickDiffUS)(double); + double TickNow; +} TickCountObject; + +typedef struct +{ + int Caption; + void (*Refresh)(void); +} MainForm_lblCount; + +typedef struct +{ + boolean Checked; + boolean Enabled; +} MainForm_men; + +typedef struct +{ + int Width; + int Height; + void (*Line)(int, int, int, int, int, int); +} MainForm_picPane; + +typedef struct +{ + MainForm_lblCount lblInfoCount; + MainForm_lblCount lblRedDiskCount; + void (*DisplayLevel)(void); + void (*DrawField)(int, int); + MainForm_men menGravOn; + MainForm_men menZonkOn; + MainForm_men menEnOn; + MainForm_men menGravOff; + MainForm_men menZonkOff; + MainForm_men menEnOff; + MainForm_men menRemSP; + MainForm_men menSP; + char *Caption; + boolean PanelVisible; + void (*ShowKey)(int); + void (*SaveSnapshot)(int); + void (*menStop_Click)(void); + MainForm_picPane picPane; + char *lblFrameCount; + void (*SetDisplayRegion)(void); +} MainFormObject; + +typedef struct +{ + int DestXOff; + int DestYOff; + + void (*Blt)(); + void (*ScrollTo)(int, int); + void (*ScrollTowards)(int, int, double); + void (*SoftScrollTo)(int, int, long, int); + +} DDScrollBuffer; + +typedef struct +{ + void (*BltEx)(int, int, int); +} DDSpriteBuffer; + +typedef struct +{ + void (*CreateAtSize)(long, long, long); + void (*Let_Palette)(long, long); + void (*Let_ColorIndex)(long, long, long); +} BitMapObject; + +struct DemoBufferObject +{ + int Size; + byte CheckSumByte; + void (*SetSubBuffer)(struct DemoBufferObject *); + void (*AddDemoKey)(int); + boolean (*Serialize)(FILE *); +}; +typedef struct DemoBufferObject DemoBufferObject; + +typedef struct +{ + int (*Read)(char *ValName, int Default); + void (*Save)(char *ValName, int Val); +} SettingsObject; + +typedef struct +{ + int left; + int top; + int ListIndex; + char (*List)(int); +} cmbFileObject; + +typedef struct +{ + int Width; + int Height; + boolean Visible; + void (*Move)(int, int, int); +} shpProgressObject; + +typedef struct +{ + int left; + int Top; + int Width; + int Height; +} lblFrameCountObject; + +typedef struct +{ + boolean Checked; +} menBorderObject; + +#endif /* VB_TYPES_H */ diff --git a/src/game_sp/vb_vars.c b/src/game_sp/vb_vars.c new file mode 100644 index 00000000..a6c17a8c --- /dev/null +++ b/src/game_sp/vb_vars.c @@ -0,0 +1,15 @@ +// ---------------------------------------------------------------------------- +// vb_vars.c +// ---------------------------------------------------------------------------- + +#include "vb_types.h" +#include "vb_defs.h" +#include "vb_vars.h" +#include "vb_lib.h" + +vb_App App; +vb_Err Err; +MainFormObject MainForm; +lblFrameCountObject lblFrameCount; +cmbFileObject cmbFile; +shpProgressObject shpProgress; diff --git a/src/game_sp/vb_vars.h b/src/game_sp/vb_vars.h new file mode 100644 index 00000000..daf359ee --- /dev/null +++ b/src/game_sp/vb_vars.h @@ -0,0 +1,23 @@ +// ---------------------------------------------------------------------------- +// vb_vars.h +// ---------------------------------------------------------------------------- + +#ifndef VB_VARS_H +#define VB_VARS_H + +extern vb_Screen Screen; +extern vb_Debug Debug; +extern vb_Err Err; +extern vb_App App; + +extern DemoBufferObject VB_OBJECT_SELF; + +extern MainFormObject MainForm; +extern cmbFileObject cmbFile; +extern shpProgressObject shpProgress; +extern lblFrameCountObject lblFrameCount; +extern menBorderObject menBorder; + +extern int hWnd; + +#endif /* VB_VARS_H */ diff --git a/src/main.h b/src/main.h index 68f1eed0..38a5bcbf 100644 --- a/src/main.h +++ b/src/main.h @@ -24,6 +24,7 @@ #include "libgame/libgame.h" #include "game_em/game_em.h" +#include "game_sp/game_sp.h" #include "conf_gfx.h" /* include auto-generated data structure definitions */ #include "conf_snd.h" /* include auto-generated data structure definitions */ @@ -2007,11 +2008,11 @@ #define PROGRAM_VERSION_MAJOR 3 #define PROGRAM_VERSION_MINOR 2 #define PROGRAM_VERSION_PATCH 6 -#define PROGRAM_VERSION_BUILD 1 +#define PROGRAM_VERSION_BUILD 2 #define PROGRAM_TITLE_STRING "Rocks'n'Diamonds" #define PROGRAM_AUTHOR_STRING "Holger Schemel" -#define PROGRAM_COPYRIGHT_STRING "Copyright ©1995-2008 by Holger Schemel" +#define PROGRAM_COPYRIGHT_STRING "Copyright ©1995-2009 by Holger Schemel" #define PROGRAM_EMAIL_STRING "info@artsoft.org" #define PROGRAM_WEBSITE_STRING "http://www.artsoft.org/" #define PROGRAM_GAME_BY_STRING "A Game by Artsoft Entertainment" @@ -2099,8 +2100,9 @@ #define GAME_ENGINE_TYPE_UNKNOWN LEVEL_FILE_TYPE_UNKNOWN #define GAME_ENGINE_TYPE_RND LEVEL_FILE_TYPE_RND #define GAME_ENGINE_TYPE_EM LEVEL_FILE_TYPE_EM +#define GAME_ENGINE_TYPE_SP LEVEL_FILE_TYPE_SP -#define NUM_ENGINE_TYPES 3 +#define NUM_ENGINE_TYPES 4 struct BorderInfo -- 2.34.1