Python: Fix tiles
Vicki Pfau vi@endrift.com
Sun, 24 Sep 2017 21:33:03 -0700
7 files changed,
60 insertions(+),
43 deletions(-)
M
src/platform/python/_builder.py
→
src/platform/python/_builder.py
@@ -75,7 +75,7 @@ import os, os.path
venv = os.getenv('VIRTUAL_ENV') if venv: activate = os.path.join(venv, 'bin', 'activate_this.py') - execfile(activate, dict(__file__=activate)) + exec(compile(open(activate, "rb").read(), activate, 'exec'), dict(__file__=activate)) from mgba._pylib import ffi, lib symbols = {} globalSyms = {
M
src/platform/python/mgba/core.py
→
src/platform/python/mgba/core.py
@@ -106,8 +106,16 @@ self._core.addCoreCallbacks(self._core, self._callbacks.context)
self.config = Config(ffi.addressof(native.config)) @cached_property + def graphicsCache(self): + return tile.CacheSet(self) + + @cached_property def tiles(self): - return tile.TileView(self) + t = [] + ts = ffi.addressof(self.graphicsCache.cache.tiles) + for i in range(lib.mTileCacheSetSize(ts)): + t.append(tile.TileView(lib.mTileCacheSetGetPointer(ts, i))) + return t @classmethod def _init(cls, native):
M
src/platform/python/mgba/gb.py
→
src/platform/python/mgba/gb.py
@@ -27,13 +27,13 @@ self.sprites = GBObjs(self)
self.cpu = LR35902Core(self._core.cpu) @needsReset - def _initTileCache(self, cache): - lib.GBVideoTileCacheInit(cache) - lib.GBVideoTileCacheAssociate(cache, ffi.addressof(self._native.video)) + def _initCache(self, cache): + lib.GBVideoCacheInit(cache) + lib.GBVideoCacheAssociate(cache, ffi.addressof(self._native.video)) - def _deinitTileCache(self, cache): + def _deinitCache(self, cache): self._native.video.renderer.cache = ffi.NULL - lib.mTileCacheDeinit(cache) + lib.mCacheSetDeinit(cache) def reset(self): super(GB, self).reset()@@ -135,6 +135,7 @@ self.tile += 512
self.paletteId = self._attr & 7 else: self.paletteId = (self._attr >> 4) & 1 + self.paletteId += 8 class GBObjs:@@ -149,5 +150,5 @@ def __getitem__(self, index):
if index >= len(self): raise IndexError() sprite = GBSprite(self._obj[index], self._core) - sprite.constitute(self._core.tiles, 0, 0) + sprite.constitute(self._core.tiles[0], 0) return sprite
M
src/platform/python/mgba/gba.py
→
src/platform/python/mgba/gba.py
@@ -35,13 +35,13 @@ self.sprites = GBAObjs(self)
self.cpu = ARMCore(self._core.cpu) @needsReset - def _initTileCache(self, cache): - lib.GBAVideoTileCacheInit(cache) - lib.GBAVideoTileCacheAssociate(cache, ffi.addressof(self._native.video)) + def _initCache(self, cache): + lib.GBAVideoCacheInit(cache) + lib.GBAVideoCacheAssociate(cache, ffi.addressof(self._native.video)) - def _deinitTileCache(self, cache): + def _deinitCache(self, cache): self._native.video.renderer.cache = ffi.NULL - lib.mTileCacheDeinit(cache) + lib.mCacheSetDeinit(cache) def reset(self): super(GBA, self).reset()@@ -127,6 +127,7 @@ def __getitem__(self, index):
if index >= len(self): raise IndexError() sprite = GBASprite(self._obj[index]) + tiles = self._core.tiles[3 if sprite._256Color else 2] map1D = bool(self._core._native.memory.io[0] & 0x40) - sprite.constitute(self._core.tiles, 0 if map1D else 0x20, int(sprite._256Color)) + sprite.constitute(tiles, 0 if map1D else 0x20) return sprite
M
src/platform/python/mgba/image.py
→
src/platform/python/mgba/image.py
@@ -12,10 +12,11 @@ except ImportError:
pass class Image: - def __init__(self, width, height, stride=0): + def __init__(self, width, height, stride=0, alpha=False): self.width = width self.height = height self.stride = stride + self.alpha = alpha self.constitute() def constitute(self):@@ -24,7 +25,7 @@ self.stride = self.width
self.buffer = ffi.new("color_t[{}]".format(self.stride * self.height)) def savePNG(self, f): - p = png.PNG(f) + p = png.PNG(f, mode=png.MODE_RGBA if self.alpha else png.MODE_RGB) success = p.writeHeader(self) success = success and p.writePixels(self) p.writeClose()@@ -32,8 +33,9 @@ return success
if 'PImage' in globals(): def toPIL(self): - return PImage.frombytes("RGBX", (self.width, self.height), ffi.buffer(self.buffer), "raw", - "RGBX", self.stride * 4) + type = "RGBA" if self.alpha else "RGBX" + return PImage.frombytes(type, (self.width, self.height), ffi.buffer(self.buffer), "raw", + type, self.stride * 4) def u16ToU32(c): r = c & 0x1F
M
src/platform/python/mgba/png.py
→
src/platform/python/mgba/png.py
@@ -6,17 +6,32 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
from ._pylib import ffi, lib from . import vfs +MODE_RGB = 0 +MODE_RGBA = 1 +MODE_INDEX = 2 + class PNG: - def __init__(self, f): + def __init__(self, f, mode=MODE_RGB): self.vf = vfs.open(f) + self.mode = mode def writeHeader(self, image): self._png = lib.PNGWriteOpen(self.vf.handle) - self._info = lib.PNGWriteHeader(self._png, image.width, image.height) + if self.mode == MODE_RGB: + self._info = lib.PNGWriteHeader(self._png, image.width, image.height) + if self.mode == MODE_RGBA: + self._info = lib.PNGWriteHeaderA(self._png, image.width, image.height) + if self.mode == MODE_INDEX: + self._info = lib.PNGWriteHeader8(self._png, image.width, image.height) return self._info != ffi.NULL def writePixels(self, image): - return lib.PNGWritePixels(self._png, image.width, image.height, image.stride, image.buffer) + if self.mode == MODE_RGB: + return lib.PNGWritePixels(self._png, image.width, image.height, image.stride, image.buffer) + if self.mode == MODE_RGBA: + return lib.PNGWritePixelsA(self._png, image.width, image.height, image.stride, image.buffer) + if self.mode == MODE_INDEX: + return lib.PNGWritePixels8(self._png, image.width, image.height, image.stride, image.buffer) def writeClose(self): lib.PNGWriteClose(self._png, self._info)
M
src/platform/python/mgba/tile.py
→
src/platform/python/mgba/tile.py
@@ -17,41 +17,31 @@ return i
def composite(self, i, x, y): for iy in range(8): - for ix in range(8): - i.buffer[ix + x + (iy + y) * i.stride] = image.u16ToColor(self.buffer[ix + iy * 8]) + ffi.memmove(ffi.addressof(i.buffer, x + (iy + y) * i.stride), ffi.addressof(self.buffer, iy * 8), 8 * ffi.sizeof("color_t")) -class TileView: +class CacheSet: def __init__(self, core): self.core = core - self.cache = ffi.gc(ffi.new("struct mTileCache*"), core._deinitTileCache) - core._initTileCache(self.cache) - lib.mTileCacheSetPalette(self.cache, 0) - self.paletteSet = 0 + self.cache = ffi.gc(ffi.new("struct mCacheSet*"), core._deinitCache) + core._initCache(self.cache) + +class TileView: + def __init__(self, cache): + self.cache = cache def getTile(self, tile, palette): return Tile(lib.mTileCacheGetTile(self.cache, tile, palette)) - def setPalette(self, paletteSet): - if paletteSet > 1 or paletteSet < 0: - raise IndexError("Palette Set ID out of bounds") - lib.mTileCacheSetPalette(self.cache, paletteSet) - self.paletteSet = paletteSet class Sprite(object): - TILE_BASE = 0, 0 - PALETTE_BASE = 0, 0 - - def constitute(self, tileView, tilePitch, paletteSet): - oldPaletteSet = tileView.paletteSet - tileView.setPalette(paletteSet) - i = image.Image(self.width, self.height) - tileId = self.tile + self.TILE_BASE[paletteSet] + def constitute(self, tileView, tilePitch): + i = image.Image(self.width, self.height, alpha=True) + tileId = self.tile for y in range(self.height // 8): for x in range(self.width // 8): - tile = tileView.getTile(tileId, self.paletteId + self.PALETTE_BASE[paletteSet]) + tile = tileView.getTile(tileId, self.paletteId) tile.composite(i, x * 8, y * 8) tileId += 1 if tilePitch: tileId += tilePitch - self.width // 8 self.image = i - tileView.setPalette(oldPaletteSet)