Starting an engine

I'm starting to write my own engine, and I'm not sure if I'm going the right way about it. So far, I've done a bit of work on core.dll, and i'd like to know if there's any stupid mistakes that I've done.. any tips or hints, and so on..

Since the engine is going to be dynamically loaded DLL's, I have another question: Say I have a sound.dll which needs to call the core.dll.. how do I handle this? sound.dll is loaded by core.dll, and core.dll is loaded by the main program. The main program is the one that gets the addresses of the functions in core.dll. How do I set this all up so that the main program can call the functions in any of these dll's directly, and so that sound.dll can call functions in core.dll? I hope I'm not being too vague here :)

Here's the source so far:

--- core.hpp ---

// Copyright 2000 by Kevin Lang - All Rights Reserved.
// Core.hpp - Main STEngine functions:

#ifndef _STENGINE_CORE_B06900C8_5EF4_4c1f_BEC6_35048B7A6A80
#define _STENGINE_CORE_B06900C8_5EF4_4c1f_BEC6_35048B7A6A80

// Global includes
#include
#include
#include

// Global defines
#define STENGINE_VERSION "0.01"
#define STENGINE_COMPILE_DATE "6 January, 2000"

#define ST_OK 0
#define ST_ERROR 1
#define ST_OUTOFMEMORY 2
#define ST_INVALIDCALL 4
#define ST_INVALIDPOINTER 8
#define ST_CORE_EMERGENCYEXIT 32768

// Define the method with which we declare functions to be exportable from our shared library
#ifdef _WIN32
#define ST_EXPORT __declspec( dllexport )
#endif

// Global variables
int MemAllocated = 0; // Used by the memory functions to track allocated memory

// Functions are declared here

// Initialize the engine
int ST_EXPORT ST_CoreInit(void);
// Shut down the engine
int ST_EXPORT ST_CoreExit(void);
// Return the amount of memory allocated by functions which have used the core memory
// allocating functions (typically, any of the engine components.. the game code cau use these
// functions too, of course.
int ST_EXPORT ST_ReturnMemAllocated(void);
// Allocate memory
void ST_EXPORT * ST_AllocateMemory(size_t n);
// Free memory
void ST_EXPORT ST_FreeMemory(void *n);
// This function is to be called when something bad has occurred and the engine must be shut down.
void ST_EXPORT _CoreException(int reason);


#endif /* End _STENGINE_CORE_B06900C8_5EF4_4c1f_BEC6_35048B7A6A80 */


--- core.cpp ---

// Copyright 2000 by Kevin Lang - All Rights Reserved.
// Core.cpp - Main STEngine functions:

// Include files
#include "core.hpp"

// Functions follow

// int ST_EXPORT ST_ReturnMemAllocated(void)
// Return the amount of memory allocated by functions which have used the core memory
// allocating functions (typically, any of the engine components.. the game code cau use these
// functions too, of course.

// Memory functions use a linked list to track memory allocations.
// Here's how it works:
// typedef struct
// {
// void * mem_ptr;
// size_t size;
// _ST_MEM_LNKLIST *previous;
// _ST_MEM_LNKLIST *next;
// } _ST_MEM_LNKLIST
//
// Everytime memory is allocated, a new _ST_MEM_LNKLIST is added to the linked list, and a copy of
// the pointer is stored, along with the size of the block that it points to. Everytime memory is
// freed, the linked list is searched for the pointer. If it can't be found, ST_ERROR is returned,
// otherwise ST_OK is returned. Then the _ST_MEM_LNKLIST is deleted from the linked list.
// Of course, memory used to store the linked list itself isn't counted under MemAllocated.

typedef struct _ST_MEM_LNKLIST
{
void *mem_ptr;
size_t size;
struct _ST_MEM_LNKLIST *previous;
struct _ST_MEM_LNKLIST *next;
} _ST_MEM_LNKLIST;

_ST_MEM_LNKLIST *memLinkList=NULL;

int ST_EXPORT ST_ReturnMemAllocated(void)
{
return MemAllocated;
}

// Allocate memory
void ST_EXPORT * ST_AllocateMemory(size_t n)
{
void *temp=NULL;
temp=malloc(n);
if (temp!=NULL)
{
MemAllocated+=n;
// We'll also zero-out the memory, just to clear out any junk
memset(temp,0,n);
}
// Now we save the info in the _ST_MEM_LNKLIST linked list structure
// First, we must seek to the end of the list:
while (memLinkList->next)
{
memLinkList=memLinkList->next;
}
// We're at the end of the list, now allocate a new _ST_MEM_LNKLIST structure:
memLinkList->next=(_ST_MEM_LNKLIST *)malloc(sizeof(_ST_MEM_LNKLIST));
if (!memLinkList->next)
{
// We must abort, because the memory could not be allocated.
// We abort here and not before because, say, not being able to allocate memory for a
// very large image or something may not be critical, but if we can't even allocate
// memory for a _ST_MEM_LNKLIST struct, well we're screwed...
_CoreException(ST_OUTOFMEMORY);
}
// We shouldn't be here unless the allocation was a success, so now it's time to initialize
// the values of our new block:
memLinkList->next->next=NULL;
memLinkList->next->previous=memLinkList;
memLinkList->next->mem_ptr=temp;
memLinkList->next->size=n;
// There, we're done.
return temp;
}

// Free memory
void ST_EXPORT ST_FreeMemory(void *n)
{
void *temp=NULL;
_ST_MEM_LNKLIST *lnkTemp=NULL;
if (n!=NULL)
{
free(n);
}
// Now we must delete the info in the _ST_MEM_LNKLIST linked list structure.
// First, we must seek to the beginning of the list:
while (memLinkList->previous)
{
memLinkList=memLinkList->previous;
}
// We're at the beginning of the list, now we start heading back to the end of the list
// searching for our void *n pointer in the linked list.
while (memLinkList->next)
{
memLinkList=memLinkList->next; // Traverse forward through the list
// compare pointers
if (memLinkList->mem_ptr==n)
{
// If they match, we set temp
temp=n;
}
}
// Now we have to see if we ever found it:
if (!temp)
{
// Temp would still be NULL if we never found a match, so that means we were given an
// invalid pointer, so we must abort:
_CoreException((ST_INVALIDCALL|ST_INVALIDPOINTER));
}
// We're still here only if we found our block. Now we can take steps to clear out our info:
// First, we already freed our block of memory before, so we just set the pointer to NULL:
memLinkList->mem_ptr=NULL;
// Decrease our memory allocated count and set size to zero:
MemAllocated-=memLinkList->size;
memLinkList->size=0;
// Now, we're about to destroy this _ST_MEM_LNKLIST structure, so we have to traverse to
// another one:
if (memLinkList->previous)
{
memLinkList=memLinkList->previous;
// Before we free it, we see if there's a block beyond the next:
if (memLinkList->next->next)
{
// If there is, we set its "previous" pointer to point to us:
memLinkList->next->next->previous=memLinkList;
// We store its position in our temp pointer:
lnkTemp=memLinkList->next->next;
}
free(memLinkList->next);
memLinkList->next=NULL;
// If there was a block beyond the next, then we set our "next" pointer to point to it:
if (lnkTemp)
{
memLinkList->next=lnkTemp;
}
}
else if (memLinkList->next && lnkTemp==NULL) // We check against NULL so we don't free a block twice by accident
{
memLinkList=memLinkList->next;
// Before we free it, we see if there's a block before the previous:
if (memLinkList->previous->previous)
{
// If there is, we set its "next" pointer to point to us:
memLinkList->previous->previous->next=memLinkList;
// We store its position in our temp pointer:
lnkTemp=memLinkList->previous->previous;
}
free(memLinkList->previous);
memLinkList->previous=NULL;
// If there was a block before the previous, then we set our "previous" pointer to point to it:
if (lnkTemp)
{
memLinkList->previous=lnkTemp;
}
}
// If neither were valid, then we stay put. We don't want to destroy our last block so we
// just leave it cleared as it is.
// That's it.
}

// Initialize the engine
int ST_EXPORT ST_CoreInit(void)
{
// Initialize our linked list for memory tracking
memLinkList=(_ST_MEM_LNKLIST *)malloc(sizeof(_ST_MEM_LNKLIST));
if (!memLinkList)
{
return ST_OUTOFMEMORY;
}
// Initialize the first block
memLinkList->mem_ptr=NULL;
memLinkList->next=NULL;
memLinkList->previous=NULL;
memLinkList->size=0;

// We're done
return ST_OK;
}

// Shut down the engine
int ST_EXPORT ST_CoreExit(void)
{
// *** Free all memory ***
// Traverse to the end of the linked list
while (memLinkList->next)
{
memLinkList=memLinkList->next;
}
// Now start freeing stuff, seeking backwards to the first block
do
{
// If there's memory allocated here, free it.
if (memLinkList->mem_ptr)
{
free(memLinkList->mem_ptr);
memLinkList->mem_ptr=NULL;
MemAllocated-=memLinkList->size;
memLinkList->size=0;
}
// Now destroy the actual _ST_MEM_LNKLIST struct
if (memLinkList->previous)
{
memLinkList=memLinkList->previous;
free(memLinkList->next);
memLinkList->next=NULL;
}
} while (memLinkList->previous);
// The first block should never actually hold any info about allocated memory, but we'll check
// just in case
if (memLinkList->mem_ptr)
{
free(memLinkList->mem_ptr);
memLinkList->mem_ptr=NULL;
MemAllocated-=memLinkList->size;
memLinkList->size=0;
}
// Finally, we destroy the first block (the last one remaining):
free(memLinkList);
memLinkList=NULL;

// We're done
return ST_OK;
}

// This function is to be called when something bad has occurred and the engine must be shut down.
void ST_EXPORT _CoreException(int reason)
{
if (reason!=ST_CORE_EMERGENCYEXIT)
{
ST_CoreExit();
}

// We end up here if an emergency exit must be issued:
// TODO: Place emergency exit code here.
}



Comments

  • You should pass a list of addresses to the loaded dll, then it can use it to access functinos.


Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories