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