Adventures in File IO and Commander X16

Chat about anything CX16 related that doesn't fit elsewhere
TomXP411
Posts: 1783
Joined: Tue May 19, 2020 8:49 pm

Adventures in File IO and Commander X16

Post by TomXP411 »



On 7/21/2022 at 12:27 PM, ZeroByte said:




Man, this onion keeps having more layers. That's why I wasn't understanding what you were saying, @TomXP411... I was thinking LFN was the channel, essentially. I know it means "logical file number" - but now I have a new question - can LFN be literally any byte the program wants to use? Could you use LFN = 72 if you want?



Yes. It can be any byte value. I don't remember if zero was valid, but definitely 1-255 are. I actually ran my test program with 1-255 for all valid secondary addresses, and it worked. 

 

BruceMcF
Posts: 1336
Joined: Fri Jul 03, 2020 4:27 am

Adventures in File IO and Commander X16

Post by BruceMcF »



On 7/22/2022 at 4:56 PM, TomXP411 said:




Yes. It can be any byte value. I don't remember if zero was valid, but definitely 1-255 are. I actually ran my test program with 1-255 for all valid secondary addresses, and it worked.



Again for the C64, not the CX16, but of course the C64 KERNAL was the starting point for the CX16 Kernel, so from the C64 PRG:


Quote




The <file-num> is the logical file number, which relates the OPEN, CLOSE, CMD, GET#, INPUT#, and PRINT# statements to each other and associates them with the file-name and the piece of equipment being used. The logical file number can range from 1 to 255 and you can assign it any number you want in that range.









NOTE: File numbers over 128 were really designed for other uses so it's good practice to use only numbers below 127 for file numbers.



I believe that 0 is the marker used to indicate that a slot n the KERNAL LFN table is not allocated to an open file. I would presume with three ten-byte vectors used to maintain the information, the LFN vector is just searched linearly for the matching LFN, and OPEN just scans the vector for a "0" entry to determine the offset to place the LFN, Device Number, and SA in their respective vectors.

I do not know what "other uses" were ever made of LFN over 127 (which is to say, negative LFN's if viewed as 8bit signed integers), but 1-127 was always more than sufficient for my purposes ... other than LFN "1" for Command Channel SA 15, I would have typically set LFN := SA.

User avatar
svenvandevelde
Posts: 488
Joined: Wed Dec 23, 2020 6:30 am
Location: Belgium, Antwerpen

Adventures in File IO and Commander X16

Post by svenvandevelde »


Hi @ZeroByte,

After our call i've been using the macptr api now also and it greatly has improved the speed of the load.

As you know, macptr receives 3 parameters, the number of bytes to load in A, the buffer to where the data needs to go with lower address in x and high address in y

And with the A being zero, it will load 512 bytes, or until EOF. All good ... The API also will increase the BRAM bank (zeropage $x00) automatically, when the Y register is between $A00 and $BF.

However, there is a defect in the API, that is annoying and that invalidates a proper load in my situation.

It all has to do with banking. Imagine I read a file into bank 4 with ptr $BE00. Apparently, the ptr is not increased automatically :-(.

Don't know why he does that. Would you have an idea how this is coming?

Note that i load with channel = 1, device = 8 and secondary = 0!

Using secondary 15 fails me big time, i juse cannot get this to work. The File open API returns me errors there!

Sven

KICKC home page by Jesper Gravgaard.
My KICKC alpha with Commander X16 extensions.
User avatar
svenvandevelde
Posts: 488
Joined: Wed Dec 23, 2020 6:30 am
Location: Belgium, Antwerpen

Adventures in File IO and Commander X16

Post by svenvandevelde »


Pls ignore, we fixed it together on the call :-). Macptr is working fine! The issue was that when the ptr gets to C000, it needs to be wrapped around to A000 when the bank changes after sequent load calls :-).


/**



 * @brief Load a file to ram or (banked ram located between address 0xA000 and 0xBFFF), incrementing the banks.



 * This function uses the new CX16 macptr kernal API at address $FF44.



 *



 * @param channel Input channel.



 * @param device Input device.



 * @param secondary Secondary channel.



 * @param filename Name of the file to be loaded.



 * @param bank The bank in banked ram to where the data of the file needs to be loaded.



 * @param sptr The pointer between 0xA000 and 0xBFFF in banked ram.



 * @return char status



 *  - not 0: Something is wrong! Kernal Error Code (https://commodore.ca/manuals/pdfs/commodore_error_messages.pdf)



 *  - 0: OK!



 */



unsigned char file_load_size(char channel, char device, char secondary, bram_bank_t dbank, bram_ptr_t dptr, size_t size)



{



    #ifdef __DEBUG_FILE



        printf("load file, c=%u, d=%u, s=%u, b=%x, p=%p, si=%u", channel, device, secondary, dbank, dptr, size);



    #endif

 


    unsigned char status = 0;

 


    unsigned int read = 0;



    unsigned int remaining = size;

 


    byte bank_old = bank_get_bram();



    bank_set_bram(dbank);

 


    status = cbm_k_chkin(channel);



    status = cbm_k_readst();



    #ifdef __DEBUG_FILE



        printf(", chkin status=%u", status);



    #endif



    if(status) return 0;

 


    char* ptr = dptr;

 


    unsigned int bytes = 0;



    do {



        if(!size) {



            #ifdef __DEBUG_FILE



                printf(", reading max ptr=%p", ptr);



            #endif



            bytes = cbm_k_macptr(0, ptr);



        } else {



            if(remaining >= 128) {



                #ifdef __DEBUG_FILE



                    printf(", reading 128 ptr=%p", ptr);



                #endif



                bytes = cbm_k_macptr(128, ptr);



            } else {



                #ifdef __DEBUG_FILE



                    printf(", reading remaining=%u ptr=%p", remaining, ptr);



                #endif



                bytes = cbm_k_macptr(remaining, ptr);



            }



        }

 


        status = cbm_k_readst();



        #ifdef __DEBUG_FILE



            printf(", macptr status=%u", status);



        #endif



        if(status & 0xBF) return 0;

 


        if(bytes == 0xFFFF) {



            printf("read error!!!");



            cbm_k_chkin(0);



            while(!getin());



            cbm_k_chkin(channel);



            break;



        }

 


        #ifdef __DEBUG_FILE



            printf(", bytes=%u", bytes);



        #endif

 


        read += bytes;



        ptr += bytes;



        if(BYTE1(ptr) == 0xC0) ptr -= 0x2000;



        remaining -= bytes;

 


        #ifdef __DEBUG_FILE



            printf(", size=%u, remaining=%u, read=%u", size, remaining, read);



        #endif

 


    } while ((status == 0) && ((size && remaining) || !size));

 


    #ifdef __DEBUG_FILE



        printf(", read bytes r=%u, status=%u\n", read, status);



    #endif

 


    bank_set_bram(bank_old);

 


    cbm_k_chkin(0);

 


    #ifdef __DEBUG_FILE



        while(!getin());



    #endif

 


    return 0;



}


KICKC home page by Jesper Gravgaard.
My KICKC alpha with Commander X16 extensions.
Post Reply