Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.


#219 Bit6 and 7 of PSG reg#7 stuck to 10xxxxxxb

SD Snatcher

Wanting to help Whizzy and avoid that some rare MSX gets damaged, I decided to debug BomberMan2 for the unsafe bits set on PSG as reported here,

I did set one watchpoint to discover were the game was setting the unsafe condition:

debug set_watchpoint write_io 0xA1 { [ expr [ debug read PSG\ regs 7 ] & 0xC0 ] != 0x80 }

Then I boot the game, openMSX shows the PSG warning on the stdout, but no break occurs. If I check the PSG' s R#7, it shows 0xBF, which is a safe value.

I tried changing the reg#7 manually to force the breakpoint to occur:

debug write PSG\ regs 7 0x3F

But reading it back again...

debug read PSG\ regs 7

...and it returns 191 (0xBF), which means that the register is being forced to 10xxxxxxb internally to the emulator, which don't makes sense, because the PSG is a generic chip and the emulator would never get damaged. This 10xxxxxxb overriding it turns impossible to use watchpoints to quicly locate such a dangerous problem...

Test environment: openMSX-0.8.1 on Mac OS-X v10.6.6
Emulated machine: Panasonic FS-A1WSX (expanded to 512KB RAM)

BTW, this unsafe PSG problem is another one of the things that made me think of the AcidTests for the MSX standard... (See #3209252)


  • I have an updated version of the file in question with some extra's. This version is currently in internal beta. It also fixes this particular bug.

  • and it does make sense in some occasions to see the bits forced correctly. It's the same thing that most MSX-Engines do with PSG built-in.

  • The command
    debug set_watchpoint write_io 0xA1 { [ expr [ debug read PSG\ regs 7 ] & 0xC0 ] != 0x80 }
    doesn't work for 2 reasons:

    a) Like you already found out yourself, in openMSX we force the upper 2 bits to '10'. This was done because many real MSX machines don't have a discrete PSG chip, but instead the PSG is integrated in some other chip. On such machines the upper 2 bits are often really forced to '10'. Initially we didn't implement this in openMSX, but then we got bug reports for MSX software that does work on a real machine but doesn't in openMSX: that software set wrong PSG port directions, but still reads the joystick/mouse port and expects stuff to work. On many MSX machine this does indeed work.

    b) The condition of the write_io watchpoint is checked right _before_ the actual write is performed. So even if we didn't force the upper 2 bits to '10', you will read the old register value (so you will only break on the next register write).

    But there is a solution: on write-watchpoints, openMSX sets the special Tcl variables 'wp_last_address' and 'wp_last_value'. These variables contain respectively the address and the value of the about-to-be-written value (for read-watchpoints only 'wp_last_address' is set, the address is useful in case a single watchpoint is set on a whole range of addresses).

    A correct solution (only lightly tested) is:
    set wp_last_value "dummy"
    set psg_latch 0
    debug set_watchpoint write_io 0xA0 true {set psg_latch $wp_last_value}
    debug set_watchpoint write_io 0xA1 {($psg_latch == 7) && (($wp_last_value & 0xC0) != 0x80)}
    and this solution also doesn't care about the forced two upper bits.

    The above solution is rather cubersome. I'm considering to implement a "invalid_psg_port_directions_callback" feature. Much like the existing "umr_callback" and the (recently added) vdpcmdinprogress_callback features (see manual for details). That would also allow to customize (e.g. remove) the current warning message you get when invalid directions are set. For example the current warning message could be implemented as the default callback. Users who find this message annoying can set an empty callback. Or if you want to investigate the problem in more detail, you can execute "debug break" in your callback.

    Because the current behaviour is as expected and because the required behaviour is already possible, i've changed this issue from a bug to a feature request (with slightly lower priority).

    • priority: 5 --> 4
  • SD Snatcher
    SD Snatcher

    The invalid_psg_port_directions_callback seems a nice feature!

    Is it possible to add a vdpwrite_with_interrupts_enabled callback too? :)

    Under normal condition, this VDP_with_ei callback would just issue a warning message, similar to the PSG warning. This would have the advantage make clear to users that any malfunctioning of the game isn't an openMSX fault, but a badly programmed game.

  • I guess we can just close this one after this got implemented:

    commit 78a84a8015a5871d61f96f8285d1802e2922e19d
    Author: Wouter Vermaelen
    Date: Tue Jul 10 19:07:21 2012 +0000

    Added invalid_psg_directions_callback
    Last edit: Manuel Bilderbeek 2014-02-08
    • status: open --> closed
    • assigned_to: Wouter Vermaelen
    • Group: --> Next_Release