This is the baseline for allowing for C++ generation.

Now to hook it all up...
This commit is contained in:
2024-04-25 01:03:13 -04:00
parent bbecfcfd47
commit b8e02b9c83
10 changed files with 483 additions and 6 deletions
+9 -2
View File
@@ -51,11 +51,14 @@ extern GenerateFunctions generateYehatFunctions;
extern GenerateFunctions generateZoqFotPikFunctions;
extern GenerateFunctions generateZoqFotPikScoutFunctions;
extern GenerateFunctions *getGenerateCxxFunctions( void );
const GenerateFunctions *
getGenerateFunctions (BYTE Index)
getGenerateFunctions (STAR_DESC *const star, void **sup )
{
switch (Index)
*sup= 0;
switch (star->Index)
{
case SOL_DEFINED:
return &generateSolFunctions;
@@ -132,6 +135,10 @@ getGenerateFunctions (BYTE Index)
return &generateIlwrathFunctions;
default:
return &generateDefaultFunctions;
case CXX_DEFINED:
*sup= star->supplement;
return getGenerateCxxFunctions();
}
}
+2 -2
View File
@@ -8,7 +8,7 @@
extern "C" {
#endif
const GenerateFunctions *getGenerateFunctions (BYTE Index);
const GenerateFunctions *getGenerateFunctions (STAR_DESC *star, void **sup);
enum
{
@@ -60,7 +60,7 @@ enum
ANDROSYNTH_DEFINED,
MYCON_TRAP_DEFINED,
CUSTOM_DEFINED,
CXX_DEFINED,
};
#define UMGAH_DEFINED TALKING_PET_DEFINED
+166
View File
@@ -0,0 +1,166 @@
/*
* 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.
*/
#include "uqm/planets/generate.h"
/*
* XXX: Note that the way that defaults get called via C++ is a bit
* indirect and wonky. The genFunc C table calls into the C++
* wrappers which then call into the C++ object's vtable to these
* functions here... which then call back out to the C functions
* that would have been in the table. This does mean a bit more
* pointer chasing on each call... But I'm not really worried.
*
* Performance concerns aren't an issue as far as I'm concerned;
* after all -- Star Control 2 was a game that ran amazingly well
* on a 486 or Pentium. I played it just fine on a 90 MHz Pentium
* 1 with 32MiB of RAM (probably overkill on the RAM). My point
* is that a second layer of indirection and cache misses won't
* even be noticed, given how little this game should tax a
* modern CPU.
*
* As these functions are used to build a solar system, I think
* it only affects the "load time" for these systems -- and
* they're pretty easily loaded to begin with. And all of
* this indirection can go away once the planet handling at
* a higher level becomes C++ -- it can just call the vptrs
* directly.
*
*
* =====================================================================
*
* Right now I need a lot of glue C++ to keep things all together,
* but once I can start to move more of the core program over
* to C++; I'll be able to let this glue fall away. This code is
* an example of that kind of glue.
*/
namespace Planets ::detail:: Generate
{
Generator::~Generator()= default;
// All of the default C++ generator functions forward to the
// plain C default impls. The idea is that you derive your
// special generator from the C++ one, just filling in the
// details you need. It _should_, in practice, clean up
// the boilerplate in the various `generate/genXXX` files.
//
// The `GenerateBindToCXX_XYZ` functions just forward to
// the C++ generator parameter in question. I still have
// to figure out where to store/parameterize that generator
// object.
//
// I think I'll just add an extra parameter to the function.
//
// That parameter will be a function pointer that returns
// a pointer to `Planets::detail::Generate::exports::Generator`
// in question.
DefaultGenerator::~DefaultGenerator()= default;
void
DefaultGenerator::initNpcs( SolarSystem *const solarSys )
{
// This always returns true...
std::ignore= GenerateDefault_initNpcs( solarSys );
}
void
DefaultGenerator::reinitNpcs( SolarSystem *const solarSys )
{
// This always returns true...
std::ignore= GenerateDefault_reinitNpcs( solarSys );
}
void
DefaultGenerator::uninitNpcs( SolarSystem *const solarSys )
{
// This always returns true...
std::ignore= GenerateDefault_uninitNpcs( solarSys );
}
bool
DefaultGenerator::generatePlanets( SolarSystem *const solarSys )
{
return GenerateDefault_generatePlanets( solarSys );
}
bool
DefaultGenerator::generateMoons( SolarSystem *const solarSys, PLANET_DESC *const planet )
{
return GenerateDefault_generateMoons( solarSys, planet );
}
bool
DefaultGenerator::generateOrbital( SolarSystem *const solarSys, PLANET_DESC *const world )
{
return GenerateDefault_generateOrbital( solarSys, world );
}
bool
DefaultGenerator::generateName( SolarSystem *const solarSys, PLANET_DESC *const world )
{
return GenerateDefault_generateName( solarSys, world );
}
COUNT
DefaultGenerator::generateMinerals( SolarSystem *const solarSys, PLANET_DESC *const world,
const COUNT whichNode, NODE_INFO *const info )
{
return GenerateDefault_generateMinerals( solarSys, world, whichNode, info );
}
COUNT
DefaultGenerator::generateEnergy( SolarSystem *const solarSys, PLANET_DESC *const world,
const COUNT whichNode, NODE_INFO *const info )
{
return GenerateDefault_generateEnergy( solarSys, world, whichNode, info );
}
COUNT
DefaultGenerator::generateLife( SolarSystem *const solarSys, PLANET_DESC *const world,
const COUNT whichNode, NODE_INFO *const info )
{
return GenerateDefault_generateLife( solarSys, world, whichNode, info );
}
bool
DefaultGenerator::pickupMinerals( SolarSystem *const solarSys, PLANET_DESC *const world,
const COUNT whichNode )
{
return GenerateDefault_pickupMinerals( solarSys, world, whichNode );
}
bool
DefaultGenerator::pickupEnergy( SolarSystem *const solarSys, PLANET_DESC *const world,
const COUNT whichNode )
{
return GenerateDefault_pickupEnergy( solarSys, world, whichNode );
}
bool
DefaultGenerator::pickupLife( SolarSystem *const solarSys, PLANET_DESC *const world,
const COUNT whichNode )
{
return GenerateDefault_pickupLife( solarSys, world, whichNode );
}
}
+85
View File
@@ -113,6 +113,91 @@ struct GenerateFunctions {
};
#if defined(__cplusplus)
} // extern "C"
namespace Planets ::detail:: Generate_m
{
inline namespace exports
{
class Generator;
class DefaultGenerator;
using SolarSystem= SOLARSYS_STATE;
}
class exports::Generator
{
public:
virtual ~Generator()= 0;
virtual void initNpcs( SolarSystem *solarSys )= 0;
virtual void reinitNpcs( SolarSystem *solarSys )= 0;
virtual void uninitNpcs( SolarSystem *solarSys )= 0;
virtual bool generatePlanets( SolarSystem *solarSys )= 0;
virtual bool generateMoons( SolarSystem *solarSys,
PLANET_DESC *planet )= 0;
virtual bool generateOrbital( SolarSystem *solarSys,
PLANET_DESC *world)= 0;
virtual bool generateName( const SolarSystem *,
const PLANET_DESC *world)= 0;
// The following functions return the number of objects being generated
// (or the index of the current object in some cases)
virtual COUNT generateMinerals( const SolarSystem *,
const PLANET_DESC *world, COUNT whichNode, NODE_INFO * )= 0;
virtual COUNT generateEnergy( const SolarSystem *,
const PLANET_DESC *world, COUNT whichNode, NODE_INFO * )= 0;
virtual COUNT generateLife( const SolarSystem *,
const PLANET_DESC *world, COUNT whichNode, NODE_INFO * )= 0;
// The following functions return true if the node should be removed
// from the surface, i.e. picked up.
virtual bool pickupMinerals( SolarSystem *solarSys,
PLANET_DESC *world, COUNT whichNode )= 0;
virtual bool pickupEnergy( SolarSystem *solarSys,
PLANET_DESC *world, COUNT whichNode )= 0;
virtual bool pickupLife( SolarSystem *solarSys,
PLANET_DESC *world, COUNT whichNode )= 0;
};
class exports::DefaultGenerator
: virtual public Generator
{
public:
~DefaultGenerator() override;
void initNpcs(SolarSystem *solarSys) override;
void reinitNpcs(SolarSystem *solarSys) override;
void uninitNpcs(SolarSystem *solarSys) override;
bool generatePlanets(SolarSystem *solarSys) override;
bool generateMoons(SolarSystem *solarSys,
PLANET_DESC *planet) override;
bool generateOrbital(SolarSystem *solarSys,
PLANET_DESC *world) override;
bool generateName(const SolarSystem *,
const PLANET_DESC *world) override;
// The following functions return the number of objects being generated
// (or the index of the current object in some cases)
COUNT generateMinerals(const SolarSystem *,
const PLANET_DESC *world, COUNT whichNode, NODE_INFO *) override;
COUNT generateEnergy(const SolarSystem *,
const PLANET_DESC *world, COUNT whichNode, NODE_INFO *) override;
COUNT generateLife(const SolarSystem *,
const PLANET_DESC *world, COUNT whichNode, NODE_INFO *) override;
// The following functions return true if the node should be removed
// from the surface, i.e. picked up.
bool pickupMinerals(SolarSystem *solarSys,
PLANET_DESC *world, COUNT whichNode) override;
bool pickupEnergy(SolarSystem *solarSys,
PLANET_DESC *world, COUNT whichNode) override;
bool pickupLife(SolarSystem *solarSys,
PLANET_DESC *world, COUNT whichNode) override;
};
}
namespace Planets::inline exports::inline Generate_m
{
using namespace detail::Generate_m::exports;
}
#endif
+1
View File
@@ -4,3 +4,4 @@ uqm_CFILES="gendefault.c genand.c genburv.c genchmmr.c gencol.c gendru.c
genthrad.c gentrap.c genutw.c genvault.c genvux.c genwreck.c
genyeh.c genzfpscout.c genzoq.c"
uqm_HFILES="genall.h gendefault.h"
uqm_CXXFILES="cxx-generator.cpp"
@@ -0,0 +1,174 @@
/*
* 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.
*/
#include "genall.h"
#include "../planets.h"
#include "../lander.h"
#include "../../encount.h"
#include "../../gamestr.h"
#include "../../globdata.h"
#include "../../grpinfo.h"
#include "../../races.h"
#include "../../state.h"
#include "../../sounds.h"
#include "libs/mathlib.h"
/*
* These bindings allow for the legacy C code to call into "GenerateFunctions" objects
* and have those calls mapped into the C++ virtual table driven object which handles
* the actual generation.
*
* This permits me to slowly migrate over the legacy C generators into C++. And to
* mess around with new C++-only generators.
*
* One nice advantage of this is that any C++ generator can inherit from another to
* specialize it. This permits `Default`ed forms to just use the base C++ defaulting
* class, using normal C++ `override` semantics.
*
*
* =====================================================================
*
* Right now I need a lot of glue C++ to keep things all together,
* but once I can start to move more of the core program over
* to C++; I'll be able to let this glue fall away. This code is
* an example of that kind of glue.
*/
namespace Planets ::detail:: CxxGeneratorBindings_m
{
namespace
{
auto &
getGenerator( const SolarSystem *const solarSys )
{
return *static_cast< Generator * >( solarSys->genSupplement );
}
bool
initNpcs( SolarSystem *const solarSys )
{
getGenerator( solarSys ).initNpcs( solarSys );
return true;
}
bool
reinitNpcs( SolarSystem *const solarSys )
{
getGenerator( solarSys ).reinitNpcs( solarSys );
return true;
}
bool
uninitNpcs( SolarSystem *const solarSys )
{
getGenerator( solarSys ).uninitNpcs( solarSys );
return true;
}
bool
generatePlanets( SolarSystem *const solarSys )
{
return getGenerator( solarSys ).generatePlanets( solarSys );
}
bool
generateMoons( SolarSystem *const solarSys, PLANET_DESC *const planet )
{
return getGenerator( solarSys ).generateMoons( solarSys, planet );
}
bool
generateName( const SolarSystem *const solarSys, const PLANET_DESC *const world )
{
return getGenerator( solarSys ).generateName( solarSys, world );
}
bool
generateOrbital( SolarSystem *const solarSys, PLANET_DESC *const world )
{
return getGenerator( solarSys ).generateOrbital( solarSys, world );
}
COUNT
generateMinerals( const SolarSystem *const solarSys,
const PLANET_DESC *const world, const COUNT whichNode, NODE_INFO *const info )
{
return getGenerator( solarSys ).generateMinerals( solarSys, world, whichNode, info );
}
bool
pickupMinerals( SolarSystem *const solarSys, PLANET_DESC *const world,
const COUNT whichNode )
{
return getGenerator( solarSys ).pickupMinerals( solarSys, world, whichNode );
}
COUNT
generateEnergy( const SolarSystem *const solarSys,
const PLANET_DESC *const world, const COUNT whichNode,
NODE_INFO *const info )
{
return getGenerator( solarSys ).generateEnergy( solarSys, world, whichNode, info );
}
bool
pickupEnergy( SolarSystem *const solarSys, PLANET_DESC *const world,
const COUNT whichNode )
{
return getGenerator( solarSys ).pickupEnergy( solarSys, world, whichNode );
}
COUNT
generateLife( const SolarSystem *const solarSys,
const PLANET_DESC *const world, const COUNT whichNode, NODE_INFO *const info )
{
return getGenerator( solarSys ).generateLife( solarSys, world, whichNode, info );
}
bool
pickupLife( SolarSystem *const solarSys, PLANET_DESC *const world,
const COUNT whichNode )
{
return getGenerator( solarSys ).pickupLife( solarSys, world, whichNode );
}
const GenerateFunctions funcs = {
/* .initNpcs = */ initNpcs,
/* .reinitNpcs = */ reinitNpcs,
/* .uninitNpcs = */ uninitNpcs,
/* .generatePlanets = */ generatePlanets,
/* .generateMoons = */ generateMoons,
/* .generateName = */ generateName,
/* .generateOrbital = */ generateOrbital,
/* .generateMinerals = */ generateMinerals,
/* .generateEnergy = */ generateEnergy,
/* .generateLife = */ generateLife,
/* .pickupMinerals = */ pickupMinerals,
/* .pickupEnergy = */ pickupEnergy,
/* .pickupLife = */ pickupLife,
};
}
}
extern "C"
{
const GenerateFunctions *getGenerateCxxFunctions( void )
{
return &Planets::detail:: CxxGeneratorBindings_m::funcs;
}
}
@@ -0,0 +1,35 @@
/*
* 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.
*/
#ifndef GENDEFAULT_H
#define GENDEFAULT_H
#include "types.h"
#include "../planets.h"
#include "libs/compiler.h"
#if defined(__cplusplus)
extern "C" {
#endif
extern const GenerateFunctions *getGenerateCxxFunctions();
#if defined(__cplusplus)
}
#endif
#endif /* GENDEFAULT_H */
+9
View File
@@ -130,6 +130,8 @@ struct star_desc
BYTE Index;
BYTE Prefix;
BYTE Postfix;
void *supplement; // The CXX builder's pointer gets put here.
};
struct node_info
@@ -249,6 +251,13 @@ struct solarsys_state
BOOLEAN InOrbit;
// Set to TRUE when player hits a world in an inner system
// Homeworld encounters count as 'in orbit'
// This points to the actual C++ generator type, for C++
// implemented generators.
//
// Since everything else probably ignores it... we can probably
// avoid setting it to `nullptr`, for now...
void *genSupplement;
};
extern SOLARSYS_STATE *pSolarSysState;
+1 -1
View File
@@ -1735,7 +1735,7 @@ ExploreSolarSys (void)
memset (pSolarSysState, 0, sizeof (*pSolarSysState));
SolarSysState.genFuncs = getGenerateFunctions (CurStarDescPtr->Index);
SolarSysState.genFuncs = getGenerateFunctions (CurStarDescPtr, &SolarSysState.genSupplement);
InitSolarSys ();
SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE);
+1 -1
View File
@@ -645,7 +645,7 @@ starRecurse (STAR_DESC *star, void *arg)
SolarSysState.SunDesc[0].location.x = 0;
SolarSysState.SunDesc[0].location.y = 0;
//SolarSysState.SunDesc[0].radius = MIN_ZOOM_RADIUS;
SolarSysState.genFuncs = getGenerateFunctions (star->Index);
SolarSysState.genFuncs = getGenerateFunctions (star, &SolarSysState.genSupplement);
pSolarSysState = &SolarSysState;
(*SolarSysState.genFuncs->generatePlanets) (&SolarSysState);