src/platform/python/mgba/gb.py (view raw)
1# Copyright (c) 2013-2017 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 .lr35902 import LR35902Core
8from .core import Core, needsReset
9from .memory import Memory
10from .tile import Sprite
11from . import createCallback
12
13class GB(Core):
14 KEY_A = lib.GBA_KEY_A
15 KEY_B = lib.GBA_KEY_B
16 KEY_SELECT = lib.GBA_KEY_SELECT
17 KEY_START = lib.GBA_KEY_START
18 KEY_DOWN = lib.GBA_KEY_DOWN
19 KEY_UP = lib.GBA_KEY_UP
20 KEY_LEFT = lib.GBA_KEY_LEFT
21 KEY_RIGHT = lib.GBA_KEY_RIGHT
22
23 def __init__(self, native):
24 super(GB, self).__init__(native)
25 self._native = ffi.cast("struct GB*", native.board)
26 self.sprites = GBObjs(self)
27 self.cpu = LR35902Core(self._core.cpu)
28
29 @needsReset
30 def _initCache(self, cache):
31 lib.GBVideoCacheInit(cache)
32 lib.GBVideoCacheAssociate(cache, ffi.addressof(self._native.video))
33
34 def _deinitCache(self, cache):
35 lib.mCacheSetDeinit(cache)
36 if self._wasReset:
37 self._native.video.renderer.cache = ffi.NULL
38
39 def _load(self):
40 super(GB, self)._load()
41 self.memory = GBMemory(self._core)
42
43 def attachSIO(self, link):
44 lib.GBSIOSetDriver(ffi.addressof(self._native.sio), link._native)
45
46 def __del__(self):
47 lib.GBSIOSetDriver(ffi.addressof(self._native.sio), ffi.NULL)
48
49createCallback("GBSIOPythonDriver", "init")
50createCallback("GBSIOPythonDriver", "deinit")
51createCallback("GBSIOPythonDriver", "writeSB")
52createCallback("GBSIOPythonDriver", "writeSC")
53
54class GBSIODriver(object):
55 def __init__(self):
56 self._handle = ffi.new_handle(self)
57 self._native = ffi.gc(lib.GBSIOPythonDriverCreate(self._handle), lib.free)
58
59 def init(self):
60 return True
61
62 def deinit(self):
63 pass
64
65 def writeSB(self, value):
66 pass
67
68 def writeSC(self, value):
69 return value
70
71class GBSIOSimpleDriver(GBSIODriver):
72 def __init__(self, period=0x100):
73 super(GBSIOSimpleDriver, self).__init__()
74 self.rx = 0x00
75 self._period = period
76
77 def init(self):
78 self._native.p.period = self._period
79 return True
80
81 def writeSB(self, value):
82 self.rx = value
83
84 def writeSC(self, value):
85 self._native.p.period = self._period
86 if value & 0x80:
87 lib.mTimingDeschedule(ffi.addressof(self._native.p.p.timing), ffi.addressof(self._native.p.event))
88 lib.mTimingSchedule(ffi.addressof(self._native.p.p.timing), ffi.addressof(self._native.p.event), self._native.p.period)
89 return value
90
91 def isReady(self):
92 return not self._native.p.remainingBits
93
94 @property
95 def tx(self):
96 self._native.p.pendingSB
97
98 @property
99 def period(self):
100 return self._native.p.period
101
102 @tx.setter
103 def tx(self, newTx):
104 self._native.p.pendingSB = newTx
105 self._native.p.remainingBits = 8
106
107 @period.setter
108 def period(self, newPeriod):
109 self._period = newPeriod
110 if self._native.p:
111 self._native.p.period = newPeriod
112
113class GBMemory(Memory):
114 def __init__(self, core):
115 super(GBMemory, self).__init__(core, 0x10000)
116
117 self.cart = Memory(core, lib.GB_SIZE_CART_BANK0 * 2, lib.GB_BASE_CART_BANK0)
118 self.vram = Memory(core, lib.GB_SIZE_VRAM, lib.GB_BASE_VRAM)
119 self.sram = Memory(core, lib.GB_SIZE_EXTERNAL_RAM, lib.GB_REGION_EXTERNAL_RAM)
120 self.iwram = Memory(core, lib.GB_SIZE_WORKING_RAM_BANK0, lib.GB_BASE_WORKING_RAM_BANK0)
121 self.oam = Memory(core, lib.GB_SIZE_OAM, lib.GB_BASE_OAM)
122 self.io = Memory(core, lib.GB_SIZE_IO, lib.GB_BASE_IO)
123 self.hram = Memory(core, lib.GB_SIZE_HRAM, lib.GB_BASE_HRAM)
124
125class GBSprite(Sprite):
126 PALETTE_BASE = 8,
127
128 def __init__(self, obj, core):
129 self.x = obj.x
130 self.y = obj.y
131 self.tile = obj.tile
132 self._attr = obj.attr
133 self.width = 8
134 lcdc = core._native.memory.io[0x40]
135 self.height = 16 if lcdc & 4 else 8
136 if core._native.model >= lib.GB_MODEL_CGB:
137 if self._attr & 8:
138 self.tile += 512
139 self.paletteId = self._attr & 7
140 else:
141 self.paletteId = (self._attr >> 4) & 1
142 self.paletteId += 8
143
144
145class GBObjs:
146 def __init__(self, core):
147 self._core = core
148 self._obj = core._native.video.oam.obj
149
150 def __len__(self):
151 return 40
152
153 def __getitem__(self, index):
154 if index >= len(self):
155 raise IndexError()
156 sprite = GBSprite(self._obj[index], self._core)
157 sprite.constitute(self._core.tiles[0], 0)
158 return sprite