1
0
mirror of https://github.com/cc65/cc65.git synced 2024-09-29 17:56:21 +00:00

Used a library-reference method to calibrate lightpen drivers.

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.
This commit is contained in:
Greg King 2013-06-23 03:18:28 -04:00
parent 66ca781bb1
commit e63bf1cde1
11 changed files with 463 additions and 318 deletions

View File

@ -6,7 +6,7 @@
/* */
/* */
/* */
/* (C) 2003-2011, Ullrich von Bassewitz */
/* (C) 2003-2013, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@ -101,6 +101,14 @@ struct mouse_callbacks {
*/
};
/*****************************************************************************/
/* Declarations */
/*****************************************************************************/
/* The default mouse callbacks */
extern const struct mouse_callbacks mouse_def_callbacks;
@ -110,6 +118,13 @@ extern const char mouse_stddrv[];
/* 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);
/*****************************************************************************/
@ -127,10 +142,10 @@ unsigned char mouse_unload (void);
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. */
@ -142,7 +157,7 @@ void mouse_hide (void);
*/
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
@ -176,14 +191,31 @@ unsigned char mouse_buttons (void);
*/
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.
*/

View File

@ -1,12 +1,18 @@
;
; 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

View File

@ -1,7 +1,7 @@
;
; Driver for the Inkwell Systems 170-C and 184-C lightpens.
;
; 2013-06-03, Greg King
; 2013-06-17, Greg King
;
.include "zeropage.inc"
@ -9,7 +9,6 @@
.include "c128.inc"
.macpack generic
.macpack cbm
; ------------------------------------------------------------------------
; Header. Includes jump table.
@ -25,7 +24,7 @@ HEADER:
; Library reference
.addr $0000
LIBREF: .addr $0000
; Jump table
@ -62,14 +61,8 @@ CMOVEY: jmp $0000 ; Move the cursor to Y co-ord.
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
;----------------------------------------------------------------------------
@ -77,6 +70,19 @@ PRIMM := $FF7D ; Print immediate
; 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:
@ -89,36 +95,21 @@ 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
INIT_save: .res 1
.data
; Start with an average offset.
; Default Inkwell calibration.
; The first number is the width of the left border;
; the second number is the actual calibration value.
XOffset: .byte 48 / 2 ; Calibration offset, for X position
XOffset: .byte (24 + 24) / 2 ; x-offset
.rodata
; Default values for above 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
.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
@ -138,15 +129,8 @@ INSTALL:
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
@ -157,121 +141,37 @@ INSTALL:
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.
; Call a calibration function through the library-reference.
lda VIC_BG_COLOR0
ldx #6 ; Blue screen
stx VIC_BG_COLOR0
pha
jsr CLRSCR
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
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.
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.
; 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.
@ -504,11 +404,11 @@ IRQ:
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.
@ -517,7 +417,7 @@ IRQ:
tay ; Remember low byte
lda #>0
rol a
tax
tax ; Remember high byte
; Limit the X co-ordinate to the bounding box.

23
libsrc/c128/mouseref.s Normal file
View File

@ -0,0 +1,23 @@
;
; Pointer for library references by device drivers.
;
; 2013-06-23, Greg King
;
.export mouse_libref, _mouse_adjuster
.data
mouse_libref: ; generic label for mouse-kernel
; 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.
;
; The function might read a value from a file; or, it might ask the user
; to help calibrate the driver.
;
; void __fastcall__ (*mouse_adjuster)(unsigned char *) = NULL;
;
_mouse_adjuster:
.addr $0000

92
libsrc/c128/pencalib.c Normal file
View File

@ -0,0 +1,92 @@
/*
** Calibrate lightpen drivers to the current video hardware.
**
** 2013-06-17, Greg King
**
*/
#include <conio.h>
#include <mouse.h>
#define COMMAND1 "Adjust by clicking on line."
#define COMMAND2 "Finish by clicking off bar."
/* 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, the driver must be calibrated to them. A white bar 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.
*/
void __fastcall__ pen_calibrate (unsigned char *XOffset)
{
unsigned char oldBg = bgcolor (COLOR_BLUE);
unsigned char oldText = textcolor (COLOR_GRAY3);
unsigned char oldRev = revers (1);
unsigned char sprite0Color = VIC.spr_color[0];
unsigned char width, width2, height, height4, height8;
struct mouse_info info;
screensize (&width, &height);
width2 = width / 2;
height4 = height / 4;
height8 = height4 * 8;
/* Draw a bar and line. */
clrscr ();
cclearxy (0, height4, height4 * width);
cvlinexy (width2, height4 + 1, height4 - 2);
/* Print instructions. */
revers (0);
cputsxy (width2 - (sizeof COMMAND1) / 2, height / 2 + 1, COMMAND1);
cputsxy (width2 - (sizeof COMMAND2) / 2, height / 2 + 3, COMMAND2);
VIC.spr_color[0] = COLOR_GRAY2;
mouse_show ();
mouse_move (width2 * 8, height8 / 2);
for (;;) {
/* Wait for the main button to be released. */
do ; while ((mouse_buttons () & MOUSE_BTN_LEFT));
/* Wait for the main button to be pressed. */
do {
mouse_info (&info);
} while (!(info.buttons & MOUSE_BTN_LEFT));
/* Find out if the pen is on or off the bar. */
if (info.pos.y < height8 || info.pos.y >= height8 * 2) {
break;
}
/* On the bar; adjust the offset. */
/* Characters are eight pixels wide.
** The VIC-II sees every other pixel;
** so, we use half of the difference.
*/
*XOffset += (info.pos.x - (width2 * 8 + 8/2)) / 2;
}
/* Off the bar; wait for the main button to be released. */
do ; while ((mouse_buttons () & MOUSE_BTN_LEFT));
mouse_hide ();
VIC.spr_color[0] = sprite0Color;
revers (oldRev);
textcolor (oldText);
bgcolor (oldBg);
clrscr ();
}

View File

@ -1,12 +1,18 @@
;
; 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

View File

@ -1,7 +1,7 @@
;
; Driver for the Inkwell Systems 170-C and 184-C lightpens.
;
; 2013-06-03, Greg King
; 2013-06-17, Greg King
;
.include "zeropage.inc"
@ -9,7 +9,6 @@
.include "c64.inc"
.macpack generic
.macpack cbm
; ------------------------------------------------------------------------
; Header. Includes jump table.
@ -25,7 +24,7 @@ HEADER:
; Library reference
.addr $0000
LIBREF: .addr $0000
; Jump table
@ -57,14 +56,8 @@ CMOVEY: jmp $0000 ; Move the cursor to Y co-ord.
;----------------------------------------------------------------------------
; 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
;----------------------------------------------------------------------------
@ -72,29 +65,9 @@ COLOR_RAM := $D800
; written with the least effort in the SETBOX and GETBOX routines; so, don't
; re-order them.
.bss
Vars:
XMin: .res 2 ; X1 value of bounding box
YMin: .res 2 ; Y1 value of bounding box
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
OldPenY: .res 1
.data
; Start with an average offset.
XOffset: .byte 48 / 2 ; Calibration offset, for X position
.rodata
; Default values for above variables
; Default values for below variables
; (We use ".proc" because we want to define both a label and a scope.)
.proc DefVars
@ -105,12 +78,31 @@ XOffset: .byte 48 / 2 ; Calibration offset, for X position
.byte %00000000 ; Buttons
.endproc
.proc Command1
scrcode "Adjust by clicking on line."
.endproc
.proc Command2
scrcode "Finish by clicking off box."
.endproc
.bss
Vars:
XMin: .res 2 ; X1 value of bounding box
YMin: .res 2 ; Y1 value of bounding box
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 ; Previous HW-counter values
OldPenY: .res 1
.data
; Default Inkwell calibration.
; The first number is the width of the left border;
; the second number is the actual calibration value.
XOffset: .byte (24 + 24) / 2 ; x-offset
; Jump to a function that puts a new calibration value into XOffset.
Calibrate: jmp $0000
.code
@ -124,7 +116,6 @@ INSTALL:
; Initiate variables. Just copy the default stuff over.
sei
ldx #.sizeof (DefVars) - 1
@L0: lda DefVars,x
sta Vars,x
@ -135,121 +126,37 @@ INSTALL:
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.
; Call a calibration function through the library-reference.
lda VIC_BG_COLOR0
ldx #6 ; Blue screen
stx VIC_BG_COLOR0
pha
jsr CLRSCR
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
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.
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.
; 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.
@ -478,20 +385,20 @@ IRQ:
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.

23
libsrc/c64/mouseref.s Normal file
View File

@ -0,0 +1,23 @@
;
; Pointer for library references by device drivers.
;
; 2013-06-23, Greg King
;
.export mouse_libref, _mouse_adjuster
.data
mouse_libref: ; generic label for mouse-kernel
; 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.
;
; The function might read a value from a file; or, it might ask the user
; to help calibrate the driver.
;
; void __fastcall__ (*mouse_adjuster)(unsigned char *) = NULL;
;
_mouse_adjuster:
.addr $0000

93
libsrc/c64/pencalib.c Normal file
View File

@ -0,0 +1,93 @@
/*
** Calibrate lightpen drivers to the current video hardware.
**
** 2013-06-17, Greg King
**
*/
#include <conio.h>
#include <mouse.h>
#define COMMAND1 "Adjust by clicking on line."
#define COMMAND2 "Finish by clicking off bar."
/*
** 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, the driver must be calibrated to them. A white bar 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.
*/
void __fastcall__ pen_calibrate (unsigned char *XOffset)
{
unsigned char oldBg = bgcolor (COLOR_BLUE);
unsigned char oldText = textcolor (COLOR_GRAY3);
unsigned char oldRev = revers (1);
unsigned char sprite0Color = VIC.spr_color[0];
unsigned char width, width2, height, height4, height8;
struct mouse_info info;
screensize (&width, &height);
width2 = width / 2;
height4 = height / 4;
height8 = height4 * 8;
/* Draw a bar and line. */
clrscr ();
cclearxy (0, height4, height4 * width);
cvlinexy (width2, height4 + 1, height4 - 2);
revers (0);
/* Print instructions. */
cputsxy (width2 - (sizeof COMMAND1) / 2, height / 2 + 1, COMMAND1);
cputsxy (width2 - (sizeof COMMAND2) / 2, height / 2 + 3, COMMAND2);
VIC.spr_color[0] = COLOR_GRAY2;
mouse_show ();
mouse_move (width2 * 8, height8 / 2);
for (;;) {
/* Wait for the main button to be released. */
do ; while ((mouse_buttons () & MOUSE_BTN_LEFT));
/* Wait for the main button to be pressed. */
do {
mouse_info (&info);
} while (!(info.buttons & MOUSE_BTN_LEFT));
/* Find out if the pen is on or off the bar. */
if (info.pos.y < height8 || info.pos.y >= height8 * 2) {
break;
}
/* On the bar; adjust the offset. */
/* Characters are eight pixels wide.
** The VIC-II sees every other pixel;
** so, we use half of the difference.
*/
*XOffset += (info.pos.x - (width2 * 8 + 8/2)) / 2;
}
/* Off the bar; wait for the main button to be released. */
do ; while ((mouse_buttons () & MOUSE_BTN_LEFT));
mouse_hide ();
VIC.spr_color[0] = sprite0Color;
revers (oldRev);
textcolor (oldText);
bgcolor (oldBg);
clrscr ();
}

53
libsrc/cbm/penadjust.c Executable file
View File

@ -0,0 +1,53 @@
/*
** Main lightpen driver calibration functions.
**
** 2013-06-23, Greg King
*/
#include <fcntl.h>
#include <unistd.h>
#include <mouse.h>
static const char *name;
/* 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.
*/
static void __fastcall__ adjuster (unsigned char *XOffset)
{
int fd = open (name, O_RDONLY);
if (fd < 0) {
pen_calibrate (XOffset);
fd = open (name, O_WRONLY | O_CREAT | O_EXCL);
if (fd >= 0) {
(void) write (fd, XOffset, 1);
close (fd);
}
} else {
(void) read (fd, XOffset, 1);
close (fd);
}
}
/* 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.
*/
void __fastcall__ pen_adjust (const char *filename)
{
if (filename != NULL && filename[0] != '\0') {
name = filename;
mouse_adjuster = adjuster;
} else {
mouse_adjuster = pen_calibrate;
}
}

View File

@ -2,7 +2,7 @@
** 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
**
*/
@ -55,7 +55,7 @@
# 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,
@ -113,9 +113,9 @@ static void DoWarning (void)
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" : "");
}
@ -128,8 +128,8 @@ int main (void)
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
@ -154,10 +154,12 @@ int main (void)
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
@ -179,20 +181,16 @@ int main (void)
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);
@ -206,8 +204,20 @@ top:
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 ()) {
@ -277,6 +287,6 @@ top:
#endif
/* Say goodbye. */
cputsxy (0, 16, "Goodbye!");
cputsxy (0, height / 2 + 3, "Goodbye!");
return EXIT_SUCCESS;
}