+3e DOS File Handling

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
Zetr0
Member
Posts: 59
Joined: Mon Aug 22, 2011 12:38 pm

+3e DOS File Handling

Post by Zetr0 »

Hello my friends, I have recently posted this on WoS, so my apologies if you have already read it there.

I am wondering if someone can help me solve this little pickle of z88dk / Windows using +3e File system, I do fully intend to try this on my Debian set up when I get some time, as its a more robust development platform, and I am pretty sure I had file handling working.

So a little info then -

Code: Select all

ZCC Version [ V2.59 (c) 16.4.2010 - D.J.MOrris ]
Win Version [ Win 7 64bit Pro ]
TXT Editor  [ ConTEXT ]
Here is the most basic of basic C code -

Code: Select all

#include <stdio.h>
#include <stdlib.h>


int main( void )
{
        FILE *fp;

        fp = fopen("e:test.txt","w");

        if( fp == NULL )
        {
                printf("Error Cannot open FILE to Write\n");
        }
        else
        {
                printf("Writing text to file\n");
                fprintf( fp,"simple text line of data\n");
                fprintf( fp,"second line of text data\n");
                fclose( fp );
                printf("file created\n");
        }
        return 0;
}
*NB I noticed the compiler has a mass fit when I use

Code: Select all

 if(( fp = fopen("e:tst.txt","w") ))
not sure if thats related to anything, anyway -

So here is the command line for compilation that I use

Code: Select all

zcc +zxansi -lndos -DPLUS3 -lm -create-app test.c >build.txt
Here is the build text

Code: Select all

        1 file(s) copied.
        1 file(s) copied.
Unrecognised argument: \\
copy C:\PROGRA~2\z88dk\lib\spec_crt0.opt C:\Users\Zetr0\AppData\Local\Temp\s1c4_1.opt
copy C:\Users\Zetr0\AppData\Local\Temp\s1c4_1.opt C:\Users\Zetr0\AppData\Local\Temp\s1c4_1.asm
zcpp -I. -DZ80 -DSMALL_C -DSPECTRUM -D__SPECTRUM__ -DSCCZ80 -DPLUS3 -IC:\PROGRA~2\z88dk\include  test.c C:\Users\Zetr0\AppData\Local\Temp\s1c4_.i
sccz80    -\\  C:\Users\Zetr0\AppData\Local\Temp\s1c4_.i
copt C:\PROGRA~2\z88dk\lib\z80rules.2 < C:\Users\Zetr0\AppData\Local\Temp\s1c4_.asm > C:\Users\Zetr0\AppData\Local\Temp\s1c4_.op1
copt C:\PROGRA~2\z88dk\lib\z80rules.1 < C:\Users\Zetr0\AppData\Local\Temp\s1c4_.op1 > C:\Users\Zetr0\AppData\Local\Temp\s1c4_.opt
z80asm -eopt -ns -Mo -IC:\PROGRA~2\z88dk\lib C:\Users\Zetr0\AppData\Local\Temp\s1c4_.opt
z80asm -a -m -Mo -LC:\PROGRA~2\z88dk\lib\clibs -oa.bin -igen_math  -indos  -izxan_clib  -iz80_crt0  C:\Users\Zetr0\AppData\Local\Temp\s1c4_1.opt C:\Users\Zetr0\AppData\Local\Temp\s1c4_.o
appmake +zx  -b a.bin -c C:\Users\Zetr0\AppData\Local\Temp\s1c4_1
So I have the following setup environment

Code: Select all

Emulator    :        FUSE version 1.0.0
Environmebt :        Spectrum +3
ROM         :        +3e ( 8bit IDE )
Peripherals :        Simple 8 bit IDE 
            :        K-Mouse
MEDIA       :        128MB (256mb) Compact Flash Hard Disk File (as Unit 0)
Within this environment I have configured a partition to "e:" which points to "ZXLaunch" partition - which is pretty empty 4MB of space available.

I can write to and read from this space in BASIC, by saving programs and variables within the environemnt, using commands like

Code: Select all

SAVE "e:slave.dat" DATA a()

SAVE "e:splice.bas"

SAVE "e:test.dat" CODE 32768,256
These all work, so here is the code I use to run the compiled program

Code: Select all

        10:  CLEAR 32767
        20:  LOAD "t:" : LOAD "" code
        30:  LOAD "e:" 
        40:  RANDOMIZE USR 32768
  9998:  STOP
  9999:  LOAD "e:" : CLS : PRINT "Saving Program" : SAVE "e:test.bas" : CLS : PRINT "Program Saved"
Running this program loads the code from the virtual tap/tape created by z88dk, yes I know could just lump the bin in the memory of the system but I am incredibly lazy! To be fair though I usually do that if I want to dump it to the virtual hard disk.

So the program prints out on the screen "Writing text to file" followed by a new line with the text "File Created". and exits safely back to BASIC - sadly no output on the disk at all... not a sausage and no error or reason given.

I appreciate any help, advice or even cryptic clues at this point =)

Thanks for reading.
Zetr0
Member
Posts: 59
Joined: Mon Aug 22, 2011 12:38 pm

Post by Zetr0 »

Hello fellow z88dk'ers!

Okay so now I am truly perplexed, my hope is someone can help.

I am currently using my Debian>Linux environment and have an identical problem. so I have simplified this even more so -

Code: Select all

/*
 *         Simple File Handling Test with the +3e DOS system
 * 
 */

#include <stdio.h>
#include <stdlib.h>

int main( void )
{
  FILE *fp;
  
  int i = 0;
  char str[15];
  
  sprintf( str,"This is a test\0");
  
/* write data to disk */

  printf("\nInitalizing File *ptr\n");

  fp = fopen( "data.dat", "w" );

  printf("\nfwriting to disk\n");
  fwrite(str , 1 , sizeof(str) , fp );
  fclose( fp );
  
  printf("String Written [%s], size of [%d]",str, sizeof(str));
  
  return 0;
}
I compile using this -

Code: Select all

zcc +zx -lndos -DPLUS3 -lm -create-app fhand.c >build.txt
I use the created ".bin" file and load this into FUSE at 32768, it is 3275 bytes long

I then use this code to run it on the spectrum

Code: Select all

   1 CLS : LOAD "e:"
  10 RANDOMIZE USR 32768
8999 STOP
9000 CLS : CAT
9898 STOP
9899 PRINT "Saving Code to Disk" : SAVE "fcode.cde" CODE 32768, 3275 : CLS : PRINT "Code Saved"
9998 STOP
9999 CLS : PRINT "Saving Program" : SAVE "ftest.bas" : CLS : PRINT "Program Saved"
Sadly nothing is written to the DISK... although all the notices do appear - I wonder what I have missed or perhaps what I am doing wrong =(
Zetr0
Member
Posts: 59
Joined: Mon Aug 22, 2011 12:38 pm

Post by Zetr0 »

So after some amazing detective work by Guesser on WoS he noticed my compile line was just using and empty retainer / stub

Code: Select all

-lndos
when it should be

Code: Select all

-lp3
A big thanks to guesser and Dom on here whom helped me last time this happen.... indeed... this has happened twice........ TWICE!!


I need to stop break-dancing or something!
Zetr0
Member
Posts: 59
Joined: Mon Aug 22, 2011 12:38 pm

Re: +3e DOS File Handling ( New Problem )

Post by Zetr0 »

Hello there my fellow z88dk'ers

I have quite the conundrum and I hope someone can see what I am obviously missing.

Problem:
when attempting to open a file for writing, reading or appending, I am met with an error or crash.

Compile Line:

Code: Select all

#!/bin/bash
zcc +zx -lp3 -DPLUS3 -lm -create-app zxmp.c > build.txt
The above is an executable text file used in the work directory

System:
I am currently Using Zubuntu ( fully updated ) with z88dk from the snap-store.

I am using the latest version of FUSE emulator and loading the binary into and executing from 32,768. I am also setting RAMTOP with a CLEAR 32768 before loading the Binary file and executing.

Code: zxmp.c

Code: Select all

int main( void )
{
    FILE *fp;
    void *scrptr;
    char str[31];

    struct PENS input_selected_pens;
    struct PENS input_unselected_pens;

    ubyte colour = 0;
    ubyte ch = 0;

    set_ScreenAttributes( Screen, _black, _white, 1, 0, _black );
    Render_Screen( Screen );

    //dbug
        zxprintf("Opening file to Write", 0, 5, BLACK, WHITE, 1 );
        getch();

        sprintf( str,"a:test.dat\0");

        fp = fopen( "a:test.dat","wb+");

        if( fp!= NULL )
        {
            //dbug
            zxprintf("File Open", 0, 6, BLACK, WHITE, 1 );
            getch();

            fprintf( fp,"happy happy, joy joy, etc.");
            fclose(fp);

            //dbug
            zxprintf("File Save", 0, 7, BLACK, WHITE, 1 );
            zxprintf( str, 0, 8, RED, WHITE, 1 );
            getch();
        }
        else
        {
        //dbug
            zxprintf("Error Opening file", 0, 6, WHITE, RED, 1 );
            getch();
        }
        return 0;
The above is "//debugging" code to simply create / open or appended a file. Initially it was hard-coded for a filename, then I changed this to a string for it to be change or edited by the end user. However, no matter how I express any statement to fopen() it always fails. With the above set to creating and writing to a file, it simply returns the "Error Opening file", if I change the device to "c:" or "m:" the same failure.

When changing to reading data from a written file, the program completely hangs and doesn't get past fopen();

This is quite simple code, as such I was very perplexed as to why this program error was happening. I created a blank project and pulled over some simple functions for use.

Working Program: testfio.c

Code: Select all

int main( void )
{
    FILE *fp;

    register unsigned char i =0;

    ubyte str[100], ch =0, loop = 1;
    ubyte fname[21];
    ubyte msg[81];

    struct PENS cpens;

// init.
    init_zxconsole();

    Wipe_Screen();
    sprintf( fname,"a:test.dat\0");

    for( i = 0; i < 100; i +=1 )
        str[ i ] = "\0";

// set the pen colours
    cpens.ink = _yellow;
    cpens.paper = _blue;
    cpens.bright = 1;
    cpens.flash = 0;
    cpens.attribute = MakeAttribute( _yellow, _blue, 1, 0 );


//dbug - operation
    while( loop == 1 )
    {
        zxprintf(" FILE IO TEST v1.0 ", 0, 0, WHITE, BLACK, 1 );
        
        zxprintf("Options               Filename:", 0, 3, BLACK, WHITE, 1 );
        zxprintf( fname, 32, 3, BLACK, CYAN, 1 );

        zxprintf("1 > Open File for Writing", 0, 5, BLACK, WHITE, 1 );
        zxprintf("2 > Open File for Reading", 0, 6, BLACK, WHITE, 1 );
        zxprintf("3 > Change Filename", 0, 7, BLACK, WHITE, 1 );
        zxprintf("4 > View Data", 0, 8, BLACK, WHITE, 1 );
        zxprintf("c > Clear Screen & Data", 0, 10, BLACK, WHITE, 1 );
        zxprintf("x > Exit", 0, 11, BLACK, WHITE, 1 );

        ch = getch();

        if( ch == '1' || ch == '2' )    // file IO
        {
            Wipe_Screen();
            zxprintf(" TESTING IO ", 0, 0, WHITE, BLACK, 1 );

// open file
            if( ch == '1' )           // open for reading;
            {
                fp = fopen( fname,"wb+");
            }
            else
            {
                fp = fopen( fname,"rb+");
            }

// test file open
            if( fp != 0 )   // file has been opened
            {
                if( ch == '1' ) // write file to disk
                {
                    zxprintf("File Open ( wb+ )", 0, 3, BLACK, WHITE, 1 );
                    zxprintf("Write Data", 0, 4, BLACK, WHITE, 1 );
                    getch();

                // write something to FILE
                    fprintf( fp,"Once upon a time, in a Galaxy just around the corner [%d]", 1837);

                    zxprintf("Data Written", 0, 5, BLACK, WHITE, 1 );
                    getch();
                }
                if( ch == '2' ) // read file from disk
                {
                    zxprintf("File Open ( rb+ )", 0, 3, BLACK, WHITE, 1 );
                    zxprintf("Read Data", 0, 4, BLACK, WHITE, 1 );
                    getch();

                // read something from file
                    fread( str, sizeof( ubyte ), 50, fp );

                    str[ 51 ] ='\0';
                    zxprintf("Data Loaded", 0, 5, BLACK, WHITE, 1 );
                    getch();
                }
            }
            else
            {
                if( ch == '1' )
                {
                    zxprintf("Error opening File ( wb+ )", 0, 5, YELLOW, RED, 1 );
                }
                else
                {
                    zxprintf("Error opening File ( rb+ )", 0, 5, YELLOW, RED, 1 );
                }
                getch();
            }
            
            zxprintf("Releasing File Pointer", 0, 7, BLACK, WHITE, 1 );
            getch();
            fclose(fp);
        }

        if( ch == '3' )       // change filename / location
        {
            Wipe_Screen();
            zxprintf(" Change Filename / Location ", 0, 0, WHITE, BLACK, 1 );

            zxprintf("Input >", 0, 22, BLACK, WHITE, 1 );
            WriteAttributeArea( 5, 22, 8, 1, cpens.attribute);
            get_str_i64c( fname, 8 +32, 22 +32, cpens, 14 );
            WriteAttributeArea( 5, 22, 8, 1, MakeAttribute( _black, _white, 1, 0));
 
            sprintf( msg,"Filename changed to [%s]\0", fname);
            zxprintf( msg, 0, 7, WHITE, BLACK, 1 );
            getch();
    
            Wipe_Screen();
        }

        if( ch == '4' )       // view loaded data
        {
            Wipe_Screen();
            zxprintf(" View Data ", 0, 0, WHITE, BLACK, 1 );

            if( str[ 0 ] != '\0' )
            {
                zxprintf( str, 0, 3, WHITE, MAGENTA, 1 );
            }
            else
            {
                zxprintf("No Data Loaded", 0, 3, WHITE, BLUE, 1 );
            }
            getch();
            Wipe_Screen();
        }

        if( ch == 'c' )         // Clear Screen & Loaded Data
        {
            Wipe_Screen();
            for( i = 0; i < 100; i +=1 )
                str[ i ] = '\0';
        }

        if( ch == 'x' )               // exit program
        {
            loop = 0;
            break;
        }
    }   // end while

    return 0;
}
Compile Line: "testfio.c"

Code: Select all

#!/bin/bash
zcc +zx -lp3 -DPLUS3 -lm -create-app testfio.c > build.txt
The above example works exactly as expected, both saving and loading data from any device. These programs use the same bin loader / launcher that does not have any open streams.

I have been looking and tweeking "zxmp.c" and I simply cannot get this to work, this is my last hope before I rewrite - and thats a lot of code.

Thanks for reading - Z.
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Re: +3e DOS File Handling

Post by dom »

[I've not had a chance to compile and try it out yet]

Just some thoughts...

+3DOS doesn't handle filenames being in the upper 16k - to call it you need to page in bank 7 so the filename would be paged out.

So...How big is zxmp? I'm wondering if in the const version (fopen("filename","w+")) the filename is being pushed past 49152?

Similarly, if the filename is a static char filename[16]; then the BSS section might be being pushed to above 49152 as well.

So a buffer on the stack should work since unless something is changing it, sp is < 32768.
Zetr0
Member
Posts: 59
Joined: Mon Aug 22, 2011 12:38 pm

Re: +3e DOS File Handling

Post by Zetr0 »

@dom

Thanks for looking into this.

zxmp.c
size of bin file = 23,323 bytes

testfio.c
size of bin file = 9,238 bytes

It would appear that you are ( especially with the blue spiked hair ) a legendary code-smith!

zxmp.c when loaded at 32,768 has a codebase spanning an upper address of 56,091

hmmm a buffer on the stack.... may need some inspiration on that one.
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Re: +3e DOS File Handling

Post by dom »

So a stack buffer would be a point fix for you.

However you won’t be the last person to find this out so I will update the libraries to do it automatically.
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Re: +3e DOS File Handling

Post by dom »

Well, it's amazing what you forget. We're already copying the filename onto the stack: https://github.com/z88dk/z88dk/blob/mas ... open.c#L65

So, that brilliant idea came to nought. Back to basics - can you send me the full project (including binary) so I can have a look and reproduce?
Zetr0
Member
Posts: 59
Joined: Mon Aug 22, 2011 12:38 pm

Re: +3e DOS File Handling

Post by Zetr0 »

Of course I can, it spans a few files, I can zip it up, how can I send it you?
Zetr0
Member
Posts: 59
Joined: Mon Aug 22, 2011 12:38 pm

Re: +3e DOS File Handling

Post by Zetr0 »

Ohhh. would you like a copy of the +3e Disk Image ( 64mb ) as well ?

I use this for launching the programs
stefano
Well known member
Posts: 2137
Joined: Mon Jul 16, 2007 7:39 pm

Re: +3e DOS File Handling

Post by stefano »

zcc +zxansi -lndos -DPLUS3 -lm -create-app test.c >build.txt

Why -lndos?
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Re: +3e DOS File Handling

Post by dom »

Zetr0 wrote: Wed Feb 01, 2023 11:19 pm Of course I can, it spans a few files, I can zip it up, how can I send it you?
Email: dom at z88dk.org which should get through to me
Zetr0
Member
Posts: 59
Joined: Mon Aug 22, 2011 12:38 pm

Re: +3e DOS File Handling

Post by Zetr0 »

@stefano
This was an error on my part back in 2017 - when I was starting out with +3e DOS / z88dk... I remember back then.... I had the looks... the taste... and the hair..... its been over 5 years since I updated this thread last Wednesday. ;)

@dom
Hello there, an email is digitizing its way to you, it contains both the "ZXMP" and "testfio" project files.

I have also included both the hdf and floppy disk file for convenience -

If using an emulator just mount the HDF - it is an 8bit IDE device image, once booted jump to +3 basic and type [ load "loader.bas" ] from there you have options to set RAMTOP and execute from 32768.

When including the data for the +3e ROM, I noticed I was / have been using version v1.38 - I found v1.43 and attempted to use this - however

testfio
completely errors when attempting to "fp = fopen()" despite it working under v1.38 - doesn't crash, it just cannot open any device/filename and prints the error trap to the screen. It doesn't matter if it's set to READ or WRITE.

I did jump back to sm8en +3e DOS v1.38 and the project works as expected.


ZXMP
Sadly this simply crashes and hangs the system under v1.43 when attempting to "fp=fopen()"

Thanks again for your help =)
Zetr0
Member
Posts: 59
Joined: Mon Aug 22, 2011 12:38 pm

Re: +3e DOS File Handling

Post by Zetr0 »

@all

I decided to put together a very BASIC File IO and compile it an attempt to run it under v1.43

Code: Select all

*
        Basic IO - testing +3e ROM v1.43


*/

// pre-processor
typedef unsigned char ubyte;

#include <stdio.h>

void clearscr( void );
void clearscr( void )
{
     #asm
          CALL 0x0DAF    ; call ROM routine to clear the screen
          ret
     #endasm    
}

ubyte getch( void );
ubyte getch( void )
{
    ubyte *LASTK = 23560;   // ZX Spectrum System Variable Address

    // fflush last input
    *LASTK = 0;
    // wait untill a keypress
    while( *LASTK == 0 );
    // return keypress value
    return *LASTK;
}

int main( void )
{
    FILE *fp;
    ubyte str[21];

    register ubyte i = 0;

    //init
    for( i = 0; i < 21 ; i +=1 )
        str[ i ] ='\0';

    clearscr();

    printf("Testing Basic File IO");

    printf("\n");
    printf("Opening File wb+");
    fp = fopen("a:somedata.dat","wb+");

    if( fp!= 0 )
    {
        printf("\n");
        printf("File Ready for Writing");

        fprintf(fp,"Some nominal text data here and there in this file");

        printf("\n");
        printf("Data Witten to file");
    }
    else
    {
        printf("\n");
        printf("Error opening File for wb+");
        return 0;
    }
    printf("\n");
    printf("Closing fp");
    fclose( fp );

    printf("\n");
    printf("Opening File rb+");
    fp = fopen("a:somedata.dat","rb+");

    if( fp!= 0 )
    {
        printf("\n");
        printf("File Ready for Reading");

        fread( str, sizeof( ubyte ), 20, fp );

        printf("\n");
        printf("20bytes Loaded to file");
    }
    else
    {
        printf("\n");
        printf("Error opening File for rb+");
        return 0;
    }
    printf("\n");
    printf("Closing fp");
    fclose( fp );

    printf("\n");
    printf("Tests Complete - Press Any Key");
    getch();

    printf("\n");
    printf("Data : %s", str);
    getch();

    return 1;
}

/* EOL */

Compile Line:

Code: Select all

#!/bin/bash
zcc +zx -lp3 -DPLUS3 -lm -create-app basicio.c > build.txt
And it works straight off the bat.

a.bin size = 5,004 bytes
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Re: +3e DOS File Handling

Post by dom »

To wrap up this bit of the thread (To be continued in 5 years?)...

The problem here was indeed the code pushing past 49152. Internally the routine that calls +3DOS used several routines that were paged out when DOS and RAM7 were paged in.

I rejigged the memory map and converted the routines to use ix rather than iy in the commit here: https://github.com/z88dk/z88dk/commit/d ... 5af85ddc73 so things should be working from the 20230203 nightly build.
Zetr0
Member
Posts: 59
Joined: Mon Aug 22, 2011 12:38 pm

Re: +3e DOS File Handling

Post by Zetr0 »

DOM!

You sir are a code-smithing genius!

I will install this a little later.
Zetr0
Member
Posts: 59
Joined: Mon Aug 22, 2011 12:38 pm

Re: +3e DOS File Handling

Post by Zetr0 »

Just a silly question,

When, and or does, the nightly build get pushed onto the snap-store?
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Re: +3e DOS File Handling

Post by dom »

There's two channels for the snap build: latest/beta which corresponds to the releases and latest/edge which builds whenever there's a change to the code.

I suspect you might be tracking latest/beta rather than latest/edge
Zetr0
Member
Posts: 59
Joined: Mon Aug 22, 2011 12:38 pm

Re: +3e DOS File Handling

Post by Zetr0 »

dom wrote: Sun Feb 05, 2023 12:06 am I suspect you might be tracking latest/beta rather than latest/edge
LOL, yes that would be me.


Finally got round to installing the latest/edge, and I am happy to say that YES it now functions as expected!!!


Thank you for your invaluable help, Dom!!!
Post Reply