kfest2017

An Apple II Build Chain for Inform

Inform is a language and compiler which creates object code that can be executed by Infocom’s Z-machine. Z-machine interpreters exist for many, many computer platforms, one of which is the Apple II. This paper describes the tools and methods for targeting Inform object code for a Z-machine interpreter running on an 8-bit Apple II computer.


apple_ii_inform

apple_ii_inform2.pdf  – PDF document

inform_a2.zip – Demo files used during my presentation. This is a companion to the PDF.

Retrochallenge, Retrochallenge 2016/10

Retrochallenge 2016/10 – Final Post

This is my last entry for my Retrochallenge 2016/10 journal, where I worked towards loading ROM images to an Intellivision from an Atari 800. To jump to the very beginning, click here.

Wrap-Up Video

Success!

I completed everything I originally set out to do.

  • Learned how to use OSS’s Action! programming environment
  • Learned more about OSS’s DOS OS/A+ and DOS XL (originally I was going to use BeWeDOS but decided early on it would be more fitting to use an OSS DOS).
  • Learned how to configure the Atari 850 Interface Module at runtime
  • Wanted to put @InverseATASCII’s Window Gadget Libraries to use
  • Extended the usefulness of my Intellicart! (it no longer was viable with my everyday laptops).

During the month, I also imagined displaying text versions of Intellivision game manuals and controller overlays on the Atari 800. I also envisioned doing a craft project to construct a floppy disk label and sleeve as if floppy-based games had been produced by Mattel Electronics. But Retrochallenges rarely accommodate feature-creep.

Some Surprises

The version of my copy of DOS XL is meant for HAPPY 1050 floppy drives and was not previously available on the Internet as far as I can find. I’ve uploaded it to AtariAge and Archive.org.

It takes much longer to transfer a ROM image to the Intellicart! than I would’ve originally guessed. ROM images also take up much more room on a single density floppy disk than I planned. There’s only room for about 2 ROM files per side. Both the speed and size problems may be due to the fact that the Intellivision uses 10-bit words, so the ROM image format uses 2 bytes to store each word.

I didn’t document this in my journal but along the way,  I upgraded my Atari 1050 floppy drive to be a HAPPY 1050. This will nicely pair it with my version of OSS DOS XL.

It took more work than I would’ve guessed to implement the GUI. This is no fault of the library code I borrowed from Wade, just the nature things.

Thanks!

A big thanks goes to John Linville & Michael Mulhern who volunteered to keep Retrochallenge a thing. Both are already busy with podcasts and normal life. Thanks to Wade Ripkowski (@InverseATASCII) for sharing his work. I learned a lot about programming in Action! by using/viewing his code. And thanks to Mark and crew who originally started it all.

It was fun.

Retrochallenge, Retrochallenge 2016/10

Retrochallenge 2016/10 – Post 6

This is part six of my Retrochallenge 2016/10 journal, where I’m working towards loading ROM images to an Intellivision from an Atari 800. To jump to the very beginning, click here.

This slideshow requires JavaScript.

Adding a User Interface

This week I’ve been working on adding a user interface based in @InverseATASCII’s Action! Window Gadgets found at https://unfinishedbitness.info/tag/action/. This slideshow from my emulator session should show everything except for the transfer because that has to be done on real hardware.

The Code

As we should expect by now, GUI’s require a *lot* of code. The Window Gadgets libraries were published in separate blogs. While it was straight-forward enough to copy the code from the blog entries, I did find there were a small number of DEFINES and supporting functions that were not included in the code snippets. For these I was able to either find in earlier entries, or I created them myself, or found similar functions on atariwiki.org.

Here’s my code, warts and all. (Libraries not included)

INCLUDE "H:DEFINES.ACT"
INCLUDE "H:DEFWIN.ACT"
INCLUDE "H:LIBMISC.ACT"
INCLUDE "H:LIBSTR.ACT"
INCLUDE "H:LIBWIN.ACT"
INCLUDE "H:LIBGADG.ACT"
INCLUDE "H:IOFUN3.ACT"

MODULE

;--------
PROC TITLEBAR()
  BYTE bW1
  bW1=WOpen(2,0,36,3,WINVOFF)
  WPrint(bW1,WPCENT,1,"Intellicart! Downloader")
RETURN

;--------
; OS/A+ 2.0 & DOS XL DRVBYT
; Rtn mnu lst of actve drvs
BYTE FUNC GetDRVBYT(CHAR ARRAY S)
  BYTE DRVBYT=$070A
  BYTE I,J,N,X
  CHAR ARRAY sDn(1)

  I=1;TEST BIT
  J=1;CUR DRV
  N=0;DRV COUNT

  ; Chk Drvs 1-4
  WHILE J<5
  DO
    ; If bit set then Dn active
    ; Inject Drive number into S
    IF DRVBYT&I THEN
      N==+1
      StrB(J,sDn)
      X=4*N-1
      SAssign(S,sDn,X,X)
    FI
    J==+1
    I==*2; Shift left
  OD

  ; Set len(S)
  S(0)=N*4
RETURN(N)

;--------
PROC MsgBox(CHAR ARRAY S)
  BYTE bW,X,Y
  CHAR ARRAY sBtn="[OK]"

  X=19-S(0)/2
  Y=10
  bW=WOpen(X,Y,S(0)+2,3,WINVOFF)
  WPrint(bW,1,1,S)
  ;WPrint(bW,S(0)/2-1,2,sBtn)
  WaitKC()
  WClose(bW)
RETURN

;--------
; Populates S with ROMs found on Dn:
BYTE FUNC GetRomLst(CHAR ARRAY sDn,S)
  DEFINE BUFSIZ="18"
  BYTE INP,COUNT,N,X
  CHAR ARRAY BUF(BUFSIZ)
  CHAR ARRAY MASK(9)
  N=0
  INP=1
  SCopy(MASK,"Dn:*.ROM")
  SAssign(MASK,sDn,1,3)
  Close(INP)
  IF FOpen(INP,6,0,MASK)<=127
  THEN
    DO
      COUNT=FREAD(INP,BUF,BUFSIZ)
      IF COUNT>0
      THEN
         IF BUF(2)<'A THEN
           EXIT
         FI
         N==+1
         X=N*16-15
         SAssign(S,BUF,X,X+16)
      FI
    UNTIL COUNT<>BUFSIZ OR N > 10 OD
  FI
  Close(INP)
  S(0)=N*16
RETURN(N)

;--------
PROC PickROM(CHAR ARRAY sDirEntry,sDn,sM1 BYTE bDrvCnt)
  BYTE bW3,bW2,bCh1,bCh2,X
  CHAR ARRAY sM2(161)
  SCopy(sDn,"Dn:")

  bW3=WOpen(11,5,8,bDrvCnt+2,WINVOFF)
  WTitle(bW3," Dn ")
  DO
    bCh1=GMenuV(bW3,1,1,4,sM1)
    IF bCH1=0 THEN
      EXIT
    FI

    X=4*bCH1-2
    SCopyS(sDn,sM1,X,X+2)

    X=GetRomLst(sDn,sM2)
    IF X=0 THEN
      MsgBox("No ROMs found")
    ELSE
      bW2=WOpen(17,6,18,X+2,sM2)
      WTitle(bW2," ROMs ")
      bCh2=GMenuV(bW2,1,1,16,sM2)
      WClose(bW2)
      IF bCH2>0 THEN
        X=bCH2*16-15+1
        SCopyS(sDirEntry,sM2,X,X+15)
        sDirEntry(0)=15
        EXIT
      FI
    FI
  OD
  WClose(bW3)
RETURN

;--------
PROC GetRomFile(CHAR ARRAY sRomFile,sDn,sDirEntry)
  BYTE L
  CHAR ARRAY S(13)

  ; Extract Basename
  SCopyS(S,sDirEntry,1,8)
  S(0)=8
  RTrim(S)
  L=S(0)

  IF L>0 THEN
    ; Inject "sDn:"
    SCopy(sRomFile,sDn)
    SAssign(sRomFile,":",3,3)
    sRomFile(0)=3
    
    ; Inject basename
    SAssign(sRomFile,S,4,L+4)
    
    ; Inject ext
    SAssign(sRomFile,".ROM",L+4,L+8)
  FI
  sRomFile(0)=L+7
RETURN

;--------
CARD FUNC GetRomSz(CHAR ARRAY sRomFile)
  CARD cRomSz
  CHAR ARRAY S(5)
  SCopyS(S,sRomFile,12,15)
  cRomSz=ValC(S)
RETURN(cRomSz)

;--------
PROC ConfigRS232(BYTE IOCB,bBaud)
  BYTE AUX1
  BYTE AUX2

  ; AUX1: bBaud,8 Bit words,1 stop bit
  ; AUX2: No READY checks
  AUX1=bBaud
  AUX2=0
  XIO(IOCB,0,36,AUX1,AUX2,"R1:")

  ; AUX1: No translation. No parity
  ; AUX2: Unused
  AUX1=32+0+0
  AUX2=0
  XIO(IOCB,0,38,AUX1,AUX2,"R1:")

  ; AUX1: DTR off,RTS off
  ; AUX2: Unused
  AUX1=128+32
  AUX2=0
  XIO(IOCB,0,34,AUX1,AUX2,"R1:")
RETURN

;--------
PROC Send(CHAR ARRAY sRomFile CARD cRomSz BYTE bBaud)
  DEFINE BUFSIZ="128"
  BYTE INP,OUT,bW1,OK
  BYTE ARRAY BUF(BUFSIZ)
  INT  iC,iP1,iP2
  
  OK=1
  iP1=0
  INP=2 ; IOCB #1
  OUT=5 ; IOCB #5

  ; OPEN INPUT FILE
  CLOSE(INP)
  IF FOPEN(INP,4,0,sRomFile)>127
  THEN
    MsgBox("ROM not found")
    OK=0
  FI

  IF OK THEN
    ; OPEN OUTPUT ON ATARI 850
    IF FOpen(OUT,8,0,"R1:")>127
    THEN
      MsgBox("Can't open R1:")
      CLOSE(INP)
      OK=0
    FI
  FI

  IF OK THEN
    bW1=WOpen(7,10,24,4,WINVOFF)
    WPrint(bW1,1,1,"Sending")
    GProg(bW1,2,2,0)

    ConfigRS232(OUT,bBaud)
    DO
      ; XFER BLOCKS FROM INP TO OUT
      iC=FRead(INP,BUF,BUFSIZ)
      IF iC>0
      THEN
        FWrite(OUT,BUF,iC)
      FI
      ; Update Progress
      iP1==+100
      iP2=iP1/cRomSz
      GProg(bW1,2,2,iP2)

      ; Break out on ESC
      IF PEEK(764)=28 THEN
        POKE(764,255)
        iC=0
      FI
    UNTIL iC<>BUFSIZ OD
    WClose(bW1)
  FI

  CLOSE(OUT)
  CLOSE(INP)
RETURN

;--------
BYTE FUNC GetBaud(BYTE X)
  BYTE B,bW,bCh
  CHAR ARRAY sM(26)
  SCopy(sM,"  2400  4800  9600 19200")

  bW=WOpen(7,7,10,6,WINVOFF)
  WTitle(bW," Baud ")

  bCh=GMenuV(bW,1,1,6,sM)
  IF bCh=1 THEN
    B=12 ; 2400
  ELSEIF bCh=2 THEN
    B=13 ; 4800
  ELSEIF bCh=3 THEN
    B=14 ; 9600
  ELSEIF bCh=4 THEN
    B=15 ; 19200(?)
  ELSE
    B=X ; No change
  FI
  WClose(bW)

RETURN(B)

;--------
PROC DisplaySettings(BYTE bW,bB CHAR ARRAY sR)
  CHAR ARRAY sB(7)
  WClr(bW)
  WPrint(bW,1,1,"ROM                   ")   
  WPrint(bW,1,2,"Baud        ")   
  IF sR(0) THEN
    WPrint(bW,6,1,sR)
  ELSE
    WPrint(bW,6,1,"None")
  FI

  IF bB=12 THEN
    SCopy(sB,"2400 ")
  ELSEIF bB=13 THEN
    SCopy(sB,"4800 ")
  ELSEIF bB=14 THEN
    SCopy(sB,"9600 ")
  ELSEIF bB=15 THEN
    SCopy(sB,"19200")
  FI
 WPrint(bW,6,2,sB)

RETURN

;--------
PROC DisplayAbout()
  BYTE bW
  CHAR ARRAY S(26)

  bW=WOpen(6,5,28,14,WINVOFF)

  SCopy(S," Retrochallenge 2016/10 ")
  STRINV(S+1,S(0))
  WPrint(bW,WPCENT,1,S)

  SCopy(S,"Intellicart! Downloader ")
  STRINV(S+1,S(0))
  WPrint(bW,WPCENT,2,S)

  WPrint(bW,WPCENT,3,"[Version 0.1]")
  WPrint(bW,WPCENT,5,"Michael Sternberg")
  WPrint(bW,WPCENT,6,"[16kRAM.com]")
  WPrint(bW,WPCENT,8,"UI Libraries by")
  WPrint(bW,WPCENT,9,"Wade Ripkowski")
  WPrint(bW,WPCENT,10,"[unfinishedbitness.info]")
  WPrint(bW,WPCENT,12,"CC BY-ND 4.0")
  WaitKC()
  WClose(bW)

RETURN

;--------
PROC MAIN()
  BYTE bW1,bW2
  BYTE bDrvCnt,bCh,N,bBaud
  CARD cRomSz
  CHAR ARRAY sM1(56),sM2(17)
  CHAR ARRAY sDn(3),sDirEntry(17),sRomFile(16)

  SCopy(sDn,"Dn:")
  SCopy(sM1," Pick ROM > Send       Set Baud   About      Exit      ")
  SCopy(sM2," Dn: Dn: Dn: Dn:")
  sRomFile(0)=0
  bBaud=14 ; Default to 9600
  bDrvCnt=GetDRVBYT(sM2)

  Winit()
  TitleBar()

  ; Current Rom
  bW2=WOpen(2,19,24,4,WINVOFF)
  ;WTitle(bW2," Settings ")
  DisplaySettings(bW2,bBaud,sRomFile)

  ; Main menu
  bW1=WOpen(2,4,13,7,WINVOFF)
  WTitle(bW1," Main ")
  DO
    bCh=GMenuV(bW1,1,1,11,sM1)
    ; Pick ROM
    IF bCh=1 THEN
      PickROM(sDirEntry,sDn,sM2,bDrvCnt)
      cRomSz=GetRomSz(sDirEntry)
      GetRomFile(sRomFile,sDn,sDirEntry)
      DisplaySettings(bW2,bBaud,sRomFile)
    ; Send ROM to Intellicart!
    ELSEIF bCh=2 THEN
      IF sRomFile(0)=0 THEN
        MsgBox("No ROM Selected")
      ELSE
        Send(sRomFile,cRomSz,bBaud)
      FI
    ; Change Baud setting
    ELSEIF bCh=3 THEN
      bBaud=GetBaud(bBaud)
      DisplaySettings(bW2,bBaud,sRomFile)
    ; Display "About" dialog
    ELSEIF bCh=4 THEN
      DisplayAbout()
    ; Exit to DOS
    ELSEIF bCh=5 THEN
      PUT(125) ; Clear screen
      PRINTE("Bye")
      EXIT
    FI
  OD
RETURN

Too Many Global Variables

I encountered a problem tonight when doing my final compile. I can successfully create a binary file that requires the Action! cartridge to be inserted in the Atari computer at runtime. However I wanted to also create a stand-alone binary that does not need the Action! cartridge at runtime. This involves adding a special runtime library file (SYS.LIB) to the list at the top of my code. However, I was getting an error code related to too many global variables when trying to compile everything with SYS.LIB.

This is a known problem and is discussed in the Action! Run-Time Library manual (pp 11). Here’s the important part:

global_variables

Alas, this will have to wait for another day if ever.

Up Next

A video to show everything working and farewell to this Retrochallenge.

Retrochallenge, Retrochallenge 2016/10

Retrochallenge 2016/10 – Post 5

This is part five of my Retrochallenge 2016/10 journal, where I’m working towards loading ROM images to an Intellivision from an Atari 800. To jump to the very beginning, click here.

Tranferring ROMs from the Atari 800 to the Intellicart!

Here I’ll combine what I learned in Post 3 about transferring non-Intellivision data from the Atari 800 to my laptop and what I learned in Post 4 about creating and transferring Intellivision ROMs from my laptop to the Intellicart!. The result should be transferring Intellivision ROMs from the Atari 800 to the Intellicart!. Yippee!

850_intellivision_setup

Something Afoul in the Library

The Action! code I created in Post 3 reads characters from a small text file using the statement CH=GETD(INP). In that experiment, the GETD() procedure found in Action!’s default library returned zeroes once the program started reading past the end-of-file. That’s somewhat okay for reading text files but will not work when reading binary ROM files which will certainly contain many, many zeroes as valid data.

I looked through the Action! documentation and couldn’t find any procedures or functions that would provide a clue when the end-of-file is encountered. One kludgey solution would be to set up a loop counter break out of it after a per-determined number of iterations. Then I’d have to maintain a table of byte counts for each ROM file. Adding new ROM files would require updating the table. That’s no good.

IOFUN3

Looking through the list of Action! articles at atariwiki.org, I found a library file called iofun3.act. It contains file I/O functions akin to those found in Unix’s low-level system library. That is, the file read function includes a requested number of bytes to be retrieved and then returns the actual number of bytes retrieved. So if the function requests to read, say, 128 bytes, but receives something less than 128 bytes, then it can be assumed the end-of-file has been reached.

action_iofun3

Let’s get cracking.

Action! Code to Upload a ROM to the Intellicart!

INCLUDE "D3:IOFUN3.ACT"

;------------------------------------
PROC CONFIG_RS232(BYTE IOCB)    
  BYTE AUX1
  BYTE AUX2

  ; AUX1: 19200,8 Bit words,1 stop bit
  ; AUX2: No READY checks
  AUX1=15
  AUX2=0
  XIO(IOCB,0,36,AUX1,AUX2,"R1:")

  ; AUX1: No translation. No parity
  ; AUX2: Unused
  AUX1=32+0+0
  AUX2=0
  XIO(IOCB,0,38,AUX1,AUX2,"R1:")

  ; AUX1: DTR off,RTS off
  ; AUX2: Unused
  AUX1=128+32
  AUX2=0
  XIO(IOCB,0,34,AUX1,AUX2,"R1:")
RETURN

;------------------------------------
PROC MAIN()
  DEFINE BUFSIZ="256"
  BYTE CH, INP,OUT, GO
  BYTE ARRAY ROMFILE(30)
  BYTE ARRAY BUF(BUFSIZ)
  CARD COUNT  
  CARD TOTAL

  INP=2 ; IOCB #1
  OUT=5 ; IOCB #5
  TOTAL=0

  ; GET INPUT FILE
  PRINT("Enter ROM: ")
  INPUTS(ROMFILE)

  ; OPEN INPUT FILE
  CLOSE(INP)  
  IF FOPEN(INP,4,0,ROMFILE)>127
  THEN
    PRINTE("Error> ROM not found.")
  ELSE
    ; OPEN OUTPUT ON ATARI 850
    FOPEN(OUT,8,0,"R1:")
    CONFIG_RS232(OUT)
    DO
      ; XFER BLOCKS FROM INP TO OUT
      COUNT=FREAD(INP,BUF,BUFSIZ)
      IF COUNT>0
      THEN
        FWRITE(OUT,BUF,COUNT)
      FI
      TOTAL==+COUNT
      PRINT("So far...")
      PRINTCE(TOTAL)
    UNTIL COUNT<>BUFSIZ OD
  FI

  ; HOUSEKEEPING
  CLOSE(OUT)   
  CLOSE(INP)
RETURN

 A Trivial Test

  1. Created a custom Intellivision ROM image called RC201610.ROM using TESTROM.BIN found on the Intellicart! Download Software diskette as a basis.
  2. Transferred the ROM file to a physical floppy disk via a NUXX SDrive SD card/floppy drive emulator.
  3. Booted DOS XL and ran the compiled version of the Action! code found above.
  4. Entered “RC201610.ROM” at the program’s input prompt.

A Non Trivial Test

Here I transferred a ROM image for the 2011 homebrew game DK Arcade which was 49,221 bytes. There’d only be room for two ROMs that size on a typical Atari-formatted diskette. (If you’re wondering why the ROM files are so large, the Intellivision uses 10-bit words called decles. The ROM format spreads that information across two bytes).

Up Next

If nothing else gets accomplished, I’d be happy with having this command-line user interface. But my original plan was to have a “GUI” using @InverseATASCII’s Window Gadgets for Action!. I’ll have a little more than a week to get that working.

Retrochallenge, Retrochallenge 2016/10

Retrochallenge 2016/10 – Post 4

This is part four of my Retrochallenge 2016/10 journal, where I’m working towards loading ROM images to an Intellivision from an Atari 800. To jump to the very beginning, click here.

Transferring ROMs from Linux to the Intellicart!

Before trying to transfer ROMs from the Atari 800 to the Intellicart!, I thought it wiser to troubleshoot these details from a modern machine.

linux_intellicart_setupBinary ROM Images and The Intellicart!

ROMs for the library of classic Intellivision games are typically available as raw binary files containing solely the bits dumped from cartridge EPROMs. These raw data files are found on ROM archive websites with a “.bin” file extension. I’d like to transfer ROM images from the Atari 800 to the Intellicart!. However, the Intellicart! cartridge emulator expects more than just the raw binary data. It expects some transmission details and metadata before and after the raw binary data. This download protocol is explained in the Intellicart! manual pages 17-22.

intellicartmanual
Intellicart! Manual (Click on image to go to archive.org)

The Intellicart! Download Protocol

Here is a summary of the Intellicart! download protocol verbatim from the manual:

  1. Send Byte 0xA8, used for auto baud rate detection
  2. Send number of ROM segments
    This is the number of non-contiguous ROM segments that will follow. For example, a cart that occupied memory from 0x5000-0x6FFF and 0xD000-0xDFFF would send the number 0x02. (The actual binary value, not its ASCII equivalent.)
  3. Send the ones complement of the number of ROM segments.
  4. Send high byte of start address of first segment, 0x50 for above example.
  5. Send high byte of stop address of first segment, 0x6F for above example.
  6. Send the ROM segment itself.
  7. Send the high byte of the CRC-16 for the first ROM segment.
  8. Send the low byte of the CRC-16 for the first ROM segment.
  9. Repeat steps 4-8 for each additional ROM segment.
  10. Send the Enable Tables (see manual for details).
  11. Send high byte of CRC-16 for the tables.
  12. Send low byte of CRC-16 for the tables.
  13. Done

The Intellicart! Diskette

intellicart_diskette

At the beginning of this season’s Retrochallenge, my assumption was I’d have to write my own code to handle the details of the download protocol either at run-time on the Atari, or more likely, in a pre-calculated form on a modern machine.

So it was with great gratitude to the Intellicart! team that I found a C source file called BIN2ROM.C included on its installation diskette. The C source compiled without complaints on my Linux laptop. The program takes a .bin and corresponding .cfg file as input and outputs a .rom file that encapsulates the entire protocol. The only caveat is that for it to run successfully under Linux, the input files need to be lowercase. Many of the .BIN files included on the installation disk are old-fashioned MS-DOS upper case.

The diskette is available here.

Creating a Test ROM File

Included on the installation diskette for the Intellicart! is (among other .BIN files) a file called TESTROM.BIN. This is a minimal Intellivision program to test downloads. I’ll be using it for my tests.

1. Compile BINROM.C (included on Intellicart! diskette).

$ cc -o bin2rom BIN2ROM.C
$ ls -l bin2rom
-rwxr-xr-x 1 michael michael 15192 Oct 20 19:44 bin2rom

2. Create copies of TESTROM.BIN & TESTROM.CFG with lower-case names to appease the Linux version of the executable.

$ cp TESTROM.BIN testrom.bin
$ cp TESTROM.CFG testrom.cfg
$ ls -l testrom.*
-rw-r--r-- 1 michael michael 512 Oct 20 19:45 testrom.bin
-rw-r--r-- 1 michael michael  92 Oct 20 19:45 testrom.cfg

2. Convert testrom.bin to testrom.rom

$ ./bin2rom testrom
$ ls -l testrom.*
-rw-r--r-- 1 michael michael 512 Oct 20 19:45 testrom.bin
-rw-r--r-- 1 michael michael  92 Oct 20 19:45 testrom.cfg
-rw-r--r-- 1 michael michael 569 Oct 20 19:48 testrom.rom

Now I need to try uploading testrom.rom to the Intellicart!.

Minicom Is a Bad Friend

I’ve used minicom to get me this far in my Retrochallenge. I’ve used it to capture data being sent from the Intellicart software for Windows to the Intellicart! cartridge. However, I tried transferring testrom.rom from my Linux laptop to the Intellicart! cartridge using minicom’s “Paste File” functionality but I kept receiving a BAUD ERROR on the Intellicart! side.

minicom_paste
minicom “Paste File” didn’t work for me
image2
Baud News

STTY Is My New Friend

To the rescue comes the old Unix tool stty, which alters terminal line settings. I’ve used STTY to correct backspace keys and screen sizes in the past. But this functionality is new to me and now I’m grateful minicom was unsuccessful. Otherwise I may not have learned about it.

$ stty -F /dev/ttyUSB0 raw speed 9600
$ cat testrom.rom > /dev/ttyUSB0

The first command configures my laptop’s serial port to 9600 baud and the second command uploads the ROM file onto the serial connection.

Up Next

So now I know I’m able to generate a ROM data file that is acceptable to the Intellicart!. And I know what serial port configuration works. I just need to do the same on the Atari 800 and I should find success there, too.

Retrochallenge, Retrochallenge 2016/10

Retrochallenge 2016/10 – Post 3

This is part three of my Retrochallenge 2016/10 journal, where I’m working towards loading ROM images to an Intellivision from an Atari 800. To jump to the very beginning, click here.

850_setup

My First Serial Transmission From Atari & Action!

Before attempting to send data to the Intellicart! cartridge emulator on the Intellivision, I wanted to be sure I can send data correctly from the Atari 800 and its 850 interface module.

For this, I wrote a quick and dirty Action! script on the Atari 800 to open a small text file as input and configure/open a serial connection for output. The Atari 800 reads bytes from a text file stored on a floppy and sends the bytes to the serial connection provided by the Atari 850 interface module. On the other end of the serial connection is a serial to USB adapter and my laptop running minicom, which is listening to /dev/ttyUSB0 and capturing any input. The serial cable I am using is a normal null-modem serial cable, not a normal null-modem cable. Correction: I am using a null-modem cable.

Using my laptop to receive the data provides a way for me to observe what exactly is arriving via the RS232 connection. The Intellicart! will provide little diagnostic feedback.

Lessons Learned:

  1. When working with a serial connection, ensure the serial cable is connected.
  2. When working with minicom,  modify its configuration–>screen & keyboard setting to display hex. This avoids any confusion caused by characters being interpreted as control codes such as vertical tabs, backspaces, etc.

Configuring the Atari 850 Interface Module

For setting the baud rate, parity, stop bits, and the other RS232 settings on the Atari 850 interface module, the Action! language provides the XIO command which is similar to the XIO command found in Atari BASIC. The XIO command is a way to talk to devices via its driver software.

The general format of the XIO command in Action! is:

XIO(IOCB, 0, cmd, AUX1, AUX2, "Rn:")
  • where IOCB is be a number between 0-7 (maybe just 1-5 in this case)

The I/O Control Block number (IOCB#) specifies which channel a program is assigning to some interaction with a device. Normally, this can be a number between 0 and 7, however when using Action! channels 6 and 7 are already assigned to the editor (E:) and screen (S:) devices. Your program would allocate a channel to a device/file, perform some operation (read, write, get status, etc), then close the channel when finished.

  • and where the zero is required
  • and where cmd can be:
cmd Description
36 Set baud rate, word size, stop bits, and ready monitoring
38 Set translation mode and parity
34 Set outgoing lines DTR, RTS, and XMT
  • and where AUX1 and AUX2 are normally bit fields containing flags for different options.

For example, with XIO command 36, bits 0 through 3 define baud rate. The 850 technical manual contains tables with the available options (15 is supposed to be 19200).

850_baud_rates

Sample table from Atari 850 Technical Manual

  • and, finally, where “Rn:” specifies which of the four RS232C ports on the Atari 850 is being configured.

n can be a value between 1 and 4. “R:” is the same as “R1:”. One thing to keep in mind is that not all 4 serial ports on the 850 have exact same pin-outs. R1 is normal enough for our use.

Code

Here is the Action! code that runs on the Atari to send a small packet of bytes at 9600 8N1 to serial port 1 (R1:) on the Atari 850.

;------------------------------------
PROC HOME()
  PUT(125); Clear screen
RETURN
       
;------------------------------------
PROC INIT_R1(BYTE IOCB)    
  BYTE AUX1
  BYTE AUX2

  AUX1=14+0+0 ; 9600,8 bit word,1 stop bit
  AUX2=0  ; no ready checks
  XIO(IOCB,0,36,AUX1,AUX2,"R1:")

  AUX1=32+0+0;No translation nor parity
  AUX2=0
  XIO(IOCB,0,38,AUX1,AUX2,"R1:")

  AUX1=128+32 ;DTR off,RTS off
  AUX2=0
  XIO(IOCB,0,34,AUX1,AUX2,"R1:")
RETURN

;------------------------------------
PROC MAIN()
  BYTE CH
  BYTE INP,OUT
  HOME() 

  INP=1 ; IOCB #1
  OUT=5 ; IOCB #5
  OPEN(INP,"D2:TEST.TXT",4,0)
  OPEN(OUT,"R1:",8,0)          
  INIT_R1(OUT)

  CH=GETD(INP) ; READ CHAR FROM TXT FILE
  WHILE CH
  DO
    PUT(CH)      ;PRINT TO SCREEN
    PUTD(OUT,CH) ;WRITE TO R1:
    CH=GETD(INP)
  OD

  CLOSE(OUT)   
  CLOSE(INP)
RETURN

Some notes:

  1. INIT_R1 calls XIO to configure the RS232 port’s baud rate, etc.
  2. D2:TEST.TXT contains the text:
ABCDEFGH
01234567

Results

Here is minicom running on my laptop set to listen to /dev/ttyUSB0 at 9600 8N1. The minicom screen/keyboard setting has been configured to display data received in hex format. The bytes received match the bytes that were sent (“A” = 0x41, “B” = 0x42, …). 0x9B is Atari’s EOL character.

rs232_success_02

I’m thrilled!

Up Next

Learn a little more about the data transfer protocol expected by the Intellicart!

Retrochallenge, Retrochallenge 2016/10

Retrochallenge 2016/10 – Post 2

This is part two of my Retrochallenge 2016/10 journal, where I’m working towards loading ROM images to an Intellivision from an Atari 800. To jump to the very beginning, click here.

dos_xl_ver_2-42w

OSS DOS XL version 2.42w

After some searching, as far as I could tell, my copy of OSS DOS XL (version 2.42w) has not been archived / preserved yet on the Internet. It’s a variation the disk operating system, called Warp Speed DOS XL, to take advantage of HAPPY 810 & 1050 upgraded Atari floppy drives.

I’ve uploaded the information I have to AtariAge and archive.org.

happy_ad
A.N.A.L.O.G. magazine no. 47 pp. 7

https://archive.org/details/a8b_DOSXL_v2.42_1985_OSS

http://atariage.com/forums/topic/239044-happy-warp-speed-software-disk/?p=3611419