all repos — mgba @ e2bcd2e05ad4d8fa879a5b32f56c91e1f5e4c964

mGBA Game Boy Advance Emulator

Python: Add memory access
Jeffrey Pfau jeffrey@endrift.com
Thu, 27 Oct 2016 18:39:52 -0700
commit

e2bcd2e05ad4d8fa879a5b32f56c91e1f5e4c964

parent

572eb40d420984f477269200dd7988eba09552bd

M src/platform/python/mgba/gb.pysrc/platform/python/mgba/gb.py

@@ -6,6 +6,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/.

from ._pylib import ffi, lib from .lr35902 import LR35902Core from .core import Core +from .memory import Memory from .tile import Sprite class GB(Core):

@@ -31,6 +32,18 @@

def _deinitTileCache(self, cache): self._native.video.renderer.cache = ffi.NULL lib.mTileCacheDeinit(cache) + +class GBMemory(Memory): + def __init__(self, core): + super(GBMemory, self).__init__(core, 0x10000) + + self.cart = Memory(core, lib.GB_SIZE_CART_BANK0 * 2, lib.GB_BASE_CART_BANK0) + self.vram = Memory(core, lib.GB_SIZE_VRAM, lib.GB_BASE_VRAM) + self.sram = Memory(core, lib.GB_SIZE_EXTERNAL_RAM, lib.GB_REGION_EXTERNAL_RAM) + self.iwram = Memory(core, lib.GB_SIZE_WORKING_RAM_BANK0, lib.GB_BASE_WORKING_RAM_BANK0) + self.oam = Memory(core, lib.GB_SIZE_OAM, lib.GB_BASE_OAM) + self.io = Memory(core, lib.GB_SIZE_IO, lib.GB_BASE_IO) + self.hram = Memory(core, lib.GB_SIZE_HRAM, lib.GB_BASE_HRAM) class GBSprite(Sprite): PALETTE_BASE = 8,
M src/platform/python/mgba/gba.pysrc/platform/python/mgba/gba.py

@@ -7,6 +7,7 @@ from ._pylib import ffi, lib

from .arm import ARMCore from .core import Core from .tile import Sprite +from .memory import Memory class GBA(Core): KEY_A = lib.GBA_KEY_A

@@ -25,6 +26,7 @@ super(GBA, self).__init__(native)

self._native = ffi.cast("struct GBA*", native.board) self.sprites = GBAObjs(self) self.cpu = ARMCore(self._core.cpu) + self.memory = GBAMemory(self._core) def _initTileCache(self, cache): lib.GBAVideoTileCacheInit(cache)

@@ -33,6 +35,23 @@

def _deinitTileCache(self, cache): self._native.video.renderer.cache = ffi.NULL lib.mTileCacheDeinit(cache) + +class GBAMemory(Memory): + def __init__(self, core): + super(GBAMemory, self).__init__(core, 0x100000000) + + self.bios = Memory(core, lib.SIZE_BIOS, lib.BASE_BIOS) + self.wram = Memory(core, lib.SIZE_WORKING_RAM, lib.BASE_WORKING_RAM) + self.iwram = Memory(core, lib.SIZE_WORKING_IRAM, lib.BASE_WORKING_IRAM) + self.io = Memory(core, lib.SIZE_IO, lib.BASE_IO) + self.palette = Memory(core, lib.SIZE_PALETTE_RAM, lib.BASE_PALETTE_RAM) + self.vram = Memory(core, lib.SIZE_VRAM, lib.BASE_VRAM) + self.oam = Memory(core, lib.SIZE_OAM, lib.BASE_OAM) + self.cart0 = Memory(core, lib.SIZE_CART0, lib.BASE_CART0) + self.cart1 = Memory(core, lib.SIZE_CART1, lib.BASE_CART1) + self.cart2 = Memory(core, lib.SIZE_CART2, lib.BASE_CART2) + self.cart = self.cart0 + self.sram = Memory(core, lib.SIZE_CART_SRAM, lib.BASE_CART_SRAM) class GBASprite(Sprite): TILE_BASE = 0x800, 0x400
A src/platform/python/mgba/memory.py

@@ -0,0 +1,64 @@

+# Copyright (c) 2013-2016 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/. +from ._pylib import ffi, lib + +class MemoryView(object): + def __init__(self, core, width, size, base=0, sign="u"): + self._core = core + self._width = width + self._size = size + self._base = base + self._busRead = getattr(self._core, "busRead" + str(width * 8)) + self._busWrite = getattr(self._core, "busWrite" + str(width * 8)) + self._rawRead = getattr(self._core, "rawRead" + str(width * 8)) + self._rawWrite = getattr(self._core, "rawWrite" + str(width * 8)) + self._mask = (1 << (width * 8)) - 1 # Used to force values to fit within range so that negative values work + if sign == "u" or sign == "unsigned": + self._type = "uint{}_t".format(width * 8) + elif sign == "i" or sign == "s" or sign == "signed": + self._type = "int{}_t".format(width * 8) + else: + raise ValueError("Invalid sign type: '{}'".format(sign)) + + def _addrCheck(self, address): + if address >= self._size or address + self._width > self._size: + raise IndexError() + if address < 0: + raise IndexError() + + def __len__(self): + return self._size + + def __getitem__(self, address): + self._addrCheck(address) + return int(ffi.cast(self._type, self._busRead(self._core, self._base + address))) + + def __setitem__(self, address, value): + self._addrCheck(address) + self._busWrite(self._core, self._base + address, value & self._mask) + + def rawRead(self, address, segment=-1): + self._addrCheck(address) + return int(ffi.cast(self._type, self._rawRead(self._core, self._base + address, segment))) + + def rawWrite(self, address, value, segment=-1): + self._addrCheck(address) + self._rawWrite(self._core, self._base + address, segment, value & self._mask) + +class Memory(object): + def __init__(self, core, size, base=0): + self.size = size + self.base = base + + self.u8 = MemoryView(core, 1, size, base, "u") + self.u16 = MemoryView(core, 2, size, base, "u") + self.u32 = MemoryView(core, 4, size, base, "u") + self.s8 = MemoryView(core, 1, size, base, "s") + self.s16 = MemoryView(core, 2, size, base, "s") + self.s32 = MemoryView(core, 4, size, base, "s") + + def __len__(self): + return self._size