Jump to content
IGNORED

DOS 2.0 DUP overwrites my CIO handler :(


Recommended Posts

I am attempting a rewrite to handle one N: device, with the init code at $4000 (which will be discarded), and the CIO code in $0600, using the page 3 and 4 cassette buffer as the buffer.

 

-Thom

 

(it really is worth noting here, that I've literally been guessing my way through ALL of this, with only a clarity of what I want in the end product. I really do think that it's possible to make a cio shim that will work everywhere, especially because the ESP is doing all the work)

 

I WILL NOT STOP until this thing works everywhere. I mean it. Everybody has their favorite DOS, and Atari did a decent enough job with CIO to make this possible.

Edited by tschak909
Link to comment
Share on other sites

Bad idea to use page 6 for driver code. -Everybody- uses page 6 since it’s known to be free.

 

Edit:

 

Anyway, using the cassette area could be problematic because some custom OSes remove the cassette driver and reuse the ram. Dataque’s 65816 OS and Puff’s UltraSpeed come to mind.

Edited by Alfred
  • Like 1
Link to comment
Share on other sites

ok, .... I've got so much more firmware to write. I've posted the code I have. If someone can make it smaller and possibly relocatable, please do.

 

This is beyond frustrating because I KNOW there are people in this community who could make mince meat of this stuff, and just can't be bothered.

 

-Thom

 

Link to comment
Share on other sites

I’m not sure that’s true. DOS 2.0 ends around $1CFC. On my disk DUP runs $1F0C-3305. Your driver will not fit in two pages. I guess the driver has to split, some basic stuff like the HATAB table down low, and the rest at MEMTOP. A CLI Dos version could load everything down low.

  • Like 1
Link to comment
Share on other sites

9 hours ago, tschak909 said:

ok, .... I've got so much more firmware to write. I've posted the code I have. If someone can make it smaller and possibly relocatable, please do.

I afraid the Atari Os is not a serious enough Os to allow for configurations that "work all the time" as there is no reliable memory allocation scheme. You may have to provide several options for various configurations.

 

Relocating drivers to just above MEMLO was the method Atari used for their R: handler. This was not too bad a choice, except that the Atari DUP overwrites this area. If you absolutely need your handler to work from the Atari DUP, then that option is not available.

 

A lot of more receint DOS choices are less limited in this respect, but then require a larger memory footprint. Dos A/+ was command line driven and did not overwrite this area, though as soon as you used an external command, it would have overwritten data above memlo as well.

 

The FMS++ DUP menu is smarter and relocable as well, so it relocates itself above APPMEMHI, but that is probably an exception.

 

Memory management was not taken very seriously back in the old days....

Link to comment
Share on other sites

if I make my handler relocatable, I can basically make an option in the web admin or config to specify where to load the damned thing.. :)

 

-Thom

 

(goal is to make the handler page-relocatable, but even this is making me cringe, as I've never done this before)

 

and yes, I know, XL/XE has type 3/4 poll, which is downright intriguing, but that will take some serious looking to see how to do that. I can study @phaeron's example code there... 

Edited by tschak909
Link to comment
Share on other sites

3 hours ago, David_P said:

Alfred, are you suggesting a "smart"driver that detects DOS and memory configuration and installs itself appropriately?  

I had more in mind at least two driver versions, but I suppose they could be combined into a smart driver.

Link to comment
Share on other sites

all possible, I just need to build a massive freakin truth table of memory mappings and DOS functions, so I can figure out how many versions I need to build, they can be put into the ESP's payload and the relocator can inject the appropriate one.

 

The failure of imagination in these file managers is really starting to piss me off.

 

"GOSH! THERE WON'T BE _ANY_ OTHER DEVICES THAT WILL _EVER_ HANDLE FILENAMES, EVER!"

 

-Thom

 

Edited by tschak909
Link to comment
Share on other sites

It might make more sense to focus on those disk operating systems which are less adversarial towards drivers. Surely 'D:' interactions (i.e. wireless disk image handling) will be the most used facility and presumably requires no drivers whatsoever. If users really want to access the Internet from their Atari (until such time as there is a PBI version of this hardware which does away with code space and compatibility troubles entirely), surely it's not too much to ask that they use a disk operating system which didn't require the developer to jump through a lot of arbitrary hoops.

 

Take the 'PCLINK' protocol, for example. The driver elegantly integrates into the driver-friendly SDX kernel architecture. Implementing something similar under DOS 2.5 or MYDOS would be quite challenging, but - as useful as PCLINK is - I don't see people crying that they cannot use PCLINK with anything but SpartaDOS X. As noble as it is to try and make the N: driver available to users of the jankiest DOSes and to the most ardent anti-SpartaDOS curmudgeons, it seems to me that it would be better to get something fully working and polished on one platform rather than trying to hit the broadest possible number of targets when the driver has only just taken its first steps from compiled C into assembly language.

Edited by flashjazzcat
  • Like 1
Link to comment
Share on other sites

yes, this may be the way forward. I was trying to show what could be possible with some help.

 

there is enough of an API right now that somebody could take the code I've written above and do an SDX kernel driver. this would be great.

 

Irony of ironies really, once you go BEYOND the utility packages of these DOSes things clear up really fast and most apps just work. The CIO was designed very well. There are just dumb assumptions from some utility packages on top of it.

 

-Thom

Edited by tschak909
Link to comment
Share on other sites

TRIP is used for indicating that there is data present, or that the connect flag changed (the proceed vector sets it)

 

INQDS is the inquire DSTATS byte, which is returned by SIO command $FF. I use this to dynamically determine the type of SIO command to pass through from CIO so that special commands don't need to be explicitly implemented inside the CIO handler (with the exception of PUT FLUSH)

 

(p.s. yes, I know my code sucks, I do not do assembler all the time, but I desperately needed this done, as I went as far as I could with the C prototype. I have done enough so that hopefully those better at this can get the gist and help do something better.)

 

-Thom

Edited by tschak909
Link to comment
Share on other sites

22 minutes ago, tschak909 said:

there is enough of an API right now that somebody could take the code I've written above and do an SDX kernel driver. this would be great.

I actually have a local copy of the driver code here and was half way through implementing some of the ideas I talked about (shrinking the code to about half its current size) when I realised time might better be spent on the SDX driver. Of course, although I have written several SDX LSIO drivers, I have never written a kernel device driver for this DOS. I have some very sketchy skeleton code sent by Konrad some years ago, but it's frustrating there isn't a skeleton device driver in any of the sample code floating around (or source code for PCLINK.SYS, for example). This would greatly simplify the process.

Edited by flashjazzcat
Link to comment
Share on other sites

Yeah, the CIO version of the handler works well enough right now that by manually assembling to different points, I can work out the filename mapping issues that I see in various file managers, and get burst mode working.

 

-Thom

 

(edit: and also, I can write various CRUD tools to do the individual operations nominally done by N: for those situations where using N: is not possible)

Edited by tschak909
Link to comment
Share on other sites

For non-SDX operations (think also about a bootable ATR/disk that just wants to use your device) it might be a good idea to provide a relocated driver code from fujinet via some SIO calls. The programs (or simple COM / AUTORUN.SYS files to install the driver to fixed locations) know best which memory location is available and then just get the driver code from there.

 

The 1050 Speedy did this to provide a highspeed SIO code and I've implemented the same in AtariSIO, providing my highspeed SIO code.

 

That's done with 2 SIO calls: the first one ($68) just returns 2 bytes, the total length of the code. The second one ($69) loads code from the drive, relocated to the address in DAUX. So the caller just needs to set DBUF=DAUX and DLEN to the result from the previous call and then has a $E459 replacement at the specified address.

 

A similar approach for fujinet could look like the caller then doing a "JSR MYLOADADDRESS" to let the code install itself into HATABS (or just provide the handler table at the very beginning).

 

To do the relocation I used another very simple (but a bit tedious) approach. I assemble my code for some fixed location (I used $1000) and provide the length of the relocation table at the very end and right before that a list of absolute locations in the code that need to be relocated.

 

See eg https://github.com/HiassofT/highspeed-sio/blob/master/hisio.src#L115-L152


RELOC .WORD ?ABS01+1, ?ABS02+1, ?ABS03+1, ?ABS04+1, ?ABS05+1

...

RLEN .WORD *-RELOC

The tedious part is that I manually need to list every location in my code that contains addresses to be relocated - so I put those ?ABS01... labels before those.

eg https://github.com/HiassofT/highspeed-sio/blob/master/hisiodet.src#L31

?ABS01 STA SPEEDTB,X

Note that with this simple approach you have to avoid using 'LDA #<MYADR / LDA #>MYADR' as that would be a PITA to handle. Using 'LDA MYLOC / LDA MYLOC+1' with MYLOC containing a 'WORD MYADR' works fine though (all three locations need to be relocated though).

 

While being a bit tedious and error prone the nice thing about this approach is that it works with every assembler. Back then when I wrote the code there weren't many alternatives and dealing with ca65's object format seemed a lot more troublesome.

The relocation code is quite simple, it checks the last 2 bytes of the driver binary to find out the relocation table begins (and where the driver code ends), and then adjusts all the addresses in the table accordingly. To get the offset in the driver binary that have to be relocated it first needs to substract the driver start address ($1000) from the values in the relocation table and then adjust the word at that offset by RELOC_DEST_START-DRIVER_START.

There are several other possibilities how you can handle that (for SDX you'd probably better use it's native relocatable format), just wanted to show a simple approach that works without needing sophisticated tools.

so long,

Hias

Edited by HiassofT
Link to comment
Share on other sites

Yes, various #FujiNet specific programs can simply use the SIO directly, as the calls are very easy to use, I do this in the PLATOTERM port, for example:

 

/**
 * PLATOTERM for Atari Cartridges
 *
 * Author: Thomas Cherryhomes <thom.cherryhomes at gmail dot com>
 *
 * I/O Functions
 */

#include <serial.h>
#include <stdbool.h>
#include <atari.h>
#include <stdlib.h>
#include "io.h"
#include "protocol.h"
#include "sio.h"

extern bool running;

static uint8_t recv_buffer[8192];
static uint8_t xmit_buffer[64];
static uint8_t xmit_buffer_len=0;
static uint8_t status[4];

extern padPt TTYLoc;

static unsigned char hostname[256]="N:TCP://irata.online:8005/";
static unsigned short bw=0;
static unsigned char connected=0;

unsigned char trip=0;
extern void ih(void);

uint8_t xoff_enabled=false;

/**
 * io_init() - Set-up the I/O
 */
void io_init(void)
{
  OS.vprced=ih;
  PIA.pactl |= 1;
  // Establish connection
  OS.dcb.ddevic=0x71;
  OS.dcb.dunit=1;
  OS.dcb.dcomnd='O';
  OS.dcb.dstats=0x80;
  OS.dcb.dbuf=&hostname;
  OS.dcb.dtimlo=0x0f;
  OS.dcb.dbyt=256;
  OS.dcb.daux=0;
  siov();
}

/**
 * io_send_byte(b) - Send specified byte out
 */
void io_send_byte(uint8_t b)
{
  xmit_buffer[xmit_buffer_len++]=b;
}

/**
 * io_main() - The IO main loop
 */
void io_main(void)
{
  if (xmit_buffer_len>0)
    {
      OS.dcb.ddevic=0x71;
      OS.dcb.dunit=1;
      OS.dcb.dcomnd='W';
      OS.dcb.dstats=0x80;
      OS.dcb.dbuf=&xmit_buffer;
      OS.dcb.dtimlo=0x0f;
      OS.dcb.dbyt=xmit_buffer_len;
      OS.dcb.daux1=xmit_buffer_len;
      OS.dcb.daux2=0;
      siov();

      xmit_buffer_len=0;
      return;
    }

  if (trip==0)
    return;

  // Get # of bytes waiting
  OS.dcb.ddevic=0x71;
  OS.dcb.dunit=1;
  OS.dcb.dcomnd='S';
  OS.dcb.dstats=0x40;
  OS.dcb.dbuf=&status;
  OS.dcb.dtimlo=0x0f;
  OS.dcb.dbyt=4;
  OS.dcb.daux=0;
  siov();

  bw=(status[1]<<8)+status[0];
  connected=status[2];

  // These functions are all I needed to change to port over to the N: device.

  if (bw>0)
    {
      // Do a read into into recv buffer and ShowPLATO
      OS.dcb.ddevic=0x71;
      OS.dcb.dunit=1;
      OS.dcb.dcomnd='R';
      OS.dcb.dstats=0x40;
      OS.dcb.dbuf=&recv_buffer;
      OS.dcb.dbyt=bw;
      OS.dcb.daux=bw;
      siov();
      ShowPLATO((padByte *)recv_buffer, bw);
      bw=trip=0;
    }

  if (connected==0)
    {
      io_done();
    }

  PIA.pactl |= 1;
}

/**
 * io_done() - Called to close I/O
 */
void io_done(void)
{
  ShowPLATO("\r\nDISCONNECTED.\r\n",17);
  OS.dcb.ddevic=0x71;
  OS.dcb.dunit=1;
  OS.dcb.dcomnd='C';
  OS.dcb.dstats=0x00;
  OS.dcb.dbuf=0;
  OS.dcb.dbyt=0;
  OS.dcb.daux=0;
  siov();
}

So really, you have two options:

 

* Use SIO calls directly (easy for things besides BASIC)

* Use the N: handler calls (CIO) (easy for BASIC)

 

and really the N: handler is meant to make stuff stupidly easy to write in BASIC. I am just trying to see how far I can realistically stretch things. There is this part of me that wants you to be able to copy a file from N:HTTP or N:FTP or N:NFS or N:SMB or N:TNFS directly, and I will try my damndest to get there. At worst case, there will be wrapper tools that work around DOS stupidities.

 

-Thom

 

 

Edited by tschak909
Link to comment
Share on other sites

1 minute ago, HiassofT said:

I was more thinking about the relocatable CIO driver being loadable from fujinet so applications can use that instead of having to deal with SIO calls.

 

so long,

 

Hias

And yup, that will be a thing. I will make the CIO driver relocatable, and you've provided a good enough explanation that I can take a whack at it. Thanks. *hug* :)

 

Point was, um..that...there are a lot of different tricks that can be done.

 

with the relocatable driver being loadable from a TYPE 1 poll, this really would work from anywhere, EVEN IN FIG-FORTH! :)

-Thom

Link to comment
Share on other sites

@HiassofT I also want to actually see what it will take to implement type 3/4 calls, because then it really could JUST WORK in even programs like PaperClip and other programs that otherwise have no opportunity to load handlers.

 

I know this only works on XL/XE systems, but still GOD IT WOULD BE COOL TO SEE A USEFUL EXAMPLE OF THIS ACTUALLY WORKING AFTER 38 YEARS!

 

-Thom

Link to comment
Share on other sites

4 hours ago, tschak909 said:

and yes, I know, XL/XE has type 3/4 poll, which is downright intriguing, but that will take some serious looking to see how to do that. I can study @phaeron's example code there... 

Frankly, I would not depend on that, but would recommend a custom loader/relocator that does not depend on a particular Os version.

Link to comment
Share on other sites

Just now, thorfdbg said:

Frankly, I would not depend on that, but would recommend a custom loader/relocator that does not depend on a particular Os version.

Absolutely nothing I've said, indicates I am depending on that. It is one of those nice to haves that would be interesting to implement for XL/XE users, that makes the N: device _really_ transparent. I will also do a type 1 poll load.

 

-Thom

Link to comment
Share on other sites

@HiassofT I have the Atari 850 source code, here, and it uses a rather interesting macro and variable reset to build the relocation table:

 

;       OPCODE DEFINITIONS FOR RELOCATING MACRO
RBIT    .EQU $2C
RJSR    .EQU $20
RLDAX   .EQU $BD
RSTAX   .EQU $9D
RCPX    .EQU $EC
RLDA    .EQU $AD
RSTX    .EQU $8E
RJMP    .EQU $4C
RSTA    .EQU $8D
RLDAY   .EQU $B9
RSTAY   .EQU $99
RINCX   .EQU $FE
RCMPX   .EQU $DD
RADCX   .EQU $7D
RLDYX   .EQU $BC
RINC    .EQU $EE
RSTY    .EQU $8C
RORAX   .EQU $1D
RLDY    .EQU $AC
RJMPI   .EQU $6C
RLDX    .EQU $AE
RDEC    .EQU $CE
RANDX   .EQU $3D
RSBCX   .EQU $FD

;       RELOCATION MACRO
REL     .MACRO  OP,VARNUM
        .BYTE   OP
        .BYTE   VARNUM
        .BYTE   *-Q+1
Q       .SET *
        .ENDM

...

ROKOPN  TYA
        ORA #$80
        REL RSTAX,2    SET-UP PERMISSION BYTE
        LDA #0
        REL RSTAX,4    INITIALIZE PUT-COUNTER
        REL RSTAX,6    CLEAR ERROR FLAGS
        LDY #SUCCES
        RTS

...and so on.

-Thom

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...