Merge branch 'master' into coniopeek
This commit is contained in:
@@ -33,6 +33,7 @@ TARGETS = apple2 \
|
||||
none \
|
||||
osic1p \
|
||||
pce \
|
||||
rp6502 \
|
||||
sim6502 \
|
||||
sim65c02 \
|
||||
supervision \
|
||||
@@ -131,8 +132,8 @@ $(TARGETS): | ../lib
|
||||
|
||||
else # TARGET
|
||||
|
||||
CA65FLAGS =
|
||||
CC65FLAGS = -Or -W error
|
||||
CA65FLAGS = -g
|
||||
CC65FLAGS = -g -Or -W error
|
||||
|
||||
EXTZP = cbm510 \
|
||||
cbm610 \
|
||||
|
||||
380
libsrc/NameClashes.md
Normal file
380
libsrc/NameClashes.md
Normal file
@@ -0,0 +1,380 @@
|
||||
List of cc65 library name clashes
|
||||
=================================
|
||||
|
||||
The following is a list of identifiers that might need
|
||||
to be fixed, sorted by directory and identifier:
|
||||
|
||||
# common
|
||||
|
||||
## \_\_argc
|
||||
|
||||
* libsrc/runtime/callmain.s
|
||||
* libsrc/cbm610/mainargs.s
|
||||
* libsrc/cx16/mainargs.s
|
||||
* libsrc/plus4/mainargs.s
|
||||
* libsrc/lynx/mainargs.s
|
||||
* libsrc/c16/mainargs.s
|
||||
* libsrc/geos-common/system/mainargs.s
|
||||
* libsrc/sim6502/mainargs.s
|
||||
* libsrc/c128/mainargs.s
|
||||
* libsrc/vic20/mainargs.s
|
||||
* libsrc/nes/mainargs.s
|
||||
* libsrc/atari/getargs.s
|
||||
* libsrc/apple2/mainargs.s
|
||||
* libsrc/cbm510/mainargs.s
|
||||
* libsrc/telestrat/mainargs.s
|
||||
* libsrc/c64/mainargs.s
|
||||
* libsrc/pet/mainargs.s
|
||||
* libsrc/atmos/mainargs.s
|
||||
|
||||
## \_\_argv
|
||||
|
||||
* libsrc/runtime/callmain.s
|
||||
* libsrc/cbm610/mainargs.s
|
||||
* libsrc/cx16/mainargs.s
|
||||
* libsrc/plus4/mainargs.s
|
||||
* libsrc/lynx/mainargs.s
|
||||
* libsrc/c16/mainargs.s
|
||||
* libsrc/geos-common/system/mainargs.s
|
||||
* libsrc/sim6502/mainargs.s
|
||||
* libsrc/c128/mainargs.s
|
||||
* libsrc/vic20/mainargs.s
|
||||
* libsrc/nes/mainargs.s
|
||||
* libsrc/atari/getargs.s
|
||||
* libsrc/apple2/mainargs.s
|
||||
* libsrc/cbm510/mainargs.s
|
||||
* libsrc/telestrat/mainargs.s
|
||||
* libsrc/c64/mainargs.s
|
||||
* libsrc/pet/mainargs.s
|
||||
* libsrc/atmos/mainargs.s
|
||||
|
||||
## \_\_cos
|
||||
|
||||
* libsrc/common/sincos.s
|
||||
|
||||
## \_\_ctypeidx
|
||||
|
||||
* libsrc/common/ctype.s
|
||||
* libsrc/common/ctypemask.s
|
||||
* libsrc/geos-common/system/ctype.s
|
||||
* libsrc/atari/ctype.s
|
||||
* libsrc/cbm/ctype.s
|
||||
* libsrc/atmos/ctype.s
|
||||
* asminc/ctype\_common.inc
|
||||
|
||||
## \_\_cwd
|
||||
|
||||
* libsrc/common/getcwd.s
|
||||
* libsrc/common/_cwd.s
|
||||
* libsrc/atari/initcwd.s
|
||||
* libsrc/apple2/initcwd.s
|
||||
* libsrc/apple2/initcwd.s
|
||||
* libsrc/telestrat/initcwd.s
|
||||
* libsrc/cbm/initcwd.s
|
||||
|
||||
## \_\_cwd\_buf\_size
|
||||
|
||||
* libsrc/common/_cwd.s
|
||||
|
||||
## \_\_envcount
|
||||
|
||||
* libsrc/common/searchenv.s
|
||||
* libsrc/common/_environ.s
|
||||
* libsrc/common/putenv.s
|
||||
* libsrc/common/getenv.s
|
||||
|
||||
## \_\_environ
|
||||
|
||||
* libsrc/common/searchenv.s
|
||||
* libsrc/common/_environ.s
|
||||
* libsrc/common/putenv.s
|
||||
* libsrc/common/getenv.s
|
||||
|
||||
## \_\_envsize
|
||||
|
||||
* libsrc/common/_environ.s
|
||||
* libsrc/common/putenv.s
|
||||
|
||||
## \_\_fdesc
|
||||
|
||||
* libsrc/common/_fdesc.s
|
||||
* libsrc/common/fopen.s
|
||||
|
||||
## \_\_filetab
|
||||
|
||||
* libsrc/common/_fdesc.s
|
||||
* libsrc/common/_file.s
|
||||
* asminc/_file.inc
|
||||
|
||||
## \_\_fopen
|
||||
|
||||
* libsrc/common/fopen.s
|
||||
* libsrc/common/_fopen.s
|
||||
|
||||
## \_\_printf
|
||||
|
||||
* libsrc/common/vsnprintf.s
|
||||
* libsrc/common/_printf.s
|
||||
* libsrc/common/vfprintf.s
|
||||
* libsrc/conio/vcprintf.s
|
||||
* libsrc/pce/_printf.s
|
||||
|
||||
## \_\_scanf
|
||||
|
||||
* libsrc/common/_scanf.inc
|
||||
* libsrc/common/vsscanf.s
|
||||
* libsrc/conio/vcscanf.s
|
||||
|
||||
## \_\_sin
|
||||
|
||||
* libsrc/common/sincos.s
|
||||
|
||||
## \_\_sys
|
||||
|
||||
* libsrc/common/_sys.s
|
||||
* libsrc/apple2/_sys.s
|
||||
|
||||
## \_\_sys\_oserrlist
|
||||
|
||||
* libsrc/common/stroserr.s
|
||||
* libsrc/geos-common/system/oserrlist.s
|
||||
* libsrc/atari/oserrlist.s
|
||||
* libsrc/apple2/oserrlist.s
|
||||
* libsrc/cbm/oserrlist.s
|
||||
* libsrc/atmos/oserrlist.s
|
||||
|
||||
## \_\_syschdir
|
||||
|
||||
* libsrc/common/chdir.s
|
||||
* libsrc/atari/syschdir.s
|
||||
* libsrc/apple2/syschdir.s
|
||||
* libsrc/telestrat/syschdir.s
|
||||
* libsrc/cbm/syschdir.s
|
||||
|
||||
## \_\_sysmkdir
|
||||
|
||||
* libsrc/common/mkdir.s
|
||||
* libsrc/atari/sysmkdir.s
|
||||
* libsrc/apple2/sysmkdir.s
|
||||
* libsrc/telestrat/sysmkdir.s
|
||||
|
||||
## \_\_sysremove
|
||||
|
||||
* libsrc/common/remove.s
|
||||
* libsrc/geos-common/file/sysremove.s
|
||||
* libsrc/atari/sysremove.s
|
||||
* libsrc/atari/sysrmdir.s
|
||||
* libsrc/apple2/sysremove.s
|
||||
* libsrc/apple2/sysrmdir.s
|
||||
* libsrc/telestrat/sysremove.s
|
||||
* libsrc/cbm/sysremove.s
|
||||
|
||||
## \_\_sysrename
|
||||
|
||||
* libsrc/common/rename.s
|
||||
* libsrc/geos-common/file/sysrename.s
|
||||
* libsrc/atari/sysrename.s
|
||||
* libsrc/apple2/sysrename.s
|
||||
* libsrc/cbm/sysrename.s
|
||||
|
||||
## \_\_sysrmdir
|
||||
|
||||
* libsrc/common/rmdir.s
|
||||
* libsrc/atari/sysrmdir.s
|
||||
* libsrc/apple2/sysrmdir.s
|
||||
|
||||
\_\_sysuname
|
||||
|
||||
* libsrc/common/uname.s
|
||||
* libsrc/cbm610/sysuname.s
|
||||
* libsrc/cx16/sysuname.s
|
||||
* libsrc/plus4/sysuname.s
|
||||
* libsrc/lynx/sysuname.s
|
||||
* libsrc/c16/sysuname.s
|
||||
* libsrc/geos-common/system/sysuname.s
|
||||
* libsrc/c128/sysuname.s
|
||||
* libsrc/creativision/sysuname.s
|
||||
* libsrc/vic20/sysuname.s
|
||||
* libsrc/nes/sysuname.s
|
||||
* libsrc/atari/sysuname.s
|
||||
* libsrc/apple2/sysuname.s
|
||||
* libsrc/cbm510/sysuname.s
|
||||
* libsrc/telestrat/sysuname.s
|
||||
* libsrc/c64/sysuname.s
|
||||
* libsrc/pet/sysuname.s
|
||||
* libsrc/atari5200/sysuname.s
|
||||
* libsrc/atmos/sysuname.s
|
||||
|
||||
# apple2
|
||||
|
||||
## \_\_auxtype
|
||||
|
||||
* libsrc/apple2/open.s
|
||||
|
||||
## \_\_datetime
|
||||
|
||||
* libsrc/apple2/open.s
|
||||
|
||||
## \_\_dos\_type
|
||||
|
||||
* libsrc/apple2/dioopen.s
|
||||
* libsrc/apple2/curdevice.s
|
||||
* libsrc/apple2/mainargs.s
|
||||
* libsrc/apple2/settime.s
|
||||
* libsrc/apple2/getdevice.s
|
||||
* libsrc/apple2/dosdetect.s
|
||||
* libsrc/apple2/irq.s
|
||||
* libsrc/apple2/open.s
|
||||
* libsrc/apple2/mli.s
|
||||
* libsrc/apple2/getres.s
|
||||
|
||||
## \_\_filetype
|
||||
|
||||
* libsrc/apple2/open.s
|
||||
* libsrc/apple2/exehdr.s
|
||||
|
||||
## atari
|
||||
|
||||
## \_\_defdev
|
||||
|
||||
* libsrc/atari/posixdirent.s
|
||||
* libsrc/atari/ucase\_fn.s
|
||||
* libsrc/atari/getdefdev.s
|
||||
|
||||
## \_\_dos\_type
|
||||
|
||||
* libsrc/atari/getargs.s
|
||||
* libsrc/atari/exec.s
|
||||
* libsrc/atari/settime.s
|
||||
* libsrc/atari/syschdir.s
|
||||
* libsrc/atari/dosdetect.s
|
||||
* libsrc/atari/is\_cmdline\_dos.s
|
||||
* libsrc/atari/sysrmdir.s
|
||||
* libsrc/atari/gettime.s
|
||||
* libsrc/atari/lseek.s
|
||||
* libsrc/atari/getres.s
|
||||
* libsrc/atari/getdefdev.s
|
||||
|
||||
## \_\_do\_oserror
|
||||
|
||||
* libsrc/atari/posixdirent.s
|
||||
* libsrc/atari/do\_oserr.s
|
||||
* libsrc/atari/serref.s
|
||||
* libsrc/atari/read.s
|
||||
* libsrc/atari/write.s
|
||||
* libsrc/atari/close.s
|
||||
|
||||
## \_\_getcolor
|
||||
|
||||
* libsrc/atari/setcolor.s
|
||||
|
||||
## \_\_getdefdev
|
||||
|
||||
* libsrc/atari/getdefdev.s
|
||||
|
||||
## \_\_graphics
|
||||
|
||||
* libsrc/atari/graphics.s
|
||||
|
||||
## \_\_inviocb
|
||||
|
||||
* libsrc/atari/serref.s
|
||||
* libsrc/atari/ser/atrrdev.s
|
||||
* libsrc/atari/inviocb.s
|
||||
* libsrc/atari/read.s
|
||||
* libsrc/atari/write.s
|
||||
* libsrc/atari/lseek.s
|
||||
* libsrc/atari/close.s
|
||||
|
||||
## \_\_is\_cmdline\_dos
|
||||
|
||||
* libsrc/atari/is\_cmdline\_dos.s
|
||||
* libsrc/atari/doesclrscr.s
|
||||
|
||||
## \_\_rest\_vecs
|
||||
|
||||
* libsrc/atari/savevec.s
|
||||
|
||||
## \_\_rwsetup
|
||||
|
||||
* libsrc/atari/rwcommon.s
|
||||
* libsrc/atari/read.s
|
||||
* libsrc/atari/write.s
|
||||
|
||||
## \_\_save\_vecs
|
||||
|
||||
* libsrc/atari/savevec.s
|
||||
|
||||
## \_\_scroll
|
||||
|
||||
* libsrc/atari/scroll.s
|
||||
|
||||
## \_\_setcolor
|
||||
|
||||
* libsrc/atari/setcolor.s
|
||||
|
||||
## \_\_setcolor\_low
|
||||
|
||||
* libsrc/atari/setcolor.s
|
||||
|
||||
## \_\_sio\_call
|
||||
|
||||
* libsrc/atari/diowritev.s
|
||||
* libsrc/atari/diopncls.s
|
||||
* libsrc/atari/siocall.s
|
||||
* libsrc/atari/diowrite.s
|
||||
* libsrc/atari/dioread.s
|
||||
|
||||
# cbm
|
||||
|
||||
## \_\_cbm\_filetype
|
||||
|
||||
* libsrc/cbm/cbm\_filetype.s
|
||||
* asminc/cbm\_filetype.in
|
||||
|
||||
## \_\_dirread
|
||||
|
||||
* libsrc/cbm/dir.inc
|
||||
* libsrc/cbm/dir.s
|
||||
|
||||
## \_\_dirread1
|
||||
|
||||
* libsrc/cbm/dir.inc
|
||||
* libsrc/cbm/dir.s
|
||||
|
||||
# lynx
|
||||
|
||||
## \_\_iodat
|
||||
|
||||
* libsrc/lynx/lynx-cart.s
|
||||
* libsrc/lynx/bootldr.s
|
||||
* libsrc/lynx/extzp.s
|
||||
* libsrc/lynx/crt0.s
|
||||
* libsrc/lynx/extzp.inc
|
||||
|
||||
## \_\_iodir
|
||||
|
||||
* libsrc/lynx/extzp.s
|
||||
* libsrc/lynx/crt0.s
|
||||
* libsrc/lynx/extzp.inc
|
||||
|
||||
## \_\_sprsys
|
||||
|
||||
* libsrc/lynx/tgi/lynx-160-102-16.s
|
||||
* libsrc/lynx/extzp.s
|
||||
* libsrc/lynx/crt0.s
|
||||
* libsrc/lynx/extzp.inc
|
||||
|
||||
## \_\_viddma
|
||||
|
||||
* libsrc/lynx/tgi/lynx-160-102-16.s
|
||||
* libsrc/lynx/extzp.s
|
||||
* libsrc/lynx/crt0.s
|
||||
* libsrc/lynx/extzp.inc
|
||||
|
||||
# pce
|
||||
|
||||
## \_\_nmi
|
||||
|
||||
* libsrc/pce/irq.s
|
||||
* libsrc/pce/crt0.s
|
||||
23
libsrc/apple2/allow_lowercase.s
Normal file
23
libsrc/apple2/allow_lowercase.s
Normal file
@@ -0,0 +1,23 @@
|
||||
;
|
||||
; Oliver Schmidt, 2024-08-06
|
||||
;
|
||||
; unsigned char __fastcall__ allow_lowercase (unsigned char onoff);
|
||||
;
|
||||
|
||||
.export _allow_lowercase
|
||||
.import uppercasemask, return0, return1
|
||||
|
||||
_allow_lowercase:
|
||||
tax
|
||||
lda values,x
|
||||
ldx uppercasemask
|
||||
sta uppercasemask
|
||||
cpx #$FF
|
||||
beq :+
|
||||
jmp return0
|
||||
: jmp return1
|
||||
|
||||
.rodata
|
||||
|
||||
values: .byte $DF ; Force uppercase
|
||||
.byte $FF ; Keep lowercase
|
||||
20
libsrc/apple2/beep.s
Normal file
20
libsrc/apple2/beep.s
Normal file
@@ -0,0 +1,20 @@
|
||||
;
|
||||
; Colin Leroy-Mira, 2024
|
||||
;
|
||||
; void beep(void)
|
||||
;
|
||||
|
||||
.export _beep
|
||||
|
||||
.include "apple2.inc"
|
||||
|
||||
.segment "LOWCODE"
|
||||
|
||||
_beep:
|
||||
; Switch in ROM and call BELL
|
||||
bit $C082
|
||||
jsr $FF3A ; BELL
|
||||
|
||||
; Switch in LC bank 2 for R/O and return
|
||||
bit $C080
|
||||
rts
|
||||
75
libsrc/apple2/callmain.s
Normal file
75
libsrc/apple2/callmain.s
Normal file
@@ -0,0 +1,75 @@
|
||||
;
|
||||
; Ullrich von Bassewitz, 2003-03-07
|
||||
;
|
||||
; Push arguments and call main()
|
||||
;
|
||||
|
||||
|
||||
.export callmain, _exit
|
||||
.export __argc, __argv
|
||||
|
||||
.import _main, pushax, done, donelib
|
||||
.import zpsave, rvsave, reset
|
||||
|
||||
.include "zeropage.inc"
|
||||
.include "apple2.inc"
|
||||
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; Setup the stack for main(), then jump to it
|
||||
|
||||
callmain:
|
||||
lda __argc
|
||||
ldx __argc+1
|
||||
jsr pushax ; Push argc
|
||||
|
||||
lda __argv
|
||||
ldx __argv+1
|
||||
jsr pushax ; Push argv
|
||||
|
||||
ldy #4 ; Argument size
|
||||
jsr _main
|
||||
|
||||
; Avoid a re-entrance of donelib. This is also the exit() entry.
|
||||
_exit: ldx #<exit
|
||||
lda #>exit
|
||||
jsr reset ; Setup RESET vector
|
||||
|
||||
; Switch in LC bank 2 for R/O in case it was switched out by a RESET.
|
||||
bit $C080
|
||||
|
||||
; Call the module destructors.
|
||||
jsr donelib
|
||||
|
||||
; Switch in ROM.
|
||||
bit $C082
|
||||
|
||||
; Restore the original RESET vector.
|
||||
exit: ldx #$02
|
||||
: lda rvsave,x
|
||||
sta SOFTEV,x
|
||||
dex
|
||||
bpl :-
|
||||
|
||||
; Copy back the zero-page stuff.
|
||||
ldx #zpspace-1
|
||||
: lda zpsave,x
|
||||
sta sp,x
|
||||
dex
|
||||
bpl :-
|
||||
|
||||
; ProDOS TechRefMan, chapter 5.2.1:
|
||||
; "System programs should set the stack pointer to $FF at the
|
||||
; warm-start entry point."
|
||||
ldx #$FF
|
||||
txs ; Re-init stack pointer
|
||||
|
||||
; We're done
|
||||
jmp done
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; Data
|
||||
|
||||
.data
|
||||
__argc: .word 0
|
||||
__argv: .addr 0
|
||||
@@ -9,6 +9,7 @@
|
||||
.export _cgetc
|
||||
.import cursor, putchardirect
|
||||
|
||||
.include "zeropage.inc"
|
||||
.include "apple2.inc"
|
||||
|
||||
_cgetc:
|
||||
@@ -22,7 +23,7 @@ _cgetc:
|
||||
.else
|
||||
lda #' ' | $40 ; Blank, flashing
|
||||
.endif
|
||||
jsr putchardirect ; Returns old character in X
|
||||
jsr putchardirect ; Saves old character in tmp3
|
||||
|
||||
; Wait for keyboard strobe.
|
||||
: inc RNDL ; Increment random counter low
|
||||
@@ -37,7 +38,7 @@ _cgetc:
|
||||
|
||||
; Restore old character.
|
||||
pha
|
||||
txa
|
||||
lda tmp3
|
||||
jsr putchardirect
|
||||
pla
|
||||
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* closedir.c */
|
||||
/* */
|
||||
/* Close a directory */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2005 Oliver Schmidt, <ol.sc@web.de> */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include "dir.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
int __fastcall__ closedir (DIR* dir)
|
||||
{
|
||||
int result;
|
||||
|
||||
/* Cleanup directory file */
|
||||
result = close (dir->fd);
|
||||
|
||||
/* Cleanup DIR */
|
||||
free (dir);
|
||||
|
||||
return result;
|
||||
}
|
||||
35
libsrc/apple2/closedir.s
Normal file
35
libsrc/apple2/closedir.s
Normal file
@@ -0,0 +1,35 @@
|
||||
;
|
||||
; Colin Leroy-Mira <colin@colino.net>, 2024
|
||||
;
|
||||
; int __fastcall__ closedir (DIR *dir)
|
||||
;
|
||||
|
||||
.export _closedir, closedir_ptr1
|
||||
|
||||
.import _close
|
||||
.import _free
|
||||
.import pushax, popax, pushptr1, swapstk
|
||||
|
||||
.importzp ptr1
|
||||
|
||||
.include "apple2.inc"
|
||||
.include "dir.inc"
|
||||
.include "errno.inc"
|
||||
.include "fcntl.inc"
|
||||
.include "zeropage.inc"
|
||||
|
||||
_closedir:
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
closedir_ptr1:
|
||||
; Close fd
|
||||
jsr pushptr1 ; Backup ptr1
|
||||
ldy #$00
|
||||
lda (ptr1),y ; Get fd
|
||||
ldx #$00
|
||||
jsr _close
|
||||
jsr swapstk ; Store result, pop ptr1
|
||||
|
||||
; Free dir structure
|
||||
jsr _free
|
||||
jmp popax ; Return result
|
||||
@@ -11,18 +11,23 @@
|
||||
_cpeekc:
|
||||
ldy CH
|
||||
.ifdef __APPLE2ENH__
|
||||
sec ; Assume main memory
|
||||
bit RD80VID ; In 80 column mode?
|
||||
bpl peek ; No, just go ahead
|
||||
tya
|
||||
lda OURCH
|
||||
lsr ; Div by 2
|
||||
tay
|
||||
bcs peek ; Odd cols are in main memory
|
||||
php
|
||||
sei ; No valid MSLOT et al. in aux memory
|
||||
bit HISCR ; Assume SET80COL
|
||||
.endif
|
||||
peek: lda (BASL),Y ; Get character
|
||||
.ifdef __APPLE2ENH__
|
||||
bit LOWSCR ; Doesn't hurt in 40 column mode
|
||||
.endif
|
||||
bcs :+ ; In main memory
|
||||
bit LOWSCR
|
||||
plp
|
||||
: .endif
|
||||
eor #$80 ; Invert high bit
|
||||
ldx #$00
|
||||
ldx #>$0000
|
||||
rts
|
||||
|
||||
@@ -11,9 +11,15 @@
|
||||
.export _cputcxy, _cputc
|
||||
.export cputdirect, newline, putchar, putchardirect
|
||||
.import gotoxy, VTABZ
|
||||
.ifndef __APPLE2ENH__
|
||||
.import uppercasemask
|
||||
.endif
|
||||
|
||||
.include "zeropage.inc"
|
||||
.include "apple2.inc"
|
||||
|
||||
.macpack cpu
|
||||
|
||||
.segment "ONCE"
|
||||
|
||||
.ifdef __APPLE2ENH__
|
||||
@@ -33,7 +39,7 @@ _cputcxy:
|
||||
pla ; Restore C and run into _cputc
|
||||
|
||||
_cputc:
|
||||
cmp #$0D ; Test for \r = carrage return
|
||||
cmp #$0D ; Test for \r = carriage return
|
||||
beq left
|
||||
cmp #$0A ; Test for \n = line feed
|
||||
beq newline
|
||||
@@ -41,19 +47,34 @@ _cputc:
|
||||
.ifndef __APPLE2ENH__
|
||||
cmp #$E0 ; Test for lowercase
|
||||
bcc cputdirect
|
||||
and #$DF ; Convert to uppercase
|
||||
and uppercasemask
|
||||
.endif
|
||||
|
||||
cputdirect:
|
||||
jsr putchar
|
||||
.ifdef __APPLE2ENH__
|
||||
bit RD80VID ; In 80 column mode?
|
||||
bpl :+
|
||||
inc OURCH ; Bump to next column
|
||||
lda OURCH
|
||||
bra check ; Must leave CH alone
|
||||
: .endif
|
||||
inc CH ; Bump to next column
|
||||
lda CH
|
||||
cmp WNDWDTH
|
||||
bcc :+
|
||||
check: cmp WNDWDTH
|
||||
bcc done
|
||||
jsr newline
|
||||
left: lda #$00 ; Goto left edge of screen
|
||||
left:
|
||||
.ifdef __APPLE2ENH__
|
||||
stz CH ; Goto left edge of screen
|
||||
bit RD80VID ; In 80 column mode?
|
||||
bpl done
|
||||
stz OURCH ; Goto left edge of screen
|
||||
.else
|
||||
lda #$00 ; Goto left edge of screen
|
||||
sta CH
|
||||
: rts
|
||||
.endif
|
||||
done: rts
|
||||
|
||||
newline:
|
||||
inc CV ; Bump to next line
|
||||
@@ -77,22 +98,27 @@ putchar:
|
||||
mask: and INVFLG ; Apply normal, inverse, flash
|
||||
|
||||
putchardirect:
|
||||
pha
|
||||
tax
|
||||
ldy CH
|
||||
.ifdef __APPLE2ENH__
|
||||
sec ; Assume main memory
|
||||
bit RD80VID ; In 80 column mode?
|
||||
bpl put ; No, just go ahead
|
||||
tya
|
||||
lda OURCH
|
||||
lsr ; Div by 2
|
||||
tay
|
||||
bcs put ; Odd cols go in main memory
|
||||
php
|
||||
sei ; No valid MSLOT et al. in aux memory
|
||||
bit HISCR ; Assume SET80COL
|
||||
.endif
|
||||
put: lda (BASL),Y ; Get current character
|
||||
tax ; Return old character for _cgetc
|
||||
pla
|
||||
sta tmp3 ; Save old character for _cgetc
|
||||
txa
|
||||
sta (BASL),Y
|
||||
.ifdef __APPLE2ENH__
|
||||
bit LOWSCR ; Doesn't hurt in 40 column mode
|
||||
.endif
|
||||
bcs :+ ; In main memory
|
||||
bit LOWSCR
|
||||
plp
|
||||
: .endif
|
||||
rts
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
; Startup code for cc65 (Apple2 version)
|
||||
;
|
||||
|
||||
.export _exit, done, return
|
||||
.export done, return
|
||||
.export zpsave, rvsave, reset
|
||||
.export __STARTUP__ : absolute = 1 ; Mark as startup
|
||||
|
||||
.import initlib, donelib
|
||||
.import initlib, _exit
|
||||
.import zerobss, callmain
|
||||
.import bltu2
|
||||
.import __ONCE_LOAD__, __ONCE_SIZE__ ; Linker generated
|
||||
.import __LC_START__, __LC_LAST__ ; Linker generated
|
||||
|
||||
@@ -33,41 +35,7 @@
|
||||
jsr zerobss
|
||||
|
||||
; Push the command-line arguments; and, call main().
|
||||
jsr callmain
|
||||
|
||||
; 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.
|
||||
bit $C082
|
||||
|
||||
; Call the module destructors.
|
||||
jsr donelib
|
||||
|
||||
; Restore the original RESET vector.
|
||||
exit: ldx #$02
|
||||
: lda rvsave,x
|
||||
sta SOFTEV,x
|
||||
dex
|
||||
bpl :-
|
||||
|
||||
; Copy back the zero-page stuff.
|
||||
ldx #zpspace-1
|
||||
: lda zpsave,x
|
||||
sta sp,x
|
||||
dex
|
||||
bpl :-
|
||||
|
||||
; ProDOS TechRefMan, chapter 5.2.1:
|
||||
; "System programs should set the stack pointer to $FF at the
|
||||
; warm-start entry point."
|
||||
ldx #$FF
|
||||
txs ; Re-init stack pointer
|
||||
|
||||
; We're done
|
||||
jmp done
|
||||
jmp callmain
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
@@ -126,6 +94,7 @@ basic: lda HIMEM
|
||||
; Call the module constructors.
|
||||
jsr initlib
|
||||
|
||||
; Copy the LC segment to its destination
|
||||
; Switch in LC bank 2 for W/O.
|
||||
bit $C081
|
||||
bit $C081
|
||||
@@ -153,7 +122,7 @@ basic: lda HIMEM
|
||||
|
||||
; Call into Applesoft Block Transfer Up -- which handles zero-
|
||||
; sized blocks well -- to move the content of the LC memory area.
|
||||
jsr $D39A ; BLTU2
|
||||
jsr bltu2
|
||||
|
||||
; Switch in LC bank 2 for R/O and return.
|
||||
bit $C080
|
||||
|
||||
@@ -23,5 +23,5 @@ _getcurrentdevice:
|
||||
bne :+
|
||||
lda #$FF ; INVALID_DEVICE
|
||||
|
||||
: ldx #$00
|
||||
: ldx #>$0000
|
||||
rts
|
||||
|
||||
17
libsrc/apple2/detect_iigs.s
Normal file
17
libsrc/apple2/detect_iigs.s
Normal file
@@ -0,0 +1,17 @@
|
||||
;
|
||||
; Colin Leroy-Mira <colin@colino.net>, 2024
|
||||
;
|
||||
; void __fastcall__ detect_iigs(void)
|
||||
;
|
||||
|
||||
.export _detect_iigs
|
||||
.import ostype, return0, return1
|
||||
|
||||
.include "apple2.inc"
|
||||
|
||||
; Returns 1 if running on IIgs, 0 otherwise
|
||||
_detect_iigs:
|
||||
lda ostype
|
||||
bpl :+
|
||||
jmp return1
|
||||
: jmp return0
|
||||
@@ -31,5 +31,5 @@ diocommon:
|
||||
dioepilog:
|
||||
; Return success or error
|
||||
sta ___oserror
|
||||
ldx #$00
|
||||
ldx #>$0000
|
||||
rts
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* dir.h */
|
||||
/* */
|
||||
/* Apple ][ system specific DIR */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2005 Oliver Schmidt, <ol.sc@web.de> */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef _DIR_H
|
||||
#define _DIR_H
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
struct DIR {
|
||||
int fd;
|
||||
unsigned char entry_length;
|
||||
unsigned char entries_per_block;
|
||||
unsigned char current_entry;
|
||||
union {
|
||||
unsigned char bytes[512];
|
||||
struct {
|
||||
unsigned prev_block;
|
||||
unsigned next_block;
|
||||
unsigned char entries[1];
|
||||
} content;
|
||||
} block;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* End of dir.h */
|
||||
#endif
|
||||
15
libsrc/apple2/dir.inc
Normal file
15
libsrc/apple2/dir.inc
Normal file
@@ -0,0 +1,15 @@
|
||||
.struct DIR
|
||||
FD .word
|
||||
ENTRY_LENGTH .byte
|
||||
ENTRIES_PER_BLOCK .byte
|
||||
FILE_COUNT .word
|
||||
CURRENT_ENTRY .byte
|
||||
.union
|
||||
BYTES .byte 512
|
||||
.struct CONTENT
|
||||
PREV_BLOCK .word
|
||||
NEXT_BLOCK .word
|
||||
ENTRIES .byte
|
||||
.endstruct
|
||||
.endunion
|
||||
.endstruct
|
||||
24
libsrc/apple2/dir_entry_count.s
Normal file
24
libsrc/apple2/dir_entry_count.s
Normal file
@@ -0,0 +1,24 @@
|
||||
;
|
||||
; Colin Leroy-Mira <colin@colino.net>, 2024
|
||||
;
|
||||
; unsigned int __fastcall__ dir_entry_count(DIR *dir);
|
||||
;
|
||||
|
||||
.export _dir_entry_count
|
||||
|
||||
.importzp ptr1
|
||||
|
||||
.include "apple2.inc"
|
||||
.include "dir.inc"
|
||||
|
||||
.proc _dir_entry_count
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
|
||||
ldy #DIR::FILE_COUNT + 1
|
||||
lda (ptr1),y
|
||||
tax
|
||||
dey
|
||||
lda (ptr1),y
|
||||
rts
|
||||
.endproc
|
||||
@@ -5,8 +5,8 @@
|
||||
;
|
||||
|
||||
.export _exec
|
||||
.import pushname, popname
|
||||
.import popax, done, _exit
|
||||
.import mli_file_info_direct
|
||||
.import pushname, popname, popax, done, _exit
|
||||
|
||||
.include "zeropage.inc"
|
||||
.include "errno.inc"
|
||||
@@ -17,13 +17,12 @@
|
||||
typerr: lda #$4A ; "Incompatible file format"
|
||||
|
||||
; Cleanup name
|
||||
oserr: jsr popname ; Preserves A
|
||||
|
||||
; Set ___oserror
|
||||
jmp ___mappederrno
|
||||
mlierr: jsr popname
|
||||
oserr: jmp ___mappederrno
|
||||
|
||||
_exec:
|
||||
; Save cmdline
|
||||
; Store cmdline
|
||||
sta ptr4
|
||||
stx ptr4+1
|
||||
|
||||
@@ -32,6 +31,9 @@ _exec:
|
||||
jsr pushname
|
||||
bne oserr
|
||||
|
||||
jsr mli_file_info_direct
|
||||
bcs mlierr
|
||||
|
||||
; ProDOS TechRefMan, chapter 5.1.5.1:
|
||||
; "The complete or partial pathname of the system program
|
||||
; is stored at $280, starting with a length byte."
|
||||
@@ -46,18 +48,6 @@ _exec:
|
||||
dey
|
||||
bpl :-
|
||||
|
||||
; Set pushed name
|
||||
lda sp
|
||||
ldx sp+1
|
||||
sta mliparam + MLI::INFO::PATHNAME
|
||||
stx mliparam + MLI::INFO::PATHNAME+1
|
||||
|
||||
; Get file_type and aux_type
|
||||
lda #GET_INFO_CALL
|
||||
ldx #GET_INFO_COUNT
|
||||
jsr callmli
|
||||
bcs oserr
|
||||
|
||||
; If we get here the program file at least exists so we copy
|
||||
; the loader stub right now and patch it later to set params
|
||||
ldx #size - 1
|
||||
@@ -121,35 +111,9 @@ setbuf: lda #$00 ; Low byte
|
||||
dex
|
||||
dex
|
||||
|
||||
; Set I/O buffer
|
||||
sta mliparam + MLI::OPEN::IO_BUFFER
|
||||
stx mliparam + MLI::OPEN::IO_BUFFER+1
|
||||
|
||||
; PATHNAME already set
|
||||
.assert MLI::OPEN::PATHNAME = MLI::INFO::PATHNAME, error
|
||||
|
||||
; Lower file level to avoid program file
|
||||
; being closed by C library shutdown code
|
||||
ldx LEVEL
|
||||
stx level
|
||||
beq :+
|
||||
dec LEVEL
|
||||
|
||||
; Open file
|
||||
: lda #OPEN_CALL
|
||||
ldx #OPEN_COUNT
|
||||
jsr callmli
|
||||
|
||||
; Restore file level
|
||||
ldx level
|
||||
stx LEVEL
|
||||
bcc :+
|
||||
jmp oserr
|
||||
|
||||
; Get and save fd
|
||||
: lda mliparam + MLI::OPEN::REF_NUM
|
||||
sta read_ref
|
||||
sta close_ref
|
||||
; Set OPEN MLI call I/O buffer parameter
|
||||
sta io_buffer
|
||||
stx io_buffer+1
|
||||
|
||||
.ifdef __APPLE2ENH__
|
||||
; Calling the 80 column firmware needs the ROM switched
|
||||
@@ -194,14 +158,25 @@ setbuf: lda #$00 ; Low byte
|
||||
; Initiate C library shutdown
|
||||
jmp _exit
|
||||
|
||||
.bss
|
||||
|
||||
level : .res 1
|
||||
|
||||
.rodata
|
||||
|
||||
source:
|
||||
; Open program file
|
||||
; PATHNAME parameter is already set (we reuse
|
||||
; the copy at $0280); IO_BUFFER has been setup
|
||||
; before shutting down the C library
|
||||
jsr $BF00
|
||||
.byte OPEN_CALL
|
||||
.word open_param
|
||||
bcs error
|
||||
|
||||
; Copy REF_NUM to MLI READ and CLOSE parameters
|
||||
lda open_ref
|
||||
sta read_ref
|
||||
sta close_ref
|
||||
|
||||
; Read whole program file
|
||||
source: jsr $BF00
|
||||
jsr $BF00
|
||||
.byte READ_CALL
|
||||
.word read_param
|
||||
bcs error
|
||||
@@ -213,8 +188,6 @@ source: jsr $BF00
|
||||
bcs error
|
||||
|
||||
; Check for cmdline handling
|
||||
lda $0100 ; Valid cmdline?
|
||||
beq jump ; No, jump to program right away
|
||||
ldx file_type ; SYS file?
|
||||
bne system ; Yes, check for startup filename
|
||||
|
||||
@@ -256,6 +229,14 @@ jump: jmp (data_buffer)
|
||||
file_type = * - source + target
|
||||
.byte $00
|
||||
|
||||
open_param = * - source + target
|
||||
.byte $03 ; PARAM_COUNT
|
||||
.addr $0280 ; PATHNAME
|
||||
io_buffer = * - source + target
|
||||
.addr $0000 ; IO_BUFFER
|
||||
open_ref = * - source + target
|
||||
.byte $00 ; REF_NUM
|
||||
|
||||
read_param = * - source + target
|
||||
.byte $04 ; PARAM_COUNT
|
||||
read_ref = * - source + target
|
||||
@@ -287,4 +268,8 @@ size = * - source
|
||||
|
||||
target = DOSWARM - size
|
||||
|
||||
; Make sure that the loader isn't too big, and
|
||||
; fits in $300-$3D0
|
||||
.assert target >= $300, error
|
||||
|
||||
dosvec: jmp quit
|
||||
|
||||
33
libsrc/apple2/extra/integer-basic-compat.s
Normal file
33
libsrc/apple2/extra/integer-basic-compat.s
Normal file
@@ -0,0 +1,33 @@
|
||||
;
|
||||
; Colin Leroy-Mira, 06.03.2025
|
||||
;
|
||||
; Copy the LC segment from the end of the binary to the Language Card
|
||||
; using _memcpy. This allows running apple2 programs on the original
|
||||
; Integer ROM Apple ][.
|
||||
;
|
||||
|
||||
.export bltu2
|
||||
|
||||
.import _memcpy, pushax
|
||||
.import __ONCE_LOAD__, __ONCE_SIZE__ ; Linker generated
|
||||
.import __LC_START__, __LC_LAST__ ; Linker generated
|
||||
|
||||
.segment "ONCE"
|
||||
|
||||
bltu2:
|
||||
; Get the destination start address.
|
||||
lda #<__LC_START__
|
||||
ldx #>__LC_START__
|
||||
jsr pushax
|
||||
|
||||
; Get the source start address.
|
||||
lda #<(__ONCE_LOAD__ + __ONCE_SIZE__)
|
||||
ldx #>(__ONCE_LOAD__ + __ONCE_SIZE__)
|
||||
jsr pushax
|
||||
|
||||
; Set the length
|
||||
lda #<(__LC_LAST__ - __LC_START__)
|
||||
ldx #>(__LC_LAST__ - __LC_START__)
|
||||
|
||||
; And do the copy
|
||||
jmp _memcpy
|
||||
@@ -8,6 +8,7 @@
|
||||
.import subysp, addysp, decsp1
|
||||
|
||||
.include "zeropage.inc"
|
||||
.include "apple2.inc"
|
||||
.include "mli.inc"
|
||||
|
||||
pushname:
|
||||
@@ -15,7 +16,7 @@ pushname:
|
||||
stx ptr1+1
|
||||
|
||||
; Alloc pathname buffer
|
||||
ldy #64+1 ; Max pathname length + zero
|
||||
ldy #FILENAME_MAX
|
||||
jsr subysp
|
||||
|
||||
; Check for full pathname
|
||||
@@ -71,14 +72,14 @@ copy: lda (ptr1),y
|
||||
sta (sp),y
|
||||
beq setlen
|
||||
iny
|
||||
cpy #64+1 ; Max pathname length + zero
|
||||
cpy #FILENAME_MAX
|
||||
bcc copy
|
||||
|
||||
; Load oserror code
|
||||
lda #$40 ; "Invalid pathname"
|
||||
|
||||
; Free pathname buffer
|
||||
addsp65:ldy #64+1
|
||||
addsp65:ldy #FILENAME_MAX
|
||||
bne addsp ; Branch always
|
||||
|
||||
; Alloc and set length byte
|
||||
@@ -93,5 +94,5 @@ setlen: tya
|
||||
|
||||
popname:
|
||||
; Cleanup stack
|
||||
ldy #1 + 64+1 ; Length byte + max pathname length + zero
|
||||
addsp: jmp addysp ; Preserves A
|
||||
ldy #1 + FILENAME_MAX
|
||||
addsp: jmp addysp ; Preserves A and X
|
||||
|
||||
22
libsrc/apple2/get_iigs_speed.s
Normal file
22
libsrc/apple2/get_iigs_speed.s
Normal file
@@ -0,0 +1,22 @@
|
||||
;
|
||||
; Colin Leroy-Mira <colin@colino.net>, 2024
|
||||
;
|
||||
; unsigned char __fastcall__ get_iigs_speed(void)
|
||||
;
|
||||
|
||||
.export _get_iigs_speed
|
||||
.import ostype, return0
|
||||
|
||||
.include "apple2.inc"
|
||||
.include "accelerator.inc"
|
||||
|
||||
_get_iigs_speed:
|
||||
lda ostype ; Return SLOW if not IIgs
|
||||
bpl :+
|
||||
lda CYAREG ; Check current setting
|
||||
bpl :+
|
||||
lda #SPEED_FAST
|
||||
ldx #>$0000
|
||||
rts
|
||||
.assert SPEED_SLOW = 0, error
|
||||
: jmp return0 ; SPEED_SLOW
|
||||
@@ -5,7 +5,7 @@
|
||||
;
|
||||
|
||||
.constructor initostype, 9
|
||||
.export _get_ostype
|
||||
.export _get_ostype, ostype
|
||||
|
||||
; Identify machine according to:
|
||||
; Apple II Miscellaneous TechNote #7, Apple II Family Identification
|
||||
|
||||
189
libsrc/apple2/get_tv.s
Normal file
189
libsrc/apple2/get_tv.s
Normal file
@@ -0,0 +1,189 @@
|
||||
;
|
||||
; Colin Leroy-Mira <colin@colino.net>, 2025
|
||||
;
|
||||
; unsigned char __fastcall__ get_tv(void)
|
||||
;
|
||||
.export _get_tv
|
||||
|
||||
.import _set_iigs_speed, _get_iigs_speed
|
||||
.import ostype
|
||||
|
||||
.constructor calibrate_tv, 2
|
||||
|
||||
.include "accelerator.inc"
|
||||
.include "apple2.inc"
|
||||
.include "get_tv.inc"
|
||||
|
||||
.segment "ONCE"
|
||||
|
||||
; Cycle wasters
|
||||
waste_72:
|
||||
jsr waste_36
|
||||
waste_36:
|
||||
jsr waste_12
|
||||
waste_24:
|
||||
jsr waste_12
|
||||
waste_12:
|
||||
rts
|
||||
|
||||
.proc calibrate_tv
|
||||
lda ostype
|
||||
bmi iigs
|
||||
cmp #$20
|
||||
bcc iip
|
||||
cmp #$40
|
||||
bcc iie
|
||||
|
||||
iic: jmp calibrate_iic
|
||||
iigs: jmp calibrate_iigs
|
||||
iie: jmp calibrate_iie
|
||||
iip: rts ; Keep TV::OTHER.
|
||||
.endproc
|
||||
|
||||
|
||||
; Magic numbers
|
||||
WASTE_LOOP_CYCLES = 92 ; The wait loop total cycles
|
||||
NTSC_LOOP_COUNT = 17030/WASTE_LOOP_CYCLES ; How many loops expected on NTSC
|
||||
PAL_LOOP_COUNT = 20280/WASTE_LOOP_CYCLES ; How many loops expected on PAL
|
||||
STOP_PTRIG = 16500/WASTE_LOOP_CYCLES ; Stop PTRIG at 16.5ms
|
||||
|
||||
; Carry set at enter: wait for VBL +
|
||||
; Carry clear at enter: wait for VBL -
|
||||
; Increments X every 92 cycles.
|
||||
.proc count_until_vbl_bit
|
||||
lda #$10 ; BPL
|
||||
bcc :+
|
||||
lda #$30 ; BMI
|
||||
: sta sign
|
||||
|
||||
; Wait for VBLsign change with 92 cycles loops.
|
||||
; Hit PTRIG repeatedly so that accelerators will slow down.
|
||||
; But stop hitting PTRIG after 16.5ms cycles, so that on the //c,
|
||||
; the VBLINT will not be reset right before we get it. 16.5ms
|
||||
; is a good value because it's far enough from 17ms for NTSC
|
||||
; models, and close enough to 20.2ms for PAL models that accelerators
|
||||
; will stay slow until there. (5ms usually).
|
||||
|
||||
: cpx #STOP_PTRIG ; 2 - see if we spent 16.5ms already
|
||||
bcs notrig ; 4 / 5 - if so, stop hitting PTRIG
|
||||
sta PTRIG ; 8 - otherwise hit it
|
||||
bcc count ; 11
|
||||
notrig:
|
||||
nop ; 7 - keep cycle count constant when not
|
||||
nop ; 9 - hitting PTRIG
|
||||
nop ; 11
|
||||
count:
|
||||
inx ; 13
|
||||
jsr waste_72 ; 85
|
||||
bit RDVBLBAR ; 89 - Wait for VBL change
|
||||
sign:
|
||||
bpl :- ; 92 - patched with bpl/bmi
|
||||
rts
|
||||
.endproc
|
||||
|
||||
.proc calibrate_iic
|
||||
php
|
||||
sei
|
||||
|
||||
sta IOUDISOFF
|
||||
lda RDVBLMSK
|
||||
pha ; Back up for cleanup
|
||||
|
||||
bit ENVBL
|
||||
bit PTRIG ; Reset VBL interrupt flag
|
||||
: bit RDVBLBAR ; Wait for one VBL
|
||||
bpl :-
|
||||
|
||||
bit PTRIG ; Reset VBL interrupt flag again
|
||||
ldx #$00
|
||||
clc
|
||||
jsr count_until_vbl_bit
|
||||
|
||||
pla ; Cleanup
|
||||
asl
|
||||
bcs :+ ; VBL interrupts were already enabled
|
||||
bit DISVBL
|
||||
: sta IOUDISON ; IIc Tech Ref Man: The firmware normally leaves IOUDIS on.
|
||||
|
||||
plp
|
||||
jmp calibrate_done
|
||||
.endproc
|
||||
|
||||
.proc calibrate_iie
|
||||
: bit RDVBLBAR ; Wait for bit 7 to be off (VBL start)
|
||||
bmi :-
|
||||
: bit RDVBLBAR ; Wait for bit 7 to be on (VBL end)
|
||||
bpl :-
|
||||
|
||||
; Wait and count during a full cycle
|
||||
ldx #$00
|
||||
sec
|
||||
jsr count_until_vbl_bit
|
||||
clc
|
||||
jsr count_until_vbl_bit
|
||||
|
||||
jmp calibrate_done
|
||||
.endproc
|
||||
|
||||
.proc calibrate_iigs
|
||||
; Backup speed and slow down
|
||||
jsr _get_iigs_speed
|
||||
pha
|
||||
lda #SPEED_SLOW
|
||||
jsr _set_iigs_speed
|
||||
|
||||
; The same as IIe, but reverted, because... something?
|
||||
: bit RDVBLBAR ; Wait for bit 7 to be on (VBL start)
|
||||
bpl :-
|
||||
: bit RDVBLBAR ; Wait for bit 7 to be off (VBL end)
|
||||
bmi :-
|
||||
|
||||
; Wait and count during a full cycle
|
||||
ldx #$00
|
||||
clc
|
||||
jsr count_until_vbl_bit
|
||||
sec
|
||||
jsr count_until_vbl_bit
|
||||
|
||||
jsr calibrate_done
|
||||
|
||||
; Restore user speed
|
||||
pla
|
||||
jmp _set_iigs_speed
|
||||
.endproc
|
||||
|
||||
.proc calibrate_done
|
||||
; Consider X +/- 3 to be valid,
|
||||
; anything else is unknown.
|
||||
|
||||
lda #TV::NTSC
|
||||
cpx #NTSC_LOOP_COUNT-3
|
||||
bcc unexpected
|
||||
cpx #NTSC_LOOP_COUNT+3
|
||||
bcc matched
|
||||
|
||||
lda #TV::PAL
|
||||
cpx #PAL_LOOP_COUNT-3
|
||||
bcc unexpected
|
||||
cpx #PAL_LOOP_COUNT+3
|
||||
bcs unexpected
|
||||
|
||||
matched:
|
||||
sta tv
|
||||
|
||||
unexpected:
|
||||
rts
|
||||
.endproc
|
||||
|
||||
.code
|
||||
|
||||
; The only thing remaining from that code after init
|
||||
.proc _get_tv
|
||||
lda tv
|
||||
ldx #>$0000
|
||||
rts
|
||||
.endproc
|
||||
|
||||
.segment "INIT"
|
||||
|
||||
tv: .byte TV::OTHER
|
||||
@@ -30,5 +30,5 @@ next: inx
|
||||
bne next
|
||||
|
||||
done: txa
|
||||
ldx #$00
|
||||
ldx #>$0000
|
||||
rts
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
; int __fastcall__ clock_gettime (clockid_t clk_id, struct timespec *tp);
|
||||
;
|
||||
|
||||
.import pushax, steaxspidx, incsp1, incsp3, return0
|
||||
.import pushax, incsp1, incsp3, steaxspidx, return0
|
||||
.import _mktime_dt
|
||||
|
||||
.include "time.inc"
|
||||
.include "zeropage.inc"
|
||||
@@ -29,42 +30,12 @@ _clock_gettime:
|
||||
jsr callmli
|
||||
bcs oserr
|
||||
|
||||
; Get date
|
||||
lda DATELO+1
|
||||
lsr
|
||||
php ; Save month msb
|
||||
cmp #70 ; Year < 70?
|
||||
bcs :+ ; No, leave alone
|
||||
adc #100 ; Move 19xx to 20xx
|
||||
: sta TM + tm::tm_year
|
||||
lda DATELO
|
||||
tax ; Save day
|
||||
plp ; Restore month msb
|
||||
ror
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
beq erange ; [1..12] allows for validity check
|
||||
tay
|
||||
dey ; Move [1..12] to [0..11]
|
||||
sty TM + tm::tm_mon
|
||||
txa ; Restore day
|
||||
and #%00011111
|
||||
sta TM + tm::tm_mday
|
||||
; Convert DATELO/TIMELO to time_t
|
||||
lda #<DATELO
|
||||
ldx #>DATELO
|
||||
jsr _mktime_dt
|
||||
|
||||
; Get time
|
||||
lda TIMELO+1
|
||||
sta TM + tm::tm_hour
|
||||
lda TIMELO
|
||||
sta TM + tm::tm_min
|
||||
|
||||
; Make time_t
|
||||
lda #<TM
|
||||
ldx #>TM
|
||||
jsr _mktime
|
||||
|
||||
; Store tv_sec
|
||||
; Store
|
||||
ldy #timespec::tv_sec
|
||||
jsr steaxspidx
|
||||
|
||||
@@ -74,21 +45,8 @@ _clock_gettime:
|
||||
; Return success
|
||||
jmp return0
|
||||
|
||||
; Load errno code
|
||||
erange: lda #ERANGE
|
||||
|
||||
; Cleanup stack
|
||||
jsr incsp3 ; Preserves A
|
||||
|
||||
; Set __errno
|
||||
jmp ___directerrno
|
||||
|
||||
; Cleanup stack
|
||||
oserr: jsr incsp3 ; Preserves A
|
||||
|
||||
; Set ___oserror
|
||||
jmp ___mappederrno
|
||||
|
||||
.bss
|
||||
|
||||
TM: .tag tm
|
||||
|
||||
73
libsrc/apple2/gmtime_dt.s
Normal file
73
libsrc/apple2/gmtime_dt.s
Normal file
@@ -0,0 +1,73 @@
|
||||
;
|
||||
; Oliver Schmidt, 14.08.2018
|
||||
; Colin Leroy-Mira, 2023 <colin@colino.net>
|
||||
;
|
||||
; struct tm * __fastcall__ gmtime_dt(const struct datetime *dt)
|
||||
;
|
||||
|
||||
.export _gmtime_dt, tm_buf
|
||||
|
||||
.include "time.inc"
|
||||
.include "zeropage.inc"
|
||||
.include "errno.inc"
|
||||
.include "mli.inc"
|
||||
|
||||
; Convert ProDOS date/time to a struct tm
|
||||
; source date address in AX
|
||||
; on stack:
|
||||
; destination struct
|
||||
|
||||
_gmtime_dt:
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
|
||||
; Get time
|
||||
ldy #$03
|
||||
lda (ptr1),y
|
||||
sta tm_buf + tm::tm_hour
|
||||
dey
|
||||
lda (ptr1),y
|
||||
sta tm_buf + tm::tm_min
|
||||
|
||||
; Get date
|
||||
dey
|
||||
lda (ptr1),y
|
||||
lsr
|
||||
php ; Save month msb
|
||||
cmp #70 ; Year < 70?
|
||||
bcs :+ ; No, leave alone
|
||||
adc #100 ; Move 19xx to 20xx
|
||||
: sta tm_buf + tm::tm_year
|
||||
|
||||
dey
|
||||
lda (ptr1),y
|
||||
tax ; Save day
|
||||
plp ; Restore month msb
|
||||
ror
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
beq erange ; [1..12] allows for validity check
|
||||
tay
|
||||
dey ; Move [1..12] to [0..11]
|
||||
sty tm_buf + tm::tm_mon
|
||||
txa ; Restore day
|
||||
and #%00011111
|
||||
sta tm_buf + tm::tm_mday
|
||||
|
||||
lda #<tm_buf ; Return pointer to tm_buf
|
||||
ldx #>tm_buf
|
||||
rts
|
||||
|
||||
; Load errno code and return NULL
|
||||
erange: lda #ERANGE
|
||||
sta ___errno
|
||||
lda #$00
|
||||
tax
|
||||
rts
|
||||
|
||||
.bss
|
||||
|
||||
tm_buf:
|
||||
.tag tm
|
||||
@@ -22,4 +22,9 @@ _gotoxy:
|
||||
|
||||
_gotox:
|
||||
sta CH ; Store X
|
||||
.ifdef __APPLE2ENH__
|
||||
bit RD80VID ; In 80 column mode?
|
||||
bpl :+
|
||||
sta OURCH ; Store X
|
||||
: .endif
|
||||
rts
|
||||
|
||||
@@ -3,22 +3,37 @@
|
||||
;
|
||||
|
||||
.export initcwd
|
||||
.import __cwd
|
||||
.import __cwd, __dos_type
|
||||
|
||||
.include "zeropage.inc"
|
||||
.include "apple2.inc"
|
||||
.include "mli.inc"
|
||||
|
||||
initcwd:
|
||||
; Set static prefix buffer
|
||||
lda #<__cwd
|
||||
ldx #>__cwd
|
||||
sta mliparam + MLI::PREFIX::PATHNAME
|
||||
stx mliparam + MLI::PREFIX::PATHNAME+1
|
||||
; Check for ProDOS 8
|
||||
lda __dos_type
|
||||
beq done
|
||||
|
||||
; Get current working directory
|
||||
lda #GET_PREFIX_CALL
|
||||
ldx #PREFIX_COUNT
|
||||
jsr callmli
|
||||
; Save random counter
|
||||
lda RNDL
|
||||
pha
|
||||
lda RNDH
|
||||
pha
|
||||
|
||||
; Call MLI
|
||||
; We're not using mli.s' callmli because its
|
||||
; mliparam is in BSS and this will be called
|
||||
; before LC code is moved to the Language Card.
|
||||
|
||||
jsr $BF00 ; MLI call entry point
|
||||
.byte GET_PREFIX_CALL ; MLI command
|
||||
.addr mli_parameters ; MLI parameter
|
||||
|
||||
; Restore random counter
|
||||
pla
|
||||
sta RNDH
|
||||
pla
|
||||
sta RNDL
|
||||
|
||||
; Check for null prefix
|
||||
ldx __cwd
|
||||
@@ -39,3 +54,9 @@ initcwd:
|
||||
sta __cwd,x
|
||||
|
||||
done: rts
|
||||
|
||||
.rodata
|
||||
|
||||
mli_parameters:
|
||||
.byte $01 ; Number of parameters
|
||||
.addr __cwd ; Address of parameter
|
||||
|
||||
@@ -92,7 +92,7 @@ COUNT:
|
||||
bvc noiic ; Not $4x
|
||||
dex ; Only one joystick for the //c
|
||||
noiic: txa ; Number of joysticks we support
|
||||
ldx #$00
|
||||
ldx #>$0000
|
||||
rts
|
||||
|
||||
; READ routine. Read a particular joystick passed in A.
|
||||
@@ -170,5 +170,5 @@ nogs2: lda #$00 ; 0 0 0 0 0 0 0 0
|
||||
|
||||
; Finalize
|
||||
eor #%00010100 ; BTN_2 BTN_1 DOWN UP RIGHT LEFT 0 0
|
||||
ldx #$00
|
||||
ldx #>$0000
|
||||
rts
|
||||
|
||||
9
libsrc/apple2/lc-copy-applesoft.s
Normal file
9
libsrc/apple2/lc-copy-applesoft.s
Normal file
@@ -0,0 +1,9 @@
|
||||
;
|
||||
; Oliver Schmidt, 15.09.2009
|
||||
;
|
||||
; Copy the LC segment from the end of the binary to the Language Card
|
||||
; using AppleSoft's BLTU2 routine.
|
||||
;
|
||||
.export bltu2
|
||||
|
||||
bltu2 := $D39A
|
||||
37
libsrc/apple2/mktime_dt.s
Normal file
37
libsrc/apple2/mktime_dt.s
Normal file
@@ -0,0 +1,37 @@
|
||||
;
|
||||
; Oliver Schmidt, 14.08.2018
|
||||
; Colin Leroy-Mira, 2023 <colin@colino.net>
|
||||
;
|
||||
; time_t __fastcall__ mktime_dt(const struct datetime *dt)
|
||||
;
|
||||
|
||||
.import steaxspidx, pushax, incsp2, _gmtime_dt
|
||||
.import tm_buf
|
||||
.export _mktime_dt
|
||||
|
||||
.include "time.inc"
|
||||
.include "zeropage.inc"
|
||||
.include "errno.inc"
|
||||
.include "mli.inc"
|
||||
|
||||
; Convert ProDOS date/time to UNIX timestamp
|
||||
; source date address in AX
|
||||
|
||||
_mktime_dt:
|
||||
; Convert to internal tm
|
||||
jsr _gmtime_dt
|
||||
cpx #$00
|
||||
bne :+
|
||||
cmp #$00
|
||||
beq err
|
||||
|
||||
; Make time_t
|
||||
: lda #<tm_buf
|
||||
ldx #>tm_buf
|
||||
jmp _mktime
|
||||
|
||||
err: lda #$00
|
||||
tax
|
||||
sta sreg
|
||||
sta sreg+1
|
||||
rts
|
||||
@@ -83,8 +83,8 @@ EOF_COUNT = 2
|
||||
AUX_TYPE .word
|
||||
STORAGE_TYPE .byte
|
||||
BLOCKS .word
|
||||
MODE_DATE .word
|
||||
MODE_TIME .word
|
||||
MOD_DATE .word
|
||||
MOD_TIME .word
|
||||
CREATE_DATE .word
|
||||
CREATE_TIME .word
|
||||
.endstruct
|
||||
@@ -139,3 +139,6 @@ LEVEL := $BF94 ; File level: used in open, flush, close
|
||||
MACHID := $BF98 ; Machine identification
|
||||
PFIXPTR := $BF9A ; If = 0, no prefix active
|
||||
KVERSION:= $BFFF ; Kernel version number
|
||||
|
||||
; Max filename length
|
||||
FILENAME_MAX = 64+1
|
||||
|
||||
33
libsrc/apple2/mli_file_info.s
Normal file
33
libsrc/apple2/mli_file_info.s
Normal file
@@ -0,0 +1,33 @@
|
||||
;
|
||||
; Colin Leroy-Mira, 2023 <colin@colino.net>
|
||||
;
|
||||
|
||||
.export mli_file_info
|
||||
.import pushname, popname, mli_file_info_direct
|
||||
.import popax
|
||||
.include "zeropage.inc"
|
||||
.include "errno.inc"
|
||||
.include "mli.inc"
|
||||
|
||||
; Calls ProDOS MLI GET_FILE_INFO on the filename
|
||||
; stored as C string in AX at top of stack
|
||||
; Returns with carry set on error, and sets errno
|
||||
mli_file_info:
|
||||
; Get pathname
|
||||
jsr popax
|
||||
jsr pushname
|
||||
bne oserr
|
||||
|
||||
jsr mli_file_info_direct
|
||||
php ; Save return status
|
||||
|
||||
jsr popname ; Preserves A
|
||||
|
||||
plp
|
||||
bcs oserr
|
||||
rts
|
||||
|
||||
oserr:
|
||||
jsr ___mappederrno
|
||||
sec
|
||||
rts
|
||||
22
libsrc/apple2/mli_file_info_direct.s
Normal file
22
libsrc/apple2/mli_file_info_direct.s
Normal file
@@ -0,0 +1,22 @@
|
||||
;
|
||||
; Colin Leroy-Mira, 2023 <colin@colino.net>
|
||||
;
|
||||
|
||||
.export mli_file_info_direct
|
||||
.include "zeropage.inc"
|
||||
.include "mli.inc"
|
||||
|
||||
; Calls ProDOS MLI GET_FILE_INFO on the ProDOS style
|
||||
; filename stored on top of stack
|
||||
; Returns with carry set on error, and sets errno
|
||||
mli_file_info_direct:
|
||||
; Set pushed name
|
||||
lda sp
|
||||
ldx sp+1
|
||||
sta mliparam + MLI::INFO::PATHNAME
|
||||
stx mliparam + MLI::INFO::PATHNAME+1
|
||||
|
||||
; Get file information
|
||||
lda #GET_INFO_CALL
|
||||
ldx #GET_INFO_COUNT
|
||||
jmp callmli
|
||||
@@ -155,6 +155,7 @@ next: inc ptr1+1
|
||||
; Disable interrupts now because setting the slot number makes
|
||||
; the IRQ handler (maybe called due to some non-mouse IRQ) try
|
||||
; calling the firmware which isn't correctly set up yet
|
||||
php
|
||||
sei
|
||||
|
||||
; Convert to and save slot number
|
||||
@@ -211,7 +212,7 @@ next: inc ptr1+1
|
||||
common: jsr firmware
|
||||
|
||||
; Enable interrupts and return success
|
||||
cli
|
||||
plp
|
||||
lda #<MOUSE_ERR_OK
|
||||
ldx #>MOUSE_ERR_OK
|
||||
rts
|
||||
@@ -220,6 +221,7 @@ common: jsr firmware
|
||||
; No return code required (the driver is removed from memory on return).
|
||||
UNINSTALL:
|
||||
; Hide cursor
|
||||
php
|
||||
sei
|
||||
jsr CHIDE
|
||||
|
||||
@@ -249,7 +251,8 @@ SETBOX:
|
||||
; Apple II Mouse TechNote #1, Interrupt Environment with the Mouse:
|
||||
; "Disable interrupts before placing position information in the
|
||||
; screen holes."
|
||||
: sei
|
||||
: php
|
||||
sei
|
||||
|
||||
; Set low clamp
|
||||
lda (ptr1),y
|
||||
@@ -298,6 +301,7 @@ GETBOX:
|
||||
; the screen). No return code required.
|
||||
MOVE:
|
||||
ldy slot
|
||||
php
|
||||
sei
|
||||
|
||||
; Set y
|
||||
@@ -328,9 +332,10 @@ MOVE:
|
||||
; no special action is required besides hiding the mouse cursor.
|
||||
; No return code required.
|
||||
HIDE:
|
||||
php
|
||||
sei
|
||||
jsr CHIDE
|
||||
cli
|
||||
plp
|
||||
rts
|
||||
|
||||
; SHOW: Is called to show the mouse cursor. The mouse kernel manages a
|
||||
@@ -339,15 +344,16 @@ HIDE:
|
||||
; no special action is required besides enabling the mouse cursor.
|
||||
; No return code required.
|
||||
SHOW:
|
||||
php
|
||||
sei
|
||||
jsr CSHOW
|
||||
cli
|
||||
plp
|
||||
rts
|
||||
|
||||
; BUTTONS: Return the button mask in A/X.
|
||||
BUTTONS:
|
||||
lda info + MOUSE_INFO::BUTTONS
|
||||
ldx #$00
|
||||
ldx #>$0000
|
||||
rts
|
||||
|
||||
; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1.
|
||||
@@ -360,12 +366,13 @@ POS:
|
||||
; struct pointed to by ptr1. No return code required.
|
||||
INFO:
|
||||
ldy #.sizeof(MOUSE_INFO)-1
|
||||
copy: sei
|
||||
copy: php
|
||||
sei
|
||||
: lda info,y
|
||||
sta (ptr1),y
|
||||
dey
|
||||
bpl :-
|
||||
cli
|
||||
plp
|
||||
rts
|
||||
|
||||
; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
.include "fcntl.inc"
|
||||
.include "mli.inc"
|
||||
.include "filedes.inc"
|
||||
.include "time.inc"
|
||||
|
||||
.segment "ONCE"
|
||||
|
||||
@@ -208,7 +209,7 @@ done: lda tmp1 ; Restore fd
|
||||
jsr popname ; Preserves A
|
||||
|
||||
; Return success
|
||||
ldx #$00
|
||||
ldx #>$0000
|
||||
stx ___oserror
|
||||
rts
|
||||
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* opendir.h */
|
||||
/* */
|
||||
/* Open a directory */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2005 Oliver Schmidt, <ol.sc@web.de> */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include "dir.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
extern char _cwd[FILENAME_MAX];
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
DIR* __fastcall__ opendir (register const char* name)
|
||||
{
|
||||
register DIR* dir;
|
||||
|
||||
/* Alloc DIR */
|
||||
if ((dir = malloc (sizeof (*dir))) == NULL) {
|
||||
|
||||
/* May not have been done by malloc() */
|
||||
_directerrno (ENOMEM);
|
||||
|
||||
/* Return failure */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Interpret dot as current working directory */
|
||||
if (*name == '.') {
|
||||
name = _cwd;
|
||||
}
|
||||
|
||||
/* Open directory file */
|
||||
if ((dir->fd = open (name, O_RDONLY)) != -1) {
|
||||
|
||||
/* Read directory key block */
|
||||
if (read (dir->fd,
|
||||
dir->block.bytes,
|
||||
sizeof (dir->block)) == sizeof (dir->block)) {
|
||||
|
||||
/* Get directory entry infos from directory header */
|
||||
dir->entry_length = dir->block.bytes[0x23];
|
||||
dir->entries_per_block = dir->block.bytes[0x24];
|
||||
|
||||
/* Skip directory header entry */
|
||||
dir->current_entry = 1;
|
||||
|
||||
/* Return success */
|
||||
return dir;
|
||||
}
|
||||
|
||||
/* EOF: Most probably no directory file at all */
|
||||
if (_oserror == 0) {
|
||||
_directerrno (EINVAL);
|
||||
}
|
||||
|
||||
/* Cleanup directory file */
|
||||
close (dir->fd);
|
||||
}
|
||||
|
||||
/* Cleanup DIR */
|
||||
free (dir);
|
||||
|
||||
/* Return failure */
|
||||
return NULL;
|
||||
}
|
||||
159
libsrc/apple2/opendir.s
Normal file
159
libsrc/apple2/opendir.s
Normal file
@@ -0,0 +1,159 @@
|
||||
;
|
||||
; Colin Leroy-Mira <colin@colino.net>, 2024
|
||||
;
|
||||
; DIR* __fastcall__ opendir (register const char* name)
|
||||
;
|
||||
|
||||
.export _opendir, read_dir_block_ptr1
|
||||
|
||||
.import closedir_ptr1
|
||||
.import _open, _read, _close
|
||||
.import _malloc
|
||||
.import ___directerrno
|
||||
|
||||
.import ___oserror, __cwd
|
||||
|
||||
.import pushptr1, popptr1
|
||||
.import pushax, pusha0
|
||||
.import return0, returnFFFF
|
||||
|
||||
.importzp ptr1
|
||||
|
||||
.include "apple2.inc"
|
||||
.include "dir.inc"
|
||||
.include "errno.inc"
|
||||
.include "fcntl.inc"
|
||||
.include "zeropage.inc"
|
||||
|
||||
.proc _opendir
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
|
||||
ldy #$00
|
||||
lda (ptr1),y
|
||||
cmp #'.'
|
||||
bne :+
|
||||
|
||||
lda #<__cwd
|
||||
ldx #>__cwd
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
|
||||
: ; Open directory
|
||||
jsr pushptr1
|
||||
lda #O_RDONLY
|
||||
jsr pusha0
|
||||
|
||||
ldy #$04
|
||||
jsr _open
|
||||
|
||||
cmp #$FF ; Did we succeed?
|
||||
beq @return_null
|
||||
pha ; Yes - Push fd for backup
|
||||
|
||||
; malloc the dir struct
|
||||
lda #<.sizeof(DIR)
|
||||
ldx #>.sizeof(DIR)
|
||||
jsr _malloc
|
||||
bne :+
|
||||
|
||||
; We failed to allocate
|
||||
pla ; Get fd back
|
||||
ldx #$00
|
||||
jsr _close ; Close it
|
||||
|
||||
lda #ENOMEM ; Set error
|
||||
jsr ___directerrno
|
||||
@return_null:
|
||||
jmp return0
|
||||
|
||||
: ; Store dir struct to pointer
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
|
||||
; Save fd to dir struct
|
||||
lda #$00
|
||||
ldy #DIR::FD + 1
|
||||
sta (ptr1),y
|
||||
|
||||
dey
|
||||
pla ; Get fd back
|
||||
sta (ptr1),y
|
||||
|
||||
jsr read_dir_block_ptr1
|
||||
bcc @read_ok
|
||||
|
||||
; Close directory, free it
|
||||
jsr closedir_ptr1
|
||||
jmp return0 ; Return NULL
|
||||
|
||||
@read_ok:
|
||||
; Read succeeded, populate dir struct
|
||||
|
||||
; Get file_count to entry_length from block
|
||||
ldy #$26 + DIR::BYTES
|
||||
: lda (ptr1),y
|
||||
pha
|
||||
dey
|
||||
cpy #$23 + DIR::BYTES - 1
|
||||
bne :-
|
||||
|
||||
; Set entry_length to file_count in struct
|
||||
ldy #DIR::ENTRY_LENGTH
|
||||
: pla
|
||||
sta (ptr1),y
|
||||
iny
|
||||
cpy #DIR::CURRENT_ENTRY
|
||||
bne :-
|
||||
|
||||
; Skip directory header entry
|
||||
lda #$01
|
||||
sta (ptr1),y
|
||||
|
||||
; Return pointer to dir struct
|
||||
lda ptr1
|
||||
ldx ptr1+1
|
||||
rts
|
||||
.endproc
|
||||
|
||||
; Read a directory for the DIR* pointer in ptr1
|
||||
; Return with carry clear on success
|
||||
read_dir_block_ptr1:
|
||||
; Push ptr1, read will destroy it
|
||||
jsr pushptr1
|
||||
|
||||
ldy #DIR::FD
|
||||
lda (ptr1),y
|
||||
|
||||
jsr pusha0 ; Push fd for read
|
||||
lda #<DIR::BYTES
|
||||
clc
|
||||
adc ptr1
|
||||
pha
|
||||
lda #>DIR::BYTES
|
||||
adc ptr1+1
|
||||
tax
|
||||
pla
|
||||
jsr pushax ; Push dir->block.bytes for read
|
||||
|
||||
lda #<.sizeof(DIR::BYTES)
|
||||
ldx #>.sizeof(DIR::BYTES)
|
||||
|
||||
jsr _read ; Read directory block
|
||||
cpx #>.sizeof(DIR::BYTES)
|
||||
bne @read_err
|
||||
cmp #<.sizeof(DIR::BYTES)
|
||||
beq @read_ok
|
||||
|
||||
@read_err:
|
||||
; Read failed, exit
|
||||
lda ___oserror
|
||||
bne :+
|
||||
lda #EINVAL
|
||||
jsr ___directerrno
|
||||
: sec
|
||||
bcs @out
|
||||
@read_ok:
|
||||
clc
|
||||
@out:
|
||||
jmp popptr1
|
||||
@@ -23,7 +23,7 @@ ___osmaperrno:
|
||||
|
||||
; Found the code
|
||||
: lda ErrTab-1,x
|
||||
ldx #$00 ; High byte always zero
|
||||
ldx #>$0000
|
||||
rts
|
||||
|
||||
.rodata
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* readdir.c */
|
||||
/* */
|
||||
/* Read directory entry */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2005 Oliver Schmidt, <ol.sc@web.de> */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include "dir.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
struct dirent* __fastcall__ readdir (register DIR* dir)
|
||||
{
|
||||
register unsigned char* entry;
|
||||
|
||||
/* Search for the next active directory entry */
|
||||
do {
|
||||
|
||||
/* Read next directory block if necessary */
|
||||
if (dir->current_entry == dir->entries_per_block) {
|
||||
if (read (dir->fd,
|
||||
dir->block.bytes,
|
||||
sizeof (dir->block)) != sizeof (dir->block)) {
|
||||
|
||||
/* Just return failure as read() has */
|
||||
/* set errno if (and only if) no EOF */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Start with first entry in next block */
|
||||
dir->current_entry = 0;
|
||||
}
|
||||
|
||||
/* Compute pointer to current entry */
|
||||
entry = dir->block.content.entries +
|
||||
dir->current_entry * dir->entry_length;
|
||||
|
||||
/* Switch to next entry */
|
||||
++dir->current_entry;
|
||||
} while (entry[0x00] == 0);
|
||||
|
||||
/* Move creation date/time to allow for next step below */
|
||||
*(unsigned long*)&entry[0x1A] = *(unsigned long*)&entry[0x18];
|
||||
|
||||
/* Feature unsigned long access to EOF by extension from 3 to 4 bytes */
|
||||
entry[0x18] = 0;
|
||||
|
||||
/* Move file type to allow for next step below */
|
||||
entry[0x19] = entry[0x10];
|
||||
|
||||
/* Zero-terminate file name */
|
||||
entry[0x01 + (entry[0x00] & 0x0F)] = 0;
|
||||
|
||||
/* Return success */
|
||||
return (struct dirent*)&entry[0x01];
|
||||
}
|
||||
113
libsrc/apple2/readdir.s
Normal file
113
libsrc/apple2/readdir.s
Normal file
@@ -0,0 +1,113 @@
|
||||
;
|
||||
; Colin Leroy-Mira <colin@colino.net>, 2024
|
||||
;
|
||||
; struct dirent * __fastcall__ readdir (DIR *dir)
|
||||
;
|
||||
.export _readdir
|
||||
.import read_dir_block_ptr1
|
||||
|
||||
.import incax1, return0
|
||||
.import tosaddax, tosumula0, incaxy
|
||||
.import pushax, pusha0, pushptr1, popptr1
|
||||
.importzp ptr1, ptr4
|
||||
|
||||
.include "dir.inc"
|
||||
|
||||
.proc _readdir
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
|
||||
@next_entry:
|
||||
; Do we need to read the next directory block?
|
||||
ldy #DIR::CURRENT_ENTRY
|
||||
lda (ptr1),y
|
||||
ldy #DIR::ENTRIES_PER_BLOCK
|
||||
cmp (ptr1),y
|
||||
bne @read_entry ; We don't
|
||||
|
||||
jsr read_dir_block_ptr1
|
||||
bcc @read_ok
|
||||
|
||||
; We had a read error
|
||||
jmp return0
|
||||
|
||||
@read_ok:
|
||||
ldy #DIR::CURRENT_ENTRY
|
||||
lda #$00
|
||||
sta (ptr1),y
|
||||
|
||||
@read_entry:
|
||||
; Compute pointer to current entry:
|
||||
; entry = dir->block.content.entries +
|
||||
; dir->current_entry * dir->entry_length
|
||||
|
||||
jsr pushptr1 ; Backup ptr1
|
||||
lda ptr1
|
||||
ldx ptr1+1
|
||||
ldy #DIR::BYTES + DIR::CONTENT::ENTRIES
|
||||
jsr incaxy
|
||||
jsr pushax
|
||||
ldy #DIR::CURRENT_ENTRY
|
||||
lda (ptr1),y
|
||||
jsr pusha0
|
||||
ldy #DIR::ENTRY_LENGTH
|
||||
lda (ptr1),y
|
||||
jsr tosumula0
|
||||
jsr tosaddax
|
||||
; Store pointer to current entry
|
||||
sta ptr4
|
||||
stx ptr4+1
|
||||
jsr popptr1
|
||||
|
||||
; Switch to next entry
|
||||
ldy #DIR::CURRENT_ENTRY
|
||||
lda (ptr1),y
|
||||
clc
|
||||
adc #1
|
||||
sta (ptr1),y
|
||||
|
||||
; Check if entry[0] == 0
|
||||
ldy #$00
|
||||
lda (ptr4),y
|
||||
beq @next_entry ; Yes, skip entry
|
||||
|
||||
; Move creation date/time to allow for next step below
|
||||
; 18-19-1A-1B => 1A-1B-1C-1D
|
||||
ldy #$1B
|
||||
: lda (ptr4),y
|
||||
iny
|
||||
iny
|
||||
sta (ptr4),y
|
||||
dey
|
||||
dey
|
||||
dey
|
||||
cpy #$17
|
||||
bne :-
|
||||
|
||||
; Feature unsigned long access to EOF by extension from 3 to 4 bytes
|
||||
; entry[0x18] = 0
|
||||
iny
|
||||
lda #$00
|
||||
sta (ptr4),y
|
||||
|
||||
; Move file type to allow for next step below
|
||||
; entry[0x19] = entry[0x10]
|
||||
ldy #$10
|
||||
lda (ptr4),y
|
||||
ldy #$19
|
||||
sta (ptr4),y
|
||||
|
||||
; Zero-terminate file name
|
||||
ldy #$00
|
||||
lda (ptr4),y
|
||||
and #$0F
|
||||
tay
|
||||
iny
|
||||
lda #$00
|
||||
sta (ptr4),y
|
||||
|
||||
; Return pointer to entry+1
|
||||
lda ptr4
|
||||
ldx ptr4+1
|
||||
jmp incax1
|
||||
.endproc
|
||||
@@ -18,5 +18,5 @@ normal: dex ; $00->$FF, $40->$3F
|
||||
stx INVFLG ; Save new flag value
|
||||
bmi :+ ; Jump if current value is $FF (normal)
|
||||
lda #$01 ; Return "inverse"
|
||||
: ldx #$00
|
||||
: ldx #>$0000
|
||||
rts
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* rewinddir.c */
|
||||
/* */
|
||||
/* Reset directory stream */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2005 Oliver Schmidt, <ol.sc@web.de> */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include "dir.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
void __fastcall__ rewinddir (register DIR* dir)
|
||||
{
|
||||
/* Rewind directory file */
|
||||
if (lseek (dir->fd, 0, SEEK_SET)) {
|
||||
|
||||
/* Read directory key block */
|
||||
if (read (dir->fd,
|
||||
dir->block.bytes,
|
||||
sizeof (dir->block)) == sizeof (dir->block)) {
|
||||
|
||||
/* Skip directory header entry */
|
||||
dir->current_entry = 1;
|
||||
|
||||
/* Return success */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Assert that no subsequent readdir() finds an active entry */
|
||||
memset (dir->block.bytes, 0, sizeof (dir->block));
|
||||
|
||||
/* Return failure */
|
||||
}
|
||||
70
libsrc/apple2/rewinddir.s
Normal file
70
libsrc/apple2/rewinddir.s
Normal file
@@ -0,0 +1,70 @@
|
||||
;
|
||||
; Colin Leroy-Mira <colin@colino.net>, 2024
|
||||
;
|
||||
; void __fastcall__ rewinddir (DIR* dir)
|
||||
;
|
||||
.export _rewinddir
|
||||
.import read_dir_block_ptr1
|
||||
|
||||
.import pusha, pusha0, pushax
|
||||
.import pushptr1, popptr1
|
||||
.import incaxy
|
||||
.import _lseek, _memset
|
||||
|
||||
.importzp ptr1, sreg
|
||||
|
||||
.include "dir.inc"
|
||||
.include "stdio.inc"
|
||||
|
||||
.proc _rewinddir
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
jsr pushptr1 ; Backup ptr1, destroyed by _lseek
|
||||
|
||||
; Rewind directory file
|
||||
ldy #DIR::FD
|
||||
lda (ptr1),y
|
||||
jsr pusha0 ; Push dir->fd
|
||||
|
||||
tya ; Y = 0 here
|
||||
jsr pusha0
|
||||
jsr pusha0 ; Push 0L
|
||||
|
||||
lda #SEEK_SET ; X = 0 here
|
||||
jsr _lseek
|
||||
|
||||
ora sreg ; Check lseek returned 0L
|
||||
ora sreg+1
|
||||
bne @rewind_err
|
||||
txa
|
||||
bne @rewind_err
|
||||
|
||||
jsr popptr1 ; Restore ptr1
|
||||
|
||||
; Read directory key block
|
||||
jsr read_dir_block_ptr1
|
||||
bcs @rewind_err
|
||||
|
||||
; Skip directory header entry
|
||||
lda #$01
|
||||
ldy #DIR::CURRENT_ENTRY
|
||||
sta (ptr1),y
|
||||
rts
|
||||
|
||||
@rewind_err:
|
||||
jsr popptr1 ; Restore ptr1
|
||||
|
||||
; Assert that no subsequent readdir() finds an active entry
|
||||
lda ptr1
|
||||
ldx ptr1+1
|
||||
ldy #DIR::BYTES + DIR::CONTENT::ENTRIES
|
||||
jsr incaxy
|
||||
jsr pushax
|
||||
|
||||
lda #$00
|
||||
jsr pusha
|
||||
|
||||
lda #<.sizeof(DIR::BYTES)
|
||||
ldx #>.sizeof(DIR::BYTES)
|
||||
jmp _memset
|
||||
.endproc
|
||||
752
libsrc/apple2/ser/a2.gs.s
Normal file
752
libsrc/apple2/ser/a2.gs.s
Normal file
@@ -0,0 +1,752 @@
|
||||
;
|
||||
; Serial driver for the Apple IIgs Zilog Z8530.
|
||||
;
|
||||
; Colin Leroy-Mira <colin@colino.net>, 2023
|
||||
;
|
||||
; This software is licensed under the same license as cc65,
|
||||
; the zlib license (see LICENSE file).
|
||||
;
|
||||
; Documentation from http://www.applelogic.org/files/Z8530UM.pdf (pages
|
||||
; referred to where applicable)
|
||||
; and https://gswv.apple2.org.za/a2zine/Utils/Z8530_SCCsamples_info.txt
|
||||
|
||||
|
||||
|
||||
.setcpu "65816"
|
||||
|
||||
.include "zeropage.inc"
|
||||
.include "ser-kernel.inc"
|
||||
.include "ser-error.inc"
|
||||
|
||||
.macpack module
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Header. Includes jump table
|
||||
|
||||
.ifdef __APPLE2ENH__
|
||||
module_header _a2e_gs_ser
|
||||
.else
|
||||
module_header _a2_gs_ser
|
||||
.endif
|
||||
|
||||
; Driver signature
|
||||
.byte $73, $65, $72 ; "ser"
|
||||
.byte SER_API_VERSION ; Serial API version number
|
||||
|
||||
; Library reference
|
||||
.addr $0000
|
||||
|
||||
; Jump table
|
||||
.addr SER_INSTALL
|
||||
.addr SER_UNINSTALL
|
||||
.addr SER_OPEN
|
||||
.addr SER_CLOSE
|
||||
.addr SER_GET
|
||||
.addr SER_PUT
|
||||
.addr SER_STATUS
|
||||
.addr SER_IOCTL
|
||||
.addr SER_IRQ
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Global variables
|
||||
|
||||
.bss
|
||||
|
||||
RecvHead: .res 1 ; Head of receive buffer
|
||||
RecvTail: .res 1 ; Tail of receive buffer
|
||||
RecvFreeCnt: .res 1 ; Number of bytes in receive buffer
|
||||
SendHead: .res 1 ; Head of send buffer
|
||||
SendTail: .res 1 ; Tail of send buffer
|
||||
SendFreeCnt: .res 1 ; Number of bytes in send buffer
|
||||
|
||||
Stopped: .res 1 ; Flow-stopped flag
|
||||
RtsOff: .res 1
|
||||
HSType: .res 1 ; Flow-control type
|
||||
|
||||
RecvBuf: .res 256 ; Receive buffers: 256 bytes
|
||||
SendBuf: .res 256 ; Send buffers: 256 bytes
|
||||
|
||||
CurClockSource: .res 1 ; Whether to use BRG or RTxC for clock
|
||||
|
||||
.data
|
||||
|
||||
Opened: .byte $00 ; 1 when opened
|
||||
Channel: .byte $00 ; Channel B by default
|
||||
CurChanIrqFlags:.byte $00
|
||||
|
||||
SerFlagOrig: .byte $00
|
||||
|
||||
RxBitTable: .byte %00000000 ; SER_BITS_5, in WR_RX_CTRL (WR3)
|
||||
.byte %10000000 ; SER_BITS_6 (Ref page 5-7)
|
||||
.byte %01000000 ; SER_BITS_7
|
||||
.byte %11000000 ; SER_BITS_8
|
||||
|
||||
TxBitTable: .byte %00000000 ; SER_BITS_5, in WR_TX_CTRL (WR5)
|
||||
.byte %01000000 ; SER_BITS_6 (Ref page 5-9)
|
||||
.byte %00100000 ; SER_BITS_7
|
||||
.byte %01100000 ; SER_BITS_8
|
||||
|
||||
.rodata
|
||||
|
||||
ClockMultiplier:.byte %01000000 ; Clock x16 (300-57600bps, WR4, ref page 5-8)
|
||||
.byte %10000000 ; Clock x32 (115200bps, ref page 5-8)
|
||||
|
||||
ClockSource: .byte %01010000 ; Use baud rate generator (ch. B) (WR11, page 5-17)
|
||||
.byte %00000000 ; Use RTxC (115200bps) (ch. B)
|
||||
.byte %11010000 ; Use baud rate generator (ch. A)
|
||||
.byte %10000000 ; Use RTxC (115200bps) (ch. A)
|
||||
|
||||
BrgEnabled: .byte %00000001 ; Baud rate generator on (WR14, page 5-19)
|
||||
.byte %00000000 ; BRG Off
|
||||
|
||||
ChanIrqFlags: .byte %00000101 ; ANDed (RX/special IRQ, ch. B) (page 5-25)
|
||||
.byte %00101000 ; ANDed (RX/special IRQ, ch. A)
|
||||
|
||||
ChanIrqMask: .byte %00000111 ; Ch. B IRQ flags mask
|
||||
.byte %00111000 ; Ch. A IRQ flags mask
|
||||
|
||||
BaudTable: ; bit7 = 1 means setting is invalid
|
||||
; Indexes cc65 RS232 SER_BAUD enum
|
||||
; into WR12/13 register values
|
||||
; (Ref page 5-18 and 5-19)
|
||||
.word $FFFF ; SER_BAUD_45_5
|
||||
.word $FFFF ; SER_BAUD_50
|
||||
.word $FFFF ; SER_BAUD_75
|
||||
.word $FFFF ; SER_BAUD_110
|
||||
.word $FFFF ; SER_BAUD_134_5
|
||||
.word $FFFF ; SER_BAUD_150
|
||||
.word $017E ; SER_BAUD_300
|
||||
.word $FFFF ; SER_BAUD_600
|
||||
.word $005E ; SER_BAUD_1200
|
||||
.word $FFFF ; SER_BAUD_1800
|
||||
.word $002E ; SER_BAUD_2400
|
||||
.word $FFFF ; SER_BAUD_3600
|
||||
.word $0016 ; SER_BAUD_4800
|
||||
.word $FFFF ; SER_BAUD_7200
|
||||
.word $000A ; SER_BAUD_9600
|
||||
.word $0004 ; SER_BAUD_19200
|
||||
.word $0001 ; SER_BAUD_38400
|
||||
.word $0000 ; SER_BAUD_57600
|
||||
.word $0000 ; SER_BAUD_115200 (constant unused at that speed)
|
||||
.word $FFFF ; SER_BAUD_230400
|
||||
|
||||
; About the speed selection: either we use the baud rate generator:
|
||||
; - Load the time constants from BaudTable into WR12/WR13
|
||||
; - Setup the TX/RX clock source to BRG (ClockSource into WR11)
|
||||
; - Setup the clock multiplier (WR4)
|
||||
; - Enable the baud rate generator (WR14)
|
||||
; In this case, the baud rate will be:
|
||||
; rate = crystal_clock/(2+BRG_time_constant))/(2*clock_multiplier)
|
||||
; Example: (3686400/(2+0x0004)) / (2*16) = 19200 bps
|
||||
;
|
||||
; Or we don't use the baud rate generator:
|
||||
; - Setup the TX/RX clock source to RTxC
|
||||
; - Setup the clock multiplier
|
||||
; - Disable the baud rate generator
|
||||
; - WR12 and 13 are ignored
|
||||
; In this case, the baud rate will be:
|
||||
; rate = crystal_clock/clock_multiplier
|
||||
; Example: 3686400/32 = 115200 bps
|
||||
|
||||
StopTable: .byte %00000100 ; SER_STOP_1, in WR_TX_RX_CTRL (WR4)
|
||||
.byte %00001100 ; SER_STOP_2 (Ref page 5-8)
|
||||
|
||||
ParityTable: .byte %00000000 ; SER_PAR_NONE, in WR_TX_RX_CTRL (WR4)
|
||||
.byte %00000001 ; SER_PAR_ODD (Ref page 5-8)
|
||||
.byte %00000011 ; SER_PAR_EVEN
|
||||
.byte $FF ; SER_PAR_MARK
|
||||
.byte $FF ; SER_PAR_SPACE
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Addresses
|
||||
|
||||
SCCAREG := $C039
|
||||
SCCBREG := $C038
|
||||
SCCADATA := $C03B
|
||||
SCCBDATA := $C03A
|
||||
|
||||
; We're supposed to get SerFlag's address using GetAddr on ROMs 1 and 3.
|
||||
; (https://archive.org/details/IIgs_2523018_SCC_Access, page 9)
|
||||
; But, it's the same value as on ROM0. As we don't expect a ROM 4 anytime
|
||||
; soon with a different value, let's keep it simple.
|
||||
|
||||
SER_FLAG := $E10104
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Channels
|
||||
|
||||
CHANNEL_B = 0
|
||||
CHANNEL_A = 1
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Write registers, read registers, and values that interest us
|
||||
|
||||
WR_INIT_CTRL = 0
|
||||
RR_INIT_STATUS = 0
|
||||
INIT_CTRL_CLEAR_EIRQ = %00010000
|
||||
INIT_CTRL_CLEAR_ERR = %00110000
|
||||
INIT_STATUS_READY = %00000100
|
||||
INIT_STATUS_RTS = %00100000
|
||||
|
||||
WR_TX_RX_MODE_CTRL = 1
|
||||
TX_RX_MODE_OFF = %00000000
|
||||
TX_RX_MODE_RXIRQ = %00010001
|
||||
|
||||
WR_RX_CTRL = 3 ; (Ref page 5-7)
|
||||
RR_RX_STATUS = 9 ; Corresponding status register
|
||||
RX_CTRL_ON = %00000001 ; ORed, Rx enabled
|
||||
RX_CTRL_OFF = %11111110 ; ANDed,Rx disabled
|
||||
|
||||
WR_TX_RX_CTRL = 4
|
||||
RR_TX_RX_STATUS = 4
|
||||
|
||||
WR_TX_CTRL = 5 ; (Ref page 5-9)
|
||||
RR_TX_STATUS = 5 ; Corresponding status register
|
||||
TX_CTRL_ON = %00001000 ; ORed, Tx enabled
|
||||
TX_CTRL_OFF = %11110111 ; ANDed,Tx disabled
|
||||
TX_DTR_ON = %01111111 ; ANDed,DTR ON (high)
|
||||
TX_DTR_OFF = %10000000 ; ORed, DTR OFF
|
||||
TX_RTS_ON = %00000010 ; ORed, RTS ON (low)
|
||||
TX_RTS_OFF = %11111101 ; ANDed, RTS OFF
|
||||
|
||||
WR_MASTER_IRQ_RST = 9 ; (Ref page 5-14)
|
||||
MASTER_IRQ_SHUTDOWN = %00000010 ; STA'd
|
||||
MASTER_IRQ_MIE_RST = %00001010 ; STA'd
|
||||
MASTER_IRQ_SET = %00011001 ; STA'd
|
||||
|
||||
WR_CLOCK_CTRL = 11 ; (Ref page 5-17)
|
||||
|
||||
WR_BAUDL_CTRL = 12 ; (Ref page 5-18)
|
||||
WR_BAUDH_CTRL = 13 ; (Ref page 5-19)
|
||||
|
||||
WR_MISC_CTRL = 14 ; (Ref page 5-19)
|
||||
|
||||
WR_IRQ_CTRL = 15 ; (Ref page 5-20)
|
||||
IRQ_CLEANUP_EIRQ = %00001000
|
||||
|
||||
RR_SPEC_COND_STATUS = 1 ; (Ref page 5-23)
|
||||
SPEC_COND_FRAMING_ERR = %01000000
|
||||
SPEC_COND_OVERRUN_ERR = %00100000
|
||||
|
||||
RR_IRQ_STATUS = 2 ; (Ref page 5-24)
|
||||
IRQ_MASQ = %01110000 ; ANDed
|
||||
IRQ_RX = %00100000
|
||||
IRQ_SPECIAL = %01100000
|
||||
|
||||
RR_INTR_PENDING_STATUS = 3 ; (Ref page 5-25)
|
||||
INTR_IS_RX = %00100100 ; ANDed (RX IRQ, channel A or B)
|
||||
|
||||
.code
|
||||
|
||||
; Read register value to A.
|
||||
; Input: X as channel
|
||||
; Y as register
|
||||
; Output: A
|
||||
readSSCReg:
|
||||
cpx #0
|
||||
bne ReadAreg
|
||||
sty SCCBREG
|
||||
lda SCCBREG
|
||||
rts
|
||||
ReadAreg:
|
||||
sty SCCAREG
|
||||
lda SCCAREG
|
||||
rts
|
||||
|
||||
; Write value of A to a register.
|
||||
; Input: X as channel
|
||||
; Y as register
|
||||
writeSCCReg:
|
||||
cpx #0
|
||||
bne WriteAreg
|
||||
sty SCCBREG
|
||||
sta SCCBREG
|
||||
rts
|
||||
WriteAreg:
|
||||
sty SCCAREG
|
||||
sta SCCAREG
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; SER_INSTALL: 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.
|
||||
;
|
||||
; Since we don't have to manage the IRQ vector on the Apple II, this is
|
||||
; actually the same as:
|
||||
;
|
||||
; SER_UNINSTALL: Is called before the driver is removed from memory.
|
||||
; No return code required (the driver is removed from memory on return).
|
||||
;
|
||||
; and:
|
||||
;
|
||||
; SER_CLOSE: Close the port and disable interrupts. Called without parameters.
|
||||
; Must return an SER_ERR_xx code in a/x.
|
||||
|
||||
SER_INSTALL:
|
||||
SER_UNINSTALL:
|
||||
SER_CLOSE:
|
||||
; Check if this is a IIgs (Apple II Miscellaneous TechNote #7,
|
||||
; Apple II Family Identification)
|
||||
sec
|
||||
bit $C082
|
||||
jsr $FE1F
|
||||
bit $C080
|
||||
|
||||
bcc IIgs
|
||||
|
||||
lda #SER_ERR_NO_DEVICE ; Not a IIgs
|
||||
ldx #>$0000
|
||||
rts
|
||||
|
||||
IIgs:
|
||||
ldx Opened ; Check for open port
|
||||
beq :+
|
||||
|
||||
ldx Channel
|
||||
|
||||
php ; Deactivate interrupts
|
||||
sei ; if enabled
|
||||
|
||||
ldy #WR_MASTER_IRQ_RST
|
||||
lda #MASTER_IRQ_SHUTDOWN
|
||||
jsr writeSCCReg
|
||||
|
||||
ldy #WR_TX_RX_MODE_CTRL
|
||||
lda #TX_RX_MODE_OFF
|
||||
jsr writeSCCReg
|
||||
|
||||
; Reset SerFlag to what it was
|
||||
lda SerFlagOrig
|
||||
sta SER_FLAG
|
||||
|
||||
lda SCCBDATA
|
||||
|
||||
; Clear external interrupts (twice)
|
||||
ldy #WR_INIT_CTRL
|
||||
lda #INIT_CTRL_CLEAR_EIRQ
|
||||
jsr writeSCCReg
|
||||
jsr writeSCCReg
|
||||
|
||||
; Reset MIE for firmware use
|
||||
ldy #WR_MASTER_IRQ_RST
|
||||
lda #MASTER_IRQ_MIE_RST
|
||||
jsr writeSCCReg
|
||||
|
||||
ldx #$00
|
||||
stx Opened ; Mark port as closed
|
||||
|
||||
plp ; Reenable interrupts if needed
|
||||
: txa ; Promote char return value
|
||||
rts
|
||||
|
||||
getClockSource:
|
||||
.assert SER_PARAMS::BAUDRATE = 0, error
|
||||
lda (ptr1) ; Baudrate index - cc65 value
|
||||
cmp #SER_BAUD_115200
|
||||
lda #$00
|
||||
adc #$00
|
||||
sta CurClockSource ; 0 = BRG, 1 = RTxC
|
||||
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:
|
||||
php ; Deactivate interrupts
|
||||
sei ; if enabled
|
||||
|
||||
; Check if the handshake setting is valid
|
||||
ldy #SER_PARAMS::HANDSHAKE ; Handshake
|
||||
lda (ptr1),y
|
||||
cmp #SER_HS_SW ; Not supported
|
||||
beq InvParam
|
||||
|
||||
sta HSType ; Store flow control type
|
||||
|
||||
; Initialize buffers
|
||||
ldy #$00
|
||||
sty Stopped
|
||||
sty RecvHead
|
||||
sty RecvTail
|
||||
sty SendHead
|
||||
sty SendTail
|
||||
dey ; Y = 255
|
||||
sty RecvFreeCnt
|
||||
sty SendFreeCnt
|
||||
|
||||
ldx Channel
|
||||
|
||||
ldy #RR_INIT_STATUS ; Hit rr0 once to sync up
|
||||
jsr readSSCReg
|
||||
|
||||
ldy #WR_MISC_CTRL ; WR14: Turn everything off
|
||||
lda #$00
|
||||
jsr writeSCCReg
|
||||
|
||||
jsr getClockSource ; Should we use BRG or RTxC?
|
||||
|
||||
ldy #SER_PARAMS::STOPBITS ; WR4 setup: clock mult., stop & parity
|
||||
lda (ptr1),y ; Stop bits
|
||||
tay
|
||||
lda StopTable,y ; Get value
|
||||
|
||||
pha
|
||||
ldy #SER_PARAMS::PARITY
|
||||
lda (ptr1),y ; Parity bits
|
||||
tay
|
||||
pla
|
||||
ora ParityTable,y ; Get value
|
||||
bmi InvParam
|
||||
|
||||
ldy CurClockSource ; Clock multiplier
|
||||
ora ClockMultiplier,y
|
||||
|
||||
ldy #WR_TX_RX_CTRL
|
||||
jsr writeSCCReg ; End of WR4 setup
|
||||
|
||||
ldy CurClockSource ; WR11 setup: clock source
|
||||
cpx #CHANNEL_B
|
||||
beq SetClock
|
||||
iny ; Shift to get correct ClockSource val
|
||||
iny ; depending on our channel
|
||||
|
||||
SetClock:
|
||||
lda ClockSource,y
|
||||
ldy #WR_CLOCK_CTRL
|
||||
jsr writeSCCReg ; End of WR11 setup
|
||||
|
||||
lda ChanIrqFlags,x ; Store which IRQ bits we'll check
|
||||
sta CurChanIrqFlags
|
||||
|
||||
SetBaud:
|
||||
.assert SER_PARAMS::BAUDRATE = 0, error
|
||||
lda (ptr1) ; Baudrate index - cc65 value
|
||||
asl
|
||||
tay
|
||||
|
||||
lda BaudTable,y ; Get low byte of register value
|
||||
bpl BaudOK ; Verify baudrate is supported
|
||||
|
||||
InvParam:
|
||||
lda #SER_ERR_INIT_FAILED
|
||||
ldy #$00 ; Mark port closed
|
||||
bra SetupOut
|
||||
|
||||
BaudOK:
|
||||
phy ; WR12 setup: BRG time constant, low byte
|
||||
ldy #WR_BAUDL_CTRL ; Setting WR12 & 13 is useless if we're using
|
||||
jsr writeSCCReg ; RTxC, but doing it anyway makes code smaller
|
||||
ply
|
||||
|
||||
iny
|
||||
lda BaudTable,y ; WR13 setup: BRG time constant, high byte
|
||||
ldy #WR_BAUDH_CTRL
|
||||
jsr writeSCCReg
|
||||
|
||||
ldy CurClockSource ; WR14 setup: BRG enabling
|
||||
lda BrgEnabled,y
|
||||
ldy #WR_MISC_CTRL ; Time to turn this thing on
|
||||
jsr writeSCCReg
|
||||
|
||||
ldy #SER_PARAMS::DATABITS ; WR3 setup: RX data bits
|
||||
lda (ptr1),y
|
||||
tay
|
||||
lda RxBitTable,y
|
||||
ora #RX_CTRL_ON ; and turn receiver on
|
||||
|
||||
phy
|
||||
ldy #WR_RX_CTRL
|
||||
jsr writeSCCReg ; End of WR3 setup
|
||||
ply
|
||||
|
||||
lda TxBitTable,y ; WR5 setup: TX data bits
|
||||
ora #TX_CTRL_ON ; and turn transmitter on
|
||||
and #TX_DTR_ON ; and turn DTR on
|
||||
|
||||
sta RtsOff ; Save value for flow control
|
||||
|
||||
ora #TX_RTS_ON ; and turn RTS on
|
||||
|
||||
ldy #WR_TX_CTRL
|
||||
jsr writeSCCReg ; End of WR5 setup
|
||||
|
||||
ldy #WR_IRQ_CTRL ; WR15 setup: IRQ
|
||||
lda #IRQ_CLEANUP_EIRQ
|
||||
jsr writeSCCReg
|
||||
|
||||
ldy #WR_INIT_CTRL ; WR0 setup: clear existing IRQs
|
||||
lda #INIT_CTRL_CLEAR_EIRQ
|
||||
jsr writeSCCReg ; Clear (write twice)
|
||||
jsr writeSCCReg
|
||||
|
||||
ldy #WR_TX_RX_MODE_CTRL ; WR1 setup: Activate RX IRQ
|
||||
lda #TX_RX_MODE_RXIRQ
|
||||
jsr writeSCCReg
|
||||
|
||||
lda SCCBREG ; WR9 setup: Activate master IRQ
|
||||
ldy #WR_MASTER_IRQ_RST
|
||||
lda #MASTER_IRQ_SET
|
||||
jsr writeSCCReg
|
||||
|
||||
lda SER_FLAG ; Get SerFlag's current value
|
||||
sta SerFlagOrig ; and save it
|
||||
|
||||
ora ChanIrqMask,x ; Tell firmware which channel IRQs we want
|
||||
sta SER_FLAG
|
||||
|
||||
ldy #$01 ; Mark port opened
|
||||
lda #SER_ERR_OK
|
||||
|
||||
SetupOut:
|
||||
plp ; Reenable interrupts if needed
|
||||
ldx #>$0000
|
||||
sty Opened
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; SER_GET: Will fetch a character from the receive buffer and store it into the
|
||||
; variable pointed to by ptr1. If no data is available, SER_ERR_NO_DATA is
|
||||
; returned.
|
||||
|
||||
SER_GET:
|
||||
ldx Channel
|
||||
|
||||
lda RecvFreeCnt ; Check for buffer empty
|
||||
cmp #$FF
|
||||
beq NoData
|
||||
|
||||
ldy Stopped ; Check for flow stopped
|
||||
beq :+
|
||||
cmp #63 ; Enough free?
|
||||
bcc :+
|
||||
stz Stopped ; Release flow control
|
||||
|
||||
lda RtsOff
|
||||
ora #TX_RTS_ON
|
||||
|
||||
ldy #WR_TX_CTRL
|
||||
jsr writeSCCReg
|
||||
|
||||
: ldy RecvHead ; Get byte from buffer
|
||||
lda RecvBuf,y
|
||||
inc RecvHead
|
||||
inc RecvFreeCnt
|
||||
sta (ptr1)
|
||||
lda #SER_ERR_OK
|
||||
.assert SER_ERR_OK = 0, error
|
||||
tax
|
||||
rts
|
||||
NoData:
|
||||
lda #SER_ERR_NO_DATA
|
||||
ldx #>$0000
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; SER_PUT: Output character in A.
|
||||
; Must return an SER_ERR_xx code in a/x.
|
||||
|
||||
SER_PUT:
|
||||
ldx Channel
|
||||
|
||||
ldy SendFreeCnt ; Anything to send first?
|
||||
iny ; Y = $FF?
|
||||
beq :+
|
||||
pha
|
||||
lda #$00 ; TryHard = false
|
||||
jsr TryToSend
|
||||
pla
|
||||
|
||||
: ldy SendFreeCnt ; Do we have room to store byte?
|
||||
bne :+
|
||||
lda #SER_ERR_OVERFLOW
|
||||
ldx #>$0000
|
||||
rts
|
||||
|
||||
: ldy SendTail ; Put byte into send buffer & send
|
||||
sta SendBuf,y
|
||||
inc SendTail
|
||||
dec SendFreeCnt
|
||||
lda #$FF ; TryHard = true
|
||||
jsr TryToSend
|
||||
lda #SER_ERR_OK
|
||||
.assert SER_ERR_OK = 0, error
|
||||
tax ; Promote char return value
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; SER_STATUS: Return the status in the variable pointed to by ptr1.
|
||||
; Must return an SER_ERR_xx code in a/x.
|
||||
; We provide the read register 0, containing interesting info like
|
||||
; INIT_STATUS_READY (hardware handshake status) or INIT_STATUS_RTS
|
||||
; (ready to send).
|
||||
|
||||
SER_STATUS:
|
||||
ldx Channel
|
||||
ldy #RR_INIT_STATUS
|
||||
jsr readSSCReg
|
||||
ldx #$00
|
||||
sta (ptr1)
|
||||
.assert SER_ERR_OK = 0, error
|
||||
txa
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; SER_IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
|
||||
; specific data in ptr1, and the ioctl code in A.
|
||||
; Sets communication channel A or B (A = 1, B = 0)
|
||||
; Must return an SER_ERR_xx code in a/x.
|
||||
|
||||
SER_IOCTL:
|
||||
ora ptr1+1 ; Check data msb and code to be 0
|
||||
bne :+
|
||||
|
||||
ldx ptr1 ; Check data lsb to be 0 or 1
|
||||
bmi :+
|
||||
cpx #$02
|
||||
bcs :+
|
||||
|
||||
stx Channel
|
||||
.assert SER_ERR_OK = 0, error
|
||||
tax ; Promote char return value
|
||||
rts
|
||||
|
||||
: lda #SER_ERR_INV_IOCTL
|
||||
ldx #>$0000
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; SER_IRQ: Called from the builtin runtime IRQ handler as a subroutine. All
|
||||
; registers are already saved, no parameters are passed, but the carry flag
|
||||
; is clear on entry. The routine must return with carry set if the interrupt
|
||||
; was handled, otherwise with carry clear.
|
||||
|
||||
SER_IRQ:
|
||||
ldy #RR_INTR_PENDING_STATUS ; IRQ status is always in A reg
|
||||
sty SCCAREG
|
||||
lda SCCAREG
|
||||
|
||||
and CurChanIrqFlags ; Is this ours?
|
||||
beq Done
|
||||
|
||||
and #INTR_IS_RX ; Is this an RX irq?
|
||||
beq CheckSpecial
|
||||
|
||||
ldx Channel
|
||||
beq ReadBdata
|
||||
lda SCCADATA
|
||||
bra ReadDone
|
||||
ReadBdata:
|
||||
lda SCCBDATA ; Get byte
|
||||
ReadDone:
|
||||
ldx RecvFreeCnt ; Check if we have free space left
|
||||
beq Flow ; Jump if no space in receive buffer
|
||||
ldy RecvTail ; Load buffer pointer
|
||||
sta RecvBuf,y ; Store received byte in buffer
|
||||
inc RecvTail ; Increment buffer pointer
|
||||
dec RecvFreeCnt ; Decrement free space counter
|
||||
cpx #33
|
||||
bcc Flow ; Assert flow control if buffer space low
|
||||
rts ; Interrupt handled (carry already set)
|
||||
|
||||
CheckSpecial:
|
||||
; Always check IRQ special flags from Channel B (Ref page 5-24)
|
||||
ldy #RR_IRQ_STATUS
|
||||
sty SCCBREG
|
||||
lda SCCBREG
|
||||
|
||||
and #IRQ_MASQ
|
||||
cmp #IRQ_SPECIAL
|
||||
beq Special
|
||||
|
||||
; Clear exint
|
||||
ldx Channel
|
||||
ldy #WR_INIT_CTRL
|
||||
lda #INIT_CTRL_CLEAR_EIRQ
|
||||
jsr writeSCCReg
|
||||
|
||||
sec
|
||||
rts
|
||||
|
||||
Flow: lda HSType ; Don't touch if no flow control
|
||||
beq IRQDone
|
||||
|
||||
ldx Channel ; Assert flow control if buffer space too low
|
||||
ldy #WR_TX_CTRL
|
||||
lda RtsOff
|
||||
jsr writeSCCReg
|
||||
|
||||
sta Stopped
|
||||
IRQDone:sec ; Interrupt handled
|
||||
Done: rts
|
||||
|
||||
Special:ldx Channel
|
||||
ldy #RR_SPEC_COND_STATUS
|
||||
jsr readSSCReg
|
||||
|
||||
tax
|
||||
and #SPEC_COND_FRAMING_ERR
|
||||
bne BadChar
|
||||
txa
|
||||
and #SPEC_COND_OVERRUN_ERR
|
||||
beq BadChar
|
||||
|
||||
ldy #WR_INIT_CTRL
|
||||
lda #INIT_CTRL_CLEAR_ERR
|
||||
jsr writeSCCReg
|
||||
|
||||
sec
|
||||
rts
|
||||
|
||||
BadChar:
|
||||
cpx #CHANNEL_B
|
||||
beq BadCharB
|
||||
lda SCCADATA
|
||||
bra BadCharDone
|
||||
BadCharB:
|
||||
lda SCCBDATA ; Remove char in error
|
||||
BadCharDone:
|
||||
sec
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Try to send a byte. Internal routine. A = TryHard, X = Channel
|
||||
|
||||
TryToSend:
|
||||
sta tmp1 ; Remember tryHard flag
|
||||
Again: lda SendFreeCnt ; Anything to send?
|
||||
cmp #$FF
|
||||
beq Quit ; No
|
||||
|
||||
lda Stopped ; Check for flow stopped
|
||||
bne Quit ; Bail out if it is
|
||||
|
||||
Wait:
|
||||
ldy #RR_INIT_STATUS
|
||||
jsr readSSCReg ; Check that we're ready to send
|
||||
tay
|
||||
and #INIT_STATUS_READY
|
||||
beq NotReady
|
||||
|
||||
tya
|
||||
and #INIT_STATUS_RTS ; Ready to send
|
||||
bne Send
|
||||
|
||||
NotReady:
|
||||
bit tmp1 ; Keep trying if must try hard
|
||||
bmi Wait
|
||||
Quit: rts
|
||||
|
||||
Send: ldy SendHead ; Send byte
|
||||
lda SendBuf,y
|
||||
|
||||
cpx #CHANNEL_B
|
||||
beq WriteBdata
|
||||
sta SCCADATA
|
||||
bra WriteDone
|
||||
WriteBdata:
|
||||
sta SCCBDATA
|
||||
WriteDone:
|
||||
inc SendHead
|
||||
inc SendFreeCnt
|
||||
jmp Again ; Continue flushing TX buffer
|
||||
@@ -26,6 +26,7 @@
|
||||
.include "ser-error.inc"
|
||||
|
||||
.macpack module
|
||||
.macpack cpu
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Header. Includes jump table
|
||||
@@ -37,8 +38,8 @@
|
||||
.endif
|
||||
|
||||
; Driver signature
|
||||
.byte $73, $65, $72 ; "ser"
|
||||
.byte SER_API_VERSION ; Serial API version number
|
||||
.byte $73, $65, $72 ; "ser"
|
||||
.byte SER_API_VERSION ; Serial API version number
|
||||
|
||||
; Library reference
|
||||
.addr $0000
|
||||
@@ -57,13 +58,19 @@
|
||||
;----------------------------------------------------------------------------
|
||||
; I/O definitions
|
||||
|
||||
.if (.cpu .bitand CPU_ISET_65C02)
|
||||
ACIA := $C088
|
||||
.else
|
||||
Offset = $8F ; Move 6502 false read out of I/O to page $BF
|
||||
ACIA := $C088-Offset
|
||||
.endif
|
||||
|
||||
ACIA = $C088-Offset
|
||||
ACIA_DATA = ACIA+0 ; Data register
|
||||
ACIA_STATUS = ACIA+1 ; Status register
|
||||
ACIA_CMD = ACIA+2 ; Command register
|
||||
ACIA_CTRL = ACIA+3 ; Control register
|
||||
ACIA_DATA := ACIA+0 ; Data register
|
||||
ACIA_STATUS := ACIA+1 ; Status register
|
||||
ACIA_CMD := ACIA+2 ; Command register
|
||||
ACIA_CTRL := ACIA+3 ; Control register
|
||||
|
||||
SLTROMSEL := $C02D ; For Apple IIgs slot verification
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Global variables
|
||||
@@ -72,16 +79,18 @@ ACIA_CTRL = ACIA+3 ; Control register
|
||||
|
||||
RecvHead: .res 1 ; Head of receive buffer
|
||||
RecvTail: .res 1 ; Tail of receive buffer
|
||||
RecvFreeCnt: .res 1 ; Number of bytes in receive buffer
|
||||
RecvFreeCnt: .res 1 ; Number of free bytes in receive buffer
|
||||
SendHead: .res 1 ; Head of send buffer
|
||||
SendTail: .res 1 ; Tail of send buffer
|
||||
SendFreeCnt: .res 1 ; Number of bytes in send buffer
|
||||
SendFreeCnt: .res 1 ; Number of free bytes in send buffer
|
||||
|
||||
Stopped: .res 1 ; Flow-stopped flag
|
||||
RtsOff: .res 1 ;
|
||||
RtsOff: .res 1 ; Cached value of command register with
|
||||
; flow stopped
|
||||
HSType: .res 1 ; Flow-control type
|
||||
|
||||
RecvBuf: .res 256 ; Receive buffers: 256 bytes
|
||||
SendBuf: .res 256 ; Send buffers: 256 bytes
|
||||
RecvBuf: .res 256 ; Receive buffer: 256 bytes
|
||||
SendBuf: .res 256 ; Send buffer: 256 bytes
|
||||
|
||||
Index: .res 1 ; I/O register index
|
||||
|
||||
@@ -91,8 +100,9 @@ Slot: .byte $02 ; Default to SSC in slot 2
|
||||
|
||||
.rodata
|
||||
|
||||
; Tables used to translate RS232 params into register values
|
||||
BaudTable: ; bit7 = 1 means setting is invalid
|
||||
BaudTable: ; Table used to translate RS232 baudrate param
|
||||
; into control register value
|
||||
; bit7 = 1 means setting is invalid
|
||||
.byte $FF ; SER_BAUD_45_5
|
||||
.byte $01 ; SER_BAUD_50
|
||||
.byte $02 ; SER_BAUD_75
|
||||
@@ -111,32 +121,44 @@ BaudTable: ; bit7 = 1 means setting is invalid
|
||||
.byte $0F ; SER_BAUD_19200
|
||||
.byte $FF ; SER_BAUD_38400
|
||||
.byte $FF ; SER_BAUD_57600
|
||||
.byte $FF ; SER_BAUD_115200
|
||||
.byte $00 ; SER_BAUD_115200
|
||||
.byte $FF ; SER_BAUD_230400
|
||||
BitTable:
|
||||
|
||||
BitTable: ; Table used to translate RS232 databits param
|
||||
; into control register value
|
||||
.byte $60 ; SER_BITS_5
|
||||
.byte $40 ; SER_BITS_6
|
||||
.byte $20 ; SER_BITS_7
|
||||
.byte $00 ; SER_BITS_8
|
||||
StopTable:
|
||||
|
||||
StopTable: ; Table used to translate RS232 stopbits param
|
||||
; into control register value
|
||||
.byte $00 ; SER_STOP_1
|
||||
.byte $80 ; SER_STOP_2
|
||||
ParityTable:
|
||||
|
||||
ParityTable: ; Table used to translate RS232 parity param
|
||||
; into command register value
|
||||
.byte $00 ; SER_PAR_NONE
|
||||
.byte $20 ; SER_PAR_ODD
|
||||
.byte $60 ; SER_PAR_EVEN
|
||||
.byte $A0 ; SER_PAR_MARK
|
||||
.byte $E0 ; SER_PAR_SPACE
|
||||
IdOfsTable:
|
||||
|
||||
IdOfsTable: ; Table of bytes positions, used to check four
|
||||
; specific bytes on the slot's firmware to make
|
||||
; sure this is a serial card.
|
||||
.byte $05 ; Pascal 1.0 ID byte
|
||||
.byte $07 ; Pascal 1.0 ID byte
|
||||
.byte $0B ; Pascal 1.1 generic signature byte
|
||||
.byte $0C ; Device signature byte
|
||||
IdValTable:
|
||||
.byte $38 ; Fixed
|
||||
.byte $18 ; Fixed
|
||||
.byte $01 ; Fixed
|
||||
.byte $31 ; Serial or parallel I/O card type 1
|
||||
|
||||
IdValTable: ; Table of expected values for the four checked
|
||||
; bytes
|
||||
.byte $38 ; ID Byte 0 (from Pascal 1.0), fixed
|
||||
.byte $18 ; ID Byte 1 (from Pascal 1.0), fixed
|
||||
.byte $01 ; Generic signature for Pascal 1.1, fixed
|
||||
.byte $31 ; Device signature byte (serial or
|
||||
; parallel I/O card type 1)
|
||||
|
||||
IdTableLen = * - IdValTable
|
||||
|
||||
@@ -163,12 +185,10 @@ SER_CLOSE:
|
||||
ldx Index ; Check for open port
|
||||
beq :+
|
||||
|
||||
; Deactivate DTR and disable 6551 interrupts
|
||||
lda #%00001010
|
||||
lda #%00001010 ; Deactivate DTR and disable 6551 interrupts
|
||||
sta ACIA_CMD,x
|
||||
|
||||
; Done, return an error code
|
||||
: lda #SER_ERR_OK
|
||||
: lda #SER_ERR_OK ; Done, return an error code
|
||||
.assert SER_ERR_OK = 0, error
|
||||
tax
|
||||
stx Index ; Mark port as closed
|
||||
@@ -177,104 +197,155 @@ SER_CLOSE:
|
||||
;----------------------------------------------------------------------------
|
||||
; SER_OPEN: A pointer to a ser_params structure is passed in ptr1.
|
||||
; Must return an SER_ERR_xx code in a/x.
|
||||
; Note: Hardware checks are done in SER_OPEN instead of SER_INSTALL,
|
||||
; because they depend on the selected slot, and we can't select the slot
|
||||
; before SER_INSTALL.
|
||||
|
||||
SER_OPEN:
|
||||
ldx #<$C000
|
||||
; Check if this is a IIgs (Apple II Miscellaneous TechNote #7,
|
||||
; Apple II Family Identification)
|
||||
sec
|
||||
bit $C082
|
||||
jsr $FE1F
|
||||
bit $C080
|
||||
|
||||
bcs NotIIgs
|
||||
|
||||
; We're on a IIgs. For every slot N, either bit N of $C02D is
|
||||
; 0 for the internal ROM, or 1 for "Your Card". Let's make sure
|
||||
; that slot N's bit is set to 1, otherwise, that can't be an SSC.
|
||||
|
||||
ldy Slot
|
||||
lda SLTROMSEL
|
||||
: lsr
|
||||
dey
|
||||
bpl :- ; Shift until slot's bit ends in carry
|
||||
bcc NoDev
|
||||
|
||||
NotIIgs:ldx #<$C000
|
||||
stx ptr2
|
||||
lda #>$C000
|
||||
ora Slot
|
||||
sta ptr2+1
|
||||
|
||||
; Check Pascal 1.1 Firmware Protocol ID bytes
|
||||
: ldy IdOfsTable,x
|
||||
: ldy IdOfsTable,x ; Check Pascal 1.1 Firmware Protocol ID bytes
|
||||
lda IdValTable,x
|
||||
cmp (ptr2),y
|
||||
bne NoDevice
|
||||
bne NoDev
|
||||
inx
|
||||
cpx #IdTableLen
|
||||
bcc :-
|
||||
|
||||
; Convert slot to I/O register index
|
||||
lda Slot
|
||||
lda Slot ; Convert slot to I/O register index
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
adc #Offset ; Assume carry to be clear
|
||||
.if .not (.cpu .bitand CPU_ISET_65C02)
|
||||
adc #Offset ; Assume carry to be clear
|
||||
.endif
|
||||
tax
|
||||
|
||||
; Check if the handshake setting is valid
|
||||
ldy #SER_PARAMS::HANDSHAKE ; Handshake
|
||||
lda (ptr1),y
|
||||
cmp #SER_HS_HW ; This is all we support
|
||||
bne InvParam
|
||||
; Check that this works like an ACIA 6551 is expected to work
|
||||
|
||||
; Initialize buffers
|
||||
ldy #$00
|
||||
lda ACIA_STATUS,x ; Save current values in what we expect to be
|
||||
sta tmp1 ; the ACIA status register
|
||||
lda ACIA_CMD,x ; and command register. So we can restore them
|
||||
sta tmp2 ; if this isn't a 6551.
|
||||
|
||||
ldy #%00000010 ; Disable TX/RX, disable IRQ
|
||||
: tya
|
||||
sta ACIA_CMD,x
|
||||
cmp ACIA_CMD,x ; Verify what we stored is there
|
||||
bne NotAcia
|
||||
iny ; Enable TX/RX, disable IRQ
|
||||
cpy #%00000100
|
||||
bne :-
|
||||
sta ACIA_STATUS,x ; Reset ACIA
|
||||
lda ACIA_CMD,x ; Check that RX/TX is disabled
|
||||
lsr
|
||||
bcc AciaOK
|
||||
|
||||
NotAcia:lda tmp2 ; Restore original values
|
||||
sta ACIA_CMD,x
|
||||
lda tmp1
|
||||
sta ACIA_STATUS,x
|
||||
|
||||
NoDev: lda #SER_ERR_NO_DEVICE
|
||||
bne Out
|
||||
|
||||
; Check if the handshake setting is valid
|
||||
AciaOK: ldy #SER_PARAMS::HANDSHAKE
|
||||
lda (ptr1),y
|
||||
cmp #SER_HS_SW ; Not supported
|
||||
bne HandshakeOK
|
||||
|
||||
lda #SER_ERR_INIT_FAILED
|
||||
bne Out
|
||||
|
||||
HandshakeOK:
|
||||
sta HSType ; Store flow control type
|
||||
|
||||
ldy #$00 ; Initialize buffers
|
||||
sty Stopped
|
||||
sty RecvHead
|
||||
sty RecvTail
|
||||
sty SendHead
|
||||
sty SendTail
|
||||
dey ; Y = 255
|
||||
dey ; Y = 255
|
||||
sty RecvFreeCnt
|
||||
sty SendFreeCnt
|
||||
|
||||
; Set the value for the control register, which contains stop bits,
|
||||
; word length and the baud rate.
|
||||
ldy #SER_PARAMS::BAUDRATE
|
||||
lda (ptr1),y ; Baudrate index
|
||||
lda (ptr1),y ; Baudrate index
|
||||
tay
|
||||
lda BaudTable,y ; Get 6551 value
|
||||
bmi InvBaud ; Branch if rate not supported
|
||||
sta tmp1
|
||||
lda BaudTable,y ; Get 6551 value
|
||||
sta tmp2 ; Backup for IRQ setting
|
||||
bpl BaudOK ; Check that baudrate is supported
|
||||
|
||||
ldy #SER_PARAMS::DATABITS ; Databits
|
||||
lda (ptr1),y
|
||||
lda #SER_ERR_BAUD_UNAVAIL
|
||||
bne Out
|
||||
|
||||
BaudOK: sta tmp1
|
||||
ldy #SER_PARAMS::DATABITS
|
||||
lda (ptr1),y ; Databits index
|
||||
tay
|
||||
lda BitTable,y
|
||||
lda BitTable,y ; Get 6551 value
|
||||
ora tmp1
|
||||
sta tmp1
|
||||
|
||||
ldy #SER_PARAMS::STOPBITS ; Stopbits
|
||||
lda (ptr1),y
|
||||
ldy #SER_PARAMS::STOPBITS
|
||||
lda (ptr1),y ; Stopbits index
|
||||
tay
|
||||
lda StopTable,y
|
||||
lda StopTable,y ; Get 6551 value
|
||||
ora tmp1
|
||||
ora #%00010000 ; Receiver clock source = baudrate
|
||||
ora #%00010000 ; Set receiver clock source = baudrate
|
||||
sta ACIA_CTRL,x
|
||||
|
||||
; Set the value for the command register. We remember the base value
|
||||
; in RtsOff, since we will have to manipulate ACIA_CMD often.
|
||||
ldy #SER_PARAMS::PARITY ; Parity
|
||||
lda (ptr1),y
|
||||
ldy #SER_PARAMS::PARITY
|
||||
lda (ptr1),y ; Parity index
|
||||
tay
|
||||
lda ParityTable,y
|
||||
ora #%00000001 ; DTR active
|
||||
sta RtsOff
|
||||
ora #%00001000 ; Enable receive interrupts
|
||||
sta ACIA_CMD,x
|
||||
lda ParityTable,y ; Get 6551 value
|
||||
|
||||
ora #%00000001 ; Set DTR active
|
||||
sta RtsOff ; Store value to easily handle flow control later
|
||||
|
||||
ora #%00001010 ; Disable interrupts and set RTS low
|
||||
|
||||
ldy tmp2 ; Don't enable IRQs if 115200bps
|
||||
beq :+
|
||||
and #%11111101 ; Enable receive IRQs
|
||||
: sta ACIA_CMD,x
|
||||
|
||||
; Done
|
||||
stx Index ; Mark port as open
|
||||
stx Index ; Mark port as open
|
||||
lda #SER_ERR_OK
|
||||
.assert SER_ERR_OK = 0, error
|
||||
tax
|
||||
rts
|
||||
|
||||
; Device (hardware) not found
|
||||
NoDevice:lda #SER_ERR_NO_DEVICE
|
||||
ldx #0 ; return value is char
|
||||
rts
|
||||
|
||||
; Invalid parameter
|
||||
InvParam:lda #SER_ERR_INIT_FAILED
|
||||
ldx #0 ; return value is char
|
||||
rts
|
||||
|
||||
; Baud rate not available
|
||||
InvBaud:lda #SER_ERR_BAUD_UNAVAIL
|
||||
ldx #0 ; return value is char
|
||||
Out:
|
||||
ldx #>$0000
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
@@ -284,38 +355,38 @@ InvBaud:lda #SER_ERR_BAUD_UNAVAIL
|
||||
|
||||
SER_GET:
|
||||
ldx Index
|
||||
ldy SendFreeCnt ; Send data if necessary
|
||||
iny ; Y == $FF?
|
||||
beq :+
|
||||
lda #$00 ; TryHard = false
|
||||
jsr TryToSend
|
||||
|
||||
; Check for buffer empty
|
||||
: lda RecvFreeCnt ; (25)
|
||||
lda RecvFreeCnt ; Check for buffer empty
|
||||
cmp #$FF
|
||||
bne :+
|
||||
lda #SER_ERR_NO_DATA
|
||||
ldx #0 ; return value is char
|
||||
ldx #>$0000
|
||||
rts
|
||||
|
||||
; Check for flow stopped & enough free: release flow control
|
||||
: ldy Stopped ; (34)
|
||||
: ldy Stopped ; Check for flow stopped
|
||||
beq :+
|
||||
cmp #63
|
||||
cmp #63 ; Enough free?
|
||||
bcc :+
|
||||
.if (.cpu .bitand CPU_ISET_65C02)
|
||||
stz Stopped ; Release flow control
|
||||
.else
|
||||
lda #$00
|
||||
sta Stopped
|
||||
.endif
|
||||
lda RtsOff
|
||||
ora #%00001000
|
||||
sta ACIA_CMD,x
|
||||
|
||||
; Get byte from buffer
|
||||
: ldy RecvHead ; (41)
|
||||
: ldy RecvHead ; Get byte from buffer
|
||||
lda RecvBuf,y
|
||||
inc RecvHead
|
||||
inc RecvFreeCnt
|
||||
ldx #$00 ; (59)
|
||||
ldx #$00
|
||||
.if (.cpu .bitand CPU_ISET_65C02)
|
||||
sta (ptr1) ; Store it for caller
|
||||
.else
|
||||
sta (ptr1,x)
|
||||
.endif
|
||||
txa ; Return code = 0
|
||||
rts
|
||||
|
||||
@@ -326,28 +397,26 @@ SER_GET:
|
||||
SER_PUT:
|
||||
ldx Index
|
||||
|
||||
; Try to send
|
||||
ldy SendFreeCnt
|
||||
iny ; Y = $FF?
|
||||
ldy SendFreeCnt ; Anything to send first?
|
||||
cpy #$FF ; No
|
||||
beq :+
|
||||
pha
|
||||
lda #$00 ; TryHard = false
|
||||
jsr TryToSend
|
||||
jsr TryToSend ; Try to flush send buffer
|
||||
pla
|
||||
|
||||
; Put byte into send buffer & send
|
||||
: ldy SendFreeCnt
|
||||
ldy SendFreeCnt ; Reload SendFreeCnt after TryToSend
|
||||
bne :+
|
||||
lda #SER_ERR_OVERFLOW
|
||||
ldx #0 ; return value is char
|
||||
ldx #>$0000
|
||||
rts
|
||||
|
||||
: ldy SendTail
|
||||
: ldy SendTail ; Put byte into send buffer
|
||||
sta SendBuf,y
|
||||
inc SendTail
|
||||
dec SendFreeCnt
|
||||
lda #$FF ; TryHard = true
|
||||
jsr TryToSend
|
||||
jsr TryToSend ; Flush send buffer
|
||||
lda #SER_ERR_OK
|
||||
.assert SER_ERR_OK = 0, error
|
||||
tax
|
||||
@@ -369,26 +438,25 @@ SER_STATUS:
|
||||
;----------------------------------------------------------------------------
|
||||
; SER_IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
|
||||
; specific data in ptr1, and the ioctl code in A.
|
||||
; The ioctl data is the slot number to open.
|
||||
; Must return an SER_ERR_xx code in a/x.
|
||||
|
||||
SER_IOCTL:
|
||||
; Check data msb and code to be 0
|
||||
ora ptr1+1
|
||||
ora ptr1+1 ; Check data msb and code to be 0
|
||||
bne :+
|
||||
|
||||
; Check data lsb to be [1..7]
|
||||
ldx ptr1
|
||||
ldx ptr1 ; Check data lsb to be [1..7]
|
||||
beq :+
|
||||
cpx #7+1
|
||||
bcs :+
|
||||
|
||||
stx Slot
|
||||
stx Slot ; Store slot
|
||||
.assert SER_ERR_OK = 0, error
|
||||
tax
|
||||
rts
|
||||
|
||||
: lda #SER_ERR_INV_IOCTL
|
||||
ldx #0 ; return value is char
|
||||
ldx #>$0000
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
@@ -404,22 +472,24 @@ SER_IRQ:
|
||||
and #$08
|
||||
beq Done ; Jump if no ACIA interrupt
|
||||
lda ACIA_DATA,x ; Get byte from ACIA
|
||||
ldy RecvFreeCnt ; Check if we have free space left
|
||||
ldx RecvFreeCnt ; Check if we have free space left
|
||||
beq Flow ; Jump if no space in receive buffer
|
||||
ldy RecvTail ; Load buffer pointer
|
||||
sta RecvBuf,y ; Store received byte in buffer
|
||||
inc RecvTail ; Increment buffer pointer
|
||||
dec RecvFreeCnt ; Decrement free space counter
|
||||
ldy RecvFreeCnt ; Check for buffer space low
|
||||
cpy #33
|
||||
cpx #33 ; Check for buffer space low
|
||||
bcc Flow ; Assert flow control if buffer space low
|
||||
rts ; Interrupt handled (carry already set)
|
||||
|
||||
; Assert flow control if buffer space too low
|
||||
Flow: lda RtsOff
|
||||
Flow: lda HSType ; Don't touch if no flow control
|
||||
beq IRQDone
|
||||
|
||||
ldx Index ; Assert flow control if buffer space too low
|
||||
lda RtsOff
|
||||
sta ACIA_CMD,x
|
||||
sta Stopped
|
||||
sec ; Interrupt handled
|
||||
IRQDone:sec ; Interrupt handled
|
||||
Done: rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
@@ -427,26 +497,24 @@ Done: rts
|
||||
|
||||
TryToSend:
|
||||
sta tmp1 ; Remember tryHard flag
|
||||
Again: lda SendFreeCnt
|
||||
cmp #$FF
|
||||
beq Quit ; Bail out
|
||||
NextByte:
|
||||
lda SendFreeCnt ; Is there anything to send? This can happen if
|
||||
cmp #$FF ; we got interrupted by RX while sending, and
|
||||
beq Quit ; flow control was asserted.
|
||||
|
||||
; Check for flow stopped
|
||||
lda Stopped
|
||||
bne Quit ; Bail out
|
||||
Again: lda Stopped ; Is flow stopped?
|
||||
bne Quit ; Yes, Bail out
|
||||
|
||||
; Check that ACIA is ready to send
|
||||
lda ACIA_STATUS,x
|
||||
lda ACIA_STATUS,x ; Check that ACIA is ready to send
|
||||
and #$10
|
||||
bne Send
|
||||
bne Send ; It is!
|
||||
bit tmp1 ; Keep trying if must try hard
|
||||
bmi Again
|
||||
Quit: rts
|
||||
|
||||
; Send byte and try again
|
||||
Send: ldy SendHead
|
||||
Send: ldy SendHead ; Get first byte to send
|
||||
lda SendBuf,y
|
||||
sta ACIA_DATA,x
|
||||
sta ACIA_DATA,x ; Send it
|
||||
inc SendHead
|
||||
inc SendFreeCnt
|
||||
jmp Again
|
||||
bne NextByte ; And try next one
|
||||
|
||||
29
libsrc/apple2/set_iigs_speed.s
Normal file
29
libsrc/apple2/set_iigs_speed.s
Normal file
@@ -0,0 +1,29 @@
|
||||
;
|
||||
; Colin Leroy-Mira <colin@colino.net>, 2024
|
||||
;
|
||||
; unsigned char __fastcall__ detect_iigs(unsigned char speed)
|
||||
;
|
||||
|
||||
.export _set_iigs_speed
|
||||
.import ostype, return0
|
||||
|
||||
.include "apple2.inc"
|
||||
.include "accelerator.inc"
|
||||
|
||||
_set_iigs_speed:
|
||||
tax ; Keep parameter
|
||||
lda ostype ; Return if not IIgs
|
||||
bmi :+
|
||||
jmp return0
|
||||
|
||||
: lda CYAREG
|
||||
cpx #SPEED_SLOW
|
||||
beq :+
|
||||
ora #%10000000
|
||||
bne set_speed
|
||||
: and #%01111111
|
||||
set_speed:
|
||||
sta CYAREG
|
||||
txa
|
||||
ldx #>$0000
|
||||
rts
|
||||
54
libsrc/apple2/sleep.s
Normal file
54
libsrc/apple2/sleep.s
Normal file
@@ -0,0 +1,54 @@
|
||||
;
|
||||
; Colin Leroy-Mira <colin@colino.net>, 2024
|
||||
;
|
||||
; void __fastcall__ sleep(unsigned s)
|
||||
;
|
||||
;
|
||||
|
||||
.export _sleep
|
||||
.import _get_iigs_speed
|
||||
.import _set_iigs_speed
|
||||
.import WAIT
|
||||
.importzp tmp1
|
||||
|
||||
.include "accelerator.inc"
|
||||
|
||||
; This functions uses the Apple2 WAIT ROM routine to waste a certain
|
||||
; amount of cycles and returns approximately after the numbers of
|
||||
; seconds passed in AX.
|
||||
;
|
||||
; It takes 1023730 cycles when called with AX=1 (1,0007s),
|
||||
; 10236364 cycles when called with AX=10 (10,006 seconds),
|
||||
; 306064298 cycles with AX=300 (299.2 seconds).
|
||||
;
|
||||
; Caveat: IRQs firing during calls to sleep will make the sleep longer
|
||||
; by the amount of cycles it takes to handle the IRQ.
|
||||
;
|
||||
_sleep:
|
||||
stx tmp1 ; High byte of s in X
|
||||
tay ; Low byte in A
|
||||
ora tmp1
|
||||
bne :+
|
||||
rts
|
||||
: jsr _get_iigs_speed ; Save current CPU speed
|
||||
pha
|
||||
lda #SPEED_SLOW ; Down to 1MHz for consistency around WAIT
|
||||
jsr _set_iigs_speed
|
||||
sleep_1s:
|
||||
ldx #$0A ; Loop 10 times
|
||||
sleep_100ms:
|
||||
lda #$C7 ; Sleep about 99ms
|
||||
jsr WAIT
|
||||
lda #$0D ; About 1ms
|
||||
jsr WAIT
|
||||
dex
|
||||
bne sleep_100ms
|
||||
dey
|
||||
bne sleep_1s
|
||||
dec tmp1
|
||||
bmi done
|
||||
dey ; Down to #$FF
|
||||
bne sleep_1s
|
||||
done:
|
||||
pla ; Restore CPU speed
|
||||
jmp _set_iigs_speed
|
||||
129
libsrc/apple2/stat.s
Normal file
129
libsrc/apple2/stat.s
Normal file
@@ -0,0 +1,129 @@
|
||||
;
|
||||
; Colin Leroy-Mira, 2023 <colin@colino.net>
|
||||
;
|
||||
; int __fastcall__ stat(const char *pathname, struct stat *statbuf);
|
||||
;
|
||||
|
||||
.export _stat
|
||||
.import __errno, _open,_close
|
||||
.import mli_file_info
|
||||
.import popax, pushax, pusha0, incsp2
|
||||
.include "zeropage.inc"
|
||||
.include "errno.inc"
|
||||
.include "fcntl.inc"
|
||||
.include "filedes.inc"
|
||||
.include "mli.inc"
|
||||
.include "stat.inc"
|
||||
|
||||
_stat:
|
||||
; Store statbuf pointer
|
||||
sta ptr4
|
||||
sta stbuf
|
||||
stx ptr4+1
|
||||
stx stbuf+1
|
||||
|
||||
; Clear statbuf
|
||||
lda #$00
|
||||
ldy #.sizeof(stat)-1
|
||||
: sta (ptr4),y
|
||||
dey
|
||||
bpl :-
|
||||
|
||||
; Reset errno
|
||||
sta ___errno
|
||||
|
||||
; Store pathname
|
||||
jsr popax
|
||||
jsr pushax ; Push it back for mli_file_info
|
||||
jsr pushax ; and for open
|
||||
|
||||
jsr mli_file_info
|
||||
|
||||
bcc got_info
|
||||
jmp incsp2 ; Drop filename copy for open
|
||||
|
||||
got_info:
|
||||
; st_dev
|
||||
lda DEVNUM
|
||||
lsr ; Shift right to cc65 representation
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
ldy #stat::st_dev
|
||||
sta (ptr4),y
|
||||
|
||||
; st_mode (S_IFDIR/S_IFREG only)
|
||||
lda mliparam + MLI::INFO::FILE_TYPE
|
||||
ldy #stat::st_mode
|
||||
cmp #$0f
|
||||
bne is_reg
|
||||
lda #S_IFDIR
|
||||
bne set_st_mode
|
||||
|
||||
is_reg: lda #S_IFREG
|
||||
|
||||
set_st_mode:
|
||||
sta (ptr4),y
|
||||
|
||||
; st_access through st_create_time
|
||||
ldx #MLI::INFO::ACCESS
|
||||
ldy #stat::st_access
|
||||
: lda mliparam,x
|
||||
sta (ptr4),y
|
||||
inx
|
||||
iny
|
||||
cpy #stat::st_create_time + .sizeof(stat::st_create_time)
|
||||
bne :-
|
||||
|
||||
; st_size
|
||||
lda #O_RDONLY
|
||||
jsr pusha0
|
||||
ldy #$04
|
||||
jsr _open
|
||||
cmp #$FF
|
||||
beq done
|
||||
pha ; Save file descriptor for closing
|
||||
|
||||
; Get ProDOS's REF_NUM from file descriptor
|
||||
jsr getfd
|
||||
; Get file information
|
||||
sta mliparam + MLI::EOF::REF_NUM
|
||||
lda #GET_EOF_CALL
|
||||
ldx #EOF_COUNT
|
||||
jsr callmli
|
||||
bcs eoferr
|
||||
|
||||
; Get struct stat in ptr4 back, open destroyed it
|
||||
lda stbuf
|
||||
ldx stbuf+1
|
||||
sta ptr4
|
||||
stx ptr4+1
|
||||
|
||||
; Store size
|
||||
ldy #stat::st_size
|
||||
lda mliparam + MLI::EOF::EOF
|
||||
sta (ptr4),y
|
||||
lda mliparam + MLI::EOF::EOF+1
|
||||
iny
|
||||
sta (ptr4),y
|
||||
lda mliparam + MLI::EOF::EOF+2
|
||||
iny
|
||||
sta (ptr4),y
|
||||
|
||||
; Close file
|
||||
eoferr:
|
||||
pla
|
||||
ldx #$00
|
||||
jsr _close
|
||||
|
||||
; Set return value if we had an error
|
||||
lda ___errno
|
||||
beq done
|
||||
lda #$FF
|
||||
done:
|
||||
tax ; Promote char return value
|
||||
rts
|
||||
|
||||
.bss
|
||||
|
||||
stbuf: .res 2
|
||||
123
libsrc/apple2/statvfs.s
Normal file
123
libsrc/apple2/statvfs.s
Normal file
@@ -0,0 +1,123 @@
|
||||
;
|
||||
; Colin Leroy-Mira, 2023 <colin@colino.net>
|
||||
;
|
||||
; int __fastcall__ statvfs(const char *pathname, struct statvfs *statvfsbuf);
|
||||
;
|
||||
|
||||
.export _statvfs
|
||||
.import _dio_query_sectsize
|
||||
.import mli_file_info, pushax, popax, popptr1, pushptr1
|
||||
.include "zeropage.inc"
|
||||
.include "apple2.inc"
|
||||
.include "errno.inc"
|
||||
.include "mli.inc"
|
||||
.include "statvfs.inc"
|
||||
|
||||
_statvfs:
|
||||
; Store statbuf
|
||||
sta ptr4
|
||||
stx ptr4+1
|
||||
|
||||
; Clear statbuf
|
||||
lda #$00
|
||||
ldy #.sizeof(statvfs)-1
|
||||
: sta (ptr4),y
|
||||
dey
|
||||
bpl :-
|
||||
|
||||
; Store pathname, keeping only volume name
|
||||
jsr popptr1
|
||||
ldy #$00
|
||||
sty vol_sep
|
||||
lda (ptr1),y
|
||||
cmp #'/' ; Is the path absolute?
|
||||
beq :+
|
||||
lda #EINVAL
|
||||
jmp ___directerrno
|
||||
|
||||
: iny
|
||||
lda (ptr1),y
|
||||
beq :+ ; End of string, no other /
|
||||
cpy #FILENAME_MAX
|
||||
beq :+ ; Max filename length reached
|
||||
cmp #'/'
|
||||
bne :- ; Not a slash, keep looking
|
||||
sty vol_sep ; Register '/' index
|
||||
lda #$00
|
||||
sta (ptr1),y ; Cut pathname at first slash
|
||||
: jsr pushptr1
|
||||
|
||||
jsr mli_file_info
|
||||
|
||||
php
|
||||
ldy vol_sep ; Put slash back in pathname
|
||||
lda #'/'
|
||||
sta (ptr1),y
|
||||
plp
|
||||
|
||||
bcc got_info
|
||||
|
||||
jmp ___mappederrno
|
||||
|
||||
got_info:
|
||||
; f_fsid
|
||||
lda DEVNUM
|
||||
lsr ; Shift right to cc65 representation
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
ldy #statvfs::f_fsid
|
||||
sta (ptr4),y
|
||||
|
||||
; total number of blocks
|
||||
lda mliparam + MLI::INFO::AUX_TYPE
|
||||
ldy #statvfs::f_blocks
|
||||
sta (ptr4),y
|
||||
lda mliparam + MLI::INFO::AUX_TYPE+1
|
||||
iny
|
||||
sta (ptr4),y
|
||||
|
||||
; blocks free & avail
|
||||
sec
|
||||
lda mliparam + MLI::INFO::AUX_TYPE
|
||||
sbc mliparam + MLI::INFO::BLOCKS
|
||||
ldy #statvfs::f_bfree
|
||||
sta (ptr4),y
|
||||
ldy #statvfs::f_bavail
|
||||
sta (ptr4),y
|
||||
|
||||
lda mliparam + MLI::INFO::AUX_TYPE+1
|
||||
sbc mliparam + MLI::INFO::BLOCKS+1
|
||||
iny
|
||||
sta (ptr4),y
|
||||
ldy #statvfs::f_bfree+1
|
||||
sta (ptr4),y
|
||||
|
||||
; block sizes
|
||||
jsr _dio_query_sectsize
|
||||
; low bytes
|
||||
ldy #statvfs::f_bsize
|
||||
sta (ptr4),y
|
||||
ldy #statvfs::f_frsize
|
||||
sta (ptr4),y
|
||||
; f_frsize high byte
|
||||
iny
|
||||
txa
|
||||
sta (ptr4),y
|
||||
; f_bsize high byte
|
||||
ldy #statvfs::f_bsize+1
|
||||
sta (ptr4),y
|
||||
|
||||
; f_namemax
|
||||
lda #FILENAME_MAX
|
||||
ldy #statvfs::f_namemax
|
||||
sta (ptr4),y
|
||||
|
||||
lda #$00
|
||||
sta ___errno
|
||||
tax
|
||||
rts
|
||||
|
||||
.bss
|
||||
|
||||
vol_sep:.res 1
|
||||
@@ -29,7 +29,8 @@ __syschdir:
|
||||
bcs cleanup
|
||||
|
||||
; Update current working directory
|
||||
jsr initcwd ; Returns with A = 0
|
||||
jsr initcwd
|
||||
lda #$00
|
||||
|
||||
; Cleanup name
|
||||
cleanup:jsr popname ; Preserves A
|
||||
|
||||
@@ -108,7 +108,7 @@ static unsigned get_dir_entry(char* p_name)
|
||||
}
|
||||
|
||||
/* Field header_pointer directly follows field last_mod */
|
||||
cur_addr = *(unsigned*)(&dirent->d_mtime.hour + 1);
|
||||
cur_addr = *(unsigned*)(&dirent->d_mtime.time.hour + 1);
|
||||
|
||||
dhandle = dio_open(getcurrentdevice());
|
||||
if (!dhandle) {
|
||||
|
||||
@@ -342,7 +342,7 @@ GETPIXEL:
|
||||
lda #$03 ; 3 (white)
|
||||
: bcc :+
|
||||
adc #$03 ; += 4 (black -> black2, white -> white2)
|
||||
: ldx #$00
|
||||
: ldx #>$0000
|
||||
bit $C080 ; Switch in LC bank 2 for R/O
|
||||
rts
|
||||
|
||||
|
||||
@@ -321,7 +321,7 @@ GETPIXEL:
|
||||
jsr SCRN
|
||||
tax
|
||||
lda COL2TGI,x
|
||||
ldx #$00
|
||||
ldx #>$0000
|
||||
bit $C080 ; Switch in LC bank 2 for R/O
|
||||
rts
|
||||
|
||||
|
||||
9
libsrc/apple2/uppercasemask.s
Normal file
9
libsrc/apple2/uppercasemask.s
Normal file
@@ -0,0 +1,9 @@
|
||||
;
|
||||
; Oliver Schmidt, 2024-08-06
|
||||
;
|
||||
|
||||
.export uppercasemask
|
||||
|
||||
.data
|
||||
|
||||
uppercasemask: .byte $DF ; Convert to uppercase
|
||||
@@ -6,7 +6,6 @@
|
||||
.ifdef __APPLE2ENH__
|
||||
|
||||
.export _videomode
|
||||
.import COUT
|
||||
|
||||
.include "apple2.inc"
|
||||
|
||||
@@ -17,52 +16,25 @@ _videomode:
|
||||
bit RD80VID
|
||||
php
|
||||
|
||||
; If we are in 80 column mode then the 80 column firmware is
|
||||
; known to be active so we can just print the ctrl-char code
|
||||
; (even if this only means staying in the current videomode)
|
||||
bpl :+
|
||||
jsr COUT
|
||||
bra done
|
||||
|
||||
; If we are in 40 column mode and want to set 40 column mode
|
||||
; then we explicitly do nothing as we neither know about the
|
||||
; current state of the 80 column firmware nor want to fix it
|
||||
: cmp #$11 ; Ctrl-char code for 40 cols
|
||||
beq done
|
||||
|
||||
; If we are in 40 column mode and want to set 80 column mode
|
||||
; then we first presume the 80 column firmware being already
|
||||
; active and print the ctrl-char code (this causes a garbage
|
||||
; char to be printed on the screen if isn't already active)
|
||||
jsr COUT
|
||||
|
||||
; If we successfully switched to 80 column mode then the 80
|
||||
; column firmware was in fact already active and we're done
|
||||
bit RD80VID
|
||||
bmi done
|
||||
|
||||
; The 80 column firmware isn't already active so we need to
|
||||
; initialize it - causing the screen to be cleared and thus
|
||||
; the garbage char printed above to be erased (but for some
|
||||
; reason the cursor horizontal position not to be zeroed)
|
||||
stz CH
|
||||
|
||||
; Initializing the 80 column firmware needs the ROM switched
|
||||
; in, otherwise it would copy the F8 ROM to the LC (@ $CEF4)
|
||||
bit $C082
|
||||
|
||||
; Initialize 80 column firmware
|
||||
jsr $C300 ; PR#3
|
||||
; Call 80 column firmware with ctrl-char code
|
||||
jsr $C300
|
||||
|
||||
; Switch in LC bank 2 for R/O
|
||||
bit $C080
|
||||
|
||||
; Switch in alternate charset again
|
||||
sta SETALTCHAR
|
||||
|
||||
; Return ctrl-char code for setting previous
|
||||
; videomode using the saved videomode flag
|
||||
done: lda #$11 ; Ctrl-char code for 40 cols
|
||||
lda #$15 ; Ctrl-char code for 40 cols
|
||||
plp
|
||||
bpl :+
|
||||
inc a ; Ctrl-char code for 80 cols
|
||||
lda #$00 ; Ctrl-char code for 80 cols
|
||||
: rts ; X was preserved all the way
|
||||
|
||||
.endif ; __APPLE2ENH__
|
||||
|
||||
20
libsrc/apple2/wait.s
Normal file
20
libsrc/apple2/wait.s
Normal file
@@ -0,0 +1,20 @@
|
||||
;
|
||||
; Colin Leroy-Mira, 2024
|
||||
;
|
||||
; WAIT routine
|
||||
;
|
||||
|
||||
.export WAIT
|
||||
|
||||
.include "apple2.inc"
|
||||
|
||||
.segment "LOWCODE"
|
||||
|
||||
WAIT:
|
||||
; Switch in ROM and call WAIT
|
||||
bit $C082
|
||||
jsr $FCA8 ; Vector to WAIT routine
|
||||
|
||||
; Switch in LC bank 2 for R/O and return
|
||||
bit $C080
|
||||
rts
|
||||
@@ -5,21 +5,11 @@
|
||||
;
|
||||
.ifdef __APPLE2ENH__
|
||||
|
||||
.constructor initvsync
|
||||
.export _waitvsync
|
||||
.import _get_ostype
|
||||
.import ostype
|
||||
|
||||
.include "apple2.inc"
|
||||
|
||||
.segment "ONCE"
|
||||
|
||||
initvsync:
|
||||
jsr _get_ostype
|
||||
sta ostype
|
||||
rts
|
||||
|
||||
.code
|
||||
|
||||
_waitvsync:
|
||||
bit ostype
|
||||
bmi iigs ; $8x
|
||||
@@ -39,7 +29,8 @@ iigs: bit RDVBLBAR
|
||||
rts
|
||||
|
||||
; Apple IIc TechNote #9, Detecting VBL
|
||||
iic: sei
|
||||
iic: php
|
||||
sei
|
||||
sta IOUDISOFF
|
||||
lda RDVBLMSK
|
||||
bit ENVBL
|
||||
@@ -50,11 +41,7 @@ iic: sei
|
||||
bcs :+ ; VBL interrupts were already enabled
|
||||
bit DISVBL
|
||||
: sta IOUDISON ; IIc Tech Ref Man: The firmware normally leaves IOUDIS on.
|
||||
cli
|
||||
plp
|
||||
rts
|
||||
|
||||
.segment "INIT"
|
||||
|
||||
ostype: .res 1
|
||||
|
||||
.endif ; __APPLE2ENH__
|
||||
|
||||
@@ -10,5 +10,10 @@
|
||||
|
||||
_wherex:
|
||||
lda CH
|
||||
ldx #$00
|
||||
.ifdef __APPLE2ENH__
|
||||
bit RD80VID ; In 80 column mode?
|
||||
bpl :+
|
||||
lda OURCH
|
||||
: .endif
|
||||
ldx #>$0000
|
||||
rts
|
||||
|
||||
@@ -12,5 +12,5 @@ _wherey:
|
||||
lda CV
|
||||
sec
|
||||
sbc WNDTOP
|
||||
ldx #$00
|
||||
ldx #>$0000
|
||||
rts
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
.export _write
|
||||
.import rwprolog, rwcommon, rwepilog
|
||||
.import COUT
|
||||
.ifndef __APPLE2ENH__
|
||||
.import uppercasemask
|
||||
.endif
|
||||
|
||||
.include "zeropage.inc"
|
||||
.include "errno.inc"
|
||||
@@ -84,7 +87,7 @@ next: lda (ptr1),y
|
||||
.ifndef __APPLE2ENH__
|
||||
cmp #$E0 ; Test for lowercase
|
||||
bcc output
|
||||
and #$DF ; Convert to uppercase
|
||||
and uppercasemask
|
||||
.endif
|
||||
output: jsr COUT ; Preserves X and Y
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
|
||||
.include "atari.inc"
|
||||
|
||||
.import __BSS_RUN__, __STARTADDRESS__, _cas_init
|
||||
.import __INIT_RUN__, __STARTADDRESS__, _cas_init
|
||||
.export _cas_hdr
|
||||
|
||||
.assert ((__BSS_RUN__ - __STARTADDRESS__ + 127) / 128) < $101, error, "File to big to load from cassette"
|
||||
.assert ((__INIT_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
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
_cas_hdr:
|
||||
.byte 0 ; ignored
|
||||
.byte <((__BSS_RUN__ - __STARTADDRESS__ + 127) / 128) ; # of 128-byte records to read
|
||||
.byte <((__INIT_RUN__ - __STARTADDRESS__ + 127) / 128) ; # of 128-byte records to read
|
||||
.word __STARTADDRESS__ ; load address
|
||||
.word _cas_init ; init address
|
||||
|
||||
@@ -31,6 +31,8 @@ _cas_hdr:
|
||||
ldy #80
|
||||
sta (SAVMSC),y
|
||||
.endif
|
||||
lda #$3c ; motor off
|
||||
sta PACTL
|
||||
clc
|
||||
rts
|
||||
|
||||
|
||||
@@ -204,6 +204,10 @@ APPMHI_save: .res 2
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
.segment "INIT" ; have at least one (empty) segment of INIT, exehdr.s needs its definition
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
.segment "LOWCODE" ; have at least one (empty) segment of LOWCODE, so that the next line works even if the program doesn't make use of this segment
|
||||
.assert (__LOWCODE_RUN__ + __LOWCODE_SIZE__ <= $4000 || __LOWCODE_RUN__ > $7FFF || __LOWCODE_SIZE__ = 0), warning, "'lowcode area' reaches into $4000..$7FFF bank memory window"
|
||||
; check for LOWBSS_SIZE = 0 not needed since the only file which uses LOWBSS (irq.s) also uses LOWCODE
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
; This file defines the EXE header and main chunk load header for Atari executables
|
||||
|
||||
.export __EXEHDR__: absolute = 1
|
||||
.import __MAIN_START__, __BSS_LOAD__
|
||||
.import __MAIN_START__, __INIT_LOAD__
|
||||
|
||||
.segment "EXEHDR"
|
||||
.word $FFFF
|
||||
|
||||
.segment "MAINHDR"
|
||||
.word __MAIN_START__
|
||||
.word __BSS_LOAD__ - 1
|
||||
.word __INIT_LOAD__ - 1
|
||||
|
||||
; Define the INIT segment so that __INIT_LOAD__ from above '.import' is always defined.
|
||||
; The segment is normally present when linking a C program, but not necessarily when linking an assembler program.
|
||||
.segment "INIT"
|
||||
|
||||
@@ -50,7 +50,7 @@ check_device:
|
||||
lda #SIO_STAT
|
||||
sta DCOMND ; set command into DCB
|
||||
lda #%01000000 ; direction value, "receive data"
|
||||
sta DSTATS ; set data flow directon
|
||||
sta DSTATS ; set data flow direction
|
||||
lda #15
|
||||
sta DTIMLO ; value got from DOS source
|
||||
lda #4
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
.code
|
||||
|
||||
; set new grapics mode
|
||||
; set new graphics mode
|
||||
; gets new mode in A
|
||||
; returns handle or -1 on error
|
||||
; uses tmp1, tmp2, tmp3, tmp4 (in subroutines)
|
||||
|
||||
@@ -374,7 +374,7 @@ IRQ:
|
||||
; 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:
|
||||
; divisions by powers of two, we use the following approximation:
|
||||
; 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.
|
||||
@@ -385,7 +385,7 @@ IRQ:
|
||||
|
||||
; X
|
||||
|
||||
ldx PADDL0 ; get X postion
|
||||
ldx PADDL0 ; get X position
|
||||
dex ; decrement, since it's 1-based
|
||||
stx XPos
|
||||
txa
|
||||
@@ -445,7 +445,7 @@ IRQ:
|
||||
|
||||
; Y
|
||||
|
||||
ldx PADDL1 ; get Y postion
|
||||
ldx PADDL1 ; get Y position
|
||||
dex ; decrement, since it's 1-based
|
||||
stx YPos
|
||||
lda #228
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
.import findfreeiocb
|
||||
.import incsp4
|
||||
.import ldaxysp,addysp
|
||||
.import ___oserror
|
||||
.import ___oserror, returnFFFF
|
||||
.ifdef UCASE_FILENAME
|
||||
.import ucase_fn
|
||||
.endif
|
||||
@@ -39,9 +39,7 @@ parmok: jsr findfreeiocb
|
||||
lda #<EMFILE ; "too many open files"
|
||||
seterr: jsr ___directerrno
|
||||
jsr incsp4 ; clean up stack
|
||||
lda #$FF
|
||||
tax
|
||||
rts ; return -1
|
||||
jmp returnFFFF
|
||||
|
||||
; process the mode argument
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ done: lda ICBLL,x ; buf len lo
|
||||
lda ICBLH,x ; get buf len hi
|
||||
tax ; to X
|
||||
okdone: lda #0
|
||||
sta ___oserror ; clear system dependend error code
|
||||
sta ___oserror ; clear system dependent error code
|
||||
pla ; get buf len lo
|
||||
rts
|
||||
|
||||
@@ -147,6 +147,7 @@ icbll_copy:
|
||||
sta dataptr+1
|
||||
lda ICBLL,x
|
||||
sta copylen
|
||||
beq copied ; length = 0 if EOF
|
||||
pha ; remember for return value
|
||||
ldy #0
|
||||
ldx index
|
||||
@@ -159,7 +160,7 @@ copy: lda linebuf,x
|
||||
bne copy
|
||||
|
||||
pla ; length
|
||||
pha ; save length to return at okdone
|
||||
copied: pha ; save length to return at okdone
|
||||
|
||||
clc
|
||||
adc index
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
.proc __sio_call
|
||||
|
||||
sta DCOMND ; set command into DCB
|
||||
stx DSTATS ; set data flow directon
|
||||
stx DSTATS ; set data flow direction
|
||||
jsr popax ; get buffer address
|
||||
sta DBUFLO ; set buffer address into DCB
|
||||
stx DBUFHI
|
||||
|
||||
@@ -21,7 +21,7 @@ write9:
|
||||
lda ICBLH,x ; buf len high
|
||||
tax
|
||||
lda #0
|
||||
sta ___oserror ; clear system dependend error code
|
||||
sta ___oserror ; clear system dependent error code
|
||||
pla
|
||||
rts
|
||||
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
.export _clrscr
|
||||
.include "atari5200.inc"
|
||||
.importzp ptr1
|
||||
.importzp screen_width, screen_height
|
||||
|
||||
SCRSIZE = 480 ; 20x24: size of default conio atari5200 screen
|
||||
SCRSIZE = screen_width * screen_height
|
||||
|
||||
_clrscr:lda SAVMSC ; screen memory
|
||||
sta ptr1
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
SCREEN_BUF_SIZE = 20 * 24
|
||||
SCREEN_BUF = $4000 - SCREEN_BUF_SIZE
|
||||
|
||||
.import _clrscr
|
||||
.export screen_setup
|
||||
.export screen_width, screen_height
|
||||
.export conio_color
|
||||
@@ -26,24 +27,10 @@ screen_setup:
|
||||
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
|
||||
jsr _clrscr
|
||||
|
||||
; set default colors
|
||||
|
||||
lda #GTIA_COLOR_WHITE
|
||||
sta COLOR0
|
||||
lda #GTIA_COLOR_LIGHTRED
|
||||
@@ -55,7 +42,6 @@ clrscr: sta (SAVMSC),y
|
||||
sta COLOR4 ; background
|
||||
|
||||
; set display list
|
||||
|
||||
lda #<dlist
|
||||
sta SDLSTL
|
||||
lda #>dlist
|
||||
@@ -82,7 +68,7 @@ dlist: .repeat 3
|
||||
.byte DL_CHR20x8x2
|
||||
.endrepeat
|
||||
|
||||
.byte DL_JVB
|
||||
.byte DL_JVB
|
||||
.word dlist
|
||||
|
||||
; end of display list
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
SCREEN_BUF_SIZE = 20 * 12
|
||||
SCREEN_BUF = $4000 - SCREEN_BUF_SIZE
|
||||
|
||||
.import _clrscr
|
||||
.export screen_setup
|
||||
.export screen_width, screen_height
|
||||
.export conio_color
|
||||
@@ -26,24 +27,10 @@ screen_setup:
|
||||
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
|
||||
jsr _clrscr
|
||||
|
||||
; set default colors
|
||||
|
||||
lda #GTIA_COLOR_WHITE
|
||||
sta COLOR0
|
||||
lda #GTIA_COLOR_LIGHTRED
|
||||
@@ -55,7 +42,6 @@ clrscr: sta (SAVMSC),y
|
||||
sta COLOR4 ; background
|
||||
|
||||
; set display list
|
||||
|
||||
lda #<dlist
|
||||
sta SDLSTL
|
||||
lda #>dlist
|
||||
@@ -82,7 +68,7 @@ dlist: .repeat 3
|
||||
.byte DL_CHR20x16x2
|
||||
.endrepeat
|
||||
|
||||
.byte DL_JVB
|
||||
.byte DL_JVB
|
||||
.word dlist
|
||||
|
||||
; end of display list
|
||||
|
||||
@@ -53,13 +53,20 @@ JOY_COUNT = 2 ; Number of joysticks we support
|
||||
; Must return an JOY_ERR_xx code in a/x.
|
||||
;
|
||||
|
||||
PB2 = $04 ; Joystick 0
|
||||
PB4 = $10 ; Joystick 1
|
||||
|
||||
INSTALL:
|
||||
; Assume 7800 2-button controller, can change
|
||||
; to 2600 1-button later
|
||||
lda #$14
|
||||
sta CTLSWB ; enable 2-button 7800 controller 1: set pin 6 to output
|
||||
lda #(PB2 | PB4)
|
||||
; enable 2-button 7800 controllers on both ports
|
||||
; by setting PB2 and PB4 to output
|
||||
sta CTLSWB
|
||||
; enable 2-button 7800 controllers by setting
|
||||
; the outputs to 0; (INPT4 and INPT5) high
|
||||
ldy #$00
|
||||
sty SWCHB ; enable 2-button 7800 controller 2: pull pin 6 (INPT4) high
|
||||
sty SWCHB
|
||||
|
||||
reset:
|
||||
lda #JOY_ERR_OK
|
||||
@@ -88,6 +95,28 @@ COUNT:
|
||||
; ------------------------------------------------------------------------
|
||||
; READ: Read a particular joystick passed in A for 2 fire buttons.
|
||||
|
||||
readdualbuttons0:
|
||||
ldy #0 ; ........
|
||||
bit INPT0 ; Check for right button
|
||||
bpl L1
|
||||
ldy #2 ; ......2.
|
||||
L1: bit INPT1 ; Check for left button
|
||||
bpl L2
|
||||
iny ; ......21
|
||||
L2: tya
|
||||
rts
|
||||
|
||||
readdualbuttons1:
|
||||
ldy #0 ; ........
|
||||
bit INPT2 ; Check for right button
|
||||
bpl L1
|
||||
ldy #2 ; ......2.
|
||||
L3: bit INPT3 ; Check for left button
|
||||
bpl L2
|
||||
iny ; ......21
|
||||
L4: tya
|
||||
rts
|
||||
|
||||
readbuttons:
|
||||
; Y has joystick of interest 0/1
|
||||
; return value:
|
||||
@@ -97,42 +126,48 @@ readbuttons:
|
||||
; $03: both buttons
|
||||
; preserves X
|
||||
tya
|
||||
beq L5
|
||||
beq readbuttons0
|
||||
readbuttons1:
|
||||
; Joystick 1 processing
|
||||
; 7800 joystick 1 buttons
|
||||
ldy #0 ; ........
|
||||
bit INPT2 ; Check for right button
|
||||
bpl L1
|
||||
ldy #2 ; ......2.
|
||||
L1: bit INPT3 ;Check for left button
|
||||
bpl L2
|
||||
iny ; ......21
|
||||
L2: tya
|
||||
bne L4 ; 7800 mode joystick worked
|
||||
; 2600 Joystick 1
|
||||
; Start by checking for single button 2600 joystick
|
||||
bit INPT5
|
||||
bmi L4
|
||||
L3: iny ; .......1
|
||||
lda #0 ; Fallback to 2600 joystick mode
|
||||
sta CTLSWB
|
||||
L4: tya ; ......21
|
||||
bpl singlebtn1detected
|
||||
jmp readdualbuttons1
|
||||
singlebtn1detected:
|
||||
; Single button joystick detected but could be dual
|
||||
jsr readdualbuttons1
|
||||
bne L5 ; It was a dual button press
|
||||
; It was a single button press
|
||||
bit INPT5
|
||||
bmi L5
|
||||
iny ; .......1
|
||||
lda #PB4 ; Joystick 1 is a single button unit
|
||||
clc
|
||||
adc SWCHB
|
||||
sta SWCHB ; Cut power from the dual button circuit
|
||||
L5: tya ; ......21
|
||||
rts
|
||||
|
||||
L5: ; Joystick 0 processing
|
||||
; 7800 joystick 0 buttons
|
||||
ldy #0 ; ........
|
||||
bit INPT0 ; Check for right button
|
||||
bpl L6
|
||||
ldy #2 ; ......2.
|
||||
L6: bit INPT1 ;Check for left button
|
||||
bpl L7
|
||||
iny ; ......21
|
||||
L7: tya
|
||||
bne L4 ; 7800 mode joystick worked
|
||||
; 2600 Joystick 0
|
||||
readbuttons0:
|
||||
; Joystick 0 processing
|
||||
; Start by checking for single button 2600 joystick
|
||||
bit INPT4
|
||||
bmi L4
|
||||
bpl L3
|
||||
bpl singlebtn0detected
|
||||
jmp readdualbuttons0
|
||||
singlebtn0detected:
|
||||
; Single button joystick detected but could be dual
|
||||
jsr readdualbuttons0
|
||||
bne L6 ; It was a dual button press
|
||||
; It was a single button press
|
||||
bit INPT4
|
||||
bmi L6
|
||||
iny ; .......1
|
||||
lda #PB2 ; Joystick 0 is a single button unit
|
||||
clc
|
||||
adc SWCHB
|
||||
sta SWCHB ; Cut power from the dual button circuit
|
||||
L6: tya ; ......21
|
||||
rts
|
||||
|
||||
READ:
|
||||
tay ; Store joystick 0/1 in Y
|
||||
|
||||
@@ -227,14 +227,8 @@ InvBaud:lda #<SER_ERR_BAUD_UNAVAIL
|
||||
; returned.
|
||||
|
||||
SER_GET:
|
||||
ldy SendFreeCnt ; Send data if necessary
|
||||
iny ; Y == $FF?
|
||||
beq :+
|
||||
lda #$00 ; TryHard = false
|
||||
jsr TryToSend
|
||||
|
||||
; Check for buffer empty
|
||||
: lda RecvFreeCnt ; (25)
|
||||
lda RecvFreeCnt ; (25)
|
||||
cmp #$FF
|
||||
bne :+
|
||||
lda #SER_ERR_NO_DATA
|
||||
@@ -269,20 +263,21 @@ SER_GET:
|
||||
SER_PUT:
|
||||
; Try to send
|
||||
ldy SendFreeCnt
|
||||
iny ; Y = $FF?
|
||||
cpy #$FF ; Nothing to flush
|
||||
beq :+
|
||||
pha
|
||||
lda #$00 ; TryHard = false
|
||||
jsr TryToSend
|
||||
pla
|
||||
|
||||
; Put byte into send buffer & send
|
||||
: ldy SendFreeCnt
|
||||
; Reload SendFreeCnt after TryToSend
|
||||
ldy SendFreeCnt
|
||||
bne :+
|
||||
lda #SER_ERR_OVERFLOW
|
||||
ldx #0 ; return value is char
|
||||
rts
|
||||
|
||||
; Put byte into send buffer & send
|
||||
: ldy SendTail
|
||||
sta SendBuf,y
|
||||
inc SendTail
|
||||
@@ -329,19 +324,19 @@ SER_IRQ:
|
||||
and #$08
|
||||
beq Done ; Jump if no ACIA interrupt
|
||||
lda ACIA::DATA,x ; Get byte from ACIA
|
||||
ldy RecvFreeCnt ; Check if we have free space left
|
||||
ldx RecvFreeCnt ; Check if we have free space left
|
||||
beq Flow ; Jump if no space in receive buffer
|
||||
ldy RecvTail ; Load buffer pointer
|
||||
sta RecvBuf,y ; Store received byte in buffer
|
||||
inc RecvTail ; Increment buffer pointer
|
||||
dec RecvFreeCnt ; Decrement free space counter
|
||||
ldy RecvFreeCnt ; Check for buffer space low
|
||||
cpy #33
|
||||
cpx #33
|
||||
bcc Flow ; Assert flow control if buffer space low
|
||||
rts ; Interrupt handled (carry already set)
|
||||
|
||||
; Assert flow control if buffer space too low
|
||||
Flow: lda RtsOff
|
||||
Flow: ldx Index ; Reload port
|
||||
lda RtsOff
|
||||
sta ACIA::CMD,x
|
||||
sta Stopped
|
||||
sec ; Interrupt handled
|
||||
@@ -352,12 +347,13 @@ Done: rts
|
||||
|
||||
TryToSend:
|
||||
sta tmp1 ; Remember tryHard flag
|
||||
Again: lda SendFreeCnt
|
||||
NextByte:
|
||||
lda SendFreeCnt
|
||||
cmp #$FF
|
||||
beq Quit ; Bail out
|
||||
|
||||
; Check for flow stopped
|
||||
lda Stopped
|
||||
Again: lda Stopped
|
||||
bne Quit ; Bail out
|
||||
|
||||
; Check that ACIA is ready to send
|
||||
@@ -374,4 +370,4 @@ Send: ldy SendHead
|
||||
sta ACIA::DATA
|
||||
inc SendHead
|
||||
inc SendFreeCnt
|
||||
jmp Again
|
||||
jmp NextByte
|
||||
|
||||
18
libsrc/atmos/waitvsync.s
Normal file
18
libsrc/atmos/waitvsync.s
Normal file
@@ -0,0 +1,18 @@
|
||||
;
|
||||
; Written by Stefan Haubenthal <polluks@sdf.org>, requires VSync hack
|
||||
;
|
||||
; void waitvsync (void);
|
||||
;
|
||||
|
||||
.export _waitvsync
|
||||
|
||||
.include "atmos.inc"
|
||||
|
||||
.proc _waitvsync
|
||||
|
||||
lda #%00010000 ; CB1
|
||||
wait: and VIA::PRA2
|
||||
bne wait
|
||||
rts
|
||||
|
||||
.endproc
|
||||
@@ -125,11 +125,10 @@ uservec: jmp $FFFF ; Patched at runtime
|
||||
|
||||
.data
|
||||
|
||||
; Old break vector preceeded by a jump opcode
|
||||
; Old break vector preceded by a jump opcode
|
||||
brk_old:
|
||||
jmp $0000
|
||||
|
||||
; Indirect vectors preceeded by a jump opcode
|
||||
; Indirect vectors preceded by a jump opcode
|
||||
brk_ind:
|
||||
jmp $0000
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ ParityTable:
|
||||
; Interrupt stub that is copied into low RAM. The startup code uses a special
|
||||
; memory configuration with just kernal and I/O enabled (anything else is RAM).
|
||||
; The NMI handler in ROM will switch back to a configuration where just the
|
||||
; low 16K RAM are accessible. So we have to copy a smal piece of code into
|
||||
; low 16K RAM are accessible. So we have to copy a small piece of code into
|
||||
; low RAM that enables the cc65 configuration and then jumps to the real NMI
|
||||
; handler.
|
||||
|
||||
@@ -296,7 +296,7 @@ SER_CLOSE:
|
||||
lda #%00001010
|
||||
sta ACIA_CMD
|
||||
|
||||
; Initalize buffers. Returns zero in a
|
||||
; Initialize buffers. Returns zero in a
|
||||
|
||||
jsr InitBuffers
|
||||
|
||||
@@ -314,15 +314,10 @@ SER_CLOSE:
|
||||
;
|
||||
|
||||
SER_GET:
|
||||
ldx SendFreeCnt ; Send data if necessary
|
||||
inx ; X == $FF?
|
||||
beq @L1
|
||||
lda #$00
|
||||
jsr TryToSend
|
||||
|
||||
; Check for buffer empty
|
||||
|
||||
@L1: lda RecvFreeCnt ; (25)
|
||||
lda RecvFreeCnt ; (25)
|
||||
cmp #$ff
|
||||
bne @L2
|
||||
lda #SER_ERR_NO_DATA
|
||||
@@ -362,21 +357,23 @@ SER_PUT:
|
||||
; Try to send
|
||||
|
||||
ldx SendFreeCnt
|
||||
inx ; X = $ff?
|
||||
cpx #$FF ; Nothing to flush
|
||||
beq @L2
|
||||
pha
|
||||
lda #$00
|
||||
jsr TryToSend
|
||||
pla
|
||||
|
||||
; Put byte into send buffer & send
|
||||
; Reload SendFreeCnt after TryToSend
|
||||
|
||||
@L2: ldx SendFreeCnt
|
||||
bne @L3
|
||||
ldx SendFreeCnt
|
||||
bne @L2
|
||||
lda #SER_ERR_OVERFLOW ; X is already zero
|
||||
rts
|
||||
|
||||
@L3: ldx SendTail
|
||||
; Put byte into send buffer & send
|
||||
|
||||
@L2: ldx SendTail
|
||||
sta SendBuf,x
|
||||
inc SendTail
|
||||
dec SendFreeCnt
|
||||
@@ -466,25 +463,25 @@ NmiHandler:
|
||||
sta tmp1 ; Remember tryHard flag
|
||||
@L0: lda SendFreeCnt
|
||||
cmp #$ff
|
||||
beq @L3 ; Bail out
|
||||
beq @L2 ; Bail out
|
||||
|
||||
; Check for flow stopped
|
||||
|
||||
@L1: lda Stopped
|
||||
bne @L3 ; Bail out
|
||||
bne @L2 ; Bail out
|
||||
|
||||
; Check that swiftlink is ready to send
|
||||
|
||||
@L2: lda ACIA_STATUS
|
||||
lda ACIA_STATUS
|
||||
and #$10
|
||||
bne @L4
|
||||
bne @L3
|
||||
bit tmp1 ;keep trying if must try hard
|
||||
bmi @L0
|
||||
@L3: rts
|
||||
bmi @L1
|
||||
@L2: rts
|
||||
|
||||
; Send byte and try again
|
||||
|
||||
@L4: ldx SendHead
|
||||
@L3: ldx SendHead
|
||||
lda SendBuf,x
|
||||
sta ACIA_DATA
|
||||
inc SendHead
|
||||
|
||||
@@ -268,7 +268,7 @@ INIT:
|
||||
@L1: ldx #$FF
|
||||
stx BITMASK
|
||||
|
||||
; Remeber current color value
|
||||
; Remember current color value
|
||||
ldx #VDC_COLORS
|
||||
jsr VDCReadReg
|
||||
sta OLDCOLOR
|
||||
|
||||
@@ -277,7 +277,7 @@ INIT:
|
||||
@L1: ldx #$FF
|
||||
stx BITMASK
|
||||
|
||||
; Remeber current color value
|
||||
; Remember current color value
|
||||
ldx #VDC_COLORS
|
||||
jsr VDCReadReg
|
||||
sta OLDCOLOR
|
||||
|
||||
@@ -23,8 +23,8 @@ _waitvsync:
|
||||
|
||||
@c80:
|
||||
;FIXME: do we have to switch banks?
|
||||
lda #$20
|
||||
@l3:
|
||||
lda VDC_INDEX
|
||||
and #$20
|
||||
and VDC_INDEX
|
||||
beq @l3
|
||||
rts
|
||||
|
||||
@@ -212,8 +212,8 @@ MAP:
|
||||
cmp pagecount
|
||||
bcs return_null
|
||||
sta curpage
|
||||
lda #<dummy ; load .A/.X with adress of data for COPYFROM-call (which expects the
|
||||
ldx #>dummy ; adress in .A/.X)
|
||||
lda #<dummy ; load .A/.X with address of data for COPYFROM-call (which expects the
|
||||
ldx #>dummy ; address in .A/.X)
|
||||
jsr COPYFROM
|
||||
bcs return_win ; function returns pointer to window (returns always with carry set!)
|
||||
|
||||
@@ -224,8 +224,8 @@ COMMIT:
|
||||
lda curpage
|
||||
cmp pagecount
|
||||
bcs return
|
||||
lda #<dummy ; load .A/.X with adress of data for COPYTO-call (which expects the
|
||||
ldx #>dummy ; adress in .A/.X)
|
||||
lda #<dummy ; load .A/.X with address of data for COPYTO-call (which expects the
|
||||
ldx #>dummy ; address in .A/.X)
|
||||
|
||||
;----------------------------------------------------------------------------------------
|
||||
;void __fastcall__ em_copyto (struct em_copy *copy_data);
|
||||
@@ -324,7 +324,7 @@ get_struct_data:
|
||||
;read and process the values from the em_copy struct passed to as parameters rameter to the
|
||||
;functions em_copyto and em_copyfrom
|
||||
|
||||
sta aux ;store adress of struct (passed in .A/.X) into a zp pointer
|
||||
sta aux ;store address of struct (passed in .A/.X) into a zp pointer
|
||||
stx aux+1
|
||||
ldy #0 ;index 0
|
||||
|
||||
@@ -347,7 +347,7 @@ get_struct_data:
|
||||
lsr
|
||||
lsr ;shift into bits 3 and 4
|
||||
ora #$23 ;set bit 5 (select ram) and 1+2 (game/exrom setting for ULTIMAX-mode)
|
||||
tax ;.X has now the value to write into $de00 to acess rr-ram at desired 16k-bank
|
||||
tax ;.X has now the value to write into $de00 to access rr-ram at desired 16k-bank
|
||||
iny
|
||||
iny ;skip unused byte
|
||||
lda (aux),y ;read length lo-byte
|
||||
@@ -357,7 +357,7 @@ get_struct_data:
|
||||
iny
|
||||
lda (aux),y ;length hi-byte
|
||||
adc c64_ram+1
|
||||
sta len+1 ;tmp2: length, tmp3 contains end adress of transfer in c64-ram.
|
||||
sta len+1 ;tmp2: length, tmp3 contains end address of transfer in c64-ram.
|
||||
rts
|
||||
;55 bytes
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ readadapter:
|
||||
lda #%00010001
|
||||
sta $dd0e ; control register a
|
||||
; timer: start
|
||||
; continous
|
||||
; continuous
|
||||
; forced load
|
||||
; serial port: input
|
||||
|
||||
@@ -110,7 +110,7 @@ readadapter:
|
||||
lda #%01010001
|
||||
sta $dc0e ; control register a
|
||||
; timer: start
|
||||
; continous
|
||||
; continuous
|
||||
; forced load
|
||||
; serial port: output
|
||||
|
||||
|
||||
@@ -270,7 +270,7 @@ SER_CLOSE:
|
||||
lda #%00001010
|
||||
sta ACIA_CMD
|
||||
|
||||
; Initalize buffers. Returns zero in a
|
||||
; Initialize buffers. Returns zero in a
|
||||
|
||||
jsr InitBuffers
|
||||
|
||||
@@ -288,15 +288,10 @@ SER_CLOSE:
|
||||
;
|
||||
|
||||
SER_GET:
|
||||
ldx SendFreeCnt ; Send data if necessary
|
||||
inx ; X == $FF?
|
||||
beq @L1
|
||||
lda #$00
|
||||
jsr TryToSend
|
||||
|
||||
; Check for buffer empty
|
||||
|
||||
@L1: lda RecvFreeCnt ; (25)
|
||||
lda RecvFreeCnt ; (25)
|
||||
cmp #$ff
|
||||
bne @L2
|
||||
lda #SER_ERR_NO_DATA
|
||||
@@ -336,21 +331,23 @@ SER_PUT:
|
||||
; Try to send
|
||||
|
||||
ldx SendFreeCnt
|
||||
inx ; X = $ff?
|
||||
cpx #$FF ; Nothing to flush
|
||||
beq @L2
|
||||
pha
|
||||
lda #$00
|
||||
jsr TryToSend
|
||||
pla
|
||||
|
||||
; Put byte into send buffer & send
|
||||
; Reload SendFreeCnt after TryToSend
|
||||
|
||||
@L2: ldx SendFreeCnt
|
||||
bne @L3
|
||||
ldx SendFreeCnt
|
||||
bne @L2
|
||||
lda #SER_ERR_OVERFLOW ; X is already zero
|
||||
rts
|
||||
|
||||
@L3: ldx SendTail
|
||||
; Put byte into send buffer & send
|
||||
|
||||
@L2: ldx SendTail
|
||||
sta SendBuf,x
|
||||
inc SendTail
|
||||
dec SendFreeCnt
|
||||
@@ -443,25 +440,25 @@ NmiHandler:
|
||||
sta tmp1 ; Remember tryHard flag
|
||||
@L0: lda SendFreeCnt
|
||||
cmp #$ff
|
||||
beq @L3 ; Bail out
|
||||
beq @L2 ; Bail out
|
||||
|
||||
; Check for flow stopped
|
||||
|
||||
@L1: lda Stopped
|
||||
bne @L3 ; Bail out
|
||||
bne @L2 ; Bail out
|
||||
|
||||
; Check that swiftlink is ready to send
|
||||
|
||||
@L2: lda ACIA_STATUS
|
||||
lda ACIA_STATUS
|
||||
and #$10
|
||||
bne @L4
|
||||
bne @L3
|
||||
bit tmp1 ;keep trying if must try hard
|
||||
bmi @L0
|
||||
@L3: rts
|
||||
bmi @L1
|
||||
@L2: rts
|
||||
|
||||
; Send byte and try again
|
||||
|
||||
@L4: ldx SendHead
|
||||
@L3: ldx SendHead
|
||||
lda SendBuf,x
|
||||
sta ACIA_DATA
|
||||
inc SendHead
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
; /* the kernal routine BASIN sets ST to EOF if the end of file
|
||||
; ** is reached the first time, then we have store tmp.
|
||||
; ** every subsequent call returns EOF and READ ERROR in ST, then
|
||||
; ** we have to exit the loop here immediatly.
|
||||
; ** we have to exit the loop here immediately.
|
||||
; */
|
||||
; if (cbm_k_readst() & 0xBF) break;
|
||||
;
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
.export _cbm_read
|
||||
.importzp ptr1, ptr2, ptr3, tmp1
|
||||
.import popax, popa
|
||||
.import popax, popa, returnFFFF
|
||||
.import ___oserror
|
||||
|
||||
|
||||
@@ -107,7 +107,4 @@ _cbm_read:
|
||||
; CHKIN failed
|
||||
|
||||
@E1: sta ___oserror
|
||||
lda #$FF
|
||||
tax
|
||||
rts ; return -1
|
||||
|
||||
jmp returnFFFF
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
.export _cbm_write
|
||||
.importzp ptr1, ptr2, ptr3
|
||||
.import popax, popa
|
||||
.import popax, popa, returnFFFF
|
||||
.import ___oserror
|
||||
|
||||
|
||||
@@ -88,7 +88,4 @@ _cbm_write:
|
||||
; Error entry, error code is in A
|
||||
|
||||
@E2: sta ___oserror
|
||||
lda #$FF
|
||||
tax
|
||||
rts ; return -1
|
||||
|
||||
jmp returnFFFF
|
||||
|
||||
@@ -89,7 +89,7 @@ int __fastcall__ exec (const char* progname, const char* cmdline)
|
||||
}
|
||||
utoa (dv, basic.unit, 10);
|
||||
|
||||
/* Tape files can be openned only once; skip this test for the Datasette. */
|
||||
/* Tape files can be opened only once; skip this test for the Datasette. */
|
||||
if (dv != 1) {
|
||||
/* Don't try to run a program that can't be found. */
|
||||
fd = open (progname, O_RDONLY);
|
||||
|
||||
@@ -54,7 +54,7 @@ next: inx
|
||||
|
||||
lda ST
|
||||
|
||||
; Either the Kernal calls above were successfull or there was
|
||||
; Either the Kernal calls above were successful or there was
|
||||
; already a cmdchannel to the device open - which is a pretty
|
||||
; good indication of its existence ;-)
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
; Ullrich von Bassewitz, 2010-11-13
|
||||
;
|
||||
; This module supplies the load address that is expected by Commodore
|
||||
; machines in the first two bytes of an excutable disk file.
|
||||
; machines in the first two bytes of an executable disk file.
|
||||
;
|
||||
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ READ: ldx #$0F ; Switch to the system bank
|
||||
lsr tmp1
|
||||
lsr tmp1
|
||||
|
||||
; Mask the relavant bits, get the push button bit
|
||||
; Mask the relevant bits, get the push button bit
|
||||
|
||||
@L2: asl a ; push button bit into carry
|
||||
lda tmp1
|
||||
|
||||
@@ -244,15 +244,10 @@ InvBaud:
|
||||
;
|
||||
|
||||
SER_GET:
|
||||
ldx SendFreeCnt ; Send data if necessary
|
||||
inx ; X == $FF?
|
||||
beq @L1
|
||||
lda #$00
|
||||
jsr TryToSend
|
||||
|
||||
; Check for buffer empty
|
||||
|
||||
@L1: lda RecvFreeCnt
|
||||
lda RecvFreeCnt
|
||||
cmp #$ff
|
||||
bne @L2
|
||||
lda #SER_ERR_NO_DATA
|
||||
@@ -292,21 +287,23 @@ SER_PUT:
|
||||
; Try to send
|
||||
|
||||
ldx SendFreeCnt
|
||||
inx ; X = $ff?
|
||||
cpx #$FF ; Nothing to flush
|
||||
beq @L2
|
||||
pha
|
||||
lda #$00
|
||||
jsr TryToSend
|
||||
pla
|
||||
|
||||
; Put byte into send buffer & send
|
||||
; Reload SendFreeCnt after TryToSend
|
||||
|
||||
@L2: ldx SendFreeCnt
|
||||
bne @L3
|
||||
ldx SendFreeCnt
|
||||
bne @L2
|
||||
lda #SER_ERR_OVERFLOW ; X is already zero
|
||||
rts
|
||||
|
||||
@L3: ldx SendTail
|
||||
; Put byte into send buffer & send
|
||||
|
||||
@L2: ldx SendTail
|
||||
sta SendBuf,x
|
||||
inc SendTail
|
||||
dec SendFreeCnt
|
||||
@@ -395,31 +392,31 @@ SER_IRQ:
|
||||
sta IndReg ; Switch to the system bank
|
||||
@L0: lda SendFreeCnt
|
||||
cmp #$ff
|
||||
beq @L3 ; Bail out
|
||||
beq @L2 ; Bail out
|
||||
|
||||
; Check for flow stopped
|
||||
|
||||
@L1: lda Stopped
|
||||
bne @L3 ; Bail out
|
||||
bne @L2 ; Bail out
|
||||
|
||||
; Check that swiftlink is ready to send
|
||||
|
||||
@L2: ldy #ACIA::STATUS
|
||||
ldy #ACIA::STATUS
|
||||
lda (acia),y
|
||||
and #$10
|
||||
bne @L4
|
||||
bne @L3
|
||||
bit tmp1 ; Keep trying if must try hard
|
||||
bmi @L0
|
||||
bmi @L1
|
||||
|
||||
; Switch back the bank and return
|
||||
|
||||
@L3: lda ExecReg
|
||||
@L2: lda ExecReg
|
||||
sta IndReg
|
||||
rts
|
||||
|
||||
; Send byte and try again
|
||||
|
||||
@L4: ldx SendHead
|
||||
@L3: ldx SendHead
|
||||
lda SendBuf,x
|
||||
ldy #ACIA::DATA
|
||||
sta (acia),y
|
||||
|
||||
@@ -245,15 +245,10 @@ InvBaud:
|
||||
;
|
||||
|
||||
SER_GET:
|
||||
ldx SendFreeCnt ; Send data if necessary
|
||||
inx ; X == $FF?
|
||||
beq @L1
|
||||
lda #$00
|
||||
jsr TryToSend
|
||||
|
||||
; Check for buffer empty
|
||||
|
||||
@L1: lda RecvFreeCnt
|
||||
lda RecvFreeCnt
|
||||
cmp #$ff
|
||||
bne @L2
|
||||
lda #SER_ERR_NO_DATA
|
||||
@@ -293,21 +288,23 @@ SER_PUT:
|
||||
; Try to send
|
||||
|
||||
ldx SendFreeCnt
|
||||
inx ; X = $ff?
|
||||
cpx #$ff ; Nothing to flush
|
||||
beq @L2
|
||||
pha
|
||||
lda #$00
|
||||
jsr TryToSend
|
||||
pla
|
||||
|
||||
; Put byte into send buffer & send
|
||||
; Reload SendFreeCnt after TryToSend
|
||||
|
||||
@L2: ldx SendFreeCnt
|
||||
bne @L3
|
||||
ldx SendFreeCnt
|
||||
bne @L2
|
||||
lda #SER_ERR_OVERFLOW ; X is already zero
|
||||
rts
|
||||
|
||||
@L3: ldx SendTail
|
||||
; Put byte into send buffer & send
|
||||
|
||||
@L2: ldx SendTail
|
||||
sta SendBuf,x
|
||||
inc SendTail
|
||||
dec SendFreeCnt
|
||||
@@ -395,31 +392,31 @@ SER_IRQ:
|
||||
sta IndReg ; Switch to the system bank
|
||||
@L0: lda SendFreeCnt
|
||||
cmp #$ff
|
||||
beq @L3 ; Bail out
|
||||
beq @L2 ; Bail out
|
||||
|
||||
; Check for flow stopped
|
||||
|
||||
@L1: lda Stopped
|
||||
bne @L3 ; Bail out
|
||||
bne @L2 ; Bail out
|
||||
|
||||
; Check that swiftlink is ready to send
|
||||
|
||||
@L2: ldy #ACIA::STATUS
|
||||
ldy #ACIA::STATUS
|
||||
lda (acia),y
|
||||
and #$10
|
||||
bne @L4
|
||||
bne @L3
|
||||
bit tmp1 ; Keep trying if must try hard
|
||||
bmi @L0
|
||||
bmi @L1
|
||||
|
||||
; Switch back the bank and return
|
||||
|
||||
@L3: lda ExecReg
|
||||
@L2: lda ExecReg
|
||||
sta IndReg
|
||||
rts
|
||||
|
||||
; Send byte and try again
|
||||
|
||||
@L4: ldx SendHead
|
||||
@L3: ldx SendHead
|
||||
lda SendBuf,x
|
||||
ldy #ACIA::DATA
|
||||
sta (acia),y
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
.import _strlower, _strlen
|
||||
|
||||
.macpack generic
|
||||
.macpack cpu
|
||||
|
||||
; ----------------------------------------------------------------------------
|
||||
; We will store variables into the register bank in the zeropage. Define
|
||||
@@ -37,7 +38,11 @@ FCount = ptr2
|
||||
|
||||
GetFormatChar:
|
||||
ldy #0
|
||||
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||
lda (Format)
|
||||
.else
|
||||
lda (Format),y
|
||||
.endif
|
||||
IncFormatPtr:
|
||||
inc Format
|
||||
bne @L1
|
||||
@@ -110,7 +115,11 @@ GetIntArg:
|
||||
lda (ArgList),y
|
||||
tax
|
||||
dey
|
||||
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||
lda (ArgList)
|
||||
.else
|
||||
lda (ArgList),y
|
||||
.endif
|
||||
rts
|
||||
|
||||
; ----------------------------------------------------------------------------
|
||||
@@ -135,9 +144,9 @@ ReadInt:
|
||||
pha ; Save digit value
|
||||
lda ptr1
|
||||
ldx ptr1+1
|
||||
asl ptr1
|
||||
asl a
|
||||
rol ptr1+1 ; * 2
|
||||
asl ptr1
|
||||
asl a
|
||||
rol ptr1+1 ; * 4, assume carry clear
|
||||
adc ptr1
|
||||
sta ptr1
|
||||
@@ -265,10 +274,16 @@ Save: lda regbank,y
|
||||
; Initialize the output counter in the output descriptor to zero
|
||||
|
||||
lda #0
|
||||
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||
sta (OutData)
|
||||
ldy #$01
|
||||
sta (OutData),y
|
||||
.else
|
||||
tay
|
||||
sta (OutData),y
|
||||
iny
|
||||
sta (OutData),y
|
||||
.endif
|
||||
|
||||
; Get the output function from the output descriptor and remember it
|
||||
|
||||
@@ -338,7 +353,11 @@ MainLoop:
|
||||
sta (sp),y
|
||||
dey
|
||||
lda FCount
|
||||
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||
sta (sp)
|
||||
.else
|
||||
sta (sp),y
|
||||
.endif
|
||||
jsr CallOutFunc ; Call the output function
|
||||
|
||||
; We're back from out(), or we didn't call it. Check for end of string.
|
||||
@@ -551,10 +570,16 @@ CheckCount:
|
||||
jsr GetIntArg
|
||||
sta ptr1
|
||||
stx ptr1+1 ; Get user supplied pointer
|
||||
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||
lda (OutData) ; Low byte of OutData->ccount
|
||||
sta (ptr1)
|
||||
ldy #1
|
||||
.else
|
||||
ldy #0
|
||||
lda (OutData),y ; Low byte of OutData->ccount
|
||||
sta (ptr1),y
|
||||
iny
|
||||
.endif
|
||||
lda (OutData),y ; High byte of OutData->ccount
|
||||
sta (ptr1),y
|
||||
jmp MainLoop ; Done
|
||||
|
||||
129
libsrc/common/_time_t_to_tm.s
Normal file
129
libsrc/common/_time_t_to_tm.s
Normal file
@@ -0,0 +1,129 @@
|
||||
;
|
||||
; Colin Leroy-Mira, 2024
|
||||
;
|
||||
; struct tm* __fastcall__ _time_t_to_tm (const time_t t)
|
||||
;
|
||||
; Helper to gmtime and localtime. Breaks down a number of
|
||||
; seconds since Jan 1, 1970 into days, hours and seconds,
|
||||
; so that each of them fits in 16 bits; passes the
|
||||
; result to _mktime which fixes all values in the struct,
|
||||
; and returns a pointer to the struct to callers.
|
||||
;
|
||||
|
||||
.export __time_t_to_tm
|
||||
.import udiv32, _mktime
|
||||
.importzp sreg, tmp3, ptr1, ptr2, ptr3, ptr4
|
||||
|
||||
.include "time.inc"
|
||||
|
||||
.macpack cpu
|
||||
|
||||
__time_t_to_tm:
|
||||
; Divide number of seconds since epoch, in ptr1:sreg,
|
||||
; by 86400 to get the number of days since epoch, and
|
||||
; the number of seconds today in the remainder.
|
||||
|
||||
; Load t as dividend (sreg is already set by the caller)
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
|
||||
; Load 86400 as divisor
|
||||
lda #$80
|
||||
sta ptr3
|
||||
lda #$51
|
||||
sta ptr3+1
|
||||
lda #$01
|
||||
sta ptr4
|
||||
lda #$00
|
||||
sta ptr4+1
|
||||
|
||||
; Clear TM buf while we have zero in A
|
||||
ldx #.sizeof(tm)-1
|
||||
: sta TM,x
|
||||
dex
|
||||
bpl :-
|
||||
|
||||
; Divide t/86400
|
||||
jsr udiv32
|
||||
|
||||
; Store the quotient (the number of full days), and increment
|
||||
; by one as epoch starts at day 1.
|
||||
clc
|
||||
lda ptr1
|
||||
adc #1
|
||||
sta TM + tm::tm_mday
|
||||
lda ptr1+1
|
||||
adc #0
|
||||
sta TM + tm::tm_mday+1
|
||||
|
||||
; Now divide the number of remaining seconds by 3600,
|
||||
; to get the number of hours, and the seconds in the
|
||||
; current hour, in neat 16-bit integers.
|
||||
|
||||
; Load the previous division's remainder (in ptr2:tmp3:tmp4)
|
||||
; as dividend
|
||||
lda ptr2
|
||||
sta ptr1
|
||||
lda ptr2+1
|
||||
sta ptr1+1
|
||||
lda tmp3
|
||||
sta sreg
|
||||
; We ignore the high byte stored in tmp4 because it will be
|
||||
; zero. We'll zero sreg+1 right below, when we'll have
|
||||
; a convenient zero already in A.
|
||||
|
||||
; Load divisor
|
||||
lda #<3600
|
||||
sta ptr3
|
||||
lda #>3600
|
||||
sta ptr3+1
|
||||
|
||||
; Zero the two high bytes of the divisor and the high byte
|
||||
; of the dividend.
|
||||
.if .cpu .bitand CPU_ISET_65SC02
|
||||
stz ptr4
|
||||
stz ptr4+1
|
||||
stz sreg+1
|
||||
.else
|
||||
lda #$00
|
||||
sta ptr4
|
||||
sta ptr4+1
|
||||
sta sreg+1
|
||||
.endif
|
||||
|
||||
; Do the division
|
||||
jsr udiv32
|
||||
|
||||
; Store year
|
||||
lda #70
|
||||
sta TM + tm::tm_year
|
||||
|
||||
; Store hours (the quotient of the last division)
|
||||
lda ptr1
|
||||
sta TM + tm::tm_hour
|
||||
lda ptr1+1
|
||||
sta TM + tm::tm_hour+1
|
||||
|
||||
; Store seconds (the remainder of the last division)
|
||||
lda ptr2
|
||||
sta TM + tm::tm_sec
|
||||
lda ptr2+1
|
||||
sta TM + tm::tm_sec+1
|
||||
|
||||
; The rest of the struct tm fields are zero. mktime
|
||||
; will take care of shifting extra seconds to minutes,
|
||||
; and extra days to months and years.
|
||||
|
||||
; Call mktime
|
||||
lda #<TM
|
||||
ldx #>TM
|
||||
jsr _mktime
|
||||
|
||||
; And return our pointer
|
||||
lda #<TM
|
||||
ldx #>TM
|
||||
rts
|
||||
|
||||
.bss
|
||||
|
||||
TM: .tag tm
|
||||
@@ -1,59 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* asctime.c */
|
||||
/* */
|
||||
/* Convert a broken down time into a string */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2002 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
CAUTION: we need to reserve enough space to be able to hold the maximum
|
||||
length string:
|
||||
|
||||
1234567890123456789012345678901234567
|
||||
"Wednesday September ..1 00:00:00 1970"
|
||||
*/
|
||||
|
||||
char* __fastcall__ asctime (const struct tm* timep)
|
||||
{
|
||||
static char buf[38];
|
||||
|
||||
/* Format into given buffer and return the result */
|
||||
return strftime (buf, sizeof (buf), "%c\n", timep)? buf : 0;
|
||||
}
|
||||
81
libsrc/common/asctime.s
Normal file
81
libsrc/common/asctime.s
Normal file
@@ -0,0 +1,81 @@
|
||||
;
|
||||
; Colin Leroy-Mira, 2024
|
||||
;
|
||||
; char* __fastcall__ asctime (const struct tm* timep)
|
||||
;
|
||||
|
||||
.export _asctime
|
||||
.import _strftime, pushax
|
||||
.importzp ptr1
|
||||
.include "time.inc"
|
||||
|
||||
.macpack cpu
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Special values
|
||||
|
||||
; We need to be able to store up to 38 bytes:
|
||||
; 1234567890123456789012345678901234567
|
||||
; "Wednesday September ..1 00:00:00 1970"
|
||||
MAX_BUF_LEN = 38
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Code
|
||||
|
||||
_asctime:
|
||||
; Backup timep
|
||||
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||
pha
|
||||
phx
|
||||
.else
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
.endif
|
||||
|
||||
; Push buf
|
||||
lda #<buf
|
||||
ldx #>buf
|
||||
jsr pushax
|
||||
|
||||
; Push sizeof(buf)
|
||||
lda #<MAX_BUF_LEN
|
||||
ldx #>MAX_BUF_LEN
|
||||
jsr pushax
|
||||
|
||||
; Push format string
|
||||
lda #<fmt
|
||||
ldx #>fmt
|
||||
jsr pushax
|
||||
|
||||
; Restore timep
|
||||
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||
plx
|
||||
pla
|
||||
.else
|
||||
lda ptr1
|
||||
ldx ptr1+1
|
||||
.endif
|
||||
|
||||
; Call formatter
|
||||
jsr _strftime
|
||||
|
||||
; Check return status
|
||||
bne :+
|
||||
cpx #$00
|
||||
bne :+
|
||||
rts
|
||||
|
||||
: lda #<buf
|
||||
ldx #>buf
|
||||
rts
|
||||
|
||||
.data
|
||||
|
||||
fmt: .byte '%'
|
||||
.byte 'c'
|
||||
.byte $0A
|
||||
.byte $00
|
||||
|
||||
.bss
|
||||
|
||||
buf: .res MAX_BUF_LEN
|
||||
24
libsrc/common/checkferror.s
Normal file
24
libsrc/common/checkferror.s
Normal file
@@ -0,0 +1,24 @@
|
||||
;
|
||||
; Colin Leroy-Mira, 2024
|
||||
;
|
||||
; Helper to check for file opened, not eof, not ferror
|
||||
; Expects file pointer in ptr1,
|
||||
; Returns with Z flag set if everything is OK,
|
||||
; Destroys A, X, Y,
|
||||
; Sets file flags in A
|
||||
;
|
||||
|
||||
.export checkferror
|
||||
.importzp ptr1
|
||||
|
||||
.include "_file.inc"
|
||||
|
||||
checkferror:
|
||||
ldy #_FILE::f_flags
|
||||
lda (ptr1),y
|
||||
tax
|
||||
and #(_FOPEN|_FERROR|_FEOF); Check for file open, error/eof
|
||||
tay
|
||||
txa
|
||||
cpy #_FOPEN
|
||||
rts
|
||||
@@ -7,7 +7,7 @@
|
||||
;
|
||||
; See "LICENSE" file for legal information.
|
||||
;
|
||||
; Character specification table, matching serveral consoles.
|
||||
; Character specification table, matching several consoles.
|
||||
;
|
||||
|
||||
.include "ctypetable.inc"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
; 2002-10-22, Greg King
|
||||
;
|
||||
; This signed-division function returns both the quotient and the remainder,
|
||||
; in this structure:
|
||||
; in this structure: (quotient in sreg, remainder in AX)
|
||||
;
|
||||
; typedef struct {
|
||||
; int rem, quot;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user