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

Correct streaming ZIP bugs in exactly-defined file sizes; Implement launching of SpringCoat.

parent b9bb050b
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="delegatedBuild" value="true" />
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="1.8" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/buildSrc" />
<option value="$PROJECT_DIR$/emulators" />
<option value="$PROJECT_DIR$/emulators/emulator-base" />
<option value="$PROJECT_DIR$/emulators/springcoat-vm" />
<option value="$PROJECT_DIR$/emulators/summercoat-vm" />
<option value="$PROJECT_DIR$/modules" />
<option value="$PROJECT_DIR$/modules/cldc" />
<option value="$PROJECT_DIR$/modules/cldc-compact" />
<option value="$PROJECT_DIR$/modules/collections" />
<option value="$PROJECT_DIR$/modules/common-vm" />
<option value="$PROJECT_DIR$/modules/demo-hello" />
<option value="$PROJECT_DIR$/modules/dio" />
<option value="$PROJECT_DIR$/modules/dio-adc" />
<option value="$PROJECT_DIR$/modules/dio-atcmd" />
<option value="$PROJECT_DIR$/modules/dio-counter" />
<option value="$PROJECT_DIR$/modules/dio-dac" />
<option value="$PROJECT_DIR$/modules/dio-generic" />
<option value="$PROJECT_DIR$/modules/dio-gpio" />
<option value="$PROJECT_DIR$/modules/dio-i2cbus" />
<option value="$PROJECT_DIR$/modules/dio-mmio" />
<option value="$PROJECT_DIR$/modules/dio-modem" />
<option value="$PROJECT_DIR$/modules/dio-pwm" />
<option value="$PROJECT_DIR$/modules/dio-spibus" />
<option value="$PROJECT_DIR$/modules/dio-uart" />
<option value="$PROJECT_DIR$/modules/dio-watchdog" />
<option value="$PROJECT_DIR$/modules/gcf" />
<option value="$PROJECT_DIR$/modules/io" />
<option value="$PROJECT_DIR$/modules/jblend-api" />
<option value="$PROJECT_DIR$/modules/launcher" />
<option value="$PROJECT_DIR$/modules/lcdui-demo" />
<option value="$PROJECT_DIR$/modules/m3g" />
<option value="$PROJECT_DIR$/modules/markdown-writer" />
<option value="$PROJECT_DIR$/modules/media-api" />
<option value="$PROJECT_DIR$/modules/meep-cellular" />
<option value="$PROJECT_DIR$/modules/meep-concurrency" />
<option value="$PROJECT_DIR$/modules/meep-event" />
<option value="$PROJECT_DIR$/modules/meep-key" />
<option value="$PROJECT_DIR$/modules/meep-liblets" />
<option value="$PROJECT_DIR$/modules/meep-lui" />
<option value="$PROJECT_DIR$/modules/meep-midlet" />
<option value="$PROJECT_DIR$/modules/meep-power" />
<option value="$PROJECT_DIR$/modules/meep-provisioning" />
<option value="$PROJECT_DIR$/modules/meep-rms" />
<option value="$PROJECT_DIR$/modules/meep-securityframework" />
<option value="$PROJECT_DIR$/modules/meep-swm" />
<option value="$PROJECT_DIR$/modules/midp-lcdui" />
<option value="$PROJECT_DIR$/modules/opengles" />
<option value="$PROJECT_DIR$/modules/profile-meep" />
<option value="$PROJECT_DIR$/modules/squirrel-quarrel" />
<option value="$PROJECT_DIR$/modules/strings" />
<option value="$PROJECT_DIR$/modules/supervisor" />
<option value="$PROJECT_DIR$/modules/tac" />
<option value="$PROJECT_DIR$/modules/tac-runner" />
<option value="$PROJECT_DIR$/modules/tool-classfile" />
<option value="$PROJECT_DIR$/modules/tool-compiler" />
<option value="$PROJECT_DIR$/modules/tool-jarfile" />
<option value="$PROJECT_DIR$/modules/tool-jdwp" />
<option value="$PROJECT_DIR$/modules/tool-manifest-reader" />
<option value="$PROJECT_DIR$/modules/tool-manifest-writer" />
<option value="$PROJECT_DIR$/modules/tool-packfile" />
<option value="$PROJECT_DIR$/modules/vodafone-api" />
<option value="$PROJECT_DIR$/modules/zip" />
<option value="$PROJECT_DIR$/tools" />
<option value="$PROJECT_DIR$/tools/dump-class" />
<option value="$PROJECT_DIR$/tools/dump-zip" />
<option value="$PROJECT_DIR$/tools/pcf-to-sqf" />
<option value="$PROJECT_DIR$/tools/sqf-to-c" />
<option value="$PROJECT_DIR$/tools/txt-to-pbm" />
<option value="$PROJECT_DIR$/tools/uudecode" />
</set>
</option>
<option name="useAutoImport" value="true" />
<option name="useQualifiedModuleNames" value="true" />
</GradleProjectSettings>
</option>
</component>
</project>
\ No newline at end of file
......@@ -312,6 +312,7 @@
<option name="ignoreSerializable" value="false" />
<option name="ignoreCloneable" value="false" />
</inspection_tool>
<inspection_tool class="RedundantTypeArguments" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ReplaceNullCheck" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SamePackageImport" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="SimplifiableJUnitAssertion" enabled="false" level="WARNING" enabled_by_default="false" />
......@@ -338,6 +339,7 @@
<inspection_tool class="TestMethodIsPublicVoidNoArg" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="TextBlockBackwardMigration" enabled="false" level="INFORMATION" enabled_by_default="false" />
<inspection_tool class="TextBlockMigration" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ToArrayCallWithZeroLengthArrayArgument" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="TodoComment" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="UnaryPlus" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="UnconstructableTestCase" enabled="false" level="WARNING" enabled_by_default="false" />
......
......@@ -13,6 +13,7 @@ package cc.squirreljme.plugin;
import cc.squirreljme.plugin.tasks.AdditionalManifestPropertiesTask;
import cc.squirreljme.plugin.tasks.GenerateTestsListTask;
import cc.squirreljme.plugin.tasks.MimeDecodeResourcesTask;
import cc.squirreljme.plugin.tasks.RunEmulatedTask;
import cc.squirreljme.plugin.tasks.RunNativeTask;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
......@@ -53,6 +54,14 @@ public class SquirrelJMEPlugin
Task rna = __project.getTasks().create("runNative",
RunNativeTask.class, jarTask);
// Run emulated program
Task esp = __project.getTasks().create("runSpringCoat",
RunEmulatedTask.class,
jarTask, "springcoat", false);
Task esu = __project.getTasks().create("runSummerCoat",
RunEmulatedTask.class,
jarTask, "summercoat", false);
// Mime Decode Resources
Task mmr = __project.getTasks().create("mimeDecodeResources",
MimeDecodeResourcesTask.class, SourceSet.MAIN_SOURCE_SET_NAME,
......
......@@ -37,7 +37,7 @@ import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.ModuleDependency;
import org.gradle.api.artifacts.ProjectDependency;
import org.gradle.api.file.FileCollection;
import org.gradle.api.java.archives.Manifest;
import org.gradle.jvm.tasks.Jar;
......@@ -185,7 +185,7 @@ public class AdditionalManifestPropertiesTask
}
// Find all module dependencies
Map<String, ModuleDependency> dependencies = new TreeMap<>();
Map<String, ProjectDependency> dependencies = new TreeMap<>();
for (String configurationName : Arrays.<String>asList(
"api", "implementation"))
{
......@@ -195,11 +195,11 @@ public class AdditionalManifestPropertiesTask
if (buildConfig == null)
continue;
// Add all module based dependencies
// Add all project based dependencies
for (Dependency dependency : buildConfig.getDependencies())
if (dependency instanceof ModuleDependency)
if (dependency instanceof ProjectDependency)
{
ModuleDependency mod = (ModuleDependency)dependency;
ProjectDependency mod = (ProjectDependency)dependency;
dependencies.put(mod.getName(), mod);
}
......@@ -207,23 +207,10 @@ public class AdditionalManifestPropertiesTask
// Put in as many dependencies as possible
int normalDep = 1;
for (ModuleDependency dependency : dependencies.values())
for (ProjectDependency dependency : dependencies.values())
{
// Find the associated project
Project subProject = project.findProject(dependency.getName());
if (subProject == null)
{
// Does it exist in the parent?
Project parent = project.getParent();
if (parent != null)
subProject = parent.findProject(dependency.getName());
// Really does not exist
if (subProject == null)
throw new RuntimeException(String.format(
"Module %s (%s) does not exist?", dependency,
dependency.getName()));
}
Project subProject = dependency.getDependencyProject();
// Get the project config
SquirrelJMEPluginConfiguration subConfig =
......
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: 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.plugin.tasks;
import cc.squirreljme.plugin.SquirrelJMEPluginConfiguration;
import cc.squirreljme.plugin.swm.JavaMEMidlet;
import cc.squirreljme.plugin.swm.JavaMEMidletType;
import groovy.lang.Closure;
import java.io.File;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Objects;
import java.util.concurrent.Callable;
import javax.inject.Inject;
import org.gradle.api.Action;
import org.gradle.api.DefaultTask;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.ProjectDependency;
import org.gradle.jvm.tasks.Jar;
import org.gradle.process.JavaExecSpec;
/**
* Launches the program but runs it in the Virtual Machine.
*
* @since 2020/02/29
*/
public class RunEmulatedTask
extends DefaultTask
{
/** Main configurations. */
private static final String[] _MAIN_CONFIGS =
new String[]{"api", "implementation"};
/** Test configurations. */
private static final String[] _TEST_CONFIGS =
new String[]{"testApi", "testImplementation"};
/** The emulator to use. */
protected final String emulator;
/** Is this for a test? */
protected final boolean isTest;
/**
* Initializes the task.
*
* @param __jar The JAR task.
* @param __emulator The emulator to use.
* @param __test Is this for tests?
* @since 2020/02/29
*/
@Inject
public RunEmulatedTask(Jar __jar, String __emulator, boolean __test)
{
if (__test)
throw new IllegalArgumentException("Implement test launching!");
this.emulator = __emulator;
this.isTest = __test;
// Set details of this task
this.setGroup("squirreljme");
this.setDescription((__test ? "Tests the program with " +
__emulator + "." : "Launches the program with the " +
__emulator + " virtual machine."));
// The output of this task is the profiling snapshot
this.getOutputs().files(
this.getProject().provider(this::__profilerSnapshotPath));
// This only runs if this is an application
this.onlyIf(this::__onlyIf);
// Run the task accordingly
this.doLast(new RunEmulatedTask.__ActionTask__());
// This needs the JAR task and the emulation task
this.dependsOn(__jar,
(Callable<Object>)this::__findEmulatorJarTask,
(Callable<Object>)this::__findEmulatorBaseJarTask);
}
/**
* Only runs if these conditions are met.
*
* @param __task Checks this task.
* @return If this can run or not.
* @since 2020/02/29
*/
private boolean __onlyIf(Task __task)
{
// Only allow if an application!
return SquirrelJMEPluginConfiguration.configuration(this.getProject())
.swmType == JavaMEMidletType.APPLICATION;
}
/**
* Finds the emulator JAR task.
*
* @return The emulator JAR task.
* @since 2020/02/29
*/
private Object __findEmulatorBaseJarTask()
{
return Objects.requireNonNull(this.getProject().getRootProject().
findProject(":emulators:emulator-base"),
"No emulator base?").getTasks().getByName("jar");
}
/**
* Locates the emulator package to base on.
*
* @return The emulator base.
* @since 2020/02/29
*/
private Object __findEmulatorJarTask()
{
return Objects.requireNonNull(this.getProject().getRootProject().
findProject(":emulators:" + this.emulator + "-vm"),
"No emulator?").getTasks().getByName("jar");
}
/**
* Returns the snapshot path for the profiler.
*
* @return The profiler snapshot path.
* @since 2020/02/29
*/
File __profilerSnapshotPath()
{
return this.getProject().getBuildDir().toPath()
.resolve(this.emulator + ".nps").toFile();
}
/**
* Returns the run class path.
*
* @return The run class path.
* @since 2020/02/29
*/
Iterable<Path> __runClassPath()
{
Collection<Path> result = new LinkedHashSet<>();
this.__recursiveDependencies(result, this.getProject());
return result;
}
/**
* Returns the run class path as a string.
*
* @return The run class path as a string.
* @since 2020/02/29
*/
String __runClassPathAsString()
{
StringBuilder sb = new StringBuilder();
for (Path path : this.__runClassPath())
{
if (sb.length() > 0)
sb.append(File.pathSeparatorChar);
sb.append(path);
}
return sb.toString();
}
/**
* Recursively scans and obtains dependencies.
*
* @param __out The output collection.
* @param __at The current project currently at.
* @since 2020/02/29
*/
final void __recursiveDependencies(Collection<Path> __out, Project __at)
{
// If this is not a SquirrelJME project, ignore
SquirrelJMEPluginConfiguration config = __at.getExtensions()
.<SquirrelJMEPluginConfiguration>findByType(
SquirrelJMEPluginConfiguration.class);
if (config == null)
return;
// Look in these configurations for dependencies, done first so what
// we depend on has higher priority first
for (String configurationName : (this.isTest ?
RunEmulatedTask._TEST_CONFIGS : RunEmulatedTask._MAIN_CONFIGS))
{
// The configuration might not even exist
Configuration buildConfig = __at.getConfigurations()
.findByName(configurationName);
if (buildConfig == null)
continue;
// Recursively scan dependencies
for (Dependency dependency : buildConfig.getDependencies())
{
// Only consider modules
if (!(dependency instanceof ProjectDependency))
continue;
// Recursive search these dependencies
this.__recursiveDependencies(__out,
((ProjectDependency)dependency).getDependencyProject());
}
}
// Process the output files for the JAR of this project, use the
// absolute path since there might be hard to find libraries that are
// relative
for (File file : ((Jar)__at.getTasks().getByName("jar"))
.getOutputs().getFiles())
__out.add(file.toPath().toAbsolutePath());
}
/**
* Used to run the emulator.
*
* @since 2020/02/29
*/
private class __ActionTask__
implements Action<Task>
{
/**
* {@inheritDoc}
* @since 2020/02/29
*/
@Override
public void execute(Task __task)
{
// Get current and emulator projects
Project project = RunEmulatedTask.this.getProject();
Project emuBase = project.getRootProject().
project(":emulators:emulator-base");
Project emuCore = project.getRootProject().
project(":emulators:" + RunEmulatedTask.this.emulator + "-vm");
// Need this to get the program details
SquirrelJMEPluginConfiguration config =
SquirrelJMEPluginConfiguration.configuration(project);
// Execute program
project.javaexec((JavaExecSpec __spec) ->
{
// Are we launching a MIDlet?
JavaMEMidlet midlet = null;
if (!config.midlets.isEmpty())
midlet = config.midlets.get(0);
// Build arguments to the VM
Collection<String> args = new LinkedList<>();
// Add emulator
args.add("-Xemulator:" + RunEmulatedTask.this.emulator);
// Add snapshot path
args.add("-Xsnapshot:" + RunEmulatedTask.this.
__profilerSnapshotPath().toPath().toString());
// Determine program classpath
args.add("-classpath");
args.add(RunEmulatedTask.this.__runClassPathAsString());
// Add main class to launch
args.add((midlet != null ?
"javax.microedition.midlet.__MainHandler__" :
Objects.requireNonNull(config.mainClass,
"No main class in project.")));
// We need to tell the MIDlet launcher what our main entry
// point is going to be
if (midlet != null)
args.add(midlet.mainClass);
// Use the given arguments
__spec.args(args);
// We only need the classpath of the emulator because this
// runs on it
__spec.classpath(
((Jar)emuBase.getTasks().getByName("jar"))
.getOutputs().getFiles(),
((Jar)emuCore.getTasks().getByName("jar"))
.getOutputs().getFiles(),
RunNativeTask.__projectClassPath(emuBase),
RunNativeTask.__projectClassPath(emuCore));
// Main entry point for the emulator
__spec.setMain("cc.squirreljme.emulator.vm.VMFactory");
});
}
}
}
......@@ -23,7 +23,8 @@ import org.gradle.jvm.tasks.Jar;
import org.gradle.process.JavaExecSpec;
/**
* Not Described
* Launches the program using the host system which is backed by the
* base emulator.
*
* @since 2020/02/29
*/
......
......@@ -126,6 +126,13 @@ More detailed changes:
traverse in the event an infinite recursive method was profiled.
* `vodafone-api`
* Added API Stubs.
* `zip`
* Added `read(byte[])` which forwards to the more optimal function
rather than the super-class which only performs single byte reads.
* When reading entries where the size is fully known, if the uncompressed
data size is fulfilled but there is still remaining compressed data
(in the case where a zero byte file is compressed to two bytes),
continue to read the compressed data to drain it out.
* Compiler Backend
* Added a bunch of string representations for class structures.
* Created a stack-cached register based compiler for Java byte code.
......
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: 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.emulator.vm;
import cc.squirreljme.vm.VMClassLibrary;
import java.util.Collection;
import java.util.LinkedList;
/**
* This is a suite manager which is just a group of already specified
* libraries.
*
* @since 2020/02/29
*/
public final class ArraySuiteManager
implements VMSuiteManager
{
/** Local libraries. */
private final VMClassLibrary[] _libraries;
/**
* Initializes the library manager.
*
* @param __libs Libraries to use.
* @since 2020/02/29
*/
public ArraySuiteManager(VMClassLibrary... __libs)
{
this._libraries = (__libs == null ? new VMClassLibrary[0] :
__libs.clone());
for (VMClassLibrary lib : this._libraries)
if (lib == null)
throw new NullPointerException("NARG");
}
/**
* Initializes the library manager.
*
* @param __libs Libraries to use.
* @since 2020/02/29
*/
public ArraySuiteManager(Iterable<VMClassLibrary> __libs)
{
Collection<VMClassLibrary> copy = new LinkedList<>();
for (VMClassLibrary lib : __libs)
copy.add(lib);
this._libraries = copy.<VMClassLibrary>toArray(
new VMClassLibrary[copy.size()]);
for (VMClassLibrary lib : this._libraries)
if (lib == null)
throw new NullPointerException("NARG");
}
/**
* {@inheritDoc}
* @since 2020/02/29
*/