em00k / NXModPlayer

Amiga MOD player for the ZX Spectrum Next
14 stars 0 forks source link

Long module or folder filenames may parse incorrectly #1

Open KevReillyUK opened 1 year ago

KevReillyUK commented 1 year ago

Some quirks with the built-in browser:

If a module has more than 40 characters in its filename (including any NextZXOS {LOAD=} flags and the file extension) it will wrap onto the next line of the built-in browser and appear to be a separate entry.

Selecting the non-wrapped part of the filename will load the module or open the folder as expected. (edit: this is true only if the item is the last one in the list -- see comments below)

If the file or folder is the last item in the list, selecting its wrapped part will return to the player in a paused and indeterminate state. Sometimes a restart (R) will return to the previously playing module, while other times it is necessary to press ENTER and (re-)select a valid module from the list.

If the file or folder is not the last item in the list, the name of the next file or folder on the SD card will be displayed on the same line as the wrapped characters. If the second filename is longer than the number of wrapped characters from the first it will overwrite them, and it will load or open correctly when selected in the browser. But if the second filename is shorter than the number of wrapped characters it will show with the excess characters appended, and when selected it will return to the player in the same indeterminate state as above.

Just to add to the confusion, a folder with a filename of exactly 40 characters will always return to the player in an indeterminate state when selected. A 39 character folder will work fine, as will one with more than 40 characters.

I hope this makes sense. It's easier to experience than to describe.

em00k commented 1 year ago

So while on the outside it might seem like a simple change, however supporting filenames that are VERY long is a bit of an issue. When NXModPlayer launches it takes over the entire machine, NextZXOS is no more so can't use relied on for any of its functions, the mod engine uses all banks slots but 3,4,5. So we have to write our own browser, we have to page in the ROM and then we can call the esxdos calls which don't rely on NextZXOS to be healthy.

So this means all file actions have to be done manually, esxdos isn't super flexible. For instance to read a dir, we set the dir with rst call - we do a REWINDDIR to make sure we're at the start item for the that dir, then we can call a READDIR - this will return the next entry. This contains info like FILE ATTRIBUTES, FILENAME, FILESIZE. Once you have called READDIR, the only option you have is to get the NEXT item or REWIND, we cannot get the previous file, or move back 2 files.

But in the browser we need to be able to move back to a previous page? How?

You can do another call F_TELLDIR which will tell you the FILEPOS of a file location in the folder. We can't really read all the entries and cache the filenames themselves because it would take quite a bit of RAM and quite fiddly to parse hundreds of filename that have no fixed length (but max is 261).

So, we need to be able to traverse through the directory if we have more than a page worth of files - we can this by storing the FILEPOS of the first entry of each page and store it, using READDIR to grab 22 items at a time.

We also need to keep SD access to a minimum, as we have to disable the player momentarily while we do our file access (this is the little pauses that can be heard we moving around the browser)

What I do is read all the entries in a folder, then store the FILEPOS of every file that is an offset of 22 in a table - for 1024 items this takes up around 4KB (4 bytes per FILEPOS) - then we move to the next page we can get the PAGE(224) from our bank will = FILEPOS of the Next page.

To reduce memory usage, when the filename is printed to screen, this is the only time I make a copy of the filename, when you select and ITEM to load, it reads the text that is on screen for the filename.

So implementing extended filenames starts to make things much more complicated because all FNs would need to be cached and retrieved in their full form.

The best I could probably do is an 80 column version that would increase the filenames to 80 - but I am a firm believer in 8bit systems should not be having filenames that are more than 20 chars :D

Hope that helps!

KevReillyUK commented 1 year ago

Wow. Much more complex than I thought, although it's interesting that I ignored one of my earliest theories -- that the program must be reading the filename characters directly from the screen -- because it seemed ridiculously kludgy and inefficient. But if the goal is to spare every byte, it actually makes sense.

I just did some more experimentation with deliberately named long and short files, because I was certain I'd seen wrapped files load correctly from their first line even when the next entry had stamped all over their wrapped part. But having tested it, that's not the case. I don't know how I drew that erroneous conclusion, but I'll edit the original post to clarify.

Aside from that error, everything I've seen ties in with your detailed description.

The only thing that puzzles me is how esxDOS "knows" the length of the filename when it reads it from the screen, such that it can successfully read an entire wrapped filename provided it's the last entry on the page. I thought it might be looking for an invisible carriage return, but that would mean short filenames overwriting earlier wraps would also load correctly, and they don't.

Might it be possible to read the length of the filename itself before printing it to the screen, and if it's longer than 40 characters use the 8.3 version instead? I'm just spitballing here because I don't know what metadata or functions are available through esxDOS.

In the meantime I have no objection to duplicating my MODs into the folder next to the executable where I won't have to navigate through possibly problematic folder trees to get to them. My SD card is 64GB, so it's not as though I'm short on storage.

(To be fair, I only noticed this problem because the folder (C:/!USER/MUSIC/) containing my MODs folder (SONGS/MODS) also contains a bunch of music-based .TAP and .Z80 demos with filenames longer than 40 characters. Most of the MODs themselves have relatively short names, and wouldn't have triggered this on their own, so this might not be a problem seen by many users. But if anyone has a structured MOD archive that uses, for example, an {artist}{group}{song name} file format then some filenames could quickly exceed 40 characters.)