From bec2757dbf0ddb3d28d09353d2cc4a7aea716103 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 24 Sep 2017 22:30:53 -0700 Subject: [PATCH] Python: Add map view --- include/mgba/core/map-cache.h | 1 + src/core/map-cache.c | 28 ++++++++++++++++++++++++++++ src/platform/python/_builder.h | 15 +++++++++++---- src/platform/python/_builder.py | 5 ++++- src/platform/python/mgba/core.py | 8 ++++++++ src/platform/python/mgba/tile.py | 21 +++++++++++++++++++++ 6 files changed, 73 insertions(+), 5 deletions(-) diff --git a/include/mgba/core/map-cache.h b/include/mgba/core/map-cache.h index 0ceeb5d98..6dc9e72f6 100644 --- a/include/mgba/core/map-cache.h +++ b/include/mgba/core/map-cache.h @@ -71,6 +71,7 @@ uint32_t mMapCacheTileId(struct mMapCache* cache, unsigned x, unsigned y); bool mMapCacheCheckTile(struct mMapCache* cache, const struct mMapCacheEntry* entry, unsigned x, unsigned y); void mMapCacheCleanTile(struct mMapCache* cache, struct mMapCacheEntry* entry, unsigned x, unsigned y); +void mMapCacheCleanRow(struct mMapCache* cache, unsigned y); const color_t* mMapCacheGetRow(struct mMapCache* cache, unsigned y); CXX_GUARD_END diff --git a/src/core/map-cache.c b/src/core/map-cache.c index 980f26899..495978672 100644 --- a/src/core/map-cache.c +++ b/src/core/map-cache.c @@ -171,6 +171,34 @@ bool mMapCacheCheckTile(struct mMapCache* cache, const struct mMapCacheEntry* en return false; } +void mMapCacheCleanRow(struct mMapCache* cache, unsigned y) { + // TODO: Cache + int tilesWide = 1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig); + int macroTile = (1 << mMapCacheSystemInfoGetMacroTileSize(cache->sysConfig)) - 1; + size_t stride = 8 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig); + int location = 0; + int x; + for (x = 0; x < tilesWide; ++x) { + if (!(x & macroTile)) { + location = mMapCacheTileId(cache, x, y); + } else { + ++location; + } + struct mMapCacheEntry* status = &cache->status[location]; + if (!mMapCacheEntryFlagsIsVramClean(status->flags)) { + status->flags = mMapCacheEntryFlagsFillVramClean(status->flags); + cache->mapParser(cache, status, &cache->vram[cache->mapStart + (location << mMapCacheSystemInfoGetMapAlign(cache->sysConfig))]); + } + unsigned tileId = status->tileId + cache->tileStart; + if (tileId >= mTileCacheSystemInfoGetMaxTiles(cache->tileCache->sysConfig)) { + tileId = 0; + } + const color_t* tile = mTileCacheGetTile(cache->tileCache, tileId, mMapCacheEntryFlagsGetPaletteId(status->flags)); + color_t* mapOut = &cache->cache[(y * stride + x) * 8]; + _cleanTile(cache, tile, mapOut, status); + } +} + const color_t* mMapCacheGetRow(struct mMapCache* cache, unsigned y) { size_t stride = 8 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig); return &cache->cache[y * stride]; diff --git a/src/platform/python/_builder.h b/src/platform/python/_builder.h index 9476a37dc..cb823125b 100644 --- a/src/platform/python/_builder.h +++ b/src/platform/python/_builder.h @@ -8,8 +8,14 @@ #define ATTRIBUTE_FORMAT(X, Y, Z) #define DECL_BITFIELD(newtype, oldtype) typedef oldtype newtype -#define DECL_BIT(type, name, bit) -#define DECL_BITS(type, name, bit, nbits) +#define DECL_BIT(type, field, bit) DECL_BITS(type, field, bit, 1) +#define DECL_BITS(TYPE, FIELD, START, SIZE) \ + TYPE TYPE ## Is ## FIELD (TYPE); \ + TYPE TYPE ## Get ## FIELD (TYPE); \ + TYPE TYPE ## Clear ## FIELD (TYPE); \ + TYPE TYPE ## Fill ## FIELD (TYPE); \ + TYPE TYPE ## Set ## FIELD (TYPE, TYPE); \ + TYPE TYPE ## TestFill ## FIELD (TYPE, bool); #define CXX_GUARD_START #define CXX_GUARD_END @@ -29,9 +35,10 @@ void free(void*); #include "flags.h" -#include -#include #include +#include +#include +#include #include #include diff --git a/src/platform/python/_builder.py b/src/platform/python/_builder.py index 0576be542..0d57d4173 100644 --- a/src/platform/python/_builder.py +++ b/src/platform/python/_builder.py @@ -17,14 +17,17 @@ if __name__ == "__main__": cppflags.extend(["-I" + incdir, "-I" + srcdir, "-I" + bindir]) ffi.set_source("mgba._pylib", """ +#define static +#define inline #include "flags.h" #define OPAQUE_THREADING +#include #include #include +#include #include #include #include -#include #include #include #include diff --git a/src/platform/python/mgba/core.py b/src/platform/python/mgba/core.py index 029c6a0ff..8b7abbf84 100644 --- a/src/platform/python/mgba/core.py +++ b/src/platform/python/mgba/core.py @@ -117,6 +117,14 @@ class Core(object): t.append(tile.TileView(lib.mTileCacheSetGetPointer(ts, i))) return t + @cached_property + def maps(self): + m = [] + ms = ffi.addressof(self.graphicsCache.cache.maps) + for i in range(lib.mMapCacheSetSize(ms)): + m.append(tile.MapView(lib.mMapCacheSetGetPointer(ms, i))) + return m + @classmethod def _init(cls, native): core = ffi.gc(native, native.deinit) diff --git a/src/platform/python/mgba/tile.py b/src/platform/python/mgba/tile.py index e48973cde..3dbc060ad 100644 --- a/src/platform/python/mgba/tile.py +++ b/src/platform/python/mgba/tile.py @@ -32,6 +32,27 @@ class TileView: def getTile(self, tile, palette): return Tile(lib.mTileCacheGetTile(self.cache, tile, palette)) +class MapView: + def __init__(self, cache): + self.cache = cache + + @property + def width(self): + return 1 << lib.mMapCacheSystemInfoGetTilesWide(self.cache.sysConfig) + + @property + def height(self): + return 1 << lib.mMapCacheSystemInfoGetTilesHigh(self.cache.sysConfig) + + @property + def image(self): + i = image.Image(self.width * 8, self.height * 8, alpha=True) + for y in range(self.height * 8): + if not y & 7: + lib.mMapCacheCleanRow(self.cache, y >> 3) + row = lib.mMapCacheGetRow(self.cache, y) + ffi.memmove(ffi.addressof(i.buffer, i.stride * y), row, self.width * 8 * ffi.sizeof("color_t")) + return i class Sprite(object): def constitute(self, tileView, tilePitch):