mirror of
https://github.com/JorjBauer/aiie.git
synced 2024-11-22 15:31:41 +00:00
Merge branch 'mouse41'
This commit is contained in:
commit
5011dd5743
3
.gitignore
vendored
3
.gitignore
vendored
@ -13,4 +13,5 @@ apple/hd32-rom.h
|
||||
aiie-sdl
|
||||
mockingboard-d.rom
|
||||
*.d
|
||||
|
||||
*.dSYM
|
||||
suspend.vm
|
||||
|
12
Makefile
12
Makefile
@ -8,19 +8,19 @@ CXXFLAGS=-Wall -I/usr/include/SDL2 -I .. -I . -I apple -I nix -I sdl -I/usr/loca
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
ROMS=apple/applemmu-rom.h apple/diskii-rom.h apple/parallel-rom.h apple/hd32-rom.h
|
||||
|
||||
.PHONY: roms clean
|
||||
|
||||
@ -40,7 +40,7 @@ test: $(TSRC)
|
||||
./testharness -f tests/65c02-all.bin -s 0x200
|
||||
|
||||
roms: apple2e.rom disk.rom parallel.rom HDDRVR.BIN
|
||||
./util/genrom.pl apple2e.rom disk.rom parallel.rom HDDRVR.BIN
|
||||
./util/genrom.pl apple2e.rom disk.rom parallel.rom HDDRVR.BIN
|
||||
|
||||
apple/applemmu-rom.h: roms
|
||||
|
||||
|
@ -216,10 +216,13 @@ inline void AppleDisplay::Draw14DoubleHiresPixelsAt(uint16_t addr)
|
||||
drawApplePixel(bitTrain & 0x0F, col+xoff+1,row);
|
||||
} else {
|
||||
// Perfect color, B&W, monochrome. Draw an exact version of the pixels, and let
|
||||
// the physical display figure out if they need to be reduced to B&W or not.
|
||||
// the physical display figure out if they need to be reduced to B&W or not
|
||||
// (for the most part - the m_blackAndWhite piece here allows full-res displays
|
||||
// to give the crispest resolution.)
|
||||
|
||||
uint8_t color = bitTrain & 0x0F;
|
||||
|
||||
if (g_displayType == m_blackAndWhite) { color = c_white; }
|
||||
|
||||
g_display->cachePixel((col*2)+(xoff*2), row,
|
||||
((bitTrain & 0x01) ? color : c_black));
|
||||
|
||||
|
@ -55,16 +55,24 @@ page 0-1 4 pages (1k) [altzp]
|
||||
0xC1-0xCF 15 * 2 pages = 30 pages (7.5k) [intcxrom, slotLatch]
|
||||
0xD0 - 0xDF 16 * 5 pages = 80 pages (20k) [altzp, bank2, {r,w}bsr]
|
||||
0xE0 - 0xFF 32 * 3 pages = 96 pages (24k) [altzp, {r,w}bsr]
|
||||
... plus 8 additional pages for the mouse ROM
|
||||
|
||||
= 147.75k (591 pages) stored off-chip
|
||||
= 147.75k (591 pages) stored off-chip (+ 8 more)
|
||||
|
||||
Current read page table [512 bytes] in real ram
|
||||
Current write page table [512 bytes] in real ram
|
||||
|
||||
*/
|
||||
|
||||
// This has a split memory model so more often addressed pages can be
|
||||
// in internal memory, and an external memory can hold others.
|
||||
// All the pages. Because we don't have enough RAM for both the
|
||||
// display's DMA and the Apple's 148k (128k + ROM space), we're using
|
||||
// an external SRAM for some of this. Anything that's accessed very
|
||||
// often should be in the *low* pages, b/c those are in internal
|
||||
// Teensy RAM. When we run out of preallocated RAM (cf. vmram.h), we
|
||||
// fall over to an external 256kB SRAM (which is much slower).
|
||||
//
|
||||
// Zero page (and its alts) are the most used pages (the stack is in
|
||||
// page 1).
|
||||
//
|
||||
// We want the video display pages in real RAM as much as possible,
|
||||
// since blits wind up touching so much of it. If we can keep that in
|
||||
@ -81,19 +89,19 @@ enum {
|
||||
MP_ZP = 0, // page 0/1 * 2 page variants = 4; 0..3
|
||||
MP_4 = 4, // 0x04 - 0x07 (text display pages) * 2 variants = 8; 4..11
|
||||
MP_20 = 12, // 0x20 - 0x5F * 2 variants = 128; 12..139
|
||||
// Pages that can go to external RAM if needed:
|
||||
// Pages that can go to external SRAM:
|
||||
MP_2 = 140, // 0x02 - 0x03 * 2 variants = 4; 140..143
|
||||
MP_8 = 144, // 0x08 - 0x1F * 2 = 48; 144..191
|
||||
MP_60 = 192, // 0x60 - 0xBF * 2 = 192; 192..383
|
||||
|
||||
MP_C1 = 384, // start of 0xC1-0xCF * 2 page variants = 30; 384-413
|
||||
MP_D0 = 414, // start of 0xD0-0xDF * 5 page variants = 80; 414-493
|
||||
MP_E0 = 493, // start of 0xE0-0xFF * 3 page variants = 96; 494-589
|
||||
MP_C0 = 590
|
||||
// = 591 pages in all (147.75k)
|
||||
MP_C1 = 384, // start of 0xC1-0xC7 * 2 page variants = 14; 384-397
|
||||
MP_C8 = 398, // 0xc8 - 0xcf, 3 page variants = 24; 398 - 421
|
||||
MP_D0 = 422, // start of 0xD0-0xDF * 5 page variants = 80; 422 - 501
|
||||
MP_E0 = 502, // start of 0xE0-0xFF * 3 page variants = 96; 502 - 597
|
||||
MP_C0 = 598
|
||||
// = 599 pages in all (149.75k)
|
||||
};
|
||||
|
||||
|
||||
static uint16_t _pageNumberForRam(uint8_t highByte, uint8_t variant)
|
||||
{
|
||||
if (highByte <= 1) {
|
||||
@ -118,11 +126,14 @@ static uint16_t _pageNumberForRam(uint8_t highByte, uint8_t variant)
|
||||
if (highByte == 0xc0) {
|
||||
return MP_C0;
|
||||
}
|
||||
if (highByte <= 0xCF) {
|
||||
// 0xC1-0xCF 15 * 2 pages = 30 pages (7.5k)
|
||||
if (highByte <= 0xC7) {
|
||||
// 0xC1-0xC7
|
||||
return ((highByte - 0xC1) * 2 + variant + MP_C1);
|
||||
}
|
||||
|
||||
if (highByte <= 0xCF) {
|
||||
// bank-switched ROM. 0 = built-in; 1 = 80-column (slot 3); 2 = mouse (slot 4)
|
||||
return ((highByte - 0xC8) * 3 + variant + MP_C8);
|
||||
}
|
||||
if (highByte <= 0xDF) {
|
||||
// 0xD0 - 0xDF 16 * 5 pages = 80 pages (20k)
|
||||
return ((highByte - 0xD0) * 5 + variant + MP_D0);
|
||||
@ -220,6 +231,8 @@ bool AppleMMU::Deserialize(int8_t fd)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AppleMMU::Reset()
|
||||
{
|
||||
resetRAM();
|
||||
@ -914,6 +927,9 @@ void AppleMMU::resetRAM()
|
||||
|
||||
// Load system ROM
|
||||
for (uint16_t i=0x80; i<=0xFF; i++) {
|
||||
uint16_t page0 = _pageNumberForRam(i, 0);
|
||||
uint16_t page1 = _pageNumberForRam(i, 1);
|
||||
|
||||
for (uint16_t k=0; k<0x100; k++) {
|
||||
uint16_t idx = ((i-0x80) << 8) | k;
|
||||
#ifdef TEENSYDUINO
|
||||
@ -921,36 +937,30 @@ void AppleMMU::resetRAM()
|
||||
#else
|
||||
uint8_t v = romData[idx];
|
||||
#endif
|
||||
for (int j=0; j<5; j++) {
|
||||
// For the ROM section from 0xc100 .. 0xcfff, we load in to
|
||||
// an alternate page space (INTCXROM).
|
||||
|
||||
uint16_t page0 = _pageNumberForRam(i, 0);
|
||||
// The space from 0xc1 through 0xcf is ROM image territory. We
|
||||
// load the C3 ROM in to page 0, but not page 1; and then we
|
||||
// load c800.CFFF to both main ROM (page 0) and the C3 aux ROM
|
||||
// (page 1) to convince the VM that we've got 128k of RAM and an
|
||||
// 80-column card.
|
||||
|
||||
if (i >= 0xc1 && i <= 0xcf) {
|
||||
// If we want to convince the VM we've got 128k of RAM, we
|
||||
// need to load C3 ROM in page 0 (but not 1, meaning there's
|
||||
// a board installed); and C800.CFFF in both page [0] and [1]
|
||||
// (meaning there's an extended 80-column ROM available,
|
||||
// that is also physically in the slot).
|
||||
// Everything else goes in page [1].
|
||||
|
||||
uint16_t page1 = _pageNumberForRam(i, 1);
|
||||
|
||||
if (i == 0xc3) {
|
||||
g_ram.writeByte((page0 << 8) | (k & 0xFF), v);
|
||||
}
|
||||
else if (i >= 0xc8) {
|
||||
g_ram.writeByte((page0 << 8) | (k & 0xFF), v);
|
||||
g_ram.writeByte((page1 << 8) | (k & 0xFF), v);
|
||||
}
|
||||
else {
|
||||
g_ram.writeByte((page1 << 8) | (k & 0xFF), v);
|
||||
}
|
||||
} else {
|
||||
// Everything else goes in page 0.
|
||||
if (i >= 0xc1 && i <= 0xcf) {
|
||||
if (i == 0xc3) {
|
||||
// C300..C3FF => built-in ROM
|
||||
g_ram.writeByte((page0 << 8) | (k & 0xFF), v);
|
||||
}
|
||||
else if (i >= 0xc8) {
|
||||
// C800..CFFF => built-in ROM and slot 3 extended ROM
|
||||
g_ram.writeByte((page0 << 8) | (k & 0xFF), v);
|
||||
g_ram.writeByte((page1 << 8) | (k & 0xFF), v);
|
||||
}
|
||||
else {
|
||||
// C000..C2FF and C400..c7FF are main ROM
|
||||
g_ram.writeByte((page1 << 8) | (k & 0xFF), v);
|
||||
}
|
||||
} else {
|
||||
// Everything else goes in page 0.
|
||||
g_ram.writeByte((page0 << 8) | (k & 0xFF), v);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -959,12 +969,33 @@ void AppleMMU::resetRAM()
|
||||
for (uint8_t slotnum = 1; slotnum <= 7; slotnum++) {
|
||||
uint16_t page0 = _pageNumberForRam(0xC0 + slotnum, 0);
|
||||
if (slots[slotnum]) {
|
||||
// Load the primary ROM for this peripheral (0xCsXX..0xCsFF)
|
||||
uint8_t tmpBuf[256];
|
||||
memset(tmpBuf, 0, sizeof(tmpBuf));
|
||||
slots[slotnum]->loadROM(tmpBuf);
|
||||
for (int i=0; i<256; i++) {
|
||||
g_ram.writeByte( (page0 << 8) + i, tmpBuf[i] );
|
||||
}
|
||||
|
||||
// See if there's an extended 2k ROM for this peripheral (0xC800..0xCFFF)
|
||||
if (slots[slotnum]->hasExtendedRom()) {
|
||||
for (int j=0; j<8; j++) {
|
||||
// Load each of the 256 byte chunks separately to its own VMRam page
|
||||
uint16_t slotPage = 0;
|
||||
if (slotnum == 4) {
|
||||
slotPage = _pageNumberForRam(0xC8 + j, 2);
|
||||
} else {
|
||||
#ifndef TEENSYDUINO
|
||||
fprintf(stderr, "ERROR: unsupported extended ROM peripheral in slot %d\n", slotnum);
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
if (slotPage) {
|
||||
uint8_t *p = g_ram.memPtr(slotPage << 8);
|
||||
slots[slotnum]->loadExtendedRom(p, j * 256);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1063,12 +1094,17 @@ void AppleMMU::updateMemoryPages()
|
||||
// If slotLatch is set (!= -1), then we are mapping 2k of ROM
|
||||
// for a given peripheral to C800..CFFF.
|
||||
if (slotLatch != -1) {
|
||||
// FIXME: the only peripheral we support this with right now is
|
||||
// the 80-column card.
|
||||
// FIXME: this is a hacky mess. Slot 3 (the 80-col card) is
|
||||
// supported, as page "1"; and Slot 4 (the mouse card) is
|
||||
// supported as page "2".
|
||||
if (slotLatch == 3) {
|
||||
for (int i=0xc8; i <= 0xcf; i++) {
|
||||
readPages[i] = _pageNumberForRam(i, 1);
|
||||
}
|
||||
} else if (slotLatch == 4) {
|
||||
for (int i=0xc8; i <= 0xcf; i++) {
|
||||
readPages[i] = _pageNumberForRam(i, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,9 @@ AppleVM::AppleVM()
|
||||
|
||||
hd32 = new HD32((AppleMMU *)mmu);
|
||||
((AppleMMU *)mmu)->setSlot(7, hd32);
|
||||
|
||||
mouse = new Mouse();
|
||||
((AppleMMU *)mmu)->setSlot(4, mouse);
|
||||
}
|
||||
|
||||
AppleVM::~AppleVM()
|
||||
@ -133,6 +136,7 @@ void AppleVM::cpuMaintenance(int64_t cycles)
|
||||
|
||||
keyboard->maintainKeyboard(cycles);
|
||||
disk6->maintenance(cycles);
|
||||
mouse->maintainMouse(cycles);
|
||||
}
|
||||
|
||||
void AppleVM::Reset()
|
||||
@ -189,3 +193,8 @@ VMKeyboard * AppleVM::getKeyboard()
|
||||
{
|
||||
return keyboard;
|
||||
}
|
||||
|
||||
bool AppleVM::isMouseEnabled()
|
||||
{
|
||||
return mouse->isEnabled();
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "hd32.h"
|
||||
#include "vmkeyboard.h"
|
||||
#include "parallelcard.h"
|
||||
#include "mouse.h"
|
||||
|
||||
#include "vm.h"
|
||||
class AppleVM : public VM {
|
||||
@ -34,11 +35,14 @@ class AppleVM : public VM {
|
||||
|
||||
virtual VMKeyboard *getKeyboard();
|
||||
|
||||
bool isMouseEnabled();
|
||||
|
||||
DiskII *disk6;
|
||||
HD32 *hd32;
|
||||
protected:
|
||||
VMKeyboard *keyboard;
|
||||
ParallelCard *parallel;
|
||||
Mouse *mouse;
|
||||
};
|
||||
|
||||
|
||||
|
361
apple/mouse.cpp
Normal file
361
apple/mouse.cpp
Normal file
@ -0,0 +1,361 @@
|
||||
#include "mouse.h"
|
||||
#include <string.h>
|
||||
#include "globals.h"
|
||||
|
||||
enum {
|
||||
SW_W_INIT = 0x00,
|
||||
SW_R_HOMEMOUSE = 0x08,
|
||||
SW_R_POSMOUSE = 0x09,
|
||||
SW_R_CLEARMOUSE = 0x0A,
|
||||
SW_R_READMOUSE = 0x0B,
|
||||
SW_R_INITMOUSE = 0x0C,
|
||||
SW_W_CLAMPMOUSE = 0x0D,
|
||||
SW_R_SERVEMOUSE = 0x0E,
|
||||
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 {
|
||||
ST_MOUSEENABLE = 1,
|
||||
ST_INTMOUSE = 2,
|
||||
ST_INTBUTTON = 4,
|
||||
ST_INTVBL = 8
|
||||
};
|
||||
|
||||
Mouse::Mouse()
|
||||
{
|
||||
status = 0;
|
||||
interruptsTriggered = 0;
|
||||
lastX = lastY = 0;
|
||||
lastXForInt = lastYForInt = 0;
|
||||
lastButton = false;
|
||||
lastButtonForInt = false;
|
||||
}
|
||||
|
||||
Mouse::~Mouse()
|
||||
{
|
||||
}
|
||||
|
||||
bool Mouse::Serialize(int8_t fd)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Mouse::Deserialize(int8_t fd)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void Mouse::Reset()
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t Mouse::readSwitches(uint8_t s)
|
||||
{
|
||||
switch (s) {
|
||||
default:
|
||||
printf("mouse: unknown switch read 0x%X\n", s);
|
||||
};
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void Mouse::writeSwitches(uint8_t s, uint8_t v)
|
||||
{
|
||||
switch (s) {
|
||||
/* Many of these were designed to be reads, because they don't have to
|
||||
* modify any state inside the VM directly -- but it's important (per docs)
|
||||
* that we return A, X, and Y as they were when we were called. So these
|
||||
* are all now writes, which don't modify A/X/Y. */
|
||||
case SW_R_HOMEMOUSE:
|
||||
g_mouse->setPosition( (g_vm->getMMU()->read(0x578) << 8) | g_vm->getMMU()->read(0x478),
|
||||
(g_vm->getMMU()->read(0x5F8) << 8) | g_vm->getMMU()->read(0x4F8)
|
||||
);
|
||||
break;
|
||||
case SW_R_POSMOUSE:
|
||||
g_mouse->setPosition( (g_vm->getMMU()->read(0x578+4) << 8) | g_vm->getMMU()->read(0x478+4),
|
||||
(g_vm->getMMU()->read(0x5F8+4) << 8) | g_vm->getMMU()->read(0x4F8+4)
|
||||
);
|
||||
break;
|
||||
case SW_R_CLEARMOUSE:
|
||||
g_vm->getMMU()->write(0x578+4, 0);
|
||||
g_vm->getMMU()->write(0x478+4, 0);
|
||||
g_vm->getMMU()->write(0x5F8+4, 0);
|
||||
g_vm->getMMU()->write(0x4F8+4, 0);
|
||||
g_mouse->setPosition(0,0);
|
||||
break;
|
||||
case SW_R_READMOUSE:
|
||||
{
|
||||
uint16_t xpos, ypos;
|
||||
g_mouse->getPosition(&xpos, &ypos);
|
||||
if (lastX != xpos || lastY != ypos) {
|
||||
interruptsTriggered |= 0x20; // "x or y changed since last reading"
|
||||
lastX = xpos; lastY = ypos;
|
||||
}
|
||||
curButton = g_mouse->getButton();
|
||||
uint8_t newStatus = g_vm->getMMU()->read(0x778+4) & ~0xC0;
|
||||
if (curButton) { newStatus |= 0x80; };
|
||||
if (lastButton) { newStatus |= 0x40; };
|
||||
|
||||
g_vm->getMMU()->write(0x578+4, (xpos >> 8) & 0xFF); // high X
|
||||
g_vm->getMMU()->write(0x478+4, xpos & 0xFF); // low X
|
||||
g_vm->getMMU()->write(0x5F8+4, (ypos >> 8) & 0xFF); // high Y
|
||||
g_vm->getMMU()->write(0x4F8+4, ypos); // low Y
|
||||
}
|
||||
break;
|
||||
case SW_R_INITMOUSE:
|
||||
// Set clamp to (0,0) - (1023,1023)
|
||||
g_vm->getMMU()->write(0x578, 0); // high of lowclamp
|
||||
g_vm->getMMU()->write(0x478, 0); // low of lowclamp
|
||||
g_vm->getMMU()->write(0x5F8, 0x03); // high of highclamp
|
||||
g_vm->getMMU()->write(0x4F8, 0xFF); // low of highclamp
|
||||
g_mouse->setClamp(XCLAMP, 0, 1023);
|
||||
g_mouse->setClamp(YCLAMP, 0, 1023);
|
||||
break;
|
||||
case SW_R_SERVEMOUSE:
|
||||
if (lastButton) interruptsTriggered |= 0x40;
|
||||
if (curButton != lastButton) {
|
||||
interruptsTriggered |= 0x80;
|
||||
lastButton = curButton;
|
||||
}
|
||||
g_vm->getMMU()->write(0x778+4, interruptsTriggered);
|
||||
g_vm->getMMU()->write(0x6B8+4, interruptsTriggered); // hack to appease ROM
|
||||
interruptsTriggered = 0;
|
||||
break;
|
||||
case SW_W_INIT:
|
||||
v &= 0x03; // just the low 3 bits apparently?
|
||||
// printf("Simple init: value is 0x%X\n", v);
|
||||
status = v;
|
||||
g_vm->getMMU()->write(0x7f8 + 4, v);
|
||||
break;
|
||||
case SW_W_CLAMPMOUSE:
|
||||
{
|
||||
uint16_t lowval = (g_vm->getMMU()->read(0x578) << 8) | (g_vm->getMMU()->read(0x478));
|
||||
uint16_t highval = (g_vm->getMMU()->read(0x5F8) << 8) | (g_vm->getMMU()->read(0x4F8));
|
||||
if (v) {
|
||||
g_mouse->setClamp(YCLAMP, lowval, highval);
|
||||
} else {
|
||||
// X is clamping
|
||||
g_mouse->setClamp(XCLAMP, lowval, highval);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SW_W_SETMOUSE:
|
||||
status = v;
|
||||
g_vm->getMMU()->write(0x7f8 + 4, v);
|
||||
break;
|
||||
default:
|
||||
printf("mouse: unknown switch write 0x%X = 0x%2X\n", s, v);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Mouse::loadROM(uint8_t *toWhere)
|
||||
{
|
||||
/* This is a custom-built ROM which hands off control to the C++ code via
|
||||
* soft switch writes. It's hard-coded to work with the mouse in Slot 4.
|
||||
*
|
||||
* ; $c400 is the entry point for PR#4
|
||||
* $C400 2C 58 FF BIT $FF58
|
||||
* $C403 70 1B BVS IOHandler
|
||||
* ; $c405 is the entry point for IN#4 when we set KSW
|
||||
* $C405 38 SEC
|
||||
* $C406 90 18 BCC IOHandler
|
||||
* $C408 B8 CLV
|
||||
* $C409 50 15 BVC IOHandler ; always branch
|
||||
* $C40B 01 20 8D 8D 8D ; data (ID bytes & such)
|
||||
* $C410 8D 00 60 68 76 7B 80 85 ; data (lookup table of entrypoints)
|
||||
* $C418 8F 94 8D 8D 8D 8D 8D 8D ; data (lookup table of entrypoints)
|
||||
* ; IOHandler ORG $c420
|
||||
* $C420 48 PHA ; save registers on stack
|
||||
* $C421 98 TYA
|
||||
* $C422 48 PHA
|
||||
* $C423 8A TXA
|
||||
* $C424 48 PHA
|
||||
* $C425 08 PHP
|
||||
* $C426 78 SEI ; disable interrupts
|
||||
* $C427 20 58 FF JSR $FF58 ; JSR to this well-known location that has
|
||||
* $C42A BA TSX ; an RTS (normally). Then when we get
|
||||
* $C42B BD 00 01 LDA $100,X ; back, pull our address off the stack
|
||||
* $C42E AA TAX ; and save the high byte in X
|
||||
* $C42F 0A ASL
|
||||
* $C430 0A ASL
|
||||
* $C431 0A ASL
|
||||
* $C432 0A ASL
|
||||
* $C433 A8 TAY ; and (high byte << 4) in Y
|
||||
* $C434 28 PLP ; restore interrupt state
|
||||
* $C435 50 0F BVC $C446
|
||||
* $C437 A5 38 LDA $0
|
||||
* $C439 D0 0D BNE $C448
|
||||
* $C43B 8A TXA
|
||||
* $C43C 45 39 EOR $0
|
||||
* $C43E D0 08 BNE $C448
|
||||
* $C440 A9 05 LDA #$0
|
||||
* $C442 85 38 STA $0
|
||||
* $C444 D0 0B BNE SendInputToDOS
|
||||
* $C446 B0 09 BCS SendInputToDOS
|
||||
* $C448 68 PLA ; restore registers
|
||||
* $C449 AA TAX
|
||||
* $C44A 68 PLA
|
||||
* $C44B EA NOP
|
||||
* $C44C 68 PLA
|
||||
* $C44D EA NOP
|
||||
* $C44E EA NOP
|
||||
* $C44F EA NOP
|
||||
* $C450 60 RTS
|
||||
* ; SendInputToDOS ORG $c451
|
||||
* $C451 EA NOP
|
||||
* $C452 EA NOP
|
||||
* $C453 EA NOP
|
||||
* $C454 68 PLA
|
||||
* $C455 BD 38 06 LDA $638,X ; X is $C4, so this is $6F8+n - which is
|
||||
* $C458 AA TAX ; a reserved hole
|
||||
* $C459 68 PLA
|
||||
* $C45A A8 TAY
|
||||
* $C45B 68 PLA
|
||||
* $C45C BD 00 02 LDA $200,X ; keyboard buffer output
|
||||
* $C45F 60 RTS
|
||||
* ; SetMouse ORG $c460
|
||||
* $C460 C9 10 CMP #$0
|
||||
* $C462 B0 29 BCS ExitWithError
|
||||
* $C464 8D CF C0 STA $C0CF ; soft switch 0x0F invokes SetMouse
|
||||
* $C467 60 RTS
|
||||
* ; ServeMouse ORG $c468
|
||||
* $C468 48 PHA
|
||||
* $C469 18 CLC ; use CLC/BCC to force relative jump
|
||||
* $C46A 90 2D BCC ServeMouseWorker
|
||||
* ; ServeMouseExit ORG $c46c
|
||||
* $C46C BD B8 06 LDA $6B8,X ; check what interrupts we say we serviced
|
||||
* $C46F 29 0E AND #$0
|
||||
* $C471 D0 01 BNE $C474 ; if we serviced any, leave carry clear
|
||||
* $C473 38 SEC ; but set carry if we serviced none
|
||||
* $C474 68 PLA
|
||||
* $C475 60 RTS
|
||||
* ; ReadMouse ORG $c476
|
||||
* $C476 8D CB C0 STA $C0CB ; soft switch 0x0B
|
||||
* $C479 18 CLC
|
||||
* $C47A 60 RTS
|
||||
* ; ClearMouse ORG $c47b
|
||||
* $C47B 8D CA C0 STA $C0CA ; soft switch 0x0A
|
||||
* $C47E 18 CLC
|
||||
* $C47F 60 RTS
|
||||
* ; PosMouse ORG $c480
|
||||
* $C480 8D C9 C0 STA $C0C9 ; soft switch 0x09
|
||||
* $C483 18 CLC
|
||||
* $C484 60 RTS
|
||||
* ; ClampMouse ORG $c485
|
||||
* $C485 C9 02 CMP #$0
|
||||
* $C487 B0 04 BCS $C48D
|
||||
* $C489 8D CD C0 STA $C0CD ; soft switch 0x0D
|
||||
* $C48C 60 RTS
|
||||
* ; ExitWithError ORG $c48d
|
||||
* $C48D 38 SEC ; the spec says carry is set on errors
|
||||
* $C48E 60 RTS
|
||||
* ; HomeMouse ORG $c48f
|
||||
* $C48F 8D C8 C0 STA $C0C8 ; soft switch 0x08
|
||||
* $C492 18 CLC
|
||||
* $C493 60 RTS
|
||||
* ; InitMouse ORG $c494
|
||||
* $C494 8D CC C0 STA $C0CC ; soft switch 0x0C
|
||||
* $C497 18 CLC
|
||||
* $C498 60 RTS
|
||||
* ; ServeMouseWorker ORG $c499
|
||||
* $C499 78 SEI ; disable interrupts
|
||||
* $C49A 8D CE C0 STA $C0CE ; soft switch 0x0E
|
||||
* $C49D A2 04 LDX #$0
|
||||
* $C49F 18 CLC
|
||||
* $C4A0 90 CA BCC ServeMouseExit ; force relative jump
|
||||
* ; $C4A2..C4FA is dead space (all $FF)
|
||||
* $C4FB D6 FF FF FF 01 ; data (ID bytes)
|
||||
*/
|
||||
|
||||
uint8_t rom[256] = { 0x2c, 0x58, 0xff, 0x70, 0x1B, 0x38, 0x90, 0x18, // C400
|
||||
0xb8, 0x50, 0x15, 0x01, 0x20, 0x8d, 0x8d, 0x8d,
|
||||
0x8d, 0x00, 0x60, 0x68, 0x76, 0x7b, 0x80, 0x85, // C410
|
||||
0x8f, 0x94, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x48, 0x98, 0x48, 0x8a, 0x48, 0x08, 0x78, 0x20, // C420
|
||||
0x58, 0xFF, 0xBA, 0xBD, 0x00, 0x01, 0xAA, 0x0A,
|
||||
0x0A, 0x0A, 0x0A, 0xA8, 0x28, 0x50, 0x0F, 0xA5, // C430
|
||||
0x38, 0xd0, 0x0d, 0x8a, 0x45, 0x39, 0xd0, 0x08,
|
||||
0xa9, 0x05, 0x85, 0x38, 0xd0, 0x0b, 0xb0, 0x09, // C440
|
||||
0x68, 0xaa, 0x68, 0xea, 0x68, 0xea, 0xea, 0xea,
|
||||
0x60, 0xea, 0xea, 0xea, 0x68, 0xbd, 0x38, 0x06, // C450
|
||||
0xaa, 0x68, 0xa8, 0x68, 0xbd, 0x00, 0x02, 0x60,
|
||||
0xc9, 0x10, 0xb0, 0x29, 0x8d, 0xcf, 0xc0, 0x60, // C460
|
||||
0x48, 0x18, 0x90, 0x2d, 0xbd, 0xb8, 0x06, 0x29,
|
||||
0x0e, 0xd0, 0x01, 0x38, 0x68, 0x60, 0x8d, 0xcb, // C470
|
||||
0xc0, 0x18, 0x60, 0x8d, 0xca, 0xc0, 0x18, 0x60,
|
||||
|
||||
0x8d, 0xc9, 0xc0, 0x18, 0x60, 0xc9, 0x02, 0xb0, // C480
|
||||
0x04, 0x8d, 0xcd, 0xc0, 0x60, 0x38, 0x60, 0x8d,
|
||||
0xc8, 0xc0, 0x18, 0x60, 0x8d, 0xcc, 0xc0, 0x18, // C490
|
||||
0x60, 0x78, 0x8d, 0xce, 0xc0, 0xa2, 0x04, 0x18,
|
||||
0x90, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // C4A0
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // C4B0
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // C4C0
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // C4D0
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // C4E0
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // C4F0
|
||||
0xff, 0xff, 0xff, 0xd6, 0xff, 0xff, 0xff, 0x01 };
|
||||
memcpy(toWhere, rom, 256);
|
||||
}
|
||||
|
||||
bool Mouse::hasExtendedRom()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void Mouse::loadExtendedRom(uint8_t *toWhere, uint16_t byteOffset)
|
||||
{
|
||||
// There's no extended ROM needed, b/c we do the extended ROM work
|
||||
// directly in C++
|
||||
}
|
||||
|
||||
void Mouse::maintainMouse(int64_t cycleCount)
|
||||
{
|
||||
// Fake a 60Hz VBL in case we need it for our interrupts
|
||||
static int64_t nextInterruptTime = cycleCount + 17050;
|
||||
|
||||
if ( (status & ST_MOUSEENABLE) &&
|
||||
(status & ST_INTVBL) &&
|
||||
(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 != lastXForInt || ypos != lastYForInt) ) {
|
||||
g_cpu->irq();
|
||||
|
||||
interruptsTriggered |= ST_INTMOUSE;
|
||||
lastXForInt = xpos; lastYForInt = ypos;
|
||||
} else if ( (status & ST_MOUSEENABLE) &&
|
||||
(status & ST_INTBUTTON) &&
|
||||
lastButtonForInt != g_mouse->getButton()) {
|
||||
g_cpu->irq();
|
||||
|
||||
interruptsTriggered |= ST_INTBUTTON;
|
||||
lastButtonForInt = g_mouse->getButton();
|
||||
}
|
||||
}
|
||||
/* FIXME: still need button */
|
||||
}
|
||||
|
||||
bool Mouse::isEnabled()
|
||||
{
|
||||
return status & ST_MOUSEENABLE;
|
||||
}
|
50
apple/mouse.h
Normal file
50
apple/mouse.h
Normal file
@ -0,0 +1,50 @@
|
||||
#ifndef __APPLEMOUSE_H
|
||||
#define __APPLEMOUSE_H
|
||||
|
||||
#ifdef TEENSYDUINO
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "applemmu.h"
|
||||
#include "slot.h"
|
||||
|
||||
class Mouse : public Slot {
|
||||
public:
|
||||
Mouse();
|
||||
virtual ~Mouse();
|
||||
|
||||
virtual bool Serialize(int8_t fd);
|
||||
virtual bool Deserialize(int8_t fd);
|
||||
|
||||
virtual void Reset(); // used by BIOS cold-boot
|
||||
virtual uint8_t readSwitches(uint8_t s);
|
||||
virtual void writeSwitches(uint8_t s, uint8_t v);
|
||||
virtual void loadROM(uint8_t *toWhere);
|
||||
|
||||
virtual bool hasExtendedRom();
|
||||
virtual void loadExtendedRom(uint8_t *toWhere, uint16_t byteOffset);
|
||||
|
||||
void maintainMouse(int64_t cycleCount);
|
||||
|
||||
bool isEnabled();
|
||||
|
||||
private:
|
||||
uint8_t status;
|
||||
uint8_t interruptsTriggered;
|
||||
|
||||
// Previous state vars used when we're asked "did this change since last time"
|
||||
uint16_t lastX, lastY;
|
||||
bool lastButton;
|
||||
|
||||
bool curButton;
|
||||
|
||||
// second set of previous state vars for use when checking if an interrupt
|
||||
// needs to fire based on a change
|
||||
uint16_t lastXForInt, lastYForInt;
|
||||
bool lastButtonForInt;
|
||||
};
|
||||
|
||||
#endif
|
43
apple/pia6821.cpp
Normal file
43
apple/pia6821.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
#include "pia6821.h"
|
||||
|
||||
PIA6821::PIA6821()
|
||||
{
|
||||
}
|
||||
|
||||
PIA6821::~PIA6821()
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t PIA6821::read(uint8_t addr)
|
||||
{
|
||||
uint8_t rv;
|
||||
|
||||
switch (addr) {
|
||||
case DDRA:
|
||||
if (cra & 0x04) { // DDR or Peripherial Interface access control
|
||||
// peripheral
|
||||
// rv = readPeripheralA();
|
||||
// FIXME continue here
|
||||
} else {
|
||||
rv = ddra;
|
||||
}
|
||||
break;
|
||||
case CTLA:
|
||||
rv = cra;
|
||||
break;
|
||||
case DDRB:
|
||||
if (crb & 0x04) {
|
||||
// rv = readPeripheralB();
|
||||
// FIXME continue here
|
||||
} else {
|
||||
rv = ddrb;
|
||||
}
|
||||
break;
|
||||
case CTLB:
|
||||
rv = crb;
|
||||
break;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
31
apple/pia6821.h
Normal file
31
apple/pia6821.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef _PIA6821_H
|
||||
#define _PIA6821_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// http://webpages.charter.net/coinopcauldron/piaarticle.html
|
||||
|
||||
#define DDRA 0
|
||||
#define CTLA 1
|
||||
#define DDRB 2
|
||||
#define CTLB 3
|
||||
|
||||
class PIA6821 {
|
||||
public:
|
||||
PIA6821();
|
||||
~PIA6821();
|
||||
|
||||
uint8_t read(uint8_t addr);
|
||||
|
||||
|
||||
private:
|
||||
uint8_t porta, portb;
|
||||
uint8_t ddra, ddrb;
|
||||
uint8_t cra, crb; // control registers
|
||||
/*
|
||||
2 ports - porta, portb
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -22,6 +22,9 @@ class Slot {
|
||||
virtual void writeSwitches(uint8_t s, uint8_t v) = 0;
|
||||
|
||||
virtual void loadROM(uint8_t *toWhere) = 0;
|
||||
|
||||
virtual bool hasExtendedRom() { return false; };
|
||||
virtual void loadExtendedRom(uint8_t *toWhere, uint16_t byteOffset) {};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -5,6 +5,7 @@ Cpu *g_cpu = NULL;
|
||||
VM *g_vm = NULL;
|
||||
PhysicalDisplay *g_display = NULL;
|
||||
PhysicalKeyboard *g_keyboard = NULL;
|
||||
PhysicalMouse *g_mouse = NULL;
|
||||
PhysicalSpeaker *g_speaker = NULL;
|
||||
PhysicalPaddles *g_paddles = NULL;
|
||||
PhysicalPrinter *g_printer = NULL;
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "vm.h"
|
||||
#include "physicaldisplay.h"
|
||||
#include "physicalkeyboard.h"
|
||||
#include "physicalmouse.h"
|
||||
#include "physicalspeaker.h"
|
||||
#include "physicalpaddles.h"
|
||||
#include "physicalprinter.h"
|
||||
@ -41,6 +42,7 @@ extern Cpu *g_cpu;
|
||||
extern VM *g_vm;
|
||||
extern PhysicalDisplay *g_display;
|
||||
extern PhysicalKeyboard *g_keyboard;
|
||||
extern PhysicalMouse *g_mouse;
|
||||
extern PhysicalSpeaker *g_speaker;
|
||||
extern PhysicalPaddles *g_paddles;
|
||||
extern PhysicalPrinter *g_printer;
|
||||
|
@ -51,6 +51,9 @@ Debugger::Debugger()
|
||||
server.sin_addr.s_addr = INADDR_ANY;
|
||||
server.sin_port = htons(12345);
|
||||
|
||||
steppingOut = false;
|
||||
singleStep = false;
|
||||
|
||||
if (bind(sd, (struct sockaddr *) &server, sizeof(server)) < 0) {
|
||||
perror("error binding to debug socket");
|
||||
exit(1);
|
||||
@ -71,10 +74,14 @@ Debugger::~Debugger()
|
||||
bool getAddress(const char *buf, unsigned int *addrOut)
|
||||
{
|
||||
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;
|
||||
return true;
|
||||
} else if (sscanf(buf, " $%X", &val) == 1) {
|
||||
} else if (sscanf(buf, " $%X", &val) == 1 ||
|
||||
sscanf(buf, " $%x", &val) == 1
|
||||
) {
|
||||
*addrOut = val;
|
||||
return true;
|
||||
} 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 FROMHEXP(p) ((HEXCHAR(*p) << 4) | HEXCHAR(*(p+1)))
|
||||
|
||||
bool steppingOut = false;
|
||||
|
||||
void Debugger::step()
|
||||
{
|
||||
static char buf[256];
|
||||
uint8_t cmdbuf[50];
|
||||
|
||||
// FIXME: add more than just RTS(0x60) here
|
||||
if (steppingOut &&
|
||||
@ -124,38 +130,49 @@ void Debugger::step()
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t cmdbuf[50];
|
||||
|
||||
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) {
|
||||
if (!singleStep && breakpoint && g_cpu->pc != breakpoint) {
|
||||
// Running until we reach the breakpoint
|
||||
return;
|
||||
}
|
||||
singleStep = false; // we have taken a single step, so reset flag
|
||||
|
||||
uint8_t b; // byte value used in parsing
|
||||
unsigned int val; // common value buffer used in parsing
|
||||
|
||||
GETCH;
|
||||
snprintf(buf, sizeof(buf), "Got char %d\012\015", b);
|
||||
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) {
|
||||
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");
|
||||
breakpoint = 0;
|
||||
close(cd); cd=-1;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
singleStep = true; // for when breakpoint is set: just step once
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
steppingOut = true;
|
||||
@ -176,6 +193,23 @@ void Debugger::step()
|
||||
write(cd, buf, strlen(buf));
|
||||
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
|
||||
{
|
||||
printf("Loading data\n");
|
||||
@ -198,6 +232,7 @@ void Debugger::step()
|
||||
}
|
||||
}
|
||||
}
|
||||
goto doover;
|
||||
break;
|
||||
|
||||
case '*': // read 1 byte of memory. Use '* 0x<address>'
|
||||
@ -214,6 +249,7 @@ void Debugger::step()
|
||||
write(cd, buf, strlen(buf));
|
||||
}
|
||||
}
|
||||
goto doover;
|
||||
break;
|
||||
|
||||
case 'G': // Goto (set PC)
|
||||
|
@ -19,6 +19,8 @@ class Debugger {
|
||||
pthread_t listenThreadID;
|
||||
|
||||
uint32_t breakpoint;
|
||||
bool steppingOut;
|
||||
bool singleStep;
|
||||
};
|
||||
|
||||
|
||||
|
@ -133,6 +133,7 @@ uint8_t Disassembler::instructionToMnemonic(uint16_t addr, uint8_t *p, char *out
|
||||
addrmode amode = opcodes[*p].mode;
|
||||
uint16_t target = 0;
|
||||
char arg[40] = "\0";
|
||||
char bytes[10] = "\0";
|
||||
|
||||
switch (amode) {
|
||||
case A_REL:
|
||||
@ -153,14 +154,19 @@ uint8_t Disassembler::instructionToMnemonic(uint16_t addr, uint8_t *p, char *out
|
||||
switch (instructionBytes(*p)) {
|
||||
case 1:
|
||||
// no arguments
|
||||
sprintf(bytes, " %.2X ", *(uint8_t *)p);
|
||||
break;
|
||||
case 2:
|
||||
sprintf(arg, "%s$%X%s", om.prefix, target, om.suffix);
|
||||
sprintf(bytes, " %.2X %.2X ", *(uint8_t *)p, *(uint8_t *)(p+1));
|
||||
break;
|
||||
case 3:
|
||||
sprintf(arg, "%s$%X%s", om.prefix, target, om.suffix);
|
||||
sprintf(bytes, "%.2X %.2X %.2X ", *(uint8_t *)p, *(uint8_t *)(p+1), *(uint8_t *)(p+2));
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(outp, "$%.4X %s %s", addr, mn, arg);
|
||||
sprintf(outp, "$%.4X %s %s %s", addr, bytes, mn, arg);
|
||||
|
||||
return instructionBytes(*p);
|
||||
}
|
||||
|
27
physicalmouse.h
Normal file
27
physicalmouse.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef __PHYSICALMOUSE_H
|
||||
#define __PHYSICALMOUSE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum {
|
||||
XCLAMP = 0,
|
||||
YCLAMP = 1
|
||||
};
|
||||
|
||||
class PhysicalMouse {
|
||||
public:
|
||||
PhysicalMouse() { lowClamp[XCLAMP] = lowClamp[YCLAMP] = 0; highClamp[XCLAMP] = highClamp[YCLAMP] = 1023; }
|
||||
virtual ~PhysicalMouse() {};
|
||||
|
||||
virtual void maintainMouse() = 0;
|
||||
|
||||
virtual void setClamp(uint8_t direction, uint16_t low, uint16_t high) { lowClamp[direction] = low; highClamp[direction] = 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
|
@ -7,6 +7,7 @@
|
||||
#include "applevm.h"
|
||||
#include "sdl-display.h"
|
||||
#include "sdl-keyboard.h"
|
||||
#include "sdl-mouse.h"
|
||||
#include "sdl-speaker.h"
|
||||
#include "sdl-paddles.h"
|
||||
#include "nix-filemanager.h"
|
||||
@ -291,7 +292,7 @@ struct timespec runMaintenance(struct timespec now)
|
||||
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
|
||||
// be until we need to run
|
||||
@ -305,6 +306,7 @@ struct timespec runMaintenance(struct timespec now)
|
||||
if (!g_biosInterrupt) {
|
||||
// If the BIOS is running, then let it handle the keyboard directly
|
||||
g_keyboard->maintainKeyboard();
|
||||
g_mouse->maintainMouse();
|
||||
}
|
||||
|
||||
doDebugging();
|
||||
@ -389,6 +391,7 @@ int main(int argc, char *argv[])
|
||||
g_vm = new AppleVM();
|
||||
|
||||
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.
|
||||
g_cpu->SetMMU(g_vm->getMMU());
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "sdl-keyboard.h"
|
||||
|
||||
#include "sdl-paddles.h"
|
||||
#include "sdl-mouse.h"
|
||||
#include "globals.h"
|
||||
|
||||
SDLKeyboard::SDLKeyboard(VMKeyboard *k) : PhysicalKeyboard(k)
|
||||
@ -149,12 +150,18 @@ void SDLKeyboard::maintainKeyboard()
|
||||
if (event.key.repeat == 0)
|
||||
handleKeypress(&event.key);
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
((SDLMouse *)g_mouse)->mouseButtonEvent(event.type == SDL_MOUSEBUTTONDOWN);
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
// 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: event.motion.state & SDL_BUTTON_LMASK, et al?
|
||||
|
||||
((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;
|
||||
|
||||
case SDL_QUIT:
|
||||
|
62
sdl/sdl-mouse.cpp
Normal file
62
sdl/sdl-mouse.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
#include "sdl-mouse.h"
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
SDLMouse::SDLMouse() : PhysicalMouse()
|
||||
{
|
||||
xpos = ypos = 0;
|
||||
button = false;
|
||||
}
|
||||
|
||||
SDLMouse::~SDLMouse()
|
||||
{
|
||||
}
|
||||
|
||||
void SDLMouse::gotMouseEvent(uint32_t buttonState, int32_t x, int32_t y)
|
||||
{
|
||||
xpos += x; ypos += y;
|
||||
|
||||
if (xpos < lowClamp[XCLAMP]) xpos=lowClamp[XCLAMP];
|
||||
if (xpos > highClamp[XCLAMP]) xpos=highClamp[XCLAMP];
|
||||
if (ypos < lowClamp[YCLAMP]) ypos = lowClamp[YCLAMP];
|
||||
if (ypos > highClamp[YCLAMP]) ypos = highClamp[YCLAMP];
|
||||
}
|
||||
|
||||
void SDLMouse::mouseButtonEvent(bool state)
|
||||
{
|
||||
button = state;
|
||||
}
|
||||
|
||||
void SDLMouse::maintainMouse()
|
||||
{
|
||||
}
|
||||
|
||||
void SDLMouse::setPosition(uint16_t x, uint16_t y)
|
||||
{
|
||||
xpos = x;
|
||||
ypos = y;
|
||||
|
||||
if (xpos < lowClamp[XCLAMP]) xpos=lowClamp[XCLAMP];
|
||||
if (xpos > highClamp[XCLAMP]) xpos=highClamp[XCLAMP];
|
||||
if (ypos < lowClamp[YCLAMP]) ypos = lowClamp[YCLAMP];
|
||||
if (ypos > highClamp[YCLAMP]) ypos = highClamp[YCLAMP];
|
||||
}
|
||||
|
||||
void SDLMouse::getPosition(uint16_t *x, uint16_t *y)
|
||||
{
|
||||
if (xpos < lowClamp[XCLAMP]) xpos=lowClamp[XCLAMP];
|
||||
if (xpos > highClamp[XCLAMP]) xpos=highClamp[XCLAMP];
|
||||
if (ypos < lowClamp[YCLAMP]) ypos = lowClamp[YCLAMP];
|
||||
if (ypos > highClamp[YCLAMP]) ypos = highClamp[YCLAMP];
|
||||
|
||||
uint16_t outx = xpos;
|
||||
uint16_t outy = ypos;
|
||||
|
||||
*x = outx;
|
||||
*y = outy;
|
||||
}
|
||||
|
||||
bool SDLMouse::getButton()
|
||||
{
|
||||
return button;
|
||||
}
|
26
sdl/sdl-mouse.h
Normal file
26
sdl/sdl-mouse.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef __SDL_MOUSE_H
|
||||
#define __SDL_MOUSE_H
|
||||
|
||||
#include "physicalmouse.h"
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
class SDLMouse : public PhysicalMouse {
|
||||
public:
|
||||
SDLMouse();
|
||||
virtual ~SDLMouse();
|
||||
|
||||
virtual void maintainMouse();
|
||||
|
||||
virtual void setPosition(uint16_t x, uint16_t y);
|
||||
virtual void getPosition(uint16_t *x, uint16_t *y);
|
||||
virtual bool getButton();
|
||||
|
||||
void gotMouseEvent(uint32_t buttonState, int32_t x, int32_t y);
|
||||
void mouseButtonEvent(bool state);
|
||||
private:
|
||||
int32_t xpos, ypos;
|
||||
bool button;
|
||||
};
|
||||
|
||||
#endif
|
142
serialize.h
Normal file
142
serialize.h
Normal file
@ -0,0 +1,142 @@
|
||||
#ifndef __SERIALIZE_H
|
||||
#define __SERIALIZE_H
|
||||
|
||||
#define serialize8(var) { uint8_t buf = (uint8_t)var; \
|
||||
if (g_filemanager->write(fd, &buf, 1) != 1) { \
|
||||
printf("Failed to write 1 byte\n"); \
|
||||
goto err; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define serializeMagic(var) { \
|
||||
printf("Serializing magic '%d'\n", var); \
|
||||
uint8_t buf = var; \
|
||||
if (g_filemanager->write(fd, &buf, 1) != 1) { \
|
||||
printf("Failed to write 1 byte of magic\n"); \
|
||||
goto err; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define serialize16(var) { \
|
||||
uint8_t buf[2]; \
|
||||
uint8_t ptr = 0; \
|
||||
buf[ptr++] = ((var >> 8) & 0xFF); \
|
||||
buf[ptr++] = ((var ) & 0xFF); \
|
||||
if (g_filemanager->write(fd, buf, 2) != 2) { \
|
||||
printf("Failed to write 2 bytes\n"); \
|
||||
goto err; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define serialize32(var) { \
|
||||
uint8_t buf[4]; \
|
||||
uint8_t ptr = 0; \
|
||||
buf[ptr++] = ((var >> 24) & 0xFF); \
|
||||
buf[ptr++] = ((var >> 16) & 0xFF); \
|
||||
buf[ptr++] = ((var >> 8) & 0xFF); \
|
||||
buf[ptr++] = ((var ) & 0xFF); \
|
||||
if (g_filemanager->write(fd, buf, 4) != 4) { \
|
||||
printf("Failed to write 4 bytes\n"); \
|
||||
goto err; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define serialize64(var) { \
|
||||
uint8_t buf[8]; \
|
||||
uint8_t ptr = 0; \
|
||||
buf[ptr++] = ((var >> 56) & 0xFF); \
|
||||
buf[ptr++] = ((var >> 48) & 0xFF); \
|
||||
buf[ptr++] = ((var >> 40) & 0xFF); \
|
||||
buf[ptr++] = ((var >> 32) & 0xFF); \
|
||||
buf[ptr++] = ((var >> 24) & 0xFF); \
|
||||
buf[ptr++] = ((var >> 16) & 0xFF); \
|
||||
buf[ptr++] = ((var >> 8) & 0xFF); \
|
||||
buf[ptr++] = ((var ) & 0xFF); \
|
||||
if (g_filemanager->write(fd, buf, 8) != 8) { \
|
||||
printf("Failed to write 8 bytes\n"); \
|
||||
goto err; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define serializeString(s) { \
|
||||
if (g_filemanager->write(fd, s, strlen(s)+1) != strlen(s)+1) { \
|
||||
printf("Failed to write string '%s'\n", s); \
|
||||
goto err; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define deserialize8(var) { \
|
||||
uint8_t buf; \
|
||||
if (g_filemanager->read(fd, &buf, 1) != 1) { \
|
||||
printf("Failed to deserialize 1 byte\n"); \
|
||||
goto err; \
|
||||
} \
|
||||
var = buf; \
|
||||
}
|
||||
|
||||
#define deserializeMagic(expect) { \
|
||||
uint8_t buf; \
|
||||
printf("Deserializing magic, expecting 0x%X\n", expect); \
|
||||
if (g_filemanager->read(fd, &buf, 1) != 1) { \
|
||||
printf("Failed to deserialize 1 byte of magic\n"); \
|
||||
goto err; \
|
||||
} \
|
||||
if (buf != expect) { \
|
||||
printf("magic error: 0x%X does not match expected 0x%X\n", buf, expect); \
|
||||
goto err; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define deserialize16(var) { \
|
||||
uint8_t buf[2]; \
|
||||
uint8_t ptr = 0; \
|
||||
if (g_filemanager->read(fd, buf, 2) != 2) { \
|
||||
printf("Failed to deserialize 2 bytes\n"); \
|
||||
goto err; \
|
||||
} \
|
||||
var = buf[ptr++]; \
|
||||
var <<= 8; var |= buf[ptr++]; }
|
||||
|
||||
#define deserialize32(var) { \
|
||||
uint8_t buf[4]; \
|
||||
uint8_t ptr = 0; \
|
||||
if (g_filemanager->read(fd, buf, 4) != 4) { \
|
||||
printf("Failed to deserialize 4 bytes\n"); \
|
||||
goto err; \
|
||||
} \
|
||||
var = buf[ptr++]; \
|
||||
var <<= 8; var |= buf[ptr++]; \
|
||||
var <<= 8; var |= buf[ptr++]; \
|
||||
var <<= 8; var |= buf[ptr++]; }
|
||||
|
||||
#define deserialize64(var) { \
|
||||
uint8_t buf[8]; \
|
||||
uint8_t ptr = 0; \
|
||||
if (g_filemanager->read(fd, buf, 8) != 8) { \
|
||||
printf("Failed to deserialize 8 bytes\n"); \
|
||||
goto err; \
|
||||
} \
|
||||
var = buf[ptr++]; \
|
||||
var <<= 8; var |= buf[ptr++]; \
|
||||
var <<= 8; var |= buf[ptr++]; \
|
||||
var <<= 8; var |= buf[ptr++]; \
|
||||
var <<= 8; var |= buf[ptr++]; \
|
||||
var <<= 8; var |= buf[ptr++]; \
|
||||
var <<= 8; var |= buf[ptr++]; \
|
||||
var <<= 8; var |= buf[ptr++]; }
|
||||
|
||||
#define deserializeString(var) { \
|
||||
uint8_t c; \
|
||||
char *ptr = var; \
|
||||
while (1) { \
|
||||
if (g_filemanager->read(fd, &c, 1) != 1) { \
|
||||
printf("Failed to read string byte\n"); \
|
||||
goto err; \
|
||||
} \
|
||||
printf(". "); \
|
||||
*(ptr++) = c; \
|
||||
if (c == 0) { break; } \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif
|
1
teensy/mouse.cpp
Symbolic link
1
teensy/mouse.cpp
Symbolic link
@ -0,0 +1 @@
|
||||
../apple/mouse.cpp
|
1
teensy/mouse.h
Symbolic link
1
teensy/mouse.h
Symbolic link
@ -0,0 +1 @@
|
||||
../apple/mouse.h
|
1
teensy/physicalmouse.h
Symbolic link
1
teensy/physicalmouse.h
Symbolic link
@ -0,0 +1 @@
|
||||
../physicalmouse.h
|
1
teensy/serialize.h
Symbolic link
1
teensy/serialize.h
Symbolic link
@ -0,0 +1 @@
|
||||
../serialize.h
|
@ -345,10 +345,14 @@ void TeensyDisplay::cachePixel(uint16_t x, uint16_t y, uint8_t color)
|
||||
// with a color between the two.
|
||||
|
||||
#if 1
|
||||
// This is straight blending, R/G/B average
|
||||
// This is straight blending, R/G/B average, except in B&W mode
|
||||
uint16_t origColor = dmaBuffer[y+VOFFSET][(x>>1)+HOFFSET];
|
||||
uint16_t newColor = loresPixelColors[color];
|
||||
cacheDoubleWidePixel(x>>1, y, blendColors(origColor, newColor));
|
||||
if (g_displayType == m_blackAndWhite) {
|
||||
cacheDoubleWidePixel(x>>1, y, (origColor && newColor) ? 0xFFFF : 0x0000);
|
||||
} else {
|
||||
cacheDoubleWidePixel(x>>1, y, blendColors(origColor, newColor));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
|
@ -4,6 +4,9 @@
|
||||
#include "LRingBuffer.h"
|
||||
#include "teensy-println.h"
|
||||
|
||||
#include "globals.h"
|
||||
#include "teensy-mouse.h"
|
||||
|
||||
const byte ROWS = 5;
|
||||
const byte COLS = 13;
|
||||
|
||||
@ -71,12 +74,13 @@ void TeensyKeyboard::pressedKey(uint8_t key)
|
||||
break;
|
||||
case PK_RSHFT:
|
||||
rightShiftPressed = 1;
|
||||
break;
|
||||
break;
|
||||
case PK_LOCK:
|
||||
capsLock = !capsLock;
|
||||
break;
|
||||
case PK_LA:
|
||||
leftApplePressed = 1;
|
||||
((TeensyMouse *)g_mouse)->mouseButtonEvent(true);
|
||||
leftApplePressed = 1;
|
||||
break;
|
||||
case PK_RA:
|
||||
rightApplePressed = 1;
|
||||
@ -162,6 +166,7 @@ void TeensyKeyboard::releasedKey(uint8_t key)
|
||||
rightShiftPressed = 0;
|
||||
break;
|
||||
case PK_LA:
|
||||
((TeensyMouse *)g_mouse)->mouseButtonEvent(false);
|
||||
leftApplePressed = 0;
|
||||
break;
|
||||
case PK_RA:
|
||||
@ -218,9 +223,15 @@ void TeensyKeyboard::maintainKeyboard()
|
||||
switch (keypad.key[i].kstate) {
|
||||
case PRESSED:
|
||||
vmkeyboard->keyDepressed(keypad.key[i].kchar);
|
||||
if (keypad.key[i].kchar == PK_LSHFT) {
|
||||
((TeensyMouse *)g_mouse)->mouseButtonEvent(true);
|
||||
}
|
||||
break;
|
||||
case RELEASED:
|
||||
vmkeyboard->keyReleased(keypad.key[i].kchar);
|
||||
if (keypad.key[i].kchar == PK_LSHFT) {
|
||||
((TeensyMouse *)g_mouse)->mouseButtonEvent(false);
|
||||
}
|
||||
break;
|
||||
case HOLD:
|
||||
case IDLE:
|
||||
|
85
teensy/teensy-mouse.cpp
Normal file
85
teensy/teensy-mouse.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
#include <Arduino.h>
|
||||
#include "teensy-mouse.h"
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
#include "applevm.h"
|
||||
|
||||
TeensyMouse::TeensyMouse() : PhysicalMouse()
|
||||
{
|
||||
xpos = ypos = 0;
|
||||
button = false;
|
||||
}
|
||||
|
||||
TeensyMouse::~TeensyMouse()
|
||||
{
|
||||
}
|
||||
|
||||
void TeensyMouse::gotMouseEvent(uint32_t buttonState, int32_t x, int32_t y)
|
||||
{
|
||||
xpos += x; ypos += y;
|
||||
|
||||
if (xpos < lowClamp[XCLAMP]) xpos=lowClamp[XCLAMP];
|
||||
if (xpos > highClamp[XCLAMP]) xpos=highClamp[XCLAMP];
|
||||
if (ypos < lowClamp[YCLAMP]) ypos = lowClamp[YCLAMP];
|
||||
if (ypos > highClamp[YCLAMP]) ypos = highClamp[YCLAMP];
|
||||
}
|
||||
|
||||
void TeensyMouse::mouseButtonEvent(bool state)
|
||||
{
|
||||
button = state;
|
||||
}
|
||||
|
||||
void TeensyMouse::maintainMouse()
|
||||
{
|
||||
if (((AppleVM *)g_vm)->isMouseEnabled()) {
|
||||
// only do this if the mouse card is enabled, so we're not incurring
|
||||
// analogRead delays constantly
|
||||
uint8_t paddle0 = g_paddles->paddle0();
|
||||
uint8_t paddle1 = g_paddles->paddle1();
|
||||
int16_t dx=0, dy=0;
|
||||
if (paddle0 <= 25) {
|
||||
dx = -1;
|
||||
} else if (paddle0 >= 245) {
|
||||
dx = 1;
|
||||
}
|
||||
if (paddle1 <= 25) {
|
||||
dy = -1;
|
||||
} else if (paddle1 >= 245) {
|
||||
dy = 1;
|
||||
}
|
||||
if (dx || dy) {
|
||||
gotMouseEvent(button, dx, dy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TeensyMouse::setPosition(uint16_t x, uint16_t y)
|
||||
{
|
||||
xpos = x;
|
||||
ypos = y;
|
||||
|
||||
if (xpos < lowClamp[XCLAMP]) xpos=lowClamp[XCLAMP];
|
||||
if (xpos > highClamp[XCLAMP]) xpos=highClamp[XCLAMP];
|
||||
if (ypos < lowClamp[YCLAMP]) ypos = lowClamp[YCLAMP];
|
||||
if (ypos > highClamp[YCLAMP]) ypos = highClamp[YCLAMP];
|
||||
}
|
||||
|
||||
void TeensyMouse::getPosition(uint16_t *x, uint16_t *y)
|
||||
{
|
||||
if (xpos < lowClamp[XCLAMP]) xpos=lowClamp[XCLAMP];
|
||||
if (xpos > highClamp[XCLAMP]) xpos=highClamp[XCLAMP];
|
||||
if (ypos < lowClamp[YCLAMP]) ypos = lowClamp[YCLAMP];
|
||||
if (ypos > highClamp[YCLAMP]) ypos = highClamp[YCLAMP];
|
||||
|
||||
uint16_t outx = xpos;
|
||||
uint16_t outy = ypos;
|
||||
|
||||
*x = outx;
|
||||
*y = outy;
|
||||
}
|
||||
|
||||
bool TeensyMouse::getButton()
|
||||
{
|
||||
return button;
|
||||
}
|
24
teensy/teensy-mouse.h
Normal file
24
teensy/teensy-mouse.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __TEENSY_MOUSE_H
|
||||
#define __TEENSY_MOUSE_H
|
||||
|
||||
#include "physicalmouse.h"
|
||||
|
||||
class TeensyMouse : public PhysicalMouse {
|
||||
public:
|
||||
TeensyMouse();
|
||||
virtual ~TeensyMouse();
|
||||
|
||||
virtual void maintainMouse();
|
||||
|
||||
virtual void setPosition(uint16_t x, uint16_t y);
|
||||
virtual void getPosition(uint16_t *x, uint16_t *y);
|
||||
virtual bool getButton();
|
||||
|
||||
void gotMouseEvent(uint32_t buttonState, int32_t x, int32_t y);
|
||||
void mouseButtonEvent(bool state);
|
||||
private:
|
||||
int32_t xpos, ypos;
|
||||
bool button;
|
||||
};
|
||||
|
||||
#endif
|
@ -6,6 +6,7 @@
|
||||
#include "applevm.h"
|
||||
#include "teensy-display.h"
|
||||
#include "teensy-keyboard.h"
|
||||
#include "teensy-mouse.h"
|
||||
#include "teensy-speaker.h"
|
||||
#include "teensy-paddles.h"
|
||||
#include "teensy-filemanager.h"
|
||||
@ -211,6 +212,7 @@ void setup()
|
||||
// And the physical keyboard needs hooks in to the virtual keyboard...
|
||||
println(" keyboard");
|
||||
g_keyboard = new TeensyKeyboard(g_vm->getKeyboard());
|
||||
g_mouse = new TeensyMouse();
|
||||
|
||||
println(" paddles");
|
||||
g_paddles = new TeensyPaddles(A3, A2, g_invertPaddleX, g_invertPaddleY);
|
||||
@ -286,7 +288,8 @@ void runMaintenance(uint32_t now)
|
||||
static uint32_t nextRuntime = 0;
|
||||
|
||||
if (now >= nextRuntime) {
|
||||
nextRuntime = now + 100000; // FIXME: what's a good time here? 1/10 sec?
|
||||
// Run maintenance at 60 Hz because the mouse will need it
|
||||
nextRuntime = now + 16667;
|
||||
|
||||
if (!resetButtonDebouncer.read()) {
|
||||
// This is the BIOS interrupt. Wait for it to clear and process it.
|
||||
@ -297,6 +300,7 @@ void runMaintenance(uint32_t now)
|
||||
}
|
||||
|
||||
if (!g_biosInterrupt) {
|
||||
g_mouse->maintainMouse();
|
||||
g_keyboard->maintainKeyboard();
|
||||
usb.maintain();
|
||||
}
|
||||
|
12
vmram.cpp
12
vmram.cpp
@ -9,11 +9,10 @@
|
||||
#include "globals.h"
|
||||
|
||||
#ifdef TEENSYDUINO
|
||||
#include "iocompat.h"
|
||||
EXTMEM uint8_t preallocatedRam[591*256];
|
||||
EXTMEM uint8_t preallocatedRam[599*256];
|
||||
#else
|
||||
#include <stdio.h>
|
||||
uint8_t preallocatedRam[591*256];
|
||||
uint8_t preallocatedRam[599*256];
|
||||
#endif
|
||||
|
||||
#ifndef TEENSYDUINO
|
||||
@ -47,6 +46,13 @@ void VMRam::writeByte(uint32_t addr, uint8_t value)
|
||||
preallocatedRam[addr] = value;
|
||||
}
|
||||
|
||||
uint8_t *VMRam::memPtr(uint32_t addr)
|
||||
{
|
||||
// printf("Asked for preallocated RAM pointer at 0x%X\n", addr);
|
||||
// printf("Base is 0x%llX\n", (unsigned long long) preallocatedRam);
|
||||
return &preallocatedRam[addr];
|
||||
}
|
||||
|
||||
bool VMRam::Serialize(int8_t fd)
|
||||
{
|
||||
uint32_t size = sizeof(preallocatedRam);
|
||||
|
6
vmram.h
6
vmram.h
@ -15,13 +15,15 @@ class VMRam {
|
||||
uint8_t readByte(uint32_t addr);
|
||||
void writeByte(uint32_t addr, uint8_t value);
|
||||
|
||||
uint8_t *memPtr(uint32_t addr);
|
||||
|
||||
bool Serialize(int8_t fd);
|
||||
bool Deserialize(int8_t fd);
|
||||
|
||||
bool Test();
|
||||
|
||||
private:
|
||||
// We need 591 pages of 256 bytes for the //e.
|
||||
// We need 599 pages of 256 bytes for the //e.
|
||||
//
|
||||
// This previously used a split memory model where some of this was
|
||||
// in internal ram and some was external - and while that's not true
|
||||
@ -37,7 +39,7 @@ class VMRam {
|
||||
// Pages 4-7 are 0x200 - 0x3FF. We want those in RAM too (text pages).
|
||||
|
||||
// Has to be static if we're using the EXTMEM sectioning, so it's now in vmram.cpp :/
|
||||
//EXTMEM uint8_t preallocatedRam[591*256];
|
||||
//EXTMEM uint8_t preallocatedRam[599*256];
|
||||
|
||||
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user