Repository navigation
formats/fs_prodos.cpp: Treat zero master index entries in tree files as sparse - #16103
Merged
ajrhacker merged 1 commit intoSep 14, 2026
Merged
Conversation
…as sparse A tree file whose master index block has a zero entry has no index block for that 128K range: ProDOS allocates neither the index block nor its data blocks, and reads the range back as zeros (ProDOS 8 Technical Reference Manual, B.3.6). any_read and any_blocks fetched block 0, the boot block, and used its bytes as data block pointers, so reading such a file either failed with a block number overflow or returned blocks belonging to other files, and flopblocks/hdblocks listed block 0 and a few hundred unrelated blocks as belonging to the file. This is the same case 47891bc handled for zero entries inside an index block, one level up.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
While reading 47891bc, which pads zero pointers inside an index block with NULs instead of reading the boot block, I noticed the tree file branch of
any_readstill takes each master index entry at face value. A zero there is the same situation one level up. ProDOS doesn't allocate an index block when none of its 256 data blocks are allocated, and the whole 128K range reads back as zeros (ProDOS 8 Technical Reference Manual, B.3.6). MAME fetches block 0 instead and uses the boot code as a list of data block pointers.any_blockshas the same loop, so it also records block 0 as allocated and walks the boot block.To check this I built floptool and generated a raw ProDOS volume with a tree file laid out the way ProDOS writes a sparse one: master index entry 0 points to an index block whose first data block is filled with 'F', entry 1 is zero, entry 2 points to an index block whose first data block is filled with 'A', EOF 256.5K. Next to it is an ordinary tree file with every block allocated, as a control.
Without this change:
floptool hdread prodos vol.po SPARSE outfails withBlock number overflow: requiring block 37121 on device of size 1600. 37121 is 0x9101, i.e.boot[0x000] | boot[0x100] << 8.floptool hdblocksreports the file as allocation blocks10-11,0,12and data blocks13,37121,24632,51376,..., a few hundred entries long.With it, the file reads back as 512 'F' bytes, zeros up to 256K, then 512 'A' bytes on both volume sizes.
hdblocksreports10-12and13-14. The control file reads and enumerates the same before and after. Seedling and sapling files take other branches and aren't affected, and the ProDOS code in floptool is read-only, so nothing on the write side depends on the old behaviour.Script used to build the volume and check floptool's output
Run as
python3 sparse_tree.py <mame checkout with floptool built> [block count].AI tools used