diff --git a/asminc/atmos.inc b/asminc/atmos.inc index 446f2e11c..20bb806f1 100644 --- a/asminc/atmos.inc +++ b/asminc/atmos.inc @@ -1,32 +1,94 @@ ; -; Oric atmos zeropage and ROM definitions +; Oric Atmos definitions +; BASIC 1.1 addresses ; +; --------------------------------------------------------------------------- +; Constants + +SCREEN_XSIZE = 40 ; screen columns +SCREEN_YSIZE = 28 ; screen rows + +FUNCTKEY = $A5 + +FNAME_LEN = 16 ; maximum length of file-name + + ; --------------------------------------------------------------------------- ; Zero page +BASIC_BUF := $35 ; --------------------------------------------------------------------------- ; Low memory -CAPSLOCK := $20C -IRQVec := $245 -CURS_Y := $268 -CURS_X := $269 -STATUS := $26A -TIMER3 := $276 -KEYBUF := $2DF +MODEKEY := $0209 +CAPSLOCK := $020C +PATTERN := $0213 +IRQVec := $0245 +JOINFLAG := $025A ; 0 = don't joiu, $4A = join BASIC programs +VERIFYFLAG := $025B ; 0 = load, 1 = verify +CURS_Y := $0268 +CURS_X := $0269 +STATUS := $026A +TIMER3 := $0276 +CFILE_NAME := $027F +CFOUND_NAME := $0293 +FILESTART := $02A9 +FILEEND := $02AB +AUTORUN := $02AD ; $00 = only load, $C7 = autorun +LANGFLAG := $02AE ; $00 = BASIC, $80 = machine code +KEYBUF := $02DF +PARAM1 := $02E1 ; & $02E2 +PARAM2 := $02E3 ; & $02E4 +PARAM3 := $02E5 ; & $02E6 + + +; --------------------------------------------------------------------------- +; I/O locations + +; 6522 +.struct VIA ; Versatile Interface Adapter + .res $0300 +PRB .byte ; Port Register B +PRA .byte ; Port Register A +DDRB .byte ; Data Direction Register B +DDRA .byte ; Data Direction Register A +T1 .word ; Timer 1 +T1L .word ; Timer 1 Latch +T2 .word ; Timer 2 +SR .byte ; Shift Register +ACR .byte ; Auxiliary Control Register +PCR .byte ; Peripheral Control Register +IFR .byte ; Interrupt Flags Register +IER .byte ; Interrupt Enable Register +PRA2 .byte ; Port Register A without handshaking +.endstruct + +; 6551 +.struct ACIA ; Asynchronous Communications Interface Adapter + .res $031C +DATA .byte +STATUS .byte +CMD .byte ; Command register +CTRL .byte ; Control register +.endstruct + +SCREEN := $BB80 ; --------------------------------------------------------------------------- ; ROM entries +TEXT := $EC21 +HIRES := $EC33 +CURSET := $F0C8 +CURMOV := $F0FD +DRAW := $F110 +CHAR := $F12D +POINT := $F1C8 +PAPER := $F204 +INK := $F210 PRINT := $F77C - - -; --------------------------------------------------------------------------- -; I/O - -SCREEN := $BB80 diff --git a/asminc/c128.inc b/asminc/c128.inc index 8ec72a172..1fb8b397c 100644 --- a/asminc/c128.inc +++ b/asminc/c128.inc @@ -1,5 +1,5 @@ ; -; C64 generic definitions. Stolen from Elite128 +; C128 generic definitions. Stolen from Elite128 ; @@ -32,7 +32,7 @@ FETVEC := $2AA ; Vector patch location for FETCH STASH := $2AF ; Stash routine in RAM STAVEC := $2B9 ; Vector patch location for STASH PALFLAG := $A03 ; $FF=PAL, $00=NTSC -INIT_STATUS := $A04 ; Flag: Reset/NMI Status +INIT_STATUS := $A04 ; Flags: Reset/Restore initiation status FKEY_LEN := $1000 ; Function key lengths FKEY_TEXT := $100A ; Function key texts @@ -102,6 +102,9 @@ VIC_CTRL2 := $D016 VIC_HLINE := $D012 +VIC_LPEN_X := $D013 +VIC_LPEN_Y := $D014 + VIC_VIDEO_ADR := $D018 VIC_IRR := $D019 ; Interrupt request register diff --git a/asminc/c64.inc b/asminc/c64.inc index 6823403c5..f5dbcf549 100644 --- a/asminc/c64.inc +++ b/asminc/c64.inc @@ -95,6 +95,9 @@ VIC_CTRL2 := $D016 VIC_HLINE := $D012 +VIC_LPEN_X := $D013 +VIC_LPEN_Y := $D014 + VIC_VIDEO_ADR := $D018 VIC_IRR := $D019 ; Interrupt request register @@ -207,4 +210,3 @@ TP_FAST = $80 ; Switch Rossmoeller TurboProcess to fast mode RAMONLY = $F8 ; (~(LORAM | HIRAM | IOEN)) & $FF - diff --git a/include/c128.h b/include/c128.h index 0b005bce0..2ca559d49 100644 --- a/include/c128.h +++ b/include/c128.h @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2009, Ullrich von Bassewitz */ +/* (C) 1998-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -131,6 +131,7 @@ extern void c128_ptvjoy_joy[]; extern void c128_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ extern void c128_1351_mous[]; /* Referred to by mouse_static_stddrv[] */ extern void c128_joy_mou[]; +extern void c128_inkwell_mou[]; extern void c128_pot_mou[]; extern void c128_swlink_ser[]; extern void c128_vdc_tgi[]; /* Referred to by tgi_static_stddrv[] */ diff --git a/include/c64.h b/include/c64.h index 0a4ebaf97..adf3840b9 100644 --- a/include/c64.h +++ b/include/c64.h @@ -2,11 +2,11 @@ /* */ /* c64.h */ /* */ -/* C64 system specific definitions */ +/* C64 system-specific definitions */ /* */ /* */ /* */ -/* (C) 1998-2010 Ullrich von Bassewitz */ +/* (C) 1998-2013 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -145,6 +145,7 @@ extern void c64_ptvjoy_joy[]; extern void c64_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ extern void c64_1351_mou[]; /* Referred to by mouse_static_stddrv[] */ extern void c64_joy_mou[]; +extern void c64_inkwell_mou[]; extern void c64_pot_mou[]; extern void c64_swlink_ser[]; extern void c64_hi_tgi[]; /* Referred to by tgi_static_stddrv[] */ diff --git a/include/mouse.h b/include/mouse.h index bc90263cf..5e69c7ff6 100644 --- a/include/mouse.h +++ b/include/mouse.h @@ -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; @@ -127,10 +135,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 +150,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 +184,14 @@ 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! */ diff --git a/include/pen.h b/include/pen.h new file mode 100644 index 000000000..bab6997df --- /dev/null +++ b/include/pen.h @@ -0,0 +1,78 @@ +/*****************************************************************************/ +/* */ +/* pen.h */ +/* */ +/* Lightpen API */ +/* */ +/* */ +/* This software is provided "as-is", without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated, but is not required. */ +/* 2. Altered source versions must be marked plainly as such; and, must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +#ifndef _PEN_H +#define _PEN_H + + + +/*****************************************************************************/ +/* Declarations */ +/*****************************************************************************/ + + + +/* 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. +** pen_adjuster must be set before the driver is installed. +*/ +extern void __fastcall__ (*pen_adjuster) (unsigned char *pValue); + + + +/*****************************************************************************/ +/* Functions */ +/*****************************************************************************/ + + + +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 pen_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 pen_adjuster pointer. The file will be read only when a driver + * is installed, and only if that driver wants to be calibrated. + */ + + + +/* End of pen.h */ +#endif + + + diff --git a/libsrc/atmos/_scrsize.s b/libsrc/atmos/_scrsize.s index 2dd58399d..7a7af33ee 100644 --- a/libsrc/atmos/_scrsize.s +++ b/libsrc/atmos/_scrsize.s @@ -1,15 +1,17 @@ ; -; Ullrich von Bassewitz, 2003-04-13 +; 2003-04-13, Ullrich von Bassewitz +; 2013-07-16, Greg King ; ; Screen size variables ; .export screensize + .include "atmos.inc" .proc screensize - ldx #40 - ldy #28 + ldx #SCREEN_XSIZE + ldy #SCREEN_YSIZE rts .endproc diff --git a/libsrc/atmos/atmos_load.s b/libsrc/atmos/atmos_load.s index 9e86373f3..b5bec3225 100644 --- a/libsrc/atmos/atmos_load.s +++ b/libsrc/atmos/atmos_load.s @@ -1,20 +1,24 @@ -; Stefan Haubenthal, 2012-05-06 -; based on code by Twilighte +; Based on code by Twilighte. +; 2012-05-06, Stefan Haubenthal +; 2013-07-22, Greg King +; ; void __fastcall__ atmos_load(const char* name); .export _atmos_load .import store_filename + .include "atmos.inc" + .proc _atmos_load sei jsr store_filename ldx #$00 - stx $02ad - stx $02ae - stx $025a - stx $025b + stx AUTORUN ; don't try to run the file + stx LANGFLAG ; BASIC + stx JOINFLAG ; don't join it to another BASIC program + stx VERIFYFLAG ; load the file jsr cload_bit cli rts diff --git a/libsrc/atmos/atmos_save.s b/libsrc/atmos/atmos_save.s index 0bd9e29cc..3d221f6fa 100644 --- a/libsrc/atmos/atmos_save.s +++ b/libsrc/atmos/atmos_save.s @@ -1,23 +1,27 @@ -; Stefan Haubenthal, 2012-05-06 -; based on code by Twilighte +; Based on code by Twilighte. +; 2012-05-06, Stefan Haubenthal +; 2013-07-22, Greg King +; ; void __fastcall__ atmos_save(const char* name, const void* start, const void* end); .export _atmos_save .import popax, store_filename + .include "atmos.inc" + .proc _atmos_save sei - sta $02ab ; file end lo - stx $02ac ; file end hi + sta FILEEND + stx FILEEND+1 jsr popax - sta $02a9 ; file start lo - stx $02aa ; file start hi + sta FILESTART + stx FILESTART+1 jsr popax jsr store_filename lda #00 - sta $02ad + sta AUTORUN jsr csave_bit cli rts diff --git a/libsrc/atmos/cgetc.s b/libsrc/atmos/cgetc.s index 38e7aa873..e13d143d2 100644 --- a/libsrc/atmos/cgetc.s +++ b/libsrc/atmos/cgetc.s @@ -1,5 +1,6 @@ ; -; Ullrich von Bassewitz, 2003-04-13 +; 2003-04-13, Ullrich von Bassewitz +; 2013-07-26, Greg King ; ; char cgetc (void); ; @@ -11,7 +12,6 @@ .include "atmos.inc" - ; ------------------------------------------------------------------------ ; @@ -41,8 +41,8 @@ @L2: and #$7F ; Mask out avail flag sta KEYBUF - ldy $209 - cpy #$A5 + ldy MODEKEY + cpy #FUNCTKEY bne @L3 ora #$80 ; FUNCT pressed diff --git a/libsrc/atmos/clrscr.s b/libsrc/atmos/clrscr.s index 9dce665e9..2230d6e0a 100644 --- a/libsrc/atmos/clrscr.s +++ b/libsrc/atmos/clrscr.s @@ -1,5 +1,6 @@ ; -; Ullrich von Bassewitz, 2003-04-13 +; 2003-04-13, Ullrich von Bassewitz +; 2013-07-16, Greg King ; .export _clrscr @@ -27,7 +28,7 @@ ; Clear full pages. Y is still zero - ldx #>(28*40) + ldx #>(SCREEN_YSIZE * SCREEN_XSIZE) lda #' ' @L1: sta (ptr2),y iny ; Bump low byte of address @@ -40,7 +41,7 @@ @L2: sta (ptr2),y iny - cpy #<(28*40) + cpy #<(SCREEN_YSIZE * SCREEN_XSIZE) bne @L2 rts diff --git a/libsrc/atmos/cputc.s b/libsrc/atmos/cputc.s index 9f65be500..a0ef14b70 100644 --- a/libsrc/atmos/cputc.s +++ b/libsrc/atmos/cputc.s @@ -1,5 +1,6 @@ ; -; Ullrich von Bassewitz, 2003-04-13 +; 2003-04-13, Ullrich von Bassewitz +; 2013-07-16, Greg King ; ; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputc (char c); @@ -41,7 +42,7 @@ output: advance: iny - cpy #40 + cpy #SCREEN_XSIZE bne L3 inc CURS_Y ; new line ldy #0 ; + cr @@ -85,12 +86,12 @@ L3: sty CURS_X .rodata ScrTabLo: - .repeat 28, Line - .byte <(SCREEN + Line * 40) + .repeat SCREEN_YSIZE, Line + .byte <(SCREEN + Line * SCREEN_XSIZE) .endrep ScrTabHi: - .repeat 28, Line - .byte >(SCREEN + Line * 40) + .repeat SCREEN_YSIZE, Line + .byte >(SCREEN + Line * SCREEN_XSIZE) .endrep diff --git a/libsrc/atmos/joy/atmos-pase.s b/libsrc/atmos/joy/atmos-pase.s index c505a1b0f..0c657584b 100644 --- a/libsrc/atmos/joy/atmos-pase.s +++ b/libsrc/atmos/joy/atmos-pase.s @@ -1,14 +1,15 @@ ; ; P.A.S.E. joystick driver for the Atmos -; May be used multiple times when linked to the statically application. +; Can be used multiple times when statically linked to the application. ; -; Stefan Haubenthal, 2009-12-21 -; Based on Ullrich von Bassewitz, 2002-12-20 +; 2002-12-20, Based on Ullrich von Bassewitz's code. +; 2009-12-21, Stefan Haubenthal +; 2013-07-15, Greg King ; .include "joy-kernel.inc" .include "joy-error.inc" -; .include "atmos.inc" + .include "atmos.inc" ; ------------------------------------------------------------------------ @@ -49,10 +50,6 @@ JOY_COUNT = 2 ; Number of joysticks we support -PRA = $0301 -DDRA = $0303 -PRA2 = $030F - ; ------------------------------------------------------------------------ ; Data. @@ -99,24 +96,24 @@ COUNT: READ: tay - lda PRA + lda VIA::PRA pha - lda DDRA + lda VIA::DDRA pha lda #%11000000 - sta DDRA + sta VIA::DDRA lda #%10000000 - sta PRA2 - lda PRA2 + sta VIA::PRA2 + lda VIA::PRA2 sta temp1 lda #%01000000 - sta PRA2 - lda PRA + sta VIA::PRA2 + lda VIA::PRA sta temp2 pla - sta DDRA + sta VIA::DDRA pla - sta PRA2 + sta VIA::PRA2 ldx #0 tya diff --git a/libsrc/atmos/mainargs.s b/libsrc/atmos/mainargs.s index 3e1f6467b..42a94da51 100644 --- a/libsrc/atmos/mainargs.s +++ b/libsrc/atmos/mainargs.s @@ -1,19 +1,19 @@ ; -; Ullrich von Bassewitz, 2003-03-07 -; Stefan Haubenthal, 2011-01-28 +; 2003-03-07, Ullrich von Bassewitz +; 2011-01-28, Stefan Haubenthal +; 2013-07-15, Greg King ; ; Setup arguments for main ; .constructor initmainargs, 24 .import __argc, __argv + + .include "atmos.inc" .macpack generic MAXARGS = 10 ; Maximum number of arguments allowed REM = $9d ; BASIC token-code -NAME_LEN = 16 ; maximum length of command-name -BASIC_BUF = $35 -FNAM = $293 ;--------------------------------------------------------------------------- @@ -29,8 +29,8 @@ FNAM = $293 ; Because the buffer, that we're copying into, was zeroed out, ; we don't need to add a NUL character. ; - ldy #NAME_LEN - 1 ; limit the length -L0: lda FNAM,y + ldy #FNAME_LEN - 1 ; limit the length +L0: lda CFOUND_NAME,y sta name,y dey bpl L0 @@ -114,7 +114,7 @@ done: lda # -; 2012-08-11, Greg King +; 2013-07-15, Greg King ; .include "zeropage.inc" @@ -79,21 +79,7 @@ ERROR: .res 1 ; Error code MODE: .res 1 ; Graphics mode PALETTE: .res 2 -; Constants and table -; BASIC 1.1 addresses -PATTERN := $213 -PARAM1 := $2E1 ; & $2E2 -PARAM2 := $2E3 ; & $2E4 -PARAM3 := $2E5 ; & $2E6 -TEXT := $EC21 -HIRES := $EC33 -CURSET := $F0C8 -CURMOV := $F0FD -DRAW := $F110 -CHAR := $F12D -POINT := $F1C8 -PAPER := $F204 -INK := $F210 +; Constant table .rodata diff --git a/libsrc/atmos/tgi/atmos-240-200-2.s b/libsrc/atmos/tgi/atmos-240-200-2.s index e58ac36d2..762c7c02d 100644 --- a/libsrc/atmos/tgi/atmos-240-200-2.s +++ b/libsrc/atmos/tgi/atmos-240-200-2.s @@ -2,7 +2,7 @@ ; Graphics driver for the 240x200x2 monochrome mode on the Atmos ; ; Stefan Haubenthal -; 2012-08-11, Greg King +; 2013-07-16, Greg King ; .include "zeropage.inc" @@ -66,10 +66,10 @@ YSIZE = 8 ; System font height ; Variables mapped to the zero page segment variables. Some of these are ; used for passing parameters to the driver. -X1 = ptr1 -Y1 = ptr2 -X2 = ptr3 -Y2 = ptr4 +X1 := ptr1 +Y1 := ptr2 +X2 := ptr3 +Y2 := ptr4 ; Absolute variables used in the code @@ -78,19 +78,7 @@ Y2 = ptr4 ERROR: .res 1 ; Error code MODE: .res 1 ; Graphics mode -; Constants and tables -PARAM1 = $2E1 -PARAM2 = $2E3 -PARAM3 = $2E5 -TEXT = $EC21 -HIRES = $EC33 -CURSET = $F0C8 -CURMOV = $F0FD -DRAW = $F110 -CHAR = $F12D -POINT = $F1C8 -PAPER = $F204 -INK = $F210 +; Constant table .rodata @@ -152,7 +140,7 @@ INIT: ; Must set an error code: NO ; -DONE = TEXT +DONE := TEXT ; ------------------------------------------------------------------------ ; GETERROR: Return the error code in A and clear it. @@ -170,7 +158,7 @@ GETERROR: ; CONTROL: - sta $213 + sta PATTERN lda #TGI_ERR_OK sta ERROR rts @@ -181,7 +169,7 @@ CONTROL: ; Must set an error code: NO ; -CLEAR = HIRES +CLEAR := HIRES ; ------------------------------------------------------------------------ ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n). diff --git a/libsrc/c128/libref.s b/libsrc/c128/libref.s index fb22515bd..4f65e3959 100644 --- a/libsrc/c128/libref.s +++ b/libsrc/c128/libref.s @@ -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 diff --git a/libsrc/c128/mou/c128-inkwell.s b/libsrc/c128/mou/c128-inkwell.s new file mode 100644 index 000000000..dc3469aac --- /dev/null +++ b/libsrc/c128/mou/c128-inkwell.s @@ -0,0 +1,457 @@ +; +; Driver for the Inkwell Systems 170-C and 184-C lightpens. +; +; 2013-07-01, Greg King +; + + .include "zeropage.inc" + .include "mouse-kernel.inc" + .include "c128.inc" + + .macpack generic + +; ------------------------------------------------------------------------ +; Header. Includes jump table. + +.segment "JUMPTABLE" + +HEADER: + +; Driver signature + + .byte $6d, $6f, $75 ; ASCII "mou" + .byte MOUSE_API_VERSION ; Mouse driver API version number + +; Library reference + +LIBREF: .addr $0000 + +; Jump table + + .addr INSTALL + .addr UNINSTALL + .addr HIDE + .addr SHOW + .addr SETBOX + .addr GETBOX + .addr MOVE + .addr BUTTONS + .addr POS + .addr INFO + .addr IOCTL + .addr IRQ + +; Mouse driver flags + + .byte MOUSE_FLAG_EARLY_IRQ + +; Callback table, set by the kernel before INSTALL is called. + +CHIDE: jmp $0000 ; Hide the cursor +CSHOW: jmp $0000 ; Show the cursor +CMOVEX: jmp $0000 ; Move the cursor to X co-ord. +CMOVEY: jmp $0000 ; Move the cursor to Y co-ord. + + +;---------------------------------------------------------------------------- +; Constants + +; This driver is for the 40-column screen. + +XSIZE = 40 +YSIZE = 25 + +SCREEN_WIDTH = XSIZE * 8 +SCREEN_HEIGHT = YSIZE * 8 + + +;---------------------------------------------------------------------------- +; Global variables. The bounding box values are sorted so that they can be +; 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: +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 + +INIT_save: .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 + +;---------------------------------------------------------------------------- +; INSTALL routine. Is called after the driver is loaded into memory. If +; possible, check if the hardware is present. +; Must return a MOUSE_ERR_xx code in .XA. + +INSTALL: + +; Disable the BASIC interpreter's interrupt-driven sprite-motion code. +; That allows direct access to the VIC-IIe's sprite registers. + + lda INIT_STATUS + sta INIT_save + lda #%11000000 + sta INIT_STATUS + +; Initiate variables. Just copy the default stuff over. + + ldx #.sizeof (DefVars) - 1 +@L0: lda DefVars,x + sta Vars,x + dex + bpl @L0 + + ldx VIC_LPEN_X + ldy VIC_LPEN_Y + stx OldPenX + sty OldPenY + +; Call a calibration function through the library-reference. + + lda LIBREF + ldx LIBREF+1 + sta ptr1 ; Point to mouse_adjuster + stx ptr1+1 + ldy #1 + lda (ptr1),y + bze @L1 ; Don't call pointer if it's NULL + sta Calibrate+2 ; Point to function + dey + lda (ptr1),y + sta Calibrate+1 + lda #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. + +@L1: sei + jsr CHIDE + + lda #<(SCREEN_HEIGHT / 2) + ldx #>(SCREEN_HEIGHT / 2) + jsr MoveY + lda #<(SCREEN_WIDTH / 2) + ldx #>(SCREEN_WIDTH / 2) + jsr MoveX + cli + +; Done, return zero. + + lda #MOUSE_ERR_OK + tax + rts + +;---------------------------------------------------------------------------- +; UNINSTALL routine. Is called before the driver is removed from memory. +; No return code required (the driver is removed from memory on return). + +UNINSTALL: + jsr HIDE ; Hide cursor on exit + lda INIT_save + sta INIT_STATUS + rts + +;---------------------------------------------------------------------------- +; HIDE routine. Is called to hide the lightpen pointer. The mouse kernel manages +; a counter for calls to show/hide, and the driver entry point is called only +; if the mouse is currently visible, and should get hidden. For most drivers, +; no special action is required besides hiding the lightpen cursor. +; No return code required. + +HIDE: sei + jsr CHIDE + cli + rts + +;---------------------------------------------------------------------------- +; SHOW routine. Is called to show the lightpen pointer. The mouse kernel manages +; a counter for calls to show/hide, and the driver entry point is called only +; if the mouse is currently hidden, and should become visible. For most drivers, +; no special action is required besides enabling the lightpen cursor. +; No return code required. + +SHOW: sei + jsr CSHOW + cli + rts + +;---------------------------------------------------------------------------- +; SETBOX: Set the lightpen bounding box. The parameters are passed as they come +; from the C program, that is, a pointer to a mouse_box struct in .XA. +; No checks are done if the lightpen is currently inside the box, that is the job +; of the caller. It is not necessary to validate the parameters; trust the +; caller; and, save some code here. No return code required. + +SETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX) - 1 + sei + +@L1: lda (ptr1),y + sta XMin,y + dey + bpl @L1 + + cli + rts + +;---------------------------------------------------------------------------- +; GETBOX: Return the lightpen bounding box. The parameters are passed as they +; come from the C program, that is, a pointer to a mouse_box struct in .XA. + +GETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX) - 1 +@L1: lda XMin,y + sta (ptr1),y + dey + bpl @L1 + rts + +;---------------------------------------------------------------------------- +; MOVE: Move the mouse to a new position. The position is passed as it comes +; from the C program, that is: X on the stack and Y in .XA. The C wrapper will +; remove the parameter from the stack on return. +; No checks are done if the new position is valid (within the bounding box or +; the screen). No return code required. +; + +MOVE: sei ; No interrupts + jsr MoveY + + ldy #$01 + lda (sp),y + tax + dey + lda (sp),y + jsr MoveX ; Move the cursor + + cli ; Allow interrupts + rts + +;---------------------------------------------------------------------------- +; BUTTONS: Return the button mask in .XA. + +BUTTONS: + lda Buttons + ldx #>0 + +; Make the lightpen buttons look like a 1351 mouse. + + asl a + asl SID_ADConv2 ; PotY + rol a + eor #MOUSE_BTN_RIGHT + and #MOUSE_BTN_LEFT | MOUSE_BTN_RIGHT + rts + +;---------------------------------------------------------------------------- +; POS: Return the lightpen position in the MOUSE_POS struct pointed to by ptr1. +; No return code required. + +POS: ldy #MOUSE_POS::XCOORD ; Structure offset + + sei ; Disable interrupts + lda XPos ; Transfer the position + sta (ptr1),y + lda XPos+1 + iny + sta (ptr1),y + lda YPos + iny + sta (ptr1),y + lda YPos+1 + cli ; Enable interrupts + + iny + sta (ptr1),y ; Store last byte + rts + +;---------------------------------------------------------------------------- +; INFO: Returns lightpen position and current button mask in the MOUSE_INFO +; struct pointed to by ptr1. No return code required. +; +; We're cheating here, to keep the code smaller: The first fields of the +; mouse_info struct are identical to the mouse_pos struct; so, we'll just +; call _mouse_pos to initiate the struct pointer, and fill the position +; fields. + +INFO: jsr POS + +; Fill in the button state + + jsr BUTTONS ; Will not touch ptr1 + ldy #MOUSE_INFO::BUTTONS + sta (ptr1),y + rts + +;---------------------------------------------------------------------------- +; IOCTL: Driver-defined entry point. The wrapper will pass a pointer to ioctl- +; specific data in ptr1, and the ioctl code in .A. +; Must return an error code in .XA. +; + +IOCTL: lda #MOUSE_ERR_INV_IOCTL + rts + +;---------------------------------------------------------------------------- +; IRQ: IRQ handler entry point. Called as a subroutine, but in the IRQ context +; (so, be careful). The routine MUST return carry set if the interrupt has been +; 'handled' -- which means that the interrupt source is gone. Otherwise, it +; MUST return carry clear. +; + +IRQ: + +; Record the state of the buttons. +; Try to avoid crosstalk between the keyboard and the lightpen. + + ldy #%00000000 ; Set ports A and B to input + sty CIA1_DDRB + sty CIA1_DDRA ; Keyboard won't look like buttons + lda CIA1_PRB ; Read Control-Port 1 + dec CIA1_DDRA ; Set port A back to output + eor #%11111111 ; Bit goes up when button goes down + sta Buttons + bze @L0 + lda #%11101111 ; (Don't change bit that feeds VIC-II) + sta CIA1_DDRB ; Buttons won't look like keyboard + sty CIA1_PRB ; Set "all keys pushed" + +; Read the VIC-II lightpen registers. + +@L0: lda VIC_LPEN_Y + cmp OldPenY + +; Skip processing if nothing has changed. + + beq @SkipY + sta OldPenY + +; Subtract the height of the top border, so that the lightpen co-ordinate +; will match the TGI co-ordinate. + + sub #50 + tay ; Remember low byte + ldx #>0 + +; Limit the Y co-ordinate to the bounding box. + + txa + cpy YMin + sbc YMin+1 + bpl @L3 + ldy YMin + ldx YMin+1 + jmp @L4 + +@L3: txa + cpy YMax + sbc YMax+1 + bmi @L4 + ldy YMax + ldx YMax+1 + +@L4: tya + jsr MoveY + +@SkipY: lda VIC_LPEN_X + cmp OldPenX + +; Skip processing if nothing has changed. + + beq @SkipX + sta OldPenX + +; Adjust the value by the calibration offset. + + sub XOffset + +; 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. + + asl a + tay ; Remember low byte + lda #>0 + rol a + tax ; Remember high byte + +; Limit the X co-ordinate to the bounding box. + + cpy XMin + sbc XMin+1 + bpl @L1 + ldy XMin + ldx XMin+1 + jmp @L2 + +@L1: txa + cpy XMax + sbc XMax+1 + bmi @L2 + ldy XMax + ldx XMax+1 + +@L2: tya + jsr MoveX + +; Done + +@SkipX: clc ; Interrupt not "handled" + rts + +; Move the lightpen pointer to the new Y pos. + +MoveY: sta YPos + stx YPos+1 + jmp CMOVEY + +; Move the lightpen pointer to the new X pos. + +MoveX: sta XPos + stx XPos+1 + jmp CMOVEX diff --git a/libsrc/c128/mouseref.s b/libsrc/c128/mouseref.s new file mode 100644 index 000000000..90aeedf3a --- /dev/null +++ b/libsrc/c128/mouseref.s @@ -0,0 +1,23 @@ +; +; Pointer for library references by device drivers. +; +; 2013-07-25, Greg King +; + + .export mouse_libref, _pen_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__ (*pen_adjuster)(unsigned char *) = NULL; +; +_pen_adjuster: + .addr $0000 diff --git a/libsrc/c128/pencalib.c b/libsrc/c128/pencalib.c new file mode 100644 index 000000000..b7bd701ec --- /dev/null +++ b/libsrc/c128/pencalib.c @@ -0,0 +1,93 @@ +/* +** Calibrate lightpen drivers to the current video hardware. +** +** 2013-07-25, Greg King +** +*/ + + +#include +#include +#include + + +#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 (); +} diff --git a/libsrc/c64/libref.s b/libsrc/c64/libref.s index fb22515bd..4f65e3959 100644 --- a/libsrc/c64/libref.s +++ b/libsrc/c64/libref.s @@ -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 diff --git a/libsrc/c64/mou/c64-inkwell.s b/libsrc/c64/mou/c64-inkwell.s new file mode 100644 index 000000000..070d8f108 --- /dev/null +++ b/libsrc/c64/mou/c64-inkwell.s @@ -0,0 +1,438 @@ +; +; Driver for the Inkwell Systems 170-C and 184-C lightpens. +; +; 2013-07-01, Greg King +; + + .include "zeropage.inc" + .include "mouse-kernel.inc" + .include "c64.inc" + + .macpack generic + +; ------------------------------------------------------------------------ +; Header. Includes jump table. + +.segment "JUMPTABLE" + +HEADER: + +; Driver signature + + .byte $6d, $6f, $75 ; ASCII "mou" + .byte MOUSE_API_VERSION ; Mouse driver API version number + +; Library reference + +LIBREF: .addr $0000 + +; Jump table + + .addr INSTALL + .addr UNINSTALL + .addr HIDE + .addr SHOW + .addr SETBOX + .addr GETBOX + .addr MOVE + .addr BUTTONS + .addr POS + .addr INFO + .addr IOCTL + .addr IRQ + +; Mouse driver flags + + .byte MOUSE_FLAG_EARLY_IRQ + +; Callback table, set by the kernel before INSTALL is called. + +CHIDE: jmp $0000 ; Hide the cursor +CSHOW: jmp $0000 ; Show the cursor +CMOVEX: jmp $0000 ; Move the cursor to X co-ord. +CMOVEY: jmp $0000 ; Move the cursor to Y co-ord. + + +;---------------------------------------------------------------------------- +; Constants + +SCREEN_WIDTH = XSIZE * 8 +SCREEN_HEIGHT = YSIZE * 8 + + +;---------------------------------------------------------------------------- +; Global variables. The bounding box values are sorted so that they can be +; 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: +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 + +;---------------------------------------------------------------------------- +; INSTALL routine. Is called after the driver is loaded into memory. If +; possible, check if the hardware is present. +; Must return a MOUSE_ERR_xx code in .XA. + +INSTALL: + +; Initiate variables. Just copy the default stuff over. + + ldx #.sizeof (DefVars) - 1 +@L0: lda DefVars,x + sta Vars,x + dex + bpl @L0 + + ldx VIC_LPEN_X + ldy VIC_LPEN_Y + stx OldPenX + sty OldPenY + +; Call a calibration function through the library-reference. + + lda LIBREF + ldx LIBREF+1 + sta ptr1 ; Point to mouse_adjuster + stx ptr1+1 + ldy #1 + lda (ptr1),y + bze @L1 ; Don't call pointer if it's NULL + sta Calibrate+2 ; Point to function + dey + lda (ptr1),y + sta Calibrate+1 + lda #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. + +@L1: sei + jsr CHIDE + + lda #<(SCREEN_HEIGHT / 2) + ldx #>(SCREEN_HEIGHT / 2) + jsr MoveY + lda #<(SCREEN_WIDTH / 2) + ldx #>(SCREEN_WIDTH / 2) + jsr MoveX + cli + +; Done, return zero. + + lda #MOUSE_ERR_OK + tax + rts + +;---------------------------------------------------------------------------- +; UNINSTALL routine. Is called before the driver is removed from memory. +; No return code required (the driver is removed from memory on return). + +UNINSTALL := HIDE ; Hide cursor on exit + +;---------------------------------------------------------------------------- +; HIDE routine. Is called to hide the lightpen pointer. The mouse kernel manages +; a counter for calls to show/hide, and the driver entry point is called only +; if the mouse is currently visible, and should get hidden. For most drivers, +; no special action is required besides hiding the lightpen cursor. +; No return code required. + +HIDE: sei + jsr CHIDE + cli + rts + +;---------------------------------------------------------------------------- +; SHOW routine. Is called to show the lightpen pointer. The mouse kernel manages +; a counter for calls to show/hide, and the driver entry point is called only +; if the mouse is currently hidden, and should become visible. For most drivers, +; no special action is required besides enabling the lightpen cursor. +; No return code required. + +SHOW: sei + jsr CSHOW + cli + rts + +;---------------------------------------------------------------------------- +; SETBOX: Set the lightpen bounding box. The parameters are passed as they come +; from the C program, that is, a pointer to a mouse_box struct in .XA. +; No checks are done if the lightpen is currently inside the box, that is the job +; of the caller. It is not necessary to validate the parameters; trust the +; caller; and, save some code here. No return code required. + +SETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX) - 1 + sei + +@L1: lda (ptr1),y + sta XMin,y + dey + bpl @L1 + + cli + rts + +;---------------------------------------------------------------------------- +; GETBOX: Return the lightpen bounding box. The parameters are passed as they +; come from the C program, that is, a pointer to a mouse_box struct in .XA. + +GETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX) - 1 +@L1: lda XMin,y + sta (ptr1),y + dey + bpl @L1 + rts + +;---------------------------------------------------------------------------- +; MOVE: Move the mouse to a new position. The position is passed as it comes +; from the C program, that is: X on the stack and Y in .XA. The C wrapper will +; remove the parameter from the stack on return. +; No checks are done if the new position is valid (within the bounding box or +; the screen). No return code required. +; + +MOVE: sei ; No interrupts + jsr MoveY + + ldy #$01 + lda (sp),y + tax + dey + lda (sp),y + jsr MoveX ; Move the cursor + + cli ; Allow interrupts + rts + +;---------------------------------------------------------------------------- +; BUTTONS: Return the button mask in .XA. + +BUTTONS: + lda Buttons + ldx #>0 + +; Make the lightpen buttons look like a 1351 mouse. + + asl a + asl SID_ADConv2 ; PotY + rol a + eor #MOUSE_BTN_RIGHT + and #MOUSE_BTN_LEFT | MOUSE_BTN_RIGHT + rts + +;---------------------------------------------------------------------------- +; POS: Return the lightpen position in the MOUSE_POS struct pointed to by ptr1. +; No return code required. + +POS: ldy #MOUSE_POS::XCOORD ; Structure offset + + sei ; Disable interrupts + lda XPos ; Transfer the position + sta (ptr1),y + lda XPos+1 + iny + sta (ptr1),y + lda YPos + iny + sta (ptr1),y + lda YPos+1 + cli ; Enable interrupts + + iny + sta (ptr1),y ; Store last byte + rts + +;---------------------------------------------------------------------------- +; INFO: Returns lightpen position and current button mask in the MOUSE_INFO +; struct pointed to by ptr1. No return code required. +; +; We're cheating here, to keep the code smaller: The first fields of the +; mouse_info struct are identical to the mouse_pos struct; so, we'll just +; call _mouse_pos to initiate the struct pointer, and fill the position +; fields. + +INFO: jsr POS + +; Fill in the button state + + jsr BUTTONS ; Will not touch ptr1 + ldy #MOUSE_INFO::BUTTONS + sta (ptr1),y + rts + +;---------------------------------------------------------------------------- +; IOCTL: Driver-defined entry point. The wrapper will pass a pointer to ioctl- +; specific data in ptr1, and the ioctl code in .A. +; Must return an error code in .XA. +; + +IOCTL: lda #MOUSE_ERR_INV_IOCTL + rts + +;---------------------------------------------------------------------------- +; IRQ: IRQ handler entry point. Called as a subroutine, but in the IRQ context +; (so, be careful). The routine MUST return carry set if the interrupt has been +; 'handled' -- which means that the interrupt source is gone. Otherwise, it +; MUST return carry clear. +; + +IRQ: + +; Record the state of the buttons. +; Try to avoid crosstalk between the keyboard and the lightpen. + + ldy #%00000000 ; Set ports A and B to input + sty CIA1_DDRB + sty CIA1_DDRA ; Keyboard won't look like buttons + lda CIA1_PRB ; Read Control-Port 1 + dec CIA1_DDRA ; Set port A back to output + eor #%11111111 ; Bit goes up when button goes down + sta Buttons + bze @L0 + lda #%11101111 ; (Don't change bit that feeds VIC-II) + sta CIA1_DDRB ; Buttons won't look like keyboard + sty CIA1_PRB ; Set "all keys pushed" + +; Read the VIC-II lightpen registers. + +@L0: lda VIC_LPEN_Y + cmp OldPenY + +; Skip processing if nothing has changed. + + beq @SkipY + sta OldPenY + +; Subtract the height of the top border, so that the lightpen co-ordinate +; will match the TGI co-ordinate. + + sub #50 + tay ; Remember low byte + ldx #>0 + +; Limit the Y co-ordinate to the bounding box. + + txa + cpy YMin + sbc YMin+1 + bpl @L3 + ldy YMin + ldx YMin+1 + jmp @L4 + +@L3: txa + cpy YMax + sbc YMax+1 + bmi @L4 + ldy YMax + ldx YMax+1 + +@L4: tya + jsr MoveY + +@SkipY: lda VIC_LPEN_X + cmp OldPenX + +; Skip processing if nothing has changed. + + beq @SkipX + sta OldPenX + +; Adjust the value by the calibration offset. + + sub XOffset + +; 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. + + asl a + tay ; Remember low byte + lda #>0 + rol a + tax ; Remember high byte + +; Limit the X co-ordinate to the bounding box. + + cpy XMin + sbc XMin+1 + bpl @L1 + ldy XMin + ldx XMin+1 + jmp @L2 + +@L1: txa + cpy XMax + sbc XMax+1 + bmi @L2 + ldy XMax + ldx XMax+1 + +@L2: tya + jsr MoveX + +; Done + +@SkipX: clc ; Interrupt not "handled" + rts + +; Move the lightpen pointer to the new Y pos. + +MoveY: sta YPos + stx YPos+1 + jmp CMOVEY + +; Move the lightpen pointer to the new X pos. + +MoveX: sta XPos + stx XPos+1 + jmp CMOVEX diff --git a/libsrc/c64/mouseref.s b/libsrc/c64/mouseref.s new file mode 100644 index 000000000..90aeedf3a --- /dev/null +++ b/libsrc/c64/mouseref.s @@ -0,0 +1,23 @@ +; +; Pointer for library references by device drivers. +; +; 2013-07-25, Greg King +; + + .export mouse_libref, _pen_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__ (*pen_adjuster)(unsigned char *) = NULL; +; +_pen_adjuster: + .addr $0000 diff --git a/libsrc/c64/pencalib.c b/libsrc/c64/pencalib.c new file mode 100644 index 000000000..00629d512 --- /dev/null +++ b/libsrc/c64/pencalib.c @@ -0,0 +1,94 @@ +/* +** Calibrate lightpen drivers to the current video hardware. +** +** 2013-07-25, Greg King +** +*/ + + +#include +#include +#include + + +#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 (); +} diff --git a/libsrc/cbm/penadjust.c b/libsrc/cbm/penadjust.c new file mode 100644 index 000000000..8b788dd33 --- /dev/null +++ b/libsrc/cbm/penadjust.c @@ -0,0 +1,54 @@ +/* +** Main lightpen driver calibration functions. +** +** 2013-07-25, Greg King +*/ + + +#include +#include +#include +#include + + +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 pen_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; + pen_adjuster = adjuster; + } else { + pen_adjuster = pen_calibrate; + } +} diff --git a/samples/Makefile b/samples/Makefile index 046eb8fc9..a17288ced 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -30,21 +30,14 @@ LD = ld65 else # "samples/" is a part of a complete source tree. -CA65_INC = ../asminc -CC65_INC = ../include -LD65_CFG = ../src/ld65/cfg -LD65_LIB = ../libsrc -LD65_OBJ = ../libsrc -MOUS = ../libsrc/$(SYS)*.mou -TGI = ../libsrc/$(SYS)*.tgi -CLIB = ../libsrc/$(SYS).lib -CL = ../src/cl65/cl65 -CC = ../src/cc65/cc65 -AS = ../src/ca65/ca65 -LD = ../src/ld65/ld65 - -MY_INC = --forget-inc-paths -I . -I $(CC65_INC) -MY_ASM = --forget-inc-paths -I . -I $(CA65_INC) +export CC65_HOME := $(abspath ..) +MOUS = ../mou/$(SYS)*.mou +TGI = ../tgi/$(SYS)*.tgi +CLIB = ../lib/$(SYS).lib +CL = ../bin/cl65 +CC = ../bin/cc65 +AS = ../bin/ca65 +LD = ../bin/ld65 endif # This one comes with VICE @@ -54,17 +47,20 @@ C1541 = c1541 # -------------------------------------------------------------------------- # Generic rules +%: %.c +%: %.s + .c.o: @echo $< - @$(CC) $(MY_INC) -Oirs --codesize 500 -T -g -t $(SYS) $< - @$(AS) $(basename $<).s + @$(CC) $(CFLAGS) -Oirs --codesize 500 -T -g -t $(SYS) $< + @$(AS) $(<:.c=.s) .s.o: @echo $< - @$(AS) $(MY_ASM) -t $(SYS) $< + @$(AS) $(AFLAGS) -t $(SYS) $< .o: - @$(LD) -o $@ -t $(SYS) -m $(basename $@).map $^ $(CLIB) + @$(LD) -o $@ -t $(SYS) -m $@.map $^ $(CLIB) # -------------------------------------------------------------------------- @@ -78,7 +74,7 @@ EXELIST = ascii \ gunzip65 \ hello \ mandelbrot \ - mousedemo \ + mousetest \ multdemo \ nachtm \ ovrldemo \ @@ -105,31 +101,31 @@ hello: hello.o # The Apple machines need the start address adjusted for the mandelbrot demo ifeq "$(SYS)" "apple2" mandelbrot: mandelbrot.o - @$(LD) -t $(SYS) -m $(basename $@).map --start-addr 0x4000 -o $@ $^ $(CLIB) + @$(LD) -o $@ -t $(SYS) -m $@.map --start-addr 0x4000 $^ $(CLIB) else ifeq "$(SYS)" "apple2enh" mandelbrot: mandelbrot.o - @$(LD) -t $(SYS) -m $(basename $@).map --start-addr 0x4000 -o $@ $^ $(CLIB) + @$(LD) -o $@ -t $(SYS) -m $@.map --start-addr 0x4000 $^ $(CLIB) else mandelbrot: mandelbrot.o endif endif -# The Apple ][ needs the start address adjusted for the mousedemo +# The Apple ][ needs the start address adjusted for the mousetest ifeq "$(SYS)" "apple2" -mousedemo: mousedemo.o - @$(LD) -t $(SYS) -m $(basename $@).map --start-addr 0x4000 -o $@ $^ $(CLIB) +mousetest: mousetest.o + @$(LD) -o $@ -t $(SYS) -m $@.map --start-addr 0x4000 $^ $(CLIB) else -mousedemo: mousedemo.o +mousetest: mousetest.o endif multdemo: multidemo.o - @$(LD) -t $(SYS) -m $(basename $@).map -C $(SYS)-overlay.cfg -o $@ $^ $(CLIB) + @$(LD) -o $@ -m $@.map -C $(SYS)-overlay.cfg $^ $(CLIB) nachtm: nachtm.o ovrldemo: overlaydemo.o - @$(LD) -t $(SYS) -m $(basename $@).map -C $(SYS)-overlay.cfg -o $@ $^ $(CLIB) + @$(LD) -o $@ -m $@.map -C $(SYS)-overlay.cfg $^ $(CLIB) plasma: plasma.o @@ -138,11 +134,11 @@ sieve: sieve.o # The Apple machines need the start address adjusted for the tgidemo ifeq "$(SYS)" "apple2" tgidemo: tgidemo.o - @$(LD) -t $(SYS) -m $(basename $@).map --start-addr 0x4000 -o $@ $^ $(CLIB) + @$(LD) -o $@ -t $(SYS) -m $@.map --start-addr 0x4000 $^ $(CLIB) else ifeq "$(SYS)" "apple2enh" tgidemo: tgidemo.o - @$(LD) -t $(SYS) -m $(basename $@).map --start-addr 0x4000 -o $@ $^ $(CLIB) + @$(LD) -o $@ -t $(SYS) -m $@.map --start-addr 0x4000 $^ $(CLIB) else tgidemo: tgidemo.o endif diff --git a/samples/README b/samples/README index 25ee43118..5997fc8d0 100644 --- a/samples/README +++ b/samples/README @@ -69,8 +69,8 @@ Platforms: Runs on all platforms that have TGI support: Apple ][, C64, C128, Oric Atmos, Geos and Lynx. ----------------------------------------------------------------------------- -Name: mousedemo -Description: Shows how to use the mouse. +Name: mousetest +Description: Tests and shows how to use the mouse. Platforms: All systems with mouse and conio support: C64, C128, CBM510, Atari, Apple ][ diff --git a/samples/mousedemo.c b/samples/mousedemo.c deleted file mode 100644 index d5d0e36a6..000000000 --- a/samples/mousedemo.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Demo program for mouse usage. Will work for the C64/C128/CBM510/Atari/Apple2 - * - * Ullrich von Bassewitz, 13.09.2001 - * - */ - - - -#include -#include -#include -#include -#include -#include - - - -#if defined(__C64__) || defined(__C128__) - -/* Address of data for sprite 0 */ -#if defined(__C64__) -# define SPRITE0_DATA 0x0340 -# define SPRITE0_PTR 0x07F8 -#elif defined(__C128__) -# define SPRITE0_DATA 0x0E00 -# define SPRITE0_PTR 0x07F8 -#endif - -/* The mouse sprite (an arrow) */ -static const unsigned char MouseSprite[64] = { - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x0F, 0xE0, 0x00, - 0x0F, 0xC0, 0x00, - 0x0F, 0x80, 0x00, - 0x0F, 0xC0, 0x00, - 0x0D, 0xE0, 0x00, - 0x08, 0xF0, 0x00, - 0x00, 0x78, 0x00, - 0x00, 0x3C, 0x00, - 0x00, 0x1E, 0x00, - 0x00, 0x0F, 0x00, - 0x00, 0x07, 0x80, - 0x00, 0x03, 0x80, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x00 -}; - -#endif /* __C64__ or __C128__ */ - - -/* Dynamically loaded driver by default */ -#ifndef DYN_DRV -# define DYN_DRV 1 -#endif - - -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#define min(a,b) (((a) < (b)) ? (a) : (b)) - - - -static void CheckError (const char* S, unsigned char Error) -{ - if (Error != MOUSE_ERR_OK) { - cprintf ("%s: %s(%d)\r\n", S, mouse_geterrormsg (Error), Error); - exit (EXIT_FAILURE); - } -} - - - -static void DoWarning (void) -/* Warn the user that a mouse driver is needed for this program */ -{ - cprintf ("Warning: This program needs the mouse\r\n" - "driver with the name\r\n" - " %s\r\n" - "on disk! Press 'y' if you have it or\r\n" - "any other key to exit.\r\n", mouse_stddrv); - if (tolower (cgetc ()) != 'y') { - exit (EXIT_SUCCESS); - } - cprintf ("Ok. Please wait patiently...\r\n"); -} - - - -static void ShowState (unsigned char Jailed, unsigned char Invisible) -/* Display jail and cursor state */ -{ - gotoxy (0, 6); - cclear (40); - gotoxy (0, 6); - cprintf ("Mouse cursor %svisible%s", Invisible? "in" : "", Jailed? ", jailed" : ""); -} - - - -int main (void) -{ - struct mouse_info info; - struct mouse_box full_box; - struct mouse_box small_box; - unsigned char Invisible; - unsigned char Done; - unsigned char Jailed; - - /* Initialize the debugger */ - DbgInit (0); - - /* Clear the screen, set white on black */ - (void) bordercolor (COLOR_BLACK); - (void) bgcolor (COLOR_BLACK); - (void) textcolor (COLOR_GRAY3); - cursor (0); - clrscr (); - -#if defined(__C64__) || defined(__C128__) || defined(__CBM510__) - /* Copy the sprite data */ - memcpy ((void*) SPRITE0_DATA, MouseSprite, sizeof (MouseSprite)); - - /* Set the VIC sprite pointer */ - *(unsigned char*)SPRITE0_PTR = SPRITE0_DATA / 64; - - /* Set the color of sprite 0 */ -#ifdef __CBM510__ - pokebsys ((unsigned) &VIC.spr0_color, COLOR_WHITE); -#else - VIC.spr0_color = COLOR_WHITE; -#endif - -#endif - -#if DYN_DRV - /* Output a warning about the driver that is needed */ - DoWarning (); - - /* Load and install the mouse driver */ - CheckError ("mouse_load_driver", - mouse_load_driver (&mouse_def_callbacks, mouse_stddrv)); -#else - /* Install the mouse driver */ - CheckError ("mouse_install", - mouse_install (&mouse_def_callbacks, mouse_static_stddrv)); -#endif - - /* Get the initial mouse bounding box */ - mouse_getbox (&full_box); - - /* Print a help line */ - clrscr (); - revers (1); - cputsxy (0, 0, "d)ebug h)ide q)uit s)how j)ail "); - revers (0); - - /* Test loop */ - Done = 0; - Jailed = 0; - Invisible = 1; - ShowState (Jailed, Invisible); - while (!Done) { - - /* Get the current mouse coordinates and button states and print them */ - mouse_info (&info); - gotoxy (0, 2); - cprintf ("X = %3d", info.pos.x); - gotoxy (0, 3); - cprintf ("Y = %3d", info.pos.y); - gotoxy (0, 4); - cprintf ("LB = %c", (info.buttons & MOUSE_BTN_LEFT)? '1' : '0'); - gotoxy (0, 5); - cprintf ("RB = %c", (info.buttons & MOUSE_BTN_RIGHT)? '1' : '0'); - - /* Handle user input */ - if (kbhit ()) { - switch (tolower (cgetc ())) { - - case 'd': - BREAK(); - break; - - case 'h': - ShowState (Jailed, ++Invisible); - mouse_hide (); - break; - - case 'j': - if (Jailed) { - Jailed = 0; - mouse_setbox (&full_box); - } else { - Jailed = 1; - small_box.minx = max (info.pos.x - 10, full_box.minx); - small_box.miny = max (info.pos.y - 10, full_box.miny); - small_box.maxx = min (info.pos.x + 10, full_box.maxx); - small_box.maxy = min (info.pos.y + 10, full_box.maxy); - mouse_setbox (&small_box); - } - ShowState (Jailed, Invisible); - break; - - case 's': - if (Invisible) { - ShowState (Jailed, --Invisible); - mouse_show (); - } - break; - - case 'q': - Done = 1; - break; - } - } - - } - -#if DYN_DRV - /* Uninstall and unload the mouse driver */ - CheckError ("mouse_unload", mouse_unload ()); -#else - /* Uninstall the mouse driver */ - CheckError ("mouse_uninstall", mouse_uninstall ()); -#endif - - /* Say goodbye */ - clrscr (); - cputs ("Goodbye!\r\n"); - - return EXIT_SUCCESS; -} diff --git a/samples/mousetest.c b/samples/mousetest.c new file mode 100644 index 000000000..dd90e0990 --- /dev/null +++ b/samples/mousetest.c @@ -0,0 +1,323 @@ +/* +** Test/demo program for mouse usage. +** Will work for the C64/C128/CBM510/Atari/Apple2. +** +** 2001-09-13, Ullrich von Bassewitz +** 2013-07-25, Greg King +** +*/ + + + +#include +#include +#include +#include +#include +#include +#include +#include + +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) + + + +#ifdef MOUSE_DRIVER + +/* A statically linked driver was named on the compiler's command line. +** Make sure that it is used instead of a dynamic one. +*/ +# undef DYN_DRV +# define DYN_DRV 0 +#else + +/* Use a dynamically loaded driver, by default. */ +# ifndef DYN_DRV +# define DYN_DRV 1 +# endif +#endif + + + +#if defined(__C64__) || defined(__C128__) || defined(__CBM510__) + +/* Addresses of data for sprite 0 */ +#if defined(__C64__) +# define SPRITE0_DATA ((unsigned char[64])0x0340) +# define SPRITE0_PTR ((unsigned char *)0x07F8) +#elif defined(__C128__) +# define SPRITE0_DATA ((unsigned char[64])0x0E00) +# define SPRITE0_PTR ((unsigned char *)0x07F8) +#elif defined(__CBM510__) +# define SPRITE0_DATA ((unsigned char[64])0xF400) +# define SPRITE0_PTR ((unsigned char *)0xF3F8) +#endif + +/* The mouse sprite (an arrow) */ +static const unsigned char MouseSprite[64] = { + 0xFE, 0x00, 0x00, + 0xFC, 0x00, 0x00, + 0xF8, 0x00, 0x00, + 0xFC, 0x00, 0x00, + 0xDE, 0x00, 0x00, + 0x8F, 0x00, 0x00, + 0x07, 0x80, 0x00, + 0x03, 0xC0, 0x00, + 0x01, 0xE0, 0x00, + 0x00, 0xF0, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x38, 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 +}; +#endif + + + +static void __fastcall__ CheckError (const char* S, unsigned char Error) +{ + if (Error != MOUSE_ERR_OK) { + cprintf ("%s: %s(%u)\r\n", S, mouse_geterrormsg (Error), Error); + exit (EXIT_FAILURE); + } +} + + + +#if DYN_DRV + +/* Points to the dynamic driver's name. */ +static const char *mouse_name; + + + +static void DoWarning (void) +/* Warn the user that a driver is needed for this program. */ +{ + cprintf ("Warning: This program needs\r\n" + "the driver with the name\r\n" + " %s\r\n" + "on a disk! Press 'y' if you have it;\r\n" + "or, any other key to exit.\r\n", mouse_stddrv); + if (tolower (cgetc ()) != 'y') { + exit (EXIT_SUCCESS); + } + cprintf ("OK. Please wait patiently...\r\n"); +} +#endif + + + +static void __fastcall__ ShowState (unsigned char Jailed, unsigned char Invisible) +/* Display jail and cursor states. */ +{ + cclearxy (0, 7, 32); + gotoxy (0, 7); + cprintf ("Pointer is %svisible%s.", Invisible? "in" : "", Jailed? " and jailed" : ""); +} + + + +#if DYN_DRV +int main (int argc, char *argv[]) +#else +int main (void) +#endif +{ + struct mouse_info info; + struct mouse_box full_box, small_box; + unsigned char width, height; + char C; + bool Invisible = true, Done = false, Jailed = false; + + /* Initialize the debugger */ + DbgInit (0); + + /* Set dark-on-light colors. Clear the screen. */ +#ifdef __CBM__ + (void) bordercolor (COLOR_GRAY2); + (void) bgcolor (COLOR_WHITE); + (void) textcolor (COLOR_GRAY1); +#else + (void) bordercolor (COLOR_BLUE); + (void) bgcolor (COLOR_WHITE); + (void) textcolor (COLOR_BLACK); +#endif + cursor (0); + clrscr (); + + /* The pointer is created before the driver is installed, + ** in case a lightpen driver needs it during calibration. + */ + +#if defined(__C64__) || defined(__C128__) || defined(__CBM510__) + /* Copy the sprite data */ + memcpy ((void*) SPRITE0_DATA, MouseSprite, sizeof (MouseSprite)); + + /* Set the VIC-II sprite pointer. */ + *SPRITE0_PTR = ((unsigned) SPRITE0_DATA & 0x3FFF) / sizeof SPRITE0_DATA; + + /* Set the color of sprite 0 */ +# ifdef __CBM510__ + pokebsys ((unsigned) &VIC.spr0_color, COLOR_BLACK); +# else + VIC.spr0_color = COLOR_BLACK; +# endif +#endif + + /* If a lightpen driver is installed, then it can get a calibration value + ** from this file (if it exists). Or, the user can adjust the pen; and, + ** the value will be put into this file, for the next time. + ** (Other drivers will ignore this.) + */ +#ifdef __CBM__ + pen_adjust ("pen.dat"); +#endif + +#if DYN_DRV + /* If a dynamically loadable driver is named on the command line, + ** then use that driver instead of the standard one. + */ + if (argc > 1) { + mouse_name = argv[1]; + } else { + /* Output a warning about the standard driver that is needed. */ + DoWarning (); + mouse_name = mouse_stddrv; + } + + /* Load and install the driver. */ + CheckError ("mouse_load_driver", + mouse_load_driver (&mouse_def_callbacks, mouse_name)); +#else + /* Install the driver. */ + CheckError ("mouse_install", + mouse_install (&mouse_def_callbacks, +# ifdef MOUSE_DRIVER + MOUSE_DRIVER +# else + mouse_static_stddrv +# endif + )); +#endif + + /* Get the initial bounding box. */ + mouse_getbox (&full_box); + + screensize (&width, &height); + +top: + clrscr (); + + /* 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, ""); + + /* Test loop */ + ShowState (Jailed, Invisible); + do { + /* Get the current co-ordinates and button states; and, print them. */ + mouse_info (&info); + 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) ? +#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 ()) { + cclearxy (1, 9, 23); + switch (tolower (C = cgetc ())) { + case 'd': + BREAK(); + + /* The debugger might have changed the colors. + ** Restore them. + */ +#ifdef __CBM__ + (void) bordercolor (COLOR_GRAY2); + (void) bgcolor (COLOR_WHITE); + (void) textcolor (COLOR_GRAY1); +#else + (void) bordercolor (COLOR_BLUE); + (void) bgcolor (COLOR_WHITE); + (void) textcolor (COLOR_BLACK); +#endif + + /* The debugger changed the screen; restore it. */ + goto top; + + case 'h': + mouse_hide (); + ShowState (Jailed, ++Invisible); + break; + + case 'j': + if (Jailed) { + mouse_setbox (&full_box); + Jailed = false; + } else { + small_box.minx = max (info.pos.x - 10, full_box.minx); + small_box.miny = max (info.pos.y - 10, full_box.miny); + small_box.maxx = min (info.pos.x + 10, full_box.maxx); + small_box.maxy = min (info.pos.y + 10, full_box.maxy); + mouse_setbox (&small_box); + Jailed = true; + } + ShowState (Jailed, Invisible); + break; + + case 's': + mouse_show (); + if (Invisible) { + ShowState (Jailed, --Invisible); + } + break; + + case 'q': + Done = true; + break; + + default: + gotoxy (1, 9); + cprintf ("Spurious character: $%02X", C); + } + } + } while (!Done); + +#if DYN_DRV + /* Uninstall and unload the driver. */ + CheckError ("mouse_unload", mouse_unload ()); +#else + /* Uninstall the static driver. */ + CheckError ("mouse_uninstall", mouse_uninstall ()); +#endif + + /* Say goodbye */ + cputsxy (0, height / 2 + 3, "Goodbye!"); + return EXIT_SUCCESS; +}