mirror of
https://github.com/blondie7575/MouseII.git
synced 2025-01-03 17:33:09 +00:00
Inital commit
This commit is contained in:
commit
a7943b50ec
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
mousedemo.lst
|
BIN
AppleCommander.jar
Normal file
BIN
AppleCommander.jar
Normal file
Binary file not shown.
32
Makefile
Normal file
32
Makefile
Normal file
@ -0,0 +1,32 @@
|
||||
#
|
||||
# Makefile
|
||||
# Mouse driver
|
||||
#
|
||||
# Created by Quinn Dunki on 7/14/15.
|
||||
# One Girl, One Laptop Productions
|
||||
# http://www.quinndunki.com
|
||||
# http://www.quinndunki.com/blondihacks
|
||||
#
|
||||
|
||||
|
||||
CL65=cl65
|
||||
AC=AppleCommander.jar
|
||||
ADDR=6000
|
||||
|
||||
PGM=mousedemo
|
||||
|
||||
all: $(PGM)
|
||||
|
||||
|
||||
$(PGM):
|
||||
@PATH=$(PATH):/usr/local/bin; $(CL65) -t apple2enh --start-addr $(ADDR) -l$(PGM).lst $(PGM).s
|
||||
java -jar $(AC) -d $(PGM).dsk $(PGM)
|
||||
java -jar $(AC) -p $(PGM).dsk $(PGM) BIN 0x$(ADDR) < $(PGM)
|
||||
rm -f $(PGM)
|
||||
rm -f $(PGM).o
|
||||
osascript V2Make.scpt $(PROJECT_DIR) $(PGM)
|
||||
|
||||
clean:
|
||||
rm -f $(PGM)
|
||||
rm -f $(PGM).o
|
||||
|
199
Mouse.xcodeproj/project.pbxproj
Normal file
199
Mouse.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,199 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
70355B941B55977F00D79881 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
|
||||
70355B951B55977F00D79881 /* mouse.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = mouse.s; sourceTree = "<group>"; };
|
||||
70355B961B55977F00D79881 /* mousedemo.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = mousedemo.s; sourceTree = "<group>"; };
|
||||
70355B971B55977F00D79881 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||
70355B981B5597EC00D79881 /* macros.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = macros.s; sourceTree = "<group>"; };
|
||||
70355B991B5597EC00D79881 /* switches.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = switches.s; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
70355B891B55975C00D79881 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
70355B971B55977F00D79881 /* README.md */,
|
||||
70355B941B55977F00D79881 /* Makefile */,
|
||||
70355B981B5597EC00D79881 /* macros.s */,
|
||||
70355B991B5597EC00D79881 /* switches.s */,
|
||||
70355B951B55977F00D79881 /* mouse.s */,
|
||||
70355B961B55977F00D79881 /* mousedemo.s */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXLegacyTarget section */
|
||||
70355B8E1B55975C00D79881 /* Mouse */ = {
|
||||
isa = PBXLegacyTarget;
|
||||
buildArgumentsString = "$(ACTION)";
|
||||
buildConfigurationList = 70355B911B55975C00D79881 /* Build configuration list for PBXLegacyTarget "Mouse" */;
|
||||
buildPhases = (
|
||||
);
|
||||
buildToolPath = /usr/bin/make;
|
||||
dependencies = (
|
||||
);
|
||||
name = Mouse;
|
||||
passBuildSettingsInEnvironment = 1;
|
||||
productName = Mouse;
|
||||
};
|
||||
/* End PBXLegacyTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
70355B8A1B55975C00D79881 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0640;
|
||||
ORGANIZATIONNAME = "Quinn Dunki";
|
||||
TargetAttributes = {
|
||||
70355B8E1B55975C00D79881 = {
|
||||
CreatedOnToolsVersion = 6.4;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 70355B8D1B55975C00D79881 /* Build configuration list for PBXProject "Mouse" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 70355B891B55975C00D79881;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
70355B8E1B55975C00D79881 /* Mouse */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
70355B8F1B55975C00D79881 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
70355B901B55975C00D79881 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
70355B921B55975C00D79881 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
DEBUGGING_SYMBOLS = YES;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
OTHER_CFLAGS = "";
|
||||
OTHER_LDFLAGS = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
70355B931B55975C00D79881 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
OTHER_CFLAGS = "";
|
||||
OTHER_LDFLAGS = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
70355B8D1B55975C00D79881 /* Build configuration list for PBXProject "Mouse" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
70355B8F1B55975C00D79881 /* Debug */,
|
||||
70355B901B55975C00D79881 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
70355B911B55975C00D79881 /* Build configuration list for PBXLegacyTarget "Mouse" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
70355B921B55975C00D79881 /* Debug */,
|
||||
70355B931B55975C00D79881 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 70355B8A1B55975C00D79881 /* Project object */;
|
||||
}
|
7
Mouse.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
Mouse.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:Mouse.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
BIN
Mouse.xcodeproj/project.xcworkspace/xcuserdata/qd.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
BIN
Mouse.xcodeproj/project.xcworkspace/xcuserdata/qd.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
Binary file not shown.
@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0640"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "70355B8E1B55975C00D79881"
|
||||
BuildableName = "Mouse"
|
||||
BlueprintName = "Mouse"
|
||||
ReferencedContainer = "container:Mouse.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "Debug">
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Debug"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
allowLocationSimulation = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "70355B8E1B55975C00D79881"
|
||||
BuildableName = "Mouse"
|
||||
BlueprintName = "Mouse"
|
||||
ReferencedContainer = "container:Mouse.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Release"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "70355B8E1B55975C00D79881"
|
||||
BuildableName = "Mouse"
|
||||
BlueprintName = "Mouse"
|
||||
ReferencedContainer = "container:Mouse.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>Mouse.xcscheme</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
<dict>
|
||||
<key>70355B8E1B55975C00D79881</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
19
README.md
Normal file
19
README.md
Normal file
@ -0,0 +1,19 @@
|
||||
*Mouse Driver for Apple II computers*
|
||||
|
||||
Supports the Apple //e Enhanced with a mouse card in any slot. Also supports Apple //c and //c+. May work on Apple IIgs as well.
|
||||
|
||||
|
||||
|
||||
<br><br><br>
|
||||
|
||||
Known issues
|
||||
------------
|
||||
|
||||
- Hitting Reset during a WeeGUI application will leave your Apple II in an unsafe state.
|
||||
- Calling WGEraseView on a view that shares border rendering with other views will require manually redrawing those views.
|
||||
- Included sample ASMDEMO has a slight tendancy to step on ProDOS's buffers. This is mostly harmless.
|
||||
|
||||
|
||||
To Do:
|
||||
------
|
||||
|
BIN
V2Make.scpt
Normal file
BIN
V2Make.scpt
Normal file
Binary file not shown.
120
macros.s
Normal file
120
macros.s
Normal file
@ -0,0 +1,120 @@
|
||||
;
|
||||
; macros.s
|
||||
; Generally useful macros for 6502 code
|
||||
;
|
||||
; Created by Quinn Dunki on 8/15/14.
|
||||
; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved.
|
||||
;
|
||||
|
||||
|
||||
; Macros
|
||||
|
||||
.macro SETSWITCH name ; Sets the named softswitch (assumes write method)
|
||||
sta name
|
||||
.endmacro
|
||||
|
||||
|
||||
.macro SAVE_AXY ; Saves all registers
|
||||
pha
|
||||
phx
|
||||
phy
|
||||
.endmacro
|
||||
|
||||
|
||||
.macro RESTORE_AXY ; Restores all registers
|
||||
ply
|
||||
plx
|
||||
pla
|
||||
.endmacro
|
||||
|
||||
|
||||
.macro SAVE_AY ; Saves accumulator and Y index
|
||||
pha
|
||||
phy
|
||||
.endmacro
|
||||
|
||||
|
||||
.macro RESTORE_AY ; Restores accumulator and Y index
|
||||
ply
|
||||
pla
|
||||
.endmacro
|
||||
|
||||
|
||||
.macro SAVE_AX ; Saves accumulator and X index
|
||||
pha
|
||||
phx
|
||||
.endmacro
|
||||
|
||||
|
||||
.macro RESTORE_AX ; Restores accumulator and X index
|
||||
plx
|
||||
pla
|
||||
.endmacro
|
||||
|
||||
|
||||
.macro SAVE_XY ; Saves X and Y index
|
||||
phx
|
||||
phy
|
||||
.endmacro
|
||||
|
||||
|
||||
.macro RESTORE_XY ; Restores X and Y index
|
||||
ply
|
||||
plx
|
||||
.endmacro
|
||||
|
||||
|
||||
.macro SAVE_ZPP ; Saves Zero Page locations we use for parameters
|
||||
lda PARAM0
|
||||
pha
|
||||
lda PARAM1
|
||||
pha
|
||||
lda PARAM2
|
||||
pha
|
||||
lda PARAM3
|
||||
pha
|
||||
.endmacro
|
||||
|
||||
|
||||
.macro RESTORE_ZPP ; Restores Zero Page locations we use for parameters
|
||||
pla
|
||||
sta PARAM3
|
||||
pla
|
||||
sta PARAM2
|
||||
pla
|
||||
sta PARAM1
|
||||
pla
|
||||
sta PARAM0
|
||||
.endmacro
|
||||
|
||||
|
||||
.macro SAVE_ZPS ; Saves Zero Page locations we use for scratch
|
||||
lda SCRATCH0
|
||||
pha
|
||||
lda SCRATCH1
|
||||
pha
|
||||
.endmacro
|
||||
|
||||
|
||||
.macro RESTORE_ZPS ; Restores Zero Page locations we use for scratch
|
||||
pla
|
||||
sta SCRATCH1
|
||||
pla
|
||||
sta SCRATCH0
|
||||
.endmacro
|
||||
|
||||
|
||||
.macro PARAM16 addr
|
||||
lda #<addr
|
||||
sta PARAM0
|
||||
lda #>addr
|
||||
sta PARAM1
|
||||
.endmacro
|
||||
|
||||
|
||||
.macro CALL16 func,addr
|
||||
PARAM16 addr
|
||||
jsr func
|
||||
.endmacro
|
||||
|
||||
|
505
mouse.s
Normal file
505
mouse.s
Normal file
@ -0,0 +1,505 @@
|
||||
;
|
||||
; mouse.s
|
||||
; Mouse driver for Apple //e Enhanced with mouse card (any slot), or Apple //c(+)
|
||||
;
|
||||
; Created by Quinn Dunki on 7/14/15.
|
||||
; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved.
|
||||
;
|
||||
|
||||
|
||||
.include "macros.s"
|
||||
.include "switches.s"
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Mouse clamping values. These are set to a convenient one-byte
|
||||
; range, but you can change to suit your application. If you
|
||||
; change them, also change the scaling math below (search for SCALING)
|
||||
; Hardware produces values 0-1023 in both dimensions if not clamped
|
||||
SCALE_X_IIE = $027f ; 640-1
|
||||
SCALE_Y_IIE = $02e0 ; 736
|
||||
|
||||
; //c tracks much slower, so smaller clamps and no scaling works better
|
||||
SCALE_X_IIC = $004f ; 8-1
|
||||
SCALE_Y_IIC = $0017 ; 24-1
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; ProDOS ROM entry points and constants
|
||||
;
|
||||
PRODOS_MLI = $bf00
|
||||
|
||||
ALLOC_INTERRUPT = $40
|
||||
DEALLOC_INTERRUPT = $41
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Mouse firmware ROM entry points and constants
|
||||
;
|
||||
|
||||
; These mouse firmware entry points are offsets from the firmware
|
||||
; entry point of the slot, and also indirect.
|
||||
SETMOUSE = $12
|
||||
SERVEMOUSE = $13
|
||||
READMOUSE = $14
|
||||
CLEARMOUSE = $15
|
||||
POSMOUSE = $16
|
||||
CLAMPMOUSE = $17
|
||||
HOMEMOUSE = $18
|
||||
INITMOUSE = $19
|
||||
|
||||
MOUSTAT = $0778 ; + Slot Num
|
||||
MOUSE_XL = $0478 ; + Slot Num
|
||||
MOUSE_XH = $0578 ; + Slot Num
|
||||
MOUSE_YL = $04f8 ; + Slot Num
|
||||
MOUSE_YH = $05f8 ; + Slot Num
|
||||
MOUSE_CLAMPL = $04f8 ; Upper mouse clamp (LSB). Slot independent.
|
||||
MOUSE_CLAMPH = $05f8 ; Upper mouse clamp (MSB). Slot independent.
|
||||
MOUSE_ZEROL = $0478 ; Zero value of mouse (LSB). Slot independent.
|
||||
MOUSE_ZEROH = $0578 ; Zero value of mouse (MSB). Slot independent.
|
||||
|
||||
MOUSTAT_MASK_BUTTONINT = %00000100
|
||||
MOUSTAT_MASK_MOVEINT = %00000010
|
||||
MOUSTAT_MASK_DOWN = %10000000
|
||||
MOUSTAT_MASK_WASDOWN = %01000000
|
||||
MOUSTAT_MASK_MOVED = %00100000
|
||||
|
||||
MOUSEMODE_OFF = $00 ; Mouse off
|
||||
MOUSEMODE_PASSIVE = $01 ; Passive mode (polling only)
|
||||
MOUSEMODE_MOVEINT = $03 ; Interrupts on movement
|
||||
MOUSEMODE_BUTINT = $05 ; Interrupts on button
|
||||
MOUSEMODE_COMBINT = $07 ; Interrupts on movement and button
|
||||
|
||||
|
||||
; Mouse firmware is all indirectly called, because
|
||||
; it moved around a lot in different Apple II ROM
|
||||
; versions. This macro helps abstracts this for us.
|
||||
.macro CALLMOUSE name
|
||||
ldx #name
|
||||
jsr WGCallMouse
|
||||
.endmacro
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; WGEnableMouse
|
||||
; Prepares the mouse for use
|
||||
;
|
||||
WGEnableMouse:
|
||||
pha
|
||||
|
||||
SETSWITCH PAGE2OFF
|
||||
|
||||
; Find slot number and calculate the various indirections needed
|
||||
jsr WGFindMouse
|
||||
bcs WGEnableMouse_Error
|
||||
|
||||
; Note if we're a //e or //c, because mouse tracking and interrupts are different
|
||||
lda $fbb3
|
||||
cmp #$06
|
||||
bne WGEnableMouse_Error ; II or II+? Sorry...
|
||||
lda $fbc0
|
||||
bne WGEnableMouse_IIe
|
||||
lda #1
|
||||
sta WG_APPLEIIC
|
||||
|
||||
WGEnableMouse_IIe:
|
||||
; Install our interrupt handler via ProDOS (play nice!)
|
||||
jsr PRODOS_MLI
|
||||
.byte ALLOC_INTERRUPT
|
||||
.addr WG_PRODOS_ALLOC
|
||||
bne WGEnableMouse_Error ; ProDOS will return here with Z clear on error
|
||||
|
||||
; Initialize the mouse
|
||||
stz WG_MOUSEPOS_X
|
||||
stz WG_MOUSEPOS_Y
|
||||
stz WG_MOUSEBG
|
||||
|
||||
CALLMOUSE INITMOUSE
|
||||
bcs WGEnableMouse_Error ; Firmware sets carry if mouse is not available
|
||||
|
||||
CALLMOUSE CLEARMOUSE
|
||||
|
||||
lda #MOUSEMODE_COMBINT ; Enable combination interrupt mode
|
||||
CALLMOUSE SETMOUSE
|
||||
|
||||
; Set the mouse's zero postion to (1,1), since we're in text screen space
|
||||
stz MOUSE_ZEROH
|
||||
lda #0
|
||||
sta MOUSE_ZEROL
|
||||
lda #1
|
||||
CALLMOUSE CLAMPMOUSE
|
||||
lda #0
|
||||
CALLMOUSE CLAMPMOUSE
|
||||
|
||||
; Scale the mouse's range into something easy to do math with,
|
||||
; while retaining as much range of motion and precision as possible
|
||||
lda WG_APPLEIIC
|
||||
bne WGEnableMouse_ConfigIIc ; Sorry //c, no scaling for you
|
||||
|
||||
lda #<SCALE_X_IIE
|
||||
sta MOUSE_CLAMPL
|
||||
lda #>SCALE_X_IIE
|
||||
sta MOUSE_CLAMPH
|
||||
lda #0
|
||||
CALLMOUSE CLAMPMOUSE
|
||||
|
||||
lda #<SCALE_Y_IIE
|
||||
sta MOUSE_CLAMPL
|
||||
lda #>SCALE_Y_IIE
|
||||
sta MOUSE_CLAMPH
|
||||
lda #1
|
||||
CALLMOUSE CLAMPMOUSE
|
||||
bra WGEnableMouse_Activate
|
||||
|
||||
WGEnableMouse_Error:
|
||||
stz WG_MOUSEACTIVE
|
||||
|
||||
WGEnableMouse_done: ; Exit point here for branch range
|
||||
pla
|
||||
rts
|
||||
|
||||
WGEnableMouse_ConfigIIc: ; //c's tracking is weird. Need to clamp to a much smaller range
|
||||
lda #<SCALE_X_IIC
|
||||
sta MOUSE_CLAMPL
|
||||
lda #>SCALE_X_IIC
|
||||
sta MOUSE_CLAMPH
|
||||
lda #0
|
||||
CALLMOUSE CLAMPMOUSE
|
||||
|
||||
lda #<SCALE_Y_IIC
|
||||
sta MOUSE_CLAMPL
|
||||
lda #>SCALE_Y_IIC
|
||||
sta MOUSE_CLAMPH
|
||||
lda #1
|
||||
CALLMOUSE CLAMPMOUSE
|
||||
|
||||
WGEnableMouse_Activate:
|
||||
lda #1
|
||||
sta WG_MOUSEACTIVE
|
||||
|
||||
cli ; Once all setup is done, it's safe to enable interrupts
|
||||
bra WGEnableMouse_done
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; WGDisableMouse
|
||||
; Shuts off the mouse when we're done with it
|
||||
;
|
||||
WGDisableMouse:
|
||||
pha
|
||||
|
||||
SETSWITCH PAGE2OFF
|
||||
|
||||
lda WG_MOUSEACTIVE ; Never activated the mouse
|
||||
beq WGDisableMouse_done
|
||||
|
||||
lda MOUSEMODE_OFF
|
||||
CALLMOUSE SETMOUSE
|
||||
|
||||
stz WG_MOUSEACTIVE
|
||||
|
||||
; Remove our interrupt handler via ProDOS (done playing nice!)
|
||||
lda WG_PRODOS_ALLOC+1 ; Copy interrupt ID that ProDOS gave us
|
||||
sta WG_PRODOS_DEALLOC+1
|
||||
|
||||
jsr PRODOS_MLI
|
||||
.byte DEALLOC_INTERRUPT
|
||||
.addr WG_PRODOS_DEALLOC
|
||||
|
||||
jsr WGUndrawPointer ; Be nice if we're disabled during a program
|
||||
|
||||
WGDisableMouse_done:
|
||||
pla
|
||||
rts
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; WGCallMouse
|
||||
; Calls a mouse firmware routine. Here's where we handle all
|
||||
; the layers of indirection needed to call mouse firmware. The
|
||||
; firmware moved in ROM several times over the life of the
|
||||
; Apple II, so it's kind of a hassle to call it.
|
||||
; X: Name of routine (firmware offset constant)
|
||||
; Side effects: Clobbers all registers
|
||||
WGCallMouse:
|
||||
stx WGCallMouse+4 ; Use self-modifying code to smooth out some indirection
|
||||
|
||||
; This load address is overwritten by the above code, AND by the mouse set
|
||||
; up code, to make sure we have the right slot entry point and firmware
|
||||
; offset
|
||||
ldx $c400 ; Self-modifying code!
|
||||
stx WG_MOUSE_JUMPL ; Get low byte of final jump from firmware
|
||||
|
||||
php ; Note that mouse firmware is not re-entrant,
|
||||
sei ; so we must disable interrupts inside them
|
||||
|
||||
jsr WGCallMouse_redirect
|
||||
plp ; Restore interrupts to previous state
|
||||
rts
|
||||
|
||||
WGCallMouse_redirect:
|
||||
ldx WG_MOUSE_JUMPH
|
||||
ldy WG_MOUSE_SLOTSHIFTED
|
||||
jmp (WG_MOUSE_JUMPL)
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; WGFindMouse
|
||||
; Figures out which slot (//e) or port (//c) the mouse is in.
|
||||
; It moved around a lot over the years. Sets it to 0 if no mouse
|
||||
; could be found
|
||||
; OUT C: Set if no mouse could be found
|
||||
WGFindMouse:
|
||||
SAVE_AX
|
||||
|
||||
ldx #7
|
||||
|
||||
WGFindMouse_loop:
|
||||
txa ; Compute slot firmware locations for this loop
|
||||
ora #$c0
|
||||
sta WGFindMouse_loopModify+2 ; Self-modifying code!
|
||||
sta WGFindMouse_loopModify+9
|
||||
sta WGFindMouse_loopModify+16
|
||||
sta WGFindMouse_loopModify+23
|
||||
sta WGFindMouse_loopModify+30
|
||||
|
||||
WGFindMouse_loopModify:
|
||||
; Check for the magic 5-byte pattern that gives away the mouse card
|
||||
lda $c005 ; These addresses are modified in place on
|
||||
cmp #$38 ; each loop iteration
|
||||
bne WGFindMouse_nextSlot
|
||||
lda $c007
|
||||
cmp #$18
|
||||
bne WGFindMouse_nextSlot
|
||||
lda $c00b
|
||||
cmp #$01
|
||||
bne WGFindMouse_nextSlot
|
||||
lda $c00c
|
||||
cmp #$20
|
||||
bne WGFindMouse_nextSlot
|
||||
lda $c0fb
|
||||
cmp #$d6
|
||||
bne WGFindMouse_nextSlot
|
||||
bra WGFindMouse_found
|
||||
|
||||
WGFindMouse_nextSlot:
|
||||
dex
|
||||
bmi WGFindMouse_none
|
||||
bra WGFindMouse_loop
|
||||
|
||||
WGFindMouse_found:
|
||||
; Found it! Now configure all our indirection lookups
|
||||
stx WG_MOUSE_SLOT
|
||||
lda #$c0
|
||||
ora WG_MOUSE_SLOT
|
||||
sta WG_MOUSE_JUMPH
|
||||
sta WGCallMouse+5 ; Self-modifying code!
|
||||
txa
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
sta WG_MOUSE_SLOTSHIFTED
|
||||
clc
|
||||
bra WGFindMouse_done
|
||||
|
||||
WGFindMouse_none:
|
||||
stz WG_MOUSE_SLOT
|
||||
sec
|
||||
|
||||
WGFindMouse_done:
|
||||
RESTORE_AX
|
||||
rts
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; WGMouseInterruptHandler
|
||||
; Handles interrupts that may be related to the mouse
|
||||
; This is a ProDOS-compliant interrupt handling routine, and
|
||||
; should be installed and removed via ProDOS as needed.
|
||||
;
|
||||
; IMPORTANT: This routine is NOT MLI-reentrant, which means MLI
|
||||
; calls can NOT be made within this handler. See page 108 of the
|
||||
; ProDOS 8 Technical Reference Manual if this feature needs to be
|
||||
; added.
|
||||
;
|
||||
WGMouseInterruptHandler:
|
||||
cld ; ProDOS interrupt handlers must open with this
|
||||
SAVE_AXY
|
||||
|
||||
CALLMOUSE SERVEMOUSE
|
||||
bcs WGMouseInterruptHandler_disregard
|
||||
|
||||
php
|
||||
sei
|
||||
|
||||
lda PAGE2 ; Need to preserve text bank, because we may interrupt rendering
|
||||
pha
|
||||
SETSWITCH PAGE2OFF
|
||||
|
||||
ldx WG_MOUSE_SLOT
|
||||
lda MOUSTAT,x ; Check interrupt status bits first, because READMOUSE clears them
|
||||
and #MOUSTAT_MASK_BUTTONINT
|
||||
bne WGMouseInterruptHandler_button
|
||||
|
||||
jsr WGUndrawPointer ; Erase the old mouse pointer
|
||||
|
||||
; Read the mouse state. Note that interrupts need to remain
|
||||
; off until after the data is copied.
|
||||
CALLMOUSE READMOUSE
|
||||
|
||||
ldx WG_MOUSE_SLOT
|
||||
lda MOUSTAT,x ; Movement/button status bits are now valid
|
||||
sta WG_MOUSE_STAT
|
||||
|
||||
lda WG_APPLEIIC
|
||||
bne WGMouseInterruptHandler_IIc
|
||||
|
||||
; Read mouse position and transform it into screen space
|
||||
; SCALING: If you change the clamps, change this division from
|
||||
; 1024 to match your new values.
|
||||
lsr MOUSE_XH,x
|
||||
ror MOUSE_XL,x
|
||||
lsr MOUSE_XH,x
|
||||
ror MOUSE_XL,x
|
||||
lsr MOUSE_XH,x
|
||||
ror MOUSE_XL,x
|
||||
|
||||
lda MOUSE_XL,x
|
||||
sta WG_MOUSEPOS_X
|
||||
|
||||
lsr MOUSE_YH,x
|
||||
ror MOUSE_YL,x
|
||||
lsr MOUSE_YH,x
|
||||
ror MOUSE_YL,x
|
||||
lsr MOUSE_YH,x
|
||||
ror MOUSE_YL,x
|
||||
lsr MOUSE_YH,x
|
||||
ror MOUSE_YL,x
|
||||
lsr MOUSE_YH,x
|
||||
ror MOUSE_YL,x
|
||||
|
||||
lda MOUSE_YL,x
|
||||
sta WG_MOUSEPOS_Y
|
||||
bra WGMouseInterruptHandler_draw
|
||||
|
||||
WGMouseInterruptHandler_IIc: ; IIc tracks much slower, so don't scale
|
||||
lda MOUSE_XL,x
|
||||
sta WG_MOUSEPOS_X
|
||||
lda MOUSE_YL,x
|
||||
sta WG_MOUSEPOS_Y
|
||||
|
||||
WGMouseInterruptHandler_draw:
|
||||
jsr WGDrawPointer ; Redraw the pointer
|
||||
bra WGMouseInterruptHandler_intDone
|
||||
|
||||
WGMouseInterruptHandler_disregard:
|
||||
; Carry will still be set here, to notify ProDOS that
|
||||
; this interrupt was not ours
|
||||
RESTORE_AXY
|
||||
rts
|
||||
|
||||
WGMouseInterruptHandler_button:
|
||||
CALLMOUSE READMOUSE
|
||||
ldx WG_MOUSE_SLOT
|
||||
lda MOUSTAT,x ; Movement/button status bits are now valid
|
||||
sta WG_MOUSE_STAT
|
||||
|
||||
bit WG_MOUSE_STAT ; Check for rising edge of button state
|
||||
bpl WGMouseInterruptHandler_intDone
|
||||
bvs WGMouseInterruptHandler_intDone ; Held, so ignore (//c only, but more elegant code to leave in for both)
|
||||
|
||||
; Button went down, so make a note of location for later
|
||||
lda WG_MOUSEPOS_X
|
||||
sta WG_MOUSECLICK_X
|
||||
lda WG_MOUSEPOS_Y
|
||||
sta WG_MOUSECLICK_Y
|
||||
|
||||
WGMouseInterruptHandler_intDone:
|
||||
pla ; Restore text bank
|
||||
bpl WGMouseInterruptHandler_intDoneBankOff
|
||||
SETSWITCH PAGE2ON
|
||||
bra WGMouseInterruptHandler_done
|
||||
|
||||
WGMouseInterruptHandler_intDoneBankOff:
|
||||
SETSWITCH PAGE2OFF
|
||||
|
||||
WGMouseInterruptHandler_done:
|
||||
RESTORE_AXY
|
||||
|
||||
plp
|
||||
clc ; Notify ProDOS this was our interrupt
|
||||
rts
|
||||
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; WGUndrawPointer
|
||||
; Unplots the mouse pointer at current location
|
||||
; Stub for your use
|
||||
;
|
||||
WGUndrawPointer:
|
||||
rts
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; WGDrawPointer
|
||||
; Plots the mouse pointer at current location
|
||||
; Stub for your use
|
||||
;
|
||||
WGDrawPointer:
|
||||
rts
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Mouse API state
|
||||
;
|
||||
|
||||
; Useful things you can poll in your code:
|
||||
WG_MOUSEACTIVE:
|
||||
.byte 0
|
||||
WG_MOUSEPOS_X:
|
||||
.byte 39
|
||||
WG_MOUSEPOS_Y:
|
||||
.byte 11
|
||||
WG_MOUSECLICK_X:
|
||||
.byte $ff
|
||||
WG_MOUSECLICK_Y:
|
||||
.byte 0
|
||||
|
||||
|
||||
; Internal state for the driver (no touchy!)
|
||||
WG_MOUSE_STAT:
|
||||
.byte 0
|
||||
WG_MOUSEBG:
|
||||
.byte 0
|
||||
WG_APPLEIIC:
|
||||
.byte 0
|
||||
WG_MOUSE_JUMPL:
|
||||
.byte 0
|
||||
WG_MOUSE_JUMPH:
|
||||
.byte 0
|
||||
WG_MOUSE_SLOT:
|
||||
.byte 0
|
||||
WG_MOUSE_SLOTSHIFTED:
|
||||
.byte 0
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; ProDOS system call parameter blocks
|
||||
;
|
||||
WG_PRODOS_ALLOC:
|
||||
.byte 2
|
||||
.byte 0 ; ProDOS returns an ID number for the interrupt here
|
||||
.addr WGMouseInterruptHandler
|
||||
|
||||
WG_PRODOS_DEALLOC:
|
||||
.byte 1
|
||||
.byte 0 ; To be filled with ProDOS ID number
|
||||
|
||||
|
BIN
mousedemo.dsk
Normal file
BIN
mousedemo.dsk
Normal file
Binary file not shown.
74
mousedemo.s
Normal file
74
mousedemo.s
Normal file
@ -0,0 +1,74 @@
|
||||
;
|
||||
; mousedemo.s
|
||||
; Mouse driver sample application
|
||||
;
|
||||
; Created by Quinn Dunki on 7/14/15.
|
||||
; Copyright (c) 2015 One Girl, One Laptop Productions. All rights reserved.
|
||||
;
|
||||
|
||||
|
||||
.org $6000
|
||||
|
||||
COUT = $fded
|
||||
PRBYTE = $fdda
|
||||
|
||||
|
||||
main: ; BRUN lands here
|
||||
|
||||
jsr WGEnableMouse
|
||||
|
||||
loop:
|
||||
; Print current mouse position
|
||||
lda #'X' + $80
|
||||
jsr COUT
|
||||
lda #'=' + $80
|
||||
jsr COUT
|
||||
|
||||
lda WG_MOUSEPOS_X
|
||||
jsr PRBYTE
|
||||
|
||||
lda #' ' + $80
|
||||
jsr COUT
|
||||
lda #'Y' + $80
|
||||
jsr COUT
|
||||
lda #'=' + $80
|
||||
jsr COUT
|
||||
|
||||
lda WG_MOUSEPOS_Y
|
||||
jsr PRBYTE
|
||||
|
||||
lda WG_MOUSECLICK_X
|
||||
bmi lineDone
|
||||
lda #' ' + $80
|
||||
jsr COUT
|
||||
lda #'!' + $80
|
||||
jsr COUT
|
||||
lda #$ff
|
||||
sta WG_MOUSECLICK_X
|
||||
|
||||
lineDone:
|
||||
lda #13 + $80
|
||||
jsr COUT
|
||||
|
||||
; Check for any key to quit
|
||||
lda KBD
|
||||
bpl loop ; No key pending
|
||||
|
||||
; Clean up and return to BASIC
|
||||
sta KBDSTRB ; Clear strobe
|
||||
|
||||
jsr WGDisableMouse
|
||||
rts
|
||||
|
||||
|
||||
|
||||
.include "mouse.s"
|
||||
|
||||
|
||||
; Suppress some linker warnings - Must be the last thing in the file
|
||||
; This is because Quinn doesn't really know how to use ca65 properly
|
||||
.SEGMENT "ZPSAVE"
|
||||
.SEGMENT "EXEHDR"
|
||||
.SEGMENT "STARTUP"
|
||||
.SEGMENT "INIT"
|
||||
.SEGMENT "LOWCODE"
|
32
switches.s
Normal file
32
switches.s
Normal file
@ -0,0 +1,32 @@
|
||||
;
|
||||
; switches.s
|
||||
; Softswitches for Apple ][
|
||||
;
|
||||
; Created by Quinn Dunki on 8/15/14.
|
||||
; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved.
|
||||
;
|
||||
|
||||
|
||||
PAGE2 = $c01c ; Read bit 7
|
||||
PAGE2OFF = $c054 ; Read/Write
|
||||
PAGE2ON = $c055 ; Read/Write
|
||||
|
||||
COL80 = $c01f ; Read bit 7
|
||||
COL80OFF = $c00c ; Write
|
||||
COL80ON = $c00d ; Write
|
||||
|
||||
STORE80 = $c018 ; Read bit 7
|
||||
STORE80OFF = $c000 ; Write
|
||||
STORE80ON = $c001 ; Write
|
||||
|
||||
TEXT = $c01a ; Read bit 7
|
||||
TEXTOFF = $c050 ; Read/Write
|
||||
TEXTON = $C051 ; Read/Write
|
||||
|
||||
KBD = $c000 ; Read
|
||||
KBDSTRB = $c010 ; Read/Write
|
||||
|
||||
RDVBLBAR = $C019 ; Read bit 7 (active low)
|
||||
|
||||
OURCH = $057b ; 80 col cursor position (H)
|
||||
OURCV = $05fb ; 80 col cursor position (V)
|
Loading…
Reference in New Issue
Block a user