And, here's my code to Find OPLL (FOPLL)
EXPTBL: EQU $FCC1 ENASLT: EQU $24 ORG $C000 ; Find OPLL ; First look for an internal, then external ROM ; If (only) external OPLL found, it gets initialized. ; Cy, OPLL is found and A=SlotID FOPLL: LD HL,OPLL.I ; internal CALL FOPL.4 RET C LD HL,OPLL.E ; external CALL FOPL.4 RET NC PUSH AF LD A,($7FF6) ; ini ext device OR 1 LD ($7FF6),A POP AF RET OPLL.I: DW $4018 ; Search address DB 8 ; String length DB "APRLOPLL" ; Search string OPLL.E: DW $4018+4 DB 4 DB "OPLL" ; Search slots ; In: HL, pointer to search attributes ; out:Cy, found + A=slotID FOPL.4: LD (FOPLL#),HL LD HL,EXPTBL LD B,4 ; 4xPrimSlot LD C,$00 ; slot 0-0 FOPL.0: PUSH BC CALL FOPL.1 POP BC RET C ; Cy, found INC HL INC C ; prim slot +1 DJNZ FOPL.0 AND A ; Cy=0, not found RET FOPLL#: DW 0 ; Search 1 prim slot ; in: HL,EXTTBL ; C,prim slot ; out:Cy, found + A=slotID FOPL.1: LD A,(HL) ; Is this base slot extended? AND $80 LD B,1 JR Z,FOPL.2 ; no, so only search 1 slot LD B,4 ; else, search 4 sec slots FOPL.2: PUSH BC PUSH HL LD A,(HL) ; Get ext bit AND $80 ; Cy=0 OR C LD H,$40 CALL ENASLT CALL FOPL.3 POP HL POP BC LD A,C RET C ; Cy,found ADD A,$04 ; Sec slot +1 LD C,A DJNZ FOPL.2 AND A ; Cy=0, not found RET ; Search FOPL.3: LD HL,(FOPLL#) LD E,(HL) INC HL LD D,(HL) INC HL LD B,(HL) INC HL EX DE,HL CALL CPSTRN RET ; Compare strings ; In : B , Compare length ; DE, string 1 ; HL, string 2 ; Out: Cy, on string1=string2 CPSTRN: PUSH BC PUSH DE PUSH HL LD C,B LD B,0 AND A STRC.0: LD A,(DE) INC DE CPI JR NZ,STRC.1 ; Not equal JP PE,STRC.0 SCF STRC.1: POP HL POP DE POP BC RET
I've written it to be readable, not to be fast. This code assumes BIOS active for ENASLT, or at least have a slot switching function at address #24. This treat is about doing the same without BIOS enabled. In that case, it is easy to just replace the ENASLT call to a custom routine that switches prim (I/O A8) and sec (Adr #FFFF) slots on the fly. No problem. And, yes, I could have use RDSLT too, to keep the system layout as it is after calling the code.
But, remember, I've written it to be clean and readable. I too am not using BIOS on my stuff, but for slot switching I make an exception. And usually, switching is done once..during booting of the app.
Hai,
As I was refactoring some old code we used to detect OPLL devices, I realized I had to flip some bits to distinct internal and external devices. As mentioned in this treat, and other sources, when an internal OPLL is present it is activated by default. When that same machine has an external OPLL attached (an FMPAC for example), it needs to get un-initialized. Fine. So I rewrote the code to search for internal using "APRLOPLL" as search string. If that isn't found, search for "OPLL" instead, assuming it is an external device.
While testing, I went ahead and wanted to test all devices out there and mix them up. All using openMSX. Easy.
Well, perhaps not.
As it turns out, APRLOPLL isn't an exclusive internal-only string. Nope. Here's what I found, so far.
int FS-A1ST: "APRLOPLL"
ext Pana FM-PAC: "PAC2OPLL"
ext Checkmark FM-PAK: "APRLOPLL"
ext Zem MusicBox: "APRLOPLL"
Oh, wait. External devices with "APRLOPLL" as ID string... well, there goes the theory of recognizing int/ext devices.
oh, and I could not find any ROMs of
- MK FMPAK
- Technosoft FM Sound Stereo
now what?!
The term internal / external is not really accurate, since most western MSX-MUSIC cartridges are actually built like an internal MSX-MUSIC, probably to simplify the design and save cost. The terms internal / external only refer to the original Japanese situation with FM-PAC and then later the MSX-MUSIC being integrated internally in the machines.
So you can consider the ID string more like it tells you whether it is capable of memory mapped I/O:
- If it has the string APRLOPLL it is always enabled on the I/O ports.
- If it has another OPLL string (as-in PAC2OPLL) you can use the memory-mapped I/O, or use a memory-mapped register to enable the I/O ports.
So your detection as you described it is still correct. Though note on FM-PAC the I/O ports are disabled by default so you don’t need to un-initialize it when internal MSX-MUSIC (APRL) is present, rather, you need to initialise it when internal MSX-MUSIC is not present.
Yes if you plug in a western MSX-MUSIC like the Checkmark FM-PAK into a machine with MSX-MUSIC built in it will always play on both of them at the same time. There is no way around that, it’s a limitation of their design because they did not fully clone all the FM-PAC functions that were designed to prevent this.
p.s. Because FM-PAC uses memory-mapped I/O, you can use multiple at the same time.
Hai Grauw, thanx. So you say that a device that carries "ADRLOPLL" as identifier, is always enabled by default? If that's correct, then indeed the result of my (and your) code is correct.
Indeed!
Let's continue here because it seems like a far bigger problem than I thought.
In VGMPlay MSX I mask out various writes to control registers:
- FLAG CONTROL (04H) writes are completely ignored
- MISC CONTROL (08H) writes ignore bits 0-1 and 3-5
- IO CONTROL (18H) writes are completely ignored
I bet the IO Control register write is the culprit. I believe the Philips NMS-1205 has a sound output enable on one of the GPIOs, where on the Panasonic FS-CA1 it has a different function. OpenMSX matches the real hardware in this regard. BlueMSX is no longer maintained for more than 10 years.
You mean we have to activate MSX-Audio I/O access manually like what is needed for FM-PAC?
But if I/O are disactivated by default, how can I activated it... through I/O!?
BTW, I can't get from your assembler code the value you write at 18h.
MSX-Audio programming article on the wiki said we have to detect MSX-Audio slot from address 0080h and change I/O setting at 3FFEh. I've never seen this info anywhere else on the internet and it doesn't seem to work. According to OpenMSX, Philipps' Music-Module is on page 1 and 2, but I've read that some MSX-Audio cards have no ROM at all.
I'm lost... :-/
I made some more test with OpenMSX.
My sample code (that through data to I/O ports C0h & C1h) don't produce any sound using audio
or Philips_NMS_1205
extensions, but works fine with Panasonic_FS-CA1
and Toshiba_HX-MU900
!
It is more and more strange.
Not that strange if you take into account the MSX-Audio BIOS. The audio
and Philips_NMS_1205
extensions have no BIOS, so there's probably something you need to initialize manually.
In VGMPlay MSX I mask out various writes to control registers:
- FLAG CONTROL (04H) writes are completely ignored
- MISC CONTROL (08H) writes ignore bits 0-1 and 3-5
- IO CONTROL (18H) writes are completely ignored
- IO DATA (19H) writes are completely ignored
I bet the IO Control and IO Data register writes are the culprit. I believe the Philips NMS-1205 has a sound output enable on one of the GPIOs, where on the Panasonic FS-CA1 it has a different function. OpenMSX matches the real hardware in this regard. BlueMSX is no longer maintained for more than 10 years.
Correction in bold above. Writes to 19H are also ignored.
You mean we have to activate MSX-Audio I/O access manually like what is needed for FM-PAC?
But if I/O are disactivated by default, how can I activated it... through I/O!?
No, it is not like FM-PAC at all. MSX-AUDIO I/O is enabled by default. And that function only applies to the Panasonic FS-CA1. But never mind it.
The issue you ran in to is something completely different. There are four GPIO pins on the Y8950, on the Philips NMS-1205 one of them mutes the sound, and you’re setting it via registers 18H and 19H. It defaults to enabled so you should not change it. Just don’t touch the register.
BTW, I can't get from your assembler code the value you write at 18h.
I don’t write anything to 18H or 19H, I prevent writes to it.
MSX-Audio programming article on the wiki said we have to detect MSX-Audio slot from address 0080h and change I/O setting at 3FFEh. I've never seen this info anywhere else on the internet and it doesn't seem to work. According to OpenMSX, Philipps' Music-Module is on page 1 and 2, but I've read that some MSX-Audio cards have no ROM at all.
That information is specific to the Panasonic FS-CA1. Neither Philips NMS-1205 nor the Toshiba HX-MU900 implements the MSX-AUDIO standard with the appropriate MSX-AUDIO BIOS ROM or that I/O port selection register at 3FFEH (they do have a firmware ROM). So unless you want to make software exclusive for the Panasonic FS-CA1, you can ignore that information.
Confusingly, the Yamaha Y8950 is also called MSX-AUDIO and the name is therefore commonly used to refer to all three modules. But that is separate from the MSX-AUDIO BIOS which completes the standard, and only the Panasonic FS-CA1 has it.
I made some more test with OpenMSX.
My sample code (that through data to I/O ports C0h & C1h) don't produce any sound using audio
or Philips_NMS_1205
extensions, but works fine with Panasonic_FS-CA1
and Toshiba_HX-MU900
!
It is more and more strange.
It works on Toshiba HX-MU900 and Panasonic FS-CA1 because they have functions on the GPIO pins.
I'm lost... :-/
I think you didn’t read my post in the way I intended, which caused a mental tangent that multiplied confusion and misdirection by a 100 fold .
As I said, block writes to registers 04H, 18H and 19H, and mask out bits 0-1 and 3-5 of register 08H. That’s all there is to it.
else if(*g_VGM_Pointer == 0x5C) // Y8950, write value dd to register aa { u8 reg = g_VGM_Pointer[1]; u8 value = g_VGM_Pointer[2]; if (reg != 0x04 && reg != 0x18 && reg != 0x19) { if (reg == 0x08) value = value & 0xC4; // 0b11000100 MSXAudio_SetRegister(reg, value); } g_VGM_Pointer += 2; }
You don’t want to let VGMs just write to any register without restrictions. What if it enables some interrupt that isn’t handled, it would lock up the machine.
In this particular case the issue was caused by register 18H & 19H.
Look into the Yamaha Y8950 manual for the function of registers 18H & 19H. You will see they control four GPIO pins on the Y8950. In the Philips, Toshiba and Panasonic sound modules these GPIO pins are all hooked up to different functions. Therefore, you must not write a GPIO value recorded on a Panasonic to a Philips (or vice versa), or undesirable stuff like muting the sound will happen.
Specifically, the function of GPIO3 is as follows:
- Philips NMS-1205: 0 = mute Y8950 sound output
- Panasonic FS-CA1: 1 = mute Y8950 sound output
- Toshiba HX-MU900: no function
The conflict is evident.
Out of extreme completeness, the other GPIO functions I know of are; on the Philips NMS-1205 GPIO0 controls whether the DAC is enabled (0 = muted), and on the Toshiba HX-MU900 GPIO0 and GPIO1 allow reading the “multi-sensor” keys of Toshiba’s HX-MU901 external keyboard. But generally, you should just leave these GPIO signals alone since detecting which of these modules is present would be difficult.
Anyway let’s move back to the other thread, because this has nothing to do with detection.
I thought you were talking about the registers setup.
I didn't understood (or even imagine) that the VGM file data could be problematic.
It's clear now, thank you.
And indeed, it has nothing to do with detection... although the wiki should be updated because imho it confuses more than it helps on the subject.