1

TL:DR

What is the reason my kernel_read() function ignoring file errors?


I'm trying to understand how to work with files in cc54 using CBM specific functions. My target is Commodore 64 with 1541 drive.

Below code works as I expected except the last part where I'm trying to get error message by attempting to read non existing file. Instead of giving error message, program continues as if there was no problem. Where am I wrong?

the output for the last part is:

Reading with cbm.h again
Opening data file...
Reading...
Done.

data 3 : 2

              data 4

and some additional garbage characters in screen, I assume due to some memory trashing.

cc65 code is:

#include <conio.h>
#include <stdio.h>

char data1[12] = "Test Data 1";
char data2[12] = "Test Data 2";
char data3[12] = "\0";
char data4[12] = "\0";

void std_write(unsigned char * file_name);
void std_read(unsigned char * file_name);
void kernel_read(unsigned char * file_name);
void kernel_getin(void *ptr, unsigned char size);

void main(void)
    {
        clrscr();

        // File read & write with stdio functions
        cputs("Writing with stido.h\n\r");
        std_write("testfile");

        cputs("\n\rReading with stido.h\n\r");
        std_read("testfile");

        cprintf("\n\rdata3 : %s\n\r",data3);
        cprintf("data4 : %s\n\r",data4);
        cprintf("\n\r");

        cgetc();
        clrscr();

        // Trying to read with cbm specific functions
        data3[0]='\0';
        data4[0]='\0';

        cputs("\n\rReading with cbm.h\n\r");
        kernel_read("testfile");

        cprintf("\n\rdata3 : %s\n\r",data3);
        cprintf("data4 : %s\n\r",data4);
        cprintf("\n\r");

        // Trying to read non exiting file
        data3[0]='\0';
        data4[0]='\0';

        cputs("\n\rReading with cbm.h again\n\r");
        kernel_read("testfile2");

        cprintf("\n\rdata3 : %s\n\r",data3);
        cprintf("data4 : %s\n\r",data4);
        cprintf("\n\r");

    }


void std_write(unsigned char * file_name)
    {
        FILE *file;
        unsigned char n;

        cputs("Opening data file...\n\r");
        _filetype = 's';
        if(file = fopen(file_name, "w"))
            {
                cputs("Writing...\n\r");
                n = fwrite(data1, sizeof(unsigned char)*11, 1, file);
                n = n + fwrite(data2, sizeof(unsigned char)*11, 1, file);

                if(n != 2)
                {
                    cputs("Error: File could not be written.\n\r");
                    fclose(file);
                }
                else
                {
                    cputs("Done.\n\r");
                    fclose(file);       
                }
            }
        else
            {
                cputs("File could not be opened\n\r");
            }
    }

void std_read(unsigned char * file_name)
    {
        FILE *file;
        unsigned char n;

        cputs("Opening data file...\n\r");
        _filetype = 's';
        if(file = fopen(file_name, "r"))
        {
            cputs("Reading...\n\r");
            n = fread(data3, sizeof(unsigned char)*11, 1, file);
            n = n + fread(data4, sizeof(unsigned char)*11, 1, file);

            if(n != 2)
            {
                cputs("Error while reading!\n\r");
                fclose(file);
            }
            else
            {
                cprintf("Done.\n\r");
                fclose(file);
            }
        }
        else
        {
            cputs("File could not be opened\n\r");
        }
    }

void kernel_read(unsigned char * file_name)
    {
        unsigned char error_channel;

        // Open error channel
        cbm_k_setlfs(15,8,15);          
        cbm_k_setnam('\0');
        error_channel = cbm_k_open();

        cbm_k_setlfs(2,8,0);            
        cbm_k_setnam(file_name);             

        cputs("Opening data file...\n\r");
        if(!cbm_k_open()) 
        {
            _filetype = 's';
            cputs("Reading...\n\r");
            cbm_k_chkin(2);
            kernel_getin(data3, sizeof(unsigned char)*11);
            kernel_getin(data4, sizeof(unsigned char)*11);

            cbm_k_chkin(15);
            if(!cbm_k_getin())
            {
                cputs("Error while reading!\n\r");
                cbm_k_clall();
            }
            else
            {
                cprintf("Done.\n\r");   
                cbm_k_clall();

            }
        }
        else
        {
            cputs("File could not be opened\n\r");
        }   
    }

void kernel_getin(void *ptr, unsigned char size)
    {
        unsigned char * data = (unsigned char *)ptr;
        unsigned char i;

        for(i=0; i<size; ++i)
        {
            data[i] = cbm_k_getin();
        }
        data[i] = '\0';
    }

Solution: I've changed the kernel_read and kernel_getin functions following the tofro's and Stavr00's suggestions.

Now kernel_read function produce "File could not be opened." error as intended.

void kernel_read(unsigned char * file_name)
    {
        cbm_k_setlfs(2,8,0);            
        cbm_k_setnam(file_name);

        cputs("Opening data file...\n\r");
        cbm_k_open();
        if(!cbm_k_readst()) 
        {
            _filetype = 's';
            cputs("Reading...\n\r");
            cbm_k_chkin(2);
            kernel_getin(data3, sizeof(unsigned char)*11);
            kernel_getin(data4, sizeof(unsigned char)*11);

            if(!cbm_k_readst())
            {
                cputs("Error while reading!\n\r");
                cbm_k_clall();
            }
            else
            {
                cprintf("Done.\n\r");   
                cbm_k_clall();
            }
        }
        else
        {
            cputs("File could not be opened\n\r");
        }   
    }

unsigned char kernel_getin(void *ptr, unsigned char size)
    {
        unsigned char * data = (unsigned char *)ptr;
        unsigned char i;
        unsigned char st=0;

        for(i=0; i<size; ++i)
        {
            st = cbm_k_readst();
            if (st) break;
            data[i] = cbm_k_getin();
        }
        data[i] = '\0';
        size = i;
        return st;
    }

Notice I changed previous

if(!cbm_k_open())

with

cbm_k_open();
if(!cbm_k_readst())

and also removed, now unnecessary, open error channel part completely.

  • You're aware that there are C64 (and cc65) specific sites that may gather way more C64/cc65 firm programmers than here? – Raffzahn Nov 13 '18 at 3:37
  • 1
    Yes @Raffzahn but it's still great that people choose to ask questions here :-) Perhaps if wizofwor or someone else does find the answer on another forum, I hope that the answer is brought here too! – Richard Downer Nov 13 '18 at 11:08
  • 4
    I'm not a cc65 programmer but would assume a few spread-out cbm_k_readst calls to get the error status wouldn't hurt. – tofro Nov 13 '18 at 11:12
3

Adding this to the code as per @tofro's suggestion:

unsigned char kernel_getin(void *ptr, unsigned char *size)
{
    unsigned char * data = (unsigned char *)ptr;
    unsigned char i;
    unsigned char st=0;

    for(i=0; i<*size; i++)
    {
        st = cbm_k_readst();
        if (st) break; 
        data[i] = cbm_k_getin();
    }
    data[i] = '\0';
    *size = i;
    return st;
}

Check the return value to detect errors / end-of-file, and the by-ref parameter size to see how many bytes read.

unsigned char n  =0;
unsigned char st =0;
unsigned char sz =0;

sz = 11;
st = st | kernel_getin(data3, &sz);
n = n + sz;
sz = 11;
st = st | kernel_getin(data4, &sz);
n = n + sz;

if(n != 22)
{
    cputs("Error while reading!\n\r");
    cbm_k_clall();
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.