Skip to content

Apple IIe MouseCard/screen emulation is wrong #13598

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
colinleroy opened this issue Apr 16, 2025 · 27 comments
Open

Apple IIe MouseCard/screen emulation is wrong #13598

colinleroy opened this issue Apr 16, 2025 · 27 comments

Comments

@colinleroy
Copy link
Contributor

The Apple MouseCard is supposed to fire interrupts synced on VBL (cf https://mirrors.apple2.org.za/Apple%20II%20Documentation%20Project/Interface%20Cards/Digitizers/Apple%20Mouse%20Interface%20Card/Documentation/Apple%20II%20Mouse%20Technical%20Notes.pdf for example).

However, doing so flickers a lot when using the mouse interrupt as VBL detection, even when it should not:
https://www.youtube.com/watch?v=NJsZvI407XI

On the contrary, emulating a IIc or IIgs never flickers, even when the drawing is too slow to stay ahead of the beam.

None of those situations are ideal and make debugging more complicated than it should be. I workaround the issue by using the $C019 softswitch on IIe, but that's not great.

I would love to help fix it, but have so far no idea where to look for what to fix.
Thanks!

@rb6502
Copy link
Contributor

rb6502 commented Apr 17, 2025

Hi Colin,

The Technical Notes mention that the mouse card can generate either 50 or 60 Hz interrupts via a setting, but they don't say the interrupt is synced to the actual vertical blank anywhere that I'm seeing. I'm not even sure how that would work, as there are no video-related signals on slot 4 where the mouse typically was installed.

I guess it's possible that the 6502 firmware polls $C019 on a IIe and tries to sync it that way, but first we need to determine if the interrupts are really synced on a IIe (or II Plus, for that matter).

-RB

@peterferrie
Copy link
Member

peterferrie commented Apr 17, 2025 via email

@rb6502
Copy link
Contributor

rb6502 commented Apr 17, 2025

If it does that, then it should just work in MAME.

@colinleroy
Copy link
Contributor Author

colinleroy commented Apr 17, 2025

If it does that, then it should just work in MAME.

And yet, it doesn't.

I have questioned my sanity over that, and I have questioned Apple engineer's sanity. I made schematics with theories:

Image

I have sent the binary that you saw running under MAME in the video linked in the issue and I got, so far, two different persons telling me "I do not see any flickering and yes it drawn clearly.", "I don't see any flickering at 60Hz, also the puck moves SO SMOOTHLY".

Which is why I think something is wrong with MAME, and would love some help figuring it out. I have a theory but I don't really want to go on a multiple-evenings-long sidequest blindly, one of them is this comment in apple2e.cpp:

m_screen->set_raw(1021800*14, (65*7)*2, 0, (40*7)*2, 262, 0, 192);

I also see nothing related to the screen in src/devices/bus/a2bus/mouse.cpp.

This does not seem to take into account the stretched cycle. Could it be a lead?

Thanks in advance.

@colinleroy
Copy link
Contributor Author

Maybe another lead, MAME outputs warnings from the a2bus/mouse PIA:

[:sl4:mouse:a2mse_pia] Warning! No port CB2 write handler. Previous value has been lost!

@colinleroy
Copy link
Contributor Author

Finally, but this proves about nothing as these are also not the real hardware, AppleWin and Virtual][ don't show this behaviour and my code does not flicker when ran by thoses emulators.

@rb6502
Copy link
Contributor

rb6502 commented Apr 17, 2025

We don't emulate the stretched cycle, but we don't emulate it for either the CPU or the video generation so vapor lock and CPU/video cycle sync work.

AppleWin and V][ make no attempts to emulate the actual mouse card hardware so that's not useful data, as you surmised.

@rb6502
Copy link
Contributor

rb6502 commented Apr 17, 2025

Oh, and CB2 on the PIA is not connected, as per the schematic on A2DP.

@rb6502
Copy link
Contributor

rb6502 commented Apr 17, 2025

Try setting the 68705 clock to 1021800 in mouse.cpp. That seems to make the cursor smoother in Apple II Desktop, and the schematic shows both the microcontroller and the PIA are connected to the slot's phase 0 so I'm not sure why it was double that before.

@colinleroy
Copy link
Contributor Author

Thanks. I tried that, and it doesn't really help.
I've patched MAME to verbosely log the RDVBL reads, the PIA, and the MCU, and... I don't really know what to do with it :/

Does this log give you any idea ? Right after the "RD VBLBAR 80" is when, I suppose, the firmware should tell the PIA that should tell the MCU to reset its timer?

Thanks in advance!

log.txt

pia_mcu_verbose.patch.txt

@colinleroy
Copy link
Contributor Author

colinleroy commented Apr 17, 2025

Adding a bit more log in m6805_timer::update, I see no timer reset either at the end of the VBL polling. I suppose that's at least part of the problem ?

...
RD VBLBAR 80
RD VBLBAR 80
[:sl4:mouse:a2mse_mcu] PORTC is unset
[:sl4:mouse:a2mse_mcu] m_tdr 216, m_source 0, prescale 10, m_divisor 0, decrements 10, interrupt 0 <=
RD VBLBAR 80
RD VBLBAR 80
RD VBLBAR 80
RD VBLBAR 80
RD VBLBAR 80
[:sl4:mouse:a2mse_mcu] PORTC is unset
[:sl4:mouse:a2mse_mcu] m_tdr 206, m_source 0, prescale 10, m_divisor 0, decrements 10, interrupt 0 <=
RD VBLBAR 80
RD VBLBAR 80
RD VBLBAR 80
RD VBLBAR 00
[:sl4:mouse:a2mse_mcu] PORTC is unset
[:sl4:mouse:a2mse_mcu] m_tdr 196, m_source 0, prescale 10, m_divisor 0, decrements 10, interrupt 0 <=
[:sl4:mouse:a2mse_pia] PIA port B read = 04
[:sl4:mouse:a2mse_pia] PIA port B read = 04
[:sl4:mouse:a2mse_pia] PIA port B write = 0C DDRB=3e
[:sl4:mouse:a2mse_mcu] PORTC is unset
[:sl4:mouse:a2mse_mcu] m_tdr 186, m_source 0, prescale 10, m_divisor 0, decrements 10, interrupt 0 <=
[:sl4:mouse:a2mse_pia] PIA port B read = 0C
[:sl4:mouse:a2mse_pia] PIA control A write = 00
[:sl4:mouse:a2mse_pia]  - CA1 interrupts disabled
[:sl4:mouse:a2mse_pia]  - CA1 interrupts active on high-to-low transition
[:sl4:mouse:a2mse_pia]  - Port A DDR register selected
[:sl4:mouse:a2mse_pia] PIA DDR A read = 00
[:sl4:mouse:a2mse_pia] PIA DDR A write = FF (output mode)
[:sl4:mouse:a2mse_pia] PIA port A write due to DDR change = 50 DDRA=ff
[:sl4:mouse:a2mse_pia] PIA control A write = 04
[:sl4:mouse:a2mse_pia]  - CA1 interrupts disabled
[:sl4:mouse:a2mse_pia]  - CA1 interrupts active on high-to-low transition
[:sl4:mouse:a2mse_pia]  - Port A Data register selected
[:sl4:mouse:a2mse_mcu] PORTC is unset
[:sl4:mouse:a2mse_mcu] m_tdr 176, m_source 0, prescale 10, m_divisor 0, decrements 10, interrupt 0 <=
[:sl4:mouse:a2mse_pia] PIA port A read = 50

Edit: Sorry, there's one just ten lines after, it goes back to 255.

@rb6502
Copy link
Contributor

rb6502 commented Apr 18, 2025

I'm going to have to read up on how the timer works on the 68705, but it probably auto-repeats if you don't do anything.

@cuavas
Copy link
Member

cuavas commented Apr 18, 2025

The 68705 timer is working. We’ve got lots of nasty test cases for it. The Zorba keyboard and Xain’d Sleena MCU were particularly nasty to get right. It isn’t free-running like the 68HC05 timers.

@cuavas
Copy link
Member

cuavas commented Apr 18, 2025

Edit: Sorry, there's one just ten lines after, it goes back to 255.

That’s correct, it triggers an interrupt when it passes zero and continues to count down, wrapping around to 255. This allows the software to determine how long it was from when the timer triggered to when it the interrupt is serviced. This is important for things that use it to generate asynchronous serial timings (like the Zorba keyboard does), etc.

@cuavas
Copy link
Member

cuavas commented Apr 18, 2025

OK, after looking at the schematics, I noticed the 6821’s CB1 is tied high, but we haven’t hooked this up in MAME. It’s worth giving that a shot just to eliminate it as a possibility. Try setting it in device_start:

void a2bus_mouse_device::device_start()
{
	// register save state variables
	save_item(NAME(m_port_a_in));
	save_item(NAME(m_port_b_in));
	save_item(NAME(m_last));
	save_item(NAME(m_count));

	m_pia->cb1_w(1); // tied high via 10k resistor
}

@colinleroy
Copy link
Contributor Author

Hi!
Thanks for looking into it :)
It seems to be better with cb1 tied high, but it's not stable, though: https://youtu.be/TbKvR71oMg0

@cuavas
Copy link
Member

cuavas commented Apr 19, 2025

Try setting the 68705 clock to 1021800 in mouse.cpp. That seems to make the cursor smoother in Apple II Desktop, and the schematic shows both the microcontroller and the PIA are connected to the slot's phase 0 so I'm not sure why it was double that before.

Schematic here shows the MCU being driven from the Q3 2MHz asymmetrical clock (card edge pin 37) via the 16R4 PAL. Is the firmware we have from a different card?

@cuavas
Copy link
Member

cuavas commented Apr 19, 2025

Would help to actually link to the schematic: https://archive.org/details/APPLE_050-0101-A-1of1

@cuavas
Copy link
Member

cuavas commented Apr 19, 2025

8ab7404 may help with timing issues.

@colinleroy
Copy link
Contributor Author

Hi Vas,

Thanks for looking into this. I've cherry-picked the commit, but it doesn't help: https://www.youtube.com/watch?v=GTbesntgicQ

If it may help to test, my code is now released at https://www.colino.net/wordpress/wp-content/uploads/shufflepuck-beta-1-960a89c4.po

Is the firmware we have from a different card?

That would explain things... :-)

@colinleroy
Copy link
Contributor Author

Very naive question, is the 6821 PIA and the 6520 the same thing? (You can tell I'm out of my depth here) https://www.applefritter.com/content/apple-mouse-card-pia-chip

@cuavas
Copy link
Member

cuavas commented Apr 19, 2025

The 6821 is supposed to be 100% compatible from a software point of view. The main difference is that it’s manufactured using a newer semiconductor process. The electrical characteristics are a bit different, but it shouldn’t matter for emulation purposes.

@robjustice
Copy link
Contributor

robjustice commented Apr 25, 2025

I did a decode of the PAL and see the SYNCLATCH is an output that goes to the PIA PB0, maybe its looking for this somehow to sync up?

Equations:

/o12(LS245) = /i8(DEVSEL) +
/i9(IOSEL)
o12.oe = vcc

these appear not connected to anything

/o13 = /i6 & i7 +
     i6 & /i7
o13.oe = vcc

/rf14 := i6
rf14.oe = OE

/rf15 :=
rf15.oe = OE

/rf16 :=
rf16.oe = OE

/rf17(SYNCLATCH) := i4(D0)
rf17.oe = OE (OE tied to GND)

/o18(2MHZCLOCK) = /i3(Q3)
o18.oe = vcc

/o19(feedback to pin 1 clock input for rf17) = i2(IOSTR) +
i3(Q3)
o19.oe = vcc

@rb6502
Copy link
Contributor

rb6502 commented Apr 26, 2025

So SYNCLATCH is just a passthrough of the A2 bus D0 line and 2MHZCLOCK is Q3 inverted?

@rb6502
Copy link
Contributor

rb6502 commented Apr 26, 2025

AppleWin doesn't do anything special with SYNCLATCH that I can see, it should always return 0 there. This is very confusing.

@robjustice
Copy link
Contributor

My understanding of the logic is that it will clock the value of D0 into SYNCLATCH only when IOSTR is low. When IOSTR is high, the clock input will be stuck at high regardless of the Q3 signal, so effectively disabling the clocking for SYNCLATCH. What its doing this for seems a mystery still.

@colinleroy
Copy link
Contributor Author

colinleroy commented Apr 28, 2025

I'm absolutely out of my depth here. A thing that I have noticed is that if I let time pass, the flickering changes place while my sprites don't: https://www.youtube.com/watch?v=cBB4_vKQtCA (that code's image at https://colino.net/tmp/shflpuck-mame-test.po if needed).

That makes me think that there might be a very small difference in the VBL frequency versus the mouseCard's IRQ frequency?

Another video showing the flickering on the Cafe screen, at 0:54, 2:05 and 3:14. https://www.youtube.com/watch?v=ADV8-4yEa50

The pointer is a 14x11, 33 bytes sprite that can't ever be out of budget to draw. It takes about 888 cycles for the IRQ to be processed, 1034 cycles to clear the pointer, 1667 to draw it, so it's supposed to be done 1ms before the beam is even back at the top.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants