david_ps wrote:Uto,
There's not empty space, all room is used. And code execution is always in one direction: from low addresses to upper addresses, lower alignment it's the only relevant 
Well, I don't pretend the code to run backwards of course, I'll try to explain in different way.I don't exactly know how it works internally as I can't see the code, but I belive you face two issues here:
1) The modules/overlays use routines in you main code, so if those routines change their position, any call made by the module code is affected.
2) The main code (everything that is not the overlays) has different size each version, so overlay area may start at a different address each version.
The first issue is easy to solve, if you have a limited number of avaliable functions, just make NMI.SYS have a vector list at the beginning of your code:
Start jr RealStart
Caller JP (HL)
Vectors DW waitKey
DW readKey
DW clrScr
DW ....
RealStart .... ;Main Loop goes here
...
...
waitKey LD A, ... ; Code of each function here
....
readKey SRL ... ; Code of the function here
....
....
....
Now module author , in case he needs to call readKey press can get the address from vector table:
LD HL, (Vectors + 2)
CALL Caller
The adventage is vector table is allways located at same address, so modules writer can easily get to the functions. The disadvantage is you have to use some room for the vectors tables and for the initial JR and the JP (HL).
Of course you can still make direct calls in your own overlays, as you will recompile them all, but any custom overlay, or any replacement of your modules (i.e. replacing hexview as you said) may use the vector table.
The second issue is the overlays are probably loaded at different address depending on NMI version, cause depending of main code size, the overlay zone starts at a different address.
Ok, lets suppose, as I don't have the real values, that the NMI.SYS code loads at address 1000 (decimal), and can take 2000 bytes, so last address you can use is address 2999. Let's imagine also the space reserved for loading modules/overlays takes 200 bytes, from 1800 to 1999. It is like that cause the main code takes up to 1799 in this version, but it may change in next version, cause you can change main code and then it may end at 1788 or 1920.
Ok, at this very moment, when you load the "delete" module, it is loaded at address 1800, and then you jump to 1800 to run it. When you load the "reset" module it´s loaded at 1800 too, then you jump to 1800.
My proposal is the main code does not load the modules at 1800, but at 2000 - <module size>, and then you jump to 2000 - <module size>. For instance if you load a module whose size is 100, instead of loading it at 1800 and jump to 1800, you load it at 1900 and jump to 1900. If the module size is 120, you load it a 1780 and jump to 1780.
The adventage of this approach is module writers, included custom module writers, know its code will be loaded at 2000 - <module size> no matter which version of the NMI handler is running. If you load them all at 1800 like you do now, then every new version. That way the know exactly at which address they would be loaded, and you don't have to recompile them every time a new version appears.
I hope I have explained it well this time.
PS: There are places in the 48K rom were a JP (HL) can be found, so maybe you can save that byte. Not sure though as not sure if that part of the ROM is paged when executing NMI.SYS.