diff --git a/Config.in b/Config.in
index 2a29eaa2bb50f838d9427a62436d689996781243..c0402f9e960b9ffa362216e831dd099cd2cf4362 100644
--- a/Config.in
+++ b/Config.in
@@ -114,6 +114,7 @@ endmenu
menu "Emulators"
source "$BR2_EXTERNAL_RECALBOX_PATH/package/advancemame/Config.in"
source "$BR2_EXTERNAL_RECALBOX_PATH/package/beebem/Config.in"
+ source "$BR2_EXTERNAL_RECALBOX_PATH/package/creativision/Config.in"
source "$BR2_EXTERNAL_RECALBOX_PATH/package/frotz-recalbox/Config.in"
source "$BR2_EXTERNAL_RECALBOX_PATH/package/hatari/Config.in"
source "$BR2_EXTERNAL_RECALBOX_PATH/package/duckstation/Config.in"
diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index 1dace1899c0a4df551f9babf77977613546bcfbe..60d7bc1a56cbf927f0b368fd23f8b7ea8346afee 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -35,6 +35,7 @@ as release notes for end user on a Recalbox upgrade.
- Bump libretro-fceumm
- Bump libretro-ecwolf
- Bump libretro-bluemsx
+- Add CreatiVision system
### Improvements
diff --git a/board/recalbox/fsoverlay/recalbox/share_init/system/.emulationstation/es_bios.xml b/board/recalbox/fsoverlay/recalbox/share_init/system/.emulationstation/es_bios.xml
index df3f7cc9dc1934551a53b6426de0fa70b215a820..9228d01ca4879169c1a5421322882302c2c84085 100644
--- a/board/recalbox/fsoverlay/recalbox/share_init/system/.emulationstation/es_bios.xml
+++ b/board/recalbox/fsoverlay/recalbox/share_init/system/.emulationstation/es_bios.xml
@@ -42,6 +42,14 @@
+
+
+
+
+
+
+
+
diff --git a/configs/recalbox-odroidgo2_defconfig b/configs/recalbox-odroidgo2_defconfig
index d4780fbfc700fc50ee4c5387ab3590f508c86aa3..a5c8dc38d2d08f6dcad90060bdac9cf093b6b86a 100644
--- a/configs/recalbox-odroidgo2_defconfig
+++ b/configs/recalbox-odroidgo2_defconfig
@@ -169,6 +169,7 @@ BR2_PACKAGE_HATARI=y
BR2_PACKAGE_ADVANCEMAME=y
BR2_PACKAGE_DUCKSTATION=y
BR2_PACKAGE_BEEBEM=y
+BR2_PACKAGE_CREATIVISION=y
BR2_PACKAGE_FROTZ_RECALBOX=y
BR2_PACKAGE_MUPEN64PLUS_AUDIO_SDL=y
BR2_PACKAGE_MUPEN64PLUS_CORE=y
diff --git a/configs/recalbox-rg353x_defconfig b/configs/recalbox-rg353x_defconfig
index a2bd3c51a1ab5a3575549c38419f7e48c02b3ca6..3ebfd414875ebd337266ac74b7787bf325997add 100644
--- a/configs/recalbox-rg353x_defconfig
+++ b/configs/recalbox-rg353x_defconfig
@@ -154,6 +154,7 @@ BR2_PACKAGE_MUPEN64PLUS_UICONSOLE=y
BR2_PACKAGE_HATARI=y
BR2_PACKAGE_ADVANCEMAME=y
BR2_PACKAGE_BEEBEM=y
+BR2_PACKAGE_CREATIVISION=y
BR2_PACKAGE_FROTZ_RECALBOX=y
BR2_PACKAGE_AMIBERRY=y
BR2_PACKAGE_ORICUTRON=y
diff --git a/configs/recalbox-rpi3_defconfig b/configs/recalbox-rpi3_defconfig
index a0990d13c7221a5edac4236776104fd85d391818..71e68e1ed9e11c6498c66eef616ba340052dc06a 100644
--- a/configs/recalbox-rpi3_defconfig
+++ b/configs/recalbox-rpi3_defconfig
@@ -215,6 +215,7 @@ BR2_PACKAGE_MUPEN64PLUS_VIDEO_GLIDE64MK2=y
BR2_PACKAGE_HATARI=y
BR2_PACKAGE_ADVANCEMAME=y
BR2_PACKAGE_BEEBEM=y
+BR2_PACKAGE_CREATIVISION=y
BR2_PACKAGE_FROTZ_RECALBOX=y
BR2_PACKAGE_AMIBERRY=y
BR2_PACKAGE_MUPEN64PLUS_UICONSOLE=y
diff --git a/configs/recalbox-rpi4_64_defconfig b/configs/recalbox-rpi4_64_defconfig
index 5683062600fa594b0f84242a555dc43d4bb8673f..f5932e7ff54aa607d882e4d9f9e35ed5c1a74fa8 100644
--- a/configs/recalbox-rpi4_64_defconfig
+++ b/configs/recalbox-rpi4_64_defconfig
@@ -202,6 +202,7 @@ BR2_PACKAGE_MUPEN64PLUS_UICONSOLE=y
BR2_PACKAGE_HATARI=y
BR2_PACKAGE_ADVANCEMAME=y
BR2_PACKAGE_BEEBEM=y
+BR2_PACKAGE_CREATIVISION=y
BR2_PACKAGE_FROTZ_RECALBOX=y
BR2_PACKAGE_AMIBERRY=y
BR2_PACKAGE_ORICUTRON=y
diff --git a/configs/recalbox-rpi5_64_defconfig b/configs/recalbox-rpi5_64_defconfig
index 32c9908faa317f65399c55fa5e574f8483f25464..5680f16ac9ea2708ad8e6c03aaf27da59897a611 100644
--- a/configs/recalbox-rpi5_64_defconfig
+++ b/configs/recalbox-rpi5_64_defconfig
@@ -202,6 +202,7 @@ BR2_PACKAGE_MUPEN64PLUS_UICONSOLE=y
BR2_PACKAGE_HATARI=y
BR2_PACKAGE_ADVANCEMAME=y
BR2_PACKAGE_BEEBEM=y
+BR2_PACKAGE_CREATIVISION=y
BR2_PACKAGE_FROTZ_RECALBOX=y
BR2_PACKAGE_AMIBERRY=y
BR2_PACKAGE_ORICUTRON=y
diff --git a/configs/recalbox-rpizero2_defconfig b/configs/recalbox-rpizero2_defconfig
index 043dbc3bd384e6a13f30ec382e40f25cb46d78bf..a9c1dda3c295073309f2165734d762c2a0eb904b 100644
--- a/configs/recalbox-rpizero2_defconfig
+++ b/configs/recalbox-rpizero2_defconfig
@@ -215,6 +215,7 @@ BR2_PACKAGE_MUPEN64PLUS_VIDEO_GLIDE64MK2=y
BR2_PACKAGE_HATARI=y
BR2_PACKAGE_ADVANCEMAME=y
BR2_PACKAGE_BEEBEM=y
+BR2_PACKAGE_CREATIVISION=y
BR2_PACKAGE_FROTZ_RECALBOX=y
BR2_PACKAGE_AMIBERRY=y
BR2_PACKAGE_MUPEN64PLUS_UICONSOLE=y
diff --git a/configs/recalbox-x86_64_defconfig b/configs/recalbox-x86_64_defconfig
index 3b081974decc16ce0e11d09d4754c88913a355f0..9ab715573986467a29f8a2cd73031c869411da83 100644
--- a/configs/recalbox-x86_64_defconfig
+++ b/configs/recalbox-x86_64_defconfig
@@ -237,6 +237,7 @@ BR2_PACKAGE_XARCADE2JSTICK=y
# BR2_PACKAGE_ADVANCEMAME is not set
BR2_PACKAGE_HATARI=y
BR2_PACKAGE_BEEBEM=y
+BR2_PACKAGE_CREATIVISION=y
BR2_PACKAGE_FROTZ_RECALBOX=y
BR2_PACKAGE_LINAPPLE_PIE=y
BR2_PACKAGE_DUCKSTATION=y
diff --git a/package/creativision/Config.in b/package/creativision/Config.in
new file mode 100644
index 0000000000000000000000000000000000000000..5b7fb11eb123e0d1f062d1a6f9c6fc37cfddbaca
--- /dev/null
+++ b/package/creativision/Config.in
@@ -0,0 +1,15 @@
+config BR2_PACKAGE_CREATIVISION
+ bool "creativision emulator"
+ depends on BR2_INSTALL_LIBSTDCPP
+ select BR2_PACKAGE_SDL2
+ select BR2_PACKAGE_SDL2_NET
+ select BR2_PACKAGE_LIBPNG
+ select BR2_PACKAGE_LIBZ
+ help
+ VTech CreatiVision emulator
+
+ https://sourceforge.net/projects/creativisionemulator/
+
+comment "creativision emulator needs a toolchain w/ C++, ALSA and SDL2"
+ depends on !BR2_INSTALL_LIBSTDCPP || !BR2_PACKAGE_SDL2 || !BR2_PACKAGE_SDL2_NET || \
+ !BR2_PACKAGE_LIBPNG || !BR2_PACKAGE_LIBZ
diff --git a/package/creativision/creativision.mk b/package/creativision/creativision.mk
new file mode 100644
index 0000000000000000000000000000000000000000..aa89e779a5047055bf42795b50442826902cae1a
--- /dev/null
+++ b/package/creativision/creativision.mk
@@ -0,0 +1,40 @@
+################################################################################
+#
+# Creativision emulator
+#
+################################################################################
+
+CREATIVISION_VERSION = d18fbe888eef21f7e7ef309a671c7d5834a5c641
+CREATIVISION_SITE = $(call gitlab,recalbox,packages/standalone/creativision,$(CREATIVISION_VERSION))
+CREATIVISION_LICENSE = CUSTOM
+CREATIVISION_DEPENDENCIES = sdl2 sdl2_net libpng zlib zip
+
+ifeq ($(BR2_ENABLE_DEBUG),y)
+CREATIVISION_CONF_OPTS += -DCMAKE_BUILD_TYPE=Debug
+else
+CREATIVISION_CONF_OPTS += -DCMAKE_BUILD_TYPE=Release
+endif
+
+CREATIVISION_CONF_OPTS += -DBUILD_SHARED_LIBS=OFF
+CREATIVISION_CONF_OPTS += -DCMAKE_C_ARCHIVE_CREATE=" qcs "
+CREATIVISION_CONF_OPTS += -DCMAKE_C_ARCHIVE_FINISH=true
+CREATIVISION_CONF_OPTS += -DCMAKE_AR="$(TARGET_CC)-ar"
+CREATIVISION_CONF_OPTS += -DCMAKE_C_COMPILER="$(TARGET_CC)"
+CREATIVISION_CONF_OPTS += -DCMAKE_CXX_COMPILER="$(TARGET_CXX)"
+CREATIVISION_CONF_OPTS += -DCMAKE_LINKER="$(TARGET_LD)"
+CREATIVISION_CONF_OPTS += -DCMAKE_C_FLAGS="$(COMPILER_COMMONS_CFLAGS_EXE)"
+CREATIVISION_CONF_OPTS += -DCMAKE_CXX_FLAGS="$(COMPILER_COMMONS_CXXFLAGS_EXE)"
+CREATIVISION_CONF_OPTS += -DCMAKE_LD_FLAGS="$(COMPILER_COMMONS_CXXFLAGS_EXE)"
+CREATIVISION_CONF_OPTS += -DCMAKE_EXE_LINKER_FLAGS="$(COMPILER_COMMONS_LDFLAGS_EXE)"
+
+define CREATIVISION_INSTALL_TARGET_CMDS
+ $(INSTALL) -D $(@D)/creatiVision $(TARGET_DIR)/usr/bin/creatiVision
+ mkdir -p $(TARGET_DIR)/usr/share/creatiVision
+ $(INSTALL) -D $(@D)/utils/tool_bas2cas $(TARGET_DIR)/usr/share/creatiVision/bas2cas
+ $(INSTALL) -D $(@D)/utils/tool_txt2cas $(TARGET_DIR)/usr/share/creatiVision/txt2cas
+ $(INSTALL) -D $(@D)/utils/tool_cas2wav $(TARGET_DIR)/usr/share/creatiVision/cas2wav
+ $(INSTALL) -D $(@D)/utils/tool_cvgfx $(TARGET_DIR)/usr/share/creatiVision/cvgfx
+ $(INSTALL) -D $(@D)/utils/tool_smbloader $(TARGET_DIR)/usr/share/creatiVision/smbloader
+endef
+
+$(eval $(cmake-package))
diff --git a/package/recalbox-romfs2/systems/creativision/init/roms/.keep b/package/recalbox-romfs2/systems/creativision/init/roms/.keep
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/package/recalbox-romfs2/systems/creativision/system.ini b/package/recalbox-romfs2/systems/creativision/system.ini
new file mode 100644
index 0000000000000000000000000000000000000000..541826dfd1ce8a98bda3ca9a55020eface90b80d
--- /dev/null
+++ b/package/recalbox-romfs2/systems/creativision/system.ini
@@ -0,0 +1,41 @@
+; ===========================
+; creativision
+; ===========================
+
+[system]
+uuid = "9776321f-4bac-4ad8-b552-731778c578dc"
+name = "creativision"
+fullname = "VTech Creativision"
+theme.folder = "creativision"
+roms.folder = "%ROOT%/creativision"
+screenscraper.id = 241
+doc.link.fr = "https://wiki.recalbox.com/fr/emulators/"
+doc.link.en = "https://wiki.recalbox.com/en/emulators/"
+port = 0
+readonly = 0
+downloader = 0
+icon.unicode = $F283
+
+[properties]
+type = console
+; Following properties can take the following values: no, optional, recommended, mandatory
+device.pad = mandatory
+device.keyboard = recommended
+device.mouse = no
+device.lightgun = no
+release.date = "1982-01"
+manufacturer = "VTech"
+retroachievements = 0
+crt.multiresolution = 0
+crt.multiregion = 0
+
+[core.0]
+package = BR2_PACKAGE_CREATIVISION
+priority = 0
+emulator = "creativision"
+core = "creativision"
+extensions = ".bin .rom .cas"
+netplay = 0
+softpatching = 0
+compatibility = high
+speed = high
diff --git a/package/recalbox-romfs2/systems/creativision/upgrade/roms/.readme.placeholder b/package/recalbox-romfs2/systems/creativision/upgrade/roms/.readme.placeholder
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/projects/configgen/configgen/emulatorlauncher.py b/projects/configgen/configgen/emulatorlauncher.py
index 5520b711b5c2881ca2dd6abb9e9bd21875c69a9e..4bda4f20344833d3ed650fb0087056c275b56799 100644
--- a/projects/configgen/configgen/emulatorlauncher.py
+++ b/projects/configgen/configgen/emulatorlauncher.py
@@ -142,6 +142,10 @@ def getGenerator(emulator):
module = __import__("configgen.generators.rb5000.rb5000Generator", fromlist=["RB5000Generator"])
generatorClass = getattr(module, "RB5000Generator")
return generatorClass()
+ elif emulator == "creativision":
+ module = __import__("configgen.generators.creativision.creativisionGenerator", fromlist=["CreativisionGenerator"])
+ generatorClass = getattr(module, "CreativisionGenerator")
+ return generatorClass()
else:
print("Missing generator for {}".format(emulator))
raise ValueError
diff --git a/projects/configgen/configgen/generators/creativision/creativisionGenerator.py b/projects/configgen/configgen/generators/creativision/creativisionGenerator.py
new file mode 100644
index 0000000000000000000000000000000000000000..c52247634f76e1f107f6e880ecda65cb66047f9a
--- /dev/null
+++ b/projects/configgen/configgen/generators/creativision/creativisionGenerator.py
@@ -0,0 +1,119 @@
+import os
+
+from configgen.controllers.inputItem import InputItem
+from configgen.settings.keyValueSettings import keyValueSettings
+from configgen.generators.Generator import Generator, ControllerPerPlayer
+import configgen.recalboxFiles as recalboxFiles
+from configgen.Emulator import Emulator
+from configgen.Command import Command
+from configgen.utils.resolutions import ResolutionParser
+
+
+class CreativisionGenerator(Generator):
+
+ BIOS_PATH = "/recalbox/share/bios/creativision"
+
+ def __BuildITem(self, name: str, base: str, item: InputItem) -> str:
+ if item.IsButton:
+ return base + name + "={}".format(item.Id)
+ return ""
+
+ def generate(self, system: Emulator, playersControllers: ControllerPerPlayer, recalboxOptions: keyValueSettings, args) -> Command:
+
+ # Option array
+ options: list[str] = []
+
+ # Try identify machine folder
+ defaultBios: str = "bioscv.rom" # Creativision console by default
+ machines: dict[str, str] = \
+ {
+ "csl": "cslbios.rom",
+ "cslcartridge": "cslbios.rom",
+ "csl-cartridge": "cslbios.rom",
+ "cslcart": "cslbios.rom",
+ "csl-cart": "cslbios.rom",
+ "csl-sm": "cslbiossm.rom",
+ "cslcartridge-sm": "cslbiossm.rom",
+ "csl-cartridge-sm": "cslbiossm.rom",
+ "cslcart-sm": "cslbiosms.rom",
+ "csl-cart-sm": "cslbiossm.rom",
+ "cslsm": "cslbiossm.rom",
+ "cslcartridgesm": "cslbiossm.rom",
+ "csl-cartridgesm": "cslbiossm.rom",
+ "cslcartsm": "cslbiosms.rom",
+ "csl-cartsm": "cslbiossm.rom",
+ "laser2001": "laser2001.rom",
+ "laser-2001": "laser2001.rom",
+ "salora": "saloram.rom",
+ "manager": "saloram.rom",
+ "saloramanager": "saloram.rom",
+ "salora-manager": "saloram.rom",
+ "laser": "laser2001.rom",
+ "2001": "laser2001.rom",
+ }
+ lrom: str = args.rom.lower()
+ for key in machines:
+ if key in lrom:
+ defaultBios = machines[key]
+ break
+
+ # Add bios
+ options.append("--bios")
+ options.append(os.path.join(self.BIOS_PATH, defaultBios))
+
+ # Change machine regarding the chosen bios
+ if defaultBios in ("cslbios.rom", "cslbiossm.rom"):
+ options.append("-2")
+ elif defaultBios in ("saloram.rom", "laser2001.rom"):
+ options.append("-3")
+
+ # Choose appropriate "rom" option
+ romname, romext = os.path.splitext(args.rom)
+ if romext == ".cas":
+ options.append("--cassette")
+ elif romext == ".dsk":
+ options.append("--floppy")
+ else:
+ options.append("--rom")
+ options.append(args.rom)
+
+ # Always fullscreen
+ options.append("--fullscreen")
+ # Screen resolution
+ resolution = ResolutionParser(system.VideoMode)
+ if resolution.isSet and resolution.selfProcess:
+ options.append("--screenwidth")
+ options.append(str(resolution.width))
+ options.append("--screenheight")
+ options.append(str(resolution.height))
+
+ # Gfx options
+ if system.IntegerScale:
+ options.append("--integerscale")
+ if system.Smooth:
+ options.append("--smooth")
+
+ # controller settings
+ for player, controller in playersControllers.items():
+ if 1 <= player <= 2:
+ base: str = "--joy{}".format(player - 1)
+ options.append(base + "={}".format(controller.SdlIndex))
+ if player == 1:
+ if controller.HasHotkey: options.append(self.__BuildITem("buttonHotkey", base, controller.Hotkey))
+ if controller.HasStart: options.append(self.__BuildITem("buttonStart" , base, controller.Start))
+ if controller.HasX: options.append(self.__BuildITem("buttonX", base, controller.X))
+ if controller.HasY: options.append(self.__BuildITem("buttonY", base, controller.Y))
+ if controller.HasL1: options.append(self.__BuildITem("buttonL1", base, controller.L1))
+ if controller.HasA: options.append(self.__BuildITem("button0", base, controller.A))
+ if controller.HasB: options.append(self.__BuildITem("button1", base, controller.B))
+ if controller.HasUp: options.append(self.__BuildITem("buttonup" , base, controller.Up))
+ if controller.HasDown: options.append(self.__BuildITem("buttondown" , base, controller.Down))
+ if controller.HasLeft: options.append(self.__BuildITem("buttonleft" , base, controller.Left))
+ if controller.HasRight: options.append(self.__BuildITem("buttonright", base, controller.Right))
+
+ commandArray: list[str] = [ recalboxFiles.recalboxBins[system.Emulator] ] # Emulator
+ commandArray.extend(options)
+ if system.HasArgs:
+ commandArray.extend(system.Args)
+
+ return Command(videomode=system.VideoMode, array=commandArray)
diff --git a/projects/configgen/configgen/recalboxFiles.py b/projects/configgen/configgen/recalboxFiles.py
index f61b33e71cecd3f7c7d183efbd72a145deef874f..39e085ad976c414196a4136376abe6d8542046f3 100644
--- a/projects/configgen/configgen/recalboxFiles.py
+++ b/projects/configgen/configgen/recalboxFiles.py
@@ -26,6 +26,7 @@ recalboxBins =\
'advancemame' : '/usr/bin/advmame',
'amiberry' : '/usr/bin/amiberry',
'beebem' : '/usr/bin/Beebem',
+ 'creativision': '/usr/bin/creatiVision',
'daphne' : '/usr/bin/hypseus',
'dolphin' : '/usr/bin/dolphin-emu-nogui',
'dosbox' : '/usr/bin/dosbox',
diff --git a/projects/configgen/setup.py b/projects/configgen/setup.py
index 12afc8a40964226dd7766a18abfb927202486438..c2b02f1962608e157478a02b01a5a2e0187b792b 100644
--- a/projects/configgen/setup.py
+++ b/projects/configgen/setup.py
@@ -10,6 +10,7 @@ setup(name='recalbox-configgen',
'configgen.controllers',
'configgen.generators',
'configgen.generators.beebem',
+ 'configgen.generators.creativision',
'configgen.generators.fba2x',
'configgen.generators.frotz',
'configgen.generators.gsplus',