summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/GNUmakefile14
-rw-r--r--src/common/Makefile14
-rw-r--r--src/common/core.c179
-rw-r--r--src/common/core.h12
-rw-r--r--src/common/db.c501
-rw-r--r--src/common/db.h47
-rw-r--r--src/common/grfio.c953
-rw-r--r--src/common/grfio.h16
-rw-r--r--src/common/lock.c37
-rw-r--r--src/common/lock.h8
-rw-r--r--src/common/malloc.c44
-rw-r--r--src/common/malloc.h25
-rw-r--r--src/common/mmo.h333
-rw-r--r--src/common/nullpo.c90
-rw-r--r--src/common/nullpo.h222
-rw-r--r--src/common/showmsg.c73
-rw-r--r--src/common/showmsg.h50
-rw-r--r--src/common/socket.c595
-rw-r--r--src/common/socket.h104
-rw-r--r--src/common/timer.c319
-rw-r--r--src/common/timer.h45
-rw-r--r--src/common/utils.c108
-rw-r--r--src/common/utils.h33
-rw-r--r--src/common/version.h27
24 files changed, 3849 insertions, 0 deletions
diff --git a/src/common/GNUmakefile b/src/common/GNUmakefile
new file mode 100644
index 000000000..b15d4d481
--- /dev/null
+++ b/src/common/GNUmakefile
@@ -0,0 +1,14 @@
+txt sql all: core.o socket.o timer.o grfio.o db.o lock.o nullpo.o malloc.o showmsg.o
+
+core.o: core.c core.h showmsg.h
+socket.o: socket.c socket.h mmo.h showmsg.h
+timer.o: timer.c timer.h showmsg.h
+grfio.o: grfio.c grfio.h showmsg.h
+db.o: db.c db.h showmsg.h
+lock.o: lock.h showmsg.h
+nullpo.o: nullpo.c nullpo.h showmsg.h
+malloc.o: malloc.c malloc.h showmsg.h
+showmsg.o: showmsg.c showmsg.h
+
+clean:
+ rm -f *.o
diff --git a/src/common/Makefile b/src/common/Makefile
new file mode 100644
index 000000000..b15d4d481
--- /dev/null
+++ b/src/common/Makefile
@@ -0,0 +1,14 @@
+txt sql all: core.o socket.o timer.o grfio.o db.o lock.o nullpo.o malloc.o showmsg.o
+
+core.o: core.c core.h showmsg.h
+socket.o: socket.c socket.h mmo.h showmsg.h
+timer.o: timer.c timer.h showmsg.h
+grfio.o: grfio.c grfio.h showmsg.h
+db.o: db.c db.h showmsg.h
+lock.o: lock.h showmsg.h
+nullpo.o: nullpo.c nullpo.h showmsg.h
+malloc.o: malloc.c malloc.h showmsg.h
+showmsg.o: showmsg.c showmsg.h
+
+clean:
+ rm -f *.o
diff --git a/src/common/core.c b/src/common/core.c
new file mode 100644
index 000000000..167b38efb
--- /dev/null
+++ b/src/common/core.c
@@ -0,0 +1,179 @@
+// $Id: core.c,v 1.1.1.1 2004/09/10 17:44:49 MagicalTux Exp $
+// original : core.c 2003/02/26 18:03:12 Rev 1.7
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+#include <signal.h>
+#include <string.h>
+
+#include "core.h"
+#include "socket.h"
+#include "timer.h"
+#include "version.h"
+#include "showmsg.h"
+
+#ifdef MEMWATCH
+#include "memwatch.h"
+#endif
+
+static void (*term_func)(void)=NULL;
+
+/*======================================
+ * CORE : Set function
+ *--------------------------------------
+ */
+void set_termfunc(void (*termfunc)(void))
+{
+ term_func = termfunc;
+}
+
+/*======================================
+ * CORE : Signal Sub Function
+ *--------------------------------------
+ */
+
+static void sig_proc(int sn)
+{
+ int i;
+ switch(sn){
+ case SIGINT:
+ case SIGTERM:
+ if(term_func)
+ term_func();
+ for(i=0;i<fd_max;i++){
+ if(!session[i])
+ continue;
+ close(i);
+ }
+ exit(0);
+ break;
+ }
+}
+
+int get_svn_revision(char *svnentry) { // Warning: minor syntax checking
+ char line[1024];
+ int rev = 0;
+ FILE *fp;
+ if ((fp = fopen(svnentry, "r")) == NULL) {
+ return 0;
+ } else {
+ while (fgets(line,1023,fp)) if (strstr(line,"revision=")) break;
+ fclose(fp);
+ if (sscanf(line," %*[^\"]\"%d%*[^\n]",&rev)==1)
+ return rev;
+ else
+ return 0;
+ }
+// return 0;
+}
+
+/*======================================
+ * CORE : Display title
+ *--------------------------------------
+ */
+
+static void display_title(void)
+{
+ int revision;
+ // for help with the console colors look here:
+ // http://www.edoceo.com/liberum/?doc=printf-with-color
+ // some code explanation (used here):
+ // \033[2J : clear screen and go up/left (0, 0 position)
+ // \033[K : clear line from actual position to end of the line
+ // \033[0m : reset color parameter
+ // \033[1m : use bold for font
+ printf("\033[2J"); // clear screen and go up/left (0, 0 position in text)
+ printf("\033[37;44m (=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=)\033[K\033[0m\n"); // white writing (37) on blue background (44), \033[K clean until end of file
+ printf("\033[0;44m (\033[1;33m (c)2004 eAthena Development Team presents \033[0;44m)\033[K\033[0m\n"); // yellow writing (33)
+ printf("\033[0;44m (\033[1m ______ __ __ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char
+ printf("\033[0;44m (\033[1m /\\ _ \\/\\ \\__/\\ \\ v%2d.%02d.%02d \033[0;44m)\033[K\033[0m\n", ATHENA_MAJOR_VERSION, ATHENA_MINOR_VERSION, ATHENA_REVISION); // 1: bold char, 0: normal char
+ printf("\033[0;44m (\033[1m __\\ \\ \\_\\ \\ \\ ,_\\ \\ \\___ __ ___ __ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char
+ printf("\033[0;44m (\033[1m /'__`\\ \\ __ \\ \\ \\/\\ \\ _ `\\ /'__`\\/' _ `\\ /'__`\\ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char
+ printf("\033[0;44m (\033[1m /\\ __/\\ \\ \\/\\ \\ \\ \\_\\ \\ \\ \\ \\/\\ __//\\ \\/\\ \\/\\ \\_\\.\\_ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char
+ printf("\033[0;44m (\033[1m \\ \\____\\\\ \\_\\ \\_\\ \\__\\\\ \\_\\ \\_\\ \\____\\ \\_\\ \\_\\ \\__/.\\_\\ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char
+ printf("\033[0;44m (\033[1m \\/____/ \\/_/\\/_/\\/__/ \\/_/\\/_/\\/____/\\/_/\\/_/\\/__/\\/_/ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char
+ printf("\033[0;44m (\033[1m _ _ _ _ _ _ _ _ _ _ _ _ _ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char
+ printf("\033[0;44m (\033[1m / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char
+ printf("\033[0;44m (\033[1m ( e | n | g | l | i | s | h ) ( A | t | h | e | n | a ) \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char
+ printf("\033[0;44m (\033[1m \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char
+ printf("\033[0;44m (\033[1m \033[0;44m)\033[K\033[0m\n"); // yellow writing (33)
+ printf("\033[0;44m (\033[1;33m Advanced Fusion Maps (c) 2003-2004 The Fusion Project \033[0;44m)\033[K\033[0m\n"); // yellow writing (33)
+ printf("\033[37;44m (=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=)\033[K\033[0m\n\n"); // reset color
+
+ if ((revision = get_svn_revision(".svn\\entries"))>0) {
+ snprintf(tmp_output,sizeof(tmp_output),"SVN Revision: %d.\n",revision);
+ ShowInfo(tmp_output);
+ }
+}
+
+// Added by Gabuzomeu
+//
+// This is an implementation of signal() using sigaction() for portability.
+// (sigaction() is POSIX; signal() is not.) Taken from Stevens' _Advanced
+// Programming in the UNIX Environment_.
+//
+#ifndef SIGPIPE
+#define SIGPIPE SIGINT
+#endif
+
+#ifndef POSIX
+#define compat_signal(signo, func) signal(signo, func)
+#else
+sigfunc *compat_signal(int signo, sigfunc *func)
+{
+ struct sigaction sact, oact;
+
+ sact.sa_handler = func;
+ sigemptyset(&sact.sa_mask);
+ sact.sa_flags = 0;
+#ifdef SA_INTERRUPT
+ sact.sa_flags |= SA_INTERRUPT; /* SunOS */
+#endif
+
+ if (sigaction(signo, &sact, &oact) < 0)
+ return (SIG_ERR);
+
+ return (oact.sa_handler);
+}
+#endif
+
+
+/*======================================
+ * CORE : MAINROUTINE
+ *--------------------------------------
+ */
+
+int runflag = 1;
+
+int main(int argc,char **argv)
+{
+ int next;
+
+ Net_Init();
+ do_socket();
+
+ compat_signal(SIGPIPE,SIG_IGN);
+ compat_signal(SIGTERM,sig_proc);
+ compat_signal(SIGINT,sig_proc);
+
+ // Signal to create coredumps by system when necessary (crash)
+ compat_signal(SIGSEGV, SIG_DFL);
+#ifndef _WIN32
+ compat_signal(SIGBUS, SIG_DFL);
+ compat_signal(SIGTRAP, SIG_DFL);
+#endif
+ compat_signal(SIGILL, SIG_DFL);
+
+ display_title();
+
+ do_init(argc,argv);
+ while(runflag){
+ next=do_timer(gettick_nocache());
+ do_sendrecv(next);
+ do_parsepacket();
+ }
+ return 0;
+}
diff --git a/src/common/core.h b/src/common/core.h
new file mode 100644
index 000000000..bc2be02c2
--- /dev/null
+++ b/src/common/core.h
@@ -0,0 +1,12 @@
+// original : core.h 2003/03/14 11:55:25 Rev 1.4
+
+#ifndef _CORE_H_
+#define _CORE_H_
+
+extern int runflag;
+
+int do_init(int,char**);
+
+void set_termfunc(void (*termfunc)(void));
+
+#endif // _CORE_H_
diff --git a/src/common/db.c b/src/common/db.c
new file mode 100644
index 000000000..58f0ea4f7
--- /dev/null
+++ b/src/common/db.c
@@ -0,0 +1,501 @@
+// $Id: db.c,v 1.2 2004/09/23 14:43:06 MouseJstr Exp $
+// #define MALLOC_DBN
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "db.h"
+#include "mmo.h"
+#include "utils.h"
+
+#ifdef MEMWATCH
+#include "memwatch.h"
+#endif
+
+#define ROOT_SIZE 4096
+#ifdef MALLOC_DBN
+static struct dbn *dbn_root[512], *dbn_free;
+static int dbn_root_rest=0,dbn_root_num=0;
+
+static void * malloc_dbn(void)
+{
+ struct dbn* ret;
+
+ if(dbn_free==NULL){
+ if(dbn_root_rest<=0){
+ CREATE(dbn_root[dbn_root_num], struct dbn, ROOT_SIZE);
+
+ dbn_root_rest=ROOT_SIZE;
+ dbn_root_num++;
+ }
+ return &(dbn_root[dbn_root_num-1][--dbn_root_rest]);
+ }
+ ret=dbn_free;
+ dbn_free = dbn_free->parent;
+ return ret;
+}
+
+static void free_dbn(struct dbn* add_dbn)
+{
+ add_dbn->parent = dbn_free;
+ dbn_free = add_dbn;
+}
+#endif
+
+static int strdb_cmp(struct dbt* table,void* a,void* b)
+{
+ if(table->maxlen)
+ return strncmp(a,b,table->maxlen);
+ return strcmp(a,b);
+}
+
+static unsigned int strdb_hash(struct dbt* table,void* a)
+{
+ int i;
+ unsigned int h;
+ unsigned char *p=a;
+
+ i=table->maxlen;
+ if(i==0) i=0x7fffffff;
+ for(h=0;*p && --i>=0;){
+ h=(h*33 + *p++) ^ (h>>24);
+ }
+ return h;
+}
+
+struct dbt* strdb_init(int maxlen)
+{
+ int i;
+ struct dbt* table;
+
+ CREATE(table, struct dbt, 1);
+
+ table->cmp=strdb_cmp;
+ table->hash=strdb_hash;
+ table->maxlen=maxlen;
+ for(i=0;i<HASH_SIZE;i++)
+ table->ht[i]=NULL;
+ return table;
+}
+
+static int numdb_cmp(struct dbt* table,void* a,void* b)
+{
+ int ia,ib;
+
+ ia=(int)a;
+ ib=(int)b;
+
+ if((ia^ib) & 0x80000000)
+ return ia<0 ? -1 : 1;
+
+ return ia-ib;
+}
+
+static unsigned int numdb_hash(struct dbt* table,void* a)
+{
+ return (unsigned int)a;
+}
+
+struct dbt* numdb_init(void)
+{
+ int i;
+ struct dbt* table;
+
+ CREATE(table, struct dbt, 1);
+
+ table->cmp=numdb_cmp;
+ table->hash=numdb_hash;
+ table->maxlen=sizeof(int);
+ for(i=0;i<HASH_SIZE;i++)
+ table->ht[i]=NULL;
+ return table;
+}
+
+void* db_search(struct dbt *table,void* key)
+{
+ struct dbn *p;
+
+ for(p=table->ht[table->hash(table,key) % HASH_SIZE];p;){
+ int c=table->cmp(table,key,p->key);
+ if(c==0)
+ return p->data;
+ if(c<0)
+ p=p->left;
+ else
+ p=p->right;
+ }
+ return NULL;
+}
+
+void * db_search2(struct dbt *table, const char *key)
+{
+ int i,sp;
+ struct dbn *p,*pn,*stack[64];
+ int slen = strlen(key);
+
+ for(i=0;i<HASH_SIZE;i++){
+ if((p=table->ht[i])==NULL)
+ continue;
+ sp=0;
+ while(1){
+ if (strnicmp(key, p->key, slen) == 0)
+ return p->data;
+ if((pn=p->left)!=NULL){
+ if(p->right){
+ stack[sp++]=p->right;
+ }
+ p=pn;
+ } else {
+ if(p->right){
+ p=p->right;
+ } else {
+ if(sp==0)
+ break;
+ p=stack[--sp];
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static void db_rotate_left(struct dbn *p,struct dbn **root)
+{
+ struct dbn * y = p->right;
+ p->right = y->left;
+ if (y->left !=0)
+ y->left->parent = p;
+ y->parent = p->parent;
+
+ if (p == *root)
+ *root = y;
+ else if (p == p->parent->left)
+ p->parent->left = y;
+ else
+ p->parent->right = y;
+ y->left = p;
+ p->parent = y;
+}
+
+static void db_rotate_right(struct dbn *p,struct dbn **root)
+{
+ struct dbn * y = p->left;
+ p->left = y->right;
+ if (y->right != 0)
+ y->right->parent = p;
+ y->parent = p->parent;
+
+ if (p == *root)
+ *root = y;
+ else if (p == p->parent->right)
+ p->parent->right = y;
+ else
+ p->parent->left = y;
+ y->right = p;
+ p->parent = y;
+}
+
+static void db_rebalance(struct dbn *p,struct dbn **root)
+{
+ p->color = RED;
+ while(p!=*root && p->parent->color==RED){ // rootは必ず黒で親は赤いので親の親は必ず存在する
+ if (p->parent == p->parent->parent->left) {
+ struct dbn *y = p->parent->parent->right;
+ if (y && y->color == RED) {
+ p->parent->color = BLACK;
+ y->color = BLACK;
+ p->parent->parent->color = RED;
+ p = p->parent->parent;
+ } else {
+ if (p == p->parent->right) {
+ p = p->parent;
+ db_rotate_left(p, root);
+ }
+ p->parent->color = BLACK;
+ p->parent->parent->color = RED;
+ db_rotate_right(p->parent->parent, root);
+ }
+ } else {
+ struct dbn* y = p->parent->parent->left;
+ if (y && y->color == RED) {
+ p->parent->color = BLACK;
+ y->color = BLACK;
+ p->parent->parent->color = RED;
+ p = p->parent->parent;
+ } else {
+ if (p == p->parent->left) {
+ p = p->parent;
+ db_rotate_right(p, root);
+ }
+ p->parent->color = BLACK;
+ p->parent->parent->color = RED;
+ db_rotate_left(p->parent->parent, root);
+ }
+ }
+ }
+ (*root)->color=BLACK;
+}
+
+static void db_rebalance_erase(struct dbn *z,struct dbn **root)
+{
+ struct dbn *y = z, *x = NULL, *x_parent = NULL;
+
+ if (y->left == NULL)
+ x = y->right;
+ else if (y->right == NULL)
+ x = y->left;
+ else {
+ y = y->right;
+ while (y->left != NULL)
+ y = y->left;
+ x = y->right;
+ }
+ if (y != z) { // 左右が両方埋まっていた時 yをzの位置に持ってきてzを浮かせる
+ z->left->parent = y;
+ y->left = z->left;
+ if (y != z->right) {
+ x_parent = y->parent;
+ if (x) x->parent = y->parent;
+ y->parent->left = x;
+ y->right = z->right;
+ z->right->parent = y;
+ } else
+ x_parent = y;
+ if (*root == z)
+ *root = y;
+ else if (z->parent->left == z)
+ z->parent->left = y;
+ else
+ z->parent->right = y;
+ y->parent = z->parent;
+ { int tmp=y->color; y->color=z->color; z->color=tmp; }
+ y = z;
+ } else { // どちらか空いていた場合 xをzの位置に持ってきてzを浮かせる
+ x_parent = y->parent;
+ if (x) x->parent = y->parent;
+ if (*root == z)
+ *root = x;
+ else if (z->parent->left == z)
+ z->parent->left = x;
+ else
+ z->parent->right = x;
+ }
+ // ここまで色の移動の除いて通常の2分木と同じ
+ if (y->color != RED) { // 赤が消える分には影響無し
+ while (x != *root && (x == NULL || x->color == BLACK))
+ if (x == x_parent->left) {
+ struct dbn* w = x_parent->right;
+ if (w->color == RED) {
+ w->color = BLACK;
+ x_parent->color = RED;
+ db_rotate_left(x_parent, root);
+ w = x_parent->right;
+ }
+ if ((w->left == NULL ||
+ w->left->color == BLACK) &&
+ (w->right == NULL ||
+ w->right->color == BLACK)) {
+ w->color = RED;
+ x = x_parent;
+ x_parent = x_parent->parent;
+ } else {
+ if (w->right == NULL ||
+ w->right->color == BLACK) {
+ if (w->left) w->left->color = BLACK;
+ w->color = RED;
+ db_rotate_right(w, root);
+ w = x_parent->right;
+ }
+ w->color = x_parent->color;
+ x_parent->color = BLACK;
+ if (w->right) w->right->color = BLACK;
+ db_rotate_left(x_parent, root);
+ break;
+ }
+ } else { // same as above, with right <-> left.
+ struct dbn* w = x_parent->left;
+ if (w->color == RED) {
+ w->color = BLACK;
+ x_parent->color = RED;
+ db_rotate_right(x_parent, root);
+ w = x_parent->left;
+ }
+ if ((w->right == NULL ||
+ w->right->color == BLACK) &&
+ (w->left == NULL ||
+ w->left->color == BLACK)) {
+ w->color = RED;
+ x = x_parent;
+ x_parent = x_parent->parent;
+ } else {
+ if (w->left == NULL ||
+ w->left->color == BLACK) {
+ if (w->right) w->right->color = BLACK;
+ w->color = RED;
+ db_rotate_left(w, root);
+ w = x_parent->left;
+ }
+ w->color = x_parent->color;
+ x_parent->color = BLACK;
+ if (w->left) w->left->color = BLACK;
+ db_rotate_right(x_parent, root);
+ break;
+ }
+ }
+ if (x) x->color = BLACK;
+ }
+}
+
+struct dbn* db_insert(struct dbt *table,void* key,void* data)
+{
+ struct dbn *p,*priv;
+ int c,hash;
+
+ hash = table->hash(table,key) % HASH_SIZE;
+ for(c=0,priv=NULL ,p = table->ht[hash];p;){
+ c=table->cmp(table,key,p->key);
+ if(c==0){ // replace
+ if (table->release)
+ table->release(p, 3);
+ p->data=data;
+ p->key=key;
+ return p;
+ }
+ priv=p;
+ if(c<0){
+ p=p->left;
+ } else {
+ p=p->right;
+ }
+ }
+#ifdef MALLOC_DBN
+ p=malloc_dbn();
+#else
+ CREATE(p, struct dbn, 1);
+#endif
+ if(p==NULL){
+ printf("out of memory : db_insert\n");
+ return NULL;
+ }
+ p->parent= NULL;
+ p->left = NULL;
+ p->right = NULL;
+ p->key = key;
+ p->data = data;
+ p->color = RED;
+ if(c==0){ // hash entry is empty
+ table->ht[hash] = p;
+ p->color = BLACK;
+ } else {
+ if(c<0){ // left node
+ priv->left = p;
+ p->parent=priv;
+ } else { // right node
+ priv->right = p;
+ p->parent=priv;
+ }
+ if(priv->color==RED){ // must rebalance
+ db_rebalance(p,&table->ht[hash]);
+ }
+ }
+ return p;
+}
+
+void* db_erase(struct dbt *table,void* key)
+{
+ void *data;
+ struct dbn *p;
+ int c,hash;
+
+ hash = table->hash(table,key) % HASH_SIZE;
+ for(c=0,p = table->ht[hash];p;){
+ c=table->cmp(table,key,p->key);
+ if(c==0)
+ break;
+ if(c<0)
+ p=p->left;
+ else
+ p=p->right;
+ }
+ if(!p)
+ return NULL;
+ data=p->data;
+ db_rebalance_erase(p,&table->ht[hash]);
+#ifdef MALLOC_DBN
+ free_dbn(p);
+#else
+ free(p);
+#endif
+ return data;
+}
+
+void db_foreach(struct dbt *table,int (*func)(void*,void*,va_list),...)
+{
+ int i,sp;
+ // red-black treeなので64個stackがあれば2^32個ノードまで大丈夫
+ struct dbn *p,*pn,*stack[64];
+ va_list ap;
+
+ va_start(ap,func);
+ for(i=0;i<HASH_SIZE;i++){
+ if((p=table->ht[i])==NULL)
+ continue;
+ sp=0;
+ while(1){
+ func(p->key,p->data,ap);
+ if((pn=p->left)!=NULL){
+ if(p->right){
+ stack[sp++]=p->right;
+ }
+ p=pn;
+ } else {
+ if(p->right){
+ p=p->right;
+ } else {
+ if(sp==0)
+ break;
+ p=stack[--sp];
+ }
+ }
+ }
+ }
+ va_end(ap);
+}
+
+void db_final(struct dbt *table,int (*func)(void*,void*,va_list),...)
+{
+ int i,sp;
+ struct dbn *p,*pn,*stack[64];
+ va_list ap;
+
+ va_start(ap,func);
+ for(i=0;i<HASH_SIZE;i++){
+ if((p=table->ht[i])==NULL)
+ continue;
+ sp=0;
+ while(1){
+ if(func)
+ func(p->key,p->data,ap);
+ if((pn=p->left)!=NULL){
+ if(p->right){
+ stack[sp++]=p->right;
+ }
+ } else {
+ if(p->right){
+ pn=p->right;
+ } else {
+ if(sp==0)
+ break;
+ pn=stack[--sp];
+ }
+ }
+#ifdef MALLOC_DBN
+ free_dbn(p);
+#else
+ free(p);
+#endif
+ p=pn;
+ }
+ }
+ free(table);
+ va_end(ap);
+}
diff --git a/src/common/db.h b/src/common/db.h
new file mode 100644
index 000000000..ea9aceab0
--- /dev/null
+++ b/src/common/db.h
@@ -0,0 +1,47 @@
+#ifndef _DB_H_
+#define _DB_H_
+
+#include <stdarg.h>
+
+#define HASH_SIZE (256+27)
+
+#define RED 0
+#define BLACK 1
+
+struct dbn {
+ struct dbn *parent,*left,*right;
+ int color;
+ void *key;
+ void *data;
+};
+
+struct dbt {
+ int (*cmp)(struct dbt*,void*,void*);
+ unsigned int (*hash)(struct dbt*,void*);
+ // which 1 - key, 2 - data, 3 - both
+ void (*release)(struct dbn*,int which);
+ int maxlen;
+ struct dbn *ht[HASH_SIZE];
+};
+
+#define strdb_search(t,k) db_search((t),(void*)(k))
+#define strdb_insert(t,k,d) db_insert((t),(void*)(k),(void*)(d))
+#define strdb_erase(t,k) db_erase ((t),(void*)(k))
+#define strdb_foreach db_foreach
+#define strdb_final db_final
+#define numdb_search(t,k) db_search((t),(void*)(k))
+#define numdb_insert(t,k,d) db_insert((t),(void*)(k),(void*)(d))
+#define numdb_erase(t,k) db_erase ((t),(void*)(k))
+#define numdb_foreach db_foreach
+#define numdb_final db_final
+
+struct dbt* strdb_init(int maxlen);
+struct dbt* numdb_init(void);
+void* db_search(struct dbt *table,void* key);
+void* db_search2(struct dbt *table, const char *key); // [MouseJstr]
+struct dbn* db_insert(struct dbt *table,void* key,void* data);
+void* db_erase(struct dbt *table,void* key);
+void db_foreach(struct dbt*,int(*)(void*,void*,va_list),...);
+void db_final(struct dbt*,int(*)(void*,void*,va_list),...);
+
+#endif
diff --git a/src/common/grfio.c b/src/common/grfio.c
new file mode 100644
index 000000000..ff01b6e76
--- /dev/null
+++ b/src/common/grfio.c
@@ -0,0 +1,953 @@
+/*********************************************************************
+ *
+ * Ragnarok Online Emulator : grfio.c -- grf file I/O Module
+ *--------------------------------------------------------------------
+ * special need library : zlib
+ *********************************************************************
+ * $Id: grfio.c,v 1.2 2004/09/29 17:31:49 kalaspuff Exp $
+ *
+ * 2002/12/18... the original edition
+ * 2003/01/23 ... Code correction
+ * 2003/02/01 ... An addition and decryption processing are improved for LocalFile and two or more GRF(s) check processing.
+ * 2003/02/02 ... Even if there is no grf it does not stop -- as -- correction
+ * 2003/02/02... grf reading specification can be added later -- as -- correction (grfio_add function addition)
+ * 2003/02 / 03... at the time of grfio_resourcecheck processing the entry addition processing method -- correction
+ * 2003/02/05... change of the processing in grfio_init
+ * 2003/02/23... a local file check -- GRFIO_LOCAL -- switch (Defoe -- Function Off)
+ * 2003/10/21 ... The data of alpha client was read.
+ * 2003/11/10 ... Ready new grf format.
+ * 2003/11/11 ... version check fix & bug fix
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/stat.h>
+
+#include <zlib.h>
+
+#include "utils.h"
+#include "grfio.h"
+#include "mmo.h"
+
+#ifdef MEMWATCH
+#include "memwatch.h"
+#endif
+
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+
+static char data_file[1024] = ""; // "data.grf";
+static char sdata_file[1024] = ""; // "sdata.grf";
+static char adata_file[1024] = ""; // "adata.grf";
+static char data_dir[1024] = ""; // "../";
+
+// accessor to data_file,adata_file,sdata_file
+char *grfio_setdatafile(const char *str){ strcpy(data_file,str); return data_file; }
+char *grfio_setadatafile(const char *str){ strcpy(adata_file,str); return adata_file; }
+char *grfio_setsdatafile(const char *str){ strcpy(sdata_file,str); return sdata_file; }
+
+//----------------------------
+// file entry table struct
+//----------------------------
+typedef struct {
+ int srclen; // compressed size
+ int srclen_aligned; //
+ int declen; // original size
+ int srcpos;
+ short next;
+ char cycle;
+ char type;
+ char fn[128-4*5]; // file name
+ char gentry; // read grf file select
+} FILELIST;
+//gentry ... 0 : It acquires from a local file.
+// It acquires from the resource file of 1>=:gentry_table[gentry-1].
+// 1<=: Check a local file.
+// If it is, after re-setting to 0, it acquires from a local file.
+// If there is nothing, mark reversal will be carried out, and it will re-set, and will acquire from a resource file as well as 1>=.
+
+//Since char defines *FILELIST.gentry, the maximum which can be added by grfio_add becomes by 127 pieces.
+
+#define GENTRY_LIMIT 127
+#define FILELIST_LIMIT 32768 // temporary maximum, and a theory top maximum are 2G.
+
+static FILELIST *filelist;
+static int filelist_entrys;
+static int filelist_maxentry;
+
+static char **gentry_table;
+static int gentry_entrys;
+static int gentry_maxentry;
+
+//----------------------------
+// file list hash table
+//----------------------------
+static int filelist_hash[256];
+
+//----------------------------
+// grf decode data table
+//----------------------------
+static unsigned char BitMaskTable[8] = {
+ 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
+};
+
+static char BitSwapTable1[64] = {
+ 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
+ 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
+ 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
+ 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
+};
+static char BitSwapTable2[64] = {
+ 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,
+ 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,
+ 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,
+ 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25
+};
+static char BitSwapTable3[32] = {
+ 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
+ 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25
+};
+
+static unsigned char NibbleData[4][64]={
+ {
+ 0xef, 0x03, 0x41, 0xfd, 0xd8, 0x74, 0x1e, 0x47, 0x26, 0xef, 0xfb, 0x22, 0xb3, 0xd8, 0x84, 0x1e,
+ 0x39, 0xac, 0xa7, 0x60, 0x62, 0xc1, 0xcd, 0xba, 0x5c, 0x96, 0x90, 0x59, 0x05, 0x3b, 0x7a, 0x85,
+ 0x40, 0xfd, 0x1e, 0xc8, 0xe7, 0x8a, 0x8b, 0x21, 0xda, 0x43, 0x64, 0x9f, 0x2d, 0x14, 0xb1, 0x72,
+ 0xf5, 0x5b, 0xc8, 0xb6, 0x9c, 0x37, 0x76, 0xec, 0x39, 0xa0, 0xa3, 0x05, 0x52, 0x6e, 0x0f, 0xd9,
+ }, {
+ 0xa7, 0xdd, 0x0d, 0x78, 0x9e, 0x0b, 0xe3, 0x95, 0x60, 0x36, 0x36, 0x4f, 0xf9, 0x60, 0x5a, 0xa3,
+ 0x11, 0x24, 0xd2, 0x87, 0xc8, 0x52, 0x75, 0xec, 0xbb, 0xc1, 0x4c, 0xba, 0x24, 0xfe, 0x8f, 0x19,
+ 0xda, 0x13, 0x66, 0xaf, 0x49, 0xd0, 0x90, 0x06, 0x8c, 0x6a, 0xfb, 0x91, 0x37, 0x8d, 0x0d, 0x78,
+ 0xbf, 0x49, 0x11, 0xf4, 0x23, 0xe5, 0xce, 0x3b, 0x55, 0xbc, 0xa2, 0x57, 0xe8, 0x22, 0x74, 0xce,
+ }, {
+ 0x2c, 0xea, 0xc1, 0xbf, 0x4a, 0x24, 0x1f, 0xc2, 0x79, 0x47, 0xa2, 0x7c, 0xb6, 0xd9, 0x68, 0x15,
+ 0x80, 0x56, 0x5d, 0x01, 0x33, 0xfd, 0xf4, 0xae, 0xde, 0x30, 0x07, 0x9b, 0xe5, 0x83, 0x9b, 0x68,
+ 0x49, 0xb4, 0x2e, 0x83, 0x1f, 0xc2, 0xb5, 0x7c, 0xa2, 0x19, 0xd8, 0xe5, 0x7c, 0x2f, 0x83, 0xda,
+ 0xf7, 0x6b, 0x90, 0xfe, 0xc4, 0x01, 0x5a, 0x97, 0x61, 0xa6, 0x3d, 0x40, 0x0b, 0x58, 0xe6, 0x3d,
+ }, {
+ 0x4d, 0xd1, 0xb2, 0x0f, 0x28, 0xbd, 0xe4, 0x78, 0xf6, 0x4a, 0x0f, 0x93, 0x8b, 0x17, 0xd1, 0xa4,
+ 0x3a, 0xec, 0xc9, 0x35, 0x93, 0x56, 0x7e, 0xcb, 0x55, 0x20, 0xa0, 0xfe, 0x6c, 0x89, 0x17, 0x62,
+ 0x17, 0x62, 0x4b, 0xb1, 0xb4, 0xde, 0xd1, 0x87, 0xc9, 0x14, 0x3c, 0x4a, 0x7e, 0xa8, 0xe2, 0x7d,
+ 0xa0, 0x9f, 0xf6, 0x5c, 0x6a, 0x09, 0x8d, 0xf0, 0x0f, 0xe3, 0x53, 0x25, 0x95, 0x36, 0x28, 0xcb,
+ }
+};
+/*-----------------
+ * long data get
+ */
+static unsigned int getlong(unsigned char *p)
+{
+ return *p+p[1]*256+(p[2]+p[3]*256)*65536;
+}
+
+/*==========================================
+ * Grf data decode : Subs
+ *------------------------------------------
+ */
+static void NibbleSwap(BYTE *Src, int len)
+{
+ for(;0<len;len--,Src++) {
+ *Src = (*Src>>4) | (*Src<<4);
+ }
+}
+
+static void BitConvert(BYTE *Src,char *BitSwapTable)
+{
+ int lop,prm;
+ BYTE tmp[8];
+ *(DWORD*)tmp=*(DWORD*)(tmp+4)=0;
+ for(lop=0;lop!=64;lop++) {
+ prm = BitSwapTable[lop]-1;
+ if (Src[(prm >> 3) & 7] & BitMaskTable[prm & 7]) {
+ tmp[(lop >> 3) & 7] |= BitMaskTable[lop & 7];
+ }
+ }
+ *(DWORD*)Src = *(DWORD*)tmp;
+ *(DWORD*)(Src+4) = *(DWORD*)(tmp+4);
+}
+
+static void BitConvert4(BYTE *Src)
+{
+ int lop,prm;
+ BYTE tmp[8];
+ tmp[0] = ((Src[7]<<5) | (Src[4]>>3)) & 0x3f; // ..0 vutsr
+ tmp[1] = ((Src[4]<<1) | (Src[5]>>7)) & 0x3f; // ..srqpo n
+ tmp[2] = ((Src[4]<<5) | (Src[5]>>3)) & 0x3f; // ..o nmlkj
+ tmp[3] = ((Src[5]<<1) | (Src[6]>>7)) & 0x3f; // ..kjihg f
+ tmp[4] = ((Src[5]<<5) | (Src[6]>>3)) & 0x3f; // ..g fedcb
+ tmp[5] = ((Src[6]<<1) | (Src[7]>>7)) & 0x3f; // ..cba98 7
+ tmp[6] = ((Src[6]<<5) | (Src[7]>>3)) & 0x3f; // ..8 76543
+ tmp[7] = ((Src[7]<<1) | (Src[4]>>7)) & 0x3f; // ..43210 v
+
+ for(lop=0;lop!=4;lop++) {
+ tmp[lop] = (NibbleData[lop][tmp[lop*2]] & 0xf0)
+ | (NibbleData[lop][tmp[lop*2+1]] & 0x0f);
+ }
+
+ *(DWORD*)(tmp+4)=0;
+ for(lop=0;lop!=32;lop++) {
+ prm = BitSwapTable3[lop]-1;
+ if (tmp[prm >> 3] & BitMaskTable[prm & 7]) {
+ tmp[(lop >> 3) + 4] |= BitMaskTable[lop & 7];
+ }
+ }
+ *(DWORD*)Src ^= *(DWORD*)(tmp+4);
+}
+
+static void decode_des_etc(BYTE *buf,int len,int type,int cycle)
+{
+ int lop,cnt=0;
+ if(cycle<3) cycle=3;
+ else if(cycle<5) cycle++;
+ else if(cycle<7) cycle+=9;
+ else cycle+=15;
+
+ for(lop=0;lop*8<len;lop++,buf+=8) {
+ if(lop<20 || (type==0 && lop%cycle==0)){ // des
+ BitConvert(buf,BitSwapTable1);
+ BitConvert4(buf);
+ BitConvert(buf,BitSwapTable2);
+ } else {
+ if(cnt==7 && type==0){
+ int a;
+ BYTE tmp[8];
+ *(DWORD*)tmp = *(DWORD*)buf;
+ *(DWORD*)(tmp+4) = *(DWORD*)(buf+4);
+ cnt=0;
+ buf[0]=tmp[3];
+ buf[1]=tmp[4];
+ buf[2]=tmp[6];
+ buf[3]=tmp[0];
+ buf[4]=tmp[1];
+ buf[5]=tmp[2];
+ buf[6]=tmp[5];
+ a=tmp[7];
+ if(a==0x00) a=0x2b;
+ else if(a==0x2b) a=0x00;
+ else if(a==0x01) a=0x68;
+ else if(a==0x68) a=0x01;
+ else if(a==0x48) a=0x77;
+ else if(a==0x77) a=0x48;
+ else if(a==0x60) a=0xff;
+ else if(a==0xff) a=0x60;
+ else if(a==0x6c) a=0x80;
+ else if(a==0x80) a=0x6c;
+ else if(a==0xb9) a=0xc0;
+ else if(a==0xc0) a=0xb9;
+ else if(a==0xeb) a=0xfe;
+ else if(a==0xfe) a=0xeb;
+ buf[7]=a;
+ }
+ cnt++;
+ }
+ }
+}
+/*==========================================
+ * Grf data decode sub : zip
+ *------------------------------------------
+ */
+static int decode_zip(Bytef* dest, uLongf* destLen, const Bytef* source, uLong sourceLen)
+{
+ z_stream stream;
+ int err;
+
+ stream.next_in = (Bytef*)source;
+ stream.avail_in = (uInt)sourceLen;
+ /* Check for source > 64K on 16-bit machine: */
+ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+
+ err = inflateInit(&stream);
+ if (err != Z_OK) return err;
+
+ err = inflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ inflateEnd(&stream);
+ return err == Z_OK ? Z_BUF_ERROR : err;
+ }
+ *destLen = stream.total_out;
+
+ err = inflateEnd(&stream);
+ return err;
+}
+/***********************************************************
+ *** File List Sobroutines ***
+ ***********************************************************/
+
+/*==========================================
+ * File List : Hash make
+ *------------------------------------------
+ */
+static int filehash(unsigned char *fname)
+{
+ unsigned int hash=0;
+ while(*fname) {
+ hash = ((hash<<1)+(hash>>7)*9+tolower(*fname));
+ fname++;
+ }
+ return hash & 255;
+}
+
+/*==========================================
+ * File List : Hash initalize
+ *------------------------------------------
+ */
+static void hashinit(void)
+{
+ int lop;
+ for(lop=0;lop<256;lop++)
+ filelist_hash[lop]=-1;
+}
+
+/*==========================================
+ * File List : File find
+ *------------------------------------------
+ */
+FILELIST *filelist_find(char *fname)
+{
+ int hash;
+
+ for(hash=filelist_hash[filehash(fname)];hash>=0;hash=filelist[hash].next) {
+ if(strcmpi(filelist[hash].fn,fname)==0)
+ break;
+ }
+
+ return (hash>=0)? &filelist[hash] : NULL;
+}
+
+/*==========================================
+ * File List : Filelist add
+ *------------------------------------------
+ */
+#define FILELIST_ADDS 1024 // number increment of file lists `
+
+static FILELIST* filelist_add(FILELIST *entry)
+{
+ int hash;
+
+ if (filelist_entrys>=FILELIST_LIMIT) {
+ printf("filelist limit : filelist_add\n");
+ exit(1);
+ }
+
+ if (filelist_entrys>=filelist_maxentry) {
+ FILELIST *new_filelist = (FILELIST*)realloc(
+ (void*)filelist, (filelist_maxentry+FILELIST_ADDS)*sizeof(FILELIST) );
+ if (new_filelist != NULL) {
+ filelist = new_filelist;
+ memset(filelist + filelist_maxentry, '\0',
+ FILELIST_ADDS * sizeof(FILELIST));
+ filelist_maxentry += FILELIST_ADDS;
+ } else {
+ printf("out of memory : filelist_add\n");
+ exit(1);
+ }
+ }
+
+ memcpy( &filelist[filelist_entrys], entry, sizeof(FILELIST) );
+
+ hash = filehash(entry->fn);
+ filelist[filelist_entrys].next = filelist_hash[hash];
+ filelist_hash[hash] = filelist_entrys;
+
+ filelist_entrys++;
+
+ return &filelist[filelist_entrys-1];
+}
+
+static FILELIST* filelist_modify(FILELIST *entry)
+{
+ FILELIST *fentry;
+ if ((fentry=filelist_find(entry->fn))!=NULL) {
+ int tmp = fentry->next;
+ memcpy( fentry, entry, sizeof(FILELIST) );
+ fentry->next = tmp;
+ } else {
+ fentry = filelist_add(entry);
+ }
+ return fentry;
+}
+
+/*==========================================
+ * File List : filelist size adjust
+ *------------------------------------------
+ */
+static void filelist_adjust(void)
+{
+ if (filelist!=NULL) {
+ if (filelist_maxentry>filelist_entrys) {
+ FILELIST *new_filelist = (FILELIST*)realloc(
+ (void*)filelist,filelist_entrys*sizeof(FILELIST) );
+ if (new_filelist != NULL) {
+ filelist = new_filelist;
+ filelist_maxentry = filelist_entrys;
+ } else {
+ printf("out of memory : filelist\n");
+ exit(1);
+ }
+ }
+ }
+}
+
+/***********************************************************
+ *** Grfio Sobroutines ***
+ ***********************************************************/
+/*==========================================
+ * Grfio : Resnametable replace
+ *------------------------------------------
+ */
+char* grfio_resnametable(char* fname, char *lfname)
+{
+ FILE *fp;
+ char *p;
+ char w1[256],w2[256],restable[256],line[512];
+
+ sprintf(restable,"%sdata\\resnametable.txt",data_dir);
+
+ for(p=&restable[0];*p!=0;p++) if (*p=='\\') *p = '/';
+
+ fp = fopen(restable,"rb");
+ if(fp==NULL) {
+ printf("%s not found (grfio_resnametable)\n",restable);
+ return NULL; // 1:not found error
+ }
+
+ while(fgets(line,508,fp)){
+ if((sscanf(line,"%[^#]#%[^#]#",w1,w2)==2) && (sscanf(fname,"%*5s%s",lfname)==1) && (!strcmpi(w1,lfname))){
+ sprintf(lfname,"data\\%s",w2);
+ fclose(fp);
+ return lfname;
+ }
+ }
+ fclose(fp);
+ return fname;
+
+}
+
+/*==========================================
+ * Grfio : Resource file size get
+ *------------------------------------------
+ */
+int grfio_size(char *fname)
+{
+ FILELIST *entry;
+
+ entry = filelist_find(fname);
+
+ if (entry==NULL || entry->gentry<0) { // LocalFileCheck
+ char lfname[256],rname[256],*p;
+ FILELIST lentry;
+ struct stat st;
+
+ if(strcmp(data_dir, "") != 0) {
+ //printf("%s\t",fname);
+ sprintf(rname,"%s",grfio_resnametable(fname,lfname));
+ //printf("%s\n",rname);
+ sprintf(lfname,"%s%s",data_dir,rname);
+ //printf("%s\n",lfname);
+ }
+
+ for(p=&lfname[0];*p!=0;p++) if (*p=='\\') *p = '/'; // * At the time of Unix
+
+ if (stat(lfname,&st)==0) {
+ strncpy(lentry.fn, fname, sizeof(lentry.fn)-1 );
+ lentry.declen = st.st_size;
+ lentry.gentry = 0; // 0:LocalFile
+ entry = filelist_modify(&lentry);
+ } else if (entry==NULL) {
+ printf("%s not found (grfio_size)\n", fname);
+ //exit(1);
+ return -1;
+ }
+ }
+ return entry->declen;
+}
+
+/*==========================================
+ * Grfio : Resource file read & size get
+ *------------------------------------------
+ */
+void* grfio_reads(char *fname, int *size)
+{
+ FILE *in = NULL;
+ unsigned char *buf=NULL,*buf2=NULL;
+ char *gfname;
+ FILELIST *entry;
+
+ entry = filelist_find(fname);
+
+ if (entry==NULL || entry->gentry<=0) { // LocalFileCheck
+ char lfname[256],rname[256],*p;
+ FILELIST lentry;
+
+ strncpy(lfname,fname,255);
+ sprintf(rname,"%s",grfio_resnametable(fname,lfname));
+ sprintf(lfname,"%s%s",data_dir,rname);
+ //printf("%s\n",lfname);
+
+ for(p=&lfname[0];*p!=0;p++) if (*p=='\\') *p = '/'; // * At the time of Unix
+
+ in = fopen(lfname,"rb");
+ if(in!=NULL) {
+ if (entry!=NULL && entry->gentry==0) {
+ lentry.declen=entry->declen;
+ } else {
+ fseek(in,0,2); // SEEK_END
+ lentry.declen = ftell(in);
+ }
+ fseek(in,0,0); // SEEK_SET
+ buf2 = calloc(lentry.declen+1024, 1);
+ if (buf2==NULL) {
+ printf("file read memory allocate error : declen\n");
+ goto errret;
+ }
+ fread(buf2,1,lentry.declen,in);
+ fclose(in); in = NULL;
+ strncpy( lentry.fn, fname, sizeof(lentry.fn)-1 );
+ lentry.gentry = 0; // 0:LocalFile
+ entry = filelist_modify(&lentry);
+ } else {
+ if (entry!=NULL && entry->gentry<0) {
+ entry->gentry = -entry->gentry; // local file checked
+ } else {
+ printf("%s not found (grfio_reads)\n", fname);
+ //goto errret;
+ free(buf2);
+ return NULL;
+ }
+ }
+ }
+ if (entry!=NULL && entry->gentry>0) { // Archive[GRF] File Read
+ buf = calloc(entry->srclen_aligned+1024, 1);
+ if (buf==NULL) {
+ printf("file read memory allocate error : srclen_aligned\n");
+ goto errret;
+ }
+ gfname = gentry_table[entry->gentry-1];
+ in = fopen(gfname,"rb");
+ if(in==NULL) {
+ printf("%s not found (grfio_reads)\n",gfname);
+ //goto errret;
+ free(buf);
+ return NULL;
+ }
+ fseek(in,entry->srcpos,0);
+ fread(buf,1,entry->srclen_aligned,in);
+ fclose(in);
+ buf2=calloc(entry->declen+1024, 1);
+ if (buf2==NULL) {
+ printf("file decode memory allocate error\n");
+ goto errret;
+ }
+ if(entry->type==1 || entry->type==3 || entry->type==5) {
+ uLongf len;
+ if (entry->cycle>=0) {
+ decode_des_etc(buf,entry->srclen_aligned,entry->cycle==0,entry->cycle);
+ }
+ len=entry->declen;
+ decode_zip(buf2,&len,buf,entry->srclen);
+ if(len!=entry->declen) {
+ printf("decode_zip size miss match err: %d != %d\n",(int)len,entry->declen);
+ goto errret;
+ }
+ } else {
+ memcpy(buf2,buf,entry->declen);
+ }
+ free(buf);
+ }
+ if (size!=NULL && entry!=NULL)
+ *size = entry->declen;
+ return buf2;
+errret:
+ if (buf!=NULL) free(buf);
+ if (buf2!=NULL) free(buf2);
+ if (in!=NULL) fclose(in);
+ exit(1); //return NULL;
+}
+
+/*==========================================
+ * Grfio : Resource file read
+ *------------------------------------------
+ */
+void* grfio_read(char *fname)
+{
+ return grfio_reads(fname,NULL);
+}
+
+/*==========================================
+ * Resource filename decode
+ *------------------------------------------
+ */
+static unsigned char * decode_filename(unsigned char *buf,int len)
+{
+ int lop;
+ for(lop=0;lop<len;lop+=8) {
+ NibbleSwap(&buf[lop],8);
+ BitConvert(&buf[lop],BitSwapTable1);
+ BitConvert4(&buf[lop]);
+ BitConvert(&buf[lop],BitSwapTable2);
+ }
+ return buf;
+}
+
+/*==========================================
+ * Grfio : Entry table read
+ *------------------------------------------
+ */
+static int grfio_entryread(char *gfname,int gentry)
+{
+ FILE *fp;
+ int grf_size,list_size;
+ unsigned char grf_header[0x2e];
+ int lop,entry,entrys,ofs,grf_version;
+ unsigned char *fname;
+ unsigned char *grf_filelist;
+
+ fp = fopen(gfname,"rb");
+ if(fp==NULL) {
+ printf("%s not found (grfio_entryread)\n",gfname);
+ return 1; // 1:not found error
+ }
+
+ fseek(fp,0,2); // SEEK_END
+ grf_size = ftell(fp);
+ fseek(fp,0,0); // SEEK_SET
+ fread(grf_header,1,0x2e,fp);
+ if(strcmp(grf_header,"Master of Magic") || fseek(fp,getlong(grf_header+0x1e),1)){ // SEEK_CUR
+ fclose(fp);
+ printf("%s read error\n",gfname);
+ return 2; // 2:file format error
+ }
+
+ grf_version = getlong(grf_header+0x2a) >> 8;
+
+ if (grf_version==0x01) { //****** Grf version 01xx ******
+ list_size = grf_size-ftell(fp);
+ grf_filelist = calloc(list_size, 1);
+ if(grf_filelist==NULL){
+ fclose(fp);
+ printf("out of memory : grf_filelist\n");
+ return 3; // 3:memory alloc error
+ }
+ fread(grf_filelist,1,list_size,fp);
+ fclose(fp);
+
+ entrys = getlong(grf_header+0x26) - getlong(grf_header+0x22) - 7;
+
+ // Get an entry
+ for(entry=0,ofs=0;entry<entrys;entry++){
+ int ofs2,srclen,srccount,type;
+ char *period_ptr;
+ FILELIST aentry;
+
+ ofs2 = ofs+getlong(grf_filelist+ofs)+4;
+ type = grf_filelist[ofs2+12];
+ if( type!=0 ){ // Directory Index ... skip
+ fname = decode_filename(grf_filelist+ofs+6,grf_filelist[ofs]-6);
+ if(strlen(fname)>sizeof(aentry.fn)-1){
+ printf("file name too long : %s\n",fname);
+ free(grf_filelist);
+ exit(1);
+ }
+ srclen=0;
+ if((period_ptr=strrchr(fname,'.'))!=NULL){
+ for(lop=0;lop<4;lop++) {
+ if(strcmpi(period_ptr,".gnd\0.gat\0.act\0.str"+lop*5)==0)
+ break;
+ }
+ srclen=getlong(grf_filelist+ofs2)-getlong(grf_filelist+ofs2+8)-715;
+ if(lop==4) {
+ for(lop=10,srccount=1;srclen>=lop;lop=lop*10,srccount++);
+ } else {
+ srccount=0;
+ }
+ } else {
+ srccount=0;
+ }
+
+ aentry.srclen = srclen;
+ aentry.srclen_aligned = getlong(grf_filelist+ofs2+4)-37579;
+ aentry.declen = getlong(grf_filelist+ofs2+8);
+ aentry.srcpos = getlong(grf_filelist+ofs2+13)+0x2e;
+ aentry.cycle = srccount;
+ aentry.type = type;
+ strncpy(aentry.fn,fname,sizeof(aentry.fn)-1);
+#ifdef GRFIO_LOCAL
+ aentry.gentry = -(gentry+1); // As Flag for making it a negative number carrying out the first time LocalFileCheck
+#else
+ aentry.gentry = gentry+1; // With no first time LocalFileCheck
+#endif
+ filelist_modify(&aentry);
+ }
+ ofs = ofs2 + 17;
+ }
+ free(grf_filelist);
+
+ } else if (grf_version==0x02) { //****** Grf version 02xx ******
+ unsigned char eheader[8];
+ unsigned char *rBuf;
+ uLongf rSize,eSize;
+
+ fread(eheader,1,8,fp);
+ rSize = getlong(eheader); // Read Size
+ eSize = getlong(eheader+4); // Extend Size
+
+ if (rSize > grf_size-ftell(fp)) {
+ fclose(fp);
+ printf("Illegal data format : grf compress entry size\n");
+ return 4;
+ }
+
+ rBuf = calloc( rSize , 1); // Get a Read Size
+ if (rBuf==NULL) {
+ fclose(fp);
+ printf("out of memory : grf compress entry table buffer\n");
+ return 3;
+ }
+ grf_filelist = calloc( eSize , 1); // Get a Extend Size
+ if (grf_filelist==NULL) {
+ free(rBuf);
+ fclose(fp);
+ printf("out of memory : grf extract entry table buffer\n");
+ return 3;
+ }
+ fread(rBuf,1,rSize,fp);
+ fclose(fp);
+ decode_zip(grf_filelist,&eSize,rBuf,rSize); // Decode function
+ list_size = eSize;
+ free(rBuf);
+
+ entrys = getlong(grf_header+0x26) - 7;
+
+ // Get an entry
+ for(entry=0,ofs=0;entry<entrys;entry++){
+ int ofs2,srclen,srccount,type;
+ FILELIST aentry;
+
+ fname = grf_filelist+ofs;
+ if (strlen(fname)>sizeof(aentry.fn)-1) {
+ printf("grf : file name too long : %s\n",fname);
+ free(grf_filelist);
+ exit(1);
+ }
+ ofs2 = ofs+strlen(grf_filelist+ofs)+1;
+ type = grf_filelist[ofs2+12];
+ if(type==1 || type==3 || type==5) {
+ srclen=getlong(grf_filelist+ofs2);
+ if (grf_filelist[ofs2+12]==3) {
+ for(lop=10,srccount=1;srclen>=lop;lop=lop*10,srccount++);
+ } else if (grf_filelist[ofs2+12]==5) {
+ srccount = 0;
+ } else { // if (grf_filelist[ofs2+12]==1) {
+ srccount = -1;
+ }
+
+ aentry.srclen = srclen;
+ aentry.srclen_aligned = getlong(grf_filelist+ofs2+4);
+ aentry.declen = getlong(grf_filelist+ofs2+8);
+ aentry.srcpos = getlong(grf_filelist+ofs2+13)+0x2e;
+ aentry.cycle = srccount;
+ aentry.type = type;
+ strncpy(aentry.fn,fname,sizeof(aentry.fn)-1);
+#ifdef GRFIO_LOCAL
+ aentry.gentry = -(gentry+1); // As Flag for making it a negative number carrying out the first time LocalFileCheck
+#else
+ aentry.gentry = gentry+1; // With no first time LocalFileCheck
+#endif
+ filelist_modify(&aentry);
+ }
+ ofs = ofs2 + 17;
+ }
+ free(grf_filelist);
+
+ } else { //****** Grf Other version ******
+ fclose(fp);
+ printf("not support grf versions : %04x\n",getlong(grf_header+0x2a));
+ return 4;
+ }
+
+ filelist_adjust(); // Unnecessary area release of filelist
+
+ return 0; // 0:no error
+}
+
+/*==========================================
+ * Grfio : Resource file check
+ *------------------------------------------
+ */
+static void grfio_resourcecheck()
+{
+ int size;
+ unsigned char *buf,*ptr;
+ char w1[256],w2[256],src[256],dst[256];
+ FILELIST *entry;
+
+ buf=grfio_reads("data\\resnametable.txt",&size);
+ buf[size] = 0;
+
+ for(ptr=buf;ptr-buf<size;) {
+ if(sscanf(ptr,"%[^#]#%[^#]#",w1,w2)==2){
+ if(strstr(w2,"bmp")){
+ sprintf(src,"data\\texture\\%s",w1);
+ sprintf(dst,"data\\texture\\%s",w2);
+ } else {
+ sprintf(src,"data\\%s",w1);
+ sprintf(dst,"data\\%s",w2);
+ }
+ entry = filelist_find(dst);
+ if (entry!=NULL) {
+ FILELIST fentry;
+ memcpy( &fentry, entry, sizeof(FILELIST) );
+ strncpy( fentry.fn ,src, sizeof(fentry.fn)-1 );
+ filelist_modify(&fentry);
+ } else {
+ //printf("file not found in data.grf : %s < %s\n",dst,src);
+ }
+ }
+ ptr = strchr(ptr,'\n'); // Next line
+ if (!ptr) break;
+ ptr++;
+ }
+ free(buf);
+ filelist_adjust(); // Unnecessary area release of filelist
+}
+
+/*==========================================
+ * Grfio : Resource add
+ *------------------------------------------
+ */
+#define GENTRY_ADDS 16 // The number increment of gentry_table entries
+
+int grfio_add(char *fname)
+{
+ int len,result;
+ char *buf;
+
+ if (gentry_entrys>=GENTRY_LIMIT) {
+ printf("gentrys limit : grfio_add\n");
+ exit(1);
+ }
+
+ printf("%s file reading...\n",fname);
+
+ if (gentry_entrys>=gentry_maxentry) {
+ char **new_gentry = (char**)realloc(
+ (void*)gentry_table,(gentry_maxentry+GENTRY_ADDS)*sizeof(char*) );
+ if (new_gentry!=NULL) {
+ int lop;
+ gentry_table = new_gentry;
+ gentry_maxentry += GENTRY_ADDS;
+ for(lop=gentry_entrys;lop<gentry_maxentry;lop++)
+ gentry_table[lop] = NULL;
+ } else {
+ printf("out of memory : grfio_add\n");
+ exit(1);
+ }
+ }
+ len = strlen( fname );
+ buf = calloc(len+1, 1);
+ if (buf==NULL) {
+ printf("out of memory : gentry\n");
+ exit(1);
+ }
+ strcpy( buf, fname );
+ gentry_table[gentry_entrys++] = buf;
+
+ result = grfio_entryread(fname,gentry_entrys-1);
+
+ if (result==0) {
+ // Resource check
+ grfio_resourcecheck();
+ }
+
+ return result;
+}
+
+/*==========================================
+ * Grfio : Finalize
+ *------------------------------------------
+ */
+void grfio_final(void)
+{
+ int lop;
+
+ if (filelist!=NULL) free(filelist);
+ filelist = NULL;
+ filelist_entrys = filelist_maxentry = 0;
+
+ if (gentry_table!=NULL) {
+ for(lop=0;lop<gentry_entrys;lop++) {
+ if (gentry_table[lop]!=NULL) {
+ free(gentry_table[lop]);
+ }
+ }
+ free(gentry_table);
+ }
+ gentry_table = NULL;
+ gentry_entrys = gentry_maxentry = 0;
+}
+
+/*==========================================
+ * Grfio : Initialize
+ *------------------------------------------
+ */
+void grfio_init(char *fname)
+{
+ FILE *data_conf;
+ char line[1024], w1[1024], w2[1024];
+ int result = 0, result2 = 0, result3 = 0, result4 = 0;
+
+ data_conf = fopen(fname, "r");
+
+ // It will read, if there is grf-files.txt.
+ if (data_conf) {
+ while(fgets(line, 1020, data_conf)) {
+ if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2) {
+ if(strcmp(w1, "data") == 0)
+ strcpy(data_file, w2);
+ else if(strcmp(w1, "sdata") == 0)
+ strcpy(sdata_file, w2);
+ else if(strcmp(w1, "adata") == 0)
+ strcpy(adata_file, w2);
+ else if(strcmp(w1,"data_dir") == 0)
+ strcpy(data_dir, w2);
+ }
+ }
+
+ fclose(data_conf);
+ printf("read %s done\n",fname);
+ } // end of reading grf-files.txt
+
+ hashinit(); // hash table initialization
+
+ filelist = NULL; filelist_entrys = filelist_maxentry = 0;
+ gentry_table = NULL; gentry_entrys = gentry_maxentry = 0;
+ atexit(grfio_final); // End processing definition
+
+ // Entry table reading
+
+ if (strcmp(data_file, "") != 0) // If data directive exists in grf-files.txt (i.e. data_file is not equal to "")
+ result = grfio_add(data_file); // Primary data file
+
+ if (strcmp(sdata_file, "") != 0) // If sdata directive exists in grf-files.txt (i.e. sdata_file is not equal to "")
+ result2 = grfio_add(sdata_file); // Sakray data file
+
+ if (strcmp(adata_file, "") != 0) // If data directive exists in grf-files.txt (i.e. adata_file is not equal to "")
+ result3 = grfio_add(adata_file); // Alpha version data file
+
+ if (strcmp(data_dir, "") == 0) // Id data_dir doesn't exist
+ result4 = 1; // Data directory
+
+ if (result != 0 && result2 != 0 && result3 != 0 && result4 != 0) {
+ printf("not grf file readed exit!!\n");
+ exit(1); // It ends, if a resource cannot read one.
+ }
+}
diff --git a/src/common/grfio.h b/src/common/grfio.h
new file mode 100644
index 000000000..53b9da8d4
--- /dev/null
+++ b/src/common/grfio.h
@@ -0,0 +1,16 @@
+// $Id: grfio.h,v 1.1.1.1 2004/09/10 17:44:49 MagicalTux Exp $
+#ifndef _GRFIO_H_
+#define _GRFIO_H_
+
+void grfio_init(char*); // GRFIO Initialize
+int grfio_add(char*); // GRFIO Resource file add
+void* grfio_read(char*); // GRFIO data file read
+void* grfio_reads(char*,int*); // GRFIO data file read & size get
+int grfio_size(char*); // GRFIO data file size get
+
+// Accessor to GRF filenames
+char *grfio_setdatafile(const char *str);
+char *grfio_setadatafile(const char *str);
+char *grfio_setsdatafile(const char *str);
+
+#endif // _GRFIO_H_
diff --git a/src/common/lock.c b/src/common/lock.c
new file mode 100644
index 000000000..9a2205bf4
--- /dev/null
+++ b/src/common/lock.c
@@ -0,0 +1,37 @@
+
+#include <stdio.h>
+#include "lock.h"
+
+// 書き込みファイルの保護処理
+// (書き込みが終わるまで、旧ファイルを保管しておく)
+
+// 新しいファイルの書き込み開始
+FILE* lock_fopen(const char* filename,int *info) {
+ char newfile[512];
+ FILE *fp;
+ int no = 0;
+
+ // 安全なファイル名を得る(手抜き)
+ do {
+ sprintf(newfile,"%s_%04d.tmp",filename,++no);
+ } while((fp = fopen(newfile,"r")) && (fclose(fp), no<9999) );
+ *info = no;
+ return fopen(newfile,"w");
+}
+
+// 旧ファイルを削除&新ファイルをリネーム
+int lock_fclose(FILE *fp,const char* filename,int *info) {
+ int ret = 0;
+ char newfile[512];
+ if(fp != NULL) {
+ ret = fclose(fp);
+ sprintf(newfile,"%s_%04d.tmp",filename,*info);
+ remove(filename);
+ // このタイミングで落ちると最悪。
+ rename(newfile,filename);
+ return ret;
+ } else {
+ return 1;
+ }
+}
+
diff --git a/src/common/lock.h b/src/common/lock.h
new file mode 100644
index 000000000..795bf8860
--- /dev/null
+++ b/src/common/lock.h
@@ -0,0 +1,8 @@
+#ifndef _LOCK_H_
+#define _LOCK_H_
+
+FILE* lock_fopen(const char* filename,int *info);
+int lock_fclose(FILE *fp,const char* filename,int *info);
+
+#endif
+
diff --git a/src/common/malloc.c b/src/common/malloc.c
new file mode 100644
index 000000000..eda9bc218
--- /dev/null
+++ b/src/common/malloc.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "malloc.h"
+
+void* aMalloc_( size_t size, const char *file, int line, const char *func )
+{
+ void *ret;
+
+// printf("%s:%d: in func %s: malloc %d\n",file,line,func,size);
+ ret=malloc(size);
+ if(ret==NULL){
+ printf("%s:%d: in func %s: malloc error out of memory!\n",file,line,func);
+ exit(1);
+
+ }
+ return ret;
+}
+void* aCalloc_( size_t num, size_t size, const char *file, int line, const char *func )
+{
+ void *ret;
+
+// printf("%s:%d: in func %s: calloc %d %d\n",file,line,func,num,size);
+ ret=calloc(num,size);
+ if(ret==NULL){
+ printf("%s:%d: in func %s: calloc error out of memory!\n",file,line,func);
+ exit(1);
+
+ }
+ return ret;
+}
+
+void* aRealloc_( void *p, size_t size, const char *file, int line, const char *func )
+{
+ void *ret;
+
+// printf("%s:%d: in func %s: realloc %p %d\n",file,line,func,p,size);
+ ret=realloc(p,size);
+ if(ret==NULL){
+ printf("%s:%d: in func %s: realloc error out of memory!\n",file,line,func);
+ exit(1);
+
+ }
+ return ret;
+}
diff --git a/src/common/malloc.h b/src/common/malloc.h
new file mode 100644
index 000000000..3733a5e55
--- /dev/null
+++ b/src/common/malloc.h
@@ -0,0 +1,25 @@
+#ifndef _MALLOC_H_
+#define _MALLOC_H_
+
+#include <stdlib.h>
+
+#if __STDC_VERSION__ < 199901L
+# if __GNUC__ >= 2
+# define __func__ __FUNCTION__
+# else
+# define __func__ ""
+# endif
+#endif
+
+#define ALC_MARK __FILE__, __LINE__, __func__
+
+void* aMalloc_( size_t size, const char *file, int line, const char *func );
+void* aCalloc_( size_t num, size_t size, const char *file, int line, const char *func );
+void* aRealloc_( void *p, size_t size, const char *file, int line, const char *func );
+
+#define aMalloc(n) aMalloc_(n,ALC_MARK)
+#define aCalloc(m,n) aCalloc_(m,n,ALC_MARK)
+#define aRealloc(p,n) aRealloc_(p,n,ALC_MARK)
+
+
+#endif
diff --git a/src/common/mmo.h b/src/common/mmo.h
new file mode 100644
index 000000000..5483e30d2
--- /dev/null
+++ b/src/common/mmo.h
@@ -0,0 +1,333 @@
+// $Id: mmo.h,v 1.3 2004/09/25 20:12:25 PoW Exp $
+// Original : mmo.h 2003/03/14 12:07:02 Rev.1.7
+
+#ifndef _MMO_H_
+#define _MMO_H_
+
+#include <time.h>
+#include "utils.h" // _WIN32
+
+#ifdef CYGWIN
+// txtやlogなどの書き出すファイルの改行コード
+#define RETCODE "\r\n" // (CR/LF:Windows系)
+#else
+#define RETCODE "\n" // (LF:Unix系)
+#endif
+
+#define RET RETCODE
+
+#define FIFOSIZE_SERVERLINK 128*1024
+
+// set to 0 to not check IP of player between each server.
+// set to another value if you want to check (1)
+#define CMP_AUTHFIFO_IP 1
+
+#define CMP_AUTHFIFO_LOGIN2 1
+
+#define MAX_MAP_PER_SERVER 512
+#define MAX_INVENTORY 100
+#define MAX_AMOUNT 30000
+#define MAX_ZENY 1000000000 // 1G zeny
+#define MAX_CART 100
+#define MAX_SKILL 450
+#define GLOBAL_REG_NUM 96
+#define ACCOUNT_REG_NUM 16
+#define ACCOUNT_REG2_NUM 16
+#define DEFAULT_WALK_SPEED 150
+#define MIN_WALK_SPEED 0
+#define MAX_WALK_SPEED 1000
+#define MAX_STORAGE 300
+#define MAX_GUILD_STORAGE 1000
+#define MAX_PARTY 12
+#define MAX_GUILD 36 // increased max guild members to accomodate for +2 increase for extension levels [Valaris] (removed) [PoW]
+#define MAX_GUILDPOSITION 20 // increased max guild positions to accomodate for all members [Valaris] (removed) [PoW]
+#define MAX_GUILDEXPLUSION 32
+#define MAX_GUILDALLIANCE 16
+#define MAX_GUILDSKILL 15 // increased max guild skills because of new skills [Sara-chan]
+#define MAX_GUILDCASTLE 24 // increased to include novice castles [Valaris]
+#define MAX_GUILDLEVEL 50
+
+#define MIN_HAIR_STYLE battle_config.min_hair_style
+#define MAX_HAIR_STYLE battle_config.max_hair_style
+#define MIN_HAIR_COLOR battle_config.min_hair_color
+#define MAX_HAIR_COLOR battle_config.max_hair_color
+#define MIN_CLOTH_COLOR battle_config.min_cloth_color
+#define MAX_CLOTH_COLOR battle_config.max_cloth_color
+
+// for produce
+#define MIN_ATTRIBUTE 0
+#define MAX_ATTRIBUTE 4
+#define ATTRIBUTE_NORMAL 0
+#define MIN_STAR 0
+#define MAX_STAR 3
+
+#define MIN_PORTAL_MEMO 0
+#define MAX_PORTAL_MEMO 2
+
+#define MAX_STATUS_TYPE 5
+
+#define WEDDING_RING_M 2634
+#define WEDDING_RING_F 2635
+
+#define CHAR_CONF_NAME "conf/char_athena.conf"
+
+struct item {
+ int id;
+ short nameid;
+ short amount;
+ unsigned short equip;
+ char identify;
+ char refine;
+ char attribute;
+ short card[4];
+};
+
+struct point{
+ char map[24];
+ short x,y;
+};
+
+struct skill {
+ unsigned short id,lv,flag;
+};
+
+struct global_reg {
+ char str[32];
+ int value;
+};
+
+struct s_pet {
+ int account_id;
+ int char_id;
+ int pet_id;
+ short class;
+ short level;
+ short egg_id;//pet egg id
+ short equip;//pet equip name_id
+ short intimate;//pet friendly
+ short hungry;//pet hungry
+ char name[24];
+ char rename_flag;
+ char incuvate;
+};
+
+struct mmo_charstatus {
+ int char_id;
+ int account_id;
+ int partner_id;
+
+ int base_exp,job_exp,zeny;
+
+ short class;
+ short status_point,skill_point;
+ int hp,max_hp,sp,max_sp;
+ short option,karma,manner;
+ short hair,hair_color,clothes_color;
+ int party_id,guild_id,pet_id;
+
+ short weapon,shield;
+ short head_top,head_mid,head_bottom;
+
+ char name[24];
+ unsigned char base_level,job_level;
+ short str,agi,vit,int_,dex,luk;
+ unsigned char char_num,sex;
+
+ unsigned long mapip;
+ unsigned int mapport;
+
+ struct point last_point,save_point,memo_point[10];
+ struct item inventory[MAX_INVENTORY],cart[MAX_CART];
+ struct skill skill[MAX_SKILL];
+ int global_reg_num;
+ struct global_reg global_reg[GLOBAL_REG_NUM];
+ int account_reg_num;
+ struct global_reg account_reg[ACCOUNT_REG_NUM];
+ int account_reg2_num;
+ struct global_reg account_reg2[ACCOUNT_REG2_NUM];
+
+ // Friends list vars
+ int friend_id[20];
+ char friend_name[20][24];
+};
+
+struct storage {
+ int account_id;
+ short storage_status;
+ short storage_amount;
+ struct item storage[MAX_STORAGE];
+};
+
+struct guild_storage {
+ int guild_id;
+ short storage_status;
+ short storage_amount;
+ struct item storage[MAX_GUILD_STORAGE];
+};
+
+struct map_session_data;
+
+struct gm_account {
+ int account_id;
+ int level;
+};
+
+struct party_member {
+ int account_id;
+ char name[24],map[24];
+ int leader,online,lv;
+ struct map_session_data *sd;
+};
+
+struct party {
+ int party_id;
+ char name[24];
+ int exp;
+ int item;
+ struct party_member member[MAX_PARTY];
+};
+
+struct guild_member {
+ int account_id, char_id;
+ short hair,hair_color,gender,class,lv;
+ int exp,exp_payper;
+ short online,position;
+ int rsv1,rsv2;
+ char name[24];
+ struct map_session_data *sd;
+};
+
+struct guild_position {
+ char name[24];
+ int mode;
+ int exp_mode;
+};
+
+struct guild_alliance {
+ int opposition;
+ int guild_id;
+ char name[24];
+};
+
+struct guild_explusion {
+ char name[24];
+ char mes[40];
+ char acc[40];
+ int account_id;
+ int rsv1,rsv2,rsv3;
+};
+
+struct guild_skill {
+ int id,lv;
+};
+
+struct guild {
+ int guild_id;
+ short guild_lv, connect_member, max_member, average_lv;
+ int exp,next_exp,skill_point,castle_id;
+ char name[24],master[24];
+ struct guild_member member[MAX_GUILD];
+ struct guild_position position[MAX_GUILDPOSITION];
+ char mes1[60],mes2[120];
+ int emblem_len,emblem_id;
+ char emblem_data[2048];
+ struct guild_alliance alliance[MAX_GUILDALLIANCE];
+ struct guild_explusion explusion[MAX_GUILDEXPLUSION];
+ struct guild_skill skill[MAX_GUILDSKILL];
+};
+
+struct guild_castle {
+ int castle_id;
+ char map_name[24];
+ char castle_name[24];
+ char castle_event[24];
+ int guild_id;
+ int economy;
+ int defense;
+ int triggerE;
+ int triggerD;
+ int nextTime;
+ int payTime;
+ int createTime;
+ int visibleC;
+ int visibleG0;
+ int visibleG1;
+ int visibleG2;
+ int visibleG3;
+ int visibleG4;
+ int visibleG5;
+ int visibleG6;
+ int visibleG7;
+ int Ghp0; // added Guardian HP [Valaris]
+ int Ghp1;
+ int Ghp2;
+ int Ghp3;
+ int Ghp4;
+ int Ghp5;
+ int Ghp6;
+ int Ghp7;
+ int GID0;
+ int GID1;
+ int GID2;
+ int GID3;
+ int GID4;
+ int GID5;
+ int GID6;
+ int GID7; // end addition [Valaris]
+};
+struct square {
+ int val1[5];
+ int val2[5];
+};
+
+enum {
+ GBI_EXP =1, // ギルドのEXP
+ GBI_GUILDLV =2, // ギルドのLv
+ GBI_SKILLPOINT =3, // ギルドのスキルポイント
+ GBI_SKILLLV =4, // ギルドスキルLv
+
+ GMI_POSITION =0, // メンバーの役職変更
+ GMI_EXP =1, // メンバーのEXP
+
+};
+
+enum {
+ GD_SKILLBASE=10000,
+ GD_APPROVAL=10000,
+ GD_KAFRACONTACT=10001,
+ GD_GUARDIANRESEARCH=10002,
+ GD_CHARISMA=10003,
+ GD_GUARDUP=10003,
+ GD_EXTENSION=10004,
+ GD_GLORYGUILD=10005,
+ GD_LEADERSHIP=10006,
+ GD_GLORYWOUNDS=10007,
+ GD_SOULCOLD=10008,
+ GD_HAWKEYES=10009,
+ GD_BATTLEORDER=10010,
+ GD_REGENERATION=10011,
+ GD_RESTORE=10012,
+ GD_EMERGENCYCALL=10013,
+ GD_DEVELOPMENT=10014,
+};
+
+#ifndef _WIN32
+#ifndef strcmpi
+#define strcmpi strcasecmp
+#endif
+#ifndef stricmp
+#define stricmp strcasecmp
+#endif
+#ifndef strncmpi
+#define strncmpi strncasecmp
+#endif
+#ifndef strnicmp
+#define strnicmp strncasecmp
+#endif
+#ifndef strrchr
+#define strrchr rindex
+#endif
+
+#endif
+
+#endif // _MMO_H_
diff --git a/src/common/nullpo.c b/src/common/nullpo.c
new file mode 100644
index 000000000..5fbf5fc1d
--- /dev/null
+++ b/src/common/nullpo.c
@@ -0,0 +1,90 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include "nullpo.h"
+// #include "logs.h" // 布石してみる
+
+static void nullpo_info_core(const char *file, int line, const char *func,
+ const char *fmt, va_list ap);
+
+/*======================================
+ * Nullチェック 及び 情報出力
+ *--------------------------------------
+ */
+int nullpo_chk_f(const char *file, int line, const char *func, const void *target,
+ const char *fmt, ...)
+{
+ va_list ap;
+
+ if (target != NULL)
+ return 0;
+
+ va_start(ap, fmt);
+ nullpo_info_core(file, line, func, fmt, ap);
+ va_end(ap);
+ return 1;
+}
+
+int nullpo_chk(const char *file, int line, const char *func, const void *target)
+{
+ if (target != NULL)
+ return 0;
+
+ nullpo_info_core(file, line, func, NULL, NULL);
+ return 1;
+}
+
+
+/*======================================
+ * nullpo情報出力(外部呼出し向けラッパ)
+ *--------------------------------------
+ */
+void nullpo_info_f(const char *file, int line, const char *func,
+ const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ nullpo_info_core(file, line, func, fmt, ap);
+ va_end(ap);
+}
+
+void nullpo_info(const char *file, int line, const char *func)
+{
+ nullpo_info_core(file, line, func, NULL, NULL);
+}
+
+
+/*======================================
+ * nullpo情報出力(Main)
+ *--------------------------------------
+ */
+static void nullpo_info_core(const char *file, int line, const char *func,
+ const char *fmt, va_list ap)
+{
+ if (file == NULL)
+ file = "??";
+
+ func =
+ func == NULL ? "unknown":
+ func[0] == '\0' ? "unknown":
+ func;
+
+ printf("--- nullpo info --------------------------------------------\n");
+ printf("%s:%d: in func `%s'\n", file, line, func);
+ if (fmt != NULL)
+ {
+ if (fmt[0] != '\0')
+ {
+ vprintf(fmt, ap);
+
+ // 最後に改行したか確認
+ if (fmt[strlen(fmt)-1] != '\n')
+ printf("\n");
+ }
+ }
+ printf("--- end nullpo info ----------------------------------------\n");
+
+ // ここらでnullpoログをファイルに書き出せたら
+ // まとめて提出できるなと思っていたり。
+}
diff --git a/src/common/nullpo.h b/src/common/nullpo.h
new file mode 100644
index 000000000..11283f941
--- /dev/null
+++ b/src/common/nullpo.h
@@ -0,0 +1,222 @@
+#ifndef _NULLPO_H_
+#define _NULLPO_H_
+
+
+#define NULLPO_CHECK 1
+ // 全体のスイッチを宣言しているヘッダがあれば
+ // そこに移動していただけると
+
+
+#if __STDC_VERSION__ < 199901L
+# if __GNUC__ >= 2
+# define __func__ __FUNCTION__
+# else
+# define __func__ ""
+# endif
+#endif
+
+#ifdef _WIN32
+#define __attribute__(x) /* nothing */
+#endif
+
+
+#define NLP_MARK __FILE__, __LINE__, __func__
+
+/*----------------------------------------------------------------------------
+ * Macros
+ *----------------------------------------------------------------------------
+ */
+/*======================================
+ * Nullチェック 及び 情報出力後 return
+ *・展開するとifとかreturn等が出るので
+ * 一行単体で使ってください。
+ *・nullpo_ret(x = func());
+ * のような使用法も想定しています。
+ *--------------------------------------
+ * nullpo_ret(t)
+ * 戻り値 0固定
+ * [引数]
+ * t チェック対象
+ *--------------------------------------
+ * nullpo_retv(t)
+ * 戻り値 なし
+ * [引数]
+ * t チェック対象
+ *--------------------------------------
+ * nullpo_retr(ret, t)
+ * 戻り値 指定
+ * [引数]
+ * ret return(ret);
+ * t チェック対象
+ *--------------------------------------
+ * nullpo_ret_f(t, fmt, ...)
+ * 詳細情報出力用
+ * 戻り値 0
+ * [引数]
+ * t チェック対象
+ * fmt ... vprintfに渡される
+ * 備考や関係変数の書き出しなどに
+ *--------------------------------------
+ * nullpo_retv_f(t, fmt, ...)
+ * 詳細情報出力用
+ * 戻り値 なし
+ * [引数]
+ * t チェック対象
+ * fmt ... vprintfに渡される
+ * 備考や関係変数の書き出しなどに
+ *--------------------------------------
+ * nullpo_retr_f(ret, t, fmt, ...)
+ * 詳細情報出力用
+ * 戻り値 指定
+ * [引数]
+ * ret return(ret);
+ * t チェック対象
+ * fmt ... vprintfに渡される
+ * 備考や関係変数の書き出しなどに
+ *--------------------------------------
+ */
+
+#if NULLPO_CHECK
+
+#define nullpo_ret(t) \
+ if (nullpo_chk(NLP_MARK, (void *)(t))) {return(0);}
+
+#define nullpo_retv(t) \
+ if (nullpo_chk(NLP_MARK, (void *)(t))) {return;}
+
+#define nullpo_retr(ret, t) \
+ if (nullpo_chk(NLP_MARK, (void *)(t))) {return(ret);}
+
+
+// 可変引数マクロに関する条件コンパイル
+#if __STDC_VERSION__ >= 199901L
+/* C99に対応 */
+#define nullpo_ret_f(t, fmt, ...) \
+ if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), __VA_ARGS__)) {return(0);}
+
+#define nullpo_retv_f(t, fmt, ...) \
+ if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), __VA_ARGS__)) {return;}
+
+#define nullpo_retr_f(ret, t, fmt, ...) \
+ if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), __VA_ARGS__)) {return(ret);}
+
+#elif __GNUC__ >= 2
+/* GCC用 */
+#define nullpo_ret_f(t, fmt, args...) \
+ if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), ## args)) {return(0);}
+
+#define nullpo_retv_f(t, fmt, args...) \
+ if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), ## args)) {return;}
+
+#define nullpo_retr_f(ret, t, fmt, args...) \
+ if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), ## args)) {return(ret);}
+
+#else
+
+/* その他の場合・・・ orz */
+
+#endif
+
+#else /* NULLPO_CHECK */
+/* No Nullpo check */
+
+// if((t)){;}
+// 良い方法が思いつかなかったので・・・苦肉の策です。
+// 一応ワーニングは出ないはず
+
+#define nullpo_ret(t) if((t)){;}
+#define nullpo_retv(t) if((t)){;}
+#define nullpo_retr(ret, t) if((t)){;}
+
+// 可変引数マクロに関する条件コンパイル
+#if __STDC_VERSION__ >= 199901L
+/* C99に対応 */
+#define nullpo_ret_f(t, fmt, ...) if((t)){;}
+#define nullpo_retv_f(t, fmt, ...) if((t)){;}
+#define nullpo_retr_f(ret, t, fmt, ...) if((t)){;}
+
+#elif __GNUC__ >= 2
+/* GCC用 */
+#define nullpo_ret_f(t, fmt, args...) if((t)){;}
+#define nullpo_retv_f(t, fmt, args...) if((t)){;}
+#define nullpo_retr_f(ret, t, fmt, args...) if((t)){;}
+
+#else
+/* その他の場合・・・ orz */
+#endif
+
+#endif /* NULLPO_CHECK */
+
+/*----------------------------------------------------------------------------
+ * Functions
+ *----------------------------------------------------------------------------
+ */
+/*======================================
+ * nullpo_chk
+ * Nullチェック 及び 情報出力
+ * [引数]
+ * file __FILE__
+ * line __LINE__
+ * func __func__ (関数名)
+ * これらには NLP_MARK を使うとよい
+ * target チェック対象
+ * [返り値]
+ * 0 OK
+ * 1 NULL
+ *--------------------------------------
+ */
+int nullpo_chk(const char *file, int line, const char *func, const void *target);
+
+
+/*======================================
+ * nullpo_chk_f
+ * Nullチェック 及び 詳細な情報出力
+ * [引数]
+ * file __FILE__
+ * line __LINE__
+ * func __func__ (関数名)
+ * これらには NLP_MARK を使うとよい
+ * target チェック対象
+ * fmt ... vprintfに渡される
+ * 備考や関係変数の書き出しなどに
+ * [返り値]
+ * 0 OK
+ * 1 NULL
+ *--------------------------------------
+ */
+int nullpo_chk_f(const char *file, int line, const char *func, const void *target,
+ const char *fmt, ...)
+ __attribute__((format(printf,5,6)));
+
+
+/*======================================
+ * nullpo_info
+ * nullpo情報出力
+ * [引数]
+ * file __FILE__
+ * line __LINE__
+ * func __func__ (関数名)
+ * これらには NLP_MARK を使うとよい
+ *--------------------------------------
+ */
+void nullpo_info(const char *file, int line, const char *func);
+
+
+/*======================================
+ * nullpo_info_f
+ * nullpo詳細情報出力
+ * [引数]
+ * file __FILE__
+ * line __LINE__
+ * func __func__ (関数名)
+ * これらには NLP_MARK を使うとよい
+ * fmt ... vprintfに渡される
+ * 備考や関係変数の書き出しなどに
+ *--------------------------------------
+ */
+void nullpo_info_f(const char *file, int line, const char *func,
+ const char *fmt, ...)
+ __attribute__((format(printf,4,5)));
+
+
+#endif
diff --git a/src/common/showmsg.c b/src/common/showmsg.c
new file mode 100644
index 000000000..b65181f3a
--- /dev/null
+++ b/src/common/showmsg.c
@@ -0,0 +1,73 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "showmsg.h"
+
+char tmp_output[1024] = {"\0"};
+
+int _ShowMessage(const char *string, enum msg_type flag){ // by MC Cameri
+ /*
+ _ShowMessage MUST be used instead of printf as of 10/24/2004.
+ Return: 0 = Successful, 1 = Failed.
+ */
+// int ret = 0;
+ char prefix[40];
+ char *output;
+ if (strlen(string) <= 0) {
+ ShowError("Empty string passed to ShowMessage().\n");
+ return 1;
+ }
+ switch (flag) {
+ case MSG_STATUS: //Bright Green (To inform about good things)
+ strcpy(prefix,"\033[1;32m[Status]\033[0;0m: ");
+ break;
+/* //Do we really need this now? [MC Cameri]
+ case MSG_SQL: //Bright Violet (For dumping out anything related with SQL)
+ strcpy(prefix,"\033[1;35m[SQL]\033[0;0m: ");
+ break;
+*/
+ case MSG_INFORMATION: //Bright Blue (Variable information)
+ strcpy(prefix,"\033[1;34m[Info]\033[0;0m: ");
+ break;
+ case MSG_NOTICE: //Bright White (Less than a warning)
+ strcpy(prefix,"\033[1;29m[Notice]\033[0;0m: ");
+ break;
+ case MSG_WARNING: //Bright Yellow
+ strcpy(prefix,"\033[1;33m[Warning]\033[0;0m: ");
+ break;
+ case MSG_ERROR: //Bright Red (Regular errors)
+ strcpy(prefix,"\033[1;31m[Error]\033[0;0m: ");
+ break;
+ case MSG_FATALERROR: //Bright Red (Fatal errors, abort(); if possible)
+ strcpy(prefix,"\033[1;31m[Fatal Error]\033[0;0m: ");
+ break;
+ default:
+ ShowError("In function _ShowMessage() -> Invalid flag passed.\n");
+ return 1;
+ }
+ output = (char*)malloc(sizeof(char)*(strlen(prefix)+strlen(string))+1);
+ if (output == NULL) {
+ return 1;
+// abort(); // Kill server?
+ }
+ strcpy(output,prefix);
+ strcat(output,string);
+ printf(output);
+ fflush(stdout);
+/*
+ if ((core_config.debug_output_level > -1) && (flag >= core_config.debug_output_level)) {
+ FILE *fp;
+ fp=fopen(OUTPUT_MESSAGES_LOG,"a");
+ if (fp == NULL) {
+ printf("\033[1;31m[Error]\033[0;0m: Could not open \033[1;29m%s\033[0;0m, file not found.\n",OUTPUT_MESSAGES_LOG);
+ fflush(stdout);
+ return;
+ }
+ StripColor(output);
+ strcpy(output,"\r");
+ fwrite(output,strlen(output),1,fp);
+ fclose(fp);
+ }
+*/
+ return 0;
+}
diff --git a/src/common/showmsg.h b/src/common/showmsg.h
new file mode 100644
index 000000000..03ffe310b
--- /dev/null
+++ b/src/common/showmsg.h
@@ -0,0 +1,50 @@
+#ifndef _SHOWMSG_H_
+#define _SHOWMSG_H_
+
+extern char tmp_output[1024];
+
+enum msg_type {MSG_STATUS,/* MSG_SQL, */MSG_INFORMATION,MSG_NOTICE,MSG_WARNING,MSG_ERROR,MSG_FATALERROR};
+
+extern int _ShowMessage(const char *string, enum msg_type flag);
+
+/* MSG_XX */
+ #define ShowMsg(string,flag) _ShowMessage(string,flag)
+// #define DisplayMsg(string,flag) _ShowMessage(string,flag)
+// #define ShowMessage(string,flag) _ShowMessage(string,flag)
+
+/* MSG_STATUS */
+ #define ShowStatus(string) _ShowMessage(string,MSG_STATUS)
+// #define DisplayStatus(string) _ShowMessage(string,MSG_STATUS)
+
+/* MSG_SQL*/
+// #define ShowSQL(string) _ShowMessage(string,MSG_SQL)
+// #define DisplaySQL(string) _ShowMessage(string,MSG_SQL)
+
+/* MSG_INFORMATION */
+ #define ShowInfo(string) _ShowMessage(string,MSG_INFORMATION)
+// #define DisplayInfo(string) _ShowMessage(string,MSG_INFORMATION)
+// #define ShowInformation(string) _ShowMessage(string,MSG_INFORMATION)
+// #define DisplayInformation(string) _ShowMessage(string,MSG_INFORMATION)
+
+/* MSG_NOTICE */
+ #define ShowNotice(string) _ShowMessage(string,MSG_NOTICE)
+// #define DisplayNotice(string) _ShowMessage(string,MSG_NOTICE)
+
+/* */
+ #define ShowWarning(string) _ShowMessage(string,MSG_WARNING)
+// #define DisplayWarning(string) _ShowMessage(string,MSG_WARNING)
+// #define Warn(string) _ShowMessage(string,MSG_WARNING)
+
+/* MSG_ERROR */
+ #define ShowError(string) _ShowMessage(string,MSG_ERROR)
+// #define DisplayError(string) _ShowMessage(string,MSG_ERROR)
+// #define OutputError(string) _ShowMessage(string,MSG_ERROR)
+
+/* MSG_FATALERROR */
+ #define ShowFatalError(string) _ShowMessage(string,MSG_FATALERROR)
+// #define DisplayFatalError(string) _ShowMessage(string,MSG_ERROR)
+// #define Terminate(string) _ShowMessage(string,MSG_FATALERROR)
+// #define Kill(string) _ShowMessage(string,MSG_FATALERROR)
+// #define AbortEx(string) _ShowMessage(string,MSG_FATALERROR)
+
+#endif
diff --git a/src/common/socket.c b/src/common/socket.c
new file mode 100644
index 000000000..4afcf50d4
--- /dev/null
+++ b/src/common/socket.c
@@ -0,0 +1,595 @@
+// original : core.c 2003/02/26 18:03:12 Rev 1.7
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <winsock2.h>
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <net/if.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#endif
+
+#include <fcntl.h>
+#include <string.h>
+
+#include "mmo.h" // [Valaris] thanks to fov
+#include "socket.h"
+#include "utils.h"
+
+#ifdef MEMWATCH
+#include "memwatch.h"
+#endif
+
+fd_set readfds;
+int fd_max;
+
+int rfifo_size = 65536;
+int wfifo_size = 65536;
+
+#ifndef TCP_FRAME_LEN
+#define TCP_FRAME_LEN 1053
+#endif
+
+struct socket_data *session[FD_SETSIZE];
+
+static int null_parse(int fd);
+static int (*default_func_parse)(int) = null_parse;
+
+static int null_console_parse(char *buf);
+static int (*default_console_parse)(char*) = null_console_parse;
+
+/*======================================
+ * CORE : Set function
+ *--------------------------------------
+ */
+void set_defaultparse(int (*defaultparse)(int))
+{
+ default_func_parse = defaultparse;
+}
+
+#ifdef NSOCKET
+static void setsocketopts(int fd)
+{
+ int yes = 1; // reuse fix
+
+ setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char *)&yes,sizeof yes);
+#ifdef SO_REUSEPORT
+ setsockopt(fd,SOL_SOCKET,SO_REUSEPORT,(char *)&yes,sizeof yes);
+#endif
+ setsockopt(fd,IPPROTO_TCP,TCP_NODELAY,(char *)&yes,sizeof yes);
+
+ setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &wfifo_size , sizeof(rfifo_size ));
+ setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *) &rfifo_size , sizeof(rfifo_size ));
+}
+
+#endif /* NSOCKET */
+/*======================================
+ * CORE : Socket Sub Function
+ *--------------------------------------
+ */
+
+static int recv_to_fifo(int fd)
+{
+ int len;
+
+ //printf("recv_to_fifo : %d %d\n",fd,session[fd]->eof);
+ if(session[fd]->eof)
+ return -1;
+
+
+#ifdef _WIN32
+ len=recv(fd,session[fd]->rdata+session[fd]->rdata_size, RFIFOSPACE(fd), 0);
+#else
+ len=read(fd,session[fd]->rdata+session[fd]->rdata_size,RFIFOSPACE(fd));
+#endif
+
+// printf (":::RECEIVE:::\n");
+// dump(session[fd]->rdata, len); printf ("\n");
+
+ //{ int i; printf("recv %d : ",fd); for(i=0;i<len;i++){ printf("%02x ",RFIFOB(fd,session[fd]->rdata_size+i)); } printf("\n");}
+ if(len>0){
+ session[fd]->rdata_size+=len;
+ } else if(len<=0){
+ // value of connection is not necessary the same
+// if (fd == 4) // Removed [Yor]
+// printf("Char-Server Has Disconnected.\n");
+// else if (fd == 5) // Removed [Yor]
+// printf("Attempt To Log In Successful.\n");
+// else if (fd == 7) // Removed [Yor]
+// printf("Char-Server Has Disconnected.\n");
+// else if (fd == 8) // Removed [Valaris]
+// printf("%s has logged off your server.\n",RFIFOP(fd,6)); // Removed [Valaris]
+
+// else if (fd != 8) // [Valaris]
+ printf("set eof : connection #%d\n", fd);
+ session[fd]->eof=1;
+ }
+ return 0;
+}
+
+static int send_from_fifo(int fd)
+{
+ int len;
+
+ //printf("send_from_fifo : %d\n",fd);
+ if(session[fd]->eof)
+ return -1;
+
+#ifdef _WIN32
+ len=send(fd, session[fd]->wdata,session[fd]->wdata_size, 0);
+#else
+ len=write(fd,session[fd]->wdata,session[fd]->wdata_size);
+#endif
+
+// printf (":::SEND:::\n");
+// dump(session[fd]->wdata, len); printf ("\n");
+
+ //{ int i; printf("send %d : ",fd); for(i=0;i<len;i++){ printf("%02x ",session[fd]->wdata[i]); } printf("\n");}
+ if(len>0){
+ if(len<session[fd]->wdata_size){
+ memmove(session[fd]->wdata,session[fd]->wdata+len,session[fd]->wdata_size-len);
+ session[fd]->wdata_size-=len;
+ } else {
+ session[fd]->wdata_size=0;
+ }
+ } else {
+ printf("set eof :%d\n",fd);
+ session[fd]->eof=1;
+ }
+ return 0;
+}
+
+static int null_parse(int fd)
+{
+ printf("null_parse : %d\n",fd);
+ RFIFOSKIP(fd,RFIFOREST(fd));
+ return 0;
+}
+
+/*======================================
+ * CORE : Socket Function
+ *--------------------------------------
+ */
+
+static int connect_client(int listen_fd)
+{
+ int fd;
+ struct sockaddr_in client_address;
+ int len;
+ int result;
+#ifndef NSOCKET
+ int yes = 1; // reuse fix
+#endif /* not NSOCKET */
+
+ //printf("connect_client : %d\n",listen_fd);
+
+ len=sizeof(client_address);
+
+ fd=accept(listen_fd,(struct sockaddr*)&client_address,&len);
+ if(fd_max<=fd) fd_max=fd+1;
+
+#ifndef NSOCKET
+ setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char *)&yes,sizeof yes);
+#ifdef SO_REUSEPORT
+ setsockopt(fd,SOL_SOCKET,SO_REUSEPORT,(char *)&yes,sizeof yes);
+#endif
+ setsockopt(fd,IPPROTO_TCP,TCP_NODELAY,(char *)&yes,sizeof yes);
+#else /* NSOCKET */
+ setsocketopts(fd);
+#endif /* NSOCKET */
+
+ if(fd==-1)
+ perror("accept");
+ else
+ FD_SET(fd,&readfds);
+
+#ifdef _WIN32
+ {
+ unsigned long val = 1;
+ ioctlsocket(fd, FIONBIO, &val);
+ }
+#else
+ result = fcntl(fd, F_SETFL, O_NONBLOCK);
+#endif
+
+ CREATE(session[fd], struct socket_data, 1);
+ CREATE(session[fd]->rdata, char, rfifo_size);
+ CREATE(session[fd]->wdata, char, wfifo_size);
+
+ session[fd]->max_rdata = rfifo_size;
+ session[fd]->max_wdata = wfifo_size;
+ session[fd]->func_recv = recv_to_fifo;
+ session[fd]->func_send = send_from_fifo;
+ session[fd]->func_parse = default_func_parse;
+ session[fd]->client_addr = client_address;
+
+ //printf("new_session : %d %d\n",fd,session[fd]->eof);
+ return fd;
+}
+
+int make_listen_port(int port)
+{
+ struct sockaddr_in server_address;
+ int fd;
+ int result;
+#ifndef NSOCKET
+ int yes = 1; // reuse fix
+#endif /* not NSOCKET */
+
+ fd = socket( AF_INET, SOCK_STREAM, 0 );
+ if(fd_max<=fd) fd_max=fd+1;
+
+#ifdef _WIN32
+ {
+ unsigned long val = 1;
+ ioctlsocket(fd, FIONBIO, &val);
+ }
+#else
+ result = fcntl(fd, F_SETFL, O_NONBLOCK);
+#endif
+
+#ifndef NSOCKET
+ setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char *)&yes,sizeof yes);
+#ifdef SO_REUSEPORT
+ setsockopt(fd,SOL_SOCKET,SO_REUSEPORT,(char *)&yes,sizeof yes);
+#endif
+ setsockopt(fd,IPPROTO_TCP,TCP_NODELAY,(char *)&yes,sizeof yes);
+#else /* NSOCKET */
+ setsocketopts(fd);
+#endif /* NSOCKET */
+
+ server_address.sin_family = AF_INET;
+ server_address.sin_addr.s_addr = htonl( INADDR_ANY );
+ server_address.sin_port = htons(port);
+
+ result = bind(fd, (struct sockaddr*)&server_address, sizeof(server_address));
+ if( result == -1 ) {
+ perror("bind");
+ exit(1);
+ }
+ result = listen( fd, 5 );
+ if( result == -1 ) { /* error */
+ perror("listen");
+ exit(1);
+ }
+
+ FD_SET(fd, &readfds );
+
+ CREATE(session[fd], struct socket_data, 1);
+
+ if(session[fd]==NULL){
+ printf("out of memory : make_listen_port\n");
+ exit(1);
+ }
+ memset(session[fd],0,sizeof(*session[fd]));
+ session[fd]->func_recv = connect_client;
+
+ return fd;
+}
+
+// Console Reciever [Wizputer]
+int console_recieve(int i) {
+ int n;
+ char *buf;
+
+ CREATE(buf, char , 64);
+
+ memset(buf,0,sizeof(64));
+
+ n = read(0, buf , 64);
+ if ( n < 0 )
+ printf("Console input read error\n");
+ else
+ session[0]->func_console(buf);
+ return 0;
+}
+
+void set_defaultconsoleparse(int (*defaultparse)(char*))
+{
+ default_console_parse = defaultparse;
+}
+
+static int null_console_parse(char *buf)
+{
+ printf("null_console_parse : %s\n",buf);
+ return 0;
+}
+
+// Console Input [Wizputer]
+int start_console(void) {
+ FD_SET(0,&readfds);
+
+ CREATE(session[0], struct socket_data, 1);
+ if(session[0]==NULL){
+ printf("out of memory : start_console\n");
+ exit(1);
+ }
+
+ memset(session[0],0,sizeof(*session[0]));
+
+ session[0]->func_recv = console_recieve;
+ session[0]->func_console = default_console_parse;
+
+ return 0;
+}
+
+int make_connection(long ip,int port)
+{
+ struct sockaddr_in server_address;
+ int fd;
+ int result;
+#ifndef NSOCKET
+ int yes = 1; // reuse fix
+#endif /* not NSOCKET */
+
+ fd = socket( AF_INET, SOCK_STREAM, 0 );
+#ifndef NSOCKET
+ if(fd_max<=fd) fd_max=fd+1;
+ setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char *)&yes,sizeof yes);
+#ifdef SO_REUSEPORT
+ setsockopt(fd,SOL_SOCKET,SO_REUSEPORT,(char *)&yes,sizeof yes);
+#endif
+ setsockopt(fd,IPPROTO_TCP,TCP_NODELAY,(char *)&yes,sizeof yes);
+#else /* NSOCKET */
+ if(fd_max<=fd)
+ fd_max=fd+1;
+
+ setsocketopts(fd);
+#endif /* NSOCKET */
+
+ server_address.sin_family = AF_INET;
+ server_address.sin_addr.s_addr = ip;
+ server_address.sin_port = htons(port);
+
+#ifdef _WIN32
+ {
+ unsigned long val = 1;
+ ioctlsocket(fd, FIONBIO, &val);
+ }
+#else
+ result = fcntl(fd, F_SETFL, O_NONBLOCK);
+#endif
+
+ result = connect(fd, (struct sockaddr *)(&server_address),sizeof(struct sockaddr_in));
+
+ FD_SET(fd,&readfds);
+
+ CREATE(session[fd], struct socket_data, 1);
+ CREATE(session[fd]->rdata, char, rfifo_size);
+ CREATE(session[fd]->wdata, char, wfifo_size);
+
+ session[fd]->max_rdata = rfifo_size;
+ session[fd]->max_wdata = wfifo_size;
+ session[fd]->func_recv = recv_to_fifo;
+ session[fd]->func_send = send_from_fifo;
+ session[fd]->func_parse = default_func_parse;
+
+ return fd;
+}
+
+int delete_session(int fd)
+{
+ if(fd<0 || fd>=FD_SETSIZE)
+ return -1;
+ FD_CLR(fd,&readfds);
+ if(session[fd]){
+ if(session[fd]->rdata)
+ free(session[fd]->rdata);
+ if(session[fd]->wdata)
+ free(session[fd]->wdata);
+ if(session[fd]->session_data)
+ free(session[fd]->session_data);
+ free(session[fd]);
+ }
+ session[fd]=NULL;
+ //printf("delete_session:%d\n",fd);
+ return 0;
+}
+
+int realloc_fifo(int fd,int rfifo_size,int wfifo_size)
+{
+ struct socket_data *s=session[fd];
+ if( s->max_rdata != rfifo_size && s->rdata_size < rfifo_size){
+ RECREATE(s->rdata, char, rfifo_size);
+ s->max_rdata = rfifo_size;
+ }
+ if( s->max_wdata != wfifo_size && s->wdata_size < wfifo_size){
+ RECREATE(s->wdata, char, wfifo_size);
+ s->max_wdata = wfifo_size;
+ }
+ return 0;
+}
+
+int WFIFOSET(int fd,int len)
+{
+ struct socket_data *s=session[fd];
+#ifdef NSOCKET
+ if (s == NULL || s->wdata == NULL)
+ return 0;
+#endif /* NSOCKET */
+ if( s->wdata_size+len+16384 > s->max_wdata ){
+ unsigned char *sin_addr = (unsigned char *)&s->client_addr.sin_addr;
+ realloc_fifo(fd,s->max_rdata, s->max_wdata <<1 );
+ printf("socket: %d (%d.%d.%d.%d) wdata expanded to %d bytes.\n",fd, sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3], s->max_wdata);
+ }
+ s->wdata_size=(s->wdata_size+(len)+2048 < s->max_wdata) ?
+ s->wdata_size+len : (printf("socket: %d wdata lost !!\n",fd),s->wdata_size);
+#ifdef NSOCKET
+ if (s->wdata_size > (TCP_FRAME_LEN))
+ send_from_fifo(fd);
+#endif /* NSOCKET */
+ return 0;
+}
+
+int do_sendrecv(int next)
+{
+ fd_set rfd,wfd;
+ struct timeval timeout;
+ int ret,i;
+
+ rfd=readfds;
+ FD_ZERO(&wfd);
+ for(i=0;i<fd_max;i++){
+ if(!session[i] && FD_ISSET(i,&readfds)){
+ printf("force clr fds %d\n",i);
+ FD_CLR(i,&readfds);
+ continue;
+ }
+ if(!session[i])
+ continue;
+ if(session[i]->wdata_size)
+ FD_SET(i,&wfd);
+ }
+ timeout.tv_sec = next/1000;
+ timeout.tv_usec = next%1000*1000;
+ ret = select(fd_max,&rfd,&wfd,NULL,&timeout);
+ if(ret<=0)
+ return 0;
+ for(i=0;i<fd_max;i++){
+ if(!session[i])
+ continue;
+ if(FD_ISSET(i,&wfd)){
+ //printf("write:%d\n",i);
+ if(session[i]->func_send)
+ //send_from_fifo(i);
+ session[i]->func_send(i);
+ }
+ if(FD_ISSET(i,&rfd)){
+ //printf("read:%d\n",i);
+ if(session[i]->func_recv)
+ //recv_to_fifo(i);
+ session[i]->func_recv(i);
+ }
+ }
+ return 0;
+}
+
+int do_parsepacket(void)
+{
+ int i;
+ for(i=0;i<fd_max;i++){
+ if(!session[i])
+ continue;
+ if(session[i]->rdata_size==0 && session[i]->eof==0)
+ continue;
+ if(session[i]->func_parse){
+ session[i]->func_parse(i);
+ if(!session[i])
+ continue;
+ }
+ RFIFOFLUSH(i);
+ }
+ return 0;
+}
+
+void do_socket(void)
+{
+ FD_ZERO(&readfds);
+}
+
+int RFIFOSKIP(int fd,int len)
+{
+ struct socket_data *s=session[fd];
+
+ if (s->rdata_size-s->rdata_pos-len<0) {
+ fprintf(stderr,"too many skip\n");
+ exit(1);
+ }
+
+ s->rdata_pos = s->rdata_pos+len;
+
+ return 0;
+}
+
+
+unsigned int addr_[16]; // ip addresses of local host (host byte order)
+unsigned int naddr_ = 0; // # of ip addresses
+
+int Net_Init(void)
+{
+#ifdef _WIN32
+ char** a;
+ unsigned int i;
+ char fullhost[255];
+ struct hostent* hent;
+
+ /* Start up the windows networking */
+ WSADATA wsaData;
+
+ if ( WSAStartup(WINSOCK_VERSION, &wsaData) != 0 ) {
+ printf("SYSERR: WinSock not available!\n");
+ exit(1);
+ }
+
+ if(gethostname(fullhost, sizeof(fullhost)) == SOCKET_ERROR) {
+ printf("Ugg.. no hostname defined!\n");
+ return 0;
+ }
+
+ // XXX This should look up the local IP addresses in the registry
+ // instead of calling gethostbyname. However, the way IP addresses
+ // are stored in the registry is annoyingly complex, so I'll leave
+ // this as T.B.D.
+ hent = gethostbyname(fullhost);
+ if (hent == NULL) {
+ printf("Cannot resolve our own hostname to a IP address");
+ return 0;
+ }
+
+ a = hent->h_addr_list;
+ for(i = 0; a[i] != 0 && i < 16; ++i) {
+ unsigned long addr1 = ntohl(*(unsigned long*) a[i]);
+ addr_[i] = addr1;
+ }
+ naddr_ = i;
+#else
+ int pos;
+ int fdes = socket(AF_INET, SOCK_STREAM, 0);
+ char buf[16 * sizeof(struct ifreq)];
+ struct ifconf ic;
+
+ // The ioctl call will fail with Invalid Argument if there are more
+ // interfaces than will fit in the buffer
+ ic.ifc_len = sizeof(buf);
+ ic.ifc_buf = buf;
+ if(ioctl(fdes, SIOCGIFCONF, &ic) == -1) {
+ printf("SIOCGIFCONF failed!\n");
+ return 0;
+ }
+
+ for(pos = 0; pos < ic.ifc_len;)
+ {
+ struct ifreq * ir = (struct ifreq *) (ic.ifc_buf + pos);
+
+ struct sockaddr_in * a = (struct sockaddr_in *) &(ir->ifr_addr);
+
+ if(a->sin_family == AF_INET) {
+ u_long ad = ntohl(a->sin_addr.s_addr);
+ if(ad != INADDR_LOOPBACK) {
+ addr_[naddr_ ++] = ad;
+ if(naddr_ == 16)
+ break;
+ }
+ }
+
+#if defined(_AIX) || defined(__APPLE__)
+ pos += ir->ifr_addr.sa_len; // For when we port athena to run on Mac's :)
+ pos += sizeof(ir->ifr_name);
+#else
+ pos += sizeof(struct ifreq);
+#endif
+ }
+
+#endif
+
+ return(0);
+}
diff --git a/src/common/socket.h b/src/common/socket.h
new file mode 100644
index 000000000..e3ad0826a
--- /dev/null
+++ b/src/common/socket.h
@@ -0,0 +1,104 @@
+// original : core.h 2003/03/14 11:55:25 Rev 1.4
+
+#ifndef _SOCKET_H_
+#define _SOCKET_H_
+
+#include <stdio.h>
+
+#ifdef _WIN32
+#include <winsock.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#endif
+
+// define declaration
+
+#define RFIFOP(fd,pos) (session[fd]->rdata+session[fd]->rdata_pos+(pos))
+#define RFIFOB(fd,pos) (*(unsigned char*)(session[fd]->rdata+session[fd]->rdata_pos+(pos)))
+#define RFIFOW(fd,pos) (*(unsigned short*)(session[fd]->rdata+session[fd]->rdata_pos+(pos)))
+#define RFIFOL(fd,pos) (*(unsigned int*)(session[fd]->rdata+session[fd]->rdata_pos+(pos)))
+//#define RFIFOSKIP(fd,len) ((session[fd]->rdata_size-session[fd]->rdata_pos-(len)<0) ? (fprintf(stderr,"too many skip\n"),exit(1)) : (session[fd]->rdata_pos+=(len)))
+#define RFIFOREST(fd) (session[fd]->rdata_size-session[fd]->rdata_pos)
+#define RFIFOFLUSH(fd) (memmove(session[fd]->rdata,RFIFOP(fd,0),RFIFOREST(fd)),session[fd]->rdata_size=RFIFOREST(fd),session[fd]->rdata_pos=0)
+#define RFIFOSPACE(fd) (session[fd]->max_rdata-session[fd]->rdata_size)
+#define RBUFP(p,pos) (((unsigned char*)(p))+(pos))
+#define RBUFB(p,pos) (*(unsigned char*)RBUFP((p),(pos)))
+#define RBUFW(p,pos) (*(unsigned short*)RBUFP((p),(pos)))
+#define RBUFL(p,pos) (*(unsigned int*)RBUFP((p),(pos)))
+
+#define WFIFOSPACE(fd) (session[fd]->max_wdata-session[fd]->wdata_size)
+#define WFIFOP(fd,pos) (session[fd]->wdata+session[fd]->wdata_size+(pos))
+#define WFIFOB(fd,pos) (*(unsigned char*)(session[fd]->wdata+session[fd]->wdata_size+(pos)))
+#define WFIFOW(fd,pos) (*(unsigned short*)(session[fd]->wdata+session[fd]->wdata_size+(pos)))
+#define WFIFOL(fd,pos) (*(unsigned int*)(session[fd]->wdata+session[fd]->wdata_size+(pos)))
+// use function instead of macro.
+//#define WFIFOSET(fd,len) (session[fd]->wdata_size = (session[fd]->wdata_size+(len)+2048 < session[fd]->max_wdata) ? session[fd]->wdata_size+len : session[fd]->wdata_size)
+#define WBUFP(p,pos) (((unsigned char*)(p))+(pos))
+#define WBUFB(p,pos) (*(unsigned char*)WBUFP((p),(pos)))
+#define WBUFW(p,pos) (*(unsigned short*)WBUFP((p),(pos)))
+#define WBUFL(p,pos) (*(unsigned int*)WBUFP((p),(pos)))
+
+#ifdef __INTERIX
+#define FD_SETSIZE 4096
+#endif // __INTERIX
+
+
+/* Removed Cygwin FD_SETSIZE declarations, now are directly passed on to the compiler through Makefile [Valaris] */
+
+// Struct declaration
+
+struct socket_data{
+ int eof;
+ unsigned char *rdata,*wdata;
+ int max_rdata,max_wdata;
+ int rdata_size,wdata_size;
+ int rdata_pos;
+ struct sockaddr_in client_addr;
+ int (*func_recv)(int);
+ int (*func_send)(int);
+ int (*func_parse)(int);
+ int (*func_console)(char*);
+ void* session_data;
+};
+
+// Data prototype declaration
+
+#ifdef _WIN32
+
+ #undef FD_SETSIZE
+ #define FD_SETSIZE 4096
+
+#endif
+
+extern struct socket_data *session[FD_SETSIZE];
+
+extern int rfifo_size,wfifo_size;
+extern int fd_max;
+
+// Function prototype declaration
+
+int make_listen_port(int);
+int make_connection(long,int);
+int delete_session(int);
+int realloc_fifo(int fd,int rfifo_size,int wfifo_size);
+int WFIFOSET(int fd,int len);
+int RFIFOSKIP(int fd,int len);
+
+int do_sendrecv(int next);
+int do_parsepacket(void);
+void do_socket(void);
+
+int start_console(void);
+
+void set_defaultparse(int (*defaultparse)(int));
+void set_defaultconsoleparse(int (*defaultparse)(char*));
+
+int Net_Init(void);
+
+extern unsigned int addr_[16]; // ip addresses of local host (host byte order)
+extern unsigned int naddr_; // # of ip addresses
+
+
+#endif // _SOCKET_H_
diff --git a/src/common/timer.c b/src/common/timer.c
new file mode 100644
index 000000000..97c162e7f
--- /dev/null
+++ b/src/common/timer.c
@@ -0,0 +1,319 @@
+// $Id: timer.c,v 1.1.1.1 2004/09/10 17:44:49 MagicalTux Exp $
+// original : core.c 2003/02/26 18:03:12 Rev 1.7
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#ifdef _WIN32
+#include <winsock.h>
+#else
+#include <sys/socket.h>
+#include <sys/time.h>
+#endif
+
+#include "timer.h"
+#include "utils.h"
+
+#ifdef MEMWATCH
+#include "memwatch.h"
+#endif
+
+// If the server shows no reaction when processing thousands of monsters
+
+// or connected by many clients, please increase TIMER_MIN_INTERVEL.
+
+#define TIMER_MIN_INTERVEL 50
+
+static struct TimerData* timer_data;
+static int timer_data_max,timer_data_num;
+static int* free_timer_list;
+static int free_timer_list_max, free_timer_list_pos;
+
+static int timer_heap_max=0; //fixed Shinomori from eA forums
+static int* timer_heap = NULL;
+
+// for debug
+struct timer_func_list {
+ int (*func)(int,unsigned int,int,int);
+ struct timer_func_list* next;
+ char* name;
+};
+static struct timer_func_list* tfl_root;
+
+#if defined(_WIN32)
+void gettimeofday(struct timeval *t, struct timezone *dummy)
+{
+ DWORD millisec = GetTickCount();
+
+ t->tv_sec = (int) (millisec / 1000);
+ t->tv_usec = (millisec % 1000) * 1000;
+}
+
+#endif
+
+
+//
+int add_timer_func_list(int (*func)(int,unsigned int,int,int),char* name)
+{
+ struct timer_func_list* tfl;
+
+ CREATE(tfl, struct timer_func_list, 1);
+ CREATE(tfl->name, char, strlen(name) + 1);
+
+ tfl->next = tfl_root;
+ tfl->func = func;
+ strcpy(tfl->name,name);
+ tfl_root = tfl;
+
+ return 0;
+}
+
+char* search_timer_func_list(int (*func)(int,unsigned int,int,int))
+{
+ struct timer_func_list* tfl;
+ for(tfl = tfl_root;tfl;tfl = tfl->next) {
+ if (func == tfl->func)
+ return tfl->name;
+ }
+ return "???";
+}
+
+/*----------------------------
+ * Get tick time
+ *----------------------------*/
+static unsigned int gettick_cache;
+static int gettick_count;
+unsigned int gettick_nocache(void)
+{
+ struct timeval tval;
+ gettimeofday(&tval,NULL);
+ gettick_count = 256;
+ return gettick_cache = tval.tv_sec * 1000 + tval.tv_usec/1000;
+}
+
+unsigned int gettick(void)
+{
+ gettick_count--;
+ if (gettick_count<0)
+ return gettick_nocache();
+ return gettick_cache;
+}
+
+/*======================================
+ * CORE : Timer Heap
+ *--------------------------------------
+ */
+static void push_timer_heap(int index)
+{
+ int i, h;
+
+ if (timer_heap == NULL || timer_heap[0] + 1 >= timer_heap_max) {
+ int first = timer_heap == NULL;
+
+ timer_heap_max += 256;
+ RECREATE(timer_heap, int, timer_heap_max);
+ memset(timer_heap + (timer_heap_max - 256), 0, sizeof(int) * 256);
+ if (first)
+ timer_heap[0] = 0;
+ }
+
+ timer_heap[0]++;
+
+ for (h = timer_heap[0]-1, i = (h - 1) / 2;
+ h > 0 && DIFF_TICK(timer_data[index].tick,
+ timer_data[timer_heap[i + 1]].tick) < 0;
+ i = (h - 1) / 2) {
+ timer_heap[h + 1] = timer_heap[i + 1];
+ h = i;
+ }
+ timer_heap[h + 1] = index;
+}
+
+static int top_timer_heap()
+{
+ if (timer_heap == NULL || timer_heap[0] <= 0)
+ return -1;
+
+ return timer_heap[1];
+}
+
+static int pop_timer_heap()
+{
+ int i,h,k;
+ int ret,last;
+
+ if (timer_heap == NULL || timer_heap[0] <= 0)
+ return -1;
+ ret = timer_heap[1];
+ last = timer_heap[timer_heap[0]];
+ timer_heap[0]--;
+
+ for(h = 0,k = 2;k<timer_heap[0];k = k * 2 + 2) {
+ if (DIFF_TICK(timer_data[timer_heap[k + 1]].tick , timer_data[timer_heap[k]].tick)>0)
+ k--;
+ timer_heap[h + 1] = timer_heap[k + 1], h = k;
+ }
+ if (k == timer_heap[0])
+ timer_heap[h + 1] = timer_heap[k], h = k-1;
+
+ for(i = (h-1)/2;
+ h>0 && DIFF_TICK(timer_data[timer_heap[i + 1]].tick , timer_data[last].tick)>0;
+ i = (h-1)/2) {
+ timer_heap[h + 1] = timer_heap[i + 1],h = i;
+ }
+ timer_heap[h + 1] = last;
+
+ return ret;
+}
+
+int add_timer(unsigned int tick,int (*func)(int,unsigned int,int,int),int id,int data)
+{
+ struct TimerData* td;
+ int i;
+
+ if (free_timer_list_pos) {
+ do {
+ i = free_timer_list[--free_timer_list_pos];
+ } while(i >= timer_data_num && free_timer_list_pos > 0);
+ } else
+ i = timer_data_num;
+ if (i >= timer_data_num)
+ for (i = timer_data_num;i<timer_data_max && timer_data[i].type; i++);
+ if (i >= timer_data_num && i >= timer_data_max) {
+ int j;
+ if (timer_data_max == 0) {
+ timer_data_max = 256;
+ CREATE(timer_data, struct TimerData, timer_data_max);
+ } else {
+ timer_data_max += 256;
+ RECREATE(timer_data, struct TimerData, timer_data_max);
+ if (timer_data == NULL) {
+ printf("out of memory : add_timer timer_data\n");
+ exit(1);
+ }
+ memset(timer_data + (timer_data_max - 256), 0,
+ sizeof(struct TimerData) * 256);
+ }
+ for(j = timer_data_max-256;j<timer_data_max; j++)
+ timer_data[j].type = 0;
+ }
+ td = &timer_data[i];
+ td->tick = tick;
+ td->func = func;
+ td->id = id;
+ td->data = data;
+ td->type = TIMER_ONCE_AUTODEL;
+ td->interval = 1000;
+ push_timer_heap(i);
+ if (i >= timer_data_num)
+ timer_data_num = i + 1;
+ return i;
+}
+
+int add_timer_interval(unsigned int tick,int (*func)(int,unsigned int,int,int),int id,int data,int interval)
+{
+ int tid;
+ tid = add_timer(tick,func,id,data);
+ timer_data[tid].type = TIMER_INTERVAL;
+ timer_data[tid].interval = interval;
+ return tid;
+}
+
+int delete_timer(int id,int (*func)(int,unsigned int,int,int))
+{
+ if (id <= 0 || id >= timer_data_num) {
+ printf("delete_timer error : no such timer %d\n", id);
+ return -1;
+ }
+ if (timer_data[id].func != func) {
+ printf("delete_timer error : function dismatch %08x(%s) != %08x(%s)\n",
+ (int)timer_data[id].func,
+ search_timer_func_list(timer_data[id].func),
+ (int)func,
+ search_timer_func_list(func));
+ return -2;
+ }
+ // そのうち消えるにまかせる
+ timer_data[id].func = NULL;
+ timer_data[id].type = TIMER_ONCE_AUTODEL;
+ timer_data[id].tick -= 60 * 60 * 1000;
+ return 0;
+}
+
+int addtick_timer(int tid,unsigned int tick)
+{
+ return timer_data[tid].tick += tick;
+}
+struct TimerData* get_timer(int tid)
+{
+ return &timer_data[tid];
+}
+
+
+int do_timer(unsigned int tick)
+{
+ int i,nextmin = 1000;
+
+#if 0
+ static int disp_tick = 0;
+ if (DIFF_TICK(disp_tick,tick)<-5000 || DIFF_TICK(disp_tick,tick)>5000) {
+ printf("timer %d(%d + %d)\n",timer_data_num,timer_heap[0],free_timer_list_pos);
+ disp_tick = tick;
+ }
+#endif
+
+ while((i = top_timer_heap()) >= 0) {
+ if (DIFF_TICK(timer_data[i].tick , tick)>0) {
+ nextmin = DIFF_TICK(timer_data[i].tick , tick);
+ break;
+ }
+ pop_timer_heap();
+ timer_data[i].type |= TIMER_REMOVE_HEAP;
+ if (timer_data[i].func) {
+ if (DIFF_TICK(timer_data[i].tick , tick) < -1000) {
+ // 1秒以上の大幅な遅延が発生しているので、
+ // timer処理タイミングを現在値とする事で
+ // 呼び出し時タイミング(引数のtick)相対で処理してる
+ // timer関数の次回処理タイミングを遅らせる
+ timer_data[i].func(i,tick,timer_data[i].id,timer_data[i].data);
+ } else {
+ timer_data[i].func(i,timer_data[i].tick,timer_data[i].id,timer_data[i].data);
+ }
+ }
+ if (timer_data[i].type&TIMER_REMOVE_HEAP) {
+ switch(timer_data[i].type & ~TIMER_REMOVE_HEAP) {
+ case TIMER_ONCE_AUTODEL:
+ timer_data[i].type = 0;
+ if (free_timer_list_pos >= free_timer_list_max) {
+ free_timer_list_max += 256;
+ RECREATE(free_timer_list, int, free_timer_list_max);
+ memset(free_timer_list + (free_timer_list_max - 256), 0,
+ 256 * sizeof(free_timer_list[0]));
+ }
+ free_timer_list[free_timer_list_pos++] = i;
+ break;
+ case TIMER_INTERVAL:
+ if (DIFF_TICK(timer_data[i].tick , tick) < -1000) {
+ timer_data[i].tick = tick + timer_data[i].interval;
+ } else {
+ timer_data[i].tick += timer_data[i].interval;
+ }
+ timer_data[i].type &= ~TIMER_REMOVE_HEAP;
+ push_timer_heap(i);
+ break;
+ }
+ }
+ }
+
+ if(nextmin < TIMER_MIN_INTERVEL)
+
+ nextmin = TIMER_MIN_INTERVEL;
+ return nextmin;
+}
+
+void timer_final()
+{
+ free(timer_data);
+}
diff --git a/src/common/timer.h b/src/common/timer.h
new file mode 100644
index 000000000..f6fc5c84d
--- /dev/null
+++ b/src/common/timer.h
@@ -0,0 +1,45 @@
+// original : core.h 2003/03/14 11:55:25 Rev 1.4
+
+#ifndef _TIMER_H_
+#define _TIMER_H_
+
+#define BASE_TICK 5
+
+#define TIMER_ONCE_AUTODEL 1
+#define TIMER_INTERVAL 2
+#define TIMER_REMOVE_HEAP 16
+
+#define DIFF_TICK(a,b) ((int)((a)-(b)))
+
+// Struct declaration
+
+struct TimerData {
+ unsigned int tick;
+ int (*func)(int,unsigned int,int,int);
+ int id;
+ int data;
+ int type;
+ int interval;
+ int heap_pos;
+};
+
+// Function prototype declaration
+
+unsigned int gettick_nocache(void);
+unsigned int gettick(void);
+
+int add_timer(unsigned int,int (*)(int,unsigned int,int,int),int,int);
+int add_timer_interval(unsigned int,int (*)(int,unsigned int,int,int),int,int,int);
+int delete_timer(int,int (*)(int,unsigned int,int,int));
+
+int addtick_timer(int tid,unsigned int tick);
+struct TimerData *get_timer(int tid);
+
+int do_timer(unsigned int tick);
+
+int add_timer_func_list(int (*)(int,unsigned int,int,int),char*);
+char* search_timer_func_list(int (*)(int,unsigned int,int,int));
+
+extern void timer_final();
+
+#endif // _TIMER_H_
diff --git a/src/common/utils.c b/src/common/utils.c
new file mode 100644
index 000000000..941f2b0bd
--- /dev/null
+++ b/src/common/utils.c
@@ -0,0 +1,108 @@
+#include <string.h>
+#include "utils.h"
+#include <stdio.h>
+
+void dump(unsigned char *buffer, int num)
+{
+ int icnt,jcnt;
+
+ printf(" Hex ASCII\n");
+ printf(" ----------------------------------------------- ----------------");
+
+ for (icnt=0;icnt<num;icnt+=16) {
+ printf("\n%p ",&buffer[icnt]);
+ for (jcnt=icnt;jcnt<icnt+16;++jcnt) {
+ if (jcnt < num) {
+ printf("%02hX ",buffer[jcnt]);
+ } else
+ printf(" ");
+ }
+
+ printf(" | ");
+
+ for (jcnt=icnt;jcnt<icnt+16;++jcnt) {
+ if (jcnt < num) {
+ if (buffer[jcnt] > 31 && buffer[jcnt] < 127)
+ printf("%c",buffer[jcnt]);
+ else
+ printf(".");
+ } else
+ printf(" ");
+ }
+ }
+ printf("\n");
+}
+
+
+#ifdef _WIN32
+char *rindex(char *str, char c)
+{
+ char *sptr;
+
+ sptr = str;
+ while(*sptr)
+ ++sptr;
+ if (c == '\0')
+ return(sptr);
+ while(str != sptr)
+ if (*sptr-- == c)
+ return(++sptr);
+ return(NULL);
+}
+
+int strcasecmp(const char *arg1, const char *arg2)
+{
+ int chk, i;
+
+ if (arg1 == NULL || arg2 == NULL) {
+ printf("SYSERR: str_cmp() passed a NULL pointer, %p or %p.\n", arg1, arg2);
+ return (0);
+ }
+
+ for (i = 0; arg1[i] || arg2[i]; i++)
+ if ((chk = LOWER(arg1[i]) - LOWER(arg2[i])) != 0)
+ return (chk); /* not equal */
+
+ return (0);
+}
+
+int strncasecmp(const char *arg1, const char *arg2, int n)
+{
+ int chk, i;
+
+ if (arg1 == NULL || arg2 == NULL) {
+ printf("SYSERR: strn_cmp() passed a NULL pointer, %p or %p.\n", arg1, arg2);
+ return (0);
+ }
+
+ for (i = 0; (arg1[i] || arg2[i]) && (n > 0); i++, n--)
+ if ((chk = LOWER(arg1[i]) - LOWER(arg2[i])) != 0)
+ return (chk); /* not equal */
+
+ return (0);
+}
+
+void str_upper(char *name)
+{
+
+ int len = strlen(name);
+ while (len--) {
+ if (*name >= 'a' && *name <= 'z')
+ *name -= ('a' - 'A');
+ name++;
+ }
+}
+
+void str_lower(char *name)
+{
+ int len = strlen(name);
+
+ while (len--) {
+ if (*name >= 'A' && *name <= 'Z')
+ *name += ('a' - 'A');
+ name++;
+ }
+}
+
+#endif
+
diff --git a/src/common/utils.h b/src/common/utils.h
new file mode 100644
index 000000000..c8efd525b
--- /dev/null
+++ b/src/common/utils.h
@@ -0,0 +1,33 @@
+
+#ifndef NULL
+#define NULL (void *)0
+#endif
+
+#define LOWER(c) (((c)>='A' && (c) <= 'Z') ? ((c)+('a'-'A')) : (c))
+#define UPPER(c) (((c)>='a' && (c) <= 'z') ? ((c)+('A'-'a')) : (c) )
+
+/* strcasecmp -> stricmp -> str_cmp */
+
+
+#ifdef _WIN32
+ int strcasecmp(const char *arg1, const char *arg2);
+ int strncasecmp(const char *arg1, const char *arg2, int n);
+ void str_upper(char *name);
+ void str_lower(char *name);
+ char *rindex(char *str, char c);
+#endif
+
+
+ void dump(unsigned char *buffer, int num);
+
+
+#define CREATE(result, type, number) do {\
+ if ((number) * sizeof(type) <= 0) \
+ printf("SYSERR: Zero bytes or less requested at %s:%d.\n", __FILE__, __LINE__); \
+ if (!((result) = (type *) calloc ((number), sizeof(type)))) \
+ { perror("SYSERR: malloc failure"); abort(); } } while(0)
+
+#define RECREATE(result,type,number) do {\
+ if (!((result) = (type *) realloc ((result), sizeof(type) * (number))))\
+ { printf("SYSERR: realloc failure"); abort(); } } while(0)
+
diff --git a/src/common/version.h b/src/common/version.h
new file mode 100644
index 000000000..e33e2b305
--- /dev/null
+++ b/src/common/version.h
@@ -0,0 +1,27 @@
+// $Id: version.h,v 1.2 2004/09/22 09:49:06 PoW Exp $
+#ifndef _VERSION_H_
+#define _VERSION_H_
+
+#define ATHENA_MAJOR_VERSION 1 // Major Version
+#define ATHENA_MINOR_VERSION 0 // Minor Version
+#define ATHENA_REVISION 0 // Revision
+
+#define ATHENA_RELEASE_FLAG 1 // 1=Develop,0=Stable
+#define ATHENA_OFFICIAL_FLAG 1 // 1=Mod,0=Official
+
+#define ATHENA_SERVER_LOGIN 1 // login server
+#define ATHENA_SERVER_CHAR 2 // char server
+#define ATHENA_SERVER_INTER 4 // inter server
+#define ATHENA_SERVER_MAP 8 // map server
+
+// ATHENA_MOD_VERSIONはパッチ番号です。
+// これは無理に変えなくても気が向いたら変える程度の扱いで。
+// (毎回アップロードの度に変更するのも面倒と思われるし、そもそも
+//  この項目を参照する人がいるかどうかで疑問だから。)
+// その程度の扱いなので、サーバーに問い合わせる側も、あくまで目安程度の扱いで
+// あんまり信用しないこと。
+// 鯖snapshotの時や、大きな変更があった場合は設定してほしいです。
+// C言語の仕様上、最初に0を付けると8進数になるので間違えないで下さい。
+#define ATHENA_MOD_VERSION 1052 // mod version (patch No.)
+
+#endif