mirror of https://github.com/mgba-emu/mgba.git
Core: Add support for caching bitmapped modes
This commit is contained in:
parent
19a42a387a
commit
fbe375fab9
1
CHANGES
1
CHANGES
|
@ -7,6 +7,7 @@ Features:
|
||||||
- GB: Expose platform information to CLI debugger
|
- GB: Expose platform information to CLI debugger
|
||||||
- Support Discord Rich Presence
|
- Support Discord Rich Presence
|
||||||
- Debugger: Add tracing to file
|
- Debugger: Add tracing to file
|
||||||
|
- Map viewer supports bitmapped GBA modes
|
||||||
Emulation fixes:
|
Emulation fixes:
|
||||||
- GBA: All IRQs have 7 cycle delay (fixes mgba.io/i/539, mgba.io/i/1208)
|
- GBA: All IRQs have 7 cycle delay (fixes mgba.io/i/539, mgba.io/i/1208)
|
||||||
- GBA: Reset now reloads multiboot ROMs
|
- GBA: Reset now reloads multiboot ROMs
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
/* Copyright (c) 2013-2019 Jeffrey Pfau
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
#ifndef M_BITMAP_CACHE_H
|
||||||
|
#define M_BITMAP_CACHE_H
|
||||||
|
|
||||||
|
#include <mgba-util/common.h>
|
||||||
|
|
||||||
|
CXX_GUARD_START
|
||||||
|
|
||||||
|
#include <mgba/core/interface.h>
|
||||||
|
|
||||||
|
DECL_BITFIELD(mBitmapCacheConfiguration, uint32_t);
|
||||||
|
DECL_BIT(mBitmapCacheConfiguration, ShouldStore, 0);
|
||||||
|
|
||||||
|
DECL_BITFIELD(mBitmapCacheSystemInfo, uint32_t);
|
||||||
|
DECL_BITS(mBitmapCacheSystemInfo, EntryBPP, 0, 3);
|
||||||
|
DECL_BIT(mBitmapCacheSystemInfo, UsesPalette, 3);
|
||||||
|
DECL_BITS(mBitmapCacheSystemInfo, Width, 4, 10);
|
||||||
|
DECL_BITS(mBitmapCacheSystemInfo, Height, 14, 10);
|
||||||
|
DECL_BITS(mBitmapCacheSystemInfo, Buffers, 24, 2);
|
||||||
|
|
||||||
|
struct mBitmapCacheEntry {
|
||||||
|
uint32_t paletteVersion;
|
||||||
|
uint32_t vramVersion;
|
||||||
|
uint8_t vramClean;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mBitmapCache {
|
||||||
|
color_t* cache;
|
||||||
|
struct mBitmapCacheEntry* status;
|
||||||
|
|
||||||
|
uint32_t globalPaletteVersion;
|
||||||
|
|
||||||
|
uint8_t* vram;
|
||||||
|
color_t* palette;
|
||||||
|
|
||||||
|
uint32_t bitsSize;
|
||||||
|
uint32_t bitsStart[2];
|
||||||
|
uint32_t stride;
|
||||||
|
uint8_t buffer;
|
||||||
|
|
||||||
|
mBitmapCacheConfiguration config;
|
||||||
|
mBitmapCacheSystemInfo sysConfig;
|
||||||
|
|
||||||
|
void* context;
|
||||||
|
};
|
||||||
|
|
||||||
|
void mBitmapCacheInit(struct mBitmapCache* cache);
|
||||||
|
void mBitmapCacheDeinit(struct mBitmapCache* cache);
|
||||||
|
void mBitmapCacheConfigure(struct mBitmapCache* cache, mBitmapCacheConfiguration config);
|
||||||
|
void mBitmapCacheConfigureSystem(struct mBitmapCache* cache, mBitmapCacheSystemInfo config);
|
||||||
|
void mBitmapCacheWriteVRAM(struct mBitmapCache* cache, uint32_t address);
|
||||||
|
void mBitmapCacheWritePalette(struct mBitmapCache* cache, uint32_t entry, color_t color);
|
||||||
|
|
||||||
|
void mBitmapCacheCleanRow(struct mBitmapCache* cache, struct mBitmapCacheEntry* entry, unsigned y);
|
||||||
|
bool mBitmapCacheCheckRow(struct mBitmapCache* cache, const struct mBitmapCacheEntry* entry, unsigned y);
|
||||||
|
const color_t* mBitmapCacheGetRow(struct mBitmapCache* cache, unsigned y);
|
||||||
|
|
||||||
|
CXX_GUARD_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -10,19 +10,22 @@
|
||||||
|
|
||||||
CXX_GUARD_START
|
CXX_GUARD_START
|
||||||
|
|
||||||
|
#include <mgba/core/bitmap-cache.h>
|
||||||
#include <mgba/core/map-cache.h>
|
#include <mgba/core/map-cache.h>
|
||||||
#include <mgba/core/tile-cache.h>
|
#include <mgba/core/tile-cache.h>
|
||||||
#include <mgba-util/vector.h>
|
#include <mgba-util/vector.h>
|
||||||
|
|
||||||
DECLARE_VECTOR(mMapCacheSet, struct mMapCache);
|
DECLARE_VECTOR(mMapCacheSet, struct mMapCache);
|
||||||
|
DECLARE_VECTOR(mBitmapCacheSet, struct mBitmapCache);
|
||||||
DECLARE_VECTOR(mTileCacheSet, struct mTileCache);
|
DECLARE_VECTOR(mTileCacheSet, struct mTileCache);
|
||||||
|
|
||||||
struct mCacheSet {
|
struct mCacheSet {
|
||||||
struct mMapCacheSet maps;
|
struct mMapCacheSet maps;
|
||||||
|
struct mBitmapCacheSet bitmaps;
|
||||||
struct mTileCacheSet tiles;
|
struct mTileCacheSet tiles;
|
||||||
};
|
};
|
||||||
|
|
||||||
void mCacheSetInit(struct mCacheSet*, size_t nMaps, size_t nTiles);
|
void mCacheSetInit(struct mCacheSet*, size_t nMaps, size_t nBitmaps, size_t nTiles);
|
||||||
void mCacheSetDeinit(struct mCacheSet*);
|
void mCacheSetDeinit(struct mCacheSet*);
|
||||||
|
|
||||||
void mCacheSetAssignVRAM(struct mCacheSet*, void* vram);
|
void mCacheSetAssignVRAM(struct mCacheSet*, void* vram);
|
||||||
|
|
|
@ -0,0 +1,182 @@
|
||||||
|
/* Copyright (c) 2013-2019 Jeffrey Pfau
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
#include <mgba/core/bitmap-cache.h>
|
||||||
|
|
||||||
|
#include <mgba-util/memory.h>
|
||||||
|
|
||||||
|
void mBitmapCacheInit(struct mBitmapCache* cache) {
|
||||||
|
// TODO: Reconfigurable cache for space savings
|
||||||
|
cache->cache = NULL;
|
||||||
|
cache->config = mBitmapCacheConfigurationFillShouldStore(0);
|
||||||
|
cache->status = NULL;
|
||||||
|
cache->palette = NULL;
|
||||||
|
cache->buffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _freeCache(struct mBitmapCache* cache) {
|
||||||
|
size_t size = mBitmapCacheSystemInfoGetHeight(cache->sysConfig) * mBitmapCacheSystemInfoGetBuffers(cache->sysConfig);
|
||||||
|
mappedMemoryFree(cache->cache, mBitmapCacheSystemInfoGetWidth(cache->sysConfig) * size * sizeof(color_t));
|
||||||
|
mappedMemoryFree(cache->status, size * sizeof(*cache->status));
|
||||||
|
if (cache->palette) {
|
||||||
|
free(cache->palette);
|
||||||
|
}
|
||||||
|
cache->cache = NULL;
|
||||||
|
cache->status = NULL;
|
||||||
|
cache->palette = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _redoCacheSize(struct mBitmapCache* cache) {
|
||||||
|
if (!mBitmapCacheConfigurationIsShouldStore(cache->config)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size = mBitmapCacheSystemInfoGetHeight(cache->sysConfig) * mBitmapCacheSystemInfoGetBuffers(cache->sysConfig);
|
||||||
|
cache->cache = anonymousMemoryMap(mBitmapCacheSystemInfoGetWidth(cache->sysConfig) * size * sizeof(color_t));
|
||||||
|
cache->status = anonymousMemoryMap(size * sizeof(*cache->status));
|
||||||
|
if (mBitmapCacheSystemInfoIsUsesPalette(cache->sysConfig)) {
|
||||||
|
cache->palette = malloc((1 << (1 << mBitmapCacheSystemInfoGetEntryBPP(cache->sysConfig))) * sizeof(color_t));
|
||||||
|
} else {
|
||||||
|
cache->palette = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mBitmapCacheConfigure(struct mBitmapCache* cache, mBitmapCacheConfiguration config) {
|
||||||
|
if (config == cache->config) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_freeCache(cache);
|
||||||
|
cache->config = config;
|
||||||
|
_redoCacheSize(cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mBitmapCacheConfigureSystem(struct mBitmapCache* cache, mBitmapCacheSystemInfo config) {
|
||||||
|
if (config == cache->sysConfig) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_freeCache(cache);
|
||||||
|
cache->sysConfig = config;
|
||||||
|
_redoCacheSize(cache);
|
||||||
|
|
||||||
|
size_t stride = mBitmapCacheSystemInfoGetWidth(cache->sysConfig);
|
||||||
|
size_t size = stride * mBitmapCacheSystemInfoGetHeight(cache->sysConfig);
|
||||||
|
size_t bpe = mBitmapCacheSystemInfoGetEntryBPP(cache->sysConfig);
|
||||||
|
if (bpe > 3) {
|
||||||
|
size <<= bpe - 3;
|
||||||
|
stride <<= bpe - 3;
|
||||||
|
} else {
|
||||||
|
size >>= 3 - bpe;
|
||||||
|
stride >>= 3 - bpe;
|
||||||
|
}
|
||||||
|
cache->bitsSize = size;
|
||||||
|
cache->stride = stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mBitmapCacheDeinit(struct mBitmapCache* cache) {
|
||||||
|
_freeCache(cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mBitmapCacheWriteVRAM(struct mBitmapCache* cache, uint32_t address) {
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < mBitmapCacheSystemInfoGetBuffers(cache->sysConfig); ++i) {
|
||||||
|
if (address < cache->bitsStart[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
uint32_t offset = address - cache->bitsStart[i];
|
||||||
|
if (offset >= cache->bitsSize) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
offset /= cache->stride;
|
||||||
|
offset *= mBitmapCacheSystemInfoGetBuffers(cache->sysConfig);
|
||||||
|
offset += cache->buffer;
|
||||||
|
cache->status[offset].vramClean = 0;
|
||||||
|
++cache->status[offset].vramVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mBitmapCacheWritePalette(struct mBitmapCache* cache, uint32_t entry, color_t color) {
|
||||||
|
if (!mBitmapCacheSystemInfoIsUsesPalette(cache->sysConfig)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
size_t maxEntry = 1 << (1 << mBitmapCacheSystemInfoGetEntryBPP(cache->sysConfig));
|
||||||
|
if (entry >= maxEntry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cache->palette[entry] = color;
|
||||||
|
++cache->globalPaletteVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t _lookupEntry8(void* vram, uint32_t offset) {
|
||||||
|
return ((uint8_t*) vram)[offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t _lookupEntry15(void* vram, uint32_t offset) {
|
||||||
|
return mColorFrom555(((uint16_t*) vram)[offset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mBitmapCacheCleanRow(struct mBitmapCache* cache, struct mBitmapCacheEntry* entry, unsigned y) {
|
||||||
|
color_t* row = &cache->cache[(cache->buffer * mBitmapCacheSystemInfoGetHeight(cache->sysConfig) + y) * mBitmapCacheSystemInfoGetWidth(cache->sysConfig)];
|
||||||
|
size_t location = cache->buffer + mBitmapCacheSystemInfoGetBuffers(cache->sysConfig) * y;
|
||||||
|
struct mBitmapCacheEntry* status = &cache->status[location];
|
||||||
|
struct mBitmapCacheEntry desiredStatus = {
|
||||||
|
.paletteVersion = cache->globalPaletteVersion,
|
||||||
|
.vramVersion = entry->vramVersion,
|
||||||
|
.vramClean = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
if (entry) {
|
||||||
|
entry[location] = desiredStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mBitmapCacheConfigurationIsShouldStore(cache->config) || !memcmp(status, &desiredStatus, sizeof(*entry))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t offset = cache->bitsStart[cache->buffer] + y * mBitmapCacheSystemInfoGetWidth(cache->sysConfig);
|
||||||
|
void* vram;
|
||||||
|
int bpe = mBitmapCacheSystemInfoGetEntryBPP(cache->sysConfig);
|
||||||
|
uint32_t (*lookupEntry)(void*, uint32_t);
|
||||||
|
switch (bpe) {
|
||||||
|
case 3:
|
||||||
|
lookupEntry = _lookupEntry8;
|
||||||
|
vram = &cache->vram[offset];
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
lookupEntry = _lookupEntry15;
|
||||||
|
vram = &cache->vram[offset << 1];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t x;
|
||||||
|
if (mBitmapCacheSystemInfoIsUsesPalette(cache->sysConfig)) {
|
||||||
|
for (x = 0; x < mBitmapCacheSystemInfoGetWidth(cache->sysConfig); ++x) {
|
||||||
|
row[x] = cache->palette[lookupEntry(vram, x)];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (x = 0; x < mBitmapCacheSystemInfoGetWidth(cache->sysConfig); ++x) {
|
||||||
|
row[x] = lookupEntry(vram, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*status = desiredStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mBitmapCacheCheckRow(struct mBitmapCache* cache, const struct mBitmapCacheEntry* entry, unsigned y) {
|
||||||
|
size_t location = cache->buffer + mBitmapCacheSystemInfoGetBuffers(cache->sysConfig) * y;
|
||||||
|
struct mBitmapCacheEntry desiredStatus = {
|
||||||
|
.paletteVersion = cache->globalPaletteVersion,
|
||||||
|
.vramVersion = entry->vramVersion,
|
||||||
|
.vramClean = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
return memcmp(&entry[location], &desiredStatus, sizeof(*entry)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const color_t* mBitmapCacheGetRow(struct mBitmapCache* cache, unsigned y) {
|
||||||
|
color_t* row = &cache->cache[(cache->buffer * mBitmapCacheSystemInfoGetHeight(cache->sysConfig) + y) * mBitmapCacheSystemInfoGetWidth(cache->sysConfig)];
|
||||||
|
return row;
|
||||||
|
}
|
|
@ -6,11 +6,14 @@
|
||||||
#include <mgba/core/cache-set.h>
|
#include <mgba/core/cache-set.h>
|
||||||
|
|
||||||
DEFINE_VECTOR(mMapCacheSet, struct mMapCache);
|
DEFINE_VECTOR(mMapCacheSet, struct mMapCache);
|
||||||
|
DEFINE_VECTOR(mBitmapCacheSet, struct mBitmapCache);
|
||||||
DEFINE_VECTOR(mTileCacheSet, struct mTileCache);
|
DEFINE_VECTOR(mTileCacheSet, struct mTileCache);
|
||||||
|
|
||||||
void mCacheSetInit(struct mCacheSet* cache, size_t nMaps, size_t nTiles) {
|
void mCacheSetInit(struct mCacheSet* cache, size_t nMaps, size_t nBitmaps, size_t nTiles) {
|
||||||
mMapCacheSetInit(&cache->maps, nMaps);
|
mMapCacheSetInit(&cache->maps, nMaps);
|
||||||
mMapCacheSetResize(&cache->maps, nMaps);
|
mMapCacheSetResize(&cache->maps, nMaps);
|
||||||
|
mBitmapCacheSetInit(&cache->bitmaps, nBitmaps);
|
||||||
|
mBitmapCacheSetResize(&cache->bitmaps, nBitmaps);
|
||||||
mTileCacheSetInit(&cache->tiles, nTiles);
|
mTileCacheSetInit(&cache->tiles, nTiles);
|
||||||
mTileCacheSetResize(&cache->tiles, nTiles);
|
mTileCacheSetResize(&cache->tiles, nTiles);
|
||||||
|
|
||||||
|
@ -18,6 +21,9 @@ void mCacheSetInit(struct mCacheSet* cache, size_t nMaps, size_t nTiles) {
|
||||||
for (i = 0; i < nMaps; ++i) {
|
for (i = 0; i < nMaps; ++i) {
|
||||||
mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, i));
|
mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, i));
|
||||||
}
|
}
|
||||||
|
for (i = 0; i < nBitmaps; ++i) {
|
||||||
|
mBitmapCacheInit(mBitmapCacheSetGetPointer(&cache->bitmaps, i));
|
||||||
|
}
|
||||||
for (i = 0; i < nTiles; ++i) {
|
for (i = 0; i < nTiles; ++i) {
|
||||||
mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, i));
|
mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, i));
|
||||||
}
|
}
|
||||||
|
@ -28,6 +34,9 @@ void mCacheSetDeinit(struct mCacheSet* cache) {
|
||||||
for (i = 0; i < mMapCacheSetSize(&cache->maps); ++i) {
|
for (i = 0; i < mMapCacheSetSize(&cache->maps); ++i) {
|
||||||
mMapCacheDeinit(mMapCacheSetGetPointer(&cache->maps, i));
|
mMapCacheDeinit(mMapCacheSetGetPointer(&cache->maps, i));
|
||||||
}
|
}
|
||||||
|
for (i = 0; i < mBitmapCacheSetSize(&cache->bitmaps); ++i) {
|
||||||
|
mBitmapCacheDeinit(mBitmapCacheSetGetPointer(&cache->bitmaps, i));
|
||||||
|
}
|
||||||
for (i = 0; i < mTileCacheSetSize(&cache->tiles); ++i) {
|
for (i = 0; i < mTileCacheSetSize(&cache->tiles); ++i) {
|
||||||
mTileCacheDeinit(mTileCacheSetGetPointer(&cache->tiles, i));
|
mTileCacheDeinit(mTileCacheSetGetPointer(&cache->tiles, i));
|
||||||
}
|
}
|
||||||
|
@ -38,6 +47,9 @@ void mCacheSetAssignVRAM(struct mCacheSet* cache, void* vram) {
|
||||||
for (i = 0; i < mMapCacheSetSize(&cache->maps); ++i) {
|
for (i = 0; i < mMapCacheSetSize(&cache->maps); ++i) {
|
||||||
mMapCacheSetGetPointer(&cache->maps, i)->vram = vram;
|
mMapCacheSetGetPointer(&cache->maps, i)->vram = vram;
|
||||||
}
|
}
|
||||||
|
for (i = 0; i < mBitmapCacheSetSize(&cache->bitmaps); ++i) {
|
||||||
|
mBitmapCacheSetGetPointer(&cache->bitmaps, i)->vram = vram;
|
||||||
|
}
|
||||||
for (i = 0; i < mTileCacheSetSize(&cache->tiles); ++i) {
|
for (i = 0; i < mTileCacheSetSize(&cache->tiles); ++i) {
|
||||||
struct mTileCache* tileCache = mTileCacheSetGetPointer(&cache->tiles, i);
|
struct mTileCache* tileCache = mTileCacheSetGetPointer(&cache->tiles, i);
|
||||||
tileCache->vram = (void*) ((uintptr_t) vram + tileCache->tileBase);
|
tileCache->vram = (void*) ((uintptr_t) vram + tileCache->tileBase);
|
||||||
|
@ -49,6 +61,9 @@ void mCacheSetWriteVRAM(struct mCacheSet* cache, uint32_t address) {
|
||||||
for (i = 0; i < mMapCacheSetSize(&cache->maps); ++i) {
|
for (i = 0; i < mMapCacheSetSize(&cache->maps); ++i) {
|
||||||
mMapCacheWriteVRAM(mMapCacheSetGetPointer(&cache->maps, i), address);
|
mMapCacheWriteVRAM(mMapCacheSetGetPointer(&cache->maps, i), address);
|
||||||
}
|
}
|
||||||
|
for (i = 0; i < mBitmapCacheSetSize(&cache->bitmaps); ++i) {
|
||||||
|
mBitmapCacheWriteVRAM(mBitmapCacheSetGetPointer(&cache->bitmaps, i), address);
|
||||||
|
}
|
||||||
for (i = 0; i < mTileCacheSetSize(&cache->tiles); ++i) {
|
for (i = 0; i < mTileCacheSetSize(&cache->tiles); ++i) {
|
||||||
mTileCacheWriteVRAM(mTileCacheSetGetPointer(&cache->tiles, i), address);
|
mTileCacheWriteVRAM(mTileCacheSetGetPointer(&cache->tiles, i), address);
|
||||||
}
|
}
|
||||||
|
@ -56,6 +71,9 @@ void mCacheSetWriteVRAM(struct mCacheSet* cache, uint32_t address) {
|
||||||
|
|
||||||
void mCacheSetWritePalette(struct mCacheSet* cache, uint32_t entry, color_t color) {
|
void mCacheSetWritePalette(struct mCacheSet* cache, uint32_t entry, color_t color) {
|
||||||
size_t i;
|
size_t i;
|
||||||
|
for (i = 0; i < mBitmapCacheSetSize(&cache->bitmaps); ++i) {
|
||||||
|
mBitmapCacheWritePalette(mBitmapCacheSetGetPointer(&cache->bitmaps, i), entry, color);
|
||||||
|
}
|
||||||
for (i = 0; i < mTileCacheSetSize(&cache->tiles); ++i) {
|
for (i = 0; i < mTileCacheSetSize(&cache->tiles); ++i) {
|
||||||
mTileCacheWritePalette(mTileCacheSetGetPointer(&cache->tiles, i), entry, color);
|
mTileCacheWritePalette(mTileCacheSetGetPointer(&cache->tiles, i), entry, color);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,16 +11,13 @@
|
||||||
#include <mgba/internal/gb/video.h>
|
#include <mgba/internal/gb/video.h>
|
||||||
|
|
||||||
void GBVideoCacheInit(struct mCacheSet* cache) {
|
void GBVideoCacheInit(struct mCacheSet* cache) {
|
||||||
mCacheSetInit(cache, 2, 1);
|
mCacheSetInit(cache, 2, 0, 1);
|
||||||
mTileCacheConfiguration config = 0;
|
mTileCacheConfiguration config = 0;
|
||||||
config = mTileCacheSystemInfoSetPaletteBPP(config, 1); // 2^(2^1) = 4 entries
|
config = mTileCacheSystemInfoSetPaletteBPP(config, 1); // 2^(2^1) = 4 entries
|
||||||
config = mTileCacheSystemInfoSetPaletteCount(config, 4); // 16 palettes
|
config = mTileCacheSystemInfoSetPaletteCount(config, 4); // 16 palettes
|
||||||
config = mTileCacheSystemInfoSetMaxTiles(config, 1024);
|
config = mTileCacheSystemInfoSetMaxTiles(config, 1024);
|
||||||
mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 0));
|
|
||||||
mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 0), config, 0, 0);
|
mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 0), config, 0, 0);
|
||||||
|
|
||||||
mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 0));
|
|
||||||
mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 1));
|
|
||||||
mMapCacheSetGetPointer(&cache->maps, 0)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0);
|
mMapCacheSetGetPointer(&cache->maps, 0)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0);
|
||||||
mMapCacheSetGetPointer(&cache->maps, 1)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0);
|
mMapCacheSetGetPointer(&cache->maps, 1)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,35 +11,45 @@
|
||||||
#include <mgba/internal/gba/video.h>
|
#include <mgba/internal/gba/video.h>
|
||||||
|
|
||||||
void GBAVideoCacheInit(struct mCacheSet* cache) {
|
void GBAVideoCacheInit(struct mCacheSet* cache) {
|
||||||
mCacheSetInit(cache, 4, 4);
|
mCacheSetInit(cache, 4, 2, 4);
|
||||||
mTileCacheSystemInfo sysconfig = 0;
|
mTileCacheSystemInfo sysconfig = 0;
|
||||||
mTileCacheConfiguration config = mTileCacheConfigurationFillShouldStore(0);
|
mTileCacheConfiguration config = mTileCacheConfigurationFillShouldStore(0);
|
||||||
sysconfig = mTileCacheSystemInfoSetPaletteBPP(sysconfig, 2); // 2^(2^2) = 16 entries
|
sysconfig = mTileCacheSystemInfoSetPaletteBPP(sysconfig, 2); // 2^(2^2) = 16 entries
|
||||||
sysconfig = mTileCacheSystemInfoSetPaletteCount(sysconfig, 4); // 16 palettes
|
sysconfig = mTileCacheSystemInfoSetPaletteCount(sysconfig, 4); // 16 palettes
|
||||||
sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 2048);
|
sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 2048);
|
||||||
mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 0));
|
|
||||||
mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 0), config);
|
mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 0), config);
|
||||||
mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 0), sysconfig, 0, 0);
|
mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 0), sysconfig, 0, 0);
|
||||||
sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 1024);
|
sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 1024);
|
||||||
mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 2));
|
|
||||||
mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 2), config);
|
mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 2), config);
|
||||||
mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 2), sysconfig, 0x10000, 0x100);
|
mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 2), sysconfig, 0x10000, 0x100);
|
||||||
|
|
||||||
sysconfig = mTileCacheSystemInfoSetPaletteBPP(sysconfig, 3); // 2^(2^3) = 256 entries
|
sysconfig = mTileCacheSystemInfoSetPaletteBPP(sysconfig, 3); // 2^(2^3) = 256 entries
|
||||||
sysconfig = mTileCacheSystemInfoSetPaletteCount(sysconfig, 0); // 1 palettes
|
sysconfig = mTileCacheSystemInfoSetPaletteCount(sysconfig, 0); // 1 palettes
|
||||||
sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 2048);
|
sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 2048);
|
||||||
mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 1));
|
|
||||||
mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 1), config);
|
mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 1), config);
|
||||||
mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 1), sysconfig, 0, 0);
|
mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 1), sysconfig, 0, 0);
|
||||||
sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 1024);
|
sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 1024);
|
||||||
mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 3));
|
|
||||||
mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 3), config);
|
mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 3), config);
|
||||||
mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 3), sysconfig, 0x10000, 0x100);
|
mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 3), sysconfig, 0x10000, 0x100);
|
||||||
|
|
||||||
mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 0));
|
mBitmapCacheSystemInfo bitConfig;
|
||||||
mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 1));
|
bitConfig = mBitmapCacheSystemInfoSetEntryBPP(0, 4);
|
||||||
mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 2));
|
bitConfig = mBitmapCacheSystemInfoClearUsesPalette(bitConfig);
|
||||||
mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 3));
|
bitConfig = mBitmapCacheSystemInfoSetHeight(bitConfig, 160);
|
||||||
|
bitConfig = mBitmapCacheSystemInfoSetWidth(bitConfig, 240);
|
||||||
|
bitConfig = mBitmapCacheSystemInfoSetBuffers(bitConfig, 1);
|
||||||
|
mBitmapCacheConfigureSystem(mBitmapCacheSetGetPointer(&cache->bitmaps, 0), bitConfig);
|
||||||
|
mBitmapCacheSetGetPointer(&cache->bitmaps, 0)->bitsStart[0] = 0;
|
||||||
|
mBitmapCacheSetGetPointer(&cache->bitmaps, 0)->bitsStart[1] = 0xA000;
|
||||||
|
|
||||||
|
bitConfig = mBitmapCacheSystemInfoSetEntryBPP(0, 3);
|
||||||
|
bitConfig = mBitmapCacheSystemInfoFillUsesPalette(bitConfig);
|
||||||
|
bitConfig = mBitmapCacheSystemInfoSetHeight(bitConfig, 160);
|
||||||
|
bitConfig = mBitmapCacheSystemInfoSetWidth(bitConfig, 240);
|
||||||
|
bitConfig = mBitmapCacheSystemInfoSetBuffers(bitConfig, 2);
|
||||||
|
mBitmapCacheConfigureSystem(mBitmapCacheSetGetPointer(&cache->bitmaps, 1), bitConfig);
|
||||||
|
mBitmapCacheSetGetPointer(&cache->bitmaps, 1)->bitsStart[0] = 0;
|
||||||
|
mBitmapCacheSetGetPointer(&cache->bitmaps, 1)->bitsStart[1] = 0xA000;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAVideoCacheAssociate(struct mCacheSet* cache, struct GBAVideo* video) {
|
void GBAVideoCacheAssociate(struct mCacheSet* cache, struct GBAVideo* video) {
|
||||||
|
@ -77,6 +87,8 @@ static void mapParser2(struct mMapCache* cache, struct mMapCacheEntry* entry, vo
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GBAVideoCacheWriteDISPCNT(struct mCacheSet* cache, uint16_t value) {
|
static void GBAVideoCacheWriteDISPCNT(struct mCacheSet* cache, uint16_t value) {
|
||||||
|
mBitmapCacheSetGetPointer(&cache->bitmaps, 1)->buffer = GBARegisterDISPCNTGetFrameSelect(value);
|
||||||
|
|
||||||
switch (GBARegisterDISPCNTGetMode(value)) {
|
switch (GBARegisterDISPCNTGetMode(value)) {
|
||||||
case 0:
|
case 0:
|
||||||
default:
|
default:
|
||||||
|
@ -110,6 +122,28 @@ static void GBAVideoCacheWriteDISPCNT(struct mCacheSet* cache, uint16_t value) {
|
||||||
mMapCacheSetGetPointer(&cache->maps, 3)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1);
|
mMapCacheSetGetPointer(&cache->maps, 3)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mBitmapCacheSystemInfo bitConfig;
|
||||||
|
switch (GBARegisterDISPCNTGetMode(value)) {
|
||||||
|
case 3:
|
||||||
|
bitConfig = mBitmapCacheSystemInfoSetEntryBPP(0, 4);
|
||||||
|
bitConfig = mBitmapCacheSystemInfoClearUsesPalette(bitConfig);
|
||||||
|
bitConfig = mBitmapCacheSystemInfoSetHeight(bitConfig, 160);
|
||||||
|
bitConfig = mBitmapCacheSystemInfoSetWidth(bitConfig, 240);
|
||||||
|
bitConfig = mBitmapCacheSystemInfoSetBuffers(bitConfig, 1);
|
||||||
|
mBitmapCacheConfigureSystem(mBitmapCacheSetGetPointer(&cache->bitmaps, 0), bitConfig);
|
||||||
|
mBitmapCacheSetGetPointer(&cache->bitmaps, 0)->buffer = 0;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
bitConfig = mBitmapCacheSystemInfoSetEntryBPP(0, 4);
|
||||||
|
bitConfig = mBitmapCacheSystemInfoClearUsesPalette(bitConfig);
|
||||||
|
bitConfig = mBitmapCacheSystemInfoSetHeight(bitConfig, 128);
|
||||||
|
bitConfig = mBitmapCacheSystemInfoSetWidth(bitConfig, 160);
|
||||||
|
bitConfig = mBitmapCacheSystemInfoSetBuffers(bitConfig, 2);
|
||||||
|
mBitmapCacheConfigureSystem(mBitmapCacheSetGetPointer(&cache->bitmaps, 0), bitConfig);
|
||||||
|
mBitmapCacheSetGetPointer(&cache->bitmaps, 0)->buffer = GBARegisterDISPCNTGetFrameSelect(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GBAVideoCacheWriteBGCNT(struct mCacheSet* cache, size_t bg, uint16_t value) {
|
static void GBAVideoCacheWriteBGCNT(struct mCacheSet* cache, size_t bg, uint16_t value) {
|
||||||
|
|
|
@ -12,7 +12,10 @@
|
||||||
#include <mgba-util/png-io.h>
|
#include <mgba-util/png-io.h>
|
||||||
#include <mgba-util/vfs.h>
|
#include <mgba-util/vfs.h>
|
||||||
#ifdef M_CORE_GBA
|
#ifdef M_CORE_GBA
|
||||||
|
#include <mgba/internal/gba/gba.h>
|
||||||
|
#include <mgba/internal/gba/io.h>
|
||||||
#include <mgba/internal/gba/memory.h>
|
#include <mgba/internal/gba/memory.h>
|
||||||
|
#include <mgba/internal/gba/video.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef M_CORE_GB
|
#ifdef M_CORE_GB
|
||||||
#include <mgba/internal/gb/memory.h>
|
#include <mgba/internal/gb/memory.h>
|
||||||
|
@ -139,6 +142,24 @@ bool MapView::eventFilter(QObject* obj, QEvent* event) {
|
||||||
void MapView::updateTilesGBA(bool force) {
|
void MapView::updateTilesGBA(bool force) {
|
||||||
{
|
{
|
||||||
CoreController::Interrupter interrupter(m_controller);
|
CoreController::Interrupter interrupter(m_controller);
|
||||||
|
int bitmap = -1;
|
||||||
|
if (m_controller->platform() == PLATFORM_GBA) {
|
||||||
|
int mode = GBARegisterDISPCNTGetMode(static_cast<GBA*>(m_controller->thread()->core->board)->memory.io[REG_DISPCNT]);
|
||||||
|
if (m_map == 2 && mode > 2) {
|
||||||
|
bitmap = mode == 4 ? 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bitmap >= 0) {
|
||||||
|
mBitmapCache* bitmapCache = mBitmapCacheSetGetPointer(&m_cacheSet->bitmaps, bitmap);
|
||||||
|
int width = mBitmapCacheSystemInfoGetWidth(bitmapCache->sysConfig);
|
||||||
|
int height = mBitmapCacheSystemInfoGetHeight(bitmapCache->sysConfig);
|
||||||
|
m_rawMap = QImage(QSize(width, height), QImage::Format_ARGB32);
|
||||||
|
uchar* bgBits = m_rawMap.bits();
|
||||||
|
for (int j = 0; j < height; ++j) {
|
||||||
|
mBitmapCacheCleanRow(bitmapCache, m_bitmapStatus, j);
|
||||||
|
memcpy(static_cast<void*>(&bgBits[width * j * 4]), mBitmapCacheGetRow(bitmapCache, j), width * 4);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
mMapCache* mapCache = mMapCacheSetGetPointer(&m_cacheSet->maps, m_map);
|
mMapCache* mapCache = mMapCacheSetGetPointer(&m_cacheSet->maps, m_map);
|
||||||
int tilesW = 1 << mMapCacheSystemInfoGetTilesWide(mapCache->sysConfig);
|
int tilesW = 1 << mMapCacheSystemInfoGetTilesWide(mapCache->sysConfig);
|
||||||
int tilesH = 1 << mMapCacheSystemInfoGetTilesHigh(mapCache->sysConfig);
|
int tilesH = 1 << mMapCacheSystemInfoGetTilesHigh(mapCache->sysConfig);
|
||||||
|
@ -153,6 +174,7 @@ void MapView::updateTilesGBA(bool force) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
m_rawMap = m_rawMap.rgbSwapped();
|
m_rawMap = m_rawMap.rgbSwapped();
|
||||||
QPixmap map = QPixmap::fromImage(m_rawMap.convertToFormat(QImage::Format_RGB32));
|
QPixmap map = QPixmap::fromImage(m_rawMap.convertToFormat(QImage::Format_RGB32));
|
||||||
if (m_ui.magnification->value() > 1) {
|
if (m_ui.magnification->value() > 1) {
|
||||||
|
@ -181,7 +203,6 @@ void MapView::exportMap() {
|
||||||
png_structp png = PNGWriteOpen(vf);
|
png_structp png = PNGWriteOpen(vf);
|
||||||
png_infop info = PNGWriteHeaderA(png, m_rawMap.width(), m_rawMap.height());
|
png_infop info = PNGWriteHeaderA(png, m_rawMap.width(), m_rawMap.height());
|
||||||
|
|
||||||
mMapCache* mapCache = mMapCacheSetGetPointer(&m_cacheSet->maps, m_map);
|
|
||||||
QImage map = m_rawMap.rgbSwapped();
|
QImage map = m_rawMap.rgbSwapped();
|
||||||
PNGWritePixelsA(png, map.width(), map.height(), map.bytesPerLine() / 4, static_cast<const void*>(map.constBits()));
|
PNGWritePixelsA(png, map.width(), map.height(), map.bytesPerLine() / 4, static_cast<const void*>(map.constBits()));
|
||||||
PNGWriteClose(png, info);
|
PNGWriteClose(png, info);
|
||||||
|
|
|
@ -45,6 +45,7 @@ private:
|
||||||
|
|
||||||
std::shared_ptr<CoreController> m_controller;
|
std::shared_ptr<CoreController> m_controller;
|
||||||
mMapCacheEntry m_mapStatus[128 * 128] = {}; // TODO: Correct size
|
mMapCacheEntry m_mapStatus[128 * 128] = {}; // TODO: Correct size
|
||||||
|
mBitmapCacheEntry m_bitmapStatus[512 * 2] = {}; // TODO: Correct size
|
||||||
int m_map = 0;
|
int m_map = 0;
|
||||||
QImage m_rawMap;
|
QImage m_rawMap;
|
||||||
int m_boundary;
|
int m_boundary;
|
||||||
|
|
Loading…
Reference in New Issue