src/platform/python/mgba/core.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 . import tile
8from cached_property import cached_property
9
10def find(path):
11 core = lib.mCoreFind(path.encode('UTF-8'))
12 if core == ffi.NULL:
13 return None
14 return Core._init(core)
15
16def findVF(vf):
17 core = lib.mCoreFindVF(vf.handle)
18 if core == ffi.NULL:
19 return None
20 return Core._init(core)
21
22def loadPath(path):
23 core = find(path)
24 if not core or not core.loadFile(path):
25 return None
26 return core
27
28def loadVF(vf):
29 core = findVF(vf)
30 if not core or not core.loadROM(vf):
31 return None
32 return core
33
34def needsReset(f):
35 def wrapper(self, *args, **kwargs):
36 if not self._wasReset:
37 raise RuntimeError("Core must be reset first")
38 return f(self, *args, **kwargs)
39 return wrapper
40
41class Core(object):
42 def __init__(self, native):
43 self._core = native
44 self._wasReset = False
45
46 @cached_property
47 def tiles(self):
48 return tile.TileView(self)
49
50 @classmethod
51 def _init(cls, native):
52 core = ffi.gc(native, native.deinit)
53 success = bool(core.init(core))
54 if not success:
55 raise RuntimeError("Failed to initialize core")
56 if hasattr(cls, 'PLATFORM_GBA') and core.platform(core) == cls.PLATFORM_GBA:
57 return GBA(core)
58 if hasattr(cls, 'PLATFORM_GB') and core.platform(core) == cls.PLATFORM_GB:
59 return GB(core)
60 return Core(core)
61
62 def _deinit(self):
63 self._core.deinit(self._core)
64
65 def loadFile(self, path):
66 return bool(lib.mCoreLoadFile(self._core, path.encode('UTF-8')))
67
68 def isROM(self, vf):
69 return bool(self._core.isROM(vf.handle))
70
71 def loadROM(self, vf):
72 return bool(self._core.loadROM(self._core, vf.handle))
73
74 def loadSave(self, vf):
75 return bool(self._core.loadSave(self._core, vf.handle))
76
77 def loadTemporarySave(self, vf):
78 return bool(self._core.loadTemporarySave(self._core, vf.handle))
79
80 def loadPatch(self, vf):
81 return bool(self._core.loadPatch(self._core, vf.handle))
82
83 def autoloadSave(self):
84 return bool(lib.mCoreAutoloadSave(self._core))
85
86 def autoloadPatch(self):
87 return bool(lib.mCoreAutoloadPatch(self._core))
88
89 def platform(self):
90 return self._core.platform(self._core)
91
92 def desiredVideoDimensions(self):
93 width = ffi.new("unsigned*")
94 height = ffi.new("unsigned*")
95 self._core.desiredVideoDimensions(self._core, width, height)
96 return width[0], height[0]
97
98 def setVideoBuffer(self, image):
99 self._core.setVideoBuffer(self._core, image.buffer, image.stride)
100
101 def reset(self):
102 self._core.reset(self._core)
103 self._wasReset = True
104
105 @needsReset
106 def runFrame(self):
107 self._core.runFrame(self._core)
108
109 @needsReset
110 def runLoop(self):
111 self._core.runLoop(self._core)
112
113 @needsReset
114 def step(self):
115 self._core.step(self._core)
116
117 @staticmethod
118 def _keysToInt(*args, **kwargs):
119 keys = 0
120 if 'raw' in kwargs:
121 keys = kwargs['raw']
122 for key in args:
123 keys |= 1 << key
124 return keys
125
126 def setKeys(self, *args, **kwargs):
127 self._core.setKeys(self._core, self._keysToInt(*args, **kwargs))
128
129 def addKeys(self, *args, **kwargs):
130 self._core.addKeys(self._core, self._keysToInt(*args, **kwargs))
131
132 def clearKeys(self, *args, **kwargs):
133 self._core.clearKeys(self._core, self._keysToInt(*args, **kwargs))
134
135 @needsReset
136 def frameCounter(self):
137 return self._core.frameCounter(self._core)
138
139 def frameCycles(self):
140 return self._core.frameCycles(self._core)
141
142 def frequency(self):
143 return self._core.frequency(self._core)
144
145 def getGameTitle(self):
146 title = ffi.new("char[16]")
147 self._core.getGameTitle(self._core, title)
148 return ffi.string(title, 16).decode("ascii")
149
150 def getGameCode(self):
151 code = ffi.new("char[12]")
152 self._core.getGameCode(self._core, code)
153 return ffi.string(code, 12).decode("ascii")
154
155if hasattr(lib, 'PLATFORM_GBA'):
156 from .gba import GBA
157 Core.PLATFORM_GBA = lib.PLATFORM_GBA
158
159if hasattr(lib, 'PLATFORM_GB'):
160 from .gb import GB
161 from .lr35902 import LR35902Core
162 Core.PLATFORM_GB = lib.PLATFORM_GB