100 ; THE NAME OF THIS PROGRAM IS 'ASM' 8 JUN 87
110 ;
120 ; SET UP FOR 1/2 MEG OF MEMORY (520) OR OVER 1/2 MEG OF MEMORY (1040)
130 ;
140 PEEK $000437,ST%:IF ST%>12 THEN ST%=1040:GOTO 160 ELSE ST%=520
150 HIMEM $03B000:DIM CODE[4096],LBL$[2048]12:GOTO 180
160 HIMEM $049800:DIM CODE[8192],LBL$[4096]12
170 ;
180 DIM TX[4096],ERR%[120,3],ERRMSG$[64]32,FILNAM$[64]16,HEX$[256]2
190 DIM D$16,E$4,F$16,LENGTH$4,LIN$79,LI$15,W$2,Y$1,Z$1:SELECT PRINT 0
200 INIT LBL$[]="            "
210 ;
220 CLS:VTAB 5:HTAB 12:PRINT "*** ASM ***":VTAB 8:D$="0123456789ABCDEF"
230 ;
240 PRINT " YOU MUST REPEAT must HAVE A PRINTER ATTACHED TO YOUR ST AND TURNED ON."
250 PRINT " THERE IS NO OPTION, NOR WILL THERE EVER BE AN OPTION, TO USE THIS ASSEMBLER"
260 PRINT " WITHOUT A HARD COPY PRINTER.  THIS ASSEMBLER IS FOR SERIOUS DEVELOPMENT WORK"
270 PRINT " WHERE A HARD COPY RECORD IS UTTERLY ESSENTIAL.":PRINT
280 PRINT " (A SECOND DISK DRIVE IS STRONGLY RECOMMENDED BUT NOT ABSOLUTELY ESSENTIAL)"
290 PRINT:PRINT:PRINT " PRESS ANY KEY TO CONTINUE"
300 INKEY Z$:IF LEN(Z$)=0 GOTO 300 ELSE CLS:VTAB 8
310 ;
320 PRINT " THIS ASSEMBLER CAN USE EITHER ONE OR TWO DISK DRIVES":PRINT
330 PRINT " IF A SECOND DRIVE IS USED, THEN THE SOURCE FILES MUST BE ON IT,"
340 PRINT " AND THE OBJECT FILE (IF SPECIFIED), WILL BE SAVED ON IT."
350 PRINT:INPUT "NUMBER OF DRIVES (1 OR 2) ? ",DRF%
360 ;
370 IF DRF%=0 GOTO 350 ELSE IF DRF%>2 GOTO 350 ELSE CLS:VTAB 5
380 ;
390 PRINT " YOU MAY ASSEMBLE A SINGLE SOURCE FILE OR A SERIES OF SOURCE FILES."
400 PRINT:PRINT " IF YOU ARE ASSEMBLING A SERIES OF SOURCE FILES, THERE MUST BE A FILE,"
410 PRINT " CALLED THE 'FILE OF FILES', WHICH CONTAINS ONLY THE NAMES OF THE SOURCE"
420 PRINT " FILES, IN THE SEQUENCE IN WHICH THE FILES ARE TO BE ASSEMBLED.":PRINT
430 PRINT " TO REPEAT, THERE MUST BE nothing IN THE 'FILE OF FILES' EXCEPT THE NAMES"
440 PRINT " OF THE SOURCE FILES TO BE ASSEMBLED:  NO COMMENTS, HEADERS, EXPLANATIONS,"
450 PRINT " nothing BUT THE NAMES OF THE SOURCE FILES.  IF THERE ARE FIVE SOURCE FILES,"
460 PRINT " THEN THE 'FILE OF FILES' CAN CONTAIN ONLY FIVE LINES.  THE NAMES OF THE"
470 PRINT " SOURCE FILES ARE ENTERED AS IF THEY ARE LABELS, WITH NO SPACE CHARACTER AT"
480 PRINT " THE BEGINNING OF THE LINE.":PRINT:PRINT
490 ;
500 INPUT "ASSEMBLE ONLY ONE FILE (Y,N) ? ",Z$
510 IF ASC(Z$)>96 THEN Z$=CHR$(ASC(Z$)-32)
520 IF Z$="Y" THEN FN%=1 ELSE IF Z$<>"N" GOTO 500 ELSE GOTO 550
530 PRINT:PRINT:INPUT "INPUT THE FILENAME ",FN$:FILNAM$[0]=FN$:GOTO OBJFN
540 ;
550 PRINT:PRINT
560 PRINT " THE FILE SEQUENCE TO BE ASSEMBLED IS SPECIFIED BY A FILE IN DRIVE";
570 PRINT DRF%;"WHICH":PRINT "CONTAINS THE FILENAME SEQUENCE.":PRINT
580 INPUT "THE NAME OF THAT FILE ? ",FN$
590 FILNAM$[0]=FN$:LIST%=2:LBLREF%=1
600 ;
610 ;
620 ; SPECIFY THE NAME OF THE OBJECT CODE FILE (IF ANY)
630 ;
640  "OBJFN":PRINT:PRINT " INPUT THE OBJECT FILE NAME ? ";:EDIT OFN$
650 ;
660 PRINT:PRINT " 1 = NEVER LIST":PRINT " 2 = FOLLOW LIST CMDS"
670 PRINT " 3 = ALWAYS LIST":PRINT:INPUT "YOUR CHOICE ? ",LIST%:PRINT
680 IF LIST%<1 GOTO 660 ELSE IF LIST%>3 GOTO 660
690 ;
700 PRINT " 1 = DON'T LIST LABEL REFERENCES":PRINT " 2 = LIST THE ALPHANUMERIC ";
710 PRINT "REF'RNC TABLE":PRINT " 3 = LIST THE NUMERIC REFERENCE TABLE"
720 PRINT " 4 = LIST BOTH LABEL REFERENCE TABLES":PRINT
730 INPUT "YOUR CHOICE ? ",LBLREF%:PRINT
740 IF LBLREF%<1 GOTO 700 ELSE IF LBLREF%>4 GOTO 700
750 ;
760 ; BEGIN THE ASSEMBLY PROCESS (LOAD THE FILES)
770 ;
780  "BEGIN"
790 BLOAD AP1P2;1,$020000
800 IF ST%=520 THEN POKE $02000C,HEX(07FF00003000000A0FFF0003B00000033000)
810 TXLOC TX[],A:IF FN%=1 GOTO 890 ELSE BLOAD FN$;DRF%,A
820 ;
830 CALL $020008:PEEKW $00FFFE,NUMFILES%
840 IF NUMFILES%<0 THEN PRINT "THERE ARE NO FILES TO BE SEQUENCED":GOTO END
850 ;
860 ; LOAD THE FIRST SOURCE FILE TO BE ASSEMBLED
870 ;
880 PRINT "LOADING THE SOURCE FILE(S):":PRINT
890 FN$=FILNAM$[0]:DR DRF%:IF FN%=1 THEN BLOAD FN$,A ELSE BLOADZ FN$,A
900 START TIMER:JUMP $020000:T=TIMER(0):IF NUMFILES%=0 GOTO 970
910 ;
920 ; LOAD AND ASSEMBLE THE REMAINING FILES, IF ANY (PASS 1)
930 ;
940 FOR I%=1 TO NUMFILES%:FN$=FILNAM$[I%]:BLOADZ FN$,A
950 START TIMER:JUMP $020004:T=T+TIMER(0):NEXT I%
960 ;
970 PRINT "PASS 1 CPU TIME =";T;"SECS":PRINT
980 PEEKW $00142E,LBLCNT%:PRINT "THERE ARE";LBLCNT%;"LABELS"
990 ;
1000 ; CHECK FOR PASS 1 ERRORS
1010 ;
1020 PN%=1:PEEKW $001428,E%:E%=E%/6:IF E%>0 GOTO PRINT_ERRORS
1030 PRINT "THERE ARE NO PASS 1 ERRORS":PRINT:POKE $001440,HEX(0001)
1040 ;
1050 ; NO PASS 1 ERRORS SO START PASS 2
1060 ;
1070 ;
1080 START TIMER:JUMP $021C00
1090 IF NUMFILES%>0 THEN FOR I%=1 TO NUMFILES%:JUMP $021C04:NEXT I%
1100 PRINT "PASS 2 ELAPSED TIME =";TIMER(0);"SECS":PRINT
1110 ;
1120 ; CHECK FOR PASS 2 ERRORS
1130 ;
1140 PN%=2:PEEKW $001428,E%:E%=E%/6:IF E%>0 GOTO PRINT_ERRORS
1150 PRINT "THERE ARE NO PASS 2 ERRORS"
1160 PEEK $001401,AH%:PEEK $001402,AM%:PEEK $001403,AL%
1170 CODESIZE=65536*FLT(AH%)+256*FLT(AM%)+FLT(AL%)
1180 PRINT "THERE ARE";CODESIZE;"OBJECT CODE BYTES"
1190 PEEKW $001444,LBLREFS%:PRINT "THERE ARE";LBLREFS%;"LABEL REFERENCES"
1200 PRINT:IF OFN$="" GOTO BEGIN_PASS_3
1210 ;
1220 ; SAVE THE OBJECT CODE IN A BINARY FILE
1230 ;
1240 IF ST%=520 THEN BSAVEZ OFN$,$033000,CODESIZE
1250 IF ST%=1040 THEN BSAVEZ OFN$,$039800,CODESIZE
1260 ;
1270 ; NO PASS 2 ERRORS; BEGIN PASS 3 UNLESS 'NEVER LIST' SELECTED
1280 ;
1290  "BEGIN_PASS_3"
1300 IF LIST%=1 GOTO END ELSE POKE $001440,HEX(0000)
1310 IF LIST%<>2 THEN POKE $001440,HEX(0100)
1320 START TIMER:JUMP $021C00
1330 IF NUMFILES%=0 GOTO 1340 ELSE FOR I%=1 TO NUMFILES%:JUMP $021C04:NEXT I%
1340 PRINT "PASS 3 ELAPSED TIME =";TIMER(0);"SECS":PRINT
1350 IF LBLREF%=1 THEN SELECT PRINT 1:Y$=HEX(0C):PRINT Y$;:SELECT PRINT 0
1360 ;
1370 ; OPTIONAL LABEL REFERENCE LISTING BEGINS HERE
1380 ;
1390 IF LBLREF%=1 GOTO END ELSE POKE $00FFC0,HEX(023900400000FFCF4E75)
1400 SELECT PRINT 1:PRINT:Y$=HEX(0C):PRINT Y$;
1410 FOR I%=0 TO 15:FOR K%=0 TO 15:HEX$=MID$(D$,I%+1,1):J%=16*I%+K%
1420 HEX$=HEX$+MID$(D$,K%+1,1):HEX$[J%]=HEX$:NEXT K%:NEXT I%
1430 ;
1440 ; PRINT THE ALPHABETICAL LABEL LISTING
1450 ;
1460 IF LBLREF%=2 THEN GOSUB SVC_LBLS ELSE IF LBLREF%=4 THEN GOSUB SVC_LBLS
1470 ;
1480 ; PRINT THE NUMERIC LABEL LISTING
1490 ;
1500 QL%=1:LBLPTR%=0:CALL $021C08
1510 IF LBLREF%=3 THEN GOSUB SVC_LBLS ELSE IF LBLREF%=4 THEN GOSUB SVC_LBLS
1520 ;
1530 GOTO END
1540 ;
1550 ;
1560  "SVC_LBLS"
1570 PEEKW $00142E,L%:NLBLS%=L%:LINES%=60:SELECT PRINT 1
1580 IF NLBLS%>=240 THEN GOSUB SVC_PAGE ELSE GOTO SVC_LAST
1590 FOR J%=1 TO 6:PRINT:NEXT J%:GOTO 1580
1600 ;
1610 ; PRINT THE LAST, PARTIAL PAGE OF LABEL REFERENCES
1620 ;
1630  "SVC_LAST"
1640 A=FLT(NLBLS%)/4:B=INT(A):IF A<>B THEN B=B+1
1650 LINES%=FIX(B):GOSUB SVC_PAGE:PRINT
1660 PRINT "          THERE ARE";L%;"LABELS"
1670 Z$=HEX(0C):PRINT Z$;:RETURN
1680 ;
1690 ;
1700 ;
1710 ; THIS IS THE END OF THE PROGRAM
1720 ; THE FOLLOWING ARE MISCELLANEOUS UTILITY SUBROUTINES
1730 ;
1740 ;
1750 ;
1760 ; PRINT A FULL PAGE OF LABEL REFERENCES
1770 ;
1780  "SVC_PAGE"
1790 ST%=LBLPTR%:END%=LBLPTR%+LINES%-1:FOR BASE%=ST% TO END%:GOSUB SVC_LINE
1800 PRINT LIN$:NEXT BASE%:LBLPTR%=LBLPTR%+240:NLBLS%=NLBLS%-240:RETURN
1810 ;
1820  "SVC_LINE"
1830 LIN$="   ":FOR Q%=0 TO 3:I%=Q%*LINES%+BASE%
1840 GOSUB SVC_LABEL:LIN$=LIN$+"    "+LI$:NEXT Q%:RETURN
1850 ;
1860  "SVC_LABEL"
1870 A$=LBL$[I%]:IF QL%=1 GOTO ADR_ORDER
1880 IF MID$(A$,1,1)=$FF THEN LI$="               ":RETURN
1890 LI$=MID$(A$,1,8)+" ":Y$=MID$(A$,9,1)
1900 POKE $00FFCF,Y$:CALL $00FFC0:PEEK $00FFCF,Z$
1910 IF Z$=$00 THEN MID$(LI$,9,1)=HEX(3F)
1920 LI$=LI$+HEX$[ASC(MID$(A$,10,1))]+HEX$[ASC(MID$(A$,11,1))]
1930 LI$=LI$+HEX$[ASC(MID$(A$,12,1))]:RETURN
1940 ;
1950  "ADR_ORDER"
1960 IF MID$(A$,5,1)=$FF THEN LI$="               ":RETURN
1970 LI$=HEX$[ASC(MID$(A$,2,1))]+HEX$[ASC(MID$(A$,3,1))]
1980 LI$=LI$+HEX$[ASC(MID$(A$,4,1))]+" "+MID$(A$,5,8):RETURN
1990 ;
2000 ;
2010 ;
2020 ; IN CASE OF ERRORS, THE ASSEMBLY PROCESS STOPS AND THE
2030 ; ERRORS ARE PRINTED
2040 ;
2050  "PRINT_ERRORS"
2060 SELECT PRINT 0:PRINT:PRINT "THERE ARE";E%;"PASS";PN%;"ERRORS":PRINT
2070 PRINT " *****  TURN ON YOUR EPSON-COMPATIBLE HARD-COPY PRINTER  *****";
2080 SELECT PRINT 1:PRINT:CLRLINE 24
2090 PRINT "THERE ARE";E%;"PASS";PN%;"ERRORS"
2100 FOR I%=0 TO E%-1:N%=ERR%[I%,0]:LINE%=ERR%[I%,1]:F%=ERR%[I%,2]
2110 PRINT "FILE ";FILNAM$[F%];", LINE";LINE%;"ERROR = ";ERRMSG$[N%]:NEXT I%
2120 PRINT:Z$=HEX(0C):PRINT Z$;
2130 ;
2140  "END":PRINT:Z$=HEX(0C):PRINT Z$;:SELECT PRINT 0:DR 1:END
