This commit is contained in:
Stephan Mühlstrasser
2014-11-02 16:17:16 +01:00
1110 changed files with 69611 additions and 13294 deletions

View File

@@ -1,3 +1,7 @@
ifneq ($(shell echo),)
CMD_EXE = 1
endif
CBMS = c128 \
c16 \
c64 \
@@ -14,6 +18,7 @@ TARGETS = apple2 \
apple2enh \
atari \
atarixl \
atari5200 \
atmos \
c1p \
$(CBMS) \
@@ -30,6 +35,27 @@ DRVTYPES = emd \
ser \
tgi
OUTPUTDIRS := lib \
$(DRVTYPES) \
targetutil \
asminc \
cfg \
include \
$(subst ../,,$(filter-out $(wildcard ../include/*.*),$(wildcard ../include/*)))
.PHONY: all mostlyclean clean install zip lib $(TARGETS)
.SUFFIXES:
ifdef CMD_EXE
DIRLIST = $(strip $(foreach dir,$1,$(wildcard $(dir))))
MKDIR = mkdir $(subst /,\,$1)
RMDIR = $(if $(DIRLIST),rmdir /s /q $(subst /,\,$(DIRLIST)))
else
MKDIR = mkdir -p $1
RMDIR = $(RM) -r $1
endif
# Every target requires its individual vpath setting but the vpath directive
# acts globally. Therefore each target is built in a separate make instance.
@@ -39,37 +65,55 @@ ifeq ($(words $(MAKECMDGOALS)),1)
endif
endif
DIRLIST = $(strip $(foreach dir,$1,$(wildcard $(dir))))
ifeq ($(shell echo),)
MKDIR = mkdir -p $1
RMDIR = $(RM) -r $1
else
MKDIR = mkdir $(subst /,\,$1)
RMDIR = $(if $(DIRLIST),rmdir /s /q $(subst /,\,$(DIRLIST)))
endif
.SUFFIXES:
.PHONY: all lib $(TARGETS) mostlyclean clean
ifndef TARGET
datadir = $(prefix)/share/cc65
all lib: $(TARGETS)
mostlyclean:
$(call RMDIR,../libwrk)
clean:
$(call RMDIR,../libwrk ../lib ../targetutil $(addprefix ../,$(DRVTYPES)))
ifdef CMD_EXE
install:
else # CMD_EXE
INSTALL = install
define INSTALL_recipe
$(if $(prefix),,$(error variable `prefix' must be set))
$(INSTALL) -d $(DESTDIR)$(datadir)/$(dir)
$(INSTALL) -m644 ../$(dir)/*.* $(DESTDIR)$(datadir)/$(dir)
endef # INSTALL_recipe
install:
$(foreach dir,$(OUTPUTDIRS),$(INSTALL_recipe))
endif # CMD_EXE
define ZIP_recipe
@cd .. && zip cc65 $(dir)/*.*
endef # ZIP_recipe
zip:
$(foreach dir,$(OUTPUTDIRS),$(ZIP_recipe))
$(TARGETS):
@$(MAKE) --no-print-directory $@
mostlyclean:
$(call RMDIR,../wrk)
clean:
$(call RMDIR,../wrk ../lib ../targetutil $(addprefix ../,$(DRVTYPES)))
else # TARGET
CA65FLAGS =
CC65FLAGS = -Osir -W error
CC65FLAGS = -Or -W error
EXTZP = cbm510 \
cbm610 \
@@ -77,9 +121,12 @@ EXTZP = cbm510 \
MKINC = $(GEOS) \
atari \
atarixl \
nes
TARGETUTIL = apple2 \
TARGETUTIL = apple2 \
apple2enh \
atari \
geos-apple
GEOSDIRS = common \
@@ -137,7 +184,7 @@ vpath %.c $(SRCDIRS)
OBJS := $(patsubst %.s,%.o,$(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.s)))
OBJS += $(patsubst %.c,%.o,$(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.c)))
OBJS := $(addprefix ../wrk/$(TARGET)/,$(sort $(notdir $(OBJS))))
OBJS := $(addprefix ../libwrk/$(TARGET)/,$(sort $(notdir $(OBJS))))
DEPS = $(OBJS:.o=.d)
@@ -145,106 +192,96 @@ EXTRA_SRCPAT = $(SRCDIR)/extra/%.s
EXTRA_OBJPAT = ../lib/$(TARGET)-%.o
EXTRA_OBJS := $(patsubst $(EXTRA_SRCPAT),$(EXTRA_OBJPAT),$(wildcard $(SRCDIR)/extra/*.s))
ZPOBJ = ../wrk/$(TARGET)/zeropage.o
ZPOBJ = ../libwrk/$(TARGET)/zeropage.o
ifeq ($(TARGET),$(filter $(TARGET),$(EXTZP)))
ZPOBJ += ../wrk/$(TARGET)/extzp.o
ZPOBJ += ../libwrk/$(TARGET)/extzp.o
endif
ifeq ($(SRCDIR),$(filter $(SRCDIR),$(MKINC)))
ifeq ($(TARGET),$(filter $(TARGET),$(MKINC)))
include $(SRCDIR)/Makefile.inc
endif
ifeq ($(SRCDIR),$(filter $(SRCDIR),$(TARGETUTIL)))
ifeq ($(TARGET),$(filter $(TARGET),$(TARGETUTIL)))
include $(SRCDIR)/targetutil/Makefile.inc
endif
##########
define DRVTYPE_template
$1_SRCDIR = $$(SRCDIR)/$1
$1_OBJDIR = ../wrk/$$(TARGET)/$1
$1_STCDIR = ../libwrk/$$(TARGET)
$1_DYNDIR = ../libwrk/$$(TARGET)/$1
$1_DRVDIR = ../$1
$1_OBJPAT = $$($1_OBJDIR)/$$(OBJPFX)%.o
$1_SRCPAT = $$($1_SRCDIR)/$$(OBJPFX)%.s
$1_STCPAT = $$($1_STCDIR)/$$(OBJPFX)%-$1.o
$1_DYNPAT = $$($1_DYNDIR)/$$(OBJPFX)%.o
$1_DRVPAT = $$($1_DRVDIR)/$$(DRVPFX)%.$1
$1_STCPAT = ../wrk/$$(TARGET)/$$(DRVPFX)%-$1.o
$1_OBJS := $$(patsubst $$($1_SRCDIR)/%.s,$$($1_OBJDIR)/%.o,$$(wildcard $$($1_SRCDIR)/*.s))
$1_SRCS := $$(wildcard $$($1_SRCDIR)/*.s)
$1_STCS = $$(patsubst $$($1_SRCPAT),$$($1_STCPAT),$$($1_SRCS))
$1_DYNS = $$(patsubst $$($1_SRCPAT),$$($1_DYNPAT),$$($1_SRCS))
$1_DRVS = $$(patsubst $$($1_DYNPAT),$$($1_DRVPAT),$$($1_DYNS))
$1_DRVS = $$(patsubst $$($1_OBJPAT),$$($1_DRVPAT),$$($1_OBJS))
$$($1_STCPAT): $$($1_SRCPAT)
@echo $$(TARGET) - $$< - static
@$$(CA65) -t $$(TARGET) -D DYN_DRV=0 $$(CA65FLAGS) --create-dep $$(@:.o=.d) -o $$@ $$<
$1_STCS = $$(patsubst $$($1_DRVPAT),$$($1_STCPAT),$$($1_DRVS))
OBJS += $$($1_STCS)
DEPS += $$($1_STCS:.o=.d)
$$($1_OBJS): | $$($1_OBJDIR)
$$($1_DYNS): | $$($1_DYNDIR)
$$($1_DRVPAT): $$($1_OBJPAT) $$(ZPOBJ) | $$($1_DRVDIR)
@echo $$(TARGET) - $$(@F)
$$($1_DRVPAT): $$($1_DYNPAT) $$(ZPOBJ) | $$($1_DRVDIR)
@echo $$(TARGET) - $$(<F)
@$$(LD65) -o $$@ -t module $$^
$$($1_OBJDIR) $$($1_DRVDIR):
$$($1_DYNDIR) $$($1_DRVDIR):
@$$(call MKDIR,$$@)
$(TARGET): $$($1_DRVS)
$$($1_STCPAT): $$($1_DRVPAT)
@echo $$(TARGET) - $$(<F)
@$$(CO65) -o $$(@:.o=.s) --code-label _$$(subst -,_,$$(subst .,_,$$(<F))) $$<
@$$(CA65) -t $$(TARGET) -o $$@ $$(@:.o=.s)
DEPS += $$($1_DYNS:.o=.d)
OBJS += $$($1_STCS)
DEPS += $$($1_OBJS:.o=.d)
endef
##########
endef # DRVTYPE_template
$(foreach drvtype,$(DRVTYPES),$(eval $(call DRVTYPE_template,$(drvtype))))
AR65 := $(if $(wildcard ../bin/ar65*),../bin/ar65,ar65)
CA65 := $(if $(wildcard ../bin/ca65*),../bin/ca65,ca65)
CC65 := $(if $(wildcard ../bin/cc65*),../bin/cc65,cc65)
CO65 := $(if $(wildcard ../bin/co65*),../bin/co65,co65)
LD65 := $(if $(wildcard ../bin/ld65*),../bin/ld65,ld65)
export CC65_HOME := $(abspath ..)
##########
define ASSEMBLE_recipe
$(if $(TRAVIS),,@echo $(TARGET) - $<)
$(if $(QUIET),,@echo $(TARGET) - $<)
@$(CA65) -t $(TARGET) $(CA65FLAGS) --create-dep $(@:.o=.d) -o $@ $<
endef
##########
endef # ASSEMBLE_recipe
define COMPILE_recipe
$(if $(TRAVIS),,@echo $(TARGET) - $<)
$(if $(QUIET),,@echo $(TARGET) - $<)
@$(CC65) -t $(TARGET) $(CC65FLAGS) --create-dep $(@:.o=.d) --dep-target $@ -o $(@:.o=.s) $<
@$(CA65) -t $(TARGET) -o $@ $(@:.o=.s)
endef
endef # COMPILE_recipe
##########
../wrk/$(TARGET)/%.o: %.s | ../wrk/$(TARGET)
../libwrk/$(TARGET)/%.o: %.s | ../libwrk/$(TARGET)
$(ASSEMBLE_recipe)
../wrk/$(TARGET)/%.o: %.c | ../wrk/$(TARGET)
../libwrk/$(TARGET)/%.o: %.c | ../libwrk/$(TARGET)
$(COMPILE_recipe)
$(EXTRA_OBJPAT): $(EXTRA_SRCPAT) | ../lib
@echo $(TARGET) - $(@F)
@echo $(TARGET) - $(<F)
@$(CA65) -t $(TARGET) $(CA65FLAGS) -o $@ $<
../lib/$(TARGET).lib: $(OBJS) | ../lib
$(AR65) a $@ $?
../wrk/$(TARGET) ../lib ../targetutil:
../libwrk/$(TARGET) ../lib ../targetutil:
@$(call MKDIR,$@)
$(TARGET): $(EXTRA_OBJS) ../lib/$(TARGET).lib

View File

@@ -24,76 +24,76 @@
ldx #$FF
txs ; Init stack pointer
; Switch in LC bank 2 for W/O
; Switch in LC bank 2 for W/O.
bit $C081
bit $C081
; Set source start address
; Set the source start address.
lda #<(__ZPSAVE_RUN__ + __INIT_SIZE__)
ldy #>(__ZPSAVE_RUN__ + __INIT_SIZE__)
sta $9B
sty $9C
; Set source last address
; Set the source last address.
lda #<(__ZPSAVE_RUN__ + __INIT_SIZE__ + __LC_LAST__ - __LC_START__)
ldy #>(__ZPSAVE_RUN__ + __INIT_SIZE__ + __LC_LAST__ - __LC_START__)
sta $96
sty $97
; Set destination last address
; Set the destination last address.
lda #<__LC_LAST__
ldy #>__LC_LAST__
sta $94
sty $95
; Call into Applesoft Block Transfer Utility - which handles zero
; sized blocks well - to move content of the LC memory area
; Call into the Applesoft Block Transfer Utility -- which handles zero-
; sized blocks well -- to move the content of the LC memory area.
jsr $D396 ; BLTU + 3
; Set source start address
; Set the source start address.
lda #<__ZPSAVE_RUN__
ldy #>__ZPSAVE_RUN__
sta $9B
sty $9C
; Set source last address
; Set the source last address.
lda #<(__ZPSAVE_RUN__ + __INIT_SIZE__)
ldy #>(__ZPSAVE_RUN__ + __INIT_SIZE__)
sta $96
sty $97
; Set destination last address
; Set the destination last address.
lda #<(__INIT_RUN__ + __INIT_SIZE__)
ldy #>(__INIT_RUN__ + __INIT_SIZE__)
sta $94
sty $95
; Call into Applesoft Block Transfer Utility - which handles moving
; overlapping blocks upwards well - to move the INIT segment
; Call into the Applesoft Block Transfer Utility -- which handles moving
; overlapping blocks upwards well -- to move the INIT segment.
jsr $D396 ; BLTU + 3
; Delegate all further processing to keep the STARTUP segment small
; Delegate all further processing, to keep the STARTUP segment small.
jsr init
; Avoid re-entrance of donelib. This is also the _exit entry
; Avoid a re-entrance of donelib. This is also the exit() entry.
_exit: ldx #<exit
lda #>exit
jsr reset ; Setup RESET vector
; Switch in ROM in case it wasn't already switched in by a RESET
; Switch in ROM, in case it wasn't already switched in by a RESET.
bit $C082
; Call module destructors
; Call the module destructors.
jsr donelib
; Restore the original RESET vector
; Restore the original RESET vector.
exit: ldx #$02
: lda rvsave,x
sta SOFTEV,x
dex
bpl :-
; Copy back the zero page stuff
; Copy back the zero-page stuff.
ldx #zpspace-1
: lda zpsave,x
sta sp,x
@@ -107,21 +107,21 @@ exit: ldx #$02
txs ; Re-init stack pointer
; We're done
jmp (done)
jmp done
.segment "INIT"
; Save the zero page locations we need
; Save the zero-page locations that we need.
init: ldx #zpspace-1
: lda sp,x
sta zpsave,x
dex
bpl :-
; Clear the BSS data
; Clear the BSS data.
jsr zerobss
; Save the original RESET vector
; Save the original RESET vector.
ldx #$02
: lda SOFTEV,x
sta rvsave,x
@@ -135,58 +135,58 @@ init: ldx #zpspace-1
lda #>_exit
jsr reset ; Setup RESET vector
; Check for ProDOS
; Check for ProDOS.
ldy $BF00 ; MLI call entry point
cpy #$4C ; Is MLI present? (JMP opcode)
bne basic
; Check ProDOS system bit map
; Check the ProDOS system bit map.
lda $BF6F ; Protection for pages $B8 - $BF
cmp #%00000001 ; Exactly system global page is protected
bne basic
; No BASIC.SYSTEM so quit to ProDOS dispatcher instead
; No BASIC.SYSTEM; so, quit to the ProDOS dispatcher instead.
lda #<quit
ldx #>quit
sta done
stx done+1
; No BASIC.SYSTEM so use addr of ProDOS system global page
sta done+1
stx done+2
; No BASIC.SYSTEM; so, use the addr of the ProDOS system global page.
lda #<$BF00
ldx #>$BF00
bne :+ ; Branch always
; Get highest available mem addr from BASIC interpreter
; Get the highest available mem addr from the BASIC interpreter.
basic: lda HIMEM
ldx HIMEM+1
; Setup the C stack
; Set up the C stack.
: sta sp
stx sp+1
; Enable interrupts as old ProDOS versions (i.e. 1.1.1)
; jump to SYS and BIN programs with interrupts disabled
; Enable interrupts, as old ProDOS versions (i.e. 1.1.1)
; jump to SYS and BIN programs with interrupts disabled.
cli
; Call module constructors
; Call the module constructors.
jsr initlib
; Switch in LC bank 2 for R/O
; Switch in LC bank 2 for R/O.
bit $C080
; Push arguments and call main()
; Push the command-line arguments; and, call main().
jmp callmain
.code
; Setup RESET vector
; Set up the RESET vector.
reset: stx SOFTEV
sta SOFTEV+1
eor #$A5
sta PWREDUP
return: rts
; Quit to ProDOS dispatcher
; Quit to the ProDOS dispatcher.
quit: jsr $BF00 ; MLI call entry point
.byte $65 ; Quit
.word q_param
@@ -202,8 +202,8 @@ q_param:.byte $04 ; param_count
.data
; Location to jump to when we're done
done: .addr DOSWARM
; Final jump when we're done
done: jmp DOSWARM ; Potentially patched at runtime
.segment "ZPSAVE"

View File

@@ -10,10 +10,16 @@
.include "em-kernel.inc"
.include "em-error.inc"
.macpack module
; ------------------------------------------------------------------------
; Header. Includes jump table
.segment "JUMPTABLE"
.ifdef __APPLE2ENH__
module_header _a2e_auxmem_emd
.else
module_header _a2_auxmem_emd
.endif
; Driver signature

View File

@@ -161,8 +161,8 @@ setbuf: lda #$00 ; Low byte
; Call loader stub after C libary shutdown
lda #<target
ldx #>target
sta done
stx done+1
sta done+1
stx done+2
; Initiate C libary shutdown
jmp _exit

View File

@@ -13,6 +13,8 @@
.include "joy-error.inc"
.include "apple2.inc"
.macpack module
; ------------------------------------------------------------------------
; Constants
@@ -29,7 +31,11 @@ PREAD := $FB1E ; Read paddle in X, return AD conv. value in Y
; Header. Includes jump table.
.segment "JUMPTABLE"
.ifdef __APPLE2ENH__
module_header _a2e_stdjoy_joy
.else
module_header _a2_stdjoy_joy
.endif
; Driver signature

View File

@@ -16,6 +16,7 @@
.bss
backup: .res 1
visible:.res 1
; ------------------------------------------------------------------------
@@ -25,6 +26,8 @@ backup: .res 1
_mouse_def_callbacks:
.addr hide
.addr show
.addr prep
.addr draw
.addr movex
.addr movey
@@ -65,10 +68,15 @@ done:
.ifdef __APPLE2ENH__
bit LOWSCR ; Doesn't hurt in 40 column mode
.endif
rts
return: rts
; Hide the mouse cursor.
hide:
dec visible
; Fall through
; Prepare to move the mouse cursor.
prep:
jsr getcursor ; Cursor visible at current position?
bne done ; No, we're done
lda backup ; Get character at cursor position
@@ -76,6 +84,13 @@ hide:
; Show the mouse cursor.
show:
inc visible
; Fall through
; Draw the mouse cursor.
draw:
lda visible
beq return
jsr getcursor ; Cursor visible at current position?
beq done ; Yes, we're done
sta backup ; Save character at cursor position

View File

@@ -8,6 +8,8 @@
.include "mouse-kernel.inc"
.include "apple2.inc"
.macpack module
; ------------------------------------------------------------------------
SETMOUSE = $12 ; Sets mouse mode
@@ -28,7 +30,11 @@ status := $0778
; ------------------------------------------------------------------------
.segment "JUMPTABLE"
.ifdef __APPLE2ENH__
module_header _a2e_stdmou_mou
.else
module_header _a2_stdmou_mou
.endif
; Driver signature
.byte $6D, $6F, $75 ; "mou"
@@ -57,6 +63,8 @@ status := $0778
; Callback table, set by the kernel before INSTALL is called
CHIDE: jmp $0000 ; Hide the cursor
CSHOW: jmp $0000 ; Show the cursor
CPREP: jmp $0000 ; Prepare to move the cursor
CDRAW: jmp $0000 ; Draw the cursor
CMOVEX: jmp $0000 ; Move the cursor to X coord
CMOVEY: jmp $0000 ; Move the cursor to Y coord
@@ -67,7 +75,6 @@ CMOVEY: jmp $0000 ; Move the cursor to Y coord
box: .tag MOUSE_BOX
info: .tag MOUSE_INFO
slot: .res 1
visible:.res 1
; ------------------------------------------------------------------------
@@ -321,7 +328,6 @@ MOVE:
; no special action is required besides hiding the mouse cursor.
; No return code required.
HIDE:
dec visible
sei
jsr CHIDE
cli
@@ -333,7 +339,9 @@ HIDE:
; no special action is required besides enabling the mouse cursor.
; No return code required.
SHOW:
inc visible
sei
jsr CSHOW
cli
rts
; BUTTONS: Return the button mask in A/X.
@@ -409,7 +417,7 @@ done: rts
beq :+
; Remove the cursor at the old position
update: jsr CHIDE
update: jsr CPREP
; Get and set the new X position
ldy slot
@@ -427,11 +435,7 @@ update: jsr CHIDE
stx info + MOUSE_POS::YCOORD+1
jsr CMOVEY
; Check for visibility
: lda visible
beq :+
; Draw the cursor at the new position
jsr CSHOW
: sec ; Interrupt handled
: jsr CDRAW
sec ; Interrupt handled
rts

View File

@@ -16,6 +16,6 @@ initreboot:
; Quit to PWRUP
lda #<$FAA6
ldx #>$FAA6
sta done
stx done+1
sta done+1
stx done+2
rts

View File

@@ -25,10 +25,16 @@
.include "ser-kernel.inc"
.include "ser-error.inc"
.macpack module
; ------------------------------------------------------------------------
; Header. Includes jump table
.segment "JUMPTABLE"
.ifdef __APPLE2ENH__
module_header _a2e_ssc_ser
.else
module_header _a2_ssc_ser
.endif
; Driver signature
.byte $73, $65, $72 ; "ser"

View File

@@ -3,10 +3,10 @@
;
; time_t _systime (void);
; /* Similar to time(), but:
; * - Is not ISO C
; * - Does not take the additional pointer
; * - Does not set errno when returning -1
; */
; ** - Is not ISO C
; ** - Does not take the additional pointer
; ** - Does not set errno when returning -1
; */
;
.include "time.inc"

View File

@@ -1,9 +1,9 @@
DEPS += ../wrk/$(TARGET)/loader.d
DEPS += ../libwrk/$(TARGET)/loader.d
../wrk/$(TARGET)/loader.o: $(SRCDIR)/targetutil/loader.s | ../wrk/$(TARGET)
../libwrk/$(TARGET)/loader.o: $(SRCDIR)/targetutil/loader.s | ../libwrk/$(TARGET)
$(ASSEMBLE_recipe)
../targetutil/loader.system: ../wrk/$(TARGET)/loader.o $(SRCDIR)/targetutil/loader.cfg | ../targetutil
../targetutil/loader.system: ../libwrk/$(TARGET)/loader.o $(SRCDIR)/targetutil/loader.cfg | ../targetutil
$(LD65) -o $@ -C $(filter %.cfg,$^) $(filter-out %.cfg,$^)
$(TARGET): ../targetutil/loader.system

View File

@@ -1,80 +0,0 @@
LOADER.SYSTEM - an Apple][ ProDOS 8 loader for cc65 programs (Oliver Schmidt)
=============================================================================
Background
----------
Apple][ ProDOS 8 system programs (filetype SYS) are always loaded into memory
starting at location $2000. This poses the problem of how to make efficient
use of the memory in the range $0800-$2000. The usual approach of relocation
has two downsides:
- Relocating e.g. 30 kB from $2000-$9800 to $0800-$8000 takes a considerable
amount of time.
- Really large programs just don't fit into memory when loaded starting at
location $2000.
The relocation can be eliminated by loading the major part(s) of the program
from disk right to the final location by a rather small system program.
LOADER.SYSTEM is such a small program. In fact it's so small that it fits into
a single block in the ProDOS 8 file system making it a so-called seedling file,
which are loaded really fast. LOADER.SYSTEM can load cc65 programs into memory
anywhere in the range $0800-$BB00 (44,75 kB).
Usage
-----
Link the cc65 program to the start address $0803 (or any other address) and
store it as binary program (filetype BIN). This is in fact no different from
a binary program to be run by BASIC.SYSTEM's BRUN command in the usual way.
If however the cc65 program isn't run by BASIC.SYSTEM but is rather run by
LOADER.SYSTEM then it behaves like a system program which means:
- It uses memory up to the ProDOS 8 system global page located at $BF00.
- It supports the ProDOS 8 startup file mechanism (mapped to argv[1]).
- It quits to the ProDOS 8 dispatcher.
Obviously LOADER.SYSTEM has to be told which cc65 program to run. Unfortunately
the ProDOS 8 dispatcher has no notion of system program parameters so the usual
approach would have been to make LOADER.SYSTEM bring up yet another menu to
select the cc65 program to run.
But to allow to select the cc65 program directly from the ProDOS 8 dispatcher
anyway LOADER.SYSTEM detects the path to the cc65 program from its own path by
just removing the '.SYSTEM' from its name. So if you want to run the cc65
program MYPROGRAM you'll need a copy of LOADER.SYSTEM in the same directory
being renamed to MYPROGRAM.SYSTEM.
This means you will end up with a copy of LOADER.SYSTEM for every cc65 program
to be run by it. But as LOADER.SYSTEM is a ProDOS 8 seedling file using up only
a single block in the ProDOS 8 file system this should be no issue.
Build
-----
In case you want to build 'loader.system' from the source code yourself you can
do so using the following commands:
ca65 loader.s
ld65 -C loader.cfg -o loader.system loader.o
Installation
------------
The file 'loader.system' as generated by the cc65 linker with the command above
does NOT include the 4-byte address/length header that is generated for Apple][
programs by default. This is because ProDOS 8 system programs are always loaded
into memory starting at location $2000.
The recommended way to transfer 'loader.system' from your native file system to
a ProDOS 8 file system disk image is to use AppleCommander which is available at
http://applecommander.sourceforge.net/
If you want to put the file 'loader.system' onto a disk image 'mydisk.dsk' as
system program MYPROGRAM.SYSTEM you can do so using the following command:
java -jar ac.jar -p mydisk.dsk MYPROGRAM.SYSTEM sys < loader.system

View File

@@ -11,6 +11,8 @@
.include "tgi-error.inc"
.include "apple2.inc"
.macpack module
; ------------------------------------------------------------------------
; Zero page stuff
@@ -68,7 +70,11 @@ Y2 := ptr4
; ------------------------------------------------------------------------
.segment "JUMPTABLE"
.ifdef __APPLE2ENH__
module_header _a2e_hi_tgi
.else
module_header _a2_hi_tgi
.endif
; Header. Includes jump table and constants.

View File

@@ -11,6 +11,8 @@
.include "tgi-error.inc"
.include "apple2.inc"
.macpack module
; ------------------------------------------------------------------------
; Zero page stuff
@@ -38,7 +40,11 @@ Y2 := ptr4
; ------------------------------------------------------------------------
.segment "JUMPTABLE"
.ifdef __APPLE2ENH__
module_header _a2e_lo_tgi
.else
module_header _a2_lo_tgi
.endif
; Header. Includes jump table and constants.

View File

@@ -31,3 +31,7 @@ CA65FLAGS += -D NUMDRVS=4 -D LINEBUF=80 -D UCASE_FILENAME=1 -D DEFAULT_DEVICE=1
# 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
# Disable if you don't want to use page 6 for mouse P/M data.
# If disabled, top of the RAM is used for P/M data.
CA65FLAGS += -D USE_PAGE6

23
libsrc/atari/carthdr.s Normal file
View File

@@ -0,0 +1,23 @@
; Cartridge "header"
; (In fact, it's at the end of the cartridge, so more a "trailer".)
;
; Christian Groessler, 06-Jan-2014
.ifndef __ATARIXL__
.export __CART_HEADER__: absolute = 1
.import __CARTSIZE__, __CARTFLAGS__, cartinit, cartstart
.include "atari.inc"
.segment "CARTHDR"
.word cartstart ; start routine
.byte 0 ; must be zero
.byte <__CARTFLAGS__
.word cartinit ; init routine
.assert (__CARTSIZE__ = $2000 || __CARTSIZE__ = $4000), error, "Cartridge size must either be $2000 or $4000"
.endif ; .ifndef __ATARIXL__

11
libsrc/atari/cartinit.s Normal file
View File

@@ -0,0 +1,11 @@
; Cartridge init routine
;
; Christian Groessler, 06-Jan-2014
.ifndef __ATARIXL__
.export cartinit
cartinit: rts
.endif ; .ifndef __ATARIXL__

20
libsrc/atari/cartstart.s Normal file
View File

@@ -0,0 +1,20 @@
; Cartridge start routine
;
; Christian Groessler, 06-Jan-2014
.ifndef __ATARIXL__
.export cartstart
.import start, copydata
.include "atari.inc"
; start routine of cartridge
; copy data segment to RAM and chain to entry point of crt0.s
cartstart: jsr copydata
jsr start ; run program
jmp (DOSVEC) ; return to DOS
.endif ; .ifndef __ATARIXL__

37
libsrc/atari/cashdr.s Normal file
View File

@@ -0,0 +1,37 @@
;
; Cassette boot file header
;
; Christian Groessler, chris@groessler.org, 2014
;
;DEBUG = 1
.ifndef __ATARIXL__
.include "atari.inc"
.import __BSS_RUN__, __STARTADDRESS__, _cas_init
.export _cas_hdr
.assert ((__BSS_RUN__ - __STARTADDRESS__ + 127) / 128) < $101, error, "File to big to load from cassette"
; for a description of the cassette header, see De Re Atari, appendix C
.segment "CASHDR"
_cas_hdr:
.byte 0 ; ignored
.byte <((__BSS_RUN__ - __STARTADDRESS__ + 127) / 128) ; # of 128-byte records to read
.word __STARTADDRESS__ ; load address
.word _cas_init ; init address
.ifdef DEBUG
lda #33
ldy #80
sta (SAVMSC),y
.endif
clc
rts
.endif ; .ifdef __ATARIXL__

31
libsrc/atari/casinit.s Normal file
View File

@@ -0,0 +1,31 @@
;
; Cassette boot file init routine
;
; Christian Groessler, chris@groessler.org, 2014
;
;DEBUG = 1
.ifndef __ATARIXL__
.include "atari.inc"
.import start
.export _cas_init
.segment "INIT"
_cas_init:
.ifdef DEBUG
lda #34
ldy #81
sta (SAVMSC),y
.endif
lda #<start
sta DOSVEC
lda #>start
sta DOSVEC+1
rts
.endif ; .ifdef __ATARIXL__

View File

@@ -14,10 +14,10 @@ _cgetc:
jsr setcursor
lda #12
sta ICAX1Z ; fix problems with direct call to KEYBDV
.ifndef __ATARIXL__
jsr @1
.else
.ifdef __ATARIXL__
jsr KEYBDV_handler
.else
jsr @1
.endif
ldx #0
rts

View File

@@ -9,6 +9,12 @@
.import popa, _gotoxy, cputdirect, setcursor
.importzp tmp1
.ifdef __ATARI5200__
CHRCODE = 14
.else
CHRCODE = $12+64
.endif
_chlinexy:
pha ; Save the length
jsr popa ; Get y
@@ -19,12 +25,8 @@ _chline:
cmp #0 ; Is the length zero?
beq L9 ; Jump if done
sta tmp1
L1: lda #$12+64 ; Horizontal line, screen code
L1: lda #CHRCODE ; Horizontal line, screen code
jsr cputdirect ; Direct output
dec tmp1
bne L1
L9: jmp setcursor

View File

@@ -32,8 +32,8 @@
.segment "STARTUP"
rts ; fix for SpartaDOS / OS/A+
; they first call the entry point from AUTOSTRT and
; then the load addess (this rts here).
; They first call the entry point from AUTOSTRT; and
; then, the load address (this rts here).
; We point AUTOSTRT directly after the rts.
; Real entry point:
@@ -44,18 +44,25 @@ start:
jsr sram_init
.endif
; Clear the BSS data
; Clear the BSS data.
jsr zerobss
; Setup the stack
; Set up the stack.
tsx
stx SP_save
.ifndef __ATARIXL__
.ifdef __ATARIXL__
; Report memory usage
lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
sta sp
lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
sta sp+1
.else
; Report the memory usage.
lda APPMHI
sta APPMHI_save ; remember old APPMHI value
@@ -66,67 +73,60 @@ start:
lda MEMTOP
sbc #<__RESERVED_MEMORY__
sta APPMHI ; initialize our APPMHI value
sta sp ; setup runtime stack part 1
sta sp ; set up runtime stack part 1
lda MEMTOP+1
sbc #>__RESERVED_MEMORY__
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
sta sp+1 ; set up runtime stack part 2
.endif
; Call module constructors
; Call the module constructors.
jsr initlib
; Set left margin to 0
; Set the left margin to 0.
lda LMARGN
sta LMARGN_save
ldy #0
sty LMARGN
; Set keyb to upper/lowercase mode
; Set the keyboard to upper-/lower-case mode.
ldx SHFLOK
stx SHFLOK_save
sty SHFLOK
; Initialize conio stuff
; Initialize the conio stuff.
dey ; Set X to $FF
sty CH
dey ; Set Y to $FF
sty CH ; remove keypress which might be in the input buffer
; Push arguments and call main
; Push the command-line arguments; and, call main().
jsr callmain
; Call module destructors. This is also the _exit entry.
; Call the module destructors. This is also the exit() entry.
_exit: jsr donelib ; Run module destructors
; Restore system stuff
; Restore the system stuff.
ldx SP_save
txs ; Restore stack pointer
; Restore left margin
; Restore the left margin.
lda LMARGN_save
sta LMARGN
; Restore kb mode
; Restore the kb mode.
lda SHFLOK_save
sta SHFLOK
; Restore APPMHI
; Restore APPMHI.
lda APPMHI_save
sta APPMHI
@@ -147,8 +147,8 @@ _exit: jsr donelib ; Run module destructors
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
; Issue a GRAPHICS 0 call (copied'n'pasted from the TGI drivers), in
; order to restore screen memory to its default location just
; before the ROM.
jsr findfreeiocb
@@ -169,7 +169,7 @@ _exit: jsr donelib ; Run module destructors
lda #0
sta ICBLH,x
jsr CIOV_org
; No error checking here, shouldn't happen(tm), and no way to
; No error checking here, shouldn't happen(TM); and, no way to
; recover anyway.
lda #CLOSE
@@ -178,12 +178,12 @@ _exit: jsr donelib ; Run module destructors
.endif
; Turn on cursor
; Turn on the cursor.
ldx #0
stx CRSINH
; Back to DOS
; Back to DOS.
rts

View File

@@ -10,6 +10,12 @@
.import popa, _gotoxy, putchar, setcursor
.importzp tmp1
.ifdef __ATARI5200__
CHRCODE = 1 ; exclamation mark
.else
CHRCODE = $7C ; Vertical bar
.endif
_cvlinexy:
pha ; Save the length
jsr popa ; Get y
@@ -22,7 +28,7 @@ _cvline:
sta tmp1
L1: lda COLCRS
pha
lda #$7C ; Vertical bar
lda #CHRCODE ; Vertical bar
jsr putchar ; Write, no cursor advance
pla
sta COLCRS
@@ -30,6 +36,3 @@ L1: lda COLCRS
dec tmp1
bne L1
L9: jmp setcursor

View File

@@ -31,12 +31,17 @@
.macpack generic
.macpack module
; ------------------------------------------------------------------------
; Header. Includes jump table
.segment "JUMPTABLE"
.ifdef __ATARIXL__
module_header _atrx130_emd
.else
module_header _atr130_emd
.endif
; Driver signature

View File

@@ -1,7 +1,7 @@
; This file defines the EXE file "trailer" which sets the entry point
.export __AUTOSTART__: absolute = 1
.import start
.import start
.include "atari.inc"

View File

@@ -16,26 +16,24 @@
.segment "INIT"
initirq:
lda VVBLKI
ldx VVBLKI+1
lda VVBLKD
ldx VVBLKD+1
sta IRQInd+1
stx IRQInd+2
lda #6
lda #7
ldy #<IRQStub
ldx #>IRQStub
jsr SETVBV
rts
jmp SETVBV
; ------------------------------------------------------------------------
.code
doneirq:
lda #6
lda #7
ldy IRQInd+1
ldx IRQInd+2
jsr SETVBV
rts
jmp SETVBV
; ------------------------------------------------------------------------
@@ -44,7 +42,6 @@ doneirq:
IRQStub:
cld ; Just to be sure
.ifdef __ATARIXL__
pha
.ifdef CHARGEN_RELOC
lda CHBAS
pha
@@ -64,7 +61,6 @@ IRQStub:
sta CHBAS
sta CHBASE
.endif
pla
.endif
jmp IRQInd ; Jump to the saved IRQ vector

View File

@@ -14,12 +14,17 @@
.include "atari.inc"
.macpack generic
.macpack module
; ------------------------------------------------------------------------
; Header. Includes jump table
.segment "JUMPTABLE"
.ifdef __ATARIXL__
module_header _atrxmj8_joy
.else
module_header _atrmj8_joy
.endif
; Driver signature

View File

@@ -13,12 +13,17 @@
.include "atari.inc"
.macpack generic
.macpack module
; ------------------------------------------------------------------------
; Header. Includes jump table
.segment "JUMPTABLE"
.ifdef __ATARIXL__
module_header _atrxstd_joy
.else
module_header _atrstd_joy
.endif
; Driver signature

View File

@@ -7,8 +7,16 @@
;
.export _joy_static_stddrv
.ifdef __ATARIXL__
.import _atrxstd_joy
.else
.import _atrstd_joy
.endif
.rodata
.ifdef __ATARIXL__
_joy_static_stddrv := _atrxstd_joy
.else
_joy_static_stddrv := _atrstd_joy
.endif

View File

@@ -10,4 +10,9 @@
.rodata
_joy_stddrv: .asciiz "atrstd.joy"
_joy_stddrv:
.ifdef __ATARIXL__
.asciiz "atrxstd.joy"
.else
.asciiz "atrstd.joy"
.endif

View File

@@ -0,0 +1,8 @@
;
; This file defines the default mouse callback
;
.import _mouse_pm_callbacks
.export _mouse_def_callbacks
_mouse_def_callbacks := _mouse_pm_callbacks

View File

@@ -0,0 +1,31 @@
;
; P/M mouse shape default definition
;
; Christian Groessler, 11.04.2014
;
; Note that the height of the mouse cursor must not exceed 32
; lines, otherwise the display routines won't do The Right
; Thing(tm).
;
.export mouse_pm_bits
.export mouse_pm_height : zeropage
.export mouse_pm_hotspot_x : zeropage
.export mouse_pm_hotspot_y : zeropage
.rodata
mouse_pm_bits:
.byte %11110000
.byte %11000000
.byte %10100000
.byte %10010000
.byte %10001000
.byte %00000100
.byte %00000010
mouse_pm_height = <(* - mouse_pm_bits)
; hot spot is upper left corner
mouse_pm_hotspot_x = 0
mouse_pm_hotspot_y = 0

237
libsrc/atari/mcbpm.s Normal file
View File

@@ -0,0 +1,237 @@
;
; P/M mouse callbacks for the Ataris
;
; Christian Groessler, 11.04.2014
;
; All functions in this module should be interrupt safe, because they may
; be called from an interrupt handler
;
.include "atari.inc"
.importzp sp
.export _mouse_pm_callbacks
.constructor pm_init,27
.destructor pm_down,7
; get mouse shape data
.import mouse_pm_bits
.importzp mouse_pm_height
.importzp mouse_pm_hotspot_x
.importzp mouse_pm_hotspot_y
; P/M definitions. The MOUSE_PM_NUM value can be changed to adjust the
; number of the P/M used for the mouse. All others depend on this value.
; Valid P/M numbers are 0 to 4. When 4 is used, the missiles are used
; as a player.
.ifdef USE_PAGE6
MOUSE_PM_NUM = 2 ; P/M used for the mouse
; This cannot be changed since only player #2 uses the memory at $600.
.else
MOUSE_PM_NUM = 4 ; P/M used for the mouse
; Using player #4 (missiles) wastes the least amount of memory on the
; atari target, since top of memory is typically at $xC20, and the
; missiles use the space at $xB00-$xBFF.
; On the atarixl target this configuration (not using page 6) is not
; really satisfying since the top of memory typically lies beneath
; the ROM and there is flickering visible while the ROM is banked in.
.endif
MOUSE_PM_BASE = pm_base ; ZP location pointing to the hw area used by the selected P/M
.if MOUSE_PM_NUM = 4
MOUSE_PM_RAW = 0 ; MOUSE_PM_RAW is the hardware P/M number for MOUSE_PM_NUM
.macro set_mouse_x
; assume CF = 0
sta HPOSM3
adc #2
sta HPOSM2
adc #2
sta HPOSM1
adc #2
sta HPOSM0
.endmacro
.else
MOUSE_PM_RAW = MOUSE_PM_NUM + 1
.macro set_mouse_x
sta HPOSP0 + MOUSE_PM_NUM
.endmacro
.endif
; ------------------------------------------------------------------------
.rodata
; Callback structure
_mouse_pm_callbacks:
.addr hide
.addr show
.addr prep
.addr draw
.addr movex
.addr movey
; ------------------------------------------------------------------------
.bss
omy: .res 1 ; old Mouse Y position
colhlp: .res 1 ; helper variable to set P/M color
; ------------------------------------------------------------------------
.segment "EXTZP" : zeropage
pm_base:.res 2
; ------------------------------------------------------------------------
.code
; Hide the mouse cursor.
hide: lda #0
sta GRACTL
rts
; Show the mouse cursor.
show:
.if MOUSE_PM_NUM < 4
lda #2
.else
lda #1
.endif
sta GRACTL
jmp update_colors
prep:
draw:
rts
; Move the mouse cursor x position to the value in A/X.
movex: cpx #1
ror a
clc
adc #48
sbc #(mouse_pm_hotspot_x - 1) & $FF
set_mouse_x
jmp update_colors
; Move the mouse cursor y position to the value in A/X.
movey: clc
adc #32
sbc #(mouse_pm_hotspot_y - 1) & $FF
pha
lda omy
jsr clr_pm ; remove player at old position
jsr update_colors
pla
sta omy
;jmp set_pm ; put player to new position
; fall thru
; Set P/M data from 'mouse_pm_bits'
set_pm: tay
ldx #0
set_l: lda mouse_pm_bits,x
sta (MOUSE_PM_BASE),y
inx
iny
beq set_end
cpx #mouse_pm_height
bcc set_l
set_end:rts
; Clear (zero) P/M data
clr_pm: ldx #mouse_pm_height
tay
lda #0
clr_l: sta (MOUSE_PM_BASE),y
iny
beq clr_end
dex
bne clr_l
clr_end:rts
pm_down = hide
; this assumes a GRAPHICS 0 screen
update_colors:
lda COLOR2 ; get background color
and #$F0
sta colhlp
lda COLOR1
and #$0F
ora colhlp
.if MOUSE_PM_NUM = 4
sta PCOLR0
sta PCOLR1
sta PCOLR2
sta PCOLR3
lda #0
sta SIZEM
.else
sta PCOLR0 + MOUSE_PM_NUM
lda #0
sta SIZEP0 + MOUSE_PM_NUM
.endif
rts
; ------------------------------------------------------------------------
.segment "INIT"
pm_init:
lda #0
.ifdef USE_PAGE6
sta MOUSE_PM_BASE
ldx #6 ; page 6
stx MOUSE_PM_BASE+1
.else
; use top of memory and lower sp accordingly
sta sp
sta MOUSE_PM_BASE
lda sp+1
and #7 ; offset within 2K
cmp #3 + MOUSE_PM_RAW + 1 ; can we use it?
bcc @decr ; no
lda sp+1
and #$F8
@set: adc #3 + MOUSE_PM_RAW - 1 ; CF is set, so adding MOUSE_PM_RAW + 3
sta MOUSE_PM_BASE+1
sta sp+1
bne @cont ; jump always
@decr: lda sp+1
and #$F8
sbc #8 - 1 ; CF is clear, subtracts 8
bcs @set ; jump always
@cont: lda #0
.endif
tay
@iniloo:sta (MOUSE_PM_BASE),y
iny
bne @iniloo
.ifndef USE_PAGE6
lda MOUSE_PM_BASE+1
and #$F8
.endif
sta PMBASE
lda #62
sta SDMCTL
lda #1
sta GPRIOR
jmp update_colors

View File

@@ -0,0 +1,7 @@
;
; Default text mode mouse cursor character
;
; Christian Groessler, 11.04.2014
;
.export mouse_txt_char : zp = 96 ; 'diamond' screen code

125
libsrc/atari/mcbtxtchar.s Normal file
View File

@@ -0,0 +1,125 @@
;
; Text mode character mouse callbacks for the Ataris
;
; Christian Groessler, 03.01.2014
;
; derived from Apple2 version by
; Oliver Schmidt, 22.09.2005
;
; All functions in this module should be interrupt safe, because they may
; be called from an interrupt handler
;
.export _mouse_txt_callbacks
.importzp tmp4
.import mul40,loc_tmp
.importzp mouse_txt_char ; screen code of mouse cursor
.include "atari.inc"
; ------------------------------------------------------------------------
.bss
backup: .res 1
visible:.res 1
; ------------------------------------------------------------------------
.segment "EXTZP" : zeropage
scrptr: .res 2
; ------------------------------------------------------------------------
.rodata
; Callback structure
_mouse_txt_callbacks:
.addr hide
.addr show
.addr prep
.addr draw
.addr movex
.addr movey
; ------------------------------------------------------------------------
.data
; setcursor
getcursor:
column: ldy #$00 ; Patched at runtime
lda (scrptr),y
rts
setcursor:
column2:ldy #$00 ; Patched at runtime
sta (scrptr),y
rts
; ------------------------------------------------------------------------
.code
done:
rts
; Hide the mouse cursor.
hide:
dec visible
prep:
jsr getcursor ; Get character at cursor position
cmp #mouse_txt_char ; "mouse" character
bne overwr ; no, probably program has overwritten it
lda backup ;
jmp setcursor ; Draw character
overwr: sta backup
rts
; Show the mouse cursor.
show:
inc visible
draw:
lda visible
beq done
jsr getcursor ; Cursor visible at current position?
sta backup ; Save character at cursor position
lda #mouse_txt_char
jmp setcursor ; Draw cursor
; Move the mouse cursor x position to the value in A/X.
movex:
cpx #1
ror a
lsr a ; convert to character position
lsr a
sta column+1
sta column2+1
rts
; Move the mouse cursor y position to the value in A/X.
movey:
tax
ldy tmp4 ; mul40 uses tmp4
lda loc_tmp ; and this local variable
pha
txa ; get parameter back
lsr a ; convert y position to character line
lsr a
lsr a
jsr mul40
clc
adc SAVMSC
sta scrptr
txa
adc SAVMSC+1
sta scrptr+1
pla
sta loc_tmp
sty tmp4
rts

View File

@@ -0,0 +1,2 @@
AMIGA_MOUSE = 1
.include "atrst.s"

440
libsrc/atari/mou/atrjoy.s Normal file
View File

@@ -0,0 +1,440 @@
;
; Driver for a "joystick mouse".
;
; C128 version: Ullrich von Bassewitz, 2004-04-05, 2009-09-26
; Adapted to Atari: Christian Groessler, 2014-01-02
;
.include "zeropage.inc"
.include "mouse-kernel.inc"
.include "atari.inc"
.macpack generic
.macpack module
; ------------------------------------------------------------------------
; Header. Includes jump table
.ifdef __ATARIXL__
module_header _atrxjoy_mou
.else
module_header _atrjoy_mou
.endif
HEADER:
; Driver signature
.byte $6d, $6f, $75 ; "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
CPREP: jmp $0000 ; Prepare to move the cursor
CDRAW: jmp $0000 ; Draw the cursor
CMOVEX: jmp $0000 ; Move the cursor to X coord
CMOVEY: jmp $0000 ; Move the cursor to Y coord
;----------------------------------------------------------------------------
; Constants
SCREEN_HEIGHT = 191
SCREEN_WIDTH = 319
.enum JOY
UP = $01
DOWN = $02
LEFT = $04
RIGHT = $08
.endenum
;----------------------------------------------------------------------------
; 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
; reorder 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
Buttons: .res 1 ; Button mask
Temp: .res 1 ; Temporary value used in the int handler
; Default values for above variables
.rodata
; (We use ".proc" because we want to define both a label and a scope.)
.proc DefVars
.word SCREEN_HEIGHT/2 ; YPos
.word SCREEN_WIDTH/2 ; XPos
.word 0 ; XMin
.word 0 ; YMin
.word SCREEN_WIDTH ; XMax
.word SCREEN_HEIGHT ; YMax
.byte 0 ; Buttons
.endproc
.code
;----------------------------------------------------------------------------
; INSTALL routine. Is called after the driver is loaded into memory. If
; possible, check if the hardware is present.
; Must return an MOUSE_ERR_xx code in a/x.
INSTALL:
; Initialize variables. Just copy the default stuff over
ldx #.sizeof(DefVars)-1
@L1: lda DefVars,x
sta Vars,x
dex
bpl @L1
; Make sure the mouse cursor is at the default location.
lda XPos
ldx XPos+1
jsr CMOVEX
lda YPos
ldx YPos+1
jsr CMOVEY
; Done, return zero (= MOUSE_ERR_OK)
ldx #$00
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 only called
; if the mouse is currently visible and should get hidden. For most drivers,
; no special action is required besides hiding the mouse cursor.
; No return code required.
HIDE: php
sei
jsr CHIDE
plp
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 only called
; if the mouse is currently hidden and should become visible. For most drivers,
; no special action is required besides enabling the mouse cursor.
; No return code required.
SHOW: php
sei
jsr CSHOW
plp
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 a/x.
; No checks are done if the mouse is currently inside the box, this 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
php
sei
@L1: lda (ptr1),y
sta XMin,y
dey
bpl @L1
plp
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 a/x.
GETBOX: sta ptr1
stx ptr1+1 ; Save data pointer
ldy #.sizeof (MOUSE_BOX)-1
php
sei
@L1: lda XMin,y
sta (ptr1),y
dey
bpl @L1
plp
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 a/x. 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: php
sei ; No interrupts
pha
txa
pha
jsr CPREP
pla
tax
pla
sta YPos
stx YPos+1 ; New Y position
jsr CMOVEY ; Set it
ldy #$01
lda (sp),y
sta XPos+1
tax
dey
lda (sp),y
sta XPos ; New X position
jsr CMOVEX ; Move the cursor
jsr CDRAW
plp ; Restore interrupt flag
rts
;----------------------------------------------------------------------------
; BUTTONS: Return the button mask in a/x.
BUTTONS:
lda Buttons
ldx #$00
rts
;----------------------------------------------------------------------------
; 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
php
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
plp ; Restore interrupt flag
iny
sta (ptr1),y ; Store last byte
rts ; Done
;----------------------------------------------------------------------------
; 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 will just
; call _mouse_pos to initialize the struct pointer and fill the position
; fields.
INFO: jsr POS
; Fill in the button state
lda Buttons
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 a/x.
;
IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now
ldx #>MOUSE_ERR_INV_IOCTL
rts
;----------------------------------------------------------------------------
; IRQ: Irq handler entry point. Called as a subroutine but in 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:
; Check for a pressed button and place the result into Buttons
ldx #0
lda TRIG0 ; joystick #0 trigger
bne @L0 ; not pressed
ldx #MOUSE_BTN_LEFT
@L0: stx Buttons
lda PORTA ; get joystick direction bits
and #15 ; clear joystick #1 bits
eor #15
sta Temp
jsr CPREP
; Check left/right
lda Temp ; Read joystick #0
and #(JOY::LEFT | JOY::RIGHT)
beq @SkipX ;
; We will cheat here and rely on the fact that either the left, OR the right
; bit can be active
and #JOY::RIGHT ; Check RIGHT bit
bne @Right
lda #$FF
tax
bne @AddX ; Branch always
@Right: lda #$01
ldx #$00
; Calculate the new X coordinate (--> a/y)
@AddX: add XPos
tay ; Remember low byte
txa
adc XPos+1
tax
; Limit the X coordinate 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: sty XPos
stx XPos+1
; Move the mouse pointer to the new X pos
tya
jsr CMOVEX
; Calculate the Y movement vector
@SkipX: lda Temp ; Read joystick #0
and #(JOY::UP | JOY::DOWN) ; Check up/down
beq @SkipY ;
; We will cheat here and rely on the fact that either the up, OR the down
; bit can be active
lsr a
bcc @Down
lda #$FF
tax
bne @AddY
@Down: lda #$01
ldx #$00
; Calculate the new Y coordinate (--> a/y)
@AddY: add YPos
tay ; Remember low byte
txa
adc YPos+1
tax
; Limit the Y coordinate 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: sty YPos
stx YPos+1
; Move the mouse pointer to the new X pos
tya
jsr CMOVEY
; Done
@SkipY: jsr CDRAW
clc ; Interrupt not "handled"
rts

823
libsrc/atari/mou/atrst.s Normal file
View File

@@ -0,0 +1,823 @@
;
; Mouse driver for ST & Amiga mouses and Atari trakball.
;
; Original access routines: 05/07/2000 Freddy Offenga
; Converted to driver: Christian Groessler, 2014-01-04
;
; Defines:
; AMIGA_MOUSE - builds Amiga mouse version
; TRAK_MOUSE - builds trakball version
; If none of these defines are active, the ST mouse version
; is being built.
;
;DEBUG = 1
DISABLE_TIMEOUT = 30 ; # of vertical blank interrupts after which, if
; no mouse motion occurred, the polling IRQ gets
; disabled.
; VBI frequency is 50Hz for PAL and 60Hz for NTSC
.include "zeropage.inc"
.include "mouse-kernel.inc"
.include "atari.inc"
.macpack generic
.macpack module
.if .not ( .defined (AMIGA_MOUSE) .or .defined (TRAK_MOUSE))
ST_MOUSE = 1
.endif
; ------------------------------------------------------------------------
; Header. Includes jump table
.if .defined (ST_MOUSE)
.ifdef __ATARIXL__
module_header _atrxst_mou
.else
module_header _atrst_mou
.endif
.elseif .defined (AMIGA_MOUSE)
.ifdef __ATARIXL__
module_header _atrxami_mou
.else
module_header _atrami_mou
.endif
.elseif .defined (TRAK_MOUSE)
.ifdef __ATARIXL__
module_header _atrxtrk_mou
.else
module_header _atrtrk_mou
.endif
.endif
HEADER:
; Driver signature
.byte $6d, $6f, $75 ; "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_LATE_IRQ
; Callback table, set by the kernel before INSTALL is called
CHIDE: jmp $0000 ; Hide the cursor
CSHOW: jmp $0000 ; Show the cursor
CPREP: jmp $0000 ; Prepare to move the cursor
CDRAW: jmp $0000 ; Draw the cursor
CMOVEX: jmp $0000 ; Move the cursor to X coord
CMOVEY: jmp $0000 ; Move the cursor to Y coord
;----------------------------------------------------------------------------
; Constants
SCREEN_HEIGHT = 191
SCREEN_WIDTH = 319
.enum JOY
UP = $01
DOWN = $02
LEFT = $04
RIGHT = $08
.endenum
;----------------------------------------------------------------------------
; 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
; reorder 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
Buttons: .res 1 ; Button mask
XPosWrk: .res 2
YPosWrk: .res 2
irq_enabled: .res 1 ; flag indicating that the high frequency polling interrupt is enabled
old_porta_vbi: .res 1 ; previous PORTA value of the VBI interrupt (IRQ)
how_long: .res 1 ; counter for how many VBI interrupts the mouse hasn't been moved
.if .defined (AMIGA_MOUSE) .or .defined (ST_MOUSE)
dumx: .res 1
dumy: .res 1
.endif
.ifdef TRAK_MOUSE
oldval: .res 1
.endif
.ifndef __ATARIXL__
OldT1: .res 2
.else
.data
set_VTIMR1_handler:
.byte $4C, 0, 0
.endif
.rodata
; Default values for some of the above variables
; (We use ".proc" because we want to define both a label and a scope.)
.proc DefVars
.word (SCREEN_HEIGHT+1)/2 ; YPos
.word (SCREEN_WIDTH+1)/2 ; XPos
.word 0 ; XMin
.word 0 ; YMin
.word SCREEN_WIDTH ; XMax
.word SCREEN_HEIGHT ; YMax
.byte 0 ; Buttons
.endproc
.ifdef ST_MOUSE
; ST mouse lookup table
STTab: .byte $FF,$01,$00,$01
.byte $00,$FF,$00,$01
.byte $01,$00,$FF,$00
.byte $01,$00,$01,$FF
.endif
.ifdef AMIGA_MOUSE
; Amiga mouse lookup table
AmiTab: .byte $FF,$01,$00,$FF
.byte $00,$FF,$FF,$01
.byte $01,$FF,$FF,$00
.byte $FF,$00,$01,$FF
.endif
.code
;----------------------------------------------------------------------------
; INSTALL routine. Is called after the driver is loaded into memory. If
; possible, check if the hardware is present.
; Must return an MOUSE_ERR_xx code in a/x.
INSTALL:
; Initialize variables. Just copy the default stuff over
ldx #.sizeof(DefVars)-1
@L1: lda DefVars,x
sta Vars,x
dex
bpl @L1
; Make sure the mouse cursor is at the default location.
lda XPos
sta XPosWrk
ldx XPos+1
stx XPosWrk+1
jsr CMOVEX
lda YPos
sta YPosWrk
ldx YPos+1
stx YPosWrk+1
jsr CMOVEY
; Install timer irq routine to poll mouse.
.ifdef __ATARIXL__
; Setup pointer to wrapper install/deinstall function.
lda libref
sta set_VTIMR1_handler+1
lda libref+1
sta set_VTIMR1_handler+2
; Install my handler.
sec
lda #<T1Han
ldx #>T1Han
jsr set_VTIMR1_handler
.else
lda VTIMR1
sta OldT1
lda VTIMR1+1
sta OldT1+1
php
sei
lda #<T1Han
sta VTIMR1
lda #>T1Han
sta VTIMR1+1
plp
.endif
lda #%00000001
sta AUDCTL
lda #0
sta AUDC1
lda #15
sta AUDF1
sta STIMER
.if 0 ; the IRQ will now be dynamically enabled when the mouse is moved
lda POKMSK
ora #%00000001 ; timer 1 enable
sta POKMSK
sta IRQEN
sta irq_enabled
.endif
lda PORTA
and #$0f
sta old_porta_vbi
; Done, return zero (= MOUSE_ERR_OK)
ldx #$00
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:
; uninstall timer irq routine
lda POKMSK
and #%11111110 ; timer 1 disable
sta IRQEN
sta POKMSK
.ifdef __ATARIXL__
clc
jsr set_VTIMR1_handler
.else
php
sei
lda OldT1
sta VTIMR1
lda OldT1+1
sta VTIMR1+1
plp
.endif
; fall thru...
;----------------------------------------------------------------------------
; 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 only called
; if the mouse is currently visible and should get hidden. For most drivers,
; no special action is required besides hiding the mouse cursor.
; No return code required.
HIDE: php
sei
jsr CHIDE
plp
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 only called
; if the mouse is currently hidden and should become visible. For most drivers,
; no special action is required besides enabling the mouse cursor.
; No return code required.
SHOW: php
sei
jsr CSHOW
plp
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 a/x.
; No checks are done if the mouse is currently inside the box, this 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
php
sei
@L1: lda (ptr1),y
sta XMin,y
dey
bpl @L1
plp
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 a/x.
GETBOX: sta ptr1
stx ptr1+1 ; Save data pointer
ldy #.sizeof (MOUSE_BOX)-1
php
sei
@L1: lda XMin,y
sta (ptr1),y
dey
bpl @L1
plp
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 a/x. 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: php
sei ; No interrupts
pha
txa
pha
jsr CPREP
pla
tax
pla
sta YPos
sta YPosWrk
stx YPos+1 ; New Y position
stx YPosWrk+1
jsr CMOVEY ; Set it
ldy #$01
lda (sp),y
sta XPos+1
sta XPosWrk+1
tax
dey
lda (sp),y
sta XPos ; New X position
sta XPosWrk
jsr CMOVEX ; Move the cursor
jsr CDRAW
plp ; Restore interrupt flag
rts
;----------------------------------------------------------------------------
; BUTTONS: Return the button mask in a/x.
BUTTONS:
lda Buttons
ldx #$00
rts
;----------------------------------------------------------------------------
; 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
php
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
plp ; Restore interrupt flag
iny
sta (ptr1),y ; Store last byte
rts ; Done
;----------------------------------------------------------------------------
; 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 will just
; call _mouse_pos to initialize the struct pointer and fill the position
; fields.
INFO: jsr POS
; Fill in the button state
lda Buttons
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 a/x.
;
IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now
ldx #>MOUSE_ERR_INV_IOCTL
rts
;----------------------------------------------------------------------------
; IRQ: Irq handler entry point. Called as a subroutine but in 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: lda PORTA ; mouse port contents
and #$0f ; check port 1 only
ldx irq_enabled
bne @L1
; IRQ is disabled, check for mouse motion and enable IRQ if mouse motion detected
cmp old_porta_vbi
beq @L3 ; no motion
; Turn mouse polling IRQ back on
lda POKMSK
ora #%00000001 ; timer 1 enable
sta POKMSK
sta IRQEN
sta irq_enabled
bne @L3
; not reached
; IRQ is enabled
@L1: cmp old_porta_vbi ; mouse motion since last VBI?
sta old_porta_vbi
beq @L2 ; no, increment timeout to disable IRQ
lda #0
sta how_long ; yes, reinitialize wait counter
beq @L3
; not reached
@L2: inc how_long ; no motion, increment wait counter
lda how_long
cmp #DISABLE_TIMEOUT ; timeout?
bcc @L3 ; no
lda #0 ; yes, turn off IRQ
sta how_long
; no mouse input -- turn IRQ off
sta irq_enabled
lda POKMSK
and #%11111110 ; timer 1 disable
sta IRQEN
sta POKMSK
; Check for a pressed button and place the result into Buttons
@L3: ldx #0
lda TRIG0 ; joystick #0 trigger
bne @L4 ; not pressed
ldx #MOUSE_BTN_LEFT
@L4: stx Buttons
jsr CPREP
; Limit the X coordinate to the bounding box
lda XPosWrk+1
ldy XPosWrk
tax
cpy XMin
sbc XMin+1
bpl @L5
ldy XMin
ldx XMin+1
jmp @L6
@L5: txa
cpy XMax
sbc XMax+1
bmi @L6
ldy XMax
ldx XMax+1
@L6: sty XPos
stx XPos+1
tya
jsr CMOVEX
; Limit the Y coordinate to the bounding box
lda YPosWrk+1
ldy YPosWrk
tax
cpy YMin
sbc YMin+1
bpl @L7
ldy YMin
ldx YMin+1
jmp @L8
@L7: txa
cpy YMax
sbc YMax+1
bmi @L8
ldy YMax
ldx YMax+1
@L8: sty YPos
stx YPos+1
tya
jsr CMOVEY
jsr CDRAW
.ifdef DEBUG
; print on upper right corner 'E' or 'D', indicating the IRQ is enabled or disabled
ldy irq_enabled
beq @L9
lda #37 ; screen code for 'E'
.byte $2c ; bit opcode, eats next 2 bytes
@L9: lda #36 ; screen code for 'D'
ldy #39
sta (SAVMSC),y
.endif
clc
rts
;----------------------------------------------------------------------------
; T1Han: Local IRQ routine to poll mouse
;
T1Han: lda CRITIC ; if CRITIC flag is set, disable the
bne disable_me ; high frequency polling IRQ, in order
; not to interfere with SIO I/O (e.g.
; floppy access)
tya
pha
txa
pha
.ifdef DEBUG
lda RANDOM
sta COLBK
.endif
lda PORTA
tay
.ifdef ST_MOUSE
; ST mouse version
and #%00000011
ora dumx
tax
lda STTab,x
bmi nxst
beq xist
dec XPosWrk
lda XPosWrk
cmp #255
bne nxst
dec XPosWrk+1
jmp nxst
xist: inc XPosWrk
bne nxst
inc XPosWrk+1
nxst: tya
and #%00001100
ora dumy
tax
lda STTab,x
bmi nyst
bne yst
dec YPosWrk
lda YPosWrk
cmp #255
bne nyst
dec YPosWrk+1
jmp nyst
yst: inc YPosWrk
bne nyst
inc YPosWrk+1
; store old readings
nyst: tya
and #%00000011
asl
asl
sta dumx
tya
and #%00001100
lsr
lsr
sta dumy
.elseif .defined (AMIGA_MOUSE)
; Amiga mouse version
lsr
and #%00000101
ora dumx
tax
lda AmiTab,x
bmi nxami
bne xiami
dec XPosWrk
lda XPosWrk
cmp #255
bne nxami
dec XPosWrk+1
jmp nxami
xiami: inc XPosWrk
bne nxami
inc XPosWrk+1
nxami: tya
and #%00000101
ora dumy
tax
lda AmiTab,x
bmi nyami
bne yiami
dec YPosWrk
lda YPosWrk
cmp #255
bne nyami
dec YPosWrk+1
jmp nyami
yiami: inc YPosWrk
bne nyami
inc YPosWrk+1
; store old readings
nyami: tya
and #%00001010
sta dumx
tya
and #%00000101
asl
sta dumy
.elseif .defined (TRAK_MOUSE)
; trakball version
eor oldval
and #%00001000
beq horiz
tya
and #%00000100
beq mmup
inc YPosWrk
bne horiz
inc YPosWrk+1
bne horiz
mmup: dec YPosWrk
lda YPosWrk
cmp #255
bne horiz
dec YPosWrk+1
horiz: tya
eor oldval
and #%00000010
beq mmexit
tya
and #%00000001
beq mmleft
inc XPosWrk
bne mmexit
inc XPosWrk+1
bne mmexit
mmleft: dec XPosWrk
lda XPosWrk
cmp #255
bne mmexit
dec XPosWrk+1
mmexit: sty oldval
.endif
pla
tax
pla
tay
.ifdef __ATARIXL__
rts
.else
pla
rti
.endif
; Disable the interrupt source which caused us to be called.
; The interrupt will be enabled again by the "IRQ" routine.
; The "IRQ" routine, despite its name, is called from the
; vertical blank NMI interrupt *only* if the CRITIC flag has
; been cleared.
disable_me:
lda POKMSK
and #%11111110 ; timer 1 disable
sta IRQEN
sta POKMSK
lda #0
sta irq_enabled
lda PORTA
and #$0f
sta old_porta_vbi
.ifdef __ATARIXL__
rts
.else
pla
rti
.endif

View File

@@ -0,0 +1,2 @@
TRAK_MOUSE = 1
.include "atrst.s"

482
libsrc/atari/mou/atrtt.s Normal file
View File

@@ -0,0 +1,482 @@
;
; Mouse driver for Atari Touch Tablet
;
; Christian Groessler, 2014-01-05
;
.include "zeropage.inc"
.include "mouse-kernel.inc"
.include "atari.inc"
.macpack generic
.macpack module
; ------------------------------------------------------------------------
; Header. Includes jump table
.ifdef __ATARIXL__
module_header _atrxtt_mou
.else
module_header _atrtt_mou
.endif
HEADER:
; Driver signature
.byte $6d, $6f, $75 ; "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
CPREP: jmp $0000 ; Prepare to move the cursor
CDRAW: jmp $0000 ; Draw the cursor
CMOVEX: jmp $0000 ; Move the cursor to X coord
CMOVEY: jmp $0000 ; Move the cursor to Y coord
;----------------------------------------------------------------------------
; Constants
SCREEN_HEIGHT = 191
SCREEN_WIDTH = 319
.enum JOY
UP = $01
DOWN = $02
LEFT = $04
RIGHT = $08
.endenum
;----------------------------------------------------------------------------
; 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
; reorder 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
Buttons: .res 1 ; Button mask
; Default values for above variables
.rodata
; (We use ".proc" because we want to define both a label and a scope.)
.proc DefVars
.word SCREEN_HEIGHT/2 ; YPos
.word SCREEN_WIDTH/2 ; XPos
.word 0 ; XMin
.word 0 ; YMin
.word SCREEN_WIDTH ; XMax
.word SCREEN_HEIGHT ; YMax
.byte 0 ; Buttons
.endproc
.code
;----------------------------------------------------------------------------
; INSTALL routine. Is called after the driver is loaded into memory. If
; possible, check if the hardware is present.
; Must return an MOUSE_ERR_xx code in a/x.
INSTALL:
; Initialize variables. Just copy the default stuff over
ldx #.sizeof(DefVars)-1
@L1: lda DefVars,x
sta Vars,x
dex
bpl @L1
; Make sure the mouse cursor is at the default location.
lda XPos
ldx XPos+1
jsr CMOVEX
lda YPos
ldx YPos+1
jsr CMOVEY
; Done, return zero (= MOUSE_ERR_OK)
ldx #$00
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 only called
; if the mouse is currently visible and should get hidden. For most drivers,
; no special action is required besides hiding the mouse cursor.
; No return code required.
HIDE: php
sei
jsr CHIDE
plp
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 only called
; if the mouse is currently hidden and should become visible. For most drivers,
; no special action is required besides enabling the mouse cursor.
; No return code required.
SHOW: php
sei
jsr CSHOW
plp
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 a/x.
; No checks are done if the mouse is currently inside the box, this 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
php
sei
@L1: lda (ptr1),y
sta XMin,y
dey
bpl @L1
plp
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 a/x.
GETBOX: sta ptr1
stx ptr1+1 ; Save data pointer
ldy #.sizeof (MOUSE_BOX)-1
php
sei
@L1: lda XMin,y
sta (ptr1),y
dey
bpl @L1
plp
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 a/x. 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: php
sei ; No interrupts
pha
txa
pha
jsr CPREP
pla
tax
pla
sta YPos
stx YPos+1 ; New Y position
jsr CMOVEY ; Set it
ldy #$01
lda (sp),y
sta XPos+1
tax
dey
lda (sp),y
sta XPos ; New X position
jsr CMOVEX ; Move the cursor
jsr CSHOW
plp ; Restore interrupt flag
rts
;----------------------------------------------------------------------------
; BUTTONS: Return the button mask in a/x.
BUTTONS:
lda Buttons
ldx #$00
rts
;----------------------------------------------------------------------------
; 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
php
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
plp ; Restore interrupt flag
iny
sta (ptr1),y ; Store last byte
rts ; Done
;----------------------------------------------------------------------------
; 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 will just
; call _mouse_pos to initialize the struct pointer and fill the position
; fields.
INFO: jsr POS
; Fill in the button state
lda Buttons
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 a/x.
;
IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now
ldx #>MOUSE_ERR_INV_IOCTL
rts
;----------------------------------------------------------------------------
; IRQ: Irq handler entry point. Called as a subroutine but in 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:
; Check for a pressed button and place the result into Buttons
ldx #0
stx Buttons
lda PORTA ; get other buttons
eor #255
tax
and #5 ; pen button and left button are mapped to left mouse button
beq @L01
lda #MOUSE_BTN_LEFT
ora Buttons
sta Buttons
@L01: txa
and #8
beq @L02
lda #MOUSE_BTN_RIGHT
ora Buttons
sta Buttons
; If we read 228 for X or Y positions, we assume the user has lifted the pen
; and don't change the cursor position.
@L02: lda PADDL0
cmp #228
beq @Cont ; CF set if equal
lda PADDL1
cmp #228 ; CF set if equal
@Cont: php ; remember CF
jsr CPREP
plp ; restore CF
bcc @L03
jmp @Show
@L03: ldx #0
stx XPos+1
stx YPos+1
; Get cursor position
; -------------------
; The touch pad is read thru the paddle potentiometers. The possible
; values are 1..228. Since the maximum value is less than the X
; dimension we have to "stretch" this value. In order to use only
; divisions by powers of two, we use the following appoximation:
; 320/227 = 1.4096
; 1+1/2-1/8+1/32 = 1.4062
; For Y we subtract 1/8 of it to get in the YMax ballpark.
; 228-228/8=199.5
; A small area in the Y dimension of the touchpad isn't used with
; this approximation. The Y value is inverted, (0,0) is the bottom
; left corner of the touchpad.
; X
ldx PADDL0 ; get X postion
dex ; decrement, since it's 1-based
stx XPos
txa
lsr a
tax
clc
adc XPos
sta XPos
bcc @L04
inc XPos+1
@L04: txa
lsr a ; port value / 4
lsr a ; port value / 8
tax
sec
lda XPos
stx XPos
sbc XPos
sta XPos
bcs @L05
dec XPos+1
@L05: txa
lsr a ; port value / 16
lsr a ; port value / 32
clc
adc XPos
sta XPos
bcc @L06
inc XPos+1
@L06: tay
lda XPos+1
tax
; Limit the X coordinate to the bounding box
cpy XMin
sbc XMin+1
bpl @L07
ldy XMin
ldx XMin+1
jmp @L08
@L07: txa
cpy XMax
sbc XMax+1
bmi @L08
ldy XMax
ldx XMax+1
@L08: sty XPos
stx XPos+1
; Move the mouse pointer to the new X pos
tya
jsr CMOVEX
; Y
ldx PADDL1 ; get Y postion
dex ; decrement, since it's 1-based
stx YPos
lda #228
sec
sbc YPos ; invert value
tax
lsr a
lsr a
lsr a
sta YPos
txa
sec
sbc YPos
sta YPos
tay
lda YPos+1
tax
; Limit the Y coordinate to the bounding box
cpy YMin
sbc YMin+1
bpl @L09
ldy YMin
ldx YMin+1
jmp @L10
@L09: txa
cpy YMax
sbc YMax+1
bmi @L10
ldy YMax
ldx YMax+1
@L10: sty YPos
stx YPos+1
; Move the mouse pointer to the new X pos
tya
jsr CMOVEY
@Show: jsr CDRAW
clc ; Interrupt not "handled"
rts

View File

@@ -1,576 +0,0 @@
;--------------------------------------------------------------------
; Atari 8-bit mouse routines -- 05/07/2000 Freddy Offenga
; Some changes by Christian Groessler, Ullrich von Bassewitz
;
; The following devices are supported:
; - Atari trak-ball
; - ST mouse
; - Amiga mouse
;
; Mouse checks are done in the timer 1 IRQ and the mouse arrow is
; drawn in player 0 during the vertical blank
;--------------------------------------------------------------------
.export _mouse_init, _mouse_done, _mouse_box
.export _mouse_show, _mouse_hide, _mouse_move
.export _mouse_buttons, _mouse_pos, _mouse_info
.constructor initmouse,27
.import popax
.importzp ptr1
.include "atari.inc"
TRAK_BALL = 0 ; device Atari trak-ball
ST_MOUSE = 1 ; device ST mouse
AMIGA_MOUSE = 2 ; device Amiga mouse
MAX_TYPE = 3 ; first illegal device type
; the default values force the mouse cursor inside the test screen (no access to border)
defxmin = 48 ; default x minimum
defymin = 31 ; default y minimum
defxmax = 204 ; default x maximum
defymax = 211 ; default y maximum
pmsize = 16 ; y size pm shape
xinit = defxmin ; init. x pos.
yinit = defymin ; init. y pos.
;--------------------------------------------------------------------
; reserve memory for the mouse pointer
initmouse:
lda APPMHI+1
and #%11111000 ; make 2k aligned
sec
sbc #%00001000 ; reserve 2k
tax
adc #3 ; add 4 (C = 1)
sta mouse_pm0
lda #0
sta APPMHI
stx APPMHI+1
rts
;--------------------------------------------------------------------
; Initialize mouse routines
; void __fastcall__ mouse_init (unsigned char type);
_mouse_init:
cmp #MAX_TYPE+1 ; Check for a valid type
bcc setup
ifail: lda #0 ; init. failed
tax
rts
setup: tax
lda lvectab,x
sta mouse_vec+1
lda hvectab,x
sta mouse_vec+2
jsr pminit
lda VTIMR1
sta old_t1
lda VTIMR1+1
sta old_t1+1
lda #<t1_vec
sta VTIMR1
lda #>t1_vec
sta VTIMR1+1
lda #%00000001
sta AUDCTL
lda #0
sta AUDC1
lda #15
sta AUDF1
sta STIMER
sei
lda POKMSK
ora #%00000001 ; timer 1 enable
sta POKMSK
sta IRQEN
cli
lda VVBLKI
sta vbi_jmp+1
lda VVBLKI+1
sta vbi_jmp+2
lda #6
ldy #<vbi
ldx #>vbi
jsr SETVBV
lda #$C0
sta NMIEN
ldx #0
lda #1
sta mouse_off
rts
;--------------------------------------------------------------------
; Finish mouse routines
; void mouse_done(void)
_mouse_done:
sei
lda POKMSK
and #%11111110 ; timer 1 disable
sta IRQEN
sta POKMSK
cli
lda old_t1
sta VTIMR1
lda old_t1+1
sta VTIMR1+1
lda #$40
sta NMIEN
lda #6
ldy vbi_jmp+1
ldx vbi_jmp+2
jsr SETVBV
ldx #0
stx GRACTL
stx HPOSP0
inx
stx mouse_off
rts
;--------------------------------------------------------------------
; Set mouse limits
; void __fastcall__ mouse_box(int xmin, int ymin, int xmax, int ymax)
_mouse_box:
sta ymax
jsr popax ; always ignore high byte
sta xmax
jsr popax
sta ymin
jsr popax
sta xmin
rts
;--------------------------------------------------------------------
; Set mouse position
; void __fastcall__ mouse_move(int xpos, int ypos)
_mouse_move:
sta mousey ; always ignore high byte
jsr popax
sta mousex
rts
;--------------------------------------------------------------------
; Show mouse arrow
; void mouse_show(void)
_mouse_show:
lda mouse_off ; Already on?
beq @L1
dec mouse_off
@L1: rts
;--------------------------------------------------------------------
; Hide mouse arrow
; void mouse_hide(void)
_mouse_hide:
inc mouse_off
rts
;--------------------------------------------------------------------
; Ask mouse button
; unsigned char mouse_buttons(void)
_mouse_buttons:
ldx #0
lda STRIG0
bne nobut
; lda #14
;??? sta COLOR1
lda #1
rts
nobut: txa
rts
;--------------------------------------------------------------------
; Get the mouse position
; void mouse_pos (struct mouse_pos* pos);
_mouse_pos:
sta ptr1
stx ptr1+1 ; Store argument pointer
ldy #0
lda mousex ; X position
sta (ptr1),y
lda #0
iny
sta (ptr1),y
lda mousey ; Y position
iny
sta (ptr1),y
lda #0
iny
sta (ptr1),y
rts
;--------------------------------------------------------------------
; Get the mouse position and button information
; void mouse_info (struct mouse_info* info);
_mouse_info:
; 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 will just
; call _mouse_pos to initialize the struct pointer and fill the position
; fields.
jsr _mouse_pos
; Fill in the button state
jsr _mouse_buttons ; Will not touch ptr1
ldy #4
sta (ptr1),y
rts
;--------------------------------------------------------------------
; Atari trak-ball check, A,Y = 4-bit port value
trak_check:
eor oldval
and #%00001000
beq horiz
tya
and #%00000100
beq mmup
inc mousey
bne horiz
mmup: dec mousey
horiz: tya
eor oldval
and #%00000010
beq mmexit
tya
and #%00000001
beq mmleft
inc mousex
bne mmexit
mmleft: dec mousex
mmexit: sty oldval
rts
;--------------------------------------------------------------------
; ST mouse check, A,Y = 4-bit port value
st_check:
and #%00000011
ora dumx
tax
lda sttab,x
bmi nxst
beq xist
dec mousex ; 1 = left
bne nxst
xist: inc mousex ; 0 = right
nxst: tya
and #%00001100
ora dumy
tax
lda sttab,x
bmi nyst
bne yst
dec mousey ; 0 = up
bne nyst
yst: inc mousey ; 1 = down
; store old readings
nyst: tya
and #%00000011
asl
asl
sta dumx
tya
and #%00001100
lsr
lsr
sta dumy
rts
;--------------------------------------------------------------------
; Amiga mouse check, A,Y = 4-bit port value
amiga_check:
lsr
and #%00000101
ora dumx
tax
lda amitab,x
bmi nxami
bne xiami
dec mousex ; 0 = left
bne nxami
xiami: inc mousex ; 1 = right
nxami: tya
and #%00000101
ora dumy
tax
lda amitab,x
bmi nyami
bne yiami
dec mousey ; 0 = up
bne nyami
yiami: inc mousey ; 1 = down
; store old readings
nyami: tya
and #%00001010
sta dumx
tya
and #%00000101
asl
sta dumy
rts
;--------------------------------------------------------------------
; timer 1 IRQ routine - check mouse
t1_vec: tya
pha
txa
pha
.ifdef DEBUG
lda RANDOM
sta COLBK ; debug
.endif
lda PORTA
tay
mouse_vec:
jsr st_check ; will be modified; won't be ROMmable
pla
tax
pla
tay
pla
rti
;--------------------------------------------------------------------
; VBI - check mouse limits and display mouse arrow
vbi: lda mousex
cmp xmin
bcs ok1 ; xmin <= mousex
lda xmin
sta mousex
ok1: lda mousey
cmp ymin
bcs ok2 ; ymin <= mousey
lda ymin
sta mousey
ok2: lda xmax
cmp mousex
bcs ok3 ; xmax >= mousex
lda xmax
sta mousex
ok3: lda ymax
cmp mousey
bcs ok4 ; ymax >= mousey
lda ymax
sta mousey
ok4: jsr clrpm
lda mouse_off
beq mon
lda #0
sta HPOSP0
beq moff
mon: jsr drwpm
lda mousey
sta omy
lda #3
moff: sta GRACTL
vbi_jmp:
jmp SYSVBV ; will be modified; won't be ROMmable
;--------------------------------------------------------------------
; initialize mouse pm
pminit: lda mouse_pm0
sta mpatch1+2
sta mpatch2+2
sta mpatch3+2
ldx #0
txa
mpatch1:
clpm: sta $1000,x ; will be patched
inx
bne clpm
lda mouse_pm0
sec
sbc #4
sta PMBASE
lda #62
sta SDMCTL
lda #1
sta GPRIOR
lda #0
sta PCOLR0
sta SIZEP0
rts
;--------------------------------------------------------------------
; draw new mouse pm
drwpm: lda mousex
sta HPOSP0
lda mousey
tax
ldy #0
fmp2: lda mskpm,y
mpatch2:
sta $1000,x ; will be patched
inx
iny
cpy #pmsize
bne fmp2
rts
;--------------------------------------------------------------------
; clear old mouse pm
clrpm: lda omy
tax
ldy #0
tya
mpatch3:
fmp1: sta $1000,x ; will be patched
inx
iny
cpy #pmsize
bne fmp1
rts
;--------------------------------------------------------------------
.rodata
; mouse arrow - pm shape
mskpm: .byte %00000000
.byte %10000000
.byte %11000000
.byte %11000000
.byte %11100000
.byte %11100000
.byte %11110000
.byte %11100000
.byte %11100000
.byte %00100000
.byte %00100000
.byte %00110000
.byte %00110000
.byte %00000000
.byte %00000000
.byte %00000000
; ST mouse lookup table
sttab: .byte $FF,$01,$00,$01
.byte $00,$FF,$00,$01
.byte $01,$00,$FF,$00
.byte $01,$00,$01,$FF
; Amiga mouse lookup table
amitab: .byte $FF,$01,$00,$FF
.byte $00,$FF,$FF,$01
.byte $01,$FF,$FF,$00
.byte $FF,$00,$01,$FF
; Device vectors
lvectab:
.byte <trak_check, <st_check, <amiga_check
hvectab:
.byte >trak_check, >st_check, >amiga_check
; default values
xmin: .byte defxmin
ymin: .byte defymin
xmax: .byte defxmax
ymax: .byte defymax
mousex: .byte xinit
mousey: .byte yinit
;--------------------------------------------------------------------
.bss
; Misc. vars
old_t1: .res 2 ; old timer interrupt vector
oldval: .res 1 ; used by trakball routines
dumx: .res 1
dumy: .res 1
omy: .res 1 ; old y pos
mouse_off:
.res 1
mouse_pm0:
.res 1

View File

@@ -0,0 +1,22 @@
;
; Address of the static standard mouse driver
;
; Christian Groessler, 2014-01-02
;
; const void mouse_static_stddrv[];
;
.export _mouse_static_stddrv
.ifdef __ATARIXL__
.import _atrxst_mou
.else
.import _atrst_mou
.endif
.rodata
.ifdef __ATARIXL__
_mouse_static_stddrv := _atrxst_mou
.else
_mouse_static_stddrv := _atrst_mou
.endif

View File

@@ -0,0 +1,18 @@
;
; Name of the standard mouse driver
;
; Christian Groessler, 2014-01-02
;
; const char mouse_stddrv[];
;
.export _mouse_stddrv
.rodata
_mouse_stddrv:
.ifdef __ATARIXL__
.asciiz "ATRXST.MOU"
.else
.asciiz "ATRST.MOU"
.endif

13
libsrc/atari/mouseref.s Normal file
View File

@@ -0,0 +1,13 @@
;
; Christian Groessler, 2014-04-22
;
.export mouse_libref
.ifdef __ATARIXL__
.import set_VTIMR1_handler
mouse_libref := set_VTIMR1_handler
.else
.import _exit
mouse_libref := _exit
.endif

View File

@@ -6,7 +6,7 @@
; uses tmp4
.importzp tmp4
.export mul40
.export mul40,loc_tmp
.proc mul40

View File

@@ -48,13 +48,13 @@ _inviocb:
.segment "EXTZP" : zeropage
index: .res 1 ; index into line buffer
buflen: .res 1 ; length of used part of buffer
cbs: .res 1 ; current buffer size: buflen - index
dataptr:.res 2 ; temp pointer to user buffer
copylen:.res 1 ; temp counter
.bss
buflen: .res 1 ; length of used part of buffer
linebuf:.res LINEBUF ; the line buffer
.code

View File

@@ -1,389 +0,0 @@
;
; Christian Groessler, Dec-2001
;
; RS232 routines using the R: device (currently tested with an 850 only)
;
; unsigned char __fastcall__ rs232_init (char hacked);
; unsigned char __fastcall__ rs232_params (unsigned char params, unsigned char parity);
; unsigned char __fastcall__ rs232_done (void);
; unsigned char __fastcall__ rs232_get (char* B);
; unsigned char __fastcall__ rs232_put (char B);
; unsigned char __fastcall__ rs232_pause (void); [TODO]
; unsigned char __fastcall__ rs232_unpause (void); [TODO]
; unsigned char __fastcall__ rs232_status (unsigned char* status,
; unsigned char* errors); [TODO]
;
.import findfreeiocb
.import __do_oserror
.import fddecusage
.import fdtoiocb
.import __inviocb
.import clriocb
.import newfd
.import _close, pushax, popax, popa
.importzp ptr1, tmp2, tmp3
.export _rs232_init, _rs232_params, _rs232_done, _rs232_get
.export _rs232_put, _rs232_pause, _rs232_unpause, _rs232_status
.include "atari.inc"
.include "errno.inc"
.include "rs232.inc"
.rodata
rdev: .byte "R:", ATEOL, 0
.bss
; receive buffer
RECVBUF_SZ = 256
recv_buf: .res RECVBUF_SZ
cm_run: .res 1 ; concurrent mode running?
.data
rshand: .word $ffff
.code
;----------------------------------------------------------------------------
;
; unsigned char __fastcall__ rs232_init (char hacked);
; /* Initialize the serial port. The parameter is ignored in the Atari version.
; * return 0/-1 for OK/Error
; */
;
.proc _rs232_init
jsr findfreeiocb
bne init_err
txa
tay ; move iocb # into Y
lda #3
sta tmp3 ; name length + 1
lda #<rdev
ldx #>rdev
jsr newfd
tya
bcs doopen ; C set: open needed / device not already open
pha
jsr _rs232_done ;** shut down if started @@@TODO check this out!!
pla
doopen: tax
pha
jsr clriocb
pla
tax
lda #<rdev
sta ICBAL,x
lda #>rdev
sta ICBAH,x
lda #OPEN
sta ICCOM,x
lda #$0D ; mode in+out+concurrent
sta ICAX1,x
lda #0
sta ICAX2,x
sta ICBLL,x ; zap buf len
sta ICBLH,x
jsr CIOV
bmi cioerr1
lda tmp2 ; get fd
sta rshand
ldx #0
stx rshand+1
txa
rts
cioerr1:jsr fddecusage ; decrement usage counter of fd as open failed
init_err:
ldx #0
lda #RS_ERR_INIT_FAILED
rts
.endproc ; _rs232_init
;----------------------------------------------------------------------------
;
; unsigned char __fastcall__ rs232_params (unsigned char params, unsigned char parity);
;
; Set communication parameters.
;
; params contains baud rate, stop bits and word size
; parity contains parity
;
; 850 manual documents restrictions on the baud rate (not > 300), when not
; using 8 bit word size. So only 8 bit is currently tested.
;
.proc _rs232_params
sta tmp2
lda rshand
cmp #$ff
bne work ; work only if initialized
lda #RS_ERR_NOT_INITIALIZED
bne done
work: lda rshand
ldx #0
jsr fdtoiocb ; get iocb index into X
bmi inverr ; shouldn't happen
tax
; set handshake lines
lda #34 ; xio 34, set cts, dtr etc
sta ICCOM,x
lda #192+48+3 ; DTR on, RTS on, XMT on
sta ICAX1,x
lda #0
sta ICBLL,x
sta ICBLH,x
sta ICBAL,x
sta ICBAH,x
sta ICAX2,x
jsr CIOV
bmi cioerr
; set baud rate, word size, stop bits and ready monitoring
lda #36 ; xio 36, baud rate
sta ICCOM,x
jsr popa ; get parameter
sta ICAX1,x
;ICAX2 = 0, monitor nothing
jsr CIOV
bmi cioerr
; set translation and parity
lda #38 ; xio 38, translation and parity
sta ICCOM,x
lda tmp2
ora #32 ; no translation
sta ICAX1,x
jsr CIOV
bmi cioerr
lda #0
done: ldx #0
rts
inverr: jmp __inviocb
.endproc ;_rs232_params
cioerr: jmp __do_oserror
;----------------------------------------------------------------------------
;
; unsigned char __fastcall__ rs232_done (void);
; /* Close the port, deinstall the interrupt hander. You MUST call this function
; * before terminating the program, otherwise the machine may crash later. If
; * in doubt, install an exit handler using atexit(). The function will do
; * nothing, if it was already called.
; */
;
.proc _rs232_done
lda rshand
cmp #$ff
beq done
work: ldx rshand+1
jsr pushax
jsr _close
pha
txa
pha
ldx #$ff
stx rshand
stx rshand+1
inx
stx cm_run
pla
tax
pla
done: rts
.endproc ;rs232_done
;----------------------------------------------------------------------------
;
; unsigned char __fastcall__ rs232_get (char* B);
; /* Get a character from the serial port. If no characters are available, the
; * function will return RS_ERR_NO_DATA, so this is not a fatal error.
; */
;
.proc _rs232_get
ldy rshand
cpy #$ff
bne work ; work only if initialized
lda #RS_ERR_NOT_INITIALIZED
bne nierr
work: sta ptr1
stx ptr1+1 ; store pointer to received char
lda rshand
ldx #0
jsr fdtoiocb
tax
lda cm_run ; concurrent mode already running?
bne go
jsr ena_cm ; turn on concurrent mode
go: ; check whether there is any input available
lda #STATIS ; status request, returns bytes pending
sta ICCOM,x
jsr CIOV
bmi cioerr ; @@@ error handling
lda DVSTAT+1 ; get byte count pending
ora DVSTAT+2
beq nix_da ; no input waiting...
; input is available: get it!
lda #GETCHR ; get raw bytes
sta ICCOM,x ; in command code
lda #0
sta ICBLL,x
sta ICBLH,x
sta ICBAL,x
sta ICBAH,x
jsr CIOV ; go get it
bmi cioerr ; @@@ error handling
ldx #0
sta (ptr1,x) ; return received byte
txa
rts
nierr: ldx #0
rts
nix_da: lda #RS_ERR_NO_DATA
ldx #0
rts
.endproc ;_rs232_get
;----------------------------------------------------------------------------
;
; unsigned char __fastcall__ rs232_put (char B);
; /* Send a character via the serial port. There is a transmit buffer, but
; * transmitting is not done via interrupt. The function returns
; * RS_ERR_OVERFLOW if there is no space left in the transmit buffer.
; */
;
.proc _rs232_put
ldy rshand
cpy #$ff
bne work ; work only if initialized
lda #RS_ERR_NOT_INITIALIZED
bne nierr
work: pha
lda rshand
ldx #0
jsr fdtoiocb
tax
lda cm_run ; concurrent mode already running?
bne go
jsr ena_cm ; turn on concurrent mode
; @@@TODO: check output buffer overflow
go: lda #PUTCHR ; put raw bytes
sta ICCOM,x ; in command code
lda #0
sta ICBLL,x
sta ICBLH,x
sta ICBAL,x
sta ICBAH,x
pla ; get the char back
jsr CIOV ; go do it
rts
nierr: ldx #0
rts
.endproc ;_rs232_put
;----------------------------------------------------------------------------
;
; unsigned char __fastcall__ rs232_pause (void);
; /* Assert flow control and disable interrupts. */
;
_rs232_pause:
;----------------------------------------------------------------------------
;
; unsigned char __fastcall__ rs232_unpause (void);
; /* Re-enable interrupts and release flow control */
;
_rs232_unpause:
;----------------------------------------------------------------------------
;
; unsigned char __fastcall__ rs232_status (unsigned char* status,
; unsigned char* errors);
; /* Return the serial port status. */
;
_rs232_status:
lda #255
tax
rts
; enable concurrent rs232 mode
; gets iocb index in X
; all registers destroyed
.proc ena_cm
lda #40 ; XIO 40, start concurrent IO
sta ICCOM,x
sta cm_run ; indicate concurrent mode is running
lda #0
sta ICAX1,x
sta ICAX2,x
lda #<recv_buf
sta ICBAL,x
lda #>recv_buf
sta ICBAH,x
lda #<RECVBUF_SZ
sta ICBLL,x
lda #>RECVBUF_SZ
sta ICBLH,x
lda #$0D ; value from 850 man, p62. must be 0D?,
sta ICAX1,x ; or any non-zero?
jmp CIOV
.endproc ;ena_cm
.end

585
libsrc/atari/ser/atrrdev.s Normal file
View File

@@ -0,0 +1,585 @@
;
; Christian Groessler, Dec-2001
; converted to driver interface Dec-2013
;
; RS232 routines using the R: device (currently tested with an 850 only)
;
.include "zeropage.inc"
.include "ser-kernel.inc"
.include "ser-error.inc"
.include "atari.inc"
.macpack module
; ------------------------------------------------------------------------
; Header. Includes jump table
.ifdef __ATARIXL__
module_header _atrxrdev_ser
.else
module_header _atrrdev_ser
.endif
; Driver signature
.byte $73, $65, $72 ; "ser"
.byte SER_API_VERSION ; Serial API version number
; Library reference
libref: .addr $0000
; Jump table
.word SER_INSTALL
.word SER_UNINSTALL
.word SER_OPEN
.word SER_CLOSE
.word SER_GET
.word SER_PUT
.word SER_STATUS
.word SER_IOCTL
.word SER_IRQ
.rodata
rdev: .byte "R:", ATEOL, 0
bauds: .byte 1 ; SER_BAUD_45_5
.byte 2 ; SER_BAUD_50
.byte 4 ; SER_BAUD_75
.byte 5 ; SER_BAUD_110
.byte 6 ; SER_BAUD_134_5
.byte 7 ; SER_BAUD_150
.byte 8 ; SER_BAUD_300
.byte 9 ; SER_BAUD_600
.byte 10 ; SER_BAUD_1200
.byte 11 ; SER_BAUD_1800
.byte 12 ; SER_BAUD_2400
.byte 0 ; SER_BAUD_3600
.byte 13 ; SER_BAUD_4800
.byte 0 ; SER_BAUD_7200
.byte 14 ; SER_BAUD_9600
.byte 0 ; SER_BAUD_19200
.byte 0 ; SER_BAUD_38400
.byte 0 ; SER_BAUD_57600
.byte 0 ; SER_BAUD_115200
.byte 0 ; SER_BAUD_230400
.byte 0 ; SER_BAUD_31250
.byte 0 ; SER_BAUD_62500
.byte 3 ; SER_BAUD_56_875
num_bauds = * - bauds
databits:
.byte 48 ; SER_BITS_5
.byte 32 ; SER_BITS_6
.byte 16 ; SER_BITS_7
.byte 0 ; SER_BITS_8
num_databits = * - databits
parities:
.byte 0 ; SER_PAR_NONE
.byte 4+1 ; SER_PAR_ODD
.byte 2+8 ; SER_PAR_EVEN
;.byte 0 ; SER_PAR_MARK
;.byte 0 ; SER_PAR_SPACE
num_parities = * - parities
.bss
; receive buffer
RECVBUF_SZ = 256
recv_buf: .res RECVBUF_SZ
cm_run: .res 1 ; concurrent mode running?
.data
rshand: .word $ffff
; jump table into main program, initialized from libref
my_newfd:
.byte $4C
.word 0
my__close:
.byte $4C
.word 0
my_pushax:
.byte $4C
.word 0
my_popax:
.byte $4C
.word 0
my_findfreeiocb:
.byte $4C
.word 0
my___do_oserror:
.byte $4C
.word 0
my_fddecusage:
.byte $4C
.word 0
my_fdtoiocb:
.byte $4C
.word 0
my___inviocb:
.byte $4C
.word 0
my_clriocb:
.byte $4C
.word 0
my_CIOV:
.byte $4C
.word 0
.code
invbaud:
lda #<SER_ERR_BAUD_UNAVAIL
ldx #>SER_ERR_BAUD_UNAVAIL
openerr:
rts
;----------------------------------------------------------------------------
; SER_OPEN: A pointer to a ser_params structure is passed in ptr1.
; Must return an SER_ERR_xx code in a/x.
SER_OPEN:
jsr do_open
bne openerr
; set line parameters
lda rshand
ldx #0
jsr my_fdtoiocb ; get iocb index into X
bmi openerr ; shouldn't happen
tax
; set baud rate, word size, stop bits and ready monitoring
; build ICAX1 value
ldy #SER_PARAMS::BAUDRATE
lda (ptr1),y
cmp #num_bauds
bcs invbaud
tay
lda bauds,y
beq invbaud
sta ICAX1,x
ldy #SER_PARAMS::DATABITS
lda (ptr1),y
cmp #num_databits
bcs init_err
tay
lda databits,y
ora ICAX1,x
sta ICAX1,x
ldy #SER_PARAMS::STOPBITS
lda (ptr1),y
clc
ror a
ror a
ora ICAX1,x
sta ICAX1,x
lda #36 ; xio 36, baud rate
sta ICCOM,x
lda #0
;ICAX2 = 0, monitor nothing
sta ICAX2,x
sta ICBLL,x
sta ICBLH,x
sta ICBAL,x
sta ICBAH,x
jsr my_CIOV
bmi cioerr
; check if the handshake setting is valid
ldy #SER_PARAMS::HANDSHAKE
lda (ptr1),y
cmp #SER_HS_HW ; this is all we support
bne init_err
; set handshake lines
lda #34 ; xio 34, set cts, dtr etc
sta ICCOM,x
lda #192+48+3 ; DTR on, RTS on, XMT on
sta ICAX1,x
jsr my_CIOV
bmi cioerr
; set translation and parity
ldy #SER_PARAMS::PARITY
lda (ptr1),y
cmp #num_parities
bcs init_err
tay
lda parities,y
ora #32 ; no translation
sta ICAX1,x
lda #38 ; xio 38, translation and parity
sta ICCOM,x
jsr my_CIOV
bmi cioerr
lda #<SER_ERR_OK
tax ; A is zero
rts
inverr: jmp my___inviocb
cioerr:
; @@@ need to close IOCB here
jsr my_fddecusage ; decrement usage counter of fd as open failed
init_err:
ldx #0
lda #SER_ERR_INIT_FAILED
rts
;---- open the device
do_open:
jsr my_findfreeiocb
bne init_err
txa
tay ; move iocb # into Y
lda #3
sta tmp3 ; name length + 1
lda #<rdev
ldx #>rdev
jsr my_newfd
tya
bcs @doopen ; C set: open needed / device not already open
pha
jsr SER_CLOSE ;** shut down if started @@@TODO check this out!!
pla
@doopen:tax
pha
jsr my_clriocb
pla
tax
lda #<rdev
sta ICBAL,x
lda #>rdev
sta ICBAH,x
lda #OPEN
sta ICCOM,x
lda #$0D ; mode in+out+concurrent
sta ICAX1,x
lda #0
sta ICAX2,x
sta ICBLL,x ; zap buf len
sta ICBLH,x
jsr my_CIOV
bmi cioerr
lda tmp2 ; get fd (from newfd)
sta rshand
ldx #0
stx rshand+1
txa
rts
;----------------------------------------------------------------------------
; CLOSE: Close the port, disable interrupts and flush the buffer. Called
; without parameters. Must return an error code in a/x.
;
;----------------------------------------------------------------------------
; SER_UNINSTALL routine. Is called before the driver is removed from memory.
; Must return an SER_ERR_xx code in a/x.
;
SER_UNINSTALL:
SER_CLOSE:
lda rshand
cmp #$ff
beq @done
ldx rshand+1
jsr my__close
ldx #$ff
stx rshand
stx rshand+1
inx
stx cm_run
@done: lda #<SER_ERR_OK
ldx #>SER_ERR_OK
rts
;----------------------------------------------------------------------------
; SER_GET: Will fetch a character from the receive buffer and store it into the
; variable pointer to by ptr1. If no data is available, SER_ERR_NO_DATA is
; return.
;
SER_GET:
ldy rshand
cpy #$ff
beq ni_err ; work only if initialized
lda rshand
ldx #0
jsr my_fdtoiocb
tax
lda cm_run ; concurrent mode already running?
bne @go
jsr ena_cm ; turn on concurrent mode
@go: ; check whether there is any input available
lda #STATIS ; status request, returns bytes pending
sta ICCOM,x
jsr my_CIOV
bmi ser_error
lda DVSTAT+1 ; get byte count pending
ora DVSTAT+2
beq @nix_da ; no input waiting...
; input is available: get it!
lda #GETCHR ; get raw bytes
sta ICCOM,x ; in command code
lda #0
sta ICBLL,x
sta ICBLH,x
sta ICBAL,x
sta ICBAH,x
jsr my_CIOV ; go get it
bmi ser_error
ldx #0
sta (ptr1,x) ; return received byte
txa
rts
@nix_da:lda #SER_ERR_NO_DATA
ldx #0
rts
ser_error:
lda #SER_ERR_OVERFLOW ; there is no large selection of serial error codes... :-/
ldx #0
rts
ni_err: lda #SER_ERR_NOT_OPEN
ldx #0
rts
;----------------------------------------------------------------------------
; SER_PUT: Output character in A.
; Must return an error code in a/x.
;
SER_PUT:
ldy rshand
cpy #$ff
beq ni_err ; work only if initialized
pha ; remember char to write
lda rshand
ldx #0
jsr my_fdtoiocb
tax
lda cm_run ; concurrent mode already running?
bne @go
jsr ena_cm ; turn on concurrent mode
; @@@TODO: check output buffer overflow
@go: lda #PUTCHR ; put raw bytes
sta ICCOM,x ; in command code
lda #0
sta ICBLL,x
sta ICBLH,x
sta ICBAL,x
sta ICBAH,x
pla ; get the char back
jsr my_CIOV ; go do it
bmi ser_error
lda #0
tax
rts
;----------------------------------------------------------------------------
; SER_STATUS: Return the status in the variable pointed to by ptr1.
; Must return an error code in a/x.
;
SER_STATUS:
; fall through to SER_IOCTL
;----------------------------------------------------------------------------
; SER_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 a/x.
;
SER_IOCTL:
lda #<SER_ERR_INV_IOCTL ; We don't support ioclts for now
ldx #>SER_ERR_INV_IOCTL
rts
;----------------------------------------------------------------------------
; SER_IRQ: Not used on the Atari
;
SER_IRQ = $0000
;----------------------------------------------------------------------------
; SER_INSTALL routine. Is called after the driver is loaded into memory. If
; possible, check if the hardware is present.
; Must return an SER_ERR_xx code in a/x.
SER_INSTALL:
; check if R: device is installed
ldy #0
search: lda HATABS,y ; get device name
cmp #'R'
beq found
iny
iny
iny
cpy #MAXDEV
bcc search
; R: device not found, return error
lda #<SER_ERR_NO_DEVICE
ldx #0
rts
; R: device found, initialize jump table into main program
found: lda ptr3
pha
lda ptr3+1
pha
lda libref
sta ptr3
lda libref+1
sta ptr3+1
ldy #0
lda (ptr3),y
sta my_newfd+1
iny
lda (ptr3),y
sta my_newfd+2
iny
lda (ptr3),y
sta my__close+1
iny
lda (ptr3),y
sta my__close+2
iny
lda (ptr3),y
sta my_pushax+1
iny
lda (ptr3),y
sta my_pushax+2
iny
lda (ptr3),y
sta my_popax+1
iny
lda (ptr3),y
sta my_popax+2
iny
lda (ptr3),y
sta my_findfreeiocb+1
iny
lda (ptr3),y
sta my_findfreeiocb+2
iny
lda (ptr3),y
sta my___do_oserror+1
iny
lda (ptr3),y
sta my___do_oserror+2
iny
lda (ptr3),y
sta my_fddecusage+1
iny
lda (ptr3),y
sta my_fddecusage+2
iny
lda (ptr3),y
sta my_fdtoiocb+1
iny
lda (ptr3),y
sta my_fdtoiocb+2
iny
lda (ptr3),y
sta my___inviocb+1
iny
lda (ptr3),y
sta my___inviocb+2
iny
lda (ptr3),y
sta my_clriocb+1
iny
lda (ptr3),y
sta my_clriocb+2
iny
lda (ptr3),y
sta my_CIOV+1
iny
lda (ptr3),y
sta my_CIOV+2
;iny
pla
sta ptr3+1
pla
sta ptr3
lda #<SER_ERR_OK
tax ; A is zero
rts
; enable concurrent rs232 mode
; gets iocb index in X
; all registers destroyed
.proc ena_cm
lda #40 ; XIO 40, start concurrent IO
sta ICCOM,x
sta cm_run ; indicate concurrent mode is running
lda #$0D ; value from 850 manual, p62. must be $0D?,
sta ICAX1,x ; or any non-zero?
lda #0
sta ICAX2,x
lda #<recv_buf
sta ICBAL,x
lda #>recv_buf
sta ICBAH,x
lda #<RECVBUF_SZ
sta ICBLL,x
lda #>RECVBUF_SZ
sta ICBLH,x
jmp my_CIOV
.endproc ;ena_cm

33
libsrc/atari/serref.s Normal file
View File

@@ -0,0 +1,33 @@
;
; Christian Groessler, 2014-04-22
;
.include "atari.inc"
.export ser_libref
.import _close, pushax, popax
.import findfreeiocb
.import __do_oserror
.import fddecusage
.import fdtoiocb
.import __inviocb
.import clriocb
.import newfd
ser_libref := atari_ser_libref
.rodata
atari_ser_libref:
.word newfd
.word _close
.word pushax
.word popax
.word findfreeiocb
.word __do_oserror
.word fddecusage
.word fdtoiocb
.word __inviocb
.word clriocb
.word CIOV

View File

@@ -0,0 +1,81 @@
;
; Atari XL shadow RAM timer IRQ #1 handler
;
; Christian Groessler, chris@groessler.org, 2014
;
;DEBUG = 1
.ifdef __ATARIXL__
SHRAM_HANDLERS = 1
.include "atari.inc"
.include "romswitch.inc"
.export set_VTIMR1_handler
.segment "LOWBSS"
VTIMR1_handler: .res 3
.segment "BSS"
old_VTIMR1_handler:
.res 2
.segment "LOWCODE"
; timer interrupt handler:
; disable ROM, call user handler, enable ROM again
my_VTIMR1_handler:
disable_rom_quick
jsr VTIMR1_handler
enable_rom_quick
pla
rti
.segment "CODE"
; install or remove VTIMR1 handler
; input: CF - 0/1 for remove/install handler
; AX - pointer to handler (if CF=1)
; registers destroyed
set_VTIMR1_handler:
bcc @remove
; install vector
stx VTIMR1_handler+2
sta VTIMR1_handler+1 ; save passed vector in low memory
lda #$4C ; "JMP" opcode
sta VTIMR1_handler
lda VTIMR1
sta old_VTIMR1_handler
lda VTIMR1+1
sta old_VTIMR1_handler+1
lda #<my_VTIMR1_handler
php
sei
sta VTIMR1
lda #>my_VTIMR1_handler
sta VTIMR1+1
plp
rts
@remove: php
sei
lda old_VTIMR1_handler
sta VTIMR1
lda old_VTIMR1_handler+1
sta VTIMR1+1
plp
rts
.endif ; .ifdef __ATARIXL__

View File

@@ -45,13 +45,7 @@ iocbok: stx tmp4 ; remember IOCB index
ldy #0
sty sspc+1 ; initialize stack space
.ifndef UCASE_FILENAME
sta ptr3
stx ptr3+1
sty sspc
.else
.ifdef UCASE_FILENAME
; uppercase first (old) name and prepend device if needed
@@ -100,6 +94,12 @@ ucok2: sta ptr2 ; remember pointer to uppercased new name
inc sspc+1
ukok4:
.else
sta ptr3
stx ptr3+1
sty sspc
.endif
; create a string on the stack with the old filename and the new filename separated by an invalid character (space in our case)

View File

@@ -194,7 +194,7 @@ delay1: ldx #0
end:
.ifndef __ATARIXL__
tmp: ; outside of the load chunk, some kind of poor man's .bss
tmp: ; outside of the load chunk, some kind of poor man's .bss
.endif
; ------------------------------------------------------------------------

View File

@@ -3,10 +3,10 @@
;
; time_t _systime (void);
; /* Similar to time(), but:
; * - Is not ISO C
; * - Does not take the additional pointer
; * - Does not set errno when returning -1
; */
; ** - Is not ISO C
; ** - Does not take the additional pointer
; ** - Does not set errno when returning -1
; */
;
.export __systime

View File

@@ -0,0 +1,9 @@
DEPS += ../libwrk/$(TARGET)/w2cas.d
../libwrk/$(TARGET)/w2cas.o: $(SRCDIR)/targetutil/w2cas.c | ../libwrk/$(TARGET)
$(COMPILE_recipe)
../targetutil/w2cas.com: ../libwrk/$(TARGET)/w2cas.o ../lib/$(TARGET).lib | ../targetutil
$(LD65) -o $@ -t $(TARGET) $^
$(TARGET): ../targetutil/w2cas.com

View File

@@ -0,0 +1,186 @@
/* w2cas.c -- write file to cassette
**
** This program writes a boot file (typically linked with
** 'atari-cassette.cfg') to the cassette.
** Only files < 32K are supported, since the loading of
** larger files requires a special loader inside the program.
**
** Christian Groessler, chris@groessler.org, 2014
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <6502.h>
#include <atari.h>
#include <conio.h>
static int verbose = 1;
static char C_dev[] = "C:";
static struct __iocb *findfreeiocb(void)
{
struct __iocb *iocb = &IOCB; /* first IOCB (#0) */
int i;
for (i = 0; i < 8; i++) {
if (iocb->handler == 0xff)
return iocb;
iocb++;
}
return NULL;
}
int main(int argc, char **argv)
{
char *filename, *x;
char buf[20];
FILE *file;
unsigned char *buffer;
size_t filen, buflen = 32768l + 1;
struct regs regs;
struct __iocb *iocb = findfreeiocb();
int iocb_num;
if (! iocb) {
fprintf(stderr, "couldn't find a free iocb\n");
if (_dos_type != 1)
cgetc();
return 1;
}
iocb_num = (iocb - &IOCB) * 16;
if (verbose)
printf("using iocb index $%02X ($%04X)\n", iocb_num, iocb);
if (argc < 2) {
printf("\nfilename: ");
x = fgets(buf, 19, stdin);
printf("\n");
if (! x)
return 1;
if (*x && *(x + strlen(x) - 1) == '\n')
*(x + strlen(x) - 1) = 0;
filename = x;
}
else {
filename = *(argv+1);
}
/* allocate buffer */
buffer = malloc(buflen);
if (! buffer) {
buflen = _heapmaxavail(); /* get as much as we can */
buffer = malloc(buflen);
if (! buffer) {
fprintf(stderr, "cannot alloc %ld bytes -- aborting...\n", (long)buflen);
if (_dos_type != 1)
cgetc();
return 1;
}
}
if (verbose)
printf("buffer size: %ld bytes\n", (long)buflen);
/* open file */
file = fopen(filename, "rb");
if (! file) {
free(buffer);
fprintf(stderr, "cannot open '%s': %s\n", filename, strerror(errno));
if (_dos_type != 1)
cgetc();
return 1;
}
/* read file -- file length must be < 32K */
if (verbose)
printf("reading input file...\n");
filen = fread(buffer, 1, buflen, file);
if (! filen) {
fprintf(stderr, "read error\n");
file_err:
fclose(file);
free(buffer);
if (_dos_type != 1)
cgetc();
return 1;
}
if (filen > 32767l) {
fprintf(stderr, "file is too large (must be < 32768)\n");
goto file_err;
}
if (filen == buflen) { /* we have a buffer < 32768 and the file fits into it (and is most probably larger) */
fprintf(stderr, "not enough memory\n");
goto file_err;
}
if (verbose)
printf("file size: %ld bytes\n", (long)filen);
/* close input file */
fclose(file);
/* open cassette */
if (verbose)
printf("opening cassette...\n");
iocb->buffer = C_dev;
iocb->aux1 = 8; /* open for output */
iocb->aux2 = 128; /* short breaks and no stop between data blocks */
iocb->command = IOCB_OPEN;
regs.x = iocb_num;
regs.pc = 0xe456; /* CIOV */
_sys(&regs);
if (regs.y != 1) {
fprintf(stderr, "CIO call to open cassette returned %d\n", regs.y);
free(buffer);
if (_dos_type != 1)
cgetc();
return 1;
}
/* write file */
if (verbose)
printf("writing to cassette...\n");
iocb->buffer = buffer;
iocb->buflen = filen;
iocb->command = IOCB_PUTCHR;
regs.x = iocb_num;
regs.pc = 0xe456; /* CIOV */
_sys(&regs);
if (regs.y != 1) {
fprintf(stderr, "CIO call to write file returned %d\n", regs.y);
free(buffer);
iocb->command = IOCB_CLOSE;
regs.x = iocb_num;
regs.pc = 0xe456; /* CIOV */
_sys(&regs);
if (_dos_type != 1)
cgetc();
return 1;
}
/* free buffer */
free(buffer);
/* close cassette */
iocb->command = IOCB_CLOSE;
regs.x = iocb_num;
regs.pc = 0xe456; /* CIOV */
_sys(&regs);
if (regs.y != 1) {
fprintf(stderr, "CIO call to close cassette returned %d\n", regs.y);
if (_dos_type != 1)
cgetc();
return 1;
}
/* all is fine */
printf("success\n");
if (_dos_type != 1)
cgetc();
return 0;
}

View File

@@ -3,6 +3,7 @@
;
.macpack longbranch
.macpack module
.ifdef __ATARIXL__
CIO_vec := my_CIOV
@@ -18,7 +19,19 @@
;
; ----------------------------------------------------------------------
.segment "JUMPTABLE"
.ifdef __ATARIXL__
.define LABEL_X "x"
.else
.define LABEL_X ""
.endif
.if pages = 2
.define LABEL_P2 "p2"
.else
.define LABEL_P2 ""
.endif
module_header .ident (.sprintf ("_atr%s%d%s_tgi", LABEL_X, ::grmode, LABEL_P2))
; Header

View File

@@ -7,8 +7,16 @@
;
.export _tgi_static_stddrv
.ifdef __ATARIXL__
.import _atrx8_tgi
.else
.import _atr8_tgi
.endif
.rodata
.ifdef __ATARIXL__
_tgi_static_stddrv := _atrx8_tgi
.else
_tgi_static_stddrv := _atr8_tgi
.endif

View File

@@ -10,4 +10,9 @@
.rodata
_tgi_stddrv: .asciiz "atr8.tgi"
_tgi_stddrv:
.ifdef __ATARIXL__
.asciiz "atrx8.tgi"
.else
.asciiz "atr8.tgi"
.endif

View File

@@ -0,0 +1,13 @@
; Cartridge entry point
;
; Christian Groessler, 01-Mar-2014
.export __CART_ENTRY__: absolute = 1
.import __CARTSIZE__, start
.forceimport __CART_YEAR__, __CART_NAME__
.segment "CARTENTRY"
.word start ; entry point
.assert (__CARTSIZE__ = $4000 || __CARTSIZE__ = $8000), error, "Cartridge size must either be $4000 or $8000"

View File

@@ -0,0 +1,13 @@
; default cartridge name
;
; Christian Groessler, 01-Mar-2014
.include "atari.mac"
.export __CART_NAME__: absolute = 1
.segment "CARTNAME"
scrcode " cc"
.byte '6' + 32, '5' + 32 ; use playfield 1
scrcode " compiled"

View File

@@ -0,0 +1,9 @@
; Cartridge copyright year
;
; Christian Groessler, 01-Mar-2014
.export __CART_YEAR__: absolute = 1
.segment "CARTYEAR"
.byte '9' + 32,'8' + 32 ; "98", but using playfield 1

View File

@@ -0,0 +1 @@
.include "../atari/cclear.s"

View File

@@ -0,0 +1 @@
.include "../atari/chline.s"

26
libsrc/atari5200/clock.s Normal file
View File

@@ -0,0 +1,26 @@
;
; from Atari computer version by Christian Groessler, 2014
;
; clock_t clock (void);
; unsigned _clocks_per_sec (void);
;
.export _clock
.importzp sreg
.include "atari5200.inc"
.proc _clock
ldx #5 ; Synchronize with Antic, so the interrupt won't change RTCLOK
stx WSYNC ; while we're reading it. The synchronization is done same as
@L1: dex ; in SETVBLV function in Atari OS.
bne @L1
stx sreg+1 ; Byte 3 is always zero
stx sreg ; Byte 2 is always zero, too
lda RTCLOK+1
ldx RTCLOK
rts
.endproc

34
libsrc/atari5200/clrscr.s Normal file
View File

@@ -0,0 +1,34 @@
;
; Christian Groessler, May-2014
;
; void clrscr (void);
;
.export _clrscr
.include "atari5200.inc"
.importzp ptr1
SCRSIZE = 480 ; 20x24: size of default conio atari5200 screen
_clrscr:lda SAVMSC ; screen memory
sta ptr1
lda SAVMSC+1
clc
adc #>(SCRSIZE-1)
sta ptr1+1
lda #0 ; screen code of space char
ldy #<(SCRSIZE-1)
ldx #>(SCRSIZE-1)
_clr1: sta (ptr1),y
dey
bne _clr1
sta (ptr1),y
dex
bmi done
dec ptr1+1
dey
jmp _clr1
done: sta COLCRS_5200
sta ROWCRS_5200
rts

View File

@@ -0,0 +1,83 @@
; setup default CONIO screen (20x24, Antic mode 6, BASIC mode 1)
;
; 28-May-2014, Christian Groessler <chris@groessler.org>
.include "atari5200.inc"
SCREEN_BUF_SIZE = 20 * 24
SCREEN_BUF = $4000 - SCREEN_BUF_SIZE
.code
.export screen_setup_20x24
screen_setup_20x24:
; initialize SAVMSC
lda #<SCREEN_BUF
sta SAVMSC
lda #>SCREEN_BUF
sta SAVMSC+1
; initialize cursor position
lda #0
sta COLCRS_5200
sta ROWCRS_5200
; clear screen buffer
ldy #<(SCREEN_BUF_SIZE-1)
ldx #>(SCREEN_BUF_SIZE-1)
clrscr: sta (SAVMSC),y
dey
cpy #$FF
bne clrscr
dex
cpx #$FF
bne clrscr
; set default colors
lda #40
sta COLOR0
lda #202
sta COLOR1
lda #148
sta COLOR2
lda #70
sta COLOR3
lda #0
sta COLOR4
; set display list
lda #<dlist
sta SDLSTL
lda #>dlist
sta SDLSTH
rts
.segment "RODATA"
; display list for 20x24 text mode
dlist: .repeat 3
.byte DL_BLK8
.endrepeat
.byte DL_CHR20x8x2 | DL_LMS
.word SCREEN_BUF
.repeat 23
.byte DL_CHR20x8x2
.endrepeat
.byte DL_JVB
.word dlist
; end of display list
.assert ((* >> 10) = (dlist >> 10)), error, "Display list crosses 1K boundary"
.end

94
libsrc/atari5200/cputc.s Normal file
View File

@@ -0,0 +1,94 @@
;
; adapted from Atari version
; Christian Groessler, 2014
;
; void cputcxy (unsigned char x, unsigned char y, char c);
; void cputc (char c);
;
.include "atari5200.inc"
.export _cputcxy, _cputc
.export plot, cputdirect, putchar
.import popa, _gotoxy, mul20
.importzp ptr4
.import setcursor
.constructor screen_setup, 26
.import screen_setup_20x24
screen_setup = screen_setup_20x24
_cputcxy:
pha ; Save C
jsr popa ; Get Y
jsr _gotoxy ; Set cursor, drop x
pla ; Restore C
_cputc:
cmp #$0D ; CR
bne L4
lda #0
sta COLCRS_5200
beq plot ; return
L4: cmp #$0A ; LF
beq newline
cmp #ATEOL ; Atari-EOL?
beq newline
tay
rol a
rol a
rol a
rol a
and #3
tax
tya
and #$9f
ora ataint,x
cputdirect: ; accepts screen code
jsr putchar
; advance cursor
inc COLCRS_5200
lda COLCRS_5200
cmp #20
bcc plot
lda #0
sta COLCRS_5200
.export newline
newline:
inc ROWCRS_5200
lda ROWCRS_5200
cmp #24
bne plot
lda #0
sta ROWCRS_5200
plot: jsr setcursor
ldy COLCRS_5200
ldx ROWCRS_5200
rts
putchar:
pha ; save char
lda ROWCRS_5200
jsr mul20 ; destroys tmp4
clc
adc SAVMSC ; add start of screen memory
sta ptr4
txa
adc SAVMSC+1
sta ptr4+1
pla ; get char again
ldy COLCRS_5200
sta (ptr4),y
jmp setcursor
.rodata
ataint: .byte 64,0,32,96

48
libsrc/atari5200/crt0.s Normal file
View File

@@ -0,0 +1,48 @@
;
; Startup code for cc65 (Atari5200 version)
;
; Christian Groessler (chris@groessler.org), 2014
;
.export _exit, start
.export __STARTUP__ : absolute = 1 ; Mark as startup
.import __RAM_START__, __RAM_SIZE__
.import __RESERVED_MEMORY__
.import initlib, donelib, callmain
.import zerobss, copydata
.include "zeropage.inc"
.include "atari5200.inc"
start:
; Clear the BSS data.
jsr zerobss
; Initialize the data.
jsr copydata
; Set up the stack.
lda #<(__RAM_START__ + __RAM_SIZE__ - __RESERVED_MEMORY__)
sta sp
lda #>(__RAM_START__ + __RAM_SIZE__ - __RESERVED_MEMORY__)
sta sp+1 ; Set argument stack ptr
; Call the module constructors.
jsr initlib
; Push the command-line arguments; and, call main().
jsr callmain
; Call the module destructors. This is also the exit() entry.
_exit: jsr donelib ; Run module destructors
; A 5200 program isn't supposed to exit.
halt: jmp halt

5
libsrc/atari5200/ctype.s Normal file
View File

@@ -0,0 +1,5 @@
; Character specification table.
;
; same as for "atari" target
.include "../atari/ctype.s"

View File

@@ -0,0 +1 @@
.include "../atari/cvline.s"

20
libsrc/atari5200/get_tv.s Normal file
View File

@@ -0,0 +1,20 @@
;
; Christian Groessler, 2014
;
; unsigned char get_tv (void);
; /* Return the video mode the machine is using */
;
.include "get_tv.inc"
;--------------------------------------------------------------------------
; _get_tv
.proc _get_tv
lda #<TV::NTSC
ldx #>TV::NTSC
rts
.endproc

13
libsrc/atari5200/gotox.s Normal file
View File

@@ -0,0 +1,13 @@
;
; Christian Groessler, 13-Mar-2014
;
; void gotox (unsigned char x);
;
.include "atari5200.inc"
.export _gotox
.import setcursor
_gotox:
sta COLCRS_5200 ; Set X
jmp setcursor

17
libsrc/atari5200/gotoxy.s Normal file
View File

@@ -0,0 +1,17 @@
;
; Christian Groessler, 13-Mar-2014
;
; void gotoxy (unsigned char x, unsigned char y);
;
.include "atari5200.inc"
.export _gotoxy
.import popa
.import setcursor
_gotoxy: ; Set the cursor position
sta ROWCRS_5200 ; Set Y
jsr popa ; Get X
sta COLCRS_5200 ; Set X
jmp setcursor

13
libsrc/atari5200/gotoy.s Normal file
View File

@@ -0,0 +1,13 @@
;
; Christian Groessler, 13-Mar-2014
;
; void gotoy (unsigned char y);
;
.include "atari5200.inc"
.export _gotoy
.import setcursor
_gotoy:
sta ROWCRS_5200 ; Set Y
jmp setcursor

59
libsrc/atari5200/irq.s Normal file
View File

@@ -0,0 +1,59 @@
;
; IRQ handling (ATARI 5200 version)
;
.export initirq, doneirq
.import callirq
.include "atari5200.inc"
; ------------------------------------------------------------------------
.segment "INIT"
initirq:
lda VVBLKD
ldx VVBLKD+1
sta IRQInd+1
stx IRQInd+2
ldy #<IRQStub
ldx #>IRQStub
jmp SETVBV
; ------------------------------------------------------------------------
.code
doneirq:
ldy IRQInd+1
ldx IRQInd+2
;jmp SETVBV
; fall thru
; ------------------------------------------------------------------------
; Set deferred vertical blank interrupt
; logic copied from Atari computer ROM
SETVBV: txa
ldx #5
sta WSYNC ; waste 20 CPU cycles
@1: dex ; to allow VBLANK to happen
bne @1 ; if this is line "7C"
sta VVBLKD+1
sty VVBLKD
rts
; ------------------------------------------------------------------------
.segment "LOWCODE"
IRQStub:
cld ; Just to be sure
jsr callirq ; Call the functions
jmp IRQInd ; Jump to the saved IRQ vector
; ------------------------------------------------------------------------
.data
IRQInd: jmp $0000

View File

@@ -0,0 +1,132 @@
;
; Standard joystick driver for the Atari 5200.
;
; Christian Groessler, 2014-05-28
;
.include "zeropage.inc"
.include "joy-kernel.inc"
.include "joy-error.inc"
.include "atari5200.inc"
.macpack module
; ------------------------------------------------------------------------
; Header. Includes jump table
module_header _atr5200std_joy
; Driver signature
.byte $6A, $6F, $79 ; "joy"
.byte JOY_API_VERSION ; Driver API version number
; Library reference
.addr $0000
; Button state masks (8 values)
.byte $01 ; JOY_UP
.byte $02 ; JOY_DOWN
.byte $04 ; JOY_LEFT
.byte $08 ; JOY_RIGHT
.byte $10 ; JOY_FIRE
.byte $20 ; JOY_FIRE2
.byte $00 ; Future expansion
.byte $00 ; Future expansion
; Jump table.
.addr INSTALL
.addr UNINSTALL
.addr COUNT
.addr READJOY
.addr 0 ; IRQ entry not used
.code
; ------------------------------------------------------------------------
; INSTALL routine. Is called after the driver is loaded into memory. If
; possible, check if the hardware is present and determine the amount of
; memory available.
; Must return an JOY_ERR_xx code in a/x.
;
INSTALL:
lda #JOY_ERR_OK
ldx #0
; rts ; Run into UNINSTALL instead
; ------------------------------------------------------------------------
; UNINSTALL routine. Is called before the driver is removed from memory.
; Can do cleanup or whatever. Must not return anything.
;
UNINSTALL:
rts
; ------------------------------------------------------------------------
; COUNT: Return the total number of available joysticks in a/x.
;
COUNT:
lda $FD32 ; check ROM version
cmp #$E8
bne @2port
lda #4
.byte $2C ; bit opcode, eats the next 2 bytes
@2port: lda #2
ldx #0
rts
; ------------------------------------------------------------------------
; READ: Read a particular joystick passed in A.
;
CENTER = 228 / 2
SENSIVITY = 16
READJOY:
and #3 ; put joystick number in range, just in case
tay
asl a
tax ; Joystick number * 2 (0-6) into X, index into ZP shadow registers
lda #0 ; Initialize return value
cmp TRIG0,y
bne @notrg
lda #$10 ; JOY_FIRE
; Read joystick
@notrg: ldy PADDL0,x ; get horizontal position
cpy #CENTER-SENSIVITY
bcs @chkleft
ora #4 ; JOY_LEFT
bne @updown
@chkleft:
cpy #CENTER+SENSIVITY
bcc @updown
ora #8 ; JOY_RIGHT
@updown:ldy PADDL0+1,x ; get vertical position
cpy #CENTER-SENSIVITY
bcs @chkdown
ora #1 ; JOY_UP
bne @done
@chkdown:
cpy #CENTER+SENSIVITY
bcc @done
ora #2 ; JOY_DOWN
@done: rts

View File

@@ -0,0 +1,12 @@
;
; Address of the static standard joystick driver
;
; Christian Groessler, 2014-05-12
;
; const void joy_static_stddrv[];
;
.export _joy_static_stddrv
.import _atr5200std_joy
_joy_static_stddrv := _atr5200std_joy

View File

@@ -0,0 +1,8 @@
;
; Christian Groessler, 2014-05-12
;
.export joy_libref
.import _exit
joy_libref := _exit

33
libsrc/atari5200/mul20.s Normal file
View File

@@ -0,0 +1,33 @@
;
; Christian Groessler, April 2014
;
; mul20
; multiplies A by 20 and returns result in AX
; uses tmp4
.importzp tmp4
.export mul20,loc_tmp
.proc mul20
ldx #0
stx tmp4
sta loc_tmp
asl a
rol tmp4
asl a
rol tmp4 ; val * 4
adc loc_tmp
bcc L1
inc tmp4 ; val * 5
L1: asl a
rol tmp4 ; val * 10
asl a
rol tmp4 ; val * 20
ldx tmp4
rts
.endproc
.bss
loc_tmp:.res 1

View File

@@ -0,0 +1,17 @@
;
; Christian Groessler, 01-Mar-2014
;
; void _randomize (void);
; /* Initialize the random number generator */
;
.export __randomize
.import _srand
.include "atari5200.inc"
__randomize:
ldx VCOUNT ; Use vertical line counter as high byte
lda RTCLOK+1 ; Use clock as low byte
jmp _srand ; Initialize generator

View File

@@ -0,0 +1,11 @@
; Dummy version, there is no visible cursor in the default CONIO screen
;
; 28-May-2014, Christian Groessler <chris@groessler.org>
.export setcursor
.proc setcursor
rts
.endproc

View File

@@ -0,0 +1,39 @@
;
; Ullrich von Bassewitz, 2003-08-12
;
; unsigned char __fastcall__ _sysuname (struct utsname* buf);
;
.export __sysuname, utsdata
.import utscopy
__sysuname = utscopy
;--------------------------------------------------------------------------
; Data. We define a fixed utsname struct here and just copy it.
.rodata
utsdata:
; sysname
.asciiz "cc65"
; nodename
.asciiz ""
; release
.byte ((.VERSION >> 8) & $0F) + '0'
.byte '.'
.byte ((.VERSION >> 4) & $0F) + '0'
.byte $00
; version
.byte (.VERSION & $0F) + '0'
.byte $00
; machine
.asciiz "Atari5200"

41
libsrc/atari5200/y2k.inc Normal file
View File

@@ -0,0 +1,41 @@
;-----------------------------------------------------------
; Y2K FIX by Alan Davis, Dennis Debro, and Ronen Habot
;-----------------------------------------------------------
Y2K LDY #$00 ; Copy BIOS opening screen to RAM
LDA #$FD
STA TEMPH
LDA #$58 ; Assume 2 port system
LDX $FD32
CPX #$E8 ; Is this a 4 port?
BNE Y2K0 ; Jump if not
LDA #$42 ; Yes, 4 port system
Y2K0 STA TEMPL
Y2K1 LDA (TEMPL),Y
STA $0600,Y
INY
BNE Y2K1
LDY #$50
INC TEMPH
Y2K2 LDA (TEMPL),Y
STA $0700,Y
DEY
BPL Y2K2
LDA #$D4 ; Point to copyright string
STA $0724
LDA #$BF
STA $0725
LDX #$0B ; Store NOP's @ end
LDA #$EA
Y2K3 STA $0732,X
DEX
BPL Y2K3
LDA #$60 ; Store RTS opcode @ end
STA $0750
JSR $0600 ; Show title screen
LDY #$00 ; Clear RAM from $0600-$3FFF
STY $80
LDA #$06
STA $81
JSR CLRRAM
RTS

49
libsrc/atmos/capslock.s Normal file
View File

@@ -0,0 +1,49 @@
;
; When Oric computers are in BASIC's command mode, the keyboard is in CAPS lock
; mode (because Oric BASIC keywords must be typed in upper-case). This
; constructor disables that mode, so that text will be typed as lower-case
; (which is the default on other cc65 platforms).
; This module is linked by the conio and POSIX input functions.
;
; 2014-09-04, Greg King
;
.constructor disable_caps
.destructor restore_caps
.include "atmos.inc"
;--------------------------------------------------------------------------
; Put this constructor into a segment that can be re-used by programs.
;
.segment "INIT"
; Turn the capitals lock off.
disable_caps:
lda CAPSLOCK
sta capsave
lda #$7F
sta CAPSLOCK
rts
;--------------------------------------------------------------------------
.code
; Restore the old capitals-lock state.
restore_caps:
lda capsave
sta CAPSLOCK
rts
;--------------------------------------------------------------------------
.bss
capsave:
.res 1

View File

@@ -1,13 +1,15 @@
;
; 2003-04-13, Ullrich von Bassewitz
; 2013-07-26, Greg King
; 2014-09-04, Greg King
;
; char cgetc (void);
;
.export _cgetc
.constructor initcgetc
.import cursor
.forceimport disable_caps
.include "atmos.inc"
@@ -22,11 +24,11 @@
; No character, enable cursor and wait
lda cursor ; Cursor currently off?
lda cursor ; Should cursor be off?
beq @L1 ; Skip if so
lda STATUS
ora #%00000001 ; Cursor ON
sta STATUS
lsr STATUS
sec ; Cursor ON
rol STATUS
@L1: lda KEYBUF
bpl @L1
@@ -34,17 +36,17 @@
ldx cursor
beq @L2
ldx #$00 ; Zero high byte
dec STATUS ; Clear bit zero
; We have the character, clear avail flag
; We have the character, clear the "available" flag
@L2: and #$7F ; Mask out avail flag
sta KEYBUF
ldx #>$0000
ldy MODEKEY
cpy #FUNCTKEY
bne @L3
ora #$80 ; FUNCT pressed
ora #$80 ; FUNCT-key pressed
; Done
@@ -53,16 +55,12 @@
.endproc
; ------------------------------------------------------------------------
; Switch the cursor off, disable capslock. Code goes into the INIT segment
; Switch the cursor off. Code goes into the INIT segment
; which may be reused after it is run.
.segment "INIT"
initcgetc:
lda STATUS
and #%11111110
sta STATUS
lda #$7F
sta CAPSLOCK
lsr STATUS
asl STATUS ; Clear bit zero
rts

View File

@@ -2,6 +2,7 @@
; Startup code for cc65 (Oric version)
;
; By Debrune J<>r<EFBFBD>me <jede@oric.org> and Ullrich von Bassewitz <uz@cc65.org>
; 2014-08-22, Greg King
;
.export _exit
@@ -39,26 +40,26 @@
.segment "STARTUP"
; Save the zero page area we're about to use
; Save the zero-page area that we're about to use.
ldx #zpspace-1
L1: lda sp,x
sta zpsave,x ; Save the zero page locations we need
sta zpsave,x
dex
bpl L1
; Clear the BSS data
; Clear the BSS data.
jsr zerobss
; Unprotect columns 0 and 1
; Unprotect screen columns 0 and 1.
lda STATUS
sta stsave
and #%11011111
sta STATUS
; Save system stuff and setup the stack
; Save some system stuff; and, set up the stack.
tsx
stx spsave ; Save system stk ptr
@@ -68,26 +69,26 @@ L1: lda sp,x
lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
sta sp+1 ; Set argument stack ptr
; Call module constructors
; Call the module constructors.
jsr initlib
; Push arguments and call main()
; Push the command-line arguments; and, call main().
jsr callmain
; Call module destructors. This is also the _exit entry.
; Call the module destructors. This is also the exit() entry.
_exit: jsr donelib ; Run module destructors
; Restore system stuff
; Restore the system stuff.
ldx spsave
txs
lda stsave
sta STATUS
; Copy back the zero page stuff
; Copy back the zero-page stuff.
ldx #zpspace-1
L2: lda zpsave,x
@@ -95,7 +96,7 @@ L2: lda zpsave,x
dex
bpl L2
; Back to BASIC
; Back to BASIC.
rts

View File

@@ -11,11 +11,13 @@
.include "joy-error.inc"
.include "atmos.inc"
.macpack module
; ------------------------------------------------------------------------
; Header. Includes jump table
.segment "JUMPTABLE"
module_header _atmos_pase_joy
; Driver signature

View File

@@ -1,9 +1,9 @@
;
; 2003-03-07, Ullrich von Bassewitz
; 2011-01-28, Stefan Haubenthal
; 2013-07-15, Greg King
; 2014-09-10, Greg King
;
; Setup arguments for main
; Set up arguments for main
;
.constructor initmainargs, 24
@@ -40,11 +40,21 @@ L0: lda CFOUND_NAME,y
;
ldx #0
L2: lda BASIC_BUF,x
beq done ; no "rem," no args.
beq done ; no "rem", no args.
inx
cmp #REM
bne L2
ldy #1 * 2
; The arguments must be copied to a safe place because BASIC's input buffer
; might be re-used by the stdin console.
ldy #(SCREEN_XSIZE * 2 - 1) - 1
L3: lda BASIC_BUF,y
sta args,y
dey
bpl L3
ldy #1 * 2 ; Point to second argv slot
; Find the next argument
@@ -65,12 +75,14 @@ found: cmp #'"' ; Is the argument quoted?
lda #' ' ; A space ends the argument
setterm:sta term ; Set end of argument marker
; Now store a pointer to the argument into the next slot. Since the BASIC
; input buffer is located at the zero page, no calculations are necessary.
; Now, store a pointer, to the argument, into the next slot.
txa ; Get low byte
add #<BASIC_BUF ; Not at page boundary
add #<args
sta argv,y ; argv[y]= &arg
lda #>$0000
adc #>args
sta argv+1,y
iny
iny
inc __argc ; Found another arg
@@ -87,8 +99,8 @@ argloop:lda BASIC_BUF,x
; A contains the terminating character. To make the argument a valid C string,
; replace the terminating character by a zero.
lda #0
sta BASIC_BUF-1,x
lda #$00
sta args-1,x
; Check if the maximum number of command line arguments is reached. If not,
; parse the next one.
@@ -103,7 +115,6 @@ done: lda #<argv
ldx #>argv
sta __argv
stx __argv + 1
rts
.endproc
@@ -115,7 +126,8 @@ done: lda #<argv
.bss
term: .res 1
name: .res FNAME_LEN + 1
args: .res SCREEN_XSIZE * 2 - 1
.data
argv: .addr name
.res MAXARGS * 2
.res MAXARGS * 2, $00

86
libsrc/atmos/read.s Normal file
View File

@@ -0,0 +1,86 @@
;
; 2014-08-22, Greg King
;
; int read (int fd, void* buf, unsigned count);
;
; This function is a hack! It lets us get text from the stdin console.
;
.export _read
.constructor initstdin
.import popax
.importzp ptr1, ptr2, ptr3
.forceimport disable_caps
.macpack generic
.include "atmos.inc"
.proc _read
sta ptr3
stx ptr3+1 ; save count as result
eor #$FF
sta ptr2
txa
eor #$FF
sta ptr2+1 ; Remember -count-1
jsr popax ; get buf
sta ptr1
stx ptr1+1
jsr popax ; get fd and discard
L1: inc ptr2
bnz L2
inc ptr2+1
bze L9 ; no more room in buf
; If there are no more characters in BASIC's input buffer, then get a line from
; the console into that buffer.
L2: ldx text_count
bpl L3
jsr GETLINE
ldx #<(0 - 1)
L3: inx
lda BASIC_BUF,x
bnz L4 ; (zero-terminated buffer)
ldx #<-1
lda #$0A ; return newline char. at end of line
L4: stx text_count
ldy #0
sta (ptr1),y
inc ptr1
bnz L1
inc ptr1+1
bnz L1 ; branch always
; No error, return count.
L9: lda ptr3
ldx ptr3+1
rts
.endproc
;--------------------------------------------------------------------------
; initstdin: Reset the stdin console.
.segment "INIT"
initstdin:
ldx #<-1
stx text_count
rts
;--------------------------------------------------------------------------
.bss
text_count:
.res 1

View File

@@ -28,10 +28,13 @@
.include "ser-error.inc"
.include "atmos.inc"
.macpack module
; ------------------------------------------------------------------------
; Header. Includes jump table
.segment "JUMPTABLE"
module_header _atmos_acia_ser
; Driver signature
.byte $73, $65, $72 ; "ser"

View File

@@ -3,10 +3,10 @@
;
; time_t _systime (void);
; /* Similar to time(), but:
; * - Is not ISO C
; * - Does not take the additional pointer
; * - Does not set errno when returning -1
; */
; ** - Is not ISO C
; ** - Does not take the additional pointer
; ** - Does not set errno when returning -1
; */
;
.export __systime

View File

@@ -2,7 +2,7 @@
; Graphics driver for the 228x200x3 palette mode on the Atmos
;
; Stefan Haubenthal <polluks@sdf.lonestar.org>
; 2013-07-15, Greg King <gregdk@users.sf.net>
; 2014-09-10, Greg King <gregdk@users.sf.net>
;
.include "zeropage.inc"
@@ -12,6 +12,7 @@
.include "atmos.inc"
.macpack generic
.macpack module
XSIZE = 6 ; System font width
YSIZE = 8 ; System font height
@@ -19,7 +20,7 @@ YSIZE = 8 ; System font height
; ------------------------------------------------------------------------
; Header. Includes jump table and constants.
.segment "JUMPTABLE"
module_header _atmos_228_200_3_tgi
; The first part of the header is a structure that has a signature,
; and defines the capabilities of the driver.
@@ -274,7 +275,7 @@ mymode: sta PARAM3
lda X1
add #2 * XSIZE ; Skip screen attribute columns
sta PARAM1
lda #0
lda #>$0000
sta PARAM1+1
sta PARAM2+1
sta PARAM3+1
@@ -290,13 +291,13 @@ GETPIXEL:
sta PARAM1
lda Y1
sta PARAM2
lda #0
lda #>$0000
sta PARAM1+1
sta PARAM2+1
jsr POINT
lda PARAM1
and #%00000001
ldx #0
ldx #>$0000
rts
; ------------------------------------------------------------------------
@@ -322,7 +323,7 @@ LINE:
sta PARAM2+1
lda MODE
sta PARAM3
ldx #>0
ldx #>$0000
stx PARAM3+1
jmp DRAW
@@ -358,7 +359,7 @@ BAR:
; ------------------------------------------------------------------------
; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in the x
; and y directions is passend in X/Y, the text direction is passed in A.
; and y directions is passed in X/Y, the text direction is passed in A.
;
; Must set an error code: NO
;
@@ -368,7 +369,7 @@ TEXTSTYLE:
; ------------------------------------------------------------------------
; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the
; OUTTEXT: Output text at x/y = ptr1/ptr2, using the current color and the
; current text style. The text to output is given as a zero-terminated
; string with its address in ptr3.
;

View File

@@ -2,7 +2,7 @@
; Graphics driver for the 240x200x2 monochrome mode on the Atmos
;
; Stefan Haubenthal <polluks@sdf.lonestar.org>
; 2013-07-16, Greg King <gregdk@users.sf.net>
; 2014-09-10, Greg King <gregdk@users.sf.net>
;
.include "zeropage.inc"
@@ -12,6 +12,7 @@
.include "atmos.inc"
.macpack generic
.macpack module
XSIZE = 6 ; System font width
YSIZE = 8 ; System font height
@@ -19,7 +20,7 @@ YSIZE = 8 ; System font height
; ------------------------------------------------------------------------
; Header. Includes jump table and constants.
.segment "JUMPTABLE"
module_header _atmos_240_200_2_tgi
; First part of the header is a structure that has a magic and defines the
; capabilities of the driver
@@ -253,7 +254,7 @@ SETPIXEL:
mymode: sta PARAM3
lda X1
sta PARAM1
lda #0
lda #>$0000
sta PARAM1+1
sta PARAM2+1
sta PARAM3+1
@@ -269,13 +270,13 @@ GETPIXEL:
sta PARAM1
lda Y1
sta PARAM2
lda #0
lda #>$0000
sta PARAM1+1
sta PARAM2+1
jsr POINT
lda PARAM1
and #%00000001
ldx #0
ldx #>$0000
rts
; ------------------------------------------------------------------------
@@ -301,7 +302,7 @@ LINE:
sta PARAM2+1
lda MODE
sta PARAM3
ldx #>0
ldx #>$0000
stx PARAM3+1
jmp DRAW

View File

@@ -8,7 +8,7 @@
.proc _toascii
; .X must be zero, on return.
ldx #>0
ldx #>$0000
rts
.endproc

View File

@@ -22,21 +22,21 @@
Start:
; Switch to the second charset
; Switch to the second charset.
lda #14
jsr BSOUT
; Before doing anything else, we have to setup our banking configuration.
; Otherwise just the lowest 16K are actually RAM. Writing through the ROM
; to the underlying RAM works, but it is bad style.
; Before doing anything else, we have to set up our banking configuration.
; Otherwise, just the lowest 16K are actually RAM. Writing through the ROM
; to the underlying RAM works; but, it is bad style.
lda MMU_CR ; Get current memory configuration...
pha ; ...and save it for later
lda #MMU_CFG_CC65 ; Bank0 with kernal ROM
lda #MMU_CFG_CC65 ; Bank0 with Kernal ROM
sta MMU_CR
; Save the zero page locations we need
; Save the zero-page locations that we need.
ldx #zpspace-1
L1: lda sp,x
@@ -44,11 +44,11 @@ L1: lda sp,x
dex
bpl L1
; Clear the BSS data
; Clear the BSS data.
jsr zerobss
; Save system stuff and setup the stack
; Save some system stuff; and, set up the stack.
pla ; Get MMU setting
sta mmusave
@@ -61,27 +61,27 @@ L1: lda sp,x
lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
sta sp+1 ; Set argument stack ptr
; Call module constructors
; Call the module constructors.
jsr initlib
; Set the bank for the file name to our execution bank. We must do this,
; *after* calling constructors, because some of them may depend on the
; original value of this register.
; Set the bank for the file name to our execution bank. We must do this
; *after* calling the constructors because some of them might depend on
; the original value of this register.
lda #0
sta FNAM_BANK
; Push arguments and call main()
; Push the command-line arguments; and, call main().
jsr callmain
; Back from main (this is also the _exit entry). Run module destructors
; Back from main() [this is also the exit() entry]. Run the module destructors.
_exit: pha ; Save the return code on stack
jsr donelib
; Copy back the zero page stuff
; Copy back the zero-page stuff.
ldx #zpspace-1
L2: lda zpsave,x
@@ -89,19 +89,19 @@ L2: lda zpsave,x
dex
bpl L2
; Place the program return code into ST
; Place the program return code into BASIC's status variable.
pla
sta ST
; Reset the stack and the memory configuration
; Reset the stack and the memory configuration.
ldx spsave
txs
ldx mmusave
stx MMU_CR
; Done, return to BASIC
; Done, return to BASIC.
rts

View File

@@ -13,14 +13,14 @@
.include "em-kernel.inc"
.include "em-error.inc"
.macpack generic
.macpack module
; ------------------------------------------------------------------------
; Header. Includes jump table
.segment "JUMPTABLE"
module_header _c128_georam_emd
; Driver signature

View File

@@ -11,14 +11,14 @@
.include "em-error.inc"
.include "c128.inc"
.macpack generic
.macpack module
; ------------------------------------------------------------------------
; Header. Includes jump table
.segment "JUMPTABLE"
module_header _c128_ram_emd
; Driver signature

View File

@@ -14,14 +14,14 @@
.include "em-error.inc"
.include "c128.inc"
.macpack generic
.macpack module
; ------------------------------------------------------------------------
; Header. Includes jump table
.segment "JUMPTABLE"
module_header _c128_ram2_emd
; Driver signature

Some files were not shown because too many files have changed in this diff Show More