more standalone TerranBASIC executable build files

This commit is contained in:
minjaesong
2023-04-15 00:48:14 +09:00
parent 9a4e28caa7
commit 9fa543af53
29 changed files with 3723 additions and 262 deletions

5
.gitignore vendored
View File

@@ -4,6 +4,11 @@ bin/*
build/*
.gradle/*
TerrarumBuild.jar
My_BASIC_Programs/*
buildapp/out/TerranBASIC*
buildapp/TerranBASIC_linux.*
buildapp/TerranBASIC_macOS.*
buildapp/TerranBASIC_windows.*
# Java native errors
hs_err_pid*

View File

@@ -1,6 +1,6 @@
<component name="ArtifactManager">
<artifact type="jar" name="TerranBASIC">
<output-path>$PROJECT_DIR$/out/artifacts/TerranBASIC</output-path>
<output-path>$PROJECT_DIR$/out</output-path>
<root id="archive" name="TerranBASIC.jar">
<element id="directory" name="META-INF">
<element id="file-copy" path="$PROJECT_DIR$/TerranBASICexecutable/META-INF/MANIFEST.MF" />

View File

@@ -1,6 +1,6 @@
<component name="ArtifactManager">
<artifact type="jar" name="TerrarumTSVM">
<output-path>$PROJECT_DIR$/out/artifacts/TerrarumTSVM</output-path>
<output-path>$PROJECT_DIR$/out</output-path>
<root id="archive" name="TerrarumTSVM.jar">
<element id="module-output" name="tsvm_core" />
</root>

View File

@@ -5,6 +5,8 @@ import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import net.torvald.tsvm.peripheral.*;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
public class TerranBASIC {
@@ -15,7 +17,24 @@ public class TerranBASIC {
public static int WIDTH = 640;
public static int HEIGHT = 480;
public static String diskDir = "My_BASIC_Programs";
private static void createDirs() {
File[] dirs = {
new File(diskDir)
};
for (File it : dirs) {
if (!it.exists())
it.mkdirs();
}
}
public static void main(String[] args) {
createDirs();
ShaderProgram.pedantic = false;
appConfig = new Lwjgl3ApplicationConfiguration();
@@ -30,8 +49,8 @@ public class TerranBASIC {
HashMap<String, VMWatchdog> watchdogs = new HashMap<>();
VM tbasvm = new VM("./assets", 64 << 10, new TheRealWorld(), new VMProgramRom[]{TBASRelBios.INSTANCE}, 2, watchdogs);
EmulInstance tbasrunner = new EmulInstance(tbasvm, "net.torvald.tsvm.peripheral.ReferenceGraphicsAdapter", "assets/disk0", 560, 448);
VM tbasvm = new VM("./assets", 64 << 10, new TheRealWorld(), new VMProgramRom[]{TerranBASICreleaseBios.INSTANCE}, 2, watchdogs);
EmulInstance tbasrunner = new EmulInstance(tbasvm, "net.torvald.tsvm.peripheral.ReferenceGraphicsAdapter", diskDir, 560, 448);
new Lwjgl3Application(new VMGUI(tbasrunner, WIDTH, HEIGHT), appConfig);
}
}

View File

@@ -2,6 +2,7 @@
// Version 1.0 Release Date 2020-12-28
// Version 1.1 Release Date 2021-01-28
// Version 1.2 Release Date 2021-05-05
// Version 1.2.1 Release Date 2021-12-02
/*
Copyright (c) 2020-2021 CuriousTorvald
@@ -25,13 +26,15 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
if (exec_args !== undefined && exec_args[1] !== undefined && exec_args[1].startsWith("-?")) {
println("Usage: basic <optional path to basic program>")
println("When the optional basic program is set, the interpreter will run the program and then quit if successful, remain open if the program had an error.")
return 0
}
// show TerranBASIC on the character LCD (aka the window title)
[..."TerranBASIC"].map(s=>s.charCodeAt(0)).forEach((c,i)=>{
sys.poke(-1025 - i, c)
})
const THEVERSION = "1.2"
let _BIOS = {}
_BIOS.FIRST_BOOTABLE_PORT=[0,1]
const THEVERSION = "1.2.1"
const PROD = true
let INDEX_BASE = 0
@@ -39,7 +42,7 @@ let TRACEON = (!PROD) && true
let DBGON = (!PROD) && true
let DATA_CURSOR = 0
let DATA_CONSTS = []
const BASIC_HOME_PATH = "/home/basic/"
const BASIC_HOME_PATH = "/"
if (sys.maxmem() < 8192) {
println("Out of memory. BASIC requires 8K or more User RAM")
@@ -867,6 +870,7 @@ bS.addAsBasicVar = function(lnum, troValue, rh) {
let varname = troValue.toUpperCase()
//println("input varname: "+varname)
if (_basicConsts[varname]) throw lang.asgnOnConst(lnum, varname)
if (bS.builtin[varname]) throw lang.asgnOnConst(lnum, varname)
let type = JStoBASICtype(rh)
bS.vars[varname] = new BasicVar(rh, type)
return {asgnVarName: varname, asgnValue: rh}
@@ -1773,7 +1777,7 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length
})
}},
/** type: (list of function) <*> (a functor)
* Sequnetial application
* SEQUENTIAL APPLICATION
*
* Can be implemented on pure TerranBASIC using:
* APL = [FS, XS, ARR] ~> IF (LEN(FS) == 0) THEN ARR ELSE APL(TAIL(FS), XS, (IF (ARR == UNDEFINED) THEN {} ELSE ARR) # MAP(HEAD(FS), XS))
@@ -1791,7 +1795,7 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length
})
}},
/** type: (a function) <*> (a functor)
* Infix MAP
* INFIX MAP
*/
"<$>" : {argc:2, f:function(lnum, stmtnum, args) {
return bS.builtin.MAP.f(lnum, stmtnum, args)
@@ -1815,6 +1819,40 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length
return ret
})
}},
/** Writes to the serial device and blocks until a status code is returned
* @param device number (int), message (str)
* @return status code from the device.
*/
"CPUT" : {argc:2, f:function(lnum, stmtnum, args) {
return twoArg(lnum, stmtnum, args, (devnum, msg) => {
if (!isNumable(devnum)) throw lang.illegalType(lnum, "LH:"+Object.entries(devnum))
com.sendMessage(devnum, msg)
return com.getStatusCode(devnum)
})
}},
/** Reads the entire message (may be larger than 4096 bytes) from the serial device to the scratchpad memory
* @param device number (int), destination pointer (int)
* @return length of the message being read; specified memory will be filled with the actual message
*/
"CGET" : {argc:2, f:function(lnum, stmtnum, args) {
return twoArgNum(lnum, stmtnum, args, (devnum, ptr) => {
let msg = com.pullMessage(devnum)
let len = msg.length|0
for (let i = 0; i < len; i++) {
sys.poke(ptr + i, msg.charCodeAt(i))
}
return len
})
}},
/** Gets the status code of the serial device
* @param device number (int)
* @return status code 0..255
*/
"CSTA" : {argc:2, f:function(lnum, stmtnum, args) {
return oneArgNum(lnum, stmtnum, args, (devnum) => {
return com.getStatusCode(devnum)
})
}},
"OPTIONDEBUG" : {f:function(lnum, stmtnum, args) {
oneArgNum(lnum, stmtnum, args, (lh) => {
if (lh != 0 && lh != 1) throw lang.syntaxfehler(line)
@@ -1917,7 +1955,7 @@ bF._opPrc = {
// function call in itself has highest precedence
"`":10, // MJOIN
"^":20,
"*":30,"/":30,"\\":20,
"*":30,"/":30,"\\":30,
"MOD":40,
"+":50,"-":50,
"NOT":60,"BNOT":60,
@@ -4217,18 +4255,6 @@ bF.catalog = function(args) { // CATALOG function
}
Object.freeze(bF)
if (exec_args !== undefined && exec_args[1] !== undefined) {
bF.load(["load", exec_args[1]])
try {
bF.run()
return 0
}
catch (e) {
serial.printerr(`${e}\n${e.stack || "Stack trace undefined"}`)
println(`${e}`)
}
}
while (!tbasexit) {
var line = sys.read().trim()
@@ -4258,5 +4284,3 @@ while (!tbasexit) {
println(prompt)
}
}
0

3157
assets/bios/basic_1.js Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

28
buildapp/build_app_linux_arm.sh Executable file
View File

@@ -0,0 +1,28 @@
#!/bin/bash
cd "${0%/*}"
APPIMAGETOOL="appimagetool-x86_64.AppImage"
SRCFILES="tbaslinux_arm"
DESTDIR="TerranBASIC_linux.arm"
RUNTIME="runtime-linux-arm"
# Cleanup
rm -rf $DESTDIR || true
mkdir $DESTDIR
# Prepare an application
cp icns.png $DESTDIR/icns.png
cp $SRCFILES/TerranBASIC.desktop $DESTDIR/
cp $SRCFILES/AppRun $DESTDIR/AppRun
chmod +x $DESTDIR/AppRun
# Copy over a Java runtime
cp -r "../out/$RUNTIME" $DESTDIR/
# Copy over all the assets and a jarfile
cp -r "../out/TerranBASIC.jar" $DESTDIR/
# Pack everything to AppImage
"./$APPIMAGETOOL" $DESTDIR "out/$DESTDIR.AppImage" || { echo 'Building AppImage failed' >&2; exit 1; }
chmod +x "out/$DESTDIR.AppImage"
rm -rf $DESTDIR || true
echo "Build successful: $DESTDIR"

28
buildapp/build_app_linux_x86.sh Executable file
View File

@@ -0,0 +1,28 @@
#!/bin/bash
cd "${0%/*}"
APPIMAGETOOL="appimagetool-x86_64.AppImage"
SRCFILES="tbaslinux_x86"
DESTDIR="TerranBASIC_linux.x86"
RUNTIME="runtime-linux-x86"
# Cleanup
rm -rf $DESTDIR || true
mkdir $DESTDIR
# Prepare an application
cp icns.png $DESTDIR/icns.png
cp $SRCFILES/TerranBASIC.desktop $DESTDIR/
cp $SRCFILES/AppRun $DESTDIR/AppRun
chmod +x $DESTDIR/AppRun
# Copy over a Java runtime
cp -r "../out/$RUNTIME" $DESTDIR/
# Copy over all the assets and a jarfile
cp -r "../out/TerranBASIC.jar" $DESTDIR/
# Pack everything to AppImage
"./$APPIMAGETOOL" $DESTDIR "out/$DESTDIR.AppImage" || { echo 'Building AppImage failed' >&2; exit 1; }
chmod +x "out/$DESTDIR.AppImage"
rm -rf $DESTDIR || true
echo "Build successful: $DESTDIR"

24
buildapp/build_app_mac_arm.sh Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/bash
cd "${0%/*}"
SRCFILES="tbasmac_arm"
DESTDIR="out/TerranBASIC_macOS.arm.app"
RUNTIME="runtime-osx-arm"
# Cleanup
rm -rf $DESTDIR || true
mkdir $DESTDIR
mkdir $DESTDIR/Contents
mkdir $DESTDIR/Contents/MacOS
# Prepare an application
cp icns.png $DESTDIR/.icns
cp $SRCFILES/Info.plist $DESTDIR/Contents/
cp $SRCFILES/TerranBASIC.sh $DESTDIR/Contents/MacOS/
chmod +x $DESTDIR/Contents/MacOS/TerranBASIC.sh
# Copy over a Java runtime
cp -r "../out/$RUNTIME" $DESTDIR/Contents/MacOS/
# Copy over all the assets and a jarfile
cp -r "../out/TerranBASIC.jar" $DESTDIR/Contents/MacOS/
echo "Build successful: $DESTDIR"

24
buildapp/build_app_mac_x86.sh Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/bash
cd "${0%/*}"
SRCFILES="tbasmac_x86"
DESTDIR="out/TerranBASIC_macOS.x86.app"
RUNTIME="runtime-osx-x86"
# Cleanup
rm -rf $DESTDIR || true
mkdir $DESTDIR
mkdir $DESTDIR/Contents
mkdir $DESTDIR/Contents/MacOS
# Prepare an application
cp icns.png $DESTDIR/.icns
cp $SRCFILES/Info.plist $DESTDIR/Contents/
cp $SRCFILES/TerranBASIC.sh $DESTDIR/Contents/MacOS/
chmod +x $DESTDIR/Contents/MacOS/TerranBASIC.sh
# Copy over a Java runtime
cp -r "../out/$RUNTIME" $DESTDIR/Contents/MacOS/
# Copy over all the assets and a jarfile
cp -r "../out/TerranBASIC.jar" $DESTDIR/Contents/MacOS/
echo "Build successful: $DESTDIR"

View File

@@ -0,0 +1,23 @@
#!/bin/bash
cd "${0%/*}"
SRCFILES="tbaswindows_x86"
DESTDIR="TerranBASIC_windows.x86.exe"
RUNTIME="runtime-windows-x86"
# Cleanup
rm -rf $DESTDIR || true
mkdir $DESTDIR
# Prepare an application
cp $SRCFILES/TerranBASIC.bat $DESTDIR/
# Copy over a Java runtime
cp -r "../out/$RUNTIME" $DESTDIR/
# Copy over all the assets and a jarfile
cp -r "../out/TerranBASIC.jar" $DESTDIR/
# Temporary solution: zip everything
zip -r -9 -l "out/$DESTDIR.zip" $DESTDIR
rm -rf $DESTDIR || true
echo "Build successful: $DESTDIR"

BIN
buildapp/icns.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

61
buildapp/instructions.md Normal file
View File

@@ -0,0 +1,61 @@
### Preparation
Download and unzip the JDKs to ~/Documents/openjdk/* for the appropriate operating systems first! JDKs can be downloaded on https://jdk.java.net/archive/.
The filenames must be:
| Target OS/Arch | filename |
|---------------------|--------------------|
| Linux AMD64 | jdk-17.0.1-x86 |
| Linux Aarch64 | jdk-17.0.1-arm |
| Windows AMD64 | jdk-17.0.1-windows |
| macOS Apple Silicon | jdk-17.0.1.jdk-arm |
| macOS Intel | jdk-17.0.1.jdk-x86 |
Then, on the terminal, run following commands:
```
jlink --module-path ~/Documents/openjdk/jdk-17.0.1-x86/jmods:mods --add-modules java.base,java.desktop,java.logging,java.scripting,jdk.unsupported --output ~/Documents/Terrarum/out/runtime-linux-x86 --no-header-files --no-man-pages --strip-debug --compress=2
jlink --module-path ~/Documents/openjdk/jdk-17.0.1-arm/jmods:mods --add-modules java.base,java.desktop,java.logging,java.scripting,jdk.unsupported --output ~/Documents/Terrarum/out/runtime-linux-arm --no-header-files --no-man-pages --strip-debug --compress=2
jlink --module-path ~/Documents/openjdk/jdk-17.0.1-windows/jmods:mods --add-modules java.base,java.desktop,java.logging,java.scripting,jdk.unsupported --output ~/Documents/Terrarum/out/runtime-windows-x86 --no-header-files --no-man-pages --strip-debug --compress=2
jlink --module-path ~/Documents/openjdk/jdk-17.0.1.jdk-arm/Contents/Home/jmods:mods --add-modules java.base,java.desktop,java.logging,java.scripting,jdk.unsupported --output ~/Documents/Terrarum/out/runtime-osx-arm --no-header-files --no-man-pages --strip-debug --compress=2
jlink --module-path ~/Documents/openjdk/jdk-17.0.1.jdk-x86/Contents/Home/jmods:mods --add-modules java.base,java.desktop,java.logging,java.scripting,jdk.unsupported --output ~/Documents/Terrarum/out/runtime-osx-x86 --no-header-files --no-man-pages --strip-debug --compress=2
```
(note: matching the building machine with the target OS is highly recommended -- Use Linux for building linux x86/arm; Mac for building macOS x86/arm; Windows for building Windows Java Runtime)
This process assumes that the game does NOT use the Java 9+ modules and every single required libraries are fat-jar'd (their contents extracted right into the Jar)
### Packaging
Create an output directory if there is none (project root/buildapp/out)
Before running the packaging script make sure:
1. The required runtime must exist on `(project root)/out/runtime-<linux|osx|windows>-<arm|x86>` directory
2. The build scripts are on a subdirectory of the project directory
To build, **cd into the "(project root)/buildapp/", then execute the appropriate script**.
The packaged application can be found on `(project root)/buildapp/out/`
#### OSX .app Packaging
```
Terrarum.*.app
+.icns /* 512x512 PNG */
+Contents
`Info.plist
+MacOS
`start_game_mac_*.sh * permission: +x */
```
`assets/TerrarumBuild.jar` is the artifact built using the TerrarumBuild.
`start_game_*` files are on the root directory of the project; use them to build executable apps.
Hide the `.jar` within the subdirectory; users will think this file is the main executable and will try to execute it using whatever JVM they may (or may not) have.
### Notes to Terrarum Programmers
By self-containing everything in one file, it is not possible to modify the base game easily. Modloading scheme must be extended to load from mutable directory such as `%APPDATA%/Terrarum/mods`.

View File

@@ -0,0 +1,7 @@
You should be able to find following files here:
TerranBASIC_macOS.x86.app (a directory)
TerranBASIC_macOS.arm.app (a directory)
TerranBASIC_linux.x86.AppImage (an ELF executable)
TerranBASIC_linux.arm.AppImage (an ELF executable)
TerranBASIC_windows.x86.exe (a Windows executable)

3
buildapp/tbaslinux_arm/AppRun Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
cd "${0%/*}"
./runtime-linux-arm/bin/java -Xms128M -Xmx2G -Dswing.aatext=true -Dawt.useSystemAAFontSettings=lcd -jar ./TerranBASIC.jar

View File

@@ -0,0 +1,6 @@
[Desktop Entry]
Name=TerranBASIC
Exec=AppRun
Icon=icns
Type=Application
Categories=Game;

3
buildapp/tbaslinux_x86/AppRun Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
cd "${0%/*}"
./runtime-linux-x86/bin/java -Xms128M -Xmx2G -Dswing.aatext=true -Dawt.useSystemAAFontSettings=lcd -jar ./TerranBASIC.jar

View File

@@ -0,0 +1,6 @@
[Desktop Entry]
Name=TerranBASIC
Exec=AppRun
Icon=icns
Type=Application
Categories=Game;

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
<key>CFBundleExecutable</key><string>TerranBASIC.sh</string>
<key>CFBundleDisplayName</key><string>TerranBASIC</string>
<key>CFBundleName</key><string>TerranBASIC</string>
</dict></plist>

View File

@@ -0,0 +1,3 @@
#!/bin/bash
cd "${0%/*}"
./runtime-osx-arm/bin/java -XstartOnFirstThread -Xms128M -Xmx2G -jar ./TerranBASIC.jar

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
<key>CFBundleExecutable</key><string>TerranBASIC.sh</string>
<key>CFBundleDisplayName</key><string>TerranBASIC</string>
<key>CFBundleName</key><string>TerranBASIC</string>
</dict></plist>

View File

@@ -0,0 +1,3 @@
#!/bin/bash
cd "${0%/*}"
./runtime-osx-x86/bin/java -XstartOnFirstThread -Xms128M -Xmx2G -jar ./TerranBASIC.jar

View File

@@ -0,0 +1,2 @@
cd /D "%~dp0"
.\runtime-windows-x86\bin\java -Xms128M -Xmx2G -jar .\TerranBASIC.jar

View File

@@ -78,9 +78,8 @@ object VMRunnerFactory {
bind.putMember("audio", AudioJSR223Delegate(vm))
bind.putMember("parallel", ringOneParallel)
val fr = FileReader("$assetsRoot/JS_INIT.js")
val prg = fr.readText()
fr.close()
val fr = this::class.java.classLoader.getResourceAsStream("net/torvald/tsvm/JS_INIT.js")
val prg = fr.readAllBytes().decodeToString()
context.eval("js", sanitiseJS(prg))
}

View File

@@ -1,6 +1,7 @@
package net.torvald.tsvm.peripheral
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.files.FileHandle
import com.badlogic.gdx.graphics.*
import com.badlogic.gdx.graphics.g2d.Gdx2DPixmap
import com.badlogic.gdx.graphics.g2d.SpriteBatch
@@ -77,7 +78,15 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
val channel = it % 4
rgba.shr((3 - channel) * 8).and(255) / 255f
}
protected fun getOriginalChrrom() = Pixmap(Gdx2DPixmap(Gdx.files.internal("$assetsRoot/"+config.chrRomPath).read(), Gdx2DPixmap.GDX2D_FORMAT_RGBA8888))
protected fun getOriginalChrrom(): Pixmap {
fun getFileHandle(): FileHandle =
if (config.chrRomPath.isEmpty())
Gdx.files.classpath("net/torvald/tsvm/rom/FontROM7x14.png")
else
Gdx.files.internal("$assetsRoot/"+config.chrRomPath)
return Pixmap(Gdx2DPixmap(getFileHandle().read(), Gdx2DPixmap.GDX2D_FORMAT_RGBA8888))
}
protected lateinit var chrrom: Pixmap
protected var chrrom0 = Texture(1,1,Pixmap.Format.RGBA8888)
protected val faketex: Texture
@@ -1919,16 +1928,16 @@ void main() {
val DEFAULT_CONFIG_COLOR_CRT = AdapterConfig(
"crt_color",
560, 448, 80, 32, 253, 255, 256.kB(), "FontROM7x14.png", 0.32f, TEXT_TILING_SHADER_COLOUR
560, 448, 80, 32, 253, 255, 256.kB(), "", 0.32f, TEXT_TILING_SHADER_COLOUR
)
val DEFAULT_CONFIG_PMLCD = AdapterConfig(
"pmlcd_inverted",
560, 448, 80, 32, 253, 255, 256.kB(), "FontROM7x14.png", 0.64f, TEXT_TILING_SHADER_LCD, DRAW_SHADER_FRAG_LCD
560, 448, 80, 32, 253, 255, 256.kB(), "", 0.64f, TEXT_TILING_SHADER_LCD, DRAW_SHADER_FRAG_LCD
)
val DEFAULT_CONFIG_FOR_TESTING = AdapterConfig(
"crt_color",
560, 448, 80, 32, 253, 255, 256.kB(), "FontROM7x14.png", 0f, TEXT_TILING_SHADER_COLOUR
560, 448, 80, 32, 253, 255, 256.kB(), "", 0f, TEXT_TILING_SHADER_COLOUR
)

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB