The file I/O does not work?

Post Reply
pasi
New member
Posts: 3
Joined: Fri Nov 22, 2013 11:06 pm

The file I/O does not work?

Post by pasi »

It says in the z88dk v1.99A Release notes:
[new c lib] Stdio base classes currently include serial character i/o and terminal i/o implementing windows and proportional fonts. Disk i/o is missing in this release.
So, fopen(), fread() ? none of that stuff works? What is the status of this?
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

pasi wrote:It says in the z88dk v1.99A Release notes:
[new c lib] Stdio base classes currently include serial character i/o and terminal i/o implementing windows and proportional fonts. Disk i/o is missing in this release.
So, fopen(), fread() ? none of that stuff works? What is the status of this?
For the new c library: all of stdio works except opening and closing of files at runtime and anything having to do with disk files. Files are currently statically opened by the crt to allow streams like stdin, stdout, stderr, etc to be created.

Of the functions listed in stdio.h ( http://www.z88dk.org/wiki/doku.php?id=libnew:stdio ) the ones that don't work are:
fclose, fopen, freopen, fdopen, fgetpos, fsetpos, ftell, rewind, fseek

Of the functions listed in unistd.h ( http://www.z88dk.org/wiki/doku.php?id=libnew:unistd ) the ones that don't work are:
close, lseek, _exit

The active development is mainly in the drivers area now. Non-blocking i/o is being added and then disk i/o will be added. What is available now for serial and terminal i/o is fairly full featured. Both can do CRLF conversion, operate in text or binary mode and the terminal i/o can use fixed width or proportional fonts, offers line editing and can manage one window on screen per open terminal. ioctl() controls the terminal features at runtime.


Many people are unaware that there are two independent C libraries in z88dk now. The new C library, which is being talked about here, is new in 1.99A and is described on this page: http://www.z88dk.org/wiki/doku.php?id=temp:front . The classic C library is the one that has always been shipped with z88dk and is described on this page: http://www.z88dk.org/wiki/doku.php . We're trying to merge the documentation together in time.

The new C library currently supports three targets: zx (zx spectrum), cpm (cp/m 2.2) and embedded (generic z80). Note that sms is not among them, although anyone could use the embedded target for generic compiles. To create a target there is some documentation here: http://www.z88dk.org/wiki/doku.php?id=t ... g_a_target

The classic C library does have an SMS target although I can see there isn't much documentation about it: http://www.z88dk.org/wiki/doku.php?id=platform:sms . I would expect its stdio functions to work as well although I don't think anything would be connected as disk device.
DarkSchneider
New member
Posts: 5
Joined: Sun Apr 01, 2018 4:02 pm

Post by DarkSchneider »

Then once those functions are working we will have file I/O. I am interested about using z88dk ASAP, and because I want to make MSX-DOS2 programs I need the file ones.

Maybe this could help:
http://msx.hansotten.com/software/msx-c-manual/
Look at the file related functions, and where they are placed.
Here to download (source included):
http://msx.hansotten.com/software/msx-c/
Here the documentation about MSX-DOS functions:
http://map.grauw.nl/resources/dos2_functioncalls.php

In example, the MSX-C open function (called from fopen) is like (K&R C):

Code: Select all

FD      open(filename, mode)
char    *filename;
int     mode;
{
    FD      fd;
    FCB     *fcb;

    if (mode < 0 || 2 < mode || (fd = _alocfcb()) == ERROR)
        return (ERROR);
    if (_setupfcb(filename, fcb=_getfcb(fd)) != OK /* wildcard is ERROR */
    ||  bdos(OPEN, fcb) == BDOSERR) {
        _freefcb(fd);
        return (ERROR);
    }
    fcb->mode = mode + 1;   /*      0 -> _READ,             *
                             *      1 -> _WRITE,            *
                             *      2 -> _READ | _WRITE     */
    fcb->recsize = 1;
    return (fd);
}
Look that it simply calls BDOS, this is, the MSX-DOS function. Then using the MSX-DOS functions should do the work.
Here the fopen for reference (K&R C):

Code: Select all

FILE    *fopen(nargs, xfn, xmode, xbsiz)
unsigned nargs;
char    *xfn, *xmode;
size_t  xbsiz;
{
        char    *filename, mode;
        TINY    bmod;
        size_t  bsiz;
        FILE    *p;

        extern  STATUS  _seek();

        if (nargs < 1 || 3 < nargs )
                return (NULL);
        filename = xfn;
        mode = (nargs == 1)? 'R': toupper(*xmode);
        bmod = (nargs != 1 && toupper(xmode[1]) == 'B')? _BINARY: 0;
        bsiz = (nargs == 3)? xbsiz: BUFSIZ;
        /* search for an empty iob */
        for (p = stdin; p < stdin + _NFILES; ++p)
                if (p->mode == 0)
                        goto found_iob;
        return (NULL);

found_iob:
        p->base = NULL;                /*  alloc buf when actually reading/writing  */
        p->bufsiz = bsiz;
        switch (mode) {
        case 'R':
                if ((fileno(p) = open(filename, O_RDONLY)) == ERROR)
                        return (NULL);
                p->mode = _IOREAD | bmod;
                p->count = 0;
                break;
        case 'A':
        case 'W':
                if(mode == 'A' && (fileno(p)=open(filename,O_RDWR)) != ERROR) {
                        if (bmod)
                                _seek(fileno(p), 0, (char)2);
                        else {
                                p->mode = _IOREAD;        /* text mode */
                                p->count = 0;
                                while (getc(p) != EOF)  /* inefficient!! */
                                        ;
                                /* set pointer to EOF */
                                _seek(fileno(p), -p->count, (char)1);
                        }
                }
                else if ((fileno(p) = creat(filename)) == ERROR)
                        return (NULL);
                p->mode = _IOWRT | bmod;
                p->count = bsiz;
                p->ptr = p->base;
                break;
        default:
                return (NULL);
        }
        p->serial = (TINY)isatty(fileno(p));
        return (p);
}
I think that knowing the MSX-DOS functions the missing ones could be easily ported from any other CPM machine.

Hope this helps.
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

Thanks for the links.

Newlib still doesn't have file io integrated but a couple of targets have added file io in parallel. For example, the ChanFatFS system for yaz180 (and any other target) has been compiled and it used names that ensure it doesn't conflict with the C library. So FILE becomes FIL, fgets() becomes f_gets(), etc. A second example is esxdos for zx / zx next whose api is similar to posix and operates with integer file descriptors instead of FILE*. Its functions are prefaced with "esxdos_" so they don't conflict with the library. So it would be possible to take those existing routines and modify them so there are no conflicts with the library and use them that way. Changes that can use z88dk's printf/scanf code would also improve things in terms of compliance with modern c standards and control over what converters were enabled. But ideally this all gets integrated eventually.

The classic library does have file io and an msx target but the disk io is not supported for the msx at this time.
User avatar
dom
Well known member
Posts: 1194
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

I believe that file io is supported for the -subtype=msxdos target - it simply uses the CP/M file io routines.

This won't work in a non-MSXDOS target because the call vector is incorrect.
DarwinNE
New member
Posts: 6
Joined: Sat Dec 21, 2019 8:33 pm

Post by DarwinNE »

Dear all,
I am about to release a text adventure game that contains some code based on file access with fopen/fputs/fclose etc. to save the game state. I noticed that it does not seem to work in my (limited) tests with MSX and ZXSpectrum targets. Searching on the forum, I found this discussion. If I understand correctly, this is the reason why I can't use this technique.

Has the status of the file access routines evolved since 2018? I can skip the load/save code for those platforms, but I just wanted to be sure.

Cheers,
D.
User avatar
dom
Well known member
Posts: 1194
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

I think you're compiling with classic aren't you?

If so, then file io should work: on the spectrum you need to decide which disc system you want to use (+3, Microdrive, ESXDOS)

For MSX which environment are you using? It should work from MSXDOS + MSXDOS2 if you provide the appropriate -subtype= option.
DarwinNE
New member
Posts: 6
Joined: Sat Dec 21, 2019 8:33 pm

Post by DarwinNE »

I am targeting the MSX 1 environment. I compile with:

zcc +msx -DMSX -O3 -create-app my_game.c -o my_game -lndos -zorg=32768 -pragma-define:CLIB_DISABLE_FGETS_CURSOR=1 -pragma-define:CRT_INITIALIZE_BSS=0

For the ZXSpectrum, I target the original 48K model:

zcc +zx -clib=ansi -lndos -create-app my_game.c -o my_game -Cz--screen -Czspectrum_splash.scr
appmake +zx -b my_game.tap --audio --fast --dumb

I guess, yes, I'm using classic.

My question was also motivated by trying to understand wether the standard I/O C commands can write or read a file on a cassette.
User avatar
dom
Well known member
Posts: 1194
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

Looking at those command lines you've got "-lndos" - this is the noop disc driver library so that matches with your observations.

In terms of saving to tape, it's possible on the spectrum - take a look at <spectrum.h> and the tape_save() function. There's nothing equivalent for the MSX though.
DarwinNE
New member
Posts: 6
Joined: Sat Dec 21, 2019 8:33 pm

Post by DarwinNE »

Thank you very much!
Post Reply