2018-01-04 02:51:20 +00:00
|
|
|
/*
|
2018-02-13 01:28:37 +00:00
|
|
|
* objstore.c
|
2018-02-13 03:15:20 +00:00
|
|
|
*
|
|
|
|
* The code here allows us to work with the object store, which is an
|
|
|
|
* entity that allows us to toss all of our binary data needs into a big
|
|
|
|
* glob of stuff that we can unpack and use at runtime. Examples of such
|
|
|
|
* data are bitmap fonts, ROM data, etc.
|
2018-01-04 02:51:20 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <zlib.h>
|
|
|
|
|
|
|
|
#include "objstore.h"
|
|
|
|
#include "objstore_data.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is data that we expect to find in the store_data variable that
|
|
|
|
* is defined in objstore_data.h.
|
|
|
|
*/
|
|
|
|
#define HEADER_DATA "hope"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Our object store. Just a simple struct that we pull data out from.
|
|
|
|
*/
|
|
|
|
static objstore store;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function will set up the store variable so that it contains
|
|
|
|
* useful information rather than garbage data from the stack. It does
|
|
|
|
* so with a simply memcpy from store_data directly into store, such
|
|
|
|
* that the store data itself can be aligned for access.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
objstore_init()
|
|
|
|
{
|
2018-01-04 03:49:26 +00:00
|
|
|
// Oh, you're calling this again? Cool, but let's bail before we do
|
|
|
|
// anything else.
|
|
|
|
if (objstore_ready()) {
|
|
|
|
return OK;
|
|
|
|
}
|
2018-01-04 02:51:20 +00:00
|
|
|
|
|
|
|
// We want to input some bad header data and compare with what
|
|
|
|
// eventually should get put into there by memcmp.
|
|
|
|
store.header[0] = 'h';
|
|
|
|
store.header[1] = 'e';
|
|
|
|
store.header[2] = 'y';
|
|
|
|
store.header[3] = '\0';
|
|
|
|
|
|
|
|
memcpy(&store, store_data, sizeof(store));
|
|
|
|
|
2018-01-04 03:49:26 +00:00
|
|
|
// If the copy didn't work out somehow...
|
|
|
|
if (!objstore_ready()) {
|
|
|
|
log_critical("Object store initialization failed with bad data");
|
|
|
|
return ERR_BADFILE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
2018-01-07 22:30:33 +00:00
|
|
|
/*
|
|
|
|
* This will empty out the store, which is not very _practically_
|
|
|
|
* useful, but is a bit useful when testing.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
objstore_clear()
|
|
|
|
{
|
|
|
|
memset(&store, 0, sizeof(store));
|
|
|
|
}
|
|
|
|
|
2018-01-07 22:07:29 +00:00
|
|
|
/*
|
|
|
|
* Return true if the object store is ready to be used.
|
|
|
|
*/
|
2018-01-04 03:49:26 +00:00
|
|
|
bool
|
|
|
|
objstore_ready()
|
|
|
|
{
|
|
|
|
int cmp;
|
|
|
|
|
2018-01-04 02:51:20 +00:00
|
|
|
// Test if the header field data is exactly equivalent to that
|
|
|
|
// defined in HEADER_DATA. Note we use memcmp(), because the header
|
|
|
|
// field is an array of just 4 bytes; strcmp() and strncmp() have an
|
|
|
|
// expectation that both pointers will be directed at NUL-terminated
|
|
|
|
// strings, which is _not_ the case for store.header (but,
|
|
|
|
// incidentally, _is_ the case for HEADER_DATA!).
|
|
|
|
cmp = memcmp(store.header, HEADER_DATA,
|
|
|
|
sizeof(store.header) / sizeof(char));
|
|
|
|
|
2018-01-04 03:49:26 +00:00
|
|
|
return cmp == 0;
|
2018-01-04 02:51:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Something to simplify the very simple getter functions we use for
|
|
|
|
* getting data from the object store.
|
|
|
|
*/
|
|
|
|
#define OBJSTORE_DEFN(x) \
|
|
|
|
const vm_8bit *objstore_##x() { return store.x; }
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Note we have an extra semicolon on the end... this is mostly to avoid
|
|
|
|
* screwing up my indent, to be honest. But C will ignore the
|
|
|
|
* semicolons, so all is well.
|
|
|
|
*/
|
2018-01-09 21:56:21 +00:00
|
|
|
OBJSTORE_DEFN(apple2_peripheral_rom); // ignore docblock
|
|
|
|
OBJSTORE_DEFN(apple2_sys_rom); // ignore docblock
|
|
|
|
OBJSTORE_DEFN(apple2_sysfont); // ignore docblock
|
2018-01-24 20:26:28 +00:00
|
|
|
OBJSTORE_DEFN(apple2_invfont); // ignore docblock
|