Reading back my text I have found a typo here 'ISR handler at 030h': the ISR starts at 38h not at 30h
Thanks for the explanation.
I think I almost have it
The init space definition is actually what sparks the interslot call - and this is specific to cartridge boot, and only swaps the page that the init is directed to (not the location of the header), and only that one page.
For a complicated example, if you have a cart in slot 2 (and slot 1 is empty), and the first byte in the cart @ $8000 (but not 4000) is $AB, even if the init location is set to $4000 it will only swap active memory page 1 (40xx-7fxx) to cartridge slot 2 - leaving the page with the cartridge header itself not swapped in, which you have to do manually.
Realistically this means 32kb of active swappable code (4000-bfff while still preserving bios/sys) with an additional theoretical 96kb of storage in the VDP for GRAPHIC3 mode, depending on how you want to use it. Locations $c000 to approx $de3f (7.5kb) is still empty and usable with disk rom still loaded but should probably be used in a particular way, like space for loading in system and commonly used routines.
I think part of my confusion came from the fact that some systems depends on the user to send code to the cartridge itself to configure which memory pages are visible, while the msx2 uses a system variable to set which pages the processor sees.
Yes, you got it right.
I think part of my confusion came from the fact that some systems depends on the user to send code to the cartridge itself to configure which memory pages are visible, while the msx2 uses a system variable to set which pages the processor sees.
This method is also sometimes used and we call them MegaROM mappers, but that is another switching mechanism on top of the standard one.
Now for whatever reason the bin/dsk version of my program has stopped working. I was doing data copy to the top of the program space, which is usually where I keep my work variables, but this is not possible for ROMs, so I was experimenting back and forth.
I was loading the program at $8020 after using an autoexec.bas with only one line,
1bload"test.bin",r
This worked fine until I added a bit more code, I did some searching and it seems reconfiguration of BASIC memory is necessary. Now, however, nothing I do can seem to get the file to boot from disk (the ROM image works perfectly fine). The system seems to run the init code and then resets itself.
My new autoexec:
1clear &HC000 2bload"test.bin",r
My new .bin header:
org $c000 binheader: byte $fe ; .bin identifier word init ; start-addr word EOF word init ; execute-addr init: (my code, identical to .rom version) EOF:
Two questions:
1. Why would the autoexec work fine before but not now?
and
2. Where and how does one define work RAM with cartridges? I found this in the technical doc:
3) When more than three bytes are needed for the work area, allocates it
from RAM used by BASIC. To do this, put the contents of BOTTOM (FC48H)
to the area corresponding to SLTWRK (FD09H to ...), and increase the
value of BOTTOM by the needed work area, then allocate it for the
work area
but it makes no sense to me. Obviously more than 3 bytes are going to be needed for any program. Maybe this is a bad translation but the entire listing of 5.13 is too complicated for my needs. I THINK what it is trying to say is set $fc48 and $fc49 (BOTTOM) to, for example $00/$81 to point to $8100, moving it up 256 bytes. I assume slot 1 is always cartridge 1, so if your cart loads into $8000, the work RAM location would be SLTWRK+(8*4)+1 and +2 (slot 1 page 1), which you then set to $00/$80.
Of course, this again makes little sense - if you load your cart into $4000, wouldn't you have to then set BOTTOM to $4100? Is that even possible?
This is all so confusing
Edit: It's not the autoexec because just inserting the disc and running bload causes the same odd resetting behavior.
You have moved your ORG-statement to wrong side of header... In BIN-file it should be after the header and on ROM-file before the header.
What comes to reserving memory I just suggest that at this point you don't... If you don't do anything the BASIC-program is in beginning of memory and variables at end... Your program fits neatly in between. CLEAR-command usually makes the situation just more unclear and in case your program does not exit that memory reservation is even more useless.
If you put your ROM at 4000h-7FFFh, just assume ram in 8000h-FFFFh. You can use it all taking care to not overwrite in the FDXXh area useful hooks from the ISR in the BIOS a a few values about system status you could need later (e.g. image of VDP registers and slot configurations).
If you put your ROM at 4000h-BFFFh, just assume ram in C000h-FFFFh. The advice to not abuse too much of the system areas you could need later is the same.
So this is interesting-
The system was resetting on the .bin version because of a bit of test code that used an ldir loop to copy my initial attribute table into the space I was using as my sprite work RAM. LDIR is clearly an acceptable opcode for MSX2 (I've seen examples that use it) and as far as I can tell I'm using it correctly so I don't know why it would cause the system to reset.
ld hl, testSpriteAttributes ld de, SPRITE_OAM ld bc, 16 ; 16 bytes to copy ldir
This was done before setting graphics mode. The sprite work ram (SPRITE_OAM) is stored atm close to the top of program memory (approx $800A+). I assume it wasn't resetting the ROM version because the code was simply failing to write (as to be expected if its a ROM).
I know the data can be changed, though, because my movement code atm manipulates those variables in their current locations and that works fine:
ld a, [SPRITE_OAM] inc a ld [SPRITE_OAM], a
Thanks for the info on the RAM and header info, even though that wasn't the exact problem with my BIN it helped me figure it out.
Definitely something weird going on with RAM.
Without any additional setup or changing anything, I am starting the ROM at $4000, and telling openMSX its a 16kb cart.
According to what you say, about $8000-$ddff should be fair game as RAM. Unfortunately, when I set my RAM base at $c000, it just doesn't work. No sprites are displayed.
When I set it to $8000, only one of four sprites will load, and only at the correct Y position, not X. This tells me that probably only one byte (the one at 8000?) is getting copied in correctly. The rest appear to not want to load into ram. I am not using the ldir code above, but tried a manual loop:
Edit: That loop code is definitely broken somehow. I unrolled it and it loads the rest of the data. I must be missing something somewhere.
Edit 2:
Must be tired. Removed the offensive code
Edit 3:
This time it was a bizarre bug with sjasm. The code "?" variable doesn't work as intended. I think it was assembling the code with incorrect addresses, causing the glitches I was seeing on different versions of the compiled app. I think for now I've figured out most of my issues
I bet everyone is getting tired of seeing me ask stupid questions, but here's one more rational one.
I understand the impracticality of attempting to develop both a disk and cartridge version of an app in tandem, but here's where I stand:
Disk version:
- Loads into $8000 fine, cannot load into $4000 due to BASIC
- Limited to one 16kb of space for initial bload command
- Can't overwrite page 1 while using disk basic
Cart version:
- Forced contiguous memory due to cartridge mapper config, e.g. if loading into $4000, basic 32kb pg1/2 cart now resides at $4000-$bfff
- Doesn't require page 1 of system ROM due to being a cartridge and not disk reliant
So, let's say I am stubborn and want to use 32kb with a disk based game, and since I don't have MSX-DOS handy and I like doing things the hard way, I want to try this:
1. Boot using autoexec.bas and load file "A" into page 2 ($8000) and memory swap routine into page 3 ($c000)
Mem config at this point: 0/1: system ROM, 2/3: page 2/3 of RAM
2. Execute memory swap to point page 2 to page 1 of RAM
Memory = 0/1: system ROM, 2/3: page 1/3 of RAM
3. Use tokenized BLOAD call to load file "B" into page 2 (still at $8000)
4. Execute memory swap to point page 1 and 2 back to page 1 and 2 of RAM
Memory = 0: system ROM, 1/2/3: pages 1/2/3 of RAM (with both files "A" and "B" loaded)
Does this sound right? This way you would have the same 32kb game in memory, presuming all the orgs were done properly.
Edit: Couple close calls and a lot of self-deprication later I think I got it. If someone else can try this example code and let me know if I got it right I'd appreciate it.
File A:
output A.bin byte $fe word init word EOF word init org $8000 init: call RAMCopyAndSetup call $c100 (rest of code, snip) RAMCopyAndSetup: ld hl, code_to_copy ld de, $c100 ld b, end_copy-code_to_copy 1 ld a, [hl++] ld [de++], a dec b jr nz, 1b ret code_to_copy: di ToggleRAMPage 1, $8000 EXEBAS equ $4646 ld hl,blcommand ld a,[hl] call EXEBAS ToggleRAMPage 1, $4000 ToggleRAMPage 2, $8000 ei ret blcommand: defb $cf,$22,"B.bin",$22 defb 0 end_copy: MACRO ToggleRAMPage page, address16 ld a, ($F341+page) ld hl, address16 call ENASLT ; $24 ENDMACRO EOF:
and file B:
output B.bin byte $fe word init word EOF word init init: ; I omitted org statement ret ; to return to $c1xx routine (data or code to include... snip) EOF:
And this seems to work, but my brain is mush Any one can confirm?
definitely doesn't but can't seem to figure out why. Doesn't crash, but the values in $40xx are all 255 for some reason.
If you want .to load a piece of code in a place that normally isn't accessible in basic, like page 1, you could create a 16kB or whatever fits block which loads in page 2 and 3 with normal bload,r and at run time copies itself to the right place in ram. Then returns. You can repeat this for next blocks, if necessary. The last block starts the actual program in ram.