mirror of
https://github.com/JorjBauer/aiie.git
synced 2024-12-27 14:30:22 +00:00
patching together more mouse work
This commit is contained in:
parent
b09df8e5f9
commit
0b8e027096
8
Makefile
8
Makefile
@ -8,17 +8,17 @@ CXXFLAGS=-Wall -I/usr/include/SDL2 -I .. -I . -I apple -I nix -I sdl -I/usr/loca
|
|||||||
|
|
||||||
TSRC=cpu.cpp util/testharness.cpp
|
TSRC=cpu.cpp util/testharness.cpp
|
||||||
|
|
||||||
COMMONSRCS=cpu.cpp apple/appledisplay.cpp apple/applekeyboard.cpp apple/applemmu.cpp apple/applevm.cpp apple/diskii.cpp apple/nibutil.cpp LRingBuffer.cpp globals.cpp apple/parallelcard.cpp apple/fx80.cpp lcg.cpp apple/hd32.cpp images.cpp apple/appleui.cpp vmram.cpp bios.cpp apple/noslotclock.cpp apple/woz.cpp apple/crc32.c apple/woz-serializer.cpp
|
COMMONSRCS=cpu.cpp apple/appledisplay.cpp apple/applekeyboard.cpp apple/applemmu.cpp apple/applevm.cpp apple/diskii.cpp apple/nibutil.cpp LRingBuffer.cpp globals.cpp apple/parallelcard.cpp apple/fx80.cpp lcg.cpp apple/hd32.cpp images.cpp apple/appleui.cpp vmram.cpp bios.cpp apple/noslotclock.cpp apple/woz.cpp apple/crc32.c apple/woz-serializer.cpp apple/mouse.c
|
||||||
|
|
||||||
COMMONOBJS=cpu.o apple/appledisplay.o apple/applekeyboard.o apple/applemmu.o apple/applevm.o apple/diskii.o apple/nibutil.o LRingBuffer.o globals.o apple/parallelcard.o apple/fx80.o lcg.o apple/hd32.o images.o apple/appleui.o vmram.o bios.o apple/noslotclock.o apple/woz.o apple/crc32.o apple/woz-serializer.o apple/mouse.o apple/pia6821.o
|
COMMONOBJS=cpu.o apple/appledisplay.o apple/applekeyboard.o apple/applemmu.o apple/applevm.o apple/diskii.o apple/nibutil.o LRingBuffer.o globals.o apple/parallelcard.o apple/fx80.o lcg.o apple/hd32.o images.o apple/appleui.o vmram.o bios.o apple/noslotclock.o apple/woz.o apple/crc32.o apple/woz-serializer.o apple/mouse.o
|
||||||
|
|
||||||
FBSRCS=linuxfb/linux-speaker.cpp linuxfb/fb-display.cpp linuxfb/linux-keyboard.cpp linuxfb/fb-paddles.cpp nix/nix-filemanager.cpp linuxfb/aiie.cpp linuxfb/linux-printer.cpp nix/nix-clock.cpp nix/nix-prefs.cpp
|
FBSRCS=linuxfb/linux-speaker.cpp linuxfb/fb-display.cpp linuxfb/linux-keyboard.cpp linuxfb/fb-paddles.cpp nix/nix-filemanager.cpp linuxfb/aiie.cpp linuxfb/linux-printer.cpp nix/nix-clock.cpp nix/nix-prefs.cpp
|
||||||
|
|
||||||
FBOBJS=linuxfb/linux-speaker.o linuxfb/fb-display.o linuxfb/linux-keyboard.o linuxfb/fb-paddles.o nix/nix-filemanager.o linuxfb/aiie.o linuxfb/linux-printer.o nix/nix-clock.o nix/nix-prefs.o
|
FBOBJS=linuxfb/linux-speaker.o linuxfb/fb-display.o linuxfb/linux-keyboard.o linuxfb/fb-paddles.o nix/nix-filemanager.o linuxfb/aiie.o linuxfb/linux-printer.o nix/nix-clock.o nix/nix-prefs.o
|
||||||
|
|
||||||
SDLSRCS=sdl/sdl-speaker.cpp sdl/sdl-display.cpp sdl/sdl-keyboard.cpp sdl/sdl-paddles.cpp nix/nix-filemanager.cpp sdl/aiie.cpp sdl/sdl-printer.cpp nix/nix-clock.cpp nix/nix-prefs.cpp nix/debugger.cpp nix/disassembler.cpp
|
SDLSRCS=sdl/sdl-speaker.cpp sdl/sdl-display.cpp sdl/sdl-keyboard.cpp sdl/sdl-paddles.cpp nix/nix-filemanager.cpp sdl/aiie.cpp sdl/sdl-printer.cpp nix/nix-clock.cpp nix/nix-prefs.cpp nix/debugger.cpp nix/disassembler.cpp sdl/sdl-mouse.cpp
|
||||||
|
|
||||||
SDLOBJS=sdl/sdl-speaker.o sdl/sdl-display.o sdl/sdl-keyboard.o sdl/sdl-paddles.o nix/nix-filemanager.o sdl/aiie.o sdl/sdl-printer.o nix/nix-clock.o nix/nix-prefs.o nix/debugger.o nix/disassembler.o
|
SDLOBJS=sdl/sdl-speaker.o sdl/sdl-display.o sdl/sdl-keyboard.o sdl/sdl-paddles.o nix/nix-filemanager.o sdl/aiie.o sdl/sdl-printer.o nix/nix-clock.o nix/nix-prefs.o nix/debugger.o nix/disassembler.o sdl/sdl-mouse.o
|
||||||
|
|
||||||
ROMS=apple/applemmu-rom.h apple/diskii-rom.h apple/parallel-rom.h apple/hd32-rom.h MouseInterface.rom
|
ROMS=apple/applemmu-rom.h apple/diskii-rom.h apple/parallel-rom.h apple/hd32-rom.h MouseInterface.rom
|
||||||
|
|
||||||
|
142
apple/mouse.cpp
142
apple/mouse.cpp
@ -5,6 +5,7 @@
|
|||||||
#include "mouse-rom.h"
|
#include "mouse-rom.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
SW_W_INIT = 0x00,
|
||||||
SW_R_HOMEMOUSE = 0x08,
|
SW_R_HOMEMOUSE = 0x08,
|
||||||
SW_R_POSMOUSE = 0x09,
|
SW_R_POSMOUSE = 0x09,
|
||||||
SW_R_CLEARMOUSE = 0x0A,
|
SW_R_CLEARMOUSE = 0x0A,
|
||||||
@ -15,6 +16,11 @@ enum {
|
|||||||
SW_W_SETMOUSE = 0x0F
|
SW_W_SETMOUSE = 0x0F
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The first 3 soft switch bits technically should pass directly to
|
||||||
|
// the PIA6821. In practice, so far, I've only seen the first (SW_W_INIT)
|
||||||
|
// used when PR#4 is invoked to initialize the mouse interface from DOS,
|
||||||
|
// so for the moment I'll just catch that specifically.
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ST_MOUSEENABLE = 1,
|
ST_MOUSEENABLE = 1,
|
||||||
ST_INTMOUSE = 2,
|
ST_INTMOUSE = 2,
|
||||||
@ -26,6 +32,8 @@ Mouse::Mouse()
|
|||||||
{
|
{
|
||||||
status = 0;
|
status = 0;
|
||||||
interruptsTriggered = 0;
|
interruptsTriggered = 0;
|
||||||
|
lastX = lastY = 0;
|
||||||
|
lastButton = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mouse::~Mouse()
|
Mouse::~Mouse()
|
||||||
@ -50,29 +58,43 @@ uint8_t Mouse::readSwitches(uint8_t s)
|
|||||||
{
|
{
|
||||||
switch (s) {
|
switch (s) {
|
||||||
case SW_R_HOMEMOUSE:
|
case SW_R_HOMEMOUSE:
|
||||||
printf("unimplemented SW_R_HOMEMOUSE\n");
|
g_mouse->setPosition( (g_ram.readByte(0x578) << 8) | g_ram.readByte(0x478),
|
||||||
/* physical mouse X = $578/$478;
|
(g_ram.readByte(0x5F8) << 8) | g_ram.readByte(0x4F8)
|
||||||
* physical mouse Y = $5f8/$4f8 */
|
);
|
||||||
break;
|
break;
|
||||||
case SW_R_POSMOUSE:
|
case SW_R_POSMOUSE:
|
||||||
printf("unimplemented SW_R_POSMOUSE\n");
|
g_mouse->setPosition( (g_ram.readByte(0x578+4) << 8) | g_ram.readByte(0x478+4),
|
||||||
/* physical mouse X = $578+4/$478+4;
|
(g_ram.readByte(0x5F8+4) << 8) | g_ram.readByte(0x4F8+4)
|
||||||
* physical mouse Y + $5F8+4/$4f8+4 */
|
);
|
||||||
break;
|
break;
|
||||||
case SW_R_CLEARMOUSE:
|
case SW_R_CLEARMOUSE:
|
||||||
g_ram.writeByte(0x578+4, 0);
|
g_ram.writeByte(0x578+4, 0);
|
||||||
g_ram.writeByte(0x478+4, 0);
|
g_ram.writeByte(0x478+4, 0);
|
||||||
g_ram.writeByte(0x5F8+4, 0);
|
g_ram.writeByte(0x5F8+4, 0);
|
||||||
g_ram.writeByte(0x4F8+4, 0);
|
g_ram.writeByte(0x4F8+4, 0);
|
||||||
/* physical mouse X = Y = 0 */
|
g_mouse->setPosition(0,0);
|
||||||
break;
|
break;
|
||||||
case SW_R_READMOUSE:
|
case SW_R_READMOUSE:
|
||||||
printf("unimplemented SW_R_READMOUSE\n");
|
{
|
||||||
// FIXME: read from physical mouse and write to:
|
uint16_t xpos, ypos;
|
||||||
g_ram.writeByte(0x578+4, 0); // high X
|
g_mouse->getPosition(&xpos, &ypos);
|
||||||
g_ram.writeByte(0x478+4, 0); // low X
|
if (lastX != xpos || lastY != ypos) {
|
||||||
g_ram.writeByte(0x5F8+4, 0); // high Y
|
interruptsTriggered |= 0x20; // "x or y changed since last reading"
|
||||||
g_ram.writeByte(0x4F8+4, 0); // low Y
|
lastX = xpos; lastY = ypos;
|
||||||
|
}
|
||||||
|
curButton = g_mouse->getButton();
|
||||||
|
uint8_t newStatus = g_ram.readByte(0x778+4) & ~0xC0;
|
||||||
|
if (curButton) { newStatus |= 0x80; };
|
||||||
|
if (lastButton) { newStatus |= 0x40; };
|
||||||
|
|
||||||
|
uint16_t xv = xpos >> 8; xv &= 0xFF;
|
||||||
|
printf("XPOS: %d => 0x%X 0x%X\n", xpos, xv, xpos & 0xFF);
|
||||||
|
|
||||||
|
g_ram.writeByte(0x578+4, xv); // high X
|
||||||
|
g_ram.writeByte(0x478+4, xpos & 0xFF); // low X
|
||||||
|
g_ram.writeByte(0x5F8+4, (ypos >> 8) & 0xFF); // high Y
|
||||||
|
g_ram.writeByte(0x4F8+4, ypos); // low Y
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SW_R_INITMOUSE:
|
case SW_R_INITMOUSE:
|
||||||
// Set clamp to (0,0) - (1023,1023)
|
// Set clamp to (0,0) - (1023,1023)
|
||||||
@ -80,11 +102,15 @@ uint8_t Mouse::readSwitches(uint8_t s)
|
|||||||
g_ram.writeByte(0x478, 0); // low of lowclamp
|
g_ram.writeByte(0x478, 0); // low of lowclamp
|
||||||
g_ram.writeByte(0x5F8, 0x03); // high of highclamp
|
g_ram.writeByte(0x5F8, 0x03); // high of highclamp
|
||||||
g_ram.writeByte(0x4F8, 0xFF); // low of highclamp
|
g_ram.writeByte(0x4F8, 0xFF); // low of highclamp
|
||||||
printf("unimplemented SW_R_INITMOUSE\n");
|
g_mouse->setClamp(XCLAMP, 0, 1023);
|
||||||
/* physicalMouse->setClamp(XCLAMP, 0, 1023);
|
g_mouse->setClamp(YCLAMP, 0, 1023);
|
||||||
* physicalMouse->setClamp(YCLAMP, 0, 1023); */
|
|
||||||
break;
|
break;
|
||||||
case SW_R_SERVEMOUSE:
|
case SW_R_SERVEMOUSE:
|
||||||
|
if (lastButton) interruptsTriggered |= 0x40;
|
||||||
|
if (curButton != lastButton) {
|
||||||
|
interruptsTriggered |= 0x80;
|
||||||
|
lastButton = curButton;
|
||||||
|
}
|
||||||
g_ram.writeByte(0x778+4, interruptsTriggered);
|
g_ram.writeByte(0x778+4, interruptsTriggered);
|
||||||
g_ram.writeByte(0x6B8+4, interruptsTriggered); // hack to appease ROM
|
g_ram.writeByte(0x6B8+4, interruptsTriggered); // hack to appease ROM
|
||||||
interruptsTriggered = 0;
|
interruptsTriggered = 0;
|
||||||
@ -98,25 +124,30 @@ uint8_t Mouse::readSwitches(uint8_t s)
|
|||||||
void Mouse::writeSwitches(uint8_t s, uint8_t v)
|
void Mouse::writeSwitches(uint8_t s, uint8_t v)
|
||||||
{
|
{
|
||||||
switch (s) {
|
switch (s) {
|
||||||
|
case SW_W_INIT:
|
||||||
|
v &= 0x03; // just the low 3 bits apparently?
|
||||||
|
printf("Simple init: value is 0x%X\n", v);
|
||||||
|
status = v;
|
||||||
|
g_ram.writeByte(0x7f8 + 4, v);
|
||||||
|
break;
|
||||||
case SW_W_CLAMPMOUSE:
|
case SW_W_CLAMPMOUSE:
|
||||||
{
|
{
|
||||||
uint16_t lowval = (g_ram.readByte(0x578) << 8) | (g_ram.readByte(0x478));
|
uint16_t lowval = (g_ram.readByte(0x578) << 8) | (g_ram.readByte(0x478));
|
||||||
uint16_t highval = (g_ram.readByte(0x5F8) << 8) | (g_ram.readByte(0x4F8));
|
uint16_t highval = (g_ram.readByte(0x5F8) << 8) | (g_ram.readByte(0x4F8));
|
||||||
if (v) {
|
if (v) {
|
||||||
// Y is clamping
|
g_mouse->setClamp(YCLAMP, lowval, highval);
|
||||||
/* physicalMouse->setClamp(YCLAMP, lowval, highval); */
|
|
||||||
} else {
|
} else {
|
||||||
// X is clamping
|
// X is clamping
|
||||||
/* physicalMouse->setClamp(XCLAMP, lowval, highval); */
|
g_mouse->setClamp(XCLAMP, lowval, highval);
|
||||||
}
|
}
|
||||||
printf("unimplemented SW_W_CLAMPMOUSE [0x%X]\n", v);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SW_W_SETMOUSE:
|
case SW_W_SETMOUSE:
|
||||||
status = v;
|
status = v;
|
||||||
|
g_ram.writeByte(0x7f8 + 4, v);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("mouse: unknown switch write 0x%X\n", s);
|
printf("mouse: unknown switch write 0x%X = 0x%2X\n", s, v);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,7 +156,7 @@ void Mouse::loadROM(uint8_t *toWhere)
|
|||||||
{
|
{
|
||||||
/* Actual mouse ROM Disassembly:
|
/* Actual mouse ROM Disassembly:
|
||||||
C400- 2C 58 FF BIT $FF58 ; test bits in FF58 w/ A
|
C400- 2C 58 FF BIT $FF58 ; test bits in FF58 w/ A
|
||||||
C403- 70 1B BVS $C420 ; V will contain bit 6 from $FF58, which should be $20 on boot-up
|
C403- 70 1B BVS $C420 ; V will contain bit 6 from $FF58, which should be $60 on boot-up (RTS), which has $40 set, so should branch here
|
||||||
C405- 38 SEC
|
C405- 38 SEC
|
||||||
C406- 90 18 BCC $C420 ; no-op; unless called @ $C406 directly?
|
C406- 90 18 BCC $C420 ; no-op; unless called @ $C406 directly?
|
||||||
|
|
||||||
@ -154,13 +185,12 @@ C41D- AE
|
|||||||
C41E- AE
|
C41E- AE
|
||||||
C41F- AE
|
C41F- AE
|
||||||
|
|
||||||
; Main
|
; Main (installs KSW for IN# handling)
|
||||||
C420- 48 PHA ; push accumulator to stack
|
C420- 48 PHA ; push accumulator to stack
|
||||||
C421- 98 TYA
|
C421- 98 TYA
|
||||||
C422- 48 PHA ; push Y to stack
|
C422- 48 PHA ; push Y to stack
|
||||||
C423- 8A TXA
|
C423- 8A TXA
|
||||||
C424- 48 PHA ; push X to stack
|
C424- 48 PHA ; push X to stack
|
||||||
C424- 48 PHA
|
|
||||||
C425- 08 PHP ; push status to stack
|
C425- 08 PHP ; push status to stack
|
||||||
C426- 78 SEI ; disable interrupts
|
C426- 78 SEI ; disable interrupts
|
||||||
|
|
||||||
@ -176,28 +206,30 @@ C426- 78 SEI ; disable interrupts
|
|||||||
; TSX
|
; TSX
|
||||||
; LDA $100, X ; grab the return address off the stack
|
; LDA $100, X ; grab the return address off the stack
|
||||||
|
|
||||||
C427- 20 58 FF JSR $FF58
|
C427- 20 58 FF JSR $FF58 ; call something that will RTS
|
||||||
C42A- BA TSX
|
C42A- BA TSX ; pull stack pointer to X
|
||||||
C42B- BD 00 01 LDA $0100,X
|
C42B- BD 00 01 LDA $0100,X ; grab A from the current stack pointer, which has our return addr
|
||||||
C42E- AA TAX
|
C42E- AA TAX ; X = return addr
|
||||||
C42F- 0A ASL
|
C42F- 0A ASL
|
||||||
C430- 0A ASL
|
C430- 0A ASL
|
||||||
C431- 0A ASL
|
C431- 0A ASL
|
||||||
C432- 0A ASL
|
C432- 0A ASL
|
||||||
C433- A8 TAY
|
C433- A8 TAY ; Y = (return addr) << 4
|
||||||
C434- 28 PLP ; restore status from stack
|
C434- 28 PLP ; restore status from stack (includes V,C)
|
||||||
C435- 50 0F BVC $C446 ; overflow is clear if ... ?
|
C435- 50 0F BVC $C446 ; overflow is clear from when we were called?
|
||||||
C437- A5 38 LDA $38 ; >> what's in $38?
|
C437- A5 38 LDA $38 ; >> $38 is the IN# vector ("KSW") low byte
|
||||||
C439- D0 0D BNE $C448 ; restore stack & return
|
C439- D0 0D BNE $C448 ; restore stack & return
|
||||||
C43B- 8A TXA
|
C43B- 8A TXA
|
||||||
C43C- 45 39 EOR $39 ; >> what's in $39?
|
C43C- 45 39 EOR $39 ; >> KSW high byte
|
||||||
C43E- D0 08 BNE $C448 ; restore stack & return
|
C43E- D0 08 BNE $C448 ; restore stack & return
|
||||||
C440- A9 05 LDA #$05
|
C440- A9 05 LDA #$05
|
||||||
C442- 85 38 STA $38 ; ($38) = $05
|
C442- 85 38 STA $38 ; ($38) = $05
|
||||||
C442- 85 38 STA $38
|
|
||||||
C444- D0 0B BNE $C451
|
C444- D0 0B BNE $C451
|
||||||
|
|
||||||
|
;; we wind up here when the entry vector $c405 is called directly (from $9eba)
|
||||||
C446- B0 09 BCS $C451 ; carry set if ... ?
|
C446- B0 09 BCS $C451 ; carry set if ... ?
|
||||||
|
|
||||||
|
;; entry point when called as PR# so BASIC/DOS can init the mouse
|
||||||
C448- 68 PLA ; pull X from stack
|
C448- 68 PLA ; pull X from stack
|
||||||
C449- AA TAX
|
C449- AA TAX
|
||||||
C44A- 68 PLA ; pull Y from stack, but
|
C44A- 68 PLA ; pull Y from stack, but
|
||||||
@ -277,6 +309,7 @@ C4A7- D0 F1 BNE $C49A
|
|||||||
C4A9- EA NOP
|
C4A9- EA NOP
|
||||||
C4AA- A9 07 LDA #$07
|
C4AA- A9 07 LDA #$07
|
||||||
C4AC- D0 EC BNE $C49A
|
C4AC- D0 EC BNE $C49A
|
||||||
|
; "TimeData" to set freq before init to 50/60 Hz? Doesn't look like it...
|
||||||
C4AE- A2 03 LDX #$03
|
C4AE- A2 03 LDX #$03
|
||||||
C4B0- 38 SEC
|
C4B0- 38 SEC
|
||||||
C4B1- 60 RTS
|
C4B1- 60 RTS
|
||||||
@ -314,8 +347,7 @@ Patch: C471 from 99 82 C0 60 => 8D CF C0 60
|
|||||||
|
|
||||||
SERVEMOUSE @ $C4B2:
|
SERVEMOUSE @ $C4B2:
|
||||||
78 SEI
|
78 SEI
|
||||||
AD CE C0 LDA $C0CE ; use soft switch 0xE (read) to trigger this - expect ne\
|
AD CE C0 LDA $C0CE ; use soft switch 0xE (read) to trigger this - expect new value to be placed in $7f8+4 and $6b8+4
|
||||||
w value to be placed in $7f8+4 and $6b8+4
|
|
||||||
A2 04 LDX #$04 ; our slot number, for cleanup code
|
A2 04 LDX #$04 ; our slot number, for cleanup code
|
||||||
18 CLC
|
18 CLC
|
||||||
90 C1 BCC $C47C
|
90 C1 BCC $C47C
|
||||||
@ -324,7 +356,7 @@ Patch: C4B2 from 08 A5 00 48 A9 60 85 00 78 =>
|
|||||||
78 AD CE C0 A2 04 18 90 C1
|
78 AD CE C0 A2 04 18 90 C1
|
||||||
|
|
||||||
READMOUSE
|
READMOUSE
|
||||||
C48E- AD CB C0 LDA $C04B ; soft switch 0x0B for readmouse
|
C48E- AD CB C0 LDA $C0CB ; soft switch 0x0B for readmouse
|
||||||
18 CLC
|
18 CLC
|
||||||
60 RTS
|
60 RTS
|
||||||
|
|
||||||
@ -332,14 +364,14 @@ Patch: from A9 04 99 83 C0 =>
|
|||||||
AD CB C0 18 60
|
AD CB C0 18 60
|
||||||
|
|
||||||
CLEARMOUSE
|
CLEARMOUSE
|
||||||
C49F- AD CA C0 LDA $C04A ; soft switch 0x0A for clearmouse
|
C49F- AD CA C0 LDA $C0CA ; soft switch 0x0A for clearmouse
|
||||||
18 CLC
|
18 CLC
|
||||||
60 RTS
|
60 RTS
|
||||||
|
|
||||||
Patch: from EA A9 05 D0 F6 =>
|
Patch: from EA A9 05 D0 F6 =>
|
||||||
AD CA C0 18 60
|
AD CA C0 18 60
|
||||||
POSMOUSE
|
POSMOUSE
|
||||||
C4a4- AD C9 C0 LDA $C049 ; soft switch 0x09 for posmouse
|
C4a4- AD C9 C0 LDA $C0C9 ; soft switch 0x09 for posmouse
|
||||||
18 CLC
|
18 CLC
|
||||||
60 RTS
|
60 RTS
|
||||||
|
|
||||||
@ -347,20 +379,20 @@ Patch: from EA A9 06 D0 F1 =>
|
|||||||
AD C9 C0 18 60
|
AD C9 C0 18 60
|
||||||
|
|
||||||
CLAMPMOUSE
|
CLAMPMOUSE
|
||||||
C48A- 8D CD C0 STA $C04D ; use write to soft switch 0x0D to trigger clamp
|
C48A- 8D CD C0 STA $C0CD ; use write to soft switch 0x0D to trigger clamp
|
||||||
60 RTS
|
60 RTS
|
||||||
|
|
||||||
Patch: from 99 83 C0 60 => 8D CD C0 60
|
Patch: from 99 83 C0 60 => 8D CD C0 60
|
||||||
|
|
||||||
HOMEMOUSE
|
HOMEMOUSE
|
||||||
C4A9- AD C8 C0 LDA $c048 ; soft switch 0x08 for homemouse (read)
|
C4A9- AD C8 C0 LDA $c0C8 ; soft switch 0x08 for homemouse (read)
|
||||||
18 CLC
|
18 CLC
|
||||||
60 RTS
|
60 RTS
|
||||||
|
|
||||||
Patch: from EA A9 07 D0 EC => AD C8 C0 18 60
|
Patch: from EA A9 07 D0 EC => AD C8 C0 18 60
|
||||||
|
|
||||||
INITMOUSE
|
INITMOUSE
|
||||||
C498- AD CC C0 LDA $C04C ; soft switch 0x0C read for initmouse
|
C498- AD CC C0 LDA $C0CC ; soft switch 0x0C read for initmouse
|
||||||
18 CLC
|
18 CLC
|
||||||
60 RTS
|
60 RTS
|
||||||
|
|
||||||
@ -376,8 +408,8 @@ Patch: from A9 02 99 83 C0 => AD CC C0 18 60
|
|||||||
0x0A, 0x0A, 0x0A, 0xA8, 0x28, 0x50, 0x0F, 0xA5, // C430
|
0x0A, 0x0A, 0x0A, 0xA8, 0x28, 0x50, 0x0F, 0xA5, // C430
|
||||||
0x38, 0xd0, 0x0d, 0x8a, 0x45, 0x39, 0xd0, 0x08,
|
0x38, 0xd0, 0x0d, 0x8a, 0x45, 0x39, 0xd0, 0x08,
|
||||||
0xa9, 0x05, 0x85, 0x38, 0xd0, 0x0b, 0xb0, 0x09, // C440
|
0xa9, 0x05, 0x85, 0x38, 0xd0, 0x0b, 0xb0, 0x09, // C440
|
||||||
0x68, 0xaa, 0x68, 0xea, 0x68, 0x99, 0x80, 0xc0,
|
0x68, 0xaa, 0x68, 0xea, 0x68, 0xea, 0xea, 0xea,
|
||||||
0x60, 0x99, 0x81, 0xc0, 0x68, 0xbd, 0x38, 0x06, // C450
|
0x60, 0x99, 0x81, 0xc0, 0x68, 0xbd, 0x38, 0x06, // C450
|
||||||
0xaa, 0x68, 0xa8, 0x68, 0xbd, 0x00, 0x02, 0x60,
|
0xaa, 0x68, 0xa8, 0x68, 0xbd, 0x00, 0x02, 0x60,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // C460
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // C460
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xc9, 0x10, 0xb0,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xc9, 0x10, 0xb0,
|
||||||
@ -426,13 +458,25 @@ void Mouse::maintainMouse(int64_t cycleCount)
|
|||||||
static int64_t nextInterruptTime = cycleCount + 17050;
|
static int64_t nextInterruptTime = cycleCount + 17050;
|
||||||
|
|
||||||
if ( (status & ST_MOUSEENABLE) &&
|
if ( (status & ST_MOUSEENABLE) &&
|
||||||
(status & ST_INTVBL) ) {
|
(status & ST_INTVBL) &&
|
||||||
if (cycleCount >= nextInterruptTime) {
|
(cycleCount >= nextInterruptTime) ) {
|
||||||
|
g_cpu->irq();
|
||||||
|
|
||||||
|
interruptsTriggered |= ST_INTVBL;
|
||||||
|
|
||||||
|
nextInterruptTime += 17050;
|
||||||
|
} else {
|
||||||
|
uint16_t xpos, ypos;
|
||||||
|
g_mouse->getPosition(&xpos, &ypos);
|
||||||
|
|
||||||
|
if ( (status & ST_MOUSEENABLE) &&
|
||||||
|
(status & ST_INTMOUSE) &&
|
||||||
|
(xpos != lastX || ypos != lastY) ) {
|
||||||
g_cpu->irq();
|
g_cpu->irq();
|
||||||
|
|
||||||
interruptsTriggered |= ST_INTVBL;
|
interruptsTriggered |= ST_INTMOUSE;
|
||||||
|
lastX = xpos; lastY = ypos;
|
||||||
nextInterruptTime += 17050;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* FIXME: still need button */
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,10 @@ class Mouse : public Slot {
|
|||||||
private:
|
private:
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
uint8_t interruptsTriggered;
|
uint8_t interruptsTriggered;
|
||||||
|
|
||||||
|
uint16_t lastX, lastY;
|
||||||
|
bool lastButton;
|
||||||
|
bool curButton;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -5,6 +5,7 @@ Cpu *g_cpu = NULL;
|
|||||||
VM *g_vm = NULL;
|
VM *g_vm = NULL;
|
||||||
PhysicalDisplay *g_display = NULL;
|
PhysicalDisplay *g_display = NULL;
|
||||||
PhysicalKeyboard *g_keyboard = NULL;
|
PhysicalKeyboard *g_keyboard = NULL;
|
||||||
|
PhysicalMouse *g_mouse = NULL;
|
||||||
PhysicalSpeaker *g_speaker = NULL;
|
PhysicalSpeaker *g_speaker = NULL;
|
||||||
PhysicalPaddles *g_paddles = NULL;
|
PhysicalPaddles *g_paddles = NULL;
|
||||||
PhysicalPrinter *g_printer = NULL;
|
PhysicalPrinter *g_printer = NULL;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
#include "physicaldisplay.h"
|
#include "physicaldisplay.h"
|
||||||
#include "physicalkeyboard.h"
|
#include "physicalkeyboard.h"
|
||||||
|
#include "physicalmouse.h"
|
||||||
#include "physicalspeaker.h"
|
#include "physicalspeaker.h"
|
||||||
#include "physicalpaddles.h"
|
#include "physicalpaddles.h"
|
||||||
#include "physicalprinter.h"
|
#include "physicalprinter.h"
|
||||||
@ -41,6 +42,7 @@ extern Cpu *g_cpu;
|
|||||||
extern VM *g_vm;
|
extern VM *g_vm;
|
||||||
extern PhysicalDisplay *g_display;
|
extern PhysicalDisplay *g_display;
|
||||||
extern PhysicalKeyboard *g_keyboard;
|
extern PhysicalKeyboard *g_keyboard;
|
||||||
|
extern PhysicalMouse *g_mouse;
|
||||||
extern PhysicalSpeaker *g_speaker;
|
extern PhysicalSpeaker *g_speaker;
|
||||||
extern PhysicalPaddles *g_paddles;
|
extern PhysicalPaddles *g_paddles;
|
||||||
extern PhysicalPrinter *g_printer;
|
extern PhysicalPrinter *g_printer;
|
||||||
|
@ -51,6 +51,9 @@ Debugger::Debugger()
|
|||||||
server.sin_addr.s_addr = INADDR_ANY;
|
server.sin_addr.s_addr = INADDR_ANY;
|
||||||
server.sin_port = htons(12345);
|
server.sin_port = htons(12345);
|
||||||
|
|
||||||
|
steppingOut = false;
|
||||||
|
singleStep = false;
|
||||||
|
|
||||||
if (bind(sd, (struct sockaddr *) &server, sizeof(server)) < 0) {
|
if (bind(sd, (struct sockaddr *) &server, sizeof(server)) < 0) {
|
||||||
perror("error binding to debug socket");
|
perror("error binding to debug socket");
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -71,10 +74,14 @@ Debugger::~Debugger()
|
|||||||
bool getAddress(const char *buf, unsigned int *addrOut)
|
bool getAddress(const char *buf, unsigned int *addrOut)
|
||||||
{
|
{
|
||||||
unsigned int val;
|
unsigned int val;
|
||||||
if (sscanf(buf, " 0x%X", &val) == 1) {
|
if (sscanf(buf, " 0x%X", &val) == 1 ||
|
||||||
|
sscanf(buf, " 0x%x", &val) == 1
|
||||||
|
) {
|
||||||
*addrOut = val;
|
*addrOut = val;
|
||||||
return true;
|
return true;
|
||||||
} else if (sscanf(buf, " $%X", &val) == 1) {
|
} else if (sscanf(buf, " $%X", &val) == 1 ||
|
||||||
|
sscanf(buf, " $%x", &val) == 1
|
||||||
|
) {
|
||||||
*addrOut = val;
|
*addrOut = val;
|
||||||
return true;
|
return true;
|
||||||
} else if (sscanf(buf, " %d", &val) == 1) {
|
} else if (sscanf(buf, " %d", &val) == 1) {
|
||||||
@ -91,11 +98,10 @@ bool getAddress(const char *buf, unsigned int *addrOut)
|
|||||||
#define HEXCHAR(x) ((x>='0'&&x<='9')?x-'0':(x>='a'&&x<='f')?x-'a'+10:(x>='A'&&x<='F')?x-'A'+10:(x=='i' || x=='I')?1:(x=='o' || x=='O')?0:0)
|
#define HEXCHAR(x) ((x>='0'&&x<='9')?x-'0':(x>='a'&&x<='f')?x-'a'+10:(x>='A'&&x<='F')?x-'A'+10:(x=='i' || x=='I')?1:(x=='o' || x=='O')?0:0)
|
||||||
#define FROMHEXP(p) ((HEXCHAR(*p) << 4) | HEXCHAR(*(p+1)))
|
#define FROMHEXP(p) ((HEXCHAR(*p) << 4) | HEXCHAR(*(p+1)))
|
||||||
|
|
||||||
bool steppingOut = false;
|
|
||||||
|
|
||||||
void Debugger::step()
|
void Debugger::step()
|
||||||
{
|
{
|
||||||
static char buf[256];
|
static char buf[256];
|
||||||
|
uint8_t cmdbuf[50];
|
||||||
|
|
||||||
// FIXME: add more than just RTS(0x60) here
|
// FIXME: add more than just RTS(0x60) here
|
||||||
if (steppingOut &&
|
if (steppingOut &&
|
||||||
@ -124,39 +130,55 @@ void Debugger::step()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t cmdbuf[50];
|
if (!singleStep && breakpoint && g_cpu->pc != breakpoint) {
|
||||||
|
|
||||||
uint16_t loc=g_cpu->pc;
|
|
||||||
for (int i=0; i<50/3; i++) {
|
|
||||||
for (int idx=0; idx<sizeof(cmdbuf); idx++) {
|
|
||||||
cmdbuf[idx] = g_vm->getMMU()->read(loc+idx);
|
|
||||||
}
|
|
||||||
loc += dis.instructionToMnemonic(loc, cmdbuf, buf, sizeof(buf));
|
|
||||||
write(cd, buf, strlen(buf));
|
|
||||||
buf[0] = 13;
|
|
||||||
buf[1] = 10;
|
|
||||||
write(cd, buf, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (breakpoint && g_cpu->pc != breakpoint) {
|
|
||||||
// Running until we reach the breakpoint
|
// Running until we reach the breakpoint
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
singleStep = false; // we have taken a single step, so reset flag
|
||||||
|
|
||||||
uint8_t b; // byte value used in parsing
|
uint8_t b; // byte value used in parsing
|
||||||
unsigned int val; // common value buffer used in parsing
|
unsigned int val; // common value buffer used in parsing
|
||||||
|
|
||||||
GETCH;
|
// debugging what's at FF58 right now
|
||||||
snprintf(buf, sizeof(buf), "Got char %d\012\015", b);
|
uint8_t tmp = g_vm->getMMU()->read(0xff58);
|
||||||
|
sprintf(buf, " 0xFF58: 0x%.2X\r\n", tmp);
|
||||||
write(cd, buf, strlen(buf));
|
write(cd, buf, strlen(buf));
|
||||||
|
|
||||||
|
doover:
|
||||||
|
do {
|
||||||
|
GETCH;
|
||||||
|
} while (b != 'c' && // continue (with breakpoint set)
|
||||||
|
b != 'q' && // quit
|
||||||
|
b != 's' && // single step
|
||||||
|
b != 'S' && // step out
|
||||||
|
b != 'b' && // set breakpoint
|
||||||
|
b != 'd' && // show disassembly
|
||||||
|
b != 'L' && // load memory (lines)
|
||||||
|
b != '*' // show memory (byte)
|
||||||
|
);
|
||||||
|
|
||||||
switch (b) {
|
switch (b) {
|
||||||
case 'c': // Continue - close connection and let execution flow
|
case 'c': // continue (if there is a breakpoint set)
|
||||||
|
if (breakpoint) {
|
||||||
|
snprintf(buf, sizeof(buf), "Continuing until breakpoint 0x%X\012\015", breakpoint);
|
||||||
|
write(cd, buf, strlen(buf));
|
||||||
|
} else {
|
||||||
|
snprintf(buf, sizeof(buf), "No breakpoint to continue until\012\015");
|
||||||
|
write(cd, buf, strlen(buf));
|
||||||
|
goto doover;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'q': // Close debugging socket and quit
|
||||||
printf("Closing debugging socket\n");
|
printf("Closing debugging socket\n");
|
||||||
|
breakpoint = 0;
|
||||||
close(cd); cd=-1;
|
close(cd); cd=-1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
singleStep = true; // for when breakpoint is set: just step once
|
||||||
|
break;
|
||||||
|
|
||||||
case 'S':
|
case 'S':
|
||||||
steppingOut = true;
|
steppingOut = true;
|
||||||
break;
|
break;
|
||||||
@ -176,6 +198,23 @@ void Debugger::step()
|
|||||||
write(cd, buf, strlen(buf));
|
write(cd, buf, strlen(buf));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'd': // show disassembly @ PC
|
||||||
|
{
|
||||||
|
uint16_t loc=g_cpu->pc;
|
||||||
|
for (int i=0; i<50/3; i++) {
|
||||||
|
for (int idx=0; idx<sizeof(cmdbuf); idx++) {
|
||||||
|
cmdbuf[idx] = g_vm->getMMU()->read(loc+idx);
|
||||||
|
}
|
||||||
|
loc += dis.instructionToMnemonic(loc, cmdbuf, buf, sizeof(buf));
|
||||||
|
write(cd, buf, strlen(buf));
|
||||||
|
buf[0] = 13;
|
||||||
|
buf[1] = 10;
|
||||||
|
write(cd, buf, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
goto doover;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'L': // Load data to memory. Use: "L 0x<address>\n" followed by lines of packed hex; ends with a blank line
|
case 'L': // Load data to memory. Use: "L 0x<address>\n" followed by lines of packed hex; ends with a blank line
|
||||||
{
|
{
|
||||||
printf("Loading data\n");
|
printf("Loading data\n");
|
||||||
@ -198,6 +237,7 @@ void Debugger::step()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
goto doover;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '*': // read 1 byte of memory. Use '* 0x<address>'
|
case '*': // read 1 byte of memory. Use '* 0x<address>'
|
||||||
@ -214,6 +254,7 @@ void Debugger::step()
|
|||||||
write(cd, buf, strlen(buf));
|
write(cd, buf, strlen(buf));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
goto doover;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'G': // Goto (set PC)
|
case 'G': // Goto (set PC)
|
||||||
|
@ -19,6 +19,8 @@ class Debugger {
|
|||||||
pthread_t listenThreadID;
|
pthread_t listenThreadID;
|
||||||
|
|
||||||
uint32_t breakpoint;
|
uint32_t breakpoint;
|
||||||
|
bool steppingOut;
|
||||||
|
bool singleStep;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,13 +2,27 @@
|
|||||||
#define __PHYSICALMOUSE_H
|
#define __PHYSICALMOUSE_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
XCLAMP = 0,
|
||||||
|
YCLAMP = 1
|
||||||
|
};
|
||||||
|
|
||||||
class PhysicalMouse {
|
class PhysicalMouse {
|
||||||
public:
|
public:
|
||||||
PhysicalMouse() {}
|
PhysicalMouse() { lowClamp[XCLAMP] = lowClamp[YCLAMP] = 0; highClamp[XCLAMP] = highClamp[YCLAMP] = 1023; }
|
||||||
virtual ~PhysicalMouse() {};
|
virtual ~PhysicalMouse() {};
|
||||||
|
|
||||||
virtual void maintainMouse() = 0;
|
virtual void maintainMouse() = 0;
|
||||||
|
|
||||||
|
virtual void setClamp(uint8_t direction, uint16_t low, uint16_t high) { lowClamp[direction] = low; highClamp[direction] = high; printf("clamp %d %d-%d\n", direction, low, high); }
|
||||||
|
virtual void setPosition(uint16_t x, uint16_t y) = 0;
|
||||||
|
virtual void getPosition(uint16_t *x, uint16_t *y) = 0;
|
||||||
|
virtual bool getButton() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint16_t lowClamp[2], highClamp[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "applevm.h"
|
#include "applevm.h"
|
||||||
#include "sdl-display.h"
|
#include "sdl-display.h"
|
||||||
#include "sdl-keyboard.h"
|
#include "sdl-keyboard.h"
|
||||||
|
#include "sdl-mouse.h"
|
||||||
#include "sdl-speaker.h"
|
#include "sdl-speaker.h"
|
||||||
#include "sdl-paddles.h"
|
#include "sdl-paddles.h"
|
||||||
#include "nix-filemanager.h"
|
#include "nix-filemanager.h"
|
||||||
@ -291,7 +292,7 @@ struct timespec runMaintenance(struct timespec now)
|
|||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
timespec_add_us(&startTime, 100000*cycleCount, &nextRuntime); // FIXME: what's a good time here? 1/10 sec?
|
timespec_add_us(&startTime, 16667*cycleCount, &nextRuntime); // FIXME: what's a good time here? 60 Hz?
|
||||||
|
|
||||||
// Check if it's time to run - and if not, return how long it will
|
// Check if it's time to run - and if not, return how long it will
|
||||||
// be until we need to run
|
// be until we need to run
|
||||||
@ -305,6 +306,7 @@ struct timespec runMaintenance(struct timespec now)
|
|||||||
if (!g_biosInterrupt) {
|
if (!g_biosInterrupt) {
|
||||||
// If the BIOS is running, then let it handle the keyboard directly
|
// If the BIOS is running, then let it handle the keyboard directly
|
||||||
g_keyboard->maintainKeyboard();
|
g_keyboard->maintainKeyboard();
|
||||||
|
g_mouse->maintainMouse();
|
||||||
}
|
}
|
||||||
|
|
||||||
doDebugging();
|
doDebugging();
|
||||||
@ -389,6 +391,7 @@ int main(int argc, char *argv[])
|
|||||||
g_vm = new AppleVM();
|
g_vm = new AppleVM();
|
||||||
|
|
||||||
g_keyboard = new SDLKeyboard(g_vm->getKeyboard());
|
g_keyboard = new SDLKeyboard(g_vm->getKeyboard());
|
||||||
|
g_mouse = new SDLMouse();
|
||||||
|
|
||||||
// Now that the VM exists and it has created an MMU, we tell the CPU how to access memory through the MMU.
|
// Now that the VM exists and it has created an MMU, we tell the CPU how to access memory through the MMU.
|
||||||
g_cpu->SetMMU(g_vm->getMMU());
|
g_cpu->SetMMU(g_vm->getMMU());
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "sdl-keyboard.h"
|
#include "sdl-keyboard.h"
|
||||||
|
|
||||||
#include "sdl-paddles.h"
|
#include "sdl-paddles.h"
|
||||||
|
#include "sdl-mouse.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
SDLKeyboard::SDLKeyboard(VMKeyboard *k) : PhysicalKeyboard(k)
|
SDLKeyboard::SDLKeyboard(VMKeyboard *k) : PhysicalKeyboard(k)
|
||||||
@ -149,12 +150,18 @@ void SDLKeyboard::maintainKeyboard()
|
|||||||
if (event.key.repeat == 0)
|
if (event.key.repeat == 0)
|
||||||
handleKeypress(&event.key);
|
handleKeypress(&event.key);
|
||||||
break;
|
break;
|
||||||
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
case SDL_MOUSEBUTTONUP:
|
||||||
|
((SDLMouse *)g_mouse)->mouseButtonEvent(event.type == SDL_MOUSEBUTTONDOWN);
|
||||||
|
break;
|
||||||
case SDL_MOUSEMOTION:
|
case SDL_MOUSEMOTION:
|
||||||
// We are handling the SDL input loop, so need to pass this off to the paddles. :/
|
// We are handling the SDL input loop, so need to pass this off to the paddles. :/
|
||||||
// FIXME: nasty rooting around in other objects and typecasting.
|
// FIXME: nasty rooting around in other objects and typecasting.
|
||||||
// FIXME: event.motion.state & SDL_BUTTON_LMASK, et al?
|
// FIXME: event.motion.state & SDL_BUTTON_LMASK, et al?
|
||||||
|
|
||||||
((SDLPaddles *)g_paddles)->gotMouseMovement(event.motion.x, event.motion.y);
|
((SDLPaddles *)g_paddles)->gotMouseMovement(event.motion.x, event.motion.y);
|
||||||
|
((SDLMouse *)g_mouse)->gotMouseEvent(event.motion.state, // button
|
||||||
|
event.motion.xrel, event.motion.yrel);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_QUIT:
|
case SDL_QUIT:
|
||||||
|
Loading…
Reference in New Issue
Block a user