esxdos, dot commands, real tape loading

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
jamesh
Dizzy
Posts: 83
Joined: Thu Jul 06, 2023 6:36 pm

esxdos, dot commands, real tape loading

Post by jamesh »

Not sure where to start, so I’ll ask here. That problem has been mentioned several times on different forums, but I could not find an answer, I can only see open-ended discussions. Perhaps my google-fu fails me (again).

I have a [hopefully] useful piece of code I’d like to convert into a dot command. The code is written in C and compiled with z88dk toolchain. But there is problem: the code essentially loads stuff from the real tape (yes, the physical tape, MIC port). No fancy tricks, LD_BYTES ROM routine will do. And I could not find much information about that. Is it possible at all? I guess it should be, because when compiled as “regular” code, it can access both tape and disk at the same time. And no, simply recompiling my code with -subtype=dot results in a crash when tape loading is about to begin.
The case can be reduced to something like this:

Code: Select all

#include <arch/zx.h>
#include <arch/zx/esxdos.h>

// compile:
// zcc +zx -vn -subtype=dot -startup=30 -clib=new -SO3 --opt-code-size test.c -o test -create-app

int main() {
    unsigned char file;
    struct zxtapehdr hdr;

    zx_tape_load_block(&hdr, sizeof(hdr), ZXT_TYPE_HEADER);
    if (16384 == hdr.hdadd && 6912 == hdr.hdlen) {
        file = esxdos_f_open("TEST.SCR", ESXDOS_MODE_CREAT_TRUNC|ESXDOS_MODE_W);
        if (file) {
            zx_tape_load_block((void *)hdr.hdadd, hdr.hdlen, ZXT_TYPE_DATA);
            esxdos_f_write(file, (void *)hdr.hdadd, hdr.hdlen);
            esxdos_f_close(file);
        }
    }

    return 0;
}
User avatar
bob_fossil
Manic Miner
Posts: 661
Joined: Mon Nov 13, 2017 6:09 pm

Re: esxdos, dot commands, real tape loading

Post by bob_fossil »

Are you directly calling the ROM tape load functions? When an esxDOS dot command is executed the normal ROM is paged out as the dot command is loaded into address 0x2000 / 8192. It is possible to call ROM functions when the esxDOS ROM is paged in with the following bit of assembly:

Code: Select all

rst $18
defw <address you want to call>
jamesh
Dizzy
Posts: 83
Joined: Thu Jul 06, 2023 6:36 pm

Re: esxdos, dot commands, real tape loading

Post by jamesh »

Right, I know the theory about RST $18. What I do not know is how to apply that knowledge to my code, in C.

I found the zx_tape_load_block(...) implementation in z88dk sources and copied that over to my project. Modified, of course to avoid any conflicts and making sure my code calls my own "library". That wasn't easy for a beginner like me, libc=sdcc_iy didn't work, I had to use libc=new, and, long story short, eventually updated the project to use RST $18 DW $0562 instead of directly calling $0562 and... Nothing changed. It still crashes. Maybe I did it wrong.

Rephrasing the question: 1) does anybody have practical experience calling tape-related ROM subroutines from dot command in any way? Is tape loading, which is intercepted by esxdos, supposed to work theoretically? 2) What would be an easy way to do so from C code?

P.S. I tried tracing the code in FUSE's debugger and since $0562 is the entry point for DivMMC/esxdos, something complicated happens. If I understand it correctly, 48K ROM quickly gets replaced by esxdos ROM, which doesn't help at all, a random code gets executed and it crashes. At the moment I do not fully understand all that paging logic, but the weird theory I have is that the caller's address located in the lower 16k may break something. That's why I have the question #1. I've tried adding a short "trampoline", placing some brief code snippet in the upper 32k (RST $18 + DW $0562 + JP BACK_TO_MY_DOT_CODE), but it did not work. Perhaps, I was too tired and made a mistake -- will be retrying next weekend.
jamesh
Dizzy
Posts: 83
Joined: Thu Jul 06, 2023 6:36 pm

Re: esxdos, dot commands, real tape loading

Post by jamesh »

Alright, some good news. I was able to get it working using 0x0564 as entry point. I've tried this approach on Sunday evening, but apparently made a mistake somewhere. A clean (re)implementation seems to be working today.

So, it looks like calling the addresses explicitly intercepted by the DivMMC ROM does not work. At lest with esxdos 0.8.9.

Remaining question is about z88dk. For now I copied entire zx_tape_load_block assembler implementation and gave it a new name, but I am wondering if there is another way to override existing library function.
jamesh
Dizzy
Posts: 83
Joined: Thu Jul 06, 2023 6:36 pm

Re: esxdos, dot commands, real tape loading

Post by jamesh »

By the way, for those who are reading this later. The code snipped in the first post has a bug which prevents it from working properly even if tape subroutine would be working as expected. &hdr points to a DivMMC RAM page, which won’t be mapped to the address space when tape loading routine is running. Thus, even if the bytes are loaded from tape, they would be sent to the ROM area and practically lost. Make sure your data buffer is above 16k boundary.
jamesh
Dizzy
Posts: 83
Joined: Thu Jul 06, 2023 6:36 pm

Re: esxdos, dot commands, real tape loading

Post by jamesh »

For future readers: working code can be found here.
Post Reply