Merge branch 'master' into c1p
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
;
|
||||
|
||||
.export _open, closedirect, freebuffer
|
||||
.export __filetype, __auxtype
|
||||
.export __filetype, __auxtype, __datetime
|
||||
.constructor raisefilelevel
|
||||
.destructor closeallfiles, 5
|
||||
|
||||
@@ -246,5 +246,6 @@ __filetype:
|
||||
__auxtype:
|
||||
.word $0000 ; AUX_TYPE: Load address N/A
|
||||
.byte $01 ; STORAGE_TYPE: Standard seedling file
|
||||
__datetime:
|
||||
.word $0000 ; CREATE_DATE: Current date
|
||||
.word $0000 ; CREATE_TIME: Current time
|
||||
|
||||
@@ -14,3 +14,20 @@
|
||||
# needs DEFAULT_DEVICE to be defined, otherwise no effect
|
||||
|
||||
CA65FLAGS += -D NUMDRVS=4 -D LINEBUF=80 -D UCASE_FILENAME=1 -D DEFAULT_DEVICE=1 -D DYNAMIC_DD=1
|
||||
|
||||
# The following defines are only used by the 'atarixl' target:
|
||||
#
|
||||
# CHARGEN_RELOC - If defined, CHBAS and CHBASE are updated when
|
||||
# enabling or disabling the ROM.
|
||||
# If the ROM is enabled, $E0 is written to CHBAS
|
||||
# and CHBASE.
|
||||
# If the ROM is disabled, the upper byte of
|
||||
# __CHARGEN_START__ is written to CHBAS and CHBASE.
|
||||
# USEWSYNC - If defined, the code waits for horizontal retrace
|
||||
# before switching the ROM and updating CHBAS and
|
||||
# CHBASE. This define only has effect if CHARGEN_RELOC
|
||||
# is also defined.
|
||||
|
||||
# Disabled by default, you should enable it if the linker script relocates the
|
||||
# character generator (like atarixl-largehimem.cfg).
|
||||
#CA65FLAGS += -D CHARGEN_RELOC -D USEWSYNC
|
||||
|
||||
13
libsrc/atari/_sys.s
Normal file
13
libsrc/atari/_sys.s
Normal file
@@ -0,0 +1,13 @@
|
||||
;
|
||||
; Christian Groessler, 17-Sep-2013
|
||||
;
|
||||
; Override _sys() function for Atari targets:
|
||||
; 'atari' gets the regular function
|
||||
; 'atarixl' doesn't support the _sys() function
|
||||
;
|
||||
|
||||
.ifndef __ATARIXL__
|
||||
|
||||
.include "../common/_sys.s"
|
||||
|
||||
.endif
|
||||
@@ -7,22 +7,28 @@
|
||||
|
||||
.include "atari.inc"
|
||||
.export _cgetc,setcursor
|
||||
.import KEYBDV_handler
|
||||
.import cursor,mul40
|
||||
|
||||
_cgetc:
|
||||
jsr setcursor
|
||||
lda #12
|
||||
sta ICAX1Z ; fix problems with direct call to KEYBDV
|
||||
.ifndef __ATARIXL__
|
||||
jsr @1
|
||||
.else
|
||||
jsr KEYBDV_handler
|
||||
.endif
|
||||
ldx #0
|
||||
rts
|
||||
|
||||
.ifndef __ATARIXL__
|
||||
@1: lda KEYBDV+5
|
||||
pha
|
||||
lda KEYBDV+4
|
||||
pha
|
||||
lda #12
|
||||
sta ICAX1Z ; fix problems with direct call to KEYBDV
|
||||
rts
|
||||
|
||||
.endif
|
||||
|
||||
.proc setcursor
|
||||
|
||||
|
||||
@@ -8,28 +8,26 @@
|
||||
; Stefan Haubenthal
|
||||
;
|
||||
|
||||
.export _exit
|
||||
.export __STARTUP__ : absolute = 1 ; Mark as startup
|
||||
.export _exit, start
|
||||
|
||||
.import initlib, donelib
|
||||
.import callmain, zerobss
|
||||
.import __STARTUP_LOAD__, __BSS_LOAD__
|
||||
.import __RESERVED_MEMORY__
|
||||
.import __RAM_START__, __RAM_SIZE__
|
||||
.ifdef __ATARIXL__
|
||||
.import __STACKSIZE__
|
||||
.import sram_init
|
||||
.import scrdev
|
||||
.import findfreeiocb
|
||||
.forceimport sramprep ; force inclusion of the "shadow RAM preparation" load chunk
|
||||
.include "save_area.inc"
|
||||
.endif
|
||||
|
||||
.include "zeropage.inc"
|
||||
.include "atari.inc"
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; EXE header
|
||||
|
||||
.segment "EXEHDR"
|
||||
|
||||
.word $FFFF
|
||||
.word __STARTUP_LOAD__
|
||||
.word __BSS_LOAD__ - 1
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Actual code
|
||||
|
||||
.segment "STARTUP"
|
||||
|
||||
@@ -40,6 +38,12 @@
|
||||
|
||||
; Real entry point:
|
||||
|
||||
start:
|
||||
|
||||
.ifdef __ATARIXL__
|
||||
jsr sram_init
|
||||
.endif
|
||||
|
||||
; Clear the BSS data
|
||||
|
||||
jsr zerobss
|
||||
@@ -47,14 +51,16 @@
|
||||
; Setup the stack
|
||||
|
||||
tsx
|
||||
stx spsave
|
||||
stx SP_save
|
||||
|
||||
.ifndef __ATARIXL__
|
||||
|
||||
; Report memory usage
|
||||
|
||||
lda APPMHI
|
||||
sta appmsav ; remember old APPMHI value
|
||||
sta APPMHI_save ; remember old APPMHI value
|
||||
lda APPMHI+1
|
||||
sta appmsav+1
|
||||
sta APPMHI_save+1
|
||||
|
||||
sec
|
||||
lda MEMTOP
|
||||
@@ -66,6 +72,15 @@
|
||||
sta APPMHI+1
|
||||
sta sp+1 ; setup runtime stack part 2
|
||||
|
||||
.else
|
||||
|
||||
lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
|
||||
sta sp
|
||||
lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
|
||||
sta sp+1
|
||||
|
||||
.endif
|
||||
|
||||
; Call module constructors
|
||||
|
||||
jsr initlib
|
||||
@@ -73,14 +88,14 @@
|
||||
; Set left margin to 0
|
||||
|
||||
lda LMARGN
|
||||
sta old_lmargin
|
||||
sta LMARGN_save
|
||||
ldy #0
|
||||
sty LMARGN
|
||||
|
||||
; Set keyb to upper/lowercase mode
|
||||
|
||||
ldx SHFLOK
|
||||
stx old_shflok
|
||||
stx SHFLOK_save
|
||||
sty SHFLOK
|
||||
|
||||
; Initialize conio stuff
|
||||
@@ -98,26 +113,71 @@ _exit: jsr donelib ; Run module destructors
|
||||
|
||||
; Restore system stuff
|
||||
|
||||
ldx spsave
|
||||
ldx SP_save
|
||||
txs ; Restore stack pointer
|
||||
|
||||
; Restore left margin
|
||||
|
||||
lda old_lmargin
|
||||
lda LMARGN_save
|
||||
sta LMARGN
|
||||
|
||||
; Restore kb mode
|
||||
|
||||
lda old_shflok
|
||||
lda SHFLOK_save
|
||||
sta SHFLOK
|
||||
|
||||
; Restore APPMHI
|
||||
|
||||
lda appmsav
|
||||
lda APPMHI_save
|
||||
sta APPMHI
|
||||
lda appmsav+1
|
||||
lda APPMHI_save+1
|
||||
sta APPMHI+1
|
||||
|
||||
.ifdef __ATARIXL__
|
||||
|
||||
; Atari XL target stuff...
|
||||
|
||||
lda PORTB_save
|
||||
sta PORTB
|
||||
lda RAMTOP_save
|
||||
sta RAMTOP
|
||||
lda MEMTOP_save
|
||||
sta MEMTOP
|
||||
lda MEMTOP_save+1
|
||||
sta MEMTOP+1
|
||||
|
||||
|
||||
; Issue a GRAPHICS 0 call (copied'n'pasted from TGI drivers) in
|
||||
; order to restore screen memory to its defailt location just
|
||||
; before the ROM.
|
||||
|
||||
jsr findfreeiocb
|
||||
|
||||
; Reopen it in Graphics 0
|
||||
lda #OPEN
|
||||
sta ICCOM,x
|
||||
lda #OPNIN | OPNOT
|
||||
sta ICAX1,x
|
||||
lda #0
|
||||
sta ICAX2,x
|
||||
lda #<scrdev
|
||||
sta ICBAL,x
|
||||
lda #>scrdev
|
||||
sta ICBAH,x
|
||||
lda #3
|
||||
sta ICBLL,x
|
||||
lda #0
|
||||
sta ICBLH,x
|
||||
jsr CIOV_org
|
||||
; No error checking here, shouldn't happen(tm), and no way to
|
||||
; recover anyway.
|
||||
|
||||
lda #CLOSE
|
||||
sta ICCOM,x
|
||||
jsr CIOV_org
|
||||
|
||||
.endif
|
||||
|
||||
; Turn on cursor
|
||||
|
||||
ldx #0
|
||||
@@ -133,13 +193,9 @@ _exit: jsr donelib ; Run module destructors
|
||||
|
||||
.bss
|
||||
|
||||
spsave: .res 1
|
||||
appmsav: .res 1
|
||||
old_shflok: .res 1
|
||||
old_lmargin: .res 1
|
||||
|
||||
|
||||
.segment "AUTOSTRT"
|
||||
.word RUNAD ; defined in atari.inc
|
||||
.word RUNAD+1
|
||||
.word __STARTUP_LOAD__ + 1
|
||||
SP_save: .res 1
|
||||
SHFLOK_save: .res 1
|
||||
LMARGN_save: .res 1
|
||||
.ifndef __ATARIXL__
|
||||
APPMHI_save: .res 2
|
||||
.endif
|
||||
|
||||
11
libsrc/atari/exehdr.s
Normal file
11
libsrc/atari/exehdr.s
Normal file
@@ -0,0 +1,11 @@
|
||||
; This file defines the EXE header and main chunk load header for Atari executables
|
||||
|
||||
.export __EXEHDR__: absolute = 1
|
||||
.import __RAM_START__, __BSS_LOAD__
|
||||
|
||||
.segment "EXEHDR"
|
||||
.word $FFFF
|
||||
|
||||
.segment "MAINHDR"
|
||||
.word __RAM_START__
|
||||
.word __BSS_LOAD__ - 1
|
||||
12
libsrc/atari/exetrailer.s
Normal file
12
libsrc/atari/exetrailer.s
Normal file
@@ -0,0 +1,12 @@
|
||||
; This file defines the EXE file "trailer" which sets the entry point
|
||||
|
||||
.export __AUTOSTART__: absolute = 1
|
||||
.import start
|
||||
|
||||
.include "atari.inc"
|
||||
|
||||
.segment "AUTOSTRT"
|
||||
.word RUNAD ; defined in atari.inc
|
||||
.word RUNAD+1
|
||||
.word start
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
.import clriocb
|
||||
.import fdtoiocb
|
||||
.import newfd
|
||||
.import scrdev
|
||||
.importzp tmp1,tmp2,tmp3
|
||||
|
||||
.include "atari.inc"
|
||||
@@ -105,8 +106,3 @@ cioerr: sty tmp3 ; remember error code
|
||||
jmp __mappederrno
|
||||
|
||||
.endproc ; __graphics
|
||||
|
||||
|
||||
.rodata
|
||||
|
||||
scrdev: .byte "S:", 0
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
.import callirq
|
||||
|
||||
.include "atari.inc"
|
||||
.ifdef __ATARIXL__
|
||||
.import __CHARGEN_START__
|
||||
.include "romswitch.inc"
|
||||
.endif
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
@@ -39,7 +43,29 @@ doneirq:
|
||||
|
||||
IRQStub:
|
||||
cld ; Just to be sure
|
||||
.ifdef __ATARIXL__
|
||||
pha
|
||||
.ifdef CHARGEN_RELOC
|
||||
lda CHBAS
|
||||
pha
|
||||
.endif
|
||||
lda PORTB
|
||||
pha
|
||||
and #$FE
|
||||
sta PORTB ; disable ROM
|
||||
set_chbase >__CHARGEN_START__
|
||||
.endif
|
||||
jsr callirq ; Call the functions
|
||||
.ifdef __ATARIXL__
|
||||
pla
|
||||
sta PORTB ; restore old ROM setting
|
||||
.ifdef CHARGEN_RELOC
|
||||
pla
|
||||
sta CHBAS
|
||||
sta CHBASE
|
||||
.endif
|
||||
pla
|
||||
.endif
|
||||
jmp IRQInd ; Jump to the saved IRQ vector
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
@@ -7,4 +7,9 @@
|
||||
|
||||
em_libref := _exit
|
||||
joy_libref := _exit
|
||||
.ifdef __ATARIXL__
|
||||
.import CIO_handler
|
||||
tgi_libref := CIO_handler
|
||||
.else
|
||||
tgi_libref := _exit
|
||||
.endif
|
||||
|
||||
@@ -40,8 +40,40 @@
|
||||
|
||||
.export _get_ostype
|
||||
|
||||
.proc _get_ostype
|
||||
.include "atari.inc"
|
||||
.include "romswitch.inc"
|
||||
|
||||
.ifdef __ATARIXL__
|
||||
|
||||
.import __CHARGEN_START__
|
||||
.segment "LOWCODE"
|
||||
|
||||
.macro disable_rom_save_a
|
||||
pha
|
||||
disable_rom
|
||||
pla
|
||||
.endmacro
|
||||
|
||||
.else ; above atarixl, below atari
|
||||
|
||||
.macro disable_rom_save_a
|
||||
.endmacro
|
||||
|
||||
.endif ; .ifdef __ATARIXL__
|
||||
|
||||
|
||||
; unknown ROM
|
||||
|
||||
_unknown:
|
||||
lda #0
|
||||
tax
|
||||
disable_rom_save_a
|
||||
rts
|
||||
|
||||
|
||||
_get_ostype:
|
||||
|
||||
enable_rom
|
||||
lda $fcd8
|
||||
cmp #$a2
|
||||
beq _400800
|
||||
@@ -63,13 +95,7 @@
|
||||
and #%00111000
|
||||
ora #%11
|
||||
_fin: ldx #0
|
||||
rts
|
||||
|
||||
; unknown ROM
|
||||
|
||||
_unknown:
|
||||
lda #0
|
||||
tax
|
||||
disable_rom_save_a
|
||||
rts
|
||||
|
||||
; 1200XL ROM
|
||||
@@ -148,5 +174,3 @@ _400800_3:
|
||||
|
||||
lda #%00010001
|
||||
bne _fin
|
||||
|
||||
.endproc
|
||||
|
||||
101
libsrc/atari/romswitch.inc
Normal file
101
libsrc/atari/romswitch.inc
Normal file
@@ -0,0 +1,101 @@
|
||||
;
|
||||
; Macros to disable and enable the ROM on Atari XL systems.
|
||||
;
|
||||
; Christian Groessler, chris@groessler.org, 19-Sep-2013
|
||||
;
|
||||
;
|
||||
; Defines which modify the operation of the macros:
|
||||
;
|
||||
; CHARGEN_RELOC: If defined, CHBAS and CHBASE are updated when
|
||||
; enabling or disabling the ROM.
|
||||
; If the ROM is enabled, $E0 is written to CHBAS
|
||||
; and CHBASE.
|
||||
; If the ROM is disabled, the upper byte of
|
||||
; __CHARGEN_START__ is written to CHBAS and CHBASE.
|
||||
; USEWSYNC: If defined, the code waits for horizontal retrace
|
||||
; before switching the ROM and updating CHBAS and
|
||||
; CHBASE. This define only has effect if CHARGEN_RELOC
|
||||
; is also defined.
|
||||
|
||||
|
||||
.ifdef __ATARIXL__
|
||||
|
||||
.ifdef CHARGEN_RELOC
|
||||
|
||||
.macro set_chbase val
|
||||
lda #val
|
||||
sta CHBAS
|
||||
sta CHBASE
|
||||
.endmacro
|
||||
|
||||
.else ; above CHARGEN_RELOC, below not
|
||||
|
||||
.macro set_chbase val
|
||||
.endmacro
|
||||
|
||||
.endif ; .ifdef CHARGEN_RELOC
|
||||
|
||||
|
||||
.if .defined(USEWSYNC) .and .defined(CHARGEN_RELOC)
|
||||
|
||||
.macro wsync
|
||||
sta WSYNC
|
||||
.endmacro
|
||||
|
||||
.else ; above USEWSYNC, below not
|
||||
|
||||
.macro wsync
|
||||
.endmacro
|
||||
|
||||
.endif
|
||||
|
||||
|
||||
; "disable ROM" macros
|
||||
|
||||
.macro disable_rom
|
||||
lda PORTB
|
||||
and #$fe
|
||||
wsync
|
||||
sta PORTB
|
||||
set_chbase >__CHARGEN_START__
|
||||
.endmacro
|
||||
|
||||
.macro disable_rom_quick
|
||||
lda PORTB
|
||||
and #$fe
|
||||
sta PORTB
|
||||
set_chbase >__CHARGEN_START__
|
||||
.endmacro
|
||||
|
||||
.macro disable_rom_val val
|
||||
lda val
|
||||
wsync
|
||||
sta PORTB
|
||||
set_chbase >__CHARGEN_START__
|
||||
.endmacro
|
||||
|
||||
; "enable ROM" macros
|
||||
|
||||
.macro enable_rom
|
||||
lda PORTB
|
||||
ora #1
|
||||
wsync
|
||||
sta PORTB
|
||||
set_chbase $E0
|
||||
.endmacro
|
||||
|
||||
.macro enable_rom_quick
|
||||
lda PORTB
|
||||
ora #1
|
||||
sta PORTB
|
||||
set_chbase $E0
|
||||
.endmacro
|
||||
|
||||
.else ; above __ATARIXL__, below not
|
||||
|
||||
.macro disable_rom
|
||||
.endmacro
|
||||
.macro enable_rom
|
||||
.endmacro
|
||||
|
||||
.endif
|
||||
13
libsrc/atari/save_area.inc
Normal file
13
libsrc/atari/save_area.inc
Normal file
@@ -0,0 +1,13 @@
|
||||
;
|
||||
; Atari XL, shared data between 2nd load chunk and main chunk, header file
|
||||
;
|
||||
; Contains old values of modified system variables and ports.
|
||||
;
|
||||
; Christian Groessler, chris@groessler.org, 2013
|
||||
;
|
||||
|
||||
.import SAVMSC_save
|
||||
.import MEMTOP_save
|
||||
.import APPMHI_save
|
||||
.import RAMTOP_save
|
||||
.import PORTB_save
|
||||
25
libsrc/atari/save_area.s
Normal file
25
libsrc/atari/save_area.s
Normal file
@@ -0,0 +1,25 @@
|
||||
;
|
||||
; Atari XL, shared data between 2nd load chunk and main chunk, definition file
|
||||
;
|
||||
; Contains old values of modified system variables and ports.
|
||||
;
|
||||
; Christian Groessler, chris@groessler.org, 2013
|
||||
;
|
||||
|
||||
.ifdef __ATARIXL__
|
||||
|
||||
.export SAVMSC_save
|
||||
.export MEMTOP_save
|
||||
.export APPMHI_save
|
||||
.export RAMTOP_save
|
||||
.export PORTB_save
|
||||
|
||||
.segment "LOWBSS"
|
||||
|
||||
SAVMSC_save: .res 2
|
||||
MEMTOP_save: .res 2
|
||||
APPMHI_save: .res 2
|
||||
RAMTOP_save: .res 1
|
||||
PORTB_save: .res 1
|
||||
|
||||
.endif
|
||||
7
libsrc/atari/scrdev.s
Normal file
7
libsrc/atari/scrdev.s
Normal file
@@ -0,0 +1,7 @@
|
||||
; Name of the "screen" device
|
||||
|
||||
.export scrdev
|
||||
|
||||
.rodata
|
||||
|
||||
scrdev: .byte "S:", 0
|
||||
1101
libsrc/atari/shadow_ram_handlers.s
Normal file
1101
libsrc/atari/shadow_ram_handlers.s
Normal file
File diff suppressed because it is too large
Load Diff
408
libsrc/atari/shadow_ram_prepare.s
Normal file
408
libsrc/atari/shadow_ram_prepare.s
Normal file
@@ -0,0 +1,408 @@
|
||||
;
|
||||
; Atari XL shadow RAM preparation routines
|
||||
;
|
||||
; Tasks:
|
||||
; - move screen memory below load address
|
||||
; - copy ROM chargen to its new place
|
||||
; - copy shadow RAM contents to their destination
|
||||
;
|
||||
; Christian Groessler, chris@groessler.org, 2013
|
||||
;
|
||||
|
||||
;DEBUG = 1
|
||||
|
||||
.ifdef __ATARIXL__
|
||||
|
||||
.export sramprep
|
||||
|
||||
.import __SRPREP_LOAD__, __SRPREPCHNK_LAST__
|
||||
.import __SHADOW_RAM_LOAD__, __SHADOW_RAM_SIZE__, __SHADOW_RAM_RUN__
|
||||
.import __SHADOW_RAM2_LOAD__, __SHADOW_RAM2_SIZE__, __SHADOW_RAM2_RUN__
|
||||
.import __CHARGEN_START__, __CHARGEN_SIZE__
|
||||
.import __STARTADDRESS__ ; needed by xlmemchk.inc
|
||||
|
||||
.include "zeropage.inc"
|
||||
.include "atari.inc"
|
||||
.include "save_area.inc"
|
||||
|
||||
.macro print_string text
|
||||
.local start, cont
|
||||
jmp cont
|
||||
start: .byte text, ATEOL
|
||||
cont: ldx #0 ; channel 0
|
||||
lda #<start
|
||||
sta ICBAL,x ; address
|
||||
lda #>start
|
||||
sta ICBAH,x
|
||||
lda #<(cont - start)
|
||||
sta ICBLL,x ; length
|
||||
lda #>(cont - start)
|
||||
sta ICBLH,x
|
||||
lda #PUTCHR
|
||||
sta ICCOM,x
|
||||
jsr CIOV_org
|
||||
.endmacro
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; EXE load chunk header
|
||||
|
||||
.segment "SRPREPHDR"
|
||||
|
||||
.word __SRPREP_LOAD__
|
||||
.word __SRPREPCHNK_LAST__ - 1
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Actual code
|
||||
|
||||
.segment "SRPREP"
|
||||
|
||||
; ***** entry point *****
|
||||
|
||||
sramprep:
|
||||
.ifdef DEBUG
|
||||
print_string "entering stage #2"
|
||||
.endif
|
||||
|
||||
; save values of modified system variables and ports
|
||||
|
||||
lda RAMTOP
|
||||
sta RAMTOP_save
|
||||
lda MEMTOP
|
||||
sta MEMTOP_save
|
||||
lda MEMTOP+1
|
||||
sta MEMTOP_save+1
|
||||
lda APPMHI
|
||||
sta APPMHI_save
|
||||
lda APPMHI+1
|
||||
sta APPMHI_save+1
|
||||
lda PORTB
|
||||
sta PORTB_save
|
||||
|
||||
; disable BASIC
|
||||
|
||||
lda PORTB
|
||||
ora #2
|
||||
sta PORTB
|
||||
|
||||
.include "xlmemchk.inc" ; calculate lowest address used and new value for RAMTOP
|
||||
|
||||
ldx lowadr
|
||||
stx MEMTOP
|
||||
lda lowadr+1
|
||||
sta MEMTOP+1
|
||||
lda lodadr+1
|
||||
sta RAMTOP
|
||||
|
||||
; set APPMHI to MEMLO (+ 1 for sanity)
|
||||
lda MEMLO
|
||||
clc
|
||||
adc #1
|
||||
sta APPMHI
|
||||
lda MEMLO+1
|
||||
adc #0
|
||||
sta APPMHI+1
|
||||
|
||||
|
||||
; issue a GRAPHICS 0 call (copied'n'pasted from TGI drivers) to move screen memory down
|
||||
|
||||
|
||||
jsr findfreeiocb
|
||||
.ifdef DEBUG ; only check in debug version, this shouldn't really happen(tm)
|
||||
beq iocbok
|
||||
print_string "Internal error, no free IOCB!"
|
||||
jsr delay
|
||||
jsr delay
|
||||
jsr delay
|
||||
jsr restore ; restore stuff we've changed
|
||||
jmp (DOSVEC) ; abort loading
|
||||
iocbok:
|
||||
.endif
|
||||
|
||||
; reopen it in Graphics 0
|
||||
lda #OPEN
|
||||
sta ICCOM,x
|
||||
lda #OPNIN | OPNOT
|
||||
sta ICAX1,x
|
||||
lda #0
|
||||
sta ICAX2,x
|
||||
lda #<screen_device
|
||||
sta ICBAL,x
|
||||
lda #>screen_device
|
||||
sta ICBAH,x
|
||||
lda #<screen_device_length
|
||||
sta ICBLL,x
|
||||
lda #>screen_device_length
|
||||
sta ICBLH,x
|
||||
jsr CIOV_org
|
||||
bpl scrok
|
||||
|
||||
; shouldn't happen(tm)
|
||||
print_string "Internal error, aborting..."
|
||||
jsr delay
|
||||
jsr delay
|
||||
jsr delay
|
||||
jsr restore ; restore stuff we've changed
|
||||
jmp (DOSVEC) ; abort loading
|
||||
|
||||
|
||||
scrok: ; now close it again -- we don't need it anymore
|
||||
lda #CLOSE
|
||||
sta ICCOM,x
|
||||
jsr CIOV_org
|
||||
|
||||
|
||||
; copy chargen to low memory, just after the next possible address beyond our loaded chunk data
|
||||
|
||||
.ifdef DEBUG
|
||||
print_string "copy chargen to low memory"
|
||||
.endif
|
||||
|
||||
lda #>__SRPREPCHNK_LAST__
|
||||
sta ptr3+1
|
||||
lda #<__SRPREPCHNK_LAST__
|
||||
sta ptr3
|
||||
beq cg_addr_ok
|
||||
|
||||
; page align the new chargen address
|
||||
inc ptr3+1
|
||||
lda #0
|
||||
sta ptr3
|
||||
|
||||
cg_addr_ok:
|
||||
|
||||
lda ptr3+1
|
||||
and #3
|
||||
beq cg_addr_ok2
|
||||
|
||||
; align to next 1K boundary
|
||||
lda ptr3+1
|
||||
and #$fc
|
||||
clc
|
||||
adc #4
|
||||
sta ptr3+1
|
||||
|
||||
cg_addr_ok2:
|
||||
|
||||
lda #<DCSORG
|
||||
sta ptr1
|
||||
lda #>DCSORG
|
||||
sta ptr1+1
|
||||
lda ptr3
|
||||
sta ptr2
|
||||
lda ptr3+1
|
||||
pha ; needed later to set CHBAS/CHBASE
|
||||
sta ptr2+1
|
||||
lda #>__CHARGEN_SIZE__
|
||||
sta tmp2
|
||||
lda #<__CHARGEN_SIZE__
|
||||
sta tmp1
|
||||
jsr memcopy
|
||||
|
||||
.ifdef DEBUG
|
||||
print_string "now setting up high memory"
|
||||
.endif
|
||||
|
||||
; disable ROM
|
||||
sei
|
||||
ldx #0
|
||||
stx NMIEN ; disable NMI
|
||||
lda PORTB
|
||||
and #$fe
|
||||
tax
|
||||
pla ; get temp. chargen address
|
||||
sta WSYNC ; wait for horiz. retrace
|
||||
stx PORTB ; now ROM is mapped out
|
||||
|
||||
; switch to temporary chargen
|
||||
|
||||
sta CHBASE
|
||||
sta CHBAS
|
||||
|
||||
; copy shadow RAM contents to their destination (segment SHADOW_RAM)
|
||||
|
||||
lda #<__SHADOW_RAM_SIZE__
|
||||
bne do_copy
|
||||
lda #>__SHADOW_RAM_SIZE__
|
||||
beq no_copy ; we have no shadow RAM contents
|
||||
|
||||
; ptr1 - src; ptr2 - dest; tmp1, tmp2 - len
|
||||
do_copy:lda #<__SHADOW_RAM_LOAD__
|
||||
sta ptr1
|
||||
lda #>__SHADOW_RAM_LOAD__
|
||||
sta ptr1+1
|
||||
lda #<__SHADOW_RAM_RUN__
|
||||
sta ptr2
|
||||
lda #>__SHADOW_RAM_RUN__
|
||||
sta ptr2+1
|
||||
lda #<__SHADOW_RAM_SIZE__
|
||||
sta tmp1
|
||||
lda #>__SHADOW_RAM_SIZE__
|
||||
sta tmp2
|
||||
|
||||
jsr memcopy
|
||||
|
||||
no_copy:
|
||||
|
||||
; copy shadow RAM #2 contents to their destination (segment SHADOW_RAM2)
|
||||
|
||||
lda #<__SHADOW_RAM2_SIZE__
|
||||
bne do_copy2
|
||||
lda #>__SHADOW_RAM2_SIZE__
|
||||
beq no_copy2 ; we have no shadow RAM #2 contents
|
||||
|
||||
; ptr1 - src; ptr2 - dest; tmp1, tmp2 - len
|
||||
do_copy2:
|
||||
lda #<__SHADOW_RAM2_LOAD__
|
||||
sta ptr1
|
||||
lda #>__SHADOW_RAM2_LOAD__
|
||||
sta ptr1+1
|
||||
lda #<__SHADOW_RAM2_RUN__
|
||||
sta ptr2
|
||||
lda #>__SHADOW_RAM2_RUN__
|
||||
sta ptr2+1
|
||||
lda #<__SHADOW_RAM2_SIZE__
|
||||
sta tmp1
|
||||
lda #>__SHADOW_RAM2_SIZE__
|
||||
sta tmp2
|
||||
|
||||
jsr memcopy
|
||||
|
||||
no_copy2:
|
||||
|
||||
; copy chargen to its new (final) location
|
||||
|
||||
lda ptr3
|
||||
sta ptr1
|
||||
lda ptr3+1
|
||||
sta ptr1+1
|
||||
lda #<__CHARGEN_START__
|
||||
sta ptr2
|
||||
lda #>__CHARGEN_START__
|
||||
sta ptr2+1
|
||||
lda #>__CHARGEN_SIZE__
|
||||
sta tmp2
|
||||
lda #<__CHARGEN_SIZE__
|
||||
sta tmp1
|
||||
jsr memcopy
|
||||
|
||||
; re-enable ROM
|
||||
|
||||
lda PORTB
|
||||
ora #1
|
||||
ldx #>DCSORG
|
||||
sta WSYNC ; wait for horiz. retrace
|
||||
sta PORTB
|
||||
stx CHBASE
|
||||
stx CHBAS
|
||||
lda #$40
|
||||
sta NMIEN ; enable VB again
|
||||
cli ; and enable IRQs
|
||||
|
||||
.ifdef DEBUG
|
||||
print_string "Stage #2 OK"
|
||||
print_string "loading main chunk"
|
||||
jsr delay
|
||||
.endif
|
||||
rts
|
||||
|
||||
.include "findfreeiocb.inc"
|
||||
|
||||
; routine taken from http://www.obelisk.demon.co.uk/6502/algorithms.html
|
||||
;
|
||||
; copy memory
|
||||
; ptr1 - source
|
||||
; ptr2 - destination
|
||||
; tmp2:tmp1 - len
|
||||
|
||||
.proc memcopy
|
||||
|
||||
ldy #0
|
||||
ldx tmp2
|
||||
beq last
|
||||
pagecp: lda (ptr1),y
|
||||
sta (ptr2),y
|
||||
iny
|
||||
bne pagecp
|
||||
inc ptr1+1
|
||||
inc ptr2+1
|
||||
dex
|
||||
bne pagecp
|
||||
last: cpy tmp1
|
||||
beq done
|
||||
lda (ptr1),y
|
||||
sta (ptr2),y
|
||||
iny
|
||||
bne last
|
||||
done: rts
|
||||
|
||||
.endproc
|
||||
|
||||
|
||||
; clean up after a fatal error
|
||||
|
||||
restore:lda RAMTOP_save
|
||||
sta RAMTOP
|
||||
lda MEMTOP_save
|
||||
sta MEMTOP
|
||||
lda MEMTOP_save+1
|
||||
sta MEMTOP+1
|
||||
lda APPMHI_save
|
||||
sta APPMHI
|
||||
lda APPMHI_save+1
|
||||
sta APPMHI+1
|
||||
rts
|
||||
|
||||
; short delay
|
||||
.proc delay
|
||||
|
||||
lda #10
|
||||
@loop: jsr delay1
|
||||
clc
|
||||
sbc #0
|
||||
bne @loop
|
||||
rts
|
||||
|
||||
delay1: ldx #0
|
||||
ldy #0
|
||||
@loop: dey
|
||||
bne @loop
|
||||
dex
|
||||
bne @loop
|
||||
rts
|
||||
|
||||
.endproc
|
||||
|
||||
.ifdef DEBUG
|
||||
|
||||
.byte "HERE ****************** HERE ***************>>>>>>"
|
||||
|
||||
sramsize:
|
||||
.word __SHADOW_RAM_SIZE__
|
||||
|
||||
.endif ; .ifdef DEBUG
|
||||
|
||||
screen_device: .byte "S:",0
|
||||
screen_device_length = * - screen_device
|
||||
|
||||
.ifdef DEBUG
|
||||
.byte " ** srprep ** end-->"
|
||||
.endif
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Provide empty SHADOW_RAM and SHADOW_RAM2 segments in order that the
|
||||
; linker is happy if the user program doesn't have these segments.
|
||||
|
||||
.segment "SHADOW_RAM"
|
||||
.segment "SHADOW_RAM2"
|
||||
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; EXE load chunk "trailer" - sets INITAD
|
||||
|
||||
.segment "SRPREPTRL"
|
||||
|
||||
.word INITAD
|
||||
.word INITAD+1
|
||||
.word sramprep
|
||||
|
||||
.endif ; .ifdef __ATARIXL__
|
||||
@@ -8,7 +8,6 @@
|
||||
;
|
||||
|
||||
.include "atari.inc"
|
||||
.include "errno.inc"
|
||||
.export __sysrmdir
|
||||
.import __sysremove
|
||||
.import __dos_type
|
||||
@@ -17,7 +16,6 @@
|
||||
.ifdef UCASE_FILENAME
|
||||
.import ucase_fn
|
||||
.import addysp
|
||||
.importzp sreg
|
||||
.importzp tmp3
|
||||
.ifdef DEFAULT_DEVICE
|
||||
.importzp tmp2
|
||||
|
||||
215
libsrc/atari/system_check.s
Normal file
215
libsrc/atari/system_check.s
Normal file
@@ -0,0 +1,215 @@
|
||||
;
|
||||
; Atari startup system check
|
||||
;
|
||||
; This routine gets loaded prior to the main part of the executable
|
||||
; and checks if the system is compatible to run the program.
|
||||
; For the XL target it checks whether the system is an XL type one
|
||||
; and that enough memory is installed (which isn't the case for a 600XL).
|
||||
; For the non-XL target it checks whether there is enough memory
|
||||
; installed to run the program.
|
||||
; For both targets it checks that the program won't load below MEMLO.
|
||||
; If one of the checks fails, the loading of the main program
|
||||
; is aborted by jumping to DOSVEC.
|
||||
;
|
||||
; Christian Groessler, chris@groessler.org, 2013
|
||||
;
|
||||
|
||||
;DEBUG = 1
|
||||
|
||||
.export __SYSTEM_CHECK__: absolute = 1
|
||||
.import __SYSCHK_LOAD__
|
||||
.import __STARTADDRESS__
|
||||
|
||||
; the following imports are only needed for the 'atari' target version
|
||||
.import __BSS_SIZE__, __BSS_RUN__
|
||||
.import __STACKSIZE__
|
||||
.import __RESERVED_MEMORY__
|
||||
|
||||
.include "zeropage.inc"
|
||||
.include "atari.inc"
|
||||
|
||||
|
||||
.macro print_string text
|
||||
.local start, cont
|
||||
jmp cont
|
||||
start: .byte text, ATEOL
|
||||
cont: ldx #0 ; channel 0
|
||||
lda #<start
|
||||
sta ICBAL,x ; address
|
||||
lda #>start
|
||||
sta ICBAH,x
|
||||
lda #<(cont - start)
|
||||
sta ICBLL,x ; length
|
||||
lda #>(cont - start)
|
||||
sta ICBLH,x
|
||||
lda #PUTCHR
|
||||
sta ICCOM,x
|
||||
jsr CIOV_org
|
||||
.endmacro
|
||||
|
||||
.macro print_string2 addr, len
|
||||
ldx #0 ; channel 0
|
||||
lda #<addr
|
||||
sta ICBAL,x ; address
|
||||
lda #>addr
|
||||
sta ICBAH,x
|
||||
lda #<len
|
||||
sta ICBLL,x ; length
|
||||
lda #>len
|
||||
sta ICBLH,x
|
||||
lda #PUTCHR
|
||||
sta ICCOM,x
|
||||
jsr CIOV_org
|
||||
.endmacro
|
||||
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; code
|
||||
|
||||
.segment "SYSCHK"
|
||||
|
||||
.ifdef __ATARIXL__
|
||||
|
||||
lmemerrxl_txt:
|
||||
.byte "Not enough memory to move screen", ATEOL
|
||||
.byte "memory to low memory. Consider using", ATEOL
|
||||
.byte "a higher load address.", ATEOL
|
||||
lmemerrxl_txt_len = * - lmemerrxl_txt
|
||||
|
||||
; no XL machine
|
||||
no_xl: print_string "This program needs an XL machine."
|
||||
jmp fail
|
||||
|
||||
|
||||
; ***** entry point (atarixl) *****
|
||||
|
||||
syschk: lda $fcd8 ; from ostype.s
|
||||
cmp #$a2
|
||||
beq no_xl
|
||||
|
||||
; we have an XL machine, now check memory
|
||||
lda RAMSIZ
|
||||
cmp #$80
|
||||
bcs sys_ok
|
||||
|
||||
jmp mem_err
|
||||
|
||||
sys_ok:
|
||||
.include "xlmemchk.inc" ; calculate lowest address we will use when we move the screen buffer down
|
||||
|
||||
lda MEMLO
|
||||
cmp lowadr
|
||||
lda MEMLO+1
|
||||
sbc lowadr+1
|
||||
bcc memlo_ok
|
||||
|
||||
; load address was too low
|
||||
print_string2 lmemerrxl_txt, lmemerrxl_txt_len
|
||||
jsr delay ; long text takes longer to read, give user additional time
|
||||
jmp fail
|
||||
|
||||
.else ; above 'atarixl', below 'atari'
|
||||
|
||||
.define CIOV_org CIOV ; the print_string macros use CIOV_org, map this to CIOV
|
||||
|
||||
lmemerr_txt:
|
||||
.byte "Program would load below MEMLO.", ATEOL
|
||||
.byte "Consider using a higher load address.", ATEOL
|
||||
lmemerr_txt_len = * - lmemerr_txt
|
||||
|
||||
|
||||
; ***** entry point (atari) *****
|
||||
|
||||
syschk:
|
||||
sec
|
||||
lda MEMTOP
|
||||
sbc #<__RESERVED_MEMORY__
|
||||
sta tmp
|
||||
lda MEMTOP+1
|
||||
sbc #>__RESERVED_MEMORY__
|
||||
sta tmp+1
|
||||
lda tmp
|
||||
sec
|
||||
sbc #<__STACKSIZE__
|
||||
sta tmp
|
||||
lda tmp+1
|
||||
sbc #>__STACKSIZE__
|
||||
sta tmp+1
|
||||
|
||||
;tmp contains address which must be above .bss's end
|
||||
|
||||
lda tmp
|
||||
cmp #<(__BSS_RUN__ + __BSS_SIZE__)
|
||||
lda tmp+1
|
||||
sbc #>(__BSS_RUN__ + __BSS_SIZE__)
|
||||
|
||||
bcc mem_err ; program doesn't fit into memory
|
||||
|
||||
lda MEMLO
|
||||
cmp #<__STARTADDRESS__
|
||||
lda MEMLO+1
|
||||
sbc #>__STARTADDRESS__
|
||||
bcc memlo_ok
|
||||
|
||||
; load address was too low
|
||||
print_string2 lmemerr_txt, lmemerr_txt_len
|
||||
jsr delay ; long text takes longer to read, give user additional time
|
||||
jmp fail
|
||||
|
||||
.endif
|
||||
|
||||
; all is well(tm), launch the application
|
||||
memlo_ok:
|
||||
.ifdef DEBUG
|
||||
print_string "Stage #1 OK"
|
||||
jsr delay
|
||||
.endif
|
||||
rts
|
||||
|
||||
; not enough memory
|
||||
mem_err:print_string "Not enough memory."
|
||||
fail: jsr delay
|
||||
jmp (DOSVEC)
|
||||
|
||||
; short delay
|
||||
.proc delay
|
||||
|
||||
lda #10
|
||||
@loop: jsr delay1
|
||||
clc
|
||||
sbc #0
|
||||
bne @loop
|
||||
rts
|
||||
|
||||
delay1: ldx #0
|
||||
ldy #0
|
||||
@loop: dey
|
||||
bne @loop
|
||||
dex
|
||||
bne @loop
|
||||
rts
|
||||
|
||||
.endproc
|
||||
|
||||
end:
|
||||
|
||||
.ifndef __ATARIXL__
|
||||
tmp: ; outside of the load chunk, some kind of poor man's .bss
|
||||
.endif
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Chunk header
|
||||
|
||||
.segment "SYSCHKHDR"
|
||||
|
||||
.word __SYSCHK_LOAD__
|
||||
.word end - 1
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Chunk "trailer" - sets INITAD
|
||||
|
||||
.segment "SYSCHKTRL"
|
||||
|
||||
.word INITAD
|
||||
.word INITAD+1
|
||||
.word syschk
|
||||
@@ -4,6 +4,12 @@
|
||||
|
||||
.macpack longbranch
|
||||
|
||||
.ifdef __ATARIXL__
|
||||
CIO_vec := my_CIOV
|
||||
.else
|
||||
CIO_vec := CIOV
|
||||
.endif
|
||||
|
||||
; ******************************************************************************
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
@@ -18,7 +24,7 @@
|
||||
|
||||
.byte $74, $67, $69 ; "tgi"
|
||||
.byte TGI_API_VERSION ; TGI API version number
|
||||
.addr $0000 ; Library reference
|
||||
libref: .addr $0000 ; Library reference
|
||||
.word x_res ; X resolution
|
||||
.word y_res ; Y resolution
|
||||
.byte colors ; Number of drawing colors
|
||||
@@ -111,6 +117,10 @@
|
||||
text_dir:
|
||||
.byte 0 ; Text direction,
|
||||
|
||||
.ifdef __ATARIXL__
|
||||
my_CIOV:
|
||||
.byte $4C, 0, 0
|
||||
.endif
|
||||
.code
|
||||
|
||||
; ******************************************************************************
|
||||
@@ -161,6 +171,17 @@ screen_device_length := * - screen_device
|
||||
|
||||
stx mask
|
||||
|
||||
.ifdef __ATARIXL__
|
||||
|
||||
; setup pointer to CIO
|
||||
|
||||
lda libref
|
||||
sta my_CIOV+1
|
||||
lda libref+1
|
||||
sta my_CIOV+2
|
||||
.endif
|
||||
|
||||
|
||||
; Find a free IOCB
|
||||
lda #$70
|
||||
search: tax
|
||||
@@ -202,7 +223,7 @@ switch: lda #OPEN
|
||||
sta ICBLL,x
|
||||
lda #>screen_device_length
|
||||
sta ICBLH,x
|
||||
jsr CIOV
|
||||
jsr CIO_vec
|
||||
|
||||
.if ::pages = 2
|
||||
; Reserve 8K of high memory
|
||||
@@ -212,7 +233,7 @@ switch: lda #OPEN
|
||||
; Close and reopen graphics
|
||||
lda #CLOSE
|
||||
sta ICCOM,x
|
||||
jsr CIOV
|
||||
jsr CIO_vec
|
||||
; Reopen graphics
|
||||
lda #OPEN
|
||||
sta ICCOM,x
|
||||
@@ -228,7 +249,7 @@ switch: lda #OPEN
|
||||
sta ICBLL,x
|
||||
lda #>screen_device_length
|
||||
sta ICBLH,x
|
||||
jsr CIOV
|
||||
jsr CIO_vec
|
||||
; Save screen pointers
|
||||
lda SAVMSC + 1
|
||||
sta p0scr
|
||||
@@ -271,7 +292,7 @@ exit: sta error
|
||||
; Close the S: device
|
||||
lda #CLOSE
|
||||
sta ICCOM,x
|
||||
jsr CIOV
|
||||
jsr CIO_vec
|
||||
|
||||
; Reopen it in Graphics 0
|
||||
lda #OPEN
|
||||
@@ -288,12 +309,12 @@ exit: sta error
|
||||
sta ICBLL,x
|
||||
lda #>screen_device_length
|
||||
sta ICBLH,x
|
||||
jsr CIOV
|
||||
jsr CIO_vec
|
||||
|
||||
; Now close it again; we don't need it anymore :)
|
||||
lda #CLOSE
|
||||
sta ICCOM,x
|
||||
jmp CIOV
|
||||
jmp CIO_vec
|
||||
.endproc
|
||||
|
||||
; ******************************************************************************
|
||||
@@ -640,7 +661,7 @@ done10:
|
||||
.endif
|
||||
|
||||
sta ATACHR
|
||||
jmp CIOV
|
||||
jmp CIO_vec
|
||||
|
||||
.else ; USE_CIO_LINE
|
||||
|
||||
|
||||
119
libsrc/atari/xlmemchk.inc
Normal file
119
libsrc/atari/xlmemchk.inc
Normal file
@@ -0,0 +1,119 @@
|
||||
;
|
||||
; Christian Groessler, Jun-2013
|
||||
;
|
||||
; This routine is used in preparation to move the screen memory
|
||||
; in front of the program.
|
||||
;
|
||||
; It calculates the value to put into RAMTOP for a subsequent
|
||||
; "GRAPHICS 0" call, and the lowest address which will be used
|
||||
; by the screen memory afterwards.
|
||||
;
|
||||
; inputs:
|
||||
; __STARTADDRESS__ - load address of the program
|
||||
; outputs:
|
||||
; lodadr - (high byte only) value to
|
||||
; write into RAMTOP
|
||||
; lowadr - lowest address occupied by
|
||||
; screen data
|
||||
;
|
||||
|
||||
|
||||
; When setting a display mode, the ROM takes the RAMTOP value
|
||||
; and subtracts the size of the screen memory from it. This will
|
||||
; become the new screen memory address.
|
||||
; From this address it subtracts the size of the display list.
|
||||
; This will become the new display list address.
|
||||
; Screen memory cannot cross 4K boundaries and a display list
|
||||
; cannot cross a 1K boundary.
|
||||
;
|
||||
; Work out a sane value for RAMTOP to prevent boundary crossing.
|
||||
; RAMTOP is only one byte, it counts in memory pages.
|
||||
;
|
||||
; The ROM doesn't do this boundary checking, since it doesn't
|
||||
; expect RAMTOP to have (rather) arbitrary values. For a
|
||||
; "GRAPHICS 0" call and RAMTOP representing the possible physically
|
||||
; available memory, boundary crossing cannot happen.
|
||||
|
||||
|
||||
SCRBUFSZ = (40 * 24) ; size of mode 0 screen buffer
|
||||
DLSZ = 32 ; size of mode 0 display list
|
||||
|
||||
|
||||
scrmemtst:
|
||||
|
||||
; subtract screen memory size from our load address
|
||||
|
||||
lda lodadr
|
||||
sec
|
||||
sbc #<SCRBUFSZ
|
||||
sta tstadr
|
||||
lda lodadr+1
|
||||
sbc #>SCRBUFSZ
|
||||
sta tstadr+1
|
||||
|
||||
; check if a 4K boundary is crossed
|
||||
|
||||
lda lodadr+1
|
||||
and #$f0
|
||||
sta tmp
|
||||
lda tstadr+1
|
||||
and #$f0
|
||||
cmp tmp
|
||||
beq scrmemok
|
||||
|
||||
; if lodadr is at an exact 4K boundary, it's still ok
|
||||
|
||||
lda lodadr+1
|
||||
and #$0f
|
||||
beq scrmemok
|
||||
|
||||
; 4K boundary will be crossed, use this 4K boundary address as lodadr
|
||||
|
||||
al4k: lda lodadr+1
|
||||
and #$f0
|
||||
sta lodadr+1
|
||||
bne scrmemtst
|
||||
; not reached
|
||||
|
||||
.ifdef DEBUG
|
||||
.byte "XLMEMCHK:>"
|
||||
.endif
|
||||
lodadr: .word __STARTADDRESS__ & $FF00 ; our program's load address, rounded down to page boundary
|
||||
tstadr: .res 2
|
||||
lowadr: .res 2
|
||||
tmp: .res 1
|
||||
|
||||
|
||||
; subtract display list size from calculated screen address
|
||||
|
||||
scrmemok:
|
||||
lda tstadr
|
||||
sec
|
||||
sbc #<DLSZ
|
||||
sta lowadr
|
||||
lda tstadr+1
|
||||
sbc #>DLSZ
|
||||
sta lowadr+1
|
||||
|
||||
.if 0 ; this cannot happen
|
||||
; check if a 1K boundary is crossed
|
||||
|
||||
lda tstadr+1
|
||||
and #$fc
|
||||
sta tmp
|
||||
lda lowadr+1
|
||||
and #$fc
|
||||
cmp tmp
|
||||
bne al4k ; 1K boundary will be crossed, decrease lodadr
|
||||
.endif
|
||||
|
||||
; address of display list is ok
|
||||
; decrease lowadr by two
|
||||
|
||||
lda lowadr
|
||||
sec
|
||||
sbc #2
|
||||
sta lowadr
|
||||
bcs dec_cont
|
||||
dec lowadr+1
|
||||
dec_cont:
|
||||
15
libsrc/atmos/atmos.s
Normal file
15
libsrc/atmos/atmos.s
Normal file
@@ -0,0 +1,15 @@
|
||||
;
|
||||
; Expose include-file symbol names to C code.
|
||||
;
|
||||
|
||||
.export _atmos_ping, _atmos_shoot, _atmos_explode
|
||||
.export _atmos_zap, _atmos_tick, _atmos_tock
|
||||
|
||||
.include "atmos.inc"
|
||||
|
||||
_atmos_ping := PING
|
||||
_atmos_shoot := SHOOT
|
||||
_atmos_explode := EXPLODE
|
||||
_atmos_zap := ZAP
|
||||
_atmos_tick := TICK
|
||||
_atmos_tock := TOCK
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
.export em_libref
|
||||
.export joy_libref
|
||||
; .export mouse_libref
|
||||
.export ser_libref
|
||||
.export tgi_libref
|
||||
|
||||
@@ -13,6 +12,5 @@
|
||||
|
||||
em_libref := _exit
|
||||
joy_libref := _exit
|
||||
;mouse_libref := _exit
|
||||
ser_libref := _exit
|
||||
tgi_libref := _exit
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
.export em_libref
|
||||
.export joy_libref
|
||||
; .export mouse_libref
|
||||
.export ser_libref
|
||||
.export tgi_libref
|
||||
|
||||
@@ -13,6 +12,5 @@
|
||||
|
||||
em_libref := _exit
|
||||
joy_libref := _exit
|
||||
;mouse_libref := _exit
|
||||
ser_libref := _exit
|
||||
tgi_libref := _exit
|
||||
|
||||
118
libsrc/cbm/exec.c
Normal file
118
libsrc/cbm/exec.c
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
** Program-chaining function for Commodore platforms.
|
||||
**
|
||||
** 2013-09-04, Greg King
|
||||
**
|
||||
** This function exploits the program-chaining feature in CBM BASIC's ROM.
|
||||
**
|
||||
** CC65's CBM programs have a BASIC program stub. We start those programs by
|
||||
** RUNning that stub; it SYSes to the Machine Language code. Normally, after
|
||||
** the ML code exits, the BASIC ROM continues running the stub. But, it has
|
||||
** no more statements; so, the program stops.
|
||||
**
|
||||
** This function puts the desired program's name and device number into a LOAD
|
||||
** statement. Then, it points BASIC to that statement, so that the ROM will run
|
||||
** that statement after this program quits. The ROM will load the next program,
|
||||
** and will execute it (because the LOAD will be seen in a running program).
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <device.h>
|
||||
#if defined(__CBM610__)
|
||||
# include <cbm610.h>
|
||||
#elif defined(__CBM510__)
|
||||
# include <cbm510.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* The struct below is a line of BASIC code. It sits in the LOWCODE segment
|
||||
** to make sure that it won't be hidden by a ROM when BASIC is re-enabled.
|
||||
** The line is:
|
||||
** 0 LOAD""+"" ,01
|
||||
** After this function has written into the line, it might look like this:
|
||||
** 0 LOAD""+"program name" ,08
|
||||
**
|
||||
** When BASIC's LOAD command asks the Kernal to load a file, it gives the
|
||||
** Kernal a pointer to a file-name string. CC65's CBM programs use that
|
||||
** pointer to give a copy of the program's name to main()'s argv[0] parameter.
|
||||
** But, when BASIC uses a string literal that's in a program, it points
|
||||
** directly to that literal -- in the models that don't use banked RAM
|
||||
** (Pet/CBM, VIC-20, and 64). The literal is overwritten by the next program
|
||||
** that's loaded. So, argv[0] would point to machine code. String operations
|
||||
** create a new result string -- even when that operation changes nothing. The
|
||||
** result is put in the string space at the top of BASIC's memory. So, the ""+
|
||||
** in this BASIC line guarantees that argv[0] will get a name from a safe place.
|
||||
*/
|
||||
#pragma data-name(push, "LOWCODE")
|
||||
static struct line {
|
||||
const char end_of_line;
|
||||
const struct line *const next;
|
||||
const unsigned line_num;
|
||||
const char load_token, quotes[2], add_token, quote;
|
||||
char name[21];
|
||||
const char comma;
|
||||
char unit[3];
|
||||
} basic = {
|
||||
'\0', &basic + 1, /* high byte of link must be non-zero */
|
||||
0, 0x93, "\"\"", 0xaa, '\"',
|
||||
"\" ", /* format: "123:1234567890123456\"" */
|
||||
',', "01"
|
||||
};
|
||||
#pragma data-name(pop)
|
||||
|
||||
/* These values are platform-specific. */
|
||||
extern const struct line *txtptr;
|
||||
#pragma zpsym("txtptr")
|
||||
extern char basbuf[]; /* BASIC's input buffer */
|
||||
extern void basbuf_len[];
|
||||
#pragma zpsym("basbuf_len")
|
||||
|
||||
|
||||
int __fastcall__ exec (const char* progname, const char* cmdline)
|
||||
{
|
||||
static int fd;
|
||||
static unsigned char dv, n = 0;
|
||||
|
||||
/* Exclude devices that can't load files. */
|
||||
dv = getcurrentdevice ();
|
||||
if (dv < 8 && dv != 1 || dv > 30) {
|
||||
return _mappederrno (9); /* illegal device number */
|
||||
}
|
||||
utoa (dv, basic.unit, 10);
|
||||
|
||||
/* Don't try to run a program that can't be found. */
|
||||
fd = open (progname, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
return fd;
|
||||
}
|
||||
close (fd);
|
||||
|
||||
do {
|
||||
if ((basic.name[n] = progname[n]) == '\0') {
|
||||
break;
|
||||
}
|
||||
} while (++n < 20); /* truncate long names */
|
||||
basic.name[n] = '\"';
|
||||
|
||||
/* Build the next program's argument list. */
|
||||
basbuf[0] = 0x8f; /* REM token */
|
||||
basbuf[1] = '\0';
|
||||
if (cmdline != NULL) {
|
||||
strncat (basbuf, cmdline, (size_t)basbuf_len - 2);
|
||||
}
|
||||
|
||||
#if defined(__CBM510__) || defined(__CBM610__)
|
||||
pokewsys ((unsigned)&txtptr, (unsigned)&basic);
|
||||
#else
|
||||
txtptr = &basic;
|
||||
#endif
|
||||
|
||||
/* (The return code, in ST, will be destroyed by LOAD.
|
||||
** So, don't bother to set it here.)
|
||||
*/
|
||||
exit (__AX__);
|
||||
}
|
||||
28
libsrc/cbm/execvars.s
Normal file
28
libsrc/cbm/execvars.s
Normal file
@@ -0,0 +1,28 @@
|
||||
;
|
||||
; Platform-specific variables for the exec program-chaining function
|
||||
;
|
||||
|
||||
.if .defined (__C128__)
|
||||
.include "c128.inc"
|
||||
.elseif .defined (__C16__)
|
||||
.include "c16.inc"
|
||||
.elseif .defined (__C64__)
|
||||
.include "c64.inc"
|
||||
.elseif .defined (__CBM510__)
|
||||
.include "cbm510.inc"
|
||||
.elseif .defined (__CBM610__)
|
||||
.include "cbm610.inc"
|
||||
.elseif .defined (__PET__)
|
||||
.include "pet.inc"
|
||||
.elseif .defined (__PLUS4__)
|
||||
.include "plus4.inc"
|
||||
.else
|
||||
.include "vic20.inc"
|
||||
.endif
|
||||
|
||||
.export _txtptr:zp, _basbuf, _basbuf_len:zp
|
||||
|
||||
_txtptr := TXTPTR
|
||||
|
||||
_basbuf := BASIC_BUF
|
||||
_basbuf_len = BASIC_BUF_LEN
|
||||
@@ -56,9 +56,9 @@
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; A table that contains values that must be transfered from the system zero
|
||||
; page into out zero page. Contains pairs of bytes, first one is the address
|
||||
; page into our zero page. Contains pairs of bytes; first one is the address
|
||||
; in the system ZP, second one is our ZP address. The table goes into page 2,
|
||||
; but is declared here, because it is needed earlier.
|
||||
; but is declared here because it is needed earlier.
|
||||
|
||||
.SEGMENT "PAGE2"
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
.byte $9F, DEVNUM
|
||||
.byte $CA, CURS_Y
|
||||
.byte $CB, CURS_X
|
||||
.byte $E6, CURS_FLAG
|
||||
.byte $E7, CURS_BLINK
|
||||
.byte $EC, CHARCOLOR
|
||||
|
||||
.endproc
|
||||
|
||||
131
libsrc/cbm510/mcbdefault.s
Normal file
131
libsrc/cbm510/mcbdefault.s
Normal file
@@ -0,0 +1,131 @@
|
||||
;
|
||||
; Default mouse callbacks for the CBM510 (P128)
|
||||
;
|
||||
; 2004-03-20, Ullrich von Bassewitz2
|
||||
; 2013-06-25, Greg King
|
||||
;
|
||||
; All functions in this module should be interrupt-safe because they might
|
||||
; be called from an interrupt handler.
|
||||
;
|
||||
|
||||
.export _mouse_def_callbacks
|
||||
.import vic:zp
|
||||
|
||||
.include "mouse-kernel.inc"
|
||||
.include "cbm510.inc"
|
||||
|
||||
.macpack generic
|
||||
|
||||
; Sprite definitions. The first value can be changed to adjust the number
|
||||
; of the sprite used for the mouse. All others depend on that value.
|
||||
MOUSE_SPR = 0 ; Sprite used for the mouse
|
||||
MOUSE_SPR_MASK = $01 .shl MOUSE_SPR ; Positive mask
|
||||
MOUSE_SPR_NMASK = .lobyte(.not MOUSE_SPR_MASK) ; Negative mask
|
||||
VIC_SPR_X = (VIC_SPR0_X + 2*MOUSE_SPR) ; Sprite X register
|
||||
VIC_SPR_Y = (VIC_SPR0_Y + 2*MOUSE_SPR) ; Sprite Y register
|
||||
|
||||
; --------------------------------------------------------------------------
|
||||
; Hide the mouse pointer. Always called with interrupts disabled.
|
||||
|
||||
.proc hide
|
||||
|
||||
ldy #15
|
||||
sty IndReg
|
||||
|
||||
ldy #VIC_SPR_ENA
|
||||
lda (vic),y
|
||||
and #MOUSE_SPR_NMASK
|
||||
sta (vic),y
|
||||
|
||||
ldy ExecReg
|
||||
sty IndReg
|
||||
rts
|
||||
|
||||
.endproc
|
||||
|
||||
; --------------------------------------------------------------------------
|
||||
; Show the mouse pointer. Always called with interrupts disabled.
|
||||
|
||||
.proc show
|
||||
|
||||
ldy #15
|
||||
sty IndReg
|
||||
|
||||
ldy #VIC_SPR_ENA
|
||||
lda (vic),y
|
||||
ora #MOUSE_SPR_MASK
|
||||
sta (vic),y
|
||||
|
||||
ldy ExecReg
|
||||
sty IndReg
|
||||
rts
|
||||
|
||||
.endproc
|
||||
|
||||
; --------------------------------------------------------------------------
|
||||
; Move the mouse pointer x position to the value in .XA. Always called with
|
||||
; interrupts disabled.
|
||||
|
||||
.proc movex
|
||||
|
||||
ldy #15
|
||||
sty IndReg
|
||||
|
||||
; Add the x correction; and, set the low byte. That frees .A.
|
||||
|
||||
add #<24 ; x correction
|
||||
ldy #VIC_SPR_X
|
||||
sta (vic),y
|
||||
|
||||
; Set the high byte
|
||||
|
||||
ldy #VIC_SPR_HI_X
|
||||
txa
|
||||
adc #>24
|
||||
bnz @L1 ; Branch if high byte not zero
|
||||
lda (vic),y ; Get high x bits of all sprites
|
||||
and #MOUSE_SPR_NMASK ; Clear high bit for sprite
|
||||
sta (vic),y
|
||||
|
||||
@L0: ldy ExecReg
|
||||
sty IndReg
|
||||
rts
|
||||
|
||||
@L1: lda (vic),y ; Get high x bits of all sprites
|
||||
ora #MOUSE_SPR_MASK ; Set high bit for sprite
|
||||
sta (vic),y
|
||||
bnz @L0 ; branch always
|
||||
|
||||
.endproc
|
||||
|
||||
; --------------------------------------------------------------------------
|
||||
; Move the mouse pointer y position to the value in .XA. Always called with
|
||||
; interrupts disabled.
|
||||
|
||||
.proc movey
|
||||
|
||||
ldy #15
|
||||
sty IndReg
|
||||
|
||||
add #50 ; y correction (first visible line)
|
||||
ldy #VIC_SPR_Y
|
||||
sta (vic),y ; Set y position
|
||||
|
||||
ldy ExecReg
|
||||
sty IndReg
|
||||
rts
|
||||
|
||||
.endproc
|
||||
|
||||
; --------------------------------------------------------------------------
|
||||
; Callback structure
|
||||
|
||||
.rodata
|
||||
|
||||
_mouse_def_callbacks:
|
||||
.addr hide
|
||||
.addr show
|
||||
.addr movex
|
||||
.addr movey
|
||||
|
||||
|
||||
444
libsrc/cbm510/mou/cbm510-inkwl.s
Normal file
444
libsrc/cbm510/mou/cbm510-inkwl.s
Normal file
@@ -0,0 +1,444 @@
|
||||
;
|
||||
; Driver for the Inkwell Systems 170-C and 184-C lightpens.
|
||||
;
|
||||
; This driver reads only the main button on the 184-C.
|
||||
;
|
||||
; 2013-09-05, Greg King
|
||||
;
|
||||
|
||||
.include "zeropage.inc"
|
||||
.include "../extzp.inc"
|
||||
|
||||
.include "mouse-kernel.inc"
|
||||
.include "cbm510.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
|
||||
.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
|
||||
|
||||
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 #15 ; Change to system bank
|
||||
stx IndReg
|
||||
ldy #VIC_LPEN_X
|
||||
lda (vic),y
|
||||
sta OldPenX
|
||||
ldy #VIC_LPEN_Y
|
||||
lda (vic),y
|
||||
sta OldPenY
|
||||
ldx ExecReg ; Change back to execution bank
|
||||
stx IndReg
|
||||
|
||||
; 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 ; Function will set this variable
|
||||
ldx #>XOffset
|
||||
jsr Calibrate
|
||||
|
||||
; Be sure that the lightpen cursor is invisible and at the default location.
|
||||
; It needs to be done here because the lightpen interrupt handler doesn't
|
||||
; set the lightpen position if it hasn't changed.
|
||||
|
||||
@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:
|
||||
ldx #15 ; To system bank
|
||||
stx IndReg
|
||||
ldy #CIA::PRB
|
||||
lda (cia2),y ; Read joystick inputs
|
||||
ldx ExecReg ; Back to execution bank
|
||||
stx IndReg
|
||||
|
||||
; Joystick 1, directions in bits 3-0.
|
||||
; Make the lightpen button look like a 1351 mouse.
|
||||
|
||||
asl a ; Move joystick-left bit ...
|
||||
asl a ; ... to fire-button bit
|
||||
eor #MOUSE_BTN_LEFT
|
||||
and #MOUSE_BTN_LEFT
|
||||
ldx #>0
|
||||
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 ; We don't support ioctls, for now
|
||||
ldx #>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: ldx #15 ; To system bank
|
||||
stx IndReg
|
||||
|
||||
; Read the VIC-II lightpen registers.
|
||||
|
||||
ldy #VIC_LPEN_Y
|
||||
lda (vic),y
|
||||
cmp OldPenY
|
||||
|
||||
; Skip processing if nothing has changed.
|
||||
|
||||
beq @SkipY
|
||||
sta OldPenY
|
||||
ldx ExecReg ; Back to execution bank
|
||||
stx IndReg
|
||||
|
||||
; 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
|
||||
|
||||
ldx #15 ; To system bank
|
||||
stx IndReg
|
||||
@SkipY: ldy #VIC_LPEN_X
|
||||
lda (vic),y
|
||||
ldx ExecReg ; Back to execution bank
|
||||
stx IndReg
|
||||
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
|
||||
445
libsrc/cbm510/mou/cbm510-joy.s
Normal file
445
libsrc/cbm510/mou/cbm510-joy.s
Normal file
@@ -0,0 +1,445 @@
|
||||
;
|
||||
; Driver for a "joystick mouse".
|
||||
;
|
||||
; 2009-09-26, Ullrich von Bassewitz
|
||||
; 2013-09-05, Greg King
|
||||
;
|
||||
|
||||
.include "zeropage.inc"
|
||||
.include "../extzp.inc"
|
||||
|
||||
.include "mouse-kernel.inc"
|
||||
.include "cbm510.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
|
||||
|
||||
.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_LATE_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_HEIGHT = YSIZE * 8
|
||||
SCREEN_WIDTH = XSIZE * 8
|
||||
|
||||
.scope JOY
|
||||
UP = %00000001
|
||||
DOWN = %00000010
|
||||
LEFT = %00000100
|
||||
RIGHT = %00001000
|
||||
FIRE = %00010000
|
||||
.endscope
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; 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.
|
||||
|
||||
.bss
|
||||
|
||||
Vars:
|
||||
YPos: .res 2 ; Current mouse position, y
|
||||
XPos: .res 2 ; Current mouse position, x
|
||||
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
|
||||
|
||||
; Temporary value used in the interrupt handler
|
||||
|
||||
Temp: .res 1
|
||||
|
||||
; Default values for above variables
|
||||
|
||||
.rodata
|
||||
|
||||
.proc DefVars
|
||||
.word SCREEN_HEIGHT / 2 ; YPos
|
||||
.word SCREEN_WIDTH / 2 ; XPos
|
||||
.word 0 ; XMin
|
||||
.word 0 ; YMin
|
||||
.word SCREEN_WIDTH - 1 ; XMax
|
||||
.word SCREEN_HEIGHT - 1 ; YMax
|
||||
.endproc
|
||||
|
||||
.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
|
||||
@L1: lda DefVars,x
|
||||
sta Vars,x
|
||||
dex
|
||||
bpl @L1
|
||||
|
||||
; Be sure the mouse cursor is invisible and at the default location. We
|
||||
; need to do that here because our mouse interrupt handler doesn't set the
|
||||
; mouse position if it hasn't changed.
|
||||
|
||||
sei
|
||||
jsr CHIDE
|
||||
lda XPos
|
||||
ldx XPos+1
|
||||
jsr CMOVEX
|
||||
lda YPos
|
||||
ldx YPos+1
|
||||
jsr CMOVEY
|
||||
cli
|
||||
|
||||
; Done, return zero.
|
||||
|
||||
ldx #>MOUSE_ERR_OK
|
||||
txa
|
||||
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 mouse pointer. The mouse kernel manages
|
||||
; a counter for calls to show/hide; and, the driver entry point is called only
|
||||
; if the mouse currently is visible and should get hidden. For most drivers,
|
||||
; no special action is required besides hiding the mouse cursor.
|
||||
; No return code required.
|
||||
|
||||
HIDE: sei
|
||||
jsr CHIDE
|
||||
cli
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages
|
||||
; a counter for calls to show/hide; and, the driver entry point is called only
|
||||
; if the mouse currently is hidden and should become visible. For most drivers,
|
||||
; no special action is required besides enabling the mouse cursor.
|
||||
; No return code required.
|
||||
|
||||
SHOW: sei
|
||||
jsr CSHOW
|
||||
cli
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; SETBOX: Set the mouse 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 mouse currently is 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 mouse 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 ; Set new y position
|
||||
|
||||
ldy #1
|
||||
lda (sp),y
|
||||
sta XPos+1
|
||||
tax
|
||||
dey
|
||||
lda (sp),y
|
||||
jsr MoveX ; Move the pointer
|
||||
|
||||
cli ; Allow interrupts
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; BUTTONS: Return the button mask in .XA.
|
||||
; Joystick 2's fire button is the left mouse button.
|
||||
; Joystick 1's fire button is the right mouse button.
|
||||
|
||||
BUTTONS:
|
||||
ldx #15 ; Switch to the system bank
|
||||
stx IndReg
|
||||
|
||||
; Get the fire-button bits
|
||||
|
||||
ldy #CIA::PRA
|
||||
lda (cia2),y
|
||||
|
||||
; Switch back to the execution bank.
|
||||
|
||||
ldy ExecReg
|
||||
sty IndReg
|
||||
|
||||
; Joystick 2, fire button is in bit 7.
|
||||
; Joystick 1, fire button is in bit 6.
|
||||
|
||||
and #%11000000
|
||||
asl a ; Move bits 7,6 to bits 1,0
|
||||
rol a
|
||||
rol a
|
||||
adc #%00001110 ; Move bit 1 to bit 4
|
||||
and #MOUSE_BTN_LEFT | MOUSE_BTN_RIGHT
|
||||
|
||||
; Bits go up when buttons go down.
|
||||
|
||||
eor #MOUSE_BTN_LEFT | MOUSE_BTN_RIGHT
|
||||
ldx #>0
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; INFO: Returns mouse 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 just will
|
||||
; use _mouse_pos to fill the position fields.
|
||||
|
||||
INFO: jsr BUTTONS
|
||||
|
||||
; Fill in the button state.
|
||||
|
||||
ldy #MOUSE_INFO::BUTTONS
|
||||
sta (ptr1),y
|
||||
|
||||
; jmp POS ; Fall through
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; POS: Return the mouse 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 ; Done
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; 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 ; We don't support ioctls, for now
|
||||
ldx #>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.
|
||||
; Reads joystick 2.
|
||||
;
|
||||
|
||||
IRQ: ldy #15 ; Switch to the system bank
|
||||
sty IndReg
|
||||
|
||||
; Get the direction bits.
|
||||
|
||||
ldy #CIA::PRB
|
||||
lda (cia2),y ; Read joystick inputs
|
||||
|
||||
; Switch back to the execution bank.
|
||||
|
||||
ldy ExecReg
|
||||
sty IndReg
|
||||
|
||||
; Joystick 2, directions in bits 7-4.
|
||||
; Mask the relevant bits.
|
||||
|
||||
and #$F0
|
||||
eor #$F0 ; All bits are inverted
|
||||
sta Temp
|
||||
|
||||
; Check left/right.
|
||||
|
||||
and #(JOY::LEFT | JOY::RIGHT) << 4
|
||||
bze @SkipX
|
||||
|
||||
; We will cheat here, and rely on the fact that either the left OR the right
|
||||
; bit can be active.
|
||||
|
||||
and #JOY::RIGHT << 4 ; Check RIGHT bit
|
||||
bnz @Right
|
||||
lda #<-1
|
||||
tax
|
||||
bnz @AddX ; Branch always
|
||||
@Right: lda #<1
|
||||
ldx #>1
|
||||
|
||||
; Calculate the new x co-ordinate (--> .YA).
|
||||
|
||||
@AddX: add XPos
|
||||
tay ; Remember low byte
|
||||
txa
|
||||
adc XPos+1
|
||||
tax
|
||||
|
||||
; 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
|
||||
|
||||
; Calculate the y movement vector.
|
||||
|
||||
@SkipX: lda Temp ; Get joystick again
|
||||
and #(JOY::UP | JOY::DOWN) << 4 ; Check up/down
|
||||
bze @SkipY
|
||||
|
||||
; We will cheat here, and rely on the fact that either the up OR the down
|
||||
; bit can be active.
|
||||
|
||||
and #JOY::UP << 4 ; Check UP bit
|
||||
bze @Down
|
||||
lda #<-1
|
||||
tax
|
||||
bnz @AddY
|
||||
@Down: lda #<1
|
||||
ldx #>1
|
||||
|
||||
; Calculate the new y co-ordinate (--> .YA).
|
||||
|
||||
@AddY: add YPos
|
||||
tay ; Remember low byte
|
||||
txa
|
||||
adc YPos+1
|
||||
tax
|
||||
|
||||
; Limit the y co-ordinate to the bounding box.
|
||||
|
||||
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
|
||||
|
||||
; Done
|
||||
|
||||
@SkipY: clc ; Interrupt not handled
|
||||
rts
|
||||
|
||||
; Move the mouse pointer to the new x pos.
|
||||
|
||||
MoveX: sta XPos
|
||||
stx XPos+1
|
||||
jmp CMOVEX
|
||||
|
||||
; Move the mouse pointer to the new y pos.
|
||||
|
||||
MoveY: sta YPos
|
||||
stx YPos+1
|
||||
jmp CMOVEY
|
||||
13
libsrc/cbm510/mouse_stat_stddrv.s
Normal file
13
libsrc/cbm510/mouse_stat_stddrv.s
Normal file
@@ -0,0 +1,13 @@
|
||||
;
|
||||
; Address of the static standard mouse driver
|
||||
;
|
||||
; 2012-11-01, Oliver Schmidt
|
||||
; 2013-08-06, Greg King
|
||||
;
|
||||
; const void mouse_static_stddrv[];
|
||||
;
|
||||
|
||||
.export _mouse_static_stddrv
|
||||
.import _cbm510_joy_mou
|
||||
|
||||
_mouse_static_stddrv := _cbm510_joy_mou
|
||||
16
libsrc/cbm510/mouse_stddrv.s
Normal file
16
libsrc/cbm510/mouse_stddrv.s
Normal file
@@ -0,0 +1,16 @@
|
||||
;
|
||||
; Name of the standard mouse driver
|
||||
;
|
||||
; 2009-09-11, Ullrich von Bassewitz
|
||||
; 2013-06-25, Greg King
|
||||
;
|
||||
; const char mouse_stddrv[];
|
||||
;
|
||||
|
||||
.export _mouse_stddrv
|
||||
|
||||
.rodata
|
||||
|
||||
_mouse_stddrv: .asciiz "cbm510-joy.mou"
|
||||
|
||||
|
||||
23
libsrc/cbm510/mouseref.s
Normal file
23
libsrc/cbm510/mouseref.s
Normal file
@@ -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
|
||||
94
libsrc/cbm510/pencalib.c
Executable file
94
libsrc/cbm510/pencalib.c
Executable file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
** Calibrate lightpen drivers to the current video hardware.
|
||||
**
|
||||
** 2013-09-05, Greg King
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
#include <conio.h>
|
||||
#include <mouse.h>
|
||||
#include <pen.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 = peekbsys ((unsigned)&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);
|
||||
|
||||
pokebsys ((unsigned)&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 ();
|
||||
pokebsys ((unsigned)&VIC.spr_color[0], sprite0Color);
|
||||
revers (oldRev);
|
||||
textcolor (oldText);
|
||||
bgcolor (oldBg);
|
||||
clrscr ();
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 02.06.1998
|
||||
; 1998-06-02, Ullrich von Bassewitz
|
||||
; 2013-08-28, Greg King
|
||||
;
|
||||
; char* strlower (char* s);
|
||||
; char* strlwr (char* s);
|
||||
; char* __fastcall__ strlower (char* s);
|
||||
; char* __fastcall__ strlwr (char* s);
|
||||
;
|
||||
; Non-ANSI
|
||||
;
|
||||
@@ -19,7 +20,7 @@ _strlwr:
|
||||
sta ptr1 ; Save s (working copy)
|
||||
stx ptr1+1
|
||||
sta ptr2
|
||||
sta ptr2+1 ; save function result
|
||||
stx ptr2+1 ; save function result
|
||||
ldy #0
|
||||
|
||||
loop: lda (ptr1),y ; get character
|
||||
|
||||
@@ -102,7 +102,7 @@ long __fastcall__ strtol (const char* nptr, char** endptr, int base)
|
||||
*/
|
||||
if (endptr) {
|
||||
if (CvtCount > 0) {
|
||||
*endptr = (char*) S - 1;
|
||||
*endptr = (char*) S;
|
||||
} else {
|
||||
*endptr = (char*) nptr;
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ unsigned long __fastcall__ strtoul (const char* nptr, char** endptr, int base)
|
||||
*/
|
||||
if (endptr) {
|
||||
if (CvtCount > 0) {
|
||||
*endptr = (char*) S - 1;
|
||||
*endptr = (char*) S;
|
||||
} else {
|
||||
*endptr = (char*) nptr;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 02.06.1998
|
||||
; 1998-06-02, Ullrich von Bassewitz
|
||||
; 2013-08-28, Greg King
|
||||
;
|
||||
; char* strupper (char* s);
|
||||
; char* strupr (char* s);
|
||||
; char* __fastcall__ strupper (char* s);
|
||||
; char* __fastcall__ strupr (char* s);
|
||||
;
|
||||
; Non-ANSI
|
||||
;
|
||||
@@ -19,7 +20,7 @@ _strupr:
|
||||
sta ptr1 ; Save s (working copy)
|
||||
stx ptr1+1
|
||||
sta ptr2
|
||||
sta ptr2+1 ; save function result
|
||||
stx ptr2+1 ; save function result
|
||||
ldy #0
|
||||
|
||||
loop: lda (ptr1),y ; get character
|
||||
|
||||
@@ -27,10 +27,10 @@
|
||||
; Restore timep and check if it is NULL
|
||||
|
||||
pla
|
||||
sta ptr1
|
||||
sta ptr1+1
|
||||
pla
|
||||
sta ptr1+1 ; Restore timep
|
||||
ora ptr1 ; timep == 0?
|
||||
sta ptr1 ; Restore timep
|
||||
ora ptr1+1 ; timep == 0?
|
||||
beq @L1
|
||||
|
||||
; timep is not NULL, store the result there
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
MAXARGS = 10 ; Maximum number of arguments allowed
|
||||
REM = $8f ; BASIC token-code
|
||||
NAME_LEN = 16 ; maximum length of command-name
|
||||
BASIC_BUF= $200
|
||||
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user