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:
parent
4a92522c82
commit
d993b332a4
@ -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
|
||||
|
||||
|
@ -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
34
libsrc/lynx/exec.s
Normal 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
41
libsrc/lynx/load.s
Normal 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
59
libsrc/lynx/lseek.s
Normal 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
99
libsrc/lynx/lynx-cart.s
Normal 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
127
libsrc/lynx/open.s
Normal 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
14
libsrc/lynx/oserror.s
Normal 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
50
libsrc/lynx/read.s
Normal 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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user