This allows you to view different commentaries side-by-side. You can enable/disable individual columns:
Microsoft/Commodore Source | The original M6502 BASIC source by Microsoft (KIM-1 version, not everything lines up, Commodore extensions are missing, but lots of comments by the original authors) and the original C64 KERNAL source by Commodore (lots of comments by the original authors) | |
Data Becker [German] | German-language comments from Das neue Commodore-64-intern-Buch by Data Becker, ISBN 3890113079. Some minor corrections have been made. | |
Lee Davison | Comments from The almost completely commented C64 ROM disassembly V1.01 by Lee Davison. Some minor corrections have been made. | |
Bob Sander-Cederlof [BASIC only] | Comments adapted from S-C DocuMentor for Applesoft by Bob Sander-Cederlof, for the version of Microsoft BASIC that shipped with the Apple II. | |
Magnus Nyman [KERNAL only] | Comments from JIFFYDOS version 6.01/version 6.02 by Magnus Nyman (Harlekin/FairLight), which were written for the JiffyDOS KERNAL, so some serial code and all tape code is missing comments. | |
Marko Mäkelä | Comments from the Commodore 64 BASIC/KERNAL ROM Disassembly Version 1.0 (June 1994) by Marko Mäkelä. |
Disassembly | Microsoft/Commodore Source | Data Becker [German] | Lee Davison | Bob Sander-Cederlof [BASIC only] | Magnus Nyman [KERNAL only] | Marko Mäkelä |
---|---|---|---|---|---|---|
.:A000 94 E3 |
Start-Vektor $E394 |
BASIC cold start entry point |
RESET |
|||
.:A002 7B E3 |
NMI-Vektor $E37B |
BASIC warm start entry point |
Warm StartCBMBASIC |
|||
.:A004 43 42 4D 42 41 53 49 43 |
PAGEDISPATCH TABLES, RESERVED WORDS, AND ERROR TEXTS.ORG ROMLOC |
'cbmbasic'Adressen der BASIC-Befehle -1(Interpreterkode Adresse Befehl) |
'cbmbasic', ROM name, unreferencedaction addresses for primary commandsthese are called by pushing the address onto the stack and doing an RTS so theactual address -1 needs to be pushed |
'cbmbasic'BRANCH TABLE FOR TOKENS |
address table for commands(address minus 1 used) |
|
.:A00C 30 A8 |
STMDSP: ADR(END-1) |
$80 $A831 END |
perform END $80 |
$80 $A831 END |
end |
|
.:A00E 41 A7 |
ADR(FOR-1) |
$81 $A742 FOR |
perform FOR $81 |
$81 $A742 FOR |
for |
|
.:A010 1D AD |
ADR(NEXT-1) |
$82 $AD1E NEXT |
perform NEXT $82 |
$82 $AD1E NEXT |
next |
|
.:A012 F7 A8 |
ADR(DATA-1) IFN EXTIO,< |
$83 $A8F8 DATA |
perform DATA $83 |
$83 $A8F8 DATA |
data |
|
.:A014 A4 AB |
ADR(INPUTN-1)> |
$84 $ABA5 INPUT# |
perform INPUT# $84 |
$84 $ABA5 INPUT# |
input# |
|
.:A016 BE AB |
ADR(INPUT-1) |
$85 $ABBF INPUT |
perform INPUT $85 |
$85 $ABBF INPUT |
input |
|
.:A018 80 B0 |
ADR(DIM-1) |
$86 $B081 DIM |
perform DIM $86 |
$86 $B081 DIM |
dim |
|
.:A01A 05 AC |
ADR(READ-1) |
$87 $AC06 READ |
perform READ $87 |
$87 $AC06 READ |
read |
|
.:A01C A4 A9 |
ADR(LET-1) |
$88 $A9A5 LET |
perform LET $88 |
$88 $A9A5 LET |
let |
|
.:A01E 9F A8 |
ADR(GOTO-1) |
$89 $A8A0 GOTO |
perform GOTO $89 |
$89 $A8A0 GOTO |
goto |
|
.:A020 70 A8 |
ADR(RUN-1) |
$8A $A871 RUN |
perform RUN $8A |
$8A $A871 RUN |
run |
|
.:A022 27 A9 |
ADR(IF-1) |
$8B $A928 IF |
perform IF $8B |
$8B $A928 IF |
if |
|
.:A024 1C A8 |
ADR(RESTORE-1) |
$8C $A81D RESTORE |
perform RESTORE $8C |
$8C $A81D RESTORE |
restore |
|
.:A026 82 A8 |
ADR(GOSUB-1) |
$8D $A883 GOSUB |
perform GOSUB $8D |
$8D $A883 GOSUB |
gosub |
|
.:A028 D1 A8 |
ADR(RETURN-1) |
$8E $A8D2 RETURN |
perform RETURN $8E |
$8E $A8D2 RETURN |
return |
|
.:A02A 3A A9 |
ADR(REM-1) |
$8F $A93B REM |
perform REM $8F |
$8F $A93B REM |
rem |
|
.:A02C 2E A8 |
ADR(STOP-1) |
$90 $A82F STOP |
perform STOP $90 |
$90 $A82F STOP |
stop |
|
.:A02E 4A A9 |
ADR(ONGOTO-1) IFN NULCMD,< ADR(NULL-1)> |
$91 $A94B ON |
perform ON $91 |
$91 $A94B ON |
on |
|
.:A030 2C B8 |
ADR(FNWAIT-1) IFN DISKO,< IFE REALIO-3,< |
$92 $B82D WAIT |
perform WAIT $92 |
$92 $B82D WAIT |
wait |
|
.:A032 67 E1 |
ADR(CQLOAD-1) |
$93 $E168 LOAD |
perform LOAD $93 |
$93 $E168 LOAD |
load |
|
.:A034 55 E1 |
ADR(CQSAVE-1) |
$94 $E156 SAVE |
perform SAVE $94 |
$94 $E156 SAVE |
save |
|
.:A036 64 E1 |
ADR(CQVERF-1)> IFN REALIO,< IFN REALIO-2,< IFN REALIO-3,< IFN REALIO-5,< ADR(LOAD-1) ADR(SAVE-1)>>>> IFN REALIO-1,< IFN REALIO-3,< IFN REALIO-4,< ADR(511) ;ADDRESS OF LOAD ADR(511)>>>> ;ADDRESS OF SAVE |
$95 $E165 VERIFY |
perform VERIFY $95 |
$95 $E165 VERIFY |
verify |
|
.:A038 B2 B3 |
ADR(DEF-1) |
$96 $B3B3 DEF |
perform DEF $96 |
$96 $B3B3 DEF |
def |
|
.:A03A 23 B8 |
ADR(POKE-1) IFN EXTIO,< |
$97 $B824 POKE |
perform POKE $97 |
$97 $B824 POKE |
poke |
|
.:A03C 7F AA |
ADR(PRINTN-1)> |
$98 $AA80 PRINT# |
perform PRINT# $98 |
$98 $AA80 PRINT# |
print# |
|
.:A03E 9F AA |
ADR(PRINT-1) |
$99 $AAA0 PRINT |
perform PRINT $99 |
$99 $AAA0 PRINT |
print |
|
.:A040 56 A8 |
ADR(CONT-1) IFE REALIO,< ADR(DDT-1)> |
$9A $A857 CONT |
perform CONT $9A |
$9A $A857 CONT |
cont |
|
.:A042 9B A6 |
ADR(LIST-1) |
$9B $A69C LIST |
perform LIST $9B |
$9B $A69C LIST |
list |
|
.:A044 5D A6 |
ADR(CLEAR-1) IFN EXTIO,< |
$9C $A65E CLR |
perform CLR $9C |
$9C $A65E CLR |
clr |
|
.:A046 85 AA |
ADR(CMD-1) |
$9D $AA86 CMD |
perform CMD $9D |
$9D $AA86 CMD |
cmd |
|
.:A048 29 E1 |
ADR(CQSYS-1) |
$9E $E12A SYS |
perform SYS $9E |
$9E $E12A SYS |
sys |
|
.:A04A BD E1 |
ADR(CQOPEN-1) |
$9F $E1BE OPEN |
perform OPEN $9F |
$9F $E1BE OPEN |
open |
|
.:A04C C6 E1 |
ADR(CQCLOS-1)> IFN GETCMD,< |
$A0 $E1C7 CLOSE |
perform CLOSE $A0 |
$A0 $E1C7 CLOSE |
close |
|
.:A04E 7A AB |
ADR(GET-1)> ;FILL W/ GET ADDR. |
$A1 $AB7B GET |
perform GET $A1 |
$A1 $AB7B GET |
get |
|
.:A050 41 A6 |
ADR(SCRATH-1) |
$A2 $A642 NEWAdressen der BASIC-Funktionen |
perform NEW $A2action addresses for functions |
$A2 $A642 NEW |
newaddress table for functions |
|
.:A052 39 BC |
FUNDSP: ADR(SGN) |
$B4 $BC39 SGN |
perform SGN $B4 |
$B4 $BC39 SGN |
sgn |
|
.:A054 CC BC |
ADR(INT) |
$B5 $BCCC INT |
perform INT $B5 |
$B5 $BCCC INT |
int |
|
.:A056 58 BC |
ADR(ABS) IFE ROMSW,< USRLOC: ADR(FCERR)> ;INITIALLY NO USER ROUTINE. IFN ROMSW,< |
$B6 $BC58 ABS |
perform ABS $B6 |
$B6 $BC58 ABS |
abs |
|
.:A058 10 03 |
USRLOC: ADR(USRPOK)> |
$B7 $0310 USR |
perform USR $B7 |
$B7 $0310 USR |
usr |
|
.:A05A 7D B3 |
ADR(FRE) |
$B8 $B37D FRE |
perform FRE $B8 |
$B8 $B37D FRE |
fre |
|
.:A05C 9E B3 |
ADR(POS) |
$B9 $B39E POS |
perform POS $B9 |
$B9 $B39E POS |
pos |
|
.:A05E 71 BF |
ADR(SQR) |
$BA $BF71 SQR |
perform SQR $BA |
$BA $BF71 SQR |
sqr |
|
.:A060 97 E0 |
ADR(RND) |
$BB $E097 RND |
perform RND $BB |
$BB $E097 RND |
rnd |
|
.:A062 EA B9 |
ADR(LOG) |
$BC $B9EA LOG |
perform LOG $BC |
$BC $B9EA LOG |
log |
|
.:A064 ED BF |
ADR(EXP) IFN KIMROM,< REPEAT 4,< ADR(FCERR)>> IFE KIMROM,< |
$BD $BFED EXP |
perform EXP $BD |
$BD $BFED EXP |
exp |
|
.:A066 64 E2 |
COSFIX: ADR(COS) |
$BE $E264 COS |
perform COS $BE |
$BE $E264 COS |
cos |
|
.:A068 6B E2 |
SINFIX: ADR(SIN) |
$BF $E26B SIN |
perform SIN $BF |
$BF $E26B SIN |
sin |
|
.:A06A B4 E2 |
TANFIX: ADR(TAN) |
$C0 $E2B4 TAN |
perform TAN $C0 |
$C0 $E2B4 TAN |
tan |
|
.:A06C 0E E3 |
ATNFIX: ADR(ATN)> |
$C1 $E30E ATN |
perform ATN $C1 |
$C1 $E30E ATN |
atn |
|
.:A06E 0D B8 |
ADR(PEEK) |
$C2 $B80D PEEK |
perform PEEK $C2 |
$C2 $B80D PEEK |
peek |
|
.:A070 7C B7 |
ADR(LEN) |
$C3 $B77C LEN |
perform LEN $C3 |
$C3 $B77C LEN |
len |
|
.:A072 65 B4 |
ADR(STR) |
$C4 $B465 STR$ |
perform STR$ $C4 |
$C4 $B465 STR$ |
str$ |
|
.:A074 AD B7 |
ADR(VAL) |
$C5 $B7AD VAL |
perform VAL $C5 |
$C5 $B7AD VAL |
val |
|
.:A076 8B B7 |
ADR(ASC) |
$C6 $B78B ASC |
perform ASC $C6 |
$C6 $B78B ASC |
asc |
|
.:A078 EC B6 |
ADR(CHR) |
$C7 $B6EC CHR$ |
perform CHR$ $C7 |
$C7 $B6EC CHR$ |
chr$ |
|
.:A07A 00 B7 |
ADR(LEFT) |
$C8 $B700 LEFT$ |
perform LEFT$ $C8 |
$C8 $B700 LEFT$ |
left$ |
|
.:A07C 2C B7 |
ADR(RIGHT) |
$C9 $B72C RIGHT$ |
perform RIGHT$ $C9 |
$C9 $B72C RIGHT$ |
right$ |
|
.:A07E 37 B7 |
ADR(MID) |
$CA $B737 MID$Hierarchiecodes undAdressen-1 der Operatoren |
perform MID$ $CAprecedence byte and action addresses for operatorslike the primary commands these are called by pushing the address onto the stackand doing an RTS, so again the actual address -1 needs to be pushed |
$CA $B737 MID$MATH OPERATOR BRANCH TABLEONE-BYTE PRECEDENCE CODETWO-BYTE ADDRESS |
mid$priority and address table for operators(address minus 1 used) |
|
.:A080 79 69 B8 |
OPTAB: 121 |
$79, $B86A Addition |
+ |
$79, $B86A + |
plus |
|
.:A083 79 52 B8 |
ADR(FADDT-1) 121 |
$79, $B853 Subtraktion |
- |
$79, $B853 - |
minus |
|
.:A086 7B 2A BA |
ADR(FSUBT-1) 123 |
$7B, $BA2B Multiplikation |
* |
$7B, $BA2B * |
multiply |
|
.:A089 7B 11 BB |
ADR(FMULTT-1) 123 |
$7B, $BB12 Division |
/ |
$7B, $BB12 / |
divide |
|
.:A08C 7F 7A BF |
ADR(FDIVT-1) 127 |
$7F, $BF7B Potenzierung |
^ |
$7F, $BF7B ^ |
power |
|
.:A08F 50 E8 AF |
ADR(FPWRT-1) 80 |
$50, $AFE9 AND |
AND |
$50, $AFE9 AND |
AND |
|
.:A092 46 E5 AF |
ADR(ANDOP-1) 70 |
$46, $AFE6 OR |
OR |
$46, $AFE6 OR (LOWEST PRECEDENCE) |
OR |
|
.:A095 7D B3 BF |
ADR(OROP-1) NEGTAB: 125 |
$7D, $BFB4 Vorzeichenwechsel |
> |
$7D, $BFB4 > |
negative |
|
.:A098 5A D3 AE |
ADR(NEGOP-1) NOTTAB: 90 |
$5A, $AED4 NOT |
= |
$5A, $AED4 = |
NOT |
|
.:A09B 64 15 B0 |
ADR(NOTOP-1) PTDORL: 100 ;PRECEDENCE. |
$64, $B016 VergleichBASIC-Befehlsworte |
<BASIC keywordseach word has b7 set in it's last character as an end marker, eventhe one character keywords such as "<" or "=" first are the primary command keywords, only these can start a statement |
$64, $B016 <TOKEN NAME TABLE |
greater / equal / lesstable of commandseach ended with a +$80 |
|
.:A09E 45 4E |
ADR (DOREL-1) ;OPERATOR ADDRESS. ; ; TOKENS FOR RESERVED WORDS ALWAYS HAVE THE MOST ; SIGNIFICANT BIT ON. ; THE LIST OF RESERVED WORDS: ; Q=128-1 DEFINE DCI(A),<Q=Q+1 DC(A)> RESLST: DCI"END" |
end |
end |
end |
end |
|
.:A0A0 C4 46 4F D2 4E 45 58 D4 |
ENDTK==Q |
for next |
for next |
for next |
||
.:A0A8 44 41 54 C1 49 4E 50 55 |
DCI"FOR" |
data input# |
data input# |
data input# |
for next data |
|
.:A0B0 54 A3 49 4E 50 55 D4 44 |
FORTK==Q |
input dim |
input dim |
input dim |
input# |
|
.:A0B8 49 CD 52 45 41 C4 4C 45 |
DCI"NEXT" |
read let |
read let |
read let |
input dim |
|
.:A0C0 D4 47 4F 54 CF 52 55 CE |
DCI"DATA" |
goto run |
goto run |
goto run |
read let |
|
.:A0C8 49 C6 52 45 53 54 4F 52 |
DATATK==Q |
if restore |
if restore |
if restore |
goto run if |
|
.:A0D0 C5 47 4F 53 55 C2 52 45 |
IFN EXTIO,< |
gosub return |
gosub return |
gosub return |
restore |
|
.:A0D8 54 55 52 CE 52 45 CD 53 |
DCI"INPUT#"> |
rem stop |
rem stop |
rem stop |
gosub return |
|
.:A0E0 54 4F D0 4F CE 57 41 49 |
DCI"INPUT" |
on wait |
on wait |
on wait |
rem stop |
|
.:A0E8 D4 4C 4F 41 C4 53 41 56 |
DCI"DIM" |
load save |
load save |
load save |
on wait |
|
.:A0F0 C5 56 45 52 49 46 D9 44 |
DCI"READ" |
verify def |
verify def |
verify def |
load save |
|
.:A0F8 45 C6 50 4F 4B C5 50 52 |
DCI"LET" |
poke print# |
poke print# |
poke print# |
verify def |
|
.:A100 49 4E 54 A3 50 52 49 4E |
DCI"GOTO" |
print |
print |
print |
poke print# |
|
.:A108 D4 43 4F 4E D4 4C 49 53 |
GOTOTK==Q |
cont list |
cont list |
cont list |
print |
|
.:A110 D4 43 4C D2 43 4D C4 53 |
DCI"RUN" |
clr cmd sys |
clr cmd sys |
clr cmd sys |
cont list |
|
.:A118 59 D3 4F 50 45 CE 43 4C |
DCI"IF" |
open close |
open close |
open close |
clr cmd sys |
|
.:A120 4F 53 C5 47 45 D4 4E 45 |
DCI"RESTORE" |
get new |
get new next are the secondary command keywords, these can not start a statement |
get new |
open close |
|
.:A128 D7 54 41 42 A8 54 CF 46 |
DCI"GOSUB" |
tab( to |
tab( to |
tab( to |
get new table of functionseach ended with a +$80 |
|
.:A130 CE 53 50 43 A8 54 48 45 |
GOSUTK=Q |
spc( then |
spc( then |
spc( then |
tab( to fn |
|
.:A138 CE 4E 4F D4 53 54 45 D0 |
DCI"RETURN" |
not step |
not step next are the operators |
not step |
spc( then |
|
.:A140 AB AD AA AF DE 41 4E C4 |
DCI"REM" |
+ - * / ' and |
+ - * / ' and |
+ - * / ' and |
not step plus |
|
.:A148 4F D2 BE BD BC 53 47 CE |
REMTK=Q |
or <=> sgn |
or <=> |
or <=> |
minus multiply divide power and on |
|
.:A150 49 4E D4 41 42 D3 55 53 |
DCI"STOP" |
int abs usr |
sgn and finally the functions int abs usr |
sgn int abs usr |
greater equal less sgn int |
|
.:A158 D2 46 52 C5 50 4F D3 53 |
DCI"ON" |
fre pos sqr |
fre pos sqr |
fre pos sqr |
abs usr |
|
.:A160 51 D2 52 4E C4 4C 4F C7 |
IFN NULCMD,< |
rnd log |
rnd log |
rnd log |
fre pos sqr |
|
.:A168 45 58 D0 43 4F D3 53 49 |
DCI"NULL"> |
exp cos sin |
exp cos sin |
exp cos sin |
rnd log exp |
|
.:A170 CE 54 41 CE 41 54 CE 50 |
DCI"WAIT" |
tan atn peek |
tan atn peek |
tan atn peek |
cos sin |
|
.:A178 45 45 CB 4C 45 CE 53 54 |
IFN DISKO,< |
len str$ |
len str$ |
len str$ |
tan atn peek |
|
.:A180 52 A4 56 41 CC 41 53 C3 |
DCI"LOAD" |
val asc |
val asc |
val asc |
len str$ |
|
.:A188 43 48 52 A4 4C 45 46 54 |
DCI"SAVE" |
chr$ left$ |
chr$ left$ |
chr$ left$ |
val asc chr$ |
|
.:A190 A4 52 49 47 48 54 A4 4D |
IFE REALIO-3,< |
right$ mid$ |
right$ mid$ lastly is GO, this is an add on so that GO TO, as well as GOTO, will work |
right$ mid$ |
left$ |
|
.:A198 49 44 A4 47 CF 00 |
DCI"VERIFY">> |
goBASIC-Fehlermeldungen |
go |
go |
right$ mid$ other commands |
|
.:A1A0 54 4F |
DCI"DEF" DCI"POKE" IFN EXTIO,< DCI"PRINT#"> DCI"PRINT" PRINTK==Q DCI"CONT" IFE REALIO,< DCI"DDT"> DCI"LIST" IFN REALIO-3,< DCI"CLEAR"> IFE REALIO-3,< DCI"CLR"> IFN EXTIO,< DCI"CMD" DCI"SYS" DCI"OPEN" DCI"CLOSE"> IFN GETCMD,< DCI"GET"> DCI"NEW" SCRATK=Q ; END OF COMMAND LIST. "T" "A" "B" "("+128 Q=Q+1 TABTK=Q DCI"TO" TOTK==Q DCI"FN" FNTK==Q "S" "P" "C" "("+128 ;MACRO DOESNT LIKE ('S IN ARGUMENTS. Q=Q+1 SPCTK==Q DCI"THEN" THENTK=Q DCI"NOT" NOTTK==Q DCI"STEP" STEPTK=Q DCI"+" PLUSTK=Q DCI"-" MINUTK=Q DCI"*" DCI"/" DCI"^" DCI"AND" DCI"OR" 190 ;A GREATER THAN SIGN Q=Q+1 GREATK=Q DCI"=" EQULTK=Q 188 Q=Q+1 ;A LESS THAN SIGN LESSTK=Q ; ; NOTE DANGER OF ONE RESERVED WORD BEING A PART ; OF ANOTHER: ; IE . . IF 2 GREATER THAN F OR T=5 THEN... ; WILL NOT WORK!!! SINCE "FOR" WILL BE CRUNCHED!! ; IN ANY CASE MAKE SURE THE SMALLER WORD APPEARS ; SECOND IN THE RESERVED WORD TABLE ("INP" AND "INPUT") ; ANOTHER EXAMPLE: IF T OR Q THEN ... "TO" IS CRUNCHED ; DCI"SGN" ONEFUN=Q DCI"INT" DCI"ABS" DCI"USR" DCI"FRE" DCI"POS" DCI"SQR" DCI"RND" DCI"LOG" DCI"EXP" DCI"COS" DCI"SIN" DCI"TAN" DCI"ATN" DCI"PEEK" DCI"LEN" DCI"STR$" DCI"VAL" DCI"ASC" DCI"CHR$" LASNUM==Q ;NUMBER OF LAST FUNCTION ;THAT TAKES ONE ARG DCI"LEFT$" DCI"RIGHT$" DCI"MID$" DCI"GO" GOTK==Q 0 ;MARKS END OF RESERVED WORD LIST IFE LNGERR,< Q=0-2 DEFINE DCE(X),<Q=Q+2 DC(X)> ERRTAB: DCE"NF" ERRNF==Q ;NEXT WITHOUT FOR. DCE"SN" ERRSN==Q ;SYNTAX DCE"RG" ERRRG==Q ;RETURN WITHOUT GOSUB. DCE"OD" ERROD==Q ;OUT OF DATA. DCE"FC" ERRFC==Q ;ILLEGAL QUANTITY. DCE"OV" ERROV==Q ;OVERFLOW. DCE"OM" ERROM==Q ;OUT OF MEMORY. DCE"US" ERRUS==Q ;UNDEFINED STATEMENT. DCE"BS" ERRBS==Q ;BAD SUBSCRIPT. DCE"DD" ERRDD==Q ;REDIMENSIONED ARRAY. DCE"/0" ERRDV0==Q ;DIVISION BY ZERO. DCE"ID" ERRID==Q ;ILLEGAL DIRECT. DCE"TM" ERRTM==Q ;TYPE MISMATCH. DCE"LS" ERRLS==Q ;STRING TOO LONG. IFN EXTIO,< DCE"FD" ;FILE DATA. ERRBD==Q> DCE"ST" ERRST==Q ;STRING FORMULA TOO COMPLEX. DCE"CN" ERRCN==Q ;CAN'T CONTINUE. DCE"UF" ERRUF==Q> ;UNDEFINED FUNCTION. IFN LNGERR,< Q=0 ; NOTE: THIS ERROR COUNT TECHNIQUE WILL NOT WORK IF THERE ARE MORE ; THAN 256 CHARACTERS OF ERROR MESSAGES ERRTAB: DC"NEXT WITHOUT FOR" |
1 too many files |
end markerBASIC error messages1 too many files |
END OF TOKEN NAME TABLEERROR MESSAGES1 too many files |
table of error messageseach ended with a +$80too many files |
|
.:A1A0 4F 20 4D 41 4E 59 20 46 | ||||||
.:A1A8 49 4C 45 D3 46 49 4C 45 |
ERRNF==Q |
2 file open |
2 file open |
2 file open |
||
.:A1B0 20 4F 50 45 CE 46 49 4C |
Q=Q+16 |
3 file not open |
3 file not open |
3 file not open |
file open |
|
.:A1B8 45 20 4E 4F 54 20 4F 50 |
DC"SYNTAX" |
file not open |
||||
.:A1C0 45 CE 46 49 4C 45 20 4E |
ERRSN==Q |
4 file not found |
4 file not found |
4 file not found |
||
.:A1C8 4F 54 20 46 4F 55 4E C4 |
Q=Q+6 |
5 device not present |
5 device not present |
5 device not present |
file not found |
|
.:A1D0 44 45 56 49 43 45 20 4E |
DC"RETURN WITHOUT GOSUB" |
device not present |
||||
.:A1D8 4F 54 20 50 52 45 53 45 |
ERRRG==Q |
|||||
.:A1E0 4E D4 4E 4F 54 20 49 4E |
Q=Q+20 |
6 not input file |
6 not input file |
6 not input file |
||
.:A1E8 50 55 54 20 46 49 4C C5 |
DC"OUT OF DATA" |
not input file |
||||
.:A1F0 4E 4F 54 20 4F 55 54 50 |
ERROD==Q |
7 not output file |
7 not output file |
7 not output file |
not output file |
|
.:A1F8 55 54 20 46 49 4C C5 4D |
Q=Q+11 |
|||||
.:A200 49 53 53 49 4E 47 20 46 |
DC"ILLEGAL QUANTITY" |
8 missing filename |
8 missing filename |
8 missing filename |
missing file name |
|
.:A208 49 4C 45 20 4E 41 4D C5 |
ERRFC==Q |
|||||
.:A210 49 4C 4C 45 47 41 4C 20 |
Q=Q+16 |
9 illegal device number |
9 illegal device number |
9 illegal device number |
illegal device number |
|
.:A218 44 45 56 49 43 45 20 4E |
DC"OVERFLOW" |
|||||
.:A220 55 4D 42 45 D2 4E 45 58 |
ERROV==Q |
10 next without for |
10 next without for |
10 next without for |
||
.:A228 54 20 57 49 54 48 4F 55 |
Q=Q+8 |
next without for |
||||
.:A230 54 20 46 4F D2 53 59 4E |
DC"OUT OF MEMORY" |
11 syntax |
11 syntax |
11 syntax |
||
.:A238 54 41 D8 52 45 54 55 52 |
ERROM==Q |
12 return without gosub |
12 return without gosub |
12 return without gosub |
syntax |
|
.:A240 4E 20 57 49 54 48 4F 55 |
Q=Q+13 |
return without gosub |
||||
.:A248 54 20 47 4F 53 55 C2 4F |
DC"UNDEF'D STATEMENT" |
13 out of data |
13 out of data |
13 out of data |
||
.:A250 55 54 20 4F 46 20 44 41 |
ERRUS==Q |
out of data |
||||
.:A258 54 C1 49 4C 4C 45 47 41 |
Q=Q+17 |
14 illegal quantity |
14 illegal quantity |
14 illegal quantity |
||
.:A260 4C 20 51 55 41 4E 54 49 |
DC"BAD SUBSCRIPT" |
illegal quantity |
||||
.:A268 54 D9 4F 56 45 52 46 4C |
ERRBS==Q |
15 overflow |
15 overflow |
15 overflow |
||
.:A270 4F D7 4F 55 54 20 4F 46 |
Q=Q+13 |
16 out of memory |
16 out of memory |
16 out of memory |
overflow |
|
.:A278 20 4D 45 4D 4F 52 D9 55 |
DC"REDIM'D ARRAY" |
17 undef'd statement |
17 undef'd statement |
17 undef'd statement |
out of memory |
|
.:A280 4E 44 45 46 27 44 20 53 |
ERRDD==Q |
undef'd statement |
||||
.:A288 54 41 54 45 4D 45 4E D4 |
Q=Q+13 |
|||||
.:A290 42 41 44 20 53 55 42 53 |
DC"DIVISION BY ZERO" |
18 bad subscript |
18 bad subscript |
18 bad subscript |
bad subscript |
|
.:A298 43 52 49 50 D4 52 45 44 |
ERRDV0==Q |
19 redim'd array |
19 redim'd array |
19 redim'd array |
||
.:A2A0 49 4D 27 44 20 41 52 52 |
Q=Q+16 |
redim'd array |
||||
.:A2A8 41 D9 44 49 56 49 53 49 |
DC"ILLEGAL DIRECT" |
20 division by zero |
20 division by zero |
20 division by zero |
||
.:A2B0 4F 4E 20 42 59 20 5A 45 |
ERRID==Q |
division by zero |
||||
.:A2B8 52 CF 49 4C 4C 45 47 41 |
Q=Q+14 |
21 illegal direct |
21 illegal direct |
21 illegal direct |
||
.:A2C0 4C 20 44 49 52 45 43 D4 |
DC"TYPE MISMATCH" |
illegal direct |
||||
.:A2C8 54 59 50 45 20 4D 49 53 |
ERRTM==Q |
22 type mismatch |
22 type mismatch |
22 type mismatch |
type mismatch |
|
.:A2D0 4D 41 54 43 C8 53 54 52 |
Q=Q+13 |
23 string too long |
23 string too long |
23 string too long |
||
.:A2D8 49 4E 47 20 54 4F 4F 20 |
DC"STRING TOO LONG" |
string to long |
||||
.:A2E0 4C 4F 4E C7 46 49 4C 45 |
ERRLS==Q |
24 file data |
24 file data |
24 file data |
||
.:A2E8 20 44 41 54 C1 46 4F 52 |
Q=Q+15 |
25 formula too complex |
25 formula too complex |
25 formula too complex |
file data |
|
.:A2F0 4D 55 4C 41 20 54 4F 4F |
IFN EXTIO,< |
formula too complex |
||||
.:A2F8 20 43 4F 4D 50 4C 45 D8 |
DC"FILE DATA" |
|||||
.:A300 43 41 4E 27 54 20 43 4F |
ERRBD==Q |
26 can't continue |
26 can't continue |
26 can't continue |
can't continue |
|
.:A308 4E 54 49 4E 55 C5 55 4E |
Q=Q+9> |
27 undef'd function |
27 undef'd function |
27 undef'd function |
||
.:A310 44 45 46 27 44 20 46 55 |
DC"FORMULA TOO COMPLEX" |
undef'd function |
||||
.:A318 4E 43 54 49 4F CE 56 45 |
ERRST==Q |
28 verify |
28 verify |
28 verify |
||
.:A320 52 49 46 D9 4C 4F 41 C4 |
Q=Q+19 DC"CAN'T CONTINUE" ERRCN==Q Q=Q+14 DC"UNDEF'D FUNCTION" ERRUF==Q> |
29 loadAdressen der Fehlermeldungen |
29 loaderror message pointer table |
29 load |
verify |
|
.:A328 9E A1 AC A1 B5 A1 C2 A1 |
loaderror message address locations01 too many files |
|||||
.:A330 D0 A1 E2 A1 F0 A1 FF A1 |
02 file open 03 file not open 04 file not found 05 device not present |
|||||
.:A338 10 A2 25 A2 35 A2 3B A2 |
06 not input file 07 not output file 08 missing file name 09 illegal device number |
|||||
.:A340 4F A2 5A A2 6A A2 72 A2 |
0A next without for 0B syntax 0C return without gosub 0D out of data |
|||||
.:A348 7F A2 90 A2 9D A2 AA A2 |
0E illegal quantity 0F overflow 10 out of memory 11 undef'd statment |
|||||
.:A350 BA A2 C8 A2 D5 A2 E4 A2 |
12 bad subscript 13 redim'd array 14 devision by zero 15 illegal direct |
|||||
.:A358 ED A2 00 A3 0E A3 1E A3 |
16 type mismatch 17 string too long 18 file data 19 formula too complex |
|||||
.:A360 24 A3 83 A3 |
; ; NEEDED FOR MESSAGES IN ALL VERSIONS. ; |
Meldungen des Interpreters |
BASIC messages |
1A can't continue 1B undef'd function 1C verify 1D load |
||
.:A364 0D 4F 4B 0D |
ERR: DT" ERROR" |
OK |
OK |
OK |
1E breakother messagesok |
|
.:A368 00 20 20 45 52 52 4F 52 |
0 |
ERROR |
ERROR |
ERROR |
||
.:A370 00 20 49 4E 20 00 0D 0A |
INTXT: DT" IN " |
IN |
IN |
IN |
error |
|
.:A378 52 45 41 44 59 2E 0D 0A |
0 |
READY. |
READY. |
READY. |
in ready. |
|
.:A380 00 0D 0A 42 52 45 41 4B |
REDDY: ACRLF |
BREAK |
BREAK |
BREAK |
||
.:A388 00 A0 |
IFE REALIO-3,< DT"READY."> IFN REALIO-3,< DT"OK"> ACRLF 0 BRKTXT: ACRLF DT"BREAK" 0 PAGE GENERAL STORAGE MANAGEMENT ROUTINES.;; FIND A "FOR" ENTRY ON THE STACK VIA "VARPNT". ; FORSIZ==2*ADDPRC+16 |
Stapelsuch-Routine fürFOR-NEXT- und GOSUB-Befehl |
spare byte, not referenced |
break |
||
.,A38A BA TSX |
FNDFOR: TSX ;LOAD XREG WITH STK PNTR. |
Stapelzeiger in X-Register |
unusedsearch the stack for FOR or GOSUB activityreturn Zb=1 if FOR variable foundcopy stack pointer |
CALLED BY "NEXT" AND "FOR" TO SCAN THROUGHTHE STACK FOR A FRAME WITH THE SAME VARIABLE.(FORPNT) = ADDRESS OF VARIABLE IF "FOR" OR "NEXT"= $XXFF IF CALLED FROM "RETURN" <<< BUG: SHOULD BE $FFXX >>> RETURNS .NE. IF VARIABLE NOT FOUND, (X) = STACK PNTR AFTER SKIPPING ALL FRAMES .EQ. IF FOUND (X) = STACK PNTR OF FRAME FOUND |
search for "for" blocks on stack |
|
.,A38B E8 INX |
REPEAT 4,<INX> ;IGNORE ADR(NEWSTT) AND RTS ADDR. |
4 mal erhöhen |
+1 pass return address |
|||
.,A38C E8 INX |
(nächsten zwei Rücksprung- |
+2 pass return address |
||||
.,A38D E8 INX |
adressen, Interpreter und |
+3 pass calling routine return address |
||||
.,A38E E8 INX |
Routine, übergehen) |
+4 pass calling routine return address |
||||
.,A38F BD 01 01 LDA $0101,X |
FFLOOP: LDA 257,X ;GET STACK ENTRY. |
nächstes Byte hoten |
get the token byte from the stack |
"FOR" FRAME HERE? |
||
.,A392 C9 81 CMP #$81 |
CMPI FORTK ;IS IT A "FOR" TOKEN? |
Ist es FOR-Code ? |
is it the FOR token |
for block code |
||
.,A394 D0 21 BNE $A3B7 |
BNE FFRTS ;NO, NO "FOR" LOOPS WITH THIS PNTR. |
Nein: dann RTS |
if not FOR token just exit it was the FOR token |
NO |
||
.,A396 A5 4A LDA $4A |
LDA FORPNT+1 ;GET HIGH. |
Variablenzeiger holen |
get FOR/NEXT variable pointer high byte |
YES -- "NEXT" WITH NO VARIABLE? |
||
.,A398 D0 0A BNE $A3A4 |
BNE CMPFOR |
keine Variable (NEXT):$A3A4 |
branch if not null |
NO, VARIABLE SPECIFIED |
||
.,A39A BD 02 01 LDA $0102,X |
LDA 258,X ;PNTR IS ZERO, SO ASSUME THIS ONE. |
Variablenzeiger aus |
get FOR variable pointer low byte |
YES, SO USE THIS FRAME |
||
.,A39D 85 49 STA $49 |
STA FORPNT |
Stapel nach $49/4A |
save FOR/NEXT variable pointer low byte |
|||
.,A39F BD 03 01 LDA $0103,X |
LDA 259,X |
(Variablenzeiger) |
get FOR variable pointer high byte |
|||
.,A3A2 85 4A STA $4A |
STA FORPNT+1 |
holen |
save FOR/NEXT variable pointer high byte |
|||
.,A3A4 DD 03 01 CMP $0103,X |
CMPFOR: CMP 259,X |
Mit Zeiger im Stapel vergl. |
compare variable pointer with stacked variable pointer high byte |
IS VARIABLE IN THIS FRAME? |
||
.,A3A7 D0 07 BNE $A3B0 |
BNE ADDFRS ;NOT THIS ONE. |
Ungleich: nächste Schleife |
branch if no match |
NO |
||
.,A3A9 A5 49 LDA $49 |
LDA FORPNT ;GET DOWN. |
Zeiger wieder holen |
get FOR/NEXT variable pointer low byte |
LOOK AT 2ND BYTE TOO |
||
.,A3AB DD 02 01 CMP $0102,X |
CMP 258,X |
Mit Zeiger im Stapel vergl. |
compare variable pointer with stacked variable pointer low byte |
SAME VARIABLE? |
||
.,A3AE F0 07 BEQ $A3B7 |
BEQ FFRTS ;WE GOT IT! WE GOT IT! |
Gleich: Schleife gefunden,RTS |
exit if match found |
YES |
||
.,A3B0 8A TXA |
ADDFRS: TXA |
Suchzeiger in Akku |
copy index |
NO, SO TRY NEXT FRAME (IF ANY) |
||
.,A3B1 18 CLC |
CLC ;ADD 16 TO X. |
Carry für Addition löschen |
clear carry for add |
18 BYTES PER FRAME |
||
.,A3B2 69 12 ADC #$12 |
ADCI FORSIZ |
Suchzeiger um 18 erhöhen |
add FOR stack use size |
|||
.,A3B4 AA TAX |
TAX ;RESULT BACK INTO X. |
und wieder zurück ins X-Rg. |
copy back to index |
|||
.,A3B5 D0 D8 BNE $A38F |
BNE FFLOOP |
nächste Schleife prüfen |
loop if not at start of stack |
...ALWAYS? |
||
.,A3B7 60 RTS |
FFRTS: RTS ;RETURN TO CALLER. ; ; THIS IS THE BLOCK TRANSFER ROUTINE. ; IT MAKES SPACE BY SHOVING EVERYTHING FORWARD. ; ; ON ENTRY: ; [Y,A]=[HIGHDS] (FOR REASON). ; [HIGHDS]= DESTINATION OF [HIGH ADDRESS]. ; [LOWTR]= LOWEST ADDR TO BE TRANSFERRED. ; [HIGHTR]= HIGHEST ADDR TO BE TRANSFERRED. ; ; A CHECK IS MADE TO ASCERTAIN THAT A REASONABLE ; AMOUNT OF SPACE REMAINS BETWEEN THE BOTTOM ; OF THE STRINGS AND THE HIGHEST LOCATION TRANSFERRED INTO. ; ; ON EXIT: ; [LOWTR] ARE UNCHANGED. ; [HIGHTR]=[LOWTR]-200 OCTAL. ; [HIGHDS]=LOWEST ADDR TRANSFERRED INTO MINUS 200 OCTAL. ; |
RücksprungBlock-Verschiebe-Routine |
open up a space in the memory, set the end of arrays |
MOVE BLOCK OF MEMORY UPON ENTRY:(Y,A) = (HIGHDS) = DESTINATION END+1 (LOWTR) = LOWEST ADDRESS OF SOURCE (HIGHTR) = HIGHEST SOURCE ADDRESS+1 |
move bytes after check for space |
|
.,A3B8 20 08 A4 JSR $A408 |
BLTU: JSR REASON ;ASCERTAIN THAT STRING SPACE WON'T ;BE OVERRUN. |
prüft auf Platz im Speicher |
check available memory, do out of memory error if no room |
BE SURE (Y,A) < FRETOP |
||
.,A3BB 85 31 STA $31 |
STWD STREND |
Ende des Arraybereichs |
set end of arrays low byte |
NEW TOP OF ARRAY STORAGE |
||
.,A3BD 84 32 STY $32 |
als Beginn für freien Platz |
set end of arrays high byte open up a space in the memory, don't set the array end |
move bytes routine$5F/$60 source start address$5A/$5B source end address $58/$59 destination end address |
|||
.,A3BF 38 SEC |
BLTUC: SEC ;PREPARE TO SUBTRACT. |
Carry setzen (Subtraktion) |
set carry for subtract |
|||
.,A3C0 A5 5A LDA $5A |
LDA HIGHTR |
Startadresse von Endad. des |
get block end low byte |
COMPUTE # OF BYTES TO BE MOVED |
||
.,A3C2 E5 5F SBC $5F |
SBC LOWTR ;COMPUTE NUMBER OF THINGS TO MOVE. |
Bereichs abziehen (LOW) |
subtract block start low byte |
(FROM LOWTR THRU HIGHTR-1) |
||
.,A3C4 85 22 STA $22 |
STA INDEX ;SAVE FOR LATER. |
Ergebnis (=Länge) speichern |
save MOD(block length/$100) byte |
PARTIAL PAGE AMOUNT |
||
.,A3C6 A8 TAY |
TAY |
Gleiches System für HIGH: |
copy MOD(block length/$100) byte to Y |
|||
.,A3C7 A5 5B LDA $5B |
LDA HIGHTR+1 |
Altes Blockende (HIGH) und |
get block end high byte |
|||
.,A3C9 E5 60 SBC $60 |
SBC LOWTR+1 |
davon alter Blockanfang sub |
subtract block start high byte |
|||
.,A3CB AA TAX |
TAX ;PUT IT IN A COUNTER REGISTER. |
Länge nach X bringen |
copy block length high byte to X |
# OF WHOLE PAGES IN X-REG |
||
.,A3CC E8 INX |
INX ;SO THAT COUNTER ALGORITHM WORKS. |
Ist ein Rest ( Länge nicht |
+1 to allow for count=0 exit |
|||
.,A3CD 98 TYA |
TYA ;SEE IF LOW PART OF COUNT IS ZERO. |
256 Bytes)? |
copy block length low byte to A |
# BYTES IN PARTIAL PAGE |
||
.,A3CE F0 23 BEQ $A3F3 |
BEQ DECBLT ;YES, GO START MOVING BLOCKS. |
Nein: dann nur ganze Blöcke |
branch if length low byte=0 block is (X-1)*256+Y bytes, do the Y bytes first |
NO PARTIAL PAGE |
||
.,A3D0 A5 5A LDA $5A |
LDA HIGHTR ;NO, MUST MODIFY BASE ADDR. |
Alte Endadresse (LOW) und |
get block end low byte |
BACK UP HIGHTR # BYTES IN PARTIAL PAGE |
||
.,A3D2 38 SEC |
SEC |
davon Länge des Restab- |
set carry for subtract |
|||
.,A3D3 E5 22 SBC $22 |
SBC INDEX ;BORROW IS OFF SINCE [HIGHTR].GT.[LOWTR]. |
schnitts subtrahieren ergibt Adresse des |
subtract MOD(block length/$100) byte |
|||
.,A3D5 85 5A STA $5A |
STA HIGHTR ;SAVE MODIFIED BASE ADDR. |
Restabschnitts |
save corrected old block end low byte |
|||
.,A3D7 B0 03 BCS $A3DC |
BCS BLT1 ;IF NO BORROW, GO SHOVE IT. |
Berechnung für HIGH umgehen |
branch if no underflow |
|||
.,A3D9 C6 5B DEC $5B |
DEC HIGHTR+1 ;BORROW IMPLIES SUB 1 FROM HIGH ORDER. |
Dasselbe System für HIGH |
else decrement block end high byte |
|||
.,A3DB 38 SEC |
SEC |
Carry setzen (Subtraktion) |
set carry for subtract |
|||
.,A3DC A5 58 LDA $58 |
BLT1: LDA HIGHDS ;MOD BASE OF DEST ADDR. |
Alte Endadresse (HIGH) und |
get destination end low byte |
BACK UP HIGHDS # BYTES IN PARTIAL PAGE |
||
.,A3DE E5 22 SBC $22 |
SBC INDEX |
davon Länge des Rests sub- |
subtract MOD(block length/$100) byte |
|||
.,A3E0 85 58 STA $58 |
STA HIGHDS |
trahieren ergibt neue Adresse |
save modified new block end low byte |
|||
.,A3E2 B0 08 BCS $A3EC |
BCS MOREN1 ;NO BORROW. |
Unbedingter Sprung zur |
branch if no underflow |
|||
.,A3E4 C6 59 DEC $59 |
DEC HIGHDS+1 ;DECREMENT HIGH ORDER BYTE. |
Kopierroutine für ganze |
else decrement block end high byte |
|||
.,A3E6 90 04 BCC $A3EC |
BCC MOREN1 ;ALWAYS SKIP. |
Blöcke |
branch always |
...ALWAYS |
||
.,A3E8 B1 5A LDA ($5A),Y |
BLTLP: LDADY HIGHTR ;FETCH BYTE TO MOVE |
Kopierroutine für Rest- |
get byte from source |
MOVE THE BYTES |
||
.,A3EA 91 58 STA ($58),Y |
STADY HIGHDS ;MOVE IT IN, MOVE IT OUT. |
abschnitt |
copy byte to destination |
|||
.,A3EC 88 DEY |
MOREN1: DEY |
Zähler vermindern |
decrement index |
|||
.,A3ED D0 F9 BNE $A3E8 |
BNE BLTLP |
Alles? wenn nicht: weiter |
loop until Y=0 now do Y=0 indexed byte |
LOOP TO END OF THIS 256 BYTES |
||
.,A3EF B1 5A LDA ($5A),Y |
LDADY HIGHTR ;MOVE LAST OF THE BLOCK. |
Kopierroutine für ganze |
get byte from source |
MOVE ONE MORE BYTE |
||
.,A3F1 91 58 STA ($58),Y |
STADY HIGHDS |
Blöcke |
save byte to destination |
|||
.,A3F3 C6 5B DEC $5B |
DECBLT: DEC HIGHTR+1 |
Adresszähler vermindern |
decrement source pointer high byte |
DOWN TO NEXT BLOCK OF 256 |
||
.,A3F5 C6 59 DEC $59 |
DEC HIGHDS+1 ;START ON NEW BLOCKS. |
Adresszähler vermindern |
decrement destination pointer high byte |
|||
.,A3F7 CA DEX |
DEX |
Zähler vermindern |
decrement block count |
ANOTHER BLOCK OF 256 TO MOVE? |
||
.,A3F8 D0 F2 BNE $A3EC |
BNE MOREN1 |
Alles? Wenn nicht: weiter |
loop until count = $0 |
YES |
||
.,A3FA 60 RTS |
RTS ;RETURN TO CALLER. ; ; THIS ROUTINE IS USED TO ASCERTAIN THAT A GIVEN ; NUMBER OF LOCS REMAIN AVAILABLE FOR THE STACK. ; THE CALL IS: ; LDAI NUMBER OF 2-BYTE ENTRIES NEEDED. ; JSR GETSTK ; ; THIS ROUTINE MUST BE CALLED BY ANY ROUTINE WHICH PUTS ; AN ARBITRARY AMOUNT OF STUFF ON THE STACK, ; I.E., ANY RECURSIVE ROUTINE LIKE "FRMEVL". ; IT IS ALSO CALLED BY ROUTINES SUCH AS "GOSUB" AND "FOR" ; WHICH MAKE PERMANENT ENTRIES ON THE STACK. ; ; ROUTINES WHICH MERELY USE AND FREE UP THE GUARANTEED ; NUMLEV LOCATIONS NEED NOT CALL THIS. ; ; ; ON EXIT: ; [A] AND [X] HAVE BEEN MODIFIED. ; |
sonst RücksprungPrüfung auf Platz im Stapel |
check room on stack for A bytesif stack too deep do out of memory error |
NO, FINISHEDCHECK IF ENOUGH ROOM LEFT ON STACKFOR "FOR", "GOSUB", OR EXPRESSION EVALUATION |
test for 2 * A bytes free on stack |
|
.,A3FB 0A ASL |
GETSTK: ASL A, ;MULT [A] BY 2. NB, CLEARS C BIT. |
Akku muß die halbe Zahl an |
*2 |
|||
.,A3FC 69 3E ADC #$3E |
ADCI 2*NUMLEV+<3*ADDPRC>+13 ;MAKE SURE 2*NUMLEV+13 LOCS ;(13 BECAUSE OF FBUFFR) |
erforderlichem Platz haben |
need at least $3E bytes free |
|||
.,A3FE B0 35 BCS $A435 |
BCS OMERR ;WILL REMAIN IN STACK. |
gibt 'OUT OF MEMORY' |
if overflow go do out of memory error then warm start |
...MEM FULL ERR |
||
.,A400 85 22 STA $22 |
STA INDEX |
Wert merken |
save result in temp byte |
|||
.,A402 BA TSX |
TSX ;GET STACKED. |
Ist Stapelzeiger kleiner |
copy stack |
|||
.,A403 E4 22 CPX $22 |
CPX INDEX ;COMPARE. |
(2 * Akku + 62)? |
compare new limit with stack |
|||
.,A405 90 2E BCC $A435 |
BCC OMERR ;IF STACK.LE.INDEX1, OM. |
Wenn ja, dann OUT OF MEMORY |
if stack < limit do out of memory error then warm start |
...MEM FULL ERR |
||
.,A407 60 RTS |
RTS ; ; [Y,A] IS A CERTAIN ADDRESS. "REASON" MAKES SURE ; IT IS LESS THAN [FRETOP]. ; |
RücksprungSchafft Platz im Speicher |
check available memory, do out of memory error if no room |
CHECK IF ENOUGH ROOM BETWEEN ARRAYS AND STRINGS(Y,A) = ADDR ARRAYS NEED TO GROW TO |
array area overflow check |
|
.,A408 C4 34 CPY $34 |
REASON: CPY FRETOP+1 |
für Zeileneinfügung |
compare with bottom of string space high byte |
HIGH BYTE |
||
.,A40A 90 28 BCC $A434 |
BCC REARTS |
und Variablen |
if less then exit (is ok) |
PLENTY OF ROOM |
||
.,A40C D0 04 BNE $A412 |
BNE TRYMOR ;GO GARB COLLECT. |
A/Y = Adresse, bis zu der |
skip next test if greater (tested <) high byte was =, now do low byte |
NOT ENOUGH, TRY GARBAGE COLLECTION |
||
.,A40E C5 33 CMP $33 |
CMP FRETOP |
Platz benötigt wird. |
compare with bottom of string space low byte |
LOW BYTE |
||
.,A410 90 22 BCC $A434 |
BCC REARTS |
Kleiner als Stringzeiger |
if less then exit (is ok) address is > string storage ptr (oops!) |
ENOUGH ROOM |
||
.,A412 48 PHA |
TRYMOR: PHA |
Akku Zwischenspeichern |
push address low byte |
SAVE (Y,A), TEMP1, AND TEMP2 |
||
.,A413 A2 09 LDX #$09 |
LDXI 8+ADDPRC ;IF TEMPF2 HAS ZERO IN BETWEEN. |
Zähler setzen |
set index to save $57 to $60 inclusive |
|||
.,A415 98 TYA |
TYA |
Y-Register auf |
copy address high byte (to push on stack) save misc numeric work area |
|||
.,A416 48 PHA |
REASAV: PHA |
Stapel retten |
push byte |
|||
.,A417 B5 57 LDA $57,X |
LDA HIGHDS-1,X ;SAVE HIGHDS ON STACK. |
Ab $57 Zwischenspeichern |
get byte from $57 to $60 |
|||
.,A419 CA DEX |
DEX |
Zähler vermindern |
decrement index |
|||
.,A41A 10 FA BPL $A416 |
BPL REASAV ;PUT 8 OF THEM ON STK. |
Alle? sonst weiter |
loop until all done |
|||
.,A41C 20 26 B5 JSR $B526 |
JSR GARBA2 ;GO GARB COLLECT. |
Garbage Collection |
do garbage collection routine restore misc numeric work area |
MAKE AS MUCH ROOM AS POSSIBLE |
||
.,A41F A2 F7 LDX #$F7 |
LDXI 256-8-ADDPRC |
Zähler setzen, um |
set index to restore bytes |
RESTORE TEMP1 AND TEMP2 |
||
.,A421 68 PLA |
REASTO: PLA |
Akku, Y-Register und andere |
pop byte |
AND (Y,A) |
||
.,A422 95 61 STA $61,X |
STA HIGHDS+8+ADDPRC,X ;RESTORE AFTER GARB COLLECT. |
Register zurückholen |
save byte to $57 to $60 |
|||
.,A424 E8 INX |
INX |
Zähler vermindern |
increment index |
|||
.,A425 30 FA BMI $A421 |
BMI REASTO |
Fertig? Nein, dann weiter |
loop while -ve |
|||
.,A427 68 PLA |
PLA |
Y-Register von Stapel |
pop address high byte |
|||
.,A428 A8 TAY |
TAY |
zurückholen |
copy back to Y |
|||
.,A429 68 PLA |
PLA ;RESTORE A AND Y. |
Akku holen |
pop address low byte |
DID WE FIND ENOUGH ROOM? |
||
.,A42A C4 34 CPY $34 |
CPY FRETOP+1 ;COMPARE HIGHS |
Ist jetzt genügend Platz? |
compare with bottom of string space high byte |
HIGH BYTE |
||
.,A42C 90 06 BCC $A434 |
BCC REARTS |
Ja, dann Rücksprung |
if less then exit (is ok) |
YES, AT LEAST A PAGE |
||
.,A42E D0 05 BNE $A435 |
BNE OMERR ;HIGHER IS BAD. |
kein Platz, dann Fehler- |
if greater do out of memory error then warm start high byte was =, now do low byte |
NO, MEM FULL ERR |
||
.,A430 C5 33 CMP $33 |
CMP FRETOP ;AND THE LOWS. |
meldung 1 out of memory 1 |
compare with bottom of string space low byte |
LOW BYTE |
||
.,A432 B0 01 BCS $A435 |
BCS OMERR |
ausgeben |
if >= do out of memory error then warm start ok exit, carry clear |
NO, MEM FULL ERR |
||
.,A434 60 RTS |
REARTS: RTS PAGE ERROR HANDLER, READY, TERMINAL INPUT, COMPACTIFY, NEW, REINIT. |
Rücksprung |
do out of memory error then warm start |
YES, RETURN |
out of memory error |
|
.,A435 A2 10 LDX #$10 |
OMERR: LDXI ERROM |
Fehlernummer 'out of memory'Fehlereinsprung |
error code $10, out of memory error do error #X then warm start |
HANDLE AN ERROR(X)=OFFSET IN ERROR MESSAGE TABLE(ERRFLG) > 128 IF "ON ERR" TURNED ON (CURLIN+1) = $FF IF IN DIRECT MODE WARM RESTART ENTRYCOME HERE FROM MONITOR BY CTL-C, 0G, 3D0G, OR E003G |
error numberhandle error messages |
|
.,A437 6C 00 03 JMP ($0300) |
ERROR: |
Zum BASIC-Warmstart ($E38B)Fehlermeldung ausgeben |
do error messagedo error #X then warm start, the error message vector is initialised to point here |
normally A43Astandard error message handler |
||
.,A43A 8A TXA |
IFN REALIO,< |
Fehlernummer im X-Register |
copy error number |
|||
.,A43B 0A ASL |
LSR CNTWFL> ;FORCE OUTPUT. |
Akku * 2 |
*2 |
|||
.,A43C AA TAX |
IFN EXTIO,< |
Akku als Zeiger nach X |
copy to index |
|||
.,A43D BD 26 A3 LDA $A326,X |
LDA CHANNL ;CLOSE NON-TERMINAL CHANNEL. |
und Adresse der |
get error message pointer low byte |
|||
.,A440 85 22 STA $22 |
BEQ ERRCRD |
Fehlernummer aus Tabelle |
save it |
|||
.,A442 BD 27 A3 LDA $A327,X |
JSR CQCCHN ;CLOSE IT. |
holen und |
get error message pointer high byte |
|||
.,A445 85 23 STA $23 |
LDAI 0 |
abspeichern |
save it |
|||
.,A447 20 CC FF JSR $FFCC |
STA CHANNL> |
I/O Kanäle zurücksetzen |
close input and output channels |
|||
.,A44A A9 00 LDA #$00 |
und Eingabekanal auf |
clear A |
||||
.,A44C 85 13 STA $13 |
Tastatur setzen |
clear current I/O channel, flag default |
||||
.,A44E 20 D7 AA JSR $AAD7 |
ERRCRD: JSR CRDO ;OUTPUT CRLF. |
(CR) und (LF) ausgeben |
print CR/LF |
|||
.,A451 20 45 AB JSR $AB45 |
JSR OUTQST ;PRINT A QUESTION MARK IFE LNGERR,< LDA ERRTAB,X, ;GET FIRST CHR OF ERR MSG. JSR OUTDO ;OUTPUT IT. LDA ERRTAB+1,X, ;GET SECOND CHR. JSR OUTDO> ;OUTPUT IT. |
'?' ausgeben |
print "?" |
|||
.,A454 A0 00 LDY #$00 |
IFN LNGERR,< |
Zeiger setzen |
clear index |
|||
.,A456 B1 22 LDA ($22),Y |
GETERR: LDA ERRTAB,X |
Fehlermeldungstext holen |
get byte from message |
|||
.,A458 48 PHA |
PHA |
Akku retten |
save status |
|||
.,A459 29 7F AND #$7F |
ANDI 127 ;GET RID OF HIGH BIT. |
Bit 7 löschen und |
mask 0xxx xxxx, clear b7 |
|||
.,A45B 20 47 AB JSR $AB47 |
JSR OUTDO ;OUTPUT IT. |
Fehlermeldung ausgeben |
output character |
|||
.,A45E C8 INY |
INX |
Zähler vermindern |
increment index |
|||
.,A45F 68 PLA |
PLA ;LAST CHAR OF MESSAGE? |
Akku zurückholen |
restore status |
|||
.,A460 10 F4 BPL $A456 |
BPL GETERR> ;NO. GO GET NEXT AND OUTPUT IT. |
Fertig? Nein, dann weiter |
loop if character was not end marker |
|||
.,A462 20 7A A6 JSR $A67A |
TYPERR: JSR STKINI ;RESET THE STACK AND FLAGS. |
BASIC-Zeiger initialisieren |
flush BASIC stack and clear continue pointer |
|||
.,A465 A9 69 LDA #$69 |
LDWDI ERR ;GET PNTR TO " ERROR". |
Zeiger A/Y auf Error- |
set " ERROR" pointer low byte |
low A369 |
||
.,A467 A0 A3 LDY #$A3 |
meldung stellen |
set " ERROR" pointer high byteprint string and do warm start, break entry |
high A369 |
|||
.,A469 20 1E AB JSR $AB1E |
ERRFIN: JSR STROUT ;OUTPUT IT. |
String ausgeben |
print null terminated string |
|||
.,A46C A4 3A LDY $3A |
LDY CURLIN+1 |
Auf Programmodus |
get current line number high byte |
|||
.,A46E C8 INY |
INY ;WAS NUMBER 64000? |
(prog/direkt) prüfen |
increment it |
|||
.,A46F F0 03 BEQ $A474 |
BEQ READY ;YES, DON'T TYPE LINE NUMBER. |
Direkt: dann ausgeben |
branch if was in immediate mode |
|||
.,A471 20 C2 BD JSR $BDC2 |
JSR INPRT READY: IFN REALIO,< LSR CNTWFL> ;TURN OUTPUT BACK ON IF SUPRESSED |
'in Zeilennummer' ausgeben |
do " IN " line number messagedo warm start |
|||
.,A474 A9 76 LDA #$76 |
LDWDI REDDY ;SAY "OK". |
Zeiger auf Ready-Modus |
set "READY." pointer low byte |
low A376 |
||
.,A476 A0 A3 LDY #$A3 |
IFN REALIO-3,< JSR RDYJSR> ;OR GO TO INIT IF INIT ERROR. IFE REALIO-3,< |
setzen und |
set "READY." pointer high byte |
low A376 |
||
.,A478 20 1E AB JSR $AB1E |
JSR STROUT> ;NO INIT ERRORS POSSIBLE. |
String ausgeben |
print null terminated string |
|||
.,A47B A9 80 LDA #$80 |
Wert für Direktmodus laden |
set for control messages only |
||||
.,A47D 20 90 FF JSR $FF90 |
und Flag setzenEingabe-Warteschleife |
control kernal messages |
||||
.,A480 6C 02 03 JMP ($0302) |
JMP $A483 |
do BASIC warm startBASIC warm start, the warm start vector is initialised to point here |
normally A483standard warm start routine |
|||
.,A483 20 60 A5 JSR $A560 |
MAIN: JSR INLIN ;GET A LINE FROM TERMINAL. |
BASIC-Zeile nach Eingabepuffer |
call for BASIC input |
READ A LINE |
||
.,A486 86 7A STX $7A |
STXY TXTPTR |
CHRGET Zeiger auf |
save BASIC execute pointer low byte |
SET UP CHRGET TO SCAN THE LINE |
||
.,A488 84 7B STY $7B |
Eingabepuffer |
save BASIC execute pointer high byte |
||||
.,A48A 20 73 00 JSR $0073 |
JSR CHRGET |
nächstes Zeichen holen |
increment and scan memory |
|||
.,A48D AA TAX |
TAX ;SET ZERO FLAG BASED ON [A] ;THIS DISTINGUISHES ":" AND 0 |
Puffer leer? |
copy byte to set flags |
|||
.,A48E F0 F0 BEQ $A480 |
BEQ MAIN ;IF BLANK LINE, GET ANOTHER. |
Ja: dann weiter warten |
loop if no input got to interpret the input line now .... |
EMPTY LINE |
||
.,A490 A2 FF LDX #$FF |
LDXI 255 ;SET DIRECT LINE NUMBER. |
Wert für |
current line high byte to -1, indicates immediate mode |
$FF IN HI-BYTE OF CURLIN MEANS |
||
.,A492 86 3A STX $3A |
STX CURLIN+1 |
Kennzeichen für Direktmodus |
set current line number high byte |
WE ARE IN DIRECT MODE |
||
.,A494 90 06 BCC $A49C |
BCC MAIN1 ;IS A LINE NUMBER. NOT DIRECT. |
Ziffer? als Zeile einfügen |
if numeric character go handle new BASIC line no line number .. immediate mode |
CHRGET SAW DIGIT, NUMBERED LINE |
||
.,A496 20 79 A5 JSR $A579 |
JSR CRUNCH ;COMPACTIFY. |
BASIC-Zeile in Code wandeln |
crunch keywords into BASIC tokens |
NO NUMBER, SO PARSE IT |
||
.,A499 4C E1 A7 JMP $A7E1 |
JMP GONE ;EXECUTE IT. |
Befehl ausführenLöschen und Einfügen vonProgrammzeilen |
go scan and interpret codehandle new BASIC line |
AND TRY EXECUTING ITHANDLE NUMBERED LINE |
handle insert/delete basic lines |
|
.,A49C 20 6B A9 JSR $A96B |
MAIN1: JSR LINGET ;READ LINE NUMBER INTO "LINNUM". |
Zeilenr. nach Adressformat |
get fixed-point number into temporary integer |
|||
.,A49F 20 79 A5 JSR $A579 |
JSR CRUNCH |
BASIC-Zeile in Code wandeln |
crunch keywords into BASIC tokens |
|||
.,A4A2 84 0B STY $0B |
STY COUNT ;RETAIN CHARACTER COUNT. |
Zeiger in Eingabepuffer |
save index pointer to end of crunched line |
SAVE INDEX TO INPUT BUFFER |
||
.,A4A4 20 13 A6 JSR $A613 |
JSR FNDLIN |
Zeilenadresse berechnen |
search BASIC for temporary integer line number |
IS THIS LINE # ALREADY IN PROGRAM? |
||
.,A4A7 90 44 BCC $A4ED |
BCC NODEL ;NO MATCH, SO DON'T DELETE. |
Vorhanden? Ja: löschenProgrammzeile löschen |
if not found skip the line delete line # already exists so delete it |
NO |
delete old line |
|
.,A4A9 A0 01 LDY #$01 |
LDYI 1 |
Zeiger setzen |
set index to next line pointer high byte |
YES, SO DELETE IT |
||
.,A4AB B1 5F LDA ($5F),Y |
LDADY LOWTR |
Startadresse der nächsten |
get next line pointer high byte |
LOWTR POINTS AT LINE |
||
.,A4AD 85 23 STA $23 |
STA INDEX1+1 |
Zeile (HIGH) setzen |
save it |
GET HIGH BYTE OF FORWARD PNTR |
||
.,A4AF A5 2D LDA $2D |
LDA VARTAB |
Variablenanfangszeiger |
get start of variables low byte |
|||
.,A4B1 85 22 STA $22 |
STA INDEX1 |
(LOW) setzen |
save it |
|||
.,A4B3 A5 60 LDA $60 |
LDA LOWTR+1 ;SET TRANSFER TO. |
Startadresse der zu |
get found line pointer high byte |
|||
.,A4B5 85 25 STA $25 |
STA INDEX2+1 |
löschenden Zeile (HIGH) |
save it |
|||
.,A4B7 A5 5F LDA $5F |
LDA LOWTR |
Startadresse der zu |
get found line pointer low byte |
|||
.,A4B9 88 DEY |
DEY |
löschenden Zeile (LOW) |
decrement index |
|||
.,A4BA F1 5F SBC ($5F),Y |
SBCDY LOWTR ;COMPUTE NEGATIVE LENGTH. |
Startadresse der nächsten |
subtract next line pointer low byte |
|||
.,A4BC 18 CLC |
CLC |
Zeile (LOW) |
clear carry for add |
|||
.,A4BD 65 2D ADC $2D |
ADC VARTAB ;COMPUTE NEW VARTAB. |
Variablenanfangszeiger (LOW) |
add start of variables low byte |
|||
.,A4BF 85 2D STA $2D |
STA VARTAB |
ergibt neuen Variablenan- |
set start of variables low byte |
|||
.,A4C1 85 24 STA $24 |
STA INDEX2 ;SET LOW OF TRANS TO. |
fangszeiger (LOW) |
save destination pointer low byte |
|||
.,A4C3 A5 2E LDA $2E |
LDA VARTAB+1 |
Gleiches System für |
get start of variables high byte |
|||
.,A4C5 69 FF ADC #$FF |
ADCI 255 |
HIGH-Byte des Variablenan- |
-1 + carry |
|||
.,A4C7 85 2E STA $2E |
STA VARTAB+1 ;COMPUTE HIGH OF VARTAB. |
fangszeigers |
set start of variables high byte |
|||
.,A4C9 E5 60 SBC $60 |
SBC LOWTR+1 ;COMPUTE NUMBER OF BLOCKS TO MOVE. |
minus Startadresse der zu |
subtract found line pointer high byte |
|||
.,A4CB AA TAX |
TAX |
löschenden Zeile (LOW) ergibt |
copy to block count |
|||
.,A4CC 38 SEC |
SEC |
die zu verschiebenden Blöcke |
set carry for subtract |
|||
.,A4CD A5 5F LDA $5F |
LDA LOWTR |
Startadresse (LOW) minus |
get found line pointer low byte |
|||
.,A4CF E5 2D SBC $2D |
SBC VARTAB ;COMPUTE OFFSET. |
Variablenanfangszeiger (LOW) |
subtract start of variables low byte |
|||
.,A4D1 A8 TAY |
TAY |
ergibt Länge des Restabschn. |
copy to bytes in first block count |
|||
.,A4D2 B0 03 BCS $A4D7 |
BCS QDECT1 ;IF VARTAB.LE.LOWTR, |
Größer als 255? Nein: $A4D7 |
branch if no underflow |
|||
.,A4D4 E8 INX |
INX ;DECR DUE TO CARRY, AND |
Zähler für Blöcke erhöhen |
increment block count, correct for = 0 loop exit |
|||
.,A4D5 C6 25 DEC $25 |
DEC INDEX2+1 ;DECREMENT STORE SO CARRY WORKS. |
Transportzeiger vermindern |
decrement destination high byte |
|||
.,A4D7 18 CLC |
QDECT1: CLC |
Carry löschen |
clear carry for add |
|||
.,A4D8 65 22 ADC $22 |
ADC INDEX1 |
Anfangszeiger (LOW) |
add source pointer low byte |
|||
.,A4DA 90 03 BCC $A4DF |
BCC MLOOP |
Verminderung überspringen |
branch if no overflow |
|||
.,A4DC C6 23 DEC $23 |
DEC INDEX1+1 |
Zeiger um 1 vermindern |
else decrement source pointer high byte |
|||
.,A4DE 18 CLC |
CLC ;FOR LATER ADCQ |
Carry löschen |
clear carry close up memory to delete old line |
|||
.,A4DF B1 22 LDA ($22),Y |
MLOOP: LDADY INDEX1 |
Verschiebeschleife |
get byte from source |
MOVE HIGHER LINES OF PROGRAM |
||
.,A4E1 91 24 STA ($24),Y |
STADY INDEX2 |
Wert abspeichern |
copy to destination |
DOWN OVER THE DELETED LINE. |
||
.,A4E3 C8 INY |
INY |
Zähler um 1 erhöhen |
increment index |
|||
.,A4E4 D0 F9 BNE $A4DF |
BNE MLOOP ;BLOCK DONE? |
Block fertig? Nein: weiter |
while <> 0 do this block |
|||
.,A4E6 E6 23 INC $23 |
INC INDEX1+1 |
1.Adreßzeiger erhöhen (LOW) |
increment source pointer high byte |
|||
.,A4E8 E6 25 INC $25 |
INC INDEX2+1 |
2.Adreßzeiger erhöhen (LOW) |
increment destination pointer high byte |
|||
.,A4EA CA DEX |
DEX |
Blockzähter um 1 vermindern |
decrement block count |
|||
.,A4EB D0 F2 BNE $A4DF |
BNE MLOOP ;DO ANOTHER BLOCK. ALWAYS. |
Alle Blöcke? Nein: weiterProgrammzeile einfügen |
loop until all done got new line in buffer and no existing same # |
insert new line |
||
.,A4ED 20 59 A6 JSR $A659 |
NODEL: JSR RUNC ;RESET ALL VARIABLE INFO SO GARBAGE ;COLLECTION CAUSED BY REASON WILL WORK |
CLR-Befehl |
reset execution to start, clear variables, flush stack and return |
|||
.,A4F0 20 33 A5 JSR $A533 |
JSR LNKPRG ;FIX UP THE LINKS |
Programmzeilen neu binden |
rebuild BASIC line chaining |
|||
.,A4F3 AD 00 02 LDA $0200 |
LDA BUF ;SEE IF ANYTHNG THERE |
Zeichen im Puffer ? |
get first byte from buffer |
ANY CHARACTERS AFTER LINE #? |
||
.,A4F6 F0 88 BEQ $A480 |
BEQ MAIN |
nein, dann zur Warteschleife |
if no line go do BASIC warm start else insert line into memory |
NO, SO NOTHING TO INSERT. |
||
.,A4F8 18 CLC |
CLC |
Carry löschen |
clear carry for add |
|||
.,A4F9 A5 2D LDA $2D |
LDA VARTAB |
Variablenanfangszeiger (LOW) |
get start of variables low byte |
SET UP BLTU SUBROUTINE |
||
.,A4FB 85 5A STA $5A |
STA HIGHTR ;SETUP HIGHTR. |
als Endadresse (Quellbereich) |
save as source end pointer low byte |
INSERT NEW LINE. |
||
.,A4FD 65 0B ADC $0B |
ADC COUNT ;ADD LENGTH OF LINE TO INSERT. |
+ Länge der Zeile als End- |
add index pointer to end of crunched line |
|||
.,A4FF 85 58 STA $58 |
STA HIGHDS ;THIS GIVES DEST ADDR. |
adresse des Zielbereichs LOW |
save as destination end pointer low byte |
|||
.,A501 A4 2E LDY $2E |
LDY VARTAB+1 |
Variablenanfangszeiger als |
get start of variables high byte |
|||
.,A503 84 5B STY $5B |
STY HIGHTR+1 ;SAME FOR HIGH ORDERS. |
Endadr. des Quellbereichs LOW |
save as source end pointer high byte |
|||
.,A505 90 01 BCC $A508 |
BCC NODELC |
Kein Übertrag? dann $A508 |
branch if no carry to high byte |
|||
.,A507 C8 INY |
INY |
Übertrag addieren |
else increment high byte |
|||
.,A508 84 59 STY $59 |
NODELC: STY HIGHDS+1 |
Als Endadresse des Zielbereichs |
save as destination end pointer high byte |
|||
.,A50A 20 B8 A3 JSR $A3B8 |
JSR BLTU IFN BUFPAG,< |
BASIC-Zeilen verschieben |
open up space in memory most of what remains to do is copy the crunched line into the space opened up in memory, however, before the crunched line comes the next line pointer and the line number. the line number is retrieved from the temporary integer and stored in memory, this overwrites the bottom two bytes on the stack. next the line is copied and the next line pointer is filled with whatever was in two bytes above the line number in the stack. this is ok because the line pointer gets fixed in the line chain re-build. |
MAKE ROOM FOR THE LINE |
||
.,A50D A5 14 LDA $14 |
LDWD LINNUM ;POSITION THE BINARY LINE NUMBER |
Zeilennummer aus |
get line number low byte |
PUT LINE NUMBER IN LINE IMAGE |
||
.,A50F A4 15 LDY $15 |
$14/15 vor |
get line number high byte |
||||
.,A511 8D FE 01 STA $01FE |
STWD BUF-2> ;IN FRONT OF BUF |
BASIC-Eingabepuffer setzen |
save line number low byte before crunched line |
|||
.,A514 8C FF 01 STY $01FF |
(ab $0200) |
save line number high byte before crunched line |
||||
.,A517 A5 31 LDA $31 |
LDWD STREND |
Neuer Variablen- |
get end of arrays low byte |
|||
.,A519 A4 32 LDY $32 |
endzeiger |
get end of arrays high byte |
||||
.,A51B 85 2D STA $2D |
STWD VARTAB |
als Zeiger auf Programm- |
set start of variables low byte |
|||
.,A51D 84 2E STY $2E |
ende speichern |
set start of variables high byte |
||||
.,A51F A4 0B LDY $0B |
LDY COUNT |
Zeilenlänge holen |
get index to end of crunched line |
|||
.,A521 88 DEY |
DEY |
und um 1 vermindern |
-1 |
COPY LINE INTO PROGRAM |
||
.,A522 B9 FC 01 LDA $01FC,Y |
STOLOP: LDA BUF-4,Y |
Zeile aus Eingabepuffer |
get byte from crunched line |
|||
.,A525 91 5F STA ($5F),Y |
STADY LOWTR |
ins Programm kopieren |
save byte to memory |
|||
.,A527 88 DEY |
DEY |
Schon alle Zeichen? |
decrement index |
|||
.,A528 10 F8 BPL $A522 |
BPL STOLOP |
Nein: dann weiterkopieren |
loop while more to do reset execution, clear variables, flush stack, rebuild BASIC chain and do warm start |
CLEAR ALL VARIABLESRE-ESTABLISH ALL FORWARD LINKS |
||
.,A52A 20 59 A6 JSR $A659 |
FINI: JSR RUNC ;DO CLEAR & SET UP STACK. ;AND SET [TXTPTR] TO [TXTTAB]-1. |
CLR-Befehl |
reset execution to start, clear variables and flush stack |
CLEAR ALL VARIABLES |
||
.,A52D 20 33 A5 JSR $A533 |
JSR LNKPRG ;FIX UP PROGRAM LINKS |
Programmzeilen neu binden |
rebuild BASIC line chaining |
|||
.,A530 4C 80 A4 JMP $A480 |
JMP MAIN |
zur Eingabe-WarteschleifeBASIC-Zeilen neu binden |
go do BASIC warm startrebuild BASIC line chaining |
relink basic program |
||
.,A533 A5 2B LDA $2B |
LNKPRG: LDWD TXTTAB ;SET [INDEX] TO [TXTTAB]. |
Zeiger auf BASIC-Programm- |
get start of memory low byte |
POINT INDEX AT START OF PROGRAM |
||
.,A535 A4 2C LDY $2C |
start holen und |
get start of memory high byte |
||||
.,A537 85 22 STA $22 |
STWD INDEX |
und als Suchzeiger nach |
set line start pointer low byte |
|||
.,A539 84 23 STY $23 |
$22/23 speichern |
set line start pointer high byte |
||||
.,A53B 18 CLC |
CLC ; ; CHEAD GOES THROUGH PROGRAM STORAGE AND FIXES ; UP ALL THE LINKS. THE END OF EACH LINE IS FOUND ; BY SEARCHING FOR THE ZERO AT THE END. ; THE DOUBLE ZERO LINK IS USED TO DETECT THE END OF THE PROGRAM. ; |
Carry löschen |
clear carry for add |
|||
.,A53C A0 01 LDY #$01 |
CHEAD: LDYI 1 |
Zeiger laden |
set index to pointer to next line high byte |
HI-BYTE OF NEXT FORWARD PNTR |
||
.,A53E B1 22 LDA ($22),Y |
LDADY INDEX ;ARRIVED AT DOUBLE ZEROES? |
Zeilenadresse holen |
get pointer to next line high byte |
END OF PROGRAM YET? |
||
.,A540 F0 1D BEQ $A55F |
BEQ LNKRTS |
=0? Ja: dann RTS |
exit if null, [EOT] |
|||
.,A542 A0 04 LDY #$04 |
LDYI 4 |
Zeiger auf erstes BASIC- |
point to first code byte of line there is always 1 byte + [EOL] as null entries are deleted |
FIND END OF THIS LINE |
||
.,A544 C8 INY |
CZLOOP: INY ;THERE IS AT LEAST ONE BYTE. |
zeichen setzen |
next code byte |
(NOTE MAXIMUM LENGTH < 256) |
||
.,A545 B1 22 LDA ($22),Y |
LDADY INDEX |
Zeichen holen |
get byte |
|||
.,A547 D0 FB BNE $A544 |
BNE CZLOOP ;NO, CONTINUE SEARCHING. |
=0? (Zeilenende) nein: weiter |
loop if not [EOL] |
|||
.,A549 C8 INY |
INY ;GO ONE BEYOND. |
Zeilenlänge nach |
point to byte past [EOL], start of next line |
COMPUTE ADDRESS OF NEXT LINE |
||
.,A54A 98 TYA |
TYA |
Akku schieben |
copy it |
|||
.,A54B 65 22 ADC $22 |
ADC INDEX |
+ Zeiger auf aktuelle Zeile |
add line start pointer low byte |
|||
.,A54D AA TAX |
TAX |
(LOW) ins X-Register |
copy to X |
|||
.,A54E A0 00 LDY #$00 |
LDYI 0 |
Zeiger laden |
clear index, point to this line's next line pointer |
STORE FORWARD PNTR IN THIS LINE |
||
.,A550 91 22 STA ($22),Y |
STADY INDEX |
Akku als Adr.zeiger (LOW) |
set next line pointer low byte |
|||
.,A552 A5 23 LDA $23 |
LDA INDEX+1 |
Zeiger auf aktuelle Zeile (HIGH) |
get line start pointer high byte |
|||
.,A554 69 00 ADC #$00 |
ADCI 0 |
Übertrag addieren |
add any overflow |
(NOTE: THIS CLEARS CARRY) |
||
.,A556 C8 INY |
INY |
Zähler um 1 erhöhen |
increment index to high byte |
|||
.,A557 91 22 STA ($22),Y |
STADY INDEX |
Adresszeiger (HIGH) speichern |
set next line pointer high byte |
|||
.,A559 86 22 STX $22 |
STX INDEX |
Startadresse der nächsten |
set line start pointer low byte |
|||
.,A55B 85 23 STA $23 |
STA INDEX+1 |
Zeile abspeichern |
set line start pointer high byte |
|||
.,A55D 90 DD BCC $A53C |
BCCA CHEAD ;ALWAYS BRANCHES. |
Zum Zeilenanfang |
go do next line, branch always |
...ALWAYS |
||
.,A55F 60 RTS |
LNKRTS: RTS ; ; THIS IS THE LINE INPUT ROUTINE. ; IT READS CHARACTERS INTO BUF USING BACKARROW (UNDERSCORE, OR ; SHIFT O) AS THE DELETE CHARACTER AND @ AS THE ; LINE DELETE CHARACTER. IF MORE THAN BUFLEN CHARACTERS ; ARE TYPED, NO ECHOING IS DONE UNTIL A BACKARROW OR @ OR CR ; IS TYPED. CONTROL-G WILL BE TYPED FOR EACH EXTRA CHARACTER. ; THE ROUTINE IS ENTERED AT INLIN. ; IFE REALIO-4,< INLIN: LDXI 128 ;NO PROMPT CHARACTER STX CQPRMP JSR CQINLN ;GET A LINE ONTO PAGE 2 CPXI BUFLEN-1 BCS GDBUFS ;NOT TOO MANY CHARACTERS LDXI BUFLEN-1 GDBUFS: LDAI 0 ;PUT A ZERO AT THE END STA BUF,X TXA BEQ NOCHR LOPBHT: LDA BUF-1,X ANDI 127 STA BUF-1,X DEX BNE LOPBHT NOCHR: LDAI 0 LDXYI <BUF-1> ;POINT AT THE BEGINNING RTS> IFN REALIO-4,< IFN REALIO-3,< LINLIN: IFE REALIO-2,< JSR OUTDO> ;ECHO IT. DEX ;BACKARROW SO BACKUP PNTR AND BPL INLINC ;GET ANOTHER IF COUNT IS POSITIVE. INLINN: IFE REALIO-2,< JSR OUTDO> ;PRINT THE @ OR A SECOND BACKARROW ;IF THERE WERE TOO MANY. JSR CRDO> |
RücksprungEingabe einer Zeile |
call for BASIC input |
get statement into buffer |
||
.,A560 A2 00 LDX #$00 |
INLIN: LDXI 0 |
Zeiger setzen |
set channel $00, keyboard |
|||
.,A562 20 12 E1 JSR $E112 |
INLINC: JSR INCHR ;GET A CHARACTER. IFN REALIO-3,< CMPI 7 ;IS IT BOB ALBRECHT RINGING THE BELL ;FOR SCHOOL KIDS? BEQ GOODCH> |
ein Zeichen holen |
input character from channel with error check |
|||
.,A565 C9 0D CMP #$0D |
CMPI 13 ;CARRIAGE RETURN? |
RETURN-Taste ? |
compare with [CR] |
|||
.,A567 F0 0D BEQ $A576 |
BEQ FININ1 ;YES, FINISH UP. IFN REALIO-3,< CMPI 32 ;CHECK FOR FUNNY CHARACTERS. BCC INLINC CMPI 125 ;IS IT TILDA OR DELETE? BCS INLINC ;BIG BAD ONES TOO. CMPI "@" ;LINE DELETE? BEQ INLINN ;YES. CMPI "_" ;CHARACTER DELETE? BEQ LINLIN> ;YES. GOODCH: IFN REALIO-3,< CPXI BUFLEN-1 ;LEAVE ROOM FOR NULL. ;COMMO ASSURES US NEVER MORE THAN BUFLEN. BCS OUTBEL> |
ja, dann Eingabe beenden |
if [CR] set XY to $200 - 1, print [CR] and exit character was not [CR] |
|||
.,A569 9D 00 02 STA $0200,X |
STA BUF,X |
Zeichen nach Eingabepuffer |
save character to buffer |
|||
.,A56C E8 INX |
INX |
Zeiger um 1 erhöhen |
increment buffer index |
|||
.,A56D E0 59 CPX #$59 |
IFE REALIO-2,<SKIP2> |
89. Zeichen ? |
compare with max+1 |
|||
.,A56F 90 F1 BCC $A562 |
IFN REALIO-2,<BNE INLINC> |
nein, weitere Zeichen holen |
branch if < max+1 |
|||
.,A571 A2 17 LDX #$17 |
IFN REALIO-3,< |
Nummer für 'string too long' |
error $17, string too long error |
error number |
||
.,A573 4C 37 A4 JMP $A437 |
OUTBEL: LDAI 7 |
Fehlermeldung ausgeben |
do error #X then warm start |
|||
.,A576 4C CA AA JMP $AACA |
IFN REALIO,< |
Puffer mit $0 abschließen, CRUmwandlung einer Zeile in denInterpreter-Code |
set XY to $200 - 1 and print [CR]crunch BASIC tokens vector |
goto end of linecrunch tokens |
||
.,A579 6C 04 03 JMP ($0304) |
JSR OUTDO> ;ECHO IT. BNE INLINC> ;CYCLE ALWAYS. FININ1: JMP FININL> ;GO TO FININL FAR, FAR AWAY. INCHR: IFE REALIO-3,< JSR CQINCH> ;FOR COMMODORE. IFE REALIO-2,< INCHRL: LDA ^O176000 REPEAT 4,<NOP> LSR A, BCC INCHRL LDA ^O176001 ;GET THE CHARACTER. REPEAT 4,<NOP> ANDI 127> IFE REALIO-1,< JSR ^O17132> ;1E5A FOR MOS TECH. IFE REALIO-4,< JSR CQINCH ;FD0C FOR APPLE COMPUTER. ANDI 127> IFE REALIO,< TJSR INSIM##> ;GET A CHARACTER FROM SIMULATOR IFN REALIO,< IFN EXTIO,< LDY CHANNL ;CNT-O HAS NO EFFECT IF NOT FROM TERM. BNE INCRTS> CMPI CONTW ;SUPPRESS OUTPUT CHARACTER (^W). BNE INCRTS ;NO, RETURN. PHA COM CNTWFL ;COMPLEMENT ITS STATE. PLA> INCRTS: RTS ;END OF INCHR. ; ; ALL "RESERVED" WORDS ARE TRANSLATED INTO SINGLE ; BYTES WITH THE MSB ON. THIS SAVES SPACE AND TIME ; BY ALLOWING FOR TABLE DISPATCH DURING EXECUTION. ; THEREFORE ALL STATEMENTS APPEAR TOGETHER IN THE ; RESERVED WORD LIST IN THE SAME ORDER THEY ; APPEAR IN STMDSP. ; BUFOFS=0 ;THE AMOUNT TO OFFSET THE LOW BYTE ;OF THE TEXT POINTER TO GET TO BUF ;AFTER TXTPTR HAS BEEN SETUP TO POINT INTO BUF IFN BUFPAG,< BUFOFS=<BUF/256>*256> |
JMP $A57C |
do crunch BASIC tokenscrunch BASIC tokens, the crunch BASIC tokens vector is initialised to point here |
TOKENIZE THE INPUT LINE |
normally A57Cstandard token cruncher |
|
.,A57C A6 7A LDX $7A |
CRUNCH: LDX TXTPTR ;SET SOURCE POINTER. |
Zeiger setzen, erstes Zeichen |
get BASIC execute pointer low byte |
INDEX INTO UNPARSED LINE |
||
.,A57E A0 04 LDY #$04 |
LDYI 4 ;SET DESTINATION OFFSET. |
Wert für codierte Zeile |
set save index |
INDEX TO PARSED OUTPUT LINE |
||
.,A580 84 0F STY $0F |
STY DORES ;ALLOW CRUNCHING. |
Flag für Hochkomma |
clear open quote/DATA flag |
CLEAR SIGN-BIT OF DATAFLG |
||
.,A582 BD 00 02 LDA $0200,X |
KLOOP: LDA BUFOFS,X IFE REALIO-3,< |
Zeichen aus Puffer holen |
get a byte from the input buffer |
|||
.,A585 10 07 BPL $A58E |
BPL CMPSPC ;GO LOOK AT SPACES. |
kein BASIC-Code ? kleiner 128 |
if b7 clear go do crunching |
|||
.,A587 C9 FF CMP #$FF |
CMPI PI ;PI?? |
Code für Pi ? |
compare with the token for PI, this toke is input directly from the keyboard as the PI character |
PI |
||
.,A589 F0 3E BEQ $A5C9 |
BEQ STUFFH ;GO SAVE IT. |
Ja: dann speichern |
if PI save byte then continue crunching this is the bit of code that stops you being able to enter some keywords as just single shifted characters. If this dropped through you would be able to enter GOTO as just [SHIFT]G |
|||
.,A58B E8 INX |
INX ;SKIP NO PRINTING. |
Zeiger erhöhen |
increment read index |
|||
.,A58C D0 F4 BNE $A582 |
BNE KLOOP> ;ALWAYS GOES. |
nächstes Zeichen überprüfen |
loop if more to do, branch always |
|||
.,A58E C9 20 CMP #$20 |
CMPSPC: CMPI " " ;IS IT A SPACE TO SAVE? |
' ' Leerzeichen? |
compare with [SPACE] |
IGNORE BLANKS |
space |
|
.,A590 F0 37 BEQ $A5C9 |
BEQ STUFFH ;YES, GO SAVE IT. |
Ja: dann speichern |
if [SPACE] save byte then continue crunching |
|||
.,A592 85 08 STA $08 |
STA ENDCHR ;IF IT'S A QUOTE, THIS WILL ;STOP LOOP WHEN OTHER QUOTE APPEARS. |
in Hochkomma-Flag speichern |
save buffer byte as search character |
|||
.,A594 C9 22 CMP #$22 |
CMPI 34 ;QUOTE SIGN? |
"'" Hochkomma? |
compare with quote character |
START OF QUOTATION? |
quote mark |
|
.,A596 F0 56 BEQ $A5EE |
BEQ STRNG ;YES, DO SPECIAL STRING HANDLING. |
Ja: dann speichern |
if quote go copy quoted string |
|||
.,A598 24 0F BIT $0F |
BIT DORES ;TEST FLAG. |
Überprüft auf Bit 6 |
get open quote/DATA token flag |
|||
.,A59A 70 2D BVS $A5C9 |
BVS STUFFH ;NO CRUNCH, JUST STORE. |
gesetzt: ASCII speichern |
branch if b6 of Oquote set, was DATA go save byte then continue crunching |
BRANCH IF IN "DATA" STATEMENT |
||
.,A59C C9 3F CMP #$3F |
CMPI "?" ;A QMARK? |
'?' Fragezeichen? |
compare with "?" character |
SHORTHAND FOR "PRINT"? |
question mark |
|
.,A59E D0 04 BNE $A5A4 |
BNE KLOOP1 |
Nein: dann weiter prüfen |
if not "?" continue crunching |
NO |
||
.,A5A0 A9 99 LDA #$99 |
LDAI PRINTK ;YES, STUFF A "PRINT" TOKEN. |
PRINT-Code für ? laden |
else the keyword token is $99, PRINT |
YES, REPLACE WITH "PRINT" TOKEN |
PRINT code |
|
.,A5A2 D0 25 BNE $A5C9 |
BNE STUFFH ;ALWAYS GO TO STUFFH. |
und abspeichern |
go save byte then continue crunching, branch always |
...ALWAYS |
||
.,A5A4 C9 30 CMP #$30 |
KLOOP1: CMPI "0" ;SKIP NUMERICS. |
Kleiner $30 ? (Code für 0) |
compare with "0" |
IS IT A DIGIT, COLON, OR SEMI-COLON? |
0 |
|
.,A5A6 90 04 BCC $A5AC |
BCC MUSTCR |
Ja: dann $A5AC |
branch if <, continue crunching |
NO, PUNCTUATION !"#$%&'()*+,-./ |
||
.,A5A8 C9 3C CMP #$3C |
CMPI 60 ;":" AND ";" ARE ENTERED STRAIGHTAWAY. |
Mit $3C vergleichen |
compare with "<" |
|||
.,A5AA 90 1D BCC $A5C9 |
BCC STUFFH |
wenn größer, dann $A5C9 |
if <, 0123456789:; go save byte then continue crunching gets here with next character not numeric, ";" or ":" |
YES, NOT A TOKENSEARCH TOKEN NAME TABLE FOR MATCH STARTINGWITH CURRENT CHAR FROM INPUT LINE |
||
.,A5AC 84 71 STY $71 |
MUSTCR: STY BUFPTR ;SAVE BUFFER POINTER. |
Zeiger Zwischenspeichern |
copy save index |
SAVE INDEX TO OUTPUT LINE |
||
.,A5AE A0 00 LDY #$00 |
LDYI 0 ;LOAD RESLST POINTER. |
Zähler für Tokentabelle |
clear table pointer |
USE Y-REG WITH (FAC) TO ADDRESS TABLE |
||
.,A5B0 84 0B STY $0B |
STY COUNT ;ALSO CLEAR COUNT. |
initialisieren |
clear word index |
HOLDS CURRENT TOKEN-$80 |
||
.,A5B2 88 DEY |
DEY |
adjust for pre increment loop |
PREPARE FOR "INY" A FEW LINES DOWN |
|||
.,A5B3 86 7A STX $7A |
STX TXTPTR ;SAVE TEXT POINTER FOR LATER USE. |
Zeiger auf Eingabepuffer |
save BASIC execute pointer low byte, buffer index |
SAVE POSITION IN INPUT LINE |
||
.,A5B5 CA DEX |
DEX |
zwischenspeichern |
adjust for pre increment loop |
PREPARE FOR "INX" A FEW LINES DOWN |
||
.,A5B6 C8 INY |
RESER: INY |
X- und Y-Register |
next table byte |
ADVANCE POINTER TO TOKEN TABLE |
||
.,A5B7 E8 INX |
RESPUL: INX |
um 1 erhöhen |
next buffer byte |
|||
.,A5B8 BD 00 02 LDA $0200,X |
RESCON: LDA BUFOFS,X |
Zeichen aus Puffer laden |
get byte from input buffer |
NEXT CHAR FROM INPUT LINE |
||
.,A5BB 38 SEC |
SEC ;PREPARE TO SUBSTARCT. |
Carry für Subtr. löschen |
set carry for subtract |
NO, COMPARE TO CHAR IN TABLE |
||
.,A5BC F9 9E A0 SBC $A09E,Y |
SBC RESLST,Y ;CHARACTERS EQUAL? |
Zeichen mit Befehlswort vergleichen |
subtract table byte |
SAME AS NEXT CHAR OF TOKEN NAME? |
||
.,A5BF F0 F5 BEQ $A5B6 |
BEQ RESER ;YES, CONTINUE SEARCH. |
Gefunden? Ja: nächstes Zeich. |
go compare next if match |
YES, CONTINUE MATCHING |
||
.,A5C1 C9 80 CMP #$80 |
CMPI 128 ;NO BUT MAYBE THE END IS HERE. |
mit $80 (128) vergleichen |
was it end marker match ? |
MAYBE; WAS IT SAME EXCEPT FOR BIT 7? |
||
.,A5C3 D0 30 BNE $A5F5 |
BNE NTHIS ;NO, TRULY UNEQUAL. |
Befehl nicht gefunden: $A5F5 |
branch if not, not found keyword actually this works even if the input buffer byte is the end marker, i.e. a shifted character. As you can't enter any keywords as a single shifted character, see above, you can enter keywords in shorthand by shifting any character after the first. so RETURN can be entered as R[SHIFT]E, RE[SHIFT]T, RET[SHIFT]U or RETU[SHIFT]R. RETUR[SHIFT]N however will not work because the [SHIFT]N will match the RETURN end marker so the routine will try to match the next character. else found keyword |
NO, SKIP TO NEXT TOKEN |
||
.,A5C5 05 0B ORA $0B |
ORA COUNT |
BASIC-Code gleich Zähler +$80 |
OR with word index, +$80 in A makes token |
YES, END OF TOKEN; GET TOKEN # |
||
.,A5C7 A4 71 LDY $71 |
GETBPT: LDY BUFPTR ;GET BUFFER PNTR. |
Zeiger auf cod. Zeile holen |
restore save index save byte then continue crunching |
GET INDEX TO OUTPUT LINE IN Y-REG |
||
.,A5C9 E8 INX |
STUFFH: INX |
increment buffer read index |
ADVANCE INPUT INDEX |
|||
.,A5CA C8 INY |
INY |
Zeiger erhöhen |
increment save index |
ADVANCE OUTPUT INDEX |
||
.,A5CB 99 FB 01 STA $01FB,Y |
STA BUF-5,Y |
BASIC-Code speichern |
save byte to output |
STORE CHAR OR TOKEN |
||
.,A5CE B9 FB 01 LDA $01FB,Y |
LDA BUF-5,Y |
und Statusregister setzen |
get byte from output, set flags |
TEST FOR EOL OR EOS |
||
.,A5D1 F0 36 BEQ $A609 |
BEQ CRDONE ;NULL IMPLIES END OF LINE. |
=0 (Ende): dann fertig |
branch if was null [EOL] A holds the token here |
END OF LINE |
||
.,A5D3 38 SEC |
SEC ;PREPARE TO SUBSTARCT. |
Carry setzen (Subtraktion) |
set carry for subtract |
|||
.,A5D4 E9 3A SBC #$3A |
SBCI ":" ;IS IT A ":"? |
':' Trennzeichen? |
subtract ":" |
END OF STATEMENT? |
colon |
|
.,A5D6 F0 04 BEQ $A5DC |
BEQ COLIS ;YES, ALLOW CRUNCHING AGAIN. |
Ja: dann $A5DC |
branch if it was (is now $00) A now holds token-':' |
YES, CLEAR DATAFLG |
||
.,A5D8 C9 49 CMP #$49 |
CMPI DATATK-":" ;IS IT A DATATK? |
DATA-Code ? |
compare with the token for DATA-':' |
"DATA" TOKEN? |
DATA code |
|
.,A5DA D0 02 BNE $A5DE |
BNE NODATT ;NO, SEE IF IT IS REM TOKEN. |
Nein: Speichern überspringen |
if not DATA go try REM token was : or DATA |
NO, LEAVE DATAFLG ALONE |
||
.,A5DC 85 0F STA $0F |
COLIS: STA DORES ;SETUP FLAG. |
nach Hochkomma-Flag speichern |
save the token-$3A |
DATAFLG = 0 OR $83-$3A = $49 |
||
.,A5DE 38 SEC |
NODATT: SEC ;PREP TO SBCQ |
Carry setzen |
set carry for subtract |
IS IT A "REM" TOKEN? |
||
.,A5DF E9 55 SBC #$55 |
SBCI REMTK-":" ;REM ONLY STOPS ON NULL. |
REM-Code ? |
subtract the token for REM-':' |
REM code |
||
.,A5E1 D0 9F BNE $A582 |
BNE KLOOP ;NO, CONTINUE CRUNCHING. |
Nein: zum Schleifenanfang |
if wasn't REM crunch next bit of line |
NO, CONTINUE PARSING LINE |
||
.,A5E3 85 08 STA $08 |
STA ENDCHR ;REM STOPS ONLY ON NULL, NOT : OR ". |
0 in Hochkomma-Flag |
else was REM so set search for [EOL] loop for "..." etc. |
YES, CLEAR LITERAL FLAGHANDLE LITERAL (BETWEEN QUOTES) OR REMARK,BY COPYING CHARS UP TO ENDCHR. |
||
.,A5E5 BD 00 02 LDA $0200,X |
STR1: LDA BUFOFS,X |
nächstes Zeichen holen |
get byte from input buffer |
|||
.,A5E8 F0 DF BEQ $A5C9 |
BEQ STUFFH ;YES, END OF LINE, SO DONE. |
=0 (Ende)? Ja: dann $A5C9 |
if null [EOL] save byte then continue crunching |
END OF LINE |
||
.,A5EA C5 08 CMP $08 |
CMP ENDCHR ;END OF GOBBLE? |
Als ASCII speichern? |
compare with stored character |
|||
.,A5EC F0 DB BEQ $A5C9 |
BEQ STUFFH ;YES, DONE WITH STRING. |
Nein: dann $A5C9 |
if match save byte then continue crunching |
FOUND ENDCHR |
||
.,A5EE C8 INY |
STRNG: INY ;INCREMENT BUFFER POINTER. |
Zeiger erhöhen |
increment save index |
NEXT OUTPUT CHAR |
||
.,A5EF 99 FB 01 STA $01FB,Y |
STA BUF-5,Y |
Code abspeichern |
save byte to output |
|||
.,A5F2 E8 INX |
INX |
Zeiger erhöhen |
increment buffer index |
NEXT INPUT CHAR |
||
.,A5F3 D0 F0 BNE $A5E5 |
BNE STR1 ;PROCESS NEXT CHARACTER. |
Zum Schleifenanfang |
loop while <> 0, should never reach 0 not found keyword this go |
...ALWAYSADVANCE POINTER TO NEXT TOKEN NAME |
||
.,A5F5 A6 7A LDX $7A |
NTHIS: LDX TXTPTR ;RESTORE TEXT POINTER. |
Zeiger wieder auf Eingabep. |
restore BASIC execute pointer low byte |
GET POINTER TO INPUT LINE IN X-REG |
||
.,A5F7 E6 0B INC $0B |
INC COUNT ;INCREMENT RES WORD COUNT. |
Suchzähler erhöhen |
increment word index (next word) now find end of this word in the table |
BUMP (TOKEN # - $80) |
||
.,A5F9 C8 INY |
NTHIS1: INY |
Zähler erhöhen |
increment table index |
NEXT TOKEN ONE BEYOND THAT |
||
.,A5FA B9 9D A0 LDA $A09D,Y |
LDA RESLST-1,Y, ;GET RES CHARACTER. |
nächsten Befehl suchen |
get table byte |
YES, AT NEXT NAME. END OF TABLE? |
||
.,A5FD 10 FA BPL $A5F9 |
BPL NTHIS1 ;END OF ENTRY? |
Gefunden? Nein: weitersuchen |
loop if not end of word yet |
|||
.,A5FF B9 9E A0 LDA $A09E,Y |
LDA RESLST,Y, ;YES. IS IT THE END? |
Ende der Tabelle? |
get byte from keyword table |
|||
.,A602 D0 B4 BNE $A5B8 |
BNE RESCON ;NO, TRY THE NEXT WORD. |
Nein: dann weiter |
go test next word if not zero byte, end of table reached end of table with no match |
NO, NOT END OF TABLE |
||
.,A604 BD 00 02 LDA $0200,X |
LDA BUFOFS,X ;YES, END OF TABLE. GET 1ST CHR. |
nächstes Zeichen holen |
restore byte from input buffer |
YES, SO NOT A KEYWORD |
||
.,A607 10 BE BPL $A5C7 |
BPL GETBPT ;STORE IT AWAY (ALWAYS BRANCHES). |
kleiner $80? Ja: $A5C7 |
branch always, all unmatched bytes in the buffer are $00 to $7F, go save byte in output and continue crunching reached [EOL] |
...ALWAYS, COPY CHAR AS IS END OF LINE |
||
.,A609 99 FD 01 STA $01FD,Y |
CRDONE: STA BUF-3,Y, ;SO THAT IF THIS IS A DIR STATEMENT ;ITS END WILL LOOK LIKE END OF PROGRAM. IFN <<BUF+BUFLEN>/256>-<<BUF-1>/256>,< |
im Eingabepuffer speichern |
save [EOL] |
STORE ANOTHER 00 ON END |
||
.,A60C C6 7B DEC $7B |
DEC TXTPTR+1> |
CHRGET-Zeiger zurücksetzen |
decrement BASIC execute pointer high byte |
SET TXTPTR = INPUT.BUFFER-1 |
||
.,A60E A9 FF LDA #$FF |
LDAI <BUF&255>-1 ;MAKE TXTPTR POINT TO |
Zeiger auf Eingabepuffer -1 |
point to start of buffer-1 |
|||
.,A610 85 7A STA $7A |
STA TXTPTR ;CRUNCHED LINE. |
setzen (LOW) |
set BASIC execute pointer low byte |
|||
.,A612 60 RTS |
LISTRT: RTS ;RETURN TO CALLER. ; ; FNDLIN SEARCHES THE PROGRAM TEXT FOR THE LINE ; WHOSE NUMBER IS PASSED IN "LINNUM". ; THERE ARE TWO POSSIBLE RETURNS: ; ; 1) CARRY SET. ; LOWTR POINTS TO THE LINK FIELD IN THE LINE ; WHICH IS THE ONE SEARCHED FOR. ; ; 2) CARRY NOT SET. ; LINE NOT FOUND. [LOWTR] POINTS TO THE LINE IN THE ; PROGRAM GREATER THAN THE ONE SOUGHT AFTER. ; |
RücksprungStartadresse einerProgrammzeile berechnen |
search BASIC for temporary integer line number |
SEARCH FOR LINE(LINNUM) = LINE # TO FINDIF NOT FOUND: CARRY = 0 LOWTR POINTS AT NEXT LINE IF FOUND: CARRY = 1 LOWTR POINTS AT LINE |
search for a line in a program |
|
.,A613 A5 2B LDA $2B |
FNDLIN: LDWX TXTTAB ;LOAD [X,A] WITH [TXTTAB] |
Zeiger auf BASIC- |
get start of memory low byte |
SEARCH FROM BEGINNING OF PROGRAM |
||
.,A615 A6 2C LDX $2C |
Programmstart laden |
get start of memory high bytesearch Basic for temp integer line number from AXreturns carry set if found |
||||
.,A617 A0 01 LDY #$01 |
FNDLNC: LDYI 1 |
Zähler setzen |
set index to next line pointer high byte |
SEARCH FROM (X,A) |
||
.,A619 85 5F STA $5F |
STWX LOWTR ;STORE [X,A] INTO LOWTR |
BASIC-Programmstart als |
save low byte as current |
|||
.,A61B 86 60 STX $60 |
Zeiger nach $5F/60 |
save high byte as current |
||||
.,A61D B1 5F LDA ($5F),Y |
LDADY LOWTR ;SEE IF LINK IS 0 |
Link-Adresse holen (HIGH) |
get next line pointer high byte from address |
|||
.,A61F F0 1F BEQ $A640 |
BEQ FLINRT |
gleich null: dann Ende |
pointer was zero so done, exit |
END OF PROGRAM, AND NOT FOUND |
||
.,A621 C8 INY |
INY |
Zähler 2 mal erhöhen ( LOW- |
increment index ... |
|||
.,A622 C8 INY |
INY |
Byte übergehen) |
... to line # high byte |
|||
.,A623 A5 15 LDA $15 |
LDA LINNUM+1 ;COMP HIGH ORDERS OF LINE NUMBERS. |
gesuchte Zeilennummer (HIGH) |
get temporary integer high byte |
|||
.,A625 D1 5F CMP ($5F),Y |
CMPDY LOWTR |
mit aktueller vergleichen |
compare with line # high byte |
|||
.,A627 90 18 BCC $A641 |
BCC FLNRTS ;NO SUCH LINE NUMBER. |
kleiner: dann nicht gefunden |
exit if temp < this line, target line passed |
IF NOT FOUND |
||
.,A629 F0 03 BEQ $A62E |
BEQ FNDLO1 |
gleich: Nummer LOW prüfen |
go check low byte if = |
|||
.,A62B 88 DEY |
DEY |
Zähler um 1 vermindern |
else decrement index |
|||
.,A62C D0 09 BNE $A637 |
BNE AFFRTS ;ALWAYS BRANCH. |
unbedingter Sprung |
branch always |
|||
.,A62E A5 14 LDA $14 |
FNDLO1: LDA LINNUM |
gesuchte Zeilennummer (LOW) |
get temporary integer low byte |
|||
.,A630 88 DEY |
DEY |
Zeiger um 1 vermindern |
decrement index to line # low byte |
|||
.,A631 D1 5F CMP ($5F),Y |
CMPDY LOWTR ;COMPARE LOW ORDERS. |
Zeilennummer LOW vergleichen |
compare with line # low byte |
|||
.,A633 90 0C BCC $A641 |
BCC FLNRTS ;NO SUCH NUMBER. |
kleiner: Zeile nicht gefunden |
exit if temp < this line, target line passed |
PAST LINE, NOT FOUND |
||
.,A635 F0 0A BEQ $A641 |
BEQ FLNRTS ;GO TIT. |
oder gleich: C=1 und RTS |
exit if temp = (found line#) not quite there yet |
IF FOUND |
||
.,A637 88 DEY |
AFFRTS: DEY |
Y-Register auf 1 setzen |
decrement index to next line pointer high byte |
|||
.,A638 B1 5F LDA ($5F),Y |
LDADY LOWTR ;FETCH LINK. |
Adresse der nächsten Zeile |
get next line pointer high byte |
|||
.,A63A AA TAX |
TAX |
in das X-Register laden |
copy to X |
|||
.,A63B 88 DEY |
DEY |
Register vermindern (auf 0) |
decrement index to next line pointer low byte |
|||
.,A63C B1 5F LDA ($5F),Y |
LDADY LOWTR |
Link-Adresse holen (LOW) |
get next line pointer low byte |
|||
.,A63E B0 D7 BCS $A617 |
BCS FNDLNC ;ALWAYS BRANCHES. |
weiter suchen |
go search for line # in temporary integer from AX, carry always set |
ALWAYS |
||
.,A640 18 CLC |
FLINRT: CLC ;C MAY BE HIGH. |
Carry löschen |
clear found flag |
RETURN CARRY = 0 |
||
.,A641 60 RTS |
FLNRTS: RTS ;RETURN TO CALLER. ; ; THE "NEW" COMMAND CLEARS THE PROGRAM TEXT AS WELL ; AS VARIABLE SPACE. ; |
RücksprungBASIC-Befehl NEW |
perform NEW |
"NEW" STATEMENT |
NEW command |
|
.,A642 D0 FD BNE $A641 |
SCRATH: BNE FLNRTS ;MAKE SURE THERE IS A TERMINATOR. |
Kein Trennzeichen: SYNTAX ERROR |
exit if following byte to allow syntax error |
IGNORE IF MORE TO THE STATEMENT |
||
.,A644 A9 00 LDA #$00 |
SCRTCH: LDAI 0 ;GET A CLEARER. |
Nullcode laden |
clear A |
|||
.,A646 A8 TAY |
TAY ;SET UP INDEX. |
und als Zähler ins Y-Reg. |
clear index |
|||
.,A647 91 2B STA ($2B),Y |
STADY TXTTAB ;CLEAR FIRST LINK. |
Nullcode an Programmanfang |
clear pointer to next line low byte |
|||
.,A649 C8 INY |
INY |
Zähler erhöhen |
increment index |
|||
.,A64A 91 2B STA ($2B),Y |
STADY TXTTAB |
noch einen Nullcode dahinter |
clear pointer to next line high byte, erase program |
|||
.,A64C A5 2B LDA $2B |
LDA TXTTAB |
Zeiger auf Programmst. (LOW) |
get start of memory low byte |
|||
.,A64E 18 CLC |
CLC |
Carry löschen |
clear carry for add |
|||
.,A64F 69 02 ADC #$02 |
ADCI 2 |
Programmstart + 2 ergibt |
add null program length |
|||
.,A651 85 2D STA $2D |
STA VARTAB ;SETUP [VARTAB]. |
neuen Variablenstart (LOW) |
set start of variables low byte |
|||
.,A653 A5 2C LDA $2C |
LDA TXTTAB+1 |
Zeiger auf Programmst. (HIGH) |
get start of memory high byte |
|||
.,A655 69 00 ADC #$00 |
ADCI 0 |
+ Übertrag ergibt neuen |
add carry |
|||
.,A657 85 2E STA $2E |
STA VARTAB+1 |
Variablenstart (HIGH) |
set start of variables high bytereset execute pointer and do CLR |
|||
.,A659 20 8E A6 JSR $A68E |
RUNC: JSR STXTPT |
CHRGET, Routine neu setzen |
set BASIC execute pointer to start of memory - 1 |
SET TXTPTR TO TXTTAB - 1 |
||
.,A65C A9 00 LDA #$00 |
LDAI 0 ;SET ZERO FLAG ; ; THIS CODE IS FOR THE CLEAR COMMAND. ; |
Zero-Flag für CLR = 1 setzenBASIC-Befehl CLR |
set Zb for CLR entryperform CLR |
(THIS COULD HAVE BEEN ".HS 2C")"CLEAR" STATEMENT |
CLR command |
|
.,A65E D0 2D BNE $A68D |
CLEAR: BNE STKRTS ;SYNTAX ERROR IF NO TERMINATOR. ; ; CLEAR INITIALIZES THE VARIABLE AND ; ARRAY SPACE BY RESETING ARYTAB (THE END OF SIMPLE VARIABLE SPACE) ; AND STREND (THE END OF ARRAY STORAGE). IT FALLS INTO "STKINI" ; WHICH RESETS THE STACK. |
Kein Trennzeichen: SYNTAX ERROR |
exit if following byte to allow syntax error |
IGNORE IF NOT AT END OF STATEMENT |
||
.,A660 20 E7 FF JSR $FFE7 |
; |
alle I/O Kanäle zurücksetzen |
close all channels and files |
|||
.,A663 A5 37 LDA $37 |
CLEARC: LDWD MEMSIZ ;FREE UP STRING SPACE. |
Zeiger auf BASIC-RAM-Ende |
get end of memory low byte |
CLEAR STRING AREA |
||
.,A665 A4 38 LDY $38 |
(LOW/HIGH) laden |
get end of memory high byte |
||||
.,A667 85 33 STA $33 |
STWD FRETOP |
String-Start auf BASIC- |
set bottom of string space low byte, clear strings |
|||
.,A669 84 34 STY $34 |
IFN EXTIO,< JSR CQCALL> ;CLOSE ALL OPEN FILES. |
RAM-Ende setzen |
set bottom of string space high byte |
|||
.,A66B A5 2D LDA $2D |
LDWD VARTAB ;LIBERATE THE |
Zeiger auf Variablen- |
get start of variables low byte |
CLEAR ARRAY AREA |
||
.,A66D A4 2E LDY $2E |
start laden |
get start of variables high byte |
||||
.,A66F 85 2F STA $2F |
STWD ARYTAB ;VARIABLES AND |
und in Array-Anfangs- |
set end of variables low byte, clear variables |
|||
.,A671 84 30 STY $30 |
zeiger setzen |
set end of variables high byte |
||||
.,A673 85 31 STA $31 |
STWD STREND ;ARRAYS. |
und in Zeiger auf Array- |
set end of arrays low byte, clear arrays |
LOW END OF FREE SPACE |
||
.,A675 84 32 STY $32 |
Ende speichern |
set end of arrays high bytedo RESTORE and clear stack |
||||
.,A677 20 1D A8 JSR $A81D |
FLOAD: JSR RESTOR ;RESTORE DATA. ; ; STKINI RESETS THE STACK POINTER ELIMINATING ; GOSUB AND FOR CONTEXT. STRING TEMPORARIES ARE FREED ; UP, SUBFLG IS RESET. CONTINUING IS PROHIBITED. ; AND A DUMMY ENTRY IS LEFT AT THE BOTTOM OF THE STACK SO "FNDFOR" WILL ALWAYS ; FIND A NON-"FOR" ENTRY AT THE BOTTOM OF THE STACK. ; |
RESTORE-Befehl |
perform RESTOREflush BASIC stack and clear the continue pointer |
SET "DATA" POINTER TO BEGINNING |
reset stack and program pointers |
|
.,A67A A2 19 LDX #$19 |
STKINI: LDXI TEMPST ;INITIALIZE STRING TEMPORARIES. |
Wert laden und String- |
get the descriptor stack start |
|||
.,A67C 86 16 STX $16 |
STX TEMPPT |
Descriptor-Index zurücksetzen |
set the descriptor stack pointer |
|||
.,A67E 68 PLA |
PLA ;SETUP RETURN ADDRESS. |
2 Bytes vom Stapel in das |
pull the return address low byte |
SAVE RETURN ADDRESS |
||
.,A67F A8 TAY |
TAY |
Y-Register und den |
copy it |
|||
.,A680 68 PLA |
PLA |
Akku holen |
pull the return address high byte |
|||
.,A681 A2 FA LDX #$FA |
LDXI STKEND-257 |
Wert laden und damit |
set the cleared stack pointer |
START STACK AT $F8, |
||
.,A683 9A TXS |
TXS |
Stapelzeiger initialisieren |
set the stack |
LEAVING ROOM FOR PARSING LINES |
||
.,A684 48 PHA |
PHA |
2 Bytes aus dem Y-Register |
push the return address high byte |
RESTORE RETURN ADDRESS |
||
.,A685 98 TYA |
TYA |
und dem Akku wieder auf |
restore the return address low byte |
|||
.,A686 48 PHA |
PHA |
den Stapel schieben |
push the return address low byte |
|||
.,A687 A9 00 LDA #$00 |
LDAI 0 |
Wert laden und damit |
clear A |
|||
.,A689 85 3E STA $3E |
STA OLDTXT+1 ;DISALLOWING CONTINUING |
CONT sperren |
clear the continue pointer high byte |
|||
.,A68B 85 10 STA $10 |
STA SUBFLG ;ALLOW SUBSCRIPTS. |
und in FN-Flag speichern |
clear the subscript/FNX flag |
|||
.,A68D 60 RTS |
STKRTS: RTS |
RücksprungProgrammzeiger aufBASIC-Start |
set BASIC execute pointer to start of memory - 1 |
SET TXTPTR TO BEGINNING OF PROGRAM |
set current character pointer to start of basic - 1 |
|
.,A68E 18 CLC |
STXTPT: CLC |
Carry löschen (Addition) |
clear carry for add |
TXTPTR = TXTTAB - 1 |
||
.,A68F A5 2B LDA $2B |
LDA TXTTAB |
Zeiger auf Programmstart (LOW) |
get start of memory low byte |
|||
.,A691 69 FF ADC #$FF |
ADCI 255 |
minus 1 ergibt |
add -1 low byte |
|||
.,A693 85 7A STA $7A |
STA TXTPTR |
neuen CHRGET-Zeiger (LOW) |
set BASIC execute pointer low byte |
|||
.,A695 A5 2C LDA $2C |
LDA TXTTAB+1 |
Programmstart (HIGH) |
get start of memory high byte |
|||
.,A697 69 FF ADC #$FF |
ADCI 255 |
minus 1 ergibt |
add -1 high byte |
|||
.,A699 85 7B STA $7B |
STA TXTPTR+1 ;SETUP TEXT POINTER. |
CHRGET-Zeiger (HIGH) |
save BASIC execute pointer high byte |
|||
.,A69B 60 RTS |
RTS PAGE THE "LIST" COMMAND. |
RücksprungBASIC Befehl LIST |
perform LIST |
"LIST" STATEMENT |
LIST command |
|
.,A69C 90 06 BCC $A6A4 |
LIST: BCC GOLST ;IT IS A DIGIT. |
Ziffer ? (Zeilennummer) |
branch if next character not token (LIST n...) |
NO LINE # SPECIFIED |
||
.,A69E F0 04 BEQ $A6A4 |
BEQ GOLST ;IT IS A TERMINATOR. |
nur LIST ? |
branch if next character [NULL] (LIST) |
---DITTO--- |
||
.,A6A0 C9 AB CMP #$AB |
CMPI MINUTK ;DASH PRECEDING? |
Code für '-'? |
compare with token for - |
IF DASH OR COMMA, START AT LINE 0 |
||
.,A6A2 D0 E9 BNE $A68D |
BNE STKRTS ;NO, SO SYNTAX ERROR. |
anderer Code, dann SYNTAX ERR |
exit if not - (LIST -m) LIST [[n][-m]] this bit sets the n , if present, as the start and end |
NO, ERROR |
||
.,A6A4 20 6B A9 JSR $A96B |
GOLST: JSR LINGET ;GET LINE NUMBER INTO NUMLIN. |
Zeilennummer holen |
get fixed-point number into temporary integer |
CONVERT LINE NUMBER IF ANY |
||
.,A6A7 20 13 A6 JSR $A613 |
JSR FNDLIN ;FIND LINE .GE. [NUMLIN]. |
Startadresse berechnen |
search BASIC for temporary integer line number |
POINT LOWTR TO 1ST LINE |
||
.,A6AA 20 79 00 JSR $0079 |
JSR CHRGOT ;GET LAST CHARACTER. |
CHRGOT letztes Zeichen holen |
scan memory |
RANGE SPECIFIED? |
||
.,A6AD F0 0C BEQ $A6BB |
BEQ LSTEND ;IF END OF LINE, # IS THE END. |
keine Zeilennummer |
branch if no more chrs this bit checks the - is present |
NO |
||
.,A6AF C9 AB CMP #$AB |
CMPI MINUTK ;DASH? |
Code für '-'? |
compare with token for - |
|||
.,A6B1 D0 8E BNE $A641 |
BNE FLNRTS ;IF NOT, SYNTAX ERROR. |
nein: SYNTAX ERROR |
return if not "-" (will be SN error) LIST [n]-m the - was there so set m as the end value |
|||
.,A6B3 20 73 00 JSR $0073 |
JSR CHRGET ;GET NEXT CHAR. |
CHRGET nächstes Zeichen holen |
increment and scan memory |
GET NEXT CHAR |
||
.,A6B6 20 6B A9 JSR $A96B |
JSR LINGET ;GET END #. |
Zeilennummer holen |
get fixed-point number into temporary integer |
CONVERT SECOND LINE # |
||
.,A6B9 D0 86 BNE $A641 |
BNE FLNRTS ;IF NOT TERMINATOR, ERROR. |
kein Trennzeichen: SYNTAX ERR |
exit if not ok |
BRANCH IF SYNTAX ERR |
||
.,A6BB 68 PLA |
LSTEND: PLA |
2 Bytes von Stapel holen |
dump return address low byte, exit via warm start |
POP RETURN ADRESS |
||
.,A6BC 68 PLA |
PLA ;GET RID OF "NEWSTT" RTS ADDR. |
(Rücksprungadresse übergehen) |
dump return address high byte |
(GET BACK BY "JMP NEWSTT") |
||
.,A6BD A5 14 LDA $14 |
LDA LINNUM ;SEE IF IT WAS EXISTENT. |
zweite Zeilennummer laden |
get temporary integer low byte |
IF NO SECOND NUMBER, USE $FFFF |
||
.,A6BF 05 15 ORA $15 |
ORA LINNUM+1 |
gleich null ? |
OR temporary integer high byte |
|||
.,A6C1 D0 06 BNE $A6C9 |
BNE LIST4 ;IT WAS TYPED. |
Nein: $A6C9 |
branch if start set |
THERE WAS A SECOND NUMBER |
||
.,A6C3 A9 FF LDA #$FF |
LDAI 255 |
Wert laden und |
set for -1 |
MAX END RANGE |
||
.,A6C5 85 14 STA $14 |
STA LINNUM |
zweite Zeilennummer Maximal- |
set temporary integer low byte |
|||
.,A6C7 85 15 STA $15 |
STA LINNUM+1 ;MAKE IT HUGE. |
wert $FFFF (65535) |
set temporary integer high byte |
list lines from $5F/$60 to $14/$15 |
||
.,A6C9 A0 01 LDY #$01 |
LIST4: LDYI 1 IFE REALIO-3,< |
Zeiger setzen |
set index for line |
|||
.,A6CB 84 0F STY $0F |
STY DORES> |
und Quote Modus abschalten |
clear open quote flag |
|||
.,A6CD B1 5F LDA ($5F),Y |
LDADY LOWTR ;IS LINK ZERO? |
Linkadresse HIGH holen |
get next line pointer high byte |
HIGH BYTE OF LINK |
||
.,A6CF F0 43 BEQ $A714 |
BEQ GRODY ;YES, GO TO READY. IFN REALIO,< |
Ja: dann fertig |
if null all done so exit |
END OF PROGRAM |
||
.,A6D1 20 2C A8 JSR $A82C |
JSR ISCNTC> ;LISTEN FOR CONT-C. |
prüft auf Stop-Taste |
do CRTL-C check vector |
CHECK IF CONTROL-C HAS BEEN TYPED |
||
.,A6D4 20 D7 AA JSR $AAD7 |
JSR CRDO ;PRINT CRLF TO START WITH. |
"CR" ausgeben, neue Zeile |
print CR/LF |
NO, PRINT <RETURN> |
||
.,A6D7 C8 INY |
INY |
Zeiger erhöhen |
increment index for line |
|||
.,A6D8 B1 5F LDA ($5F),Y |
LDADY LOWTR |
Zeilenadresse holen (LOW) |
get line number low byte |
GET LINE #, COMPARE WITH END RANGE |
||
.,A6DA AA TAX |
TAX |
und in das X-Reg. schieben |
copy to X |
|||
.,A6DB C8 INY |
INY |
Zeiger erhöhen |
increment index |
|||
.,A6DC B1 5F LDA ($5F),Y |
LDADY LOWTR ;GET LINE NUMBER. |
Zeilenadresse holen (HIGH) |
get line number high byte |
|||
.,A6DE C5 15 CMP $15 |
CMP LINNUM+1 ;SEE IF BEYOND LAST. |
mit Endnummer vergleichen |
compare with temporary integer high byte |
|||
.,A6E0 D0 04 BNE $A6E6 |
BNE TSTDUN ;GO DETERMINE RELATION. |
Gleich? Nein: $A6E6 |
branch if no high byte match |
|||
.,A6E2 E4 14 CPX $14 |
CPX LINNUM ;WAS EQUAL SO TEST LOW ORDER. |
LOW-Nummer vergleichen |
compare with temporary integer low byte |
|||
.,A6E4 F0 02 BEQ $A6E8 |
BEQ TYPLIN ;EQUAL, SO LIST IT. |
Gleich? Ja: $A6E8 |
branch if = last line to do, < will pass next branch else |
ON LAST LINE OF RANGE |
||
.,A6E6 B0 2C BCS $A714 |
TSTDUN: BCS GRODY ;IF LINE IS GR THAN LAST, THEN DUNE. |
Größer: dann fertig |
if greater all done so exit |
FINISHED THE RANGE LIST ONE LINE |
||
.,A6E8 84 49 STY $49 |
TYPLIN: STY LSTPNT |
Y-Reg. Zwischenspeichern |
save index for line |
|||
.,A6EA 20 CD BD JSR $BDCD |
JSR LINPRT ;PRINT AS INT WITHOUT LEADING SPACE. |
Zeilennnummer ausgeben |
print XA as unsigned integer |
PRINT LINE # FROM X,A |
||
.,A6ED A9 20 LDA #$20 |
LDAI " " ;ALWAYS PRINT SPACE AFTER NUMBER. |
' ' Leerzeichen |
space is the next character |
PRINT SPACE AFTER LINE # |
||
.,A6EF A4 49 LDY $49 |
PRIT4: LDY LSTPNT ;GET POINTER TO LINE BACK. |
Y-Reg. wiederholen |
get index for line |
|||
.,A6F1 29 7F AND #$7F |
ANDI 127 |
Bit 7 löschen |
mask top out bit of character |
|||
.,A6F3 20 47 AB JSR $AB47 |
PLOOP: JSR OUTDO ;PRINT CHAR. IFE REALIO-3,< |
Zeichen ausgeben |
go print the character |
|||
.,A6F6 C9 22 CMP #$22 |
CMPI 34 |
'"' Hochkomma ? |
was it " character |
|||
.,A6F8 D0 06 BNE $A700 |
BNE PLOOP1 |
Nein: $A700 |
if not skip the quote handle we are either entering or leaving a pair of quotes |
|||
.,A6FA A5 0F LDA $0F |
COM DORES> ;IF QUOTE, COMPLEMENT FLAG. |
Hochkomma-Flag laden, |
get open quote flag |
|||
.,A6FC 49 FF EOR #$FF |
umdrehen (NOT) |
toggle it |
||||
.,A6FE 85 0F STA $0F |
und wieder abspeichern |
save it back |
||||
.,A700 C8 INY |
PLOOP1: INY |
Zeilenende nach 255 Zeichen ? |
increment index |
|||
.,A701 F0 11 BEQ $A714 |
BEQ GRODY ;IF WE HAVE PRINTED 256 CHARACTERS ;THE PROGRAM MUST BE MISFORMATED IN ;MEMORY DUE TO A BAD LOAD OR BAD ;HARDWARE. LET THE GUY RECOVER |
Nein: dann aufhören |
line too long so just bail out and do a warm start |
|||
.,A703 B1 5F LDA ($5F),Y |
LDADY LOWTR ;GET NEXT CHAR. IS IT ZERO? |
Zeichen holen |
get next byte |
|||
.,A705 D0 10 BNE $A717 |
BNE QPLOP ;YES. END OF LINE. |
kein Zeilenende, dann listen |
if not [EOL] (go print character) was [EOL] |
NOT END OF LINE YET |
||
.,A707 A8 TAY |
TAY |
Akku als Zeiger nach Y |
else clear index |
END OF LINE |
||
.,A708 B1 5F LDA ($5F),Y |
LDADY LOWTR |
Startadresse der nächsten |
get next line pointer low byte |
GET LINK TO NEXT LINE |
||
.,A70A AA TAX |
TAX |
Zeile holen (LOW) und nach X |
copy to X |
|||
.,A70B C8 INY |
INY |
Zeiger erhöhen |
increment index |
|||
.,A70C B1 5F LDA ($5F),Y |
LDADY LOWTR |
Adresse der Zeile (HIGH) |
get next line pointer high byte |
|||
.,A70E 86 5F STX $5F |
STX LOWTR |
als Zeiger merken |
set pointer to line low byte |
POINT TO NEXT LINE |
||
.,A710 85 60 STA $60 |
STA LOWTR+1 |
(speichern nach $5F/60) und |
set pointer to line high byte |
|||
.,A712 D0 B5 BNE $A6C9 |
BNE LIST4 ;BRANCH IF SOMETHING TO LIST. |
weitermachen |
go do next line if not [EOT] else ... |
BRANCH IF NOT END OF PROGRAM |
||
.,A714 4C 86 E3 JMP $E386 |
GRODY: JMP READY |
zum BASIC-WarmstartBASIC Code in Klartextumwandlen |
do warm start |
TO NEXT STATEMENT |
print tokens routine |
|
.,A717 6C 06 03 JMP ($0306) |
;IS IT A TOKEN? |
JMP $A71A |
do uncrunch BASIC tokensuncrunch BASIC tokens, the uncrunch BASIC tokens vector is initialised to point here |
normally A71Astandard token printer |
||
.,A71A 10 D7 BPL $A6F3 |
QPLOP: BPL PLOOP ;NO, HEAD FOR PRINTER. IFE REALIO-3,< |
kein Interpretercode:ausgeben |
just go print it if not token byte else was token byte so uncrunch it |
BRANCH IF NOT A TOKEN |
||
.,A71C C9 FF CMP #$FF |
CMPI PI |
Code für Pi? |
compare with the token for PI. in this case the token is the same as the PI character so it just needs printing |
|||
.,A71E F0 D3 BEQ $A6F3 |
BEQ PLOOP |
Ja: so ausgeben |
just print it if so |
|||
.,A720 24 0F BIT $0F |
BIT DORES ;INSIDE QUOTE MARKS? |
Hochkommamodus ? |
test the open quote flag |
|||
.,A722 30 CF BMI $A6F3 |
BMI PLOOP> ;YES, JUST TYPE THE CHARACTER. |
dann Zeichen so ausgeben |
just go print character if open quote set |
|||
.,A724 38 SEC |
SEC |
Carry setzen (Subtraktion) |
else set carry for subtract |
|||
.,A725 E9 7F SBC #$7F |
SBCI 127 ;GET RID OF SIGN BIT AND ADD 1. |
Offset abziehen |
reduce token range to 1 to whatever |
CONVERT TOKEN TO INDEX |
||
.,A727 AA TAX |
TAX ;MAKE IT A COUNTER. |
Code nach X |
copy token # to X |
|||
.,A728 84 49 STY $49 |
STY LSTPNT ;SAVE POINTER TO LINE. |
Zeichenzeiger merken |
save index for line |
SAVE LINE POINTER |
||
.,A72A A0 FF LDY #$FF |
LDYI 255 ;LOOK AT RES'D WORD LIST. |
Zeiger auf Befehlstabelle |
start from -1, adjust for pre increment |
|||
.,A72C CA DEX |
RESRCH: DEX ;IS THIS THE RES'D WORD? |
erstes Befehlswort? |
decrement token # |
SKIP KEYWORDS UNTIL REACH THIS ONE |
||
.,A72D F0 08 BEQ $A737 |
BEQ PRIT3 ;YES, GO TOSS IT UP.. |
Ja: ausgeben |
if now found go do printing |
|||
.,A72F C8 INY |
RESCR1: INY |
Zeiger erhöhen |
else increment index |
|||
.,A730 B9 9E A0 LDA $A09E,Y |
LDA RESLST,Y, ;END OF ENTRY? |
Offset für X-tes Befehlswort |
get byte from keyword table |
|||
.,A733 10 FA BPL $A72F |
BPL RESCR1 ;NO, CONTINUE PASSING. |
alle Zeichen bis zum letzen |
loop until keyword end marker |
NOT AT END OF KEYWORD YET |
||
.,A735 30 F5 BMI $A72C |
BMI RESRCH |
überlesen (Bit 7 gesetzt) |
go test if this is required keyword, branch always found keyword, it's the next one |
END OF KEYWORD, ALWAYS BRANCHES |
print keyword |
|
.,A737 C8 INY |
PRIT3: INY |
Zeiger erhöhen |
increment keyword table index |
|||
.,A738 B9 9E A0 LDA $A09E,Y |
LDA RESLST,Y |
Befehlswort aus Tabelle holen |
get byte from table |
|||
.,A73B 30 B2 BMI $A6EF |
BMI PRIT4 ;END OF RESERVED WORD. |
letzter Buchstabe: fertig |
go restore index, mask byte and print if byte was end marker |
LAST CHAR OF KEYWORD |
||
.,A73D 20 47 AB JSR $AB47 |
JSR OUTDO ;PRINT IT. |
Zeichen ausgeben |
else go print the character |
|||
.,A740 D0 F5 BNE $A737 |
BNE PRIT3 ;END OF ENTRY? NO, TYPE REST. PAGE THE "FOR" STATEMENT.;; A "FOR" ENTRY ON THE STACK HAS THE FOLLOWING FORMAT: ; ; LOW ADDRESS ; TOKEN (FORTK) 1 BYTE ; A POINTER TO THE LOOP VARIABLE 2 BYTES ; THE STEP 4+ADDPRC BYTES ; A BYTE REFLECTING THE SIGN OF THE INCREMENT 1 BYTE ; THE UPPER VALUE 4+ADDPRC BYTES ; THE LINE NUMBER OF THE "FOR" STATEMENT 2 BYTES ; A TEXT POINTER INTO THE "FOR" STATEMENT 2 BYTES ; HIGH ADDRESS ; ; TOTAL 16+2*ADDPRC BYTES. ; |
nächsten Buchstaben ausgebenBASIC-Befehl FOR |
go get next character, branch alwaysperform FOR |
...ALWAYS"FOR" STATEMENTFOR PUSHES 18 BYTES ON THE STACK:2 -- TXTPTR 2 -- LINE NUMBER 5 -- INITIAL (CURRENT) FOR VARIABLE VALUE 1 -- STEP SIGN 5 -- STEP VALUE 2 -- ADDRESS OF FOR VARIABLE IN VARTAB 1 -- FOR TOKEN ($81) |
FOR command |
|
.,A742 A9 80 LDA #$80 |
FOR: LDAI 128 ;DON'T RECOGNIZE |
Wert laden und |
set FNX |
|||
.,A744 85 10 STA $10 |
STA SUBFLG ;SUBSCRIPTED VARIABLES. |
Integer sperren |
set subscript/FNX flag |
SUBSCRIPTS NOT ALLOWED |
||
.,A746 20 A5 A9 JSR $A9A5 |
JSR LET ;READ THE VARIABLE AND ASSIGN IT ;THE CORRECT INITIAL VALUE AND STORE ;A POINTER TO THE VARIABLE IN VARPNT. |
LET, setzt FOR-Variable |
perform LET |
DO <VAR> = <EXP>, STORE ADDR IN FORPNT |
||
.,A749 20 8A A3 JSR $A38A |
JSR FNDFOR ;PNTR IS IN VARPNT, AND FORPNT. |
sucht offene FOR-NEXT-Schlei. |
search the stack for FOR or GOSUB activity |
IS THIS FOR VARIABLE ACTIVE? |
||
.,A74C D0 05 BNE $A753 |
BNE NOTOL ;IF NO MATCH, DON'T ELIMINATE ANYTHING. |
nicht gefunden: $A753 |
branch if FOR, this variable, not found FOR, this variable, was found so first we dump the old one |
NO |
||
.,A74E 8A TXA |
TXA ;MAKE IT ARITHMETICAL. |
X-Reg. nach Akku |
copy index |
YES, CANCEL IT AND ENCLOSED LOOPS |
||
.,A74F 69 0F ADC #$0F |
ADCI FORSIZ-3 ;ELIMINATE ALMOST ALL. |
Stapelzejger erhöhen |
add FOR structure size-2 |
CARRY=1, THIS ADDS 16 |
||
.,A751 AA TAX |
TAX ;NOTE C=1, THEN PLA, PLA. |
Akku zurück nach X-Reg. und |
copy to index |
X WAS ALREADY S+2 |
||
.,A752 9A TXS |
TXS ;MANIFEST. |
in den Stapelzeiger |
set stack (dump FOR structure (-2 bytes)) |
|||
.,A753 68 PLA |
NOTOL: PLA ;GET RID OF NEWSTT RETURN ADDRESS |
Rücksprungadresse vom Stapel |
pull return address |
POP RETURN ADDRESS TOO |
||
.,A754 68 PLA |
PLA ;IN CASE THIS IS A TOTALLY NEW ENTRY. |
holen (LOW und HIGH) |
pull return address |
|||
.,A755 A9 09 LDA #$09 |
LDAI 8+ADDPRC |
Wert für Prüfung laden |
we need 18d bytes ! |
BE CERTAIN ENOUGH ROOM IN STACK |
||
.,A757 20 FB A3 JSR $A3FB |
JSR GETSTK ;MAKE SURE 16 BYTES ARE AVAILABLE. |
prüft auf Platz im Stapel |
check room on stack for 2*A bytes |
|||
.,A75A 20 06 A9 JSR $A906 |
JSR DATAN ;GET A COUNT IN [Y] OF THE NUMBER OF ;CHACRACTERS LEFT IN THE "FOR" STATEMENT ;[TXTPTR] IS UNAFFECTED. |
sucht nächstes BAS.-Statement |
scan for next BASIC statement ([:] or [EOL]) |
SCAN AHEAD TO NEXT STATEMENT |
||
.,A75D 18 CLC |
CLC ;PREP TO ADD. |
Carry löschen (Addition) |
clear carry for add |
PUSH STATEMENT ADDRESS ON STACK |
||
.,A75E 98 TYA |
TYA ;SAVE IT FOR PUSHING. |
CHRGET-Zeiger und Offset |
copy index to A |
|||
.,A75F 65 7A ADC $7A |
ADC TXTPTR |
= Startadresse der Schleife |
add BASIC execute pointer low byte |
|||
.,A761 48 PHA |
PHA |
auf Stapel speichern |
push onto stack |
|||
.,A762 A5 7B LDA $7B |
LDA TXTPTR+1 |
HIGH-Byte holen und |
get BASIC execute pointer high byte |
|||
.,A764 69 00 ADC #$00 |
ADCI 0 |
Übertrag addieren und |
add carry |
|||
.,A766 48 PHA |
PHA |
auf den Stapel legen |
push onto stack |
|||
.,A767 A5 3A LDA $3A |
PSHWD CURLIN ;PUT LINE NUMBER ON STACK. |
Aktuelle |
get current line number high byte |
PUSH LINE NUMBER ON STACK |
||
.,A769 48 PHA |
Zeilennummer laden und auf |
push onto stack |
||||
.,A76A A5 39 LDA $39 |
den Stapel schieben |
get current line number low byte |
||||
.,A76C 48 PHA |
(LOW und HIGH-Byte) |
push onto stack |
||||
.,A76D A9 A4 LDA #$A4 |
SYNCHK TOTK ;"TO" IS NECESSARY. |
'TO' - Code |
set "TO" token |
|||
.,A76F 20 FF AE JSR $AEFF |
prüft auf Code |
scan for CHR$(A), else do syntax error then warm start |
REQUIRE "TO" |
|||
.,A772 20 8D AD JSR $AD8D |
JSR CHKNUM ;VALUE MUST BE A NUMBER. |
prüft ob numerische Variable |
check if source is numeric, else do type mismatch |
<VAR> = <EXP> MUST BE NUMERIC |
||
.,A775 20 8A AD JSR $AD8A |
JSR FRMNUM ;GET UPPER VALUE INTO FAC. |
numerischer Ausdruck nach FAC |
evaluate expression and check is numeric, else do type mismatch |
GET FINAL VALUE, MUST BE NUMERIC |
||
.,A778 A5 66 LDA $66 |
LDA FACSGN ;PACK FAC. |
Vorzeichenbyte von FAC holen |
get FAC1 sign (b7) |
PUT SIGN INTO VALUE IN FAC |
||
.,A77A 09 7F ORA #$7F |
ORAI 127 |
Bit 0 bis 6 setzen |
set all non sign bits |
|||
.,A77C 25 62 AND $62 |
AND FACHO |
mit $62 angleichen |
and FAC1 mantissa 1 |
|||
.,A77E 85 62 STA $62 |
STA FACHO ;SET PACKED SIGN BIT. |
und abspeichern |
save FAC1 mantissa 1 |
|||
.,A780 A9 8B LDA #$8B |
LDWDI LDFONE |
Rücksprungadresse laden |
set return address low byte |
SET UP FOR RETURN |
low A78B |
|
.,A782 A0 A7 LDY #$A7 |
(LOW und HIGH) |
set return address high byte |
TO STEP |
high A78B |
||
.,A784 85 22 STA $22 |
STWD INDEX1 |
und Zwischenspeichern |
save return address low byte |
|||
.,A786 84 23 STY $23 |
(LOW und HIGH) |
save return address high byte |
||||
.,A788 4C 43 AE JMP $AE43 |
JMP FORPSH ;PUT FAC ONTO STACK, PACKED. |
Schleifenendwert auf Stapel |
round FAC1 and put on stack, returns to next instruction |
RETURNS BY "JMP (INDEX)""STEP" PHRASE OF "FOR" STATEMENT |
||
.,A78B A9 BC LDA #$BC |
LDFONE: LDWDI FONE ;PUT 1.0 INTO FAC. |
Zeiger auf Konstante 1 setzen |
set 1 pointer low address, default step size |
STEP DEFAULT=1 |
low B9BC |
|
.,A78D A0 B9 LDY #$B9 |
(Ersatzwert für STEP) |
set 1 pointer high address |
high B9BC |
|||
.,A78F 20 A2 BB JSR $BBA2 |
JSR MOVFM |
als Default-STEP-Wert in FAC |
unpack memory (AY) into FAC1 |
|||
.,A792 20 79 00 JSR $0079 |
JSR CHRGOT |
CHRGOT: letztes Zeichen holen |
scan memory |
|||
.,A795 C9 A9 CMP #$A9 |
CMPI STEPTK ;A STEP IS GIVEN? |
'STEP' - Code? |
compare with STEP token |
|||
.,A797 D0 06 BNE $A79F |
BNE ONEON ;NO. ASSUME 1.0. |
kein STEP-Wert: $A79F |
if not "STEP" continue was step so .... |
USE DEFAULT VALUE OF 1.0 |
||
.,A799 20 73 00 JSR $0073 |
JSR CHRGET ;YES. ADVANCE POINTER. |
CHRGET nächstes Zeichen holen |
increment and scan memory |
STEP SPECIFIED, GET IT |
||
.,A79C 20 8A AD JSR $AD8A |
JSR FRMNUM ;READ THE STEP. |
numerischer Ausdruck nach FAC |
evaluate expression and check is numeric, else do type mismatch |
|||
.,A79F 20 2B BC JSR $BC2B |
ONEON: JSR SIGN ;GET SIGN IN ACCA. |
holt Vorzeichenbyte |
get FAC1 sign, return A = $FF -ve, A = $01 +ve |
|||
.,A7A2 20 38 AE JSR $AE38 |
JSR PUSHF ;PUSH FAC ONTO STACK (THRU A). |
Vorz. und STEP-Wert auf Stack |
push sign, round FAC1 and put on stack |
|||
.,A7A5 A5 4A LDA $4A |
PSHWD FORPNT ;PUT PNTR TO VARIABLE ON STACK. |
Zeiger auf Variablenwert |
get FOR/NEXT variable pointer high byte |
|||
.,A7A7 48 PHA |
(LOW) auf den Stapel |
push on stack |
||||
.,A7A8 A5 49 LDA $49 |
Zeiger (HIGH) |
get FOR/NEXT variable pointer low byte |
||||
.,A7AA 48 PHA |
auf den Stapel |
push on stack |
||||
.,A7AB A9 81 LDA #$81 |
NXTCON: LDAI FORTK ;PUT A FORTK ONTO STACK. |
und FOR-Code |
get FOR token |
FOR block code |
||
.,A7AD 48 PHA |
PHA ; BNEA NEWSTT ;SIMULATE BNE TO NEWSTT. JUST FALL IN. PAGE NEW STATEMENT FETCHER.;; BACK HERE FOR NEW STATEMENT. CHARACTER POINTED TO BY TXTPTR ; IS ":" OR END-OF-LINE. THE ADDRESS OF THIS LOC IS LEFT ; ON THE STACK WHEN A STATEMENT IS EXECUTED SO THAT ; IT CAN MERELY DO A RTS WHEN IT IS DONE. ; NEWSTT: IFN REALIO,< |
auf den Stapel legenInterpreterschleife |
push on stackinterpreter inner loop |
PERFORM NEXT STATEMENT |
execute next statement |
|
.,A7AE 20 2C A8 JSR $A82C |
JSR ISCNTC> ;LISTEN FOR CONTROL-C. |
prüft auf Stop-Taste |
do CRTL-C check vector |
SEE IF CONTROL-C HAS BEEN TYPED |
||
.,A7B1 A5 7A LDA $7A |
LDWD TXTPTR ;LOOK AT CURRENT CHARACTER. |
CHRGET Zeiger (LOW und HIGH) |
get the BASIC execute pointer low byte |
NO, KEEP EXECUTING |
||
.,A7B3 A4 7B LDY $7B |
IFN BUFPAG,< |
laden |
get the BASIC execute pointer high byte |
|||
.,A7B5 C0 02 CPY #$02 |
CPYI BUFPAG> ;SEE IF IT WAS DIRECT BY CHECK FOR BUF'S PAGE NUMBER |
Direkt-Modus? |
compare the high byte with $02xx |
|||
.,A7B7 EA NOP |
No OPeration |
unused byte |
||||
.,A7B8 F0 04 BEQ $A7BE |
BEQ DIRCON |
ja: $A7BE |
if immediate mode skip the continue pointer save |
IN DIRECT MODE |
||
.,A7BA 85 3D STA $3D |
STWD OLDTXT ;SAVE IN CASE OF RESTART BY INPUT. |
als Zeiger für CONT |
save the continue pointer low byte |
IN RUNNING MODE |
||
.,A7BC 84 3E STY $3E |
IFN BUFPAG,<DIRCON:> |
merken |
save the continue pointer high byte |
|||
.,A7BE A0 00 LDY #$00 |
LDYI 0 IFE BUFPAG,<DIRCON:> |
Zeiger setzen |
clear the index |
|||
.,A7C0 B1 7A LDA ($7A),Y |
LDADY TXTPTR |
laufendes Zeichen holen |
get a BASIC byte |
END OF LINE YET? |
||
.,A7C2 D0 43 BNE $A807 |
BNE MORSTS ;NOT NULL -- CHECK WHAT IT IS |
nicht Zeilenende? |
if not [EOL] go test for ":" |
NO |
||
.,A7C4 A0 02 LDY #$02 |
LDYI 2 ;LOOK AT LINK. |
Zeiger neu setzen |
else set the index |
YES, SEE IF END OF PROGRAM |
||
.,A7C6 B1 7A LDA ($7A),Y |
LDADY TXTPTR ;IS LINK 0? |
Programmende? |
get next line pointer high byte |
|||
.,A7C8 18 CLC |
CLC ;CLEAR CARRY FOR ENDCON AND MATH THAT FOLLOWS |
Flag für END setzen |
clear carry for no "BREAK" message |
|||
.,A7C9 D0 03 BNE $A7CE |
JEQ ENDCON ;YES - RAN OFF THE END. |
Kein Programmende: $A7CE |
branch if not end of program |
|||
.,A7CB 4C 4B A8 JMP $A84B |
ja: dann END ausführen |
else go to immediate mode,was immediate or [EOT] marker |
YES, END OF PROGRAM |
|||
.,A7CE C8 INY |
INY ;PUT LINE NUMBER IN CURLIN. |
Zeiger erhöhen |
increment index |
|||
.,A7CF B1 7A LDA ($7A),Y |
LDADY TXTPTR |
laufende Zeilennummer |
get line number low byte |
GET LINE # OF NEXT LINE |
||
.,A7D1 85 39 STA $39 |
STA CURLIN |
(LOW) nach $39 |
save current line number low byte |
|||
.,A7D3 C8 INY |
INY |
Zeiger auf nächstes Byte |
increment index |
|||
.,A7D4 B1 7A LDA ($7A),Y |
LDADY TXTPTR |
laufende Zeilennummer |
get line # high byte |
|||
.,A7D6 85 3A STA $3A |
STA CURLIN+1 |
(HIGH) nach $3A |
save current line number high byte |
|||
.,A7D8 98 TYA |
TYA |
Zeiger nach Akku |
A now = 4 |
ADJUST TXTPTR TO START |
||
.,A7D9 65 7A ADC $7A |
ADC TXTPTR |
Programmzeiger auf |
add BASIC execute pointer low byte, now points to code |
OF NEW LINE |
||
.,A7DB 85 7A STA $7A |
STA TXTPTR |
Programmzeile setzen |
save BASIC execute pointer low byte |
|||
.,A7DD 90 02 BCC $A7E1 |
BCC GONE |
C=0: Erhöhung umgehen |
branch if no overflow |
|||
.,A7DF E6 7B INC $7B |
INC TXTPTR+1 |
Programmzeiger (HIGH) erhöhen |
else increment BASIC execute pointer high byte |
|||
.,A7E1 6C 08 03 JMP ($0308) |
Statement ausführen |
do start new BASIC codestart new BASIC code, the start new BASIC code vector is initialised to point here |
normally A7E4execute a statement |
|||
.,A7E4 20 73 00 JSR $0073 |
GONE: JSR CHRGET ;GET THE STATEMENT TYPE. |
CHRGET nächstes Zeichen holen |
increment and scan memory |
GET FIRST CHR OF STATEMENT |
||
.,A7E7 20 ED A7 JSR $A7ED |
JSR GONE3 |
Statement ausführen |
go interpret BASIC code from BASIC execute pointer |
AND START PROCESSING |
||
.,A7EA 4C AE A7 JMP $A7AE |
JMP NEWSTT |
zurück zur Interpreterschlei.BASIC-Statement ausführen |
loopgo interpret BASIC code from BASIC execute pointer |
BACK FOR MOREEXECUTE A STATEMENT(A) IS FIRST CHAR OF STATEMENTCARRY IS SET |
execute command in A |
|
.,A7ED F0 3C BEQ $A82B |
GONE3: BEQ ISCRTS ;IF TERMINATOR, TRY AGAIN. ;NO NEED TO SET UP CARRY SINCE IT WILL ;BE ON IF NON-NUMERIC AND NUMERICS ;WILL CAUSE A SYNTAX ERROR LIKE THEY SHOULD |
Zeilenende, dann fertig |
if the first byte is null just exit |
END OF LINE, NULL STATEMENT |
||
.,A7EF E9 80 SBC #$80 |
GONE2: SBCI ENDTK ;" ON ... GOTO AND GOSUB" COME HERE. |
Token? |
normalise the token |
FIRST CHAR A TOKEN? |
||
.,A7F1 90 11 BCC $A804 |
BCC GLET |
nein: dann zum LET-Befehl |
if wasn't token go do LET |
NOT TOKEN, MUST BE "LET" |
||
.,A7F3 C9 23 CMP #$23 |
CMPI SCRATK-ENDTK+1 |
NEW? |
compare with token for TAB(-$80 |
STATEMENT-TYPE TOKEN? |
||
.,A7F5 B0 17 BCS $A80E |
BCS SNERRX ;SOME RES'D WORD BUT NOT ;A STATEMENT RES'D WORD. |
Funktions-Token oder GO TO |
branch if >= TAB( |
NO, SYNTAX ERROR |
||
.,A7F7 0A ASL |
ASL A, ;MULTIPLY BY TWO. |
BASIC-Befehl, Code mal 2 |
*2 bytes per vector |
DOUBLE TO GET INDEX |
||
.,A7F8 A8 TAY |
TAY ;MAKE AN INDEX. |
als Zeiger ins Y-Reg. |
copy to index |
INTO ADDRESS TABLE |
||
.,A7F9 B9 0D A0 LDA $A00D,Y |
LDA STMDSP+1,Y |
Befehlsadresse (LOW und |
get vector high byte |
|||
.,A7FC 48 PHA |
PHA |
HIGH) aus Tabelle |
push on stack |
PUT ADDRESS ON STACK |
||
.,A7FD B9 0C A0 LDA $A00C,Y |
LDA STMDSP,Y |
holen und als |
get vector low byte |
|||
.,A800 48 PHA |
PHA ;PUT DISP ADDR ONTO STACK. |
Rücksprungadresse auf Stapel |
push on stack |
|||
.,A801 4C 73 00 JMP $0073 |
JMP CHRGET |
Zeichen und Befehl ausführen |
increment and scan memory and return. the return in this case calls the command code, the return from that will eventually return to the interpreter inner loop above |
GET NEXT CHR & RTS TO ROUTINE |
||
.,A804 4C A5 A9 JMP $A9A5 |
GLET: JMP LET ;MUST BE A LET |
zum LET-Befehl |
perform LET was not [EOL] |
MUST BE <VAR> = <EXP> |
||
.,A807 C9 3A CMP #$3A |
MORSTS: CMPI ":" |
':' ist es Doppelpunkt? |
comapre with ":" |
colon |
||
.,A809 F0 D6 BEQ $A7E1 |
BEQ GONE ;IF A ":" CONTINUE STATEMENT |
ja: $A7E1 |
if ":" go execute new code else ... |
|||
.,A80B 4C 08 AF JMP $AF08 |
SNERR1: JMP SNERR ;NEITHER 0 OR ":" SO SYNTAX ERROR |
sonst 'SYNTAX ERROR'prüft auf 'GO' 'TO' Code |
do syntax error then warm start token was >= TAB( |
|||
.,A80E C9 4B CMP #$4B |
SNERRX: CMPI GOTK-ENDTK |
'GO' (minus $80) |
compare with the token for GO |
GO code |
||
.,A810 D0 F9 BNE $A80B |
BNE SNERR1 |
nein: 'SYNTAX ERROR' |
if not "GO" do syntax error then warm start else was "GO" |
|||
.,A812 20 73 00 JSR $0073 |
JSR CHRGET ;READ IN THE CHARACTER AFTER "GO " |
nächstes Zeichen holen |
increment and scan memory |
|||
.,A815 A9 A4 LDA #$A4 |
SYNCHK TOTK |
'TO' |
set "TO" token |
TO code |
||
.,A817 20 FF AE JSR $AEFF |
prüft auf Code |
scan for CHR$(A), else do syntax error then warm start |
||||
.,A81A 4C A0 A8 JMP $A8A0 |
JMP GOTO PAGE RESTORE,STOP,END,CONTINUE,NULL,CLEAR. |
zum GOTO-BefehlBASIC-Befehl RESTORE |
perform GOTOperform RESTORE |
"RESTORE" STATEMENT |
do GOTORESTORE command |
|
.,A81D 38 SEC |
RESTOR: SEC |
Carry setzen (Subtraktion) |
set carry for subtract |
SET DATPTR TO BEGINNING OF PROGRAM |
||
.,A81E A5 2B LDA $2B |
LDA TXTTAB |
Programmstartzeiger (LOW) |
get start of memory low byte |
|||
.,A820 E9 01 SBC #$01 |
SBCI 1 |
laden und davon 1 abziehen |
-1 |
|||
.,A822 A4 2C LDY $2C |
LDY TXTTAB+1 |
und HIGH-Byte holen |
get start of memory high byte |
|||
.,A824 B0 01 BCS $A827 |
BCS RESFIN |
branch if no rollunder |
||||
.,A826 88 DEY |
DEY |
LOW-Byte -1 |
else decrement high byte |
SET DATPTR TO Y,A |
||
.,A827 85 41 STA $41 |
RESFIN: STWD DATPTR ;READ FINISHES COME TO "RESFIN". |
als DATA-Zeiger |
set DATA pointer low byte |
|||
.,A829 84 42 STY $42 |
abspeichern |
set DATA pointer high byte |
||||
.,A82B 60 RTS |
ISCRTS: RTS IFE REALIO-1,< ISCNTC: LDAI 1 BIT ^O13500 BMI ISCRTS LDXI 8 LDAI 3 CMPI 3> IFE REALIO-2,< ISCNTC: LDA ^O176000 REPEAT 4,<NOP> LSR A, BCC ISCRTS JSR INCHR ;EAT CHAR THAT WAS TYPED CMPI 3> ;WAS IT A CONTROL-C?? IFE REALIO-4,< ISCNTC: LDA ^O140000 ;CHECK THE CHARACTER CMPI ^O203 BEQ ISCCAP RTS ISCCAP: JSR INCHR |
Rücksprungprüft auf Stop-Taste |
do CRTL-C check vector |
SEE IF CONTROL-C TYPED |
||
.,A82C 20 E1 FF JSR $FFE1 |
CMPI ^O203> |
Stop-Taste abfragenBASIC-Befehl STOP |
scan stop keyperform STOP |
"STOP" STATEMENT |
test stop keySTOP command |
|
.,A82F B0 01 BCS $A832 |
STOP: BCS STOPC ;MAKE [C] NONZERO AS A FLAG. |
C=1: Flag für STOPBASIC-Befehl END |
if carry set do BREAK instead of just ENDperform END |
CARRY=1 TO FORCE PRINTING "BREAK AT..""END" STATEMENT |
END command |
|
.,A831 18 CLC |
END: CLC |
C=0 Flag für END |
clear carry |
CARRY=0 TO AVOID PRINTING MESSAGE |
||
.,A832 D0 3C BNE $A870 |
STOPC: BNE CONTRT ;RETURN IF NOT CONT-C OR ;IF NO TERMINATOR FOR STOP OR END. ;[C]=0 SO WILL NOT PRINT "BREAK". |
RUN/STOP nicht gedrückt: RTS |
return if wasn't CTRL-C |
IF NOT END OF STATEMENT, DO NOTHING |
||
.,A834 A5 7A LDA $7A |
LDWD TXTPTR |
Programmzeiger laden |
get BASIC execute pointer low byte |
|||
.,A836 A4 7B LDY $7B |
IFN BUFPAG,< |
(LOW und HIGH-Byte) |
get BASIC execute pointer high byte |
|||
.,A838 A6 3A LDX $3A |
LDX CURLIN+1 |
Direkt-Modus? |
get current line number high byte |
|||
.,A83A E8 INX |
INX> |
(Zeilennummer -1) |
increment it |
RUNNING? |
||
.,A83B F0 0C BEQ $A849 |
BEQ DIRIS |
ja: $A849 |
branch if was immediate mode |
NO, DIRECT MODE |
||
.,A83D 85 3D STA $3D |
STWD OLDTXT |
als Zeiger für CONT setzen |
save continue pointer low byte |
|||
.,A83F 84 3E STY $3E |
(LOW und HIGH) |
save continue pointer high byte |
||||
.,A841 A5 39 LDA $39 |
STPEND: LDWD CURLIN |
Nummer der laufenden Zeile |
get current line number low byte |
|||
.,A843 A4 3A LDY $3A |
holen (LOW und HIGH) |
get current line number high byte |
||||
.,A845 85 3B STA $3B |
STWD OLDLIN |
und als Zeilennummer für |
save break line number low byte |
|||
.,A847 84 3C STY $3C |
CONT merken |
save break line number high byte |
||||
.,A849 68 PLA |
DIRIS: PLA ;POP OFF NEWSTT ADDR. |
Rücksprungadresse |
dump return address low byte |
|||
.,A84A 68 PLA |
PLA |
vom Stapel entfernen |
dump return address high byte |
|||
.,A84B A9 81 LDA #$81 |
ENDCON: LDWDI BRKTXT |
Zeiger auf Startadresse |
set [CR][LF]"BREAK" pointer low byte |
" BREAK" AND BELL |
low A381 |
|
.,A84D A0 A3 LDY #$A3 |
IFN REALIO,< LDXI 0 STX CNTWFL> |
BREAK setzen |
set [CR][LF]"BREAK" pointer high byte |
high A381 |
||
.,A84F 90 03 BCC $A854 |
BCC GORDY ;CARRY CLEAR SO DON'T PRINT "BREAK". |
END Flag? |
if was program end skip the print string |
|||
.,A851 4C 69 A4 JMP $A469 |
JMP ERRFIN |
nein: 'BREAK IN XXX' ausgeben |
print string and do warm start |
|||
.,A854 4C 86 E3 JMP $E386 |
GORDY: JMP READY ;TYPE "READY". IFE REALIO,< DDT: PLA ;GET RID OF NEWSTT RETURN. PLA HRRZ 14,.JBDDT## JRST 0(14)> |
zum BASIC-WarmstartBASIC-Befehl CONT |
do warm startperform CONT |
"CONT" COMMAND |
CONT command |
|
.,A857 D0 17 BNE $A870 |
CONT: BNE CONTRT ;MAKE SURE THERE IS A TERMINATOR. |
Kein Trennzeichen: SYNTAX ERR |
exit if following byte to allow syntax error |
IF NOT END OF STATEMENT, DO NOTHING |
||
.,A859 A2 1A LDX #$1A |
LDXI ERRCN ;CONTINUE ERROR. |
Fehlernr. für 'CAN'T CONTINUE |
error code $1A, can't continue error |
error number |
||
.,A85B A4 3E LDY $3E |
LDY OLDTXT+1 ;A STORED TXTPTR OF ZERO IS SETUP ;BY STKINI AND INDICATES THERE IS ;NOTHING TO CONTINUE. |
CONT gesperrt? |
get continue pointer high byte |
MEANINGFUL RE-ENTRY? |
||
.,A85D D0 03 BNE $A862 |
JEQ ERROR ;"STOP", "END", TYPING CRLF TO |
nein: $A862 |
go do continue if we can |
YES |
||
.,A85F 4C 37 A4 JMP $A437 |
;"INPUT" AND ^C SETUP OLDTXT. |
Fehlermeldung ausgeben |
else do error #X then warm start we can continue so ... |
NO |
||
.,A862 A5 3D LDA $3D |
LDA OLDTXT |
CONT-Zeiger (LOW) laden |
get continue pointer low byte |
RESTORE TXTPTR |
||
.,A864 85 7A STA $7A |
STWD TXTPTR |
und CONT-Zeiger als Programm- |
save BASIC execute pointer low byte |
|||
.,A866 84 7B STY $7B |
zeiger abspeichern |
save BASIC execute pointer high byte |
||||
.,A868 A5 3B LDA $3B |
LDWD OLDLIN |
und |
get break line low byte |
RESTORE LINE NUMBER |
||
.,A86A A4 3C LDY $3C |
Zeilennummer wieder |
get break line high byte |
||||
.,A86C 85 39 STA $39 |
STWD CURLIN |
setzen |
set current line number low byte |
|||
.,A86E 84 3A STY $3A |
(LOW- und HIGH-Byte) |
set current line number high byte |
||||
.,A870 60 RTS |
CONTRT: RTS ;RETURN TO CALLER. IFN NULCMD,< NULL: JSR GETBYT BNE CONTRT ;MAKE SURE THERE IS TERMINATOR. INX CPXI 240 ;IS THE NUMBER REASONABLE? BCS FCERR1 ;"FUNCTION CALL" ERROR. DEX ;BACK -1 STX NULCNT RTS FCERR1: JMP FCERR> PAGE LOAD AND SAVE SUBROUTINES.IFE REALIO-1,< ;KIM CASSETTE I/OSAVE: TSX ;SAVE STACK POINTER STX INPFLG LDAI STKEND-256-200 STA ^O362 ;SETUP DUMMY STACK FOR KIM MONITOR LDAI 254 ;MAKE ID BYTE EQUAL TO FF HEX STA ^O13771 ;STORE INTO KIM ID LDWD TXTTAB ;START DUMPING FROM TXTTAB STWD ^O13765 ;SETUP SAL,SAH LDWD VARTAB ;STOP AT VARTAB STWD ^O13767 ;SETUP EAL,EAH JMP ^O14000 RETSAV: LDX INPFLG ;RESORE THE REAL STACK POINTER TXS LDWDI TAPMES ;SAY IT WAS DONE JMP STROUT GLOAD: DT"LOADED" 0 TAPMES: DT"SAVED" ACRLF 0 PATSAV: BLOCK 20 LOAD: LDWD TXTTAB ;START DUMPING IN AT TXTTAB STWD ^O13765 ;SETUP SAL,SAH LDAI 255 STA ^O13771 LDWDI RTLOAD STWD ^O1 ;SET UP RETURN ADDRESS FOR LOAD JMP ^O14163 ;GO READ THE DATA IN RTLOAD: LDXI STKEND-256 ;RESET THE STACK TXS LDWDI READY STWD ^O1 LDWDI GLOAD ;TELL HIM IT WORKED JSR STROUT LDXY ^O13755 ;GET LAST LOCATION TXA ;ITS ONE TOO BIG BNE DECVRT ;DECREMENT [X,Y] NOP DECVRT: NOP STXY VARTAB ;SETUP NEW VARIABLE LOCATION JMP FINI> ;RELINK THE PROGRAM IFE REALIO-4,< SAVE: SEC ;CALCLUATE PROGRAM SIZE IN POKER LDA VARTAB SBC TXTTAB STA POKER LDA VARTAB+1 SBC TXTTAB+1 STA POKER+1 JSR VARTIO JSR CQCOUT ;WRITE PROGRAM SIZE [POKER] JSR PROGIO JMP CQCOUT ;WRITE PROGRAM. LOAD: JSR VARTIO JSR CQCSIN ;READ SIZE OF PROGRAM INTO POKER CLC LDA TXTTAB ;CALCULATE VARTAB FROM SIZE AND ADC POKER ;TXTTAB STA VARTAB LDA TXTTAB+1 ADC POKER+1 STA VARTAB+1 JSR PROGIO JSR CQCSIN ;READ PROGRAM. LDWDI TPDONE JSR STROUT JMP FINI TPDONE: DT"LOADED" 0 VARTIO: LDWDI POKER STWD ^O74 LDAI POKER+2 STWD ^O76 RTS PROGIO: LDWD TXTTAB STWD ^O74 LDWD VARTAB STWD ^O76 RTS> PAGE RUN,GOTO,GOSUB,RETURN. |
RücksprungBASIC-Befehl RUN |
perform RUN |
"RUN" COMMAND |
RUN command |
|
.,A871 08 PHP |
Statusregister retten |
save status |
SAVE STATUS WHILE SUBTRACTING |
|||
.,A872 A9 00 LDA #$00 |
Wert laden und |
no control or kernal messages |
||||
.,A874 20 90 FF JSR $FF90 |
Flag für Programmodus setzen |
control kernal messages |
||||
.,A877 28 PLP |
Statusregister zurückholen |
restore status |
GET STATUS AGAIN (FROM CHRGET) |
|||
.,A878 D0 03 BNE $A87D |
RUN: JEQ RUNC ;IF NO LINE # ARGUMENT. |
weitere Zeichen (Zeilennr.)? |
branch if RUN n |
PROBABLY A LINE NUMBER |
||
.,A87A 4C 59 A6 JMP $A659 |
Programmzeiger setzen, CLR |
reset execution to start, clear variables, flush stack and return |
START AT BEGINNING OF PROGRAM |
|||
.,A87D 20 60 A6 JSR $A660 |
JSR CLEARC ;CLEAN UP -- RESET THE STACK. |
CLR-Befehl |
go do "CLEAR" |
CLEAR VARIABLES |
do CLR |
|
.,A880 4C 97 A8 JMP $A897 |
JMP RUNC2 ;MUST REPLACE RTS ADDR. ; ; A GOSUB ENTRY ON THE STACK HAS THE FOLLOWING FORMAT: ; ; LOW ADDRESS: ; THE GOSUTK ONE BYTE ; THE LINE NUMBER OF THE GOSUB STATEMENT TWO BYTES ; A POINTER INTO THE TEXT OF THE GOSUB TWO BYTES ; ; HIGH ADDRESS. ; ; TOTAL FIVE BYTES. ; |
GOTO-BefehlBASIC-Befehl GOSUB |
get n and do GOTO nperform GOSUB |
JOIN GOSUB STATEMENT"GOSUB" STATEMENTLEAVES 7 BYTES ON STACK:2 -- RETURN ADDRESS (NEWSTT) 2 -- TXTPTR 2 -- LINE # 1 -- GOSUB TOKEN ($B0) |
do GOTOGOSUB command |
|
.,A883 A9 03 LDA #$03 |
GOSUB: LDAI 3 |
Wert für Prüfung |
need 6 bytes for GOSUB |
BE SURE ENOUGH ROOM ON STACK |
||
.,A885 20 FB A3 JSR $A3FB |
JSR GETSTK ;MAKE SURE THERE IS ROOM. |
prüft auf Platz im Stapel |
check room on stack for 2*A bytes |
|||
.,A888 A5 7B LDA $7B |
PSHWD TXTPTR ;PUSH ON THE TEXT POINTER. |
Programmzeiger (LOW- |
get BASIC execute pointer high byte |
|||
.,A88A 48 PHA |
und HIGH-Byte) laden |
save it |
||||
.,A88B A5 7A LDA $7A |
und auf den |
get BASIC execute pointer low byte |
||||
.,A88D 48 PHA |
Stapel retten |
save it |
||||
.,A88E A5 3A LDA $3A |
PSHWD CURLIN ;PUSH ON THE CURRENT LINE NUMBER. |
Zeilennummer laden (HIGH) |
get current line number high byte |
|||
.,A890 48 PHA |
und auf den Stapel legen |
save it |
||||
.,A891 A5 39 LDA $39 |
Zeilennummer LOW laden |
get current line number low byte |
||||
.,A893 48 PHA |
und auf den Stapel legen |
save it |
||||
.,A894 A9 8D LDA #$8D |
LDAI GOSUTK |
'GOSUB'-Code laden |
token for GOSUB |
|||
.,A896 48 PHA |
PHA ;PUSH ON A GOSUB TOKEN. |
und auf den Stapel legen |
save it |
|||
.,A897 20 79 00 JSR $0079 |
RUNC2: JSR CHRGOT ;GET CHARACTER AND SET CODES FOR LINGET. |
CHRGOT: letztes Zeichen holen |
scan memory |
|||
.,A89A 20 A0 A8 JSR $A8A0 |
JSR GOTO ;USE RTS SCHEME TO "NEWSTT". |
GOTO-Befehl |
perform GOTO |
|||
.,A89D 4C AE A7 JMP $A7AE |
JMP NEWSTT |
zur InterpreterschleifeBASIC-Befehl GOTO |
go do interpreter inner loopperform GOTO |
"GOTO" STATEMENTALSO USED BY "RUN" AND "GOSUB" |
GOTO command |
|
.,A8A0 20 6B A9 JSR $A96B |
GOTO: JSR LINGET ;PICK UP THE LINE NUMBER IN "LINNUM". |
Zeilennummer nach $14/$15 |
get fixed-point number into temporary integer |
GET GOTO LINE |
||
.,A8A3 20 09 A9 JSR $A909 |
JSR REMN ;SKIP TO END OF LINE. |
nächsten Zeilenanfang suchen |
scan for next BASIC line |
POINT Y TO EOL |
||
.,A8A6 38 SEC |
Carry setzen (Subtraktion) |
set carry for subtract |
||||
.,A8A7 A5 39 LDA $39 |
aktuelle Zeilennummer (LOW) |
get current line number low byte |
||||
.,A8A9 E5 14 SBC $14 |
kleiner als laufende Zeile? |
subtract temporary integer low byte |
||||
.,A8AB A5 3A LDA $3A |
LDA CURLIN+1 |
aktuelle Zeilennummer (HIGH) |
get current line number high byte |
IS CURRENT PAGE < GOTO PAGE? |
||
.,A8AD E5 15 SBC $15 |
CMP LINNUM+1 |
kleiner als laufende Zeile? |
subtract temporary integer high byte |
|||
.,A8AF B0 0B BCS $A8BC |
BCS LUK4IT |
nein: $A8BC |
if current line number >= temporary integer, go search from the start of memory |
SEARCH FROM PROG START IF NOT |
||
.,A8B1 98 TYA |
TYA |
Differenz in Akku |
else copy line index to A |
OTHERWISE SEARCH FROM NEXT LINE |
||
.,A8B2 38 SEC |
SEC |
Carry setzen (Addition) |
set carry (+1) |
|||
.,A8B3 65 7A ADC $7A |
ADC TXTPTR |
Programmzeiger addieren |
add BASIC execute pointer low byte |
|||
.,A8B5 A6 7B LDX $7B |
LDX TXTPTR+1 |
sucht ab laufender Zeile |
get BASIC execute pointer high byte |
|||
.,A8B7 90 07 BCC $A8C0 |
BCC LUKALL |
unbedingter |
branch if no overflow to high byte |
|||
.,A8B9 E8 INX |
INX |
Sprung |
increment high byte |
|||
.,A8BA B0 04 BCS $A8C0 |
BCSA LUKALL ;ALWAYS GOES. |
zu $A8C0 |
branch always (can never be carry)search for line number in temporary integer from start of memory pointer |
|||
.,A8BC A5 2B LDA $2B |
LUK4IT: LDWX TXTTAB |
sucht ab Programmstart |
get start of memory low byte |
GET PROGRAM BEGINNING |
||
.,A8BE A6 2C LDX $2C |
get start of memory high bytesearch for line # in temporary integer from (AX) |
|||||
.,A8C0 20 17 A6 JSR $A617 |
LUKALL: JSR FNDLNC ;[X,A] ARE ALL SET UP. |
sucht Programmzeile |
search Basic for temp integer line number from AX |
SEARCH FOR GOTO LINE |
||
.,A8C3 90 1E BCC $A8E3 |
QFOUND: BCC USERR ;GOTO LINE IS NONEXISTANT. |
nicht gefunden: 'undef'd st.' |
if carry clear go do unsdefined statement error carry all ready set for subtract |
ERROR IF NOT THERE |
||
.,A8C5 A5 5F LDA $5F |
LDA LOWTR |
von der Startadresse (Zeile) |
get pointer low byte |
TXTPTR = START OF THE DESTINATION LINE |
||
.,A8C7 E9 01 SBC #$01 |
SBCI 1 |
eins subtrahieren und als |
-1 |
|||
.,A8C9 85 7A STA $7A |
STA TXTPTR |
Programmzeiger (LOW) |
save BASIC execute pointer low byte |
|||
.,A8CB A5 60 LDA $60 |
LDA LOWTR+1 |
HIGH-Byte der Zeile laden |
get pointer high byte |
|||
.,A8CD E9 00 SBC #$00 |
SBCI 0 |
Übertrag berücksichtigen |
subtract carry |
|||
.,A8CF 85 7B STA $7B |
STA TXTPTR+1 |
und als Programmzeiger |
save BASIC execute pointer high byte |
|||
.,A8D1 60 RTS |
GORTS: RTS ;PROCESS THE STATEMENT. ; ; "RETURN" RESTORES THE LINE NUMBER AND TEXT PNTR FROM THE STACK ; AND ELIMINATES ALL THE "FOR" ENTRIES IN FRONT OF THE "GOSUB" ENTRY. ; |
RücksprungBASIC-Befehl RETURN |
perform RETURN |
RETURN TO NEWSTT OR GOSUB"POP" AND "RETURN" STATEMENTS |
RETURN command |
|
.,A8D2 D0 FD BNE $A8D1 |
RETURN: BNE GORTS ;NO TERMINATOR=BLOW HIM UP. |
Kein Trennzeichen: SYNTAX ERR |
exit if following token to allow syntax error |
|||
.,A8D4 A9 FF LDA #$FF |
LDAI 255 |
Wert laden und |
set byte so no match possible |
|||
.,A8D6 85 4A STA $4A |
STA FORPNT+1 ;MAKE SURE THE VARIABLE'S PNTR ;NEVER GETS MATCHED. |
FOR-NEXT-ZEIGER neu setzen |
save FOR/NEXT variable pointer high byte |
|||
.,A8D8 20 8A A3 JSR $A38A |
JSR FNDFOR ;GO PAST ALL THE "FOR" ENTRIES. |
GOSUB-Datensatz suchen |
search the stack for FOR or GOSUB activity, get token off stack |
TO CANCEL FOR/NEXT IN SUB |
||
.,A8DB 9A TXS |
TXS |
correct the stack |
||||
.,A8DC C9 8D CMP #$8D |
CMPI GOSUTK ;RETURN WITHOUT GOSUB? |
'GOSUB'-Code? |
compare with GOSUB token |
LAST GOSUB FOUND? |
||
.,A8DE F0 0B BEQ $A8EB |
BEQ RETU1 |
ja: $A8E8 |
if matching GOSUB go continue RETURN |
|||
.,A8E0 A2 0C LDX #$0C |
LDXI ERRRG |
Nr für 'return without gosub’ |
else error code $04, return without gosub error |
|||
.:A8E2 2C .BYTE $2C |
SKIP2 |
BIT-Befehl um folgenden Befehl auszulassen |
makes next line BIT $11A2 |
FAKE |
||
.,A8E3 A2 11 LDX #$02 |
USERR: LDXI ERRUS ;NO MATCH SO "US" ERROR. |
Nr für 'undef'd statement' |
error code $11, undefined statement error |
|||
.,A8E5 4C 37 A4 JMP $A437 |
JMP ERROR ;YES. |
Fehlermeldung ausgeben |
do error #X then warm start |
|||
.,A8E8 4C 08 AF JMP $AF08 |
SNERR2: JMP SNERR |
'syntax error' ausgeben |
do syntax error then warm start was matching GOSUB token |
remove GOSUB block from stack |
||
.,A8EB 68 PLA |
RETU1: PLA ;REMOVE GOSUTK. |
GOSUB-Code vom Stapel holen |
dump token byte |
DISCARD GOSUB TOKEN |
||
.,A8EC 68 PLA |
PULWD CURLIN ;GET LINE NUMBER "GOSUB" WAS FROM. |
Zeilennummer (LOW) wieder- |
pull return line low byte |
|||
.,A8ED 85 39 STA $39 |
holen und abspeichern |
save current line number low byte |
PULL LINE # |
|||
.,A8EF 68 PLA |
Zeilennummer (HIGH) holen |
pull return line high byte |
||||
.,A8F0 85 3A STA $3A |
und abspeichern |
save current line number high byte |
||||
.,A8F2 68 PLA |
PULWD TXTPTR ;GET TEXT PNTR FROM "GOSUB". |
Programmzeiger (LOW) wieder- |
pull return address low byte |
|||
.,A8F3 85 7A STA $7A |
holen und abspeichern |
save BASIC execute pointer low byte |
PULL TXTPTR |
|||
.,A8F5 68 PLA |
Programmzeiger (HIGH) holen |
pull return address high byte |
||||
.,A8F6 85 7B STA $7B |
abspeichernBASIC-Befehl DATA |
save BASIC execute pointer high byteperform DATA |
"DATA" STATEMENTEXECUTED BY SKIPPING TO NEXT COLON OR EOL |
DATA command |
||
.,A8F8 20 06 A9 JSR $A906 |
DATA: JSR DATAN ;SKIP TO END OF STATEMENT, ;SINCE WHEN "GOSUB" STUCK THE TEXT PNTR ;ONTO THE STACK, THE LINE NUMBER ARG ;HADN'T BEEN READ YET. |
nächstes Statement suchen |
scan for next BASIC statement ([:] or [EOL])add Y to the BASIC execute pointer |
MOVE TO NEXT STATEMENTADD (Y) TO TXTPTR |
||
.,A8FB 98 TYA |
ADDON: TYA |
Offset |
copy index to A |
|||
.,A8FC 18 CLC |
CLC |
Carry löschen (Addition) |
clear carry for add |
|||
.,A8FD 65 7A ADC $7A |
ADC TXTPTR |
Programmzeiger addieren |
add BASIC execute pointer low byte |
|||
.,A8FF 85 7A STA $7A |
STA TXTPTR |
und wieder abspeichern |
save BASIC execute pointer low byte |
|||
.,A901 90 02 BCC $A905 |
BCC REMRTS |
Verminderung übergehen |
skip increment if no carry |
|||
.,A903 E6 7B INC $7B |
INC TXTPTR+1 |
Programmzeiger vermindern |
else increment BASIC execute pointer high byte |
|||
.,A905 60 RTS |
REMRTS: RTS ;"NEWSTT" RTS ADDR IS STILL THERE. |
RücksprungOffset des nächstenTrennzeichens finden |
scan for next BASIC statement ([:] or [EOL])returns Y as index to [:] or [EOL] |
SCAN AHEAD TO NEXT ":" OR EOL |
get end of statement |
|
.,A906 A2 3A LDX #$3A |
DATAN: LDXI ":" ;"DATA" TERMINATES ON ":" AND NULL. |
':' Doppelpunkt |
set look for character = ":" |
GET OFFSET IN Y TO EOL OR ":" |
colon |
|
.:A908 2C .BYTE $2C |
SKIP2 |
makes next line BIT $00A2scan for next BASIC linereturns Y as index to [EOL] |
FAKE |
get end of line |
||
.,A909 A2 00 LDX #$00 |
REMN: LDXI 0 ;THE ONLY TERMINATOR IS NULL. |
$0 Zeilenende |
set alternate search character = [EOL] |
TO EOL ONLY |
||
.,A90B 86 07 STX $07 |
STX CHARAC ;PRESERVE IT. |
als Suchzeichen |
store alternate search character |
|||
.,A90D A0 00 LDY #$00 |
LDYI 0 ;THIS MAKES CHARAC=0 AFTER SWAP. |
Zähler |
set search character = [EOL] |
|||
.,A90F 84 08 STY $08 |
STY ENDCHR |
initialisieren |
save the search character |
|||
.,A911 A5 08 LDA $08 |
EXCHQT: LDA ENDCHR |
Speicherzelle $7 |
get search character |
TRICK TO COUNT QUOTE PARITY |
||
.,A913 A6 07 LDX $07 |
LDX CHARAC |
gesuchtes Zeichen |
get alternate search character |
|||
.,A915 85 07 STA $07 |
STA CHARAC |
mit $8 |
make search character = alternate search character |
|||
.,A917 86 08 STX $08 |
STX ENDCHR |
vertauschen |
make alternate search character = search character |
|||
.,A919 B1 7A LDA ($7A),Y |
REMER: LDADY TXTPTR |
Zeichen holen |
get BASIC byte |
|||
.,A91B F0 E8 BEQ $A905 |
BEQ REMRTS ;NULL ALWAYS TERMINATES. |
Zeilenende, dann fertig |
exit if null [EOL] |
END OF LINE |
||
.,A91D C5 08 CMP $08 |
CMP ENDCHR ;IS IT THE OTHER TERMINATOR? |
= Suchzeichen? |
compare with search character |
|||
.,A91F F0 E4 BEQ $A905 |
BEQ REMRTS ;YES, IT'S FINISHED. |
ja: $A905 |
exit if found |
COLON IF LOOKING FOR COLONS |
||
.,A921 C8 INY |
INY ;PROGRESS TO NEXT CHARACTER. |
Zeiger erhöhen |
else increment index |
|||
.,A922 C9 22 CMP #$22 |
CMPI 34 ;IS IT A QUOTE? |
"" Hochkomma? |
compare current character with open quote |
quote mark |
||
.,A924 D0 F3 BNE $A919 |
BNE REMER ;NO, JUST CONTINUE. |
nein: $A919 |
if found go swap search character for alternate search character |
|||
.,A926 F0 E9 BEQ $A911 |
BEQA EXCHQT ;YES, TIME TO TRADE. PAGE "IF ... THEN" CODE. |
sonst $7 und $8 vertauschenBASIC-Befehl IF |
loop for next character, branch alwaysperform IF |
...ALWAYS"IF" STATEMENT |
IF command |
|
.,A928 20 9E AD JSR $AD9E |
IF: JSR FRMEVL ;EVALUATE A FORMULA. |
FRMEVL Ausdruck berechnen |
evaluate expression |
|||
.,A92B 20 79 00 JSR $0079 |
JSR CHRGOT ;GET CURRENT CHARACTER. |
CHRGOT letztes Zeichen |
scan memory |
|||
.,A92E C9 89 CMP #$89 |
CMPI GOTOTK ;IS TERMINATING CHARACTER A GOTOTK? |
'GOTO'-Code? |
compare with "GOTO" token |
|||
.,A930 F0 05 BEQ $A937 |
BEQ OKGOTO ;YES. |
ja: $A937 |
if it was the token for GOTO go do IF ... GOTO wasn't IF ... GOTO so must be IF ... THEN |
|||
.,A932 A9 A7 LDA #$A7 |
SYNCHK THENTK ;NO, IT MUST BE "THEN". |
'THEN'-Code |
set "THEN" token |
|||
.,A934 20 FF AE JSR $AEFF |
prüft auf Code |
scan for CHR$(A), else do syntax error then warm start |
||||
.,A937 A5 61 LDA $61 |
OKGOTO: LDA FACEXP ;0=FALSE. ALL OTHERS TRUE. |
Ergebnis des IF-Ausdrucks |
get FAC1 exponent |
CONDITION TRUE OR FALSE? |
||
.,A939 D0 05 BNE $A940 |
BNE DOCOND ;TRUE ! |
Ausdruck wahr?BASIC-Befehl REM |
if result was non zero continue execution else REM rest of line perform REM |
BRANCH IF TRUE"REM" STATEMENT, OR FALSE "IF" STATEMENT |
REM command |
|
.,A93B 20 09 A9 JSR $A909 |
REM: JSR REMN ;SKIP REST OF STATEMENT. |
nein, Zeilenanfang suchen |
scan for next BASIC line |
SKIP REST OF LINE |
||
.,A93E F0 BB BEQ $A8FB |
BEQA ADDON ;WILL ALWAYS BRANCH. |
Programmz. auf nächste Zeile |
add Y to the BASIC execute pointer and return, branch always result was non zero so do rest of line |
...ALWAYS |
THEN part of IF |
|
.,A940 20 79 00 JSR $0079 |
DOCOND: JSR CHRGOT ;TEST CURRENT CHARACTER. |
CHRGOT: letztes Zeichen holen |
scan memory |
COMMAND OR NUMBER? |
||
.,A943 B0 03 BCS $A948 |
BCS DOCO ;IF A NUMBER, GOTO IT. |
keine Ziffer? |
branch if not numeric character, is variable or keyword |
COMMAND |
||
.,A945 4C A0 A8 JMP $A8A0 |
JMP GOTO |
zum GOTO-Befehl |
else perform GOTO n is variable or keyword |
NUMBER |
do GOTO |
|
.,A948 4C ED A7 JMP $A7ED |
DOCO: JMP GONE3 ;INTERPRET NEW STATEMENT. PAGE "ON ... GO TO ..." CODE. |
Befehl dekodieren, ausführenBASIC-Befehl ON |
interpret BASIC code from BASIC execute pointerperform ON |
"ON" STATEMENTON <EXP> GOTO <LIST>ON <EXP> GOSUB <LIST> |
ON command |
|
.,A94B 20 9E B7 JSR $B79E |
ONGOTO: JSR GETBYT ;GET VALUE IN FACLO. |
Byte-Wert (0 bis 255) holen |
get byte parameter |
EVALUATE <EXP>, AS BYTE IN FAC+4 |
||
.,A94E 48 PHA |
PHA ;SAVE FOR LATER. |
Code merken |
push next character |
SAVE NEXT CHAR ON STACK |
||
.,A94F C9 8D CMP #$8D |
CMPI GOSUTK ;AN "ON ... GOSUB" PERHAPS? |
'GOSUB'-Code? |
compare with GOSUB token |
GOSUB code |
||
.,A951 F0 04 BEQ $A957 |
BEQ ONGLOP ;YES. |
ja: $A957 |
if GOSUB go see if it should be executed |
|||
.,A953 C9 89 CMP #$89 |
SNERR3: CMPI GOTOTK ;MUST BE "GOTOTK". |
'GOTO'-Code? |
compare with GOTO token |
GOTO code |
||
.,A955 D0 91 BNE $A8E8 |
BNE SNERR2 |
nein: dann 'SYNTAX ERROR' |
if not GOTO do syntax error then warm start next character was GOTO or GOSUB, see if it should be executed |
|||
.,A957 C6 65 DEC $65 |
ONGLOP: DEC FACLO |
Zähler vermindern |
decrement the byte value |
COUNTED TO RIGHT ONE YET? |
||
.,A959 D0 04 BNE $A95F |
BNE ONGLP1 ;SKIP ANOTHER LINE NUMBER. |
noch nicht null? |
if not zero go see if another line number exists |
NO, KEEP LOOKING |
||
.,A95B 68 PLA |
PLA ;GET DISPATCH CHARACTER. |
ja: Code zurückholen |
pull keyword token |
YES, RETRIEVE CMD |
||
.,A95C 4C EF A7 JMP $A7EF |
JMP GONE2 |
und Befehl ausführen |
go execute it |
AND GO. |
||
.,A95F 20 73 00 JSR $0073 |
ONGLP1: JSR CHRGET ;ADVANCE AND SET CODES. |
CHRGET nächstes Zeichen holen |
increment and scan memory |
PRIME CONVERT SUBROUTINE |
||
.,A962 20 6B A9 JSR $A96B |
JSR LINGET |
Zeilennummer holen |
get fixed-point number into temporary integer skip this n |
CONVERT LINE # |
||
.,A965 C9 2C CMP #$2C |
CMPI 44 ;IS IT A COMMA? |
',' Komma? |
compare next character with "," |
TERMINATE WITH COMMA? |
comma |
|
.,A967 F0 EE BEQ $A957 |
BEQ ONGLOP |
ja: dann weiter |
loop if "," |
YES |
||
.,A969 68 PLA |
PLA ;REMOVE STACK ENTRY (TOKEN). |
kein Sprung: Code zurückholen |
else pull keyword token, ran out of options |
NO, END OF LIST, SO IGNORE |
||
.,A96A 60 RTS |
ONGRTS: RTS ;EITHER END-OF-LINE OR SYNTAX ERROR. PAGE LINGET -- READ A LINE NUMBER INTO LINNUM;; "LINGET" READS A LINE NUMBER FROM THE CURRENT TEXT POSITION. ; ; LINE NUMBERS RANGE FROM 0 TO 64000-1. ; ; THE ANSWER IS RETURNED IN "LINNUM". ; "TXTPTR" IS UPDATED TO POINT TO THE TERMINATING CHARCTER ; AND [A] = THE TERMINATING CHARACTER WITH CONDITION ; CODES SET UP TO REFLECT ITS VALUE. ; |
RücksprungZeilennummer nach $14/$15 |
get fixed-point number into temporary integer |
CONVERT LINE NUMBER |
get decimal number into $14/$15 |
|
.,A96B A2 00 LDX #$00 |
LINGET: LDXI 0 |
Wert Laden und |
clear X |
ASC # TO HEX ADDRESS |
||
.,A96D 86 14 STX $14 |
STX LINNUM ;INITIALIZE LINE NUMBER TO ZERO. |
Vorsetzen |
clear temporary integer low byte |
IN LINNUM. |
||
.,A96F 86 15 STX $15 |
STX LINNUM+1 |
(für Zeilennummer gleich 0) |
clear temporary integer high byte |
|||
.,A971 B0 F7 BCS $A96A |
MORLIN: BCS ONGRTS ;IT IS NOT A DIGIT. |
keine Ziffer, dann fertig |
return if carry set, end of scan, character was not 0-9 |
NOT A DIGIT |
||
.,A973 E9 2F SBC #$2F |
SBCI "0"-1 ;-1 SINCE C=0. |
'0'-1 abziehen, gibt Hexwert |
subtract $30, $2F+carry, from byte |
CONVERT DIGIT TO BINARY |
||
.,A975 85 07 STA $07 |
STA CHARAC ;SAVE CHARACTER. |
merken |
store # |
SAVE THE DIGIT |
||
.,A977 A5 15 LDA $15 |
LDA LINNUM+1 |
HIGH-Byte holen |
get temporary integer high byte |
CHECK RANGE |
||
.,A979 85 22 STA $22 |
STA INDEX |
Zwischenspeichern |
save it for now |
|||
.,A97B C9 19 CMP #$19 |
CMPI 25 ;LINE NUMBER WILL BE .LT. 64000? |
Zahl bereits größer 6400? |
compare with $19 |
LINE # TOO LARGE? |
||
.,A97D B0 D4 BCS $A953 |
BCS SNERR3 |
dann 'SYNTAX ERROR' |
branch if >= this makes the maximum line number 63999 because the next bit does $1900 * $0A = $FA00 = 64000 decimal. the branch target is really the SYNTAX error at $A8E8 but that is too far so an intermediate compare and branch to that location is used. the problem with this is that line number that gives a partial result from $8900 to $89FF, 35072x to 35327x, will pass the new target compare and will try to execute the remainder of the ON n GOTO/GOSUB. a solution to this is to copy the byte in A before the branch to X and then branch to $A955 skipping the second compare |
YES, > 63999, GO INDIRECTLY TO "SYNTAX ERROR". <<<<<DANGEROUS CODE>>>>> NOTE THAT IF (A) = $AB ON THE LINE ABOVE, ON.1 WILL COMPARE = AND CAUSE A CATASTROPHIC JUMP TO $22D9 (FOR GOTO), OR OTHER LOCATIONS FOR OTHER CALLS TO LINGET. YOU CAN SEE THIS IS YOU FIRST PUT "BRK" IN $22D9, THEN TYPE "GO TO 437761". ANY VALUE FROM 437760 THROUGH 440319 WILL CAUSE THE PROBLEM. ($AB00 - $ABFF) <<<<<DANGEROUS CODE>>>>> |
||
.,A97F A5 14 LDA $14 |
LDA LINNUM |
Zahl * 10 (= *2*2+Zahl*2) |
get temporary integer low byte |
MULTIPLY BY TEN |
||
.,A981 0A ASL |
ASL A, ;MULTIPLY BY 10. |
Wert und Zwischenwert je |
*2 low byte |
times 2 |
||
.,A982 26 22 ROL $22 |
ROL INDEX |
2 mal um 1 Bit nach |
*2 high byte |
|||
.,A984 0A ASL |
ASL A |
links rollen |
*2 low byte |
times 2 |
||
.,A985 26 22 ROL $22 |
ROL INDEX |
(entspricht 2 * 2) |
*2 high byte (*4) |
|||
.,A987 65 14 ADC $14 |
ADC LINNUM |
plus ursprünglicher Wert |
+ low byte (*5) |
add original |
||
.,A989 85 14 STA $14 |
STA LINNUM |
und abspeichern |
save it |
|||
.,A98B A5 22 LDA $22 |
LDA INDEX |
Zwischenwert zu |
get high byte temp |
|||
.,A98D 65 15 ADC $15 |
ADC LINNUM+1 |
zweitem Wert addieren |
+ high byte (*5) |
|||
.,A98F 85 15 STA $15 |
STA LINNUM+1 |
und wieder abspeichern |
save it |
|||
.,A991 06 14 ASL $14 |
ASL LINNUM |
Speicherzelle $14 und |
*2 low byte (*10d) |
times 2 |
||
.,A993 26 15 ROL $15 |
ROL LINNUM+1 |
$15 verdoppeln |
*2 high byte (*10d) |
= times 10 overall |
||
.,A995 A5 14 LDA $14 |
LDA LINNUM |
Wert wieder laden |
get low byte |
|||
.,A997 65 07 ADC $07 |
ADC CHARAC ;ADD IN DIGIT. |
und Einerziffer addieren |
add # |
ADD DIGIT |
||
.,A999 85 14 STA $14 |
STA LINNUM |
wieder speichern |
save low byte |
|||
.,A99B 90 02 BCC $A99F |
BCC NXTLGC |
Carry gesetzt? (Übertrag) |
branch if no overflow to high byte |
|||
.,A99D E6 15 INC $15 |
INC LINNUM+1 |
Übertrag addieren |
else increment high byte |
|||
.,A99F 20 73 00 JSR $0073 |
NXTLGC: JSR CHRGET |
CHRGET nächstes Zeichen holen |
increment and scan memory |
GET NEXT CHAR |
||
.,A9A2 4C 71 A9 JMP $A971 |
JMP MORLIN PAGE "LET" CODE. |
und weiter machenBASIC-Befehl LET |
loop for next characterperform LET |
MORE CONVERTING"LET" STATEMENTLET <VAR> = <EXP><VAR> = <EXP> |
LET command |
|
.,A9A5 20 8B B0 JSR $B08B |
LET: JSR PTRGET ;GET PNTR TO VARIABLE INTO "VARPNT". |
sucht Variable hinter LET |
get variable address |
GET <VAR> |
||
.,A9A8 85 49 STA $49 |
STWD FORPNT ;PRESERVE POINTER. |
und Variablenadresse |
save variable address low byte |
|||
.,A9AA 84 4A STY $4A |
merken (LOW- und HIGH-Byte) |
save variable address high byte |
||||
.,A9AC A9 B2 LDA #$B2 |
SYNCHK EQULTK ;"=" IS NECESSARY. |
'=' - Code |
$B2 is "=" token |
equals code |
||
.,A9AE 20 FF AE JSR $AEFF |
IFN INTPRC,< |
prüft auf Code |
scan for CHR$(A), else do syntax error then warm start |
|||
.,A9B1 A5 0E LDA $0E |
LDA INTFLG ;SAVE FOR LATER. |
Integer-Flag |
get data type flag, $80 = integer, $00 = float |
SAVE VARIABLE TYPE |
||
.,A9B3 48 PHA |
PHA> |
auf Stapel retten |
push data type flag |
|||
.,A9B4 A5 0D LDA $0D |
LDA VALTYP ;RETAIN THE VARIABLE'S VALUE TYPE. |
und Typ-Flag |
get data type flag, $FF = string, $00 = numeric |
|||
.,A9B6 48 PHA |
PHA |
(String/numerisch) retten |
push data type flag |
|||
.,A9B7 20 9E AD JSR $AD9E |
JSR FRMEVL ;GET VALUE OF FORMULA INTO "FAC". |
FRMEVL: Ausdruck holen |
evaluate expression |
EVALUATE <EXP> |
||
.,A9BA 68 PLA |
PLA |
Typ-Flag wiederholen |
pop data type flag |
|||
.,A9BB 2A ROL |
ROL A, ;CARRY SET FOR STRING, OFF FOR ;NUMERIC. |
und Bit 7 ins Carry schieben |
string bit into carry |
|||
.,A9BC 20 90 AD JSR $AD90 |
JSR CHKVAL ;MAKE SURE "VALTYP" MATCHES CARRY. ;AND SET ZERO FLAG FOR NUMERIC. |
auf richtigen Typ prüfen |
do type match check |
|||
.,A9BF D0 18 BNE $A9D9 |
BNE COPSTR ;IF NUMERIC, COPY IT. COPNUM: IFN INTPRC,< |
String? ja: $A9D9 |
branch if string |
|||
.,A9C1 68 PLA |
PLA ;GET NUMBER TYPE. |
Integer-Flag zurückholen |
pop integer/float data type flag assign value to numeric variable |
|||
.,A9C2 10 12 BPL $A9D6 |
QINTGR: BPL COPFLT ;STORE A FLTING NUMBER. |
INTEGER? ja: $A9D6Wertzuweisung INTEGER |
branch if float expression is numeric integer |
REAL VARIABLE |
assign to integer |
|
.,A9C4 20 1B BC JSR $BC1B |
JSR ROUND ;ROUND INTEGER. |
FAC runden |
round FAC1 |
INTEGER VAR: ROUND TO 32 BITS |
||
.,A9C7 20 BF B1 JSR $B1BF |
JSR AYINT ;MAKE 2-BYTE NUMBER. |
und nach INTEGER wandlen |
evaluate integer expression, no sign check |
TRUNCATE TO 16-BITS |
||
.,A9CA A0 00 LDY #$00 |
LDYI 0 |
Zeiger setzen |
clear index |
|||
.,A9CC A5 64 LDA $64 |
LDA FACMO ;GET HIGH. |
HIGH-Byte holen und |
get FAC1 mantissa 3 |
|||
.,A9CE 91 49 STA ($49),Y |
STADY FORPNT ;STORE IT. |
Wert in Variable bringen |
save as integer variable low byte |
|||
.,A9D0 C8 INY |
INY |
Zeiger erhöhen |
increment index |
|||
.,A9D1 A5 65 LDA $65 |
LDA FACLO ;GET LOW. |
LOW-Byte holen und |
get FAC1 mantissa 4 |
|||
.,A9D3 91 49 STA ($49),Y |
STADY FORPNT |
Wert in Variable bringen |
save as integer variable high byte |
|||
.,A9D5 60 RTS |
RTS> |
RücksprungWertzuweisung REAL |
REAL VARIABLE = EXPRESSION |
assign to float |
||
.,A9D6 4C D0 BB JMP $BBD0 |
COPFLT: JMP MOVVF ;PUT NUMBER @FORPNT. COPSTR: |
FAC nach Variable bringenWertzuweisung String |
pack FAC1 into variable pointer and return assign value to numeric variable |
assign to string |
||
.,A9D9 68 PLA |
IFN INTPRC,<PLA> ;IF STRING, NO INTFLG. INPCOM: IFN TIME,< |
Akku vom Stapel holen |
dump integer/float data type flag |
INSTALL STRING, DESCRIPTOR ADDRESS IS AT FAC+3,4 |
||
.,A9DA A4 4A LDY $4A |
LDY FORPNT+1 ;TI$? |
Variablenadresse (HIGH) holen |
get variable pointer high byte |
STRING DATA ALREADY IN STRING AREA? |
||
.,A9DC C0 BF CPY #$BF |
CPYI ZERO/256 ;ONLY TI$ CAN BE THIS ON ASSIG. |
ist Variable TI$? |
was it TI$ pointer |
|||
.,A9DE D0 4C BNE $AA2C |
BNE GETSPT ; WAS NOT TI$. |
nein: $AA2C |
branch if not else it's TI$ = <expr$> |
assign to TI$ |
||
.,A9E0 20 A6 B6 JSR $B6A6 |
JSR FREFAC ;WE WONT NEEDIT. |
FRESTR |
pop string off descriptor stack, or from top of string space returns with A = length, X = pointer low byte, Y = pointer high byte |
|||
.,A9E3 C9 06 CMP #$06 |
CMPI 6 ;LENGTH CORRECT? |
Stringlänge gleich 6 |
compare length with 6 |
length 6 |
||
.,A9E5 D0 3D BNE $AA24 |
BNE FCERR2 |
nein: 'illegal quantity' |
if length not 6 do illegal quantity error then warm start |
|||
.,A9E7 A0 00 LDY #$00 |
LDYI 0 ;YES. DO SETUP. |
Wert holen |
clear index |
|||
.,A9E9 84 61 STY $61 |
STY FACEXP ;ZERO FAC TO START WITH. |
und damit FAC |
clear FAC1 exponent |
|||
.,A9EB 84 66 STY $66 |
STY FACSGN |
initialisieren |
clear FAC1 sign (b7) |
|||
.,A9ED 84 71 STY $71 |
TIMELP: STY FBUFPT ;SAVE POSOTION. |
(Akku, Vorzeichen und Zeiger) |
save index |
|||
.,A9EF 20 1D AA JSR $AA1D |
JSR TIMNUM ;GET A DIGIT. |
prüft nächstes Z. auf Ziffer |
check and evaluate numeric digit |
|||
.,A9F2 20 E2 BA JSR $BAE2 |
JSR MUL10 ;WHOLE QTY BY 10. |
FAC = FAC * 10 |
multiply FAC1 by 10 |
|||
.,A9F5 E6 71 INC $71 |
INC FBUFPT |
Stellenzähler erhöhen |
increment index |
|||
.,A9F7 A4 71 LDY $71 |
LDY FBUFPT |
und ins Y-Reg. bringen |
restore index |
|||
.,A9F9 20 1D AA JSR $AA1D |
JSR TIMNUM |
prüft nächstes Z. auf Ziffer |
check and evaluate numeric digit |
|||
.,A9FC 20 0C BC JSR $BC0C |
JSR MOVAF |
FAC nach ARG kopieren |
round and copy FAC1 to FAC2 |
|||
.,A9FF AA TAX |
TAX ;IF NUM=0 THEN NO MULT. |
FAC gleich 0? |
copy FAC1 exponent |
|||
.,AA00 F0 05 BEQ $AA07 |
BEQ NOML6 ;IF =0, GO TIT. |
ja: $AA07 |
branch if FAC1 zero |
|||
.,AA02 E8 INX |
INX ;MULT BY TWO. |
Exponent von FAC erhöhen |
increment index, * 2 |
|||
.,AA03 8A TXA |
TXA |
(FAC *2) und in den Akku |
copy back to A |
|||
.,AA04 20 ED BA JSR $BAED |
JSR FINML6 ;ADD IN AND MULT BY 2 GIVES *6. |
FAC = FAC + ARG |
FAC1 = (FAC1 + (FAC2 * 2)) * 2 = FAC1 * 6 |
|||
.,AA07 A4 71 LDY $71 |
NOML6: LDY FBUFPT |
Stellenzähler |
get index |
|||
.,AA09 C8 INY |
INY |
erhöhen |
increment index |
|||
.,AA0A C0 06 CPY #$06 |
CPYI 6 ;DONE ALL SIX? |
schon 6 Stellen? |
compare index with 6 |
|||
.,AA0C D0 DF BNE $A9ED |
BNE TIMELP |
nein: nächstes Zeichen |
loop if not 6 |
|||
.,AA0E 20 E2 BA JSR $BAE2 |
JSR MUL10 ;ONE LAST TIME. |
FAC = FAC * 10 |
multiply FAC1 by 10 |
|||
.,AA11 20 9B BC JSR $BC9B |
JSR QINT ;SHIFT IT OVER TO THE RIGHT. |
FAC rechtsbündig machen |
convert FAC1 floating to fixed |
|||
.,AA14 A6 64 LDX $64 |
LDXI 2 |
Werte für |
get FAC1 mantissa 3 |
|||
.,AA16 A4 63 LDY $63 |
SEI ;DISALLOW INTERRUPTS. |
eingegebene Uhrzeit |
get FAC1 mantissa 2 |
|||
.,AA18 A5 65 LDA $65 |
TIMEST: LDA FACMOH,X |
holen und |
get FAC1 mantissa 4 |
|||
.,AA1A 4C DB FF JMP $FFDB |
STA CQTIMR,X DEX BPL TIMEST ;LOOP 3 TIMES. CLI ;TURN ON INTS AGAIN. RTS |
Time setzenZeichen auf Ziffer prüfen |
set real time clock and returncheck and evaluate numeric digit |
add next digit to float accum |
||
.,AA1D B1 22 LDA ($22),Y |
TIMNUM: LDADY INDEX ;INDEX SET UP BY FREFAC. |
Zeichen holen (aus String) |
get byte from string |
|||
.,AA1F 20 80 00 JSR $0080 |
JSR QNUM |
auf Ziffer prüfen |
clear Cb if numeric. this call should be to $84 as the code from $80 first comapres the byte with [SPACE] and does a BASIC increment and get if it is |
|||
.,AA22 90 03 BCC $AA27 |
BCC GOTNUM |
Ziffer: $AA27 |
branch if numeric |
|||
.,AA24 4C 48 B2 JMP $B248 |
FCERR2: JMP FCERR ;MUST BE NUMERIC STRING. |
sonst: 'illegal quantity' |
do illegal quantity error then warm start |
|||
.,AA27 E9 2F SBC #$2F |
GOTNUM: SBCI "0"-1 ;C IS OFF. |
von ASCII nach HEX umwandeln |
subtract $2F + carry to convert ASCII to binary |
|||
.,AA29 4C 7E BD JMP $BD7E |
JMP FINLOG> ;ADD IN DIGIT TO FAC. |
in FAC und ARG übertragenWertzuweisung an normalenString |
evaluate new ASCII digit and returnassign value to numeric variable, but not TI$ |
assign to string variable |
||
.,AA2C A0 02 LDY #$02 |
GETSPT: LDYI 2 ;GET PNTR TO DESCRIPTOR. |
Zeiger setzen |
index to string pointer high byte |
|||
.,AA2E B1 64 LDA ($64),Y |
LDADY FACMO |
Stringadresse HIGH mit |
get string pointer high byte |
(STRING AREA IS BTWN FRETOP |
||
.,AA30 C5 34 CMP $34 |
CMP FRETOP+1 ;SEE IF IT POINTS INTO STRING SPACE. |
Stringanfangsadr. vergleichen |
compare with bottom of string space high byte |
HIMEM) |
||
.,AA32 90 17 BCC $AA4B |
BCC DNTCPY ;IF [FRETOP],GT.[2&3,FACMO], DON'T COPY. |
kleiner: String im Programm |
branch if string pointer high byte is less than bottom of string space high byte |
YES, DATA ALREADY UP THERE |
||
.,AA34 D0 07 BNE $AA3D |
BNE QVARIA ;IT IS LESS. |
größer: $AA3D |
branch if string pointer high byte is greater than bottom of string space high byte else high bytes were equal |
NO |
||
.,AA36 88 DEY |
DEY |
Zeiger vermindern |
decrement index to string pointer low byte |
MAYBE, TEST LOW BYTE OF POINTER |
||
.,AA37 B1 64 LDA ($64),Y |
LDADY FACMO |
Stringadresse (LOW) holen |
get string pointer low byte |
|||
.,AA39 C5 33 CMP $33 |
CMP FRETOP ;COMPARE LOW ORDERS. |
und vergleichen |
compare with bottom of string space low byte |
|||
.,AA3B 90 0E BCC $AA4B |
BCC DNTCPY |
kleiner: String im Programm |
branch if string pointer low byte is less than bottom of string space low byte |
YES, ALREADY THERE |
||
.,AA3D A4 65 LDY $65 |
QVARIA: LDY FACLO |
Zeiger auf Stringdescriptor |
get descriptor pointer high byte |
NO. DESCRIPTOR ALREADY AMONG VARIABLES? |
||
.,AA3F C4 2E CPY $2E |
CPY VARTAB+1 ;IF [VARTAB].GT.[FACMO], DON'T COPY. |
mit Variablenstart vergl. |
compare with start of variables high byte |
|||
.,AA41 90 08 BCC $AA4B |
BCC DNTCPY |
kleiner: $AA4B |
branch if less, is on string stack |
NO |
||
.,AA43 D0 0D BNE $AA52 |
BNE COPY ;IT IS LESS. |
größer: $AA52 |
if greater make space and copy string else high bytes were equal |
YES |
||
.,AA45 A5 64 LDA $64 |
LDA FACMO |
Stringdiscriptorzeiger (LOW) |
get descriptor pointer low byte |
MAYBE, COMPARE LO-BYTE |
||
.,AA47 C5 2D CMP $2D |
CMP VARTAB ;COMPARE LOW ORDERS. |
mit Variablenstart vergl. |
compare with start of variables low byte |
|||
.,AA49 B0 07 BCS $AA52 |
BCS COPY |
größer: $AA52 |
if greater or equal make space and copy string |
YES, DESCRIPTOR IS AMONG VARIABLES |
||
.,AA4B A5 64 LDA $64 |
DNTCPY: LDWD FACMO |
Zeiger in Akku und Y-Reg. |
get descriptor pointer low byte |
EITHER STRING ALREADY ON TOP, OR |
||
.,AA4D A4 65 LDY $65 |
auf Stringdescriptor setzen |
get descriptor pointer high byte |
DESCRIPTOR IS NOT A VARIABLE |
|||
.,AA4F 4C 68 AA JMP $AA68 |
JMP COPYZC |
bis $AA68 überspringen |
go copy descriptor to variable |
SO JUST STORE THE DESCRIPTORSTRING NOT YET IN STRING AREA,AND DESCRIPTOR IS A VARIABLE |
||
.,AA52 A0 00 LDY #$00 |
COPY: LDYI 0 |
Zeiger setzen |
clear index |
POINT AT LENGTH IN DESCRIPTOR |
||
.,AA54 B1 64 LDA ($64),Y |
LDADY FACMO |
Länge des Strings holen |
get string length |
GET LENGTH |
||
.,AA56 20 75 B4 JSR $B475 |
JSR STRINI ;GET ROOM TO COPY STRING INTO. |
prüft Platz, setzt Stringz. |
copy descriptor pointer and make string space A bytes long |
MAKE A STRING THAT LONG UP ABOVE |
||
.,AA59 A5 50 LDA $50 |
LDWD DSCPNT ;GET POINTER TO OLD DESCRIPTOR, SO |
Zeiger auf Stringdescriptor |
copy old descriptor pointer low byte |
SET UP SOURCE PNTR FOR MONINS |
||
.,AA5B A4 51 LDY $51 |
holen (LOW- und HIGH-Byte) |
copy old descriptor pointer high byte |
||||
.,AA5D 85 6F STA $6F |
STWD STRNG1 ;MOVINS CAN FIND STRING. |
und |
save old descriptor pointer low byte |
|||
.,AA5F 84 70 STY $70 |
speichern |
save old descriptor pointer high byte |
||||
.,AA61 20 7A B6 JSR $B67A |
JSR MOVINS ;COPY IT. |
String in Bereich übertragen |
copy string from descriptor to utility pointer |
MOVE STRING DATA TO NEW AREA |
||
.,AA64 A9 61 LDA #$61 |
LDWDI DSCTMP ;GET POINTER TO OLD DESCRIPTOR. |
Werte laden |
get descriptor pointer low byte |
ADDRESS OF DESCRIPTOR IS IN FAC |
low 0061 |
|
.,AA66 A0 00 LDY #$00 |
und damit |
get descriptor pointer high byte |
high 0061move descriptor into variable |
|||
.,AA68 85 50 STA $50 |
COPYZC: STWD DSCPNT ;REMEMBER POINTER TO DESCRIPTOR. |
Stringdiscriptor |
save descriptor pointer low byte |
|||
.,AA6A 84 51 STY $51 |
neu setzen |
save descriptor pointer high byte |
||||
.,AA6C 20 DB B6 JSR $B6DB |
JSR FRETMS ;FREE UP THE TEMPORARY WITHOUT ;FREEING UP ANY STRING SPACE. |
Descriptor löschen |
clean descriptor stack, YA = pointer |
DISCARD DESCRIPTOR IF 'TWAS TEMPORARY |
||
.,AA6F A0 00 LDY #$00 |
LDYI 0 |
Zeiger setzen |
clear index |
COPY STRING DESCRIPTOR |
||
.,AA71 B1 50 LDA ($50),Y |
LDADY DSCPNT |
Länge des Descriptors holen |
get string length from new descriptor |
|||
.,AA73 91 49 STA ($49),Y |
STADY FORPNT |
und abspeichern |
copy string length to variable |
|||
.,AA75 C8 INY |
INY ;POINT TO STRING PNTR. |
Zeiger erhöhen |
increment index |
|||
.,AA76 B1 50 LDA ($50),Y |
LDADY DSCPNT |
Adresse (LOW) holen |
get string pointer low byte from new descriptor |
|||
.,AA78 91 49 STA ($49),Y |
STADY FORPNT |
und speichern |
copy string pointer low byte to variable |
|||
.,AA7A C8 INY |
INY |
Zeiger erhöhen |
increment index |
|||
.,AA7B B1 50 LDA ($50),Y |
LDADY DSCPNT |
und Adresse (HIGH) |
get string pointer high byte from new descriptor |
|||
.,AA7D 91 49 STA ($49),Y |
STADY FORPNT |
in Variable bringen |
copy string pointer high byte to variable |
|||
.,AA7F 60 RTS |
RTS PAGE PRINT CODE.IFN EXTIO,< |
RücksprungBASIC-Befehl PRINT# |
perform PRINT# |
PRINT# comand |
||
.,AA80 20 86 AA JSR $AA86 |
PRINTN: JSR CMD ;DOCMD |
CMD-Befehl |
perform CMD |
|||
.,AA83 4C B5 AB JMP $ABB5 |
JMP IODONE ;RELEASE CHANNEL. |
und CLRCHBASIC-Befehl CMD |
close input and output channels and returnperform CMD |
CMD command |
||
.,AA86 20 9E B7 JSR $B79E |
CMD: JSR GETBYT |
holt Byte-Ausdruck |
get byte parameter |
|||
.,AA89 F0 05 BEQ $AA90 |
BEQ SAVEIT |
Trennzeichen: $AA90 |
branch if following byte is ":" or [EOT] |
|||
.,AA8B A9 2C LDA #$2C |
SYNCHK 44 ;COMMA? |
',', Wert laden |
set "," |
comma |
||
.,AA8D 20 FF AE JSR $AEFF |
prüft auf Komma |
scan for CHR$(A), else do syntax error then warm start |
||||
.,AA90 08 PHP |
SAVEIT: PHP |
Statusregister merken |
save status |
|||
.,AA91 86 13 STX $13 |
JSR CQOOUT ;CHECK AND OPEN OUTPUT CHANNL. |
Nr. des Ausgabegeräts merken |
set current I/O channel |
|||
.,AA93 20 18 E1 JSR $E118 |
STX CHANNL ;CHANNL TO OUTPUT ON. |
CKOUT, Ausgabegerät setzen |
open channel for output with error check |
|||
.,AA96 28 PLP |
PLP ;GET STATUS BACK. |
Statusregister wiederholen |
restore status |
|||
.,AA97 4C A0 AA JMP $AAA0 |
JMP PRINT> |
zum PRINT-Befehl |
perform PRINT |
do PRINT |
||
.,AA9A 20 21 AB JSR $AB21 |
STRDON: JSR STRPRT |
String drucken |
print string from utility pointer |
|||
.,AA9D 20 79 00 JSR $0079 |
NEWCHR: JSR CHRGOT ;REGET LAST CHARACTER. |
CHRGOT letztes ZeichenBASIC-Befehl PRINT |
scan memoryperform PRINT |
"PRINT" STATEMENT |
PRINT command |
|
.,AAA0 F0 35 BEQ $AAD7 |
PRINT: BEQ CRDO ;TERMINATOR SO TYPE CRLF. |
Trennzeichen: $AAD7 |
if nothing following just print CR/LF |
NO MORE LIST, PRINT <RETURN> |
||
.,AAA2 F0 43 BEQ $AAE7 |
PRINTC: BEQ PRTRTS ;HERE AFTER SEEING TAB(X) OR , OR ; ;IN WHICH CASE A TERMINATOR DOES NOT ;MEAN TYPE A CRLF BUT JUST RTS. |
Trennz. (TAB, SPC): RTS |
exit if nothing following, end of PRINT branch |
NO MORE LIST, DON'T PRINT <RETURN> |
||
.,AAA4 C9 A3 CMP #$A3 |
CMPI TABTK ;TAB FUNCTION? |
'TAB('-Code? |
compare with token for TAB( |
TAB( code |
||
.,AAA6 F0 50 BEQ $AAF8 |
BEQ TABER ;YES. |
ja: $AAF8 |
if TAB( go handle it |
C=1 FOR TAB( |
||
.,AAA8 C9 A6 CMP #$A6 |
CMPI SPCTK ;SPACE FUNCTION? |
'SPC('-Code? |
compare with token for SPC( |
SPC( code |
||
.,AAAA 18 CLC |
CLC |
Flag für SPC setzen |
flag SPC( |
|||
.,AAAB F0 4B BEQ $AAF8 |
BEQ TABER |
SPC-Code: $AAF8 |
if SPC( go handle it |
C=0 FOR SPC( |
||
.,AAAD C9 2C CMP #$2C |
CMPI 44 ;A COMMA? |
','-Code? (Komma) |
compare with "," |
comma |
||
.,AAAF F0 37 BEQ $AAE8 |
BEQ COMPRT ;YES. |
ja: $AAE8 |
if "," go skip to the next TAB position |
|||
.,AAB1 C9 3B CMP #$3B |
CMPI 59 ;A SEMICOLON? |
';'-Code? (Semikolon) |
compare with ";" |
semi-colon |
||
.,AAB3 F0 5E BEQ $AB13 |
BEQ NOTABR ;YES. |
ja: nächstes Zeichen, weiter |
if ";" go continue the print loop |
|||
.,AAB5 20 9E AD JSR $AD9E |
JSR FRMEVL ;EVALUATE THE FORMULA. |
FRMEVL: Term holen |
evaluate expression |
EVALUATE EXPRESSION |
||
.,AAB8 24 0D BIT $0D |
BIT VALTYP ;A STRING? |
Typflag |
test data type flag, $FF = string, $00 = numeric |
STRING OR FP VALUE? |
||
.,AABA 30 DE BMI $AA9A |
BMI STRDON ;YES. |
String? |
if string go print string, scan memory and continue PRINT |
STRING |
||
.,AABC 20 DD BD JSR $BDDD |
JSR FOUT |
FAC in ASCII-String wandeln |
convert FAC1 to ASCII string result in (AY) |
FP: CONVERT INTO BUFFER |
||
.,AABF 20 87 B4 JSR $B487 |
JSR STRLIT ;BUILD DESCRIPTOR. IFN REALIO-3,< LDYI 0 ;GET THE POINTER. LDADY FACMO CLC ADC TRMPOS ;MAKE SURE LEN+POS.LT.WIDTH. CMP LINWID ;GREATER THAN LINE LENGTH? ;REMEMBER SPACE PRINTED AFTER NUMBER. BCC LINCHK ;GO TYPE. JSR CRDO> ;YES, TYPE CRLF FIRST. |
Stringparameter holen |
print " terminated string to utility pointer |
MAKE BUFFER INTO STRING |
||
.,AAC2 20 21 AB JSR $AB21 |
LINCHK: JSR STRPRT ;PRINT THE NUMBER. |
String drucken |
print string from utility pointer |
|||
.,AAC5 20 3B AB JSR $AB3B |
JSR OUTSPC ;PRINT A SPACE |
Cursor right bzw. Leerzeichen |
print [SPACE] or [CURSOR RIGHT] |
|||
.,AAC8 D0 D3 BNE $AA9D |
BNEA NEWCHR ;ALWAYS GOES. IFN REALIO-4,< IFN BUFPAG,< |
weiter machen |
go scan memory and continue PRINT, branch alwaysset XY to $0200 - 1 and print [CR] |
PRINT THE STRING |
end statement in buffer and screen |
|
.,AACA A9 00 LDA #$00 |
FININL: LDAI 0 |
Eingabepuffer |
clear A |
|||
.,AACC 9D 00 02 STA $0200,X |
STA BUF,X |
mit $0 abschließen |
clear first byte of input buffer |
|||
.,AACF A2 FF LDX #$FF |
LDXYI BUF-1> |
Zeiger auf |
$0200 - 1 low byte |
|||
.,AAD1 A0 01 LDY #$01 |
IFE BUFPAG,< FININL: LDYI 0 ;PUT A ZERO AT END OF BUF. STY BUF,X LDXI BUF-1> ;SETUP POINTER. IFN EXTIO,< |
Eingabepuffer ab $0200 setzen |
$0200 - 1 high byte |
|||
.,AAD3 A5 13 LDA $13 |
LDA CHANNL ;NO CRDO IF NOT TERMINAL. |
Nummer des Ausgabegeräts |
get current I/O channel |
|||
.,AAD5 D0 10 BNE $AAE7 |
BNE PRTRTS>> CRDO: IFE EXTIO,< LDAI 13 ;MAKE TRMPOS LESS THAN LINE LENGTH. STA TRMPOS> IFN EXTIO,< IFN REALIO-3,< LDA CHANNL BNE GOCR STA TRMPOS> |
Tastatur? nein: RTS |
exit if not default channelprint CR/LF |
end line on CMD output file |
||
.,AAD7 A9 0D LDA #$0D |
GOCR: LDAI 13> ;X AND Y MUST BE PRESERVED. |
'CR' carriage return |
set [CR] |
PRINT <RETURN> |
||
.,AAD9 20 47 AB JSR $AB47 |
JSR OUTDO |
ausgeben |
print the character |
|||
.,AADC 24 13 BIT $13 |
LDAI 10 |
logische Filenummer |
test current I/O channel |
|||
.,AADE 10 05 BPL $AAE5 |
JSR OUTDO |
kleiner 128? |
if ?? toggle A, EOR #$FF and return |
|||
.,AAE0 A9 0A LDA #$0A |
CRFIN: |
'LF' line feed |
set [LF] |
|||
.,AAE2 20 47 AB JSR $AB47 |
IFN EXTIO,< |
ausgeben |
print the character toggle A |
|||
.,AAE5 49 FF EOR #$FF |
IFN REALIO-3,< |
NOT |
invert A |
<<< WHY??? >>> |
||
.,AAE7 60 RTS |
LDA CHANNL BNE PRTRTS>> IFE NULCMD,< IFN REALIO-3,< LDAI 0 STA TRMPOS> EORI 255> IFN NULCMD,< TXA ;PRESERVE [ACCX]. SOME NEED IT. PHA LDX NULCNT ;GET NUMBER OF NULLS. BEQ CLRPOS LDAI 0 PRTNUL: JSR OUTDO DEX ;DONE WITH NULLS? BNE PRTNUL CLRPOS: STX TRMPOS PLA TAX> PRTRTS: RTS COMPRT: LDA TRMPOS NCMPOS==<<<LINLEN/CLMWID>-1>*CLMWID> ;CLMWID BEYOND WHICH THERE ARE IFN REALIO-3,< ;NO MORE COMMA FIELDS. CMP NCMWID ;SO ALL COMMA DOES IS "CRDO". |
Rücksprung |
was "," |
routine for printing TAB( and SPC( |
||
.,AAE8 38 SEC |
BCC MORCOM |
Zehner-Tabulator mit Komma |
set Cb for read cursor position |
|||
.,AAE9 20 F0 FF JSR $FFF0 |
JSR CRDO ;TYPE CRLF. |
Cursorposition holen |
read/set X,Y cursor position |
|||
.,AAEC 98 TYA |
JMP NOTABR> ;AND QUIT IF BEYOND LAST FIELD. |
Spalte ins Y-Reg. |
copy cursor Y |
|||
.,AAED 38 SEC |
MORCOM: SEC |
Carry setzen (Subtr.) |
set carry for subtract |
|||
.,AAEE E9 0A SBC #$0A |
MORCO1: SBCI CLMWID ;GET [A] MODULUS CLMWID. |
10 abziehen |
subtract one TAB length |
|||
.,AAF0 B0 FC BCS $AAEE |
BCS MORCO1 |
nicht negativ? |
loop if result was +ve |
|||
.,AAF2 49 FF EOR #$FF |
EORI 255 ;FILL PRINT POS OUT TO EVEN CLMWID SO |
invertieren |
complement it |
|||
.,AAF4 69 01 ADC #$01 |
ADCI 1 |
+1 (Zweierkomplement) |
+1, twos complement |
|||
.,AAF6 D0 16 BNE $AB0E |
BNE ASPAC ;PRINT [A] SPACES. |
unbedingter SprungTAB( (C=1) und SPC( (C=0) |
always print A spaces, result is never $00 |
|||
.,AAF8 08 PHP |
TABER: PHP ;REMEMBER IF SPC OR TAB FUNCTION. |
Flags merken |
save TAB( or SPC( status |
C=0 FOR SPC(, C=1 FOR TAB( |
||
.,AAF9 38 SEC |
JSR GTBYTC ;GET VALUE INTO ACCX. |
Carry setzen |
set Cb for read cursor position |
|||
.,AAFA 20 F0 FF JSR $FFF0 |
Cursorposition holen |
read/set X,Y cursor position |
||||
.,AAFD 84 09 STY $09 |
und Spalte merken |
save current cursor position |
||||
.,AAFF 20 9B B7 JSR $B79B |
Byte-Wert holen |
scan and get byte parameter |
GET VALUE |
|||
.,AB02 C9 29 CMP #$29 |
CMPI 41 |
')' Klammer zu? |
compare with ")" |
TRAILING PARENTHESIS |
) |
|
.,AB04 D0 59 BNE $AB5F |
BNE SNERR4 |
nein: 'SYNTAX ERROR' |
if not ")" do syntax error |
NO, SYNTAX ERROR |
||
.,AB06 28 PLP |
PLP |
Flags wiederherstellen |
restore TAB( or SPC( status |
TAB( OR SPC( |
||
.,AB07 90 06 BCC $AB0F |
BCC XSPAC ;PRINT [X] SPACES. |
zu SPC( |
branch if was SPC( else was TAB( |
SPC( |
||
.,AB09 8A TXA |
TXA |
TAB-Wert in Akku |
copy TAB() byte to A |
CALCULATE SPACES NEEDED FOR TAB( |
||
.,AB0A E5 09 SBC $09 |
SBC TRMPOS |
mit Cursorspalte vergleichen |
subtract current cursor position |
|||
.,AB0C 90 05 BCC $AB13 |
BCC NOTABR ;NEGATIVE, DON'T PRINT ANY. |
kleiner Cursor-Position: RTS |
go loop for next if already past requited position |
ALREADY PAST THAT COLUMN |
||
.,AB0E AA TAX |
ASPAC: TAX |
Schritte bis zum Tabulator |
copy [SPACE] count to X |
NOW DO A SPC( TO THE SPECIFIED COLUMN |
||
.,AB0F E8 INX |
XSPAC: INX |
aus Zähler initialisieren |
increment count |
|||
.,AB10 CA DEX |
XSPAC2: DEX ;DECREMENT THE COUNT. |
um 1 vermindern |
decrement count |
|||
.,AB11 D0 06 BNE $AB19 |
BNE XSPAC1 |
=0? nein: Cursor right |
branch if count was not zero was ";" or [SPACES] printed |
MORE SPACES TO PRINT |
||
.,AB13 20 73 00 JSR $0073 |
NOTABR: JSR CHRGET ;REGET LAST CHARACTER. |
nächstes Zeichen holen |
increment and scan memory |
|||
.,AB16 4C A2 AA JMP $AAA2 |
JMP PRINTC ;DON'T CALL CRDO. |
und weitermachen |
continue print loop |
CONTINUE PARSING PRINT LIST |
||
.,AB19 20 3B AB JSR $AB3B |
XSPAC1: JSR OUTSPC |
Cursor right bzw. Leerzeichen |
print [SPACE] or [CURSOR RIGHT] |
|||
.,AB1C D0 F2 BNE $AB10 |
BNEA XSPAC2 ; ; PRINT THE STRING POINTED TO BY [Y,A] WHICH ENDS WITH A ZERO. ; IF THE STRING IS BELOW DSCTMP IT WILL BE COPIED INTO STRING SPACE. ; |
zum SchleifenanfangString ausgeben |
loop, branch alwaysprint null terminated string |
...ALWAYSPRINT STRING AT (Y,A) |
print string form AY |
|
.,AB1E 20 87 B4 JSR $B487 |
STROUT: JSR STRLIT ;GET A STRING LITERAL. ; ; PRINT THE STRING WHOSE DESCRIPTOR IS POINTED TO BY FACMO. ; |
Stringparameter holen |
print " terminated string to utility pointerprint string from utility pointer |
MAKE (Y,A) PRINTABLEPRINT STRING AT (FACMO,FACLO) |
print string from $22/$23 |
|
.,AB21 20 A6 B6 JSR $B6A6 |
STRPRT: JSR FREFAC ;RETURN TEMP POINTER. |
FRESTR |
pop string off descriptor stack, or from top of string space returns with A = length, X = pointer low byte, Y = pointer high byte |
GET ADDRESS INTO INDEX, (A)=LENGTH |
||
.,AB24 AA TAX |
TAX ;PUT COUNT INTO COUNTER. |
Stringlänge |
copy length |
USE X-REG FOR COUNTER |
||
.,AB25 A0 00 LDY #$00 |
LDYI 0 |
Zeiger für Stringausgabe |
clear index |
USE Y-REG FOR SCANNER |
||
.,AB27 E8 INX |
INX ;MOVE ONE AHEAD. |
erhöhen |
increment length, for pre decrement loop |
|||
.,AB28 CA DEX |
STRPR2: DEX |
vermindern |
decrement length |
|||
.,AB29 F0 BC BEQ $AAE7 |
BEQ PRTRTS ;ALL DONE. |
String zu Ende? |
exit if done |
FINISHED |
||
.,AB2B B1 22 LDA ($22),Y |
LDADY INDEX ;PNTR TO ACT STRNG SET BY FREFAC. |
Zeichen des Strings |
get byte from string |
NEXT CHAR FROM STRING |
||
.,AB2D 20 47 AB JSR $AB47 |
JSR OUTDO |
ausgeben |
print the character |
PRINT THE CHAR |
||
.,AB30 C8 INY |
INY |
Zeiger erhöhen |
increment index |
<<< NEXT THREE LINES ARE USELESS >>> |
||
.,AB31 C9 0D CMP #$0D |
CMPI 13 |
'CR' carriage return? |
compare byte with [CR] |
WAS IT <RETURN>? |
||
.,AB33 D0 F3 BNE $AB28 |
BNE STRPR2 |
nein: weiter |
loop if not [CR] |
NO |
||
.,AB35 20 E5 AA JSR $AAE5 |
JSR CRFIN ;TYPE REST OF CARRIAGE RETURN. |
Fehler ! Test auf LF-Ausgabe |
toggle A, EOR #$FF. what is the point of this ?? |
EOR #$FF WOULD DO IT, BUT WHY? <<< ABOVE THREE LINES ARE USELESS >>> |
||
.,AB38 4C 28 AB JMP $AB28 |
JMP STRPR2 ;AND ON AND ON. ; ; OUTDO OUTPUTS THE CHARACTER IN ACCA, USING CNTWFL ; (SUPPRESS OR NOT), TRMPOS (PRINT HEAD POSITION), ; TIMING, ETCQ. NO REGISTERS ARE CHANGED. ; OUTSPC: IFN REALIO-3,< LDAI " "> IFE REALIO-3,< |
und weitermachenAusgabe eines Leerzeichensbzw. Cursor right |
loopprint [SPACE] or [CURSOR RIGHT] |
print character on CMD output file |
||
.,AB3B A5 13 LDA $13 |
LDA CHANNL |
Ausgabe in File? |
get current I/O channel |
|||
.,AB3D F0 03 BEQ $AB42 |
BEQ CRTSKP |
Bildschirm: dann Cursor right |
if default channel go output [CURSOR RIGHT] |
|||
.,AB3F A9 20 LDA #$20 |
LDAI " " |
' ' Leerzeichencode laden |
else output [SPACE] |
PRINT A SPACE |
space |
|
.:AB41 2C .BYTE $2C |
SKIP2 |
makes next line BIT $1DA9 |
SKIP OVER NEXT LINE |
|||
.,AB42 A9 1D LDA #$1D |
CRTSKP: LDAI 29> ;COMMODORE'S SKIP CHARACTER. |
Cursor right Code laden |
set [CURSOR RIGHT] |
csr right |
||
.:AB44 2C .BYTE $2C |
SKIP2 |
makes next line BIT $3FA9print "?" |
SKIP OVER NEXT LINE |
|||
.,AB45 A9 3F LDA #$3F |
OUTQST: LDAI "?" OUTDO: IFN REALIO,< BIT CNTWFL ;SHOULDN'T AFFECT CHANNEL I/O! BMI OUTRTS> IFN REALIO-3,< PHA CMPI 32 ;IS THIS A PRINTING CHAR? BCC TRYOUT ;NO, DON'T INCLUDE IT IN TRMPOS. LDA TRMPOS CMP LINWID ;LENGTH = TERMINAL WIDTH? BNE OUTDO1 JSR CRDO ;YES, TYPE CRLF OUTDO1: IFN EXTIO,< LDA CHANNL BNE TRYOUT> INCTRM: INC TRMPOS ;INCREMENT COUNT. TRYOUT: PLA> ;RESTORE THE A REGISTER IFE REALIO-1,< STY KIMY> ;PRESERVE Y. IFE REALIO-4,<ORAI ^O200> ;TURN ON B7 FOR APPLE. IFN REALIO,< |
'?' Fragezeichencode laden |
set "?"print character |
PRINT QUESTION MARK |
question mark |
|
.,AB47 20 0C E1 JSR $E10C |
OUTLOC: JSR OUTCH> ;OUTPUT THE CHARACTER. IFE REALIO-1,< LDY KIMY> ;GET Y BACK. IFE REALIO-2,<REPEAT 4,<NOP>> IFE REALIO-4,<ANDI ^O177> ;GET [A] BACK FROM APPLE. IFE REALIO,< TJSR OUTSIM##> ;CALL SIMULATOR OUTPUT ROUTINE |
Code ausgeben |
output character to channel with error check |
|||
.,AB4A 29 FF AND #$FF |
OUTRTS: ANDI 255 ;SET Z=0. |
Flags setzen |
set the flags on A |
PRINT CHAR FROM (A)NOTE: POKE 243,32 ($20 IN $F3) WILL CONVERTOUTPUT TO LOWER CASE. THIS CAN BE CANCELLED BY NORMAL, INVERSE, OR FLASH OR POKE 243,0. |
||
.,AB4C 60 RTS |
GETRTS: RTS PAGE INPUT AND READ CODE.;; HERE WHEN THE DATA THAT WAS TYPED IN OR IN "DATA" STATEMENTS ; IS IMPROPERLY FORMATTED. FOR "INPUT" WE START AGAIN. ; FOR "READ" WE GIVE A SYNTAX ERROR AT THE DATA LINE. ; |
RücksprungFehlerbehandlung bei Eingabe |
bad input routine |
INPUT CONVERSION ERRORILLEGAL CHARACTER IN NUMERIC FIELD.MUST DISTINGUISH BETWEEN INPUT, READ, AND GET |
read errors |
|
.,AB4D A5 11 LDA $11 |
TRMNOK: LDA INPFLG |
Flag für INPUT / GET / READ |
get INPUT mode flag, $00 = INPUT, $40 = GET, $98 = READ |
|||
.,AB4F F0 11 BEQ $AB62 |
BEQ TRMNO1 ;IF INPUT TRY AGAIN. IFN GETCMD,< |
INPUT: $AB62 |
branch if INPUT |
TAKEN IF INPUT |
||
.,AB51 30 04 BMI $AB57 |
BMI GETDTL |
READ: $AB57 |
branch if READ else was GET |
TAKEN IF READ |
||
.,AB53 A0 FF LDY #$FF |
LDYI 255 ;MAKE IT LOOK DIRECT. |
GET: |
set current line high byte to -1, indicate immediate mode |
FROM A GET |
||
.,AB55 D0 04 BNE $AB5B |
BNEA STCURL ;ALWAYS GOES. GETDTL:> |
unbedingter SprungFehler bei READ |
branch always |
...ALWAYS |
||
.,AB57 A5 3F LDA $3F |
LDWD DATLIN ;GET DATA LINE NUMBER. |
DATA-Zeilennummer |
get current DATA line number low byte |
TELL WHERE THE "DATA" IS, RATHER |
||
.,AB59 A4 40 LDY $40 |
holen (LOW- und HIGH-Byte)Fehler bei GET |
get current DATA line number high byte |
THAN THE "READ" |
|||
.,AB5B 85 39 STA $39 |
STCURL: STWD CURLIN ;MAKE IT CURRENT LINE. |
gleiche Zeilennummer |
set current line number low byte |
|||
.,AB5D 84 3A STY $3A |
des Fehlers |
set current line number high byte |
||||
.,AB5F 4C 08 AF JMP $AF08 |
SNERR4: JMP SNERR TRMNO1: IFN EXTIO,< |
'SYNTAX ERROR'Fehler bei INPUT |
do syntax error then warm start was INPUT |
|||
.,AB62 A5 13 LDA $13 |
LDA CHANNL ;IF NOT TERMINAL, GIVE BAD DATA. |
Nummer des Eingabegeräts |
get current I/O channel |
|||
.,AB64 F0 05 BEQ $AB6B |
BEQ DOAGIN |
Tastatur: 'REDO FROM START' |
branch if default channel |
|||
.,AB66 A2 18 LDX #$18 |
LDXI ERRBD |
Nummer für 'FILE DATA' |
else error $18, file data error |
ERROR CODE = 254 |
||
.,AB68 4C 37 A4 JMP $A437 |
JMP ERROR> |
Fehlermeldung ausgeben |
do error #X then warm start |
|||
.,AB6B A9 0C LDA #$0C |
DOAGIN: LDWDI TRYAGN |
Zeiger in Akku und Y-Reg. |
set "?REDO FROM START" pointer low byte |
"?REENTER" |
low AD0C |
|
.,AB6D A0 AD LDY #$AD |
auf '?REDO FROM START' |
set "?REDO FROM START" pointer high byte |
high AD0C |
|||
.,AB6F 20 1E AB JSR $AB1E |
JSR STROUT ;PRINT "?REDO FROM START". |
String ausgeben |
print null terminated string |
|||
.,AB72 A5 3D LDA $3D |
LDWD OLDTXT ;POINT AT START |
Werte holen und |
get continue pointer low byte |
RE-EXECUTE THE WHOLE INPUT STATEMENT |
||
.,AB74 A4 3E LDY $3E |
Programmzeiger |
get continue pointer high byte |
||||
.,AB76 85 7A STA $7A |
STWD TXTPTR ;OF THIS CURRENT LINE. |
zurücksetzen |
save BASIC execute pointer low byte |
|||
.,AB78 84 7B STY $7B |
auf INPUT-Befehl |
save BASIC execute pointer high byte |
||||
.,AB7A 60 RTS |
RTS ;GO TO "NEWSTT". IFN GETCMD,< |
RücksprungBASIC-Befehl GET |
perform GET |
"GET" STATEMENT |
GET command |
|
.,AB7B 20 A6 B3 JSR $B3A6 |
GET: JSR ERRDIR ;DIRECT IS NOT OK. IFN EXTIO,< |
Testet auf Direkt-Modus |
check not Direct, back here if ok |
ILLEGAL IF IN DIRECT MODE |
||
.,AB7E C9 23 CMP #$23 |
CMPI "#" ;SEE IF "GET#". |
folgt '#’? |
compare with "#" |
# |
||
.,AB80 D0 10 BNE $AB92 |
BNE GETTTY ;NO, JUST GET TTY INPUT. |
nein: $AB92 |
branch if not GET# |
|||
.,AB82 20 73 00 JSR $0073 |
JSR CHRGET ;MOVE UP TO NEXT BYTE. |
CHRGET nächstes Zeichen holen |
increment and scan memory |
|||
.,AB85 20 9E B7 JSR $B79E |
JSR GETBYT ;GET CHANNEL INTO X |
Byte-Wert holen |
get byte parameter |
|||
.,AB88 A9 2C LDA #$2C |
SYNCHK 44 ;COMMA? |
',' Komma |
set "," |
comma |
||
.,AB8A 20 FF AE JSR $AEFF |
prüft auf Code |
scan for CHR$(A), else do syntax error then warm start |
||||
.,AB8D 86 13 STX $13 |
JSR CQOIN ;GET CHANNEL OPEN FOR INPUT. |
Filenummer |
set current I/O channel |
|||
.,AB8F 20 1E E1 JSR $E11E |
STX CHANNL> |
CHKIN, Eingabe vorbereiten |
open channel for input with error check |
|||
.,AB92 A2 01 LDX #$01 |
GETTTY: LDXYI BUF+1 ;POINT TO 0. |
Zeiger auf |
set pointer low byte |
SIMULATE INPUT |
||
.,AB94 A0 02 LDY #$02 |
IFN BUFPAG,< |
Pufferende = $201 ein Zeichen |
set pointer high byte |
|||
.,AB96 A9 00 LDA #$00 |
LDAI 0 ;TO STUFF AND TO POINT. |
Wert laden und |
clear A |
|||
.,AB98 8D 01 02 STA $0201 |
STA BUF+1> IFE BUFPAG,< STY BUF+1> ;ZERO IT. |
Puffer mit $0 abschließen |
ensure null terminator |
|||
.,AB9B A9 40 LDA #$40 |
LDAI 64 ;TURN ON V-BIT. |
GET-Flag |
input mode = GET |
SET UP INPUTFLG |
GET code |
|
.,AB9D 20 0F AC JSR $AC0F |
JSR INPCO1 ;DO THE GET. IFN EXTIO,< |
Wertzuweisung an Variable |
perform the GET part of READ |
|||
.,ABA0 A6 13 LDX $13 |
LDX CHANNL |
Eingabegerät |
get current I/O channel |
|||
.,ABA2 D0 13 BNE $ABB7 |
BNE IORELE> ;RELEASE. |
nicht Tastatur, dann CLRCH |
if not default channel go do channel close and return |
|||
.,ABA4 60 RTS |
RTS> IFN EXTIO,< |
RücksprungBASIC-Befehl INPUT# |
perform INPUT# |
INPUT# command |
||
.,ABA5 20 9E B7 JSR $B79E |
INPUTN: JSR GETBYT ;GET CHANNEL NUMBER. |
holt Byte-Wert |
get byte parameter |
|||
.,ABA8 A9 2C LDA #$2C |
SYNCHK 44 ;A COMMA? |
',' Code für Komma |
set "," |
comma |
||
.,ABAA 20 FF AE JSR $AEFF |
prüft auf Komma |
scan for CHR$(A), else do syntax error then warm start |
||||
.,ABAD 86 13 STX $13 |
JSR CQOIN ;GO WHERE COMMODORE CHECKS IN OPEN. |
Eingabegerät |
set current I/O channel |
|||
.,ABAF 20 1E E1 JSR $E11E |
STX CHANNL |
CHKIN, Eingabe vorbereiten |
open channel for input with error check |
|||
.,ABB2 20 CE AB JSR $ABCE |
JSR NOTQTI ;DO INPUT TO VARIABLES. |
INPUT ohne Dialogstring |
perform INPUT with no prompt stringclose input and output channels |
|||
.,ABB5 A5 13 LDA $13 |
IODONE: LDA CHANNL ;RELEASE CHANNEL. |
Eingabegerät im Akku |
get current I/O channel |
|||
.,ABB7 20 CC FF JSR $FFCC |
IORELE: JSR CQCCHN |
setzt Eingabegerät zurück |
close input and output channels |
|||
.,ABBA A2 00 LDX #$00 |
LDXI 0 ;RESET CHANNEL TO TERMINAL. |
Wert laden und |
clear X |
|||
.,ABBC 86 13 STX $13 |
STX CHANNL |
Eingabegerät wieder Tastatur |
clear current I/O channel, flag default |
|||
.,ABBE 60 RTS |
RTS> INPUT: IFN REALIO,< LSR CNTWFL> ;BE TALKATIVE. |
RücksprungBASIC-Befehl INPUT |
perform INPUT |
"INPUT" STATEMENT |
INPUT command |
|
.,ABBF C9 22 CMP #$22 |
CMPI 34 ;A QUOTE? |
'"' Hochkomma? |
compare next byte with open quote |
CHECK FOR OPTIONAL PROMPT STRING |
quote mark |
|
.,ABC1 D0 0B BNE $ABCE |
BNE NOTQTI ;NO MESSAGE. |
nein: $ABDE |
if no prompt string just do INPUT |
NO, PRINT "?" PROMPT |
||
.,ABC3 20 BD AE JSR $AEBD |
JSR STRTXT ;LITERALIZE THE STRING IN TEXT |
Dialogstring holen |
print "..." string |
MAKE A PRINTABLE STRING OUT OF IT |
||
.,ABC6 A9 3B LDA #$3B |
SYNCHK 59 ;MUST END WITH SEMICOLON. |
';' Semikolon |
load A with ";" |
MUST HAVE ; NOW |
semi-colon |
|
.,ABC8 20 FF AE JSR $AEFF |
prüft auf Code |
scan for CHR$(A), else do syntax error then warm start |
||||
.,ABCB 20 21 AB JSR $AB21 |
JSR STRPRT ;PRINT IT OUT. |
String ausgeben |
print string from utility pointer done with prompt, now get data |
PRINT THE STRING |
||
.,ABCE 20 A6 B3 JSR $B3A6 |
NOTQTI: JSR ERRDIR ;USE COMMON ROUTINE SINCE DEF DIRECT |
prüft auf Direkt-Modus |
check not Direct, back here if ok |
ILLEGAL IF IN DIRECT MODE |
||
.,ABD1 A9 2C LDA #$2C |
LDAI 44 ;GET COMMA. |
',' Komma |
set "," |
PRIME THE BUFFER |
comma |
|
.,ABD3 8D FF 01 STA $01FF |
STA BUF-1 ;IS ALSO ILLEGAL. |
an Pufferstart |
save to start of buffer - 1 |
|||
.,ABD6 20 F9 AB JSR $ABF9 |
GETAGN: JSR QINLIN ;TYPE "?" AND INPUT A LINE OF TEXT. IFN EXTIO,< |
Fragezeichen ausgeben |
print "? " and get BASIC input |
NO STRING, PRINT "?" |
||
.,ABD9 A5 13 LDA $13 |
LDA CHANNL |
Nummer des Eingabegeräts |
get current I/O channel |
|||
.,ABDB F0 0D BEQ $ABEA |
BEQ BUFFUL |
Tastatur? ja: $ABEA |
branch if default I/O channel |
|||
.,ABDD 20 B7 FF JSR $FFB7 |
LDA CQSTAT ;GET STATUS BYTE. |
Status holen |
read I/O status word |
|||
.,ABE0 29 02 AND #$02 |
ANDI 2 |
Bit 1 isolieren (Tineout R.) |
mask no DSR/timeout |
|||
.,ABE2 F0 06 BEQ $ABEA |
BEQ BUFFUL ;A-OK. |
Time-out? |
branch if not error |
|||
.,ABE4 20 B5 AB JSR $ABB5 |
JSR IODONE ;BAD. CLOSE CHANNEL. |
ja: CLRCH,Tastatur aktivieren |
close input and output channels |
|||
.,ABE7 4C F8 A8 JMP $A8F8 |
JMP DATA ;SKIP REST OF INPUT. BUFFUL:> |
nächstes Statement ausführen |
perform DATA |
do DATA |
||
.,ABEA AD 00 02 LDA $0200 |
LDA BUF ;ANYTHING INPUT? |
erstes Zeichen holen |
get first byte in input buffer |
|||
.,ABED D0 1E BNE $AC0D |
BNE INPCON ;YES, CONTINUE. IFN EXTIO,< |
Ende? |
branch if not null else .. |
|||
.,ABEF A5 13 LDA $13 |
LDA CHANNL ;BLANK LINE MEANS GET ANOTHER. |
ja: Eingabegerät |
get current I/O channel |
|||
.,ABF1 D0 E3 BNE $ABD6 |
BNE GETAGN> ;IF NOT TERMINAL. |
nicht Tastatur: $ABD6 |
if not default channel go get BASIC input |
|||
.,ABF3 20 06 A9 JSR $A906 |
CLC ;MAKE SURE DONT PRINT BREAK |
Offset (Statement) suchen |
scan for next BASIC statement ([:] or [EOL]) |
|||
.,ABF6 4C FB A8 JMP $A8FB |
JMP STPEND ;NO, STOP. QINLIN: IFN EXTIO,< |
Programmzeiger auf Statement |
add Y to the BASIC execute pointer and returnprint "? " and get BASIC input |
get line into input buffer |
||
.,ABF9 A5 13 LDA $13 |
LDA CHANNL |
Eingabegerät holen |
get current I/O channel |
|||
.,ABFB D0 06 BNE $AC03 |
BNE GINLIN> |
nicht Tastatur: $AC03 |
skip "?" prompt if not default channel |
|||
.,ABFD 20 45 AB JSR $AB45 |
JSR OUTQST |
'?' ausgeben |
print "?" |
|||
.,AC00 20 3B AB JSR $AB3B |
JSR OUTSPC |
' ' Leerzeichen ausgeben |
print [SPACE] or [CURSOR RIGHT] |
|||
.,AC03 4C 60 A5 JMP $A560 |
GINLIN: JMP INLIN |
Eingabezeile holenBASIC-Befehl READ |
call for BASIC input and returnperform READ |
"READ" STATEMENT |
READ command |
|
.,AC06 A6 41 LDX $41 |
READ: LDXY DATPTR ;GET LAST DATA LOCATION. |
DATA-Zeiger nach |
get DATA pointer low byte |
Y,X POINTS AT NEXT DATA STATEMENT |
||
.,AC08 A4 42 LDY $42 |
$41/42 holen |
get DATA pointer high byte |
||||
.,AC0A A9 98 LDA #$98 |
XWD ^O1000,^O251 ;LDAI TYA TO MAKE IT NONZERO. IFE BUFPAG,< INPCON: > TYA IFN BUFPAG,< |
READ-Flag |
set input mode = READ |
SET INPUTFLG = $98 |
READ code |
|
.:AC0C 2C .BYTE $2C |
SKIP2 |
makes next line BIT $00A9 |
||||
.,AC0D A9 00 LDA #$00 |
INPCON: LDAI 0> ;SET FLAG THAT THIS IS INPUT |
Flagwert laden |
set input mode = INPUTperform GET |
SET INPUTFLG = $00PROCESS INPUT LIST(Y,X) IS ADDRESS OF INPUT DATA STRING(A) = VALUE FOR INPUTFLG: $00 FOR INPUT $40 FOR GET $98 FOR READ |
||
.,AC0F 85 11 STA $11 |
INPCO1: STA INPFLG ;STORE THE FLAG. ; ; IN THE PROCESSING OF DATA AND READ STATEMENTS: ; ONE POINTER POINTS TO THE DATA (IE, THE NUMBERS BEING FETCHED) ; AND ANOTHER POINTS TO THE LIST OF VARIABLES. ; ; THE POINTER INTO THE DATA ALWAYS STARTS POINTING TO A ; TERMINATOR -- A , : OR END-OF-LINE. ; ; AT THIS POINT TXTPTR POINTS TO LIST OF VARIABLES AND ; [Y,X] POINTS TO DATA OR INPUT LINE. ; |
und INPUT-Zeiger setzen |
set input mode flag, $00 = INPUT, $40 = GET, $98 = READ |
|||
.,AC11 86 43 STX $43 |
STXY INPPTR |
INPUT-Zeiger auf |
save READ pointer low byte |
ADDRESS OF INPUT STRING |
||
.,AC13 84 44 STY $44 |
Eingabequelle setzen |
save READ pointer high byte READ, GET or INPUT next variable from list |
||||
.,AC15 20 8B B0 JSR $B08B |
INLOOP: JSR PTRGET ;READ VARIABLE LIST. |
sucht Variable |
get variable address |
GET ADDRESS OF VARIABLE |
||
.,AC18 85 49 STA $49 |
STWD FORPNT ;SAVE POINTER FOR "LET" STRING STUFFING. |
Variablenadresse |
save address low byte |
|||
.,AC1A 84 4A STY $4A |
;RETURNS PNTR TOP VAR IN VARPNT. |
speichern |
save address high byte |
|||
.,AC1C A5 7A LDA $7A |
LDWD TXTPTR ;SAVE TEXT PNTR. |
LOW- und HIGH-Byte des |
get BASIC execute pointer low byte |
SAVE CURRENT TXTPTR, |
||
.,AC1E A4 7B LDY $7B |
Programmzeigers |
get BASIC execute pointer high byte |
WHICH POINTS INTO PROGRAM |
|||
.,AC20 85 4B STA $4B |
STWD VARTXT |
in $4B/$4C |
save BASIC execute pointer low byte |
|||
.,AC22 84 4C STY $4C |
Zwischenspeichern |
save BASIC execute pointer high byte |
||||
.,AC24 A6 43 LDX $43 |
LDXY INPPTR |
INPUT-Zeiger |
get READ pointer low byte |
SET TXTPTR TO POINT AT INPUT BUFFER |
||
.,AC26 A4 44 LDY $44 |
(LOW und HIGH) |
get READ pointer high byte |
OR "DATA" LINE |
|||
.,AC28 86 7A STX $7A |
STXY TXTPTR |
als Programmzeiger |
save as BASIC execute pointer low byte |
|||
.,AC2A 84 7B STY $7B |
abspeichern |
save as BASIC execute pointer high byte |
||||
.,AC2C 20 79 00 JSR $0079 |
JSR CHRGOT ;GET IT AND SET Z IF TERM. |
CHRGOT letztes Zeichen holen |
scan memory |
GET CHAR AT PNTR |
||
.,AC2F D0 20 BNE $AC51 |
BNE DATBK1 |
Endzeichen? nein: $AC51 |
branch if not null pointer was to null entry |
NOT END OF LINE OR COLON |
||
.,AC31 24 11 BIT $11 |
BIT INPFLG IFN GETCMD,< |
Eingabeflag |
test input mode flag, $00 = INPUT, $40 = GET, $98 = READ |
DOING A "GET"? |
||
.,AC33 50 0C BVC $AC41 |
BVC QDATA |
kein GET: $AC41 |
branch if not GET else was GET |
NO |
||
.,AC35 20 24 E1 JSR $E124 |
JSR CZGETL ;DON'T WANT INCHR. JUST ONE. IFE REALIO-4,< ANDI 127> |
GETIN |
get character from input device with error check |
YES, GET CHAR |
||
.,AC38 8D 00 02 STA $0200 |
STA BUF ;MAKE IT FIRST CHARACTER. |
Zeichen in Puffer schreiben |
save to buffer |
|||
.,AC3B A2 FF LDX #$FF |
LDXYI <BUF-1> ;POINT JUST BEFORE IT. |
Zeiger auf |
set pointer low byte |
|||
.,AC3D A0 01 LDY #$01 |
IFE BUFPAG,< |
Puffer setzen |
set pointer high byte |
|||
.,AC3F D0 0C BNE $AC4D |
BEQA DATBK> |
unbedingter Sprung |
go interpret single character |
...ALWAYS |
||
.,AC41 30 75 BMI $ACB8 |
IFN BUFPAG,< BNEA DATBK>> ;GO PROCESS. QDATA: BMI DATLOP ;SEARCH FOR ANOTHER DATA STATEMENT. IFN EXTIO,< |
READ: $ACB8 |
branch if READ else was INPUT |
DOING A "READ" |
||
.,AC43 A5 13 LDA $13 |
LDA CHANNL |
Eingabegerät holen |
get current I/O channel |
|||
.,AC45 D0 03 BNE $AC4A |
BNE GETNTH> |
nicht Tastatur: $AC4A |
skip "?" prompt if not default channel |
|||
.,AC47 20 45 AB JSR $AB45 |
JSR OUTQST |
Fragezeichen ausgeben |
print "?" |
DOING AN "INPUT", PRINT "?" |
||
.,AC4A 20 F9 AB JSR $ABF9 |
GETNTH: JSR QINLIN ;GET ANOTHER LINE. |
zweites Fragezeichen ausgeben |
print "? " and get BASIC input |
PRINT ANOTHER "?", AND INPUT A LINE |
||
.,AC4D 86 7A STX $7A |
DATBK: STXY TXTPTR ;SET FOR "CHRGET". |
Programmzeiger setzen |
save BASIC execute pointer low byte |
|||
.,AC4F 84 7B STY $7B |
(LOW und HIGH) |
save BASIC execute pointer high byte |
||||
.,AC51 20 73 00 JSR $0073 |
DATBK1: JSR CHRGET |
CHRGET nächstes Zeichen holen |
increment and scan memory, execute pointer now points to start of next data or null terminator |
GET NEXT INPUT CHAR |
||
.,AC54 24 0D BIT $0D |
BIT VALTYP ;GET VALUE TYPE. |
Typ-Flag |
test data type flag, $FF = string, $00 = numeric |
STRING OR NUMERIC? |
||
.,AC56 10 31 BPL $AC89 |
BPL NUMINS ;INPUT A NUMBER IF NUMERIC. IFN GETCMD,< |
kein String: $AC89 |
branch if numeric type is string |
NUMERIC |
||
.,AC58 24 11 BIT $11 |
BIT INPFLG ;GET? |
Eingabeflag |
test INPUT mode flag, $00 = INPUT, $40 = GET, $98 = READ |
STRING -- NOW WHAT INPUT TYPE? |
||
.,AC5A 50 09 BVC $AC65 |
BVC SETQUT ;NO, GO SET QUOTE. |
kein GET: $AC65 |
branch if not GET else do string GET |
NOT A "GET" |
||
.,AC5C E8 INX |
INX |
Programmzeiger erhöhen |
clear X ?? |
"GET" |
||
.,AC5D 86 7A STX $7A |
STX TXTPTR |
und neu setzen ($0200) |
save BASIC execute pointer low byte |
|||
.,AC5F A9 00 LDA #$00 |
LDAI 0 ;ZERO TERMINATORS. |
Wert laden und |
clear A |
|||
.,AC61 85 07 STA $07 |
STA CHARAC |
Trennzeichen setzen |
clear search character |
NO OTHER TERMINATORS THAN $00 |
||
.,AC63 F0 0C BEQ $AC71 |
BEQA RESETC> |
unbedingter Sprung |
branch always is string INPUT or string READ |
...ALWAYS |
||
.,AC65 85 07 STA $07 |
SETQUT: STA CHARAC ;ASSUME QUOTED STRING. |
nächstes Zeichen |
save search character |
|||
.,AC67 C9 22 CMP #$22 |
CMPI 34 ;TERMINATORS OK? |
'"' Hochkomma? |
compare with " |
TERMINATE ON $00 OR QUOTE |
quote mark |
|
.,AC69 F0 07 BEQ $AC72 |
BEQ NOWGET ;YES. |
ja: $AC72 |
branch if quote string is not in quotes so ":", "," or $00 are the termination characters |
|||
.,AC6B A9 3A LDA #$3A |
LDAI ":" ;SET TERMINATORS TO ":" AND |
':' Doppelpunktcode laden |
set ":" |
TERMINATE ON $00, COLON, OR COMMA |
colon |
|
.,AC6D 85 07 STA $07 |
STA CHARAC |
und abspeichern |
set search character |
|||
.,AC6F A9 2C LDA #$2C |
LDAI 44 ;COMMA. |
',' Kommacode (Endzeichen |
set "," |
comma |
||
.,AC71 18 CLC |
RESETC: CLC |
für Stringübertragung) |
clear carry for add |
|||
.,AC72 85 08 STA $08 |
NOWGET: STA ENDCHR |
abspeichern |
set scan quotes flag |
|||
.,AC74 A5 7A LDA $7A |
LDWD TXTPTR |
Programmzeiger laden |
get BASIC execute pointer low byte |
|||
.,AC76 A4 7B LDY $7B |
(LOW und HIGH) |
get BASIC execute pointer high byte |
||||
.,AC78 69 00 ADC #$00 |
ADCI 0 ;C IS SET PROPERLY ABOVE. |
und Übertrag addieren |
add to pointer low byte. this add increments the pointer if the mode is INPUT or READ and the data is a "..." string |
SKIP OVER QUOTATION MARK, IF |
||
.,AC7A 90 01 BCC $AC7D |
BCC NOWGE1 |
C = 0: $AC7D |
branch if no rollover |
THERE WAS ONE |
||
.,AC7C C8 INY |
INY |
bei "'" um 1 erhöhen |
else increment pointer high byte |
|||
.,AC7D 20 8D B4 JSR $B48D |
NOWGE1: JSR STRLT2 ;MAKE A STRING DESCRIPTOR FOR THE VALUE ;AND COPY IF NECESSARY. |
String übernehmen |
print string to utility pointer |
BUILD STRING STARTING AT (Y,A) TERMINATED BY $00, (CHARAC), OR (ENDCHR) |
||
.,AC80 20 E2 B7 JSR $B7E2 |
JSR ST2TXT ;SET TEXT POINTER. |
Programmzeiger hinter String |
restore BASIC execute pointer from temp |
SET TXTPTR TO POINT AT STRING |
||
.,AC83 20 DA A9 JSR $A9DA |
JSR INPCOM ;DO ASSIGNMENT. |
String an Variable zuweisen |
perform string LET |
STORE STRING IN VARIABLE |
||
.,AC86 4C 91 AC JMP $AC91 |
JMP STRDN2 |
weiter machen |
continue processing command GET, INPUT or READ is numeric |
|||
.,AC89 20 F3 BC JSR $BCF3 |
NUMINS: JSR FIN IFE INTPRC,< JSR MOVVF> IFN INTPRC,< |
Ziffernstring in FAC holen |
get FAC1 from string |
GET FP NUMBER AT TXTPTR |
||
.,AC8C A5 0E LDA $0E |
LDA INTFLG ;SET CODES ON FLAG. |
INTEGER/REAL-Flag |
get data type flag, $80 = integer, $00 = float |
|||
.,AC8E 20 C2 A9 JSR $A9C2 |
JSR QINTGR> ;GO DECIDE ON FLOAT. |
FAC an numerische Variable |
assign value to numeric variable |
STORE RESULT IN VARIABLE |
||
.,AC91 20 79 00 JSR $0079 |
STRDN2: JSR CHRGOT ;READ LAST CHARACTER. |
CHRGOT: letztes Zeichen holen |
scan memory |
|||
.,AC94 F0 07 BEQ $AC9D |
BEQ TRMOK ;":" OR EOL IS OK. |
Ende? |
branch if ":" or [EOL] |
END OF LINE OR COLON |
||
.,AC96 C9 2C CMP #$2C |
CMPI 44 ;A COMMA? |
',' Code? |
comparte with "," |
COMMA IN INPUT? |
comma |
|
.,AC98 F0 03 BEQ $AC9D |
JNE TRMNOK |
ja: $AC9D |
branch if "," |
YES |
||
.,AC9A 4C 4D AB JMP $AB4D |
zur Fehlerbehandlung |
else go do bad input routine string terminated with ":", "," or $00 |
NOTHING ELSE WILL DO |
|||
.,AC9D A5 7A LDA $7A |
TRMOK: LDWD TXTPTR |
Programmzeiger |
get BASIC execute pointer low byte |
SAVE POSITION IN INPUT BUFFER |
||
.,AC9F A4 7B LDY $7B |
holen und |
get BASIC execute pointer high byte |
||||
.,ACA1 85 43 STA $43 |
STWD INPPTR ;SAVE FOR MORE READS. |
in DATA-Zeiger |
save READ pointer low byte |
|||
.,ACA3 84 44 STY $44 |
abspeichern |
save READ pointer high byte |
||||
.,ACA5 A5 4B LDA $4B |
LDWD VARTXT |
ursprüngliche |
get saved BASIC execute pointer low byte |
RESTORE PROGRAM POINTER |
||
.,ACA7 A4 4C LDY $4C |
Programmzeiger |
get saved BASIC execute pointer high byte |
||||
.,ACA9 85 7A STA $7A |
STWD TXTPTR ;POINT TO VARIABLE LIST. |
wieder zurückholen |
restore BASIC execute pointer low byte |
|||
.,ACAB 84 7B STY $7B |
und speichern |
restore BASIC execute pointer high byte |
||||
.,ACAD 20 79 00 JSR $0079 |
JSR CHRGOT ;LOOK AT LAST VARIABLE LIST CHARACTER. |
CHRGOT: letztes Zeichen holen |
scan memory |
NEXT CHAR FROM PROGRAM |
||
.,ACB0 F0 2D BEQ $ACDF |
BEQ VAREND ;THAT'S THE END OF THE LIST. |
Trennzeichen: $ACDF |
branch if ":" or [EOL] |
END OF STATEMENT |
||
.,ACB2 20 FD AE JSR $AEFD |
JSR CHKCOM ;NOT END. CHECK FOR COMMA. |
CKCOM: prüft auf Komma |
scan for ",", else do syntax error then warm start |
BETTER BE A COMMA THEN |
||
.,ACB5 4C 15 AC JMP $AC15 |
JMP INLOOP ; ; SUBROUTINE TO FIND DATA ; THE SEARCH IS MADE BY USING THE EXECUTION CODE FOR DATA TO ; SKIP OVER STATEMENTS. THE START WORD OF EACH STATEMENT ; IS COMPARED WITH "DATATK". EACH NEW LINE NUMBER ; IS STORED IN "DATLIN" SO THAT IF AN ERROR OCCURS ; WHILE READING DATA THE ERROR MESSAGE CAN GIVE THE LINE ; NUMBER OF THE ILL-FORMATTED DATA. ; |
weiter |
go READ or INPUT next variable from list was READ |
|||
.,ACB8 20 06 A9 JSR $A906 |
DATLOP: JSR DATAN ;SKIP SOME TEXT. |
nächstes Statement suchen |
scan for next BASIC statement ([:] or [EOL]) |
GET OFFSET TO NEXT COLON OR EOL |
||
.,ACBB C8 INY |
INY |
Offset erhöhen |
increment index to next byte |
TO FIRST CHAR OF NEXT LINE |
||
.,ACBC AA TAX |
TAX ;END OF LINE? |
Zeilenende? |
copy byte to X |
WHICH: EOL OR COLON? |
||
.,ACBD D0 12 BNE $ACD1 |
BNE NOWLIN ;SHO AIN'T. |
nein: $ACD1 |
branch if ":" |
COLON |
||
.,ACBF A2 0D LDX #$0D |
LDXI ERROD ;YES = "NO DATA" ERROR. |
'OUT OF DATA' Code |
else set error $0D, out of data error |
EOL: MIGHT BE OUT OF DATA |
error number |
|
.,ACC1 C8 INY |
INY |
Zeiger erhöhen |
increment index to next line pointer high byte |
CHECK HI-BYTE OF FORWARD PNTR |
||
.,ACC2 B1 7A LDA ($7A),Y |
LDADY TXTPTR |
Programmende? |
get next line pointer high byte |
END OF PROGRAM? |
||
.,ACC4 F0 6C BEQ $AD32 |
BEQ ERRGO5 |
ja: 'OUT OF DATA', X = 0 |
branch if program end, eventually does error X |
YES, WE ARE OUT OF DATA |
||
.,ACC6 C8 INY |
INY |
Zeiger erhöhen |
increment index |
PICK UP THE LINE # |
||
.,ACC7 B1 7A LDA ($7A),Y |
LDADY TXTPTR ;GET HIGH BYTE OF LINE NUMBER. |
Zeilennummer (LOW) holen |
get next line # low byte |
|||
.,ACC9 85 3F STA $3F |
STA DATLIN |
und abspeichern |
save current DATA line low byte |
|||
.,ACCB C8 INY |
INY |
Zeiger erhöhen |
increment index |
|||
.,ACCC B1 7A LDA ($7A),Y |
LDADY TXTPTR ;GET LOW BYTE. |
Zeilenummer (HIGH) |
get next line # high byte |
|||
.,ACCE C8 INY |
INY |
Zeiger erhöhen |
increment index |
POINT AT FIRST TEXT CHAR IN LINE |
||
.,ACCF 85 40 STA $40 |
STA DATLIN+1 |
Zeilennummer speichern |
save current DATA line high byte |
|||
.,ACD1 20 FB A8 JSR $A8FB |
NOWLIN: LDADY TXTPTR ;HOW IS IT? |
Programmz. auf Statement |
add Y to the BASIC execute pointer |
GET 1ST TOKEN OF STATEMENT |
||
.,ACD4 20 79 00 JSR $0079 |
TAX |
CHRGOT letztes Zeichen holen |
scan memory |
|||
.,ACD7 AA TAX |
JSR ADDON ;ADD [Y] TO [TXTPTR]. |
und ins X-Reg. |
copy the byte |
SAVE TOKEN IN X-REG |
||
.,ACD8 E0 83 CPX #$83 |
CPXI DATATK ;IS IT A "DATA" STATEMENT. |
'DATA' Code? |
compare it with token for DATA |
DID WE FIND A "DATA" STATEMENT? |
DATA code |
|
.,ACDA D0 DC BNE $ACB8 |
BNE DATLOP ;NOT QUITE RIGHT. KEEP LOOKING. |
nein: weitersuchen |
loop if not DATA |
NOT YET |
||
.,ACDC 4C 51 AC JMP $AC51 |
JMP DATBK1 ;THIS IS THE ONE ! |
Daten lesen |
continue evaluating READ |
YES, READ IT NO MORE INPUT REQUESTED |
||
.,ACDF A5 43 LDA $43 |
VAREND: LDWD INPPTR ;PUT AWAY A NEW DATA PNTR MAYBE. |
LOW- und HIGH-Byte des |
get READ pointer low byte |
GET POINTER IN CASE IT WAS "READ" |
||
.,ACE1 A4 44 LDY $44 |
Input-Zeigers |
get READ pointer high byte |
||||
.,ACE3 A6 11 LDX $11 |
LDX INPFLG |
Eingabe-Flag |
get INPUT mode flag, $00 = INPUT, $40 = GET, $98 = READ |
"READ" OR "INPUT"? |
||
.,ACE5 10 03 BPL $ACEA |
BPL VARY0 |
kein DATA: $ACEA |
branch if INPUT or GET |
"INPUT" |
||
.,ACE7 4C 27 A8 JMP $A827 |
JMP RESFIN |
DATA-Zeiger setzen |
else set data pointer and exit |
"DATA", SO STORE (Y,X) AT DATPTR |
||
.,ACEA A0 00 LDY #$00 |
VARY0: LDYI 0 |
Zeiger setzen |
clear index |
"INPUT": ANY MORE CHARS ON LINE? |
||
.,ACEC B1 43 LDA ($43),Y |
LDADY INPPTR ;LAST DATA CHR COULD HAVE BEEN ;COMMA OR COLON BUT SHOULD BE NULL. |
nächstes Zeichen holen |
get READ byte |
|||
.,ACEE F0 0B BEQ $ACFB |
BEQ INPRTS ;IT IS NULL. IFN EXTIO,< |
Endzeichen: $ACFB |
exit if [EOL] |
NO, ALL IS WELL |
||
.,ACF0 A5 13 LDA $13 |
LDA CHANNL ;IF NOT TERMINAL, NO TYPE. |
Eingabe über Tastatur? |
get current I/O channel |
YES, ERROR |
||
.,ACF2 D0 07 BNE $ACFB |
BNE INPRTS> |
nein: $ACFB |
exit if not default channel |
|||
.,ACF4 A9 FC LDA #$FC |
LDWDI EXIGNT |
Zeiger auf |
set "?EXTRA IGNORED" pointer low byte |
low ACFC |
||
.,ACF6 A0 AC LDY #$AC |
'?extra ignored' setzen |
set "?EXTRA IGNORED" pointer high byte |
"EXTRA IGNORED" |
high ACFC |
||
.,ACF8 4C 1E AB JMP $AB1E |
JMP STROUT ;TYPE "?EXTRA IGNORED" |
String ausgeben |
print null terminated string |
|||
.,ACFB 60 RTS |
INPRTS: RTS ;DO NEXT STATEMENT. |
Rücksprung |
input error messages |
messages used dring READ |
||
.:ACFC 3F 45 58 54 52 41 20 49 |
EXIGNT: DT"?EXTRA IGNORED" |
'?extra ignored' |
'?extra ignored' |
'?extra ignored' |
?EXTRA IGNORED |
|
.:AD04 47 4E 4F 52 45 44 0D 00 |
ACRLF |
|||||
.:AD0C 3F 52 45 44 4F 20 46 52 |
0 |
'?redo from start' |
'?redo from start' |
'?redo from start' |
?REDO FROM START |
|
.:AD14 4F 4D 20 53 54 41 52 54 |
TRYAGN: DT"?REDO FROM START" |
|||||
.:AD1C 0D 00 |
ACRLF 0 PAGE THE NEXT CODE IS THE "NEXT CODE";; A "FOR" ENTRY ON THE STACK HAS THE FOLLOWING FORMAT: ; ; LOW ADDRESS ; TOKEN (FORTK) 1 BYTE ; A POINTER TO THE LOOP VARIABLE 2 BYTES ; THE STEP 4+ADDPRC BYTES ; A BYTE REFLECTING THE SIGN OF THE INCREMENT 1 BYTE ; THE UPPER VALUE (PACKED) 4+ADDPRC BYTES ; THE LINE NUMBER OF THE "FOR" STATEMENT 2 BYTES ; A TEXT POINTER INTO THE "FOR" STATEMENT 2 BYTES ; HIGH ADDRESS ; ; TOTAL 16+2*ADDPRC BYTES. ; |
BASIC-Befehl NEXT |
perform NEXT |
"NEXT" STATEMENT |
NEXT command |
|
.,AD1E D0 04 BNE $AD24 |
NEXT: BNE GETFOR |
folgt Variablenname? ja:$AD24 |
branch if NEXT variable |
VARIABLE AFTER "NEXT" |
||
.,AD20 A0 00 LDY #$00 |
LDYI 0 ;WITHOUT ARG CALL "FNDFOR" WITH |
Variablenzeiger = 0 |
else clear Y |
FLAG BY SETTING FORPNT+1 = 0 |
||
.,AD22 F0 03 BEQ $AD27 |
BEQA STXFOR ;[FORPNT]=0. |
unbedingter Sprung |
branch always NEXT variable |
...ALWAYS |
||
.,AD24 20 8B B0 JSR $B08B |
GETFOR: JSR PTRGET ;GET A POINTER TO LOOP VARIABLE |
sucht Variable |
get variable address |
GET PNTR TO VARIABLE IN (Y,A) |
||
.,AD27 85 49 STA $49 |
STXFOR: STWD FORPNT ;INTO "FORPNT". |
Adresse der |
save FOR/NEXT variable pointer low byte |
|||
.,AD29 84 4A STY $4A |
Variablen speichern |
save FOR/NEXT variable pointer high byte (high byte cleared if no variable defined) |
||||
.,AD2B 20 8A A3 JSR $A38A |
JSR FNDFOR ;FIND THE MATCHING ENTRY IF ANY. |
sucht FOR-NEXT-Schleife |
search the stack for FOR or GOSUB activity |
FIND FOR-FRAME FOR THIS VARIABLE |
||
.,AD2E F0 05 BEQ $AD35 |
BEQ HAVFOR |
gefunden: $AD35 |
branch if FOR, this variable, found |
FOUND IT |
||
.,AD30 A2 0A LDX #$0A |
LDXI ERRNF ;"NEXT WITHOUT FOR". |
Nummer für 'next without for' |
else set error $0A, next without for error |
NOT THERE, ABORT |
error number |
|
.,AD32 4C 37 A4 JMP $A437 |
ERRGO5: BEQ ERRGO4 |
Fehlermeldung ausgeben |
do error #X then warm start found this FOR variable |
...ALWAYS |
||
.,AD35 9A TXS |
HAVFOR: TXS ;SETUP STACK. CHOP FIRST. |
X-Reg. retten |
update stack pointer |
SET STACK PTR TO POINT TO THIS FRAME, |
||
.,AD36 8A TXA |
TXA |
X-Register nach Akku |
copy stack pointer |
|||
.,AD37 18 CLC |
CLC |
Carry löschen (Addition) |
clear carry for add |
|||
.,AD38 69 04 ADC #$04 |
ADCI 4 ;POINT TO INCREMENT |
Zeiger auf Exponenten des |
point to STEP value |
|||
.,AD3A 48 PHA |
PHA ;SAVE THIS POINTER TO RESTORE TO [A] |
STEP-Wert + 4 und retten |
save it |
|||
.,AD3B 69 06 ADC #$06 |
ADCI 5+ADDPRC ;POINT TO UPPER LIMIT |
Zeiger auf Exponent des TO- |
point to TO value |
|||
.,AD3D 85 24 STA $24 |
STA INDEX2 ;SAVE AS INDEX |
Wert und retten |
save pointer to TO variable for compare |
|||
.,AD3F 68 PLA |
PLA ;RESTORE POINTER TO INCREMENT |
Akku wieder vom Stapel holen |
restore pointer to STEP value |
|||
.,AD40 A0 01 LDY #$01 |
LDYI 1 ;SET HI ADDR OF THING TO MOVE. |
Zeiger für Konstante setzen |
point to stack page |
(Y,A) IS ADDRESS OF STEP VALUE |
||
.,AD42 20 A2 BB JSR $BBA2 |
JSR MOVFM ;GET QUANTITY INTO THE FAC. |
Variable vom Stapel nach FAC |
unpack memory (AY) into FAC1 |
STEP TO FAC |
||
.,AD45 BA TSX |
TSX |
Stapelzeiger als Zeiger h. |
get stack pointer back |
|||
.,AD46 BD 09 01 LDA $0109,X |
LDA 257+7+ADDPRC,X, ;SET SIGN CORRECTLY. |
Vorzeichenbyte holen und |
get step sign |
|||
.,AD49 85 66 STA $66 |
STA FACSGN |
für FAC speichern |
save FAC1 sign (b7) |
|||
.,AD4B A5 49 LDA $49 |
LDWD FORPNT |
Variablenadresse für |
get FOR/NEXT variable pointer low byte |
|||
.,AD4D A4 4A LDY $4A |
FOR-NEXT holen |
get FOR/NEXT variable pointer high byte |
||||
.,AD4F 20 67 B8 JSR $B867 |
JSR FADD ;ADD INC TO LOOP VARIABLE. |
addiert STEP-Wert zu FAC |
add FOR variable to FAC1 |
ADD TO FOR VALUE |
||
.,AD52 20 D0 BB JSR $BBD0 |
JSR MOVVF ;PACK THE FAC INTO MEMORY. |
FAC nach Variable bringen |
pack FAC1 into FOR variable |
PUT NEW VALUE BACK |
||
.,AD55 A0 01 LDY #$01 |
LDYI 1 |
Zeiger auf Konstante setzen |
point to stack page |
(Y,A) IS ADDRESS OF END VALUE |
||
.,AD57 20 5D BC JSR $BC5D |
JSR FCOMPN ;COMPARE FAC WITH UPPER VALUE. |
FAC mit Schleifenendwert vergleichen |
compare FAC1 with TO value |
COMPARE TO END VALUE |
||
.,AD5A BA TSX |
TSX |
Stapelzeiger als Zeiger h. |
get stack pointer back |
|||
.,AD5B 38 SEC |
SEC |
Carry setzen (Subtraktion) |
set carry for subtract |
|||
.,AD5C FD 09 01 SBC $0109,X |
SBC 257+7+ADDPRC,X, ;SUBTRACT SIGN OF INC FROM SIGN OF ;OF (CURRENT VALUE-FINAL VALUE). |
Stapelwert größer? |
subtract step sign |
SIGN OF STEP |
||
.,AD5F F0 17 BEQ $AD78 |
BEQ LOOPDN ;IF SIGN (FINAL-CURRENT)-SIGN STEP=0 ;THEN LOOP IS DONE. |
ja: Schleife verlassen |
branch if =, loop complete loop back and do it all again |
BRANCH IF FOR COMPLETE |
||
.,AD61 BD 0F 01 LDA $010F,X |
LDA 2*ADDPRC+12+257,X |
Zeilennummer des Schleifen- |
get FOR line low byte |
OTHERWISE SET UP |
||
.,AD64 85 39 STA $39 |
STA CURLIN ;STORE LINE NUMBER OF "FOR" STATEMENT. |
anfangs holen (LOW- und |
save current line number low byte |
FOR LINE # |
||
.,AD66 BD 10 01 LDA $0110,X |
LDA 257+13+<2*ADDPRC>,X |
HIGH-Byte) und als aktuelle |
get FOR line high byte |
|||
.,AD69 85 3A STA $3A |
STA CURLIN+1 |
BASIC-Zeilennummer speichern |
save current line number high byte |
|||
.,AD6B BD 12 01 LDA $0112,X |
LDA 2*ADDPRC+15+257,X |
Schleifenanfang holen (LOW- |
get BASIC execute pointer low byte |
AND SET TXTPTR TO JUST |
||
.,AD6E 85 7A STA $7A |
STA TXTPTR ;STORE TEXT PNTR INTO "FOR" STATEMENT. |
und HIGH-Byte) und |
save BASIC execute pointer low byte |
AFTER FOR STATEMENT |
||
.,AD70 BD 11 01 LDA $0111,X |
LDA 2*ADDPRC+14+257,X |
als neuen Programmzeiger |
get BASIC execute pointer high byte |
|||
.,AD73 85 7B STA $7B |
STA TXTPTR+1 |
abspeichern |
save BASIC execute pointer high byte |
|||
.,AD75 4C AE A7 JMP $A7AE |
NEWSGO: JMP NEWSTT ;PROCESS NEXT STATEMENT. |
zur Interpreterschleife |
go do interpreter inner loop NEXT loop comlete |
|||
.,AD78 8A TXA |
LOOPDN: TXA |
Zeiger in Akku holen |
stack copy to A |
POP OFF FOR-FRAME, LOOP IS DONE |
||
.,AD79 69 11 ADC #$11 |
ADCI 2*ADDPRC+15 ;ADDS 16 WITH CARRY. |
(Werte der Schleife aus |
add $12, $11 + carry, to dump FOR structure |
CARRY IS SET, SO ADDS 18 |
||
.,AD7B AA TAX |
TAX |
Stapel entfernen) |
copy back to index |
|||
.,AD7C 9A TXS |
TXS ;NEW STACK PNTR. |
neuen Stapelzeiger setzen |
copy to stack pointer |
|||
.,AD7D 20 79 00 JSR $0079 |
JSR CHRGOT |
CHRGOT letztes Zeichen holen |
scan memory |
CHAR AFTER VARIABLE |
||
.,AD80 C9 2C CMP #$2C |
CMPI 44 ;COMMA AT END? |
',' Komma? |
compare with "," |
ANOTHER VARIABLE IN NEXT? |
comma |
|
.,AD82 D0 F1 BNE $AD75 |
BNE NEWSGO |
nein: dann fertig |
if not "," go do interpreter inner loop was "," so another NEXT variable to do |
NO, GO TO NEXT STATEMENT |
||
.,AD84 20 73 00 JSR $0073 |
JSR CHRGET |
CHRGET nächstes Zeichen holen |
increment and scan memory |
YES, PRIME FOR NEXT VARIABLE |
||
.,AD87 20 24 AD JSR $AD24 |
JSR GETFOR ;DO NEXT BUT DON'T ALLOW BLANK VARIABLE ;PNTR. [VARPNT] IS THE STK PNTR WHICH ;NEVER MATCHES ANY POINTER. ;JSR TO PUT ON DUMMY NEWSTT ADDR. FORMULA EVALUATION CODE.;; THESE ROUTINES CHECK FOR CERTAIN "VALTYP". ; [C] IS NOT PRESERVED. ; |
nächste NEXT-VariableFRMNUM Ausdruck holen undauf numerisch prüfen |
do NEXT variableevaluate expression and check type mismatch |
(DOES NOT RETURN)EVALUATE EXPRESSION, MAKE SURE IT IS NUMERIC |
get next non-string value |
|
.,AD8A 20 9E AD JSR $AD9E |
FRMNUM: JSR FRMEVL |
FRMEVL Term holenprüft auf numerisch |
evaluate expression check if source and destination are numeric |
MAKE SURE (FAC) IS NUMERIC |
||
.,AD8D 18 CLC |
CHKNUM: CLC |
Flag für Test auf numerisch |
||||
.:AD8E 24 .BYTE $24 |
SKIP1 |
BIT-Befehl um folgenden Befehl auszulassenprüft auf String |
makes next line BIT $38 check if source and destination are string |
DUMMY FOR SKIPMAKE SURE (FAC) IS STRING |
check value to be string |
|
.,AD8F 38 SEC |
CHKSTR: SEC ;SET CARRY. |
Flag für Test auf String |
destination is string type match check, set C for string, clear C for numeric |
MAKE SURE (FAC) IS CORRECT TYPEIF C=0, TYPE MUST BE NUMERICIF C=1, TYPE MUST BE STRING |
check value according to C flag |
|
.,AD90 24 0D BIT $0D |
CHKVAL: BIT VALTYP ;WILL NOT F UP "VALTYP". |
Typflag testen |
test data type flag, $FF = string, $00 = numeric |
$00 IF NUMERIC, $FF IF STRING |
||
.,AD92 30 03 BMI $AD97 |
BMI DOCSTR |
gesetzt: $AD97 |
branch if string |
TYPE IS STRING |
||
.,AD94 B0 03 BCS $AD99 |
BCS CHKERR |
C=1: 'TYPE MISMATCH' |
if destiantion is numeric do type missmatch error |
NOT STRING, BUT WE NEED STRING |
||
.,AD96 60 RTS |
CHKOK: RTS |
Rücksprung |
TYPE IS CORRECT |
|||
.,AD97 B0 FD BCS $AD96 |
DOCSTR: BCS CHKOK |
C=1: RTS |
exit if destination is string do type missmatch error |
IS STRING AND WE WANTED STRING |
||
.,AD99 A2 16 LDX #$16 |
CHKERR: LDXI ERRTM |
Nummer für 'TYPE MISMATCH' |
error code $16, type missmatch error |
TYPE MISMATCH |
||
.,AD9B 4C 37 A4 JMP $A437 |
ERRGO4: JMP ERROR ; ; THE FORMULA EVALUATOR STARTS WITH ; [TXTPTR] POINTING TO THE FIRST CHARACTER OF THE FORMULA. ; AT THE END [TXTPTR] POINTS TO THE TERMINATOR. ; THE RESULT IS LEFT IN THE FAC. ; ON RETURN [A] DOES NOT REFLECT THE TERMINATOR. ; ; THE FORMULA EVALUATOR USES THE OPERATOR LIST (OPTAB) ; TO DETERMINE PRECEDENCE AND DISPATCH ADDRESSES FOR ; EACH OPERATOR. ; A TEMPORARY RESULT ON THE STACK HAS THE FOLLOWING FORMAT. ; THE ADDRESS OF THE OPERATOR ROUTINE. ; THE FLOATING POINT TEMPORARY RESULT. ; THE PRECEDENCE OF THE OPERATOR. ; |
Fehlermeldung ausgebenFRMEVL auswerten einesbeliebigen Ausdrucks |
do error #X then warm startevaluate expression |
EVALUATE THE EXPRESSION AT TXTPTR, LEAVING THERESULT IN FAC.WORKS FOR BOTH STRING AND NUMERIC EXPRESSIONS. |
evaluate expression |
|
.,AD9E A6 7A LDX $7A |
FRMEVL: LDX TXTPTR |
Programmzeiger (LOW) = 0? |
get BASIC execute pointer low byte |
DECREMENT TXTPTR |
||
.,ADA0 D0 02 BNE $ADA4 |
BNE FRMEV1 |
ja: HIGH-B. nicht vermindern |
skip next if not zero |
|||
.,ADA2 C6 7B DEC $7B |
DEC TXTPTR+1 |
HIGH-Byte vermindern |
else decrement BASIC execute pointer high byte |
|||
.,ADA4 C6 7A DEC $7A |
FRMEV1: DEC TXTPTR |
LOW-Byte vermindern |
decrement BASIC execute pointer low byte |
|||
.,ADA6 A2 00 LDX #$00 |
LDXI 0 ;INITIAL DUMMY PRECEDENCE IS 0. |
Prioritätswert laden |
set null precedence, flag done |
START WITH PRECEDENCE = 0 |
||
.:ADA8 24 .BYTE $24 |
SKIP1 |
makes next line BIT $48 |
TRICK TO SKIP FOLLOWING "PHA" |
|||
.,ADA9 48 PHA |
LPOPER: PHA ;SAVE LOW PRECEDENCE. (MASK.) |
Operatormaske retten |
push compare evaluation byte if branch to here |
PUSH RELOPS FLAGS |
||
.,ADAA 8A TXA |
TXA |
Prioritätswert in Akku |
copy precedence byte |
|||
.,ADAB 48 PHA |
PHA ;SAVE HIGH PRECEDENCE. |
schieben und retten |
push precedence byte |
SAVE LAST PRECEDENCE |
||
.,ADAC A9 01 LDA #$01 |
LDAI 1 |
2 Bytes |
2 bytes |
|||
.,ADAE 20 FB A3 JSR $A3FB |
JSR GETSTK ;MAKE SURE THERE IS ROOM FOR ;RECURSIVE CALLS. |
prüft auf Platz im Stapel |
check room on stack for A*2 bytes |
CHECK IF ENOUGH ROOM ON STACK |
||
.,ADB1 20 83 AE JSR $AE83 |
JSR EVAL ;EVALUATE SOMETHING. |
Nächstes Element holen |
get value from line |
GET AN ELEMENT |
||
.,ADB4 A9 00 LDA #$00 |
CLR OPMASK ;PREPARE TO BUILD MASK MAYBE. |
Wert laden und |
clear A |
|||
.,ADB6 85 4D STA $4D |
Maske für Vergleichsoperator |
clear comparrison evaluation flag |
CLEAR COMPARISON OPERATOR FLAGS |
|||
.,ADB8 20 79 00 JSR $0079 |
TSTOP: JSR CHRGOT ;REGET LAST CHARACTER. |
CHRGOT letztes Zeichen holen |
scan memory |
CHECK FOR RELATIONAL OPERATORS |
||
.,ADBB 38 SEC |
LOPREL: SEC ;PREP TO SUBTRACT. |
Carry setzen (Subtraktion) |
set carry for subtract |
> IS $CF, = IS $D0, < IS $D1 |
||
.,ADBC E9 B1 SBC #$B1 |
SBCI GREATK ;IS CURRENT CHARACTER A RELATION? |
$B1 von Operatorcode subtr. |
subtract the token for ">" |
> IS 0, = IS 1, < IS 2 |
code for greater than |
|
.,ADBE 90 17 BCC $ADD7 |
BCC ENDREL ;NO. RELATIONS ALL THROUGH. |
C=0: $ADD7 |
branch if < ">" |
NOT RELATIONAL OPERATOR |
||
.,ADC0 C9 03 CMP #$03 |
CMPI LESSTK-GREATK+1 ;REALLY RELATIONAL? |
mit $3 vergleichen |
compare with ">" to +3 |
|||
.,ADC2 B0 13 BCS $ADD7 |
BCS ENDREL ;NO -- JUST BIG. |
=3: $ADD7 |
branch if >= 3 was token for ">" "=" or "<" |
NOT RELATIONAL OPERATOR |
||
.,ADC4 C9 01 CMP #$01 |
CMPI 1 ;RESET CARRY FOR ZERO ONLY. |
compare with token for = |
SET CARRY IF "=" OR "<" |
|||
.,ADC6 2A ROL |
ROL A, ;0 TO 1, 1 TO 2, 2 TO 4. |
Maske für kleiner |
*2, b0 = carry (=1 if token was = or <) |
NOW > IS 0, = IS 3, < IS 5 |
||
.,ADC7 49 01 EOR #$01 |
EORI 1 |
gleich und größer |
toggle b0 |
NOW > IS 1, = IS 2, < IS 4 |
||
.,ADC9 45 4D EOR $4D |
EOR OPMASK ;BRING IN THE OLD BITS. |
für Bits 0,1 und 2 |
EOR with comparrison evaluation flag |
SET BITS OF CPRTYP: 00000<=> |
||
.,ADCB C5 4D CMP $4D |
CMP OPMASK ;MAKE SURE THE NEW MASK IS BIGGER. |
in $40 erstellen |
compare with comparrison evaluation flag |
CHECK FOR ILLEGAL COMBINATIONS |
||
.,ADCD 90 61 BCC $AE30 |
BCC SNERR5 ;SYNTAX ERROR. BECAUSE TWO OF THE SAME. |
(Wenn Codes von 177 |
if < saved flag do syntax error then warm start |
IF LESS THAN, A RELOP WAS REPEATED |
||
.,ADCF 85 4D STA $4D |
STA OPMASK ;SAVE MASK. |
bis 179 folgen) |
save new comparrison evaluation flag |
|||
.,ADD1 20 73 00 JSR $0073 |
JSR CHRGET |
CHRGET nächstes Zeichen holen |
increment and scan memory |
ANOTHER OPERATOR? |
||
.,ADD4 4C BB AD JMP $ADBB |
JMP LOPREL ;GET THE NEXT CANDIDATE. |
nächstes Zeichen auswerten |
go do next character |
CHECK FOR <,=,> AGAIN |
||
.,ADD7 A6 4D LDX $4D |
ENDREL: LDX OPMASK ;WERE THERE ANY? |
Operatormaske holen |
get comparrison evaluation flag |
DID WE FIND A RELATIONAL OPERATOR? |
||
.,ADD9 D0 2C BNE $AE07 |
BNE FINREL ;YES, HANDLE AS SPECIAL OP. |
gleich 0? nein: $AE07 |
branch if compare function |
YES |
||
.,ADDB B0 7B BCS $AE58 |
BCS QOP ;NOT AN OPERATOR. |
Code größer oder gleich 180? |
go do functions else was < TK_GT so is operator or lower |
NO, AND NEXT TOKEN IS > $D1 |
||
.,ADDD 69 07 ADC #$07 |
ADCI GREATK-PLUSTK |
Code kleiner 170? |
add # of operators (+, -, *, /, ^, AND or OR) |
NO, AND NEXT TOKEN < $CF |
||
.,ADDF 90 77 BCC $AE58 |
BCC QOP ;NOT AN OPERATOR. |
ja: $AE58 |
branch if < + operator carry was set so token was +, -, *, /, ^, AND or OR |
IF NEXT TOKEN < "+" |
||
.,ADE1 65 0D ADC $0D |
ADC VALTYP ;[C]=1. |
Stringaddition? |
add data type flag, $FF = string, $00 = numeric |
+ AND LAST RESULT A STRING? |
||
.,ADE3 D0 03 BNE $ADE8 |
JEQ CAT ;ONLY IF [A]=0 AND [VALTYP]=-1 (A STR). |
nein: Verkettung umgehen |
branch if not string or not + token will only be $00 if type is string and token was + |
BRANCH IF NOT |
||
.,ADE5 4C 3D B6 JMP $B63D |
Stringverkettung |
add strings, string 1 is in the descriptor, string 2 is in line, and return |
CONCATENATE IF SO. |
|||
.,ADE8 69 FF ADC #$FF |
ADCI ^O377 ;GET BACK ORIGINAL [A]. |
Code-$AA (wiederherstellen) |
-1 (corrects for carry add) |
+-*/ IS 0123 |
||
.,ADEA 85 22 STA $22 |
STA INDEX1 |
und speichern |
save it |
|||
.,ADEC 0A ASL |
ASL A, ;MULTIPLY BY 2. |
verdoppeln |
*2 |
MULTIPLY BY 3 |
||
.,ADED 65 22 ADC $22 |
ADC INDEX1 ;BY THREE. |
+ Wert (also mal 3) |
*3 |
+-*/ IS 0,3,6,9 |
||
.,ADEF A8 TAY |
TAY ;SET UP FOR LATER. |
als Zeiger ins Y-Register |
copy to index |
|||
.,ADF0 68 PLA |
QPREC: PLA ;GET PREVIOUS PRECEDENCE. |
bisheriger Prioritätswert |
pull previous precedence |
GET LAST PRECEDENCE |
||
.,ADF1 D9 80 A0 CMP $A080,Y |
CMP OPTAB,Y ;IS OLD PRECEDENCE GREATER OR EQUAL? |
mit Prioritätsw. vergleichen |
compare with precedence byte |
|||
.,ADF4 B0 67 BCS $AE5D |
BCS QCHNUM ;YES, GO OPERATE. |
größer: $AE5D |
branch if A >= |
DO NOW IF HIGHER PRECEDENCE |
||
.,ADF6 20 8D AD JSR $AD8D |
JSR CHKNUM ;CAN'T BE STRING HERE. |
prüft auf numerisch |
check if source is numeric, else do type mismatch |
WAS LAST RESULT A #? |
||
.,ADF9 48 PHA |
DOPREC: PHA ;SAVE OLD PRECEDENCE. |
Prioritätswert retten |
save precedence |
YES, SAVE PRECEDENCE ON STACK |
||
.,ADFA 20 20 AE JSR $AE20 |
NEGPRC: JSR DOPRE1 ;SET A RETURN ADDRESS FOR OP. |
Operatoradr. und Operanden r. |
get vector, execute function then continue evaluation |
SAVE REST, CALL FRMEVL RECURSIVELY |
||
.,ADFD 68 PLA |
PLA ;PULL OFF PREVIOUS PRECEDENCE. |
restore precedence |
||||
.,ADFE A4 4B LDY $4B |
LDY OPPTR ;GET POINTER TO OP. |
Operator? |
get precedence stacked flag |
|||
.,AE00 10 17 BPL $AE19 |
BPL QPREC1 ;THAT'S A REAL OPERATOR. |
ja: $AE19 |
branch if stacked values |
|||
.,AE02 AA TAX |
TAX ;DONE ? |
weitere Operation? |
copy precedence, set flags |
|||
.,AE03 F0 56 BEQ $AE5B |
BEQ QOPGO ;DONE ! |
nein: RTS |
exit if done |
EXIT IF NO MATH IN EXPRESSION |
||
.,AE05 D0 5F BNE $AE66 |
BNE PULSTK |
ARG vom Stapel holen |
else pop FAC2 and return, branch always |
...ALWAYS FOUND ONE OR MORE RELATIONAL OPERATORS <,=,> |
||
.,AE07 46 0D LSR $0D |
FINREL: LSR VALTYP ;GET VALUE TYPE INTO "C". |
Stringflag löschen |
clear data type flag, $FF = string, $00 = numeric |
(VALTYP) = 0 (NUMERIC), = $FF (STRING) |
||
.,AE09 8A TXA |
TXA |
Operatormaske nach |
copy compare function flag |
SET CPRTYP TO 0000<=>C |
||
.,AE0A 2A ROL |
ROL A, ;PUT VALTYP INTO LOW ORDER BIT OF MASK. |
links schieben |
<<1, shift data type flag into b0, 1 = string, 0 = num |
WHERE C=0 IF #, C=1 IF STRING |
||
.,AE0B A6 7A LDX $7A |
LDX TXTPTR ;DECREMENT TEXT POINTER. |
Programmzeiger holen (LOW) |
get BASIC execute pointer low byte |
BACK UP TXTPTR |
||
.,AE0D D0 02 BNE $AE11 |
BNE FINRE2 |
=0: HIGH-Byte vermindern |
branch if no underflow |
|||
.,AE0F C6 7B DEC $7B |
DEC TXTPTR+1 |
HIGH-Byte vermindern |
else decrement BASIC execute pointer high byte |
|||
.,AE11 C6 7A DEC $7A |
FINRE2: DEC TXTPTR |
LOW-Byte vermindern |
decrement BASIC execute pointer low byte |
|||
.,AE13 A0 1B LDY #$1B |
LDYI PTDORL-OPTAB ;MAKE [YREG] POINT AT OPERATOR ENTRY. |
Offset des Hierarchieflags |
set offset to = operator precedence entry |
POINT AT RELOPS ENTRY |
||
.,AE15 85 4D STA $4D |
STA OPMASK ;SAVE THE OPERATION MASK. |
Flag setzen |
save new comparrison evaluation flag |
|||
.,AE17 D0 D7 BNE $ADF0 |
BNE QPREC ;SAVE IT ALL. BR ALWAYS. ;NOTE B7(VALTYP)=0 SO CHKNUM CALL IS OK. |
unbedingter Sprung |
branch always |
...ALWAYS |
||
.,AE19 D9 80 A0 CMP $A080,Y |
QPREC1: CMP OPTAB,Y ;LAST PRECEDENCE IS GREATER? |
mit Hierarchieflag vergl. |
compare with stacked function precedence |
|||
.,AE1C B0 48 BCS $AE66 |
BCS PULSTK ;YES, GO OPERATE. |
größer: $AE66 |
if A >=, pop FAC2 and return |
DO NOW IF HIGHER PRECEDENCE |
||
.,AE1E 90 D9 BCC $ADF9 |
BCC DOPREC ;NO SAVE ARGUMENT AND GET OTHER OPERAND. |
sonst weiter |
else go stack this one and continue, branch alwaysget vector, execute function then continue evaluation |
...ALWAYS STACK THIS OPERATION AND CALL FRMEVL FOR ANOTHER ONE |
recursive entry for evaluation of expressions |
|
.,AE20 B9 82 A0 LDA $A082,Y |
DOPRE1: LDA OPTAB+2,Y |
Operationsadresse (HIGH) |
get function vector high byte |
|||
.,AE23 48 PHA |
PHA ;DISP ADDR GOES ONTO STACK. |
auf Stapel retten |
onto stack |
PUSH ADDRESS OF OPERATION PERFORMER |
||
.,AE24 B9 81 A0 LDA $A081,Y |
LDA OPTAB+1,Y |
Operationsadresse (LOW) |
get function vector low byte |
|||
.,AE27 48 PHA |
PHA |
auf Stapel retten |
onto stack now push sign, round FAC1 and put on stack |
|||
.,AE28 20 33 AE JSR $AE33 |
JSR PUSHF1 ;SAVE FAC ON STACK UNPACKED. |
Operanden auf Stapel retten |
function will return here, then the next RTS will call the function |
STACK FAC.SIGN AND FAC |
||
.,AE2B A5 4D LDA $4D |
LDA OPMASK ;[ACCA] MAY BE MASK FOR REL. |
Operatormaske laden |
get comparrison evaluation flag |
A=RELOP FLAGS, X=PRECEDENCE BYTE |
||
.,AE2D 4C A9 AD JMP $ADA9 |
JMP LPOPER |
zum Schleifenanfang |
continue evaluating expression |
RECURSIVELY CALL FRMEVL |
||
.,AE30 4C 08 AF JMP $AF08 |
SNERR5: JMP SNERR ;GO TO AN ERROR. |
gibt 'SYNTAX ERROR' |
do syntax error then warm start |
STACK (FAC)THREE ENTRY POINTS:.1, FROM FRMEVL .2, FROM "STEP" .3, FROM "FOR" |
save rounded value of left operand |
|
.,AE33 A5 66 LDA $66 |
PUSHF1: LDA FACSGN |
Vorzeichen von FAC |
get FAC1 sign (b7) |
GET FAC.SIGN TO PUSH IT |
||
.,AE35 BE 80 A0 LDX $A080,Y |
LDX OPTAB,Y, ;GET HIGH PRECEDENCE. |
Hierarchieflag |
get precedence bytepush sign, round FAC1 and put on stack |
PRECEDENCE BYTE FROM MATHTBL ENTER HERE FROM "STEP", TO PUSH STEP SIGN AND VALUE |
||
.,AE38 A8 TAY |
PUSHF: TAY ;GET POINTER INTO STACK. |
Vorzeichen ins Y-Reg. |
copy sign |
FAC.SIGN OR SGN(STEP VALUE) |
||
.,AE39 68 PLA |
PLA |
Rücksprungadresse holen |
get return address low byte |
PULL RETURN ADDRESS AND ADD 1 |
pull return address |
|
.,AE3A 85 22 STA $22 |
STA INDEX1 |
und merken |
save it |
<<< ASSUMES NOT ON PAGE BOUNDARY! >>> |
||
.,AE3C E6 22 INC $22 |
INC INDEX1 |
Rücksprungadresse erhöhen |
increment it as return-1 is pushed note, no check is made on the high byte so if the calling routine ever assembles to a page edge then this all goes horribly wrong! |
PLACE BUMPED RETURN ADDRESS IN |
||
.,AE3E 68 PLA |
PLA |
nächstes Adressbyte holen |
get return address high byte |
INDEX,INDEX+1 |
and store in $22/$23 |
|
.,AE3F 85 23 STA $23 |
STA INDEX1+1 |
und speichern |
save it |
|||
.,AE41 98 TYA |
TYA ;STORE FAC ON STACK UNPACKED. |
Vorzeichen wieder in Akku |
restore sign |
FAC.SIGN OR SGN(STEP VALUE) |
||
.,AE42 48 PHA |
PHA ;START WITH SIGN SET UP. |
und auf Stapel legen |
push signround FAC1 and put on stack |
PUSH FAC.SIGN OR SGN(STEP VALUE) ENTER HERE FROM "FOR", WITH (INDEX) = STEP, TO PUSH INITIAL VALUE OF "FOR" VARIABLE |
||
.,AE43 20 1B BC JSR $BC1B |
FORPSH: JSR ROUND ;PUT ROUNDED FAC ON STACK. |
FAC runden |
round FAC1 |
ROUND TO 32 BITS |
||
.,AE46 A5 65 LDA $65 |
LDA FACLO ;ENTRY POINT TO SKIP STORING SIGN. |
FAC auf Stapel legen |
get FAC1 mantissa 4 |
PUSH (FAC) |
||
.,AE48 48 PHA |
PHA |
1. Byte retten |
save it |
|||
.,AE49 A5 64 LDA $64 |
LDA FACMO |
2. Byte holen |
get FAC1 mantissa 3 |
|||
.,AE4B 48 PHA |
PHA IFN ADDPRC,< |
und retten |
save it |
|||
.,AE4C A5 63 LDA $63 |
LDA FACMOH |
3. Byte holen |
get FAC1 mantissa 2 |
|||
.,AE4E 48 PHA |
PHA> |
und retten |
save it |
|||
.,AE4F A5 62 LDA $62 |
LDA FACHO |
4. Byte holen |
get FAC1 mantissa 1 |
|||
.,AE51 48 PHA |
PHA |
und retten |
save it |
|||
.,AE52 A5 61 LDA $61 |
LDA FACEXP |
5. Byte holen |
get FAC1 exponent |
|||
.,AE54 48 PHA |
PHA |
und retten |
save it |
|||
.,AE55 6C 22 00 JMP ($0022) |
JMPD INDEX1 ;RETURN. |
Sprung auf Operation |
return, sort ofdo functions |
DO RTS FUNNY WAY |
return to callerapply operator |
|
.,AE58 A0 FF LDY #$FF |
QOP: LDYI 255 |
Flagwert für Operator |
flag function |
SET UP TO EXIT ROUTINE |
||
.,AE5A 68 PLA |
PLA ;GET HIGH PRECEDENCE OF LAST OP. |
Prioritätsflag retten |
pull precedence byte |
|||
.,AE5B F0 23 BEQ $AE80 |
QOPGO: BEQ QOPRTS ;DONE ! |
=0? ja: $AE80 |
exit if done |
EXIT IF NO MATH TO DOPERFORM STACKED OPERATION(A) = PRECEDENCE BYTESTACK: 1 -- CPRMASK 5 -- (ARG) 2 -- ADDR OF PERFORMER |
||
.,AE5D C9 64 CMP #$64 |
QCHNUM: CMPI 100 ;RELATIONAL OPERATOR? |
=$64? |
compare previous precedence with $64 |
WAS IT RELATIONAL OPERATOR? |
||
.,AE5F F0 03 BEQ $AE64 |
BEQ UNPSTK ;YES, DON'T CHECK OPERAND. |
ja: $AE64 |
branch if was $64 (< function) |
YES, ALLOW STRING COMPARE |
||
.,AE61 20 8D AD JSR $AD8D |
JSR CHKNUM ;MUST BE NUMBER. |
prüft auf numerisch |
check if source is numeric, else do type mismatch |
MUST BE NUMERIC VALUE |
||
.,AE64 84 4B STY $4B |
UNPSTK: STY OPPTR ;SAVE OPERATOR'S POINTER FOR NEXT TIME. |
flag fur Operator |
save precedence stacked flag pop FAC2 and return |
|||
.,AE66 68 PLA |
PULSTK: PLA ;GET MASK FOR REL OP IF IT IS ONE. |
Akku vom Stapel holen |
pop byte |
GET 0000<=>C FROM STACK |
||
.,AE67 4A LSR |
LSR A, ;SETUP [C] FOR DOREL'S "CHKVAL". |
halbieren |
shift out comparison evaluation lowest bit |
SHIFT TO 00000<=> FORM |
||
.,AE68 85 12 STA $12 |
STA DOMASK ;SAVE FOR "DOCMP". |
und abspeichern |
save the comparison evaluation flag |
00000<=> |
||
.,AE6A 68 PLA |
PLA ;UNPACK STACK INTO ARG. |
ARG von Stapel holen |
pop exponent |
|||
.,AE6B 85 69 STA $69 |
STA ARGEXP |
1. Byte speichern |
save FAC2 exponent |
GET FLOATING POINT VALUE OFF STACK, |
||
.,AE6D 68 PLA |
PLA |
2. Byte holen |
pop mantissa 1 |
AND PUT IT IN ARG |
||
.,AE6E 85 6A STA $6A |
STA ARGHO IFN ADDPRC,< |
und speichern |
save FAC2 mantissa 1 |
|||
.,AE70 68 PLA |
PLA |
3. Byte holen |
pop mantissa 2 |
|||
.,AE71 85 6B STA $6B |
STA ARGMOH> |
und speichern |
save FAC2 mantissa 2 |
|||
.,AE73 68 PLA |
PLA |
4. Byte holen |
pop mantissa 3 |
|||
.,AE74 85 6C STA $6C |
STA ARGMO |
und speichern |
save FAC2 mantissa 3 |
|||
.,AE76 68 PLA |
PLA |
5. Byte holen |
pop mantissa 4 |
|||
.,AE77 85 6D STA $6D |
STA ARGLO |
und speichern |
save FAC2 mantissa 4 |
|||
.,AE79 68 PLA |
PLA |
6. Byte (Vorzeichen holen |
pop sign |
|||
.,AE7A 85 6E STA $6E |
STA ARGSGN |
und speichern |
save FAC2 sign (b7) |
|||
.,AE7C 45 66 EOR $66 |
EOR FACSGN ;GET PROBABLE RESULT SIGN. |
Vorzeichen von ARG und FAC |
EOR FAC1 sign (b7) |
SAVE EOR OF SIGNS OF THE OPERANDS, |
||
.,AE7E 85 6F STA $6F |
STA ARISGN ;ARITHMETIC SIGN. USED BY ;ADD, SUB, MULT, DIV. |
verknüpfen und speichern |
save sign compare (FAC1 EOR FAC2) |
IN CASE OF MULTIPLY OR DIVIDE |
||
.,AE80 A5 61 LDA $61 |
QOPRTS: LDA FACEXP ;GET IT AND SET CODES. |
Exponentbyte von FAC laden |
get FAC1 exponent |
FAC EXPONENT IN A-REG |
||
.,AE82 60 RTS |
UNPRTS: RTS ;RETURN. |
RücksprungNächstes Element einesAusdrucks holen |
get value from line |
STATUS .EQ. IF (FAC)=0 RTS GOES TO PERFORM OPERATION GET ELEMENT IN EXPRESSIONGET VALUE OF VARIABLE OR NUMBER AT TXTPNT, OR POINTTO STRING DESCRIPTOR IF A STRING, AND PUT IN FAC. |
get arithmetic element routine |
|
.,AE83 6C 0A 03 JMP ($030A) |
JMP $AE86 |
get arithmetic elementget arithmetic element, the get arithmetic element vector is initialised to point here |
normally AE86standard arithmetic element |
|||
.,AE86 A9 00 LDA #$00 |
EVAL: CLR VALTYP ;ASSUME VALUE WILL BE NUMERIC. |
Wert laden und damit |
clear byte |
ASSUME NUMERIC |
||
.,AE88 85 0D STA $0D |
Typflag auf numerisch setzen |
clear data type flag, $FF = string, $00 = numeric |
||||
.,AE8A 20 73 00 JSR $0073 |
EVAL0: JSR CHRGET ;GET A CHARACTER. |
CHRGET nächstes Zeichen holen |
increment and scan memory |
|||
.,AE8D B0 03 BCS $AE92 |
BCS EVAL2 |
Ziffer? nein: $AE92 |
branch if not numeric character else numeric string found (e.g. 123) |
NOT A DIGIT |
||
.,AE8F 4C F3 BC JMP $BCF3 |
EVAL1: JMP FIN ;IT IS A NUMBER. |
Variable nach FAC holen |
get FAC1 from string and return get value from line .. continued wasn't a number so ... |
NUMERIC CONSTANT |
||
.,AE92 20 13 B1 JSR $B113 |
EVAL2: JSR ISLETC ;VARIABLE NAME? |
Buchstabe? |
check byte, return Cb = 0 if<"A" or >"Z" |
VARIABLE NAME? |
||
.,AE95 90 03 BCC $AE9A |
BCS ISVAR ;YES. |
nein: JMP umgehen |
branch if not variable name |
|||
.,AE97 4C 28 AF JMP $AF28 |
IFE REALIO-3,< |
Variable holen |
variable name set-up and return |
YES |
||
.,AE9A C9 FF CMP #$FF |
CMPI PI |
BASIC-Code für Pi? |
compare with token for PI |
PI |
||
.,AE9C D0 0F BNE $AEAD |
BNE QDOT |
nein: $AEAD |
branch if not PI |
|||
.,AE9E A9 A8 LDA #$A8 |
LDWDI PIVAL |
Zeiger auf Konstante Pi |
get PI pointer low byte |
low AEA8 |
||
.,AEA0 A0 AE LDY #$AE |
(LOW und HIGH-Byte) |
get PI pointer high byte |
high AEA8 |
|||
.,AEA2 20 A2 BB JSR $BBA2 |
JSR MOVFM ;PUT VALUE IN FOR PI. |
Konstante in FAC holen |
unpack memory (AY) into FAC1 |
|||
.,AEA5 4C 73 00 JMP $0073 |
JMP CHRGET |
CHRGET nächstes Zeichen holen |
increment and scan memory and returnPI as floating number |
float value of PI |
||
.:AEA8 82 49 0F DA A1 |
PIVAL: ^O202 ^O111 ^O017 ^O332 ^O241> |
Konstante Pi 3.14159265 |
3.141592653get value from line .. continuedwasn't variable name so ... |
|||
.,AEAD C9 2E CMP #$2E |
QDOT: CMPI "." ;LEADING CHARACTER OF CONSTANT? |
'.' Dezimalpunkt? |
compare with "." |
DECIMAL POINT |
decimal point |
|
.,AEAF F0 DE BEQ $AE8F |
BEQ EVAL1 |
ja: $AE8F |
if so get FAC1 from string and return, e.g. was .123 wasn't .123 so ... |
YES, NUMERIC CONSTANT |
||
.,AEB1 C9 AB CMP #$AB |
CMPI MINUTK ;NEGATION? |
'-'? |
compare with token for - |
UNARY MINUS? |
plus code |
|
.,AEB3 F0 58 BEQ $AF0D |
BEQ DOMIN ;SHO IS. |
zum Vorzeichenwechsel |
branch if - token, do set-up for functions wasn't -123 so ... |
YES |
||
.,AEB5 C9 AA CMP #$AA |
CMPI PLUSTK |
'+'? |
compare with token for + |
UNARY PLUS |
times code |
|
.,AEB7 F0 D1 BEQ $AE8A |
BEQ EVAL0 |
ja: $Ae8A |
branch if + token, +1 = 1 so ignore leading + it wasn't any sort of number so ... |
YES |
||
.,AEB9 C9 22 CMP #$22 |
CMPI 34 ;A QUOTE? A STRING? |
'"'? |
compare with " |
STRING CONSTANT? |
quote mark |
|
.,AEBB D0 0F BNE $AECC |
BNE EVAL3 |
nein: $AECC |
branch if not open quote was open quote so get the enclosed string print "..." string to string utility area |
NOSTRING CONSTANT ELEMENTSET Y,A = (TXTPTR)+CARRY |
||
.,AEBD A5 7A LDA $7A |
STRTXT: LDWD TXTPTR |
LOW- und HIGH-Byte des |
get BASIC execute pointer low byte |
ADD (CARRY) TO GET ADDRESS OF 1ST CHAR |
||
.,AEBF A4 7B LDY $7B |
Programmzeigers holen |
get BASIC execute pointer high byte |
OF STRING IN Y,A |
|||
.,AEC1 69 00 ADC #$00 |
ADCI 0 ;TO INC, ADD C=1. |
und Übertrag addieren |
add carry to low byte |
|||
.,AEC3 90 01 BCC $AEC6 |
BCC STRTX2 |
C=0: $AEC6 |
branch if no overflow |
|||
.,AEC5 C8 INY |
INY |
HIGH-Byte erhöhen |
increment high byte |
|||
.,AEC6 20 87 B4 JSR $B487 |
STRTX2: JSR STRLIT ;YES. GO PROCESS IT. |
String übertragen |
print " terminated string to utility pointer |
BUILD DESCRIPTOR TO STRING GET ADDRESS OF DESCRIPTOR IN FAC |
||
.,AEC9 4C E2 B7 JMP $B7E2 |
JMP ST2TXT |
Programmz. auf Stringende +1 |
restore BASIC execute pointer from temp and return get value from line .. continued wasn't a string so ... |
POINT TXTPTR AFTER TRAILING QUOTE |
||
.,AECC C9 A8 CMP #$A8 |
EVAL3: CMPI NOTTK ;CHECK FOR "NOT" OPERATOR. |
'NOT'-Code? |
compare with token for NOT |
NOT code |
||
.,AECE D0 13 BNE $AEE3 |
BNE EVAL4 |
nein: $AEE3 |
branch if not token for NOT was NOT token |
NOT "NOT", TRY "FN" |
||
.,AED0 A0 18 LDY #$18 |
LDYI NOTTAB-OPTAB ;"NOT" HAS PRECEDENCE 90. |
Offset des H.Flags in Tabelle |
offset to NOT function |
POINT AT = COMPARISON |
||
.,AED2 D0 3B BNE $AF0F |
BNE GONPRC ;GO DO ITS EVALUATION. |
unbedingter SprungBASIC-Befehl NOT |
do set-up for function then execute, branch always do = compare |
...ALWAYS"NOT" FUNCTIONIF FAC=0, RETURN FAC=1IF FAC<>0, RETURN FAC=0 |
NOT operator |
|
.,AED4 20 BF B1 JSR $B1BF |
NOTOP: JSR AYINT ;INTEGERIZE. |
FAC nach INTEGER wandeln |
evaluate integer expression, no sign check |
|||
.,AED7 A5 65 LDA $65 |
LDA FACLO ;GET THE ARGUMENT. |
HIGH-Byte holen |
get FAC1 mantissa 4 |
|||
.,AED9 49 FF EOR #$FF |
EORI 255 |
alle Bits umdrehen |
invert it |
|||
.,AEDB A8 TAY |
TAY |
und ins Y-Reg. |
copy it |
|||
.,AEDC A5 64 LDA $64 |
LDA FACMO |
LOW-Byte holen |
get FAC1 mantissa 3 |
|||
.,AEDE 49 FF EOR #$FF |
EORI 255 |
alle Bits invertieren |
invert it |
|||
.,AEE0 4C 91 B3 JMP $B391 |
JMP GIVAYF ;FLOAT [Y,A] AS RESULT IN FAC. ;AND RETURN. |
nach Fließkomma wandeln |
convert fixed integer AY to float FAC1 and return get value from line .. continued wasn't a string or NOT so ... |
COMPARISON FOR EQUALITY (= OPERATOR)ALSO USED TO EVALUATE "NOT" FUNCTION |
GET operand |
|
.,AEE3 C9 A5 CMP #$A5 |
EVAL4: CMPI FNTK ;USER-DEFINED FUNCTION? |
'FN'-Code? |
compare with token for FN |
|||
.,AEE5 D0 03 BNE $AEEA |
JEQ FNDOER |
nein: $AEEA |
branch if not token for FN |
|||
.,AEE7 4C F4 B3 JMP $B3F4 |
FN ausführen |
else go evaluate FNx get value from line .. continued wasn't a string, NOT or FN so ... |
||||
.,AEEA C9 B4 CMP #$B4 |
CMPI ONEFUN ;A FUNCTION NAME? |
'SGN'-Code |
compare with token for SGN |
SGN code or higher |
||
.,AEEC 90 03 BCC $AEF1 |
BCC PARCHK ;FUNCTIONS ARE THE HIGHEST NUMBERED |
kleiner (keine Stringfunkt.)? |
if less than SGN token evaluate expression in parentheses else was a function token |
|||
.,AEEE 4C A7 AF JMP $AFA7 |
JMP ISFUN ;CHARACTERS SO NO NEED TO CHECK ;AN UPPER-BOUND. |
holt String ,ersten Parameterholt Term in Klammern |
go set up function references, branch always get value from line .. continued if here it can only be something in brackets so .... evaluate expression within parentheses |
EVALUATE "(EXPRESSION)" |
||
.,AEF1 20 FA AE JSR $AEFA |
PARCHK: JSR CHKOPN ;ONLY POSSIBILITY LEFT IS |
prüft auf Klammer auf |
scan for "(", else do syntax error then warm start |
IS THERE A '(' AT TXTPTR? |
||
.,AEF4 20 9E AD JSR $AD9E |
JSR FRMEVL ;A FORMULA IN PARENTHESIS. ;RECURSIVELY EVALUATE THE FORMULA. |
FRMEVL holt Termprüft auf Zeichen im B.-Text |
evaluate expression all the 'scan for' routines return the character after the sought character scan for ")", else do syntax error then warm start |
YES, EVALUATE EXPRESSION |
check and skip characters |
|
.,AEF7 A9 29 LDA #$29 |
CHKCLS: LDAI 41 ;CHECK FOR A RIGHT PARENTHESE |
')' Klammer zu |
load A with ")" |
CHECK FOR ')' |
) |
|
.:AEF9 2C .BYTE $2C |
SKIP2 |
makes next line BIT $28A9 scan for "(", else do syntax error then warm start |
TRICK |
|||
.,AEFA A9 28 LDA #$28 |
CHKOPN: LDAI 40 |
'(' Klammer auf |
load A with "(" |
( |
||
.:AEFC 2C .BYTE $2C |
SKIP2 |
makes next line BIT $2CA9 scan for ",", else do syntax error then warm start |
TRICK |
|||
.,AEFD A9 2C LDA #$2C |
CHKCOM: LDAI 44 ; ; "SYNCHK" LOOKS AT THE CURRENT CHARACTER TO MAKE SURE IT ; IS THE SPECIFIC THING LOADED INTO ACCA JUST BEFORE THE CALL TO ; "SYNCHK". IF NOT, IT CALLS THE "SYNTAX ERROR" ROUTINE. ; OTHERWISE IT GOBBLES THE NEXT CHAR AND RETURNS, ; ; [A]=NEW CHAR AND TXTPTR IS ADVANCED BY "CHRGET". ; |
',' Komma |
load A with "," scan for CHR$(A), else do syntax error then warm start |
COMMA AT TXTPTR?UNLESS CHAR AT TXTPTR = (A), SYNTAX ERROR |
comma |
|
.,AEFF A0 00 LDY #$00 |
SYNCHR: LDYI 0 |
Zeiger setzen |
clear index |
|||
.,AF01 D1 7A CMP ($7A),Y |
CMPDY TXTPTR ;CHARACTERS EQUAL? |
mit laufendem Zeichen vergl. |
compare with BASIC byte |
|||
.,AF03 D0 03 BNE $AF08 |
BNE SNERR |
keine Übereinstimmung? |
if not expected byte do syntax error then warm start |
|||
.,AF05 4C 73 00 JMP $0073 |
CHRGO5: JMP CHRGET |
CHRGET nächstes Zeichen holen |
else increment and scan memory and return syntax error then warm start |
MATCH, GET NEXT CHAR & RETURN |
||
.,AF08 A2 0B LDX #$0B |
SNERR: LDXI ERRSN ;"SYNTAX ERROR" |
Nummer für 'SYNTAX ERROR' |
error code $0B, syntax error |
error number |
||
.,AF0A 4C 37 A4 JMP $A437 |
JMP ERROR |
Fehlermeldung ausgeben |
do error #X then warm start |
recursive geet value |
||
.,AF0D A0 15 LDY #$15 |
DOMIN: LDYI NEGTAB-OPTAB ;A PRECEDENCE BELOW "^". |
Offset Hierachie-Code für VZW |
set offset from base to > operator |
POINT AT UNARY MINUS |
||
.,AF0F 68 PLA |
GONPRC: PLA ;GET RID OF RTS ADDR. |
nächsten 2 Bytes vom |
dump return address low byte |
|||
.,AF10 68 PLA |
PLA |
Stapel entfernen |
dump return address high byte |
|||
.,AF11 4C FA AD JMP $ADFA |
JMP NEGPRC ;EVALUTE FOR NEGATION. |
zur Auswertungprüft auf Variable |
execute function then continue evaluationcheck address range, return Cb = 1 if address in BASIC ROM |
check variable pointer range |
||
.,AF14 38 SEC |
innerhalb des BASICs |
set carry for subtract |
||||
.,AF15 A5 64 LDA $64 |
Carry setzen (Subtr.) |
get variable address low byte |
||||
.,AF17 E9 00 SBC #$00 |
Descriptor holen |
subtract $A000 low byte |
||||
.,AF19 A5 65 LDA $65 |
liegt Descriptor ($64/$65) |
get variable address high byte |
||||
.,AF1B E9 A0 SBC #$A0 |
zwischen $A000 und $E32A? |
subtract $A000 high byte |
||||
.,AF1D 90 08 BCC $AF27 |
ja: dann C=1, sonst RTS |
exit if address < $A000 |
||||
.,AF1F A9 A2 LDA #$A2 |
1. Wert laden |
get end of BASIC marker low byte |
||||
.,AF21 E5 64 SBC $64 |
1. Descriptorbyte abziehen |
subtract variable address low byte |
||||
.,AF23 A9 E3 LDA #$E3 |
2. Wert laden |
get end of BASIC marker high byte |
||||
.,AF25 E5 65 SBC $65 |
und Descriptorwert abziehen |
subtract variable address high byte |
||||
.,AF27 60 RTS |
RücksprungVariable holen |
variable name set-up |
get value of variable |
|||
.,AF28 20 8B B0 JSR $B08B |
ISVAR: JSR PTRGET ;GET A PNTR TO VARIABLE. |
Variable suchen |
get variable address |
|||
.,AF2B 85 64 STA $64 |
ISVRET: STWD FACMO |
Zeiger auf Variable |
save variable pointer low byte |
ADDRESS OF VARIABLE |
||
.,AF2D 84 65 STY $65 |
IFN TIME!EXTIO,< |
bzw. Stringdescriptor |
save variable pointer high byte |
|||
.,AF2F A6 45 LDX $45 |
LDWD VARNAM> ;CHECK TIME,TIME$,STATUS. |
als |
get current variable name first character |
NUMERIC OR STRING? |
||
.,AF31 A4 46 LDY $46 |
LDX VALTYP |
Variablenname speichern |
get current variable name second character |
|||
.,AF33 A5 0D LDA $0D |
Typflag holen |
get data type flag, $FF = string, $00 = numeric |
||||
.,AF35 F0 26 BEQ $AF5D |
BEQ GOOO ;THE STRING IS SET UP. |
numerisch? |
branch if numeric variable is string |
NUMERIC |
||
.,AF37 A9 00 LDA #$00 |
LDXI 0 |
Wert laden und |
else clear A |
|||
.,AF39 85 70 STA $70 |
STX FACOV IFN TIME,< |
in Rundungsbyte fur FAC |
clear FAC1 rounding byte |
|||
.,AF3B 20 14 AF JSR $AF14 |
BIT FACLO ;AN ARRAY? |
Descriptor im Interpreter? |
check address range |
|||
.,AF3E 90 1C BCC $AF5C |
BPL STRRTS ;YES. |
nein |
exit if not in BASIC ROM |
|||
.,AF40 E0 54 CPX #$54 |
CMPI "T" ;TI$? |
'T'? (von TI$) |
compare variable name first character with "T" |
T |
||
.,AF42 D0 18 BNE $AF5C |
BNE STRRTS |
nein: $AF5C |
exit if not "T" |
|||
.,AF44 C0 C9 CPY #$C9 |
CPYI "I"+128 |
'I$'? (von TI$) |
compare variable name second character with "I$" |
I$ |
||
.,AF46 D0 14 BNE $AF5C |
BNE STRRTS |
nein: $AF5C |
exit if not "I$" variable name was "TI$" |
|||
.,AF48 20 84 AF JSR $AF84 |
JSR GETTIM ;YES. PUT TIME IN FACMOH-LO. |
Zeit nach FAC holen |
read real time clock into FAC1 mantissa, 0HML |
|||
.,AF4B 84 5E STY $5E |
STY TENEXP ;Y=0. |
Flag für Exponentialdarst. =0 |
clear exponent count adjust |
|||
.,AF4D 88 DEY |
DEY |
vermindern (=$FF) |
Y = $FF |
|||
.,AF4E 84 71 STY $71 |
STY FBUFPT |
Zeiger für Stringstartadresse |
set output string index, -1 to allow for pre increment |
|||
.,AF50 A0 06 LDY #$06 |
LDYI 6 ;SIX DIGITS TO PRINT. |
Länge 6 für TI$ |
HH:MM:SS is six digits |
|||
.,AF52 84 5D STY $5D |
STY DECCNT |
speichern |
set number of characters before the decimal point |
|||
.,AF54 A0 24 LDY #$24 |
LDYI FDCEND-FOUTBL |
Zeiger auf Stellenwert |
index to jiffy conversion table |
|||
.,AF56 20 68 BE JSR $BE68 |
JSR FOUTIM ;CONVERT TO ASCII. |
erzeugt String TI$ |
convert jiffy count to string |
|||
.,AF59 4C 6F B4 JMP $B46F |
JMP TIMSTR> |
bringt String in Str.bereich |
exit via STR$() code tail |
|||
.,AF5C 60 RTS |
STRRTS: RTS GOOO: IFN INTPRC,< |
Rücksprung |
variable name set-up, variable is numeric |
|||
.,AF5D 24 0E BIT $0E |
LDX INTFLG |
INTEGER/ REAL Flag |
test data type flag, $80 = integer, $00 = float |
|||
.,AF5F 10 0D BPL $AF6E |
BPL GOOOOO |
REAL? ja: $AF6EIntegervariable holen |
branch if float |
FLOATING POINT |
||
.,AF61 A0 00 LDY #$00 |
LDYI 0 |
Zeiger setzen |
clear index |
INTEGER |
||
.,AF63 B1 64 LDA ($64),Y |
LDADY FACMO ;FETCH HIGH. |
Intgerzahl holen (1. Byte) |
get integer variable low byte |
|||
.,AF65 AA TAX |
TAX |
ins X-Reg. |
copy to X |
GET VALUE IN A,Y |
||
.,AF66 C8 INY |
INY |
Zeiger erhöhen |
increment index |
|||
.,AF67 B1 64 LDA ($64),Y |
LDADY FACMO |
2. Byte holen |
get integer variable high byte |
|||
.,AF69 A8 TAY |
TAY ;PUT LOW IN Y. |
ins Y-Register |
copy to Y |
|||
.,AF6A 8A TXA |
TXA ;GET HIGH IN A. |
1. Byte in Akku holen |
copy loa byte to A |
|||
.,AF6B 4C 91 B3 JMP $B391 |
JMP GIVAYF> ;FLOAT AND RETURN. GOOOOO: IFN TIME,< |
und nach Fließkomma wandelnREAL-Variable holen |
convert fixed integer AY to float FAC1 and return variable name set-up, variable is float |
CONVERT A,Y TO FLOATING POINT |
||
.,AF6E 20 14 AF JSR $AF14 |
BIT FACLO ;AN ARRAY? |
Descriptor im Interpreter? |
check address range |
|||
.,AF71 90 2D BCC $AFA0 |
BPL GOMOVF ;YES. |
nein |
if not in BASIC ROM get pointer and unpack into FAC1 |
|||
.,AF73 E0 54 CPX #$54 |
CMPI "T" |
'T'? (von TI) |
compare variable name first character with "T" |
T |
||
.,AF75 D0 1B BNE $AF92 |
BNE QSTATV |
nein: $AF92 |
branch if not "T" |
|||
.,AF77 C0 49 CPY #$49 |
CPYI "I" |
'I'? (von TI) |
compare variable name second character with "I" |
I |
||
.,AF79 D0 25 BNE $AFA0 |
BNE GOMOVF |
nein: $AFA0 |
branch if not "I" variable name was "TI" |
|||
.,AF7B 20 84 AF JSR $AF84 |
JSR GETTIM |
TIME in FAC holen |
read real time clock into FAC1 mantissa, 0HML |
|||
.,AF7E 98 TYA |
TYA ;FOR FLOATB. |
Akku =0 setzen |
clear A |
|||
.,AF7F A2 A0 LDX #$A0 |
LDXI 160 ;SET EXPONNENT. |
Exponentbyte für FAC |
set exponent to 32 bit value |
|||
.,AF81 4C 4F BC JMP $BC4F |
JMP FLOATB |
FAC linksbündig machenZeit holen |
set exponent = X and normalise FAC1read real time clock into FAC1 mantissa, 0HML |
get time in float accu |
||
.,AF84 20 DE FF JSR $FFDE |
GETTIM: LDWDI <CQTIMR-2> |
TIME holen |
read real time clock |
|||
.,AF87 86 64 STX $64 |
SEI ;TURN OF INT SYS. |
1. Byte nach FAC |
save jiffy clock mid byte as FAC1 mantissa 3 |
|||
.,AF89 84 63 STY $63 |
JSR MOVFM |
2. Byte nach FAC |
save jiffy clock high byte as FAC1 mantissa 2 |
|||
.,AF8B 85 65 STA $65 |
CLI ;BACK ON. |
3. Byte nach FAC |
save jiffy clock low byte as FAC1 mantissa 4 |
|||
.,AF8D A0 00 LDY #$00 |
Wert laden (0) und |
clear Y |
||||
.,AF8F 84 62 STY $62 |
STY FACHO ;ZERO HIGHEST. |
als 4. Byte nach FAC |
clear FAC1 mantissa 1 |
|||
.,AF91 60 RTS |
RTS> QSTATV: IFN EXTIO,< |
Rücksprung |
variable name set-up, variable is float and not "Tx" |
continue of get value of variable |
||
.,AF92 E0 53 CPX #$53 |
CMPI "S" |
'S'? |
compare variable name first character with "S" |
S |
||
.,AF94 D0 0A BNE $AFA0 |
BNE GOMOVF |
nein: $AFA0 |
if not "S" go do normal floating variable |
|||
.,AF96 C0 54 CPY #$54 |
CPYI "T" |
'T'? |
compare variable name second character with " |
T |
||
.,AF98 D0 06 BNE $AFA0 |
BNE GOMOVF |
nein: $AFA0 |
if not "T" go do normal floating variable variable name was "ST" |
|||
.,AF9A 20 B7 FF JSR $FFB7 |
LDA CQSTAT |
Status holen |
read I/O status word |
|||
.,AF9D 4C 3C BC JMP $BC3C |
JMP FLOAT GOMOVF:> IFN TIME!EXTIO,< |
Byte in FließkommaformatREAL-Variable holen |
save A as integer byte and return variable is float |
|||
.,AFA0 A5 64 LDA $64 |
LDWD FACMO> |
LOW- und HIGH-Byte der |
get variable pointer low byte |
|||
.,AFA2 A4 65 LDY $65 |
Variablenadresse |
get variable pointer high byte |
||||
.,AFA4 4C A2 BB JMP $BBA2 |
JMP MOVFM ;MOVE ACTUAL VALUE IN. ;AND RETURN. |
Variable in FAC holenFunktionsberechnung |
unpack memory (AY) into FAC1get value from line continuedonly functions left so ..set up function references |
PROCESS UNARY OPERATORS (FUNCTIONS) |
apply function |
|
.,AFA7 0A ASL |
ISFUN: ASL A, ;MULTIPLY BY TWO. |
Funktionscode mal 2 |
*2 (2 bytes per function address) |
DOUBLE TOKEN TO GET INDEX |
||
.,AFA8 48 PHA |
PHA |
auf den Stapel retten |
save function offset |
|||
.,AFA9 AA TAX |
TAX |
und ins X-Register |
copy function offset |
|||
.,AFAA 20 73 00 JSR $0073 |
JSR CHRGET ;SET UP FOR SYNCHK. |
CHRGET nächstes Zeichen |
increment and scan memory |
|||
.,AFAD E0 8F CPX #$8F |
CPXI 2*LASNUM-256+1 ;IS IT PAST "LASNUM"? |
numerische Funktion? |
compare function offset to CHR$ token offset+1 |
LEFT$, RIGHT$, AND MID$ |
||
.,AFAF 90 20 BCC $AFD1 |
BCC OKNORM ;NO, MUST BE NORMAL FUNCTION. ; ; MOST FUNCTIONS TAKE A SINGLE ARGUMENT. ; THE RETURN ADDRESS OF THESE FUNCTIONS IS "CHKNUM" ; WHICH ASCERTAINS THAT [VALTYP]=0 (NUMERIC). ; NORMAL FUNCTIONS THAT RETURN STRING RESULTS ; (E.G., CHR$) MUST POP OFF THAT RETURN ADDR AND ; RETURN DIRECTLY TO "FRMEVL". ; ; THE SO-CALLED "FUNNY" FUNCTIONS CAN TAKE MORE THAN ONE ARGUMENT, ; THE FIRST OF WHICH MUST BE STRING AND THE SECOND OF WHICH ; MUST BE A NUMBER BETWEEN 0 AND 255. ; THE CLOSED PARENTHESIS MUST BE CHECKED AND RETURN IS DIRECTLY ; TO "FRMEVL" WITH THE TEXT PNTR POINTING BEYOND THE ")". ; THE POINTER TO THE DESCRIPTOR OF THE STRING ARGUMENT ; IS STORED ON THE STACK UNDERNEATH THE VALUE OF THE ; INTEGER ARGUMENT. ; |
ja: $AFD1Stringfunktion, String understen Parameter |
branch if < LEFT$ (can not be =) get value from line .. continued was LEFT$, RIGHT$ or MID$ so.. |
NOT ONE OF THE STRING FUNCTIONS |
||
.,AFB1 20 FA AE JSR $AEFA |
JSR CHKOPN ;CHECK FOR AN OPEN PARENTHESE |
prüft auf Klammer auf |
scan for "(", else do syntax error then warm start |
STRING FUNCTION, NEED "(" |
||
.,AFB4 20 9E AD JSR $AD9E |
JSR FRMEVL ;EAT OPEN PAREN AND FIRST ARG. |
FRMEVL holen beliebigen Term |
evaluate, should be string, expression |
EVALUATE EXPRESSION FOR STRING |
||
.,AFB7 20 FD AE JSR $AEFD |
JSR CHKCOM ;TWO ARGS SO COMMA MUST DELIMIT. |
prüft auf Komma |
scan for ",", else do syntax error then warm start |
REQUIRE A COMMA |
||
.,AFBA 20 8F AD JSR $AD8F |
JSR CHKSTR ;MAKE SURE FIRST WAS STRING. |
prüft auf String |
check if source is string, else do type mismatch |
MAKE SURE EXPRESSION IS A STRING |
||
.,AFBD 68 PLA |
PLA ;GET FUNCTION NUMBER. |
Funktionstoken left$, r$, m$ |
restore function offset |
|||
.,AFBE AA TAX |
TAX |
Akku nach X holen |
copy it |
RETRIEVE ROUTINE POINTER |
||
.,AFBF A5 65 LDA $65 |
PSHWD FACMO ;SAVE POINTER AT STRING DESCRIPTOR |
Adresse des |
get descriptor pointer high byte |
STACK ADDRESS OF STRING |
||
.,AFC1 48 PHA |
Stringdescriptors |
push string pointer high byte |
||||
.,AFC2 A5 64 LDA $64 |
holen und auf den Stapel |
get descriptor pointer low byte |
||||
.,AFC4 48 PHA |
retten (LOW und HIGH) |
push string pointer low byte |
||||
.,AFC5 8A TXA |
TXA |
Akku wiederholen |
restore function offset |
|||
.,AFC6 48 PHA |
PHA ;RESAVE FUNCTION NUMBER. ;THIS MUST BE ON STACK SINCE RECURSIVE. |
Token auf den Stapel retten |
save function offset |
STACK DOUBLED TOKEN |
||
.,AFC7 20 9E B7 JSR $B79E |
JSR GETBYT ;[X]=VALUE OF FORMULA. |
holt Byte-Wert (2. Parameter) |
get byte parameter |
CONVERT NEXT EXPRESSION TO BYTE IN X-REG |
||
.,AFCA 68 PLA |
PLA ;GET FUNCTION NUMBER. |
Token zurückholen |
restore function offset |
GET DOUBLED TOKEN OFF STACK |
||
.,AFCB A8 TAY |
TAY |
und ins Y-Reg. |
copy function offset |
USE AS INDEX TO BRANCH |
||
.,AFCC 8A TXA |
TXA |
2. Bytewert in den Akku laden |
copy byte parameter to A |
VALUE OF SECOND PARAMETER |
||
.,AFCD 48 PHA |
PHA |
und auf den Stapel retten |
push byte parameter |
PUSH 2ND PARAM |
||
.,AFCE 4C D6 AF JMP $AFD6 |
JMP FINGO ;DISPATCH TO FUNCTION. |
Routine ausführennumerische Funktion auswerten |
go call function get value from line .. continued was SGN() to CHR$() so.. |
JOIN UNARY FUNCTIONS |
||
.,AFD1 20 F1 AE JSR $AEF1 |
OKNORM: JSR PARCHK ;READ A FORMULA SURROUNDED BY PARENS. |
holt Term in Klammern |
evaluate expression within parentheses |
REQUIRE "(EXPRESSION)" |
||
.,AFD4 68 PLA |
PLA ;GET DISPATCH FUNCTION. |
BASIC-Code für Funktion holen |
restore function offset |
|||
.,AFD5 A8 TAY |
TAY |
und als Zeiger ins Y-Reg. |
copy to index |
INDEX INTO FUNCTION ADDRESS TABLE |
||
.,AFD6 B9 EA 9F LDA $9FEA,Y |
FINGO: LDA FUNDSP-2*ONEFUN+256,Y, ;MODIFY DISPATCH ADDRESS. |
Vektor für Funktionsbe- |
get function jump vector low byte |
|||
.,AFD9 85 55 STA $55 |
STA JMPER+1 |
rechnung holen und speichern |
save functions jump vector low byte |
PREPARE TO JSR TO ADDRESS |
||
.,AFDB B9 EB 9F LDA $9FEB,Y |
LDA FUNDSP-2*ONEFUN+257,Y |
2.Byte holen |
get function jump vector high byte |
|||
.,AFDE 85 56 STA $56 |
STA JMPER+2 |
und speichern |
save functions jump vector high byte |
|||
.,AFE0 20 54 00 JSR $0054 |
JSR JMPER ;DISPATCH! ;STRING FUNCTIONS REMOVE THIS RET ADDR. |
Funktion ausführen |
do function call |
DOES NOT RETURN FOR CHR$, LEFT$, RIGHT$, OR MID$ |
||
.,AFE3 4C 8D AD JMP $AD8D |
JMP CHKNUM ;CHECK IT FOR NUMERICNESS AND RETURN. |
prüft auf numerischBASIC-Befehl OR |
check if source is numeric and RTS, else do type mismatch string functions avoid this by dumping the return address perform ORthis works because NOT(NOT(x) AND NOT(y)) = x OR y |
REQUIRE NUMERIC RESULT |
OR operator |
|
.,AFE6 A0 FF LDY #$FF |
OROP: LDYI 255 ;MUST ALWAYS COMPLEMENT.. |
Flag für OR |
set Y for OR |
|||
.:AFE8 2C .BYTE $2C |
SKIP2 |
BASIC-Befehl AND |
makes next line BIT $00A0perform AND |
AND operator |
||
.,AFE9 A0 00 LDY #$00 |
ANDOP: LDYI 0 |
Flag fur AND |
clear Y for AND |
|||
.,AFEB 84 0B STY $0B |
STY COUNT ;OPERATOR. |
Flag setzen |
set AND/OR invert value |
|||
.,AFED 20 BF B1 JSR $B1BF |
JSR AYINT ;[FACMO&LO]=INT VALUE AND CHECK SIZE. |
FAC nach INTEGER wandeln |
evaluate integer expression, no sign check |
|||
.,AFF0 A5 64 LDA $64 |
LDA FACMO ;USE DEMORGAN'S LAW ON HIGH |
ersten Wert holen |
get FAC1 mantissa 3 |
|||
.,AFF2 45 0B EOR $0B |
EOR COUNT |
mit Flag verknüpfen |
EOR low byte |
|||
.,AFF4 85 07 STA $07 |
STA INTEGR |
und speichern |
save it |
|||
.,AFF6 A5 65 LDA $65 |
LDA FACLO ;AND LOW. |
zweiten Wert holen |
get FAC1 mantissa 4 |
|||
.,AFF8 45 0B EOR $0B |
EOR COUNT |
mit Flag verknüpfen |
EOR high byte |
|||
.,AFFA 85 08 STA $08 |
STA INTEGR+1 |
und speichern |
save it |
|||
.,AFFC 20 FC BB JSR $BBFC |
JSR MOVFA |
ARG nach FAC |
copy FAC2 to FAC1, get 2nd value in expression |
|||
.,AFFF 20 BF B1 JSR $B1BF |
JSR AYINT ;[FACMO&LO]=INT OF ARG. |
FAC nach Integer |
evaluate integer expression, no sign check |
|||
.,B002 A5 65 LDA $65 |
LDA FACLO |
zweites Byte holen |
get FAC1 mantissa 4 |
|||
.,B004 45 0B EOR $0B |
EOR COUNT |
mit Flag verknüpfen |
EOR high byte |
|||
.,B006 25 08 AND $08 |
AND INTEGR+1 |
logische AND-Verknüpfung |
AND with expression 1 high byte |
|||
.,B008 45 0B EOR $0B |
EOR COUNT ;FINISH OUT DEMORGAN. |
mit Flag verknüpfen |
EOR result high byte |
|||
.,B00A A8 TAY |
TAY ;SAVE HIGH. |
ins Y-Reg. retten |
save in Y |
|||
.,B00B A5 64 LDA $64 |
LDA FACMO |
erstes Byte holen |
get FAC1 mantissa 3 |
|||
.,B00D 45 0B EOR $0B |
EOR COUNT |
mit Flag verknüpfen |
EOR low byte |
|||
.,B00F 25 07 AND $07 |
AND INTEGR |
logische AND-Verknüpfung |
AND with expression 1 low byte |
|||
.,B011 45 0B EOR $0B |
EOR COUNT |
mit Flag verknüpfen |
EOR result low byte |
|||
.,B013 4C 91 B3 JMP $B391 |
JMP GIVAYF ;FLOAT [A.Y] AND RET TO USER. ; ; TIME TO PERFORM A RELATIONAL OPERATOR. ; [DOMASK] CONTAINS THE BITS AS TO WHICH RELATIONAL ; OPERATOR IT WAS. CARRY BIT ON=STRING COMPARE. ; |
wieder in Fließkomma wandelnVergleich |
convert fixed integer AY to float FAC1 and returnperform comparisonsdo < compare |
PERFORM RELATIONAL OPERATIONS |
greater/equal/less operator |
|
.,B016 20 90 AD JSR $AD90 |
DOREL: JSR CHKVAL ;CHECK FOR MATCH. |
prüft auf identischen Typ |
type match check, set C for string |
MAKE SURE FAC IS CORRECT TYPE |
||
.,B019 B0 13 BCS $B02E |
BCS STRCMP ;IT IS A STRING. |
String: dann weiter |
branch if string do numeric < compare |
TYPE MATCHES, BRANCH IF STRINGS |
||
.,B01B A5 6E LDA $6E |
LDA ARGSGN ;PACK ARG FOR FCOMP. |
Wert holen |
get FAC2 sign (b7) |
NUMERIC COMPARISON |
||
.,B01D 09 7F ORA #$7F |
ORAI 127 |
ARG in Speicherformat |
set all non sign bits |
RE-PACK VALUE IN ARG FOR FCOMP |
||
.,B01F 25 6A AND $6A |
AND ARGHO |
wandeln und |
and FAC2 mantissa 1 (AND in sign bit) |
|||
.,B021 85 6A STA $6A |
STA ARGHO |
wieder abspeichern |
save FAC2 mantissa 1 |
|||
.,B023 A9 69 LDA #$69 |
LDWDI ARGEXP |
Adresse von ARG |
set pointer low byte to FAC2 |
|||
.,B025 A0 00 LDY #$00 |
(LOW- und HIGH-Byte) |
set pointer high byte to FAC2 |
||||
.,B027 20 5B BC JSR $BC5B |
JSR FCOMP |
Vergleich ARG mit FAC |
compare FAC1 with (AY) |
RETURN A-REG = -1,0,1 |
||
.,B02A AA TAX |
TAX |
copy the result |
AS ARG <,=,> FAC |
|||
.,B02B 4C 61 B0 JMP $B061 |
JMP QCOMP |
Ergebnis in FAC holenStringvergleich |
go evaluate result do string < compare |
STRING COMPARISON |
||
.,B02E A9 00 LDA #$00 |
STRCMP: CLR VALTYP ;RESULT WILL BE NUMERIC. |
Wert laden und damit |
clear byte |
SET RESULT TYPE TO NUMERIC |
||
.,B030 85 0D STA $0D |
Stringflag löschen |
clear data type flag, $FF = string, $00 = numeric |
||||
.,B032 C6 4D DEC $4D |
DEC OPMASK ;TURN OFF VALTYP WHICH WAS STRING. |
Operatormaske - 1 |
clear < bit in comparrison evaluation flag |
MAKE CPRTYP 0000<=>0 |
||
.,B034 20 A6 B6 JSR $B6A6 |
JSR FREFAC ;FREE THE FACLO STRING. |
FRLSTR |
pop string off descriptor stack, or from top of string space returns with A = length, X = pointer low byte, Y = pointer high byte |
|||
.,B037 85 61 STA $61 |
STA DSCTMP ;SAVE FOR LATER. |
Stringlänge holen |
save length |
STRING LENGTH |
||
.,B039 86 62 STX $62 |
STXY DSCTMP+1 |
LOW- und HIGH-Byte der |
save string pointer low byte |
|||
.,B03B 84 63 STY $63 |
Stringadresse speichern |
save string pointer high byte |
||||
.,B03D A5 6C LDA $6C |
LDWD ARGMO ;GET POINTER TO OTHER STRING. |
LOW- und HIGH-Byte des |
get descriptor pointer low byte |
|||
.,B03F A4 6D LDY $6D |
Zeigers auf zweiten String |
get descriptor pointer high byte |
||||
.,B041 20 AA B6 JSR $B6AA |
JSR FRETMP ;FREES FIRST DESC POINTER. |
FRESTR |
pop (YA) descriptor off stack or from top of string space returns with A = length, X = pointer low byte, Y = pointer high byte |
|||
.,B044 86 6C STX $6C |
STXY ARGMO |
Adresse des |
save string pointer low byte |
|||
.,B046 84 6D STY $6D |
2. Strings |
save string pointer high byte |
||||
.,B048 AA TAX |
TAX ;COPY COUNT INTO X. |
Länge des 2.Strings merken |
copy length |
LEN (ARG) STRING |
||
.,B049 38 SEC |
SEC |
Carry setzen (Subtraktion) |
set carry for subtract |
|||
.,B04A E5 61 SBC $61 |
SBC DSCTMP ;WHICH IS GREATER. IF 0, ALL SET UP. |
Längen vergleichen |
subtract string 1 length |
SET X TO SMALLER LEN |
||
.,B04C F0 08 BEQ $B056 |
BEQ STASGN ;JUST PUT SIGN OF DIFFERENCE AWAY. |
gleich: $B056 |
branch if str 1 length = string 2 length |
|||
.,B04E A9 01 LDA #$01 |
LDAI 1 |
Wert für: 1.String länger |
set str 1 length > string 2 length |
|||
.,B050 90 04 BCC $B056 |
BCC STASGN ;SIGN IS POSITIVE. |
2.String kürzer |
branch if so |
|||
.,B052 A6 61 LDX $61 |
LDX DSCTMP ;LENGTH OF FAC IS SHORTER. |
Länge des 1.Strings |
get string 1 length |
|||
.,B054 A9 FF LDA #$FF |
LDAI ^O377 ;GET A MINUS 1 FOR NEGATIVES. |
Wert für: 1.String kürzer |
set str 1 length < string 2 length |
|||
.,B056 85 66 STA $66 |
STASGN: STA FACSGN ;KEEP FOR LATER. |
Flag für gleichen String, |
save length compare |
FLAG WHICH SHORTER |
||
.,B058 A0 FF LDY #$FF |
LDYI 255 ;SET POINTER TO FIRST STRING. (ARG.) |
wenn beide Strings identisch aber |
set index |
|||
.,B05A E8 INX |
INX ;TO LOOP PROPERLY. |
ungleich lang sind |
adjust for loop |
|||
.,B05B C8 INY |
NXTCMP: INY |
Zeiger erhöhen |
increment index |
|||
.,B05C CA DEX |
DEX ;ANY CHARACTERS LEFT TO COMPARE? |
Stringende? |
decrement count |
|||
.,B05D D0 07 BNE $B066 |
BNE GETCMP ;NOT DONE YET. |
nein: weiter |
branch if still bytes to do |
MORE CHARS IN BOTH STRINGS |
||
.,B05F A6 66 LDX $66 |
LDX FACSGN ;USE SIGN OF LENGTH DIFFERENCE ;SINCE ALL CHARACTERS ARE THE SAME. |
Vorzeichenbyte holen |
get length compare back |
IF = SO FAR, DECIDE BY LENGTH |
||
.,B061 30 0F BMI $B072 |
QCOMP: BMI DOCMP ;C IS ALWAYS SET THEN. |
negativ: $B072 |
branch if str 1 < str 2 |
|||
.,B063 18 CLC |
CLC |
Carry löschen |
flag str 1 <= str 2 |
|||
.,B064 90 0C BCC $B072 |
BCC DOCMP ;ALWAYS BRANCH. |
unbedingter Sprung |
go evaluate result |
...ALWAYS |
||
.,B066 B1 6C LDA ($6C),Y |
GETCMP: LDADY ARGMO ;GET NEXT CHAR TO COMPARE. |
Vergleich der Strings |
get string 2 byte |
|||
.,B068 D1 62 CMP ($62),Y |
CMPDY DSCTMP+1 ;SAME? |
zeichenweise |
compare with string 1 byte |
|||
.,B06A F0 EF BEQ $B05B |
BEQ NXTCMP ;YEP. TRY FURTHER. |
gleiche Zeichen: weiter |
loop if bytes = |
SAME, KEEP COMPARING |
||
.,B06C A2 FF LDX #$FF |
LDXI ^O377 ;SET A POSITIVE DIFFERENCE. |
Wert laden |
set str 1 < string 2 |
IN CASE ARG GREATER |
||
.,B06E B0 02 BCS $B072 |
BCS DOCMP ;PUT STACK BACK TOGETHER. |
und Vergleich beenden |
branch if so |
IT IS |
||
.,B070 A2 01 LDX #$01 |
LDXI 1 ;SET A NEGATIVE DIFFERENCE. |
Wert laden |
set str 1 > string 2 |
FAC GREATER |
||
.,B072 E8 INX |
DOCMP: INX ;-1 TO 1, 0 TO 2, 1 TO 4. |
und um 1 erhöhen |
x = 0, 1 or 2 |
CONVERT FF,0,1 TO 0,1,2 |
||
.,B073 8A TXA |
TXA |
Wert in den Akku |
copy to A |
|||
.,B074 2A ROL |
ROL A |
linksverschieben, Bit 1, 2=$1 |
* 2 (1, 2 or 4) |
AND TO 0,2,4 IF C=0, ELSE 1,2,5 |
||
.,B075 25 12 AND $12 |
AND DOMASK |
mit Vorzeichen verknüpfen |
AND with the comparison evaluation flag |
00000<=> |
||
.,B077 F0 02 BEQ $B07B |
BEQ GOFLOT |
=0: $B07B |
branch if 0 (compare is false) |
IF NO MATCH: FALSE |
||
.,B079 A9 FF LDA #$FF |
LDAI ^O377 ;MAP 0 TO 0. ALL OTHERS TO -1. |
else set result true |
AT LEAST ONE MATCH: TRUE |
|||
.,B07B 4C 3C BC JMP $BC3C |
GOFLOT: JMP FLOAT ;FLOAT THE ONE-BYTE RESULT INTO FAC. PAGE DIMENSION AND VARIABLE SEARCHING.;; THE "DIM" CODE SETS [DIMFLG] AND THEN FALLS INTO THE VARIABLE SEARCH ; ROUTINE, WHICH LOOKS AT DIMFLG AT THREE DIFFERENT POINTS. ; 1) IF AN ENTRY IS FOUND, "DIMFLG" BEING ON INDICATES ; A "DOUBLY" DIMENSIONED VARIABLE. ; 2) WHEN A NEW ENTRY IS BEING BUILT "DIMFLG" BEING ON ; INDICTAES THE INDICES SHOULD BE USED FOR THE ; SIZE OF EACH INDEX. OTHERWISE THE DEFAULT OF TEN ; IS USED. ; 3) WHEN THE BUILD ENTRY CODE FINISHES, ONLY IF "DIMFLG" IS OFF ; WILL INDEXING BE DONE. ; |
Ergebnis nach FAC holen |
save A as integer byte and return |
"DIM" STATEMENT |
DIM command |
|
.,B07E 20 FD AE JSR $AEFD |
DIM3: JSR CHKCOM ;MUST BE A COMMA |
CHKCOM prüft auf KommaBASIC-Befehl DIM |
scan for ",", else do syntax error then warm startperform DIM |
SEPARATED BY COMMAS |
||
.,B081 AA TAX |
DIM: TAX ;SET [ACCX] NONZERO. ;[ACCA] MUST BE NONZERO TO WORK RIGHT. |
nächstes Zeichen |
copy "DIM" flag to X |
NON-ZERO, FLAGS PTRGET DIM CALLED |
||
.,B082 20 90 B0 JSR $B090 |
DIM1: JSR PTRGT1 |
Variable dimensionieren |
search for variable |
ALLOCATE THE ARRAY |
||
.,B085 20 79 00 JSR $0079 |
DIMCON: JSR CHRGOT ;GET LAST CHARACTER. |
CHRGOT letztes Zeichen holen |
scan memory |
NEXT CHAR |
||
.,B088 D0 F4 BNE $B07E |
BNE DIM3 |
nicht Ende: zur nächsten Var. |
scan for "," and loop if not null |
NOT END OF STATEMENT |
||
.,B08A 60 RTS |
RTS ; ; ROUTINE TO READ THE VARIABLE NAME AT THE CURRENT TEXT POSITION ; AND PUT A POINTER TO ITS VALUE IN VARPNT. [TXTPTR] ; POINTS TO THE TERMINATING CHARCTER.. NOT THAT EVALUATING SUBSCRIPTS ; IN A VARIABLE NAME CAN CAUSE RECURSIVE CALLS TO "PTRGET" SO AT ; THAT POINT ALL VALUES MUST BE STORED ON THE STACK. ; |
RücksprungVariable holen |
search for variable |
PTRGET -- GENERAL VARIABLE SCANSCANS VARIABLE NAME AT TXTPTR, AND SEARCHES THEVARTAB AND ARYTAB FOR THE NAME. IF NOT FOUND, CREATE VARIABLE OF APPROPRIATE TYPE. RETURN WITH ADDRESS IN VARPNT AND Y,A ACTUAL ACTIVITY CONTROLLED SOMEWHAT BY TWO FLAGS: DIMFLG -- NONZERO IF CALLED FROM "DIM" ELSE = 0 SUBFLG -- = $00 = $40 IF CALLED FROM "GETARYPT" = $80 IF CALLED FROM "DEF FN" = $C1-DA IF CALLED FROM "FN" |
get name and pointer to a variable |
|
.,B08B A2 00 LDX #$00 |
PTRGET: LDXI 0 ;MAKE [ACCX]=0. |
Flag für nicht dimensionieren |
set DIM flag = $00 |
|||
.,B08D 20 79 00 JSR $0079 |
JSR CHRGOT ;RETRIEVE LAST CHARACTER. |
CHRGOT letztes Zeichen holen |
scan memory, 1st character |
GET FIRST CHAR OF VARIABLE NAME |
||
.,B090 86 0C STX $0C |
PTRGT1: STX DIMFLG ;STORE FLAG AWAY. |
DIM-Flag setzen |
save DIM flag |
X IS NONZERO IF FROM DIM |
||
.,B092 85 45 STA $45 |
PTRGT2: STA VARNAM |
Variablenname |
save 1st character |
|||
.,B094 20 79 00 JSR $0079 |
JSR CHRGOT ;GET CURRENT CHARACTER ;MAYBE WITH FUNCTION BIT OFF. |
CHRGOT letztes Zeichen holen |
scan memory |
|||
.,B097 20 13 B1 JSR $B113 |
JSR ISLETC ;CHECK FOR LETTER. |
prüft auf Buchstabe |
check byte, return Cb = 0 if<"A" or >"Z" |
IS IT A LETTER? |
||
.,B09A B0 03 BCS $B09F |
BCS PTRGT3 ;MUST HAVE A LETTER. |
ja: $B09F |
branch if ok |
YES, OKAY SO FAR |
||
.,B09C 4C 08 AF JMP $AF08 |
INTERR: JMP SNERR |
'SYNTAX ERROR' |
else syntax error then warm start was variable name so ... |
NO, SYNTAX ERROR |
||
.,B09F A2 00 LDX #$00 |
PTRGT3: LDXI 0 ;ASSUME NO SECOND CHARACTER. |
Wert laden und damit |
clear 2nd character temp |
|||
.,B0A1 86 0D STX $0D |
STX VALTYP ;DEFAULT IS NUMERIC. IFN INTPRC,< |
Stringflag löschen |
clear data type flag, $FF = string, $00 = numeric |
|||
.,B0A3 86 0E STX $0E |
STX INTFLG> ;ASSUME FLOATING. |
Integerflag löschen |
clear data type flag, $80 = integer, $00 = float |
|||
.,B0A5 20 73 00 JSR $0073 |
JSR CHRGET ;GET FOLLOWING CHARACTER. |
CHRGET nächstes Zeichen holen |
increment and scan memory, 2nd character |
SECOND CHAR OF VARIABLE NAME |
||
.,B0A8 90 05 BCC $B0AF |
BCC ISSEC ;CARRY RESET BY CHRGET IF NUMERIC. |
Ziffer? |
if character = "0"-"9" (ok) go save 2nd character 2nd character wasn't "0" to "9" so ... |
NUMERIC |
||
.,B0AA 20 13 B1 JSR $B113 |
JSR ISLETC ;SET CARRY IF NOT ALPHABETIC. |
prüft auf Buchstabe |
check byte, return Cb = 0 if<"A" or >"Z" |
LETTER? |
||
.,B0AD 90 0B BCC $B0BA |
BCC NOSEC ;ALLOW ALPHABETICS. |
nein: $B0BA |
branch if <"A" or >"Z" (go check if string) |
NO, END OF NAME |
||
.,B0AF AA TAX |
ISSEC: TAX ;IT IS A NUMBER -- SAVE IN ACCX. |
zweiter Buchstabe des Names |
copy 2nd character ignore further (valid) characters in the variable name |
SAVE SECOND CHAR OF NAME IN X |
||
.,B0B0 20 73 00 JSR $0073 |
EATEM: JSR CHRGET ;LOOK AT NEXT CHARACTER. |
CHRGET nächstes Zeichen holen |
increment and scan memory, 3rd character |
SCAN TO END OF VARIABLE NAME |
||
.,B0B3 90 FB BCC $B0B0 |
BCC EATEM ;SKIP NUMERICS. |
Ziffer? |
loop if character = "0"-"9" (ignore) |
NUMERIC |
||
.,B0B5 20 13 B1 JSR $B113 |
JSR ISLETC |
prüft auf Buchstabe |
check byte, return Cb = 0 if<"A" or >"Z" |
|||
.,B0B8 B0 F6 BCS $B0B0 |
BCS EATEM ;SKIP ALPHABETICS. |
ja: weitere Zeichen überlesen |
loop if character = "A"-"Z" (ignore) check if string variable |
ALPHA |
||
.,B0BA C9 24 CMP #$24 |
NOSEC: CMPI "$" ;IS IT A STRING? |
'$' Code? |
compare with "$" |
STRING? |
$ |
|
.,B0BC D0 06 BNE $B0C4 |
BNE NOTSTR ;IF NOT, [VALTYP]=0. |
nein: $B0C4 |
branch if not string type is string |
NO |
||
.,B0BE A9 FF LDA #$FF |
LDAI ^O377 ;SET [VALTYP]=255 (STRING !). |
Wert laden und |
set data type = string |
|||
.,B0C0 85 0D STA $0D |
STA VALTYP IFN INTPRC,< |
Stringflag setzen |
set data type flag, $FF = string, $00 = numeric |
|||
.,B0C2 D0 10 BNE $B0D4 |
BNEA TURNON ;ALWAYS GOES. |
Sprung |
branch always |
...ALWAYS |
||
.,B0C4 C9 25 CMP #$25 |
NOTSTR: CMPI "%" ;INTEGER VARIABLE? |
'%' Code? |
compare with "%" |
INTEGER? |
% |
|
.,B0C6 D0 13 BNE $B0DB |
BNE STRNAM ;NO. |
nein: $B0DB |
branch if not integer |
NO |
||
.,B0C8 A5 10 LDA $10 |
LDA SUBFLG |
Integer erlaubt? |
get subscript/FNX flag |
YES; INTEGER VARIABLE ALLOWED? |
||
.,B0CA D0 D0 BNE $B09C |
BNE INTERR |
nein: 'SYNTAX ERROR' |
if ?? do syntax error then warm start |
NO, SYNTAX ERROR |
||
.,B0CC A9 80 LDA #$80 |
LDAI 128 |
Wert für Integer laden |
set integer type |
YES |
||
.,B0CE 85 0E STA $0E |
STA INTFLG ;SET FLAG. |
und Integerflag setzen |
set data type = integer |
FLAG INTEGER MODE |
||
.,B0D0 05 45 ORA $45 |
ORA VARNAM ;TURN ON BOTH HIGH BITS. |
Bit 7 im 1.Zeichen setzen und |
OR current variable name first byte |
|||
.,B0D2 85 45 STA $45 |
STA VARNAM> |
speichern (Bit7=1: Integer) |
save current variable name first byte |
SET SIGN BIT ON VARNAME |
||
.,B0D4 8A TXA |
TURNON: TXA |
X nach Akku speichern |
get 2nd character back |
SECOND CHAR OF NAME |
||
.,B0D5 09 80 ORA #$80 |
ORAI 128 ;TURN ON MSB OF SECOND CHARACTER. |
Bit 7 im 2.Buchstaben setzen |
set top bit, indicate string or integer variable |
SET SIGN |
||
.,B0D7 AA TAX |
TAX |
X-Reg. zurückholen |
copy back to 2nd character temp |
|||
.,B0D8 20 73 00 JSR $0073 |
JSR CHRGET ;GET CHARACTER AFTER $. IFE INTPRC,< NOTSTR:> |
CHRGET nächstes Zeichen holen |
increment and scan memory |
GET TERMINATING CHAR |
||
.,B0DB 86 46 STX $46 |
STRNAM: STX VARNAM+1 ;STORE AWAY SECOND CHARACTER. |
zweiten Buchstaben speichern |
save 2nd character |
STORE SECOND CHAR OF NAME |
||
.,B0DD 38 SEC |
SEC |
Feldvariablen erlaubt? |
set carry for subtract |
|||
.,B0DE 05 10 ORA $10 |
ORA SUBFLG ;ADD FLAG WHETHER TO ALLOW ARRAYS. |
wenn nicht, Bit7 setzen |
or with subscript/FNX flag - or FN name |
$00 OR $40 IF SUBSCRIPTS OK, ELSE $80 |
||
.,B0E0 E9 28 SBC #$28 |
SBCI 40 ;(CHECK FOR "(") WON'T MATCH IF SUBFLG SET. |
'('-Wert abziehen |
subtract "(" |
IF SUBFLG=$00 AND CHAR="("... |
( |
|
.,B0E2 D0 03 BNE $B0E7 |
JEQ ISARY ;IT IS! |
nicht Klammer auf? |
branch if not "(" |
NOPE |
||
.,B0E4 4C D1 B1 JMP $B1D1 |
dimensionierte Variable holen |
go find, or make, array either find or create variable variable name wasn't xx(.... so look for plain variable |
YES |
|||
.,B0E7 A0 00 LDY #$00 |
CLR SUBFLG ;ALLOW SUBSCRIPTS AGAIN. |
Wert laden und |
clear A |
|||
.,B0E9 84 10 STY $10 |
FN-Flag = 0 setzen |
clear subscript/FNX flag |
||||
.,B0EB A5 2D LDA $2D |
LDA VARTAB ;PLACE TO START SEARCH. |
Zeiger auf Variablenanfang |
get start of variables low byte |
START LOWTR AT SIMPLE VARIABLE TABLE |
||
.,B0ED A6 2E LDX $2E |
LDX VARTAB+1 LDYI 0 |
holen (LOW und HIGH) |
get start of variables high byte |
|||
.,B0EF 86 60 STX $60 |
STXFND: STX LOWTR+1 |
und zum |
save search address high byte |
|||
.,B0F1 85 5F STA $5F |
LOPFND: STA LOWTR |
Suchen merken |
save search address low byte |
|||
.,B0F3 E4 30 CPX $30 |
CPX ARYTAB+1 ;AT END OF TABLE YET? |
Suchzeiger = Variablenanfang |
compare with end of variables high byte |
END OF SIMPLE VARIABLES? |
||
.,B0F5 D0 04 BNE $B0FB |
BNE LOPFN |
nein: $B0FB |
skip next compare if <> high addresses were = so compare low addresses |
NO, GO ON |
||
.,B0F7 C5 2F CMP $2F |
CMP ARYTAB |
Ende der Variablen erreicht? |
compare low address with end of variables low byte |
YES; END OF ARRAYS? |
||
.,B0F9 F0 22 BEQ $B11D |
BEQ NOTFNS ;YES. WE COULDN'T FIND IT. |
ja: nicht gefunden, anlegen |
if not found go make new variable |
YES, MAKE ONE |
||
.,B0FB A5 45 LDA $45 |
LOPFN: LDA VARNAM |
ersten Buchstaben des Namens |
get 1st character of variable to find |
SAME FIRST LETTER? |
||
.,B0FD D1 5F CMP ($5F),Y |
CMPDY LOWTR ;COMPARE HIGH ORDERS. |
mit Tabelle vergleichen |
compare with variable name 1st character |
|||
.,B0FF D0 08 BNE $B109 |
BNE NOTIT ;NO COMPARISON. |
nein: weitersuchen |
branch if no match 1st characters match so compare 2nd character |
NOT SAME FIRST LETTER |
||
.,B101 A5 46 LDA $46 |
LDA VARNAM+1 |
zweiten Buchstaben |
get 2nd character of variable to find |
SAME SECOND LETTER? |
||
.,B103 C8 INY |
INY |
Zeiger erhöhen |
index to point to variable name 2nd character |
|||
.,B104 D1 5F CMP ($5F),Y |
CMPDY LOWTR ;AND THE LOW PART? |
vergleichen |
compare with variable name 2nd character |
|||
.,B106 F0 7D BEQ $B185 |
BEQ FINPTR ;THAT'S IT ! THAT'S IT ! |
gleich: gefunden |
branch if match (found variable) |
YES, SAME VARIABLE NAME |
||
.,B108 88 DEY |
DEY |
Zeiger vermindern |
else decrement index (now = $00) |
NO, BUMP TO NEXT NAME |
||
.,B109 18 CLC |
NOTIT: CLC |
Carry setzen (Addition) |
clear carry for add |
|||
.,B10A A5 5F LDA $5F |
LDA LOWTR |
Zeiger um 7 |
get search address low byte |
|||
.,B10C 69 07 ADC #$07 |
ADCI 6+ADDPRC ;MAKES NO DIF AMONG TYPES. |
erhöhen (2+5 Byte REAL Var.) |
+7, offset to next variable name |
|||
.,B10E 90 E1 BCC $B0F1 |
BCC LOPFND |
(Länge eines V.-Eintrags) |
loop if no overflow to high byte |
|||
.,B110 E8 INX |
INX |
Übertrag addieren |
else increment high byte |
|||
.,B111 D0 DC BNE $B0EF |
BNEA STXFND ;ALWAYS BRANCHES. ; ; TEST FOR A LETTER. / CARRY OFF= NOT A LETTER. ; CARRY ON= A LETTER. ; |
weiter suchenprüft auf Buchstabe |
loop always, RAM doesn't extend to $FFFF check byte, return Cb = 0 if<"A" or >"Z" |
...ALWAYSCHECK IF (A) IS ASCII LETTER A-ZRETURN CARRY = 1 IF A-Z= 0 IF NOT <<<NOTE FASTER AND SHORTER CODE: >>> <<< CMP #'Z'+1 COMPARE HI END <<< BCS .1 ABOVE A-Z <<< CMP #'A' COMPARE LO END <<< RTS C=0 IF LO, C=1 IF A-Z <<<.1 CLC C=0 IF HI <<< RTS |
check character in AC=1 if alphabetic, C=0 if not |
|
.,B113 C9 41 CMP #$41 |
ISLETC: CMPI "A" |
'A'-Code? (Buchstabencode) |
compare with "A" |
COMPARE LO END |
A |
|
.,B115 90 05 BCC $B11C |
BCC ISLRTS ;IF LESS THAN "A", RET. |
wenn kleiner: RTS mit C = 0 |
exit if less carry is set |
C=0 IF LOW |
||
.,B117 E9 5B SBC #$5B |
SBCI "Z"+1 |
'Z' + 1 |
subtract "Z"+1 |
PREPARE HI END TEST |
Z |
|
.,B119 38 SEC |
SEC |
wenn größer 'Z': C = 0 |
set carry |
TEST HI END, RESTORING (A) |
||
.,B11A E9 A5 SBC #$A5 |
SBCI 256-"Z"-1 ;RESET CARRY IF [A] .GT. "Z". |
sonst: C = 1 = Buchstabe |
subtract $A5 (restore byte) carry clear if byte > $5A |
C=0 IF LO, C=1 IF A-Z |
||
.,B11C 60 RTS |
ISLRTS: RTS ;RETURN TO CALLER. |
RücksprungVariable anlegen |
reached end of variable memory without match ... so create new variable |
VARIABLE NOT FOUND, SO MAKE ONE |
variable not found |
|
.,B11D 68 PLA |
NOTFNS: PLA ;CHECK WHO'S CALLING. |
pop return address low byte |
LOOK AT RETURN ADDRESS ON STACK TO |
|||
.,B11E 48 PHA |
PHA ;RESTORE IT. |
Aufrufadresse prüfen |
push return address low byte |
SEE IF CALLED FROM FRM.VARIABLE |
||
.,B11F C9 2A CMP #$2A |
CMPI ISVRET-1-<ISVRET-1>/256*256 ;IS EVAL CALLING? |
Aufruf von FRMEVL? |
compare with expected calling routine return low byte |
|||
.,B121 D0 05 BNE $B128 |
BNE NOTEVL ;NO, CARRY ON. IFN REALIO-3,< TSX LDA 258,X CMPI <<ISVRET-1>/256> BNE NOTEVL> |
nein: dann neu anlegen |
if not get variable go create new variable this will only drop through if the call was from $AF28 and is only called from there if it is searching for a variable from the right hand side of a LET a=b statement, it prevents the creation of variables not assigned a value. value returned by this is either numeric zero, exponent byte is $00, or null string, descriptor length byte is $00. in fact a pointer to any $00 byte would have done. else return dummy null value |
NO |
||
.,B123 A9 13 LDA #$13 |
LDZR: LDWDI ZERO ;SET UP PNTR TO SIMULATED ZERO. |
Zeiger auf Konstante 0 |
set result pointer low byte |
YES, CALLED FROM FRM.VARIABLE |
||
.,B125 A0 BF LDY #$BF |
(LOW und HIGH) |
set result pointer high byte |
POINT TO A CONSTANT ZERO |
|||
.,B127 60 RTS |
RTS ;FOR STRINGS OR NUMERIC. ;AND FOR INTEGERS TOO. NOTEVL: IFN TIME!EXTIO,< |
Rücksprung |
create new numeric variable |
NEW VARIABLE USED IN EXPRESSION = 0MAKE A NEW SIMPLE VARIABLEMOVE ARRAYS UP 7 BYTES TO MAKE ROOM FOR NEW VARIABLEENTER 7-BYTE VARIABLE DATA IN THE HOLE |
||
.,B128 A5 45 LDA $45 |
LDWD VARNAM> |
LOW- und HIGH-Byte |
get variable name first character |
|||
.,B12A A4 46 LDY $46 |
IFN TIME,< |
des Variablennames |
get variable name second character |
|||
.,B12C C9 54 CMP #$54 |
CMPI "T" |
'T'-Code? |
compare first character with "T" |
T |
||
.,B12E D0 0B BNE $B13B |
BNE QSTAVR |
nein: $B13B |
branch if not "T" |
|||
.,B130 C0 C9 CPY #$C9 |
CPYI "I"+128 |
'I$'-Code? |
compare second character with "I$" |
I$ |
||
.,B132 F0 EF BEQ $B123 |
BEQ LDZR |
ja: TI$ |
if "I$" return null value |
|||
.,B134 C0 49 CPY #$49 |
CPYI "I" |
'I'-Code? |
compare second character with "I" |
I |
||
.,B136 D0 03 BNE $B13B |
BNE QSTAVR> IFN EXTIO!TIME,< |
nein: $B13B |
branch if not "I" if name is "TI" do syntax error |
|||
.,B138 4C 08 AF JMP $AF08 |
GOBADV: JMP SNERR> QSTAVR: IFN EXTIO,< |
'SYNTAX ERROR' |
do syntax error then warm start |
|||
.,B13B C9 53 CMP #$53 |
CMPI "S" |
'S'-Code? |
compare first character with "S" |
S |
||
.,B13D D0 04 BNE $B143 |
BNE VAROK |
nein: $B143 |
branch if not "S" |
|||
.,B13F C0 54 CPY #$54 |
CPYI "T" |
'T'-Code? |
compare second character with "T" |
T |
||
.,B141 F0 F5 BEQ $B138 |
BEQ GOBADV> |
ST, dann 'SYNTAX ERROR' |
if name is "ST" do syntax error |
|||
.,B143 A5 2F LDA $2F |
VAROK: LDWD ARYTAB |
LOW- und HIGH-Byte des |
get end of variables low byte |
SET UP CALL TO BLTU TO |
||
.,B145 A4 30 LDY $30 |
Zeigers auf Arraytabelle |
get end of variables high byte |
TO MOVE FROM ARYTAB THRU STREND-1 |
|||
.,B147 85 5F STA $5F |
STWD LOWTR ;LOWEST THING TO MOVE. |
laden und |
save old block start low byte |
7 BYTES HIGHER |
||
.,B149 84 60 STY $60 |
merken |
save old block start high byte |
||||
.,B14B A5 31 LDA $31 |
LDWD STREND ;GET HIGHEST ADDR TO MOVE. |
LOW- und HIGH-Byte des |
get end of arrays low byte |
|||
.,B14D A4 32 LDY $32 |
Zeigers auf Ende der |
get end of arrays high byte |
||||
.,B14F 85 5A STA $5A |
STWD HIGHTR |
Arraytabelle |
save old block end low byte |
|||
.,B151 84 5B STY $5B |
merken |
save old block end high byte |
||||
.,B153 18 CLC |
CLC |
Carry für Addition setzen |
clear carry for add |
|||
.,B154 69 07 ADC #$07 |
ADCI 6+ADDPRC |
um 7 verschieben für Anlage |
+7, space for one variable |
|||
.,B156 90 01 BCC $B159 |
BCC NOTEVE |
einer neuen Variablen |
branch if no overflow to high byte |
|||
.,B158 C8 INY |
INY |
Übertrag addieren |
else increment high byte |
|||
.,B159 85 58 STA $58 |
NOTEVE: STWD HIGHDS ;PLACE TO STUFF IT. |
LOW- und HIGH-Byte des |
set new block end low byte |
|||
.,B15B 84 59 STY $59 |
neuen Blockendes speichern |
set new block end high byte |
||||
.,B15D 20 B8 A3 JSR $A3B8 |
JSR BLTU ;MOVE IT ALL. ;NOTE [Y,A] HAS [HIGHDS] FOR REASON. |
Block verschieben |
open up space in memory |
MOVE ARRAY BLOCK UP |
||
.,B160 A5 58 LDA $58 |
LDWD HIGHDS ;AND SET UP |
Werte |
get new start low byte |
STORE NEW START OF ARRAYS |
||
.,B162 A4 59 LDY $59 |
wiederholen |
get new start high byte (-$100) |
||||
.,B164 C8 INY |
INY |
und damit |
correct high byte |
|||
.,B165 85 2F STA $2F |
STWD ARYTAB ;NEW START OF ARRAY TABLE. |
Zeiger auf Arraytabelle |
set end of variables low byte |
|||
.,B167 84 30 STY $30 |
neu setzen |
set end of variables high byte |
||||
.,B169 A0 00 LDY #$00 |
LDYI 0 ;GET ADDR OF VARIABLE ENTRY. |
Zeiger setzen |
clear index |
|||
.,B16B A5 45 LDA $45 |
LDA VARNAM |
erster Buchstabe des Namens |
get variable name 1st character |
FIRST CHAR OF NAME |
||
.,B16D 91 5F STA ($5F),Y |
STADY LOWTR |
und speichern |
save variable name 1st character |
|||
.,B16F C8 INY |
INY |
Zeiger erhöhen, |
increment index |
|||
.,B170 A5 46 LDA $46 |
LDA VARNAM+1 |
zweiten Buchstaben holen |
get variable name 2nd character |
SECOND CHAR OF NAME |
||
.,B172 91 5F STA ($5F),Y |
STADY LOWTR ;STORE NAME OF VARIABLE. |
und abspeichern |
save variable name 2nd character |
|||
.,B174 A9 00 LDA #$00 |
LDAI 0 |
Nullwert laden |
clear A |
SET FIVE-BYTE VALUE TO 0 |
||
.,B176 C8 INY |
INY |
Zeiger erhöhen |
increment index |
|||
.,B177 91 5F STA ($5F),Y |
STADY LOWTR |
nächsten 5 Werte |
initialise variable byte |
|||
.,B179 C8 INY |
INY |
der Variable auf 0 setzen |
increment index |
|||
.,B17A 91 5F STA ($5F),Y |
STADY LOWTR |
2. Byte speichern |
initialise variable byte |
|||
.,B17C C8 INY |
INY |
Zeiger erhöhen |
increment index |
|||
.,B17D 91 5F STA ($5F),Y |
STADY LOWTR |
3. Byte speichern |
initialise variable byte |
|||
.,B17F C8 INY |
INY |
Zeiger erhöhen |
increment index |
|||
.,B180 91 5F STA ($5F),Y |
STADY LOWTR ;FOURTH ZERO FOR DEF FUNC. IFN ADDPRC,< |
4. Byte speichern |
initialise variable byte |
|||
.,B182 C8 INY |
INY |
Zeiger erhöhen |
increment index |
|||
.,B183 91 5F STA ($5F),Y |
STADY LOWTR> |
5. Byte speichern |
initialise variable byte found a match for variable |
PUT ADDRESS OF VALUE OF VARIABLE IN VARPNT AND Y,A |
variable found |
|
.,B185 A5 5F LDA $5F |
FINPTR: LDA LOWTR |
Zeiger auf Variablenwert |
get variable address low byte |
LOWTR POINTS AT NAME OF VARIABLE, |
||
.,B187 18 CLC |
CLC |
Carry löschen (Addition) |
clear carry for add |
SO ADD 2 TO GET TO VALUE |
||
.,B188 69 02 ADC #$02 |
ADCI 2 |
zwei für Namen addieren |
+2, offset past variable name bytes |
|||
.,B18A A4 60 LDY $60 |
LDY LOWTR+1 |
in Zeiger auf Variable |
get variable address high byte |
|||
.,B18C 90 01 BCC $B18F |
BCC FINNOW |
Zeiger auf erstes Byte |
branch if no overflow from add |
|||
.,B18E C8 INY |
INY |
High-Byte $48 erhöhen |
else increment high byte |
|||
.,B18F 85 47 STA $47 |
FINNOW: STWD VARPNT ;THIS IS IT. |
als Variablenzeiger |
save current variable pointer low byte |
ADDRESS IN VARPNT AND Y,A |
||
.,B191 84 48 STY $48 |
nach $47/48 speichern |
save current variable pointer high byte |
||||
.,B193 60 RTS |
RTS PAGE MULTIPLE DIMENSION CODE. |
Rücksprungberechnet Zeiger auf erstesArrayelement |
set-up array pointer to first element in array |
COMPUTE ADDRESS OF FIRST VALUE IN ARRAYARYPNT = (LOWTR) + #DIMS*2 + 5 |
compute pointer to array body |
|
.,B194 A5 0B LDA $0B |
FMAPTR: LDA COUNT |
Anzahl der Dimensionen |
get # of dimensions (1, 2 or 3) |
GET # OF DIMENSIONS |
||
.,B196 0A ASL |
ASL A, |
mal 2 |
*2 (also clears the carry !) |
#DIMS*2 (SIZE OF EACH DIM IN 2 BYTES) |
||
.,B197 69 05 ADC #$05 |
ADCI 5 ;POINT TO ENTRIES. C CLR'D BY ASL. |
plus 5 |
+5 (result is 7, 9 or 11 here) |
+ 5 (2 FOR NAME, 2 FOR OFFSET TO NEXT ARRAY, AND 1 FOR #DIMS |
||
.,B199 65 5F ADC $5F |
ADC LOWTR |
zu $5F und |
add array start pointer low byte |
ADDRESS OF TH IS ARRAY IN ARYTAB |
||
.,B19B A4 60 LDY $60 |
LDY LOWTR+1 |
$60 addieren |
get array pointer high byte |
|||
.,B19D 90 01 BCC $B1A0 |
BCC JSRGM |
Erhöhung umgehen |
branch if no overflow |
|||
.,B19F C8 INY |
INY |
Übertrag addieren |
else increment high byte |
|||
.,B1A0 85 58 STA $58 |
JSRGM: STWD ARYPNT |
Ergebnis-Zeiger nach |
save array data pointer low byte |
ADDRESS OF FIRST VALUE IN ARRAY |
||
.,B1A2 84 59 STY $59 |
$58/59 speichern |
save array data pointer high byte |
||||
.,B1A4 60 RTS |
RTS |
Rücksprung |
-32768 as floating value |
float number for conversion to integer |
||
.:B1A5 90 80 00 00 00 |
N32768: EXP 144,128,0,0 ;-32768. |
Konstante -32768Umwandlung FAC nach Integer |
-32768convert float to fixed |
-32768 IN FLOATING POINT |
routine to convert float to fixed point |
|
.,B1AA 20 BF B1 JSR $B1BF |
FAC nach Integer wandeln |
evaluate integer expression, no sign check |
||||
.,B1AD A5 64 LDA $64 |
LOW-Byte |
get result low byte |
||||
.,B1AF A4 65 LDY $65 |
HIGH-Byte |
get result high byte |
||||
.,B1B1 60 RTS |
; ; INTIDX READS A FORMULA FROM THE CURRENT POSITION AND ; TURNS IT INTO A POSITIVE INTEGER ; LEAVING THE RESULT IN FACMO&LO. NEGATIVE ARGUMENTS ; ARE NOT ALLOWED. ; |
RücksprungAusdruck holen undnach Integer |
evaluate integer expression |
EVALUATE NUMERIC FORMULA AT TXTPTRCONVERTING RESULT TO INTEGER 0 <= X <= 32767IN FAC+3,4 |
convert value from statement to integer |
|
.,B1B2 20 73 00 JSR $0073 |
INTIDX: JSR CHRGET |
CHRGET nächstes Zeichen holen |
increment and scan memory |
|||
.,B1B5 20 9E AD JSR $AD9E |
JSR FRMEVL ;GET A NUMBER |
FRMEVL, Ausdruck auswerten |
evaluate expression evaluate integer expression, sign check |
|||
.,B1B8 20 8D AD JSR $AD8D |
POSINT: JSR CHKNUM |
prüft auf numerisch |
check if source is numeric, else do type mismatch |
CONVERT FAC TO INTEGERMUST BE POSITIVE AND LESS THAN 32768 |
||
.,B1BB A5 66 LDA $66 |
LDA FACSGN |
Vorzeichen? |
get FAC1 sign (b7) |
ERROR IF - |
||
.,B1BD 30 0D BMI $B1CC |
BMI NONONO ;IF NEGATIVE, BLOW HIM OUT. |
negativ: dann 'ILLEGAL QUANT' |
do illegal quantity error if -ve evaluate integer expression, no sign check |
CONVERT FAC TO INTEGERMUST BE -32767 <= FAC <= 32767 |
convert float number to integer |
|
.,B1BF A5 61 LDA $61 |
AYINT: LDA FACEXP |
Exponent |
get FAC1 exponent |
EXPONENT OF VALUE IN FAC |
||
.,B1C1 C9 90 CMP #$90 |
CMPI 144 ;FAC .GT. 32767? |
Betrag größer 32768? |
compare with exponent = 2^16 (n>2^15) |
ABS(VALUE) < 32768? |
||
.,B1C3 90 09 BCC $B1CE |
BCC QINTGO |
nein: $B1CE |
if n<2^16 go convert FAC1 floating to fixed and return |
YES, OK FOR INTEGER |
||
.,B1C5 A9 A5 LDA #$A5 |
LDWDI N32768 ;GET ADDR OF -32768. |
Zeiger auf |
set pointer low byte to -32768 |
NO; NEXT FEW LINES ARE SUPPOSED TO |
low B1A5 |
|
.,B1C7 A0 B1 LDY #$B1 |
Konstante -32768 setzen |
set pointer high byte to -32768 |
ALLOW -32768 ($8000) |
high B1A5 |
||
.,B1C9 20 5B BC JSR $BC5B |
JSR FCOMP ;SEE IF FAC=[[Y,A]]. |
Vergleich FAC mit Konstante |
compare FAC1 with (AY) |
|||
.,B1CC D0 7A BNE $B248 |
NONONO: BNE FCERR ;NO, FAC IS TOO BIG. |
ungleich: 'ILLEGAL QUANT' |
if <> do illegal quantity error then warm start |
ILLEGAL QUANTITY |
||
.,B1CE 4C 9B BC JMP $BC9B |
QINTGO: JMP QINT ;GO TO QINT AND SHOVE IT. ; ; FORMAT OF ARRAYS IN CORE. ; ; DESCRIPTOR: ; LOWBYTE = FIRST CHARACTER. ; HIGHBYTE = SECOND CHARACTER (200 BIT IS STRING FLAG). ; LENGTH OF ARRAY IN CORE IN BYTES (INCLUDES EVERYTHING). ; NUMBER OF DIMENSIONS. ; FOR EACH DIMENSION STARTING WITH THE FIRST A LIST ; (2 BYTES EACH) OF THE MAX INDICE+1 ; THE VALUES ; |
wandelt Fließkomma in Integerdimensionierte Variable holen |
convert FAC1 floating to fixed and returnfind or make arrayan array is stored as followsarray name two bytes with the following patterns for different types 1st char 2nd char b7 b7 type element size -------- -------- ----- ------------ 0 0 floating point 5 0 1 string 3 1 1 integer 2 offset to next array word dimension count byte 1st dimension size word, this is the number of elements including 0 2nd dimension size word, only here if the array has a second dimension 2nd dimension size word, only here if the array has a third dimension note: the dimension size word is in high byte low byte format, not like most 6502 words then for each element the required number of bytes given as the element size above |
CONVERT TO INTEGERLOCATE ARRAY ELEMENT OR CREATE AN ARRAYPARSE THE SUBSCRIPT LIST |
get pointer to dimensioned variable |
|
.,B1D1 A5 0C LDA $0C |
ISARY: LDA DIMFLG IFN INTPRC,< |
DIM Flag |
get DIM flag |
YES |
||
.,B1D3 05 0E ORA $0E |
ORA INTFLG> |
Integer Flag |
OR with data type flag |
SET HIGH BIT IF % |
||
.,B1D5 48 PHA |
PHA ;SAVE [DIMFLG] FOR RECURSION. |
auf Stapel retten |
push it |
SAVE VALTYP AND DIMFLG ON STACK |
||
.,B1D6 A5 0D LDA $0D |
LDA VALTYP |
String Flag |
get data type flag, $FF = string, $00 = numeric |
|||
.,B1D8 48 PHA |
PHA ;SAVE [VALTYP] FOR RECURSION. |
auf Stapel retten |
push it |
|||
.,B1D9 A0 00 LDY #$00 |
LDYI 0 ;SET NUMBER OF DIMENSIONS TO ZERO. |
Anzahl der Indizes |
clear dimensions count now get the array dimension(s) and stack it (them) before the data type and DIM flag |
COUNT # DIMENSIONS IN Y-REG |
||
.,B1DB 98 TYA |
INDLOP: TYA ;SAVE NUMBER OF DIMS. |
in Akku und |
copy dimensions count |
SAVE #DIMS ON STACK |
||
.,B1DC 48 PHA |
PHA |
auf Stapel retten |
save it |
|||
.,B1DD A5 46 LDA $46 |
PSHWD VARNAM ;SAVE LOOKS. |
2. Buchstabe des Variablenn. |
get array name 2nd byte |
SAVE VARIABLE NAME ON STACK |
||
.,B1DF 48 PHA |
und retten |
save it |
||||
.,B1E0 A5 45 LDA $45 |
1. Buchstabe der Variablenn. |
get array name 1st byte |
||||
.,B1E2 48 PHA |
retten |
save it |
||||
.,B1E3 20 B2 B1 JSR $B1B2 |
JSR INTIDX ;EVALUATE INDICE INTO FACMO&LO. |
Index holen und nach Integer |
evaluate integer expression |
EVALUATE SUBSCRIPT AS INTEGER |
||
.,B1E6 68 PLA |
PULWD VARNAM ;GET BACK ALL... WE'RE HOME. |
die zwei |
pull array name 1st byte |
RESTORE VARIABLE NAME |
||
.,B1E7 85 45 STA $45 |
Bytes des |
restore array name 1st byte |
||||
.,B1E9 68 PLA |
Variablennamens zurückholen |
pull array name 2nd byte |
||||
.,B1EA 85 46 STA $46 |
und wieder abspeichern |
restore array name 2nd byte |
||||
.,B1EC 68 PLA |
PLA ;(# OF DIMS). |
Anzahl der Indizes |
pull dimensions count |
RESTORE # DIMS TO Y-REG |
||
.,B1ED A8 TAY |
TAY |
holen und ins Y-Reg. |
restore it |
|||
.,B1EE BA TSX |
TSX |
Stapelzeiger als Zeiger setzen |
copy stack pointer |
COPY VALTYP AND DIMFLG ON STACK |
||
.,B1EF BD 02 01 LDA $0102,X |
LDA 258,X |
Variablenflags |
get DIM flag |
TO LEAVE ROOM FOR THE SUBSCRIPT |
||
.,B1F2 48 PHA |
PHA ;PUSH DIMFLG AND VALTYP FURTHER. |
aus dem Stapel kopieren |
push it |
|||
.,B1F3 BD 01 01 LDA $0101,X |
LDA 257,X |
und oben auf den |
get data type flag |
|||
.,B1F6 48 PHA |
PHA |
Stapel legen |
push it |
|||
.,B1F7 A5 64 LDA $64 |
LDA INDICE ;PUT INDICE ONTO STACK. |
anstelle der |
get this dimension size high byte |
GET SUBSCRIPT VALUE AND PLACE IN THE |
||
.,B1F9 9D 02 01 STA $0102,X |
STA 258,X, ;UNDER DIMFLG AND VALTYP. |
Variablenflags |
stack before flag bytes |
STACK WHERE VALTYP & DIMFLG WERE |
||
.,B1FC A5 65 LDA $65 |
LDA INDICE+1 |
Index LOW und HIGH in |
get this dimension size low byte |
|||
.,B1FE 9D 01 01 STA $0101,X |
STA 257,X |
den Stapel kopieren |
stack before flag bytes |
|||
.,B201 C8 INY |
INY ;INCREMENT # OF DIMS. |
Anzahl der Indizes erhöhen |
increment dimensions count |
COUNT THE SUBSCRIPT |
||
.,B202 20 79 00 JSR $0079 |
JSR CHRGOT ;GET TERMINATING CHARACTER. |
CHRGOT letztes Zeichen holen |
scan memory |
NEXT CHAR |
||
.,B205 C9 2C CMP #$2C |
CMPI 44 ;A COMMA? |
',' Komma? |
compare with "," |
comma |
||
.,B207 F0 D2 BEQ $B1DB |
BEQ INDLOP ;YES. |
ja: dann nächsten Index |
if found go do next dimension |
COMMA, PARSE ANOTHER SUBSCRIPT |
||
.,B209 84 0B STY $0B |
STY COUNT ;SAVE COUNT OF DIMS. |
Anzahl der Indizes speichern |
store dimensions count |
NO MORE SUBSCRIPTS, SAVE # |
||
.,B20B 20 F7 AE JSR $AEF7 |
JSR CHKCLS ;MUST BE CLOSED PAREN. |
prüft auf Klammer zu |
scan for ")", else do syntax error then warm start |
NOW NEED ")" |
||
.,B20E 68 PLA |
PLA |
Flags vom |
pull data type flag |
RESTORE VALTYPE AND DIMFLG |
||
.,B20F 85 0D STA $0D |
STA VALTYP ;GET VALTYP AND |
Stapel |
restore data type flag, $FF = string, $00 = numeric |
|||
.,B211 68 PLA |
PLA IFN INTPRC,< |
zurückholen |
pull data type flag |
|||
.,B212 85 0E STA $0E |
STA INTFLG |
und abspeichern |
restore data type flag, $80 = integer, $00 = float |
|||
.,B214 29 7F AND #$7F |
ANDI 127> |
Integerflag herstellen |
mask dim flag |
ISOLATE DIMFLG |
||
.,B216 85 0C STA $0C |
STA DIMFLG ;DIMFLG OFF STACK. |
und abspeichern |
restore DIM flag |
SEARCH ARRAY TABLE FOR THIS ARRAY NAME |
||
.,B218 A6 2F LDX $2F |
LDX ARYTAB ;PLACE TO START SEARCH. |
LOW- und HIGH-Byte des |
set end of variables low byte (array memory start low byte) |
(A,X) = START OF ARRAY TABLE |
||
.,B21A A5 30 LDA $30 |
LDA ARYTAB+1 |
Zeigers auf Arraytabelle |
set end of variables high byte (array memory start high byte) now check to see if we are at the end of array memory, we would be if there were no arrays. |
|||
.,B21C 86 5F STX $5F |
LOPFDA: STX LOWTR |
holen und |
save as array start pointer low byte |
USE LOWTR FOR RUNNING POINTER |
||
.,B21E 85 60 STA $60 |
STA LOWTR+1 |
Zeiger merken |
save as array start pointer high byte |
|||
.,B220 C5 32 CMP $32 |
CMP STREND+1 ;END OF ARRAYS? |
Ende erreicht? |
compare with end of arrays high byte |
DID WE REACH THE END OF ARRAYS YET? |
||
.,B222 D0 04 BNE $B228 |
BNE LOPFDV |
nein: weiter |
branch if not reached array memory end |
NO, KEEP SEARCHING |
||
.,B224 E4 31 CPX $31 |
CPX STREND |
mit Tabellenende vergleichen |
else compare with end of arrays low byte |
|||
.,B226 F0 39 BEQ $B261 |
BEQ NOTFDD ;A FINE THING! NO ARRAY!. |
ja: nicht gefunden, anlegen |
go build array if not found search for array |
YES, THIS IS A NEW ARRAY NAME |
||
.,B228 A0 00 LDY #$00 |
LOPFDV: LDYI 0 |
Zeiger setzen |
clear index |
POINT AT 1ST CHAR OF ARRAY NAME |
||
.,B22A B1 5F LDA ($5F),Y |
LDADY LOWTR |
Namen aus Tabelle holen |
get array name first byte |
GET 1ST CHAR OF NAME |
||
.,B22C C8 INY |
INY |
Zeiger erhöhen |
increment index to second name byte |
POINT AT 2ND CHAR |
||
.,B22D C5 45 CMP $45 |
CMP VARNAM ;COMPARE HIGH ORDERS. |
mit ges. Namen vergleichen |
compare with this array name first byte |
1ST CHAR SAME? |
||
.,B22F D0 06 BNE $B237 |
BNE NMARY1 ;NO WAY IS IT THIS. GET OUT OF HERE. |
ungleich: $B237 |
branch if no match |
NO, MOVE TO NEXT ARRAY |
||
.,B231 A5 46 LDA $46 |
LDA VARNAM+1 |
Vergleich mit |
else get this array name second byte |
YES, TRY 2ND CHAR |
||
.,B233 D1 5F CMP ($5F),Y |
CMPDY LOWTR ;LOW ORDERS? |
zweitem Buchstaben |
compare with array name second byte |
SAME? |
||
.,B235 F0 16 BEQ $B24D |
BEQ GOTARY ;WELL, HERE IT IS !! |
gefunden: $B24D |
array found so branch no match |
YES, ARRAY FOUND |
||
.,B237 C8 INY |
NMARY1: INY |
Zeiger erhöhen |
increment index |
POINT AT OFFSET TO NEXT ARRAY |
||
.,B238 B1 5F LDA ($5F),Y |
LDADY LOWTR ;GET LENGTH. |
Suchzeiger zur |
get array size low byte |
ADD OFFSET TO RUNNING POINTER |
||
.,B23A 18 CLC |
CLC |
Feldlänge |
clear carry for add |
|||
.,B23B 65 5F ADC $5F |
ADC LOWTR |
Addieren |
add array start pointer low byte |
|||
.,B23D AA TAX |
TAX |
ergibt Zeiger auf |
copy low byte to X |
|||
.,B23E C8 INY |
INY |
nächstes Array |
increment index |
|||
.,B23F B1 5F LDA ($5F),Y |
LDADY LOWTR |
gleiches System |
get array size high byte |
|||
.,B241 65 60 ADC $60 |
ADC LOWTR+1 |
mit zweitem Byte |
add array memory pointer high byte |
|||
.,B243 90 D7 BCC $B21C |
BCC LOPFDA ;ALWAYS BRANCHES. |
und weiter suchen |
if no overflow go check next arraydo bad subscript error |
...ALWAYSERROR: BAD SUBSCRIPTS |
||
.,B245 A2 12 LDX #$12 |
BSERR: LDXI ERRBS ;GET BAD SUB ERROR NUMBER. |
Nummer für 'bad subscript' |
error $12, bad subscript error |
error number |
||
.:B247 2C .BYTE $2C |
SKIP2 |
makes next line BIT $0EA2do illegal quantity error |
TRICK TO SKIP NEXT LINEERROR: ILLEGAL QUANTITY |
|||
.,B248 A2 0E LDX #$0E |
FCERR: LDXI ERRFC ;TOO BIG. "FUNCTION CALL" ERROR. |
Nummer für 'illegal quanti.' |
error $0E, illegal quantity error |
error number |
||
.,B24A 4C 37 A4 JMP $A437 |
ERRGO3: JMP ERROR |
Fehlermeldung ausgeben |
do error #X then warm startfound the array |
FOUND THE ARRAY |
||
.,B24D A2 13 LDX #$13 |
GOTARY: LDXI ERRDD ;PERHAPS A "RE-DIMENSION" ERROR |
Nummer für 'redim'd array' |
set error $13, double dimension error |
SET UP FOR REDIM'D ARRAY ERROR |
error number |
|
.,B24F A5 0C LDA $0C |
LDA DIMFLG ;TEST THE DIMFLG |
DIM-Flag null? |
get DIM flag |
CALLED FROM "DIM" STATEMENT? |
||
.,B251 D0 F7 BNE $B24A |
BNE ERRGO3 |
nein: dann Fehlermeldung |
if we are trying to dimension it do error #X then warm start found the array and we're not dimensioning it so we must find an element in it |
YES, ERROR |
||
.,B253 20 94 B1 JSR $B194 |
JSR FMAPTR |
Zeiger auf 1.Arrayelement |
set-up array pointer to first element in array |
SET (ARYPNT) = ADDR OF FIRST ELEMENT |
||
.,B256 A5 0B LDA $0B |
LDA COUNT ;GET NUMBER OF DIMS INPUT. |
Zahl der gefundenen Dimensio. |
get dimensions count |
COMPARE NUMBER OF DIMENSIONS |
||
.,B258 A0 04 LDY #$04 |
LDYI 4 |
Zeiger setzen |
set index to array's # of dimensions |
|||
.,B25A D1 5F CMP ($5F),Y |
CMPDY LOWTR ;# OF DIMS THE SAME? |
mit Dimensionen des Arrays vergleichen |
compare with no of dimensions |
|||
.,B25C D0 E7 BNE $B245 |
BNE BSERR ;SAME SO GO GET DEFINITION. |
ungleich: 'bad subscript' |
if wrong do bad subscript error |
NOT SAME, SUBSCRIPT ERROR |
||
.,B25E 4C EA B2 JMP $B2EA |
JMP GETDEF ; ; HERE WHEN VARIABLE IS NOT FOUND IN THE ARRAY TABLE. ; ; BUILDING AN ENTRY. ; ; PUT DOWN THE DESCRIPTOR. ; SETUP NUMBER OF DIMENSIONS. ; MAKE SURE THERE IS ROOM FOR THE NEW ENTRY. ; REMEMBER "VARPNT". ; TALLY=4. ; SKIP 2 LOCS FOR LATER FILL IN OF SIZE. ; LOOP: GET AN INDICE ; PUT DOWN NUMBER+1 AND INCREMENT VARPTR. ; TALLY=TALLY*NUMBER+1. ; DECREMENT NUMBER-DIMS. ; BNE LOOP ; CALL "REASON" WITH [Y,A] REFLECTING LAST LOC OF VARIABLE. ; UPDATE STREND. ; ZERO ALL. ; MAKE TALLY INCLUDE MAXDIMS AND DESCRIPTOR. ; PUT DOWN TALLY. ; IF CALLED BY DIMENSION, RETURN. ; OTHERWISE INDEX INTO THE VARIABLE AS IF IT ; WERE FOUND ON THE INITIAL SEARCH. ; |
sucht gewünschtes ElementArrayvariable anlegen |
found array so go get element array not found, so build it |
CREATE A NEW ARRAY, UNLESS CALLED FROM GETARYPT |
allocate array |
|
.,B261 20 94 B1 JSR $B194 |
NOTFDD: JSR FMAPTR ;FORM ARYPNT. |
Länge des Arraykopfs |
set-up array pointer to first element in array |
PUT ADDR OF 1ST ELEMENT IN ARYPNT |
||
.,B264 20 08 A4 JSR $A408 |
JSR REASON |
prüft auf genügend Platz |
check available memory, do out of memory error if no room |
MAKE SURE ENOUGH MEMORY LEFT |
||
.,B267 A0 00 LDY #$00 |
LDAI 0 TAY |
Zeiger für Polynom- |
clear Y |
POINT Y-REG AT VARIABLE NAME SLOT |
||
.,B269 84 72 STY $72 |
STA CURTOL+1 IFE ADDPRC,< LDXI 4> IFN ADDPRC,< |
auswertung neu setzen |
clear array data size high byte |
START SIZE COMPUTATION |
||
.,B26B A2 05 LDX #$05 |
LDXI 5> |
Wert für Variablenlänge(REAL) |
set default element size |
ASSUME 5-BYTES PER ELEMENT |
||
.,B26D A5 45 LDA $45 |
LDA VARNAM ;THIS CODE ONLY WORKS FOR INTPRC=1 |
erster Buchstabe des Namens |
get variable name 1st byte |
STUFF VARIABLE NAME IN ARRAY |
||
.,B26F 91 5F STA ($5F),Y |
STADY LOWTR ;IF ADDPRC=1. IFN ADDPRC,< |
in Arraytabelle |
save array name 1st byte |
|||
.,B271 10 01 BPL $B274 |
BPL NOTFLT |
kein Integer? |
branch if not string or floating point array |
NOT INTEGER ARRAY |
||
.,B273 CA DEX |
DEX> |
bei Integerzahl |
decrement element size, $04 |
INTEGER ARRAY, DECR. SIZE TO 4-BYTES |
||
.,B274 C8 INY |
NOTFLT: INY |
Bytes vermindern |
increment index |
POINT Y-REG AT NEXT CHAR OF NAME |
||
.,B275 A5 46 LDA $46 |
LDA VARNAM+1 |
zweiter Buchstabe |
get variable name 2nd byte |
REST OF ARRAY NAME |
||
.,B277 91 5F STA ($5F),Y |
STADY LOWTR |
in Tabelle schreiben |
save array name 2nd byte |
|||
.,B279 10 02 BPL $B27D |
BPL STOMLT |
kein String oder Integer? |
branch if not integer or string |
REAL ARRAY, STICK WITH SIZE = 5 BYTES |
||
.,B27B CA DEX |
DEX IFN ADDPRC,< |
entgültige |
decrement element size, $03 |
INTEGER OR STRING ARRAY, ADJUST SIZE |
||
.,B27C CA DEX |
DEX> |
Variablenlänge herstellen |
decrement element size, $02 |
TO INTEGER=3, STRING=2 BYTES |
||
.,B27D 86 71 STX $71 |
STOMLT: STX CURTOL |
und speichern (2, 3 oder 5) |
save element size |
STORE LOW-BYTE OF ARRAY ELEMENT SIZE |
||
.,B27F A5 0B LDA $0B |
LDA COUNT |
Anzahl der Dimensionen holen |
get dimensions count |
STORE NUMBER OF DIMENSIONS |
||
.,B281 C8 INY |
REPEAT 3,<INY> |
Zeiger |
increment index .. |
IN 5TH BYTE OF ARRAY |
||
.,B282 C8 INY |
um 3 |
.. to array .. |
||||
.,B283 C8 INY |
erhöhen |
.. dimension count |
||||
.,B284 91 5F STA ($5F),Y |
STADY LOWTR ;SAVE NUMBER OF DIMENSIONS. |
im Arrayheader speichern |
save array dimension count |
|||
.,B286 A2 0B LDX #$0B |
LOPPTA: LDXI 11 ;DEFAULT SIZE. |
11, Defaultwert für |
set default dimension size low byte |
DEFAULT DIMENSION = 11 ELEMENTS |
||
.,B288 A9 00 LDA #$00 |
LDAI 0 |
Dimensionierung |
set default dimension size high byte |
FOR HI-BYTE OF DIMENSION IF DEFAULT |
||
.,B28A 24 0C BIT $0C |
BIT DIMFLG |
Aufruf durch DIM-Befehl? |
test DIM flag |
DIMENSIONED ARRAY? |
||
.,B28C 50 08 BVC $B296 |
BVC NOTDIM ;NOT IN A DIM STATEMENT. |
nein: $B296 |
branch if default to be used |
NO, USE DEFAULT VALUE |
||
.,B28E 68 PLA |
PLA ;GET LOW ORDER OF INDICE. |
Dimension vom Stapel holen |
pull dimension size low byte |
GET SPECIFIED DIM IN A,X |
||
.,B28F 18 CLC |
CLC |
Carry löschen (Addition) |
clear carry for add |
# ELEMENTS IS 1 LARGER THAN |
||
.,B290 69 01 ADC #$01 |
ADCI 1 |
eins addieren |
add 1, allow for zeroeth element |
DIMENSION VALUE |
||
.,B292 AA TAX |
TAX |
und ins X-Reg. |
copy low byte to X |
|||
.,B293 68 PLA |
PLA ;GET HIGH PART OF INDICE. |
2.Wert holen |
pull dimension size high byte |
|||
.,B294 69 00 ADC #$00 |
ADCI 0 |
Übertrag addieren |
add carry to high byte |
|||
.,B296 C8 INY |
NOTDIM: INY |
Zeiger erhöhen |
incement index to dimension size high byte |
ADD THIS DIMENSION TO ARRAY DESCRIPTOR |
||
.,B297 91 5F STA ($5F),Y |
STADY LOWTR ;STORE HIGH PART OF INDICE. |
und speichern |
save dimension size high byte |
|||
.,B299 C8 INY |
INY |
Zeiger erhöhen |
incement index to dimension size low byte |
|||
.,B29A 8A TXA |
TXA |
1.Wert wieder in den Akku |
copy dimension size low byte |
|||
.,B29B 91 5F STA ($5F),Y |
STADY LOWTR ;STORE LOW ORDER OF INDICE. |
und ebenfalls speichern |
save dimension size low byte |
|||
.,B29D 20 4C B3 JSR $B34C |
JSR UMULT ;[X,A]=[CURTOL]*[LOWTR,Y] |
Platz für Dimensionen berech. |
compute array size |
MULTIPLY THIS DIMENSION BY RUNNING SIZE ((LOWTR)) * (STRNG2) --> A,X |
||
.,B2A0 86 71 STX $71 |
STX CURTOL ;SAVE NEW TALLY. |
LOW- und HIGH-Byte des |
save result low byte |
STORE RUNNING SIZE IN STRNG2 |
||
.,B2A2 85 72 STA $72 |
STA CURTOL+1 |
Variablenende-Zeigers merken |
save result high byte |
|||
.,B2A4 A4 22 LDY $22 |
LDY INDEX |
Zeiger auf Arrayheader |
restore index |
RETRIEVE Y SAVED BY MULTIPLY.SUBSCRIPT |
||
.,B2A6 C6 0B DEC $0B |
DEC COUNT ;ANY MORE INDICES LEFT? |
weitere Dimensionen? |
decrement dimensions count |
COUNT DOWN # DIMS |
||
.,B2A8 D0 DC BNE $B286 |
BNE LOPPTA ;YES. |
ja: $B286 (Schleifenbeginn) |
loop if not all done |
LOOP TILL DONE NOW A,X HAS TOTAL # BYTES OF ARRAY ELEMENTS |
||
.,B2AA 65 59 ADC $59 |
ADC ARYPNT+1 |
Feldlänge plus Startadresse |
add array data pointer high byte |
COMPUTE ADDRESS OF END OF THIS ARRAY |
||
.,B2AC B0 5D BCS $B30B |
BCS OMERR1 ;OVERFLOW. |
Überlauf: 'OUT OF MEMORY' |
if overflow do out of memory error then warm start |
...TOO LARGE, ERROR |
||
.,B2AE 85 59 STA $59 |
STA ARYPNT+1 ;COMPUTE WHERE TO ZERO. |
Wert wieder speichern |
save array data pointer high byte |
|||
.,B2B0 A8 TAY |
TAY |
und ins Y-Reg. bringen |
copy array data pointer high byte |
|||
.,B2B1 8A TXA |
TXA |
Variablenendzeiger in Akku |
copy array size low byte |
|||
.,B2B2 65 58 ADC $58 |
ADC ARYPNT |
2.Zeichen addieren |
add array data pointer low byte |
|||
.,B2B4 90 03 BCC $B2B9 |
BCC GREASE |
Überlauf: Platz prüfen |
branch if no rollover |
|||
.,B2B6 C8 INY |
INY |
Endadresse erhöhen |
else increment next array pointer high byte |
|||
.,B2B7 F0 52 BEQ $B30B |
BEQ OMERR1 |
Überlauf: 'OUT OF MEMORY' |
if rolled over do out of memory error then warm start |
...TOO LARGE, ERROR |
||
.,B2B9 20 08 A4 JSR $A408 |
GREASE: JSR REASON ;GET ROOM. |
prüft auf Speicherplatz |
check available memory, do out of memory error if no room |
MAKE SURE THERE IS ROOM UP TO Y,A |
||
.,B2BC 85 31 STA $31 |
STWD STREND ;NEW END OF STORAGE. |
Zeiger auf Ende |
set end of arrays low byte |
THERE IS ROOM SO SAVE NEW END OF TABLE |
||
.,B2BE 84 32 STY $32 |
der Arraytabelle setzen |
set end of arrays high byte now the aray is created we need to zero all the elements in it |
AND ZERO THE ARRAY |
|||
.,B2C0 A9 00 LDA #$00 |
LDAI 0 ;STORING [ACCA] IS FASTER THAN CLEAR. |
Array mit Nullen füllen |
clear A for array clear |
|||
.,B2C2 E6 72 INC $72 |
INC CURTOL+1 |
Schleifenzähler high um 1 erhöhen |
increment array size high byte, now block count |
PREPARE FOR FAST ZEROING LOOP |
||
.,B2C4 A4 71 LDY $71 |
LDY CURTOL |
Schleifenzähler low |
get array size low byte, now index to block |
# BYTES MOD 256 |
||
.,B2C6 F0 05 BEQ $B2CD |
BEQ DECCUR |
wenn null: $B2CD |
branch if $00 |
FULL PAGE |
||
.,B2C8 88 DEY |
ZERITA: DEY |
Zeiger vermindern |
decrement index, do 0 to n-1 |
CLEAR PAGE FULL |
||
.,B2C9 91 58 STA ($58),Y |
STADY ARYPNT |
Nullwert setzen |
clear array element byte |
|||
.,B2CB D0 FB BNE $B2C8 |
BNE ZERITA ;NO. CONTINUE. |
solang Y <>0: $B2C8 |
loop until this block done |
|||
.,B2CD C6 59 DEC $59 |
DECCUR: DEC ARYPNT+1 |
High-Byte STA-Ziel verringern |
decrement array pointer high byte |
POINT TO NEXT PAGE |
||
.,B2CF C6 72 DEC $72 |
DEC CURTOL+1 |
Schleifenzähler high verringern |
decrement block count high byte |
COUNT THE PAGES |
||
.,B2D1 D0 F5 BNE $B2C8 |
BNE ZERITA ;DO ANOTHER BLOCK. |
solang <>0: $B2C8 |
loop until all blocks done |
STILL MORE TO CLEAR |
||
.,B2D3 E6 59 INC $59 |
INC ARYPNT+1 ;BUMP BACK UP. WILL USE LATER. |
High-Byte STA-Ziel erhöhen |
correct for last loop |
RECOVER LAST DEC, POINT AT 1ST ELEMENT |
||
.,B2D5 38 SEC |
SEC |
Carry setzen (Subtr.) |
set carry for subtract |
|||
.,B2D6 A5 31 LDA $31 |
LDA STREND ;RESTORE [ACCA]. |
Zeiger auf Feldende |
get end of arrays low byte |
COMPUTE OFFSET TO END OF ARRAYS |
||
.,B2D8 E5 5F SBC $5F |
SBC LOWTR ;DETERMINE LENGTH. |
- Zeiger auf Arrayheader |
subtract array start low byte |
AND STORE IN ARRAY DESCRIPTOR |
||
.,B2DA A0 02 LDY #$02 |
LDYI 2 |
Zeiger setzen |
index to array size low byte |
|||
.,B2DC 91 5F STA ($5F),Y |
STADY LOWTR ;LOW. |
Arraylänge LOW |
save array size low byte |
|||
.,B2DE A5 32 LDA $32 |
LDA STREND+1 |
Zeiger auf Feldende |
get end of arrays high byte |
|||
.,B2E0 C8 INY |
INY |
Zeiger erhöhen |
index to array size high byte |
|||
.,B2E1 E5 60 SBC $60 |
SBC LOWTR+1 |
- Zeiger auf Arrayheader |
subtract array start high byte |
|||
.,B2E3 91 5F STA ($5F),Y |
STADY LOWTR ;HIGH. |
Arraylänge HIGH |
save array size high byte |
|||
.,B2E5 A5 0C LDA $0C |
LDA DIMFLG |
Aufruf vom DIM-Befehl? |
get default DIM flag |
WAS THIS CALLED FROM "DIM" STATEMENT? |
||
.,B2E7 D0 62 BNE $B34B |
BNE DIMRTS ;BYE. |
ja: RTSArrayelement suchen |
exit if this was a DIM command else, find element |
YES, WE ARE FINISHED |
||
.,B2E9 C8 INY |
INY ; ; AT THIS POINT [LOWTR,Y] POINTS BEYOND THE SIZE TO THE NUMBER OF ; DIMENSIONS. STRATEGY: ; NUMDIM=NUMBER OF DIMENSIONS. ; CURTOL=0. ; INLPNM:GET A NEW INDICE. ; MAKE SURE INDICE IS NOT TOO BIG. ; MULTIPLY CURTOL BY CURMAX. ; ADD INDICE TO CURTOL. ; NUMDIM=NUMDIM-1. ; BNE INLPNM. ; USE [CURTOL]*4 AS OFFSET. ; |
Zeiger erhöhen |
set index to # of dimensions, the dimension indeces are on the stack and will be removed as the position of the array element is calculated |
NO, NOW NEED TO FIND THE ELEMENTFIND SPECIFIED ARRAY ELEMENT(LOWTR),Y POINTS AT # OF DIMS IN ARRAY DESCRIPTORTHE SUBSCRIPTS ARE ALL ON THE STACK AS INTEGERS |
compute reference to array element |
|
.,B2EA B1 5F LDA ($5F),Y |
GETDEF: LDADY LOWTR |
Zahl der Dimensionen |
get array's dimension count |
GET # OF DIMENSIONS |
||
.,B2EC 85 0B STA $0B |
STA COUNT ;SAVE A COUNTER. |
speichern |
save it |
|||
.,B2EE A9 00 LDA #$00 |
LDAI 0 ;ZERO [CURTOL]. |
Nullwert laden und |
clear byte |
ZERO SUBSCRIPT ACCUMULATOR |
||
.,B2F0 85 71 STA $71 |
STA CURTOL |
Zeiger auf Polynom- |
clear array data pointer low byte |
|||
.,B2F2 85 72 STA $72 |
INLPNM: STA CURTOL+1 |
auswertung löschen |
save array data pointer high byte |
|||
.,B2F4 C8 INY |
INY |
Zeiger erhöhen |
increment index, point to array bound high byte |
|||
.,B2F5 68 PLA |
PLA ;GET LOW INDICE. |
1. Indexwert vom Stapel |
pull array index low byte |
PULL NEXT SUBSCRIPT FROM STACK |
||
.,B2F6 AA TAX |
TAX |
holen und ins X-Reg. bringen |
copy to X |
SAVE IN FAC+3,4 |
||
.,B2F7 85 64 STA $64 |
STA INDICE |
Wert speichern |
save index low byte to FAC1 mantissa 3 |
AND COMPARE WITH DIMENSIONED SIZE |
||
.,B2F9 68 PLA |
PLA ;AND THE HIGH PART |
2. Indexwert holen |
pull array index high byte |
|||
.,B2FA 85 65 STA $65 |
STA INDICE+1 |
und speichern |
save index high byte to FAC1 mantissa 4 |
|||
.,B2FC D1 5F CMP ($5F),Y |
CMPDY LOWTR ;COMPARE WITH MAX INDICE. |
mit Wert im Array vergleichen |
compare with array bound high byte |
|||
.,B2FE 90 0E BCC $B30E |
BCC INLPN2 |
kleiner? |
branch if within bounds |
SUBSCRIPT NOT TOO LARGE |
||
.,B300 D0 06 BNE $B308 |
BNE BSERR7 ;IF GREATER, "BAD SUBSCRIPT" ERROR. |
größer: 'bad subscript' |
if outside bounds do bad subscript error else high byte was = so test low bytes |
SUBSCRIPT IS TOO LARGE |
||
.,B302 C8 INY |
INY |
Zeiger erhöhen |
index to array bound low byte |
CHECK LOW-BYTE OF SUBSCRIPT |
||
.,B303 8A TXA |
TXA |
1.Wert zurückholen |
get array index low byte |
|||
.,B304 D1 5F CMP ($5F),Y |
CMPDY LOWTR |
LOW-Byte vergleichen |
compare with array bound low byte |
|||
.,B306 90 07 BCC $B30F |
BCC INLPN1 |
kleiner: dann weiter |
branch if within bounds |
NOT TOO LARGE |
||
.,B308 4C 45 B2 JMP $B245 |
BSERR7: JMP BSERR |
'bad subscript' |
do bad subscript error |
BAD SUBSCRIPTS ERROR |
||
.,B30B 4C 35 A4 JMP $A435 |
OMERR1: JMP OMERR |
'out of memory'Berechnung der Adresseeines Arrayelements |
do out of memory error then warm start |
MEM FULL ERROR |
||
.,B30E C8 INY |
INLPN2: INY |
Zeiger erhöhen |
index to array bound low byte |
BUMP POINTER INTO DESCRIPTOR |
||
.,B30F A5 72 LDA $72 |
INLPN1: LDA CURTOL+1 ;DON'T MULTIPLY IF CURTOL=0. |
Zeiger auf Polynomausw.(HIGH) |
get array data pointer high byte |
BYPASS MULTIPLICATION IF VALUE SO |
||
.,B311 05 71 ORA $71 |
ORA CURTOL |
Zeiger auf Polynomausw.(LOW) |
OR with array data pointer low byte |
FAR = 0 |
||
.,B313 18 CLC |
CLC ;PREPARE TO GET INDICE BACK. |
Carry löschen |
clear carry for either add, carry always clear here ?? |
|||
.,B314 F0 0A BEQ $B320 |
BEQ ADDIND ;GET HIGH PART OF INDICE BACK. |
Multiplikation umgehen |
branch if array data pointer = null, skip multiply |
IT IS ZERO SO FAR |
||
.,B316 20 4C B3 JSR $B34C |
JSR UMULT ;MULTIPLY [CURTOL] BY [LOWTR,Y,Y+1]. |
Multiplikation |
compute array size |
NOT ZERO, SO MULTIPLY |
||
.,B319 8A TXA |
TXA |
(X/Y)=($71/72)*(($5F/60),Y) |
get result low byte |
ADD CURRENT SUBSCRIPT |
||
.,B31A 65 64 ADC $64 |
ADC INDICE ;ADD IN [INDICE]. |
add index low byte from FAC1 mantissa 3 |
||||
.,B31C AA TAX |
TAX |
Akku zurück ins X-Reg. |
save result low byte |
|||
.,B31D 98 TYA |
TYA |
get result high byte |
||||
.,B31E A4 22 LDY $22 |
LDY INDEX1 |
Zeiger in Arrayheader |
restore index |
RETRIEVE Y SAVED BY MULTIPLY.SUBSCRIPT |
||
.,B320 65 65 ADC $65 |
ADDIND: ADC INDICE+1 |
add index high byte from FAC1 mantissa 4 |
FINISH ADDING CURRENT SUBSCRIPT |
|||
.,B322 86 71 STX $71 |
STX CURTOL |
save array data pointer low byte |
STORE ACCUMULATED OFFSET |
|||
.,B324 C6 0B DEC $0B |
DEC COUNT ;ANY MORE? |
Anzahl der Dimensionen |
decrement dimensions count |
LAST SUBSCRIPT YET? |
||
.,B326 D0 CA BNE $B2F2 |
BNE INLPNM ;YES. |
mit nächstem Index weiter |
loop if dimensions still to do |
NO, LOOP TILL DONE |
||
.,B328 85 72 STA $72 |
STA CURTOL+1 ;FIX ARRAY BUG **** IFE ADDPRC,< LDXI 4> IFN ADDPRC,< |
save array data pointer high byte |
YES, NOW MULTIPLY BE ELEMENT SIZE |
|||
.,B32A A2 05 LDX #$05 |
LDXI 5 ;THIS CODE ONLY WORKS FOR INTPRC=1 |
Variablenlänge (5, REAL) |
set default element size |
START WITH SIZE = 5 |
||
.,B32C A5 45 LDA $45 |
LDA VARNAM ;IF ADDPRC=1. |
erster Buchstabe des Namens |
get variable name 1st byte |
DETERMINE VARIABLE TYPE |
||
.,B32E 10 01 BPL $B331 |
BPL NOTFL1 |
Integer? nein: $B331 |
branch if not string or floating point array |
NOT INTEGER |
||
.,B330 CA DEX |
DEX> |
Länge vermindern |
decrement element size, $04 |
INTEGER, BACK DOWN SIZE TO 4 BYTES |
||
.,B331 A5 46 LDA $46 |
NOTFL1: LDA VARNAM+1 |
zweiter Buchstabe des Namens |
get variable name 2nd byte |
DISCRIMINATE BETWEEN REAL AND STR |
||
.,B333 10 02 BPL $B337 |
BPL STOML1 |
FLP? ja: $B337 |
branch if not integer or string |
IT IS REAL |
||
.,B335 CA DEX |
DEX IFN ADDPRC,< |
Länge 2 mal |
decrement element size, $03 |
SIZE = 3 IF STRING, =2 IF INTEGER |
||
.,B336 CA DEX |
DEX> |
vermindern |
decrement element size, $02 |
|||
.,B337 86 28 STX $28 |
STOML1: STX ADDEND |
Länge der Variablen 2,3 oder5 |
save dimension size low byte |
SET UP MULTIPLIER |
||
.,B339 A9 00 LDA #$00 |
LDAI 0 |
Wert laden und damit |
clear dimension size high byte |
HI-BYTE OF MULTIPLIER |
||
.,B33B 20 55 B3 JSR $B355 |
JSR UMULTD ;ON RTS, A&Y=HI . X=LO. |
Offset im Array berechnen |
compute array size |
(STRNG2) BY ELEMENT SIZE |
||
.,B33E 8A TXA |
TXA |
zur Adresse des ersten |
copy array size low byte |
ADD ACCUMULATED OFFSET |
||
.,B33F 65 58 ADC $58 |
ADC ARYPNT |
Elements addieren |
add array data start pointer low byte |
TO ADDRESS OF 1ST ELEMENT |
||
.,B341 85 47 STA $47 |
STA VARPNT |
ergibt Variablenadresse |
save as current variable pointer low byte |
TO GET ADDRESS OF SPECIFIED ELEMENT |
||
.,B343 98 TYA |
TYA |
2.Byte in Akku holen |
copy array size high byte |
|||
.,B344 65 59 ADC $59 |
ADC ARYPNT+1 |
addieren, ergibt |
add array data start pointer high byte |
|||
.,B346 85 48 STA $48 |
STA VARPNT+1 |
HIGH-Byte der Adresse |
save as current variable pointer high byte |
|||
.,B348 A8 TAY |
TAY |
ins Y-Reg. bringen und |
copy high byte to Y |
RETURN WITH ADDR IN VARPNT |
||
.,B349 A5 47 LDA $47 |
LDA VARPNT |
1.Byte wieder in Akku holen |
get current variable pointer low byte pointer to element is now in AY |
AND IN Y,A |
||
.,B34B 60 RTS |
DIMRTS: RTS ;RETURN TO CALLER.INTEGER ARITHMETIC ROUTINES.;TWO BYTE UNSIGNED INTEGER MULTIPLY.;THIS IS FOR MULTIPLY DIMENSIONED ARRAYS. ; [X,Y]=[X,A]=[CURTOL]*[LOWTR,Y,Y+1]. |
RücksprungHilfsroutine fürArrayberechnung |
compute array size, result in XY |
MULTIPLY (STRNG2) BY ((LOWTR),Y)LEAVING PRODUCT IN A,X.(HI-BYTE ALSO IN Y.)USED ONLY BY ARRAY SUBSCRIPT ROUTINES |
XY = XA = length * limit from array data |
|
.,B34C 84 22 STY $22 |
UMULT: STY INDEX |
Register merken |
save index |
SAVE Y-REG |
||
.,B34E B1 5F LDA ($5F),Y |
LDADY LOWTR |
1. Wert holen |
get dimension size low byte |
GET MULTIPLIER |
||
.,B350 85 28 STA $28 |
STA ADDEND ;LOW, THEN HIGH. |
und abspeichern |
save dimension size low byte |
SAVE IN RESULT+2,3 |
||
.,B352 88 DEY |
DEY |
Zeiger vermindern |
decrement index |
|||
.,B353 B1 5F LDA ($5F),Y |
LDADY LOWTR ;PUT [LOWTR,Y,Y+1] IN FASTER MEMORY. |
2. Wert holen |
get dimension size high byte |
|||
.,B355 85 29 STA $29 |
UMULTD: STA ADDEND+1 |
und abspeichern |
save dimension size high byte |
LOW BYTE OF MULTIPLIER |
||
.,B357 A9 10 LDA #$10 |
LDAI 16 |
Wert laden und damit |
count = $10 (16 bit multiply) |
MULTIPLY 16 BITS |
||
.,B359 85 5D STA $5D |
STA DECCNT |
Verschiebezähler setzen |
save bit count |
|||
.,B35B A2 00 LDX #$00 |
LDXI 0 ;CLR THE ACCS. |
LOW- und HIGH-Byte des Er- |
clear result low byte |
PRODUCT = 0 INITIALLY |
||
.,B35D A0 00 LDY #$00 |
LDYI 0 ;RESULT INITIALLY ZERO. |
gebnisregisters auf 0 setzen |
clear result high byte |
|||
.,B35F 8A TXA |
UMULTC: TXA |
LOW-Byte in Akku holen und |
get result low byte |
DOUBLE PRODUCT |
||
.,B360 0A ASL |
ASL A, ;MULTIPLY BY TWO. |
um 1 Bit nach links schieben |
*2 |
LOW BYTE |
||
.,B361 AA TAX |
TAX |
Byte zurück ins X-Reg. |
save result low byte |
|||
.,B362 98 TYA |
TYA |
HIGH-Byte in den Akku holen, |
get result high byte |
HIGH BYTE |
||
.,B363 2A ROL |
ROL A, |
um 1 Bit nach links rotieren |
*2 |
IF TOO LARGE, SET CARRY |
||
.,B364 A8 TAY |
TAY |
und zurückbringen |
save result high byte |
|||
.,B365 B0 A4 BCS $B30B |
BCS OMERR1 ;TWO MUCH ! |
Überlauf: 'out of memory' |
if overflow go do "Out of memory" error |
TOO LARGE, "MEM FULL ERROR" |
||
.,B367 06 71 ASL $71 |
ASL CURTOL |
nächstes Bit aus |
shift element size low byte |
NEXT BIT OF MUTLPLICAND |
||
.,B369 26 72 ROL $72 |
ROL CURTOL+1 |
$71/72 herausholen |
shift element size high byte |
INTO CARRY |
||
.,B36B 90 0B BCC $B378 |
BCC UMLCNT ;NOTHING IN THIS POSITION TO MULTIPLY. |
=0? ja: Addition umgehen |
skip add if no carry |
BIT=0, DON'T NEED TO ADD |
||
.,B36D 18 CLC |
CLC |
Carry setzen (Addition) |
else clear carry for add |
BIT=1, ADD INTO PARTIAL PRODUCT |
||
.,B36E 8A TXA |
TXA |
LOW-Byte holen |
get result low byte |
|||
.,B36F 65 28 ADC $28 |
ADC ADDEND |
1. Wert addieren |
add dimension size low byte |
|||
.,B371 AA TAX |
TAX |
LOW-Byte zurückbringen |
save result low byte |
|||
.,B372 98 TYA |
TYA |
HIGH-Byte holen |
get result high byte |
|||
.,B373 65 29 ADC $29 |
ADC ADDEND+1 |
2. Wert addieren |
add dimension size high byte |
|||
.,B375 A8 TAY |
TAY |
HIGH-Byte zurückholen |
save result high byte |
|||
.,B376 B0 93 BCS $B30B |
BCS OMERR1 ;MAN, JUST TOO MUCH ! |
Überlauf: 'out of memory' |
if overflow go do "Out of memory" error |
TOO LARGE, "MEM FULL ERROR" |
||
.,B378 C6 5D DEC $5D |
UMLCNT: DEC DECCNT ;DONE? |
nächstes Bit holen |
decrement bit count |
16-BITS YET? |
||
.,B37A D0 E3 BNE $B35F |
BNE UMULTC ;KEEP IT UP. |
alle 16 Bits? nein: weiter |
loop until all done |
NO, KEEP SHUFFLING |
||
.,B37C 60 RTS |
UMLRTS: RTS ;YES, ALL DONE. PAGE FRE FUNCTION AND INTEGER TO FLOATING ROUTINES. |
RücksprungBASIC-Funktion FRE |
perform FRE() |
YES, PRODUCT IN Y,X AND A,X"FRE" FUNCTIONCOLLECTS GARBAGE AND RETURNS # BYTES OF MEMORY LEFT |
FRE function |
|
.,B37D A5 0D LDA $0D |
FRE: LDA VALTYP |
Typflag |
get data type flag, $FF = string, $00 = numeric |
LOOK AT VALUE OF ARGUMENT |
||
.,B37F F0 03 BEQ $B384 |
BEQ NOFREF |
kein String |
branch if numeric |
=0 MEANS REAL, =$FF MEANS STRING |
||
.,B381 20 A6 B6 JSR $B6A6 |
JSR FREFAC |
FRESTR |
pop string off descriptor stack, or from top of string space returns with A = length, X=$71=pointer low byte, Y=$72=pointer high byte FRE(n) was numeric so do this |
STRING, SO SET IT FREE IS TEMP |
||
.,B384 20 26 B5 JSR $B526 |
NOFREF: JSR GARBA2 |
Garbage Collection |
go do garbage collection |
COLLECT ALL THE GARBAGE IN SIGHT |
||
.,B387 38 SEC |
SEC |
Carry setzen (Subtr.) |
set carry for subtract |
COMPUTE SPACE BETWEEN ARRAYS AND |
||
.,B388 A5 33 LDA $33 |
LDA FRETOP ;WE WANT |
Stringanfang (LOW) |
get bottom of string space low byte |
STRING TEMP AREA |
||
.,B38A E5 31 SBC $31 |
SBC STREND ;[FRETOP]-[STREND]. |
- Variablenende (LOW) |
subtract end of arrays low byte |
|||
.,B38C A8 TAY |
TAY |
ergibt freien Speicher |
copy result to Y |
|||
.,B38D A5 34 LDA $34 |
LDA FRETOP+1 |
Stringanfang (HIGH) |
get bottom of string space high byte |
|||
.,B38F E5 32 SBC $32 |
SBC STREND+1 |
- Variablenende (HIGH) |
subtract end of arrays high byteconvert fixed integer AY to float FAC1 |
FREE SPACE IN Y,A FALL INTO GIVAYF TO FLOAT THE VALUE NOTE THAT VALUES OVER 32767 WILL RETURN AS NEGATIVE FLOAT THE SIGNED INTEGER IN A,Y |
routine to convert integer to float |
|
.,B391 A2 00 LDX #$00 |
GIVAYF: LDXI 0 |
Wert laden und |
set type = numeric |
MARK FAC VALUE TYPE REAL |
||
.,B393 86 0D STX $0D |
STX VALTYP |
Flag auf numerisch setzen |
clear data type flag, $FF = string, $00 = numeric |
|||
.,B395 85 62 STA $62 |
STWD FACHO |
LOW- und HIGH-Byte des |
save FAC1 mantissa 1 |
SAVE VALUE FROM A,Y IN MANTISSA |
||
.,B397 84 63 STY $63 |
Ergebnisses merken |
save FAC1 mantissa 2 |
||||
.,B399 A2 90 LDX #$90 |
LDXI 144 ;SET EXPONENT TO 2^16. |
und nach |
set exponent=2^16 (integer) |
SET EXPONENT TO 2^16 |
||
.,B39B 4C 44 BC JMP $BC44 |
JMP FLOATS ;TURN IT TO A FLOATING PNT #. |
Fließkomma wandlenBASIC-Funktion POS |
set exp = X, clear FAC1 3 and 4, normalise and returnperform POS() |
CONVERT TO SIGNED FP"POS" FUNCTIONRETURNS CURRENT LINE POSITION FROM MON.CH |
POS function |
|
.,B39E 38 SEC |
POS: LDY TRMPOS ;GET POSITION. |
C=1 Cursorposition holen |
set Cb for read cursor position |
|||
.,B39F 20 F0 FF JSR $FFF0 |
Cursorposition holen |
read/set X,Y cursor position |
FLOAT (Y) INTO FAC, GIVING VALUE 0-255 |
|||
.,B3A2 A9 00 LDA #$00 |
SNGFLT: LDAI 0 |
Z=1 |
clear high byte |
MSB = 0 |
||
.,B3A4 F0 EB BEQ $B391 |
BEQA GIVAYF ;FLOAT IT. PAGE SIMPLE-USER-DEFINED-FUNCTION CODE.;; NOTE ONLY SINGLE ARGUMENTS ARE ALLOWED TO FUNCTIONS ; AND FUNCTIONS MUST BE OF THE SINGLE LINE FORM: ; DEF FNA(X)=X^2+X-2 ; NO STRINGS CAN BE INVOLVED WITH THESE FUNCTIONS. ; ; IDEA: CREATE A SIMPLE VARIABLE ENTRY ; WHOSE FIRST CHARACTER HAS THE 200 BIT SET. ; THE VALUE WILL BE: ; ; A TEXT PNTR TO THE FORMULA. ; A PNTR TO THE ARGUMENT VARIABLE. ; ; FUNCTION NAMES CAN BE LIKE "FNA4". ; ; ; SUBROUTINE TO SEE IF WE ARE IN DIRECT MODE. ; AND COMPLAIN IF SO. ; |
unbedingter SprungTest auf Direkt-Modus |
convert fixed integer AY to float FAC1, branch always check not Direct, used by DEF and INPUT |
...ALWAYSCHECK FOR DIRECT OR RUNNING MODEGIVING ERROR IF DIRECT MODE |
check for non-direct mode |
|
.,B3A6 A6 3A LDX $3A |
ERRDIR: LDX CURLIN+1 ;DIR MODE HAS [CURLIN]=0,255 |
Flag laden (Direktm. = $FF) |
get current line number high byte |
=$FF IF DIRECT MODE |
||
.,B3A8 E8 INX |
INX ;SO NOW, IS RESULT ZERO? |
testen |
increment it |
MAKES $FF INTO ZERO |
||
.,B3A9 D0 A0 BNE $B34B |
BNE DIMRTS ;YES. |
nein: dann RTS |
return if not direct mode else do illegal direct error |
RETURN IF RUNNING MODE |
||
.,B3AB A2 15 LDX #$15 |
LDXI ERRID ;INPUT DIRECT ERROR CODE. |
Nummer für 'illegal direct' |
error $15, illegal direct error |
DIRECT MODE, GIVE ERROR |
error number |
|
.:B3AD 2C .BYTE $2C |
SKIP2 |
makes next line BIT $1BA2 |
TRICK TO SKIP NEXT 2 BYTES |
|||
.,B3AE A2 1B LDX #$1B |
ERRGUF: LDXI ERRUF ;USER DEFINED FUNCTION NEVER DEFINED |
Nummer für 'undef'd function' |
error $1B, undefined function error |
UNDEFINDED FUNCTION ERROR |
error number |
|
.,B3B0 4C 37 A4 JMP $A437 |
ERRGO1: JMP ERROR |
Fehlermeldung ausgebenBASIC-Befehl DEF FN |
do error #X then warm startperform DEF |
"DEF" STATEMENT |
DEF command |
|
.,B3B3 20 E1 B3 JSR $B3E1 |
DEF: JSR GETFNM ;GET A PNTR TO THE FUNCTION. |
prüft FN-Syntax |
check FNx syntax |
PARSE "FN", FUNCTION NAME |
||
.,B3B6 20 A6 B3 JSR $B3A6 |
JSR ERRDIR |
testet auf Direkt-Modus |
check not direct, back here if ok |
ERROR IF IN DIRECT MODE |
||
.,B3B9 20 FA AE JSR $AEFA |
JSR CHKOPN ;MUST HAVE "(". |
prüft auf 'Klammer auf |
scan for "(", else do syntax error then warm start |
NEED "(" |
||
.,B3BC A9 80 LDA #$80 |
LDAI 128 |
Wert laden |
set flag for FNx |
FLAG PTRGET THAT CALLED FROM "DEF FN" |
||
.,B3BE 85 10 STA $10 |
STA SUBFLG ;PROHIBIT SUBSCRIPTED VARIABLES. |
sperrt INTEGER-Variable |
save subscript/FNx flag |
ALLOW ONLY SIMPLE FP VARIABLE FOR ARG |
||
.,B3C0 20 8B B0 JSR $B08B |
JSR PTRGET ;GET PNTR TO ARGUMENT. |
sucht Variable |
get variable address |
GET PNTR TO ARGUMENT |
||
.,B3C3 20 8D AD JSR $AD8D |
JSR CHKNUM ;IS IT A NUMBER? |
prüft auf numerisch |
check if source is numeric, else do type mismatch |
MUST BE NUMERIC |
||
.,B3C6 20 F7 AE JSR $AEF7 |
JSR CHKCLS ;MUST HAVE ")" |
prüft auf 'Klammer zu' |
scan for ")", else do syntax error then warm start |
MUST HAVE ")" NOW |
||
.,B3C9 A9 B2 LDA #$B2 |
SYNCHK EQULTK ;MUST HAVE "=". |
'=' BASIC-Code |
get = token |
NOW NEED "=" |
||
.,B3CB 20 FF AE JSR $AEFF |
prüft auf '=' |
scan for CHR$(A), else do syntax error then warm start |
OR ELSE SYNTAX ERROR |
|||
.,B3CE 48 PHA |
IFN ADDPRC,<PHA> ;PUT CRAZY BYTE ON. |
erstes Zeichen auf Stapel |
push next character |
SAVE CHAR AFTER "=" |
||
.,B3CF A5 48 LDA $48 |
PSHWD VARPNT |
LOW- und HIGH-Byte der |
get current variable pointer high byte |
SAVE PNTR TO ARGUMENT |
||
.,B3D1 48 PHA |
FN-Variablen-Adresse |
push it |
||||
.,B3D2 A5 47 LDA $47 |
auf den Stapel |
get current variable pointer low byte |
||||
.,B3D4 48 PHA |
legen |
push it |
||||
.,B3D5 A5 7B LDA $7B |
PSHWD TXTPTR |
LOW- und HIGH-Byte |
get BASIC execute pointer high byte |
SAVE TXTPTR |
||
.,B3D7 48 PHA |
des Programmzeigers |
push it |
||||
.,B3D8 A5 7A LDA $7A |
auf den Stapel |
get BASIC execute pointer low byte |
||||
.,B3DA 48 PHA |
legen |
push it |
||||
.,B3DB 20 F8 A8 JSR $A8F8 |
JSR DATA |
Programmzeiger auf Statement |
perform DATA |
SCAN TO NEXT STATEMENT |
||
.,B3DE 4C 4F B4 JMP $B44F |
JMP DEFFIN ; ; SUBROUTINE TO GET A PNTR TO A FUNCTION NAME. ; |
FN-Variable vom Stapel holenprüft FN-Syntax |
put execute pointer and variable pointer into function and return check FNx syntax |
STORE ABOVE 5 BYTES IN "VALUE"COMMON ROUTINE FOR "DEFFN" AND "FN", TOPARSE "FN" AND THE FUNCTION NAME |
get function name |
|
.,B3E1 A9 A5 LDA #$A5 |
GETFNM: SYNCHK FNTK ;MUST START WITH FN. |
FN-Code |
set FN token |
MUST NOW SEE "FN" TOKEN |
||
.,B3E3 20 FF AE JSR $AEFF |
prüft auf FN-Code |
scan for CHR$(A), else do syntax error then warm start |
OR ELSE SYNTAX ERROR |
|||
.,B3E6 09 80 ORA #$80 |
ORAI 128 ;PUT FUNCTION BIT ON. |
Wert laden |
set FN flag bit |
SET SIGN BIT ON 1ST CHAR OF NAME, |
||
.,B3E8 85 10 STA $10 |
STA SUBFLG |
sperrt INTEGER-Variable |
save FN name |
MAKING $C0 < SUBFLG < $DB |
||
.,B3EA 20 92 B0 JSR $B092 |
JSR PTRGT2 ;GET POINTER TO FUNCTION OR CREATE ANEW. |
sucht Variable |
search for FN variable |
WHICH TELLS PTRGET WHO CALLED |
||
.,B3ED 85 4E STA $4E |
STWD DEFPNT |
LOW- und HIGH-Byte |
save function pointer low byte |
FOUND VALID FUNCTION NAME, SO |
||
.,B3EF 84 4F STY $4F |
FN-Variablenzeiger setzen |
save function pointer high byte |
SAVE ADDRESS |
|||
.,B3F1 4C 8D AD JMP $AD8D |
JMP CHKNUM ;MAKE SURE IT'S NOT A STRING AND RETURN. |
prüft auf numerischBASIC-Funktion FN |
check if source is numeric and return, else do type mismatch Evaluate FNx |
MUST BE NUMERIC"FN" FUNCTION CALL |
expand FN call |
|
.,B3F4 20 E1 B3 JSR $B3E1 |
FNDOER: JSR GETFNM ;GET THE FUNCTION'S NAME. |
prüft FN-Syntax |
check FNx syntax |
PARSE "FN", FUNCTION NAME |
||
.,B3F7 A5 4F LDA $4F |
PSHWD DEFPNT |
LOW- und HiGH-Byte des |
get function pointer high byte |
STACK FUNCTION ADDRESS |
||
.,B3F9 48 PHA |
FN-Variablenzeigers |
push it |
IN CASE OF A NESTED FN CALL |
|||
.,B3FA A5 4E LDA $4E |
auf den Stapel |
get function pointer low byte |
||||
.,B3FC 48 PHA |
legen |
push it |
||||
.,B3FD 20 F1 AE JSR $AEF1 |
JSR PARCHK ;EVALUATE PARAMETER. |
holt Term in Klammern |
evaluate expression within parentheses |
MUST NOW HAVE "(EXPRESSION)" |
||
.,B400 20 8D AD JSR $AD8D |
JSR CHKNUM |
prüft auf numerisch |
check if source is numeric, else do type mismatch |
MUST BE NUMERIC EXPRESSION |
||
.,B403 68 PLA |
PULWD DEFPNT |
LOW- und HIGH-Byte |
pop function pointer low byte |
GET FUNCTION ADDRESS BACK |
||
.,B404 85 4E STA $4E |
des |
restore it |
||||
.,B406 68 PLA |
FN-Variablenzeigers wieder- |
pop function pointer high byte |
||||
.,B407 85 4F STA $4F |
holen und speichern |
restore it |
||||
.,B409 A0 02 LDY #$02 |
LDYI 2 |
Zeiger setzen |
index to variable pointer high byte |
POINT AT ADD OF ARGUMENT VARIABLE |
||
.,B40B B1 4E LDA ($4E),Y |
LDADY DEFPNT ;GET POINTER TO VARIABLE. |
Zeiger (LOW) auf FN-Variable |
get variable address low byte |
|||
.,B40D 85 47 STA $47 |
STA VARPNT ;SAVE VARIABLE POINTER. |
in Variablenadresszeiger |
save current variable pointer low byte |
|||
.,B40F AA TAX |
TAX |
und ins X-Reg. |
copy address low byte |
|||
.,B410 C8 INY |
INY |
Zeiger erhöhen |
index to variable address high byte |
|||
.,B411 B1 4E LDA ($4E),Y |
LDADY DEFPNT |
Zeiger (HIGH) laden |
get variable pointer high byte |
|||
.,B413 F0 99 BEQ $B3AE |
BEQ ERRGUF |
gibt 'undef'd function' |
branch if high byte zero |
UNDEFINED FUNCTION |
||
.,B415 85 48 STA $48 |
STA VARPNT+1 |
in Variablenadresse |
save current variable pointer high byte |
|||
.,B417 C8 INY |
IFN ADDPRC,<INY> ;SINCE DEF USES ONLY 4. |
Zeiger erhöhen |
index to mantissa 3 now stack the function variable value before use |
Y=4 NOW |
||
.,B418 B1 47 LDA ($47),Y |
DEFSTF: LDADY VARPNT |
FN-Variablenwert holen |
get byte from variable |
SAVE OLD VALUE OF ARGUMENT VARIABLE |
||
.,B41A 48 PHA |
PHA ;PUSH IT ALL ON STACK. |
und auf Stapel retten |
stack it |
ON STACK, IN CASE ALSO USED AS |
||
.,B41B 88 DEY |
DEY ;SINCE WE ARE RECURSING MAYBE. |
Zeiger vermindern |
decrement index |
A NORMAL VARIABLE! |
||
.,B41C 10 FA BPL $B418 |
BPL DEFSTF |
fertig? nein: nächster Wert |
loop until variable stacked |
|||
.,B41E A4 48 LDY $48 |
LDY VARPNT+1 |
get current variable pointer high byte |
(Y,X)= ADDRESS, STORE FAC IN VARIABLE |
|||
.,B420 20 D4 BB JSR $BBD4 |
JSR MOVMF ;PUT CURRENT FAC INTO OUR ARG VARIABLE. |
FAC in FN-Variable übertragen |
pack FAC1 into (XY) |
|||
.,B423 A5 7B LDA $7B |
PSHWD TXTPTR ;SAVE TEXT POINTER. |
Programmzeiger (LOW) |
get BASIC execute pointer high byte |
REMEMBER TXTPTR AFTER FN CALL |
||
.,B425 48 PHA |
auf Stapel |
push it |
||||
.,B426 A5 7A LDA $7A |
Programmzeiger (HIGH) |
get BASIC execute pointer low byte |
||||
.,B428 48 PHA |
auf Stapel |
push it |
||||
.,B429 B1 4E LDA ($4E),Y |
LDADY DEFPNT ;PNTR TO FUNCTION. |
LOW und HIGH-Byte |
get function execute pointer low byte |
Y=0 FROM MOVMF |
||
.,B42B 85 7A STA $7A |
STA TXTPTR |
des |
save BASIC execute pointer low byte |
POINT TO FUNCTION DEF'N |
||
.,B42D C8 INY |
INY |
Programmzeigers auf |
index to high byte |
|||
.,B42E B1 4E LDA ($4E),Y |
LDADY DEFPNT |
FN-Ausdruck |
get function execute pointer high byte |
|||
.,B430 85 7B STA $7B |
STA TXTPTR+1 |
speichern |
save BASIC execute pointer high byte |
|||
.,B432 A5 48 LDA $48 |
PSHWD VARPNT ;SAVE VARIABLE POINTER. |
Zeiger auf FN-Variable |
get current variable pointer high byte |
SAVE ADDRESS OF ARGUMENT VARIABLE |
||
.,B434 48 PHA |
holen und |
push it |
||||
.,B435 A5 47 LDA $47 |
auf den Stapel |
get current variable pointer low byte |
||||
.,B437 48 PHA |
retten |
push it |
||||
.,B438 20 8A AD JSR $AD8A |
JSR FRMNUM ;EVALUATE FORMULA AND CHECK NUMERIC. |
numerischen Ausdruck holen |
evaluate expression and check is numeric, else do type mismatch |
EVALUATE THE FUNCTION EXPRESSION |
||
.,B43B 68 PLA |
PULWD DEFPNT |
LOW- und HIGH-Byte |
pull variable address low byte |
GET ADDRESS OF ARGUMENT VARIABLE |
||
.,B43C 85 4E STA $4E |
des Zeigers auf FN- |
save variable address low byte |
AND SAVE IT |
|||
.,B43E 68 PLA |
Variable vom Stapel holen |
pull variable address high byte |
||||
.,B43F 85 4F STA $4F |
und in FN-Zeiger speichern |
save variable address high byte |
||||
.,B441 20 79 00 JSR $0079 |
JSR CHRGOT |
CHRGOT letztes Zeichen holen |
scan memory |
MUST BE AT ":" OR EOL |
||
.,B444 F0 03 BEQ $B449 |
JNE SNERR ;IT DIDN'T TERMINATE. HUH? |
keine weiteren Zeichen? |
branch if null (should be [EOL] marker) |
WE ARE |
||
.,B446 4C 08 AF JMP $AF08 |
gibt 'SYNTAX ERROR' |
else syntax error then warm startrestore BASIC execute pointer and function variable from stack |
WE ARE NOT, SLYNTAX ERROR |
|||
.,B449 68 PLA |
PULWD TXTPTR ;RESTORE TEXT PNTR. |
LOW- und HIGH-Byte |
pull BASIC execute pointer low byte |
RETRIEVE TXTPTR AFTER "FN" CALL |
||
.,B44A 85 7A STA $7A |
des |
save BASIC execute pointer low byte |
||||
.,B44C 68 PLA |
Programmzeigers |
pull BASIC execute pointer high byte |
||||
.,B44D 85 7B STA $7B |
zurückholen |
save BASIC execute pointer high byte put execute pointer and variable pointer into function |
STACK NOW HAS 5-BYTE VALUE OF THE ARGUMENT VARIABLE, AND FNCNAM POINTS AT THE VARIABLE STORE FIVE BYTES FROM STACK AT (FNCNAM) |
|||
.,B44F A0 00 LDY #$00 |
DEFFIN: LDYI 0 |
Zeiger setzen |
clear index |
|||
.,B451 68 PLA |
PLA ;GET OLD ARG VALUE OFF STACK |
FN-Variable vom Stapel |
pull BASIC execute pointer low byte |
|||
.,B452 91 4E STA ($4E),Y |
STADY DEFPNT ;AND PUT IT BACK IN VARIABLE. |
zurückholen |
save to function |
|||
.,B454 68 PLA |
PLA |
und abspeichern |
pull BASIC execute pointer high byte |
|||
.,B455 C8 INY |
INY |
Zeiger erhöhen |
increment index |
|||
.,B456 91 4E STA ($4E),Y |
STADY DEFPNT |
2. Wert abspeichern |
save to function |
|||
.,B458 68 PLA |
PLA |
3. Wert vom Stapel holen |
pull current variable address low byte |
|||
.,B459 C8 INY |
INY |
Zeiger erhöhen |
increment index |
|||
.,B45A 91 4E STA ($4E),Y |
STADY DEFPNT |
und abspeichern |
save to function |
|||
.,B45C 68 PLA |
PLA |
4. Wert vom Stapel holen |
pull current variable address high byte |
|||
.,B45D C8 INY |
INY |
Zeiger erhöhen |
increment index |
|||
.,B45E 91 4E STA ($4E),Y |
STADY DEFPNT IFN ADDPRC,< |
und abspeichern |
save to function |
|||
.,B460 68 PLA |
PLA |
5. Wert vom Stapel holen |
pull ?? |
|||
.,B461 C8 INY |
INY |
Zeiger erhöhen |
increment index |
|||
.,B462 91 4E STA ($4E),Y |
STADY DEFPNT> |
und abspeichern |
save to function |
|||
.,B464 60 RTS |
DEFRTS: RTS PAGE STRING FUNCTIONS.;; THE STR$ FUNCTION TAKES A NUMBER AND GIVES A STRING ; WITH THE CHARACTERS THE OUTPUT OF THE NUMBER ; WOULD HAVE GIVEN. ; |
RücksprungBASIC-Funktion STR$ |
perform STR$() |
"STR$" FUNCTION |
STR$ function |
|
.,B465 20 8D AD JSR $AD8D |
STR: JSR CHKNUM ;ARG HAS TO BE NUMERIC. |
prüft auf numerisch |
check if source is numeric, else do type mismatch |
EXPRESSION MUST BE NUMERIC |
||
.,B468 A0 00 LDY #$00 |
LDYI 0 |
Wert laden und |
set string index |
START STRING AT STACK-1 ($00FF) SO STRLIT CAN DIFFRENTIATE STR$ CALLS |
||
.,B46A 20 DF BD JSR $BDDF |
JSR FOUTC ;DO ITS OUTPUT. |
FAC nach ASCII umwandeln |
convert FAC1 to string |
CONVERT FAC TO STRING |
||
.,B46D 68 PLA |
PLA |
Rücksprungadresse vom |
dump return address (skip type check) |
POP RETURN OFF STACK |
||
.,B46E 68 PLA |
PLA |
Stapel entfernen |
dump return address (skip type check) |
|||
.,B46F A9 FF LDA #$FF |
TIMSTR: LDWDI LOFBUF |
LOW-Byte |
set result string low pointer |
POINT TO STACK-1 |
||
.,B471 A0 00 LDY #$00 |
Startadresse des Strings=$FF |
set result string high pointer |
(WHICH=0) |
|||
.,B473 F0 12 BEQ $B487 |
BEQA STRLIT ;SCAN IT AND TURN IT INTO A STRING. ; ; "STRINI" GET STRING SPACE FOR THE CREATION OF A STRING AND ; CREATES A DESCRIPTOR FOR IT IN "DSCTMP". ; |
Stringzeiger berechnen |
print null terminated string to utility pointerdo string vectorcopy descriptor pointer and make string space A bytes long |
...ALWAYS, CREATE DESC & MOVE STRING GET SPACE AND MAKE DESCRIPTOR FOR STRING WHOSE ADDRESS IS IN FAC+3,4 AND WHOSE LENGTH IS IN A-REG |
||
.,B475 A6 64 LDX $64 |
STRINI: LDXY FACMO ;GET FACMO TO STORE IN DSCPNT. |
Zeiger in |
get descriptor pointer low byte |
Y,X = STRING ADDRESS |
||
.,B477 A4 65 LDY $65 |
$64/65 in |
get descriptor pointer high byte |
||||
.,B479 86 50 STX $50 |
STXY DSCPNT ;RETAIN THE DESCRIPTOR POINTER. |
Zeiger auf Stringdescriptor |
save descriptor pointer low byte |
|||
.,B47B 84 51 STY $51 |
speichern |
save descriptor pointer high bytemake string space A bytes long |
GET SPACE AND MAKE DESCRIPTOR FOR STRING WHOSE ADDRESS IS IN Y,X AND WHOSE LENGTH IS IN A-REG |
allocate area according to A |
||
.,B47D 20 F4 B4 JSR $B4F4 |
STRSPA: JSR GETSPA ;GET STRING SPACE. |
Platz für String, Länge in A |
make space in string memory for string A long |
A HOLDS LENGTH |
||
.,B480 86 62 STX $62 |
STXY DSCTMP+1 ;SAVE LOCATION. |
Adresse LOW |
save string pointer low byte |
SAVE DESCRIPTOR IN FAC |
||
.,B482 84 63 STY $63 |
Adresse HIGH |
save string pointer high byte |
---FAC--- --FAC+1-- --FAC+2-- |
|||
.,B484 85 61 STA $61 |
STA DSCTMP ;SAVE LENGTH. |
Länge |
save length |
<LENGTH> <ADDR-LO> <ADDR-HI> |
||
.,B486 60 RTS |
RTS ;ALL DONE. ; ; "STRLT2" TAKES THE STRING LITERAL WHOSE FIRST CHARACTER ; IS POINTED TO BY [Y,A] AND BUILDS A DESCRIPTOR FOR IT. ; THE DESCRIPTOR IS INITIALLY BUILT IN "DSCTMP", BUT "PUTNEW" ; TRANSFERS IT INTO A TEMPORARY AND LEAVES A POINTER ; AT THE TEMPORARY IN FACMO&LO. THE CHARACTERS OTHER THAN ; ZERO THAT TERMINATE THE STRING SHOULD BE SET UP IN "CHARAC" ; AND "ENDCHR". IF THE TERMINATOR IS A QUOTE, THE QUOTE IS SKIPPED ; OVER. LEADING QUOTES SHOULD BE SKIPPED BEFORE JSR. ON RETURN ; THE CHARACTER AFTER THE STRING LITERAL IS POINTED TO ; BY [STRNG2]. ; |
String holen, Zeiger in A/Y |
scan, set up stringprint " terminated string to utility pointer |
BUILD A DESCRIPTOR FOR STRING STARTING AT Y,A AND TERMINATED BY $00 OR QUOTATION MARK RETURN WITH DESCRIPTOR IN A TEMPORARY AND ADDRESS OF DESCRIPTOR IN FAC+3,4 |
get description of string into float accu |
|
.,B487 A2 22 LDX #$22 |
STRLIT: LDXI 34 ;ASSUME STRING ENDS ON QUOTE. |
'"'-Code |
set terminator to " |
SET UP LITERAL SCAN TO STOP ON |
quote mark |
|
.,B489 86 07 STX $07 |
STX CHARAC |
nach Suchzeichen |
set search character, terminator 1 |
QUOTATION MARK OR $00 |
||
.,B48B 86 08 STX $08 |
STX ENDCHR |
und Hochkommaflag |
set terminator 2 print search or alternate terminated string to utility pointer source is AY |
BUILD A DESCRIPTOR FOR STRING STARTING AT Y,A AND TERMINATED BY $00, (CHARAC), OR (ENDCHR) RETURN WITH DESCRIPTOR IN A TEMPORARY AND ADDRESS OF DESCRIPTOR IN FAC+3,4 |
||
.,B48D 85 6F STA $6F |
STRLT2: STWD STRNG1 ;SAVE POINTER TO STRING. |
Startadresse des Strings |
store string start low byte |
SAVE ADDRESS OF STRING |
||
.,B48F 84 70 STY $70 |
nach $6F/70 |
store string start high byte |
||||
.,B491 85 62 STA $62 |
STWD DSCTMP+1 ;IN CASE NO STRCPY. |
und $62/63 |
save string pointer low byte |
...AGAIN |
||
.,B493 84 63 STY $63 |
speichern |
save string pointer high byte |
||||
.,B495 A0 FF LDY #$FF |
LDYI 255 ;INITIALIZE CHARACTER COUNT. |
Zeiger setzen |
set length to -1 |
|||
.,B497 C8 INY |
STRGET: INY |
Zeiger erhöhen |
increment length |
FIND END OF STRING |
||
.,B498 B1 6F LDA ($6F),Y |
LDADY STRNG1 ;GET CHARACTER. |
nächstes Zeichen des Strings |
get byte from string |
NEXT STRING CHAR |
||
.,B49A F0 0C BEQ $B4A8 |
BEQ STRFI1 ;IF ZERO. |
Endekennzeichen? |
exit loop if null byte [EOS] |
END OF STRING |
||
.,B49C C5 07 CMP $07 |
CMP CHARAC ;THIS TERMINATOR? |
Suchzeichen? |
compare with search character, terminator 1 |
ALTERNATE TERMINATOR # 1? |
||
.,B49E F0 04 BEQ $B4A4 |
BEQ STRFIN ;YES. |
ja: $B4A4 |
branch if terminator |
YES |
||
.,B4A0 C5 08 CMP $08 |
CMP ENDCHR |
= Zeichen in Hochkommaflag |
compare with terminator 2 |
ALTERNATE TERMINATOR # 2? |
||
.,B4A2 D0 F3 BNE $B497 |
BNE STRGET ;LOOK FURTHER. |
nein: $B497 |
loop if not terminator 2 |
NO, KEEP SCANNING |
||
.,B4A4 C9 22 CMP #$22 |
STRFIN: CMPI 34 ;QUOTE? |
'"'-Code? |
compare with " |
IS STRING ENDED WITH QUOTE MARK? |
quote mark |
|
.,B4A6 F0 01 BEQ $B4A9 |
BEQ STRFI2 |
ja: $B4A9 |
branch if " (carry set if = !) |
YES, C=1 TO INCLUDE " IN STRING |
||
.,B4A8 18 CLC |
STRFI1: CLC ;NO, BACK UP. |
Carry löschen (Addition) |
clear carry for add (only if [EOL] terminated string) |
|||
.,B4A9 84 61 STY $61 |
STRFI2: STY DSCTMP ;RETAIN COUNT. |
Länge des Str. speichern und |
save length in FAC1 exponent |
SAVE LENGTH |
||
.,B4AB 98 TYA |
TYA |
in Akku holen |
copy length to A |
|||
.,B4AC 65 6F ADC $6F |
ADC STRNG1 ;WISHING TO SET [TXTPTR]. |
und zur Startadresse addieren |
add string start low byte |
COMPUTE ADDRESS OF END OF STRING |
||
.,B4AE 85 71 STA $71 |
STA STRNG2 |
ergibt Endadresse LOW + 1 |
save string end low byte |
(OF 00 BYTE, OR JUST AFTER ") |
||
.,B4B0 A6 70 LDX $70 |
LDX STRNG1+1 |
Übertrag |
get string start high byte |
|||
.,B4B2 90 01 BCC $B4B5 |
BCC STRST2 |
Addition umgehen |
branch if no low byte overflow |
|||
.,B4B4 E8 INX |
INX |
Übertrag addieren |
else increment high byte |
|||
.,B4B5 86 72 STX $72 |
STRST2: STX STRNG2+1 |
Endadresse HIGH + 1 |
save string end high byte |
|||
.,B4B7 A5 70 LDA $70 |
LDA STRNG1+1 ;IF PAGE 0, COPY SINCE IT IS EITHER ;A STRING CONSTANT IN BUF OR A STR$ ;RESULT IN LOFBUF IFN BUFPAG,< |
Startadresse HIGH |
get string start high byte |
WHERE DOES THE STRING START? |
||
.,B4B9 F0 04 BEQ $B4BF |
BEQ STRCP |
null? |
branch if in utility area |
PAGE 0, MUST BE FROM STR$ FUNCTION |
||
.,B4BB C9 02 CMP #$02 |
CMPI BUFPAG> |
zwei? |
compare with input buffer memory high byte |
PAGE 2? |
||
.,B4BD D0 0B BNE $B4CA |
BNE PUTNEW |
nein: $B4CA |
branch if not in input buffer memory string in input buffer or utility area, move to string memory |
NO, NOT PAGE 0 OR 2 |
||
.,B4BF 98 TYA |
STRCP: TYA |
Länge in Akku |
copy length to A |
LENGTH OF STRING |
||
.,B4C0 20 75 B4 JSR $B475 |
JSR STRINI |
Stringzeiger berechnen |
copy descriptor pointer and make string space A bytes long |
MAKE SPACE FOR STRING |
||
.,B4C3 A6 6F LDX $6F |
LDXY STRNG1 |
LOW- und HIGH-Byte der |
get string start low byte |
|||
.,B4C5 A4 70 LDY $70 |
Startadresse holen |
get string start high byte |
||||
.,B4C7 20 88 B6 JSR $B688 |
JSR MOVSTR ;MOVE STRING. ; ; SOME STRING FUNCTION IS RETURNING A RESULT IN DSCTMP. ; SETUP A TEMP DESCRIPTOR WITH DSCTMP IN IT. ; PUT A POINTER TO THE DESCRIPTOR IN FACMO&LO AND FLAG THE ; RESULT AS TYPE STRING. ; |
String in Bereich kopierenStringzeiger inDescriptorstapel bringen |
store string A bytes long from XY to utility pointer check for space on descriptor stack then ... put string address and length on descriptor stack and update stack pointers |
MOVE IT IN STORE DESCRIPTOR IN TEMPORARY DESCRIPTOR STACK THE DESCRIPTOR IS NOW IN FAC, FAC+1, FAC+2 PUT ADDRESS OF TEMP DESCRIPTOR IN FAC+3,4 |
save descriptor from $61-$63 on stack |
|
.,B4CA A6 16 LDX $16 |
PUTNEW: LDX TEMPPT ;POINTER TO FIRST FREE TEMP. |
Stringdescriptor-Zeiger |
get the descriptor stack pointer |
POINTER TO NEXT TEMP STRING SLOT |
||
.,B4CC E0 22 CPX #$22 |
CPXI TEMPST+STRSIZ*NUMTMP |
Stringstapel voll? |
compare it with the maximum + 1 |
MAX OF 3 TEMP STRINGS |
||
.,B4CE D0 05 BNE $B4D5 |
BNE PUTNW1 |
nein: $B4D5 |
if there is space on the string stack continue else do string too complex error |
ROOM FOR ANOTHER ONE |
||
.,B4D0 A2 19 LDX #$19 |
LDXI ERRST ;STRING TEMPORARY ERROR. |
Nr für 'formula too complex' |
error $19, string too complex error |
TOO MANY, FORMULA TOO COMPLEX |
||
.,B4D2 4C 37 A4 JMP $A437 |
ERRGO2: JMP ERROR ;GO TELL HIM. |
Fehlermeldung ausgeben |
do error #X then warm start put string address and length on descriptor stack and update stack pointers |
|||
.,B4D5 A5 61 LDA $61 |
PUTNW1: LDA DSCTMP |
Stringlänge holen und |
get the string length |
COPY TEMP DESCRIPTOR INTO TEMP STACK |
||
.,B4D7 95 00 STA $00,X |
STA 0,X |
Stringstapel speichern |
put it on the string stack |
|||
.,B4D9 A5 62 LDA $62 |
LDA DSCTMP+1 |
LOW- und HIGH-Byte der |
get the string pointer low byte |
|||
.,B4DB 95 01 STA $01,X |
STA 1,X |
Adresse holen |
put it on the string stack |
|||
.,B4DD A5 63 LDA $63 |
LDA DSCTMP+2 |
und in |
get the string pointer high byte |
|||
.,B4DF 95 02 STA $02,X |
STA 2,X |
Stringstapel bringen |
put it on the string stack |
|||
.,B4E1 A0 00 LDY #$00 |
LDYI 0 |
Nullwert laden |
clear Y |
|||
.,B4E3 86 64 STX $64 |
STXY FACMO |
und Zeiger |
save the string descriptor pointer low byte |
ADDRESS OF TEMP DESCRIPTOR |
||
.,B4E5 84 65 STY $65 |
jetzt auf Descriptor setzen |
save the string descriptor pointer high byte, always $00 |
IN Y,X AND FAC+3,4 |
|||
.,B4E7 84 70 STY $70 |
STY FACOV |
Zeiger für Polynomauswertung |
clear FAC1 rounding byte |
|||
.,B4E9 88 DEY |
DEY |
Register vermindern |
Y = $FF |
Y=$FF |
||
.,B4EA 84 0D STY $0D |
STY VALTYP ;TYPE IS "STRING". |
Stringflag setzen $FF |
save the data type flag, $FF = string |
FLAG (FAC ) AS STRING |
||
.,B4EC 86 17 STX $17 |
STX LASTPT ;SET POINTER TO LAST-USED TEMP. |
Index des letzten |
save the current descriptor stack item pointer low byte |
INDEX OF LAST POINTER |
||
.,B4EE E8 INX |
INX |
Stringdescriptors |
update the stack pointer |
UPDATE FOR NEXT TEMP ENTRY |
||
.,B4EF E8 INX |
INX |
um drei erhöhen |
update the stack pointer |
|||
.,B4F0 E8 INX |
INX ;POINT FURTHER. |
und als |
update the stack pointer |
|||
.,B4F1 86 16 STX $16 |
STX TEMPPT ;SAVE POINTER TO NEXT TEMP IF ANY. |
neuen Index merken |
save the new descriptor stack pointer |
|||
.,B4F3 60 RTS |
RTS ;ALL DONE. ; ; GETSPA - GET SPACE FOR CHARACTER STRING. ; MAY FORCE GARBAGE COLLECTION. ; ; # OF CHARACTERS (BYTES) IN ACCA. ; RETURNS WITH POINTER IN [Y,X]. OTHERWISE (IF CAN'T GET ; SPACE) BLOWS OFF TO "OUT OF STRING SPACE" TYPE ERROR. ; ALSO PRESERVES [ACCA] AND SETS [FRESPC]=[Y,X]=PNTR AT SPACE. ; |
RücksprungPlatz für String reservieren,Länge in A |
make space in string memory for string A longreturn X = pointer low byte, Y = pointer high byte |
MAKE SPACE FOR STRING AT BOTTOM OF STRING SPACE (A)=# BYTES SPACE TO MAKE RETURN WITH (A) SAME, AND Y,X = ADDRESS OF SPACE ALLOCATED |
allocate number of bytes in A |
|
.,B4F4 46 0F LSR $0F |
GETSPA: LSR GARBFL ;SIGNAL NO GARBAGE COLLECTION YET. |
Flag für Garbage Collection zurücksetzen |
clear garbage collected flag (b7) make space for string A long |
CLEAR SIGNBIT OF FLAG |
||
.,B4F6 48 PHA |
TRYAG2: PHA ;SAVE FOR LATER. |
Stringlänge |
save string length |
A HOLDS LENGTH |
||
.,B4F7 49 FF EOR #$FF |
EORI 255 |
Alle Bits umdrehen |
complement it |
GET -LENGTH |
||
.,B4F9 38 SEC |
SEC ;ADD ONE TO COMPLETE NEGATION. |
mit HIGH-Byte des |
set carry for subtract, two's complement add |
|||
.,B4FA 65 33 ADC $33 |
ADC FRETOP |
Stringanfangs-Zeigers addieren |
add bottom of string space low byte, subtract length |
COMPUTE STARTING ADDRESS OF SPACE |
||
.,B4FC A4 34 LDY $34 |
LDY FRETOP+1 |
LOW-Byte ins Y-Reg. |
get bottom of string space high byte |
FOR THE STRING |
||
.,B4FE B0 01 BCS $B501 |
BCS TRYAG3 |
Carry gesetzt ? dann weiter |
skip decrement if no underflow |
|||
.,B500 88 DEY |
DEY |
ansonsten LOW-Byte erniedrigen |
decrement bottom of string space high byte |
|||
.,B501 C4 32 CPY $32 |
TRYAG3: CPY STREND+1 ;COMPARE HIGH ORDERS. |
Zu wenig Platz, dann |
compare with end of arrays high byte |
SEE IF FITS IN REMAINING MEMORY |
||
.,B503 90 11 BCC $B516 |
BCC GARBAG ;MAKE ROOM FOR MORE. |
Garbage Collection durchführen |
do out of memory error if less |
NO, TRY GARBAGE |
||
.,B505 D0 04 BNE $B50B |
BNE STRFRE ;SAVE NEW FRETOP. |
alles ok ? |
if not = skip next test |
YES, IT FITS |
||
.,B507 C5 31 CMP $31 |
CMP STREND ;COMPARE LOW ORDERS. |
Ende der Arrays, dann |
compare with end of arrays low byte |
HAVE TO CHECK LOWER BYTES |
||
.,B509 90 0B BCC $B516 |
BCC GARBAG ;CLEAN UP. |
Garbage Collect durchführen |
do out of memory error if less |
NOT ENUF ROOM YET |
||
.,B50B 85 33 STA $33 |
STRFRE: STWD FRETOP ;SAVE NEW [FRETOP]. |
ansonsten |
save bottom of string space low byte |
THERE IS ROOM SO SAVE NEW FRETOP |
||
.,B50D 84 34 STY $34 |
alle |
save bottom of string space high byte |
||||
.,B50F 85 35 STA $35 |
STWD FRESPC ;PUT IT THERE OLD MAN. |
Zeiger |
save string utility ptr low byte |
|||
.,B511 84 36 STY $36 |
neu |
save string utility ptr high byte |
||||
.,B513 AA TAX |
TAX ;PRESERVE A IN X. |
setzen |
copy low byte to X |
ADDR IN Y,X |
||
.,B514 68 PLA |
PLA ;GET COUNT BACK IN ACCA. |
Stringlänge zurückholen |
get string length back |
LENGTH IN A |
||
.,B515 60 RTS |
RTS ;ALL DONE. |
Rücksprung |
||||
.,B516 A2 10 LDX #$10 |
GARBAG: LDXI ERROM ;"OUT OF STRING SPACE" |
Nummer für 'OUT OF MEMORY' |
error code $10, out of memory error |
|||
.,B518 A5 0F LDA $0F |
LDA GARBFL |
Flag für Garbage Collection |
get garbage collected flag |
GARBAGE DONE YET? |
||
.,B51A 30 B6 BMI $B4D2 |
BMI ERRGO2 |
durchgeführt? 'OUT OF MEMORY' |
if set then do error code X |
YES, MEMORY IS REALLY FULL |
||
.,B51C 20 26 B5 JSR $B526 |
JSR GARBA2 |
Garbage Collection |
else go do garbage collection |
NO, TRY COLLECTING NOW |
||
.,B51F A9 80 LDA #$80 |
LDAI 128 |
Flag setzen |
flag for garbage collected |
FLAG THAT COLLECTED GARBAGE ALREADY |
||
.,B521 85 0F STA $0F |
STA GARBFL |
und speichern |
set garbage collected flag |
|||
.,B523 68 PLA |
PLA ;GET BACK STRING LENGTH. |
Stringlänge |
pull length |
GET STRING LENGTH AGAIN |
||
.,B524 D0 D0 BNE $B4F6 |
BNE TRYAG2 ;ALWAYS BRANCHES. GARBA2: ;START FROM TOP DOWN. IFE REALIO!DISKO,< LDAI 7 ;TYPE "BELL". JSR OUTDO> |
String nochmals einbauenGarbage Collection |
go try again (loop always, length should never be = $00)garbage collection routine |
...ALWAYS SHOVE ALL REFERENCED STRINGS AS HIGH AS POSSIBLE IN MEMORY (AGAINST HIMEM) FREEING UP SPACE BELOW STRING AREA DOWN TO STREND. |
string garbage clean up |
|
.,B526 A6 37 LDX $37 |
LDX MEMSIZ |
LOW-Byte Basic-RAM-Zeiger |
get end of memory low byte |
COLLECT FROM TOP DOWN |
||
.,B528 A5 38 LDA $38 |
LDA MEMSIZ+1 |
HIGH-Byte Basic-RAM-Zeiger |
get end of memory high byte re-run routine from last ending |
|||
.,B52A 86 33 STX $33 |
FNDVAR: STX FRETOP ;LIKE SO. |
in Stringzeiger |
set bottom of string space low byte |
ONE PASS THROUGH ALL VARS |
||
.,B52C 85 34 STA $34 |
STA FRETOP+1 |
speichern |
set bottom of string space high byte |
FOR EACH ACTIVE STRING! |
||
.,B52E A0 00 LDY #$00 |
LDYI 0 |
LOW- und HIGH-Byte |
clear index |
|||
.,B530 84 4F STY $4F |
STY GRBPNT+1 |
der FN Zeiger |
clear working pointer high byte |
FLAG IN CASE NO STRINGS TO COLLECT |
||
.,B532 84 4E STY $4E |
STY GRBPNT ;BOTH BYTES SET TO ZERO (FIX BUG) |
auf Null setzen |
clear working pointer low byte |
|||
.,B534 A5 31 LDA $31 |
LDWX STREND |
LOW- und HIGH-Byte der |
get end of arrays low byte |
|||
.,B536 A6 32 LDX $32 |
Array-Zeiger laden |
get end of arrays high byte |
||||
.,B538 85 5F STA $5F |
STWX GRBTOP |
und in die Arithmetikregister |
save as highest uncollected string pointer low byte |
|||
.,B53A 86 60 STX $60 |
speichern |
save as highest uncollected string pointer high byte |
START BY COLLECTING TEMPORARIES |
|||
.,B53C A9 19 LDA #$19 |
LDWXI TEMPST |
Startadresse |
set descriptor stack pointer |
low 0019 |
||
.,B53E A2 00 LDX #$00 |
der Descriptorentabelle |
clear X |
high 0019 |
|||
.,B540 85 22 STA $22 |
STWX INDEX1 |
als Suchzeiger nach |
save descriptor stack pointer low byte |
|||
.,B542 86 23 STX $23 |
$22 und $23 bringen |
save descriptor stack pointer high byte ($00) |
||||
.,B544 C5 16 CMP $16 |
TVAR: CMP TEMPPT ;DONE WITH TEMPS? |
identisch mit String-Zeiger? |
compare with descriptor stack pointer |
FINISHED WITH TEMPS YET? |
||
.,B546 F0 05 BEQ $B54D |
BEQ SVARS ;YEP. |
wenn ja, dann weiter |
branch if = |
YES, NOW DO SIMPLE VARIABLES |
||
.,B548 20 C7 B5 JSR $B5C7 |
JSR DVAR |
Stringposition feststellen |
check string salvageability |
DO A TEMP |
||
.,B54B F0 F7 BEQ $B544 |
BEQ TVAR ;LOOP. |
unbedingter Sprung |
loop always done stacked strings, now do string variables |
...ALWAYS NOW COLLECT SIMPLE VARIABLES |
||
.,B54D A9 07 LDA #$07 |
SVARS: LDAI 6+ADDPRC |
Schrittweite für die Suche |
set step size = $07, collecting variables |
LENGTH OF EACH VARIABLE IS 7 BYTES |
||
.,B54F 85 53 STA $53 |
STA FOUR6 |
in Variablentabelle |
save garbage collection step size |
|||
.,B551 A5 2D LDA $2D |
LDWX VARTAB ;GET START OF SIMPLE VARIABLES. |
Tabellenzeiger |
get start of variables low byte |
START AT BEGINNING OF VARTAB |
||
.,B553 A6 2E LDX $2E |
laden |
get start of variables high byte |
||||
.,B555 85 22 STA $22 |
STWX INDEX1 |
und als Suchzeiger nach |
save as pointer low byte |
|||
.,B557 86 23 STX $23 |
$22 und $23 bringen |
save as pointer high byte |
||||
.,B559 E4 30 CPX $30 |
SVAR: CPX ARYTAB+1 ;DONE WITH SIMPLE VARIABLES? |
Am Ende der Tabelle angelangt |
compare end of variables high byte, start of arrays high byte |
FINISHED WITH SIMPLE VARIABLES? |
||
.,B55B D0 04 BNE $B561 |
BNE SVARGO ;NO. |
wenn nicht, dann zu $B561 |
branch if no high byte match |
NO |
||
.,B55D C5 2F CMP $2F |
CMP ARYTAB |
ansonsten Sprung zur |
else compare end of variables low byte, start of arrays low byte |
MAYBE, CHECK LO-BYTE |
||
.,B55F F0 05 BEQ $B566 |
BEQ ARYVAR ;YEP. |
Array-Behandlung |
branch if = variable memory end |
YES, NOW DO ARRAYS |
||
.,B561 20 BD B5 JSR $B5BD |
SVARGO: JSR DVARS ;DO IT , AGAIN. |
Stringposition feststellen |
check variable salvageability |
|||
.,B564 F0 F3 BEQ $B559 |
BEQ SVAR ;LOOP. |
unbedingter Sprung |
loop always done string variables, now do string arrays |
...ALWAYS NOW COLLECT ARRAY VARIABLES |
||
.,B566 85 58 STA $58 |
ARYVAR: STWX ARYPNT ;SAVE FOR ADDITION. |
Zeiger in die |
save start of arrays low byte as working pointer |
|||
.,B568 86 59 STX $59 |
Array-Tabelle speichern |
save start of arrays high byte as working pointer |
||||
.,B56A A9 03 LDA #$03 |
LDAI STRSIZ |
Schrittweite für Suche |
set step size, collecting descriptors |
DESCRIPTORS IN ARRAYS ARE 3-BYTES EACH |
||
.,B56C 85 53 STA $53 |
STA FOUR6 |
innerhalb des Arrays festlegen |
save step size |
|||
.,B56E A5 58 LDA $58 |
ARYVA2: LDWX ARYPNT ;GET THE POINTER TO VARIABLE. |
Am Ende |
get pointer low byte |
COMPARE TO END OF ARRAYS |
||
.,B570 A6 59 LDX $59 |
der |
get pointer high byte |
||||
.,B572 E4 32 CPX $32 |
ARYVA3: CPX STREND+1 ;DONE WITH ARRAYS? |
Arraytabelle angelangt, dann |
compare with end of arrays high byte |
FINISHED WITH ARRAYS YET? |
||
.,B574 D0 07 BNE $B57D |
BNE ARYVGO ;NO. |
Sprung zu $B57D |
branch if not at end |
NOT YET |
||
.,B576 C5 31 CMP $31 |
CMP STREND |
Vergleich mit HIGH-Byte |
else compare with end of arrays low byte |
MAYBE, CHECK LO-BYTE |
||
.,B578 D0 03 BNE $B57D |
JEQ GRBPAS ;YES, GO FINISH UP. |
Sprung zu $B57D |
branch if not at end |
NOT FINISHED YET |
||
.,B57A 4C 06 B6 JMP $B606 |
ansonsten Transfer |
collect string, tidy up and exit if at end ?? |
FINISHED |
|||
.,B57D 85 22 STA $22 |
ARYVGO: STWX INDEX1 |
Zeiger auf Array-Header |
save pointer low byte |
SET UP PNTR TO START OF ARRAY |
||
.,B57F 86 23 STX $23 |
stellen |
save pointer high byte |
||||
.,B581 A0 00 LDY #$00 |
LDYI 1-ADDPRC IFN ADDPRC,< |
Zähler auf Null setzen |
set index |
POINT AT NAME OF ARRAY |
||
.,B583 B1 22 LDA ($22),Y |
LDADY INDEX1 |
Variablenname erstes Zeichen |
get array name first byte |
|||
.,B585 AA TAX |
TAX |
ins X-Reg übertragen |
copy it |
1ST LETTER OF NAME IN X-REG |
||
.,B586 C8 INY |
INY> |
Zähler erhöhen |
increment index |
|||
.,B587 B1 22 LDA ($22),Y |
LDADY INDEX1 |
Variablenname zweites Zeichen |
get array name second byte |
|||
.,B589 08 PHP |
PHP |
Statusregister retten |
push the flags |
STATUS FROM SECOND LETTER OF NAME |
||
.,B58A C8 INY |
INY |
Zähler erhöhen |
increment index |
|||
.,B58B B1 22 LDA ($22),Y |
LDADY INDEX1 |
Die Länge |
get array size low byte |
OFFSET TO NEXT ARRAY |
||
.,B58D 65 58 ADC $58 |
ADC ARYPNT |
des Arrays |
add start of this array low byte |
(CARRY ALWAYS CLEAR) |
||
.,B58F 85 58 STA $58 |
STA ARYPNT ;FORM POINTER TO NEXT ARRAY VAR. |
zu |
save start of next array low byte |
CALCULATE START OF NEXT ARRAY |
||
.,B591 C8 INY |
INY |
Zeiger |
increment index |
|||
.,B592 B1 22 LDA ($22),Y |
LDADY INDEX1 |
auf |
get array size high byte |
HI-BYTE OF OFFSET |
||
.,B594 65 59 ADC $59 |
ADC ARYPNT+1 |
Arraytabelle |
add start of this array high byte |
|||
.,B596 85 59 STA $59 |
STA ARYPNT+1 |
addieren |
save start of next array high byte |
|||
.,B598 28 PLP |
PLP |
Statusregister wiederholen |
restore the flags |
GET STATUS FROM 2ND CHAR OF NAME |
||
.,B599 10 D3 BPL $B56E |
BPL ARYVA2 IFN ADDPRC,< |
keine Stringvariable ? |
skip if not string array was possibly string array so ... |
NOT A STRING ARRAY |
||
.,B59B 8A TXA |
TXA |
dann weitersuchen |
get name first byte back |
SET STATUS WITH 1ST CHAR OF NAME |
||
.,B59C 30 D0 BMI $B56E |
BMI ARYVA2> |
Stringvariable, nein, weiter |
skip if not string array |
NOT A STRING ARRAY |
||
.,B59E C8 INY |
INY |
Zähler erhöhen |
increment index |
|||
.,B59F B1 22 LDA ($22),Y |
LDADY INDEX1 |
Dimensionenanzahl holen |
get # of dimensions |
# OF DIMENSIONS FOR THIS ARRAY |
||
.,B5A1 A0 00 LDY #$00 |
LDYI 0 ;RESET INDEX Y. |
Zähler wieder Null |
clear index |
|||
.,B5A3 0A ASL |
ASL A, |
mal 2 |
*2 |
PREAMBLE SIZE = 2*#DIMS + 5 |
||
.,B5A4 69 05 ADC #$05 |
ADCI 5 ;CARRY IS OFF AND OFF AFTER ADD. |
plus 5 |
+5 (array header size) |
|||
.,B5A6 65 22 ADC $22 |
ADC INDEX1 |
zum Zeiger addieren |
add pointer low byte |
MAKE INDEX POINT AT FIRST ELEMENT |
||
.,B5A8 85 22 STA $22 |
STA INDEX1 |
und speichern |
save pointer low byte |
IN THE ARRAY |
||
.,B5AA 90 02 BCC $B5AE |
BCC ARYGET |
wenn ungleich, dann zu $B5AE |
branch if no rollover |
|||
.,B5AC E6 23 INC $23 |
INC INDEX1+1 |
Zeiger erhöhen |
else increment pointer hgih byte |
|||
.,B5AE A6 23 LDX $23 |
ARYGET: LDX INDEX1+1 |
und in Array schieben |
get pointer high byte |
STEP THRU EACH STRING IN THIS ARRAY |
||
.,B5B0 E4 59 CPX $59 |
ARYSTR: CPX ARYPNT+1 ;END OF THE ARRAY? |
auf nächstes Feld vergleichen |
compare pointer high byte with end of this array high byte |
ARRAY DONE? |
||
.,B5B2 D0 04 BNE $B5B8 |
BNE GOGO |
wenn ungleich, dann zu $B5B8 |
branch if not there yet |
NO, PROCESS NEXT ELEMENT |
||
.,B5B4 C5 58 CMP $58 |
CMP ARYPNT |
wenn gleich, dann |
compare pointer low byte with end of this array low byte |
MAYBE, CHECK LO-BYTE |
||
.,B5B6 F0 BA BEQ $B572 |
BEQ ARYVA3 ;YES. |
zu $B572 |
if at end of this array go check next array |
YES, MOVE TO NEXT ARRAY |
||
.,B5B8 20 C7 B5 JSR $B5C7 |
GOGO: JSR DVAR |
Stringposition feststellen |
check string salvageability |
PROCESS THE ARRAY |
||
.,B5BB F0 F3 BEQ $B5B0 |
BEQ ARYSTR ;CYCLE. DVARS: IFN INTPRC,< |
unbedingter Sprungprüft Beseitigungsmöglichkeit |
loop check variable salvageability |
...ALWAYS PROCESS A SIMPLE VARIABLE |
check string area |
|
.,B5BD B1 22 LDA ($22),Y |
LDADY INDEX1 |
Variablenname erstes Zeichen |
get variable name first byte |
LOOK AT 1ST CHAR OF NAME |
||
.,B5BF 30 35 BMI $B5F6 |
BMI DVARTS> |
Integer o. Funktion ? |
add step and exit if not string |
NOT A STRING VARIABLE |
||
.,B5C1 C8 INY |
INY |
Zähler erhöhen |
increment index |
|||
.,B5C2 B1 22 LDA ($22),Y |
LDADY INDEX1 |
Variablenname zweites Zeichen |
get variable name second byte |
LOOK AT 2ND CHAR OF NAME |
||
.,B5C4 10 30 BPL $B5F6 |
BPL DVARTS |
wenn Real, dann $B5F6 |
add step and exit if not string |
NOT A STRING VARIABLE |
||
.,B5C6 C8 INY |
INY |
Zähler erhöhen |
increment index check string salvageability |
IF STRING IS NOT EMPTY, CHECK IF IT IS HIGHEST |
check string area |
|
.,B5C7 B1 22 LDA ($22),Y |
DVAR: LDADY INDEX1 ;IS LENGTH=0? |
holt Stringlänge |
get string length |
GET LENGTH OF STRING |
||
.,B5C9 F0 2B BEQ $B5F6 |
BEQ DVARTS ;YES, RETURN. |
wenn Stringlänge=0,dann $B5F6 |
add step and exit if null string |
IGNORE STRING IF LENGTH IS ZERO |
||
.,B5CB C8 INY |
INY |
Zähler erhöhen |
increment index |
|||
.,B5CC B1 22 LDA ($22),Y |
LDADY INDEX1 ;GET LOW(ADR). |
holt Startadresse des Strings |
get string pointer low byte |
GET ADDRESS OF STRING |
||
.,B5CE AA TAX |
TAX |
schiebt ins X-Reg |
copy to X |
|||
.,B5CF C8 INY |
INY |
Zähler erhöhen |
increment index |
|||
.,B5D0 B1 22 LDA ($22),Y |
LDADY INDEX1 |
holt Sringzeiger |
get string pointer high byte |
|||
.,B5D2 C5 34 CMP $34 |
CMP FRETOP+1 ;COMPARE HIGHS. |
Vergleich mit $34 |
compare string pointer high byte with bottom of string space high byte |
CHECK IF ALREADY COLLECTED |
||
.,B5D4 90 06 BCC $B5DC |
BCC DVAR2 ;IF THIS STRING'S PNTR .GE. [FRETOP] |
wenn gleich, dann $B5DC |
if bottom of string space greater go test against highest uncollected string |
NO, BELOW FRETOP |
||
.,B5D6 D0 1E BNE $B5F6 |
BNE DVARTS ;NO NEED TO MESS WITH IT FURTHER. |
wenn größer, dann $B5F6 |
if bottom of string space less string has been collected so go update pointers, step to next and return high bytes were equal so test low bytes |
YES, ABOVE FRETOP |
||
.,B5D8 E4 33 CPX $33 |
CPX FRETOP ;COMPARE LOWS. |
mit $33 vergleichen |
compare string pointer low byte with bottom of string space low byte |
MAYBE, CHECK LO-BYTE |
||
.,B5DA B0 1A BCS $B5F6 |
BCS DVARTS |
wenn gleich, dann $B5F6 |
if bottom of string space less string has been collected so go update pointers, step to next and return else test string against highest uncollected string so far |
YES, ABOVE FRETOP |
||
.,B5DC C5 60 CMP $60 |
DVAR2: CMP GRBTOP+1 |
Vergleich mit $60 |
compare string pointer high byte with highest uncollected string high byte |
ABOVE HIGHEST STRING FOUND? |
||
.,B5DE 90 16 BCC $B5F6 |
BCC DVARTS ;IF THIS STRING IS BELOW PREVIOUS, ;FORGET IT. |
wenn gleich, dann $B5F6 |
if highest uncollected string is greater then go update pointers, step to next and return |
NO, IGNORE FOR NOW |
||
.,B5E0 D0 04 BNE $B5E6 |
BNE DVAR3 |
wenn größer, dann $B5E6 |
if highest uncollected string is less then go set this string as highest uncollected so far high bytes were equal so test low bytes |
YES, THIS IS THE NEW HIGHEST |
||
.,B5E2 E4 5F CPX $5F |
CPX GRBTOP ;COMPARE LOW ORDERS. |
Vergleich mit $5F |
compare string pointer low byte with highest uncollected string low byte |
MAYBE, TRY LO-BYTE |
||
.,B5E4 90 10 BCC $B5F6 |
BCC DVARTS ;[X,A] .LE. [GRBTOP]. |
wenn gleich, dann $B5F6 |
if highest uncollected string is greater then go update pointers, step to next and return else set current string as highest uncollected string |
NO, IGNORE FOR NOW |
||
.,B5E6 86 5F STX $5F |
DVAR3: STX GRBTOP |
Startadresse des |
save string pointer low byte as highest uncollected string low byte |
MAKE THIS THE HIGHEST STRING |
||
.,B5E8 85 60 STA $60 |
STA GRBTOP+1 |
Strings speichern |
save string pointer high byte as highest uncollected string high byte |
|||
.,B5EA A5 22 LDA $22 |
LDWX INDEX1 |
Stringdescriptor |
get descriptor pointer low byte |
SAVE ADDRESS OF DESCRIPTOR TOO |
||
.,B5EC A6 23 LDX $23 |
laden |
get descriptor pointer high byte |
||||
.,B5EE 85 4E STA $4E |
und |
save working pointer high byte |
||||
.,B5F0 86 4F STX $4F |
STWX GRBPNT |
speichern |
save working pointer low byte |
|||
.,B5F2 A5 53 LDA $53 |
LDA FOUR6 |
Tabellen Schrittweite laden |
get step size |
|||
.,B5F4 85 55 STA $55 |
STA SIZE |
und speichern |
copy step size |
ADD (DSCLEN) TO PNTR IN INDEX RETURN WITH Y=0, PNTR ALSO IN X,A |
||
.,B5F6 A5 53 LDA $53 |
DVARTS: LDA FOUR6 |
und zum |
get step size |
BUMP TO NEXT VARIABLE |
||
.,B5F8 18 CLC |
CLC |
Suchzeiger |
clear carry for add |
|||
.,B5F9 65 22 ADC $22 |
ADC INDEX1 |
addieren |
add pointer low byte |
|||
.,B5FB 85 22 STA $22 |
STA INDEX1 |
und wieder |
save pointer low byte |
|||
.,B5FD 90 02 BCC $B601 |
BCC GRBRTS |
speichern |
branch if no rollover |
|||
.,B5FF E6 23 INC $23 |
INC INDEX1+1 |
Zeiger erhöhen |
else increment pointer high byte |
|||
.,B601 A6 23 LDX $23 |
GRBRTS: LDX INDEX1+1 |
und laden |
get pointer high byte |
|||
.,B603 A0 00 LDY #$00 |
LDYI 0 |
Zähler löschen |
flag not moved |
|||
.,B605 60 RTS |
RTS ;DONE. ; ; HERE WHEN MADE ONE COMPLETE PASS THROUGH STRING VARIABLES. ; |
RücksprungStrings zusammenfügen |
collect string |
FOUND HIGHEST NON-EMPTY STRING, SO MOVE IT TO TOP AND GO BACK FOR ANOTHER |
continuation of garbage clean up |
|
.,B606 A5 4F LDA $4F |
GRBPAS: LDA GRBPNT+1 ;VARIABLE POINTER. |
String zwischen Tabellenende |
get working pointer low byte |
|||
.,B608 05 4E ORA $4E |
ORA GRBPNT |
und dem oberen RAM-Bereich |
OR working pointer high byte |
|||
.,B60A F0 F5 BEQ $B601 |
BEQ GRBRTS ;ALL DONE. |
gefunden ? nein, dann RTS |
exit if nothing to collect |
|||
.,B60C A5 55 LDA $55 |
LDA SIZE |
Arraysuchlauf, dann $55=03 |
get copied step size |
|||
.,B60E 29 04 AND #$04 |
ANDI 4 ;LEAVES C OFF. |
ansonsten $55=07 |
mask step size, $04 for variables, $00 for array or stack |
|||
.,B610 4A LSR |
LSR A, |
wenn Einzelvariable, dann |
>> 1 |
|||
.,B611 A8 TAY |
TAY |
Y-Reg =2 und 0 bei Array |
copy to index |
|||
.,B612 85 55 STA $55 |
STA SIZE |
Wert sichern |
save offset to descriptor start |
|||
.,B614 B1 4E LDA ($4E),Y |
LDADY GRBPNT ;NOTE: GRBTOP=LOWTR SO NO NEED TO SET LOWTR. |
Stringlänge holen |
get string length low byte |
|||
.,B616 65 5F ADC $5F |
ADC LOWTR |
zum LOW-Byte der Stringanfangs- |
add string start low byte |
|||
.,B618 85 5A STA $5A |
STA HIGHTR |
adresse Add., =Endadresse +1 |
set block end low byte |
|||
.,B61A A5 60 LDA $60 |
LDA LOWTR+1 |
auf gleiche |
get string start high byte |
|||
.,B61C 69 00 ADC #$00 |
ADCI 0 |
Weise das |
add carry |
|||
.,B61E 85 5B STA $5B |
STA HIGHTR+1 |
HIGH-Byte berechnen |
set block end high byte |
|||
.,B620 A5 33 LDA $33 |
LDWX FRETOP |
Zielbereich |
get bottom of string space low byte |
|||
.,B622 A6 34 LDX $34 |
für den |
get bottom of string space high byte |
||||
.,B624 85 58 STA $58 |
STWX HIGHDS ;WHERE IT ALL GOES. |
Transfer |
save destination end low byte |
|||
.,B626 86 59 STX $59 |
holen |
save destination end high byte |
||||
.,B628 20 BF A3 JSR $A3BF |
JSR BLTUC |
Strings verschieben |
open up space in memory, don't set array end. this copies the string from where it is to the end of the uncollected string memory |
|||
.,B62B A4 55 LDY $55 |
LDY SIZE |
LOW-Byte |
restore offset to descriptor start |
|||
.,B62D C8 INY |
INY |
der |
increment index to string pointer low byte |
|||
.,B62E A5 58 LDA $58 |
LDA HIGHDS ;GET POSITION OF START OF RESULT. |
Anfangsadresse in |
get new string pointer low byte |
|||
.,B630 91 4E STA ($4E),Y |
STADY GRBPNT |
Descriptor speichern |
save new string pointer low byte |
|||
.,B632 AA TAX |
TAX |
HIGH-Byte |
copy string pointer low byte |
|||
.,B633 E6 59 INC $59 |
INC HIGHDS+1 |
der Anfangsadresse |
increment new string pointer high byte |
|||
.,B635 A5 59 LDA $59 |
LDA HIGHDS+1 |
in |
get new string pointer high byte |
|||
.,B637 C8 INY |
INY |
Descriptor |
increment index to string pointer high byte |
|||
.,B638 91 4E STA ($4E),Y |
STADY GRBPNT ;CHANGE ADDR OF STRING IN VAR. |
bringen |
save new string pointer high byte |
|||
.,B63A 4C 2A B5 JMP $B52A |
JMP FNDVAR ;GO TO FNDVAR WITH SOMETHING FOR ;[FRETOP]. ; ; THE FOLLOWING ROUTINE CONCATENATES TWO STRINGS. ; THE FAC CONTAINS THE FIRST ONE AT THIS POINT. ; [TXTPTR] POINTS TO THE + SIGN. ; |
nicht alles ?, dann weiter Stringverknüpfung '+' |
re-run routine from last ending, XA holds new bottom of string memory pointer concatenateadd strings, the first string is in the descriptor, the second string is in line |
CONCATENATE TWO STRINGS |
joining strings |
|
.,B63D A5 65 LDA $65 |
CAT: LDA FACLO ;PSH HIGH ORDER ONTO STACK. |
HIGH-Byte des Descriptors vom |
get descriptor pointer high byte |
SAVE ADDRESS OF FIRST DESCRIPTOR |
||
.,B63F 48 PHA |
PHA |
ersten String auf Stack |
put on stack |
|||
.,B640 A5 64 LDA $64 |
LDA FACMO ;AND THE LOW. |
LOW-Byte |
get descriptor pointer low byte |
|||
.,B642 48 PHA |
PHA |
in Stack |
put on stack |
|||
.,B643 20 83 AE JSR $AE83 |
JSR EVAL ;CAN COME BACK HERE SINCE ;OPERATOR IS KNOWN. |
zweiten String holen |
get value from line |
GET SECOND STRING ELEMENT |
||
.,B646 20 8F AD JSR $AD8F |
JSR CHKSTR ;RESULT MUST BE STRING. |
prüft auf Stringvariable |
check if source is string, else do type mismatch |
MUST BE A STRING |
||
.,B649 68 PLA |
PLA |
Descriptorzeiger des ersten |
get descriptor pointer low byte back |
RECOVER ADDRES OF 1ST DESCRIPTOR |
||
.,B64A 85 6F STA $6F |
STA STRNG1 ;GET HIGH ORDER OF OLD DESC. |
Strings wiederholen |
set pointer low byte |
|||
.,B64C 68 PLA |
PLA |
und |
get descriptor pointer high byte back |
|||
.,B64D 85 70 STA $70 |
STA STRNG1+1 |
speichern |
set pointer high byte |
|||
.,B64F A0 00 LDY #$00 |
LDYI 0 |
Zähler auf Null |
clear index |
|||
.,B651 B1 6F LDA ($6F),Y |
LDADY STRNG1 ;GET LENGTH OF OLD STRING. |
Länge des ersten Strings |
get length of first string from descriptor |
ADD LENGTHS, GET CONCATENATED SIZE |
||
.,B653 18 CLC |
CLC |
plus Länge |
clear carry for add |
|||
.,B654 71 64 ADC ($64),Y |
ADCDY FACMO |
des zweiten Strings |
add length of second string |
|||
.,B656 90 05 BCC $B65D |
BCC SIZEOK ;RESULT IS LESS THAN 256. |
kleiner als 256 |
branch if no overflow |
OK IF < $100 |
||
.,B658 A2 17 LDX #$17 |
LDXI ERRLS ;ERROR "LONG STRING". |
Nummer für 'STRING TOO LONG' |
else error $17, string too long error |
|||
.,B65A 4C 37 A4 JMP $A437 |
JMP ERROR |
Fehlermeldung ausgeben |
do error #X then warm start |
|||
.,B65D 20 75 B4 JSR $B475 |
SIZEOK: JSR STRINI ;INITIALIZE STRING. |
Platz für verknüpften String |
copy descriptor pointer and make string space A bytes long |
GET SPACE FOR CONCATENATED STRINGS |
||
.,B660 20 7A B6 JSR $B67A |
JSR MOVINS ;MOVE IT. |
ersten String übertragen |
copy string from descriptor to utility pointer |
MOVE 1ST STRING |
||
.,B663 A5 50 LDA $50 |
LDWD DSCPNT ;GET POINTER TO SECOND. |
Zeiger auf |
get descriptor pointer low byte |
|||
.,B665 A4 51 LDY $51 |
zweiten Stringdescriptor |
get descriptor pointer high byte |
||||
.,B667 20 AA B6 JSR $B6AA |
JSR FRETMP ;FREE IT. |
FRESTR |
pop (YA) descriptor off stack or from top of string space returns with A = length, X = pointer low byte, Y = pointer high byte |
|||
.,B66A 20 8C B6 JSR $B68C |
JSR MOVDO |
2. String an 1. anhängen |
store string from pointer to utility pointer |
MOVE 2ND STRING |
||
.,B66D A5 6F LDA $6F |
LDWD STRNG1 |
Descriptorzeiger des |
get descriptor pointer low byte |
|||
.,B66F A4 70 LDY $70 |
zweiten Strings |
get descriptor pointer high byte |
||||
.,B671 20 AA B6 JSR $B6AA |
JSR FRETMP |
FRESTR |
pop (YA) descriptor off stack or from top of string space returns with A = length, X = pointer low byte, Y = pointer high byte |
|||
.,B674 20 CA B4 JSR $B4CA |
JSR PUTNEW |
Descriptor in Stringstack |
check space on descriptor stack then put string address and length on descriptor stack and update stack pointers |
SET UP DESCRIPTOR |
||
.,B677 4C B8 AD JMP $ADB8 |
JMP TSTOP ;"CAT" REENTERS FORM EVAL AT TSTOP. |
zurück zur FormelauswertungString in reserv. Bereich |
continue evaluationcopy string from descriptor to utility pointer |
FINISH EXPRESSION GET STRING DESCRIPTOR POINTED AT BY (STRNG1) AND MOVE DESCRIBED STRING TO (FRESPC) |
move string |
|
.,B67A A0 00 LDY #$00 |
MOVINS: LDYI 0 ;GET ADDR OF STRING. |
Zähler auf Null |
clear index |
|||
.,B67C B1 6F LDA ($6F),Y |
LDADY STRNG1 |
Stringlänge holen |
get string length |
|||
.,B67E 48 PHA |
PHA |
und merken |
save it |
LENGTH |
||
.,B67F C8 INY |
INY |
Zähler erhöhen |
increment index |
|||
.,B680 B1 6F LDA ($6F),Y |
LDADY STRNG1 |
LOW-Byte der Stringadresse |
get string pointer low byte |
|||
.,B682 AA TAX |
TAX |
ins X-Reg |
copy to X |
PUT STRING POINTER IN X,Y |
||
.,B683 C8 INY |
INY |
Zähler erhöhen |
increment index |
|||
.,B684 B1 6F LDA ($6F),Y |
LDADY STRNG1 |
HIGH-Byte der Stringadresse |
get string pointer high byte |
|||
.,B686 A8 TAY |
TAY |
ins Y-Reg und |
copy to Y |
|||
.,B687 68 PLA |
PLA |
Stack |
get length back |
RETRIEVE LENGTH MOVE STRING AT (Y,X) WITH LENGTH (A) TO DESTINATION WHOSE ADDRESS IS IN FRESPC,FRESPC+1 |
move string with length A, pointer in XY |
|
.,B688 86 22 STX $22 |
MOVSTR: STXY INDEX |
Zeiger auf |
save string pointer low byte |
PUT POINTER IN INDEX |
||
.,B68A 84 23 STY $23 |
String speichern |
save string pointer high byte store string from pointer to utility pointer |
||||
.,B68C A8 TAY |
MOVDO: TAY |
Länge null ? |
copy length as index |
LENGTH TO Y-REG |
||
.,B68D F0 0A BEQ $B699 |
BEQ MVDONE |
dann fertig |
branch if null string |
IF LENGTH IS ZERO, FINISHED |
||
.,B68F 48 PHA |
PHA |
wieder in Stack |
save length |
SAVE LENGTH ON STACK |
||
.,B690 88 DEY |
MOVLP: DEY |
Zähler erniedrigen |
decrement length/index |
MOVE BYTES FROM (INDEX) TO (FRESPC) |
||
.,B691 B1 22 LDA ($22),Y |
LDADY INDEX |
String |
get byte from string |
|||
.,B693 91 35 STA ($35),Y |
STADY FRESPC |
in den |
save byte to destination |
|||
.,B695 98 TYA |
QMOVE: TYA |
Stringbereich |
copy length/index |
TEST IF ANY LEFT TO MOVE |
||
.,B696 D0 F8 BNE $B690 |
BNE MOVLP |
übertragen |
loop if not all done yet |
YES, KEEP MOVING |
||
.,B698 68 PLA |
PLA |
Den |
restore length |
NO, FINISHED. GET LENGTH |
||
.,B699 18 CLC |
MVDONE: CLC |
Zeiger |
clear carry for add |
AND ADD TO FRESPC, SO |
||
.,B69A 65 35 ADC $35 |
ADC FRESPC |
um |
add string utility ptr low byte |
FRESPC POINTS TO NEXT HIGHER |
||
.,B69C 85 35 STA $35 |
STA FRESPC |
die |
save string utility ptr low byte |
BYTE. (USED BY CONCATENATION) |
||
.,B69E 90 02 BCC $B6A2 |
BCC MVSTRT |
Stringlänge |
branch if no rollover |
|||
.,B6A0 E6 36 INC $36 |
INC FRESPC+1 |
erhöhen |
increment string utility ptr high byte |
|||
.,B6A2 60 RTS |
MVSTRT: RTS ; ; "FRETMP" IS PASSED A STRING DESCRIPTOR PNTR IN [Y,A]. ; A CHECK IS MADE TO SEE IF THE STRING DESCRIPTOR POINTS TO THE LAST ; TEMPORARY DESCRIPTOR ALLOCATED BY PUTNEW. ; IF SO, THE TEMPORARY IS FREED UP BY THE UPDATING OF [TEMPPT]. ; IF A TEMP IS FREED UP, A FURTHER CHECK SEES IF THE STRING DATA THAT ; THAT STRING TEMP PNT'D TO IS THE LOWEST PART OF STRING SPACE IN USE. ; IF SO, [FRETOP] IS UPDATED TO REFLECT THE FACT THE FACT THAT THE SPACE ; IS NO LONGER IN USE. ; THE ADDR OF THE ACTUAL STRING IS RETURNED IN [Y,X] AND ; ITS LENGTH IN ACCA. ; |
RücksprungStringverwaltung FRESTR |
evaluate string |
IF (FAC) IS A TEMPORARY STRING, RELEASE DESCRIPTOR |
de-allocate temporary string |
|
.,B6A3 20 8F AD JSR $AD8F |
FRESTR: JSR CHKSTR ;MAKE SURE ITS A STRING. |
prüft auf Stringvariable |
check if source is string, else do type mismatch pop string off descriptor stack, or from top of string space returns with A = length, X = pointer low byte, Y = pointer high byte |
LAST RESULT A STRING? IF STRING DESCRIPTOR POINTED TO BY FAC+3,4 IS A TEMPORARY STRING, RELEASE IT. |
||
.,B6A6 A5 64 LDA $64 |
FREFAC: LDWD FACMO ;FREE UP STR PNT'D TO BY FAC. |
Zeiger auf |
get descriptor pointer low byte |
GET DESCRIPTOR POINTER |
||
.,B6A8 A4 65 LDY $65 |
Stringdescriptor |
get descriptor pointer high byte pop (YA) descriptor off stack or from top of string space returns with A = length, X = pointer low byte, Y = pointer high byte |
IF STRING DESCRIPTOR WHOSE ADDRESS IS IN Y,A IS A TEMPORARY STRING, RELEASE IT. |
|||
.,B6AA 85 22 STA $22 |
FRETMP: STWD INDEX ;GET LENGTH FOR LATER. |
nach |
save string pointer low byte |
SAVE THE ADDRESS OF THE DESCRIPTOR |
||
.,B6AC 84 23 STY $23 |
$22 und $23 bringen |
save string pointer high byte |
||||
.,B6AE 20 DB B6 JSR $B6DB |
JSR FRETMS ;FREE UP THE TEMPORARY DESC. |
Descriptor vom Stringstack |
clean descriptor stack, YA = pointer |
FREE DESCRIPTOR IF IT IS TEMPORARY |
||
.,B6B1 08 PHP |
PHP ;SAVE CODES. |
Statusregister retten |
save status flags |
REMEMBER IF TEMP |
||
.,B6B2 A0 00 LDY #$00 |
LDYI 0 ;PREP TO GET STUFF. |
Zähler auf Null |
clear index |
POINT AT LENGTH OF STRING |
||
.,B6B4 B1 22 LDA ($22),Y |
LDADY INDEX ;GET COUNT AND |
Stringlänge holen |
get length from string descriptor |
|||
.,B6B6 48 PHA |
PHA ;SAVE IT. |
und in Stack schieben |
put on stack |
SAVE LENGTH ON STACK |
||
.,B6B7 C8 INY |
INY |
Zähler erhöhen |
increment index |
|||
.,B6B8 B1 22 LDA ($22),Y |
LDADY INDEX |
LOW-Byte der Anfangsadresse |
get string pointer low byte from descriptor |
|||
.,B6BA AA TAX |
TAX ;SAVE LOW ORDER. |
ins X-Reg schieben |
copy to X |
GET ADDRESS OF STRING IN Y,X |
||
.,B6BB C8 INY |
INY |
Zähler erhöhen |
increment index |
|||
.,B6BC B1 22 LDA ($22),Y |
LDADY INDEX |
HIGH-Byte der Anfangsadresse |
get string pointer high byte from descriptor |
|||
.,B6BE A8 TAY |
TAY ;SAVE HIGH ORDER. |
ins Y-Reg schieben |
copy to Y |
|||
.,B6BF 68 PLA |
PLA |
Stringlänge wieder aus Stack |
get string length back |
LENGTH IN A |
||
.,B6C0 28 PLP |
PLP ;RETURN STATUS. |
Statusreg. wieder aus Stack |
restore status |
RETRIEVE STATUS, Z=1 IF TEMP |
||
.,B6C1 D0 13 BNE $B6D6 |
BNE FRETRT |
Neustring=Altstring nein? RTS |
branch if pointer <> last_sl,last_sh |
NOT A TEMPORARY STRING |
||
.,B6C3 C4 34 CPY $34 |
CPY FRETOP+1 ;STRING IS LAST ONE IN? |
Stringadresse identisch mit |
compare with bottom of string space high byte |
IS IT THE LOWEST STRING? |
||
.,B6C5 D0 0F BNE $B6D6 |
BNE FRETRT |
Zeiger auf Stringende? |
branch if <> |
NO |
||
.,B6C7 E4 33 CPX $33 |
CPX FRETOP |
nein, dann |
else compare with bottom of string space low byte |
|||
.,B6C9 D0 0B BNE $B6D6 |
BNE FRETRT |
zu $B6D6 |
branch if <> |
NO |
||
.,B6CB 48 PHA |
PHA |
String-Anfangszeiger |
save string length |
YES, PUSH LENGTH AGAIN |
||
.,B6CC 18 CLC |
CLC |
auf Länge |
clear carry for add |
RECOVER THE SPACE USED BY |
||
.,B6CD 65 33 ADC $33 |
ADC FRETOP |
des |
add bottom of string space low byte |
THE STRING |
||
.,B6CF 85 33 STA $33 |
STA FRETOP |
Strings |
set bottom of string space low byte |
|||
.,B6D1 90 02 BCC $B6D5 |
BCC FREPLA |
hinaufsetzen |
skip increment if no overflow |
|||
.,B6D3 E6 34 INC $34 |
INC FRETOP+1 |
Stringlänge |
increment bottom of string space high byte |
|||
.,B6D5 68 PLA |
FREPLA: PLA ;GET COUNT BACK. |
holen |
restore string length |
RETRIEVE LENGTH AGAIN |
||
.,B6D6 86 22 STX $22 |
FRETRT: STXY INDEX ;SAVE FOR LATER USE. |
LOW-Byte der Startadresse |
save string pointer low byte |
ADDRESS OF STRING IN Y,X |
||
.,B6D8 84 23 STY $23 |
HIGH-Byte der Startadresse |
save string pointer high byte |
LENGTH OF STRING IN A-REG |
|||
.,B6DA 60 RTS |
RTS |
RücksprungStringzeiger ausDescriptorstack entfernen |
clean descriptor stack, YA = pointer checks if AY is on the descriptor stack, if so does a stack discard |
RELEASE TEMPORARY DESCRIPTOR IF Y,A = LASTPT |
check descriptor stack |
|
.,B6DB C4 18 CPY $18 |
FRETMS: CPY LASTPT+1 ;LAST ENTRY TO TEMP? |
Zeiger auf Stringdescriptor |
compare high byte with current descriptor stack item pointer high byte |
COMPARE Y,A TO LATEST TEMP |
||
.,B6DD D0 0C BNE $B6EB |
BNE FRERTS |
identisch mit $18, nicht? RTS |
exit if <> |
NOT SAME ONE, CANNOT RELEASE |
||
.,B6DF C5 17 CMP $17 |
CMP LASTPT |
identisch mit 17 |
compare low byte with current descriptor stack item pointer low byte |
|||
.,B6E1 D0 08 BNE $B6EB |
BNE FRERTS |
wenn nicht, dann RTS |
exit if <> |
NOT SAME ONE, CANNOT RELEASE |
||
.,B6E3 85 16 STA $16 |
STA TEMPPT |
Zeiger nach $16 speichern |
set descriptor stack pointer |
UPDATE TEMPT FOR NEXT TEMP |
||
.,B6E5 E9 03 SBC #$03 |
SBCI STRSIZ ;POINT TO LAST ONE. |
Von Adresse $17 |
update last string pointer low byte |
BACK OFF LASTPT |
||
.,B6E7 85 17 STA $17 |
STA LASTPT ;UPDATE TEMP PNTR. |
3 abziehen |
save current descriptor stack item pointer low byte |
|||
.,B6E9 A0 00 LDY #$00 |
LDYI 0 ;ALSO CLEARS ZFLG SO WE DO REST OF FRETMP. |
Zähler auf Null |
clear high byte |
NOW Y,A POINTS TO TOP TEMP |
||
.,B6EB 60 RTS |
FRERTS: RTS ;ALL DONE. ; ; CHR$(#) CREATES A STRING WHICH CONTAINS AS ITS ONLY ; CHARACTER THE ASCII EQUIVALENT OF THE INTEGER ARGUMENT (#) ; WHICH MUST BE .LT. 255. ; |
RücksprungBASIC-Funktion CHR$ |
perform CHR$() |
Z=0 IF NOT TEMP, Z=1 IF TEMP"CHR$" FUNCTION |
CHR$ function |
|
.,B6EC 20 A1 B7 JSR $B7A1 |
CHR: JSR CONINT ;GET INTEGER IN RANGE. |
holt Byte-Wert (0 bis 255) |
evaluate byte expression, result in X |
CONVERT ARGUMENT TO BYTE IN X |
||
.,B6EF 8A TXA |
TXA |
Kode in Akku |
copy to A |
|||
.,B6F0 48 PHA |
PHA |
Akkuinhalt in Stack |
save character |
SAVE IT |
||
.,B6F1 A9 01 LDA #$01 |
LDAI 1 ;ONE-CHARACTER STRING. |
Länge des Strings gleich 1 |
string is single byte |
GET SPACE FOR STRING OF LENGTH 1 |
||
.,B6F3 20 7D B4 JSR $B47D |
JSR STRSPA ;GET SPACE FOR STRING. |
Platz für String freimachen |
make string space A bytes long |
|||
.,B6F6 68 PLA |
PLA |
ASCII-Kode zurückholen |
get character back |
RECALL THE CHARACTER |
||
.,B6F7 A0 00 LDY #$00 |
LDYI 0 |
Zähler auf Null |
clear index |
PUT IN STRING |
||
.,B6F9 91 62 STA ($62),Y |
STADY DSCTMP+1 |
als Stringzeichen speichern |
save byte in string - byte IS string! |
|||
.,B6FB 68 PLA |
PLA ;GET RID OF "CHKNUM" RETURN ADDR. |
Rücksprungadresse aus |
dump return address (skip type check) |
POP RETURN ADDRESS |
||
.,B6FC 68 PLA |
PLA |
Stack entfernen |
dump return address (skip type check) |
|||
.,B6FD 4C CA B4 JMP $B4CA |
RLZRET: JMP PUTNEW ;SETUP FAC TO POINT TO DESC. ; ; THE FOLLOWING IS THE LEFT$($,#) FUNCTION. ; IT TAKES THE LEFTMOST # CHARACTERS OF THE STRING. ; IF # .GT. THE LEN OF THE STRING, IT RETURNS THE WHOLE STRING. ; |
Descriptor in StringstackBASIC-Funktion LEFT$ |
check space on descriptor stack then put string address and length on descriptor stack and update stack pointers perform LEFT$() |
MAKE IT A TEMPORARY STRING"LEFT$" FUNCTION |
LEFT$ function |
|
.,B700 20 61 B7 JSR $B761 |
LEFT: JSR PREAM ;TEST PARAMETERS. |
Stringadresse & Länge aus Stack holen |
pull string data and byte parameter from stack return pointer in descriptor, byte in A (and X), Y=0 |
|||
.,B703 D1 50 CMP ($50),Y |
CMPDY DSCPNT |
Länge mit LEFT$-Parameter vergleichen |
compare byte parameter with string length |
COMPARE 1ST PARAMETER TO LENGTH |
||
.,B705 98 TYA |
TYA |
LEFT$-Parameter |
clear A |
Y=A=0 |
||
.,B706 90 04 BCC $B70C |
RLEFT: BCC RLEFT1 |
kleiner als Stringlänge ? |
branch if string length > byte parameter |
1ST PARAMETER SMALLER, USE IT |
||
.,B708 B1 50 LDA ($50),Y |
LDADY DSCPNT |
Stringlänge holen |
else make parameter = length |
1ST IS LONGER, USE STRING LENGTH |
||
.,B70A AA TAX |
TAX ;PUT LENGTH INTO X. |
und ins X-Reg schieben |
copy to byte parameter copy |
IN X-REG |
||
.,B70B 98 TYA |
TYA ;ZERO A, THE OFFSET. |
Stringlänge und |
clear string start offset |
Y=A=0 AGAIN |
||
.,B70C 48 PHA |
RLEFT1: PHA ;SAVE OFFSET. |
Parameter für LEFT$ |
save string start offset |
PUSH LEFT END OF SUBSTRING |
||
.,B70D 8A TXA |
RLEFT2: TXA |
in Stack |
copy byte parameter (or string length if <) |
|||
.,B70E 48 PHA |
RLEFT3: PHA ;SAVE LENGTH. |
schieben |
save string length |
PUSH LENGTH OF SUBSTRING |
||
.,B70F 20 7D B4 JSR $B47D |
JSR STRSPA ;GET SPACE. |
Platz für neuen String reservieren |
make string space A bytes long |
MAKE ROOM FOR STRING OF (A) BYTES |
||
.,B712 A5 50 LDA $50 |
LDWD DSCPNT |
Zeiger auf Stringdescriptor |
get descriptor pointer low byte |
RELEASE PARAMETER STRING IF TEMP |
||
.,B714 A4 51 LDY $51 |
laden |
get descriptor pointer high byte |
||||
.,B716 20 AA B6 JSR $B6AA |
JSR FRETMP |
FRESTR |
pop (YA) descriptor off stack or from top of string space returns with A = length, X = pointer low byte, Y = pointer high byte |
|||
.,B719 68 PLA |
PLA |
Länge des neuen Strings aus |
get string length back |
GET LENGTH OF SUBSTRING |
||
.,B71A A8 TAY |
TAY |
Stack holen und ins X-Reg |
copy length to Y |
IN Y-REG |
||
.,B71B 68 PLA |
PLA |
alte |
get string start offset back |
GET LEFT END OF SUBSTRING |
||
.,B71C 18 CLC |
CLC |
Stringadresse |
clear carry for add |
ADD TO POINTER TO STRING |
||
.,B71D 65 22 ADC $22 |
ADC INDEX ;COMPUTE WHERE TO COPY. |
entsprechend |
add start offset to string start pointer low byte |
|||
.,B71F 85 22 STA $22 |
STA INDEX |
erhöhen |
save string start pointer low byte |
|||
.,B721 90 02 BCC $B725 |
BCC PULMOR |
und speichern |
branch if no overflow |
|||
.,B723 E6 23 INC $23 |
INC INDEX+1 |
HIGH-Byte erhöhen |
else increment string start pointer high byte |
|||
.,B725 98 TYA |
PULMOR: TYA |
neue Stringlänge holen |
copy length to A |
LENGTH |
||
.,B726 20 8C B6 JSR $B68C |
JSR MOVDO ;GO MOVE IT. |
neuen String in Stringbereich übertragen |
store string from pointer to utility pointer |
COPY STRING INTO SPACE |
||
.,B729 4C CA B4 JMP $B4CA |
JMP PUTNEW |
Descriptor in Stringstack bringen BASIC-Funktion RIGHT$ |
check space on descriptor stack then put string address and length on descriptor stack and update stack pointers perform RIGHT$() |
ADD TO TEMPS"RIGHT$" FUNCTION |
RIGHT$ function |
|
.,B72C 20 61 B7 JSR $B761 |
RIGHT: JSR PREAM |
Stringparameter und Länge vom Stack holen |
pull string data and byte parameter from stack return pointer in descriptor, byte in A (and X), Y=0 |
|||
.,B72F 18 CLC |
CLC ;[LENGTH DES'D]-[LENGTH]-1. |
von Stringlänge |
clear carry for add-1 |
COMPUTE LENGTH-WIDTH OF SUBSTRING |
||
.,B730 F1 50 SBC ($50),Y |
SBCDY DSCPNT |
abziehen |
subtract string length |
TO GET STARTING POINT IN STRING |
||
.,B732 49 FF EOR #$FF |
EORI 255 ;NEGATE. |
Nummer des ersten Elements im alten String |
invert it (A=LEN(expression$)-l) |
|||
.,B734 4C 06 B7 JMP $B706 |
JMP RLEFT ; ; MID ($,#) RETURNS STRING WITH CHARS FROM # POSITION ; ONWARD. IF # .GT. LEN ($) THEN RETURN NULL STRING. ; MID ($,#,#) RETURNS STRING WITH CHARACTERS FROM ; # POSITION FOR #2 CHARACTERS. IF #2 GOES PAST END OF STRING ; RETURN AS MUCH AS POSSIBLE. ; |
weiter wie LEFT$BASIC-Funktion MID$ |
go do rest of LEFT$()perform MID$() |
JOIN LEFT$"MID$" FUNCTION |
MID$ function |
|
.,B737 A9 FF LDA #$FF |
MID: LDAI 255 ;DEFAULT. |
Ersatzwert für den zweiten |
set default length = 255 |
FLAG WHETHER 2ND PARAMETER |
default 3 parameter |
|
.,B739 85 65 STA $65 |
STA FACLO ;SAVE FOR LATER COMPARE. |
Zahlenparameter |
save default length |
|||
.,B73B 20 79 00 JSR $0079 |
JSR CHRGOT ;GET CURRENT CHARACTER. |
CHRGOT letztes Zeichen holen |
scan memory |
SEE IF ")" YET |
||
.,B73E C9 29 CMP #$29 |
CMPI 41 ;IS IT A RIGHT PAREN )? |
')' Klammer zu |
compare with ")" |
) |
||
.,B740 F0 06 BEQ $B748 |
BEQ MID2 ;NO THIRD PARAM. |
wenn ja, dann kein zweiter Parameter, weiter bei $B748 |
branch if = ")" (skip second byte get) |
YES, NO 2ND PARAMETER |
||
.,B742 20 FD AE JSR $AEFD |
JSR CHKCOM ;MUST HAVE COMMA. |
prüft auf Komma |
scan for ",", else do syntax error then warm start |
NO, MUST HAVE COMMA |
||
.,B745 20 9E B7 JSR $B79E |
JSR GETBYT ;GET THE LENGTH INTO "FACLO". |
holt Byte-Wert des zweiten Parameters |
get byte parameter |
GET 2ND PARAM IN X-REG |
||
.,B748 20 61 B7 JSR $B761 |
MID2: JSR PREAM ;CHECK IT OUT. |
Stringparameter und Startposition holen |
pull string data and byte parameter from stack return pointer in descriptor, byte in A (and X), Y=0 |
|||
.,B74B F0 4B BEQ $B798 |
BEQ GOFUC ;THERE IS NO POSTION 0 |
1. Parameter null, 'ILLEGAL QUANTITY' |
if null do illegal quantity error then warm start |
|||
.,B74D CA DEX |
DEX ;COMPUTE OFFSET. |
erste Elementposition |
decrement start index |
1ST PARAMETER - 1 |
||
.,B74E 8A TXA |
TXA |
innerhalb |
copy to A |
|||
.,B74F 48 PHA |
PHA ;PRSERVE AWHILE. |
des alten Strings |
save string start offset |
|||
.,B750 18 CLC |
CLC |
im Stack ablegen |
clear carry for sub-1 |
|||
.,B751 A2 00 LDX #$00 |
LDXI 0 |
Zähler setzen |
clear output string length |
|||
.,B753 F1 50 SBC ($50),Y |
SBCDY DSCPNT ;GET LENGTH OF WHAT'S LEFT. |
alte Stringlänge kleiner als erster Parameter ? |
subtract string length |
|||
.,B755 B0 B6 BCS $B70D |
BCS RLEFT2 ;GIVE NULL STRING. |
wenn ja, dann zu LEFT$ |
if start>string length go do null string |
|||
.,B757 49 FF EOR #$FF |
EORI 255 ;IN SUB C WAS 0 SO JUST COMPLEMENT. |
Berechnen der neuen Länge |
complement -length |
|||
.,B759 C5 65 CMP $65 |
CMP FACLO ;GREATER THAN WHAT'S DESIRED? |
wenn kleiner als zweiter |
compare byte parameter |
USE SMALLER OF TWO |
||
.,B75B 90 B1 BCC $B70E |
BCC RLEFT3 ;NO, COPY THAT MUCH. |
Parameter, dann zu LEFT$ |
if length>remaining string go do RIGHT$ |
|||
.,B75D A5 65 LDA $65 |
LDA FACLO ;GET LENGTH OF WHAT'S DESIRED. |
Zweitparameter als 'rechte' Stringbegrenzung |
get length byte |
|||
.,B75F B0 AD BCS $B70E |
BCS RLEFT3 ;COPY IT. ; ; USED BY RIGHT$, LEFT$, MID$ FOR PARAMETER CHECKING AND SETUP. ; |
unbedingter SprungStringparameter numerischer Wertvom Stack holen |
go do string copy, branch alwayspull string data and byte parameter from stackreturn pointer in descriptor, byte in A (and X), Y=0 |
...ALWAYSCOMMON SETUP ROUTINE FOR LEFT$, RIGHT$, MID$REQUIRE ")"; POP RETURN ADRS, GET DESCRIPTORADDRESS, GET 1ST PARAMETER OF COMMAND |
get first 2 parameters forLEFT$, RIGHT$ and MID$ |
|
.,B761 20 F7 AE JSR $AEF7 |
PREAM: JSR CHKCLS ;PARAM LIST SHOULD END. |
prüft auf Klammer zu |
scan for ")", else do syntax error then warm start |
REQUIRE ")" |
||
.,B764 68 PLA |
PLA ;GET THE RETURN ADDRESS INTO |
LOW-Byte der |
pull return address low byte |
SAVE RETURN ADDRESS |
||
.,B765 A8 TAY |
TAY ;[JMPER+1,Y] |
Aufrufadresse merken |
save return address low byte |
IN Y-REG AND LENGTH |
||
.,B766 68 PLA |
PLA |
HIGH-Byte der |
pull return address high byte |
|||
.,B767 85 55 STA $55 |
STA JMPER+1 |
Aufrufadresse merken |
save return address high byte |
|||
.,B769 68 PLA |
PLA ;GET RID OF FINGO'S JSR RET ADDR. |
LOW-und HIGH-Byte der |
dump call to function vector low byte |
POP PREVIOUS RETURN ADDRESS |
||
.,B76A 68 PLA |
PLA |
Aufrufadresse merken |
dump call to function vector high byte |
(FROM GOROUT). |
||
.,B76B 68 PLA |
PLA ;GET LENGTH. |
1. Parameter holen |
pull byte parameter |
RETRIEVE 1ST PARAMETER |
||
.,B76C AA TAX |
TAX |
und ins X-Reg |
copy byte parameter to X |
|||
.,B76D 68 PLA |
PULWD DSCPNT |
LOW- und HIGH-Byte |
pull string pointer low byte |
GET ADDRESS OF STRING DESCRIPTOR |
||
.,B76E 85 50 STA $50 |
des |
save it |
||||
.,B770 68 PLA |
Stringdescriptors |
pull string pointer high byte |
||||
.,B771 85 51 STA $51 |
nach |
save it |
||||
.,B773 A5 55 LDA $55 |
LDA JMPER+1 ;PUT RETURN ADDRESS BACK ON |
$51 und $52 speichern |
get return address high byte |
RESTORE RETURN ADDRESS |
||
.,B775 48 PHA |
PHA |
Aufrufadresse |
back on stack |
|||
.,B776 98 TYA |
TYA |
wieder auf |
get return address low byte |
|||
.,B777 48 PHA |
PHA |
Stack |
back on stack |
|||
.,B778 A0 00 LDY #$00 |
LDYI 0 |
Zähler auf Null |
clear index |
|||
.,B77A 8A TXA |
TXA |
Länge, zweiter Parameter |
copy byte parameter |
GET 1ST PARAMETER IN A-REG |
||
.,B77B 60 RTS |
RTS ; ; THE FUNCTION LEN($) RETURNS THE LENGTH OF THE STRING ; PASSED AS AN ARGUMENT. ; |
RücksprungBASIC-Funktion LEN |
perform LEN() |
"LEN" FUNCTION |
LEN function |
|
.,B77C 20 82 B7 JSR $B782 |
LEN: JSR LEN1 |
FRESTR, Stringlänge holen |
evaluate string, get length in A (and Y) |
GET LENTGH IN Y-REG, MAKE FAC NUMERIC |
||
.,B77F 4C A2 B3 JMP $B3A2 |
JMP SNGFLT |
Byte-Wert nach Fließkommaformat wandeln Stringparameter holen |
convert Y to byte in FAC1 and returnevaluate string, get length in Y |
FLOAT Y-REG INTO FAC IF LAST RESULT IS A TEMPORARY STRING, FREE IT MAKE VALTYP NUMERIC, RETURN LENGTH IN Y-REG |
||
.,B782 20 A3 B6 JSR $B6A3 |
LEN1: JSR FRESTR ;FREE UP STRING. |
FRESTR, String holen, Länge in A |
evaluate string |
IF LAST RESULT IS A STRING, FREE IT |
||
.,B785 A2 00 LDX #$00 |
LDXI 0 |
Typeflag |
set data type = numeric |
MAKE VALTYP NUMERIC |
||
.,B787 86 0D STX $0D |
STX VALTYP ;FORCE NUMERIC. |
auf numerisch setzen |
clear data type flag, $FF = string, $00 = numeric |
|||
.,B789 A8 TAY |
TAY ;SET CODES ON LENGTH. |
Länge in Y |
copy length to Y |
LENGTH OF STRING TO Y-REG |
||
.,B78A 60 RTS |
RTS ;DONE. ; ; THE FOLLOWING IS THE ASC($) FUNCTION. IT RETURNS ; AN INTEGER WHICH IS THE DECIMAL ASCII EQUIVALENT. ; |
RücksprungBASIC-Funktion ASC |
perform ASC() |
"ASC" FUNCTION |
ASC function |
|
.,B78B 20 82 B7 JSR $B782 |
ASC: JSR LEN1 |
String holen, Zeiger in $22/$23, Länge in Y |
evaluate string, get length in A (and Y) |
GET STRING, GET LENGTH IN Y-REG |
||
.,B78E F0 08 BEQ $B798 |
BEQ GOFUC ;NULL STRING, BAD ARG. |
Länge gleich null, 'ILLEGAL QUANTITY' |
if null do illegal quantity error then warm start |
ERROR IF LENGTH 0 |
||
.,B790 A0 00 LDY #$00 |
LDYI 0 |
Zähler auf Null |
set index to first character |
|||
.,B792 B1 22 LDA ($22),Y |
LDADY INDEX1 ;GET CHARACTER. |
erstes Zeichen holen |
get byte |
GET 1ST CHAR OF STRING |
||
.,B794 A8 TAY |
TAY |
ASCII-Kode |
copy to Y |
|||
.,B795 4C A2 B3 JMP $B3A2 |
JMP SNGFLT |
nach Fließkomma wandeln |
convert Y to byte in FAC1 and returndo illegal quantity error then warm start |
FLOAT Y-REG INTO FAC |
||
.,B798 4C 48 B2 JMP $B248 |
GOFUC: JMP FCERR ;YES. |
'ILLEGAL QUANTITY'holt Byte-Wert nach X |
do illegal quantity error then warm startscan and get byte parameter |
ILLEGAL QUANTITY ERRORSCAN TO NEXT CHARACTER AND CONVERT EXPRESSIONTO SINGLE BYTE IN X-REG |
fetch integer value in X and check range |
|
.,B79B 20 73 00 JSR $0073 |
GTBYTC: JSR CHRGET |
CHRGET nächstes Zeichen holen |
increment and scan memoryget byte parameter |
EVALUATE EXPRESSION AT TXTPTR, ANDCONVERT IT TO SINGLE BYTE IN X-REG |
||
.,B79E 20 8A AD JSR $AD8A |
GETBYT: JSR FRMNUM ;READ FORMULA INTO FAC. |
FRMNUM numerischen Wert nach FAC holen |
evaluate expression and check is numeric, else do type mismatch evaluate byte expression, result in X |
CONVERT (FAC) TO SINGLE BYTE INTEGER IN X-REG |
||
.,B7A1 20 B8 B1 JSR $B1B8 |
CONINT: JSR POSINT ;CONVERT THE FAC TO A SINGLE BYTE INT. |
prüft auf Bereich und wandelt nach Integer |
evaluate integer expression, sign check |
CONVERT IF IN RANGE -32767 TO +32767 |
||
.,B7A4 A6 64 LDX $64 |
LDX FACMO |
HIGH-Byte |
get FAC1 mantissa 3 |
HI-BYTE MUST BE ZERO |
||
.,B7A6 D0 F0 BNE $B798 |
BNE GOFUC ;RESULT MUST BE .LE. 255. |
ungleich null, dann 'ILLEGAL QUANTITY' |
if not null do illegal quantity error then warm start |
VALUE > 255, ERROR |
||
.,B7A8 A6 65 LDX $65 |
LDX FACLO |
LOW-Byte des geholten Ausdrucks ins X-Reg |
get FAC1 mantissa 4 |
VALUE IN X-REG |
||
.,B7AA 4C 79 00 JMP $0079 |
CHRGO2: JMP CHRGOT ;SET CONDITION CODES ON TERMINATOR. ; ; THE "VAL" FUNCTION TAKES A STRING AND TURNS IT INTO ; A NUMBER BY INTERPRETING THE ASCII DIGITS ETCQ ; EXCEPT FOR THE PROBLEM THAT A TERMINATOR MUST BE SUPPLIED ; BY REPLACING THE CHARACTER BEYOND THE STRING, VAL IS MERELY ; A CALL TO FLOATING POINT INPUT ("FIN"). ; |
CHRGOT letztes Zeichen holenBASIC-Funktion VAL |
scan memory and returnperform VAL() |
GET NEXT CHAR IN A-REG"VAL" FUNCTION |
VAL function |
|
.,B7AD 20 82 B7 JSR $B782 |
VAL: JSR LEN1 ;DO SETUP. SET RESULT=NUMERIC. |
Stringadresse und Länge holen |
evaluate string, get length in A (and Y) |
GET POINTER TO STRING IN INDEX |
||
.,B7B0 D0 03 BNE $B7B5 |
JEQ ZEROFC ;ZERO THE FAC ON A NULL STRING |
Stringlänge ungleich Null ? |
branch if not null string string was null so set result = $00 |
LENGTH NON-ZERO |
||
.,B7B2 4C F7 B8 JMP $B8F7 |
Null in FAC |
clear FAC1 exponent and sign and return |
RETURN 0 IF LENGTH=0 |
|||
.,B7B5 A6 7A LDX $7A |
LDXY TXTPTR |
Programmzeiger |
get BASIC execute pointer low byte |
SAVE CURRENT TXTPTR |
||
.,B7B7 A4 7B LDY $7B |
holen |
get BASIC execute pointer high byte |
||||
.,B7B9 86 71 STX $71 |
STXY STRNG2 ;SAVE FOR LATER. |
und |
save BASIC execute pointer low byte |
|||
.,B7BB 84 72 STY $72 |
speichern |
save BASIC execute pointer high byte |
||||
.,B7BD A6 22 LDX $22 |
LDX INDEX1 |
Stringanfangsadresse |
get string pointer low byte |
|||
.,B7BF 86 7A STX $7A |
STX TXTPTR |
in Stringzeiger bringen |
save BASIC execute pointer low byte |
POINT TXTPTR TO START OF STRING |
||
.,B7C1 18 CLC |
CLC |
LOW-Byte des |
clear carry for add |
|||
.,B7C2 65 22 ADC $22 |
ADC INDEX1 |
ersten Zeichens |
add string length |
ADD LENGTH |
||
.,B7C4 85 24 STA $24 |
STA INDEX2 |
nach dem String speichern |
save string end low byte |
POINT DEST TO END OF STRING + 1 |
||
.,B7C6 A6 23 LDX $23 |
LDX INDEX1+1 |
HIGH-Byte |
get string pointer high byte |
|||
.,B7C8 86 7B STX $7B |
STX TXTPTR+1 |
des ersten |
save BASIC execute pointer high byte |
|||
.,B7CA 90 01 BCC $B7CD |
BCC VAL2 ;NO CARRY, NO INC. |
Zeichens |
branch if no high byte increment |
|||
.,B7CC E8 INX |
INX |
nach dem String |
increment string end high byte |
|||
.,B7CD 86 25 STX $25 |
VAL2: STX INDEX2+1 |
speichern |
save string end high byte |
|||
.,B7CF A0 00 LDY #$00 |
LDYI 0 |
Zähler auf Null |
set index to $00 |
SAVE BYTE THAT FOLLOWS STRING |
||
.,B7D1 B1 24 LDA ($24),Y |
LDADY INDEX2 ;PRESERVE CHARACTER. |
erstes Byte nach String |
get string end byte |
ON STACK |
||
.,B7D3 48 PHA |
PHA |
auf Stack |
push it |
|||
.,B7D4 98 TYA |
LDAI 0 ;SET A TERMINATOR. |
speichern |
clear A |
AND STORE $00 IN ITS PLACE |
||
.,B7D5 91 24 STA ($24),Y |
STADY INDEX2 |
und durch null ersetzen |
terminate string with $00 |
<<< THAT CAUSES A BUG IF HIMEM = $BFFF, >>> <<< BECAUSE STORING $00 AT $C000 IS NO >>> <<< USE; $C000 WILL ALWAYS BE LAST CHAR >>> <<< TYPED, SO FIN WON'T TERMINATE UNTIL >>> <<< IT SEES A ZERO AT $C010! >>> |
||
.,B7D7 20 79 00 JSR $0079 |
JSR CHRGOT ;GET CHARACTER PNT'D TO AND SET FLAGS. |
CHRGOT letztes Zeichen holen |
scan memory |
PRIME THE PUMP |
||
.,B7DA 20 F3 BC JSR $BCF3 |
JSR FIN |
String in Fließkommazahl umwandeln |
get FAC1 from string |
EVALUATE STRING |
||
.,B7DD 68 PLA |
PLA ;GET PRES'D CHARACTER. |
Zeichen nach String |
restore string end byte |
GET BYTE THAT SHOULD FOLLOW STRING |
||
.,B7DE A0 00 LDY #$00 |
LDYI 0 |
Zähler auf Null |
clear index |
AND PUT IT BACK |
||
.,B7E0 91 24 STA ($24),Y |
STADY INDEX2 ;STUFF IT BACK. |
wieder zurücksetzen |
put string end byte backrestore BASIC execute pointer from temp |
RESTORE TXTPTRCOPY STRNG2 INTO TXTPTR |
||
.,B7E2 A6 71 LDX $71 |
ST2TXT: LDXY STRNG2 |
Die |
get BASIC execute pointer low byte back |
|||
.,B7E4 A4 72 LDY $72 |
Programmzeiger |
get BASIC execute pointer high byte back |
||||
.,B7E6 86 7A STX $7A |
STXY TXTPTR |
wieder |
save BASIC execute pointer low byte |
|||
.,B7E8 84 7B STY $7B |
zurückholen |
save BASIC execute pointer high byte |
||||
.,B7EA 60 RTS |
VALRTS: RTS ;ALL DONE WITH STRINGS. PAGE PEEK, POKE, AND FNWAIT. |
RücksprungGETADR und GETBYT holt16-Bit und 8-Bit-Wert |
get parameters for POKE/WAIT |
EVALUATE "EXP1,EXP2"CONVERT EXP1 TO 16-BIT NUMBER IN LINNUMCONVERT EXP2 TO 8-BIT NUMBER IN X-REG |
get address into $14/$15 and integer in X |
|
.,B7EB 20 8A AD JSR $AD8A |
GETNUM: JSR FRMNUM ;GET ADDRESS. |
FRMNUM holt numerischen Wert |
evaluate expression and check is numeric, else do type mismatch |
|||
.,B7EE 20 F7 B7 JSR $B7F7 |
JSR GETADR ;GET THAT LOCATION. |
FAC in Adressformat wandlen $14/$15 |
convert FAC_1 to integer in temporary integer |
EVALUATE ",EXPRESSION"CONVERT EXPRESSION TO SINGLE BYTE IN X-REG |
||
.,B7F1 20 FD AE JSR $AEFD |
COMBYT: JSR CHKCOM ;CHECK FOR A COMMA. |
CHKCOM prüft auf Komma |
scan for ",", else do syntax error then warm start |
MUST HAVE COMMA FIRST |
||
.,B7F4 4C 9E B7 JMP $B79E |
JMP GETBYT ;GET SOMETHING TO STORE AND RETURN. |
holt Byte-Wert nach XGETADR FAC in positive16-Bit-Zahl wandeln |
get byte parameter and returnconvert FAC_1 to integer in temporary integer |
CONVERT EXPRESSION TO BYTE IN X-REGCONVERT (FAC) TO A 16-BIT VALUE IN LINNUM |
convert float ti integer in $14/$15 |
|
.,B7F7 A5 66 LDA $66 |
GETADR: LDA FACSGN ;EXAMINE SIGN. |
Vorzeichen |
get FAC1 sign |
FAC < 2^16? |
||
.,B7F9 30 9D BMI $B798 |
BMI GOFUC ;FUNCTION CALL ERROR. |
negativ, dann 'ILLEGAL QUANTITY' |
if -ve do illegal quantity error then warm start |
|||
.,B7FB A5 61 LDA $61 |
LDA FACEXP ;EXAMINE EXPONENT. |
Exponent |
get FAC1 exponent |
|||
.,B7FD C9 91 CMP #$91 |
CMPI 145 |
Zahl mit 65536 vergleichen |
compare with exponent = 2^16 |
|||
.,B7FF B0 97 BCS $B798 |
BCS GOFUC ;FUNCTION CALL ERROR. |
größer, dann |
if >= do illegal quantity error then warm start |
NO, ILLEGAL QUANTITY |
||
.,B801 20 9B BC JSR $BC9B |
JSR QINT ;INTEGERIZE IT. |
'ILLEGAL QUANTITY' FAC in Adressformat wandeln |
convert FAC1 floating to fixed |
CONVERT TO INTEGER |
||
.,B804 A5 64 LDA $64 |
LDWD FACMO |
Wert |
get FAC1 mantissa 3 |
COPY IT INTO LINNUM |
||
.,B806 A4 65 LDY $65 |
holen |
get FAC1 mantissa 4 |
||||
.,B808 84 14 STY $14 |
STY POKER |
und nach $14/$15 |
save temporary integer low byte |
TO LINNUM |
||
.,B80A 85 15 STA $15 |
STA POKER+1 |
speichern |
save temporary integer high byte |
|||
.,B80C 60 RTS |
RTS ;IT'S DONE !. |
RücksprungBASIC-Funktion PEEK |
perform PEEK() |
"PEEK" FUNCTION |
PEEK function |
|
.,B80D A5 15 LDA $15 |
PEEK: PSHWD POKER |
$14 und $15 |
get line number high byte |
SAVE (LINNUM) ON STACK DURING PEEK |
||
.,B80F 48 PHA |
in |
save line number high byte |
||||
.,B810 A5 14 LDA $14 |
Stack |
get line number low byte |
||||
.,B812 48 PHA |
sichern |
save line number low byte |
||||
.,B813 20 F7 B7 JSR $B7F7 |
JSR GETADR |
FAC nach Adressformat wandeln |
convert FAC_1 to integer in temporary integer |
GET ADDRESS PEEKING AT |
||
.,B816 A0 00 LDY #$00 |
LDYI 0 IFE REALIO-3,< CMPI ROMLOC/256 ;IF WITHIN BASIC, BCC GETCON CMPI LASTWR/256 BCC DOSGFL> ;GIVE HIM ZERO FOR AN ANSWER. |
Zähler auf Null |
clear index |
|||
.,B818 B1 14 LDA ($14),Y |
GETCON: LDADY POKER ;GET THAT BYTE. |
Peek-Wert holen |
read byte |
TAKE A QUICK LOOK |
||
.,B81A A8 TAY |
TAY |
nach Y-Reg |
copy byte to A |
VALUE IN Y-REG |
||
.,B81B 68 PLA |
DOSGFL: PULWD POKER |
$14 und $15 |
pull byte |
RESTORE LINNUM FROM STACK |
||
.,B81C 85 14 STA $14 |
wieder |
restore line number low byte |
||||
.,B81E 68 PLA |
vom Stack |
pull byte |
||||
.,B81F 85 15 STA $15 |
zurückholen |
restore line number high byte |
||||
.,B821 4C A2 B3 JMP $B3A2 |
JMP SNGFLT ;FLOAT IT. |
Y nach FließkommaformatBASIC-Befehl POKE |
convert Y to byte in FAC_1 and returnperform POKE |
FLOAT Y-REG INTO FAC"POKE" STATEMENT |
POKE command |
|
.,B824 20 EB B7 JSR $B7EB |
POKE: JSR GETNUM |
Poke-Adrefcse und Wert holen |
get parameters for POKE/WAIT |
GET THE ADDRESS AND VALUE |
||
.,B827 8A TXA |
TXA |
Poke-Wert in Akku |
copy byte to A |
VALUE IN A, |
||
.,B828 A0 00 LDY #$00 |
LDYI 0 |
Zähler auf Null |
clear index |
|||
.,B82A 91 14 STA ($14),Y |
STADY POKER ;STORE VALUE AWAY. |
und in Speicher schreiben |
write byte |
STORE IT AWAY, |
||
.,B82C 60 RTS |
RTS ;SCANNED EVERYTHING. ; THE WAIT LOCATION,MASK1,MASK2 STATEMENT WAITS UNTIL THE CONTENTS ; OF LOCATION IS NONZERO WHEN XORED WITH MASK2 ; AND THEN ANDED WITH MASK1. IF MASK2 IS NOT PRESENT, IT ; IS ASSUMED TO BE ZERO. |
RücksprungBASIC-Befehl WAIT |
perform WAIT |
AND THAT'S ALL FOR TODAY"WAIT" STATEMENT |
WAIT command |
|
.,B82D 20 EB B7 JSR $B7EB |
FNWAIT: JSR GETNUM |
Adresse und Wert holen |
get parameters for POKE/WAIT |
GET ADDRESS IN LINNUM, MASK IN X |
||
.,B830 86 49 STX $49 |
STX ANDMSK |
zweiter Parameter nach $49 |
save byte |
SAVE MASK |
||
.,B832 A2 00 LDX #$00 |
LDXI 0 |
Default für dritten Parameter |
clear mask |
|||
.,B834 20 79 00 JSR $0079 |
JSR CHRGOT |
CHRGOT letztes Zeichen |
scan memory |
ANOTHER PARAMETER? |
||
.,B837 F0 03 BEQ $B83C |
BEQ ZSTORDO |
kein dritter Parameter ? |
skip if no third argument |
NO, USE $00 FOR EXCLUSIVE-OR |
||
.,B839 20 F1 B7 JSR $B7F1 |
JSR COMBYT ;GET MASK2. |
prüft auf Komma und holt Parameter |
scan for "," and get byte, else syntax error then warm start |
GET XOR-MASK |
||
.,B83C 86 4A STX $4A |
STORDO: STX EORMSK |
dritter Parameter nach $4A |
save EOR argument |
SAVE XOR-MASK HERE |
||
.,B83E A0 00 LDY #$00 |
LDYI 0 |
Zähler auf Null |
clear index |
|||
.,B840 B1 14 LDA ($14),Y |
WAITER: LDADY POKER |
Wait-Adresse |
get byte via temporary integer (address) |
GET BYTE AT ADDRESS |
||
.,B842 45 4A EOR $4A |
EOR EORMSK |
logisch |
EOR with second argument (mask) |
INVERT SPECIFIED BITS |
||
.,B844 25 49 AND $49 |
AND ANDMSK |
verknüpfen |
AND with first argument (byte) |
SELECT SPECIFIED BITS |
||
.,B846 F0 F8 BEQ $B840 |
BEQ WAITER |
weiter warten |
loop if result is zero |
LOOP TILL NOT 0 |
||
.,B848 60 RTS |
ZERRTS: RTS ;GOT A NONZERO.FLOATING POINT MATH PACKAGE CONFIGURATION.RADIX 8 ;!!!! ALERT !!!!;THROUGHOUT THE MATH PACKAGE. COMMENT % THE FLOATING POINT FORMAT IS AS FOLLOWS: THE SIGN IS THE FIRST BIT OF THE MANTISSA. THE MANTISSA IS 24 BITS LONG. THE BINARY POINT IS TO THE LEFT OF THE MSB. NUMBER = MANTISSA * 2 ^ EXPONENT. THE MANTISSA IS POSITIVE WITH A ONE ASSUMED TO BE WHERE THE SIGN BIT IS. THE SIGN OF THE EXPONENT IS THE FIRST BIT OF THE EXPONENT. THE EXPONENT IS STORED IN EXCESS 200, I.E. WITH A BIAS OF +200. SO, THE EXPONENT IS A SIGNED 8-BIT NUMBER WITH 200 ADDED TO IT. AN EXPONENT OF ZERO MEANS THE NUMBER IS ZERO. THE OTHER BYTES MAY NOT BE ASSUMED TO BE ZERO. TO KEEP THE SAME NUMBER IN THE FAC WHILE SHIFTING, TO SHIFT RIGHT, EXP:=EXP+1 TO SHIFT LEFT, EXP:=EXP-1 IN MEMORY THE NUMBER LOOKS LIKE THIS: [THE EXPONENT AS A SIGNED NUMBER +200] [THE SIGN BIT IN 7, BITS 2-8 OF MANTISSA ARE IN BITS 6-0]. (REMEMBER BIT 1 OF MANTISSA IS ALWAYS A ONE.) [BITS 9-16 OF THE MANTISSA] [BITS 17-24] OF THE MANTISSA] ARITHMETIC ROUTINE CALLING CONVENTIONS: FOR ONE ARGUMENT FUNCTIONS: THE ARGUMENT IS IN THE FAC. THE RESULT IS LEFT IN THE FAC. FOR TWO ARGUMENT OPERATIONS: THE FIRST ARGUMENT IS IN ARG (ARGEXP,HO,MO,LO AND ARGSGN). THE SECOND ARGUMENT IS IN THE FAC. THE RESULT IS LEFT IN THE FAC. THE "T" ENTRY POINTS TO THE TWO-ARGUMENT OPERATIONS HAVE BOTH ARGUMENTS SETUP IN THE RESPECTIVE REGISTERS. BEFORE CALLING ARG MAY HAVE BEEN POPPED OFF THE STACK AND INTO ARG, FOR EXAMPLE. THE OTHER ENTRY POINT ASSUMES [Y,A] POINTS TO THE ARGUMENT SOMEWHERE IN MEMORY. IT IS UNPACKED INTO ARG BY "CONUPK". ON THE STACK, THE SGN IS PUSHED ON FIRST, THE LO,MO,HO AND FINALLY EXP. NOTE ALL THINGS ARE KEPT UNPACKED IN ARG, FAC AND ON THE STACK. IT IS ONLY WHEN SOMETHING IS STORED AWAY THAT IT IS PACKED TO FOUR BYTES. THE UNPACKED FORMAT HAS A SGN BYTE REFLECTING THE SIGN OF THE NUMBER (POSITIVE=0, NEGATIVE=-1) A HO,MO AND LO WITH THE HIGH BIT OF THE HO TURNED ON. THE EXP IS THE SAME AS STORED FORMAT. THIS IS DONE FOR SPEED OF OPERATION. % PAGE FLOATING POINT ADDITION AND SUBTRACTION. |
RücksprungArithmetik-RoutinenFAC = FAC + 0.5 |
add 0.5 to FAC1 (round FAC1) |
ADD 0.5 TO FAC |
add 0.5 to float accu (rounding) |
|
.,B849 A9 11 LDA #$11 |
FADDH: LDWDI FHALF ;ENTRY TO ADD 1/2. |
Zeiger auf |
set 0.5 pointer low byte |
FAC+1/2 -> FAC |
low BF11 |
|
.,B84B A0 BF LDY #$BF |
Konstante 0.5 |
set 0.5 pointer high byte |
high BF11 |
|||
.,B84D 4C 67 B8 JMP $B867 |
JMP FADD ;UNPACK AND GO ADD IT. |
FAC = FAC + Konstante (A/Y)Minus FAC = Konstante(A/Y) - FAC |
add (AY) to FAC1perform subtraction, FAC1 from (AY) |
FAC = (Y,A) - FAC |
minus operator |
|
.,B850 20 8C BA JSR $BA8C |
FSUB: JSR CONUPK ;UNPACK ARGUMENT INTO ARG. |
Konstante (A/Y) nach ARGMinus FAC = ARG - FAC |
unpack memory (AY) into FAC2perform subtraction, FAC1 from FAC2 |
FAC = ARG - FAC |
||
.,B853 A5 66 LDA $66 |
FSUBT: LDA FACSGN |
Die |
get FAC1 sign (b7) |
COMPLEMENT FAC AND ADD |
||
.,B855 49 FF EOR #$FF |
EORI 377 ;COMPLEMENT IT. |
Vorzeichen |
complement it |
|||
.,B857 85 66 STA $66 |
STA FACSGN |
umdrehen |
save FAC1 sign (b7) |
|||
.,B859 45 6E EOR $6E |
EOR ARGSGN ;COMPLEMENT ARISGN. |
mit Vorzeichen von FAC |
EOR with FAC2 sign (b7) |
FIX SGNCPR TOO |
||
.,B85B 85 6F STA $6F |
STA ARISGN |
verknüpfen |
save sign compare (FAC1 EOR FAC2) |
|||
.,B85D A5 61 LDA $61 |
LDA FACEXP ;SET CODES ON FACEXP. |
Exponent von FAC |
get FAC1 exponent |
MAKE STATUS SHOW FAC EXPONENT |
||
.,B85F 4C 6A B8 JMP $B86A |
JMP FADDT ;[Y]=ARGEXP.. XLIST .XCREF IFN REALIO-3,<ZSTORDO=STORDO> IFE REALIO-3,< ZSTORD:! LDA POKER CMPI 146 BNE STORDO LDA POKER+1 SBCI 31 BNE STORDO STA POKER TAY LDAI 200 STA POKER+1 MRCHKR: LDXI 12 IF1,< MRCHR: LDA 60000,X,> IF2,< MRCHR: LDA SINCON+36,X,> ANDI 77 STADY POKER INY BNE PKINC INC POKER+1 PKINC: DEX BNE MRCHR DEC ANDMSK BNE MRCHKR RTS IF2,<PURGE ZSTORD>> .CREF LIST |
FAC = FAC + ARG |
add FAC2 to FAC1 and return |
JOIN FADDSHIFT SMALLER ARGUMENT MORE THAN 7 BITS |
||
.,B862 20 99 B9 JSR $B999 |
FADD5: JSR SHIFTR ;DO A LONG SHIFT. |
Exponenten von FAC und ARG |
shift FACX A times right (>8 shifts) |
ALIGN RADIX BY SHIFTING |
||
.,B865 90 3C BCC $B8A3 |
BCC FADD4 ;CONTINUE WITH ADDITION. |
angleichenPlus FAC = Konstante (A/Y) +FAC |
go subtract mantissasadd (AY) to FAC1 |
...ALWAYSFAC = (Y,A) + FAC |
add float indexed by AY to float accu |
|
.,B867 20 8C BA JSR $BA8C |
FADD: JSR CONUPK |
Konstante (A/Y) nach ARGPlus FAC = FAC + ARG |
unpack memory (AY) into FAC2add FAC2 to FAC1 |
FAC = ARG + FAC |
plus operator |
|
.,B86A D0 03 BNE $B86F |
FADDT: JEQ MOVFA ;IF FAC=0, RESULT IS IN ARG. |
FAC ungleich null ? |
branch if FAC1 is not zero |
FAC IS NON-ZERO |
||
.,B86C 4C FC BB JMP $BBFC |
nein, dann FAC = ARG |
FAC1 was zero so copy FAC2 to FAC1 and return FAC1 is non zero |
FAC = 0 + ARG |
|||
.,B86F A6 70 LDX $70 |
LDX FACOV |
Rundungsbyte für FAC |
get FAC1 rounding byte |
|||
.,B871 86 56 STX $56 |
STX OLDOV |
in $56 speichern |
save as FAC2 rounding byte |
|||
.,B873 A2 69 LDX #$69 |
LDXI ARGEXP ;DEFAULT IS SHIFT ARGUMENT. |
Offset-Zeiger für ARG laden |
set index to FAC2 exponent address |
SET UP TO SHIFT ARG |
||
.,B875 A5 69 LDA $69 |
LDA ARGEXP ;IF ARG=0, FAC IS RESULT. |
Exponent von ARG laden |
get FAC2 exponent |
EXPONENT |
||
.,B877 A8 TAY |
FADDC: TAY ;ALSO COPY ACCA INTO ACCY. |
in Y-Reg schieben |
copy exponent |
|||
.,B878 F0 CE BEQ $B848 |
BEQ ZERRTS ;RETURN. |
wenn ARG=0, dann RTS |
exit if zero |
IF ARG=0, WE ARE FINISHED |
||
.,B87A 38 SEC |
SEC |
Exponent von |
set carry for subtract |
|||
.,B87B E5 61 SBC $61 |
SBC FACEXP |
FAC subtrahieren |
subtract FAC1 exponent |
GET DIFFNCE OF EXP |
||
.,B87D F0 24 BEQ $B8A3 |
BEQ FADD4 ;NO SHIFTING. |
wenn Exponent gleich, dann zu $B8A3 |
if equal go add mantissas |
GO ADD IF SAME EXP |
||
.,B87F 90 12 BCC $B893 |
BCC FADDA ;BR IF ARGEXP.LT.FACEXP. |
wenn Exponent von FAC größer, dann zu $B893 |
if FAC2 < FAC1 then go shift FAC2 right else FAC2 > FAC1 |
ARG HAS SMALLER EXPONENT |
||
.,B881 84 61 STY $61 |
STY FACEXP ;RESULTING EXPONENT. |
FAC-Exponent durch ARG-Vorzeichen ersetzen |
save FAC1 exponent |
EXP HAS SMALLER EXPONENT |
||
.,B883 A4 6E LDY $6E |
LDY ARGSGN ;SINCE ARG IS BIGGER, IT'S |
FAC-Vorzeichen durch |
get FAC2 sign (b7) |
|||
.,B885 84 66 STY $66 |
STY FACSGN ;SIGN IS SIGN OF RESULT. |
ARG-Vorzeichen ersetzen |
save FAC1 sign (b7) |
|||
.,B887 49 FF EOR #$FF |
EORI 377 ;SHIFT A NEGATIVE NUMBER OF PLACES. |
Vorzeichen wechseln |
complement A |
COMPLEMENT SHIFT COUNT |
||
.,B889 69 00 ADC #$00 |
ADCI 0 ;COMPLETE NEGATION. W/ C=1. |
Carry ist schon 1 |
+1, twos complement, carry is set |
CARRY WAS SET |
||
.,B88B A0 00 LDY #$00 |
LDYI 0 ;ZERO OLDOV. |
Rundungsstelle |
clear Y |
|||
.,B88D 84 56 STY $56 |
STY OLDOV |
löschen |
clear FAC2 rounding byte |
|||
.,B88F A2 61 LDX #$61 |
LDXI FAC ;SHIFT THE FAC INSTEAD. |
Offset-Zeiger für FAC laden |
set index to FAC1 exponent address |
SET UP TO SHIFT FAC |
||
.,B891 D0 04 BNE $B897 |
BNE FADD1 |
unbedingter Sprung |
branch always FAC2 < FAC1 |
...ALWAYS |
||
.,B893 A0 00 LDY #$00 |
FADDA: LDYI 0 |
FAC-Rundungsstelle |
clear Y |
|||
.,B895 84 70 STY $70 |
STY FACOV |
löschen |
clear FAC1 rounding byte |
|||
.,B897 C9 F9 CMP #$F9 |
FADD1: CMPI ^D256-7 ;FOR SPEED AND NECESSITY. GETS ;MOST LIKELY CASE TO SHIFTR FASTEST ;AND ALLOWS SHIFTING OF NEG NUMS ;BY "QINT". |
wenn Exponentdifferenz |
compare exponent diff with $F9 |
SHIFT MORE THAN 7 BITS? |
||
.,B899 30 C7 BMI $B862 |
BMI FADD5 ;SHIFT BIG. |
größer als 7, dann zu $B862 |
branch if range $79-$F8 |
YES |
||
.,B89B A8 TAY |
TAY |
Akku löschen |
copy exponent difference to Y |
INDEX TO # OF SHIFTS |
||
.,B89C A5 70 LDA $70 |
LDA FACOV ;SET FACOV. |
FAC-Rundungsstelle |
get FAC1 rounding byte |
|||
.,B89E 56 01 LSR $01,X |
LSR 1,X, ;GETS 0 IN MOST SIG BIT. |
laden |
shift FAC? mantissa 1 |
START SHIFTING... |
||
.,B8A0 20 B0 B9 JSR $B9B0 |
JSR ROLSHF ;DO THE ROLLING. |
Mantisse verschieben |
shift FACX Y times right exponents are equal now do mantissa subtract |
...COMPLETE SHIFTING |
||
.,B8A3 24 6F BIT $6F |
FADD4: BIT ARISGN ;GET RESULTING SIGN. |
wenn FAC- und ARG-Vorzeichen |
test sign compare (FAC1 EOR FAC2) |
DO FAC AND ARG HAVE SAME SIGNS? |
||
.,B8A5 10 57 BPL $B8FE |
BPL FADD2 ;IF POSITIVE, ADD. ;CARRY IS CLEAR. |
identisch, dann zu $B8FE |
if = add FAC2 mantissa to FAC1 mantissa and return |
YES, ADD THE MANTISSAS |
||
.,B8A7 A0 61 LDY #$61 |
FADD3: LDYI FACEXP |
Offset-Zeiger für FAC laden |
set the Y index to FAC1 exponent address |
NO, SUBTRACT SMALLER FROM LARGER |
||
.,B8A9 E0 69 CPX #$69 |
CPXI ARGEXP ;FAC IS BIGGER. |
wenn Offset-Zeiger für ARG |
compare X to FAC2 exponent address |
WHICH WAS ADJUSTED? |
||
.,B8AB F0 02 BEQ $B8AF |
BEQ SUBIT |
initialisiert, dann zu $B8AF |
if = continue, Y = FAC1, X = FAC2 |
IF ARG, DO FAC-ARG |
||
.,B8AD A0 69 LDY #$69 |
LDYI ARGEXP ;ARG IS BIGGER. |
Offset-Zeiger laden |
else set the Y index to FAC2 exponent address subtract the smaller from the bigger (take the sign of the bigger) |
IF FAC, DO ARG-FAC |
||
.,B8AF 38 SEC |
SUBIT: SEC |
Carryflag für Subtraktion setzen |
set carry for subtract |
SUBTRACT SMALLER FROM LARGER (WE HOPE) |
||
.,B8B0 49 FF EOR #$FF |
EORI 377 |
Alle Bits umdrehen |
ones complement A |
(IF EXPONENTS WERE EQUAL, WE MIGHT BE |
||
.,B8B2 65 56 ADC $56 |
ADC OLDOV |
Rundungsstelle addieren |
add FAC2 rounding byte |
SUBTRACTING LARGER FROM SMALLER) |
||
.,B8B4 85 70 STA $70 |
STA FACOV |
und speichern |
save FAC1 rounding byte |
|||
.,B8B6 B9 04 00 LDA $0004,Y |
LDA 3+ADDPRC,Y |
viertes Byte |
get FACY mantissa 4 |
|||
.,B8B9 F5 04 SBC $04,X |
SBC 3+ADDPRC,X |
subtrahieren und in |
subtract FACX mantissa 4 |
|||
.,B8BB 85 65 STA $65 |
STA FACLO |
FAC speichern |
save FAC1 mantissa 4 |
|||
.,B8BD B9 03 00 LDA $0003,Y |
LDA 2+ADDPRC,Y |
drittes Byte |
get FACY mantissa 3 |
|||
.,B8C0 F5 03 SBC $03,X |
SBC 2+ADDPRC,X |
subtrahieren und in |
subtract FACX mantissa 3 |
|||
.,B8C2 85 64 STA $64 |
STA FACMO IFN ADDPRC,< |
FAC speichern |
save FAC1 mantissa 3 |
|||
.,B8C4 B9 02 00 LDA $0002,Y |
LDA 2,Y |
zweites Byte |
get FACY mantissa 2 |
|||
.,B8C7 F5 02 SBC $02,X |
SBC 2,X |
subtrahieren und in |
subtract FACX mantissa 2 |
|||
.,B8C9 85 63 STA $63 |
STA FACMOH> |
FAC speichern |
save FAC1 mantissa 2 |
|||
.,B8CB B9 01 00 LDA $0001,Y |
LDA 1,Y |
erstes Byte |
get FACY mantissa 1 |
|||
.,B8CE F5 01 SBC $01,X |
SBC 1,X |
subtrahieren und in |
subtract FACX mantissa 1 |
|||
.,B8D0 85 62 STA $62 |
STA FACHO |
FAC speichern |
save FAC1 mantissa 1do ABS and normalise FAC1 |
NORMALIZE VALUE IN FAC |
||
.,B8D2 B0 03 BCS $B8D7 |
FADFLT: BCS NORMAL ;HERE IF SIGNS DIFFER. IF CARRY, ;FAC IS SET OK. |
wenn Übertrag negativ, dann weiter |
branch if number is +ve |
|||
.,B8D4 20 47 B9 JSR $B947 |
JSR NEGFAC ;NEGATE [FAC]. |
Mantisse von FAC invertieren |
negate FAC1normalise FAC1 |
|||
.,B8D7 A0 00 LDY #$00 |
NORMAL: LDYI 0 |
Y-Reg und |
clear Y |
SHIFT UP SIGNIF DIGIT |
||
.,B8D9 98 TYA |
TYA |
Akku löschen |
clear A |
START A=0, COUNT SHIFTS IN A-REG |
||
.,B8DA 18 CLC |
CLC |
Carry löschen |
clear carry for add |
|||
.,B8DB A6 62 LDX $62 |
NORM3: LDX FACHO |
wenn $62=0 dann, |
get FAC1 mantissa 1 |
LOOK AT MOST SIGNIFICANT BYTE |
||
.,B8DD D0 4A BNE $B929 |
BNE NORM1 |
zu $B929 |
if not zero normalise FAC1 |
SOME 1-BITS HERE |
||
.,B8DF A6 63 LDX $63 |
LDX FACHO+1 ;SHIFT 8 BITS AT A TIME FOR SPEED. |
Das |
get FAC1 mantissa 2 |
HI-BYTE OF MANTISSA STILL ZERO, |
||
.,B8E1 86 62 STX $62 |
STX FACHO IFN ADDPRC,< |
gesamte |
save FAC1 mantissa 1 |
SO DO A FAST 8-BIT SHUFFLE |
||
.,B8E3 A6 64 LDX $64 |
LDX FACMOH+1 |
FAC |
get FAC1 mantissa 3 |
|||
.,B8E5 86 63 STX $63 |
STX FACMOH> |
wieder |
save FAC1 mantissa 2 |
|||
.,B8E7 A6 65 LDX $65 |
LDX FACMO+1 |
norma- |
get FAC1 mantissa 4 |
|||
.,B8E9 86 64 STX $64 |
STX FACMO |
lisieren |
save FAC1 mantissa 3 |
|||
.,B8EB A6 70 LDX $70 |
LDX FACOV |
Rundungsstelle |
get FAC1 rounding byte |
|||
.,B8ED 86 65 STX $65 |
STX FACLO |
wieder |
save FAC1 mantissa 4 |
|||
.,B8EF 84 70 STY $70 |
STY FACOV |
löschen |
clear FAC1 rounding byte |
ZERO EXTENSION BYTE |
||
.,B8F1 69 08 ADC #$08 |
ADCI 10 |
Zähler um 8 Bits verschieben |
add x to exponent offset |
BUMP SHIFT COUNT |
||
.,B8F3 C9 20 CMP #$20 |
CMPI 10*ADDPRC+30 |
wenn 32 Bits verschoben, |
compare with $20, max offset, all bits would be = 0 |
DONE 4 TIMES YET? |
||
.,B8F5 D0 E4 BNE $B8DB |
BNE NORM3 |
dann weiter |
loop if not maxclear FAC1 exponent and sign |
NO, STILL MIGHT BE SOME 1'S YES, VALUE OF FAC IS ZERO SET FAC = 0(ONLY NECESSARY TO ZERO EXPONENT AND SIGN CELLS) |
||
.,B8F7 A9 00 LDA #$00 |
ZEROFC: LDAI 0 ;NOT NEED BY NORMAL BUT BY OTHERS. |
Mantisse =0 |
clear A |
|||
.,B8F9 85 61 STA $61 |
ZEROF1: STA FACEXP ;NUMBER MUST BE ZERO. |
FAC =0 |
set FAC1 exponentsave FAC1 sign |
|||
.,B8FB 85 66 STA $66 |
ZEROML: STA FACSGN ;MAKE SIGN POSITIVE. |
Exponent =0 |
save FAC1 sign (b7) |
|||
.,B8FD 60 RTS |
RTS ;ALL DONE. |
Rücksprung |
add FAC2 mantissa to FAC1 mantissa |
ADD MANTISSAS OF FAC AND ARG INTO FAC |
add fractions |
|
.,B8FE 65 56 ADC $56 |
FADD2: ADC OLDOV |
Rundungsstelle addieren |
add FAC2 rounding byte |
|||
.,B900 85 70 STA $70 |
STA FACOV |
und speichern |
save FAC1 rounding byte |
|||
.,B902 A5 65 LDA $65 |
LDA FACLO |
FAC |
get FAC1 mantissa 4 |
|||
.,B904 65 6D ADC $6D |
ADC ARGLO |
und ARG |
add FAC2 mantissa 4 |
|||
.,B906 85 65 STA $65 |
STA FACLO |
addieren |
save FAC1 mantissa 4 |
|||
.,B908 A5 64 LDA $64 |
LDA FACMO |
FAC |
get FAC1 mantissa 3 |
|||
.,B90A 65 6C ADC $6C |
ADC ARGMO |
und ARG |
add FAC2 mantissa 3 |
|||
.,B90C 85 64 STA $64 |
STA FACMO IFN ADDPRC,< |
addieren |
save FAC1 mantissa 3 |
|||
.,B90E A5 63 LDA $63 |
LDA FACMOH |
FAC |
get FAC1 mantissa 2 |
|||
.,B910 65 6B ADC $6B |
ADC ARGMOH |
und ARG |
add FAC2 mantissa 2 |
|||
.,B912 85 63 STA $63 |
STA FACMOH> |
addieren |
save FAC1 mantissa 2 |
|||
.,B914 A5 62 LDA $62 |
LDA FACHO |
FAC |
get FAC1 mantissa 1 |
|||
.,B916 65 6A ADC $6A |
ADC ARGHO |
und ARG |
add FAC2 mantissa 1 |
|||
.,B918 85 62 STA $62 |
STA FACHO |
addieren |
save FAC1 mantissa 1 |
|||
.,B91A 4C 36 B9 JMP $B936 |
JMP SQUEEZ ;GO ROUND IF SIGNS SAME. |
Überlaufbit in Mantisse zurückshiften |
test and normalise FAC1 for C=0/1 |
FINISH NORMALIZING FAC |
postshift |
|
.,B91D 69 01 ADC #$01 |
NORM2: ADCI 1 ;DECREMENT SHIFT COUNT. |
Zähler erhöhen |
add 1 to exponent offset |
COUNT BITS SHIFTED |
||
.,B91F 06 70 ASL $70 |
ASL FACOV ;SHIFT ALL LEFT ONE BIT. |
FAC solange |
shift FAC1 rounding byte |
|||
.,B921 26 65 ROL $65 |
ROL FACLO |
nach links |
shift FAC1 mantissa 4 |
|||
.,B923 26 64 ROL $64 |
ROL FACMO IFN ADDPRC,< |
verschieben bis das |
shift FAC1 mantissa 3 |
|||
.,B925 26 63 ROL $63 |
ROL FACMOH> |
Bit 7 |
shift FAC1 mantissa 2 |
|||
.,B927 26 62 ROL $62 |
ROL FACHO |
gesetzt ist |
shift FAC1 mantissa 1 normalise FAC1 |
|||
.,B929 10 F2 BPL $B91D |
NORM1: BPL NORM2 ;IF MSB=0 SHIFT AGAIN. |
nicht gesetzt ? dann nochmal |
loop if not normalised |
UNTIL TOP BIT = 1 |
||
.,B92B 38 SEC |
SEC |
wenn Binärexponent kleiner |
set carry for subtract |
|||
.,B92C E5 61 SBC $61 |
SBC FACEXP |
als die Anzahl der |
subtract FAC1 exponent |
ADJUST EXPONENT BY BITS SHIFTED |
||
.,B92E B0 C7 BCS $B8F7 |
BCS ZEROFC |
Verschiebungen, dann wird die Zahl als Null behandelt |
branch if underflow (set result = $0) |
UNDERFLOW, RETURN ZERO |
||
.,B930 49 FF EOR #$FF |
EORI 377 |
Exponent um |
complement exponent |
|||
.,B932 69 01 ADC #$01 |
ADCI 1 ;COMPLEMENT. |
Verschiebungsanzahl |
+1 (twos complement) |
2'S COMPLEMENT |
||
.,B934 85 61 STA $61 |
STA FACEXP |
vermindern |
save FAC1 exponent test and normalise FAC1 for C=0/1 |
CARRY=0 NOW |
||
.,B936 90 0E BCC $B946 |
SQUEEZ: BCC RNDRTS ;BITS TO SHIFT? |
Carry gesetzt, nein dann RTS |
exit if no overflow normalise FAC1 for C=1 |
UNLESS MANTISSA CARRIED |
||
.,B938 E6 61 INC $61 |
RNDSHF: INC FACEXP |
Exponent erhöhen |
increment FAC1 exponent |
MANTISSA CARRIED, SO SHIFT RIGHT |
||
.,B93A F0 42 BEQ $B97E |
BEQ OVERR |
wenn Überlauf in Exponent, dann 'OVERFLOW ERROR' |
if zero do overflow error then warm start |
OVERFLOW IF EXPONENT TOO BIG |
||
.,B93C 66 62 ROR $62 |
ROR FACHO IFN ADDPRC,< |
Überlaufbit in Carry schieben |
shift FAC1 mantissa 1 |
|||
.,B93E 66 63 ROR $63 |
ROR FACMOH> |
Das Carry-Flag |
shift FAC1 mantissa 2 |
|||
.,B940 66 64 ROR $64 |
ROR FACMO |
erhält die |
shift FAC1 mantissa 3 |
|||
.,B942 66 65 ROR $65 |
ROR FACLO |
Position des |
shift FAC1 mantissa 4 |
|||
.,B944 66 70 ROR $70 |
ROR FACOV |
höchstwertigen Bits |
shift FAC1 rounding byte |
|||
.,B946 60 RTS |
RNDRTS: RTS ;ALL DONE ADDING. |
RücksprungMantisse von FAC invertieren |
negate FAC1 |
2'S COMPLEMENT OF FAC |
negate float accu |
|
.,B947 A5 66 LDA $66 |
NEGFAC: COM FACSGN ;COMPLEMENT FAC ENTIRELY. |
FAC Vorzeichen |
get FAC1 sign (b7) |
|||
.,B949 49 FF EOR #$FF |
invertieren |
complement it |
||||
.,B94B 85 66 STA $66 |
und speichern |
save FAC1 sign (b7) twos complement FAC1 mantissa |
2'S COMPLEMENT OF FAC MANTISSA ONLY |
|||
.,B94D A5 62 LDA $62 |
NEGFCH: COM FACHO ;COMPLEMENT JUST THE NUMBER. |
FAC |
get FAC1 mantissa 1 |
|||
.,B94F 49 FF EOR #$FF |
invertieren |
complement it |
||||
.,B951 85 62 STA $62 |
IFN ADDPRC,< |
und speichern |
save FAC1 mantissa 1 |
|||
.,B953 A5 63 LDA $63 |
COM FACMOH> |
FAC |
get FAC1 mantissa 2 |
|||
.,B955 49 FF EOR #$FF |
invertieren |
complement it |
||||
.,B957 85 63 STA $63 |
und speichern |
save FAC1 mantissa 2 |
||||
.,B959 A5 64 LDA $64 |
COM FACMO |
FAC |
get FAC1 mantissa 3 |
|||
.,B95B 49 FF EOR #$FF |
invertieren |
complement it |
||||
.,B95D 85 64 STA $64 |
und speichern |
save FAC1 mantissa 3 |
||||
.,B95F A5 65 LDA $65 |
COM FACLO |
FAC |
get FAC1 mantissa 4 |
|||
.,B961 49 FF EOR #$FF |
invertieren |
complement it |
||||
.,B963 85 65 STA $65 |
und speichern |
save FAC1 mantissa 4 |
||||
.,B965 A5 70 LDA $70 |
COM FACOV |
FAC-Rundungsbyte |
get FAC1 rounding byte |
|||
.,B967 49 FF EOR #$FF |
invertieren |
complement it |
||||
.,B969 85 70 STA $70 |
und speichern |
save FAC1 rounding byte |
||||
.,B96B E6 70 INC $70 |
INC FACOV |
Mantisse erhöhen |
increment FAC1 rounding byte |
START INCREMENTING MANTISSA |
||
.,B96D D0 0E BNE $B97D |
BNE INCFRT |
nicht Null? dann RTS |
exit if no overflow increment FAC1 mantissa |
INCREMENT FAC MANTISSA |
increment fraction |
|
.,B96F E6 65 INC $65 |
INCFAC: INC FACLO |
FAC erhöhen |
increment FAC1 mantissa 4 |
ADD CARRY FROM EXTRA |
||
.,B971 D0 0A BNE $B97D |
BNE INCFRT |
nicht Null? dann RTS |
finished if no rollover |
|||
.,B973 E6 64 INC $64 |
INC FACMO |
FAC erhöhen |
increment FAC1 mantissa 3 |
|||
.,B975 D0 06 BNE $B97D |
BNE INCFRT ;IF NO CARRY, RETURN. IFN ADDPRC,< |
nicht Null? dann RTS |
finished if no rollover |
|||
.,B977 E6 63 INC $63 |
INC FACMOH |
FAC erhöhen |
increment FAC1 mantissa 2 |
|||
.,B979 D0 02 BNE $B97D |
BNE INCFRT> |
nicht Null? dann RTS |
finished if no rollover |
|||
.,B97B E6 62 INC $62 |
INC FACHO ;CARRY INCREMENT. |
FAC erhöhen |
increment FAC1 mantissa 1 |
|||
.,B97D 60 RTS |
INCFRT: RTS |
Rücksprung |
do overflow error then warm start |
|||
.,B97E A2 0F LDX #$0F |
OVERR: LDXI ERROV |
Nummer für 'OVERFLOW' |
error $0F, overflow error |
error number |
||
.,B980 4C 37 A4 JMP $A437 |
JMP ERROR ;TELL USER. ; ; "SHIFTR" SHIFTS [X+1:X+3] [-ACCA] BITS RIGHT. ; SHIFTS BYTES TO START WITH IF POSSIBLE. ; |
Fehlermeldung ausgebenRechtsverschieben einesRegisters |
do error #X then warm startshift FCAtemp << A+8 times |
SHIFT 1,X THRU 5,X RIGHT(A) = NEGATIVE OF SHIFT COUNT(X) = POINTER TO BYTES TO BE SHIFTED RETURN WITH (Y)=0, CARRY=0, EXTENSION BITS IN A-REG |
preshift |
|
.,B983 A2 25 LDX #$25 |
MULSHF: LDXI RESHO-1 ;ENTRY POINT FOR MULTIPLIER. |
Offset-Zeiger auf Register |
set the offset to FACtemp |
SHIFT RESULT RIGHT |
||
.,B985 B4 04 LDY $04,X |
SHFTR2: LDY 3+ADDPRC,X, ;SHIFT BYTES FIRST. |
FAC- |
get FACX mantissa 4 |
SHIFT 8 BITS RIGHT |
||
.,B987 84 70 STY $70 |
STY FACOV IFN ADDPRC,< |
Rundungsbyte |
save as FAC1 rounding byte |
|||
.,B989 B4 03 LDY $03,X |
LDY 3,X |
1 mal |
get FACX mantissa 3 |
|||
.,B98B 94 04 STY $04,X |
STY 4,X> |
verschieben |
save FACX mantissa 4 |
|||
.,B98D B4 02 LDY $02,X |
LDY 2,X, ;GET MO. |
2 mal |
get FACX mantissa 2 |
|||
.,B98F 94 03 STY $03,X |
STY 3,X, ;STORE LO. |
verschieben |
save FACX mantissa 3 |
|||
.,B991 B4 01 LDY $01,X |
LDY 1,X, ;GET HO. |
3 mal |
get FACX mantissa 1 |
|||
.,B993 94 02 STY $02,X |
STY 2,X, ;STORE MO. |
verschieben |
save FACX mantissa 2 |
|||
.,B995 A4 68 LDY $68 |
LDY BITS |
FAC- |
get FAC1 overflow byte |
$00 IF +, $FF IF - |
||
.,B997 94 01 STY $01,X |
STY 1,X, ;STORE HO. |
Rundungsbyte |
save FACX mantissa 1 shift FACX -A times right (> 8 shifts) |
MAIN ENTRY TO RIGHT SHIFT SUBROUTINE |
||
.,B999 69 08 ADC #$08 |
SHIFTR: ADCI 10 |
Zähler um 8 erhöhen |
add 8 to shift count |
|||
.,B99B 30 E8 BMI $B985 |
BMI SHFTR2 |
größer als 0? |
go do 8 shift if still -ve |
STILL MORE THAN 8 BITS TO GO |
||
.,B99D F0 E6 BEQ $B985 |
BEQ SHFTR2 |
wenn nicht, dann weiter verschieben |
go do 8 shift if zero |
EXACTLY 8 MORE BITS TO GO |
||
.,B99F E9 08 SBC #$08 |
SBCI 10 ;C CAN BE EITHER 1,0 AND IT WORKS. |
Zähler um 8 vermindern |
else subtract 8 again |
UNDO ADC ABOVE |
||
.,B9A1 A8 TAY |
TAY |
Zähler sichern |
save count to Y |
REMAINING SHIFT COUNT |
||
.,B9A2 A5 70 LDA $70 |
LDA FACOV |
FAC-Rundungsbyte laden |
get FAC1 rounding byte |
|||
.,B9A4 B0 14 BCS $B9BA |
BCS SHFTRT ;EQUIV TO BEQ HERE. IFN RORSW,< |
wenn Null, dann CLC, RTS |
FINISHED SHIFTING |
|||
.,B9A6 16 01 ASL $01,X |
SHFTR3: ASL 1,X |
höchstwertiges Bit =1?, |
shift FACX mantissa 1 |
SIGN -> CARRY (SIGN EXTENSION) |
||
.,B9A8 90 02 BCC $B9AC |
BCC SHFTR4 |
wenn nicht, dann zu $B9AC |
branch if +ve |
SIGN + |
||
.,B9AA F6 01 INC $01,X |
INC 1,X |
höchste Mantissenstelle erhöhen |
this sets b7 eventually |
PUT SIGN IN LSB |
||
.,B9AC 76 01 ROR $01,X |
SHFTR4: ROR 1,X |
sämtliche |
shift FACX mantissa 1 (correct for ASL) |
RESTORE VALUE, SIGN STILL IN CARRY |
||
.,B9AE 76 01 ROR $01,X |
ROR 1,X> ;YES, TWO OF THEM. IFE RORSW,< SHFTR3: PHA LDA 1,X ANDI 200 LSR 1,X ORA 1,X STA 1,X SKIP1> ROLSHF: IFN RORSW,< |
Stellen |
shift FACX mantissa 1 (put carry in b7) shift FACX Y times right |
START RIGHT SHIFT, INSERTING SIGNENTER HERE FOR SHORT SHIFTS WITH NO SIGN EXTENSION |
||
.,B9B0 76 02 ROR $02,X |
ROR 2,X |
um ein |
shift FACX mantissa 2 |
|||
.,B9B2 76 03 ROR $03,X |
ROR 3,X |
Bit nach |
shift FACX mantissa 3 |
|||
.,B9B4 76 04 ROR $04,X |
IFN ADDPRC,< ROR 4,X> ;ONE MO TIME. > IFE RORSW,< PHA LDAI 0 BCC SHFTR5 LDAI 200 SHFTR5: LSR 2,X ORA 2,X STA 2,X LDAI 0 BCC SHFTR6 LDAI 200 SHFTR6: LSR 3,X ORA 3,X STA 3,X IFN ADDPRC,< LDAI 0 BCC SHFT6A LDAI 200 SHFT6A: LSR 4,X ORA 4,X STA 4,X>> |
rechts |
shift FACX mantissa 4 |
|||
.,B9B6 6A ROR |
IFN RORSW,<ROR A,> ;ROTATE ARGUMENT 1 BIT RIGHT. IFE RORSW,< PLA PHP LSR A, PLP BCC SHFTR7 ORAI 200> |
verschieben |
shift FACX rounding byte |
EXTENSION |
||
.,B9B7 C8 INY |
SHFTR7: INY |
Zähler um eins erhöhen |
increment exponent diff |
COUNT THE SHIFT |
||
.,B9B8 D0 EC BNE $B9A6 |
BNE SHFTR3 ;$$$ ( MOST EXPENSIVE ! ) |
verschieben bis Zähler =0 |
branch if range adjust not complete |
|||
.,B9BA 18 CLC |
SHFTRT: CLC ;CLEAR OUTPUT OF FACOV. |
Carry löschen |
just clear it |
RETURN WITH CARRY CLEAR |
||
.,B9BB 60 RTS |
RTS PAGE NATURAL LOG FUNCTION.;; CALCULATION IS BY: ; LN(F*2^N)=(N+LOG2(F))*LN(2) ; AN APPROXIMATION POLYNOMIAL IS USED TO CALCULATE LOG2(F). ; CONSTANTS USED BY LOG: |
RücksprungKonstanten für LOG |
constants and series for LOG(n) |
1 |
||
.:B9BC 81 00 00 00 00 |
FONE: 201 ; 1.0 000 000 000 IFN ADDPRC,<0> IFE ADDPRC,< LOGCN2: 2 ; DEGREE-1 200 ; 0.59897437 031 126 142 200 ; 0.96147080 166 042 363 202 ; 2.88539129 070 252 100> IFN ADDPRC,< |
1 |
1 |
LOG polynomial table |
||
.:B9C1 03 |
LOGCN2: 3 ;DEGREE-1 |
3 = Polynomgrad, dann 4 Koeffizienten |
series counter |
# OF COEFFICIENTS - 1 |
degree 4 |
|
.:B9C2 7F 5E 56 CB 79 |
177 ;.43425594188 136 126 313 171 |
.434255942 |
.434255942 |
X^7 + |
||
.:B9C7 80 13 9B 0B 64 |
200 ; .57658454134 023 233 013 144 |
.576584541 |
.576584541 |
X^5 + |
||
.:B9CC 80 76 38 93 16 |
200 ; .96180075921 166 070 223 026 |
.961800759 |
.961800759 |
X^3 + |
||
.:B9D1 82 38 AA 3B 20 |
202 ; 2.8853900728 070 252 073 040> |
2.88539007 |
2.88539007 |
X |
0,5 * SQR(2) |
|
.:B9D6 80 35 04 F3 34 |
SQRHLF: 200 ; SQR(0.5) 065 004 363 IFN ADDPRC,<064> |
.707106781 = 1/SQR(2) |
.707106781 = 1/SQR(2) |
SQR(1/2) |
SQR(2) |
|
.:B9DB 81 35 04 F3 34 |
SQRTWO: 201 ; SQR(2.0) 065 004 363 IFN ADDPRC,<064> |
1.41421356 = SQR(2) |
1.41421356 = SQR(2) |
SQR(TWO) |
-0.5 |
|
.:B9E0 80 80 00 00 00 |
NEGHLF: 200 ; -1/2 200 000 000 IFN ADDPRC,<0> |
-.5 |
-.5 |
-1/2 |
LOG(2) |
|
.:B9E5 80 31 72 17 F8 |
LOG2: 200 ; LN(2) 061 162 IFE ADDPRC,<030> IFN ADDPRC,<027 370> |
.693147181 = LOG(2)BASIC-Funktion LOG |
.693147181 = LOG(2)perform LOG() |
LOG(2)"LOG" FUNCTION |
LOG function |
|
.,B9EA 20 2B BC JSR $BC2B |
LOG: JSR SIGN ;IS IT POSITIVE? |
Vorzeichen holen |
test sign and zero |
GET -1,0,+1 IN A-REG FOR FAC |
||
.,B9ED F0 02 BEQ $B9F1 |
BEQ LOGERR |
null ?, dann fertig |
if zero do illegal quantity error then warm start |
LOG (0) IS ILLEGAL |
||
.,B9EF 10 03 BPL $B9F4 |
BPL LOG1 |
positiv ?, dann ok |
skip error if +ve |
>0 IS OK |
||
.,B9F1 4C 48 B2 JMP $B248 |
LOGERR: JMP FCERR ;CAN'T TOLERATE NEG OR ZERO. |
'ILLEGAL QUANTITY' |
do illegal quantity error then warm start |
<= 0 IS NO GOOD |
||
.,B9F4 A5 61 LDA $61 |
LOG1: LDA FACEXP ;GET EXPONENT INTO ACCA. |
Exponent |
get FAC1 exponent |
FIRST GET LOG BASE 2 |
||
.,B9F6 E9 7F SBC #$7F |
SBCI 177 ;REMOVE BIAS. (CARRY IS OFF) |
normalisieren |
normalise it |
SAVE UNBIASED EXPONENT |
||
.,B9F8 48 PHA |
PHA ;SAVE AWHILE. |
und merken |
save it |
|||
.,B9F9 A9 80 LDA #$80 |
LDAI 200 |
Zahl in Bereich 0.5 bis 1 |
set exponent to zero |
NORMALIZE BETWEEN .5 AND 1 |
||
.,B9FB 85 61 STA $61 |
STA FACEXP ;RESULT IS FAC IN RANGE [0.5,1]. |
bringen |
save FAC1 exponent |
|||
.,B9FD A9 D6 LDA #$D6 |
LDWDI SQRHLF ;GET POINTER TO SQR(0.5). |
Zeiger auf |
pointer to 1/root 2 low byte |
low B9D6 |
||
.,B9FF A0 B9 LDY #$B9 |
; CALCULATE (F-SQR(.5))/(F+SQR(.5)) |
Konstante 1/SQR(2) |
pointer to 1/root 2 high byte |
high B9D6 |
||
.,BA01 20 67 B8 JSR $B867 |
JSR FADD ;ADD TO FAC. |
zu FAC addieren |
add (AY) to FAC1 (1/root2) |
COMPUTE VIA SERIES OF ODD |
||
.,BA04 A9 DB LDA #$DB |
LDWDI SQRTWO ;GET SQR(2.). |
Zeiger auf |
pointer to root 2 low byte |
POWERS OF |
low B9DB |
|
.,BA06 A0 B9 LDY #$B9 |
Konstante SQR(2) |
pointer to root 2 high byte |
(SQR(2)X-1)/(SQR(2)X+1) |
high B9DB |
||
.,BA08 20 0F BB JSR $BB0F |
JSR FDIV |
SQR(2) durch FAC dividieren |
convert AY and do (AY)/FAC1 (root2/(x+(1/root2))) |
|||
.,BA0B A9 BC LDA #$BC |
LDWDI FONE |
Zeiger |
pointer to 1 low byte |
low B9BC |
||
.,BA0D A0 B9 LDY #$B9 |
auf Konstante 1 |
pointer to 1 high byte |
high B9BC |
|||
.,BA0F 20 50 B8 JSR $B850 |
JSR FSUB |
1 minus FAC |
subtract FAC1 ((root2/(x+(1/root2)))-1) from (AY) |
|||
.,BA12 A9 C1 LDA #$C1 |
LDWDI LOGCN2 |
Zeiger auf |
pointer to series for LOG(n) low byte |
low B9C1 |
||
.,BA14 A0 B9 LDY #$B9 |
Polynomkoeffizienten |
pointer to series for LOG(n) high byte |
high B9C1 |
|||
.,BA16 20 43 E0 JSR $E043 |
JSR POLYX ;EVALUATE APPROXIMATION POLYNOMIAL. |
Polynomberechnung |
^2 then series evaluation |
|||
.,BA19 A9 E0 LDA #$E0 |
LDWDI NEGHLF ;ADD IN LAST CONSTANT. |
Zeiger auf |
pointer to -0.5 low byte |
low B9E0 |
||
.,BA1B A0 B9 LDY #$B9 |
Konstante -0.5 |
pointer to -0.5 high byte |
high B9E0 |
|||
.,BA1D 20 67 B8 JSR $B867 |
JSR FADD |
zu FAC addieren |
add (AY) to FAC1 |
|||
.,BA20 68 PLA |
PLA ;GET EXPONENT BACK. |
Exponent zurückholen |
restore FAC1 exponent |
|||
.,BA21 20 7E BD JSR $BD7E |
JSR FINLOG ;ADD IT IN. |
FAC = FAC + FAC |
evaluate new ASCII digit |
ADD ORIGINAL EXPONENT |
||
.,BA24 A9 E5 LDA #$E5 |
MULLN2: LDWDI LOG2 ;MULTIPLY RESULT BY LOG(2.0). |
Zeiger auf |
pointer to LOG(2) low byte |
MULTIPLY BY LOG(2) TO FORM |
low B9E5 |
|
.,BA26 A0 B9 LDY #$B9 |
; JMP FMULT ;MULTIPLY TOGETHER. PAGE FLOATING MULTIPLICATION AND DIVISION.;MULTIPLICATION FAC:=ARG*FAC. |
Konstante LOG(2)Multiplikation FAC =Konstante (A/Y) * FAC |
pointer to LOG(2) high bytedo convert AY, FCA1*(AY) |
NATURAL LOG OF XFAC = (Y,A) * FAC |
high B9E5 |
|
.,BA28 20 8C BA JSR $BA8C |
FMULT: JSR CONUPK ;UNPACK THE CONSTANT INTO ARG FOR USE. |
Konstante nach ARGMultiplikation FAC = ARG *FAC |
unpack memory (AY) into FAC2 |
FAC = ARG * FAC |
times operator |
|
.,BA2B D0 03 BNE $BA30 |
FMULTT: JEQ MULTRT ;IF FAC=0, RETURN. FAC IS SET. |
nicht null ? |
multiply FAC1 by FAC2 ?? |
FAC .NE. ZERO |
||
.,BA2D 4C 8B BA JMP $BA8B |
RTS |
exit if zero |
FAC = 0 * ARG = 0 |
|||
.,BA30 20 B7 BA JSR $BAB7 |
JSR MULDIV ;FIX UP THE EXPONENTS. |
Exponent berechnen |
test and adjust accumulators |
|||
.,BA33 A9 00 LDA #$00 |
LDAI 0 ;TO CLEAR RESULT. |
Alle |
clear A |
|||
.,BA35 85 26 STA $26 |
STA RESHO IFN ADDPRC,< |
Funktions- |
clear temp mantissa 1 |
INIT PRODUCT = 0 |
||
.,BA37 85 27 STA $27 |
STA RESMOH> |
register |
clear temp mantissa 2 |
|||
.,BA39 85 28 STA $28 |
STA RESMO |
lö- |
clear temp mantissa 3 |
|||
.,BA3B 85 29 STA $29 |
STA RESLO |
schen |
clear temp mantissa 4 |
|||
.,BA3D A5 70 LDA $70 |
LDA FACOV |
bitweise |
get FAC1 rounding byte |
|||
.,BA3F 20 59 BA JSR $BA59 |
JSR MLTPLY |
Multiplikation |
go do shift/add FAC2 |
|||
.,BA42 A5 65 LDA $65 |
LDA FACLO ;MLTPLY ARG BY FACLO. |
bitweise |
get FAC1 mantissa 4 |
|||
.,BA44 20 59 BA JSR $BA59 |
JSR MLTPLY |
Multiplikation |
go do shift/add FAC2 |
|||
.,BA47 A5 64 LDA $64 |
LDA FACMO ;MLTPLY ARG BY FACMO. |
bitweise |
get FAC1 mantissa 3 |
|||
.,BA49 20 59 BA JSR $BA59 |
JSR MLTPLY IFN ADDPRC,< |
Multiplikation |
go do shift/add FAC2 |
|||
.,BA4C A5 63 LDA $63 |
LDA FACMOH |
bitweise |
get FAC1 mantissa 2 |
|||
.,BA4E 20 59 BA JSR $BA59 |
JSR MLTPLY> |
Multiplikation |
go do shift/add FAC2 |
|||
.,BA51 A5 62 LDA $62 |
LDA FACHO ;MLTPLY ARG BY FACHO. |
bitweise |
get FAC1 mantissa 1 |
|||
.,BA53 20 5E BA JSR $BA5E |
JSR MLTPL1 |
Multiplikation Register nach FAC, linksbündig machen |
go do shift/add FAC2 |
|||
.,BA56 4C 8F BB JMP $BB8F |
JMP MOVFR ;MOVE RESULT INTO FAC, ;NORMALIZE RESULT, AND RETURN. |
bitweise Multiplikation |
copy temp to FAC1, normalise and return |
MULTIPLY ARG BY (A) INTO RESULT |
||
.,BA59 D0 03 BNE $BA5E |
MLTPLY: JEQ MULSHF ;SHIFT RESULT RIGHT 1 BYTE. |
Rechtsverschieben |
branch if byte <> zero |
THIS BYTE NON-ZERO |
||
.,BA5B 4C 83 B9 JMP $B983 |
des Registers |
shift FCAtemp << A+8 times else do shift and add |
(A)=0, JUST SHIFT ARG RIGHT 8 |
|||
.,BA5E 4A LSR |
MLTPL1: LSR A, |
binäre Multiplikation |
shift byte |
SHIFT BIT INTO CARRY |
||
.,BA5F 09 80 ORA #$80 |
ORAI 200 |
des Akkus |
set top bit (mark for 8 times) |
SUPPLY SENTINEL BIT |
||
.,BA61 A8 TAY |
MLTPL2: TAY |
mit ARG. |
copy result |
REMAINING MULTIPLIER TO Y |
||
.,BA62 90 19 BCC $BA7D |
BCC MLTPL3 ;IT MULT BIT=0, JUST SHIFT. |
Das Ergebnis kommt |
skip next if bit was zero |
THIS MULTIPLIER BIT = 0 |
||
.,BA64 18 CLC |
CLC |
in das |
clear carry for add |
= 1, SO ADD ARG TO RESULT |
||
.,BA65 A5 29 LDA $29 |
LDA RESLO |
Register für |
get temp mantissa 4 |
|||
.,BA67 65 6D ADC $6D |
ADC ARGLO |
Funktionen. |
add FAC2 mantissa 4 |
|||
.,BA69 85 29 STA $29 |
STA RESLO |
Bei gesetztem Bit |
save temp mantissa 4 |
|||
.,BA6B A5 28 LDA $28 |
LDA RESMO |
im Akku |
get temp mantissa 3 |
|||
.,BA6D 65 6C ADC $6C |
ADC ARGMO |
wird ARG |
add FAC2 mantissa 3 |
|||
.,BA6F 85 28 STA $28 |
STA RESMO IFN ADDPRC,< |
zum |
save temp mantissa 3 |
|||
.,BA71 A5 27 LDA $27 |
LDA RESMOH |
Funktionsregister |
get temp mantissa 2 |
|||
.,BA73 65 6B ADC $6B |
ADC ARGMOH |
addiert. |
add FAC2 mantissa 2 |
|||
.,BA75 85 27 STA $27 |
STA RESMOH> |
Zusätzlich |
save temp mantissa 2 |
|||
.,BA77 A5 26 LDA $26 |
LDA RESHO |
werden |
get temp mantissa 1 |
|||
.,BA79 65 6A ADC $6A |
ADC ARGHO |
die |
add FAC2 mantissa 1 |
|||
.,BA7B 85 26 STA $26 |
STA RESHO |
Funktionsregister |
save temp mantissa 1 |
|||
.,BA7D 66 26 ROR $26 |
MLTPL3: ROR RESHO IFN ADDPRC,< |
noch |
shift temp mantissa 1 |
SHIFT RESULT RIGHT 1 |
||
.,BA7F 66 27 ROR $27 |
ROR RESMOH> |
verdoppelt. |
shift temp mantissa 2 |
|||
.,BA81 66 28 ROR $28 |
ROR RESMO |
Die Routine |
shift temp mantissa 3 |
|||
.,BA83 66 29 ROR $29 |
ROR RESLO |
arbeitet |
shift temp mantissa 4 |
|||
.,BA85 66 70 ROR $70 |
ROR FACOV ;SAVE FOR ROUNDING. |
im selben |
shift temp rounding byte |
|||
.,BA87 98 TYA |
TYA |
Prinzip |
get byte back |
REMAINING MULTIPLIER |
||
.,BA88 4A LSR |
LSR A, ;CLEAR MSB SO WE GET A CLOSER TO 0. |
wie |
shift byte |
LSB INTO CARRY |
||
.,BA89 D0 D6 BNE $BA61 |
BNE MLTPL2 ;SLOW AS A TURTLE ! |
bei $B34C. |
loop if all bits not done |
IF SENTINEL STILL HERE, MULTIPLY |
||
.,BA8B 60 RTS |
MULTRT: RTS ;ROUTINE TO UNPACK MEMORY INTO ARG. |
RücksprungARG = Konstante (A/Y) |
unpack memory (AY) into FAC2 |
8 X 32 COMPLETEDUNPACK NUMBER AT (Y,A) INTO ARG |
move float indexed by AY into second float accu |
|
.,BA8C 85 22 STA $22 |
CONUPK: STWD INDEX1 |
Die |
save pointer low byte |
USE INDEX FOR PNTR |
||
.,BA8E 84 23 STY $23 |
Konstante, |
save pointer high byte |
||||
.,BA90 A0 04 LDY #$04 |
LDYI 3+ADDPRC |
auf |
5 bytes to get (0-4) |
FIVE BYTES TO MOVE |
||
.,BA92 B1 22 LDA ($22),Y |
LDADY INDEX1 |
die |
get mantissa 4 |
|||
.,BA94 85 6D STA $6D |
STA ARGLO |
das |
save FAC2 mantissa 4 |
|||
.,BA96 88 DEY |
DEY |
Akku |
decrement index |
|||
.,BA97 B1 22 LDA ($22),Y |
LDADY INDEX1 |
und |
get mantissa 3 |
|||
.,BA99 85 6C STA $6C |
STA ARGMO |
das |
save FAC2 mantissa 3 |
|||
.,BA9B 88 DEY |
DEY IFN ADDPRC,< |
Y-Reg |
decrement index |
|||
.,BA9C B1 22 LDA ($22),Y |
LDADY INDEX1 |
zeigt, nach ARG. |
get mantissa 2 |
|||
.,BA9E 85 6B STA $6B |
STA ARGMOH |
Die |
save FAC2 mantissa 2 |
|||
.,BAA0 88 DEY |
DEY> |
gesamten |
decrement index |
|||
.,BAA1 B1 22 LDA ($22),Y |
LDADY INDEX1 |
Vor- |
get mantissa 1 + sign |
|||
.,BAA3 85 6E STA $6E |
STA ARGSGN |
zei - |
save FAC2 sign (b7) |
|||
.,BAA5 45 66 EOR $66 |
EOR FACSGN |
chen |
EOR with FAC1 sign (b7) |
SET COMBINED SIGN FOR MULT/DIV |
||
.,BAA7 85 6F STA $6F |
STA ARISGN |
von |
save sign compare (FAC1 EOR FAC2) |
|||
.,BAA9 A5 6E LDA $6E |
LDA ARGSGN |
FAC |
recover FAC2 sign (b7) |
TURN ON NORMALIZED INVISIBLE BIT |
||
.,BAAB 09 80 ORA #$80 |
ORAI 200 |
und |
set 1xxx xxx (set normal bit) |
TO COMPLETE MANTISSA |
||
.,BAAD 85 6A STA $6A |
STA ARGHO |
ARG |
save FAC2 mantissa 1 |
|||
.,BAAF 88 DEY |
DEY |
ver- |
decrement index |
|||
.,BAB0 B1 22 LDA ($22),Y |
LDADY INDEX1 |
knüp- |
get exponent byte |
|||
.,BAB2 85 69 STA $69 |
STA ARGEXP |
fen |
save FAC2 exponent |
EXPONENT |
||
.,BAB4 A5 61 LDA $61 |
LDA FACEXP ;SET CODES OF FACEXP. |
FAC-Exponent |
get FAC1 exponent |
SET STATUS BITS ON FAC EXPONENT |
||
.,BAB6 60 RTS |
RTS ;CHECK SPECIAL CASES AND ADD EXPONENTS FOR FMULT, FDIV. |
Rücksprung |
test and adjust accumulators |
ADD EXPONENTS OF ARG AND FAC(CALLED BY FMULT AND FDIV)ALSO CHECK FOR OVERFLOW, AND SET RESULT SIGN |
add exponents |
|
.,BAB7 A5 69 LDA $69 |
MULDIV: LDA ARGEXP ;EXP OF ARG=0? |
wenn Exponent von ARG=0, |
get FAC2 exponent |
|||
.,BAB9 F0 1F BEQ $BADA |
MLDEXP: BEQ ZEREMV ;SO WE GET ZERO EXPONENT. |
dann zu $BADA |
branch if FAC2 = $00 (handle underflow) |
IF ARG=0, RESULT IS ZERO |
||
.,BABB 18 CLC |
CLC |
FAC- und ARG- |
clear carry for add |
|||
.,BABC 65 61 ADC $61 |
ADC FACEXP ;RESULT IS IN ACCA. |
Exponent |
add FAC1 exponent |
|||
.,BABE 90 04 BCC $BAC4 |
BCC TRYOFF ;FIND [C] XOR [N]. |
addieren |
branch if sum of exponents < $0100 |
IN RANGE |
||
.,BAC0 30 1D BMI $BADF |
BMI GOOVER ;OVERFLOW IF BITS MATCH. |
wenn Überlauf, dann 'OVERFLOW ERROR' |
do overflow error |
OVERFLOW |
||
.,BAC2 18 CLC |
CLC |
Carry |
clear carry for the add |
|||
.:BAC3 2C .BYTE $2C |
SKIP2 |
löschen |
makes next line BIT $1410 |
TRICK TO SKIP |
||
.,BAC4 10 14 BPL $BADA |
TRYOFF: BPL ZEREMV ;UNDERFLOW. |
Wenn Unterlauf, dann zu $BADA |
if +ve go handle underflow |
OVERFLOW |
||
.,BAC6 69 80 ADC #$80 |
ADCI 200 ;ADD BIAS. |
ergibt |
adjust exponent |
RE-BIAS |
||
.,BAC8 85 61 STA $61 |
STA FACEXP |
FAC- |
save FAC1 exponent |
RESULT |
||
.,BACA D0 03 BNE $BACF |
JEQ ZEROML ;ZERO THE REST OF IT. |
Exponent |
branch if not zero |
|||
.,BACC 4C FB B8 JMP $B8FB |
FAC = 0 |
save FAC1 sign and return |
RESULT IS ZERO <<< CRAZY TO JUMP WAY BACK THERE! >>> <<< SAME IDENTICAL CODE IS BELOW! >>> <<< INSTEAD OF BNE .2, JMP STA.IN.FAC.SIGN >>> <<< ONLY NEEDED BEQ .3 >>> |
|||
.,BACF A5 6F LDA $6F |
LDA ARISGN |
FAC- und ARG-Vorzeichen verknüpfen |
get sign compare (FAC1 EOR FAC2) |
SET SIGN OF RESULT |
||
.,BAD1 85 66 STA $66 |
STA FACSGN ;ARISGN IS RESULT'S SIGN. |
und speichern |
save FAC1 sign (b7) |
|||
.,BAD3 60 RTS |
RTS ;DONE. |
Rücksprung |
handle overflow and underflow |
IF (FAC) IS POSITIVE, GIVE "OVERFLOW" ERROR IF (FAC) IS NEGATIVE, SET FAC=0, POP ONE RETURN, AND RTS CALLED FROM "EXP" FUNCTION |
||
.,BAD4 A5 66 LDA $66 |
MLDVEX: LDA FACSGN ;GET SIGN. |
wenn positives |
get FAC1 sign (b7) |
|||
.,BAD6 49 FF EOR #$FF |
EORI 377 ;COMPLEMENT IT. |
Vorzeichen, dann |
complement it |
|||
.,BAD8 30 05 BMI $BADF |
BMI GOOVER |
'OVERFLOW ERROR' |
do overflow error handle underflow |
ERROR IF POSITIVE #POP RETURN ADDRESS AND SET FAC=0 |
||
.,BADA 68 PLA |
ZEREMV: PLA ;GET ADDR OFF STACK. |
Einsprungadresse |
pop return address low byte |
|||
.,BADB 68 PLA |
PLA |
vom Stack holen |
pop return address high byte |
|||
.,BADC 4C F7 B8 JMP $B8F7 |
JMP ZEROFC ;UNDERFLOW. |
FAC = 0 |
clear FAC1 exponent and sign and return |
|||
.,BADF 4C 7E B9 JMP $B97E |
GOOVER: JMP OVERR ;OVERFLOW. ;MULTIPLY FAC BY 10. |
'OVERFLOW ERROR'FAC = FAC * 10 |
do overflow error then warm startmultiply FAC1 by 10 |
MULTIPLY FAC BY 10 |
multiply float accu by 10 |
|
.,BAE2 20 0C BC JSR $BC0C |
MUL10: JSR MOVAF ;COPY FAC INTO ARG. |
FAC runden und nach ARG |
round and copy FAC1 to FAC2 |
|||
.,BAE5 AA TAX |
TAX |
FAC-Exponent |
copy exponent (set the flags) |
TEXT FAC EXPONENT |
||
.,BAE6 F0 10 BEQ $BAF8 |
BEQ MUL10R ;IF [FAC]=0, GOT ANSWER. |
FAC gleich null, dann fertig |
exit if zero |
FINISHED IF FAC=0 |
||
.,BAE8 18 CLC |
CLC |
Exponent + 2 |
clear carry for add |
|||
.,BAE9 69 02 ADC #$02 |
ADCI 2 ;AUGMENT EXP BY 2. |
entspricht mal 4 |
add two to exponent (*4) |
ADD 2 TO EXPONENT GIVES (FAC)*4 |
||
.,BAEB B0 F2 BCS $BADF |
BCS GOOVER ;OVERFLOW. |
Übertrag ? |
do overflow error if > $FF FAC1 = (FAC1 + FAC2) * 2 |
OVERFLOW |
||
.,BAED A2 00 LDX #$00 |
FINML6: LDXI 0 |
Vergleichsbyte |
clear byte |
|||
.,BAEF 86 6F STX $6F |
STX ARISGN ;SIGNS ARE SAME. |
löschen |
clear sign compare (FAC1 EOR FAC2) |
|||
.,BAF1 20 77 B8 JSR $B877 |
JSR FADDC ;ADD TOGETHER. |
FAC = FAC + ARG entspricht mal 5 |
add FAC2 to FAC1 (*5) |
MAKES (FAC)*5 |
||
.,BAF4 E6 61 INC $61 |
INC FACEXP ;MULTIPLY BY TWO. |
Exponent erhöhen entspricht mal 2 |
increment FAC1 exponent (*10) |
*2, MAKES (FAC)*10 |
||
.,BAF6 F0 E7 BEQ $BADF |
BEQ GOOVER ;OVERFLOW. |
Übertrag, dann 'OVERFLOW' |
if exponent now zero go do overflow error |
OVERFLOW |
||
.,BAF8 60 RTS |
MUL10R: RTS ; DIVIDE FAC BY 10. |
Rücksprung |
10 as a floating value |
constant 10 for division |
||
.:BAF9 84 20 00 00 00 |
TENZC: 204 040 000 000 IFN ADDPRC,<0> |
Fließkommakonstante 10FAC = FAC / 10 |
10divide FAC1 by 10 |
10DIVIDE FAC BY 10 |
divide float by 10 |
|
.,BAFE 20 0C BC JSR $BC0C |
DIV10: JSR MOVAF ;MOVE FAC TO ARG. |
FAC runden und nach ARG |
round and copy FAC1 to FAC2 |
|||
.,BB01 A9 F9 LDA #$F9 |
LDWDI TENZC ;POINT TO CONSTANT OF 10.0 |
Zeiger |
set 10 pointer low byte |
SET UP TO PUT |
low BAF9 |
|
.,BB03 A0 BA LDY #$BA |
auf |
set 10 pointer high byte |
10 IN FAC |
high BAF9 |
||
.,BB05 A2 00 LDX #$00 |
LDXI 0 ;SIGNS ARE BOTH POSITIVE. |
Konstante 10 |
clear signdivide by (AY) (X=sign) |
FAC = ARG / (Y,A) |
||
.,BB07 86 6F STX $6F |
FDIVF: STX ARISGN |
Vergleichsbyte löschen |
save sign compare (FAC1 EOR FAC2) |
|||
.,BB09 20 A2 BB JSR $BBA2 |
JSR MOVFM ;PUT IT INTO FAC. |
Konstante 10 nach FAC |
unpack memory (AY) into FAC1 |
|||
.,BB0C 4C 12 BB JMP $BB12 |
JMP FDIVT ;SKIP OVER NEXT TWO BYTES. |
FAC = ARG / FACFAC = Konstante (A/Y) / FAC |
do FAC2/FAC1 Perform divide-by convert AY and do (AY)/FAC1 |
DIVIDE ARG BY FACFAC = (Y,A) / FAC |
divide number indexed by AY by float accu |
|
.,BB0F 20 8C BA JSR $BA8C |
FDIV: JSR CONUPK ;UNPACK CONSTANT. |
Konstante (A/Y) nach ARGFAC = ARG / FAC |
unpack memory (AY) into FAC2 |
FAC = ARG / FAC |
divide operator |
|
.,BB12 F0 76 BEQ $BB8A |
FDIVT: BEQ DV0ERR ;CAN'T DIVIDE BY ZERO ! ;(NOT ENOUGH ROOM TO STORE RESULT.) |
FAC gleich null, 'DIVISION BY ZERO' |
if zero go do /0 error |
FAC = 0, DIVIDE BY ZERO ERROR |
||
.,BB14 20 1B BC JSR $BC1B |
JSR ROUND ;TAKE FACOV INTO ACCT IN FAC. |
FAC runden |
round FAC1 |
|||
.,BB17 A9 00 LDA #$00 |
LDAI 0 ;NEGATE FACEXP. |
Vorzeichen |
clear A |
NEGATE FAC EXPONENT, SO |
||
.,BB19 38 SEC |
SEC |
von FAC- |
set carry for subtract |
ADD.EXPONENTS FORMS DIFFERENCE |
||
.,BB1A E5 61 SBC $61 |
SBC FACEXP |
Exponent |
subtract FAC1 exponent (2s complement) |
|||
.,BB1C 85 61 STA $61 |
STA FACEXP |
wechseln |
save FAC1 exponent |
|||
.,BB1E 20 B7 BA JSR $BAB7 |
JSR MULDIV ;FIX UP EXPONENTS. |
Exponent des Ergebnisses bestimmen |
test and adjust accumulators |
|||
.,BB21 E6 61 INC $61 |
INC FACEXP ;SCALE IT RIGHT. |
wenn Exponentenüberlauf, |
increment FAC1 exponent |
|||
.,BB23 F0 BA BEQ $BADF |
BEQ GOOVER ;OVERFLOW. |
dann ’OVERFLOW ERROR’ |
if zero do overflow error |
OVERFLOW |
||
.,BB25 A2 FC LDX #$FC |
LDXI ^D256-3-ADDPRC ;SETUP PROCEDURE. |
Zeiger |
set index to FAC temp |
INDEX FOR RESULT |
||
.,BB27 A9 01 LDA #$01 |
LDAI 1 DIVIDE: ;THIS IS THE BEST CODE IN THE WHOLE PILE. |
auf |
set byte |
SENTINEL |
||
.,BB29 A4 6A LDY $6A |
LDY ARGHO ;SEE WHAT RELATION HOLDS. |
Funktionsregister |
get FAC2 mantissa 1 |
SEE IF FAC CAN BE SUBTRACTED |
||
.,BB2B C4 62 CPY $62 |
CPY FACHO |
diese |
compare FAC1 mantissa 1 |
|||
.,BB2D D0 10 BNE $BB3F |
BNE SAVQUO ;[C]=0,1. N(C=0)=0. IFN ADDPRC,< |
Routine |
branch if <> |
|||
.,BB2F A4 6B LDY $6B |
LDY ARGMOH |
vergleicht |
get FAC2 mantissa 2 |
|||
.,BB31 C4 63 CPY $63 |
CPY FACMOH |
das |
compare FAC1 mantissa 2 |
|||
.,BB33 D0 0A BNE $BB3F |
BNE SAVQUO> |
FAC |
branch if <> |
|||
.,BB35 A4 6C LDY $6C |
LDY ARGMO |
und |
get FAC2 mantissa 3 |
|||
.,BB37 C4 64 CPY $64 |
CPY FACMO |
das |
compare FAC1 mantissa 3 |
|||
.,BB39 D0 04 BNE $BB3F |
BNE SAVQUO |
ARG |
branch if <> |
|||
.,BB3B A4 6D LDY $6D |
LDY ARGLO |
byte- |
get FAC2 mantissa 4 |
|||
.,BB3D C4 65 CPY $65 |
CPY FACLO |
weise |
compare FAC1 mantissa 4 |
|||
.,BB3F 08 PHP |
SAVQUO: PHP |
Statusregister retten |
save FAC2-FAC1 compare status |
SAVE THE ANSWER, AND ALSO ROLL THE |
||
.,BB40 2A ROL |
ROL A, ;SAVE RESULT. |
Carry gelöscht, |
shift byte |
BIT INTO THE QUOTIENT, SENTINEL OUT |
||
.,BB41 90 09 BCC $BB4C |
BCC QSHFT ;IF NOT DONE, CONTINUE. |
dann zu $BB4C |
skip next if no carry |
NO SENTINEL, STILL NOT 8 TRIPS |
||
.,BB43 E8 INX |
INX |
Ergebnis |
increment index to FAC temp |
8 TRIPS, STORE BYTE OF QUOTIENT |
||
.,BB44 95 29 STA $29,X |
STA RESLO,X |
aufbauen |
||||
.,BB46 F0 32 BEQ $BB7A |
BEQ LD100 |
wenn X-Reg =0, dann zu $BB7A |
32-BITS COMPLETED |
|||
.,BB48 10 34 BPL $BB7E |
BPL DIVNRM ;NOTE THIS REQ 1 MO RAM THEN NECESS. |
wenn X-Reg =1, dann zu $BB7E |
FINAL EXIT WHEN X=1 |
|||
.,BB4A A9 01 LDA #$01 |
LDAI 1 |
wenn |
RE-START SENTINEL |
|||
.,BB4C 28 PLP |
QSHFT: PLP ;RETURN CONDITION CODES. |
FAC kleiner oder gleich |
restore FAC2-FAC1 compare status |
GET ANSWER, CAN FAC BE SUBTRACTED? |
||
.,BB4D B0 0E BCS $BB5D |
BCS DIVSUB ;FAC .LE. ARG. |
ARG, dann zu $BB5D |
if FAC2 >= FAC1 then do subtract FAC2 = FAC2*2 |
YES, DO IT |
||
.,BB4F 06 6D ASL $6D |
SHFARG: ASL ARGLO ;SHIFT ARG ONE PLACE LEFT. |
Das |
shift FAC2 mantissa 4 |
NO, SHIFT ARG LEFT |
||
.,BB51 26 6C ROL $6C |
ROL ARGMO IFN ADDPRC,< |
ARG |
shift FAC2 mantissa 3 |
|||
.,BB53 26 6B ROL $6B |
ROL ARGMOH> |
ver- |
shift FAC2 mantissa 2 |
|||
.,BB55 26 6A ROL $6A |
ROL ARGHO |
doppeln |
shift FAC2 mantissa 1 |
|||
.,BB57 B0 E6 BCS $BB3F |
BCS SAVQUO ;SAVE A RESULT OF ONE FOR THIS POSITION ;AND DIVIDE. |
wenn Überlauf, dann zu $BB3F |
loop with no compare |
ANOTHER TRIP |
||
.,BB59 30 CE BMI $BB29 |
BMI DIVIDE ;IF MSB ON, GO DECIDE WHETHER TO SUB. |
wenn Bit 7 gesetzt, dann zu $BB29 |
loop with compare |
HAVE TO COMPARE FIRST |
||
.,BB5B 10 E2 BPL $BB3F |
BPL SAVQUO |
ansonsten zu $BB3F |
loop with no compare, branch always |
...ALWAYS |
||
.,BB5D A8 TAY |
DIVSUB: TAY ;NOTICE C MUST BE ON HERE. |
Die |
save FAC2-FAC1 compare status |
SAVE QUOTIENT/SENTINEL BYTE |
||
.,BB5E A5 6D LDA $6D |
LDA ARGLO |
Mantisse |
get FAC2 mantissa 4 |
SUBTRACT FAC FROM ARG ONCE |
||
.,BB60 E5 65 SBC $65 |
SBC FACLO |
von |
subtract FAC1 mantissa 4 |
|||
.,BB62 85 6D STA $6D |
STA ARGLO |
ARG |
save FAC2 mantissa 4 |
|||
.,BB64 A5 6C LDA $6C |
LDA ARGMO |
minus |
get FAC2 mantissa 3 |
|||
.,BB66 E5 64 SBC $64 |
SBC FACMO |
der |
subtract FAC1 mantissa 3 |
|||
.,BB68 85 6C STA $6C |
STA ARGMO IFN ADDPRC,< |
Mantisse |
save FAC2 mantissa 3 |
|||
.,BB6A A5 6B LDA $6B |
LDA ARGMOH |
von |
get FAC2 mantissa 2 |
|||
.,BB6C E5 63 SBC $63 |
SBC FACMOH |
FAC |
subtract FAC1 mantissa 2 |
|||
.,BB6E 85 6B STA $6B |
STA ARGMOH> |
sub- |
save FAC2 mantissa 2 |
|||
.,BB70 A5 6A LDA $6A |
LDA ARGHO |
tra- |
get FAC2 mantissa 1 |
|||
.,BB72 E5 62 SBC $62 |
SBC FACHO |
hie- |
subtract FAC1 mantissa 1 |
|||
.,BB74 85 6A STA $6A |
STA ARGHO |
ren |
save FAC2 mantissa 1 |
|||
.,BB76 98 TYA |
TYA |
und wieder |
restore FAC2-FAC1 compare status |
RESTORE QUOTIENT/SENTINEL BYTE |
||
.,BB77 4C 4F BB JMP $BB4F |
JMP SHFARG |
zu $BB4C |
GO TO SHIFT ARG AND CONTINUE |
|||
.,BB7A A9 40 LDA #$40 |
LD100: LDAI 100 ;ONLY WANT TWO MORE BITS. |
unbedingter |
DO A FEW EXTENSION BITS |
|||
.,BB7C D0 CE BNE $BB4C |
BNE QSHFT ;ALWAYS BRANCHES. |
Sprung |
branch always do A<<6, save as FAC1 rounding byte, normalise and return |
...ALWAYS |
||
.,BB7E 0A ASL |
DIVNRM: REPEAT 6,<ASL A> ;GET LAST TWO BITS INTO MSB AND B6. |
den |
LEFT JUSTIFY THE EXTENSION BITS WE DID |
|||
.,BB7F 0A ASL |
Akku |
|||||
.,BB80 0A ASL |
mit |
|||||
.,BB81 0A ASL |
64 |
|||||
.,BB82 0A ASL |
multi - |
|||||
.,BB83 0A ASL |
plizieren |
|||||
.,BB84 85 70 STA $70 |
STA FACOV |
Ergeben = RundungssteLle |
save FAC1 rounding byte |
|||
.,BB86 28 PLP |
PLP ;TO GET GARBAGE OFF STACK. |
Statusregister aus Stack |
dump FAC2-FAC1 compare status |
|||
.,BB87 4C 8F BB JMP $BB8F |
JMP MOVFR ;MOVE RESULT INTO FAC, THEN ;NORMALIZE RESULT AND RETURN. |
Hilfsregister nach FAC |
copy temp to FAC1, normalise and return do "Divide by zero" error |
|||
.,BB8A A2 14 LDX #$14 |
DV0ERR: LDXI ERRDV0 |
Nummer für 'DIVISION BY ZERO' |
error $14, divide by zero error |
error number |
||
.,BB8C 4C 37 A4 JMP $A437 |
JMP ERROR PAGE FLOATING POINT MOVEMENT ROUTINES.;MOVE RESULT TO FAC. |
Fehlermeldung ausgeben |
do error #X then warm start |
COPY RESULT INTO FAC MANTISSA, AND NORMALIZE |
||
.,BB8F A5 26 LDA $26 |
MOVFR: LDA RESHO |
Hilfs- |
get temp mantissa 1 |
|||
.,BB91 85 62 STA $62 |
STA FACHO IFN ADDPRC,< |
register |
save FAC1 mantissa 1 |
|||
.,BB93 A5 27 LDA $27 |
LDA RESMOH |
($26 - $29) |
get temp mantissa 2 |
|||
.,BB95 85 63 STA $63 |
STA FACMOH> |
nach |
save FAC1 mantissa 2 |
|||
.,BB97 A5 28 LDA $28 |
LDA RESMO |
FAC |
get temp mantissa 3 |
|||
.,BB99 85 64 STA $64 |
STA FACMO |
über- |
save FAC1 mantissa 3 |
|||
.,BB9B A5 29 LDA $29 |
LDA RESLO ;MOVE LO AND SGN. |
tra- |
get temp mantissa 4 |
|||
.,BB9D 85 65 STA $65 |
STA FACLO |
gen |
save FAC1 mantissa 4 |
|||
.,BB9F 4C D7 B8 JMP $B8D7 |
JMP NORMAL ;ALL DONE. ;MOVE MEMORY INTO FAC (UNPACKED). |
FAC linksbündig machenKonstante (A/Y) nach FACübertragen |
normalise FAC1 and returnunpack memory (AY) into FAC1 |
UNPACK (Y,A) INTO FAC |
||
.,BBA2 85 22 STA $22 |
MOVFM: STWD INDEX1 |
Zeiger |
save pointer low byte |
USE INDEX FOR PNTR |
||
.,BBA4 84 23 STY $23 |
setzen |
save pointer high byte |
||||
.,BBA6 A0 04 LDY #$04 |
LDYI 3+ADDPRC |
Zähler setzen |
5 bytes to do |
PICK UP 5 BYTES |
||
.,BBA8 B1 22 LDA ($22),Y |
LDADY INDEX1 |
LOW-Byte |
get fifth byte |
|||
.,BBAA 85 65 STA $65 |
STA FACLO |
der |
save FAC1 mantissa 4 |
|||
.,BBAC 88 DEY |
DEY |
Mantisse |
decrement index |
|||
.,BBAD B1 22 LDA ($22),Y |
LDADY INDEX1 |
und |
get fourth byte |
|||
.,BBAF 85 64 STA $64 |
STA FACMO |
HIGH- |
save FAC1 mantissa 3 |
|||
.,BBB1 88 DEY |
DEY IFN ADDPRC,< |
Byte |
decrement index |
|||
.,BBB2 B1 22 LDA ($22),Y |
LDADY INDEX1 |
der |
get third byte |
|||
.,BBB4 85 63 STA $63 |
STA FACMOH |
Mantisse |
save FAC1 mantissa 2 |
|||
.,BBB6 88 DEY |
DEY> |
in |
decrement index |
|||
.,BBB7 B1 22 LDA ($22),Y |
LDADY INDEX1 |
FAC |
get second byte |
|||
.,BBB9 85 66 STA $66 |
STA FACSGN |
holen |
save FAC1 sign (b7) |
FIRST BIT IS SIGN |
||
.,BBBB 09 80 ORA #$80 |
ORAI 200 |
Vorzeichen |
set 1xxx xxxx (add normal bit) |
SET NORMALIZED INVISIBLE BIT |
||
.,BBBD 85 62 STA $62 |
STA FACHO |
der |
save FAC1 mantissa 1 |
|||
.,BBBF 88 DEY |
DEY |
Man- |
decrement index |
|||
.,BBC0 B1 22 LDA ($22),Y |
LDADY INDEX1 |
tisse |
get first byte (exponent) |
|||
.,BBC2 85 61 STA $61 |
STA FACEXP ;LEAVE SWITCHES SET ON EXP. |
Exponent |
save FAC1 exponent |
EXPONENT |
||
.,BBC4 84 70 STY $70 |
STY FACOV |
Rundungsstelle |
clear FAC1 rounding byte |
Y=0 |
||
.,BBC6 60 RTS |
RTS ;MOVE NUMBER FROM FAC TO MEMORY. |
Rücksprung |
pack FAC1 into $5C |
ROUND FAC, STORE IN TEMP2 |
store float accu at $5C-$60 |
|
.,BBC7 A2 5C LDX #$5C |
MOV2F: LDXI TEMPF2 |
Adresse LOW |
set pointer low byte |
PACK FAC INTO TEMP2 |
low 005C |
|
.:BBC9 2C .BYTE $2C |
SKIP2 |
Akku #4FAC nach Akku #3 übertragen |
makes next line BIT $57A2pack FAC1 into $57 |
TRICK TO BRANCHROUND FAC, STORE IN TEMP1 |
store float accu at $57-$5B |
|
.,BBCA A2 57 LDX #$57 |
MOV1F: LDXI TEMPF1 |
Adresse LOW Akku #3 |
set pointer low byte |
PACK FAC INTO TEMP1 |
low 0057 |
|
.,BBCC A0 00 LDY #$00 |
MOVML: LDYI 0 |
Adresse HIGH |
set pointer high byte |
HI-BYTE OF TEMP1 SAME AS TEMP2 |
high 0057 |
|
.,BBCE F0 04 BEQ $BBD4 |
BEQ MOVMF ;ALWAYS BRANCHES. |
unbedingter SprungFAC nach Variable übertragen |
pack FAC1 into (XY) and return, branch alwayspack FAC1 into variable pointer |
...ALWAYSROUND FAC, AND STORE WHERE FORPNT POINTS |
store float accu in index at $49/$4A |
|
.,BBD0 A6 49 LDX $49 |
MOVVF: LDXY FORPNT |
Variablenadresse |
get destination pointer low byte |
|||
.,BBD2 A4 4A LDY $4A |
holen |
get destination pointer high bytepack FAC1 into (XY) |
ROUND FAC, AND STORE AT (Y,X) |
store float accu in index XY |
||
.,BBD4 20 1B BC JSR $BC1B |
MOVMF: JSR ROUND |
FAC runden |
round FAC1 |
ROUND VALUE IN FAC USING EXTENSION |
||
.,BBD7 86 22 STX $22 |
STXY INDEX1 |
Zeiger auf |
save pointer low byte |
USE INDEX FOR PNTR |
||
.,BBD9 84 23 STY $23 |
Zieladresse |
save pointer high byte |
||||
.,BBDB A0 04 LDY #$04 |
LDYI 3+ADDPRC |
Zähler setzen |
set index |
STORING 5 PACKED BYTES |
||
.,BBDD A5 65 LDA $65 |
LDA FACLO |
LOW-Byte der Mantisse |
get FAC1 mantissa 4 |
|||
.,BBDF 91 22 STA ($22),Y |
STADY INDEX |
Den |
store in destination |
|||
.,BBE1 88 DEY |
DEY |
FAC |
decrement index |
|||
.,BBE2 A5 64 LDA $64 |
LDA FACMO |
in |
get FAC1 mantissa 3 |
|||
.,BBE4 91 22 STA ($22),Y |
STADY INDEX |
den |
store in destination |
|||
.,BBE6 88 DEY |
DEY IFN ADDPRC,< |
Ziel- |
decrement index |
|||
.,BBE7 A5 63 LDA $63 |
LDA FACMOH |
bereich |
get FAC1 mantissa 2 |
|||
.,BBE9 91 22 STA ($22),Y |
STADY INDEX |
über- |
store in destination |
|||
.,BBEB 88 DEY |
DEY> |
tragen |
decrement index |
|||
.,BBEC A5 66 LDA $66 |
LDA FACSGN ;INCLUDE SIGN IN HO. |
FAC-Vorzeichen |
get FAC1 sign (b7) |
PACK SIGN IN TOP BIT OF MANTISSA |
||
.,BBEE 09 7F ORA #$7F |
ORAI 177 |
Die Bits 0 bis 6 setzen |
set bits x111 1111 |
|||
.,BBF0 25 62 AND $62 |
AND FACHO |
Vorzeichen auf |
AND in FAC1 mantissa 1 |
|||
.,BBF2 91 22 STA ($22),Y |
STADY INDEX |
Speicherformat |
store in destination |
|||
.,BBF4 88 DEY |
DEY |
bringen |
decrement index |
|||
.,BBF5 A5 61 LDA $61 |
LDA FACEXP |
FAC-Exponent |
get FAC1 exponent |
EXPONENT |
||
.,BBF7 91 22 STA ($22),Y |
STADY INDEX |
übertragen |
store in destination |
|||
.,BBF9 84 70 STY $70 |
STY FACOV ;ZERO IT SINCE ROUNDED. |
FAC-Rundungsstelle löschen |
clear FAC1 rounding byte |
ZERO THE EXTENSION |
||
.,BBFB 60 RTS |
RTS ;[Y]=0. ;MOVE ARG INTO FAC. |
RücksprungARG nach FAC übertragen |
copy FAC2 to FAC1 |
COPY ARG INTO FAC |
move second float accu into first |
|
.,BBFC A5 6E LDA $6E |
MOVFA: LDA ARGSGN |
ARG-Vorzeichen |
get FAC2 sign (b7) save FAC1 sign and copy ABS(FAC2) to FAC1 |
COPY SIGN |
||
.,BBFE 85 66 STA $66 |
MOVFA1: STA FACSGN |
in FAC-Reg übertragen |
save FAC1 sign (b7) |
|||
.,BC00 A2 05 LDX #$05 |
LDXI 4+ADDPRC |
5 Bytes |
5 bytes to copy |
MOVE 5 BYTES |
||
.,BC02 B5 68 LDA $68,X |
MOVFAL: LDA ARGEXP-1,X |
ARG in |
get byte from FAC2,X |
|||
.,BC04 95 60 STA $60,X |
STA FACEXP-1,X |
FAC |
save byte at FAC1,X |
|||
.,BC06 CA DEX |
DEX |
übertragen |
decrement count |
|||
.,BC07 D0 F9 BNE $BC02 |
BNE MOVFAL |
schon alle Zeichen ? |
loop if not all done |
|||
.,BC09 86 70 STX $70 |
STX FACOV |
FAC-Rundungsstelle löschen |
clear FAC1 rounding byte |
ZERO EXTENSION |
||
.,BC0B 60 RTS |
RTS ;MOVE FAC INTO ARG. |
RücksprungFAC nach ARG übertragen |
round and copy FAC1 to FAC2 |
ROUND FAC AND COPY TO ARG |
move rounded float accu into second |
|
.,BC0C 20 1B BC JSR $BC1B |
MOVAF: JSR ROUND |
FAC runden |
round FAC1 copy FAC1 to FAC2 |
ROUND FAC USING EXTENSION |
||
.,BC0F A2 06 LDX #$06 |
MOVEF: LDXI 5+ADDPRC |
6 Zeichen |
6 bytes to copy |
COPY 6 BYTES, INCLUDES SIGN |
||
.,BC11 B5 60 LDA $60,X |
MOVAFL: LDA FACEXP-1,X |
FAC in |
get byte from FAC1,X |
|||
.,BC13 95 68 STA $68,X |
STA ARGEXP-1,X |
ARG |
save byte at FAC2,X |
|||
.,BC15 CA DEX |
DEX |
übertragen |
decrement count |
|||
.,BC16 D0 F9 BNE $BC11 |
BNE MOVAFL |
schon alle Zeichen ? |
loop if not all done |
|||
.,BC18 86 70 STX $70 |
STX FACOV ;ZERO IT SINCE ROUNDED. |
FAC-Rundungsstelle löschen |
clear FAC1 rounding byte |
ZERO FAC EXTENSION |
||
.,BC1A 60 RTS |
MOVRTS: RTS |
RücksprungFAC runden |
round FAC1 |
ROUND FAC USING EXTENSION BYTE |
round float accu according to guard bit |
|
.,BC1B A5 61 LDA $61 |
ROUND: LDA FACEXP ;ZERO? |
Exponent null ?, |
get FAC1 exponent |
|||
.,BC1D F0 FB BEQ $BC1A |
BEQ MOVRTS ;YES. DONE ROUNDING. |
dann fertig |
exit if zero |
FAC = 0, RETURN |
||
.,BC1F 06 70 ASL $70 |
ASL FACOV ;ROUND? |
Rundungsstelle größer $7F ? |
shift FAC1 rounding byte |
IS FAC.EXTENSION >= 128? |
||
.,BC21 90 F7 BCC $BC1A |
BCC MOVRTS ;NO. MSB OFF. |
nein, dann fertig |
exit if no overflow round FAC1 (no check) |
NO, FINISHEDINCREMENT MANTISSA AND RE-NORMALIZE IF CARRY |
||
.,BC23 20 6F B9 JSR $B96F |
INCRND: JSR INCFAC ;YES, ADD ONE TO LSB(FAC). |
Mantisse um eins erhöhen |
increment FAC1 mantissa |
YES, INCREMENT FAC |
||
.,BC26 D0 F2 BNE $BC1A |
BNE MOVRTS ;NO CARRY MEANS DONE. |
jetzt null ? |
branch if no overflow |
HIGH BYTE HAS BITS, FINISHED |
||
.,BC28 4C 38 B9 JMP $B938 |
JMP RNDSHF ;SQUEEZ MSB IN AND RTS. ;NOTE [C]=1 SINCE INCFAC DOESNT TOUCH C. PAGE SIGN, SGN, FLOAT, NEG, ABS.;PUT SIGN OF FAC IN ACCA. |
nach rechts verschieben, Exponent erhöhen Vorzeichen von FAC holen |
nornalise FAC1 for C=1 and returnget FAC1 signreturn A = $FF, Cb = 1/-ve A = $01, Cb = 0/+ve, A = $00, Cb = ?/0 |
HI-BYTE=0, SO SHIFT LEFTTEST FAC FOR ZERO AND SIGNFAC > 0, RETURN +1FAC = 0, RETURN 0 FAC < 0, RETURN -1 |
get sign of float accu in A |
|
.,BC2B A5 61 LDA $61 |
SIGN: LDA FACEXP |
wenn null, |
get FAC1 exponent |
CHECK SIGN OF FAC AND |
||
.,BC2D F0 09 BEQ $BC38 |
BEQ SIGNRT ;IF NUMBER IS ZERO, SO IS RESULT. |
dann RTS |
exit if zero (allready correct SGN(0)=0)return A = $FF, Cb = 1/-ve A = $01, Cb = 0/+veno = 0 check |
RETURN -1,0,1 IN A-REG |
||
.,BC2F A5 66 LDA $66 |
FCSIGN: LDA FACSGN |
FAC-Vorzeichen |
else get FAC1 sign (b7)return A = $FF, Cb = 1/-ve A = $01, Cb = 0/+veno = 0 check, sign in A |
|||
.,BC31 2A ROL |
FCOMPS: ROL A |
holen |
move sign bit to carry |
MSBIT TO CARRY |
||
.,BC32 A9 FF LDA #$FF |
LDAI ^O377 ;ASSUME NEGATIVE. |
negativ? |
set byte for -ve result |
-1 |
||
.,BC34 B0 02 BCS $BC38 |
BCS SIGNRT |
dann RTS |
return if sign was set (-ve) |
MSBIT = 1 |
||
.,BC36 A9 01 LDA #$01 |
LDAI 1 ;GET +1. |
sonst positiv |
else set byte for +ve result |
+1 |
||
.,BC38 60 RTS |
SIGNRT: RTS ;SGN FUNCTION. |
RücksprungBASIC-Funktion SGN |
perform SGN() |
"SGN" FUNCTION |
SGN function |
|
.,BC39 20 2B BC JSR $BC2B |
SGN: JSR SIGN ;FLOAT THE SIGNED INTEGER IN ACCA. |
Vorzeichen holen |
get FAC1 sign, return A = $FF -ve, A = $01 +vesave A as integer byte |
CONVERT FAC TO -1,0,1CONVERT (A) INTO FAC, AS SIGNED VALUE -128 TO +127 |
move signed number from A into float accu |
|
.,BC3C 85 62 STA $62 |
FLOAT: STA FACHO ;PUT [ACCA] IN HIGH ORDER. |
und in FAC speichern |
save FAC1 mantissa 1 |
PUT IN HIGH BYTE OF MANTISSA |
||
.,BC3E A9 00 LDA #$00 |
LDAI 0 |
$63 |
clear A |
CLEAR 2ND BYTE OF MANTISSA |
||
.,BC40 85 63 STA $63 |
STA FACHO+1 |
löschen |
clear FAC1 mantissa 2 |
|||
.,BC42 A2 88 LDX #$88 |
LDXI 210 ;GET THE EXPONENT. ;FLOAT THE SIGNED NUMBER IN FAC. |
Exponent |
set exponent set exponent = X, clear FAC1 3 and 4 and normalise |
USE EXPONENT 2^9FLOAT UNSIGNED VALUE IN FAC+1,2(X) = EXPONENT |
||
.,BC44 A5 62 LDA $62 |
FLOATS: LDA FACHO |
Vorzeichen |
get FAC1 mantissa 1 |
MSBIT=0, SET CARRY; =1, CLEAR CARRY |
||
.,BC46 49 FF EOR #$FF |
EORI 377 |
invertieren |
complement it |
|||
.,BC48 2A ROL |
ROL A, ;GET COMP OF SIGN IN CARRY. |
und nach links rollen |
sign bit into carry set exponent = X, clear mantissa 4 and 3 and normalise FAC1 |
FLOAT UNSIGNED VALUE IN FAC+1,2(X) = EXPONENTC=0 TO MAKE VALUE NEGATIVE C=1 TO MAKE VALUE POSITIVE |
||
.,BC49 A9 00 LDA #$00 |
FLOATC: LDAI 0 ;ZERO [ACCA] BUT NOT CARRY. |
Die Adressen |
clear A |
CLEAR LOWER 16-BITS OF MANTISSA |
||
.,BC4B 85 65 STA $65 |
STA FACLO IFN ADDPRC,< |
$65 |
clear FAC1 mantissa 4 |
|||
.,BC4D 85 64 STA $64 |
STA FACMO> |
und $64 löschen |
clear FAC1 mantissa 3 set exponent = X and normalise FAC1 |
|||
.,BC4F 86 61 STX $61 |
FLOATB: STX FACEXP |
Exponent |
set FAC1 exponent |
STORE EXPONENT |
||
.,BC51 85 70 STA $70 |
STA FACOV |
Rundungsstelle |
clear FAC1 rounding byte |
CLEAR EXTENSION |
||
.,BC53 85 66 STA $66 |
STA FACSGN |
löschen |
clear FAC1 sign (b7) |
MAKE SIGN POSITIVE |
||
.,BC55 4C D2 B8 JMP $B8D2 |
JMP FADFLT ;ABSOLUTE VALUE OF FAC. |
linksbündig machenBASIC-Funktion ABS |
do ABS and normalise FAC1perform ABS() |
IF C=0, WILL NEGATE FAC"ABS" FUNCTION |
ABS function |
|
.,BC58 46 66 LSR $66 |
ABS: LSR FACSGN |
Vorzeichenbit löschen |
clear FAC1 sign, put zero in b7 |
CHANGE SIGN TO + |
||
.,BC5A 60 RTS |
RTS PAGE COMPARE TWO NUMBERS.;A=1 IF ARG .LT. FAC.;A=0 IF ARG=FAC. ;A=-1 IF ARG .GT. FAC. |
RücksprungVergleich Konstante (A/Y) mitFAC |
compare FAC1 with (AY)returns A=$00 if FAC1 = (AY)returns A=$01 if FAC1 > (AY) returns A=$FF if FAC1 < (AY) |
COMPARE FAC WITH PACKED # AT (Y,A)RETURN A=1,0,-1 AS (Y,A) IS <,=,> FAC |
compare float accu to float indexed by XY |
|
.,BC5B 85 24 STA $24 |
FCOMP: STA INDEX2 |
Zeiger auf |
save pointer low byte |
USE DEST FOR PNTRSPECIAL ENTRY FROM "NEXT" PROCESSOR"DEST" ALREADY SET UP |
||
.,BC5D 84 25 STY $25 |
FCOMPN: STY INDEX2+1 |
Konstante |
save pointer high byte |
|||
.,BC5F A0 00 LDY #$00 |
LDYI 0 |
Zähler setzen |
clear index |
GET EXPONENT OF COMPARAND |
||
.,BC61 B1 24 LDA ($24),Y |
LDADY INDEX2 ;HAS ARGEXP. |
Exponent |
get exponent |
|||
.,BC63 C8 INY |
INY ;BUMP PNTR UP. |
Zähler erhöhen |
increment index |
POINT AT NEXT BYTE |
||
.,BC64 AA TAX |
TAX ;SAVE A IN X AND RESET CODES. |
ins X-Reg |
copy (AY) exponent to X |
EXPONENT TO X-REG |
||
.,BC65 F0 C4 BEQ $BC2B |
BEQ SIGN |
null?, dann Vorzeichen von FAC holen |
branch if (AY) exponent=0 and get FAC1 sign A = $FF, Cb = 1/-ve A = $01, Cb = 0/+ve |
IF COMPARAND=0, "SIGN" COMPARES FAC |
||
.,BC67 B1 24 LDA ($24),Y |
LDADY INDEX2 |
Konstante |
get (AY) mantissa 1, with sign |
GET HI-BYTE OF MANTISSA |
||
.,BC69 45 66 EOR $66 |
EOR FACSGN ;SIGNS THE SAME. |
FAC-Vorzeichen |
EOR FAC1 sign (b7) |
COMPARE WITH FAC SIGN |
||
.,BC6B 30 C2 BMI $BC2F |
BMI FCSIGN ;SIGNS DIFFER SO RESULT IS ;SIGN OF FAC AGAIN. |
verschiedene Vorzeichen?, dann zu $BC2F |
if signs <> do return A = $FF, Cb = 1/-ve A = $01, Cb = 0/+ve and return |
DIFFERENT SIGNS, "SIGN" GIVES ANSWER |
||
.,BC6D E4 61 CPX $61 |
FOUTCP: CPX FACEXP |
Exponenten vergleichen |
compare (AY) exponent with FAC1 exponent |
SAME SIGN, SO COMPARE EXPONENTS |
||
.,BC6F D0 21 BNE $BC92 |
BNE FCOMPC |
falls verschieden, dann zu $BC92 |
branch if different |
DIFFERENT, SO SUFFICIENT TEST |
||
.,BC71 B1 24 LDA ($24),Y |
LDADY INDEX2 |
das |
get (AY) mantissa 1, with sign |
SAME EXPONENT, COMPARE MANTISSA |
||
.,BC73 09 80 ORA #$80 |
ORAI 200 |
erste |
normalise top bit |
SET INVISIBLE NORMALIZED BIT |
||
.,BC75 C5 62 CMP $62 |
CMP FACHO |
Byte |
compare with FAC1 mantissa 1 |
|||
.,BC77 D0 19 BNE $BC92 |
BNE FCOMPC |
vergleichen |
branch if different |
NOT SAME, SO SUFFICIENT |
||
.,BC79 C8 INY |
INY IFN ADDPRC,< |
Zähler erhöhen |
increment index |
SAME, COMPARE MORE MANTISSA |
||
.,BC7A B1 24 LDA ($24),Y |
LDADY INDEX2 |
das zweite |
get mantissa 2 |
|||
.,BC7C C5 63 CMP $63 |
CMP FACMOH |
Byte |
compare with FAC1 mantissa 2 |
|||
.,BC7E D0 12 BNE $BC92 |
BNE FCOMPC |
vergleichen |
branch if different |
NOT SAME, SO SUFFICIENT |
||
.,BC80 C8 INY |
INY> |
Zähler erhöhen |
increment index |
SAME, COMPARE MORE MANTISSA |
||
.,BC81 B1 24 LDA ($24),Y |
LDADY INDEX2 |
das dritte |
get mantissa 3 |
|||
.,BC83 C5 64 CMP $64 |
CMP FACMO |
Byte |
compare with FAC1 mantissa 3 |
|||
.,BC85 D0 0B BNE $BC92 |
BNE FCOMPC |
vergleichen |
branch if different |
NOT SAME, SO SUFFICIENT |
||
.,BC87 C8 INY |
INY |
Zähler erhöhen |
increment index |
SAME, COMPARE REST OF MANTISSA |
||
.,BC88 A9 7F LDA #$7F |
LDAI 177 |
FAC-Rundungsstelle mit |
set for 1/2 value rounding byte |
ARTIFICIAL EXTENSION BYTE FOR COMPARAND |
||
.,BC8A C5 70 CMP $70 |
CMP FACOV |
$7F vergleichen |
compare with FAC1 rounding byte (set carry) |
|||
.,BC8C B1 24 LDA ($24),Y |
LDADY INDEX2 |
letzte Stellen, gemäß Ver- |
get mantissa 4 |
|||
.,BC8E E5 65 SBC $65 |
SBC FACLO ;GET ZERO IF EQUAL. |
gleich der Rundungsstelle, subtrahieren |
subtract FAC1 mantissa 4 |
|||
.,BC90 F0 28 BEQ $BCBA |
BEQ QINTRT |
wenn alle Stellen gleich sind, dann RTS |
exit if mantissa 4 equal gets here if number <> FAC1 |
NUMBERS ARE EQUAL, RETURN (A)=0 |
||
.,BC92 A5 66 LDA $66 |
FCOMPC: LDA FACSGN |
FAC-Vorzeichen |
get FAC1 sign (b7) |
NUMBERS ARE DIFFERENT |
||
.,BC94 90 02 BCC $BC98 |
BCC FCOMPD |
ist die Konstante kleiner FAC, dann zu $BC98 |
branch if FAC1 > (AY) |
FAC IS LARGER MAGNITUDE |
||
.,BC96 49 FF EOR #$FF |
EORI 377 |
Ergebnis kleiner, dann invertieren |
else toggle FAC1 sign |
FAC IS SMALLER MAGNITUDE <<< NOTE THAT ABOVE THREE LINES CAN BE SHORTENED: >>> <<< .1 ROR PUT CARRY INTO SIGN BIT >>> <<< EOR FAC.SIGN TOGGLE WITH SIGN OF FAC >>> |
||
.,BC98 4C 31 BC JMP $BC31 |
FCOMPD: JMP FCOMPS ;A PART OF SIGN SETS ACCA UP. PAGE GREATEST INTEGER FUNCTION.;QUICK GREATEST INTEGER FUNCTION.;LEAVES INT(FAC) IN FACHO&MO&LO SIGNED. ;ASSUMES FAC .LT. 2^23 = 8388608 |
Flag für Ergebnis setzenUmwandlung Fließkomma nachInteger |
return A = $FF, Cb = 1/-ve A = $01, Cb = 0/+veconvert FAC1 floating to fixed |
CONVERT +1 OR -1QUICK INTEGER FUNCTIONCONVERTS FP VALUE IN FAC TO INTEGER VALUEIN FAC+1...FAC+4, BY SHIFTING RIGHT WITH SIGN EXTENSION UNTIL FRACTIONAL BITS ARE OUT. THIS SUBROUTINE ASSUMES THE EXPONENT < 32. |
convert float to a 4 byte signed integer |
|
.,BC9B A5 61 LDA $61 |
QINT: LDA FACEXP |
Exponent |
get FAC1 exponent |
LOOK AT FAC EXPONENT |
||
.,BC9D F0 4A BEQ $BCE9 |
BEQ CLRFAC ;IF ZERO, GOT IT. |
null ? |
if zero go clear FAC1 and return |
FAC=0, SO FINISHED |
||
.,BC9F 38 SEC |
SEC |
Integer- |
set carry for subtract |
GET -(NUMBER OF FRACTIONAL BITS) |
||
.,BCA0 E9 A0 SBC #$A0 |
SBCI 8*ADDPRC+230 ;GET NUMBER OF PLACES TO SHIFT. |
Exponent |
subtract maximum integer range exponent |
IN A-REG FOR SHIFT COUNT |
||
.,BCA2 24 66 BIT $66 |
BIT FACSGN |
wenn FAC positiv, |
test FAC1 sign (b7) |
CHECK SIGN OF FAC |
||
.,BCA4 10 09 BPL $BCAF |
BPL QISHFT |
dann zu $BCAF |
branch if FAC1 +ve FAC1 was -ve |
POSITIVE, CONTINUE |
||
.,BCA6 AA TAX |
TAX |
FAC |
copy subtracted exponent |
NEGATIVE, SO COMPLEMENT MANTISSA |
||
.,BCA7 A9 FF LDA #$FF |
LDAI 377 |
Rundungsbyte |
overflow for -ve number |
AND SET SIGN EXTENSION FOR SHIFT |
||
.,BCA9 85 68 STA $68 |
STA BITS ;PUT 377 IN WHEN SHFTR SHIFTS BYTES. |
setzen |
set FAC1 overflow byte |
|||
.,BCAB 20 4D B9 JSR $B94D |
JSR NEGFCH ;TRULY NEGATE QUANTITY IN FAC. |
Mantisse von FAC invertieren |
twos complement FAC1 mantissa |
|||
.,BCAE 8A TXA |
TXA |
Exponent in Akku |
restore subtracted exponent |
RESTORE BIT COUNT TO A-REG |
||
.,BCAF A2 61 LDX #$61 |
QISHFT: LDXI FAC |
FAC-Offset-Zeiger |
set index to FAC1 |
POINT SHIFT SUBROUTINE AT FAC |
||
.,BCB1 C9 F9 CMP #$F9 |
CMPI ^D256-7 |
wenn Exponent größer als |
compare exponent result |
MORE THAN 7 BITS TO SHIFT? |
||
.,BCB3 10 06 BPL $BCBB |
BPL QINT1 ;IF NUMBER OF PLACES .GE. 7 ;SHIFT 1 PLACE AT A TIME. |
-8, dann zu BCBB |
if < 8 shifts shift FAC1 A times right and return |
NO, SHORT SHIFT |
||
.,BCB5 20 99 B9 JSR $B999 |
JSR SHIFTR ;START SHIFTING BYTES, THEN BITS. |
FAC rechtsverschieben |
shift FAC1 A times right (> 8 shifts) |
YES, USE GENERAL ROUTINE |
||
.,BCB8 84 68 STY $68 |
STY BITS ;ZERO BITS SINCE ADDER WANTS ZERO. |
FAC-Rundungsbyte löschen |
clear FAC1 overflow byte |
Y=0, CLEAR SIGN EXTENSION |
||
.,BCBA 60 RTS |
QINTRT: RTS |
Rücksprung |
shift FAC1 A times right |
|||
.,BCBB A8 TAY |
QINT1: TAY ;PUT COUNT IN COUNTER. |
Akku löschen |
copy shift count |
SAVE SHIFT COUNT |
||
.,BCBC A5 66 LDA $66 |
LDA FACSGN |
FAC-Vorzeichen laden |
get FAC1 sign (b7) |
GET SIGN BIT |
||
.,BCBE 29 80 AND #$80 |
ANDI 200 ;GET SIGN BIT. |
das |
mask sign bit only (x000 0000) |
|||
.,BCC0 46 62 LSR $62 |
LSR FACHO ;SAVE FIRST SHIFTED BYTE. |
FAC- |
shift FAC1 mantissa 1 |
START RIGHT SHIFT |
||
.,BCC2 05 62 ORA $62 |
ORA FACHO |
Vorzeichen |
OR sign in b7 FAC1 mantissa 1 |
AND MERGE WITH SIGN |
||
.,BCC4 85 62 STA $62 |
STA FACHO |
isolieren |
save FAC1 mantissa 1 |
|||
.,BCC6 20 B0 B9 JSR $B9B0 |
JSR ROLSHF ;SHIFT THE REST. |
FAC bitweise nach rechts verschieben |
shift FAC1 Y times right |
JUMP INTO MIDDLE OF SHIFTER |
||
.,BCC9 84 68 STY $68 |
STY BITS ;ZERO [BITS]. |
FAC-Rundungsbyte löschen |
clear FAC1 overflow byte |
Y=0, CLEAR SIGN EXTENSION |
||
.,BCCB 60 RTS |
RTS ;GREATEST INTEGER FUNCTION. |
RücksprungBASIC-Funktion INT |
perform INT() |
"INT" FUNCTIONUSES QINT TO CONVERT (FAC) TO INTEGER FORM,AND THEN REFLOATS THE INTEGER. <<< A FASTER APPROACH WOULD SIMPLY CLEAR >>> <<< THE FRACTIONAL BITS BY ZEROING THEM >>> |
INT function |
|
.,BCCC A5 61 LDA $61 |
INT: LDA FACEXP |
Exponent |
get FAC1 exponent |
CHECK IF EXPONENT < 32 |
||
.,BCCE C9 A0 CMP #$A0 |
CMPI 8*ADDPRC+230 |
ganze Zahl ? |
compare with max int |
BECAUSE IF > 31 THERE IS NO FRACTION |
||
.,BCD0 B0 20 BCS $BCF2 |
BCS INTRTS ;FORGET IT. |
ja, dann fertig |
exit if >= (allready int, too big for fractional part!) |
NO FRACTION, WE ARE FINISHED |
||
.,BCD2 20 9B BC JSR $BC9B |
JSR QINT |
FAC nach Integer wandeln |
convert FAC1 floating to fixed |
USE GENERAL INTEGER CONVERSION |
||
.,BCD5 84 70 STY $70 |
STY FACOV ;CLR OVERFLOW BYTE. |
Rundungsstelle löschen |
save FAC1 rounding byte |
Y=0, CLEAR EXTENSION |
||
.,BCD7 A5 66 LDA $66 |
LDA FACSGN |
Vorzeichen in Akku |
get FAC1 sign (b7) |
GET SIGN OF VALUE |
||
.,BCD9 84 66 STY $66 |
STY FACSGN ;MAKE FAC LOOK POSITIVE. |
und positiv machen |
save FAC1 sign (b7) |
Y=0, CLEAR SIGN |
||
.,BCDB 49 80 EOR #$80 |
EORI 200 ;GET COMPLEMENT OF SIGN IN CARRY. |
Bei |
toggle FAC1 sign |
TOGGLE ACTUAL SIGN |
||
.,BCDD 2A ROL |
ROL A, |
negativen Vorzeichen |
shift into carry |
AND SAVE IN CARRY |
||
.,BCDE A9 A0 LDA #$A0 |
LDAI 8*ADDPRC+230 |
das |
set new exponent |
SET EXPONENT TO 32 |
||
.,BCE0 85 61 STA $61 |
STA FACEXP |
Carry- |
save FAC1 exponent |
BECAUSE 4-BYTE INTEGER NOW |
||
.,BCE2 A5 65 LDA $65 |
LDA FACLO |
flag |
get FAC1 mantissa 4 |
SAVE LOW 8-BITS OF INTEGER FORM |
||
.,BCE4 85 07 STA $07 |
STA INTEGR |
löschen |
save FAC1 mantissa 4 for power function |
FOR EXP AND POWER |
||
.,BCE6 4C D2 B8 JMP $B8D2 |
JMP FADFLT |
FAC linksbündig machen |
do ABS and normalise FAC1clear FAC1 and return |
NORMALIZE TO FINISH CONVERSION |
clear float accu |
|
.,BCE9 85 62 STA $62 |
CLRFAC: STA FACHO ;MAKE IT REALLY ZERO. |
Mantisse |
clear FAC1 mantissa 1 |
FAC=0, SO CLEAR ALL 4 BYTES FOR |
||
.,BCEB 85 63 STA $63 |
IFN ADDPRC,<STA FACMOH> |
mit |
clear FAC1 mantissa 2 |
INTEGER VERSION |
||
.,BCED 85 64 STA $64 |
STA FACMO |
Nullen |
clear FAC1 mantissa 3 |
|||
.,BCEF 85 65 STA $65 |
STA FACLO |
füllen |
clear FAC1 mantissa 4 |
|||
.,BCF1 A8 TAY |
TAY |
Y-Reg löschen |
clear Y |
Y=0 TOO |
||
.,BCF2 60 RTS |
INTRTS: RTS PAGE FLOATING POINT INPUT ROUTINE.;NUMBER INPUT IS LEFT IN FAC.;AT ENTRY [TXTPTR] POINTS TO THE FIRST CHARACTER IN A TEXT BUFFER. ;THE FIRST CHARACTER IS ALSO IN ACCA. FIN PACKS THE DIGITS ;INTO THE FAC AS AN INTEGER AND KEEPS TRACK OF WHERE THE ;DECIMAL POINT IS. [DPTFLG] TELL WHETHER A DP HAS BEEN ;SEEN. [DECCNT] IS THE NUMBER OF DIGITS AFTER THE DP. ;AT THE END [DECCNT] AND THE EXPONENT ARE USED TO ;DETERMINE HOW MANY TIMES TO MULTIPLY OR DIVIDE BY TEN ;TO GET THE CORRECT NUMBER. |
RücksprungUmwandlung ASCII nachFließkommaformat |
get FAC1 from string |
CONVERT STRING TO FP VALUE IN FACSTRING POINTED TO BY TXTPTRFIRST CHAR ALREADY SCANNED BY CHRGET (A) = FIRST CHAR, C=0 IF DIGIT. |
convert string to float in float accu |
|
.,BCF3 A0 00 LDY #$00 |
FIN: LDYI 0 ;ZERO FACSGN&SGNFLG. |
Wert festlegen |
clear Y |
CLEAR WORKING AREA ($99...$A3) |
||
.,BCF5 A2 0A LDX #$0A |
LDXI 11+ADDPRC ;ZERO EXP AND HO (AND MOH). |
Zähler stellen |
set index |
TMPEXP, EXPON, DPFLG, EXPSGN, FAC, SERLEN |
||
.,BCF7 94 5D STY $5D,X |
FINZLP: STY DECCNT,X ;ZERO MO AND LO. |
den Bereich |
clear byte |
|||
.,BCF9 CA DEX |
DEX ;ZERO TENEXP AND EXPSGN |
von $5D bis $66 mit |
decrement index |
|||
.,BCFA 10 FB BPL $BCF7 |
BPL FINZLP ;ZERO DECCNT, DPTFLG. |
Nullen füllen |
loop until numexp to negnum (and FAC1) = $00 |
|||
.,BCFC 90 0F BCC $BD0D |
BCC FINDGQ ;FLAGS STILL SET FROM CHRGET. |
wenn erstes Zeichen eine Ziffer, dann zu $BD0D |
branch if first character is numeric |
FIRST CHAR IS A DIGIT |
||
.,BCFE C9 2D CMP #$2D |
CMPI "-" ;A NEGATIVE SIGN? |
Nummer für '-'? |
else compare with "-" |
CHECK FOR LEADING SIGN |
minus |
|
.,BD00 D0 04 BNE $BD06 |
BNE QPLUS ;NO, TRY PLUS SIGN. |
wenn nicht, dann zu $BD06 |
branch if not "-" |
NOT MINUS |
||
.,BD02 86 67 STX $67 |
STX SGNFLG ;IT'S NEGATIVE. (X=377). |
Flag für negativ |
set flag for -ve n (negnum = $FF) |
MINUS, SET SERLEN = $FF FOR FLAG |
||
.,BD04 F0 04 BEQ $BD0A |
BEQ FINC ;ALWAYS BRANCHES. |
unbedingter Sprung |
branch always |
...ALWAYS |
||
.,BD06 C9 2B CMP #$2B |
QPLUS: CMPI "+" ;PLUS SIGN? |
Nummer für ' + ' |
else compare with "+" |
MIGHT BE PLUS |
plus |
|
.,BD08 D0 05 BNE $BD0F |
BNE FIN1 ;YES, SKIP IT. |
wenn nicht, dann zu $BD0F |
branch if not "+" |
NOT PLUS EITHER, CHECK DECIMAL POINT |
||
.,BD0A 20 73 00 JSR $0073 |
FINC: JSR CHRGET |
CHRGET nächstes Zeichen holen |
increment and scan memory |
GET NEXT CHAR OF STRING |
||
.,BD0D 90 5B BCC $BD6A |
FINDGQ: BCC FINDIG |
wenn Ziffer, dann zu $BD6A |
branch if numeric character |
INSERT THIS DIGIT |
||
.,BD0F C9 2E CMP #$2E |
FIN1: CMPI "." ;THE DP? |
Nummer für '.' |
else compare with "." |
CHECK FOR DECIMAL POINT |
decimal point |
|
.,BD11 F0 2E BEQ $BD41 |
BEQ FINDP ;NO KIDDING. |
wenn ja, dann zu $BD41 |
branch if "." |
YES |
||
.,BD13 C9 45 CMP #$45 |
CMPI "E" ;EXPONENT FOLLOWS. |
Nummer für 'E' |
else compare with "E" |
CHECK FOR EXPONENT PART |
E |
|
.,BD15 D0 30 BNE $BD47 |
BNE FINE ;NO. ;HERE TO CHECK FOR SIGN OF EXP. |
wenn nicht, dann zu $BD47 |
branch if not "E" was "E" so evaluate exponential part |
NO, END OF NUMBER |
||
.,BD17 20 73 00 JSR $0073 |
JSR CHRGET ;YES. GET ANOTHER. |
CHRGET nächstes Zeichen holen |
increment and scan memory |
YES, START CONVERTING EXPONENT |
||
.,BD1A 90 17 BCC $BD33 |
BCC FNEDG1 ;IT IS A DIGIT. (EASIER THAN ;BACKING UP POINTER.) |
wenn Ziffer, dann zu $BD33 |
branch if numeric character |
EXPONENT DIGIT |
||
.,BD1C C9 AB CMP #$AB |
CMPI MINUTK ;MINUS? |
'-' BASIC-Kode |
else compare with token for - |
NEGATIVE EXPONENT? |
minus code |
|
.,BD1E F0 0E BEQ $BD2E |
BEQ FINEC1 ;NEGATE. |
wenn ja, dann zu $BD2E |
branch if token for - |
YES |
||
.,BD20 C9 2D CMP #$2D |
CMPI "-" ;MINUS SIGN? |
Nummer für '-' |
else compare with "-" |
MIGHT NOT BE TOKENIZED YET |
minus |
|
.,BD22 F0 0A BEQ $BD2E |
BEQ FINEC1 |
wenn ja, dann zu $BD2E |
branch if "-" |
YES, IT IS NEGATIVE |
||
.,BD24 C9 AA CMP #$AA |
CMPI PLUSTK ;PLUS? |
'+' BASIC-Kode |
else compare with token for + |
OPTIONAL "+" |
plus code |
|
.,BD26 F0 08 BEQ $BD30 |
BEQ FINEC |
wenn ja, dann zu $BD30 |
branch if token for + |
YES |
||
.,BD28 C9 2B CMP #$2B |
CMPI "+" ;PLUS SIGN? |
Nummer für '+' |
else compare with "+" |
MIGHT NOT BE TOKENIZED YET |
plus |
|
.,BD2A F0 04 BEQ $BD30 |
BEQ FINEC |
wenn ja, dann zu $BD30 |
branch if "+" |
YES, FOUND "+" |
||
.,BD2C D0 07 BNE $BD35 |
BNE FINEC2 |
unbedingter Sprung |
branch always |
...ALWAYS, NUMBER COMPLETED |
||
.,BD2E 66 60 ROR $60 |
FINEC1: ROR EXPSGN ;TURN IT ON. |
Bit 7 setzen |
set exponent -ve flag (C, which=1, into b7) |
C=1, SET FLAG NEGATIVE |
||
.,BD30 20 73 00 JSR $0073 |
FINEC: JSR CHRGET ;GET ANOTHER. |
CHRGET nächstes Zeichen holen |
increment and scan memory |
GET NEXT DIGIT OF EXPONENT |
||
.,BD33 90 5C BCC $BD91 |
FNEDG1: BCC FINEDG ;IT IS A DIGIT. |
wenn Ziffer, dann zu $BD91 |
branch if numeric character |
CHAR IS A DIGIT OF EXPONENT |
||
.,BD35 24 60 BIT $60 |
FINEC2: BIT EXPSGN |
Bit 7 gesetzt ? |
test exponent -ve flag |
END OF NUMBER, CHECK EXP SIGN |
||
.,BD37 10 0E BPL $BD47 |
BPL FINE |
wenn nicht, dann zu $BD47 |
if +ve go evaluate exponent else do exponent = -exponent |
POSITIVE EXPONENT |
||
.,BD39 A9 00 LDA #$00 |
LDAI 0 |
Vorzeichen des |
clear result |
NEGATIVE EXPONENT |
||
.,BD3B 38 SEC |
SEC |
Exponenten |
set carry for subtract |
MAKE 2'S COMPLEMENT OF EXPONENT |
||
.,BD3C E5 5E SBC $5E |
SBC TENEXP |
wechseln |
subtract exponent byte |
|||
.,BD3E 4C 49 BD JMP $BD49 |
JMP FINE1 |
weiter bei $BD49 |
go evaluate exponent |
FOUND A DECIMAL POINT |
||
.,BD41 66 5F ROR $5F |
FINDP: ROR DPTFLG |
Aufruf durch Dezimalpunkt |
set decimal point flag |
C=1, SET DPFLG FOR DECIMAL POINT |
||
.,BD43 24 5F BIT $5F |
BIT DPTFLG |
schon zweiter Dezimalpunkt |
test decimal point flag |
CHECK IF PREVIOUS DEC. PT. |
||
.,BD45 50 C3 BVC $BD0A |
BVC FINC |
wenn nicht, dann weiter |
branch if only one decimal point so far evaluate exponent |
NO PREVIOUS DECIMAL POINT A SECOND DECIMAL POINT IS TAKEN AS A TERMINATOR TO THE NUMERIC STRING. "A=11..22" WILL GIVE A SYNTAX ERROR, BECAUSE IT IS TWO NUMBERS WITH NO OPERATOR BETWEEN. "PRINT 11..22" GIVES NO ERROR, BECAUSE IT IS JUST THE CONCATENATION OF TWO NUMBERS. NUMBER TERMINATED, ADJUST EXPONENT NOW |
||
.,BD47 A5 5E LDA $5E |
FINE: LDA TENEXP |
Zahl gemäß |
get exponent count byte |
E-VALUE |
||
.,BD49 38 SEC |
FINE1: SEC |
Position |
set carry for subtract |
MODIFY WITH COUNT OF DIGITS |
||
.,BD4A E5 5D SBC $5D |
SBC DECCNT ;GET NUMBER OF PLACES TO SHIFT. |
des Dezimalpunkts |
subtract numerator exponent |
AFTER THE DECIMAL POINT |
||
.,BD4C 85 5E STA $5E |
STA TENEXP |
und Exponenten anpassen |
save exponent count byte |
COMPLETE CURRENT EXPONENT |
||
.,BD4E F0 12 BEQ $BD62 |
BEQ FINQNG ;NEGATE? |
Zahl= Null, dann zu $BD62 |
branch if no adjustment |
NO ADJUST NEEDED IF EXP=0 |
||
.,BD50 10 09 BPL $BD5B |
BPL FINMUL ;POSITIVE SO MULTIPLY. |
Zahl kleiner als $7F |
else if +ve go do FAC1*10^expcnt else go do FAC1/10^(0-expcnt) |
EXP>0, MULTIPLY BY TEN |
||
.,BD52 20 FE BA JSR $BAFE |
FINDIV: JSR DIV10 |
FAC = FAC / 10 |
divide FAC1 by 10 |
EXP<0, DIVIDE BY TEN |
||
.,BD55 E6 5E INC $5E |
INC TENEXP ;DONE? |
Zahl erhöhen |
increment exponent count byte |
UNTIL EXP=0 |
||
.,BD57 D0 F9 BNE $BD52 |
BNE FINDIV ;NO. |
unbedingter |
loop until all done |
|||
.,BD59 F0 07 BEQ $BD62 |
BEQ FINQNG ;YES. |
Sprung |
branch always |
...ALWAYS, WE ARE FINISHED |
||
.,BD5B 20 E2 BA JSR $BAE2 |
FINMUL: JSR MUL10 |
FAC = FAC * 10 |
multiply FAC1 by 10 |
EXP>0, MULTIPLY BKY TEN |
||
.,BD5E C6 5E DEC $5E |
DEC TENEXP ;DONE? |
Zahl gemäß |
decrement exponent count byte |
UNTIL EXP=0 |
||
.,BD60 D0 F9 BNE $BD5B |
BNE FINMUL ;NO |
Exponenten anpassen |
loop until all done |
|||
.,BD62 A5 67 LDA $67 |
FINQNG: LDA SGNFLG |
wenn negativ, |
get -ve flag |
IS WHOLE NUMBER NEGATIVE? |
||
.,BD64 30 01 BMI $BD67 |
BMI NEGXQS ;IF POSITIVE, RETURN. |
dann Vorzeichen invertieren |
if -ve do - FAC1 and return |
YES |
||
.,BD66 60 RTS |
RTS |
Rücksprung |
do - FAC1 and return |
NO, RETURN, WHOLE JOB DONE! |
||
.,BD67 4C B4 BF JMP $BFB4 |
NEGXQS: JMP NEGOP ;OTHERWISE, NEGATE AND RETURN. |
Vorzeichenwechsel FAC = -FAC |
do - FAC1 do unsigned FAC1*10+number |
NEGATIVE NUMBER, SO NEGATE FACACCUMULATE A DIGIT INTO FAC |
||
.,BD6A 48 PHA |
FINDIG: PHA |
Aufruf durch Mantisse |
save character |
SAVE DIGIT |
||
.,BD6B 24 5F BIT $5F |
BIT DPTFLG |
wenn Vorkommastelle, |
test decimal point flag |
SEEN A DECIMAL POINT YET? |
||
.,BD6D 10 02 BPL $BD71 |
BPL FINDG1 |
dann zu $BD71 |
skip exponent increment if not set |
NO, STILL IN INTEGER PART |
||
.,BD6F E6 5D INC $5D |
INC DECCNT |
Zähler erhöhen |
else increment number exponent |
YES, COUNT THE FRACTIONAL DIGIT |
||
.,BD71 20 E2 BA JSR $BAE2 |
FINDG1: JSR MUL10 |
FAC = FAC * 10 |
multiply FAC1 by 10 |
FAC = FAC * 10 |
||
.,BD74 68 PLA |
PLA ;GET IT BACK. |
ASCII in |
restore character |
CURRENT DIGIT |
||
.,BD75 38 SEC |
SEC |
Ziffer umwandeln |
set carry for subtract |
<<<SHORTER HERE TO JUST "AND #$0F">>> |
||
.,BD76 E9 30 SBC #$30 |
SBCI "0" |
'0' abziehen gibt hex |
convert to binary |
<<<TO CONVERT ASCII TO BINARY FORM>>> |
0 |
|
.,BD78 20 7E BD JSR $BD7E |
JSR FINLOG ;ADD IT IN. |
addiert nächste Stelle zu FAC |
evaluate new ASCII digit |
ADD THE DIGIT |
||
.,BD7B 4C 0A BD JMP $BD0A |
JMP FINC |
nächstes Zeichen |
go do next character evaluate new ASCII digit multiply FAC1 by 10 then (ABS) add in new digit |
GO BACK FOR MOREADD (A) TO FAC |
add signed integer from A to float accu |
|
.,BD7E 48 PHA |
FINLOG: PHA |
Wert aus Stack |
save digit |
SAVE ADDEND |
||
.,BD7F 20 0C BC JSR $BC0C |
JSR MOVAF ;SAVE FAC FOR LATER. |
FAC nach ARG |
round and copy FAC1 to FAC2 |
|||
.,BD82 68 PLA |
PLA |
Wert in Stack |
restore digit |
GET ADDEND AGAIN |
||
.,BD83 20 3C BC JSR $BC3C |
JSR FLOAT ;FLOAT THE VALUE IN ACCA. |
Accu in höchste Stelle von FAC |
save A as integer byte |
CONVERT TO FP VALUE IN FAC |
||
.,BD86 A5 6E LDA $6E |
LDA ARGSGN |
FAC-Vorzeichen und |
get FAC2 sign (b7) |
|||
.,BD88 45 66 EOR $66 |
EOR FACSGN |
ARG-Vorzeichen |
toggle with FAC1 sign (b7) |
|||
.,BD8A 85 6F STA $6F |
STA ARISGN ;RESULTANT SIGN. |
verknüpfen |
save sign compare (FAC1 EOR FAC2) |
|||
.,BD8C A6 61 LDX $61 |
LDX FACEXP ;SET SIGNS ON THING TO ADD. |
erste Stelle von FAC holen |
get FAC1 exponent |
TO SIGNAL IF FAC=0 |
||
.,BD8E 4C 6A B8 JMP $B86A |
JMP FADDT ;ADD TOGETHER AND RETURN. ;HERE PACK IN THE NEXT DIGIT OF THE EXPONENT. ;MULTIPLY THE OLD EXP BY 10 AND ADD IN THE NEXT ;DIGIT. NOTE: EXP OVERFLOW IS NOT CHECKED FOR. |
FAC = FAC + ARG |
add FAC2 to FAC1 and return evaluate next character of exponential part of number |
PERFORM THE ADDITIONACCUMULATE DIGIT OF EXPONENT |
get exponent of number from string |
|
.,BD91 A5 5E LDA $5E |
FINEDG: LDA TENEXP ;GET EXP SO FAR. |
Aufruf durch 'E' |
get exponent count byte |
CHECK CURRENT VALUE |
||
.,BD93 C9 0A CMP #$0A |
CMPI 12 ;WILL RESULT BE .GE. 100? |
wenn dritte Exponentenziffer, |
compare with 10 decimal |
FOR MORE THAN 2 DIGITS |
||
.,BD95 90 09 BCC $BDA0 |
BCC MLEX10 |
dann zu $BDA0 |
branch if less |
NO, THIS IS 1ST OR 2ND DIGIT |
||
.,BD97 A9 64 LDA #$64 |
LDAI 144 ;GET 100. |
wenn Vorzeichen |
make all -ve exponents = -100 decimal (causes underflow) |
EXPONENT TOO BIG |
||
.,BD99 24 60 BIT $60 |
BIT EXPSGN |
negativ, |
test exponent -ve flag |
UNLESS IT IS NEGATIVE |
||
.,BD9B 30 11 BMI $BDAE |
BMI MLEXMI ;IF NEG EXP, NO CHK FOR OVERR. |
dann Unterlauf |
branch if -ve |
LARGE NEGATIVE EXPONENT MAKES FAC=0 |
||
.,BD9D 4C 7E B9 JMP $B97E |
JMP OVERR |
zu 'OVERFLOW ERROR' |
else do overflow error then warm start |
LARGE POSITIVE EXPONENT IS ERROR |
||
.,BDA0 0A ASL |
MLEX10: ASL A, ;MULT BY 2 TWICE |
Den |
*2 |
EXPONENT TIMES 10 |
||
.,BDA1 0A ASL |
ASL A |
Exponenten |
*4 |
|||
.,BDA2 18 CLC |
CLC ;POSSIBLE SHIFT OUT OF HIGH. |
mit |
clear carry for add |
|||
.,BDA3 65 5E ADC $5E |
ADC TENEXP ;LIKE MULTIPLYING BY FIVE. |
10 |
*5 |
|||
.,BDA5 0A ASL |
ASL A, ;AND NOW BY TEN. |
multi- |
*10 |
|||
.,BDA6 18 CLC |
CLC |
plizieren |
clear carry for add |
<<< ASL ALREADY DID THIS! >>> |
||
.,BDA7 A0 00 LDY #$00 |
LDYI 0 |
Zähler setzen |
set index |
ADD THE NEW DIGIT |
||
.,BDA9 71 7A ADC ($7A),Y |
ADCDY TXTPTR |
Exponenten- |
add character (will be $30 too much!) |
BUT THIS IS IN ASCII, |
||
.,BDAB 38 SEC |
SEC |
ziffer |
set carry for subtract |
SO ADJUST BACK TO BINARY |
||
.,BDAC E9 30 SBC #$30 |
SBCI "0" |
addie- |
convert character to binary |
0 |
||
.,BDAE 85 5E STA $5E |
MLEXMI: STA TENEXP ;SAVE RESULT. |
ren |
save exponent count byte |
NEW VALUE |
||
.,BDB0 4C 30 BD JMP $BD30 |
JMP FINEC PAGE FLOATING POINT OUTPUT ROUTINE.IFE ADDPRC,<NZ0999: 221 ; 99999.9499 103 117 370 NZ9999: 224 ; 999999.499 164 043 367 NZMIL: 224 ; 10^6. 164 044 000> IFN ADDPRC,< |
nächstes Zeichen holenKonstanten für Fließkommanach ASCII |
go get next characterlimits for scientific mode |
BACK FOR MORE |
constants for float to string conversion |
|
.:BDB3 9B 3E BC 1F FD |
NZ0999: 233 ; 99999999.9499 076 274 037 375 |
99999999.9 |
99999999.90625, maximum value with at least one decimal |
99,999,999.9 |
||
.:BDB8 9E 6E 6B 27 FD |
NZ9999: 236 ; 999999999.499 156 153 047 375 |
999999999 |
999999999.25, maximum value before scientific notation |
999,999,999 |
||
.:BDBD 9E 6E 6B 28 00 |
NZMIL: 236 ; 10^9 156 153 050 000> ;ENTRY TO LINPRT. |
1E9Ausgabe der Zeilennummerbei Fehlermeldung |
1000000000do " IN " line number message |
1,000,000,000PRINT "IN <LINE #>" |
print IN followed by line number |
|
.,BDC2 A9 71 LDA #$71 |
INPRT: LDWDI INTXT |
Zeiger |
set " IN " pointer low byte |
PRINT " IN " |
low A371 |
|
.,BDC4 A0 A3 LDY #$A3 |
auf 'in' |
set " IN " pointer high byte |
high A371 |
|||
.,BDC6 20 DA BD JSR $BDDA |
JSR STROU2 |
String ausgeben |
print null terminated string |
|||
.,BDC9 A5 3A LDA $3A |
LDA CURLIN+1 |
laufende |
get the current line number high byte |
|||
.,BDCB A6 39 LDX $39 |
LDX CURLIN |
Zeilennummer holenpositive Integerzahlin A/X ausgeben |
get the current line number low byteprint XA as unsigned integer |
PRINT A,X AS DECIMAL INTEGER |
print number from AX |
|
.,BDCD 85 62 STA $62 |
LINPRT: STWX FACHO |
für Umwandlung |
save high byte as FAC1 mantissa1 |
PRINT A,X IN DECIMAL |
||
.,BDCF 86 63 STX $63 |
in FAC schreiben |
save low byte as FAC1 mantissa2 |
||||
.,BDD1 A2 90 LDX #$90 |
LDXI 220 ;EXPONENT OF 16. |
Exponent |
set exponent to 16d bits |
EXPONENT = 2^16 |
||
.,BDD3 38 SEC |
SEC ;NUMBER IS POSITIVE. |
= 16 |
set integer is +ve flag |
CONVERT UNSIGNED |
||
.,BDD4 20 49 BC JSR $BC49 |
JSR FLOATC |
Integer nach Fließkomma wandeln |
set exponent = X, clear mantissa 4 and 3 and normalise FAC1 |
CONVERT LINE # TO FPCONVERT (FAC) TO STRING, AND PRINT IT |
||
.,BDD7 20 DF BD JSR $BDDF |
JSR FOUT |
FAC nach ASCII wandeln |
convert FAC1 to string |
CONVERT (FAC) TO STRING AT STACKPRINT STRING STARTING AT Y,A |
||
.,BDDA 4C 1E AB JMP $AB1E |
STROU2: JMP STROUT ;PRINT AND RETURN. |
String ausgebenFAC nach ASCII-Formatwandeln und nach $100 |
print null terminated stringconvert FAC1 to ASCII string result in (AY) |
PRINT STRING AT A,YCONVERT (FAC) TO STRING STARTING AT STACKRETURN WITH (Y,A) POINTING AT STRING |
convert number in float accu to string |
|
.,BDDD A0 01 LDY #$01 |
FOUT: LDYI 1 |
Stringzeiger |
set index = 1 |
NORMAL ENTRY PUTS STRING AT STACK... |
||
.,BDDF A9 20 LDA #$20 |
FOUTC: LDAI " " ;PRINT SPACE IF POSITIVE. |
' ' Leerzeichen für positive Zahl |
character = " " (assume +ve) |
|||
.,BDE1 24 66 BIT $66 |
BIT FACSGN |
wenn Vorzeichen |
test FAC1 sign (b7) |
|||
.,BDE3 10 02 BPL $BDE7 |
BPL FOUT1 |
positiv ?, dann zu $BDE7 |
branch if +ve |
|||
.,BDE5 A9 2D LDA #$2D |
LDAI "-" |
'-' Minuszeichen für |
else character = "-" |
"STR$" FUNCTION ENTERS HERE, WITH (Y)=0SO THAT RESULT STRING STARTS AT STACK-1(THIS IS USED AS A FLAG) |
minus |
|
.,BDE7 99 FF 00 STA $00FF,Y |
FOUT1: STA FBUFFR-1,Y, ;STORE THE CHARACTER. |
negative Zahl in |
save leading character (" " or "-") |
EMIT "-" |
||
.,BDEA 85 66 STA $66 |
STA FACSGN ;MAKE FAC POS FOR QINT. |
Pufferbereich |
save FAC1 sign (b7) |
MAKE FAC.SIGN POSITIVE ($2D) |
||
.,BDEC 84 71 STY $71 |
STY FBUFPT ;SAVE FOR LATER. |
schreiben |
save index |
SAVE STRING PNTR |
||
.,BDEE C8 INY |
INY |
Zähler erhöhen |
increment index |
|||
.,BDEF A9 30 LDA #$30 |
LDAI "0" ;GET ZERO TO TYPE IF FAC=0. |
'0’ |
set character = "0" |
IN CASE (FAC)=0 |
0 |
|
.,BDF1 A6 61 LDX $61 |
LDX FACEXP |
Exponent |
get FAC1 exponent |
NUMBER=0? |
||
.,BDF3 D0 03 BNE $BDF8 |
JEQ FOUT19 |
wenn Zahl nicht null ? |
branch if FAC1<>0 exponent was $00 so FAC1 is 0 |
NO, (FAC) NOT ZERO |
||
.,BDF5 4C 04 BF JMP $BF04 |
dann fertig |
save last character, [EOT] and exit FAC1 is some non zero value |
YES, FINISHED |
|||
.,BDF8 A9 00 LDA #$00 |
LDAI 0 |
FAC |
clear (number exponent count) |
STARTING VALUE FOR TMPEXP |
||
.,BDFA E0 80 CPX #$80 |
CPXI 200 ;IS NUMBER .LT. 1.0 ? |
mit 1 vergleichen |
compare FAC1 exponent with $80 (<1.00000) |
ANY INTEGER PART? |
||
.,BDFC F0 02 BEQ $BE00 |
BEQ FOUT37 ;NO. |
wenn ja ,dann zu $BE00 |
branch if 0.5 <= FAC1 < 1.0 |
NO, BTWN .5 AND .999999999 |
||
.,BDFE B0 09 BCS $BE09 |
BCS FOUT7 |
FAC größer 1 |
branch if FAC1=>1 |
YES |
||
.,BE00 A9 BD LDA #$BD |
FOUT37: LDWDI NZMIL ;MULTIPLY BY 10^6. |
Zeiger auf |
set 1000000000 pointer low byte |
MULTIPLY BY 1E9 |
low BDBD |
|
.,BE02 A0 BD LDY #$BD |
Konstante 1E9 |
set 1000000000 pointer high byte |
TO GIVE ADJUSTMENT A HEAD START |
high BDBD |
||
.,BE04 20 28 BA JSR $BA28 |
JSR FMULT |
Konstante (Zeiger A/Y) * FAC |
do convert AY, FCA1*(AY) |
|||
.,BE07 A9 F7 LDA #$F7 |
LDAI ^D256-3*ADDPRC-6 |
= -9 |
set number exponent count |
EXPONENT ADJUSTMENT |
||
.,BE09 85 5D STA $5D |
FOUT7: STA DECCNT ;SAVE COUNT OR ZERO IT. |
$ 5D = -9 |
save number exponent count |
0 OR -9ADJUST UNTIL 1E8 <= (FAC) <1E9 |
||
.,BE0B A9 B8 LDA #$B8 |
FOUT4: LDWDI NZ9999 |
Zeiger auf |
set 999999999.25 pointer low byte (max before sci note) |
low BDB8 |
||
.,BE0D A0 BD LDY #$BD |
Konstante 999999999 |
set 999999999.25 pointer high byte |
high BDB8 |
|||
.,BE0F 20 5B BC JSR $BC5B |
JSR FCOMP ;IS NUMBER .GT. 999999.499 ? ;OR 999999999.499? |
Vergleich Konstante (Zeiger A/Y) mit FAC |
compare FAC1 with (AY) |
COMPARE TO 1E9-1 |
||
.,BE12 F0 1E BEQ $BE32 |
BEQ BIGGES |
gleich |
exit if FAC1 = (AY) |
(FAC) = 1E9-1 |
||
.,BE14 10 12 BPL $BE28 |
BPL FOUT9 ;YES. MAKE IT SMALLER. |
kleiner |
go do /10 if FAC1 > (AY) FAC1 < (AY) |
TOO LARGE, DIVIDE BY TEN |
||
.,BE16 A9 B3 LDA #$B3 |
FOUT3: LDWDI NZ0999 |
Zeiger auf |
set 99999999.90625 pointer low byte |
COMPARE TO 1E8-.1 |
low BDB3 |
|
.,BE18 A0 BD LDY #$BD |
Konstante 99999999.9 |
set 99999999.90625 pointer high byte |
high BDB3 |
|||
.,BE1A 20 5B BC JSR $BC5B |
JSR FCOMP ;IS NUMBER .GT. 99999.9499 ? ; OR 99999999.9499? |
Vergleich Konstante (Zeiger A/Y) mit FAC |
compare FAC1 with (AY) |
COMPARE TO 1E8-.1 |
||
.,BE1D F0 02 BEQ $BE21 |
BEQ FOUT38 |
gleich |
branch if FAC1 = (AY) (allow decimal places) |
(FAC) = 1E8-.1 |
||
.,BE1F 10 0E BPL $BE2F |
BPL FOUT5 ;YES. DONE MULTIPLYING. |
kleiner |
branch if FAC1 > (AY) (no decimal places) FAC1 <= (AY) |
IN RANGE, ADJUSTMENT FINISHED |
||
.,BE21 20 E2 BA JSR $BAE2 |
FOUT38: JSR MUL10 ;MAKE IT BIGGER. |
FAC = FAC * 10 |
multiply FAC1 by 10 |
TOO SMALL, MULTIPLY BY TEN |
||
.,BE24 C6 5D DEC $5D |
DEC DECCNT |
Dezimalexponent erniedrigen |
decrement number exponent count |
KEEP TRACK OF MULTIPLIES |
||
.,BE26 D0 EE BNE $BE16 |
BNE FOUT3 ;SEE IF THAT DOES IT. ;THIS ALWAYS GOES. |
schon 0? |
go test again, branch always |
...ALWAYS |
||
.,BE28 20 FE BA JSR $BAFE |
FOUT9: JSR DIV10 ;MAKE IT SMALLER. |
FAC = FAC / 10 |
divide FAC1 by 10 |
TOO LARGE, DIVIDE BY TEN |
||
.,BE2B E6 5D INC $5D |
INC DECCNT |
Dezimalexponent erhöhen |
increment number exponent count |
KEEP TRACK OF DIVISIONS |
||
.,BE2D D0 DC BNE $BE0B |
BNE FOUT4 ;SEE IF THAT DOES IT. ;THIS ALWAYS GOES. |
Überlauf ? |
go test again, branch always now we have just the digits to do |
...ALWAYS |
||
.,BE2F 20 49 B8 JSR $B849 |
FOUT5: JSR FADDH ;ADD A HALF TO ROUND UP. |
FAC = FAC + .5 , runden |
add 0.5 to FAC1 (round FAC1) |
ROUND ADJUSTED RESULT |
||
.,BE32 20 9B BC JSR $BC9B |
BIGGES: JSR QINT |
FAC nach Integer |
convert FAC1 floating to fixed |
CONVERT ADJUSTED VALUE TO 32-BIT INTEGER FAC+1...FAC+4 IS NOW IN INTEGER FORM WITH POWER OF TEN ADJUSTMENT IN TMPEXP IF -10 < TMPEXP > 1, PRINT IN DECIMAL FORM OTHERWISE, PRINT IN EXPONENTIAL FORM |
||
.,BE35 A2 01 LDX #$01 |
LDXI 1 ;DECIMAL POINT COUNT. |
FAC ist nun im Bereich von |
set default digits before dp = 1 |
ASSUME 1 DIGIT BEFORE "." |
||
.,BE37 A5 5D LDA $5D |
LDA DECCNT |
1E8 bis 1E9, $5D hat Wert |
get number exponent count |
CHECK RANGE |
||
.,BE39 18 CLC |
CLC |
von Zehnerpotenz |
clear carry for add |
|||
.,BE3A 69 0A ADC #$0A |
ADCI 3*ADDPRC+7 ;SHOULD NUMBER BE PRINTED IN E NOTATION? ;IE, IS NUMBER .LT. .01 ? |
Zahl =0.01 |
up to 9 digits before point |
|||
.,BE3C 30 09 BMI $BE47 |
BMI FOUTPI ;YES. |
Betrag kleiner 0.1 ? |
if -ve then 1 digit before dp |
< .01, USE EXPONENTIAL FORM |
||
.,BE3E C9 0B CMP #$0B |
CMPI 3*ADDPRC+10 ;IS IT .GT. 999999 (999999999)? |
wenn ja, dann |
A>=$0B if n>=1E9 |
|||
.,BE40 B0 06 BCS $BE48 |
BCS FOUT6 ;YES. USE E NOTATION. |
Betrag größer 1E9 ? |
branch if >= $0B carry is clear |
>= 1E10, USE EXPONENTIAL FORM |
||
.,BE42 69 FF ADC #$FF |
ADCI ^O377 ;NUMBER OF PLACES BEFORE DECIMAL POINT. |
die |
take 1 from digit count |
LESS 1 GIVES INDEX FOR "." |
||
.,BE44 AA TAX |
TAX ;PUT INTO ACCX. |
Be- |
copy to X |
|||
.,BE45 A9 02 LDA #$02 |
LDAI 2 ;NO E NOTATION. |
rechnung |
set exponent adjust |
SET REMAINING EXPONENT = 0 |
||
.,BE47 38 SEC |
FOUTPI: SEC |
des |
set carry for subtract |
COMPUTE REMAINING EXPONENT |
||
.,BE48 E9 02 SBC #$02 |
FOUT6: SBCI 2 ;EFFECTIVELY ADD 5 TO ORIG EXP. |
Exponenten- |
-2 |
|||
.,BE4A 85 5E STA $5E |
STA TENEXP ;THAT IS THE EXPONENT TO PRINT. |
flags |
save exponent adjust |
VALUE FOR "E+XX" OR "E-XX" |
||
.,BE4C 86 5D STX $5D |
STX DECCNT ;NUMBER OF DECIMAL PLACES. |
Negative Darstellung des |
save digits before dp count |
INDEX FOR DECIMAL POINT |
||
.,BE4E 8A TXA |
TXA |
Exponenten |
copy to A |
SEE IF "." COMES FIRST |
||
.,BE4F F0 02 BEQ $BE53 |
BEQ FOUT39 |
wenn 0.1, dann zu $BE53 |
branch if no digits before dp |
YES |
||
.,BE51 10 13 BPL $BE66 |
BPL FOUT8 ;SOME PLACES BEFORE DEC PNT. |
wenn nicht 0.01, dann zu $BE66 |
branch if digits before dp |
NO, LATER |
||
.,BE53 A4 71 LDY $71 |
FOUT39: LDY FBUFPT ;GET POINTER TO OUTPUT. |
Zeiger für Polynomauswertung |
get output string index |
GET INDEX INTO STRING BEING BUILT |
||
.,BE55 A9 2E LDA #$2E |
LDAI "." ;PUT IN "." |
Nummer für '.' |
character "." |
STORE A DECIMAL POINT |
decimal point |
|
.,BE57 C8 INY |
INY |
Zeiger erhöhen |
increment index |
|||
.,BE58 99 FF 00 STA $00FF,Y |
STA FBUFFR-1,Y |
in Stringbereich |
save to output string |
|||
.,BE5B 8A TXA |
TXA |
schreiben |
SEE IF NEED ".0" |
|||
.,BE5C F0 06 BEQ $BE64 |
BEQ FOUT16 |
wenn 0.1, dann zu $BE64 |
NO |
|||
.,BE5E A9 30 LDA #$30 |
LDAI "0" ;GET THE ENSUING ZERO. |
Nummer für '0' |
character "0" |
YES, STORE "0" |
0 |
|
.,BE60 C8 INY |
INY |
Zeiger erhöhen |
increment index |
|||
.,BE61 99 FF 00 STA $00FF,Y |
STA FBUFFR-1,Y |
in Stringbereich |
save to output string |
|||
.,BE64 84 71 STY $71 |
FOUT16: STY FBUFPT ;SAVE FOR LATER. |
schreiben |
save output string index |
SAVE OUTPUT INDEX AGAIN NOW DIVIDE BY POWERS OF TEN TO GET SUCCESSIVE DIGITS |
||
.,BE66 A0 00 LDY #$00 |
FOUT8: LDYI 0 |
Zeiger |
clear index (point to 100,000) |
INDEX TO TABLE OF POWERS OF TEN |
||
.,BE68 A2 80 LDX #$80 |
FOUTIM: LDXI 200 ;FIRST PASS THRU, ACCX HAS MSB SET. |
stellen |
STARTING VALUE FOR DIGIT WITH DIRECTION |
|||
.,BE6A A5 65 LDA $65 |
FOUT2: LDA FACLO |
Durch |
get FAC1 mantissa 4 |
START BY ADDING -100000000 UNTIL |
||
.,BE6C 18 CLC |
CLC |
Addition |
clear carry for add |
OVERSHOOT. THEN ADD +10000000, |
||
.,BE6D 79 19 BF ADC $BF19,Y |
ADC FOUTBL+2+ADDPRC,Y |
und |
add byte 4, least significant |
THEN ADD -1000000, THEN ADD |
||
.,BE70 85 65 STA $65 |
STA FACLO |
Subtraktion |
save FAC1 mantissa4 |
+100000, AND SO ON. |
||
.,BE72 A5 64 LDA $64 |
LDA FACMO |
der |
get FAC1 mantissa 3 |
THE # OF TIMES EACH POWER IS ADDED |
||
.,BE74 79 18 BF ADC $BF18,Y |
ADC FOUTBL+1+ADDPRC,Y |
Werte |
add byte 3 |
IS 1 MORE THAN CORRESPONDING DIGIT |
||
.,BE77 85 64 STA $64 |
STA FACMO IFN ADDPRC,< |
aus |
save FAC1 mantissa3 |
|||
.,BE79 A5 63 LDA $63 |
LDA FACMOH |
der |
get FAC1 mantissa 2 |
|||
.,BE7B 79 17 BF ADC $BF17,Y |
ADC FOUTBL+1,Y |
Tabelle |
add byte 2 |
|||
.,BE7E 85 63 STA $63 |
STA FACMOH> |
werden |
save FAC1 mantissa2 |
|||
.,BE80 A5 62 LDA $62 |
LDA FACHO |
die |
get FAC1 mantissa 1 |
|||
.,BE82 79 16 BF ADC $BF16,Y |
ADC FOUTBL,Y |
einzelnen |
add byte 1, most significant |
|||
.,BE85 85 62 STA $62 |
STA FACHO |
Ziffern |
save FAC1 mantissa1 |
|||
.,BE87 E8 INX |
INX ;IT WAS DONE YET ANOTHER TIME. |
des |
increment the digit, set the sign on the test sense bit |
COUNT THE ADD |
||
.,BE88 B0 04 BCS $BE8E |
BCS FOUT41 |
Zahlen- |
if the carry is set go test if the result was positive else the result needs to be negative |
IF C=1 AND X NEGATIVE, KEEP ADDING |
||
.,BE8A 10 DE BPL $BE6A |
BPL FOUT2 |
Strings |
not -ve so try again |
IF C=0 AND X POSITIVE, KEEP ADDING |
||
.,BE8C 30 02 BMI $BE90 |
BMI FOUT40 |
be- |
else done so return the digit |
IF C=0 AND X NEGATIVE, WE OVERSHOT |
||
.,BE8E 30 DA BMI $BE6A |
FOUT41: BMI FOUT2 |
rech- |
not +ve so try again else done so return the digit |
IF C=1 AND X POSITIVE, WE OVERSHOT |
||
.,BE90 8A TXA |
FOUT40: TXA |
net |
copy the digit |
OVERSHOT, SO MAKE X INTO A DIGIT |
||
.,BE91 90 04 BCC $BE97 |
BCC FOUTYP ;CAN USE ACCA AS IS. |
alles addiert?, wenn nicht, dann zu $BE97 |
if Cb=0 just use it |
HOW DEPENDS ON DIRECTION WE WERE GOING |
||
.,BE93 49 FF EOR #$FF |
EORI 377 ;FIND 11.-[A]. |
Ergebnis mit 10 |
else make the 2's complement .. |
DIGIT = 9-X |
||
.,BE95 69 0A ADC #$0A |
ADCI 12 ;C IS STILL ON TO COMPLETE NEGATION. ;AND WILL ALWAYS BE ON AFTER. |
komplementieren |
.. and subtract it from 10 |
|||
.,BE97 69 2F ADC #$2F |
FOUTYP: ADCI "0"-1 ;GET A CHARACTER TO PRINT. |
'0' - 1 |
add "0"-1 to result |
MAKE DIGIT INTO ASCII |
||
.,BE99 C8 INY |
REPEAT 3+ADDPRC,<INY> ;BUMP POINTER UP. |
Zähler |
increment .. |
ADVANCE TO NEXT SMALLER POWER OF TEN |
||
.,BE9A C8 INY |
ent- |
.. index to.. |
||||
.,BE9B C8 INY |
sprechend |
.. next less .. |
||||
.,BE9C C8 INY |
erhöhen |
.. power of ten |
||||
.,BE9D 84 47 STY $47 |
STY FDECPT |
Zähler sichern |
save current variable pointer low byte |
SAVE PNTR TO POWERS |
||
.,BE9F A4 71 LDY $71 |
LDY FBUFPT |
Zeiger auf Stringbereich laden |
get output string index |
GET OUTPUT PNTR |
||
.,BEA1 C8 INY |
INY ;POINT TO PLACE TO STORE OUTPUT. |
und erhöhen |
increment output string index |
STORE THE DIGIT |
||
.,BEA2 AA TAX |
TAX |
Ziffer |
copy character to X |
SAVE DIGIT, HI-BIT IS DIRECTION |
||
.,BEA3 29 7F AND #$7F |
ANDI 177 ;GET RID OF MSB. |
in |
mask out top bit |
MAKE SURE $30...$39 FOR STRING |
||
.,BEA5 99 FF 00 STA $00FF,Y |
STA FBUFFR-1,Y |
Stringbereich |
save to output string |
|||
.,BEA8 C6 5D DEC $5D |
DEC DECCNT |
bringen |
decrement # of characters before the dp |
COUNT THE DIGIT |
||
.,BEAA D0 06 BNE $BEB2 |
BNE STXBUF ;NOT TIME FOR DP YET. |
wenn Einerstelle nicht erreicht, dann zu $BEB2 |
branch if still characters to do else output the point |
NOT TIME FOR "." YET |
||
.,BEAC A9 2E LDA #$2E |
LDAI "." |
Nummer für '.' |
character "." |
TIME, SO STORE THE DECIMAL POINT |
||
.,BEAE C8 INY |
INY |
Zähler erhöhen |
increment output string index |
|||
.,BEAF 99 FF 00 STA $00FF,Y |
STA FBUFFR-1,Y, ;STORE DP. |
in Stringbereich schreiben |
save to output string |
|||
.,BEB2 84 71 STY $71 |
STXBUF: STY FBUFPT ;STORE PNTR FOR LATER. |
Zähler speichern |
save output string index |
SAVE OUTPUT PNTR AGAIN |
||
.,BEB4 A4 47 LDY $47 |
LDY FDECPT |
Neuen Zähler holen |
get current variable pointer low byte |
GET PNTR TO POWERS |
||
.,BEB6 8A TXA |
FOUTCM: TXA ;COMPLEMENT ACCX |
FAC- |
get character back |
GET DIGIT WITH HI-BIT = DIRECTION |
||
.,BEB7 49 FF EOR #$FF |
EORI 377 ;COMPLEMENT ACCA. |
Um- |
toggle the test sense bit |
CHANGE DIRECTION |
||
.,BEB9 29 80 AND #$80 |
ANDI 200 ;SAVE ONLY MSB. |
wand- |
clear the digit |
$00 IF ADDING, $80 IF SUBTRACTING |
||
.,BEBB AA TAX |
TAX |
lung |
copy it to the new digit |
|||
.,BEBC C0 24 CPY #$24 |
CPYI FDCEND-FOUTBL IFN TIME,< |
Tabellenende ereicht, |
compare the table index with the max for decimal numbers |
|||
.,BEBE F0 04 BEQ $BEC4 |
BEQ FOULDY |
dann zu $BEC4 |
if at the max exit the digit loop |
|||
.,BEC0 C0 3C CPY #$3C |
CPYI TIMEND-FOUTBL> |
Tabellenende bei TI$-Berechnung |
compare the table index with the max for time |
|||
.,BEC2 D0 A6 BNE $BE6A |
BNE FOUT2 ;CONTINUE WITH OUTPUT. |
nicht erreicht, dann zu $BE6A |
loop if not at the max now remove trailing zeroes |
NOT FINISHED YET NINE DIGITS HAVE BEEN STORED IN STRING. NOW LOOK BACK AND LOP OFF TRAILING ZEROES AND A TRAILING DECIMAL POINT. |
||
.,BEC4 A4 71 LDY $71 |
FOULDY: LDY FBUFPT ;GET BACK OUTPUT PNTR. |
Zähler wieder holen |
restore the output string index |
POINTS AT LAST STORED CHAR |
||
.,BEC6 B9 FF 00 LDA $00FF,Y |
FOUT11: LDA FBUFFR-1,Y, ;REMOVE TRAILING ZEROES. |
letzte Stelle suchen |
get character from output string |
SEE IF LOPPABLE |
||
.,BEC9 88 DEY |
DEY |
Zähler erniedrigen |
decrement output string index |
|||
.,BECA C9 30 CMP #$30 |
CMPI "0" |
Nummer für '0' |
compare with "0" |
SUPPRESS TRAILING ZEROES |
0 |
|
.,BECC F0 F8 BEQ $BEC6 |
BEQ FOUT11 |
wenn ja, dann zu $BEC6 |
loop until non "0" character found |
YES, KEEP LOOPING |
||
.,BECE C9 2E CMP #$2E |
CMPI "." |
Nummer für '.' |
compare with "." |
SUPPRESS TRAILING DECIMAL POINT |
decimal point |
|
.,BED0 F0 01 BEQ $BED3 |
BEQ FOUT12 ;RUN INTO DP. STOP. |
wenn ja, dann zu $BED3 |
branch if was dp restore last character |
".", SO WRITE OVER IT |
||
.,BED2 C8 INY |
INY ;SOMETHING ELSE. SAVE IT. |
Zähler erhöhen |
increment output string index |
NOT ".", SO INCLUDE IN STRING AGAIN |
||
.,BED3 A9 2B LDA #$2B |
FOUT12: LDAI "+" |
Nummer für '+' |
character "+" |
PREPARE FOR POSITIVE EXPONENT "E+XX" |
plus |
|
.,BED5 A6 5E LDX $5E |
LDX TENEXP |
wenn Flag nicht gesetzt, |
get exponent count |
SEE IF ANY E-VALUE |
||
.,BED7 F0 2E BEQ $BF07 |
BEQ FOUT17 ;NO EXPONENT TO OUTPUT. |
dann zu $BF07 |
if zero go set null terminator and exit exponent isn't zero so write exponent |
NO, JUST MARK END OF STRING |
||
.,BED9 10 08 BPL $BEE3 |
BPL FOUT14 |
wenn Exponent positiv, dann zu $BEE3 |
branch if exponent count +ve |
YES, AND IT IS POSITIVE |
||
.,BEDB A9 00 LDA #$00 |
LDAI 0 |
Den |
clear A |
YES, AND IT IS NEGATIVE |
||
.,BEDD 38 SEC |
SEC |
Exponenten |
set carry for subtract |
COMPLEMENT THE VALUE |
||
.,BEDE E5 5E SBC $5E |
SBC TENEXP |
be- |
subtract exponent count adjust (convert -ve to +ve) |
|||
.,BEE0 AA TAX |
TAX |
rechnen |
copy exponent count to X |
GET MAGNITUDE IN X |
||
.,BEE1 A9 2D LDA #$2D |
LDAI "-" ;EXPONENT IS NEGATIVE. |
Nummer für '-' |
character "-" |
E SIGN |
minus |
|
.,BEE3 99 01 01 STA $0101,Y |
FOUT14: STA FBUFFR-1+2,Y, ;STORE SIGN OF EXP |
in Stringbereich schreiben |
save to output string |
STORE SIGN IN STRING |
||
.,BEE6 A9 45 LDA #$45 |
LDAI "E" |
Nummer für 'E' |
character "E" |
STORE "E" IN STRING BEFORE SIGN |
||
.,BEE8 99 00 01 STA $0100,Y |
STA FBUFFR-1+1,Y, ;STORE THE "E" CHARACTER. |
in Stringbereich schreiben |
save exponent sign to output string |
|||
.,BEEB 8A TXA |
TXA |
Zehner- |
get exponent count back |
EXPONENT MAGNITUDE IN A-REG |
||
.,BEEC A2 2F LDX #$2F |
LDXI "0"-1 |
stelle |
one less than "0" character |
SEED FOR EXPONENT DIGIT |
||
.,BEEE 38 SEC |
SEC |
für |
set carry for subtract |
CONVERT TO DECIMAL |
||
.,BEEF E8 INX |
FOUT15: INX ;MOVE CLOSER TO OUTPUT VALUE. |
den |
increment 10's character |
COUNT THE SUBTRACTION |
||
.,BEF0 E9 0A SBC #$0A |
SBCI 12 ;SUBTRACT 10. |
Exponenten |
subtract 10 from exponent count |
TEN'S DIGIT |
||
.,BEF2 B0 FB BCS $BEEF |
BCS FOUT15 ;NOT NEGATIVE YET. |
berechnen |
loop while still >= 0 |
MORE TENS TO SUBTRACT |
||
.,BEF4 69 3A ADC #$3A |
ADCI "0"+12 ;GET SECOND OUTPUT CHARACTER. |
'9' + 1 |
add character ":" ($30+$0A, result is 10 less that value) |
CONVERT REMAINDER TO ONE'S DIGIT |
||
.,BEF6 99 03 01 STA $0103,Y |
STA FBUFFR-1+4,Y, ;STORE HIGH DIGIT. |
in Stringbereich schreiben |
save to output string |
STORE ONE'S DIGIT |
||
.,BEF9 8A TXA |
TXA |
Zehnerstelle |
copy 10's character |
|||
.,BEFA 99 02 01 STA $0102,Y |
STA FBUFFR-1+3,Y, ;STORE LOW DIGIT. |
in Stringbereich schreiben |
save to output string |
STORE TEN'S DIGIT |
||
.,BEFD A9 00 LDA #$00 |
LDAI 0 ;PUT IN TERMINATOR. |
Puffer mit $0 |
set null terminator |
MARK END OF STRING WITH $00 |
||
.,BEFF 99 04 01 STA $0104,Y |
STA FBUFFR-1+5,Y, |
abschließen |
save to output string |
|||
.,BF02 F0 08 BEQ $BF0C |
BEQA FOUT20 ;RETURN. (ALWAYS BRANCHES). |
unbedingter Sprung |
go set string pointer (AY) and exit, branch always save last character, [EOT] and exit |
...ALWAYS |
||
.,BF04 99 FF 00 STA $00FF,Y |
FOUT19: STA FBUFFR-1,Y, ;STORE THE CHARACTER. |
Puffer |
save last character to output string set null terminator and exit |
STORE "0" IN ASCII |
||
.,BF07 A9 00 LDA #$00 |
FOUT17: LDAI 0 ;A TERMINATOR. |
mit $0 |
set null terminator |
STORE $00 ON END OF STRING |
||
.,BF09 99 00 01 STA $0100,Y |
STA FBUFFR-1+1,Y |
abschließen |
save after last character set string pointer (AY) and exit |
|||
.,BF0C A9 00 LDA #$00 |
FOUT20: LDWDI FBUFFR |
Zeiger auf |
set result string pointer low byte |
POINT Y,A AT BEGINNING OF STRING |
low 0100 |
|
.,BF0E A0 01 LDY #$01 |
Puffer $100 |
set result string pointer high byte |
(STR$ STARTED STRING AT STACK-1, BUT |
high 0100 |
||
.,BF10 60 RTS |
FPWRRT: RTS ;ALL DONE. |
Rücksprung |
constants |
STR$ DOESN'T USE Y,A ANYWAY.) |
0.5 |
|
.:BF11 80 00 00 00 00 |
FHALF: 200 ;1/2 000 ZERO: 000 000 IFN ADDPRC,<0> ;POWER OF TEN TABLE IFE ADDPRC,< FOUTBL: 376 ;-100000 171 140 000 ;10000 047 020 377 ;-1000 374 030 000 ;100 000 144 377 ;-10 377 366 000 ;1 000 001> IFN ADDPRC,< |
Konstante 0.5 für SQR-Funktion Konstanten für Gleitkommanach ASCII(32-Bit Binärzahlen mit Vorzeichen) |
0.5, first two bytes |
POWERS OF 10 FROM 1E8 DOWN TO 1,AS 32-BIT INTEGERS, WITH ALTERNATING SIGNS |
divisors for decimal conversion |
|
.:BF16 FA 0A 1F 00 |
FOUTBL: 372 ;-100,000,000 012 037 000 |
-100 000 000 |
null return for undefined variables -100 000 000 |
-100000000 |
||
.:BF1A 00 98 96 80 |
000 ;10,000,000 230 226 200 |
10 000 000 |
+10 000 000 |
10000000 |
||
.:BF1E FF F0 BD C0 |
377 ;-1,000,000 360 275 300 |
-1 000 000 |
-1 000 000 |
-1000000 |
||
.:BF22 00 01 86 A0 |
000 ;100,000 001 206 240 |
100 000 |
+100 000 |
100000 |
||
.:BF26 FF FF D8 F0 |
377 ;-10,000 377 330 360 |
-10 000 |
-10 000 |
-10000 |
||
.:BF2A 00 00 03 E8 |
000 ;1000 000 003 350 |
1 000 |
+1 000 |
1000 |
||
.:BF2E FF FF FF 9C |
377 ;-100 377 377 234 |
- 100 |
- 100 |
-100 |
||
.:BF32 00 00 00 0A |
000 ;10 000 000 012 |
10 |
+10 |
10 |
||
.:BF36 FF FF FF FF |
377 ;-1 377 377 377> FDCEND: IFN TIME,< |
-1Konstanten für UmwandlungTI nach TI$ |
-1jiffy counts |
-1 |
divisors for time conversion |
|
.:BF3A FF DF 0A 80 |
377 ; -2160000 FOR TIME CONVERTER. 337 012 200 |
-2 160 000 |
-2160000 10s hours |
|||
.:BF3E 00 03 4B C0 |
000 ; 216000 003 113 300 |
216 000 |
+216000 hours |
|||
.:BF42 FF FF 73 60 |
377 ; -36000 377 163 140 |
-36 000 |
-36000 10s mins |
|||
.:BF46 00 00 0E 10 |
000 ; 3600 000 016 020 |
3 600 |
+3600 mins |
|||
.:BF4A FF FF FD A8 |
377 ; -600 377 375 250 |
- 600 |
-600 10s secs |
|||
.:BF4E 00 00 00 3C |
000 ; 60 000 000 074 TIMEND:> |
60 |
+60 secsnot referenced |
unusedis this some version id? |
||
.:BF52 EC |
checksum bytespare bytes, not referenced |
unused |
||||
.:BF53 AA AA AA AA AA | ||||||
.:BF58 AA AA AA AA AA AA AA AA | ||||||
.:BF60 AA AA AA AA AA AA AA AA | ||||||
.:BF68 AA AA AA AA AA AA AA AA | ||||||
.:BF70 AA |
PAGEEXPONENTIATION AND SQUARE ROOT FUNCTION.;SQUARE ROOT FUNCTION --- SQR(A);USE SQR(X)=X^.5 |
BASIC-Funktion SQR |
perform SQR() |
"SQR" FUNCTION<<< UNFORTUNATELY, RATHER THAN A NEWTON-RAPHSON >>><<< ITERATION, MS BASIC USES EXPONENTIATION >>> <<< SQR(X) = X^.5 >>> |
SQR function |
|
.,BF71 20 0C BC JSR $BC0C |
SQR: JSR MOVAF ;MOVE FAC INTO ARG. |
FAC runden und nach ARG |
round and copy FAC1 to FAC2 |
|||
.,BF74 A9 11 LDA #$11 |
LDWDI FHALF |
Zeiger auf |
set 0.5 pointer low address |
SET UP POWER OF 0.5 |
||
.,BF76 A0 BF LDY #$BF |
Konstante 0.5Potenzierung FAC = ARGhoch Konstante (A/Y) |
set 0.5 pointer high address |
||||
.,BF78 20 A2 BB JSR $BBA2 |
JSR MOVFM ;PUT MEMORY INTO FAC. ;LAST THING FETCHED IS FACEXP. INTO ACCX. ; JMP FPWRT ;FALL INTO FPWRT. ;EXPONENTIATION --- X^Y. ;N.B. 0^0=1 ;FIRST CHECK IF Y=0. IF SO, THE RESULT IS 1. ;NEXT CHECK IF X=0. IF SO THE RESULT IS 0. ;THEN CHECK IF X.GT.0. IF NOT CHECK THAT Y IS AN INTEGER. ;IF SO, NEGATE X, SO THAT LOG DOESN'T GIVE FCERR. ;IF X IS NEGATIVE AND Y IS ODD, NEGATE THE RESULT ;RETURNED BY EXP. ;TO COMPUTE THE RESULT USE X^Y=EXP((Y*LOG(X)). |
Konstante nach FACPotenzierung FAC = ARGhoch FAC |
unpack memory (AY) into FAC1perform power function |
EXPONENTIATION OPERATIONARG ^ FAC = EXP( LOG(ARG) * FAC ) |
power operator |
|
.,BF7B F0 70 BEQ $BFED |
FPWRT: BEQ EXP ;IF FAC=0, JUST EXPONENTIATE THAT. |
wenn FAC=0, dann zu $BFED |
perform EXP() |
IF FAC=0, ARG^FAC=EXP(0) |
||
.,BF7D A5 69 LDA $69 |
LDA ARGEXP ;IS X=0? |
Exponent ARG = Basis |
get FAC2 exponent |
IF ARG=0, ARG^FAC=0 |
||
.,BF7F D0 03 BNE $BF84 |
BNE FPWRT1 |
nicht null ?, |
branch if FAC2<>0 |
NEITHER IS ZERO |
||
.,BF81 4C F9 B8 JMP $B8F9 |
JMP ZEROF1 ;ZERO FAC. |
dann fertig |
clear FAC1 exponent and sign and return |
SET FAC = 0 |
||
.,BF84 A2 4E LDX #$4E |
FPWRT1: LDXYI TEMPF3 ;SAVE FOR LATER IN A TEMP. |
Zeiger auf |
set destination pointer low byte |
SAVE FAC IN TEMP3 |
low 004E |
|
.,BF86 A0 00 LDY #$00 |
Hilfsakku |
set destination pointer high byte |
high 004E |
|||
.,BF88 20 D4 BB JSR $BBD4 |
JSR MOVMF ;Y=0 ALREADY. GOOD IN CASE NO ONE CALLS INT. |
FAC nach Hilfsakku |
pack FAC1 into (XY) |
|||
.,BF8B A5 6E LDA $6E |
LDA ARGSGN |
Exponent FAC = Potenzexponent |
get FAC2 sign (b7) |
NORMALLY, ARG MUST BE POSITIVE |
||
.,BF8D 10 0F BPL $BF9E |
BPL FPWR1 ;NO PROBLEMS IF X.GT.0. |
kleiner eins ?, |
branch if FAC2>0 else FAC2 is -ve and can only be raised to an integer power which gives an x + j0 result |
IT IS POSITIVE, SO ALL IS WELL |
||
.,BF8F 20 CC BC JSR $BCCC |
JSR INT ;INTEGERIZE THE FAC. |
dann INT-Funktion |
perform INT() |
NEGATIVE, BUT OK IF INTEGRAL POWER |
||
.,BF92 A9 4E LDA #$4E |
LDWDI TEMPF3 ;GET ADDR OF COMPERAND. |
Zeiger auf |
set source pointer low byte |
SEE IF INT(FAC)=FAC |
low 004E |
|
.,BF94 A0 00 LDY #$00 |
Hilfsakku |
set source pointer high byte |
high 004E |
|||
.,BF96 20 5B BC JSR $BC5B |
JSR FCOMP ;EQUAL? |
mit FAC vergleichen |
compare FAC1 with (AY) |
IS IT AN INTEGER POWER? |
||
.,BF99 D0 03 BNE $BF9E |
BNE FPWR1 ;LEAVE X NEG. LOG WILL BLOW HIM OUT. ;A=-1 AND Y IS IRRELEVANT. |
Exponent nicht ganzzahlig, dann zu $BF9E |
branch if FAC1 <> (AY) to allow Function Call error this will leave FAC1 -ve and cause a Function Call error when LOG() is called |
NOT INTEGRAL, WILL CAUSE ERROR LATER |
||
.,BF9B 98 TYA |
TYA ;NEGATE X. MAKE POSITIVE. |
Akku= 4 |
clear sign b7 |
MAKE ARG SIGN + AS IT IS MOVED TO FAC |
||
.,BF9C A4 07 LDY $07 |
LDY INTEGR ;GET EVENNESS. |
Exponentenstelle |
get FAC1 mantissa 4 from INT() function as sign in Y for possible later negation, b0 only needed |
INTEGRAL, SO ALLOW NEGATIVE ARG |
||
.,BF9E 20 FE BB JSR $BBFE |
FPWR1: JSR MOVFA1 ;ALTERNATE ENTRY POINT. |
ARG nach FAC |
save FAC1 sign and copy ABS(FAC2) to FAC1 |
MOVE ARGUMENT TO FAC |
||
.,BFA1 98 TYA |
TYA |
Exponentenstelle |
copy sign back .. |
SAVE FLAG FOR NEGATIVE ARG (0=+) |
||
.,BFA2 48 PHA |
PHA ;SAVE EVENNESS FOR LATER. |
in Stack |
.. and save it |
|||
.,BFA3 20 EA B9 JSR $B9EA |
JSR LOG ;FIND LOG. |
LOG-Funktion |
perform LOG() |
GET LOG(ARG) |
||
.,BFA6 A9 4E LDA #$4E |
LDWDI TEMPF3 ;MULTIPLY FAC TIMES LOG(X). |
Zeiger auf |
set pointer low byte |
MULTIPLY BY POWER |
low 004E |
|
.,BFA8 A0 00 LDY #$00 |
Hilfsakku |
set pointer high byte |
high 004E |
|||
.,BFAA 20 28 BA JSR $BA28 |
JSR FMULT |
mit FAC multiplizieren |
do convert AY, FCA1*(AY) |
|||
.,BFAD 20 ED BF JSR $BFED |
JSR EXP ;EXPONENTIATE THE FAC. |
EXP-Funktion |
perform EXP() |
E ^ LOG(FAC) |
||
.,BFB0 68 PLA |
PLA |
Exponent aus Stack |
pull sign from stack |
GET FLAG FOR NEGATIVE ARG |
||
.,BFB1 4A LSR |
LSR A, ;IS IT EVEN? |
wenn Exponent gradzahlig, |
b0 is to be tested |
<<<LSR,BCC COULD BE MERELY BPL>>> |
||
.,BFB2 90 0A BCC $BFBE |
BCC NEGRTS ;YES. OR X.GT.0. ;NEGATE THE NUMBER IN FAC. |
dann fertigVorzeichenwechsel |
if no bit then exit do - FAC1 |
NOT NEGATIVE, FINISHED NEGATIVE ARG, SO NEGATE RESULT NEGATE VALUE IN FAC |
minus operator |
|
.,BFB4 A5 61 LDA $61 |
NEGOP: LDA FACEXP |
Exponent |
get FAC1 exponent |
IF FAC=0, NO NEED TO COMPLEMENT |
||
.,BFB6 F0 06 BEQ $BFBE |
BEQ NEGRTS |
Zahl gleich null, dann fertig |
exit if FAC1_e = $00 |
YES, FAC=0 |
||
.,BFB8 A5 66 LDA $66 |
COM FACSGN |
Vorzeichen |
get FAC1 sign (b7) |
NO, SO TOGGLE SIGN |
||
.,BFBA 49 FF EOR #$FF |
invertieren und |
complement it |
||||
.,BFBC 85 66 STA $66 |
speichern |
save FAC1 sign (b7) |
||||
.,BFBE 60 RTS |
NEGRTS: RTS PAGE EXPONENTIATION FUNCTION.;FIRST SAVE THE ORIGINAL ARGUMENT AND MULTIPLY THE FAC BY;LOG2(E). THE RESULT IS USED TO DETERMINE IF OVERFLOW ;WILL OCCUR SINCE EXP(X)=2^(X*LOG2(E)) WHERE ;LOG2(E)=LOG(E) BASE 2. THEN SAVE THE INTEGER PART OF ;THIS TO SCALE THE ANSWER AT THE END. SINCE ;2^Y=2^INT(Y)*2^(Y-INT(Y)) AND 2^INT(Y) IS EASY TO COMPUTE. ;NOW COMPUTE 2^(X*LOG2(E)-INT(X*LOG2(E)) BY ;P(LN(2)*(INT(X*LOG2(E))+1)-X) WHERE P IS AN APPROXIMATION ;POLYNOMIAL. THE RESULT IS THEN SCALED BY THE POWER OF 2 ;PREVIOUSLY SAVED. |
RücksprungKonstanten für EXP |
exp(n) constant and series |
floating point constands for EXP1/LOG(2) |
||
.:BFBF 81 38 AA 3B 29 |
LOGEB2: 201 ;LOG(E) BASE 2. 070 252 073 IFN ADDPRC,<051> ife addprc,< expcon: 6 ; degree -1. 164 ; .00021702255 143 220 214 167 ; .0012439688 043 014 253 172 ; .0096788410 036 224 000 174 ; .055483342 143 102 200 176 ; .24022984 165 376 320 200 ; .69314698 061 162 025 201 ; 1.0 000 000 000> IFN ADDPRC,< |
1.44269504 = 1/LOG(2) |
1.44269504 = 1/LOG(2) |
LOG(E) TO BASE 2 |
EXP polynomial table |
|
.:BFC4 07 |
EXPCON: 7 ;DEGREE-1 |
7 = Polynomgrad, 8 Koeffizienten |
series count |
( # OF TERMS IN POLYNOMIAL) - 1 |
degree 8 |
|
.:BFC5 71 34 58 3E 56 |
161 ; .000021498763697 064 130 076 126 |
2.14987637E-5 |
2.14987637E-5 |
(LOG(2)^7)/8! |
||
.:BFCA 74 16 7E B3 1B |
164 ; .00014352314036 026 176 263 033 |
1.4352314E-4 |
1.43523140E-4 |
(LOG(2)^6)/7! |
||
.:BFCF 77 2F EE E3 85 |
167 ; .0013422634824 057 356 343 205 |
1.34226348E-3 |
1.34226348E-3 |
(LOG(2)^5)/6! |
||
.:BFD4 7A 1D 84 1C 2A |
172 ; .0096140170119 035 204 034 052 |
9.614011701E-3 |
9.61401701E-3 |
(LOG(2)^4)/5! |
||
.:BFD9 7C 63 59 58 0A |
174 ; .055505126860 143 131 130 012 |
.0555051269 |
5.55051269E-2 |
(LOG(2)^3)/4! |
||
.:BFDE 7E 75 FD E7 C6 |
176 ; .24022638462 165 375 347 306 |
.240226385 |
2.40226385E-1 |
(LOG(2)^2)/3! |
||
.:BFE3 80 31 72 18 10 |
200 ; .69314718608 061 162 030 020 |
.693147186 |
6.93147186E-1 |
LOG(2)/2! |
||
.:BFE8 81 00 00 00 00 |
201 ; 1.0 000 000 000 000> EXP: |
1BASIC-Funktion EXP |
1.00000000perform EXP() |
1"EXP" FUNCTIONFAC = E ^ FAC |
EXP command |
|
.,BFED A9 BF LDA #$BF |
LDWDI LOGEB2 ;MULTIPLY BY LOG(E) BASE 2. |
Zeiger auf |
set 1.443 pointer low byte |
CONVERT TO POWER OF TWO PROBLEM |
||
.,BFEF A0 BF LDY #$BF |
Konstante 1/LOG(2) |
set 1.443 pointer high byte |
E^X = 2^(LOG2(E)*X) |
|||
.,BFF1 20 28 BA JSR $BA28 |
JSR FMULT |
mit FAC multiplizieren |
do convert AY, FCA1*(AY) |
|||
.,BFF4 A5 70 LDA $70 |
LDA FACOV |
80 zu Rundungsstelle |
get FAC1 rounding byte |
NON-STANDARD ROUNDING HERE |
||
.,BFF6 69 50 ADC #$50 |
ADCI 120 |
addieren |
+$50/$100 |
ROUND UP IF EXTENSION > $AF |
||
.,BFF8 90 03 BCC $BFFD |
BCC STOLD |
wenn kleiner als $FF, dann zu $BFFD |
skip rounding if no carry |
NO, DON'T ROUND UP |
||
.,BFFA 20 23 BC JSR $BC23 |
JSR INCRND |
Mantisse von FAC um eins erhöhen |
round FAC1 (no check) |
|||
.,BFFD 4C 00 E0 JMP $E000 |
weiter bei $E000 |
continue EXP()start of the kernal ROMEXP() continued |
continuation of EXP function |
|||
.,E000 85 56 STA $56 |
STOLD: STA OLDOV |
Rundungsstelle |
save FAC2 rounding byte |
STRANGE VALUE |
||
.,E002 20 0F BC JSR $BC0F |
JSR MOVEF ;TO SAVE IN ARG WITHOUT ROUND. |
FAC nach ARG bringen |
copy FAC1 to FAC2 |
COPY FAC INTO ARG |
||
.,E005 A5 61 LDA $61 |
LDA FACEXP |
Exponent |
get FAC1 exponent |
MAXIMUM EXPONENT IS < 128 |
||
.,E007 C9 88 CMP #$88 |
CMPI 210 ;IF ABS(FAC) .GE. 128, TOO BIG. |
Zahl größer 128 ?, |
compare with EXP limit (256d) |
WITHIN RANGE? |
||
.,E009 90 03 BCC $E00E |
BCC EXP1 |
dann zu $E00E |
branch if less |
YES |
||
.,E00B 20 D4 BA JSR $BAD4 |
GOMLDV: JSR MLDVEX ;OVERFLOW OR OVERFLOW. |
falls positiv 'OVERFLOW' |
handle overflow and underflow |
OVERFLOW IF +, RETURN 0.0 IF - |
||
.,E00E 20 CC BC JSR $BCCC |
EXP1: JSR INT |
INTEGER-Funktion |
perform INT() |
GET INT(FAC) |
||
.,E011 A5 07 LDA $07 |
LDA INTEGR ;GET LOW PART. |
ganze Zahl |
get mantissa 4 from INT() |
THIS IS THE INETGRAL PART OF THE POWER |
||
.,E013 18 CLC |
CLC |
Zahl |
clear carry for add |
ADD TO EXPONENT BIAS + 1 |
||
.,E014 69 81 ADC #$81 |
ADCI 201 |
gleich |
normalise +1 |
|||
.,E016 F0 F3 BEQ $E00B |
BEQ GOMLDV ;OVERFLOW OR OVERFLOW !! |
127 ?, dann zu $E00B |
if $00 result has overflowed so go handle it |
OVERFLOW |
||
.,E018 38 SEC |
SEC |
ansonsten |
set carry for subtract |
BACK OFF TO NORMAL BIAS |
||
.,E019 E9 01 SBC #$01 |
SBCI 1 ;SUBTRACT 1. |
subtrahieren |
exponent now correct |
|||
.,E01B 48 PHA |
PHA ;SAVE A WHILE. |
und in Stack |
save FAC2 exponent swap FAC1 and FAC2 |
SAVE EXPONENT |
||
.,E01C A2 05 LDX #$05 |
LDXI 4+ADDPRC ;PREP TO SWAP FAC AND ARG. |
FAC |
4 bytes to do |
SWAP ARG AND FAC |
||
.,E01E B5 69 LDA $69,X |
SWAPLP: LDA ARGEXP,X |
und |
get FAC2,X |
<<< WHY SWAP? IT IS DOING >>> |
||
.,E020 B4 61 LDY $61,X |
LDY FACEXP,X |
ARG |
get FAC1,X |
<<< -(A-B) WHEN (B-A) IS THE >>> |
||
.,E022 95 61 STA $61,X |
STA FACEXP,X |
ver- |
save FAC1,X |
<<< SAME THING! >>> |
||
.,E024 94 69 STY $69,X |
STY ARGEXP,X |
tauschen |
save FAC2,X |
|||
.,E026 CA DEX |
DEX |
Zähler erniedrigen |
decrement count/index |
|||
.,E027 10 F5 BPL $E01E |
BPL SWAPLP |
schon alle Zeichen? |
loop if not all done |
|||
.,E029 A5 56 LDA $56 |
LDA OLDOV |
Rundungs- |
get FAC2 rounding byte |
|||
.,E02B 85 70 STA $70 |
STA FACOV |
stelle |
save as FAC1 rounding byte |
|||
.,E02D 20 53 B8 JSR $B853 |
JSR FSUBT |
ARG - FAC |
perform subtraction, FAC2 from FAC1 |
POWER-INT(POWER) --> FRACTIONAL PART |
||
.,E030 20 B4 BF JSR $BFB4 |
JSR NEGOP ;NEGATE FAC. |
Vorzeichenwechsel |
do - FAC1 |
|||
.,E033 A9 C4 LDA #$C4 |
LDWDI EXPCON |
Zeiger auf |
set counter pointer low byte |
|||
.,E035 A0 BF LDY #$BF |
Polynomkoeffizienten |
set counter pointer high byte |
||||
.,E037 20 59 E0 JSR $E059 |
JSR POLY |
Polynom berechnen |
go do series evaluation |
COMPUTE F(X) ON FRACTIONAL PART |
||
.,E03A A9 00 LDA #$00 |
CLR ARISGN ;MULTIPLY BY POSITIVE 1.0. |
Vergleichsbyte |
clear A |
|||
.,E03C 85 6F STA $6F |
löschen |
clear sign compare (FAC1 EOR FAC2) |
||||
.,E03E 68 PLA |
PLA ;GET SCALE FACTOR. |
Zahl aus Stack |
get saved FAC2 exponent |
GET EXPONENT |
||
.,E03F 20 B9 BA JSR $BAB9 |
JSR MLDEXP ;MODIFY FACEXP AND CHECK FOR OVERFLOW. |
Exponenten von FAC und ARG addieren |
test and adjust accumulators |
|||
.,E042 60 RTS |
RTS ;HAS TO DO JSR DUE TO PULAS IN MULDIV. PAGE POLYNOMIAL EVALUATOR AND THE RANDOM NUMBER GENERATOR.;EVALUATE P(X^2)*X;POINTER TO DEGREE IS IN [Y,A]. ;THE CONSTANTS FOLLOW THE DEGREE. ;FOR X=FAC, COMPUTE: ; C0*X+C1*X^3+C2*X^5+C3*X^7+...+C(N)*X^(2*N+1) |
RücksprungPolynomberechnungy=a1*x+a2*x^3+a3*x^5+... |
^2 then series evaluation |
<<< WASTED BYTE HERE, COULD HAVE >>> <<< JUST USED "JMP ADD.EXPO..." >>> ODD POLYNOMIAL SUBROUTINEF(X) = X * P(X^2)WHERE: X IS VALUE IN FAC Y,A POINTS AT COEFFICIENT TABLE FIRST BYTE OF COEFF. TABLE IS N COEFFICIENTS FOLLOW, HIGHEST POWER FIRST P(X^2) COMPUTED USING NORMAL POLYNOMIAL SUBROUTINE |
compute odd degrees for SIN and ATN |
|
.,E043 85 71 STA $71 |
POLYX: STWD POLYPT ;RETAIN POLYNOMIAL POINTER FOR LATER. |
Zeiger auf |
save count pointer low byte |
SAVE ADDRESS OF COEFFICIENT TABLE |
||
.,E045 84 72 STY $72 |
Polynomkoeffizienten |
save count pointer high byte |
||||
.,E047 20 CA BB JSR $BBCA |
JSR MOV1F ;SAVE FAC IN FACTMP. |
FAC nach Akku #3 bringen |
pack FAC1 into $57 |
|||
.,E04A A9 57 LDA #$57 |
LDAI TEMPF1 |
Zeiger auf Akku #3 |
set pointer low byte (Y already $00) |
Y=0 ALREADY, SO Y,A POINTS AT TEMP1 |
||
.,E04C 20 28 BA JSR $BA28 |
JSR FMULT ;COMPUTE X^2. |
FAC * Akku #3 (quadrieren) |
do convert AY, FCA1*(AY) |
FORM X^2 |
||
.,E04F 20 5D E0 JSR $E05D |
JSR POLY1 ;COMPUTE P(X^2). |
Polynomberechnung |
go do series evaluation |
DO SERIES IN X^2 |
||
.,E052 A9 57 LDA #$57 |
LDWDI TEMPF1 |
Zeiger auf |
pointer to original # low byte |
GET X AGAIN |
||
.,E054 A0 00 LDY #$00 |
Akku #3 |
pointer to original # high byte |
||||
.,E056 4C 28 BA JMP $BA28 |
JMP FMULT ;MULTIPLY BY FAC AGAIN. ;POLYNOMIAL EVALUATOR. ;POINTER TO DEGREE IS IN [Y,A]. ;COMPUTE: ; C0+C1*X+C2*X^2+C3*X^3+C4*X^4+...+C(N-1)*X^(N-1)+C(N)*X^N. |
FAC = FAC * Akku #3Polynomberechnungy=a0+a1*x+a2*x^2+a3*x^3+... |
do convert AY, FCA1*(AY) do series evaluation |
MULTIPLY X BY P(X^2) AND EXITNORMAL POLYNOMIAL SUBROUTINEP(X) = C(0)*X^N + C(1)*X^(N-1) + ... + C(N)WHERE: X IS VALUE IN FAC Y,A POINTS AT COEFFICIENT TABLE FIRST BYTE OF COEFF. TABLE IS N COEFFICIENTS FOLLOW, HIGHEST POWER FIRST |
compute polynomials according to table indexed by AY |
|
.,E059 85 71 STA $71 |
POLY: STWD POLYPT |
Zeiger auf |
save count pointer low byte |
POINTER TO COEFFICIENT TABLE |
||
.,E05B 84 72 STY $72 |
Polynomgrad |
save count pointer high byte do series evaluation |
||||
.,E05D 20 C7 BB JSR $BBC7 |
POLY1: JSR MOV2F ;SAVE FAC. |
FAC nach Akku #4 bringen |
pack FAC1 into $5C |
|||
.,E060 B1 71 LDA ($71),Y |
LDADY POLYPT |
Polynomgrad |
get constants count |
GET N |
||
.,E062 85 67 STA $67 |
STA DEGREE |
als Zähler |
save constants count |
SAVE N |
||
.,E064 A4 71 LDY $71 |
LDY POLYPT |
Zeiger für Polynomauswertung |
get count pointer low byte |
BUMP PNTR TO HIGHEST COEFFICIENT |
||
.,E066 C8 INY |
INY |
Zeiger erhöhen, |
increment it (now constants pointer) |
AND GET PNTR INTO Y,A |
||
.,E067 98 TYA |
TYA |
zeigt dann |
copy it |
|||
.,E068 D0 02 BNE $E06C |
BNE POLY3 |
auf ersten Koeffizienten |
skip next if no overflow |
|||
.,E06A E6 72 INC $72 |
INC POLYPT+1 |
Zeiger |
else increment high byte |
|||
.,E06C 85 71 STA $71 |
POLY3: STA POLYPT |
für |
save low byte |
|||
.,E06E A4 72 LDY $72 |
LDY POLYPT+1 |
Polynomauswertung |
get high byte |
|||
.,E070 20 28 BA JSR $BA28 |
POLY2: JSR FMULT |
FAC = FAC * Konstante |
do convert AY, FCA1*(AY) |
ACCUMULATE SERIES TERMS |
||
.,E073 A5 71 LDA $71 |
LDWD POLYPT ;GET CURRENT POINTER. |
Zeiger in |
get constants pointer low byte |
BUMP PNTR TO NEXT COEFFICIENT |
||
.,E075 A4 72 LDY $72 |
(A/Y) |
get constants pointer high byte |
||||
.,E077 18 CLC |
CLC |
Zeiger |
clear carry for add |
|||
.,E078 69 05 ADC #$05 |
ADCI 4+ADDPRC |
um 5 erhöhen - nächste Zahl |
+5 to low pointer (5 bytes per constant) |
|||
.,E07A 90 01 BCC $E07D |
BCC POLY4 |
wenn kleiner, dann zu $E07D |
skip next if no overflow |
|||
.,E07C C8 INY |
INY |
ansonsten erhöhen |
increment high byte |
|||
.,E07D 85 71 STA $71 |
POLY4: STWD POLYPT |
Zeiger für |
save pointer low byte |
|||
.,E07F 84 72 STY $72 |
Polynomauswertung speichern |
save pointer high byte |
||||
.,E081 20 67 B8 JSR $B867 |
JSR FADD ;ADD IN CONSTANT. |
FAC = FAC + Konstante |
add (AY) to FAC1 |
ADD NEXT COEFFICIENT |
||
.,E084 A9 5C LDA #$5C |
LDWDI TEMPF2 ;MULTIPLY THE ORIGINAL FAC. |
Zeiger auf |
set pointer low byte to partial |
POINT AT X AGAIN |
||
.,E086 A0 00 LDY #$00 |
Akku #4 |
set pointer high byte to partial |
||||
.,E088 C6 67 DEC $67 |
DEC DEGREE ;DONE? |
Zähler erniedrigen |
decrement constants count |
IF SERIES NOT FINISHED, |
||
.,E08A D0 E4 BNE $E070 |
BNE POLY2 |
schon alle, nein, dann zu $E070 |
loop until all done |
THEN ADD ANOTHER TERM |
||
.,E08C 60 RTS |
RANDRT: RTS ;YES. ;PSUEDO-RANDOM NUMBER GENERATOR. ;IF ARG=0, THE LAST RANDOM NUMBER GENERATED IS RETURNED. ;IF ARG .LT. 0, A NEW SEQUENCE OF RANDOM NUMBERS IS ;STARTED USING THE ARGUMENT. ; TO FORM THE NEXT RANDOM NUMBER IN THE SEQUENCE, ;MULTIPLY THE PREVIOUS RANDOM NUMBER BY A RANDOM CONSTANT ;AND ADD IN ANOTHER RANDOM CONSTANT. THE THEN HO ;AND LO BYTES ARE SWITCHED, THE EXPONENT IS PUT WHERE ;IT WILL BE SHIFTED IN BY NORMAL, AND THE EXPONENT IN THE FAC ;IS SET TO 200 SO THE RESULT WILL BE LESS THAN 1. THIS ;IS THEN NORMALIZED AND SAVED FOR THE NEXT TIME. ;THE HO AND LOW BYTES WERE SWITCHED SO THERE WILL BE A ;RANDOM CHANCE OF GETTING A NUMBER LESS THAN OR GREATER ;THAN .5 . |
RücksprungKonstanten für RND |
RND values |
FINISHED |
float numbers for RND |
|
.:E08D 98 35 44 7A 00 |
RMULZC: 230 065 104 172 |
11879546 |
11879546 multiplier |
RND 1 |
||
.:E092 68 28 B1 46 00 |
RADDZC: 150 050 261 106 |
3.92767774E-4BASIC-Funktion RND |
3.927677739E-8 offsetperform RND() |
RND 2"RND" FUNCTION |
RND function |
|
.,E097 20 2B BC JSR $BC2B |
RND: JSR SIGN ;GET SIGN INTO ACCX. IFN REALIO-3,< TAX> ;GET INTO ACCX, SINCE "MOVFM" USES ACCX. |
Vorzeichen holen |
get FAC1 sign return A = $FF -ve, A = $01 +ve |
REDUCE ARGUMENT TO -1, 0, OR +1 |
||
.,E09A 30 37 BMI $E0D3 |
BMI RND1 ;START NEW SEQUENCE IF NEGATIVE. IFE REALIO-3,< |
negativ ?, dann zu $E0D3 |
if n<0 copy byte swapped FAC1 into RND() seed |
= -1, USE CURRENT ARGUMENT FOR SEED |
||
.,E09C D0 20 BNE $E0BE |
BNE QSETNR ;TIMERS ARE AT 9044(L0),45(HI),48(LO),49(HI) HEX. ;FIRST TWO ARE ALWAYS FREE RUNNING. ;SECOND PAIR IS NOT. LO IS FREER THAN HI THEN. ;SO ORDER IN FAC IS 44,48,45,49. |
nicht Null?, dann zu $E0BE |
if n>0 get next number in RND() sequence else n=0 so get the RND() number from VIA 1 timers |
|||
.,E09E 20 F3 FF JSR $FFF3 |
LDA CQHTIM |
Basis-Adresse CIA holen |
return base address of I/O devices |
|||
.,E0A1 86 22 STX $22 |
STA FACHO |
als Zeiger |
save pointer low byte |
|||
.,E0A3 84 23 STY $23 |
LDA CQHTIM+4 |
speichern |
save pointer high byte |
|||
.,E0A5 A0 04 LDY #$04 |
STA FACMOH |
Zähler setzen |
set index to T1 low byte |
|||
.,E0A7 B1 22 LDA ($22),Y |
LDA CQHTIM+1 |
LOW-Byte Timer A laden |
get T1 low byte |
|||
.,E0A9 85 62 STA $62 |
STA FACMO |
und speichern |
save FAC1 mantissa 1 |
|||
.,E0AB C8 INY |
LDA CQHTIM+5 |
Zähler erhöhen |
increment index |
|||
.,E0AC B1 22 LDA ($22),Y |
STA FACLO |
HIGH-Byte Timer A laden |
get T1 high byte |
|||
.,E0AE 85 64 STA $64 |
JMP STRNEX> |
und speichern |
save FAC1 mantissa 3 |
|||
.,E0B0 A0 08 LDY #$08 |
QSETNR: LDWDI RNDX ;GET LAST ONE INTO FAC. |
Zähler neu setzen |
set index to T2 low byte |
|||
.,E0B2 B1 22 LDA ($22),Y |
JSR MOVFM |
TOD 1/10 sec laden |
get T2 low byte |
|||
.,E0B4 85 63 STA $63 |
IFN REALIO-3,< |
und speichern |
save FAC1 mantissa 2 |
|||
.,E0B6 C8 INY |
TXA ;FAC WAS ZERO? |
Zähler erhöhen |
increment index |
|||
.,E0B7 B1 22 LDA ($22),Y |
BEQ RANDRT> ;RESTORE LAST ONE. |
TOD sec laden |
get T2 high byte |
|||
.,E0B9 85 65 STA $65 |
und speichern |
save FAC1 mantissa 4 |
||||
.,E0BB 4C E3 E0 JMP $E0E3 |
weiter bei $E0E3 |
set exponent and exit |
||||
.,E0BE A9 8B LDA #$8B |
Zeiger auf |
set seed pointer low address |
USE CURRENT SEED |
|||
.,E0C0 A0 00 LDY #$00 |
letzten RND-Wert |
set seed pointer high address |
||||
.,E0C2 20 A2 BB JSR $BBA2 |
nach FAC holen |
unpack memory (AY) into FAC1 |
||||
.,E0C5 A9 8D LDA #$8D |
LDWDI RMULZC ;MULTIPLY BY RANDOM CONSTANT. |
Zeiger auf |
set 11879546 pointer low byte |
VERY POOR RND ALGORITHM |
||
.,E0C7 A0 E0 LDY #$E0 |
Konstante |
set 11879546 pointer high byte |
||||
.,E0C9 20 28 BA JSR $BA28 |
JSR FMULT |
FAC = FAC * Konstante |
do convert AY, FCA1*(AY) |
|||
.,E0CC A9 92 LDA #$92 |
LDWDI RADDZC |
Zeiger auf |
set 3.927677739E-8 pointer low byte |
ALSO, CONSTANTS ARE TRUNCATED |
||
.,E0CE A0 E0 LDY #$E0 |
Konstante |
set 3.927677739E-8 pointer high byte |
<<<THIS DOES NOTHING, DUE TO >>> <<<SMALL EXPONENT >>> |
|||
.,E0D0 20 67 B8 JSR $B867 |
JSR FADD ;ADD RANDOM CONSTANT. |
FAC = FAC + Konstante |
add (AY) to FAC1 |
|||
.,E0D3 A6 65 LDX $65 |
RND1: LDX FACLO |
alle |
get FAC1 mantissa 4 |
SHUFFLE HI AND LO BYTES |
||
.,E0D5 A5 62 LDA $62 |
LDA FACHO |
Stel- |
get FAC1 mantissa 1 |
TO SUPPOSEDLY MAKE IT MORE RANDOM |
||
.,E0D7 85 65 STA $65 |
STA FACLO |
len |
save FAC1 mantissa 4 |
|||
.,E0D9 86 62 STX $62 |
STX FACHO ;REVERSE HO AND LO. IFE REALIO-3,< |
im |
save FAC1 mantissa 1 |
|||
.,E0DB A6 63 LDX $63 |
LDX FACMOH |
FAC |
get FAC1 mantissa 2 |
|||
.,E0DD A5 64 LDA $64 |
LDA FACMO |
ver- |
get FAC1 mantissa 3 |
MAKE IT POSITIVE |
||
.,E0DF 85 63 STA $63 |
STA FACMOH |
tau- |
save FAC1 mantissa 2 |
|||
.,E0E1 86 64 STX $64 |
STX FACMO> |
schen |
save FAC1 mantissa 3 |
|||
.,E0E3 A9 00 LDA #$00 |
STRNEX: CLR FACSGN ;MAKE NUMBER POSITIVE. |
Vorzeichen |
clear byte |
A SOMEWHAT RANDOM EXTENSION |
||
.,E0E5 85 66 STA $66 |
positiv |
clear FAC1 sign (always +ve) |
||||
.,E0E7 A5 61 LDA $61 |
LDA FACEXP ;PUT EXP WHERE IT WILL |
Exponent in |
get FAC1 exponent |
EXPONENT TO MAKE VALUE < 1.0 |
||
.,E0E9 85 70 STA $70 |
STA FACOV ;BE SHIFTED IN BY NORMAL. |
Rundungsstelle |
save FAC1 rounding byte |
|||
.,E0EB A9 80 LDA #$80 |
LDAI 200 |
Zufallszahl |
set exponent = $80 |
|||
.,E0ED 85 61 STA $61 |
STA FACEXP ;MAKE RESULT BETWEEN 0 AND 1. |
speichern |
save FAC1 exponent |
|||
.,E0EF 20 D7 B8 JSR $B8D7 |
JSR NORMAL ;NORMALIZE. |
FAC linksbündig machen |
normalise FAC1 |
|||
.,E0F2 A2 8B LDX #$8B |
LDXYI RNDX |
Zeiger auf |
set seed pointer low address |
MOVE FAC TO RND SEED |
||
.,E0F4 A0 00 LDY #$00 |
letzten RND-Wert |
set seed pointer high addresspack FAC1 into (XY) |
||||
.,E0F6 4C D4 BB JMP $BBD4 |
GMOVMF: JMP MOVMF ;PUT NEW ONE INTO MEMORY. |
FAC runden und speichernFehlerauswertung nachI/O-Routinen |
pack FAC1 into (XY)handle BASIC I/O error |
handle errors for direct I/Ocalls from basic |
||
.,E0F9 C9 F0 CMP #$F0 |
EREXIT CMP #$F0 ;CHECK FOR SPECIAL CASE |
RS 232 OPEN oder CLOSE ? |
compare error with $F0 |
test error |
||
.,E0FB D0 07 BNE $E104 |
BNE EREXIX ; TOP OF MEMORY HAS CHANGED |
nein |
branch if not $F0 |
|||
.,E0FD 84 38 STY $38 |
STY MEMSIZ+1 |
BASIC-RAM Ende |
set end of memory high byte |
MEMSIZ, highest address in BASIC |
||
.,E0FF 86 37 STX $37 |
STX MEMSIZ |
neu setzen |
set end of memory low byte |
|||
.,E101 4C 63 A6 JMP $A663 |
JMP CLEART ;ACT AS IF HE TYPED CLEAR |
und zum CLR-Befehl |
clear from start to end and return error was not $F0 |
do CLR without aborting I/O |
||
.,E104 AA TAX |
EREXIX TAX ;SET TERMINATION FLAGS |
Fehlernummer nach X |
copy error # |
put error flag i (X) |
||
.,E105 D0 02 BNE $E109 |
BNE EREXIY |
nicht Null ? |
branch if not $00 |
if error code $00, then set error code $1e |
||
.,E107 A2 1E LDX #$1E |
LDX #ERBRK ;BREAK ERROR |
sonst Nummer für 'BREAK' |
else error $1E, break error |
|||
.,E109 4C 37 A4 JMP $A437 |
EREXIY JMP ERROR ;NORMAL ERROR CLSCHN =$FFCC |
Fehlermeldung ausgebenBASIC BSOUT |
do error #X then warm startoutput character to channel with error check |
do errorBCHOUT: OUTPUT CHARACTERThis routine uses the KERNAL routine CHROUT to output thecharacter in (A) to an available output channel. A test is made for a possible I/O error. |
||
.,E10C 20 D2 FF JSR $FFD2 |
OUTCH JSR $FFD2 |
ein Zeichen ausgeben |
output character to channel |
output character in (A) |
||
.,E10F B0 E8 BCS $E0F9 |
BCS EREXIT |
Fehler ? |
if error go handle BASIC I/O error |
if carry set, handle I/O error |
||
.,E111 60 RTS |
RTS |
RücksprungBASIC BASIN |
input character from channel with error check |
else returnBCHIN: INPUT CHARACTERThis routine uses the KERNAL routine CHRIN to input acharacter to (A) from an available input channel. A test is made for a possible I/O error. |
||
.,E112 20 CF FF JSR $FFCF |
INCHR JSR $FFCF |
ein Zeichen holen |
input character from channel |
input character from CHRIN |
||
.,E115 B0 E2 BCS $E0F9 |
BCS EREXIT |
Fehler ? |
if error go handle BASIC I/O error |
if carry set, handle I/O error |
||
.,E117 60 RTS |
RTS CCALL =$FFE7 SETTIM =$FFDB RDTIM =$FFDE |
RücksprungBASIC CKOUT |
open channel for output with error check |
else returnBCKOUT:SET UP FOR OUTPUTThis routine uses the KERNAL routine CHKOUT to open anoutput channel, and tests for possible I/O error. On entry (X) must hold the the logical file number as used in OPEN. |
||
.,E118 20 AD E4 JSR $E4AD |
COOUT JSR PPACH ; GO OUT TO SAVE .A FOR PRINT# PATCH |
Ausgabegerät setzen |
open channel for output |
open output channel via CHKOUT |
||
.,E11B B0 DC BCS $E0F9 |
BCS EREXIT |
Fehler ? |
if error go handle BASIC I/O error |
if carry set, handle I/O error |
||
.,E11D 60 RTS |
RTS |
RücksprungBASIC CHKIN |
open channel for input with error check |
else returnBCKIN: SET UP FOR INPUTThis routine uses the KERNAL routine CHKIN to open aninput channel. A test as made for possible I/O error. |
||
.,E11E 20 C6 FF JSR $FFC6 |
COIN JSR $FFC6 |
Eingabegerät setzen |
open channel for input |
open input channel via CHKIN |
||
.,E121 B0 D6 BCS $E0F9 |
BCS EREXIT |
Fehler ? |
if error go handle BASIC I/O error |
if carry set, handle I/O error |
||
.,E123 60 RTS |
RTS READST =$FFB7 |
RücksprungBASIC GETIN |
get character from input device with error check |
else returnBGETIN: GET ONT CHARACTERThis routine uses the KERNAL routine GETIN to get acharacter from the keyboard buffer into (A). A test is made for possible I/O error. |
||
.,E124 20 E4 FF JSR $FFE4 |
CGETL JSR $FFE4 |
ein Zeichen holen |
get character from input device |
GETIN, get character from keyboard buffer |
||
.,E127 B0 D0 BCS $E0F9 |
BCS EREXIT |
Fehler ? |
if error go handle BASIC I/O error |
if carry set, handle I/O error |
||
.,E129 60 RTS |
RTS RDBAS =$FFF3 SETMSG =$FF90 PLOT =$FFF0 |
RücksprungSYS-Befehl |
perform SYS |
else returnSYS: PERFORM SYSThis routine enables machine language routines to beexecuted from BASIC. The routine evaluates the address and confirms that it is a numeric number. The return address is set up, and the user routine is executed. |
SYS command |
|
.,E12A 20 8A AD JSR $AD8A |
CSYS JSR FRMNUM ;EVAL FORMULA |
FRMNUM, numerischen Ausdruck holen |
evaluate expression and check is numeric, else do type mismatch |
evaluate text & confirm numeric |
||
.,E12D 20 F7 B7 JSR $B7F7 |
JSR GETADR ;CONVERT TO INT. ADDR |
in Adressformat wandeln, nach $14/$15 |
convert FAC_1 to integer in temporary integer |
convert fac#1 to integer in LINNUM |
||
.,E130 A9 E1 LDA #$E1 |
LDA #>CSYSRZ ;PUSH RETURN ADDRESS |
Rück- |
get return address high byte |
set return address on stack to $ea46 |
low E146 |
|
.,E132 48 PHA |
PHA |
sprungadresse |
push as return address |
|||
.,E133 A9 46 LDA #$46 |
LDA #<CSYSRZ |
auf |
get return address low byte |
high E146 |
||
.,E135 48 PHA |
PHA |
Stack |
push as return address |
|||
.,E136 AD 0F 03 LDA $030F |
LDA SPREG ;STATUS REG |
Status, |
get saved status register |
SPREG, user flag register |
||
.,E139 48 PHA |
PHA |
in Stack |
put on stack |
|||
.,E13A AD 0C 03 LDA $030C |
LDA SAREG ;LOAD 6502 REGS |
Akku, |
get saved A |
SAREG, user (A) register |
||
.,E13D AE 0D 03 LDX $030D |
LDX SXREG |
X-Register und |
get saved X |
SXREG, user (X) register |
||
.,E140 AC 0E 03 LDY $030E |
LDY SYREG |
Y-Register übergeben |
get saved Y |
SYREG, user (Y) register |
||
.,E143 28 PLP |
PLP ;LOAD 6502 STATUS REG |
Status setzen |
pull processor status |
|||
.,E144 6C 14 00 JMP ($0014) |
JMP (LINNUM) ;GO DO IT CSYSRZ =*-1 ;RETURN TO HERE |
Routine aufrufen |
call SYS address tail end of SYS code |
execute user routine, exit with rts |
||
.,E147 08 PHP |
PHP ;SAVE STATUS REG |
Status speichern |
save status |
|||
.,E148 8D 0C 03 STA $030C |
STA SAREG ;SAVE 6502 REGS |
Akku, |
save returned A |
store in SAREG, user (A) register |
||
.,E14B 8E 0D 03 STX $030D |
STX SXREG |
X-Register, |
save returned X |
store in SXREG, user (X) register |
||
.,E14E 8C 0E 03 STY $030E |
STY SYREG |
Y-Register und |
save returned Y |
store in SYREG, user (Y) register |
||
.,E151 68 PLA |
PLA ;GET STATUS REG |
Status |
restore saved status |
|||
.,E152 8D 0F 03 STA $030F |
STA SPREG |
wieder speichern |
save status |
store in SPREG, user flag register |
||
.,E155 60 RTS |
RTS ;RETURN TO SYSTEM |
RücksprungSAVE-Befehl |
perform SAVE |
backSAVET: PERFORM SAVEThis routine is sets parameters for save, and calls thesave routine. The start and end addresses are obtained from TXTTAB and VARTAB. Finally, a test is made if any errors ocured. |
SAVE command |
|
.,E156 20 D4 E1 JSR $E1D4 |
CSAVE JSR PLSV ;PARSE PARMS |
Parameter (Filenamen, Prim, und Sek. Adresse) |
get parameters for LOAD/SAVE |
get SAVE paramerters from text |
||
.,E159 A6 2D LDX $2D |
LDX VARTAB ;END SAVE ADDR |
Endadresse gleich |
get start of variables low byte |
VARTAB, start of variables |
||
.,E15B A4 2E LDY $2E |
LDY VARTAB+1 |
BASIC-Rücksprung |
get start of variables high byte |
|||
.,E15D A9 2B LDA #$2B |
LDA #<TXTTAB ;INDIRECT WITH START ADDRESS |
Startadresse gleich Zeiger auf BASIC Anfang |
index to start of program memory |
<TXTTAB, start of BASIC text |
||
.,E15F 20 D8 FF JSR $FFD8 |
JSR $FFD8 ;SAVE IT |
Save-Routine |
save RAM to device, A = index to start address, XY = end address low/high |
execute SAVE |
||
.,E162 B0 95 BCS $E0F9 |
BCS EREXIT |
Fehler ? |
if error go handle BASIC I/O error |
if carry is set, handle I/O errors |
||
.,E164 60 RTS |
RTS |
RücksprungVERIFY-Befehl |
perform VERIFY |
VERFYT: PERFORM LOAD/SAVEThis routine is essentially the same for both LOAD andVERIFY. The entry point determins which is performed, by setting VERCK accordingly. The LOAD/VERIFY parameters, filename, device etc. are obtained from text before the KERNAL routine LOAD is called. A test is made for I/O errors. At this point, the two functios are distiguished. VERIFY reads the the status word and prints the message OK or ?VERIFY error depending on the result of the test. LOAD reads the I/O status word for a possible ?LOAD error, then updates the pointers to text and variables, exiting via CLR. |
VERIFY command |
|
.,E165 A9 01 LDA #$01 |
CVERF LDA #1 ;VERIFY FLAG |
Verify- |
flag verify |
flag verify |
||
.:E167 2C .BYTE $2C |
.BYT $2C ;SKIP TWO BYTES |
FlagLOAD-Befehl |
makes next line BIT $00A9perform LOAD |
mask |
LOAD command |
|
.,E168 A9 00 LDA #$00 |
CLOAD LDA #0 ;LOAD FLAG |
Load-Flag |
flag load |
|||
.,E16A 85 0A STA $0A |
STA VERCK |
speichern |
set load/verify flag |
store in VRECK, LOAD/VERIFY flag |
||
.,E16C 20 D4 E1 JSR $E1D4 |
JSR PLSV ;PARSE PARAMETERS ; CLD10 ; JSR $FFE1 ;CHECK RUN/STOP ; CMP #$FF ;DONE YET? ; BNE CLD10 ;STILL BOUNCING |
Parameter holen |
get parameters for LOAD/SAVE |
get LOAD/VERIFY parameters from text |
||
.,E16F A5 0A LDA $0A |
LDA VERCK |
Flag |
get load/verify flag |
get VRECK |
||
.,E171 A6 2B LDX $2B |
LDX TXTTAB ;.X AND .Y HAVE ALT... |
Startadresse gleich |
get start of memory low byte |
TXTTAB, start of BASIC |
||
.,E173 A4 2C LDY $2C |
LDY TXTTAB+1 ;...LOAD ADDRESS |
BASIC-Start |
get start of memory high byte |
|||
.,E175 20 D5 FF JSR $FFD5 |
JSR $FFD5 ;LOAD IT |
Load-Routine |
load RAM from a device |
execute LOAD, KERNAL routine |
||
.,E178 B0 57 BCS $E1D1 |
BCS JERXIT ;PROBLEMS ; |
Fehler ? |
if error go handle BASIC I/O error |
if carry set, handle error |
||
.,E17A A5 0A LDA $0A |
LDA VERCK |
Load/Verify - Flag |
get load/verify flag |
test VRECK for LOAD or VERIFY |
||
.,E17C F0 17 BEQ $E195 |
BEQ CLD50 ;WAS LOAD ; ;FINISH VERIFY ; |
Load ? |
branch if load |
do LOAD |
||
.,E17E A2 1C LDX #$1C |
LDX #ERVFY ;ASSUME ERROR |
Offset für 'VERIFY ERROR' |
error $1C, verify error |
set error $1c, VERIFY error |
||
.,E180 20 B7 FF JSR $FFB7 |
JSR $FFB7 ;READ STATUS |
Status holen |
read I/O status word |
do READST, get status I/O word |
||
.,E183 29 10 AND #$10 |
AND #$10 ;CHECK ERROR |
Fehler-Bit isolieren |
mask for tape read error |
%00010000, test for mismatch |
||
.,E185 D0 17 BNE $E19E |
BNE CLD55 ;REPLACES BEQ *+5/JMP ERROR ; ;PRINT VERIFY 'OK' IF DIRECT ; |
Statusbit gesetzt, dann Fehler |
branch if no read error |
data mismatch, do error |
||
.,E187 A5 7A LDA $7A |
LDA TXTPTR |
muß HIGH-Byte $7B sein |
get the BASIC execute pointer low byte is this correct ?? won't this mean the "OK" prompt when doing a load from within a program ? |
<TXTPTR |
||
.,E189 C9 02 CMP #$02 |
CMP #BUFPAG |
Test auf Direkt-Modus |
||||
.,E18B F0 07 BEQ $E194 |
BEQ CLD20 |
ja, dann fertig |
if ?? skip "OK" prompt |
|||
.,E18D A9 64 LDA #$64 |
LDA #<OKMSG |
Zeiger auf |
set "OK" pointer low byte |
set address to text OK |
||
.,E18F A0 A3 LDY #$A3 |
LDY #>OKMSG |
'OK' |
set "OK" pointer high byte |
at $a364 |
||
.,E191 4C 1E AB JMP $AB1E |
JMP STROUT ; |
ausgeben |
print null terminated string |
output string in (A/Y) |
||
.,E194 60 RTS |
CLD20 RTS ; ;FINISH LOAD ; |
Rücksprung |
do READY return to BASIC |
|||
.,E195 20 B7 FF JSR $FFB7 |
CLD50 JSR $FFB7 ;READ STATUS |
Status holen |
read I/O status word |
do READST, get status I/O for LOAD |
||
.,E198 29 BF AND #$BF |
AND #$FF-$40 ;CLEAR E.O.I. |
EOF-Bit löschen |
mask x0xx xxxx, clear read error |
%10111111, test all but EOI |
||
.,E19A F0 05 BEQ $E1A1 |
BEQ CLD60 ;WAS O.K. |
kein Fehler |
branch if no errors |
nope, no errors |
||
.,E19C A2 1D LDX #$1D |
LDX #ERLOAD |
Offset für 'LOAD ERROR' |
error $1D, load error |
set error $1d, LOAD error |
||
.,E19E 4C 37 A4 JMP $A437 |
CLD55 JMP ERROR ; |
Fehlermeldung ausgeben |
do error #X then warm start |
do error |
||
.,E1A1 A5 7B LDA $7B |
CLD60 LDA TXTPTR+1 |
Direkt- |
get BASIC execute pointer high byte |
>TXTPTR |
||
.,E1A3 C9 02 CMP #$02 |
CMP #BUFPAG ;DIRECT? |
modus testen |
compare with $02xx |
|||
.,E1A5 D0 0E BNE $E1B5 |
BNE CLD70 ;NO... ; |
nein, dann weiter |
branch if not immediate mode |
|||
.,E1A7 86 2D STX $2D |
STX VARTAB |
Endadresse gleich |
set start of variables low byte |
set VARTAB, start of variables |
||
.,E1A9 84 2E STY $2E |
STY VARTAB+1 ;END LOAD ADDRESS |
Rücksprung |
set start of variables high byte |
|||
.,E1AB A9 76 LDA #$76 |
LDA #<REDDY |
Zeiger auf |
set "READY." pointer low byte |
set address to text READY |
||
.,E1AD A0 A3 LDY #$A3 |
LDY #>REDDY |
'READY' |
set "READY." pointer high byte |
at $a376 |
||
.,E1AF 20 1E AB JSR $AB1E |
JSR STROUT |
String ausgeben |
print null terminated string |
output string in (A/Y) |
||
.,E1B2 4C 2A A5 JMP $A52A |
JMP FINI ; ;PROGRAM LOAD ; |
Programmzeilen neu binden, CLR |
reset execution, clear variables, flush stack, rebuild BASIC chain and do warm start |
do CLR and restart BASIC |
||
.,E1B5 20 8E A6 JSR $A68E |
CLD70 JSR STXTPT |
CHRGET-Zeiger auf Programmstart |
set BASIC execute pointer to start of memory - 1 |
reset TXTPTR |
||
.,E1B8 20 33 A5 JSR $A533 |
JSR LNKPRG |
Programmzeilen neu binden |
rebuild BASIC line chaining |
rechain BASIC lines |
||
.,E1BB 4C 77 A6 JMP $A677 |
JMP FLOAD |
RESTORE, BASIC initialisierenBASIC-Befehl OPEN |
rebuild BASIC line chaining, do RESTORE and returnperform OPEN |
do RESTORE and reset OLDTXTOPENT: PERFORM OPENThis routine extracts paramerters from text and performsthe OPEN routine in KERNAL. A test is made for I/O errors. |
OPEN command |
|
.,E1BE 20 19 E2 JSR $E219 |
COPEN JSR PAOC ;PARSE STATEMENT |
Parameter holen |
get parameters for OPEN/CLOSE |
get parameters from text |
||
.,E1C1 20 C0 FF JSR $FFC0 |
JSR $FFC0 ;OPEN IT |
OPEN-Routine |
open a logical file |
execute OPEN |
||
.,E1C4 B0 0B BCS $E1D1 |
BCS JERXIT ;BAD STUFF OR MEMSIZ CHANGE |
Fehler ? |
branch if error |
if carry set, handle error |
||
.,E1C6 60 RTS |
RTS ;A.O.K. |
RücksprungBASIC-Befehl CLOSE |
perform CLOSE |
CLOSET: PERFORM CLOSEThe parameters for CLOSE are obtained from text, and thelogical filenumber placed in (A), The KERNAL routine CLOSE is performed, and a test is made for I/O errors. |
CLOSE command |
|
.,E1C7 20 19 E2 JSR $E219 |
CCLOS JSR PAOC ;PARSE STATEMENT |
Parameter holen |
get parameters for OPEN/CLOSE |
get parameters from text |
||
.,E1CA A5 49 LDA $49 |
LDA ANDMSK ;GET LA |
Filenummer |
get logical file number |
logical file number |
||
.,E1CC 20 C3 FF JSR $FFC3 |
JSR $FFC3 ;CLOSE IT |
CLOSE-Routine |
close a specified logical file |
perform CLOSE |
||
.,E1CF 90 C3 BCC $E194 |
BCC CLD20 ;IT'S OKAY...NO MEMSIZE CHANGE ; |
kein Fehler, RTS |
exit if no error |
if carry set, handle error, else return |
||
.,E1D1 4C F9 E0 JMP $E0F9 |
JERXIT JMP EREXIT ; ;PARSE LOAD AND SAVE COMMANDS ; PLSV ;DEFAULT FILE NAME ; |
zur FehlerauswertungParameter für LOAD und SAVEholen |
go handle BASIC I/O errorget parameters for LOAD/SAVE |
jump to error routineSLPARA: GET PARAMETERS FOR LOAD/SAVEThis routine gets the filename, devicenumber and secondaryaddress for LOAD/VERIFY and SAVE operations. The KERNAL routines SETNAM and SETLFS are used to do this. Default parameters are set up, then tests are made if any of the parameters were given. If so, these are set up as wanted. |
set parameters for load/verify/save |
|
.,E1D4 A9 00 LDA #$00 |
LDA #0 ;LENGTH=0 |
Default für Länge des Filenamen |
clear file name length |
clear length of filename |
||
.,E1D6 20 BD FF JSR $FFBD |
JSR $FFBD ; ;DEFAULT DEVICE # ; |
Filenamenparameter setzen |
clear the filename |
SETNAM |
||
.,E1D9 A2 01 LDX #$01 |
LDX #1 ;DEVICE #1 |
Default für Gerätenummer |
set default device number, cassette |
default FA, device number is #01 |
||
.,E1DB A0 00 LDY #$00 |
LDY #0 ;COMMAND 0 |
Sekundäradresse |
set default command |
default SA, secondary address is #00 |
||
.,E1DD 20 BA FF JSR $FFBA |
JSR $FFBA ; |
Fileparameter setzen |
set logical, first and second addresses |
SETLFS, and device number |
||
.,E1E0 20 06 E2 JSR $E206 |
JSR PAOC20 ;BY-PASS JUNK |
weitere Zeichen ? |
exit function if [EOT] or ":" |
test if "end of line", if so end here |
||
.,E1E3 20 57 E2 JSR $E257 |
JSR PAOC15 ;GET/SET FILE NAME |
Filenamen holen |
set filename |
set up given filename and perform SETNAM |
||
.,E1E6 20 06 E2 JSR $E206 |
JSR PAOC20 ;BY-PASS JUNK |
weitere Zeichen ? |
exit function if [EOT] or ":" |
test if "end of line", if so end here |
||
.,E1E9 20 00 E2 JSR $E200 |
JSR PLSV7 ;GET ',FA' |
Geräteadresse holen |
scan and get byte, else do syntax error then warm start |
check for comma, and input one byte, FA, to (X) |
||
.,E1EC A0 00 LDY #$00 |
LDY #0 ;COMMAND 0 |
Sekundäradresse |
clear command |
|||
.,E1EE 86 49 STX $49 |
STX ANDMSK |
Geräteadresse |
save device number |
|||
.,E1F0 20 BA FF JSR $FFBA |
JSR $FFBA |
Fileparameter setzen |
set logical, first and second addresses |
perform new SETLFS with device number |
||
.,E1F3 20 06 E2 JSR $E206 |
JSR PAOC20 ;BY-PASS JUNK |
weitere Zeichen ? |
exit function if [EOT] or ":" |
test if "end of line", if so end here |
||
.,E1F6 20 00 E2 JSR $E200 |
JSR PLSV7 ;GET ',SA' |
Sekundäradresse holen |
scan and get byte, else do syntax error then warm start |
check for comma, and input one byte, SA, to (X) |
||
.,E1F9 8A TXA |
TXA ;NEW COMMAND |
in Akku schieben |
copy command to A |
transfer (X) to (Y) |
||
.,E1FA A8 TAY |
TAY |
Sekundäradresse |
copy command to Y |
|||
.,E1FB A6 49 LDX $49 |
LDX ANDMSK ;DEVICE # |
Gerätenummer |
get device number back |
get FA |
||
.,E1FD 4C BA FF JMP $FFBA |
JMP $FFBA ;LOOK FOR COMMA FOLLOWED BY BYTE |
Fileparameter setzen |
set logical, first and second addresses and returnscan and get byte, else do syntax error then warm start |
perform SETLFS with both device number and secondary address. Then exit COMBYT: GET NEXT ONE-BYTE PARAMETERThis routine checks if the next character of text is acomma, and then inputs the parameter following into (X). |
skip comma and get integer in X |
|
.,E200 20 0E E2 JSR $E20E |
PLSV7 JSR PAOC30 |
prüft auf Komma und weitere Zeichen |
scan for ",byte", else do syntax error then warm start |
check for comma |
||
.,E203 4C 9E B7 JMP $B79E |
JMP GETBYT ;SKIP RETURN IF NEXT CHAR IS END ; |
holt Byte-Wert nach Xprüft auf weitere Zeichen |
get byte parameter and return exit function if [EOT] or ":" |
input one byte parameter to (X)DEFLT: CHECK DEFAULT PARAMETERSThis routine tests CHRGOT to see if a optional parameterwas included in the text. If it was, a normal exit is performed via RTS. If not, the return address on the stack is discarded, and the routine exits both this and the calling routine. |
get character and check for end of line |
|
.,E206 20 79 00 JSR $0079 |
PAOC20 JSR CHRGOT |
CHRGOT letztes Zeichen |
scan memory |
get CHRGOT |
||
.,E209 D0 02 BNE $E20D |
BNE PAOCX |
weiteres Zeichen, dann Rückkehr |
branch if not [EOL] or ":" |
if last character is a character, do normal exit |
||
.,E20B 68 PLA |
PLA |
sonst Rückkehr zur |
dump return address low byte |
else, remove return address |
||
.,E20C 68 PLA |
PLA |
übergeordneten Routine |
dump return address high byte |
to exit this AND the calling routine. |
||
.,E20D 60 RTS |
PAOCX RTS ;CHECK FOR COMMA AND GOOD STUFF ; |
Rücksprung |
scan for ",valid byte", else do syntax error then warm start |
exitCMMERR: CHECK FOR COMMAThis routine confirms that the next character in the textis a comma. It also test that the comma is not immediately ollowed by a terminator. If so, exit and do SYNTAX error. |
check for comma and skip it |
|
.,E20E 20 FD AE JSR $AEFD |
PAOC30 JSR CHKCOM ;CHECK COMMA |
prüft auf Komma |
scan for ",", else do syntax error then warm startscan for valid byte, not [EOL] or ":", else do syntax error then warm start |
confirm comma |
||
.,E211 20 79 00 JSR $0079 |
PAOC32 JSR CHRGOT ;GET CURRENT |
CHRGOT letztes Zeichen holen |
scan memory |
get CHRGOT |
||
.,E214 D0 F7 BNE $E20D |
BNE PAOCX ;IS O.K. |
weitere Zeichen, dann Rückkehr |
exit if following byte |
else than null |
||
.,E216 4C 08 AF JMP $AF08 |
PAOC40 JMP SNERR ;BAD...END OF LINE ;PARSE OPEN/CLOSE ; |
'SYNTAX ERROR'Parameter für OPEN holen |
else do syntax error then warm startget parameters for OPEN/CLOSE |
execute SYNTAX errorOCPARA: GET PARAMETERS FOR OPEN/CLOSEThis routine gets the logical file number, device number,secondary address and filename for OPEN/CLOSE. Initially the default filename is set to null, and the device number to #1. The logical filenumber is compulsory, and is obtained from text and placed in <FORPNT. The other parameters are optinal and are obtained if present. The device number is stored in >FORPNT. The parameters are set via the KERNAL routines SETNAM and SETLFS. |
get open/close parameters |
|
.,E219 A9 00 LDA #$00 |
PAOC LDA #0 |
Default für Länge des Filenamens |
clear the filename length |
default filename is null |
||
.,E21B 20 BD FF JSR $FFBD |
JSR $FFBD ;DEFAULT FILE NAME ; |
Filenamenparameter setzen |
clear the filename |
SETNAM |
||
.,E21E 20 11 E2 JSR $E211 |
JSR PAOC32 ;MUST GOT SOMETHING |
weitere Zeichen ? |
scan for valid byte, else do syntax error then warm start |
confirm TXTPNT is no terminator, if so - error |
||
.,E221 20 9E B7 JSR $B79E |
JSR GETBYT ;GET LA |
holt logische Filenummer nach X-Reg |
get byte parameter, logical file number |
input one byte character to (X) |
||
.,E224 86 49 STX $49 |
STX ANDMSK |
und speichern |
save logical file number |
store logical filenumber in <FORPNT |
||
.,E226 8A TXA |
TXA |
logische Filenummer |
copy logical file number to A |
set default parameters to |
||
.,E227 A2 01 LDX #$01 |
LDX #1 ;DEFAULT DEVICE |
Default für Geräteadresse |
set default device number, cassette |
device = #1 |
||
.,E229 A0 00 LDY #$00 |
LDY #0 ;DEFAULT COMMAND |
Sekundäradresse |
set default command |
secondary address = #0 |
||
.,E22B 20 BA FF JSR $FFBA |
JSR $FFBA ;STORE IT |
Fileparameter setzen |
set logical, first and second addresses |
SETLFS |
||
.,E22E 20 06 E2 JSR $E206 |
JSR PAOC20 ;SKIP JUNK |
weitere Zeichen ? |
exit function if [EOT] or ":" |
test if "end of line", if so end here |
||
.,E231 20 00 E2 JSR $E200 |
JSR PLSV7 |
holt Geräteadresse |
scan and get byte, else do syntax error then warm start |
check for comma, and input FA, device number |
||
.,E234 86 4A STX $4A |
STX EORMSK |
und speichern |
save device number |
store in >FORPNT |
||
.,E236 A0 00 LDY #$00 |
LDY #0 ;DEFAULT COMMAND |
Sekundäradresse |
clear command |
secondary address = #0 |
||
.,E238 A5 49 LDA $49 |
LDA ANDMSK ;GET LA |
logische Filenummer |
get logical file number |
logical file number from temp store |
||
.,E23A E0 03 CPX #$03 |
CPX #3 |
Gerätenummer kleiner 3 ? |
compare device number with screen |
test if serial devce |
||
.,E23C 90 01 BCC $E23F |
BCC PAOC5 |
ja |
branch if less than screen |
nope |
||
.,E23E 88 DEY |
DEY ;DEFAULT IEEE TO $FF |
sonst Sekundäradresse auf 255 (keine Sek-Adr) |
else decrement command |
if serial, set secondary address to $ff |
||
.,E23F 20 BA FF JSR $FFBA |
PAOC5 JSR $FFBA ;STORE THEM |
Fileparameter setzen |
set logical, first and second addresses |
SETLFS |
||
.,E242 20 06 E2 JSR $E206 |
JSR PAOC20 ;SKIP JUNK |
weitere Zeichen ? |
exit function if [EOT] or ":" |
test if "end of line", if so end here |
||
.,E245 20 00 E2 JSR $E200 |
JSR PLSV7 ;GET SA |
holt Sekundäradresse |
scan and get byte, else do syntax error then warm start |
check for comma, and input SA, secondary address |
||
.,E248 8A TXA |
TXA |
in Akku schieben |
copy command to A |
|||
.,E249 A8 TAY |
TAY |
Sekundäradresse |
copy command to Y |
SA to (Y) |
||
.,E24A A6 4A LDX $4A |
LDX EORMSK |
Gerätenummer |
get device number |
FA |
||
.,E24C A5 49 LDA $49 |
LDA ANDMSK |
logische Filenummer |
get logical file number |
LA |
||
.,E24E 20 BA FF JSR $FFBA |
JSR $FFBA ;SET UP REAL EVEYTHING |
Fileparameter setzen |
set logical, first and second addresses |
SETLFS |
||
.,E251 20 06 E2 JSR $E206 |
PAOC7 JSR PAOC20 |
weitere Zeichen ? |
exit function if [EOT] or ":" |
test if "end of line", if so end here |
||
.,E254 20 0E E2 JSR $E20E |
JSR PAOC30 |
prüft auf Komma |
scan for ",byte", else do syntax error then warm startset filename |
check for comma only |
||
.,E257 20 9E AD JSR $AD9E |
PAOC15 JSR FRMEVL |
FRMEVL Ausdruck holen |
evaluate expression |
evaluate expression in text |
||
.,E25A 20 A3 B6 JSR $B6A3 |
JSR FRESTR ;LENGTH IN .A |
holt Stringparameter, FRESTR |
evaluate string |
do string housekeeping |
||
.,E25D A6 22 LDX $22 |
LDX INDEX1 |
Adresse des |
get string pointer low byte |
pointers to given filename |
||
.,E25F A4 23 LDY $23 |
LDY INDEX1+1 |
Filenamens |
get string pointer high byte |
|||
.,E261 4C BD FF JMP $FFBD |
JMP $FFBD PAGE SINE, COSINE AND TANGENT FUNCTIONS.IFE KIMROM,<;COSINE FUNCTION. ;USE COS(X)=SIN(X+PI/2) |
Filenamenparameter setzenBASIC-Funktion COS |
set the filename and returnperform COS() |
"COS" FUNCTION |
SETNAM and exitCOS: PERFORM COSThis routine manipulates the input COS to be calcuatedwith SIN. COS(X) = SIN(X+pi/2), where X is in radians. We use it as Fac#1=SIN(fac#1+pi/2), ie pi/2 is added to fac#1 and the following SIN is performed. |
COS function |
.,E264 A9 E0 LDA #$E0 |
COS: LDWDI PI2 ;PNTR TO PI/2. |
Zeiger auf |
set pi/2 pointer low byte |
COS(X)=SIN(X + PI/2) |
set address to pi/2 |
low E2E0 |
.,E266 A0 E2 LDY #$E2 |
Konstante Pi/2 |
set pi/2 pointer high byte |
at $e2e0 |
high E2E0 |
||
.,E268 20 67 B8 JSR $B867 |
JSR FADD ;ADD IT IN. ;FALL INTO SIN. ;SINE FUNCTION. ;USE IDENTITIES TO GET FAC IN QUADRANTS I OR IV. ;THE FAC IS DIVIDED BY 2*PI AND THE INTEGER PART IS IGNORED ;BECAUSE SIN(X+2*PI)=SIN(X). THEN THE ARGUMENT CAN BE COMPARED ;WITH PI/2 BY COMPARING THE RESULT OF THE DIVISION ;WITH PI/2/(2*PI)=1/4. ;IDENTITIES ARE THEN USED TO GET THE RESULT IN QUADRANTS ;I OR IV. AN APPROXIMATION POLYNOMIAL IS THEN USED TO ;COMPUTE SIN(X). |
zu FAC addierenBASIC-Funktion SIN |
add (AY) to FAC1perform SIN() |
"SIN" FUNCTION |
add fltp at (A/Y) to fac#1SIN: PERFORM SIN |
SIN function |
.,E26B 20 0C BC JSR $BC0C |
SIN: JSR MOVAF |
FAC runden und nach ARG |
round and copy FAC1 to FAC2 |
|||
.,E26E A9 E5 LDA #$E5 |
LDWDI TWOPI ;GET PNTR TO DIVISOR. |
Zeiger auf |
set 2*pi pointer low byte |
REMOVE MULTIPLES OF 2*PI |
low E2E5 |
|
.,E270 A0 E2 LDY #$E2 |
Konstante Pi*2 |
set 2*pi pointer high byte |
BY DIVIDING AND SAVING |
high E2E5 |
||
.,E272 A6 6E LDX $6E |
LDX ARGSGN ;GET SIGN OF RESULT. |
Vorzeichen von ARG |
get FAC2 sign (b7) |
THE FRACTIONAL PART |
||
.,E274 20 07 BB JSR $BB07 |
JSR FDIVF |
FAC durch 2*Pi dividieren |
divide by (AY) (X=sign) |
USE SIGN OF ARGUMENT |
||
.,E277 20 0C BC JSR $BC0C |
JSR MOVAF ;GET RESULT INTO ARG. |
FAC runden und nach ARG |
round and copy FAC1 to FAC2 |
|||
.,E27A 20 CC BC JSR $BCCC |
JSR INT ;INTEGERIZE FAC. |
INT - Funktion |
perform INT() |
TAKE INTEGER PART |
||
.,E27D A9 00 LDA #$00 |
CLR ARISGN ;ALWAYS HAVE THE SAME SIGN. |
Vergleichsbyte |
clear byte |
<<< WASTED LINES, BECAUSE FSUBT >>> |
||
.,E27F 85 6F STA $6F |
löschen |
clear sign compare (FAC1 EOR FAC2) |
<<< CHANGES SGNCPR AGAIN >>> |
|||
.,E281 20 53 B8 JSR $B853 |
JSR FSUBT ;KEEP ONLY THE FRACTIONAL PART. |
ARG minus FAC |
perform subtraction, FAC2 from FAC1 |
SUBTRACT TO GET FRACTIONAL PART(FAC) = ANGLE AS A FRACTION OF A FULL CIRCLENOW FOLD THE RANGE INTO A QUARTER CIRCLE<<< THERE ARE MUCH SIMPLER WAYS TO DO THIS >>> |
||
.,E284 A9 EA LDA #$EA |
LDWDI FR4 ;GET PNTR TO 1/4. |
Zeiger auf |
set 0.25 pointer low byte |
1/4 - FRACTION MAKES |
low E2EA |
|
.,E286 A0 E2 LDY #$E2 |
Konstante 0.25 |
set 0.25 pointer high byte |
-3/4 <= FRACTION < 1/4 |
high E2EA |
||
.,E288 20 50 B8 JSR $B850 |
JSR FSUB ;COMPUTE 1/4-FAC. |
0.25 - FAC |
perform subtraction, FAC1 from (AY) |
|||
.,E28B A5 66 LDA $66 |
LDA FACSGN ;SAVE SIGN FOR LATER. |
Vorzeichen laden |
get FAC1 sign (b7) |
TEST SIGN OF RESULT |
||
.,E28D 48 PHA |
PHA |
Vorzeichen in Stack |
save FAC1 sign |
SAVE SIGN FOR LATER UNFOLDING |
||
.,E28E 10 0D BPL $E29D |
BPL SIN1 ;FIRST QUADRANT. |
positiv ? |
branch if +ve FAC1 sign was -ve |
ALREADY 0...1/4 |
||
.,E290 20 49 B8 JSR $B849 |
JSR FADDH ;ADD 1/2 TO FAC. |
FAC + 0.5 |
add 0.5 to FAC1 (round FAC1) |
ADD 1/2 TO SHIFT TO -1/4...1/2 |
||
.,E293 A5 66 LDA $66 |
LDA FACSGN ;SIGN IS NEGATIVE? |
Vorzeichen |
get FAC1 sign (b7) |
TEST SIGN |
||
.,E295 30 09 BMI $E2A0 |
BMI SIN2 |
negativ ? |
branch if -ve |
-1/4...0 0...1/2 |
||
.,E297 A5 12 LDA $12 |
COM TANSGN ;QUADRANTS II AND III COME HERE. |
Vorzeichen laden |
get the comparison evaluation flag |
SIGNFLG INITIALIZED = 0 IN "TAN" |
||
.,E299 49 FF EOR #$FF |
und umdrehen |
toggle flag |
FUNCTION |
|||
.,E29B 85 12 STA $12 |
Vorzeichen speichern |
save the comparison evaluation flag |
"TAN" IS ONLY USER OF SIGNFLG TOO IF FALL THRU, RANGE IS 0...1/2 IF BRANCH HERE, RANGE IS 0...1/4 |
|||
.,E29D 20 B4 BF JSR $BFB4 |
SIN1: JSR NEGOP ;IF POSITIVE, NEGATE IT. |
Vorzeichen wechseln |
do - FAC1 |
IF FALL THRU, RANGE IS -1/2...0 IF BRANCH HERE, RANGE IS -1/4...0 |
||
.,E2A0 A9 EA LDA #$EA |
SIN2: LDWDI FR4 ;POINTER TO 1/4. |
Zeiger auf |
set 0.25 pointer low byte |
ADD 1/4 TO SHIFT RANGE |
low E2EA |
|
.,E2A2 A0 E2 LDY #$E2 |
Konstante 0.25 |
set 0.25 pointer high byte |
TO -1/4...1/4 |
high E2EA |
||
.,E2A4 20 67 B8 JSR $B867 |
JSR FADD ;ADD IT IN. |
FAC + 0.25 |
add (AY) to FAC1 |
|||
.,E2A7 68 PLA |
PLA ;GET ORIGINAL QUADRANT. |
Vorzeichen holen |
restore FAC1 sign |
GET SAVED SIGN FROM ABOVE |
||
.,E2A8 10 03 BPL $E2AD |
BPL SIN3 |
positiv ? |
branch if was +ve else correct FAC1 |
|||
.,E2AA 20 B4 BF JSR $BFB4 |
JSR NEGOP ;IF NEGATIVE, NEGATE RESULT. |
Vorzeichen wechseln |
do - FAC1 |
MAKE RANGE 0...1/4 |
||
.,E2AD A9 EF LDA #$EF |
SIN3: LDWDI SINCON |
Zeiger auf |
set pointer low byte to counter |
DO STANDARD SIN SERIES |
||
.,E2AF A0 E2 LDY #$E2 |
Polynomkoeffizienten |
set pointer high byte to counter |
||||
.,E2B1 4C 43 E0 JMP $E043 |
GPOLYX: JMP POLYX ;DO APPROXIMATION POLYNOMIAL. ;TANGENT FUNCTION. |
Polynom berechnenBASIC-Funktion TAN |
^2 then series evaluation and returnperform TAN() |
"TAN" FUNCTIONCOMPUTE TAN(X) = SIN(X) / COS(X) |
TAN: PERFORM TAN |
TAN function |
.,E2B4 20 CA BB JSR $BBCA |
TAN: JSR MOV1F ;MOVE FAC INTO TEMPORARY. |
FAC nach Akku#3 |
pack FAC1 into $57 |
|||
.,E2B7 A9 00 LDA #$00 |
CLR TANSGN ;REMEMBER WHETHER TO NEGATE. |
Flag |
clear A |
SIGNFLG WILL BE TOGGLED IF 2ND OR 3RD |
||
.,E2B9 85 12 STA $12 |
setzen |
clear the comparison evaluation flag |
QUADRANT |
|||
.,E2BB 20 6B E2 JSR $E26B |
JSR SIN ;COMPUTE THE SIN. |
SIN berechnen |
perform SIN() |
GET SIN(X) |
||
.,E2BE A2 4E LDX #$4E |
LDXYI TEMPF3 |
Zeiger auf |
set sin(n) pointer low byte |
SAVE SIN(X) IN TEMP3 |
low 004E |
|
.,E2C0 A0 00 LDY #$00 |
Hilfsakku |
set sin(n) pointer high byte |
high 004E |
|||
.,E2C2 20 F6 E0 JSR $E0F6 |
JSR GMOVMF ;PUT SIGN INTO OTHER TEMP. |
FAC nach Hilfsakku |
pack FAC1 into (XY) |
<<<FUNNY WAY TO CALL MOVMF! >>> |
||
.,E2C5 A9 57 LDA #$57 |
LDWDI TEMPF1 |
Zeiger auf |
set n pointer low byte |
RETRIEVE X |
low 005F |
|
.,E2C7 A0 00 LDY #$00 |
Akku#3 |
set n pointer high byte |
high 005F |
|||
.,E2C9 20 A2 BB JSR $BBA2 |
JSR MOVFM ;PUT THIS MEMORY LOC INTO FAC. |
Akku#3 nach FAC |
unpack memory (AY) into FAC1 |
|||
.,E2CC A9 00 LDA #$00 |
CLR FACSGN ;START OFF POSITIVE. |
Vorzeichen |
clear byte |
AND COMPUTE COS(X) |
||
.,E2CE 85 66 STA $66 |
löschen |
clear FAC1 sign (b7) |
||||
.,E2D0 A5 12 LDA $12 |
LDA TANSGN |
Flag |
get the comparison evaluation flag |
|||
.,E2D2 20 DC E2 JSR $E2DC |
JSR COSC ;COMPUTE COSINE. |
COS berechnen |
save flag and go do series evaluation |
WEIRD & DANGEROUS WAY TO GET INTO SIN |
||
.,E2D5 A9 4E LDA #$4E |
LDWDI TEMPF3 ;ADDRESS OF SINE VALUE. |
Zeiger auf |
set sin(n) pointer low byte |
NOW FORM SIN/COS |
low 004E |
|
.,E2D7 A0 00 LDY #$00 |
Hilfsakku (SIN) |
set sin(n) pointer high byte |
high 004E |
|||
.,E2D9 4C 0F BB JMP $BB0F |
GFDIV: JMP FDIV ;DIVIDE SINE BY COSINE AND RETURN. |
durch FAC dividieren |
convert AY and do (AY)/FAC1save comparison flag and do series evaluation |
|||
.,E2DC 48 PHA |
COSC: PHA |
COS |
save comparison flag |
SHAME, SHAME! |
||
.,E2DD 4C 9D E2 JMP $E29D |
JMP SIN1 |
berechnenKonstanten für SIN und COS |
add 0.25, ^2 then series evaluationconstants and series for SIN/COS(n) |
PI2: TABLE OF TRIGONOMETRY CONSTANTSThe following constants are held in 5 byte flpt fortrigonometry evaluation. |
float numbers for SIN, COS and TAN0.5 * PI |
|
.:E2E0 81 49 0F DA A2 |
PI2: 201 ;PI/2 111 017 333-ADDPRC IFN ADDPRC,<242> |
1.57079633 Pi/2 |
1.570796371, pi/2, as floating number |
PI/2 |
; 1.570796327 (pi/2) |
2 * PI |
.:E2E5 83 49 0F DA A2 |
TWOPI: 203 ;2*PI. 111 017 333-ADDPRC IFN ADDPRC,<242> |
6.28318531 2*Pi |
6.28319, 2*pi, as floating number |
2*PI |
; 6.28318531 (pi*2) |
0,25 |
.:E2EA 7F 00 00 00 00 |
FR4: 177 ;1/4 000 000 0000 IFN ADDPRC,<0> IFE ADDPRC,<SINCON: 4 ;DEGREE-1. 206 ;39.710899 036 327 373 207 ;-76.574956 231 046 145 207 ;81.602231 043 064 130 206 ;-41.341677 245 135 341 203 ;6.2831853 111 017 333> IFN ADDPRC,< |
.25 |
0.25 |
1/4 |
; 0.25 |
polynomial table |
.:E2EF 05 |
SINCON: 5 ;DEGREE-1. |
5 = Polynomgrad, 6 Koeffizienten |
series counter |
POWER OF POLYNOMIAL |
; 5 (one byte counter for SIN series) |
degree 6 |
.:E2F0 84 E6 1A 2D 1B |
204 ; -14.381383816 346 032 055 033 |
-14.3813907 |
-14.3813907 |
(2PI)^11/11! |
; -14.3813907 (SIN constant 1) |
|
.:E2F5 86 28 07 FB F8 |
206 ; 42.07777095 050 007 373 370 |
42.0077971 |
42.0077971 |
(2PI)^9/9! |
; 42.0077971 (SIN constant 2) |
|
.:E2FA 87 99 68 89 01 |
207 ; -76.704133676 231 150 211 001 |
-76.7041703 |
-76.7041703 |
(2PI)^7/7! |
; -76.7041703 (SIN constant 3) |
|
.:E2FF 87 23 35 DF E1 |
207 ; 81.605223690 043 065 337 341 |
81.6052237 |
81.6052237 |
(2PI)^5/5! |
; 81.6052237 (SIN constant 4) |
|
.:E304 86 A5 5D E7 28 |
206 ; -41.34170209 245 135 347 050 |
-41.3147021 |
-41.3147021 |
(2PI)^3/3! |
; -41.3417021 (SIN constant 5) |
|
.:E309 83 49 0F DA A2 |
203 ; 6.2831853070 111 017 332 242 241 ; 7.2362932E7 124 106 217 23 217 ; 73276.2515 122 103 211 315> PAGE ARCTANGENT FUNCTION.;USE IDENTITIES TO GET ARG BETWEEN 0 AND 1 AND THEN USE AN;APPROXIMATION POLYNOMIAL TO COMPUTE ARCTAN(X). |
6.28318531 2*PiBASIC-Funktion ATN |
6.28318531 2*piperform ATN() |
2PI"ATN" FUNCTION |
; 6.28318531 (SIN constant 6, pi*2)ATN: PERFORM ATN |
ATN function |
.,E30E A5 66 LDA $66 |
ATN: LDA FACSGN ;WHAT IS SIGN? |
Vorzeichen |
get FAC1 sign (b7) |
FOLD THE ARGUMENT RANGE FIRST |
||
.,E310 48 PHA |
PHA ;(MEANWHILE SAVE FOR LATER.) |
retten |
save sign |
SAVE SIGN FOR LATER UNFOLDING |
||
.,E311 10 03 BPL $E316 |
BPL ATN1 |
positiv ? |
branch if +ve |
.GE. 0 |
||
.,E313 20 B4 BF JSR $BFB4 |
JSR NEGOP ;IF NEGATIVE, NEGATE FAC. ;USE ARCTAN(X)=-ARCTAN(-X) . |
Vorzeichen vertauschen |
else do - FAC1 |
.LT. 0, SO COMPLEMENT |
||
.,E316 A5 61 LDA $61 |
ATN1: LDA FACEXP |
Exponent |
get FAC1 exponent |
IF .GE. 1, FORM RECIPROCAL |
||
.,E318 48 PHA |
PHA ;SAVE THIS TOO FOR LATER. |
retten |
push exponent |
SAVE FOR LATER UNFOLDING |
||
.,E319 C9 81 CMP #$81 |
CMPI 201 ;SEE IF FAC .GE. 1.0 . |
Zahl mit 1 vergleichen |
compare with 1 |
(EXPONENT FOR .GE. 1 |
||
.,E31B 90 07 BCC $E324 |
BCC ATN2 ;IT IS LESS THAN 1. |
kleiner ? |
branch if FAC1 < 1 |
X < 1 |
||
.,E31D A9 BC LDA #$BC |
LDWDI FONE ;GET PNTR TO 1.0 . |
Zeiger auf |
pointer to 1 low byte |
FORM 1/X |
low B9BC |
|
.,E31F A0 B9 LDY #$B9 |
Konstante 1 |
pointer to 1 high byte |
high B9BC |
|||
.,E321 20 0F BB JSR $BB0F |
JSR FDIV ;COMPUTE RECIPROCAL. ;USE ARCTAN(X)=PI/2-ARCTAN(1/X) . |
1 durch FAC dividieren (Kehrwert) |
convert AY and do (AY)/FAC1 |
0 <= X <= 1 0 <= ATN(X) <= PI/8 |
||
.,E324 A9 3E LDA #$3E |
ATN2: LDWDI ATNCON ;PNTR TO ARCTAN CONSTANTS. |
Zeiger auf |
pointer to series low byte |
COMPUTE POLYNOMIAL APPROXIMATION |
low E33E |
|
.,E326 A0 E3 LDY #$E3 |
Polynomkoeffizienten |
pointer to series high byte |
high E33E |
|||
.,E328 20 43 E0 JSR $E043 |
JSR POLYX |
Polynom berechnen |
^2 then series evaluation |
|||
.,E32B 68 PLA |
PLA |
Exponent zurückholen |
restore old FAC1 exponent |
START TO UNFOLD |
||
.,E32C C9 81 CMP #$81 |
CMPI 201 ;WAS ORIGINAL ARGUMENT .LT. 1 ? |
war Zahl |
compare with 1 |
WAS IT .GE. 1? |
||
.,E32E 90 07 BCC $E337 |
BCC ATN3 ;YES. |
kleiner 1, dann zu $E337 |
branch if FAC1 < 1 |
NO |
||
.,E330 A9 E0 LDA #$E0 |
LDWDI PI2 |
Zeiger auf |
pointer to (pi/2) low byte |
YES, SUBTRACT FROM PI/2 |
low E2E0 |
|
.,E332 A0 E2 LDY #$E2 |
Konstante Pi/2 |
pointer to (pi/2) low byte |
high E2E0 |
|||
.,E334 20 50 B8 JSR $B850 |
JSR FSUB ;SUBTRACT ARCTAGN FROM PI/2. |
Pi/2 minus FAC |
perform subtraction, FAC1 from (AY) |
|||
.,E337 68 PLA |
ATN3: PLA ;WAS ORIGINAL ARGUMENT POSITIVE? |
Vorzeichen holen |
restore FAC1 sign |
WAS IT NEGATIVE? |
||
.,E338 10 03 BPL $E33D |
BPL ATN4 ;YES. |
positiv ? |
exit if was +ve |
NO |
||
.,E33A 4C B4 BF JMP $BFB4 |
JMP NEGOP ;IF NEGATIVE, NEGATE RESULT. |
Vorzeichen wechseln |
else do - FAC1 and return |
YES, COMPLEMENT |
||
.,E33D 60 RTS |
ATN4: RTS ;ALL DONE. IFE ADDPRC,< ATNCON: 10 ;DEGREE-1. 170 ;.0028498896 072 305 067 173 ;-.016068629 203 242 134 174 ;.042691519 056 335 115 175 ;-.075042945 231 260 036 175 ;.10640934 131 355 044 176 ;-.14203644 221 162 000 176 ;.19992619 114 271 163 177 ;.-33333073 252 252 123 201 ;1.0 000 000 000> IFN ADDPRC,< |
RücksprungFließkommakonstanten fürATN-Funktion |
series for ATN(n) |
ATNCON: TABLE OF ATN CONSTANTSThe table holds a 1 byte counter and the folloeing 5 byteflpt constants. |
float numbers for ATNpolynomial table |
|
.:E33E 0B |
ATNCON: 13 ;DEGREE-1. |
11 = Polynomgrad, dann 12 Koeffizienten |
series counter |
POWER OF POLYNOMIAL |
; 13 (one byte counter for ATN series) |
degree 12 |
.:E33F 76 B3 83 BD D3 |
166 ; -.0006847939119 263 203 275 323 |
-6.84793912E-04 |
-6.84793912E-04 |
; -0.000684793912 (ATN constant 1) |
||
.:E344 79 1E F4 A6 F5 |
171 ; .004850942156 036 364 246 365 |
4.85094216E-03 |
4.85094216E-03 |
; 0.00485094216 (ATN constant 2) |
||
.:E349 7B 83 FC B0 10 |
173 ; -.01611170184 203 374 260 020 |
-.0161117015 |
-.0161117015 |
; -0.161117018 (ATN constant 3) |
||
.:E34E 7C 0C 1F 67 CA |
174 ; .03420963805 014 037 147 312 |
.034209638 |
.034209638 |
; 0.034209638 (ATN constant 5) |
||
.:E353 7C DE 53 CB C1 |
174 ; -.05427913276 336 123 313 301 |
-.054279133 |
-.054279133 |
; -0.0542791328 (ATN constant 6) |
||
.:E358 7D 14 64 70 4C |
175 ; .07245719654 024 144 160 114 |
.0724571965 |
.0724571965 |
; 0.0724571965 (ATN constant 7) |
||
.:E35D 7D B7 EA 51 7A |
175 ; -.08980239538 267 352 121 172 |
-.0898019185 |
-.0898019185 |
; -0.0898023954 (ATN constant 8) |
||
.:E362 7D 63 30 88 7E |
175 ; .1109324134 143 060 210 176 |
.110932413 |
.110932413 |
; 0.110932413 (ATN constant 9) |
||
.:E367 7E 92 44 99 3A |
176 ; -.1428398077 222 104 231 072 |
-.142839808 |
-.142839808 |
; -0.14283908 (ATN constant 10) |
||
.:E36C 7E 4C CC 91 C7 |
176 ; .1999991205 114 314 221 307 |
.19999912 |
.19999912 |
; 0.19999912 (ATN constant 11) |
||
.:E371 7F AA AA AA 13 |
177 ; -.3333333157 252 252 252 023 |
-.333333316 |
-.333333316 |
; -0.333333316 (ATN constant 12) |
||
.:E376 81 00 00 00 00 |
201 ; 1.0 000 000 000 000>> |
1BASIC NMI-Einsprung |
1BASIC warm start entry point |
; 1 (ATN constant 13)BASSFT: BASIC WARM STARTThis is the BASIC warm start routine that is vectored atthe very start of the BASIC ROM. The routine is called by the 6510 BRK instruction, or STOP/RESTORE being pressed. It outputs the READY prompt via the IERROR vector at $0300. If the error code, in (X) is larger than $80, then only the READY text will be displayed. |
warm start entry |
|
.,E37B 20 CC FF JSR $FFCC |
CLRCH |
close input and output channels |
CLRCHN, close all I/O channels |
|||
.,E37E A9 00 LDA #$00 |
Eingabegerät gleich |
clear A |
||||
.,E380 85 13 STA $13 |
Tastatur |
set current I/O channel, flag default |
input prompt flag |
|||
.,E382 20 7A A6 JSR $A67A |
BASIC initialisieren |
flush BASIC stack and clear continue pointer |
do CLR |
|||
.,E385 58 CLI |
Interrupt freigeben |
enable the interrupts |
enable IRQ |
|||
.,E386 A2 80 LDX #$80 |
Flag für kein Fehler |
set -ve error, just do warm start |
error code #$80 |
|||
.,E388 6C 00 03 JMP ($0300) |
BASIC Warmstart Vektor JMP $E38B |
go handle error message, normally $E38B |
perform error |
normally E38Bhandle error messages |
||
.,E38B 8A TXA |
Fehlernummer in Akku |
copy the error number |
error number |
|||
.,E38C 30 03 BMI $E391 |
kein Fehler, dann 'ready.' |
if -ve go do warm start |
larger than $80 |
|||
.,E38E 4C 3A A4 JMP $A43A |
Fehlermeldung ausgeben |
else do error #X then warm start |
nope, print error |
|||
.,E391 4C 74 A4 JMP $A474 |
Ready - ModusBASIC Kaltstart |
do warm startBASIC cold start entry point |
print READYINIT: BASIC COLD STARTThis is the BASIC cold start routine that is vectored atthe very start of the BASIC ROM. BASIC vectors and variables are set up, and power-up message is output, and BASIC is restarted. |
RESET routine |
||
.,E394 20 53 E4 JSR $E453 |
BASIC-Vektoren setzen |
initialise the BASIC vector table |
||||
.,E397 20 BF E3 JSR $E3BF |
RAM initialisieren |
initialise the BASIC RAM locations |
Initialize BASIC |
|||
.,E39A 20 22 E4 JSR $E422 |
Einschaltmeldung ausgeben |
print the start up message and initialise the memory pointers not ok ?? |
output power-up message |
|||
.,E39D A2 FB LDX #$FB |
Stackzeiger |
value for start stack |
reset stack |
|||
.,E39F 9A TXS |
setzen |
set stack pointer |
||||
.,E3A0 D0 E4 BNE $E386 |
PAGESYSTEM INITIALIZATION CODE.RADIX 10 ;IN ALL NON-MATH-PACKAGE CODE.; THIS INITIALIZES THE BASIC INTERPRETER FOR THE M6502 AND SHOULD BE ; LOCATED WHERE IT WILL BE WIPED OUT IN RAM IF CODE IS ALL IN RAM. IFE ROMSW,< BLOCK 1> ;SO ZEROING AT TXTTAB DOESN'T PREVENT ;RESTARTING INIT |
zum WarmstartKopie der CHRGET-Routine |
do "READY." warm start, branch alwayscharacter get subroutine for zero pagethe target address for the LDA $EA60 becomes the BASIC execute pointer once theblock is copied to its destination, any non zero page address will do at assembly time, to assemble a three byte instruction. $EA60 is RTS, NOP. page 0 initialisation table from $0073 increment and scan memory |
GENERIC COPY OF CHRGET SUBROUTINEWHICH IS COPIED INTO $00B1...$00C8 DURING INITIALIZATIONCORNELIS BONGERS DESCRIBED SEVERAL IMPROVEMENTS TO CHRGET IN MICRO MAGAZINE OR CALL A.P.P.L.E. (I DON'T REMEMBER WHICH OR EXACTLY WHEN) |
output READY, and restart BASICINITAT: CHRGET FOR ZEROPAGEThis is the CHRGET routine which is transferred to RAMstarting at $0073 on power-up or reset. |
character fetch code for zero page $0073-$008F |
.,E3A2 E6 7A INC $7A |
INITAT: INC CHRGET+7 ;INCREMENT THE WHOLE TXTPTR. |
LOW-Byte Zeiger erhöhen |
increment BASIC execute pointer low byte |
increment <TXTPTR |
||
.,E3A4 D0 02 BNE $E3A8 |
BNE CHZGOT |
Zeiger in BASIC-Text erhöhen |
branch if no carry else |
skip high byte |
||
.,E3A6 E6 7B INC $7B |
INC CHRGET+8 |
HIGH-Byte Zeiger erhöhen |
increment BASIC execute pointer high byte page 0 initialisation table from $0079 scan memory |
increment >TXTPTR |
||
.,E3A8 AD 60 EA LDA $EA60 |
CHZGOT: LDA 60000 ;A LOAD WITH AN EXT ADDR. |
BASIC-Adresse laden |
get byte to scan, address set by call routine |
<<< ACTUAL ADDRESS FILLED IN LATER >>> |
CHRGOT entry, read TXTPTR |
|
.,E3AB C9 3A CMP #$3A |
CMPI ":" ;IS IT A ":"? |
keine Zahl, |
compare with ":" |
EOS, ALSO TOP OF NUMERIC RANGE |
colon (terminator), sets (Z) |
colon |
.,E3AD B0 0A BCS $E3B9 |
BCS CHZRTS ;IT IS .GE. ":" |
dann fertig |
exit if>= page 0 initialisation table from $0080 clear Cb if numeric |
NOT NUMBER, MIGHT BE EOS |
||
.,E3AF C9 20 CMP #$20 |
CMPI " " ;SKIP SPACES. |
' ' Leerzeichen überlesen |
compare with " " |
IGNORE BLANKS |
space, get next character |
space |
.,E3B1 F0 EF BEQ $E3A2 |
BEQ INITAT |
ja, nächstes Zeichen |
if " " go do next |
|||
.,E3B3 38 SEC |
SEC |
Test auf |
set carry for SBC |
TEST FOR NUMERIC RANGE IN WAY THAT |
||
.,E3B4 E9 30 SBC #$30 |
SBCI "0" ;ALL CHARS .GT. "9" HAVE RET'D SO |
Ziffer, |
subtract "0" |
CLEARS CARRY IF CHAR IS DIGIT |
zero |
0 |
.,E3B6 38 SEC |
SEC |
dann |
set carry for SBC |
AND LEAVES CHAR IN A-REG |
||
.,E3B7 E9 D0 SBC #$D0 |
SBCI ^D256-"0" ;SEE IF NUMERIC. ;TURN CARRY ON IF NUMERIC. ;ALSO, SETZ IF NULL. |
C=1 |
subtract -"0" clear carry if byte = "0"-"9" |
|||
.,E3B9 60 RTS |
CHZRTS: RTS ;RETURN TO CALLER. |
RücksprungAnfangswert für RND-Funktion |
spare bytes, not referenced |
INITIAL VALUE FOR RANDOM NUMBERALSO COPIED IN ALONG WITH CHRGET, BUT ERRONEOUSLY:<<< THE LAST BYTE IS NOT COPIED >>> |
RNDSED: RANDOM SEED FOR ZEROPAGEThis is the initial value of the seed for the randomnumber function. It is copied into RAM from $008b-$008f. Its fltp value is 0.811635157. |
first RND seed value |
.:E3BA 80 4F C7 52 58 |
128 ;LOADED OR FROM ROM. 79 ;THE INITIAL RANDOM NUMBER. 199 82 IFN ADDPRC,<88> IFN REALIO-3,< IFE KIMROM,< TYPAUT: LDWDI AUTTXT JSR STROUT>> INIT: IFN REALIO-3,< |
.811635157RAM für BASIC initialisieren |
0.811635157initialise BASIC RAM locations |
APPROX. = .811635157 |
INITCZ: INITIALISE BASIC RAMThis routine sets the USR jump instruction to point to?ILLEGAL QUANTITY error, sets ADRAY1 and ADRAY2, copies CHRGET and RNDSED to zeropage, sets up the start and end locations for BASIC text and sets the first text byte to zero. |
initialisation of basic |
.,E3BF A9 4C LDA #$4C |
LDXI 255 ;MAKE IT LOOK DIRECT IN CASE OF |
JMP |
opcode for JMP |
; opcode for JMP |
||
.,E3C1 85 54 STA $54 |
STX CURLIN+1> ;ERROR MESSAGE. |
für Funktionen |
save for functions vector jump |
; store in JMPER |
||
.,E3C3 8D 10 03 STA $0310 |
IFN STKEND-511,< |
für USR-Funktion |
save for USR() vector jump set USR() vector to illegal quantity error |
; USRPOK, set USR JMP instruction |
||
.,E3C6 A9 48 LDA #$48 |
LDXI STKEND-256> |
Zeiger auf |
set USR() vector low byte |
low B248 |
||
.,E3C8 A0 B2 LDY #$B2 |
TXS |
'ILLEGAL QUANTITY' |
set USR() vector high byte |
; vector to $b248, ?ILLEGAL QUANTITY |
high B248 |
|
.,E3CA 8D 11 03 STA $0311 |
IFN REALIO-3,< |
als USR-Vektor |
save USR() vector low byte |
|||
.,E3CD 8C 12 03 STY $0312 |
LDWDI INIT ;ALLOW RESTART. |
speichern |
save USR() vector high byte |
; store in USRADD |
||
.,E3D0 A9 91 LDA #$91 |
STWD START+1 |
Adresse |
set fixed to float vector low byte |
lowh B391 |
||
.,E3D2 A0 B3 LDY #$B3 |
STWD RDYJSR+1 ;RTS HERE ON ERRORS. |
$B391 |
set fixed to float vector high byte |
; vector to $b391 |
high B391 |
|
.,E3D4 85 05 STA $05 |
LDWDI AYINT |
als Vektor für |
save fixed to float vector low byte |
|||
.,E3D6 84 06 STY $06 |
STWD ADRAYI |
Fest-/Fließkomma-Wandlung |
save fixed to float vector high byte |
; store in ADRAY2 |
||
.,E3D8 A9 AA LDA #$AA |
LDWDI GIVAYF |
Adresse |
set float to fixed vector low byte |
POINT "USR" TO ILLEGAL QUANTITY |
low B1AA |
|
.,E3DA A0 B1 LDY #$B1 |
STWD ADRGAY> |
$B1AA |
set float to fixed vector high byte |
ERROR, UNTIL USER SETS IT UP |
; vector to $b1aa |
high B1AA |
.,E3DC 85 03 STA $03 |
LDAI 76 ;JMP INSTRUCTION. |
als Vektor für |
save float to fixed vector low byte |
|||
.,E3DE 84 04 STY $04 |
IFE REALIO,<HRLI 1,^O1000> ;MAKE AN INST. IFN REALIO-3,< STA START STA RDYJSR> STA JMPER IFN ROMSW,< STA USRPOK LDWDI FCERR STWD USRPOK+1> LDAI LINLEN ;THESE MUST BE NON-ZERO SO CHEAD WILL STA LINWID ;WORK AFTER MOVING A NEW LINE IN BUF ;INTO THE PROGRAM LDAI NCMPOS STA NCMWID |
Fließ-/Festkomma-Wandlung |
save float to fixed vector high byte copy the character get subroutine from $E3A2 to $0074 |
MOVE GENERIC CHRGET AND RANDOM SEED INTO PLACE<<< NOTE THAT LOOP VALUE IS WRONG! >>><<< THE LAST BYTE OF THE RANDOM SEED IS NOT >>> <<< COPIED INTO PAGE ZERO! >>> |
; store in ADRAY1 |
|
.,E3E0 A2 1C LDX #$1C |
LDXI RNDX+4-CHRGET |
Zähler setzen |
set the byte count |
; copy the CHRGET routine and RNDSED to RAM |
||
.,E3E2 BD A2 E3 LDA $E3A2,X |
MOVCHG: LDA INITAT-1,X, |
CHRGET-Routine |
get a byte from the table |
; source address |
||
.,E3E5 95 73 STA $73,X |
STA CHRGET-1,X, ;MOVE TO RAM. |
ins |
save the byte in page zero |
; destination address |
||
.,E3E7 CA DEX |
DEX |
RAM kopieren |
decrement the count |
; next byte |
||
.,E3E8 10 F8 BPL $E3E2 |
BNE MOVCHG |
schon alles? |
loop if not all done clear descriptors, strings, program area and mamory pointers |
; till ready |
||
.,E3EA A9 03 LDA #$03 |
LDAI STRSIZ |
Schrittweise |
set the step size, collecting descriptors |
SET LENGTH OF TEMP. STRING DESCRIPTORS |
||
.,E3EC 85 53 STA $53 |
STA FOUR6 |
für Garbage Collection |
save the garbage collection step size |
FOR GARBAGE COLLECTION SUBROUTINE |
; store #3 in FOUR6, garbage collection |
|
.,E3EE A9 00 LDA #$00 |
TXA ;SET CONST IN RAM. |
FAC-Rundungsbyte |
clear A |
|||
.,E3F0 85 68 STA $68 |
STA BITS |
löschen |
clear FAC1 overflow byte |
; init BITS, fac#1 overflow |
||
.,E3F2 85 13 STA $13 |
IFN EXTIO,< |
Eingabegerät gleich |
clear the current I/O channel, flag default |
; init input prompt flag |
||
.,E3F4 85 18 STA $18 |
STA CHANNL> |
Tastatur |
clear the current descriptor stack item pointer high byte |
; init LASTPT |
||
.,E3F6 A2 01 LDX #$01 |
STA LASTPT+1 |
Dummys |
set X |
SET UP FAKE FORWARD LINK |
||
.,E3F8 8E FD 01 STX $01FD |
IFN NULCMD,< |
für Linkadresse beim |
set the chain link pointer low byte |
|||
.,E3FB 8E FC 01 STX $01FC |
STA NULCNT> |
Zeileneinbau |
set the chain link pointer high byte |
|||
.,E3FE A2 19 LDX #$19 |
PHA ;PUT ZERO AT THE END OF THE STACK |
Zeiger für |
initial the value for descriptor stack |
INIT INDEX TO TEMP STRING DESCRIPTORS |
||
.,E400 86 16 STX $16 |
;SO FNDFOR WILL STOP |
Stringverwaltung |
set descriptor stack pointer |
; TEMPPT, pointer to descriptor stack |
||
.,E402 38 SEC |
IFN REALIO,< |
RAM- |
set Cb = 1 to read the bottom of memory |
; set carry to indicate read mode |
||
.,E403 20 9C FF JSR $FF9C |
STA CNTWFL> ;BE TALKATIVE. |
Start holen |
read/set the bottom of memory |
; read MEMBOT |
||
.,E406 86 2B STX $2B |
IFN BUFPAG,< |
als BASIC-Start |
save the start of memory low byte |
; set TXTTAB, bottom of RAM |
||
.,E408 84 2C STY $2C |
INX ;MAKE [X]=1 |
speichern |
save the start of memory high byte |
|||
.,E40A 38 SEC |
STX BUF-3 ;SET PRE-BUF BYTES NON-ZERO FOR CHEAD |
RAM- |
set Cb = 1 to read the top of memory |
; set carry to indicate read mode |
||
.,E40B 20 99 FF JSR $FF99 |
STX BUF-4> |
Ende holen |
read/set the top of memory |
; read MEMTOP |
||
.,E40E 86 37 STX $37 |
IFN REALIO-3,< |
als |
save the end of memory low byte |
; set MEMSIZ, top of RAM |
||
.,E410 84 38 STY $38 |
JSR CRDO> ;TYPE A CR. |
BASIC- |
save the end of memory high byte |
|||
.,E412 86 33 STX $33 |
LDXI TEMPST |
Ende |
set the bottom of string space low byte |
; set FRETOP = MEMTOP |
||
.,E414 84 34 STY $34 |
STX TEMPPT ;SET UP STRING TEMPORARIES. |
speichern |
set the bottom of string space high byte |
|||
.,E416 A0 00 LDY #$00 |
IFN REALIO!LONGI,< |
$00 |
clear the index |
|||
.,E418 98 TYA |
IFN REALIO-3,< |
an |
clear the A |
|||
.,E419 91 2B STA ($2B),Y |
LDWDI MEMORY |
BASIC-Start |
clear the the first byte of memory |
; store zero at start of BASIC |
||
.,E41B E6 2B INC $2B |
JSR STROUT |
den |
increment the start of memory low byte |
; increment TXTTAB to next memory position |
||
.,E41D D0 02 BNE $E421 |
JSR QINLIN ;GET A LINE OF INPUT. |
BASIC- |
if no rollover skip the high byte increment |
; skip msb |
||
.,E41F E6 2C INC $2C |
STXY TXTPTR ;READ THIS ! |
Start + 1 |
increment start of memory high byte |
|||
.,E421 60 RTS |
JSR CHRGET ;GET THE FIRST CHARACTER. |
Programmnde |
print the start up message and initialise the memory pointers |
; returnINITMS: OUTPUT POWER-UP MESSAGEThis routine outputs the startup message. It thencalcuates the number of BASIC bytes free by subatracting the TXTTAB from MEMSIZ, and outputs this number. The routine exits via NEW. |
print BASIC start up messages |
|
.,E422 A5 2B LDA $2B |
IFE KIMROM,< |
Zeiger auf |
get the start of memory low byte |
read TXTTAB, start of BASIC |
||
.,E424 A4 2C LDY $2C |
CMPI "A" ;IS IT AN "A"? |
BASIC-RAM Start |
get the start of memory high byte |
|||
.,E426 20 08 A4 JSR $A408 |
BEQ TYPAUT> ;YES TYPE AUTHOR'S NAME. |
prüft auf Platz im Speicher |
check available memory, do out of memory error if no room |
check for memory overlap |
||
.,E429 A9 73 LDA #$73 |
TAY ;NULL INPUT? |
Zeiger auf |
set "**** COMMODORE 64 BASIC V2 ****" pointer low byte |
$e473, startup message |
low E473 |
|
.,E42B A0 E4 LDY #$E4 |
BNE USEDE9> ;NO. |
Einschaltmeldung |
set "**** COMMODORE 64 BASIC V2 ****" pointer high byte |
high E473 |
||
.,E42D 20 1E AB JSR $AB1E |
IFE REALIO-3,< |
String ausgeben |
print a null terminated string |
output (A/Y) |
||
.,E430 A5 37 LDA $37 |
LDYI RAMLOC/^D256> |
BASIC- |
get the end of memory low byte |
MEMSIZ, highest address in BASIC |
||
.,E432 38 SEC |
IFN REALIO-3,< |
Ende |
set carry for subtract |
prepare for substract |
||
.,E433 E5 2B SBC $2B |
IFE ROMSW,< |
minus |
subtract the start of memory low byte |
substract TXTTAB |
||
.,E435 AA TAX |
LDWDI LASTWR> ;YES GET PNTR TO LAST WORD. |
BASIC-Start |
copy the result to X |
move to (X) |
||
.,E436 A5 38 LDA $38 |
IFN ROMSW,< |
gleich |
get the end of memory high byte |
and highbyte |
||
.,E438 E5 2C SBC $2C |
LDWDI RAMLOC>> |
Bytes free |
subtract the start of memory high byte |
|||
.,E43A 20 CD BD JSR $BDCD |
IFN ROMSW,< |
Anzahl ausgeben |
print XA as unsigned integer |
output number in (A/X) |
||
.,E43D A9 60 LDA #$60 |
STWD TXTTAB> ;SET UP START OF PROGRAM LOCATION |
Zeiger auf |
set " BYTES FREE" pointer low byte |
$e460 |
low E460 |
|
.,E43F A0 E4 LDY #$E4 |
STWD LINNUM |
'BASIC BYTES FREE' |
set " BYTES FREE" pointer high byte |
pointer to 'BASIC BYTES FREE' |
high E460 |
|
.,E441 20 1E AB JSR $AB1E |
IFE REALIO-3,< |
String ausgeben |
print a null terminated string |
output (A/Y) |
||
.,E444 4C 44 A6 JMP $A644 |
TAY> |
zum NEW-BefehlTabelle der BASIC-Vektoren |
do NEW, CLEAR, RESTORE and returnBASIC vectors, these are copied to RAM from $0300 onwards |
perform NEWVECTORSThis table contains jump vectors that are transfered to$0300-$030b. |
vectors for $0300-$030B |
|
.:E447 8B E3 83 A4 7C A5 1A A7 |
IFN REALIO-3,< |
error message $0300 |
IERROR VEC, print basic error message ($e38b) |
|||
.:E44F E4 A7 86 AE |
LDYI 0> |
BASIC warm start $0302 crunch BASIC tokens $0304 uncrunch BASIC tokens $0306 start new BASIC code $0308 |
IMAIN VECTOR, basic warm start ($a483) ICRNCH VECTOR, tokenise basic text ($a57c) IQPLOP VECTOR, list basic text ($a7a1) IGONE VEXTOR, basic character dispatch ($a7e4) |
|||
.,E453 A2 0B LDX #$0B |
LOOPMM: INC LINNUM |
Die |
get arithmetic element $030Ainitialise the BASIC vectorsset byte count |
IEVAL VECTOR, evaluate basic token ($ae86)INIT VECTORSThis routine transfers the vectors $0300-$030b.6 vectors to be copied |
initialise vectors |
|
.,E455 BD 47 E4 LDA $E447,X |
BNE LOOPM1 |
BASIC- |
get byte from table |
|||
.,E458 9D 00 03 STA $0300,X |
INC LINNUM+1 |
Vektoren |
save byte to RAM |
|||
.,E45B CA DEX |
IFE REALIO-3,< |
laden |
decrement index |
next byte |
||
.,E45C 10 F7 BPL $E455 |
BMI USEDEC> |
schon alle? |
loop if more to do |
ready |
||
.,E45E 60 RTS |
LOOPM1: LDAI 85 ;PUT RANDOM INFO INTO MEM. STADY LINNUM CMPDY LINNUM ;WAS IT SAVED? BNE USEDEC ;NO. THAT IS END OF MEMORY. ASL A, ;LOOKS LIKE IT. TRY ANOTHER. STADY LINNUM CMPDY LINNUM ;WAS IT SAVED? IFN REALIO-3,< BNE USEDEC> ;NO. THIS IS THE END. IFN REALIO-2,< BEQ LOOPMM> IFE REALIO-2,< BNE USEDEC CMP 0 ;SEE IF HITTING PAGE 0 BNE LOOPMM LDAI 76 STA 0 BNEA USEDEC> IFN REALIO-3,< USEDE9: JSR CHRGOT ;GET CURRENT CHARACTER. JSR LINGET ;GET DECIMAL ARGUMENT. TAY ;MAKE SURE A TERMINATOR EXISTS. BEQ USEDEC ;IT DOES. JMP SNERR> ;IT DOESN'T. USEDEC: LDWD LINNUM ;GET SIZE OF MEMORY INPUT. USEDEF: > ;HIGHEST ADDRESS. IFE REALIO!LONGI,< LDWDI 16190> ;A STRANGE NUMBER. STWD MEMSIZ ;THIS IS THE SIZE OF MEMORY. STWD FRETOP ;TOP OF STRINGS TOO. TTYW: IFN REALIO-3,< IFN REALIO!LONGI,< LDWDI TTYWID JSR STROUT JSR QINLIN ;GET LINE OF INPUT. STXY TXTPTR ;READ THIS ! JSR CHRGET ;GET FIRST CHARACTER. TAY ;TEST ACCA BUT DON'T AFFECT CARRY. BEQ ASKAGN JSR LINGET ;GET ARGUMENT. LDA LINNUM+1 BNE TTYW ;WIDTH MUST BE .LT. 256. LDA LINNUM CMPI 16 ;WIDTH MUST BE GREATER THAN 16. BCC TTYW STA LINWID ;THAT IS THE LINE WIDTH. MORCPS: SBCI CLMWID ;COMPUTE POSITION BEYOND WHICH BCS MORCPS ;THERE ARE NO MORE FIELDS. EORI 255 SBCI CLMWID-2 CLC ADC LINWID STA NCMWID> ASKAGN: IFE ROMSW,< IFN REALIO!LONGI,< LDWDI FNS JSR STROUT JSR QINLIN STXY TXTPTR ;READ THIS ! JSR CHRGET LDXYI INITAT ;DEFAULT. CMPI "Y" BEQ HAVFNS ;SAVE ALL FUNCTIONS. CMPI "A" BEQ OKCHAR ;SAVE ALL BUT ATN. CMPI "N" BNE ASKAGN ;BAD INPUT. ;SAVE NOTHING. OKCHAR: LDXYI FCERR STXY ATNFIX ;GET RID OF ATN FUNCTION. LDXYI ATN ;UNTIL WE KNOW THAT WE SHOULD DEL MORE. CMPI "A" BEQ HAVFNS ;JUST GET RID OF ATN. LDXYI FCERR STXY COSFIX ;GET RID OF THE REST. STXY TANFIX STXY SINFIX LDXYI COS ;AND GET RID OF ALL BACK TO "COS". HAVFNS:> IFE REALIO!LONGI,< LDXYI INITAT-1>>> ;GET RID OF ALL UP TO "INITAT". IFN ROMSW,< LDXYI RAMLOC STXY TXTTAB> LDYI 0 TYA STADY TXTTAB ;SET UP TEXT TABLE. INC TXTTAB IFN REALIO-3,< BNE QROOM INC TXTTAB+1> QROOM: LDWD TXTTAB ;PREPARE TO USE "REASON". JSR REASON IFE REALIO-3,< LDWDI FREMES JSR STROUT> IFN REALIO-3,< JSR CRDO> LDA MEMSIZ ;COMPUTE [MEMSIZ]-[VARTAB]. SEC SBC TXTTAB TAX LDA MEMSIZ+1 SBC TXTTAB+1 JSR LINPRT ;TYPE THIS VALUE. LDWDI WORDS ;MORE BULLSHIT. JSR STROUT JSR SCRTCH ;SET UP EVERYTHING ELSE. IFE REALIO-3,< JMP READY> IFN REALIO-3,< LDWDI STROUT STWD RDYJSR+1 LDWDI READY STWD START+1 JMPD START+1 IFE ROMSW,< FNS: DT"WANT SIN-COS-TAN-ATN" 0> IFE KIMROM,< AUTTXT: ACRLF 12 ;ANOTHER LINE FEED. DT"WRITTEN " DT"BY WEILAND & GATES" ACRLF 0> MEMORY: DT"MEMORY SIZE" 0 TTYWID: IFE KIMROM,< DT"TERMINAL "> DT"WIDTH" 0> WORDS: DT" BYTES FREE" IFN REALIO-3,< ACRLF ACRLF> IFE REALIO-3,< EXP ^O15 0 FREMES: > IFE REALIO,< DT"SIMULATED BASIC FOR THE 6502 V1.1"> IFE REALIO-1,< DT"KIM BASIC V1.1"> IFE REALIO-2,< DT"OSI 6502 BASIC VERSION 1.1"> IFE REALIO-3,< DT"### COMMODORE BASIC ###" EXP ^O15 EXP ^O15> IFE REALIO-4,<DT"APPLE BASIC V1.1"> IFE REALIO-5,<DT"STM BASIC V1.1"> IFN REALIO-3,< ACRLF DT"COPYRIGHT 1978 MICROSOFT" ACRLF> 0 LASTWR:: BLOCK 100 ;SPACE FOR TEMP STACK. IFE REALIO,< TSTACK::BLOCK 13600> IF2,< PURGE A,X,Y> IFNDEF START,<START==0> END $Z+START ERNAL ROM Disassembly (English, "CBM") rom rce by Commodore (901227-03) bmsrc p=894 y a complete copy of the original version in the C64 ROM. mes are intact. hael Steil <mist64@mac.com> g up) welcome at: ef ---------------------------- ted so that it can be automatically s-references etc. op-level information. The first line with "--" are separators. internal comments. icate code to be disassembled. icate bytes to be dumped. olumn. indicate a heading. indicate an overflow comment. .LIB DISCLAIMER;****************************************;* * ;* KK K EEEEE RRRR NN N AAA LL * ;* KK KK EE RR R NNN N AA A LL * ;* KKK EE RR R NNN N AA A LL * ;* KKK EEEE RRRR NNNNN AAAAA LL * ;* KK K EE RR R NN NN AA A LL * ;* KK KK EE RR R NN NN AA A LL * ;* KK KK EEEEE RR R NN NN AA A LLLLL * ;* * ;*************************************** ; ;*************************************** ;* PET KERNAL * ;* MEMORY AND I/O DEPENDENT ROUTINES * ;* DRIVING THE HARDWARE OF THE * ;* FOLLOWING CBM MODELS: * ;* COMMODORE 64 OR MODIFED VIC-40 * ;* COPYRIGHT (C) 1982 BY * ;* COMMODORE BUSINESS MACHINES (CBM) * ;*************************************** ;****LISTING DATE --1200 14 MAY 1982**** ;*************************************** ;* THIS SOFTWARE IS FURNISHED FOR USE * ;* USE IN THE VIC OR COMMODORE COMPUTER* ;* SERIES ONLY. * ;* * ;* COPIES THEREOF MAY NOT BE PROVIDED * ;* OR MADE AVAILABLE FOR USE ON ANY * ;* OTHER SYSTEM. * ;* * ;* THE INFORMATION IN THIS DOCUMENT IS * ;* SUBJECT TO CHANGE WITHOUT NOTICE. * ;* * ;* NO RESPONSIBILITY IS ASSUMED FOR * ;* RELIABILITY OF THIS SOFTWARE. RSR * ;* * ;*************************************** .END .LIB DECLARE*=$0000 ;DECLARE 6510 PORTSD6510 *=*+1 ;6510 DATA DIRECTION REGISTER R6510 *=*+1 ;6510 DATA REGISTER *=$0002 ;MISS 6510 REGS ;VIRTUAL REGS FOR MACHINE LANGUAGE MONITOR PCH *=*+1 PCL *=*+1 FLGS *=*+1 ACC *=*+1 XR *=*+1 YR *=*+1 SP *=*+1 INVH *=*+1 ;USER MODIFIABLE IRQ INVL *=*+1 * =$90 STATUS *=*+1 ;I/O OPERATION STATUS BYTE ; CRFAC *=*+2 ;CORRECTION FACTOR (UNUSED) STKEY *=*+1 ;STOP KEY FLAG SVXT *=*+1 ;TEMPORARY VERCK *=*+1 ;LOAD OR VERIFY FLAG C3P0 *=*+1 ;IEEE BUFFERED CHAR FLAG BSOUR *=*+1 ;CHAR BUFFER FOR IEEE SYNO *=*+1 ;CASSETTE SYNC # XSAV *=*+1 ;TEMP FOR BASIN LDTND *=*+1 ;INDEX TO LOGICAL FILE DFLTN *=*+1 ;DEFAULT INPUT DEVICE # DFLTO *=*+1 ;DEFAULT OUTPUT DEVICE # PRTY *=*+1 ;CASSETTE PARITY DPSW *=*+1 ;CASSETTE DIPOLE SWITCH MSGFLG *=*+1 ;OS MESSAGE FLAG PTR1 ;CASSETTE ERROR PASS1 T1 *=*+1 ;TEMPORARY 1 TMPC PTR2 ;CASSETTE ERROR PASS2 T2 *=*+1 ;TEMPORARY 2 TIME *=*+3 ;24 HOUR CLOCK IN 1/60TH SECONDS R2D2 ;SERIAL BUS USAGE PCNTR *=*+1 ;CASSETTE STUFF ; PTCH *=*+1 (UNUSED) BSOUR1 ;TEMP USED BY SERIAL ROUTINE FIRT *=*+1 COUNT ;TEMP USED BY SERIAL ROUTINE CNTDN *=*+1 ;CASSETTE SYNC COUNTDOWN BUFPT *=*+1 ;CASSETTE BUFFER POINTER INBIT ;RS-232 RCVR INPUT BIT STORAGE SHCNL *=*+1 ;CASSETTE SHORT COUNT BITCI ;RS-232 RCVR BIT COUNT IN RER *=*+1 ;CASSETTE READ ERROR RINONE ;RS-232 RCVR FLAG FOR START BIT CHECK REZ *=*+1 ;CASSETE READING ZEROES RIDATA ;RS-232 RCVR BYTE BUFFER RDFLG *=*+1 ;CASSETTE READ MODE RIPRTY ;RS-232 RCVR PARITY STORAGE SHCNH *=*+1 ;CASSETTE SHORT CNT SAL *=*+1 SAH *=*+1 EAL *=*+1 EAH *=*+1 CMP0 *=*+1 TEMP *=*+1 TAPE1 *=*+2 ;ADDRESS OF TAPE BUFFER #1Y. BITTS ;RS-232 TRNS BIT COUNT SNSW1 *=*+1 NXTBIT ;RS-232 TRNS NEXT BIT TO BE SENT DIFF *=*+1 RODATA ;RS-232 TRNS BYTE BUFFER PRP *=*+1 FNLEN *=*+1 ;LENGTH CURRENT FILE N STR LA *=*+1 ;CURRENT FILE LOGICAL ADDR SA *=*+1 ;CURRENT FILE 2ND ADDR FA *=*+1 ;CURRENT FILE PRIMARY ADDR FNADR *=*+2 ;ADDR CURRENT FILE NAME STR ROPRTY ;RS-232 TRNS PARITY BUFFER OCHAR *=*+1 FSBLK *=*+1 ;CASSETTE READ BLOCK COUNT MYCH *=*+1 CAS1 *=*+1 ;CASSETTE MANUAL/CONTROLLED SWITCH TMP0 STAL *=*+1 STAH *=*+1 MEMUSS ;CASSETTE LOAD TEMPS (2 BYTES) TMP2 *=*+2 ; ;VARIABLES FOR SCREEN EDITOR ; LSTX *=*+1 ;KEY SCAN INDEX ; SFST *=*+1 ;KEYBOARD SHIFT FLAG (UNUSED) NDX *=*+1 ;INDEX TO KEYBOARD Q RVS *=*+1 ;RVS FIELD ON FLAG INDX *=*+1 LSXP *=*+1 ;X POS AT START LSTP *=*+1 SFDX *=*+1 ;SHIFT MODE ON PRINT BLNSW *=*+1 ;CURSOR BLINK ENAB BLNCT *=*+1 ;COUNT TO TOGGLE CUR GDBLN *=*+1 ;CHAR BEFORE CURSOR BLNON *=*+1 ;ON/OFF BLINK FLAG CRSW *=*+1 ;INPUT VS GET FLAG PNT *=*+2 ;POINTER TO ROW ; POINT *=*+1 (UNUSED) PNTR *=*+1 ;POINTER TO COLUMN QTSW *=*+1 ;QUOTE SWITCH LNMX *=*+1 ;40/80 MAX POSITON TBLX *=*+1 DATA *=*+1 INSRT *=*+1 ;INSERT MODE FLAG LDTB1 *=*+26 ;LINE FLAGS+ENDSPACE USER *=*+2 ;SCREEN EDITOR COLOR IP KEYTAB *=*+2 ;KEYSCAN TABLE INDIRECT ;RS-232 Z-PAGE RIBUF *=*+2 ;RS-232 INPUT BUFFER POINTER ROBUF *=*+2 ;RS-232 OUTPUT BUFFER POINTER FREKZP *=*+4 ;FREE KERNAL ZERO PAGE 9/24/80 BASZPT *=*+1 ;LOCATION ($00FF) USED BY BASIC *=$100 BAD *=*+1 *=$200 BUF *=*+89 ;BASIC/MONITOR BUFFER ; TABLES FOR OPEN FILES ; LAT *=*+10 ;LOGICAL FILE NUMBERS FAT *=*+10 ;PRIMARY DEVICE NUMBERS SAT *=*+10 ;SECONDARY ADDRESSES ; SYSTEM STORAGE ; KEYD *=*+10 ;IRQ KEYBOARD BUFFER MEMSTR *=*+2 ;START OF MEMORY MEMSIZ *=*+2 ;TOP OF MEMORY TIMOUT *=*+1 ;IEEE TIMEOUT FLAG ; SCREEN EDITOR STORAGE ; COLOR *=*+1 ;ACTIV COLOR NYBBLE GDCOL *=*+1 ;ORIGINAL COLOR BEFORE CURSOR HIBASE *=*+1 ;BASE LOCATION OF SCREEN (TOP) XMAX *=*+1 RPTFLG *=*+1 ;KEY REPEAT FLAG KOUNT *=*+1 DELAY *=*+1 SHFLAG *=*+1 ;SHIFT FLAG BYTE LSTSHF *=*+1 ;LAST SHIFT PATTERN KEYLOG *=*+2 ;INDIRECT FOR KEYBOARD TABLE SETUP MODE *=*+1 ;0-PET MODE, 1-CATTACANNA AUTODN *=*+1 ;AUTO SCROLL DOWN FLAG(=0 ON,<>0 OFF) ; RS-232 STORAGE ; M51CTR *=*+1 ;6551 CONTROL REGISTER M51CDR *=*+1 ;6551 COMMAND REGISTER M51AJB *=*+2 ;NON STANDARD (BITTIME/2-100) RSSTAT *=*+1 ; RS-232 STATUS REGISTER BITNUM *=*+1 ;NUMBER OF BITS TO SEND (FAST RESPONSE) BAUDOF *=*+2 ;BAUD RATE FULL BIT TIME (CREATED BY OPEN) ; ; RECIEVER STORAGE ; ; INBIT *=*+1 ;INPUT BIT STORAGE ; BITCI *=*+1 ;BIT COUNT IN ; RINONE *=*+1 ;FLAG FOR START BIT CHECK ; RIDATA *=*+1 ;BYTE IN BUFFER ; RIPRTY *=*+1 ;BYTE IN PARITY STORAGE RIDBE *=*+1 ;INPUT BUFFER INDEX TO END RIDBS *=*+1 ;INPUT BUFFER POINTER TO START ; ; TRANSMITTER STORAGE ; ; BITTS *=*+1 ;# OF BITS TO BE SENT ; NXTBIT *=*+1 ;NEXT BIT TO BE SENT ; ROPRTY *=*+1 ;PARITY OF BYTE SENT ; RODATA *=*+1 ;BYTE BUFFER OUT RODBS *=*+1 ;OUTPUT BUFFER INDEX TO START RODBE *=*+1 ;OUTPUT BUFFER INDEX TO END ; IRQTMP *=*+2 ;HOLDS IRQ DURING TAPE OPS ; ; TEMP SPACE FOR VIC-40 VARIABLES **** ; ENABL *=*+1 ;RS-232 ENABLES (REPLACES IER) CASTON *=*+1 ;TOD SENSE DURING CASSETTES KIKA26 *=*+1 ;TEMP STORAGE FOR CASSETTE READ ROUTINE STUPID *=*+1 ;TEMP D1IRQ INDICATOR FOR CASSETTE READ LINTMP *=*+1 ;TEMPORARY FOR LINE INDEX *=$0300 ;REM PROGRAM INDIRECTS(10) *=$0300+20 ;REM KERNAL/OS INDIRECTS(20) CINV *=*+2 ;IRQ RAM VECTOR CBINV *=*+2 ;BRK INSTR RAM VECTOR NMINV *=*+2 ;NMI RAM VECTOR IOPEN *=*+2 ;INDIRECTS FOR CODE ICLOSE *=*+2 ; CONFORMS TO KERNAL SPEC 8/19/80 ICHKIN *=*+2 ICKOUT *=*+2 ICLRCH *=*+2 IBASIN *=*+2 IBSOUT *=*+2 ISTOP *=*+2 IGETIN *=*+2 ICLALL *=*+2 USRCMD *=*+2 ILOAD *=*+2 ISAVE *=*+2 ;SAVESP *=$0300+60 TBUFFR *=*+192 ;CASSETTE DATA BUFFER * =$400 VICSCN *=*+1024 RAMLOC ; I/O DEVICES ; * =$D000 VICREG =* ;VIC REGISTERS * =$D400 SIDREG =* ;SID REGISTERS * =$D800 VICCOL *=*+1024 ;VIC COLOR NYBBLES * =$DC00 ;DEVICE1 6526 (PAGE1 IRQ) COLM ;KEYBOARD MATRIX D1PRA *=*+1 ROWS ;KEYBOARD MATRIX D1PRB *=*+1 D1DDRA *=*+1 D1DDRB *=*+1 D1T1L *=*+1 D1T1H *=*+1 D1T2L *=*+1 D1T2H *=*+1 D1TOD1 *=*+1 D1TODS *=*+1 D1TODM *=*+1 D1TODH *=*+1 D1SDR *=*+1 D1ICR *=*+1 D1CRA *=*+1 D1CRB *=*+1 * =$DD00 ;DEVICE2 6526 (PAGE2 NMI) D2PRA *=*+1 D2PRB *=*+1 D2DDRA *=*+1 D2DDRB *=*+1 D2T1L *=*+1 D2T1H *=*+1 D2T2L *=*+1 D2T2H *=*+1 D2TOD1 *=*+1 D2TODS *=*+1 D2TODM *=*+1 D2TODH *=*+1 D2SDR *=*+1 D2ICR *=*+1 D2CRA *=*+1 D2CRB *=*+1 TIMRB =$19 ;6526 CRB ENABLE ONE-SHOT TB ;TAPE BLOCK TYPES ; EOT =5 ;END OF TAPE BLF =1 ;BASIC LOAD FILE BDF =2 ;BASIC DATA FILE PLF =3 ;FIXED PROGRAM TYPE BDFH =4 ;BASIC DATA FILE HEADER BUFSZ =192 ;BUFFER SIZE ; ;SCREEN EDITOR CONSTANTS ; LLEN =40 ;SINGLE LINE 40 COLUMNS LLEN2 =80 ;DOUBLE LINE = 80 COLUMNS NLINES =25 ;25 ROWS ON SCREEN WHITE =$01 ;WHITE SCREEN COLOR BLUE =$06 ;BLUE CHAR COLOR CR =$D ;CARRIAGE RETURN .END *=$E500 ;START OF VIC-40 KERNAL .LIB EDITOR.1MAXCHR=80NWRAP=2 ;MAX NUMBER OF PHYSICAL LINES PER LOGICAL LINE ; ;UNDEFINED FUNCTION ENTRY ; ; UNDEFD LDX #0 ; UNDEF2 LDA UNMSG,X ; JSR PRT ; INX ; CPX #UNMSG2-UNMSG ; BNE UNDEF2 ; SEC ; RTS ; ; UNMSG .BYT $D,'?ADVANCED FUNCTION NOT AVAILABLE',$D ; UNMSG2 ; ;RETURN ADDRESS OF 6526 ; |
RücksprungBetriebssystemSystem-Meldungen |
BASIC startup messages |
returnWORDS: POWER UP MESSAGEThis is the power up message displayed on the screen whenthe 'Commie' is switched on or reset. The strings are seperated by a zero byte. |
startup messages |
|
.:E45F 00 20 42 41 53 49 43 20 |
basic bytes free |
basic bytes free |
basic bytes free |
basic bytes free |
||
.:E467 42 59 54 45 53 20 46 52 | ||||||
.:E46F 45 45 0D 00 93 0D 20 20 | ||||||
.:E473 93 0D 20 20 20 20 2A 2A |
(clr) **** commodore 64 basic v2 **** |
(clr) **** commodore 64 basic v2 **** |
(clr) **** commodore 64 basic v2 **** |
(clr) **** commodore 64 basic v2 **** |
||
.:E47B 2A 2A 20 43 4F 4D 4D 4F |
(cr) (cr) 64k ram system |
(cr) (cr) 64k ram system |
(cr) (cr) 64k ram system |
(cr) (cr) 64k ram system |
||
.:E483 44 4F 52 45 20 36 34 20 | ||||||
.:E48B 42 41 53 49 43 20 56 32 | ||||||
.:E493 20 2A 2A 2A 2A 0D 0D 20 | ||||||
.:E49B 36 34 4B 20 52 41 4D 20 | ||||||
.:E4A3 53 59 53 54 45 4D 20 20 | ||||||
.:E4AB 00 |
unused |
|||||
.:E4AC 5C |
BASIC-CKOUT Routine |
open channel for output |
PATCH FOR BASIC CHKOUT CALLThis is a short patch added for the KERNAL ROM to preserv(A) when there was no error returned from BASIC calling the CHKOUT routine. This corrects a bug in the early versions of PRINT# and CMD. |
set output device |
||
.,E4AD 48 PHA |
Akkuinhalt in Stack |
save the flag byte |
temp store (A) |
|||
.,E4AE 20 C9 FF JSR $FFC9 |
CKOUT Ausgabegerät setzen |
open channel for output |
CHKOUT |
|||
.,E4B1 AA TAX |
Fehlernummer nach X |
copy the returned flag byte |
||||
.,E4B2 68 PLA |
Akkuinhalt zurückholen |
restore the alling flag byte |
retrieve (A) |
|||
.,E4B3 90 01 BCC $E4B6 |
kein Fehler ? |
if there is no error skip copying the error flag |
||||
.,E4B5 8A TXA |
Fehlernummer wieder in Akku |
else copy the error flag |
||||
.,E4B6 60 RTS |
Rücksprung |
unused bytes |
unused |
|||
.:E4B7 AA AA AA AA AA AA AA AA | ||||||
.:E4BF AA AA AA AA AA AA AA AA | ||||||
.:E4C7 AA AA AA AA AA AA AA AA | ||||||
.:E4CF AA AA AA AA AA AA AA AA |
flag the RS232 start bit and set the parity |
RS232 PATCHThis patch has been added to the RS232 input routine inKERNAL v.3. It initialises the RS232 parity byte, RIPRTY, on reception of a start bit. |
||||
.:E4D7 AA AA AA |
Hintergrundfarbe setzen |
save the start bit check flag, set start bit received set the initial parity state save the receiver parity bit |
RINONE, check for start bit RIPRTY, RS232 input parity |
|||
.,E4DA AD 21 D0 LDA $D021 |
Farbe holen |
save the current colour to the colour RAMget the current colour code |
RESET CHARACTER COLOURThis routine is a patch in KERNAL version 3 to fix a bugwith the colour code. The routine is called by 'clear a screen line', and sets the character colour to COLOR. get COLOR |
clear byte in color ram |
||
.,E4DD 91 F3 STA ($F3),Y |
ins Farbram schreiben |
save it to the colour RAM |
and store in current screen position |
|||
.,E4DF 60 RTS |
Rücksprungwartet auf Commodore-Taste |
wait ~8.5 seconds for any key from the STOP key column |
PAUSE AFTER FINDING TAPE FILEThis routine continues tape loading without pressing C=when a file was found. |
pause after finding a file on casette |
||
.,E4E0 69 02 ADC #$02 |
2*256/60 = 8.5 Sekunden warten |
set the number of jiffies to wait |
||||
.,E4E2 A4 91 LDY $91 |
Flag testen |
read the stop key column |
||||
.,E4E4 C8 INY |
und erhöhen |
test for $FF, no keys pressed |
||||
.,E4E5 D0 04 BNE $E4EB |
Taste gedrückt ? |
if any keys were pressed just exit |
||||
.,E4E7 C5 A1 CMP $A1 |
Zeit noch nicht um ?, |
compare the wait time with the jiffy clock mid byte |
||||
.,E4E9 D0 F7 BNE $E4E2 |
dann warten |
if not there yet go wait some more |
||||
.,E4EB 60 RTS |
RücksprungTimerkonstanten für RS 232Baud Rate, PAL-Version |
baud rate tables for PAL C64baud rate word is calculated from ..(system clock / baud rate) / 2 - 100 system clock ------------ PAL 985248 Hz NTSC 1022727 Hz |
RS232 TIMING TABLE - PALTimingtable for RS232 NMI for use with PAL machines. Thistable contains the prescaler values for setting up the RS232 baudrates. The table containe 10 entries which corresponds to one of the fixed RS232 rates, starting with lowest (50 baud) and finishing with the highest (2400 baud). Since the clock frequency is different between NTSC and PAL systems, there is another table for NTSC machines at $fec2. |
baud rate factor table |
||
.:E4EC 19 26 |
$2619 = 9753 50 Baud |
50 baud 985300 |
50 baud |
50 |
||
.:E4EE 44 19 |
$1944 = 6468 75 Baud |
75 baud 985200 |
75 baud |
75 |
||
.:E4F0 1A 11 |
$111A = 4378 110 Baud |
110 baud 985160 |
110 baud |
110 |
||
.:E4F2 E8 0D |
$0DE8 = 3560 134.5 Baud |
134.5 baud 984540 |
134.5 baud |
134.5 |
||
.:E4F4 70 0C |
$0C70 = 3184 150 Baud |
150 baud 985200 |
150 baud |
150 |
||
.:E4F6 06 06 |
$0606 = 1542 300 Baud |
300 baud 985200 |
300 baud |
300 |
||
.:E4F8 D1 02 |
$02D1 = 736 600 Baud |
600 baud 985200 |
600 baud |
600 |
||
.:E4FA 37 01 |
$0137 = 311 1200 Baud |
1200 baud 986400 |
1200 baud |
1200 |
||
.:E4FC AE 00 |
$00AE = 174 1800 Baud |
1800 baud 986400 |
(1800) 2400 baud |
1800 |
||
.:E4FE 69 00 |
$0069 = 105 2400 BaudBasis-Adresse des CIAs holen |
2400 baud 984000return the base address of the I/O devices |
2400 baudIOBASE: GET I/O ADDRESSThe KERNAL routine IOBASE ($fff3) jumps to this routine.It returns the base address $dc00 in (X/Y) |
2400read base address of I/O device into XY |
||
.,E500 A2 00 LDX #$00 |
IOBASE LDX #<D1PRA |
Adresse |
get the I/O base address low byte |
set (X/Y) to $dc00 |
low DC00 |
|
.,E502 A0 DC LDY #$DC |
LDY #>D1PRA |
$DC00 |
get the I/O base address high byte |
high DC00 |
||
.,E504 60 RTS |
RTS ; ;RETURN MAX ROWS,COLS OF SCREEN ; |
Rücksprungholt Anzahl der Zeilen undSpalten |
return the x,y organization of the screen |
SCREEN: GET SCREEN SIZEThe KERNAL routine SCREEN ($ffed) jumps to this routine.It returns the screen size; columns in (X) and rows in (Y). |
read screen size |
|
.,E505 A2 28 LDX #$28 |
SCRORG LDX #LLEN |
40 Spalten |
get the x size |
40 columns |
40 columns |
|
.,E507 A0 19 LDY #$19 |
LDY #NLINES |
25 Zeilen |
get the y size |
25 rows |
25 rows |
|
.,E509 60 RTS |
RTS ; ;READ/PLOT CURSOR POSITION ; |
RücksprungCursor setzen (C=0) / holen(C=1) |
read/set the x,y cursor position |
PLOT: PUT/GET ROW AND COLUMNThe KERNAL routine PLOT ($fff0) jumps to this routine. Theoption taken depends on the state of carry on entry. If it is set, the column is placed in (Y) and the row placed in (X). If carry is clear, the cursor position is read from (X/Y) and the screen pointers are set. |
read/set XY cursor position |
|
.,E50A B0 07 BCS $E513 |
PLOT BCS PLOT10 |
Carry gesetzt, dann zu $E513 |
if read cursor go do read |
if carry set, jump |
||
.,E50C 86 D6 STX $D6 |
STX TBLX |
Zeile |
save the cursor row |
store TBLX, current row |
||
.,E50E 84 D3 STY $D3 |
STY PNTR |
Spalte |
save the cursor column |
store PNTR, current column |
||
.,E510 20 6C E5 JSR $E56C |
JSR STUPT |
Cursor setzen |
set the screen pointers for the cursor row, column |
set screen pointers |
||
.,E513 A6 D6 LDX $D6 |
PLOT10 LDX TBLX |
Zeile |
get the cursor row |
read TBLX |
||
.,E515 A4 D3 LDY $D3 |
LDY PNTR |
Spalte |
get the cursor column |
read PNTR |
||
.,E517 60 RTS |
RTS ;INITIALIZE I/O ; CINT ; ; ESTABLISH SCREEN MEMORY ; |
RücksprungBildschirm Reset |
initialise the screen and keyboard |
CINT1: INITIALISE I/OThis routine is part of the KERNAL CINT init routine. I/Odefault values are set, <shift+cbm> keys are disabled, and cursor is switched off. The vector to the keyboard table is set up, and the length of the keyboardbuffer is set to 10 characters. The cursor color is set to lightblue, and the key-repeat parameters are set up. |
initialise screen and keyboard |
|
.,E518 20 A0 E5 JSR $E5A0 |
JSR PANIC ;SET UP VIC ; |
Videocontroller initialisieren |
initialise the vic chip |
set I/O defaults |
||
.,E51B A9 00 LDA #$00 |
LDA #0 ;MAKE SURE WE'RE IN PET MODE |
Shift- |
clear A |
|||
.,E51D 8D 91 02 STA $0291 |
STA MODE |
Commodore ermöglichen |
clear the shift mode switch |
disable <SHIFT + CBM> by writing zero into MODE |
||
.,E520 85 CF STA $CF |
STA BLNON ;WE DONT HAVE A GOOD CHAR FROM THE SCREEN YET |
Cursor nicht in Blinkphase |
clear the cursor blink phase |
the cursor blink flag, set BLNON on |
||
.,E522 A9 48 LDA #$48 |
LDA #<SHFLOG ;SET SHIFT LOGIC INDIRECTS |
Adresse |
get the keyboard decode logic pointer low byte |
low EB48 |
||
.,E524 8D 8F 02 STA $028F |
STA KEYLOG |
($028F) = $EB48 |
save the keyboard decode logic pointer low byte |
|||
.,E527 A9 EB LDA #$EB |
LDA #>SHFLOG |
setzen |
get the keyboard decode logic pointer high byte |
set the KEYLOG vector to point at $eb48 |
high EB48 |
|
.,E529 8D 90 02 STA $0290 |
STA KEYLOG+1 |
= Zeiger auf Adressen für Tastaturdekodierung |
save the keyboard decode logic pointer high byte |
|||
.,E52C A9 0A LDA #$0A |
LDA #10 |
10 |
set the maximum size of the keyboard buffer |
set max number of character is keyboard buffer to 10 |
||
.,E52E 8D 89 02 STA $0289 |
STA XMAX ;MAXIMUM TYPE AHEAD BUFFER SIZE |
max. Länge des Tastaturpuffers |
save the maximum size of the keyboard buffer |
XMAX |
||
.,E531 8D 8C 02 STA $028C |
STA DELAY |
Zähler für Repeat-Geschwindigkeit |
save the repeat delay counter |
How many 1/60 of a second to wait before key is repeated. Used togeather with $028b |
||
.,E534 A9 0E LDA #$0E |
LDA #$E ;INIT COLOR TO LIGHT BLUE<<<<<<<<<< |
hellblau |
set light blue |
set character colour to light blue |
||
.,E536 8D 86 02 STA $0286 |
STA COLOR |
Augenblickliche Farbe |
save the current colour code |
COLOR |
||
.,E539 A9 04 LDA #$04 |
LDA #4 |
Repeat- |
speed 4 |
How many $028c before a new entry is |
||
.,E53B 8D 8B 02 STA $028B |
STA KOUNT ;DELAY BETWEEN KEY REPEATS |
Geschwindigkeit |
save the repeat speed counter |
put in the keyboard buffer, KOUNT |
||
.,E53E A9 0C LDA #$0C |
LDA #$C |
Cursor |
set the cursor flash timing |
|||
.,E540 85 CD STA $CD |
STA BLNCT |
Blinkzeit |
save the cursor timing countdown |
store in BLCNT, cursor toggle timer |
||
.,E542 85 CC STA $CC |
STA BLNSW |
Cursor BlinkflagBildschirm löschen |
save the cursor enable, $00 = flash cursorclear the screen |
store in BLNSW, cursor enableCLEAR SCREENThis routine sets up the screen line link table ($d9 -$f2), LDTB1, which is used to point out the address to the screen. The later part of the routine performs the screen clear, line by line, starting at the bottom line. It continues to the next routine which is used to home the cursor. |
||
.,E544 AD 88 02 LDA $0288 |
CLSR LDA HIBASE ;FILL HI BYTE PTR TABLE |
Speicherseite für Bildschirm-RAM |
get the screen memory page |
get HIBASE, top of screen memory |
||
.,E547 09 80 ORA #$80 |
ORA #$80 |
Adressen |
set the high bit, flag every line is a logical line start |
fool around |
||
.,E549 A8 TAY |
TAY |
der |
copy to Y |
|||
.,E54A A9 00 LDA #$00 |
LDA #0 |
Bild- |
clear the line start low byte |
|||
.,E54C AA TAX |
TAX |
schirm- |
clear the index |
|||
.,E54D 94 D9 STY $D9,X |
LPS1 STY LDTB1,X |
zeilen |
save the start of line X pointer high byte |
store in screen line link table, LDTB1 |
||
.,E54F 18 CLC |
CLC |
40 addieren |
clear carry for add |
|||
.,E550 69 28 ADC #$28 |
ADC #LLEN |
(eine Zeile) |
add the line length to the low byte |
add #40 to next line |
||
.,E552 90 01 BCC $E555 |
BCC LPS2 |
kein Übertrag, dann HIGH-Byte nicht erhöhen |
if no rollover skip the high byte increment |
|||
.,E554 C8 INY |
INY ;CARRY BUMP HI BYTE |
HIGH-Byte erhöhen |
else increment the high byte |
inc page number |
||
.,E555 E8 INX |
LPS2 INX |
LOW-Byte erhöhen |
increment the line index |
next |
||
.,E556 E0 1A CPX #$1A |
CPX #NLINES+1 ;DONE # OF LINES? |
26, alle Zeilen ? |
compare it with the number of lines + 1 |
till all 26?? is done |
||
.,E558 D0 F3 BNE $E54D |
BNE LPS1 ;NO... |
nein, dann weiter |
loop if not all done |
|||
.,E55A A9 FF LDA #$FF |
LDA #$FF ;TAG END OF LINE TABLE |
Kennzeichnung der |
set the end of table marker |
|||
.,E55C 95 D9 STA $D9,X |
STA LDTB1,X |
26, Zeile |
mark the end of the table |
last pointer is $ff |
||
.,E55E A2 18 LDX #$18 |
LDX #NLINES-1 ;CLEAR FROM THE BOTTOM LINE UP |
24, Anzahl der Zeilen minus 1 |
set the line count, 25 lines to do, 0 to 24 |
start clear screen with line $18 (bottom line) |
||
.,E560 20 FF E9 JSR $E9FF |
CLEAR1 JSR CLRLN ;SEE SCROLL ROUTINES |
Bildschirmzeile löschen |
clear screen line X |
erase line (X) |
||
.,E563 CA DEX |
DEX |
Zähler erniedrigen |
decrement the count |
next |
||
.,E564 10 FA BPL $E560 |
BPL CLEAR1 ;HOME FUNCTION ; |
schon alle?Cursor Home |
loop if more to dohome the cursor |
till screen is emptyHOME CURSORThis routine puts the cursor in the top left corner bywriting its column and line to zero. |
||
.,E566 A0 00 LDY #$00 |
NXTD LDY #0 |
Löschen der |
clear Y |
|||
.,E568 84 D3 STY $D3 |
STY PNTR ;LEFT COLUMN |
Cursorspalte und |
clear the cursor column |
write to PNTR, cursor column |
||
.,E56A 84 D6 STY $D6 |
STY TBLX ;TOP LINE ; ;MOVE CURSOR TO TBLX,PNTR ; STUPT |
CursorzeileCursorpos. berechnen,Bildschirmzeiger setzen |
clear the cursor rowset screen pointers for cursor row, column |
write to TBLX, line numberSET SCREEN POINTERSThis routine positions the cursor on the screen and setsup the screen pointers. On entry, TBLX must hold the line number, and PNTR the column number of the cursor position. |
set address of curent screen line |
|
.,E56C A6 D6 LDX $D6 |
LDX TBLX ;GET CURENT LINE INDEX |
Cursorzeile |
get the cursor row |
read TBLX |
||
.,E56E A5 D3 LDA $D3 |
LDA PNTR ;GET CHARACTER POINTER |
Cursorspalte |
get the cursor column |
read PNTR |
||
.,E570 B4 D9 LDY $D9,X |
FNDSTR LDY LDTB1,X ;FIND BEGINING OF LINE |
HIGH-Bytes für Doppelzeilen |
get start of line X pointer high byte |
read value from screen line link table, LDTB1 |
||
.,E572 30 08 BMI $E57C |
BMI STOK ;BRANCH IF START FOUND |
einfache Zeile, dann zu $E57C |
if it is the logical line start continue |
heavy calcuations??? jump when ready |
||
.,E574 18 CLC |
CLC |
Spalte |
else clear carry for add |
|||
.,E575 69 28 ADC #$28 |
ADC #LLEN ;ADJUST POINTER |
+40 |
add one line length |
|||
.,E577 85 D3 STA $D3 |
STA PNTR |
und speichern |
save the cursor column |
PNTR |
||
.,E579 CA DEX |
DEX |
nächste Zeile |
decrement the cursor row |
|||
.,E57A 10 F4 BPL $E570 |
BPL FNDSTR ; |
schon alle? |
loop, branch always |
|||
.,E57C 20 F0 E9 JSR $E9F0 |
STOK JSR SETPNT ;SET UP PNT INDIRECT 901227-03********** ; |
Zeiger auf Video-RAM setzen |
fetch a screen address |
set start of line (X) |
||
.,E57F A9 27 LDA #$27 |
LDA #LLEN-1 |
39 Spalten |
set the line length |
|||
.,E581 E8 INX |
INX |
Zeiger auf Bildschirmtabelle erhöhen |
increment the cursor row |
|||
.,E582 B4 D9 LDY $D9,X |
FNDEND LDY LDTB1,X |
HIGH-Byte Startadresse der Zeile in Y-REG schreiben |
get the start of line X pointer high byte |
LDTB1 |
||
.,E584 30 06 BMI $E58C |
BMI STDONE |
Verzweige falls größer, gleich 128 |
if logical line start exit |
|||
.,E586 18 CLC |
CLC |
Cursor eine Zeile |
else clear carry for add |
|||
.,E587 69 28 ADC #$28 |
ADC #LLEN |
tiefer setzen (+40 Spalten) |
add one line length to the current line length |
|||
.,E589 E8 INX |
INX |
Zeiger auf Bildschirmtabelle erhöhen |
increment the cursor row |
|||
.,E58A 10 F6 BPL $E582 |
BPL FNDEND STDONE |
unbedingter Sprung |
loop, branch always |
|||
.,E58C 85 D5 STA $D5 |
STA LNMX |
Zeilenlänge speichern |
save current screen line length |
store in LMNX, physical screen line length |
||
.,E58E 4C 24 EA JMP $EA24 |
JMP SCOLOR ;MAKE COLOR POINTER FOLLOW 901227-03********** ; THIS IS A PATCH FOR INPUT LOGIC 901227-03********** ; FIXES INPUT"XXXXXXX-40-XXXXX";A$ PROBLEM ; |
Zeiger auf Farb-RAM berechnen Rücksprung |
calculate the pointer to colour RAM and return |
sync color pointer |
||
.,E591 E4 C9 CPX $C9 |
FINPUT CPX LSXP ;CHECK IF ON SAME LINE |
wenn Cursorzeile |
compare it with the input cursor row |
read LXSP, chech cursor at start of input |
||
.,E593 F0 03 BEQ $E598 |
BEQ FINPUX ;YES..RETURN TO SEND |
gleich null, dann Rücksprung |
if there just exit |
|||
.,E595 4C ED E6 JMP $E6ED |
JMP FINDST ;CHECK IF WE WRAPPED DOWN... |
Adresse für zugehörige Zeilennummer nach $D1/$D2 |
else go ?? |
retreat cursor |
||
.,E598 60 RTS |
FINPUX RTS |
Rücksprung |
orphan bytes ?? |
|||
.,E599 EA NOP |
NOP ;KEEP THE SPACE THE SAME... ;PANIC NMI ENTRY ; |
no operation |
huh |
A free byte!!!SET I/O DEFAULTSThe default output device is set to 3 (screen), and thedefault input device is set to 0 (keyboard). The VIC chip registers are set from the video chip setup table. The cursor is then set to the home position. |
this code is unused by kernelsince no other part of therom jumps to this location! |
|
.,E59A 20 A0 E5 JSR $E5A0 |
VPAN JSR PANIC ;FIX VIC SCREEN |
Videocontroller initialisieren |
initialise the vic chip |
set I/O defaults |
||
.,E59D 4C 66 E5 JMP $E566 |
JMP NXTD ;HOME CURSOR |
Cursor HomeVideocontrollerinitialisieren |
home the cursor and returninitialise the vic chip |
home cursor and exit routine |
initialise vic chip |
|
.,E5A0 A9 03 LDA #$03 |
PANIC LDA #3 ;RESET DEFAULT I/O |
Ausgabe auf |
set the screen as the output device |
|||
.,E5A2 85 9A STA $9A |
STA DFLTO |
Bildschirm |
save the output device number |
DFLTO, default output device - screen |
||
.,E5A4 A9 00 LDA #$00 |
LDA #0 |
Eingabe von |
set the keyboard as the input device |
|||
.,E5A6 85 99 STA $99 |
STA DFLTN ;INIT VIC ; |
Tastatur |
save the input device number |
DFLTN, default input device - keyboard |
||
.,E5A8 A2 2F LDX #$2F |
INITV LDX #47 ;LOAD ALL VIC REGS *** |
47 |
set the count/index |
|||
.,E5AA BD B8 EC LDA $ECB8,X |
PX4 LDA TVIC-1,X |
Konstanten |
get a vic ii chip initialisation value |
VIC chip setup table |
||
.,E5AD 9D FF CF STA $CFFF,X |
STA VICREG-1,X |
in Videokontroller schreiben |
save it to the vic ii chip |
VIC chip I/O registers |
||
.,E5B0 CA DEX |
DEX |
Zähler erniedrigen |
decrement the count/index |
next |
||
.,E5B1 D0 F7 BNE $E5AA |
BNE PX4 |
schon alle? |
loop if more to do |
till ready |
||
.,E5B3 60 RTS |
RTS ; ;REMOVE CHARACTER FROM QUEUE ; |
RücksprungZeichen aus Tastaturpufferholen |
input from the keyboard buffer |
LP2: GET CHARACTER FROM KEYBOARD BUFFERIt is assumed that there is at leaset one character in thekeyboard buffer. This character is obtained and the rest of the queue is moved up one by one to overwrite it. On exit, the character is in (A). |
get character from keyboard buffer |
|
.,E5B4 AC 77 02 LDY $0277 |
LP2 LDY KEYD |
erstes Zeichen holen |
get the current character from the buffer |
read KEYD, first character in keyboard buffer queue |
||
.,E5B7 A2 00 LDX #$00 |
LDX #0 |
Zähler auf Null |
clear the index |
|||
.,E5B9 BD 78 02 LDA $0278,X |
LP1 LDA KEYD+1,X |
Puffer nach |
get the next character,X from the buffer |
overwrite with next in queue |
||
.,E5BC 9D 77 02 STA $0277,X |
STA KEYD,X |
vorne aufrücken |
save it as the current character,X in the buffer |
|||
.,E5BF E8 INX |
INX |
Zähler erhöhen |
increment the index |
|||
.,E5C0 E4 C6 CPX $C6 |
CPX NDX |
mit Anzahl der |
compare it with the keyboard buffer index |
compare with NDX, number of characters in queue |
||
.,E5C2 D0 F5 BNE $E5B9 |
BNE LP1 |
Zeichen vergleichen |
loop if more to do |
till all characters are moved |
||
.,E5C4 C6 C6 DEC $C6 |
DEC NDX |
Zeichenzahl erniedrigen |
decrement keyboard buffer index |
decrement NDX |
||
.,E5C6 98 TYA |
TYA |
Zeichen in Akku holen |
copy the key to A |
transfer read character to (A) |
||
.,E5C7 58 CLI |
CLI |
Interrupt freigeben |
enable the interrupts |
enable interrupt |
||
.,E5C8 18 CLC |
CLC ;GOOD RETURN |
Carry löschen |
flag got byte |
|||
.,E5C9 60 RTS |
RTS ; |
RücksprungWarteschleife fürTastatureingabe |
write character and wait for key |
INPUT FROM KEYBOARDThis routine uses the previous routine to get charactersfrom the keyboard buffer. Each character is output to the screen, unless it is <shift/RUN>. If so, the contents of the keyboard buffer is replaced with LOAD <CR> RUN <CR>. The routine ends when a carriage routine is encountered. |
wait for return for keyboard |
|
.,E5CA 20 16 E7 JSR $E716 |
LOOP4 JSR PRT LOOP3 |
Zeichen auf Bildschirm ausgeben |
output characterwait for a key from the keyboard |
output to screen |
||
.,E5CD A5 C6 LDA $C6 |
LDA NDX |
Anzahl der |
get the keyboard buffer index |
read NDX, number of characters in keyboard queue |
||
.,E5CF 85 CC STA $CC |
STA BLNSW |
gedrückten |
cursor enable, $00 = flash cursor, $xx = no flash |
BLNSW, cursor blink enable |
||
.,E5D1 8D 92 02 STA $0292 |
STA AUTODN ;TURN ON AUTO SCROLL DOWN |
Tasten |
screen scrolling flag, $00 = scroll, $xx = no scroll this disables both the cursor flash and the screen scroll while there are characters in the keyboard buffer |
AUTODN, auto scroll down flag |
||
.,E5D4 F0 F7 BEQ $E5CD |
BEQ LOOP3 |
keine Taste gedrückt ?, dann warten |
loop if the buffer is empty |
loop till key is pressed |
||
.,E5D6 78 SEI |
SEI |
Interrupt verhindern |
disable the interrupts |
disable interrupt |
||
.,E5D7 A5 CF LDA $CF |
LDA BLNON |
Cursor in Blink-Phase ? |
get the cursor blink phase |
BLNON, last cursor blink (on/off) |
||
.,E5D9 F0 0C BEQ $E5E7 |
BEQ LP21 |
nein |
if cursor phase skip the overwrite else it is the character phase |
|||
.,E5DB A5 CE LDA $CE |
LDA GDBLN |
Zeichen unter dem Cursor |
get the character under the cursor |
GDBLN, character under cursor |
||
.,E5DD AE 87 02 LDX $0287 |
LDX GDCOL ;RESTORE ORIGINAL COLOR |
Farbe unter dem Cursor |
get the colour under the cursor |
GDCOL, background color under cursor |
||
.,E5E0 A0 00 LDY #$00 |
LDY #0 |
Cursor nicht |
clear Y |
|||
.,E5E2 84 CF STY $CF |
STY BLNON |
in Blinkphase |
clear the cursor blink phase |
clear BLNON |
||
.,E5E4 20 13 EA JSR $EA13 |
JSR DSPP |
Zeichen und Farbe setzen |
print character A and colour X |
print to screen |
||
.,E5E7 20 B4 E5 JSR $E5B4 |
LP21 JSR LP2 |
Zeichen aus Tastaturpuffer holen |
input from the keyboard buffer |
Get character from keyboard buffer |
||
.,E5EA C9 83 CMP #$83 |
CMP #$83 ;RUN KEY? |
Kode für |
compare with [SHIFT][RUN] |
test if <shift/RUN> is pressed |
||
.,E5EC D0 10 BNE $E5FE |
BNE LP22 |
'SHIFT RUN' ? |
if not [SHIFT][RUN] skip the buffer fill keys are [SHIFT][RUN] so put "LOAD",$0D,"RUN",$0D into the buffer |
nope |
||
.,E5EE A2 09 LDX #$09 |
LDX #9 |
9 Zeichen |
set the byte count |
transfer 'LOAD <CR> RUN <CR>' to keyboard buffer |
||
.,E5F0 78 SEI |
SEI |
Interrupt verhindern |
disable the interrupts |
|||
.,E5F1 86 C6 STX $C6 |
STX NDX |
Zeichenzahl merken |
set the keyboard buffer index |
store #9 in NDX, characters in buffer |
||
.,E5F3 BD E6 EC LDA $ECE6,X |
LP23 LDA RUNTB-1,X |
'LOAD (cr) RUN (cr)' |
get byte from the auto load/run table |
'LOAD <CR> RUN <CR>' message in ROM |
||
.,E5F6 9D 76 02 STA $0276,X |
STA KEYD-1,X |
in Tastaturpuffer holen |
save it to the keyboard buffer |
store in keyboard buffer |
||
.,E5F9 CA DEX |
DEX |
nächstes Zeichen |
decrement the count/index |
|||
.,E5FA D0 F7 BNE $E5F3 |
BNE LP23 |
schon alle ? |
loop while more to do |
all nine characters |
||
.,E5FC F0 CF BEQ $E5CD |
BEQ LOOP3 |
und auswerten |
loop for the next key, branch always was not [SHIFT][RUN] |
allways jump |
||
.,E5FE C9 0D CMP #$0D |
LP22 CMP #$D |
'CR' |
compare the key with [CR] |
carriage return pressed? |
||
.,E600 D0 C8 BNE $E5CA |
BNE LOOP4 |
nein ?, dann zurück zur Warteschleife |
if not [CR] print the character and get the next key else it was [CR] |
nope, go to start |
||
.,E602 A4 D5 LDY $D5 |
LDY LNMX |
Länge der Bildschirmzeile |
get the current screen line length |
get LNMX, screen line length |
||
.,E604 84 D0 STY $D0 |
STY CRSW |
CR-Flag setzen |
input from keyboard or screen, $xx = screen, $00 = keyboard |
CRSV, flag input/get from keyboard |
||
.,E606 B1 D1 LDA ($D1),Y |
CLP5 LDA (PNT)Y |
Zeichen vom Bildschirm holen |
get the character from the current screen line |
PNT, screen address |
||
.,E608 C9 20 CMP #$20 |
CMP #' |
Leerzeichen |
compare it with [SPACE] |
space? |
||
.,E60A D0 03 BNE $E60F |
BNE CLP6 |
am Ende |
if not [SPACE] continue |
nope |
||
.,E60C 88 DEY |
DEY |
der |
else eliminate the space, decrement end of input line |
|||
.,E60D D0 F7 BNE $E606 |
BNE CLP5 |
Zeile |
loop, branch always |
next |
||
.,E60F C8 INY |
CLP6 INY |
eliminieren |
increment past the last non space character on line |
|||
.,E610 84 C8 STY $C8 |
STY INDX |
Position als Index merken |
save the input [EOL] pointer |
store in INDX, end of logical line for input |
||
.,E612 A0 00 LDY #$00 |
LDY #0 |
Cursorspalte |
clear A |
|||
.,E614 8C 92 02 STY $0292 |
STY AUTODN ;TURN OFF AUTO SCROLL DOWN |
gleich Null |
clear the screen scrolling flag, $00 = scroll |
AUTODN |
||
.,E617 84 D3 STY $D3 |
STY PNTR |
Cursorposition auf Null |
clear the cursor column |
PNTR, cursor column |
||
.,E619 84 D4 STY $D4 |
STY QTSW |
Hochkommaflag löschen |
clear the cursor quote flag, $xx = quote, $00 = no quote |
QTSW, reset quoute mode |
||
.,E61B A5 C9 LDA $C9 |
LDA LSXP |
wenn Cursorzeile schon durch |
get the input cursor row |
LXSP, corsor X/Y position |
||
.,E61D 30 1B BMI $E63A |
BMI LOP5 |
scrollen verschwunden, dann zu $E63A |
||||
.,E61F A6 D6 LDX $D6 |
LDX TBLX |
Cursorzeile |
get the cursor row |
TBLX, cursor line number |
||
.,E621 20 ED E6 JSR $E6ED |
JSR FINDST ;FIND 1ST PHYSICAL LINE |
Adresse für Startzeile setzen |
find and set the pointers for the start of logical line |
retreat cursor |
||
.,E624 E4 C9 CPX $C9 |
CPX LSXP |
Fehler bei Eingabe ?, |
compare with input cursor row |
LXSP |
||
.,E626 D0 12 BNE $E63A |
BNE LOP5 |
dann nochmal lesen |
||||
.,E628 A5 CA LDA $CA |
LDA LSTP |
letzte Spalte |
get the input cursor column |
|||
.,E62A 85 D3 STA $D3 |
STA PNTR |
in Spaltenzeiger bringen |
save the cursor column |
PNTR |
||
.,E62C C5 C8 CMP $C8 |
CMP INDX |
mit Index vergleichen |
compare the cursor column with input [EOL] pointer |
INDX |
||
.,E62E 90 0A BCC $E63A |
BCC LOP5 |
wenn kleiner, dann Zeile auswerten |
if less, cursor is in line, go ?? |
|||
.,E630 B0 2B BCS $E65D |
BCS CLP2 ;INPUT A LINE UNTIL CARRIAGE RETURN ; |
wenn größer oder gleich, dann keine Eingabe Ein Zeichen vom Bildschirmholen |
else the cursor is beyond the line end, branch alwaysinput from screen or keyboard |
INPUT FROM SCREEN OR KEYBOARDThis routine is used by INPUT to input data from devicesnot on the serial bus, ie. from screen or keyboard. On entry (X) and (Y) registers are preserved. A test is made to determine which device the input is to be from. If it is the screen, then quotes and <RVS> are tested for and the character is echoed on the screen. Keyboard inputs make use of the previous routine. |
get character from device 0 or 3 |
|
.,E632 98 TYA |
LOOP5 TYA |
die |
copy Y |
preserve (X) and (Y) registers |
||
.,E633 48 PHA |
PHA |
Re- |
save Y |
|||
.,E634 8A TXA |
TXA |
gister |
copy X |
|||
.,E635 48 PHA |
PHA |
retten |
save X |
|||
.,E636 A5 D0 LDA $D0 |
LDA CRSW |
CR-Flag |
input from keyboard or screen, $xx = screen, $00 = keyboard |
CRSW, INPUT/GET from keyboard or screen |
||
.,E638 F0 93 BEQ $E5CD |
BEQ LOOP3 |
nein, dann zur Warteschleife |
if keyboard go wait for key |
input from keyboard |
get character from current screen line |
|
.,E63A A4 D3 LDY $D3 |
LOP5 LDY PNTR |
Spalte |
get the cursor column |
PNTR, cursor column |
||
.,E63C B1 D1 LDA ($D1),Y |
LDA (PNT)Y NOTONE |
Zeichen vom Bildschirm holen |
get character from the current screen line |
read from current screen address |
||
.,E63E 85 D7 STA $D7 |
STA DATA |
und |
save temporary last character |
temp store |
||
.,E640 29 3F AND #$3F |
LOP51 AND #$3F |
nach |
mask key bits |
|||
.,E642 06 D7 ASL $D7 |
ASL DATA |
ASCII |
<< temporary last character |
|||
.,E644 24 D7 BIT $D7 |
BIT DATA |
wandeln |
test it |
|||
.,E646 10 02 BPL $E64A |
BPL LOP54 |
wenn Bit 6 nicht gesetzt, dann zu $E64A |
branch if not [NO KEY] |
|||
.,E648 09 80 ORA #$80 |
ORA #$80 |
Bit 7 setzen |
||||
.,E64A 90 04 BCC $E650 |
LOP54 BCC LOP52 |
Zeichen nicht revers ?, dann zu $E650 |
||||
.,E64C A6 D4 LDX $D4 |
LDX QTSW |
Hochkommaflag nicht |
get the cursor quote flag, $xx = quote, $00 = no quote |
QTSW, editor in quotes mode |
||
.,E64E D0 04 BNE $E654 |
BNE LOP53 |
gesetzt ?, dann zu $E654 |
if in quote mode go ?? |
yepp |
||
.,E650 70 02 BVS $E654 |
LOP52 BVS LOP53 |
wenn ja, dann zu $E654 |
||||
.,E652 09 40 ORA #$40 |
ORA #$40 |
Bit 6 im Zeichen setzen |
||||
.,E654 E6 D3 INC $D3 |
LOP53 INC PNTR |
Cursor eins weiter setzen |
increment the cursor column |
PNTR |
||
.,E656 20 84 E6 JSR $E684 |
JSR QTSWC |
auf Hochkomma testen |
if open quote toggle the cursor quote flag |
do quotes test |
||
.,E659 C4 C8 CPY $C8 |
CPY INDX |
Cursor in letzter Spalte ? |
compare ?? with input [EOL] pointer |
INDX, end of logical line for input |
||
.,E65B D0 17 BNE $E674 |
BNE CLP1 |
wenn nicht, dann zu $E674 |
if not at line end go ?? |
|||
.,E65D A9 00 LDA #$00 |
CLP2 LDA #0 |
Zeile |
clear A |
|||
.,E65F 85 D0 STA $D0 |
STA CRSW |
vollständig gelesen |
clear input from keyboard or screen, $xx = screen, $00 = keyboard |
CRSW |
||
.,E661 A9 0D LDA #$0D |
LDA #$D |
'CR' |
set character [CR] |
|||
.,E663 A6 99 LDX $99 |
LDX DFLTN ;FIX GETS FROM SCREEN |
ans Ende der Zeile setzen |
get the input device number |
DFLTN, default input device |
||
.,E665 E0 03 CPX #$03 |
CPX #3 ;IS IT THE SCREEN? |
Eingabe vom Bildschirm ? |
compare the input device with the screen |
screen |
||
.,E667 F0 06 BEQ $E66F |
BEQ CLP2A |
ja, dann zu $E66F |
if screen go ?? |
yes |
||
.,E669 A6 9A LDX $9A |
LDX DFLTO |
Ausgabe auf Bildschirm |
get the output device number |
DFLTO, default output device |
||
.,E66B E0 03 CPX #$03 |
CPX #3 |
ja, dann |
compare the output device with the screen |
screen |
||
.,E66D F0 03 BEQ $E672 |
BEQ CLP21 |
zu $E672 |
if screen go ?? |
yes |
||
.,E66F 20 16 E7 JSR $E716 |
CLP2A JSR PRT |
Zeichen auf Bildschirm schreiben |
output the character |
output to screen |
||
.,E672 A9 0D LDA #$0D |
CLP21 LDA #$D |
Wert für |
set character [CR] |
|||
.,E674 85 D7 STA $D7 |
CLP1 STA DATA |
'CR' |
save character |
|||
.,E676 68 PLA |
PLA |
die |
pull X |
|||
.,E677 AA TAX |
TAX |
Register |
restore X |
restore (X) and (Y) registers |
||
.,E678 68 PLA |
PLA |
zürück- |
pull Y |
|||
.,E679 A8 TAY |
TAY |
holen |
restore Y |
|||
.,E67A A5 D7 LDA $D7 |
LDA DATA |
Bildschirm-Kode |
restore character |
|||
.,E67C C9 DE CMP #$DE |
CMP #$DE ;IS IT <PI> ? |
mit Kode für Pi vergleichen |
screen PI code |
|||
.,E67E D0 02 BNE $E682 |
BNE CLP7 |
nein ?, dann fertig |
||||
.,E680 A9 FF LDA #$FF |
LDA #$FF |
ja ?, durch BASIC-Kode für Pi ersetzen |
petscii PI code |
|||
.,E682 18 CLC |
CLP7 CLC |
Carry löschen |
flag ok |
|||
.,E683 60 RTS |
RTS |
Rücksprungauf Hochkomma testen |
if open quote toggle cursor quote flag |
QUOTES TSETOn entry, (A) holds the character to be tested. If (A)holds ASCII quotes, then the quotes flag is toggled. |
check for quote mark and set flag |
|
.,E684 C9 22 CMP #$22 |
QTSWC CMP #$22 |
'"' ? |
comapre byte with " |
ASCII quotes (") |
quote mark |
|
.,E686 D0 08 BNE $E690 |
BNE QTSWL |
nein ?, dann fertig |
exit if not " |
nope, return |
||
.,E688 A5 D4 LDA $D4 |
LDA QTSW |
Hochkomma- |
get cursor quote flag, $xx = quote, $00 = no quote |
QTSW, quotes mode flag |
||
.,E68A 49 01 EOR #$01 |
EOR #$1 |
Flag |
toggle it |
toggle on/off |
||
.,E68C 85 D4 STA $D4 |
STA QTSW |
umdrehen |
save cursor quote flag |
store |
||
.,E68E A9 22 LDA #$22 |
LDA #$22 |
Hochkomma-Code wieder- herstellen |
restore the " |
restore (A) to #$22 |
quote mark |
|
.,E690 60 RTS |
QTSWL RTS |
RücksprungZeichen auf Bildschirmausgeben |
insert uppercase/graphic character |
SET UP SCREEN PRINTThe RVS flag is tested to see if reversed characters areto be printed. If insert mode is on, the insert counter is decremented by one. When in insert mode, all characters will be displayd, ie. DEL RVS etc. The character colour is placed in (X) and the character is printed to the scrren and the cursor advanced. |
fill screen at current position |
|
.,E691 09 40 ORA #$40 |
NXT33 ORA #$40 |
Bit 6 im Zeichen setzen |
change to uppercase/graphic |
|||
.,E693 A6 C7 LDX $C7 |
NXT3 LDX RVS |
RVS ? |
get the reverse flag |
test RVS, flag for reversed characters |
||
.,E695 F0 02 BEQ $E699 |
BEQ NVS |
Umwandlung in Bildschirmcode |
branch if not reverse else .. insert reversed character |
nope |
||
.,E697 09 80 ORA #$80 |
NC3 ORA #$80 |
ja, dann Bit 7 setzen |
reverse character |
set bit 7 to reverse character |
||
.,E699 A6 D8 LDX $D8 |
NVS LDX INSRT |
wenn Einfügzähler Null, |
get the insert count |
test INSRT, flag for insert mode |
||
.,E69B F0 02 BEQ $E69F |
BEQ NVS1 |
dann zu $E69F |
branch if none |
nope |
||
.,E69D C6 D8 DEC $D8 |
DEC INSRT |
Zähler erniedrigen |
else decrement the insert count |
decrement number of characters left to insert |
||
.,E69F AE 86 02 LDX $0286 |
NVS1 LDX COLOR PUT COLOR ON SCREEN |
Farbkode |
get the current colour code |
get COLOR, current character colour code |
||
.,E6A2 20 13 EA JSR $EA13 |
JSR DSPP |
Zeichen in Bildschirm-RAM schreiben |
print character A and colour X |
print to screen |
||
.,E6A5 20 B6 E6 JSR $E6B6 |
JSR WLOGIC ;CHECK FOR WRAPAROUND |
Tabelle der Zeilenanfänge aktualisieren |
advance the cursor restore the registers, set the quote flag and exit |
advance cursor |
return from output to the screen |
|
.,E6A8 68 PLA |
LOOP2 PLA |
Y-Reg |
pull Y |
|||
.,E6A9 A8 TAY |
TAY |
aus Stack |
restore Y |
|||
.,E6AA A5 D8 LDA $D8 |
LDA INSRT |
wenn Einfügzähler Null, |
get the insert count |
INSRT |
||
.,E6AC F0 02 BEQ $E6B0 |
BEQ LOP2 |
dann zu $E6B0 |
skip quote flag clear if inserts to do |
|||
.,E6AE 46 D4 LSR $D4 |
LSR QTSW |
Hochkommamodus löschen |
clear cursor quote flag, $xx = quote, $00 = no quote |
|||
.,E6B0 68 PLA |
LOP2 PLA |
X-Reg |
pull X |
|||
.,E6B1 AA TAX |
TAX |
aus Stack |
restore X |
|||
.,E6B2 68 PLA |
PLA |
Akku aus Stack |
restore A |
|||
.,E6B3 18 CLC |
CLC ;GOOD RETURN |
Carry löschen |
||||
.,E6B4 58 CLI |
CLI |
Interrupt freigeben |
enable the interrupts |
|||
.,E6B5 60 RTS |
RTS WLOGIC |
RücksprungHIGH-Byte für Zeilenanfängeneu berechnen |
advance the cursor |
ADVANCE CURSORThe cursor is advanced one position on the screen. If thisputs it beyond the 40th column, then it is placed at the beginning of the next line. If the length of that line is less than 80, then this new line is linked to the previous one. A space is opened if data already exists on the new line. If the cursor has reached the bottom of the screen, then the screen is scrolled down. |
get/insert new line |
|
.,E6B6 20 B3 E8 JSR $E8B3 |
JSR CHKDWN ;MAYBE WE SHOULD WE INCREMENT TBLX |
Zeilenzeiger erhöhen |
test for line increment |
check line increment |
||
.,E6B9 E6 D3 INC $D3 |
INC PNTR ;BUMP CHARCTER POINTER |
Cursorspalte erhöhen |
increment the cursor column |
increment PNTR, cursor column on current line |
||
.,E6BB A5 D5 LDA $D5 |
LDA LNMX ; |
Zeilenlänge holen |
get current screen line length |
LNMX, physical screen line length |
||
.,E6BD C5 D3 CMP $D3 |
CMP PNTR ;IF LNMX IS LESS THAN PNTR |
Vergleich mit Cursorspalte |
compare ?? with the cursor column |
compare to PNTR |
||
.,E6BF B0 3F BCS $E700 |
BCS WLGRTS ;BRANCH IF LNMX>=PNTR |
nicht überschritten, dann RTS |
exit if line length >= cursor column |
not beyond end of line, exit |
||
.,E6C1 C9 4F CMP #$4F |
CMP #MAXCHR-1 ;PAST MAX CHARACTERS |
79 Zeichen (Doppelzeile) ? |
compare with max length |
$4f = 79 |
||
.,E6C3 F0 32 BEQ $E6F7 |
BEQ WLOG10 ;BRANCH IF SO |
wenn ja, dann zu $E6F7 |
if at max clear column, back cursor up and do newline |
put cursor on new logical line |
||
.,E6C5 AD 92 02 LDA $0292 |
LDA AUTODN ;SHOULD WE AUTO SCROLL DOWN? |
Zeilenübergang nicht |
get the autoscroll flag |
AUTODN, auto scroll down flag |
||
.,E6C8 F0 03 BEQ $E6CD |
BEQ WLOG20 ;BRANCH IF NOT |
im Editmodus, dann zu $E6CD |
branch if autoscroll on |
auto scroll is on |
||
.,E6CA 4C 67 E9 JMP $E967 |
JMP BMT1 ;ELSE DECIDE WHICH WAY TO SCROLL WLOG20 |
neue Zeile einfügen |
else open space on screen |
open a space on the screen |
||
.,E6CD A6 D6 LDX $D6 |
LDX TBLX ;SEE IF WE SHOULD SCROLL DOWN |
Zeile |
get the cursor row |
read TBLX, current line number |
||
.,E6CF E0 19 CPX #$19 |
CPX #NLINES |
25 ? |
compare with max + 1 |
$19 = 25 |
||
.,E6D1 90 07 BCC $E6DA |
BCC WLOG30 ;BRANCH IF NOT |
wenn ja, dann zu $E6DA |
if less than max + 1 go add this row to the current logical line |
less than 25 |
||
.,E6D3 20 EA E8 JSR $E8EA |
JSR SCROL ;ELSE DO THE SCROL UP |
SCROLL |
else scroll the screen |
scroll down |
||
.,E6D6 C6 D6 DEC $D6 |
DEC TBLX ;AND ADJUST CURENT LINE# |
Cursorzeilenzeiger erniedrigen |
decrement the cursor row |
place cursor on line 24 |
||
.,E6D8 A6 D6 LDX $D6 |
LDX TBLX |
Zähler holen |
get the cursor row add this row to the current logical line |
|||
.,E6DA 16 D9 ASL $D9,X |
WLOG30 ASL LDTB1,X ;WRAP THE LINE |
Zeile |
shift start of line X pointer high byte |
clear bit7 in LDTB1 to indicate that it is line 2 |
||
.,E6DC 56 D9 LSR $D9,X |
LSR LDTB1,X |
markieren |
shift start of line X pointer high byte back, make next screen line start of logical line, increment line length and set pointers clear b7, start of logical line |
in the logical line |
||
.,E6DE E8 INX |
INX ;INDEX TO NEXT LLINE |
Zähler erhöhen |
increment screen row |
next line |
||
.,E6DF B5 D9 LDA $D9,X |
LDA LDTB1,X ;GET HIGH ORDER BYTE OF ADDRESS |
Startzeile |
get start of line X pointer high byte |
set bit7 in LDTB1 to indicate that it is line 1 |
||
.,E6E1 09 80 ORA #$80 |
ORA #$80 ;MAKE IT A NON-CONTINUATION LINE |
markieren |
mark as start of logical line |
in the logical line |
||
.,E6E3 95 D9 STA $D9,X |
STA LDTB1,X ;AND PUT IT BACK |
und speichern |
set start of line X pointer high byte |
|||
.,E6E5 CA DEX |
DEX ;GET BACK TO CURRENT LINE |
Zähler erniedrigen |
restore screen row |
|||
.,E6E6 A5 D5 LDA $D5 |
LDA LNMX ;CONTINUE THE BYTES TAKEN OUT |
Zeilenlänge |
get current screen line length add one line length and set the pointers for the start of the line |
add $28 (40) to LNMX to allow 80 characters |
||
.,E6E8 18 CLC |
CLC |
mit |
clear carry for add |
on the logical line |
||
.,E6E9 69 28 ADC #$28 |
ADC #LLEN |
40 addieren |
add one line length |
|||
.,E6EB 85 D5 STA $D5 |
STA LNMX FINDST |
und speichern |
save current screen line length |
RETREAT CURSORThe screen line link table is searched, and then the startof line is set. The rest of the routine sets the cursor onto the next line for the previous routine. |
||
.,E6ED B5 D9 LDA $D9,X |
LDA LDTB1,X ;IS THIS THE FIRST LINE? |
keine Doppelzeile, |
get start of line X pointer high byte |
LDTB1, screen line link table |
||
.,E6EF 30 03 BMI $E6F4 |
BMI FINX ;BRANCH IF SO |
dann zu $E6F4 |
exit loop if start of logical line |
test bit7 |
||
.,E6F1 CA DEX |
DEX ;ELSE BACKUP 1 |
Zähler erniedrigen |
else back up one line |
next line |
||
.,E6F2 D0 F9 BNE $E6ED |
BNE FINDST FINX |
noch nicht alle?, dann weiter |
loop if not on first line |
till all are done |
||
.,E6F4 4C F0 E9 JMP $E9F0 |
JMP SETPNT ;MAKE SURE PNT IS RIGHT |
Zeiger auf Farb-RAM für Zeile X |
fetch a screen address |
set start of line |
||
.,E6F7 C6 D6 DEC $D6 |
WLOG10 DEC TBLX |
Cursorzeile erniedrigen |
decrement the cursor row |
decrement TBLX, cursor line |
||
.,E6F9 20 7C E8 JSR $E87C |
JSR NXLN |
und initialisieren |
do newline |
goto next line |
||
.,E6FC A9 00 LDA #$00 |
LDA #0 |
Spalte |
clear A |
|||
.,E6FE 85 D3 STA $D3 |
STA PNTR ;POINT TO FIRST BYTE |
auf Null |
clear the cursor column |
set PNTR, the cursor column, to zero |
||
.,E700 60 RTS |
WLGRTS RTS |
RücksprungRückschritt in vorhergehendeZeile |
back onto the previous line if possible |
BACK ON TO PREVIOUS LINEThis routine is called when using <DEL> and <cursor LEFT>.The line number is tested, and if the cursor is already on the top line, then no further action is taken. The screen pointers are set up and the cursor placed at the end of the previous line. |
move backwards over a line boundary |
|
.,E701 A6 D6 LDX $D6 |
BKLN LDX TBLX |
Cursorzeile |
get the cursor row |
test TBLX, physical line number |
||
.,E703 D0 06 BNE $E70B |
BNE BKLN1 |
wenn null, dann zu $E70B |
branch if not top row |
if not on top line, branch |
||
.,E705 86 D3 STX $D3 |
STX PNTR |
Cursorspalte |
clear cursor column |
set PNTR to zero as well |
||
.,E707 68 PLA |
PLA |
Sprungadresse |
dump return address low byte |
|||
.,E708 68 PLA |
PLA |
aus Stack holen |
dump return address high byte |
|||
.,E709 D0 9D BNE $E6A8 |
BNE LOOP2 ; |
unbedingter Sprung |
restore registers, set quote flag and exit, branch always |
allways jump |
||
.,E70B CA DEX |
BKLN1 DEX |
Zeilennummer |
decrement the cursor row |
decrement TBLX |
||
.,E70C 86 D6 STX $D6 |
STX TBLX |
erniedrigen |
save the cursor row |
and store |
||
.,E70E 20 6C E5 JSR $E56C |
JSR STUPT |
Cursorposition berechnen |
set the screen pointers for cursor row, column |
set screen pointers |
||
.,E711 A4 D5 LDY $D5 |
LDY LNMX |
Zeilenlänge |
get current screen line length |
get LNMX |
||
.,E713 84 D3 STY $D3 |
STY PNTR |
speichern |
save the cursor column |
and store in PNTR |
||
.,E715 60 RTS |
RTS ;PRINT ROUTINE ; |
RücksprungAusgabe auf Bildschirm |
output a character to the screen |
OUTPUT TO SCREENThis routine is part of the main KERNAL CHROUT routine. Itprints CBM ASCII characters to the screen and takes care of all the screen editing characters. The cursor is automatically updated and scrolling occurs if necessary. On entry, (A) must hold the character to be output. On entry all registers are stored on the stack. For convinience, the routine is slpit into sections showing the processing of both shifted and unshifted character. |
put a character to screen |
|
.,E716 48 PHA |
PRT PHA |
Zeichen |
save character |
store (A), (X) and (Y) on stack |
||
.,E717 85 D7 STA $D7 |
STA DATA |
merken |
save temporary last character |
temp store |
||
.,E719 8A TXA |
TXA |
die |
copy X |
|||
.,E71A 48 PHA |
PHA |
Re- |
save X |
|||
.,E71B 98 TYA |
TYA |
gister |
copy Y |
|||
.,E71C 48 PHA |
PHA |
retten |
save Y |
|||
.,E71D A9 00 LDA #$00 |
LDA #0 |
Eingabeflag |
clear A |
|||
.,E71F 85 D0 STA $D0 |
STA CRSW |
löschen |
clear input from keyboard or screen, $xx = screen, $00 = keyboard |
store in CRSW |
||
.,E721 A4 D3 LDY $D3 |
LDY PNTR |
Cursorspalte |
get cursor column |
PNTR, cursor positions on line |
||
.,E723 A5 D7 LDA $D7 |
LDA DATA |
Zeichen |
restore last character |
retrieve from temp store |
||
.,E725 10 03 BPL $E72A |
BPL *+5 |
wenn kleiner 128, dann zu $E72A |
branch if unshifted |
do unshifted characters |
||
.,E727 4C D4 E7 JMP $E7D4 |
JMP NXTX |
Zeichen größer $7F behandeln |
do shifted characters and return |
do shifted characters UNSHIFTED CHARACTERS. Ordinary unshifted ASCII characters and PET graphics are output directly to the screen. The following control codes are trapped and precessed: <RETURN>, <DEL>, <CRSR RIGHT>, <CRSR DOWN>. If either insert mode is on or quotes are open (except for <DEL>) then the control characters are not processed, but output as reversed ASCII literals. |
||
.,E72A C9 0D CMP #$0D |
CMP #$D |
'CARRIAGE RETURN' ? |
compare with [CR] |
<RETURN>? |
return code |
|
.,E72C D0 03 BNE $E731 |
BNE NJT1 |
wenn nicht, dann zu $E731 |
branch if not [CR] |
nope |
||
.,E72E 4C 91 E8 JMP $E891 |
JMP NXT1 |
Return ausgeben |
else output [CR] and return |
execute return |
||
.,E731 C9 20 CMP #$20 |
NJT1 CMP #' |
' ' |
compare with [SPACE] |
<SPACE>? |
||
.,E733 90 10 BCC $E745 |
BCC NTCN |
druckendes Zeichen ? |
branch if < [SPACE], not a printable character |
|||
.,E735 C9 60 CMP #$60 |
CMP #$60 ;LOWER CASE? |
Zahl kleiner $60, |
#$60, first PET graphic character? |
|||
.,E737 90 04 BCC $E73D |
BCC NJT8 ;NO... |
dann keine Graphikzeichen |
branch if $20 to $5F character is $60 or greater |
|||
.,E739 29 DF AND #$DF |
AND #$DF ;YES...MAKE SCREEN LOWER |
Umwandlung in BS-Kode |
conversion of PETSCII character to screen code |
%11011111 |
||
.,E73B D0 02 BNE $E73F |
BNE NJT9 ;ALWAYS |
unbedingter Sprung |
branch always character is $20 to $5F |
|||
.,E73D 29 3F AND #$3F |
NJT8 AND #$3F |
Umwandlung in BS-Kode |
conversion of PETSCII character to screen code |
%00111111 |
||
.,E73F 20 84 E6 JSR $E684 |
NJT9 JSR QTSWC |
Test auf Hochkomma |
if open quote toggle cursor direct/programmed flag |
do quotes test |
||
.,E742 4C 93 E6 JMP $E693 |
JMP NXT3 |
zur Ausgabe, ASCII-Kode in BS-Code |
character was < [SPACE] so is a control character of some sort |
setup screen print |
||
.,E745 A6 D8 LDX $D8 |
NTCN LDX INSRT |
wenn Einfügzähler =0, |
get the insert count |
INSRT, insert mode flag |
||
.,E747 F0 03 BEQ $E74C |
BEQ CNC3X |
dann zu $E74C |
if no characters to insert continue |
mode not set |
||
.,E749 4C 97 E6 JMP $E697 |
JMP NC3 |
ASCII-Kode in BS-Code |
insert reversed character |
output reversed charcter |
||
.,E74C C9 14 CMP #$14 |
CNC3X CMP #$14 |
nicht 'DEL' ?, |
compare the character with [INSERT]/[DELETE] |
<DEL>? |
delete code |
|
.,E74E D0 2E BNE $E77E |
BNE NTCN1 |
dann zu $E77E |
if not [INSERT]/[DELETE] go ?? |
nope |
||
.,E750 98 TYA |
TYA |
erste Spalte =0 |
(Y) holds cursor column |
|||
.,E751 D0 06 BNE $E759 |
BNE BAK1UP |
dann zu $E759 |
not start of line |
|||
.,E753 20 01 E7 JSR $E701 |
JSR BKLN |
zurück in vorherige Zeile |
back onto the previous line if possible |
back on previous line |
||
.,E756 4C 73 E7 JMP $E773 |
JMP BK2 |
Zeichen in Cursorposition eliminieren |
||||
.,E759 20 A1 E8 JSR $E8A1 |
BAK1UP JSR CHKBAK ;SHOULD WE DEC TBLX |
Rückschritt prüfen |
test for line decrement now close up the line |
check line decrement |
||
.,E75C 88 DEY |
DEY |
Zeiger erniedrigen |
decrement index to previous character |
decrement cursor column |
||
.,E75D 84 D3 STY $D3 |
STY PNTR |
und speichern |
save the cursor column |
and store in PNTR |
||
.,E75F 20 24 EA JSR $EA24 |
BK1 JSR SCOLOR ;FIX COLOR PTRS |
Zeiger auf Farb-RAM berechnen |
calculate the pointer to colour RAM |
syncronise colour pointer |
||
.,E762 C8 INY |
BK15 INY |
Zeiger erhöhen |
increment index to next character |
copy character at cursor position (Y+1) to (Y) |
||
.,E763 B1 D1 LDA ($D1),Y |
LDA (PNT)Y |
Zeichen vom Bildschirm |
get character from current screen line |
read character |
||
.,E765 88 DEY |
DEY |
Zeiger erniedrigen |
decrement index to previous character |
|||
.,E766 91 D1 STA ($D1),Y |
STA (PNT)Y |
eins nach links schieben |
save character to current screen line |
and store it one position back |
||
.,E768 C8 INY |
INY |
Zeiger erhöhen |
increment index to next character |
|||
.,E769 B1 F3 LDA ($F3),Y |
LDA (USER)Y |
Farbe |
get colour RAM byte |
read character colour |
||
.,E76B 88 DEY |
DEY |
Zeiger erniedrigen |
decrement index to previous character |
|||
.,E76C 91 F3 STA ($F3),Y |
STA (USER)Y |
eins nach links schieben |
save colour RAM byte |
and store it one position back |
||
.,E76E C8 INY |
INY |
Zeiger erhöhen |
increment index to next character |
more characters to move |
||
.,E76F C4 D5 CPY $D5 |
CPY LNMX |
Endspalte nicht |
compare with current screen line length |
compare with LNMX, length of physical screen line |
||
.,E771 D0 EF BNE $E762 |
BNE BK15 |
erreicht, dann weiter |
loop if not there yet |
if not equal, move more characters |
||
.,E773 A9 20 LDA #$20 |
BK2 LDA #' |
Blank |
set [SPACE] |
space |
||
.,E775 91 D1 STA ($D1),Y |
STA (PNT)Y |
einfügen |
clear last character on current screen line |
store <SPACE> at end of line |
||
.,E777 AD 86 02 LDA $0286 |
LDA COLOR |
Farbcode |
get the current colour code |
COLOR, current character colour |
||
.,E77A 91 F3 STA ($F3),Y |
STA (USER)Y |
setzen |
save to colour RAM |
store colour at end of line |
||
.,E77C 10 4D BPL $E7CB |
BPL JPL3 |
fertig |
branch always |
allways jump |
||
.,E77E A6 D4 LDX $D4 |
NTCN1 LDX QTSW |
Hochkomma-Modus ? |
get cursor quote flag, $xx = quote, $00 = no quote |
QTSW, editor in quotes mode |
||
.,E780 F0 03 BEQ $E785 |
BEQ NC3W |
nein |
branch if not quote mode |
no |
||
.,E782 4C 97 E6 JMP $E697 |
CNC3 JMP NC3 |
Zeichen revers ausgeben |
insert reversed character |
output reversed character |
||
.,E785 C9 12 CMP #$12 |
NC3W CMP #$12 |
'RVS ON' ? |
compare with [RVS ON] |
<RVS>? |
reverse code |
|
.,E787 D0 02 BNE $E78B |
BNE NC1 |
nein, dann |
if not [RVS ON] skip setting the reverse flag |
no |
||
.,E789 85 C7 STA $C7 |
STA RVS |
Flag für RVS setzen |
else set the reverse flag |
RVS, reversed character output flag |
||
.,E78B C9 13 CMP #$13 |
NC1 CMP #$13 |
'HOME' ? |
compare with [CLR HOME] |
<HOME>? |
home code |
|
.,E78D D0 03 BNE $E792 |
BNE NC2 |
nein |
if not [CLR HOME] continue |
no |
||
.,E78F 20 66 E5 JSR $E566 |
JSR NXTD |
ja, Cursor Home |
home the cursor |
home cursor |
||
.,E792 C9 1D CMP #$1D |
NC2 CMP #$1D |
'Cursor right' ? |
compare with [CURSOR RIGHT] |
<CRSR RIGHT>? |
csr right |
|
.,E794 D0 17 BNE $E7AD |
BNE NCX2 |
nein |
if not [CURSOR RIGHT] go ?? |
nope |
||
.,E796 C8 INY |
INY |
Zeiger erhöhen |
increment the cursor column |
increment (Y), internal counter for column |
||
.,E797 20 B3 E8 JSR $E8B3 |
JSR CHKDWN |
Cursorposition prüfen |
test for line increment |
check line increment |
||
.,E79A 84 D3 STY $D3 |
STY PNTR |
neuer Zeiger |
save the cursor column |
store (Y) in PNTR |
||
.,E79C 88 DEY |
DEY |
Zeiger erniedrigen |
decrement the cursor column |
decrement (Y) |
||
.,E79D C4 D5 CPY $D5 |
CPY LNMX |
keine neue Zeile ?, |
compare cursor column with current screen line length |
and compare to LNMX |
||
.,E79F 90 09 BCC $E7AA |
BCC NCZ2 |
dann fertig |
exit if less else the cursor column is >= the current screen line length so back onto the current line and do a newline |
not exceeded line length |
||
.,E7A1 C6 D6 DEC $D6 |
DEC TBLX |
Zeiger erniedrigen |
decrement the cursor row |
TBLX, current physical line number |
||
.,E7A3 20 7C E8 JSR $E87C |
JSR NXLN |
Zeile initialisieren |
do newline |
goto next line |
||
.,E7A6 A0 00 LDY #$00 |
LDY #0 |
Spalte |
clear cursor column |
|||
.,E7A8 84 D3 STY $D3 |
JPL4 STY PNTR |
gleich null |
save the cursor column |
set PNTR to zero, cursor to the left |
||
.,E7AA 4C A8 E6 JMP $E6A8 |
NCZ2 JMP LOOP2 |
fertig |
restore the registers, set the quote flag and exit |
finish screen print |
||
.,E7AD C9 11 CMP #$11 |
NCX2 CMP #$11 |
'Cursor down' ? |
compare with [CURSOR DOWN] |
<CRSR DOWN>? |
csr down |
|
.,E7AF D0 1D BNE $E7CE |
BNE COLR1 |
nein |
if not [CURSOR DOWN] go ?? |
no |
||
.,E7B1 18 CLC |
CLC |
plus |
clear carry for add |
prepare for add |
||
.,E7B2 98 TYA |
TYA |
40, |
copy the cursor column |
(Y) holds cursor column |
||
.,E7B3 69 28 ADC #$28 |
ADC #LLEN |
eine Zeile |
add one line |
add 40 to next line |
||
.,E7B5 A8 TAY |
TAY |
tiefer |
copy back to Y |
to (Y) |
||
.,E7B6 E6 D6 INC $D6 |
INC TBLX |
Zeiger erhöhen |
increment the cursor row |
increment TBLX, physical line number |
||
.,E7B8 C5 D5 CMP $D5 |
CMP LNMX |
neue Zeile erreicht? |
compare cursor column with current screen line length |
compare to LNMX |
||
.,E7BA 90 EC BCC $E7A8 |
BCC JPL4 |
nein, dann zu $E7A8 |
if less go save cursor column and exit |
finish screen print |
||
.,E7BC F0 EA BEQ $E7A8 |
BEQ JPL4 |
Ja, dann zu $E7A8 |
if equal go save cursor column and exit else the cursor has moved beyond the end of this line so back it up until it's on the start of the logical line |
finish screen print |
||
.,E7BE C6 D6 DEC $D6 |
DEC TBLX |
Zeiger erniedrigen |
decrement the cursor row |
restore TBLX |
||
.,E7C0 E9 28 SBC #$28 |
CURS10 SBC #LLEN |
40 abziehen |
subtract one line |
|||
.,E7C2 90 04 BCC $E7C8 |
BCC GOTDWN |
genügend abgezogen, dann zu $E7C8 |
if on previous line exit the loop |
|||
.,E7C4 85 D3 STA $D3 |
STA PNTR |
Spalte setzen |
else save the cursor column |
store PNTR |
||
.,E7C6 D0 F8 BNE $E7C0 |
BNE CURS10 |
noch mal |
loop if not at the start of the line |
|||
.,E7C8 20 7C E8 JSR $E87C |
GOTDWN JSR NXLN |
Zeile initialisieren |
do newline |
go to next line |
||
.,E7CB 4C A8 E6 JMP $E6A8 |
JPL3 JMP LOOP2 |
fertig |
restore the registers, set the quote flag and exit |
finish screen print |
||
.,E7CE 20 CB E8 JSR $E8CB |
COLR1 JSR CHKCOL ;CHECK FOR A COLOR |
prüft auf Farbcodes |
set the colour code |
set colour code |
||
.,E7D1 4C 44 EC JMP $EC44 |
JMP LOWER ;WAS JMP LOOP2 ;CHECK COLOR ; ;SHIFTED KEYS ; NXTX KEEPIT |
Test auf weitere Sonderzeichen Zeichen größer $127 |
go check for special character codes |
do graphics/text control SHIFTED CHARACTERS. These are dealt with in the following order: Shifted ordinart ASCII and PET graphics characters, <shift RETURN>, <INST>, <CRSR UP>, <RVS OFF>, <CRSR LEFT>, <CLR>. If either insert mode is on, or quotes are open, then the control character is not processed but reversed ASCII literal is printed. |
put shifted chars to screen |
|
.,E7D4 29 7F AND #$7F |
AND #$7F |
Kode größer 127, Bit 7 löschen |
mask 0xxx xxxx, clear b7 |
clear bit7 |
remove shift bit |
|
.,E7D6 C9 7F CMP #$7F |
CMP #$7F |
nicht 'Pi' ? |
was it $FF before the mask |
compare to #$7f |
code for PI |
|
.,E7D8 D0 02 BNE $E7DC |
BNE NXTX1 |
dann zu $E7DC |
branch if not |
not equal |
||
.,E7DA A9 5E LDA #$5E |
LDA #$5E NXTX1 NXTXA |
Bildschirmkode für Pi |
else make it $5E |
if #$7f, load #$5e |
screen PI |
|
.,E7DC C9 20 CMP #$20 |
CMP #$20 ;IS IT A FUNCTION KEY |
Steuerzeichen ? |
compare the character with [SPACE] |
ASCII <SPACE>? |
||
.,E7DE 90 03 BCC $E7E3 |
BCC UHUH |
ja |
if < [SPACE] go ?? |
|||
.,E7E0 4C 91 E6 JMP $E691 |
JMP NXT33 UHUH |
druckendes Zeichen ausgeben |
insert uppercase/graphic character and return character was $80 to $9F and is now $00 to $1F |
set up screen print |
||
.,E7E3 C9 0D CMP #$0D |
CMP #$D |
nicht 'Shift return' ? |
compare with [CR] |
<RETURN>? |
shift return |
|
.,E7E5 D0 03 BNE $E7EA |
BNE UP5 |
dann zu $E7EA |
if not [CR] continue |
nope |
||
.,E7E7 4C 91 E8 JMP $E891 |
JMP NXT1 |
neue Zeile |
else output [CR] and return was not [CR] |
do return |
||
.,E7EA A6 D4 LDX $D4 |
UP5 LDX QTSW |
Hochkomma-Hodus ? |
get the cursor quote flag, $xx = quote, $00 = no quote |
read QTSW |
||
.,E7EC D0 3F BNE $E82D |
BNE UP6 |
ja, Steuerzeichen revers ausgeben |
branch if quote mode |
if quotes mode, jump |
||
.,E7EE C9 14 CMP #$14 |
CMP #$14 |
nicht 'INS' ?, |
compare with [INSERT DELETE] |
<INST>? |
insert |
|
.,E7F0 D0 37 BNE $E829 |
BNE UP9 |
dann zu $E829 |
if not [INSERT DELETE] go ?? |
nope |
||
.,E7F2 A4 D5 LDY $D5 |
LDY LNMX |
Zeilenlänge |
get current screen line length |
LNMX |
||
.,E7F4 B1 D1 LDA ($D1),Y |
LDA (PNT)Y |
letztes Zeichen in Zeile |
get character from current screen line |
get screen character |
||
.,E7F6 C9 20 CMP #$20 |
CMP #' |
gleich Leerzeichen ? |
compare the character with [SPACE] |
space? |
||
.,E7F8 D0 04 BNE $E7FE |
BNE INS3 |
nein, dann zu $E7FE |
if not [SPACE] continue |
nope |
||
.,E7FA C4 D3 CPY $D3 |
CPY PNTR |
Cursor in letzter Spalte ? |
compare the current column with the cursor column |
PNTR equal to LNMX |
||
.,E7FC D0 07 BNE $E805 |
BNE INS1 |
nein, dann zu $E805 |
if not cursor column go open up space on line |
nope |
||
.,E7FE C0 4F CPY #$4F |
INS3 CPY #MAXCHR-1 |
79 ? maximale Zeilenlänge |
compare current column with max line length |
#$4f=79, last character |
||
.,E800 F0 24 BEQ $E826 |
BEQ INSEXT ;EXIT IF LINE TOO LONG |
letzte Spalte, dann keine Aktion |
if at line end just exit |
end of logical line, can not insert |
||
.,E802 20 65 E9 JSR $E965 |
JSR NEWLIN ;SCROLL DOWN 1 |
Leerzeile einfügen |
else open up a space on the screen now open up space on the line to insert a character |
open space on line |
||
.,E805 A4 D5 LDY $D5 |
INS1 LDY LNMX |
Zeilenlänge |
get current screen line length |
LNMX |
||
.,E807 20 24 EA JSR $EA24 |
JSR SCOLOR |
Zeiger auf Farbram berechnen |
calculate the pointer to colour RAM |
syncronise colour pointer |
||
.,E80A 88 DEY |
INS2 DEY |
Zeiger erniedrigen |
decrement the index to previous character |
prepare for move |
||
.,E80B B1 D1 LDA ($D1),Y |
LDA (PNT)Y |
Zeichen vom Bildschirm |
get the character from the current screen line |
read character at pos (Y) |
||
.,E80D C8 INY |
INY |
Zeiger erhöhen |
increment the index to next character |
|||
.,E80E 91 D1 STA ($D1),Y |
STA (PNT)Y |
eins nach rechts schieben |
save the character to the current screen line |
and move one step to the right |
||
.,E810 88 DEY |
DEY |
Zeiger erniedrigen |
decrement the index to previous character |
|||
.,E811 B1 F3 LDA ($F3),Y |
LDA (USER)Y |
und Farbe |
get the current screen line colour RAM byte |
read character colour |
||
.,E813 C8 INY |
INY |
Zeiger erhöhen |
increment the index to next character |
|||
.,E814 91 F3 STA ($F3),Y |
STA (USER)Y |
verschieben |
save the current screen line colour RAM byte |
move one step to the right |
||
.,E816 88 DEY |
DEY |
Zeiger erniedrigen |
decrement the index to the previous character |
decrement counter |
||
.,E817 C4 D3 CPY $D3 |
CPY PNTR |
bis zur aktuellen Position aufrücken |
compare the index with the cursor column |
compare with PNTR |
||
.,E819 D0 EF BNE $E80A |
BNE INS2 |
nicht ?, dann weiter |
loop if not there yet |
till all characters right of cursor are moved |
||
.,E81B A9 20 LDA #$20 |
LDA #$20 |
Leerzeichen |
set [SPACE] |
<SPACE>, ASCII #$20 |
||
.,E81D 91 D1 STA ($D1),Y |
STA (PNT)Y |
an augenblickliche Position schreiben |
clear character at cursor position on current screen line |
store at new character position |
||
.,E81F AD 86 02 LDA $0286 |
LDA COLOR |
Farbe |
get current colour code |
COLOR, current character colour |
||
.,E822 91 F3 STA ($F3),Y |
STA (USER)Y |
setzen |
save to cursor position on current screen line colour RAM |
store at new colour position |
||
.,E824 E6 D8 INC $D8 |
INC INSRT |
Anzahl der Inserts erhöhen |
increment insert count |
INSRT FLAG |
||
.,E826 4C A8 E6 JMP $E6A8 |
INSEXT JMP LOOP2 |
Ende der Zeichenausgabe |
restore the registers, set the quote flag and exit |
finish screen print |
||
.,E829 A6 D8 LDX $D8 |
UP9 LDX INSRT |
Zähler Null? |
get the insert count |
INSRT FLAG |
||
.,E82B F0 05 BEQ $E832 |
BEQ UP2 |
dann zu $E832 |
branch if no insert space |
insert mode is off |
||
.,E82D 09 40 ORA #$40 |
UP6 ORA #$40 |
Bit 6 setzen |
change to uppercase/graphic |
|||
.,E82F 4C 97 E6 JMP $E697 |
JMP NC3 |
und Zeichen ausgeben |
insert reversed character |
set up screen print |
||
.,E832 C9 11 CMP #$11 |
UP2 CMP #$11 |
nicht Cursor up ?, |
compare with [CURSOR UP] |
<CRSR UP>? |
csr up |
|
.,E834 D0 16 BNE $E84C |
BNE NXT2 |
dann zu $E84C |
branch if not [CURSOR UP] |
nope |
||
.,E836 A6 D6 LDX $D6 |
LDX TBLX |
Zeile |
get the cursor row |
read TBLX |
||
.,E838 F0 37 BEQ $E871 |
BEQ JPL2 |
null, dann fertig |
if on the top line go restore the registers, set the quote flag and exit |
at topline, do nothing |
||
.,E83A C6 D6 DEC $D6 |
DEC TBLX |
Zeilennummer um eins erniedrigen |
decrement the cursor row |
else decrement TBLX |
||
.,E83C A5 D3 LDA $D3 |
LDA PNTR |
Spalte |
get the cursor column |
PNTR |
||
.,E83E 38 SEC |
SEC |
40 |
set carry for subtract |
prepare for substract |
||
.,E83F E9 28 SBC #$28 |
SBC #LLEN |
abziehen nicht in Doppelzeile ?, |
subtract one line length |
back 40 columns for double line |
||
.,E841 90 04 BCC $E847 |
BCC UPALIN |
dann zu $E847 |
branch if stepped back to previous line |
skip |
||
.,E843 85 D3 STA $D3 |
STA PNTR |
Cursorspalte |
else save the cursor column .. |
store PNTR |
||
.,E845 10 2A BPL $E871 |
BPL JPL2 |
positiv, ok |
.. and exit, branch always |
finish screen print |
||
.,E847 20 6C E5 JSR $E56C |
UPALIN JSR STUPT |
Bildschirmzeiger neu setzen |
set the screen pointers for cursor row, column .. |
set screen pointer |
||
.,E84A D0 25 BNE $E871 |
BNE JPL2 |
unbedingter Sprung |
.. and exit, branch always |
finish screen print |
||
.,E84C C9 12 CMP #$12 |
NXT2 CMP #$12 |
nicht 'RVS OFF' ?, |
compare with [RVS OFF] |
<RVS OFF>? |
reverse off |
|
.,E84E D0 04 BNE $E854 |
BNE NXT6 |
dann zu $E854 |
if not [RVS OFF] continue |
nope |
||
.,E850 A9 00 LDA #$00 |
LDA #0 |
RVS-Flag |
else clear A |
|||
.,E852 85 C7 STA $C7 |
STA RVS |
löschen |
clear the reverse flag |
RVS, disable reverse print |
||
.,E854 C9 1D CMP #$1D |
NXT6 CMP #$1D |
nicht ’Cursor left' ?, |
compare with [CURSOR LEFT] |
<CRSR LEFT>? |
csr left |
|
.,E856 D0 12 BNE $E86A |
BNE NXT61 |
dann zu $E86A |
if not [CURSOR LEFT] go ?? |
nope |
||
.,E858 98 TYA |
TYA |
wenn erste Spalte, |
copy the cursor column |
(Y) holds cursor column |
||
.,E859 F0 09 BEQ $E864 |
BEQ BAKBAK |
dann zu $E864 |
if at start of line go back onto the previous line |
at first position |
||
.,E85B 20 A1 E8 JSR $E8A1 |
JSR CHKBAK |
Cursorzeile erniedrigen |
test for line decrement |
check line decrement |
||
.,E85E 88 DEY |
DEY |
Zähler erniedrigen |
decrement the cursor column |
one position left |
||
.,E85F 84 D3 STY $D3 |
STY PNTR |
Cursorspalte |
save the cursor column |
store in PNTR |
||
.,E861 4C A8 E6 JMP $E6A8 |
JMP LOOP2 |
fertig |
restore the registers, set the quote flag and exit |
finish screen print |
||
.,E864 20 01 E7 JSR $E701 |
BAKBAK JSR BKLN |
Rückschritt in vorherige Zeile |
back onto the previous line if possible |
back to previous line |
||
.,E867 4C A8 E6 JMP $E6A8 |
JMP LOOP2 |
fertig |
restore the registers, set the quote flag and exit |
finish screen print |
||
.,E86A C9 13 CMP #$13 |
NXT61 CMP #$13 |
nicht 'CLR SCREEN' ?, |
compare with [CLR] |
<CLR>? |
clr code |
|
.,E86C D0 06 BNE $E874 |
BNE SCCL |
dann zu $E874 |
if not [CLR] continue |
nope |
||
.,E86E 20 44 E5 JSR $E544 |
JSR CLSR |
Bildschirm löschen |
clear the screen |
clear screen |
||
.,E871 4C A8 E6 JMP $E6A8 |
JPL2 JMP LOOP2 SCCL |
fertig |
restore the registers, set the quote flag and exit |
finish screen print |
||
.,E874 09 80 ORA #$80 |
ORA #$80 ;MAKE IT UPPER CASE |
Bit 7 wiederherstellen |
restore b7, colour can only be black, cyan, magenta or yellow |
|||
.,E876 20 CB E8 JSR $E8CB |
JSR CHKCOL ;TRY FOR COLOR |
auf Farbcode prüfen |
set the colour code |
set colour code |
||
.,E879 4C 4F EC JMP $EC4F |
JMP UPPER ;WAS JMP LOOP2 ; |
prüft auf Umschaltung Text/Grafik |
go check for special character codes except fro switch to lower case do newline |
set graphics/text modeGO TO NEXT LINEThe cursor is placed at the start of the next logicalscreen line. This involves moving down two lines for a linked line. If this places the cursor below the bottom of the screen, then the screen is scrolled. |
set next line number |
|
.,E87C 46 C9 LSR $C9 |
NXLN LSR LSXP |
Flag für Zeilenwechsel |
shift >> input cursor row |
LXSP, cursor X-Y position |
||
.,E87E A6 D6 LDX $D6 |
LDX TBLX |
Cursorzeilenzeiger |
get the cursor row |
TBLX, current line number |
||
.,E880 E8 INX |
NXLN2 INX |
Zeiger erhöhen |
increment the row |
next line |
||
.,E881 E0 19 CPX #$19 |
CPX #NLINES ;OFF BOTTOM? |
noch nicht letzte Zeile ?, |
compare it with last row + 1 |
26th line |
||
.,E883 D0 03 BNE $E888 |
BNE NXLN1 ;NO... |
dann zu $E888 |
if not last row + 1 skip the screen scroll |
nope, scroll is not needed |
||
.,E885 20 EA E8 JSR $E8EA |
JSR SCROL ;YES...SCROLL |
Bildschirm scrollen |
else scroll the screen |
scroll down |
||
.,E888 B5 D9 LDA $D9,X |
NXLN1 LDA LDTB1,X ;DOUBLE LINE? |
nächste Zeile, dann |
get start of line X pointer high byte |
test LTDB1, screen line link table if first of two |
||
.,E88A 10 F4 BPL $E880 |
BPL NXLN2 ;YES...SCROLL AGAIN |
wieder scrollen |
loop if not start of logical line |
yes, jump down another line |
||
.,E88C 86 D6 STX $D6 |
STX TBLX |
neue Zeile |
save the cursor row |
store in TBLX |
||
.,E88E 4C 6C E5 JMP $E56C |
JMP STUPT NXT1 |
Cursorposition berechnen |
set the screen pointers for cursor row, column and returnoutput [CR] |
set screen pointersOUTPUT <CARRIAGE RETURN>All editor modes are swithed off and the cursor placed atthe start of the next line. |
action for return |
|
.,E891 A2 00 LDX #$00 |
LDX #0 |
Einfüg- |
clear X |
|||
.,E893 86 D8 STX $D8 |
STX INSRT |
zähler löschen |
clear the insert count |
INSRT, disable insert mode |
||
.,E895 86 C7 STX $C7 |
STX RVS |
Flag für RVS löschen |
clear the reverse flag |
RVS, disable reversed mode |
||
.,E897 86 D4 STX $D4 |
STX QTSW |
Quote-Modus löschen |
clear the cursor quote flag, $xx = quote, $00 = no quote |
QTSW, disable quotes mode |
||
.,E899 86 D3 STX $D3 |
STX PNTR |
Cursor in erste Spalte |
save the cursor column |
PNTR, put cursor at first column |
||
.,E89B 20 7C E8 JSR $E87C |
JSR NXLN |
Zeile initialisieren |
do newline |
go to next line |
||
.,E89E 4C A8 E6 JMP $E6A8 |
JPL5 JMP LOOP2 ; ; ; CHECK FOR A DECREMENT TBLX ; |
fertig |
restore the registers, set the quote flag and exittest for line decrement |
finish screen printCHECK LINE DECREMENTWhen the cursor is at the beginning of a screen line, ifit is moved backwards, this routine places the cursor at the end of the line above. It tests both column 0 and column 40. |
move cursor to previous line ifat start of line |
|
.,E8A1 A2 02 LDX #$02 |
CHKBAK LDX #NWRAP |
maximale Zeilenanzahl |
set the count |
test if PNTR is at the first column |
||
.,E8A3 A9 00 LDA #$00 |
LDA #0 |
wenn Cursorspalte |
set the column |
yepp |
||
.,E8A5 C5 D3 CMP $D3 |
CHKLUP CMP PNTR |
gleich Akku, |
compare the column with the cursor column |
add $28 (40) |
||
.,E8A7 F0 07 BEQ $E8B0 |
BEQ BACK |
dann zu $E8B0 |
if at the start of the line go decrement the cursor row and exit |
to test if cursor is at line two in the logical line |
||
.,E8A9 18 CLC |
CLC |
40 addieren, |
else clear carry for add |
|||
.,E8AA 69 28 ADC #$28 |
ADC #LLEN |
eine Zeile |
increment to next line |
test two lines |
||
.,E8AC CA DEX |
DEX |
schon zweimal addiert ?, |
decrement loop count |
|||
.,E8AD D0 F6 BNE $E8A5 |
BNE CHKLUP |
ja, dann weiter |
loop if more to test |
decrement line number |
||
.,E8AF 60 RTS |
RTS ; |
Rücksprung |
||||
.,E8B0 C6 D6 DEC $D6 |
BACK DEC TBLX |
Zeiger auf Cursorzeile erniedrigen |
else decrement the cursor row |
|||
.,E8B2 60 RTS |
RTS ; ; CHECK FOR INCREMENT TBLX ; |
Rücksprung |
test for line incrementif at end of the line, but not at end of the last line, increment the cursor row |
CHECK LINE INCREMENTWhen the cursor is at the end of the screen, if it ismoved forward, this routine places the cursor at the start of the line below. |
move cursor to next line ifat end of line |
|
.,E8B3 A2 02 LDX #$02 |
CHKDWN LDX #NWRAP |
maximale Zeilenanzahl |
set the count |
start by testing position $27 (39) |
||
.,E8B5 A9 27 LDA #$27 |
LDA #LLEN-1 |
39, letzte Spalte |
set the column |
compare with PNTR |
||
.,E8B7 C5 D3 CMP $D3 |
DWNCHK CMP PNTR |
wenn Cursorspalte gleich |
compare the column with the cursor column |
brach if equal, and move cursor down |
||
.,E8B9 F0 07 BEQ $E8C2 |
BEQ DNLINE |
akku ?, dann zu $E8C2 |
if at end of line test and possibly increment cursor row |
else, add $28 to test next physical line |
||
.,E8BB 18 CLC |
CLC |
40 |
else clear carry for add |
|||
.,E8BC 69 28 ADC #$28 |
ADC #LLEN |
addieren |
increment to the next line |
two lines to test |
||
.,E8BE CA DEX |
DEX |
schon zweimal ?, |
decrement the loop count |
|||
.,E8BF D0 F6 BNE $E8B7 |
BNE DWNCHK |
ja, dann weiter |
loop if more to test |
return here without moving cursor down |
||
.,E8C1 60 RTS |
RTS ; |
Rücksprung |
cursor is at end of line |
get TBLX |
||
.,E8C2 A6 D6 LDX $D6 |
DNLINE LDX TBLX |
wenn Cursorzeile |
get the cursor row |
and test if at the 25th line |
||
.,E8C4 E0 19 CPX #$19 |
CPX #NLINES |
gleich 25, |
compare it with the end of the screen |
yepp, return without moving down |
||
.,E8C6 F0 02 BEQ $E8CA |
BEQ DWNBYE |
dann fertig |
if at the end of screen just exit |
increment TBLX |
||
.,E8C8 E6 D6 INC $D6 |
INC TBLX ; |
Zeiger auf Cursorzeile erhöhen |
else increment the cursor row |
|||
.,E8CA 60 RTS |
DWNBYE RTS CHKCOL |
Rücksprungprüft auf Farbcodes |
set the colour code. enter with the colour character in A. if A does not contain acolour character this routine exits without changing the colour |
SET COLOUR CODEThis routine is called by the output to screen routine.The Commodore ASCII code in (A) is compared with the ASCII colout code table. If a match is found, then the table offset (and hence the colour value) is stored in COLOR. |
check for colour change codes |
|
.,E8CB A2 0F LDX #$0F |
LDX #15 ;THERE'S 15 COLORS |
Anzahl der Kodes |
set the colour code count |
16 values to be tested |
||
.,E8CD DD DA E8 CMP $E8DA,X |
CHK1A CMP COLTAB,X |
mit Farbcodetabelle vergleichen |
compare the character with a table code |
compare with colour code table |
||
.,E8D0 F0 04 BEQ $E8D6 |
BEQ CHK1B |
wenn gefunden, dann farbe setzen |
if a match go save the colour and exit |
found, jump |
||
.,E8D2 CA DEX |
DEX |
nächster Farbcode |
else decrement the index |
next colour in table |
||
.,E8D3 10 F8 BPL $E8CD |
BPL CHK1A |
schon alle ? |
loop if more to do |
till all 16 are tested |
||
.,E8D5 60 RTS |
RTS ; CHK1B |
Rücksprung |
if not found, return |
|||
.,E8D6 8E 86 02 STX $0286 |
STX COLOR ;CHANGE THE COLOR |
Farbcode setzen |
save the current colour code |
if found, store code in COLOR |
||
.,E8D9 60 RTS |
RTS COLTAB ;BLK,WHT,RED,CYAN,MAGENTA,GRN,BLUE,YELLOW |
RücksprungTabelle der Farb-Kodes |
ASCII colour code tableCHR$() colour------ ------ |
COLOUR CODE TABLEThis is a table containing 16 Commodore ASCII codesrepresenting the 16 available colours. Thus red is represented as $1c in the table, and would be obtained by PRINT CHR$(28), or poke 646,2. |
colour key codes |
|
.:E8DA 90 05 1C 9F 9C 1E 1F 9E |
.BYT $90,$05,$1C,$9F,$9C,$1E,$1F,$9E |
144 black |
color0, black |
|||
.:E8E2 81 95 96 97 98 99 9A 9B |
.BYT $81,$95,$96,$97,$98,$99,$9A,$9B .END ;.LIB CONKAT (JAPAN CONVERSION TABLES) .LIB EDITOR.2;SCREEN SCROLL ROUTINE; |
Bildschirm scrollen |
5 white 28 red 159 cyan 156 purple 30 green 31 blue 158 yellow 129 orange |
color1, white color2, red color3, cyan color4, purple color5, green color6, blue color7, yellow color8, orange |
scroll screen |
|
.,E8EA A5 AC LDA $AC |
SCROL LDA SAL |
Alle |
149 brown 150 light red 151 dark grey 152 medium grey 153 light green 154 light blue 155 light grey scroll the screencopy the tape buffer start pointer |
color9, brown colorA, pink colorB, grey1 colorC, grey2 colorD, light green colorE, light blue colorF, grey3 SCROLL SCREENThis routine scrolls the screen down by one line. If thetop two lines are linked togeather, then the scroll down is repeated. The screen line link pointers are updated, each screen line is cleared and the line below is moved up. The keyboard is directly read from CIA#1, and the routine tests if <CTRL> is pressed. temp store SAL on stack |
||
.,E8EC 48 PHA |
PHA |
wichtigen |
save it |
|||
.,E8ED A5 AD LDA $AD |
LDA SAH |
Zeiger |
copy the tape buffer start pointer |
|||
.,E8EF 48 PHA |
PHA |
in |
save it |
|||
.,E8F0 A5 AE LDA $AE |
LDA EAL |
den |
copy the tape buffer end pointer |
temp store EAL on stack |
||
.,E8F2 48 PHA |
PHA |
Stack |
save it |
|||
.,E8F3 A5 AF LDA $AF |
LDA EAH |
schie- |
copy the tape buffer end pointer |
|||
.,E8F5 48 PHA |
PHA ; ; S C R O L L U P ; |
ben |
save it |
|||
.,E8F6 A2 FF LDX #$FF |
SCRO0 LDX #$FF |
ab Zeile Null beginnen |
set to -1 for pre increment loop |
|||
.,E8F8 C6 D6 DEC $D6 |
DEC TBLX |
Cursorzeiger |
decrement the cursor row |
decrement TBLX |
||
.,E8FA C6 C9 DEC $C9 |
DEC LSXP |
erniedrigen |
decrement the input cursor row |
decrement LXSP |
||
.,E8FC CE A5 02 DEC $02A5 |
DEC LINTMP |
Fortsetzungszeile erniedrigen |
decrement the screen row marker |
temp store for line index |
||
.,E8FF E8 INX |
SCR10 INX ;GOTO NEXT LINE |
Zeilennummer erhöhen |
increment the line number |
|||
.,E900 20 F0 E9 JSR $E9F0 |
JSR SETPNT ;POINT TO 'TO' LINE |
Zeiger auf Video-RAM für Zeile X |
fetch a screen address, set the start of line X |
set start of line (X) |
||
.,E903 E0 18 CPX #$18 |
CPX #NLINES-1 ;DONE? |
24 |
compare with last line |
|||
.,E905 B0 0C BCS $E913 |
BCS SCR41 ;BRANCH IF SO ; |
schon alle Zeilen ? |
branch if >= $16 |
|||
.,E907 BD F1 EC LDA $ECF1,X |
LDA LDTB2+1,X ;SETUP FROM PNTR |
LOW-Byte holen |
get the start of the next line pointer low byte |
read low-byte screen addresses |
||
.,E90A 85 AC STA $AC |
STA SAL |
und speichern |
save the next line pointer low byte |
|||
.,E90C B5 DA LDA $DA,X |
LDA LDTB1+1,X |
HIGH-Byte |
get the start of the next line pointer high byte |
|||
.,E90E 20 C8 E9 JSR $E9C8 |
JSR SCRLIN ;SCROLL THIS LINE UP1 |
Bildschirmzeile nach oben schieben |
shift the screen line up |
move a screen line |
||
.,E911 30 EC BMI $E8FF |
BMI SCR10 ; SCR41 |
nächste Zeile |
loop, branch always |
|||
.,E913 20 FF E9 JSR $E9FF |
JSR CLRLN ; |
unterste Bildschirmzeile löschen |
clear screen line X now shift up the start of logical line bits |
clear a screen line |
||
.,E916 A2 00 LDX #$00 |
LDX #0 ;SCROLL HI BYTE POINTERS |
HIGH- |
clear index |
|||
.,E918 B5 D9 LDA $D9,X |
SCRL5 LDA LDTB1,X |
Bytes |
get the start of line X pointer high byte |
calcuate new screen line link table |
||
.,E91A 29 7F AND #$7F |
AND #$7F |
und |
clear the line X start of logical line bit |
clear bit7 |
||
.,E91C B4 DA LDY $DA,X |
LDY LDTB1+1,X |
die |
get the start of the next line pointer high byte |
|||
.,E91E 10 02 BPL $E922 |
BPL SCRL3 |
Doppel- |
if next line is not a start of line skip the start set |
|||
.,E920 09 80 ORA #$80 |
ORA #$80 |
zeilen |
set line X start of logical line bit |
set bit7 |
||
.,E922 95 D9 STA $D9,X |
SCRL3 STA LDTB1,X |
ver- |
set start of line X pointer high byte |
store new value in table |
||
.,E924 E8 INX |
INX |
schieben |
increment line number |
next line |
||
.,E925 E0 18 CPX #$18 |
CPX #NLINES-1 |
nicht 24 ?, |
compare with last line |
till all 25 are done |
||
.,E927 D0 EF BNE $E918 |
BNE SCRL5 ; |
dann nochmal |
loop if not last line |
|||
.,E929 A5 F1 LDA $F1 |
LDA LDTB1+NLINES-1 |
Zeile |
get start of last line pointer high byte |
bottom line link |
||
.,E92B 09 80 ORA #$80 |
ORA #$80 |
als einfache Zeile |
mark as start of logical line |
unlink it |
||
.,E92D 85 F1 STA $F1 |
STA LDTB1+NLINES-1 |
auszeichnen |
set start of last line pointer high byte |
and store back |
||
.,E92F A5 D9 LDA $D9 |
LDA LDTB1 ;DOUBLE LINE? |
wenn Fortsetzungszeile, |
get start of first line pointer high byte |
test top line link |
||
.,E931 10 C3 BPL $E8F6 |
BPL SCRO0 ;YES...SCROLL AGAIN ; |
dann nochmal |
if not start of logical line loop back and scroll the screen up another line |
line is linked, scroll again |
||
.,E933 E6 D6 INC $D6 |
INC TBLX |
Zeiger auf Cursor erhöhen |
increment the cursor row |
increment TBLX |
||
.,E935 EE A5 02 INC $02A5 |
INC LINTMP |
Fortsetzungszeile erhöhen |
increment screen row marker |
|||
.,E938 A9 7F LDA #$7F |
LDA #$7F ;CHECK FOR CONTROL KEY |
Kode |
set keyboard column c7 |
|||
.,E93A 8D 00 DC STA $DC00 |
STA COLM ;DROP LINE 2 ON PORT B |
für |
save VIA 1 DRA, keyboard column drive |
|||
.,E93D AD 01 DC LDA $DC01 |
LDA ROWS |
Tastaturabfrage |
read VIA 1 DRB, keyboard row port |
read keyboard decode column |
||
.,E940 C9 FB CMP #$FB |
CMP #$FB ;SLOW SCROLL KEY?(CONTROL) |
CTRL-Taste gedrückt ? |
compare with row r2 active, [CTL] |
<CTRL> pressed |
||
.,E942 08 PHP |
PHP ;SAVE STATUS. RESTORE PORT B |
Statusregister retten |
save status |
|||
.,E943 A9 7F LDA #$7F |
LDA #$7F ;FOR STOP KEY CHECK |
code für |
set keyboard column c7 |
|||
.,E945 8D 00 DC STA $DC00 |
STA COLM |
Tastaturabfrage |
save VIA 1 DRA, keyboard column drive |
|||
.,E948 28 PLP |
PLP |
Statusregister holen |
restore status |
|||
.,E949 D0 0B BNE $E956 |
BNE MLP42 ; |
nicht gedrückt ? |
skip delay if ?? first time round the inner loop X will be $16 |
nope, exit |
||
.,E94B A0 00 LDY #$00 |
LDY #0 |
Ver- |
clear delay outer loop count, do this 256 times |
|||
.,E94D EA NOP |
MLP4 NOP ;DELAY |
zö- |
waste cycles |
|||
.,E94E CA DEX |
DEX |
geru- |
decrement inner loop count |
|||
.,E94F D0 FC BNE $E94D |
BNE MLP4 |
ngs- |
loop if not all done |
|||
.,E951 88 DEY |
DEY |
sch- |
decrement outer loop count |
|||
.,E952 D0 F9 BNE $E94D |
BNE MLP4 |
leife |
loop if not all done |
|||
.,E954 84 C6 STY $C6 |
STY NDX ;CLEAR KEY QUEUE BUFFER ; |
Anzahl der gedrückten Tasten gleich null |
clear the keyboard buffer index |
clear NDX |
||
.,E956 A6 D6 LDX $D6 |
MLP42 LDX TBLX ; |
alle |
get the cursor row restore the tape buffer pointers and exit |
read TBLX |
||
.,E958 68 PLA |
PULIND PLA ;RESTORE OLD INDIRECTS |
benö- |
pull tape buffer end pointer |
retrieve EAL |
||
.,E959 85 AF STA $AF |
STA EAH |
tigten |
restore it |
|||
.,E95B 68 PLA |
PLA |
Zei- |
pull tape buffer end pointer |
|||
.,E95C 85 AE STA $AE |
STA EAL |
ger |
restore it |
|||
.,E95E 68 PLA |
PLA |
zu- |
pull tape buffer pointer |
retrieve SAL |
||
.,E95F 85 AD STA $AD |
STA SAH |
rück- |
restore it |
|||
.,E961 68 PLA |
PLA |
ho- |
pull tape buffer pointer |
|||
.,E962 85 AC STA $AC |
STA SAL |
len |
restore it |
|||
.,E964 60 RTS |
RTS NEWLIN |
RücksprungEinfügen einerFortsetzungszeile |
open up a space on the screen |
exitOPEN A SPACE ON THE SCREENThis routine opens a space on the screen for use with<INST>. If needed, the screen is then scrolled down, otherwise the screen line is moved and cleared. Finally the screen line link table is adjusted and updated. |
insert blank line in screen |
|
.,E965 A6 D6 LDX $D6 |
LDX TBLX |
Zeiger auf Cursorzeile |
get the cursor row |
TBLX, current cursor line number |
||
.,E967 E8 INX |
BMT1 INX ; CPX #NLINES ;EXCEDED THE NUMBER OF LINES ??? ; BEQ BMT2 ;VIC-40 CODE |
Zeiger erhöhen |
increment the row |
test next |
||
.,E968 B5 D9 LDA $D9,X |
LDA LDTB1,X ;FIND LAST DISPLAY LINE OF THIS LINE |
untere Zeile gleich |
get the start of line X pointer high byte |
LDTB1, screen line link table |
||
.,E96A 10 FB BPL $E967 |
BPL BMT1 ;TABLE END MARK=>$FF WILL ABORT...ALSO |
Cursorzeile, dann zu $E967 |
loop if not start of logical line |
|||
.,E96C 8E A5 02 STX $02A5 |
BMT2 STX LINTMP ;FOUND IT ;GENERATE A NEW LINE |
Zeilennummer |
save the screen row marker |
temp line for index |
||
.,E96F E0 18 CPX #$18 |
CPX #NLINES-1 ;IS ONE LINE FROM BOTTOM? |
gleich |
compare it with the last line |
bottom of screen |
||
.,E971 F0 0E BEQ $E981 |
BEQ NEWLX ;YES...JUST CLEAR LAST |
24 |
if = last line go ?? |
yes |
||
.,E973 90 0C BCC $E981 |
BCC NEWLX ;<NLINES...INSERT LINE |
dann zu $E981 |
if < last line go ?? else it was > last line |
above bottom line |
||
.,E975 20 EA E8 JSR $E8EA |
JSR SCROL ;SCROLL EVERYTHING |
Bildschirm scrollen |
scroll the screen |
scroll screen down |
||
.,E978 AE A5 02 LDX $02A5 |
LDX LINTMP |
Zeilennummer |
get the screen row marker |
temp line for index |
||
.,E97B CA DEX |
DEX |
erniedrigen |
decrement the screen row marker |
|||
.,E97C C6 D6 DEC $D6 |
DEC TBLX |
Zeiger auf Cursorzeile erniedrigen |
decrement the cursor row |
TBLX |
||
.,E97E 4C DA E6 JMP $E6DA |
JMP WLOG30 |
Zeile initialisieren |
add this row to the current logical line and return |
adjust link table and end |
||
.,E981 A5 AC LDA $AC |
NEWLX LDA SAL |
Alle |
copy tape buffer pointer |
push SAL, scrolling pointer |
||
.,E983 48 PHA |
PHA |
benötigten |
save it |
|||
.,E984 A5 AD LDA $AD |
LDA SAH |
Zeiger |
copy tape buffer pointer |
|||
.,E986 48 PHA |
PHA |
in |
save it |
|||
.,E987 A5 AE LDA $AE |
LDA EAL |
den |
copy tape buffer end pointer |
push EAL, end of program |
||
.,E989 48 PHA |
PHA |
Stack |
save it |
|||
.,E98A A5 AF LDA $AF |
LDA EAH |
schie- |
copy tape buffer end pointer |
|||
.,E98C 48 PHA |
PHA |
ben |
save it |
|||
.,E98D A2 19 LDX #$19 |
LDX #NLINES |
25 |
set to end line + 1 for predecrement loop |
|||
.,E98F CA DEX |
SCD10 DEX |
Zeilennummer |
decrement the line number |
|||
.,E990 20 F0 E9 JSR $E9F0 |
JSR SETPNT ;SET UP TO ADDR |
Zeilen-Zeiger berechnen |
fetch a screen address |
set start of line |
||
.,E993 EC A5 02 CPX $02A5 |
CPX LINTMP |
alle Zeilen verschoben ?, |
compare it with the screen row marker |
temp line for index |
||
.,E996 90 0E BCC $E9A6 |
BCC SCR40 |
wenn ja, |
if < screen row marker go ?? |
|||
.,E998 F0 0C BEQ $E9A6 |
BEQ SCR40 ;BRANCH IF FINISHED |
dann zu $E9A6 |
if = screen row marker go ?? |
|||
.,E99A BD EF EC LDA $ECEF,X |
LDA LDTB2-1,X ;SET FROM ADDR |
LOW-Byte des Zeilenanfangs |
else get the start of the previous line low byte from the ROM table |
screen line address table |
||
.,E99D 85 AC STA $AC |
STA SAL |
setzen |
save previous line pointer low byte |
SAL |
||
.,E99F B5 D8 LDA $D8,X |
LDA LDTB1-1,X |
HIGH-Byte setzen |
get the start of the previous line pointer high byte |
LDTB1 |
||
.,E9A1 20 C8 E9 JSR $E9C8 |
JSR SCRLIN ;SCROLL THIS LINE DOWN |
Zeile nach oben schieben |
shift the screen line down |
move screen line |
||
.,E9A4 30 E9 BMI $E98F |
BMI SCD10 SCR40 |
Unbedingter Sprung |
loop, branch always |
|||
.,E9A6 20 FF E9 JSR $E9FF |
JSR CLRLN |
Bildschirmzeile löschen |
clear screen line X |
clear screen line |
||
.,E9A9 A2 17 LDX #$17 |
LDX #NLINES-2 SCRD21 |
HIGH-Byte-Tabelle |
fix screen line link table |
|||
.,E9AB EC A5 02 CPX $02A5 |
CPX LINTMP ;DONE? |
verschieben |
compare it with the screen row marker |
temp line for index |
||
.,E9AE 90 0F BCC $E9BF |
BCC SCRD22 ;BRANCH IF SO |
alles verschoben ? |
||||
.,E9B0 B5 DA LDA $DA,X |
LDA LDTB1+1,X |
HIGH- |
LDTB1+1 |
|||
.,E9B2 29 7F AND #$7F |
AND #$7F |
Byte- |
||||
.,E9B4 B4 D9 LDY $D9,X |
LDY LDTB1,X ;WAS IT CONTINUED |
und |
get start of line X pointer high byte |
LDTB1 |
||
.,E9B6 10 02 BPL $E9BA |
BPL SCRD19 ;BRANCH IF SO |
Doppelzeilen- |
||||
.,E9B8 09 80 ORA #$80 |
ORA #$80 |
Tabelle |
||||
.,E9BA 95 DA STA $DA,X |
SCRD19 STA LDTB1+1,X |
nach |
||||
.,E9BC CA DEX |
DEX |
unten schieben |
next line |
|||
.,E9BD D0 EC BNE $E9AB |
BNE SCRD21 SCRD22 |
schon alles ? |
till line zero |
|||
.,E9BF AE A5 02 LDX $02A5 |
LDX LINTMP |
Zeilennummer |
get the screen row marker |
temp line for index |
||
.,E9C2 20 DA E6 JSR $E6DA |
JSR WLOG30 ; |
MSB neu berechnen |
add this row to the current logical line |
adjust link table |
||
.,E9C5 4C 58 E9 JMP $E958 |
JMP PULIND ;GO PUL OLD INDIRECTS AND RETURN ; ; SCROLL LINE FROM SAL TO PNT ; AND COLORS FROM EAL TO USER ; SCRLIN |
Register zurückholen, RTSZeile nach oben schieben |
restore the tape buffer pointers and exitshift screen line up/down |
pull SAL and EALMOVE A SCREEN LINEThis routine synchronises colour transfer, and then movesthe screen line pointed to down, character by character. The colour codes for each character are also moved in the same way. |
move one screen line |
|
.,E9C8 29 03 AND #$03 |
AND #$03 ;CLEAR ANY GARBAGE STUFF |
Bildschirmzeiger |
mask 0000 00xx, line memory page |
|||
.,E9CA 0D 88 02 ORA $0288 |
ORA HIBASE ;PUT IN HIORDER BITS |
für neue Zeile |
OR with screen memory page |
HIBASE, top of screen page |
||
.,E9CD 85 AD STA $AD |
STA SAL+1 |
berechnen |
save next/previous line pointer high byte |
store >SAL, screen scroll pointer |
||
.,E9CF 20 E0 E9 JSR $E9E0 |
JSR TOFROM ;COLOR TO & FROM ADDRS |
Zeiger für neue Zeile berechnen |
calculate pointers to screen lines colour RAM |
synchronise colour transfer |
||
.,E9D2 A0 27 LDY #$27 |
LDY #LLEN-1 SCD20 |
39 Zeichen |
set the column count |
offset for character on screen line |
||
.,E9D4 B1 AC LDA ($AC),Y |
LDA (SAL)Y |
alle |
get character from next/previous screen line |
move screen character |
||
.,E9D6 91 D1 STA ($D1),Y |
STA (PNT)Y |
Zeichen |
save character to current screen line |
|||
.,E9D8 B1 AE LDA ($AE),Y |
LDA (EAL)Y |
und |
get colour from next/previous screen line colour RAM |
move character colour |
||
.,E9DA 91 F3 STA ($F3),Y |
STA (USER)Y |
Farbe übertragen |
save colour to current screen line colour RAM |
|||
.,E9DC 88 DEY |
DEY |
nächstes Zeichen |
decrement column index/count |
next character |
||
.,E9DD 10 F5 BPL $E9D4 |
BPL SCD20 |
schon alle ? |
loop if more to do |
till all 40 are done |
||
.,E9DF 60 RTS |
RTS ; ; DO COLOR TO AND FROM ADDRESSES ; FROM CHARACTER TO AND FROM ADRS ; TOFROM |
RücksprungBildschirmzeile fürScrollzeile berechnen |
calculate pointers to screen lines colour RAM |
SYNCHRONISE COLOUR TRANSFERThis routine setd up a temporary pointer in EAL to thecolour RAM address that corresponts to the temporary screen address held in EAL. |
set colour and screen addresses |
|
.,E9E0 20 24 EA JSR $EA24 |
JSR SCOLOR |
Zeiger auf Farb-RAM berechnen |
calculate the pointer to the current screen line colour RAM |
synchronise colour pointer |
||
.,E9E3 A5 AC LDA $AC |
LDA SAL ;CHARACTER FROM |
Zeiger |
get the next screen line pointer low byte |
SAL, pointer for screen scroll |
||
.,E9E5 85 AE STA $AE |
STA EAL ;MAKE COLOR FROM |
für Zeile |
save the next screen line colour RAM pointer low byte |
EAL |
||
.,E9E7 A5 AD LDA $AD |
LDA SAL+1 |
speichern |
get the next screen line pointer high byte |
|||
.,E9E9 29 03 AND #$03 |
AND #$03 |
Startadresse |
mask 0000 00xx, line memory page |
|||
.,E9EB 09 D8 ORA #$D8 |
ORA #>VICCOL |
des Video-RAM |
set 1101 01xx, colour memory page |
setup colour ram to $d800 |
||
.,E9ED 85 AF STA $AF |
STA EAL+1 |
berechnen |
save the next screen line colour RAM pointer high byte |
|||
.,E9EF 60 RTS |
RTS ; ; SET UP PNT AND Y ; FROM .X ; |
RücksprungZeiger auf Video-RAM fürZeile X |
fetch a screen address |
SET START OF LINEOn entry, (X) holds the line number. The low byte of theaddress is set from the ROM table, and the highbyte derived from the screen link and HIBASE. |
fetch screen addresses |
|
.,E9F0 BD F0 EC LDA $ECF0,X |
SETPNT LDA LDTB2,X |
LOW-Byte |
get the start of line low byte from the ROM table |
table of screen line to bytes |
||
.,E9F3 85 D1 STA $D1 |
STA PNT |
holen |
set the current screen line pointer low byte |
<PNT, current screen line address |
||
.,E9F5 B5 D9 LDA $D9,X |
LDA LDTB1,X |
HIGH-Byte |
get the start of line high byte from the RAM table |
LDTB1, screen line link table |
||
.,E9F7 29 03 AND #$03 |
AND #$03 |
des |
mask 0000 00xx, line memory page |
|||
.,E9F9 0D 88 02 ORA $0288 |
ORA HIBASE |
Video- |
OR with the screen memory page |
HIBASE, page of top screen |
||
.,E9FC 85 D2 STA $D2 |
STA PNT+1 |
RAM |
save the current screen line pointer high byte |
>PNT |
||
.,E9FE 60 RTS |
RTS ; ; CLEAR THE LINE POINTED TO BY .X ; |
RücksprungBildschirmzeile X löschen |
clear screen line X |
CLEAR SCREEN LINEThe start of line is set and the screen line is cleared byfilloing it with ASCII spaces. The corresponding line of colour RAM is also cleared to the value held in COLOR. |
clear one screen line |
|
.,E9FF A0 27 LDY #$27 |
CLRLN LDY #LLEN-1 |
40-1 Spalten |
set number of columns to clear |
|||
.,EA01 20 F0 E9 JSR $E9F0 |
JSR SETPNT |
Zeilenpointer (D1/D2) setzen |
fetch a screen address |
set start of line |
||
.,EA04 20 24 EA JSR $EA24 |
JSR SCOLOR |
Pointer (F3/F4) für Farb-RAM berechnen |
calculate the pointer to colour RAM |
synchronise colour pointer |
||
.,EA07 A9 20 LDA #$20 |
CLR10 JSR CPATCH ;REVERSED ORDER FROM 901227-02 |
Leerzeichen |
save the current colour to the colour RAM |
reset character colour, to COLOR |
||
.,EA09 91 D1 STA ($D1),Y |
ins Video-RAM schreiben |
|||||
.,EA0B 20 DA E4 JSR $E4DA |
LDA #$20 ;STORE A SPACE |
Hintergrundfarbe setzen |
set [SPACE] |
ASCII space |
||
.,EA0E EA NOP |
STA (PNT)Y ;TO DISPLAY DEY |
clear character in current screen line decrement index |
store character on screen next |
|||
.,EA0F 88 DEY |
BPL CLR10 |
schon 40 Zeichen gelöscht? |
loop if more to do |
till hole line is done |
||
.,EA10 10 F5 BPL $EA07 |
wenn nicht, fortfahren |
|||||
.,EA12 60 RTS |
RTS NOP ; ;PUT A CHAR ON THE SCREEN ; |
Rücksprung zum Hauptprogramm |
orphan byteunusedprint character A and colour X |
free bytePRINT TO SCREENThe colour pointer is synchronised, and the character in(A) directly stored in the screen RAM. The character colour in (X) is stored at the equivalent point in the colour RAM. |
set cursor flash timing and colour memory addresses |
|
.,EA13 A8 TAY |
DSPP TAY ;SAVE CHAR |
Akku retten |
copy the character |
put print character in (Y) |
||
.,EA14 A9 02 LDA #$02 |
LDA #2 |
count to $02, usually $14 ?? |
||||
.,EA16 85 CD STA $CD |
STA BLNCT ;BLINK CURSOR |
Blinkzähler bei Repeatfunktion setzen |
save the cursor countdown |
store in BLNCT, timer to toggle cursor |
||
.,EA18 20 24 EA JSR $EA24 |
JSR SCOLOR ;SET COLOR PTR |
Pointer für Farb-RAM berechnen |
calculate the pointer to colour RAM |
synchronise colour pointer |
||
.,EA1B 98 TYA |
TYA ;RESTORE COLOR |
Akku wieder holenZeichen und Farbe aufBildschirm setzen |
get the character backsave the character and colour to the screen @ the cursor |
print character back to (A) |
put a char on the screen |
|
.,EA1C A4 D3 LDY $D3 |
DSPP2 LDY PNTR ;GET COLUMN |
Spaltenposition |
get the cursor column |
PNTR, cursor column on line |
||
.,EA1E 91 D1 STA ($D1),Y |
STA (PNT)Y ;CHAR TO SCREEN |
Zeichen in Akku auf Bildschirm |
save the character from current screen line |
store character on screen |
||
.,EA20 8A TXA |
TXA |
Farb-Code von x in Akku |
copy the colour to A |
|||
.,EA21 91 F3 STA ($F3),Y |
STA (USER)Y ;COLOR TO SCREEN |
in Farb-RAM schreiben |
save to colour RAM |
stor character colour |
||
.,EA23 60 RTS |
RTS |
Rücksprung zum HauptprogrammZeiger auf Farb-RAM berechnen |
calculate the pointer to colour RAM |
SYNCHRONISE COLOUR POINTERThe pointer to the colour RAM is set up according to thecurrent screen line address. This is done by reading the current screen line address and modefying it to colour RAM pointers and write it to USER at $f3/$f4 |
set colour memory adress parallel to screen |
|
.,EA24 A5 D1 LDA $D1 |
SCOLOR LDA PNT ;GENERATE COLOR PTR |
$D1/$D2 = Zeiger auf Video-RAM-Position |
get current screen line pointer low byte |
copy screen line low byte |
||
.,EA26 85 F3 STA $F3 |
STA USER |
LOW-Byte auf Zeichenposition = LOW-Byte auf Farbposition |
save pointer to colour RAM low byte |
to colour RAM low byte |
||
.,EA28 A5 D2 LDA $D2 |
LDA PNT+1 |
HIGH-Byte der Zeichenposition |
get current screen line pointer high byte |
read'n modify the hi byte |
||
.,EA2A 29 03 AND #$03 |
AND #$03 |
mit HIGH-Byte der Farb-RAM- |
mask 0000 00xx, line memory page |
|||
.,EA2C 09 D8 ORA #$D8 |
ORA #>VICCOL ;VIC COLOR RAM |
Position = $D8 verknüpfen und |
set 1101 01xx, colour memory page |
|||
.,EA2E 85 F4 STA $F4 |
STA USER+1 |
in $F4 = speichern |
save pointer to colour RAM high byte |
to suite the colour RAM |
||
.,EA30 60 RTS |
RTS |
Rücksprung zum HauptprogrammInterrupt-Routine |
IRQ vector |
MAIN IRQ ENTRY POINTThis routine services the normal IRQ that jumps throughthe hardware vector to $ff48, and then continues to the CINV vector at $0314. First it checks if the <STOP> key was pressed and updates the realtime clock. Next, the cursor is updated (if it is enabled, BLNSW). The blink counter, BLNCT, is decremented. When this reaches zero, the cursor is toggled (blink on/off). Finally it scans the keyboard. The processor registers are then restored on exit. |
normal IRQ interrupt |
|
.,EA31 20 EA FF JSR $FFEA |
KEY JSR $FFEA ;UPDATE JIFFY CLOCK |
Stop-Taste, Zeit erhöhen |
increment the real time clock |
update realtime clock, routine UDTIM |
do clock |
|
.,EA34 A5 CC LDA $CC |
LDA BLNSW ;BLINKING CRSR ? |
Blink-Flag für Cursor |
get the cursor enable, $00 = flash cursor |
read BLNSW to see if cursor is enabled |
flash cursor |
|
.,EA36 D0 29 BNE $EA61 |
BNE KEY4 ;NO |
nicht blinkend, dann weiter |
if flash not enabled skip the flash |
nope |
||
.,EA38 C6 CD DEC $CD |
DEC BLNCT ;TIME TO BLINK ? |
Blinkzähler erniedrigen |
decrement the cursor timing countdown |
read BLNCT |
||
.,EA3A D0 25 BNE $EA61 |
BNE KEY4 ;NO |
nicht Null, dann weiter |
if not counted out skip the flash |
if zero, toggle cursor - else jump |
||
.,EA3C A9 14 LDA #$14 |
LDA #20 ;RESET BLINK COUNTER |
Blinkzähler wieder auf 20 setzen |
set the flash count |
blink speed |
||
.,EA3E 85 CD STA $CD |
REPDO STA BLNCT |
und speichern |
save the cursor timing countdown |
restore BLCNT |
||
.,EA40 A4 D3 LDY $D3 |
LDY PNTR ;CURSOR POSITION |
Cursorspalte |
get the cursor column |
get PNTR, cursor column |
||
.,EA42 46 CF LSR $CF |
LSR BLNON ;CARRY SET IF ORIGINAL CHAR |
Blinkschalter eins dann C=1 |
shift b0 cursor blink phase into carry |
BLNON, flag last cursor blink on/off |
||
.,EA44 AE 87 02 LDX $0287 |
LDX GDCOL ;GET CHAR ORIGINAL COLOR |
Farbe unter Cursor |
get the colour under the cursor |
get background colour under cursor, GDCOL |
||
.,EA47 B1 D1 LDA ($D1),Y |
LDA (PNT)Y ;GET CHARACTER |
Zeichen-Kode holen |
get the character from current screen line |
get screen character |
||
.,EA49 B0 11 BCS $EA5C |
BCS KEY5 ;BRANCH IF NOT NEEDED ; |
Blinkschalter war ein, dann weiter |
branch if cursor phase b0 was 1 |
? |
||
.,EA4B E6 CF INC $CF |
INC BLNON ;SET TO 1 |
Blinkschalter ein |
set the cursor blink phase to 1 |
increment BLNON |
||
.,EA4D 85 CE STA $CE |
STA GDBLN ;SAVE ORIGINAL CHAR |
Zeichen unter Cursor merken |
save the character under the cursor |
temporary store character under cursor |
||
.,EA4F 20 24 EA JSR $EA24 |
JSR SCOLOR |
Zeiger in Farb-RAM berechnen |
calculate the pointer to colour RAM |
synchronise colour pointer |
||
.,EA52 B1 F3 LDA ($F3),Y |
LDA (USER)Y ;GET ORIGINAL COLOR |
Farb-Code holen |
get the colour RAM byte |
get colour under character |
||
.,EA54 8D 87 02 STA $0287 |
STA GDCOL ;SAVE IT |
und merken |
save the colour under the cursor |
store in GDCOL |
||
.,EA57 AE 86 02 LDX $0286 |
LDX COLOR ;BLINK IN THIS COLOR |
Farb-Code unter Cursor |
get the current colour code |
get current COLOR |
||
.,EA5A A5 CE LDA $CE |
LDA GDBLN ;WITH ORIGINAL CHARACTER ; |
Zeichen unter Cursor holen |
get the character under the cursor |
retrieve character under cursor |
||
.,EA5C 49 80 EOR #$80 |
KEY5 EOR #$80 ;BLINK IT |
RVS-Bit umdrehen |
toggle b7 of character under cursor |
toggle cursor by inverting character |
||
.,EA5E 20 1C EA JSR $EA1C |
JSR DSPP2 ;DISPLAY IT ; |
Zeichen und Farbe setzen |
save the character and colour to the screen @ the cursor |
print to screen by using part of 'print to screen' |
display cursor |
|
.,EA61 A5 01 LDA $01 |
KEY4 LDA R6510 ;GET CASSETTE SWITCHES |
Prozessorport laden |
read the 6510 I/O port |
checl cassette sense |
||
.,EA63 29 10 AND #$10 |
AND #$10 ;IS SWITCH DOWN ? |
prüft Rekorder-Taste |
mask 000x 0000, the cassette switch sense |
|||
.,EA65 F0 0A BEQ $EA71 |
BEQ KEY3 ;BRANCH IF SO ; |
gedrückt, dann verzweige |
if the cassette sense is low skip the motor stop the cassette sense was high, the switch was open, so turn off the motor and clear the interlock |
|||
.,EA67 A0 00 LDY #$00 |
LDY #0 |
Wert für keine Taste gedrückt |
clear Y |
|||
.,EA69 84 C0 STY $C0 |
STY CAS1 ;CASSETTE OFF SWITCH ; |
Rekorder-Flag setzen |
clear the tape motor interlock |
|||
.,EA6B A5 01 LDA $01 |
LDA R6510 |
Prozessorport laden |
read the 6510 I/O port |
|||
.,EA6D 09 20 ORA #$20 |
ORA #$20 |
Rekoder-Motor ausschalten |
mask xxxx xx1x, turn off the motor |
|||
.,EA6F D0 08 BNE $EA79 |
BNE KL24 ;BRANCH IF MOTOR IS OFF ; |
unbedingter Sprung |
go save the port value, branch always the cassette sense was low so turn the motor on, perhaps |
|||
.,EA71 A5 C0 LDA $C0 |
KEY3 LDA CAS1 |
lade Rekorder-Flag |
get the tape motor interlock |
|||
.,EA73 D0 06 BNE $EA7B |
BNE KL2 ; |
verzweige, wenn Motor läuft |
if the cassette interlock <> 0 don't turn on motor |
|||
.,EA75 A5 01 LDA $01 |
LDA R6510 |
Prozessorport laden |
read the 6510 I/O port |
|||
.,EA77 29 1F AND #$1F |
AND #%011111 ;TURN MOTOR ON ; KL24 |
Rekorder-Motor einschalten |
mask xxxx xx0x, turn on the motor |
|||
.,EA79 85 01 STA $01 |
STA R6510 ; |
und wieder speichern |
save the 6510 I/O port |
|||
.,EA7B 20 87 EA JSR $EA87 |
KL2 JSR SCNKEY ;SCAN KEYBOARD ; |
Tastaturabfrage |
scan the keyboard |
scan keyboard |
scan keyboard |
|
.,EA7E AD 0D DC LDA $DC0D |
KPREND LDA D1ICR ;CLEAR INTERUPT FLAGS |
IRQ-Flag löschen |
read VIA 1 ICR, clear the timer interrupt flag |
clear CIA#1 I.C.R to enable next IRQ |
||
.,EA81 68 PLA |
PLA ;RESTORE REGISTERS |
Accu aus dem Stapel holen |
pull Y |
restore (Y), (X), (A) |
||
.,EA82 A8 TAY |
TAY |
und in Y-Register schieben |
restore Y |
|||
.,EA83 68 PLA |
PLA |
Accu aus dem Stapel holen |
pull X |
|||
.,EA84 AA TAX |
TAX |
und in X-Register schieben |
restore X |
|||
.,EA85 68 PLA |
PLA |
und Rückkehr vom Interrupt |
restore A |
|||
.,EA86 40 RTI |
RTI ;EXIT FROM IRQ ROUTINES ; ****** GENERAL KEYBOARD SCAN ****** ; |
Tastaturabfrage |
scan keyboard performs the following ..1) check if key pressed, if not then exit the routine2) init I/O ports of VIA ?? for keyboard scan and set pointers to decode table 1. clear the character counter 3) set one line of port B low and test for a closed key on port A by shifting the byte read from the port. if the carry is clear then a key is closed so save the count which is incremented on each shift. check for shift/stop/cbm keys and flag if closed 4) repeat step 3 for the whole matrix 5) evaluate the SHIFT/CTRL/C= keys, this may change the decode table selected 6) use the key count saved in step 3 as an index into the table selected in step 5 7) check for key repeat operation 8) save the decoded key to the buffer if first press or repeat scan the keyboard |
back to normalSCNKEY: SCAN KEYBOARDThe KERNAL routine SCNKEY ($ff9f) jumps to this routine.First, the shift-flag, SHFLAG, is cleared, and the keyboard tested for nokey. The keyboard is set up as a 8 * 8 matrix, and is read one row at a time. $ff indicates that no key has been pressed, and a zerobit, that one key has been pressed. |
scan keyboard |
|
.,EA87 A9 00 LDA #$00 |
SCNKEY LDA #$00 |
clear A |
||||
.,EA89 8D 8D 02 STA $028D |
STA SHFLAG |
Shift/CTRL Flag rücksetzen |
clear the keyboard shift/control/c= flag |
clear SHFLAG |
||
.,EA8C A0 40 LDY #$40 |
LDY #64 ;LAST KEY INDEX |
$40 = keine Taste gedrückt |
set no key |
|||
.,EA8E 84 CB STY $CB |
STY SFDX ;NULL KEY FOUND |
Kode für gedrückte Taste |
save which key |
|||
.,EA90 8D 00 DC STA $DC00 |
STA COLM ;RAISE ALL LINES |
alle Bits des Port A löschen |
clear VIA 1 DRA, keyboard column drive |
store in keyboard write register |
||
.,EA93 AE 01 DC LDX $DC01 |
LDX ROWS ;CHECK FOR A KEY DOWN |
Port B laden |
read VIA 1 DRB, keyboard row port |
keyboard read register |
||
.,EA96 E0 FF CPX #$FF |
CPX #$FF ;NO KEYS DOWN? |
keine Taste gedrückt ? |
compare with all bits set |
no key pressed |
||
.,EA98 F0 61 BEQ $EAFB |
BEQ SCNOUT ;BRANCH IF NONE |
dann beenden |
if no key pressed clear current key and exit (does further BEQ to $EBBA) |
skip |
||
.,EA9A A8 TAY |
TAY ;.A=0 LDY #0 |
Y-Register löschen |
clear the key count |
|||
.,EA9B A9 81 LDA #$81 |
LDA #<MODE1 |
get the decode table low byte |
point KEYTAB vector to $eb81 |
|||
.,EA9D 85 F5 STA $F5 |
STA KEYTAB |
$F5/$F6 = Zeiger auf |
save the keyboard pointer low byte |
|||
.,EA9F A9 EB LDA #$EB |
LDA #>MODE1 |
Tastaturtabelle setzen |
get the decode table high byte |
|||
.,EAA1 85 F6 STA $F6 |
STA KEYTAB+1 |
save the keyboard pointer high byte |
||||
.,EAA3 A9 FE LDA #$FE |
LDA #$FE ;START WITH 1ST COLUMN |
erstes Bit für erste Matrixzeile löschen |
set column 0 low |
bit0 = 0 |
||
.,EAA5 8D 00 DC STA $DC00 |
STA COLM |
und in Port A schreiben |
save VIA 1 DRA, keyboard column drive |
will test first row in matrix |
||
.,EAA8 A2 08 LDX #$08 |
SCN20 LDX #8 ;8 ROW KEYBOARD |
8 Matrixzeilen |
set the row count |
scan 8 rows in matrix |
||
.,EAAA 48 PHA |
PHA ;SAVE COLUMN OUTPUT INFO |
Bitstellung für Matrix retten |
save the column |
temp store |
||
.,EAAB AD 01 DC LDA $DC01 |
SCN22 LDA ROWS |
Port B laden und |
read VIA 1 DRB, keyboard row port |
read |
||
.,EAAE CD 01 DC CMP $DC01 |
CMP ROWS ;DEBOUNCE KEYBOARD |
Tastatur entprellen |
compare it with itself |
wait for value to settle (key bouncing) |
||
.,EAB1 D0 F8 BNE $EAAB |
BNE SCN22 |
noch nicht entprellt ? |
loop if changing |
|||
.,EAB3 4A LSR |
SCN30 LSR A ;LOOK FOR KEY DOWN |
Bits nacheinander ins Carry schieben |
shift row to Cb |
test bit0 |
||
.,EAB4 B0 16 BCS $EACC |
BCS CKIT ;NONE |
'1' gleich nicht gedrückt |
if no key closed on this row go do next row |
no key pressed |
||
.,EAB6 48 PHA |
PHA |
Bitstelung retten |
save row |
|||
.,EAB7 B1 F5 LDA ($F5),Y |
LDA (KEYTAB),Y ;GET CHAR CODE |
ASCII-Kode aus Tabelle holen |
get character from decode table |
get key from KEYTAB |
||
.,EAB9 C9 05 CMP #$05 |
CMP #$05 |
größer als 4, dann keine Control-Taste |
compare with $05, there is no $05 key but the control keys are all less than $05 |
value less than 5 |
||
.,EABB B0 0C BCS $EAC9 |
BCS SPCK2 ;IF NOT SPECIAL KEY GO ON |
verzweige bei größer/gleich 5 |
if not shift/control/c=/stop go save key count else was shift/control/c=/stop key |
nope |
||
.,EABD C9 03 CMP #$03 |
CMP #$03 ;COULD IT BE A STOP KEY? |
Kode für STOP-Taste ? |
compare with $03, stop |
value = 3 |
||
.,EABF F0 08 BEQ $EAC9 |
BEQ SPCK2 ;BRANCH IF SO |
falls ja, dann verzweige |
if stop go save key count and continue character is $01 - shift, $02 - c= or $04 - control |
nope |
||
.,EAC1 0D 8D 02 ORA $028D |
ORA SHFLAG |
entsprechendes Flag für SHIFT |
OR it with the keyboard shift/control/c= flag |
|||
.,EAC4 8D 8D 02 STA $028D |
STA SHFLAG ;PUT SHIFT BIT IN FLAG BYTE |
COMMOD.-Taste oder CTRL setzen |
save the keyboard shift/control/c= flag |
store in SHFLAG |
||
.,EAC7 10 02 BPL $EACB |
BPL CKUT SPCK2 |
unbedingter Sprung |
skip save key, branch always |
|||
.,EAC9 84 CB STY $CB |
STY SFDX ;SAVE KEY NUMBER |
Nummer der Taste merken |
save key count |
store keynumber we pressed in SFDX |
||
.,EACB 68 PLA |
CKUT PLA |
Akku holen |
restore row |
|||
.,EACC C8 INY |
CKIT INY |
Zähler für Taste erhöhen |
increment key count |
key counter |
||
.,EACD C0 41 CPY #$41 |
CPY #65 |
schon alle Tasten? |
compare with max+1 |
all 64 keys (8*8) |
||
.,EACF B0 0B BCS $EADC |
BCS CKIT1 ;BRANCH IF FINISHED |
wenn ja, verzweige |
exit loop if >= max+1 else still in matrix |
jump if ready |
||
.,EAD1 CA DEX |
DEX |
nächste Matrix-Spalte |
decrement row count |
next key in row |
||
.,EAD2 D0 DF BNE $EAB3 |
BNE SCN30 |
unbedingter Sprung |
loop if more rows to do |
row ready |
||
.,EAD4 38 SEC |
SEC |
Carry setzen |
set carry for keyboard column shift |
prepare for rol |
||
.,EAD5 68 PLA |
PLA ;RELOAD COLUMN INFO |
gespeicherte Bitfolge holen |
restore the column |
|||
.,EAD6 2A ROL |
ROL A |
verschieben und |
shift the keyboard column |
next row |
||
.,EAD7 8D 00 DC STA $DC00 |
STA COLM ;NEXT COLUMN ON KEYBOARD |
in Port A schreiben |
save VIA 1 DRA, keyboard column drive |
store bit |
||
.,EADA D0 CC BNE $EAA8 |
BNE SCN20 ;ALWAYS BRANCH |
unbedingter Sprung |
loop for next column, branch always |
always jump |
||
.,EADC 68 PLA |
CKIT1 PLA ;DUMP COLUMN OUTPUT...ALL DONE |
Stapel normalisieren |
dump the saved column |
clean upPROCESS KEY IMAGEThis routine decodes the pressed key, and calcuates itsASCII value, by use of the four tables. If the pressed key is the same key as in the former interrupt, then the key- repeat-section is entered. The routine tests the RPTFLG if he key shall repeat. The new key is stored in the keyboard buffer, and all pointers are uppdated. |
||
.,EADD 6C 8F 02 JMP ($028F) |
JMP (KEYLOG) ;EVALUATE SHIFT FUNCTIONS |
JMP $EB48 setzt Zeiger auf Tabelle |
evaluate the SHIFT/CTRL/C= keys, $EBDC key decoding continues here after the SHIFT/CTRL/C= keys are evaluated |
jump through KEYLOG vector, points to $eae0 |
||
.,EAE0 A4 CB LDY $CB |
REKEY LDY SFDX ;GET KEY INDEX |
Nummer der Taste |
get saved key count |
SFDX, number of the key we pressed |
||
.,EAE2 B1 F5 LDA ($F5),Y |
LDA (KEYTAB)Y ;GET CHAR CODE |
ASCII-Wert aus Tabelle holen |
get character from decode table |
get ASCII value from decode table |
||
.,EAE4 AA TAX |
TAX ;SAVE THE CHAR |
Tastenwert retten |
copy character to X |
temp store |
||
.,EAE5 C4 C5 CPY $C5 |
CPY LSTX ;SAME AS PREV CHAR INDEX? |
mit letzter Taste vergleichen |
compare key count with last key count |
same key as former interrupt |
||
.,EAE7 F0 07 BEQ $EAF0 |
BEQ RPT10 ;YES |
verzweige wenn gleiche Taste |
if this key = current key, key held, go test repeat |
yepp |
||
.,EAE9 A0 10 LDY #$10 |
LDY #$10 ;NO - RESET DELAY BEFORE REPEAT |
Wert für Repeatverzögerung |
set the repeat delay count |
restore the repeat delay counter |
||
.,EAEB 8C 8C 02 STY $028C |
STY DELAY |
in Repeat-Verzögerungszähler |
save the repeat delay count |
DELAY |
||
.,EAEE D0 36 BNE $EB26 |
BNE CKIT2 ;ALWAYS |
unbedingter Sprung |
go save key to buffer and exit, branch always |
always jump |
||
.,EAF0 29 7F AND #$7F |
RPT10 AND #$7F ;UNSHIFT IT |
Bit 7 löschen |
clear b7 |
|||
.,EAF2 2C 8A 02 BIT $028A |
BIT RPTFLG ;CHECK FOR REPEAT DISABLE |
Repeat-Funktion für alle Tasten ? |
test key repeat |
RPTFLG, test repeat mode |
||
.,EAF5 30 16 BMI $EB0D |
BMI RPT20 ;YES |
Bit 7 gesetzt, dann alle Tasten wiederholen |
if repeat all go ?? |
repeat all keys |
||
.,EAF7 70 49 BVS $EB42 |
BVS SCNRTS |
Bit 6 gesetzt, dann keine Wiederholung |
if repeat none go ?? |
repeat none - exit routine |
||
.,EAF9 C9 7F CMP #$7F |
CMP #$7F ;NO KEYS ? |
keine Taste? |
compare with end marker |
|||
.,EAFB F0 29 BEQ $EB26 |
SCNOUT BEQ CKIT2 ;YES - GET OUT |
ja, dann verzweige |
if $00/end marker go save key to buffer and exit |
|||
.,EAFD C9 14 CMP #$14 |
CMP #$14 ;AN INST/DEL KEY ? |
'DEL', 'INST' Kode |
compare with [INSERT]/[DELETE] |
<DEL> key pressed |
delete |
|
.,EAFF F0 0C BEQ $EB0D |
BEQ RPT20 ;YES - REPEAT IT |
wenn ja, verzweige |
if [INSERT]/[DELETE] go test for repeat |
yepp... |
||
.,EB01 C9 20 CMP #$20 |
CMP #$20 ;A SPACE KEY ? |
Leerzeichen |
compare with [SPACE] |
<space> key pressed |
space |
|
.,EB03 F0 08 BEQ $EB0D |
BEQ RPT20 ;YES |
wenn ja, verzweige |
if [SPACE] go test for repeat |
yepp... |
||
.,EB05 C9 1D CMP #$1D |
CMP #$1D ;A CRSR LEFT/RIGHT ? |
Cursor right, left |
compare with [CURSOR RIGHT] |
<CRSR LEFT/RIGHT> |
csr right/left |
|
.,EB07 F0 04 BEQ $EB0D |
BEQ RPT20 ;YES |
wenn ja, verzweige |
if [CURSOR RIGHT] go test for repeat |
yepp.. |
||
.,EB09 C9 11 CMP #$11 |
CMP #$11 ;A CRSR UP/DWN ? |
Cursor down, up |
compare with [CURSOR DOWN] |
<CRSRS DOWN/UP> |
csr up/down |
|
.,EB0B D0 35 BNE $EB42 |
BNE SCNRTS ;NO - EXIT |
verzweige wenn keine Taste zu wiederholen ist |
if not [CURSOR DOWN] just exit was one of the cursor movement keys, insert/delete key or the space bar so always do repeat tests |
yepp.. |
||
.,EB0D AC 8C 02 LDY $028C |
RPT20 LDY DELAY ;TIME TO REPEAT ? |
Repeatverzögerungszähler |
get the repeat delay counter |
DELAY |
||
.,EB10 F0 05 BEQ $EB17 |
BEQ RPT40 ;YES |
wenn abgelaufen, so verzweige |
if delay expired go ?? |
skip |
||
.,EB12 CE 8C 02 DEC $028C |
DEC DELAY |
herunterzählen |
else decrement repeat delay counter |
decrement DELAY |
||
.,EB15 D0 2B BNE $EB42 |
BNE SCNRTS |
0? nein dann verzweige |
if delay not expired go ?? repeat delay counter has expired |
end |
||
.,EB17 CE 8B 02 DEC $028B |
RPT40 DEC KOUNT ;TIME FOR NEXT REPEAT ? |
Repeatgeschwindigkeitszähler |
decrement the repeat speed counter |
decremant KOUNT, repeat speed counter |
||
.,EB1A D0 26 BNE $EB42 |
BNE SCNRTS ;NO |
0? nein dann verzweige |
branch if repeat speed count not expired |
end |
||
.,EB1C A0 04 LDY #$04 |
LDY #4 ;YES - RESET CTR |
Repeatgeschwindigkeits- |
set for 4/60ths of a second |
|||
.,EB1E 8C 8B 02 STY $028B |
STY KOUNT |
zähler neu setzen |
save the repeat speed counter |
init KOUNT |
||
.,EB21 A4 C6 LDY $C6 |
LDY NDX ;NO REPEAT IF QUEUE FULL |
Anzahl der Zeichen im Tastaturpuffer |
get the keyboard buffer index |
read NDX, number of keys in keyboard queue |
||
.,EB23 88 DEY |
DEY |
herunterzählen |
decrement it |
|||
.,EB24 10 1C BPL $EB42 |
BPL SCNRTS CKIT2 |
mehr als ein Zeichen im Puffer, dann ignorieren |
if the buffer isn't empty just exit else repeat the key immediately possibly save the key to the keyboard buffer. if there was no key pressed or the key was not found during the scan (possibly due to key bounce) then X will be $FF here |
end |
||
.,EB26 A4 CB LDY $CB |
LDY SFDX ;GET INDEX OF KEY |
Tastennummermatrixcode |
get the key count |
read SFDX |
||
.,EB28 84 C5 STY $C5 |
STY LSTX ;SAVE THIS INDEX TO KEY FOUND |
umspeichern |
save it as the current key count |
store in LSTX |
||
.,EB2A AC 8D 02 LDY $028D |
LDY SHFLAG ;UPDATE SHIFT STATUS |
sowie die Flags für SHIFT |
get the keyboard shift/control/c= flag |
read SHFLAG |
||
.,EB2D 8C 8E 02 STY $028E |
STY LSTSHF |
COMMOD.-Taste und CTRL |
save it as last keyboard shift pattern |
store in LSTSHF, last keyboard shift pattern |
||
.,EB30 E0 FF CPX #$FF |
CKIT3 CPX #$FF ;A NULL KEY OR NO KEY ? |
Tastatur-Kode ungültig ? |
compare the character with the table end marker or no key |
no valid key pressed |
||
.,EB32 F0 0E BEQ $EB42 |
BEQ SCNRTS ;BRANCH IF SO |
ja, dann ignorieren |
if it was the table end marker or no key just exit |
end |
||
.,EB34 8A TXA |
TXA ;NEED X AS INDEX SO... |
gerettete Taste wieder holen |
copy the character to A |
|||
.,EB35 A6 C6 LDX $C6 |
LDX NDX ;GET # OF CHARS IN KEY QUEUE |
Anzahl der Zeichen im Tastaturpuffer |
get the keyboard buffer index |
NDX, number of keys in buffer |
||
.,EB37 EC 89 02 CPX $0289 |
CPX XMAX ;IRQ BUFFER FULL ? |
mit Haximalzahl vergleichen |
compare it with the keyboard buffer size |
compare to XMAX, max numbers oc characters in buffer |
||
.,EB3A B0 06 BCS $EB42 |
BCS SCNRTS ;YES - NO MORE INSERT PUTQUE |
Puffer voll, dann Zeichen ignorieren |
if the buffer is full just exit |
buffer is full, end |
||
.,EB3C 9D 77 02 STA $0277,X |
STA KEYD,X ;PUT RAW DATA HERE |
Zeichen in Tastaturpuffer schreiben |
save the character to the keyboard buffer |
store new character in keyboard buffer |
||
.,EB3F E8 INX |
INX |
Zeichenanzahl erhöhen und |
increment the index |
increment counter |
||
.,EB40 86 C6 STX $C6 |
STX NDX ;UPDATE KEY QUEUE COUNT |
abspeichern |
save the keyboard buffer index |
and store in NDX |
||
.,EB42 A9 7F LDA #$7F |
SCNRTS LDA #$7F ;SETUP PB7 FOR STOP KEY SENSE |
Tastatur-Matrix Abfrage |
enable column 7 for the stop key |
|||
.,EB44 8D 00 DC STA $DC00 |
STA COLM |
auf Normalwert |
save VIA 1 DRA, keyboard column drive |
keyboard write register |
||
.,EB47 60 RTS |
RTS ; ; SHIFT LOGIC ; SHFLOG |
RücksprungPrüft auf Shift, CTRL,Commodore |
evaluate the SHIFT/CTRL/C= keys |
exit |
||
.,EB48 AD 8D 02 LDA $028D |
LDA SHFLAG |
Flag für Shift/CTRL |
get the keyboard shift/control/c= flag |
SHFLAG |
||
.,EB4B C9 03 CMP #$03 |
CMP #$03 ;COMMODORE SHIFT COMBINATION? |
SHIFT und COMMOD.-Taste gedrückt? |
compare with [SHIFT][C=] |
<SHIFT> and <CBM> at the same time |
||
.,EB4D D0 15 BNE $EB64 |
BNE KEYLG2 ;BRANCH IF NOT |
nein dann zum Dekodieren |
if not [SHIFT][C=] go ?? |
nope |
||
.,EB4F CD 8E 02 CMP $028E |
CMP LSTSHF ;DID I DO THIS ALREADY |
waren beide Tasten vorher schon vorher gedrückt |
compare with last |
same as LSTSHF |
||
.,EB52 F0 EE BEQ $EB42 |
BEQ SCNRTS ;BRANCH IF SO |
ja, dann zum Ende |
exit if still the same |
if so, end |
||
.,EB54 AD 91 02 LDA $0291 |
LDA MODE |
Shift-Commodore erlaubt ? |
get the shift mode switch $00 = enabled, $80 = locked |
read MODE, shift key enable flag |
||
.,EB57 30 1D BMI $EB76 |
BMI SHFOUT ;DONT SHIFT IF ITS MINUS |
nein, zurück zur Dekodierung |
if locked continue keyboard decode toggle text mode |
end |
||
.,EB59 AD 18 D0 LDA $D018 |
SWITCH LDA VICREG+24 ;**********************************: |
Zeichensatzzeiger laden |
get the start of character memory address |
VIC memory control register |
||
.,EB5C 49 02 EOR #$02 |
EOR #$02 ;TURN ON OTHER CASE |
Umschaltung Klein -Großschreibung und |
toggle address b1 |
toggle character set, upper/lower case |
||
.,EB5E 8D 18 D0 STA $D018 |
STA VICREG+24 ;POINT THE VIC THERE |
wieder speichern |
save the start of character memory address |
and store |
||
.,EB61 4C 76 EB JMP $EB76 |
JMP SHFOUT ; KEYLG2 |
fertig |
continue the keyboard decode select keyboard table |
process key image |
select keyboard table |
|
.,EB64 0A ASL |
ASL A |
Wert mit 2 multiplizieren, da jede Adresse 2 Bytes hat |
<< 1 |
|||
.,EB65 C9 08 CMP #$08 |
CMP #$08 ;WAS IT A CONTROL KEY |
vergleiche mit CTRL |
compare with [CTRL] |
test <CTRL> |
||
.,EB67 90 02 BCC $EB6B |
BCC NCTRL ;BRANCH IF NOT |
nein dann verzweige |
if [CTRL] is not pressed skip the index change |
nope |
||
.,EB69 A9 06 LDA #$06 |
LDA #6 ;ELSE USE TABLE #4 ; NCTRL NOTKAT |
Tabellenpointer für CTRL |
else [CTRL] was pressed so make the index = $06 |
set offset for ctrl |
||
.,EB6B AA TAX |
TAX |
in X Register übertragen |
copy the index to X |
to (X) |
||
.,EB6C BD 79 EB LDA $EB79,X |
LDA KEYCOD,X |
LOW-Byte der Tabellenadresse laden |
get the decode table pointer low byte |
read keyboard select vectors, low byte |
||
.,EB6F 85 F5 STA $F5 |
STA KEYTAB |
und in die Zeigeradresse LOW schreiben |
save the decode table pointer low byte |
store in KEYTAB, decode table vector |
||
.,EB71 BD 7A EB LDA $EB7A,X |
LDA KEYCOD+1,X |
HIGH-Byte der Tabellenadresse laden |
get the decode table pointer high byte |
read keyboard select vectors, high byte |
||
.,EB74 85 F6 STA $F6 |
STA KEYTAB+1 SHFOUT |
und in die Zeigeradresse HIGH schreiben |
save the decode table pointer high byte |
KEYTAB+1 |
||
.,EB76 4C E0 EA JMP $EAE0 |
JMP REKEY .END .LIB EDITOR.3KEYCOD ;KEYBOARD MODE 'DISPATCH'.WORD MODE1 .WORD MODE2 .WORD MODE3 |
zurück zur DekodierungZeiger auf Tastatur-Dekodiertabellen |
continue the keyboard decodetable addresses |
process key imageKEYBOARD SELECT VECTORSThis is a table of vectors pointing to the start of thefour keyboard decode tables. |
table addresses |
|
.:EB79 81 EB C2 EB 03 EC 78 EC |
.WORD CONTRL ;CONTROL KEYS ; ; COTTACONNA MODE ; ;.WORD MODE1 ;PET MODE1 ;.WORD MODE2 ;PET MODE2 ;.WORD CCTTA3 ;DUMMY WORD ;.WORD CONTRL ; ; EXTENDED KATAKANA MODE ; ;.WORD CCTTA2 ;KATAKANA CHARACTERS ;.WORD CCTTA3 ;LIMITED GRAPHICS ;.WORD CCTTA3 ;DUMMY ;.WORD CONTRL MODE1 ;DEL,3,5,7,9,+,YEN SIGN,1 |
Tastatur-Dekodiertabelle 1ungeshifted |
standard |
vector to unshifted keyboard, $eb81 |
standard |
|
.:EB81 14 0D 1D 88 85 86 87 11 |
.BYT $14,$0D,$1D,$88,$85,$86,$87,$11 ;RETURN,W,R,Y,I,P,*,LEFT ARROW |
shift commodore control standard keyboard table |
vector to shifted keyboard, $ebc2 vector to cbm keyboard, $ec03 vector to ctrl keyboard, $ec78 KEYBOARD 1 - UNSHIFTEDThis is the first of four keybboard decode tables. TheASCII code for the key pressed is at the intersection of the row (written to $dc00) and the column (read from $dc01). The matrix values are shown below. Note that left and right shift keys are seperated. |
shift commodore key control standard keyboard table |
||
.:EB89 33 57 41 34 5A 53 45 01 |
.BYT $33,$57,$41,$34,$5A,$53,$45,$01 ;RT CRSR,A,D,G,J,L,;,CTRL |
|||||
.:EB91 35 52 44 36 43 46 54 58 |
.BYT $35,$52,$44,$36,$43,$46,$54,$58 ;F4,4,6,8,0,-,HOME,2 |
|||||
.:EB99 37 59 47 38 42 48 55 56 |
.BYT $37,$59,$47,$38,$42,$48,$55,$56 ;F1,Z,C,B,M,.,R.SHIFTT,SPACE |
|||||
.:EBA1 39 49 4A 30 4D 4B 4F 4E |
.BYT $39,$49,$4A,$30,$4D,$4B,$4F,$4E ;F2,S,F,H,K,:,=,COM.KEY |
|||||
.:EBA9 2B 50 4C 2D 2E 3A 40 2C |
.BYT $2B,$50,$4C,$2D,$2E,$3A,$40,$2C ;F3,E,T,U,O,@,EXP,Q |
|||||
.:EBB1 5C 2A 3B 13 01 3D 5E 2F |
.BYT $5C,$2A,$3B,$13,$01,$3D,$5E,$2F ;CRSR DWN,L.SHIFT,X,V,N,,,/,STOP |
|||||
.:EBB9 31 5F 04 32 20 02 51 03 |
.BYT $31,$5F,$04,$32,$20,$02,$51,$03 |
|||||
.:EBC1 FF |
.BYT $FF ;END OF TABLE NULL MODE2 ;SHIFT ;INS,%,',),+,YEN,! |
Tastatur-Dekodierung,Tabelle 2 geshifted |
shifted keyboard table |
free byteKEYBOARD 2 - SHIFTEDThis is the second of four keyboard decode tables. TheASCII code for the key pressed is at the intersection of the row (written to $dc00) and the column (read from $dc01). The matrix values are shown below. |
shift keyboard table |
|
.:EBC2 94 8D 9D 8C 89 8A 8B 91 |
.BYT $94,$8D,$9D,$8C,$89,$8A,$8B,$91 ;SRETURN,W,R,Y,I,P,*,SLEFT ARROW |
|||||
.:EBCA 23 D7 C1 24 DA D3 C5 01 |
.BYT $23,$D7,$C1,$24,$DA,$D3,$C5,$01 ;LF.CRSR,A,D,G,J,L,;,CTRL |
|||||
.:EBD2 25 D2 C4 26 C3 C6 D4 D8 |
.BYT $25,$D2,$C4,$26,$C3,$C6,$D4,$D8 ;,$,&,(, ," |
|||||
.:EBDA 27 D9 C7 28 C2 C8 D5 D6 |
.BYT $27,$D9,$C7,$28,$C2,$C8,$D5,$D6 ;F5,Z,C,B,M,.,R.SHIFT,SSPACE |
|||||
.:EBE2 29 C9 CA 30 CD CB CF CE |
.BYT $29,$C9,$CA,$30,$CD,$CB,$CF,$CE ;F6,S,F,H,K,:,=,SCOM.KEY |
|||||
.:EBEA DB D0 CC DD 3E 5B BA 3C |
.BYT $DB,$D0,$CC,$DD,$3E,$5B,$BA,$3C ;F7,E,T,U,O,@,PI,G |
|||||
.:EBF2 A9 C0 5D 93 01 3D DE 3F |
.BYT $A9,$C0,$5D,$93,$01,$3D,$DE,$3F ;CRSR DWN,L.SHIFT,X,V,N,,,/,RUN |
|||||
.:EBFA 21 5F 04 22 A0 02 D1 83 |
.BYT $21,$5F,$04,$22,$A0,$02,$D1,$83 |
|||||
.:EC02 FF |
.BYT $FF ;END OF TABLE NULL ; MODE3 ;LEFT WINDOW GRAHPICS ;INS,C10,C12,C14,9,+,POUND SIGN,C8 |
Tastatur-Dekodierung,Tabelle 3, mit 'C='-Taste |
CBM key keyboard table |
free byteKEYBOARD 3 - COMMODOREThis is the third of four keyboard decode tables. TheASCII code for the key pressed is at the intersection of the ro (written to $dc00) and hte column (read from $dc01). The matrix values are shown below. |
commodore key keyboard table |
|
.:EC03 94 8D 9D 8C 89 8A 8B 91 |
.BYT $94,$8D,$9D,$8C,$89,$8A,$8B,$91 ;RETURN,W,R,Y,I,P,*,LFT.ARROW |
|||||
.:EC0B 96 B3 B0 97 AD AE B1 01 |
.BYT $96,$B3,$B0,$97,$AD,$AE,$B1,$01 ;LF.CRSR,A,D,G,J,L,;,CTRL |
|||||
.:EC13 98 B2 AC 99 BC BB A3 BD |
.BYT $98,$B2,$AC,$99,$BC,$BB,$A3,$BD ;F8,C11,C13,C15,0,-,HOME,C9 |
|||||
.:EC1B 9A B7 A5 9B BF B4 B8 BE |
.BYT $9A,$B7,$A5,$9B,$BF,$B4,$B8,$BE ;F2,Z,C,B,M,.,R.SHIFT,SPACE |
|||||
.:EC23 29 A2 B5 30 A7 A1 B9 AA |
.BYT $29,$A2,$B5,$30,$A7,$A1,$B9,$AA ;F4,S,F,H,K,:,=,COM.KEY |
|||||
.:EC2B A6 AF B6 DC 3E 5B A4 3C |
.BYT $A6,$AF,$B6,$DC,$3E,$5B,$A4,$3C ;F6,E,T,U,O,@,PI,Q |
|||||
.:EC33 A8 DF 5D 93 01 3D DE 3F |
.BYT $A8,$DF,$5D,$93,$01,$3D,$DE,$3F ;CRSR.UP,L.SHIFT,X,V,N,,,/,STOP |
|||||
.:EC3B 81 5F 04 95 A0 02 AB 83 |
.BYT $81,$5F,$04,$95,$A0,$02,$AB,$83 |
|||||
.:EC43 FF |
.BYT $FF ;END OF TABLE NULL ;CCTTA2 ;WAS CCTTA2 IN JAPANESE VERSION LOWER |
prüft auf Steuerzeichen |
check for special character codes |
free byteGRAPHICS / TEXT CONTROLThis routine is used to toggle between text and graphicscharacter set, and to enable/disable the <shift-CBM> keys. The routine is called by the main 'output to screen' routine, and (A) holds a CBM ASCII code on entry. |
check for special petscii codes |
|
.,EC44 C9 0E CMP #$0E |
CMP #$0E ;DOES HE WANT LOWER CASE? |
chr$(14) Großschrift |
compare with [SWITCH TO LOWER CASE] |
<switch to lower case> |
||
.,EC46 D0 07 BNE $EC4F |
BNE UPPER ;BRANCH IF NOT |
verzweige wenn nein |
if not [SWITCH TO LOWER CASE] skip the switch |
nope |
||
.,EC48 AD 18 D0 LDA $D018 |
LDA VICREG+24 ;ELSE SET VIC TO POINT TO LOWER CASE |
Character-Generator |
get the start of character memory address |
VIC memory control register |
||
.,EC4B 09 02 ORA #$02 |
ORA #$02 |
auf Großschrift-Modus |
mask xxxx xx1x, set lower case characters |
set bit1 |
||
.,EC4D D0 09 BNE $EC58 |
BNE ULSET ;JMP UPPER |
unbedingter Sprung |
go save the new value, branch always check for special character codes except fro switch to lower case |
allways branch |
||
.,EC4F C9 8E CMP #$8E |
CMP #$8E ;DOES HE WANT UPPER CASE |
chr$(142) Kleinschrift |
compare with [SWITCH TO UPPER CASE] |
<switch to upper case> |
||
.,EC51 D0 0B BNE $EC5E |
BNE LOCK ;BRANCH IF NOT |
verzweige wenn nein |
if not [SWITCH TO UPPER CASE] go do the [SHIFT]+[C=] key check |
nope |
||
.,EC53 AD 18 D0 LDA $D018 |
LDA VICREG+24 ;MAKE SURE VIC POINT TO UPPER/PET SET |
Character-Generator |
get the start of character memory address |
VIC memory control register |
||
.,EC56 29 FD AND #$FD |
AND #$FF-$02 |
Kleinschrift-Modus |
mask xxxx xx0x, set upper case characters |
clear bit1 |
||
.,EC58 8D 18 D0 STA $D018 |
ULSET STA VICREG+24 |
setzen |
save the start of character memory address |
and store |
||
.,EC5B 4C A8 E6 JMP $E6A8 |
OUTHRE JMP LOOP2 LOCK |
Ausgabe abschließen |
restore the registers, set the quote flag and exit do the [SHIFT]+[C=] key check |
finish screen print |
shift + commodore key check |
|
.,EC5E C9 08 CMP #$08 |
CMP #8 ;DOES HE WANT TO LOCK IN THIS MODE? |
chr$(8) Code zur Blockierung SHIFT und COMMOD.-Taste |
compare with disable [SHIFT][C=] |
<disable <shift-CBM>> |
||
.,EC60 D0 07 BNE $EC69 |
BNE UNLOCK ;BRANCH IF NOT |
verzweige wenn nein |
if not disable [SHIFT][C=] skip the set |
nope |
||
.,EC62 A9 80 LDA #$80 |
LDA #$80 ;ELSE SET LOCK SWITCH ON |
oberstes Bit des |
set to lock shift mode switch |
|||
.,EC64 0D 91 02 ORA $0291 |
ORA MODE ;DON'T HURT ANYTHING - JUST IN CASE |
Shift-Commodore Flags setzen |
OR it with the shift mode switch |
disable MODE |
||
.,EC67 30 09 BMI $EC72 |
BMI LEXIT UNLOCK |
unbedingter Sprung |
go save the value, branch always |
allways jump |
||
.,EC69 C9 09 CMP #$09 |
CMP #9 ;DOES HE WANT TO UNLOCK THE KEYBOARD? |
chr$(9) Code zur Freigabe von SHIFT und COMMOD.-Taste |
compare with enable [SHIFT][C=] |
<enable <shift-CBM>> |
||
.,EC6B D0 EE BNE $EC5B |
BNE OUTHRE ;BRANCH IF NOT |
verzweige wenn nein |
exit if not enable [SHIFT][C=] |
nope, exit |
||
.,EC6D A9 7F LDA #$7F |
LDA #$7F ;CLEAR THE LOCK SWITCH |
oberstes Bit des |
set to unlock shift mode switch |
|||
.,EC6F 2D 91 02 AND $0291 |
AND MODE ;DONT HURT ANYTHING |
Shift-Commodore Flags löschen |
AND it with the shift mode switch |
enable MODE |
||
.,EC72 8D 91 02 STA $0291 |
LEXIT STA MODE |
Wert speichern |
save the shift mode switch $00 = enabled, $80 = locked |
store MODE, enable/disable shift keys |
||
.,EC75 4C A8 E6 JMP $E6A8 |
JMP LOOP2 ;GET OUT ;CCTTA3 ;.BYT $04,$FF,$FF,$FF,$FF,$FF,$E2,$9D ;RUN-K24-K31 ;.BYT $83,$01,$FF,$FF,$FF,$FF,$FF,$91 ;K32-K39.F5 ;.BYT $A0,$FF,$FF,$FF,$FF,$EE,$01,$89 ;CO.KEY,K40-K47.F6 ;.BYT $02,$FF,$FF,$FF,$FF,$E1,$FD,$8A ;K48-K55 ;.BYT $FF,$FF,$FF,$FF,$FF,$B0,$E0,$8B ;K56-K63 ;.BYT $F2,$F4,$F6,$FF,$F0,$ED,$93,$8C ;.BYT $FF ;END OF TABLE NULL CONTRL ;NULL,RED,PURPLE,BLUE,RVS ,NULL,NULL,BLACK |
Ausgabe abschließenTastaturdekodierung,Tabelle 4, mit CTRL-Taste |
restore the registers, set the quote flag and exitcontrol keyboard table |
finish screen printKEYBOARD 4 - CONTROLThis is the last keyboard decode table. The ASCII code forthe key pressed is at the intersection of the row (written to $dc00) and the column (read from $dc01). The matrix values are shown below. A few special function are found in this table ie. <ctrl H> - disables the upper/lower case switch <ctrl I> - enables the upper/lower case switch <ctrl S> - homes the cursor <ctrl T> - delets character Note that the italic keys only represent a ASCII code, and not a CBM character. |
control keyboard table |
|
.:EC78 FF FF FF FF FF FF FF FF |
.BYT $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF ;NULL, W ,REVERSE, Y , I , P ,NULL,MUSIC |
|||||
.:EC80 1C 17 01 9F 1A 13 05 FF |
.BYT $1C,$17,$01,$9F,$1A,$13,$05,$FF |
|||||
.:EC88 9C 12 04 1E 03 06 14 18 |
.BYT $9C,$12,$04,$1E,$03,$06,$14,$18 ;NULL,CYAN,GREEN,YELLOW,RVS OFF,NULL,NULL,WHITE |
|||||
.:EC90 1F 19 07 9E 02 08 15 16 |
.BYT $1F,$19,$07,$9E,$02,$08,$15,$16 |
|||||
.:EC98 12 09 0A 92 0D 0B 0F 0E |
.BYT $12,$09,$0A,$92,$0D,$0B,$0F,$0E |
|||||
.:ECA0 FF 10 0C FF FF 1B 00 FF |
.BYT $FF,$10,$0C,$FF,$FF,$1B,$00,$FF |
|||||
.:ECA8 1C FF 1D FF FF 1F 1E FF |
.BYT $1C,$FF,$1D,$FF,$FF,$1F,$1E,$FF |
|||||
.:ECB0 90 06 FF 05 FF FF 11 FF |
.BYT $90,$06,$FF,$05,$FF,$FF,$11,$FF |
|||||
.:ECB8 FF |
.BYT $FF ;END OF TABLE NULL TVIC .BYT 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;SPRITES (0-16) .BYT $1B,0,0,0,0,$08,0,$14,0,0,0,0,0,0,0 ;DATA (17-31) |
Konstanten fürVideocontroller |
vic ii chip initialisation values |
free byteVIDEO CHIP SET UP TABLEThis is a table of the initial values for the VIC chipregisters at start up. |
default values for VIC chip |
|
.:ECB9 00 00 00 00 00 00 00 00 |
.BYT 14,6,1,2,3,4,0,1,2,3,4,5,6,7 ;32-46 ; |
sprite 0 x,y |
$d000/1, sprite0 - x,y cordinate |
sprite 1 x,y |
||
.:ECC1 00 00 00 00 00 00 00 00 |
sprite 1 x,y sprite 2 x,y sprite 3 x,y sprite 4 x,y |
$d002/3, sprite1 - x,y cordinate $d004/5, sprite2 - x,y cordinate $d006/7, sprite3 - x,y cordinate $d008/9, sprite4 - x,y cordinate |
sprite 2 x,y sprite 3 x,y sprite 4 x,y sprite 5 x,y |
|||
.:ECC9 00 9B 37 00 00 00 08 00 |
sprite 5 x,y sprite 6 x,y sprite 7 x,y sprites 0 to 7 x bit 8 |
$d00a/b, sprite5 - x,y cordinate $d00c/d, sprite6 - x,y cordinate $d00e/f, sprite7 - x,y cordinate $d010, sprite MSB |
sprite 6 x,y sprite 7 x,y sprite 8 x,y |
|||
.:ECD1 14 0F 00 00 00 00 00 00 |
enable screen, enable 25 rows vertical fine scroll and control bit function --- ------- 7 raster compare bit 8 6 1 = enable extended color text mode 5 1 = enable bitmap graphics mode 4 1 = enable screen, 0 = blank screen 3 1 = 25 row display, 0 = 24 row display 2-0 vertical scroll count raster compare light pen x light pen y sprite 0 to 7 enable enable 40 column display horizontal fine scroll and control bit function --- ------- 7-6 unused 5 1 = vic reset, 0 = vic on 4 1 = enable multicolor mode 3 1 = 40 column display, 0 = 38 column display 2-0 horizontal scroll count sprite 0 to 7 y expand memory control bit function --- ------- 7-4 video matrix base address 3-1 character data base address 0 unused |
$d011, VIC control register $d012, $d013/4, light pen x/y position $d015, sprite enable $d016, VIC control register 2 $d017, sprite y-expansion $d018, VIC memory control register |
sprite Y expand |
|||
.:ECD9 0E 06 01 02 03 04 00 01 |
clear all interrupts interrupt flags 7 1 = interrupt 6-4 unused 3 1 = light pen interrupt 2 1 = sprite to sprite collision interrupt 1 1 = sprite to foreground collision interrupt 0 1 = raster compare interrupt all vic IRQs disabeld IRQ enable bit function --- ------- 7-4 unused 3 1 = enable light pen 2 1 = enable sprite to sprite collision 1 1 = enable sprite to foreground collision 0 1 = enable raster compare sprite 0 to 7 foreground priority sprite 0 to 7 multicolour sprite 0 to 7 x expand sprite 0 to 7 sprite collision sprite 0 to 7 foreground collision border colour |
$d019, VIC irq flag register $d01a, VIC irq mask register $d01b, sprite/background priority $d01c, sprite multicolour mode $d01d, sprite x-expansion $d01e, sprite/sprite collision $d01f, sprite/background collision $d020, border colour (light blue) |
sprite multi-colour sprite X expand boarder colour |
|||
.:ECE1 02 03 04 05 06 07 |
Text nach Drücken von SHIFTRUN/STOP |
background colour 0 background colour 1 background colour 2 background colour 3 sprite multicolour 0 sprite multicolour 1 sprite 0 colour sprite 1 colour |
$d021, background colour 0 (blue) $d022, background colour 1 $d023, background colour 2 $d024, background colour 3 $d025, sprite multicolour register 0 $d026, sprite multicolour register 1 $d027, sprite0 colour $d028, sprite1 colour |
background colour sprite colour sprite colour sprite colour |
||
.:ECE7 4C 4F 41 44 0D 52 55 4E |
RUNTB .BYT 'LOAD',$D,'RUN',$D ; LINZ0 = VICSCN LINZ1 = LINZ0+LLEN LINZ2 = LINZ1+LLEN LINZ3 = LINZ2+LLEN LINZ4 = LINZ3+LLEN LINZ5 = LINZ4+LLEN LINZ6 = LINZ5+LLEN LINZ7 = LINZ6+LLEN LINZ8 = LINZ7+LLEN LINZ9 = LINZ8+LLEN LINZ10 = LINZ9+LLEN LINZ11 = LINZ10+LLEN LINZ12 = LINZ11+LLEN LINZ13 = LINZ12+LLEN LINZ14 = LINZ13+LLEN LINZ15 = LINZ14+LLEN LINZ16 = LINZ15+LLEN LINZ17 = LINZ16+LLEN LINZ18 = LINZ17+LLEN LINZ19 = LINZ18+LLEN LINZ20 = LINZ19+LLEN LINZ21 = LINZ20+LLEN LINZ22 = LINZ21+LLEN LINZ23 = LINZ22+LLEN LINZ24 = LINZ23+LLEN ;****** SCREEN LINES LO BYTE TABLE ****** ; LDTB2 .BYTE <LINZ0 .BYTE <LINZ1 .BYTE <LINZ2 .BYTE <LINZ3 .BYTE <LINZ4 .BYTE <LINZ5 .BYTE <LINZ6 .BYTE <LINZ7 .BYTE <LINZ8 .BYTE <LINZ9 .BYTE <LINZ10 .BYTE <LINZ11 .BYTE <LINZ12 .BYTE <LINZ13 .BYTE <LINZ14 .BYTE <LINZ15 .BYTE <LINZ16 .BYTE <LINZ17 .BYTE <LINZ18 .BYTE <LINZ19 .BYTE <LINZ20 .BYTE <LINZ21 .BYTE <LINZ22 .BYTE <LINZ23 |
'load (cr) run (cr)' |
sprite 2 colour sprite 3 colour sprite 4 colour sprite 5 colour sprite 6 colour sprite 7 colour is actually the first character of "LOAD" ($4C) keyboard buffer for auto load/run'load (cr) run (cr)' |
$d029, sprite2 colour $d02a, sprite3 colour $d02b, sprite4 colour $d02c, sprite5 colour $d02d, sprite6 colour SHIFT-RUN EQUIVALENTThis is the message LOAD <CR> RUN <CR>, which is placed inthe keyboard buffer when <shift-RUN> is pressed. LOAD <CR> RUN <CR> |
sprite colour sprite colour sprite colour sprite colour sprite colour loadrun |
|
.:ECEA 44 0D 52 55 4E 0D |
Tabelle der LSB derBildschirmzeilen-Anfänge |
|||||
.:ECF0 00 28 50 78 A0 C8 F0 18 |
.BYTE <LINZ24 .END .LIB SERIAL4.0;COMMAND SERIAL BUS DEVICE TO TALK; |
low bytes of screen line addresses |
LOW BYTE SCREEN LINE ADDRESSESThis is a table of the low bytes of screen line addresses.The high byte of the addresses is obtained by derivation from the page on which the screen starts. There was an additional table of high byte addresses on the fixed screen PETs. |
low bytes of screen line addresses |
||
.:ECF8 40 68 90 B8 E0 08 30 58 | ||||||
.:ED00 80 A8 D0 F8 20 48 70 98 | ||||||
.:ED08 C0 |
IEC-Bus RoutinenTALK senden |
command serial bus device to TALK |
TALK: SEND 'TALK' / 'LISTEN'The KERNAL routine TALK ($ffb4) and LISTEN ($ffb1) arevectored here. The routine sends the command 'TALK' or 'LISTEN' on the serial bus. On entry (A) must hold the device number to which the command will be sent. The two entry points differ only in that to TALK, (A) is ORed with #$40, and to LISTEN, (A) is ORed with #$20. The UNTALK (#$3f) and UNLISTEN (#$5f) are also sent via this routine, but their values are set on entry. If there is a character waiting to go out on the bus, then this is output. Handshaking is performed, and ATN (attension) is set low so that the byte is interpreted as a command. The routine drops through to the next one to output the byte on the serial bus. Note that on conclusion, ATN must be set high. |
send talk on serial bus |
||
.,ED09 09 40 ORA #$40 |
TALK ORA #$40 ;MAKE A TALK ADR |
Bit für Talk setzen |
OR with the TALK command |
set TALK flag |
||
.:ED0B 2C .BYTE $2C |
.BYT $2C ;SKIP TWO BYTES ;COMMAND SERIAL BUS DEVICE TO LISTEN ; |
Skip nach $ED0ELISTEN senden |
makes next line BIT $2009command devices on the serial bus to LISTEN |
bit $2009, mask ORA command |
send listen on serial bus |
|
.,ED0C 09 20 ORA #$20 |
LISTN ORA #$20 ;MAKE A LISTEN ADR |
Bit für Listen setzen |
OR with the LISTEN command |
set LISTEN flag |
||
.,ED0E 20 A4 F0 JSR $F0A4 |
JSR RSP232 ;PROTECT SELF FROM RS232 NMI'S |
Ende der RS 232 Übertragung abwarten |
check RS232 bus idlesend a control character |
check serial bus idle |
||
.,ED11 48 PHA |
LIST1 PHA ; ; |
Akku merken |
save device address |
|||
.,ED12 24 94 BIT $94 |
BIT C3P0 ;CHARACTER LEFT IN BUF? |
Noch Zeichen im Puffer ? |
test deferred character flag |
C3PO, character in serial buffer |
||
.,ED14 10 0A BPL $ED20 |
BPL LIST2 ;NO... ; ;SEND BUFFERED CHARACTER ; |
verzweige wenn nein |
if no defered character continue |
nope |
||
.,ED16 38 SEC |
SEC ;SET EOI FLAG |
Carry setzen |
else flag EOI |
prepare for ROR |
||
.,ED17 66 A3 ROR $A3 |
ROR R2D2 ; |
Bit für EOI setzen |
rotate into EOI flag byte |
temp data area |
||
.,ED19 20 40 ED JSR $ED40 |
JSR ISOUR ;SEND LAST CHARACTER ; |
Byte auf IEC-Bus ausgeben |
Tx byte on serial bus |
send data to serial bus |
||
.,ED1C 46 94 LSR $94 |
LSR C3P0 ;BUFFER CLEAR FLAG |
Flag für Zeichen im Puffer löschen |
clear deferred character flag |
3CPO |
||
.,ED1E 46 A3 LSR $A3 |
LSR R2D2 ;CLEAR EOI FLAG ; ; |
Flag für EOI löschen |
clear EOI flag |
|||
.,ED20 68 PLA |
LIST2 PLA ;TALK/LISTEN ADDRESS |
Akku wiederholen und |
restore the device addressdefer a command |
|||
.,ED21 85 95 STA $95 |
STA BSOUR |
im Puffer speichern |
save as serial defered character |
BSOUR, buffered character for bus |
||
.,ED23 78 SEI |
SEI |
Interruptflag setzen |
disable the interrupts |
|||
.,ED24 20 97 EE JSR $EE97 |
JSR DATAHI |
DATA auf LOW setzen |
set the serial data out high |
set data 1, and clear serial bit count |
||
.,ED27 C9 3F CMP #$3F |
CMP #$3F ;CLKHI ONLY ON UNLISTEN |
Akku kann nicht $3F sein |
compare read byte with $3F |
UNTALK? |
||
.,ED29 D0 03 BNE $ED2E |
BNE LIST5 |
unbedingter Sprung |
branch if not $3F, this branch will always be taken as after VIA 2's PCR is read it is ANDed with $DF, so the result can never be $3F ?? |
nope |
||
.,ED2B 20 85 EE JSR $EE85 |
JSR CLKHI ; |
CLOCK auf LOW setzen |
set the serial clock out high |
set CLK 1 |
||
.,ED2E AD 00 DD LDA $DD00 |
LIST5 LDA D2PRA ;ASSERT ATTENTION |
Port A laden |
read VIA 2 DRA, serial port and video address |
serial bus I/O port |
||
.,ED31 09 08 ORA #$08 |
ORA #$08 |
ATN HIGH setzen und |
mask xxxx 1xxx, set serial ATN low |
clear ATN, prepare for command |
||
.,ED33 8D 00 DD STA $DD00 |
STA D2PRA ; |
ausgeben |
save VIA 2 DRA, serial port and video address if the code drops through to here the serial clock is low and the serial data has been released so the following code will have no effect apart from delaying the first byte by 1ms set the serial clk/data, wait and Tx byte on the serial bus |
store |
||
.,ED36 78 SEI |
ISOURA SEI |
InterruptfLag setzen |
disable the interrupts |
disable interrupts |
||
.,ED37 20 8E EE JSR $EE8E |
JSR CLKLO ;SET CLOCK LINE LOW |
CLOCK auf HIGH setzen |
set the serial clock out low |
set CLK 1 |
||
.,ED3A 20 97 EE JSR $EE97 |
JSR DATAHI |
DATA auf LOW setzen |
set the serial data out high |
set data 1 |
||
.,ED3D 20 B3 EE JSR $EEB3 |
JSR W1MS ;DELAY 1 MS |
eine Millisekunde wartenein Byte auf IEC-Busausgeben |
1ms delayTx byte on serial bus |
delay 1 msSEND DATA ON SERIAL BUSThe byte of data to be output on the serial bus must havebeen previously stored in the serial buffer, BSOUR. An initial test is made for bus activity, and if none is detected then ST is set to #$80, ie. ?DEVICE NOT PRESENT. The byte is output by rotating it right and sending the state of the carry flag. This is done eight times until the whole byte was sent. The CIA timer is set to 65 ms and the bus is checked for 'data accepted'. If timeout occurs before this happens then ST is set to #$03, ie. write timeout. |
send byte from $95 on serial bus |
|
.,ED40 78 SEI |
ISOUR SEI ;NO IRQ'S ALLOWED |
Interruptflag setzen |
disable the interrupts |
disable interrupts |
||
.,ED41 20 97 EE JSR $EE97 |
JSR DATAHI ;MAKE SURE DATA IS RELEASED |
DATA auf LOW setzen |
set the serial data out high |
set data 1 |
||
.,ED44 20 A9 EE JSR $EEA9 |
JSR DEBPIA ;DATA SHOULD BE LOW |
Hardware-Rückmeldung aus DATA holen |
get the serial data status in Cb |
get serial in and clock |
||
.,ED47 B0 64 BCS $EDAD |
BCS NODEV |
DATA LOW, dann 'DEVICE NOT PRESENT' |
if the serial data is high go do 'device not present' |
no activity, device not present. |
||
.,ED49 20 85 EE JSR $EE85 |
JSR CLKHI ;CLOCK LINE HIGH |
CLOCK auf LOW setzen |
set the serial clock out high |
set CLK 1 |
||
.,ED4C 24 A3 BIT $A3 |
BIT R2D2 ;EOI FLAG TEST |
Bit für EOI gesetzt? |
test the EOI flag |
temp data area |
||
.,ED4E 10 0A BPL $ED5A |
BPL NOEOI ; DO THE EOI |
nein, dann verzweige |
if not EOI go ?? I think this is the EOI sequence so the serial clock has been released and the serial data is being held low by the peripheral. first up wait for the serial data to rise |
|||
.,ED50 20 A9 EE JSR $EEA9 |
ISR02 JSR DEBPIA ;WAIT FOR DATA TO GO HIGH |
DATA ins Carry |
get the serial data status in Cb |
get serial in and clock |
||
.,ED53 90 FB BCC $ED50 |
BCC ISR02 ; |
warten bis Listener bereit |
loop if the data is low now the data is high, EOI is signalled by waiting for at least 200us without pulling the serial clock line low again. the listener should respond by pulling the serial data line low |
wait for indata = 0 |
||
.,ED55 20 A9 EE JSR $EEA9 |
ISR03 JSR DEBPIA ;WAIT FOR DATA TO GO LOW |
DATA ins Carry |
get the serial data status in Cb |
get serial in and clock |
||
.,ED58 B0 FB BCS $ED55 |
BCS ISR03 ; |
warten auf DATA HIGH |
loop if the data is high the serial data has gone low ending the EOI sequence, now just wait for the serial data line to go high again or, if this isn't an EOI sequence, just wait for the serial data to go high the first time |
wait for indata = 1 |
||
.,ED5A 20 A9 EE JSR $EEA9 |
NOEOI JSR DEBPIA ;WAIT FOR DATA HIGH |
DATA ins Carry |
get the serial data status in Cb |
get serial in and clock |
||
.,ED5D 90 FB BCC $ED5A |
BCC NOEOI |
warten bis bereit für Daten |
loop if the data is low serial data is high now pull the clock low, preferably within 60us |
wait for indata = 0 |
||
.,ED5F 20 8E EE JSR $EE8E |
JSR CLKLO ;SET CLOCK LOW ; ; SET TO SEND DATA ; |
CLOCK auf HIGH setzen |
set the serial clock out low now the C64 has to send the eight bits, LSB first. first it sets the serial data line to reflect the bit in the byte, then it sets the serial clock to high. The serial clock is left high for 26 cycles, 23us on a PAL Vic, before it is again pulled low and the serial data is allowed high again |
set CLK 0 |
||
.,ED62 A9 08 LDA #$08 |
LDA #$08 ;COUNT 8 BITS |
Bitzähler für serielle |
eight bits to do |
output 8 bits |
||
.,ED64 85 A5 STA $A5 |
STA COUNT ; ISR01 |
Ausgabe setzen ($08 Bits) |
set serial bus bit count |
|||
.,ED66 AD 00 DD LDA $DD00 |
LDA D2PRA ;DEBOUNCE THE BUS |
Port A lesen |
read VIA 2 DRA, serial port and video address |
|||
.,ED69 CD 00 DD CMP $DD00 |
CMP D2PRA |
und entprellen |
compare it with itself |
|||
.,ED6C D0 F8 BNE $ED66 |
BNE ISR01 |
verzweige wenn Änderung |
if changed go try again |
|||
.,ED6E 0A ASL |
ASL A ;SET THE FLAGS |
Datenbit ins Carry |
shift the serial data into Cb |
|||
.,ED6F 90 3F BCC $EDB0 |
BCC FRMERR ;DATA MUST BE HI ; |
DATA HIGH, dann 'TIME OUT' |
if the serial data is low go do serial bus timeout |
|||
.,ED71 66 95 ROR $95 |
ROR BSOUR ;NEXT BIT INTO CARRY |
nächstes Bit zur Ausgabe bereitstellen |
rotate the transmit byte |
BSOUR, buffered character for bus |
||
.,ED73 B0 05 BCS $ED7A |
BCS ISRHI |
verzweige wenn Bit gesetzt |
if the bit = 1 go set the serial data out high |
prepare to output 1 |
||
.,ED75 20 A0 EE JSR $EEA0 |
JSR DATALO |
DATA auf HIGH setzen |
else set the serial data out low |
else, serial output 0 |
||
.,ED78 D0 03 BNE $ED7D |
BNE ISRCLK |
unbedingter Sprung |
continue, branch always |
|||
.,ED7A 20 97 EE JSR $EE97 |
ISRHI JSR DATAHI |
DATA auf LOW setzen |
set the serial data out high |
|||
.,ED7D 20 85 EE JSR $EE85 |
ISRCLK JSR CLKHI ;CLOCK HI |
CLOCK auf LOW setzen |
set the serial clock out high |
|||
.,ED80 EA NOP |
NOP |
Listener |
waste .. |
|||
.,ED81 EA NOP |
NOP |
8 Microsekunden Zeit zur |
.. a .. |
|||
.,ED82 EA NOP |
NOP |
Verarbeitung der |
.. cycle .. |
|||
.,ED83 EA NOP |
NOP |
Daten geben |
.. or two |
|||
.,ED84 AD 00 DD LDA $DD00 |
LDA D2PRA |
Port A laden |
read VIA 2 DRA, serial port and video address |
|||
.,ED87 29 DF AND #$DF |
AND #$FF-$20 ;DATA HIGH |
DATA auf LOW |
mask xx0x xxxx, set the serial data out high |
|||
.,ED89 09 10 ORA #$10 |
ORA #$10 ;CLOCK LOW |
und CLOCK auf HIGH |
mask xxx1 xxxx, set the serial clock out low |
|||
.,ED8B 8D 00 DD STA $DD00 |
STA D2PRA |
setzen |
save VIA 2 DRA, serial port and video address |
|||
.,ED8E C6 A5 DEC $A5 |
DEC COUNT |
nächstes Bit |
decrement the serial bus bit count |
decrement bit counter |
||
.,ED90 D0 D4 BNE $ED66 |
BNE ISR01 |
mache weiter wenn noch nicht alle Bits gesendet |
loop if not all done now all eight bits have been sent it's up to the peripheral to signal the byte was received by pulling the serial data low. this should be done within one milisecond |
next bit till all 8 are done |
||
.,ED92 A9 04 LDA #$04 |
LDA #$04 ;SET TIMER FOR 1MS |
$04 als Timerwert setzen |
wait for up to about 1ms |
|||
.,ED94 8D 07 DC STA $DC07 |
STA D1T2H |
Timer B HIGH, ca. eine ms |
save VIA 1 timer B high byte |
CIA timer B, high byte |
||
.,ED97 A9 19 LDA #$19 |
LDA #TIMRB ;TRIGGER TIMER |
und Timer B |
load timer B, timer B single shot, start timer B |
|||
.,ED99 8D 0F DC STA $DC0F |
STA D1CRB |
starten |
save VIA 1 CRB |
set 1 shot, load and start CIA timer B |
||
.,ED9C AD 0D DC LDA $DC0D |
LDA D1ICR ;CLEAR THE TIMER FLAGS<<<<<<<<<<<<< |
Interrupt control register |
read VIA 1 ICR |
CIA ICR |
||
.,ED9F AD 0D DC LDA $DC0D |
ISR04 LDA D1ICR |
laden |
read VIA 1 ICR |
|||
.,EDA2 29 02 AND #$02 |
AND #$02 |
Timer B abgelaufen ? |
mask 0000 00x0, timer A interrupt |
timeout |
||
.,EDA4 D0 0A BNE $EDB0 |
BNE FRMERR |
ja, dann 'TIME OUT' |
if timer A interrupt go do serial bus timeout |
yep, flag write timeout |
||
.,EDA6 20 A9 EE JSR $EEA9 |
JSR DEBPIA |
DATA ins Carry |
get the serial data status in Cb |
get serial in and clock |
||
.,EDA9 B0 F4 BCS $ED9F |
BCS ISR04 |
warten auf DATA HIGH |
if the serial data is high go wait some more |
|||
.,EDAB 58 CLI |
CLI ;LET IRQ'S CONTINUE |
Interruptflag löschen |
enable the interrupts |
enable interrupts |
||
.,EDAC 60 RTS |
RTS ; NODEV ;DEVICE NOT PRESENT ERROR |
Rücksprung |
device not present |
FLAG ERRORS(A) is loaded with one of the two error flags, dependingon the entry point. #$80 signifies the device was not present, and #$03 signifies a write timeout. The value is then set into the I/O status word, ST. The routine exits by clearing ATN and giving the final handshake. |
||
.,EDAD A9 80 LDA #$80 |
LDA #$80 |
'DEVICE NOT PRESENT' |
error $80, device not present |
flag ?DEVICE NOT PRESENT |
||
.:EDAF 2C .BYTE $2C |
.BYT $2C FRMERR ;FRAMING ERROR |
Skip nach $EDB2 |
makes next line BIT $03A9 timeout on serial bus |
mask LDA #$03 |
||
.,EDB0 A9 03 LDA #$03 |
LDA #$03 |
'TIME OUT' |
error $03, read timeout, write timeout |
flag write timeout |
||
.,EDB2 20 1C FE JSR $FE1C |
CSBERR JSR UDST ;COMMODORE SERIAL BUSS ERROR ENTRY |
Status setzen |
OR into the serial status byte |
set I/O status word |
||
.,EDB5 58 CLI |
CLI ;IRQ'S WERE OFF...TURN ON |
Interruptflag löschen |
enable the interrupts |
|||
.,EDB6 18 CLC |
CLC ;MAKE SURE NO KERNAL ERROR RETURNED |
Carry setzen |
clear for branch |
|||
.,EDB7 90 4A BCC $EE03 |
BCC DLABYE ;TURN ATN OFF ,RELEASE ALL LINES ; ;SEND SECONDARY ADDRESS AFTER LISTEN ; |
unbedingter SprungSekundäradresse nach LISTENsenden |
ATN high, delay, clock high then data high, branch alwayssend secondary address after LISTEN |
allways jump, do final handshakeSECOND: SEND LISTEN SAThe KERNAL routine SECOND ($ff93) is vectored here. Onentry, (A) holds the secondary address. This is placed in the serial buffer and sent to the serial bus "under attension". Finally the routine drops through to the next routine to set ATN false. |
send secondary address (listen) on serial bus |
|
.,EDB9 85 95 STA $95 |
SECND STA BSOUR ;BUFFER CHARACTER |
Sekundäradresse speichern |
save the defered Tx byte |
store (A) in BSOUT, buffer for the serial bus |
||
.,EDBB 20 36 ED JSR $ED36 |
JSR ISOURA ;SEND IT ;RELEASE ATTENTION AFTER LISTEN ; |
mit ATN HIGH ausgeben |
set the serial clk/data, wait and Tx the byteset serial ATN high |
handshake and send byte.CLEAR ATNThe ATN, attension, line on the serial bus is set to 1,ie. ATN is now false and data sent on the serial bus will not be interpreted as a command. |
||
.,EDBE AD 00 DD LDA $DD00 |
SCATN LDA D2PRA |
Port A laden |
read VIA 2 DRA, serial port and video address |
serial bus I/O port |
||
.,EDC1 29 F7 AND #$F7 |
AND #$FF-$08 |
ATN rücksetzen, LOW |
mask xxxx 0xxx, set serial ATN high |
clear bit4, ie. ATN 1 |
||
.,EDC3 8D 00 DD STA $DD00 |
STA D2PRA ;RELEASE ATTENTION |
und ausgeben |
save VIA 2 DRA, serial port and video address |
store to port |
||
.,EDC6 60 RTS |
RTS ;TALK SECOND ADDRESS ; |
RücksprungSekundäradresse nach TALKausgeben |
send secondary address after TALK |
TKSA: SEND TALK SAThe KERNAL routine TKSA ($ff96) is vectored here. Onentry, (A) holds the secondary address. This is placed in the serial buffer and sent out to the serial bus "under attension". The routine drops through to the next routine to wait for CLK and clear ATN. |
send secondary address (talk) on serial bus |
|
.,EDC7 85 95 STA $95 |
TKSA STA BSOUR ;BUFFER CHARACTER |
Sekundäradresse speichern |
save the defered Tx byte |
BSOUR, the serial bus buffer |
||
.,EDC9 20 36 ED JSR $ED36 |
JSR ISOURA ;SEND SECOND ADDR TKATN ;SHIFT OVER TO LISTENER |
mit ATN ausgeben |
set the serial clk/data, wait and Tx the bytewait for the serial bus end after sendreturn address from patch 6 |
handshake and send byte to the busWAIT FOR CLOCKThis routine sets data = 0, ATN = 1 and CLK = 1. It thenwaits to recieve CLK = 0 from the serial bus. |
||
.,EDCC 78 SEI |
SEI ;NO IRQ'S HERE |
Interruptflag setzen |
disable the interrupts |
disable interrupts |
||
.,EDCD 20 A0 EE JSR $EEA0 |
JSR DATALO ;DATA LINE LOW |
DATA auf HIGH setzen |
set the serial data out low |
set data 0 |
||
.,EDD0 20 BE ED JSR $EDBE |
JSR SCATN |
ATN rücksetzen, LOW |
set serial ATN high |
set ATN 1 |
||
.,EDD3 20 85 EE JSR $EE85 |
JSR CLKHI ;CLOCK LINE HIGH JSR/RTS |
CLOCK auf LOW setzen |
set the serial clock out high |
set CLK 1 |
||
.,EDD6 20 A9 EE JSR $EEA9 |
TKATN1 JSR DEBPIA ;WAIT FOR CLOCK TO GO LOW |
CLOCK-IN holen |
get the serial data status in Cb |
read serial bus I/O port |
||
.,EDD9 30 FB BMI $EDD6 |
BMI TKATN1 |
auf CLOCK HIGH warten |
loop if the clock is high |
test bit6, and wait for CLK = 0 |
||
.,EDDB 58 CLI |
CLI ;IRQ'S OKAY NOW |
Interruptflag löschen |
enable the interrupts |
enable interrupt |
||
.,EDDC 60 RTS |
RTS ;BUFFERED OUTPUT TO SERIAL BUS ; |
RücksprungIECOUT ein Byte auf IEC-Busausgeben |
output a byte to the serial bus |
CIOUT: SEND SERIAL DEFERREDThe KERNAL routine CIOUT ($ffa8) jumps to this routine.The output flag, C3PO is set (ie. bit 7 = 1) and the contents of (A) is placed in the serial buffer. |
output byte on serial bus |
|
.,EDDD 24 94 BIT $94 |
CIOUT BIT C3P0 ;BUFFERED CHAR? |
noch ein Byte auszugeben ? |
test the deferred character flag |
C3PO flag, character in serial buffer |
||
.,EDDF 30 05 BMI $EDE6 |
BMI CI2 ;YES...SEND LAST ; |
verzweige wenn ja |
if there is a defered character go send it |
yes |
||
.,EDE1 38 SEC |
SEC ;NO... |
Carry setzen |
set carry |
prepare for ROR |
||
.,EDE2 66 94 ROR $94 |
ROR C3P0 ;SET BUFFERED CHAR FLAG |
Flag für gepuffertes Byte setzen |
shift into the deferred character flag |
set C3PO |
||
.,EDE4 D0 05 BNE $EDEB |
BNE CI4 ;BRANCH ALWAYS ; |
unbedingter Sprung |
save the byte and exit, branch always |
always jump |
||
.,EDE6 48 PHA |
CI2 PHA ;SAVE CURRENT CHAR |
Byte merken |
save the byte |
temp store |
||
.,EDE7 20 40 ED JSR $ED40 |
JSR ISOUR ;SEND LAST CHAR |
gepuffertes Byte auf Bus ausgeben |
Tx byte on serial bus |
send data to serial bus |
||
.,EDEA 68 PLA |
PLA ;RESTORE CURRENT CHAR |
Byte zurückholen und |
restore the byte |
|||
.,EDEB 85 95 STA $95 |
CI4 STA BSOUR ;BUFFER CURRENT CHAR |
in Ausgaberegister holen |
save the defered Tx byte |
store character in BSOUR |
||
.,EDED 18 CLC |
CLC ;CARRY-GOOD EXIT |
Carry löschen |
flag ok |
clear carry to indicate no errors |
||
.,EDEE 60 RTS |
RTS ;SEND UNTALK COMMAND ON SERIAL BUS ; |
RücksprungUNTALK senden |
command serial bus to UNTALK |
UNTLK: SEND 'UNTALK'/'UNLISTEN'The KERNAL routine UNTALK ($ffab)and UNLISTEN ($ffae) arevectored here. ATN is set to 0, and CLK is set to 0. (A) is loaded with #$5f for 'UNTALK' and #$3f for 'UNLISTEN'. The command is sent to the serial bus via the 'send TALK/ LISTEN' routine. Finally ATN is set to 1, and after s short delay, CLK and data are both set to 1. |
send talk on serial bus |
|
.,EDEF 78 SEI |
UNTLK SEI |
Interruptflag setzen |
disable the interrupts |
disable interrupts |
||
.,EDF0 20 8E EE JSR $EE8E |
JSR CLKLO |
CLOCK auf HIGH setzen |
set the serial clock out low |
serial bus I/O |
||
.,EDF3 AD 00 DD LDA $DD00 |
LDA D2PRA ;PULL ATN |
Poar A laden |
read VIA 2 DRA, serial port and video address |
set bit4 |
||
.,EDF6 09 08 ORA #$08 |
ORA #$08 |
ATN HIGH setzen und |
mask xxxx 1xxx, set the serial ATN low |
and store, set ATN 0 |
||
.,EDF8 8D 00 DD STA $DD00 |
STA D2PRA |
ausgeben |
save VIA 2 DRA, serial port and video address |
set CLK 0 |
||
.,EDFB A9 5F LDA #$5F |
LDA #$5F ;UNTALK COMMAND |
Kennzeichnung für UNTALK |
set the UNTALK command |
flag UNTALK |
||
.:EDFD 2C .BYTE $2C |
.BYT $2C ;SKIP TWO BYTES ;SEND UNLISTEN COMMAND ON SERIAL BUS ; |
Skip nach $EE00UNLISTEN senden |
makes next line BIT $3FA9command serial bus to UNLISTEN |
mask LDA #$3f with BIT $3fa9 |
send unlisten on serial bus |
|
.,EDFE A9 3F LDA #$3F |
UNLSN LDA #$3F ;UNLISTEN COMMAND |
Kennzeichnung für UNLISTEN |
set the UNLISTEN command |
flag UNLISTEN |
||
.,EE00 20 11 ED JSR $ED11 |
JSR LIST1 ;SEND IT ; ; RELEASE ALL LINES |
ausgeben |
send a control character |
send command to serial bus |
||
.,EE03 20 BE ED JSR $EDBE |
DLABYE JSR SCATN ;ALWAYS RELEASE ATN ; DELAY THEN RELEASE CLOCK AND DATA ; |
ATN rücksetzen, LOW |
set serial ATN high 1ms delay, clock high then data high |
clear ATN |
||
.,EE06 8A TXA |
DLADLH TXA ;DELAY APPROX 60 US |
X-Register merken |
save the device number |
|||
.,EE07 A2 0A LDX #$0A |
LDX #10 |
Warteschleife von |
short delay |
init delay |
||
.,EE09 CA DEX |
DLAD00 DEX |
ca. 40 Mikrosekunden |
decrement the count |
decrement counter |
||
.,EE0A D0 FD BNE $EE09 |
BNE DLAD00 |
abwarten |
loop if not all done |
till ready |
||
.,EE0C AA TAX |
TAX |
X-Register wiederholen |
restore the device number |
|||
.,EE0D 20 85 EE JSR $EE85 |
JSR CLKHI |
CLOCK auf LOW setzen |
set the serial clock out high |
set CLK 1 |
||
.,EE10 4C 97 EE JMP $EE97 |
JMP DATAHI ;INPUT A BYTE FROM SERIAL BUS ; ACPTR |
DATA auf LOW setzenIECIN ein Zeichen vomIEC-Bus holen |
set the serial data out high and returninput a byte from the serial bus |
set data 1ACPTR: RECIEVE FROM SERIAL BUSThe KERNAL routine ACPTR ($ffa5) points to this routine. Atiming loop is enteredusing the CIA timer, and if a byte is not received in 65 ms, ST is set to #$02, ie. a read timeout. A test is made for EOI and if this occurs, ST is set to #$40, indicating end of file. The byte is then received from the serial bus and built up bit by bit in the temporary stora at #$a4. This is transfered to (A) on exit, unless EOI has occured. |
input byte on serial bus |
|
.,EE13 78 SEI |
SEI ;NO IRQ ALLOWED |
Interruptflag setzen |
disable the interrupts |
|||
.,EE14 A9 00 LDA #$00 |
LDA #$00 ;SET EOI/ERROR FLAG |
$00 laden |
set 0 bits to do, will flag EOI on timeour |
|||
.,EE16 85 A5 STA $A5 |
STA COUNT |
und Zähler löschen |
save the serial bus bit count |
CNTDN, counter |
||
.,EE18 20 85 EE JSR $EE85 |
JSR CLKHI ;MAKE SURE CLOCK LINE IS RELEASED |
CLOCK auf LOW setzen |
set the serial clock out high |
set CLK 1 |
||
.,EE1B 20 A9 EE JSR $EEA9 |
ACP00A JSR DEBPIA ;WAIT FOR CLOCK HIGH |
CLOCK-IN LOW ? |
get the serial data status in Cb |
get serial in and clock |
||
.,EE1E 10 FB BPL $EE1B |
BPL ACP00A ; EOIACP |
nein, dann warten |
loop if the serial clock is low |
wait for CLK = 1 |
||
.,EE20 A9 01 LDA #$01 |
LDA #$01 ;SET TIMER 2 FOR 256US |
$01 |
set the timeout count high byte |
|||
.,EE22 8D 07 DC STA $DC07 |
STA D1T2H |
in Timer B HIGH schreiben |
save VIA 1 timer B high byte |
setup CIA#1 timer B, high byte |
||
.,EE25 A9 19 LDA #$19 |
LDA #TIMRB |
Timer |
load timer B, timer B single shot, start timer B |
|||
.,EE27 8D 0F DC STA $DC0F |
STA D1CRB |
starten |
save VIA 1 CRB |
set 1 shot, load and start CIA timer B |
||
.,EE2A 20 97 EE JSR $EE97 |
JSR DATAHI ;DATA LINE HIGH (MAKES TIMMING MORE LIKE VIC-20 |
DATA auf LOW setzen |
set the serial data out high |
set data 1 |
||
.,EE2D AD 0D DC LDA $DC0D |
LDA D1ICR ;CLEAR THE TIMER FLAGS<<<<<<<<<<<< |
Interrupt Control Register |
read VIA 1 ICR |
|||
.,EE30 AD 0D DC LDA $DC0D |
ACP00 LDA D1ICR |
laden |
read VIA 1 ICR |
read CIA#1 ICR |
||
.,EE33 29 02 AND #$02 |
AND #$02 ;CHECK THE TIMER |
Timer B abgelaufen ? |
mask 0000 00x0, timer A interrupt |
test if timer B reaches zero |
||
.,EE35 D0 07 BNE $EE3E |
BNE ACP00B ;RAN OUT..... |
ja, 'TIME OUT' |
if timer A interrupt go ?? |
timeout |
||
.,EE37 20 A9 EE JSR $EEA9 |
JSR DEBPIA ;CHECK THE CLOCK LINE |
CLOCK-IN HIGH ? |
get the serial data status in Cb |
get serial in and clock |
||
.,EE3A 30 F4 BMI $EE30 |
BMI ACP00 ;NO NOT YET |
nein, dann warten |
loop if the serial clock is low |
CLK 1 |
||
.,EE3C 10 18 BPL $EE56 |
BPL ACP01 ;YES..... ; |
unbedingter Sprung |
else go set 8 bits to do, branch always timer A timed out |
CLK 0 |
||
.,EE3E A5 A5 LDA $A5 |
ACP00B LDA COUNT ;CHECK FOR ERROR (TWICE THRU TIMEOUTS) |
lade Zähler |
get the serial bus bit count |
CNTDN |
||
.,EE40 F0 05 BEQ $EE47 |
BEQ ACP00C |
verzweige wenn $00 |
if not already EOI then go flag EOI |
|||
.,EE42 A9 02 LDA #$02 |
LDA #2 |
'TIME OUT' |
else error $02, read timeour |
flag read timeout |
||
.,EE44 4C B2 ED JMP $EDB2 |
JMP CSBERR ; ST = 2 READ TIMEOUT ; ; TIMER RAN OUT DO AN EOI THING ; |
Status setzen |
set the serial status and exit |
set I/O status word |
||
.,EE47 20 A0 EE JSR $EEA0 |
ACP00C JSR DATALO ;DATA LINE LOW |
DATA auf HIGH setzen |
set the serial data out low |
set data 1 |
||
.,EE4A 20 85 EE JSR $EE85 |
JSR CLKHI ; DELAY AND THEN SET DATAHI (FIX FOR 40US C64) |
CLOCK auf LOW setzen |
set the serial clock out high |
set CLK 1 |
||
.,EE4D A9 40 LDA #$40 |
LDA #$40 |
Bit 6 für 'END OR IDENTIFY' |
set EOI |
flag EOI |
||
.,EE4F 20 1C FE JSR $FE1C |
JSR UDST ;OR AN EOI BIT INTO STATUS |
Status setzen |
OR into the serial status byte |
set I/O status word |
||
.,EE52 E6 A5 INC $A5 |
INC COUNT ;GO AROUND AGAIN FOR ERROR CHECK ON EOI |
Zähler erhöhen |
increment the serial bus bit count, do error on the next timeout |
increment CNTDN, counter |
||
.,EE54 D0 CA BNE $EE20 |
BNE EOIACP ; ; DO THE BYTE TRANSFER ; |
unbedingter Sprung |
go try again, branch always |
again |
||
.,EE56 A9 08 LDA #$08 |
ACP01 LDA #08 ;SET UP COUNTER |
$08 als |
set 8 bits to do |
set up CNTDN to receive 8 bits |
||
.,EE58 85 A5 STA $A5 |
STA COUNT ; |
Bitzähler setzen |
save the serial bus bit count |
|||
.,EE5A AD 00 DD LDA $DD00 |
ACP03 LDA D2PRA ;WAIT FOR CLOCK HIGH |
Port A laden |
read VIA 2 DRA, serial port and video address |
serial bus I/O port |
||
.,EE5D CD 00 DD CMP $DD00 |
CMP D2PRA ;DEBOUNCE |
Änderung ? |
compare it with itself |
compare |
||
.,EE60 D0 F8 BNE $EE5A |
BNE ACP03 |
verzweige wenn ja |
if changing go try again |
wait for serial bus to settle |
||
.,EE62 0A ASL |
ASL A ;SHIFT DATA INTO CARRY |
Datenbit ins Carry schieben |
shift the serial data into the carry |
|||
.,EE63 10 F5 BPL $EE5A |
BPL ACP03 ;CLOCK STILL LOW... |
erneut holen wenn CLOCK = 1 |
loop while the serial clock is low |
wait for data in =1 |
||
.,EE65 66 A4 ROR $A4 |
ROR BSOUR1 ;ROTATE DATA IN ; |
Datenbit in $A4 schieben |
shift the data bit into the receive byte |
roll in received bit in temp data area |
||
.,EE67 AD 00 DD LDA $DD00 |
ACP03A LDA D2PRA ;WAIT FOR CLOCK LOW |
Port A laden |
read VIA 2 DRA, serial port and video address |
serial bus I/O port |
||
.,EE6A CD 00 DD CMP $DD00 |
CMP D2PRA ;DEBOUNCE |
Änderung ? |
compare it with itself |
compare |
||
.,EE6D D0 F8 BNE $EE67 |
BNE ACP03A |
verzweige wenn ja |
if changing go try again |
wait for bus to settle |
||
.,EE6F 0A ASL |
ASL A |
Datenbit ins Carry schieben |
shift the serial data into the carry |
|||
.,EE70 30 F5 BMI $EE67 |
BMI ACP03A |
erneut wenn CLOCK = 0 |
loop while the serial clock is high |
wait for data in =0 |
||
.,EE72 C6 A5 DEC $A5 |
DEC COUNT |
Bitzähler veringerrn |
decrement the serial bus bit count |
one bit received |
||
.,EE74 D0 E4 BNE $EE5A |
BNE ACP03 ;MORE BITS..... ;...EXIT... |
verzweige wenn noch nicht alle 8 Bits gesendet |
loop if not all done |
repeat for all 8 bits |
||
.,EE76 20 A0 EE JSR $EEA0 |
JSR DATALO ;DATA LOW |
DATA auf HIGH setzen |
set the serial data out low |
set data 1 |
||
.,EE79 24 90 BIT $90 |
BIT STATUS ;CHECK FOR EOI |
Status |
test the serial status byte |
STATUS, I/O status word |
||
.,EE7B 50 03 BVC $EE80 |
BVC ACP04 ;NONE... ; |
verzweige wenn kein 'EOI' ? |
if EOI not set skip the bus end sequence |
not EOI |
||
.,EE7D 20 06 EE JSR $EE06 |
JSR DLADLH ;DELAY THEN SET DATA HIGH ; |
warten und Bits 101 senden |
1ms delay, clock high then data high |
handshake and exit without byte |
||
.,EE80 A5 A4 LDA $A4 |
ACP04 LDA BSOUR1 |
Datenbyte in Akku holen |
get the receive byte |
read received byte |
||
.,EE82 58 CLI |
CLI ;IRQ IS OK |
Interruptflag löschen |
enable the interrupts |
enable interrupts |
||
.,EE83 18 CLC |
CLC ;GOOD EXIT |
Carry löschen |
flag ok |
clear carry, no errors |
||
.,EE84 60 RTS |
RTS ; CLKHI ;SET CLOCK LINE HIGH (INVERTED) |
RücksprungCLOCK auf LOW setzen |
set the serial clock out high |
SERIAL CLOCK ONThis routine sets the clock outline on the serial bus to1. This means writing a 0 to the port. This value is reversed by hardware on the bus. |
set serial clock line low |
|
.,EE85 AD 00 DD LDA $DD00 |
LDA D2PRA |
Port A laden |
read VIA 2 DRA, serial port and video address |
serial port I/O register |
||
.,EE88 29 EF AND #$EF |
AND #$FF-$10 |
Bit 4 löschen |
mask xxx0 xxxx, set serial clock out high |
clear bit4, ie. CLK out =1 |
||
.,EE8A 8D 00 DD STA $DD00 |
STA D2PRA |
und wieder speichern |
save VIA 2 DRA, serial port and video address |
store |
||
.,EE8D 60 RTS |
RTS ; CLKLO ;SET CLOCK LINE LOW (INVERTED) |
RücksprungCLOCK auf HIGH setzen |
set the serial clock out low |
SERIAL CLOCK OFFThis routine sets the clock outline on the serial bus to0. This means writing a 1 to the port. This value is reversed by hardware on the bus. |
set serial clock line high |
|
.,EE8E AD 00 DD LDA $DD00 |
LDA D2PRA |
Port A laden |
read VIA 2 DRA, serial port and video address |
serial port I/O register |
||
.,EE91 09 10 ORA #$10 |
ORA #$10 |
Bit 4 setzen |
mask xxx1 xxxx, set serial clock out low |
set bit4, ie. CLK out =0 |
||
.,EE93 8D 00 DD STA $DD00 |
STA D2PRA |
und wieder speichern |
save VIA 2 DRA, serial port and video address |
store |
||
.,EE96 60 RTS |
RTS ; ; DATAHI ;SET DATA LINE HIGH (INVERTED) |
RücksprungDATA auf LOW setzen |
set the serial data out high |
SERIAL OUTPUT 1This routine sets the data out line on the serial bus to1. This means writing a 0 to the port. This value is reversed by hardware on the bus. |
set serial data line low |
|
.,EE97 AD 00 DD LDA $DD00 |
LDA D2PRA |
Port A laden |
read VIA 2 DRA, serial port and video address |
serial bus I/O register |
||
.,EE9A 29 DF AND #$DF |
AND #$FF-$20 |
Bit 5 löschen |
mask xx0x xxxx, set serial data out high |
clear bit5 |
||
.,EE9C 8D 00 DD STA $DD00 |
STA D2PRA |
und wieder speichern |
save VIA 2 DRA, serial port and video address |
store |
||
.,EE9F 60 RTS |
RTS ; DATALO ;SET DATA LINE LOW (INVERTED) |
RücksprungDATA auf HIGH setzen |
set the serial data out low |
SERIAL OUTPUT 0This routine sets the data out line on the serial bus to0. This means writing a 1 to the port. This value is reversed by hardware on the bus. |
set serial data line high |
|
.,EEA0 AD 00 DD LDA $DD00 |
LDA D2PRA |
Port A laden |
read VIA 2 DRA, serial port and video address |
serial bus I/O resister |
||
.,EEA3 09 20 ORA #$20 |
ORA #$20 |
Bit 5 setzen |
mask xx1x xxxx, set serial data out low |
set bit 5 |
||
.,EEA5 8D 00 DD STA $DD00 |
STA D2PRA |
und wieder speichern |
save VIA 2 DRA, serial port and video address |
store |
||
.,EEA8 60 RTS |
RTS ; |
RücksprungBit vom IEC-Bus insCarry-Flag holen |
get the serial data status in Cb |
GET SERIAL DATA AND CLOCK INThe serial port I/O register is stabilised and read. Thedata is shifteed into carry and CLK into bit 7. This way, both the data and clock can bee determined by flags in the processor status register. Note that the values read are true, and do not nead to be reversed in the same way as the outuput line do. |
||
.,EEA9 AD 00 DD LDA $DD00 |
DEBPIA LDA D2PRA ;DEBOUNCE THE PIA |
Port A laden |
read VIA 2 DRA, serial port and video address |
serial port I/O register |
||
.,EEAC CD 00 DD CMP $DD00 |
CMP D2PRA |
Änderung ? |
compare it with itself |
compare |
||
.,EEAF D0 F8 BNE $EEA9 |
BNE DEBPIA |
verzweige wenn ja |
if changing got try again |
wait for bus to settle |
||
.,EEB1 0A ASL |
ASL A ;SHIFT THE DATA BIT INTO THE CARRY... |
Datenbit ins Carry schieben |
shift the serial data into Cb |
shift data into carry, and CLK into bit 7 |
||
.,EEB2 60 RTS |
RTS ;...AND THE CLOCK INTO NEG FLAG ; W1MS ;DELAY 1MS USING LOOP |
RücksprungVerzögerung 1 Millisekunde |
1ms delay |
DELAY 1 MSThis routine is a software delay loop where (X) is used ascounter, and are decremented for a period of 1 millisecond. The original (X) is stored on entry and (A) is messed up. |
delay 1 millisecond |
|
.,EEB3 8A TXA |
TXA ;SAVE .X |
X-Register retten |
save X |
move (X) to (A) |
||
.,EEB4 A2 B8 LDX #$B8 |
LDX #200-16 ;1000US-(1000/500*8=#40US HOLDS) |
X-Register mit $B8 laden |
set the loop count |
start value |
||
.,EEB6 CA DEX |
W1MS1 DEX ;5US LOOP |
herunterzählen |
decrement the loop count |
decrement |
||
.,EEB7 D0 FD BNE $EEB6 |
BNE W1MS1 |
verzweige wenn nicht fertig |
loop if more to do |
untill zero |
||
.,EEB9 AA TAX |
TAX ;RESTORE .X |
X-Register wiederherstellen |
restore X |
(A) to (X) |
||
.,EEBA 60 RTS |
RTS .END .LIB RS232TRANS; RSTRAB - ENTRY FOR NMI CONTINUE ROUTINE; RSTBGN - ENTRY FOR START TRANSMITTER ; ; RSR - 8/18/80 ; ; VARIABLES USED ; BITTS - # OF BITS TO BE SENT (<>0 NOT DONE) ; NXTBIT - BYTE CONTAINS NEXT BIT TO BE SENT ; ROPRTY - BYTE CONTAINS PARITY BIT CALCULATED ; RODATA - STORES DATA BYTE CURRENTLY BEING TRANSMITTED ; RODBS - OUTPUT BUFFER INDEX START ; RODBE - OUTPUT BUFFER INDEX END ; IF RODBS=RODBE THEN BUFFER EMPTY ; ROBUF - INDIRECT POINTER TO DATA BUFFER ; RSSTAT - RS-232 STATUS BYTE ; ; XXX US - NORMAL BIT PATH ; XXX US - WORST CASE PARITY BIT PATH ; XXX US - STOP BIT PATH ; XXX US - START BIT PATH ; |
RücksprungRS 232 Ausgabe |
RS232 Tx NMI routine |
RS232 SENDThis routine is concerned with sending a byte on the RS232port. The data is actually written to the port under NMI interrupt control. The CTS line generates an NMI when the port is ready for data. If all the bits in the byte have been sent, then a new RS232 byte is set up. Otherwise, this routine calculates parity and number of stop bits set up in the OPEN command. These bits are added to the end of the byte being sent. |
set next bit to transmit on RS-232 |
|
.,EEBB A5 B4 LDA $B4 |
RSTRAB LDA BITTS ;CHECK FOR PLACE IN BYTE... |
Anzahl Bits zu senden |
get RS232 bit count |
BITTS, RS232 out bit count |
||
.,EEBD F0 47 BEQ $EF06 |
BEQ RSTBGN ;...DONE, =0 START NEXT ; |
verzweige wenn Byte schon komplett übertragen |
if zero go setup next RS232 Tx byte and return |
send new RS232 byte |
||
.,EEBF 30 3F BMI $EF00 |
BMI RST050 ;...DOING STOP BITS ; |
verzweige falls Stopbit erforderlich |
if -ve go do stop bit(s) else bit count is non zero and +ve |
|||
.,EEC1 46 B6 LSR $B6 |
LSR RODATA ;SHIFT DATA INTO CARRY |
nächstes Bit ins Carry schieben |
shift RS232 output byte buffer |
RODATA, RS232 out byte buffer |
||
.,EEC3 A2 00 LDX #$00 |
LDX #00 ;PREPARE FOR A ZERO |
'0' falls Datenbit = 0 |
set $00 for bit = 0 |
|||
.,EEC5 90 01 BCC $EEC8 |
BCC RST005 ;YES...A ZERO |
verzweige wenn Datenbit gelöscht |
branch if bit was 0 |
|||
.,EEC7 CA DEX |
DEX ;NO...MAKE AN $FF |
nein, dann X-Register =$FF |
set $FF for bit = 1 |
|||
.,EEC8 8A TXA |
RST005 TXA ;READY TO SEND ; |
X-Register in Akku |
copy bit to A |
|||
.,EEC9 45 BD EOR $BD |
EOR ROPRTY ;CALC INTO PARITY |
mit Register für Paritybit verknüpfen |
EOR with RS232 parity byte |
ROPRTY, RS232 out parity |
||
.,EECB 85 BD STA $BD |
STA ROPRTY ; |
und abspeichern |
save RS232 parity byte |
|||
.,EECD C6 B4 DEC $B4 |
DEC BITTS ;BIT COUNT DOWN |
Bitzähler erniedrigen |
decrement RS232 bit count |
BITTS |
||
.,EECF F0 06 BEQ $EED7 |
BEQ RST010 ;WANT A PARITY INSTEAD ; |
verzweige wenn alle Bits übertragen |
if RS232 bit count now zero go do parity bit save bit and exit |
|||
.,EED1 8A TXA |
RSTEXT TXA ;CALC BIT WHOLE TO SEND |
alten Akku wiederherstellen |
copy bit to A |
|||
.,EED2 29 04 AND #$04 |
AND #$04 ;GOES OUT D2PA2 |
Bit 2 isolieren |
mask 0000 0x00, RS232 Tx DATA bit |
|||
.,EED4 85 B5 STA $B5 |
STA NXTBIT |
und ins Ausgaberegister bringen |
save the next RS232 data bit to send |
NXTBIT, next RS232 bit to send |
||
.,EED6 60 RTS |
RTS ; CALCULATE PARITY ; NXTBIT =0 UPON ENTRY ; |
Rücksprung |
do RS232 parity bit, enters with RS232 bit count = 0 |
|||
.,EED7 A9 20 LDA #$20 |
RST010 LDA #$20 ;CHECK 6551 REG BITS |
Bit 5 (Parity) |
mask 00x0 0000, parity enable bit |
|||
.,EED9 2C 94 02 BIT $0294 |
BIT M51CDR |
RS 232 Befehlsregister abfragen |
test the pseudo 6551 command register |
M51CDR, 6551 command register immage |
||
.,EEDC F0 14 BEQ $EEF2 |
BEQ RSPNO ;...NO PARITY, SEND A STOP |
verzweige wenn ohne Parity |
if parity disabled go ?? |
no patity |
||
.,EEDE 30 1C BMI $EEFC |
BMI RST040 ;...NOT REAL PARITY |
verzweige wenn feste Parität |
if fixed mark or space parity go ?? |
mark/space transmit |
||
.,EEE0 70 14 BVS $EEF6 |
BVS RST030 ;...EVEN PARITY ; |
verzweige wenn ungerade Parität |
if even parity go ?? else odd parity |
even parity |
||
.,EEE2 A5 BD LDA $BD |
LDA ROPRTY ;CALC ODD PARITY |
verzweige wenn Parity gleich eins |
get RS232 parity byte |
ROPRTY, out parity |
||
.,EEE4 D0 01 BNE $EEE7 |
BNE RSPEXT ;CORRECT GUESS ; |
verzweige wenn ja |
if parity not zero leave parity bit = 0 |
|||
.,EEE6 CA DEX |
RSWEXT DEX ;WRONG GUESS...ITS A ONE ; |
Parity $FF |
make parity bit = 1 |
|||
.,EEE7 C6 B4 DEC $B4 |
RSPEXT DEC BITTS ;ONE STOP BIT ALWAYS |
Bitzähler auf $FF |
decrement RS232 bit count, 1 stop bit |
BITTS, out bit count |
||
.,EEE9 AD 93 02 LDA $0293 |
LDA M51CTR ;CHECK # OF STOP BITS |
RS 232 Kontrollregister laden |
get pseudo 6551 control register |
M51CTR, 6551 control register image |
||
.,EEEC 10 E3 BPL $EED1 |
BPL RSTEXT ;...ONE |
verzweige wenn zwei Stopbits |
if 1 stop bit save parity bit and exit else two stop bits .. |
one stop bit only |
||
.,EEEE C6 B4 DEC $B4 |
DEC BITTS ;...TWO |
Bitzähler auf $FE |
decrement RS232 bit count, 2 stop bits |
BITTS |
||
.,EEF0 D0 DF BNE $EED1 |
BNE RSTEXT ;JUMP ; RSPNO ;LINE TO SEND CANNOT BE PB0 |
unbedingter Sprung zur Berechnung der Stopbits |
save bit and exit, branch always parity is disabled so the parity bit becomes the first, and possibly only, stop bit. to do this increment the bit count which effectively decrements the stop bit count. |
|||
.,EEF2 E6 B4 INC $B4 |
INC BITTS ;COUNTS AS ONE STOP BIT |
Bitzähler erhöhen, keine Parity |
increment RS232 bit count, = -1 stop bit |
BITTS |
||
.,EEF4 D0 F0 BNE $EEE6 |
BNE RSWEXT ;JUMP TO FLIP TO ONE ; |
unbedingter Sprung zur Berechnung der Stopbits |
set stop bit = 1 and exit do even parity |
|||
.,EEF6 A5 BD LDA $BD |
RST030 LDA ROPRTY ;EVEN PARITY |
Parity |
get RS232 parity byte |
ROPRTY |
||
.,EEF8 F0 ED BEQ $EEE7 |
BEQ RSPEXT ;CORRECT GUESS...EXIT |
verzweige wenn gleich 0, dann Null-Bit ausgeben |
if parity zero leave parity bit = 0 |
|||
.,EEFA D0 EA BNE $EEE6 |
BNE RSWEXT ;WRONG...FLIP AND EXIT ; |
unbedingter Sprung 1-Bit ausgeben |
else make parity bit = 1, branch always fixed mark or space parity |
|||
.,EEFC 70 E9 BVS $EEE7 |
RST040 BVS RSPEXT ;WANTED SPACE |
Null-Bit ausgeben |
if fixed space parity leave parity bit = 0 |
|||
.,EEFE 50 E6 BVC $EEE6 |
BVC RSWEXT ; WANTED MARK ; STOP BITS ; |
sonst 1-Bit ausgeben (feste Parität) |
else fixed mark parity make parity bit = 1, branch always decrement stop bit count, set stop bit = 1 and exit. $FF is one stop bit, $FE is two stop bits |
|||
.,EF00 E6 B4 INC $B4 |
RST050 INC BITTS ;STOP BIT COUNT TOWARDS ZERO |
Bitzähler erhöhen |
decrement RS232 bit count |
BITTS |
||
.,EF02 A2 FF LDX #$FF |
LDX #$FF ;SEND STOP BIT |
Wert für Stopbit |
set stop bit = 1 |
|||
.,EF04 D0 CB BNE $EED1 |
BNE RSTEXT ;JUMP TO EXIT ; ; RSTBGN - ENTRY TO START BYTE TRANS ; |
unbedingter Sprung |
save stop bit and exit, branch alwayssetup next RS232 Tx byte |
SEND NEW RS232 BYTEThis routine sets up the system variables ready to send anew byte to the RS232 port. A test is made for 3-line or X-line modus. In X-line mode, DSR and CTS are checked. |
||
.,EF06 AD 94 02 LDA $0294 |
RSTBGN LDA M51CDR ;CHECK FOR 3/X LINE |
RS 232 Befehlsregister laden |
read the 6551 pseudo command register |
M51CDR, 6551 command register |
||
.,EF09 4A LSR |
LSR A |
Bit 0 ins Carry |
handshake bit inot Cb |
test handshake mode |
||
.,EF0A 90 07 BCC $EF13 |
BCC RST060 ;3 LINE...NO CHECK |
verzweige wenn 3-Line Handshake, Abfrage übergehen |
if 3 line interface go ?? |
3-line mode (no handshake) |
||
.,EF0C 2C 01 DD BIT $DD01 |
BIT D2PRB ;CHECK FOR... |
Port B abfragen |
test VIA 2 DRB, RS232 port |
RS232 port |
||
.,EF0F 10 1D BPL $EF2E |
BPL DSRERR ;...DSR ERROR |
verzweige wenn DSR fehlt |
if DSR = 0 set DSR signal not present and exit |
no DSR, error |
||
.,EF11 50 1E BVC $EF31 |
BVC CTSERR ;...CTS ERROR ; ; SET UP TO SEND NEXT BYTE ; |
verzweige wenn CTS fehlt |
if CTS = 0 set CTS signal not present and exit was 3 line interface |
no CTS, error |
||
.,EF13 A9 00 LDA #$00 |
RST060 LDA #0 |
0 laden und |
clear A |
|||
.,EF15 85 BD STA $BD |
STA ROPRTY ;ZERO PARITY |
Parity-Register löschen |
clear the RS232 parity byte |
ROPRTY, RS232 out parity |
||
.,EF17 85 B5 STA $B5 |
STA NXTBIT ;SEND START BIT |
Register für zu sendendes Bit (Startbit) |
clear the RS232 next bit to send |
NXTBIT, next bit to send |
||
.,EF19 AE 98 02 LDX $0298 |
LDX BITNUM ;GET # OF BITS |
Anzahl der zu übertragenden Bits |
get the number of bits to be sent/received |
BITNUM, number of bits left to send |
||
.,EF1C 86 B4 STX $B4 |
RST070 STX BITTS ;BITTS=#OF BITTS+1 ; |
als Bitzähler merken |
set the RS232 bit count |
BITTS, RS232 out bit count |
||
.,EF1E AC 9D 02 LDY $029D |
RST080 LDY RODBS ;CHECK BUFFER POINTERS |
lade Zeiger für übertragenes Byte |
get the index to the Tx buffer start |
RODBS, start page of out buffer |
||
.,EF21 CC 9E 02 CPY $029E |
CPY RODBE |
alle Bytes übertragen ? |
compare it with the index to the Tx buffer end |
RODBE, index to end if out buffer |
||
.,EF24 F0 13 BEQ $EF39 |
BEQ RSODNE ;ALL DONE... ; |
ja, dann abschließen |
if all done go disable T?? interrupt and return |
disable timer |
||
.,EF26 B1 F9 LDA ($F9),Y |
LDA (ROBUF)Y ;GET DATA... |
Datenbyte aus RS 232 Puffer holen |
else get a byte from the buffer |
RS232 out buffer |
||
.,EF28 85 B6 STA $B6 |
STA RODATA ;...INTO BYTE BUFFER |
zum Senden übergeben |
save it to the RS232 output byte buffer |
RODATA, RS232 out byte buffer |
||
.,EF2A EE 9D 02 INC $029D |
INC RODBS ;MOVE POINTER TO NEXT |
Pufferzeiger erhöhen |
increment the index to the Tx buffer start |
RODBS |
||
.,EF2D 60 RTS |
RTS ; SET ERRORS ; |
Rücksprung |
set DSR signal not present |
NO DSR / CTS ERROR(A) is loaded with the error flag - $40 for no DSR, and$10 for no CTS. This is then ORed with 6551 status image and stored in RSSTAT. |
handle RS-232 errors |
|
.,EF2E A9 40 LDA #$40 |
DSRERR LDA #$40 ;DSR GONE ERROR |
DSR (Data Set Ready) fehlt |
set DSR signal not present |
entrypoint for 'NO DSR' |
||
.:EF30 2C .BYTE $2C |
.BYT $2C |
Skip nach $EF33 |
makes next line BIT $10A9set CTS signal not present |
mask next LDA-command |
||
.,EF31 A9 10 LDA #$10 |
CTSERR LDA #$10 ;CTS GONE ERROR |
CTS (Clear To Send) fehlt |
set CTS signal not present |
entrypoint for 'NO CTS' |
||
.,EF33 0D 97 02 ORA $0297 |
ORA RSSTAT |
mit Status verknüpfen |
OR it with the RS232 status register |
RSSTAT, 6551 status register image |
||
.,EF36 8D 97 02 STA $0297 |
STA RSSTAT ; ; ERRORS TURN OFF T1 ; |
und setzen |
save the RS232 status registerdisable timer A interrupt |
DISABLE TIMERThis routine set the interrupt mask on CIA#2 timer B. Italso clears the NMI flag. |
||
.,EF39 A9 01 LDA #$01 |
RSODNE LDA #$01 ;KILL T1 NMI ;ENTRY TO TURN OFF AN ENABLED NMI... |
NMI für |
disable timer A interruptset VIA 2 ICR from A |
; CIA#2 interrupt control register |
||
.,EF3B 8D 0D DD STA $DD0D |
OENABL STA D2ICR ;TOSS BAD/OLD NMI |
Timer A löschen |
save VIA 2 ICR |
; ENABL, RS232 enables |
||
.,EF3E 4D A1 02 EOR $02A1 |
EOR ENABL ;FLIP ENABLE |
Flag für |
EOR with the RS-232 interrupt enable byte |
|||
.,EF41 09 80 ORA #$80 |
ORA #$80 ;ENABLE GOOD NMI'S |
RS 232 umdrehen |
set the interrupts enable bit |
; ENABL |
||
.,EF43 8D A1 02 STA $02A1 |
STA ENABL |
und speichern |
save the RS-232 interrupt enable byte |
; CIA#2 interrupt control register |
||
.,EF46 8D 0D DD STA $DD0D |
STA D2ICR |
IRR setzen, alle übrigen zulassen NMIs |
save VIA 2 ICR |
|||
.,EF49 60 RTS |
RTS ; BITCNT - CAL # OF BITS TO BE SENT ; RETURNS #OF BITS+1 ; |
RücksprungAnzahl der RS 232 Datenbitsberechnen |
compute bit count |
COMPUTE BIT COUNTThis routine computes the number of bits in the word to besent. The word length information is held in bits 5 & 6 of M51CTR. Bit 7 of this register indicates the number of stop bits. On exit, the number of bits is held in (X). |
check control register |
|
.,EF4A A2 09 LDX #$09 |
BITCNT LDX #9 ;CALC WORD LENGTH |
Zähler für Wortlänge |
set bit count to 9, 8 data + 1 stop bit |
|||
.,EF4C A9 20 LDA #$20 |
LDA #$20 |
Maskenwert für Bit 5 |
mask for 8/7 data bits |
|||
.,EF4E 2C 93 02 BIT $0293 |
BIT M51CTR |
Testen vom RS-232 Kontrollregister |
test pseudo 6551 control register |
M51CTR, 6551 control register image |
||
.,EF51 F0 01 BEQ $EF54 |
BEQ BIT010 |
verzweige wenn Bit 5 gelöscht |
branch if 8 bits |
|||
.,EF53 CA DEX |
DEX ;BIT 5 HIGH IS A 7 OR 5 |
Zähler für Wortlänge vermindern |
else decrement count for 7 data bits |
|||
.,EF54 50 02 BVC $EF58 |
BIT010 BVC BIT020 |
verzweige wenn Bit 6 gelöscht |
branch if 7 bits |
|||
.,EF56 CA DEX |
DEX ;BIT 6 HIGH IS A 6 OR 5 |
Wortlänge um zwei |
else decrement count .. |
|||
.,EF57 CA DEX |
DEX |
vermindern |
.. for 5 data bits |
|||
.,EF58 60 RTS |
BIT020 RTS .END .LIB RS232RCVR; RSRCVR - NMI ROUTINE TO COLLECT; DATA INTO BYTES ; ; RSR 8/18/80 ; ; VARIABLES USED ; INBIT - INPUT BIT VALUE ; BITCI - BIT COUNT IN ; RINONE - FLAG FOR START BIT CHECK <>0 START BIT ; RIDATA - BYTE INPUT BUFFER ; RIPRTY - HOLDS BYTE INPUT PARITY ; RIBUF - INDIRECT POINTER TO DATA BUFFER ; RIDBE - INPUT BUFFER INDEX TO END ; RIDBS - INPUT BUFFER POINTER TO START ; IF RIDBE=RIDBS THEN INPUT BUFFER EMPTY ; |
Rücksprungempfangenes Bit verarbeiten |
RS232 Rx NMI |
RS232 RECEIVEThis routine builds up the input byte from the RS232 portin RIDATA. Each bit is input from the port under NMI interrupt control. The bit is placed in INBIT before being passed to this routine, where it is shifted into the carry flag and then rotated into RIDATA. The bit count is decremented and parity updated. |
add bit input on RS-232 bus to word being input |
|
.,EF59 A6 A9 LDX $A9 |
RSRCVR LDX RINONE ;CHECK FOR START BIT |
Startbit ? |
get start bit check flag |
RINONE, check for start bit? |
||
.,EF5B D0 33 BNE $EF90 |
BNE RSRTRT ;WAS START BIT ; |
verzweige wenn ja |
if no start bit received go ?? |
|||
.,EF5D C6 A8 DEC $A8 |
DEC BITCI ;CHECK WHERE WE ARE IN INPUT... |
Bitzähler erniedrigen |
decrement receiver bit count in |
BITC1, RS232 in bit count |
||
.,EF5F F0 36 BEQ $EF97 |
BEQ RSR030 ;HAVE A FULL BYTE |
verzweige wenn alle Bits empfangen |
if the byte is complete go add it to the buffer |
process received byte |
||
.,EF61 30 0D BMI $EF70 |
BMI RSR020 ;GETTING STOP BITS ; ; CALC PARITY ; |
verzweige wenn noch Stopbits zu erwarten |
||||
.,EF63 A5 A7 LDA $A7 |
LDA INBIT ;GET DATA UP |
empfangenes Bit |
get the RS232 received data bit |
INBIT, RS232 in bits |
||
.,EF65 45 AB EOR $AB |
EOR RIPRTY ;CALC NEW PARITY |
mit Register für Parity verknüpfen |
EOR with the receiver parity bit |
RIPRTY, RS232 in parity |
||
.,EF67 85 AB STA $AB |
STA RIPRTY ; ; SHIFT DATA BIT IN ; |
und abspeichern |
save the receiver parity bit |
|||
.,EF69 46 A7 LSR $A7 |
LSR INBIT ;IN BIT POS 0 |
empfangenes Bit ins Carry |
shift the RS232 received data bit |
INBIT, put input bit into carry |
||
.,EF6B 66 AA ROR $AA |
ROR RIDATA ;C INTO DATA ; ; EXIT ; |
und in Empfangsregister schieben |
RIDATA, |
|||
.,EF6D 60 RTS |
RSREXT RTS ; HAVE STOP BIT, SO STORE IN BUFFER ; |
Rücksprung |
handle end of word for RS-232 input |
|||
.,EF6E C6 A8 DEC $A8 |
RSR018 DEC BITCI ;NO PARITY, DEC SO CHECK WORKS |
Bitzähler erniedrigen |
decrement receiver bit count in |
BITC1 |
||
.,EF70 A5 A7 LDA $A7 |
RSR020 LDA INBIT ;GET DATA... |
Stopbit |
get the RS232 received data bit |
INBIT |
||
.,EF72 F0 67 BEQ $EFDB |
BEQ RSR060 ;...ZERO, AN ERROR? ; |
verzweige wenn gleich Null |
||||
.,EF74 AD 93 02 LDA $0293 |
LDA M51CTR ;CHECK FOR CORRECT # OF STOP BITS |
Kontrollregister laden |
get pseudo 6551 control register |
M51CTR, 6551 control register image |
||
.,EF77 0A ASL |
ASL A ;CARRY TELL HOW MAY STOP BITS |
Bit 7 (Anzahl Stopbits) ins Carry |
shift the stop bit flag to Cb |
|||
.,EF78 A9 01 LDA #$01 |
LDA #01 |
1 laden und mit der Anzahl |
+ 1 |
|||
.,EF7A 65 A8 ADC $A8 |
ADC BITCI |
von Bits und Stopbits addieren |
add receiver bit count in |
BITC1 |
||
.,EF7C D0 EF BNE $EF6D |
BNE RSREXT ;NO..EXIT ; ; RSRABL - ENABLE TO RECIEVE A BYTE ; |
verzweige wenn noch nicht alle Stopbits empfangen |
exit, branch alwayssetup to receive an RS232 bit |
endSET UP TO RECEIVEThis routine sets up the I.C.R. to wait for the receiveredge, and flags this into ENABL. It then flags the check for a start bit. |
enable byte reception |
|
.,EF7E A9 90 LDA #$90 |
RSRABL LDA #$90 ;ENABLE FLAG FOR NEXT BYTE |
Wert für Freigabe von NMI über die Flagleitung |
enable FLAG interrupt |
|||
.,EF80 8D 0D DD STA $DD0D |
STA D2ICR ;TOSS BAD/OLD NMI |
Wert NMI freigeben |
save VIA 2 ICR |
CIA#2 I.C.R. |
||
.,EF83 0D A1 02 ORA $02A1 |
ORA ENABL ;MARK IN ENABLE REGISTER*********** |
auch im NMI Register |
OR with the RS-232 interrupt enable byte |
ENABL, RS232 enables |
||
.,EF86 8D A1 02 STA $02A1 |
STA ENABL ;RE-ENABLED BY JMP OENABL |
für RS 232 NMIs vermerken |
save the RS-232 interrupt enable byte |
|||
.,EF89 85 A9 STA $A9 |
STA RINONE ;FLAG FOR START BIT ; |
und Flag für Startbit setzen |
set start bit check flag, set no start bit received |
RINONE, check for start bit |
||
.,EF8B A9 02 LDA #$02 |
RSRSXT LDA #$02 ;DISABLE T2 |
Bitwert für |
disable timer B interrupt |
|||
.,EF8D 4C 3B EF JMP $EF3B |
JMP OENABL ;FLIP-OFF ENABL*************** ; RECIEVER START BIT CHECK ; |
NMI für Timer B löschen |
set VIA 2 ICR from A and returnno RS232 start bit received |
disable timer and exitPROCESS RS232 BYTEThe byte recieved from the RS232 port is checked againstparity. This involvs checking the input parity options selected, and then verifying the parity bit calculated against that input. If the test is passed, then the byte is stored in the in-buffer. Otherwise an error is flagged into RSSTAT. A patch in KERNAL version 3, has been added to the input routine at $ef94 to initialise the RS232 parity byte, RIPRTY, on reception of a start bit. |
receiver start bit test |
|
.,EF90 A5 A7 LDA $A7 |
RSRTRT LDA INBIT ;CHECK IF SPACE |
Startbit laden |
get the RS232 received data bit |
INBIT, RS232 in bits |
||
.,EF92 D0 EA BNE $EF7E |
BNE RSRABL ;BAD...TRY AGAIN |
verzweige wenn ungleich Null |
if ?? go setup to receive an RS232 bit and return |
set up to receive |
||
.,EF94 85 A9 STA $A9 |
STA RINONE ;GOOD...DISABLE FLAG |
Flag für Startbit rücksetzen |
flag the RS232 start bit and set the parityreceived a whole byte, add it to the buffer |
patch, init parity byte |
put received data into RS-232 buffer |
|
.,EF96 60 RTS |
RTS ;AND EXIT ; ; PUT DATA IN BUFFER (AT PARITY TIME) ; |
RücksprungEmpfangenes Byteweiterverarbeiten |
||||
.,EF97 AC 9B 02 LDY $029B |
RSR030 LDY RIDBE ;GET END |
Pufferzeiger laden |
get index to Rx buffer end |
RIDBE, index to the end of in buffer |
||
.,EF9A C8 INY |
INY |
und erhöhen |
increment index |
|||
.,EF9B CC 9C 02 CPY $029C |
CPY RIDBS ;HAVE WE PASSED START? |
mit Empfangspuffer vergleichen |
compare with index to Rx buffer start |
RIDBS, start page of in buffer |
||
.,EF9E F0 2A BEQ $EFCA |
BEQ RECERR ;YES...ERROR ; |
verzweige wenn voll, dann Status setzen |
if buffer full go do Rx overrun error |
receive overflow error |
||
.,EFA0 8C 9B 02 STY $029B |
STY RIDBE ;MOVE RIDBE FOWARD |
Pufferzeiger abspeichern |
save index to Rx buffer end |
RIDBE |
||
.,EFA3 88 DEY |
DEY ; |
und normalisieren |
decrement index |
|||
.,EFA4 A5 AA LDA $AA |
LDA RIDATA ;GET BYTE BUFFER UP |
empfangenes Byte laden |
get assembled byte |
RIDATA, RS232 in byte buffer |
||
.,EFA6 AE 98 02 LDX $0298 |
LDX BITNUM ;SHIFT UNTILL FULL BYTE |
Anzahl Datenbits laden |
get bit count |
BITNUM, number of bits left to send |
||
.,EFA9 E0 09 CPX #$09 |
RSR031 CPX #9 ;ALWAYS 8 BITS |
8 Bits plus ein Stopbit? |
compare with byte + stop |
full word to come? |
||
.,EFAB F0 04 BEQ $EFB1 |
BEQ RSR032 |
verzweige wenn ja, ok |
branch if all nine bits received |
yes |
||
.,EFAD 4A LSR |
LSR A ;FILL WITH ZEROS |
sonst Bits in richtige Position schieben |
else shift byte |
|||
.,EFAE E8 INX |
INX |
Datenbitzähler um 1 erhöhen |
increment bit count |
|||
.,EFAF D0 F8 BNE $EFA9 |
BNE RSR031 ; |
unbedingter Sprung |
loop, branch always |
|||
.,EFB1 91 F7 STA ($F7),Y |
RSR032 STA (RIBUF)Y ;DATA TO PAGE BUFFER ; ; PARITY CHECKING ; |
Byte in RS 232 Puffer schreiben |
save received byte to Rx buffer |
RIBUF, RS232 in buffer |
||
.,EFB3 A9 20 LDA #$20 |
LDA #$20 ;CHECK 6551 COMMAND REGISTER |
Maskenwert für Paritätsprüfung |
mask 00x0 0000, parity enable bit |
|||
.,EFB5 2C 94 02 BIT $0294 |
BIT M51CDR |
Bit 5 im Kommandregister prüfen |
test the pseudo 6551 command register |
M51CDR, 6551 command register image |
||
.,EFB8 F0 B4 BEQ $EF6E |
BEQ RSR018 ;NO PARITY BIT SO STOP BIT |
verzweige wenn Übertragung ohne Parity |
branch if parity disabled |
parity disabled |
||
.,EFBA 30 B1 BMI $EF6D |
BMI RSREXT ;NO PARITY CHECK ; ; CHECK CALC PARITY ; |
verzweige wenn festes Bit anstelle Parity |
branch if mark or space parity |
parity check disabled, TRS |
||
.,EFBC A5 A7 LDA $A7 |
LDA INBIT |
empfangenes Paritybit laden |
get the RS232 received data bit |
INBIT, parity check |
||
.,EFBE 45 AB EOR $AB |
EOR RIPRTY ;PUT IN WITH PARITY |
mit berechneter Parity vergleichen |
EOR with the receiver parity bit |
RIPRTY, RS232 in parity |
||
.,EFC0 F0 03 BEQ $EFC5 |
BEQ RSR050 ;EVEN PARITY |
verzweige wenn gleich, ok |
receive parity error |
|||
.,EFC2 70 A9 BVS $EF6D |
BVS RSREXT ;ODD...OKAY SO EXIT |
gerade Parity, dann ok |
if ?? just exit |
|||
.:EFC4 2C .BYTE $2C |
.BYT $2C ;SKIP TWO |
Skip nach $EFC7 |
makes next line BIT $A650 |
mask |
||
.,EFC5 50 A6 BVC $EF6D |
RSR050 BVC RSREXT ;EVEN...OKAY SO EXIT ; ; ERRORS REPORTED |
verzweige wenn ungerade Parity, dann ok |
if ?? just exit |
|||
.,EFC7 A9 01 LDA #$01 |
LDA #1 ;PARITY ERROR |
sonst Parity-Fehler |
set Rx parity error |
receive parity error |
||
.:EFC9 2C .BYTE $2C |
.BYT $2C |
Skip nach EFCC |
makes next line BIT $04A9 |
mask |
||
.,EFCA A9 04 LDA #$04 |
RECERR LDA #$4 ;RECIEVER OVERRUN |
Empfängerpuffer voll |
set Rx overrun error |
receive overflow |
||
.:EFCC 2C .BYTE $2C |
.BYT $2C |
Skip nach $EFCF |
makes next line BIT $80A9 |
mask |
||
.,EFCD A9 80 LDA #$80 |
BREAKE LDA #$80 ;BREAK DETECTED |
Break-Befehl empfangen |
set Rx break error |
framing break |
||
.:EFCF 2C .BYTE $2C |
.BYT $2C |
Skip nach $EFD2 |
makes next line BIT $02A9 |
mask |
||
.,EFD0 A9 02 LDA #$02 |
FRAMEE LDA #$02 ;FRAME ERROR |
Rahmen-Fehler |
set Rx frame error |
framing error |
||
.,EFD2 0D 97 02 ORA $0297 |
ERR232 ORA RSSTAT |
mit Code für RS-232 Status verknüpfen |
OR it with the RS232 status byte |
RSSTAT, 6551 status register image |
||
.,EFD5 8D 97 02 STA $0297 |
STA RSSTAT |
und speichern |
save the RS232 status byte |
|||
.,EFD8 4C 7E EF JMP $EF7E |
JMP RSRABL ;BAD EXIT SO HANG ##????????## ; ; CHECK FOR ERRORS ; |
zum Empfang des nächsten Bytes springen |
setup to receive an RS232 bit and return |
set up to receive |
||
.,EFDB A5 AA LDA $AA |
RSR060 LDA RIDATA ;EXPECTING STOP... |
empfangenes Byte |
RIDATA |
|||
.,EFDD D0 F1 BNE $EFD0 |
BNE FRAMEE ;FRAME ERROR |
ungleich 0, dann zu Rahmen- Fehler |
if ?? do frame error |
framing error |
||
.,EFDF F0 EC BEQ $EFCD |
BEQ BREAKE ;COULD BE A BREAK .END .LIB RS232INOUT; OUTPUT A FILE OVER USR PORT; USING RS232 ; |
sonst zu Break-Befehl empfangen RS-232 CKOUT, Ausgabe aufRS-232 |
else do break error, branch alwaysopen RS232 channel for output |
receive breakSUBMIT TO RS232This routine is called when data is required from theRS232 port. Its function is to perform the handshaking on the poort needed to receive the data. If 3 line mode is used, then no handshaking is implemented and the routine exits. |
output of RS-232 device |
|
.,EFE1 85 9A STA $9A |
CKO232 STA DFLTO ;SET DEFAULT OUT |
Gerätenummer abspeichern |
save the output device number |
DFLTO, default output device |
||
.,EFE3 AD 94 02 LDA $0294 |
LDA M51CDR ;CHECK FOR 3/X LINE |
RS 232 Kommandregister laden |
read the pseudo 6551 command register |
M51CDR, 6551 command register image |
||
.,EFE6 4A LSR |
LSR A |
Bit 0 (Handshake) ins Carry |
shift handshake bit to carry |
|||
.,EFE7 90 29 BCC $F012 |
BCC CKO100 ;3LINE...NO TURN AROUND ; ;*TURN AROUND LOGIC ; ; CHECK FOR DSR AND RTS ; |
verzweige wenn 3-Line- Handshake |
if 3 line interface go ?? |
3 line mode, no handshaking, exit |
||
.,EFE9 A9 02 LDA #$02 |
LDA #$02 ;BIT RTS IS ON |
Haske für DATA SET READY |
mask 0000 00x0, RTS out |
|||
.,EFEB 2C 01 DD BIT $DD01 |
BIT D2PRB |
Port B auslesen |
test VIA 2 DRB, RS232 port |
RS232 I/O port |
||
.,EFEE 10 1D BPL $F00D |
BPL CKDSRX ;NO DSR...ERROR |
kein DSR, dann Fehler |
if DSR = 0 set DSR not present and exit |
no DRS, error |
||
.,EFF0 D0 20 BNE $F012 |
BNE CKO100 ;RTS...OUTPUTING OR FULL DUPLEX ; ; CHECK FOR ACTIVE INPUT ; RTS WILL BE LOW IF CURRENTLY INPUTING ; |
verzweige wenn kein Request To Send |
if RTS = 1 just exit |
|||
.,EFF2 AD A1 02 LDA $02A1 |
CKO020 LDA ENABL |
RS-232 NMI Status Laden |
get the RS-232 interrupt enable byte |
ENABL, RS232 enables |
||
.,EFF5 29 02 AND #$02 |
AND #$02 ;LOOK AT IER FOR T2 |
verknüpfe mit Bit für Datenempfang aktiv |
mask 0000 00x0, timer B interrupt |
|||
.,EFF7 D0 F9 BNE $EFF2 |
BNE CKO020 ;HANG UNTILL INPUT DONE ; ; WAIT FOR CTS TO BE OFF AS SPEC REQS ; |
warten bis Empfang beendet |
loop while the timer B interrupt is enebled |
|||
.,EFF9 2C 01 DD BIT $DD01 |
CKO030 BIT D2PRB |
Port B der NMI-CIA auslesen |
test VIA 2 DRB, RS232 port |
RS232 I/O port |
||
.,EFFC 70 FB BVS $EFF9 |
BVS CKO030 ; ; TURN ON RTS ; |
und auf Clear To Send warten |
loop while CTS high |
wait for no CTS |
||
.,EFFE AD 01 DD LDA $DD01 |
LDA D2PRB |
Port B lesen |
read VIA 2 DRB, RS232 port |
|||
.,F001 09 02 ORA #$02 |
ORA #$02 |
Bit für Request To Send setzen |
mask xxxx xx1x, set RTS high |
|||
.,F003 8D 01 DD STA $DD01 |
STA D2PRB ; ; WAIT FOR CTS TO GO ON ; |
und wieder zurückschreiben |
save VIA 2 DRB, RS232 port |
set RTS |
||
.,F006 2C 01 DD BIT $DD01 |
CKO040 BIT D2PRB |
Port B holen und |
test VIA 2 DRB, RS232 port |
|||
.,F009 70 07 BVS $F012 |
BVS CKO100 ;DONE... |
auf Clear To Send warten |
exit if CTS high |
CTS set |
||
.,F00B 30 F9 BMI $F006 |
BMI CKO040 ;WE STILL HAVE DSR ; |
verzweige wenn nicht Data Set Ready |
loop while DSR high set no DSR and exit |
wait for no DSRNO DSR ERRORThis routine sets the 6551 status register image to #40when a no DSR error has occurred. |
||
.,F00D A9 40 LDA #$40 |
CKDSRX LDA #$40 ;A DATA SET READY ERROR |
Bit für fehlendes DSR |
set DSR signal not present |
|||
.,F00F 8D 97 02 STA $0297 |
STA RSSTAT ;MAJOR ERROR....WILL REQUIRE REOPEN ; |
Status setzen |
save the RS232 status register |
RSSTAT, 6551 status register image |
||
.,F012 18 CLC |
CKO100 CLC ;NO ERROR |
Carry für ok Kennzeichen setzen |
flag ok |
|||
.,F013 60 RTS |
RTS ; ; BSO232 - OUTPUT A CHAR RS232 ; DATA PASSED IN T1 FROM BSOUT ; ; HANG LOOP FOR BUFFER FULL ; |
RücksprungAusgabe in RS 232 Puffer |
send byte to the RS232 buffer |
SEND TO RS232 BUFFERNote: The entry point to the routine is at |
buffer char to output on RS-232 |
|
.,F014 20 28 F0 JSR $F028 |
BSOBAD JSR BSO100 ;KEEP TRYING TO START SYSTEM... ; ; BUFFER HANDLER ; |
falls erforderlich Übertragung starten |
setup for RS232 transmit send byte to the RS232 buffer, no setup |
|||
.,F017 AC 9E 02 LDY $029E |
BSO232 LDY RODBE |
Zeiger auf Ausgabepuffer laden |
get index to Tx buffer end |
|||
.,F01A C8 INY |
INY |
und erhöhen |
+ 1 |
|||
.,F01B CC 9D 02 CPY $029D |
CPY RODBS ;CHECK FOR BUFFER FULL |
und mit Lesezeiger vergleichen |
compare with index to Tx buffer start |
|||
.,F01E F0 F4 BEQ $F014 |
BEQ BSOBAD ;HANG IF SO...TRYING TO RESTART |
Puffer voll, dann warten |
loop while buffer full |
|||
.,F020 8C 9E 02 STY $029E |
STY RODBE ;INDICATE NEW START |
neuen Wert für Schreibzeiger merken |
set index to Tx buffer end |
|||
.,F023 88 DEY |
DEY |
und wieder normalisieren |
index to available buffer byte |
|||
.,F024 A5 9E LDA $9E |
LDA T1 ;GET DATA... |
auszugebendes Byte holen und |
read the RS232 character buffer |
|||
.,F026 91 F9 STA ($F9),Y |
STA (ROBUF)Y ;STORE DATA ; ; SET UP IF NECESSARY TO OUTPUT ; |
in Puffer schreiben |
save the byte to the buffersetup for RS232 transmit |
|||
.,F028 AD A1 02 LDA $02A1 |
BSO100 LDA ENABL ;CHECK FOR A T1 NMI ENABLE |
RS 232 NMI Status laden |
get the RS-232 interrupt enable byte |
|||
.,F02B 4A LSR |
LSR A ;BIT 0 |
Bit 0 testen (läuft Sendebetrieb) |
shift the enable bit to Cb |
|||
.,F02C B0 1E BCS $F04C |
BCS BSO120 ;RUNNING....SO EXIT ; ; SET UP T1 NMI'S ; |
verzweige wenn ja |
if interrupts are enabled just exit |
|||
.,F02E A9 10 LDA #$10 |
BSO110 LDA #$10 ;TURN OFF TIMER TO PREVENT FALSE START... |
Bitwert für Timer starten |
start timer A |
|||
.,F030 8D 0E DD STA $DD0E |
STA D2CRA |
Timer A starten |
save VIA 2 CRA |
|||
.,F033 AD 99 02 LDA $0299 |
LDA BAUDOF ;SET UP TIMER1 |
Timer für |
get the baud rate bit time low byte |
|||
.,F036 8D 04 DD STA $DD04 |
STA D2T1L |
Sende-Baud-Rate |
save VIA 2 timer A low byte |
|||
.,F039 AD 9A 02 LDA $029A |
LDA BAUDOF+1 |
neu |
get the baud rate bit time high byte |
|||
.,F03C 8D 05 DD STA $DD05 |
STA D2T1H |
setzen |
save VIA 2 timer A high byte |
|||
.,F03F A9 81 LDA #$81 |
LDA #$81 |
Code für Timer-Unterlauf NMI Timer A |
enable timer A interrupt |
|||
.,F041 20 3B EF JSR $EF3B |
JSR OENABL |
in IC-Register schreiben |
set VIA 2 ICR from A |
|||
.,F044 20 06 EF JSR $EF06 |
JSR RSTBGN ;SET UP TO SEND (WILL STOP ON CTS OR DSR ERROR) |
CTS und DSR prüfen und Übertragung freigeben |
setup next RS232 Tx byte |
|||
.,F047 A9 11 LDA #$11 |
LDA #$11 ;TURN ON TIMER |
Bitwert Timer A starten |
load timer A, start timer A |
|||
.,F049 8D 0E DD STA $DD0E |
STA D2CRA |
Timer A starten |
save VIA 2 CRA |
|||
.,F04C 60 RTS |
BSO120 RTS ; INPUT A FILE OVER USER PORT ; USING RS232 ; |
RücksprungRS-232 CHKIN, Eingabe aufRS-232 setzen |
input from RS232 buffer |
INPUT FROM RS232 |
initalise RS-232 input |
|
.,F04D 85 99 STA $99 |
CKI232 STA DFLTN ;SET DEFAULT INPUT ; |
Gerätenummer speichern |
save the input device number |
|||
.,F04F AD 94 02 LDA $0294 |
LDA M51CDR ;CHECK FOR 3/X LINE |
RS 232 Befehlsregister laden |
get pseudo 6551 command register |
|||
.,F052 4A LSR |
LSR A |
Bit 0 ins Carry schieben |
shift the handshake bit to Cb |
|||
.,F053 90 28 BCC $F07D |
BCC CKI100 ;3 LINE...NO HANDSHAKE ; |
verzweige wenn 3-Line- Handshake |
if 3 line interface go ?? |
|||
.,F055 29 08 AND #$08 |
AND #$08 ;FULL/HALF CHECK (BYTE SHIFTED ABOVE) |
Bit für Dupex Mode isolieren |
mask the duplex bit, pseudo 6551 command is >> 1 |
|||
.,F057 F0 24 BEQ $F07D |
BEQ CKI100 ;FULL...NO HANDSHAKE ; ;*TURN AROUND LOGIC ; ; CHECK IF DSR AND NOT RTS ; |
verzweige wenn voll Dupex |
if full duplex go ?? |
|||
.,F059 A9 02 LDA #$02 |
LDA #$02 ;BIT RTS IS ON |
Maske für 'RTS OUT' |
mask 0000 00x0, RTS out |
|||
.,F05B 2C 01 DD BIT $DD01 |
BIT D2PRB |
Data Set Ready abfragen |
test VIA 2 DRB, RS232 port |
|||
.,F05E 10 AD BPL $F00D |
BPL CKDSRX ;NO DSR...ERROR |
verzweige wenn nein |
if DSR = 0 set no DSR and exit |
|||
.,F060 F0 22 BEQ $F084 |
BEQ CKI110 ;RTS LOW...IN CORRECT MODE ; ; WAIT FOR ACTIVE OUTPUT TO BE DONE ; |
Ready To Send abfragen |
if RTS = 0 just exit |
|||
.,F062 AD A1 02 LDA $02A1 |
CKI010 LDA ENABL |
RS 232 NMI Status laden |
get the RS-232 interrupt enable byte |
|||
.,F065 4A LSR |
LSR A ;CHECK T1 (BIT 0) |
Bit 0 ins Carry (Sendebetrieb aktiv) |
shift the timer A interrupt enable bit to Cb |
|||
.,F066 B0 FA BCS $F062 |
BCS CKI010 ; ; TURN OFF RTS ; |
ja, warten bis beendet |
loop while the timer A interrupt is enabled |
|||
.,F068 AD 01 DD LDA $DD01 |
LDA D2PRB |
Port B laden |
read VIA 2 DRB, RS232 port |
|||
.,F06B 29 FD AND #$FD |
AND #$FF-02 |
Request To Send |
mask xxxx xx0x, clear RTS out |
|||
.,F06D 8D 01 DD STA $DD01 |
STA D2PRB ; ; WAIT FOR DCD TO GO HIGH (IN SPEC) ; |
und wieder speichern |
save VIA 2 DRB, RS232 port |
|||
.,F070 AD 01 DD LDA $DD01 |
CKI020 LDA D2PRB |
Port B holen |
read VIA 2 DRB, RS232 port |
|||
.,F073 29 04 AND #$04 |
AND #$04 |
Bit für Data Terminal Ready |
mask xxxx x1xx, DTR in |
|||
.,F075 F0 F9 BEQ $F070 |
BEQ CKI020 ; ; ENABLE FLAG FOR RS232 INPUT ; |
verzweige wenn nein, warten |
loop while DTR low |
|||
.,F077 A9 90 LDA #$90 |
CKI080 LDA #$90 |
NMI-Maske für 'Flag' laden |
enable the FLAG interrupt |
|||
.,F079 18 CLC |
CLC ;NO ERROR |
Carry löschen (ok Kennzeichen) |
flag ok |
|||
.,F07A 4C 3B EF JMP $EF3B |
JMP OENABL ;FLAG IN ENABL********** ; ; IF NOT 3 LINE HALF THEN... ; SEE IF WE NEED TO TURN ON FLAG ; |
NMI freigebenRS-232 CHKIN bei 3-LineHandshake |
set VIA 2 ICR from A and return |
|||
.,F07D AD A1 02 LDA $02A1 |
CKI100 LDA ENABL ;CHECK FOR FLAG OR T2 ACTIVE |
RS-232 NMI Status laden |
get the RS-232 interrupt enable byte |
|||
.,F080 29 12 AND #$12 |
AND #$12 |
wenn RS-232 nicht aktiv |
mask 000x 00x0 |
|||
.,F082 F0 F3 BEQ $F077 |
BEQ CKI080 ;NO NEED TO TURN ON |
dann starten |
if FLAG or timer B bits set go enable the FLAG inetrrupt |
|||
.,F084 18 CLC |
CKI110 CLC ;NO ERROR |
Carry löschen (ok Kenneichen) |
flag ok |
|||
.,F085 60 RTS |
RTS ; BSI232 - INPUT A CHAR RS232 ; ; BUFFER HANDLER ; |
RücksprungGET von RS-232 |
get byte from RS232 buffer |
F086 GET FROM RS232 |
get next character from RS-232 input buffer |
|
.,F086 AD 97 02 LDA $0297 |
BSI232 LDA RSSTAT ;GET STATUS UP TO CHANGE... |
RS-232 Status holen |
get the RS232 status register |
|||
.,F089 AC 9C 02 LDY $029C |
LDY RIDBS ;GET LAST BYTE ADDRESS |
Zeiger auf Ende des Eingabepuffers |
get index to Rx buffer start |
|||
.,F08C CC 9B 02 CPY $029B |
CPY RIDBE ;SEE IF BUFFER EMPTY |
mit Zeiger auf Anfang vergleichen |
compare with index to Rx buffer end |
|||
.,F08F F0 0B BEQ $F09C |
BEQ BSI010 ;RETURN A NULL IF NO CHAR ; |
verzweige wenn gleich (Puffer leer) |
return null if buffer empty |
|||
.,F091 29 F7 AND #$F7 |
AND #$FF-$08 ;CLEAR BUFFER EMPTY STATUS |
Bit 3 (Puffer leer) |
clear the Rx buffer empty bit |
|||
.,F093 8D 97 02 STA $0297 |
STA RSSTAT |
im Status löschen (Zeichen im Puffer) |
save the RS232 status register |
|||
.,F096 B1 F7 LDA ($F7),Y |
LDA (RIBUF)Y ;GET LAST CHAR |
Byte aus Puffer holen |
get byte from Rx buffer |
|||
.,F098 EE 9C 02 INC $029C |
INC RIDBS ;INC TO NEXT POS ; ; RECEIVER ALWAYS RUNS ; |
Pufferzeiger erhöhen |
increment index to Rx buffer start |
|||
.,F09B 60 RTS |
RTS ; |
Rücksprung |
||||
.,F09C 09 08 ORA #$08 |
BSI010 ORA #$08 ;SET BUFFER EMPTY STATUS |
Bitwert für Puffer leer |
set the Rx buffer empty bit |
|||
.,F09E 8D 97 02 STA $0297 |
STA RSSTAT |
Status setzen |
save the RS232 status register |
|||
.,F0A1 A9 00 LDA #$00 |
LDA #$0 ;RETURN A NULL |
Null übergeben |
return null |
|||
.,F0A3 60 RTS |
RTS ; RSP232 - PROTECT SERIAL/CASS FROM RS232 NMI'S ; |
RücksprungEnde der RS-232 Übertragungabwarten |
check RS232 bus idle |
SERIAL BUS IDLEThis routine checks the RS232 bus for data transmission/reception. The routine waits for any activity on the bus to end before setting I.C.R. The routine is called by serial bus routines, since these devices use IRQ generated timing, and conflicts may occur if they are all used at once. |
protect serial/casette routine from RS-232 NMI's |
|
.,F0A4 48 PHA |
RSP232 PHA ;SAVE .A |
Akku auf Stack retten |
save A |
store (A) |
||
.,F0A5 AD A1 02 LDA $02A1 |
LDA ENABL ;DOES RS232 HAVE ANY ENABLES? |
RS-232 NMI Status laden |
get the RS-232 interrupt enable byte |
ENABL, RS232 enables |
||
.,F0A8 F0 11 BEQ $F0BB |
BEQ RSPOK ;NO... |
nicht gesetzt, dann ok |
if no interrupts enabled just exit |
bus not in use |
||
.,F0AA AD A1 02 LDA $02A1 |
RSPOFF LDA ENABL ;WAIT UNTILL DONE |
RS-232 NMI Status laden |
get the RS-232 interrupt enable byte |
ENABL |
||
.,F0AD 29 03 AND #$03 |
AND #%00000011 ; WITH T1 & T2 |
Bit 0 = senden und Bit 1 = empfangen |
mask 0000 00xx, the error bits |
test RS232 |
||
.,F0AF D0 F9 BNE $F0AA |
BNE RSPOFF |
warten bis beide Bits gelöscht |
if there are errors loop |
yes, wait for port to clear |
||
.,F0B1 A9 10 LDA #$10 |
LDA #%00010000 ; DISABLE FLAG (NEED TO RENABLE IN USER CODE) |
Bitwert für Interrupt durch |
disable FLAG interrupt |
|||
.,F0B3 8D 0D DD STA $DD0D |
STA D2ICR ;TURN OF ENABL************ |
'Flag'-Leitung setzen |
save VIA 2 ICR |
set up CIA#2 I.C.R |
||
.,F0B6 A9 00 LDA #$00 |
LDA #0 |
RS-232 NMI Status |
clear A |
clear |
||
.,F0B8 8D A1 02 STA $02A1 |
STA ENABL ;CLEAR ALL ENABLS |
zurücksetzen |
clear the RS-232 interrupt enable byte |
ENABL |
||
.,F0BB 68 PLA |
RSPOK PLA ;ALL DONE |
Akku wieder holen |
restore A |
retrieve (A) |
||
.,F0BC 60 RTS |
RTS .END .LIB MESSAGESMS1 .BYT $D,'I/O ERROR ',$A3MS5 .BYT $D,'SEARCHING',$A0 MS6 .BYT 'FOR',$A0 MS7 .BYT $D,'PRESS PLAY ON TAP',$C5 MS8 .BYT 'PRESS RECORD & PLAY ON TAP',$C5 MS10 .BYT $D,'LOADIN',$C7 MS11 .BYT $D,'SAVING',$A0 MS21 .BYT $D,'VERIFYIN',$C7 MS17 .BYT $D,'FOUND',$A0 MS18 .BYT $D,'OK',$8D ; MS34 .BYT $D,'MONITOR',$8D |
RücksprungSystemmeldungen |
kernel I/O messages |
TABLE OF KERNAL I/O MESSAGES 1This is a table of messages used by the KERNAL inconjunction with its I/O routines. Bit 7 is set in the last character in each message as a terminator. |
kernal I/O messages |
|
.:F0BD 0D 49 2F 4F 20 45 52 52 |
; MS36 .BYT $D,'BREA',$CB ;PRINT MESSAGE TO SCREEN ONLY IF ;OUTPUT ENABLED ; |
I/O ERROR # |
I/O ERROR # |
I/O error |
I/O error |
|
.:F0C6 52 20 A3 0D 53 45 41 52 | ||||||
.:F0C9 0D 53 45 41 52 43 48 49 |
SEARCHING |
SEARCHING |
searching for |
searching for |
||
.:F0D1 4E 47 A0 46 4F 52 A0 0D | ||||||
.:F0D4 46 4F 52 A0 0D 50 52 45 |
FOR |
FOR |
||||
.:F0D8 0D 50 52 45 53 53 20 50 |
PRESS PLAY ON TAPE |
PRESS PLAY ON TAPE |
press play on tape |
press play on tape |
||
.:F0E0 4C 41 59 20 4F 4E 20 54 | ||||||
.:F0E8 41 50 C5 50 52 45 53 53 | ||||||
.:F0EB 50 52 45 53 53 20 52 45 |
PRESS RECORD & PLAY ON TAPE |
PRESS RECORD & PLAY ON TAPE |
press record and play on tape |
press record and play on tape |
||
.:F0F3 43 4F 52 44 20 26 20 50 | ||||||
.:F0FB 4C 41 59 20 4F 4E 20 54 | ||||||
.:F103 41 50 C5 0D 4C 4F 41 44 | ||||||
.:F106 0D 4C 4F 41 44 49 4E C7 |
LOADING |
LOADING |
loading |
loading |
||
.:F10E 0D 53 41 56 49 4E 47 A0 |
SAVING |
SAVING |
saving |
saving |
||
.:F116 0D 56 45 52 49 46 59 49 |
VERIFYING |
VERIFYING |
verifying |
verifying |
||
.:F11E 4E C7 0D 46 4F 55 4E 44 | ||||||
.:F120 0D 46 4F 55 4E 44 A0 0D |
FOUND |
FOUND |
found |
found |
||
.:F127 0D 4F 4B 8D |
OKSystemmeldungen ausgeben |
OKdisplay control I/O message if in direct mode |
okPRINT MESSAGE IF DIRECTThis is a routine to output a message from the I/Omessages table at $f0bd. On entry, (Y) holds the offset to control which message is printed. The routine tests if we are in program mode or direct mode. If in program mode, the routine exits. Else, the routine prints character after caracter untill it reaches a character with bit7 set. |
okprint kernal message indexed by Y |
||
.,F12B 24 9D BIT $9D |
SPMSG BIT MSGFLG ;PRINTING MESSAGES? |
Direkt-Modus Flag |
test message mode flag |
MSGFLG, test if direct or program mode |
||
.,F12D 10 0D BPL $F13C |
BPL MSG10 ;NO... |
Programm, dann überspringen |
exit if control messages off display kernel I/O message |
program mode, don't print message |
||
.,F12F B9 BD F0 LDA $F0BD,Y |
MSG LDA MS1,Y |
Zeichen holen mit Offset der Meldung in Y-Register |
get byte from message table |
get output character from table |
||
.,F132 08 PHP |
PHP |
Status-Register retten |
save status |
store processor registers |
||
.,F133 29 7F AND #$7F |
AND #$7F |
Bit 7 löschen |
clear b7 |
clear bit7 |
||
.,F135 20 D2 FF JSR $FFD2 |
JSR BSOUT |
und Zeichen ausgeben |
output character to channel |
output character using CHROUT |
||
.,F138 C8 INY |
INY |
Zeiger erhöhen |
increment index |
increment pointer to next character |
||
.,F139 28 PLP |
PLP |
Status wiederholen |
restore status |
retrieve message |
||
.,F13A 10 F3 BPL $F12F |
BPL MSG |
verzweige wenn noch weitere Buchstaben |
loop if not end of message |
untill bit7 was set |
||
.,F13C 18 CLC |
MSG10 CLC |
Carry löschen, ok |
clear carry to indicate no error |
|||
.,F13D 60 RTS |
RTS .END .LIB CHANNELIO;***************************************;* GETIN -- GET CHARACTER FROM CHANNEL * ;* CHANNEL IS DETERMINED BY DFLTN.* ;* IF DEVICE IS 0, KEYBOARD QUEUE IS * ;* EXAMINED AND A CHARACTER REMOVED IF * ;* AVAILABLE. IF QUEUE IS EMPTY, Z * ;* FLAG IS RETURNED SET. DEVICES 1-31 * ;* ADVANCE TO BASIN. * ;*************************************** ; |
RücksprungGETIN |
get character from the input device |
GETIN: GET a BYTEThe KERNAL routine GETIN ($ffe4) is vectored to thisroutine. It load a character into fac#1 from the external device indicated by DFLTN. Thus, if device = 0, GET is from the keyboard buffer. If device = 2, GET is from the RS232 port. If neither of these devices then GET is further handled by the next routine, INPUT. |
get a character |
|
.,F13E A5 99 LDA $99 |
NGETIN LDA DFLTN ;CHECK DEVICE |
Eingabegerät laden |
get the input device number |
DFLTN, default input device. |
||
.,F140 D0 08 BNE $F14A |
BNE GN10 ;NOT KEYBOARD ; |
verzweige wenn nicht Tastatur |
if not the keyboard go handle other devices the input device was the keyboard |
not keyboard |
||
.,F142 A5 C6 LDA $C6 |
LDA NDX ;QUEUE INDEX |
Anzahl der Zeichen im Tastaturpuffer laden |
get the keyboard buffer index |
NDX, number of keys in keyboard queue |
||
.,F144 F0 0F BEQ $F155 |
BEQ GN20 ;NOBODY THERE...EXIT ; |
verzweige wenn kein Zeichen |
if the buffer is empty go flag no byte and return |
buffer empty, exit |
||
.,F146 78 SEI |
SEI |
Interruptflag setzen |
disable the interrupts |
disable interrupts |
||
.,F147 4C B4 E5 JMP $E5B4 |
JMP LP2 ;GO REMOVE A CHARACTER ; |
Zeichen aus Tastaturpuffer holen |
get input from the keyboard buffer and return the input device was not the keyboard |
get character from keyboard buffer, and exit |
||
.,F14A C9 02 CMP #$02 |
GN10 CMP #2 ;IS IT RS-232 |
Geräteadresse für RS-232 |
compare the device with the RS232 device |
RS232 |
||
.,F14C D0 18 BNE $F166 |
BNE BN10 ;NO...USE BASIN ; |
nein dann zur BASIN-Routine |
if not the RS232 device go ?? the input device is the RS232 device |
nope, try next device |
||
.,F14E 84 97 STY $97 |
GN232 STY XSAV ;SAVE .Y, USED IN RS232 |
Y-Register merken |
save Y |
temp store |
||
.,F150 20 86 F0 JSR $F086 |
JSR BSI232 |
Get von RS 232 |
get a byte from RS232 buffer |
get character from RS232 |
||
.,F153 A4 97 LDY $97 |
LDY XSAV ;RESTORE .Y |
Y-Register wiederholen |
restore Y |
retrieve (Y) |
||
.,F155 18 CLC |
GN20 CLC ;GOOD RETURN |
Carry löschen, ok |
flag no error |
|||
.,F156 60 RTS |
RTS ;*************************************** ;* BASIN-- INPUT CHARACTER FROM CHANNEL* ;* INPUT DIFFERS FROM GET ON DEVICE* ;* #0 FUNCTION WHICH IS KEYBOARD. THE * ;* SCREEN EDITOR MAKES READY AN ENTIRE * ;* LINE WHICH IS PASSED CHAR BY CHAR * ;* UP TO THE CARRIAGE RETURN. OTHER * ;* DEVICES ARE: * ;* 0 -- KEYBOARD * ;* 1 -- CASSETTE #1 * ;* 2 -- RS232 * ;* 3 -- SCREEN * ;* 4-31 -- SERIAL BUS * ;*************************************** ; |
RücksprungBASIN Eingabe einesZeichens |
input a character from channel |
CHRIN: INPUT A BYTEThe KERNAL routine CHRIN ($ffcf) is vectored to thisroutine. It is similar in function to the GET routine above, and also provides a continuation to that routine. If the input device is 0 or 3, ie. keyboard or screen, then input takes place from the screen. INPUT/GET from other devices are performed by calls to the next routine. Two bytes are input from the device so that end of file can be set if necessary (ie. ST = #40) |
input a character |
|
.,F157 A5 99 LDA $99 |
NBASIN LDA DFLTN ;CHECK DEVICE |
Gerätenummer laden |
get the input device number |
DFLTN, default input |
||
.,F159 D0 0B BNE $F166 |
BNE BN10 ;IS NOT KEYBOARD... ; ;INPUT FROM KEYBOARD ; |
verzweige wenn nicht Tastatur |
if not the keyboard continue the input device was the keyboard |
not keyboard, next device |
||
.,F15B A5 D3 LDA $D3 |
LDA PNTR ;SAVE CURRENT... |
Cursorposition holen |
get the cursor column |
PNTR, cursor column on screen |
||
.,F15D 85 CA STA $CA |
STA LSTP ;... CURSOR COLUMN |
und für |
set the input cursor column |
>LXSP, cursor position at start |
||
.,F15F A5 D6 LDA $D6 |
LDA TBLX ;SAVE CURRENT... |
Tastatureingabe |
get the cursor row |
TBLX, cursor line number |
||
.,F161 85 C9 STA $C9 |
STA LSXP ;... LINE NUMBER |
setzen |
set the input cursor row |
<LXSP |
||
.,F163 4C 32 E6 JMP $E632 |
JMP LOOP5 ;BLINK CURSOR UNTIL RETURN ; |
Eingabe vom Bildschirm |
input from screen or keyboard the input device was not the keyboard |
input from screen or keyboard |
||
.,F166 C9 03 CMP #$03 |
BN10 CMP #3 ;IS INPUT FROM SCREEN? |
Eingabekanal 3 = Bildschirm |
compare device number with screen |
screen |
||
.,F168 D0 09 BNE $F173 |
BNE BN20 ;NO... ; |
wenn nicht verzweigevom Bildschirm |
if not screen continue the input device was the screen |
nope, next device |
||
.,F16A 85 D0 STA $D0 |
STA CRSW ;FAKE A CARRIAGE RETURN |
Flag auf Eingabe von Bild- schimrstelle |
input from keyboard or screen, $xx = screen, $00 = keyboard |
CRSW, flag INPUT/GET from keyboard |
||
.,F16C A5 D5 LDA $D5 |
LDA LNMX ;SAY WE ENDED... |
Cursorzeile laden |
get current screen line length |
LNMX, physical screen line length |
||
.,F16E 85 C8 STA $C8 |
STA INDX ;...UP ON THIS LINE |
als Pointer für Ende der Zeile speichern |
save input [EOL] pointer |
INDX, end of logical line for input |
||
.,F170 4C 32 E6 JMP $E632 |
JMP LOOP5 ;PICK UP CHARACTERS ; |
zu Eingabe vom Bildschirm |
input from screen or keyboard the input device was not the screen |
input from screen of keyboard |
||
.,F173 B0 38 BCS $F1AD |
BN20 BCS BN30 ;DEVICES >3 |
verzweige zu Eingabe vom IEC-Bus |
if input device > screen go do IEC devices the input device was < screen |
|||
.,F175 C9 02 CMP #$02 |
CMP #2 ;RS232? |
Eingabe von RS-232 ? |
compare the device with the RS232 device |
RS232 |
||
.,F177 F0 3F BEQ $F1B8 |
BEQ BN50 ; ;INPUT FROM CASSETTE BUFFERS ; |
ja, so verzweigeEingabe vom Band |
if RS232 device go get a byte from the RS232 device only the tape device left .. |
yes, get data from RS232 port |
||
.,F179 86 97 STX $97 |
STX XSAV |
X-Register merken |
save X |
|||
.,F17B 20 99 F1 JSR $F199 |
JSR JTGET |
ein Zeichen vom Band holen |
get a byte from tape |
|||
.,F17E B0 16 BCS $F196 |
BCS JTG37 ;STOP KEY/ERROR |
verzweige bei Fehler |
if error just exit |
|||
.,F180 48 PHA |
PHA |
Akku retten |
save the byte |
|||
.,F181 20 99 F1 JSR $F199 |
JSR JTGET |
ein Zeichen vom Band holen |
get the next byte from tape |
|||
.,F184 B0 0D BCS $F193 |
BCS JTG36 ;STOP KEY/ERROR |
verzweige bei Fehler |
if error just exit |
|||
.,F186 D0 05 BNE $F18D |
BNE JTG35 ;NOT AN END OF FILE |
letzes Zeichen ? |
if end reached ?? |
|||
.,F188 A9 40 LDA #$40 |
LDA #64 ;TELL USER EOF |
Code für 'End of Identify' |
set EOI |
|||
.,F18A 20 1C FE JSR $FE1C |
JSR UDST ;IN STATUS |
Status setzen |
OR into the serial status byte |
|||
.,F18D C6 A6 DEC $A6 |
JTG35 DEC BUFPT |
Bandpuffer Zeiger erniedrigen |
decrement tape buffer index |
|||
.,F18F A6 97 LDX $97 |
LDX XSAV ;.X PRESERVED |
X-Register zurückholen |
restore X |
|||
.,F191 68 PLA |
PLA ;CHARACTER RETURNED ;C-CLEAR FROM JTGET |
geholtes Zeichen in Akku |
restore the saved byte |
|||
.,F192 60 RTS |
RTS ;ALL DONE ; |
Rücksprung |
||||
.,F193 AA TAX |
JTG36 TAX ;SAVE ERROR INFO |
Fehlernummer ins X-Register |
copy the error byte |
|||
.,F194 68 PLA |
PLA ;TOSS DATA |
Stack normalisieren |
dump the saved byte |
|||
.,F195 8A TXA |
TXA ;RESTORE ERROR |
Fehlernummer in Akku |
restore error byte |
|||
.,F196 A6 97 LDX $97 |
JTG37 LDX XSAV ;RETURN |
X-Register zurückholen |
restore X |
|||
.,F198 60 RTS |
RTS ;ERROR RETURN C-SET FROM JTGET ;GET A CHARACTER FROM APPROPRIATE ;CASSETTE BUFFER ; |
Rücksprungein Zeichen vom Band holen |
get byte from tape |
read a byte from cassette buffer |
||
.,F199 20 0D F8 JSR $F80D |
JTGET JSR JTP20 ;BUFFER POINTER WRAP? |
Bandpuffer Zeiger erhöhen |
bump tape pointer |
|||
.,F19C D0 0B BNE $F1A9 |
BNE JTG10 ;NO... |
verzweige wenn noch Zeichen im Puffer |
if not end get next byte and exit |
|||
.,F19E 20 41 F8 JSR $F841 |
JSR RBLK ;YES...READ NEXT BLOCK |
sonst nächsten Block vom Band holen |
initiate tape read |
|||
.,F1A1 B0 11 BCS $F1B4 |
BCS BN33 ;STOP KEY PRESSED |
STOP-Taste, dann Abbruch |
exit if error flagged |
|||
.,F1A3 A9 00 LDA #$00 |
LDA #0 |
Pufferzeiger |
clear A |
|||
.,F1A5 85 A6 STA $A6 |
STA BUFPT ;POINT TO BEGIN. |
auf Null |
clear tape buffer index |
|||
.,F1A7 F0 F0 BEQ $F199 |
BEQ JTGET ;BRANCH ALWAYS ; |
unbedingter Sprung |
loop, branch always |
|||
.,F1A9 B1 B2 LDA ($B2),Y |
JTG10 LDA (TAPE1)Y ;GET CHAR FROM BUF |
Zeichen aus Puffer lesen |
get next byte from buffer |
|||
.,F1AB 18 CLC |
CLC ;GOOD RETURN |
Carry =0 (ok Kennzeichen) |
flag no error |
|||
.,F1AC 60 RTS |
RTS ;INPUT FROM SERIAL BUS ; |
RücksprungEingabe vom IEC-Bus |
input device was serial bus |
GET FROM SERIAL/RS232These routines, actually two different, is entered fromthe previous routine. The serial sectionchecks the state of ST. If zero, then the data is recieved from the bus, otherwise carriage return (#0d) is returned in (A). In the second section, the recieved byte is read from the RS232 port. |
||
.,F1AD A5 90 LDA $90 |
BN30 LDA STATUS ;STATUS FROM LAST |
Status testen |
get the serial status byte |
STATUS, I/O status word |
||
.,F1AF F0 04 BEQ $F1B5 |
BEQ BN35 ;WAS GOOD |
verzweige wenn ok |
if no errors flagged go input byte and return |
status OK |
||
.,F1B1 A9 0D LDA #$0D |
BN31 LDA #$D ;BAD...ALL DONE |
'CR' Kode ausgeben |
else return [EOL] |
else return <CR> and exit |
||
.,F1B3 18 CLC |
BN32 CLC ;VALID DATA |
Carry =0 (ok Kennzeichen) |
flag no error |
|||
.,F1B4 60 RTS |
BN33 RTS ; |
Rücksprung |
read a byte from serial bus |
|||
.,F1B5 4C 13 EE JMP $EE13 |
BN35 JMP ACPTR ;GOOD...HANDSHAKE ; ;INPUT FROM RS232 ; |
ein Byte vom IEC-Bus holenRS 232 Eingabe |
input byte from serial bus and return input device was RS232 device |
ACPTR, get byte from serial bus |
read a byte from RS-232 bus |
|
.,F1B8 20 4E F1 JSR $F14E |
BN50 JSR GN232 ;GET INFO |
ein Byte von RS 232 holen |
get byte from RS232 device |
receive from RS232 |
||
.,F1BB B0 F7 BCS $F1B4 |
BCS BN33 ;ERROR RETURN |
verzweige wenn Fehler |
branch if error, this doesn't get taken as the last instruction in the get byte from RS232 device routine is CLC ?? |
end with carry set |
||
.,F1BD C9 00 CMP #$00 |
CMP #00 |
vergleiche mit Nullbyte |
compare with null |
|||
.,F1BF D0 F2 BNE $F1B3 |
BNE BN32 ;GOOD DATA...EXIT |
nein, dann ok |
exit if not null |
end with carry clear |
||
.,F1C1 AD 97 02 LDA $0297 |
LDA RSSTAT ;CHECK FOR DSR OR DCD ERROR |
Status laden |
get the RS232 status register |
RSSTAT, 6551 status register |
||
.,F1C4 29 60 AND #$60 |
AND #$60 |
fehlt DSR ? |
mask 0xx0 0000, DSR detected and ?? |
mask |
||
.,F1C6 D0 E9 BNE $F1B1 |
BNE BN31 ;AN ERROR...EXIT WITH C/R |
ja, 'CR' zurückgeben |
if ?? return null |
return with <CR> |
||
.,F1C8 F0 EE BEQ $F1B8 |
BEQ BN50 ;NO ERROR...STAY IN LOOP ;*************************************** ;* BSOUT -- OUT CHARACTER TO CHANNEL * ;* DETERMINED BY VARIABLE DFLTO: * ;* 0 -- INVALID * ;* 1 -- CASSETTE #1 * ;* 2 -- RS232 * ;* 3 -- SCREEN * ;* 4-31 -- SERIAL BUS * ;*************************************** ; |
nein, neuer VersuchBSOUT Ausgabe einesZeichens |
else loop, branch alwaysoutput character to channel |
get from RS232CHROUT: OUTPUT ONE CHARACTERThe KERNAL routine CHROUT ($ffd2) is vectored to thisroutine. On entry, (A) must hold the character to be output. The default output device number is examined, and output directed to relevant device. The screen, serial bus and RS232 all use previously described routines for their output. |
output a character |
|
.,F1CA 48 PHA |
NBSOUT PHA ;PRESERVE .A |
Datenbyte retten |
save the character to output |
temp store on stack |
||
.,F1CB A5 9A LDA $9A |
LDA DFLTO ;CHECK DEVICE |
Gerätenummer für Ausgabe |
get the output device number |
DFLTO, default output device |
||
.,F1CD C9 03 CMP #$03 |
CMP #3 ;IS IT THE SCREEN? |
vergleiche mit Bildschirm |
compare the output device with the screen |
screen? |
||
.,F1CF D0 04 BNE $F1D5 |
BNE BO10 ;NO... ; ;PRINT TO CRT ; |
verzweige wenn nein |
if not the screen go ?? |
nope, test next device |
||
.,F1D1 68 PLA |
PLA ;RESTORE DATA |
Datenbyte wiederholen |
else restore the output character |
retrieve (A) |
||
.,F1D2 4C 16 E7 JMP $E716 |
JMP PRT ;PRINT ON CRT ; BO10 |
ein Zeichen auf Bildschirm ausgeben |
go output the character to the screen |
output to screen |
||
.,F1D5 90 04 BCC $F1DB |
BCC BO20 ;DEVICE 1 OR 2 ; ;PRINT TO SERIAL BUS ; |
verzweige wenn keine Ausgabe IEC-Bus Ausgabe auf IEC-Bus |
if < screen go ?? |
device <3 |
||
.,F1D7 68 PLA |
PLA |
Datenbyte retten |
else restore the output character |
retrieve (A) |
||
.,F1D8 4C DD ED JMP $EDDD |
JMP CIOUT ; ;PRINT TO CASSETTE DEVICES ; |
ein Byte auf IEC-Bus ausgeben |
go output the character to the serial bus |
send serial deferred |
||
.,F1DB 4A LSR |
BO20 LSR A ;RS232? |
Bit 0 der Ausgabekanal- Nummer ins Carry |
shift b0 of the device into Cb |
|||
.,F1DC 68 PLA |
PLA ;GET DATA OFF STACK... ; |
Datenbyte wiederholen |
restore the output characteroutput the character to the cassette or RS232 device |
|||
.,F1DD 85 9E STA $9E |
CASOUT STA T1 ;PASS DATA IN T1 ; CASOUT MUST BE ENTERED WITH CARRY SET!!! ;PRESERVE REGISTERS ; |
auszugebendes Zeichen merken |
save the character to the character buffer |
PTR1 |
||
.,F1DF 8A TXA |
TXA |
X-Register |
copy X |
|||
.,F1E0 48 PHA |
PHA |
und Y-Register |
save X |
|||
.,F1E1 98 TYA |
TYA |
auf Stack |
copy Y |
|||
.,F1E2 48 PHA |
PHA |
retten |
save Y |
|||
.,F1E3 90 23 BCC $F208 |
BCC BO50 ;C-CLR MEANS DFLTO=2 (RS232) ; |
RS-232 AusgabeAusgabe auf Band |
if Cb is clear it must be the RS232 device output the character to the cassette |
RS232 |
||
.,F1E5 20 0D F8 JSR $F80D |
JSR JTP20 ;CHECK BUFFER POINTER |
Bandpuffer Zeiger erhöhen |
bump the tape pointer |
|||
.,F1E8 D0 0E BNE $F1F8 |
BNE JTP10 ;HAS NOT REACHED END |
verzweige wenn Puffer nicht voll |
if not end save next byte and exit |
|||
.,F1EA 20 64 F8 JSR $F864 |
JSR WBLK ;WRITE FULL BUFFER |
Puffer auf Band schreiben |
initiate tape write |
|||
.,F1ED B0 0E BCS $F1FD |
BCS RSTOR ;ABORT ON STOP KEY ; ;PUT BUFFER TYPE BYTE ; |
STOP-Taste, dann Abbruch |
exit if error |
|||
.,F1EF A9 02 LDA #$02 |
LDA #BDF |
Kontrollbyte für Datenblock |
set data block type ?? |
|||
.,F1F1 A0 00 LDY #$00 |
LDY #0 |
Pufferzeiger auf 0 |
clear index |
|||
.,F1F3 91 B2 STA ($B2),Y |
STA (TAPE1)Y ; ;RESET BUFFER POINTER ; |
Akku in Puffer schreiben |
save type to buffer ?? |
|||
.,F1F5 C8 INY |
INY ;MAKE .Y=1 |
Zeiger erhöhen |
increment index |
|||
.,F1F6 84 A6 STY $A6 |
STY BUFPT ;BUFPT=1 ; |
und merken |
save tape buffer index |
|||
.,F1F8 A5 9E LDA $9E |
JTP10 LDA T1 |
Datenbyte holen |
restore character from character buffer |
|||
.,F1FA 91 B2 STA ($B2),Y |
STA (TAPE1)Y ;DATA TO BUFFER ; ;RESTORE .X AND .Y ; |
Zeichen in Puffer schreiben |
save to buffer |
|||
.,F1FC 18 CLC |
RSTOA CLC ;GOOD RETURN |
Carry =0 (ok Kennzeichen) |
flag no error |
|||
.,F1FD 68 PLA |
RSTOR PLA |
X-Register |
pull Y |
|||
.,F1FE A8 TAY |
TAY |
und Y-Register |
restore Y |
|||
.,F1FF 68 PLA |
PLA |
aus Stack |
pull X |
|||
.,F200 AA TAX |
TAX |
holen |
restore X |
|||
.,F201 A5 9E LDA $9E |
LDA T1 ;GET .A FOR RETURN |
Datenbyte zurückholen |
get the character from the character buffer |
|||
.,F203 90 02 BCC $F207 |
BCC RSTOR1 ;NO ERROR |
verzweige wenn ok |
exit if no error |
|||
.,F205 A9 00 LDA #$00 |
LDA #00 ;STOP ERROR IF C-SET |
Flag für 'STOP-Taste gedrückt' |
else clear A |
|||
.,F207 60 RTS |
RSTOR1 RTS ; ;OUTPUT TO RS232 ; |
RücksprungRS-232 Ausgabe |
output the character to the RS232 device |
|||
.,F208 20 17 F0 JSR $F017 |
BO50 JSR BSO232 ;PASS DATA THROUGH VARIABLE T1 |
ein Zeichen in RS-232 Puffer schreiben |
send byte to the RS232 buffer, no setup |
send to RS232 |
||
.,F20B 4C FC F1 JMP $F1FC |
JMP RSTOA ;GO RESTORE ALL..ALWAYS GOOD .END .LIB OPENCHANNEL;***************************************;* CHKIN -- OPEN CHANNEL FOR INPUT * ;* * ;* THE NUMBER OF THE LOGICAL FILE TO BE* ;* OPENED FOR INPUT IS PASSED IN .X. * ;* CHKIN SEARCHES THE LOGICAL FILE * ;* TO LOOK UP DEVICE AND COMMAND INFO. * ;* ERRORS ARE REPORTED IF THE DEVICE * ;* WAS NOT OPENED FOR INPUT ,(E.G. * ;* CASSETTE WRITE FILE), OR THE LOGICAL* ;* FILE HAS NO REFERENCE IN THE TABLES.* ;* DEVICE 0, (KEYBOARD), AND DEVICE 3 * ;* (SCREEN), REQUIRE NO TABLE ENTRIES * ;* AND ARE HANDLED SEPARATE. * ;*************************************** ; |
CHROUTCHKIN Eingabegerät setzen |
do no error exitopen channel for input |
end outputCHKIN: SET INPUT DEVICEThe KERNAL routine CHKIN ($ffc6) is vectored to thisroutine. On entry, (X) must hold the logical file number. A test is made to see if the file is open, or ?FILE NOT OPEN. If the file is not an input file then ?NOT INPUT FILE. If the device is on the serial bus then it is commanded to TALK and secondary address is sent. ST is then checked, and if non-zero, ?DEVICE NOT PRESENT. Finally, the device number is stored in DLFTN. |
set input device |
|
.,F20E 20 0F F3 JSR $F30F |
NCHKIN JSR LOOKUP ;SEE IF FILE KNOWN |
sucht logische Filenummer |
find a file |
find file number |
||
.,F211 F0 03 BEQ $F216 |
BEQ JX310 ;YUP... ; |
verzweige wenn gefunden |
if the file is open continue |
ok, skip next command |
||
.,F213 4C 01 F7 JMP $F701 |
JMP ERROR3 ;NO...FILE NOT OPEN ; |
sonst 'file not open' |
else do 'file not open' error and return |
I/O error #3, file not open |
||
.,F216 20 1F F3 JSR $F31F |
JX310 JSR JZ100 ;EXTRACT FILE INFO ; |
setzt Fileparameter |
set file details from table,X |
set file variables |
||
.,F219 A5 BA LDA $BA |
LDA FA |
Gerätenummer laden |
get the device number |
FA, current device number |
||
.,F21B F0 16 BEQ $F233 |
BEQ JX320 ;IS KEYBOARD...DONE. ; ;COULD BE SCREEN, KEYBOARD, OR SERIAL ; |
0, Tastatur |
if the device was the keyboard save the device #, flag ok and exit |
keyboard |
||
.,F21D C9 03 CMP #$03 |
CMP #3 |
vergleiche mit Bildschirm |
compare the device number with the screen |
screen |
||
.,F21F F0 12 BEQ $F233 |
BEQ JX320 ;IS SCREEN...DONE. |
verzweige zu Bildschirm |
if the device was the screen save the device #, flag ok and exit |
yes |
||
.,F221 B0 14 BCS $F237 |
BCS JX330 ;IS SERIAL...ADDRESS IT |
verzweige zu IEC-Bus |
if the device was a serial bus device go ?? |
larger than 3, serial bus device |
||
.,F223 C9 02 CMP #$02 |
CMP #2 ;RS232? |
vergleiche mit RS-232 |
else compare the device with the RS232 device |
RS232 |
||
.,F225 D0 03 BNE $F22A |
BNE JX315 ;NO... ; |
nein, dann Band |
if not the RS232 device continue |
nope |
||
.,F227 4C 4D F0 JMP $F04D |
JMP CKI232 ; ;SOME EXTRA CHECKS FOR TAPE ; |
ja, dann RS-232Band als Eingabegerät setzen |
else go get input from the RS232 buffer and return |
input from RS232 |
||
.,F22A A6 B9 LDX $B9 |
JX315 LDX SA |
Sekundäradresse laden |
get the secondary address |
SA, current secondart address |
||
.,F22C E0 60 CPX #$60 |
CPX #$60 ;IS COMMAND A READ? |
vergleichemit 'Null' |
||||
.,F22E F0 03 BEQ $F233 |
BEQ JX320 ;YES...O.K....DONE ; |
verzweige wenn 'Null' |
||||
.,F230 4C 0A F7 JMP $F70A |
JMP ERROR6 ;NOT INPUT FILE ; |
sonst 'not input file' |
go do 'not input file' error and return |
I/O error #6, not output file |
||
.,F233 85 99 STA $99 |
JX320 STA DFLTN ;ALL INPUT COME FROM HERE ; |
Gerätenummer für Ausgabe speichern |
save the input device number |
DFLTN, default input device |
||
.,F235 18 CLC |
CLC ;GOOD EXIT |
Carry =0 (ok Kennzeichen) |
flag ok |
|||
.,F236 60 RTS |
RTS ; ;AN SERIAL DEVICE HAS TO BE A TALKER ; |
RücksprungIEC-Bus als Eingabegerät |
the device was a serial bus device |
set serial bus input device |
||
.,F237 AA TAX |
JX330 TAX ;DEVICE # FOR DFLTO |
Geräteadresse retten |
copy device number to X |
|||
.,F238 20 09 ED JSR $ED09 |
JSR TALK ;TELL HIM TO TALK ; |
TALK senden |
command serial bus device to TALK |
send TALK to serial device |
||
.,F23B A5 B9 LDA $B9 |
LDA SA ;A SECOND? |
Sekundäradresse laden |
get the secondary address |
SA |
||
.,F23D 10 06 BPL $F245 |
BPL JX340 ;YES...SEND IT |
verzweige wenn kleiner 128 |
send SA |
|||
.,F23F 20 CC ED JSR $EDCC |
JSR TKATN ;NO...LET GO |
wartet auf Takt-Signal |
wait for the serial bus end after send |
wait for clock |
||
.,F242 4C 48 F2 JMP $F248 |
JMP JX350 ; |
nächsten Befehl überspringen |
||||
.,F245 20 C7 ED JSR $EDC7 |
JX340 JSR TKSA ;SEND SECOND ; |
Sekundäradresse für TALK senden |
send secondary address after TALK |
send talk secondary address |
||
.,F248 8A TXA |
JX350 TXA |
Geräteadresse wiederholen |
copy device back to A |
|||
.,F249 24 90 BIT $90 |
BIT STATUS ;DID HE LISTEN? |
Status abfragen |
test the serial status byte |
STATUS, I/O status word |
||
.,F24B 10 E6 BPL $F233 |
BPL JX320 ;YES ; |
verzweige wenn ok |
if device present save device number and exit |
store DFLTN, and exit |
||
.,F24D 4C 07 F7 JMP $F707 |
JMP ERROR5 ;DEVICE NOT PRESENT ;*************************************** ;* CHKOUT -- OPEN CHANNEL FOR OUTPUT * ;* * ;* THE NUMBER OF THE LOGICAL FILE TO BE* ;* OPENED FOR OUTPUT IS PASSED IN .X. * ;* CHKOUT SEARCHES THE LOGICAL FILE * ;* TO LOOK UP DEVICE AND COMMAND INFO. * ;* ERRORS ARE REPORTED IF THE DEVICE * ;* WAS NOT OPENED FOR INPUT ,(E.G. * ;* KEYBOARD), OR THE LOGICAL FILE HAS * ;* REFERENCE IN THE TABLES. * ;* DEVICE 0, (KEYBOARD), AND DEVICE 3 * ;* (SCREEN), REQUIRE NO TABLE ENTRIES * ;* AND ARE HANDLED SEPARATE. * ;*************************************** ; |
sonst 'DEVICE NOT PRESENT'CKOUT Ausgabegerät setzen |
do 'device not present' error and returnopen channel for output |
I/O error #5, device not presentCHKOUT: SET OUTPUT DEVICEThe KERNAL routine CHKOUT ($ffc9) is vectored to thisroutinr. On entry (X) must hold the logical filenumber. A test is made to see if the file is open, or ?FILE NOT OPEN error. If the device is 0, ie. the keyboard, or the file is not an output file, then ?FILE OUTPUT FILE error is generated. If the device is on the serial bus, then it commanded to LISTEN and the secondary address is sent. ST is then checked and if non-zero, then ?DEVICE NOT PRESENT error. Finally, the device number is stored in DFLTO. |
set output device |
|
.,F250 20 0F F3 JSR $F30F |
NCKOUT JSR LOOKUP ;IS FILE IN TABLE? |
sucht logische Filenummer |
find a file |
fine file number (X) |
||
.,F253 F0 03 BEQ $F258 |
BEQ CK5 ;YES... ; |
verzweige wenn gefunden |
if file found continue |
OK |
||
.,F255 4C 01 F7 JMP $F701 |
JMP ERROR3 ;NO...FILE NOT OPEN ; |
sonst 'FILE NOT OPEN' |
else do 'file not open' error and return |
I/O error #3, file not open |
||
.,F258 20 1F F3 JSR $F31F |
CK5 JSR JZ100 ;EXTRACT TABLE INFO ; |
setzt Fileparameter |
set file details from table,X |
set file values |
||
.,F25B A5 BA LDA $BA |
LDA FA ;IS IT KEYBOARD? |
Gerätenummer holen |
get the device number |
FA, current device number |
||
.,F25D D0 03 BNE $F262 |
BNE CK10 ;NO...SOMETHING ELSE. ; |
verzweige wenn ungleich Null |
if the device is not the keyboard go ?? |
not keyboard |
||
.,F25F 4C 0D F7 JMP $F70D |
CK20 JMP ERROR7 ;YES...NOT OUTPUT FILE ; ;COULD BE SCREEN,SERIAL,OR TAPES ; |
sonst 'NOT INPUT FILE' |
go do 'not output file' error and return |
I/O error #7, not output file |
||
.,F262 C9 03 CMP #$03 |
CK10 CMP #3 |
vergleiche mit Bildschirm ? |
compare the device with the screen |
screen? |
||
.,F264 F0 0F BEQ $F275 |
BEQ CK30 ;IS SCREEN...DONE |
verzweige wenn Bildschirm |
if the device is the screen go save output the output device number and exit |
yes |
||
.,F266 B0 11 BCS $F279 |
BCS CK40 ;IS SERIAL...ADDRESS IT |
verzweige wenn IEC-Bus |
if > screen then go handle a serial bus device |
serial bus device |
||
.,F268 C9 02 CMP #$02 |
CMP #2 ;RS232? |
vergleiche mit RS-232 |
compare the device with the RS232 device |
RS232 |
||
.,F26A D0 03 BNE $F26F |
BNE CK15 ; |
verzweige wenn nein |
if not the RS232 device then it must be the tape device |
nope |
||
.,F26C 4C E1 EF JMP $EFE1 |
JMP CKO232 ; ; ;SPECIAL TAPE CHANNEL HANDLING ; |
Ausgabe auf RS-232 vorbereiten Band als Ausgabegerät setzen |
else go open RS232 channel for output open a tape channel for output |
submit to RS232 |
||
.,F26F A6 B9 LDX $B9 |
CK15 LDX SA |
Sekundäradresse laden |
get the secondary address |
SA, current secondary address |
||
.,F271 E0 60 CPX #$60 |
CPX #$60 ;IS COMMAND READ? |
mit 'Null' vergleichen |
||||
.,F273 F0 EA BEQ $F25F |
BEQ CK20 ;YES...ERROR ; |
Bandfile zum Lesen, 'NOT OUTPUT FILE' |
if ?? do not output file error and return |
not output file error |
||
.,F275 85 9A STA $9A |
CK30 STA DFLTO ;ALL OUTPUT GOES HERE ; |
Nummer des Ausgabegeräts setzen |
save the output device number |
DFLTO, default output device |
||
.,F277 18 CLC |
CLC ;GOOD EXIT |
Carry =0 (ok Kennzeichen) |
flag ok |
clear carry to incicate no errors |
||
.,F278 60 RTS |
RTS ; |
RücksprungAusgabe auf IEC-Bus legen |
set serial bus output device |
|||
.,F279 AA TAX |
CK40 TAX ;SAVE DEVICE FOR DFLTO |
Geräteadresse retten |
copy the device number |
file (X) to (A) |
||
.,F27A 20 0C ED JSR $ED0C |
JSR LISTN ;TELL HIM TO LISTEN ; |
LISTEN senden |
command devices on the serial bus to LISTEN |
send LISTEN to serial device |
||
.,F27D A5 B9 LDA $B9 |
LDA SA ;IS THERE A SECOND? |
Sekundäradresse laden |
get the secondary address |
SA |
||
.,F27F 10 05 BPL $F286 |
BPL CK50 ;YES... ; |
verzweige wenn kleiner 128 |
if address to send go ?? |
send SA |
||
.,F281 20 BE ED JSR $EDBE |
JSR SCATN ;NO...RELEASE LINES |
ATN zurücksetzen |
else set serial ATN high |
clear ATN |
||
.,F284 D0 03 BNE $F289 |
BNE CK60 ;BRANCH ALWAYS ; |
unbedingter Sprung |
go ??, branch always |
|||
.,F286 20 B9 ED JSR $EDB9 |
CK50 JSR SECND ;SEND SECOND... ; |
Sekundäradresse für LISTEN senden |
send secondary address after LISTEN |
send listen secondary address |
||
.,F289 8A TXA |
CK60 TXA |
Geräteadresse wiederholen |
copy device number back to A |
|||
.,F28A 24 90 BIT $90 |
BIT STATUS ;DID HE LISTEN? |
Status abfragen |
test the serial status byte |
STATUS, I/O status word |
||
.,F28C 10 E7 BPL $F275 |
BPL CK30 ;YES...FINISH UP ; |
verzweige wenn ok |
if the device is present go save the output device number and exit |
OK, set output device |
||
.,F28E 4C 07 F7 JMP $F707 |
JMP ERROR5 ;NO...DEVICE NOT PRESENT .END .LIB CLOSE;***************************************;* CLOSE -- CLOSE LOGICAL FILE * ;* * ;* THE LOGICAL FILE NUMBER OF THE* ;* FILE TO BE CLOSED IS PASSED IN .A.* ;* KEYBOARD, SCREEN, AND FILES NOT * ;* OPEN PASS STRAIGHT THROUGH. TAPE * ;* FILES OPEN FOR WRITE ARE CLOSED BY* ;* DUMPING THE LAST BUFFER AND * ;* CONDITIONALLY WRITING AN END OF * ;* TAPE BLOCK.SERIAL FILES ARE CLOSED* ;* BY SENDING A CLOSE FILE COMMAND IF* ;* A SECONDARY ADDRESS WAS SPECIFIED * ;* IN ITS OPEN COMMAND. * ;*************************************** ; |
'device not present'CLOSE logische Filenummerim Akku |
else do 'device not present error' and returnclose a specified logical file |
I/O error #5, device not presentCLOSE: CLOSE FILE, PART 1The KERNAL routine CLOSE ($ffc3) is vectored here. Thefile parameters are fetched, and if not found, the routine exits without any action. It checks the device number associated with the file. If it is RS232, then the RS232 port is reset. If it is a serial device, the device is UNTALKed, or UNLISTENed. Finally the number of open logical files are decremented, and the table of active file numbers are updated. On entry (A) holds the file number to close. |
close a file |
|
.,F291 20 14 F3 JSR $F314 |
NCLOSE JSR JLTLK ;LOOK FILE UP |
sucht logische Filenummer |
find file A |
find logical file, (X) holds location i table |
||
.,F294 F0 02 BEQ $F298 |
BEQ JX050 ;OPEN... |
verzweige wenn gefunden |
if file found go close it |
OK |
||
.,F296 18 CLC |
CLC ;ELSE RETURN |
File nicht vorhanden, dann fertig |
else the file was closed so just flag ok |
file not found |
||
.,F297 60 RTS |
RTS ; |
Rücksprung |
file found so close it |
and exit |
||
.,F298 20 1F F3 JSR $F31F |
JX050 JSR JZ100 ;EXTRACT TABLE DATA |
Fileparameter setzen |
set file details from table,X |
get file values from table, position (X) |
||
.,F29B 8A TXA |
TXA ;SAVE TABLE INDEX |
Zeiger auf Parametereintrag in Filetabelle |
copy file index to A |
|||
.,F29C 48 PHA |
PHA ; |
retten |
save file index |
temp store |
||
.,F29D A5 BA LDA $BA |
LDA FA ;CHECK DEVICE NUMBER |
Geräteadresse laden |
get the device number |
FA, current device number |
||
.,F29F F0 50 BEQ $F2F1 |
BEQ JX150 ;IS KEYBOARD...DONE |
verzweige wenn Tastatur |
if it is the keyboard go restore the index and close the file |
keyboard?, update file table |
||
.,F2A1 C9 03 CMP #$03 |
CMP #3 |
vergleiche mit Bildschirm |
compare the device number with the screen |
screen |
||
.,F2A3 F0 4C BEQ $F2F1 |
BEQ JX150 ;IS SCREEN...DONE |
verzweige wenn Bildschirm |
if it is the screen go restore the index and close the file |
yepp, update file table |
||
.,F2A5 B0 47 BCS $F2EE |
BCS JX120 ;IS SERIAL...PROCESS |
verzweige wenn IEC-Bus |
if > screen go do serial bus device close |
Serial bus |
||
.,F2A7 C9 02 CMP #$02 |
CMP #2 ;RS232? |
vergleiche mit RS-232 |
compare the device with the RS232 device |
RS232 |
||
.,F2A9 D0 1D BNE $F2C8 |
BNE JX115 ;NO... ; ; RS-232 CLOSE ; ; REMOVE FILE FROM TABLES |
nein, dann BandRS-232 File schließen |
if not the RS232 device go ?? else close RS232 device |
nope, serial |
||
.,F2AB 68 PLA |
PLA |
Zeiger auf Parametereintrag |
restore file index |
retrieve (A) |
||
.,F2AC 20 F2 F2 JSR $F2F2 |
JSR JXRMV ; |
Fileeintrag in Tabelle löschen |
close file index X |
remove entry (A) from file table |
||
.,F2AF 20 83 F4 JSR $F483 |
JSR CLN232 ;CLEAN UP RS232 FOR CLOSE ; ; DEALLOCATE BUFFERS ; |
CIAs für I/O rücksetzen |
initialise RS232 output |
init RS232 port by using part of RS232OPEN |
||
.,F2B2 20 27 FE JSR $FE27 |
JSR GETTOP ;GET MEMSIZ |
Memory-Top holen |
read the top of memory |
MEMTOP, read top of memory (X/Y) |
||
.,F2B5 A5 F8 LDA $F8 |
LDA RIBUF+1 ;CHECK INPUT ALLOCATION |
RS-232 Eingabepuffer HIGH-Byte laden |
get the RS232 input buffer pointer high byte |
>RIBUF, RS232 input buffer |
||
.,F2B7 F0 01 BEQ $F2BA |
BEQ CLS010 ;NOT...ALLOCATED |
verzweige wenn 0 |
if no RS232 input buffer go ?? |
|||
.,F2B9 C8 INY |
INY |
HIGH-Byte von Memory-Top erhöhen |
else reclaim RS232 input buffer memory |
|||
.,F2BA A5 FA LDA $FA |
CLS010 LDA ROBUF+1 ;CHECK OUTPUT ALLOCATION |
RS-232 Ausgabepuffer HIGH-Byte laden |
get the RS232 output buffer pointer high byte |
>ROBUF, RS232 output buffer |
||
.,F2BC F0 01 BEQ $F2BF |
BEQ CLS020 |
verzweige wenn 0 |
if no RS232 output buffer skip the reclaim |
|||
.,F2BE C8 INY |
INY |
sonst HIGH-Byte von Memory- Top erhöhen |
else reclaim the RS232 output buffer memory |
|||
.,F2BF A9 00 LDA #$00 |
CLS020 LDA #00 ;DEALLOCATE |
0 laden |
clear A |
Clear RS232 input/output buffers |
||
.,F2C1 85 F8 STA $F8 |
STA RIBUF+1 |
und Puffer |
clear the RS232 input buffer pointer high byte |
|||
.,F2C3 85 FA STA $FA |
STA ROBUF+1 ; FLAG TOP OF MEMORY CHANGE |
freigeben |
clear the RS232 output buffer pointer high byte |
|||
.,F2C5 4C 7D F4 JMP $F47D |
JMP MEMTCF ;GO SET NEW TOP ; ;CLOSE CASSETTE FILE ; |
Memory Top neu setzenBand File schließen |
go set the top of memory to F0xx is not the RS232 device |
Set new ROBOF values and set new MEMTOP |
close cassette device |
|
.,F2C8 A5 B9 LDA $B9 |
JX115 LDA SA ;WAS IT A TAPE READ? |
Sekundäradresse laden |
get the secondary address |
|||
.,F2CA 29 0F AND #$0F |
AND #$F |
Bits 0 bis 3 isolieren |
mask the device # |
|||
.,F2CC F0 23 BEQ $F2F1 |
BEQ JX150 ;YES ; |
verzweige wenn File zum Lesen |
if ?? restore index and close file |
|||
.,F2CE 20 D0 F7 JSR $F7D0 |
JSR ZZZ ;NO. . .IT IS WRITE |
Band-Puffer Startadresse holen |
get tape buffer start pointer in XY |
|||
.,F2D1 A9 00 LDA #$00 |
LDA #0 ;END OF FILE CHARACTER |
Markierung für letztes Zeichen im Datenpuffer |
character $00 |
|||
.,F2D3 38 SEC |
SEC ;NEED TO SET CARRY FOR CASOUT (ELSE RS232 OUTPUT!) |
Flag für Ausgabe auf Recorder |
flag the tape device |
|||
.,F2D4 20 DD F1 JSR $F1DD |
JSR CASOUT ;PUT IN END OF FILE |
Zeichen in Kassettenpuffer |
output the character to the cassette or RS232 device |
|||
.,F2D7 20 64 F8 JSR $F864 |
JSR WBLK |
Puffer auf Band schreiben |
initiate tape write |
|||
.,F2DA 90 04 BCC $F2E0 |
BCC JX117 ;NO ERRORS... |
verzweige wenn alles ok |
||||
.,F2DC 68 PLA |
PLA ;CLEAN STACK FOR ERROR |
Zeiger auf Fileeintrag holen |
||||
.,F2DD A9 00 LDA #$00 |
LDA #0 ;BREAK KEY ERROR |
0 für Break |
||||
.,F2DF 60 RTS |
RTS ; |
Rücksprung |
||||
.,F2E0 A5 B9 LDA $B9 |
JX117 LDA SA |
Sekundäradresse laden |
get the secondary address |
|||
.,F2E2 C9 62 CMP #$62 |
CMP #$62 ;WRITE END OF TAPE BLOCK? |
vergleiche auf Open mit EOT |
||||
.,F2E4 D0 0B BNE $F2F1 |
BNE JX150 ;NO... ; |
verzweige wenn kein EOT |
if not ?? restore index and close file |
|||
.,F2E6 A9 05 LDA #$05 |
LDA #EOT |
Kontrollbyte für EOT-Header |
set logical end of the tape |
|||
.,F2E8 20 6A F7 JSR $F76A |
JSR TAPEH ;WRITE END OF TAPE BLOCK |
Block auf Band schreiben |
write tape header |
|||
.,F2EB 4C F1 F2 JMP $F2F1 |
JMP JX150 ; ;CLOSE AN SERIAL FILE ; |
Überspringe nächsten Befehl |
restore index and close fileserial bus device close |
CLOSE: CLOSE FILE, PART 2 |
close serial bus device |
|
.,F2EE 20 42 F6 JSR $F642 |
JX120 JSR CLSEI ; ;ENTRY TO REMOVE A GIVE LOGICAL FILE ;FROM TABLE OF LOGICAL, PRIMARY, ;AND SECONDARY ADDRESSES ; |
IEC-File schließen |
close serial bus device |
UNTALK/UNLISTEN serial device |
||
.,F2F1 68 PLA |
JX150 PLA ;GET TABLE INDEX OFF STACK ; ; JXRMV - ENTRY TO USE AS AN RS-232 SUBROUTINE ; |
Zeiger auf Fileeintrag holen |
restore file indexclose file index X |
reorganise file tables |
||
.,F2F2 AA TAX |
JXRMV TAX |
ins X-Register schieben |
copy index to file to close |
|||
.,F2F3 C6 98 DEC $98 |
DEC LDTND |
Anzahl der offenen Files erniedrigen |
decrement the open file count |
decrement LDTND, number of open files |
||
.,F2F5 E4 98 CPX $98 |
CPX LDTND ;IS DELETED FILE AT END? |
und mit Zeiger auf Fileeintrag vergleichen |
compare the index with the open file count |
compare LDTND to (X) |
||
.,F2F7 F0 14 BEQ $F30D |
BEQ JX170 ;YES...DONE ; ;DELETE ENTRY IN MIDDLE BY MOVING ;LAST ENTRY TO THAT POSITION. ; |
gleich, dann fertig |
exit if equal, last entry was closing file else entry was not last in list so copy last table entry file details over the details of the closing one |
equal, closed file = last file in table |
||
.,F2F9 A4 98 LDY $98 |
LDY LDTND |
Anzahl der offenen Files |
get the open file count as index |
else, move last entry to position of closed entry |
||
.,F2FB B9 59 02 LDA $0259,Y |
LDA LAT,Y |
Letzten Fileeintrag |
get last+1 logical file number from logical file table |
LAT, active filenumbers |
||
.,F2FE 9D 59 02 STA $0259,X |
STA LAT,X |
an die |
save logical file number over closed file |
|||
.,F301 B9 63 02 LDA $0263,Y |
LDA FAT,Y |
freigewordene |
get last+1 device number from device number table |
FAT, active device numbers |
||
.,F304 9D 63 02 STA $0263,X |
STA FAT,X |
Stelle in der |
save device number over closed file |
|||
.,F307 B9 6D 02 LDA $026D,Y |
LDA SAT,Y |
Filetabelle |
get last+1 secondary address from secondary address table |
SAT, active secondary addresses |
||
.,F30A 9D 6D 02 STA $026D,X |
STA SAT,X ; |
schreiben |
save secondary address over closed file |
|||
.,F30D 18 CLC |
JX170 CLC ;CLOSE EXIT |
Carry =0 (ok Kennzeichnung) |
flag ok |
|||
.,F30E 60 RTS |
JX175 RTS ;LOOKUP TABLIZED LOGICAL FILE DATA ; |
Rücksprungsucht logische Filenummer(in X) |
find a file |
returnFIND FILEThis routine finds a logical file from it's file number.On entry, (X) must hold the logical file number to be found. LAT, the table of file numbers is searched, and if found (X) contains the offset to the position of the file in the table, and the Z flag is set. If not found, Z=0. |
check X against logical file table |
|
.,F30F A9 00 LDA #$00 |
LOOKUP LDA #0 |
Status |
clear A |
|||
.,F311 85 90 STA $90 |
STA STATUS |
löschen |
clear the serial status byte |
clear STATUS |
||
.,F313 8A TXA |
TXA |
Filenummer in Akku schieben |
copy the logical file number to Afind file A |
file number to search for |
||
.,F314 A6 98 LDX $98 |
JLTLK LDX LDTND |
Anzahl der offenen Files |
get the open file count |
LDTND, number of open files |
||
.,F316 CA DEX |
JX600 DEX |
Anzahl um eins verringern |
decrememnt the count to give the index |
|||
.,F317 30 15 BMI $F32E |
BMI JZ101 |
verzweige wenn kein File offen oder Filenummer nicht gefunden |
if no files just exit |
end of table, return |
||
.,F319 DD 59 02 CMP $0259,X |
CMP LAT,X |
sucht Eintrag in Tabelle |
compare the logical file number with the table logical file number |
compare file number with LAT, table of open files |
||
.,F31C D0 F8 BNE $F316 |
BNE JX600 |
verzweige wenn noch nicht gefunden |
if no match go try again |
not equal, try next |
||
.,F31E 60 RTS |
RTS ;ROUTINE TO FETCH TABLE ENTRIES ; |
Rücksprungsetzt Fileparameter |
set file details from table,X |
back with Z flag setSEET FILE VALUESThis routine sets the current logical file number, devicenumber and secondary address from the file parameter tables. On entry (X) must hold the offset to the position of the file in the table. |
set file parameters depending on X |
|
.,F31F BD 59 02 LDA $0259,X |
JZ100 LDA LAT,X |
logische Filenummer aus |
get logical file from logical file table |
LAT, table of active logical files |
||
.,F322 85 B8 STA $B8 |
STA LA |
Tabelle holen und speichern |
save the logical file |
store in LA |
||
.,F324 BD 63 02 LDA $0263,X |
LDA FAT,X |
Geräteadresse aus Tabelle |
get device number from device number table |
FAT, table of active device numbers |
||
.,F327 85 BA STA $BA |
STA FA |
holen und speichern |
save the device number |
store in FA |
||
.,F329 BD 6D 02 LDA $026D,X |
LDA SAT,X |
Sekundäradresse aus Tabelle |
get secondary address from secondary address table |
SAT, table of active secondary addresses |
||
.,F32C 85 B9 STA $B9 |
STA SA |
holen und speichern |
save the secondary address |
store in SAT |
||
.,F32E 60 RTS |
JZ101 RTS .END .LIB CLALL;***************************************;* CLALL -- CLOSE ALL LOGICAL FILES * ;* DELETES ALL TABLE ENTRIES AND* ;* RESTORES DEFAULT I/O CHANNELS * ;* AND CLEARS IEEE PORT DEVICES * ;************************************* ; |
RücksprungCLALL schließt alleEin-/Ausgabe Kanäle |
close all channels and files |
returnCLALL: ABORT ALL FILESThe KERNAL routine CLALL ($ffe7) is vectored here. Thenumber of open files are set to zero, and the next routine is performed. |
close all files |
|
.,F32F A9 00 LDA #$00 |
NCLALL LDA #0 |
Anzahl der offenen Files |
clear A |
|||
.,F331 85 98 STA $98 |
STA LDTND ;FORGET ALL FILES ;******************************************** ;* CLRCH -- CLEAR CHANNELS * ;* UNLISTEN OR UNTALK IEEE DEVICES, BUT * ;* LEAVE OTHERS ALONE. DEFAULT CHANNELS * ;* ARE RESTORED. * ;******************************************** ; |
auf Null stellenCLRCH schließt aktivenI/O-Kanal |
clear the open file countclose input and output channels |
clear LDTND, no open filesCLRCHN: RESTORE TO DEFAULT I/OThe KERNAL routine CLRCHN ($ffcc) is vectored here. Thedefault output device is UNLISTENed, if it is on the serial bus, and the default output is set to the screen. The default input device is UNTALKed, if it is on the serial bus, and the default input device is set to keyboard. |
restore I/O to default devices |
|
.,F333 A2 03 LDX #$03 |
NCLRCH LDX #3 |
Vergleichswert in X |
set the screen device |
check if device > 3 (serial bus is 4,5...) |
||
.,F335 E4 9A CPX $9A |
CPX DFLTO ;IS OUTPUT CHANNEL IEEE? |
vergleiche mit Nummer des Ausgabegeräts |
compare the screen with the output device number |
test DFLTO, default output device |
||
.,F337 B0 03 BCS $F33C |
BCS JX750 ;NO... ; |
verzweige wenn kleiner als 3 |
if <= screen skip the serial bus unlisten |
nope, no serial device |
||
.,F339 20 FE ED JSR $EDFE |
JSR UNLSN ;YES...UNLISTEN IT ; |
IEC, UNLISTEN senden |
else command the serial bus to UNLISTEN |
send UNLISTEN to serial bus |
||
.,F33C E4 99 CPX $99 |
JX750 CPX DFLTN ;IS INPUT CHANNEL IEEE? |
vergleiche mit Nummer des Eingabegeräts |
compare the screen with the input device number |
test DFLTI, default input device |
||
.,F33E B0 03 BCS $F343 |
BCS CLALL2 ;NO... ; |
verzweige wenn kleiner als 3 |
if <= screen skip the serial bus untalk |
nope, no serial device |
||
.,F340 20 EF ED JSR $EDEF |
JSR UNTLK ;YES...UNTALK IT ; ;RESTORE DEFAULT VALUES ; ; |
IEC, UNTALK senden |
else command the serial bus to UNTALK |
send UNTALK to serial bus |
||
.,F343 86 9A STX $9A |
CLALL2 STX DFLTO ;OUTPUT CHAN=3=SCREEN |
Ausgabe wieder auf Bildschirm |
save the screen as the output device number |
store screen as DFLTO |
||
.,F345 A9 00 LDA #$00 |
LDA #0 |
Eingabe wieder |
set the keyboard as the input device |
|||
.,F347 85 99 STA $99 |
STA DFLTN ;INPUT CHAN=0=KEYBOARD |
von Tastatur |
save the input device number |
store keyboard as DFLTI |
||
.,F349 60 RTS |
RTS .END .LIB OPEN;***********************************;* * ;* OPEN FUNCTION * ;* * ;* CREATES AN ENTRY IN THE LOGICAL * ;* FILES TABLES CONSISTING OF * ;* LOGICAL FILE NUMBER--LA, DEVICE * ;* NUMBER--FA, AND SECONDARY CMD-- * ;* SA. * ;* * ;* A FILE NAME DESCRIPTOR, FNADR & * ;* FNLEN ARE PASSED TO THIS ROUTINE* ;* * ;*********************************** ; |
RücksprungOPEN |
open a logical file |
OPEN: OPEN FILEThe KERNAL routine OPEN ($ffc0) is vectored here. The fileparamerters must be set before entry. The routine reads the LAT, to see if file already exists, which will result in I/O error #2, ?FILE OPEN. A test is made to see if more than 10 files are open. If so, I/O error #1, ?TOO MANY FiLES, will occur. The file parameters are set, and put in their respective tables. The device number is checked, and each kind of device jumps to their own routine. Keyboard and screen will exit here with no further actions. RS232 is opened via a seperate routine. SA, secondary address, and filename will be sent on the serial bus. |
open a file |
|
.,F34A A6 B8 LDX $B8 |
NOPEN LDX LA ;CHECK FILE # |
Filenummer in X |
get the logical file |
LA, current logical number |
||
.,F34C D0 03 BNE $F351 |
BNE OP98 ;IS NOT THE KEYBOARD ; |
verzweige wenn ungleich Null |
if there is a file continue |
|||
.,F34E 4C 0A F7 JMP $F70A |
JMP ERROR6 ;NOT INPUT FILE... ; |
'not input file' (??) |
else do 'not input file error' and return |
I/O error #6, not input file |
||
.,F351 20 0F F3 JSR $F30F |
OP98 JSR LOOKUP ;SEE IF IN TABLE |
sucht logische Filenummer |
find a file |
find file (X) |
||
.,F354 D0 03 BNE $F359 |
BNE OP100 ;NOT FOUND...O.K. ; |
nicht gefunden, kann neu angelegt werden |
if file not found continue |
|||
.,F356 4C FE F6 JMP $F6FE |
JMP ERROR2 ;FILE OPEN ; |
sonst 'file open' |
else do 'file already open' error and return |
I/O error #2, file exists |
||
.,F359 A6 98 LDX $98 |
OP100 LDX LDTND ;LOGICAL DEVICE TABLE END |
Anzahl der offenen Files |
get the open file count |
LDTND, number of open files |
||
.,F35B E0 0A CPX #$0A |
CPX #10 ;MAXIMUM # OF OPEN FILES |
mit 10 vergleichen |
compare it with the maximum + 1 |
more than ten |
||
.,F35D 90 03 BCC $F362 |
BCC OP110 ;LESS THAN 10...O.K. ; |
kleiner 10 dann ok |
if less than maximum + 1 go open the file |
nope |
||
.,F35F 4C FB F6 JMP $F6FB |
JMP ERROR1 ;TOO MANY FILES ; |
'too many files' |
else do 'too many files error' and return |
I/O error #1, too many files |
||
.,F362 E6 98 INC $98 |
OP110 INC LDTND ;NEW FILE |
Anzahl erhöhen |
increment the open file count |
increment LDTND |
||
.,F364 A5 B8 LDA $B8 |
LDA LA |
logische Filenummer laden |
get the logical file |
LA |
||
.,F366 9D 59 02 STA $0259,X |
STA LAT,X ;STORE LOGICAL FILE # |
und in die Tabelle schreiben |
save it to the logical file table |
store in LAT, table of active file numbers |
||
.,F369 A5 B9 LDA $B9 |
LDA SA |
Sekundäradresse laden |
get the secondary address |
SA |
||
.,F36B 09 60 ORA #$60 |
ORA #$60 ;MAKE SA AN SERIAL COMMAND |
Bit 5 und 6 setzen |
OR with the OPEN CHANNEL command |
fixx |
||
.,F36D 85 B9 STA $B9 |
STA SA |
wieder speichern |
save the secondary address |
store in SA |
||
.,F36F 9D 6D 02 STA $026D,X |
STA SAT,X ;STORE COMMAND # |
und in die Tabelle schreiben |
save it to the secondary address table |
store in SAT, table of active secondary addresses |
||
.,F372 A5 BA LDA $BA |
LDA FA |
Gerätenummer laden |
get the device number |
FA |
||
.,F374 9D 63 02 STA $0263,X |
STA FAT,X ;STORE DEVICE # ; ;PERFORM DEVICE SPECIFIC OPEN TASKS ; |
und in die Tabelle schreiben |
save it to the device number table |
store in FAT, table of active device numbers |
||
.,F377 F0 5A BEQ $F3D3 |
BEQ OP175 ;IS KEYBOARD...DONE. |
verzweige wenn Gerätenummer für Tastatur |
if it is the keyboard go do the ok exit |
keyboard, end |
||
.,F379 C9 03 CMP #$03 |
CMP #3 |
Code für Bildschirm |
compare the device number with the screen |
screen |
||
.,F37B F0 56 BEQ $F3D3 |
BEQ OP175 ;IS SCREEN...DONE. |
ja, so verzweige |
if it is the screen go do the ok exit |
yep, end |
||
.,F37D 90 05 BCC $F384 |
BCC OP150 ;ARE CASSETTES 1 & 2 ; |
verzweige wenn nicht IEC-Bus |
if tape or RS232 device go ?? else it is a serial bus device |
less than 3, not serial bus |
||
.,F37F 20 D5 F3 JSR $F3D5 |
JSR OPENI ;IS ON SERIAL...OPEN IT |
File auf IEC-Bus eröffnen |
send the secondary address and filename |
send SA |
||
.,F382 90 4F BCC $F3D3 |
BCC OP175 ;BRANCH ALWAYS...DONE ; ;PERFORM TAPE OPEN STUFF ; |
unbedingter Sprung |
go do ok exit, branch always |
end |
||
.,F384 C9 02 CMP #$02 |
OP150 CMP #2 |
Code für Band |
TAPE |
|||
.,F386 D0 03 BNE $F38B |
BNE OP152 ; |
verzweige wenn nein |
I/O error #5, device not present |
|||
.,F388 4C 09 F4 JMP $F409 |
JMP OPN232 ; |
RS-232 open |
go open RS232 device and return |
open RS232 file |
open for cassette device |
|
.,F38B 20 D0 F7 JSR $F7D0 |
OP152 JSR ZZZ ;SEE IF TAPE BUFFER |
Bandpuffer Startadresse in X und Y holen |
get tape buffer start pointer in XY |
|||
.,F38E B0 03 BCS $F393 |
BCS OP155 ;YES ; |
verzweige wenn HIGH-Byte größer als 2 |
if >= $0200 go ?? |
|||
.,F390 4C 13 F7 JMP $F713 |
JMP ERROR9 ;NO...DEALLOCATED ; |
'illegal device number' |
else do 'illegal device number' and return |
|||
.,F393 A5 B9 LDA $B9 |
OP155 LDA SA |
Sekundäradresse laden |
get the secondary address |
|||
.,F395 29 0F AND #$0F |
AND #$F ;MASK OFF COMMAND |
Bits 0 bis 3 isolieren |
||||
.,F397 D0 1F BNE $F3B8 |
BNE OP200 ;NON ZERO IS TAPE WRITE ; ;OPEN CASSETE TAPE FILE TO READ ; |
ungleich Null dann schreiben |
||||
.,F399 20 17 F8 JSR $F817 |
JSR CSTE1 ;TELL "PRESS PLAY" |
wartet auf Play-Taste |
wait for PLAY |
|||
.,F39C B0 36 BCS $F3D4 |
BCS OP180 ;STOP KEY PRESSED ; |
verzweige wenn Play Taste gedrückt |
exit if STOP was pressed |
|||
.,F39E 20 AF F5 JSR $F5AF |
JSR LUKING ;TELL USER "SEARCHING" ; |
'SEARCHING' ('for name') ausgeben |
print "Searching..." |
|||
.,F3A1 A5 B7 LDA $B7 |
LDA FNLEN |
Länge des Filenamens |
get file name length |
|||
.,F3A3 F0 0A BEQ $F3AF |
BEQ OP170 ;LOOKING FOR ANY FILE ; |
kein Filename, dann weiter |
if null file name just go find header |
|||
.,F3A5 20 EA F7 JSR $F7EA |
JSR FAF ;LOOKING FOR NAMED FILE |
sucht gewünschen Bandheader |
find specific tape header |
|||
.,F3A8 90 18 BCC $F3C2 |
BCC OP171 ;FOUND IT!!! |
verzweige wenn gefunden |
branch if no error |
|||
.,F3AA F0 28 BEQ $F3D4 |
BEQ OP180 ;STOP KEY PRESSED ; |
verzweige wenn STOP-Taste |
exit if ?? |
|||
.,F3AC 4C 04 F7 JMP $F704 |
OP160 JMP ERROR4 ;FILE NOT FOUND ; |
EOT, 'FILE NOT FOUND' ausgeben |
do file not found error and return |
|||
.,F3AF 20 2C F7 JSR $F72C |
OP170 JSR FAH ;GET ANY OLD HEADER |
nächsten Bandheader suchen |
find tape header, exit with header in buffer |
|||
.,F3B2 F0 20 BEQ $F3D4 |
BEQ OP180 ;STOP KEY PRESSED |
EOT, Fehler |
exit if end of tape found |
|||
.,F3B4 90 0C BCC $F3C2 |
BCC OP171 ;ALL O.K. |
verzweige wenn gefunden |
||||
.,F3B6 B0 F4 BCS $F3AC |
BCS OP160 ;FILE NOT FOUND... ; ;OPEN CASSETTE TAPE FOR WRITE ; |
sonst PRG-File, weiter suchen |
open cassette for input |
|||
.,F3B8 20 38 F8 JSR $F838 |
OP200 JSR CSTE2 ;TELL "PRESS PLAY AND RECORD" |
wartet auf Record & Play Taste |
wait for PLAY/RECORD |
|||
.,F3BB B0 17 BCS $F3D4 |
BCS OP180 ;STOP KEY PRESSED |
STOP-Taste, dann Abbruch |
exit if STOP was pressed |
|||
.,F3BD A9 04 LDA #$04 |
LDA #BDFH ;DATA FILE HEADER TYPE |
Kontrollbyte für Datenheader |
set data file header |
|||
.,F3BF 20 6A F7 JSR $F76A |
JSR TAPEH ;WRITE IT ; ;FINISH OPEN FOR TAPE READ/WRITE ; |
Header auf Band schreiben |
write tape header |
|||
.,F3C2 A9 BF LDA #$BF |
OP171 LDA #BUFSZ-1 ;ASSUME FORCE READ ; |
Zeiger auf Ende des Bandpuffers |
||||
.,F3C4 A4 B9 LDY $B9 |
LDY SA |
Sekundäradresse laden |
get the secondary address |
|||
.,F3C6 C0 60 CPY #$60 |
CPY #$60 ;OPEN FOR READ? |
vergleiche mit $60 für Band lesen |
||||
.,F3C8 F0 07 BEQ $F3D1 |
BEQ OP172 ; ;SET POINTERS FOR BUFFERING DATA ; |
lesen, dann verzweige |
||||
.,F3CA A0 00 LDY #$00 |
LDY #0 |
Zeiger auf 0 setzen |
clear index |
|||
.,F3CC A9 02 LDA #$02 |
LDA #BDF ;TYPE FLAG FOR BLOCK |
Kontrollbyte für Datenblock |
||||
.,F3CE 91 B2 STA ($B2),Y |
STA (TAPE1)Y ;TO BEGIN OF BUFFER |
in Bandpuffer schreiben |
save to tape buffer |
|||
.,F3D0 98 TYA |
TYA ; |
Zeiger in Akku |
clear A |
|||
.,F3D1 85 A6 STA $A6 |
OP172 STA BUFPT ;POINT TO DATA |
Zeiger in Bandpuffer setzen |
save tape buffer index |
|||
.,F3D3 18 CLC |
OP175 CLC ;FLAG GOOD OPEN |
Carry =0 (ok Kennzeichen) |
flag ok |
|||
.,F3D4 60 RTS |
OP180 RTS ;EXIT IN PEACE |
RücksprungFile auf IEC-Bus eröffnen |
send secondary address and filename |
SEND SAThis routine exits if there is no secondary address orfilename specifyed. The I/O status word, ST, is reset, and the serial device is commanded to LISTEN. A check is made for a possible ?DEVICE NOT PRESENT error. Finally, the filename is sent to the device. |
open for serial bus devices |
|
.,F3D5 A5 B9 LDA $B9 |
OPENI LDA SA |
Sekundäradresse laden |
get the secondary address |
SA, current secondary address |
||
.,F3D7 30 FA BMI $F3D3 |
BMI OP175 ;NO SA...DONE ; |
Rücksprung wenn größer, gleich 128 |
ok exit if -ve |
exit |
||
.,F3D9 A4 B7 LDY $B7 |
LDY FNLEN |
Länge des Filenamens laden |
get file name length |
FNLEN, length of filename |
||
.,F3DB F0 F6 BEQ $F3D3 |
BEQ OP175 ;NO FILE NAME...DONE ; |
gleich Null, dann fertig |
ok exit if null |
exit |
||
.,F3DD A9 00 LDA #$00 |
LDA #0 ;CLEAR THE SERIAL STATUS |
Status |
clear A |
|||
.,F3DF 85 90 STA $90 |
STA STATUS ; |
löschen |
clear the serial status byte |
clear STATUS, I/O status word |
||
.,F3E1 A5 BA LDA $BA |
LDA FA |
Geräteadressse laden |
get the device number |
FA, current device number |
||
.,F3E3 20 0C ED JSR $ED0C |
JSR LISTN ;DEVICE LA TO LISTEN ; |
LISTEN |
command devices on the serial bus to LISTEN |
send LISTEN to serial bus |
||
.,F3E6 A5 B9 LDA $B9 |
LDA SA |
Sekundäradresse laden |
get the secondary address |
SA |
||
.,F3E8 09 F0 ORA #$F0 |
ORA #$F0 |
Bits 4 bis 7 setzen (Open Kennzeichnung) |
OR with the OPEN command |
|||
.,F3EA 20 B9 ED JSR $EDB9 |
JSR SECND ; |
Sekundäradresse senden |
send secondary address after LISTEN |
send LISTEN SA |
||
.,F3ED A5 90 LDA $90 |
LDA STATUS ;ANYBODY HOME? |
Status testen |
get the serial status byte |
STATUS |
||
.,F3EF 10 05 BPL $F3F6 |
BPL OP35 ;YES...CONTINUE ; ;THIS ROUTINE IS CALLED BY OTHER ;KERNAL ROUTINES WHICH ARE CALLED ;DIRECTLY BY OS. KILL RETURN ;ADDRESS TO RETURN TO OS. ; |
verzweige wenn ok |
if device present skip the 'device not present' error |
ok |
||
.,F3F1 68 PLA |
PLA |
Stack |
else dump calling address low byte |
remove two stack entries for RTS command |
||
.,F3F2 68 PLA |
PLA |
rücksetzen |
dump calling address high byte |
|||
.,F3F3 4C 07 F7 JMP $F707 |
JMP ERROR5 ;DEVICE NOT PRESENT ; |
'device not present' |
do 'device not present' error and return |
I/O error #5, device not present |
||
.,F3F6 A5 B7 LDA $B7 |
OP35 LDA FNLEN |
Länge des Filenamens |
get file name length |
FNLEN |
||
.,F3F8 F0 0C BEQ $F406 |
BEQ OP45 ;NO NAME...DONE SEQUENCE ; ;SEND FILE NAME OVER SERIAL ; |
kein Filename, dann fertig |
branch if null name |
unlisten and exit |
||
.,F3FA A0 00 LDY #$00 |
LDY #0 |
Zeiger auf Null setzen |
clear index |
clear offset |
||
.,F3FC B1 BB LDA ($BB),Y |
OP40 LDA (FNADR)Y |
Filenamen holen |
get file name byte |
FNADR, pointer to filename |
||
.,F3FE 20 DD ED JSR $EDDD |
JSR CIOUT |
auf IEC-Bus ausgeben |
output byte to serial bus |
send byte on serial bus |
||
.,F401 C8 INY |
INY |
Zeiger erhöhen |
increment index |
next character |
||
.,F402 C4 B7 CPY $B7 |
CPY FNLEN |
mit Länge des Filenamens vergleichen |
compare with file name length |
until entire filename is sent |
||
.,F404 D0 F6 BNE $F3FC |
BNE OP40 ; |
verzweige wenn noch nicht alle Zeichen |
loop if not all done |
again |
||
.,F406 4C 54 F6 JMP $F654 |
OP45 JMP CUNLSN ;JSR UNLSN: CLC: RTS ; OPN232 - OPEN AN RS-232 OR PARALLEL PORT FILE ; ; VARIABLES INITILIZED ; BITNUM - # OF BITS TO BE SENT CALC FROM M51CTR ; BAUDOF - BAUD RATE FULL ; RSSTAT - RS-232 STATUS REG ; M51CTR - 6551 CONTROL REG ; M51CDR - 6551 COMMAND REG ; M51AJB - USER BAUD RATE (CLOCK/BAUD/2-100) ; ENABL - 6526 NMI ENABLES (1-NMI BIT ON) ; |
UNLISTEN, returnRS-232 Open |
command serial bus to UNLISTEN and returnopen RS232 device |
unlisten and exitOPEN RS232 |
open RS-232 device |
|
.,F409 20 83 F4 JSR $F483 |
OPN232 JSR CLN232 ;SET UP RS232, .Y=0 ON RETURN ; ; PASS PRAMS TO M51REGS ; |
CIAs setzen |
initialise RS232 output |
|||
.,F40C 8C 97 02 STY $0297 |
STY RSSTAT ;CLEAR STATUS ; |
RS-232 Status löschen |
save the RS232 status register |
|||
.,F40F C4 B7 CPY $B7 |
OPN020 CPY FNLEN ;CHECK IF AT END OF FILENAME |
Länge des "Filenamens" |
compare with file name length |
|||
.,F411 F0 0A BEQ $F41D |
BEQ OPN025 ;YES... ; |
verzweige wenn kein Filename |
exit loop if done |
|||
.,F413 B1 BB LDA ($BB),Y |
LDA (FNADR)Y ;MOVE DATA |
die ersten |
get file name byte |
|||
.,F415 99 93 02 STA $0293,Y |
STA M51CTR,Y ;TO M51REGS |
vier |
copy to 6551 register set |
|||
.,F418 C8 INY |
INY |
Zeichen |
increment index |
|||
.,F419 C0 04 CPY #$04 |
CPY #4 ;ONLY 4 POSSIBLE PRAMS |
speichern |
compare with $04 |
|||
.,F41B D0 F2 BNE $F40F |
BNE OPN020 ; ; CALC # OF BITS ; |
verzweige wenn noch nicht alle vier Zeichen |
loop if not to 4 yet |
|||
.,F41D 20 4A EF JSR $EF4A |
OPN025 JSR BITCNT |
Anzahl der Datenbits berechnen |
compute bit count |
|||
.,F420 8E 98 02 STX $0298 |
STX BITNUM ; ; CALC BAUD RATE ; |
und speichern |
save bit count |
|||
.,F423 AD 93 02 LDA $0293 |
LDA M51CTR |
Kontrollregister holen |
get pseudo 6551 control register |
|||
.,F426 29 0F AND #$0F |
AND #$0F |
Bits für Baud-Rate isolieren |
mask 0000 xxxx, baud rate |
|||
.,F428 F0 1C BEQ $F446 |
BNE OPN010 ; ; CALCULATE START-TEST RATE... ; DIFFERENT THAN ORIGINAL RELEASE 901227-01 ; |
verzweige wenn User-Baud-Rate |
if zero skip the baud rate setup |
|||
.,F42A 0A ASL |
ASL A ;GET OFFSET INTO TABLES |
mal 2 für Tabelle |
* 2 bytes per entry |
|||
.,F42B AA TAX |
TAX |
als Zeiger merken |
copy to the index |
|||
.,F42C AD A6 02 LDA $02A6 |
LDA PALNTS ;GET TV STANDARD |
NTSC-Version |
get the PAL/NTSC flag |
|||
.,F42F D0 09 BNE $F43A |
BNE OPN026 |
verzweige wenn nein |
if PAL go set PAL timing |
|||
.,F431 BC C1 FE LDY $FEC1,X |
LDY BAUDO-1,X ;NTSC STANDARD |
Baud-Rate, HIGH für NTSC-Timing |
get the NTSC baud rate value high byte |
|||
.,F434 BD C0 FE LDA $FEC0,X |
LDA BAUDO-2,X |
Baud-Rate, LOW |
get the NTSC baud rate value low byte |
|||
.,F437 4C 40 F4 JMP $F440 |
JMP OPN027 ; |
überspringe zwei Befehle |
go save the baud rate values |
|||
.,F43A BC EB E4 LDY $E4EB,X |
OPN026 LDY BAUDOP-1,X ;PAL STANDARD |
Baud-Rate, HIGH für PAL-Timing |
get the PAL baud rate value high byte |
|||
.,F43D BD EA E4 LDA $E4EA,X |
LDA BAUDOP-2,X |
Baud-Rate, LOW |
get the PAL baud rate value low byte |
|||
.,F440 8C 96 02 STY $0296 |
OPN027 STY M51AJB+1 ;HOLD START RATE IN M51AJB |
HIGH-Byte speichern |
save the nonstandard bit timing high byte |
|||
.,F443 8D 95 02 STA $0295 |
STA M51AJB |
LOW-Byte speichern |
save the nonstandard bit timing low byte |
|||
.,F446 AD 95 02 LDA $0295 |
OPN028 LDA M51AJB ;CALCULATE BAUD RATE |
Timerwert = Baud-Rate * zwei + $C8 (200) |
get the nonstandard bit timing low byte |
|||
.,F449 0A ASL |
ASL |
Timer LOW * zwei |
* 2 |
|||
.,F44A 20 2E FF JSR $FF2E |
JSR POPEN ;GOTO PATCH AREA ; ; CHECK FOR 3/X LINE RESPONSE ; |
Timerwert für Baud-Rate ermitteln |
||||
.,F44D AD 94 02 LDA $0294 |
OPN030 LDA M51CDR ;BIT 0 OF M51CDR |
Kommandoregister laden |
read the pseudo 6551 command register |
|||
.,F450 4A LSR |
LSR A |
Prüfe ob 3-Line-Handshake |
shift the X line/3 line bit into Cb |
|||
.,F451 90 09 BCC $F45C |
BCC OPN050 ;...3 LINE ; ; CHECK FOR X LINE PROPER STATES ; |
verzweige wenn ja |
if 3 line skip the DRS test |
|||
.,F453 AD 01 DD LDA $DD01 |
LDA D2PRB |
Prüfe ob Data Set Ready |
read VIA 2 DRB, RS232 port |
|||
.,F456 0A ASL |
ASL A |
Bit 7 ins Carry |
shift DSR in into Cb |
|||
.,F457 B0 03 BCS $F45C |
BCS OPN050 |
verzweige wenn DSR vorhanden |
if DSR present skip the error set |
|||
.,F459 20 0D F0 JSR $F00D |
JMP CKDSRX ;NO DATA SET...DSR ERROR EXIT ; ; SET UP BUFFER POINTERS (DBE=DBS) ; |
Status für DSR setzen |
set no DSR |
|||
.,F45C AD 9B 02 LDA $029B |
OPN050 LDA RIDBE |
Anfang RS-232 Eingabepuffer |
get index to Rx buffer end |
|||
.,F45F 8D 9C 02 STA $029C |
STA RIDBS |
mit Ende des Eingabepuffers gleichsetzen |
set index to Rx buffer start, clear Rx buffer |
|||
.,F462 AD 9E 02 LDA $029E |
LDA RODBE |
Anfang des RS-232 Ausgabepuffers |
get index to Tx buffer end |
|||
.,F465 8D 9D 02 STA $029D |
STA RODBS ; ; ALLOCATE BUFFERS ; |
mit Ende des Ausgabepuffers gleichsetzen |
set index to Tx buffer start, clear Tx buffer |
|||
.,F468 20 27 FE JSR $FE27 |
OPN055 JSR GETTOP ;GET MEMSIZ |
Memory Top holen |
read the top of memory |
|||
.,F46B A5 F8 LDA $F8 |
LDA RIBUF+1 ;IN ALLOCATION... |
HIGH-Byte des Zeigers auf RS-232 Eingabepuffer |
get the RS232 input buffer pointer high byte |
|||
.,F46D D0 05 BNE $F474 |
BNE OPN060 ;ALREADY |
ungleich Null, so Eingabe- puffer bereits angelegt |
if buffer already set skip the save |
|||
.,F46F 88 DEY |
DEY ;THERE GOES 256 BYTES |
HIGH-Byte Memory Top -1 |
decrement top of memory high byte, 256 byte buffer |
|||
.,F470 84 F8 STY $F8 |
STY RIBUF+1 |
als Zeiger für RS-232 Eingabepuffer speichern |
save the RS232 input buffer pointer high byte |
|||
.,F472 86 F7 STX $F7 |
STX RIBUF |
LOW-Byte Memory Top als LOW- Byte Eingabepuffer setzen |
save the RS232 input buffer pointer low byte |
|||
.,F474 A5 FA LDA $FA |
OPN060 LDA ROBUF+1 ;OUT ALLOCATION... |
HIGH-Byte des Zeigers auf RS-232 Ausgabepuffer |
get the RS232 output buffer pointer high byte |
|||
.,F476 D0 05 BNE $F47D |
BNE MEMTCF ;ALREAY |
verzweige wenn Ausgabepuffer bereits angelegt |
if ?? go set the top of memory to F0xx |
|||
.,F478 88 DEY |
DEY ;THERE GOES 256 BYTES |
HIGH-Byte des Memory Top -1 |
||||
.,F479 84 FA STY $FA |
STY ROBUF+1 |
und als Zeiger für RS-232 Ausgabepuffer setzen |
save the RS232 output buffer pointer high byte |
|||
.,F47B 86 F9 STX $F9 |
STX ROBUF |
LOW-Byte Memory Top als LOW- Byte Ausgabepuffer setzen |
save the RS232 output buffer pointer low byteset the top of memory to F0xx |
|||
.,F47D 38 SEC |
MEMTCF SEC ;SIGNAL TOP OF MEMORY CHANGE |
Carry =1 (Fehlerkennzeichen) |
read the top of memory |
|||
.,F47E A9 F0 LDA #$F0 |
LDA #$F0 |
Ftag für Puffer schützen/ freigeben setzen |
set $F000 |
|||
.,F480 4C 2D FE JMP $FE2D |
JMP SETTOP ;TOP CHANGED ; ; CLN232 - CLEAN UP 232 SYSTEM FOR OPEN/CLOSE ; SET UP DDRB AND CB2 FOR RS-232 ; |
Memory-Top neu setzenCIAs nach RS 232 rücksetzen |
set the top of memory and returninitialise RS232 output |
initialise CIA2 |
||
.,F483 A9 7F LDA #$7F |
CLN232 LDA #$7F ;CLEAR NMI'S |
Bitwert für alle |
disable all interrupts |
|||
.,F485 8D 0D DD STA $DD0D |
STA D2ICR |
NMIs blockieren setzen |
save VIA 2 ICR |
|||
.,F488 A9 06 LDA #$06 |
LDA #%00000110 ;DDRB |
Bit 1 und 2 Ausgang |
set RS232 DTR output, RS232 RTS output |
|||
.,F48A 8D 03 DD STA $DD03 |
STA D2DDRB |
PORT B Richtung |
save VIA 2 DDRB, RS232 port |
|||
.,F48D 8D 01 DD STA $DD01 |
STA D2PRB ;DTR,RTS HIGH |
PORT A Richtung |
save VIA 2 DRB, RS232 port |
|||
.,F490 A9 04 LDA #$04 |
LDA #$04 ;OUTPUT HIGH PA2 |
Bit 2 setzen |
mask xxxx x1xx, set RS232 Tx DATA high |
|||
.,F492 0D 00 DD ORA $DD00 |
ORA D2PRA |
Bit 2 = TXD |
OR it with VIA 2 DRA, serial port and video address |
|||
.,F495 8D 00 DD STA $DD00 |
STA D2PRA |
Ausgeben |
save VIA 2 DRA, serial port and video address |
|||
.,F498 A0 00 LDY #$00 |
LDY #00 |
RS-232 |
clear Y |
|||
.,F49A 8C A1 02 STY $02A1 |
STY ENABL ;CLEAR ENABLS |
NMI-Flag löschen |
clear the RS-232 interrupt enable byte |
|||
.,F49D 60 RTS |
RTS .END .LIB LOAD;**********************************;* LOAD RAM FUNCTION * ;* * ;* LOADS FROM CASSETTE 1 OR 2, OR * ;* SERIAL BUS DEVICES >=4 TO 31 * ;* AS DETERMINED BY CONTENTS OF * ;* VARIABLE FA. VERIFY FLAG IN .A * ;* * ;* ALT LOAD IF SA=0, NORMAL SA=1 * ;* .X , .Y LOAD ADDRESS IF SA=0 * ;* .A=0 PERFORMS LOAD,<> IS VERIFY* ;* * ;* HIGH LOAD RETURN IN X,Y. * ;* * ;********************************** |
RücksprungLOAD - Routine |
load RAM from a device |
LOAD: LOAD RAMThe kernal routine LOAD ($ffd5) is vectoed here. If arelocated load is desired, then the start address is set in MEMUSS. The load/verify flag is set, and the I/O status word is reset. A test is done on the device number, less than 3 results in illegal device number. |
load ram from a device |
|
.,F49E 86 C3 STX $C3 |
LOADSP STX MEMUSS ;.X HAS LOW ALT START |
Startadresse |
set kernal setup pointer low byte |
MEMUSS, relocated load address |
||
.,F4A0 84 C4 STY $C4 |
STY MEMUSS+1 |
speichern |
set kernal setup pointer high byte |
|||
.,F4A2 6C 30 03 JMP ($0330) |
LOAD JMP (ILOAD) ;MONITOR LOAD ENTRY ; |
JMP $F4A5 LOAD-Vektor |
do LOAD vector, usually points to $F4A5load |
ILOAD vector. Points to $f4a5 |
normally F4A5standard load ram entry |
|
.,F4A5 85 93 STA $93 |
NLOAD STA VERCK ;STORE VERIFY FLAG |
Load/Verify Flag |
save load/verify flag |
VRECK, load/verify flag |
||
.,F4A7 A9 00 LDA #$00 |
LDA #0 |
Status |
clear A |
|||
.,F4A9 85 90 STA $90 |
STA STATUS ; |
löschen |
clear the serial status byte |
clear STATUS, I/O status |
||
.,F4AB A5 BA LDA $BA |
LDA FA ;CHECK DEVICE NUMBER |
Geräteadresse laden |
get the device number |
get FA, current device |
||
.,F4AD D0 03 BNE $F4B2 |
BNE LD20 ; |
ungleich Null, dann weiter |
if not the keyboard continue do 'illegal device number' |
keyboard |
||
.,F4AF 4C 13 F7 JMP $F713 |
LD10 JMP ERROR9 ;BAD DEVICE #-KEYBOARD ; |
'ILLEGAL DEVICE NUMBER' |
else do 'illegal device number' and return |
I/O error #9, illegal device |
||
.,F4B2 C9 03 CMP #$03 |
LD20 CMP #3 |
vergleiche mit Code für Bildschirm |
screen? |
|||
.,F4B4 F0 F9 BEQ $F4AF |
BEQ LD10 ;DISALLOW SCREEN LOAD |
verzweige wenn ja, Fehler |
yes, illegal deviceLOAD FROM SERIAL BUSThe message 'SEARCHING' is printed and the filename issent with the TALK command and secondary address to the serial bus. If EOI occurs at this point, then ?FILE NOT FOUND is displayed. The message 'LOADING' or 'VERIFYING' is output and a loop is entered, which recieves a byte from the serial bus, checks the <STOP> key and either stores the received byte, or compares it to the memory, depending on the state of VERCK. Finally the bus is UNTALKed. |
|||
.,F4B6 90 7B BCC $F533 |
BCC LD100 ;HANDLE TAPES DIFFERENT ; ;LOAD FROM CBM IEEE DEVICE ; |
kleiner 3, dann vom BandIEC-Load |
device < 3, eg tape or RS232, illegal device |
|||
.,F4B8 A4 B7 LDY $B7 |
LDY FNLEN ;MUST HAVE FILE NAME |
Länge des Filenamens laden |
get file name length |
FNLEN, length of filename |
||
.,F4BA D0 03 BNE $F4BF |
BNE LD25 ;YES...OK ; |
ungleich Null, dann ok |
if not null name go ?? |
if length not is zero |
||
.,F4BC 4C 10 F7 JMP $F710 |
JMP ERROR8 ;MISSING FILE NAME ; |
'MISSING FILENAME' |
else do 'missing file name' error and return |
'MISSING FILENAME' |
||
.,F4BF A6 B9 LDX $B9 |
LD25 LDX SA ;SAVE SA IN .X |
Sekundäradresse laden |
get the secondary address |
SA, current secondary address |
||
.,F4C1 20 AF F5 JSR $F5AF |
JSR LUKING ;TELL USER LOOKING |
'SEARCHING FOR' (filename) |
print "Searching..." |
print "SEARCHING" |
||
.,F4C4 A9 60 LDA #$60 |
LDA #$60 ;SPECIAL LOAD COMMAND |
Sekundäradresse Null laden (für OPEN) |
||||
.,F4C6 85 B9 STA $B9 |
STA SA |
und speichern |
save the secondary address |
set SA to $60 |
||
.,F4C8 20 D5 F3 JSR $F3D5 |
JSR OPENI ;OPEN THE FILE ; |
File auf IEC-Bus eröffnen |
send secondary address and filename |
send SA and filename |
||
.,F4CB A5 BA LDA $BA |
LDA FA |
Gerätenummer laden |
get the device number |
FA, current devicenumber |
||
.,F4CD 20 09 ED JSR $ED09 |
JSR TALK ;ESTABLISH THE CHANNEL |
und TALK senden |
command serial bus device to TALK |
send TALK to serial bus |
||
.,F4D0 A5 B9 LDA $B9 |
LDA SA |
Sekundäradresse laden |
get the secondary address |
SA |
||
.,F4D2 20 C7 ED JSR $EDC7 |
JSR TKSA ;TELL IT TO LOAD ; |
und senden |
send secondary address after TALK |
send TALK SA |
||
.,F4D5 20 13 EE JSR $EE13 |
JSR ACPTR ;GET FIRST BYTE |
Byte vom IEC-Bus holen |
input byte from serial bus |
receive from serial bus |
||
.,F4D8 85 AE STA $AE |
STA EAL ; |
als Startadresse LOW spei chern |
save program start address low byte |
load address, <EAL |
||
.,F4DA A5 90 LDA $90 |
LDA STATUS ;TEST STATUS FOR ERROR |
Status laden |
get the serial status byte |
check STATUS |
||
.,F4DC 4A LSR |
LSR A |
Bit 1 |
shift time out read .. |
|||
.,F4DD 4A LSR |
LSR A |
ins Carry schieben |
.. into carry bit |
|||
.,F4DE B0 50 BCS $F530 |
BCS LD90 ;FILE NOT FOUND... |
falls gesetzt, dann Time out (Fehler) |
if timed out go do file not found error and return |
EOI set, file not found |
||
.,F4E0 20 13 EE JSR $EE13 |
JSR ACPTR |
Startadresse HIGH holen |
input byte from serial bus |
recieve from serial bus |
||
.,F4E3 85 AF STA $AF |
STA EAH ; |
und speichern |
save program start address high byte |
load address, >EAL |
||
.,F4E5 8A TXA |
TXA ;FIND OUT OLD SA |
Sekundäradresse laden |
copy secondary address |
retrieve SA and test relocated load |
||
.,F4E6 D0 08 BNE $F4F0 |
BNE LD30 ;SA<>0 USE DISK ADDRESS |
verzweige falls ungleich Null |
load location not set in LOAD call, so continue with the load |
|||
.,F4E8 A5 C3 LDA $C3 |
LDA MEMUSS ;ELSE LOAD WHERE USER WANTS |
Startadresse LOW laden |
get the load address low byte |
use MEMUSS as load address |
||
.,F4EA 85 AE STA $AE |
STA EAL |
und speichern |
save the program start address low byte |
store in <EAL |
||
.,F4EC A5 C4 LDA $C4 |
LDA MEMUSS+1 |
Startadresse HIGH laden |
get the load address high byte |
|||
.,F4EE 85 AF STA $AF |
STA EAH |
und speichern |
save the program start address high byte |
store in >EAL |
||
.,F4F0 20 D2 F5 JSR $F5D2 |
LD30 JSR LODING ;TELL USER LOADING ; |
'LOADING'/'VERIFYING' ausgeben |
||||
.,F4F3 A9 FD LDA #$FD |
LD40 LDA #$FD ;MASK OFF TIMEOUT |
Time-out |
mask xxxx xx0x, clear time out read bit |
mask %11111101 |
||
.,F4F5 25 90 AND $90 |
AND STATUS |
Bit |
mask the serial status byte |
read ST |
||
.,F4F7 85 90 STA $90 |
STA STATUS ; |
löschen |
set the serial status byte |
|||
.,F4F9 20 E1 FF JSR $FFE1 |
JSR STOP ;STOP KEY? |
Stop-Taste abfragen |
scan stop key, return Zb = 1 = [STOP] |
scan <STOP> |
||
.,F4FC D0 03 BNE $F501 |
BNE LD45 ;NO... ; |
nicht gedrückt, dann weiter |
if not [STOP] go ?? |
not stopped |
||
.,F4FE 4C 33 F6 JMP $F633 |
JMP BREAK ;STOP KEY PRESSED ; |
File schließen |
else close the serial bus device and flag stop |
|||
.,F501 20 13 EE JSR $EE13 |
LD45 JSR ACPTR ;GET BYTE OFF IEEE |
Programmbyte vom Bus holen |
input byte from serial bus |
CPTR, recrive from serial bus |
||
.,F504 AA TAX |
TAX |
Akku in X-REG retten |
copy byte |
|||
.,F505 A5 90 LDA $90 |
LDA STATUS ;WAS THERE A TIMEOUT? |
Status testen |
get the serial status byte |
|||
.,F507 4A LSR |
LSR A |
Time-out |
shift time out read .. |
|||
.,F508 4A LSR |
LSR A |
Bit ins Carry schieben |
.. into carry bit |
|||
.,F509 B0 E8 BCS $F4F3 |
BCS LD40 ;YES...TRY AGAIN |
falls Fehler, dann abbrechen |
if timed out go try again |
|||
.,F50B 8A TXA |
TXA |
ansonsten Akku wiederholen |
copy received byte back |
|||
.,F50C A4 93 LDY $93 |
LDY VERCK ;PERFORMING VERIFY? |
Load/Verify Flag testen |
get load/verify flag |
|||
.,F50E F0 0C BEQ $F51C |
BEQ LD50 ;NO...LOAD |
gleich Null, dann LOAD |
if load go load else is verify |
jump to LOAD |
||
.,F510 A0 00 LDY #$00 |
LDY #0 |
Zähler auf Null setzen |
clear index |
|||
.,F512 D1 AE CMP ($AE),Y |
CMP (EAL)Y ;VERIFY IT |
Verify, Vergleich |
compare byte with previously loaded byte |
compare with memory |
||
.,F514 F0 08 BEQ $F51E |
BEQ LD60 ;O.K.... |
verzweige falls gleich |
if match go ?? |
veryfied byte OK |
||
.,F516 A9 10 LDA #$10 |
LDA #SPERR ;NO GOOD...VERIFY ERROR |
Bit 4 für Status setzen |
flag read error |
|||
.,F518 20 1C FE JSR $FE1C |
JSR UDST ;UPDATE STATUS |
Status setzen |
OR into the serial status byte |
|||
.:F51B 2C .BYTE $2C |
.BYT $2C ;SKIP NEXT STORE ; |
Skip nach $F51E |
makes next line BIT $AE91 |
mask next write command |
||
.,F51C 91 AE STA ($AE),Y |
LD50 STA (EAL)Y |
Byte abspeichern |
save byte to memory |
store in memory |
||
.,F51E E6 AE INC $AE |
LD60 INC EAL ;INCREMENT STORE ADDR |
LOW-Byte der Adresse erhöhen |
increment save pointer low byte |
increment <EAL, next address |
||
.,F520 D0 02 BNE $F524 |
BNE LD64 |
verzweige falls kein Übertrag |
if no rollover go ?? |
skip MSB |
||
.,F522 E6 AF INC $AF |
INC EAH |
ansonsten HIGH-Byte erhöhen |
else increment save pointer high byte |
increment >EAL |
||
.,F524 24 90 BIT $90 |
LD64 BIT STATUS ;EOI? |
Status prüfen |
test the serial status byte |
test STATUS |
||
.,F526 50 CB BVC $F4F3 |
BVC LD40 ;NO...CONTINUE LOAD ; |
verzweige wenn noch kein EOI |
loop if not end of file close file and exit |
get next byte |
||
.,F528 20 EF ED JSR $EDEF |
JSR UNTLK ;CLOSE CHANNEL |
UNTALK senden |
command serial bus to UNTALK |
send UNTALK to serial bus |
||
.,F52B 20 42 F6 JSR $F642 |
JSR CLSEI ;CLOSE THE FILE |
File schließen |
close serial bus device |
|||
.,F52E 90 79 BCC $F5A9 |
BCC LD180 ;BRANCH ALWAYS ; |
vezweige wenn kein Fehler |
if ?? go flag ok and exit |
end routine |
||
.,F530 4C 04 F7 JMP $F704 |
LD90 JMP ERROR4 ;FILE NOT FOUND ; ;LOAD FROM TAPE ; |
'FILE NOT FOUND' |
do file not found error and return?? |
I/O error #4, file not found |
||
.,F533 4A LSR |
LD100 LSR A |
Gerätenummer feststellen |
||||
.,F534 B0 03 BCS $F539 |
BCS LD102 ;IF C-SET THEN IT'S CASSETTE ; |
eins (Band) , dann weiter |
||||
.,F536 4C 13 F7 JMP $F713 |
JMP ERROR9 ;BAD DEVICE # ; |
RS 232, 'ILLEGAL DEVICE NUMBER' |
else do 'illegal device number' and return |
|||
.,F539 20 D0 F7 JSR $F7D0 |
LD102 JSR ZZZ ;SET POINTERS AT TAPE |
Bandpuffer Startadresse holen |
get tape buffer start pointer in XY |
|||
.,F53C B0 03 BCS $F541 |
BCS LD104 |
verzweige wenn HIGH-Byte der Bandpufferstartadresse größer/ gleich 2 |
if ?? |
|||
.,F53E 4C 13 F7 JMP $F713 |
JMP ERROR9 ;DEALLOCATED... |
sonst 'ILLEGAL DEVICE NUMBER' |
else do 'illegal device number' and return |
|||
.,F541 20 17 F8 JSR $F817 |
LD104 JSR CSTE1 ;TELL USER ABOUT BUTTONS |
wartet auf Play-Taste |
wait for PLAY |
|||
.,F544 B0 68 BCS $F5AE |
BCS LD190 ;STOP KEY PRESSED? |
STOP-Taste, dann Abbruch |
exit if STOP was pressed |
|||
.,F546 20 AF F5 JSR $F5AF |
JSR LUKING ;TELL USER SEARCHING ; |
'SEARCHING' ('for name') ausgeben |
print "Searching..." |
|||
.,F549 A5 B7 LDA $B7 |
LD112 LDA FNLEN ;IS THERE A NAME? |
Länge des Filenamens laden |
get file name length |
|||
.,F54B F0 09 BEQ $F556 |
BEQ LD150 ;NONE...LOAD ANYTHING |
verzweige wenn Null |
||||
.,F54D 20 EA F7 JSR $F7EA |
JSR FAF ;FIND A FILE ON TAPE |
gewünschten Bandheader suchen |
find specific tape header |
|||
.,F550 90 0B BCC $F55D |
BCC LD170 ;GOT IT! |
verzweige wenn gefunden |
if no error continue |
|||
.,F552 F0 5A BEQ $F5AE |
BEQ LD190 ;STOP KEY PRESSED |
STOP-Taste, dann Abbruch |
exit if ?? |
|||
.,F554 B0 DA BCS $F530 |
BCS LD90 ;NOPE...END OF TAPE ; |
EOT, dann 'FILE NOT FOUND' |
, branch always |
|||
.,F556 20 2C F7 JSR $F72C |
LD150 JSR FAH ;FIND ANY HEADER |
nächsten Bandheader suchen |
find tape header, exit with header in buffer |
|||
.,F559 F0 53 BEQ $F5AE |
BEQ LD190 ;STOP KEY PRESSED |
STOP-Taste, dann Abbruch |
exit if ?? |
|||
.,F55B B0 D3 BCS $F530 |
BCS LD90 ;NO HEADER ; |
'EOT', dann 'FILE NOT FOUND' |
||||
.,F55D A5 90 LDA $90 |
LD170 LDA STATUS |
Status holen |
get the serial status byte |
|||
.,F55F 29 10 AND #$10 |
AND #SPERR ;MUST GOT HEADER RIGHT |
EOF-Bit ausblenden |
mask 000x 0000, read error |
|||
.,F561 38 SEC |
SEC |
Carry =1 (Fehlerkennzeichen) |
flag fail |
|||
.,F562 D0 4A BNE $F5AE |
BNE LD190 ;IS BAD ; |
verzweige falls Fehler |
if read error just exit |
|||
.,F564 E0 01 CPX #$01 |
CPX #BLF ;IS IT A MOVABLE PROGRAM... |
Header-Typ 1 = BASIC- Programm (verschiebbar) |
||||
.,F566 F0 11 BEQ $F579 |
BEQ LD178 ;YES ; |
verzweige wenn Header-Typ =1 |
||||
.,F568 E0 03 CPX #$03 |
CPX #PLF ;IS IT A PROGRAM |
3 = Maschinen-Programm (absolut) |
||||
.,F56A D0 DD BNE $F549 |
BNE LD112 ;NO...ITS SOMETHING ELSE ; |
verzweige wenn nicht 3 (falscher Header) |
||||
.,F56C A0 01 LDY #$01 |
LD177 LDY #1 ;FIXED LOAD... |
Zeiger setzen |
||||
.,F56E B1 B2 LDA ($B2),Y |
LDA (TAPE1)Y ;...THE ADDRESS IN THE... |
LOW-Byte Startadresse holen |
||||
.,F570 85 C3 STA $C3 |
STA MEMUSS ;...BUFFER IS THE START ADDRESS |
und speichern |
||||
.,F572 C8 INY |
INY |
Zeiger erhöhen |
||||
.,F573 B1 B2 LDA ($B2),Y |
LDA (TAPE1)Y |
HIGH-Byte Startadresse holen |
||||
.,F575 85 C4 STA $C4 |
STA MEMUSS+1 |
und speichern |
||||
.,F577 B0 04 BCS $F57D |
BCS LD179 ;JMP ..CARRY SET BY CPX'S ; |
unbedingter Sprung |
||||
.,F579 A5 B9 LDA $B9 |
LD178 LDA SA ;CHECK FOR MONITOR LOAD... |
Sekundär-Adresse |
get the secondary address |
|||
.,F57B D0 EF BNE $F56C |
BNE LD177 ;...YES WE WANT FIXED TYPE ; |
ungleich Null, dann nicht verschiebbar laden |
||||
.,F57D A0 03 LDY #$03 |
LD179 LDY #3 ;TAPEA - TAPESTA ;CARRY SET BY CPX'S |
Zeiger setzen |
||||
.,F57F B1 B2 LDA ($B2),Y |
LDA (TAPE1)Y |
LOW-Byte der Endadresse+1 des Programms holen |
||||
.,F581 A0 01 LDY #$01 |
LDY #1 |
Zeiger auf LOW-Byte Anfangs adresse setzen |
||||
.,F583 F1 B2 SBC ($B2),Y |
SBC (TAPE1)Y |
von Endadresse subtrahieren |
||||
.,F585 AA TAX |
TAX ;LOW TO .X |
Ergebnis ins X-REG schieben |
||||
.,F586 A0 04 LDY #$04 |
LDY #4 |
Zeiger auf HIGH-Byte der Endadresse setzen |
||||
.,F588 B1 B2 LDA ($B2),Y |
LDA (TAPE1)Y |
Endadresse holen |
||||
.,F58A A0 02 LDY #$02 |
LDY #2 |
Zeiger auf Startadresse setzen |
||||
.,F58C F1 B2 SBC ($B2),Y |
SBC (TAPE1)Y |
und von Endadresse subtrahie ren |
||||
.,F58E A8 TAY |
TAY ;HIGH TO .Y ; |
Ergebnis ins Y-REG schieben |
||||
.,F58F 18 CLC |
CLC ;EA = STA+(TAPEA-TAPESTA) |
Carry für Addition löschen |
||||
.,F590 8A TXA |
TXA |
LOW-Byte der Programmlänge in Akku schieben |
||||
.,F591 65 C3 ADC $C3 |
ADC MEMUSS ; |
mit LOW-Byte der Anfangs adresse addieren |
||||
.,F593 85 AE STA $AE |
STA EAL |
als LOW-Byte der Endadresse speichern |
||||
.,F595 98 TYA |
TYA |
HIGH-Byte der Programmlänge in Akku schieben |
||||
.,F596 65 C4 ADC $C4 |
ADC MEMUSS+1 |
mit HIGH-Byte Anfangsadresse addieren |
||||
.,F598 85 AF STA $AF |
STA EAH |
als HIGH-Byte Endadresse speichern |
||||
.,F59A A5 C3 LDA $C3 |
LDA MEMUSS ;SET UP STARTING ADDRESS |
Startadresse |
||||
.,F59C 85 C1 STA $C1 |
STA STAL |
nach $C1 |
set I/O start addresses low byte |
|||
.,F59E A5 C4 LDA $C4 |
LDA MEMUSS+1 |
und $C2 |
||||
.,F5A0 85 C2 STA $C2 |
STA STAH |
bringen |
set I/O start addresses high byte |
|||
.,F5A2 20 D2 F5 JSR $F5D2 |
JSR LODING ;TELL USER LOADING |
'LOADING' / 'VERIFYING' ausgeben |
display "LOADING" or "VERIFYING" |
|||
.,F5A5 20 4A F8 JSR $F84A |
JSR TRD ;DO TAPE BLOCK LOAD |
Programm vom Band laden |
do the tape read |
|||
.:F5A8 24 .BYTE $24 |
.BYT $24 ;CARRY FROM TRD ; |
Skip nach $F5AA |
makes next line BIT $18, keep the error flag in Cb |
LOAD ENDThis is the last part of the loader routine which sets the(X/Y) register with the endaddress of the loaded program, clears carry and exit. |
||
.,F5A9 18 CLC |
LD180 CLC ;GOOD EXIT ; ; SET UP END LOAD ADDRESS ; |
Carry =0 (ok Kennzeichen) |
flag ok |
|||
.,F5AA A6 AE LDX $AE |
LDX EAL |
Endadresse |
get the LOAD end pointer low byte |
|||
.,F5AC A4 AF LDY $AF |
LDY EAH ; |
nach X/Y |
get the LOAD end pointer high byte |
|||
.,F5AE 60 RTS |
LD190 RTS ;SUBROUTINE TO PRINT TO CONSOLE: ; ;SEARCHING [FOR NAME] ; |
Rücksprung'SEARCHING FOR' (Filename)ausgeben |
print "Searching..." |
PRINT "SEARCHING"If MSGFLG indicates program mode then the message is notprinted, otherwise the message "SEARCHING" is printed from the KERNAL I/O message table. If the length of filename >0 then the message "FOR" is printed, and the routine drops through to print the filename. |
handle messages for loading |
|
.,F5AF A5 9D LDA $9D |
LUKING LDA MSGFLG ;SUPPOSED TO PRINT? |
Direkt-Modus-Flag laden |
get message mode flag |
MSGFLG, direct or program mode? |
||
.,F5B1 10 1E BPL $F5D1 |
BPL LD115 ;...NO |
verzweige wenn Bit 7 =0 (Programm-Mode) |
exit if control messages off |
program mode, don´t print, exit |
||
.,F5B3 A0 0C LDY #$0C |
LDY #MS5-MS1 ;"SEARCHING" |
Offset für 'SEARCHING' |
index to "SEARCHING " |
|||
.,F5B5 20 2F F1 JSR $F12F |
JSR MSG |
Meldung ausgeben |
display kernel I/O message |
print "SEARCHING" |
||
.,F5B8 A5 B7 LDA $B7 |
LDA FNLEN |
Länge des Filenamens |
get file name length |
FNLEN, length of current filename |
||
.,F5BA F0 15 BEQ $F5D1 |
BEQ LD115 |
gleich Null, dann fertig |
exit if null name |
no name, exit |
||
.,F5BC A0 17 LDY #$17 |
LDY #MS6-MS1 ;"FOR" |
Offset für 'FOR' |
else index to "FOR " |
|||
.,F5BE 20 2F F1 JSR $F12F |
JSR MSG ;SUBROUTINE TO OUTPUT FILE NAME ; |
Meldung ausgeben |
display kernel I/O messageprint file name |
print "FOR"PRINT FILENAMEFilename is pointed to by FNADR, and length in FNLEN. TheKERNAL routine CHROUT is used to print filename. |
||
.,F5C1 A4 B7 LDY $B7 |
OUTFN LDY FNLEN ;IS THERE A NAME? |
Länge des Filenamens |
get file name length |
FNLEN, length of current filename |
||
.,F5C3 F0 0C BEQ $F5D1 |
BEQ LD115 ;NO...DONE |
gleich Null, dann fertig |
exit if null file name |
exit |
||
.,F5C5 A0 00 LDY #$00 |
LDY #0 |
Zähler setzen |
clear index |
|||
.,F5C7 B1 BB LDA ($BB),Y |
LD110 LDA (FNADR)Y |
Filenamen holen |
get file name byte |
get character in filename |
||
.,F5C9 20 D2 FF JSR $FFD2 |
JSR BSOUT |
und ausgeben |
output character to channel |
output |
||
.,F5CC C8 INY |
INY |
Zähler erhöhen |
increment index |
next character |
||
.,F5CD C4 B7 CPY $B7 |
CPY FNLEN |
mit Länge des Filenamens ver- gleichen |
compare with file name length |
ready? |
||
.,F5CF D0 F6 BNE $F5C7 |
BNE LD110 ; |
verzweige wenn noch nicht alle Buchstaben |
loop if more to do |
|||
.,F5D1 60 RTS |
LD115 RTS ;SUBROUTINE TO PRINT: ; ;LOADING/VERIFING ; |
Rücksprung'LOADING/VERIFYING' ausgeben |
display "LOADING" or "VERIFYING" |
backPRINT "LOADING/VERIFYING"The load/verify flag is checked, and if the message to beoutput is flagged according to the result. This message is printed from the KERNAL I/O messages table. |
do load/verify message |
|
.,F5D2 A0 49 LDY #$49 |
LODING LDY #MS10-MS1 ;ASSUME 'LOADING' |
Offset für 'LOADING' |
point to "LOADING" |
offset to verify message |
||
.,F5D4 A5 93 LDA $93 |
LDA VERCK ;CHECK FLAG |
Load/Verify-Flag laden |
get load/verify flag |
VERCK, load/verify flag |
||
.,F5D6 F0 02 BEQ $F5DA |
BEQ LD410 ;ARE DOING LOAD |
Load wenn 0, dann ausgeben |
branch if load |
verify |
||
.,F5D8 A0 59 LDY #$59 |
LDY #MS21-MS1 ;ARE 'VERIFYING' |
sonst Offset für 'VERIFYING' |
point to "VERIFYING" |
offset to load message |
||
.,F5DA 4C 2B F1 JMP $F12B |
LD410 JMP SPMSG .END .LIB SAVE;***********************************;* SAVE * ;* * ;* SAVES TO CASSETTE 1 OR 2, OR * ;* IEEE DEVICES 4>=N>=31 AS SELECT-* ;* ED BY VARIABLE FA. * ;* * ;*START OF SAVE IS INDIRECT AT .A * ;*END OF SAVE IS .X,.Y * ;*********************************** |
Meldung ausgeben, RücksprungSAVE - Routine |
display kernel I/O message if in direct mode and returnsave RAM to device, A = index to start address, XY = end address low/high |
output message flagged by (Y)SAVE: SAVE RAMThe KERNAL routine SAVE ($ffd8) jumps to this routine. Onentry, (X/Y) must hold the end address+1 of the area of memory to be saved. (A) holds the pointer to the start address of the block, held in zeropage. The current device number is checked to ensure that it is niether keyboard (0) or screen (3). Both of these result in ?ILLEGAL DEVICE NUMBER. |
save ram to a device |
|
.,F5DD 86 AE STX $AE |
SAVESP STX EAL |
LOW-Byte der Endadresse speichern |
save end address low byte |
EAL , end address of block +1 |
||
.,F5DF 84 AF STY $AF |
STY EAH |
High-Byte der Endadresse speichern |
save end address high byte |
|||
.,F5E1 AA TAX |
TAX ;SET UP START |
Zeiger auf Anfangsadress- tabelle ins X-REG schieben |
copy index to start pointer |
move start pointer to (X) |
||
.,F5E2 B5 00 LDA $00,X |
LDA $00,X |
LOW-Byte der Startadresse |
get start address low byte |
|||
.,F5E4 85 C1 STA $C1 |
STA STAL |
holen und speichern |
set I/O start addresses low byte |
STAL, start address of block |
||
.,F5E6 B5 01 LDA $01,X |
LDA $01,X |
HIGH-Byte der Startadresse |
get start address high byte |
|||
.,F5E8 85 C2 STA $C2 |
STA STAH ; |
holen und speichern |
set I/O start addresses high byte |
|||
.,F5EA 6C 32 03 JMP ($0332) |
SAVE JMP (ISAVE) |
SAVE-Vektor, JMP $F5ED |
go save, usually points to $F685save |
vector ISAVE, points to $f5ed |
normally F5EDstandard save ram entry |
|
.,F5ED A5 BA LDA $BA |
NSAVE LDA FA ***MONITOR ENTRY |
Geräteadresse laden |
get the device number |
FA, current device number |
||
.,F5EF D0 03 BNE $F5F4 |
BNE SV20 ; |
verzweige wenn nicht gleich 0 |
if not keyboard go ?? else .. |
ok |
||
.,F5F1 4C 13 F7 JMP $F713 |
SV10 JMP ERROR9 ;BAD DEVICE # ; |
sonst 'ILLEGAL DEVICE NUMBER' |
else do 'illegal device number' and return |
I/O error #9, illegal device number |
||
.,F5F4 C9 03 CMP #$03 |
SV20 CMP #3 |
mit Code für Bildschirm vergleichen |
compare device number with screen |
screen? |
||
.,F5F6 F0 F9 BEQ $F5F1 |
BEQ SV10 |
wenn Bildschirm, dann Fehler |
if screen do illegal device number and return |
yep, output error |
||
.,F5F8 90 5F BCC $F659 |
BCC SV100 |
kleiner 3, dann verzweigeSpeichern auf IEC-Bus |
branch if < screen is greater than screen so is serial bus |
less than 3, ie. tape, output errorSAVE TO SERIAL BUSA filename is assumed by the routine, or ?MISSING FILENAMEerror is called. The serial device is commanded to LISTEN, and the filename is sent along with the secondary address. The message 'SAVING' is printed, and a loop sends a byte to the serial bus and checks <STOP> key until the whole specifyed block of memory has been saved. Note that the first two bytes sent are the start address of the block. Finally the serial bus is UNLISTENed. |
||
.,F5FA A9 61 LDA #$61 |
LDA #$61 |
Sekundäradresse 1 |
set secondary address to $01 when a secondary address is to be sent to a device on the serial bus the address must first be ORed with $60 |
|||
.,F5FC 85 B9 STA $B9 |
STA SA |
setzen |
save the secondary address |
set SA, secondary address, to #1 |
||
.,F5FE A4 B7 LDY $B7 |
LDY FNLEN |
Länge des Filenamens laden |
get the file name length |
FNLEN, length of current filename |
||
.,F600 D0 03 BNE $F605 |
BNE SV25 ; |
ungleich Null, dann ok |
if filename not null continue |
ok |
||
.,F602 4C 10 F7 JMP $F710 |
JMP ERROR8 ;MISSING FILE NAME ; |
sonst 'MISSING FILENAME' |
else do 'missing file name' error and return |
I/O error #8, missing filename |
||
.,F605 20 D5 F3 JSR $F3D5 |
SV25 JSR OPENI |
Filenamen auf IEC-Bus |
send secondary address and filename |
send SA & filename |
||
.,F608 20 8F F6 JSR $F68F |
JSR SAVING |
'SAVING' ausgeben |
print saving <file name> |
print 'SAVING' and filename |
||
.,F60B A5 BA LDA $BA |
LDA FA |
Geräteadresse laden |
get the device number |
FA, current device number |
||
.,F60D 20 0C ED JSR $ED0C |
JSR LISTN |
und LISTEN senden |
command devices on the serial bus to LISTEN |
send LISTEN |
||
.,F610 A5 B9 LDA $B9 |
LDA SA |
Sekundäradresse laden |
get the secondary address |
SA |
||
.,F612 20 B9 ED JSR $EDB9 |
JSR SECND |
und für LISTEN senden |
send secondary address after LISTEN |
send LISTEN SA |
||
.,F615 A0 00 LDY #$00 |
LDY #0 |
Zähler auf Null setzen |
clear index |
|||
.,F617 20 8E FB JSR $FB8E |
JSR RD300 |
Startadresse nach $AC/$AD |
copy I/O start address to buffer address |
reset pointer |
||
.,F61A A5 AC LDA $AC |
LDA SAL |
Startadresse LOW- |
get buffer address low byte |
SAL, holds start address |
||
.,F61C 20 DD ED JSR $EDDD |
JSR CIOUT |
Byte senden |
output byte to serial bus |
send low byte of start address |
||
.,F61F A5 AD LDA $AD |
LDA SAH |
und HIGH- |
get buffer address high byte |
|||
.,F621 20 DD ED JSR $EDDD |
JSR CIOUT |
senden |
output byte to serial bus |
send high byte of start address |
||
.,F624 20 D1 FC JSR $FCD1 |
SV30 JSR CMPSTE ;COMPARE START TO END |
Endadresse schon erreicht ? |
check read/write pointer, return Cb = 1 if pointer >= end |
check read/write pointer |
||
.,F627 B0 16 BCS $F63F |
BCS SV50 ;HAVE REACHED END |
ja, dann fertig |
go do UNLISTEN if at end |
|||
.,F629 B1 AC LDA ($AC),Y |
LDA (SAL)Y |
Programmbyte laden |
get byte from buffer |
get character from memory |
||
.,F62B 20 DD ED JSR $EDDD |
JSR CIOUT |
auf IEC-Bus ausgeben |
output byte to serial bus |
send byte to serial device |
||
.,F62E 20 E1 FF JSR $FFE1 |
JSR STOP |
STOP-Taste abfragen |
scan stop key |
test <STOP> key |
||
.,F631 D0 07 BNE $F63A |
BNE SV40 ; |
nicht gedrückt, dann weitermachen |
if stop not pressed go increment pointer and loop for next else .. close the serial bus device and flag stop |
not pressed |
||
.,F633 20 42 F6 JSR $F642 |
BREAK JSR CLSEI |
IEC-Bus Kanal schließen |
close serial bus device |
exit and unlisten |
||
.,F636 A9 00 LDA #$00 |
LDA #0 |
Kennzeichnung für 'BREAK' |
flag break |
|||
.,F638 38 SEC |
SEC |
Carry =1 (Fehlerkennzeichen) |
flag stop |
|||
.,F639 60 RTS |
RTS ; |
Rücksprung |
||||
.,F63A 20 DB FC JSR $FCDB |
SV40 JSR INCSAL ;INCREMENT CURRENT ADDR. |
laufende Adresse erhöhen |
increment read/write pointer |
bump r/w pointer |
||
.,F63D D0 E5 BNE $F624 |
BNE SV30 |
unbedingter Sprung |
loop, branch always |
save next byte |
||
.,F63F 20 FE ED JSR $EDFE |
SV50 JSR UNLSN |
UNLISTEN sendenFile auf IEC-Bus schließen |
command serial bus to UNLISTEN close serial bus device |
send UNLISTEN |
close serial bus device |
|
.,F642 24 B9 BIT $B9 |
CLSEI BIT SA |
Sekundäradresse testen |
test the secondary address |
SA |
||
.,F644 30 11 BMI $F657 |
BMI CLSEI2 |
verzweige falls keine Sekundäradresse |
if already closed just exit |
|||
.,F646 A5 BA LDA $BA |
LDA FA |
Geräteadresse laden |
get the device number |
FA |
||
.,F648 20 0C ED JSR $ED0C |
JSR LISTN |
und LISTEN senden |
command devices on the serial bus to LISTEN |
send LISTEN |
||
.,F64B A5 B9 LDA $B9 |
LDA SA |
Sekundäradresse laden |
get the secondary address |
|||
.,F64D 29 EF AND #$EF |
AND #$EF |
Sekundäradresse |
mask the channel number |
|||
.,F64F 09 E0 ORA #$E0 |
ORA #$E0 |
für CLOSE berechnen |
OR with the CLOSE command |
|||
.,F651 20 B9 ED JSR $EDB9 |
JSR SECND ; |
und ausgeben |
send secondary address after LISTEN |
send UNLISTEN SA |
||
.,F654 20 FE ED JSR $EDFE |
CUNLSN JSR UNLSN ;ENTRY FOR OPENI ; |
UNLISTEN senden |
command serial bus to UNLISTEN |
send UNLISTEN |
||
.,F657 18 CLC |
CLSEI2 CLC |
Carry =0 (ok Kennzeichen) |
flag ok |
|||
.,F658 60 RTS |
RTS |
Rücksprung |
||||
.,F659 4A LSR |
SV100 LSR A |
Bit 0 ins Carry schieben |
||||
.,F65A B0 03 BCS $F65F |
BCS SV102 ;IF C-SET THEN IT'S CASSETTE ; |
falls gesetzt, dann zu Band |
if not RS232 device ?? |
|||
.,F65C 4C 13 F7 JMP $F713 |
JMP ERROR9 ;BAD DEVICE # ; |
sonst RS-232, 'ILLEGAL DIVICE NUMBER' |
else do 'illegal device number' and return |
save ram to cassette |
||
.,F65F 20 D0 F7 JSR $F7D0 |
SV102 JSR ZZZ ;GET ADDR OF TAPE |
Bandpuffer Startadresse holen |
get tape buffer start pointer in XY |
|||
.,F662 90 8D BCC $F5F1 |
BCC SV10 ;BUFFER IS DEALLOCATED |
falls HIGH-Byte der Band Pufferstartadresse kleiner 2 dann 'ILLEGAL DEVICE NUMBER' |
if < $0200 do illegal device number and return |
|||
.,F664 20 38 F8 JSR $F838 |
JSR CSTE2 |
wartet auf Record & Play- Taste |
wait for PLAY/RECORD |
|||
.,F667 B0 25 BCS $F68E |
BCS SV115 ;STOP KEY PRESSED |
STOP, dann Abbruch |
exit if STOP was pressed |
|||
.,F669 20 8F F6 JSR $F68F |
JSR SAVING ;TELL USER 'SAVING' |
'SAVING' (Name) ausgeben |
print saving <file name> |
|||
.,F66C A2 03 LDX #$03 |
SV105 LDX #PLF ;DECIDE TYPE TO SAVE |
Header-Typ 3 = Maschinen programm (absolut) |
set header for a non relocatable program file |
|||
.,F66E A5 B9 LDA $B9 |
LDA SA ;1-PLF 0-BLF |
Sekundäradresse laden |
get the secondary address |
|||
.,F670 29 01 AND #$01 |
AND #01 |
Bit 0 gesetzt (1 oder 3) |
mask non relocatable bit |
|||
.,F672 D0 02 BNE $F676 |
BNE SV106 |
falls ja, dann Maschinen programm |
if non relocatable program go ?? |
|||
.,F674 A2 01 LDX #$01 |
LDX #BLF |
Header-Typ 1 = BASIC- Programm (verschiebbar) |
else set header for a relocatable program file |
|||
.,F676 8A TXA |
SV106 TXA |
Header in Akku schieben |
copy header type to A |
|||
.,F677 20 6A F7 JSR $F76A |
JSR TAPEH |
Header auf Band schreiben |
write tape header |
|||
.,F67A B0 12 BCS $F68E |
BCS SV115 ;STOP KEY PRESSED |
Aussprung bei Stop-Taste |
exit if error |
|||
.,F67C 20 67 F8 JSR $F867 |
JSR TWRT |
Programm auf Band schreiben |
do tape write, 20 cycle count |
|||
.,F67F B0 0D BCS $F68E |
BCS SV115 ;STOP KEY PRESSED |
Aussprung bei Stop-Taste |
exit if error |
|||
.,F681 A5 B9 LDA $B9 |
LDA SA |
Sekundäradresse laden |
get the secondary address |
|||
.,F683 29 02 AND #$02 |
AND #2 ;WRITE END OF TAPE? |
Bit 1 gesetzt (2 oder 3) |
mask end of tape flag |
|||
.,F685 F0 06 BEQ $F68D |
BEQ SV110 ;NO... ; |
falls nicht, dann fertig |
if not end of tape go ?? |
|||
.,F687 A9 05 LDA #$05 |
LDA #EOT |
EOT Kontrollbyte |
else set logical end of the tape |
|||
.,F689 20 6A F7 JSR $F76A |
JSR TAPEH |
Block auf Band schreiben |
write tape header |
|||
.:F68C 24 .BYTE $24 |
.BYT $24 ;SKIP 1 BYTE ; |
Skip zu $F68E |
makes next line BIT $18 so Cb is not changed |
|||
.,F68D 18 CLC |
SV110 CLC |
Carry =0 (ok Kennzeichen) |
flag ok |
|||
.,F68E 60 RTS |
SV115 RTS ;SUBROUTINE TO OUTPUT: ;'SAVING <FILE NAME>' ; |
Rücksprung'SAVING' ausgeben |
print saving <file name> |
PRINT 'SAVING'MSGFLG is checked, and if direct mode is on, then themessage 'SAVING' is flagged and printed from the KERNAL I/O message table. |
do saving message and filename |
|
.,F68F A5 9D LDA $9D |
SAVING LDA MSGFLG |
Flag für Direktmodus laden |
get message mode flag |
MSGFLG |
||
.,F691 10 FB BPL $F68E |
BPL SV115 ;NO PRINT ; |
Bit 7 gelöscht, dann Programm-Mode |
exit if control messages off |
not in direct mode, exit |
||
.,F693 A0 51 LDY #$51 |
LDY #MS11-MS1 ;'SAVING' |
Offset für 'SAVING' |
index to "SAVING " |
offset to message in table |
||
.,F695 20 2F F1 JSR $F12F |
JSR MSG |
Meldung ausgeben |
display kernel I/O message |
output 'SAVING' |
||
.,F698 4C C1 F5 JMP $F5C1 |
JMP OUTFN ;<FILE NAME> .END .LIB TIME;***********************************;* * ;* TIME * ;* * ;*CONSISTS OF THREE FUNCTIONS: * ;* (1) UDTIM-- UPDATE TIME. USUALLY* ;* CALLED EVERY 60TH SECOND. * ;* (2) SETTIM-- SET TIME. .Y=MSD, * ;* .X=NEXT SIGNIFICANT,.A=LSD * ;* (3) RDTIM-- READ TIME. .Y=MSD, * ;* .X=NEXT SIGNIFICANT,.A=LSD * ;* * ;*********************************** ;INTERRUPTS ARE COMING FROM THE 6526 TIMERS ; |
Filenamen ausgeben, Rücksprung UDTIM Time erhöhen undSTOP-Taste abfragen |
print file name and returnincrement the real time clock |
output filenameUDTIM: BUMP CLOCKThe KERNAL routine UDTIM ($ffea) jumps to this routine.The three byte jiffy clock in RAM is incremented. If it has reached $4f1a01, then it is reset to zero. this number represents 5184001 jiffies (each jiffy is 1/60 sec) or 24 hours. finally, the next routine is used to log the CIA key reading. |
increment real time clock |
|
.,F69B A2 00 LDX #$00 |
UDTIM LDX #0 ;PRE-LOAD FOR LATER ; ;HERE WE PROCEED WITH AN INCREMENT ;OF THE TIME REGISTER. ; |
X-REG auf Null setzen |
clear X |
|||
.,F69D E6 A2 INC $A2 |
UD20 INC TIME+2 |
Sekundenzeiger erhöhen |
increment the jiffy clock low byte |
low byte of jiffy clock |
||
.,F69F D0 06 BNE $F6A7 |
BNE UD30 |
verzweige falls kein Überlauf |
if no rollover ?? |
|||
.,F6A1 E6 A1 INC $A1 |
INC TIME+1 |
Minutenzeiger erhöhen |
increment the jiffy clock mid byte |
mid byte of jiffy clock |
||
.,F6A3 D0 02 BNE $F6A7 |
BNE UD30 |
verzweige falls kein Überlauf |
branch if no rollover |
|||
.,F6A5 E6 A0 INC $A0 |
INC TIME ; ;HERE WE CHECK FOR ROLL-OVER 23:59:59 ;AND RESET THE CLOCK TO ZERO IF TRUE ; |
Stundenzeiger erhöhen |
increment the jiffy clock high byte now subtract a days worth of jiffies from current count and remember only the Cb result |
high byte of jiffy clock |
||
.,F6A7 38 SEC |
UD30 SEC |
Carry für Subtraktion löschen |
set carry for subtract |
|||
.,F6A8 A5 A2 LDA $A2 |
LDA TIME+2 |
Stundenzeiger laden |
get the jiffy clock low byte |
substract $4f1a01 |
||
.,F6AA E9 01 SBC #$01 |
SBC #$01 |
feststellen |
subtract $4F1A01 low byte |
|||
.,F6AC A5 A1 LDA $A1 |
LDA TIME+1 |
ob |
get the jiffy clock mid byte |
|||
.,F6AE E9 1A SBC #$1A |
SBC #$1A |
24 |
subtract $4F1A01 mid byte |
|||
.,F6B0 A5 A0 LDA $A0 |
LDA TIME |
Stunden |
get the jiffy clock high byte |
|||
.,F6B2 E9 4F SBC #$4F |
SBC #$4F |
erreicht |
subtract $4F1A01 high byte |
|||
.,F6B4 90 06 BCC $F6BC |
BCC UD60 ; ;TIME HAS ROLLED--ZERO REGISTER ; |
falls kleiner, dann verzweige |
if less than $4F1A01 jiffies skip the clock reset else .. |
and test carry if 24 hours |
||
.,F6B6 86 A0 STX $A0 |
STX TIME |
alle |
clear the jiffy clock high byte |
yepp, reset jiffy clock |
||
.,F6B8 86 A1 STX $A1 |
STX TIME+1 |
Zeiger |
clear the jiffy clock mid byte |
|||
.,F6BA 86 A2 STX $A2 |
STX TIME+2 ; ;SET STOP KEY FLAG HERE ; |
auf Null setzenAbfrage auf STOP-Taste direktvom Port |
clear the jiffy clock low byte this is wrong, there are $4F1A00 jiffies in a day so the reset to zero should occur when the value reaches $4F1A00 and not $4F1A01. this would give an extra jiffy every day and a possible TI value of 24:00:00 |
LOG CIA KEY READINGThis routine tests the keyboard for either <STOP> or <RVS>pressed. If so, the keypress is stored in STKEY. |
||
.,F6BC AD 01 DC LDA $DC01 |
UD60 LDA ROWS ;WAIT FOR IT TO SETTLE |
Port B laden |
read VIA 1 DRB, keyboard row port |
keyboard read register |
||
.,F6BF CD 01 DC CMP $DC01 |
CMP ROWS |
und |
compare it with itself |
|||
.,F6C2 D0 F8 BNE $F6BC |
BNE UD60 ;STILL BOUNCING |
entprellen |
loop if changing |
wait for value to settle |
||
.,F6C4 AA TAX |
TAX ;SET FLAGS... |
Wert ins X-REG schieben |
||||
.,F6C5 30 13 BMI $F6DA |
BMI UD80 ;NO STOP KEY...EXIT STOP KEY=$7F |
verzweige falls STOP-Taste nicht gedrückt |
||||
.,F6C7 A2 BD LDX #$BD |
LDX #$FF-$42 ;CHECK FOR A SHIFT KEY (C64 KEYBOARD) |
Bitmuster zur Abrage der Reihe mit SHIFT-Tasten |
set c6 |
|||
.,F6C9 8E 00 DC STX $DC00 |
STX COLM |
in Port A schreiben |
save VIA 1 DRA, keyboard column drive |
keyboard write register |
||
.,F6CC AE 01 DC LDX $DC01 |
UD70 LDX ROWS ;WAIT TO SETTLE... |
Port B laden |
read VIA 1 DRB, keyboard row port |
keyboard read register |
||
.,F6CF EC 01 DC CPX $DC01 |
CPX ROWS |
und |
compare it with itself |
|||
.,F6D2 D0 F8 BNE $F6CC |
BNE UD70 |
entprellen |
loop if changing |
wiat for value to settle |
||
.,F6D4 8D 00 DC STA $DC00 |
STA COLM ;!!!!!WATCH OUT...STOP KEY .A=$7F...SAME AS COLMS WAS... |
Akku in Port A schreiben |
save VIA 1 DRA, keyboard column drive |
|||
.,F6D7 E8 INX |
INX ;ANY KEY DOWN ABORTS |
inhalt von Port B erhöhen |
||||
.,F6D8 D0 02 BNE $F6DC |
BNE UD90 ;LEAVE SAME AS BEFORE... |
verzweige falls ungleich Null (SHIFT-Taste gedrückt) |
||||
.,F6DA 85 91 STA $91 |
UD80 STA STKEY ;SAVE FOR OTHER ROUTINES |
Flag für Stop-Taste setzen |
save the stop key column |
STKEY, flag STOP/RVS |
||
.,F6DC 60 RTS |
UD90 RTS |
RücksprungTIME holen |
read the real time clock |
RDTIM: GET TIMEThe KERNAL routine RDTIM ($ffde) jumps to this routine.The three byte jiffy clock is read into (A/X/Y) in the format high/mid/low. The routine exits, setting the time to its existing value in the next routine. The clock resolution is 1/60 second. SEI is included since part of the IRQ routine is to update the clock. |
read real time clock |
|
.,F6DD 78 SEI |
RDTIM SEI ;KEEP TIME FROM ROLLING |
Interrupt verhindern um Uhr anzuhalten |
disable the interrupts |
disable interrupt |
||
.,F6DE A5 A2 LDA $A2 |
LDA TIME+2 ;GET LSD |
Stunden |
get the jiffy clock low byte |
read TIME |
||
.,F6E0 A6 A1 LDX $A1 |
LDX TIME+1 ;GET NEXT MOST SIG. |
Minuten |
get the jiffy clock mid byte |
|||
.,F6E2 A4 A0 LDY $A0 |
LDY TIME ;GET MSD |
Sekunden holenTIME setzen |
get the jiffy clock high byteset the real time clock |
SETTIM: SET TIMEThe KERNAL routine SETTIM ($ffdb) jumps to this routine.On entry, (A/X/Y) must hold the value to be stored in the clock. The forman is high/mid/low, and clock resolution is 1/60 second. SEI is included since part of the IRQ routine is to update the clock. |
set real time clock |
|
.,F6E4 78 SEI |
SETTIM SEI ;KEEP TIME FROM CHANGING |
Interrupt verhindern um Uhr anzuhalten |
disable the interrupts |
disable interrupt |
||
.,F6E5 85 A2 STA $A2 |
STA TIME+2 ;STORE LSD |
Stunden |
save the jiffy clock low byte |
wrine TIME |
||
.,F6E7 86 A1 STX $A1 |
STX TIME+1 ;NEXT MOST SIGNIFICANT |
Minuten |
save the jiffy clock mid byte |
|||
.,F6E9 84 A0 STY $A0 |
STY TIME ;STORE MSD |
Sekunden schreiben |
save the jiffy clock high byte |
|||
.,F6EB 58 CLI |
CLI |
Interrupt wieder ermöglichen |
enable the interrupts |
enable interrupts |
||
.,F6EC 60 RTS |
RTS .END .LIB ERRORHANDLER;***************************************;* STOP -- CHECK STOP KEY FLAG AND * ;* RETURN Z FLAG SET IF FLAG TRUE. * ;* ALSO CLOSES ACTIVE CHANNELS AND * ;* FLUSHES KEYBOARD QUEUE. * ;* ALSO RETURNS KEY DOWNS FROM LAST * ;* KEYBOARD ROW IN .A. * ;*************************************** |
RücksprungSTOP-Taste abfragen |
scan the stop key, return Zb = 1 = [STOP] |
STOP: CHECK <STOP> KEYThe KERNAL routine STOP ($ffe1) is vectored here. If STKEY=#7f, then <STOP> was pressed and logged whilest the jiffy clock was being updated, so all I/O channels are closed and the keyboard buffer reset. |
test STOP key |
|
.,F6ED A5 91 LDA $91 |
NSTOP LDA STKEY ;VALUE OF LAST ROW |
STOP-Flag laden |
read the stop key column |
STKEY |
||
.,F6EF C9 7F CMP #$7F |
CMP #$7F ;CHECK STOP KEY POSITION |
auf Code für STOP testen |
compare with [STP] down |
<STOP> ? |
||
.,F6F1 D0 07 BNE $F6FA |
BNE STOP2 ;NOT DOWN |
verzweige falls nicht |
if not [STP] or not just [STP] exit just [STP] was pressed |
nope |
||
.,F6F3 08 PHP |
PHP |
Statusregister retten |
save status |
|||
.,F6F4 20 CC FF JSR $FFCC |
JSR CLRCH ;CLEAR CHANNELS |
Ein-Ausgabe zurücksetzen CLRCH |
close input and output channels |
CLRCHN, close all I/O channels |
||
.,F6F7 85 C6 STA $C6 |
STA NDX ;FLUSH QUEUE |
Anzahl der gedrückten Tasten |
save the keyboard buffer index |
NDX, number of characters in keyboard buffer |
||
.,F6F9 28 PLP |
PLP |
Statusregister holen |
restore status |
|||
.,F6FA 60 RTS |
STOP2 RTS ;************************************ ;* * ;* ERROR HANDLER * ;* * ;* PRINTS KERNAL ERROR MESSAGE IF * ;* BIT 6 OF MSGFLG SET. RETURNS * ;* WITH ERROR # IN .A AND CARRY. * ;* * ;************************************ ; |
RücksprungMeldungen des Betriebssystems ausgeben |
file error messages |
OUTPUT KERNAL ERROR MESSAGESThe error message to be output is flagged into (A)depending on the entry point. I/O channels are closed, and then if KERNAL messages are enabled, "I/O ERROR #" is printed along with the error number. |
handle I/O errors |
|
.,F6FB A9 01 LDA #$01 |
ERROR1 LDA #1 ;TOO MANY FILES |
'TOO MANY FILES' |
'too many files' error |
error #1, too many files |
too many files |
|
.:F6FD 2C .BYTE $2C |
.BYT $2C |
Skip zu $F700 |
makes next line BIT $02A9 |
|||
.,F6FE A9 02 LDA #$02 |
ERROR2 LDA #2 ;FILE OPEN |
'FILE OPEN' |
'file already open' error |
error #2, file open |
file open |
|
.:F700 2C .BYTE $2C |
.BYT $2C |
Skip zu $F703 |
makes next line BIT $03A9 |
|||
.,F701 A9 03 LDA #$03 |
ERROR3 LDA #3 ;FILE NOT OPEN |
'FILE NOT OPEN' |
'file not open' error |
error #3, file not open |
file not open |
|
.:F703 2C .BYTE $2C |
.BYT $2C |
Skip zu $F706 |
makes next line BIT $04A9 |
|||
.,F704 A9 04 LDA #$04 |
ERROR4 LDA #4 ;FILE NOT FOUND |
'FILE NOT FOUND' |
'file not found' error |
error #4, file not found |
file not found |
|
.:F706 2C .BYTE $2C |
.BYT $2C |
Skip zu $F709 |
makes next line BIT $05A9 |
|||
.,F707 A9 05 LDA #$05 |
ERROR5 LDA #5 ;DEVICE NOT PRESENT |
'DIVICE NOT PRESENT' |
'device not present' error |
error #5, device not found |
device not present |
|
.:F709 2C .BYTE $2C |
.BYT $2C |
Skip zu $F70C |
makes next line BIT $06A9 |
|||
.,F70A A9 06 LDA #$06 |
ERROR6 LDA #6 ;NOT INPUT FILE |
'NOT INPUT FILE' |
'not input file' error |
error #6, not input file |
not input file |
|
.:F70C 2C .BYTE $2C |
.BYT $2C |
Skip zu $F70F |
makes next line BIT $07A9 |
|||
.,F70D A9 07 LDA #$07 |
ERROR7 LDA #7 ;NOT OUTPUT FILE |
'NOT OUTPUT FILE' |
'not output file' error |
error #7, not output file |
not output file |
|
.:F70F 2C .BYTE $2C |
.BYT $2C |
Skip zu $F712 |
makes next line BIT $08A9 |
|||
.,F710 A9 08 LDA #$08 |
ERROR8 LDA #8 ;MISSING FILE NAME |
'MISSING FILENAME' |
'missing file name' error |
error #8, missing filename |
file name missing |
|
.:F712 2C .BYTE $2C |
.BYT $2C |
Skip zu $F715 |
makes next line BIT $09A9 |
|||
.,F713 A9 09 LDA #$09 |
ERROR9 LDA #9 ;BAD DEVICE # ; |
'ILLEGAL DEVICE NUMBER' |
do 'illegal device number' |
error #9, illegal device number |
illegal device no. |
|
.,F715 48 PHA |
PHA ;ERROR NUMBER ON STACK |
Fehlernummer merken |
save the error # |
|||
.,F716 20 CC FF JSR $FFCC |
JSR CLRCH ;RESTORE I/O CHANNELS ; |
Ein-Ausgabe zurücksetzen CLRCH |
close input and output channels |
CLRCHN, close all I/O channels |
||
.,F719 A0 00 LDY #$00 |
LDY #MS1-MS1 |
index to "I/O ERROR #" |
||||
.,F71B 24 9D BIT $9D |
BIT MSGFLG ;ARE WE PRINTING ERROR? |
Flag auf Direkt-Mode testen |
test message mode flag |
test MSGFLAG, KERNAL messages enabled |
||
.,F71D 50 0A BVC $F729 |
BVC EREXIT ;NO... ; |
nicht gesetzt, dann übergehen |
exit if kernal messages off |
no |
||
.,F71F 20 2F F1 JSR $F12F |
JSR MSG ;PRINT "CBM I/O ERROR #" |
'I/O ERROR #' ausgeben |
display kernel I/O message |
print "I/O ERROR #" |
||
.,F722 68 PLA |
PLA |
Fehlernummer holen |
restore error # |
|||
.,F723 48 PHA |
PHA |
und wieder merken |
copy error # |
|||
.,F724 09 30 ORA #$30 |
ORA #$30 ;MAKE ERROR # ASCII |
nach ASCII wandeln |
convert to ASCII |
convert (A) to ASCII number |
||
.,F726 20 D2 FF JSR $FFD2 |
JSR BSOUT ;PRINT IT ; |
und ausgeben |
output character to channel |
use CHROUT to print number in (A) |
||
.,F729 68 PLA |
EREXIT PLA |
Fehlernummer holen |
pull error number |
|||
.,F72A 38 SEC |
SEC |
Carry =1 (Fehlerkennzeichen) |
flag error |
|||
.,F72B 60 RTS |
RTS .END .LIB TAPEFILE;FAH -- FIND ANY HEADER; ;READS TAPE DEVICE UNTIL ONE OF FOLLOWING ;BLOCK TYPES FOUND: BDFH--BASIC DATA ;FILE HEADER, BLF--BASIC LOAD FILE ;FOR SUCCESS CARRY IS CLEAR ON RETURN. ;FOR FAILURE CARRY IS SET ON RETURN. ;IN ADDITION ACCUMULATOR IS 0 IF STOP ;KEY WAS PRESSED. ; |
RücksprungProgramm Header vom Bandlesen |
find the tape header, exit with header in buffer |
get next file header from cassette |
||
.,F72C A5 93 LDA $93 |
FAH LDA VERCK ;SAVE OLD VERIFY |
Load/Verify Flag laden |
get load/verify flag |
|||
.,F72E 48 PHA |
PHA |
und retten |
save load/verify flag |
|||
.,F72F 20 41 F8 JSR $F841 |
JSR RBLK ;READ TAPE BLOCK |
Block vom Band lesen |
initiate tape read |
|||
.,F732 68 PLA |
PLA |
L/V Flag wiederholen |
restore load/verify flag |
|||
.,F733 85 93 STA $93 |
STA VERCK ;RESTORE VERIFY FLAG |
und speichern |
save load/verify flag |
|||
.,F735 B0 32 BCS $F769 |
BCS FAH40 ;READ TERMINATED ; |
Fehler, dann beenden |
exit if error |
|||
.,F737 A0 00 LDY #$00 |
LDY #0 |
Zähler auf Null stellen |
clear the index |
|||
.,F739 B1 B2 LDA ($B2),Y |
LDA (TAPE1)Y ;GET HEADER TYPE ; |
Header-Typ testen |
read first byte from tape buffer |
|||
.,F73B C9 05 CMP #$05 |
CMP #EOT ;CHECK END OF TAPE? |
EOT ? |
compare with logical end of the tape |
|||
.,F73D F0 2A BEQ $F769 |
BEQ FAH40 ;YES...FAILURE ; |
verzweige falls ja |
if end of the tape exit |
|||
.,F73F C9 01 CMP #$01 |
CMP #BLF ;BASIC LOAD FILE? |
BASIC-Programm ? |
compare with header for a relocatable program file |
|||
.,F741 F0 08 BEQ $F74B |
BEQ FAH50 ;YES...SUCCESS ; |
verzweige falls ja |
if program file header go ?? |
|||
.,F743 C9 03 CMP #$03 |
CMP #PLF ;FIXED LOAD FILE? |
Maschinenprogramm ? |
compare with header for a non relocatable program file |
|||
.,F745 F0 04 BEQ $F74B |
BEQ FAH50 ;YES...SUCCESS ; |
verzweige falls ja |
if program file header go ?? |
|||
.,F747 C9 04 CMP #$04 |
CMP #BDFH ;BASIC DATA FILE? |
Daten-Header ? |
compare with data file header |
|||
.,F749 D0 E1 BNE $F72C |
BNE FAH ;NO...KEEP TRYING ; |
kein Header gefunden, dann erneut suchen |
if data file loop to find the tape header was a program file header |
|||
.,F74B AA TAX |
FAH50 TAX ;RETURN FILE TYPE IN .X |
Kennzeichen merken |
copy header type |
|||
.,F74C 24 9D BIT $9D |
BIT MSGFLG ;PRINTING MESSAGES? |
Direktmodus ? |
get message mode flag |
|||
.,F74E 10 17 BPL $F767 |
BPL FAH45 ;NO... ; |
nein, dann weiter |
exit if control messages off |
|||
.,F750 A0 63 LDY #$63 |
LDY #MS17-MS1 ;PRINT "FOUND" |
Offset für 'FOUND' |
index to "FOUND " |
|||
.,F752 20 2F F1 JSR $F12F |
JSR MSG ; ;OUTPUT COMPLETE FILE NAME ; |
Meldung ausgeben |
display kernel I/O message |
|||
.,F755 A0 05 LDY #$05 |
LDY #5 |
Zeiger auf Filenamen |
index to the tape filename |
|||
.,F757 B1 B2 LDA ($B2),Y |
FAH55 LDA (TAPE1)Y |
Filenamen holen |
get byte from tape buffer |
|||
.,F759 20 D2 FF JSR $FFD2 |
JSR BSOUT |
und ausgeben |
output character to channel |
|||
.,F75C C8 INY |
INY |
Zeiger erhöhen |
increment the index |
|||
.,F75D C0 15 CPY #$15 |
CPY #21 |
schon alle Buchstaben |
compare it with end+1 |
|||
.,F75F D0 F6 BNE $F757 |
BNE FAH55 ; |
verzweige wenn nein |
loop if more to do |
|||
.,F761 A5 A1 LDA $A1 |
FAH56 LDA STKEY ;KEY DOWN ON LAST ROW... |
Akku mit mittelwertigem Time-Byte laden |
get the jiffy clock mid byte |
|||
.,F763 20 E0 E4 JSR $E4E0 |
JSR FPATCH ;GOTO PATCH... |
wartet auf Commodore-Taste oder Zeitschleife |
wait ~8.5 seconds for any key from the STOP key column |
|||
.,F766 EA NOP |
NOP ; |
no operation |
waste cycles |
|||
.,F767 18 CLC |
FAH45 CLC ;SUCCESS FLAG |
Carry =0 (ok Kennzeichen) |
flag no error |
|||
.,F768 88 DEY |
DEY ;MAKE NONZERO FOR OKAY RETURN ; |
Y-REG auf $FF zur Kennzeich nung, daß kein EOT |
decrement the index |
|||
.,F769 60 RTS |
FAH40 RTS ;TAPEH--WRITE TAPE HEADER ;ERROR IF TAPE BUFFER DE-ALLOCATED ;CARRY CLEAR IF O.K. ; |
RücksprungHeader generieren und aufBand schreiben |
write the tape header |
write a special block to cassette with code in A |
||
.,F76A 85 9E STA $9E |
TAPEH STA T1 ; ;DETERMINE ADDRESS OF BUFFER ; |
Header-Typ speichern |
save header type |
|||
.,F76C 20 D0 F7 JSR $F7D0 |
JSR ZZZ |
Bandpufferadresse holen |
get tape buffer start pointer in XY |
|||
.,F76F 90 5E BCC $F7CF |
BCC TH40 ;BUFFER WAS DE-ALLOCATED ; ;PRESERVE START AND END ADDRESSES ;FOR CASE OF HEADER FOR LOAD FILE ; |
verzweige falls Adresse ungültig |
if < $0200 just exit ?? |
|||
.,F771 A5 C2 LDA $C2 |
LDA STAH |
Startadresse |
get I/O start address high byte |
|||
.,F773 48 PHA |
PHA |
laden |
save it |
|||
.,F774 A5 C1 LDA $C1 |
LDA STAL |
und in |
get I/O start address low byte |
|||
.,F776 48 PHA |
PHA |
Stack schreiben |
save it |
|||
.,F777 A5 AF LDA $AF |
LDA EAH |
Endadresse |
get tape end address high byte |
|||
.,F779 48 PHA |
PHA |
laden |
save it |
|||
.,F77A A5 AE LDA $AE |
LDA EAL |
und in |
get tape end address low byte |
|||
.,F77C 48 PHA |
PHA ; ;PUT BLANKS IN TAPE BUFFER ; |
Stack schreiben |
save it |
|||
.,F77D A0 BF LDY #$BF |
LDY #BUFSZ-1 |
Pufferlänge für Schleife holen |
index to header end |
|||
.,F77F A9 20 LDA #$20 |
LDA #' |
Code für ' ' laden |
clear byte, [SPACE] |
|||
.,F781 91 B2 STA ($B2),Y |
BLNK2 STA (TAPE1)Y |
und speichern |
clear header byte |
|||
.,F783 88 DEY |
DEY |
Zähler verringern |
decrement index |
|||
.,F784 D0 FB BNE $F781 |
BNE BLNK2 ; ;PUT BLOCK TYPE IN HEADER ; |
verzweige falls Puffer noch nicht alles gelöscht |
loop if more to do |
|||
.,F786 A5 9E LDA $9E |
LDA T1 |
gespeicherten Header-Typ holen |
get the header type back |
|||
.,F788 91 B2 STA ($B2),Y |
STA (TAPE1)Y ; ;PUT START LOAD ADDRESS IN HEADER ; |
und in Puffer schreiben |
write it to header |
|||
.,F78A C8 INY |
INY |
Zähler erhöhen |
increment the index |
|||
.,F78B A5 C1 LDA $C1 |
LDA STAL |
Startadresse LOW holen |
get the I/O start address low byte |
|||
.,F78D 91 B2 STA ($B2),Y |
STA (TAPE1)Y |
und in Puffer schreiben |
write it to header |
|||
.,F78F C8 INY |
INY |
Zähler erhöhen |
increment the index |
|||
.,F790 A5 C2 LDA $C2 |
LDA STAH |
Startadesse HIGH holen |
get the I/O start address high byte |
|||
.,F792 91 B2 STA ($B2),Y |
STA (TAPE1)Y ; ;PUT END LOAD ADDRESS IN HEADER ; |
und in Puffer schreiben |
write it to header |
|||
.,F794 C8 INY |
INY |
Zähler erhöhen |
increment the index |
|||
.,F795 A5 AE LDA $AE |
LDA EAL |
Endadresse LOW holen |
get the tape end address low byte |
|||
.,F797 91 B2 STA ($B2),Y |
STA (TAPE1)Y |
und in Puffer schreiben |
write it to header |
|||
.,F799 C8 INY |
INY |
Zähler erhöhen |
increment the index |
|||
.,F79A A5 AF LDA $AF |
LDA EAH |
Endadresse HIGH holen |
get the tape end address high byte |
|||
.,F79C 91 B2 STA ($B2),Y |
STA (TAPE1)Y ; ;PUT FILE NAME IN HEADER ; |
und in Puffer schreiben |
write it to header |
|||
.,F79E C8 INY |
INY |
Zähler erhöhen |
increment the index |
|||
.,F79F 84 9F STY $9F |
STY T2 |
Zähler speichern |
save the index |
|||
.,F7A1 A0 00 LDY #$00 |
LDY #0 |
Zähler für Filenamen auf Null setzen |
clear Y |
|||
.,F7A3 84 9E STY $9E |
STY T1 |
und speichern |
clear the name index |
|||
.,F7A5 A4 9E LDY $9E |
TH20 LDY T1 |
Zähler holen |
get name index |
|||
.,F7A7 C4 B7 CPY $B7 |
CPY FNLEN |
und mit Länge des Filenamens vergleichen |
compare with file name length |
|||
.,F7A9 F0 0C BEQ $F7B7 |
BEQ TH30 |
verzweige falls alle Buchsta- ben geholt |
if all done exit the loop |
|||
.,F7AB B1 BB LDA ($BB),Y |
LDA (FNADR)Y |
Filenamen holen |
get file name byte |
|||
.,F7AD A4 9F LDY $9F |
LDY T2 |
Pufferzeiger laden |
get buffer index |
|||
.,F7AF 91 B2 STA ($B2),Y |
STA (TAPE1)Y |
und Zeichen in Puffer schrei- ben |
save file name byte to buffer |
|||
.,F7B1 E6 9E INC $9E |
INC T1 |
Zähler für Filenamen erhöhen |
increment file name index |
|||
.,F7B3 E6 9F INC $9F |
INC T2 |
Zeiger auf Bandpuffer erhöhen |
increment tape buffer index |
|||
.,F7B5 D0 EE BNE $F7A5 |
BNE TH20 ; ;SET UP START AND END ADDRESS OF HEADER ; |
unbedingter Sprung |
loop, branch always |
|||
.,F7B7 20 D7 F7 JSR $F7D7 |
TH30 JSR LDAD1 ; ;SET UP TIME FOR LEADER ; |
Start- und Endadresse auf Bandpuffer holen |
set tape buffer start and end pointers |
|||
.,F7BA A9 69 LDA #$69 |
LDA #$69 |
set write lead cycle count |
||||
.,F7BC 85 AB STA $AB |
STA SHCNH ; |
Checksumme für Header bzw. Datenblock = $69 |
save write lead cycle count |
|||
.,F7BE 20 6B F8 JSR $F86B |
JSR TWRT2 ;WRITE HEADER ON TAPE ; ;RESTORE START AND END ADDRESS OF ;LOAD FILE. ; |
Block auf Band schreiben |
do tape write, no cycle count set |
|||
.,F7C1 A8 TAY |
TAY ;SAVE ERROR CODE IN .Y |
Akku retten |
||||
.,F7C2 68 PLA |
PLA |
Endadresse |
pull tape end address low byte |
|||
.,F7C3 85 AE STA $AE |
STA EAL |
vom Stack |
restore it |
|||
.,F7C5 68 PLA |
PLA |
holen und |
pull tape end address high byte |
|||
.,F7C6 85 AF STA $AF |
STA EAH |
in $AE/SAF speichern |
restore it |
|||
.,F7C8 68 PLA |
PLA |
Startadresse |
pull I/O start addresses low byte |
|||
.,F7C9 85 C1 STA $C1 |
STA STAL |
vom Stack |
restore it |
|||
.,F7CB 68 PLA |
PLA |
holen und |
pull I/O start addresses high byte |
|||
.,F7CC 85 C2 STA $C2 |
STA STAH |
in $C1/C2 speichern |
restore it |
|||
.,F7CE 98 TYA |
TYA ;RESTORE ERROR CODE FOR RETURN ; |
Akku wiederholen |
||||
.,F7CF 60 RTS |
TH40 RTS ;FUNCTION TO RETURN TAPE BUFFER ;ADDRESS IN TAPE1 ; |
RücksprungBandpuffer Startadresse holenund prüfen ob gültig |
get the tape buffer start pointer |
set tape buffer pointer in XY |
||
.,F7D0 A6 B2 LDX $B2 |
ZZZ LDX TAPE1 ;ASSUME TAPE1 |
Anfang Bandpuffer LOW in X |
get tape buffer start pointer low byte |
|||
.,F7D2 A4 B3 LDY $B3 |
LDY TAPE1+1 |
Anfang Bandpuffer HIGH in Y |
get tape buffer start pointer high byte |
|||
.,F7D4 C0 02 CPY #$02 |
CPY #>BUF ;CHECK FOR ALLOCATION... ;...[TAPE1+1]=0 OR 1 MEANS DEALLOCATED ;...C CLR => DEALLOCATED |
Adresse kleiner $200 ? |
compare high byte with $02xx |
|||
.,F7D6 60 RTS |
RTS |
RücksprungBandpufferendadresse = Puf-ferstartadresse + $C0 (192) |
set the tape buffer start and end pointers |
set cassette buffer to I/O area |
||
.,F7D7 20 D0 F7 JSR $F7D0 |
LDAD1 JSR ZZZ ;GET PTR TO CASSETTE |
BandpufferaAdresse holen |
get tape buffer start pointer in XY |
|||
.,F7DA 8A TXA |
TXA |
Pufferanfang LOW in Akku |
copy tape buffer start pointer low byte |
|||
.,F7DB 85 C1 STA $C1 |
STA STAL ;SAVE START LOW |
und speichern |
save as I/O address pointer low byte |
|||
.,F7DD 18 CLC |
CLC |
Carry für Addition löschen |
clear carry for add |
|||
.,F7DE 69 C0 ADC #$C0 |
ADC #BUFSZ ;COMPUTE POINTER TO END |
Endadresse = Startadresse + Länge $C0 (192) |
add buffer length low byte |
|||
.,F7E0 85 AE STA $AE |
STA EAL ;SAVE END LOW |
und Endadresse speichern |
save tape buffer end pointer low byte |
|||
.,F7E2 98 TYA |
TYA |
Pufferanfang HIGH in Akku |
copy tape buffer start pointer high byte |
|||
.,F7E3 85 C2 STA $C2 |
STA STAH ;SAVE START HIGH |
und speichern |
save as I/O address pointer high byte |
|||
.,F7E5 69 00 ADC #$00 |
ADC #0 ;COMPUTE POINTER TO END |
mit Übertrag addieren |
add buffer length high byte |
|||
.,F7E7 85 AF STA $AF |
STA EAH ;SAVE END HIGH |
und speichern |
save tape buffer end pointer high byte |
|||
.,F7E9 60 RTS |
RTS |
RücksprungBandheader nach Namen suchen |
find specific tape header |
search tape for a file name |
||
.,F7EA 20 2C F7 JSR $F72C |
FAF JSR FAH ;FIND ANY HEADER |
nächsten Bandheader suchen |
find tape header, exit with header in buffer |
|||
.,F7ED B0 1D BCS $F80C |
BCS FAF40 ;FAILED ; ;SUCCESS...SEE IF RIGHT NAME ; |
verzweige falls EOT (fertig) |
just exit if error |
|||
.,F7EF A0 05 LDY #$05 |
LDY #5 ;OFFSET INTO TAPE HEADER |
Offset für Filenamen im Header |
index to name |
|||
.,F7F1 84 9F STY $9F |
STY T2 |
und speichern |
save as tape buffer index |
|||
.,F7F3 A0 00 LDY #$00 |
LDY #0 ;OFFSET INTO FILE NAME |
Zähler für Länge des Filena- mens auf Null setzen |
clear Y |
|||
.,F7F5 84 9E STY $9E |
STY T1 |
und Zähler speichern |
save as name buffer index |
|||
.,F7F7 C4 B7 CPY $B7 |
FAF20 CPY FNLEN ;COMPARE THIS MANY |
mit Länge des gesuchten Namens vergleichen |
compare with file name length |
|||
.,F7F9 F0 10 BEQ $F80B |
BEQ FAF30 ;DONE ; |
gleich, dann gefunden |
ok exit if match |
|||
.,F7FB B1 BB LDA ($BB),Y |
LDA (FNADR)Y |
Buchstaben des Filenamens |
get file name byte |
|||
.,F7FD A4 9F LDY $9F |
LDY T2 |
Position im Header laden |
get index to tape buffer |
|||
.,F7FF D1 B2 CMP ($B2),Y |
CMP (TAPE1)Y |
mit Filenamen im Header vergleichen |
compare with tape header name byte |
|||
.,F801 D0 E7 BNE $F7EA |
BNE FAF ;MISMATCH--TRY NEXT HEADER |
verzweige falls ungleich, dann nächsten Header testen |
if no match go get next header |
|||
.,F803 E6 9E INC $9E |
INC T1 |
Zähler für Filenamen erhöhen |
else increment name buffer index |
|||
.,F805 E6 9F INC $9F |
INC T2 |
Zeiger auf Position im Header erhöhen |
increment tape buffer index |
|||
.,F807 A4 9E LDY $9E |
LDY T1 |
Zähler für Filenamen laden |
get name buffer index |
|||
.,F809 D0 EC BNE $F7F7 |
BNE FAF20 ;BRANCH ALWAYS ; |
unbedingter Sprung |
loop, branch always |
|||
.,F80B 18 CLC |
FAF30 CLC ;SUCCESS FLAG |
Carry =0 (ok Kennzeichen) |
flag ok |
|||
.,F80C 60 RTS |
FAF40 RTS .END .LIB TAPECONTROL |
RücksprungBandpufferzeiger erhöhen |
bump tape pointer |
add 1 to tape index and test for overflow |
||
.,F80D 20 D0 F7 JSR $F7D0 |
JTP20 JSR ZZZ |
Bandpufferadresse holen |
get tape buffer start pointer in XY |
|||
.,F810 E6 A6 INC $A6 |
INC BUFPT |
Zeiger erhöhen |
increment tape buffer index |
|||
.,F812 A4 A6 LDY $A6 |
LDY BUFPT |
und laden um |
get tape buffer index |
|||
.,F814 C0 C0 CPY #$C0 |
CPY #BUFSZ |
mit Maximalwert (192) zu vergleichen |
compare with buffer length |
|||
.,F816 60 RTS |
RTS ;STAYS IN ROUTINE D2T1LL PLAY SWITCH ; |
RücksprungWartet auf Bandtaste |
wait for PLAY |
handle messages andtest cassette buttons for read |
||
.,F817 20 2E F8 JSR $F82E |
CSTE1 JSR CS10 |
fragt BandtTaste ab |
return cassette sense in Zb |
|||
.,F81A F0 1A BEQ $F836 |
BEQ CS25 |
gedrückt, dann fertig |
if switch closed just exit cassette switch was open |
|||
.,F81C A0 1B LDY #$1B |
LDY #MS7-MS1 ;"PRESS PLAY..." |
Offset für 'PRESS PLAY ON TAPE' |
index to "PRESS PLAY ON TAPE" |
|||
.,F81E 20 2F F1 JSR $F12F |
CS30 JSR MSG |
und ausgeben |
display kernel I/O message |
|||
.,F821 20 D0 F8 JSR $F8D0 |
CS40 JSR TSTOP ;WATCH FOR STOP KEY |
testet auf STOP-Taste |
scan stop key and flag abort if pressed note if STOP was pressed the return is to the routine that called this one and not here |
|||
.,F824 20 2E F8 JSR $F82E |
JSR CS10 ;WATCH CASSETTE SWITCHES |
fragt BandtTaste ab |
return cassette sense in Zb |
|||
.,F827 D0 F8 BNE $F821 |
BNE CS40 |
nicht gedrückt so erneut abfragen |
loop if the cassette switch is open |
|||
.,F829 A0 6A LDY #$6A |
LDY #MS18-MS1 ;"OK" |
Offset für 'OK' |
index to "OK" |
|||
.,F82B 4C 2F F1 JMP $F12F |
JMP MSG ;SUBR RETURNS <> FOR CASSETTE SWITCH ; |
und ausgeben, RücksprungAbfrage ob Band-Tastegedrückt |
display kernel I/O message and returnreturn cassette sense in Zb |
test sense line for a buttondepressed on cassette |
||
.,F82E A9 10 LDA #$10 |
CS10 LDA #$10 ;CHECK PORT |
Bit 4 testen |
set the mask for the cassette switch |
|||
.,F830 24 01 BIT $01 |
BIT R6510 ;CLOSED?... |
mit Port vergleichen |
test the 6510 I/O port |
|||
.,F832 D0 02 BNE $F836 |
BNE CS25 ;NO. . . |
verzweige wenn Bandtaste nicht gedrückt |
branch if cassette sense high |
|||
.,F834 24 01 BIT $01 |
BIT R6510 ;CHECK AGAIN TO DEBOUNCE |
nochmal abfragen (Entprellen) |
test the 6510 I/O port |
|||
.,F836 18 CLC |
CS25 CLC ;GOOD RETURN |
Carry =0 (ok Kennzeichen) |
||||
.,F837 60 RTS |
RTS ;CHECKS FOR PLAY & RECORD ; |
RücksprungWartet auf Bandtaste fürSchreiben |
wait for PLAY/RECORD |
set messages and test cassette linefor input |
||
.,F838 20 2E F8 JSR $F82E |
CSTE2 JSR CS10 |
fragt Bandtaste ab |
return the cassette sense in Zb |
|||
.,F83B F0 F9 BEQ $F836 |
BEQ CS25 |
gedrückt, dann fertig |
exit if switch closed cassette switch was open |
|||
.,F83D A0 2E LDY #$2E |
LDY #MS8-MS1 ;"RECORD" |
Offset für 'PRESS RECORD & PLAY ON TAPE' |
index to "PRESS RECORD & PLAY ON TAPE" |
|||
.,F83F D0 DD BNE $F81E |
BNE CS30 ;READ HEADER BLOCK ENTRY ; |
unbedingter SprungBlock vom Band lesen |
display message and wait for switch, branch alwaysinitiate a tape read |
read a block from cassette |
||
.,F841 A9 00 LDA #$00 |
RBLK LDA #0 |
Status |
clear A |
|||
.,F843 85 90 STA $90 |
STA STATUS |
und Verify-Flag |
clear serial status byte |
|||
.,F845 85 93 STA $93 |
STA VERCK |
löschen |
clear the load/verify flag |
|||
.,F847 20 D7 F7 JSR $F7D7 |
JSR LDAD1 ;READ LOAD BLOCK ENTRY ; |
Bandpufferadresse holenProgramm vom Band laden |
set the tape buffer start and end pointers |
|||
.,F84A 20 17 F8 JSR $F817 |
TRD JSR CSTE1 ;SAY 'PRESS PLAY' |
wartet auf Play-Taste |
wait for PLAY |
|||
.,F84D B0 1F BCS $F86E |
BCS TWRT3 ;STOP KEY PRESSED |
STOP-Taste gedrückt ? |
exit if STOP was pressed, uses a further BCS at the target address to reach final target at $F8DC |
|||
.,F84F 78 SEI |
SEI |
Interrupt verhindern |
disable interrupts |
|||
.,F850 A9 00 LDA #$00 |
LDA #0 ;CLEAR FLAGS... |
Arbeitsspeicher für IRQ- Routine löschen |
clear A |
|||
.,F852 85 AA STA $AA |
STA RDFLG |
Eingabebytespeicher (read) |
||||
.,F854 85 B4 STA $B4 |
STA SNSW1 |
Band Hilfszeiger |
||||
.,F856 85 B0 STA $B0 |
STA CMP0 |
Kassetten Zeitkonstante |
clear tape timing constant min byte |
|||
.,F858 85 9E STA $9E |
STA PTR1 |
Korrekturzähler Pass 1 |
clear tape pass 1 error log/char buffer |
|||
.,F85A 85 9F STA $9F |
STA PTR2 |
Korrekturzähler Pass 2 |
clear tape pass 2 error log corrected |
|||
.,F85C 85 9C STA $9C |
STA DPSW |
Flag für Byte emfngen |
clear byte received flag |
|||
.,F85E A9 90 LDA #$90 |
LDA #$90 ;ENABLE FOR CA1 IRQ...READ LINE |
Bitwert IRQ an Pin 'Flag' |
enable CA1 interrupt ?? |
|||
.,F860 A2 0E LDX #$0E |
LDX #14 ;POINT IRQ VECTOR TO READ |
Nummer des IRQ-Vektors, $F92C |
set index for tape read vector |
|||
.,F862 D0 11 BNE $F875 |
BNE TAPE ;JMP ;WRITE HEADER BLOCK ENTRY ; |
unbedingter SprungBandpuffer auf Band schreiben |
go do tape read/write, branch alwaysinitiate a tape write |
write a block from cassette |
||
.,F864 20 D7 F7 JSR $F7D7 |
WBLK JSR LDAD1 ; ;WRITE LOAD BLOCK ENTRY ; |
Bandpufferadresse holen |
set tape buffer start and end pointers do tape write, 20 cycle count |
|||
.,F867 A9 14 LDA #$14 |
TWRT LDA #20 ;BETWEEN BLOCK SHORTS |
Länge des Vorspanns vor WRITE |
set write lead cycle count |
|||
.,F869 85 AB STA $AB |
STA SHCNH |
speichernBlock bzw. Programm auf Bandschreiben |
save write lead cycle count do tape write, no cycle count set |
|||
.,F86B 20 38 F8 JSR $F838 |
TWRT2 JSR CSTE2 ;SAY 'PRESS PLAY & RECORD' |
wartet auf Record & Play Taste |
wait for PLAY/RECORD |
|||
.,F86E B0 6C BCS $F8DC |
TWRT3 BCS STOP3 ;STOP KEY PRESSED |
verzweige falls STOP-Taste gedrückt |
if STOPped clear save IRQ address and exit |
|||
.,F870 78 SEI |
SEI |
Interrupt verhindern |
disable interrupts |
|||
.,F871 A9 82 LDA #$82 |
LDA #$82 ;ENABLE T2 IRQS...WRITE TIME |
Bitwert für IRQ bei Unterlauf von Timer B |
enable ?? interrupt |
|||
.,F873 A2 08 LDX #$08 |
LDX #8 ;VECTOR IRQ TO WRTZ ;START TAPE OPERATION ENTRY POINT ; |
Nummer des IRQ-Vektors, $FC6A |
set index for tape write tape leader vectortape read/write |
common code for cassette read and write |
||
.,F875 A0 7F LDY #$7F |
TAPE LDY #$7F ;KILL UNWANTED IRQ'S |
Bitwert für alle IRQs sperren |
disable all interrupts |
|||
.,F877 8C 0D DC STY $DC0D |
STY D1ICR |
Wert schreiben |
save VIA 1 ICR, disable all interrupts |
|||
.,F87A 8D 0D DC STA $DC0D |
STA D1ICR ;TURN ON WANTED |
und neu setzen |
save VIA 1 ICR, enable interrupts according to A check RS232 bus idle |
|||
.,F87D AD 0E DC LDA $DC0E |
LDA D1CRA ;CALC TIMER ENABLES |
Control Register A laden |
read VIA 1 CRA |
|||
.,F880 09 19 ORA #$19 |
ORA #$19 |
Bitwert für one shot, starten |
load timer B, timer B single shot, start timer B |
|||
.,F882 8D 0F DC STA $DC0F |
STA D1CRB ;TURN ON T2 IRQ'S FOR CASS WRITE(ONE SHOT) |
und ins Steuerregister für Timer B |
save VIA 1 CRB |
|||
.,F885 29 91 AND #$91 |
AND #$91 ;SAVE TOD 50/60 INDICATION |
Vergleichszeiger für Bandope- |
mask x00x 000x, TOD clock, load timer A, start timer A |
|||
.,F887 8D A2 02 STA $02A2 |
STA CASTON ;PLACE IN AUTO MODE FOR T1 ; WAIT FOR RS-232 TO FINISH |
rationen entsprechend setzen |
save VIA 1 CRB shadow copy |
|||
.,F88A 20 A4 F0 JSR $F0A4 |
JSR RSP232 ; DISABLE SCREEN DISPLAY |
auf Ende RS-232 Übertragung warten |
||||
.,F88D AD 11 D0 LDA $D011 |
LDA VICREG+17 |
Bildschirm |
read the vertical fine scroll and control register |
|||
.,F890 29 EF AND #$EF |
AND #$FF-$10 ;DISABLE SCREEN |
dunkel |
mask xxx0 xxxx, blank the screen |
|||
.,F892 8D 11 D0 STA $D011 |
STA VICREG+17 ; MOVE IRQ TO IRQTEMP FOR CASS OPS |
Tasten |
save the vertical fine scroll and control register |
|||
.,F895 AD 14 03 LDA $0314 |
LDA CINV |
IRQ-Vector |
get IRQ vector low byte |
|||
.,F898 8D 9F 02 STA $029F |
STA IRQTMP |
nach $029F |
save IRQ vector low byte |
|||
.,F89B AD 15 03 LDA $0315 |
LDA CINV+1 |
und $02A0 |
get IRQ vector high byte |
|||
.,F89E 8D A0 02 STA $02A0 |
STA IRQTMP+1 |
speichern |
save IRQ vector high byte |
|||
.,F8A1 20 BD FC JSR $FCBD |
JSR BSIV ;GO CHANGE IRQ VECTOR |
IRQ-Vektor für Band I/O setzen (X-indiziert) |
set the tape vector |
|||
.,F8A4 A9 02 LDA #$02 |
LDA #2 ;FSBLK STARTS AT 2 |
Anzahl der |
set copies count. the first copy is the load copy, the second copy is the verify copy |
|||
.,F8A6 85 BE STA $BE |
STA FSBLK |
zu lesenden Blöcke |
save copies count |
|||
.,F8A8 20 97 FB JSR $FB97 |
JSR NEWCH ;PREP LOCAL COUNTERS AND FLAGS |
serielle Ausgabe vorbereiten Bit-Zähler setzen |
new tape byte setup |
|||
.,F8AB A5 01 LDA $01 |
LDA R6510 ;TURN MOTOR ON |
Prozessorport laden |
read the 6510 I/O port |
|||
.,F8AD 29 1F AND #$1F |
AND #%011111 ;LOW TURNS ON |
Bandmotor einschalten |
mask 000x xxxx, cassette motor on ?? |
|||
.,F8AF 85 01 STA $01 |
STA R6510 |
und wieder speichern |
save the 6510 I/O port |
|||
.,F8B1 85 C0 STA $C0 |
STA CAS1 ;FLAG INTERNAL CONTROL OF CASS MOTOR |
Flag für Bandmotor setzen |
set the tape motor interlock 326656 cycle delay, allow tape motor speed to stabilise |
|||
.,F8B3 A2 FF LDX #$FF |
LDX #$FF ;DELAY BETWEEN BLOCKS |
HIGH-Byte für Zähler |
outer loop count |
|||
.,F8B5 A0 FF LDY #$FF |
TP32 LDY #$FF |
LOW-Byte für Zähler |
inner loop count |
|||
.,F8B7 88 DEY |
TP35 DEY |
Verzögerungsschleife |
decrement inner loop count |
|||
.,F8B8 D0 FD BNE $F8B7 |
BNE TP35 |
für Bandhochlaufzeit |
loop if more to do |
|||
.,F8BA CA DEX |
DEX |
HIGH-Byte veringern |
decrement outer loop count |
|||
.,F8BB D0 F8 BNE $F8B5 |
BNE TP32 |
verzweige falls nicht Null |
loop if more to do |
|||
.,F8BD 58 CLI |
CLI |
Interrupt für Band I/O freigeben I/O Abschluß abwarten |
enable tape interrupts |
|||
.,F8BE AD A0 02 LDA $02A0 |
TP40 LDA IRQTMP+1 ;CHECK FOR INTERRUPT VECTOR... |
Band IRQ Vector mit normalem |
get saved IRQ high byte |
|||
.,F8C1 CD 15 03 CMP $0315 |
CMP CINV+1 ;...POINTING AT KEY ROUTINE |
IRQ Vector vergleichen |
compare with the current IRQ high byte |
|||
.,F8C4 18 CLC |
CLC |
Carry =0 (ok Kennzeichen) |
flag ok |
|||
.,F8C5 F0 15 BEQ $F8DC |
BEQ STOP3 ;...YES RETURN |
verzweige falls ja (fertig) |
if tape write done go clear saved IRQ address and exit |
|||
.,F8C7 20 D0 F8 JSR $F8D0 |
JSR TSTOP ;...NO CHECK FOR STOP KEY ; ; 60 HZ KEYSCAN IGNORED ; |
Testen auf Stop-Taste |
scan stop key and flag abort if pressed note if STOP was pressed the return is to the routine that called this one and not here |
|||
.,F8CA 20 BC F6 JSR $F6BC |
JSR UD60 ; STOP KEY CHECK |
bei gedrückter Stop-Taste Flag setzen |
increment real time clock |
|||
.,F8CD 4C BE F8 JMP $F8BE |
JMP TP40 ;STAY IN LOOP UNTILL TAPES ARE DONE |
weiter wartentestet auf Stop-Taste |
loopscan stop key and flag abort if pressed |
handle stop key during cassette operations |
||
.,F8D0 20 E1 FF JSR $FFE1 |
TSTOP JSR STOP ;STOP KEY DOWN? |
Stop-Taste abfragen |
scan stop key |
|||
.,F8D3 18 CLC |
CLC ;ASSUME NO STOP |
Carry =0 (ok Kennzeichen) |
flag no stop |
|||
.,F8D4 D0 0B BNE $F8E1 |
BNE STOP4 ;WE WERE RIGHT ; ;STOP KEY DOWN... ; |
verzweige wenn Taste nein gedrückt |
exit if no stop |
|||
.,F8D6 20 93 FC JSR $FC93 |
JSR TNIF ;TURN OFF CASSETTES |
Band-Motor aus, normalen IRQ wiederherstellen |
restore everything for STOP |
|||
.,F8D9 38 SEC |
SEC ;FAILURE FLAG |
Kennzeichen für Abbruch |
flag stopped |
|||
.,F8DA 68 PLA |
PLA ;BACK ONE SQUARE... |
Rücksprung |
dump return address low byte |
|||
.,F8DB 68 PLA |
PLA ; ; LDA #0 ;STOP KEY FLAG ; |
Adresse löschen |
dump return address high byteclear saved IRQ address |
|||
.,F8DC A9 00 LDA #$00 |
STOP3 LDA #0 ;DEALLOCATE IRQTMP |
Kennzeichen für normalen |
clear A |
|||
.,F8DE 8D A0 02 STA $02A0 |
STA IRQTMP+1 ;IF C-SET THEN STOP KEY |
IRQ setzen |
clear saved IRQ address high byte |
|||
.,F8E1 60 RTS |
STOP4 RTS ; ; STT1 - SET UP TIMEOUT WATCH FOR NEXT DIPOLE ; |
RücksprungBand für Lesen vorbereiten |
# set timing |
schedule CIA1 timer A depending on X |
||
.,F8E2 86 B1 STX $B1 |
STT1 STX TEMP ;.X HAS CONSTANT FOR TIMEOUT |
X-Register speichern |
save tape timing constant max byte |
|||
.,F8E4 A5 B0 LDA $B0 |
LDA CMP0 ;CMP0*5 |
Timing-Konstante laden |
get tape timing constant min byte |
|||
.,F8E6 0A ASL |
ASL A |
mit vier |
*2 |
|||
.,F8E7 0A ASL |
ASL A |
multiplizieren |
*4 |
|||
.,F8E8 18 CLC |
CLC |
zur Addition Carry löschen |
clear carry for add |
|||
.,F8E9 65 B0 ADC $B0 |
ADC CMP0 |
mit altem Wert addieren (*5) |
add tape timing constant min byte *5 |
|||
.,F8EB 18 CLC |
CLC |
zur Addition Carry löschen |
clear carry for add |
|||
.,F8EC 65 B1 ADC $B1 |
ADC TEMP ;ADJUST LONG BYTE COUNT |
alten X Wert dazuaddieren |
add tape timing constant max byte |
|||
.,F8EE 85 B1 STA $B1 |
STA TEMP |
und im Hilfszeiger speichern |
save tape timing constant max byte |
|||
.,F8F0 A9 00 LDA #$00 |
LDA #0 |
Akku löschen |
||||
.,F8F2 24 B0 BIT $B0 |
BIT CMP0 ;CHECK CMP0 ... |
prüfe Timing-Konstante |
test tape timing constant min byte |
|||
.,F8F4 30 01 BMI $F8F7 |
BMI STT2 ;...MINUS, NO ADJUST |
verzweige, falls größer 128 |
branch if b7 set |
|||
.,F8F6 2A ROL |
ROL A ;...PLUS SO ADJUST POS |
Carry in die unterste Position des Akkus schieben |
else shift carry into ?? |
|||
.,F8F7 06 B1 ASL $B1 |
STT2 ASL TEMP ;MULTIPLY CORRECTED VALUE BY 4 |
und Timer A |
shift tape timing constant max byte |
|||
.,F8F9 2A ROL |
ROL A |
Initialisierung |
||||
.,F8FA 06 B1 ASL $B1 |
ASL TEMP |
mit vier |
shift tape timing constant max byte |
|||
.,F8FC 2A ROL |
ROL A |
multiplizieren |
||||
.,F8FD AA TAX |
TAX |
Akku ins X-Register |
||||
.,F8FE AD 06 DC LDA $DC06 |
STT3 LDA D1T2L ;WATCH OUT FOR D1T2H ROLLOVER... |
LOW-Byte Timer B laden |
get VIA 1 timer B low byte |
|||
.,F901 C9 16 CMP #$16 |
CMP #22 ;...TIME FOR ROUTINE...!!!... |
mit $16 vergleichen |
compare with ?? |
|||
.,F903 90 F9 BCC $F8FE |
BCC STT3 ;...TOO CLOSE SO WAIT UNTILL PAST |
verzweige, wenn kleiner |
loop if less |
|||
.,F905 65 B1 ADC $B1 |
ADC TEMP ;CALCULATE AND... |
LOW-Byte für Initialisierung addieren |
add tape timing constant max byte |
|||
.,F907 8D 04 DC STA $DC04 |
STA D1T1L ;...STORE ADUSTED TIME COUNT |
Timer A LOW speichern |
save VIA 1 timer A low byte |
|||
.,F90A 8A TXA |
TXA |
HIGH-Byte für Initialisierung |
||||
.,F90B 6D 07 DC ADC $DC07 |
ADC D1T2H ;ADJUST FOR HIGH TIME COUNT |
zu Timer B HIGH addieren |
add VIA 1 timer B high byte |
|||
.,F90E 8D 05 DC STA $DC05 |
STA D1T1H |
und in Timer A HIGH schreiben |
save VIA 1 timer A high byte |
|||
.,F911 AD A2 02 LDA $02A2 |
LDA CASTON ;ENABLE TIMERS |
Init. Wert für Band Zeitkon. |
read VIA 1 CRB shadow copy |
|||
.,F914 8D 0E DC STA $DC0E |
STA D1CRA |
zum Starten von Timer A |
save VIA 1 CRA |
|||
.,F917 8D A4 02 STA $02A4 |
STA STUPID ;NON-ZERO MEANS AN T1 IRQ HAS NOT OCCURED YET |
Timer A Flag zurücksetzten |
save VIA 1 CRA shadow copy |
|||
.,F91A AD 0D DC LDA $DC0D |
LDA D1ICR ;CLEAR OLD T1 INTERRUPT |
ICR laden |
read VIA 1 ICR |
|||
.,F91D 29 10 AND #$10 |
AND #$10 ;CHECK FOR OLD-FLAG IRQ |
Bit isolieren |
mask 000x 0000, FLAG interrupt |
|||
.,F91F F0 09 BEQ $F92A |
BEQ STT4 ;NO...NORMAL EXIT |
verzweige wenn IRQ nicht vom Pin Flag |
if no FLAG interrupt just exit else first call the IRQ routine |
|||
.,F921 A9 F9 LDA #$F9 |
LDA #>STT4 ;PUSH SIMULATED RETURN ADDRESS ON STACK |
Rücksprungadresse |
set the return address high byte |
|||
.,F923 48 PHA |
PHA |
auf |
push the return address high byte |
|||
.,F924 A9 2A LDA #$2A |
LDA #<STT4 |
Stack |
set the return address low byte |
|||
.,F926 48 PHA |
PHA |
schieben |
push the return address low byte |
|||
.,F927 4C 43 FF JMP $FF43 |
JMP SIMIRQ |
zum Interrupt |
save the status and do the IRQ routine |
|||
.,F92A 58 CLI |
STT4 CLI ;ALLOW FOR RE-ENTRY CODE |
alle Interrupts freigeben |
enable interrupts |
|||
.,F92B 60 RTS |
RTS .END .LIB READ; VARIABLES USED IN CASSETTE READ ROUTINES; ; REZ - COUNTS ZEROS (IF Z THEN CORRECT # OF DIPOLES) ; RER - FLAGS ERRORS (IF Z THEN NO ERROR) ; DIFF - USED TO PRESERVE SYNO (OUTSIDE OF BIT ROUTINES) ; SYNO - FLAGS IF WE HAVE BLOCK SYNC (16 ZERO DIPOLES) ; SNSW1 - FLAGS IF WE HAVE BYTE SYNC (A LONGLONG) ; DATA - HOLDS MOST RECENT DIPOLE BIT VALUE ; MYCH - HOLDS INPUT BYTE BEING BUILT ; FIRT - USED TO INDICATE WHICH HALF OF DIPOLE WE'RE IN ; SVXT - TEMP USED TO ADJUST SOFTWARE SERVO ; TEMP - USED TO HOLD DIPOLE TIME DURING TYPE CALCULATIONS ; PRTY - HOLDS CURRENT CALCULATED PARITY BIT ; PRP - HAS COMBINED ERROR VALUES FROM BIT ROUTINES ; FSBLK - INDICATE WHICH BLOCK WE'RE LOOKING AT (0 TO EXIT) ; SHCNL - HOLDS FSBLK, USED TO DIRECT ROUTINES, BECAUSE OF EXIT CASE ; RDFLG - HOLDS FUNCTION MODE ; MI - WAITING FOR BLOCK SYNC ; VS - IN DATA BLOCK READING DATA ; NE - WAITING FOR BYTE SYNC ; SAL - INDIRECT TO DATA STORAGE AREA ; SHCNH - LEFT OVER FROM DEBUGGING ; BAD - STORAGE SPACE FOR BAD READ LOCATIONS (BOTTOM OF STACK) ; PTR1 - COUNT OF READ LOCATIONS IN ERROR (POINTER INTO BAD, MAX 61) ; PTR2 - COUNT OF RE-READ LOCATIONS (POINTER INTO BAD, DURING RE-READ) ; VERCHK - VERIFY OR LOAD FLAG (Z - LOADING) ; CMP0 - SOFTWARE SERVO (+/- ADJUST TO TIME CALCS) ; DPSW - IF NZ THEN EXPECTING LL/L COMBINATION THAT ENDS A BYTE ; PCNTR - COUNTS DOWN FROM 8-0 FOR DATA THEN TO FF FOR PARITY ; STUPID - HOLD INDICATOR (NZ - NO T1IRQ YET) FOR T1IRQ ; KIKA26 - HOLDS OLD D1ICR AFTER CLEAR ON READ ; |
RücksprungInterrupt-Routine für Bandlesen |
On Commodore computers, the streams consist of four kinds of symbolsthat denote different kinds of low-to-high-to-low transitions on theread or write signals of the Commodore cassette interface. A A break in the communications, or a pulse with very long cycle time. B A short pulse, whose cycle time typically ranges from 296 to 424 microseconds, depending on the computer model. C A medium-length pulse, whose cycle time typically ranges from 440 to 576 microseconds, depending on the computer model. D A long pulse, whose cycle time typically ranges from 600 to 744 microseconds, depending on the computer model. The actual interpretation of the serial data takes a little more work to explain. The typical ROM tape loader (and the turbo loaders) will initialize a timer with a specified value and start it counting down. If either the tape data changes or the timer runs out, an IRQ will occur. The loader will determine which condition caused the IRQ. If the tape data changed before the timer ran out, we have a short pulse, or a "0" bit. If the timer ran out first, we have a long pulse, or a "1" bit. Doing this continuously and we decode the entire file. read tape bits, IRQ routine read T2C which has been counting down from $FFFF. subtract this from $FFFF |
cassette read IRQ routine |
||
.,F92C AE 07 DC LDX $DC07 |
READ LDX D1T2H ;GET TIME SINCE LAST INTERRUPT |
Timer B HIGH laden |
read VIA 1 timer B high byte |
|||
.,F92F A0 FF LDY #$FF |
LDY #$FF ;COMPUTE COUNTER DIFFERENCE |
Y-Register mit $FF laden (für Timer) |
set $FF |
|||
.,F931 98 TYA |
TYA |
in Akku schieben |
A = $FF |
|||
.,F932 ED 06 DC SBC $DC06 |
SBC D1T2L |
Timer B von $FF abziehen |
subtract VIA 1 timer B low byte |
|||
.,F935 EC 07 DC CPX $DC07 |
CPX D1T2H ;CHECK FOR TIMER HIGH ROLLOVER... |
Timer B mit altem Wert vergleichen |
compare it with VIA 1 timer B high byte |
|||
.,F938 D0 F2 BNE $F92C |
BNE READ ;...YES THEN RECOMPUTE |
verzweige, falls vermindert |
if timer low byte rolled over loop |
|||
.,F93A 86 B1 STX $B1 |
STX TEMP |
Timer B HIGH ablegen |
save tape timing constant max byte |
|||
.,F93C AA TAX |
TAX |
und in Akku schieben |
copy $FF - T2C_l |
|||
.,F93D 8C 06 DC STY $DC06 |
STY D1T2L ;RELOAD TIMER2 (COUNT DOWN FROM $FFFF) |
Timer B LOW und |
save VIA 1 timer B low byte |
|||
.,F940 8C 07 DC STY $DC07 |
STY D1T2H |
Timer B HIGH auf $FF setzen |
save VIA 1 timer B high byte |
|||
.,F943 A9 19 LDA #$19 |
LDA #$19 ;ENABLE TIMER |
Arbeitsmodus für Timer B |
load timer B, timer B single shot, start timer B |
|||
.,F945 8D 0F DC STA $DC0F |
STA D1CRB |
festlegen und starten |
save VIA 1 CRB |
|||
.,F948 AD 0D DC LDA $DC0D |
LDA D1ICR ;CLEAR READ INTERRUPT |
Interrupt Control Register |
read VIA 1 ICR |
|||
.,F94B 8D A3 02 STA $02A3 |
STA KIKA26 ;SAVE FOR LATTER |
laden und nach $02A3 |
save VIA 1 ICR shadow copy |
|||
.,F94E 98 TYA |
TYA |
Y-REG in Akku ($FF) |
y = $FF |
|||
.,F94F E5 B1 SBC $B1 |
SBC TEMP ;CALCULATE HIGH |
Errechnung von vergangener Zeit seit letzter Flanke |
subtract tape timing constant max byte A = $FF - T2C_h |
|||
.,F951 86 B1 STX $B1 |
STX TEMP |
vergangene Zeit LOW nach $B1 |
save tape timing constant max byte $B1 = $FF - T2C_l |
|||
.,F953 4A LSR |
LSR A ;MOVE TWO BITS FROM HIGH TO TEMP |
vergangene Zeit |
A = $FF - T2C_h >> 1 |
|||
.,F954 66 B1 ROR $B1 |
ROR TEMP |
HIGH |
shift tape timing constant max byte $B1 = $FF - T2C_l >> 1 |
|||
.,F956 4A LSR |
LSR A |
geteilt |
A = $FF - T2C_h >> 1 |
|||
.,F957 66 B1 ROR $B1 |
ROR TEMP |
durch vier |
shift tape timing constant max byte $B1 = $FF - T2C_l >> 1 |
|||
.,F959 A5 B0 LDA $B0 |
LDA CMP0 ;CALC MIN PULSE VALUE |
Timingkonstante laden |
get tape timing constant min byte |
|||
.,F95B 18 CLC |
CLC |
und mit |
clear carry for add |
|||
.,F95C 69 3C ADC #$3C |
ADC #60 |
$3C addiert |
||||
.,F95E C5 B1 CMP $B1 |
CMP TEMP ;IF PULSE LESS THAN MIN... |
errechnete Zeit größer als die Zeit bei letzten Flanken |
compare with tape timing constant max byte compare with ($FFFF - T2C) >> 2 |
|||
.,F960 B0 4A BCS $F9AC |
BCS RDBK ;...THEN IGNORE AS NOISE |
verzweige, wenn größer |
branch if min + $3C >= ($FFFF - T2C) >> 2 min + $3C < ($FFFF - T2C) >> 2 |
|||
.,F962 A6 9C LDX $9C |
LDX DPSW ;CHECK IF LAST BIT... |
Flag für empfangenes Byte laden |
get byte received flag |
|||
.,F964 F0 03 BEQ $F969 |
BEQ RJDJ ;...NO THEN CONTINUE |
verzweige, falls Null (Byte nicht geladen) |
if not byte received ?? |
|||
.,F966 4C 60 FA JMP $FA60 |
JMP RADJ ;...YES THEN GO FINISH BYTE |
ansonsten nach $FA60 |
store the tape character |
|||
.,F969 A6 A3 LDX $A3 |
RJDJ LDX PCNTR ;IF 9 BITS READ... |
Byte vollständig gelesen |
get EOI flag byte |
|||
.,F96B 30 1B BMI $F988 |
BMI JRAD2 ;... THEN GOTO ENDING |
verzweige, falls ja |
||||
.,F96D A2 00 LDX #$00 |
LDX #0 ;SET BIT VALUE TO ZERO |
Code für kurzer Impuls (X=0) |
||||
.,F96F 69 30 ADC #$30 |
ADC #48 ;ADD UP TO HALF WAY BETWEEN... |
zu errechneter Zeit mit $30 |
||||
.,F971 65 B0 ADC $B0 |
ADC CMP0 ;...SHORT PULSE AND SYNC PULSE |
und mit Zeitkonstante addieren |
add tape timing constant min byte |
|||
.,F973 C5 B1 CMP $B1 |
CMP TEMP ;CHECK FOR SHORT... |
größer als Zeit beim letztem Flanken ? |
compare with tape timing constant max byte |
|||
.,F975 B0 1C BCS $F993 |
BCS RADX2 ;...YES IT'S A SHORT |
verzweige wenn größer |
||||
.,F977 E8 INX |
INX ;SET BIT VALUE TO ONE |
sonst langer Impuls (X=1) |
||||
.,F978 69 26 ADC #$26 |
ADC #38 ;MOVE TO MIDDLE OF HIGH |
und wieder $26 und |
||||
.,F97A 65 B0 ADC $B0 |
ADC CMP0 |
Zeitkonstanten addieren |
add tape timing constant min byte |
|||
.,F97C C5 B1 CMP $B1 |
CMP TEMP ;CHECK FOR ONE... |
jetzt größer ? |
compare with tape timing constant max byte |
|||
.,F97E B0 17 BCS $F997 |
BCS RADL ;...YES IT'S A ONE |
verzweige, falls ja |
||||
.,F980 69 2C ADC #$2C |
ADC #44 ;MOVE TO LONGLONG |
sonst wieder $2C und |
||||
.,F982 65 B0 ADC $B0 |
ADC CMP0 |
Zeitkonstante addieren |
add tape timing constant min byte |
|||
.,F984 C5 B1 CMP $B1 |
CMP TEMP ;CHECK FOR LONGLONG... |
vergangene Zeit noch länger ? |
compare with tape timing constant max byte |
|||
.,F986 90 03 BCC $F98B |
BCC SRER ;...GREATER THAN IS ERROR |
verzweige, wenn jetzt kürzer |
||||
.,F988 4C 10 FA JMP $FA10 |
JRAD2 JMP RAD2 ;...IT'S A LONGLONG |
zu empfangenes Byte verarbeiten |
||||
.,F98B A5 B4 LDA $B4 |
SRER LDA SNSW1 ;IF NOT SYNCRONIZED... |
Flag für Timer A laden |
get the bit count |
|||
.,F98D F0 1D BEQ $F9AC |
BEQ RDBK ;...THEN NO ERROR |
verzweige, wenn Timer A nicht freigegeben |
if all done go ?? |
|||
.,F98F 85 A8 STA $A8 |
STA RER ;...ELSE FLAG RER |
Zeiger auf 'READ ERROR' setzen |
save receiver bit count in |
|||
.,F991 D0 19 BNE $F9AC |
BNE RDBK ;JMP |
unbedingter Sprung |
branch always |
|||
.,F993 E6 A9 INC $A9 |
RADX2 INC REZ ;COUNT REZ UP ON ZEROS |
Zeiger auf Impulswechsel +1 |
increment ?? start bit check flag |
|||
.,F995 B0 02 BCS $F999 |
BCS RAD5 ;JMP |
unbedingter Sprung |
||||
.,F997 C6 A9 DEC $A9 |
RADL DEC REZ ;COUNT REZ DOWN ON ONES |
Zeiger auf Impulswechsel -1 |
decrement ?? start bit check flag |
|||
.,F999 38 SEC |
RAD5 SEC ;CALC ACTUAL VALUE FOR COMPARE STORE |
Carry für Subtraktion setzen |
||||
.,F99A E9 13 SBC #$13 |
SBC #19 |
Anfangswert ($13) und |
||||
.,F99C E5 B1 SBC $B1 |
SBC TEMP ;SUBTRACT INPUT VALUE FROM CONSTANT... |
vergangene Zeit subtrahieren |
subtract tape timing constant max byte |
|||
.,F99E 65 92 ADC $92 |
ADC SVXT ;...ADD DIFFERENCE TO TEMP STORAGE... |
und mit Flag für Timing Korrektur addieren |
add timing constant for tape |
|||
.,F9A0 85 92 STA $92 |
STA SVXT ;...USED LATER TO ADJUST SOFT SERVO |
Ergebnis dort speichern |
save timing constant for tape |
|||
.,F9A2 A5 A4 LDA $A4 |
LDA FIRT ;FLIP DIPOLE FLAG |
Flag für Empfang beider |
get tape bit cycle phase |
|||
.,F9A4 49 01 EOR #$01 |
EOR #1 |
Impulse invertieren |
||||
.,F9A6 85 A4 STA $A4 |
STA FIRT |
und abspeichern |
save tape bit cycle phase |
|||
.,F9A8 F0 2B BEQ $F9D5 |
BEQ RAD3 ;SECOND HALF OF DIPOLE |
verzweige wenn beide Impulse empfangen |
||||
.,F9AA 86 D7 STX $D7 |
STX DATA ;FIRST HALF SO STORE ITS VALUE |
empfangenes Signal speichern |
||||
.,F9AC A5 B4 LDA $B4 |
RDBK LDA SNSW1 ;IF NO BYTE START... |
Flag für Timer A laden |
get the bit count |
|||
.,F9AE F0 22 BEQ $F9D2 |
BEQ RADBK ;...THEN RETURN |
verzweige wenn Timer gesperrt |
if all done go ?? |
|||
.,F9B0 AD A3 02 LDA $02A3 |
LDA KIKA26 ;CHECK TO SEE IF TIMER1 IRQD US... |
ICR in Akku |
read VIA 1 ICR shadow copy |
|||
.,F9B3 29 01 AND #$01 |
AND #$01 |
Bit 0 isolieren |
mask 0000 000x, timer A interrupt enabled |
|||
.,F9B5 D0 05 BNE $F9BC |
BNE RADKX ;...YES |
verzweige wenn Interrupt von Timer A |
if timer A is enabled go ?? |
|||
.,F9B7 AD A4 02 LDA $02A4 |
LDA STUPID ;CHECK FOR OLD T1IRQ |
Timer A abgelaufen |
read VIA 1 CRA shadow copy |
|||
.,F9BA D0 16 BNE $F9D2 |
BNE RADBK ;NO...SO EXIT ; |
nein, dann zum Interruptende |
if ?? just exit |
|||
.,F9BC A9 00 LDA #$00 |
RADKX LDA #0 ;...YES, SET DIPOLE FLAG FOR FIRST HALF |
Impulszähler |
clear A |
|||
.,F9BE 85 A4 STA $A4 |
STA FIRT |
löschen und |
clear the tape bit cycle phase |
|||
.,F9C0 8D A4 02 STA $02A4 |
STA STUPID ;SET T1IRQ FLAG |
Zeiger auf Timeout setzen |
save VIA 1 CRA shadow copy |
|||
.,F9C3 A5 A3 LDA $A3 |
LDA PCNTR ;CHECK WHERE WE ARE IN BYTE... |
prüfe ob Byte vollständig gelesen |
get EOI flag byte |
|||
.,F9C5 10 30 BPL $F9F7 |
BPL RAD4 ;...DOING DATA |
verzweige falls nein |
||||
.,F9C7 30 BF BMI $F988 |
BMI JRAD2 ;...PROCESS PARITY |
unbedingter Sprung |
||||
.,F9C9 A2 A6 LDX #$A6 |
RADP LDX #166 ;SET UP FOR LONGLONG TIMEOUT |
Initialisierungswert für Timer A |
set timimg max byte |
|||
.,F9CB 20 E2 F8 JSR $F8E2 |
JSR STT1 |
Band zum Lesen vorbereiten |
set timing |
|||
.,F9CE A5 9B LDA $9B |
LDA PRTY ;IF PARITY NOT EVEN... |
Paritätsbyte in Akku |
||||
.,F9D0 D0 B9 BNE $F98B |
BNE SRER ;...THEN GO SET ERROR |
verzweige falls parit. Fehler |
||||
.,F9D2 4C BC FE JMP $FEBC |
RADBK JMP PREND ;GO RESTORE REGS AND RTI |
Rückkehr vom Interrupt |
restore registers and exit interrupt |
|||
.,F9D5 A5 92 LDA $92 |
RAD3 LDA SVXT ;ADJUST THE SOFTWARE SERVO (CMP0) |
Timing Korrekturzeiger laden |
get timing constant for tape |
|||
.,F9D7 F0 07 BEQ $F9E0 |
BEQ ROUT1 ;NO ADJUST |
verzweige wenn Flag gelöscht |
||||
.,F9D9 30 03 BMI $F9DE |
BMI ROUT2 ;ADJUST FOR MORE BASE TIME |
verzweige wenn kleiner Null |
||||
.,F9DB C6 B0 DEC $B0 |
DEC CMP0 ;ADJUST FOR LESS BASE TIME |
Timing Konstante -1 |
decrement tape timing constant min byte |
|||
.:F9DD 2C .BYTE $2C |
.BYT $2C ;SKIP TWO BYTES |
Skip zu $F9E0 |
makes next line BIT $B0E6 |
|||
.,F9DE E6 B0 INC $B0 |
ROUT2 INC CMP0 |
Timing Konstante +1 |
increment tape timing constant min byte |
|||
.,F9E0 A9 00 LDA #$00 |
ROUT1 LDA #0 ;CLEAR DIFFERENCE VALUE |
Timing |
||||
.,F9E2 85 92 STA $92 |
STA SVXT ;CHECK FOR CONSECUTIVE LIKE VALUES IN DIPOLE... |
Korrekturzeiger löschen |
clear timing constant for tape |
|||
.,F9E4 E4 D7 CPX $D7 |
CPX DATA |
Vergleiche empfangenen Impuls mit vorherigem |
||||
.,F9E6 D0 0F BNE $F9F7 |
BNE RAD4 ;...NO, GO PROCESS INFO |
verzweige falls ungleich |
||||
.,F9E8 8A TXA |
TXA ;...YES SO CHECK THE VALUES... |
Prüfe ob kurzer Impuls empfangen |
||||
.,F9E9 D0 A0 BNE $F98B |
BNE SRER ;IF THEY WERE ONES THEN ERROR ; CONSECUTIVE ZEROS |
falls nein, verzweige |
||||
.,F9EB A5 A9 LDA $A9 |
LDA REZ ;...CHECK HOW MANY ZEROS HAVE HAPPENED |
Impulswechselzeiger laden |
get start bit check flag |
|||
.,F9ED 30 BD BMI $F9AC |
BMI RDBK ;...IF MANY DON'T CHECK |
verzweige wenn negativ |
||||
.,F9EF C9 10 CMP #$10 |
CMP #16 ;... DO WE HAVE 16 YET?... |
vergleiche mit $10 |
||||
.,F9F1 90 B9 BCC $F9AC |
BCC RDBK ;....NO SO CONTINUE |
verzweige wenn kleiner $10 |
||||
.,F9F3 85 96 STA $96 |
STA SYNO ;....YES SO FLAG SYNO (BETWEEN BLOCKS) |
sonst EOB Flag empfangen |
save cassette block synchronization number |
|||
.,F9F5 B0 B5 BCS $F9AC |
BCS RDBK ;JMP |
unbedingter Sprung |
||||
.,F9F7 8A TXA |
RAD4 TXA ;MOVE READ DATA TO .A |
Empfangenes Bit in Akku |
||||
.,F9F8 45 9B EOR $9B |
EOR PRTY ;CALCULATE PARITY |
mit Band-Parität verknüpfen |
||||
.,F9FA 85 9B STA $9B |
STA PRTY |
in Band-Parität speichern |
||||
.,F9FC A5 B4 LDA $B4 |
LDA SNSW1 ;REAL DATA?... |
Flag für Timer A laden |
||||
.,F9FE F0 D2 BEQ $F9D2 |
BEQ RADBK ;...NO SO FORGET BY EXITING |
verzweige wenn nicht frei ge- geben |
||||
.,FA00 C6 A3 DEC $A3 |
DEC PCNTR ;DEC BIT COUNT |
Speicher für Bitzähler -1 |
decrement EOI flag byte |
|||
.,FA02 30 C5 BMI $F9C9 |
BMI RADP ;IF MINUS THEN TIME FOR PARITY |
verzweige wenn Paritätsbit empfangen |
||||
.,FA04 46 D7 LSR $D7 |
LSR DATA ;SHIFT BIT FROM DATA... |
gelesenes Bit ins Carry und |
||||
.,FA06 66 BF ROR $BF |
ROR MYCH ;...INTO BYTE STORAGE (MYCH) BUFFER |
dann in $BF rollen |
parity count |
|||
.,FA08 A2 DA LDX #$DA |
LDX #218 ;SET UP FOR NEXT DIPOLE |
Initialisierungswert für Timer A ins X-Register |
set timimg max byte |
|||
.,FA0A 20 E2 F8 JSR $F8E2 |
JSR STT1 |
zur Kassettensynchronisation |
set timing |
|||
.,FA0D 4C BC FE JMP $FEBC |
JMP PREND ;RESTORE REGS AND RTI ; RAD2 - LONGLONG HANDLER (COULD BE A LONG ONE) |
Rückkehr vom Interrupt |
restore registers and exit interrupt |
|||
.,FA10 A5 96 LDA $96 |
RAD2 LDA SYNO ;HAVE WE GOTTEN BLOCK SYNC... |
Prüfe ob EOB empfangen |
get cassette block synchronization number |
|||
.,FA12 F0 04 BEQ $FA18 |
BEQ RAD2Y ;...NO |
falls nein, verzweige |
||||
.,FA14 A5 B4 LDA $B4 |
LDA SNSW1 ;CHECK IF WE'VE HAD A REAL BYTE START... |
Prüfe ob Timer A freige. |
||||
.,FA16 F0 07 BEQ $FA1F |
BEQ RAD2X ;...NO |
wenn nein, überspringe Bit Zähler Test |
||||
.,FA18 A5 A3 LDA $A3 |
RAD2Y LDA PCNTR ;ARE WE AT END OF BYTE... |
Bitzähler laden |
get EOI flag byte |
|||
.,FA1A 30 03 BMI $FA1F |
BMI RAD2X ;YES...GO ADJUST FOR LONGLONG |
verzweige falls negatv |
||||
.,FA1C 4C 97 F9 JMP $F997 |
JMP RADL ;...NO SO TREAT IT AS A LONG ONE READ |
langen Impuls verarbeiten |
||||
.,FA1F 46 B1 LSR $B1 |
RAD2X LSR TEMP ;ADJUST TIMEOUT FOR... |
vergangene Zeit seit letztem Flangen halbieren |
shift tape timing constant max byte |
|||
.,FA21 A9 93 LDA #$93 |
LDA #147 ;...LONGLONG PULSE VALUE |
und diesen Wert |
||||
.,FA23 38 SEC |
SEC |
von $93 |
||||
.,FA24 E5 B1 SBC $B1 |
SBC TEMP |
abziehen |
subtract tape timing constant max byte |
|||
.,FA26 65 B0 ADC $B0 |
ADC CMP0 |
dazu dann Timing-Konstante addieren |
add tape timing constant min byte |
|||
.,FA28 0A ASL |
ASL A |
und Ergebnis verdoppeln |
||||
.,FA29 AA TAX |
TAX ;AND SET TIMEOUT FOR LAST BIT |
Ergebnis ins X-Register |
copy timimg high byte |
|||
.,FA2A 20 E2 F8 JSR $F8E2 |
JSR STT1 |
Timing initialisieren |
set timing |
|||
.,FA2D E6 9C INC $9C |
INC DPSW ;SET BIT THROW AWAY FLAG |
Flag für Byte empfangen setzen |
||||
.,FA2F A5 B4 LDA $B4 |
LDA SNSW1 ;IF BYTE SYNCRONIZED.... |
Flag für Timer A laden |
||||
.,FA31 D0 11 BNE $FA44 |
BNE RADQ2 ;...THEN SKIP TO PASS CHAR |
verzweige falls freigegeben |
||||
.,FA33 A5 96 LDA $96 |
LDA SYNO ;THROWS OUT DATA UNTILL BLOCK SYNC... |
wurde EOB emfangen ? |
get cassette block synchronization number |
|||
.,FA35 F0 26 BEQ $FA5D |
BEQ RDBK2 ;...NO BLOCK SYNC |
verzweige wenn nicht empfangen |
||||
.,FA37 85 A8 STA $A8 |
STA RER ;FLAG DATA AS ERROR |
Flag für Lesefehler setzen |
save receiver bit count in |
|||
.,FA39 A9 00 LDA #$00 |
LDA #0 ;KILL 16 SYNC FLAG |
Flag für |
clear A |
|||
.,FA3B 85 96 STA $96 |
STA SYNO |
EOB rücksetzen |
clear cassette block synchronization number |
|||
.,FA3D A9 81 LDA #$81 |
LDA #$81 ;SET UP FOR TIMER1 INTERRUPTS |
Interrupt für |
enable timer A interrupt |
|||
.,FA3F 8D 0D DC STA $DC0D |
STA D1ICR |
Timer A freigeben |
save VIA 1 ICR |
|||
.,FA42 85 B4 STA $B4 |
STA SNSW1 ;FLAG THAT WE HAVE BYTE SYNCRONIZED ; |
und Flag für Timer A setzen |
||||
.,FA44 A5 96 LDA $96 |
RADQ2 LDA SYNO ;SAVE SYNO STATUS |
Flag für EOB laden |
get cassette block synchronization number |
|||
.,FA46 85 B5 STA $B5 |
STA DIFF |
und nach $B5 kopieren |
||||
.,FA48 F0 09 BEQ $FA53 |
BEQ RADK ;NO BLOCK SYNC, NO BYTE LOOKING |
verzweige wenn kein EOB |
||||
.,FA4A A9 00 LDA #$00 |
LDA #0 ;TURN OFF BYTE SYNC SWITCH |
Flag für Timer A |
||||
.,FA4C 85 B4 STA $B4 |
STA SNSW1 |
löschen und auch |
||||
.,FA4E A9 01 LDA #$01 |
LDA #$01 ;DISABLE TIMER1 INTERRUPTS |
Interruptflag |
disable timer A interrupt |
|||
.,FA50 8D 0D DC STA $DC0D |
STA D1ICR |
wieder löschen |
save VIA 1 ICR |
|||
.,FA53 A5 BF LDA $BF |
RADK LDA MYCH ;PASS CHARACTER TO BYTE ROUTINE |
Shift Register für Read laden |
parity count |
|||
.,FA55 85 BD STA $BD |
STA OCHAR |
und nach $BD bringen |
save RS232 parity byte |
|||
.,FA57 A5 A8 LDA $A8 |
LDA RER ;COMBINE ERROR VALUES WITH ZERO COUNT... |
Flag für Lesefehler laden |
get receiver bit count in |
|||
.,FA59 05 A9 ORA $A9 |
ORA REZ |
mit Impulswechselzeiger |
OR with start bit check flag |
|||
.,FA5B 85 B6 STA $B6 |
STA PRP ;...AND SAVE IN PRP |
verknüpfen und in Fehlercode des Bytes ablegen |
||||
.,FA5D 4C BC FE JMP $FEBC |
RDBK2 JMP PREND ;GO BACK AND GET LAST BYTE |
Rückkehr vom Interrupt |
restore registers and exit interrupt# store character |
receive next byte from cassette |
||
.,FA60 20 97 FB JSR $FB97 |
RADJ JSR NEWCH ;FINISH BYTE, CLR FLAGS |
Bitzähler für serielle Ausgabe setzen |
new tape byte setup |
|||
.,FA63 85 9C STA $9C |
STA DPSW ;CLEAR BIT THROW AWAY FLAG |
Zeiger auf Byte empfangen rücksetzen |
clear byte received flag |
|||
.,FA65 A2 DA LDX #$DA |
LDX #218 ;INITILIZE FOR NEXT DIPOLE |
Initialisierungswert Timer A |
set timimg max byte |
|||
.,FA67 20 E2 F8 JSR $F8E2 |
JSR STT1 |
Kassettensynchronisation |
set timing |
|||
.,FA6A A5 BE LDA $BE |
LDA FSBLK ;CHECK FOR LAST VALUE |
Anzahl der verbliebenen Blöcke laden |
get copies count |
|||
.,FA6C F0 02 BEQ $FA70 |
BEQ RD15 |
verzweige wenn Null |
||||
.,FA6E 85 A7 STA $A7 |
STA SHCNL ;************************************************* ;* BYTE HANDLER OF CASSETTE READ * ;* * ;* THIS PORTION OF IN LINE CODE IS PASSED THE * ;* BYTE ASSEMBLED FROM READING TAPE IN OCHAR. * ;* RER IS SET IF THE BYTE READ IS IN ERROR. * ;* REZ IS SET IF THE INTERRUPT PROGRAM IS READING* ;* ZEROS. RDFLG TELLS US WHAT WE ARE DOING. * ;* BIT 7 SAYS TO IGNORE BYTES UNTIL REZ IS SET * ;* BIT 6 SAYS TO LOAD THE BYTE. OTHERWISE RDFLG * ;* IS A COUNTDOWN AFTER SYNC. IF VERCK IS SET * ;* WE DO A COMPARE INSTEAD OF A STORE AND SET * ;* STATUS. FSBLK COUNTS THE TWO BLOCKS. PTR1 IS * ;* INDEX TO ERROR TABLE FOR PASS1. PTR2 IS INDEX* ;* TO CORRECTION TABLE FOR PASS2. * ;************************************************* ; SPERR=16 CKERR=32 SBERR=4 LBERR=8 ; |
Blockanzahl neu setzen |
save receiver input bit temporary storage |
|||
.,FA70 A9 0F LDA #$0F |
RD15 LDA #$F ; |
Maskenwert für Zählung vor dem Lesen |
||||
.,FA72 24 AA BIT $AA |
BIT RDFLG ;TEST FUNCTION MODE |
Prüfe Zeiger für Lesen von Band |
||||
.,FA74 10 17 BPL $FA8D |
BPL RD20 ;NOT WAITING FOR ZEROS ; |
verzweige wenn alle Zeichen empfangen (Ende) |
||||
.,FA76 A5 B5 LDA $B5 |
LDA DIFF ;ZEROS YET? |
Flag für EOB laden |
||||
.,FA78 D0 0C BNE $FA86 |
BNE RD12 ;YES...WAIT FOR SYNC |
verzweige wenn gültiges EOB empfangen |
||||
.,FA7A A6 BE LDX $BE |
LDX FSBLK ;IS PASS OVER? |
Anzahl der verbliebenen Blöcke laden |
get copies count |
|||
.,FA7C CA DEX |
DEX ;...IF FSBLK ZERO THEN NO ERROR (FIRST GOOD) |
Anzahl -1 |
||||
.,FA7D D0 0B BNE $FA8A |
BNE RD10 ;NO... ; |
verzweige wenn nicht Null |
if ?? restore registers and exit interrupt |
|||
.,FA7F A9 08 LDA #$08 |
LDA #LBERR |
'LONG BLOCK' error |
set short block |
|||
.,FA81 20 1C FE JSR $FE1C |
JSR UDST ;YES...LONG BLOCK ERROR |
Status setzen |
OR into serial status byte |
|||
.,FA84 D0 04 BNE $FA8A |
BNE RD10 ;BRANCH ALWAYS ; |
unbedingter Sprung zum normalen IRQ |
restore registers and exit interrupt, branch always |
|||
.,FA86 A9 00 LDA #$00 |
RD12 LDA #0 |
Flag für Lesen vom Band auf |
||||
.,FA88 85 AA STA $AA |
STA RDFLG ;NEW MODE IS WAIT FOR SYNC |
Abtastung setzen |
||||
.,FA8A 4C BC FE JMP $FEBC |
RD10 JMP PREND ;EXIT...DONE ; |
Rückkehr vom Interrupt |
restore registers and exit interrupt |
|||
.,FA8D 70 31 BVS $FAC0 |
RD20 BVS RD60 ;WE ARE LOADING |
verzweige wenn Bandzeiger auf lesen |
||||
.,FA8F D0 18 BNE $FAA9 |
BNE RD200 ;WE ARE SYNCING ; |
verzweige wenn Bandzeiger auf Zählen |
||||
.,FA91 A5 B5 LDA $B5 |
LDA DIFF ;DO WE HAVE BLOCK SYNC... |
Flag für EOB laden |
||||
.,FA93 D0 F5 BNE $FA8A |
BNE RD10 ;...YES, EXIT |
verzweige wenn EOB empfangen |
||||
.,FA95 A5 B6 LDA $B6 |
LDA PRP ;IF FIRST BYTE HAS ERROR... |
Flag für Lesefehler laden |
||||
.,FA97 D0 F1 BNE $FA8A |
BNE RD10 ;...THEN SKIP (EXIT) |
verzweige falls Fehler aufgetreten |
||||
.,FA99 A5 A7 LDA $A7 |
LDA SHCNL ;MOVE FSBLK TO CARRY... |
Anzahl der noch zu lesenden Blöcke holen |
get receiver input bit temporary storage |
|||
.,FA9B 4A LSR |
LSR A |
Bit 0 ins Carry schieben |
||||
.,FA9C A5 BD LDA $BD |
LDA OCHAR ; SHOULD BE A HEADER COUNT CHAR |
hole gelesenes Byte |
get RS232 parity byte |
|||
.,FA9E 30 03 BMI $FAA3 |
BMI RD22 ;IF NEG THEN FIRSTBLOCK DATA |
verzweige wenn es Zählbyte ist |
||||
.,FAA0 90 18 BCC $FABA |
BCC RD40 ;...EXPECTING FIRSTBLOCK DATA...YES |
verzweige wenn mehr als ein Block zu lesen |
||||
.,FAA2 18 CLC |
CLC |
lösche Carry um nicht zu verzweigen |
||||
.,FAA3 B0 15 BCS $FABA |
RD22 BCS RD40 ;EXPECTING SECOND BLOCK?...YES |
verzweige falls nur ein Block zu lesen |
||||
.,FAA5 29 0F AND #$0F |
AND #$F ;MASK OFF HIGH STORE HEADER COUNT... |
Bits 0 bis 3 isolieren |
||||
.,FAA7 85 AA STA $AA |
STA RDFLG ;...IN MODE FLAG (HAVE CORRECT BLOCK) |
und für Zählung speichern |
||||
.,FAA9 C6 AA DEC $AA |
RD200 DEC RDFLG ;WAIT UNTILL WE GET REAL DATA... |
alle Synchrrnisationsbytes empfangen |
||||
.,FAAB D0 DD BNE $FA8A |
BNE RD10 ;...9876543210 REAL |
wenn nein verzweige |
||||
.,FAAD A9 40 LDA #$40 |
LDA #$40 ;NEXT UP IS REAL DATA... |
Bandzeiger auf |
||||
.,FAAF 85 AA STA $AA |
STA RDFLG ;...SET DATA MODE |
lesen stellen |
||||
.,FAB1 20 8E FB JSR $FB8E |
JSR RD300 ;GO SETUP ADDRESS POINTERS |
Ein/Ausgabe Adresse kopieren |
copy I/O start address to buffer address |
|||
.,FAB4 A9 00 LDA #$00 |
LDA #0 ;DEBUG CODE################################################## |
Flag für |
||||
.,FAB6 85 AB STA $AB |
STA SHCNH |
Leseprüfsumme löschen |
||||
.,FAB8 F0 D0 BEQ $FA8A |
BEQ RD10 ;JMP TO CONTINUE |
unbedingter Sprung |
||||
.,FABA A9 80 LDA #$80 |
RD40 LDA #$80 ;WE WANT TO... |
Bandzeiger |
||||
.,FABC 85 AA STA $AA |
STA RDFLG ;IGNORE BYTES MODE |
auf Ende stellen |
||||
.,FABE D0 CA BNE $FA8A |
BNE RD10 ;JMP |
unbedingter Sprung |
restore registers and exit interrupt, branch always |
|||
.,FAC0 A5 B5 LDA $B5 |
RD60 LDA DIFF ;CHECK FOR END OF BLOCK... |
Flag für EOB laden |
||||
.,FAC2 F0 0A BEQ $FACE |
BEQ RD70 ;...OKAY ; |
verzweige wenn nicht gesetzt |
||||
.,FAC4 A9 04 LDA #$04 |
LDA #SBERR ;SHORT BLOCK ERROR |
'SHORT BLOCK’ error |
||||
.,FAC6 20 1C FE JSR $FE1C |
JSR UDST |
Status setzen |
OR into serial status byte |
|||
.,FAC9 A9 00 LDA #$00 |
LDA #0 ;FORCE RDFLG FOR AN END |
Code für Lesezeiger auf "Abtasten" |
||||
.,FACB 4C 4A FB JMP $FB4A |
JMP RD161 |
setzen, unbedingter Sprung |
||||
.,FACE 20 D1 FC JSR $FCD1 |
RD70 JSR CMPSTE ;CHECK FOR END OF STORAGE AREA |
Endadresse schon erreicht ? |
check read/write pointer, return Cb = 1 if pointer >= end |
|||
.,FAD1 90 03 BCC $FAD6 |
BCC *+5 ;NOT DONE YET |
nein dann verzweige |
||||
.,FAD3 4C 48 FB JMP $FB48 |
JMP RD160 |
zu Read Ende für Block |
||||
.,FAD6 A6 A7 LDX $A7 |
LDX SHCNL ;CHECK WHICH PASS... |
nur noch |
get receiver input bit temporary storage |
|||
.,FAD8 CA DEX |
DEX |
ein Block zu lesen |
||||
.,FAD9 F0 2D BEQ $FB08 |
BEQ RD58 ;...SECOND PASS |
verzweige wenn ja (Pass 2) |
||||
.,FADB A5 93 LDA $93 |
LDA VERCK ;CHECK IF LOAD OR VERIFY... |
Load/Verify-Flag |
get load/verify flag |
|||
.,FADD F0 0C BEQ $FAEB |
BEQ RD80 ;...LOADING |
verzweige wenn Load |
if load go ?? |
|||
.,FADF A0 00 LDY #$00 |
LDY #0 ;...JUST VERIFYING |
Zähler auf Null setzen |
clear index |
|||
.,FAE1 A5 BD LDA $BD |
LDA OCHAR |
gelesenes Byte |
get RS232 parity byte |
|||
.,FAE3 D1 AC CMP ($AC),Y |
CMP (SAL)Y ;COMPARE WITH DATA IN PET |
vergleichen |
||||
.,FAE5 F0 04 BEQ $FAEB |
BEQ RD80 ;...GOOD SO CONTINUE |
verzweige wenn Übereinstim- mung |
||||
.,FAE7 A9 01 LDA #$01 |
LDA #1 ;...BAD SO FLAG... |
Fehlerflag |
||||
.,FAE9 85 B6 STA $B6 |
STA PRP ;...AS AN ERROR ; STORE BAD LOCATIONS FOR SECOND PASS RE-TRY |
setzen |
||||
.,FAEB A5 B6 LDA $B6 |
RD80 LDA PRP ;CHK FOR ERRORS... |
Fehlerflag laden |
||||
.,FAED F0 4B BEQ $FB3A |
BEQ RD59 ;...NO ERRORS |
verzweige wenn kein Fehler aufgetreten |
||||
.,FAEF A2 3D LDX #$3D |
LDX #61 ;MAX ALLOWED IS 30 |
bereits 31 Fehler |
||||
.,FAF1 E4 9E CPX $9E |
CPX PTR1 ;ARE WE AT MAX?... |
aufgetreten |
||||
.,FAF3 90 3E BCC $FB33 |
BCC RD55 ;...YES, FLAG AS SECOND PASS ERROR |
verzweige wenn weniger Fehler |
||||
.,FAF5 A6 9E LDX $9E |
LDX PTR1 ;GET INDEX INTO BAD... |
Index für Lesefehler |
||||
.,FAF7 A5 AD LDA $AD |
LDA SAH ;...AND STORE THE BAD LOCATION |
laufender Adressbyte HIGH |
||||
.,FAF9 9D 01 01 STA $0101,X |
STA BAD+1,X ;...IN BAD TABLE |
im Stack speichern |
||||
.,FAFC A5 AC LDA $AC |
LDA SAL |
Adressbyte LOW |
||||
.,FAFE 9D 00 01 STA $0100,X |
STA BAD,X |
für spätere Korrektur ebenfalls im Stack speichern |
||||
.,FB01 E8 INX |
INX ;ADVANCE POINTER TO NEXT |
Zeiger auf nachfolgende |
||||
.,FB02 E8 INX |
INX |
freie Stelle setzen |
||||
.,FB03 86 9E STX $9E |
STX PTR1 |
und abspeichern |
||||
.,FB05 4C 3A FB JMP $FB3A |
JMP RD59 ;GO STORE CHARACTER ; CHECK BAD TABLE FOR RE-TRY (SECOND PASS) |
weitermachen |
||||
.,FB08 A6 9F LDX $9F |
RD58 LDX PTR2 ;HAVE WE DONE ALL IN THE TABLE?... |
bereits alle Lesefehler |
||||
.,FB0A E4 9E CPX $9E |
CPX PTR1 |
korrigiert ? |
||||
.,FB0C F0 35 BEQ $FB43 |
BEQ RD90 ;...YES |
verzweige falls ja |
||||
.,FB0E A5 AC LDA $AC |
LDA SAL ;SEE IF THIS IS NEXT IN THE TABLE... |
Adressbyte LOW laden |
||||
.,FB10 DD 00 01 CMP $0100,X |
CMP BAD,X |
mit fehlerhaftem Adressbyte LOW vergleichen |
||||
.,FB13 D0 2E BNE $FB43 |
BNE RD90 ;...NO |
verzweige falls nicht gefunden |
||||
.,FB15 A5 AD LDA $AD |
LDA SAH |
Adressbyte HIGH laden |
||||
.,FB17 DD 01 01 CMP $0101,X |
CMP BAD+1,X |
mit fehlerhaftem Adressbyte HIGH vergleichen |
||||
.,FB1A D0 27 BNE $FB43 |
BNE RD90 ;...NO |
verzweige wenn nicht gefunden |
||||
.,FB1C E6 9F INC $9F |
INC PTR2 ;WE FOUND NEXT ONE, SO ADVANCE POINTER |
Korrekturzähler |
||||
.,FB1E E6 9F INC $9F |
INC PTR2 |
Pass 2 um zwei erhöhen |
||||
.,FB20 A5 93 LDA $93 |
LDA VERCK ;DOING A LOAD OR VERIFY?... |
Verify-Flag gesetzt |
get load/verify flag |
|||
.,FB22 F0 0B BEQ $FB2F |
BEQ RD52 ;...LOADING |
verzweige wenn nicht gesetzt |
if load ?? |
|||
.,FB24 A5 BD LDA $BD |
LDA OCHAR ;...VERIFYING, SO CHECK |
gelesenes Byte laden |
get RS232 parity byte |
|||
.,FB26 A0 00 LDY #$00 |
LDY #0 |
Zähler auf Null setzen |
||||
.,FB28 D1 AC CMP ($AC),Y |
CMP (SAL)Y |
mit Speicherinhalt verglei- chen |
||||
.,FB2A F0 17 BEQ $FB43 |
BEQ RD90 ;...OKAY |
verzweige wenn gleich, dann nächstes Byte |
||||
.,FB2C C8 INY |
INY ;MAKE .Y= 1 |
Flag für |
||||
.,FB2D 84 B6 STY $B6 |
STY PRP ;FLAG IT AS AN ERROR |
Fehler setzen |
||||
.,FB2F A5 B6 LDA $B6 |
RD52 LDA PRP ;A SECOND PASS ERROR?... |
Fehlerflag testen |
||||
.,FB31 F0 07 BEQ $FB3A |
BEQ RD59 ;...NO ;SECOND PASS ERR |
verzweige wenn kein Fehler |
||||
.,FB33 A9 10 LDA #$10 |
RD55 LDA #SPERR |
'SECOND PASS' error |
||||
.,FB35 20 1C FE JSR $FE1C |
JSR UDST |
Status setzen |
OR into serial status byte |
|||
.,FB38 D0 09 BNE $FB43 |
BNE RD90 ;JMP |
und nächstes Byte verarbeiten |
||||
.,FB3A A5 93 LDA $93 |
RD59 LDA VERCK ;LOAD OR VERIFY?... |
Verify-Flag laden |
get load/verify flag |
|||
.,FB3C D0 05 BNE $FB43 |
BNE RD90 ;...VERIFY, DON'T STORE |
verzweige wenn gesetzt |
if verify go ?? |
|||
.,FB3E A8 TAY |
TAY ;MAKE Y ZERO |
Zeiger löschen |
||||
.,FB3F A5 BD LDA $BD |
LDA OCHAR |
gelesenes Byte |
get RS232 parity byte |
|||
.,FB41 91 AC STA ($AC),Y |
STA (SAL)Y ;STORE CHARACTER |
speichern |
||||
.,FB43 20 DB FC JSR $FCDB |
RD90 JSR INCSAL ;INCREMENT ADDR. |
Adresszeiger erhöhen |
increment read/write pointer |
|||
.,FB46 D0 43 BNE $FB8B |
BNE RD180 ;BRANCH ALWAYS |
Rückkehr vom Interrupt |
restore registers and exit interrupt, branch always |
|||
.,FB48 A9 80 LDA #$80 |
RD160 LDA #$80 ;SET MODE SKIP NEXT DATA |
Flag für Lesen |
||||
.,FB4A 85 AA STA $AA |
RD161 STA RDFLG ; ; MODIFY FOR C64 6526'S ; |
auf Ende |
||||
.,FB4C 78 SEI |
SEI ;PROTECT CLEARING OF T1 INFORMATION |
Interrupt verhindern |
||||
.,FB4D A2 01 LDX #$01 |
LDX #$01 |
IRQ vom |
disable timer A interrupt |
|||
.,FB4F 8E 0D DC STX $DC0D |
STX D1ICR ;CLEAR T1 ENABLE... |
Timer A verhindern |
save VIA 1 ICR |
|||
.,FB52 AE 0D DC LDX $DC0D |
LDX D1ICR ;CLEAR THE INTERRUPT |
IRQ-Flag löschen |
read VIA 1 ICR |
|||
.,FB55 A6 BE LDX $BE |
LDX FSBLK ;DEC FSBLK FOR NEXT PASS... |
Pass-Zähler |
get copies count |
|||
.,FB57 CA DEX |
DEX |
erniedrigen |
||||
.,FB58 30 02 BMI $FB5C |
BMI RD167 ;WE ARE DONE...FSBLK=0 |
verzweige wenn Null gewesen |
||||
.,FB5A 86 BE STX $BE |
STX FSBLK ;...ELSE FSBLK=NEXT |
Passzähler merken |
save copies count |
|||
.,FB5C C6 A7 DEC $A7 |
RD167 DEC SHCNL ;DEC PASS CALC... |
Blockzähler vermindern |
decrement receiver input bit temporary storage |
|||
.,FB5E F0 08 BEQ $FB68 |
BEQ RD175 ;...ALL DONE |
verzweige wenn Null |
||||
.,FB60 A5 9E LDA $9E |
LDA PTR1 ;CHECK FOR FIRST PASS ERRORS... |
Fehler in Pass 1 aufgetre- ten ? |
||||
.,FB62 D0 27 BNE $FB8B |
BNE RD180 ;...YES SO CONTINUE |
ja, Rückkehr vom Interrupt |
if ?? restore registers and exit interrupt |
|||
.,FB64 85 BE STA $BE |
STA FSBLK ;CLEAR FSBLK IF NO ERRORS... |
kein Block mehr zu verarbei- ten |
save copies count |
|||
.,FB66 F0 23 BEQ $FB8B |
BEQ RD180 ;JMP TO EXIT |
Rückkehr vom Interrupt |
restore registers and exit interrupt, branch always |
|||
.,FB68 20 93 FC JSR $FC93 |
RD175 JSR TNIF ;READ IT ALL...EXIT |
ein Pass beendet |
restore everything for STOP |
|||
.,FB6B 20 8E FB JSR $FB8E |
JSR RD300 ;RESTORE SAL & SAH |
Adresse wieder auf Programm- anfang |
copy I/O start address to buffer address |
|||
.,FB6E A0 00 LDY #$00 |
LDY #0 ;SET SHCNH TO ZERO... |
Zähler auf Null setzen |
clear index |
|||
.,FB70 84 AB STY $AB |
STY SHCNH ;...USED TO CALC PARITY BYTE ; ;COMPUTE PARITY OVER LOAD ; |
Checksumme löschen |
clear checksum |
|||
.,FB72 B1 AC LDA ($AC),Y |
VPRTY LDA (SAL)Y ;CALC BLOCK BCC |
Programm |
get byte from buffer |
|||
.,FB74 45 AB EOR $AB |
EOR SHCNH |
Checksumme berechnen |
XOR with checksum |
|||
.,FB76 85 AB STA $AB |
STA SHCNH |
und speichern |
save new checksum |
|||
.,FB78 20 DB FC JSR $FCDB |
JSR INCSAL ;INCREMENT ADDRESS |
Adresszeiger erhöhen |
increment read/write pointer |
|||
.,FB7B 20 D1 FC JSR $FCD1 |
JSR CMPSTE ;TEST AGAINST END |
Endadresse schon erreicht ? |
check read/write pointer, return Cb = 1 if pointer >= end |
|||
.,FB7E 90 F2 BCC $FB72 |
BCC VPRTY ;NOT DONE YET... |
nein, weiter vergleichen |
loop if not at end |
|||
.,FB80 A5 AB LDA $AB |
LDA SHCNH ;CHECK FOR BCC CHAR MATCH... |
berechnete Checksumme |
get computed checksum |
|||
.,FB82 45 BD EOR $BD |
EOR OCHAR |
mit Checksumme vom Band vergleichen |
compare with stored checksum ?? |
|||
.,FB84 F0 05 BEQ $FB8B |
BEQ RD180 ;...YES, EXIT ;CHKSUM ERROR |
Checksumme gleich , dann ok |
if checksum ok restore registers and exit interrupt |
|||
.,FB86 A9 20 LDA #$20 |
LDA #CKERR |
'CHECKSUM' error |
else set checksum error |
|||
.,FB88 20 1C FE JSR $FE1C |
JSR UDST |
Status setzen |
OR into the serial status byte |
|||
.,FB8B 4C BC FE JMP $FEBC |
RD180 JMP PREND |
Rückkehr vom Interruptlaufenden Zeiger aufProgrammstart |
restore registers and exit interruptcopy I/O start address to buffer address |
move save/load address into $AC/$AD |
||
.,FB8E A5 C2 LDA $C2 |
RD300 LDA STAH ; RESTORE STARTING ADDRESS... |
Startadresse |
get I/O start address high byte |
|||
.,FB90 85 AD STA $AD |
STA SAH ;...POINTERS (SAH & SAL) |
$C1/$C2 |
set buffer address high byte |
|||
.,FB92 A5 C1 LDA $C1 |
LDA STAL |
nach $AC/$AD |
get I/O start address low byte |
|||
.,FB94 85 AC STA $AC |
STA SAL |
speichern |
set buffer address low byte |
|||
.,FB96 60 RTS |
RTS |
RücksprungBitzähler für serielleAusgabe setzen |
new tape byte setup |
initalise cassette read/write variables |
||
.,FB97 A9 08 LDA #$08 |
NEWCH LDA #8 ;SET UP FOR 8 BITS+PARITY |
Zähler für 8 Bits |
eight bits to do |
|||
.,FB99 85 A3 STA $A3 |
STA PCNTR |
Nach $A3 |
set bit count |
|||
.,FB9B A9 00 LDA #$00 |
LDA #0 ;INITILIZE... |
Akku mit $00 laden |
clear A |
|||
.,FB9D 85 A4 STA $A4 |
STA FIRT ;..DIPOLE COUNTER |
Bit-Impuls-Flag löschen |
clear tape bit cycle phase |
|||
.,FB9F 85 A8 STA $A8 |
STA RER ;..ERROR FLAG |
Lesefehler Byte löschen |
clear start bit first cycle done flag |
|||
.,FBA1 85 9B STA $9B |
STA PRTY ;..PARITY BIT |
Parity-Bit löschen |
clear byte parity |
|||
.,FBA3 85 A9 STA $A9 |
STA REZ ;..ZERO COUNT |
Impulswechsel-Flag löschen |
clear start bit check flag, set no start bit yet |
|||
.,FBA5 60 RTS |
RTS ;.A=0 ON RETURN .END .LIB WRITE; CASSETTE INFO - FSBLK IS BLOCK COUNTER FOR RECORD; FSBLK = 2 -FIRST HEADER ; = 1 -FIRST DATA ; = 0 -SECOND DATA ; ; WRITE - TOGGLE WRITE BIT ACCORDING TO LSB IN OCHAR ; |
RücksprungEin Bit auf Band schreiben |
send lsb from tape write byte to tapethis routine tests the least significant bit in the tape write byte and sets VIA 2 T2depending on the state of the bit. if the bit is a 1 a time of $00B0 cycles is set, if the bot is a 0 a time of $0060 cycles is set. note that this routine does not shift the bits of the tape write byte but uses a copy of that byte, the byte itself is shifted elsewhere |
schedule CIA1 timer B andinvert casette write line |
||
.,FBA6 A5 BD LDA $BD |
WRITE LDA OCHAR ;SHIFT BIT TO WRITE INTO CARRY |
Bit in $BD |
get tape write byte |
|||
.,FBA8 4A LSR |
LSR A |
Bit 0 in Carry |
shift lsb into Cb |
|||
.,FBA9 A9 60 LDA #$60 |
LDA #96 ;...C CLR WRITE SHORT |
Zeit für '0' Bit |
set time constant low byte for bit = 0 |
|||
.,FBAB 90 02 BCC $FBAF |
BCC WRT1 |
verzweige falls Carry=0 |
branch if bit was 0 set time constant for bit = 1 and toggle tape |
|||
.,FBAD A9 B0 LDA #$B0 |
WRTW LDA #176 ;...C SET WRITE LONG |
Zeit für '1' Bit |
set time constant low byte for bit = 1 write time constant and toggle tape |
|||
.,FBAF A2 00 LDX #$00 |
WRT1 LDX #0 ;SET AND STORE TIME |
HIGH-Byte Timerwert laden |
set time constant high byte write time constant and toggle tape |
|||
.,FBB1 8D 06 DC STA $DC06 |
WRTX STA D1T2L |
Timer B LOW |
save VIA 1 timer B low byte |
|||
.,FBB4 8E 07 DC STX $DC07 |
STX D1T2H |
Timer B HIGH |
save VIA 1 timer B high byte |
|||
.,FBB7 AD 0D DC LDA $DC0D |
LDA D1ICR ;CLEAR IRQ |
Interrupt-Flag löschen |
read VIA 1 ICR |
|||
.,FBBA A9 19 LDA #$19 |
LDA #$19 ;ENABLE TIMER (ONE-SHOT) |
Timer |
load timer B, timer B single shot, start timer B |
|||
.,FBBC 8D 0F DC STA $DC0F |
STA D1CRB |
B starten |
save VIA 1 CRB |
|||
.,FBBF A5 01 LDA $01 |
LDA R6510 ;TOGGLE WRITE BIT |
Tape-Write-Bit laden |
read the 6510 I/O port |
|||
.,FBC1 49 08 EOR #$08 |
EOR #$08 |
Ausgabe-Bit für Band invertieren |
toggle tape out bit |
|||
.,FBC3 85 01 STA $01 |
STA R6510 |
und speichern |
save the 6510 I/O port |
|||
.,FBC5 29 08 AND #$08 |
AND #$08 ;LEAVE ONLY WRITE BIT |
augenblicklichen Pegel merken |
mask tape out bit |
|||
.,FBC7 60 RTS |
RTS ; |
flag block done and exit interrupt |
IRQ routine for cassette write B |
|||
.,FBC8 38 SEC |
WRTL3 SEC ;FLAG PRP FOR END OF BLOCK |
Block-Write-Flag |
set carry flag |
|||
.,FBC9 66 B6 ROR $B6 |
ROR PRP |
Negativ |
set buffer address high byte negative, flag all sync, data and checksum bytes written |
|||
.,FBCB 30 3C BMI $FC09 |
BMI WRT3 ; JMP ; ; WRTN - CALLED AT THE END OF EACH BYTE ; TO WRITE A LONG RER REZ ; HHHHHHLLLLLLHHHLLL... ; |
Rückkehr vom InterruptInterrupt-Routine für Bandschreiben |
restore registers and exit interrupt, branch alwaystape write IRQ routinethis is the routine that writes the bits to the tape. it is called each time VIA 2 T2times out and checks if the start bit is done, if so checks if the data bits are done, if so it checks if the byte is done, if so it checks if the synchronisation bytes are done, if so it checks if the data bytes are done, if so it checks if the checksum byte is done, if so it checks if both the load and verify copies have been done, if so it stops the tape |
|||
.,FBCD A5 A8 LDA $A8 |
WRTN LDA RER ;CHECK FOR ONE LONG |
falls 'Byte'-Impuls ge- |
get start bit first cycle done flag |
|||
.,FBCF D0 12 BNE $FBE3 |
BNE WRTN1 |
schrieben, dann verzweige |
if first cycle done go do rest of byte each byte sent starts with two half cycles of $0110 ststem clocks and the whole block ends with two more such half cycles |
|||
.,FBD1 A9 10 LDA #$10 |
LDA #16 ;WRITE A LONG BIT |
Timer auf |
set first start cycle time constant low byte |
|||
.,FBD3 A2 01 LDX #$01 |
LDX #1 |
$110 (272) |
set first start cycle time constant high byte |
|||
.,FBD5 20 B1 FB JSR $FBB1 |
JSR WRTX |
Takt auf Band schreiben |
write time constant and toggle tape |
|||
.,FBD8 D0 2F BNE $FC09 |
BNE WRT3 |
Rückkehr vom Interrupt |
if first half cycle go restore registers and exit interrupt |
|||
.,FBDA E6 A8 INC $A8 |
INC RER |
'1' Byte-Write-Flag setzen |
set start bit first start cycle done flag |
|||
.,FBDC A5 B6 LDA $B6 |
LDA PRP ;IF END OF BLOCK(BIT SET BY WRTL3)... |
falls Block-Write-Flag positiv, dann |
get buffer address high byte |
|||
.,FBDE 10 29 BPL $FC09 |
BPL WRT3 ;...NO END CONTINUE |
Rückkehr vom Interrupt |
if block not complete go restore registers and exit interrupt. the end of a block is indicated by the tape buffer high byte b7 being set to 1 |
|||
.,FBE0 4C 57 FC JMP $FC57 |
JMP WRNC ;...END ...FINISH OFF ; |
zweiten Block schreiben |
else do tape routine, block complete exit continue tape byte write. the first start cycle, both half cycles of it, is complete so the routine drops straight through to here |
|||
.,FBE3 A5 A9 LDA $A9 |
WRTN1 LDA REZ ;CHECK FOR A ONE BIT |
falls '1' Bit gesezt |
get start bit check flag |
|||
.,FBE5 D0 09 BNE $FBF0 |
BNE WRTN2 |
dann verzweige |
if the start bit is complete go send the byte bits after the two half cycles of $0110 ststem clocks the start bit is completed with two half cycles of $00B0 system clocks. this is the same as the first part of a 1 bit |
|||
.,FBE7 20 AD FB JSR $FBAD |
JSR WRTW |
'1' Bit schreiben |
set time constant for bit = 1 and toggle tape |
|||
.,FBEA D0 1D BNE $FC09 |
BNE WRT3 |
Rückkehr vom Interrupt |
if first half cycle go restore registers and exit interrupt |
|||
.,FBEC E6 A9 INC $A9 |
INC REZ |
'1' Bit-Flag setzen |
set start bit check flag |
|||
.,FBEE D0 19 BNE $FC09 |
BNE WRT3 ; |
Rückkehr vom Interrupt |
restore registers and exit interrupt, branch always continue tape byte write. the start bit, both cycles of it, is complete so the routine drops straight through to here. now the cycle pairs for each bit, and the parity bit, are sent |
|||
.,FBF0 20 A6 FB JSR $FBA6 |
WRTN2 JSR WRITE |
Bit auf Band schreiben |
send lsb from tape write byte to tape |
|||
.,FBF3 D0 14 BNE $FC09 |
BNE WRT3 ;ON BIT LOW EXIT |
Rückkehr vom Interrupt |
if first half cycle go restore registers and exit interrupt else two half cycles have been done |
|||
.,FBF5 A5 A4 LDA $A4 |
LDA FIRT ;CHECK FOR FIRST OF DIPOLE |
Bit-Impulsflag laden |
get tape bit cycle phase |
|||
.,FBF7 49 01 EOR #$01 |
EOR #1 |
Bit 0 invertieren |
toggle b0 |
|||
.,FBF9 85 A4 STA $A4 |
STA FIRT |
und speichern |
save tape bit cycle phase |
|||
.,FBFB F0 0F BEQ $FC0C |
BEQ WRT2 ;DIPOLE DONE |
falls null, dann verzweige |
if bit cycle phase complete go setup for next bit each bit is written as two full cycles. a 1 is sent as a full cycle of $0160 system clocks then a full cycle of $00C0 system clocks. a 0 is sent as a full cycle of $00C0 system clocks then a full cycle of $0160 system clocks. to do this each bit from the write byte is inverted during the second bit cycle phase. as the bit is inverted it is also added to the, one bit, parity count for this byte |
|||
.,FBFD A5 BD LDA $BD |
LDA OCHAR ;FLIPS BIT FOR COMPLEMENTARY RIGHT |
Bit-SHIFT-Register laden |
get tape write byte |
|||
.,FBFF 49 01 EOR #$01 |
EOR #1 |
Bit für Ausgabe invertieren |
invert bit being sent |
|||
.,FC01 85 BD STA $BD |
STA OCHAR |
und speichern |
save tape write byte |
|||
.,FC03 29 01 AND #$01 |
AND #1 ;TOGGLE PARITY |
Bit holen und mit |
mask b0 |
|||
.,FC05 45 9B EOR $9B |
EOR PRTY |
Parity-Bit verknüpfen |
EOR with tape write byte parity bit |
|||
.,FC07 85 9B STA $9B |
STA PRTY |
und speichern |
save tape write byte parity bit |
|||
.,FC09 4C BC FE JMP $FEBC |
WRT3 JMP PREND ;RESTORE REGS AND RTI EXIT ; |
Rückkehr vom Interrupt |
restore registers and exit interrupt the bit cycle phase is complete so shift out the just written bit and test for byte end |
|||
.,FC0C 46 BD LSR $BD |
WRT2 LSR OCHAR ;MOVE TO NEXT BIT |
nächstes Bit in Position 0 |
shift bit out of tape write byte |
|||
.,FC0E C6 A3 DEC $A3 |
DEC PCNTR ;DEC COUNTER FOR # OF BITS |
Bitzähler erniedrigen |
decrement tape write bit count |
|||
.,FC10 A5 A3 LDA $A3 |
LDA PCNTR ;CHECK FOR 8 BITS SENT... |
und laden |
get tape write bit count |
|||
.,FC12 F0 3A BEQ $FC4E |
BEQ WRT4 ;...IF YES MOVE IN PARITY |
nächstes Bit ausgeben |
if all the data bits have been written go setup for sending the parity bit next and exit the interrupt |
|||
.,FC14 10 F3 BPL $FC09 |
BPL WRT3 ;...ELSE SEND REST ; |
Rückkehr vom Interrupt |
if all the data bits are not yet sent just restore the registers and exit the interrupt do next tape byte the byte is complete. the start bit, data bits and parity bit have been written to the tape so setup for the next byte |
|||
.,FC16 20 97 FB JSR $FB97 |
WRTS JSR NEWCH ;CLEAN UP COUNTERS |
Bitzähler wieder auf 8 setzen |
new tape byte setup |
|||
.,FC19 58 CLI |
CLI ;ALLOW FOR INTERRUPTS TO NEST |
Interrupt freigeben |
enable the interrupts |
|||
.,FC1A A5 A5 LDA $A5 |
LDA CNTDN ;ARE WE WRITING HEADER COUNTERS?... |
Falls Synchronbytes geschrie- ben |
get cassette synchronization character count |
|||
.,FC1C F0 12 BEQ $FC30 |
BEQ WRT6 ;...NO ; WRITE HEADER COUNTERS (9876543210 TO HELP WITH READ) |
dann verzweige |
if synchronisation characters done go do block data at the start of each block sent to tape there are a number of synchronisation bytes that count down to the actual data. the commodore tape system saves two copies of all the tape data, the first is loaded and is indicated by the synchronisation bytes having b7 set, and the second copy is indicated by the synchronisation bytes having b7 clear. the sequence goes $09, $08, ..... $02, $01, data bytes |
|||
.,FC1E A2 00 LDX #$00 |
LDX #0 ;CLEAR BCC |
Prüfsumme |
clear X |
|||
.,FC20 86 D7 STX $D7 |
STX DATA |
löschen |
clear checksum byte |
|||
.,FC22 C6 A5 DEC $A5 |
WRTS1 DEC CNTDN |
Zähler vermindern |
decrement cassette synchronization byte count |
|||
.,FC24 A6 BE LDX $BE |
LDX FSBLK ;CHECK FOR FIRST BLOCK HEADER |
noch zu schreibende Blockanzahl laden |
get cassette copies count |
|||
.,FC26 E0 02 CPX #$02 |
CPX #2 |
falls erster Block nicht |
compare with load block indicator |
|||
.,FC28 D0 02 BNE $FC2C |
BNE WRT61 ;...NO |
geschrieben, dann verzweige |
branch if not the load block |
|||
.,FC2A 09 80 ORA #$80 |
ORA #$80 ;...YES MARK FIRST BLOCK HEADER |
Bit 7 setzen |
this is the load block so make the synchronisation count go $89, $88, ..... $82, $81 |
|||
.,FC2C 85 BD STA $BD |
WRT61 STA OCHAR ;WRITE CHARACTERS IN HEADER |
und speichern |
save the synchronisation byte as the tape write byte |
|||
.,FC2E D0 D9 BNE $FC09 |
BNE WRT3 ; |
Rückkehr vom Interrupt |
restore registers and exit interrupt, branch always the synchronization bytes have been done so now check and do the actual block data |
|||
.,FC30 20 D1 FC JSR $FCD1 |
WRT6 JSR CMPSTE ;COMPARE START:END |
Endadresse schon erreicht ? |
check read/write pointer, return Cb = 1 if pointer >= end |
|||
.,FC33 90 0A BCC $FC3F |
BCC WRT7 ;NOT DONE |
falls kleiner, dann weiterschreiben |
if not all done yet go get the byte to send |
|||
.,FC35 D0 91 BNE $FBC8 |
BNE WRTL3 ;GO MARK END |
falls ungleich, dann Block-Write-Flag setzen |
if pointer > end go flag block done and exit interrupt else the block is complete, it only remains to write the checksum byte to the tape so setup for that |
|||
.,FC37 E6 AD INC $AD |
INC SAH |
HIGH-Byte ungleich machen |
increment buffer pointer high byte, this means the block done branch will always be taken next time without having to worry about the low byte wrapping to zero |
|||
.,FC39 A5 D7 LDA $D7 |
LDA DATA ;WRITE OUT BCC |
Prüfsumme laden |
get checksum byte |
|||
.,FC3B 85 BD STA $BD |
STA OCHAR |
und in SHIFT-Flag speichern |
save checksum as tape write byte |
|||
.,FC3D B0 CA BCS $FC09 |
BCS WRT3 ;JMP ; |
Rückkehr vom Interrupt |
restore registers and exit interrupt, branch always the block isn't finished so get the next byte to write to tape |
|||
.,FC3F A0 00 LDY #$00 |
WRT7 LDY #0 ;GET NEXT CHARACTER |
Zähler auf Null |
clear index |
|||
.,FC41 B1 AC LDA ($AC),Y |
LDA (SAL)Y |
zu schreibendes Byte laden |
get byte from buffer |
|||
.,FC43 85 BD STA $BD |
STA OCHAR ;STORE IN OUTPUT CHARACTER |
in SHIFT-Flag bringen |
save as tape write byte |
|||
.,FC45 45 D7 EOR $D7 |
EOR DATA ;UPDATE BCC |
Prüfsumme |
XOR with checksum byte |
|||
.,FC47 85 D7 STA $D7 |
STA DATA |
bilden |
save new checksum byte |
|||
.,FC49 20 DB FC JSR $FCDB |
JSR INCSAL ;INCREMENT FETCH ADDRESS |
Adresszeiger erhöhen |
increment read/write pointer |
|||
.,FC4C D0 BB BNE $FC09 |
BNE WRT3 ;BRANCH ALWAYS ; |
Rückkehr vom Interrupt |
restore registers and exit interrupt, branch always set parity as next bit and exit interrupt |
|||
.,FC4E A5 9B LDA $9B |
WRT4 LDA PRTY ;MOVE PARITY INTO OCHAR... |
Parity-Bit |
get parity bit |
|||
.,FC50 49 01 EOR #$01 |
EOR #1 |
invertieren |
toggle it |
|||
.,FC52 85 BD STA $BD |
STA OCHAR ;...TO BE WRITTEN AS NEXT BIT |
und ins SHIFT-Flag speichern |
save as tape write byte |
|||
.,FC54 4C BC FE JMP $FEBC |
WRTBK JMP PREND ;RESTORE REGS AND RTI EXIT ; |
Rückkehr vom Interrupt |
restore registers and exit interrupt tape routine, block complete exit |
|||
.,FC57 C6 BE DEC $BE |
WRNC DEC FSBLK ;CHECK FOR END |
Zähler für Blocks erniedrigen |
decrement copies remaining to read/write |
|||
.,FC59 D0 03 BNE $FC5E |
BNE WREND ;...BLOCK ONLY |
falls noch ein Block, |
branch if more to do |
|||
.,FC5B 20 CA FC JSR $FCCA |
JSR TNOF ;...WRITE, SO TURN OFF MOTOR |
dann Bandmotor aus |
stop the cassette motor |
|||
.,FC5E A9 50 LDA #$50 |
WREND LDA #80 ;PUT 80 CASSETTE SYNCS AT END |
80 |
set tape write leader count |
|||
.,FC60 85 A7 STA $A7 |
STA SHCNL |
Zähler für Impulse |
save tape write leader count |
|||
.,FC62 A2 08 LDX #$08 |
LDX #8 |
Offset für IRQ |
set index for write tape leader vector |
|||
.,FC64 78 SEI |
SEI |
Interrupt verhindern |
disable the interrupts |
|||
.,FC65 20 BD FC JSR $FCBD |
JSR BSIV ;SET VECTOR TO WRITE ZEROS |
IRQ auf $FC6A |
set the tape vector |
|||
.,FC68 D0 EA BNE $FC54 |
BNE WRTBK ;JMP ; |
Rückkehr vom InterruptInterrupt-Routine für Bandschreiben |
restore registers and exit interrupt, branch alwayswrite tape leader IRQ routine |
IRQ routine for cassette write A |
||
.,FC6A A9 78 LDA #$78 |
WRTZ LDA #120 ;WRITE LEADING ZEROS FOR SYNC |
120 |
set time constant low byte for bit = leader |
|||
.,FC6C 20 AF FB JSR $FBAF |
JSR WRT1 |
Bit auf Band schreiben |
write time constant and toggle tape |
|||
.,FC6F D0 E3 BNE $FC54 |
BNE WRTBK |
Rückkehr vom Interrupt |
if tape bit high restore registers and exit interrupt |
|||
.,FC71 C6 A7 DEC $A7 |
DEC SHCNL ;CHECK IF DONE WITH LOW SYNC... |
Zähler erniedrigen |
decrement cycle count |
|||
.,FC73 D0 DF BNE $FC54 |
BNE WRTBK ;...NO |
nicht null, dann Rückkehr vom Interrupt |
if not all done restore registers and exit interrupt |
|||
.,FC75 20 97 FB JSR $FB97 |
JSR NEWCH ;...YES CLEAR UP COUNTERS |
Bitzähler für serielle Ausgabe setzen |
new tape byte setup |
|||
.,FC78 C6 AB DEC $AB |
DEC SHCNH ;CHECK IF DONE WITH SYNC... |
falls Datenende nicht er- reicht, dann |
decrement cassette leader count |
|||
.,FC7A 10 D8 BPL $FC54 |
BPL WRTBK ;...NO |
Rückkehr vom Interrupt |
if not all done restore registers and exit interrupt |
|||
.,FC7C A2 0A LDX #$0A |
LDX #10 ;...YES SO SET VECTOR FOR DATA |
IRQ |
set index for tape write vector |
|||
.,FC7E 20 BD FC JSR $FCBD |
JSR BSIV |
IRQ auf $FBCD |
set the tape vector |
|||
.,FC81 58 CLI |
CLI |
Interrupt ermöglichen |
enable the interrupts |
|||
.,FC82 E6 AB INC $AB |
INC SHCNH ;ZERO SHCNH |
Shortdauer |
clear cassette leader counter, was $FF |
|||
.,FC84 A5 BE LDA $BE |
LDA FSBLK ;IF DONE THEN... |
Zähler für Anzahl der Blocks |
get cassette block count |
|||
.,FC86 F0 30 BEQ $FCB8 |
BEQ STKY ;...GOTO SYSTEM RESTORE |
alle Blocks geschrieben ? |
if all done restore everything for STOP and exit the interrupt |
|||
.,FC88 20 8E FB JSR $FB8E |
JSR RD300 |
Adresse wieder auf Anfang setzen |
copy I/O start address to buffer address |
|||
.,FC8B A2 09 LDX #$09 |
LDX #9 ;SET UP FOR HEADER COUNT |
Zähler für |
set nine synchronisation bytes |
|||
.,FC8D 86 A5 STX $A5 |
STX CNTDN |
Synchronisation |
save cassette synchronization byte count |
|||
.,FC8F 86 B6 STX $B6 |
STX PRP ;CLEAR ENDOF BLOCK FLAG |
Flag für Block geschrieben |
||||
.,FC91 D0 83 BNE $FC16 |
BNE WRTS ;JMP ; |
unbedingter SprungRekorderbetrieb beenden |
go do the next tape byte, branch alwaysrestore everything for STOP |
switch from cassette IRQ to default IRQ |
||
.,FC93 08 PHP |
TNIF PHP ;CLEAN UP INTERRUPTS AND RESTORE PIA'S |
Status merken |
save status |
|||
.,FC94 78 SEI |
SEI |
Interrupt verhindern |
disable the interrupts |
|||
.,FC95 AD 11 D0 LDA $D011 |
LDA VICREG+17 ;UNLOCK VIC |
Bildschirm |
read the vertical fine scroll and control register |
|||
.,FC98 09 10 ORA #$10 |
ORA #$10 ;ENABLE DISPLAY |
wieder |
mask xxx1 xxxx, unblank the screen |
|||
.,FC9A 8D 11 D0 STA $D011 |
STA VICREG+17 |
einschalten |
save the vertical fine scroll and control register |
|||
.,FC9D 20 CA FC JSR $FCCA |
JSR TNOF ;TURN OFF MOTOR |
Rekordermotor ausschalten |
stop the cassette motor |
|||
.,FCA0 A9 7F LDA #$7F |
LDA #$7F ;CLEAR INTERRUPTS |
Interruptmöglichkeiten |
disable all interrupts |
|||
.,FCA2 8D 0D DC STA $DC0D |
STA D1ICR |
löschen |
save VIA 1 ICR |
|||
.,FCA5 20 DD FD JSR $FDDD |
JSR IOKEYS ;RESTORE KEYBOARD IRQ FROM TIMMER1 |
CIA wieder auf Standardwerte, 1/60 s Timing |
||||
.,FCA8 AD A0 02 LDA $02A0 |
LDA IRQTMP+1 ;RESTORE KEYBOARD INTERRUPT VECTOR |
Interruptvektor schon auf Standardwert ? |
get saved IRQ vector high byte |
|||
.,FCAB F0 09 BEQ $FCB6 |
BEQ TNIQ ;NO IRQ (IRQ VECTOR CANNOT BE Z-PAGE) |
falls ja, dann fertig |
branch if null |
|||
.,FCAD 8D 15 03 STA $0315 |
STA CINV+1 |
ansonsten zurücksetzen |
restore IRQ vector high byte |
|||
.,FCB0 AD 9F 02 LDA $029F |
LDA IRQTMP |
geretteten lRQ zurückholen |
get saved IRQ vector low byte |
|||
.,FCB3 8D 14 03 STA $0314 |
STA CINV |
und speichern |
restore IRQ vector low byte |
|||
.,FCB6 28 PLP |
TNIQ PLP |
Status zurückholen |
restore status |
|||
.,FCB7 60 RTS |
RTS ; |
RücksprungIRQ-Vektor setzen,X-indiziert |
reset vector |
terminate cassette I/O |
||
.,FCB8 20 93 FC JSR $FC93 |
STKY JSR TNIF ;GO RESTORE SYSTEM INTERRUPTS |
IRQ auf Standard |
restore everything for STOP |
|||
.,FCBB F0 97 BEQ $FC54 |
BEQ WRTBK ;CAME FOR CASSETTE IRQ SO RTI ; ; BSIV - SUBROUTINE TO CHANGE IRQ VECTORS ; ENTRYS - .X = 8 WRITE ZEROS TO TAPE ; .X = 10 WRITE DATA TO TAPE ; .X = 12 RESTORE TO KEYSCAN ; .X = 14 READ DATA FROM TAPE ; |
Abschluß IRQ |
restore registers and exit interrupt, branch alwaysset tape vector |
set IRQ vector depending on X |
||
.,FCBD BD 93 FD LDA $FD93,X |
BSIV LDA BSIT-8,X ;MOVE IRQ VECTORS, TABLE TO INDIRECT |
IRQ-Vektor |
get tape IRQ vector low byte |
|||
.,FCC0 8D 14 03 STA $0314 |
STA CINV |
aus Tabelle setzen |
set IRQ vector low byte |
|||
.,FCC3 BD 94 FD LDA $FD94,X |
LDA BSIT+1-8,X |
lRQ-Vektor |
get tape IRQ vector high byte |
|||
.,FCC6 8D 15 03 STA $0315 |
STA CINV+1 |
aus Tabelle setzen |
set IRQ vector high byte |
|||
.,FCC9 60 RTS |
RTS ; |
Rücksprung |
stop the cassette motor |
stop cassette motor |
||
.,FCCA A5 01 LDA $01 |
TNOF LDA R6510 ;TURN OFF CASSETTE MOTOR |
Rekorder- |
read the 6510 I/O port |
|||
.,FCCC 09 20 ORA #$20 |
ORA #$20 ; |
motor |
mask xxxx xx1x, turn the cassette motor off |
|||
.,FCCE 85 01 STA $01 |
STA R6510 |
ausschalten |
save the 6510 I/O port |
|||
.,FCD0 60 RTS |
RTS ;COMPARE START AND END LOAD/SAVE ;ADDRESSES. SUBROUTINE CALLED BY ;TAPE READ, SAVE, TAPE WRITE ; |
Rücksprungprüft auf Erreichen derEndadresse |
check read/write pointerreturn Cb = 1 if pointer >= end |
compare $AC/$AD with $AE/$AF |
||
.,FCD1 38 SEC |
CMPSTE SEC |
Carry für Subtraktion vorbereiten |
set carry for subtract |
|||
.,FCD2 A5 AC LDA $AC |
LDA SAL |
laufende Adresse |
get buffer address low byte |
|||
.,FCD4 E5 AE SBC $AE |
SBC EAL |
$AC/$AD |
subtract buffer end low byte |
|||
.,FCD6 A5 AD LDA $AD |
LDA SAH |
Endadresse |
get buffer address high byte |
|||
.,FCD8 E5 AF SBC $AF |
SBC EAH |
$AE/$AF |
subtract buffer end high byte |
|||
.,FCDA 60 RTS |
RTS ;INCREMENT ADDRESS POINTER SAL ; |
Rücksprung |
increment read/write pointer |
increment $AC/$AD |
||
.,FCDB E6 AC INC $AC |
INCSAL INC SAL |
Adreßzeiger |
increment buffer address low byte |
|||
.,FCDD D0 02 BNE $FCE1 |
BNE INCR |
er- |
branch if no overflow |
|||
.,FCDF E6 AD INC $AD |
INC SAH |
höhen |
increment buffer address low byte |
|||
.,FCE1 60 RTS |
INCR RTS .END .LIB INIT; START - SYSTEM RESET; WILL GOTO ROM AT $8000... ; IF LOCS $8004-$8008 ; = 'CBM80' ; ^^^ > THESE HAVE MSB SET ; KERNAL EXPECTS... ; $8000- .WORD INITILIZE (HARD START) ; $8002- .WORD PANIC (WARM START) ; ... ELSE BASIC SYSTEM USED ; ******************TESTING ONLY*************** ; USE AUTO DISK/CASSETTE LOAD WHEN DEVELOPED... ; |
RücksprungRESET |
RESET, hardware reset starts here |
POWER RESET ENTRY POINTThe system hardware reset vector ($FFFC) points here. Thisis the first routine executed when the computer is switched on. The routine firstly sets the stackpointer to #ff, disables interrupts and clears the decimal flag. It jumps to a routine at $fd02 which checks for autostart- cartridges. If so, an indirectjump is performed to the cartridge coldstart vector at $8000. I/O chips are initiated, and system constants are set up. Finaly the IRQ is enabled, and an indirect jump is performed to $a000, the basic cold start vector. |
RESET routine |
|
.,FCE2 A2 FF LDX #$FF |
START LDX #$FF |
Wert für Stapelzeiger |
set X for stack |
|||
.,FCE4 78 SEI |
SEI |
Interrupt setzen |
disable the interrupts |
|||
.,FCE5 9A TXS |
TXS |
Stapelzeiger initialisieren |
clear stack |
Set stackpointer to #ff |
||
.,FCE6 D8 CLD |
CLD |
Dezimalflag zurücksetzen |
clear decimal mode |
|||
.,FCE7 20 02 FD JSR $FD02 |
JSR A0INT ;TEST FOR $A0 ROM IN |
prüft auf ROM in $8000 |
scan for autostart ROM at $8000 |
Check ROM at $8000 |
||
.,FCEA D0 03 BNE $FCEF |
BNE START1 |
kein Autostart-Modul ? |
if not there continue startup |
|||
.,FCEC 6C 00 80 JMP ($8000) |
JMP ($8000) ; GO INIT AS $A000 ROM WANTS |
Sprung auf Modul-Start |
else call ROM start code |
Jump to autostartvector |
start cartridge |
|
.,FCEF 8E 16 D0 STX $D016 |
START1 STX VICREG+22 ;SET UP REFRESH (.X=<5) |
Videocontroller Steuerreg. 2 |
read the horizontal fine scroll and control register |
|||
.,FCF2 20 A3 FD JSR $FDA3 |
JSR IOINIT ;GO INITILIZE I/O DEVICES |
Interrupt vorbereiten |
initialise SID, CIA and IRQ |
Init I/O |
||
.,FCF5 20 50 FD JSR $FD50 |
JSR RAMTAS ;GO RAM TEST AND SET |
Arbeitsspeicher initialisieren |
RAM test and find RAM end |
Init system constants |
||
.,FCF8 20 15 FD JSR $FD15 |
JSR RESTOR ;GO SET UP OS VECTORS ; |
Hardware und I/O Vekt. setzen |
restore default I/O vectors |
KERNAL reset |
||
.,FCFB 20 5B FF JSR $FF5B |
JSR CINT ;GO INITILIZE SCREEN |
Video-Reset |
initialise VIC and screen editor |
Setup PAL/NTSC |
||
.,FCFE 58 CLI |
CLI ;INTERRUPTS OKAY NOW |
enable the interrupts |
||||
.,FCFF 6C 00 A0 JMP ($A000) |
JMP ($A000) ;GO TO BASIC SYSTEM ; A0INT - TEST FOR AN $8000 ROM ; RETURNS Z - $8000 IN ; |
zum BASIC Kaltstartprüft auf ROM in $8000 |
execute BASICscan for autostart ROM at $8000, returns Zb=1 if ROM found |
Basic coldstartCHECK FOR 8-ROMChecks for the ROM autostartparametrar at $8004-$8008. Itcompares data with $fd10, and if equal, set Z=1. |
start basiccheck for a cartridge |
|
.,FD02 A2 05 LDX #$05 |
A0INT LDX #TBLA0E-TBLA0R ;CHECK FOR $8000 |
Zeiger setzen |
five characters to test |
5 bytes to check |
||
.,FD04 BD 0F FD LDA $FD0F,X |
A0IN1 LDA TBLA0R-1,X |
Wert aus Tabelle holen und |
get test character |
Identifyer at $fd10 |
||
.,FD07 DD 03 80 CMP $8003,X |
CMP $8004-1,X |
ab $8000 vergleichen (CBM80) |
compare wiith byte in ROM space |
Compare with $8004 |
||
.,FD0A D0 03 BNE $FD0F |
BNE A0IN2 |
verzweige wenn ungleich |
exit if no match |
NOT equal! |
||
.,FD0C CA DEX |
DEX |
Zeiger vermindern |
decrement index |
|||
.,FD0D D0 F5 BNE $FD04 |
BNE A0IN1 |
weiter wenn nicht 5 Bytes |
loop if not all done |
until Z=1 |
||
.,FD0F 60 RTS |
A0IN2 RTS ; |
RücksprungROM-Modul Identifizierung |
autostart ROM signature |
8-ROM IDENTIFYERThe following 5 bytes contains the 8-ROM identifyer,reading "CBM80" with CBM ASCII. It is used with autostartcartridges. See $fd02. |
CBM80 |
|
.:FD10 C3 C2 CD 38 30 |
TBLA0R .BYT $C3,$C2,$CD,'80' ;..CBM80.. TBLA0E ; RESTOR - SET KERNAL INDIRECTS AND VECTORS (SYSTEM) ; |
'CBM80’Hardware und I/O Vektorensetzen/holen |
'CBM80’restore default I/O vectors |
CBM80RESTOR: KERNAL RESETThe KERNAL routine RESTOR ($ff8a) jumps to this routine.It restores (copys) the KERNAL vectors at $fd30 to $0314- $0333. Continues through VECTOR. |
restore I/O vectors |
|
.,FD15 A2 30 LDX #$30 |
RESTOR LDX #<VECTSS |
LOW- und HIGH-Byte des |
pointer to vector table low byte |
$fd30 - table of KERNAL vectors |
low FD30 |
|
.,FD17 A0 FD LDY #$FD |
LDY #>VECTSS |
Zeigers auf Tabelle $FD30 |
pointer to vector table high byte |
Clear carry to SET values. |
high FD30 |
|
.,FD19 18 CLC |
CLC ; ; VECTOR - SET KERNAL INDIRECT AND VECTORS (USER) ; |
Flag für 'Vektoren setzen' |
flag set vectorsset/read vectored I/O from (XY), Cb = 1 to read, Cb = 0 to set |
VECTOR: KERNAL MOVEThe KERNAL routine VECTOR ($ff8d) jumps to this routine.It reads or sets the vactors at $0314-$0333 depending on state of carry. X/Y contains the adress to read/write area, normally $fd30. See $fd15. A problem is that the RAM under the ROM at $fd30 always gets a copy of the contents in the ROM then you perform the copy. |
set I/O vectors depending on XY |
|
.,FD1A 86 C3 STX $C3 |
VECTOR STX TMP2 |
LOW- und HIGH-Byte |
save pointer low byte |
MEMUSS - c3/c4 temporary used for adress |
||
.,FD1C 84 C4 STY $C4 |
STY TMP2+1 |
des Zeigers setzen |
save pointer high byte |
|||
.,FD1E A0 1F LDY #$1F |
LDY #VECTSE-VECTSS-1 |
Zeiger setzen (16 Vektoren) |
set byte count |
Number of bytes to transfer |
||
.,FD20 B9 14 03 LDA $0314,Y |
MOVOS1 LDA CINV,Y ;GET FROM STORAGE |
Wert aus Tabelle holen |
read vector byte from vectors |
|||
.,FD23 B0 02 BCS $FD27 |
BCS MOVOS2 ;C...WANT STORAGE TO USER |
C=1 holen,C=0 setzen |
branch if read vectors |
Read or Write the vectors |
||
.,FD25 B1 C3 LDA ($C3),Y |
LDA (TMP2)Y ;...WANT USER TO STORAGE |
Tabellenwert holen |
read vector byte from (XY) |
|||
.,FD27 91 C3 STA ($C3),Y |
MOVOS2 STA (TMP2)Y ;PUT IN USER |
Tabellenwert setzen |
save byte to (XY) |
|||
.,FD29 99 14 03 STA $0314,Y |
STA CINV,Y ;PUT IN STORAGE |
Wert in Tabelle ablegen |
save byte to vector |
|||
.,FD2C 88 DEY |
DEY |
Zähler vermindern |
decrement index |
|||
.,FD2D 10 F1 BPL $FD20 |
BPL MOVOS1 |
Fertig? nein: nächster Wert |
loop if more to do |
Again... |
||
.,FD2F 60 RTS |
RTS ; VECTSS .WOR KEY,TIMB,NNMI .WOR NOPEN,NCLOSE,NCHKIN .WOR NCKOUT,NCLRCH,NBASIN .WOR NBSOUT,NSTOP,NGETIN .WOR NCLALL,TIMB ;GOTO BREAK ON A USRCMD JMP |
RücksprungTabelle der Hardwareund I/O-Vektoren |
The above code works but it tries to write to the ROM. while this is usually harmless systems that use flash ROM may suffer. Here is a version that makes the extra write to RAM instead but is otherwise identical in function. ## set/read vectored I/O from (XY), Cb = 1 to read, Cb = 0 to set STX $C3 ; save pointer low byte STY $C4 ; save pointer high byte LDY #$1F ; set byte count LDA ($C3),Y ; read vector byte from (XY) BCC $FD29 ; branch if set vectors LDA $0314,Y ; else read vector byte from vectors STA ($C3),Y ; save byte to (XY) STA $0314,Y ; save byte to vector DEY ; decrement index BPL $FD20 ; loop if more to do RTS kernal vectors |
KERNAL RESET VECTORSThese are the vectors that is copyed to $0314-$0333 whenRESTOR is called. |
vectors for OS at $0314-$0333 |
|
.:FD30 31 EA 66 FE 47 FE 4A F3 |
.WOR NLOAD,NSAVE VECTSE ; RAMTAS - MEMORY SIZE CHECK AND SET ; |
$0314 IRQ vector |
CINV VECTOR: hardware interrupt ($ea31) |
IRQ |
||
.:FD38 91 F2 0E F2 50 F2 33 F3 |
$0316 BRK vector $0318 NMI vector $031A open a logical file $031C close a specified logical file |
CBINV VECTOR: software interrupt ($fe66) NMINV VECTOR: hardware nmi interrupt ($fe47) IOPEN VECTOR: KERNAL open routine ($f3a4) ICLOSE VECTOR: KERNAL close routine ($f291) |
BRK NMI open close |
|||
.:FD40 57 F1 CA F1 ED F6 3E F1 |
$031E open channel for input $0320 open channel for output $0322 close input and output channels $0324 input character from channel |
ICHKIN VECTOR: KERNAL chkin routine ($f20e) ICKOUT VECTOR: KERNAL chkout routine ($f250) ICLRCH VECTOR: KERNAL clrchn routine ($f333) IBASIN VECTOR: KERNAL chrin routine ($f157) |
set input dev set output dev restore I/O input |
|||
.:FD48 2F F3 66 FE A5 F4 ED F5 |
Arbeitsspei. initialisieren |
$0326 output character to channel $0328 scan stop key $032A get character from the input device $032C close all channels and files |
IBSOUT VECTOR: KERNAL chrout routine ($f1ca) ISTOP VECTOR: KERNAL stop routine ($f6ed) IGETIN VECTOR: KERNAL getin routine ($f13e) ICLALL VECTOR: KERNAL clall routine ($f32f) |
output test stop key get abort I/O |
||
.,FD50 A9 00 LDA #$00 |
RAMTAS LDA #0 ;ZERO LOW MEMORY |
Wert zum Löschen laden |
$032E user function Vector to user defined command, currently points to BRK. This appears to be a holdover from PET days, when the built-in machine language monitor would jump through the $032E vector when it encountered a command that it did not understand, allowing the user to add new commands to the monitor. Although this vector is initialized to point to the routine called by STOP/RESTORE and the BRK interrupt, and is updated by the kernal vector routine at $FD57, it no longer has any function. $0330 load $0332 save test RAM and find RAM endclear A |
USRCMD VECTOR: user defined ($fe66) ILOAD VECTOR: KERNAL load routine ($f4a5) ISAVE VECTOR: KERNAL save routine ($f5ed) RAMTAS: INIT SYSTEM CONSTANTSThe KERNAL routine RAMTAS($ff87) jumps to this routine. Itclears the pages 0,2 and 3 by writing 00 into them. It also sets the start of the cassette buffer - $033c, and determins how much free RAM-memory there is. The memorycheck is performed by writing two different bytes into all memory positions, starting at $0400, till it reaches the ROM (the byte read is not the same as the one you wrote.) Note that the contents of the memory is restored afterwards. Finally, bottom of the memory, and top of screen-pointers are set. |
unused (BRK) load ram save ram initalise memory pointers |
|
.,FD52 A8 TAY |
TAY ;START AT 0002 |
als Zähler nach Y |
clear index |
|||
.,FD53 99 02 00 STA $0002,Y |
RAMTZ0 STA $0002,Y ;ZERO PAGE |
Zeropage, |
clear page 0, don't do $0000 or $0001 |
Fill pages 0,2,3 with zeros |
||
.,FD56 99 00 02 STA $0200,Y |
STA $0200,Y ;USER BUFFERS AND VARS |
Page 2 und |
clear page 2 |
|||
.,FD59 99 00 03 STA $0300,Y |
STA $0300,Y ;SYSTEM SPACE AND USER SPACE |
Page 3 löschen |
clear page 3 |
|||
.,FD5C C8 INY |
INY |
Zähler vermindern |
increment index |
|||
.,FD5D D0 F4 BNE $FD53 |
BNE RAMTZ0 ; ;ALLOCATE TAPE BUFFERS ; |
weiter wenn nicht fertig |
loop if more to do |
all 256 bytes |
||
.,FD5F A2 3C LDX #$3C |
LDX #<TBUFFR |
Werte für Startadresse |
set cassette buffer pointer low byte |
|||
.,FD61 A0 03 LDY #$03 |
LDY #>TBUFFR |
des Bandpuffers laden |
set cassette buffer pointer high byte |
Set tapebuffer to $033c |
||
.,FD63 86 B2 STX $B2 |
STX TAPE1 |
Bandpuffer Zeiger |
save tape buffer start pointer low byte |
Variables TAPE1 is used. |
||
.,FD65 84 B3 STY $B3 |
STY TAPE1+1 ; ; SET TOP OF MEMORY ; RAMTBT |
auf $033C setzen |
save tape buffer start pointer high byte |
|||
.,FD67 A8 TAY |
TAY ;MOVE $00 TO .Y |
Zeiger in Y auf 0 setzen |
clear Y |
|||
.,FD68 A9 03 LDA #$03 |
LDA #3 ;SET HIGH INITAL INDEX |
Wert für RAM testen ($04-1) |
set RAM test pointer high byte |
|||
.,FD6A 85 C2 STA $C2 |
STA TMP0+1 ; |
Startadresse (HIGH) des RAM |
save RAM test pointer high byte |
|||
.,FD6C E6 C2 INC $C2 |
RAMTZ1 INC TMP0+1 ;MOVE INDEX THRU MEMORY |
setzen und auf $0400 erhöhen |
increment RAM test pointer high byte |
|||
.,FD6E B1 C1 LDA ($C1),Y |
RAMTZ2 LDA (TMP0)Y ;GET PRESENT DATA |
Wert holen |
Perform memorytest. Starting at $0400 and upwards. |
|||
.,FD70 AA TAX |
TAX ;SAVE IN .X |
Wert merken |
Store temporary in X-reg |
|||
.,FD71 A9 55 LDA #$55 |
LDA #$55 ;DO A $55,$AA TEST |
%01010101 ($55) |
||||
.,FD73 91 C1 STA ($C1),Y |
STA (TMP0)Y |
abspeichern und über- |
Write #$55 into memory |
|||
.,FD75 D1 C1 CMP ($C1),Y |
CMP (TMP0)Y |
prüfen, ob Wert drin ist |
and compare. |
|||
.,FD77 D0 0F BNE $FD88 |
BNE SIZE |
ungleich dann kein RAM |
if not equal... ROM |
|||
.,FD79 2A ROL |
ROL A |
%10101010 |
||||
.,FD7A 91 C1 STA ($C1),Y |
STA (TMP0)Y |
Wert abspeichern und |
Write #$AA into same memory |
|||
.,FD7C D1 C1 CMP ($C1),Y |
CMP (TMP0)Y |
überprüfen, ob Wert drin ist |
and compare again. |
|||
.,FD7E D0 08 BNE $FD88 |
BNE SIZE |
ungleich dann kein RAM |
if not equal... ROM |
|||
.,FD80 8A TXA |
TXA ;RESTORE OLD DATA |
Wert wieder zurückholen |
||||
.,FD81 91 C1 STA ($C1),Y |
STA (TMP0)Y |
und wieder zurückschreiben |
Restore stored value |
|||
.,FD83 C8 INY |
INY |
Zeiger erhöhen |
||||
.,FD84 D0 E8 BNE $FD6E |
BNE RAMTZ2 |
Pageende? nein: weiter |
Next memorypos |
|||
.,FD86 F0 E4 BEQ $FD6C |
BEQ RAMTZ1 ; |
sonst Zeiger-HIGH erhöhen |
New page in memory |
|||
.,FD88 98 TYA |
SIZE TYA ;SET TOP OF MEMORY |
Zeiger-LOW ins |
The memorytest always exits when reaching a ROM |
|||
.,FD89 AA TAX |
TAX |
X-Register bringen |
||||
.,FD8A A4 C2 LDY $C2 |
LDY TMP0+1 |
Zeiger-HIGH holen |
||||
.,FD8C 18 CLC |
CLC |
C=0 (Flag für setzen) |
||||
.,FD8D 20 2D FE JSR $FE2D |
JSR SETTOP |
Memory (RAM) Top setzen |
set the top of memory |
Set top of memory. X and Y holds address. |
||
.,FD90 A9 08 LDA #$08 |
LDA #$08 ;SET BOTTOM OF MEMORY |
HIGH-Byte der Startadresse |
||||
.,FD92 8D 82 02 STA $0282 |
STA MEMSTR+1 ;ALWAYS AT $0800 |
Memory (RAM) Start auf $800 |
save the OS start of memory high byte |
Set pointer to bottom of memory ($0800) |
||
.,FD95 A9 04 LDA #$04 |
LDA #$04 ;SCREEN ALWAYS AT $400 |
HIGH-Byte der Startadresse |
||||
.,FD97 8D 88 02 STA $0288 |
STA HIBASE ;SET BASE OF SCREEN |
Video-RAM auf $400 |
save the screen memory page |
Set pointer to bottom of screen ($0400) |
||
.,FD9A 60 RTS |
RTS |
RücksprungIRQ Vektoren |
tape IRQ vectors |
TAPE IRQ VECTORSThis table contains the vectors to the four tape-IRQroutines. |
IRQ vectors |
|
.:FD9B 6A FC CD FB 31 EA 2C F9 |
BSIT .WOR WRTZ,WRTN,KEY,READ ;TABLE OF INDIRECTS FOR CASSETTE IRQ'S ; IOINIT - INITILIZE IO DEVICES ; |
$FC6A, $FBCD, $EA31, $F92CInterrupt Initialisierung |
$08 write tape leader IRQ routine |
$fc6a - tape write |
cassette write A |
|
.,FDA3 A9 7F LDA #$7F |
IOINIT LDA #$7F ;KILL INTERRUPTS |
Interrupt löschen |
$0A tape write IRQ routine $0C normal IRQ vector $0E read tape bits IRQ routine initialise SID, CIA and IRQdisable all interrupts |
$fbcd - tape write II $ea31 - normal IRQ $f92c - tape read IOINIT: INIT I/OThe KERNAL routine IOINIT ($ff84) jumps to this routine.It sets the init-values for the CIAs (IRQ, DDRA, DRA etc.), the SID-volume, and the processor onboard I/O port. |
cassette write B standard IRQ cassette read initaliase I/O devices |
|
.,FDA5 8D 0D DC STA $DC0D |
STA D1ICR |
ICR CIA 1 |
save VIA 1 ICR |
CIA#1 IRQ control register |
||
.,FDA8 8D 0D DD STA $DD0D |
STA D2ICR |
ICR CIA 2 Port A CIA 1 |
save VIA 2 ICR |
CIA#2 IRQ control register |
||
.,FDAB 8D 00 DC STA $DC00 |
STA D1PRA ;TURN ON STOP KEY |
Tastatur Matrixzeile 0 |
save VIA 1 DRA, keyboard column drive |
CIA#1 data port $ (keyboard) |
||
.,FDAE A9 08 LDA #$08 |
LDA #%00001000 ;SHUT OFF TIMERS |
Wert laden |
set timer single shot |
|||
.,FDB0 8D 0E DC STA $DC0E |
STA D1CRA |
CRA CIA 1 Timer A 'one shot' |
save VIA 1 CRA |
CIA#1 control register timer A |
||
.,FDB3 8D 0E DD STA $DD0E |
STA D2CRA |
CRA CIA 2 Timer A 'one shot' |
save VIA 2 CRA |
CIA#2 control register timer A |
||
.,FDB6 8D 0F DC STA $DC0F |
STA D1CRB |
CRB CIA 1 Timer B 'one shot' |
save VIA 1 CRB |
CIA#1 control register timer B |
||
.,FDB9 8D 0F DD STA $DD0F |
STA D2CRB ; CONFIGURE PORTS |
CRB CIA 2 Timer B 'one shot' |
save VIA 2 CRB |
CIA#2 control register timer B |
||
.,FDBC A2 00 LDX #$00 |
LDX #$00 ;SET UP KEYBOARD INPUTS |
Eingangs-Modus |
set all inputs |
|||
.,FDBE 8E 03 DC STX $DC03 |
STX D1DDRB ;KEYBOARD INPUTS |
Datenrichtungsreg. B CIA 1 |
save VIA 1 DDRB, keyboard row |
CIA#1 DDRB. Port B is input |
||
.,FDC1 8E 03 DD STX $DD03 |
STX D2DDRB ;USER PORT (NO RS-232) |
Datenrichtungsreg. B CIA 2 |
save VIA 2 DDRB, RS232 port |
CIA#2 DDRB. Port B is input |
||
.,FDC4 8E 18 D4 STX $D418 |
STX SIDREG+24 ;TURN OFF SID |
Lautstärke für SID auf Null |
clear the volume and filter select register |
No sound from SID |
||
.,FDC7 CA DEX |
DEX |
Ausgabe-Modus |
set X = $FF |
|||
.,FDC8 8E 02 DC STX $DC02 |
STX D1DDRA ;KEYBOARD OUTPUTS |
Datenrichtungsreg. A CIA 1 |
save VIA 1 DDRA, keyboard column |
CIA#1 DDRA. Port A is output |
||
.,FDCB A9 07 LDA #$07 |
LDA #%00000111 ;SET SERIAL/VA14/15 (CLKHI) |
Videocontroller auf unterste 16 K |
DATA out high, CLK out high, ATN out high, RE232 Tx DATA high, video address 15 = 1, video address 14 = 1 |
%00000111 |
||
.,FDCD 8D 00 DD STA $DD00 |
STA D2PRA |
Port A CIA 2, ATN löschen |
save VIA 2 DRA, serial port and video address |
CIA#2 dataport A. Set Videobank to $0000-$3fff |
||
.,FDD0 A9 3F LDA #$3F |
LDA #%00111111 ;SET SERIAL IN/OUT, VA14/15OUT |
Bit 0 bis 5 auf Ausgabe |
set serial DATA input, serial CLK input |
%00111111 |
||
.,FDD2 8D 02 DD STA $DD02 |
STA D2DDRA ; ; SET UP THE 6510 LINES ; |
Datenrichtungsreg. A CIA 2 |
save VIA 2 DDRA, serial port and video address |
CIA#2 DDRA. Serial bus and videobank |
||
.,FDD5 A9 E7 LDA #$E7 |
LDA #%11100111 ;MOTOR ON, HIRAM LOWRAM CHAREN HIGH |
Normalwert laden und |
set 1110 0111, motor off, enable I/O, enable KERNAL, enable BASIC |
6510 I/O port - %XX100111 |
||
.,FDD7 85 01 STA $01 |
STA R6510 |
Speicheraufteilung neu setzen |
save the 6510 I/O port |
|||
.,FDD9 A9 2F LDA #$2F |
LDA #%00101111 ;MTR OUT,SW IN,WR OUT,CONTROL OUT |
Bit 0-3 und 5 Ausgang, Bit 4 Eingang |
set 0010 1111, 0 = input, 1 = output |
6510 I/O DDR - %00101111 |
||
.,FDDB 85 00 STA $00 |
STA D6510 |
Datenrichtung Prozessorport |
save the 6510 I/O port direction register |
ENABLE TIMERThis routine inits and starts the CIA#1 timer A accordingto the PAL/NTSC flag. Different system clocks rates are used in PAL/NTSC systems. |
initalise TAL1/TAH1 fpr 1/60 of a second |
|
.,FDDD AD A6 02 LDA $02A6 |
IOKEYS LDA PALNTS ;PAL OR NTSC |
NTSC-Version ? |
get the PAL/NTSC flag |
PAL/NTSC flag |
||
.,FDE0 F0 0A BEQ $FDEC |
BEQ I0010 ;NTSC |
ja |
if NTSC go set NTSC timing else set PAL timing |
NTSC setup |
||
.,FDE2 A9 25 LDA #$25 |
LDA #<SIXTYP |
Wert für PAL-Version |
||||
.,FDE4 8D 04 DC STA $DC04 |
STA D1T1L |
Timer für PAL-Version setzen |
save VIA 1 timer A low byte |
CIA#1 timer A - lowbyte |
||
.,FDE7 A9 40 LDA #$40 |
LDA #>SIXTYP |
$4025 = 16421 Zyklen |
PAL-setup #4025 |
|||
.,FDE9 4C F3 FD JMP $FDF3 |
JMP I0020 |
NTSC-Version übergehen |
||||
.,FDEC A9 95 LDA #$95 |
I0010 LDA #<SIXTY ;KEYBOARD SCAN IRQ'S |
Wert für NTSC-Version |
||||
.,FDEE 8D 04 DC STA $DC04 |
STA D1T1L |
Timer für NTSC-Version setzen |
save VIA 1 timer A low byte |
CIA#1 timer A - lowbyte |
||
.,FDF1 A9 42 LDA #$42 |
LDA #>SIXTY |
$4295 = 17045 Zyklen |
NTSC-setup #4295 |
|||
.,FDF3 8D 05 DC STA $DC05 |
I0020 STA D1T1H |
Timer-HIGH setzen |
save VIA 1 timer A high byte |
CIA#1 timer A - highbyte |
||
.,FDF6 4C 6E FF JMP $FF6E |
JMP PIOKEY ; LDA #$81 ;ENABLE T1 IRQ'S ; STA D1ICR ; LDA D1CRA ; AND #$80 ;SAVE ONLY TOD BIT ; ORA #%00010001 ;ENABLE TIMER1 ; STA D1CRA ; JMP CLKLO ;RELEASE THE CLOCK LINE ; ; SIXTY HERTZ VALUE ; SIXTY = 16667 |
Interrupt durch Timer setzenParameter f. Filenamen setzen |
set filename |
start timerSETNAM: SAVE FILENAME DATAThe KERNAL routine SETNAM ($ffbd) jumps to this routine.On entry, A-reg holds the length of the filename, and X/Y the address in mem to the filename. |
initalise file name parameters |
|
.,FDF9 85 B7 STA $B7 |
SETNAM STA FNLEN |
Länge speichern |
set file name length |
store length of filename in FNLEN |
||
.,FDFB 86 BB STX $BB |
STX FNADR |
Adresse-LOW speichern |
set file name pointer low byte |
store pointer to filename in FNADDR |
||
.,FDFD 84 BC STY $BC |
STY FNADR+1 |
Adresse-HIGH speichern |
set file name pointer high byte |
|||
.,FDFF 60 RTS |
RTS |
RücksprungParameter für aktivesFile setzen |
set logical, first and second addresses |
SETLFS: SAVE FILE DETAILSThe KERNAL routine SETLFS ($ffba) jumps to this routine.On entry A-reg holds the logical filenumber, X the device number, and Y the secondary address. |
inatalise file parameters |
|
.,FE00 85 B8 STA $B8 |
SETLFS STA LA |
logische Filenummer |
save the logical file |
store logical filenumber in LA |
||
.,FE02 86 BA STX $BA |
STX FA |
Geräteadresse |
save the device number |
store devicenumber in FA |
||
.,FE04 84 B9 STY $B9 |
STY SA |
Sekundäradresse |
save the secondary address |
store secondary address in SA |
||
.,FE06 60 RTS |
RTS |
RücksprungStatus holen |
read I/O status word |
READST: READ STATUSThe KERNAL routine READST ($ffb7) jumps to this routine.The routine checks if the current devicenumber is 2, (ie RS232) then the value of RSSTAT (the ACIA 6551 status)is returned in (A), and RSSTAT is cleared. Else it reads and returnes the value of STATUS. |
read I/O status word |
|
.,FE07 A5 BA LDA $BA |
READSS LDA FA ;SEE WHICH DEVICES' TO READ |
Gerätenummer holen |
get the device number |
read current device number from FA |
||
.,FE09 C9 02 CMP #$02 |
CMP #2 ;IS IT RS-232? |
gleich 2 ? (RS 232) |
compare device with RS232 device |
device = RS232? |
||
.,FE0B D0 0D BNE $FE1A |
BNE READST ;NO...READ SERIAL/CASS |
nein |
if not RS232 device go ?? get RS232 device status |
nope, read STATUS |
||
.,FE0D AD 97 02 LDA $0297 |
LDA RSSTAT ;YES...GET RS-232 UP |
RS 232-Status holen |
get the RS232 status register |
RSSTAT |
||
.,FE10 48 PHA |
PHA |
und auf Stapel retten |
save the RS232 status value |
temp store |
||
.,FE11 A9 00 LDA #$00 |
LDA #00 ;CLEAR RS232 STATUS WHEN READ |
Status |
clear A |
|||
.,FE13 8D 97 02 STA $0297 |
STA RSSTAT |
löschen |
clear the RS232 status register |
clear RSSTAT |
||
.,FE16 68 PLA |
PLA |
und Statuswert zurückholen |
restore the RS232 status value |
|||
.,FE17 60 RTS |
RTS |
RücksprungFlag für Betriebssystem-meldungen setzen |
control kernal messages |
SETMSG: FLAG STATUSThe KERNAL routine SETMSG ($ff90) jumps to this routine.On entry, the value in (A) is stored in MSGFLG, then the I/O status is placed in (A). If routine is entered at $fe1c the contents in (A) will be stored in STATUS. |
control kernel messages |
|
.,FE18 85 9D STA $9D |
SETMSG STA MSGFLG |
Ausgabeflag (Direktmodus) |
set message mode flag |
store MSGFLG |
read ST |
|
.,FE1A A5 90 LDA $90 |
READST LDA STATUS |
Statusflag holenStatus setzen |
read the serial status byteOR into the serial status byte |
read STATUS |
add A to ST |
|
.,FE1C 05 90 ORA $90 |
UDST ORA STATUS |
Statusflag testen und |
OR with the serial status byte |
|||
.,FE1E 85 90 STA $90 |
STA STATUS |
wieder abspeichern |
save the serial status byte |
|||
.,FE20 60 RTS |
RTS |
RücksprungTimeout-Flag für IEC setzen |
set timeout on serial bus |
SETTMO: SET TIMEOUTThe KERNAL routine SETTMO ($ffa2) jumps to this routine.On entry the value in (A) is stored in the IEEE timeout flag. (Who uses IEEE nowadays?) |
set timeout on serail bus |
|
.,FE21 8D 85 02 STA $0285 |
SETTMO STA TIMOUT |
Timeout-disable |
save serial bus timeout flag |
store in TIMOUT |
||
.,FE24 60 RTS |
RTS |
RücksprungMEMTOP, Obergrenze desBASIC-RAM holen/setzen |
read/set the top of memory, Cb = 1 to read, Cb = 0 to set |
MEMTOP: READ/SET TOP OF MEMORYThe KERNAL routine MEMTOP ($ffa9) jumps to this routine.If carry is set on entry, the top of memory address will be loaded into (X/Y). If carry is clear on entry, the top of memory will be set according to the contents in (X/Y) |
read/set top of memory |
|
.,FE25 90 06 BCC $FE2D |
MEMTOP BCC SETTOP ; ;CARRY SET--READ TOP OF MEMORY ; |
C=0: Adresse setzen |
if Cb clear go set the top of memoryread the top of memory |
carry clear? |
||
.,FE27 AE 83 02 LDX $0283 |
GETTOP LDX MEMSIZ |
Carry gesetzt |
get memory top low byte |
read memtop from MEMSIZ |
||
.,FE2A AC 84 02 LDY $0284 |
LDY MEMSIZ+1 ; ;CARRY CLEAR--SET TOP OF MEMORY ; |
Adresse nach X/Y holen |
get memory top high byteset the top of memory |
|||
.,FE2D 8E 83 02 STX $0283 |
SETTOP STX MEMSIZ |
Carry gelöscht |
set memory top low byte |
store memtop in MEMSIZ |
||
.,FE30 8C 84 02 STY $0284 |
STY MEMSIZ+1 |
X/Y nach Adresse setzen |
set memory top high byte |
|||
.,FE33 60 RTS |
RTS ;MANAGE BOTTOM OF MEMORY ; |
RücksprungMEMBOT, Untergrenze desBASIC-RAM holen/setzen |
read/set the bottom of memory, Cb = 1 to read, Cb = 0 to set |
MEMBOT: READ/SET BOTTOM OF MEMORYThe KERNAL routine MEMBOT ($ff9c) jumps to this routine.If carry is set on entry, the bottom of memory address will be loaded into (X/Y). If carry is clear on entry, the bottom of memory will set according to the contents in (X/Y) |
read/set bottom of memory |
|
.,FE34 90 06 BCC $FE3C |
MEMBOT BCC SETBOT ; ;CARRY SET--READ BOTTOM OF MEMORY ; |
C=0: Adresse setzen |
if Cb clear go set the bottom of memory |
carry clear? |
||
.,FE36 AE 81 02 LDX $0281 |
LDX MEMSTR |
Carry gesetzt |
get the OS start of memory low byte |
read membot from MEMSTR |
||
.,FE39 AC 82 02 LDY $0282 |
LDY MEMSTR+1 ; ;CARRY CLEAR--SET BOTTOM OF MEMORY ; |
Adresse nach X/Y holen |
get the OS start of memory high byte |
|||
.,FE3C 8E 81 02 STX $0281 |
SETBOT STX MEMSTR |
Carry gelöscht |
save the OS start of memory low byte |
store membot in MEMSTR |
||
.,FE3F 8C 82 02 STY $0282 |
STY MEMSTR+1 |
Adresse aus X/Y setzen |
save the OS start of memory high byte |
|||
.,FE42 60 RTS |
RTS .END .LIB RS232NMI |
RücksprungNMI Einsprung |
NMI vector |
NMI ENTRY POINTThe processor jumps to this routine every time a NMIoccurs (see jump vector at $fffa). On entry all processor registers will be put on the stack. The routine will check the presents of a ROM cartridge at $8000 with autostart, and warm start it. Otherwise, the following warm start routine is called. |
NMI entry |
|
.,FE43 78 SEI |
NMI SEI ;NO IRQ'S ALLOWED... |
Interrupt setzen |
disable the interrupts |
disable interrupts |
||
.,FE44 6C 18 03 JMP ($0318) |
JMP (NMINV) ;...COULD MESS UP CASSETTES |
JMP $FE47, NMI-Vektor |
do NMI vectorNMI handler |
jump to NMINV, points normally to $fe47 |
normally FE47standard NMI routine |
|
.,FE47 48 PHA |
NNMI PHA |
Akku auf Stapel retten |
save A |
store (A), (X), (Y) on the stack |
||
.,FE48 8A TXA |
TXA |
X nach Akku |
copy X |
|||
.,FE49 48 PHA |
PHA |
X retten |
save X |
|||
.,FE4A 98 TYA |
TYA |
Y nach Akku |
copy Y |
|||
.,FE4B 48 PHA |
PHA |
Y retten |
save Y |
|||
.,FE4C A9 7F LDA #$7F |
NNMI10 LDA #$7F ;DISABLE ALL NMI'S |
Wert laden |
disable all interrupts |
CIA#2 interrupt control register |
||
.,FE4E 8D 0D DD STA $DD0D |
STA D2ICR |
NMI-Möglichkeiten löschen |
save VIA 2 ICR |
|||
.,FE51 AC 0D DD LDY $DD0D |
LDY D2ICR ;CHECK IF REAL NMI... |
Flags lesen und löschen |
save VIA 2 ICR |
|||
.,FE54 30 1C BMI $FE72 |
BMI NNMI20 ;NO...RS232/OTHER ; |
RS 232 aktiv ? |
NMI caused by RS232? If so - jump |
|||
.,FE56 20 02 FD JSR $FD02 |
NNMI18 JSR A0INT ;CHECK IF $A0 IN...NO .Y |
Prüft auf ROM-Modul in $8000 |
scan for autostart ROM at $8000 |
check for autostart at $8000 |
||
.,FE59 D0 03 BNE $FE5E |
BNE NNMI19 ;...NO |
nein: weiter |
branch if no autostart ROM |
|||
.,FE5B 6C 02 80 JMP ($8002) |
JMP ($8002) ;...YES ; ; CHECK FOR STOP KEY DOWN ; NNMI19 |
ja: Sprung auf Modul-NMI |
else do autostart ROM break entry |
Jump to warm start vector |
cartridge warm start |
|
.,FE5E 20 BC F6 JSR $F6BC |
JSR UD60 ;NO .Y |
Flag für Stop-Taste setzen |
increment real time clock |
Scan 1 row in keymatrix and store value in $91 |
||
.,FE61 20 E1 FF JSR $FFE1 |
JSR STOP ;NO .Y |
Stop-Taste abfragen |
scan stop key |
Check $91 to see if <STOP> was pressed |
||
.,FE64 D0 0C BNE $FE72 |
BNE NNMI20 ;NO STOP KEY...TEST FOR RS232 ; ; TIMB - WHERE SYSTEM GOES ON A BRK INSTRUCTION ; |
nicht gedrückt ? |
if not [STOP] restore registers and exit interruptuser function default vectorBRK handler |
<STOP> not pressed, skip part of following routineWARM START BASICThis routine is called from the NMI routine above. If<STOP> was pressed, then KERNAL vectors are restored to default values, I/O vectors initialised and a jump to ($a002), the Basic warm start vector. The NMI routine continues at $fe72 by checking the RS232, if there is anyting to send. |
BRK routine |
|
.,FE66 20 15 FD JSR $FD15 |
TIMB JSR RESTOR ;RESTORE SYSTEM INDIRECTS |
Standard-Vektoren für Interrupt und I/O setzen |
restore default I/O vectors |
KERNAL reset |
||
.,FE69 20 A3 FD JSR $FDA3 |
JSR IOINIT ;RESTORE I/O FOR BASIC |
I/O initialisieren |
initialise SID, CIA and IRQ |
init I/O |
||
.,FE6C 20 18 E5 JSR $E518 |
JSR CINT ;RESTORE SCREEN FOR BASIC |
Bildschirmreset |
initialise the screen and keyboard |
init I/O |
||
.,FE6F 6C 02 A0 JMP ($A002) |
JMP ($A002) ;...NO, SO BASIC WARM START ; DISABLE NMI'S UNTILL READY ; SAVE ON STACK ; |
zum BASIC-WarmstartNMI-Routine für RS 232 |
do BASIC break entryRS232 NMI routine |
jump to Basic warm start vectorNMI RS232 HANDLING |
internal NMI |
|
.,FE72 98 TYA |
NNMI20 TYA ;.Y SAVED THROUGH RESTORE |
ICR-Register |
Read CIA#2 interrupt control register |
|||
.,FE73 2D A1 02 AND $02A1 |
AND ENABL ;SHOW ONLY ENABLES |
mit RS 232 NMI-Flag verknüp. |
AND with the RS-232 interrupt enable byte |
mask with ENABL, RS232 enable |
||
.,FE76 AA TAX |
TAX ;SAVE IN .X FOR LATTER ; ; T1 NMI CHECK - TRANSMITT A BIT ; |
nach X retten |
temp store in (X) |
|||
.,FE77 29 01 AND #$01 |
AND #$01 ;CHECK FOR T1 |
Sendebetrieb aktiv ? |
test if sending (%00000001) |
|||
.,FE79 F0 28 BEQ $FEA3 |
BEQ NNMI30 ;NO... ; |
nein |
nope, jump to recieve test |
|||
.,FE7B AD 00 DD LDA $DD00 |
LDA D2PRA |
Datenport lesen |
read VIA 2 DRA, serial port and video address |
load CIA#1 DRA |
||
.,FE7E 29 FB AND #$FB |
AND #$FF-$04 ;FIX FOR CURRENT I/O |
Bit 2 TXD löschen |
mask xxxx x0xx, clear RS232 Tx DATA |
mask bit2 (RS232 send) |
||
.,FE80 05 B5 ORA $B5 |
ORA NXTBIT ;LOAD DATA AND... |
zu sendendes Bit übergeben |
OR in the RS232 transmit data bit |
NXTBIT, next bit to send |
||
.,FE82 8D 00 DD STA $DD00 |
STA D2PRA ;...SEND IT ; |
und wieder in Datenport spei. |
save VIA 2 DRA, serial port and video address |
and write to port |
||
.,FE85 AD A1 02 LDA $02A1 |
LDA ENABL ;RESTORE NMI'S |
RS-232 NMI-Flag |
get the RS-232 interrupt enable byte |
|||
.,FE88 8D 0D DD STA $DD0D |
STA D2ICR ;READY FOR NEXT... ; ; BECAUSE OF 6526 ICR STRUCTURE... ; HANDLE ANOTHER NMI AS A SUBROUTINE ; |
wieder in ICR schreiben |
save VIA 2 ICR |
write ENABL to CIA#2 I.C.R |
||
.,FE8B 8A TXA |
TXA ;TEST FOR ANOTHER NMI |
Wert aus X zurückholen |
get temp |
|||
.,FE8C 29 12 AND #$12 |
AND #$12 ;TEST FOR T2 OR FLAG |
Bit 1 und 4 isolieren |
test if recieving (bit1), or waiting for reciever edge (bit4) ($12 = %00010010) |
|||
.,FE8E F0 0D BEQ $FE9D |
BEQ NNMI25 |
Bit 1 und 4=0: Bit empfangen |
nope, skip reciever routine |
|||
.,FE90 29 02 AND #$02 |
AND #$02 ;CHECK FOR T2 |
Bit 1, Aufruf von Timer B |
test if recieving |
|||
.,FE92 F0 06 BEQ $FE9A |
BEQ NNMI22 ;MUST BE A FLAG ; |
nein: verzweige zu Startbit |
nope |
|||
.,FE94 20 D6 FE JSR $FED6 |
JSR T2NMI ;HANDLE A NORMAL BIT IN... |
empfangenes Bit verarbeiten |
jump to NMI RS232 in |
|||
.,FE97 4C 9D FE JMP $FE9D |
JMP NNMI25 ;...THEN CONTINUE OUTPUT ; |
Vorbereitung für Byte umgehen |
||||
.,FE9A 20 07 FF JSR $FF07 |
NNMI22 JSR FLNMI ;HANDLE A START BIT... ; |
Vorbereitung für Empfang des nächsten Bytes |
jump to NMI RS232 out |
|||
.,FE9D 20 BB EE JSR $EEBB |
NNMI25 JSR RSTRAB ;GO CALC INFO (CODE COULD BE IN LINE) |
Empfang des nächsten Bits v. |
RS232 send byte |
|||
.,FEA0 4C B6 FE JMP $FEB6 |
JMP NMIRTI ; ; T2 NMI CHECK - RECIEVE A BIT ; |
Rückkehr vom Interrupt |
goto exit |
|||
.,FEA3 8A TXA |
NNMI30 TXA |
X nach Akku |
get active interrupts back |
get temp |
||
.,FEA4 29 02 AND #$02 |
AND #$02 ;MASK TO T2 |
Datenempfang ? |
mask ?? interrupt |
test bit1 |
||
.,FEA6 F0 06 BEQ $FEAE |
BEQ NNMI40 ;NO... ; |
verzweige wenn kein Empfang |
branch if not ?? interrupt was ?? interrupt |
nope |
||
.,FEA8 20 D6 FE JSR $FED6 |
JSR T2NMI ;HANDLE INTERRUPT |
empfangenes Bit verarbeiten |
NMI RS232 in??? |
|||
.,FEAB 4C B6 FE JMP $FEB6 |
JMP NMIRTI ; FLAG NMI HANDLER - RECIEVE A START BIT ; |
Rückkehr vom Interrupt |
goto exit |
|||
.,FEAE 8A TXA |
NNMI40 TXA ;CHECK FOR EDGE |
X nach Akku |
get active interrupts back |
set temp |
||
.,FEAF 29 10 AND #$10 |
AND #$10 ;ON FLAG... |
warten auf Startbit ? |
mask CB1 interrupt, Rx data bit transition |
test bit4 |
||
.,FEB1 F0 03 BEQ $FEB6 |
BEQ NMIRTI ;NO... ; |
verzweige wenn kein Startbit |
if no bit restore registers and exit interrupt |
nope, exit |
||
.,FEB3 20 07 FF JSR $FF07 |
JSR FLNMI ;START BIT ROUTINE |
Vorbereitung für Empfang des nächsten Bytes |
NMI RS232 out |
|||
.,FEB6 AD A1 02 LDA $02A1 |
NMIRTI LDA ENABL ;RESTORE NMI'S |
RS-232 NMI-Flag |
get the RS-232 interrupt enable byte |
ENABL |
||
.,FEB9 8D 0D DD STA $DD0D |
STA D2ICR |
wieder in ICR |
save VIA 2 ICR |
CIA#2 interrupt control register |
||
.,FEBC 68 PLA |
PREND PLA ;BECAUSE OF MISSING SCREEN EDITOR |
Y-Register vom Stapel |
pull Y |
restore registers (Y),(X),(A) |
||
.,FEBD A8 TAY |
TAY |
zurückholen |
restore Y |
|||
.,FEBE 68 PLA |
PLA |
X-Register |
pull X |
|||
.,FEBF AA TAX |
TAX |
zurückholen |
restore X |
|||
.,FEC0 68 PLA |
PLA |
Akku zurückholen |
restore A |
|||
.,FEC1 40 RTI |
RTI ; BAUDO TABLE CONTAINS VALUES ; FOR 1E6/BAUD RATE/2 ; |
RücksprungTimerkonstanten für RS 232 Baud-Rate,NTSC-Version |
baud rate word is calculated from ..(system clock / baud rate) / 2 - 100system clock ------------ PAL 985248 Hz NTSC 1022727 Hz baud rate tables for NTSC C64 |
back from NMIRS232 TIMING TABLE - NTSCTimingtable for RS232 NMI for use with NTSC machines. Thetable containe 10 entries which corresponds to one of the fixed RS232 rates, starting with lowest (50 baud) and finishing with the highest (2400 baud). Since the clock frequency is different between NTSC and PAL systems, there is another table for PAL machines at $e4ec. |
baud rate tables |
|
.:FEC2 C1 27 |
BAUDO .WOR 10000-CBIT ; 50 BAUD |
$27C1 = 10177 50 Baud |
50 baud 1027700 |
50 baud |
50 |
|
.:FEC4 3E 1A |
.WOR 6667-CBIT ; 75 BAUD |
$1A3E = 6718 75 Baud |
75 baud 1022700 |
75 baud |
75 |
|
.:FEC6 C5 11 |
.WOR 4545-CBIT ; 110 BAUD |
$11C5 = 4549 110 Baud |
110 baud 1022780 |
110 baud |
110 |
|
.:FEC8 74 0E |
.WOR 3715-CBIT ; 134.6 BAUD |
$0E74 = 3700 134.5 Baud |
134.5 baud 1022200 |
134.5 baud |
134.5 |
|
.:FECA ED 0C |
.WOR 3333-CBIT ; 150 BAUD |
$0CED = 3309 150 Baud |
150 baud 1022700 |
150 baud |
150 |
|
.:FECC 45 06 |
.WOR 1667-CBIT ; 300 BAUD |
$0645 = 1605 300 Baud |
300 baud 1023000 |
300 baud |
300 |
|
.:FECE F0 02 |
.WOR 833-CBIT ; 600 BAUD |
$02F0 = 752 600 Baud |
600 baud 1022400 |
600 baud |
600 |
|
.:FED0 46 01 |
.WOR 417-CBIT ; 1200 BAUD |
$0146 = 326 1200 Baud |
1200 baud 1022400 |
1200 baud |
1200 |
|
.:FED2 B8 00 |
.WOR 278-CBIT ; 1800 BAUD |
$00B8 = 184 1800 Baud |
1800 baud 1022400 |
(1800) 2400 baud |
1800 |
|
.:FED4 71 00 |
.WOR 208-CBIT ; 2400 BAUD ; ; CBIT - AN ADJUSTMENT TO MAKE NEXT T2 HIT NEAR CENTER ; OF THE NEXT BIT. ; APROX THE TIME TO SERVICE A CB1 NMI CBIT =100 ;CYCLES ; T2NMI - SUBROUTINE TO HANDLE AN RS232 ; BIT INPUT. ; |
$0071 = 113 2400 BaudNMI-Routine für RS-232Eingabe |
2400 baud 1022400?? |
2400 baudNMI RS232 INThis routine inputs a bit from the RS232 port and sets thebaudrate timing for the next bit. Continues to the RS232 recieve routine. |
2400input next bit on RS-232 and schedule TB2 |
|
.,FED6 AD 01 DD LDA $DD01 |
T2NMI LDA D2PRB ;GET DATA IN |
Port Register B |
read VIA 2 DRB, RS232 port |
RS232 I/O port |
||
.,FED9 29 01 AND #$01 |
AND #01 ;MASK OFF... |
Bit für Receive Data isolie- ren |
mask 0000 000x, RS232 Rx DATA |
test bit0, received data |
||
.,FEDB 85 A7 STA $A7 |
STA INBIT ;...SAVE FOR LATTER ; ; UPDATE T2 FOR MID BIT CHECK ; (WORST CASE <213 CYCLES TO HERE) ; (CALC 125 CYCLES+43-66 DEAD) ; |
und speichern |
save the RS232 received data bit |
store in INBIT |
||
.,FEDD AD 06 DD LDA $DD06 |
LDA D2T2L ;CALC NEW TIME & CLR NMI |
Timer B LOW |
get VIA 2 timer B low byte |
lowbyte of timer B |
||
.,FEE0 E9 1C SBC #$1C |
SBC #22+6 |
minus 28 |
||||
.,FEE2 6D 99 02 ADC $0299 |
ADC BAUDOF |
+ LOW-Byte der Baudrate |
<BAUDOF |
|||
.,FEE5 8D 06 DD STA $DD06 |
STA D2T2L |
wieder abspeichern |
save VIA 2 timer B low byte |
store timer B |
||
.,FEE8 AD 07 DD LDA $DD07 |
LDA D2T2H |
RS 232 Timerkon. für Baudrate |
get VIA 2 timer B high byte |
highbyte of timer B |
||
.,FEEB 6D 9A 02 ADC $029A |
ADC BAUDOF+1 |
HIGH-Byte addieren |
>BAUDOF |
|||
.,FEEE 8D 07 DD STA $DD07 |
STA D2T2H ; |
in Timer schreiben |
save VIA 2 timer B high byte |
store timer B |
||
.,FEF1 A9 11 LDA #$11 |
LDA #$11 ;ENABLE TIMER |
Timer B starten |
set timer B single shot, start timer B |
|||
.,FEF3 8D 0F DD STA $DD0F |
STA D2CRB ; |
Control Register B |
save VIA 2 CRB |
CIA#2 control register B |
||
.,FEF6 AD A1 02 LDA $02A1 |
LDA ENABL ;RESTORE NMI'S EARLY... |
CIA 2 NMI-Flag holen |
get the RS-232 interrupt enable byte |
ENABL |
||
.,FEF9 8D 0D DD STA $DD0D |
STA D2ICR ; |
Interrupt Control Register |
save VIA 2 ICR |
CIA#2 interrupt control register |
||
.,FEFC A9 FF LDA #$FF |
LDA #$FF ;ENABLE COUNT FROM $FFFF |
Wert laden |
||||
.,FEFE 8D 06 DD STA $DD06 |
STA D2T2L |
und damit |
save VIA 2 timer B low byte |
|||
.,FF01 8D 07 DD STA $DD07 |
STA D2T2H ; |
Timer setzen |
save VIA 2 timer B high byte |
|||
.,FF04 4C 59 EF JMP $EF59 |
JMP RSRCVR ;GO SHIFT IN... FLNMI ; ; GET HALF BIT RATE VALUE ; |
Bit holenNMI-Routine RS 232 Ausgabe |
jump to RS232 receive routineNMI RS232 OUTThis routine sets up the baudrate for sending the bitsout, and adjusts the number of bits remaining to send. |
schedule TB2 using baud rate factor |
||
.,FF07 AD 95 02 LDA $0295 |
LDA M51AJB |
LOW- und HIGH-Byte |
nonstandard bit timing low byte |
M51AJB - non standard BPS time |
||
.,FF0A 8D 06 DD STA $DD06 |
STA D2T2L |
holen und in |
save VIA 2 timer B low byte |
timer B low |
||
.,FF0D AD 96 02 LDA $0296 |
LDA M51AJB+1 |
RS 232 Timerkonstanten für |
nonstandard bit timing high byte |
|||
.,FF10 8D 07 DD STA $DD07 |
STA D2T2H ; |
Baudrate |
save VIA 2 timer B high byte |
timer B high |
||
.,FF13 A9 11 LDA #$11 |
LDA #$11 ;ENABLE TIMER |
Timer B starten |
set timer B single shot, start timer B |
|||
.,FF15 8D 0F DD STA $DD0F |
STA D2CRB ; |
Control Register B |
save VIA 2 CRB |
CIA#2 control register B |
||
.,FF18 A9 12 LDA #$12 |
LDA #$12 ;DISABLE FLAG, ENABLE T2 |
Bit 1 und 4 für Verknüpfung |
||||
.,FF1A 4D A1 02 EOR $02A1 |
EOR ENABL |
mit NMI-Flag für CIA 2 |
EOR with the RS-232 interrupt enable byte |
|||
.,FF1D 8D A1 02 STA $02A1 |
STA ENABL ;ORA #$82 ;STA D2ICR ; |
Wert wieder speichern |
save the RS-232 interrupt enable byte |
ENABL, RS232 enables |
||
.,FF20 A9 FF LDA #$FF |
LDA #$FF ;PRESET FOR COUNT DOWN |
höchsten Wert laden |
||||
.,FF22 8D 06 DD STA $DD06 |
STA D2T2L |
und in Latch von |
save VIA 2 timer B low byte |
|||
.,FF25 8D 07 DD STA $DD07 |
STA D2T2H ; |
Timer B laden |
save VIA 2 timer B high byte |
timer B |
||
.,FF28 AE 98 02 LDX $0298 |
LDX BITNUM ;GET #OF BITS IN |
Anzahl der zu sendenden Bits |
BITNUM, number of bits still to send in this byte |
|||
.,FF2B 86 A8 STX $A8 |
STX BITCI ;PUT IN RCVRCNT |
in Zähler für Wortlänge |
BITC1, RS232 bitcount |
|||
.,FF2D 60 RTS |
RTS ; ; POPEN - PATCHES OPEN RS232 FOR UNIVERSAL KERNAL ; |
RücksprungTimerwert für Sendebaudrateermitteln |
?? |
continuation of baud rate calculation |
||
.,FF2E AA TAX |
POPEN TAX ;WE'RE CALCULATING BAUD RATE |
Baudrate aus Tabelle nach X |
||||
.,FF2F AD 96 02 LDA $0296 |
LDA M51AJB+1 ; M51AJB=FREQ/BAUD/2-100 |
HIGH-Byte holen |
nonstandard bit timing high byte |
|||
.,FF32 2A ROL |
ROL A |
mal 2 |
||||
.,FF33 A8 TAY |
TAY |
nach Y retten |
||||
.,FF34 8A TXA |
TXA |
LOW-Byte holen |
||||
.,FF35 69 C8 ADC #$C8 |
ADC #CBIT+CBIT |
plus 200 |
||||
.,FF37 8D 99 02 STA $0299 |
STA BAUDOF |
nach Timerwert LOW |
||||
.,FF3A 98 TYA |
TYA |
HIGH-Byte zurückholen |
||||
.,FF3B 69 00 ADC #$00 |
ADC #0 |
Übertrag addieren |
add any carry |
|||
.,FF3D 8D 9A 02 STA $029A |
STA BAUDOF+1 |
nach Timerwert HIGH |
||||
.,FF40 60 RTS |
RTS |
Rücksprung |
unused bytes |
|||
.,FF41 EA NOP |
NOP |
No OPeration |
waste cycles |
|||
.,FF42 EA NOP |
NOP .END .LIB IRQFILE; SIMIRQ - SIMULATE AN IRQ (FOR CASSETTE READ); ENTER BY A JSR SIMIRQ ; |
No OPerationEinsprung aus Bandroutine |
waste cyclessave the status and do the IRQ routine |
FAKE IRQ TAPE |
||
.,FF43 08 PHP |
SIMIRQ PHP |
Statusregister auf Stapel |
save the processor status |
store processor reg. |
||
.,FF44 68 PLA |
PLA ;FIX THE BREAK FLAG |
Statusregister in Akku |
pull the processor status |
get reg |
||
.,FF45 29 EF AND #$EF |
AND #$EF |
Break-Flag löschen |
mask xxx0 xxxx, clear the break bit |
clear bit4 |
||
.,FF47 48 PHA |
PHA ; PULS - CHECKS FOR REAL IRQ'S OR BREAKS ; |
und wieder auf Stapel legenIRQ-Einsprung |
save the modified processor statusIRQ vector |
store regIRQ ENTRYThis routine is pointed to by the hardware IRQ vector at$fffe. This routine is able to distinguish between a hardware IRQ, and a software BRK. The two types of interrupts are processed by its own routine. |
IRQ entry point |
|
.,FF48 48 PHA |
PULS PHA |
Akku auf Stapel retten |
save A |
Store Acc |
||
.,FF49 8A TXA |
TXA |
X nach Akku |
copy X |
|||
.,FF4A 48 PHA |
PHA |
X-Register retten |
save X |
Store X-reg |
||
.,FF4B 98 TYA |
TYA |
Y nach Akku |
copy Y |
|||
.,FF4C 48 PHA |
PHA |
Y-Register retten |
save Y |
Store Y-reg |
||
.,FF4D BA TSX |
TSX |
Stapelzeiger als Zähler in X |
copy stack pointer |
|||
.,FF4E BD 04 01 LDA $0104,X |
LDA $104,X ;GET OLD P STATUS |
Break-Flag vom Stapel holen |
get stacked status register |
Read byte on stack written by processor? |
||
.,FF51 29 10 AND #$10 |
AND #$10 ;BREAK FLAG? |
und testen |
mask BRK flag |
check bit 4 to determine HW or SW interrupt |
||
.,FF53 F0 03 BEQ $FF58 |
BEQ PULS1 ;...NO |
nicht gesetzt |
branch if not BRK |
|||
.,FF55 6C 16 03 JMP ($0316) |
JMP (CBINV) ;...YES...BREAK INSTR |
BREAK - Routine |
else do BRK vector (iBRK) |
jump to CBINV. Points to FE66, basic warm start |
normally FE66 |
|
.,FF58 6C 14 03 JMP ($0314) |
PULS1 JMP (CINV) ;...IRQ .END .LIB VECTORS |
Interrupt - RoutineVideo-Reset |
do IRQ vector (iIRQ)initialise VIC and screen editor |
jump to CINV. Points to EA31, main IRQ entry pointCINT: INIT SCREEN EDITORThe KERNAL routine CINT ($FF81) jumps to this routine. Itsets up VIC for operation. The original CINT is at $e518, and this patch checks out if this is a PAL or NTSC machine. This is done by setting the raster compare register to 311, which is the number of scanlines in a PAL machine. If no interrupt occurs, then it's a NTSC machine. |
normally EA31addition to I/O device initalisation |
|
.,FF5B 20 18 E5 JSR $E518 |
*=$FF8A-9 |
Videocontroller initialisie- ren |
initialise the screen and keyboard |
original I/O init |
||
.,FF5E AD 12 D0 LDA $D012 |
Rasterzeile |
read the raster compare register |
wait for top of screen |
|||
.,FF61 D0 FB BNE $FF5E |
wartet auf Ende Videozeile |
loop if not raster line $00 |
at line zero |
|||
.,FF63 AD 19 D0 LDA $D019 |
Interrupt durch Rasterzeile? |
read the vic interrupt flag register |
Check IRQ flag register if interrupt occured |
|||
.,FF66 29 01 AND #$01 |
Bit 0 isolieren und als Flag |
mask the raster compare flag |
only first bit |
|||
.,FF68 8D A6 02 STA $02A6 |
PAL/NTSC-Version merken |
save the PAL/NTSC flag |
store in PAL/NTSC flag |
|||
.,FF6B 4C DD FD JMP $FDDD |
Interrupttimer setzenTimer für Interrupt setzen |
?? |
jump to ENABLE TIMERSTART TIMERThis routine starts the CIA#1 timer and jumps into aroutine that handles the serial clock. |
end of scheduling TA for 1/60 second IRQ's |
||
.,FF6E A9 81 LDA #$81 |
Timer A Unterlauf |
enable timer A interrupt |
Enable IRQ when timer B reaches zero |
|||
.,FF70 8D 0D DC STA $DC0D |
Interrupt Control Register |
save VIA 1 ICR |
CIA#1 interrupt controll register |
|||
.,FF73 AD 0E DC LDA $DC0E |
Control Register A |
read VIA 1 CRA |
CIA#1 control register A |
|||
.,FF76 29 80 AND #$80 |
Bit 7 retten Uhrzeittrigger (50/60 Hz) |
mask x000 0000, TOD clock |
||||
.,FF78 09 11 ORA #$11 |
Timer A starten |
mask xxx1 xxx1, load timer A, start timer A |
Force load of timer A values -bit4, and start -bit0 |
|||
.,FF7A 8D 0E DC STA $DC0E |
Control Register A |
save VIA 1 CRA |
Action! |
|||
.,FF7D 4C 8E EE JMP $EE8E |
seriellen Takt aus |
set the serial clock out low and returnunused |
Continue to 'serial clock off'KERNAL VERSION IDThis byte contains the version number of the KERNAL. |
|||
.,FF80 00 BRK |
BReaKSprungtabelle fürBetriebssystem-Routinen |
initialise VIC and screen editor |
KERNAL JUMP TABLEThis table contains jump vectors to the I/O routines. Thisis a Commodore standard, so no matter what system you are using (VIC20, C64, C128, Plus4 etc) the jump vectors are always located at this position. |
kernal version numberkernal vectors |
||
.,FF81 4C 5B FF JMP $FF5B |
JMP CINT |
Video-Reset |
initialise VIC and screen editorinitialise SID, CIA and IRQ, unused |
CINT, init screen editor |
initalise screen and keyboard |
|
.,FF84 4C A3 FD JMP $FDA3 |
JMP IOINIT |
CIAs initialisieren |
initialise SID, CIA and IRQRAM test and find RAM end |
IOINT, init input/output |
initalise I/O devices |
|
.,FF87 4C 50 FD JMP $FD50 |
JMP RAMTAS *=$FF8A ;NEW VECTORS FOR BASIC |
RAM löschen bzw. testen |
RAM test and find RAM endrestore default I/O vectorsthis routine restores the default values of all system vectors used in KERNAL andBASIC routines and interrupts. |
RAMTAS, init RAM, tape screen |
initalise memory pointers |
|
.,FF8A 4C 15 FD JMP $FD15 |
JMP RESTOR ;RESTORE VECTORS TO INITIAL SYSTEM |
I/O initialisieren |
restore default I/O vectorsread/set vectored I/Othis routine manages all system vector jump addresses stored in RAM. Calling thisroutine with the carry bit set will store the current contents of the RAM vectors in a list pointed to by the X and Y registers. When this routine is called with the carry bit clear, the user list pointed to by the X and Y registers is copied to the system RAM vectors. NOTE: This routine requires caution in its use. The best way to use it is to first read the entire vector contents into the user area, alter the desired vectors and then copy the contents back to the system vectors. |
RESTOR, restore default I/O vector |
restore I/O vectors |
|
.,FF8D 4C 1A FD JMP $FD1A |
JMP VECTOR ;CHANGE VECTORS FOR USER * =$FF90 |
I/O Vektoren initialisieren |
read/set vectored I/Ocontrol kernal messagesthis routine controls the printing of error and control messages by the KERNAL.Either print error messages or print control messages can be selected by setting the accumulator when the routine is called. FILE NOT FOUND is an example of an error message. PRESS PLAY ON CASSETTE is an example of a control message. bits 6 and 7 of this value determine where the message will come from. If bit 7 is set one of the error messages from the KERNAL will be printed. If bit 6 is set a control message will be printed. |
VECTOR, read/set I/O vector |
set I/O vectors from XY |
|
.,FF90 4C 18 FE JMP $FE18 |
JMP SETMSG ;CONTROL O.S. MESSAGES |
Status setzen |
control kernal messagessend secondary address after LISTENthis routine is used to send a secondary address to an I/O device after a call tothe LISTEN routine is made and the device commanded to LISTEN. The routine cannot be used to send a secondary address after a call to the TALK routine. A secondary address is usually used to give set-up information to a device before I/O operations begin. When a secondary address is to be sent to a device on the serial bus the address must first be ORed with $60. |
SETMSG, control KERNAL messages |
control kernal messages |
|
.,FF93 4C B9 ED JMP $EDB9 |
JMP SECND ;SEND SA AFTER LISTEN |
Sekundäradresse nach LISTEN senden |
send secondary address after LISTENsend secondary address after TALKthis routine transmits a secondary address on the serial bus for a TALK device.This routine must be called with a number between 4 and 31 in the accumulator. The routine will send this number as a secondary address command over the serial bus. This routine can only be called after a call to the TALK routine. It will not work after a LISTEN. |
SECOND, send SA after LISTEN |
read secondary address after listen |
|
.,FF96 4C C7 ED JMP $EDC7 |
JMP TKSA ;SEND SA AFTER TALK |
Sekundäradresse nach TALK senden |
send secondary address after TALKread/set the top of memorythis routine is used to read and set the top of RAM. When this routine is calledwith the carry bit set the pointer to the top of RAM will be loaded into XY. When this routine is called with the carry bit clear XY will be saved as the top of memory pointer changing the top of memory. |
TKSA, send SA after TALK |
read secondary address after talk |
|
.,FF99 4C 25 FE JMP $FE25 |
JMP MEMTOP ;SET/READ TOP OF MEMORY |
RAM-Ende setzen/holen |
read/set the top of memoryread/set the bottom of memorythis routine is used to read and set the bottom of RAM. When this routine iscalled with the carry bit set the pointer to the bottom of RAM will be loaded into XY. When this routine is called with the carry bit clear XY will be saved as the bottom of memory pointer changing the bottom of memory. |
MEMTOP, read/set top of memory |
read/set top of memory |
|
.,FF9C 4C 34 FE JMP $FE34 |
JMP MEMBOT ;SET/READ BOTTOM OF MEMORY |
RAM-Anfang setzen/holen |
read/set the bottom of memoryscan the keyboardthis routine will scan the keyboard and check for pressed keys. It is the sameroutine called by the interrupt handler. If a key is down, its ASCII value is placed in the keyboard queue. |
MEMBOT, read/set bottom of memory |
read/set bottom of memory |
|
.,FF9F 4C 87 EA JMP $EA87 |
JMP SCNKEY ;SCAN KEYBOARD |
Tastatur abfragen |
scan keyboardset timeout on serial busthis routine sets the timeout flag for the serial bus. When the timeout flag isset, the computer will wait for a device on the serial port for 64 milliseconds. If the device does not respond to the computer's DAV signal within that time the computer will recognize an error condition and leave the handshake sequence. When this routine is called and the accumulator contains a 0 in bit 7, timeouts are enabled. A 1 in bit 7 will disable the timeouts. NOTE: The the timeout feature is used to communicate that a disk file is not found on an attempt to OPEN a file. |
SCNKEY, scan keyboard |
scan keyboard |
|
.,FFA2 4C 21 FE JMP $FE21 |
JMP SETTMO ;SET TIMEOUT IN IEEE |
Time-out-Flag für IEC-Bus setzen |
set timeout on serial businput byte from serial busthis routine reads a byte of data from the serial bus using full handshaking. thedata is returned in the accumulator. before using this routine the TALK routine, $FFB4, must have been called first to command the device on the serial bus to send data on the bus. if the input device needs a secondary command it must be sent by using the TKSA routine, $FF96, before calling this routine. errors are returned in the status word which can be read by calling the READST routine, $FFB7. |
SETTMO, set IEEE timeout |
set timout for serial bus |
|
.,FFA5 4C 13 EE JMP $EE13 |
JMP ACPTR ;HANDSHAKE IEEE BYTE IN |
Eingabe vom IEC-Bus |
input byte from serial busoutput a byte to serial busthis routine is used to send information to devices on the serial bus. A call tothis routine will put a data byte onto the serial bus using full handshaking. Before this routine is called the LISTEN routine, $FFB1, must be used to command a device on the serial bus to get ready to receive data. the accumulator is loaded with a byte to output as data on the serial bus. A device must be listening or the status word will return a timeout. This routine always buffers one character. So when a call to the UNLISTEN routine, $FFAE, is made to end the data transmission, the buffered character is sent with EOI set. Then the UNLISTEN command is sent to the device. |
ACPTR, input byte from serial bus |
input on serial bus |
|
.,FFA8 4C DD ED JMP $EDDD |
JMP CIOUT ;HANDSHAKE IEEE BYTE OUT |
Ausgabe vom IEC-Bus |
output byte to serial buscommand serial bus to UNTALKthis routine will transmit an UNTALK command on the serial bus. All devicespreviously set to TALK will stop sending data when this command is received. |
CIOUT, output byte to serial bus |
output byte on serial bus |
|
.,FFAB 4C EF ED JMP $EDEF |
JMP UNTLK ;SEND UNTALK OUT IEEE |
UNTALK senden |
command serial bus to UNTALKcommand serial bus to UNLISTENthis routine commands all devices on the serial bus to stop receiving data fromthe computer. Calling this routine results in an UNLISTEN command being transmitted on the serial bus. Only devices previously commanded to listen will be affected. This routine is normally used after the computer is finished sending data to external devices. Sending the UNLISTEN will command the listening devices to get off the serial bus so it can be used for other purposes. |
UNTALK, command serial bus UNTALK |
send untalk on serial bus |
|
.,FFAE 4C FE ED JMP $EDFE |
JMP UNLSN ;SEND UNLISTEN OUT IEEE |
UNLISTEN senden |
command serial bus to UNLISTENcommand devices on the serial bus to LISTENthis routine will command a device on the serial bus to receive data. Theaccumulator must be loaded with a device number between 4 and 31 before calling this routine. LISTEN convert this to a listen address then transmit this data as a command on the serial bus. The specified device will then go into listen mode and be ready to accept information. |
UNLSN, command serial bus UNLSN |
send unlisten on serial bus |
|
.,FFB1 4C 0C ED JMP $ED0C |
JMP LISTN ;SEND LISTEN OUT IEEE |
LISTEN senden |
command devices on the serial bus to LISTENcommand serial bus device to TALKto use this routine the accumulator must first be loaded with a device numberbetween 4 and 30. When called this routine converts this device number to a talk address. Then this data is transmitted as a command on the Serial bus. |
LISTEN, command serial bus LISTEN |
send listen on serial bus |
|
.,FFB4 4C 09 ED JMP $ED09 |
JMP TALK ;SEND TALK OUT IEEE |
TALK senden |
command serial bus device to TALKread I/O status wordthis routine returns the current status of the I/O device in the accumulator. Theroutine is usually called after new communication to an I/O device. The routine will give information about device status, or errors that have occurred during the I/O operation. |
TALK, command serial bus TALK |
send talk on serial bus |
|
.,FFB7 4C 07 FE JMP $FE07 |
JMP READSS ;RETURN I/O STATUS BYTE |
Status holen |
read I/O status wordset logical, first and second addressesthis routine will set the logical file number, device address, and secondaryaddress, command number, for other KERNAL routines. the logical file number is used by the system as a key to the file table created by the OPEN file routine. Device addresses can range from 0 to 30. The following codes are used by the computer to stand for the following CBM devices: ADDRESS DEVICE ======= ====== 0 Keyboard 1 Cassette #1 2 RS-232C device 3 CRT display 4 Serial bus printer 8 CBM Serial bus disk drive device numbers of four or greater automatically refer to devices on the serial bus. a command to the device is sent as a secondary address on the serial bus after the device number is sent during the serial attention handshaking sequence. If no secondary address is to be sent Y should be set to $FF. |
READST, read I/O status word |
read I/O status word |
|
.,FFBA 4C 00 FE JMP $FE00 |
JMP SETLFS ;SET LA, FA, SA |
Fileparameter setzen |
set logical, first and second addressesset the filenamethis routine is used to set up the file name for the OPEN, SAVE, or LOAD routines.The accumulator must be loaded with the length of the file and XY with the pointer to file name, X being th low byte. The address can be any valid memory address in the system where a string of characters for the file name is stored. If no file name desired the accumulator must be set to 0, representing a zero file length, in that case XY may be set to any memory address. |
SETLFS, set logical file parameters |
set file parameters |
|
.,FFBD 4C F9 FD JMP $FDF9 |
JMP SETNAM ;SET LENGTH AND FN ADR |
Filenamenparameter setzen |
set the filenameopen a logical filethis routine is used to open a logical file. Once the logical file is set up itcan be used for input/output operations. Most of the I/O KERNAL routines call on this routine to create the logical files to operate on. No arguments need to be set up to use this routine, but both the SETLFS, $FFBA, and SETNAM, $FFBD, KERNAL routines must be called before using this routine. |
SETNAM, set filename |
set filename parameters |
|
.,FFC0 6C 1A 03 JMP ($031A) |
OPEN JMP (IOPEN) ;OPEN LOGICAL FILE |
$F34A OPEN |
do open a logical fileclose a specified logical filethis routine is used to close a logical file after all I/O operations have beencompleted on that file. This routine is called after the accumulator is loaded with the logical file number to be closed, the same number used when the file was opened using the OPEN routine. |
OPEN, open file |
(F34A) open a file |
|
.,FFC3 6C 1C 03 JMP ($031C) |
CLOSE JMP (ICLOSE) ;CLOSE LOGICAL FILE |
$F291 CLOSE |
do close a specified logical fileopen channel for inputany logical file that has already been opened by the OPEN routine, $FFC0, can bedefined as an input channel by this routine. the device on the channel must be an input device or an error will occur and the routine will abort. if you are getting data from anywhere other than the keyboard, this routine must be called before using either the CHRIN routine, $FFCF, or the GETIN routine, $FFE4. if you are getting data from the keyboard and no other input channels are open then the calls to this routine and to the OPEN routine, $FFC0, are not needed. when used with a device on the serial bus this routine will automatically send the listen address specified by the OPEN routine, $FFC0, and any secondary address. possible errors are: 3 : file not open 5 : device not present 6 : file is not an input file |
CLOSE, close file |
(F291) close a file |
|
.,FFC6 6C 1E 03 JMP ($031E) |
CHKIN JMP (ICHKIN) ;OPEN CHANNEL IN |
$F20E CHKIN Eingabeg. setzen |
do open channel for inputopen channel for outputany logical file that has already been opened by the OPEN routine, $FFC0, can bedefined as an output channel by this routine the device on the channel must be an output device or an error will occur and the routine will abort. if you are sending data to anywhere other than the screen this routine must be called before using the CHROUT routine, $FFD2. if you are sending data to the screen and no other output channels are open then the calls to this routine and to the OPEN routine, $FFC0, are not needed. when used with a device on the serial bus this routine will automatically send the listen address specified by the OPEN routine, $FFC0, and any secondary address. possible errors are: 3 : file not open 5 : device not present 7 : file is not an output file |
CHKIN, prepare channel for input |
(F20E) set input device |
|
.,FFC9 6C 20 03 JMP ($0320) |
CKOUT JMP (ICKOUT) ;OPEN CHANNEL OUT |
$F250 CKOUT Ausgabegerät set. |
do open channel for outputclose input and output channelsthis routine is called to clear all open channels and restore the I/O channels totheir original default values. It is usually called after opening other I/O channels and using them for input/output operations. The default input device is 0, the keyboard. The default output device is 3, the screen. If one of the channels to be closed is to the serial port, an UNTALK signal is sent first to clear the input channel or an UNLISTEN is sent to clear the output channel. By not calling this routine and leaving listener(s) active on the serial bus, several devices can receive the same data from the VIC at the same time. One way to take advantage of this would be to command the printer to TALK and the disk to LISTEN. This would allow direct printing of a disk file. |
CHKOUT, prepare channel for output |
(F250) set output device |
|
.,FFCC 6C 22 03 JMP ($0322) |
CLRCH JMP (ICLRCH) ;CLOSE I/O CHANNEL |
$F333 CLRCH Ein-Ausgabe zurücksetzen |
do close input and output channelsinput character from channelthis routine will get a byte of data from the channel already set up as the inputchannel by the CHKIN routine, $FFC6. If CHKIN, $FFC6, has not been used to define another input channel the data is expected to be from the keyboard. the data byte is returned in the accumulator. the channel remains open after the call. input from the keyboard is handled in a special way. first, the cursor is turned on and it will blink until a carriage return is typed on the keyboard. all characters on the logical line, up to 80 characters, will be stored in the BASIC input buffer. then the characters can be returned one at a time by calling this routine once for each character. when the carriage return is returned the entire line has been processed. the next time this routine is called the whole process begins again. |
CLRCHN, close all I/O |
(F333) restore I/O devices to default |
|
.,FFCF 6C 24 03 JMP ($0324) |
BASIN JMP (IBASIN) ;INPUT FROM CHANNEL |
$F157 BASIN Eingabe eines Zeichens |
do input character from channeloutput character to channelthis routine will output a character to an already opened channel. Use the OPENroutine, $FFC0, and the CHKOUT routine, $FFC9, to set up the output channel before calling this routine. If these calls are omitted, data will be sent to the default output device, device 3, the screen. The data byte to be output is loaded into the accumulator, and this routine is called. The data is then sent to the specified output device. The channel is left open after the call. NOTE: Care must be taken when using routine to send data to a serial device since data will be sent to all open output channels on the bus. Unless this is desired, all open output channels on the serial bus other than the actually intended destination channel must be closed by a call to the KERNAL close channel routine. |
CHRIN, inpup byte from channel |
(F157) input char on current device |
|
.,FFD2 6C 26 03 JMP ($0326) |
BSOUT JMP (IBSOUT) ;OUTPUT TO CHANNEL |
$F1CA BSOUT Ausgabe eines Zeichens |
do output character to channelload RAM from a devicethis routine will load data bytes from any input device directly into the memoryof the computer. It can also be used for a verify operation comparing data from a device with the data already in memory, leaving the data stored in RAM unchanged. The accumulator must be set to 0 for a load operation or 1 for a verify. If the input device was OPENed with a secondary address of 0 the header information from device will be ignored. In this case XY must contain the starting address for the load. If the device was addressed with a secondary address of 1 or 2 the data will load into memory starting at the location specified by the header. This routine returns the address of the highest RAM location which was loaded. Before this routine can be called, the SETLFS, $FFBA, and SETNAM, $FFBD, routines must be called. |
CHROUT, output byte to channel |
(F1CA) output char on current device |
|
.,FFD5 4C 9E F4 JMP $F49E |
JMP LOADSP ;LOAD FROM FILE |
LOAD |
load RAM from a devicesave RAM to a devicethis routine saves a section of memory. Memory is saved from an indirect addresson page 0 specified by A, to the address stored in XY, to a logical file. The SETLFS, $FFBA, and SETNAM, $FFBD, routines must be used before calling this routine. However, a file name is not required to SAVE to device 1, the cassette. Any attempt to save to other devices without using a file name results in an error. NOTE: device 0, the keyboard, and device 3, the screen, cannot be SAVEd to. If the attempt is made, an error will occur, and the SAVE stopped. |
LOAD, load from serial device |
load ram from device |
|
.,FFD8 4C DD F5 JMP $F5DD |
JMP SAVESP ;SAVE TO FILE |
SAVE |
save RAM to deviceset the real time clockthe system clock is maintained by an interrupt routine that updates the clockevery 1/60th of a second. The clock is three bytes long which gives the capability to count from zero up to 5,184,000 jiffies - 24 hours plus one jiffy. At that point the clock resets to zero. Before calling this routine to set the clock the new time, in jiffies, should be in YXA, the accumulator containing the most significant byte. |
SAVE, save to serial device |
save ram to device |
|
.,FFDB 4C E4 F6 JMP $F6E4 |
JMP SETTIM ;SET INTERNAL CLOCK |
Time setzen |
set real time clockread the real time clockthis routine returns the time, in jiffies, in AXY. The accumulator contains themost significant byte. |
SETTIM, set realtime clock |
set real time clock |
|
.,FFDE 4C DD F6 JMP $F6DD |
JMP RDTIM ;READ INTERNAL CLOCK |
Time holen |
read real time clockscan the stop keyif the STOP key on the keyboard is pressed when this routine is called the Z flagwill be set. All other flags remain unchanged. If the STOP key is not pressed then the accumulator will contain a byte representing the last row of the keyboard scan. The user can also check for certain other keys this way. |
RDTIM, read realtime clock |
read real time clock |
|
.,FFE1 6C 28 03 JMP ($0328) |
STOP JMP (ISTOP) ;SCAN STOP KEY |
$F6ED STOP-Taste abfragen |
do scan stop keyget character from input devicein practice this routine operates identically to the CHRIN routine, $FFCF,for all devices except for the keyboard. If the keyboard is the current input device this routine will get one character from the keyboard buffer. It depends on the IRQ routine to read the keyboard and put characters into the buffer. If the keyboard buffer is empty the value returned in the accumulator will be zero. |
STOP, check <STOP> key |
(F6ED) check stop key |
|
.,FFE4 6C 2A 03 JMP ($032A) |
GETIN JMP (IGETIN) ;GET CHAR FROM Q |
$F13E GET |
do get character from input deviceclose all channels and filesthis routine closes all open files. When this routine is called, the pointers intothe open file table are reset, closing all files. Also the routine automatically resets the I/O channels. |
GETIN, get input from keyboard |
(F13E) get a character |
|
.,FFE7 6C 2C 03 JMP ($032C) |
CLALL JMP (ICLALL) ;CLOSE ALL FILES |
$F32F CLALL |
do close all channels and filesincrement real time clockthis routine updates the system clock. Normally this routine is called by thenormal KERNAL interrupt routine every 1/60th of a second. If the user program processes its own interrupts this routine must be called to update the time. Also, the STOP key routine must be called if the stop key is to remain functional. |
CLALL, close all files and channels |
(F32F) close all channels and files |
|
.,FFEA 4C 9B F6 JMP $F69B |
JMP UDTIM ;INCREMENT CLOCK |
Time erhöhen |
increment real time clockreturn X,Y organization of screenthis routine returns the x,y organisation of the screen in X,Y |
UDTIM, increment realtime clock |
increment real time clock |
|
.,FFED 4C 05 E5 JMP $E505 |
JSCROG JMP SCRORG ;SCREEN ORG |
SCREEN Anzahl Zeilen und Spalten holen |
return X,Y organization of screenread/set X,Y cursor positionthis routine, when called with the carry flag set, loads the current position ofthe cursor on the screen into the X and Y registers. X is the column number of the cursor location and Y is the row number of the cursor. A call with the carry bit clear moves the cursor to the position determined by the X and Y registers. |
SCREEN, return screen organisation |
read organisation of screen into XY |
|
.,FFF0 4C 0A E5 JMP $E50A |
JPLOT JMP PLOT ;READ/SET X,Y COORD |
Cursor setzen / Cursorposition holen |
read/set X,Y cursor positionreturn the base address of the I/O devicesthis routine will set XY to the address of the memory section where the memorymapped I/O devices are located. This address can then be used with an offset to access the memory mapped I/O devices in the computer. |
PLOT, read/set cursor X/Y position |
read/set XY cursor position |
|
.,FFF3 4C 00 E5 JMP $E500 |
JIOBAS JMP IOBASE ;RETURN I/O BASE |
Startadresse des I/O-Bausteins holen |
return the base address of the I/O devicesRRBY |
IOBASE, return IOBASE address |
read base address of I/O devicesunused |
|
.:FFF6 52 52 42 59 |
*=$FFFA |
Hardware Vektoren |
RRBYhardware vectors |
SYSTEM HARDWARE VECTORSThis table contains jumpvectors for system reset, IRQ, andNMI. The IRQ and NMI vectors points to addresses which contains an indirect jump to RAM, to provide user defined routines. |
||
.:FFFA 43 FE |
.WOR NMI ;PROGRAM DEFINEABLE |
NMI Vektor |
NMI Vektor |
NMI vector |
||
.:FFFC E2 FC |
.WOR START ;INITIALIZATION CODE |
RESET Vektor |
RESET Vektor |
RESET vector |
||
.:FFFE 48 FF |
.WOR PULS ;INTERRUPT HANDLER |
IRQ Vektor |
IRQ Vektor |
IRQ/BRK vector |