Calling page 1 RAM address $4110 in FM music player

Par cjs

Master (143)

Portrait de cjs

27-04-2023, 06:31

I've been disassembling and reverse-engineering the music code for a game called Slime World. (src/psgv.asm is the PSG player, and src/fmvs.asm is the FM player.) Early in the code, just after setting up the H.TIMI hook, it's got code running in page 1 RAM that loads A and E registers and then calls $4110, which is before the start address of $4E00 that the player code uses, and so hasn't been set up by routines that load the player and copy it (and it's data) down to page 1 RAM, as far as I can tell.

There are six calls at the start that happen with A:E values $16:$20, $17:$50, $26:$05, $27:$05 and $28:$01. (There are more calls that do similar things later in the code.)

This looks to me as if it's some sort of routine that sends data to FM chip registers or something like that (register number in A, and value in E?). But it's a bit mysterious to me why it would be calling into page 1 RAM. Does something in system FM initialisation routines perhaps place some code there?

If anybody has any ideas on what's happening here, and maybe pointers to documentation on this, I'd appreciate it.

!login ou Inscrivez-vous pour poster

Par cjs

Master (143)

Portrait de cjs

27-04-2023, 06:37

(This is a reply since at the time I couldn't figure out how to edit my initial post.)

Ah, I just noticed that the MSX-MUSIC FM-BIOS specifies that $4110 is the WRTOPL routine. But I'm still confused by this becuase I don't see anything switching the page to the FM-BIOS ROM, and since the code is running in page 1 RAM anyway, switching away from the RAM page would cause things to blow up. Does the FM-BIOS copy some of its code into page 1 RAM?

Par jepmsx

Champion (281)

Portrait de jepmsx

27-04-2023, 09:11

When I have programmed OPLL I've used the out command to addresses #0x7C, #0x7D. In the first address there is the number of the register of OPLL and the second is the value to that register.

In this document you can find the reference manual to know what the registers do.

Par cjs

Master (143)

Portrait de cjs

27-04-2023, 11:51

Thanks for the link, but I'm not trying to program the chip myself: I'm trying to disassemble existing code that uses what I now see appears to be the FM-BIOS interface.

And what I don't understand is how it appears to be calling into the RAM page that the disk BASIC startup mapped for page 1 (the slot descriptor in $F342 RAMAD1) rather than switching in the FM-PAC ROM and calling that. Does the FM-BIOS, during its setup, copy certain parts of itself to that RAM page, if present?

Par sd_snatcher

Prophet (3675)

Portrait de sd_snatcher

27-04-2023, 21:47

Tip: The MSX-Music FM-BIOS chapter of the MSX Turbo-R Datapack is available here.

Par cjs

Master (143)

Portrait de cjs

28-04-2023, 05:10

That is a brilliant reference book; I don't know how I've gone this long without discovering it. So definitely thanks for that. And the chapter you linked has given me several pieces of important information about the FM-BIOS.

That said, on examining 3.3.5 FM BIOS使用上の注意 ("Calling the the FM-BIOS"), it says "ワークエリアはいかなる場合においても、ページ1に指定することはできません", or, roughly, "the work area may never be in page 1." The additional discussion seems to make it reasonably clear that this reference is assuming that you'll be mapping the FM-BIOS ROM into page 1 (which is why the work area can never be in that page) and that's definitely not happening in Slime World before it does a call WRTOPL.

So it seems fairly clear that the FM-BIOS itself isn't setting itself up to support these calls, and I'm familiar enough with the BASIC code for Slime World to know that it didn't do anything special in this regard. But it now occurs to me that I've not yet reverse-engineered some initial code (src/fmslotck.asm) that does detection of whether FM sound is present; perhaps that also does whatever setup that allows the page 1 RAM calls I'm seeing. I'll have a look at that.

Thanks again for the link!

Par DarkSchneider

Paragon (1030)

Portrait de DarkSchneider

28-04-2023, 14:46

I recommend you to make some room in stack at program enter, copy there that part of the code (the method for music play), it must be self-contained code (so change the JP by JR, use fixed addresses if required variables or patch code after moving to reference new positions, and etc), and call it from interrupt in its stack position.
On the new code you can simply ENASLT the FM-BIOS for page 1, do the stuff, then restore the previous one.
Doing all those inter-slot calls is not feasible for real time performance.

Also valid if you place the code at address 0x8000 or greater, but probably that memory positions would be overwritten by others.

Par cjs

Master (143)

Portrait de cjs

28-04-2023, 15:02

DarkSchneider wrote:

I recommend you to....

Well, if you have a time machine, do feel free to go back to 1992 and recommend that to the original developer. Right now I'm reverse-engineering this code, not writing my own game.

That said, I have to move some stuff around in the memory map anyway to free up some memory for a translation, so I'll keep your hints in mind if I decide to make more extensive changes.

Quote:

Doing all those inter-slot calls is not feasible for real time performance.

Are they particularly slow? I'd estimate that the H.TIMI routine is doing about half a dozen calls to FM-BIOS on those ticks where it does something (I'm not sure if it updates things on every tick, but I suspect not). Neither the music nor the game (written in BASIC) seem to have any performance issues.

Par cjs

Master (143)

Portrait de cjs

28-04-2023, 18:48

Right, so I reverse-engineered a good part of src/fmslotck.asm, which is run at the start of the game to check for the presence of FM sound support, and it turns out that it copies the entire FM-BIOS from the ROM slot to the RAM slot for page 1. That explains why the player code wasn't changing pages or doing a cross-slot call when calling FM-BIOS routines.

I'm curious; is this a generally accepted technique?