Page 11 of 14

Re: Adventures in FAT32 with 65c02

Posted: Sat Feb 07, 2026 6:39 am
by barnacle
Ach, Martin, the projects that are worrying me are a text editor that can handle large files efficiently, and a micro-C compiler :mrgreen: both of which need a working file system!

A warning/reminder: this thread has a lot of meanderings and changes in the code I've posted over time. When things finally work, I'll post the complete code for sanity. Meanwhile, I _think_ that the descriptive passages are all correct - but beware of the assumptions I've made regarding particular sector locations and cluster sizes.

To be honest, I don't think that the FAT32 implementation is significantly different from FAT16 or FAT12, though the code would not be interchangeable. The complication is that MS wrote all three... that and doing 32-bit arithmetic on the 65c02.

(The code posted last night has the cf_write calls commented out so I can test without trashing the disk!)

Neil

Re: Adventures in FAT32 with 65c02

Posted: Sat Feb 07, 2026 11:12 am
by drogon
barnacle wrote:
Ach, Martin, the projects that are worrying me are a text editor that can handle large files efficiently, and a micro-C compiler :mrgreen: both of which need a working file system!
At the risk of more meandering; Lets think about what "large" might be in the context of a 6502... (Or even a 65C816).

Which is what I did when I wrote (re-wrote/ported, again) my original C nano-like editor which I've used in several projects over the years....

You have 64KB of RAM. Lets say you have 32KB free for applications. Do you want the whole file in RAM? (Answer; Yes - because paging in bits from a file is slower than you can type) You you need to manipulate 32K of RAM. That's achievable.

My first port was to take the C version and make it run in my 65C02 board. It compiled with cc65 to about 14KB of code, using the ROM based IO routines (which were another 10K). My system is much like ye-olde BBC Micro with the top 32K being application + OS + IO and the bottom 32K for data. A good number of Acorn ROMs worked without change including BBC Basic, Comal, etc..

The editor worked very well and I could edit text files up to the size of RAM. It relies on a "malloc" which I'd already written in Sweet16. It worked well on the files I edited, but at that point I stalled - because, like you, I wanted "a micro C compiler" for the system. I could edit Basic files as text and *exec them into the system, but that was a bit tedious.

Plan B; Use BCPL. so I could load the editor (written in C), create/edit BCPL source code. Load up the BCPL system and compile and run those BCPL programs.

An iteration later and I'd re-written it in BCPL and I could just about use it on the same system running the BBC Micro BCPL system. Not much free RAM though, but as a proof of concept, I could use it to edit a BCPL source file and compile it.

Plan C; Move to the '816 and write an OS in BCPL. (He said, casually...) Adapted the editor for the new system and it trivially handles files up to 5000 lines of 250 characters long. That's a limit I artificially set. The system has 512KB of RAM - but if I were to load such a file, I'd need nearly 8MB of RAM, so that's not going to happen - in reality files I use are only a few 100 lines long. The editor itself is 1800 lines and 32KB, compiles to about 6KB in bytecode, the BCPL compiler is 2 files of 2500 and 4100 lines respectively. I can not compile the compiler on the '816 system as it takes many hours and runs out of memory. The editor compiles in a few minutes.

And that's sort of where I'm at today, but the platform has moved to RISC-V (and ARM32) with memory sizes measured in MB... The memory allocator is still "best fit" (same as it was in the Sweet16 version) and it seems to work remarkably well.

But there is still the hankering for a micro C compiler... I want one written in BCPL that produces the bytecode my system runs on.... Might have to write it myself - one day... Actually, I'd settle for one written in C that can be adapted to produce the bytecode..

-Gordon
Quote:
(The code posted last night has the cf_write calls commented out so I can test without trashing the disk!)
Neil
(Small) SD cards are cheap enough now that you can afford to treat them as almost disposable. Or no worse than old uv-eproms. Keep a stack pre-formatted and go for it.

-Gordon

Re: Adventures in FAT32 with 65c02

Posted: Sat Feb 07, 2026 1:14 pm
by barnacle
It's not that they're not disposable, Gordon; I have a dozen in various denominations sitting on the desk. It's that I need to get the exact disk image back on so I'm not chasing my tail trying to hunt bugs - consistency is all. Probably I should use dd but that's always risky; at least using Gparted and then copying files has a little visual feedback!

I'm having a minor consideration at the moment... I just wrote a small addendum to list the file system information:

Code: Select all

NeoDOS32 v0.0285                                                                
VIB sector $00000800                                                            
FSI sector $00000801                                                            
Sectors in partition $000F3800                                                  
Sectors per cluster $08                                                         
Free cluster count $0001E5EC                                                    
Next free cluster $0000007D                                                     
FAT 1 sector $00000820                                                          
FAT 2 sector $00000BF0                                                          
Sectors per fat $000003D0                                                       
Start of clusters $00000FC0                                                     
Press any key to boot:
Which is fine for a 512MB disk (which is my main test disk) but for a 2GB drive, got garbage:

Code: Select all

VIB sector $00000020                                                            
FSI sector $00000021                                                            
Sectors in partition $003D0FC0                                                  
Sectors per cluster $40                                                         
Free cluster count $00000000                                                    
Next free cluster $00000000                                                     
FAT 1 sector $00000026                                                          
FAT 2 sector $B6290126                                                          
Sectors per fat $B6290100                                                       
Start of clusters $00000226                                                     
which on inspection turns out to be because it's formatted FAT16...

I think I need to make a check at the partition identification stage to confirm that the format is as expected - specifically, it should be $0C for LBA/FAT32 - and reject the boot otherwise. The plan is that any operating system will be loaded from the disk, with only a minimal disk IO in eeprom, so an invalid disk is a no-boot anyway, but I don't want to accidentally trash an invalid disk. I may also need to confirm some other assumptions, but we'll see.

Regarding editing; yes, it may be too much to expect a 65c02 at 2MHz with only 32k (or at least, under 64k) to be able to handle megabyte text files, but I'm certainly curious to see where it falls over...

Neil

Re: Adventures in FAT32 with 65c02

Posted: Sat Feb 07, 2026 3:29 pm
by drogon
barnacle wrote:
It's not that they're not disposable, Gordon; I have a dozen in various denominations sitting on the desk. It's that I need to get the exact disk image back on so I'm not chasing my tail trying to hunt bugs - consistency is all. Probably I should use dd but that's always risky; at least using Gparted and then copying files has a little visual feedback!
Rsync is your best friend here. It can delete files created that you don't want (on the SD) and make sure existing files are identical to those stored locally and copy over missing ones.

Stick an entry in /etc/fstab to let you mount as user without sudo:

Code: Select all

UUID=5EB9-8D6F					/pico		vfat	defaults,noatime,noauto,user	0 0
(Change UUID to device like /dev/sdb1 or whatever)

Code: Select all

mount /6502
cd /path/to/local/files
rsync -n -vaHx --delete --whole-file . /6502

# then repeat without the 'n' option

umount /6502
(Oh, assumes Linuxy type system, but I guess that's what you have with gparted and dd)

Gordon

Re: Adventures in FAT32 with 65c02

Posted: Sat Feb 07, 2026 4:55 pm
by barnacle
I considered rsync (yes, this is a linux house) but it doesn't (afaik) do a bitwise media copy. If I damage the FATs or the partition table or the VIB or FSI sectors, half the time the cf won't mount on my linux box. Formatting and rebuilding puts things back as they should be.

It's a _very_ fragile file system, as we've discussed earlier.

But thanks for the tip.

Neil

Re: Adventures in FAT32 with 65c02

Posted: Sat Feb 07, 2026 11:23 pm
by BigDumbDinosaur
barnacle wrote:
I considered rsync (yes, this is a linux house) but it doesn't (afaik) do a bitwise media copy.
Correct: rsync knows about files on the disk, not how they are organized and stored.  Nor does rsync know anything about the disk’s boot block, partition table, etc..

I think dd is your friend in this case, but working with raw dd commands can be perilous.  Given the nature of what you are doing, you need to wrap dd in a script to semi-automate the process.  The good thing about dd is you don’t have to be able to mount a filesystem on the CF card to restore the card’s content from an image file on your server.

I routinely use dd to restore disks when I’m fooling around with things that might make a mess, e.g., a custom kernel.  However, I run dd through a BASH script that asks questions so I get it right.  Needless to say, accidentally mixing up dd’s if= and of= parameters can be mighty unpleasant!  :evil:

Re: Adventures in FAT32 with 65c02

Posted: Sun Feb 08, 2026 6:42 am
by barnacle
As the old saw has it: 'dd' doesn't only allow you to shoot yourself in the foot, it loads the gun before handing it to you.

I've just spent ten days recovering data from a failed NAS - successfully, though it was touch and go for a while - and I don't want to have to repeat the process on my working machine!

Neil

Re: Adventures in FAT32 with 65c02

Posted: Sun Feb 08, 2026 8:28 am
by BigDumbDinosaur
barnacle wrote:
As the old saw has it: 'dd' doesn't only allow you to shoot yourself in the foot, it loads the gun before handing it to you.
My distant experience is that when you mess up with dd, the gun is aimed much higher than the foot.  :cry:
Quote:
I've just spent ten days recovering data from a failed NAS - successfully, though it was touch and go for a while - and I don't want to have to repeat the process on my working machine!
It’s been quite a while since I’ve had to do a bare-metal recovery on one of my servers.  I had to do that about a year ago for a client following repeated warnings to them that they were way overdue for fresh disks in their servers.

Re: Adventures in FAT32 with 65c02

Posted: Sun Feb 08, 2026 9:02 am
by barnacle
In this case it turned out that the drives were still ok; the controller (single point of failure!) had decided they were no longer formatted. Strange. I was able to mount one of the drives in an external controller, force it to behave as a raid array with one disk missing, and then mount it as a visible disk and copy from that to another external portable disk.

The new QNAP NAS included a (3!) USB ports on the back and was able to copy from the external drive to the array in a few hours... copying from the same drive to the old Buffalo NAS (which lacked that facility) via my last laptop took nearly three days.

But now I have the data recovered on three systems...

Neil

Re: Adventures in FAT32 with 65c02

Posted: Sun Feb 08, 2026 2:51 pm
by barnacle
One step forwards, one step back...

I've added some code that does a test for a partition type $0b or $0c (both are FAT32, the first says CHS addressing, the second LBA addressing - but apparently all IDE drives understand LBA addressing) and does a hang with "Invalid Partition" displayed if the partition type isn't one of those two.

I also derive the location of the FSI sector the 'proper' way by looking at offset 48 ($30) in the VIB, though it turns out to be in every case where I expected it to be (immediately after the VIB).

But... most of the code is written on the assumption that there are eight sectors per cluster. This turns out not to be the case. I could format and tell it to use eight, but I'd rather be able to deal with the correct value irrespective of the CF card, if it's FAT32. And the 4GB card I have it uses 64 ($40) sectors per cluster... so I'm going to have to make some modifications to the code, and do a lot of regression testing before I go further.

Aye well,

Neil

Re: Adventures in FAT32 with 65c02

Posted: Fri Feb 13, 2026 9:29 am
by barnacle
So, after a certain amount of hunting down and jumping on all my divide-by-eight assumptions, I think I've got 'em all. The regression tests work: correct listing of a large directory, correct printing of a large (i.e. multi-cluster) text file, general lack of the program disappearing up itself and crashing horribly.

(As an aside: what's the failure mode for an AT28C256 eeprom? My homebrew programmer powers them at 5v but drives the pins at 3v3; it seems that as the parts are programmed more often the data is not always sticking. That's after a few hundred erase/program cycles in my possession, but the parts are almost certainly ebay/aliexpress 'new', i.e. board pulls.)

Now I have a decimal output routine, I shall modify the dir function to include the size.

Meanwhile, here are the two routines that caused some annoyance, because they multiply/divide by the secs_per_cluster value rather than simply incrementing till they get there...

Code: Select all

;-----------------------------------------------------------------------
; clus_to_1st_sec
;
; Returns the LBA of the first sector of a cluster
;
; On entry: lba contains the cluster number (i.e. the FAT record number)
; On exit: lba contains the first sector of that cluster
; 1st_sector = ((cluster - 2) * secs_per_cluster) + cluster_begin_lba
; NOTE: secs_per_cluster is one of 1, 2, 4, 8, 16, 32, 60, 128

clus_to_1st_sec:
	LYA two
	jsr u32_sub				; lba = record minus two	
	ldy secs_per_cluster	; shift this right; shift lba left
fs_ct_1:
	tya
	lsr a
	tay						; y >>= 2
	beq fs_ct_2				; lba = lba * sectors per cluster	
	asl lba
	rol lba+1
	rol lba+2
	rol lba+3				; multiply by two
	bra fs_ct_1
fs_ct_2:	
	LYA cluster_begin_lba
	jsr u32_add				; and that should be that, result in lba
	rts

;-----------------------------------------------------------------------
; sec_to_clus
;
; Return the cluster number for any sector within that cluster
; On entry: lba contains the sector's LBA
; On exit: lba contains the cluster number
;
; cluster = ((lba - cluster_begin_lba) / secs_per_cluster) + 2

sec_to_cluster:
	LYA cluster_begin_lba
	jsr u32_sub
	ldy secs_per_cluster
fs_stc_1:
	tya
	lsr a
	tay						; y >>= 2
	beq fs_stc_2
	lsr lba+3
	ror lba+2
	ror lba+1
	ror lba					; divide by two
	bra fs_stc_1			; until lba = lba / secs_per_cluster
fs_stc_2:
	LYA two
	jsr u32_add				; the first cluster is #2
	rts
	
;-----------------------------------------------------------------------
Neil

Re: Adventures in FAT32 with 65c02

Posted: Fri Feb 13, 2026 10:14 am
by barnacle

Code: Select all

NeoDOS32 v0.0341                                                                
VIB sector $00000800                                                            
FSI sector $00000801                                                            
Sectors in partition $000F3800                                                  
Sectors per cluster $08                                                         
Free cluster count $0001E553                                                    
Next free cluster $000000B0                                                     
FAT 1 sector $00000820                                                          
FAT 2 sector $00000BF0                                                          
Sectors per fat $000003D0                                                       
Start of clusters $00000FC0                                                     
Press any key to boot:                                                          
AS65            60268                                                           
BIOS.ASM        12326                                                           
CF.ASM          6323                                                            
DOS.ASM         18206                                                           
FILE_SYS.ASM    14012                                                           
MAIN.ASM        8190                                                            
MAIN.HEX        9192                                                            
MAIN.LST        173092                                                          
SERIAL          21608                                                           
U32MATHS.ASM    6905                                                            
VARS.ASM        8960                                                            
PG6133.TXT      344217                                                          
Finished   
On terminals with eight-space tabs, this all lines up nicely. For some reason, this board uses three spaces...

Neil

Re: Adventures in FAT32 with 65c02

Posted: Fri Feb 13, 2026 7:17 pm
by BigDumbDinosaur
barnacle wrote:
(As an aside: what's the failure mode for an AT28C256 eeprom? My homebrew programmer powers them at 5v but drives the pins at 3v3; it seems that as the parts are programmed more often the data is not always sticking. That's after a few hundred erase/program cycles in my possession, but the parts are almost certainly ebay/aliexpress 'new', i.e. board pulls.)
EEPROMs are subject to wear-out failures.  If your parts are pulls, it’s anybody’s guess as to how many erase/program cycles they have endured.  Also, they may have been exposed to some ESD when they were being salvaged.

Incidentally, I have found that UV-erasable EPROMs wear out as well.  They will erase okay, but will end up with one or more stuck bits.  Over time, my large stock of EPROMs has shrunk as individual devices have failed verification after programming.  When that happens, I set the bad part aside with others and later subject all of them to a longer-than-normal erase cycle, followed by a test—almost always, they will fail again.  I have had some of these EPROMs for 20+ years, so I figure I’ve gotten my money’s worth out of them.

As EPROMs have become hideously expensive, and EEPROMs have traditionally been slow, my latest POC deign will be using a flash ROM.  Those are inexpensive and available in speed grades down to 55ns.  The faster ones are usually in PLCC packages.

Re: Adventures in FAT32 with 65c02

Posted: Fri Feb 13, 2026 8:12 pm
by barnacle
Yeah. I'm having difficulties finding fast eeproms. I have some faster flash memories in stock, but need to sort out a programmer. And it gripes my economical Yorkshire soul to stick a megabyte in when I only need a few K :)

Not happy that I appear to have lost the source for my eeprom programmer - I think STM did something odd with one of their recent builds; I lost a couple of other things too. So I'll have to write it again, I guess.

Neil

Re: Adventures in FAT32 with 65c02

Posted: Fri Feb 13, 2026 9:22 pm
by drogon
barnacle wrote:
Yeah. I'm having difficulties finding fast eeproms. I have some faster flash memories in stock, but need to sort out a programmer. And it gripes my economical Yorkshire soul to stick a megabyte in when I only need a few K :)
And for those not in the UK, the definition of a Yorkshireman is along the lines of "a Scotsman with the sense of generosity removed" ... ;-)

-Gordon