Commit a40a1bd1 authored by Stephanie Gawroriski's avatar Stephanie Gawroriski
Browse files

Add base GIF handler that loads a magenta placeholder; Implement methods to...

Add base GIF handler that loads a magenta placeholder; Implement methods to make the i-mode Block Breaker example run; Make the LCDUI exit go through the ApplicationInterface instead of MIDlet for using the exit command on i-mode applications; Use a better means of grabbing the default title so that i-mode applications show the application name rather than just "SquirrelJME"; Add generic vibration handler.
parent c8dae828
Pipeline #87035 passed with stages
in 1 minute and 28 seconds
......@@ -30,6 +30,12 @@ JNIEXPORT jint JNICALL Impl_mle_RuntimeShelf_memoryProfile(JNIEnv*, jclass)
return 0;
}
JNIEXPORT jint JNICALL Impl_mle_RuntimeShelf_phoneModel(JNIEnv*, jclass)
{
// Just be a generic device here
return 0;
};
JNIEXPORT jint JNICALL Impl_mle_RuntimeShelf_vmType(JNIEnv*, jclass)
{
// The value 1 is Java SE type
......@@ -41,6 +47,7 @@ static const JNINativeMethod mleRuntimeMethods[] =
{"garbageCollect", "()V", (void*)Impl_mle_RuntimeShelf_garbageCollect},
{"lineEnding", "()I", (void*)Impl_mle_RuntimeShelf_lineEnding},
{"memoryProfile", "()I", (void*)Impl_mle_RuntimeShelf_memoryProfile},
{"phoneModel", "()I", (void*)Impl_mle_RuntimeShelf_phoneModel},
{"vmType", "()I", (void*)Impl_mle_RuntimeShelf_vmType},
};
......
......@@ -14,9 +14,11 @@ import cc.squirreljme.jvm.mle.constants.BuiltInEncodingType;
import cc.squirreljme.jvm.mle.constants.BuiltInLocaleType;
import cc.squirreljme.jvm.mle.constants.ByteOrderType;
import cc.squirreljme.jvm.mle.constants.MemoryProfileType;
import cc.squirreljme.jvm.mle.constants.PhoneModelType;
import cc.squirreljme.jvm.mle.constants.VMDescriptionType;
import cc.squirreljme.jvm.mle.constants.VMStatisticType;
import cc.squirreljme.jvm.mle.constants.VMType;
import cc.squirreljme.runtime.cldc.debug.Debugging;
import cc.squirreljme.runtime.cldc.lang.LineEndingUtils;
import cc.squirreljme.vm.springcoat.exceptions.SpringMLECallError;
......@@ -178,6 +180,21 @@ public enum MLERuntime
}
},
/** {@link RuntimeShelf#phoneModel()}. */
PHONE_MODEL("phoneModel:()I")
{
/**
* {@inheritDoc}
* @since 2022/02/14
*/
@Override
public Object handle(SpringThreadWorker __thread, Object... __args)
{
// Just be a generic model
return PhoneModelType.GENERIC;
}
},
/** {@link RuntimeShelf#systemProperty(String)}. */
SYSTEM_PROPERTY("systemProperty:(Ljava/lang/String;)" +
"Ljava/lang/String;")
......
......@@ -8,12 +8,15 @@
package cc.squirreljme.jvm.launch;
import cc.squirreljme.jvm.mle.RuntimeShelf;
import cc.squirreljme.jvm.mle.brackets.JarPackageBracket;
import cc.squirreljme.jvm.mle.constants.PhoneModelType;
import cc.squirreljme.jvm.suite.Configuration;
import cc.squirreljme.jvm.suite.DependencyInfo;
import cc.squirreljme.jvm.suite.EntryPoint;
import cc.squirreljme.jvm.suite.InvalidSuiteException;
import cc.squirreljme.jvm.suite.Profile;
import cc.squirreljme.runtime.cldc.SquirrelJME;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
......@@ -190,6 +193,12 @@ public class IModeApplication
if (spSize != null && !spSize.isEmpty())
rv.put(IModeApplication.SCRATCH_PAD_PROPERTY, spSize);
// If a specific phone model is used, set the platform property
// explicitly
if (RuntimeShelf.phoneModel() == PhoneModelType.GENERIC)
rv.put("microedition.platform",
SquirrelJME.platform(PhoneModelType.NTT_DOCOMO_D503I));
return rv;
}
......
......@@ -14,6 +14,7 @@ import cc.squirreljme.jvm.mle.constants.BuiltInLocaleType;
import cc.squirreljme.jvm.mle.constants.ByteOrderType;
import cc.squirreljme.jvm.mle.constants.LineEndingType;
import cc.squirreljme.jvm.mle.constants.MemoryProfileType;
import cc.squirreljme.jvm.mle.constants.PhoneModelType;
import cc.squirreljme.jvm.mle.constants.VMDescriptionType;
import cc.squirreljme.jvm.mle.constants.VMStatisticType;
import cc.squirreljme.jvm.mle.constants.VMType;
......@@ -111,6 +112,14 @@ public final class RuntimeShelf
*/
public static native long nanoTime();
/**
* Returns the phone model that SquirrelJME is simulating itself as.
*
* @return The {@link PhoneModelType}.
* @since 2022/02/14
*/
public static native int phoneModel();
/**
* Returns the system property for the given key, if there is one.
*
......
// ---------------------------------------------------------------------------
// SquirrelJME
// Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------
package cc.squirreljme.jvm.mle.constants;
/**
* This represents potential simulated phone models.
*
* @since 2022/02/14
*/
public interface PhoneModelType
{
/** Generic SquirrelJME. */
byte GENERIC =
0;
/** NTT Docomo D503i. */
byte NTT_DOCOMO_D503I =
1;
/** NTT Docomo F503i. */
byte NTT_DOCOMO_F503I =
2;
/** NTT Docomo So503i. */
byte NTT_DOCOMO_SO503I =
3;
/** NTT Docomo P503i. */
byte NTT_DOCOMO_P503I =
4;
}
......@@ -9,19 +9,60 @@
package cc.squirreljme.runtime.cldc;
import cc.squirreljme.jvm.mle.RuntimeShelf;
import cc.squirreljme.jvm.mle.constants.PhoneModelType;
/**
* Contains information on SquirrelJME.
*
* @since 2018/12/05
*/
public interface SquirrelJME
public final class SquirrelJME
{
/** The version of this SquirrelJME runtime. */
String RUNTIME_VERSION =
public static final String RUNTIME_VERSION =
"0.3.0";
/** The microedition platform. */
String MICROEDITION_PLATFORM =
public static final String MICROEDITION_PLATFORM =
"SquirrelJME/0.3.0";
/**
* Not used.
*
* @since 2022/02/14
*/
private SquirrelJME()
{
}
/**
* Returns the {@code microedition.platform} property of the machine.
*
* @param __phoneModel The current phone model.
* @since 2022/02/14
*/
public static String platform(int __phoneModel)
{
// This can vary
String base = SquirrelJME.MICROEDITION_PLATFORM;
switch (__phoneModel)
{
case PhoneModelType.NTT_DOCOMO_D503I:
return base + " D503i";
case PhoneModelType.NTT_DOCOMO_F503I:
return base + " F503i";
case PhoneModelType.NTT_DOCOMO_SO503I:
return base + " So503i";
case PhoneModelType.NTT_DOCOMO_P503I:
return base + " P503i";
}
// Unknown
return base;
}
}
......@@ -13,6 +13,7 @@ import cc.squirreljme.jvm.mle.ObjectShelf;
import cc.squirreljme.jvm.mle.RuntimeShelf;
import cc.squirreljme.jvm.mle.TypeShelf;
import cc.squirreljme.jvm.mle.brackets.TypeBracket;
import cc.squirreljme.jvm.mle.constants.PhoneModelType;
import cc.squirreljme.jvm.mle.constants.StandardPipeType;
import cc.squirreljme.jvm.mle.constants.VMDescriptionType;
import cc.squirreljme.runtime.cldc.SquirrelJME;
......@@ -418,6 +419,15 @@ public final class System
// The current platform
case "microedition.platform":
// Allow this to be overridden by the user
String platformOverride = RuntimeShelf.systemProperty(__k);
if (platformOverride != null)
return platformOverride;
// Try to use a specific platform
int phoneModel = RuntimeShelf.phoneModel();
if (phoneModel != PhoneModelType.GENERIC)
return SquirrelJME.platform(phoneModel);
return SquirrelJME.MICROEDITION_PLATFORM;
// The operating system architecture
......
......@@ -11,6 +11,7 @@ package cc.squirreljme.runtime.midlet;
import cc.squirreljme.jvm.mle.ThreadShelf;
import cc.squirreljme.runtime.cldc.Poking;
import cc.squirreljme.runtime.cldc.debug.Debugging;
import javax.microedition.midlet.MIDlet;
/**
* This handles the main starting loop and otherwise for applications, it is
......@@ -21,6 +22,22 @@ import cc.squirreljme.runtime.cldc.debug.Debugging;
*/
public final class ApplicationHandler
{
/** Undefined application name. */
public static final String UNDEFINED_NAME =
"UndefinedName";
/** The current application interface. */
private static volatile ApplicationInterface<?> _CURRENT_INTERFACE;
/** The current application instance. */
private static volatile Object _CURRENT_INSTANCE;
/** The current vendor. */
private static String _CURRENT_VENDOR;
/** The current name. */
private static String _CURRENT_NAME;
/** One second in milliseconds. */
private static final int _TERM_WAIT_TIME =
30_000;
......@@ -29,6 +46,106 @@ public final class ApplicationHandler
private static final long _SETTLE_NS =
2_000_000_000;
/**
* Returns the current application interface.
*
* @return The current application interface.
* @since 2022/02/14
*/
public static ApplicationInterface<?> currentInterface()
{
return ApplicationHandler._CURRENT_INTERFACE;
}
/**
* Returns the current application instance.
*
* @return The current application instance.
* @since 2022/02/14
*/
public static Object currentInstance()
{
return ApplicationHandler._CURRENT_INSTANCE;
}
/**
* Returns the current name.
*
* @return The current name.
* @since 2019/04/14
*/
public static String currentName()
{
String rv;
synchronized (ApplicationHandler.class)
{
rv = ApplicationHandler._CURRENT_NAME;
if (rv != null)
return rv;
}
// TODO: Better means of getting the current name
Debugging.todoNote("Better means of currentName()");
// Try through the current MIDlet properties
if (rv == null)
{
MIDlet mid = ActiveMidlet.optional();
if (mid != null)
rv = mid.getAppProperty("MIDlet-Name");
}
// Fallback
if (rv == null)
rv = ApplicationHandler.UNDEFINED_NAME;
// Cache and return
synchronized (ApplicationHandler.class)
{
ApplicationHandler._CURRENT_NAME = rv;
return rv;
}
}
/**
* Returns the current vendor.
*
* @return The current vendor.
* @since 2019/04/14
*/
public static String currentVendor()
{
String rv;
synchronized (ApplicationHandler.class)
{
rv = ApplicationHandler._CURRENT_VENDOR;
if (rv != null)
return rv;
}
// TODO: Better means of getting the current name
Debugging.todoNote("Better means of currentVendor()");
// Try through the current MIDlet properties
if (rv == null)
{
MIDlet mid = ActiveMidlet.optional();
if (mid != null)
rv = mid.getAppProperty("MIDlet-Vendor");
}
// Fallback
if (rv == null)
rv = "UndefinedVendor";
// Cache and return
synchronized (ApplicationHandler.class)
{
ApplicationHandler._CURRENT_VENDOR = rv;
return rv;
}
}
/**
* Handles the main application handling and logic.
*
......@@ -51,6 +168,10 @@ public final class ApplicationHandler
// Setup new instance of the application
T instance = __ai.<T>newInstance();
// Store current application that is being used
ApplicationHandler._CURRENT_INTERFACE = __ai;
ApplicationHandler._CURRENT_INSTANCE = instance;
// Start the application and perform any potential handling of it
Throwable throwable = null;
try
......@@ -134,4 +255,25 @@ public final class ApplicationHandler
__ai.<T>destroy(instance, throwable);
}
}
/**
* Forces the set of the suite name and vendor.
*
* @param __name The name to set.
* @param __vend The vendor to set.
* @throws NullPointerException On null arguments.
* @since 2021/12/02
*/
public static void setNameAndVendor(String __name, String __vend)
throws NullPointerException
{
if (__name == null || __vend == null)
throw new NullPointerException("NARG");
synchronized (ApplicationHandler.class)
{
ApplicationHandler._CURRENT_NAME = __name;
ApplicationHandler._CURRENT_VENDOR = __vend;
}
}
}
......@@ -9,9 +9,7 @@
package cc.squirreljme.runtime.rms;
import cc.squirreljme.runtime.cldc.debug.Debugging;
import cc.squirreljme.runtime.midlet.ActiveMidlet;
import javax.microedition.midlet.MIDlet;
import cc.squirreljme.runtime.midlet.ApplicationHandler;
/**
* This is used to help identify suites and such.
......@@ -23,12 +21,6 @@ public final class SuiteIdentifier
/** The identifier for the current suite. */
private static long _CURRENT_ID;
/** The current vendor. */
private static String _CURRENT_VENDOR;
/** The current name. */
private static String _CURRENT_NAME;
/**
* Not used.
*
......@@ -53,88 +45,10 @@ public final class SuiteIdentifier
// Set, cache, and store
SuiteIdentifier._CURRENT_ID = (rv = SuiteIdentifier.identifier(
SuiteIdentifier.currentVendor(), SuiteIdentifier.currentName()));
ApplicationHandler.currentVendor(), ApplicationHandler.currentName()));
return rv;
}
/**
* Returns the current name.
*
* @return The current name.
* @since 2019/04/14
*/
public static String currentName()
{
String rv;
synchronized (SuiteIdentifier.class)
{
rv = SuiteIdentifier._CURRENT_NAME;
if (rv != null)
return rv;
}
// TODO: Better means of getting the current name
Debugging.todoNote("Better means of currentName()");
// Try through the current MIDlet properties
if (rv == null)
{
MIDlet mid = ActiveMidlet.optional();
if (mid != null)
rv = mid.getAppProperty("MIDlet-Name");
}
// Fallback
if (rv == null)
rv = "UndefinedName";
// Cache and return
synchronized (SuiteIdentifier.class)
{
SuiteIdentifier._CURRENT_NAME = rv;
return rv;
}
}
/**
* Returns the current vendor.
*
* @return The current vendor.
* @since 2019/04/14
*/
public static String currentVendor()
{
String rv;
synchronized (SuiteIdentifier.class)
{
rv = SuiteIdentifier._CURRENT_VENDOR;
if (rv != null)
return rv;
}
// TODO: Better means of getting the current name
Debugging.todoNote("Better means of currentVendor()");
// Try through the current MIDlet properties
if (rv == null)
{
MIDlet mid = ActiveMidlet.optional();
if (mid != null)
rv = mid.getAppProperty("MIDlet-Vendor");
}
// Fallback
if (rv == null)
rv = "UndefinedVendor";
// Cache and return
synchronized (SuiteIdentifier.class)
{
SuiteIdentifier._CURRENT_VENDOR = rv;
return rv;
}
}
/**
* Returns the suite identifier.
*
......@@ -153,26 +67,5 @@ public final class SuiteIdentifier
return ((((long)__vend.hashCode()) & 0xFFFFFFFFL) << 32) |
(((long)__suite.hashCode()) & 0xFFFFFFFFL);
}
/**
* Forces the set of the suite name and vendor.
*
* @param __name The name to set.
* @param __vend The vendor to set.
* @throws NullPointerException On null arguments.
* @since 2021/12/02
*/
public static void setNameAndVendor(String __name, String __vend)
throws NullPointerException
{
if (__name == null || __vend == null)
throw new NullPointerException("NARG");
synchronized (SuiteIdentifier.class)
{
SuiteIdentifier._CURRENT_NAME = __name;
SuiteIdentifier._CURRENT_VENDOR = __vend;
}
}
}
......@@ -10,6 +10,7 @@
package javax.microedition.rms;
import cc.squirreljme.runtime.cldc.lang.ImplementationClass;
import cc.squirreljme.runtime.midlet.ApplicationHandler;
import cc.squirreljme.runtime.rms.SuiteIdentifier;
import cc.squirreljme.runtime.rms.TemporaryVinylRecord;
import cc.squirreljme.runtime.rms.VinylLock;
......@@ -1047,7 +1048,7 @@ public class RecordStore
SecureRecordStoreException, SecurityException
{
return RecordStore.__openRecordStore(__n,
SuiteIdentifier.currentVendor(), SuiteIdentifier.currentName(),
ApplicationHandler.currentVendor(), ApplicationHandler.currentName(),
__create, __auth, __write, __pass);
}
......
......@@ -10,6 +10,7 @@ package cc.squirreljme.runtime.lcdui.image;
import cc.squirreljme.runtime.cldc.debug.Debugging;
import java.io.IOException;
import java.io.InputStream;
import javax.microedition.lcdui.Image;
import net.multiphasicapps.io.ExtendedDataInputStream;
......@@ -49,8 +50,17 @@ public class GIFReader
protected Image parse()
throws IOException
{
// Skip header
ExtendedDataInputStream in = this.in;
for (int i = 0; i < 6; i++)
in.readByte();
// Read "screen" size
int screenWidth = in.readUnsignedShort();
int screenHeight = in.readUnsignedShort();
throw Debugging.todo();
// Build image
return Image.createImage(Image.createImage(screenWidth, screenHeight,