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.

Advertisements