|
Joined: Feb 2014
Posts: 1,102 Likes: 173
Very Senior Member
|
Very Senior Member
Joined: Feb 2014
Posts: 1,102 Likes: 173 |
More silly fun: You midi guys would know all of this stuff, but I just discovered the virtual midi piano keyboard (vmpk) and it's pretty cool if you don't have a real midi keyboard handy. ./mame64 apple2p -sl2 midi -verbose -flop1 ../../Passport\ designs\ -\ Master\ tracks\ v1.8.dsk -snapsize 560x384 -debug -midiout "VMPK Input" -midiin "VMPK Output" -log I also installed fluidsynth for linux so I can get some midi sounds too. Now I get a bunch more items when I listmidi: ./mame64 apple2e -listmidi
MIDI input ports:
Midi Through Port-0 (default)
Portable Grand MIDI 1
VMPK Output
MIDI output ports:
Midi Through Port-0 (default)
Portable Grand MIDI 1
Synth input port (20027:0)
VMPK Input
qjackctl
./mame64 apple2p -sl2 midi -verbose -flop1 ../../Passport\ designs\ -\ Master\ tracks\ v1.8.dsk -snapsize 560x384 -debug -midiin "Virtual Keyboard" -log -midiout "Synth input port (20027:0)" On ubuntu, just "sudo apt install vmpk fluidsynth" and get a soundfont2 from the net (I got the General User one)
|
|
|
|
Joined: May 2006
Posts: 148 Likes: 4
Senior Member
|
Senior Member
Joined: May 2006
Posts: 148 Likes: 4 |
This is a glaring omission that has now been corrected. I'll PR this addition tonight.
|
|
|
|
Joined: Feb 2014
Posts: 1,102 Likes: 173
Very Senior Member
|
Very Senior Member
Joined: Feb 2014
Posts: 1,102 Likes: 173 |
Hi Arbee, I was looking at how mame hooks up to the midi with portmidi src/osd/modules/midi/portmidi.cpp and it seems that it doesn't pass the 1 byte messages through like F8 (timing clock).
int osd_midi_device_pm::read(uint8_t *pOut)
...
case 0xf: // system common
switch (status & 0xf)
{
case 0: // System Exclusive
{
*pOut++ = status; // this should be OK: the shortest legal sysex is F0 tt dd F7, I believe
*pOut++ = (rx_evBuf[msg].message>>8) & 0xff;
*pOut++ = (rx_evBuf[msg].message>>16) & 0xff;
uint8_t last = *pOut++ = (rx_evBuf[msg].message>>24) & 0xff;
bytesOut += 4;
rx_sysex = (last != MIDI_EOX);
break;
}
case 7: // End of System Exclusive
*pOut++ = status;
bytesOut += 1;
rx_sysex = false;
break;
case 2: // song pos
case 3: // song select
*pOut++ = status;
*pOut++ = Pm_MessageData1(rx_evBuf[msg].message);
*pOut++ = Pm_MessageData2(rx_evBuf[msg].message);
bytesOut += 3;
break;
default: // all other defined Fx messages are 1 byte
*pOut++ = status; // shouldn't we pass the 1 byte messages along?
bytesOut += 1;
break;
}
Also if I read it correctly, 0xF3 (song select) should only supply 2 bytes (status + 1 data byte). http://www.personal.kent.edu/~sbirch/Music_Production/MP-II/MIDI/midi_protocol.htm http://www.personal.kent.edu/~sbirch/Music_Production/MP-II/MIDI/midi_system_common_messages.htm http://www.personal.kent.edu/~sbirch/Music_Production/MP-II/MIDI/midi_system_real.htm
|
|
|
|
Joined: Mar 2001
Posts: 17,217 Likes: 234
Very Senior Member
|
Very Senior Member
Joined: Mar 2001
Posts: 17,217 Likes: 234 |
Thanks! You missed a detail or two but it's fixed in GitHub top-of-tree now
|
|
|
|
Joined: Feb 2014
Posts: 1,102 Likes: 173
Very Senior Member
|
Very Senior Member
Joined: Feb 2014
Posts: 1,102 Likes: 173 |
Thanks! You missed a detail or two but it's fixed in GitHub top-of-tree now Thanks, RB! I always miss those details 8-)
|
|
|
|
Joined: Feb 2014
Posts: 1,102 Likes: 173
Very Senior Member
|
Very Senior Member
Joined: Feb 2014
Posts: 1,102 Likes: 173 |
I think I've finally figured out why MasterTracks 1.8 was freezing after typing some midi keys, it's actually very subtle. After setting up a new ubuntu system on a new laptop, I thought I'd download a fresh mame for experiments/mangling. I totally forgot all about the typo in a2midi.cpp after a month or two of being busy with other stuff. (Yeah, I suppose I should read my own posts 8-) (I mistakenly thought that this typo didn't make a difference) https://github.com/mamedev/mame/blob/master/src/devices/bus/a2bus/a2midi.cpp
WRITE_LINE_MEMBER( a2bus_midi_device::acia_irq_w )
{
m_acia_irq = state ? true : false;
if (m_acia_irq || m_ptm_irq)
{
raise_slot_irq();
}
else
{
lower_slot_irq();
}
}
WRITE_LINE_MEMBER( a2bus_midi_device::ptm_irq_w )
{
m_acia_irq = state ? true : false; // should be m_ptm_irq
if (m_acia_irq || m_ptm_irq)
{
raise_slot_irq();
}
else
{
lower_slot_irq();
}
}
So how does the bug manifest itself? You've got the 6840ptm and the 6850 acia both modifying the variable m_acia_irq. The 6502 interrupt routine at $2572 (vector stored at $3FE/3FF) will first check the midi to see if there's data, if not the routine will check the timer and reset it by reading c0a1 and c0a4 which will clear the timer interrupt. The problem comes in when you have midi data that comes in generating an IRQ while there's a timer IRQ as well. The 6840 routine update_interrupts() will only modify its IRQ variable on transitions from 0 to 1 or 1 to 0, so once it calls a2bus_midi_device::ptm_irq_w (true) and setting m_acia_irq to true it won't call it again. But our interrupt routine processes the midi byte first, clearing the midi interrupt by reading $c0a9 and it calls a2bus_midi_device::acia_irq_w(false) which will set m_acia_irq to false. This ends up dropping all interrupts for the timer so it will never update the clock. It will keep processing the midi acia interrupts, but no timer processing will happen after this occurs. I ended up disassembling a bunch of master tracks to figure out how it worked. I think I understand quite a bit more about the 6840 and the 6850 now. (the 6840 data sheet is really difficult to figure out)
|
|
|
|
Joined: Feb 2014
Posts: 1,102 Likes: 173
Very Senior Member
|
Very Senior Member
Joined: Feb 2014
Posts: 1,102 Likes: 173 |
Some more dumb fun seeing if I can read midi data from the 6850 ACIA with lua. (with a midi card in slot 2 -sl2 midi) If I keep polling 0xc0a8 every 1/31250*10 seconds (1 second divided by the midi clock times 10 bits) I should be able to see all of the data bytes since one byte will arrive at this interval. It's useful to me to see just exactly how the device behaves. We'll just read 18 bytes and then exit the coroutine.
mem=manager:machine().devices[":maincpu"].spaces["program"]
mem:write_u8(0xc0a8,19) -- acia master reset CR0=1, CR1=1
mem:write_u8(0xc0a8,17) -- set divider to 16 CR0=1, CR1=0
co1 = function() for i=1,18 do
status=mem:read_u8(0xc0a8)
while (status&1)==0 do
emu.wait(1/31250*10)
status=mem:read_u8(0xc0a8)
end
data=mem:read_u8(0xc0a9)
if (status&0x20)~=0 then print ("OVERRUN ") end
print(string.format("status=%x data=%x",status,data))
emu.wait(1/31250*10)
end end
myco1=coroutine.create(co1) ok,errormsg=coroutine.resume(myco1)
and you get something like this as output:
[MAME]> myco1=coroutine.create(co1) ok,errormsg=coroutine.resume(myco1)
status=3 data=45
OVERRUN
status=23 data=45
[MAME]> status=3 data=90
status=3 data=49
status=3 data=44
status=3 data=90
status=3 data=49
status=3 data=0
|
|
|
|
Joined: Mar 2001
Posts: 17,217 Likes: 234
Very Senior Member
|
Very Senior Member
Joined: Mar 2001
Posts: 17,217 Likes: 234 |
Neat. I've started working on creating a "picture" image device so we can emulate the ComputerEyes for real now that the gameio is a slot. (I already added the Sirius Joyport so you can get more precise control of a lot of classic A2 games that support it).
|
|
|
|
Joined: Feb 2014
Posts: 1,102 Likes: 173
Very Senior Member
|
Very Senior Member
Joined: Feb 2014
Posts: 1,102 Likes: 173 |
Hi Arbee,
that sounds awesome! I gotta try the Joyport now. 8-)
|
|
|
|
Joined: Feb 2014
Posts: 1,102 Likes: 173
Very Senior Member
|
Very Senior Member
Joined: Feb 2014
Posts: 1,102 Likes: 173 |
Hi Arbee, I thought I'd give the sirius joyport a spin with my favorite game ever Stellar 7 and it was only letting me go left and right, but not up and down. Diving into joyport.cpp it looks like we just need to swap an_0 with an_1 and vice versa, super simple fix. an_0 selecting the player and an_1 choosing which direction we're reading git diff
diff --git a/src/devices/bus/a2gameio/joyport.cpp b/src/devices/bus/a2gameio/joyport.cpp
index cfc8ef1246..9ed0579644 100644
--- a/src/devices/bus/a2gameio/joyport.cpp
+++ b/src/devices/bus/a2gameio/joyport.cpp
@@ -76,23 +76,23 @@ void apple2_joyport_device::device_start()
READ_LINE_MEMBER(apple2_joyport_device::sw0_r)
{
- u8 port_read = m_an1 ? m_player2->read() : m_player1->read();
+ u8 port_read = m_an0 ? m_player2->read() : m_player1->read();
return BIT(port_read, 4);
}
READ_LINE_MEMBER(apple2_joyport_device::sw1_r)
{
- u8 port_read = m_an1 ? m_player2->read() : m_player1->read();
+ u8 port_read = m_an0 ? m_player2->read() : m_player1->read();
- return m_an0 ? BIT(port_read, 0) : BIT(port_read, 3);
+ return m_an1 ? BIT(port_read, 0) : BIT(port_read, 3);
}
READ_LINE_MEMBER(apple2_joyport_device::sw2_r)
{
- u8 port_read = m_an1 ? m_player2->read() : m_player1->read();
+ u8 port_read = m_an0 ? m_player2->read() : m_player1->read();
- return m_an0 ? BIT(port_read, 2) : BIT(port_read, 1);
+ return m_an1 ? BIT(port_read, 2) : BIT(port_read, 1);
}
WRITE_LINE_MEMBER(apple2_joyport_device::an0_w)
(END)
|
|
|
Forums9
Topics9,320
Posts121,944
Members5,074
|
Most Online1,283 Dec 21st, 2022
|
|
These forums are sponsored by Superior Solitaire, an ad-free card game collection for macOS and iOS. Download it today!
|
|
|
|