From 3314e88244513d1bc91189e79bf44cbc8a665eec Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 5 Jun 2023 00:26:10 +0300 Subject: [PATCH 01/15] readme: make it more neutral I'd like the readme to not look weird in notaz/picodrive when I merge all the changes, where it will be unclear who the 1st person pronoun refers to. Several people have put quite some effort into it, so I think it's best not to highlight anyone. Also remove the old readme which has become outdated. --- README | 14 -------------- README.md | 23 ++++++++++------------- 2 files changed, 10 insertions(+), 27 deletions(-) delete mode 100644 README diff --git a/README b/README deleted file mode 100644 index af1bbfcc5..000000000 --- a/README +++ /dev/null @@ -1,14 +0,0 @@ - -This is yet another Megadrive / Genesis / Sega CD / Mega CD / 32X / SMS -emulator, which was written having ARM-based handheld devices in mind -(such as smartphones and handheld consoles like GP2X and Pandora), -but also runs on non-ARM little-endian hardware too. - -The emulator is heavily optimized for ARM, features assembly cores for -68k, Z80 and VDP chip emulation, also has dynamic recompilers for SH2 and -SSP16 (for 32X and SVP emulation). It was started by Dave (aka fdave, -finalburn author) as basic Genesis/Megadrive emulator for Pocket PC, -then taken over and expanded by notaz. - -PicoDrive was the first emulator ever to properly emulate Virtua Racing and -it's SVP chip. diff --git a/README.md b/README.md index 154ff5105..d43d1b217 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,18 @@ -This is my foray into dynamic recompilation using PicoDrive, a -Megadrive / Genesis / Sega CD / Mega CD / 32X / SMS emulator. +This is yet another Megadrive / Genesis / Sega CD / Mega CD / 32X / SMS +emulator, which was originally written having ARM-based handheld devices +in mind, but later had got various improvements for other architectures +too, like SH2 recompilers for MIPS (mips32r2), ARM64 (armv8), RISC-V (RV64IM) +and PowerPC (G4/2.03). -I added support for MIPS (mips32r2), ARM64 (armv8), RISC-V (RV64IM) and -PowerPC (G4/2.03) support to the SH2 recompiler, as well as spent much effort to -optimize the DRC-generated code. I also optimized SH2 memory access inside the -emulator, and did some work on M68K/SH2 CPU synchronization to fix some problems -and speed up the emulator. +PicoDrive was the first emulator ever to properly emulate Virtua Racing and +it's SVP chip. -It got a bit out of hand. I ended up doing fixes and optimizations all over the -place, mainly for 32X and CD, graphics handling, sound, and probably some more, -see the commit history. As a result, 32X emulation speed has improved a lot, a -lot of bugs were fixed, and some new features (e.g. chd file support) have been -added. +Currently the main development happens in the +[irixxxx's fork](https://github.com/irixxxx/picodrive), +[notaz's repo](https://github.com/notaz/picodrive) isn't updated as much. ### compiling -I mainly worked with standalone PicoDrive versions as created by configure/make. A list of platforms for which this is possible can be obtained with > configure --help From a67db32a4ac32fba0c081ca43fdd309674f3eca5 Mon Sep 17 00:00:00 2001 From: techmetx11 Date: Mon, 21 Aug 2023 16:21:25 +0100 Subject: [PATCH 02/15] Add hack for unlicensed games that don't handle the Z80 bus properly --- pico/cart.c | 2 ++ pico/carthw.cfg | 26 ++++++++++++++++++++++---- pico/carthw_cfg.c | 12 ++++++++++++ pico/memory.c | 4 ++-- pico/pico.h | 1 + 5 files changed, 39 insertions(+), 6 deletions(-) diff --git a/pico/cart.c b/pico/cart.c index e8293abce..339b9fe71 100644 --- a/pico/cart.c +++ b/pico/cart.c @@ -1210,6 +1210,8 @@ static void parse_carthw(const char *carthw_cfg, int *fill_sram, PicoIn.quirks |= PQUIRK_MARSCHECK_HACK; else if (strcmp(p, "force_6btn") == 0) PicoIn.quirks |= PQUIRK_FORCE_6BTN; + else if (strcmp(p, "no_z80_bus_lock") == 0) + PicoIn.quirks |= PQUIRK_NO_Z80_BUS_LOCK; else { elprintf(EL_STATUS, "carthw:%d: unsupported prop: %s", line, p); goto bad_nomsg; diff --git a/pico/carthw.cfg b/pico/carthw.cfg index 64e9152c7..013b04cf3 100644 --- a/pico/carthw.cfg +++ b/pico/carthw.cfg @@ -4,10 +4,11 @@ # prot - simple copy protection devices in unlicensed cartridges (see prot. below) # # cartridge properties (prop = ...): -# no_sram - don't emulate sram/EEPROM even if ROM headers tell it's there -# no_eeprom - save storage is not EEPROM, even if ROM headers tell it is -# filled_sram - save storage needs to be initialized with FFh instead of 00h -# force_6btn - game only supports 6 button pad (32X X-men proto) +# no_sram - don't emulate sram/EEPROM even if ROM headers tell it's there +# no_eeprom - save storage is not EEPROM, even if ROM headers tell it is +# filled_sram - save storage needs to be initialized with FFh instead of 00h +# force_6btn - game only supports 6 button pad (32X X-men proto) +# no_z80_bus_lock - don't emulate z80 bus getting closed to the 68k when bus is released # # mappers (hw = ...): # ssf2_mapper - used in Super Street Fighter2 @@ -526,3 +527,20 @@ check_crc32 = 0xee9fc429 hw = prot prot_ro_value16 = 0x400000,-2,0x6300 +# Unlicensed homebrew games made by V.M.V. +# to prevent bus conflicts between the audio drivers in 68k and Z80 + +[Ben 10 (Unl)] +check_str = 0x180, "GM 00000000-00" +check_crc32 = 0x6732aab4 +prop = no_z80_bus_lock + +[Mario 3: Vokrug Sveta (Unl)] +check_str = 0x180, "GM 00000000-00" +check_crc32 = 0xe302585a +prop = no_z80_bus_lock + +[Mario 4: Kosmicheskaya Odisseya (Unl)] +check_csum = 8224 +check_crc32 = 0x20ed0de8 +prop = no_z80_bus_lock diff --git a/pico/carthw_cfg.c b/pico/carthw_cfg.c index 02f8c111b..97e7ddae5 100644 --- a/pico/carthw_cfg.c +++ b/pico/carthw_cfg.c @@ -387,4 +387,16 @@ static const char builtin_carthw_cfg[] = "check_crc32=0xee9fc429\n" "hw=prot\n" "prot_ro_value16=0x400000,-2,0x6300\n" + "[]\n" + "check_str=0x180,\"GM 00000000-00\"\n" + "check_crc32=0x6732aab4\n" + "prop=no_z80_bus_lock\n" + "[]\n" + "check_str=0x180,\"GM 00000000-00\"\n" + "check_crc32=0xe302585a\n" + "prop=no_z80_bus_lock\n" + "[]\n" + "check_csum=8224\n" + "check_crc32=0x20ed0de8\n" + "prop=no_z80_bus_lock\n" ; diff --git a/pico/memory.c b/pico/memory.c index 818080fd4..6ee6282b6 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -675,7 +675,7 @@ static void PicoWrite16_sram(u32 a, u32 d) static u32 PicoRead8_z80(u32 a) { u32 d = 0xff; - if ((Pico.m.z80Run & 1) || Pico.m.z80_reset) { + if (!(PicoIn.quirks & PQUIRK_NO_Z80_BUS_LOCK) && ((Pico.m.z80Run & 1) || Pico.m.z80_reset)) { elprintf(EL_ANOMALY, "68k z80 read with no bus! [%06x] @ %06x", a, SekPc); // open bus. Pulled down if MegaCD2 is attached. return 0; @@ -699,7 +699,7 @@ static u32 PicoRead16_z80(u32 a) static void PicoWrite8_z80(u32 a, u32 d) { - if ((Pico.m.z80Run & 1) || Pico.m.z80_reset) { + if (!(PicoIn.quirks & PQUIRK_NO_Z80_BUS_LOCK) && ((Pico.m.z80Run & 1) || Pico.m.z80_reset)) { // verified on real hw elprintf(EL_ANOMALY, "68k z80 write with no bus or reset! [%06x] %02x @ %06x", a, d&0xff, SekPc); return; diff --git a/pico/pico.h b/pico/pico.h index 2ef469286..f17d93ded 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -99,6 +99,7 @@ extern void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s; #define PQUIRK_BLACKTHORNE_HACK (1<<1) #define PQUIRK_WWFRAW_HACK (1<<2) #define PQUIRK_MARSCHECK_HACK (1<<3) +#define PQUIRK_NO_Z80_BUS_LOCK (1<<4) // the emulator is configured and some status is reported // through this global state (not saved in savestates) From 1a9da199e82e3bb60ba88de736aaecab0f5a1430 Mon Sep 17 00:00:00 2001 From: kub Date: Wed, 30 Aug 2023 22:54:10 +0200 Subject: [PATCH 03/15] platform, revisit menu, add option profiles --- platform/common/emu.c | 2 +- platform/common/menu_pico.c | 237 ++++++++++++++++++++++++------------ platform/common/menu_pico.h | 4 + 3 files changed, 164 insertions(+), 79 deletions(-) diff --git a/platform/common/emu.c b/platform/common/emu.c index 0f4ae1699..4e24c00bf 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -619,7 +619,7 @@ void emu_prep_defconfig(void) memset(&defaultConfig, 0, sizeof(defaultConfig)); defaultConfig.EmuOpt = EOPT_EN_SRAM | EOPT_EN_SOUND | EOPT_16BPP | EOPT_EN_CD_LEDS | EOPT_GZIP_SAVES | 0x10/*?*/; - defaultConfig.s_PicoOpt = POPT_EN_SNDFILTER|POPT_EN_GG_LCD | + defaultConfig.s_PicoOpt = POPT_EN_SNDFILTER|POPT_EN_GG_LCD|POPT_EN_YM2413 | POPT_EN_STEREO|POPT_EN_FM|POPT_EN_PSG|POPT_EN_Z80 | POPT_EN_MCD_PCM|POPT_EN_MCD_CDDA|POPT_EN_MCD_GFX | POPT_EN_DRC|POPT_ACC_SPRITES | diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 532bd30fa..14ddf0678 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -411,9 +411,6 @@ static const char *mgn_dev_name(int id, int *offs) return name; } -static int mh_saveloadcfg(int id, int keys); -static const char *mgn_saveloadcfg(int id, int *offs); - const char *indev0_names[] = { "none", "3 button pad", "6 button pad", "Team player", "4 way play", NULL }; const char *indev1_names[] = { "none", "3 button pad", "6 button pad", NULL }; @@ -426,13 +423,11 @@ static menu_entry e_menu_keyconfig[] = mee_handler_id("Player 2", MA_CTRL_PLAYER2, key_config_loop_wrap), mee_handler_id_h("Player 3", MA_CTRL_PLAYER3, key_config_loop_wrap, h_play34), mee_handler_id_h("Player 4", MA_CTRL_PLAYER4, key_config_loop_wrap, h_play34), - mee_handler_id("Emulator controls", MA_CTRL_EMU, key_config_loop_wrap), + mee_handler_id("Emulator hotkeys", MA_CTRL_EMU, key_config_loop_wrap), mee_enum ("Input device 1", MA_OPT_INPUT_DEV0, currentConfig.input_dev0, indev0_names), mee_enum ("Input device 2", MA_OPT_INPUT_DEV1, currentConfig.input_dev1, indev1_names), mee_range ("Turbo rate", MA_CTRL_TURBO_RATE, currentConfig.turbo_rate, 1, 30), mee_range ("Analog deadzone", MA_CTRL_DEADZONE, currentConfig.analog_deadzone, 1, 99), - mee_cust_nosave("Save global config", MA_OPT_SAVECFG, mh_saveloadcfg, mgn_saveloadcfg), - mee_cust_nosave("Save cfg for loaded game", MA_OPT_SAVECFG_GAME, mh_saveloadcfg, mgn_saveloadcfg), mee_label (""), mee_label ("Input devices:"), mee_label_mk (MA_CTRL_DEV_FIRST, mgn_dev_name), @@ -448,8 +443,13 @@ static menu_entry e_menu_keyconfig[] = static int menu_loop_keyconfig(int id, int keys) { static int sel = 0; + int it = 0, x = me_id2offset(e_menu_keyconfig, MA_CTRL_DEV_FIRST); + + while (in_get_dev_name(it, 1, 1)) + it++; + for (it += x; x && e_menu_keyconfig[x].name; x++) + e_menu_keyconfig[x].enabled = x < it; - me_enable(e_menu_keyconfig, MA_OPT_SAVECFG_GAME, PicoGameLoaded); me_loop_d(e_menu_keyconfig, &sel, menu_draw_prep, NULL); PicoSetInputDevice(0, currentConfig.input_dev0); @@ -460,25 +460,27 @@ static int menu_loop_keyconfig(int id, int keys) // ------------ MD options menu ------------ +static const char h_renderer[] = "16bit is more accurate, 8bit is faster"; static const char h_fmsound[] = "Disabling improves performance, but breaks sound"; -static const char h_dacnoise[] = "Megadrive 1 has DAC noise, Megadrive 2 doesn't"; +static const char h_dacnoise[] = "FM chips in the 1st Megadrive model have DAC noise,\n" + "newer models used different chips without this"; static const char h_fmfilter[] = "Improves sound accuracy but is noticeably slower,\n" "best´quality if native rate isn't working"; static menu_entry e_menu_md_options[] = { - mee_enum ("Renderer", MA_OPT_RENDERER, currentConfig.renderer, renderer_names), + mee_enum_h ("Renderer", MA_OPT_RENDERER, currentConfig.renderer, renderer_names, h_renderer), mee_onoff_h ("FM audio", MA_OPT2_ENABLE_YM2612, PicoIn.opt, POPT_EN_FM, h_fmsound), + mee_onoff_h ("FM filter", MA_OPT_FM_FILTER, PicoIn.opt, POPT_EN_FM_FILTER, h_fmfilter), mee_onoff_h ("FM DAC noise", MA_OPT2_ENABLE_YM_DAC, PicoIn.opt, POPT_EN_FM_DAC, h_dacnoise), - mee_onoff_h ("FM filtering", MA_OPT_FM_FILTER, PicoIn.opt, POPT_EN_FM_FILTER, h_fmfilter), mee_end, }; static int menu_loop_md_options(int id, int keys) { static int sel = 0; - - me_enable(e_menu_md_options, MA_OPT_RENDERER, renderer_names[0] != NULL); + if (renderer_names[0] == NULL) + me_enable(e_menu_md_options, MA_OPT_RENDERER, 0); me_loop_d(e_menu_md_options, &sel, menu_draw_prep, NULL); return 0; @@ -494,10 +496,10 @@ static const char h_srcart[] = "Emulate the save RAM cartridge accessory\n" static menu_entry e_menu_cd_options[] = { + mee_onoff_h("SaveRAM cart", MA_CDOPT_SAVERAM, PicoIn.opt, POPT_EN_MCD_RAMCART, h_srcart), mee_onoff_h("CD LEDs", MA_CDOPT_LEDS, currentConfig.EmuOpt, EOPT_EN_CD_LEDS, h_cdleds), mee_onoff_h("CDDA audio", MA_CDOPT_CDDA, PicoIn.opt, POPT_EN_MCD_CDDA, h_cdda), mee_onoff_h("PCM audio", MA_CDOPT_PCM, PicoIn.opt, POPT_EN_MCD_PCM, h_cdpcm), - mee_onoff_h("SaveRAM cart", MA_CDOPT_SAVERAM, PicoIn.opt, POPT_EN_MCD_RAMCART, h_srcart), mee_end, }; @@ -555,7 +557,8 @@ static int menu_loop_32x_options(int id, int keys) { static int sel = 0; - me_enable(e_menu_32x_options, MA_32XOPT_RENDERER, renderer_names32x[0] != NULL); + if (renderer_names32x[0] == NULL) + me_enable(e_menu_32x_options, MA_32XOPT_RENDERER, 0); me_loop_d(e_menu_32x_options, &sel, menu_draw_prep, NULL); Pico32xSetClocks(currentConfig.msh2_khz * 1000, currentConfig.msh2_khz * 1000); @@ -572,8 +575,10 @@ static int menu_loop_32x_options(int id, int keys) static const char *sms_hardwares[] = { "auto", "Game Gear", "Master System", "SG-1000", "SC-3000", NULL }; static const char *gg_ghosting_opts[] = { "OFF", "weak", "normal", NULL }; static const char *sms_mappers[] = { "auto", "Sega", "Codemasters", "Korea", "Korea MSX", "Korea X-in-1", "Korea 4-Pak", "Korea Janggun", "Korea Nemesis", "Taiwan 8K RAM", "Korea XOR", "Sega 32K RAM", NULL }; -static const char h_smsfm[] = "FM sound is only supported by few games\nOther games may crash with FM enabled"; -static const char h_ghost[] = "Simulates the inertia of the GG LCD display"; + +static const char h_smsfm[] = "FM sound is only supported by few games,\n" + "some games may crash with FM enabled"; +static const char h_ghost[] = "Simulate the inertia of the GG LCD display"; static menu_entry e_menu_sms_options[] = { @@ -766,8 +771,8 @@ static const char h_confirm_save[] = "Ask for confirmation when overwriting s static menu_entry e_menu_ui_options[] = { mee_onoff ("Show FPS", MA_OPT_SHOW_FPS, currentConfig.EmuOpt, EOPT_SHOW_FPS), - mee_enum_h ("Confirm savestate", MA_OPT_CONFIRM_STATES, currentConfig.confirm_save, men_confirm_save, h_confirm_save), - mee_onoff ("Don't save last used ROM", MA_OPT2_NO_LAST_ROM, currentConfig.EmuOpt, EOPT_NO_AUTOSVCFG), + mee_enum_h ("Confirm save/load", MA_OPT_CONFIRM_STATES, currentConfig.confirm_save, men_confirm_save, h_confirm_save), + mee_onoff ("Don't save last used game", MA_OPT2_NO_LAST_ROM, currentConfig.EmuOpt, EOPT_NO_AUTOSVCFG), mee_end, }; @@ -782,7 +787,73 @@ static int menu_loop_ui_options(int id, int keys) // ------------ options menu ------------ -static menu_entry e_menu_options[]; +static int find_renderer(const char *names[], const char *which) +{ + int i = 0; + for (i = 0; *names; names++, i++) + if (strstr(*names, which)) return i; + return 0; +} + +static int mh_profile(int id, int keys) { + switch (id) { + case MA_PROFILE_ACCURATE: + currentConfig.renderer = find_renderer(renderer_names, "16bit"); + currentConfig.renderer32x = find_renderer(renderer_names32x, "accurate"); + PicoIn.sndRate = 44100; + PicoIn.opt |= POPT_EN_FM_FILTER | POPT_EN_FM | POPT_EN_MCD_CDDA; + PicoIn.opt &= ~POPT_PWM_IRQ_OPT; + break; + case MA_PROFILE_BALANCED: + currentConfig.renderer = find_renderer(renderer_names, "8bit"); + currentConfig.renderer32x = find_renderer(renderer_names32x, "fast"); + PicoIn.sndRate = 44100; + PicoIn.opt |= POPT_EN_FM | POPT_EN_MCD_CDDA; + PicoIn.opt &= ~(POPT_PWM_IRQ_OPT | POPT_EN_FM_FILTER); + break; + case MA_PROFILE_FAST: + currentConfig.renderer = find_renderer(renderer_names, "fast"); + currentConfig.renderer32x = find_renderer(renderer_names32x, "fastest"); + PicoIn.sndRate = 22050; + PicoIn.opt |= POPT_PWM_IRQ_OPT | POPT_EN_FM | POPT_EN_MCD_CDDA; + PicoIn.opt &= ~POPT_EN_FM_FILTER; + break; + case MA_PROFILE_BREAKING: + currentConfig.renderer = find_renderer(renderer_names, "fast"); + currentConfig.renderer32x = find_renderer(renderer_names32x, "fastest"); + PicoIn.sndRate = 16000; + PicoIn.opt |= POPT_PWM_IRQ_OPT; + PicoIn.opt &= ~(POPT_EN_FM_FILTER | POPT_EN_FM | POPT_EN_MCD_CDDA); + break; + } + return 1; +} + +static menu_entry e_menu_profile[] = +{ + mee_label ("Select option profile and press OK:"), + mee_handler_id("accurate", MA_PROFILE_ACCURATE, mh_profile), + mee_handler_id("balanced", MA_PROFILE_BALANCED, mh_profile), + mee_handler_id("fast", MA_PROFILE_FAST, mh_profile), + mee_handler_id("breaking", MA_PROFILE_BREAKING, mh_profile), + mee_label (""), + mee_label ("Options changed by Option profiles:"), + mee_label (""), + mee_label ("Sound: Sound quality"), + mee_label ("MD: Renderer, FM audio, FM filter"), + mee_label ("32X: Renderer, PWM IRQ optimization"), + mee_label ("CD: CDDA audio"), + mee_end, +}; + +static int menu_loop_profile_options(int id, int keys) +{ + static int sel = 0; + + me_loop_d(e_menu_profile, &sel, menu_draw_prep, NULL); + + return 0; +} static void region_prevnext(int right) { @@ -824,39 +895,6 @@ static int mh_opt_misc(int id, int keys) return 0; } -static int mh_saveloadcfg(int id, int keys) -{ - int ret; - - if (keys & (PBTN_LEFT|PBTN_RIGHT)) { // multi choice - config_slot += (keys & PBTN_LEFT) ? -1 : 1; - if (config_slot < 0) config_slot = 9; - else if (config_slot > 9) config_slot = 0; - me_enable(e_menu_options, MA_OPT_LOADCFG, config_slot != config_slot_current); - return 0; - } - - switch (id) { - case MA_OPT_SAVECFG: - case MA_OPT_SAVECFG_GAME: - if (emu_write_config(id == MA_OPT_SAVECFG_GAME ? 1 : 0)) - menu_update_msg("config saved"); - else - menu_update_msg("failed to write config"); - break; - case MA_OPT_LOADCFG: - ret = emu_read_config(rom_fname_loaded, 1); - if (!ret) ret = emu_read_config(NULL, 1); - if (ret) menu_update_msg("config loaded"); - else menu_update_msg("failed to load config"); - break; - default: - return 0; - } - - return 1; -} - static int mh_restore_defaults(int id, int keys) { emu_set_defconfig(); @@ -892,32 +930,35 @@ static const char *mgn_opt_region(int id, int *offs) static const char *mgn_saveloadcfg(int id, int *offs) { - static_buff[0] = 0; + strcpy(static_buff, " "); if (config_slot != 0) sprintf(static_buff, "[%i]", config_slot); return static_buff; } +static const char h_hotkeysvld[] = "Slot used for save/load by emulator hotkey"; + static menu_entry e_menu_options[] = { - mee_range ("Save slot", MA_OPT_SAVE_SLOT, state_slot, 0, 9), mee_cust ("Region", MA_OPT_REGION, mh_opt_misc, mgn_opt_region), mee_range ("", MA_OPT_CPU_CLOCKS, currentConfig.CPUclock, 20, 3200), - mee_handler ("[Interface options]", menu_loop_ui_options), - mee_handler ("[Display options]", menu_loop_gfx_options), - mee_handler ("[Sound options]", menu_loop_snd_options), - mee_handler ("[MD/Genesis options]", menu_loop_md_options), - mee_handler (" [Sega/Mega CD add-on]", menu_loop_cd_options), + mee_range_h ("Hotkey save/load slot", MA_OPT_SAVE_SLOT, state_slot, 0, 9, h_hotkeysvld), + mee_handler ("Configure controls", menu_loop_keyconfig), + mee_label (""), + mee_handler ("Option profiles", menu_loop_profile_options), + mee_handler ("Interface options", menu_loop_ui_options), + mee_handler ("Display options", menu_loop_gfx_options), + mee_handler ("Sound options", menu_loop_snd_options), + mee_handler ("MD/Genesis options", menu_loop_md_options), + mee_handler (" Sega/Mega CD add-on", menu_loop_cd_options), #ifndef NO_32X - mee_handler (" [32X add-on]", menu_loop_32x_options), + mee_handler (" 32X add-on", menu_loop_32x_options), #endif #ifndef NO_SMS - mee_handler ("[SG/SMS/GG options]", menu_loop_sms_options), + mee_handler ("SG/SMS/GG options", menu_loop_sms_options), #endif - mee_handler ("[Advanced options]", menu_loop_adv_options), - mee_cust_nosave("Save global config", MA_OPT_SAVECFG, mh_saveloadcfg, mgn_saveloadcfg), - mee_cust_nosave("Save cfg for loaded game",MA_OPT_SAVECFG_GAME, mh_saveloadcfg, mgn_saveloadcfg), - mee_cust_nosave("Load cfg from profile", MA_OPT_LOADCFG, mh_saveloadcfg, mgn_saveloadcfg), + mee_handler ("Advanced options", menu_loop_adv_options), + mee_handler ("Restore defaults", mh_restore_defaults), mee_end, }; @@ -926,9 +967,6 @@ static int menu_loop_options(int id, int keys) { static int sel = 0; - me_enable(e_menu_options, MA_OPT_SAVECFG_GAME, PicoGameLoaded); - me_enable(e_menu_options, MA_OPT_LOADCFG, config_slot != config_slot_current); - me_loop_d(e_menu_options, &sel, menu_draw_prep, NULL); return 0; @@ -1106,7 +1144,7 @@ static void draw_frame_credits(void) static const char credits[] = "PicoDrive v" VERSION "\n" - "(c) notaz, 2006-2013; irixxxx, 2018-2021\n\n" + "(c) notaz, 2006-2013; irixxxx, 2018-2023\n\n" "Credits:\n" "fDave: initial code\n" #ifdef EMU_C68K @@ -1183,6 +1221,8 @@ static void menu_main_draw_status(void) bp[(w - i) + g_menuscreen_pp * u] = menu_text_color; } +static menu_entry e_menu_main[]; + static int main_menu_handler(int id, int keys) { const char *ret_name; @@ -1251,22 +1291,58 @@ static int main_menu_handler(int id, int keys) return 0; } +static int mh_saveloadcfg(int id, int keys) +{ + int ret; + + if (keys & (PBTN_LEFT|PBTN_RIGHT)) { // multi choice + config_slot += (keys & PBTN_LEFT) ? -1 : 1; + if (config_slot < 0) config_slot = 9; + else if (config_slot > 9) config_slot = 0; + me_enable(e_menu_main, MA_OPT_LOADCFG, PicoGameLoaded && config_slot != config_slot_current); + return 0; + } + + switch (id) { + case MA_OPT_SAVECFG: + case MA_OPT_SAVECFG_GAME: + if (emu_write_config(id == MA_OPT_SAVECFG_GAME ? 1 : 0)) + menu_update_msg("config saved"); + else + menu_update_msg("failed to write config"); + break; + case MA_OPT_LOADCFG: + ret = emu_read_config(rom_fname_loaded, 1); + if (!ret) ret = emu_read_config(NULL, 1); + if (ret) menu_update_msg("config loaded"); + else menu_update_msg("failed to load config"); + break; + default: + return 0; + } + + return 1; +} + +static const char h_saveload[] = "Game options are overloading global options"; + static menu_entry e_menu_main[] = { mee_label ("PicoDrive " VERSION), mee_label (""), mee_label (""), - mee_label (""), mee_handler_id("Resume game", MA_MAIN_RESUME_GAME, main_menu_handler), mee_handler_id("Save State", MA_MAIN_SAVE_STATE, main_menu_handler), mee_handler_id("Load State", MA_MAIN_LOAD_STATE, main_menu_handler), mee_handler_id("Reset game", MA_MAIN_RESET_GAME, main_menu_handler), - mee_handler_id("Load new ROM/ISO", MA_MAIN_LOAD_ROM, main_menu_handler), - mee_handler_id("Change CD/ISO", MA_MAIN_CHANGE_CD, main_menu_handler), + mee_handler_id("Change CD", MA_MAIN_CHANGE_CD, main_menu_handler), + mee_handler_id("Patches / GameGenie",MA_MAIN_PATCHES, main_menu_handler), + mee_handler_id("Load new game", MA_MAIN_LOAD_ROM, main_menu_handler), mee_handler ("Change options", menu_loop_options), - mee_handler ("Configure controls", menu_loop_keyconfig), + mee_cust_s_h ("Save global options",MA_OPT_SAVECFG, 0, mh_saveloadcfg, mgn_saveloadcfg, NULL), + mee_cust_s_h ("Save game options", MA_OPT_SAVECFG_GAME, 0, mh_saveloadcfg, mgn_saveloadcfg, h_saveload), + mee_cust_s_h ("Load game options", MA_OPT_LOADCFG, 0, mh_saveloadcfg, mgn_saveloadcfg, h_saveload), mee_handler_id("Credits", MA_MAIN_CREDITS, main_menu_handler), - mee_handler_id("Patches / GameGenie",MA_MAIN_PATCHES, main_menu_handler), mee_handler_id("Exit", MA_MAIN_EXIT, main_menu_handler), mee_end, }; @@ -1280,7 +1356,9 @@ void menu_loop(void) me_enable(e_menu_main, MA_MAIN_LOAD_STATE, PicoGameLoaded); me_enable(e_menu_main, MA_MAIN_RESET_GAME, PicoGameLoaded); me_enable(e_menu_main, MA_MAIN_CHANGE_CD, PicoIn.AHW & PAHW_MCD); - me_enable(e_menu_main, MA_MAIN_PATCHES, PicoPatches != NULL); + me_enable(e_menu_main, MA_MAIN_PATCHES, PicoPatches != NULL); + me_enable(e_menu_main, MA_OPT_SAVECFG_GAME, PicoGameLoaded); + me_enable(e_menu_main, MA_OPT_LOADCFG, PicoGameLoaded && config_slot != config_slot_current); menu_enter(PicoGameLoaded); in_set_config_int(0, IN_CFG_BLOCKING, 1); @@ -1369,14 +1447,17 @@ void menu_update_msg(const char *msg) static menu_entry e_menu_hidden[] = { mee_onoff("Accurate sprites", MA_OPT_ACC_SPRITES, PicoIn.opt, POPT_ACC_SPRITES), - mee_onoff("autoload savestates", MA_OPT_AUTOLOAD_SAVE, g_autostateld_opt, 1), - mee_onoff("SDL fullscreen mode", MA_OPT_VOUT_FULL, plat_target.vout_fullscreen, 1), +// mee_range("Save slot", MA_OPT_SAVE_SLOT, state_slot, 0, 9), + +// mee_enum ("Confirm savestate", MA_OPT_CONFIRM_STATES, currentConfig.confirm_save, men_confirm_save), + mee_onoff("autoload savestates", MA_OPT_AUTOLOAD_SAVE, g_autostateld_opt, 1), + mee_onoff("SDL fullscreen mode", MA_OPT_VOUT_FULL, plat_target.vout_fullscreen, 1), mee_onoff("Emulate Z80", MA_OPT2_ENABLE_Z80, PicoIn.opt, POPT_EN_Z80), mee_onoff("Emulate YM2612 (FM)", MA_OPT2_ENABLE_YM2612, PicoIn.opt, POPT_EN_FM), mee_onoff("Disable YM2612 SSG-EG", MA_OPT2_DISABLE_YM_SSG,PicoIn.opt, POPT_DIS_FM_SSGEG), mee_onoff("Enable YM2612 DAC noise", MA_OPT2_ENABLE_YM_DAC, PicoIn.opt, POPT_EN_FM_DAC), mee_onoff("Emulate SN76496 (PSG)", MA_OPT2_ENABLE_SN76496,PicoIn.opt, POPT_EN_PSG), - mee_onoff("Scale/Rot. fx", MA_CDOPT_SCALEROT_CHIP, PicoIn.opt, POPT_EN_MCD_GFX), + mee_onoff("Scale/Rot. fx", MA_CDOPT_SCALEROT_CHIP,PicoIn.opt, POPT_EN_MCD_GFX), mee_onoff("32X enabled", MA_32XOPT_ENABLE_32X, PicoIn.opt, POPT_EN_32X), mee_end, }; diff --git a/platform/common/menu_pico.h b/platform/common/menu_pico.h index 7d23b4388..d8c1855c5 100644 --- a/platform/common/menu_pico.h +++ b/platform/common/menu_pico.h @@ -16,6 +16,10 @@ typedef enum MA_MAIN_CREDITS, MA_MAIN_PATCHES, MA_MAIN_EXIT, + MA_PROFILE_ACCURATE, + MA_PROFILE_BALANCED, + MA_PROFILE_FAST, + MA_PROFILE_BREAKING, MA_OPT_RENDERER, MA_OPT_SCALING, MA_OPT_VSCALING, From 324dbe04731d9fc950afd3c6b100e9cb985c82ec Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 3 Sep 2023 22:47:36 +0200 Subject: [PATCH 04/15] readme, some cleanup --- README.md | 65 ++++++++++++++++++++++++++----------------------- pico/cd/libchdr | 2 +- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index d43d1b217..537106cbf 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ too, like SH2 recompilers for MIPS (mips32r2), ARM64 (armv8), RISC-V (RV64IM) and PowerPC (G4/2.03). PicoDrive was the first emulator ever to properly emulate Virtua Racing and -it's SVP chip. +its SVP chip. Currently the main development happens in the [irixxxx's fork](https://github.com/irixxxx/picodrive), @@ -13,6 +13,16 @@ Currently the main development happens in the ### compiling +For platforms for which release builds are supplied the most easy way is to +use the release script in tools/release.sh. The script requires toolchains +to be installed locally, depending on the platform to build. See the release +script for details. To make a platform release build use + +> tools/release.sh [version] [platforms...] + +This will deliver a zip files for each platform in a the release-[version] +directory. + A list of platforms for which this is possible can be obtained with > configure --help @@ -23,49 +33,44 @@ platform list, just use > configure --platform=generic If DRC is available for the platform, it should be enabled automatically. - -For other platforms using a cross-compiling toolchain I used this, -assuming $TC points to the appropriate cross compile toolchain directory: - -platform|toolchain|configure command ---------|---------|----------------- -gp2x,wiz,caanoo|open2x|CROSS_COMPILE=arm-open2x-linux- CFLAGS="-I$TC/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux/include" LDFLAGS="--sysroot $TC/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux -L$TC/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux/lib" ./configure --platform=gp2x -gp2x,wiz,caanoo|open2x with ubuntu arm gcc 4.7|CROSS_COMPILE=arm-linux-gnueabi- CFLAGS="-I$TC/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux/include" LDFLAGS="-B$TC/gcc-4.1.1-glibc-2.3.6/lib/gcc/arm-open2x-linux/4.1.1 -B$TC/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux/lib -L$TC/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux/lib" ./configure --platform=gp2x -dingux|dingux|CROSS_COMPILE=mipsel-linux- CFLAGS="-I$TC/usr/include -I$TC/usr/include/SDL" LDFLAGS="--sysroot $TC -L$TC/lib" ./configure --platform=dingux -dingux|dingux with ubuntu mips gcc 5.4|CROSS_COMPILE=mipsel-linux-gnu- CFLAGS="-I$TC/usr/include -I$TC/usr/include/SDL" LDFLAGS="-B$TC/usr/lib -B$TC/lib -Wl,-rpath-link=$TC/usr/lib -Wl,-rpath-link=$TC/lib" ./configure --platform=dingux -retrofw|retrofw|CROSS_COMPILE=mipsel-linux- CFLAGS="-I $TC/include -I $TC/include/SDL -Wno-unused-result" LDFLAGS="--sysroot $TC/mipsel-buildroot-linux-uclibc/sysroot" ./configure --platform=retrofw -gcw0|gcw0|CROSS_COMPILE=mipsel-gcw0-linux-uclibc- CFLAGS="-I$TC/usr/mipsel-gcw0-linux-uclibc/sysroot/usr/include -I$TC/usr/mipsel-gcw0-linux-uclibc/sysroot/usr/include/SDL" LDFLAGS="--sysroot $TC/usr/mipsel-gcw0-linux-uclibc/sysroot" ./configure --platform=gcw0 -rg350|rg350|CROSS_COMPILE=mipsel-linux- CFLAGS="-I$TC/usr/include -I$TC/usr/include/SDL" LDFLAGS="--sysroot $TC -L$TC/lib" ./configure --platform=rg350 -miyoo|miyoo|CROSS_COMPILE=arm-miyoo-linux-uclibcgnueabi- CFLAGS="-I$TC/arm-miyoo-linux-uclibcgnueabi/sysroot/usr/include -I$TC/arm-miyoo-linux-uclibcgnueabi/sysroot/usr/include/SDL" LDFLAGS="--sysroot $TC/arm-miyoo-linux-uclibcgnueabi/sysroot" ./configure --platform=miyoo - For gp2x, wiz, and caanoo you may need to compile libpng first. After configure, compile with > make + ### helix MP3 decoder for ARM -For 32 bit ARM platforms, there is the possibility to compile the helix MP3 -decoder into a shared library to be able to use MP3 audio files with CD games. -The helix source files aren't supplied because of licensing issues. However, if -you have obtained the sources, put them into the platform/common/helix -directory, set CROSS to your cross compiler prefix (e.g. arm-linux-gnueabi-) -and LIBGCC to your cross compiler's libgcc.a +For 32 bit ARM platforms, the optimized helix MP3 decoder can be used to play +MP3 audio files with CD games. The helix source files are however not supplied +due to licensing issues. If you have legally obtained the sources, put them in +the platform/common/helix directory. + +To compile the helix sources, set CROSS to your cross compiler prefix +(e.g. arm-linux-gnueabi-) and LIBGCC to your cross compiler's libgcc.a (e.g. /usr/lib/gcc-cross/arm-linux-gnueabi/4.7/libgcc.a), and compile with > make -C platform/common/helix CROSS=$CROSS LIBGCC=$LIBGCC -Copy the resulting ${CROSS}helix_mp3.so as libhelix.so to the directory where -the PicoDrive binary is. +This will result in a shared library named ${CROSS}helix_mp3.so. Copy this +as libhelix.so to where the PicoDrive binary is on the target device. + + +Also, the support for helix must be enabled in PicoDrive by compiling with + +> make PLATFORM_MP3=1 + +This switch is automatically enabled for Gamepark Holdings devices (gp2x, +caanoo and wiz). Without installing libhelix.so those devices will not play +MP3 audio. + ### installing -You need to install the resulting binary onto your device manually. -For opendingux, gcw0, and rg350, copy the opk to your SD card. -For gp2x, wiz, and caanoo, the easiest way is to unpack -[PicoDrive_191.zip](http://notaz.gp2x.de/releases/PicoDrive/PicoDrive_191.zip) -on your SD card and replace the PicoDrive binary. -For legacy dingux, unpack the dge zip and copy the files to your SD card. +The release scripts produces zip files which need to be installed on the +target device manually. Usually that means unpacking the file to some +directory on the device storage or on an SD card. See device specific +descriptions on the net. Send bug reports, fixes etc to diff --git a/pico/cd/libchdr b/pico/cd/libchdr index a20e04c12..4ad57f9e7 160000 --- a/pico/cd/libchdr +++ b/pico/cd/libchdr @@ -1 +1 @@ -Subproject commit a20e04c12c0c20048bf771da6df7aa2e51f5e0cb +Subproject commit 4ad57f9e71ea35a8e62be20a059463bfe3abf043 From 694427bea430f238c81901e64d9e966594032476 Mon Sep 17 00:00:00 2001 From: kub Date: Mon, 23 Oct 2023 23:02:13 +0200 Subject: [PATCH 05/15] more changes to readme's --- AUTHORS | 9 +- README.md | 9 +- platform/base_readme.txt | 517 ++++++++++++++++++++++----------------- 3 files changed, 312 insertions(+), 223 deletions(-) diff --git a/AUTHORS b/AUTHORS index df62245c2..e5ed75808 100644 --- a/AUTHORS +++ b/AUTHORS @@ -4,6 +4,12 @@ Pandora, GPH device, PSP, Gizmondo ports, CPU core hacks lots of additional coding (see changeLog). Homepage: http://notaz.gp2x.de/ +irixxxx +improvements to dynamic recompilers, 32X emulation, ARM asm, sound, VDP, +platforms (GPH, PSP, generic linux), added SG-1000 and Game Gear support, +fixed a lot of bugs (and probably added more new bugs), cleaned up stuff, +probably more that I've already forgotten. + fDave project starter Cyclone 68000 core and PicoDrive core itself @@ -29,9 +35,6 @@ Homepage: http://www.mame.net/ Eke-Eke CD graphics processor and CD controller implementation (from Genesis Plus GX) -Irixxxx -Improvements to dynamic recompilers, 32X emulation, ARM asm, sound, VDP - Additional thanks ----------------- diff --git a/README.md b/README.md index 537106cbf..1b8030aac 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,10 @@ -This is yet another Megadrive / Genesis / Sega CD / Mega CD / 32X / SMS -emulator, which was originally written having ARM-based handheld devices +This is yet another SEGA 8 bit and 16 bit console emulator for emulating most +of the hardware SEGA has published up to and including the 32X. + +Emulated 16 bit systems: Megadrive/Genesis, Sega/Mega CD, 32X, Pico. +Emulated 8 bit systems: SG-1000, SC-3000, Master System/Mark III, Game Gear. + +PicoDrive was originally written having ARM-based handheld devices in mind, but later had got various improvements for other architectures too, like SH2 recompilers for MIPS (mips32r2), ARM64 (armv8), RISC-V (RV64IM) and PowerPC (G4/2.03). diff --git a/platform/base_readme.txt b/platform/base_readme.txt index c37ed0373..5925a4725 100644 --- a/platform/base_readme.txt +++ b/platform/base_readme.txt @@ -1,28 +1,26 @@ -# -PicoDrive 1.xx +About PicoDrive +--------------- + +#include "../README.md" -About ------ -#include "../README" How to make it run ------------------ +#ifdef GENERIC +Extract the zip file into some directory and run PicoDrive from there. +#endif #ifdef GP2X Extract all files to some directory on your SD and run PicoDrive.gpe from your GP2X/Wiz/Caanoo menu. The same .gpe supports GP2X F100/F200, Wiz and Caanoo, there is no need to use separate versions. -Then load a ROM and enjoy! ROMs can be in .smd or .bin format and can be zipped. -Sega/Mega CD images can be in ISO/CSO+MP3/WAV or CUE+BIN formats (read below -for more details). #endif #ifdef GIZ First make sure you have homebrew-enabled Service Pack installed. Then copy PicoDrive.exe and KGSDK.dll to any place in your filesystem (both files must be in the same directory) and run PicoDrive.exe using the launcher of your choice (some of them might require renaming PicoDrive.exe to Autorun.exe, placing it in -the root of SD, etc). Then load a ROM and enjoy! ROMs can be placed anywhere, can -be in .smd or .bin format and can be zipped (one ROM per zip). +the root of SD, etc). #endif #ifdef PSP If you are running a custom firmware, just copy the whole PicoDrive directory to @@ -35,6 +33,14 @@ If you are on 1.5, there is a separate KXploited version for it. Just copy the .pnd to /pandora/menu or /pandora/desktop. #endif +Then load a ROM and enjoy! Cartridge ROMs can be in various common formats and +can be zipped, one ROM file per zip. Certain extensions are used to detect the +console the ROM is for (.sg, .sc, .sms, .gg, .smd, .md, .gen, .32x, .pco). +For MSU games, load the .cue file and make sure the cartridge ROM has the same +name and is in the same directory. +Sega/Mega CD images can be in CHD, CUE+BIN/ISO or ISO/CSO+MP3/WAV format (read +below for more details). + This emulator has lots of options with various tweaks (for improved speed mostly), but it should have best compatibility in it's default config. If suddenly you start getting glitches or change something and forget what, use "Restore defaults" @@ -44,33 +50,37 @@ option. How to run Sega/Mega CD games ----------------------------- -To play any CD game, you need BIOS files. These files must be copied to +To play any non-MSU CD game you need BIOS files. These files must be copied to #ifdef PANDORA /pandora/appdata/picodrive/ directory (if you run PicoDrive once it will create that directory for you). #else +#ifdef GENERIC +the .picodrive directory in your home directory. +#else the same directory as PicoDrive files. #endif -Files can be named as follows: +#endif +Files must be named as follows: -US: us_scd1_9210.bin us_scd2_9306.bin SegaCDBIOS9303.bin -EU: eu_mcd1_9210.bin eu_mcd2_9303.bin eu_mcd2_9306.bin -JP: jp_mcd1_9112.bin jp_mcd1_9111.bin +US: us_scd1_9210.bin, us_scd2_9306.bin, SegaCDBIOS9303.bin +EU: eu_mcd1_9210.bin, eu_mcd2_9303.bin, eu_mcd2_9306.bin +JP: jp_mcd1_9112.bin, jp_mcd1_9111.bin these files can also be zipped. -The game must be dumped to CUE+BIN or CUE+ISO format. +The game must be dumped to CHD, CUE+BIN or CUE+ISO format. ISO/CSO+MP3/WAV is also supported, but may cause problems. -When using CUE/BIN, you must load .cue file from the menu, or else -the emu will not find audio tracks. +When using CUE/BIN, you must load .cue file from the menu, or else the emu will +not find audio tracks. Other important stuff --------------------- * Sega/Mega CD: If the background music is missing, the CD image format may be - wrong. Currently .cue/bin is recommended. Be aware that there are lots of bad - dumps on the web, and some use mp3 format for audio, which often causes - problems (see below). + wrong. Currently .cue/bin or .chd is recommended. Be aware that there are + lots of bad dumps on the web, and some use mp3 format for audio, which often + causes problems (see below). * While iso/mp3 format is supported, it's not recommended to use. Some of many problems with mp3 are listed below: * MP3s may be named incorrectly and will not play. @@ -81,7 +91,7 @@ Other important stuff you may be using a bad BIOS dump. Try another from a different source, like dumping it from your own console. #ifdef GP2X -* What using mp3s, use lower bitrate for better performance (96 or 128kbps +* When using mp3s, use lower bitrate for better performance (96 or 128kbps CBRs recommended). * GP2X F100/F200: When you use both GP2X CPUs, keep in mind that you can't overclock as high as when using ARM920 only. For example my GP2X when run @@ -93,294 +103,356 @@ Other important stuff #endif -Configuration -------------- - -@@0. "Save slot" -This is a slot number to use for savestates, when done by a button press outside -menu. This can also be configured to be changed with a button -(see "key configuration"). - -@@0. "Frameskip" -How many frames to skip rendering before displaying another. -"Auto" is recommended. +Options +------- @@0. "Region" This option lets you force the game to think it is running on machine from the specified region, or just to set autodetection order. Also affects Sega/Mega CD. -@@0. "Show FPS" -Self-explanatory. Format is XX/YY, where XX is the number of rendered frames and -YY is the number of emulated frames per second. +@@0. "Hotkey save/load slot" +This is a slot number to use for savestates, when done by a button press outside +menu. This can also be configured to be changed with a button +(see "Key configuration"). -@@0. "Enable sound" -Does what it says. You must enable at least YM2612 or SN76496 (in advanced options, -see below) for this to make sense (already done by default). +@@0. "Interface options" +Enters Interface options menu (see below). -@@0. "Sound Quality" -#ifdef PSP -Sound sample rate, affects sound quality and emulation performance. -22050Hz setting is the recommended one. -#else -Sound sample rate and stereo mode. Mono is not available in Sega/Mega CD mode. -#endif +@@0. "Display options" +Enters Display options menu (see below). -@@0. "Confirm savestate" -Allows to enable confirmation on savestate saving (to prevent savestate overwrites), -on loading (to prevent destroying current game progress), and on both or none, when -using shortcut buttons (not menu) for saving/loading. +@@0. "Sound options" +Enters Sound options menu (see below). -@@0. "[Display options]" -Enters Display options menu (see below). +@@0. "MD/Genesis/Pico options" +Enters Mega Drive/Genesis/Pico options menu (see below). -@@0. "[Sega/Mega CD options]" +@@0. "Sega/Mega CD add-on" Enters Sega/Mega CD options menu (see below). -@@0. "[32X options]" +@@0. "32X add-on" Enters 32X options menu (see below). -@@0. "[Advanced options]" +@@0. "SG/SMS/GG options" +Enters SG-1000/SC-3000/Master System/Game Gear options menu (see below). + +@@0. "Advanced options" Enters advanced options menu (see below). -@@0. "Save cfg as default" -If you save your config here it will be loaded on next ROM load, but only if there -is no game specific config saved (which will be loaded in that case). +@@0. "Restore defaults" +Restores all options (except controls) to defaults. + + +Interface options +----------------- + +@@1. "Save global options" +If you save your config here it will be loaded on next ROM load, but only if +there is no game specific config saved (which will be loaded in that case). You can press left/right to switch to a different config profile. -@@0. "Save cfg for current game only" +@@1. "Save game options" Whenever you load current ROM again these settings will be loaded. -@@0. "Restore defaults" -Restores all options (except controls) to defaults. +@@1. "Show FPS" +Self-explanatory. Format is XX/YY, where XX is the number of rendered frames and +YY is the number of emulated frames per second. + +@@1. "Confirm save/load" +Allows to enable confirmation on saving (to prevent savestate overwrites), on +loading (to prevent destroying current game progress), and on both or none, when +using shortcut buttons (not menu) for saving/loading. + +@@1. "Don't save last used ROM" +This will disable writing last used ROM to config on exit (what might cause SD +card corruption according to DaveC). Display options --------------- +#ifdef GENERIC + +@@2. "Video output mode" +SDL Window: +This is the default mode on portable devices, used if no overlay modes are +available. Window size is fixed at 320x240. +Video Overlay: +Used if hardware accelerated overlay scaling is available. Supports flexible +window sizes. The "2X" version has a higher color resolution but is slower. +#endif -#ifndef PANDORA -@@1. "Renderer" -#ifdef GP2X -8bit fast: -This enables alternative heavily optimized tile-based renderer, which renders -pixels not line-by-line (this is what accurate renderers do), but in 8x8 tiles, -which is much faster. But because of the way it works it can't render any -mid-frame image changes (raster effects), so it is useful only with some games. +@@2. "Frameskip" +How many frames to skip rendering before displaying another. +"Auto" is recommended. -Other two are accurate line-based renderers. The 8bit is faster but does not -run well with some games like Street Racer. +@@2. "Max auto frameskip" +How many frames to skip rendering at most if Frameskip is "Auto". -#endif -#ifdef GIZ -This option allows to switch between 16bit and 8bit renderers. The 8bit one is -a bit faster for some games, but not much, because colors still need to be -converted to 16bit, as this is what Gizmondo requires. It also introduces -graphics problems for some games, so it's best to use 16bit one. +#ifdef GENERIC +@@2. "Horizontal scaling" +This allows to resize the displayed image. "OFF" is unscaled, "software" uses +a smoothing filter to scale the image. "hardware" uses a hardware scaler for +better performance. Hardware scaling is not available on every device. -#endif -#ifdef PSP -This option allows to switch between fast and accurate renderers. The fast one -is much faster, because it draws the whole frame at a time, instead of doing it -line by line, like the accurate one does. But because of the way it works it -can't render any mid-frame image changes (raster effects), so it is useful only -for some games. +@@2. "Vertical scaling" +This allows to resize the displayed image. "OFF" is unscaled, "software" uses +a smoothing filter to scale the image. "hardware" uses a hardware scaler for +better performance. Hardware scaling is not available on every device. +@@2. "Scaler type" +Selects the filtering the software scaler will apply. "nearest" is unfiltered, +"bilinear" makes the image smoother but blurrier. #endif +#ifdef PANDORA +@@2. "Filter" +Selects filter type used for image filtering. + +Other options allow to set up scaling, filtering and vertical sync. #endif #ifdef GP2X -@@1. "Tearing Fix" -Wiz only: works around the tearing problem by using portrait mode. Causes ~5-10% -performance hit, but eliminates the tearing effect. - -@@1. "Gamma correction" +@@2. "Gamma correction" F100/F200 only: Alters image gamma through GP2X hardware. Larger values make image to look brighter, lower - darker (default is 1.0). -@@1. "Vsync" +@@2. "Horizontal scaling" +This allows to resize the displayed image. "OFF" is unscaled, "software" uses +a smoothing filter to scale the image. F100/F200 only: "hardware" uses a +hardware scaler for better performance. + +@@2. "Vertical scaling" +This allows to resize the displayed image. "OFF" is unscaled, "software" uses +a smoothing filter to scale the image. F100/F200 only: "hardware" uses a +hardware scaler for better performance. + +@@2. "Tearing Fix" +Wiz only: works around the tearing problem by using portrait mode. Causes ~5-10% +performance hit, but eliminates the tearing effect. + +@@2. "Vsync" This one adjusts the LCD refresh rate to better match game's refresh rate and starts synchronizing rendering with it. Should make scrolling smoother and eliminate tearing on F100/F200. #endif #ifdef GIZ -@@1. "Scanline mode" +@@2. "Scanline mode" This option was designed to work around slow framebuffer access (the Gizmondo's main bottleneck) by drawing every other line (even numbered lines only). This improves performance greatly, but looses detail. -@@1. "Scale low res mode" -The Genesis/Megadrive had several graphics modes, some of which were only 256 +@@2. "Scale low res mode" +The Genesis/Mega Drive had several graphics modes, some of which were only 256 pixels wide. This option scales their width to 320 by using simple pixel averaging scaling. Works only when 16bit renderer is enabled. -@@1. "Double buffering" +@@2. "Double buffering" Draws the display to offscreen buffer, and flips it with visible one when done. Unfortunately this causes serious tearing, unless v-sync is used (next option). -@@1. "Wait for V-sync" +@@2. "Wait for V-sync" Waits for vertical sync before drawing (or flipping buffers, if previous option is enabled). Emulation is stopped while waiting, so this causes large performance hit. #endif #ifdef PSP -@@1. "Scale factor" -This allows to resize the displayed image by using the PSP's hardware. The number is -used to multiply width and height of the game image to get the size of image to be -displayed. If you just want to make it fullscreen, just use "Set to fullscreen" -setting below. - -@@1. "Hor. scale (for low res. games)" -This one works similarly as the previous setting, but can be used to apply additional -scaling horizontally, and is used for games which use lower (256 pixel wide) Gen/MD -resolution. +@@2. "Horizontal scaling" +This allows to resize the displayed image by using the PSP's hardware. "OFF" is +unscaled, "4:3" is closest to the original Mega Drive screen, "fullscreen" uses +the full screen width. -@@1. "Hor. scale (for hi res. games)" -Same as above, only for higher (320 pixel wide) resolution using games. +@@2. "Vertical scaling" +This allows to resize the displayed image by using the PSP's hardware. "OFF" is +unscaled, "4:3" is closest to the original Mega Drive screen, "fullscreen" uses +the full screen height. -@@1. "Bilinear filtering" -If this is enabled, PSP hardware will apply bilinear filtering on the resulting image, -making it smoother, but blurry. +@@2. "Scaler type" +Selects the filtering the PSP hardware will apply for scaling. "Bilinear" makes +the image smoother but blurrier. -@@1. "Gamma adjustment" +@@2. "Gamma adjustment" Color gamma can be adjusted with this. -@@1. "Black level" +@@2. "Black level" This can be used to reduce unwanted "ghosting" effect for dark games, by making -black pixels brighter. Use in conjunction with "gamma adjustment" for more effect. +black pixels brighter. Use together with "gamma adjustment" for more effect. + +@@2. "Wait for v-sync" +If enabled, wait for the screen to finish updating before switching to next +frame, to avoid tearing. +#endif -@@1. "Wait for v-sync" -Wait for the screen to finish updating before switching to next frame, to avoid tearing. -There are 3 options: -* never: don't wait for vsync. -* sometimes: wait only if emulator is running fast enough. -* always: always wait (causes emulation slowdown). -@@1. "Set to unscaled centered" -Adjust the resizing options to set game image to it's original size. +Sound options +------------- -@@1. "Set to 4:3 scaled" -Scale the image up, but keep 4:3 aspect, by adding black borders. +@@3. "Enable sound" +Does what it says. -@@1. "Set to fullscreen" -Adjust the resizing options to make the game image fullscreen. +@@3. "Sound Quality" +#ifdef PSP +Sound sample rate. Lower rates improve performance but sound quality is lower. +22050Hz setting is the recommended one. +#else +Sound sample rate and stereo mode. Lower rates improve performance but sound +quality is lower. #endif -#ifdef PANDORA -Allows to set up scaling, filtering and vertical sync. + +@@3. "Sound filter" +Enables a low pass filter, similar to filtering in the real Mega Drive hardware. + +@@3. "Filter strength" +Controls the sound filter. Higher values have more impact. + + +Mega Drive/Genesis/Pico options +------------------------------- +#ifndef PANDORA + +@@4. "Renderer" +#ifdef GP2X +8bit fast: +This enables alternative heavily optimized tile-based renderer, which renders +pixels not line-by-line (this is what accurate renderers do), but in 8x8 tiles, +which is much faster. But because of the way it works it can't render any +mid-frame image changes (raster effects), so it is useful only with some games. + +Other two are accurate line-based renderers. The 8bit is faster but does not +run well with some games like Street Racer. #endif +#ifdef GIZ +This option allows to switch between 16bit and 8bit renderers. The 8bit one is +a bit faster for some games, but not much, because colors still need to be +converted to 16bit, as this is what Gizmondo requires. It also introduces +graphics problems for some games, so it's best to use 16bit one. +#endif +#ifdef PSP +This option allows to switch between fast and accurate renderers. The fast one +is much faster, because it draws the whole frame at a time, instead of doing it +line by line, like the accurate one does. But because of the way it works it +can't render any mid-frame image changes (raster effects), so it is useful only +for some games. +#endif +#endif + +@@4. "FM audio" +This enables emulation of six-channel FM sound synthesizer chip, which was used +to produce sound effects and music. +@@4. "FM filter" +This filter makes the sound output more accurate, but it is slower, especially +for lower sound rates. -Sega/Mega CD options --------------------- +@@4. "FM DAC noise" +Makes the sound output more like a first model Mega Drive/Genesis if enabled. +Later models had an improved FM chip without the DAC noise. -@@2. "CD LEDs" + +Sega/Mega CD add-on +------------------- + +@@5. "Save RAM cart" +Here you can enable 64K RAM cart. Format it in BIOS if you do. + +@@5. "CD LEDs" The Sega/Mega CD unit had two blinking LEDs (red and green) on it. This option will display them on top-left corner of the screen. -@@2. "CDDA audio" +@@5. "CDDA audio" This option enables CD audio playback. -@@2. "PCM audio" +@@5. "PCM audio" This enables 8 channel PCM sound source. It is required for some games to run, because they monitor state of this audio chip. -@@2. "Save RAM cart" -Here you can enable 64K RAM cart. Format it in BIOS if you do. -@@2. "Scale/Rot. fx" -The Sega/Mega CD had scaling/rotation chip, which allows effects similar to -"Mode 7" effects in SNES. On slow systems like GP2X, disabling may improve -performance but cause graphical glitches. +32X add-on +---------- - -32X options ------------ - -@@3. "32X enabled" -Enables emulation of addon. Option only takes effect when ROM is reloaded. - -#ifdef GP2X -@@3. "32X renderer" +@@6. "32X renderer" This currently only affects how the Genesis/MD layers are rendered, which is same as "Renderer" in display options. -#endif -@@3. "PWM sound" +@@6. "PWM audio" Emulates PWM sound portion of 32X hardware. Disabling this may greatly improve performance for games that dedicate one of SD2s for sound, but will cause missing sound effects and instruments. -@@3. "Master SH2 cycles" / "Slave SH2 cycles" -This allows underclocking the 32X CPUs for better emulation performance. The -number has the same meaning as cycles in DOSBox, which is cycles per millisecond. -Underclocking too much may cause various in-game glitches. +@@6. "PWM IRQ optimization" +Enabling this may improve performance, but may also introduce sound glitches. -Advanced configuration ----------------------- +SG/Master System/Game Gear options +---------------------------------- -@@4. "Use SRAM/BRAM savestates" -This will automatically read/write SRAM (or BRAM for Sega/Mega CD) savestates for -games which are using them. SRAM is saved whenever you enter the menu or exit the -emulator. +@@7. "System" +Selects which of the Sega 8 bit systems is emulated. "auto" is recommended. -@@4. "Disable sprite limit" -The MegaDrive/Genesis had a limit on how many sprites (usually smaller moving -objects) can be displayed on single line. This option allows to disable that -limit. Note that some games used this to hide unwanted things, so it is not -always good to enable this option. +@@7. "Cartridge mapping" +Some cartridges have hardware to enable additional capabilities, e.g. mapping +excess ROM storage or acessing a battery backed RAM storage. "auto" is +recommended, but in some rare cases it may be needed to manually select this. -@@4. "Emulate Z80" -Enables emulation of Z80 chip, which was mostly used to drive the other sound chips. -Some games do complex sync with it, so you must enable it even if you don't use -sound to be able to play them. +@@7. "Game Gear LCD ghosting" +The Game Gear LCD display had a very noticeable inertia for image changes. This +setting enables emulating the effect, with "weak" being recommended. -@@4. "Emulate YM2612 (FM)" -This enables emulation of six-channel FM sound synthesizer chip, which was used to -produce sound effects and music. +@@7. "FM sound unit" +The Japanese Master System (aka Mark III) has an extension slot for an FM sound +unit. Some games made use of this for providing better music and effects. +Disabling this improves performance for games using the FM unit, and usually +means falling back to the non-FM sound. -@@4. "Emulate SN76496 (PSG)" -This enables emulation of PSG (programmable sound generation) sound chip for -additional effects. -Note: if you change sound settings AFTER loading a ROM, you may need to reset -game to get sound. This is because most games initialize sound chips on -startup, and this data is lost when sound chips are being enabled/disabled. +Advanced options +---------------- -@@4. "gzip savestates" -This will always apply gzip compression on your savestates, allowing you to -save some space and load/save time. +@@8. "Disable frame limiter" +This allows games to run faster then 50/60fps, useful for benchmarking. -@@4. "Don't save last used ROM" -This will disable writing last used ROM to config on exit (what might cause SD -card corruption according to DaveC). +@@8. "Disable sprite limit" +The Mega Drive/Genesis had a limit on how many sprites (usually smaller moving +objects) can be displayed on single line. This option allows to disable that +limit. Note that some games used this to hide unwanted things, so it is not +always good to enable this option. -@@4. "Disable idle loop patching" +@@8. "Disable idle loop patching" Idle loop patching is used to improve performance, but may cause compatibility problems in some rare cases. Try disabling this if your game has problems. -@@4. "Disable frame limiter" -This allows games to run faster then 50/60fps, useful for benchmarking. +@@8. "Emulate Game Gear LCD" +Disabling this option displays the full Game Gear VDP image with the normally +invisible borders. + +@@8. "Enable dynarecs" +This enables dynamic recompilation for SH2 and SVP CPU code, which is improving +emulation performance greatly. SVP dynarec is only available on 32 bit ARM CPUs. +@@8. "Master SH2 cycles" / "Slave SH2 cycles" +This allows underclocking the 32X CPUs for better emulation performance. The +number has the same meaning as cycles in DOSBox, which is cycles per millisecond. +Underclocking too much may cause various in-game glitches. #ifdef GP2X -@@4. "Use ARM940 core for sound" + +@@8. "Use ARM940 core for sound" F100/F200: This option causes PicoDrive to use ARM940T core (GP2X's second CPU) for sound (i.e. to generate YM2612 samples) to improve performance noticeably. It also decodes MP3s in Sega/Mega CD mode. - #endif -@@4. "Enable dynarecs" -This enables dynamic recompilation for SH2 and SVP CPU code, -what improves emulation performance greatly. Key configuration ----------------- -Select "Configure controls" from the main menu. Then select "Player 1" and you will -see two columns. The left column lists names of Genesis/MD controller buttons, and -the right column your handheld ones, which are assigned. +Select "Configure controls" from the options menu. Then selecting "Player " +will display 2 columns. The left column lists names of Genesis/MD controller +buttons, the right column shows which key on your handheld is assigned to it. -There is also option to enable 6 button pad (will allow you to configure XYZ +There is also option to enable 6 button pads (will allow you to configure XYZ buttons), and an option to set turbo rate (in Hz) for turbo buttons. +Players 3 and 4 can only be used if a 4 player adapter is selected for input +device 1, and the game is supporting this. Only 3 button pads are currently +supported in 4 player mode. + Cheat support ------------- @@ -423,36 +495,44 @@ a ROM. Then Cheat Menu Option should appear in main menu. What is emulated? ----------------- -Genesis/MegaDrive: -#ifdef PSP -main 68k @ 7.6MHz: yes, FAME/C core -z80 @ 3.6MHz: yes, CZ80 core -#else -main 68k @ 7.6MHz: yes, Cyclone core -z80 @ 3.6MHz: yes, DrZ80 core -#endif -VDP: yes, except some quirks and modes not used by games -YM2612 FM: yes, optimized MAME core +SG-1000/SC-3000/Master System/Game Gear: +z80 @ 3.6MHz: yes, DrZ80 (on 32 bit ARM CPUs) or CZ80 core +VDP: yes, all SG/SMS/GG modes, except some quirks not used by games +YM2413 FM: yes, digital-sound-antiques core SN76489 PSG: yes, MAME core -SVP chip: yes! This is first emu to ever do this. Some in-cart mappers are also supported. +Genesis/Mega Drive: +main 68k @ 7.6MHz: yes, Cyclone (on 32 bit ARM CPUs) or FAME/C core +z80 @ 3.6MHz: yes, DrZ80 (on 32 bit ARM CPUs) or CZ80 core +VDP: yes, except some quirks and mode 4, not used by games +YM2612 FM: yes, optimized MAME core +SN76489 PSG: yes, MAME core +SVP chip: yes! This is first emu to ever do this +Pico PCM: yes, MAME core +Some Mega Drive/Genesis in-cart mappers are also supported. + Sega/Mega CD: -#ifdef PSP -another 68k @ 12.5MHz: yes, FAME/C too -#else -another 68k @ 12.5MHz: yes, Cyclone too -#endif +another 68k @ 12.5MHz: yes, Cyclone or FAME/C too gfx scaling/rotation chip (custom ASIC): yes PCM sound source: yes CD-ROM controller: yes (mostly) bram (internal backup RAM): yes +RAM cart: yes 32X: -2x SH2 @ 23MHz: yes, custom recompiler +2x SH2 @ 23MHz: yes, MAME core or custom recompiler Super VDP: yes PWM: yes +Pico: +main 68k @ 7.6MHz: yes, Cyclone (on 32 bit ARM CPUs) or FAME/C core +VDP: yes, except some quirks and mode 4, not used by games +SN76489 PSG: yes, MAME core +ADPCM: yes, MAME core +Pico Pen: yes, to some extend +Pico Storyware pages: no + Problems / limitations ---------------------- @@ -461,13 +541,14 @@ Problems / limitations * SVP emulation is terribly slow. #endif * Various VDP modes and quirks (window bug, scroll size 2, etc.) are not - emulated, as very few games use this (if any at all). -* The emulator is not 100% accurate, so some things may not work as expected. + perfectly emulated, as very few games use this (if any at all). +* The emulator is designed for speed and not 100% accurate, so some things may + not work as expected. * The FM sound core doesn't support all features and has some accuracy issues. Changelog -------- +--------- #include "../ChangeLog" @@ -483,9 +564,9 @@ This emulator is made of the code from following people/projects: License ------- -This program and it's code is released under the terms of MAME license: +This program and its code is released under the terms of MAME license: #include "../COPYING" -SEGA/Genesis/MegaDrive/SEGA-CD/Mega-CD/32X are trademarks of -Sega Enterprises Ltd. +SEGA/Master System/Game Gear/Genesis/Mega Drive/SEGA CD/Mega CD/32X/Pico are +trademarks of Sega Enterprises Ltd. From d818246c51ad8bd7c2646cc494d12beb558ec20e Mon Sep 17 00:00:00 2001 From: kub Date: Mon, 23 Oct 2023 23:16:43 +0200 Subject: [PATCH 06/15] handle "Mega Drive" naming consistently --- README.md | 2 +- platform/common/emu.c | 2 +- platform/common/menu_pico.c | 8 ++++---- platform/libretro/libretro_core_options.h | 2 +- platform/opendingux/data/default.gcw0.desktop | 2 +- platform/opendingux/data/default.retrofw.desktop | 2 +- platform/opendingux/data/default.rg99.desktop | 2 +- platform/pandora/PicoDrive.pxml.template | 4 ++-- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 1b8030aac..688066373 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ This is yet another SEGA 8 bit and 16 bit console emulator for emulating most of the hardware SEGA has published up to and including the 32X. -Emulated 16 bit systems: Megadrive/Genesis, Sega/Mega CD, 32X, Pico. +Emulated 16 bit systems: Mega Drive/Genesis, Sega/Mega CD, 32X, Pico. Emulated 8 bit systems: SG-1000, SC-3000, Master System/Mark III, Game Gear. PicoDrive was originally written having ARM-based handheld devices diff --git a/platform/common/emu.c b/platform/common/emu.c index 4e24c00bf..43c7d0af7 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -371,7 +371,7 @@ static void system_announce(void) } else if (PicoIn.AHW & PAHW_32X) { sys_name = "32X"; } else { - sys_name = "MegaDrive"; + sys_name = "Mega Drive"; if ((Pico.m.hardware & 0xc0) == 0x80) sys_name = "Genesis"; } diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 14ddf0678..a8e5e3b6b 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -414,7 +414,7 @@ static const char *mgn_dev_name(int id, int *offs) const char *indev0_names[] = { "none", "3 button pad", "6 button pad", "Team player", "4 way play", NULL }; const char *indev1_names[] = { "none", "3 button pad", "6 button pad", NULL }; -static char h_play34[] = "Works only for Megadrive/CD/32X games having\n" +static char h_play34[] = "Works only for Mega Drive/CD/32X games having\n" "support for Team player or 4 way play"; static menu_entry e_menu_keyconfig[] = @@ -462,7 +462,7 @@ static int menu_loop_keyconfig(int id, int keys) static const char h_renderer[] = "16bit is more accurate, 8bit is faster"; static const char h_fmsound[] = "Disabling improves performance, but breaks sound"; -static const char h_dacnoise[] = "FM chips in the 1st Megadrive model have DAC noise,\n" +static const char h_dacnoise[] = "FM chips in the 1st Mega Drive model have DAC noise,\n" "newer models used different chips without this"; static const char h_fmfilter[] = "Improves sound accuracy but is noticeably slower,\n" "best´quality if native rate isn't working"; @@ -699,7 +699,7 @@ static const char *mgn_opt_alpha(int id, int *offs) static const char h_ensound[] = "Disabling turns off sound output, however all\n" "enabled sound components are still emulated"; -static const char h_quality[] = "native: Megadrive FM hardware rate (~53000Hz),\n" +static const char h_quality[] = "native: Mega Drive FM hardware rate (~53000Hz),\n" "best quality, but may not work on some devices"; static const char h_lowpass[] = "Low pass filter for sound closer to real hardware"; static const char h_lpalpha[] = "Higher values have more impact"; @@ -949,7 +949,7 @@ static menu_entry e_menu_options[] = mee_handler ("Interface options", menu_loop_ui_options), mee_handler ("Display options", menu_loop_gfx_options), mee_handler ("Sound options", menu_loop_snd_options), - mee_handler ("MD/Genesis options", menu_loop_md_options), + mee_handler ("MD/Genesis/Pico options", menu_loop_md_options), mee_handler (" Sega/Mega CD add-on", menu_loop_cd_options), #ifndef NO_32X mee_handler (" 32X add-on", menu_loop_32x_options), diff --git a/platform/libretro/libretro_core_options.h b/platform/libretro/libretro_core_options.h index 4498b4695..1e1d4c4bf 100644 --- a/platform/libretro/libretro_core_options.h +++ b/platform/libretro/libretro_core_options.h @@ -208,7 +208,7 @@ struct retro_core_option_v2_definition option_defs_us[] = { "picodrive_sound_rate", "Audio Sample Rate (Hz)", "Sample Rate (Hz)", - "Higher values increase sound quality. Lower values may increase performance. Native is the Megadrive sound chip rate (~53000). Select this if you want the most accurate audio.", + "Higher values increase sound quality. Lower values may increase performance. Native is the Mega Drive sound chip rate (~53000). Select this if you want the most accurate audio.", NULL, "audio", { diff --git a/platform/opendingux/data/default.gcw0.desktop b/platform/opendingux/data/default.gcw0.desktop index 17ff8cb46..857f932f8 100644 --- a/platform/opendingux/data/default.gcw0.desktop +++ b/platform/opendingux/data/default.gcw0.desktop @@ -1,7 +1,7 @@ [Desktop Entry] Type=Application Name=Picodrive -Comment=A megadrive/genesis emulator +Comment=A mega drive/genesis emulator Exec=PicoDrive %f Icon=megadrive Terminal=false diff --git a/platform/opendingux/data/default.retrofw.desktop b/platform/opendingux/data/default.retrofw.desktop index 36a01e5f7..d702b339e 100644 --- a/platform/opendingux/data/default.retrofw.desktop +++ b/platform/opendingux/data/default.retrofw.desktop @@ -1,6 +1,6 @@ [Desktop Entry] Name=Picodrive -Comment=A megadrive/genesis emulator +Comment=A mega drive/genesis emulator Exec=PicoDrive %f Icon=megadrive Categories=emulators; diff --git a/platform/opendingux/data/default.rg99.desktop b/platform/opendingux/data/default.rg99.desktop index 17ff8cb46..857f932f8 100644 --- a/platform/opendingux/data/default.rg99.desktop +++ b/platform/opendingux/data/default.rg99.desktop @@ -1,7 +1,7 @@ [Desktop Entry] Type=Application Name=Picodrive -Comment=A megadrive/genesis emulator +Comment=A mega drive/genesis emulator Exec=PicoDrive %f Icon=megadrive Terminal=false diff --git a/platform/pandora/PicoDrive.pxml.template b/platform/pandora/PicoDrive.pxml.template index 96d7b1ec4..d7203a1e3 100644 --- a/platform/pandora/PicoDrive.pxml.template +++ b/platform/pandora/PicoDrive.pxml.template @@ -14,8 +14,8 @@ PicoDrive @major@.@minor@@build_post@ - Genesis/MegaDrive/SegaCD/32x Emulator. - Ein MegaDrive/SegaCD/32x Emulator + Genesis/Mega Drive/Sega CD/32x Emulator. + Ein Mega Drive/Sega CD/32x Emulator From 725e007ae55d715aa5ac1e042309a320e32f9d58 Mon Sep 17 00:00:00 2001 From: kub Date: Mon, 23 Oct 2023 23:04:03 +0200 Subject: [PATCH 07/15] revisit CI using a set of toolchain containers from my toolchains repo support more platforms, artifact uploading, some release preparation --- .github/workflows/ci-gp2x.yml | 20 -- .github/workflows/ci-libretro-default.yml | 11 - .github/workflows/ci-linux.yml | 17 -- .github/workflows/ci-pandora.yml | 20 -- .github/workflows/ci-psp.yml | 20 -- .github/workflows/ci.yml | 268 ++++++++++++++++++++++ 6 files changed, 268 insertions(+), 88 deletions(-) delete mode 100644 .github/workflows/ci-gp2x.yml delete mode 100644 .github/workflows/ci-libretro-default.yml delete mode 100644 .github/workflows/ci-linux.yml delete mode 100644 .github/workflows/ci-pandora.yml delete mode 100644 .github/workflows/ci-psp.yml create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci-gp2x.yml b/.github/workflows/ci-gp2x.yml deleted file mode 100644 index 1be74f72f..000000000 --- a/.github/workflows/ci-gp2x.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: CI (GP2X) -on: [push, pull_request] -jobs: - build-linux: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - submodules: true - - name: Install dependencies - run: | - whoami - sudo apt-get update -qq - sudo apt-get install -y wget - wget http://notaz.gp2x.de/downloads/gp2x/devkitGP2X_small.tar.xz - tar -C /tmp/ -xf devkitGP2X_small.tar.xz - - name: configure - run: DUMP_CONFIG_LOG=1 PATH=$PATH:/tmp/devkitGP2X/bin CROSS_COMPILE=arm-linux- ./configure --platform=gp2x - - name: make - run: PATH=$PATH:/tmp/devkitGP2X/bin CROSS_COMPILE=arm-linux- make PLATFORM_MP3=0 diff --git a/.github/workflows/ci-libretro-default.yml b/.github/workflows/ci-libretro-default.yml deleted file mode 100644 index eccbaf5ef..000000000 --- a/.github/workflows/ci-libretro-default.yml +++ /dev/null @@ -1,11 +0,0 @@ -name: CI (libretro default) -on: [push, pull_request] -jobs: - build-linux: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - submodules: true - - name: make - run: LDFLAGS=-Wl,--no-undefined make -f Makefile.libretro diff --git a/.github/workflows/ci-linux.yml b/.github/workflows/ci-linux.yml deleted file mode 100644 index 7ab7d3603..000000000 --- a/.github/workflows/ci-linux.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: CI (Linux) -on: [push, pull_request] -jobs: - build-linux: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - submodules: true - - name: Install dependencies - run: | - sudo apt-get update -qq - sudo apt-get install -y libsdl1.2-dev libasound2-dev libpng-dev libz-dev - - name: configure - run: DUMP_CONFIG_LOG=1 ./configure - - name: make - run: make diff --git a/.github/workflows/ci-pandora.yml b/.github/workflows/ci-pandora.yml deleted file mode 100644 index e922bcf00..000000000 --- a/.github/workflows/ci-pandora.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: CI (pandora) -on: [push, pull_request] -jobs: - build-linux: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - submodules: true - - name: Install dependencies - run: | - whoami - sudo apt-get update -qq - sudo apt-get install -y wget - wget http://notaz.gp2x.de/misc/pnd/toolchains/arm-gcc-4.9.4_with_libs_small.tar.xz - tar -C /tmp/ -xf arm-gcc-4.9.4_with_libs_small.tar.xz - - name: configure - run: DUMP_CONFIG_LOG=1 PATH=$PATH:/tmp/arm-gcc-4.9.4/bin CPATH=/tmp/arm-gcc-4.9.4/arm-unknown-linux-gnueabi/sysroot/usr/local/include/ CROSS_COMPILE=arm-unknown-linux-gnueabi- ./configure --platform=pandora - - name: make - run: PATH=$PATH:/tmp/arm-gcc-4.9.4/bin CPATH=/tmp/arm-gcc-4.9.4/arm-unknown-linux-gnueabi/sysroot/usr/local/include/ CROSS_COMPILE=arm-unknown-linux-gnueabi- make diff --git a/.github/workflows/ci-psp.yml b/.github/workflows/ci-psp.yml deleted file mode 100644 index 9682380e5..000000000 --- a/.github/workflows/ci-psp.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: CI (PSP) -on: [push, pull_request] -jobs: - build-linux: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - submodules: true - - name: Install dependencies - run: | - whoami - sudo apt-get update -qq - sudo apt-get install -y wget - wget https://github.com/pspdev/pspdev/releases/download/latest/pspdev-ubuntu-latest.tar.gz - tar -C /tmp/ -xf pspdev-ubuntu-latest.tar.gz - - name: configure - run: DUMP_CONFIG_LOG=1 PATH=$PATH:/tmp/pspdev/bin CROSS_COMPILE=psp- ./configure --platform=psp - - name: make - run: PATH=$PATH:/tmp/pspdev/bin CROSS_COMPILE=psp- make diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..e22d343e9 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,268 @@ +name: Picodrive CI +on: [push, pull_request] +jobs: + prepare-release: + runs-on: ubuntu-latest + steps: + - name: create release + id: create_release + if: ${{ github.ref_type == 'tag' }} + uses: actions/create-release@v1 + with: + prerelease: ${{ contains(github.ref, '-') }} + tag_name: ${{ github.ref }} + release_name: ${{ github.ref }} + + build-linux: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + submodules: true + - name: Install dependencies + run: | + sudo apt-get update -qq + sudo apt-get install -y libsdl1.2-dev libasound2-dev libpng-dev libz-dev + - name: configure + run: DUMP_CONFIG_LOG=1 ./configure + - name: make + run: make + + build-libretro: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + submodules: true + - name: make + run: LDFLAGS=-Wl,--no-undefined make -f Makefile.libretro + + + build-gp2x: + needs: prepare-release + runs-on: ubuntu-latest + container: ghcr.io/irixxxx/toolchain-gp2x + permissions: + packages: read + steps: + - uses: actions/checkout@v3 + with: + submodules: true + - name: build + run: | + git config --global --add safe.directory $PWD + ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) + CROSS_COMPILE=arm-none-eabi- ./configure --platform=gp2x + make PLATFORM_MP3=0 + make -C platform/gp2x rel VER=$ver + mv PicoDrive_$ver.zip PicoDrive-gph_$ver.zip + - name: artifacts + uses: actions/upload-artifact@v3 + with: + name: GP2X + path: PicoDrive-gph_*.zip + - name: publish + if: ${{ github.ref_type == 'tag' }} + uses: actions/upload-release-asset@v1 + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: PicoDrive-gph_*.zip + + build-pandora: + needs: prepare-release + runs-on: ubuntu-latest + container: ghcr.io/irixxxx/toolchain-pandora + steps: + - uses: actions/checkout@v3 + with: + submodules: true + - name: build + run: | + git config --global --add safe.directory $PWD + ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) + ./configure --platform=pandora + make + mv PicoDrive PicoDrive-pandora + ${CROSS_COMPILE}strip PicoDrive-pandora + - name: artifacts + uses: actions/upload-artifact@v3 + with: + name: Pandora + path: PicoDrive-pandora + - name: publish + if: ${{ github.ref_type == 'tag' }} + uses: actions/upload-release-asset@v1 + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: PicoDrive-pandora + + build-psp: + needs: prepare-release + runs-on: ubuntu-latest + container: ghcr.io/pspdev/pspdev + steps: + - name: build environment + run: | + apk add git gcc g++ zip + - uses: actions/checkout@v3 + with: + submodules: true + - name: build + run: | + git config --global --add safe.directory $PWD + ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) + CROSS_COMPILE=psp- ./configure --platform=psp + CROSS_COMPILE=psp- make + make -C platform/psp rel VER=$ver + - name: artifacts + uses: actions/upload-artifact@v3 + with: + name: PSP + path: PicoDrive_psp_*.zip + - name: publish + if: ${{ github.ref_type == 'tag' }} + uses: actions/upload-release-asset@v1 + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: PicoDrive_psp_*.zip + + + build-dingux: + needs: prepare-release + runs-on: ubuntu-latest + permissions: + packages: read + container: ghcr.io/irixxxx/toolchain-dingux + steps: + - uses: actions/checkout@v3 + with: + submodules: true + - name: build + run: | + git config --global --add safe.directory $PWD + ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) + CROSS_COMPILE=mipsel-linux- ./configure --platform=dingux + CROSS_COMPILE=mipsel-linux- make + mv PicoDrive-dge.zip PicoDrive-dge-$ver.zip + - name: artifacts + uses: actions/upload-artifact@v3 + with: + name: Dingux + path: PicoDrive-dge*.zip + - name: publish + if: ${{ github.ref_type == 'tag' }} + uses: actions/upload-release-asset@v1 + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: PicoDrive-dge*.zip + + build-gcw0: + needs: prepare-release + runs-on: ubuntu-latest + container: ghcr.io/irixxxx/toolchain-opendingux + steps: + - uses: actions/checkout@v3 + with: + submodules: true + - name: build + run: | + git config --global --add safe.directory $PWD + ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) + CROSS_COMPILE=mipsel-linux- ./configure --platform=gcw0 + CROSS_COMPILE=mipsel-linux- make + mv PicoDrive.opk PicoDrive-gcw0-$ver.opk + - name: artifacts + uses: actions/upload-artifact@v3 + with: + name: GCW0 + path: PicoDrive-gcw0*.opk + - name: publish + if: ${{ github.ref_type == 'tag' }} + uses: actions/upload-release-asset@v1 + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: PicoDrive-gcw0*.opk + + build-opendingux: + needs: prepare-release + runs-on: ubuntu-latest + container: ghcr.io/irixxxx/toolchain-opendingux + steps: + - uses: actions/checkout@v3 + with: + submodules: true + - name: build + run: | + git config --global --add safe.directory $PWD + ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) + CROSS_COMPILE=mipsel-linux- ./configure --platform=opendingux + CROSS_COMPILE=mipsel-linux- make + mv PicoDrive.opk PicoDrive-opendingux-$ver.opk + - name: artifacts + uses: actions/upload-artifact@v3 + with: + name: Opendingux + path: PicoDrive-opendingux*.opk + - name: publish + if: ${{ github.ref_type == 'tag' }} + uses: actions/upload-release-asset@v1 + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: PicoDrive-opendingux*.opk + + build-miyoo: + needs: prepare-release + runs-on: ubuntu-latest + permissions: + packages: read + container: miyoocfw/toolchain + steps: + - uses: actions/checkout@v3 + with: + submodules: true + - name: build + run: | + git config --global --add safe.directory /home/picodrive + ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) + CROSS_COMPILE=arm-buildroot-linux-musleabi- ./configure --platform=miyoo + CROSS_COMPILE=arm-buildroot-linux-musleabi- make + mv PicoDrive.zip PicoDrive-miyoo-$ver.zip + - name: artifacts + uses: actions/upload-artifact@v3 + with: + name: Miyoo + path: PicoDrive-miyoo*.zip + - name: publish + if: ${{ github.ref_type == 'tag' }} + uses: actions/upload-release-asset@v1 + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: PicoDrive-miyoo*.zip + + build-retrofw: + needs: prepare-release + runs-on: ubuntu-latest + container: ghcr.io/irixxxx/toolchain-retrofw + steps: + - uses: actions/checkout@v3 + with: + submodules: true + - name: build + run: | + git config --global --add safe.directory $PWD + ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) + CROSS_COMPILE=mipsel-RetroFW-linux-uclibc- ./configure --platform=retrofw + CROSS_COMPILE=mipsel-RetroFW-linux-uclibc- make + mv PicoDrive.opk PicoDrive-retrofw-$ver.opk + - name: artifacts + uses: actions/upload-artifact@v3 + with: + name: RetroFW + path: PicoDrive-retrofw*.opk + - name: publish + if: ${{ github.ref_type == 'tag' }} + uses: actions/upload-release-asset@v1 + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: PicoDrive-retrofw*.opk + From 3167aa9a9446a68458e26c14e5589e4581b15a04 Mon Sep 17 00:00:00 2001 From: kub Date: Mon, 23 Oct 2023 23:13:30 +0200 Subject: [PATCH 08/15] compile fixes for CI --- .gitmodules | 3 ++- Makefile | 7 +++++-- README.md | 8 ++++---- pico/32x/32x.c | 2 +- pico/sound/sound.c | 8 +++++++- pico/sound/ym2612.h | 26 +++++++++----------------- platform/common/helix/Makefile | 10 +++++----- platform/common/mp3_helix.c | 10 ++++++++-- platform/gp2x/code940/Makefile | 25 ++++++++----------------- platform/gp2x/code940/pico940_v3.bin | Bin 0 -> 72196 bytes platform/gp2x/warm_2.4.25.o | Bin 0 -> 10062 bytes platform/gp2x/warm_2.4.26-open2x.o | Bin 0 -> 9493 bytes platform/gp2x/warm_2.6.24.ko | Bin 0 -> 86123 bytes platform/psp/Makefile | 6 ++++++ tools/Makefile | 2 +- 15 files changed, 56 insertions(+), 51 deletions(-) create mode 100755 platform/gp2x/code940/pico940_v3.bin create mode 100644 platform/gp2x/warm_2.4.25.o create mode 100644 platform/gp2x/warm_2.4.26-open2x.o create mode 100644 platform/gp2x/warm_2.6.24.ko diff --git a/.gitmodules b/.gitmodules index 53449e32f..4f610dff6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,9 +7,10 @@ [submodule "pico/sound/emu2413"] path = pico/sound/emu2413 url = https://github.com/digital-sound-antiques/emu2413.git + branch = main [submodule "pico/cd/libchdr"] path = pico/cd/libchdr - url = https://github.com/rtissera/libchdr.git + url = https://github.com/irixxxx/libchdr.git [submodule "platform/common/dr_libs"] path = platform/common/dr_libs url = https://github.com/mackron/dr_libs.git diff --git a/Makefile b/Makefile index d3fe5e3e9..152e01819 100644 --- a/Makefile +++ b/Makefile @@ -231,7 +231,7 @@ OBJS += platform/gp2x/vid_mmsp2.o OBJS += platform/gp2x/vid_pollux.o OBJS += platform/gp2x/warm.o USE_FRONTEND = 1 -PLATFORM_MP3 = 1 +PLATFORM_MP3 ?= 1 endif ifeq "$(PLATFORM)" "psp" CFLAGS += -DUSE_BGR565 -G8 # -DLPRINTF_STDIO -DFW15 @@ -373,6 +373,7 @@ clean: $(RM) $(TARGET) $(OBJS) pico/pico_int_offs.h $(MAKE) -C cpu/cyclone clean $(MAKE) -C cpu/musashi clean + $(MAKE) -C tools clean $(RM) -r .od_data $(TARGET): $(OBJS) @@ -439,7 +440,9 @@ cpu/fame/famec.o: CFLAGS += -Od endif endif -pico/carthw_cfg.c: pico/carthw.cfg +tools/make_carthw_c: + make -C tools make_carthw_c +pico/carthw_cfg.c: pico/carthw.cfg tools/make_carthw_c tools/make_carthw_c $< $@ # preprocessed asm files most probably include the offsets file diff --git a/README.md b/README.md index 688066373..cdfb1da75 100644 --- a/README.md +++ b/README.md @@ -52,14 +52,14 @@ MP3 audio files with CD games. The helix source files are however not supplied due to licensing issues. If you have legally obtained the sources, put them in the platform/common/helix directory. -To compile the helix sources, set CROSS to your cross compiler prefix +To compile the helix sources, set CROSS_COMPILE to your cross compiler prefix (e.g. arm-linux-gnueabi-) and LIBGCC to your cross compiler's libgcc.a (e.g. /usr/lib/gcc-cross/arm-linux-gnueabi/4.7/libgcc.a), and compile with -> make -C platform/common/helix CROSS=$CROSS LIBGCC=$LIBGCC +> make -C platform/common/helix CROSS_COMPILE=$CROSS_COMPILE LIBGCC=$LIBGCC -This will result in a shared library named ${CROSS}helix_mp3.so. Copy this -as libhelix.so to where the PicoDrive binary is on the target device. +This will result in a shared library named ${CROSS_COMPILE}helix_mp3.so. Copy +this as libhelix.so to where the PicoDrive binary is on the target device. Also, the support for helix must be enabled in PicoDrive by compiling with diff --git a/pico/32x/32x.c b/pico/32x/32x.c index d0d26f023..d88b23f05 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -282,7 +282,7 @@ static void p32x_end_blank(void) Pico32x.vdp_regs[0x0a/2] &= ~P32XV_PEN; // no palette access if (!(Pico32x.sh2_regs[0] & 0x80)) { // NB must precede VInt per hw manual, min 4 SH-2 cycles to pass Mars Check - Pico32x.hint_counter = -0x18; + Pico32x.hint_counter = (int)(-1.5*0x10); p32x_schedule_hint(NULL, Pico.t.m68c_aim); } diff --git a/pico/sound/sound.c b/pico/sound/sound.c index f4686c2dd..9c7a92891 100644 --- a/pico/sound/sound.c +++ b/pico/sound/sound.c @@ -120,6 +120,12 @@ static void YM2612_setup_FIR(int inrate, int outrate, int stereo) 0.85, 2, 2*inrate/50, stereo); } +// wrapper for the YM2612UpdateONE macro +static int YM2612UpdateONE(s32 *buffer, int length, int stereo, int is_buf_empty) +{ + return YM2612UpdateOne(buffer, length, stereo, is_buf_empty); +} + // to be called after changing sound rate or chips void PsndRerate(int preserve_state) { @@ -146,7 +152,7 @@ void PsndRerate(int preserve_state) YM2612Init(ym2612_clock, PicoIn.sndRate, ((PicoIn.opt&POPT_DIS_FM_SSGEG) ? 0 : ST_SSG) | ((PicoIn.opt&POPT_EN_FM_DAC) ? ST_DAC : 0)); - PsndFMUpdate = YM2612UpdateOne; + PsndFMUpdate = YM2612UpdateONE; } if (preserve_state) { // feed it back it's own registers, just like after loading state diff --git a/pico/sound/ym2612.h b/pico/sound/ym2612.h index 3e364b7a3..84263b2bd 100644 --- a/pico/sound/ym2612.h +++ b/pico/sound/ym2612.h @@ -179,6 +179,7 @@ void *YM2612GetRegs(void); void YM2612PicoStateSave2(int tat, int tbt); int YM2612PicoStateLoad2(int *tat, int *tbt); +/* NB must be macros for compiling GP2X 940 code */ #ifndef __GP2X__ #define YM2612Init YM2612Init_ #define YM2612ResetChip YM2612ResetChip_ @@ -187,23 +188,14 @@ int YM2612PicoStateLoad2(int *tat, int *tbt); #else /* GP2X specific */ #include -static inline void YM2612Init(int baseclock, int rate, int flags) { - if (PicoIn.opt&POPT_EXT_FM) YM2612Init_940(baseclock, rate, flags); - else YM2612Init_(baseclock, rate, flags); -} - -static inline void YM2612ResetChip(void) { - if (PicoIn.opt&POPT_EXT_FM) YM2612ResetChip_940(); - else YM2612ResetChip_(); -} -static inline int YM2612UpdateOne(s32 *buffer, int length, int stereo, int is_buf_empty) { - return (PicoIn.opt&POPT_EXT_FM) ? YM2612UpdateOne_940(buffer, length, stereo, is_buf_empty) : - YM2612UpdateOne_(buffer, length, stereo, is_buf_empty); -} -static inline void YM2612PicoStateLoad(void) { - if (PicoIn.opt&POPT_EXT_FM) YM2612PicoStateLoad_940(); - else YM2612PicoStateLoad_(); -} +#define YM2612Init(baseclock, rate, flags) \ + (PicoIn.opt & POPT_EXT_FM ? YM2612Init_940 : YM2612Init_)(baseclock, rate, flags) +#define YM2612ResetChip() \ + (PicoIn.opt & POPT_EXT_FM ? YM2612ResetChip_940 : YM2612ResetChip_)() +#define YM2612PicoStateLoad() \ + (PicoIn.opt & POPT_EXT_FM ? YM2612PicoStateLoad_940 : YM2612PicoStateLoad_)() +#define YM2612UpdateOne(buffer, length, sterao, isempty) \ + (PicoIn.opt & POPT_EXT_FM ? YM2612UpdateOne_940 : YM2612UpdateOne_)(buffer, length, stereo, isempty) #endif /* __GP2X__ */ diff --git a/platform/common/helix/Makefile b/platform/common/helix/Makefile index 9fa4c1cc6..9f3f4ef08 100644 --- a/platform/common/helix/Makefile +++ b/platform/common/helix/Makefile @@ -1,9 +1,9 @@ -CROSS ?= arm-linux-gnueabi- +CROSS_COMPILE ?= arm-linux-gnueabi- -CC = $(CROSS)gcc -AS = $(CROSS)as -AR = $(CROSS)ar -TOOLCHAIN = $(notdir $(CROSS)) +CC = $(CROSS_COMPILE)gcc +AS = $(CROSS_COMPILE)as +AR = $(CROSS_COMPILE)ar +TOOLCHAIN = $(notdir $(CROSS_COMPILE)) LIBGCC ?= ${HOME}/opt/open2x/gcc-4.1.1-glibc-2.3.6/lib/gcc/arm-open2x-linux/4.1.1/libgcc.a CFLAGS += -Ipub -O2 -Wall -fstrict-aliasing -ffast-math diff --git a/platform/common/mp3_helix.c b/platform/common/mp3_helix.c index 0e53bf8fc..f3650bf2e 100644 --- a/platform/common/mp3_helix.c +++ b/platform/common/mp3_helix.c @@ -12,10 +12,16 @@ #include #include -#include "helix/pub/mp3dec.h" +/*#include "helix/pub/mp3dec.h"*/ #include "mp3.h" -static HMP3Decoder mp3dec; +#ifndef _MP3DEC_H +typedef void *HMP3Decoder; +#define ERR_MP3_INDATA_UNDERFLOW -1 +#define ERR_MP3_MAINDATA_UNDERFLOW -2 +#endif + +static void *mp3dec; static unsigned char mp3_input_buffer[2 * 1024]; #ifdef __GP2X__ diff --git a/platform/gp2x/code940/Makefile b/platform/gp2x/code940/Makefile index 6968f835a..2535cfdab 100644 --- a/platform/gp2x/code940/Makefile +++ b/platform/gp2x/code940/Makefile @@ -1,15 +1,6 @@ # you may or may not need to change this -#devkit_path ?= $(HOME)/opt/devkitGP2X/ -#lgcc_path = $(devkit_path)lib/gcc/arm-linux/4.0.3/ -#CROSS = $(devkit_path)bin/arm-linux- -#devkit_path ?= $(HOME)/opt/open2x -#lgcc_path = $(devkit_path)/gcc-4.1.1-glibc-2.3.6/lib/gcc/arm-open2x-linux/4.1.1/ -#CROSS ?= $(devkit_path)/gcc-4.1.1-glibc-2.3.6/bin/arm-open2x-linux- -#devkit_path ?= $(HOME)/opt/arm-unknown-linux-gnu -#lgcc_path = $(HOME)/opt/open2x/gcc-4.1.1-glibc-2.3.6/lib/gcc/arm-open2x-linux/4.1.1/ -#CROSS ?= $(devkit_path)/bin/arm-unknown-linux-gnu- lgcc_path = $(HOME)/opt/open2x/gcc-4.1.1-glibc-2.3.6/lib/gcc/arm-open2x-linux/4.1.1/ -CROSS ?= arm-linux-gnueabi- +CROSS_COMPILE ?= arm-none-eabi- # settings #up = 1 @@ -19,11 +10,11 @@ CFLAGS += -I../../common/helix/pub -I../../.. -I. -D__GP2X__ -DARM CFLAGS += -mcpu=arm940t -mtune=arm940t -mabi=apcs-gnu -mfloat-abi=soft -mfpu=fpa LDFLAGS = -static -e code940 -Ttext 0x0 -L$(lgcc_path) -lgcc -GCC = $(CROSS)gcc -STRIP = $(CROSS)strip -AS = $(CROSS)as -LD = $(CROSS)ld -OBJCOPY = $(CROSS)objcopy +GCC = $(CROSS_COMPILE)gcc +STRIP = $(CROSS_COMPILE)strip +AS = $(CROSS_COMPILE)as +LD = $(CROSS_COMPILE)ld +OBJCOPY = $(CROSS_COMPILE)objcopy vpath %.c = ../../common @@ -52,7 +43,7 @@ OBJS940 += 940init.o 940.o 940ym2612.o misc_arm.o mp3_sync.o OBJS940 += uClibc/memset.o uClibc/s_floor.o uClibc/e_pow.o uClibc/e_sqrt.o uClibc/s_fabs.o OBJS940 += uClibc/s_scalbn.o uClibc/s_copysign.o uClibc/k_sin.o uClibc/k_cos.o uClibc/s_sin.o OBJS940 += uClibc/e_rem_pio2.o uClibc/k_rem_pio2.o uClibc/e_log.o uClibc/wrappers.o -LIBHELIX ?= ../../common/helix/$(notdir $(CROSS))helix_mp3.a +LIBHELIX ?= ../../common/helix/$(notdir $(CROSS_COMPILE))helix_mp3.a $(BIN) : code940.elf @echo ">>>" $@ @@ -75,7 +66,7 @@ mp3_sync.o: ../../common/mp3_sync.c $(GCC) $(CFLAGS) -Os -DCODE940 -c $< -o $@ $(LIBHELIX): - @$(MAKE) -C ../../common/helix/ CROSS=$(CROSS) + @$(MAKE) -C ../../common/helix/ CROSS_COMPILE=$(CROSS_COMPILE) up: $(BIN) diff --git a/platform/gp2x/code940/pico940_v3.bin b/platform/gp2x/code940/pico940_v3.bin new file mode 100755 index 0000000000000000000000000000000000000000..d77ac4bc3ecb85ef458d22b3c30a94cd205e045b GIT binary patch literal 72196 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 z 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 literal 0 HcmV?d00001 diff --git a/platform/gp2x/warm_2.4.25.o b/platform/gp2x/warm_2.4.25.o new file mode 100644 index 0000000000000000000000000000000000000000..23a80b8131063bfbc5ceb87f9171d144c62a777d GIT binary patch literal 10062 zcmcJUe{57&cE`_~H^u`D@t7Z}1Mc!5c6LaOc^JbwtclHH0&JY^1e{$ISs9OK9(bDZ z%w%Q^CPl*hNQ015SqrO>h{jJ9S)pB|vfW6_A2f1EsznuDu`SY~Eox`xG2+Kk>S+0c zR#t3WmndyoSM%egg;!oF zl6I=3m}swmRC;R6EU2`-FrV_rcM*N4P{8tazPo@rP1S>YuYSZ*JI&hvnVR}tb-*lm z4w}}bV`gFM4b!R#y;E$Wxuqt3Nl96D{HD@(u&C;uqCz{YZA6QGx+kwHhl?~}TAqSw z{pz+^(DQRk{$*n~Rhn)Ii!i|CG5ay8X_$Wqep7X8acZYmR_#VP8wRucVo7UHgguVuLB=it(- zqYv$PiDPbc1kX%m>4)s?af!Cy)uG#*!OPUk9W)c&!Qg`2=DbQa_3P@ zYhsRBXjl)M+7E83nu7PU-P%gyi#|jSNmue};c&6xX}nWiDXO1+1RFp4+irb?y!eqj z4bSS;%mVvfM0x8Xo{eaybsF_m6QhNXA$Q@~@XS;-ak(({t5Hiaj}?{g9x2YE9`XB^ zH;)mmXCGX;UHShEehB$j^p}c0?|Zj>v}iitUfeez=T5Hc?OgA)>JXDV-@lZ6bFMkh zV<=9pb(tr~XMs9@RO0^aeDF97c<`*RS_Q=L8;m^#_rJycm+*)2XWf?jsg8@5s()^& ztC6eckSh)CFy?;`yXDVgUZ701eqq(D``qI9uWE-1q`gzpF&C#^ylB-(+o@G{U9q9j zlXu#4PT9_hMOA3de@QI=?TW<*J;${?i2hKf+D&UpKa4r&&HEL)Gu4cKw2PJ(@A_F3 zTek{vv+mo_p*V4IjNB)$69Feb7)$VF&#z|`TFiM`4!;V<`yZokNA^I5eoj5!0qeN% zoM;pqmf3#*{=dL`aIaNMCu)m+?NDH8;Ijpa-ih(C!&1K-fB!Y~qg4@gq7X_5C4i!% zOnM3HA)Xmyk$to6|EKK4KfR7hel|XXd0Kz4SXFzF=TJdKz53A%6&KB%ZH|PGB9pqEo3`Y;%e=mEfx9t8RQ_Z&6Ks&39~SUewEq1)^UYC zGVYt^RV+7dU>4 zcuXLUPvMuahBGz9Hj8FrWf}9oFzC{G5#NE8$SKCVAM3X#jq!~9ROa;R6XN~N6XI>^ zdl}=@EL@Vl{QCPP?*z|d%(1|UyeIH$oiu)5+bs;t#a`I*H-~d+kEIE$J9rM{c+Na| z*1AyMs)F65%t7Z{K1EdANS(zXg)G9nX!6jVF?>kQOF8MfcXX9J^EGVFeGQvRzfY1) z_~P#&&zA-ve=}I-HG;|OHFKfx0jBvw6ijTwx<(pG5XHS#D9FPs$wLTv2+Ss`L(x!z zC^||TN+(nNwhDD&lkoqFuL*tYD6J@MDD5bnC|gmwQQUFyy!6zYs#qhN($%B0g#;fYIZD@dRy{dQ_buJKhBHJ@2%^}sj$^`V|^otSE#t15=L4ZfwUtI_`6;_n>$V7oT1Tkf*g zs)|AAbXQKk(NI;agYK`J%65U(<0Zwr$nr~^KGZpJHqJ(lFy9)tU=P*lwb$6!CAJ%Z znbMyzK8)spiLH%1&cg|g>N*@~^?_<$VTdtG{r zBa7FN5XNXP$^goKlu?xPC_JW5qg+6_jFLy0M5*^+E}?i)G!(oO!W^Rkl>I0tQQTu1 zW3}Kzzj$vJzZ)L6H!$zqHjbWk&Yml-2;9f0D+lbl9KJ$4d?RNNG$PFV$-!rO^=HZHsA<{!Zx#bi8LD z>BRe8hdHSqDGkGq?O*#*i2^6^9o$|BsdOwR`W-6W>BYUGeaGH6_u&4Qo#p4-Rc%_v z+>zqH){GRD&Mv!Np`7)7mA^^lz0(8as1+~19fhxRkg-*nzWSgaMmdUd3dNnP0Q$l= z-p-{@;^CaKKdcIrM_tF7gVq}z)%TP&JBsl0ycT%1xEK7!)T)A0|GLzVNc{n+=NO-^ zslLaye80$b|DoJ3#qY%zalaNtqmd%}A5-ZcxQ$ci=-+qg*H^UptBN|O&1si@T}7Lp zRMa_be&*7<sw>-Oxh*zJGwt=^M(!jOL5`9`gZ&2Di*CEIC!UR`l8$0i zBsySd(cHc?!VsIXZYUYw6*pq&nL9|Pi1ry->MB=e<8M!g?dT%eY$_U$bYJO5>K^lh$NtJ|0KaqiiuubtDlAKn|7~9*V|FkV8%kijM6wvV zgXws}h}nZb7T>kY$lzsYn?kQOX_5X^CKpfc=G^a%WUy_uK*oZUBwsSoBdWezxZIb%3S%`k12yA&pBq^!xvJzhpUxhqA@<*NQ{ zmYVTacuv?se7!$QV1`dL;rEVx@x1k6qvBl7H)a_W_ykX1mll=x!kl+*&vw|F)1Qcp z&y#(%!`CPH#yFSbkLRS@pKmGl574ncHh28-I>G)Of0Ofx+|TFu+bVWWSFr_9xGwg= z*Y{93PPd(V_&fe~z{Y8VTVj9D@r_(gT`gqC7grsFU9Z?M96P4-46JX%^QO_+T-<*X zh5HSla8BI*&OA%>W0%75hb5I12x*}y{6ct5cuUBEu)R;{2R+zm282P;^KTNi{}=Vj6RV9WjjO!!*}a-4NclzO2iN7yUu6AlOy zLf&t2yGz3B!o2X7@UHN_@PROZ7tie*gnhyo6ARUV$UIiqF2}_44vRb@Jj%rLjxsTz zPKf>_^V`@HGFRh0f&Bber2Z<)@Ow>oU6>c%5Z)5r6+QqJ9DqJ#qP-8_6lD#Op9#5+ ziN&N|7dS$IWwRX7Rq`@PRH_(1qj$R7eb-$I|zFAOo!UypF7uvge8 zj0p#X384vc{|}j+m>2l)G8ZzTuNSt7J|yfBeV;HV`u!rG6#1<1oaiqIFN;1ed?*ay zL&*I%2s?#4nTTgV=uTEJ;I&BUSXebKd5ZNcade};{?m!A(~)9zQn}(e}mbK z`7HY2yt2NH3A;{_yF?C&+$&5oH{<&v^+!O?&r#v1aEuv593r1&Vy!sEd=dKtkxxtg z8R1#sIpHNx!6xqt6Y*aY{dM6a>k;<@Vc@BPVe%{M(QIwJ>JhDfv!uncY8AmoVU#gxKpQh<7Krx%4*sRna>3i(*7?X2ay&{s-hZlSe;sm@%l_XXce&)*7<R?1Pi=U?iSwj?(UEv?c7ExHMBZTt0{iKYF-9yNz5pz1u!bq*yA9 zW5;l`KWv|t@X3jD6E>2u86lg)Nf^mVh^rYNBC^PA;nPhPqI@D2PNlQqy#py6`ngr* zh~uefE+MxwM|9z2WY8#UBRJf1iDi#``cKM2GW^$GWX_8!^a|V`sHLv;$0_c ztTYDS#YfV!feM8t4=>+&8B{1&vsm~HPvL-VGMQX zhsv1#nvB`tgU#3Xqe38atbzTlQa>mz8bh6y=hm64%gR)G^O48i8Z_Uuss_NSXJt+ zqBeTm^4A}^@k6E7v299s=R`^AKX=CTBaTUZ*VaR(KNd0@0({m@|A1~Hq;J}bIwzVS zRodhxt1&Q9>JFW}Su=XF#ClZNwEcZ%aUo*wlXxPQUz>;EH_Suu|ConrnFq#QQ(5~H z^ig|kyZx-DK4vVzr~Kh6tgRjPAq_s*var#Y2LoURboz+(!v0lZJ#o#<&3j*;#d&9* z;N+Q7J7d3O?1n$&LtJ0C{|9aMXjsd5Mp&_~3pO^)t;X0ysc|FY_fbiO$4gw_oJ-7e zabdXd^J7YV%>F17b8nXCK45;}%zF)DRXbWJUPFJhzV|Jy_6_?rP5na^+YS4$R(IIH zL!V~XU%~wU()JhMv(%(%UuXWw6V|NSMgOmZ^?!52uj=h0`Z(M1nazH1y9H zC;sXmktbB8R1HKy?gx~bf!u@?AnYsi{D0}knqWV<-`k%@ybyc;_c^vB)-xo=_8s(- z^-`w8mHX`}TTOmca`)UNHBkyE*b3t%@7_C&a@u6Cg?*--MIKc+Sqe;^#9AxwKkVIG zW3WGowas>#!iBm0cu?#K>4!Vc^C%OC&+Qxax$&&PyOaILcsLGS$}$hf8pIyqSo!Xw zug3XSD1}g}AcSPakY%9pQUdQ{C2IW1nj39SgZvm+i(qh@Sbs>Gu_L->S{nNcH{jX3Eky579d|cY~172ebr6&r>M8?)h0{xfxT7M zf?&Vx!#fS%6@LJES%!IM@E&Pt!8%)I7HPY)upFB@y~?_dXWGKj&f=CT>u=l5;`*o??XV9{8~%se*iuo)C)&epv{(53s>-QBSz3Ri>dQ7RX$Rf|PYpbOGE%LN|i#(O}K1#oe1=_o^JcnEA%kx^T`t7%U zsd754E8mXm30Fid`Adl)`60wLm%{J&>J{U69=nd`s1F$XUo`$TZ{* zB!F{b5Yhr^gS10>Aia=2NIzr{G6FdP8Hb#LoQ9Z?vygL;^AHXF3!r~k(>CIAYkYz8 zUcMDt5xTonk#=>h5D@DVt!4; zfoB}PLz}~gON`5@?uk+hp2z#JUss_lzDFlmHhdI$-!GqO^zo7keOThT_BTF!%k`J7 zB=T_128I99ZQ6UPP1|^U)cTLQQA_LYalU(+%Gbw~@O6A~yaFNIJC&a#Zt?HW7>3TLh}W~^r?@)Y1(zxuHK*81wZ z+Ugw^?9b_;*R9*&;@K5gdu9I*#gBFz|9^>}{r*l}^SP-J441qdDe^8@X6Ek;y00sTVhF z-==4>>6nqrrL%g@$nHzvS*awD${8VXm%*F&&Up>VMr+TwvkO4Nm_EOVpT_H z$Er2U(-|YRil0`MGx92yG@@A}uDaH|v>$D((_3S$F?}GBZ_6#yTXXupL^iLthS!cP z=O4YTHLho(dyU*OjO$Tl_MnHE!2`KRmg|(ZFj761j%IU)o{tVBjrC3m=MTfy<;|BH ziYAjz+YjZM%acg$izXBCXx`BGClJ$NRE@Ev^h8dNM^k%^YrqK(ni;Z0*62 zF)}`H$i@Z}c_Wq|&Kj^fQ}}~uHW5wbskX+$wQ9SuFTrT8)59aJD77&f8#MG-{y+vr z$|iLH6O&3S@eQXEdlE(*HRRApPq{!Y@$Os`t}TkGjU}S_#J)uSfZM+0PbN}^?k%+S z8|o3;H`XJ*uh)~x8%f4tD3dgXj8s0IMbj}%v@^vDYeMyG+Nidr;YlZ>`f~l1tbv6Y zO&Tbswnel1jAT-+U%y_h`FadFWHlE}Du|40v=~dPTLO?usg1k#u z4_OWAS}p5lC>CerODt<}#c^lqXg7O+ zW#;z9aH`xy2dtYnZd|9gZGP>IW%_DtM2xE=cVGz19?WOU9CV+uMzSMsjO0}ZpR#Ez z>!|9$uoJ00X&4;?%dJF39cAx8E~h#W4o)I_`t8!w$cE3c!Y9*7jQ2Gj#3i}klRtuv zQ`?tYenPbjqoHaEHTwZh=7?|d`Pfv~YYe1_)gTZw1Z z@7C9k`VK;OlUv_97?^LBIHr*=$%-T~AN^Z}uB(f8R-VK>On(mHc)a;MVR8D$eEkr& z40YCr->q}W^|2YZE;?U>;V@0Pqw`h!f}KkjGec>J4+CIkHKx1 zG1Z`OUP;ac$vsb=5}qY{aGnzVny^6r8Gi4Ieox4AAItOXNA?Q`h2uh=`{@5%$n&4J zL8&ju*Oa<0_GS!P>n@)KnIC6ir$3z}^xZ<93E7{F=m&+zg=0dV6Q=(rZQGY@7>%s>@2A%cQ2tz`iuW0WT@+?I?F3by$3&(|~@S<>1cvIMd31>Z> zML#e4CDE@6r^roMhoVoDsP7BWza&vlfy73;F7`V@z98A}0ErJ$jp)rn9rWRa z(LzGngzdsG34f<>t=PMS-NGJW9AtZE$yb%SD7-B8tHOfV?+b&t0APMy*e&cQQD0p2 zyy!XPU)B;Hp%Fwq|*p*ITKNgQH2#or_LEu!~{z6)ghb_?U=7Tmp%ew-6X9I7%T z)>>XTLZaM3;i&Ma@VM|4sBOi2j70y=iT%8Al6LfeN>~uy6t>~uLw~n$moP6J6P^=J z3K1En-}w9}AAXpi>&mxTsYN8}(}it9;E~Dy&8@2 z;5^B%@G|uzzth`!gP)t*ll)xtp5#{umM8gfTEr0NQb7HF7ROt{TfTtD|Rlk4aFGP!>4Jtq49yZq?<<@#WJFL?5EkIaZ3LjDHNg5vLw zCD0Et7)bO#FaGaAugCh?1l?U<3*qPQ12?h!TP%o=en=75aZdpYpU{<#}Z>e*^ShunxlU zI2R_7p=cu25tC=<(j}5eCGrm$j1d?jk@B5PMD8Q!4G&*JmP_tQXL70~URDz6SUy>P zRl(0O;(&5)QMboo}-xm-;RXWSxe zC7Cmfw-tlvTFX~R5ndr-K)6CeHBsC|Mq=sAfk-|b8OCj|w>jrp6aC?p7BfZSSxi%8 z|G>P(?Nh>Ql5%c$AMNs#DwlC1kjW-e`M2i_eyt~Ny9|~r2+t)pjmFTsxQU&wqFlA7 z#cZUap9$PkzZ1bdTU-rAN3bL_sjSKxL+O2nH)zb{^l#5Y@!OM450xXB!%bk)Kt;F} j#@Z5fe#yB}l=$S61E?sLPUZ5ExRH! literal 0 HcmV?d00001 diff --git a/platform/gp2x/warm_2.6.24.ko b/platform/gp2x/warm_2.6.24.ko new file mode 100644 index 0000000000000000000000000000000000000000..d2b8dc4df48baecade0fbf35c09ee5402fe9f6a1 GIT binary patch literal 86123 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 literal 0 HcmV?d00001 diff --git a/platform/psp/Makefile b/platform/psp/Makefile index ee6ed25fa..6231d1eaf 100644 --- a/platform/psp/Makefile +++ b/platform/psp/Makefile @@ -6,6 +6,12 @@ $(error need VER) endif endif +../../tools/textfilter: ../../tools/textfilter.c + make -C ../../tools/ textfilter + +readme.txt: ../../tools/textfilter ../base_readme.txt ../../ChangeLog + ../../tools/textfilter ../base_readme.txt $@ PSP + # ? rel: ../../EBOOT.PBP readme.txt ../game_def.cfg mkdir -p PicoDrive/skin/ diff --git a/tools/Makefile b/tools/Makefile index b20bc20f2..77fd273f2 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,4 +1,4 @@ -TARGETS = amalgamate textfilter +TARGETS = amalgamate textfilter make_carthw_c HOSTCC ?= cc all: From 3a6b0cc00440311b1e00d396502545b99edfce87 Mon Sep 17 00:00:00 2001 From: kub Date: Wed, 25 Oct 2023 22:33:14 +0200 Subject: [PATCH 09/15] revisit release script --- README.md | 15 +++---- tools/release.sh | 109 ++++++++++++++++++++++++++--------------------- 2 files changed, 65 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index cdfb1da75..dd5e3604d 100644 --- a/README.md +++ b/README.md @@ -19,21 +19,16 @@ Currently the main development happens in the ### compiling For platforms for which release builds are supplied the most easy way is to -use the release script in tools/release.sh. The script requires toolchains -to be installed locally, depending on the platform to build. See the release -script for details. To make a platform release build use +use the release script in tools/release.sh. See the release script for details. +To make a platform build use > tools/release.sh [version] [platforms...] -This will deliver a zip files for each platform in a the release-[version] -directory. - -A list of platforms for which this is possible can be obtained with - -> configure --help +This will deliver a file for each platform in a the release-[version] directory. +A list of platforms is in the release script. If you want to build an executable for a unixoid platform not listed in the -platform list, just use +platform list, try using > configure --platform=generic diff --git a/tools/release.sh b/tools/release.sh index 3731ef9f0..57487ac62 100755 --- a/tools/release.sh +++ b/tools/release.sh @@ -5,18 +5,15 @@ # creates builds for the supported platforms in the release directory # # usage: release.sh [platform...] -# platforms: gph dingux retrofw gcw0 rg350 psp +# platforms: gph dingux retrofw gcw0 rg350 miyoo psp pandora # -# expects toolchains to be installed in $HOME/opt: -# gph: arm-open2x-linux; arm-none-eabi 4.7 (from launchpad) -# needs additional libpng, ATM in src/gp2x/armroot/lib -# dingux: opendingux-toolchain (the old 2012 version) -# retrofw: mipsel-linux-uclibc (the retrofw toolchain) -# gcw0: gcw0-toolchain; mips-toolchain (buildroot, newer gcc) -# rg350: rg350-toolchain; mips-toolchain (buildroot, newer gcc) -# miyoo: miyoo -# psp: pspdev -# additionally needed libs for toolchains in $HOME/opt/lib and $HOME/opt/lib64 +# expects toolchains to be installed in these docker containers: +# gph: ghcr.io/irixxxx/toolchain-gp2x +# dingux: ghcr.io/irixxxx/toolchain-dingux +# retrofw: ghcr.io/irixxxx/toolchain-retrofw +# gcw0, rg350: ghcr.io/irixxxx/toolchain-opendingux +# miyoo: miyoocfw/toolchain +# psp: ghcr.io/pspdev/pspdev trap "exit" ERR @@ -24,76 +21,90 @@ rel=$1 mkdir -p release-$rel shift; plat=" $* " -[ -z "$plat" ] && plat=" gph dingux retrofw gcw0 rg350 psp " +[ -z "$(echo $plat|tr -d ' ')" ] && plat=" gph dingux retrofw gcw0 rg350 miyoo psp " -[ -n "$LD_LIBRARY_PATH" ] && LD_LIBRARY_PATH=$LD_LIBRARY_PATH: -LD_LIBRARY_PATH=${LD_LIBRARY_PATH}/usr/i686-linux-gnu/lib:$HOME/opt/lib -LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/x86_64-linux-gnu/lib:$HOME/opt/lib64 -export LD_LIBRARY_PATH [ -z "${plat##* gph *}" ] && { # GPH devices: gp2x, wiz, caanoo, with ubuntu arm gcc 4.7 -# NB: -msoft-float uses the fpu setting for determining the parameter passing; -# default upto gcc 4.7 was -mfpu=fpa, which has been removed in gcc 4.8, so -# nothing newer than gcc 4.7 can be used here :-/ -# NB: the arm-none-eabi toolchain is available for gcc 4.7, but it creates bad -# ELF files for linux. The -Wl,-Ttext-segment=... below seems to fix this -TC=$HOME/opt/open2x/gcc-4.1.1-glibc-2.3.6 PATH=$HOME/opt/gcc-arm-none-eabi-4_7-2014q2/bin:$PATH CROSS_COMPILE=arm-none-eabi- CFLAGS="-I$TC/arm-open2x-linux/include -I$HOME/src/gp2x/armroot/include -U_FORTIFY_SOURCE -D__linux__" LDFLAGS="-B$TC/lib/gcc/arm-open2x-linux/4.1.1 -B$TC/arm-open2x-linux/lib -L$TC/arm-open2x-linux/lib -L$HOME/src/gp2x/armroot/lib -Wl,-Ttext-segment=0x10100" ./configure --platform=gp2x -PATH=$HOME/opt/gcc-arm-none-eabi-4_7-2014q2/bin:$PATH make clean all -PATH=$HOME/opt/gcc-arm-none-eabi-4_7-2014q2/bin:$PATH make -C platform/gp2x rel VER=$rel +docker pull ghcr.io/irixxxx/toolchain-gp2x +echo " git config --global --add safe.directory /home/picodrive &&\ + CROSS_COMPILE=arm-none-eabi- ./configure --platform=gp2x &&\ + make clean all &&\ + make -C platform/gp2x rel VER=$rel "\ + | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-gp2x sh && mv PicoDrive_$rel.zip release-$rel/PicoDrive-gph_$rel.zip } [ -z "${plat##* dingux *}" ] && { # dingux: dingoo a320, ritmix rzx-50, JZ4755 or older (mips32r1 w/o fpu) # NB works for legacy dingux and possibly opendingux before gcw0 -TC=$HOME/opt/opendingux-toolchain PATH=$TC/usr/bin:$PATH CROSS_COMPILE=mipsel-linux- CFLAGS="-I $TC/usr/include -I $TC/usr/include/SDL -Wno-unused-result -mabicalls" LDFLAGS="--sysroot $TC" ./configure --platform=dingux -TC=$HOME/opt/opendingux-toolchain PATH=$TC/usr/bin:$PATH make clean all +docker pull ghcr.io/irixxxx/toolchain-dingux +echo " git config --global --add safe.directory /home/picodrive &&\ + CROSS_COMPILE=mipsel-linux- ./configure --platform=dingux &&\ + CROSS_COMPILE=mipsel-linux- make clean all "\ + | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-dingux sh && mv PicoDrive-dge.zip release-$rel/PicoDrive-dge_$rel.zip } [ -z "${plat##* retrofw *}" ] && { # retrofw: rs-97 and similar, JZ4760 (mips32r1 with fpu) -TC=$HOME/opt/mipsel-linux-uclibc PATH=$TC/bin:$PATH CROSS_COMPILE=mipsel-linux- CFLAGS="-I $TC/mipsel-buildroot-linux-uclibc/sysroot/usr/include -I $TC/mipsel-buildroot-linux-uclibc/sysroot/usr/include/SDL -Wno-unused-result" LDFLAGS="--sysroot $TC/mipsel-buildroot-linux-uclibc/sysroot" ./configure --platform=retrofw -TC=$HOME/opt/mipsel-linux-uclibc PATH=$TC/bin:$PATH make clean all +docker pull ghcr.io/irixxxx/toolchain-retrofw +echo " git config --global --add safe.directory /home/picodrive &&\ + CROSS_COMPILE=mipsel-RetroFW-linux-uclibc- ./configure --platform=retrofw &&\ + CROSS_COMPILE=mipsel-RetroFW-linux-uclibc- make clean all "\ + | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-retrofw sh && mv PicoDrive.opk release-$rel/PicoDrive-retrofw_$rel.opk } [ -z "${plat##* gcw0 *}" ] && { -# gcw0: JZ4770 (mips32r2 with fpu), swapped X/Y buttons, SDK toolchain -#TC=$HOME/opt/gcw0-toolchain PATH=$TC/usr/bin:$PATH CROSS_COMPILE=mipsel-linux- TS=$TC/usr/mipsel-gcw0-linux-uclibc/sysroot CFLAGS="-I$TS/usr/include -I$TS/usr/include/SDL" LDFLAGS="--sysroot $TS" ./configure --platform=gcw0 -#TC=$HOME/opt/gcw0-toolchain PATH=$TC/usr/bin:$PATH make clean all - -# gcw0: JZ4770 (mips32r2 with fpu), swapped X/Y buttons, newer generic gcc -TC=$HOME/opt/gcw0-toolchain PATH=$HOME/opt/mips-toolchain/bin:$PATH CROSS_COMPILE=mipsel-linux- TS=$TC/usr/mipsel-gcw0-linux-uclibc/sysroot CFLAGS="-I$TS/usr/include -I$TS/usr/include/SDL -mabicalls" LDFLAGS="--sysroot $TS -Wl,--dynamic-linker=/lib/ld-uClibc.so.0" ./configure --platform=gcw0 -PATH=$HOME/opt/mips-toolchain/usr/bin:$PATH make clean all +# gcw0: JZ4770 (mips32r2 with fpu), swapped X/Y buttons +docker pull ghcr.io/irixxxx/toolchain-opendingux +echo " git config --global --add safe.directory /home/picodrive &&\ + CROSS_COMPILE=mipsel-linux- ./configure --platform=gcw0 &&\ + CROSS_COMPILE=mipsel-linux- make clean all "\ + | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-opendingux sh && mv PicoDrive.opk release-$rel/PicoDrive-gcw0_$rel.opk } [ -z "${plat##* rg350 *}" ] && { -# rg350: JZ4770, SDK toolchain -#TC=$HOME/opt/rg350-toolchain PATH=$TC/usr/bin:$PATH CROSS_COMPILE=mipsel-linux- TS=$TC/usr/mipsel-gcw0-linux-uclibc/sysroot CFLAGS="-I$TS/usr/include -I$TS/usr/include/SDL" LDFLAGS="--sysroot $TS" ./configure --platform=rg350 -#TC=$HOME/opt/rg350-toolchain PATH=$TC/usr/bin:$PATH make clean all - -# rg350, gkd350h etc: JZ4770 or newer, newer generic gcc -# NB this may or may not work on the newer opendingux beta. undefine frame_info -# symbols to force linking them from libgcc.a - they might not be in the libc -TC=$HOME/opt/rg350-toolchain PATH=$HOME/opt/mips-toolchain/bin:$PATH CROSS_COMPILE=mipsel-linux- TS=$TC/usr/mipsel-gcw0-linux-uclibc/sysroot CFLAGS="-I$TS/usr/include -I$TS/usr/include/SDL -mabicalls" LDFLAGS="--sysroot $TS -Wl,--dynamic-linker=/lib/ld-uClibc.so.0 -u__register_frame_info -u__deregister_frame_info" ./configure --platform=opendingux -PATH=$HOME/opt/mips-toolchain/usr/bin:$PATH make clean all +# rg350, gkd350h etc: JZ4770 or newer +docker pull ghcr.io/irixxxx/toolchain-opendingux +echo " git config --global --add safe.directory /home/picodrive &&\ + CROSS_COMPILE=mipsel-linux- ./configure --platform=opendingux &&\ + CROSS_COMPILE=mipsel-linux- make clean all "\ + | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-opendingux sh && mv PicoDrive.opk release-$rel/PicoDrive-opendingux_$rel.opk } [ -z "${plat##* miyoo *}" ] && { # miyoo: BittBoy >=v1, PocketGo, Powkiddy [QV]90/Q20 (Allwinner F1C100s, ARM926) -TC=$HOME/opt/miyoo PATH=$TC/bin:$PATH CROSS_COMPILE=arm-miyoo-linux-uclibcgnueabi- CFLAGS="-I $TC/arm-miyoo-linux-uclibcgnueabi/sysroot/usr/include -I $TC/arm-miyoo-linux-uclibcgnueabi/sysroot/usr/include/SDL -Wno-unused-result" LDFLAGS="--sysroot $TC/arm-miyoo-linux-uclibcgnueabi/sysroot" ./configure --platform=miyoo -TC=$HOME/opt/miyoo PATH=$TC/bin:$PATH make clean all +docker pull miyoocfw/toolchain +echo " git config --global --add safe.directory /home/picodrive &&\ + CROSS_COMPILE=arm-buildroot-linux-musleabi- ./configure --platform=miyoo &&\ + CROSS_COMPILE=arm-buildroot-linux-musleabi- make clean all "\ + | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm miyoocfw/toolchain sh && mv PicoDrive.zip release-$rel/PicoDrive-miyoo_$rel.zip } [ -z "${plat##* psp *}" ] && { # psp (experimental), pspdev SDK toolchain -TC=$HOME/opt/pspdev PATH=$TC/bin:$PATH CROSS_COMPILE=psp- CFLAGS="-I$TC/psp/sdk/include -D_POSIX_C_SOURCE=199506L" LDFLAGS="-L$TC/psp/sdk/lib" ./configure --platform=psp -TC=$HOME/opt/pspdev PATH=$TC/bin:$PATH make clean all -make -C platform/psp rel VER=$rel +docker pull --platform=linux/amd64 ghcr.io/pspdev/pspdev +echo " apk add git gcc g++ zip &&\ + git config --global --add safe.directory /home/picodrive &&\ + CROSS_COMPILE=psp- ./configure --platform=psp &&\ + CROSS_COMPILE=psp- make clean all &&\ + make -C platform/psp rel VER=$rel "\ + | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/pspdev/pspdev sh && mv PicoDrive_psp_$rel.zip release-$rel/PicoDrive-psp_$rel.zip } + +[ -z "${plat##* pandora *}" ] && { +# pandora (untested), openpandora SDK toolchain +docker pull ghcr.io/irixxxx/toolchain-pandora +echo " git config --global --add safe.directory /home/picodrive &&\ + ./configure --platform=pandora &&\ + make clean all &&\ + \${CROSS_COMPILE}strip -o PicoDrive-pandora-$rel PicoDrive"\ + | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-pandora sh && +mv PicoDrive-pandora-$rel release-$rel/ +} From ec0357587efc118db56bed905a56aef4e1e53a3c Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 26 Oct 2023 23:10:17 +0200 Subject: [PATCH 10/15] build, cleanup after toolchain container changes --- .github/workflows/ci.yml | 36 +++++++++++++++++++----------------- tools/release.sh | 35 ++++++++++++++++++----------------- 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e22d343e9..5db92205e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: - name: configure run: DUMP_CONFIG_LOG=1 ./configure - name: make - run: make + run: make -j2 build-libretro: runs-on: ubuntu-latest @@ -35,7 +35,7 @@ jobs: with: submodules: true - name: make - run: LDFLAGS=-Wl,--no-undefined make -f Makefile.libretro + run: LDFLAGS=-Wl,--no-undefined make -j2 -f Makefile.libretro build-gp2x: @@ -52,8 +52,8 @@ jobs: run: | git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) - CROSS_COMPILE=arm-none-eabi- ./configure --platform=gp2x - make PLATFORM_MP3=0 + ./configure --platform=gp2x + make -j2 PLATFORM_MP3=0 make -C platform/gp2x rel VER=$ver mv PicoDrive_$ver.zip PicoDrive-gph_$ver.zip - name: artifacts @@ -81,7 +81,7 @@ jobs: git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=pandora - make + make -j2 mv PicoDrive PicoDrive-pandora ${CROSS_COMPILE}strip PicoDrive-pandora - name: artifacts @@ -109,10 +109,11 @@ jobs: submodules: true - name: build run: | + export CROSS_COMPILE=psp- git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) - CROSS_COMPILE=psp- ./configure --platform=psp - CROSS_COMPILE=psp- make + ./configure --platform=psp + make -j2 make -C platform/psp rel VER=$ver - name: artifacts uses: actions/upload-artifact@v3 @@ -141,8 +142,8 @@ jobs: run: | git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) - CROSS_COMPILE=mipsel-linux- ./configure --platform=dingux - CROSS_COMPILE=mipsel-linux- make + ./configure --platform=dingux + make -j2 mv PicoDrive-dge.zip PicoDrive-dge-$ver.zip - name: artifacts uses: actions/upload-artifact@v3 @@ -168,8 +169,8 @@ jobs: run: | git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) - CROSS_COMPILE=mipsel-linux- ./configure --platform=gcw0 - CROSS_COMPILE=mipsel-linux- make + ./configure --platform=gcw0 + make -j2 mv PicoDrive.opk PicoDrive-gcw0-$ver.opk - name: artifacts uses: actions/upload-artifact@v3 @@ -195,8 +196,8 @@ jobs: run: | git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) - CROSS_COMPILE=mipsel-linux- ./configure --platform=opendingux - CROSS_COMPILE=mipsel-linux- make + ./configure --platform=opendingux + make -j2 mv PicoDrive.opk PicoDrive-opendingux-$ver.opk - name: artifacts uses: actions/upload-artifact@v3 @@ -222,10 +223,11 @@ jobs: submodules: true - name: build run: | + export CROSS_COMPILE=arm-buildroot-linux-musleabi- git config --global --add safe.directory /home/picodrive ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) - CROSS_COMPILE=arm-buildroot-linux-musleabi- ./configure --platform=miyoo - CROSS_COMPILE=arm-buildroot-linux-musleabi- make + ./configure --platform=miyoo + make -j2 mv PicoDrive.zip PicoDrive-miyoo-$ver.zip - name: artifacts uses: actions/upload-artifact@v3 @@ -251,8 +253,8 @@ jobs: run: | git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) - CROSS_COMPILE=mipsel-RetroFW-linux-uclibc- ./configure --platform=retrofw - CROSS_COMPILE=mipsel-RetroFW-linux-uclibc- make + ./configure --platform=retrofw + make -j2 mv PicoDrive.opk PicoDrive-retrofw-$ver.opk - name: artifacts uses: actions/upload-artifact@v3 diff --git a/tools/release.sh b/tools/release.sh index 57487ac62..0e071eaaa 100755 --- a/tools/release.sh +++ b/tools/release.sh @@ -28,8 +28,8 @@ shift; plat=" $* " # GPH devices: gp2x, wiz, caanoo, with ubuntu arm gcc 4.7 docker pull ghcr.io/irixxxx/toolchain-gp2x echo " git config --global --add safe.directory /home/picodrive &&\ - CROSS_COMPILE=arm-none-eabi- ./configure --platform=gp2x &&\ - make clean all &&\ + ./configure --platform=gp2x &&\ + make clean && make -j2 all &&\ make -C platform/gp2x rel VER=$rel "\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-gp2x sh && mv PicoDrive_$rel.zip release-$rel/PicoDrive-gph_$rel.zip @@ -40,8 +40,8 @@ mv PicoDrive_$rel.zip release-$rel/PicoDrive-gph_$rel.zip # NB works for legacy dingux and possibly opendingux before gcw0 docker pull ghcr.io/irixxxx/toolchain-dingux echo " git config --global --add safe.directory /home/picodrive &&\ - CROSS_COMPILE=mipsel-linux- ./configure --platform=dingux &&\ - CROSS_COMPILE=mipsel-linux- make clean all "\ + ./configure --platform=dingux &&\ + make clean && make -j2 all "\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-dingux sh && mv PicoDrive-dge.zip release-$rel/PicoDrive-dge_$rel.zip } @@ -50,8 +50,8 @@ mv PicoDrive-dge.zip release-$rel/PicoDrive-dge_$rel.zip # retrofw: rs-97 and similar, JZ4760 (mips32r1 with fpu) docker pull ghcr.io/irixxxx/toolchain-retrofw echo " git config --global --add safe.directory /home/picodrive &&\ - CROSS_COMPILE=mipsel-RetroFW-linux-uclibc- ./configure --platform=retrofw &&\ - CROSS_COMPILE=mipsel-RetroFW-linux-uclibc- make clean all "\ + ./configure --platform=retrofw &&\ + make clean && make -j2 all "\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-retrofw sh && mv PicoDrive.opk release-$rel/PicoDrive-retrofw_$rel.opk } @@ -60,8 +60,8 @@ mv PicoDrive.opk release-$rel/PicoDrive-retrofw_$rel.opk # gcw0: JZ4770 (mips32r2 with fpu), swapped X/Y buttons docker pull ghcr.io/irixxxx/toolchain-opendingux echo " git config --global --add safe.directory /home/picodrive &&\ - CROSS_COMPILE=mipsel-linux- ./configure --platform=gcw0 &&\ - CROSS_COMPILE=mipsel-linux- make clean all "\ + ./configure --platform=gcw0 &&\ + make clean && make -j2 all "\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-opendingux sh && mv PicoDrive.opk release-$rel/PicoDrive-gcw0_$rel.opk } @@ -70,8 +70,8 @@ mv PicoDrive.opk release-$rel/PicoDrive-gcw0_$rel.opk # rg350, gkd350h etc: JZ4770 or newer docker pull ghcr.io/irixxxx/toolchain-opendingux echo " git config --global --add safe.directory /home/picodrive &&\ - CROSS_COMPILE=mipsel-linux- ./configure --platform=opendingux &&\ - CROSS_COMPILE=mipsel-linux- make clean all "\ + ./configure --platform=opendingux &&\ + make clean && make -j2 all "\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-opendingux sh && mv PicoDrive.opk release-$rel/PicoDrive-opendingux_$rel.opk } @@ -79,9 +79,10 @@ mv PicoDrive.opk release-$rel/PicoDrive-opendingux_$rel.opk [ -z "${plat##* miyoo *}" ] && { # miyoo: BittBoy >=v1, PocketGo, Powkiddy [QV]90/Q20 (Allwinner F1C100s, ARM926) docker pull miyoocfw/toolchain -echo " git config --global --add safe.directory /home/picodrive &&\ - CROSS_COMPILE=arm-buildroot-linux-musleabi- ./configure --platform=miyoo &&\ - CROSS_COMPILE=arm-buildroot-linux-musleabi- make clean all "\ +echo " export CROSS_COMPILE=arm-buildroot-linux-musleabi- &&\ + git config --global --add safe.directory /home/picodrive &&\ + ./configure --platform=miyoo &&\ + make clean && make -j2 all "\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm miyoocfw/toolchain sh && mv PicoDrive.zip release-$rel/PicoDrive-miyoo_$rel.zip } @@ -89,10 +90,10 @@ mv PicoDrive.zip release-$rel/PicoDrive-miyoo_$rel.zip [ -z "${plat##* psp *}" ] && { # psp (experimental), pspdev SDK toolchain docker pull --platform=linux/amd64 ghcr.io/pspdev/pspdev -echo " apk add git gcc g++ zip &&\ +echo " apk add git gcc g++ zip && export CROSS_COMPILE=psp- &&\ git config --global --add safe.directory /home/picodrive &&\ - CROSS_COMPILE=psp- ./configure --platform=psp &&\ - CROSS_COMPILE=psp- make clean all &&\ + ./configure --platform=psp &&\ + make clean && make -j2 all &&\ make -C platform/psp rel VER=$rel "\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/pspdev/pspdev sh && mv PicoDrive_psp_$rel.zip release-$rel/PicoDrive-psp_$rel.zip @@ -103,7 +104,7 @@ mv PicoDrive_psp_$rel.zip release-$rel/PicoDrive-psp_$rel.zip docker pull ghcr.io/irixxxx/toolchain-pandora echo " git config --global --add safe.directory /home/picodrive &&\ ./configure --platform=pandora &&\ - make clean all &&\ + make clean && make -j2 all &&\ \${CROSS_COMPILE}strip -o PicoDrive-pandora-$rel PicoDrive"\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-pandora sh && mv PicoDrive-pandora-$rel release-$rel/ From df765ed91bfd29b339ba5ed125e766d4e3758373 Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 26 Oct 2023 23:52:07 +0200 Subject: [PATCH 11/15] core, fix bug in m68k state saving thanks to bnister for pointing this out --- pico/sek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico/sek.c b/pico/sek.c index 77cf73e93..4dd0b4abe 100644 --- a/pico/sek.c +++ b/pico/sek.c @@ -221,7 +221,7 @@ PICO_INTERNAL void SekPackCpu(unsigned char *cpu, int is_sub) *(s16 *)(cpu+0x4e) = SekCycleCntS68k - SekCycleAimS68k; } else { *(u32 *)(cpu+0x50) = Pico.t.m68c_cnt; - *(u32 *)(cpu+0x4e) = Pico.t.m68c_cnt - Pico.t.m68c_aim; + *(s16 *)(cpu+0x4e) = Pico.t.m68c_cnt - Pico.t.m68c_aim; } } From 801daef9aacc027009cc60202f3a22e4ddcf0211 Mon Sep 17 00:00:00 2001 From: kub Date: Wed, 1 Nov 2023 23:56:37 +0200 Subject: [PATCH 12/15] build, remove non-working release actions --- .github/workflows/ci.yml | 68 ---------------------------------------- 1 file changed, 68 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5db92205e..160374c4b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,18 +1,6 @@ name: Picodrive CI on: [push, pull_request] jobs: - prepare-release: - runs-on: ubuntu-latest - steps: - - name: create release - id: create_release - if: ${{ github.ref_type == 'tag' }} - uses: actions/create-release@v1 - with: - prerelease: ${{ contains(github.ref, '-') }} - tag_name: ${{ github.ref }} - release_name: ${{ github.ref }} - build-linux: runs-on: ubuntu-latest steps: @@ -39,7 +27,6 @@ jobs: build-gp2x: - needs: prepare-release runs-on: ubuntu-latest container: ghcr.io/irixxxx/toolchain-gp2x permissions: @@ -61,15 +48,8 @@ jobs: with: name: GP2X path: PicoDrive-gph_*.zip - - name: publish - if: ${{ github.ref_type == 'tag' }} - uses: actions/upload-release-asset@v1 - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: PicoDrive-gph_*.zip build-pandora: - needs: prepare-release runs-on: ubuntu-latest container: ghcr.io/irixxxx/toolchain-pandora steps: @@ -89,15 +69,8 @@ jobs: with: name: Pandora path: PicoDrive-pandora - - name: publish - if: ${{ github.ref_type == 'tag' }} - uses: actions/upload-release-asset@v1 - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: PicoDrive-pandora build-psp: - needs: prepare-release runs-on: ubuntu-latest container: ghcr.io/pspdev/pspdev steps: @@ -120,16 +93,9 @@ jobs: with: name: PSP path: PicoDrive_psp_*.zip - - name: publish - if: ${{ github.ref_type == 'tag' }} - uses: actions/upload-release-asset@v1 - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: PicoDrive_psp_*.zip build-dingux: - needs: prepare-release runs-on: ubuntu-latest permissions: packages: read @@ -150,15 +116,8 @@ jobs: with: name: Dingux path: PicoDrive-dge*.zip - - name: publish - if: ${{ github.ref_type == 'tag' }} - uses: actions/upload-release-asset@v1 - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: PicoDrive-dge*.zip build-gcw0: - needs: prepare-release runs-on: ubuntu-latest container: ghcr.io/irixxxx/toolchain-opendingux steps: @@ -177,15 +136,8 @@ jobs: with: name: GCW0 path: PicoDrive-gcw0*.opk - - name: publish - if: ${{ github.ref_type == 'tag' }} - uses: actions/upload-release-asset@v1 - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: PicoDrive-gcw0*.opk build-opendingux: - needs: prepare-release runs-on: ubuntu-latest container: ghcr.io/irixxxx/toolchain-opendingux steps: @@ -204,15 +156,8 @@ jobs: with: name: Opendingux path: PicoDrive-opendingux*.opk - - name: publish - if: ${{ github.ref_type == 'tag' }} - uses: actions/upload-release-asset@v1 - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: PicoDrive-opendingux*.opk build-miyoo: - needs: prepare-release runs-on: ubuntu-latest permissions: packages: read @@ -234,15 +179,8 @@ jobs: with: name: Miyoo path: PicoDrive-miyoo*.zip - - name: publish - if: ${{ github.ref_type == 'tag' }} - uses: actions/upload-release-asset@v1 - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: PicoDrive-miyoo*.zip build-retrofw: - needs: prepare-release runs-on: ubuntu-latest container: ghcr.io/irixxxx/toolchain-retrofw steps: @@ -261,10 +199,4 @@ jobs: with: name: RetroFW path: PicoDrive-retrofw*.opk - - name: publish - if: ${{ github.ref_type == 'tag' }} - uses: actions/upload-release-asset@v1 - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: PicoDrive-retrofw*.opk From 6bd90c9666dff584d129a660de9d3a054cff13d9 Mon Sep 17 00:00:00 2001 From: zoltanvb <101990835+zoltanvb@users.noreply.github.com> Date: Tue, 7 Nov 2023 19:26:39 +0100 Subject: [PATCH 13/15] Propagate GIT_REVISION to REVISION --- Makefile.libretro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.libretro b/Makefile.libretro index a57a24c73..60e6bfdd1 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -41,7 +41,7 @@ LOW_MEMORY := 0 TARGET_NAME := picodrive LIBM := -lm GIT_REVISION ?= -$(shell git rev-parse --short HEAD || echo ???) - +CFLAGS += -DREVISION=\"$(GIT_REVISION)\" fpic := From 02ed0c7f60c2fc86d35afe3f05a0a8c6ad54747c Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 9 Nov 2023 23:38:38 +0100 Subject: [PATCH 14/15] build, add odbeta --- .github/workflows/ci.yml | 39 +++++++++++++++++++++++++++++++++++ .github/workflows/prepare.yml | 19 +++++++++++++++++ platform/common/version.h | 2 +- tools/release.sh | 24 ++++++++++++++++++++- 4 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/prepare.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 160374c4b..58a35a8fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -200,3 +200,42 @@ jobs: name: RetroFW path: PicoDrive-retrofw*.opk + build-odbeta-gcw0: + runs-on: ubuntu-latest + container: ghcr.io/irixxxx/toolchain-odbeta-gcw0 + steps: + - uses: actions/checkout@v3 + with: + submodules: true + - name: build + run: | + git config --global --add safe.directory $PWD + ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) + ./configure --platform=opendingux + make -j2 + mv PicoDrive.opk PicoDrive-odbeta-gcw0-$ver.opk + - name: artifacts + uses: actions/upload-artifact@v3 + with: + name: ODbeta gcw0 + path: PicoDrive-odbeta-*.opk + + build-odbeta-lepus: + runs-on: ubuntu-latest + container: ghcr.io/irixxxx/toolchain-odbeta-lepus + steps: + - uses: actions/checkout@v3 + with: + submodules: true + - name: build + run: | + git config --global --add safe.directory $PWD + ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) + ./configure --platform=opendingux + make -j2 + mv PicoDrive.opk PicoDrive-odbeta-lepus-$ver.opk + - name: artifacts + uses: actions/upload-artifact@v3 + with: + name: ODbeta lepus + path: PicoDrive-odbeta-*.opk diff --git a/.github/workflows/prepare.yml b/.github/workflows/prepare.yml new file mode 100644 index 000000000..e4f4b552d --- /dev/null +++ b/.github/workflows/prepare.yml @@ -0,0 +1,19 @@ +name: prepare +on: workflow_call + +jobs: + prepare: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + submodules: true + - name: create release + id: create_release + if: ${{ github.ref_type == 'tag' }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + tag=$(echo ${{ github.ref }} | sed 's:refs/tags/::') + gh release create "$tag" --verify-tag -d -t "$tag" -n "$tag" + diff --git a/platform/common/version.h b/platform/common/version.h index 45138ddb5..98ec231a1 100644 --- a/platform/common/version.h +++ b/platform/common/version.h @@ -1 +1 @@ -#define VERSION "1.99" REVISION +#define VERSION "2.00-alpha1" REVISION diff --git a/tools/release.sh b/tools/release.sh index 0e071eaaa..b4e043025 100755 --- a/tools/release.sh +++ b/tools/release.sh @@ -5,7 +5,7 @@ # creates builds for the supported platforms in the release directory # # usage: release.sh [platform...] -# platforms: gph dingux retrofw gcw0 rg350 miyoo psp pandora +# platforms: gph dingux retrofw gcw0 rg350 miyoo psp pandora odbeta-gcw0 odbeta-lepus # # expects toolchains to be installed in these docker containers: # gph: ghcr.io/irixxxx/toolchain-gp2x @@ -14,6 +14,8 @@ # gcw0, rg350: ghcr.io/irixxxx/toolchain-opendingux # miyoo: miyoocfw/toolchain # psp: ghcr.io/pspdev/pspdev +# odbeta-gcw0: ghcr.io/irixxxx/toolchain-odbeta-gcw0 +# odbeta-lepus: ghcr.io/irixxxx/toolchain-odbeta-lepus trap "exit" ERR @@ -109,3 +111,23 @@ echo " git config --global --add safe.directory /home/picodrive &&\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-pandora sh && mv PicoDrive-pandora-$rel release-$rel/ } + +[ -z "${plat##* odbeta-gcw0 *}" ] && { +# gcw0 (untested): JZ4770 (mips32r2 with fpu), swapped X/Y buttons +docker pull ghcr.io/irixxxx/toolchain-odbeta-gcw0 +echo " git config --global --add safe.directory /home/picodrive &&\ + ./configure --platform=gcw0 &&\ + make clean && make -j2 all "\ + | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-odbeta-gcw0 sh && +mv PicoDrive.opk release-$rel/PicoDrive-odbeta-gcw0_$rel.opk +} + +[ -z "${plat##* odbeta-lepus *}" ] && { +# lepus (untested): JZ4760 (mips32r1 with fpu) +docker pull ghcr.io/irixxxx/toolchain-odbeta-lepus +echo " git config --global --add safe.directory /home/picodrive &&\ + ./configure --platform=opendingux &&\ + make clean && make -j2 all "\ + | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-odbeta-lepus sh && +mv PicoDrive.opk release-$rel/PicoDrive-odbeta-lepus_$rel.opk +} From 6101a0052d9a49bc9f5a5f97f1369a41726f25d6 Mon Sep 17 00:00:00 2001 From: LibretroAdmin <105389611+LibretroAdmin@users.noreply.github.com> Date: Sat, 11 Nov 2023 22:09:05 -0800 Subject: [PATCH 15/15] Update .gitlab-ci.yml --- .gitlab-ci.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 47e07c9bf..5bc85b746 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -38,10 +38,6 @@ include: # MacOS ARM 64-bit - project: 'libretro-infrastructure/ci-templates' file: '/osx-arm64.yml' - - # MacOS PPC - - project: 'libretro-infrastructure/ci-templates' - file: '/osx-ppc.yml' ################################## CELLULAR ################################ # Android @@ -153,16 +149,6 @@ libretro-build-osx-arm64: - .libretro-osx-arm64-make-default - .core-defs -# MacOS PPC -libretro-build-osx-ppc: - extends: - - .libretro-osx-ppc-make-default - - .core-defs - variables: - CFLAGS: -mmacosx-version-min=10.4 - CXXFLAGS: -mmacosx-version-min=10.4 - LDFLAGS: -mmacosx-version-min=10.4 - ################################### CELLULAR ################################# # Android ARMv7a android-armeabi-v7a: