The problem with doing this is that DLIs are non-maskable interrupts and thus run at highest priority. Exceed 8 scanlines within a DLI and you are guaranteed to cause a serial input overrun and fail a transfer at 19200 baud. That's less than 900 cycles of run time.
If you've just got little bit to run like a bit of color cycling or a counter, you can run it off of the VBI or a POKEY timer and safely interleave it with the standard SIO routines. Any sort of actual game logic and you're going to need a custom disk routine. The standard routines only use the foreground task for simply polling for completion of the interrupt-driven transfer, but you have no guarantee of that. With PBI or a high-speed SIO routine, it's more likely straight polling with IRQs off. What you don't want to do is try to wedge your own meaty foreground task into the standard SIO routines -- that way lies madness. Easier to use a custom disk routine where you actually know what code you're hooking into rather than some unknown and potentially patched OS.
You've given some great input, and I've used that to give this a bit more thought. Thank you.
GENERAL (HIDING I/O BECAUSE IT IS BORING, TAKING TWO MAJOR PATHS):
I really like the idea of making sure that I/O isn't the thing that shuts everything down while it does its thing. BORING. I think, depending on situation, I might choose something cheap which tries to stay out of the way of any existing OS routine (like a small graphics window with page flipping (or character set flipping) to keep a fresh animation on-screen during a long read). Otherwise, my preferred route is going to be a custom I/O routine with a slow regular stream of I/O. More on that choice a bit later.
UNDERCLOCKING (SLOW AND STEADY WINS THE I/O READING RACE):
I've been pouring over Chapter 10 of the Altirra Hardware Reference manual. I see lots of discussion on going faster than the default 19.2 Kbaud, but not so much going slower. (Not as popular of a topic, right?) It looks like, universally, the sector reads are going to be buffered, so that much is fine. I'm going to have to read through this chapter a few more times. I know that AUDF3 and 4 are combined into a single 16 bit channel, with a standard divisor (plugged into AUDF3, I believe) of $28 for a 19040 baud with NTSC. I only saw it mention in passing, but it looks like that the frequency generation isn't just the Atari's internal clock but also the clock signal which is sent over the SIO bus? So on both sides, I'm going to be able to dial in the exact transfer rate that I want? (And hope their firmware doesn't barf at something outside the expected range. But I wonder if I can have some really stretched cycles here and there without penalty.) There are going to be exceptions.
This was your number one caution. The standard OS vectors may have custom routines hiding behind them. The underlying media might be completely different than what I expect (a flash cartridge instead of magnetic media) so if I attempt my own routines, they could fail horribly. So what I think I need to do is checksum the OS routines and whitelist the ones that I know that I can replace. After that, depending on what I find, either whitelist or blacklist the remaining hardware devices which may or may not cooperate with underclocking. So this goes back to the first paragraph. Where I can whitelist, I can plug in my custom slow and steady I/O routine and hide the boring I/O behind the scenes. Where I can't, I might have to try to use a CPU light intermission to wallpaper over the delay with eye candy.
THE MISSING 8-BIT COMMON LIBRARIES:
One way or another, I want the program to figure out what will or won't work when it first launches. (Not in the middle.) Even better if it determines a path, stores it on disk, and reuses it on the next launch if it can determine that nothing important has changed. (So that's a small part of my need for avoiding data being lost when an emulated virtual disks isn't written back when the emulator closes.)
Either the Atari 8-bit is missing a ton of community-created common libraries that I would have expected to be decades old, or I'm looking in the wrong place. Is there a capability sensing/enumeration library? I'm hoping that there is something already out there which will go through a system's configuration and sort out any of the unique configuration parameters that a programmer might want to interrogate, use, or avoid. So, we're not just talking about the CIO handler list, but things like dual pokeys, 65C02 processor, memory expansion type, storage devices, etc etc. I know a number of different places where I'd want to use that, but figuring out the OS / driver / device situation is just one specific example where I'd want to whitelist or blacklist software paths based on capabilities.
ALTIRRA DEBUGGING AND APPLICATION SOUNDS DURING DISK I/O:
I'm spending more time learning Altirra's debugger and I took a look at what was going on with the AUDFn, AUDCn, and AUDCTL registers during disk reads. (Since I can't directly read them from the POKEY, I'm doing a break on updates and sometimes I'm running a manual .pokey interrogation.) Channels 3&4 combined, okay, expected that. I won't touch them. My question was, can I carefully avoid the OS I/O routines and do my own sounds (related or unrelated) during disk I/O?
So it looks like if you zero out SOUNDR ($41), the standard OS routine disables noises during I/O by keeping the volume set to 0 on the audio channel. That's fine. Let's put that to the side now and look at the typical situation. I hope I'm not reading this next part wrong, but what I'm seeing is that the clicking sound that happens during disk I/O may not be bleed-through (crosstalk) on the cables, but from the OS routines regularly switching all of AUDC1 through AUDC4 between A8 and A0 (flopping back and forth between zero volume and half volume). On the surface, it seems like a good explanation for the popping noises on each command.
This is also going to be a problem for doing my own sound during disk I/O (if I'm trying to work along side the OS routines). I don't see that audio channels 1 and 2 are being used, and I can live with the most significant nibble of AUDC1/2 being set to $A, but it looks like it is also flipping the volume off-and-on for those two channels, too. I can get around it (by poking AUDC1/2 back or by replacing the routine) but I had hope it wasn't going to get in my way. Either that, or it is using AUDF1 and AUDF2 in some way that I'm not seeing and understanding.
So that's where I'm at right now. I have a few specific questions here and there, but aside from those, I was just wanting to put this out there and bounce the ideas off of my more experienced peers. Normally, this kind of thing might be a minor consideration, but I plan on pushing a lot of content through the machine. I'm hoping that users will appreciate large amounts of content when I/O isn't the regular foreground activity that brings everything to a grinding halt. If a program is a restaurant, then loading from disk is neither the sizzle nor the steak. It is the guy at the register who stops you in your tracks until they get paid.
Edited by jmccorm, Tue Feb 13, 2018 11:19 PM.