OXYGENHUB
◆ main openmsx / Contrib / omsxctl / omsxctl.tcl
2.4 KiB · Tcl · last changed chore(): initial commit 1 month ago source blame history raw
e8555c89 Andy McCall 1
# omsxctl -- execute openMSX commands from within an MSX program
2
#
3
# This script should NOT be installed in the ~/.openmsx/share/scripts directory
4
# (because you don't want it to be active every time you start openMSX). Instead
5
# you should activate it via the openMSX command line with the option '-script
6
# omsxctl.tcl'.
7
#
8
# Typically used in combination with the MSX-DOS 'omsxctl.com' utility.
9
#
10
# But can also be used from any other MSX program with a code snippet like
11
# this:
12
#   ld   hl,command    ; pointer to the to be executed command
13
#   ld   de,result     ; the result of the command is written here
14
#   ld   bc,resultSize ; size of the result buffer (set to 0 if result is not needed)
15
#   out  (#2d),a       ; the value of A doesn't matter
16
#   jp   c,error       ; carry-flag set if there was an error executing the command
17
#                      ; BC is set to the actual length of the result string,
18
#                      ; or set to 0xffff when the result buffer was too small,
19
#                      ; in that case the result is still written to [DE] but truncated.
20
#
21
# Limitations:
22
#  Strings containing characters >=128 are not handled well:
23
#  - For passing the command string from the MSX to openMSX this could be
24
#    fixed (but is it worth it?).
25
#  - For passing the result from openMSX to the MSX I currently don't see a
26
#    solution that handles both arbitrary utf-8 strings and binary data (e.g.
27
#    created via the 'binary format' Tcl command). The current implementation
28
#    chooses to handle binary data (and of course pure ASCII strings work fine
29
#    as well).
30
31
proc trigger_omsxctl {} {
32
    # Read the command string from memory.
33
    set hl [reg HL]
34
    set cmd ""
35
    while 1 {
36
        set c [peek $hl]
37
        incr hl
38
        if {$c == 0} break
39
        append cmd [binary format c $c]
40
    }
41
42
    # Execute the command.
43
    set err [catch [list uplevel #0 $cmd] result]
44
45
    # Write the error status to the carry flag.
46
    reg F [expr {([reg F] & 0xfe) | $err}]
47
48
    # Write the result back to memory.
49
    set len [string length $result]
50
    set de [reg DE]
51
    set bc [reg BC]
52
    for {set i 0} {$i < $bc && $i < $len} {incr i} {
53
        binary scan [string index $result $i] c c
54
        poke [expr {$de + $i}] $c
55
    }
56
57
    # Write the actual result-length to BC.
58
    reg BC [expr {($len <= $bc) ? $len : 0xffff}]
59
}
60
61
# Register callback on write to IO-port 0x2d.
62
debug set_watchpoint write_io 0x2d 1 trigger_omsxctl