Anyway, you can check the value of H in you cartridge execution routine
Hmm, you say it executes first in page 4000-7FFF and then in 8000-BFFF? I will check this, and if so, that can be issue, hence compiled with ORG 4000h, so it can do absolute calls and jumps from window 8000h to window 4000h, where can be unexpected slot activated. Otherwise should not be an issue, hence I check SLTWRK record for nonzero if there is already allocated memory and exit initialization prematurely expelling allocation repetition. So I can check not only SLTWRK for window 4000h, but also 8000h and maybe 0000h and C000h.
Are you using emulators? If so, you need to indicate the correct size of your rom otherwise it will mirror execute twice.
Yes, I use emulator hence there's debugger available and my NMS 8250 has front panel broken and not printed yet. How can I limit the size — any xml for it? I use openMSX.
Thanks for the sources, I see you are doing interesting thing, I will examine for new ideas — my project is much more humble. But I am still not sure that problem is in dual initialization — I'd saw multiple records in SLTWRK while debugging. Problem is disk bios memory allocation function corrupts some machinery, even I do not write to allocated area.
UPD: pretty same I did, but I ignored subslot, so better I'll add this for a case. And I see your malloc routine pretty differs from what I used — it rather simplier, just moving HIMEM down and nothing more. Is it ok you at least do not move stack? I'll check if your routine is better for my case.
What compiler do you use? I am on GENS80, it limits me to use 6 character labels. I suggest you compile on PC.
Hmm, you say it executes first in page 4000-7FFF and then in 8000-BFFF? I will check this, and if so, that can be issue, hence compiled with ORG 4000h, so it can do absolute calls and jumps from window 8000h to window 4000h, where can be unexpected slot activated. Otherwise should not be an issue, hence I check SLTWRK record for nonzero if there is already allocated memory and exit initialization prematurely expelling allocation repetition. So I can check not only SLTWRK for window 4000h, but also 8000h and maybe 0000h and C000h.
A real interface on a real system NEVER, EVER should do that unless designed to do so. Mirroring is a side-effect of not having the proper connections to selection signals for your type/size of ROM. On emulators, that is a different animal, ROM files do not have a reader information indicating what kind of mapper that ROM file uses and in the regular ROM files, that do not need mapping, if there is mirroring or not. Some game cartridges count on mirroring to find out if it is a copy or just because it is useful to the game to have a copy mirrored on another page, so, by default I think that all, if not most MSX emulators will mirror 16KB rom files unless you explicitly tell it is a 16KB rom. You can make your life easier by just adding the H check on your ROM entry point, if you do so, it will only execute when @0x4000 (or 0x8000 if that is your thing).
Thanks for the sources, I see you are doing interesting thing, I will examine for new ideas — my project is much more humble. But I am still not sure that problem is in dual initialization — I'd saw multiple records in SLTWRK while debugging. Problem is disk bios memory allocation function corrupts some machinery, even I do not write to allocated area.
UPD: pretty same I did, but I ignored subslot, so better I'll add this for a case. And I see your malloc routine pretty differs from what I used — it rather simplier, just moving HIMEM down and nothing more. Is it ok you at least do not move stack? I'll check if your routine is better for my case.
What compiler do you use? I am on GENS80, it limits me to use 6 character labels. I suggest you compile on PC.
My project also started very humble, by looking at great examples out there and researching MRC and other sources, got to improve it to this point, so the general idea is that, start small, and grow on it, starting with huge projects might end up as a bad thing as you may quite because it would take quite a while to get something working. I always like to break into small tasks and get things working slowly, one by one, this way I feel motivated every time a small piece is working.
Not sure about open msx as I use BlueMSX as it was quite easier to integrate a few extra hardware emulation to it than it would be to add to OpenMSX, but I'm pretty sure someone already asked this question around here, if you don't find through search, try asking Manoel, he is a great guy that has great knowledge on OpenMSX.
About moving HIMEM, it works fine, on my experience, as long as you do it after all adapters are initialized. It survived going to basic, executing something, and going back to DOS... Since what I did has no use if you don't have DOS, don't need to care if no disk rom is available. Notice that in my case I didn't want to use H_STKE to do the memory allocation as I've found out that ESE SCSI doesn't like when someone hook to H_STKE before it, but pretty sure it should work fine on H_STKE otherwise.
The DOS2 memory initialization routine is fine as well, but you need to adapt it to work for you, as there are some memory initializations and shuffling around that you shouldn't do, unfortunately can't help much on that as I really don't remember what need to change on that routine for something that is not a disk adapter, but by debugging and understanding the calls and addresses and pointers it is moving, you should be able to figure it out after some thinkering.
I use two Assemblers, one is SDASZ80 which I really recommend you never try unless you want to create libraries for SDCC... It is non-standard, crazy and I really don't like it, but it is what you need to use to make sdcc libraries so I've used it for the MSX2ANSI library. For all other projects I like to use sjasm 0.42c , but there are lots of great assemblers, I've also used glass and like it a lot. And yes, nowadays everything MSX related I do is cross compiled, so I edit the files and compile on a PC and for quite a few projects also debug on o the PC using BlueMSX or OpenMSX as well.
About moving HIMEM, it works fine, on my experience, as long as you do it after all adapters are initialized
How can I postpone my initialization to be executed after DISK ROM? I suggest that will match the condition all adapters are initialized?
Hook H.STKE in the ROM INIT routine. When the hook is called, all adapters are initialised.
Copy the old hook to the SLTWRK area, each slot has 8 bytes available so it will fit.
Thanks, I was afraid that SLTWRK must only contain a pointer to reserved memory or flags regarding the documentation. So if not, that will be enough for sure. So you say on H.STKE I can safely move HIMEM down and use the memory between old and new HIMEM as real slot work area?
Thanks, I was afraid that SLTWRK must only contain a pointer to reserved memory or flags regarding the documentation. So if not, that will be enough for sure.
As far as I know the space is opaque and the structure of the data stored is entirely up to the ROM. The BIOS just provides 2 bytes per page per subslot (so 2 × 4 × 4 × 4 = 128 bytes in total) so that cartridges have a small amount of storage space available without having to lower HIMEM.
So you say on H.STKE I can safely move HIMEM down and use the memory between old and new HIMEM as real slot work area?
Ducasp can say more about than I can, I’ve never had the need to move HIMEM down so I’ve never looked into the intricacies of that in detail. But from what I understand so far, that is the case.
Hook H.STKE
Just tried with the hook. This does not work. Even if the only thing I do in my H.STKE is restoring old hook and JP to it, the system continuously reboots. After I remove installing my hook, the system boots well. Surprizingly, there were no hook to backup, 5×0xC9 were backed up, but nevertheless. Are you sure right hook it is?
About moving HIMEM, it works fine, on my experience, as long as you do it after all adapters are initialized. It survived going to basic, executing something, and going back to DOS... Since what I did has no use if you don't have DOS, don't need to care if no disk rom is available. Notice that in my case I didn't want to use H_STKE to do the memory allocation as I've found out that ESE SCSI doesn't like when someone hook to H_STKE before it, but pretty sure it should work fine on H_STKE otherwise.
I think I am doing something wrong and it is time to share some code.
init in a, (0A8h) rrca rrca and 003h ;Bits for 4000h-7FFFh window chosen slot. di ;Code skipped there to set some RST30-based hooks ei push af call getwrk ;HL is our address in SLTWRK dec hl dec hl ld (hl), 1 ;Set flag that old H_STKE stored here inc hl ex de, hl ; Check if RST 30/DB slotid/DW init2/RET are already there (these comparisons are obviously not optimized, but let make it work first) ld hl, H_STKE+4 ld a, 0C9h xor (hl) ld c, a dec hl ld a, init2 / 256 xor (hl) or c ld c, a dec hl ld a, init2 & 255 xor (hl) or c ld c, a dec hl pop af ld b, a xor (hl) or c ld c, a dec hl ld a, 0F7h ;RST 30 xor (hl) or c ret z ;Stop initialization hence H_STKE is already replaced (this is because init is called twice) push bc ld bc, 5 ;Backing up H_STKE ldir dec hl ;Our hook for H_STKE to point to init2, not optimized too, maybe LDIR later. ld (hl), 0C9h dec hl ld (hl), init2 / 256 dec hl ld (hl), init2 & 255 dec hl pop af ld (hl), a dec hl ld (hl), 0F7h ;RST 30 ret
And init2 is as simple as
init2 call getwrk dec hl ld de, H_STKE ; Restore old H_STKE ld bc, 5 ldir ret
I checked it in the debugger, and while H.STKE is 5×RET, it was called multiple times, that made me think it might be wrong hook, but the description in the hooks docs pretty matches your advice, so, more likely I have a bug in my code, and it is probably ok to be called multiple times. It is also called once for my routine, which restored well to 5×RET, and system reboots after that.
init in a, (0A8h) rrca rrca and 003h ;Bits for 4000h-7FFFh window chosen slot. di ;Code skipped there to set some RST30-based hooks ei push af call getwrk ;HL is our address in SLTWRK dec hl dec hl ld (hl), 1 ;Set flag that old H_STKE stored here inc hl ex de, hl ; Check if RST 30/DB slotid/DW init2/RET are already there (these comparisons are obviously not optimized, but let make it work first) ld hl, H_STKE+4 ld a, 0C9h xor (hl) ld c, a dec hl ld a, init2 / 256 xor (hl) or c ld c, a dec hl ld a, init2 & 255 xor (hl) or c ld c, a dec hl pop af ld b, a xor (hl) or c ld c, a dec hl ld a, 0F7h ;RST 30 xor (hl) or c ret z ;Stop initialization hence H_STKE is already replaced (this is because init is called twice) push bc ld bc, 5 ;Backing up H_STKE ldir dec hl ;Our hook for H_STKE to point to init2, not optimized too, maybe LDIR later. ld (hl), 0C9h dec hl ld (hl), init2 / 256 dec hl ld (hl), init2 & 255 dec hl pop af ld (hl), a dec hl ld (hl), 0F7h ;RST 30 ret
And init2 is as simple as
init2 call getwrk dec hl ld de, H_STKE ; Restore old H_STKE ld bc, 5 ldir ret
There are some fundamental errors in this code:
1) secundairy slots are ignored, which is a bad idea
2) SLTWRK is only 2 bytes (per page), or if you take the whole address space (all pages) 2*4 = 8 bytes, but primairy and secundairy slot must be taken into account, or you end up using the wrong SLTWRK entries.
You have not included the getwrk code, so i am not sure what the inputs are. But I assume A takes the slotid (in your case the primairy slot, which could be wrong if the slot is expanded). But init2 does not contain any code for the slotid in A.
Thanks, I will add subslot code later, just now it does not make much sense, but I have it in mind to do when this works.
Getwrk code also does not use slot expansion, but otherwise it is working.
getwrk ; Gets allocated mem address, result=DE, address=HL, A nonzero if H_STKE stored instead of allocated mem address. in a, (0A8h) rlca rlca rlca and 060h ;Bits for 4000h-7FFFh window chosen slot * 32. ld e, a ld d, 0 ld hl, SLTWRK add hl, de ld a, (hl) inc hl inc hl ld e, (hl) inc hl ld d, (hl) dec hl ret
Definitely, init2 (and others) does not have any code but the H.STKE restoring, I meaningly removed any code except H.STKE backup/restore when troubleshooting, and when I disable H.STKE overriding (ret z→ret in init routine), this no more reboots, but of course incapable to do some things I want it to do.
UPD. Made a function (untested) instead of this {A←(A8), 2×rrca &=3} and also getwrk reworked:
gsltid ; Gets SlotId, A=slotId, EHL=corrupted in a, (0A8h) rrca rrca and 3 ;Bits for 4000h-7FFFh window chosen slot. ld hl, EXPTBL ld e, a add a, l ld l, a bit 7, (HL) ld a, e ret z ld a, (0FFFFh) cpl and 00Ch or e or 128 ret getwrk ; Gets allocated mem address, result=DE, address=HL, A nonzero if H_STKE stored instead of allocated mem address. in a, (0A8h) rrca rrca and 03h ;Bits for 4000h-7FFFh window chosen slot. ld hl, EXPTBL ld e, a add a, l ld l, a ld a, e rrca rrca rrca bit 7, (hl) jr z, gwrksk ld a, (0FFFFh) rrca cpl ; Subslot read inverted and 006h or e gwrksk ld e, a ld d, 0 ld hl, SLTWRK add hl, de ld a, (hl) inc hl inc hl ld e, (hl) inc hl ld d, (hl) dec hl ret
Just a thinking out loud... These TPA memory reservation issues for DOS, BASIC & ROM would need own Wiki-page I think.