all repos — mgba @ f026c900892409d92b588f5789108f9079732af2

mGBA Game Boy Advance Emulator

src/platform/python/mgba/gba.py (view raw)

 1# Copyright (c) 2013-2016 Jeffrey Pfau
 2#
 3# This Source Code Form is subject to the terms of the Mozilla Public
 4# License, v. 2.0. If a copy of the MPL was not distributed with this
 5# file, You can obtain one at http://mozilla.org/MPL/2.0/.
 6from ._pylib import ffi, lib
 7from .arm import ARMCore
 8from .core import Core, needsReset
 9from .tile import Sprite
10from .memory import Memory
11
12class GBA(Core):
13    KEY_A = lib.GBA_KEY_A
14    KEY_B = lib.GBA_KEY_B
15    KEY_SELECT = lib.GBA_KEY_SELECT
16    KEY_START = lib.GBA_KEY_START
17    KEY_DOWN = lib.GBA_KEY_DOWN
18    KEY_UP = lib.GBA_KEY_UP
19    KEY_LEFT = lib.GBA_KEY_LEFT
20    KEY_RIGHT = lib.GBA_KEY_RIGHT
21    KEY_L = lib.GBA_KEY_L
22    KEY_R = lib.GBA_KEY_R
23
24    def __init__(self, native):
25        super(GBA, self).__init__(native)
26        self._native = ffi.cast("struct GBA*", native.board)
27        self.sprites = GBAObjs(self)
28        self.cpu = ARMCore(self._core.cpu)
29
30    @needsReset
31    def _initTileCache(self, cache):
32        lib.GBAVideoTileCacheInit(cache)
33        lib.GBAVideoTileCacheAssociate(cache, ffi.addressof(self._native.video))
34
35    def _deinitTileCache(self, cache):
36        self._native.video.renderer.cache = ffi.NULL
37        lib.mTileCacheDeinit(cache)
38
39    def reset(self):
40        super(GBA, self).reset()
41        self.memory = GBAMemory(self._core, self._native.memory.romSize)
42
43class GBAMemory(Memory):
44    def __init__(self, core, romSize=lib.SIZE_CART0):
45        super(GBAMemory, self).__init__(core, 0x100000000)
46
47        self.bios = Memory(core, lib.SIZE_BIOS, lib.BASE_BIOS)
48        self.wram = Memory(core, lib.SIZE_WORKING_RAM, lib.BASE_WORKING_RAM)
49        self.iwram = Memory(core, lib.SIZE_WORKING_IRAM, lib.BASE_WORKING_IRAM)
50        self.io = Memory(core, lib.SIZE_IO, lib.BASE_IO)
51        self.palette = Memory(core, lib.SIZE_PALETTE_RAM, lib.BASE_PALETTE_RAM)
52        self.vram = Memory(core, lib.SIZE_VRAM, lib.BASE_VRAM)
53        self.oam = Memory(core, lib.SIZE_OAM, lib.BASE_OAM)
54        self.cart0 = Memory(core, romSize, lib.BASE_CART0)
55        self.cart1 = Memory(core, romSize, lib.BASE_CART1)
56        self.cart2 = Memory(core, romSize, lib.BASE_CART2)
57        self.cart = self.cart0
58        self.rom = self.cart0
59        self.sram = Memory(core, lib.SIZE_CART_SRAM, lib.BASE_CART_SRAM)
60
61class GBASprite(Sprite):
62    TILE_BASE = 0x800, 0x400
63    PALETTE_BASE = 0x10, 1
64
65    def __init__(self, obj):
66        self._a = obj.a
67        self._b = obj.b
68        self._c = obj.c
69        self.x = self._b & 0x1FF
70        self.y = self._a & 0xFF
71        self._shape = self._a >> 14
72        self._size = self._b >> 14
73        self._256Color = bool(self._a & 0x2000)
74        self.width, self.height = lib.GBAVideoObjSizes[self._shape * 4 + self._size]
75        self.tile = self._c & 0x3FF
76        if self._256Color:
77            self.paletteId = 0
78            self.tile >>= 1
79        else:
80            self.paletteId = self._c >> 12
81
82class GBAObjs:
83    def __init__(self, core):
84        self._core = core
85        self._obj = core._native.video.oam.obj
86
87    def __len__(self):
88        return 128
89
90    def __getitem__(self, index):
91        if index >= len(self):
92            raise IndexError()
93        sprite = GBASprite(self._obj[index])
94        map1D = bool(self._core._native.memory.io[0] & 0x40)
95        sprite.constitute(self._core.tiles, 0 if map1D else 0x20, int(sprite._256Color))
96        return sprite