Initial commit of Dink Smallwood HD source. See the "Programmer readme.txt" for information on how to set it up.

git-svn-id: svn://rtsoft.com/rtsvn/projects/RTDink@1469 353e56fe-9613-0410-8469-b96ad8e6f29c
This commit is contained in:
seth 2017-09-12 04:57:47 +00:00
parent dfbc2348a5
commit d4f66a5d2e
115 changed files with 37737 additions and 0 deletions

236
source/dink/FFReader.cpp Normal file
View file

@ -0,0 +1,236 @@
#include "PlatformPrecomp.h"
#include "FFReader.h"
FFReader::FFReader()
{
m_fp = NULL;
}
FFReader::~FFReader()
{
Kill();
}
void FFReader::Kill()
{
if (m_fp)
{
fclose(m_fp);
m_fp = NULL;
}
m_fileHeader.clear();
m_bUsingBaseDinkFF = false;
m_error = ERROR_NONE;
}
int FFReader::GetFFRecordIndexFromFileName(const string &fName)
{
assert(m_fp);
for (unsigned int i=0; i < m_fileHeader.size(); i++)
{
if (strcmp(fName.c_str(), m_fileHeader[i].name) == 0)
return i;
}
return -1;
}
bool FFReader::DoesFileExist( const string &fName )
{
//LogMsg("Checking for %s", (m_basePath+fName).c_str());
if (m_fp)
{
if (GetFFRecordIndexFromFileName(fName) != -1) return true;
}
if (!m_dmodGamePath.empty())
{
if (FileExists(m_dmodGamePath+m_basePath+fName)) return true;
}
if (!FileExists(m_gamePath+m_basePath+fName))
{
//LogMsg("Can't find %s", (m_basePath+fName).c_str());
return false;
}
return true;
}
void FFReader::Init( const string &gamePath, const string &dmodGamePath, const string &basePath, bool bUsingDinkPak )
{
if (m_basePath == basePath && m_dmodGamePath == dmodGamePath)
{
//optimization, detect when we don't have to reload this
return;
}
Kill();
m_dmodBasePath = basePath;
if (!bUsingDinkPak)
{
m_gamePath = GetBaseAppPath()+gamePath;
m_basePath = basePath;
} else
{
//using dink.pak
m_basePath = gamePath+basePath;
}
m_dmodGamePath = dmodGamePath;
//first scan for an .ff file
assert(!m_fp);
if (!dmodGamePath.empty())
{
m_fp = fopen((m_dmodGamePath+m_dmodBasePath+"dir.ff").c_str(), "rb");
}
if (!m_fp)
{
m_fp = fopen((m_gamePath+m_basePath+"dir.ff").c_str(), "rb");
if (m_fp)
{
m_bUsingBaseDinkFF = true;
}
}
if (!m_fp) return; //no ff to scan in this case
int totalFiles;
FFFileInfo f;
fread(&totalFiles, sizeof(int), 1, m_fp);
for (int i=0; i < totalFiles; i++)
{
fread(&f, sizeof(f), 1, m_fp);
assert(strlen(f.name) < 13);
ToLowerCase(f.name);
m_fileHeader.push_back(f);
}
//LogMsg("FFScanning %s, %d entries", basePath.c_str(), m_fileHeader.size());
}
int FFReader::GetNextFFIndex(int index)
{
if (m_fileHeader[index+1].offset != 0)
{
return index+1;
}
assert(index+2 < m_fileHeader.size() );
return index+2;
}
void FFReader::SetError(eErrorType error)
{
m_error = error;
if (error == ERROR_LOW_MEM)
{
GetBaseApp()->SetLastError(BaseApp::ERROR_MEM);
}
}
byte * FFReader::LoadFFIntoMemory(int index, int *pSizeOut)
{
int byteSize = m_fileHeader[GetNextFFIndex(index)].offset-m_fileHeader[index].offset;
if (pSizeOut) *pSizeOut = byteSize;
fseek(m_fp, m_fileHeader[index].offset, SEEK_SET);
byte *pMem = new byte[byteSize+1]; //extra one for a null we're going to attach
#ifdef _DEBUG
/*
if (Random(60) == 1)
{
//fake a memory error
SAFE_DELETE_ARRAY(pMem);
}
*/
#endif
if (!pMem)
{
LogError("Out of mem!");
SetError(ERROR_LOW_MEM);
return NULL;
}
pMem[byteSize] = 0; //ending null, useful if we loaded a text file
fread(pMem, byteSize, 1, m_fp);
return pMem;
}
byte * FFReader::LoadFileIntoMemory( string const &fName, int *pSizeOut )
{
#ifdef _DEBUG
//LogMsg("loading for %s", (m_basePath+fName).c_str());
#endif
int len;
byte *pBuff = NULL;
if (m_fp)
{
if (m_bUsingBaseDinkFF && !m_dmodGamePath.empty())
{
//you know what? Let's do a last minute try in the dmod dir as well.
if (FileExists(m_dmodGamePath+m_dmodBasePath+fName))
{
//pBuff = LoadFileIntoMemoryBasic(m_dmodGamePath+m_basePath+fName, &len, false, false);
pBuff = GetFileManager()->Get(m_dmodGamePath+m_dmodBasePath+fName, &len, false);
if (!pBuff) SetError(ERROR_LOW_MEM);
return pBuff;
}
}
int index = GetFFRecordIndexFromFileName(fName);
if (index != -1)
{
//we found it!
return LoadFFIntoMemory(index, pSizeOut);
}
} else
{
if (!m_dmodGamePath.empty())
{
if (FileExists(m_dmodGamePath+m_dmodBasePath+fName))
{
//pBuff = LoadFileIntoMemoryBasic(m_dmodGamePath+m_basePath+fName, &len, false, false);
pBuff = GetFileManager()->Get(m_dmodGamePath+m_dmodBasePath+fName, &len,false);
if (!pBuff) SetError(ERROR_LOW_MEM);
return pBuff;
}
}
//pBuff = LoadFileIntoMemoryBasic(m_gamePath+m_basePath+fName, &len, false, false);
pBuff = GetFileManager()->Get(m_gamePath+m_basePath+fName,&len, false);
if (len == UINT_MAX) SetError(ERROR_LOW_MEM);
return pBuff;
}
return NULL;
}

60
source/dink/FFReader.h Normal file
View file

@ -0,0 +1,60 @@
// ***************************************************************
// FFReader - Creation date: 12/31/2009
// -------------------------------------------------------------
// Robinson Technologies Copyright (C) 2009 - All Rights Reserved
//
// ***************************************************************
// Programmer(s): Seth A. Robinson (seth@rtsoft.com)
// ***************************************************************
#ifndef FFReader_h__
#define FFReader_h__
#include "BaseApp.h"
#pragma pack(push, 1)
struct FFFileInfo
{
int offset;
char name[13];
};
#pragma pack(pop)
class FFReader
{
public:
enum eErrorType
{
ERROR_NONE,
ERROR_LOW_MEM
};
FFReader();
virtual ~FFReader();
bool DoesFileExist(const string &fName);
void Init( const string &gamePath, const string &dmodGamePath, const string &baseDir, bool bUsingDinkPak);
byte * LoadFileIntoMemory(string const &fName, int *pSizeout); //you need to delete [] what this gives you on your own
eErrorType GetLastError() {return m_error;}
private:
void Kill();
int GetFFRecordIndexFromFileName(const string &fName);
byte * LoadFFIntoMemory(int index, int *pSizeOut);
int GetNextFFIndex(int index);
void SetError(eErrorType error);
string m_gamePath;
string m_dmodGamePath;
string m_basePath;
FILE *m_fp;
bool m_bUsingBaseDinkFF;
eErrorType m_error;
string m_dmodBasePath;
vector<FFFileInfo> m_fileHeader;
};
#endif // FFReader_h__

View file

@ -0,0 +1,38 @@
#include "PlatformPrecomp.h"
#include "ScriptAccelerator.h"
#include "util/MiscUtils.h"
ScriptAccelerator::ScriptAccelerator()
{
}
ScriptAccelerator::~ScriptAccelerator()
{
}
void ScriptAccelerator::Kill()
{
m_data.clear();
}
void ScriptAccelerator::AddPosition(string label, int current)
{
label = ToUpperCaseString(label);
m_data[label] = ScriptPosition(current);
}
ScriptPosition * ScriptAccelerator::GetPositionByName( string label )
{
label = ToUpperCaseString(label);
ScriptMap::iterator itor = m_data.find(label);
if (itor != m_data.end())
{
//bingo!
return &(itor->second);
}
return NULL;
}

View file

@ -0,0 +1,46 @@
// ***************************************************************
// ScriptAccelerator - Creation date: 01/23/2010
// -------------------------------------------------------------
// Robinson Technologies Copyright (C) 2010 - All Rights Reserved
//
// ***************************************************************
// Programmer(s): Seth A. Robinson (seth@rtsoft.com)
// ***************************************************************
#ifndef ScriptAccelerator_h__
#define ScriptAccelerator_h__
#include "PlatformSetup.h"
class ScriptPosition
{
public:
ScriptPosition(){};
ScriptPosition(int pos) : current (pos){};
int current;
};
typedef map<string, ScriptPosition> ScriptMap;
class ScriptAccelerator
{
public:
ScriptAccelerator();
virtual ~ScriptAccelerator();
void Kill();
ScriptPosition * GetPositionByName(string label);
void AddPosition(string label, int current);
private:
ScriptMap m_data;
};
#endif // ScriptAccelerator_h__

17078
source/dink/dink.cpp Normal file

File diff suppressed because it is too large Load diff

762
source/dink/dink.h Normal file
View file

@ -0,0 +1,762 @@
#ifndef dink_h__
#define dink_h__
#include "App.h"
#define DSBSTATUS_PLAYING 0x00000001
#define DSBSTATUS_BUFFERLOST 0x00000002
#define DSBSTATUS_LOOPING 0x00000004
#define DSBSTATUS_LOCHARDWARE 0x00000008
#define DSBSTATUS_LOCSOFTWARE 0x00000010
#define DSBSTATUS_TERMINATED 0x00000020
#include "misc_util.h"
#include "video_gl.h"
#include "util/TextScanner.h"
bool InitDinkEngine();
bool LoadGameChunk(int gameIDToLoad, float &progressOut); //0 for new game
void updateFrame();
void finiObjects();
struct SpriteStruct;
//finished loading is used with g_dglo.m_curLoadState to fake the loader out
#define FINISHED_LOADING 100
enum eDinkInput
{
DINK_INPUT_UP,
DINK_INPUT_RIGHT,
DINK_INPUT_DOWN,
DINK_INPUT_LEFT,
DINK_INPUT_BUTTON1, //punch
DINK_INPUT_BUTTON2, //talk
DINK_INPUT_BUTTON3,
DINK_INPUT_BUTTON4,
DINK_INPUT_BUTTON5, //escape
DINK_INPUT_BUTTON6, //map
DINK_INPUT_BUTTON7,
DINK_INPUT_COUNT
};
enum eDinkGameMode
{
DINK_GAME_MODE_NONE,
DINK_GAME_MODE_MOUSE,
DINK_GAME_MODE_NORMAL,
DINK_GAME_MODE_INVENTORY,
};
enum eDinkSubGameMode
{
DINK_SUB_GAME_MODE_NONE,
DINK_SUB_GAME_MODE_NORMAL,
DINK_SUB_GAME_MODE_SHOWING_BMP,
DINK_SUB_GAME_MODE_DIALOG
};
struct BackgroundSprite
{
rtRect32 dstRect;
rtRect32 srcRect;
int32 pic;
};
class BackgroundSpriteManager
{
public:
void Clear();
void Add(int spriteID);
void Render(LPDIRECTDRAWSURFACE lpdest);
int GetCount() {return m_sprites.size();}
private:
deque<BackgroundSprite> m_sprites;
};
class DinkGlobals
{
public:
enum eView
{
VIEW_ZOOMED,
VIEW_FULL_WITHOUT_EDGES,
VIEW_FULL, //all 640X480 of it, used in the title screen parts
VIEW_ONE_TO_ONE,
VIEW_NONE,
VIEW_COUNT
};
DinkGlobals()
{
memset(m_dirInput, 0, sizeof(DINK_INPUT_COUNT*sizeof(bool)));
memset(m_dirInputFinished, 0, sizeof(DINK_INPUT_COUNT*sizeof(bool)));
m_curLoadState = 0;
m_bFullKeyboardActive = false;
m_bLastFullKeyboardActive = false;
m_bSpeedUpMode = false;
m_bUsingDinkPak = false;
m_aspectRatioModX = 1.0f; //not the aspect ratio, the change to the aspect ratio so it's the correct aspect ratio. I know, it makes no sense
m_aspectRatioModY = 1.0f;
}
void SetView(eView view);
void ToggleView();
void SetViewOverride(eView view); //don't allow anyone to change it
void UnSetViewOverride();
eView GetActiveView() {if (m_viewOverride != VIEW_NONE) return m_viewOverride; return m_curView;}
bool m_dirInput[DINK_INPUT_COUNT];
bool m_dirInputFinished[DINK_INPUT_COUNT]; //allows us to handle button up/down events on the same frame without losing
//data
string m_lastMusicPath;
string m_gamePath; //where the dink dir is located
string m_gamePathWithDir; //same as above but with /dink tagged on
string m_gameDir; //"dink/"
string m_dmodGamePathWithDir;
string m_dmodGameDir;
string m_savePath; //where the save games are
float m_fontSize;
rtRectf m_nativeGameArea;
rtRect32 m_gameArea;
rtRect32 m_orthoRenderRect; //control which part of Dink's 640X480 get drawn to the screen and at what scale
unsigned int m_transitionTimer;
float m_transitionProgress;
CL_Vec2f m_transitionOffset;
CL_Vec2f m_transitionOffsetNative; //same thing in actual screen pixels
eView m_curView;
eView m_viewOverride;
bool m_bWaitingForSkippableConversation;
//handle the loading process
int m_curLoadState;
TextScanner m_iniScanner;
eDinkGameMode m_lastGameMode;
eDinkSubGameMode m_lastSubGameMode;
eView m_lastActiveView;
bool m_lastIsUpdatingDinkStatusBar;
bool m_bFullKeyboardActive;
bool m_bLastFullKeyboardActive;
bool m_bSpeedUpMode;
BackgroundSpriteManager m_bgSpriteMan;
bool m_bUsingDinkPak;
float m_aspectRatioModX;
float m_aspectRatioModY;
CL_Vec3f m_centeringOffset;
};
//#define KYLES_CRAZY_VERSION
#ifdef KYLES_CRAZY_VERSION
const int C_MAX_SEQUENCES = 9999; //Max # of sprite animations
const int C_MAX_SPRITES = 19999;
const int C_MAX_SPRITES_AT_ONCE = 500;
const int C_MAX_SCRIPT_CALLBACKS = 300;
const int max_vars = 5000;
#define C_MAX_SPRITE_FRAMES 99
#define C_SPRITE_MAX_FILENAME_SIZE 64
const int C_MAX_SCRIPTS = 400;
#else
const int32 C_MAX_SEQUENCES = 1300; //Max # of sprite animations
const int32 C_MAX_SPRITES = 6000;
const int32 C_MAX_SPRITES_AT_ONCE = 300;
const int32 C_MAX_SCRIPT_CALLBACKS = 100;
const int32 max_vars = 250;
#define C_MAX_SPRITE_FRAMES 51
#define C_SPRITE_MAX_FILENAME_SIZE 64
const int32 C_MAX_SCRIPTS = 200;
#endif
struct sequence
{
int16 frame[C_MAX_SPRITE_FRAMES];
int16 delay[C_MAX_SPRITE_FRAMES];
unsigned char special[C_MAX_SPRITE_FRAMES];
byte active;
short m_xoffset, m_yoffset;
rtRect32 m_hardbox;
eTransparencyType m_transType;
byte m_bLeftAlign;
byte m_speed;
char m_fileName[C_SPRITE_MAX_FILENAME_SIZE];
short x,y;
short s;
byte last;
byte m_spaceAllowed;
byte m_bFrameSetUsed;
byte m_bIsAnim;
};
const int32 C_DINK_SCREENSIZE_X = 640;
const int32 C_DINK_SCREENSIZE_Y = 480;
const int32 C_DINK_VERSION = 109;
const int32 num_soundbanks = 20;
const int32 max_idata = 1000;
const int32 max_sounds = 100;
const int32 text_timer = 77;
const int32 text_min = 2700;
const int32 max_game = 20;
const int32 C_TILE_SCREEN_COUNT = 41+1;
const int32 g_gameAreaRightBarStartX = 620;
const int32 g_gameAreaLeftOffset = 20;
const int32 C_DINK_ORIGINAL_GAME_AREA_Y = 400; //redink1's fix for the 'no sprites on pixel line above status bar' bug
eDinkGameMode GetDinkGameMode();
eDinkSubGameMode GetDinkSubGameMode();
struct font_color
{
int32 red;
int32 green;
int32 blue;
};
struct ShowingBitmapInfo
{
bool active;
bool showdot;
int32 reserved;
int32 script;
int32 stime;
int32 picframe;
};
struct wait_for_button
{
int32 script;
int32 button;
bool active;
};
struct talk_struct
{
char line[21][101];
int32 line_return[21];
char buffer[3000];
int32 cur;
int32 last;
bool active;
int32 cur_view;
int32 cur_view_end;
int32 page;
int32 script;
int32 offset;
int32 newy;
int32 color;
int32 curf;
int32 timer;
};
struct mydata
{
unsigned char type[100];
unsigned short seq[100];
unsigned char frame[100];
int32 last_time;
};
struct varman
{
int32 var;
char name[20];
int32 scope;
bool active;
};
struct item_struct
{
bool active;
char name[10];
int32 seq;
int32 frame;
};
struct player_info_tile
{
char file[50];
};
struct global_function
{
char file[10];
char func[20];
};
struct player_info
{
int32 version;
char gameinfo[196];
int32 minutes;
int32 x,y,die, size, defense, dir, pframe, pseq, seq, frame, strength, base_walk, base_idle, base_hit,que;
item_struct g_MagicData[9]; //1 index based, man I was dumb(er) back then
item_struct g_itemData[17];
int32 curitem, unused;
int32 counter;
bool idle;
mydata spmap[769];
int32 button[10];
varman var[max_vars];
bool push_active;
int32 push_dir;
uint32 push_timer;
int32 last_talk;
int32 mouse;
bool item_magic;
int32 last_map;
int32 crap;
int32 buff[95];
uint32 dbuff[20];
int32 lbuff[10];
//redink1... use wasted space for storing file location of map.dat, dink.dat, palette, and tiles
char mapdat[50];
char dinkdat[50];
char palette[50];
player_info_tile tile[42];
global_function func[100];
uint32 m_gameTime;
char cbuff[746];
};
struct attackinfo_struct
{
int32 time;
bool active;
int32 script;
bool hitme;
int32 last_power;
int32 wait;
int32 pull_wait;
};
struct player_short_info
{
int32 version;
char gameinfo[196];
int32 minutes;
};
struct refinfo
{
char name[10];
int32 location;
int32 current;
int32 level;
int32 end;
int32 sprite; //if more than 0, it was spawned and is owned by a sprite, if 1000 doesn't die
bool skipnext;
int32 onlevel;
int32 proc_return;
int32 arg1;
int32 arg2;
int32 arg3;
int32 arg4;
int32 arg5;
int32 arg6;
int32 arg7;
int32 arg8;
int32 arg9;
};
struct call_back
{
int32 owner;
bool active;
int32 type;
char name[20];
int32 offset;
int32 min, max;
int32 lifespan;
uint32 timer;
};
struct SpriteStruct
{
int32 x,moveman;
int32 y;
int32 mx,my;
int32 lpx[C_MAX_SPRITE_FRAMES],lpy[C_MAX_SPRITE_FRAMES];
int32 speed;
int32 brain;
int32 seq_orig,dir;
int32 seq;
int32 frame;
uint32 delay;
int32 pseq;
int32 pframe;
bool active;
int32 attrib;
uint32 wait;
int32 timer;
int32 skip;
int32 skiptimer;
int32 size;
int32 que;
int32 base_walk;
int32 base_idle;
int32 base_attack;
int32 base_hit;
int32 last_sound;
int32 hard;
rtRect32 alt;
int32 althard;
int32 sp_index;
bool nocontrol;
int32 idle;
int32 strength;
int32 damage;
int32 defense;
int32 hitpoints;
int32 exp;
int32 gold;
int32 base_die;
int32 kill;
int32 kill_timer;
int32 script_num;
char text[200];
int32 owner;
int32 script;
int32 sound;
int32 callback;
int32 freeze;
bool move_active;
int32 move_script;
int32 move_dir;
int32 move_num;
bool move_nohard;
int32 follow;
int32 nohit;
bool notouch;
uint32 notouch_timer;
bool flying;
int32 touch_damage;
int32 brain_parm;
int32 brain_parm2;
bool noclip;
bool reverse;
bool disabled;
int32 target;
int32 attack_wait;
int32 move_wait;
int32 distance;
int32 last_hit;
bool live;
int32 range;
int32 attack_hit_sound;
int32 attack_hit_sound_speed;
int32 action;
int32 nodraw;
int32 frame_delay;
int32 picfreeze;
//redink1
int32 bloodseq;
int32 bloodnum;
int32 m_containsSpriteMapData; //1 if yes, 0 if no (the save/load function adds data here if needed)
};
extern std::map<std::string, int32>* g_customSpriteMap[C_MAX_SPRITES_AT_ONCE];
struct seth_joy
{
bool joybit[17]; //is button held down?
bool letgo[17]; //copy of old above
bool button[17]; //has button been pressed recently?
bool key[256];
bool kletgo[256];
bool realkey[256];
bool right,left,up,down;
bool rightd,leftd,upd,downd;
bool rightold,leftold,upold,downold;
};
//sub struct for hardness map
struct mega_y
{
byte y[401];
};
//struct for hardness map
struct hit_map
{
mega_y x[601];
};
//sub struct for tile hardness
#define C_DINK_TILE_SIZE_IN_PIXELS 50
struct block_y
{
byte y[C_DINK_TILE_SIZE_IN_PIXELS+1]; //the +1 is because I did everything 1 index based. Yeah, I was an idiot.
};
struct ts_block
{
block_y x[C_DINK_TILE_SIZE_IN_PIXELS+1];
bool used;
int32 hold;
};
//struct for hardness info, INDEX controls which hardness each block has. 800 max
//types available.
struct hardness
{
ts_block tile[800];
int32 index[8000];
};
struct map_info
{
char name[20];
int32 loc[769];
int32 music[769];
int32 indoor[769];
int32 v[40];
char s[80];
char buffer[2000];
};
struct tile
{
int32 num, property, althard, more2;
byte more3,more4;
int32 buff[15];
};
struct sprite_placement
{
int32 x,y,seq,frame, type,size;
bool active;
int32 rotation, special,brain;
char script[13];
char hit[13];
char die[13];
char talk[13];
int32 speed, base_walk,base_idle,base_attack,base_hit,timer,que;
int32 hard;
rtRect32 alt;
int32 prop;
int32 warp_map;
int32 warp_x;
int32 warp_y;
int32 parm_seq;
int32 base_die, gold, hitpoints, strength, defense,exp, sound, vision, nohit, touch_damage;
int32 buff[5];
};
struct small_map
{
char name[20];
tile t[97];
int32 v[40];
char s[80];
sprite_placement sprite[101];
char script[13];
char random[13];
char load[13];
char buffer[1000];
};
struct pic_info
{
int32 m_filler; //used to store a pointer here, was moved out of the struct as it's saved/loaded in a raw way that depended on 32 bit pointers
rtRect32 box,hardbox;
int16 yoffset;
int16 xoffset;
int16 m_parentSeq;
byte m_bCustomSettingsApplied;
};
extern LPDIRECTDRAWSURFACE g_pSpriteSurface[C_MAX_SPRITES];
struct seth_sound
{
string m_fileName;
};
struct soundstruct
{
bool repeat;
int32 owner;
int32 survive;
int32 vol;
int32 freq; //what speed it was played at
};
class SoundBankDummy
{
public:
SoundBankDummy()
{
m_audioID = AUDIO_HANDLE_BLANK;
}
void Stop() {GetAudioManager()->Stop(m_audioID); m_audioID = 0; m_soundIDThatPlayedUs = 0;};
void SetPan(float f) {GetAudioManager()->SetPan(m_audioID,f/1700);};
void SetVolume(float f){GetAudioManager()->SetVol(m_audioID, (1800+f) / 1800);};
bool IsInUse() {if (m_audioID == 0) return false; return GetAudioManager()->IsPlaying(m_audioID);}
void Reset()
{
if (m_audioID)
{
GetAudioManager()->Stop(m_audioID);
m_audioID = AUDIO_HANDLE_BLANK;
}
}
AudioHandle m_audioID;
int32 m_soundIDThatPlayedUs;
};
#define C_SHOWN_BITMAP_SIZE 128
struct DinkGlobalsStatic
{
sequence g_seq[C_MAX_SEQUENCES];
pic_info g_picInfo[C_MAX_SPRITES]; // Sprite data
ShowingBitmapInfo g_bShowingBitmap;
wait_for_button g_wait_for_button;
attackinfo_struct g_bowStatus;
small_map g_smallMap;
player_info g_playerInfo;
talk_struct g_talkInfo;
hit_map g_hitmap;
int32 but_timer;
int32 dinkspeed;
uint32 time_start;
uint32 g_DinkUpdateTimerMS;
uint32 mDinkBasePush;
int32 walk_off_screen;
int32 keep_mouse;
int32 last_sprite_created;
int32 g_curPicIndex; //we actually need this set before finiObjects is called
int32 cur_map,cur_tile;
uint32 g_dinkTick,lastTickCount;
char current_map[50];
char current_dat[50];
char dversion_string[6];
char save_game_info[200];
font_color font_colors[16];
int32 g_stopEntireGame;
int32 g_pushingEnabled;
bool no_running_main;
int32 process_count;
int32 show_dot;
int32 plane_process;
int32 base_timing;
int32 weapon_script;
int32 magic_script;
int32 g_gameMode;
bool midi_active;
bool mLoopMidi;
int32 flub_mode;
int32 process_warp;
bool process_upcycle;
bool process_downcycle;
uint32 cycle_clock;
int32 cycle_script;
bool bFadedDown;
bool smooth_follow;
bool mSwapped;
int32 item_timer;
int32 item_pic;
int32 mbase_count;
int32 mbase_timing;
call_back g_scriptCallback[C_MAX_SCRIPT_CALLBACKS];
int32 g_guiLife, g_guiExp, g_guiStrength, g_guiDefense, g_guiGold, g_guiMagic, g_guiMagicLevel, g_guiLifeMax, g_guiRaise, g_guiLastMagicDraw;
int32 g_returnint;
bool bKeepReturnInt;
int32 screenlock;
bool m_bRenderBackgroundOnLoad;
char g_lastBitmapShown[C_SHOWN_BITMAP_SIZE];
char m_bufferForExpansion[4968];
};
enum eDinkGameState
{
//helps us to know when to automatically save the game
DINK_GAME_STATE_NOT_PLAYING,
DINK_GAME_STATE_PLAYING
};
extern DinkGlobals g_dglo;
extern DinkGlobalsStatic g_dglos; //static data, made to write/read from disk
bool load_game_small(int num, char * line, int *mytime);
void InitDinkPaths(string gamePath, string gameDir, string dmodGameDir);
void DinkUnloadGraphicsCache();
void ProcessGraphicGarbageCollection();
string GetDMODRootPath(); //where dmods are stored
bool DinkIsWaitingForSkippableDialog();
bool DinkSkipDialogLine(); //returns true if a line was actually skipped
void DinkSetCursorPosition(CL_Vec2f vPos);
CL_Vec2f NativeToDinkCoords(CL_Vec2f vPos);
bool IsDrawingDinkStatusBar();
bool DinkSetInventoryPosition(CL_Vec2f vPos); //returns true if an item was actually set
bool DinkCanRunScriptNow();
bool DinkLoadPlayerScript(const string fileName);
void DinkUnloadUnusedGraphicsByUsageTime(unsigned int timeMS);
bool LoadState(string const &path, bool bLoadPathsOnly);
bool SaveState(string const &path);
eDinkGameState GetDinkGameState();
void SetDinkGameState(eDinkGameState state);
void DinkModStrength(int mod);
void DinkModDefense(int mod);
void DinkModMagic(int mod);
void DinkModLifeMax(int mod);
void DinkFillLife();
void DinkModGold(int mod);
Surface* DinkGetMagicIconImage();
Surface* DinkGetWeaponIconImage();
float DinkGetMagicChargePercent();
float DinkGetHealthPercent();
bool DinkIsDoingScreenTransition();
string DinkGetSavePath();
void DinkAddBow();
bool DinkGetSpeedUpMode();
void DinkSetSpeedUpMode(bool bSpeedup);
void SaveStateWithExtra();
void LoadStateWithExtra();
void SaveAutoSave();
void DinkOnForeground();
string GetDMODStaticRootPath();
void DinkReInitSurfacesAfterVideoChange();
void WriteLastPathSaved(string dmodDir);
string ReadLastPathSaved();
//is the DMOD dir if applicable
#endif // dink_h__

8
source/dink/dinkvar.h Normal file
View file

@ -0,0 +1,8 @@
#ifndef __DINKVAR
#define __DINKVAR
#endif

355
source/dink/misc_util.cpp Normal file
View file

@ -0,0 +1,355 @@
#include "PlatformPrecomp.h"
#include "misc_util.h"
#include "util/MiscUtils.h"
void strchar(char *string, char ch)
/* This acts in the same way as strcat except it combines a string and
a single character, updating the null at the end. */
{
int last;
last=strlen(string);
string[last]=ch;
string[last+1]=0;
}
void dink_decompress( unsigned char *in, char * destBuf )
{
const int stackSize = 2*1024;
unsigned char stack[stackSize], pair[128][2];
int c, top = 0;
memset(stack, 0, stackSize);
memset(pair, 0, 128*2);
int outputSize = 0;
c = *in; in++;
if (c > 127)
{
//read optional pair count and pair table
int readCount = (c-128)*2;
memcpy(&pair,in, readCount );
in += readCount;
}
else
{
if (c == '\r') c = '\n';
if (c == 9) c = ' ';
strchar(destBuf,c);
}
// putc(c,out);
for (;;)
{
/* Pop byte from stack or read byte from file */
if (top)
c = stack[--top];
else
{
if ((c = *in) == 0) break;
in++;
}
/* Push pair on stack or output byte to file */
if (c > 127)
{
if (top >= stackSize )
{
#ifdef _DEBUG
LogMsg("Malformed .d file, can't read it. Would overwrite random memory on the old Dink versions.");
LogMsg("Decompressed to %d bytes", outputSize);
#endif
destBuf[outputSize] = 0;
return;
}
stack[top++] = pair[c-128][1];
stack[top++] = pair[c-128][0];
}
else
{
if (c == '\r') c = '\n';
if (c == 9) c = ' ';
strchar(destBuf,c);// putc(c,out);
outputSize++;
}
}
destBuf[outputSize] = 0;
#ifdef _DEBUG
//LogMsg("Decompressed to %d bytes", outputSize);
#endif
}
//this legacy code is very stupid, but I'll leave it for now, it works, whatever
void decompress_nocomp (byte *in, char destBuf[])
{
const int stackSize = 2*1024;
unsigned char stack[stackSize], pair[128][2];
memset(stack, 0, stackSize);
int c, top = 0;
int outputSize = 0;
c = *in; in++;
if (0)
{
//read optional pair count and pair table
int readCount = (c-128)*2;
memcpy(&pair,in, readCount );
in += readCount;
}
else
{
if (c == '\r') c = '\n';
if (c == 9) c = ' ';
strchar(destBuf,c);
}
// putc(c,out);
for (;;)
{
/* Pop byte from stack or read byte from file */
if (top)
c = stack[--top];
else
{
if ((c = *in) == 0) break;
in++;
}
/* Push pair on stack or output byte to file */
if (0)
{
if (top >= stackSize )
{
#ifdef _DEBUG
LogMsg("Malformed .c file, can't read it. Would overwrite random memory on the old Dink versions.");
destBuf[outputSize] = 0;
#endif
return;
}
stack[top++] = pair[c-128][1];
stack[top++] = pair[c-128][0];
}
else
{
if (c == '\r') c = '\n';
if (c == 9) c = ' ';
strchar(destBuf,c);// putc(c,out);
outputSize++;
}
}
destBuf[outputSize] = 0;
#ifdef _DEBUG
//LogMsg("Decompressed to %d bytes", outputSize);
#endif
}
/*
void decompress (FILE *in, char destBuf[])
{
const int stackSize = 512*1024;
unsigned char stack[stackSize], pair[128][2];
int c, top = 0;
int outputSize = 0;
if ((c = getc(in)) > 127)
fread(pair,2,c-128,in);
else
{
if (c == '\r') c = '\n';
if (c == 9) c = ' ';
strchar(destBuf,c);
}
// putc(c,out);
for (;;) {
if (top)
c = stack[--top];
else if ((c = getc(in)) == EOF)
break;
if (c > 127)
{
if (top >= stackSize )
{
LogMsg("Malformed .d file, can't read it. Would overwrite random memory on the old Dink versions.");
destBuf[outputSize] = 0;
return;
}
stack[top++] = pair[c-128][1];
stack[top++] = pair[c-128][0];
}
else
{
if (c == '\r') c = '\n';
if (c == 9) c = ' ';
strchar(destBuf,c);// putc(c,out);
outputSize++;
}
}
destBuf[outputSize] = 0;
#ifdef _DEBUG
//LogMsg("Decompressed to %d bytes", outputSize);
#endif
}
void decompress_nocomp (FILE *in, char destBuf[])
{
//let's do it, only this time decompile OUR style
unsigned char stack[16], pair[128][2];
short c, top = 0;
if ((c = getc(in)) > 255)
fread(pair,2,c-128,in);
else
{
if (c == '\r') c = '\n';
if (c == 9) c = ' ';
strchar(destBuf,c);
}
// putc(c,out);
for (;;) {
if (top)
c = stack[--top];
else if ((c = getc(in)) == EOF)
break;
if (c > 255) {
stack[top++] = pair[c-128][1];
stack[top++] = pair[c-128][0];
}
else
{
if (c == '\r') c = '\n';
if (c == 9) c = ' ';
strchar(destBuf,c);// putc(c,out);
}
}
}
*/
void replace(const char *this1, char *that, char *line)
{
char hold[500];
char thisup[200],lineup[500];
int u,i;
int checker;
start:
strcpy(hold,"");
strcpy(lineup,line);
strcpy(thisup,this1);
ToUpperCase(lineup);
ToUpperCase(thisup);
if (strstr(lineup,thisup) == NULL) return;
checker = -1;
strcpy(hold,"");
for (u = 0; u < strlen(line); u++)
{
if (checker > -1)
{
if (toupper(line[u]) == toupper(this1[checker]))
{
if (checker+1 == strlen(this1))
{
doit:
u = u - strlen(this1);
u++;
for (i = 0; i < u; i++) hold[i] = line[i];
for (i = 0; i < strlen(that); i++) hold[(u)+i]=that[i];
hold[strlen(that)+u] = 0;
for (i = 0; i < (strlen(line)-u)-strlen(this1); i++)
{
hold[(u+strlen(that))+i] = line[(u+strlen(this1))+i];
}
hold[(strlen(line)-strlen(this1))+strlen(that)] = 0;
strcpy(line,hold);
goto start;
}
checker++;
} else { checker = -1; }
}
if( checker == -1)
{
if (toupper(line[u]) == toupper(this1[0]))
{
checker = 1;
if (strlen(this1) == 1) goto doit;
}
}
}
}
bool separate_string (const char str[255], int num, char liney, char *return1)
{
int l;
int k;
l = 1;
strcpy(return1 ,"");
for (k = 0; k <= strlen(str); k++)
{
if (str[k] == liney)
{
l++;
if (l == num+1)
goto done;
if (k < strlen(str)) strcpy(return1,"");
}
if (str[k] != liney)
sprintf(return1, "%s%c",return1 ,str[k]);
}
if (l < num) strcpy(return1,"");
replace("\n","",return1); //Take the /n off it.
/*
char s[2];
s[0] = 9; //tab
s[1] = 0; //null
replace(s,"",return1); //Take the /n off it.
*/
return(false);
done:
if (l < num) strcpy(return1,"");
replace("\n","",return1); //Take the /n off it.
//Msg("Took %s and turned it to %s.",str, return1);
return(true);
}

18
source/dink/misc_util.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef misc_util_h__
#define misc_util_h__
#include "PlatformSetup.h"
void getdir(char final[]);
void dink_decompress (unsigned char *in, char * destBuf);
void decompress_nocomp (byte *in, char destBuf[]);
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
#endif
void strchar(char *string, char ch) /* This acts in the same way as strcat except it combines a string and a single character, updating the null at the end. */;
bool separate_string (const char str[255], int num, char liney, char *return1);
void replace(const char *this1, char *that, char *line);
char * lmon(int money, char *dest);
void reverse(char *st);
#endif // misc_util_h__

16
source/dink/resource.h Normal file
View file

@ -0,0 +1,16 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by dink.rc
//
#define IDI_ICON1 120
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 122
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View file