diff --git a/docs/index.html b/docs/index.html
index 175e11905..9f53e5b74 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -394,6 +394,42 @@
Kwargs
Game title
"""
+ self.cartridge_title = self.mb.cartridge.gametype
+ """
+ The game type stored on the currently loaded cartridge ROM. Values are:
+ Game Boy, Game Boy Color, Super Game Boy
+
+ Example:
+ ```python
+ >>> pyboy.cartridge_type # Game type of PyBoy's default ROM
+ 'Game Boy Color'
+
+ ```
+
+ Returns
+ -------
+ str :
+ Game type
+ """
+
+ self.cartridge_region = self.mb.cartridge.gameregion
+ """
+ The game region stored on the currently loaded cartridge ROM. Example values are:
+ Europe, USA, Japan, Spain, Germany, World...
+
+ Example:
+ ```python
+ >>> pyboy.cartridge_region # Game region of PyBoy's default ROM
+ 'Europe'
+
+ ```
+
+ Returns
+ -------
+ str :
+ Europe
+ """
+
self._hooks = {}
self._plugin_manager = PluginManager(self, self.mb, kwargs)
diff --git a/pyboy/core/cartridge/base_mbc.pxd b/pyboy/core/cartridge/base_mbc.pxd
index 5b8842795..9d404c50e 100644
--- a/pyboy/core/cartridge/base_mbc.pxd
+++ b/pyboy/core/cartridge/base_mbc.pxd
@@ -15,6 +15,8 @@ cdef Logger logger
cdef class BaseMBC:
cdef str filename
cdef str gamename
+ cdef srt gametype
+ cdef str gameregion
cdef uint8_t[:, :] rombanks
cdef uint8_t[:,:] rambanks
cdef uint8_t carttype
@@ -37,6 +39,8 @@ cdef class BaseMBC:
cdef void load_ram(self, IntIOInterface) noexcept
cdef void init_rambanks(self, uint8_t) noexcept
cdef str getgamename(self, uint8_t[:,:]) noexcept
+ cdef str getgametype(self, uint8_t[:,:]) noexcept
+ cdef str getgameregion(self, uint8_t[:,:]) noexcept
cdef uint8_t getitem(self, uint16_t) noexcept nogil
cdef void setitem(self, uint16_t, uint8_t) noexcept nogil
diff --git a/pyboy/core/cartridge/base_mbc.py b/pyboy/core/cartridge/base_mbc.py
index f03bf0fdf..08bc60293 100644
--- a/pyboy/core/cartridge/base_mbc.py
+++ b/pyboy/core/cartridge/base_mbc.py
@@ -34,6 +34,8 @@ def __init__(self, filename, rombanks, external_ram_count, carttype, sram, batte
self.external_ram_count = external_ram_count
self.init_rambanks(external_ram_count)
self.gamename = self.getgamename(rombanks)
+ self.gametype = self.getgametype(rombanks)
+ self.gameregion = self.getgameregion(rombanks)
self.memorymodel = 0
self.rambank_enabled = False
@@ -103,7 +105,55 @@ def init_rambanks(self, n):
self.rambanks = memoryview(array.array("B", [0] * (8*1024*16))).cast("B", shape=(16, 8 * 1024))
def getgamename(self, rombanks):
- return "".join([chr(rombanks[0, x]) for x in range(0x0134, 0x0142)]).split("\0")[0]
+ return "".join([chr(rombanks[0, x]) for x in range(0x0134, 0x0143)]).split("\0")[0]
+
+ def getgametype(self, rombanks):
+ if rombanks[0, 0x143] == 0x80 or rombanks[0, 0x143] == 0xc0:
+ return "Game Boy Color"
+ elif rombanks[0, 0x146] == 0x03:
+ return "Super Game Boy"
+ else:
+ return "Game Boy"
+
+ def getgameregion(self, rombanks):
+ game_type = self.getgametype(rombanks)
+ # The region character is only present in GBC/SGB games only; for regular GB games can't be fetched
+ if game_type == 'Game Boy':
+ return "Unknown"
+ else:
+ # Get the last letter of the sales code that determines the region
+ region_string = "".join([chr(rombanks[0, x]) for x in range(0x13f, 0x0143)]).split("\0")[0]
+ if region_string:
+ region_code = region_string[-1]
+ else:
+ return "Unknown"
+ # Return game region according to the last letter of the serial code
+ if region_code == 'J':
+ return "Japan"
+ elif region_code == 'E':
+ return "USA"
+ elif region_code == 'P':
+ return "Europe"
+ elif region_code == 'S':
+ return "Spain"
+ elif region_code == 'I':
+ return "Italy"
+ elif region_code == 'F':
+ return "France"
+ elif region_code == 'D':
+ return "Germany"
+ elif region_code == 'A':
+ return "World"
+ elif region_code == 'X':
+ return "Europe"
+ elif region_code == 'Y':
+ return "Europe"
+ elif region_code == 'K':
+ return "Korea"
+ elif region_code == 'U':
+ return "Australia"
+ else:
+ return "Unknown"
def setitem(self, address, value):
raise Exception("Cannot set item in MBC")
@@ -138,6 +188,8 @@ def __repr__(self):
"MBC class: %s" % self.__class__.__name__,
"Filename: %s" % self.filename,
"Game name: %s" % self.gamename,
+ "Game type: %s" % self.gametype,
+ "Game region: %s" % self.gameregion,
"GB Color: %s" % str(self.rombanks[0, 0x143] == 0x80),
"Cartridge type: %s" % hex(self.carttype),
"Number of ROM banks: %s" % self.external_rom_count,
diff --git a/pyboy/pyboy.pxd b/pyboy/pyboy.pxd
index fec26265d..3353648a1 100644
--- a/pyboy/pyboy.pxd
+++ b/pyboy/pyboy.pxd
@@ -60,6 +60,8 @@ cdef class PyBoy:
cdef readonly object game_wrapper
cdef readonly MemoryScanner memory_scanner
cdef readonly str cartridge_title
+ cdef readonly str cartridge_type
+ cdef readonly str cartridge_region
cdef bint limit_emulationspeed
cdef int emulationspeed, target_emulationspeed, save_target_emulationspeed
diff --git a/pyboy/pyboy.py b/pyboy/pyboy.py
index f2c969134..674462521 100644
--- a/pyboy/pyboy.py
+++ b/pyboy/pyboy.py
@@ -323,6 +323,42 @@ def __init__(
Game title
"""
+ self.cartridge_type = self.mb.cartridge.gametype
+ """
+ The game type stored on the currently loaded cartridge ROM. Values are:
+ Game Boy, Game Boy Color, Super Game Boy
+
+ Example:
+ ```python
+ >>> pyboy.cartridge_type # Game type of PyBoy's default ROM
+ 'Game Boy Color'
+
+ ```
+
+ Returns
+ -------
+ str :
+ Game type
+ """
+
+ self.cartridge_region = self.mb.cartridge.gameregion
+ """
+ The game region stored on the currently loaded cartridge ROM. Example values are:
+ Europe, USA, Japan, Spain, Germany, World...
+
+ Example:
+ ```python
+ >>> pyboy.cartridge_region # Game region of PyBoy's default ROM
+ 'Europe'
+
+ ```
+
+ Returns
+ -------
+ str :
+ Europe
+ """
+
self._hooks = {}
self._plugin_manager = PluginManager(self, self.mb, kwargs)