--- /dev/null
+;
+; Low level file I/O routines, ONLY for module loading OR sth similar
+;
+; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl>
+; 25.12.2002
+;
+; only ONE opened file at a time, only O_RDONLY flag
+
+; int open (const char* name, int flags, ...); /* May take a mode argument */
+; int __fastcall__ close (int fd);
+; int __fastcall__ read (int fd, void* buf, unsigned count);
+
+FILEDES = 3 ; first free to use file descriptor
+
+ .include "../inc/geossym.inc"
+ .include "../inc/const.inc"
+ .include "fcntl.inc"
+
+ .importzp ptr1, ptr2, ptr3, tmp1
+ .import addysp, popax
+ .import __oserror
+ .import _FindFile, _ReadByte
+
+ .export _open, _close, _read
+
+
+;--------------------------------------------------------------------------
+; _open
+
+_open:
+
+ cpy #4 ; correct # of arguments (bytes)?
+ beq @parmok ; parameter count ok
+ tya ; parm count < 4 shouldn't be needed to be...
+ sec ; ...checked (it generates a c compiler warning)
+ sbc #4
+ tay
+ jsr addysp ; fix stack, throw away unused parameters
+
+; Parameters ok. Pop the flags and save them into tmp3
+
+@parmok:
+ jsr popax ; Get flags
+ sta tmp1
+ jsr popax ; Get name
+ sta ptr1
+ stx ptr1+1
+
+ lda filedesc ; is there a file already open?
+ bne @alreadyopen
+
+ lda tmp1 ; check open mode
+ and #(O_RDWR | O_CREAT)
+ cmp #O_RDONLY ; only O_RDONLY is valid
+ bne @badmode
+
+ lda ptr1
+ ldx ptr1+1
+ jsr _FindFile ; try to find the file
+ bne @error
+
+ lda dirEntryBuf + OFF_DE_TR_SC ; tr&se for ReadByte (r1)
+ sta f_track
+ lda dirEntryBuf + OFF_DE_TR_SC + 1
+ sta f_sector
+ lda #<diskBlkBuf ; buffer for ReadByte (r4)
+ sta f_buffer
+ lda #>diskBlkBuf
+ sta f_buffer+1
+ ldx #0 ; offset for ReadByte (r5)
+ stx f_offset
+ stx f_offset+1
+ lda #FILEDES ; return fd
+ sta filedesc
+ rts
+@badmode:
+@alreadyopen:
+ lda #70 ; no channel
+ sta __oserror
+@error:
+ lda #$ff
+ tax
+ rts
+
+_close:
+ lda #0 ; clear fd
+ sta filedesc
+ tax
+ rts
+
+_read:
+ ; a/x - number of bytes
+ ; popax - buffer ptr
+ ; popax - fd, must be == to the above one
+ ; return -1+__oserror or number of bytes read
+
+ eor #$ff
+ sta ptr1
+ txa
+ eor #$ff
+ sta ptr1+1 ; -(# of bytes to read)-1
+ jsr popax
+ sta ptr2
+ stx ptr2+1 ; buffer ptr
+ jsr popax
+ cmp #FILEDES
+ bne @notopen
+ txa
+ bne @notopen ; fd must be == FILEDES
+
+ lda #0
+ sta ptr3
+ sta ptr3+1 ; put 0 into ptr3 (number of bytes read)
+
+ lda f_track ; restore stuff for ReadByte
+ ldx f_sector
+ sta r1L
+ stx r1H
+ lda f_buffer
+ ldx f_buffer+1
+ sta r4L
+ stx r4H
+ lda f_offset
+ ldx f_offset+1
+ sta r5L
+ stx r5H
+
+ clc
+ bcc @L3 ; branch always
+
+@L0: jsr _ReadByte
+ ldy #0 ; store the byte
+ sta (ptr2),y
+ inc ptr2 ; increment target address
+ bne @L1
+ inc ptr2+1
+
+@L1: inc ptr3 ; increment byte count
+ bne @L2
+ inc ptr3+1
+
+@L2: txa ; was there error ?
+ beq @L3
+ cmp #BFR_OVERFLOW ; EOF?
+ bne @error
+ beq @done
+
+@L3: inc ptr1 ; decrement the count
+ bne @L0
+ inc ptr1+1
+ bne @L0
+
+@done:
+ lda r1L ; preserve data for ReadByte
+ ldx r1H
+ sta f_track
+ stx f_sector
+ lda r4L
+ ldx r4H
+ sta f_buffer
+ stx f_buffer+1
+ lda r5L
+ ldx r5H
+ sta f_offset
+ stx f_offset+1
+
+ lda ptr3 ; return byte count
+ ldx ptr3+1
+ rts
+
+@notopen:
+ lda #61 ; File not open
+@error:
+ sta __oserror
+ lda #$ff
+ tax
+ rts
+
+.bss
+filedesc: .res 1 ; file open flag - 0 (no file opened) or 1
+f_track: .res 1 ; values preserved for ReadByte
+f_sector: .res 1
+f_offset: .res 2
+f_buffer: .res 2
--- /dev/null
+;
+; Extended memory driver for the VDC RAM available on all C128 machines
+; version for GEOS enters safe I/O config on C64 (transparent on C128)
+;
+; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl>
+; 06,20,25.12.2002
+
+ .include "zeropage.inc"
+
+ .include "em-kernel.inc"
+ .include "em-error.inc"
+
+
+ .macpack generic
+
+
+; ------------------------------------------------------------------------
+; Header. Includes jump table
+
+.segment "JUMPTABLE"
+
+; Driver signature
+
+ .byte $65, $6d, $64 ; "emd"
+ .byte $00 ; EM API version number
+
+; Jump table.
+
+ .word INSTALL
+ .word DEINSTALL
+ .word PAGECOUNT
+ .word MAP
+ .word USE
+ .word COMMIT
+ .word COPYFROM
+ .word COPYTO
+
+; ------------------------------------------------------------------------
+; Constants
+
+VDC_ADDR_REG = $D600 ; VDC address
+VDC_DATA_REG = $D601 ; VDC data
+
+VDC_DATA_HI = 18 ; used registers
+VDC_DATA_LO = 19
+VDC_CSET = 28
+VDC_DATA = 31
+
+; ------------------------------------------------------------------------
+; Data.
+
+.data
+
+pagecount: .word 64 ; $0000-$3fff as 16k default
+curpage: .word $ffff ; currently mapped-in page (invalid)
+
+.bss
+
+window: .res 256 ; memory window
+
+.code
+
+; ------------------------------------------------------------------------
+; INSTALL routine. Is called after the driver is loaded into memory. If
+; possible, check if the hardware is present and determine the amount of
+; memory available.
+; Must return an EM_ERR_xx code in a/x.
+;
+
+INSTALL:
+ ; do test for VDC presence here???
+
+ php
+ sei
+ lda $01
+ pha
+ lda #$35
+ sta $01
+
+ ldx #VDC_CSET ; determine size of RAM...
+ jsr vdcgetreg
+ sta tmp1
+ ora #%00010000
+ jsr vdcputreg ; turn on 64k
+
+ jsr settestadr1 ; save original value of test byte
+ jsr vdcgetbyte
+ sta tmp2
+
+ lda #$55 ; write $55 here
+ ldy #ptr1
+ jsr test64k ; read it here and there
+ lda #$aa ; write $aa here
+ ldy #ptr2
+ jsr test64k ; read it here and there
+
+ jsr settestadr1
+ lda tmp2
+ jsr vdcputbyte ; restore original value of test byte
+
+ lda ptr1 ; do bytes match?
+ cmp ptr1+1
+ bne @have64k
+ lda ptr2
+ cmp ptr2+1
+ bne @have64k
+
+ ldx #VDC_CSET
+ lda tmp1
+ jsr vdcputreg ; restore 16/64k flag
+ jmp @endok ; and leave default values for 16k
+
+@have64k:
+ lda #<256
+ ldx #>256
+ sta pagecount
+ stx pagecount+1
+@endok:
+ pla
+ sta $01
+ plp
+ lda #<EM_ERR_OK
+ ldx #>EM_ERR_OK
+ rts
+
+test64k:
+ sta tmp1
+ sty ptr3
+ lda #0
+ sta ptr3+1
+ jsr settestadr1
+ lda tmp1
+ jsr vdcputbyte ; write $55
+ jsr settestadr1
+ jsr vdcgetbyte ; read here
+ pha
+ jsr settestadr2
+ jsr vdcgetbyte ; and there
+ ldy #1
+ sta (ptr3),y
+ pla
+ dey
+ sta (ptr3),y
+ rts
+
+settestadr1:
+ ldy #$02 ; test page 2 (here)
+ .byte $2c
+settestadr2:
+ ldy #$42 ; or page 64+2 (there)
+ lda #0
+ jmp vdcsetsrcaddr
+
+; ------------------------------------------------------------------------
+; DEINSTALL routine. Is called before the driver is removed from memory.
+; Can do cleanup or whatever. Must not return anything.
+;
+
+DEINSTALL:
+ ;on C128 restore font and clear the screen?
+ rts
+
+; ------------------------------------------------------------------------
+; PAGECOUNT: Return the total number of available pages in a/x.
+;
+
+PAGECOUNT:
+ lda pagecount
+ ldx pagecount+1
+ rts
+
+; ------------------------------------------------------------------------
+; MAP: Map the page in a/x into memory and return a pointer to the page in
+; a/x. The contents of the currently mapped page (if any) may be discarded
+; by the driver.
+;
+
+MAP: sta curpage
+ stx curpage+1
+ sta ptr1+1
+ ldy #0
+ sty ptr1
+
+ lda #<window
+ sta ptr2
+ lda #>window
+ sta ptr2+1
+
+ jsr transferin
+
+ lda #<window
+ ldx #>window
+ rts
+
+; copy a single page from (ptr1):VDCRAM to (ptr2):RAM
+
+transferin:
+ php
+ sei
+ lda $01
+ pha
+ lda #$35
+ sta $01
+ lda ptr1
+ ldy ptr1+1
+ jsr vdcsetsrcaddr ; set source address in VDC
+ ldy #0
+ ldx #VDC_DATA
+ stx VDC_ADDR_REG
+@L0: bit VDC_ADDR_REG
+ bpl @L0
+ lda VDC_DATA_REG ; get 2 bytes at a time to speed-up
+ sta (ptr2),y ; (in fact up to 8 bytes could be fetched with special VDC config)
+ iny
+ lda VDC_DATA_REG
+ sta (ptr2),y
+ iny
+ bne @L0
+ pla
+ sta $01
+ plp
+ rts
+
+; ------------------------------------------------------------------------
+; USE: Tell the driver that the window is now associated with a given page.
+
+USE: sta curpage
+ stx curpage+1 ; Remember the page
+ lda #<window
+ ldx #>window ; Return the window
+done: rts
+
+; ------------------------------------------------------------------------
+; COMMIT: Commit changes in the memory window to extended storage.
+
+COMMIT:
+ lda curpage ; jump if no page mapped
+ ldx curpage+1
+ bmi done
+ sta ptr1+1
+ ldy #0
+ sty ptr1
+
+ lda #<window
+ sta ptr2
+ lda #>window
+ sta ptr2+1
+
+; fall through to transferout
+
+; copy a single page from (ptr2):RAM to (ptr1):VDCRAM
+
+transferout:
+ php
+ sei
+ lda $01
+ pha
+ lda #$35
+ sta $01
+ lda ptr1
+ ldy ptr1+1
+ jsr vdcsetsrcaddr ; set source address in VDC
+ ldy #0
+ ldx #VDC_DATA
+ stx VDC_ADDR_REG
+@L0: bit VDC_ADDR_REG
+ bpl @L0
+ lda (ptr2),y ; speedup does not work for writing
+ sta VDC_DATA_REG
+ iny
+ bne @L0
+ pla
+ sta $01
+ plp
+ rts
+
+; ------------------------------------------------------------------------
+; COPYFROM: Copy from extended into linear memory. A pointer to a structure
+; describing the request is passed in a/x.
+; The function must not return anything.
+;
+
+COPYFROM:
+ jsr setup
+ beq @L2 ; Skip if no full pages
+
+; Copy full pages
+
+@L1: jsr transferin
+ inc ptr1+1
+ inc ptr2+1
+ dec tmp1
+ bne @L1
+
+; Copy the remainder of the page
+
+@L2: ldy #EM_COPY_COUNT
+ lda (ptr3),y ; Get bytes in last page
+ beq @L4
+ sta tmp1
+
+; Transfer the bytes in the last page
+ php
+ sei
+ lda $01
+ pha
+ lda #$35
+ sta $01
+ ldy #0
+@L3: jsr vdcgetbyte
+ sta (ptr2),y
+ iny
+ dec tmp1
+ lda tmp1
+ bne @L3
+ pla
+ sta $01
+ plp
+@L4: rts
+
+; ------------------------------------------------------------------------
+; COPYTO: Copy from linear into extended memory. A pointer to a structure
+; describing the request is passed in a/x.
+; The function must not return anything.
+;
+
+COPYTO:
+ jsr setup
+ beq @L2 ; Skip if no full pages
+
+; Copy full pages
+
+@L1: jsr transferout
+ inc ptr1+1
+ inc ptr2+1
+ dec tmp1
+ bne @L1
+
+; Copy the remainder of the page
+
+@L2: ldy #EM_COPY_COUNT
+ lda (ptr3),y ; Get bytes in last page
+ beq @L4
+ sta tmp1
+
+; Transfer the bytes in the last page
+ php
+ sei
+ lda $01
+ pha
+ lda #$35
+ sta $01
+ ldy #0
+@L3: lda (ptr2),y
+ jsr vdcputbyte
+ iny
+ dec tmp1
+ lda tmp1
+ bne @L3
+ pla
+ sta $01
+ plp
+@L4: rts
+
+;-------------------------------------------------------------------------
+; Helper functions to handle VDC ram
+;
+
+vdcsetsrcaddr:
+ ldx #VDC_DATA_LO
+ stx VDC_ADDR_REG
+@L0: bit VDC_ADDR_REG
+ bpl @L0
+ sta VDC_DATA_REG
+ dex
+ tya
+ stx VDC_ADDR_REG
+ sta VDC_DATA_REG
+ rts
+
+vdcgetbyte:
+ ldx #VDC_DATA
+vdcgetreg:
+ stx VDC_ADDR_REG
+@L0: bit VDC_ADDR_REG
+ bpl @L0
+ lda VDC_DATA_REG
+ rts
+
+vdcputbyte:
+ ldx #VDC_DATA
+vdcputreg:
+ stx VDC_ADDR_REG
+@L0: bit VDC_ADDR_REG
+ bpl @L0
+ sta VDC_DATA_REG
+ rts
+
+; ------------------------------------------------------------------------
+; Helper function for COPYFROM and COPYTO: Store the pointer to the request
+; structure and prepare data for the copy
+;
+
+setup:
+ sta ptr3
+ stx ptr3+1 ; Save the passed em_copy pointer
+
+ ldy #EM_COPY_OFFS
+ lda (ptr3),y
+ sta ptr1
+ ldy #EM_COPY_PAGE
+ lda (ptr3),y
+ sta ptr1+1 ; From
+
+ ldy #EM_COPY_BUF
+ lda (ptr3),y
+ sta ptr2
+ iny
+ lda (ptr3),y
+ sta ptr2+1 ; To
+
+ ldy #EM_COPY_COUNT+1
+ lda (ptr3),y ; Get number of pages
+ sta tmp1
+ rts
+