From 9f55ccd61b8edc3999d2f85b02f7c200964e09a4 Mon Sep 17 00:00:00 2001 From: yangkui <752544765@qq.com> Date: Mon, 30 Jan 2023 12:33:11 +0800 Subject: [PATCH] fix bug --- app/pom.xml | 6 - .../navclub/nes4j/app/control/IconPopup.java | 72 ++++++++++++ .../nes4j/app/control/StatusIndicator.java | 104 ------------------ .../nes4j/app/control/skin/IconPopupSkin.java | 44 ++++++++ .../cn/navclub/nes4j/app/view/GameWorld.java | 16 ++- .../app/assets/css/{common.css => Common.css} | 2 +- .../nes4j/app/assets/css/DException.css | 2 +- .../navclub/nes4j/app/assets/css/DHandle.css | 2 +- .../nes4j/app/assets/css/DNesHeaderStyle.css | 2 +- .../nes4j/app/assets/css/DebuggerStyle.css | 2 +- .../nes4j/app/assets/css/GameHallStyle.css | 7 +- .../cn/navclub/nes4j/app/assets/css/Nes4j.css | 2 +- .../nes4j/app/assets/css/SystemPalette.css | 2 +- .../nes4j/app/assets/css/TextPopup.css | 9 ++ .../cn/navclub/nes4j/app/assets/img/speed.png | Bin 0 -> 5116 bytes .../main/java/cn/navclub/nes4j/bin/NES.java | 17 ++- build/icon/nes4j.ico | Bin 0 -> 67646 bytes build/jpackage.sh | 5 +- 18 files changed, 168 insertions(+), 126 deletions(-) create mode 100644 app/src/main/java/cn/navclub/nes4j/app/control/IconPopup.java delete mode 100644 app/src/main/java/cn/navclub/nes4j/app/control/StatusIndicator.java create mode 100644 app/src/main/java/cn/navclub/nes4j/app/control/skin/IconPopupSkin.java rename app/src/main/resources/cn/navclub/nes4j/app/assets/css/{common.css => Common.css} (99%) create mode 100644 app/src/main/resources/cn/navclub/nes4j/app/assets/css/TextPopup.css create mode 100644 app/src/main/resources/cn/navclub/nes4j/app/assets/img/speed.png create mode 100644 build/icon/nes4j.ico diff --git a/app/pom.xml b/app/pom.xml index d3311e9..8d79b56 100644 --- a/app/pom.xml +++ b/app/pom.xml @@ -36,12 +36,6 @@ javafx-fxml ${javafx.version} - - - org.controlsfx - controlsfx - 11.1.2 - cn.navclub nes4j-bin diff --git a/app/src/main/java/cn/navclub/nes4j/app/control/IconPopup.java b/app/src/main/java/cn/navclub/nes4j/app/control/IconPopup.java new file mode 100644 index 0000000..063b3e3 --- /dev/null +++ b/app/src/main/java/cn/navclub/nes4j/app/control/IconPopup.java @@ -0,0 +1,72 @@ +package cn.navclub.nes4j.app.control; + +import cn.navclub.nes4j.app.control.skin.IconPopupSkin; +import javafx.animation.FadeTransition; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.scene.control.PopupControl; +import javafx.scene.control.Skin; +import javafx.scene.image.Image; +import javafx.stage.Screen; +import javafx.util.Duration; + +/** + * A icon popup implement. + * + * @author GZYangKui + */ +public class IconPopup extends PopupControl { + private final FadeTransition transition; + private final ObjectProperty image; + + public IconPopup() { + this.setAutoFix(true); + this.transition = new FadeTransition(); + this.transition.setToValue(0); + this.transition.setFromValue(1.0); + this.transition.setOnFinished(event -> this.hide()); + this.transition.setDuration(Duration.millis(1000)); + this.image = new SimpleObjectProperty<>(this, "image", null); + + this.setOnShown(event -> { + this.transition.stop(); + this.transition.setNode(this.getSkin().getNode()); + this.transition.setDelay(Duration.millis(500)); + this.transition.play(); + this.calculateXY(); + }); + } + + public IconPopup(Image image) { + this(); + this.setImage(image); + } + + @Override + protected Skin createDefaultSkin() { + return new IconPopupSkin(this); + } + + public Image getImage() { + return image.get(); + } + + public ObjectProperty imageProperty() { + return image; + } + + public void setImage(Image image) { + this.image.set(image); + } + + private void calculateXY() { + var screen = Screen.getPrimary(); + var rect = screen.getVisualBounds(); + + var x = (rect.getWidth() - this.getWidth()) / 2; + var y = (rect.getHeight() - this.getHeight()) - 10; + + this.setX(x); + this.setY(y); + } +} diff --git a/app/src/main/java/cn/navclub/nes4j/app/control/StatusIndicator.java b/app/src/main/java/cn/navclub/nes4j/app/control/StatusIndicator.java deleted file mode 100644 index d577fd1..0000000 --- a/app/src/main/java/cn/navclub/nes4j/app/control/StatusIndicator.java +++ /dev/null @@ -1,104 +0,0 @@ -//package cn.navclub.nes4j.app.control; -// -//import cn.navclub.nes4j.app.assets.FXResource; -//import javafx.animation.FadeTransition; -//import javafx.beans.property.ObjectProperty; -//import javafx.beans.property.SimpleObjectProperty; -//import javafx.collections.ListChangeListener; -//import javafx.scene.Node; -//import javafx.scene.Parent; -// -//import javafx.scene.image.Image; -//import javafx.scene.image.ImageView; -//import javafx.scene.layout.VBox; -//import javafx.util.Duration; -// -///** -// * Custom status indicator control,current implement only support {@link Parent} and subclass. -// * -// * @author GZYangKui -// */ -//public class StatusIndicator extends VBox { -// private static final Image DEFAULT_IMAGE = FXResource.loadImage("empty.png"); -// private static final Image DEFAULT_ERROR_IMAGE = FXResource.loadImage("error.png"); -// -// private final ImageView icon; -// private ObjectProperty attach; -// private final ObjectProperty type; -// private ListChangeListener listChangeListener; -// -// public StatusIndicator() { -// this.icon = new ImageView(); -// this.type = new SimpleObjectProperty<>(this, "type", null); -// -// this.getStyleClass().add("status-indicator"); -// this.getChildren().add(this.icon); -// -// -// //listener type change -// this.type.addListener(((observable, oldValue, newValue) -> { -// var image = switch (newValue) { -// case ERROR -> DEFAULT_ERROR_IMAGE; -// case LOAD -> DEFAULT_LOAD_IMAGE; -// default -> DEFAULT_IMAGE; -// }; -// this.icon.setImage(image); -// })); -// } -// -// private ListChangeListener listChangeListener() { -// return c -> { -// var children = this.getAttach().getChildrenUnmodifiable(); -// if (children.size() > 0) { -// transition.play(); -// } else { -// this.setVisible(true); -// } -// }; -// } -// -// public Parent getAttach() { -// return this.attachProperty().get(); -// } -// -// public ObjectProperty attachProperty() { -// if (this.attach == null) { -// this.attach = new SimpleObjectProperty<>(this, "attach", null); -// } -// return attach; -// } -// -// public void setAttach(Parent attach) { -// var oldValue = this.getAttach(); -// if (oldValue == attach) { -// return; -// } -// if (oldValue != null) { -// oldValue.getChildrenUnmodifiable().removeListener(this.listChangeListener); -// } -// this.listChangeListener = this.listChangeListener(); -// attach.getChildrenUnmodifiable().addListener(this.listChangeListener); -// this.attachProperty().set(attach); -// } -// -// public Type getType() { -// return type.get(); -// } -// -// public ObjectProperty typeProperty() { -// return type; -// } -// -// public void setType(Type type) { -// this.type.set(type); -// } -// -// public enum Type { -// //Empty -// EMPTY, -// //Load -// LOAD, -// //error -// ERROR -// } -//} diff --git a/app/src/main/java/cn/navclub/nes4j/app/control/skin/IconPopupSkin.java b/app/src/main/java/cn/navclub/nes4j/app/control/skin/IconPopupSkin.java new file mode 100644 index 0000000..bc9d20f --- /dev/null +++ b/app/src/main/java/cn/navclub/nes4j/app/control/skin/IconPopupSkin.java @@ -0,0 +1,44 @@ +package cn.navclub.nes4j.app.control.skin; + +import cn.navclub.nes4j.app.assets.FXResource; +import cn.navclub.nes4j.app.control.IconPopup; +import javafx.scene.Node; +import javafx.scene.control.Skin; +import javafx.scene.image.ImageView; +import javafx.scene.layout.VBox; + + +public class IconPopupSkin implements Skin { + private VBox node; + @SuppressWarnings("all") + private final ImageView icon; + private final IconPopup popup; + + public IconPopupSkin(IconPopup popup) { + this.popup = popup; + this.node = new VBox(); + this.icon = new ImageView(); + + this.icon.imageProperty().bind(popup.imageProperty()); + + this.node.getChildren().add(this.icon); + this.node.getStyleClass().add("text-popup"); + this.node.getStylesheets().add(FXResource.loadStyleSheet("TextPopup.css")); + } + + @Override + public IconPopup getSkinnable() { + return this.popup; + } + + @Override + public Node getNode() { + return node; + } + + @Override + public void dispose() { + this.node = null; + this.icon.imageProperty().unbind(); + } +} diff --git a/app/src/main/java/cn/navclub/nes4j/app/view/GameWorld.java b/app/src/main/java/cn/navclub/nes4j/app/view/GameWorld.java index 02707ff..c300aaa 100644 --- a/app/src/main/java/cn/navclub/nes4j/app/view/GameWorld.java +++ b/app/src/main/java/cn/navclub/nes4j/app/view/GameWorld.java @@ -3,6 +3,7 @@ import cn.navclub.nes4j.app.assets.FXResource; import cn.navclub.nes4j.app.INes; import cn.navclub.nes4j.app.audio.JavaXAudio; +import cn.navclub.nes4j.app.control.IconPopup; import cn.navclub.nes4j.app.service.TaskService; import cn.navclub.nes4j.app.dialog.DHandle; import cn.navclub.nes4j.app.event.FPSTracer; @@ -24,6 +25,7 @@ import javafx.scene.control.*; import javafx.scene.image.PixelFormat; import javafx.scene.image.WritableImage; +import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; import javafx.scene.paint.Color; import javafx.scene.text.Font; @@ -56,16 +58,17 @@ public class GameWorld extends Stage { private volatile int fps; private Debugger debugger; private TaskService service; + private final IconPopup speedPopup; public GameWorld() { var scene = new Scene(FXResource.loadFXML(this)); this.scale = 3; - this.ctx = canvas.getGraphicsContext2D(); this.eventQueue = new LinkedBlockingDeque<>(); this.tracer = new FPSTracer(it -> this.fps = it); + this.speedPopup = new IconPopup(FXResource.loadImage("speed.png")); this.intBuffer = IntBuffer.allocate(this.scale * this.scale); this.image = new WritableImage(this.scale * Frame.width, this.scale * Frame.height); @@ -74,7 +77,7 @@ public GameWorld() { this.setHeight(600); this.setScene(scene); this.setResizable(false); - this.getScene().getStylesheets().add(FXResource.loadStyleSheet("common.css")); + this.getScene().getStylesheets().add(FXResource.loadStyleSheet("Common.css")); this.setOnCloseRequest(event -> this.dispose(null)); @@ -94,6 +97,15 @@ public GameWorld() { } } } + + //Change emulator speed + if (code == KeyCode.ADD || code == KeyCode.SUBTRACT) { + if (log.isDebugEnabled()) { + log.debug("Change ppu output frame action:{}", code); + } + this.instance.speed(code == KeyCode.ADD ? -1 : 1); + this.speedPopup.show(this); + } }); } diff --git a/app/src/main/resources/cn/navclub/nes4j/app/assets/css/common.css b/app/src/main/resources/cn/navclub/nes4j/app/assets/css/Common.css similarity index 99% rename from app/src/main/resources/cn/navclub/nes4j/app/assets/css/common.css rename to app/src/main/resources/cn/navclub/nes4j/app/assets/css/Common.css index 43bbb0a..b418faf 100644 --- a/app/src/main/resources/cn/navclub/nes4j/app/assets/css/common.css +++ b/app/src/main/resources/cn/navclub/nes4j/app/assets/css/Common.css @@ -16,7 +16,7 @@ /**Game hall text color**/ -nes4j-game-hall-text-fill: #000000; /**Game hall list-cell select background color**/ - -nes4j-game-hall-list-cell-active: linear-gradient(to right, #D6E0F0, #DDE4EF, #E6EAEF, #EAEBED); + -nes4j-game-hall-list-cell-active: linear-gradient(to right, #b4cbf3, #c6d6ef, #cfddef, #e4e7ef); /**Game hall list-cell select text fill*/ -nes4j-game-hall-list-cell-text: #5185fd; /**Default list view select row background color**/ diff --git a/app/src/main/resources/cn/navclub/nes4j/app/assets/css/DException.css b/app/src/main/resources/cn/navclub/nes4j/app/assets/css/DException.css index f7c724f..937dc3f 100644 --- a/app/src/main/resources/cn/navclub/nes4j/app/assets/css/DException.css +++ b/app/src/main/resources/cn/navclub/nes4j/app/assets/css/DException.css @@ -1,4 +1,4 @@ -@import "common.css"; +@import "Common.css"; .text-area { -fx-padding: 0; diff --git a/app/src/main/resources/cn/navclub/nes4j/app/assets/css/DHandle.css b/app/src/main/resources/cn/navclub/nes4j/app/assets/css/DHandle.css index f8a9713..e5e15a0 100644 --- a/app/src/main/resources/cn/navclub/nes4j/app/assets/css/DHandle.css +++ b/app/src/main/resources/cn/navclub/nes4j/app/assets/css/DHandle.css @@ -1,4 +1,4 @@ -@import "common.css"; +@import "Common.css"; .box, .content { -fx-spacing: 2em; diff --git a/app/src/main/resources/cn/navclub/nes4j/app/assets/css/DNesHeaderStyle.css b/app/src/main/resources/cn/navclub/nes4j/app/assets/css/DNesHeaderStyle.css index 2db39f1..128b9c2 100644 --- a/app/src/main/resources/cn/navclub/nes4j/app/assets/css/DNesHeaderStyle.css +++ b/app/src/main/resources/cn/navclub/nes4j/app/assets/css/DNesHeaderStyle.css @@ -1,4 +1,4 @@ -@import "common.css"; +@import "Common.css"; GridPane { -fx-hgap: 1em; diff --git a/app/src/main/resources/cn/navclub/nes4j/app/assets/css/DebuggerStyle.css b/app/src/main/resources/cn/navclub/nes4j/app/assets/css/DebuggerStyle.css index 097056c..3acd8d3 100644 --- a/app/src/main/resources/cn/navclub/nes4j/app/assets/css/DebuggerStyle.css +++ b/app/src/main/resources/cn/navclub/nes4j/app/assets/css/DebuggerStyle.css @@ -1,4 +1,4 @@ -@import "common.css"; +@import "Common.css"; GridPane { -fx-vgap: 1em; diff --git a/app/src/main/resources/cn/navclub/nes4j/app/assets/css/GameHallStyle.css b/app/src/main/resources/cn/navclub/nes4j/app/assets/css/GameHallStyle.css index b7fdd7c..bf76958 100644 --- a/app/src/main/resources/cn/navclub/nes4j/app/assets/css/GameHallStyle.css +++ b/app/src/main/resources/cn/navclub/nes4j/app/assets/css/GameHallStyle.css @@ -1,4 +1,4 @@ -@import "common.css"; +@import "Common.css"; .navbar *, .assort, .flow-pane .game-tray .label, .empty .label { -fx-font-size: 1.4em; @@ -53,6 +53,7 @@ } .assort { + -fx-padding: 0; -fx-background-insets: 0; } @@ -68,12 +69,12 @@ -fx-shape: 'M970.666667 213.333333H546.586667a10.573333 10.573333 0 0 1-7.54-3.126666L429.793333 100.953333A52.986667 52.986667 0 0 0 392.08 85.333333H96a53.393333 53.393333 0 0 0-53.333333 53.333334v704a53.393333 53.393333 0 0 0 53.333333 53.333333h874.666667a53.393333 53.393333 0 0 0 53.333333-53.333333V266.666667a53.393333 53.393333 0 0 0-53.333333-53.333334z m-275.866667 374.82c-25.486667 33.926667-71.333333 74.92-148.666667 132.913334a21.333333 21.333333 0 0 1-25.6 0c-77.333333-58-123.18-98.986667-148.666666-132.913334S341.333333 528.273333 341.333333 497.233333C341.333333 434.793333 392.126667 384 454.566667 384A112.893333 112.893333 0 0 1 533.333333 415.9 112.893333 112.893333 0 0 1 612.1 384c62.44 0 113.233333 50.793333 113.233333 113.233333 0 31.04-5.106667 57.08-30.533333 90.92z'; } -.assort .list-cell { +.assort .tree-cell { -fx-background-color: -nes4j-game-hall-list-view; -fx-focus-traversable: false; } -.assort .list-cell:selected { +.assort .tree-cell:selected { -fx-text-fill: -nes4j-game-hall-list-cell-text; -fx-background-color: -nes4j-game-hall-list-cell-active; } diff --git a/app/src/main/resources/cn/navclub/nes4j/app/assets/css/Nes4j.css b/app/src/main/resources/cn/navclub/nes4j/app/assets/css/Nes4j.css index 87b9082..e24a9ea 100644 --- a/app/src/main/resources/cn/navclub/nes4j/app/assets/css/Nes4j.css +++ b/app/src/main/resources/cn/navclub/nes4j/app/assets/css/Nes4j.css @@ -1,4 +1,4 @@ -@import "common.css"; +@import "Common.css"; .left-box, .right-box { -fx-spacing: .5em; diff --git a/app/src/main/resources/cn/navclub/nes4j/app/assets/css/SystemPalette.css b/app/src/main/resources/cn/navclub/nes4j/app/assets/css/SystemPalette.css index 3098a08..0e1940f 100644 --- a/app/src/main/resources/cn/navclub/nes4j/app/assets/css/SystemPalette.css +++ b/app/src/main/resources/cn/navclub/nes4j/app/assets/css/SystemPalette.css @@ -1,4 +1,4 @@ -@import "common.css"; +@import "Common.css"; VBox { -fx-spacing: 1em; diff --git a/app/src/main/resources/cn/navclub/nes4j/app/assets/css/TextPopup.css b/app/src/main/resources/cn/navclub/nes4j/app/assets/css/TextPopup.css new file mode 100644 index 0000000..1405096 --- /dev/null +++ b/app/src/main/resources/cn/navclub/nes4j/app/assets/css/TextPopup.css @@ -0,0 +1,9 @@ +@import "Common.css"; + +.text-popup { + -fx-padding: 2em 3em; + -fx-alignment: CENTER; + -fx-border-radius: .5em; + -fx-background-radius: .5em; + -fx-background-color: rgba(0, 0, 0, .8); +} \ No newline at end of file diff --git a/app/src/main/resources/cn/navclub/nes4j/app/assets/img/speed.png b/app/src/main/resources/cn/navclub/nes4j/app/assets/img/speed.png new file mode 100644 index 0000000000000000000000000000000000000000..2910fa3b155a05e911280cf4b5b2e211fe09d9e8 GIT binary patch literal 5116 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 elZ8h3^Zx^NtPtvl1hHQL0000 gameLoopCallback; //cpu stall cycle private int stall; - @Setter private int speed; //APU mute @Setter @@ -157,7 +156,7 @@ public void stop() { } /** - * 在debug模式下用于执行下一个断点所用 + * Execute next break line */ public synchronized void release() { if (this.thread == null) { @@ -166,6 +165,20 @@ public synchronized void release() { LockSupport.unpark(this.thread); } + /** + * Manual change emulator speed + * + * @param span offset value + */ + public int speed(int span) { + var temp = this.speed + span; + if (temp < 0) { + temp = 0; + } + this.speed = temp; + return this.speed; + } + public static class NESBuilder { private File file; private byte[] buffer; diff --git a/build/icon/nes4j.ico b/build/icon/nes4j.ico new file mode 100644 index 0000000000000000000000000000000000000000..18e0e5e9c281ec2647550d8964f3e180bc812531 GIT binary patch literal 67646 zcmeHQXK)o)mXWNG4~C3=$F`kt9F}iJ+{fKs4i;+Nz!M&YnHr)w`{Jt?rj}yIf5*5FJG>V6PF!5vhfI747sYj)ibTsv)c*hR-1^s<-e>B= zG@fY{(?O<-Or=bXOfQ-Ko9Q<<;T+d+4|$Lm&)`|`059--J!%yfp%r6H{=hVZDV3>! z=~pJQiNG6Wpe&U6hX_?$#EQ*2f0L;@(;BAxOm<=IFJH(2Ss>G!5v$lR7M%6^22&!_ z4kq|%f3a~oA7q1!koAo)R%t|t#yUiwo5a-2nn~afhn8m zpG@t=A=J;K4yX(26ed~@KQW*iCdAn{nL>@3UFD;0sAKp65JHJqA6=QQGufs0aN~=* zb`7D*!=h-`!3Rw6jp2rmQ}UqhAA|)M4hq3_?!c7H^baPdbRDkcKnKu82L~YtSy5b1 z#6cBI;fhD7u@PC+ylnl=*ytPh+21KdEaI_9>c!f*h^c0 zF5kAHnJQ<=a=yb9&2xAX6Q_^RDYkZm?H|kcE>k$H$vTaVQ{_Ro?}noRuv{IPYM7kT z#j9ElblfqVY=GrKyN_Y-ob5x`Vc`c@4)pgipYI&@((gg%A&m#Pe8l;&SkHOvr42y$ zAsH8NxftKa#(1H_UfKXKaD0A%%S>UCGQ^Id)kTVv@gU=lIo%lM;iUsd=8742tmVY! z^TP{!v_)WI>zWbs#~N-4Q>^WWrw)LPZEMHO8*9@s?893JYwU;x7{P+;g7xa&A>`oKft`OKT-0I9V0^*$trvRReR*;1S)uS5EiJAJD^!Dynbr ztan*uGp#(*K;7;43&7U$yJUPX(M~;q_pnvuB?H=0E0d8x(S^sv+ZN@*I z>$7x!13ju~#l6neNY`%^(ea;8P}a5`l)iCu8``*O3+>svpUz##rLy}EwKj0CqM2sz zXt293iB>*<>xggH*;fAi-3?S-->NHb*amX1ysDYTZF1Qrx0z1*EM+_9{z%G+cAk@) zM;TkQ+Td+w1Nv)w_Z^^Hw@Wl$2lE^4j1hL2;m>t^lL_B1v_+4bPc>@wlR8s*tZQhd z6IYw)IQI)q&|O{sezW*CWm>d#J#D_ z?gPO~WnN%^jQeHXcZG0Z3Q+^T6SOPZu_}L)jr_9zWp=y_=dXDGGMb9;|7Ws z;^(TGI(k%DO%+u&;@mi13Y4en{Dq9A5ihg!(PKYTHP>hFqo=g4{266eJ{9#jeB_v4 z&u`nlld5a$3FDkG+?Et$quum%)f0g!#{N5Z?e@tJb%ySyWhtE-NY&ww-?UI>TMPF1*Y@G-@7%qo zVT*CpqD4#E=ws31rCJ`?37!ds4LstxJIvjf`Fi8E;#+rUZpm{~{4*as)BIR%eFLG5 z8=u#w(T@QC^E_{+5T^p*&;0Nn@2?8^(uLyIc@eWVk8ALOMt=|dmvLLy*B$4$CjEmv z;#u&p;xDfkF;Dcj@Z0j5@pz-?79G}&y^Z%}`U21I7-h3cBi>ujeZIck%kz^Q2S}ds zc>QLvWxoQOL*Iw`4qC3PodR=UkM%xfcGYuHJ-1EYxL_V!VkwWn!3zH(Zcj3wJR(Mv z`m;JNU%rAiq;H~?tJa9Qce8v;mn|20R;^y^)lPQ)w8s>GjM;zMz1O2ZKXB*>RWv-N z5k;Q;|19E4Xj96)y4+EWA&O;%?4m6MjOC?-7`0S5U&x%k;;D9P0mdA?01I6+HCi!S^6&7NqI%-0(W39Y5#?9xE(i%egu9B&%hR76MBB~ z{QRYAf&0IGoI{fS+$WF99ySncN0y1UfM+Ueo0VbZ#{Qs6{IPZ=>t=Ptcm~*6;V-er zackywO$SmJdi?e4r&i_RI&1)b9=-$fab|g81F7rMM4nvs-TFLv`IkN9Ks>qo>~IZt zi9e3zl`VZW{CRHPC2h=b`s{ham`Bfd;*Z4|?h=0-(|4591w%i8z5%gAyt=(m!2Y62 z{IM@XUq7>RIo`LzADBxU$k^KAMhYIjW3zJ1t{L_3ZyqE5=)?A$``i@&`;|95 zbbztS_8q%~{UBz5|C8m8{h`Pd|J2MfI(MG!fa@zsj(HWX2LSt0mH1=rRo2bwh&GG% zzbnD#G?`+{d0F=J5?Ra~6a*B8cJg~RMsvMQqjs73w%FDMh+u)BF0PWsb zHvG@AF!sYZP1=DxA|AuIK<2|Uh>?N6F-|jzaX$z zy659)f%({0%8n!EynvmN3a{NT9sgte2YndxBkhkr*OwjaIr@7&9ykXk@MVbi>Km-* zJZmcNQPJ5Xx}H6k9^5%A{6At)@W2`m`iIKuCc1vBp2stdVr{@U&j?$A>`jlKl0y7} zJ%0OIS^M9Y-!ixDOV7r+KVTWi{2%hm^-*7Csk)CbpV0>3ldzU!=JQc*MR_5eUi&9H zvEpAfx}CF5^jmsfu!nv74_fXYyIgQp;9uYLOc_>g?0-{i>tVaM9D}zi9GGxvh@Ssl*>g z#Mv14=m{~CJ`e21il5!r{n_({*i??ytlEDKw|_Y%lsH=*(O05gXjiE}D~$yl@@sI9M;PC@bLp|35u^ zz^$BAVb9*4m-pnnKV(9?`YKK7{6DZ)I{pLx=_j8AzqINXm9Zaq z0ehwMKfoV-z?0`M{f-0dz{pOXutT&u(l}c@$AJ* zT768Z?+5LCCD5|KOpO>@_3W?6s%pluHA%nYQ0?O-~HXkDKYi;2>ZZT zNS62H*$b*|dPzNaZ-ruJBJbn4dfjtfUtfmVIdH}Ece($-``wTWeT&t+HT*r=2z1o&_$5uu zuoZjQ04fVe}%YY3&)#j z=@~RGImZd?VMqG+zm&iKX@x(oC$MdQlXQvgV5gWv+s?5NVlKS@ffx&YIO1tdI5pYyJb3?b{bG{rjKF-~aZ8 zzq}Vew~pWsCa0XHq;kK*>PWc|J&UMDF6P0#M$3tmw8n*VBuY1 z6T_AikvD?fB+RV|S}*;RTr_ONM1lX{Prjg`DXwM7cJ zUC^@ot4}ZaJihY>~B zCj|Duzt`BTR}Fu&??2i4{kL$lfy7bkHT=6w$$gdZ$DWTi-+y!W0k(esF`R6m--sVI z{1axCy-N6-e*e*pzwO_D4Hp|2_}O;?|G~q)Wb8v4i#ct3-oF3p*!Q19Y6o*_IQIKg z;6LE6)120SD9iKu{b#oiaP<4{p|FF5nRhhb-*@DqP~zcq*(3vz$*BJQw=PpJ+uHs+%_ycGe9D=eKoVSSb9y zEED)(-VcO%AbDNIvHOHW+Smg8`+T#KKIZX;3f}GD5zy~H!cMp>P*nc@Yy9j-8vcF1 zTB;12&eIA!u-9yCbh@%Kg0O+0e*e{N15x|?&x1bwR@lJ6&nK$EhTHhS&nIYh)q7Mb zVOI*j6Hw}0P7&+m3=*!LSThq11s z9^dWJuJsy|5eoeMj`=0t#v|kZ0ngn49R zTThr(s+H0I%OBcRhFQ5jt^uq2G|t zBgX48HQ)33IkkL$xZsc2&>{SRQ9`gddwY)gM%^B<#L=5HAAoorG26$Cn>Va5e(XJJ zoz{QAetL}G+vXYlIuqheZ#)&=YqPh@8>WHWV;Rv8lqi(dDV&Bd zz(%RxH`)jD|A^`D(PaZQVjfV&gA!X`$HAX|P1r|hrHdZp_iOlLKG-UsqU*rqBO_jR zq`91-ie$E1Cjs%t{2lfK$UfT&|3Sk?i#8uW`=M9v=LvH<7|$h+-aweYLA;0lz~8ZA|1W20eS|MtX{RnztZ=gHI?Idq zhL5*X?x66Ah%$LzK#u(eem2g|dIE#j?ZVj`UoQ7;Caf*mS-*(njXlNE_anZvNk`EA z+uks;`yQA74pYeA9kWTlLE~ok9s{?|-?1BCfB3U3?=sbd8wR12r~Aa?TKmU1K(Q>) z^}GIH<5V7&rz2C$2HbsNPo5Ky{vWZVLj0lQj!xkkNI5JQ{6MTPU>oSo^F0!Oh5Nvu z+puc)M*Cp-5D&caF=6j-*J${6no*>p{X?f=(cc>}H>O!mj0;}rv7vtMr}Ok{?ZqFu z3~8Ki#MoDw<;DC!3R8RQ9+A)Y8k?!L|8~A#3>}7KeD4cmf9|vFm@AI1^#VU^+9UqQ znxY@i81g`8j?U@&gJ&>#xE@$DDlybA7@b7SGo5DM*4lr+kqZNr8@h62EhiW}gL#JQ zgSBJqABd_wBwQa$YzKTXS=a#fh9t}^vCJoVbeeGsdr{LkZR;9tF!-r@hUb^D6-_~X5w0iRFO zY@pBA$-F-G3f_%TfG;Nf$qwB{5>Lhz?-@nqyJoOi>?@J)8^Hz!e>$>+_XZ?J z5=M5*%6h{4hIr>RD(4RIjuF2LdVAn!6NYx0Rcg07BbLA04iF=vUx66lQrKGh}~16uOJ1GFgZCE?FWIzE6nn7lx}XKsLw-S>K2z z48o-@tXF)ev^x{#lEPuF88Sc?$YlCm&2Z6OG|Is`$G7Y8`vs{?_#Km9ne6fp;Egg+ z7RvPahI%yWH`40Fm|)!zaRbH@&GHtr!0^5Pl! z`*`35o)NnaXN4oR{Kdt&Pg)LnadE%XUHD%-9p8GP7U{QI(@5$#i0rxt{?>B;U*rRM zEorTUmZZkO{kX>9f8_o5S{T&Iv|EBanRYW=Ak(jj{QoDDadGo;L1XVOKw}>l_a5%M zrNvW1;@Z~dMS*#(X;I*U*0dZ3t{gdx*~!Fs41k=L#9q9@XIr8Pgus;|lsp*LuqLmalZ4Xa3&>nqJ`f z{A;Syp6p+}lxlq%`Q>@4G+_K|J)eKeSK62T8t)t1gE4JvPsX&dJsQ)-_S`1DKwm)< z|B$D@&;F!VpEmJ79u;H<>QNzfupSkNZ=3e0zDB^8aYR~yqBxyKL~*(rzb77VEg-%nt<}h#lnmYMv>r(7 gFWnN#$E8Z-<8BGurQ@o2pf$S?S>rAq(>mM#2cH-S?f?J) literal 0 HcmV?d00001 diff --git a/build/jpackage.sh b/build/jpackage.sh index 41a9e29..b07cf3f 100644 --- a/build/jpackage.sh +++ b/build/jpackage.sh @@ -19,6 +19,7 @@ fi PROGRAM_NAME="nes4j" PROGRAM_ICON="icon/nes4j.png" MAIN_CLASS="cn.navclub.nes4j.app/cn.navclub.nes4j.app.Launcher" - +CMD="jpackage -n $PROGRAM_NAME -p $1 -m $MAIN_CLASS --icon $PROGRAM_ICON --license-file ../LICENSE --linux-package-name $PROGRAM_NAME --linux-app-category game" +echo "Jpackage command:$CMD" # shellcheck disable=SC2091 -$(jpackage -n "$PROGRAM_NAME" -p "$1" -m "${MAIN_CLASS}" --icon "$PROGRAM_ICON" --license-file ../LICENSE --linux-package-name "$PROGRAM_NAME") +$($CMD)