Add native objects and bridge menu to playback
- NativeFunctionFactory resolves script method calls to native Java methods via reflection; VsmxNativeFunction wraps them for the VM. - Native objects: Controller, MoviePlayer, Resource, Math, Timer, GlobalVariables, decoupled from the UI via a MenuHost interface. - BaseNativeObject.callCallback invokes script callbacks like onAutoPlay. - CLI 'rco' now wires the full menu and executes onAutoPlay headlessly. - Validated against Batman Begins: onAutoPlay computes stream IDs and issues play(playList=3, chapter=1, video=0xE000, audio=0xBD00, audioFlag=1, subtitle=-1, subtitleFlag=0) — the anti-piracy warning clip with English video/audio.
This commit is contained in:
@@ -13,7 +13,13 @@ import dev.quoije.umd.rco.RcoFile;
|
||||
import dev.quoije.umd.rco.vsmx.Vsmx;
|
||||
import dev.quoije.umd.rco.vsmx.interpreter.VsmxBaseObject;
|
||||
import dev.quoije.umd.rco.vsmx.interpreter.VsmxInterpreter;
|
||||
import dev.quoije.umd.rco.vsmx.interpreter.VsmxNativeObject;
|
||||
import dev.quoije.umd.rco.vsmx.interpreter.VsmxObject;
|
||||
import dev.quoije.umd.rco.vsmx.objects.Controller;
|
||||
import dev.quoije.umd.rco.vsmx.objects.GlobalVariables;
|
||||
import dev.quoije.umd.rco.vsmx.objects.MenuHost;
|
||||
import dev.quoije.umd.rco.vsmx.objects.MoviePlayer;
|
||||
import dev.quoije.umd.rco.vsmx.objects.Resource;
|
||||
import dev.quoije.umd.sfo.Sfo;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -420,13 +426,53 @@ public final class Main {
|
||||
|
||||
VsmxInterpreter interpreter = new VsmxInterpreter();
|
||||
interpreter.setVsmx(vsmx);
|
||||
VsmxObject globals = new VsmxObject(interpreter, null);
|
||||
|
||||
final List<String> playCalls = new java.util.ArrayList<>();
|
||||
MenuHost menuHost = new MenuHost() {
|
||||
@Override
|
||||
public void playMovie(int playListNumber, int chapterNumber, int videoNumber, int audioNumber,
|
||||
int audioFlag, int subtitleNumber, int subtitleFlag) {
|
||||
playCalls.add(String.format("play(playList=%d, chapter=%d, video=%d, audio=%d, audioFlag=%d, subtitle=%d, subtitleFlag=%d)",
|
||||
playListNumber, chapterNumber, videoNumber, audioNumber, audioFlag, subtitleNumber, subtitleFlag));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopMovie() {
|
||||
playCalls.add("stop()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeResource(String resourceName) {
|
||||
playCalls.add("changeResource(" + resourceName + ")");
|
||||
}
|
||||
};
|
||||
|
||||
String resourceName = rcoPath.substring(rcoPath.lastIndexOf('/') + 1).replace(".RCO", "");
|
||||
VsmxNativeObject globals = GlobalVariables.create(interpreter, 854, 480);
|
||||
VsmxNativeObject controller = Controller.create(interpreter, menuHost, resourceName);
|
||||
VsmxNativeObject movieplayer = MoviePlayer.create(interpreter, menuHost, controller);
|
||||
VsmxNativeObject resource = Resource.create(interpreter);
|
||||
VsmxNativeObject math = dev.quoije.umd.rco.vsmx.objects.Math.create(interpreter);
|
||||
globals.setPropertyValue(Controller.objectName, controller);
|
||||
globals.setPropertyValue(MoviePlayer.objectName, movieplayer);
|
||||
globals.setPropertyValue(Resource.objectName, resource);
|
||||
globals.setPropertyValue(dev.quoije.umd.rco.vsmx.objects.Math.objectName, math);
|
||||
|
||||
interpreter.run(globals);
|
||||
|
||||
System.out.printf("global variables (%d):%n", globals.getPropertyNames().size());
|
||||
for (String varName : globals.getPropertyNames()) {
|
||||
VsmxBaseObject value = globals.getPropertyValue(varName);
|
||||
System.out.printf(" %s = %s%n", varName, value);
|
||||
if (!(value instanceof VsmxNativeObject)) {
|
||||
System.out.printf(" %s = %s%n", varName, value);
|
||||
}
|
||||
}
|
||||
|
||||
// Execute the menu's autoplay handler (stored on the controller).
|
||||
((Controller) controller.getObject()).callCallback(interpreter, "onAutoPlay", null);
|
||||
System.out.printf("onAutoPlay play calls (%d):%n", playCalls.size());
|
||||
for (String call : playCalls) {
|
||||
System.out.println(" " + call);
|
||||
}
|
||||
|
||||
if (!interpreter.getWarnings().isEmpty()) {
|
||||
|
||||
Reference in New Issue
Block a user