Python: Add memory access

This commit is contained in:
Jeffrey Pfau 2016-10-27 18:39:52 -07:00
parent 572eb40d42
commit e2bcd2e05a
3 changed files with 96 additions and 0 deletions

View File

@ -6,6 +6,7 @@
from ._pylib import ffi, lib from ._pylib import ffi, lib
from .lr35902 import LR35902Core from .lr35902 import LR35902Core
from .core import Core from .core import Core
from .memory import Memory
from .tile import Sprite from .tile import Sprite
class GB(Core): class GB(Core):
@ -32,6 +33,18 @@ class GB(Core):
self._native.video.renderer.cache = ffi.NULL self._native.video.renderer.cache = ffi.NULL
lib.mTileCacheDeinit(cache) 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): class GBSprite(Sprite):
PALETTE_BASE = 8, PALETTE_BASE = 8,

View File

@ -7,6 +7,7 @@ from ._pylib import ffi, lib
from .arm import ARMCore from .arm import ARMCore
from .core import Core from .core import Core
from .tile import Sprite from .tile import Sprite
from .memory import Memory
class GBA(Core): class GBA(Core):
KEY_A = lib.GBA_KEY_A KEY_A = lib.GBA_KEY_A
@ -25,6 +26,7 @@ class GBA(Core):
self._native = ffi.cast("struct GBA*", native.board) self._native = ffi.cast("struct GBA*", native.board)
self.sprites = GBAObjs(self) self.sprites = GBAObjs(self)
self.cpu = ARMCore(self._core.cpu) self.cpu = ARMCore(self._core.cpu)
self.memory = GBAMemory(self._core)
def _initTileCache(self, cache): def _initTileCache(self, cache):
lib.GBAVideoTileCacheInit(cache) lib.GBAVideoTileCacheInit(cache)
@ -34,6 +36,23 @@ class GBA(Core):
self._native.video.renderer.cache = ffi.NULL self._native.video.renderer.cache = ffi.NULL
lib.mTileCacheDeinit(cache) 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): class GBASprite(Sprite):
TILE_BASE = 0x800, 0x400 TILE_BASE = 0x800, 0x400
PALETTE_BASE = 0x10, 1 PALETTE_BASE = 0x10, 1

View File

@ -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