From 4db4a5f1b29ada4789c62f330d7189046106ac29 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 16 Mar 2024 20:58:45 +0100 Subject: [PATCH] vm: txt.width() and height() now return the actual console terminal width and height if possible. --- compiler/res/prog8lib/virtual/textio.p8 | 11 ++++- docs/source/todo.rst | 4 +- examples/test.p8 | 19 ++++----- examples/textelite.p8 | 53 +++++++++++++++---------- virtualmachine/src/prog8/vm/SysCalls.kt | 46 +++++++++++++++++---- 5 files changed, 89 insertions(+), 44 deletions(-) diff --git a/compiler/res/prog8lib/virtual/textio.p8 b/compiler/res/prog8lib/virtual/textio.p8 index 00d551430..f7148d3b9 100644 --- a/compiler/res/prog8lib/virtual/textio.p8 +++ b/compiler/res/prog8lib/virtual/textio.p8 @@ -6,11 +6,18 @@ txt { sub width() -> ubyte { - return 80 ; just some chosen value for the 'width' of the console + %ir {{ + syscall 62 (): r0.w + returnr.b r0 + }} } sub height() -> ubyte { - return 30 ; just some chosen value for the 'height' of the console + %ir {{ + syscall 62 (): r0.w + msig.b r1,r0 + returnr.b r1 + }} } sub clear_screen() { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 4a9d5da73..5485488c1 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,9 +1,9 @@ TODO ==== -vm textelite: after 1 galaxy jump: galaxy map shows wrong planet name if you first print local area map. local map is wrong too (secnd time it's okay). +fix ubyte width = text.width() text.width() gets removed as 'unused subroutine' -vm: textio.width and height should return the real console width and height. +vm textelite: after 1 galaxy jump: galaxy maps shows wrong planet name until you redraw them a second time. Current planet name changes when showing maps and asking planet i)nfo! ... diff --git a/examples/test.p8 b/examples/test.p8 index 952344108..f3f7daa32 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,19 +1,16 @@ -%import textio %zeropage basicsafe %option no_sysinit - main { + ubyte tw = text.width() sub start() { - txt.print("hello, world!") - ubyte col = txt.get_column() - ubyte row = txt.get_row() - txt.row(10) - txt.print("row 10") - txt.column(2) - txt.print("col 2") - txt.plot(0, 18) + tw++ } } - +text { + sub width() -> ubyte { + cx16.r0++ + return 80 + } +} diff --git a/examples/textelite.p8 b/examples/textelite.p8 index 09308cbd1..2d04f6bef 100644 --- a/examples/textelite.p8 +++ b/examples/textelite.p8 @@ -8,7 +8,7 @@ ; Prog8 adaptation of the Text-Elite galaxy system trading simulation engine. ; Original C-version obtained from: http://www.elitehomepage.org/text/index.htm -; Note: this program can be compiled for multiple target systems. +; Note: this program can be compiled for multiple target systems, including the virtual machine. main { @@ -16,11 +16,13 @@ main { const ubyte numforZaonce = 129 const ubyte numforDiso = 147 const ubyte numforRiedquat = 46 + ubyte terminal_width sub start() { + terminal_width = txt.width() txt.lowercase() txt.clear_screen() - txt.print("\n --- TextElite v1.2 ---\n") + txt.print("\n --- TextElite v1.3 ---\n") planet.set_seed(0, 0) galaxy.travel_to(1, numforLave) @@ -84,7 +86,7 @@ trader { sub do_load() { txt.print("\nLoading universe...") - if diskio.load(Savegame, &savedata)!=0 { + if diskio.load(Savegame, &savedata)==&savedata+sizeof(savedata) { txt.print("ok\n") } else { txt.print("\ni/o error: ") @@ -493,16 +495,6 @@ galaxy { ubyte py = planet.y str current_name = " " ; 8 max ubyte pn = 0 - ubyte scaling_x = 8 - ubyte scaling_y = 16 - if local { - scaling_x = 2 - scaling_y = 4 - } - if txt.width() > 60 { - scaling_x /= 2 - scaling_y /= 2 - } current_name = planet.name init(number) @@ -533,10 +525,8 @@ galaxy { tx = tx + 24 - px ty = ty + 24 - py } - tx /= scaling_x - ty /= scaling_y - ubyte sx = lsb(tx) - ubyte sy = lsb(ty) + ubyte sx = display_scale_x(tx) + ubyte sy = display_scale_y(ty) ubyte char = '*' if planet.number==current_planet char = '%' @@ -555,11 +545,10 @@ galaxy { if not local print_planet_details(current_name, home_sx, home_sy, home_distance) - if txt.width() < 80 - txt.plot(0,20) + if local + txt.plot(0, display_scale_y(64) + 4) else - txt.plot(0,36) - + txt.plot(0, display_scale_y(256) + 4 as ubyte) travel_to(number, current_planet) sub print_planet_details(str name, ubyte screenx, ubyte screeny, ubyte d) { @@ -571,6 +560,28 @@ galaxy { txt.print(" LY") } } + + sub display_scale_x(uword x) -> ubyte { + if main.terminal_width > 64 { + if local + return x as ubyte + return x/4 as ubyte + } + if local + return x/2 as ubyte + return x/8 as ubyte + } + + sub display_scale_y(uword y) -> ubyte { + if main.terminal_width > 64 { + if local + return y/2 as ubyte + return y/8 as ubyte + } + if local + return y/4 as ubyte + return y/16 as ubyte + } } ubyte pn_pair1 diff --git a/virtualmachine/src/prog8/vm/SysCalls.kt b/virtualmachine/src/prog8/vm/SysCalls.kt index 141c56838..e5542b5be 100644 --- a/virtualmachine/src/prog8/vm/SysCalls.kt +++ b/virtualmachine/src/prog8/vm/SysCalls.kt @@ -72,6 +72,7 @@ SYSCALLS: 59 = delete 60 = rename 61 = directory +62 = getconsolesize */ enum class Syscall { @@ -136,7 +137,8 @@ enum class Syscall { SAVE, DELETE, RENAME, - DIRECTORY + DIRECTORY, + GETGONSOLESIZE ; companion object { @@ -644,9 +646,9 @@ object SysCalls { for (i in 0.. { @@ -658,9 +660,9 @@ object SysCalls { for (i in 0.. { @@ -686,10 +688,10 @@ object SysCalls { } val filename = vm.memory.getString((filenamePtr as UShort).toInt()) if (File(filename).exists()) - vm.registers.setUB(0, 0u) + returnValue(callspec.returns!!, 0u, vm) else { File(filename).writeBytes(data) - vm.registers.setUB(0, 1u) + returnValue(callspec.returns!!, 1u, vm) } } Syscall.DELETE -> { @@ -710,7 +712,35 @@ object SysCalls { directory.listDirectoryEntries().sorted().forEach { println("${it.toFile().length()}\t${it.normalize()}") } - vm.registers.setUB(0, 1u) + returnValue(callspec.returns!!, 1u, vm) + } + Syscall.GETGONSOLESIZE -> { + // no arguments + if(System.console()==null) { + return returnValue(callspec.returns!!, 30*256 + 80, vm) // just return some defaults in this case 80*30 + } + + val linesS = System.getenv("LINES") + val columnsS = System.getenv("COLUMNS") + if(linesS!=null && columnsS!=null) { + val lines = linesS.toInt() + val columns = columnsS.toInt() + return returnValue(callspec.returns!!, lines*256 + columns, vm) + } + + try { + val process = ProcessBuilder("tput", "cols", "lines").inheritIO().redirectOutput(ProcessBuilder.Redirect.PIPE).start() + val result=process.waitFor() + if (result == 0) { + val response = process.inputStream.bufferedReader().lineSequence().iterator() + val width = response.next().toInt() + val height = response.next().toInt() + return returnValue(callspec.returns!!, height*256 + width, vm) + } + } catch (x: Exception) { + // dunno what happened... + } + return returnValue(callspec.returns!!, 30*256 + 80, vm) // just return some defaults in this case 80*30 } } }