]> git.sur5r.net Git - cc65/commitdiff
Lynx update including file routines that access a file system on a cartridge
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Wed, 29 Dec 2010 10:37:57 +0000 (10:37 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Wed, 29 Dec 2010 10:37:57 +0000 (10:37 +0000)
by Karri Kaksonen.

git-svn-id: svn://svn.cc65.org/cc65/trunk@4892 b7a2c559-68d2-44c3-8de9-860c34a00d81

include/lynx.h
libsrc/lynx/Makefile
libsrc/lynx/exec.s [new file with mode: 0644]
libsrc/lynx/load.s [new file with mode: 0644]
libsrc/lynx/lseek.s [new file with mode: 0644]
libsrc/lynx/lynx-cart.s [new file with mode: 0644]
libsrc/lynx/open.s [new file with mode: 0644]
libsrc/lynx/oserror.s [new file with mode: 0644]
libsrc/lynx/read.s [new file with mode: 0644]
src/ld65/cfg/lynx.cfg

index 985c33fe94d6662e4ad4e459b63f7aecab888fde..b127b28251db17b595657a48534f08900c64fbf2 100644 (file)
 
 
 /*****************************************************************************/
-/*                                  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
 
index 7225ebddb6500ab44c83e4777034e5cd44137d8e..07cf5c20c61eeb61362453acc8a2fce266cb1241 100644 (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
 
diff --git a/libsrc/lynx/exec.s b/libsrc/lynx/exec.s
new file mode 100644 (file)
index 0000000..44550fd
--- /dev/null
@@ -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
+
diff --git a/libsrc/lynx/load.s b/libsrc/lynx/load.s
new file mode 100644 (file)
index 0000000..2e6baa9
--- /dev/null
@@ -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
+
diff --git a/libsrc/lynx/lseek.s b/libsrc/lynx/lseek.s
new file mode 100644 (file)
index 0000000..1d9d93b
--- /dev/null
@@ -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
+
diff --git a/libsrc/lynx/lynx-cart.s b/libsrc/lynx/lynx-cart.s
new file mode 100644 (file)
index 0000000..f740614
--- /dev/null
@@ -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
+
diff --git a/libsrc/lynx/open.s b/libsrc/lynx/open.s
new file mode 100644 (file)
index 0000000..9e22f62
--- /dev/null
@@ -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
+
diff --git a/libsrc/lynx/oserror.s b/libsrc/lynx/oserror.s
new file mode 100644 (file)
index 0000000..f3643a5
--- /dev/null
@@ -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
+
diff --git a/libsrc/lynx/read.s b/libsrc/lynx/read.s
new file mode 100644 (file)
index 0000000..c461e37
--- /dev/null
@@ -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
+
index e756395d5ee7ca7c9d281db835aa9cb4111eb776..d94b1fa90935ee3217a648c087f4cbac8cc48b59 100644 (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;