Close
0%
0%

OSI SD Card Operating System (OSISDOS)

Ohio Scientific / UK101 SD Card based Operating System under Multicomp FPGA Computer

Similar projects worth following
Starting from
$14.00
land_boards has 826 orders / 20reviews
Ships from United States of America
Make an SD card Operating System for the Ohio Scientific / UK101 which runs with the Multicomp FPGA Computer

Grant Searle's FPGA computer project, Multicomp, has support for the Ohio Scientific / UK 101 from the late 1970's. There's also hardware support in the Multicomp project for SD Cards but so far there's no software support for the SD Card with the OSI / UK101 design.

The goal of this project is to use the existing hardware base to create an SD card Operating System. The desired features are:

  • Replace "D" (Disk) selection at boot in CEGMON monitor
  • Boot to file selector/loader
  • Support for loading BASIC or Machine Language programs
  • SDHC supports FAT32 file system
    • Programs can be loaded from a PC to the SD Card
  • Support for SDHC cards up to 32 GB
    • Cards larger than 64 GB can be formatted as SDHC (not exFAT)

  • BASIC Makes This Hard

    land-boards.com05/12/2022 at 10:56 0 comments

    Trying to go from a typed in file name as a string like "TEST.BAS" into "TEST    BAS" to find the file in the directory. The string functions didn't work as expected.

    DIM A$(11) - Allocates string space for the output string 

    Inserting characters didn't work. Code to test:

     6000 REM STRING STUFF
     6010 DIM A$(8)
     6020 PRINT A$
     6030 PRINT LEN(A$)
     6040 A$(1)="X"
     6050 PRINT A$
     6060 PRINT LEN(A$)
    

    Produces no string. This should be relatively easy to solve in assembly so the problem can be ignored for the moment by just typing in the file name with spaces to pad the file name to 8 characters and 3 character extension.

    Working on the BASIC code to find a file offset from a file name. Let's look through the directory for "STARS   BAS" which is on the disk. String matching does work.

     7000 A$="TEST    BAS"
     7010 B$="TEST    BAS"
     7020 IF A$=B$ THEN PRINT "OK-MATCH"
     7030 IF A$<>B$ THEN PRINT "MATCH ERROR"
     7040 B$="TEST2   BAS"
     7050 IF A$<>B$ THEN PRINT "OK-DOES NOT MATCH"
     7060 IF A$=B$ THEN PRINT "DOES NOT MATCH ERROR"
    

    Produces OK messages. But how can the file name be extracted into a string without the first method? This simple function does not work as expected.

     7000 A$="TEST    BAS"
     7010 PRINT A$(1)
    

    Can the individual characters be converted to numbers and compared? 

    MID$ does seem to work. This function pulls out characters and turns them into their numeric equivalent.

     7000 A$="TEST    BAS"
     7010 C$=MID$(A$,1,1)
     7020 PRINT ASC(C$)
     7030 C$=MID$(A$,2,1)
     7040 PRINT ASC(C$)
    

    This produces 84,69 as expected. The reverse function works so it could be used one character at a time.

     7000 A$="TEST    BAS"
     7010 C$=MID$(A$,1,1)
     7020 PRINT ASC(C$)
     7030 C$=MID$(A$,2,1)
     7040 N=ASC(C$)
     7050 PRINT N
     7060 PRINT CHR$(N)
    

    This turns the second character back into the string value which can be used to compare to the value in the buffer. This code matches like it should.

     6000 A$="TEST    BAS"
     6010 DIM B(20)
     6020 V$="T"
     6030 B(5)=ASC(V$)
     6040 C$=MID$(A$,1,1)
     6050 X=ASC(C$)
     6060 IF X=B(5) THEN PRINT "OK-MATCHES"
    

    So the method is to pull the character out of the buffer, convert the character to ASCII number then compare it to the value of the string. This is painful but works. Here's the code.

     265 Q$="STARS   BAS"
    
     6010 CM=1
     6020 FOR I=1 TO 10
     6030 SE=ASC(MID$(Q$,I,1))
     6040 IF MA(DF+I-1)<>SE THEN CM=0
     6050 NEXT I
     6060 IF CM=1 THEN PRINT "FILE FOUND"
     6190 RETURN
    

     This returns:

    SPLAT.BAS      4942 CLUSTER OFFSET 150
    FILE FOUND
    STARS.BAS      1590 CLUSTER OFFSET 151
    STARTR~1.BAS   8481 CLUSTER OFFSET 152
    

    For some unknown reason typing in 151 does not work. Smaller numbers are OK. Looking for WAR returned 112 which did get the correct file. Added code to prompt fpor a file name and if that file name was found in the directory then print the first block of the file. Name still has to be entered with spaces but this same method could work for comparisons.

    Checked code into GitHub.

  • Print the file cluster offset

    land-boards.com05/11/2022 at 17:22 0 comments

    Back to the Directory Entry Structure table:

    The offset to the cluster is at locations 20-21 and 26-27. The code to support this is:

     4550 PRINT " ";:PRINT ((MA(DF+30)*65536)+(MA(DF+29)*256)+MA(DF+28));
     4560 AC=(65536*MA(DF+21))+(256*MA(DF+27))+MA(DF+26)
     4570 PRINT "CLUSTER OFFSET";:PRINT AC
    

    The result looks like this now.

    *** DIRECTORY START ***
    SYSTEM~1.      0 CLUSTER OFFSET 3
    HOCKEY.BAS     8377 CLUSTER OFFSET 5
    HORSER~1.BAS   3014 CLUSTER OFFSET 6
    HURKLE.BAS     1390 CLUSTER OFFSET 7
    KINEMA.BAS     813 CLUSTER OFFSET 8
    KING.BAS       8950 CLUSTER OFFSET 9
    LABYRI~1.BAS   4988 CLUSTER OFFSET 10
    LETTER.BAS     935 CLUSTER OFFSET 11
    LIFE2.BAS      2298 CLUSTER OFFSET 12
    ...

    It should now be possible to replace the cluster offset with a value that gets typed in by the user. Wrote the code and is worked. Top part is:

     270 GOSUB 5200:REM PRINT DIRECTORY
     280 INPUT "FILE OFFSET";FS
     360 GOSUB 5000:REM PRINT FILE AT 9
    

    The file listing dumps the first block of the file.  For QUBIC.BAS: 

    FILE OFFSET? 129
    FILE OFFSET SECTOR 32704
    000 35 30 20 50 52 49 4E 54 20 43 48 52 24 28 32 36  50 PRINT CHR$(26
    010 29 3A 57 49 44 54 48 20 38 30 0D 0A 31 30 30 20  ):WIDTH 80..100
    020 50 52 49 4E 54 20 54 41 42 28 33 33 29 3B 22 51  PRINT TAB(33);"Q
    030 55 42 49 43 22 3A 50 52 49 4E 54 0D 0A 31 31 30  UBIC":PRINT..110
    040 20 50 52 49 4E 54 20 54 41 42 28 31 35 29 3B 22   PRINT TAB(15);"
    050 43 52 45 41 54 49 56 45 20 43 4F 4D 50 55 54 49  CREATIVE COMPUTI
    060 4E 47 20 20 4D 4F 52 52 49 53 54 4F 57 4E 2C 20  NG  MORRISTOWN,
    070 4E 45 57 20 4A 45 52 53 45 59 22 0D 0A 31 32 30  NEW JERSEY"..120
    080 20 50 52 49 4E 54 3A 50 52 49 4E 54 3A 50 52 49   PRINT:PRINT:PRI
    090 4E 54 0D 0A 32 31 30 20 50 52 49 4E 54 20 22 44  NT..210 PRINT "D
    0A0 4F 20 59 4F 55 20 57 41 4E 54 20 49 4E 53 54 52  O YOU WANT INSTR
    0B0 55 43 54 49 4F 4E 53 22 3B 0D 0A 32 32 30 20 49  UCTIONS";..220 I
    0C0 4E 50 55 54 20 43 24 0D 0A 32 33 30 20 49 46 20  NPUT C$..230 IF
    0D0 4C 45 46 54 24 28 43 24 2C 31 29 3D 22 4E 22 20  LEFT$(C$,1)="N"
    0E0 54 48 45 4E 20 33 31 35 0D 0A 32 34 30 20 49 46  THEN 315..240 IF
    0F0 20 4C 45 46 54 24 28 43 24 2C 31 29 3D 22 59 22   LEFT$(C$,1)="Y"
    100 20 54 48 45 4E 20 32 36 35 0D 0A 32 35 30 20 50   THEN 265..250 P
    110 52 49 4E 54 20 22 49 4E 43 4F 52 52 45 43 54 20  RINT "INCORRECT
    120 41 4E 53 57 45 52 2E 20 20 50 4C 45 41 53 45 20  ANSWER.  PLEASE
    130 54 59 50 45 20 27 59 45 53 27 20 4F 52 20 27 4E  TYPE 'YES' OR 'N
    140 4F 27 22 3B 0D 0A 32 36 30 20 47 4F 54 4F 20 32  O'";..260 GOTO 2
    150 32 30 0D 0A 32 36 35 20 50 52 49 4E 54 0D 0A 32  20..265 PRINT..2
    160 37 30 20 50 52 49 4E 54 20 22 54 48 45 20 47 41  70 PRINT "THE GA
    170 4D 45 20 49 53 20 54 49 43 2D 54 41 43 2D 54 4F  ME IS TIC-TAC-TO
    180 45 20 49 4E 20 41 20 34 20 58 20 34 20 58 20 34  E IN A 4 X 4 X 4
    190 20 43 55 42 45 2E 22 0D 0A 32 38 30 20 50 52 49   CUBE."..280 PRI
    1A0 4E 54 20 22 45 41 43 48 20 4D 4F 56 45 20 49 53  NT "EACH MOVE IS
    1B0 20 49 4E 44 49 43 41 54 45 44 20 42 59 20 41 20   INDICATED BY A
    1C0 33 20 44 49 47 49 54 20 4E 55 4D 42 45 52 2C 20  3 DIGIT NUMBER,
    1D0 57 49 54 48 20 45 41 43 48 22 0D 0A 32 39 30 20  WITH EACH"..290
    1E0 50 52 49 4E 54 20 22 44 49 47 49 54 20 42 45 54  PRINT "DIGIT BET
    1F0 57 45 45 4E 20 31 20 41 4E 44 20 34 20 49 4E 43  WEEN 1 AND 4 INC
    
    

    One complication of loading BASIC programs is that BASIC is tokenized. There's a few ways to handle this.

    • Do the tokenization and convert ASCII code to tokenized code at load time
    • Load initially over serial port and save the file to the SD card as tokenized
    • Intercept the BASIC LOAD/SAVE calls
      • Could this be done at the I/O routine level? Or would BASIC need to be re-built? Hints are in here.
    • Put the SD card code into an IOP16 core and emulate the serial port
      • Advantage is this could be ported to any design - not just the OSI UK101

    Thinking about other ways.

    Loading C1P machine code should be much easier. The format is pretty simple:

    000 2E 30 34 30 30 2F 41 32 0D 44 45 0D 41 39 0D 30  .0400/A2.DE.A9.0
    010 34 0D 32 30 0D 33 45 0D 30 34 0D 32 30 0D 33...
    Read more »

  • Small Improvement to Directory Listing

    land-boards.com05/11/2022 at 12:14 0 comments

    Add spaces to the directory listing to pad out to the size. New code is:

     4600 REM
     4610 DF=0:REM START AT FIRST ENTRY
     4620 IF MA(DF+2)<>0 THEN GOSUB 4400:REM PRINT CURRENT DIR ENTRY
     4630 DF=DF+32:REM ADVANCE TO NEXT DIR ENTRY
     4640 IF DF<512 GOTO 4620:REM BLOCKS ARE 512 BYTES
     4660 RETURN
     4800 REM POKE LBA, CHECK STAT, READ BLOCK TO MA()
     4810 GOSUB 3800:REM POKE LBA VALS
     4820 GOSUB 2200:REM CHECK CARD INIT STATUS
     4830 GOSUB 2400:REM READ IN BLOCK
     4840 RETURN

    Result is better 

    *** DIRECTORY ***
    SYSTEM~1.      0
    HOCKEY.BAS     8377
    HORSER~1.BAS   3014
    HURKLE.BAS     1390
    KINEMA.BAS     813
    KING.BAS       8950
    LABYRI~1.BAS   4988
    

  • Find the next Directory Block

    land-boards.com05/11/2022 at 11:25 0 comments

    The previous log properly parsed the first directory block but it did not go through all the directory blocks. Where is the next directory block? A hint is here.

    For FAT32, the root directory can be of variable size 
    and is a cluster chain, just like any other directory is. 
    The first cluster of the root directory on a FAT32 volume 
    is stored in BPB_RootClus.

    Each entry is:

    Picking one entry in the middle:

    080 48 4F 43 4B 45 59 20 20 42 41 53 20 00 23 BD 8C  HOCKEY  BAS .#..
    090 A9 54 A9 54 00 00 F5 91 4D 54 05 00 B9 20 00 00  .T.T....MT... ..
    
    • Offset 0-10 = Short File Name - "HOCKEY  BAS"
    • Offset 11 = 0x20 - ATTR_ARCHIVE (see below)
    • Offset 12 = 0x00 NT_Reserved - is 0 like it should be
    • Offset 13 - 0x23 = Millisecond timestamp - ignore
    • Offset 14-19 = BD 8C A9 54 A9 54 - Not sure what this is but there's stuff in there and it's different for each entry
    • Offset 20-21 = 00 00 - High word of entry's first cluster
    • Offset 22-23 = F5 91 - Last Time
    • Offset 24-25 = 4D 54  - Last Date
    • Offset 27-28 = 05 00 - Low word of entry's first cluster
    • Offset 28-31 = B9 20 00 00 - File size

    For example HOCKEY.BAS is at offset 0x00 00 00 05.

    There's no chain element in this entry.

    Note about the ATTR_ARCHIVE - This attribute supports backup utilities. This bit is set by the FAT file system driver when a file is created, renamed, or written to. Backup utilities may use this attribute to indicate which files on the volume have been modified since the last time that a backup was performed.

    The first character in the Short File name has special meaning.

    • If DIR_Name[0] == 0xE5, then the directory entry is free (there is no file or directory name in this entry).
    • If DIR_Name[0] == 0x00, then the directory entry is free (same as for 0xE5), and there are no allocated directory entries after this one (all of the DIR_Name[0] bytes in all of the entries after this one are also set to 0).

    The special 0 value, rather than the 0xE5 value, indicates to FAT file system driver code that the rest of the entries in this directory do not need to be examined because they are all free.

    Nothing There

    There's nothing in the directory block that tells where the next block is located. Backing up a level to the FAT32 FSInfo Sector Structure.

    The root directory seems to be in consecutive block. Added code to read blocks until a block that starts with the first item equal to 0x00.

    Result is:

    *** DIRECTORY START ***
    SYSTEM~1.      0
    HOCKEY.BAS     8377
    HORSER~1.BAS   3014
    HURKLE.BAS     1390
    KINEMA.BAS     813
    ...
    [CLIPPED HERE
    ...
    STARTR~1.BAS   8481
    STOCK.BAS      7440
    SUPERS~1.BAS   20045
    SUPERS~2.BAS   5960
    SWING.BAS      1151
    SYNONYM.BAS    1981
    T1000.BAS      32
    TANKFORT.BAS   3456
    *** DIRECTORY END ***
    

    The code is:

     5200 REM READ/PRINT ROOT DIRECTORY
     5210 BO=0
     5220 PRINT "*** DIRECTORY START ***"
     5230 L0=(DS+BO) AND 255:L1=(DS+BO)/256:L2=(DS+BO)/65536
     5240 GOSUB 4800:REM READ BLOCK
     5250 IF MA(0)=0 THEN GOTO 5300
     5260 REM GOSUB 3000:REM DUMP ARRAY
     5270 GOSUB 4600:REM PRINT DIRECTORY
     5280 BO=BO+1
     5290 GOTO 5230
     5300 PRINT "*** DIRECTORY END ***"
     5310 RETURN
    

    It works but I'm not sure if it is a robust result since I am assuming that the directory is in consecutive blocks. Moving on for the moment.

    I think the answer is in Rebuilding FAT cluster chains.

    By now you know from the previous entries that this structure 
    in the FAT was zeroed out when the file was deleted and that 
    the file system uses the data contained in these 16 bit cluster 
    entries to map out the file's location on disk. Without this map,
    who knows where the file lies.
    
    To rebuild the map, we have to populate the 16 bit cluster 
    entries with cluster addresses where the data resides on disk. 
    We saw in the previous entry that the FAT Directory Entry told 
    us the file began in cluster two. We know from the way a 
    file system optimizes writes that it will put the file down 
    contiguously if it can and in this instance we have enough 
    available cluster entries in...
    Read more »

  • Parse the Directory Better

    land-boards.com05/11/2022 at 10:55 0 comments

    The previous logs found its way to the directory on an SD card when the first LBA contained a partition table. It was able to "roughly" read in the directory but had trouble with proper parsing when the directory had long file names.

    This log is a quick solution to that issue. If successful, this should produce a clean listing of the part of the directory in the first LBA.

    Directory entries are 32-bytes per entry. Here's the first directory LBA seperated into 32-byte chunks..

    DIR SECTOR #    24576  96  0
    READING LBA   24576
    000 42 20 00 49 00 6E 00 66 00 6F 00 0F 00 72 72 00  B .I.n.f.o...rr.
    010 6D 00 61 00 74 00 69 00 6F 00 00 00 6E 00 00 00  m.a.t.i.o...n...
    
    020 01 53 00 79 00 73 00 74 00 65 00 0F 00 72 6D 00  .S.y.s.t.e...rm.
    030 20 00 56 00 6F 00 6C 00 75 00 00 00 6D 00 65 00   .V.o.l.u...m.e.
    
    040 53 59 53 54 45 4D 7E 31 20 20 20 16 00 99 98 8C  SYSTEM~1   .....
    050 A9 54 A9 54 00 00 99 8C A9 54 03 00 00 00 00 00  .T.T.....T......
    
    060 41 48 00 6F 00 63 00 6B 00 65 00 0F 00 69 79 00  AH.o.c.k.e...iy.
    070 2E 00 62 00 61 00 73 00 00 00 00 00 FF FF FF FF  ..b.a.s.........
    
    080 48 4F 43 4B 45 59 20 20 42 41 53 20 00 23 BD 8C  HOCKEY  BAS .#..
    090 A9 54 A9 54 00 00 F5 91 4D 54 05 00 B9 20 00 00  .T.T....MT... ..
    
    0A0 41 48 00 6F 00 72 00 73 00 65 00 0F 00 63 52 00  AH.o.r.s.e...cR.
    0B0 61 00 63 00 65 00 2E 00 62 00 00 00 61 00 73 00  a.c.e...b...a.s.
    
    0C0 48 4F 52 53 45 52 7E 31 42 41 53 20 00 4B BD 8C  HORSER~1BAS .K..
    0D0 A9 54 A9 54 00 00 01 92 4D 54 06 00 C6 0B 00 00  .T.T....MT......
    
    0E0 41 48 00 75 00 72 00 6B 00 6C 00 0F 00 39 65 00  AH.u.r.k.l...9e.
    0F0 2E 00 62 00 61 00 73 00 00 00 00 00 FF FF FF FF  ..b.a.s.........
    
    100 48 55 52 4B 4C 45 20 20 42 41 53 20 00 52 BD 8C  HURKLE  BAS .R..
    110 A9 54 A9 54 00 00 F7 54 F1 52 07 00 6E 05 00 00  .T.T...T.R..n...
    
    120 41 4B 00 69 00 6E 00 65 00 6D 00 0F 00 17 61 00  AK.i.n.e.m....a.
    130 2E 00 62 00 61 00 73 00 00 00 00 00 FF FF FF FF  ..b.a.s.........
    
    140 4B 49 4E 45 4D 41 20 20 42 41 53 20 00 55 BD 8C  KINEMA  BAS .U..
    150 A9 54 A9 54 00 00 F7 54 F1 52 08 00 2D 03 00 00  .T.T...T.R..-...
    
    160 41 4B 00 69 00 6E 00 67 00 2E 00 0F 00 DD 62 00  AK.i.n.g......b.
    170 61 00 73 00 00 00 FF FF FF FF 00 00 FF FF FF FF  a.s.............
    
    180 4B 49 4E 47 20 20 20 20 42 41 53 20 00 58 BD 8C  KING    BAS .X..
    190 A9 54 A9 54 00 00 F7 54 F1 52 09 00 F6 22 00 00  .T.T...T.R..."..
    
    1A0 42 69 00 63 00 00 00 FF FF FF FF 0F 00 A4 FF FF  Bi.c............
    1B0 FF FF FF FF FF FF FF FF FF FF 00 00 FF FF FF FF  ................
    
    1C0 01 6C 00 61 00 62 00 79 00 72 00 0F 00 A4 69 00  .l.a.b.y.r....i.
    1D0 6E 00 74 00 68 00 2E 00 62 00 00 00 61 00 73 00  n.t.h...b...a.s.
    
    1E0 4C 41 42 59 52 49 7E 31 42 41 53 20 00 5E BD 8C  LABYRI~1BAS .^..
    1F0 A9 54 A9 54 00 00 F8 54 F1 52 0A 00 7C 13 00 00  .T.T...T.R..|...
    

    A quick filter of each of the entries could be to look at the third byte. If the third byte is 0x00 then skip the record.

    BASIC Code

    The BASIC code is in GitHub here. So far, the code is able to read in the first directory block but it does a poor job of parsing the directory. Let's improve the directory code by looking at 32 byte chunks. The previous code stepped forward in 64 byte chunks but really should step in 32 byte chunks. 

    Here's the previous BASIC code:

     4400 REM PRINT DIR ENTRY
     4410 FOR I=0 TO 7
     4420 IF MA(DF+I)<>32 THEN PRINT CHR$(MA(DF+I));
     4430 NEXT I
     4440 PRINT ".";
     4450 FOR I=8 TO 10
     4460 IF MA(DF+I)<> 32 THEN PRINT CHR$(MA(DF+I));
     4470 NEXT I
     4480 REM PRINT
     4490 PRINT " ";:PRINT ((MA(DF+30)*65536)+(MA(DF+29)*256)+MA(DF+28))
     4500 RETURN
     4600 PRINT "*** DIRECTORY ***"
     4610 DF=128:REM DIR OFFSET
     4620 GOSUB 4400:REM PRINT CURRENT DIR ENTRY
     4630 DF=DF+64
     4640 IF DF<512 GOTO 4620
     4650 FF=DS+((9-2)*SC):REM MANUALLY ADDING FILE OFFSET
     4660 L0=FF AND 255:L1=FF/256:L2=0:L3=0
     4670 GOSUB 3800:REM POKE LBA VALS
     4680 GOSUB 2200:REM CHECK CARD INIT STATUS
     4690 GOSUB 2400:REM READ IN BLOCK
     4700 GOSUB 3000:REM DUMP ARRAY
     4710 RETURN
    

    Instead of starting at 128,. start at 0. Then, look at the...

    Read more »

  • Directory Stuff

    land-boards.com05/10/2022 at 13:33 0 comments

    I put a bunch of files on the SD card so the directory spans across multiple blocks.

    It might be fun to have a directory listing. The front of the first directory block has:

    000 42 20 00 49 00 6E 00 66 00 6F 00 0F 00 72 72 00  B .I.n.f.o...rr.
    010 6D 00 61 00 74 00 69 00 6F 00 00 00 6E 00 00 00  m.a.t.i.o...n...
    020 01 53 00 79 00 73 00 74 00 65 00 0F 00 72 6D 00  .S.y.s.t.e...rm.
    030 20 00 56 00 6F 00 6C 00 75 00 00 00 6D 00 65 00   .V.o.l.u...m.e.
    040 53 59 53 54 45 4D 7E 31 20 20 20 16 00 99 98 8C  SYSTEM~1   .....
    050 A9 54 A9 54 00 00 99 8C A9 54 03 00 00 00 00 00  .T.T.....T......
    
    060 41 48 00 6F 00 63 00 6B 00 65 00 0F 00 69 79 00  AH.o.c.k.e...iy.
    070 2E 00 62 00 61 00 73 00 00 00 00 00 FF FF FF FF  ..b.a.s.........
    080 48 4F 43 4B 45 59 20 20 42 41 53 20 00 23 BD 8C  HOCKEY  BAS .#..
    090 A9 54 A9 54 00 00 F5 91 4D 54 05 00 B9 20 00 00  .T.T....MT... ..
    
    0A0 41 48 00 6F 00 72 00 73 00 65 00 0F 00 63 52 00  AH.o.r.s.e...cR.
    0B0 61 00 63 00 65 00 2E 00 62 00 00 00 61 00 73 00  a.c.e...b...a.s.
    

    I'm going to ignore the stuff from 0x000-0x04F since it looks like volume stuff.

    Directory Entries

    The Microsoft Extensible Firmware Initiative FAT32 File System Specification provides additional information on the fields in the directory. 

    Looking a 0x060-0x09F looks like a single file's directory entry using 64 bytes. The first part from 0x060 to 0x07F looks like the file name with each character separated by a NULL character. The byte at 0x060 has looks different from the previous values since it has a value of 0x41. The 8.3 plain text file name is at 0x080-0x0x87. Spaces fill out shorter file The extension is at 0x088-0x8A.

    It should be easy to print out the directory. Let's give it a shot!

    The plain text starts at offset 0x080. Adding a BASIC function to print a single file name. The block is in the MA() array. DF is the offset to the first file directory field.

     4400 REM PRINT DIR ENTRY
     4410 FOR I=0 TO 7
     4420 IF MA(DF+I)<>32 THEN PRINT CHR$(MA(DF+I));
     4430 NEXT I
     4440 PRINT ".";
     4450 FOR I=8 TO 10
     4460 IF MA(DF+I)<> 32 THEN PRINT CHR$(MA(DF+I));
     4470 NEXT I
     4480 PRINT
     4490 RETURN
    

    The BASIC calling function to work through each directory entry is:

     360 DF=128:REM DIR OFFSET
     370 GOSUB 4400
     380 DF=DF+64
     390 IF DF<512 GOTO 370
    

    The result is:

    HORSER~1.BAS
    HURKLE.BAS
    KINEMA.BAS
    KING.BAS
    laby.r
    

    The last entry has issues that need to be figured out. The raw data is:

    160 41 4B 00 69 00 6E 00 67 00 2E 00 0F 00 DD 62 00  AK.i.n.g......b.
    170 61 00 73 00 00 00 FF FF FF FF 00 00 FF FF FF FF  a.s.............
    180 4B 49 4E 47 20 20 20 20 42 41 53 20 00 58 BD 8C  KING    BAS .X..
    190 A9 54 A9 54 00 00 F7 54 F1 52 09 00 F6 22 00 00  .T.T...T.R..."..
    
    1A0 42 69 00 63 00 00 00 FF FF FF FF 0F 00 A4 FF FF  Bi.c............
    1B0 FF FF FF FF FF FF FF FF FF FF 00 00 FF FF FF FF  ................
    
    1C0 01 6C 00 61 00 62 00 79 00 72 00 0F 00 A4 69 00  .l.a.b.y.r....i.
    1D0 6E 00 74 00 68 00 2E 00 62 00 00 00 61 00 73 00  n.t.h...b...a.s.
    1E0 4C 41 42 59 52 49 7E 31 42 41 53 20 00 5E BD 8C  LABYRI~1BAS .^..
    1F0 A9 54 A9 54 00 00 F8 54 F1 52 0A 00 7C 13 00 00  .T.T...T.R..|...
    

    The byte offset at 0x1A0 does not have 0x41. This entry also has a different size. It does not have 64 bytes so the final file name was not caught. That's likely because the file name is: labyrinth.basic . Let's ignore long file names for now.

    For each directory entry, the fields are

    In the FDISK.EXE example above:

    • 0-10 = "FDISK   EXE ".
    • 11 = 0x20: archive?
    • 26-27 = Starting cluster - 0x0020
    • 28-31 = Filesize - 0x00007317 (29463 bytes)

    For KING.BAS:

    180 4B 49 4E 47 20 20 20 20 42 41 53 20 00 58 BD 8C  KING    BAS .X..
    190 A9 54 A9 54 00 00 F7 54 F1 52 09 00 F6 22 00 00  .T.T...T.R..."..
    • 0-10 = "KING    BAS"
    • 11 = 0x20: archive?
    • 26-27 = Starting cluster - 0x0009
    • 28-31 = Filesize - 0x000022f6 (8950)

    The file size matches the File Properties:

    Reading in the file

    Added BASIC code to read in first...

    Read more »

  • ​Different SD card MBR formats

    land-boards.com05/09/2022 at 22:31 0 comments

    I tried a couple of other cards and found that they have different MBR formats with no header. I noted this in a previous log. There's an offset at 0x01BE that points to the MBR. My theory is this is true for "bigger" cards. I think the reason I could get it to work on the other card is that it is a small card. I think that bigger cards contain this offset to the MBR and smaller cards don't.

    Why Big Cards?

    I think the answer is that larger cards have a lot of "wasted" space at the start. There's really no point in supporting smaller cards. I tried to buy some 8GB SD cards and they are getting hard to find and expensive. 32 Gb seems to be the sweet spot at the moment. Of course, all of the existing software in the world for the OSI could easily fit onto one of these SD cards, so why not? 64 GB cards are formatted as exFAT and older devices like cameras don't support exFAT so there's likely to be some market "life" left in 32GB cards. 

    INIT STATUS - OK
    LBA0 ? 0
    LBA1 ? 0
    LBA2 ? 0
    000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    1A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    1B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 82  ................
    1C0 03 00 0C FE FF FF 00 20 00 00 00 04 B7 03 00 00  ....... ........
    1D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    1E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    1F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA  ..............U.
    

    Is the first sector Partition Table?

    A comment on this page helped.

     ...the four entry partition table stars at 0x1BE. Each entry is 16 bytes and in this case it's pretty clear only one is filled... 

    Also, on this  FAT32 Structure Information - MBR, FAT32 Boot Sector Introduction page:

    ...The Master Boot Record is the same for pretty much all Operating Systems. It is located on the first Sector of the Hard Drive, at Cylinder 0, Head 0, Sector 1. It is the first piece of code that your computer runs after it has checked all of your hardware (POST) and turned control of loading software over the hard drive. It also contains the partition table, which defines the different sections of your hard drive...

    Also see Hard Drive Partition. Partition...

    Read more »

  • DOS/65

    land-boards.com08/30/2020 at 17:36 0 comments

    It looks as if someone has done a lot of the heavy lifting towards making an operating system for the 6502. The project is DOS/65 by Richard A. Leary.

    This could save a lot of work. Richard chose to have a lot of compatibility with CP/M and I've got a lot of time already invested with the Multicomp CP/M systems.

    Not sure how tough it will be to port the DOS/65 system but it has to be a lot less than writing an OS from scratch.

  • OSISDOS Command Line

    land-boards.com08/08/2020 at 17:10 0 comments

    Now that the input and output work, it's time to work on the command line. At a high level, a notional set of commands could be:

    • mnt - mount the SD card, load/parse the boot record
    • dir - fetch the directory from the SD card and display to the screen, starts in root folder
    • cd - change directory
    • ld - load a file from the SD card

  • Screen Handler Code

    land-boards.com08/08/2020 at 11:38 0 comments

    Now that the low level SD card code is working well it's time to give some attention to the command handler. Making this work will require screen/keyboard I/O and cc65 does provide support for I/O. 

    This is where things start to get a bit ugly. To start with, there is no stdio.h support for the C1P in cc65

    conio on the C1P

    There is a conio.h file in cc65 which supports command style I/O from the console but it has serious limitations. For instance, from this page:

    ... conio doesn't scroll the screen when moving below the last line. 
    In fact, allowing that to happen might spell disaster on several
    machines because, for performance reasons, there are no checks.

    The example code from the tutorial works with some changes but it is flakey. I removed the text section from the example but will probably need to add it back in later when moving this code to the ROM.

    /* hello.c example    */
    /* conio.h docs - Not sure how well it matches    */
    /*     https://digitalmars.com/rtl/conio.html     */
    
    #include <conio.h>    /* Console I/O    */
    #include <stdlib.h>
    
    int main (void)
    {
        clrscr ();
        cprintf ("\r\nPress <RETURN>.");
        cgetc ();
        return EXIT_SUCCESS;
    }
    

    The result is that the "Press <RETURN>" message is printed to the right on the screen. It does wait for a key to be pressed so it's basically working. 

    The example above is built using this command line.

    "..\..\..\PC Tools\srecord\srec_cat.exe" hello.o -bin -of 0x300 -o hello.c1p -os -esa=0x300

    The function three functions do work (at least intermittently in the case of the cprintf function):

    • clrscr()  - Clears the screen
    • cprintf ("str") - Prints string to the screen
    • cgetc() - Waits for a character.

    The screen size on the UK101 Multicomp build is currently 48 columns x 16 rows. The default C1P screen is formatted for a different size:

    By default the conio library uses a 24 columns by 24 lines 
    screen layout for the Challenger 1P.
    
    There is a module screen-c1p-24x24.o in the OSI-specific 
    cc65 runtime library that contains all conio functions that 
    depend on the screen layout. 
    No further configuration is needed for using the default screen 
    layout of the Challenger 1P.

    There is support for other screen layouts but they are limited to:

    For other screen layouts additional versions of the screen module 
    are available.
    The linker finds these modules without further configuration if 
    they are specified on the compiler or linker command line. 
    The extra module then overrides the default module.
    
    Sample cl65 command line to override the default screen module with 
    the module osic1p-screen-s3-32x28.o:
    
    cl65 -o hello -t osic1p osic1p-screen-s3-32x28.o hello.c
    
    Currently the following extra screen configuration modules are 
    implemented:
    
    osic1p-screen-s3-32x28.o: 32 columns by 28 lines mode for 
    Briel Superboard ///

    It looks like all that needs to be done is to create a version of the osic1p-screen-s3-32x28.o file for our screen and have it override the default resolution.

    Here is the source code for the 24x24 display. with a few comments added:

    ;
    ; Implementation of screen-layout related functions for Challenger 1P
    ;
    
            .include        "osiscreen.inc"
    
    C1P_SCR_BASE    := $D000        ; Base of C1P video RAM
    C1P_VRAM_SIZE   = $0400         ; Size of C1P video RAM (1 kB)
    C1P_SCR_WIDTH   = $18           ; Screen width (24)
    C1P_SCR_HEIGHT  = $18           ; Screen height (24)
    C1P_SCR_FIRSTCHAR = $85         ; Offset of cursor position (0, 0) from base
                                    ; of video RAM
    C1P_SCROLL_DIST = $20           ; Memory distance for scrolling by one line (32 chars/line)
    
    osi_screen_funcs C1P_SCR_BASE, C1P_VRAM_SIZE, C1P_SCR_FIRSTCHAR, \
                            C1P_SCR_WIDTH, C1P_SCR_HEIGHT, C1P_SCROLL_DIST

    The windows distribution of cc65 does not include the source tree for the C1P libraries but it is on the GitHub repository located here. Changing the screen requires making a new screen file with:

    ;
    ; Implementation of 48x16 screen-layout related functions for Challenger 1P
    ;
    
            .include        "osiscreen.inc"
    
    C1P_SCR_BASE :=...
    Read more »

View all 25 project logs

Enjoy this project?

Share

Discussions

Does this project spark your interest?

Become a member to follow this project and never miss any updates