Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.sys.apple2.programmer > #838 > unrolled thread

DOS 3.3 RWTS - C65 library function - please help

Started by"Bill Buckels" <bbuckels@mts.net>
First post2013-08-30 12:14 -0500
Last post2013-08-30 22:16 -0500
Articles 7 — 2 participants

Back to article view | Back to comp.sys.apple2.programmer


Contents

  DOS 3.3 RWTS - C65 library function - please help "Bill Buckels" <bbuckels@mts.net> - 2013-08-30 12:14 -0500
    Re: DOS 3.3 RWTS - C65 library function - please help "Bill Buckels" <bbuckels@mts.net> - 2013-08-30 12:19 -0500
      Re: DOS 3.3 RWTS - C65 library function - please help "Bill Buckels" <bbuckels@mts.net> - 2013-08-30 12:28 -0500
        Re: DOS 3.3 RWTS - C65 library function - please help "Bill Buckels" <bbuckels@mts.net> - 2013-08-30 13:19 -0500
    Re: DOS 3.3 RWTS - C65 library function - please help Antoine Vignau <antoine.vignau@laposte.net> - 2013-08-30 12:35 -0700
      Re: DOS 3.3 RWTS - C65 library function - please help "Bill Buckels" <bbuckels@mts.net> - 2013-08-30 17:07 -0500
    Re: DOS 3.3 RWTS - C65 library function - please help "Bill Buckels" <bbuckels@mts.net> - 2013-08-30 22:16 -0500

#838 — DOS 3.3 RWTS - C65 library function - please help

From"Bill Buckels" <bbuckels@mts.net>
Date2013-08-30 12:14 -0500
SubjectDOS 3.3 RWTS - C65 library function - please help
Message-ID<kvqju7$lph$1@speranza.aioe.org>
The following Code will not work in the Aztec C65 3.2b compiler but works in 
the previous version. I have commented the heck out of it. Any thoughts, 
tips, or solutions?

 I will follow this listing with an uncommented original source.

VAL EQU 0
SP EQU 2
FRAME EQU 4
PC EQU 6
R0 EQU 8
R1 EQU 12
R2 EQU 16

* Removed old equates from CII (old version)
* ACC EQU 20
* SEC EQU 22
* Added Zero Page offsets for this version (3.2b)

ACC EQU 28
SEC EQU 30

*
*
* call sequence (stack offsets below):
*
* rwts(tr, se, buf, cmd, sl, dr, vol);
*      01  23  45   67   89  ab  cd
*
*
* Accumulator (A)
* Stack pointer (S)
* Processor status (P)
* Index registers (X and Y)
*
* # - immediate mode of addressing is signified by a
*     # (pound sign) followed by a constant (i.e. a decimal value)
*
* () - indexed indirect - parentheses around a zero page address
*JSR $3D9 ;call RWTS (with IOB address in Y/A)
*
*The IOB (Input/Output Block)
*============================
*
*$00 table type (always $01)
*$01 slot *16
*$02 drive (1 or 2)
*$03 volume expected ($00 for any)
*$04 track ($0-$22)
*$05 sector ($0-$0f)
*$06-07 address (lo/hi) of the Device Characteristics Table
*$08-09 address (lo/hi) of the 256 byte buffer for read/write
*$0A not used
*$0B byte count for partial sector ($00 for 256 bytes)
*$0C command code (0= seek, 1=read, 2=write, 4=format)
*$0D return code (carry set on error):
* $00 = no errors
* $08 = error during initialization
* $10 = write protect error
* $20 = volume mismatch error
* $40 = drive error
* $80 = read error (obsolete)
*$0E volume number of last access (must be initialized)
*$0F slot number of last access *16 (must be initialized)
*$10 drive number of last access (must be initialized)
*
*Device characteristics table:
*============================
*
*$00 device type (should be $00 for DiskII)
*$01 phases per track (should be $01 for DiskII)
*$02-03 motor on time count (should be $EFD8 for DiskII)
*
* NOTE: RWTS uses zero-page location $48, which is also used by the Apple
* monitor to hold the P-register value.
*
* Location $48 should be set to zero after each call to RWTS.
* (Not Done Below - No need for monitor I guess.)
IOB EQU $48
*
cseg
public rwts_
rwts_ clc           ; clear carry flag
jsr $3e3  ; get address of RWTS IOB
 sta IOB+1 ; IOB address in Y/A)
 sty IOB
* This provides the following:
* - address of the device characteristics table
* - volume number of last access
* - slot number of last access * 16
* - drive number of last access
*
* Track
 ldy #0       ; track offset on stack
 lda (SP),y   ; put track in accumulator
 ldy #4       ; track offset in IOB
 sta (IOB),y  ; put track into IOB
* Sector
 ldy #2       ; sector offset on stack
 lda (SP),y   ; put sector in accumulator
 ldy #5       ; sector offset in IOB
 sta (IOB),y  ; put sector into IOB
* Sector Buffer for R/W
 ldy #4       ; sector buffer address low order byte on stack
 lda (SP),y   ; put in accumulator
 ldy #8       ; offset in IOB
 sta (IOB),y  ; put in IOB
 ldy #5       ; sector buffer address hi order byte on stack
 lda (SP),y   ; put in accumulator
 ldy #9       ; offset in IOB
 sta (IOB),y  ; put in IOB
* Command
 ldy #6  ; command code offset on stack
 lda (SP),y  ; put command code in accumulator
 ldy #$c  ; command code offset in IOB
 sta (IOB),y  ; put accumulator into IOB
* Slot
 ldy #8       ; slot offset on stack
 lda (SP),y  ; put slot in accumulator
 asl a  ; shift slot left 4 times
 asl a        ; (multiply * 16)
 asl a
 asl a
 ldy #1  ; slot * 16 offset in IOB
 sta (IOB),y  ; put slot in IOB
* Drive
 ldy #10  ; drive offset on stack
 lda (SP),y  ; put drive in accumulator
 ldy #2  ; drive offset in IOB
 sta (IOB),y  ; put drive in IOB
* Volume
 ldy #12  ; volume offset on stack
 lda (SP),y  ; put volume in accumulator
 ldy #3  ; volume offset in IOB
 sta (IOB),y  ; put volume in IOB
 jsr $3e3 ; get address of RWTS IOB
 jsr $3d9 ; call RWTS
* Return Code
        ldy     #13        ; return code offset in IOB
        lda     (IOB),y    ; put in accumulator
        sta     R0+1       ; put accumulator in low byte
 ldy #0         ; load 0 as high byte
 sty     R0         ; store 0 - provides integer return of error
 clc                ; clear carry
 rts                ; return from subroutine
* Old return code
* Returned 0 (success) or ffff (error, -1)
*
* old code checked carry flag and if no carry jumped
* if carry decremented 0 byte
* duplicated byte to make integer return register
* ldy #0
* bcc .1
* dey
*.1 sty R0
* sty R0+1
* rts

[toc] | [next] | [standalone]


#839

From"Bill Buckels" <bbuckels@mts.net>
Date2013-08-30 12:19 -0500
Message-ID<kvqk7e$mmq$1@speranza.aioe.org>
In reply to#838
"Bill Buckels" <bbuckels@mts.net> wrote:
> I will follow this listing with an uncommented original source

Note: the zero page registers below are not all used;  the SP (stack 
pointer) and R0 are the only regs used.

I will follow this listing with the zero page header from 3.2b (the newer 
version).

VAL EQU 0
SP EQU 2
FRAME EQU 4
PC EQU 6
R0 EQU 8
R1 EQU 12
R2 EQU 16
ACC EQU 20
SEC EQU 22
*
*
* call sequence:
*
*rwts(tr, se, buf, cmd, sl, dr, vol);
*
*
IOB EQU $48
*
 cseg
 public rwts_
rwts_ jsr $3e3
 sta IOB+1
 sty IOB
 ldy #0
 lda (SP),y
 ldy #4
 sta (IOB),y
 ldy #2
 lda (SP),y
 ldy #5
 sta (IOB),y
 ldy #4
 lda (SP),y
 ldy #8
 sta (IOB),y
 ldy #5
 lda (SP),y
 ldy #9
 sta (IOB),y
 ldy #6
 lda (SP),y
 ldy #$c
 sta (IOB),y
 ldy #8
 lda (SP),y
 asl a
 asl a
 asl a
 asl a
 ldy #1
 sta (IOB),y
 ldy #10
 lda (SP),y
 ldy #2
 sta (IOB),y
 ldy #12
 lda (SP),y
 ldy #3
 sta (IOB),y
 jsr $3e3
 jsr $3d9
 ldy #0
 bcc .1
 dey
.1 sty R0
 sty R0+1
 rts

[toc] | [prev] | [next] | [standalone]


#840

From"Bill Buckels" <bbuckels@mts.net>
Date2013-08-30 12:28 -0500
Message-ID<kvqkp2$o9f$1@speranza.aioe.org>
In reply to#839
"Bill Buckels" <bbuckels@mts.net> wrote:
> I will follow this listing with the zero page header from 3.2b (the newer
version).

As I said initially, this is a real noodle-scratcher. It works flawlessly in 
the old version leading me to believe some other setting within the 
compiler's runtime has changed besides adding a couple more registers to 
zero page.

My thoughts are currently to break this into smaller public functions to 
decompose the problem,
then do hexdumps to disk for analysis, or maybe print in memory.

But before I do that, It nags me that working code was in the old compiler's 
library but never added into the library for the newer version; do you think 
that Aztec C65's developers had the same problem, so decided to remove rwts 
from the rewritten 3.2b library for that reason?

Anyway, here's the current zero page settings:

I will provide one more zero page layout after the one below which shows the 
differences between the old version's equates and the new version's equates 
more precisely.


* These are set up for the Apple // Dos 3.3

STK EQU $00  ;8 byte stack area
VAL EQU STK
SP EQU STK+2
AFRAME EQU STK+4
FRAME EQU STK+4
LFRAME EQU STK+6
PC EQU STK+6

TREGS equ $08  ;24 byte tmp register area
R0 EQU TREGS+0
R1 EQU TREGS+4
R2 EQU TREGS+8
R3 EQU TREGS+12
R4 EQU TREGS+16

ACC EQU TREGS+20    ;pointers for floating point registers
SEC EQU TREGS+22    ;4 bytes (points to 2 - 14 byte areas)

REGS EQU $80  ;16 byte user register area

TMP EQU $40  ;4 byte zero page temporary area


[toc] | [prev] | [next] | [standalone]


#842

From"Bill Buckels" <bbuckels@mts.net>
Date2013-08-30 13:19 -0500
Message-ID<kvqnn2$12h$1@speranza.aioe.org>
In reply to#840
"Bill Buckels" <bbuckels@mts.net> wrote:

>I will provide one more zero page layout ...which shows the differences 
>between the old version's equates and the new version's equates more 
>precisely.

Thank you for taking time to look at this. I have many other similarly 
complex issues that I have been working through, and in the end the problem 
becomes simple and obvious generally with a simple solution. But in the 
meanwhile I always wish I had more sets of eyes...

Like many C compilers that interface with assembly including Microsoft 
Compilers and the Windows API which uses PASCAL calling convention, the 
Aztec C65 compiler passes its parameters on a stack but using the C calling 
convention (in forward order)... pascal is backwards to c.

The rwts function takes integer length arguments so it is not hard to 
calculate the offsets of each parameter passed to the assembly module. The 8 
bit architecture of the 6502 makes it difficult to pass values in integers. 
I realize that I can optimize this module further by using 1 byte parameters 
from C. This is one of the reasons that Aztec C is less efficient than CC65 
which uses 1 byte when Aztec C65 uses two.

But it would take me a lifetime to optimize Aztec C65's runtime libraries 
by myself. So CC65 wins in that area.

The stack in Aztec C65 is on zero page. The 6502 series of compilers 
including the C64 and Atari compilers all use zero page which different 
offsets but the same regs. While the culprit may be on Zero Page for this 
problem, it is not obvious to me.

Annotated Zero Page listing between versions... the old and the new...

Thanks for your help. This is driving me bananas and my knowledge is very 
limited on 6502 code, DOS 3.3, and the Apple II in general compared to the 
experts here (I mean that sincerely) so I look forward to your comments:

 * Comparison to ZPAGE.H From Aztec C 3.2b
* Copyright (C) Bill Buckels 2013. All Rights Reserved.
*

*
* The following EQU's are stored directly in the .A65 source.
*
* Comments for porting DOS 3.3 A65 routines from Aztec C65 3.2b.
*

* missing - STK EQU $00 ; 8 byte stack area (same offset as VAL)
VAL EQU 0 ; same (from blockmv.a65) = STK - 8 byte stack area
SP EQU 2 ; same (from blockmv.a65)
AFRAME EQU 4 ; same (from OV65.A65)
FRAME EQU 4 ; same (from blockmv.a65)
LFRAME  EQU 6 ; same (from OV65.A65)
PC EQU 6 ; same (from blockmv.a65)

* missing - TREGS EQU $08 ; 24 byte tmp register area (same offset as R0)
R0 EQU 8 ; same (from blockmv.a65) = TREGS - 4 byte tmp register area
R1 EQU 12 ; same (from blockmv.a65)
R2 EQU 16 ; same (from blockmv.a65)
* missing - R3 EQU TREGS+12 (same offset as ACC)
* missing - R4 EQU TREGS+16 (same offset as SEC)

ACC EQU 20 ; different (from blockmv.a65) = R3 3.2b
SEC EQU 22 ; different (from blockmv.a65) = R4 3.2b

* different ACC EQU TREGS+20 = ACC+8 (to allow R3 and R4 in 3.2b)
* different SEC EQU TREGS+22 = SEC+8 (to allow R3 and R4 in 3.2b)

REGS EQU $80 ; same (from OV65.A65) 16 byte user register area

* missing - TMP EQU $40 ;4 byte zero page temporary area


[toc] | [prev] | [next] | [standalone]


#845

FromAntoine Vignau <antoine.vignau@laposte.net>
Date2013-08-30 12:35 -0700
Message-ID<2905e0d3-b4fb-4889-81e1-c6c39589d1cc@googlegroups.com>
In reply to#838
I would like to help but I do not know Aztec at all, sorry,
av

[toc] | [prev] | [next] | [standalone]


#847

From"Bill Buckels" <bbuckels@mts.net>
Date2013-08-30 17:07 -0500
Message-ID<kvr53q$655$1@speranza.aioe.org>
In reply to#845
"Antoine Vignau" <antoine.vignau@laposte.net> wrote:
> I would like to help but I do not know Aztec at all, sorry,

I am slowly plodding along, and will post my solution Tony. It takes me a 
long time. For example it took me almost a week back in 1992 to disassemble 
the mouse firmware on the Apple II so I could relocate it. I can't remember 
the details, but it seems to me that I wanted it at a fixed location for 
some reason. That code is still in place in my Aztec C65 stuff today. But 
8088 code I could wtite in my sleep and often did:)

I am a typical lazy programmer so if someone has time to help I will never 
refuse:) This is someone's big chance!!! jk of course...

Bill 

[toc] | [prev] | [next] | [standalone]


#848

From"Bill Buckels" <bbuckels@mts.net>
Date2013-08-30 22:16 -0500
Message-ID<kvrn7a$ck9$1@speranza.aioe.org>
In reply to#838
The following C language function implements DOS 3.3 RWTS (Read Write Track 
Sector) for Aztec C65 3.2b. It will be added to the Apple33 distribution for 
the next update complete with demo programs.

The rwts() function from the old CII DOS 3.3 compiler was entirely 
incompatible with the new 3.2b compiler which also produces ProDOS 8 
programs. (The CG65 variant of the 3.2b compiler produces programs for other 
6502 platforms like the Commodore 64 and Atari 400/800 and ROMable 6502 
code.)

Manx Software never included the rwts() function with the new compiler. This 
version is far different from Manx's CII version and follows the more 
advanced calling convention of version 3.2b. This is my original work, and 
was a little tricky to write and debug. The final version only took a day to 
write,  but the research took much longer.

You are free to use this code for whatever purpose you wish as long as you 
agree that I am not liable in any way whatsoever for its use.

Warning: this program is targetted to DOS 3.3 and C language expert 
knowledge level. Use with caution!

Rubywand's DOS Mini-Manual - csa2 version:

http://apple2.org.za/gswv/a2zine/faqs/Csa2DOSMM.html

You can run quite a few DOS 3.3 programs from 3.5" disk, a large RAM disk, 
or hard disk. However, there are numerous DOS 3.3 programs which will not 
run this way, this one included, and some can even damage files and 
directories on the larger media. DOS 3.3 was designed specifically to 
support the Disk II drive. Hard disks, RAM disks, and 3.5 disks (like those 
used in the Macintosh when it was released in 1984) could not be easily used 
with DOS 3.3 (without doing major patching).

http://apple2history.org/history/ah15/

Problems are especially likely when a program modifies and CALLs machine 
code routines such as Read/Write Track-Sector (RWTS) and/or makes 
assumptions about the physical locations on disk of important DOS 3.3 areas 
such as the Volume Table of Contents, CATALOG track, and DOS itself.

Consider yourself warned!

All the Best,

Bill Buckels, August 2013

Code follows:
=========

/* (C) Copyright Bill Buckels 2013.
   All rights reserved. */

int rwts(tr, se, buf, cmd, sl, dr, vol)
unsigned tr,se,cmd,sl,dr,vol;
char *buf;
{
 struct rwts_iob *r;
 unsigned val;

    /* read IOB - initialize structure */
 val = riob();

 /* load variant fields of IOB */
    r = (struct rwts_iob *) val;

 r->slot = (sl * 16);
 r->drive = dr;
 r->volume = vol;
 r->track = tr;
 r->sector = se;
 r->buf_addr = (unsigned)&buf[0];

 /* Portion of Sector to read
    (to read all 256 bytes set to 0) */
 r->sect_cnt = 0;
 r->cmd_code = cmd;

    /* call track sector IO */
    val = tsio();

 return val;
}

The assembly language functions below are called from the C language 
function above and follow the standard C65 32.b and CG65 calling and return 
convention:

* TrackSector I/O
* tsio.a65
* Copyright (c) 2013 by Bill Buckels
* the following 2 helper functions are called from
* the Aztec C65 3.2b DOS 3.3 function rwts()
* riob() - get IO buf address
*          return IO buf address
* tsio() - track sector IO
*          return 0 if success
*          return -1 if error
R0 EQU 8
IOB EQU $48

riob_   cseg
        public riob_
        clc
        jsr $3e3  ; get address of RWTS IOB
 sta IOB+1 ; IOB address in Y/A)
 sty IOB
        sta     R0+1
        sty     R0
        rts

tsio_   cseg
        public tsio_
        clc
 jsr $3e3 ; get address of RWTS IOB
 jsr $3d9 ; call RWTS
 ldy #0
 bcc .1
 dey
.1 sty R0
 sty R0+1
 rts

The following structures can be is used with the above:

/* Read/Write Track Sector IO Buf Structure */
struct rwts_iob {
 unsigned char type;
 unsigned char slot;
 unsigned char drive;
 unsigned char volume;
 unsigned char track;
 unsigned char sector;
 unsigned dev_addr;
 unsigned buf_addr;
 unsigned char unused;
 unsigned char sect_cnt;
 unsigned char cmd_code;
 unsigned char ret_code;
 unsigned char last_v;
 unsigned char last_s;
 unsigned char last_d;
 };

/* Device Characteristics Structure for rwts_iob */
struct rwts_dev {
 unsigned char type;
 unsigned char phases;
 unsigned motor;
   };

/* structures for rwts routines */

/* vtoc structure - 256 bytes (1 sector) */
struct vtoc {
char unused;
char ctrack;
char csector;
char version;
char unused2[2];
char volume;
char unused3[32];
char max;
char unused4[8];
char last;
char direction;
char unused5[2];
char tracks;
char sectors;
unsigned bytes;
char bitmap[4][50];
};

/* catalog sector structure - 256 bytes (1 sector) */
struct catsect{
    char unused;
    char track;
    char sector;
    char unused2[8];
    char f1[35];
    char f2[35];
    char f3[35];
    char f4[35];
    char f5[35];
    char f6[35];
    char f7[35];
};

/* file entry structure - 35 bytes */
struct fentry {
char track;
char sector;
char type;
char name[30];
unsigned int sectors;
};

End of Listing 

[toc] | [prev] | [standalone]


Back to top | Article view | comp.sys.apple2.programmer


csiph-web