I have the following memory layout:
typedef struct map_obj_s
{
thing_t** things;
linedef_t** linedefs;
sidedef_t** sidedefs;
vertex_t** vertices;
segment_t** segments;
ssector_t** subsectors;
node_t* node_tree;
sector_t** sectors;
int32_t lump_counts[ MAP_LUMP_COUNT ];
}
map_obj_t;
The problem is that I'm basically repeating the exact same processes for each of these data types, here, with the exception of the node_tree and lump_counts members.
Here's what the result is with the repetition:
map_obj_t* Map_Read( lumpbuffer_t* map_lump )
{
int32_t lump_counts[ MAP_LUMP_COUNT ];
__GetLumpCounts( map_lump, lump_counts );
// laziness
const lumpinfo_t* const mlumps = map_lump->lumps;
FILE* mapfile = Wad_GetFilePtr();
map_obj_t* map = Mem_Alloc( 1, sizeof( map_obj_t ) );
// allocate buffers
map->things = Mem_Alloc( lump_counts[ LUMP_THINGS ], sizeof( thing_t* ) );
map->linedefs = Mem_Alloc( lump_counts[ LUMP_LINEDEFS ], sizeof( linedef_t* ) );
map->sidedefs = Mem_Alloc( lump_counts[ LUMP_SIDEDEFS ], sizeof( sidedef_t* ) );
map->vertices = Mem_Alloc( lump_counts[ LUMP_VERTICES ], sizeof( vertex_t* ) );
map->segments = Mem_Alloc( lump_counts[ LUMP_SEGMENTS ], sizeof( segment_t* ) );
map->subsectors = Mem_Alloc( lump_counts[ LUMP_SSECTORS ], sizeof( ssector_t* ) );
map->node_tree = Mem_Alloc( lump_counts[ LUMP_NODES ], sizeof( node_t ) );
map->sectors = Mem_Alloc( lump_counts[ LUMP_SECTORS ], sizeof( sector_t* ) );
// parse things
PARSE_LUMP( mapfile,
map->things,
sizeof( thing_t ),
lump_counts[ LUMP_THINGS ],
mlumps,
LUMP_THINGS );
// parse linedefs
PARSE_LUMP( mapfile,
map->linedefs,
sizeof( linedef_t ),
lump_counts[ LUMP_LINEDEFS ],
mlumps,
LUMP_LINEDEFS );
// parse sidedefs
PARSE_LUMP( mapfile,
map->sidedefs,
sizeof( sidedef_t ),
lump_counts[ LUMP_SIDEDEFS ],
mlumps,
LUMP_SIDEDEFS );
// parse vertices
PARSE_LUMP( mapfile,
map->vertices,
sizeof( vertex_t ),
lump_counts[ LUMP_VERTICES ],
mlumps,
LUMP_VERTICES );
// parse segments
PARSE_LUMP( mapfile,
map->segments,
sizeof( vertex_t ),
lump_counts[ LUMP_SEGMENTS ],
mlumps,
LUMP_SEGMENTS );
// parse subsectors
PARSE_LUMP( mapfile,
map->subsectors,
sizeof( ssector_t ),
lump_counts[ LUMP_SSECTORS ],
mlumps,
LUMP_SSECTORS );
// parse nodes
PARSE_LUMP( mapfile,
map->node_tree,
sizeof( node_t ),
lump_counts[ LUMP_NODES ],
mlumps,
LUMP_NODES );
// parse sectors
PARSE_LUMP( mapfile,
map->sectors,
sizeof( sector_t ),
lump_counts[ LUMP_SECTORS ],
mlumps,
LUMP_SECTORS );
memcpy( map->lump_counts, lump_counts, sizeof( int32_t ) * MAP_LUMP_COUNT );
return map;
}
And the PARSE_LUMP macro:
#define PARSE_LUMP( wad_fileptr, data, data_size, count, lumps_ptr, lump_type ) \
do { \
\
Mem_AllocBuffer( ( generic_buffer_t ) ( data ), ( data_size ), ( count ) ); \
\
fseek( ( wad_fileptr ), \
( lumps_ptr )[ ( lump_type ) ].address_offset, \
SEEK_SET ); \
\
for ( int32_t i = 0; i < count; ++i ) \
{ \
fread( ( data )[ i ], ( data_size ), 1, ( wad_fileptr ) ); \
} \
\
} while( 0 ) \
The Point
Is it wrong of me to want to abstract this out? It's readable, sure, but the idea of it consists of a lot of code. I'm not an awesome C programmer (this is my first real/serious project with it), but I have experience with C++. On the C++ side this would be easy with templates, but in C I'm limited to void* and macro functions. Serialization seems like a possibility, but the issue with all of these seems to point to the fact that I have pointers-to-pointers for my buffers. Is there any sense of going about this, or am I just wasting my time even bothering with it? Not to mention the fact that I'm even sure of how to dynamically allocate memory from a serialized struct.
What you have works I guess, but I think there's no reason to allocate and then read each set of lumps separatly, if you know the number of lumps and their sizes in advance then you could allocate all the memory you will need and read the whole file in one go and then you'd just set each pointer to the start (offset) of its respective set of lumps, something like this:
//first set of lumps
map->things = map_data;
//increment pointer
map_data += lump_counts[ LUMP_THINGS ] * sizeof( thing_t );
//second set of lumps
map->linedefs = map_data;
map_data += lump_counts[ LUMP_LINEDEFS ] * sizeof( linedefs_t );
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With