Core: Add support for caching bitmapped modes
@@ -7,6 +7,7 @@ - Debugger: Add unary operators and memory dereferencing
- GB: Expose platform information to CLI debugger - Support Discord Rich Presence - Debugger: Add tracing to file + - Map viewer supports bitmapped GBA modes Emulation fixes: - GBA: All IRQs have 7 cycle delay (fixes mgba.io/i/539, mgba.io/i/1208) - 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 @@ #include <mgba-util/common.h>
CXX_GUARD_START +#include <mgba/core/bitmap-cache.h> #include <mgba/core/map-cache.h> #include <mgba/core/tile-cache.h> #include <mgba-util/vector.h> DECLARE_VECTOR(mMapCacheSet, struct mMapCache); +DECLARE_VECTOR(mBitmapCacheSet, struct mBitmapCache); DECLARE_VECTOR(mTileCacheSet, struct mTileCache); struct mCacheSet { struct mMapCacheSet maps; + struct mBitmapCacheSet bitmaps; 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 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 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <mgba/core/cache-set.h> DEFINE_VECTOR(mMapCacheSet, struct mMapCache); +DEFINE_VECTOR(mBitmapCacheSet, struct mBitmapCache); 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); mMapCacheSetResize(&cache->maps, nMaps); + mBitmapCacheSetInit(&cache->bitmaps, nBitmaps); + mBitmapCacheSetResize(&cache->bitmaps, nBitmaps); mTileCacheSetInit(&cache->tiles, nTiles); mTileCacheSetResize(&cache->tiles, nTiles);@@ -18,6 +21,9 @@ size_t i;
for (i = 0; i < nMaps; ++i) { mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, i)); } + for (i = 0; i < nBitmaps; ++i) { + mBitmapCacheInit(mBitmapCacheSetGetPointer(&cache->bitmaps, i)); + } for (i = 0; i < nTiles; ++i) { mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, i)); }@@ -28,6 +34,9 @@ size_t i;
for (i = 0; i < mMapCacheSetSize(&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) { mTileCacheDeinit(mTileCacheSetGetPointer(&cache->tiles, i)); }@@ -38,6 +47,9 @@ size_t i;
for (i = 0; i < mMapCacheSetSize(&cache->maps); ++i) { 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) { struct mTileCache* tileCache = mTileCacheSetGetPointer(&cache->tiles, i); tileCache->vram = (void*) ((uintptr_t) vram + tileCache->tileBase);@@ -49,6 +61,9 @@ size_t i;
for (i = 0; i < mMapCacheSetSize(&cache->maps); ++i) { 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) { mTileCacheWriteVRAM(mTileCacheSetGetPointer(&cache->tiles, i), address); }@@ -56,6 +71,9 @@ }
void mCacheSetWritePalette(struct mCacheSet* cache, uint32_t entry, color_t color) { 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) { mTileCacheWritePalette(mTileCacheSetGetPointer(&cache->tiles, i), entry, color); }
@@ -11,16 +11,13 @@ #include <mgba/internal/gb/io.h>
#include <mgba/internal/gb/video.h> void GBVideoCacheInit(struct mCacheSet* cache) { - mCacheSetInit(cache, 2, 1); + mCacheSetInit(cache, 2, 0, 1); mTileCacheConfiguration config = 0; config = mTileCacheSystemInfoSetPaletteBPP(config, 1); // 2^(2^1) = 4 entries config = mTileCacheSystemInfoSetPaletteCount(config, 4); // 16 palettes config = mTileCacheSystemInfoSetMaxTiles(config, 1024); - mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 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, 1)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0); }
@@ -11,35 +11,45 @@ #include <mgba/internal/gba/io.h>
#include <mgba/internal/gba/video.h> void GBAVideoCacheInit(struct mCacheSet* cache) { - mCacheSetInit(cache, 4, 4); + mCacheSetInit(cache, 4, 2, 4); mTileCacheSystemInfo sysconfig = 0; mTileCacheConfiguration config = mTileCacheConfigurationFillShouldStore(0); sysconfig = mTileCacheSystemInfoSetPaletteBPP(sysconfig, 2); // 2^(2^2) = 16 entries sysconfig = mTileCacheSystemInfoSetPaletteCount(sysconfig, 4); // 16 palettes sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 2048); - mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 0)); mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 0), config); mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 0), sysconfig, 0, 0); sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 1024); - mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 2)); mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 2), config); mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 2), sysconfig, 0x10000, 0x100); sysconfig = mTileCacheSystemInfoSetPaletteBPP(sysconfig, 3); // 2^(2^3) = 256 entries sysconfig = mTileCacheSystemInfoSetPaletteCount(sysconfig, 0); // 1 palettes sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 2048); - mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 1)); mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 1), config); mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 1), sysconfig, 0, 0); sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 1024); - mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 3)); mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 3), config); mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 3), sysconfig, 0x10000, 0x100); - mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 0)); - mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 1)); - mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 2)); - mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 3)); + mBitmapCacheSystemInfo bitConfig; + 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)->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) {@@ -77,6 +87,8 @@ entry->flags = mMapCacheEntryFlagsClearPaletteId(entry->flags);
} static void GBAVideoCacheWriteDISPCNT(struct mCacheSet* cache, uint16_t value) { + mBitmapCacheSetGetPointer(&cache->bitmaps, 1)->buffer = GBARegisterDISPCNTGetFrameSelect(value); + switch (GBARegisterDISPCNTGetMode(value)) { case 0: default:@@ -108,6 +120,28 @@ mMapCacheSystemInfoGetPaletteBPP(mMapCacheSetGetPointer(&cache->maps, 1)->sysConfig) == 3);
mMapCacheSetGetPointer(&cache->maps, 2)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1); mMapCacheSetGetPointer(&cache->maps, 3)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1); + 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; } }
@@ -12,7 +12,10 @@
#include <mgba-util/png-io.h> #include <mgba-util/vfs.h> #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/video.h> #endif #ifdef M_CORE_GB #include <mgba/internal/gb/memory.h>@@ -139,17 +142,36 @@
void MapView::updateTilesGBA(bool force) { { CoreController::Interrupter interrupter(m_controller); - mMapCache* mapCache = mMapCacheSetGetPointer(&m_cacheSet->maps, m_map); - int tilesW = 1 << mMapCacheSystemInfoGetTilesWide(mapCache->sysConfig); - int tilesH = 1 << mMapCacheSystemInfoGetTilesHigh(mapCache->sysConfig); - m_rawMap = QImage(QSize(tilesW * 8, tilesH * 8), QImage::Format_ARGB32); - uchar* bgBits = m_rawMap.bits(); - for (int j = 0; j < tilesH; ++j) { - for (int i = 0; i < tilesW; ++i) { - mMapCacheCleanTile(mapCache, m_mapStatus, i, j); + 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); } - for (int i = 0; i < 8; ++i) { - memcpy(static_cast<void*>(&bgBits[tilesW * 32 * (i + j * 8)]), mMapCacheGetRow(mapCache, i + j * 8), tilesW * 32); + } else { + mMapCache* mapCache = mMapCacheSetGetPointer(&m_cacheSet->maps, m_map); + int tilesW = 1 << mMapCacheSystemInfoGetTilesWide(mapCache->sysConfig); + int tilesH = 1 << mMapCacheSystemInfoGetTilesHigh(mapCache->sysConfig); + m_rawMap = QImage(QSize(tilesW * 8, tilesH * 8), QImage::Format_ARGB32); + uchar* bgBits = m_rawMap.bits(); + for (int j = 0; j < tilesH; ++j) { + for (int i = 0; i < tilesW; ++i) { + mMapCacheCleanTile(mapCache, m_mapStatus, i, j); + } + for (int i = 0; i < 8; ++i) { + memcpy(static_cast<void*>(&bgBits[tilesW * 32 * (i + j * 8)]), mMapCacheGetRow(mapCache, i + j * 8), tilesW * 32); + } } } }@@ -181,7 +203,6 @@ CoreController::Interrupter interrupter(m_controller);
png_structp png = PNGWriteOpen(vf); png_infop info = PNGWriteHeaderA(png, m_rawMap.width(), m_rawMap.height()); - mMapCache* mapCache = mMapCacheSetGetPointer(&m_cacheSet->maps, m_map); QImage map = m_rawMap.rgbSwapped(); PNGWritePixelsA(png, map.width(), map.height(), map.bytesPerLine() / 4, static_cast<const void*>(map.constBits())); PNGWriteClose(png, info);
@@ -45,6 +45,7 @@ Ui::MapView m_ui;
std::shared_ptr<CoreController> m_controller; mMapCacheEntry m_mapStatus[128 * 128] = {}; // TODO: Correct size + mBitmapCacheEntry m_bitmapStatus[512 * 2] = {}; // TODO: Correct size int m_map = 0; QImage m_rawMap; int m_boundary;