Ejemplo n.º 1
0
void GBASavedataMask(struct GBASavedata* savedata, struct VFile* vf, bool writeback) {
	enum SavedataType type = savedata->type;
	GBASavedataDeinit(savedata);
	savedata->vf = vf;
	savedata->mapMode = MAP_READ;
	savedata->maskWriteback = writeback;
	GBASavedataForceType(savedata, type, savedata->realisticTiming);
}
Ejemplo n.º 2
0
void GBASavedataMask(struct GBASavedata* savedata, struct VFile* vf, bool writeback) {
	enum SavedataType type = savedata->type;
	struct VFile* oldVf = savedata->vf;
	GBASavedataDeinit(savedata);
	if (oldVf && oldVf != savedata->realVf) {
		oldVf->close(oldVf);
	}
	savedata->vf = vf;
	savedata->mapMode = MAP_READ;
	savedata->maskWriteback = writeback;
	GBASavedataForceType(savedata, type);
}
Ejemplo n.º 3
0
void GBASavedataUnmask(struct GBASavedata* savedata) {
	if (!savedata->realVf || savedata->vf == savedata->realVf) {
		return;
	}
	enum SavedataType type = savedata->type;
	struct VFile* vf = savedata->vf;
	GBASavedataDeinit(savedata);
	savedata->vf = savedata->realVf;
	savedata->mapMode = MAP_WRITE;
	GBASavedataForceType(savedata, type);
	if (savedata->maskWriteback) {
		GBASavedataLoad(savedata, vf);
		savedata->maskWriteback = false;
	}
	vf->close(vf);
}
Ejemplo n.º 4
0
bool GBASavedataImportSharkPort(struct GBA* gba, struct VFile* vf, bool testChecksum) {
    union {
        char c[0x1C];
        int32_t i;
    } buffer;
    if (vf->read(vf, &buffer.i, 4) < 4) {
        return false;
    }
    int32_t size;
    LOAD_32(size, 0, &buffer.i);
    if (size != (int32_t) strlen(SHARKPORT_HEADER)) {
        return false;
    }
    if (vf->read(vf, buffer.c, size) < size) {
        return false;
    }
    if (memcmp(SHARKPORT_HEADER, buffer.c, size) != 0) {
        return false;
    }
    if (vf->read(vf, &buffer.i, 4) < 4) {
        return false;
    }
    LOAD_32(size, 0, &buffer.i);
    if (size != 0x000F0000) {
        // What is this value?
        return false;
    }

    // Skip first three fields
    if (vf->read(vf, &buffer.i, 4) < 4) {
        return false;
    }
    LOAD_32(size, 0, &buffer.i);
    if (vf->seek(vf, size, SEEK_CUR) < 0) {
        return false;
    }

    if (vf->read(vf, &buffer.i, 4) < 4) {
        return false;
    }
    LOAD_32(size, 0, &buffer.i);
    if (vf->seek(vf, size, SEEK_CUR) < 0) {
        return false;
    }

    if (vf->read(vf, &buffer.i, 4) < 4) {
        return false;
    }
    LOAD_32(size, 0, &buffer.i);
    if (vf->seek(vf, size, SEEK_CUR) < 0) {
        return false;
    }

    // Read payload
    if (vf->read(vf, &buffer.i, 4) < 4) {
        return false;
    }
    LOAD_32(size, 0, &buffer.i);
    if (size < 0x1C || size > SIZE_CART_FLASH1M + 0x1C) {
        return false;
    }
    char* payload = malloc(size);
    if (vf->read(vf, payload, size) < size) {
        goto cleanup;
    }

    struct GBACartridge* cart = (struct GBACartridge*) gba->memory.rom;
    memcpy(buffer.c, &cart->title, 16);
    buffer.c[0x10] = 0;
    buffer.c[0x11] = 0;
    buffer.c[0x12] = cart->checksum;
    buffer.c[0x13] = cart->maker;
    buffer.c[0x14] = 1;
    buffer.c[0x15] = 0;
    buffer.c[0x16] = 0;
    buffer.c[0x17] = 0;
    buffer.c[0x18] = 0;
    buffer.c[0x19] = 0;
    buffer.c[0x1A] = 0;
    buffer.c[0x1B] = 0;
    if (memcmp(buffer.c, payload, 0x1C) != 0) {
        goto cleanup;
    }

    uint32_t checksum;
    if (vf->read(vf, &buffer.i, 4) < 4) {
        goto cleanup;
    }
    LOAD_32(checksum, 0, &buffer.i);

    if (testChecksum) {
        uint32_t calcChecksum = 0;
        int i;
        for (i = 0; i < size; ++i) {
            calcChecksum += ((int32_t) payload[i]) << (calcChecksum % 24);
        }

        if (calcChecksum != checksum) {
            goto cleanup;
        }
    }

    uint32_t copySize = size - 0x1C;
    switch (gba->memory.savedata.type) {
    case SAVEDATA_SRAM:
        if (copySize > SIZE_CART_SRAM) {
            copySize = SIZE_CART_SRAM;
        }
        break;
    case SAVEDATA_FLASH512:
        if (copySize > SIZE_CART_FLASH512) {
            GBASavedataForceType(&gba->memory.savedata, SAVEDATA_FLASH1M, gba->memory.savedata.realisticTiming);
        }
    // Fall through
    case SAVEDATA_FLASH1M:
        if (copySize > SIZE_CART_FLASH1M) {
            copySize = SIZE_CART_FLASH1M;
        }
        break;
    case SAVEDATA_EEPROM:
        if (copySize > SIZE_CART_EEPROM) {
            copySize = SAVEDATA_EEPROM;
        }
        break;
    case SAVEDATA_FORCE_NONE:
    case SAVEDATA_AUTODETECT:
        goto cleanup;
    }

    memcpy(gba->memory.savedata.data, &payload[0x1C], copySize);

    free(payload);
    return true;

cleanup:
    free(payload);
    return false;
}