The mouse reference is a pointer. If it's NULL, the driver uses a default. If it's non-NULL, then it points to a function that the driver can call. That function will adjust the driver's calibration value. It could ask the user to adjust the pen; or, it could read a file that holds a value from a previous calibration.
Application writers can choose how it's done: a function that's provided by the library, a custom function, or nothing.
/* */
/* */
/* */
-/* (C) 2003-2011, Ullrich von Bassewitz */
+/* (C) 2003-2013, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
*/
};
+
+
+/*****************************************************************************/
+/* Declarations */
+/*****************************************************************************/
+
+
+
/* The default mouse callbacks */
extern const struct mouse_callbacks mouse_def_callbacks;
/* The address of the static standard mouse driver for a platform */
extern const void mouse_static_stddrv[];
+/* A program optionally can set this pointer to a function that gives
+** a calibration value to a driver. If this pointer isn't NULL,
+** then a driver that wants a value can call that function.
+** mouse_adjuster must be set before the driver is installed.
+*/
+extern void __fastcall__ (*mouse_adjuster) (unsigned char *pValue);
+
/*****************************************************************************/
unsigned char __fastcall__ mouse_install (const struct mouse_callbacks* c,
void* driver);
-/* Install an already loaded driver. Returns an error code. */
+/* Install an already loaded driver. Return an error code. */
unsigned char mouse_uninstall (void);
-/* Uninstall the currently loaded driver. Returns an error code. */
+/* Uninstall the currently loaded driver. Return an error code. */
const char* __fastcall__ mouse_geterrormsg (unsigned char code);
/* Get an error message describing the error in code. */
*/
void mouse_show (void);
-/* Show the mouse. See mouse_hide for more information. */
+/* Show the mouse. See mouse_hide() for more information. */
void __fastcall__ mouse_setbox (const struct mouse_box* box);
/* Set the bounding box for the mouse pointer movement. The mouse X and Y
*/
void __fastcall__ mouse_pos (struct mouse_pos* pos);
-/* Return the current mouse position */
+/* Return the current mouse position. */
void __fastcall__ mouse_info (struct mouse_info* info);
-/* Return the state of the mouse buttons and the position of the mouse */
+/* Return the state of the mouse buttons and the position of the mouse. */
unsigned char __fastcall__ mouse_ioctl (unsigned char code, void* data);
-/* Call the driver specific ioctl function. NON PORTABLE! Returns an error
- * code.
+/* Call the driver-specific ioctl function. Return an error code.
+ * NON-PORTABLE!
+ */
+
+void __fastcall__ pen_calibrate (unsigned char *XOffset);
+/* Ask the user to help to calibrate a lightpen. Changes the screen!
+ * A pointer to this function can be put into mouse_adjuster.
+ */
+
+void __fastcall__ pen_adjust (const char *filename);
+/* Get a lightpen calibration value from a file if it exists. Otherwise, call
+ * pen_calibrate() to create a value; then, write it into a file, so that it
+ * will be available at the next time that the lightpen is used.
+ * Might change the screen.
+ * pen_adjust() is optional; if you want to use its feature,
+ * then it must be called before a driver is installed.
+ * Note: This function merely saves the file-name pointer, and sets
+ * the mouse_adjuster pointer. The file will be read only when a driver
+ * is installed, and only if that driver wants to be calibrated.
*/
;
-; Oliver Schmidt, 2013-05-31
+; 2013-05-31, Oliver Schmidt
+; 2013-06-11, Greg King
;
- .export em_libref, joy_libref, mouse_libref, ser_libref, tgi_libref
+ .export em_libref
+ .export joy_libref
+; .export mouse_libref
+ .export ser_libref
+ .export tgi_libref
+
.import _exit
em_libref := _exit
joy_libref := _exit
-mouse_libref := _exit
+;mouse_libref := _exit
ser_libref := _exit
tgi_libref := _exit
;
; Driver for the Inkwell Systems 170-C and 184-C lightpens.
;
-; 2013-06-03, Greg King
+; 2013-06-17, Greg King
;
.include "zeropage.inc"
.include "c128.inc"
.macpack generic
- .macpack cbm
; ------------------------------------------------------------------------
; Header. Includes jump table.
; Library reference
- .addr $0000
+LIBREF: .addr $0000
; Jump table
XSIZE = 40
YSIZE = 25
-SCREEN_HEIGHT = YSIZE * 8
SCREEN_WIDTH = XSIZE * 8
-SCREEN_ZONE = YSIZE / 4 * XSIZE
-
-SCREEN := $0400
-COLOR_RAM := $D800
-
-PRIMM := $FF7D ; Print immediate
+SCREEN_HEIGHT = YSIZE * 8
;----------------------------------------------------------------------------
; written with the least effort in the SETBOX and GETBOX routines; so, don't
; re-order them.
+.rodata
+
+; Default values for below variables
+; (We use ".proc" because we want to define both a label and a scope.)
+
+.proc DefVars
+ .word 0 ; XMin
+ .word 0 ; YMin
+ .word SCREEN_WIDTH - 1 ; XMax
+ .word SCREEN_HEIGHT - 1 ; YMax
+ .byte %00000000 ; Buttons
+.endproc
+
.bss
Vars:
XPos: .res 2 ; Current lightpen position, X
YPos: .res 2 ; Current lightpen position, Y
-OldPenX: .res 1 ; Old HW-counter values
+OldPenX: .res 1 ; Previous HW-counter values
OldPenY: .res 1
INIT_save: .res 1
.data
-; Start with an average offset.
-
-XOffset: .byte 48 / 2 ; Calibration offset, for X position
-
-.rodata
+; Default Inkwell calibration.
+; The first number is the width of the left border;
+; the second number is the actual calibration value.
-; Default values for above variables
-; (We use ".proc" because we want to define both a label and a scope.)
+XOffset: .byte (24 + 24) / 2 ; x-offset
-.proc DefVars
- .word 0 ; XMin
- .word 0 ; YMin
- .word SCREEN_WIDTH - 1 ; XMax
- .word SCREEN_HEIGHT - 1 ; YMax
- .byte %00000000 ; Buttons
-.endproc
-
-.proc Command1
- scrcode "Adjust by clicking on line."
-.endproc
-.proc Command2
- scrcode "Finish by clicking off box."
-.endproc
+; Jump to a function that puts a new calibration value into XOffset.
+Calibrate: jmp $0000
.code
lda #%11000000
sta INIT_STATUS
- bit MODE
- bpl @L7 ; Already 40 columns
- jsr PRIMM
- .byte $1B, 'x' ; Toggle the screen-width mode
- .byte $0E, $00 ; Switch to lower-case chars.
-
; Initiate variables. Just copy the default stuff over.
-@L7: sei
ldx #.sizeof (DefVars) - 1
@L0: lda DefVars,x
sta Vars,x
ldy VIC_LPEN_Y
stx OldPenX
sty OldPenY
- cli
-
-; There is a delay between when the VIC sends its signal, and when the display
-; shows that signal. There is another delay between the display and when
-; the lightpen says that it saw that signal. Each display and pen is different.
-; Therefore, this driver must be calibrated to them. A white box is painted on
-; the screen; and, a line is drawn down the middle of it. When the user clicks
-; on that line, the difference between its position and where the VIC thinks
-; that the pen is pointing becomes an offset that is subtracted from what the
-; VIC sees.
-
- lda VIC_BG_COLOR0
- ldx #6 ; Blue screen
- stx VIC_BG_COLOR0
- pha
- jsr CLRSCR
-
- ldy #.sizeof (Command2) - 1
-@L2: lda Command2,y
- sta SCREEN + SCREEN_ZONE * 2 + XSIZE * 3 + (XSIZE - .sizeof (Command2)) / 2,y
- lda #15 ; Light gray text
- sta COLOR_RAM + SCREEN_ZONE * 2 + XSIZE * 3 + (XSIZE - .sizeof (Command1)) / 2,y
- dey
- bpl @L2
- ldy #.sizeof (Command1) - 1
-@L1: lda Command1,y
- sta SCREEN + SCREEN_ZONE * 2 + XSIZE * 1 + (XSIZE - .sizeof (Command1)) / 2,y
- lda #15 ; Light gray text
- sta COLOR_RAM + SCREEN_ZONE * 2 + XSIZE * 1 + (XSIZE - .sizeof (Command1)) / 2,y
- dey
- bpl @L1
-
- ldx #SCREEN_ZONE
-@L3: lda #$80 | $20 ; Reversed space screen-code
- sta SCREEN + SCREEN_ZONE - 1,x
- lda #15 ; Light gray box
- sta COLOR_RAM + SCREEN_ZONE - 1,x
- dex
- bnz @L3
-
- ldy #$80 | $5d ; Reversed vertical-bar screen-code
- .repeat 4, L
- sty SCREEN + SCREEN_ZONE + (L + 1) * XSIZE + XSIZE / 2
- .endrep
-
- lda VIC_SPR0_COLOR
- ldx #12 ; Medium gray pointer
- stx VIC_SPR0_COLOR
- pha
- jsr SHOW
-
- lda #<(SCREEN_HEIGHT / 4 / 2)
- ldx #>(SCREEN_HEIGHT / 4 / 2)
- jsr PutCursor
-
-; Wait for the main button to be released.
-
-@L4: lda Buttons
- bnz @L4
-
-; Wait for the main button to be pressed.
-
-@L5: lda Buttons
- bze @L5
-; Find out if the pen is on or off the box.
+; Call a calibration function through the library-reference.
- ldy YPos
- ldx YPos+1
- txa
- cpy #<(YSIZE / 4 * 1 * 8)
- sbc #>(YSIZE / 4 * 1 * 8)
- bmi @L6 ; Above box
- txa
- cpy #<(YSIZE / 4 * 2 * 8)
- sbc #>(YSIZE / 4 * 2 * 8)
- bpl @L6 ; Below box
-
-; The pen is on the box; adjust the offset.
-
- lda OldPenX
- sub #(XSIZE * 8 / 2 + 8/2) / 2
- sta XOffset
- sta OldPenX ; Make IRQ update X co-ordinate
- jmp @L4
-
-; Wait for the main button to be released.
-
-@L6: lda Buttons
- bnz @L6
-
- lda XOffset ; Tell test program about calibration
- sta $3ff
-
- pla
- sta VIC_SPR0_COLOR
- pla
- sta VIC_BG_COLOR0
- jsr CLRSCR
-
-; Be sure the lightpen cursor is invisible and at the default location.
+ lda LIBREF
+ ldx LIBREF+1
+ sta ptr1 ; Point to mouse_adjuster
+ stx ptr1+1
+ ldy #0
+ lda (ptr1),y
+ sta Calibrate+1 ; Point to function
+ iny
+ lda (ptr1),y
+ sta Calibrate+2
+ ora Calibrate+1 ; Don't call pointer if it's NULL
+ bze @L1
+ lda #<XOffset ; Function will set this variable
+ ldx #>XOffset
+ jsr Calibrate
+
+; Be sure that the lightpen cursor is invisible and at the default location.
; It needs to be done here because the lightpen interrupt handler doesn't
; set the lightpen position if it hasn't changed.
- jsr HIDE
+@L1: jsr CHIDE
lda #<(SCREEN_HEIGHT / 2)
ldx #>(SCREEN_HEIGHT / 2)
-PutCursor:
- sei
jsr MoveY
lda #<(SCREEN_WIDTH / 2)
ldx #>(SCREEN_WIDTH / 2)
jsr MoveX
- cli
; Done, return zero.
beq @SkipX
sta OldPenX
-; Adjust the co-ordinate by the calibration offset.
+; Adjust the value by the calibration offset.
sub XOffset
-; Calculate the new X co-ordinate (--> .AY --> .XY).
+; Calculate the new X co-ordinate.
; The VIC-II register is eight bits; but, the screen co-ordinate is nine bits.
; Therefore, the VIC-II number is doubled. Then, it points to every other pixel;
; but, it can reach across the screen.
tay ; Remember low byte
lda #>0
rol a
- tax
+ tax ; Remember high byte
; Limit the X co-ordinate to the bounding box.
--- /dev/null
+;\r
+; Pointer for library references by device drivers.\r
+;\r
+; 2013-06-23, Greg King\r
+;\r
+\r
+ .export mouse_libref, _mouse_adjuster\r
+\r
+ .data\r
+\r
+mouse_libref: ; generic label for mouse-kernel\r
+\r
+; A program optionally can set this pointer to a function that gives\r
+; a calibration value to a driver. If this pointer isn't NULL,\r
+; then a driver that wants a value can call that function.\r
+;\r
+; The function might read a value from a file; or, it might ask the user\r
+; to help calibrate the driver.\r
+;\r
+; void __fastcall__ (*mouse_adjuster)(unsigned char *) = NULL;\r
+;\r
+_mouse_adjuster:\r
+ .addr $0000\r
--- /dev/null
+/*\r
+** Calibrate lightpen drivers to the current video hardware.\r
+**\r
+** 2013-06-17, Greg King\r
+**\r
+*/\r
+\r
+\r
+#include <conio.h>\r
+#include <mouse.h>\r
+\r
+\r
+#define COMMAND1 "Adjust by clicking on line."\r
+#define COMMAND2 "Finish by clicking off bar."\r
+\r
+\r
+/* There is a delay between when the VIC sends its signal, and when the display\r
+** shows that signal. There is another delay between the display and when the\r
+** lightpen says that it saw that signal. Each display and pen is different.\r
+** Therefore, the driver must be calibrated to them. A white bar is painted on\r
+** the screen; and, a line is drawn down the middle of it. When the user\r
+** clicks on that line, the difference between its position and where the VIC\r
+** thinks that the pen is pointing becomes an offset that is subtracted from\r
+** what the VIC sees.\r
+*/\r
+void __fastcall__ pen_calibrate (unsigned char *XOffset)\r
+{\r
+ unsigned char oldBg = bgcolor (COLOR_BLUE);\r
+ unsigned char oldText = textcolor (COLOR_GRAY3);\r
+ unsigned char oldRev = revers (1);\r
+ unsigned char sprite0Color = VIC.spr_color[0];\r
+ unsigned char width, width2, height, height4, height8;\r
+ struct mouse_info info;\r
+\r
+ screensize (&width, &height);\r
+ width2 = width / 2;\r
+ height4 = height / 4;\r
+ height8 = height4 * 8;\r
+\r
+ /* Draw a bar and line. */\r
+\r
+ clrscr ();\r
+ cclearxy (0, height4, height4 * width);\r
+ cvlinexy (width2, height4 + 1, height4 - 2);\r
+\r
+ /* Print instructions. */\r
+\r
+ revers (0);\r
+ cputsxy (width2 - (sizeof COMMAND1) / 2, height / 2 + 1, COMMAND1);\r
+ cputsxy (width2 - (sizeof COMMAND2) / 2, height / 2 + 3, COMMAND2);\r
+\r
+ VIC.spr_color[0] = COLOR_GRAY2;\r
+ mouse_show ();\r
+ mouse_move (width2 * 8, height8 / 2);\r
+\r
+ for (;;) {\r
+ /* Wait for the main button to be released. */\r
+\r
+ do ; while ((mouse_buttons () & MOUSE_BTN_LEFT));\r
+\r
+ /* Wait for the main button to be pressed. */\r
+\r
+ do {\r
+ mouse_info (&info);\r
+ } while (!(info.buttons & MOUSE_BTN_LEFT));\r
+\r
+ /* Find out if the pen is on or off the bar. */\r
+\r
+ if (info.pos.y < height8 || info.pos.y >= height8 * 2) {\r
+ break;\r
+ }\r
+\r
+ /* On the bar; adjust the offset. */\r
+ /* Characters are eight pixels wide.\r
+ ** The VIC-II sees every other pixel;\r
+ ** so, we use half of the difference.\r
+ */\r
+\r
+ *XOffset += (info.pos.x - (width2 * 8 + 8/2)) / 2;\r
+ }\r
+\r
+ /* Off the bar; wait for the main button to be released. */\r
+\r
+ do ; while ((mouse_buttons () & MOUSE_BTN_LEFT));\r
+\r
+ mouse_hide ();\r
+ VIC.spr_color[0] = sprite0Color;\r
+ revers (oldRev);\r
+ textcolor (oldText);\r
+ bgcolor (oldBg);\r
+ clrscr ();\r
+}\r
;
-; Oliver Schmidt, 2013-05-31
+; 2013-05-31, Oliver Schmidt
+; 2013-06-11, Greg King
;
- .export em_libref, joy_libref, mouse_libref, ser_libref, tgi_libref
+ .export em_libref
+ .export joy_libref
+; .export mouse_libref
+ .export ser_libref
+ .export tgi_libref
+
.import _exit
em_libref := _exit
joy_libref := _exit
-mouse_libref := _exit
+;mouse_libref := _exit
ser_libref := _exit
tgi_libref := _exit
;
; Driver for the Inkwell Systems 170-C and 184-C lightpens.
;
-; 2013-06-03, Greg King
+; 2013-06-17, Greg King
;
.include "zeropage.inc"
.include "c64.inc"
.macpack generic
- .macpack cbm
; ------------------------------------------------------------------------
; Header. Includes jump table.
; Library reference
- .addr $0000
+LIBREF: .addr $0000
; Jump table
;----------------------------------------------------------------------------
; Constants
-SCREEN_HEIGHT = YSIZE * 8
SCREEN_WIDTH = XSIZE * 8
-SCREEN_ZONE = YSIZE / 4 * XSIZE
-
-; This driver is for the standard 40-column screen.
-
-SCREEN := $0400
-COLOR_RAM := $D800
+SCREEN_HEIGHT = YSIZE * 8
;----------------------------------------------------------------------------
; written with the least effort in the SETBOX and GETBOX routines; so, don't
; re-order them.
+.rodata
+
+; Default values for below variables
+; (We use ".proc" because we want to define both a label and a scope.)
+
+.proc DefVars
+ .word 0 ; XMin
+ .word 0 ; YMin
+ .word SCREEN_WIDTH - 1 ; XMax
+ .word SCREEN_HEIGHT - 1 ; YMax
+ .byte %00000000 ; Buttons
+.endproc
+
.bss
Vars:
XMax: .res 2 ; X2 value of bounding box
YMax: .res 2 ; Y2 value of bounding box
Buttons: .res 1 ; Button status bits
+
XPos: .res 2 ; Current lightpen position, X
YPos: .res 2 ; Current lightpen position, Y
-OldPenX: .res 1 ; Old HW-counter values
+OldPenX: .res 1 ; Previous HW-counter values
OldPenY: .res 1
.data
-; Start with an average offset.
-
-XOffset: .byte 48 / 2 ; Calibration offset, for X position
-
-.rodata
+; Default Inkwell calibration.
+; The first number is the width of the left border;
+; the second number is the actual calibration value.
-; Default values for above variables
-; (We use ".proc" because we want to define both a label and a scope.)
+XOffset: .byte (24 + 24) / 2 ; x-offset
-.proc DefVars
- .word 0 ; XMin
- .word 0 ; YMin
- .word SCREEN_WIDTH - 1 ; XMax
- .word SCREEN_HEIGHT - 1 ; YMax
- .byte %00000000 ; Buttons
-.endproc
-
-.proc Command1
- scrcode "Adjust by clicking on line."
-.endproc
-.proc Command2
- scrcode "Finish by clicking off box."
-.endproc
+; Jump to a function that puts a new calibration value into XOffset.
+Calibrate: jmp $0000
.code
; Initiate variables. Just copy the default stuff over.
- sei
ldx #.sizeof (DefVars) - 1
@L0: lda DefVars,x
sta Vars,x
ldy VIC_LPEN_Y
stx OldPenX
sty OldPenY
- cli
-
-; There is a delay between when the VIC sends its signal, and when the display
-; shows that signal. There is another delay between the display and when
-; the lightpen says that it saw that signal. Each display and pen is different.
-; Therefore, this driver must be calibrated to them. A white box is painted on
-; the screen; and, a line is drawn down the middle of it. When the user clicks
-; on that line, the difference between its position and where the VIC thinks
-; that the pen is pointing becomes an offset that is subtracted from what the
-; VIC sees.
-
- lda VIC_BG_COLOR0
- ldx #6 ; Blue screen
- stx VIC_BG_COLOR0
- pha
- jsr CLRSCR
-
- ldy #.sizeof (Command2) - 1
-@L2: lda Command2,y
- sta SCREEN + SCREEN_ZONE * 2 + XSIZE * 3 + (XSIZE - .sizeof (Command2)) / 2,y
- lda #15 ; Light gray text
- sta COLOR_RAM + SCREEN_ZONE * 2 + XSIZE * 3 + (XSIZE - .sizeof (Command1)) / 2,y
- dey
- bpl @L2
- ldy #.sizeof (Command1) - 1
-@L1: lda Command1,y
- sta SCREEN + SCREEN_ZONE * 2 + XSIZE * 1 + (XSIZE - .sizeof (Command1)) / 2,y
- lda #15 ; Light gray text
- sta COLOR_RAM + SCREEN_ZONE * 2 + XSIZE * 1 + (XSIZE - .sizeof (Command1)) / 2,y
- dey
- bpl @L1
-
- ldx #SCREEN_ZONE
-@L3: lda #$80 | $20 ; Reversed space screen-code
- sta SCREEN + SCREEN_ZONE - 1,x
- lda #15 ; Light gray box
- sta COLOR_RAM + SCREEN_ZONE - 1,x
- dex
- bnz @L3
-
- ldy #$80 | $5d ; Reversed vertical-bar screen-code
- .repeat 4, L
- sty SCREEN + SCREEN_ZONE + (L + 1) * XSIZE + XSIZE / 2
- .endrep
-
- lda VIC_SPR0_COLOR
- ldx #12 ; Medium gray pointer
- stx VIC_SPR0_COLOR
- pha
- jsr SHOW
-
- lda #<(SCREEN_HEIGHT / 4 / 2)
- ldx #>(SCREEN_HEIGHT / 4 / 2)
- jsr PutCursor
-
-; Wait for the main button to be released.
-
-@L4: lda Buttons
- bnz @L4
-
-; Wait for the main button to be pressed.
-@L5: lda Buttons
- bze @L5
+; Call a calibration function through the library-reference.
-; Find out if the pen is on or off the box.
-
- ldy YPos
- ldx YPos+1
- txa
- cpy #<(YSIZE / 4 * 1 * 8)
- sbc #>(YSIZE / 4 * 1 * 8)
- bmi @L6 ; Above box
- txa
- cpy #<(YSIZE / 4 * 2 * 8)
- sbc #>(YSIZE / 4 * 2 * 8)
- bpl @L6 ; Below box
-
-; The pen is on the box; adjust the offset.
-
- lda OldPenX
- sub #(XSIZE * 8 / 2 + 8/2) / 2
- sta XOffset
- sta OldPenX ; Make IRQ update X co-ordinate
- jmp @L4
-
-; Wait for the main button to be released.
-
-@L6: lda Buttons
- bnz @L6
-
- lda XOffset ; Tell test program about calibration
- sta $3ff
-
- pla
- sta VIC_SPR0_COLOR
- pla
- sta VIC_BG_COLOR0
- jsr CLRSCR
-
-; Be sure the lightpen cursor is invisible and at the default location.
+ lda LIBREF
+ ldx LIBREF+1
+ sta ptr1 ; Point to mouse_adjuster
+ stx ptr1+1
+ ldy #0
+ lda (ptr1),y
+ sta Calibrate+1 ; Point to function
+ iny
+ lda (ptr1),y
+ sta Calibrate+2
+ ora Calibrate+1 ; Don't call pointer if it's NULL
+ bze @L1
+ lda #<XOffset ; Function will set this variable
+ ldx #>XOffset
+ jsr Calibrate
+
+; Be sure that the lightpen cursor is invisible and at the default location.
; It needs to be done here because the lightpen interrupt handler doesn't
; set the lightpen position if it hasn't changed.
- jsr HIDE
+@L1: jsr CHIDE
lda #<(SCREEN_HEIGHT / 2)
ldx #>(SCREEN_HEIGHT / 2)
-PutCursor:
- sei
jsr MoveY
lda #<(SCREEN_WIDTH / 2)
ldx #>(SCREEN_WIDTH / 2)
jsr MoveX
- cli
; Done, return zero.
beq @SkipX
sta OldPenX
-; Adjust the co-ordinate by the calibration offset.
+; Adjust the value by the calibration offset.
sub XOffset
-; Calculate the new X co-ordinate (--> .AY --> .XY).
+; Calculate the new X co-ordinate.
; The VIC-II register is eight bits; but, the screen co-ordinate is nine bits.
-; Therefor, the VIC-II number is doubled. Then, it points to every other pixel;
+; Therefore, the VIC-II number is doubled. Then, it points to every other pixel;
; but, it can reach across the screen.
asl a
tay ; Remember low byte
lda #>0
rol a
- tax
+ tax ; Remember high byte
; Limit the X co-ordinate to the bounding box.
--- /dev/null
+;\r
+; Pointer for library references by device drivers.\r
+;\r
+; 2013-06-23, Greg King\r
+;\r
+\r
+ .export mouse_libref, _mouse_adjuster\r
+\r
+ .data\r
+\r
+mouse_libref: ; generic label for mouse-kernel\r
+\r
+; A program optionally can set this pointer to a function that gives\r
+; a calibration value to a driver. If this pointer isn't NULL,\r
+; then a driver that wants a value can call that function.\r
+;\r
+; The function might read a value from a file; or, it might ask the user\r
+; to help calibrate the driver.\r
+;\r
+; void __fastcall__ (*mouse_adjuster)(unsigned char *) = NULL;\r
+;\r
+_mouse_adjuster:\r
+ .addr $0000\r
--- /dev/null
+/*\r
+** Calibrate lightpen drivers to the current video hardware.\r
+**\r
+** 2013-06-17, Greg King\r
+**\r
+*/\r
+\r
+\r
+#include <conio.h>\r
+#include <mouse.h>\r
+\r
+\r
+#define COMMAND1 "Adjust by clicking on line."\r
+#define COMMAND2 "Finish by clicking off bar."\r
+\r
+\r
+/*\r
+** There is a delay between when the VIC sends its signal, and when the display\r
+** shows that signal. There is another delay between the display and when\r
+** the lightpen says that it saw that signal. Each display and pen is different.\r
+** Therefore, the driver must be calibrated to them. A white bar is painted on\r
+** the screen; and, a line is drawn down the middle of it. When the user clicks\r
+** on that line, the difference between its position and where the VIC thinks\r
+** that the pen is pointing becomes an offset that is subtracted from what the\r
+** VIC sees.\r
+*/\r
+void __fastcall__ pen_calibrate (unsigned char *XOffset)\r
+{\r
+ unsigned char oldBg = bgcolor (COLOR_BLUE);\r
+ unsigned char oldText = textcolor (COLOR_GRAY3);\r
+ unsigned char oldRev = revers (1);\r
+ unsigned char sprite0Color = VIC.spr_color[0];\r
+ unsigned char width, width2, height, height4, height8;\r
+ struct mouse_info info;\r
+\r
+ screensize (&width, &height);\r
+ width2 = width / 2;\r
+ height4 = height / 4;\r
+ height8 = height4 * 8;\r
+\r
+ /* Draw a bar and line. */\r
+\r
+ clrscr ();\r
+ cclearxy (0, height4, height4 * width);\r
+ cvlinexy (width2, height4 + 1, height4 - 2);\r
+ revers (0);\r
+\r
+ /* Print instructions. */\r
+\r
+ cputsxy (width2 - (sizeof COMMAND1) / 2, height / 2 + 1, COMMAND1);\r
+ cputsxy (width2 - (sizeof COMMAND2) / 2, height / 2 + 3, COMMAND2);\r
+\r
+ VIC.spr_color[0] = COLOR_GRAY2;\r
+ mouse_show ();\r
+ mouse_move (width2 * 8, height8 / 2);\r
+\r
+ for (;;) {\r
+ /* Wait for the main button to be released. */\r
+\r
+ do ; while ((mouse_buttons () & MOUSE_BTN_LEFT));\r
+\r
+ /* Wait for the main button to be pressed. */\r
+\r
+ do {\r
+ mouse_info (&info);\r
+ } while (!(info.buttons & MOUSE_BTN_LEFT));\r
+\r
+ /* Find out if the pen is on or off the bar. */\r
+\r
+ if (info.pos.y < height8 || info.pos.y >= height8 * 2) {\r
+ break;\r
+ }\r
+\r
+ /* On the bar; adjust the offset. */\r
+ /* Characters are eight pixels wide.\r
+ ** The VIC-II sees every other pixel;\r
+ ** so, we use half of the difference.\r
+ */\r
+\r
+ *XOffset += (info.pos.x - (width2 * 8 + 8/2)) / 2;\r
+ }\r
+\r
+ /* Off the bar; wait for the main button to be released. */\r
+\r
+ do ; while ((mouse_buttons () & MOUSE_BTN_LEFT));\r
+\r
+ mouse_hide ();\r
+ VIC.spr_color[0] = sprite0Color;\r
+ revers (oldRev);\r
+ textcolor (oldText);\r
+ bgcolor (oldBg);\r
+ clrscr ();\r
+}\r
--- /dev/null
+/*\r
+** Main lightpen driver calibration functions.\r
+**\r
+** 2013-06-23, Greg King\r
+*/\r
+\r
+\r
+#include <fcntl.h>\r
+#include <unistd.h>\r
+#include <mouse.h>\r
+\r
+\r
+static const char *name;\r
+\r
+\r
+/* Get a lightpen calibration value from a file if it exists. Otherwise, call\r
+** pen_calibrate() to create a value; then, write it into a file, so that it\r
+** will be available at the next time that the lightpen is used.\r
+** Might change the screen.\r
+*/\r
+static void __fastcall__ adjuster (unsigned char *XOffset)\r
+{\r
+ int fd = open (name, O_RDONLY);\r
+\r
+ if (fd < 0) {\r
+ pen_calibrate (XOffset);\r
+ fd = open (name, O_WRONLY | O_CREAT | O_EXCL);\r
+ if (fd >= 0) {\r
+ (void) write (fd, XOffset, 1);\r
+ close (fd);\r
+ }\r
+ } else {\r
+ (void) read (fd, XOffset, 1);\r
+ close (fd);\r
+ }\r
+}\r
+\r
+\r
+/* pen_adjust() is optional; if you want to use its feature,\r
+** then it must be called before a driver is installed.\r
+** Note: This function merely saves the file-name pointer, and sets\r
+** the mouse_adjuster pointer. The file will be read only when a driver\r
+** is installed, and only if that driver wants to be calibrated.\r
+*/\r
+void __fastcall__ pen_adjust (const char *filename)\r
+{\r
+ if (filename != NULL && filename[0] != '\0') {\r
+ name = filename;\r
+ mouse_adjuster = adjuster;\r
+ } else {\r
+ mouse_adjuster = pen_calibrate;\r
+ }\r
+}\r
** Test program for lightpen drivers. Will work for the C64/C128.
**
** 2001-09-13, Ullrich von Bassewitz
-** 2013-05-24, Greg King
+** 2013-06-21, Greg King
**
*/
# define SPRITE0_PTR ((unsigned char *)0x07F8)
#endif
-/* The lightpen sprite (an arrow) */
+/* An arrow sprite */
static const unsigned char PenSprite[64] = {
0xFF, 0xFF, 0xFF,
0xFC, 0x00, 0x00,
static void __fastcall__ ShowState (unsigned char Jailed, unsigned char Invisible)
/* Display jail and cursor states. */
{
- cclearxy (0, 7, 40);
+ cclearxy (0, 7, 32);
gotoxy (0, 7);
- cprintf ("Lightpen cursor is %svisible%s.", Invisible? "in" : "", Jailed? " and jailed" : "");
+ cprintf ("Pointer is %svisible%s.", Invisible? "in" : "", Jailed? " and jailed" : "");
}
unsigned char width, height;
bool Invisible = false, Done = false, Jailed = false;
- /* Only the VIC-II has a lightpen connection. */
#ifdef __C128__
+ /* Only the VIC-IIe has a lightpen connection. */
videomode (VIDEOMODE_40x25);
#endif
memcpy (SPRITE0_DATA, PenSprite, sizeof PenSprite);
/* Set the VIC-II sprite pointer. */
- *SPRITE0_PTR = (unsigned) SPRITE0_DATA / sizeof SPRITE0_DATA;
+ *SPRITE0_PTR = ((unsigned) SPRITE0_DATA & 0x3FFF) / sizeof SPRITE0_DATA;
/* Set the color of sprite 0. */
VIC.spr0_color = COLOR_BLACK;
+
+ pen_adjust ("inkwell.dat");
#endif
#if DYN_DRV
screensize (&width, &height);
top:
- /* Print a help line. */
clrscr ();
-/* revers (1); */
- cputs (" d)ebug h)ide q)uit s)how j)ail ");
-/* revers (0); */
+
+ /* Print a help line. */
+ cputs (" d)ebug h)ide q)uit s)how j)ail");
/* Put a cross at the center of the screen. */
gotoxy (width / 2 - 3, height / 2 - 1);
cprintf ("%3u,%3u\r\n%*s\xDB", width / 2 * 8 + 4, height / 2 * 8 + 4,
width / 2, "");
- /* Custom driver debugging line */
- cprintf ("\n\r\n Calibration X-offset = %u", (*(unsigned char *)0x3ff) * 2);
-
/* Expose the arrow. */
mouse_show ();
ShowState (Jailed, Invisible);
gotoxy (0, 2);
cprintf (" X = %3d\r\n", info.pos.x);
cprintf (" Y = %3d\r\n", info.pos.y);
- cprintf (" B1 = %c\r\n", (info.buttons & MOUSE_BTN_LEFT) ? 0x5F : '^');
- cprintf (" B2 = %c", (info.buttons & MOUSE_BTN_RIGHT) ? 0x5F : '^');
+ cprintf (" B1 = %c\r\n", (info.buttons & MOUSE_BTN_LEFT) ?
+#ifdef __CBM__
+ 0x5F
+#else
+ 'v'
+#endif
+ : '^');
+ cprintf (" B2 = %c", (info.buttons & MOUSE_BTN_RIGHT) ?
+#ifdef __CBM__
+ 0x5F
+#else
+ 'v'
+#endif
+ : '^');
/* Handle user input. */
if (kbhit ()) {
#endif
/* Say goodbye. */
- cputsxy (0, 16, "Goodbye!");
+ cputsxy (0, height / 2 + 3, "Goodbye!");
return EXIT_SUCCESS;
}