AppleWin / AppleWin

Apple II emulator for Windows
GNU General Public License v2.0
727 stars 167 forks source link

Asking for the way Applewin handles VBL and mouse interrupts. #265

Closed benoit0123 closed 8 years ago

benoit0123 commented 9 years ago

This post just to advise that Applewin and Virtual][ handle the same program differently (crash on Applewin, not on Virtual2) and asking for help... Forgive me for the verbosity of this post and the lack of fluency in English (which is not my mother language). A similar post was posted to comp.sys.apple2.emulators some time ago. Let's begin: I am in the process of adding some features to a utility I began working on some years ago. The newly added feature would be to enable high level "handling" of hardware interrupts (mouse moves, mouse button presses and VBL for the time being) by Applesoft "user written" subroutines (the ones being invoked with a GOSUB statement and usually ending their flow with a RETURN statement). The architecture is based on two components only being lazily bound together: A generic hardware interrupt handling which is inserted at the user IRQ vector (daisy chain). This hardware will handle mouse interface interrupts the apple way (which I hope so) and passing on the IRQ to the original IRQ vector it found when installed ($FF65 monitor ROM routine address if none). An intercept at the level of the Applesoft interpreter eval loop for creating Applesoft GOSUB stack frames ex nihilo and "passing control" to registered Applesoft subroutines (one for mouse related and one for timer/VBL related). The issue I've met here is: a) As the mechanism works great in my main developement environment which is the Virtual ][ emulator under Mac OS X (emulates an enhanced Apple //e with mouse interface card in slot 5). b) The same mechanism leads to a monitor prompt under the Applewin emulator (trying to handle both VBL and mouse moves/button presses concurrently (i.e. mouse interface mode being $0F) as soon as a mouse move occurs. However if I restrict myself to handle VBL only interupts (mouse interface mode being $08), the mechanism works great on Applewin as it does on Virtual ][. By the way, I observe the same behavior in Sweet16 as in Applewin :-( .. But what I do not understand is that the program works great on Virtual 2.

* My asking is: at which level is the mouse emulated within Applewin? Does Applewin emulate the Apple mouse card at the harware level (i.e. r/w access to page $C0), or does it include its own firmware for emulating an Apple mouse //? * For your information here is the extract which might be useful for investigation (65C02 variant). RSRVM = 1 SERVMOUSE reason code RREAD = 2 READMOUSE reason code BAMBS EQU $0778 Base address for mouse status

Thank you for reading, Benoît

tomcw commented 9 years ago

Hi Benoît,

My asking is: at which level is the mouse emulated within Applewin? Does Applewin emulate the Apple mouse card at the harware level (i.e. r/w access to page $C0), or does it include its own firmware for emulating an Apple mouse //?

AppleWin emulates the MouseCard at the hardware level with the exact firmware from the original MouseCard.

There have been several bugs in the MouseCard emulation over the years, so it's feasible that AppleWin's implementation contains yet more issues, especially around simultaneous IRQ generation (which I'm sure is untested).

I will take a look at your P15preview.zip and try to triage the issue.

benoit0123 commented 9 years ago

Thank you Tom for your quick reply. As I feel uncomfortable with the debugger (particularly for debugging interrupt routines), I have setup some markers within external memory for debugging purpose: $0300: Mouse status as returned from the last successful SERVEMOUSE call to firmware. $0301: Counter to give a hint when the break occurs. (initialized to zero value just after a successful (i.e. one that designates the mouse interact as the interrupt source) servmouse call has returned and incremented thereafter in the interrupt handling as well as in the foreground handling. $0302: Last reason code used for calling the mouse interface card: 01 for SERVEMOUSE, 02 for READMOUSE. $0303: Last offset applied to vector called which seems to be: $C4 for SERVEMOUSE and $9B for READMOUSE. The source contains many modules: the one that handles all runtime mouse interactions is PEERMOUSETIME. The mouse detection and filling of the offset (starting at OM_DEB) table is done within the MOUSEDET routine from the PEERINSTALL source code module. One thing that gets my attention is that you think that the firmware on the card within Applewin is standard but I do not get the same offsets in Apple win and in Virtual 2. For instance, if I get a look at the offset for SERVEMOUSE within Virtual 2, I get the $75 value not the $C4 value and the disassembly of this section differ from what I get within the Applewin context (C4C4L in the latter case). C575L PHA CLC BCC $C5B2 STA $C083,Y ... *C5B2L PHP LDA $00 PHA LDA #$60 << He he.. it looks like the code starting at $C4C4 within Applewin.. STA $00 SEI << but not identical... JSR $0000 TSX PLA STA $00 LDA $100,X PLP TAX ASL ASL ASL TAY ... I will ask M. Gerard Putter (the author of Virtual 2) whether he made some customizations to the mouse firmware. Or likely there were many versions of Apple mouse firmware released. Do not hesitate to contact me in case more clarification is required from I. Best regards, Benoît

benoit0123 commented 9 years ago

Hello Tom, Here is the reply I got on today from Gerard about what he did related to the Applemouse // firmware. " Hi Benoît,

Thanks for this very interesting question! The design pattern for the interface cards in Virtual ][ is to use the Apple II firmware as is, and emulate everything at the hardware level. Alas, this was not possible with the mouse card. This is because the mouse must smoothly integrate with the Mac mouse, and from the Mac application level you cannot access the detailed readings needed in the Apple II firmware. You can still see the effect of this design in the two modes of operation Virtual ][ has for the mouse: "relative" mode and "absolute" mode. They both have to do with the way the Mac mouse values are translated to Apple II mouse values.

So what I did is this: I loosely based my firmware on the Apple //e mouse card, in order to be compatible with the documented software interface. I had to replace some 65C02 instructions with 6502 equivalents, so it would work run on the Apple ][(+) as well. And I made shortcuts for the low level hardware access, to make it redirect to Virtual ][, which then interfaces with the Mac mouse. Regards, Gerard "

Op 10 feb. 2015, om 09:35 heeft Benoît Gilon bgilon@free.fr het volgende geschreven:

Hello Gerard,

I am in the process of delivering a DOS 3.3 utility allowing the use of Applesoft subroutines to handle interrupts originating from the mouse interface (moves, button presses and VBL/timer). Currently, the mechanism works great on the Virtual 2 emulator which is my main development environment. However, I observe a crash in Applewin (see my recent post in comp.emulators.apple2 for details). Tom, who is in charge of the emulator, told me that the Apple mouse firmware he used within Applewin is standard from Apple and that the emulation level is a pure hardware emulation. However, I do not get the same disassembly listing when comparing what is output from the Apple mouse card within Virtual 2 and within Applewin card. Please would you tell me whether you modified the firmware on the card emulated by Virtual 2 or you followed the same direction as the Applewin team (i.e. no firmware customization)?

Thank you for any info on this, Best regards, Benoît

benoit0123 commented 9 years ago

I plan to deliver an exec and a source code dedicated for testing on this issue w/o all the sideways aspect of the utility itself thus we can communiate on this hopefully tiny code (planned delivery for this week end). One asking: Is there a way to confirgure Applewin on its behavior when encountering an invalid opcode in memory? sorry to ask this newbie question but the CHM Applewin file on my "workstation" is not operational (WIndows 7 x64) as the content panel (right pannel) is all blank whatever the item is selected on the navigation tree on the left panel.

Regards, Benoît

sicklittlemonkey commented 9 years ago

This is a "security feature" of Windows 7. Right-click the CHM and unblock it. http://stackoverflow.com/questions/11438634/opening-a-chm-file-produces-navigation-to-the-webpage-was-canceled

In any case, I don't think AppleWin's behavior to opcodes is configurable.

Cheers, Nick. On 13/02/2015 12:03 AM, "benoit0123" notifications@github.com wrote:

I plan to deliver an exec and a source code dedicated for testing on this issue w/o all the sideways aspect of the utility itself thus we can communiate on this hopefully tiny code (planned delivery for this week end). One asking: Is there a way to confirgure Applewin on its behavior when encountering an invalid opcode in memory? sorry to ask this newbie question but the CHM Applewin file on my "workstation" is not operational (WIndows 7 x64) as the content panel (right pannel) is all blank whatever the item is selected on the navigation tree on the left panel.

Regards, Benoît

— Reply to this email directly or view it on GitHub https://github.com/AppleWin/AppleWin/issues/265#issuecomment-74053479.

tomcw commented 9 years ago

One asking: Is there a way to confirgure Applewin on its behavior when encountering an invalid opcode in memory?

Actually you can configure things when running from the debugger (F7), eg:

F7
> brk 1
> brk 2
> brk 3
> brk on
g

But this is convoluted, and of course it's running in debug mode, so you need to be proficient in using the built in debugger. (See the debugger's help brk for a bit more info.)

EDIT: This may not be of any use due to #267.

tomcw commented 9 years ago

OK, I've given this issue a small bit of triage.

When running in Debug mode, AppleWin will output debug messages about the mouse activity. Around the point where it goes wrong, AppleWin's mouse emulation is apparently seeing a spurious interrupt. I'll need to do more tracing to understand more.

But from my comments in the code, it looks like I saw a similar issue with Contiki's mouse support, but I never resolved things (other than adding the debug output to AppleWin).

benoit0123 commented 9 years ago

One thing worth noting is that a similar crash in the same circumstances occurs within Sweet 16 3.0.3 (that's the reason of my original post in comp.emulators.apple2 and not just onto the Applewin forum).

So in order to cater for most of environments (from native hardware to emulation), I'll prepare a new version of my utility which will only claim VBL interrupts (mouse mode being 8 or 9) and generate mouse moves and buttons presses events from the interrupt handler as it seems that the TIMRTST1 Applesoft sample code works great both in Applewin current release and Sweet 16.

Regards, Benoît

benoit0123 commented 9 years ago

I have posted a new archive P15preview.zip on my Web site which illustrates the issue but without to cater with higher levels of debugging my own utility. Here is a quick help text: Just boot the D34Peersoftv15.do disk image; Type Ctrl-C at the HELLO program prompting you to select a Peersoft variant. Type the DOS command at the DOS 3.3. prompt ] BLOAD APWINMOUSTST2 Then issue a CALL-151 to enter the monitor and *6000G The program installs a small routine handling both VBL interrupts and mouse moves/button presses interrupts. Some words of explanation: I is a status for housekeeping by my utility (either $80 or $C0 means VBL interrupt detected) (either $40 or $C0 means mouse move or button press interrupt juste handled). X and Y are the X and Y values extracted from the screenholes (the READMOUSE call lies within the interrupt routine). S is the mouse button status after the READMOUSE call ($77C). H is the button and interrupt status just after a successful SERVEMOUSE call from interrupt handling. So that you can know track data (and possibly correlations) between what you get there and the debug trace. The source file has also been put in the source disk image (name is APWINMOUSTST2.S). One thing that I noted is that the frequency of VBL interrupts follows the frequency of the CPU (they seem to occur at 120 i/s when CPU frequency is set to x2).

Regards, Benoît

tomcw commented 9 years ago

Thanks for the simplified reproducible.

btw. changing the CPU frequency changes everything to run at this new frequency not just CPU. Yes, strictly speaking this is a bug, but I'm not too worried about it.

tomcw commented 9 years ago

The problem is that a new mouse event (IRQ) is occurring mid-way through your interrupt handler, ie:

So a fix for your IRQ handler would be to just exit your handler if TOMOUSE(Y=RSRVM) returns with C=1, since you already got the mouse state from the previous IRQ handler.

NB. I don't know if my MouseCard emulation is correct though. If you have real MouseCard hardware, then I'd be very interested to know how it behaves in this specific case. Can you check and report your findings?

On extra thing: I noticed that Dazzle Draw also causes AppleWin to output debug messages about spurious interrupts. I will check its IRQ handler to see how it handles this error case for RSRVM (MOUSE_SERV).

benoit0123 commented 9 years ago

Hello Tom,

Thank you for your deep analysis of what might happen.

a) During the WE, I managed to put a new IH mechanism where only VBL interrupts are officialy handled (mouse mode set to $9). However, as I am still calling the READMOUSE from this routine, I can "regenerate" missing mouse moves and mouse button presses for my foreground environment to cater for. Good to see that it seems to work both in Applewin and in Sweet 16 3.0.3;

b) I've put my hand on a hardware Applemouse // and an enhanced //e hardware during this week end. I'll run the APWINMOUSTST2 sample binary program within this environment and report the results to you once the 5"1/4 image is concverted to physical disk in the days to come. In case more info is needed (than those actually shown onscreen) like $C0 hardware locations values, feel free to ask for them as I plan to leave the mouse card in the Apple //e till I find that the utility I am working on could be delivered (which might need some furthers weeks of thorough testing).

Best regards, Benoît

benoit0123 commented 9 years ago

Hi Tom, For your information: a) On a ROM03 hardware //gs: a.1) original IH routine (mouse mode set to $0F).. same behavior (exactly) as in Sweet 16 3.0.3.. (output to monitor prompt likely the one being on $FF65 address). a.2) new IH routine (with mouse mode set to $09): works great just like on Sweet 16 3.0.3. b) On a real hardware //e with Applemouse // in slot 4: b.1) passive mode (code sample from user manual): OK (that means that the hardware seems to work); b.2) original routine (APWINMOUSTST2S4): leads to an horrible crash (cannot even recover from it). I have to investigate more on this. b.3) new IH routine: not yet tested.(will do that tonight after case b.2 be solved if time allows).

Regards, Benoît

tomcw commented 9 years ago

That's interesting information about how your code behaves on real hardware. So it appears that AppleWin is correctly emulating (or it's very similar) to the real hardware.

btw. even with your new IH (that just enables VBL interrupts) there is a chance that this will have problems too, eg:

benoit0123 commented 9 years ago

If I get things right from your last comments, you are suggesting that I conclude the IH routine by a RTI whenever the SERVEMOUSE returns with a carry set instead of just passing the user IRQ to some potential earlier claimants. That would imply that the mouse be the last user IRQ potential claimant to be tested. Other potential sources like a serial port or a clock chip should be tested before because I could not discriminate between a spurious mouse interrupt and a valid interrupt from another source by studying the SERVEMOUSE result (i.e. carry flag).

Here are two URL which might help: http://www.archivum.info/comp.sys.apple2.programmer/2006-02/00162/Contiki-developer-needs-help-on-mouse-programming-!.html Oliver is using ProDOS (an established OS according to Apple tech notes) rather than DOS 3.3 (an unestablished OS according to the same source). http://www.umich.edu/~archive/apple2/technotes/tn/mous/

benoit0123 commented 9 years ago

OK I've finished my validation work on every hardware (ROM03 2GS, mem. exp. //c and enhanced //e)/emulation host I could put my hand on and it seems that the solution suggested by Tom is the best. That is: a) keep the mouse mode range from $0 to $F; b) as the OLDVECT (original vector) is set to $FF65 (original value put at $3FE by DOS 3.3), return with a RTI instead of jumping to the address held in OLDVECT ($FF65) whenever SERVEMOUSE returns with carry set. Thank you Tom for the diagnose on this issue.

tomcw commented 9 years ago

That would imply that the mouse be the last user IRQ potential claimant to be tested. Other potential sources like a serial port or a clock chip should be tested before because I could not discriminate between a spurious mouse interrupt and a valid interrupt from another source by studying the SERVEMOUSE result (i.e. carry flag).

You make an interesting point. Do you know if there is a specification (from Apple) for chaining to other interrupt handlers?

tomcw commented 9 years ago

Apple II: Interrupt Handling http://support.apple.com/kb/TA28361?viewlocale=en_US

So cards in adjacent slots can mask interrupts.

Slot 0 has the highest priority and slot 7 has the least.

EG: slot4 = mouse slot5 = mockingboard

So slot4 interrupts will take priority (and mask) any slot5 interrupt.

But this doesn't work if there's an empty slot.

This priorty system fails if there is an empty slot between any two interrupting cards.

EG: slot2 = mouse slot5 = mockingboard

In this case, both cards can assert the 6502's IRQ, and the slot h/w masking doesn't come into play.

NB. This slot priority & h/w interrupt masking isn't emulated.

At the s/w level, it just says to set the user vector in $3FE,3FF. It doesn't discuss chaining. Maybe there's an updated document for the Enhance Apple //e (or //c)?

sicklittlemonkey commented 9 years ago

(BTW, I suggest gettings PDFs with OCR text if available for all archive.org downloads.)

The Apple IIe Technical Reference Manual discusses interrupts starting on page 146: https://archive.org/details/Apple_IIe_Technical_Reference_Manual

I don't think it discusses chaining, but refers the reader to:

(a) the Apple II Pascal 1.2 Device and Interrupt Support Tools Manual: https://archive.org/details/Apple_II_Pascal_1.2_Device_and_Interrupt_Support_Tools_Manual This discusses chaining.

and (b) the ProDOS Technical Reference Manual: https://archive.org/details/Apple_ProDOS_8_Technical_Reference_Manual No chaining mentioned. : - (

Cheers, Nick.

benoit0123 commented 9 years ago

Talking here about software chaining of user IRQ handling routines (not hardware chaining for IRQ (de)assertions "up to" the 6502 pin level)...

What I am trying to do here is something like "application level" cooperative chaining as neither the firmware in ROM nor the DOS 3.3 provides such ability from a system point of view AFAIK.

Likely the ability to chain user IRQ handling routines is the difference made by Apple when they consider "established* OS (ProDOS 8 and Pascal 1.2 at the time the notes were composed) "versus" "unestablished OS" (as the venerable DOS 3.3) within the A2tech notes dealing with mouse handling.

Section 1.1.4 of the ProDOS technical reference manual mentions that up to 4 "interrupting devices" at a time can be handled by ProDOS. Two system calls are provided ALLOC_INTERRUPT and DEALLOC_INTERRUPT Section 6.2 details the internal mechanism within ProDOS 8. I understand that this mechanism works like "chaining"... albeit the exact term is not quoted as such in this section.

Regards, Benoît

sicklittlemonkey commented 9 years ago

Benoit, thanks for pointing that out.

I guess ProDOS provides a framework that does chaining then.

The Apple Pascal document describes how to chain manually.

Cheers, Nick.

tomcw commented 9 years ago

On extra thing: I noticed that Dazzle Draw also causes AppleWin to output debug messages about spurious interrupts. I will check its IRQ handler to see how it handles this error case for RSRVM (MOUSE_SERV).

I took a look at Dazzle Draw's mouse handling routines.

Here's what it does:

So Dazzle Draw just ignores the case when MOUSE_SERV returns with C=1. Additionally to reduce the IRQ handler's overhead it calls MOUSE_READ back in the main code.

tomcw commented 9 years ago

I checked the AppleMouse II User's Manual, appendix B ("AppleMouse II Firmware"):

irq

This implies that any interrupts are latched until the end of the video frame, and then (if any interrupts are pending) IRQ is asserted.

If this were true, then the interrupt handler should not exit to the Monitor (except for the edge case I described above).

But given the empirical evidence from Benoît (ie. for both and ROM03 //gs and //e behaving like AppleWin), I'm doubting the correctness of this bit of the manual. (Also the manual has other errors, eg. "Except for SERVEMOUSE, the status of the 6502 carry bit (C) indicates whether or not the routine was successfully executed: C=0 Successful execution"... when clear this does apply to SERVEMOUSE.)

benoit0123 commented 8 years ago

Hi all,

Just got my hand on an apple mouse tech note @ http://www.brutaldeluxe.fr/products/france/apple/forumdesdeveloppeurs/apple_forumdesdeveloppeurs_08_tn_mouse.pdf

And its refers to some bug within the mouse card firmware (6805 chip version). By the way, the conservative measures they recommend to potential developers were the ones I comply within my utility. I have to be careful when adding support to more interrupt enabled cards such as the SSC ;-).