1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-25 17:29:50 +00:00

Lynx update including file routines that access a file system on a cartridge

by Karri Kaksonen.


git-svn-id: svn://svn.cc65.org/cc65/trunk@4892 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
uz 2010-12-29 10:37:57 +00:00
parent 4a92522c82
commit d993b332a4
10 changed files with 447 additions and 1 deletions

View File

@ -73,11 +73,19 @@
/*****************************************************************************/
/* Code */
/* Accessing the cart */
/*****************************************************************************/
void __fastcall__ lynx_load (int fileno);
/* Load a file into ram. The first entry is fileno=0. */
void __fastcall__ lynx_exec (int fileno);
/* Load a file into ram and execute it. */
/*****************************************************************************/
/* Accessing the EEPROM */
/*****************************************************************************/
@ -94,10 +102,13 @@ void __fastcall__ lynx_eeprom_erase (unsigned char cell);
/* Clear the word at the given address */
/*****************************************************************************/
/* TGI extras */
/*****************************************************************************/
#define tgi_sprite(spr) tgi_ioctl(0, spr)
#define tgi_flip() tgi_ioctl(1, (void*)0)
#define tgi_setbgcolor(bgcol) tgi_ioctl(2, (void*)(bgcol))
@ -106,6 +117,8 @@ void __fastcall__ lynx_eeprom_erase (unsigned char cell);
#define tgi_updatedisplay() tgi_ioctl(4, (void*)1)
#define tgi_setcollisiondetection(active) tgi_ioctl(5, (void*)(active))
/* End of lynx.h */
#endif

View File

@ -49,9 +49,16 @@ OBJS = cgetc.o \
crt0.o \
ctype.o \
eeprom.o \
exec.o \
extzp.o \
kbhit.o \
load.o \
lseek.o \
lynx-cart.o \
mainargs.o \
open.o \
oserror.o \
read.o \
sysuname.o \
toascii.o

34
libsrc/lynx/exec.s Normal file
View File

@ -0,0 +1,34 @@
;
; Karri Kaksonen, 2010
;
; lynx_exec(fileno) loads a file into memory but after the read the CPU
; does a jump into the loaded start address.
;
; lynx_exec is often used in compilation carts when you run small demos
; created with various (non-cc65) compilers.
;
; void lynx_exec(int fileno)
;
.importzp _FileDestAddr
.import pushax,ldax0sp,incsp2
.import _lynx_load
.export _lynx_exec
; ---------------------------------------------------------------
; void __near__ __fastcall__ lynx_exec (int)
; ---------------------------------------------------------------
.segment "CODE"
.proc _lynx_exec: near
.segment "CODE"
jsr pushax
jsr ldax0sp
jsr _lynx_load
jsr incsp2
jmp (_FileDestAddr)
.endproc

41
libsrc/lynx/load.s Normal file
View File

@ -0,0 +1,41 @@
;
; Karri Kaksonen, 2010
;
; lynx_load(fileno) is a convenience function that is widely used on the Lynx.
; Basically this opens directory entry fileno and reads the content of the
; file this points to into RAM.
;
; void lynx_load(int fileno)
;
.importzp _FileFileLen
.importzp _FileDestAddr
.import pushax,ldax0sp,pusha0,incsp2
.import _openn
.import _read
.export _lynx_load
; ---------------------------------------------------------------
; void __near__ __fastcall__ lynx_load (int)
; ---------------------------------------------------------------
.segment "CODE"
.proc _lynx_load: near
.segment "CODE"
jsr pushax
jsr ldax0sp
jsr _openn
lda #$01
jsr pusha0
lda _FileDestAddr
ldx _FileDestAddr+1
jsr pushax
lda _FileFileLen
ldx _FileFileLen+1
jsr _read
jmp incsp2
.endproc

59
libsrc/lynx/lseek.s Normal file
View File

@ -0,0 +1,59 @@
;
; Karri Kaksonen, 2010
;
; This function is used to place the Lynx hardware to point to any byte in
; the Lynx cart.
;
; This function supports all available block sizes (512, 1024 and 2048 bytes).
; No other block sizes have been used afaik.
;
; Only SEEK_SET operation mode is implemented.
;
; off_t __fastcall__ lseek(int fd, off_t offset, int whence);
.importzp sp, sreg, regsave, regbank, tmp1, ptr1, ptr2
.macpack longbranch
.export _lseek
.import addysp, stax0sp, tosand0ax, pusheax, asreax2
.import ldeaxysp, decsp2, pushax, incsp8
.import tosandeax,decax1,tosdiveax,axlong,ldaxysp
.import lynxskip0, lynxblock,tosasreax
.import __BLOCKSIZE__
.importzp _FileCurrBlock
.segment "CODE"
.proc _lseek: near
.segment "CODE"
jsr pushax
ldy #$05
jsr ldeaxysp
jsr pusheax
ldx #$00
lda #<(__BLOCKSIZE__/1024 + 9)
jsr tosasreax
sta _FileCurrBlock
jsr lynxblock
ldy #$05
jsr ldeaxysp
jsr pusheax
lda #<(__BLOCKSIZE__-1)
ldx #>(__BLOCKSIZE__-1)
jsr decax1
jsr axlong
jsr tosandeax
eor #$FF
pha
txa
eor #$FF
tay
plx
jsr lynxskip0
ldy #$05
jsr ldeaxysp
jmp incsp8
.endproc

99
libsrc/lynx/lynx-cart.s Normal file
View File

@ -0,0 +1,99 @@
; ***
; CC65 Lynx Library
;
; Originally by Bastian Schick
; http://www.geocities.com/SiliconValley/Byte/4242/lynx/
;
; Ported to cc65 (http://www.cc65.org) by
; Shawn Jefferson, June 2004
;
; This version by Karri Kaksonen, December 2010
;
; Helper stuff for the cartridge file functions. This version can deal
; with 1024 bytes/block carts that are using CART0 as a read strobe.
; Also the default crt0.s supports this most common Lynx cart format.
.include "lynx.inc"
.include "extzp.inc"
.export lynxskip0, lynxread0
.export lynxblock
__BLOCKSIZE0__ = 1024
.code
;**********************************
; Skip bytes on bank 0
; X:Y count (EOR $FFFF)
;**********************************
lynxskip0:
inx
bne @0
iny
beq exit
@0: jsr readbyte0
bra lynxskip0
;**********************************
; Read bytes from bank 0
; X:Y count (EOR $ffff)
;**********************************
lynxread0:
inx
bne @1
iny
beq exit
@1: jsr readbyte0
sta (_FileDestPtr)
inc _FileDestPtr
bne lynxread0
inc _FileDestPtr+1
bra lynxread0
;**********************************
; Read one byte from cartridge
;**********************************
readbyte0:
lda RCART0
inc _FileBlockByte
bne exit
inc _FileBlockByte+1
bne exit
;**********************************
; Select a block
;**********************************
lynxblock:
pha
phx
phy
lda __iodat
and #$fc
tay
ora #2
tax
lda _FileCurrBlock
inc _FileCurrBlock
sec
bra @2
@0: bcc @1
stx IODAT
clc
@1: inx
stx SYSCTL1
dex
@2: stx SYSCTL1
rol
sty IODAT
bne @0
lda __iodat
sta IODAT
stz _FileBlockByte
lda #$100-(>__BLOCKSIZE0__)
sta _FileBlockByte+1
ply
plx
pla
exit: rts

127
libsrc/lynx/open.s Normal file
View File

@ -0,0 +1,127 @@
;
; Karri Kaksonen, 2010
;
; This function reads the directory entry for file "name".
;
; The name is actually plain ASCII string starting from
; "0", "1", up to "4095" which is the largest file number we can handle.
;
; open() does not take part in what kind of cart we have. If it is RAM
; you may also be able to write into it. Therefore we allow both reads
; and writes in this routine.
;
; int open(const char *name, int flags, ...)
;
; As helper functions we also provide.
; void openn(int fileno)
;
.importzp sreg, tmp3
.macpack longbranch
.import _atoi
.import _read
.import _lseek
.import addysp,popax,pushax,decsp6,pusha0,pusheax,ldaxysp
.import aslax3,axlong,tosaddeax,steaxysp,stax0sp,incsp8
.import ldax0sp
.importzp _FileEntry
.importzp _FileStartBlock
.importzp _FileCurrBlock
.importzp _FileBlockOffset
.import __STARTOFDIRECTORY__
.export _open
.export _openn
.include "errno.inc"
.include "fcntl.inc"
.segment "DATA"
_startofdirectory:
.dword __STARTOFDIRECTORY__
; ---------------------------------------------------------------
; int __near__ open (__near__ const unsigned char*, int)
; ---------------------------------------------------------------
.segment "CODE"
.proc _open
.segment "CODE"
dey
dey
dey
dey
beq parmok
jsr addysp
parmok: jsr popax
sta tmp3
and #(O_RDWR | O_CREAT)
cmp #O_RDONLY
beq flagsok
cmp #(O_WRONLY | O_CREAT)
beq flagsok
lda #EINVAL
ldx #0
jmp __directerrno
flagsok:
jsr popax
jsr _atoi
jsr pushax
jsr ldax0sp
jsr _openn
ldx #$00
lda #$01
stx __oserror
rts
.endproc
; ---------------------------------------------------------------
; void __near__ __fastcall__ openn (int)
; ---------------------------------------------------------------
.segment "CODE"
.proc _openn: near
.segment "CODE"
jsr pushax
jsr decsp6
lda #$01
jsr pusha0
lda _startofdirectory+3
sta sreg+1
lda _startofdirectory+2
sta sreg
ldx _startofdirectory+1
lda _startofdirectory
jsr pusheax
ldy #$0D
jsr ldaxysp
jsr aslax3
jsr axlong
jsr tosaddeax
jsr pusheax
ldx #$00
txa
jsr _lseek
ldy #$02
jsr steaxysp
lda #$01
jsr pusha0
lda _FileEntry
ldx _FileEntry+1
jsr pushax
ldx #$00
lda #$08
jsr _read
jsr stax0sp
jmp incsp8
.endproc

14
libsrc/lynx/oserror.s Normal file
View File

@ -0,0 +1,14 @@
;
; Karri Kaksonen, 2010
;
; int __fastcall__ _osmaperrno (unsigned char oserror);
; /* Map a system specific error into a system independent code */
;
.include "errno.inc"
.code
__osmaperrno:
rts

50
libsrc/lynx/read.s Normal file
View File

@ -0,0 +1,50 @@
;
; Karri Kaksonen, 2010
;
; This function reads count bytes from the place where the address counter is.
; Use lseek to place the address counter where you want to read from.
;
; The file descriptor is ignored in this implementation. The read operation
; reads bytes from a raw cart and does not understand the concept of files.
; So if you read over the end of file you get data from the next file.
;
; The count-parameter can be positive (Atari style) or negative (BLL style).
; In any case the read routine will work correctly.
;
; int __fastcall__ read(int fd,void *buf,int count)
;
.importzp _FileDestPtr
.import lynxread0
.import pushax,ldaxysp,ldax0sp,incsp6
.export _read
.segment "CODE"
.proc _read: near
.segment "CODE"
jsr pushax
ldy #$03
jsr ldaxysp
sta _FileDestPtr
stx _FileDestPtr+1
jsr ldax0sp
phx ; The BLL kit uses negative counts
plx ; while the basic Lynx uses positive
bmi @1 ; make all counts negative
eor #$FF
pha
txa
eor #$FF
bra @2
@1: pha
txa
@2: tay
plx
jsr lynxread0
jsr ldax0sp
jmp incsp6
.endproc

View File

@ -1,5 +1,7 @@
SYMBOLS {
__STACKSIZE__: type = weak, value = $0800; # 2k stack
__STARTOFDIRECTORY__: type = weak, value = $019A; # start just after loader
__BLOCKSIZE__: type = weak, value = 1024; # cart block size
}
MEMORY {
ZP: file = "", define = yes, start = $0000, size = $0100;