How can I read files non-sequentially?

Basic and Machine Language

Moderator: Moderators

User avatar
Victragic
Frogger '07
Posts: 492
Joined: Tue Nov 14, 2006 5:56 pm

How can I read files non-sequentially?

Postby Victragic » Tue May 27, 2008 3:49 am

Hi all,

as part of a related project, I'm trying to read files from a disk byte-by-byte and display the results on the screen.

All well and good if reading sequentially, but I'd like to be able to enable a user to go back a page as well.. thus (I guess) I need to use a file that allows random access - I believe this is typically what you'd use a USR file for.

My first question - is a USR file the same as a PRG or SEQ file in the way the data is stored on the disk? ie does the extension indicate a fundamental difference in the file, or is it merely nominal? Can you treat a PRG file as a USR file and vice versa?

Cheers
-G
Commodore Vic-20 -- State of the heart technology

User avatar
Mike
Herr VC
Posts: 2951
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Postby Mike » Tue May 27, 2008 3:56 am

PRG, USR, and SEQ files can only be accessed sequentially. They are organised the same way on disc.

PRG files usually contain the load address as first two bytes.

SEQ files only contain 'raw data' for the computer to read.

USR files usually contain executables for the disc drive. There exists a floppy command ('&') which load a file (strictly typed as USR) into floppy RAM, and executes it right there without loading it into the computers memory. But I digress.

For true random access, you'd use REL files. But I doubt they're supported by the fastloader in Easyload.

Beforehand it would be necessary to split (read: convert) the text file into records (most probably on a per-line basis). You then have direct access to individual lines.

As an alternative, keep the last read page in memory. If the user decides to go back, that page can be displayed quickly. Only if the user decides to go back even further, quickly read the file from the beginning up to the desired page (which, of course, involves a page count, and character count for each page read thus far).

This could be combined with reading one page, or the next two pages ahead.

Michael

User avatar
carlsson
Class of '6502
Posts: 5516
Joined: Wed Mar 10, 2004 1:41 am

Postby carlsson » Tue May 27, 2008 5:39 am

You could also keep storing the text files as SEQ, but instead of loading them as such you would write your own loader that uses B-R or U1 commands to read block by block. Each block will contain a pointer to the next, but the problem lies in that paragraphs and sentences may span across two disk blocks.

I suppose you can add a special character for "end of paragraph" and the application you use to save a sequential file to disk will pad out the current block to get to the next one. It would take a bit of keeping your tongue right. In this case, the text file reader would read as many blocks in sequence until it finds this marker, and also have pointers to the previous and next blocks of text.

All this could be done by directly allocating blocks or perhaps go via REL files, but I have a feeling keeping the files as SEQ even though they are read block by block, will be more safe to VALIDATE commands and such. Of course you could create fake directory entries for direct access files too, whichever is more practical.
Anders Carlsson

Image Image Image Image Image

User avatar
nbla000
Salmon Run
Posts: 2426
Joined: Thu Oct 13, 2005 8:58 am

Postby nbla000 » Wed May 28, 2008 7:42 am

Mike wrote:For true random access, you'd use REL files. But I doubt they're supported by the fastloader in Easyload.

Never tested btw i don't think so because you need to use the OPEN command for REL files and not the LOAD that is the only burst command on EasyLoad.


Victragic wrote:I'd like to be able to enable a user to go back a page as well

Really hard work, REL files may be a solution but i never managed them.


Some infos about REL files found, i hope it may help you:

REL - Relative file
This is the toughest one and so I kept it to the last.
Technical seen a REL-file exists of two files: a sequential file containing the records, and a "side sector" file containing the pointers to sectors containing the records. As already said, byte 20 and 21 of an directory entry point to this "side record" file. Byte 01 and 1 point to the sequential part.

A side sector is built according the following scheme:

Bytes Meaning
------- -----------------------------------------------------------
0 Track where next sector can be found
1 Next sector
4- 15 T/S bytes of maximal 6 side sectors (both 0 when unused)
16-255 T/S bytes of 120 data blocks (both 0 when unused)
Mega-Cart: the cartridge you plug in once and for all.

User avatar
Victragic
Frogger '07
Posts: 492
Joined: Tue Nov 14, 2006 5:56 pm

Postby Victragic » Thu May 29, 2008 3:10 am

Thanks guys -

Based on this info I'm abandoning the thought of using REL files (not USR as I thought!) for what is meant to be a simple .txt file reader..

So, probably the idea of loading in the file up to the point I want to display a screen from seems the best option. I may get it to generate a 'page index'.

I'll do a standard bit-banging version first I think. Currently I'm using OPEN routines from the kernal, so there probably isn't any directly insertable code floating around.
Commodore Vic-20 -- State of the heart technology

User avatar
Mike
Herr VC
Posts: 2951
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Postby Mike » Mon Jun 02, 2008 12:44 am

Aww! Just don't despise REL files. They're unarguably the best thing built into an unmodded 1541! ;)

nbla000's paragraph may be technically correct, but that info just is neither helpful nor necessary to use REL files. Furthermore carlsson's ideas more or less lead to re-inventing the wheel. And direct-access files without a directory entry guaranteed won't survive a Validate command as well.

Only thing that is necessary to use REL files sensibly, is a replacement for INPUT#, look at the lines 11-13, 31, 38, and 47-52. The ML routine is explained in "ROM calls and other tricks". Here we go:

Code: Select all

10 REM ** SETUP RECORD READ ROUTINE
11 IFPEEK(1)+256*PEEK(2)<>828THENPOKE56,PEEK(56)-1:CLR:POKE1,60:POKE2,3
12 FORT=828TO916:READA:POKET,A:NEXT
13 Z$="I'M 17 CHARS LONG":Z$=Z$+Z$+Z$+Z$+Z$:Z$=Z$+Z$+Z$
14 :
15 OPEN15,8,15,"I0"
16 OPEN2,8,2,"TEST,L,"+CHR$(51)
17 :
18 REM ** CREATE WHOLE FILE
19 PRINT#15,"P"+CHR$(2)+CHR$(100)+CHR$(0)+CHR$(1)
20 PRINT#2,"TEST"
21 :
22 REM ** WRITE FILE SEQUENTIALLY
23 PRINT#15,"P"+CHR$(2)+CHR$(1)+CHR$(0)+CHR$(1)
24 FORT=1TO100
25 PRINT#2,"RECORD #"+MID$(STR$(T),2)
26 NEXT
27 :
28 REM ** CHECK FILE CONTENTS (READ SEQUENTIALLY)
29 PRINT#15,"P"+CHR$(2)+CHR$(1)+CHR$(0)+CHR$(1)
30 FORT=1TO100
31 R$=LEFT$(Z$,USR(2)):SYS873,R$:PRINTT;TAB(5);R$
32 IFVAL(MID$(R$,9))<>TTHENPRINT"ERROR IN RECORD!":GOTO42
33 NEXT
34 :
35 REM ** RANDOM READ ACCESS (SOAK TEST)
36 T=INT(RND(1)*100)+1
37 PRINT#15,"P"+CHR$(2)+CHR$(T)+CHR$(0)+CHR$(1)
38 R$=LEFT$(Z$,USR(2)):SYS873,R$:PRINTT;TAB(5);R$
39 IFVAL(MID$(R$,9))<>TTHENPRINT"POSITIONING ERROR!":GOTO42
40 GETA$:IFA$=""THEN36
41 :
42 CLOSE2
43 CLOSE15
44 END
45 :
46 REM ** ML DATA
47 DATA 32,247,215,165,21,208,35,166,20,32,27,225,160,0,132,254
48 DATA 32,15,225,201,13,240,11,164,254,145,55,200,132,254,192
49 DATA 255,208,238,32,204,255,164,254,76,162,211,76,72,210
50 DATA 32,253,206,32,139,208,133,20,132,21,160,0,177,20,72,200
51 DATA 177,20,72,200,177,20,133,21,104,133,20,104,133,254,160,0
52 DATA 196,254,240,7,177,55,145,20,200,208,245,96


Return to “Programming”

Who is online

Users browsing this forum: No registered users and 1 guest