From ad3f5e0bc44c39f5c77152c0754e053643714552 Mon Sep 17 00:00:00 2001 From: Willem Date: Wed, 23 Dec 2020 18:55:56 +0100 Subject: [PATCH] Initial poc setup --- Cargo.lock | 371 ++++++++++++++++++++++ Cargo.toml | 13 + Makefile | 30 ++ Makelocal.mk.tpl | 8 + README.md | 25 +- src/drivers/0module.mk | 51 +++ src/drivers/drv-midi.asm | 66 ++++ src/drivers/drv-tcpip.asm | 356 +++++++++++++++++++++ src/drivers/drv-unapi.asm | 320 +++++++++++++++++++ src/drivers/mmi-1205.asm | 49 +++ src/drivers/mmi-fac.asm | 71 +++++ src/drivers/mmi-mext.asm | 14 + src/drivers/mmi-mint.asm | 14 + src/mmidrv/0module.mk | 57 ++++ src/mmidrv/mmidrv.asm | 413 +++++++++++++++++++++++++ src/mmidrv/mmidrv.asm.org | 630 ++++++++++++++++++++++++++++++++++++++ src/mmigate/0module.mk | 10 + src/mmigate/main.rs | 200 ++++++++++++ tmp/hget.com | Bin 0 -> 21163 bytes tmp/inl.com | Bin 0 -> 24922 bytes tmp/ping.com | Bin 0 -> 2301 bytes tmp/ramhelpr.com | Bin 0 -> 1854 bytes 22 files changed, 2696 insertions(+), 2 deletions(-) create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 Makefile create mode 100644 Makelocal.mk.tpl create mode 100644 src/drivers/0module.mk create mode 100644 src/drivers/drv-midi.asm create mode 100644 src/drivers/drv-tcpip.asm create mode 100644 src/drivers/drv-unapi.asm create mode 100644 src/drivers/mmi-1205.asm create mode 100644 src/drivers/mmi-fac.asm create mode 100644 src/drivers/mmi-mext.asm create mode 100644 src/drivers/mmi-mint.asm create mode 100644 src/mmidrv/0module.mk create mode 100644 src/mmidrv/mmidrv.asm create mode 100644 src/mmidrv/mmidrv.asm.org create mode 100644 src/mmigate/0module.mk create mode 100644 src/mmigate/main.rs create mode 100644 tmp/hget.com create mode 100644 tmp/inl.com create mode 100644 tmp/ping.com create mode 100644 tmp/ramhelpr.com diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..3e10ed1 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,371 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "alsa" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "alsa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "alsa-sys" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "atty" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bitflags" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bitflags" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clap" +version = "2.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "core-foundation" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "core-foundation-sys" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "coremidi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "coremidi-sys 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "coremidi-sys" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "heck" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.2.51" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memalloc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "midir" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "alsa 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "coremidi 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "memalloc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winmm-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mmigate" +version = "0.0.1" +dependencies = [ + "midir 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nix" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "numtoa" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pkg-config" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.54" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "redox_termios" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "structopt" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "structopt-derive" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.15.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termion" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "time" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-segmentation" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-width" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "vec_map" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winmm-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum alsa 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fd5a75e70d45a943d2a0a818277e71d6ff777e97358529d6b460d3d4c4d0745" +"checksum alsa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0edcbbf9ef68f15ae1b620f722180b82a98b6f0628d30baa6b8d2a5abc87d58" +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" +"checksum bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c" +"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" +"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" +"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +"checksum core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67" +"checksum core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "065a5d7ffdcbc8fa145d6f0746f3555025b9097a9e9cda59f7467abae670c78d" +"checksum coremidi 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae2b8d4679b3a2a92b843d4c8e4a721be038ce49fce701c46296b2713f24c814" +"checksum coremidi-sys 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "07f05827cebb30dcd539ff1ac9bf6764f574a15fa147f8572f99d7617142f95e" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +"checksum libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "bedcc7a809076656486ffe045abeeac163da1b558e963a31e29fbfbeba916917" +"checksum memalloc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df39d232f5c40b0891c10216992c2f250c054105cb1e56f0fc9032db6203ecc1" +"checksum midir 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e653b919aca8b5f2697854f1819b33bfe49bcb3378abb0dbd834ce43ede9c7b1" +"checksum nix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2c5afeb0198ec7be8569d666644b574345aad2e95a53baf3a532da3e0f3fb32" +"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" +"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" +"checksum proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)" = "ba92c84f814b3f9a44c5cfca7d2ad77fa10710867d2bbb1b3d175ab5f47daa12" +"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" +"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" +"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +"checksum structopt 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "3d0760c312538987d363c36c42339b55f5ee176ea8808bbe4543d484a291c8d1" +"checksum structopt-derive 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "528aeb7351d042e6ffbc2a6fb76a86f9b622fdf7c25932798e7a82cb03bc94c6" +"checksum syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)" = "846620ec526c1599c070eff393bfeeeb88a93afa2513fc3b49f1fea84cf7b0ed" +"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea" +"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" +"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum winmm-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "20a57a816b63ca4bf31aec70b4c334be13c4b73a30ab5b546135041627866035" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..7714b33 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "mmigate" +description = "Msx Midi Internet Gateway" +version = "0.0.1" +authors = [ "Willem Cazander" ] + +[dependencies] +structopt = "0.2" +midir = "0.5.0" + +[[bin]] +name = "mmigate" +path = "src/mmigate/main.rs" \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..826956c --- /dev/null +++ b/Makefile @@ -0,0 +1,30 @@ +# +# Top level makefile for tara +# + +rwildcard = $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)) +INC_MODS := $(call rwildcard, src, */0module.mk) +PATH_BIN := bin +PATH_SRC := src +BUILD_ALL := "Use 'make help' for possible targets." +BUILD_HELP := "Use one of the following build targets;" +MB_OPENMSX_EXTS += -ext FAC_MIDI_Interface +#MB_OPENMSX_EXTS += -ext Philips_NMS_1205 + +.SUFFIXES: +.PHONY: all +all: + @echo $(BUILD_ALL) + +BUILD_HELP += \\n\\t* help +.PHONY: help +help: + @echo $(BUILD_HELP) + +.PHONY: clean +clean: + $(call mb_clean,$(PATH_BIN)) + +-include Makelocal.mk +include $(PATH_MSXBUILD)/lib/make/msxbuild.mk +include $(INC_MODS) diff --git a/Makelocal.mk.tpl b/Makelocal.mk.tpl new file mode 100644 index 0000000..356c4cc --- /dev/null +++ b/Makelocal.mk.tpl @@ -0,0 +1,8 @@ +# Local included makefile fragment. +# Save this file without tpl suffix and custumize it. +# +# Change to local installations if needed; + +#PATH_SDCC ?= /usr/bin +#PATH_OPENMSX ?= /opt/openMSX/bin/ +#PATH_MSXBUILD ?= /opt/msxbuild diff --git a/README.md b/README.md index 203c2f0..5db85fc 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,24 @@ -# mmigate -Msx Midi Internet Gateway \ No newline at end of file +### MMIGATE + +Msx Midi Internet Gateway + +NOTE: Proof of concept no working code here... + +## Running + +make test-mmidrv + +note: requires working openmsx with 8250+ide roms. + +## Compile dist + +make bin/dist.tar.gz + + +set prompt=on +set date=dd/mm/yy +set path=c:\;c:\msxdos;c:\utils;..;. +ntsc +doskey +ver \ No newline at end of file diff --git a/src/drivers/0module.mk b/src/drivers/0module.mk new file mode 100644 index 0000000..0b81fe4 --- /dev/null +++ b/src/drivers/0module.mk @@ -0,0 +1,51 @@ + +DRIVERS_NAME := drivers +DRIVERS_SRC := $(PATH_SRC)/$(DRIVERS_NAME) +DRIVERS_BIN := $(PATH_BIN)/$(DRIVERS_NAME) +DRIVERS_DEP := $(DRIVERS_SRC)/drv-unapi.asm $(DRIVERS_SRC)/drv-tcpip.asm $(DRIVERS_SRC)/drv-midi.asm +BUILD_HELP += \\n\\t* $(DRIVERS_BIN)/mmi-fac.dat\\n\\t* $(DRIVERS_BIN)/mmi-1205.dat\\n\\t* $(DRIVERS_BIN)/mmi-mint.dat\\n\\t* $(DRIVERS_BIN)/mmi-mext.dat + +$(DRIVERS_BIN): + $(call mb_mkdir,$(DRIVERS_BIN)) + + +$(DRIVERS_BIN)/mmi-fac.rel: $(DRIVERS_SRC)/mmi-fac.asm $(DRIVERS_DEP) | $(DRIVERS_BIN) + $(call mb_compile_asm,$@,$<) + +$(DRIVERS_BIN)/mmi-fac.hex: $(DRIVERS_BIN)/mmi-fac.rel + $(call mb_link_asm_4000,$(DRIVERS_BIN)/mmi-fac.hex,$(DRIVERS_BIN)/mmi-fac.rel) + +$(DRIVERS_BIN)/mmi-fac.dat: $(DRIVERS_BIN)/mmi-fac.hex + $(call mb_hex2dat,$(DRIVERS_BIN)/mmi-fac.hex,$(DRIVERS_BIN)/mmi-fac.dat) + + +$(DRIVERS_BIN)/mmi-1205.rel: $(DRIVERS_SRC)/mmi-1205.asm $(DRIVERS_DEP) | $(DRIVERS_BIN) + $(call mb_compile_asm,$@,$<) + +$(DRIVERS_BIN)/mmi-1205.hex: $(DRIVERS_BIN)/mmi-1205.rel + $(call mb_link_asm_4000,$(DRIVERS_BIN)/mmi-1205.hex,$(DRIVERS_BIN)/mmi-1205.rel) + +$(DRIVERS_BIN)/mmi-1205.dat: $(DRIVERS_BIN)/mmi-1205.hex + $(call mb_hex2dat,$(DRIVERS_BIN)/mmi-1205.hex,$(DRIVERS_BIN)/mmi-1205.dat) + + +$(DRIVERS_BIN)/mmi-mint.rel: $(DRIVERS_SRC)/mmi-mint.asm $(DRIVERS_DEP) | $(DRIVERS_BIN) + $(call mb_compile_asm,$@,$<) + +$(DRIVERS_BIN)/mmi-mint.hex: $(DRIVERS_BIN)/mmi-mint.rel + $(call mb_link_asm_4000,$(DRIVERS_BIN)/mmi-mint.hex,$(DRIVERS_BIN)/mmi-mint.rel) + +$(DRIVERS_BIN)/mmi-mint.dat: $(DRIVERS_BIN)/mmi-mint.hex + $(call mb_hex2dat,$(DRIVERS_BIN)/mmi-mint.hex,$(DRIVERS_BIN)/mmi-mint.dat) + + +$(DRIVERS_BIN)/mmi-mext.rel: $(DRIVERS_SRC)/mmi-mext.asm $(DRIVERS_DEP) | $(DRIVERS_BIN) + $(call mb_compile_asm,$@,$<) + +$(DRIVERS_BIN)/mmi-mext.hex: $(DRIVERS_BIN)/mmi-mext.rel + $(call mb_link_asm_4000,$(DRIVERS_BIN)/mmi-mext.hex,$(DRIVERS_BIN)/mmi-mext.rel) + +$(DRIVERS_BIN)/mmi-mext.dat: $(DRIVERS_BIN)/mmi-mext.hex + $(call mb_hex2dat,$(DRIVERS_BIN)/mmi-mext.hex,$(DRIVERS_BIN)/mmi-mext.dat) + +# EOF diff --git a/src/drivers/drv-midi.asm b/src/drivers/drv-midi.asm new file mode 100644 index 0000000..ca1b0af --- /dev/null +++ b/src/drivers/drv-midi.asm @@ -0,0 +1,66 @@ + +;--- 3. Error codes +ERR_OK .equ 0 ; Operation completed successfully +ERR_NOT_IMP .equ 1 ; Capability not implemented +ERR_NO_NETWORK .equ 2 ; No network connection available +ERR_NO_DATA .equ 3 ; No incoming data available +ERR_INV_PARAM .equ 4 ; Invalid input parameter +ERR_QUERY_EXISTS .equ 5 ; Another query is already in progress +ERR_INV_IP .equ 6 ; Invalid IP address +ERR_NO_DNS .equ 7 ; No DNS servers are configured +ERR_DNS .equ 8 ; Error returned by DNS server +ERR_NO_FREE_CONN .equ 9 ; No free connections available +ERR_CONN_EXISTS .equ 10 ; Connection already exists +ERR_NO_CONN .equ 11 ; Connection does not exists +ERR_CONN_STATE .equ 12 ; Invalid connection state +ERR_BUFFER .equ 13 ; Insufficient output buffer space +ERR_LARGE_DGRAM .equ 14 ; Datagram is too large +ERR_INV_OPER .equ 15 ; Invalid operation + +.macro RET_NO_IMPL + LD A,#ERR_NOT_IMP + RET +.endm + + + +.macro MIDI_TX_START function_number + LD A,#0xF0 ; SystemExclusive + MIDI_TX + LD A,#0xF1 ; SOX Send data + MIDI_TX + LD A,#function_number + MIDI_TX; ; if a=0xF7 then send F7 + F0 + F2 +.endm +.macro MIDI_TX_HL + LD A,H + MIDI_TX + LD A,L + MIDI_TX +.endm +.macro MIDI_TX_B + LD A,B + MIDI_TX +.endm +.macro MIDI_TX_END + LD A,#0xF7 ; End of SysEx + MIDI_TX +.endm +.macro MIDI_RX_START function_start + MIDI_RX + CP A + JR nz,#function_start + ;CALL #function_start +.endm +.macro MIDI_RX_A_PUSH + MIDI_RX + PUSH AF +.endm +.macro MIDI_RX_B + MIDI_RX + LD B,A +.endm +.macro MIDI_RX_END_POP + POP AF +.endm + diff --git a/src/drivers/drv-tcpip.asm b/src/drivers/drv-tcpip.asm new file mode 100644 index 0000000..90dd119 --- /dev/null +++ b/src/drivers/drv-tcpip.asm @@ -0,0 +1,356 @@ + + + + +;4.1.2. TCPIP_GET_CAPAB: Get information about the TCP/IP capabilities and features +;Input: A = 1 +; B = Index of information block to retrieve: +; 1: Capabilities and features flags, link level protocol +; 2: Connection pool size and status +; 3: Maximum datagram size allowed +;Output: A = Error code +; When information block 1 requested: +; HL = Capabilities flags +; DE = Features flags +; B = Link level protocol used +; When information block 2 requested: +; B = Maximum simultaneous TCP connections supported +; C = Maximum simultaneous UDP connections supported +; D = Free TCP connections currently available +; E = Free UDP connections currently available +; H = Maximum simultaneous raw IP connections supported +; L = Free raw IP connections currently available +; When information block 3 requested: +; HL = Maximum incoming datagram size supported +; DE = Maximum outgoing datagram size supported +TCPIP_GET_CAPAB: + MIDI_TX_START 1 + MIDI_TX_B + MIDI_TX_END + MIDI_RX_START #TCPIP_GET_CAPAB + MIDI_RX_A_PUSH + MIDI_RX_B + MIDI_RX_END_POP + RET + RET_NO_IMPL + +;4.1.3. TCPIP_GET_IPINFO: Get IP address +;Input: A = 2 +; B = Index of address to obtain: +; 1: Local IP address +; 2: Peer IP address +; 3: Subnet mask +; 4: Default gateway +; 5: Primary DNS server IP address +; 6: Secondary DNS server IP address +;Output: A = Error code +; L.H.E.D = Requested address +TCPIP_GET_IPINFO: + ret_no_impl + +;4.1.4. TCPIP_NET_STATE: Get network state +;Input: A = 3 +;Output: A = Error code +; B = Current network state: +; 0: Closed +; 1: Opening +; 2: Open +; 3: Closing +; 255: Unknown +TCPIP_NET_STATE: + ret_no_impl + +;4.2.1. TCPIP_SEND_ECHO: Send ICMP echo message (PING) +;Input: A = 4 +; HL = Address of echo parameters block +;Output: A = Error code +TCPIP_SEND_ECHO: + ret_no_impl + +;4.2.2. TCPIP_RCV_ECHO: Retrieve ICMP echo response message +;Input: A = 5 +; HL = Address for the echo parameters block +;Output: A = Error code +TCPIP_RCV_ECHO: + ret_no_impl + +;4.3.1. TCPIP_DNS_Q: Start a host name resolution query +;Input: A = 6 +; HL = Address of the host name to be resolved, zero terminated +; B = Flags, when set to 1 they instruct the resolver to: +; bit 0: Only abort the query currently in progress, if there is any +; (other flags and registers are then ignored) +; bit 1: Assume that the passed name is an IP address, +; and return an error if this is not true +; bit 2: If there is a query in progress already, +; do NOT abort it and return an error instead +;Output: A = Error code +; B = 0 if a query to a DNS server is in progress +; 1 if the name represented an IP address +; 2 if the name could be resolved locally +; L.H.E.D = Resolved IP address +; (only if no error occurred and B=1 or 2 is returned) +TCPIP_DNS_Q: + ret_no_impl + +;4.3.2. TCPIP_DNS_S: Obtains the host name resolution process state and result +;Input: A = 7 +; B = Flags, when set to 1 they instruct the resolver to: +; bit 0: Clear any existing result or error condition after the execution +; (except if there is a query in progress) +;Output: A = Error code +; B = DNS error code (when error is ERR_DNS) +; B = Current query status (when error is ERR_OK): +; 0: There is no query in progress, nor any result nor error code available +; 1: There is a query in progress +; 2: Query is complete +; C = Current query substatus (when error is ERR_OK and B=1): +; 0: Unknown +; 1: Querying the primary DNS server +; 2: Querying the secondary DNS server +; 3: Querying another DNS server +; C = Resolution proces type (when error is ERR_OK and B=2): +; 0: The name was obtained by querying a DNS server +; 1: The name was a direct representation of an IP address +; 2: The name was resolved locally +; L.H.E.D = Resolved IP address (when error is ERR_OK and B=2) +TCPIP_DNS_S: + ret_no_impl + +;4.4.1. TCPIP_UDP_OPEN: Open a UDP connection +;Input: A = 8 +; HL = Local port number (0FFFFh: random port) +; B = Intended connection lifetime: +; 0: Transient +; 1: Resident +;Output: A = Error code +; B = Connection number +TCPIP_UDP_OPEN: + MIDI_TX_START 8 + MIDI_TX_HL + MIDI_TX_B + MIDI_TX_END + MIDI_RX_START #TCPIP_UDP_OPEN + MIDI_RX_A_PUSH + MIDI_RX_B + MIDI_RX_END_POP + RET + +;4.4.2. TCPIP_UDP_CLOSE: Close a UDP connection +;Input: A = 9 +; B = Connection number +; 0 to close all open transient UDP connections +;Output: A = Error code +TCPIP_UDP_CLOSE: + ret_no_impl + +;4.4.3. TCPIP_UDP_STATE: Get the state of a UDP connection +;Input: A = 10 +; B = Connection number +;Output: A = Error code +; HL = Local port number +; B = Number of pending incoming datagrams +; DE = Size of oldest pending incoming datagram (data part only) +TCPIP_UDP_STATE: + ret_no_impl + +;4.4.4. TCPIP_UDP_SEND: Send an UDP datagram +;Input: A = 11 +; B = Connection number +; HL = Address of datagram data +; DE = Address of parameters block +;Output: A = Error code +TCPIP_UDP_SEND: + ret_no_impl + +;4.4.5. TCPIP_UDP_RCV: Retrieve an incoming UDP datagram +;Input: A = 12 +; B = Connection number +; HL = Address for datagram data +; DE = Maximum data size to retrieve +;Output: A = Error code +; L.H.E.D = Source IP address +; IX = Source port +; BC = Actual received data size +TCPIP_UDP_RCV: + ret_no_impl + +;4.5.1. TCPIP_TCP_OPEN: Open a TCP connection +;Input: A = 13 +; HL = Address of parameters block +;Output: A = Error code +; B = Connection number +TCPIP_TCP_OPEN: + ret_no_impl + +;4.5.2. TCPIP_TCP_CLOSE: Close a TCP connection +;Input: A = 14 +; B = Connection number +; 0 to close all open transient TCP connections +;Output: A = Error code +TCPIP_TCP_CLOSE: + ret_no_impl + +;4.5.3. TCPIP_TCP_ABORT: Abort a TCP connection +;Input: A = 15 +; B = Connection number +; 0 to abort all open transient TCP connections +;Output: A = Error code +TCPIP_TCP_ABORT: + ret_no_impl + +;4.5.4. TCPIP_TCP_STATE: Get the state of a TCP connection +;Input: A = 16 +; B = Connection number +; HL = Pointer in TPA for connection information block +; (0 if not needed) +;Output: A = Error code +; B = Connection state +; C = Close reason (only if ERR_NO_CONN is returned) +; HL = Number of total available incoming bytes +; DE = Number of urgent available incoming bytes +; IX = Available free space in the output buffer +; (0FFFFh = infinite) +TCPIP_TCP_STATE: + ret_no_impl + +;4.5.5. TCPIP_TCP_SEND: Send data a TCP connection +;Input: A = 17 +; B = Connection number +; DE = Address of the data to be sent +; HL = Length of the data to be sent +; C = Flags: +; bit 0: Send the data PUSHed +; bit 1: The data is urgent +;Output: A = Error code +TCPIP_TCP_SEND: + ret_no_impl + +;4.5.6. TCPIP_TCP_RCV: Receive data from a TCP connection +;Input: A = 18 +; B = Connection number +; DE = Address for the retrieved data +; HL = Length of the data to be obtained +;Output: A = Error code +; BC = Total number of bytes that have been actually retrieved +; HL = Number of urgent data bytes that have been retrieved +; (placed at the beginning of the received data block) +TCPIP_TCP_RCV: + ret_no_impl + + +;4.5.7. TCPIP_TCP_FLUSH: Flush the output buffer of a TCP connection +;Input: A = 19 +; B = Connection number +;Output: A = Error code +TCPIP_TCP_FLUSH: + ret_no_impl + +;4.6.1. TCPIP_RAW_OPEN: Open a raw IP connection +;Input: A = 20 +; B = Transport protocol code +; C = Intended connection lifetime: +; 0: Transient +; 1: Resident +;Output: A = Error code +; B = Connection number +TCPIP_RAW_OPEN: + ret_no_impl + +;4.6.2. TCPIP_RAW_CLOSE: Close a raw IP connection +;Input: A = 21 +; B = Connection number +; 0 to close all open transient UDP connections +;Output: A = Error code +TCPIP_RAW_CLOSE: + ret_no_impl + +;4.6.3. TCPIP_RAW_STATE: Get the state of a raw IP connection +;Input: A = 22 +; B = Connection number +;Output: A = Error code +; B = Associated protocol code +; HL = Number of pending incoming datagrams +; DE = Size of the oldest pending incoming datagram +TCPIP_RAW_STATE: + ret_no_impl + +;4.6.4. TCPIP_RAW_SEND: Send a raw IP datagram +;Input: A = 23 +; B = Connection number +; HL = Address of datagram data +; DE = Address of parameters block +;Output: A = Error code +TCPIP_RAW_SEND: + ret_no_impl + +;4.6.5. TCPIP_RAW_RCV: Retrieve an incoming raw IP datagram +;Input: A = 24 +; B = Connection number +; HL = Address for datagram data +; DE = Maximum data size to retrieve +;Output: A = Error code +; L.H.E.D = Source IP address +; BC = Actual received data size +TCPIP_RAW_RCV: + ret_no_impl + +;4.7.1. TCPIP_CONFIG_AUTOIP: Enable or disable the automatic IP addresses retrieval +;Input: A = 25 +; B = 0: Get current configuration +; 1: Set configuration +; C = Configuration to set (only if B=1): +; bit 0: Set to automatically retrieve +; local IP address, subnet mask and default gateway +; bit 1: Set to automatically retrieve DNS servers addresses +; bits 2-7: Unused, must be zero +;Output: A = Error code +; C = Configuration after the routine execution +; (same format as C at input) +TCPIP_CONFIG_AUTOIP: + ret_no_impl + +;4.7.2. TCPIP_CONFIG_IP: Manually configure an IP address +;Input: A = 26 +; B = Index of address to set: +; 1: Local IP address +; 2: Peer IP address +; 3: Subnet mask +; 4: Default gateway +; 5: Primary DNS server IP address +; 6: Secondary DNS server IP address +; L.H.E.D = Address value +;Output: A = Error code +TCPIP_CONFIG_IP: + ret_no_impl + +;4.7.3. TCPIP_CONFIG_TTL: Get/set the value of TTL and TOS for outgoing datagrams +;Input: A = 27 +; B = 0: Get current values +; 1: Set values +; D = New value for TTL (only if B=1) +; E = New value for ToS (only if B=1) +;Output: A = Error code +; D = Value of TTL after the routine execution +; E = Value of ToS after the routine execution +TCPIP_CONFIG_TTL: + ret_no_impl + +;4.7.4. TCPIP_CONFIG_PING: Get/set the automatic PING reply flag +;Input: A = 28 +; B = 0: Get current flag value +; 1: Set flag value +; C = New flag value (only if B=1): +; 0: Off +; 1: On +;Output: A = Error code +; C = Flag value after the routine execution +TCPIP_CONFIG_PING: + ret_no_impl + +;4.8.1. TCPIP_WAIT: Wait for a processing step to run +;Input: A = 29 +;Output: A = Error code +TCPIP_WAIT: + ret_no_impl + diff --git a/src/drivers/drv-unapi.asm b/src/drivers/drv-unapi.asm new file mode 100644 index 0000000..a137879 --- /dev/null +++ b/src/drivers/drv-unapi.asm @@ -0,0 +1,320 @@ +; +; +; 0x4000 - extbio unapi +; 0x5000 - +; 0x6000 - +; 0x7000 - +; + +ARG .equ 0xF847 + +;--- API version and implementation version + +API_V_P .equ 1 +API_V_S .equ 0 +ROM_V_P .equ 1 +ROM_V_S .equ 1 + +;--- Maximum number of available standard and implementation-specific function numbers + +;Must be 0 to 127 +MAX_FN .equ 30+1 + +;Must be either zero (if no implementation-specific functions available), or #128 to 254 +MAX_IMPFN .equ 127+3 + + +;********************************************* +;*** CODE TO BE INSTALLED ON RAM SEGMENT *** +;********************************************* + + ;=============================== + ;=== EXTBIO hook execution === + ;=============================== + + ;>>> Note that this code starts exactly at address 0x4000 + +; .ds 129 +;.area CODE1 (ABS) +; .org 0H4400 + +DO_EXTBIO: + push hl + push bc + push af + ld a,d + cp #0x22 + jr nz,JUMP_OLD + cp e + jr nz,JUMP_OLD + + ;Check API ID + + ld hl,#UNAPI_ID + ld de,#ARG +LOOP: ld a,(de) + call TOUPPER + cp (hl) + jr nz,JUMP_OLD2 + inc hl + inc de + or a + jr nz,LOOP + + ;A=255: Jump to old hook + pop af + push af + inc a + jr z,JUMP_OLD2 + + ;A=0: B=B+1 and jump to old hook + pop af + pop bc + or a + jr nz,DO_EXTBIO2 + inc b + pop hl + ld de,#0x2222 + jp OLD_EXTBIO + +DO_EXTBIO2: + ;A=1: Return A=Slot, B=Segment, HL=UNAPI entry address + dec a + jr nz,DO_EXTBIO3 + pop hl + ld a,(MY_SEG) + ld b,a + ld a,(MY_SLOT) + ld hl,#UNAPI_ENTRY + ld de,#0x2222 + ret + + ;A>1: A=A-1, and jump to old hook + +DO_EXTBIO3: ;A=A-1 already done + pop hl + ld de,#0x2222 + jp OLD_EXTBIO + + + ;--- Jump here to execute old EXTBIO code + +JUMP_OLD2: + ld de,#0x2222 +JUMP_OLD: ;Assumes "push hl,bc,af" done + pop af + pop bc + pop hl + + ;Old EXTBIO hook contents is here + ;(it is setup at installation time) + +OLD_EXTBIO: + .ds 5 + + + ;==================================== + ;=== Functions entry point code === + ;==================================== + +UNAPI_ENTRY: + push hl + push af + ld hl,#FN_TABLE + bit 7,a + jr z,IS_STANDARD + ld hl,#IMPFN_TABLE + and #0b01111111 + cp #MAX_IMPFN-128 + jr z,OK_FNUM + jr nc,UNDEFINED +IS_STANDARD: + cp #MAX_FN + jr z,OK_FNUM + jr nc,UNDEFINED +OK_FNUM: + add a,a + push de + ld e,a + ld d,#0 + add hl,de + pop de + + ld a,(hl) + inc hl + ld h,(hl) + ld l,a + + pop af + ex (sp),hl + ret + + ;--- Undefined function: return with registers unmodified + +UNDEFINED: + pop af + pop hl + ret + +;--- Convert a character to upper-case if it is a lower-case letter + +TOUPPER: + cp #"a" + ret c + cp #"z"+1 + ret nc + and #0xDF + ret + + ;=================================== + ;=== Functions addresses table === + ;=================================== + +;--- Standard routines addresses table + +FN_TABLE: + .dw UNAPI_GET_INFO + .dw TCPIP_GET_CAPAB + .dw TCPIP_GET_IPINFO + .dw TCPIP_NET_STATE + .dw TCPIP_SEND_ECHO + .dw TCPIP_RCV_ECHO + .dw TCPIP_DNS_Q + .dw TCPIP_DNS_S + .dw TCPIP_UDP_OPEN + .dw TCPIP_UDP_CLOSE + .dw TCPIP_UDP_STATE + .dw TCPIP_UDP_SEND + .dw TCPIP_UDP_RCV + .dw TCPIP_TCP_OPEN + .dw TCPIP_TCP_CLOSE + .dw TCPIP_TCP_ABORT + .dw TCPIP_TCP_STATE + .dw TCPIP_TCP_SEND + .dw TCPIP_TCP_RCV + .dw TCPIP_TCP_FLUSH + .dw TCPIP_RAW_OPEN + .dw TCPIP_RAW_CLOSE + .dw TCPIP_RAW_STATE + .dw TCPIP_RAW_SEND + .dw TCPIP_RAW_RCV + .dw TCPIP_CONFIG_AUTOIP + .dw TCPIP_CONFIG_IP + .dw TCPIP_CONFIG_TTL + .dw TCPIP_CONFIG_PING + .dw TCPIP_WAIT + .dw 0 + + +;--- Implementation-specific routines addresses table + +IMPFN_TABLE: + .dw UNAPIE_INIT + .dw UNAPIE_GET_JUMP + .dw DRV_INIT + .dw DRV_GET_INFO + ;.dw TCPIPE_STATS + ;.dw TCPIPE_RESET + .dw 0 + + + +;UNAPI_GET_INFO: Obtain the implementation name and version +;Input: A = 0 +;Output: A = Error code +; HL = Address of the implementation name string +; DE = API specification version supported. D=primary, E=secondary. +; BC = API implementation version. B=primary, C=secondary. +UNAPI_GET_INFO: + LD BC,#256*ROM_V_P+ROM_V_S + LD DE,#256*API_V_P+API_V_S + LD HL,#APIINFO + XOR A + RET + + +;UNAPIE_INIT: Inits unapi jump code +;Input: A = 128 +; HL = slot and segment ids +; BC = copy 5 bytes from this addres to OLD_EXTBIO +;Output: +; A = Error code +; +;The routines of the XXXX specification are intended to be called intensively, therefore being performance a concern. For this reason, a jump table is provided so that all the routines can be invoked directly in addition to using the standard UNAPI entry point. Routines are ordered by their UNAPI routine number, so that routine 0 is at (HL), routine 1 is at (HL+3), and so on. +UNAPIE_INIT: + LD (MY_SLOT),HL + LD H,B + LD L,C + LD DE,#OLD_EXTBIO + LD BC,#5 + LDIR + RET + +;UNAPIE_GET_JUMP: Get the routines jump table address +;Input: A = 129 +;Output: HL = Address of the jump table (possibly in page 2) +;A = Segment of the jump table (#FF if ROM) +; +;The routines of the XXXX specification are intended to be called intensively, therefore being performance a concern. For this reason, a jump table is provided so that all the routines can be invoked directly in addition to using the standard UNAPI entry point. Routines are ordered by their UNAPI routine number, so that routine 0 is at (HL), routine 1 is at (HL+3), and so on. +UNAPIE_GET_JUMP: + LD HL,#FN_TABLE + LD A,(#MY_SEG) + RET + + +;DRV_INIT: Inits the implementation hardware. +;Input: A = 130 +;Output: A = Error code +; HL = Address of the implementation name string +; DE = API specification version supported. D=primary, E=secondary. +; BC = API implementation version. B=primary, C=secondary. +DRV_INIT: + MIDI_INIT + XOR A + RET + +;DRV_GET_INFO: Obtain the implementation gateway name and version +;Input: A = 131 +;Output: A = Error code +; HL = Address of the implementation hostname string +; DE = Connected gateway version. D=primary, E=secondary. +DRV_GET_INFO: + MIDI_TX_START 131 + MIDI_TX_END + MIDI_RX_START #DRV_GET_INFO + MIDI_RX_A_PUSH + ;MIDI_RX_STR #DRV_HOSTNAME + ;MIDI_RX_DE + MIDI_RX_END_POP + LD HL,#DRV_HOSTNAME + RET + +DRV_HOSTNAME: + .str "hostname" + .str "$" + .ds 40 + + ;============================ + ;=== UNAPI related data === + ;============================ + +;This data is setup at installation time + +MY_SLOT: .db 0 +MY_SEG: .db 0 + + + ;--- Specification identifier (up to 15 chars) + +UNAPI_ID: + .str "TCP/IP" + .db 0 +UNAPI_ID_END: + + ;--- Implementation name (up to 63 chars and zero terminated) + +APIINFO: + .str "mmidrv-rpc" + .str "$" + .db 0 + diff --git a/src/drivers/mmi-1205.asm b/src/drivers/mmi-1205.asm new file mode 100644 index 0000000..1d96391 --- /dev/null +++ b/src/drivers/mmi-1205.asm @@ -0,0 +1,49 @@ + .module nms-1205.asm + .title driver for the NMS-1205 Music Module +;----------------------------------------------------------------------------- + +; Motorola MC68B50 +; #00-#01 Music Module MIDI, output ports (mirrored on ports #08-#09, #10-#11, #18-#19) +; #04-#05 Music Module MIDI, input ports (mirrored on ports #0C-#0D, #14-#15, #1C-#1D) + +;IF INP(&H02)=255 AND INP(&HC0)=255 THEN CLS: PRINT"Geen FAC MIDI interface of Philips Music Module gevonden!!!":NEW + +.macro MIDI_CMD_WAIT ?wait_loop + LD B,#4 +wait_loop: + djnz #wait_loop +.endm + +.macro MIDI_INIT ?wait_loop_1 ?wait_loop_2 + LD A,#3 ; Reset first + OUT (#0),A + MIDI_CMD_WAIT + + LD A,#21 ; enable x but no int + OUT (#0),A + MIDI_CMD_WAIT +.endm + +.macro MIDI_TX ?wait_loop + PUSH AF +wait_loop: + IN A,(#4) + AND #2 + JR Z,wait_loop + POP AF + OUT (#1),A +.endm + +.macro MIDI_RX ?wait_loop +wait_loop: + IN A,(#4) + AND #1 + JR Z,wait_loop + IN A,(#5) +.endm + +.area _CODE +.include "drv-midi.asm" +.include "drv-unapi.asm" +.include "drv-tcpip.asm" +.area _DATA diff --git a/src/drivers/mmi-fac.asm b/src/drivers/mmi-fac.asm new file mode 100644 index 0000000..ee996b7 --- /dev/null +++ b/src/drivers/mmi-fac.asm @@ -0,0 +1,71 @@ + .module mm-fac.asm + .title driver for the FAC midi interface +;----------------------------------------------------------------------------- + +; +; #02-#03 FAC MIDI interface (i8251, mirrored on ports #00-#07) +; +; +UART_DATA .equ 0x02 ;8251 data +UART_CMD .equ 0x03 ;8251 command + +.macro MIDI_CMD_WAIT ?wait_loop + LD B,#4 +wait_loop: + djnz #wait_loop +.endm + +.macro MIDI_INIT ?wait_loop_1 ?wait_loop_2 + ; Do chip reset + XOR A + ;OUT (#UART_CMD),A + ;MIDI_CMD_WAIT + ;OUT (#UART_CMD),A + ;MIDI_CMD_WAIT + ;OUT (#UART_CMD),A + ;MIDI_CMD_WAIT + ;LD A,#0x40 + ;OUT (#UART_CMD),A + ;MIDI_CMD_WAIT + + ; Init 8251 mode + command + LD A,#0b01001110 + OUT (#UART_CMD),A + MIDI_CMD_WAIT + LD A,#0b00100101 + OUT (#UART_CMD),A +.endm + +.macro MIDI_TX_A register ?wait_loop +wait_loop: + IN A,(#UART_CMD) + AND #1 + JR Z,wait_loop + LD A,#register + OUT (#UART_DATA),A +.endm + +.macro MIDI_TX ?wait_loop + PUSH AF +wait_loop: + IN A,(#UART_CMD) + AND #1 + JR Z,wait_loop + POP AF + OUT (#UART_DATA),A +.endm + +.macro MIDI_RX ?wait_loop +wait_loop: + IN A,(#UART_CMD) + AND #2 + JR Z,wait_loop + IN A,(#UART_DATA) +.endm + +.area _CODE + +.include "drv-midi.asm" +.include "drv-unapi.asm" +.include "drv-tcpip.asm" +.area _DATA diff --git a/src/drivers/mmi-mext.asm b/src/drivers/mmi-mext.asm new file mode 100644 index 0000000..466a6d7 --- /dev/null +++ b/src/drivers/mmi-mext.asm @@ -0,0 +1,14 @@ + .module mm-fac.asm + .title driver for the FAC midi interface +;----------------------------------------------------------------------------- + +; Intel i8251 + i8253 External MSX-MIDI +; #E0-#E2 External MSX-MIDI interface (µ·pack) +; + + +.area _CODE +.include "drv-midi.asm" +.include "drv-unapi.asm" +.include "drv-tcpip.asm" +.area _DATA diff --git a/src/drivers/mmi-mint.asm b/src/drivers/mmi-mint.asm new file mode 100644 index 0000000..7d70afa --- /dev/null +++ b/src/drivers/mmi-mint.asm @@ -0,0 +1,14 @@ + .module mm-fac.asm + .title driver for the FAC midi interface +;----------------------------------------------------------------------------- + +; Intel i8251 + i8253 Internal MSX-MIDI +; #E8-#EF Internal MSX-MIDI interface (turboR GT) +; + + +.area _CODE +.include "drv-midi.asm" +.include "drv-unapi.asm" +.include "drv-tcpip.asm" +.area _DATA diff --git a/src/mmidrv/0module.mk b/src/mmidrv/0module.mk new file mode 100644 index 0000000..703dc0f --- /dev/null +++ b/src/mmidrv/0module.mk @@ -0,0 +1,57 @@ + +MMIDRV_NAME := mmidrv +MMIDRV_TEST := test-$(MMIDRV_NAME) +MMIDRV_SRC := $(PATH_SRC)/$(MMIDRV_NAME) +MMIDRV_BIN := $(PATH_BIN)/$(MMIDRV_NAME) +MMIDRV_HEX := $(MMIDRV_BIN)/$(MMIDRV_NAME).hex +MMIDRV_COM := $(MMIDRV_BIN)/$(MMIDRV_NAME).com +MMIDRV_COM2 := $(MMIDRV_BIN)/$(MMIDRV_NAME)2.com +MMIDRV_RELS := $(MMIDRV_BIN)/$(MMIDRV_NAME).rel +MMIDRV_CODE := $(MMIDRV_SRC)/$(MMIDRV_NAME).asm +BUILD_HELP += \\n\\t* $(MMIDRV_COM) \\n\\t* $(MMIDRV_TEST) + +$(MMIDRV_BIN): + $(call mb_mkdir,$(MMIDRV_BIN)) + +$(MMIDRV_BIN)/%.rel: $(MMIDRV_SRC)/%.asm | $(MMIDRV_BIN) + $(call mb_compile_asm,$@,$<) + +$(MMIDRV_HEX): $(MMIDRV_RELS) + $(call mb_link_asm_dos,$(MMIDRV_HEX),$(MMIDRV_RELS)) + +$(MMIDRV_COM): $(MMIDRV_HEX) + $(call mb_hex2com,$(MMIDRV_HEX),$(MMIDRV_COM)) + +$(MMIDRV_COM2): $(MMIDRV_COM) $(PATH_BIN)/drivers/mmi-fac.dat $(PATH_BIN)/drivers/mmi-1205.dat + cp $< $@; + dd if=/dev/null of=$@ seek=1792 bs=1 count=0 + dd if=$(PATH_BIN)/drivers/mmi-fac.dat of=$@ seek=1792 bs=1 + +$(MMIDRV_TEST): $(MMIDRV_COM2) + $(call mb_autoexec_open_gui_cmd,$(MMIDRV_BIN)) + + $(call mb_autoexec_append_cmd,$(MMIDRV_BIN),omsxctl set midi-out-logfilename /tmp/mm.out > NUL) + $(call mb_autoexec_append_cmd,$(MMIDRV_BIN),omsxctl plug FAC\ MIDI\ Interface\ MIDI-out midi-out-logger > NUL) + + #$(call mb_autoexec_append_echo,$(MMIDRV_BIN),Plugging midi-out to mmigate.) + #$(call mb_autoexec_append_cmd,$(MMIDRV_BIN),omsxctl plug FAC\ MIDI\ Interface\ MIDI-out mmigate-in > NUL) + #$(call mb_autoexec_append_cmd,$(MMIDRV_BIN),omsxctl plug Philips\ Music\ Module\ MIDI-out mmigate-in > NUL) + #$(call mb_autoexec_append_echo,$(MMIDRV_BIN),Plugging midi-in to mmigate.) + #$(call mb_autoexec_append_cmd,$(MMIDRV_BIN),omsxctl plug FAC\ MIDI\ Interface\ MIDI-in mmigate-out > NUL) + #$(call mb_autoexec_append_cmd,$(MMIDRV_BIN),omsxctl plug Philips\ Music\ Module\ MIDI-in mmigate-out > NUL) + $(call mb_autoexec_append_echo,$(MMIDRV_BIN),Install ram helper.) + $(call mb_autoexec_append_cmd,$(MMIDRV_BIN),ramhelpr i autocont) + echo -n "" > $(MMIDRV_BIN)/autocont.bat + echo "echo Starting mmidrv.\r" >> $(MMIDRV_BIN)/autocont.bat + echo "echo SKIPPED.\r" >> $(MMIDRV_BIN)/autocont.bat + + #echo "$(MMIDRV_NAME)\r" >> $(MMIDRV_BIN)/autocont.bat + #echo "echo Install InterNestor Lite.\r" >> $(MMIDRV_BIN)/autocont.bat + #echo "inl i\r" >> $(MMIDRV_BIN)/autocont.bat + + $(call mb_copy,tmp/ramhelpr.com,$(MMIDRV_BIN)) + $(call mb_copy,tmp/inl.com,$(MMIDRV_BIN)) + $(call mb_copy,tmp/ping.com,$(MMIDRV_BIN)) + $(call mb_copy,tmp/hget.com,$(MMIDRV_BIN)) + $(call mb_openmsx_dos2,$(MMIDRV_BIN)) + diff --git a/src/mmidrv/mmidrv.asm b/src/mmidrv/mmidrv.asm new file mode 100644 index 0000000..61ba6db --- /dev/null +++ b/src/mmidrv/mmidrv.asm @@ -0,0 +1,413 @@ + ;--- Sample RAM implementation of a MSX-UNAPI specification + ; By Konami Man, 1-2010 + ; + ; This code implements a sample mathematical specification, "SIMPLE_MATH" + ; .db + ; which has just two functions: + ; Function 1: Returns HL = L + E + ; Function 2: Returns HL = L * E + ; The code installs on a mapped RAM segment. + ; The RAM helper must have been previously installed. + ; + ; To create your own implementation: + ; 1) In the "Constants" section, modify the API version and implementation version + ; constants, as well as MAX_FN and MAX_IMPFN. + ; 2) In the "Functions code" section, leave FN_INFO unmodified, + ; and add your own functions. + ; 3) Add an entry for each function in the "Functions addresses table" section. + ; 4) In the "Data" section, modify the specification identifier + ; and the implementation identifier. + ; + ; Optional improvements (up to you): + ; - Install a RAM helper if none is detected. + ; - Let the user choose the install segment in DOS 1. + ; - Add code for uninstallation. + + +;******************* +;*** CONSTANTS *** +;******************* + + + +;--- System variables and routines + +_TERM0 .equ 0x00 +_STROUT .equ 0x09 + +BDOS .equ 0x0005 +ENASLT .equ 0x0024 +EXTBIO .equ 0xFFCA +ARG .equ 0xF847 +SEG_CODE .equ 0x0800 + + +;*************************** +;*** INSTALLATION CODE *** +;*************************** + + ; org #100 +.area _CODE + + ;--- Show welcome message + + ld de,#WELCOME_S + ld c,#_STROUT + call #BDOS + + ;--- Locate the RAM helper, terminate with error if not installed + + ld de,#0x2222 + ld hl,#0 + ld a,#0xFF + call EXTBIO + ld a,h + or l + jr nz,HELPER_OK + + ld de,#NOHELPER_S + ld c,#_STROUT + call BDOS + ld c,#_TERM0 + jp BDOS +HELPER_OK: + ld (HELPER_ADD),hl + ld (MAPTAB_ADD),bc + + ;--- Check if we are already installed. + ; Do this by searching all the TCP/IP + ; implementations installed, and comparing + ; the implementation name of each one with + ; our implementation name. + + ;* Copy the implementation identifier to ARG + + ld hl,#UNAPI_ID + ld de,#ARG + ld bc,#UNAPI_ID_END-UNAPI_ID + ldir + + ;* Obtain the number of installed implementations + + ld de,#0x2222 + xor a + ld b,#0 + call EXTBIO + ld a,b + or a + jr z,NOT_INST + + ;>>> The loop for each installed implementations + ; starts here, with A=implementation index + +IMPL_LOOP: push af + + ;* Obtain the slot, segment and entry point + ; for the implementation + + ld de,#0x2222 + call EXTBIO + ld (ALLOC_SLOT),a + ld a,b + ld (ALLOC_SEG),a + ld (IMPLEM_ENTRY),hl + + ;* If the implementation is in page 3 + ; or in ROM, skip it + + ld a,h + and #0b10000000 + jr nz,NEXT_IMP + ld a,b + cp #0xFF + jr z,NEXT_IMP + + ;* Call the routine for obtaining + ; the implementation information + + ld a,(ALLOC_SLOT) + ;ld iyh,a + .db 0xFD; iy + ld h,a + + ld a,(ALLOC_SEG) + ;ld iyl,a + .db 0xFD; iy + ld l,a + ld ix,(IMPLEM_ENTRY) + ld hl,(HELPER_ADD) + xor a + call CALL_HL ;Returns HL=name address + + ;* Compare the name of the implementation + ; against our own name + + ld a,(ALLOC_SEG) + ld b,a + ld de,#APIINFO ; -SEG_CODE_START+SEG_CODE + ld ix,(HELPER_ADD) + inc ix + inc ix + inc ix ;Now IX=helper routine to read from segment +NAME_LOOP: ld a,(ALLOC_SLOT) + push bc + push de + push hl + push ix + call CALL_IX + pop ix + pop hl + pop de + pop bc + ld c,a + ld a,(de) + cp c + jr nz,NEXT_IMP + or a + inc hl + inc de + jr nz,NAME_LOOP + + ;* The names match: already installed + + ld de,#ALINST_S + ld c,#_STROUT + call 5 + ld c,#_TERM0 + jp 5 + + ;* Names don't match: go to the next implementation + +NEXT_IMP: pop af + dec a + jr nz,IMPL_LOOP + + ;* No more implementations: + ; continue installation process + +NOT_INST: + + ;--- Obtain the mapper support routines table, if available + + xor a + ld de,#0x0402 + call EXTBIO + or a + jr nz,ALLOC_DOS2 + + ;--- DOS 1: Use the last segment on the primary mapper + + ld hl,(MAPTAB_ADD) + ld b,(hl) + inc hl + ld a,(hl) + jr ALLOC_OK + + ;--- DOS 2: Allocate a segment using mapper support routines + +ALLOC_DOS2: + ld a,b + ld (PRIM_SLOT),a + ld de,#ALL_SEG + ld bc,#15*3 + ldir + + ld a,(PRIM_SLOT) + or #0b00100000 ;Try primary mapper, then try others + ld b,a + ld a,#1 ;System segment + call ALL_SEG + jr nc,ALLOC_OK + + ld de,#NOFREE_S ;Terminate if no free segments available + ld c,#_STROUT + call 5 + ld c,#_TERM0 + jp 5 + +ALLOC_OK: + ld (ALLOC_SEG),a + ld a,b + ld (ALLOC_SLOT),a + + ;--- Switch segment, copy code, and setup data + + call GET_P1 ;Backup current segment + ld (P1_SEG),a + + ld a,(ALLOC_SLOT) ;Switch slot and segment + ld h,#0x40 + call ENASLT + ld a,(ALLOC_SEG) + call PUT_P1 + + ld hl,#0x4000 ;Clear the segment first + ld de,#0x4001 + ld bc,#0x4000-1 + ld (hl),#0x0 + ldir + + ld hl,#SEG_CODE ;Copy the code to the segment + ld de,#0x4000 + ld bc,#0x4000 ; note use file lenth.. + ldir + + ld hl,(ALLOC_SLOT) ;Setup slot and segment information + ;ld (MY_SLOT),hl + ;* Now backup and #0xpatc the EXTBIO hook + ; so that it calls address #4000 of the allocated segment + ;ld hl,#EXTBIO + ;ld de,#OLD_EXTBIO + ;ld bc,#5 + ;ldir + + LD a,#128 ; UNAPIE_INIT, hl=slot , DE=5b jump + LD BC,#EXTBIO + ld de,#0x2222 + call 0x4000 + + ;LD a,#0 ; UNAPI_GET_INFO + ;ld de,#0x2222 + ;call 0x4000 + ;LD D,H + ;LD E,L + ;ld c,#_STROUT + ;call BDOS + + LD a,#130 ; DRV_INIT + ld de,#0x2222 + call 0x4000 + + LD a,#131 ; DRV_GET_INFO + ld de,#0x2222 + call 0x4000 + LD D,H + LD E,L + ld c,#_STROUT + call BDOS + + di + ld a,#0xCD ;Code for #"CALL" + ld (EXTBIO),a + ld hl,(HELPER_ADD) + ld bc,#6 + add hl,bc ;Now HL points to segment call routine + ld (EXTBIO+1),hl + + ld hl,(MAPTAB_ADD) + ld a,(ALLOC_SLOT) + ld d,a + ld e,#0 ;Index on mappers table +SRCHMAP: + ld a,(hl) + cp d + jr z,MAPFND + inc hl + inc hl ;Next table entry + inc e + jr SRCHMAP +MAPFND: + ld a,e ;A = Index of slot on mappers table + rrca + rrca + and #0b11000000 ;Entry point #4010 = index 0 + ld (EXTBIO+3),a + + ld a,(ALLOC_SEG) + ld (EXTBIO+4),a + ei + + ;--- Restore slot and segment, and terminate + + ld a,(PRIM_SLOT) + ld h,#0x40 + call ENASLT + ld a,(P1_SEG) + call PUT_P1 + + ld de,#OK_S + ld c,#_STROUT + call BDOS + + ld c,#_TERM0 + jp BDOS + + ;>>> Other auxiliary code + +CALL_IX: jp (ix) +CALL_HL: jp (hl) + + +;**************************************************** +;*** DATA AND STRINGS FOR THE INSTALLATION CODE *** +;**************************************************** + + ;--- Variables + +PRIM_SLOT: .db 0 ;Primary mapper slot number +P1_SEG: .db 0 ;Segment number for TPA on page 1 +ALLOC_SLOT: .db 0 ;Slot for the allocated segment +ALLOC_SEG: .db 0 ;Allocated segment +HELPER_ADD: .dw 0 ;Address of the RAM helper jump table +MAPTAB_ADD: .dw 0 ;Address of the RAM helper mappers table +IMPLEM_ENTRY: .dw 0 ;Entry point for implementations + + ;--- DOS 2 mapper support routines + +ALL_SEG: .ds 3 +FRE_SEG: .ds 3 +RD_SEG: .ds 3 +WR_SEG: .ds 3 +CAL_SEG: .ds 3 +CALLS: .ds 3 +PUT_PH: .ds 3 +GET_PH: .ds 3 +PUT_P0: .ds 3 +GET_P0: .ds 3 +PUT_P1: out (#0xFD),a + ret +GET_P1: in a,(#0xFD) + ret +PUT_P2: .ds 3 +GET_P2: .ds 3 +PUT_P3: .ds 3 + + ;--- Strings + +WELCOME_S: + .str "UNAPI TCP/IP over MIDI implementation 1.0" + .db 13,10 + .str "(c) 2019 by Willem Cazander" + .db 13,10 + ;.db 13,10 + .str "$" + +NOHELPER_S: + .str "*** ERROR: No UNAPI RAM helper is installed" + .db 13,10,"$" + +NOMAPPER_S: + .str "*** ERROR: No mapped RAM found" + .db 13,10,"$" + +NOFREE_S: + .str "*** ERROR: Could not allocate any RAM segment" + .db 13,10,"$" + +OK_S: .str "Installed. Have fun!" + .db 13,10,"$" + +ALINST_S: .str "*** Already installed." + .db 13,10,"$" + +UNAPI_ID: + .str "TCP/IP" + .db 0 +UNAPI_ID_END: + +APIINFO: + .str "mmidrv-rpc" + .db 0 +APIINFO_END: + +.area _DATA diff --git a/src/mmidrv/mmidrv.asm.org b/src/mmidrv/mmidrv.asm.org new file mode 100644 index 0000000..98a78bf --- /dev/null +++ b/src/mmidrv/mmidrv.asm.org @@ -0,0 +1,630 @@ + ;--- Sample RAM implementation of a MSX-UNAPI specification + ; By Konami Man, 1-2010 + ; + ; This code implements a sample mathematical specification, "SIMPLE_MATH", + ; which has just two functions: + ; Function 1: Returns HL = L + E + ; Function 2: Returns HL = L * E + ; The code installs on a mapped RAM segment. + ; The RAM helper must have been previously installed. + ; + ; To create your own implementation: + ; 1) In the "Constants" section, modify the API version and implementation version + ; constants, as well as MAX_FN and MAX_IMPFN. + ; 2) In the "Functions code" section, leave FN_INFO unmodified, + ; and add your own functions. + ; 3) Add an entry for each function in the "Functions addresses table" section. + ; 4) In the "Data" section, modify the specification identifier + ; and the implementation identifier. + ; + ; Optional improvements (up to you): + ; - Install a RAM helper if none is detected. + ; - Let the user choose the install segment in DOS 1. + ; - Add code for uninstallation. + + +;******************* +;*** CONSTANTS *** +;******************* + +;--- System variables and routines + +_TERM0: equ #00 +_STROUT: equ #09 + +ENASLT: equ #0024 +EXTBIO: equ #FFCA +ARG: equ #F847 + +;--- API version and implementation version + +API_V_P: equ 1 +API_V_S: equ 0 +ROM_V_P: equ 1 +ROM_V_S: equ 1 + +;--- Maximum number of available standard and implementation-specific function numbers + +;Must be 0 to 127 +MAX_FN: equ 2 + +;Must be either zero (if no implementation-specific functions available), or 128 to 254 +MAX_IMPFN: equ 0 + + +;*************************** +;*** INSTALLATION CODE *** +;*************************** + + org #100 + + ;--- Show welcome message + + ld de,WELCOME_S + ld c,_STROUT + call 5 + + ;--- Locate the RAM helper, terminate with error if not installed + + ld de,#2222 + ld hl,0 + ld a,#FF + call EXTBIO + ld a,h + or l + jr nz,HELPER_OK + + ld de,NOHELPER_S + ld c,_STROUT + call 5 + ld c,_TERM0 + jp 5 +HELPER_OK: + ld (HELPER_ADD),hl + ld (MAPTAB_ADD),bc + + ;--- Check if we are already installed. + ; Do this by searching all the SIMPLE_MATH + ; implementations installed, and comparing + ; the implementation name of each one with + ; our implementation name. + + ;* Copy the implementation identifier to ARG + + ld hl,UNAPI_ID-SEG_CODE_START+SEG_CODE + ld de,ARG + ld bc,UNAPI_ID_END-UNAPI_ID + ldir + + ;* Obtain the number of installed implementations + + ld de,#2222 + xor a + ld b,0 + call EXTBIO + ld a,b + or a + jr z,NOT_INST + + ;>>> The loop for each installed implementations + ; starts here, with A=implementation index + +IMPL_LOOP: push af + + ;* Obtain the slot, segment and entry point + ; for the implementation + + ld de,#2222 + call EXTBIO + ld (ALLOC_SLOT),a + ld a,b + ld (ALLOC_SEG),a + ld (IMPLEM_ENTRY),hl + + ;* If the implementation is in page 3 + ; or in ROM, skip it + + ld a,h + and %10000000 + jr nz,NEXT_IMP + ld a,b + cp #FF + jr z,NEXT_IMP + + ;* Call the routine for obtaining + ; the implementation information + + ld a,(ALLOC_SLOT) + ld iyh,a + ld a,(ALLOC_SEG) + ld iyl,a + ld ix,(IMPLEM_ENTRY) + ld hl,(HELPER_ADD) + xor a + call CALL_HL ;Returns HL=name address + + ;* Compare the name of the implementation + ; against our own name + + ld a,(ALLOC_SEG) + ld b,a + ld de,APIINFO-SEG_CODE_START+SEG_CODE + ld ix,(HELPER_ADD) + inc ix + inc ix + inc ix ;Now IX=helper routine to read from segment +NAME_LOOP: ld a,(ALLOC_SLOT) + push bc + push de + push hl + push ix + call CALL_IX + pop ix + pop hl + pop de + pop bc + ld c,a + ld a,(de) + cp c + jr nz,NEXT_IMP + or a + inc hl + inc de + jr nz,NAME_LOOP + + ;* The names match: already installed + + ld de,ALINST_S + ld c,_STROUT + call 5 + ld c,_TERM0 + jp 5 + + ;* Names don't match: go to the next implementation + +NEXT_IMP: pop af + dec a + jr nz,IMPL_LOOP + + ;* No more implementations: + ; continue installation process + +NOT_INST: + + ;--- Obtain the mapper support routines table, if available + + xor a + ld de,#0402 + call EXTBIO + or a + jr nz,ALLOC_DOS2 + + ;--- DOS 1: Use the last segment on the primary mapper + + ld hl,(MAPTAB_ADD) + ld b,(hl) + inc hl + ld a,(hl) + jr ALLOC_OK + + ;--- DOS 2: Allocate a segment using mapper support routines + +ALLOC_DOS2: + ld a,b + ld (PRIM_SLOT),a + ld de,ALL_SEG + ld bc,15*3 + ldir + + ld a,(PRIM_SLOT) + or %00100000 ;Try primary mapper, then try others + ld b,a + ld a,1 ;System segment + call ALL_SEG + jr nc,ALLOC_OK + + ld de,NOFREE_S ;Terminate if no free segments available + ld c,_STROUT + call 5 + ld c,_TERM0 + jp 5 + +ALLOC_OK: + ld (ALLOC_SEG),a + ld a,b + ld (ALLOC_SLOT),a + + ;--- Switch segment, copy code, and setup data + + call GET_P1 ;Backup current segment + ld (P1_SEG),a + + ld a,(ALLOC_SLOT) ;Switch slot and segment + ld h,#40 + call ENASLT + ld a,(ALLOC_SEG) + call PUT_P1 + + ld hl,#4000 ;Clear the segment first + ld de,#4001 + ld bc,#4000-1 + ld (hl),0 + ldir + + ld hl,SEG_CODE ;Copy the code to the segment + ld de,#4000 + ld bc,SEG_CODE_END-SEG_CODE_START + ldir + + ld hl,(ALLOC_SLOT) ;Setup slot and segment information + ld (MY_SLOT),hl + + ;* Now backup and patch the EXTBIO hook + ; so that it calls address #4000 of the allocated segment + + ld hl,EXTBIO + ld de,OLD_EXTBIO + ld bc,5 + ldir + + di + ld a,#CD ;Code for "CALL" + ld (EXTBIO),a + ld hl,(HELPER_ADD) + ld bc,6 + add hl,bc ;Now HL points to segment call routine + ld (EXTBIO+1),hl + + ld hl,(MAPTAB_ADD) + ld a,(ALLOC_SLOT) + ld d,a + ld e,0 ;Index on mappers table +SRCHMAP: + ld a,(hl) + cp d + jr z,MAPFND + inc hl + inc hl ;Next table entry + inc e + jr SRCHMAP +MAPFND: + ld a,e ;A = Index of slot on mappers table + rrca + rrca + and %11000000 ;Entry point #4010 = index 0 + ld (EXTBIO+3),a + + ld a,(ALLOC_SEG) + ld (EXTBIO+4),a + ei + + ;--- Restore slot and segment, and terminate + + ld a,(PRIM_SLOT) + ld h,#40 + call ENASLT + ld a,(P1_SEG) + call PUT_P1 + + ld de,OK_S + ld c,_STROUT + call 5 + + ld c,_TERM0 + jp 5 + + ;>>> Other auxiliary code + +CALL_IX: jp (ix) +CALL_HL: jp (hl) + + +;**************************************************** +;*** DATA AND STRINGS FOR THE INSTALLATION CODE *** +;**************************************************** + + ;--- Variables + +PRIM_SLOT: db 0 ;Primary mapper slot number +P1_SEG: db 0 ;Segment number for TPA on page 1 +ALLOC_SLOT: db 0 ;Slot for the allocated segment +ALLOC_SEG: db 0 ;Allocated segment +HELPER_ADD: dw 0 ;Address of the RAM helper jump table +MAPTAB_ADD: dw 0 ;Address of the RAM helper mappers table +IMPLEM_ENTRY: dw 0 ;Entry point for implementations + + ;--- DOS 2 mapper support routines + +ALL_SEG: ds 3 +FRE_SEG: ds 3 +RD_SEG: ds 3 +WR_SEG: ds 3 +CAL_SEG: ds 3 +CALLS: ds 3 +PUT_PH: ds 3 +GET_PH: ds 3 +PUT_P0: ds 3 +GET_P0: ds 3 +PUT_P1: out (#FD),a + ret +GET_P1: in a,(#FD) + ret +PUT_P2: ds 3 +GET_P2: ds 3 +PUT_P3: ds 3 + + ;--- Strings + +WELCOME_S: + db "UNAPI Sample RAM implementation 1.0 (SIMPLE_MATH)",13,10 + db "(c) 2010 by Konamiman",13,10 + db 13,10 + db "$" + +NOHELPER_S: + db "*** ERROR: No UNAPI RAM helper is installed",13,10,"$" + +NOMAPPER_S: + db "*** ERROR: No mapped RAM found",13,10,"$" + +NOFREE_S: + db "*** ERROR: Could not allocate any RAM segment",13,10,"$" + +OK_S: db "Installed. Have fun!",13,10,"$" + +ALINST_S: db "*** Already installed.",13,10,"$" + + +;********************************************* +;*** CODE TO BE INSTALLED ON RAM SEGMENT *** +;********************************************* + +SEG_CODE: + org #4000 +SEG_CODE_START: + + + ;=============================== + ;=== EXTBIO hook execution === + ;=============================== + + ;>>> Note that this code starts exactly at address #4000 + +DO_EXTBIO: + push hl + push bc + push af + ld a,d + cp #22 + jr nz,JUMP_OLD + cp e + jr nz,JUMP_OLD + + ;Check API ID + + ld hl,UNAPI_ID + ld de,ARG +LOOP: ld a,(de) + call TOUPPER + cp (hl) + jr nz,JUMP_OLD2 + inc hl + inc de + or a + jr nz,LOOP + + ;A=255: Jump to old hook + + pop af + push af + inc a + jr z,JUMP_OLD2 + + ;A=0: B=B+1 and jump to old hook + + pop af + pop bc + or a + jr nz,DO_EXTBIO2 + inc b + pop hl + ld de,#2222 + jp OLD_EXTBIO +DO_EXTBIO2: + + ;A=1: Return A=Slot, B=Segment, HL=UNAPI entry address + + dec a + jr nz,DO_EXTBIO3 + pop hl + ld a,(MY_SEG) + ld b,a + ld a,(MY_SLOT) + ld hl,UNAPI_ENTRY + ld de,#2222 + ret + + ;A>1: A=A-1, and jump to old hook + +DO_EXTBIO3: ;A=A-1 already done + pop hl + ld de,#2222 + jp OLD_EXTBIO + + + ;--- Jump here to execute old EXTBIO code + +JUMP_OLD2: + ld de,#2222 +JUMP_OLD: ;Assumes "push hl,bc,af" done + pop af + pop bc + pop hl + + ;Old EXTBIO hook contents is here + ;(it is setup at installation time) + +OLD_EXTBIO: + ds 5 + + + ;==================================== + ;=== Functions entry point code === + ;==================================== + +UNAPI_ENTRY: + push hl + push af + ld hl,FN_TABLE + bit 7,a + + if MAX_IMPFN >= 128 + + jr z,IS_STANDARD + ld hl,IMPFN_TABLE + and %01111111 + cp MAX_IMPFN-128 + jr z,OK_FNUM + jr nc,UNDEFINED +IS_STANDARD: + + else + + jr nz,UNDEFINED + + endif + + cp MAX_FN + jr z,OK_FNUM + jr nc,UNDEFINED + +OK_FNUM: + add a,a + push de + ld e,a + ld d,0 + add hl,de + pop de + + ld a,(hl) + inc hl + ld h,(hl) + ld l,a + + pop af + ex (sp),hl + ret + + ;--- Undefined function: return with registers unmodified + +UNDEFINED: + pop af + pop hl + ret + + + ;=================================== + ;=== Functions addresses table === + ;=================================== + +;--- Standard routines addresses table + +FN_TABLE: +FN_0: dw FN_INFO +FN_1: dw FN_ADD +FN_2: dw FN_MULT + + +;--- Implementation-specific routines addresses table + + if MAX_IMPFN >= 128 + +IMPFN_TABLE: +FN_128: dw FN_DUMMY + + endif + + + ;======================== + ;=== Functions code === + ;======================== + +;--- Mandatory routine 0: return API information +; Input: A = 0 +; Output: HL = Descriptive string for this implementation, on this slot, zero terminated +; DE = API version supported, D.E +; BC = This implementation version, B.C. +; A = 0 and Cy = 0 + +FN_INFO: + ld bc,256*ROM_V_P+ROM_V_S + ld de,256*API_V_P+API_V_S + ld hl,APIINFO + xor a + ret + + +;--- Sample routine 1: adds two 8-bit numbers +; Input: E, L = Numbers to add +; Output: HL = Result + +FN_ADD: + ld h,0 + ld d,0 + add hl,de + ret + + +;--- Sample routine 2: multiplies two 8-bit numbers +; Input: E, L = Numbers to multiply +; Output: HL = Result + +FN_MULT: + ld b,e + ld e,l + ld d,0 + ld hl,0 +MULT_LOOP: + add hl,de + djnz MULT_LOOP + ret + + + ;============================ + ;=== Auxiliary routines === + ;============================ + +;--- Convert a character to upper-case if it is a lower-case letter + +TOUPPER: + cp "a" + ret c + cp "z"+1 + ret nc + and #DF + ret + + + ;============================ + ;=== UNAPI related data === + ;============================ + +;This data is setup at installation time + +MY_SLOT: db 0 +MY_SEG: db 0 + + + ;--- Specification identifier (up to 15 chars) + +UNAPI_ID: + db "SIMPLE_MATH",0 +UNAPI_ID_END: + + ;--- Implementation name (up to 63 chars and zero terminated) + +APIINFO: + db "Konamiman's RAM implementation of SIMPLE_MATH UNAPI",0 + + +SEG_CODE_END: diff --git a/src/mmigate/0module.mk b/src/mmigate/0module.mk new file mode 100644 index 0000000..42af236 --- /dev/null +++ b/src/mmigate/0module.mk @@ -0,0 +1,10 @@ + +BUILD_HELP += \\n\\t* mmigate-build\\n\\t* mmigate-run-virtual + +.PHONY: mmigate-build +mmigate-build: + cargo build + +.PHONY: mmigate-run-virtual +mmigate-run-virtual: + cargo run virtual diff --git a/src/mmigate/main.rs b/src/mmigate/main.rs new file mode 100644 index 0000000..3110036 --- /dev/null +++ b/src/mmigate/main.rs @@ -0,0 +1,200 @@ + +extern crate midir; +//#[macro_use] +extern crate structopt; + +use std::thread::sleep; +use std::time::Duration; +use std::io::{stdin, stdout, Write}; +use std::error::Error; + +use structopt::StructOpt; +use midir::{ + MidiInput, + MidiOutput, + MidiInputConnection, + MidiOutputConnection +}; + +#[cfg(not(windows))] +use midir::os::unix::VirtualInput; +#[cfg(not(windows))] +use midir::os::unix::VirtualOutput; + +const boot_logo: &str = " +Starting: _ _ + _ __ ___ _ __ ___ (_) __ _ __ _| |_ ___ +| '_ ` _ \\| '_ ` _ \\| |/ _` |/ _` | __/ _ \\ +| | | | | | | | | | | | (_| | (_| | || __/ +|_| |_| |_|_| |_| |_|_|\\__, |\\__,_|\\__\\___| + |___/ +"; + +#[derive(StructOpt, Debug)] +#[structopt(name = "mmigate", rename_all = "kebab-case")] +struct Startup { + /// Enable debug mode. + #[structopt(short, long)] + debug: bool, + + /// MIDI client name. + #[structopt(short, long, default_value = "mmigate")] + client_name: String, + + #[structopt(subcommand)] + cmd: StartupCommand +} + +#[derive(StructOpt, Debug)] +enum StartupCommand { + + /// Proxy internet over virtual MIDI. + #[structopt(name = "virtual")] + VirtualProxy { + /// MIDI client name. + #[structopt(short, long, default_value = "rpc-tcp-unapi")] + port_name: String, + }, + + /// List all MIDI devices. + #[structopt(name = "hw-list")] + HardwareList {}, + + /// Proxy internet over MIDI devices. + #[structopt(name = "hw-proxy")] + HardwareProxy { + /// MIDI-In port + #[structopt(short = "i", long)] + midi_in: usize, + + /// MIDI-Out port + #[structopt(short = "o", long)] + midi_out: usize, + }, +} + +fn main() { + match run(Startup::from_args()) { + Ok(_) => (), + Err(err) => println!("Error: {}", err.description()) + } +} + +//const MIDI_CLIENT_NAME: &str = "mmigate"; + +fn run(startup: Startup) -> Result<(), Box> { + println!("{}", boot_logo); + println!("version: {}", 123); + if startup.debug { + println!("{:?}", startup); + } + let midir_in = MidiInput::new(&(startup.client_name.to_string() + "-in"))?; + let midir_out = MidiOutput::new(&(startup.client_name.to_string() + "-out"))?; + + match startup.cmd { + StartupCommand::HardwareList {} => { + //println!("Available MIDI-in ports:"); + for i in 0..midir_in.port_count() { + println!("in_{}: {}", i, midir_in.port_name(i)?); + } + //println!("\nAvailable MIDI-out ports:"); + for i in 0..midir_out.port_count() { + println!("out_{}: {}", i, midir_out.port_name(i)?); + } + return Ok(()); + }, + StartupCommand::VirtualProxy {port_name} => { + #[cfg(not(windows))] { + println!("mode: virtual"); + println!("port_names: {}-in,{}-out", port_name, port_name); + + let mut conn_out = midir_out.create_virtual(&(port_name.to_string() + "-out"))?; + + let conn_in = midir_in.create_virtual(&(port_name.to_string() + "-in"), move |stamp, message, _| { + conn_out.send(message).unwrap_or_else(|_| println!("Error when forwarding message ...")); + println!("{}: {:?} (len = {})", stamp, message, message.len()); + }, ())?; + + + //input.clear(); + let mut input = String::new(); + stdin().read_line(&mut input)?; // wait for next enter key press + println!("Closing connections"); + + return Ok(()); + //return proxy(); + } + // + #[cfg(windows)] { + return Error(("Virtual MIDI ports are not supported on Windows.")); + } + } + StartupCommand::HardwareProxy {midi_in, midi_out} => { + + // Get an output port (read from console if multiple are available) + let out_port = match midir_out.port_count() { + 0 => return Err("no output port found".into()), + 1 => { + println!("Choosing the only available output port: {}", midir_out.port_name(0).unwrap()); + 0 + }, + _ => { + println!("\nAvailable output ports:"); + for i in 0..midir_out.port_count() { + println!("{}: {}", i, midir_out.port_name(i).unwrap()); + } + print!("Please select output port: "); + stdout().flush()?; + let mut input = String::new(); + stdin().read_line(&mut input)?; + input.trim().parse()? + } + }; + + println!("\nOpening connection"); + let mut conn_out = midir_out.connect(out_port, "midir-test")?; + println!("Connection open. Listen!"); + { + // Define a new scope in which the closure `play_note` borrows conn_out, so it can be called easily + let mut play_note = |note: u8, duration: u64| { + const NOTE_ON_MSG: u8 = 0x90; + const NOTE_OFF_MSG: u8 = 0x80; + const VELOCITY: u8 = 0x64; + // We're ignoring errors in here + let _ = conn_out.send(&[NOTE_ON_MSG, note, VELOCITY]); + sleep(Duration::from_millis(duration * 150)); + let _ = conn_out.send(&[NOTE_OFF_MSG, note, VELOCITY]); + }; + + play_note(66, 4); + play_note(65, 3); + play_note(63, 1); + play_note(61, 6); + play_note(59, 2); + play_note(58, 4); + play_note(56, 4); + play_note(54, 4); + } + sleep(Duration::from_millis(150)); + println!("\nClosing connection"); + // This is optional, the connection would automatically be closed as soon as it goes out of scope + conn_out.close(); + println!("Connection closed"); + Ok(()) + } + } + + +} + +fn proxy(startup: Startup, conn_in: MidiInputConnection, conn_out: MidiOutputConnection) -> Result<(), Box> { + println!("Starting mmigate proxy"); + + sleep(Duration::from_millis(150)); + println!("\nClosing connections"); + conn_in.close(); + conn_out.close(); + println!("Connections closed"); + Ok(()) +} + diff --git a/tmp/hget.com b/tmp/hget.com new file mode 100644 index 0000000000000000000000000000000000000000..fcbe0a0919a6f29ccf9c301088f958b27285a327 GIT binary patch literal 21163 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 literal 0 HcmV?d00001 diff --git a/tmp/inl.com b/tmp/inl.com new file mode 100644 index 0000000000000000000000000000000000000000..df38fe905126ca9d776694768aa39f9ac60da26b GIT binary patch literal 24922 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 literal 0 HcmV?d00001 diff --git a/tmp/ping.com b/tmp/ping.com new file mode 100644 index 0000000000000000000000000000000000000000..47cda085f2439dd2141aa834091edc835cf1f6ab GIT binary patch literal 2301 zcmb7D-ES0C6u&b&GrOI#OQ)?k#bEAqCuE>dmkl7PG6)I z;8$073c|rD@6zOsuwG8y;pNukJwER}!v6JFUJfPi^AgJyAwWrMWu8V&QaZ#45V&$I zlsq017@es+26?o z`Ff?o2etr&SJwGyOWKmODtNEF&&p5M(?9(vCIEvaE#gH#=?lR_!yJE8JE988#V|mO zRL+HJM-*WVQa*)y5w6nNWmGf4Iis^1JA`;=hoEyxYml&6nr`q>JJKO2@2)tf0;h6i zmfcmJI(upQT)Fh@Y;Vuo2#)+x6@-HVQqG{J?Pz|ndXrYEf)G6hngTSz!*T5w8V51# zi+ANEI<=EtOeEo5U<$tO0iC*_HF3U-AINtF)aA=sq@?k!ZE^Wtv6ZLOC7F4a&R?G| z_w4y`{Rc*5aJk5&KZKefO z(%L=#Mm40j$Pt}ggXo;_j&E2%Uicc~JPyb7{W7cX$;Ihbj&9{opVt&H+NVi#r?qGm zs4CV57v^u*fYU-rZsIqqsg=5C2scdsOFxq2NEyoTGm=sun=cnRFpMYnNu z8{cv-?&D=O*$csR30T$l$T2;>;wiW5`*U%9{qo(f!v7Uk`NcC>(7R+#7WK_5_O!s# zkGZb|UW?HWxL#Ta)n8ifQ&Xg)&BZFsMQDNB`Q{qbu`mzP+^*g$Yxga*W)|X4UCx&@ zw&jPwlpc-J*J8Av^H+F*7MR=N5};(X7@!Sz6@Gp@CpQ&=UNz^lyN?Ic`RjCkv5fxp z^TZvZm);TcW_PTWH(gCY>uJ0kORTyjdSc=}JqcI&4(#fdTWJ~x)psB#K=%cl$y>AX z_iNiqn3KNc%NJ(Xws|VdZ0)dl!nAUx+9L_2OFNU2priVb>S!h%ihNnQ!~Yifat5JD z5#Ay*e1Ptef4mUL%l}X1w?)MP!#svZEgQRI1P{G9@XUb$e7Jx2zyZ9adrMT@Gl}~w zGc{pMq|8k?`AjmgWouLv)x!?y!2<{Sd-3yQmg8bDA$n9)H*VaB`z>q|H)q)=@Q7ua zWW+Tr^N+X3k{A=2aWX+nH{}}vkgS>RUbYNYr)P8)v0)Ho(1V-~i_$t-bPCo1{{1Rg1K5?jEEjZctC z-;?AG*ROpuJ_LXtbHq8r9fQyi#T+5n%uWo0U;Tq(6g)^qh;fRfSDZ5AlmFqO;*^=j zLqo6ZT!}D99BcfPUs{9h?(S}^M#a5@g9it3(9wf^Jh}}W->~NTqtT!OHwFP(C{5DB8ySIOC+J~3ox&5@J~kn6503bqRU4i+2=cmMzZ literal 0 HcmV?d00001 diff --git a/tmp/ramhelpr.com b/tmp/ramhelpr.com new file mode 100644 index 0000000000000000000000000000000000000000..8d066dc8d83f986dc3b5e43d2c2b615de962e772 GIT binary patch literal 1854 zcmc&!|7#m%7=JIh%a_`AyKQ0}b9?Sm;x#L2n~fsJR@a$*DK1TEH$h5=x8%}gOYX8H zZQ5(`1KPe*kC$s}42xG1bQA2!G`T;ZM*b zLZ2Rm{na6Z<#`UFa>=;Z#exfA{=kOjRCvWe3t&YVGGuBpfmy)Js5t35eJeh>a==I1HOor4r zsR&QHw*#-&J2f?Bo&oYiMHp#b0jd(4hiC*8^%(&vkYY($3X{E-maw;ZHX_1FH5rn( zHhMvxl@*gBeNl##6qi9wf=WPgyPX%awFHXb4^BV}Kw55EvfygU@?-pcmpZv2-*Mleex&K}b@}OHv6r z6pcjXa4)3fgp`!hdf>-I6F2>lt>|&RI~;ohrMuGnw23kqi`hs56eD{asU7T literal 0 HcmV?d00001