Exemple #1
0
	/**
	 * Destroy a placeholder. Mark this placeholder as free
	 * and store the index in the pool of free placeholders.
	 * @param index The placeholder handle.
	 * @return Status code.
	 */
	int ResourceArray::_maDestroyPlaceholder(unsigned index) {
		// The handle must be a dynamic placeholder.
		if (!(index & DYNAMIC_PLACEHOLDER_BIT)) {
			// TODO: Use MYASSERT_IF_PANICS_ENABLED when
			// conditional panics are to be used.
			BIG_PHAT_ERROR(ERR_RES_PLACEHOLDER_NOT_DYNAMIC);
			return -2;
		}

		// Get the index into the dynamic resource array.
		unsigned i = index & (~DYNAMIC_PLACEHOLDER_BIT);
		TESTINDEX(i, mDynResSize);

		// The placeholder must not have been destroyed.
		if (RT_NIL == mDynResTypes[i])
		{
			// TODO: Use MYASSERT_IF_PANICS_ENABLED when
			// conditional panics are to be used.
			BIG_PHAT_ERROR(ERR_RES_PLACEHOLDER_ALREADY_DESTROYED);
			return -2;
		}

		// Set the handle type to RT_NIL. This marks the
		// placeholder as destroyed.
		mDynResTypes[i] = RT_NIL;

		// Put handle into the pool.

		// Create or expand the pool as needed.
		if (0 == mDynResPoolCapacity) {
			// Create the initial pool.
			mDynResPoolCapacity = 2;
			mDynResPool = new unsigned[mDynResPoolCapacity];
			MYASSERT(mDynResPool != NULL, ERR_OOM);
		}
		else if (mDynResPoolSize + 1 > mDynResPoolCapacity) {
			// Expand the pool.
			unsigned* oldDynResPool = mDynResPool;
			mDynResPool = new unsigned[mDynResPoolCapacity * 2];
			MYASSERT(mDynResPool != NULL, ERR_OOM);

			// Copy from old to new and delete old.
			memcpy(
				mDynResPool,
				oldDynResPool,
				mDynResPoolCapacity * sizeof(unsigned));
			delete []oldDynResPool;

			// Set new capacity.
			mDynResPoolCapacity = mDynResPoolCapacity * 2;
		}

		// Increment pool size.
		++mDynResPoolSize;

		// Add free handle index last in array (push to stack).
		mDynResPool[mDynResPoolSize - 1] = index;

		return RES_OK;
	}
Exemple #2
0
/**
* /return The newly created Data Section as a Direct ByteBuffer object
*/
static void nativeRun(JNIEnv* env, jobject jthis)
{
	SYSLOG("nativeRun");

	Base::gSyscall->setJNIEnvironment(env, jthis);

	while(1)
	{
		Core::Run2(gCore);

		SYSLOG("Runtime yielded!");

		// Check if we should load a resource as a program/resource combfile
		int reloadHandle = Base::gSyscall->getReloadHandle();
		if (0 != reloadHandle)
		{
			SYSLOG("Program is loading from handle");

			Base::Stream* stream =
				Base::gSyscall->resources.extract_RT_BINARY(reloadHandle);

			bool res = Core::LoadVMApp(gCore, *stream);

			delete stream;

			if (!res)
			{
				BIG_PHAT_ERROR(ERR_PROGRAM_LOAD_FAILED);
			}

			Base::gSyscall->setReloadHandle(0);
		}
		// Check if we should reload the initial program and resource file
		else if (Base::gSyscall->isReloading())
		{
			SYSLOG("Program is reloading! 1");

			Base::gSyscall->setReloading(false);

			SYSLOG("Program is reloading! 2");

			jclass cls = env->GetObjectClass(jthis);
			jmethodID methodID = env->GetMethodID(cls, "loadProgram", "()Z");
			if (methodID == 0) return;
			jboolean res = env->CallBooleanMethod(jthis, methodID);

			SYSLOG("Program is reloading! 3");

			if (!res)
			{
				BIG_PHAT_ERROR(ERR_PROGRAM_LOAD_FAILED);
			}

			__android_log_write(ANDROID_LOG_INFO,"JNI","Program is reloading! 4");
		}
	}
}
Exemple #3
0
	void* ResourceArray::_extract(unsigned index, byte R) {
		void **res = mRes;
		byte *types = mResTypes;
		if(index&DYNAMIC_PLACEHOLDER_BIT) {
			res = mDynRes;
			types = mDynResTypes;
			index = index&(~DYNAMIC_PLACEHOLDER_BIT);
			TESTINDEX(index, mDynResSize);
		} else {
			TESTINDEX(index, mResSize);
		}

		if(types[index] != R) {
			BIG_PHAT_ERROR(ERR_RES_INVALID_TYPE);
		}

#ifdef RESOURCE_MEMORY_LIMIT
		switch(types[index]) {
#define CASE_SUBMEM(R, T, D) case R: mResmem -= size_##R((T*)res[index]); break;
			TYPES(CASE_SUBMEM);
		}
		if(mResmem > mResmemMax) {
			DEBIG_PHAT_ERROR;
		}
#endif	//RESOURCE_MEMORY_LIMIT

		void* temp = res[index];
		res[index] = NULL;
		types[index] = RT_PLACEHOLDER;
		return temp;
	}
Exemple #4
0
	/**
	 * Gets a pointer to the data for the given handle.
	 * @param index The resource handle.
	 * @param R The resource type.
	 * @return a pointer to the data for the given handle.
	 */
	void* ResourceArray::_get(unsigned index, byte R) {
		void **res = mRes;
		byte *types = mResTypes;
		if(index&DYNAMIC_PLACEHOLDER_BIT) {
			res = mDynRes;
			types = mDynResTypes;
			index = index&(~DYNAMIC_PLACEHOLDER_BIT);
			TESTINDEX(index, mDynResSize);
		} else {
			TESTINDEX(index, mResSize);
		}

		if(types[index] != R) {
			BIG_PHAT_ERROR(ERR_RES_INVALID_TYPE);
		}
		return res[index];
	}
Exemple #5
0
	/**
	 * Add a resource.
	 * @param index Resource index.
	 * @param obj Pointer to object data.
	 * @param type Resource type.
	 */
	int ResourceArray::_add(unsigned index, void* obj, byte type) {
		void **res = mRes;
		byte *types = mResTypes;
		if(index&DYNAMIC_PLACEHOLDER_BIT) {
			res = mDynRes;
			types = mDynResTypes;
			index = index&(~DYNAMIC_PLACEHOLDER_BIT);
			TESTINDEX(index, mDynResSize);
		} else {
			TESTINDEX(index, mResSize);
		}

		// obj is the resource data. If the resource is NULL
		// and not a placeholder or in flux (resource is changing)
		// then create a panic.
		if (obj == NULL && (type != RT_PLACEHOLDER && type != RT_FLUX)) {
			DEBIG_PHAT_ERROR;
		}

		// Resource at this index must not be in use, but it can be a
		// placeholder. If the resource is in use, a panic is generated.
		if(res[index] != NULL || types[index] != RT_PLACEHOLDER) {
			BIG_PHAT_ERROR(ERR_RES_OVERWRITE);
		}

#ifdef RESOURCE_MEMORY_LIMIT
		int oldResmem = mResmem;
		switch(type) {
#define CASE_ADDMEM(R, T, D) case R: mResmem += size_##R((T*)obj); break;
			TYPES(CASE_ADDMEM);
		}
		if(mResmem >= mResmemMax) {
			//BIG_PHAT_ERROR(ERR_RES_OOM);
			mResmem = oldResmem;
			__destroy(obj, type, index);	//avoids memory leaks
			return RES_OUT_OF_MEMORY;
		}
#endif	//RESOURCE_MEMORY_LIMIT
		res[index] = obj;
		types[index] = type;
		return RES_OK;
	}
Exemple #6
0
/*
* Loads a resource from the stream, from originalHandle index to destHandle placeholder.
*/
bool Syscall::loadResource(Stream& file, MAHandle originalHandle, MAHandle destHandle)  {

    if(!file.isOpen())
    {
        return false;
    }

    if ((resourceType == NULL) || (resourceSize == NULL) || (resourceOffset == NULL))
    {
        return false;
    }

    int type = resourceType[originalHandle - 1];
    int size = resourceSize[originalHandle - 1];
    int offset = resourceOffset[originalHandle - 1];
    int rI = destHandle;

    if ( resources.is_loaded(rI) )
    {
        return true;
    }

    TEST(file.seek(Seek::Start, offset));

    switch(type) {
    case RT_BINARY:
    {
#ifndef _android
        MemStream* ms = new MemStream(size);
#else
        char* b = loadBinary(rI, size);
        MemStream* ms = new MemStream(b, size);
#endif
        TEST(file.readFully(*ms));
        ROOM(resources.dadd_RT_BINARY(rI, ms));
#ifdef _android
        checkAndStoreAudioResource(rI);
#endif
    }
    break;
    case RT_IMAGE:
    {
        MemStream b(size);
        TEST(file.readFully(b));
#ifndef _android
        // On all platforms except Android, we load and add
        // the image data. "dadd" means "delete and add",
        // and is defined in runtimes\cpp\base\ResourceArray.h
        RT_IMAGE_Type* image = loadImage(b);
        if(!image)
            BIG_PHAT_ERROR(ERR_IMAGE_LOAD_FAILED);
        ROOM(resources.dadd_RT_IMAGE(rI, image));
#else
        // On Android images are stored on the Java side.
        // Here we allocate a dummy array (real image is
        // in a table in Java) so that the resource handling,
        // like deleting resources, will work also on Android.
        // The actual image will be garbage collected on
        // Android when a resource is replaced in the Java table.
        ROOM(resources.dadd_RT_IMAGE(rI, new int[1]));
        int pos;
        file.tell(pos);
        loadImage(
            rI,
            pos - size,
            size,
            Base::gSyscall->getReloadHandle());
#endif
    }
    break;
    case RT_SPRITE:
    {
        DAR_USHORT(indexSource);
        DAR_USHORT(left);
        DAR_USHORT(top);
        DAR_USHORT(width);
        DAR_USHORT(height);
        DAR_SHORT(cx);
        DAR_SHORT(cy);
#ifndef _android
        ROOM(resources.dadd_RT_IMAGE(rI, loadSprite(resources.get_RT_IMAGE(indexSource),
                                     left, top, width, height, cx, cy)));
#endif
    }
    break;
    default:
        LOG("Cannot load resource type %d.", type);
    }
    return true;
}
Exemple #7
0
/*
* Loads all resources from the stream, except images, binaries and sprites.
*/
bool Syscall::loadResources(Stream& file, const char* aFilename)  {
    bool hasResources = true;
    if(!file.isOpen())
        hasResources = false;
    else {
        int len, pos;
        TEST(file.length(len));
        TEST(file.tell(pos));
        if(len == pos)
            hasResources = false;
    }
    if(!hasResources/* && aFilename != NULL*/) {
        resources.init(0);
        return true;
    }

#define MATCH_BYTE(c) { DAR_UBYTE(b); if(b != c) { FAIL; } }
    MATCH_BYTE('M');
    MATCH_BYTE('A');
    MATCH_BYTE('R');
    MATCH_BYTE('S');

    DAR_UVINT(nResources);
    DAR_UVINT(rSize);
    resources.init(nResources);

    resourcesCount = nResources;
    resourceOffset = new int[nResources];
    resourceSize = new int[nResources];
    resourceType = new int[nResources];
    resourcesFilename = new char[strlen(aFilename) + 1];
    strcpy(resourcesFilename, aFilename);

    // rI is the resource index.
    int rI = 1;

    while(true) {
        DAR_UBYTE(type);
        if(type == 0)
            break;

        //dispose flag

        DAR_UVINT(size);
        LOG_RES("Type %i, size %i\n", type, size);

        int index = rI - 1;

        TEST(file.tell(resourceOffset[index]));
        resourceSize[index] = size;
        resourceType[index] = type;

        switch(type) {
        case RT_UBIN:
        {
            int pos;
            MYASSERT(aFilename, ERR_RES_LOAD_UBIN);
            TEST(file.tell(pos));
#ifndef _android
            ROOM(resources.dadd_RT_BINARY(rI,
                                          new LimitedFileStream(aFilename, pos, size)));
#else
            // Android loads ubins by using JNI.
            loadUBinary(rI, pos, size);
            ROOM(resources.dadd_RT_BINARY(rI,
                                          new LimitedFileStream(
                                              aFilename,
                                              pos,
                                              size,
                                              getJNIEnvironment(),
                                              getJNIThis())));
#endif
            TEST(file.seek(Seek::Current, size));
        }
        break;
        case RT_PLACEHOLDER:
            ROOM(resources.dadd_RT_PLACEHOLDER(rI, NULL));
            break;
        case RT_LABEL:
        {
            MemStream b(size);
            TEST(file.readFully(b));
            ROOM(resources.dadd_RT_LABEL(rI, new Label((const char*)b.ptr(), rI)));
        }
        break;

#ifdef LOGGING_ENABLED
        case 99:  //testtype
#define DUMP_UVI { DAR_UVINT(u); LOG_RES("u %i\n", u); }
#define DUMP_SVI { DAR_SVINT(s); LOG_RES("s %i\n", s); }
            DUMP_UVI;
            DUMP_UVI;
            DUMP_UVI;
            DUMP_SVI;
            DUMP_SVI;
            DUMP_SVI;
            DUMP_SVI;
            DUMP_SVI;
            DUMP_SVI;
            break;
#endif
        default:
            TEST(file.seek(Seek::Current, size));
        }

        rI++;
    }
    if(rI != nResources + 1) {
        LOG("rI %i, nR %i\n", rI, nResources);
        BIG_PHAT_ERROR(ERR_RES_FILE_INCONSISTENT);
    }
    LOG_RES("ResLoad complete\n");
    return true;
}
Exemple #8
0
/*
* Loads all resources from the given buffer.
*/
bool Syscall::loadResourcesFromBuffer(Stream& file, const char* aFilename)  {
    bool hasResources = true;
    if(!file.isOpen())
        hasResources = false;
    else {
        int len, pos;
        TEST(file.length(len));
        TEST(file.tell(pos));
        if(len == pos)
            hasResources = false;
    }
    if(!hasResources/* && aFilename != NULL*/) {
        resources.init(0);
        return true;
    }

#define MATCH_BYTE(c) { DAR_UBYTE(b); if(b != c) { FAIL; } }
    MATCH_BYTE('M');
    MATCH_BYTE('A');
    MATCH_BYTE('R');
    MATCH_BYTE('S');

    DAR_UVINT(nResources);
    DAR_UVINT(rSize);
    resources.init(nResources);

    // rI is the resource index.
    int rI = 1;

    while(true) {
        DAR_UBYTE(type);
        if(type == 0)
            break;

        //dispose flag

        DAR_UVINT(size);
        LOG_RES("Type %i, size %i\n", type, size);

        switch(type) {
        case RT_BINARY:
        {
#ifndef _android
            MemStream* ms = new MemStream(size);
#else
            char* b = loadBinary(rI, size);
            MemStream* ms = new MemStream(b, size);
#endif
            TEST(file.readFully(*ms));
            ROOM(resources.dadd_RT_BINARY(rI, ms));
#ifdef _android
            checkAndStoreAudioResource(rI);
#endif
        }
        break;
        case RT_UBIN:
        {
            int pos;
            MYASSERT(aFilename, ERR_RES_LOAD_UBIN);
            TEST(file.tell(pos));
#ifndef _android
            ROOM(resources.dadd_RT_BINARY(rI,
                                          new LimitedFileStream(aFilename, pos, size)));
#else
            // Android loads ubins by using JNI.
            loadUBinary(rI, pos, size);
            ROOM(resources.dadd_RT_BINARY(rI,
                                          new LimitedFileStream(
                                              aFilename,
                                              pos,
                                              size,
                                              getJNIEnvironment(),
                                              getJNIThis())));
#endif
            TEST(file.seek(Seek::Current, size));
        }
        break;
        case RT_PLACEHOLDER:
            ROOM(resources.dadd_RT_PLACEHOLDER(rI, NULL));
            break;
        case RT_IMAGE:
        {
            MemStream b(size);
            TEST(file.readFully(b));
#ifndef _android
            // On all platforms except Android, we load and add
            // the image data. "dadd" means "delete and add",
            // and is defined in runtimes\cpp\base\ResourceArray.h
            RT_IMAGE_Type* image = loadImage(b);
            if(!image)
                BIG_PHAT_ERROR(ERR_IMAGE_LOAD_FAILED);
            ROOM(resources.dadd_RT_IMAGE(rI, image));
#else
            // On Android images are stored on the Java side.
            // Here we allocate a dummy array (real image is
            // in a table in Java) so that the resource handling,
            // like deleting resources, will work also on Android.
            // The actual image will be garbage collected on
            // Android when a resource is replaced in the Java table.
            ROOM(resources.dadd_RT_IMAGE(rI, new int[1]));
            int pos;
            file.tell(pos);
            loadImage(
                rI,
                pos - size,
                size,
                Base::gSyscall->getReloadHandle());
#endif
        }
        break;
        case RT_SPRITE:
        {
            DAR_USHORT(indexSource);
            DAR_USHORT(left);
            DAR_USHORT(top);
            DAR_USHORT(width);
            DAR_USHORT(height);
            DAR_SHORT(cx);
            DAR_SHORT(cy);
#ifndef _android
            ROOM(resources.dadd_RT_IMAGE(rI, loadSprite(resources.get_RT_IMAGE(indexSource),
                                         left, top, width, height, cx, cy)));
#endif
        }
        break;
        case RT_LABEL:
        {
            MemStream b(size);
            TEST(file.readFully(b));
            ROOM(resources.dadd_RT_LABEL(rI, new Label((const char*)b.ptr(), rI)));
        }
        break;

#ifdef LOGGING_ENABLED
        case 99:  //testtype
#define DUMP_UVI { DAR_UVINT(u); LOG_RES("u %i\n", u); }
#define DUMP_SVI { DAR_SVINT(s); LOG_RES("s %i\n", s); }
            DUMP_UVI;
            DUMP_UVI;
            DUMP_UVI;
            DUMP_SVI;
            DUMP_SVI;
            DUMP_SVI;
            DUMP_SVI;
            DUMP_SVI;
            DUMP_SVI;
            break;
#endif
        default:
            TEST(file.seek(Seek::Current, size));
        }
        rI++;
    }
    if(rI != nResources + 1) {
        LOG("rI %i, nR %i\n", rI, nResources);
        BIG_PHAT_ERROR(ERR_RES_FILE_INCONSISTENT);
    }
    LOG_RES("ResLoad complete\n");
    return true;
}
Exemple #9
0
/**
*	/return The newly created Data Section as a Direct ByteBuffer object
*/
static void nativeRun(JNIEnv* env, jobject jthis)
{
	__android_log_write(ANDROID_LOG_INFO,"JNI","native run");
	
	Base::gSyscall->setJNIEnvironment(env, jthis);
	
	while(1)
	{
		
		Core::Run2(gCore);
		
		__android_log_write(ANDROID_LOG_INFO,"JNI","Runtime yielded!");
		
		// Check if we should load a resource as a program/resource combfile
		int reloadHandle = Base::gSyscall->getReloadHandle();
		if(0 != reloadHandle)
		{
			__android_log_write(ANDROID_LOG_INFO,"JNI","Program is loading from handle");
		
			Base::Stream* stream = Base::gSyscall->resources.extract_RT_BINARY(reloadHandle);
			
			bool res = Core::LoadVMApp(gCore, *stream);
			
			delete stream;
			
			if(!res) {
				BIG_PHAT_ERROR(ERR_PROGRAM_LOAD_FAILED);
			}
			
			Base::gSyscall->setReloadHandle(0);
		}
		
		// TODO: Could this be a good place to check for pending 
		// exceptions from the Java side? 
		// See commented out function handlePendingExceptions
		// below for how to do this.
		//handlePendingExceptions(env);
		
		// TODO: Why is this code commented out? Document its purpose.
	
		// check if we should reload the initial program and resource file
		else if(true == Base::gSyscall->isReloading())
		{
			__android_log_write(ANDROID_LOG_INFO,"JNI","Program is reloading! 1");
			
			Base::gSyscall->setReloading(false);
			
			__android_log_write(ANDROID_LOG_INFO,"JNI","Program is reloading! 2");
			
			jclass cls = env->GetObjectClass(jthis);
			jmethodID methodID = env->GetMethodID(cls, "loadProgram", "()Z");
			if (methodID == 0) return;
			jboolean res = env->CallBooleanMethod(jthis, methodID);
			
			__android_log_write(ANDROID_LOG_INFO,"JNI","Program is reloading! 3");
			
			if(!res) {
				BIG_PHAT_ERROR(ERR_PROGRAM_LOAD_FAILED);
			}
			
			__android_log_write(ANDROID_LOG_INFO,"JNI","Program is reloading! 4");
			
		}
	
	}
	
}
Exemple #10
0
extern "C" void GCCATTRIB(noreturn) maLoadProgram(MAHandle data, int reload) {
	BIG_PHAT_ERROR(ERR_FUNCTION_UNSUPPORTED);
}
Exemple #11
0
int Base::Syscall::GetValidatedStackValue(int offset) {
	BIG_PHAT_ERROR(ERR_FUNCTION_UNSUPPORTED);	
}