Files
Vangers/lib/xtool/xtcore.cpp
2022-05-12 21:36:56 +07:00

663 lines
15 KiB
C++

/* ---------------------------- INCLUDE SECTION ----------------------------- */
#include "lang.h"
#include "xglobal.h"
#include "xt_list.h"
#include "../xgraph/xgraph.h"
#if defined(__unix__) || defined(__linux__) || defined(__APPLE__)
#include <locale.h>
#endif
int __internal_argc;
char **__internal_argv;
/* ----------------------------- STRUCT SECTION ----------------------------- */
struct xtMsgHandlerObject
{
int ID;
void (*Handler)(SDL_Event*);
void* list;
xtMsgHandlerObject* next;
xtMsgHandlerObject* prev;
xtMsgHandlerObject(void (*p)(SDL_Event*),int id);
};
/* ----------------------------- EXTERN SECTION ----------------------------- */
/* --------------------------- PROTOTYPE SECTION ---------------------------- */
void xtSetExit(void);
//int xtNeedExit(void);
int xtCallXKey(SDL_Event* m);
void xtSysQuant(void);
void xtAddSysObj(XList* lstPtr,void (*fPtr)(void),int id);
void xtDeleteSysObj(XList* lstPtr,int id);
void xtDeactivateSysObj(XList* lstPtr,int id);
void xtReadConsoleInput(void);
void xtRegisterSysMsgFnc(void (*fPtr)(SDL_Event*),int id);
void xtRegisterSysFinitFnc(void (*fPtr)(void),int id);
void xtUnRegisterSysFinitFnc(int id);
void xtDeactivateSysFinitFnc(int id);
void xtSysFinit(void);
//void xtPostMessage(HANDLE hWnd,int msg,int wp,int lp);
int xtDispatchMessage(SDL_Event* msg);
void xtProcessMessageBuffer(void);
/* --------------------------- DEFINITION SECTION --------------------------- */
//#define _RTO_LOG_
typedef void (*XFNC)();
#define XT_DEFAULT_TABLE_SIZE 32
XRuntimeObject** XRObjTable = NULL;
unsigned int XRObjTableSize = 0;
XRuntimeObject* XRObjFirst = NULL;
XRuntimeObject* XRObjLast = NULL;
const char* XToolClassName = "XToolClass";
const char* XToolWndName = "XToolWindow";
void* XAppHinst = NULL;
void* XGR_hWnd = NULL;
void* hXConOutput = NULL;
void* hXConInput = NULL;
int XAppMode = 0;
void (*press_handler)(SDL_Event* m);
void (*unpress_handler)(SDL_Event* m);
XList XSysQuantLst;
XList XSysFinitLst;
xtList<xtMsgHandlerObject> XSysHandlerLst;
double XTCORE_FRAME_DELTA = 0;
double XTCORE_FRAME_NORMAL = 0;
#ifdef _RTO_LOG_
XStream xtRTO_Log;
#endif
int xtSysQuantDisabled = 0;
extern bool XGR_FULL_SCREEN;
bool autoconnect = false;
char *autoconnectHost;
unsigned short autoconnectPort = 2197;
bool autoconnectJoinGame = false;
int autoconnectGameID;
XRuntimeObject* XObj = nullptr;
int getCurRtoId() {
return XObj == nullptr ? 0 : XObj->ID;
}
int main(int argc, char *argv[])
{
int id, prevID, clockDelta, clockCnt, clockNow, clockCntGlobal, clockNowGlobal;
__internal_argc = argc;
__internal_argv = argv;
#ifdef _WIN32
std::cout<<"Load backtrace"<<std::endl;
LoadLibraryA("backtrace.dll");
std::cout<<"Set priority class"<<std::endl;
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
putenv("SDL_AUDIODRIVER=DirectSound");
#endif
for (int i = 1; i < argc; i++) {
std::string cmd_key = argv[i];
if (cmd_key == "-fullscreen") {
XGR_FULL_SCREEN = true;
} else if (cmd_key == "-russian") {
setLang(RUSSIAN);
} else if (cmd_key == "-server") {
if (argc > i) {
i++;
autoconnect = true;
autoconnectHost = argv[i];
} else {
std::cout << "Invalid parameter usage: '-server hostname' expected" << std::endl;
}
} else if (cmd_key == "-port") {
if (argc > i) {
i++;
autoconnectPort = (unsigned short)strtol(argv[i], NULL, 0);
} else {
std::cout << "Invalid parameter usage: '-port value' expected" << std::endl;
}
} else if (cmd_key == "-game") {
if (argc > i) {
i++;
std::string value = argv[i];
autoconnectJoinGame = true;
if (value == "new") {
autoconnectGameID = 0;
} else if (value == "any") {
autoconnectGameID = -1;
} else {
autoconnectGameID = (int)strtol(argv[i], NULL, 0);
}
} else {
std::cout << "Invalid parameter usage: '-game [id|new|any]' expected" << std::endl;
}
} else {
std::cout << "Unknown parameter: '" << cmd_key << "'" << std::endl;
}
}
#if defined(__unix__) || defined(__linux__) || defined(__APPLE__)
std::cout<<"Set locale. ";
char* res = setlocale(LC_NUMERIC, "POSIX");
std::cout<<"Result:"<<res<<std::endl;
#endif
//Set handlers to null
press_handler = NULL;
unpress_handler = NULL;
XMsgBuf = new XMessageBuffer;
initclock();
prevID = 0;
#ifdef _WIN32
set_signal_handler();
#endif
id = xtInitApplication();
XObj = xtGetRuntimeObject(id);
#ifdef _RTO_LOG_
if(XRec.flags & XRC_PLAY_MODE)
xtRTO_Log.open("xt_rto_p.log",XS_OUT);
else
xtRTO_Log.open("xt_rto_w.log",XS_OUT);
#endif
while(XObj){
XObj -> Init(prevID);
prevID = id;
id = 0;
clockCnt = clocki();
clockCntGlobal = clockCnt;
while(!id) {
if(XObj->Timer) {
id = XObj -> Quant();
clockNow = clockNowGlobal = clocki();
clockDelta = clockNow - clockCnt;
XTCORE_FRAME_DELTA = (clockNowGlobal - clockCntGlobal) / 1000.0;
XTCORE_FRAME_NORMAL = XTCORE_FRAME_DELTA / 0.050; //20FPS
clockCntGlobal = clockNowGlobal;
// std::cout<<"XTCORE_FRAME_DELTA:"<<XTCORE_FRAME_DELTA
// <<" XTCORE_FRAME_NORMAL:"<<XTCORE_FRAME_NORMAL
// <<" clockDelta:"<<clockDelta<<std::endl;
if (clockDelta < XObj->Timer) {
SDL_Delay(XObj->Timer - clockDelta);
} else {
std::cout<<"Strange deltas clockDelta:"<<clockDelta<<" Timer:"<<XObj->Timer<<std::endl;
if (clockDelta > 300) {
// something wrong and for preventing abnormal physics set something neutral
XTCORE_FRAME_NORMAL = 1.0;
}
}
clockCnt = clocki();
} else {
id = XObj -> Quant();
}
if(!xtSysQuantDisabled)
XRec.Quant(); // впускает внешние события, записывает их или воспроизводит
XGR_Flip();
}
XObj -> Finit();
#ifdef _RTO_LOG_
xtRTO_Log < "\r\nChange RTO: " <= XObj -> ID < " -> " <= id < " frame -> " <= XRec.frameCount;
#endif
XObj = xtGetRuntimeObject(id);
}
xtDoneApplication();
xtSysFinit();
#ifdef _RTO_LOG_
xtRTO_Log.close();
#endif
return 0;
}
void xtCreateRuntimeObjectTable(int len)
{
int i;
if(!len) len = XT_DEFAULT_TABLE_SIZE;
XRObjTableSize = len;
XRObjTable = new XRuntimeObject*[len];
for(i = 0; i < len; i ++){
XRObjTable[i] = NULL;
}
}
XRuntimeObject* xtGetRuntimeObject(unsigned int id)
{
if(id == XT_TERMINATE_ID)
return NULL;
if(!XRObjTable || !XRObjTableSize || id < 1 || id > XRObjTableSize)
ErrH.Abort("XTool system error...");
return XRObjTable[id - 1];
}
void xtRegisterRuntimeObject(XRuntimeObject* p)
{
if(!XRObjFirst){
XRObjFirst = XRObjLast = p;
}
else {
XRObjLast -> next = p;
XRObjLast = p;
}
XRObjTable[p -> ID - 1] = p;
}
int xtCallXKey(SDL_Event* m) {
switch(m->type) {
case SDL_KEYDOWN:
if (press_handler) {
(*press_handler)(m);
}
break;
case SDL_KEYUP:
if (unpress_handler) {
(*unpress_handler)(m);
}
break;
case SDL_TEXTINPUT:
if (press_handler) {
(*press_handler)(m);
}
break;
case SDL_JOYBUTTONDOWN:
//std::cout<<"jevent down button:"<<(int)m->jbutton.button<<std::endl;
if (press_handler) {
(*press_handler)(m);
}
break;
case SDL_JOYBUTTONUP:
//std::cout<<"jevent up"<<std::endl;
if (unpress_handler) {
(*unpress_handler)(m);
}
break;
case SDL_CONTROLLERBUTTONDOWN:
//std::cout<<"CONTROLLERBUTTONDOWN"<<std::endl;
if (press_handler) {
(*press_handler)(m);
}
break;
case SDL_CONTROLLERBUTTONUP:
//std::cout<<"CONTROLLERBUTTONUP"<<std::endl;
if (unpress_handler) {
(*unpress_handler)(m);
}
break;
case SDL_JOYHATMOTION:
//std::cout<<"SDL_JOYHATMOTION:"<<(int)m->jhat.hat<<" value"<<(int)m->jhat.value<<" k:"<<std::endl;
if (press_handler) {
(*press_handler)(m);
}
break;
case SDL_JOYBALLMOTION:
//std::cout<<"SDL_JOYBALLMOTION:"<<(int)m->jball.ball<<" xrel:"<<m->jball.xrel<<" yrel:"<<m->jball.yrel<<std::endl;
break;
case SDL_JOYAXISMOTION:
//std::cout<<"SDL_JOYAXISMOTION:"<<(int)m->jaxis.axis<<" value"<<m->jaxis.value<<std::endl;
break;
case SDL_MOUSEWHEEL:
if (press_handler) {
(*press_handler)(m);
}
break;
}
return 1;
}
/*int xtCallXKey(SDL_Event* m)
{
int rec_flag = 0,ret = 0;
switch(m->type){
case SDL_KEYDOWN:
//std::cout<<"xtCallXKey sym:"<<m->key.keysym.sym<<" scancode:"<<(int)m->key.keysym.scancode<<" SDLK_q:"<<SDLK_q<<std::endl;
// TODO(amdmi3): this is supposed to be executed on WM_CHAR; non-char keys should probably be filtered here
XKey.LastChar = m->key.keysym.sym;
XKey.PressFnc(m->key.keysym.sym, m->key.keysym.sym);
rec_flag = 1;
if (m->key.keysym.sym == SDLK_LALT || m->key.keysym.sym == SDLK_RALT || m->key.keysym.sym == SDLK_F10)
ret = 1;
break;
case SDL_KEYUP:
XKey.UnPressFnc(m->key.keysym.sym, m->key.keysym.sym);
rec_flag = 1;
if (m->key.keysym.sym == SDLK_LALT || m->key.keysym.sym == SDLK_RALT || m->key.keysym.sym == SDLK_F10)
ret = 1;
break;
}
if(rec_flag && XRec.flags & XRC_RECORD_MODE){
XRec.PutSysMessage(XRC_SYSTEM_MESSAGE, m);
}
return ret;
}*/
XList::XList(void)
{
ClearList();
}
XList::~XList(void)
{
}
void XList::AddElement(XListElement* p)
{
if(!fPtr){
fPtr = lPtr = p;
p -> prev = p;
p -> next = NULL;
}
else {
lPtr -> next = p;
p -> prev = lPtr;
p -> next = NULL;
lPtr = p;
fPtr -> prev = p;
}
ListSize ++;
}
void XList::RemoveElement(XListElement* p)
{
XListElement* pPtr,*nPtr;
ListSize --;
if(ListSize){
pPtr = p -> prev;
nPtr = p -> next;
pPtr -> next = nPtr;
if(nPtr) nPtr -> prev = pPtr;
if(p == fPtr) fPtr = nPtr;
if(p == lPtr) lPtr = pPtr;
lPtr -> next = NULL;
fPtr -> prev = lPtr;
}
else
ClearList();
}
void xtRegisterSysQuant(void (*qPtr)(void),int id)
{
xtAddSysObj(&XSysQuantLst,qPtr,id);
}
void xtUnRegisterSysQuant(int id)
{
xtDeleteSysObj(&XSysQuantLst,id);
}
void xtRegisterSysFinitFnc(void (*fPtr)(void),int id)
{
xtAddSysObj(&XSysFinitLst,fPtr,id);
}
void xtDeactivateSysFinitFnc(int id)
{
xtDeactivateSysObj(&XSysFinitLst,id);
}
void xtUnRegisterSysFinitFnc(int id)
{
xtDeleteSysObj(&XSysFinitLst,id);
}
void xtDeleteSysObj(XList* lstPtr,int id)
{
XSysObject* p = (XSysObject*)lstPtr -> fPtr;
while(p){
if(p -> ID == id){
lstPtr -> RemoveElement((XListElement*)p);
delete p;
return;
}
p = (XSysObject*)p -> next;
}
}
void xtDeactivateSysObj(XList* lstPtr,int id)
{
XSysObject* p = (XSysObject*)lstPtr -> fPtr;
while(p){
if(p -> ID == id)
p -> flags |= XSYS_OBJ_INACTIVE;
p = (XSysObject*)p -> next;
}
}
void xtAddSysObj(XList* lstPtr,void (*fPtr)(void),int id)
{
XSysObject* p = (XSysObject*)lstPtr -> fPtr;
while(p){
if(p -> ID == id) return;
p = (XSysObject*)p -> next;
}
p = new XSysObject;
p -> ID = id;
p -> QuantPtr = (void*)fPtr;
lstPtr -> AddElement((XListElement*)p);
}
void xtSysQuant(void)
{
XSysObject* p = (XSysObject*)XSysQuantLst.fPtr;
while(p){
(*(XFNC)(p -> QuantPtr))();
p = (XSysObject*)p -> next;
}
}
void xtSysFinit(void)
{
int i,sz = XSysFinitLst.ListSize;
XSysObject* p = (XSysObject*)XSysFinitLst.lPtr;
for(i = 0; i < sz; i ++){
if(!(p -> flags & XSYS_OBJ_INACTIVE))
(*(XFNC)(p -> QuantPtr))();
p = (XSysObject*)p -> prev;
}
XRec.Close();
}
/*int xtIsActive(void)
{
// return (WAIT_OBJECT_0 == WaitForSingleObject(hXActiveWndEvent,0)) ? 1 : 0;
};*/
/*int xtNeedExit()
{
// return (WAIT_OBJECT_0 == WaitForSingleObject(hXNeedExitEvent, 0)) ? 1 : 0;
};*/
void xtSetExit()
{
std::cout<<"Exit!"<<std::endl;
SDL_Quit();
exit(0);
// ResetEvent(hXActiveWndEvent);
// SetEvent(hXNeedExitEvent);
};
extern int Pause;
int xtDispatchMessage(SDL_Event* msg)
{
int ret = 0;
xtMsgHandlerObject* p = XSysHandlerLst.first();
while(p){
(*p -> Handler)(msg);
p = p -> next;
}
ret += xtCallXKey(msg);
switch(msg -> type){
case SDL_QUIT:
xtSetExit();
break;
case SDL_WINDOWEVENT:
switch (msg->window.event) {
case SDL_WINDOWEVENT_SHOWN:
//Pause = 0;
SDL_LockAudioDevice(1);
SDL_PauseAudioDevice(1, 0);
SDL_UnlockAudioDevice(1);
std::cout<<"window show"<<std::endl;
break;
case SDL_WINDOWEVENT_HIDDEN:
//Pause = 1;
SDL_LockAudioDevice(1);
SDL_PauseAudioDevice(1, 1);
SDL_UnlockAudioDevice(1);
std::cout<<"window hidden"<<std::endl;
break;
case SDL_WINDOWEVENT_RESTORED:
//Pause = 0;
SDL_LockAudioDevice(1);
SDL_PauseAudioDevice(1, 0);
SDL_UnlockAudioDevice(1);
std::cout<<"window restored"<<std::endl;
break;
case SDL_WINDOWEVENT_FOCUS_LOST:
//Pause = 1;
SDL_LockAudioDevice(1);
SDL_PauseAudioDevice(1, 1);
SDL_UnlockAudioDevice(1);
std::cout<<"window focus lost"<<std::endl;
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
//Pause = 0;
SDL_LockAudioDevice(1);
SDL_PauseAudioDevice(1, 0);
SDL_UnlockAudioDevice(1);
std::cout<<"window focus gained"<<std::endl;
break;
}
break;
case SDL_USEREVENT:
switch (msg->user.code) {
case CursorAnimationEvent:
doCursorAnimation();
}
break;
}
return ret;
}
void xtClearMessageQueue(void)
{
SDL_Event event;
while(SDL_PollEvent(&event)) {
//std::cout<<"event "<<event.type<<std::endl;
if(XRec.CheckMessage(event.type)) {
xtDispatchMessage(&event);
// if(!xtDispatchMessage(&event))
// DispatchMessage(&event);
} else {
XMsgBuf -> put(&event);
}
}
}
void xtProcessMessageBuffer(void)
{
SDL_Event event;
while(XMsgBuf -> get(&event)) {
if(!(XRec.flags & XRC_PLAY_MODE) || XRec.CheckMessage(event.type)){
xtDispatchMessage(&event);
// if(!xtDispatchMessage(&event))
// DispatchMessage(&event);
}
}
}
xtMsgHandlerObject::xtMsgHandlerObject(void (*p)(SDL_Event*),int id)
{
list = NULL;
ID = id;
Handler = p;
}
void xtRegisterSysMsgFnc(void (*fPtr)(SDL_Event*),int id)
{
xtMsgHandlerObject* p = new xtMsgHandlerObject(fPtr,id);
XSysHandlerLst.append(p);
}
void win32_break(char* error,char* msg)
{
std::cout<<"--------------------------------\n";
std::cout<<error<<"\n";
std::cout<<msg<<"\n";
std::cout<<"--------------------------------\n";
}
void* xtGet_hInstance(void)
{
return XAppHinst;
}
void* xtGet_hWnd(void)
{
return XGR_hWnd;
}
void xtSet_hWnd(void* hWnd)
{
XGR_hWnd = hWnd;
}
void xtSysQuantDisable(int v)
{
xtSysQuantDisabled = v;
}
void set_key_handlers(void (*pH)(SDL_Event*),void (*upH)(SDL_Event*)) {
press_handler = pH;
unpress_handler = upH;
}