mirror of
https://github.com/JorjBauer/aiie.git
synced 2024-12-26 23:29:21 +00:00
spun mouse rom to its own .asm file; fixed PR# and IN# behavior in the mouse driver
This commit is contained in:
parent
e63b21d7c0
commit
7028e1dfd2
8
Makefile
8
Makefile
@ -20,7 +20,7 @@ SDLSRCS=sdl/sdl-speaker.cpp sdl/sdl-display.cpp sdl/sdl-keyboard.cpp sdl/sdl-pad
|
||||
|
||||
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 apple/mouse-rom.h
|
||||
|
||||
.PHONY: roms clean
|
||||
|
||||
@ -39,8 +39,8 @@ test: $(TSRC)
|
||||
./testharness -f tests/65C02_extended_opcodes_test.bin -s 0x400 && \
|
||||
./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
|
||||
roms: apple2e.rom disk.rom parallel.rom HDDRVR.BIN mouse.rom
|
||||
./util/genrom.pl apple2e.rom disk.rom parallel.rom HDDRVR.BIN mouse.rom
|
||||
|
||||
apple/applemmu-rom.h: roms
|
||||
|
||||
@ -48,6 +48,8 @@ apple/diskii-rom.h: roms
|
||||
|
||||
apple/parallel-rom.h: roms
|
||||
|
||||
apple/mouse-rom.h: roms
|
||||
|
||||
clean:
|
||||
rm -f *.o *~ */*.o */*~ testharness.basic testharness.verbose testharness.extended testharness apple/diskii-rom.h apple/applemmu-rom.h apple/parallel-rom.h aiie-sdl *.d */*.d
|
||||
|
||||
|
36
apple/manual-linker.pl
Executable file
36
apple/manual-linker.pl
Executable file
@ -0,0 +1,36 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# The ca65 assembler honors .ORG statements - but the ld65 assembler
|
||||
# then destroys them. I haven't figured out how to make its config
|
||||
# do what I want yet, so this is brute force...
|
||||
#
|
||||
# This script takes the listing output from ca65 and generates the
|
||||
# final binary object, like so:
|
||||
#
|
||||
# ca65 --target apple2enh mouserom.asm --listing mouserom.lst --list-bytes 50
|
||||
# ./manual-linker.pl < mouserom.lst > out.bin
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my @memory;
|
||||
|
||||
while (<STDIN>) {
|
||||
chomp;
|
||||
if (/^(......)\s\s[12]\s\s(.+)/) {
|
||||
my $addr = hex($1);
|
||||
my $rest = $2;
|
||||
my @data;
|
||||
while ($rest =~ /^([0-9A-F][0-9A-F])\s+(.+)/) {
|
||||
$memory[$addr] = hex($1);
|
||||
$addr++;
|
||||
$rest = $2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Specifcally, memory $C400..$C4FF gets dumped
|
||||
foreach my $i (0xC400..0xC4FF) {
|
||||
$memory[$i] ||= 0;
|
||||
print chr($memory[$i]);
|
||||
}
|
39
apple/mouse-rom.h
Normal file
39
apple/mouse-rom.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef TEENSYDUINO
|
||||
#define PROGMEM
|
||||
#endif
|
||||
|
||||
static
|
||||
uint8_t romData[256] PROGMEM = {
|
||||
0x2C, 0x58, 0xFF, 0x70, 0x1B, 0x38, 0x90, 0x18,
|
||||
0xB8, 0x50, 0x15, 0x01, 0x20, 0x68, 0x68, 0x68,
|
||||
0x68, 0x00, 0x60, 0x6A, 0x7B, 0x80, 0x85, 0x8A,
|
||||
0x93, 0x98, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68,
|
||||
0x48, 0x98, 0x48, 0x8A, 0x48, 0x08, 0x78, 0x20,
|
||||
0x58, 0xFF, 0xBA, 0xBD, 0x00, 0x01, 0xAA, 0x0A,
|
||||
0x0A, 0x0A, 0x0A, 0xA8, 0x28, 0x50, 0x0F, 0xA5,
|
||||
0x38, 0xD0, 0x0D, 0x8A, 0x45, 0x39, 0xD0, 0x08,
|
||||
0xA9, 0x05, 0x85, 0x38, 0xD0, 0x0B, 0xB0, 0x09,
|
||||
0x68, 0xAA, 0x68, 0xEA, 0x68, 0x99, 0x80, 0xC0,
|
||||
0x60, 0x99, 0x81, 0xC0, 0x68, 0xBD, 0x38, 0x06,
|
||||
0xAA, 0x68, 0xA8, 0x68, 0xBD, 0x00, 0x02, 0x60,
|
||||
0xC9, 0x0A, 0xB0, 0x04, 0x8D, 0xCF, 0xC0, 0x60,
|
||||
0x38, 0x60, 0x48, 0x78, 0x8D, 0xCE, 0xC0, 0xA2,
|
||||
0x04, 0xBD, 0xB8, 0x06, 0x29, 0x0E, 0xD0, 0x01,
|
||||
0x38, 0x68, 0x60, 0x8D, 0xCB, 0xC0, 0x18, 0x60,
|
||||
0x8D, 0xCA, 0xC0, 0x18, 0x60, 0x8D, 0xC9, 0xC0,
|
||||
0x18, 0x60, 0xC9, 0x02, 0xB0, 0xDA, 0x8D, 0xCD,
|
||||
0xC0, 0x18, 0x60, 0x8D, 0xC8, 0xC0, 0x18, 0x60,
|
||||
0x8D, 0xCC, 0xC0, 0x18, 0x60, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xD6, 0x00, 0x00, 0x00, 0x01,
|
||||
};
|
223
apple/mouse.cpp
223
apple/mouse.cpp
@ -2,8 +2,15 @@
|
||||
#include <string.h>
|
||||
#include "globals.h"
|
||||
|
||||
// This ROM is part of the Aiie source code, but it was compiled and
|
||||
// bundled as a binary. If you want to see what it's doing, take a
|
||||
// look at mouserom.asm.
|
||||
#include "mouse-rom.h"
|
||||
|
||||
enum {
|
||||
SW_W_INIT = 0x00,
|
||||
SW_W_INITPR = 0x00,
|
||||
SW_W_HANDLEIN = 0x01,
|
||||
|
||||
SW_R_HOMEMOUSE = 0x08,
|
||||
SW_R_POSMOUSE = 0x09,
|
||||
SW_R_CLEARMOUSE = 0x0A,
|
||||
@ -14,11 +21,6 @@ enum {
|
||||
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 = 0x01,
|
||||
ST_INTMOUSE = 0x02,
|
||||
@ -58,12 +60,32 @@ void Mouse::Reset()
|
||||
{
|
||||
}
|
||||
|
||||
void Mouse::performHack()
|
||||
{
|
||||
char buf[20];
|
||||
uint16_t xpos, ypos;
|
||||
g_mouse->getPosition(&xpos, &ypos);
|
||||
bool curButton = g_mouse->getButton();
|
||||
static bool prevButton = false;
|
||||
bool isKeyPressed = ((AppleMMU *)(g_vm->getMMU()))->readDirect(0xC010, 0) & 0x80 ? true : false;
|
||||
uint8_t buttonPressData = (curButton ? 1 : 3) + (prevButton ? 0 : 1);
|
||||
sprintf(buf, "%d,%d,%s%d\015", xpos, ypos,
|
||||
isKeyPressed ? "-" : "",
|
||||
buttonPressData);
|
||||
for (int i=0; i<strlen(buf); i++) {
|
||||
g_vm->getMMU()->write(0x200 + i, buf[i] | 0x80);
|
||||
}
|
||||
|
||||
// Put the string length in 0x638+$c0+n == $6FC for slot #4.
|
||||
// The caller will pick that up and return it as the length of the buffer,
|
||||
// which that caller will interpret as the next byte it has to display to
|
||||
// the screen in the GETLN call; and since it's a return, it will display
|
||||
// *nothing* and start parsing the string immediately.
|
||||
g_vm->getMMU()->write(0x6fc, strlen(buf)-1);
|
||||
}
|
||||
|
||||
uint8_t Mouse::readSwitches(uint8_t s)
|
||||
{
|
||||
switch (s) {
|
||||
default:
|
||||
printf("mouse: unknown switch read 0x%X\n", s);
|
||||
};
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
@ -74,6 +96,17 @@ void Mouse::writeSwitches(uint8_t s, uint8_t v)
|
||||
* 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_W_INITPR:
|
||||
v &= 0x01;
|
||||
//printf("Simple init: value is 0x%X\n", v);
|
||||
g_vm->getMMU()->write(0x7f8 + 4, v);
|
||||
break;
|
||||
|
||||
case SW_W_HANDLEIN:
|
||||
performHack();
|
||||
break;
|
||||
|
||||
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)
|
||||
@ -127,12 +160,6 @@ void Mouse::writeSwitches(uint8_t s, uint8_t v)
|
||||
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));
|
||||
@ -165,168 +192,24 @@ void Mouse::writeSwitches(uint8_t s, uint8_t v)
|
||||
|
||||
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);
|
||||
#ifdef TEENSYDUINO
|
||||
println("loading Mouse rom");
|
||||
for (uint16_t i=0; i<=0xFF; i++) {
|
||||
toWhere[i] = pgm_read_byte(&romData[i]);
|
||||
}
|
||||
#else
|
||||
printf("loading HD32 rom\n");
|
||||
memcpy(toWhere, romData, 256);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Mouse::hasExtendedRom()
|
||||
{
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -31,6 +31,8 @@ class Mouse : public Slot {
|
||||
|
||||
bool isEnabled();
|
||||
|
||||
void performHack();
|
||||
|
||||
private:
|
||||
uint8_t status;
|
||||
uint8_t interruptsTriggered;
|
||||
|
146
apple/mouserom.asm
Normal file
146
apple/mouserom.asm
Normal file
@ -0,0 +1,146 @@
|
||||
.ORG $C400
|
||||
Entry:
|
||||
BIT $FF58 ; well-known RTS location - where RTS is $60
|
||||
BVS PREntry ; always branches (used to relocatably branch)
|
||||
|
||||
.ORG $C405
|
||||
INEntry:
|
||||
SEC
|
||||
BCC PREntry ; never happens, but has a magic ID byte @ C407 == 18
|
||||
CLV
|
||||
BVC PREntry ; always branches
|
||||
|
||||
;; lookup table
|
||||
.ORG $C40B
|
||||
.byte $01 ; magic identifier
|
||||
.byte $20 ; magic identifier
|
||||
.byte .LOBYTE(ExitWithError)
|
||||
.byte .LOBYTE(ExitWithError)
|
||||
.byte .LOBYTE(ExitWithError)
|
||||
.byte .LOBYTE(ExitWithError)
|
||||
.byte $00
|
||||
.byte .LOBYTE(SetMouse)
|
||||
.byte .LOBYTE(ServeMouse)
|
||||
.byte .LOBYTE(ReadMouse)
|
||||
.byte .LOBYTE(ClearMouse)
|
||||
.byte .LOBYTE(PosMouse)
|
||||
.byte .LOBYTE(ClampMouse)
|
||||
.byte .LOBYTE(HomeMouse)
|
||||
.byte .LOBYTE(InitMouse)
|
||||
.byte .LOBYTE(ExitWithError)
|
||||
.byte .LOBYTE(ExitWithError)
|
||||
.byte .LOBYTE(ExitWithError)
|
||||
.byte .LOBYTE(ExitWithError)
|
||||
.byte .LOBYTE(ExitWithError)
|
||||
.byte .LOBYTE(ExitWithError)
|
||||
|
||||
.ORG $C420
|
||||
PREntry:
|
||||
PHA ; save Y, X, A, S on the stack
|
||||
TYA
|
||||
PHA
|
||||
TXA
|
||||
PHA
|
||||
PHP
|
||||
SEI ; turn off interrupts while we find our address via the stack
|
||||
JSR $FF58 ; well-known RTS
|
||||
TSX ; grab stack pointer
|
||||
LDA $0100,X ; inspect the stack frame
|
||||
TAX ; now A and X hold the high byte of the return address to *us*
|
||||
ASL ; A <<= 4
|
||||
ASL
|
||||
ASL
|
||||
ASL
|
||||
TAY ; so Y = $n0, while X = $Cn for whatever slot we're in
|
||||
PLP ; pull Status off the stack
|
||||
BVC lastChance
|
||||
LDA $38 ; We're being invoked in an IN# context, not a PR# context.
|
||||
BNE PopAndReturn ; if $38/$39 don't point to us, then exit
|
||||
TXA
|
||||
EOR $39 ; is $39 == $Cn?
|
||||
BNE PopAndReturn
|
||||
InstallInHandler:
|
||||
LDA #$05 ; Update IN handler to point to $Cn05 instead of $Cn00, so we know we've
|
||||
STA $38 ;initialized it
|
||||
BNE INHandler
|
||||
lastChance:
|
||||
BCS INHandler
|
||||
PopAndReturn:
|
||||
PLA
|
||||
TAX
|
||||
PLA
|
||||
NOP
|
||||
PLA
|
||||
STA $c080,Y ; call soft-switch #0 for our slot to set mouse state
|
||||
RTS
|
||||
INHandler:
|
||||
STA $c081,Y ; call soft-switch #1 for our slot to fill the keyboard buffer w/ mouse info
|
||||
PLA
|
||||
LDA $0638,X ; pull the string length from this magic screen hole (X == $Cn)
|
||||
TAX ; which we'll return to the caller in X
|
||||
PLA ; restore Y
|
||||
TAY
|
||||
PLA ; restore A
|
||||
LDA $200,X ; Grab the last character entered in to the buffer by the magic switch call
|
||||
RTS
|
||||
|
||||
SetMouse:
|
||||
CMP #$0A ; values >= 10 are invalid
|
||||
BCS ExitWithError
|
||||
STA $C0CF ; soft switch 0x0F, hard-coded slot 4 for now
|
||||
RTS
|
||||
|
||||
ExitWithError:
|
||||
SEC ; the spec says carry is set on errors
|
||||
RTS
|
||||
|
||||
ServeMouse:
|
||||
PHA
|
||||
SEI ; disable interrupts while we find out about interrupts
|
||||
STA $C0CE ; soft switch 0x0E, hard-coded slot 4 for now
|
||||
LDX #$04
|
||||
LDA $6B8,X ; check what interrupts we serviced
|
||||
AND #$0E
|
||||
BNE _sm1 ; if we serviced any, leave carry clear
|
||||
SEC ; ... but set carry if we serviced none
|
||||
_sm1:
|
||||
PLA
|
||||
RTS
|
||||
|
||||
ReadMouse:
|
||||
STA $C0CB ; soft switch 0x0B, hard-coded slot 4 for now
|
||||
CLC
|
||||
RTS
|
||||
|
||||
ClearMouse:
|
||||
STA $C0CA ; soft switch 0x0A, hard-coded slot 4 for now
|
||||
CLC
|
||||
RTS
|
||||
|
||||
PosMouse:
|
||||
STA $C0C9 ; soft switch 0x09, hard-coded slot 4 for now
|
||||
CLC
|
||||
RTS
|
||||
|
||||
ClampMouse:
|
||||
CMP #$02
|
||||
BCS ExitWithError
|
||||
STA $C0CD ; soft switch 0x0D, hard-coded slot 4 for now
|
||||
CLC
|
||||
RTS
|
||||
|
||||
HomeMouse:
|
||||
STA $C0C8 ; soft switch 0x08, hard-coded slot 4 for now
|
||||
CLC
|
||||
RTS
|
||||
|
||||
InitMouse:
|
||||
STA $C0CC ; soft switch 0x0C, hard-coded slot 4 for now
|
||||
CLC
|
||||
RTS
|
||||
|
||||
.ORG $C4FB
|
||||
.byte $D6 ; magic identifier
|
||||
.ORG $C4FF
|
||||
.byte $01 ; version
|
||||
|
151
apple/mouserom.lst
Normal file
151
apple/mouserom.lst
Normal file
@ -0,0 +1,151 @@
|
||||
ca65 V2.18 - N/A
|
||||
Main file : mouserom.asm
|
||||
Current file: mouserom.asm
|
||||
|
||||
000000r 1 .ORG $C400
|
||||
00C400 1 Entry:
|
||||
00C400 1 2C 58 FF BIT $FF58 ; well-known RTS location - where RTS is $60
|
||||
00C403 1 70 1B BVS PREntry ; always branches (used to relocatably branch)
|
||||
00C405 1
|
||||
00C405 1 .ORG $C405
|
||||
00C405 1 INEntry:
|
||||
00C405 1 38 SEC
|
||||
00C406 1 90 18 BCC PREntry ; never happens, but has a magic ID byte @ C407 == 18
|
||||
00C408 1 B8 CLV
|
||||
00C409 1 50 15 BVC PREntry ; always branches
|
||||
00C40B 1
|
||||
00C40B 1 ;; lookup table
|
||||
00C40B 1 .ORG $C40B
|
||||
00C40B 1 01 .byte $01 ; magic identifier
|
||||
00C40C 1 20 .byte $20 ; magic identifier
|
||||
00C40D 1 68 .byte .LOBYTE(ExitWithError)
|
||||
00C40E 1 68 .byte .LOBYTE(ExitWithError)
|
||||
00C40F 1 68 .byte .LOBYTE(ExitWithError)
|
||||
00C410 1 68 .byte .LOBYTE(ExitWithError)
|
||||
00C411 1 00 .byte $00
|
||||
00C412 1 60 .byte .LOBYTE(SetMouse)
|
||||
00C413 1 6A .byte .LOBYTE(ServeMouse)
|
||||
00C414 1 7B .byte .LOBYTE(ReadMouse)
|
||||
00C415 1 80 .byte .LOBYTE(ClearMouse)
|
||||
00C416 1 85 .byte .LOBYTE(PosMouse)
|
||||
00C417 1 8A .byte .LOBYTE(ClampMouse)
|
||||
00C418 1 93 .byte .LOBYTE(HomeMouse)
|
||||
00C419 1 98 .byte .LOBYTE(InitMouse)
|
||||
00C41A 1 68 .byte .LOBYTE(ExitWithError)
|
||||
00C41B 1 68 .byte .LOBYTE(ExitWithError)
|
||||
00C41C 1 68 .byte .LOBYTE(ExitWithError)
|
||||
00C41D 1 68 .byte .LOBYTE(ExitWithError)
|
||||
00C41E 1 68 .byte .LOBYTE(ExitWithError)
|
||||
00C41F 1 68 .byte .LOBYTE(ExitWithError)
|
||||
00C420 1
|
||||
00C420 1 .ORG $C420
|
||||
00C420 1 PREntry:
|
||||
00C420 1 48 PHA ; save Y, X, A, S on the stack
|
||||
00C421 1 98 TYA
|
||||
00C422 1 48 PHA
|
||||
00C423 1 8A TXA
|
||||
00C424 1 48 PHA
|
||||
00C425 1 08 PHP
|
||||
00C426 1 78 SEI ; turn off interrupts while we find our address via the stack
|
||||
00C427 1 20 58 FF JSR $FF58 ; well-known RTS
|
||||
00C42A 1 BA TSX ; grab stack pointer
|
||||
00C42B 1 BD 00 01 LDA $0100,X ; inspect the stack frame
|
||||
00C42E 1 AA TAX ; now A and X hold the high byte of the return address to *us*
|
||||
00C42F 1 0A ASL ; A <<= 4
|
||||
00C430 1 0A ASL
|
||||
00C431 1 0A ASL
|
||||
00C432 1 0A ASL
|
||||
00C433 1 A8 TAY ; so Y = $n0, while X = $Cn for whatever slot we're in
|
||||
00C434 1 28 PLP ; pull Status off the stack
|
||||
00C435 1 50 0F BVC lastChance
|
||||
00C437 1 A5 38 LDA $38 ; We're being invoked in an IN# context, not a PR# context.
|
||||
00C439 1 D0 0D BNE PopAndReturn ; if $38/$39 don't point to us, then exit
|
||||
00C43B 1 8A TXA
|
||||
00C43C 1 45 39 EOR $39 ; is $39 == $Cn?
|
||||
00C43E 1 D0 08 BNE PopAndReturn
|
||||
00C440 1 InstallInHandler:
|
||||
00C440 1 A9 05 LDA #$05 ; Update IN handler to point to $Cn05 instead of $Cn00, so we know we've
|
||||
00C442 1 85 38 STA $38 ;initialized it
|
||||
00C444 1 D0 0B BNE INHandler
|
||||
00C446 1 lastChance:
|
||||
00C446 1 B0 09 BCS INHandler
|
||||
00C448 1 PopAndReturn:
|
||||
00C448 1 68 PLA
|
||||
00C449 1 AA TAX
|
||||
00C44A 1 68 PLA
|
||||
00C44B 1 EA NOP
|
||||
00C44C 1 68 PLA
|
||||
00C44D 1 99 80 C0 STA $c080,Y ; call soft-switch #0 for our slot to set mouse state
|
||||
00C450 1 60 RTS
|
||||
00C451 1 INHandler:
|
||||
00C451 1 99 81 C0 STA $c081,Y ; call soft-switch #1 for our slot to fill the keyboard buffer w/ mouse info
|
||||
00C454 1 68 PLA
|
||||
00C455 1 BD 38 06 LDA $0638,X ; pull the string length from this magic screen hole (X == $Cn)
|
||||
00C458 1 AA TAX ; which we'll return to the caller in X
|
||||
00C459 1 68 PLA ; restore Y
|
||||
00C45A 1 A8 TAY
|
||||
00C45B 1 68 PLA ; restore A
|
||||
00C45C 1 BD 00 02 LDA $200,X ; Grab the last character entered in to the buffer by the magic switch call
|
||||
00C45F 1 60 RTS
|
||||
00C460 1
|
||||
00C460 1 SetMouse:
|
||||
00C460 1 C9 0A CMP #$0A ; values >= 10 are invalid
|
||||
00C462 1 B0 04 BCS ExitWithError
|
||||
00C464 1 8D CF C0 STA $C0CF ; soft switch 0x0F, hard-coded slot 4 for now
|
||||
00C467 1 60 RTS
|
||||
00C468 1
|
||||
00C468 1 ExitWithError:
|
||||
00C468 1 38 SEC ; the spec says carry is set on errors
|
||||
00C469 1 60 RTS
|
||||
00C46A 1
|
||||
00C46A 1 ServeMouse:
|
||||
00C46A 1 48 PHA
|
||||
00C46B 1 78 SEI ; disable interrupts while we find out about interrupts
|
||||
00C46C 1 8D CE C0 STA $C0CE ; soft switch 0x0E, hard-coded slot 4 for now
|
||||
00C46F 1 A2 04 LDX #$04
|
||||
00C471 1 BD B8 06 LDA $6B8,X ; check what interrupts we serviced
|
||||
00C474 1 29 0E AND #$0E
|
||||
00C476 1 D0 01 BNE _sm1 ; if we serviced any, leave carry clear
|
||||
00C478 1 38 SEC ; ... but set carry if we serviced none
|
||||
00C479 1 _sm1:
|
||||
00C479 1 68 PLA
|
||||
00C47A 1 60 RTS
|
||||
00C47B 1
|
||||
00C47B 1 ReadMouse:
|
||||
00C47B 1 8D CB C0 STA $C0CB ; soft switch 0x0B, hard-coded slot 4 for now
|
||||
00C47E 1 18 CLC
|
||||
00C47F 1 60 RTS
|
||||
00C480 1
|
||||
00C480 1 ClearMouse:
|
||||
00C480 1 8D CA C0 STA $C0CA ; soft switch 0x0A, hard-coded slot 4 for now
|
||||
00C483 1 18 CLC
|
||||
00C484 1 60 RTS
|
||||
00C485 1
|
||||
00C485 1 PosMouse:
|
||||
00C485 1 8D C9 C0 STA $C0C9 ; soft switch 0x09, hard-coded slot 4 for now
|
||||
00C488 1 18 CLC
|
||||
00C489 1 60 RTS
|
||||
00C48A 1
|
||||
00C48A 1 ClampMouse:
|
||||
00C48A 1 C9 02 CMP #$02
|
||||
00C48C 1 B0 DA BCS ExitWithError
|
||||
00C48E 1 8D CD C0 STA $C0CD ; soft switch 0x0D, hard-coded slot 4 for now
|
||||
00C491 1 18 CLC
|
||||
00C492 1 60 RTS
|
||||
00C493 1
|
||||
00C493 1 HomeMouse:
|
||||
00C493 1 8D C8 C0 STA $C0C8 ; soft switch 0x08, hard-coded slot 4 for now
|
||||
00C496 1 18 CLC
|
||||
00C497 1 60 RTS
|
||||
00C498 1
|
||||
00C498 1 InitMouse:
|
||||
00C498 1 8D CC C0 STA $C0CC ; soft switch 0x0C, hard-coded slot 4 for now
|
||||
00C49B 1 18 CLC
|
||||
00C49C 1 60 RTS
|
||||
00C49D 1
|
||||
00C49D 1 .ORG $C4FB
|
||||
00C4FB 1 D6 .byte $D6 ; magic identifier
|
||||
00C4FC 1 .ORG $C4FF
|
||||
00C4FF 1 01 .byte $01 ; version
|
||||
00C500 1
|
||||
00C500 1
|
@ -7,16 +7,19 @@ my $romfile = shift || die "Must provide the path to an Apple //e ROM image";
|
||||
my $diskrom = shift || die "Must also provide the path to an Apple //e Disk II ROM image";
|
||||
my $parallelrom = shift || die "Must also provide the path to an Apple // parallel card ROM image";
|
||||
my $hdrom = shift || die "Must also provide the path to the AppleWin HDDRVR.BIN";
|
||||
my $mouserom = shift || die "Also need the path to a mouse.rom image";
|
||||
|
||||
validate($romfile, 32768, "an Apple //e ROM image");
|
||||
validate($diskrom, 256, "a DiskII ROM image");
|
||||
validate($parallelrom, 256, "a parallel card ROM image");
|
||||
validate($hdrom, 256, "HDDRVR.BIN from AppleWin");
|
||||
validate($mouserom, 256, "mouse.rom, compiled as part of Aiie");
|
||||
|
||||
dumpRom($romfile, "apple/applemmu-rom.h", "romData", 32768);
|
||||
dumpRom($diskrom, "apple/diskii-rom.h", "romData", 256);
|
||||
dumpRom($parallelrom, "apple/parallel-rom.h", "romData", 256);
|
||||
dumpRom($hdrom, "apple/hd32-rom.h", "romData", 256);
|
||||
dumpRom($mouserom, "apple/mouse-rom.h", "romData", 256);
|
||||
exit 0;
|
||||
|
||||
sub validate {
|
||||
|
Loading…
Reference in New Issue
Block a user