tastyspleen / q2admin-tsmod

This is Q2Admin 1.17.44 with R1CH's security patches applied, and a couple tweaks to prevent kicking of players for false positives (Q2Admin would think a player was a bot when they were merely lagging badly.)
7 stars 8 forks source link

aarch64 compilation #10

Open PowaBanga opened 4 years ago

PowaBanga commented 4 years ago

Hello, I am trying to compil this source into my raspberry pi 3b+ with Archlinux installed on in aarch64 architecture.

so, i modified the code like i did for arm

#ifdef LINUXAXP
        #define DLLNAME   "gameaxp.real.so"
#elif defined(SOLARIS_INTEL)
        #define DLLNAME   "gamei386.real.so"
#elif defined(SOLARIS_SPARC)
        #define DLLNAME   "gamesparc.real.so"
#elif defined (LINUX)
#if defined __i386__
        #define DLLNAME "gamei386.real.so"
#elif defined __x86_64__
        #define DLLNAME "gamex86_64.real.so"
#elif define __aarch64__
        #define DLLNAME "gameaarch64.real.so"
#else
        #error Unknown architecture
#endif

and i have this error message :

make[1]: Entering directory '/home/powabanga/DDaynormandyFPS/src/q2admin-tsmod'
gcc -std=gnu99 -O2 -fPIC -DARCH="aarch64" -DLINUX -DSTDC_HEADERS -I/usr/include   -c -o g_main.o g_main.c
g_main.c:51:14: error: missing binary operator before token "1"
   51 | #elif define __aarch64__
      |              ^~~~~~~~~~~
g_main.c:54:3: error: #error Unknown architecture
   54 |  #error Unknown architecture
      |   ^~~~~
g_main.c: In function 'GetGameAPI':
g_main.c:232:36: error: 'DLLNAME' undeclared (first use in this function)
  232 |  sprintf(dllname, "%s/%s", moddir, DLLNAME);
      |                                    ^~~~~~~
g_main.c:232:36: note: each undeclared identifier is reported only once for each function it appears in
make[1]: *** [<builtin>: g_main.o] Error 1
make[1]: Leaving directory '/home/powabanga/DDaynormandyFPS/src/q2admin-tsmod'

Does anybody can help me to understand this error, and maybe find a way to fix that please ? :/

QwazyWabbitWOS commented 4 years ago

Line 51 should read #elif defined __aarch64__ not define.

This assumes the compiler defines the target architecture as__aarch64__.

QwazyWabbitWOS commented 4 years ago

I should point out that this is going to be a problem when porting to other architectures besides x86 going forward. The naming convention you are extending was intended to allow the development toolset to automatically name the DLL according to the platform. There are now too many platforms to maintain. The game might as well have been named game.dll or game.so for all architectures.

PowaBanga commented 4 years ago

hmm... this source https://github.com/PowaBanga/DDaynormandyFPS compil q2pro, q2admintsmod (from this this github source), and ddaymod very well on all my computers and architectures.

my question is, why doesn't it work on my aarch64 archlinux, is it from q2tadmin that the problem is, or is it from something who can be missin on my aarch computer ?

QwazyWabbitWOS commented 4 years ago

PowaBanga, Did you solve your problem? I don't have an aarch64 Pi but on my Pi 3b+ your repository together with the q2pro and q2admin-tsmod repositories build correctly with gamearm.so, as the q2admin dll and gamearm.real.so as the ddayNormandy dll without any changes.

I cloned your repository and I cloned q2admin-tsmod and q2pro into your subtree and they all built without changes.

Invoking the server with ./ddaynormandyded map dday1 started the server correctly and all bots started correctly and I was able to join the server without any trouble.

From what I can see, the q2pro build assumes all arm processors are "arm" so the building of the game dll should always keep "arm" as the CPU type and make no changes there. You can test this by building q2pro and looking at the game dll it built in the q2pro folder. If the name of that binary is gamearm.so then your build of q2admin should follow that naming and the name of the real normandy game dll should be gamearm.real.so.

Note: if your aarch64 compiler doesn't define__arm__but defines__aarch64__ then the correct line to write in q2admin-tsmod g_main.c is:

#elif defined (__arm__) || defined (__aarch64__)
    #define DLLNAME "gamearm.real.so"

I hope this helps. QW

P.S. Please report results if this fixes your issue with q2admin-tsmod and I will modify the repository accordingly.

PowaBanga commented 4 years ago

ok, here is my g_main.c

[powabanga@alarm DDaynormandyFPS]$ cat src/q2admin-tsmod/g_main.c
/*
Copyright (C) 2000 Shane Powell

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

//
// q2admin
//
// g_main.c
//
// copyright 2000 Shane Powell
//

#include "g_local.h"

#ifdef __GNUC__
#include <dlfcn.h>
#elif defined(WIN32)
#include <windows.h>
#endif

#ifdef __GNUC__
void *hdll = NULL;

#ifdef LINUXAXP
        #define DLLNAME   "gameaxp.real.so"
#elif defined(SOLARIS_INTEL)
        #define DLLNAME   "gamei386.real.so"
#elif defined(SOLARIS_SPARC)
        #define DLLNAME   "gamesparc.real.so"
#elif defined (LINUX)
#if defined __i386__
        #define DLLNAME "gamei386.real.so"
#elif defined __x86_64__
        #define DLLNAME "gamex86_64.real.so"
#elif define (__arm__) || defined (__aarch64__)
        #define DLLNAME "gamearm.real.so"
#else
        #error Unknown architecture
#endif
#else
        #error Unknown GNUC OS
#endif

#elif defined(WIN32)
HINSTANCE hdll;
#define DLLNAME   "gamex86.real.dll"  // Not sure how this was suppsoed to work, but it was loading itself and overwriting its own gi.vars when just called "gamex86.dll"
#define DLLNAMEMODDIR "gamex86.real.dll"
#else
#error Unknown OS
#endif

typedef game_export_t  *GAMEAPI (game_import_t *import);

char  zbot_teststring1[] = ZBOT_TESTSTRING1;
char  zbot_teststring_test1[] = ZBOT_TESTSTRING_TEST1;
char  zbot_teststring_test2[] = ZBOT_TESTSTRING_TEST2;
char  zbot_teststring_test3[] = ZBOT_TESTSTRING_TEST3;
char  zbot_testchar1;
char  zbot_testchar2;

qboolean soloadlazy;

void ShutdownGame (void)
{
        INITPERFORMANCE(1);
        INITPERFORMANCE(2);

        if(!dllloaded) return;

//*** UPDATE START ***
        if (whois_details)
        {
                whois_write_file();
                gi.TagFree (whois_details);
        }
//*** UPDATE END ***

        if(q2adminrunmode)
                {
                        STARTPERFORMANCE(1);
                        logEvent(LT_SERVEREND, 0, NULL, NULL, 0, 0.0);
                        STARTPERFORMANCE(2);
                }

        // reset the password just in case something has gone wrong...
        lrcon_reset_rcon_password(0, 0, 0);
        dllglobals->Shutdown();

        if(q2adminrunmode)
                {
                        STOPPERFORMANCE(2, "mod->ShutdownGame", 0, NULL);
                }

#ifdef __GNUC__
        dlclose(hdll);
#elif defined(WIN32)
        FreeLibrary(hdll);
#endif

        dllloaded = FALSE;

        if(q2adminrunmode)
                {
                        STOPPERFORMANCE(1, "q2admin->ShutdownGame", 0, NULL);
                }
}

/*
=================
GetGameAPI

Returns a pointer to the structure with all entry points
and global variables
=================
*/
game_export_t *GetGameAPI(game_import_t *import)
{
        GAMEAPI *getapi;
#ifdef __GNUC__
        int loadtype;
#endif

        unsigned int i;// UPDATE
        dllloaded = FALSE;
        gi = *import;

        import->bprintf = bprintf_internal;
        import->cprintf = cprintf_internal;
        import->dprintf = dprintf_internal;
        import->AddCommandString = AddCommandString_internal;
        //import->Pmove = Pmove_internal;
        import->linkentity = linkentity_internal;
        import->unlinkentity = unlinkentity_internal;

        globals.Init = InitGame;
        globals.Shutdown = ShutdownGame;
        globals.SpawnEntities = SpawnEntities;

        globals.WriteGame = WriteGame;
        globals.ReadGame = ReadGame;
        globals.WriteLevel = WriteLevel;
        globals.ReadLevel = ReadLevel;

        globals.ClientThink = ClientThink;
        globals.ClientConnect = ClientConnect;
        globals.ClientUserinfoChanged = ClientUserinfoChanged;
        globals.ClientDisconnect = ClientDisconnect;
        globals.ClientBegin = ClientBegin;
        globals.ClientCommand = ClientCommand;

        globals.RunFrame = G_RunFrame;

        globals.ServerCommand = ServerCommand;

        port = gi.cvar("port", "", 0);
        rcon_password = gi.cvar("rcon_password", "", 0) ; // UPDATE
        q2admintxt = gi.cvar("q2admintxt", "", 0);
        q2adminbantxt = gi.cvar("q2adminbantxt", "", 0);

        gamedir = gi.cvar ("game", "baseq2", 0);
        q2a_strcpy(moddir, gamedir->string);

        if(moddir[0] == 0)
                {
                        q2a_strcpy(moddir, "baseq2");
                }

        for (i=0;i<PRIVATE_COMMANDS;i++)
                {
                        private_commands[i].command[0] = 0;
                }

//*** UPDATE START ***
        q2a_strcpy(client_msg,DEFAULTQ2AMSG);
//*** UPDATE END ***
        q2a_strcpy(zbotuserdisplay, DEFAULTUSERDISPLAY);
        q2a_strcpy(timescaleuserdisplay, DEFAULTTSDISPLAY);
        q2a_strcpy(hackuserdisplay, DEFAULTHACKDISPLAY);
        q2a_strcpy(skincrashmsg, DEFAULTSKINCRASHMSG);
        q2a_strcpy(defaultreconnectmessage, DEFAULTRECONNECTMSG);
        q2a_strcpy(defaultBanMsg, DEFAULTBANMSG);
        q2a_strcpy(nameChangeFloodProtectMsg, DEFAULTFLOODMSG);
        q2a_strcpy(skinChangeFloodProtectMsg, DEFAULTSKINFLOODMSG);
        q2a_strcpy(defaultChatBanMsg, DEFAULTCHABANMSG);
        q2a_strcpy(chatFloodProtectMsg, DEFAULTCHATFLOODMSG);
        q2a_strcpy(clientVoteCommand, DEFAULTVOTECOMMAND);
        q2a_strcpy(cl_pitchspeed_kickmsg, DEFAULTCL_PITCHSPEED_KICKMSG);
        q2a_strcpy(cl_anglespeedkey_kickmsg, DEFAULTCL_ANGLESPEEDKEY_KICKMSG);
        q2a_strcpy(lockoutmsg, DEFAULTLOCKOUTMSG);

        adminpassword[0] = 0;
        customServerCmd[0] = 0;
        customClientCmd[0] = 0;
        customClientCmdConnect[0] = 0;
        customServerCmdConnect[0] = 0;

        readCfgFiles();

        if(q2adminrunmode)
                {
                        loadLogList();
                }

        // setup zbot test strings
        srand( (unsigned)time( NULL ) );
        random(); random(); random(); random();
        zbot_teststring1[7] = zbot_teststring_test1[7] = '0' + (int)(9.9 * random());
        zbot_teststring1[8] = zbot_teststring_test1[8] = '0' + (int)(9.9 * random());
        zbot_teststring_test2[3] = '0' + (int)(9.9 * random());
        zbot_teststring_test2[4] = '0' + (int)(9.9 * random());
        zbot_testchar1 = '0' + (int)(9.9 * random());
        zbot_testchar2 = '0' + (int)(9.9 * random());

#ifdef __GNUC__
        loadtype = soloadlazy ? RTLD_LAZY : RTLD_NOW;
        sprintf(dllname, "%s/%s", moddir, DLLNAME);
        hdll = dlopen(dllname, loadtype);
#elif defined(WIN32)
        if(quake2dirsupport)
                {
                        sprintf(dllname, "%s/%s", moddir, DLLNAME);
                }
        else
                {
                        sprintf(dllname, "%s/%s", moddir, DLLNAMEMODDIR);
                }

        hdll = LoadLibrary(dllname);
#endif

        if(hdll == NULL)
                {
                        // try the baseq2 directory...
                        sprintf(dllname, "baseq2/%s", DLLNAME);

#ifdef __GNUC__
                        hdll = dlopen(dllname, loadtype);
#elif defined(WIN32)
                        hdll = LoadLibrary(dllname);
#endif

#ifdef __GNUC__
                        sprintf(dllname, "%s/%s", moddir, DLLNAME);
#elif defined(WIN32)
                        if(quake2dirsupport)
                                {
                                        sprintf(dllname, "%s/%s", moddir, DLLNAME);
                                }
                        else
                                {
                                        sprintf(dllname, "%s/%s", moddir, DLLNAMEMODDIR);
                                }
#endif

                        if(hdll == NULL)
                                {
                                        gi.dprintf ("Unable to load DLL %s.\n", dllname);
                                        return &globals;
                                }
                        else
                                {
                                        gi.dprintf ("Unable to load DLL %s, loading baseq2 DLL.\n", dllname);
                                }
                }

#ifdef __GNUC__
        getapi = (GAMEAPI *)dlsym(hdll, "GetGameAPI");
#elif defined(WIN32)
        getapi = (GAMEAPI *)GetProcAddress (hdll, "GetGameAPI");
#endif

        if(getapi == NULL)
                {
#ifdef __GNUC__
                        dlclose(hdll);
#elif defined(WIN32)
                        FreeLibrary(hdll);
#endif

                        gi.dprintf ("No \"GetGameApi\" entry in DLL %s.\n", dllname);
                        return &globals;
                }

        dllglobals = (*getapi)(import);
        dllloaded = TRUE;
        copyDllInfo();
        import->cprintf = gi.cprintf;

        if(q2adminrunmode)
                {
                        logEvent(LT_SERVERSTART, 0, NULL, NULL, 0, 0.0);
                }

        return &globals;
}

and the compilation here :

[powabanga@alarm ~]$ cd DDaynormandyFPS/
[powabanga@alarm DDaynormandyFPS]$ cd src
[powabanga@alarm src]$ls
-bash: $'ls\302': command not found
[powabanga@alarm src]$ ls
dday  q2admin-tsmod  q2pro  q2pro.config
[powabanga@alarm src]$ cd q2pro
[powabanga@alarm q2pro]$ ls
INSTALL.md  Makefile   doc             inc  q2pro     src
LICENSE     README.md  gameaarch64.so  man  q2proded  version.sh
[powabanga@alarm q2pro]$ cd ..
[powabanga@alarm src]$ cd ..
[powabanga@alarm DDaynormandyFPS]$ make
make -C src/q2pro CONFIG_FILE=../q2pro.config
make[1]: Entering directory '/home/powabanga/DDaynormandyFPS/src/q2pro'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/home/powabanga/DDaynormandyFPS/src/q2pro'
cp -a src/q2pro/q2pro ddaynormandy
cp -a src/q2pro/q2proded ddaynormandyded
make -C src/dday
make[1]: Entering directory '/home/powabanga/DDaynormandyFPS/src/dday'
make gameaarch64.real.so CFLAGS="-Dstricmp=strcasecmp -g"
make[2]: Entering directory '/home/powabanga/DDaynormandyFPS/src/dday'
make[2]: 'gameaarch64.real.so' is up to date.
make[2]: Leaving directory '/home/powabanga/DDaynormandyFPS/src/dday'
make[1]: Leaving directory '/home/powabanga/DDaynormandyFPS/src/dday'
cp -a src/dday/game?*.real.* dday/
make -C src/q2admin-tsmod
make[1]: Entering directory '/home/powabanga/DDaynormandyFPS/src/q2admin-tsmod'
gcc -std=gnu99 -O2 -fPIC -DARCH="aarch64" -DLINUX -DSTDC_HEADERS -I/usr/include   -c -o g_main.o g_main.c
g_main.c:51:14: error: missing binary operator before token "("
   51 | #elif define (__arm__) || defined (__aarch64__)
      |              ^
g_main.c:54:3: error: #error Unknown architecture
   54 |  #error Unknown architecture
      |   ^~~~~
g_main.c: In function 'GetGameAPI':
g_main.c:232:36: error: 'DLLNAME' undeclared (first use in this function)
  232 |  sprintf(dllname, "%s/%s", moddir, DLLNAME);
      |                                    ^~~~~~~
g_main.c:232:36: note: each undeclared identifier is reported only once for each function it appears in
make[1]: *** [<builtin>: g_main.o] Error 1
make[1]: Leaving directory '/home/powabanga/DDaynormandyFPS/src/q2admin-tsmod'
make: *** [Makefile:18: q2admin] Error 2
QwazyWabbitWOS commented 4 years ago

`` OK, now we have some clues. I have snipped out the irrelevancies and I am highlighting the details that tell us what is happening:

[snip]

[powabanga@alarm src]$ ls dday q2admin-tsmod q2pro q2pro.config [powabanga@alarm src]$ cd q2pro [powabanga@alarm q2pro]$ ls

This shows us that q2pro is expecting the game dll to have aarch64 in it:

INSTALL.md Makefile doc inc q2pro src LICENSE README.md gameaarch64.so man q2proded version.sh [snip]

NOTE: The q2pro game module is named gameaarch64.so This tells us we need to name q2admin with that architecture.

[snip]

make[1]: Entering directory '/home/powabanga/DDaynormandyFPS/src/dday' make gameaarch64.real.so CFLAGS="-Dstricmp=strcasecmp -g"

This shows dday is building correctly.

[snip]

make -C src/q2admin-tsmod make[1]: Entering directory '/home/powabanga/DDaynormandyFPS/src/q2admin-tsmod' gcc -std=gnu99 -O2 -fPIC -DARCH="aarch64" -DLINUX -DSTDC_HEADERS -I/usr/include -c -o g_main.o g_main.c g_main.c:51:14: error: missing binary operator before token "(" 51 | #elif define (arm) || defined (aarch64) | ^

WRONG WRONG WRONG You wrote define again, not defined. [snip]

But we now know that aarch64 is the correct name for the dll, now all we need to do is write the defines for gcc correctly. Copy this block and insert it into g_main.c ar line 51 to replace the corresponding block there: #elif defined __arm__ #define DLLNAME "gamearm.real.so" #elif defined __aarch64__ #define DLLNAME "gameaarch64.real.so"

It should look like this when you are done: 2020-05-03

I will push my changes to my repository and post a pull request to this repo but I don't know when spatulasnout will get around to pulling it here.