Jump to content
IGNORED

PLATOTerm for Atari - Working out tgi and ser issues.


Recommended Posts

Hello. Letting everybody know that I am hard at work trying to get the Atari version of PLATOTerm working, but am running into a snag where initializing TGI and SER together is causing what is amounting to system crashes. Why, is what I'm trying to figure out, right now.

 

The code is here: http://github.com/tschak909/platoterm64

 

And currently the distribution tools require dir2atr to produce an atr file containing DOS 2.5, the 850 AUTORUN.SYS, several mouse drivers, the CC65 serial driver for the atari R: device, and PLATO.COM for the main program.

 

Currently, the program hangs when ser_open happens, I can't even get an error code from it to determine what could be wrong.

 

If anyone would like to help, there are a few things that can be tweaked and messed with:

 

try loading in various DOSes. If it complains about MEMLO, adjust the STARTADDRESS to above the DOS memlo. I am trying to make this work on all Atari computers, so I am not building to work with SpartaDOS, there's just no way..the binary is 24K in size...

 

This is driving me insane, and I've already roped in the cc65 devs to see what could be going on (they will hate me before this whole exercise of PLATOTerm is over, I understand this...)

 

-Thom

  • Like 2
Link to comment
Share on other sites

Okay, here's a build.

 

I've managed to make it work correctly under SpartaDOS 3.2, and under MyDOS.. It pukes under DOS 2.5, or anything else.

 

By correct I mean:

 

You can load the 850 handler if you need to (e.g. under SpartaDOS)

 

* It starts

* you see splash

* you see a single 'c' go out the serial port, because the protocol stream in the splash screen contains an echo character I haven't stripped out.. am using it to test and make sure the serial port is working.

 

Keyboard is not hooked up, yet, so you can't do anything beyond that atm.

 

 

plato.zip

 

-Thom

Link to comment
Share on other sites

Seems you've got it at least partially sorted already.

 

One thing I noticed trying to get this to work: there is a deferred VBI handler chaining through a vector table at $6F23. Looks like this makes the program fail under SpartaDOS X when extended memory is used.

Link to comment
Share on other sites

Here's a pre-alpha of PLATOTerm for Atari for crazy people to test, will make an official announcement once I have an actual alpha.

 

Binary download below...

Code: http://github.com/tschak909/platoterm64

 

Some notes:

 

* There is an installer to select the desired R: handler to load. Let me know what you think.

* The login stops displaying somewhere in the middle for some reason, but input/output and protocol decoding/encoding still continue. go figure.

* Prefs won't allow you to exit.

* Prefs won't allow you to save (due to brain-damaged IOCB usage in the CC65 libs.)

* Lots of other weird broken stuff probably.

 

Let me know how it works.

-Thom

platoterm-20180814.zip

Edited by tschak909
Link to comment
Share on other sites

I can't specify a specific IOCB with the stdio routines, so if there are, say, two fopen and fcloses (e.g. to copy a file), then there is a good chance that an existing IOCB will get clobbered. This happens with my installer, and is the reason the installer has to boot after copying the handler into place.

 

-Thom

Link to comment
Share on other sites

No, this is not true. The CC65 runtime lib won't clobber an "in-use" IOCB. It looks for a free one and uses this in fopen. If is doesn't find a free one, you'll get an error back from fopen. Explain what you do when you say "this happens with my installer". You of course need to do a close in order to free the IOCB again.

Link to comment
Share on other sites

Dragon cart not on the config list, although ethernet is a selection in the options menu...

once you set the options and save there is no exiting the option choice bar reloads and can't exit...

must reset....

I will try slower speed with mio, just filling screen with garbage after initial connection it logs in... as you see it ask ask at prompts then it goes back to making a mess

 

okay, at 2400 no mess, had to set baud save and reboot

 

got the main menu with the squished ball so far so we are getting somewhere.... I will try 4800, or no I won't it's not in the baud list... it skips to 9600

Edited by _The Doctor__
Link to comment
Share on other sites

checkers is not rendering correctly looks like the bug on the others is now on the Atari.... the numbers for squares are in the wrong place on the lower half and the black checkers are malformed.... and didn't have the issue at 2400 using tlp...I haven't seen the flow control flicker at all, I will make sure hardware fc is set across the board just in case...

 

yep hardware handshake is set so, probably not the issue....

Edited by _The Doctor__
Link to comment
Share on other sites

I had to remove the Ethernet support temporarily from all of the PLATOTerm builds, as IP65 has issues that need to be addressed first (lack of receive window shrinking is a big problem)

 

Preferences is broken. It's on my short list to fix.

 

Can you attach a screenie of checkers?

 

Flow control isn't there yet. I am going to try using XIO calls to assert it. If not possible, i'll check the handler setting that was specified at boot, and tickle the exposed ACIA registers, directly.

 

@phaeron, since Doctor is able to see a somewhat stable display with the MIO, I think I need to mention that both MIO and Blackbox exhibit VERY strange behavior where you start seeing nothing but "UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU" returned after the connect string. Not sure if it's the CC65 code, or if Altirra is going sideways.

 

-Thom

Link to comment
Share on other sites

A little touchy, are we? tad bit defensive? I do NOT spread FUD, and I am _very_ angry that you even went there.

 

I am working on 12 different ports of this software at the moment, while also doing tons of communicating across many communications channels, so forgive me if I don't answer immediately.

 

The code, for reference:

/**
 * PLATOTerm Installer for Atari. Needed to specify
 * the RS232 handler to use.
 *
 * Author: Thom Cherryhomes
 *   <thom.cherryhomes@gmail.com>
 *
 */

#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#include <peekpoke.h>

#define BUFFER_SIZE 2048

#define FILENAME_HANDLER_CONFIG "D1:HANDLER.CFG"
#define FILENAME_HANDLER_850 "D1:RHND850.BIN"
#define FILENAME_HANDLER_RVERTER "D1:RHNDRVER.BIN"
#define FILENAME_HANDLER_HYPERSPEED_MIO "D1:RHNDHMIO.BIN"
#define FILENAME_HANDLER_HYPERSPEED_BLACKBOX "D1:RHNDHBB.BIN"
#define FILENAME_HANDLER_NONE "D1:NOHAND.BIN"

#define LENGTH_HANDLER_850 93
#define LENGTH_HANDLER_RVERTER 1369
#define LENGTH_HANDLER_HYPERSPEED_MIO 1351
#define LENGTH_HANDLER_HYPERSPEED_BLACKBOX 1367
#define LENGTH_HANDLER_NONE 516

extern void coldstart(void);

unsigned char selected_option=1;

/**
 * Setup screen
 */
void screen_setup(void)
{
  clrscr();
  POKE(710,149);
  POKE(712,149);
}

/**
 * Copy the selected handler to AUTORUN.AR1
 */
void copy_selected_handler_to_autorun_ar1(void)
{
  unsigned char buf[2048];
  FILE* fpa;
  FILE* fpb;
  unsigned int len=0;
  unsigned int file_len=0;
  unsigned char* fn;

  switch(selected_option)
    {
    case 1:
      strcpy(fn,FILENAME_HANDLER_850);
      len=LENGTH_HANDLER_850;
      break;
    case 2:
      strcpy(fn,FILENAME_HANDLER_RVERTER);
      len=LENGTH_HANDLER_RVERTER;
      break;
    case 3:
      strcpy(fn,FILENAME_HANDLER_HYPERSPEED_MIO);
      len=LENGTH_HANDLER_HYPERSPEED_MIO;
      break;
    case 4:
      strcpy(fn,FILENAME_HANDLER_HYPERSPEED_BLACKBOX);
      len=LENGTH_HANDLER_HYPERSPEED_BLACKBOX;
      break;
    case 5:
      strcpy(fn,FILENAME_HANDLER_NONE);
      len=LENGTH_HANDLER_NONE;
      break;
    }

  remove("D1:AUTORUN.AR1");

  fpa=fopen(fn,"r");
  fread(&buf,1,len,fpa);
  fclose(fpa);

  fpb=fopen("D1:AUTORUN.AR1","w");
  fwrite(&buf,1,len,fpb);
  fclose(fpb);

}

/**
 * Read selected option from disk.
 */
void read_selected_option(void)
{
  FILE* fpr;

  fpr=fopen(FILENAME_HANDLER_CONFIG,"r");

  if (fpr)
    {
      fread(&selected_option,1,sizeof(unsigned char),fpr);
    }
  fclose(fpr);
}

/**
 * Save the selected option to disk.
 */
void save_selected_option(void)
{
  FILE* fps;
  fps=fopen(FILENAME_HANDLER_CONFIG,"w");
  if (!fps)
    return;
  fwrite(&selected_option,1,sizeof(unsigned char),fps);
  fclose(fps);
}

/**
 * Show the current selected option
 */
void show_option(unsigned char option, const char* text)
{
  cputs("   ");
  if (option==selected_option)
    revers(1);
  else
    revers(0);
  cputs(text);
  revers(0);
}

/**
 * Show the options menu
 */
void show_menu(void)
{
  unsigned char i;
  for (i=10;i<15;++i)
    {
      cclearxy(0,i,40);
    }

  gotoxy(0,10);
  show_option(1," (1) Atari 850 or P:R: Connection \r\n");
  show_option(2," (2) R-Verter \r\n");
  show_option(3," (3) Hyperspeed MIO \r\n");
  show_option(4," (4) Hyperspeed Blackbox \r\n");
  show_option(5," (5) Do not load handler \r\n");

  cputsxy(4,16,"Which driver? ");
  cursor(1);

}

/**
 * Run the setup routine
 */
void run_setup(void)
{
  unsigned char key;

  clrscr();
  gotoxy(12,1);
  revers(1);
  cputs(" PLATOTerm Setup ");
  revers(0);
  chlinexy(12,2,17);
  cputsxy(0,4,"PLATOTerm utilizes a standard R: handler\r\n");
  cputsxy(0,5,"for serial communications. Please select\r\n");
  cputsxy(0,6,"the desired handler for your serial\r\n");
  cputsxy(0,7,"interface.\r\n");

  cputsxy(0,19,"You do not need a handler if you have a\r\n");
  cputsxy(0,20,"bus device, which loads its own handler,\r\n");
  cputsxy(0,21,"or if you are running a modified OS with\r\n");
  cputsxy(0,22,"its own handler.\r\n");

  show_menu();

  while (key=cgetc())
    {
      if (key>=0x31 && key<=0x35)
        {
          revers(0);
          gotoxy(18,16);
          cputc(key);
          selected_option=atoi(&key);
          show_menu();
          cursor(0);
          cclearxy(4,16,20);
          break;
        }
    }

  cputsxy(4,16,"Saving...");
  save_selected_option();

  cputsxy(4,16,"Copying Handler to AUTORUN.AR1...");
  copy_selected_handler_to_autorun_ar1();

  cputsxy(4,16,"Rebooting...                     ");
  sleep(1);

  coldstart();

}

/**
 * Count and wait for a key press. If key pressed,
 * run the setup routine. Otherwise, fall through.
 */
unsigned char count_and_wait(void)
{
  unsigned char i;
  unsigned char count_text[4];
  cursor(0);
  clrscr();
  revers(1);
  cputsxy(9,0," Welcome to PLATOTerm ");
  revers(0);
  cputsxy(0,4,"Current Handler: ");
  switch(selected_option)
    {
    case 1:
      cputs("Atari 850 or Compatible");
      break;
    case 2:
      cputs("R-Verter or Compatible");
      break;
    case 3:
      cputs("Hyperspeed MIO");
      break;
    case 4:
      cputs("Hyperspeed Blackbox");
      break;
    case 5:
      cputs("No handler (PBI)");
      break;
    }
  revers(0);
  cputsxy(6,12,"Press any key for setup. ");
  for (i=5;i -->0; )
    {
      if (kbhit())
        return cgetc();

      itoa(i,count_text,10);
      cputsxy(32,12,count_text);
      sleep(1);
    }
  revers(0);
  cursor(0);
  cputs("\r\n\r\n            Loading...");
  cputs("\r\n\r\n");
}

/**
 * Main Program Entry
 */
void main(void)
{
  unsigned char key;
  screen_setup();
  read_selected_option();
  key=count_and_wait();

  if (key!=0)
    run_setup();

  return;

}

Once the install does the requisite copy, the IOCB that MyDOS is using for autorun chaining, gets clobbered, and can't continue. I need a way to explicitly specify an IOCB so this doesn't happen.

 

I guess given that this is an atari-specific program, I could just set up the CIO calls myself, but it is nice to use standard c file functions.

 

My experience with CC65 and its toolchain has been a very mixed bag, I know it's a volunteer project, but it gets very frustrating to track down bugs in not only my code, but the surrounding libraries.

 

-Thom

Link to comment
Share on other sites

A little touchy, are we?

 

Yes.

 

 

tad bit defensive?

 

Yes, too. Since you've claimed things without backing them up.

 

 

I do NOT spread FUD, and I am _very_ angry that you even went there.

 

I am working on 12 different ports of this software at the moment, while also doing tons of communicating across many communications channels, so forgive me if I don't answer immediately.

 

Understood. But you've answered to a later post than mine (from "Doctor"). And on the cc65 page you've just simply ignored my answers in some cases (e.g. your serial test program).

 

 

Once the install does the requisite copy, the IOCB that MyDOS is using for autorun chaining, gets clobbered, and can't continue. I need a way to explicitly specify an IOCB so this doesn't happen.

 

 

Ok. Let's get more constructive. The cc65 lib shouldn't use an IOCB which is open. I'm not normally using MyDOS. Can you give me exact instructions about how to reproduce the problem?

At a brief glance, your program looks correct. Of course, there's always the possibility that there's a bug in the cc65 lib. I'm not ruling that out :-)

 

 

 

but it gets very frustrating to track down bugs in not only my code, but the surrounding libraries.

 

 

You have a point here. In my tests with my "sertst" program (can be found on the cc65 site, issue #713), I'm getting mixed results. Sometimes it works, sometimes not. Where "sometimes" doesn't mean running the same thing multiple times, but it somehow depends on the DOS, or whether the test program was started from D2: instead of D1:, or so. I need to debug....

 

 

regards,

chris

Link to comment
Share on other sites

I am attaching a version of the disk, which I have removed the coldstart call from the installer, so you can see:

plato-nocoldstart.zip

 

(I wonder if saving and restoring the IOCB before and after would allow me to work around the problem, for now?)

 

The disk should boot into the installer, press a key, select any handler to cause the copy, let it finish. it SHOULD go onto PLATOTerm (it might do an out of memory, but that's okay, I am still trying to shuffle the start addresses to be happy with all the handlers.),... instead, it will crash.

 

-Thom

Link to comment
Share on other sites

Seems you've got it at least partially sorted already.

 

One thing I noticed trying to get this to work: there is a deferred VBI handler chaining through a vector table at $6F23. Looks like this makes the program fail under SpartaDOS X when extended memory is used.

 

@sanny from cc65 pinged back in bug report:

 

"I've compiled plato a few days ago, and looking at the map file I see that callirq.o is compiled in. I guess it's coming from the serial driver framework. Still, please explain why having a VBI handler should be harmful on a system with more than 128K of memory. regards, chris"

 

-Thom

 

Relevant code, don't see anything odd here:

;
; Ullrich von Bassewitz, 2004-04-04
;
; CC65 runtime: Support for calling special irq routines declared as condes
; type 2.
;
; There are two reasons, why this is a separate routine, and the generic
; condes routine in condes.s is not used:
;
;   1. Speed. Having several things hardcoded makes it faster. This is
;      important if it is called in each interrupt.
;
;   2. Reentrancy. The condes routines must use self modyfiying code, which
;      means it is not reentrant. An IRQ using condes, that interrupts
;      another use of condes will cause unpredicatble behaviour. The current
;      code avoids this by using locking mechanisms, but it's complex and
;      has a size and performance penalty.
;
;   3. Special semantics: An interruptor called by callirq must tell by
;      setting or resetting the carry flag if the interrupt has been handled
;      (which means that the interrupt is no longer active at the interrupt
;      source). callirq will call no other interruptors if this happens. To
;      simplify code, all interrupt routines will be called with carry clear
;      on entry.
;
; As the normal condes routine, this one has the limitation of 127 table
; entries.
;

        .export         callirq
        .export         callirq_y       ; Same but with Y preloaded
        .export         __CALLIRQ__ : absolute = 1
        .constructor    irq_init, 10
        .destructor     irq_done, 10

        .import         __INTERRUPTOR_TABLE__, __INTERRUPTOR_COUNT__
        .import         initirq
        .import         doneirq

        irq_init :=     initirq
        irq_done :=     doneirq

; --------------------------------------------------------------------------
; Call all IRQ routines. The function needs to use self modifying code and
; is thereforce placed in the data segment. It will return carry set if the
; interrupt was handled and carry clear if not. The caller may choose to
; ignore this at will.
; NOTE: The routine must not be called if the table is empty!

.data

callirq:
        ldy     #.lobyte(__INTERRUPTOR_COUNT__*2)
callirq_y:
        clc                             ; Preset carry flag
loop:   dey
        lda     __INTERRUPTOR_TABLE__,y
        sta     jmpvec+2                ; Modify code below
        dey
        lda     __INTERRUPTOR_TABLE__,y
        sta     jmpvec+1                ; Modify code below
        sty     index+1                 ; Modify code below
jmpvec: jsr     $FFFF                   ; Patched at runtime
        bcs     done                    ; Bail out if interrupt handled
index:  ldy     #$FF                    ; Patched at runtime
        bne     loop
done:   rts

Edited by tschak909
Link to comment
Share on other sites

One thing I noticed trying to get this to work: there is a deferred VBI handler chaining through a vector table at $6F23. Looks like this makes the program fail under SpartaDOS X when extended memory is used.

 

Could you elaborate a little bit more, please? I don't see why having a VBI handler should cause a program to fail "under SpartaDOS X when extended memory is used".

 

regards,

chris

Edited by sanny
Link to comment
Share on other sites

Well, as soon as an extended RAM bank appears in the $4000-$7FFF address range, the vector table at $6F23 will disappear, which is bad news if an interrupt happens to fire. SpartaDOS X makes extensive use of extended memory, but it's preferable to keep interrupt handlers (especially for NMIs) out of the banking window anyway, since RAMdisks handlers and the like will come a cropper.

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

Well, as soon as an extended RAM bank appears in the $4000-$7FFF address range, the vector table at $6F23 will disappear, which is bad news if an interrupt happens to fire. SpartaDOS X makes extensive use of extended memory, but it's preferable to keep interrupt handlers (especially for NMIs) out of the banking window anyway, since RAMdisks handlers and the like will come a cropper.

 

Hmm, do I understand you correctly, that when an interrupt occurs SDX doesn't switch back to the "main" bank of the $4000-$7FFF memory before chaining to user interrupt handlers?

 

Somehow, I have to admit, I cannot believe this. If this is true, there would be many potential compatibility problems with programs which use an interrupt handler which happens to reside in this area. Do you have pointers to SDX docs which talk about that?

 

regards,

chris

Link to comment
Share on other sites

The OS dispatches the NMIs and - according to what Phaeron observed - this is a deferred VBI handler which SpartaDOS X need have no hand in at all. There are sources of NMIs on the Atari (DLIs) where dispatch time is far too critical for wrappers to handle banking considerations, so (in the matter of compatibility problems), the best advice would be to completely avoid placing interrupt handlers at $4000-$7FFF. I don't think there are too many compatibility issues with existing software intended for use with DOS, as I guess developers will naturally avoid the banking window (since the banking window has been in the same place for over thirty years). I'm not sure how one directs the CC65 linker to avoid placing a particular module in a particular address range.

Edited by flashjazzcat
Link to comment
Share on other sites

The memory window is there since long, correct. But it first appeared with the 130XE in, IDK, 1986? Or 1987? So there were around 8 years where nobody was aware of the memory window. All programs written in this time frame are potentially "vulnerable" to this problem.

 

Putting just the main handler which tschak909 posted above, and the table itself, into lower memory is not that much involved. But also, all functions which are called by the main handler would need to be put somewhere else. This could become a bit fiddly. And users, writing their own handlers, would have one more thing to look for.

 

Sadly, the SDX devs don't publish the source code, so I cannot verify. (I don't have time and energy to disassemble and analyze the beast...)

 

regards,

chris

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...