From 1aa4a1d97f7263d3975120e4358228c341915be1 Mon Sep 17 00:00:00 2001 From: AShiningRay Date: Sat, 21 Oct 2023 23:18:57 -0300 Subject: [PATCH] Make the max amount of MIDI players a configurable setting Instead of relying on a fixed value for the max, a user setting for that allows more control and fine tuning for specific apps. --- src/javax/microedition/media/Manager.java | 19 +++++---- src/libretro/freej2me_libretro.c | 37 +++++++++++++----- src/libretro/freej2me_libretro.h | 47 ++++++++++++++++++++++- src/org/recompile/freej2me/Config.java | 33 ++++++++++++++-- src/org/recompile/freej2me/FreeJ2ME.java | 3 ++ src/org/recompile/freej2me/Libretro.java | 20 ++++++++++ 6 files changed, 136 insertions(+), 23 deletions(-) diff --git a/src/javax/microedition/media/Manager.java b/src/javax/microedition/media/Manager.java index 07db55ca..3f856816 100644 --- a/src/javax/microedition/media/Manager.java +++ b/src/javax/microedition/media/Manager.java @@ -23,21 +23,20 @@ public final class Manager { - public static final String TONE_DEVICE_LOCATOR = "device://tone"; - public static Player midiChannel[] = new Player[36]; - public static byte midiChannelIndex = 0; + public static Player midiPlayers[] = new Player[32]; /* Default max amount of players in FreeJ2ME's config */ + public static byte midiPlayersIndex = 0; public static Player createPlayer(InputStream stream, String type) throws IOException, MediaException { //System.out.println("Create Player Stream "+type); if(type.equalsIgnoreCase("audio/mid") || type.equalsIgnoreCase("audio/midi") || type.equalsIgnoreCase("sp-midi") || type.equalsIgnoreCase("audio/spmidi")) { - if(midiChannelIndex >= midiChannel.length) { midiChannelIndex = 0; } - if(midiChannel[midiChannelIndex] != null) { midiChannel[midiChannelIndex].deallocate(); } - midiChannel[midiChannelIndex] = new PlatformPlayer(stream, type); - midiChannelIndex++; - return midiChannel[midiChannelIndex-1]; + if(midiPlayersIndex >= midiPlayers.length) { midiPlayersIndex = 0; } + if(midiPlayers[midiPlayersIndex] != null) { midiPlayers[midiPlayersIndex].deallocate(); } + midiPlayers[midiPlayersIndex] = new PlatformPlayer(stream, type); + midiPlayersIndex++; + return midiPlayers[midiPlayersIndex-1]; } else { @@ -69,4 +68,8 @@ public static void playTone(int note, int duration, int volume) System.out.println("Play Tone"); } + public static void updatePlayerNum(byte num) + { + midiPlayers = new Player[num]; + } } diff --git a/src/libretro/freej2me_libretro.c b/src/libretro/freej2me_libretro.c index b9a91f31..05184b4c 100755 --- a/src/libretro/freej2me_libretro.c +++ b/src/libretro/freej2me_libretro.c @@ -144,6 +144,7 @@ int rotateScreen; /* acts as a boolean */ int phoneType; /* 0=standard, 1=nokia, 2=siemens, 3=motorola */ int gameFPS; /* Auto(0), 60, 30, 15 */ int soundEnabled; /* also acts as a boolean */ +int maxMidiPlayers; /* Maximum amount of MIDI Players allowed on FreeJ2ME at any given time */ /* Variables used to manage the pointer speed when controlled from an analog stick */ int pointerXSpeed = 8; int pointerYSpeed = 8; @@ -331,6 +332,21 @@ static void check_variables(bool first_time_startup) else if (!strcmp(var.value, "on")) { soundEnabled = 1; } } + var.key = "freej2me_maxmidiplayers"; + if (Environ(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "32")) { maxMidiPlayers = 32; } + else if (!strcmp(var.value, "1")) { maxMidiPlayers = 1; } + else if (!strcmp(var.value, "2")) { maxMidiPlayers = 2; } + else if (!strcmp(var.value, "4")) { maxMidiPlayers = 4; } + else if (!strcmp(var.value, "8")) { maxMidiPlayers = 8; } + else if (!strcmp(var.value, "16")) { maxMidiPlayers = 16; } + else if (!strcmp(var.value, "32")) { maxMidiPlayers = 32; } + else if (!strcmp(var.value, "48")) { maxMidiPlayers = 48; } + else if (!strcmp(var.value, "64")) { maxMidiPlayers = 64; } + else if (!strcmp(var.value, "96")) { maxMidiPlayers = 96; } + } + var.key = "freej2me_pointertype"; if (Environ(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) @@ -410,7 +426,7 @@ static void check_variables(bool first_time_startup) /* Prepare a string to pass those core options to the Java app */ - snprintf(options_update, PIPE_MAX_LEN, "FJ2ME_LR_OPTS:|%lux%lu|%d|%d|%d|%d", screenRes[0], screenRes[1], rotateScreen, phoneType, gameFPS, soundEnabled); + snprintf(options_update, PIPE_MAX_LEN, "FJ2ME_LR_OPTS:|%lux%lu|%d|%d|%d|%d|%d", screenRes[0], screenRes[1], rotateScreen, phoneType, gameFPS, soundEnabled, maxMidiPlayers); optstrlen = strlen(options_update); /* 0xD = 13, which is the special case where the java app will receive the updated configs */ @@ -470,23 +486,24 @@ void retro_init(void) */ check_variables(true); - char resArg[2][4], rotateArg[2], phoneArg[2], fpsArg[3], soundArg[2]; + char resArg[2][4], rotateArg[2], phoneArg[2], fpsArg[3], soundArg[2], maxMidiArg[3]; sprintf(resArg[0], "%lu", screenRes[0]); /* Libretro config Width */ sprintf(resArg[1], "%lu", screenRes[1]); /* Libretro config Height */ sprintf(rotateArg, "%d", rotateScreen); sprintf(phoneArg, "%d", phoneType); sprintf(fpsArg, "%d", gameFPS); sprintf(soundArg, "%d", soundEnabled); + sprintf(maxMidiArg, "%d", maxMidiPlayers); /* start java process */ char *javapath; Environ(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &javapath); char *outPath = malloc(sizeof(char) * PATH_MAX_LENGTH); fill_pathname_join(outPath, javapath, "freej2me-lr.jar", PATH_MAX_LENGTH); - char *params[] = { "java", "-jar", outPath, resArg[0], resArg[1], rotateArg, phoneArg, fpsArg, soundArg, NULL }; + char *params[] = { "java", "-jar", outPath, resArg[0], resArg[1], rotateArg, phoneArg, fpsArg, soundArg, maxMidiArg, NULL }; - log_fn(RETRO_LOG_INFO, "Passing params: %s | %s | %s | %s | %s | %s \n", *(params+3), - *(params+4), *(params+5), *(params+6), *(params+7), *(params+8)); + log_fn(RETRO_LOG_INFO, "Passing params: %s | %s | %s | %s | %s | %s | %s \n", *(params+3), + *(params+4), *(params+5), *(params+6), *(params+7), *(params+8), *(params+9)); log_fn(RETRO_LOG_INFO, "Preparing to open FreeJ2ME's Java app (make sure freej2me-lr.jar is inside system/).\n"); #ifdef __linux__ @@ -974,8 +991,8 @@ pid_t javaOpen(char *cmd, char **params) log_fn(RETRO_LOG_INFO, "Setting up java app's process and pipes...\n"); log_fn(RETRO_LOG_INFO, "Opening: %s %s %s ...\n", *(params+0), *(params+1), *(params+2)); - log_fn(RETRO_LOG_INFO, "Params: %s | %s | %s | %s | %s | %s \n", *(params+3), - *(params+4), *(params+5), *(params+6), *(params+7), *(params+8)); + log_fn(RETRO_LOG_INFO, "Params: %s | %s | %s | %s | %s | %s | %s \n", *(params+3), + *(params+4), *(params+5), *(params+6), *(params+7), *(params+8), *(params+9)); int fd_stdin = 0; int fd_stdout = 1; @@ -1098,15 +1115,15 @@ void javaOpen(char *cmd, char **params) sprintf(cmdWin, "javaw -jar %s", cmd); log_fn(RETRO_LOG_INFO, "Opening: %s \n", cmd); - for (int i = 3; i <= 8; i++) /* There are 8 cmd arguments for now */ + for (int i = 3; i <= 9; i++) /* There are 8 cmd arguments for now */ { log_fn(RETRO_LOG_INFO, "Processing arg %d: %s \n", i, *(params+i)); sprintf(cmdWin, "%s %s", cmdWin, *(params+i)); } log_fn(RETRO_LOG_INFO, "Creating proc: %s \n", cmdWin); - log_fn(RETRO_LOG_INFO, "Params: %s | %s | %s | %s | %s | %s \n", *(params+3), - *(params+4), *(params+5), *(params+6), *(params+7), *(params+8)); + log_fn(RETRO_LOG_INFO, "Params: %s | %s | %s | %s | %s | %s | %s\n", *(params+3), + *(params+4), *(params+5), *(params+6), *(params+7), *(params+8), *(params+9)); GetStartupInfo(&startInfo); startInfo.dwFlags = STARTF_USESTDHANDLES; diff --git a/src/libretro/freej2me_libretro.h b/src/libretro/freej2me_libretro.h index 3dd33d97..b691b341 100644 --- a/src/libretro/freej2me_libretro.h +++ b/src/libretro/freej2me_libretro.h @@ -150,8 +150,8 @@ struct retro_core_option_v2_definition core_options[] = "freej2me_sound", "Virtual Phone Settings > Virtual Phone Sound", "Virtual Phone Sound", - "Enables or disables the virtual phone's ability to load and play audio samples/tones. Some games require support for codecs not yet implemented, or have issues that can be worked around by disabling audio in FreeJ2ME (ID Software games such as DOOM II RPG having memory leaks with MIDI samples being one example). If a game doesn't run or has issues during longer sessions, try disabling this option.", - "Enables or disables the virtual phone's ability to load and play audio samples/tones. Some games require support for codecs not yet implemented, or have issues that can be worked around by disabling audio in FreeJ2ME (ID Software games such as DOOM II RPG having memory leaks with MIDI samples being one example). If a game doesn't run or has issues during longer sessions, try disabling this option.", + "Enables or disables the virtual phone's ability to load and play audio samples/tones. Some games require support for codecs not yet implemented, or have issues that can be worked around by disabling audio in FreeJ2ME. If a game doesn't run or has issues during longer sessions, try disabling this option.", + "Enables or disables the virtual phone's ability to load and play audio samples/tones. Some games require support for codecs not yet implemented, or have issues that can be worked around by disabling audio in FreeJ2ME. If a game doesn't run or has issues during longer sessions, try disabling this option.", "vphone_settings", { { "on", "On" }, @@ -160,6 +160,27 @@ struct retro_core_option_v2_definition core_options[] = }, "on" }, + { + "freej2me_maxmidiplayers", + "Virtual Phone Settings > Max MIDI Players", + "Max MIDI Players", + "Sets the maximum amount of MIDI files that a given J2ME app can load up and play at any given time. Lower values may reduce memory usage and improve the VM's performance (especially on ID Software games like DOOM II RPG where setting this to 1 vastly reduces memory usage compared to the default), but some games might need bigger values.", + "Sets the maximum amount of MIDI files that a given J2ME app can load up and play at any given time. Lower values may reduce memory usage and improve the VM's performance (especially on ID Software games like DOOM II RPG where setting this to 1 vastly reduces memory usage compared to the default), but some games might need bigger values.", + "vphone_settings", + { + { "1", "1" }, + { "2", "2" }, + { "4", "4" }, + { "8", "8" }, + { "16", "16" }, + { "32", "32" }, + { "48", "48" }, + { "64", "64" }, + { "96", "96" }, + { NULL, NULL }, + }, + "32" + }, { "freej2me_pointertype", "Advanced Settings > Pointer Type", @@ -357,6 +378,24 @@ struct retro_core_option_definition core_options_v1 [] = }, "on" }, + { + "freej2me_maxmidiplayers", + "Max MIDI Players", + "Sets the maximum amount of MIDI files that a given J2ME app can load up and play at any given time. Lower values may reduce memory usage and improve the VM's performance (especially on ID Software games like DOOM II RPG where setting this to 1 vastly reduces memory usage compared to the default), but some games might need bigger values.", + { + { "1", "1" }, + { "2", "2" }, + { "4", "4" }, + { "8", "8" }, + { "16", "16" }, + { "32", "32" }, + { "48", "48" }, + { "64", "64" }, + { "96", "96" }, + { NULL, NULL }, + }, + "32" + }, { "freej2me_pointertype", "Pointer Type", @@ -475,6 +514,10 @@ static const struct retro_variable vars[] = "freej2me_sound", "Virtual Phone Sound; on|off" }, + { /* Max MIDI Players */ + "freej2me_maxmidiplayers", + "Max MIDI Players: 32|1|2|4|8|16|48|64|96" + }, { /* Pointer Type */ "freej2me_pointertype", "Pointer Type; Mouse|Touch|None", diff --git a/src/org/recompile/freej2me/Config.java b/src/org/recompile/freej2me/Config.java index b994923f..92fe3cda 100644 --- a/src/org/recompile/freej2me/Config.java +++ b/src/org/recompile/freej2me/Config.java @@ -31,6 +31,7 @@ import java.nio.file.Path; import javax.microedition.lcdui.Graphics; +import javax.microedition.media.Manager; import org.recompile.mobile.Mobile; import org.recompile.mobile.PlatformImage; @@ -65,13 +66,14 @@ public Config() gc = lcd.getGraphics(); menu = new ArrayList(); - menu.add(new String[]{"Resume Game", "Display Size", "Sound", "Limit FPS", "Phone", "Rotate", "Exit"}); // 0 - Main Menu + menu.add(new String[]{"Resume Game", "Display Size", "Sound", "Limit FPS", "Phone", "Rotate", "Max MIDI Players", "Exit"}); // 0 - Main Menu menu.add(new String[]{"96x65","96x96","104x80","128x128","132x176","128x160","176x208","176x220", "208x208", "240x320", "320x240", "240x400", "352x416", "360x640", "640x360" ,"480x800", "800x480"}); // 1 - Size menu.add(new String[]{"Quit", "Main Menu"}); // 2 - Restart Notice menu.add(new String[]{"On", "Off"}); // 3 - sound menu.add(new String[]{"Standard", "Nokia", "Siemens","Motorola"}); // 4 - Phone menu.add(new String[]{"On", "Off"}); // 5 - rotate menu.add(new String[]{"Auto", "60 - Fast", "30 - Slow", "15 - Turtle"}); // 6 - FPS + menu.add(new String[]{"1", "2", "4", "8", "16", "32", "48", "64", "96"}); // 7 - Max amount of MIDI Players onChange = new Runnable() @@ -150,6 +152,7 @@ public void init() if(!settings.containsKey("phone")) { settings.put("phone", "Standard"); } if(!settings.containsKey("rotate")) { settings.put("rotate", "off"); } if(!settings.containsKey("fps")) { settings.put("fps", "0"); } + if(!settings.containsKey("maxmidiplayers")) { settings.put("maxmidiplayers", "32"); } int w = Integer.parseInt(settings.get("width")); int h = Integer.parseInt(settings.get("height")); @@ -160,6 +163,7 @@ public void init() lcd = new PlatformImage(width, height); gc = lcd.getGraphics(); } + } catch (Exception e) { @@ -311,7 +315,7 @@ public void render() for(int i=start; (i<(start+max))&(i1 && i<7) + if(menuid==0 && i>1 && i<8) { switch(i) { @@ -319,6 +323,7 @@ public void render() case 3: label = label+": "+settings.get("fps"); break; case 4: label = label+": "+settings.get("phone"); break; case 5: label = label+": "+settings.get("rotate"); break; + case 6: label = label+": "+settings.get("maxmidiplayers"); break; } } if(i==itemid) @@ -349,7 +354,8 @@ private void doMenuAction() case 3: menuid=6; itemid=0; break; // fps case 4: menuid=4; itemid=0; break; // phone case 5: menuid=5; itemid=0; break; // rotate - case 6: System.exit(0); break; + case 6: menuid=7; itemid=0; break; // max MIDI Players + case 7: System.exit(0); break; } break; @@ -397,6 +403,19 @@ private void doMenuAction() menuid=0; itemid=0; break; + case 7: // Max Midi Players + if(itemid==0) { updateMIDIPlayers("1"); } + if(itemid==1) { updateMIDIPlayers("2"); } + if(itemid==2) { updateMIDIPlayers("4"); } + if(itemid==3) { updateMIDIPlayers("8"); } + if(itemid==4) { updateMIDIPlayers("16"); } + if(itemid==5) { updateMIDIPlayers("32"); } + if(itemid==6) { updateMIDIPlayers("48"); } + if(itemid==7) { updateMIDIPlayers("64"); } + if(itemid==8) { updateMIDIPlayers("96"); } + menuid=2; itemid=0; + break; + } render(); @@ -446,4 +465,12 @@ private void updateFPS(String value) saveConfig(); onChange.run(); } + + private void updateMIDIPlayers(String value) + { + System.out.println("Config: maxmidiplayers "+value); + settings.put("maxmidiplayers", value); + saveConfig(); + onChange.run(); + } } diff --git a/src/org/recompile/freej2me/FreeJ2ME.java b/src/org/recompile/freej2me/FreeJ2ME.java index c9f7b13f..8ecad00d 100644 --- a/src/org/recompile/freej2me/FreeJ2ME.java +++ b/src/org/recompile/freej2me/FreeJ2ME.java @@ -28,6 +28,7 @@ import java.io.File; import java.io.FilenameFilter; import javax.imageio.ImageIO; +import javax.microedition.media.Manager; public class FreeJ2ME { @@ -349,6 +350,8 @@ private void settingsChanged() resize(); main.setSize(lcdWidth*scaleFactor+xborder , lcdHeight*scaleFactor+yborder); } + + Manager.updatePlayerNum((byte) Integer.parseInt(config.settings.get("maxmidiplayers"))); } private int getMobileKey(int keycode) diff --git a/src/org/recompile/freej2me/Libretro.java b/src/org/recompile/freej2me/Libretro.java index 0810c5c8..4127b044 100644 --- a/src/org/recompile/freej2me/Libretro.java +++ b/src/org/recompile/freej2me/Libretro.java @@ -33,6 +33,8 @@ import java.io.File; import java.net.URL; +import javax.microedition.media.Manager; + public class Libretro { private int lcdWidth; @@ -50,6 +52,7 @@ public class Libretro private boolean rotateDisplay = false; private boolean soundEnabled = true; private int limitFPS = 0; + private int maxmidiplayers = 32; private boolean[] pressedKeys = new boolean[128]; @@ -98,6 +101,9 @@ public Libretro(String args[]) if(Integer.parseInt(args[5]) == 0) { soundEnabled = false; } + maxmidiplayers = Integer.parseInt(args[6]); + Manager.updatePlayerNum((byte) maxmidiplayers); + /* Once it finishes parsing all arguments, it's time to set up freej2me-lr */ surface = new BufferedImage(lcdWidth, lcdHeight, BufferedImage.TYPE_INT_ARGB); // libretro display @@ -275,6 +281,8 @@ public void run() config.settings.put("fps", ""+limitFPS); + config.settings.put("maxmidiplayers", ""+maxmidiplayers); + config.saveConfig(); settingsChanged(); @@ -330,6 +338,16 @@ public void run() if(Integer.parseInt(cfgtokens[6])==1) { config.settings.put("sound", "on"); } if(Integer.parseInt(cfgtokens[6])==0) { config.settings.put("sound", "off"); } + if(Integer.parseInt(cfgtokens[7])==0) { config.settings.put("maxmidiplayers", "1");} + if(Integer.parseInt(cfgtokens[7])==1) { config.settings.put("maxmidiplayers", "2");} + if(Integer.parseInt(cfgtokens[7])==2) { config.settings.put("maxmidiplayers", "4");} + if(Integer.parseInt(cfgtokens[7])==3) { config.settings.put("maxmidiplayers", "8");} + if(Integer.parseInt(cfgtokens[7])==4) { config.settings.put("maxmidiplayers", "16");} + if(Integer.parseInt(cfgtokens[7])==5) { config.settings.put("maxmidiplayers", "32");} + if(Integer.parseInt(cfgtokens[7])==6) { config.settings.put("maxmidiplayers", "48");} + if(Integer.parseInt(cfgtokens[7])==7) { config.settings.put("maxmidiplayers", "64");} + if(Integer.parseInt(cfgtokens[7])==8) { config.settings.put("maxmidiplayers", "96");} + config.saveConfig(); settingsChanged(); break; @@ -423,6 +441,8 @@ private void settingsChanged() surface = new BufferedImage(lcdWidth, lcdHeight, BufferedImage.TYPE_INT_ARGB); // libretro display gc = (Graphics2D)surface.getGraphics(); } + + Manager.updatePlayerNum((byte) Integer.parseInt(config.settings.get("maxmidiplayers"))); } private void keyDown(int key)