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:

Alas, this will have to wait for another day if ever.
Up Next
A video to show everything working and farewell to this Retrochallenge.