Compare commits

..

31 commits

Author SHA1 Message Date
Michael Steil
ed639a4825 kernal: kernal_mlr.txt formatting 2020-05-16 21:45:32 +02:00
Michael Steil
6683e3f308 kernal: formatting kernal_mlr.txt WIP 2020-05-16 21:42:57 +02:00
Michael Steil
2c95cb317b kernal: formatting kernal_mlr.txt WIP 2020-05-16 21:31:24 +02:00
Michael Steil
6b04ebcf20 kernal: formatting kernal_mlr.txt WIP 2020-05-16 21:17:26 +02:00
Michael Steil
89b00b236f kernal: added kernal_mlr.txt 2020-05-16 21:07:08 +02:00
Michael Steil
ca257b7736 kernal: kernal_128intern.txt formatting 2020-05-16 20:59:48 +02:00
Michael Steil
edd649e76f kernal: formatting kernal_128intern.txt WIP 2020-05-16 20:46:04 +02:00
Michael Steil
249a1aecaa kernal: added kernal_128intern.txt 2020-05-16 20:25:46 +02:00
Michael Steil
0cc5cb48c4 kernal: kernal_dh formatting 2020-05-16 20:19:28 +02:00
Michael Steil
81eaf30249 kernal: kernal_dh formatting WIP 2020-05-16 20:06:13 +02:00
Michael Steil
162936722e kernal: kernal_dh formatting WIP 2020-05-16 19:38:06 +02:00
Michael Steil
baba399bec kernal: kernal_dh formatting WIP 2020-05-16 19:24:00 +02:00
Michael Steil
12cde3c592 kernal: kernal_dh formatting WIP 2020-05-16 19:12:54 +02:00
Michael Steil
1d80964835 kernal: added kernal_dh.txt (OCRed) 2020-05-16 18:52:49 +02:00
Michael Steil
a27e7041a1 kernal: added kernal_64intern.txt 2020-05-16 12:26:25 +02:00
Michael Steil
b6b7f09527 kernal: formatted kernal_ct.txt 2020-05-16 12:10:11 +02:00
Michael Steil
52398fecf7 kernal: added kernal_ct.txt 2020-05-16 11:59:51 +02:00
Michael Steil
1d58a51d0c kernal: formatted kernal_pm.txt 2020-05-16 11:56:28 +02:00
Michael Steil
1b2f4b8c9a kernal: added kernal_pm.txt 2020-05-16 11:41:30 +02:00
Michael Steil
04f477ccad kernal: formatted kernal_ld.txt 2020-05-16 11:39:10 +02:00
Michael Steil
8116edd7a9 kernal: added kernal_ld.txt 2020-05-16 11:33:38 +02:00
Michael Steil
a1dae93e56 kernal: added kernal_fk.txt 2020-05-16 11:25:17 +02:00
Michael Steil
2eb35055e7 kernal: added kernal_sta.txt from https://sta.c64.org/cbm64krnfunc.html 2020-05-16 11:12:15 +02:00
Michael Steil
ddd58fcb87 kernal: added kernal_mapc64.md 2020-05-16 10:59:46 +02:00
Michael Steil
e39c5eb99e kernal: changed format 2020-05-16 10:41:12 +02:00
Michael Steil
0afc0df22a kernal: fixed PRG errors - http://forum.6502.org/viewtopic.php?f=2&t=5596 2020-05-16 10:25:43 +02:00
Michael Steil
23bd5666c1 kernal: formatting 2020-05-15 08:53:22 +02:00
Michael Steil
b14b904990 kernal: formatting... 2020-05-15 00:46:42 +02:00
Michael Steil
2513ac6065 kernal: formatting... 2020-05-14 23:54:31 +02:00
Michael Steil
367cefeb73 kernal: formatting... 2020-05-14 22:54:39 +02:00
Michael Steil
c84b18b9d2 kernal: added from C64 Programmer's Reference Guide 2020-05-14 22:41:10 +02:00
38 changed files with 7396 additions and 17425 deletions

View file

@ -1,31 +1,71 @@
# Ultimate Commodore 64 Reference
# Ultimate Commodore 64 BASIC & KERNAL ROM Disassembly
This project collects C64 reference material in a machine readable format and maintains a set of scripts to present these on the web.
This project maintains six commented disassemblies of the C64 ROM (BASIC and KERNAL), five in English and one in German.
The most current web version can be found at [pagetable.com/c64disasm](http://pagetable.com/c64disasm).
The txt files are the parsable master versions that can be used to create more rich representations.
* KERNAL & BASIC ROM Disassembly
* [original Microsoft BASIC source](c64disasm/c64disasm_ms.txt)
* [original Commodore KERNAL source](c64disasm/c64disasm_cbm.txt)
* [disassembly by Lee Davison](c64disasm/c64disasm_en.txt)
* [BASIC disassembly by Bob Sander-Cederlof](c64disasm/c64disasm_sc.txt)
* [disassembly from Commodore-64-intern-Buch](c64disasm/c64disasm_de.txt) (German)
* [disassembly by Magnus Nyman](c64disasm/c64disasm_mn.txt)
* [disassembly by Marko Mäkelä](c64disasm/c64disasm_mm.txt)
* Memory Map
* ["Mapping the Commodore 64" by Sheldon Leemon](c64mem/c64mem_mapc64.txt)
* ["Memory Map mit Wandervorschlägen" by Dr. H. Hauck](c64mem/c64mem_64er.txt) (German)
* ["Commodore-64-intern-Buch"](c64mem/c64mem_64intern.txt) (German)
* [reference by Joe Forster/STA](c64mem/c64mem_sta.txt)
* [comments in the original Microsoft & Commodore Source](c64mem/c64mem_src.txt)
* ["C64 Programmer's Reference Guide"](c64mem/c64mem_prg.txt)
* ["64map"](c64mem/c64mem_64map.txt)
* [reference by Jim Butterfield](c64mem/c64mem_jb.txt)
## c64disasm_ms.txt
## Credits
This is CBMBASIC only. The comments have been taken from
The files have been collected, converted, formatted and edited by [Michael Steil](mailto:mist64@mac.com).
*Microsoft's original BASIC for M6502 source, [pagetable.com/?p=774](http://www.pagetable.com/?p=774)*
Converted and formatted by Michael Steil <mist64@mac.com>
## c64disasm_cbm.txt
This is KERNAL only. The comments have been taken from
*The original C64 KERNAL source by Commodore (901227-03), [pagetable.com/?p=894](http://www.pagetable.com/?p=894), [github.com/mist64/cbmsrc](https://github.com/mist64/cbmsrc)*
Converted and formatted by Michael Steil <mist64@mac.com>
## c64disasm_en.txt
The comments have been taken from
*The almost completely commented C64 ROM disassembly. V1.01 Lee Davison 2012*
Converted and formatted by Michael Steil <mist64@mac.com>
## c64disasm_sc.txt
This is CBMBASIC only. The comments have been taken from
*Bob Sander-Cederlof: S-C DocuMentor for Applesoft, [txbobsc.com/scsc/scdocumentor](http://www.txbobsc.com/scsc/scdocumentor/)*
Converted and adapted from Applesoft to CBMBASIC, as well as formatted by Michael Steil <mist64@mac.com>
## c64disasm_de.txt
The comments have been taken from
*Baloui, Said. Das neue Commodore-64-intern-Buch. Düsseldorf: Data-Becker, 1990. ISBN 3890113079*
OCRed and formatted by Michael Steil <mist64@mac.com>
## c64disasm_mn.txt
The comments have been taken from
*JIFFYDOS version 6.01/version 6.02 by Magnus Nyman (Harlekin/FairLight)*
Converted and formatted by Michael Steil <mist64@mac.com>
## c64disasm_mm.txt
The comments have been taken from
*Commodore 64 BASIC/KERNAL ROM Disassembly Version 1.0 (June 1994), by Marko Mäkelä*
Converted and formatted by Michael Steil <mist64@mac.com>
## Side-by-side HTML version
combine.py creates a cross-referenced HTML from all commentaries.
The most current version can be found at [pagetable.com/c64disasm](http://pagetable.com/c64disasm)
## Contributing
Extensions, corrections (typos as well as content), translations etc. welcome.
Corrections (typos as well as content), translations etc. welcome.

View file

@ -1,273 +0,0 @@
#!/usr/bin/python3
import html, re, os
filenames = [
"c64disasm_ms.txt;c64disasm_cbm.txt",
"c64disasm_de.txt",
"c64disasm_en.txt",
"c64disasm_sc.txt",
"c64disasm_mn.txt",
"c64disasm_mm.txt"
]
names = [
"Microsoft/Commodore Source",
"Data Becker [German]",
"Lee Davison",
"Bob Sander-Cederlof [BASIC only]",
"Magnus Nyman [KERNAL only]",
"Marko M&auml;kel&auml;"
]
links = [
"https://github.com/mist64/cbmsrc",
"https://www.pagetable.com/?p=1015",
"https://www.pagetable.com/?p=726",
"https://www.pagetable.com/?p=728",
"https://www.telecomm.at/documents/Jiffydos_Romlisting.doc",
"http://www.unusedino.de/ec64/technical/misc/c64/romlisting.html"
]
descriptions = [
"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)<br/>and the original C64 KERNAL source by Commodore (lots of comments by the original authors)",
"German-language comments from <i>Das neue Commodore-64-intern-Buch</i> by Data Becker, ISBN 3890113079. Some minor corrections have been made.",
"Comments from <i>The almost completely commented C64 ROM disassembly V1.01</i> by Lee Davison. Some minor corrections have been made.",
"Comments adapted from <i>S-C DocuMentor for Applesoft</i> by Bob Sander-Cederlof, for the version of Microsoft BASIC that shipped with the Apple II.",
"Comments from <i>JIFFYDOS version 6.01/version 6.02</i> by Magnus Nyman (Harlekin/FairLight), which were written for the JiffyDOS KERNAL, so some serial code and all tape code is missing comments.",
"Comments from the <i>Commodore 64 BASIC/KERNAL ROM Disassembly Version 1.0 (June 1994)</i> by Marko M&auml;kel&auml;."
]
def cross_reference(string, symbols):
hex_numbers = re.findall(r'(?<!#)\$[0-9A-F][0-9A-F]+', string)
for hex_number in hex_numbers:
dec_number = int(hex_number[1:], 16)
if dec_number < 0x0400:
string = string.replace(hex_number, "<a href=\"../c64mem/#" + '{:04X}'.format(dec_number) + "\">" + hex_number + "</a>")
elif (dec_number >= 0xa000 and dec_number <= 0xbfff) or (dec_number >= 0xe000 and dec_number <= 0xffff):
string = string.replace(hex_number, "<a href=\"#" + hex_number[1:] + "\">" + hex_number + "</a>")
for symbol in symbols:
string = re.sub('\\b' + symbol + '\\b', '<a href="../c64mem/#' + symbol + '">' + symbol + '</a>', string)
return string
asm_donor_index = 1
source_index = 0 # we treat the Microsoft/Commodore source differently
f = os.popen("git log -1 --pretty=format:%h .")
revision = f.read()
f = os.popen("git log -1 --date=short --pretty=format:%cd .")
date = f.read()
symbols = []
symbol_lines = [line.rstrip() for line in open('../c64mem/c64mem_src.txt')]
for line in symbol_lines:
if line.startswith('#') or line.startswith('-'):
continue
symbol = line[13:19].rstrip()
if symbol != '':
symbols.append(symbol)
symbols = set(symbols)
data = []
linenumber = []
address = []
for filename in filenames:
d = []
for f in filename.split(";"):
d += [line.rstrip() for line in open(f)]
data.append(d)
linenumber.append(0)
address.append(0)
files = len(filenames)
asmaddress = 0
asmlinenumber = 0
for i in range(0, files):
while True:
line = data[i][linenumber[i]]
if len(line) > 0 and line[0] == '.':
break
linenumber[i] = linenumber[i] + 1
print('<meta http-equiv="Content-type" content="text/html; charset=utf-8" />')
print('<html>')
print('<head>')
print('<title>BASIC & KERNAL ROM Disassembly | Ultimate C64 Reference</title>')
print('')
print('<script language="javascript">')
print(' window.onload = init;')
print(' function init() {')
print(' var tbl = document.getElementById("disassembly_table");')
print(' for (var i = 0; i < ' + str(len(filenames)) + '; i++) {')
print(' var key = "com.pagetable.c64disasm.column_" + i;')
print(' var element_name = "checkbox_" + i;')
print(' var checked = localStorage.getItem(key) != "hidden";')
print(' document.getElementById(element_name).checked = checked;')
print(' hideCol(i, checked);')
print(' }')
print(' }')
print(' function hideCol(col, checked) {')
print(' var tbl = document.getElementById("disassembly_table");')
print(' for (var i = 0; i < tbl.rows.length; i++) {')
print(' tbl.rows[i].cells[col+1].style.display = checked ? "" : "none";')
print(' }')
print(' var key = "com.pagetable.c64disasm.column_" + col;')
print(' if (checked) {')
print(' localStorage.removeItem(key);')
print(' } else {')
print(' localStorage.setItem(key, "hidden");')
print(' }')
print(' }')
print('</script>')
print('')
print('<link rel="stylesheet" href="../style.css">')
print('<style type="text/css">')
print('')
print('h3 {')
print(' font-family: serif;')
print('}')
print('')
print('.com {')
print(' white-space: pre;')
print('}')
print('')
print('div.disassembly_container {')
print(' padding: 1em 0em 1em 16em;')
print(' overflow: scroll;')
print('}')
print('')
print('table.disassembly_table td, table.disassembly_table th {')
print(' font-family: monospace;')
print('}')
print('')
print('table.disassembly_table th.left_column {')
print(' width: 18em;')
print('}')
print('')
print('</style>')
print('</head>')
print('<body>')
# http://tholman.com/github-corners/
print('<a href="https://github.com/mist64/c64ref" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:var(--main-color); color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>')
print('<div class="topnav">')
print(' <h1>Ultimate Commodore 64 Reference</h1> ')
#print(' <a href="#">KERNAL API</a><!-- kernal/ -->')
print(' <a class="active" href="../c64disasm/">ROM Disassembly</a><!-- c64disasm/ -->')
print(' <a href="../c64mem/">Memory Map</a><!-- c64mem/ -->')
#print(' <a href="#">I/O Map</a><!-- c64io/ -->')
#print(' <a href="#">6502 CPU</a><!-- 6502/ -->')
print('</div>')
print('<div class="body">')
print('<h1>C64 BASIC & KERNAL ROM Disassembly</h1>')
print('<p><i>by <a href="http://www.pagetable.com/">Michael Steil</a>, <a href="https://github.com/mist64/c64ref">github.com/mist64/c64ref</a>. Revision ' + revision + ', ' + date + '</i></p>')
print('<b>This allows you to view different commentaries side-by-side. You can enable/disable individual columns:</b><br/><br/>')
print('<table class="checkbox_table">')
for i in range(0, len(filenames)):
print('<tr><td><input type="checkbox" id="checkbox_' + str(i) + '" checked onclick="hideCol(' + str(i) + ', document.getElementById(\'checkbox_' + str(i) + '\').checked);" /></td><td style="white-space: nowrap;"><b><a href="' + links[i] + '">' + names[i] + '</a></b><td>' + descriptions[i] + '</td></tr>')
print('</table>')
print('<div class="disassembly_container">')
print('<table id="disassembly_table" class="disassembly_table">')
print('<tr>')
print('<th class="left_column">Disassembly</th>')
for i in range(0, files):
print('<th class="top_row">' + names[i] + '</th>')
print('</tr>')
count = 0
while(True):
count += 1
# if count > 80:
# break
for i in range(0, files):
if linenumber[i] >= len(data[i]):
continue
while len(data[i][linenumber[i]]) > 0 and (data[i][linenumber[i]][0] == '-' or data[i][linenumber[i]][0] == '#'):
linenumber[i] = linenumber[i] + 1
if asmlinenumber >= len(data[asm_donor_index]):
break
asm = data[asm_donor_index][asmlinenumber][0:32].rstrip()
asmlinenumber = asmlinenumber + 1
if len(asm) == 0:
continue
if asm[0] == '#' or asm[0] == '-':
continue
has_address = False
if asm[0] == '.':
hexaddress = asm[2:6]
asmaddress = int(hexaddress, 16)
has_address = True
asm = cross_reference(asm, symbols)
print('<tr>')
print('<th class="left_column">')
if has_address:
print('<a name="' + hexaddress + '" />')
print('<span class="com">' + asm + '</span></th>')
for i in range(0, files):
print('<td>')
comments = []
while True:
if linenumber[i] >= len(data[i]):
break
line = data[i][linenumber[i]]
if line.startswith('.'):
address[i] = int(line[2:6], 16)
if address[i] > asmaddress:
break
comment = line[32:]
comment = html.escape(comment)
comment = cross_reference(comment, symbols)
if comment.startswith('***'):
comment = '<h3>' + comment[3:] + '</h3>'
elif comment.startswith('SUBTTL'):
comment = '<h3>' + comment[6:] + '</h3>'
elif comment.startswith('.LIB '):
comment = '<h3>' + comment + '</h3>'
else:
scomment = comment.lstrip()
if scomment.startswith(';'):
comment = '<b>' + comment + '</b>'
if len(comment) != 0:
comment = '<span class="com">' + comment + '</span><br />'
if len(comment) != 0:
comments.append(comment)
linenumber[i] = linenumber[i] + 1
if len(comments):
for comment in comments:
print(comment)
else:
print('&nbsp;')
print('</td>')
print('</tr>')
print('</table>')
print('</div>')
print('</div>')
print('</body>')
print('</html>')

View file

@ -3,7 +3,7 @@
- CBMBASIC and KERNAL
-
- The comments have been taken from
- Baloui, Brückmann, Englisch, Felt, Gelfand, Gerits, Krsnik:
- Baloui, Said.
- Das neue Commodore-64-intern-Buch.
- Düsseldorf: Data-Becker, 1990.
- ISBN 3890113079

View file

@ -11,10 +11,6 @@
- up perfectly, so make sure the machine code matches the assembly
- code in the respective lines your looking at.
-
- The range $E0F9-$E261 was taken from
- The original C64 BASIC source by Commodore
- https://github.com/mist64/cbmsrc
-
- Converted and formatted by Michael Steil <mist64@mac.com>
-
- Corrections (formatting, lining up) welcome at:
@ -6754,239 +6750,167 @@
.,E0F4 A0 00 LDY #$00
.,E0F6 4C D4 BB JMP $BBD4 GMOVMF: JMP MOVMF ;PUT NEW ONE INTO MEMORY.
.,E0F9 C9 F0 CMP #$F0 EREXIT CMP #$F0 ;CHECK FOR SPECIAL CASE
.,E0FB D0 07 BNE $E104 BNE EREXIX
; TOP OF MEMORY HAS CHANGED
.,E0FD 84 38 STY $38 STY MEMSIZ+1
.,E0FF 86 37 STX $37 STX MEMSIZ
.,E101 4C 63 A6 JMP $A663 JMP CLEART ;ACT AS IF HE TYPED CLEAR
.,E104 AA TAX EREXIX TAX ;SET TERMINATION FLAGS
.,E105 D0 02 BNE $E109 BNE EREXIY
.,E107 A2 1E LDX #$1E LDX #ERBRK ;BREAK ERROR
.,E109 4C 37 A4 JMP $A437 EREXIY JMP ERROR ;NORMAL ERROR
CLSCHN =$FFCC
.,E10C 20 D2 FF JSR $FFD2 OUTCH JSR $FFD2
.,E10F B0 E8 BCS $E0F9 BCS EREXIT
.,E111 60 RTS RTS
.,E112 20 CF FF JSR $FFCF INCHR JSR $FFCF
.,E115 B0 E2 BCS $E0F9 BCS EREXIT
.,E117 60 RTS RTS
CCALL =$FFE7
SETTIM =$FFDB
RDTIM =$FFDE
.,E118 20 AD E4 JSR $E4AD COOUT JSR PPACH ; GO OUT TO SAVE .A FOR PRINT# PATCH
.,E11B B0 DC BCS $E0F9 BCS EREXIT
.,E11D 60 RTS RTS
.,E11E 20 C6 FF JSR $FFC6 COIN JSR $FFC6
.,E121 B0 D6 BCS $E0F9 BCS EREXIT
.,E123 60 RTS RTS
READST =$FFB7
.,E124 20 E4 FF JSR $FFE4 CGETL JSR $FFE4
.,E127 B0 D0 BCS $E0F9 BCS EREXIT
.,E129 60 RTS RTS
RDBAS =$FFF3
SETMSG =$FF90
PLOT =$FFF0
.,E12A 20 8A AD JSR $AD8A CSYS JSR FRMNUM ;EVAL FORMULA
.,E12D 20 F7 B7 JSR $B7F7 JSR GETADR ;CONVERT TO INT. ADDR
.,E130 A9 E1 LDA #$E1 LDA #>CSYSRZ ;PUSH RETURN ADDRESS
.,E132 48 PHA PHA
.,E133 A9 46 LDA #$46 LDA #<CSYSRZ
.,E135 48 PHA PHA
.,E136 AD 0F 03 LDA $030F LDA SPREG ;STATUS REG
.,E139 48 PHA PHA
.,E13A AD 0C 03 LDA $030C LDA SAREG ;LOAD 6502 REGS
.,E13D AE 0D 03 LDX $030D LDX SXREG
.,E140 AC 0E 03 LDY $030E LDY SYREG
.,E143 28 PLP PLP ;LOAD 6502 STATUS REG
.,E144 6C 14 00 JMP ($0014) JMP (LINNUM) ;GO DO IT
CSYSRZ =*-1 ;RETURN TO HERE
.,E147 08 PHP PHP ;SAVE STATUS REG
.,E148 8D 0C 03 STA $030C STA SAREG ;SAVE 6502 REGS
.,E14B 8E 0D 03 STX $030D STX SXREG
.,E14E 8C 0E 03 STY $030E STY SYREG
.,E151 68 PLA PLA ;GET STATUS REG
.,E152 8D 0F 03 STA $030F STA SPREG
.,E155 60 RTS RTS ;RETURN TO SYSTEM
.,E156 20 D4 E1 JSR $E1D4 CSAVE JSR PLSV ;PARSE PARMS
.,E159 A6 2D LDX $2D LDX VARTAB ;END SAVE ADDR
.,E15B A4 2E LDY $2E LDY VARTAB+1
.,E15D A9 2B LDA #$2B LDA #<TXTTAB ;INDIRECT WITH START ADDRESS
.,E15F 20 D8 FF JSR $FFD8 JSR $FFD8 ;SAVE IT
.,E162 B0 95 BCS $E0F9 BCS EREXIT
.,E164 60 RTS RTS
.,E165 A9 01 LDA #$01 CVERF LDA #1 ;VERIFY FLAG
.:E167 2C .BYTE $2C .BYT $2C ;SKIP TWO BYTES
.,E168 A9 00 LDA #$00 CLOAD LDA #0 ;LOAD FLAG
.,E16A 85 0A STA $0A STA VERCK
.,E16C 20 D4 E1 JSR $E1D4 JSR PLSV ;PARSE PARAMETERS
;
CLD10 ; JSR $FFE1 ;CHECK RUN/STOP
; CMP #$FF ;DONE YET?
; BNE CLD10 ;STILL BOUNCING
.,E16F A5 0A LDA $0A LDA VERCK
.,E171 A6 2B LDX $2B LDX TXTTAB ;.X AND .Y HAVE ALT...
.,E173 A4 2C LDY $2C LDY TXTTAB+1 ;...LOAD ADDRESS
.,E175 20 D5 FF JSR $FFD5 JSR $FFD5 ;LOAD IT
.,E178 B0 57 BCS $E1D1 BCS JERXIT ;PROBLEMS
;
.,E17A A5 0A LDA $0A LDA VERCK
.,E17C F0 17 BEQ $E195 BEQ CLD50 ;WAS LOAD
;
;FINISH VERIFY
;
.,E17E A2 1C LDX #$1C LDX #ERVFY ;ASSUME ERROR
.,E180 20 B7 FF JSR $FFB7 JSR $FFB7 ;READ STATUS
.,E183 29 10 AND #$10 AND #$10 ;CHECK ERROR
.,E185 D0 17 BNE $E19E BNE CLD55 ;REPLACES BEQ *+5/JMP ERROR
;
;PRINT VERIFY 'OK' IF DIRECT
;
.,E187 A5 7A LDA $7A LDA TXTPTR
.,E189 C9 02 CMP #$02 CMP #BUFPAG
.,E18B F0 07 BEQ $E194 BEQ CLD20
.,E18D A9 64 LDA #$64 LDA #<OKMSG
.,E18F A0 A3 LDY #$A3 LDY #>OKMSG
.,E191 4C 1E AB JMP $AB1E JMP STROUT
;
.,E194 60 RTS CLD20 RTS
;
;FINISH LOAD
;
.,E195 20 B7 FF JSR $FFB7 CLD50 JSR $FFB7 ;READ STATUS
.,E198 29 BF AND #$BF AND #$FF-$40 ;CLEAR E.O.I.
.,E19A F0 05 BEQ $E1A1 BEQ CLD60 ;WAS O.K.
.,E19C A2 1D LDX #$1D LDX #ERLOAD
.,E19E 4C 37 A4 JMP $A437 CLD55 JMP ERROR
;
.,E1A1 A5 7B LDA $7B CLD60 LDA TXTPTR+1
.,E1A3 C9 02 CMP #$02 CMP #BUFPAG ;DIRECT?
.,E1A5 D0 0E BNE $E1B5 BNE CLD70 ;NO...
;
.,E1A7 86 2D STX $2D STX VARTAB
.,E1A9 84 2E STY $2E STY VARTAB+1 ;END LOAD ADDRESS
.,E1AB A9 76 LDA #$76 LDA #<REDDY
.,E1AD A0 A3 LDY #$A3 LDY #>REDDY
.,E1AF 20 1E AB JSR $AB1E JSR STROUT
.,E1B2 4C 2A A5 JMP $A52A JMP FINI
;
;PROGRAM LOAD
;
.,E1B5 20 8E A6 JSR $A68E CLD70 JSR STXTPT
.,E1B8 20 33 A5 JSR $A533 JSR LNKPRG
.,E1BB 4C 77 A6 JMP $A677 JMP FLOAD
.,E1BE 20 19 E2 JSR $E219 COPEN JSR PAOC ;PARSE STATEMENT
.,E1C1 20 C0 FF JSR $FFC0 JSR $FFC0 ;OPEN IT
.,E1C4 B0 0B BCS $E1D1 BCS JERXIT ;BAD STUFF OR MEMSIZ CHANGE
.,E1C6 60 RTS RTS ;A.O.K.
.,E1C7 20 19 E2 JSR $E219 CCLOS JSR PAOC ;PARSE STATEMENT
.,E1CA A5 49 LDA $49 LDA ANDMSK ;GET LA
.,E1CC 20 C3 FF JSR $FFC3 JSR $FFC3 ;CLOSE IT
.,E1CF 90 C3 BCC $E194 BCC CLD20 ;IT'S OKAY...NO MEMSIZE CHANGE
;
.,E1D1 4C F9 E0 JMP $E0F9 JERXIT JMP EREXIT
;
;PARSE LOAD AND SAVE COMMANDS
;
PLSV
;DEFAULT FILE NAME
;
.,E1D4 A9 00 LDA #$00 LDA #0 ;LENGTH=0
.,E1D6 20 BD FF JSR $FFBD JSR $FFBD
;
;DEFAULT DEVICE #
;
.,E1D9 A2 01 LDX #$01 LDX #1 ;DEVICE #1
.,E1DB A0 00 LDY #$00 LDY #0 ;COMMAND 0
.,E1DD 20 BA FF JSR $FFBA JSR $FFBA
;
.,E1E0 20 06 E2 JSR $E206 JSR PAOC20 ;BY-PASS JUNK
.,E1E3 20 57 E2 JSR $E257 JSR PAOC15 ;GET/SET FILE NAME
.,E1E6 20 06 E2 JSR $E206 JSR PAOC20 ;BY-PASS JUNK
.,E1E9 20 00 E2 JSR $E200 JSR PLSV7 ;GET ',FA'
.,E1EC A0 00 LDY #$00 LDY #0 ;COMMAND 0
.,E1EE 86 49 STX $49 STX ANDMSK
.,E1F0 20 BA FF JSR $FFBA JSR $FFBA
.,E1F3 20 06 E2 JSR $E206 JSR PAOC20 ;BY-PASS JUNK
.,E1F6 20 00 E2 JSR $E200 JSR PLSV7 ;GET ',SA'
.,E1F9 8A TXA TXA ;NEW COMMAND
.,E1FA A8 TAY TAY
.,E1FB A6 49 LDX $49 LDX ANDMSK ;DEVICE #
.,E1FD 4C BA FF JMP $FFBA JMP $FFBA
;LOOK FOR COMMA FOLLOWED BY BYTE
.,E200 20 0E E2 JSR $E20E PLSV7 JSR PAOC30
.,E203 4C 9E B7 JMP $B79E JMP GETBYT
;SKIP RETURN IF NEXT CHAR IS END
;
.,E206 20 79 00 JSR $0079 PAOC20 JSR CHRGOT
.,E209 D0 02 BNE $E20D BNE PAOCX
.,E20B 68 PLA PLA
.,E20C 68 PLA PLA
.,E20D 60 RTS PAOCX RTS
;CHECK FOR COMMA AND GOOD STUFF
;
.,E20E 20 FD AE JSR $AEFD PAOC30 JSR CHKCOM ;CHECK COMMA
.,E211 20 79 00 JSR $0079 PAOC32 JSR CHRGOT ;GET CURRENT
.,E214 D0 F7 BNE $E20D BNE PAOCX ;IS O.K.
.,E216 4C 08 AF JMP $AF08 PAOC40 JMP SNERR ;BAD...END OF LINE
;PARSE OPEN/CLOSE
;
.,E219 A9 00 LDA #$00 PAOC LDA #0
.,E21B 20 BD FF JSR $FFBD JSR $FFBD ;DEFAULT FILE NAME
;
.,E21E 20 11 E2 JSR $E211 JSR PAOC32 ;MUST GOT SOMETHING
.,E221 20 9E B7 JSR $B79E JSR GETBYT ;GET LA
.,E224 86 49 STX $49 STX ANDMSK
.,E226 8A TXA TXA
.,E227 A2 01 LDX #$01 LDX #1 ;DEFAULT DEVICE
.,E229 A0 00 LDY #$00 LDY #0 ;DEFAULT COMMAND
.,E22B 20 BA FF JSR $FFBA JSR $FFBA ;STORE IT
.,E22E 20 06 E2 JSR $E206 JSR PAOC20 ;SKIP JUNK
.,E231 20 00 E2 JSR $E200 JSR PLSV7
.,E234 86 4A STX $4A STX EORMSK
.,E236 A0 00 LDY #$00 LDY #0 ;DEFAULT COMMAND
.,E238 A5 49 LDA $49 LDA ANDMSK ;GET LA
.,E23A E0 03 CPX #$03 CPX #3
.,E23C 90 01 BCC $E23F BCC PAOC5
.,E23E 88 DEY DEY ;DEFAULT IEEE TO $FF
.,E23F 20 BA FF JSR $FFBA PAOC5 JSR $FFBA ;STORE THEM
.,E242 20 06 E2 JSR $E206 JSR PAOC20 ;SKIP JUNK
.,E245 20 00 E2 JSR $E200 JSR PLSV7 ;GET SA
.,E248 8A TXA TXA
.,E249 A8 TAY TAY
.,E24A A6 4A LDX $4A LDX EORMSK
.,E24C A5 49 LDA $49 LDA ANDMSK
.,E24E 20 BA FF JSR $FFBA JSR $FFBA ;SET UP REAL EVEYTHING
.,E251 20 06 E2 JSR $E206 PAOC7 JSR PAOC20
.,E254 20 0E E2 JSR $E20E JSR PAOC30
.,E257 20 9E AD JSR $AD9E PAOC15 JSR FRMEVL
.,E25A 20 A3 B6 JSR $B6A3 JSR FRESTR ;LENGTH IN .A
.,E25D A6 22 LDX $22 LDX INDEX1
.,E25F A4 23 LDY $23 LDY INDEX1+1
.,E261 4C BD FF JMP $FFBD JMP $FFBD
.,E0F9 C9 F0 CMP #$F0
.,E0FB D0 07 BNE $E104
.,E0FD 84 38 STY $38
.,E0FF 86 37 STX $37
.,E101 4C 63 A6 JMP $A663
.,E104 AA TAX
.,E105 D0 02 BNE $E109
.,E107 A2 1E LDX #$1E
.,E109 4C 37 A4 JMP $A437
.,E10C 20 D2 FF JSR $FFD2
.,E10F B0 E8 BCS $E0F9
.,E111 60 RTS
.,E112 20 CF FF JSR $FFCF
.,E115 B0 E2 BCS $E0F9
.,E117 60 RTS
.,E118 20 AD E4 JSR $E4AD
.,E11B B0 DC BCS $E0F9
.,E11D 60 RTS
.,E11E 20 C6 FF JSR $FFC6
.,E121 B0 D6 BCS $E0F9
.,E123 60 RTS
.,E124 20 E4 FF JSR $FFE4
.,E127 B0 D0 BCS $E0F9
.,E129 60 RTS
.,E12A 20 8A AD JSR $AD8A
.,E12D 20 F7 B7 JSR $B7F7
.,E130 A9 E1 LDA #$E1
.,E132 48 PHA
.,E133 A9 46 LDA #$46
.,E135 48 PHA
.,E136 AD 0F 03 LDA $030F
.,E139 48 PHA
.,E13A AD 0C 03 LDA $030C
.,E13D AE 0D 03 LDX $030D
.,E140 AC 0E 03 LDY $030E
.,E143 28 PLP
.,E144 6C 14 00 JMP ($0014)
.,E147 08 PHP
.,E148 8D 0C 03 STA $030C
.,E14B 8E 0D 03 STX $030D
.,E14E 8C 0E 03 STY $030E
.,E151 68 PLA
.,E152 8D 0F 03 STA $030F
.,E155 60 RTS
.,E156 20 D4 E1 JSR $E1D4
.,E159 A6 2D LDX $2D
.,E15B A4 2E LDY $2E
.,E15D A9 2B LDA #$2B
.,E15F 20 D8 FF JSR $FFD8
.,E162 B0 95 BCS $E0F9
.,E164 60 RTS
.,E165 A9 01 LDA #$01
.:E167 2C .BYTE $2C
.,E168 A9 00 LDA #$00
.,E16A 85 0A STA $0A
.,E16C 20 D4 E1 JSR $E1D4
.,E16F A5 0A LDA $0A
.,E171 A6 2B LDX $2B
.,E173 A4 2C LDY $2C
.,E175 20 D5 FF JSR $FFD5
.,E178 B0 57 BCS $E1D1
.,E17A A5 0A LDA $0A
.,E17C F0 17 BEQ $E195
.,E17E A2 1C LDX #$1C
.,E180 20 B7 FF JSR $FFB7
.,E183 29 10 AND #$10
.,E185 D0 17 BNE $E19E
.,E187 A5 7A LDA $7A
.,E189 C9 02 CMP #$02
.,E18B F0 07 BEQ $E194
.,E18D A9 64 LDA #$64
.,E18F A0 A3 LDY #$A3
.,E191 4C 1E AB JMP $AB1E
.,E194 60 RTS
.,E195 20 B7 FF JSR $FFB7
.,E198 29 BF AND #$BF
.,E19A F0 05 BEQ $E1A1
.,E19C A2 1D LDX #$1D
.,E19E 4C 37 A4 JMP $A437
.,E1A1 A5 7B LDA $7B
.,E1A3 C9 02 CMP #$02
.,E1A5 D0 0E BNE $E1B5
.,E1A7 86 2D STX $2D
.,E1A9 84 2E STY $2E
.,E1AB A9 76 LDA #$76
.,E1AD A0 A3 LDY #$A3
.,E1AF 20 1E AB JSR $AB1E
.,E1B2 4C 2A A5 JMP $A52A
.,E1B5 20 8E A6 JSR $A68E
.,E1B8 20 33 A5 JSR $A533
.,E1BB 4C 77 A6 JMP $A677
.,E1BE 20 19 E2 JSR $E219
.,E1C1 20 C0 FF JSR $FFC0
.,E1C4 B0 0B BCS $E1D1
.,E1C6 60 RTS
.,E1C7 20 19 E2 JSR $E219
.,E1CA A5 49 LDA $49
.,E1CC 20 C3 FF JSR $FFC3
.,E1CF 90 C3 BCC $E194
.,E1D1 4C F9 E0 JMP $E0F9
.,E1D4 A9 00 LDA #$00
.,E1D6 20 BD FF JSR $FFBD
.,E1D9 A2 01 LDX #$01
.,E1DB A0 00 LDY #$00
.,E1DD 20 BA FF JSR $FFBA
.,E1E0 20 06 E2 JSR $E206
.,E1E3 20 57 E2 JSR $E257
.,E1E6 20 06 E2 JSR $E206
.,E1E9 20 00 E2 JSR $E200
.,E1EC A0 00 LDY #$00
.,E1EE 86 49 STX $49
.,E1F0 20 BA FF JSR $FFBA
.,E1F3 20 06 E2 JSR $E206
.,E1F6 20 00 E2 JSR $E200
.,E1F9 8A TXA
.,E1FA A8 TAY
.,E1FB A6 49 LDX $49
.,E1FD 4C BA FF JMP $FFBA
.,E200 20 0E E2 JSR $E20E
.,E203 4C 9E B7 JMP $B79E
.,E206 20 79 00 JSR $0079
.,E209 D0 02 BNE $E20D
.,E20B 68 PLA
.,E20C 68 PLA
.,E20D 60 RTS
.,E20E 20 FD AE JSR $AEFD
.,E211 20 79 00 JSR $0079
.,E214 D0 F7 BNE $E20D
.,E216 4C 08 AF JMP $AF08
.,E219 A9 00 LDA #$00
.,E21B 20 BD FF JSR $FFBD
.,E21E 20 11 E2 JSR $E211
.,E221 20 9E B7 JSR $B79E
.,E224 86 49 STX $49
.,E226 8A TXA
.,E227 A2 01 LDX #$01
.,E229 A0 00 LDY #$00
.,E22B 20 BA FF JSR $FFBA
.,E22E 20 06 E2 JSR $E206
.,E231 20 00 E2 JSR $E200
.,E234 86 4A STX $4A
.,E236 A0 00 LDY #$00
.,E238 A5 49 LDA $49
.,E23A E0 03 CPX #$03
.,E23C 90 01 BCC $E23F
.,E23E 88 DEY
.,E23F 20 BA FF JSR $FFBA
.,E242 20 06 E2 JSR $E206
.,E245 20 00 E2 JSR $E200
.,E248 8A TXA
.,E249 A8 TAY
.,E24A A6 4A LDX $4A
.,E24C A5 49 LDA $49
.,E24E 20 BA FF JSR $FFBA
.,E251 20 06 E2 JSR $E206
.,E254 20 0E E2 JSR $E20E
.,E257 20 9E AD JSR $AD9E
.,E25A 20 A3 B6 JSR $B6A3
.,E25D A6 22 LDX $22
.,E25F A4 23 LDY $23
.,E261 4C BD FF JMP $FFBD
PAGE
SUBTTL SINE, COSINE AND TANGENT FUNCTIONS.

File diff suppressed because it is too large Load diff

View file

@ -1,373 +0,0 @@
- C64 I/O Map (Programmer's Reference Guide)
-
- C64PRG10.TXT
-
- practically the same:
- 64MAP10.TXT/Commodore_64_IO_Maps.doc
- 64MAP10.TXT/Commodore_64_Memory_Maps.txt
------------------------------------------------------------
-
# [...]
0000 0 7-0 MOS 6510 Data Direction
Register (xx101111)
Bit= 1: Output, Bit=0:
Input, x=Don't Care
0001 1 MOS 6510 Micro-Processor
On-Chip I/O Port
0 /LORAM Signal (0=Switch BASIC ROM Out)
1 /HIRAM Signal (0=Switch Kernal ROM Out)
2 /CHAREN Signal (0=Switch Char. ROM In)
3 Cassette Data Output Line
4 Cassette Switch Sense: 1 = Switch Closed
5 Cassette Motor Control 0 = ON, 1 = OFF
6-7 Undefined
D000-D02E 53248-54271 MOS 6566 VIDEO INTERFACE CONTROLLER
(VIC)
D000 53248 Sprite 0 X Pos
D001 53249 Sprite 0 Y Pos
D002 53250 Sprite 1 X Pos
D003 53251 Sprite 1 Y Pos
D004 53252 Sprite 2 X Pos
D005 53253 Sprite 2 Y Pos
D006 53254 Sprite 3 X Pos
D007 53255 Sprite 3 Y Pos
D008 53256 Sprite 4 X Pos
D009 53257 Sprite 4 Y Pos
D00A 53258 Sprite 5 X Pos
D00B 53259 Sprite 5 Y Pos
D00C 53260 Sprite 6 X Pos
D00D 53261 Sprite 6 Y Pos
D00E 53262 Sprite 7 X Pos
D00F 53263 Sprite 7 Y Pos
D010 53264 Sprites 0-7 X Pos (msb of X coord.)
D011 53265 VIC Control Register
7 Raster Compare: (Bit 8) See 53266
6 Extended Color Text Mode 1 = Enable
5 Bit Map Mode. 1 = Enable
4 Blank Screen to Border Color: 0 = Blank
3 Select 24/25 Row Text Display: 1=25 Rows
2-0 Smooth Scroll to Y Dot-Position (0-7)
D012 53266 Read Raster/Write Raster Value for
Compare IRQ
D013 53267 Light-Pen Latch X Pos
D014 53268 Light-Pen Latch Y Pos
D015 53269 Sprite display Enable: 1 = Enable
D016 53270 VIC Control Register
7-6 Unused
5 ALWAYS SET THIS BIT TO 0 !
4 Multi-Color Mode: 1 = Enable (Text or
Bit-Map)
3 Select 38/40 Column Text Display:
1 = 40 Cols
2-0 Smooth Scroll to X Pos
D017 53271 Sprites 0-7 Expand 2x Vertical (Y)
D018 53272 VIC Memory Control Register
7-4 Video Matrix Base Address (inside VIC)
3-1 Character Dot-Data Base Address (inside
VIC)
0 Select upper/lower Character Set
D019 53273 VIC Interrupt Flag Register (Bit = 1:
IRQ Occurred)
7 Set on Any Enabled VIC IRQ Condition
3 Light-Pen Triggered IRQ Flag
2 Sprite to Sprite Collision IRQ Flag
1 Sprite to Background Collision IRQ Flag
0 Raster Compare IRQ Flag
D01A 53274 IRQ Mask Register: 1 = Interrupt Enabled
D01B 53275 Sprite to Background Display Priority:
1 = Sprite
D01C 53276 Sprites 0-7 Multi-Color Mode Select:
1 = M.C.M.
D01D 53277 Sprites 0-7 Expand 2x Horizontal (X)
D01E 53278 Sprite to Sprite Collision Detect
D01F 53279 Sprite to Background Collision Detect
D020 53280 Border Color
D021 53281 Background Color 0
D022 53282 Background Color 1
D023 53283 Background Color 2
D024 53284 Background Color 3
D025 53285 Sprite Multi-Color Register 0
D026 53286 Sprite Multi-Color Register 1
D027 53287 Sprite 0 Color
D028 53288 Sprite 1 Color
D029 53289 Sprite 2 Color
D02A 53290 Sprite 3 Color
D02B 53291 Sprite 4 Color
D02C 53292 Sprite 5 Color
D02D 53293 Sprite 6 Color
D02E 53294 Sprite 7 Color
D400-D7FF 54272-55295 MOS 6581 SOUND INTERFACE DEVICE (SID)
D400 54272 Voice 1: Frequency Control - Low-Byte
D401 54273 Voice 1: Frequency Control - High-Byte
D402 54274 Voice 1: Pulse Waveform Width - Low-Byte
D403 54275 7-4 Unused
3-0 Voice 1: Pulse Waveform Width - High-
Nybble
D404 54276 Voice 1: Control Register
7 Select Random Noise Waveform, 1 = On
6 Select Pulse Waveform, 1 = On
5 Select Sawtooth Waveform, 1 = On
4 Select Triangle Waveform, 1 = On
3 Test Bit: 1 = Disable Oscillator 1
2 Ring Modulate Osc. 1 with Osc. 3 Output,
1 = On
1 Synchronize Osc.1 with Osc.3 Frequency,
1 = On
0 Gate Bit: 1 = Start Att/Dec/Sus,
0 = Start Release
D405 54277 Envelope Generator 1: Attack/Decay Cycle
Control
7-4 Select Attack Cycle Duration: 0-15
3-0 Select Decay Cycle Duration: 0-15
D406 54278 Envelope Generator 1: Sustain/Release
Cycle Control
7-4 Select Sustain Cycle Duration: 0-15
3-0 Select Release Cycle Duration: 0-15
D407 54279 Voice 2: Frequency Control - Low-Byte
D408 54280 Voice 2: Frequency Control - High-Byte
D409 54281 Voice 2: Pulse Waveform Width - Low-Byte
D40A 54282 7-4 Unused
3-0 Voice 2: Pulse Waveform Width - High-
Nybble
D40B 54283 Voice 2: Control Register
7 Select Random Noise Waveform, 1 = On
6 Select Pulse Waveform, 1 = On
5 Select Sawtooth Waveform, 1 = On
4 Select Triangle Waveform, 1 = On
3 Test Bit: 1 = Disable Oscillator 1
2 Ring Modulate Osc. 2 with Osc. 1 Output,
1 = On
1 Synchronize Osc.2 with Osc. 1 Frequency,
1 = On
0 Gate Bit: 1 = Start Att/Dec/Sus,
0 = Start Release
D40C 54284 Envelope Generator 2: Attack / Decay
Cycle Control
7-4 Select Attack Cycle Duration: 0-15
3-0 Select Decay Cycle Duration: 0-15
D40D 54285 Envelope Generator 2: Sustain / Release
Cycle Control
7-4 Select Sustain Cycle Duration: 0-15
3-0 Select Release Cycle Duration: 0-15
D40E 54286 Voice 3: Frequency Control - Low-Byte
D40F 54287 Voice 3: Frequency Control - High-Byte
D410 54288 Voice 3: Pulse Waveform Width - Low-Byte
D411 54289 7-4 Unused
3-0 Voice 3: Pulse Waveform Width - High-
Nybble
D412 54290 Voice 3: Control Register
7 Select Random Noise Waveform, 1 = On
6 Select Pulse Waveform, 1 = On
5 Select Sawtooth Waveform, 1 = On
4 Select Triangle Waveform, 1 = On
3 Test Bit: 1 = Disable Oscillator 1
2 Ring Modulate Osc. 3 with Osc. 2 Output,
1 = On
1 Synchronize Osc. 3 with Osc.2 Frequency,
1 = On
0 Gate Bit: 1 = Start Att/Dec/Sus,
0 = Start Release
D413 54291 Envelope Generator 3: Attack/Decay Cycle
Control
7-4 Select Attack Cycle Duration: 0-15
3-0 Select Decay Cycle Duration: 0-15
D414 54285 Envelope Generator 3: Sustain / Release
Cycle Control
7-4 Select Sustain Cycle Duration: 0-15
3-0 Select Release Cycle Duration: 0-15
D415 54293 Filter Cutoff Frequency: Low-Nybble
(Bits 2-0)
D416 54294 Filter Cutoff Frequency: High-Byte
D417 54295 Filter Resonance Control / Voice Input
Control
7-4 Select Filter Resonance: 0-15
3 Filter External Input: 1 = Yes, 0 = No
2 Filter Voice 3 Output: 1 = Yes, 0 = No
Filter Voice 2 Output: 1 = Yes, 0 = No
0 Filter Voice 1 Output: 1 = Yes, 0 = No
D418 54296 Select Filter Mode and Volume
7 Cut-Off Voice 3 Output: 1 = Off, 0 = On
6 Select Filter High-Pass Mode: 1 = On
5 Select Filter Band-Pass Mode: 1 = On
4 Select Filter Low-Pass Mode: 1 = On
3-0 Select Output Volume: 0-15
D419 54297 Analog/Digital Converter: Game Paddle 1
(0-255)
D41A 54298 Analog/Digital Converter: Game Paddle 2
(0-255)
D41B 54299 Oscillator 3 Random Number Generator
D41C 54230 Envelope Generator 3 Output
D500-D7FF 54528-55295 SID IMAGES
D800-DBFF 55296-56319 Color RAM (Nybbles)
DC00-DCFF 56320-56575 MOS 6526 Complex Interface Adapter
(CIA) #1
DC00 56320 Data Port A (Keyboard, Joystick,
Paddles, Light-Pen)
7-0 Write Keyboard Column Values for
Keyboard Scan
7-6 Read Paddles on Port A / B (01 = Port A,
10 = Port B)
4 Joystick A Fire Button: 1 = Fire
3-2 Paddle Fire Buttons
3-0 Joystick A Direction (0-15)
DC01 56321 Data Port B (Keyboard, Joystick,
Paddles): Game Port 1
7-0 Read Keyboard Row Values for Keyboard
Scan
7 Timer B Toggle/Pulse Output
6 Timer A: Toggle/Pulse Output
4 Joystick 1 Fire Button: 1 = Fire
3-2 Paddle Fire Buttons
3-0 Joystick 1 Direction
DC02 56322 Data Direction Register - Port A (56320)
DC03 56323 Data Direction Register - Port B (56321)
DC04 56324 Timer A: Low-Byte
DC05 56325 Timer A: High-Byte
DC06 56326 Timer B: Low-Byte
DC07 56327 Timer B: High-Byte
DC08 56328 Time-of-Day Clock: 1/10 Seconds
DC09 56329 Time-of-Day Clock: Seconds
DC0A 56330 Time-of-Day Clock: Minutes
DC0B 56331 Time-of-Day Clock: Hours + AM/PM Flag
(Bit 7)
DC0C 56332 Synchronous Serial I/O Data Buffer
DC0D 56333 CIA Interrupt Control Register
(Read IRQs/Write Mask)
7 IRQ Flag (1 = IRQ Occurred) / Set-
Clear Flag
4 FLAG1 IRQ (Cassette Read / Serial Bus
SRQ Input)
3 Serial Port Interrupt
2 Time-of-Day Clock Alarm Interrupt
1 Timer B Interrupt
0 Timer A Interrupt
DC0E 56334 CIA Control Register A
7 Time-of-Day Clock Frequency: 1 = 50 Hz,
0 = 60 Hz
6 Serial Port I/O Mode Output, 0 = Input
5 Timer A Counts: 1 = CNT Signals,
0 = System 02 Clock
4 Force Load Timer A: 1 = Yes
3 Timer A Run Mode: 1 = One-Shot,
0 = Continuous
2 Timer A Output Mode to PB6: 1 = Toggle,
0 = Pulse
1 Timer A Output on PB6: 1 = Yes, 0 = No
0 Start/Stop Timer A: 1 = Start, 0 = Stop
DC0F 56335 CIA Control Register B
7 Set Alarm/TOD-Clock: 1 = Alarm,
0 = Clock
6-5 Timer B Mode Select:
00 = Count System 02 Clock Pulses
01 = Count Positive CNT Transitions
10 = Count Timer A Underflow Pulses
11 = Count Timer A Underflows While
CNT Positive
4-0 Same as CIA Control Reg. A - for Timer B
DD00-DDFF 56576-56831 MOS 6526 Complex Interface Adapter
(CIA) #2
DD00 56576 Data Port A (Serial Bus, RS-232, VIC
Memory Control)
7 Serial Bus Data Input
6 Serial Bus Clock Pulse Input
5 Serial Bus Data Output
4 Serial Bus Clock Pulse Output
3 Serial Bus ATN Signal Output
2 RS-232 Data Output (User Port)
1-0 VIC Chip System Memory Bank Select
(Default = 11)
DD01 56577 Data Port B (User Port, RS-232)
7 User / RS-232 Data Set Ready
6 User / RS-232 Clear to Send
5 User
4 User / RS-232 Carrier Detect
3 User / RS-232 Ring Indicator
2 User / RS-232 Data Terminal Ready
1 User / RS-232 Request to Send
0 User / RS-232 Received Data
DD02 56578 Data Direction Register - Port A
DD03 56579 Data Direction Register - Port B
DD04 56580 Timer A: Low-Byte
DD05 56581 Timer A: High-Byte
DD06 56582 Timer B: Low-Byte
DD07 56583 Timer B: High-Byte
DD08 56584 Time-of-Day Clock: 1/10 Seconds
DD09 56585 Time-of-Day Clock: Seconds
DD0A 56586 Time-of-Day Clock: Minutes
DD0B 56587 Time-of-Day Clock: Hours + AM/PM Flag
(Bit 7)
DD0C 56588 Synchronous Serial I/O Data Buffer
DD0D 56589 CIA Interrupt Control Register (Read
NMls/Write Mask)
7 NMI Flag (1 = NMI Occurred) / Set-
Clear Flag
4 FLAG1 NMI (User/RS-232 Received Data
Input)
3 Serial Port Interrupt
1 Timer B Interrupt
0 Timer A Interrupt
DD0E 56590 CIA Control Register A
7 Time-of-Day Clock Frequency: 1 = 50 Hz,
0 = 60 Hz
6 Serial Port I/O Mode Output, 0 = Input
5 Timer A Counts: 1 = CNT Signals,
0 = System 02 Clock
4 Force Load Timer A: 1 = Yes
3 Timer A Run Mode: 1 = One-Shot,
0 = Continuous
2 Timer A Output Mode to PB6: 1 = Toggle,
0 = Pulse
1 Timer A Output on PB6: 1 = Yes, 0 = No
0 Start/Stop Timer A: 1 = Start, 0 = Stop
DD0F 56591 CIA Control Register B
7 Set Alarm/TOD-Clock: 1=Alarm, 0=Clock
6-5 Timer B Mode Select:
00 = Count System 02 Clock Pulses
01 = Count Positive CNT Transitions
10 = Count Timer A Underflow Pulses
11 = Count Timer A Underflows While
CNT Positive
4-0 Same as CIA Control Reg. A - for Timer B
DE00-DEFF 56832-57087 Reserved for Future I/O Expansion
DF00-DFFF 57088-57343 Reserved for Future I/O Expansion

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,322 +0,0 @@
- C64 RAM Map (64MAP10.TXT)
-
- Anonymous
- Commodore_64_Memory_Maps.txt
- in: 64MAP10.TXT, which states ftp://arnold.hiof.no/programs
- as the original source
-
- Corrections (typos as well as content), translations etc.
- welcome at: https://github.com/mist64/c64disasm
-
------------------------------------------------------------
-
# This plain text file is formatted so that it can be automatically
# parsed in order to create cross-references etc.
# * Lines starting with "-" is top-level information. The first line
# is the title. Lines starting with "--" are separators.
# * Lines starting with "#" are internal comments.
# * Hex addresses start at column 0.
# * Symbols start at column 13.
# * The description starts at column 21.
# * All lines of the description until the first blank line are
# combined into the heading.
# * A '.' character at the end of a heading line represents a hard
# line break.
# * The remaining text is in MarkDown format.
# * All addresses are 4 digits and have a leading '$'.
# The encoding is UTF-8.
$0000 D6510 6510 On-chip Data Direction Register.
$0001 R6510 6510 On-chip 8-bit Input/Output Register.
$0002 Unused. Free for user programs.
$0003-$0004 ADRAY1 Jump Vector: Convert FAC to Integer in (A/Y)
($B1AA).
$0005-$0006 ADRAY2 Jump Vector: Convert Integer in (A/Y) to
Floating point in (FAC); ($B391).
$0007-$0008 Temporary Integer during OR/AND.
$0007 CHARAC Search Character/Temporary Integer during INT.
$0008 ENDCHR Flag: Scan for Quote at end of String.
$0009 TRMPOS Screen Column for last TAB.
$000A VERCK Flag: 0 = Load, 1 = Verify.
$000B COUNT Input Buffer Pointer/Number of Subscripts.
$000C DIMFLG Flag: Default Array dimension.
$000D VALTYP Data type Flag: $00 = Numeric, $FF = String.
$000E INTFLG Data type Flag: $00 = Floating point, $80 =
Integer.
$000F GARBFL Flag: DATA scan/List Quote/Garbage collection.
$0010 SUBFLG Flag: Subscript reference/User Function call.
$0011 INPFLG Input Flag: $00 = INPUT, $40 = GET, $98 =
READ.
$0012 TANSGN Flag: TAN sign/Comparative result.
$0013 CHANNL File number of current Input Device.
$0014-$0015 LINNUM Temporary: Integer value.
$0016 TEMPPT Pointer: Temporary String Stack.
$0017-$0018 LASTPT Last temporary String Address.
$0019-$0021 TEMPST Stack for temporary Strings.
$0022-$0025 INDEX Utility Pointer Area.
$0022-$0023 INDEX1 First Utility Pointer.
$0024-$0025 INDEX2 Secong Utility Pointer.
$0026-$002A RES Floating point product of Multiply and
Divide.
$002B-$002C TXTTAB Pointer: Start of BASIC Text Area ($0801).
$002D-$002E VARTAB Pointer: Start of BASIC Variables.
$002F-$0030 ARYTAB Pointer: Start of BASIC Arrays.
$0031-$0032 STREND Pointer: End of BASIC Arrays + 1.
$0033-$0034 FRETOP Pointer: Bottom of String space.
$0035-$0036 FRESPC Utility String Pointer.
$0037-$0038 MEMSIZ Pointer: Highest Address available to BASIC
($A000).
$0039-$003A CURLIN Current BASIC Line number.
$003B-$003C OLDLIN Previous BASIC Line number.
$003D-$003E OLDTXT Pointer: BASIC Statement for CONT.
$003F-$0040 DATLIN Current DATA Line number.
$0041-$0042 DATPTR Pointer: Used by READ - current DATA Item
Address.
$0043-$0044 INPPTR Pointer: Temporary storage of Pointer during
INPUT Routine.
$0045-$0046 VARNAM Name of Variable being sought in Variable
Table.
$0047-$0048 VARPNT Pointer: to value of (VARNAM) if Integer, to
descriptor if String.
$0049-$004A FORPNT Pointer: Index Variable for FOR/NEXT loop.
$004B-$004C VARTXT Temporary storage for TXTPTR during READ,
INPUT and GET.
$004D OPMASK Mask used during FRMEVL.
$004E-$0052 TEMPF3 Temporary storage for FLPT value.
$0053 FOUR6 Length of String Variable during Garbege
collection.
$0054-$0056 JMPER Jump Vector used in Function Evaluation -
JMP followed by Address ($4C,$LB,$MB).
$0057-$005B TEMPF1 Temporary storage for FLPT value.
$005C-$0060 TEMPF2 Temporary storage for FLPT value.
$0061-$0066 FAC Main Floating point Accumulator.
$0061 FACEXP FAC Exponent.
$0062-$0065 FACHO FAC Mantissa.
$0066 FACSGN FAC Sign.
$0067 SGNFLG Pointer: Series Evaluation Constant.
$0068 BITS Bit Overflow Area during normalisation
Routine.
$0069-$006E ARG Auxiliary Floating point Accumulator.
$0069 ARGEXP AFAC Exponent.
$006A-$006D AFAC Mantissa.
$006E ARGSGN AFAC Sign.
$006F ARISGN Sign of result of Arithmetic Evaluation.
$0070 FACOV FAC low-order rounding.
$0071-$0072 FBUFPT Pointer: Used during CRUNCH/ASCII conversion.
$0073-$008A CHRGET Subroutine: Get next Byte of BASIC Text.
,0073 INC $7A
,0075 BNE $0079
,0077 INC $7B
,0079 LDA $0801
,007C CMP #$3A
,007E BCS $008A
,0080 CMP #$20
,0082 BEQ $0073
,0084 SEC
,0085 SBC #$30
,0087 SEC
,0088 SBC #$D0
,008A RTS
$0079 CHRGOT Entry to Get same Byte again.
$007A-$007B TXTPTR Pointer: Current Byte of BASIC Text.
$008B-$008F RNDX Floating RND Function Seed Value.
$0090 STATUS Kernal I/O Status Word ST.
$0091 STKEY Flag: $7F = STOP key.
$0092 SVXT Timing Constant for Tape.
$0093 VERCK Flag: 0 = Load, 1 = Verify.
$0094 C3P0 Flag: Serial Bus - Output Character buffered.
$0095 BSOUR Buffered Character for Serial Bus.
$0096 SYNO Cassette Sync. number.
$0097 XSAV Temporary storage of X Register during CHRIN.
Temporary storage of Y Register during RS232
fetch.
$0098 LDTND Number of Open Files/Index to File Table.
$0099 DFLTN Default Input Device (0).
$009A DFLTO Default Output Device (3).
$009B PRTY Parity of Byte Output to Tape.
$009C DPSW Flag: Byte received from Tape.
$009D MSGFLG Flag: $00 = Program mode: Suppress Error
Messages, $40 = Kernal Error Messages only,
$80 = Direct mode: Full Error Messages.
$009E PTR1 Tape Error log pass 1.
$009E T1 Index to Cassette File name/Header ID for
Tape write.
$009F PTR2 Tape Error log pass 2.
$00A0-$00A2 TIME Real-time jiffy Clock (Updated by IRQ
Interrupt approx. every 1/60 of Second);
Update Routine: UDTIMK ($F69B).
$00A3 Bit Counter Tape Read or Write/Serial Bus
EOI (End Of Input) Flag.
$00A4 Pulse Counter Tape Read or Write/Serial Bus
shift Counter.
$00A5 CNTDN Tape Synchronising count down.
$00A6 BUFPT Pointer: Tape I/O buffer.
$00A7 INBIT RS232 temporary for received Bit/Tape
temporary.
$00A8 BITCI RS232 Input Bit count/Tape temporary.
$00A9 RINONE RS232 Flag: Start Bit check/Tape temporary.
$00AA RIDATA RS232 Input Byte Buffer/Tape temporary.
$00AB RIPRTY RS232 Input parity/Tape temporary.
$00AC-$00AD Pointer: Tape Buffer/Screen scrolling.
$00AE-$00AF Tape End Address/End of Program.
$00B0-$00B1 Tape timing Constants.
$00B2-$00B3 TAPE1 Pointer: Start Address of Tape Buffer ($033C).
$00B4 BITTS RS232 Write bit count/Tape Read timing Flag.
$00B5 NXTBIT RS232 Next Bit to send/Tape Read - End of
Tape.
$00B6 RODATA RS232 Output Byte Buffer/Tape Read Error Flag.
$00B7 FNLEN Number of Characters in Filename.
$00B8 LA Current File - Logical File number.
$00B9 SA Current File - Secondary Address.
$00BA FA Current File - First Address (Device number).
OPEN LA,FA,SA; OPEN 1,8,15,"I0":CLOSE 1
$00BB-$00BC FNADR Pointer: Current File name Address.
$00BD ROPRTY RS232 Output Parity/Tape Byte to be Input or
Output.
$00BE FSBLK Tape Input/Output Block count.
$00BF MYCH Serial Word Buffer.
$00C0 CAS1 Tape Motor Switch.
$00C1-$00C2 STAL Start Address for LOAD and Cassette Write.
$00C3-$00C4 MEMUSS Pointer: Type 3 Tape LOAD and general use.
$00C5 LSTX Matrix value of last Key pressed; No Key = $40.
$00C6 NDX Number of Characters in Keyboard Buffer
queue.
$00C7 RVS Flag: Reverse On/Off; On = $01, Off = $00.
$00C8 INDX Pointer: End of Line for Input (Used to
suppress trailing spaces).
$00C9-$00CA Cursor X/Y (Line/Column) position at start of
Input.
$00CB SFDX Flag: Print shifted Characters.
$00CC BLNSW Flag: Cursor blink; $00 = Enabled, $01 =
Disabled.
$00CD BLNCT Timer: Count down for Cursor blink toggle.
$00CE GDBLN Character under Cursor while Cursor Inverted.
$00CF BLNON Flag: Cursor Status; $00 = Off, $01 = On.
$00D0 CRSW Flag: Input from Screen = $03, or Keyboard =
$00.
$00D1-$00D2 PNT Pointer: Current Screen Line Address.
$00D3 PNTR Cursor Column on current Line, including
Wrap-round Line, if any.
$00D4 QTSW Flag: Editor in Quote Mode; $00 = Not.
$00D5 LNMX Current logical Line length: 39 or 79.
$00D6 TBLX Current Screen Line number of Cursor.
$00D7 DATA Screen value of current Input Character/Last
Character Output.
$00D8 INSRT Count of number of inserts outstanding.
$00D9-$00F2 LDTB1 Screen Line link Table/Editor temporaries.
High Byte of Line Screen Memory Location.
$00F3-$00F4 USER Pointer: Current Colour RAM Location.
$00F5-$00F6 KEYTAB Vector: Current Keyboard decoding Table.
($EB81)
$00F7-$00F8 RIBUF RS232 Input Buffer Pointer.
$00F9-$00FA ROBUF RS232 Output Buffer Pointer.
$00FB-$00FE FREKZP Free Zero Page space for User Programs.
$00FF-$010A Assembly Area for Floating point to ASCII
conversion.
$0100-$01FF 6510 Hardware Stack Area.
$0100-$013E BAD Tape Input Error log.
$013F-$01FF BASIC Stack Area.
$0200-$0258 BUF BASIC Input Buffer (Input Line from Screen).
$0259-$0262 LAT Kernal Table: Active logical File numbers.
$0263-$026C FAT Kernal Table: Active File First Addresses
(Device numbers).
$026D-$0276 SAT Kernal Table: Active File Secondary
Addresses.
$0277-$0280 KEYD Keyboard Buffer Queue (FIFO).
$0281-$0282 MEMSTR Pointer: Bottom of Memory for Operating
System ($0800).
$0283-$0284 MEMSIZ Pointer: Top of Memory for Operating
System ($A000).
$0285 TIMOUT Serial IEEE Bus timeout defeat Flag.
$0286 COLOR Current Character Colour code.
$0287 GDCOL Background Colour under Cursor.
$0288 HIBASE High Byte of Screen Memory Address ($04).
$0289 XMAX Maximum number of Bytes in Keyboard
Buffer ($0A).
$028A RPTFLG Flag: Repeat keys; $00 = Cursors, INST/DEL &
Space repeat, $40 no Keys repeat, $80 all
Keys repeat ($00).
$028B KOUNT Repeat Key: Speed Counter ($04).
$028C DELAY Repeat Key: First repeat delay Counter ($10).
$028D SHFLAG Flag: Shift Keys: Bit 1 = Shift, Bit 2 = CBM,
Bit 3 = CTRL; ($00 = None, $01 = Shift, etc.).
$028E LSTSHF Last Shift Key used for debouncing.
$028F-$0290 KEYLOG Vector: Routine to determine Keyboard table
to use based on Shift Key Pattern ($EB48).
$0291 MODE Flag: Upper/Lower Case change: $00 = Disabled,
$80 = Enabled ($00).
$0292 AUTODN Flag: Auto scroll down: $00 = Disabled ($00).
$0293 M51CTR RS232 Pseudo 6551 control Register Image.
$0294 M51CDR RS232 Pseudo 6551 command Register Image.
$0295-$0296 M51AJB RS232 Non-standard Bits/Second.
$0297 RSSTAT RS232 Pseudo 6551 Status Register Image.
$0298 BITNUM RS232 Number of Bits left to send.
$0299-$029A BAUDOF RS232 Baud Rate; Full Bit time microseconds.
$029B RIDBE RS232 Index to End of Input Buffer.
$029C RIDBS RS232 Pointer: High Byte of Address of Input
Buffer.
$029D RODBS RS232 Pointer: High Byte of Address of Output
Buffer.
$029E RODBE RS232 Index to End of Output Buffer.
$029F-$02A0 IRQTMP Temporary store for IRQ Vector during Tape
operations.
$02A1 ENABL RS232 Enables.
$02A2 CASTON TOD sense during Tape I/O.
$02A3 KIKA26 Temporary storage during Tape READ.
$02A4 STUPID Temporary D1IRQ Indicator during Tape READ.
$02A5 LINTMP Temporary for Line Index.
$02A6 PALNTS Flag: TV Standard: $00 = NTSC, $01 = PAL.
$02A7-$02FF Unused.
$0300-$0301 IERROR Vector: Indirect entry to BASIC Error
Message, (X) points to Message ($E38B).
$0302-$0303 IMAIN Vector: Indirect entry to BASIC Input Line
and Decode ($A483).
$0304-$0305 ICRNCH Vector: Indirect entry to BASIC Tokenise
Routine ($A57C).
$0306-$0307 IQPLOP Vector: Indirect entry to BASIC LIST
Routine ($A71A).
$0308-$0309 IGONE Vector: Indirect entry to BASIC Character
dispatch Routine ($A7E4).
$030A-$030B IEVAL Vector: Indirect entry to BASIC Token
evaluation ($AE86).
$030C SAREG Storage for 6510 Accumulator during SYS.
$030D SXREG Storage for 6510 X-Register during SYS.
$030E SYREG Storage for 6510 Y-Register during SYS.
$030F SPREG Storage for 6510 Status Register during SYS.
$0310 USR Function JMP Instruction ($4C).
$0311-$0312 USRADD USR Address ($LB,$MB).
$0313 Unused.
$0314-$0315 CINV Vector: Hardware IRQ Interrupt Address ($EA31).
$0316-$0317 CBINV Vector: BRK Instruction Interrupt Address
($FE66).
$0318-$0319 NMINV Vector: Hardware NMI Interrupt Address ($FE47).
$031A-$031B IOPEN Vector: Indirect entry to Kernal OPEN
Routine ($F34A).
$031C-$031D ICLOSE Vector: Indirect entry to Kernal CLOSE
Routine ($F291).
$031E-$031F ICHKIN Vector: Indirect entry to Kernal CHKIN
Routine ($F20E).
$0320-$0321 ICKOUT Vector: Indirect entry to Kernal CHKOUT
Routine ($F250).
$0322-$0323 ICLRCH Vector: Indirect entry to Kernal CLRCHN
Routine ($F333).
$0324-$0325 IBASIN Vector: Indirect entry to Kernal CHRIN
Routine ($F157).
$0326-$0327 IBSOUT Vector: Indirect entry to Kernal CHROUT
Routine ($F1CA).
$0328-$0329 ISTOP Vector: Indirect entry to Kernal STOP
Routine ($F6ED).
$032A-$032B IGETIN Vector: Indirect entry to Kernal GETIN
Routine ($F13E).
$032C-$032D ICLALL Vector: Indirect entry to Kernal CLALL
Routine ($F32F).
$032E-$032F USRCMD User Defined Vector ($FE66).
$0330-$0331 ILOAD Vector: Indirect entry to Kernal LOAD
Routine ($F4A5).
$0332-$0333 ISAVE Vector: Indirect entry to Kernal SAVE
Routine ($F5ED).
$0334-$033B Unused.
$033C-$03FB TBUFFR Tape I/O Buffer.
$03FC-$03FF Unused.

View file

@ -1,221 +0,0 @@
- C64 RAM Map (Jim Butterfield)
-
- Butterfield, Jim [compiled by]:
- COMMODORE 64 MEMORY MAP
- Classic Computer Magazine Archive COMPUTE! issue 29, October 1982, p.150
-
- https://www.atarimagazines.com/compute/issue29/394_1_COMMODORE_64_MEMORY_MAP.php
- https://www.atariarchives.org/mlb/appendix_b.php
- https://archive.org/details/1982-10-compute-magazine/page/n153/mode/2up
-
- Corrections (typos as well as content), translations etc.
- welcome at: https://github.com/mist64/c64disasm
-
------------------------------------------------------------
-
# This plain text file is formatted so that it can be automatically
# parsed in order to create cross-references etc.
# * Lines starting with "-" is top-level information. The first line
# is the title. Lines starting with "--" are separators.
# * Lines starting with "#" are internal comments.
# * Hex addresses start at column 0.
# * Symbols start at column 13.
# * The description starts at column 21.
# * All lines of the description until the first blank line are
# combined into the heading.
# * A '.' character at the end of a heading line represents a hard
# line break.
# * The remaining text is in MarkDown format.
# * All addresses are 4 digits and have a leading '$'.
# The encoding is UTF-8.
$0000 D6510 Chip directional register
$0001 R6510 Chip I/O; memory & tape control
$0003-$0004 ADRAY1 Float-Fixed vector
$0005-$0006 ADRAY2 Fixed-Float vector
$0007 CHARAC Search character
$0008 ENDCHR Scan-quotes flag
$0009 TRMPOS TAB column save
$000A VERCK 0 = LOAD, 1 = VERIFY
$000B COUNT Input buffer pointer/# subscrpt
$000C DIMFLG Default DIM flag
$000D VALTYP Type : FF = string, 00 = numeric
$000E INTFLG Type : 80 = integer, 00 = floating point
$000F GARBFL DATA scan/LIST quote/memry flag
$0010 SUBFLG Subscript/FNx flag
$0011 INPFLG 0 = INPUT; $40 = GET; $98 = READ
$0012 TANSGN ATN sign/Comparison eval flag
$0013 CHANNL Current I/O prompt flag
$0014-$0015 LINNUM Integer value
$0016 TEMPPT Pointer : temporary strg stack
$0017-$0018 LASTPT Last temp string vector
$0019-$0021 TEMPST Stack for temporary strings
$0022-$0025 INDEX Utility pointer area
$0026-$002A RES Product area for multiplication
$002B-$002C TXTTAB Pointer : Start-of-Basic
$002D-$002E VARTAB Pointer : Start-of-Variables
$002F-$0030 ARYTAB Pointer : Start-of-Arrays
$0031-$0032 STREND Pointer : End-of-Arrays
$0033-$0034 FRETOP Pointer : String-storage(moving down)
$0035-$0036 FRESPC Utility string pointer
$0037-$0038 MEMSIZ Pointer : Limit-of-memory
$0039-$003A CURLIN Current Basic line number
$003B-$003C OLDLIN Previous Basic line number
$003D-$003E OLDTXT Pointer : Basic statement for CONT
$003F-$0040 DATLIN Current DATA line number
$0041-$0042 DATPTR Current DATA address
$0043-$0044 INPPTR Input vector
$0045-$0046 VARNAM Current variable name
$0047-$0048 VARPNT Current variable address
$0049-$004A FORPNT Variable pointer for FOR/NEXT
$004B-$004C VARTXT Y-save; op-save; Basic pointer save
$004D OPMASK Comparison symbol accumulator
$004E-$0053 Misc work area, pointer, etc
$0054-$0056 JMPER Jump vector for functions
$0057-$0060 Misc numeric work area
$0061 FACEXP Accum#l : Exponent
$0062-$0065 FACHO Accum#l : Mantissa
$0066 FACSGN Accum#l : Sign
$0067 SGNFLG Series evaluation constant pointer
$0068 BITS Accum#l hi-order (over flow)
$0069-$006E ARG Accum#2 : Exponent, etc.
$006F ARISGN Sign comparison, Acc#l vs #2
$0070 FACOV Accum#l lo-order (rounding)
$0071-$0072 FBUFPT Cassette buff len/Series pointer
$0073-$008A CHRGET CHRGET subroutine; get Basic char
$007A-$007B TXTPTR Basic pointer (within subrtn)
$008B-$008F RNDX RND seed value
$0090 STATUS Status word ST
$0091 STKEY Keyswitch PIA : STOP and RVS flags
$0092 SVXT Timing constant for tape
$0093 VERCK Load = 0, Verify = l
$0094 C3P0 Serial output : deferred char flag
$0095 BSOUR Serial deferred character
$0096 SYNO Tape EOT received
$0097 XSAV Register save
$0098 LDTND How many open files
$0099 DFLTN Input device, normally 0
$009A DFLTO Output CMD device, normally 3
$009B PRTY Tape character parity
$009C DPSW Byte-received flag
$009D MSGFLG Direct = $80/RUN = 0 output control
$009E PTR1 Tp Pass 1 error log/char buffer
$009F PTR2 Tp Pass 2 err log corrected
$00A0-$00A2 TIME Jiffy Clock HML
$00A3 R2D2 Serial bit count/EOI flag
$00A4 FIRT Cycle count
$00A5 CNTDN Countdown, tape write/bit count
$00A6 BUFPT Tape buffer pointer
$00A7 INBIT Tp Wrt ldr count/Rd pass/inbit
$00A8 BITCI Tp Wrt new byte/Rd error/inbit cnt
$00A9 RINONE Wrt start bit/Rd bit err/stbit
$00AA RIDATA Tp Scan; Cnt; Ld; End/byte assy
$00AB RIPRTY Wr lead length/Rd checksum/parity
$00AC-$00AD Pointer : tape bufr, scrolling
$00AE-$00AF Tape end adds/End of program
$00B0-$00B1 Tape timing constants
$00B2-$00B3 TAPE1 Pntr : start of tape buffer
$00B4 BITTS l = Tp timer enabled; bit count
$00B5 NXTBIT Tp EOT/RS232 next bit to send
$00B6 RODATA Read character error/outbyte buf
$00B7 FNLEN # characters in file name
$00B8 LA Current logical file
$00B9 SA Current secndy address
$00BA FA Current device
$00BB-$00BC FNADR Pointer to file name
$00BD ROPRTY Wr shift word/Rd input char
$00BE FSBLK # blocks remaining to Wr/Rd
$00BF MYCH Serial word buffer
$00C0 CAS1 Tape motor interlock
$00C1-$00C2 STAL I/O start address
$00C3-$00C4 MEMUSS Kernel setup pointer
$00C5 LSTX Last key pressed
$00C6 NDX # chars in keybd buffer
$00C7 RVS Screen reverse flag
$00C8 INDX End-of-line for input pointer
$00C9-$00CA Input cursor log (row, column)
$00CB SFDX Which key : 64 if no key
$00CC BLNSW 0 = flash cursor
$00CD BLNCT Cursor timing countdown
$00CE GDBLN Character under cursor
$00CF BLNON Cursor in blink phase
$00D0 CRSW Input from screen/from keyboard
$00D1-$00D2 PNT Pointer to screen line
$00D3 PNTR Position of cursor on above line
$00D4 QTSW 0 = direct cursor, else programmed
$00D5 LNMX Current screen line length
$00D6 TBLX Row where curosr lives
$00D7 DATA Last inkey/checksum/buffer
$00D8 INSRT # of INSERTs outstanding
$00D9-$00F2 LDTB1 Screen line link table
$00F3-$00F4 USER Screen color pointer
$00F5-$00F6 KEYTAB Keyboard pointer
$00F7-$00F8 RIBUF RS-232 Rev pntr
$00F9-$00FA ROBUF RS-232 Tx pntr
$00FF-$010A BASZPT Floating to ASCII work area
$0100-$01FF Processor stack area
$0100-$013E BAD Tape error log
$0200-$0258 BUF Basic input buffer
$0259-$0262 LAT Logical file table
$0263-$026C FAT Device # table
$026D-$0276 SAT Sec Adds table
$0277-$0280 KEYD Keybd buffer
$0281-$0282 MEMSTR Start of Basic Memory
$0283-$0284 MEMSIZ Top of Basic Memory
$0285 TIMOUT Serial bus timeout flag
$0286 COLOR Current color code
$0287 GDCOL Color under cursor
$0288 HIBASE Screen memory page
$0289 XMAX Max size of keybd buffer
$028A RPTFLG Repeat all keys
$028B KOUNT Repeat speed counter
$028C DELAY Repeat delay counter
$028D SHFLAG Keyboard Shift/Control flag
$028E LSTSHF Last shift pattern
$028F-$0290 KEYLOG Keyboard table setup pointer
$0291 MODE Keyboard shift mode
$0292 AUTODN 0 = scroll enable
$0293 M51CTR RS-232 control reg
$0294 M51CDR RS-232 command reg
$0295-$0296 M51AJB Bit timing
$0297 RSSTAT RS-232 status
$0298 BITNUM # bits to send
$0299-$029A BAUDOF RS-232 speed/code
$029B RIDBE RS232 receive pointer
$029C RIDBS RS232 input pointer
$029D RODBS RS232 transmit pointer
$029E RODBE RS232 output pointer
$029F-$02A0 IRQTMP IRQ save during tape I/O
$02A1 ENABL CIA 2 (NMI) Interrupt Control
$02A2 CASTON CIA 1 Timer A control log
$02A3 KIKA26 CIA 1 Interrupt Log
$02A4 STUPID CIA 1 Timer A enabled flag
$02A5 LINTMP Screen row marker
$0300-$0301 IERROR Error message link
$0302-$0303 IMAIN Basic warm start link
$0304-$0305 ICRNCH Crunch Basic tokens link
$0306-$0307 IQPLOP Print tokens link
$0308-$0309 IGONE Start new Basic code link
$030A-$030B IEVAL Get arithmetic element link
$030C SAREG SYS A-reg save
$030D SXREG SYS X-reg save
$030E SYREG SYS Y-reg save
$030F SPREG SYS status reg save
$0310-$0312 USRPOK USR function jump ($B248)
$0314-$0315 CINV Hardware interrupt vector ($EA31)
$0316-$0317 CBINV Break interrupt vector ($FE66)
$0318-$0319 NMINV NMI interrupt vector ($FE47)
$031A-$031B IOPEN OPEN vector ($F34A)
$031C-$031D ICLOSE CLOSE vector ($F291)
$031E-$031F ICHKIN Set - input vector ($F20E)
$0320-$0321 ICKOUT Set - output vector ($F250)
$0322-$0323 ICLRCH Restore I/0 vector ($F333)
$0324-$0325 IBASIN INPUT vector ($F157)
$0326-$0327 IBSOUT Output vector ($F1CA)
$0328-$0329 ISTOP Test-STOP vector ($F6ED)
$032A-$032B IGETIN GET vector ($F13E)
$032C-$032D ICLALL Abort I/o vector ($F32F)
$032E-$032F USRCMD Warm start vector ($FE66)
$0330-$0331 ILOAD LOAD link ($F4A5)
$0332-$0333 ISAVE SAVE link ($F5ED)
$033C-$03FB TBUFFR Cassette buffer

File diff suppressed because it is too large Load diff

View file

@ -1,240 +0,0 @@
- C64 RAM Map (Programmer's Reference Guide)
-
- Commodore 64 Programmer's Reference Guide
- Indianapolis: Howard W. Sams & Co., Inc, 1982.
- ISBN 0-672-22056-3
-
- C64PRG10.TXT, June 1996, etext #46
- converted to etext by
- Ville Muikkula
- Jouko Valta
-
- Corrections (typos as well as content), translations etc.
- welcome at: https://github.com/mist64/c64disasm
-
----------------------------------------------
-
# This plain text file is formatted so that it can be automatically
# parsed in order to create cross-references etc.
# * Lines starting with "-" is top-level information. The first line
# is the title. Lines starting with "--" are separators.
# * Lines starting with "#" are internal comments.
# * Hex addresses start at column 0.
# * Symbols start at column 13.
# * The description starts at column 21.
# * All lines of the description until the first blank line are
# combined into the heading.
# * A '.' character at the end of a heading line represents a hard
# line break.
# * The remaining text is in MarkDown format.
# * All addresses are 4 digits and have a leading '$'.
# The encoding is UTF-8.
$0000 D6510 6510 On-Chip Data-Direction Register
$0001 R6510 6510 On-Chip 8-Bit Input/Output Register
$0002 Unused
$0003-$0004 ADRAY1 Jump Vector: Convert Floating-Integer
$0005-$0006 ADRAY2 Jump Vector: Convert Integer--Floating
$0007 CHARAC Search Character
$0008 ENDCHR Flag: Scan for Quote at End of String
$0009 TRMPOS Screen Column From Last TAB
$000A VERCK Flag: 0 = Load, 1 = Verify
$000B COUNT Input Buffer Pointer / No. of Subscripts
$000C DIMFLG Flag: Default Array DiMension
$000D VALTYP Data Type: $FF = String, $00 = Numeric
$000E INTFLG Data Type: $80 = Integer, $00 = Floating
$000F GARBFL Flag: DATA scan/LIST quote/Garbage Coll
$0010 SUBFLG Flag: Subscript Ref / User Function Call
$0011 INPFLG Flag: $00 = INPUT, $40 = GET, $98 = READ
$0012 TANSGN Flag TAN sign / Comparison Result
$0013 Flag: INPUT Prompt
$0014-$0015 LINNUM Temp: Integer Value
$0016 TEMPPT Pointer Temporary String
$0017-$0018 LASTPT Last Temp String Address
$0019-$0021 TEMPST Stack for Temporary Strings
$0022-$0025 INDEX Utility Pointer Area
$0022-$0023 INDEX1 First Utility Pointer.
$0024-$0025 INDEX2 Second Utility Pointer.
$0026-$002A RES Floating-Point Product of Multiply
$002B-$002C TXTTAB Pointer: Start of BASIC Text
$002D-$002E VARTAB Pointer: Start of BASIC Variables
$002F-$0030 ARYTAB Pointer: Start of BASIC Arrays
$0031-$0032 STREND Pointer End of BASIC Arrays (+1)
$0033-$0034 FRETOP Pointer: Bottom of String Storage
$0035-$0036 FRESPC Utility String Pointer
$0037-$0038 MEMSIZ Pointer: Highest Address Used by BASIC
$0039-$003A CURLIN Current BASIC Line Number
$003B-$003C OLDLIN Previous BASIC Line Number
$003D-$003E OLDTXT Pointer: BASIC Statement for CONT
$003F-$0040 DATLIN Current DATA Line Number
$0041-$0042 DATPTR Pointer: Current DATA Item Address
$0043-$0044 INPPTR Vector: INPUT Routine
$0045-$0046 VARNAM Current BASIC Variable Name
$0047-$0048 VARPNT Pointer: Current BASIC Variable Data
$0049-$004A FORPNT Pointer: Index Variable for FOR/NEXT
$004B-$0060 Temp Pointer / Data Area
$004B-$004C VARTXT Temporary storage for TXTPTR during
READ, INPUT and GET.
$004D OPMASK Mask used during FRMEVL.
$004E-$0052 TEMPF3 Temporary storage for FLPT value.
$0053 FOUR6 Length of String Variable during Garbage
collection.
$0054-$0056 JMPER Jump Vector used in Function Evaluation-
JMP followed by Address ($4C,$LB,$MB).
$0057-$005B TEMPF1 Temporary storage for FLPT value.
$005C-$0060 TEMPF2 Temporary storage for FLPT value.
$0061 FACEXP Floating-Point Accumulator #1: Exponent
$0062-$0065 FACHO Floating Accum. #1: Mantissa
$0066 FACSGN Floating Accum. #1: Sign
$0067 SGNFLG Pointer: Series Evaluation Constant
$0068 BITS Floating Accum. #1: Overflow Digit
$0069 ARGEXP Floating-Point Accumulator #2: Exponent
$006A-$006D Floating Accum. #2: Mantissa
$006E ARGSGN Floating Accum. #2: Sign
$006F ARISGN Sign Comparison Result: Accum. # 1 vs #2
$0070 FACOV Floating Accum. #1. Low-Order (Rounding)
$0071-$0072 FBUFPT Pointer: Cassette Buffer
$0073-$008A CHRGET Subroutine: Get Next Byte of BASIC Text
$0079 CHRGOT Entry to Get Same Byte of Text Again
$007A-$007B TXTPTR Pointer: Current Byte of BASIC Text
$008B-$008F RNDX Floating RND Function Seed Value
$0090 STATUS Kernal I/O Status Word: ST
$0091 STKEY Flag: STOP key / RVS key
$0092 SVXT Timing Constant for Tape
$0093 VERCK Flag: 0 = Load, 1 = Verify
$0094 C3P0 Flag: Serial Bus-Output Char. Buffered
$0095 BSOUR Buffered Character for Serial Bus
$0096 SYNO Cassette Sync No.
$0097 Temp Data Area
$0098 LDTND No. of Open Files / Index to File Table
$0099 DFLTN Default Input Device (0)
$009A DFLTO Default Output (CMD) Device (3)
$009B PRTY Tape Character Parity
$009C DPSW Flag: Tape Byte-Received
$009D MSGFLG Flag: $80 = Direct Mode, $00 = Program
$009E PTR1 Tape Pass 1 Error Log
$009F PTR2 Tape Pass 2 Error Log
$00A0-$00A2 TIME Real-Time Jiffy Clock (approx) 1/60 Sec
$00A3-$00A4 Temp Data Area
$00A5 CNTDN Cassette Sync Countdown
$00A6 BUFPT Pointer: Tape I/O Buffer
$00A7 INBIT RS-232 Input Bits / Cassette Temp
$00A8 BITCI RS-232 Input Bit Count / Cassette Temp
$00A9 RINONE RS-232 Flag: Check for Start Bit
$00AA RIDATA RS-232 Input Byte Buffer/Cassette Temp
$00AB RIPRTY RS-232 Input Parity / Cassette Short Cnt
$00AC-$00AD Pointer: Tape Buffer/ Screen Scrolling
$00AE-$00AF Tape End Addresses/End of Program
$00B0-$00B1 Tape Timing Constants
$00B2-$00B3 TAPE1 Pointer: Start of Tape Buffer
$00B4 BITTS RS-232 Out Bit Count / Cassette Temp
$00B5 NXTBIT RS-232 Next Bit to Send/ Tape EOT Flag
$00B6 RODATA RS-232 Out Byte Buffer
$00B7 FNLEN Length of Current File Name
$00B8 LA Current Logical File Number
$00B9 SA Current Secondary Address
$00BA FA Current Device Number
$00BB-$00BC FNADR Pointer: Current File Name
$00BD ROPRTY RS-232 Out Parity / Cassette Temp
$00BE FSBLK Cassette Read / Write Block Count
$00BF MYCH Serial Word Buffer
$00C0 CAS1 Tape Motor Interlock
$00C1-$00C2 STAL I/O Start Address
$00C3-$00C4 MEMUSS Tape Load Temps
$00C5 LSTX Current Key Pressed: CHR$(n) 0 = No Key
$00C6 NDX No. of Chars. in Keyboard Buffer (Queue)
$00C7 RVS Flag: Reverse Chars. - 1=Yes, 0=No Used
$00C8 INDX Pointer: End of Logical Line for INPUT
$00C9-$00CA Cursor X-Y Pos. at Start of INPUT
$00CB SFDX Flag: Print Shifted Chars.
$00CC BLNSW Cursor Blink enable: 0 = Flash Cursor
$00CD BLNCT Timer: Countdown to Toggle Cursor
$00CE GDBLN Character Under Cursor
$00CF BLNON Flag: Last Cursor Blink On/Off
$00D0 CRSW Flag: INPUT or GET from Keyboard
$00D1-$00D2 PNT Pointer: Current Screen Line Address
$00D3 PNTR Cursor Column on Current Line
$00D4 QTSW Flag: Editor in Quote Mode, $00 = NO
$00D5 LNMX Physical Screen Line Length
$00D6 TBLX Current Cursor Physical Line Number
$00D7 Temp Data Area
$00D8 INSRT Flag: Insert Mode, >0 = # INSTs
$00D9-$00F2 LDTB1 Screen Line Link Table / Editor Temps
$00F3-$00F4 USER Pointer: Current Screen Color RAM loc.
$00F5-$00F6 KEYTAB Vector Keyboard Decode Table
$00F7-$00F8 RIBUF RS-232 Input Buffer Pointer
$00F9-$00FA ROBUF RS-232 Output Buffer Pointer
$00FB-$00FE FREKZP Free 0-Page Space for User Programs
$00FF-$010A BASZPT Floating to String Work Area
$0100-$01FF Micro-Processor System Stack Area
$0100-$013E BAD Tape Input Error Log
$0200-$0258 BUF System INPUT Buffer
$0259-$0262 LAT KERNAL Table: Active Logical File No's.
$0263-$026C FAT KERNAL Table: Device No. for Each File
$026D-$0276 SAT KERNAL Table: Second Address Each File
$0277-$0280 KEYD Keyboard Buffer Queue (FIFO)
$0281-$0282 MEMSTR Pointer: Bottom of Memory for O.S.
$0283-$0284 MEMSIZ Pointer: Top of Memory for O.S.
$0285 TIMOUT Flag: Kernal Variable for IEEE Timeout
$0286 COLOR Current Character Color Code
$0287 GDCOL Background Color Under Cursor
$0288 HIBASE Top of Screen Memory (Page)
$0289 XMAX Size of Keyboard Buffer
$028A RPTFLG Flag: REPEAT Key Used, $80 = Repeat
$028B KOUNT Repeat Speed Counter
$028C DELAY Repeat Delay Counter
$028D SHFLAG Flag: Keyboard SHIFT Key/CTRL Key/C= Key
$028E LSTSHF Last Keyboard Shift Pattern
$028F-$0290 KEYLOG Vector: Keyboard Table Setup
$0291 MODE Flag: $00=Disable SHIFT Keys, $80=Enable
$0292 AUTODN Flag: Auto Scroll Down, 0 = ON
$0293 M51CTR RS-232: 6551 Control Register Image
$0294 M51CDR RS-232: 6551 Command Register Image
$0295-$0296 M51AJB RS-232 Non-Standard BPS (Time/2-100) USA
$0297 RSSTAT RS-232: 6551 Status Register Image
$0298 BITNUM RS-232 Number of Bits Left to Send
$0299-$029A BAUDOF RS-232 Baud Rate: Full Bit Time (us)
$029B RIDBE RS-232 Index to End of Input Buffer
$029C RIDBS RS-232 Start of Input Buffer (Page)
$029D RODBS RS-232 Start of Output Buffer (Page)
$029E RODBE RS-232 Index to End of Output Buffer
$029F-$02A0 IRQTMP Holds IRQ Vector During Tape I/O
$02A1 ENABL RS-232 Enables
$02A2 TOD Sense During Cassette I/O
$02A3 Temp Storage For Cassette Read
$02A4 Temp D1 IRQ Indicator For Cassette Read
$02A5 Temp For Line Index
$02A6 PAL/NTSC Flag, 0= NTSC, 1 = PAL
$02A7-$02FF Unused
$0300-$0301 IERROR Vector: Print BASIC Error Message
$0302-$0303 IMAIN Vector: BASIC Warm Start
$0304-$0305 ICRNCH Vector: Tokenize BASIC Text
$0306-$0307 IQPLOP Vector: BASIC Text LIST
$0308-$0309 IGONE Vector: BASIC Char. Dispatch
$030A-$030B IEVAL Vector: BASIC Token Evaluation
$030C SAREG Storage for 6502 .A Register
$030D SXREG Storage for 5502 .X Register
$030E SYREG Storage for 6502 .Y Register
$030F SPREG Storage for 6502 .SP Register
$0310 USR Function Jump Instr (4C)
$0311-$0312 USRADD USR Address Low Byte / High Byte
$0313 Unused
$0314-$0315 CINV Vector: Hardware Interrupt
$0316-$0317 CBINV Vector: BRK Instr. Interrupt
$0318-$0319 NMINV Vector: Non-Maskable Interrupt
$031A-$031B IOPEN KERNAL OPEN Routine Vector
$031C-$031D ICLOSE KERNAL CLOSE Routine Vector
$031E-$031F ICHKIN KERNAL CHKIN Routine
$0320-$0321 ICKOUT KERNAL CHKOUT Routine
$0322-$0323 ICLRCH KERNAL CLRCHN Routine Vector
$0324-$0325 IBASIN KERNAL CHRIN Routine
$0326-$0327 IBSOUT KERNAL CHROUT Routine
$0328-$0329 ISTOP KERNAL STOP Routine Vector
$032A-$032B IGETIN KERNAL GETIN Routine
$032C-$032D ICLALL KERNAL CLALL Routine Vector
$032E-$032F USRCMD User-Defined Vector
$0330-$0331 ILOAD KERNAL LOAD Routine
$0332-$0333 ISAVE KERNAL SAVE Routine Vector
$0334-$033B Unused
$033C-$03FB TBUFFR Tape I/O Buffer
$03FC-$03FF Unused

View file

@ -1,668 +0,0 @@
- C64 RAM Map (Microsoft/Commodore)
-
- The labels and descriptions have been taken from
- Microsoft's original BASIC for M6502 source
- and
- The original C64 KERNAL source by Commodore (901227-03)
- https://github.com/mist64/cbmsrc
-
- Converted and formatted by Michael Steil <mist64@mac.com>
-
- Corrections (typos as well as content), translations etc.
- welcome at: https://github.com/mist64/c64disasm
-
------------------------------------------------------------
-
# This plain text file is formatted so that it can be automatically
# parsed in order to create cross-references etc.
# * Lines starting with "-" is top-level information. The first line
# is the title. Lines starting with "--" are separators.
# * Lines starting with "#" are internal comments.
# * Hex addresses start at column 0.
# * Symbols start at column 13.
# * The description starts at column 21.
# * All lines of the description until the first blank line are
# combined into the heading.
# * A '.' character at the end of a heading line represents a hard
# line break.
# * The remaining text is in MarkDown format.
# * All addresses are 4 digits and have a leading '$'.
# The encoding is UTF-8.
#
# KERNAL
#
$0000 D6510 6510 data direction register
$0001 R6510 6510 data register
#
# BASIC
#
$0003-$0004 ADRAY1 Store here the addr of the
routine to turn the FAC into a
two byte signed integer in [Y,A]
$0005-$0006 ADRAY2 Store here the addr of the
routine to convert [Y,A] to a floating
point number in the FAC.
$0007 CHARAC A delimiting character.
$0007 INTEGR A one-byte integer from "QINT".
$0008 ENDCHR The other delimiting character.
$0009 TRMPOS Position of terminal carriage.
$000B COUNT A general counter.
$000C DIMFLG
In getting a pointer to a variable
it is important to remember whether it
is being done for "dim" or not.
DIMFLG and VALTYP must be
consecutive locations.
$000D VALTYP The type indicator.
0=numeric 1=string.
$000E INTFLG Tells if integer.
$000F GARBFL Whether to do garbage collection.
$000F DORES Whether can or can't crunch res'd words.
Turned on when "data"
being scanned by crunch so unquoted
strings won't be crunched.
$0010 SUBFLG Flag whether sub'd variable allowed.
"FOR" and user-defined function
pointer fetching turn
this on before calling "PTRGET"
so arrays won't be detected.
"STKINI" and "PTRGET" clear it.
Also disallows integers there.
$0011 INPFLG Flags whether we are doing "INPUT"
or "READ".
$0012 TANSGN Used in determining sign of tangent.
$0012 DOMASK Mask in use by relation operations.
$0013 CHANNL Holds channel number.
$0014-$0015 LINNUM Location to store line number before BUF
so that "BLTUC" can store it all away at once.
A comma (preload or from ROM)
used by input statement since the
data pointer always starts on a
comma or terminator.
$0014-$0015 POKER Set up location used by POKE.
Temporary for input and read code
$0016 TEMPPT Pointer at first free temp descriptor.
Initialized to point to TEMPST.
$0017-$0018 LASTPT Pointer to last-used string temporary.
$0019-$0021 TEMPST Storage for NUMTMP temp descriptors.
$0022-$0025 INDEX Indexes.
$0022-$0023 INDEX1
$0024-$0025 INDEX2
$0026 RESHO Result of multiplier and divider.
$0027 RESMOH One more byte.
$0028 RESMO
$0028 ADDEND Temporary used by "UMULT".
$0029 RESLO
$002B-$002C TXTTAB Pointer to beginning of text.
Doesn't change after being
setup by "INIT".
$002D-$002E VARTAB Pointer to start of simple
variable space.
Updated whenever the size of the
program changes, set to [TXTTAB]
by "SCRATCH" ("NEW").
$002F-$0030 ARYTAB Pointer to beginning of array
table.
Incremented by 6 whenever
a new simple variable is found, and
set to [VARTAB] by "CLEARC".
$0031-$0032 STREND End of storage in use.
Increased whenever a new array
or simple variable is encountered.
set to [VARTAB] by "CLEARC".
$0033-$0034 FRETOP Top of string free space.
$0035-$0036 FRESPC Pointer to new string.
$0037-$0038 MEMSIZ Highest location in memory.
$0039-$003A CURLIN Current line #.
Set to 0,255 for direct statements.
$003B-$003C OLDLIN Old line number
Set up by ^C,"STOP"
or "END" in a program.
$003D-$003E OLDTXT Old text pointer.
Points at statement to be exec'd next.
$003F-$0040 DATLIN Data line # -- remember for errors.
$0041-$0042 DATPTR Pointer to data.
Initialized to point
at the zero in front of [TXTTAB]
by "RESTORE" which is called by "CLEARC".
updated by execution of a "READ".
$0043-$0044 INPPTR This remembers where input is coming from.
$0045-$0046 VARNAM Variable's name is stored here.
$0047-$0048 VARPNT Pointer to variable in memory.
$0047 FDECPT Pointer into power of tens of "FOUT".
$0049-$004A FORPNT A variable's pointer for "FOR" loops
and "LET" statements.
$0049 LSTPNT Pntr to list string.
$0049 ANDMSK The mask used by WAIT for ANDing.
$004A EORMSK The mask for EORing in wait.
$004B-$004C OPPTR Pointer to current op's entry in "OPTAB".
$004B VARTXT Pointer into list of variables.
$004D OPMASK Mask created by current operator.
$004E-$0052 TEMPF3 A third FAC temporary (4 bytes).
$004E-$004F DEFPNT Pointer used in function definition.
$004E GRBPNT Another used in garbage collection.
$0050-$0052 DSCPNT Pointer to a string descriptor.
$0053 FOUR6 Variable constant used by garb collect.
$0054-$0056 JMPER
$0055 SIZE
$0056 OLDOV The old overflow.
$0057-$005B TEMPF1
$0058 HIGHDS Destination of highest element in BLT.
$005A HIGHTR Source of highest element to move.
$005C-$0060 TEMPF2
$005D LOWDS Location of last byte transferred into.
$005F LOWTR Last thing to move in BLT.
$0058 ARYPNT A pointer used in array building.
$005F GRBTOP A pointer used in garbage collection.
$005D DECCNT Number of places before decimal point.
$005E TENEXP Has a DPT been input?
$005F DPTFLG Base ten exponent.
$0060 EXPSGN Sign of base ten exponent.
$0061-$0066 FAC The floating accumulator
$0061 FACEXP
$0061 DSCTMP This is where temp descs are built.
$0062 FACHO Most significant byte of mantissa.
$0063 FACMOH One more.
$0064 FACMO Middle order of mantissa.
$0064 INDICE Indice is set up here by "QINT".
$0065 FACLO Least sig byte of mantissa.
$0066 FACSGN Sign of FAC (0 or -1) when unpacked.
$0067 SGNFLG Sign of FAC is preserved bere by "FIN".
$0067 DEGREE A count used by polynomials.
$0068 BITS Something for "SHIFTR" to use.
$0069-$006E The floating argument (unpacked)
$0069 ARGEXP
$006A ARGHO
$006B ARGMOH
$006C ARGMO
$006D ARGLO
$006E ARGSGN
$006F ARISGN A sign reflecting the result.
$006F-$0070 STRNG1 Pointer to a string or descriptor.
$0070 FACOV Overflow byte of the FAC.
$0071-$0072 FBUFPT Pointer into FBUFFR used by FOUT.
$0071-$0072 BUFPTR Pointer to buf used by "CRUNCH".
$0071-$0072 STRNG2 Pointer to string or desc.
$0071-$0072 POLYPT Pointer into polynomial coefficients.
$0071-$0072 CURTOL Absolute linear index is formed here.
$0073-$008A CHRGET RAM code.
This code gets changed throughout execution.
It is made to be fast this way.
Also, [X] and [Y] are not disturbed.
"CHRGET" using [TXTPTR] as the current text pntr,
fetches a new character into ACCA after incrementing [TXTPTR]
and sets condition codes according to what's in ACCA.
* not C = numeric ("0" thru "9")
* Z = ":" or end-of-line (a null)
[ACCA] = new char.
[TXTPTR]=[TXTPTR]+1
The following exists in ROM if ROM exists and is loaded
down here by init. Otherwise it is just loaded into this
RAM like all the rest of RAM is loaded.
$008B-$008F RNDX
#
# KERNAL
#
$0090 STATUS I/O operation status byte
$0091 STKEY STOP key flag
$0092 SVXT Cassette: temp used to adjust software servo
$0093 VERCK Cassette: verify or load flag (Z - loading)
$0094 C3P0 IEEE buffered char flag
$0095 BSOUR Char buffer for IEEE
$0096 SYNO Cassette: flags if we have block SYNC (16 zero dipoles)
$0097 XSAV Temp for BASIN
$0098 LDTND Index to logical file
$0099 DFLTN Default input device #
$009A DFLTO Default output device #
$009B PRTY Cassette: holds current calculated parity bit
$009C DPSW Cassette: if NZ then expecting LL/L combination that ends a byte
$009D MSGFLG OS message flag
$009E PTR1 Cassette: count of read locations in error (pointer into bad, max 61)
$009E T1 Temporary 1
$009F PTR2 Cassette: count of re-read locations (pointer into bad, during re-read)
$009F T2 Temporary 2
$00A0-$00A2 TIME 24 hour clock in 1/60th seconds
$00A3 R2D2 Serial bus usage
$00A3 PCNTR Cassette: counts down from 8-0 for data then to ff for parity
$00A4 BSOUR1 Temp used by serial routine
$00A4 FIRT Cassette: used to indicate which half of dipole we're in
$00A5 COUNT Temp used by serial routine
$00A5 CNTDN Cassette sync countdown
$00A6 BUFPT Cassette buffer pointer
$00A7 INBIT RS-232 rcvr input bit storage
$00A7 SHCNL Cassette: holds FSBLK, used to direct routines, because of exit case
$00A8 BITCI RS-232 rcvr bit count in
$00A8 RER Cassette: flags errors (if Z then no error)
$00A9 RINONE RS-232 rcvr flag for start bit check
$00A9 REZ Cassette: counts zeros (if Z then correct # of dipoles)
$00AA RIDATA RS-232 rcvr byte buffer
$00AA RDFLG Cassette: holds function mode
MI - waiting for block SYNC
VS - in data block reading data
NE - waiting for byte SYNC
$00AB RIPRTY RS-232 rcvr parity storage
$00AB SHCNH Cassette: short cnt; left over from debugging
$00AC SAL Cassette: indirect to data storage area
$00AD SAH
$00AE EAL
$00AF EAH
$00B0 CMP0 Cassette: software servo (+/- adjust to time calcs)
$00B1 TEMP Cassette: used to hold dipole time during type calculations
$00B2-$00B3 TAPE1 Address of tape buffer #1y.
$00B4 BITTS RS-232 trns bit count
$00B4 SNSW1 Cassette: flags if we have byte SYNC (a longlong)
$00B5 NXTBIT RS-232 trns next bit to be sent
$00B5 DIFF Cassette: used to preserve SYNO (outside of bit routines)
$00B6 RODATA RS-232 trns byte buffer
$00B6 PRP Cassette: has combined error values from bit routines
$00B7 FNLEN Length current file n str
$00B8 LA Current file logical addr
$00B9 SA Current file 2nd addr
$00BA FA Current file primary addr
$00BB-$00BC FNADR Addr current file name str
$00BD ROPRTY RS-232 trns parity buffer
$00BD OCHAR
$00BE FSBLK Cassette: indicate which block we're looking at (0 to exit)
$00BF MYCH Cassette: holds input byte being built
$00C0 CAS1 Cassette manual/controlled switch
$00C1 TMP0
$00C1 STAL
$00C2 STAH
$00C3-$00C4 MEMUSS Cassette load temps (2 bytes)
$00C3-$00C4 TMP2
$00C5 LSTX Key scan index
$00C6 NDX Index to keyboard q
$00C7 RVS RVS field on flag
$00C8 INDX
$00C9 LSXP X pos at start
$00CA LSTP
$00CB SFDX SHIFT mode on print
$00CC BLNSW Cursor blink enab
$00CD BLNCT Count to toggle cur
$00CE GDBLN Char before cursor
$00CF BLNON On/off blink flag
$00D0 CRSW INPUT vs GET flag
$00D1-$00D2 PNT Pointer to row
$00D3 PNTR Pointer to column
$00D4 QTSW Quote switch
$00D5 LNMX 40/80 max positon
$00D6 TBLX
$00D7 DATA Cassette: holds most recent dipole bit value
$00D8 INSRT Insert mode flag
$00D9-$00F2 LDTB1 Line flags+endspace
$00F3-$00F4 USER Screen editor color IP
$00F5-$00F6 KEYTAB Keyscan table indirect
$00F7-$00F8 RIBUF RS-232 input buffer pointer
$00F9-$00FA ROBUF RS-232 output buffer pointer
$00FB-$00FE FREKZP Free KERNAL zero page 9/24/80
$00FF-$010A BASZPT Location ($00FF) used by BASIC
$0100-$013E BAD Cassette: storage space for bad read locations (bottom of stack)
#
# BASIC
#
$0200-$0258 BUF BASIC/MONITOR buffer
Type-in stored here.
Direct statements execute out of
here. Remember "INPUT" smashes buf.
Must be on page zero
or assignment of string
values in direct statements won't copy
into string space -- which it must.
N.B.: Two nonzero bytes must precede "BUFLNM".
#
# KERNAL
#
$0259-$0262 LAT Logical file numbers
$0263-$026C FAT Primary device numbers
$026D-$0276 SAT Secondary addresses
$0277-$0280 KEYD IRQ keyboard buffer
$0281-$0282 MEMSTR Start of memory
$0283-$0284 MEMSIZ Top of memory
$0285 TIMOUT IEEE timeout flag
$0286 COLOR Active color nybble
$0287 GDCOL Original color before cursor
$0288 HIBASE Base location of screen (top)
$0289 XMAX
$028A RPTFLG Key repeat flag
$028B KOUNT
$028C DELAY
$028D SHFLAG SHIFT flag byte
$028E LSTSHF Last SHIFT pattern
$028F-$0290 KEYLOG Indirect for keyboard table setup
$0291 MODE 0-PET mode, 1-cattacanna
$0292 AUTODN Auto scroll down flag(=0 on,<>0 off)
$0293 M51CTR 6551 control register
$0294 M51CDR 6551 command register
$0295-$0296 M51AJB Non standard (bittime/2-100)
$0297 RSSTAT RS-232 status register
$0298 BITNUM Number of bits to send (fast response)
$0299-$029A BAUDOF Baud rate full bit time (created by open)
$029B RIDBE Input buffer index to end
$029C RIDBS Input buffer pointer to start
$029D RODBS Output buffer index to start
$029E RODBE Output buffer index to end
$029F-$02A0 IRQTMP Holds irq during tape ops
$02A1 ENABL RS-232 enables (replaces ier)
$02A2 CASTON TOD sense during cassettes
$02A3 KIKA26 Cassette: holds old D1ICR after clear on read
$02A4 STUPID Cassette: hold indicator (NZ - no T1IRQ yet) for T1IRQ
$02A5 LINTMP Temporary for line index
$02A6 PALNTS PAL vs NTSC flag 0=NTSC 1=PAL
#
# BASIC
#
$0300-$0301 IERROR indirect ERROR (output error in .X)
$0302-$0303 IMAIN indirect MAIN (system direct loop)
$0304-$0305 ICRNCH indirect CRUNCH (tokenization routine)
$0306-$0307 IQPLOP indirect LIST (char list)
$0308-$0309 IGONE indirect GONE (char dispatch)
$030A-$030B IEVAL indirect EVAL (symbol evaluation)
$030C SAREG .A reg
$030D SXREG .X reg
$030E SYREG .Y reg
$030F SPREG .P reg
$0310-$0312 USRPOK user function dispatch
#
# KERNAL
#
$0314-$0315 CINV IRQ RAM vector
$0316-$0317 CBINV BRK instr RAM vector
$0318-$0319 NMINV NMI RAM vector
$031A-$032D Indirects for code
Conforms to KERNAL spec 8/19/80
$031A-$031B IOPEN
$031C-$031D ICLOSE
$031E-$031F ICHKIN
$0320-$0321 ICKOUT
$0322-$0323 ICLRCH
$0324-$0325 IBASIN
$0326-$0327 IBSOUT
$0328-$0329 ISTOP
$032A-$032B IGETIN
$032C-$032D ICLALL
$032E-$032F USRCMD
$0330-$0331 ILOAD
$0332-$0333 ISAVE savesp
$033C-$03FB TBUFFR cassette data b

View file

@ -1,894 +0,0 @@
- C64 RAM Map (STA)
-
- Joe Forster/STA:
- Commodore 64 memory map
- http://sta.c64.org/cbm64mem.html
-
- edited by awsm.de // @awsm9000
- http://www.awsm.de/mem64/
-
- Corrections (typos as well as content), translations etc.
- welcome at: https://github.com/mist64/c64disasm
-
------------------------------------------------------------
-
# This plain text file is formatted so that it can be automatically
# parsed in order to create cross-references etc.
# * Lines starting with "-" is top-level information. The first line
# is the title. Lines starting with "--" are separators.
# * Lines starting with "#" are internal comments.
# * Hex addresses start at column 0.
# * Symbols start at column 13.
# * The description starts at column 21.
# * All lines of the description until the first blank line are
# combined into the heading.
# * A '.' character at the end of a heading line represents a hard
# line break.
# * The remaining text is in MarkDown format.
# * All addresses are 4 digits and have a leading '$'.
# The encoding is UTF-8.
$0000 D6510 Processor port data direction register
Bits:
* Bit #x: 0 = Bit #x in processor port can only be read; 1 = Bit #x in processor port can be read and written.
Default: $2F, %00101111.
$0001 R6510 Processor port
Bits:
* Bits #0-#2: Configuration for memory areas $A000-$BFFF, $D000-$DFFF and $E000-$FFFF. Values:
* %x00: RAM visible in all three areas.
* %x01: RAM visible at $A000-$BFFF and $E000-$FFFF.
* %x10: RAM visible at $A000-$BFFF; KERNAL ROM visible at $E000-$FFFF.
* %x11: BASIC ROM visible at $A000-$BFFF; KERNAL ROM visible at $E000-$FFFF.
* %0xx: Character ROM visible at $D000-$DFFF. (Except for the value %000, see above.)
* %1xx: I/O area visible at $D000-$DFFF. (Except for the value %100, see above.)
* Bit #3: Datasette output signal level.
* Bit #4: Datasette button status; 0 = One or more of PLAY, RECORD, F.FWD or REW pressed; 1 = No button is pressed.
* Bit #5: Datasette motor control; 0 = On; 1 = Off.
Default: $37, %00110111.
$0002 Unused
$0003-$0004 ADRAY1 Unused.
Default: $B1AA, execution address of routine converting floating point to integer.
$0005-$0006 ADRAY2 Unused.
Default: $B391, execution address of routine converting integer to floating point.
$0007 CHARAC Byte being searched for during various operations.
Current digit of number being input.
$0007 INTEGR Low byte of first integer operand during AND and OR.
Low byte of integer-format FAC during INT().
$0008 ENDCHR Byte being search for during various operations.
Current byte of BASIC line during tokenization.
High byte of first integer operand during AND and OR.
$0009 TRMPOS Current column number during SPC() and TAB().
$000A VERCK LOAD/VERIFY switch
Values:
* $00: LOAD.
* $01-$FF: VERIFY.
$000B COUNT Current token during tokenization.
Length of BASIC line during insertion of line.
AND/OR switch; $00 = AND; $FF = OR.
Number of dimensions during array operations.
$000C DIMFLG Switch for array operations
Values:
* $00: Operation was not called by DIM.
* $40-$7F: Operation was called by DIM.
$000D VALTYP Current expression type
Values:
* $00: Numerical.
* $FF: String.
$000E INTFLG Current numerical expression type
Bits:
* Bit #7: 0 = Floating point; 1 = Integer.
$000F GARBFL Garbage collection indicator during memory allocation for string variable; $00-$7F = There was no garbage collection yet; $80 = Garbage collection already took place.
$000F DORES Quotation mode switch during tokenization; Bit #6: 0 = Normal mode; 1 = Quotation mode.
Quotation mode switch during LIST; $01 = Normal mode; $FE = Quotation mode.
$0010 SUBFLG Switch during fetch of variable name
Values:
* $00: Integer variables are accepted.
* $01-$FF: Integer variables are not accepted.
$0011 INPFLG GET/INPUT/READ switch
Values:
* $00: INPUT.
* $40: GET.
* $98: READ.
$0012 TANSGN Sign during SIN() and TAN()
Values:
* $00: Positive.
* $FF: Negative.
$0013 CHANNL Current I/O device number.
Default: $00, keyboard for input and screen for output.
$0014-$0015 LINNUM Line number during GOSUB, GOTO and RUN.
Second line number during LIST.
$0014-$0015 POKER Memory address during PEEK, POKE, SYS and WAIT.
$0016 TEMPPT Pointer to next expression in string stack
Values: $19; $1C; $1F; $22.
Default: $19.
$0017-$0018 LASTPT Pointer to previous expression in string stack.
$0019-$0021 TEMPST String stack, temporary area for processing string expressions (9 bytes, 3 entries).
$0022-$0025 INDEX Temporary area for various operations (4 bytes).
$0026-$002A RES Auxiliary arithmetical register for division and multiplication (4 bytes).
$002B-$002C TXTTAB Pointer to beginning of BASIC area.
Default: $0801, 2049.
$002D-$002E VARTAB Pointer to beginning of variable area.
(End of program plus 1.)
$002F-$0030 ARYTAB Pointer to beginning of array variable area.
$0031-$0032 STREND Pointer to end of array variable area.
$0033-$0034 FRETOP Pointer to beginning of string variable area.
(Grows downwards from end of BASIC area.)
$0035-$0036 FRESPC Pointer to memory allocated for current string variable.
$0037-$0038 MEMSIZ Pointer to end of BASIC area.
Default: $A000, 40960.
$0039-$003A CURLIN Current BASIC line number
Values:
* $0000-$F9FF, 0-63999: Line number.
* $FF00-$FFFF: Direct mode, no BASIC program is being executed.
$003B-$003C OLDLIN Current BASIC line number for CONT.
$003D-$003E OLDTXT Pointer to next BASIC instruction for CONT
Values:
* $0000-$00FF: CONT'ing is not possible.
* $0100-$FFFF: Pointer to next BASIC instruction.
$003F-$0040 DATLIN BASIC line number of current DATA item for READ.
$0041-$0042 DATPTR Pointer to next DATA item for READ.
$0043-$0044 INPPTR Pointer to input result during GET, INPUT and READ.
$0045-$0046 VARNAM Name and type of current variable
Bits:
* $0045 bits #0-#6: First character of variable name.
* $0046 bits #0-#6: Second character of variable name; $00 = Variable name consists of only one character.
* $0045 bit #7 and $0046 bit #7:
* %00: Floating-point variable.
* %01: String variable.
* %10: FN function, created with DEF FN.
* %11: Integer variable.
$0047-$0048 VARPNT Pointer to value of current variable or FN function.
$0049-$004A FORPNT Pointer to value of current variable during LET.
$0049 ANDMSK Value of second parameter during WAIT.
Logical number during CLOSE and CLOSE
Device number of LOAD, SAVE and VERIFY.
$004A EORMSK Value of third parameter during WAIT.
Device number during OPEN.
$004B-$004C VARTXT Temporary area for saving original pointer to current BASIC instruction during GET, INPUT and READ.
$004D OPMASK Comparison operator indicator
Bits:
* Bit #1: 1 = ">" (greater than) is present in expression.
* Bit #2: 1 = "=" (equal to) is present in expression.
* Bit #3: 1 = "<" (less than) is present in expression.
$004E-$004F Pointer to current FN function.
$0050-$0052 DSCPNT Pointer to current string variable during memory allocation.
$0053 FOUR6 Step size of garbage collection
Values: $03; $07.
$0054-$0056 JMPER JMP ABS machine instruction, jump to current BASIC function.
$0055-$0056 Execution address of current BASIC function.
$0057-$005B TEMPF1 Arithmetic register #3 (5 bytes).
$005C-$0060 TEMPF2 Arithmetic register #4 (5 bytes).
$0061-$0066 FAC FAC, arithmetic register #1 (5 bytes).
$0066 FACSGN Sign of FAC
Bits:
* Bit #7: 0 = Positive; 1 = Negative.
$0067 SGNFLG Number of degrees during polynomial evaluation.
$0068 BITS Temporary area for various operations.
$0069-$006E ARG, arithmetic register #2 (5 bytes).
$006E ARGSGN Sign of ARG
Bits:
* Bit #7: 0 = Positive; 1 = Negative.
$006F-$0070 STRNG1 Pointer to first string expression during string comparison.
$0071-$0072 STRNG2 Temporary area for saving original pointer to current BASIC instruction during VAL().
$0071-$0072 POLYPT Pointer to current item of polynomial table during polynomial evaluation.
$0071-$0072 CURTOL Auxiliary pointer during array operations.
$0073-$008A CHRGET CHRGET. Machine code routine to read next byte from BASIC program or direct command (24 bytes).
$0079 CHRGOT CHRGOT. Read current byte from BASIC program or direct command.
007A-$007B Pointer to current byte in BASIC program or direct command.
$008B-$008F RNDX Previous result of RND().
$0090 STATUS Value of ST variable, device status for serial bus and datasette input/output
Serial bus bits:
* Bit #0: Transfer direction during which the timeout occured; 0 = Input; 1 = Output.
* Bit #1: 1 = Timeout occurred.
* Bit #4: 1 = VERIFY error occurred (only during VERIFY), the file read from the device did not match that in the memory.
* Bit #6: 1 = End of file has been reached.
* Bit #7: 1 = Device is not present.
Datasette bits:
* Bit #2: 1 = Block is too short (shorter than 192 bytes).
* Bit #3: 1 = Block is too long (longer than 192 bytes).
* Bit #4: 1 = Not all bytes read with error during pass 1 could be corrected during pass 2, or a VERIFY error occurred, the file read from the device did not match that in the memory.
* Bit #5: 1 = Checksum error occurred.
* Bit #6: 1 = End of file has been reached (only during reading data files).
$0091 STKEY Stop key indicator
Values:
* $7F: Stop key is pressed.
* $FF: Stop key is not pressed.
$0092 SVXT Unknown. (Timing constant during datasette input.)
$0093 VERCK LOAD/VERIFY switch
Values:
* $00: LOAD.
* $01-$FF: VERIFY.
$0094 C3P0 Serial bus output cache status
Bits:
* Bit #7: 1 = Output cache dirty, must transfer cache contents upon next output to serial bus.
$0095 BSOUR Serial bus output cache, previous byte to be sent to serial bus.
$0096 SYNO Unknown. (End of tape indicator during datasette input/output.)
$0097 XSAV Temporary area for saving original value of Y register during input from RS232.
Temporary area for saving original value of X register during input from datasette.
$0098 LDTND Number of files currently open
Values: $00-$0A, 0-10.
$0099 DFLTN Current input device number.
Default: $00, keyboard.
$009A DFLTO Current output device number.
Default: $03, screen.
$009B PRTY Unknown. (Parity bit during datasette input/output.)
$009C DPSW Unknown. (Byte ready indicator during datasette input/output.)
$009D MSGFLG System error display switch
Bits:
* Bit #6: 0 = Suppress I/O error messages; 1 = Display them.
* Bit #7: 0 = Suppress system messages; 1 = Display them.
$009E PTR1 Error counter during LOAD from datasette.
Values: $00-$3E, 0-62.
$009E T1 Block header type during datasette input/output.
Length of file name during datasette input/output.
Byte to be put into output buffer during RS232 and datasette output.
$009F PTR2 Error correction counter during LOAD from datasette.
Values: $00-$3E, 0-62.
$009F T2 Auxiliary counter for writing file name into datasette buffer.
Auxiliary counter for comparing requested file name with file name read from datasette during datasette input.
$00A0-$00A2 TIME Value of TI variable, time of day, increased by 1 every 1/60 second (on PAL machines)
Values: $000000-$4F19FF, 0-518399 (on PAL machines).
$00A3 R2D2 EOI switch during serial bus output
Bits:
* Bit #7: 0 = Send byte right after handshake; 1 = Do EOI delay first.
Bit counter during datasette output.
$00A4 FIRT Byte buffer during serial bus input.
Parity during datasette input/output.
$00A5 CNTDN Bit counter during serial bus input/output.
Counter for sync mark during datasette output.
$00A6 BUFPT Offset of current byte in datasette buffer.
$00A7 INBIT Bit buffer during RS232 input.
$00A8 BITCI Bit counter during RS232 input.
$00A9 RINONE Stop bit switch during RS232 input
Values:
* $00: Data bit.
* $01-$FF: Stop bit.
$00AA RIDATA Byte buffer during RS232 input.
$00AB RIPRTY Parity during RS232 input.
Computed block checksum during datasette input.
$00AC-$00AD Start address for SAVE to serial bus.
Pointer to current byte during SAVE to serial bus or datasette.
Pointer to line in screen memory to be scrolled during scrolling the screen.
$00AE-$00AF Load address read from input file and pointer to current byte during LOAD/VERIFY from serial bus.
End address after LOAD/VERIFY from serial bus or datasette.
End address for SAVE to serial bus or datasette.
Pointer to line in Color RAM to be scrolled during scrolling the screen.
$00B0-$00B1 Unknown.
$00B2-$00B3 TAPE1 Pointer to datasette buffer.
Default: $033C, 828.
$00B4 BITTS Bit counter and stop bit switch during RS232 output
Bits:
* Bits #0-#6: Bit count.
* Bit #7: 0 = Data bit; 1 = Stop bit.
Bit counter during datasette input/output.
$00B5 NXTBIT Bit buffer (in bit #2) during RS232 output.
$00B6 RODATA Byte buffer during RS232 output.
$00B7 FNLEN Length of file name or disk command; first parameter of LOAD, SAVE and VERIFY or fourth parameter of OPEN
Values:
* $00: No parameter.
* $01-$FF: Parameter length.
$00B8 LA Logical number of current file.
$00B9 SA Secondary address of current file.
$00BA FA Device number of current file.
$00BB-$00BC FNADR Pointer to current file name or disk command; first parameter of LOAD, SAVE and VERIFY or fourth parameter of OPEN.
$00BD ROPRTY Parity during RS232 output.
Byte buffer during datasette input/output.
$00BE FSBLK Block counter during datasette input/output.
$00BF MYCH Unknown.
$00C0 CAS1 Datasette motor switch
Values:
* $00: No button was pressed, motor has been switched off. If a button is pressed on the datasette, must switch motor on.
* $01-$FF: Motor is on.
$00C1-$00C2 STAL Start address during SAVE to serial bus, LOAD and VERIFY from datasette and SAVE to datasette.
Pointer to current byte during memory test.
$00C3-$00C4 MEMUSS Start address for a secondary address of 0 for LOAD and VERIFY from serial bus or datasette.
Pointer to ROM table of default vectors during initialization of I/O vectors.
$00C5 LSTX Matrix code of key previously pressed
Values:
* $00-$3F: Keyboard matrix code.
* $40: No key was pressed at the time of previous check.
$00C6 NDX Length of keyboard buffer
Values:
* $00, 0: Buffer is empty.
* $01-$0A, 1-10: Buffer length.
$00C7 RVS Reverse mode switch
Values:
* $00: Normal mode.
* $12: Reverse mode.
$00C8 INDX Length of line minus 1 during screen input. Values: $27, 39; $4F, 79.
$00C9 LSXP Cursor row during screen input. Values: $00-$18, 0-24.
$00CA Cursor column during screen input. Values: $00-$27, 0-39.
$00CB SFDX Matrix code of key currently being pressed
Values:
* $00-$3F: Keyboard matrix code.
* $40: No key is currently pressed.
$00CC BLNSW Cursor visibility switch
Values:
* $00: Cursor is on.
* $01-$FF: Cursor is off.
$00CD BLNCT Delay counter for changing cursor phase
Values:
* $00, 0: Must change cursor phase.
* $01-$14, 1-20: Delay.
$00CE GDBLN Screen code of character under cursor.
$00CF BLNON Cursor phase switch
Values:
* $00: Cursor off phase, original character visible.
* $01: Cursor on phase, reverse character visible.
$00D0 CRSW End of line switch during screen input
Values:
* $00: Return character reached, end of line.
* $01-$FF: Still reading characters from line.
$00D1-$00D2 PNT Pointer to current line in screen memory.
$00D3 PNTR Current cursor column. Values: $00-$27, 0-39.
$00D4 QTSW Quotation mode switch
Values:
* $00: Normal mode.
* $01: Quotation mode.
$00D5 LNMX Length of current screen line minus 1. Values: $27, 39; $4F, 79.
$00D6 TBLX Current cursor row. Values: $00-$18, 0-24.
$00D7 DATA PETSCII code of character during screen input/output.
Bit buffer during datasette input.
Block checksum during datasette output.
$00D8 INSRT Number of insertions
Values:
* $00: No insertions made, normal mode, control codes change screen layout or behavior.
* $01-$FF: Number of insertions, when inputting this many character next, those must be turned into control codes, similarly to quotation mode.
$00D9-$00F2 LDTB1 High byte of pointers to each line in screen memory (25 bytes)
Values:
* $00-$7F: Pointer high byte.
* $80-$FF: No pointer, line is an extension of previous line on screen.
$00F3-$00F4 USER Pointer to current line in Color RAM.
$00F5-$00F6 KEYTAB Pointer to current conversion table during conversion from keyboard matrix codes to PETSCII codes.
$00F7-$00F8 RIBUF Pointer to RS232 input buffer
Values:
* $0000-$00FF: No buffer defined, a new buffer must be allocated upon RS232 input.
* $0100-$FFFF: Buffer pointer.
$00F9-$00FA ROBUF Pointer to RS232 output buffer
Values:
* $0000-$00FF: No buffer defined, a new buffer must be allocated upon RS232 output.
* $0100-$FFFF: Buffer pointer.
$00FB-$00FE FREKZP Unused (4 bytes).
$00FF-$010A BASZPT Buffer for conversion from floating point to string (12 bytes.)
$0100-$01FF Processor stack. Also used for storing data related to FOR and GOSUB.
$0100-$013D BAD Pointers to bytes read with error during datasette input (62 bytes, 31 entries).
$0200-$0258 BUF Input buffer, storage area for data read from screen (89 bytes).
$0259-$0262 LAT Logical numbers assigned to files (10 bytes, 10 entries).
$0263-$026C FAT Device numbers assigned to files (10 bytes, 10 entries).
$026D-$0276 SAT Secondary addresses assigned to files (10 bytes, 10 entries).
$0277-$0280 KEYD Keyboard buffer (10 bytes, 10 entries).
$0281-$0282 MEMSTR Pointer to beginning of BASIC area after memory test.
Default: $0800, 2048.
$0283-$0284 MEMSIZ Pointer to end of BASIC area after memory test.
Default: $A000, 40960.
$0285 TIMOUT Unused. (Serial bus timeout.)
$0286 COLOR Current color, cursor color
Values: $00-$0F, 0-15.
$0287 GDCOL Color of character under cursor
Values: $00-$0F, 0-15.
$0288 HIBASE High byte of pointer to screen memory for screen input/output.
Default: $04, $0400, 1024.
$0289 XMAX Maximum length of keyboard buffer
Values:
* $00, 0: No buffer.
* $01-$0F, 1-15: Buffer size.
$028A RPTFLG Keyboard repeat switch
Bits:
* Bits #6-#7:
* %00 = Only cursor up/down, cursor left/right, Insert/Delete and Space repeat
* %01 = No key repeats
* %1x = All keys repeat.
$028B KOUNT Delay counter during repeat sequence, for delaying between successive repeats
Values:
* $00, 0: Must repeat key.
* $01-$04, 1-4: Delay repetition.
$028C DELAY Repeat sequence delay counter, for delaying before first repetition
Values:
* $00, 0: Must start repeat sequence.
* $01-$10, 1-16: Delay repeat sequence.
$028D SHFLAG Shift key indicator
Bits:
* Bit #0: 1 = One or more of left Shift, right Shift or Shift Lock is currently being pressed or locked.
* Bit #1: 1 = Commodore is currently being pressed.
* Bit #2: 1 = Control is currently being pressed.
$028E LSTSHF Previous value of shift key indicator
Bits:
* Bit #0: 1 = One or more of left Shift, right Shift or Shift Lock was pressed or locked at the time of previous check.
* Bit #1: 1 = Commodore was pressed at the time of previous check.
* Bit #2: 1 = Control was pressed at the time of previous check.
$028F-$0290 KEYLOG Execution address of routine that, based on the status of shift keys, sets the pointer at memory address $00F5-$00F6 to the appropriate conversion table for converting keyboard matrix codes to PETSCII codes.
Default: $EB48.
$0291 MODE Commodore-Shift switch
Bits:
* Bit #7: 0 = Commodore-Shift is disabled; 1 = Commodore-Shift is enabled, the key combination will toggle between the uppercase/graphics and lowercase/uppercase character set.
$0292 AUTODN Scroll direction switch during scrolling the screen
Values:
* $00: Insertion of line before current line, current line and all lines below it must be scrolled 1 line downwards.
* $01-$FF: Bottom of screen reached, complete screen must be scrolled 1 line upwards.
$0293 M51CTR RS232 control register
Bits:
* Bits #0-#3: Baud rate, transfer speed. Values:
* %0000: User specified.
* %0001: 50 bit/s.
* %0010: 75 bit/s.
* %0011: 110 bit/s.
* %0100: 150 bit/s.
* %0101: 300 bit/s.
* %0110: 600 bit/s.
* %0111: 1200 bit/s.
* %1000: 2400 bit/s.
* %1001: 1800 bit/s.
* %1010: 2400 bit/s.
* %1011: 3600 bit/s.
* %1100: 4800 bit/s.
* %1101: 7200 bit/s.
* %1110: 9600 bit/s.
* %1111: 19200 bit/s.
* Bits #5-#6: Byte size, number of data bits per byte; %00 = 8; %01 = 7, %10 = 6; %11 = 5.
* Bit #7: Number of stop bits; 0 = 1 stop bit; 1 = 2 stop bits.
$0294 M51CDR RS232 command register
Bits:
* Bit #0: Synchronization type; 0 = 3 lines; 1 = X lines.
* Bit #4: Transmission type; 0 = Duplex; 1 = Half duplex.
* Bits #5-#7: Parity mode. Values:
* %xx0: No parity check, bit #7 does not exist.
* %001: Odd parity.
* %011: Even parity.
* %101: No parity check, bit #7 is always 1.
* %111: No parity check, bit #7 is always 0.
$0295-$0296 M51AJB Default value of RS232 output timer, based on baud rate
(Must be filled with actual value before RS232 input/output if baud rate is "user specified" in RS232 control register, memory address $0293.)
$0297 RSSTAT Value of ST variable, device status for RS232 input/output
Bits:
* Bit #0: 1 = Parity error occurred.
* Bit #1: 1 = Frame error, a stop bit with the value of 0, occurred.
* Bit #2: 1 = Input buffer underflow occurred, too much data has arrived but it has not been read from the buffer in time.
* Bit #3: 1 = Input buffer is empty, nothing to read.
* Bit #4: 0 = Sender is Clear To Send; 1 = Sender is not ready to send data to receiver.
* Bit #6: 0 = Receiver reports Data Set Ready; 1 = Receiver is not ready to receive data.
* Bit #7: 1 = Carrier loss, a stop bit and a data byte both with the value of 0, detected.
$0298 BITNUM RS232 byte size, number of data bits per data byte, default value for bit counters.
$0299-$029A BAUDOF Default value of RS232 input timer, based on baud rate
(Calculated automatically from default value of RS232 output timer, at memory address $0295-$0296.)
$029B RIDBE Offset of byte received in RS232 input buffer.
$029C RIDBS Offset of current byte in RS232 input buffer.
$029D RODBS Offset of byte to send in RS232 output buffer.
$029E RODBE Offset of current byte in RS232 output buffer.
$029F-$02A0 IRQTMP Temporary area for saving pointer to original interrupt service routine during datasette input output
Values:
* $0000-$00FF: No datasette input/output took place yet or original pointer has been already restored.
* $0100-$FFFF: Original pointer, datasette input/output currently in progress.
$02A1 ENABL Temporary area for saving original value of CIA#2 interrupt control register, at memory address $DD0D, during RS232 input/output.
$02A2 CASTON Temporary area for saving original value of CIA#1 timer #1 control register, at memory address $DC0E, during datasette input/output.
$02A3-$02A4 Unknown.
$02A5 LINTMP Number of line currently being scrolled during scrolling the screen.
$02A6 PALNTS PAL/NTSC switch, for selecting RS232 baud rate from the proper table
Values:
* $00: NTSC.
* $01: PAL.
$02A7-$02FF Unused (89 bytes).
$0300-$0301 IERROR Execution address of warm reset, displaying optional BASIC error message and entering BASIC idle loop.
Default: $E38B.
$0302-$0303 IMAIN Execution address of BASIC idle loop.
Default: $A483.
$0304-$0305 ICRNCH Execution address of BASIC line tokenizater routine.
Default: $A57C.
$0306-$0307 IQPLOP Execution address of BASIC token decoder routine.
Default: $A71A.
$0308-$0309 IGONE Execution address of BASIC instruction executor routine.
Default: $A7E4.
$030A-$030B IEVAL Execution address of routine reading next item of BASIC expression.
Default: $AE86.
$030C SAREG Default value of register A for SYS.
Value of register A after SYS.
$030D SXREG Default value of register X for SYS.
Value of register X after SYS.
$030E SYREG Default value of register Y for SYS.
Value of register Y after SYS.
$030F SPREG Default value of status register for SYS.
Value of status register after SYS.
$0310-$0312 USRPOK JMP ABS machine instruction, jump to USR() function.
$0311-$0312 USRADD Execution address of USR() function.
$0313 Unused.
$0314-$0315 CINV Execution address of interrupt service routine.
Default: $EA31.
$0316-$0317 CBINV Execution address of BRK service routine.
Default: $FE66.
$0318-$0319 NMINV Execution address of non-maskable interrupt service routine.
Default: $FE47.
$031A-$031B IOPEN Execution address of OPEN, routine opening files.
Default: $F34A.
$031C-$031D ICLOSE Execution address of CLOSE, routine closing files.
Default: $F291.
$031E-$031F ICHKIN Execution address of CHKIN, routine defining file as default input.
Default: $F20E.
$0320-$0321 ICKOUT Execution address of CHKOUT, routine defining file as default output.
Default: $F250.
$0322-$0323 ICLRCH Execution address of CLRCHN, routine initializating input/output.
Default: $F333.
$0324-$0325 IBASIN Execution address of CHRIN, data input routine, except for keyboard and RS232 input.
Default: $F157.
$0326-$0327 IBSOUT Execution address of CHROUT, general purpose data output routine.
Default: $F1CA.
$0328-$0329 ISTOP Execution address of STOP, routine checking the status of Stop key indicator, at memory address $0091.
Default: $F6ED.
$032A-$032B IGETIN Execution address of GETIN, general purpose data input routine.
Default: $F13E.
$032C-$032D ICLALL Execution address of CLALL, routine initializing input/output and clearing all file assignment tables.
Default: $F32F.
$032E-$032F USRCMD Unused.
Default: $FE66.
$0330-$0331 ILOAD Execution address of LOAD, routine loading files.
Default: $F4A5.
$0332-$0333 ISAVE Execution address of SAVE, routine saving files.
Default: $F5ED.
$0334-$033B Unused (8 bytes).
$033C-$03FB TBUFFR Datasette buffer (192 bytes).
$03FC-$03FF Unused (4 bytes).

View file

@ -1,449 +0,0 @@
#!/usr/bin/python3
import re, os
import pprint
import markdown
filenames = [
'c64mem_mapc64.txt',
'c64mem_64er.txt',
'c64mem_64intern.txt',
'c64mem_sta.txt',
'c64mem_src.txt',
'c64mem_prg.txt',
'c64mem_64map.txt',
'c64mem_jb.txt',
]
names = [
'Mapping the Commodore 64',
'64\'er [German]',
'Data Becker [German]',
'Joe Forster/STA',
'Microsoft/Commodore Source',
'Programmer\'s Reference Guide',
'64map',
'Jim Butterfield',
]
links = [
'http://unusedino.de/ec64/technical/project64/mapping_c64.html',
'https://archive.org/details/64er_sonderheft_1986_07/page/n6/mode/2up',
'https://www.pagetable.com/?p=1015',
'http://www.awsm.de/mem64/',
'https://github.com/mist64/cbmsrc',
'http://www.zimmers.net/cbmpics/cbm/c64/c64prg.txt',
'http://unusedino.de/ec64/technical/project64/memory_maps.html',
'https://www.atarimagazines.com/compute/issue29/394_1_COMMODORE_64_MEMORY_MAP.php',
]
descriptions = [
'Reference from <i>Mapping the Commodore 64</i> by Sheldon Leemon, ISBN 0-942386-23-X.',
'German-language reference from <i>Memory Map mit Wandervorschl&auml;gen</i> by Dr. H. Hauck, in 64\'er Sonderheft 1986/07.',
'German-language reference from <i>Das neue Commodore-64-intern-Buch</i> by Data Becker, ISBN 3890113079.',
'Reference by Joe Forster/STA, with awsm\'s changes applied.',
'Comments from the original M6502 BASIC source by Microsoft and the original C64 KERNAL source by Commodore',
'Reference from <i>Commodore 64 Programmer\'s Reference Guide</i>.',
'Reference as found in "Commodore_64_Memory_Maps.txt" by anonymous.',
'Reference by Jim Butterfield in COMPUTE! #29 (October 1982).',
]
def cross_reference(string):
hex_numbers = re.findall(r'\$[0-9A-F][0-9A-F][0-9A-F][0-9A-F]', string)
for hex_number in hex_numbers:
dec_number = int(hex_number[1:], 16)
if dec_number < 0x0400:
if dec_number < 0x100:
formatted_hex_number = '${:02X}'.format(dec_number)
else:
formatted_hex_number = '${:04X}'.format(dec_number)
string = string.replace(hex_number, '<a href="#' + '{:04X}'.format(dec_number) + '">' + formatted_hex_number + '</a>')
elif (dec_number >= 0xa000 and dec_number <= 0xbfff) or (dec_number >= 0xe000 and dec_number <= 0xffff):
string = string.replace(hex_number, '<a href="../c64disasm/#' + '{:04X}'.format(dec_number) + '">' + hex_number + '</a>')
return string
f = os.popen('git log -1 --pretty=format:%h .')
revision = f.read()
f = os.popen('git log -1 --date=short --pretty=format:%cd .')
date = f.read()
data = []
linenumber = []
address = []
for filename in filenames:
d = []
for f in filename.split(';'):
d += [line.rstrip() for line in open(f)]
data.append(d)
linenumber.append(0)
address.append(0)
files = len(filenames)
for i in range(0, files):
while True:
line = data[i][linenumber[i]]
if len(line) > 0 and line[0] == '$':
break
linenumber[i] = linenumber[i] + 1
print('<meta http-equiv="Content-type" content="text/html; charset=utf-8" />')
print('<html>')
print('<head>')
print('<title>Memory Map | Ultimate C64 Reference</title>')
print('')
print('<script language="javascript">')
print(' window.onload = init;')
print(' function init() {')
print(' var tbl = document.getElementById("disassembly_table");')
print(' for (var i = 0; i < ' + str(len(filenames)) + '; i++) {')
print(' var key = "com.pagetable.c64mem.column_" + i;')
print(' var element_name = "checkbox_" + i;')
print(' var checked = localStorage.getItem(key) != "hidden";')
print(' document.getElementById(element_name).checked = checked;')
print(' hideCol(i, checked);')
print(' }')
print(' var key = "com.pagetable.c64mem.column_decimal";')
print(' var element_name = "checkbox_decimal";')
print(' var visible = localStorage.getItem(key) == "visible";')
print(' document.getElementById(element_name).checked = visible;')
print(' toggleDecimal(visible);')
print(' }')
print(' function toggleDecimal(visible) {')
print(' var tbl = document.getElementById("disassembly_table");')
print(' for (var i = 0; i < tbl.rows.length; i++) {')
print(' tbl.rows[i].cells[2].style.display = visible ? "" : "none";')
print(' }')
print(' var key = "com.pagetable.c64mem.column_decimal";')
print(' var cnt = document.getElementById("disassembly_container");')
print(' if (visible) {')
print(' cnt.className = "disassembly_container_with_dec";')
print(' localStorage.setItem(key, "visible");')
print(' } else {')
print(' cnt.className = "disassembly_container_no_dec";')
print(' localStorage.removeItem(key);')
print(' }')
print(' }')
print(' function hideCol(col, checked) {')
print(' var tbl = document.getElementById("disassembly_table");')
print(' for (var i = 0; i < tbl.rows.length; i++) {')
print(' tbl.rows[i].cells[col+3].style.display = checked ? "" : "none";') # data columns start at index 3
print(' }')
print(' var key = "com.pagetable.c64mem.column_" + col;')
print(' if (checked) {')
print(' localStorage.removeItem(key);')
print(' } else {')
print(' localStorage.setItem(key, "hidden");')
print(' }')
print(' }')
print(' function openAll() {')
print(' var elems = document.getElementsByTagName("details");')
print(' document.getElementById("toggle_details_button").innerHTML = "Hide All Details";')
print(' document.getElementById("toggle_details_button").setAttribute("onClick", "javascript: closeAll();");')
print('')
print(' for (let item of elems) {')
print(' item.setAttribute("open", true);')
print(' }')
print(' }')
print('')
print(' function closeAll() { ')
print(' var elems = document.getElementsByTagName("details");')
print(' document.getElementById("toggle_details_button").setAttribute("onClick", "javascript: openAll();" );')
print(' document.getElementById("toggle_details_button").innerHTML = "Expand All Details"; ')
print(' ')
print(' for (let item of elems) {')
print(' item.removeAttribute("open");')
print(' }')
print(' }')
print('</script>')
print('')
print('<link rel="stylesheet" href="../style.css">')
address_width=6.4
label_width=4
decimal_width=5
print('<style type="text/css">')
print('')
print('div.disassembly_container_with_dec {')
print(' padding: 1em 0em 1em ' + str(address_width + label_width + decimal_width + 1.6) + 'em;')
print(' overflow: scroll;')
print('}')
print('')
print('div.disassembly_container_no_dec {')
print(' padding: 1em 0em 1em ' + str(address_width + label_width + 0.9) + 'em;')
print(' overflow: scroll;')
print('}')
print('')
print('table.disassembly_table>tbody>tr>td, table.disassembly_table>tbody>tr>th.top_row {')
print(' min-width: 30em;')
print(' max-width: 40em;')
print('}')
print('')
print('table.disassembly_table th.left_column {')
print(' width: '+ str(address_width) +'em;')
print('}')
print('')
print('table.disassembly_table th.label_column {')
print(' width: ' + str(label_width) +'em;')
print(' left: ' + str(address_width + 3) + 'em;')
print(' z-index: 12;')
print(' font-family: monospace;')
print(' text-align: center;')
print(' color: yellow;')
print('}')
print('')
print('table.disassembly_table th.decimal_column {')
print(' width: ' + str(decimal_width) + 'em;')
print(' left: ' + str(address_width + label_width + 1.2) + 'em;')
print(' z-index: 13;')
print('}')
print('')
print('details {')
print(' font-family: serif;')
print('}')
print('summary {')
print(' font-family: Helvetica;')
print('}')
print('')
print('</style>')
print('</head>')
print('<body>')
# http://tholman.com/github-corners/
print('<a href="https://github.com/mist64/c64ref" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:var(--main-color); color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>')
print('<div class="topnav">')
print(' <h1>Ultimate Commodore 64 Reference</h1> ')
#print(' <a href="#">KERNAL API</a><!-- kernal/ -->')
print(' <a href="../c64disasm/">ROM Disassembly</a><!-- c64disasm/ -->')
print(' <a class="active" href="../c64mem/">Memory Map</a><!-- c64mem/ -->')
#print(' <a href="#">I/O Map</a><!-- c64io/ -->')
#print(' <a href="#">6502 CPU</a><!-- 6502/ -->')
print('</div>')
print('<div class="body">')
print('<h1>C64 Memory Map</h1>')
print('<p><i>by <a href="http://www.pagetable.com/">Michael Steil</a>, <a href="https://github.com/mist64/c64ref">github.com/mist64/c64ref</a>. Revision ' + revision + ', ' + date + '</i></p>')
print('<b>This allows you to view different commentaries side-by-side. You can enable/disable individual columns:</b><br/><br/>')
print('<table class="checkbox_table">')
for i in range(0, len(filenames)):
print('<tr><td><input type="checkbox" id="checkbox_' + str(i) + '" checked onclick="hideCol(' + str(i) + ', document.getElementById(\'checkbox_' + str(i) + '\').checked);" /></td><td style="white-space: nowrap;"><b><a href="' + links[i] + '">' + names[i] + '</a></b><td>' + descriptions[i] + '</td></tr>')
print('</table>')
print('<p>')
print('<input type="checkbox" id="checkbox_decimal" name="checkbox_decimal" onclick="toggleDecimal(document.getElementById(\'checkbox_decimal\').checked);">')
print('<label for="checkbox_decimal">Show Decimal Address</label></input>')
print('<br />')
print('<button id="toggle_details_button" onclick="closeAll()">Hide All Details</button>')
print('</p>')
print('<div class="disassembly_container_no_dec" id="disassembly_container">')
print('<table id="disassembly_table" class="disassembly_table">')
print('<tr>')
print('<th class="left_column">Address</th>')
print('<th class="label_column">Symbol</th>')
print('<th class="decimal_column">Decimal</th>')
for i in range(0, files):
print('<th class="top_row">' + names[i] + '</th>')
print('</tr>')
count = 0
last_address1 = None
last_address2 = None
while(True):
count += 1
# if count > 80:
# break
# make linenumber[] point to next line for all files
for i in range(0, files):
if linenumber[i] >= len(data[i]):
continue
while len(data[i][linenumber[i]]) > 0 and (data[i][linenumber[i]][0] == '-' or data[i][linenumber[i]][0] == '#'):
linenumber[i] = linenumber[i] + 1
list_address1 = []
list_address2 = []
list_symbol = []
for i in range(0, files):
if linenumber[i] >= len(data[i]):
continue
line = data[i][linenumber[i]]
address1 = line[1:5]
address1 = int(address1, 16)
address2 = line[7:11]
if len(address2.rstrip()) != 0:
address2 = int(address2, 16)
else:
address2 = None
symbol = line[13:19].rstrip()
list_address1.append(address1)
list_address2.append(address2)
list_symbol.append(symbol)
# reached end of all files?
if len(list_address1) == 0:
break
# the next address is the lowest one from all source
address1 = min(list_address1)
# the longest range wins
address2 = None
symbol = None
good_symbols = []
for i in range(0, len(list_address1)):
if list_address1[i] == address1 and (address2 == None or (list_address2[i] != None and list_address2[i] > address2)):
address2 = list_address2[i]
# get symbols of longest range
for i in range(0, len(list_address1)):
if list_address1[i] == address1 and list_address2[i] == address2 and list_symbol[i] != '':
good_symbols.append(list_symbol[i])
#print('xxx', address1, address2, good_symbols)
if len(good_symbols) != 0:
symbol = good_symbols[0]
else:
symbol = ''
print('<tr>')
# print address
anchors = ''
if address2 is not None:
r = range(address1, address2 + 1)
else:
r = range(address1, address1 + 1)
for address in r:
anchors += '<a name="{:04X}"/>'.format(address)
if address1 == last_address1 and address2 == last_address2:
print('<th class="left_column" style="visibility:hidden;"> ' + anchors + ' </th>')
else:
hex_range = '${:04X}'.format(address1)
if address2 != None:
hex_range += '-${:04X}'.format(address2)
print('<th class="left_column"> ' + anchors + hex_range + ' </th>')
# print symbol
if len(symbol) == 0:
print('<th class="label_column" style="visibility:hidden;"> </th>')
else:
print('<th class="label_column">' + symbol + ' <a name="' + symbol + '"/> </th>')
# print decimal
if address1 == last_address1 and address2 == last_address2:
print('<th class="decimal_column" style="visibility:hidden;"> </th>')
else:
dec_range = str(address1)
if address2 != None:
dec_range += '-' + str(address2)
print('<th class="decimal_column"> ' + dec_range + ' </th>')
last_address1 = address1
last_address2 = address2
for i in range(0, files):
print('<td>')
headings = []
comments = []
has_seen_blank_line = False
is_first_line = True
while True:
if linenumber[i] >= len(data[i]):
break
line = data[i][linenumber[i]]
if line.startswith('$'):
if not is_first_line:
# next address; stop here
break
# compare whether this address matches
cmp_address1 = line[1:5]
cmp_address1 = int(cmp_address1, 16)
cmp_address2 = line[7:11]
if len(cmp_address2.rstrip()) != 0:
cmp_address2 = int(cmp_address2, 16)
else:
cmp_address2 = None
cmp_symbol = line[13:19].rstrip()
if cmp_address1 != address1 or cmp_address2 != address2 or (cmp_symbol != symbol and cmp_symbol != ''):
break
is_first_line = False
comment = line[21:]
# print(comment)
if not has_seen_blank_line:
if len(comment.lstrip()) == 0:
has_seen_blank_line = True
else:
headings.append(comment)
else:
scomment = comment.lstrip()
comment = comment + '\n'
comments.append(comment)
linenumber[i] += 1
while len(comments) > 0 and comments[-1] == '\n':
comments = comments[0:-1]
#print('xxx',headings,comments)
is_collapsible = len(comments) and not (len(comments) == 1 and comments[0].isspace())
if is_collapsible:
print('<details open>')
if len(headings) or is_collapsible:
print('<b>')
all_text = ''
if is_collapsible:
print('<summary>')
if not len(headings):
print('')
previous_heading = ''
for heading in headings:
if previous_heading.endswith('.'):
heading = '<br/>' + heading
html_heading = markdown.markdown(heading)
html_heading.replace('<p>', '')
html_heading.replace('</p>', '')
all_text += heading + ' '
previous_heading = heading
all_text = cross_reference(all_text)
print(all_text)
print('</b>')
if is_collapsible:
print('</summary>')
else:
print('&nbsp;')
if len(comments):
all_text = ''
for comment in comments:
all_text += comment
all_text = markdown.markdown(all_text, extensions=['tables', 'sane_lists'])
all_text = cross_reference(all_text)
print(all_text)
else:
print('&nbsp;')
if is_collapsible:
print('</details>')
print('</td>')
print('</tr>')
print('</table>')
print('</div>')
print('</div>')
print('</body>')
print('</html>')

View file

@ -1,40 +0,0 @@
#!/usr/bin/python3
import sys
import os
import pprint
with open('c64mem_64intern.txt', 'r') as f:
lines = f.read().split('\n')
with open('symbols.txt', 'r') as f:
sym = f.read().split('\n')
symbols = {}
for s in sym:
if not s.startswith('$'):
continue
address = s[1:5]
name = s[6:12]
symbols[address] = name
#pprint.pprint(symbols)
for line in lines:
if line.startswith('-') or line.startswith('#') or len(line) == 0:
print(line)
continue
if not line.startswith('$'):
print(line)
continue
address = line[0:13]
start_address = line[1:5]
description = line[21:]
if start_address in symbols:
symbol = (symbols[start_address] + " ")[:8]
else:
symbol = " "
print(address + symbol + description)

View file

@ -1,207 +0,0 @@
$0000 D6510
$0001 R6510
#0002 # unnamed in Programmer's Reference Manual; part of "BLANK0" 3 (!) byte register area in BASIC source
$0003 ADRAY1
$0005 ADRAY2
$0007 CHARAC # also INTEGR
$0008 ENDCHR
$0009 TRMPOS
$000A VERCK
$000B COUNT
$000C DIMFLG
$000D VALTYP
$000E INTFLG
$000F GARBFL
$0010 SUBFLG
$0011 INPFLG
$0012 TANSGN
$0013 CHANNL # unnamed in Programmer's Reference Manual
$0014 LINNUM
$0016 TEMPPT
$0017 LASTPT
$0019 TEMPST
$0022 INDEX
$0022 INDEX1
$0024 INDEX2
$0026 RESHO
$002B TXTTAB
$002D VARTAB
$002F ARYTAB
$0031 STREND
$0033 FRETOP
$0035 FRESPC
$0037 MEMSIZ
$0039 CURLIN
$003B OLDLIN
$003D OLDTXT
$003F DATLIN
$0041 DATPTR
$0043 INPPTR
$0045 VARNAM
$0047 VARPNT
$0049 FORPNT
$004B OPPTR
$004B VARTXT
$004D OPMASK
$004E DEFPNT
$004E TEMPF3
$0050 DSCPNT
$0053 FOUR6
$0054 JMPER
$0057 TEMPF1
$005C TEMPF2
$0061 FAC
$0061 FACEXP
$0062 FACHO
$0066 FACSGN
$0067 SGNFLG
$0068 BITS
$0069 ARGEXP # aka ARG, AFAC, FAC2
$006A ARGHO
$006E ARGSGN
$006F ARISGN
$0070 FACOV
$0071 FBUFPT
$0073 CHRGET
$0079 CHRGOT
$007A TXTPTR
$008B RNDX
$0090 STATUS
$0091 STKEY
$0092 SVXT
$0093 VERCK
$0094 C3P0
$0095 BSOUR
$0096 SYNO
$0097 XSAV # unnamed in Programmer's Reference Manual
$0098 LDTND
$0099 DFLTN
$009A DFLTO
$009B PRTY
$009C DPSW
$009D MSGFLG
$009E PTR1
$009F PTR2
$00A0 TIME
$00A3 PCNTR # unnamed in Programmer's Reference Manual
$00A3 R2D2 # unnamed in Programmer's Reference Manual
$00A4 BSOUR1 # unnamed in Programmer's Reference Manual
$00A4 FIRT # unnamed in Programmer's Reference Manual
$00A5 CNTDN
$00A6 BUFPT
$00A7 INBIT
$00A8 BITCI
$00A9 RINONE
$00AA RIDATA
$00AB RIPRTY
$00AC SAL
$00AE EAL
$00B0 CMP0
$00B2 TAPE1
$00B4 BITTS
$00B5 NXTBIT
$00B6 RODATA
$00B7 FNLEN
$00B8 LA
$00B9 SA
$00BA FA
$00BB FNADR
$00BD ROPRTY
$00BE FSBLK
$00BF MYCH
$00C0 CAS1
$00C1 STAL
$00C3 MEMUSS
$00C5 LSTX
$00C6 NDX
$00C7 RVS
$00C8 INDX
$00C9 LSXP
$00CB SFDX
$00CC BLNSW
$00CD BLNCT
$00CE GDBLN
$00CF BLNON
$00D0 CRSW
$00D1 PNT
$00D3 PNTR
$00D4 QTSW
$00D5 LNMX
$00D6 TBLX
$00D7 DATA # unnamed in Programmer's Reference Manual
$00D8 INSRT
$00D9 LDTB1
$00F3 USER
$00F5 KEYTAB
$00F7 RIBUF
$00F9 ROBUF
$00FB FREKZP
$00FF BASZPT
$0100 BAD
$0200 BUF
$0259 LAT
$0263 FAT
$026D SAT
$0277 KEYD
$0281 MEMSTR
$0283 MEMSIZ
$0285 TIMOUT
$0286 COLOR
$0287 GDCOL
$0288 HIBASE
$0289 XMAX
$028A RPTFLG
$028B KOUNT
$028C DELAY
$028D SHFLAG
$028E LSTSHF
$028F KEYLOG
$0291 MODE
$0292 AUTODN
$0293 M51CTR
$0294 M51CDR
$0295 M51AJB
$0297 RSSTAT
$0298 BITNUM
$0299 BAUDOF
$029B RIDBE
$029C RIDBS
$029D RODBS
$029E RODBE
$029F IRQTMP
$02A1 ENABL
$02A2 CASTON # unnamed in Programmer's Reference Manual
$02A3 KIKA26 # unnamed in Programmer's Reference Manual
$02A4 STUPID # unnamed in Programmer's Reference Manual
$02A5 LINTMP # unnamed in Programmer's Reference Manual
$02A6 PALNTS # unnamed in Programmer's Reference Manual
$0300 IERROR
$0302 IMAIN
$0304 ICRNCH
$0306 IQPLOP
$0308 IGONE
$030A IEVAL
$030C SAREG
$030D SXREG
$030E SYREG
$030F SPREG
$0310 USRPOK
$0311 USRADD # from Programmer's Reference Manual; not in KERNAL/BASIC source!
$0314 CINV
$0316 CBINV
$0318 NMINV
$031A IOPEN
$031C ICLOSE
$031E ICHKIN
$0320 ICKOUT
$0322 ICLRCH
$0324 IBASIN
$0326 IBSOUT
$0328 ISTOP
$032A IGETIN
$032C ICLALL
$032E USRCMD
$0330 ILOAD
$0332 ISAVE
$033C TBUFFR
$0400 VICSCN

View file

@ -1,769 +0,0 @@
# Texteinschub Nr. 1: Der USR-Befehl
Hand aufs Herz: Haben Sie USR schon einmal benutzt? Ohne Zweifel gehört dieser Befehl zu den seltenen. Ich will ihn daher hier kurz erläutern. USR hat dieselbe Funktion wie SYS, nämlich aus einem Basic-Programm direkt in ein Maschinenprogramm zu springen und dort solange weiterzufahren, bis mit dem Befehl RTS (entspricht dem Basic-Befehl RETURN) in das Basic-Programm zurückgesprungen wird. Die Sprungadresse in das Maschinenprogramm steht bei SYS gleich hinter dem Befehl.
Bei USR muß die Adresse zuerst in die Speicherzellen 1 und 2 (aha!!) gePOKEt werden.
Beispiel - Sprung auf 56524 ($DCCC):
* mit SYS: `SYS 56524`
* mit USR: `POKE 1,204:P0KE 2,220:X=USR(Y)`
Kein Wunder, daß USR selten benutzt wird. Aber erstens ist er durch das POKEn der Low-/High-Byte-Darstellung aufgebläht und zweitens hat er auch wesentlich mehr Fähigkeiten als SYS.
Sein Argument, im obigen Beispiel also das »Y«, wird nämlich zuerst in den »Fließkomma-Akkumulator« FAC 1 (Floating Point Accumulator Nr. 1) gebracht, der sich in den Speicherzellen 97 bis 102 ($61 bis $66) befindet. Da wir ihn auf unserer Reise durch den Speicher noch treffen werden, brauche ich jetzt nicht näher darauf einzugehen. Wichtig ist lediglich, daß der Wert von »Y« dann vom angesprungenen Maschinenprogramm verarbeitet werden kann. Das Resultat kommt dann wieder in diesen FAC 1 und steht als Wert von X (siehe Beispiel oben) dem Basic- Programm zur Verfügung.
Mit USR kann man also Variable ins Maschinenprogramm zur Bearbeitung und zurück transferieren - und das ist der Unterschied zum SYS-Befehl. Ich möchte das an einem kleinen Beispiel demonstrieren. Statt allerdings ein Maschinenprogramm selbst zu schreiben, verwende ich beziehungsweise springe ich auf eine Routine des Betriebssystems, welches Werte des FAC 1 für mathematische Operationen verwendet.
Als mathematische Operation wähle ich das eingebaute Programm für INT, welches im VC 20 ab Speicherzelle 56524 ($DCCC) steht, im C 64 steht es ab 48332 ($BCCC). Dieses wollen wir verwenden:
In Zeile 10 definieren wir einen Wert für die Variable X, der in das Maschinenprogramm gebracht werden soll. Mit Zeile 20 bringen wir die Startadresse des Maschinenprogramms in die Speicherzellen 1 und 2.
Laut Kochrezept teilen wir die Adresse 56524 auf in ein Low- Byte = 204 und ein High-Byte = 220.
Der Befehl in Zeile 30 löst den ganzen USR-Vorgang aus, Zeile 40 gibt uns das Resultat.
10 Y=14.35
20 POKE l,204:P0KE 2,220 30 X=USR(Y)
40 PRINT X
Hinweis: Entsprechend der anderen Adresse 48332 lautet die Zeile 20 beim C 64:
20 POKE 785,204:POKE 786,188
Nach RUN erhalten wirdas Resultat 14, wie das Gesetz für INT es befiehlt. Natürlich hätten wir gleich PRINT INT (14.35) schreiben können, aber ich wollte ja nur demonstrieren. Der eigentliche Wert des USR-Befehls kommt hauptsächlich bei selbstgeschriebenen Maschinenprogrammen zum Zuge.
Sie können zur Übung im obigen Programm statt INT auch COS verwenden, indem Sie auf die Adresse 57935 ($E261) beziehungsweise beim C 64 auf 57938 ($E264) springen. Der Vergleich mit dem Basic-Befehl COS muß dasselbe Resultat ergeben.
Wer hat gemerkt, daß wir überhaupt nichts mit der Speicherzelle 0 gemacht haben, obwohl sie doch beim USR angeblich beteiligt ist?
Sie ist es wirklich, doch ohne unser Zutun. In diese Adresse wird beim Einschalten des Computers die Zahl 76 ($4C) geschrieben. Das ist der Code für den Maschinenbefehl »JMP«, der soviel bedeutet wie GOTO. Bei USR springt nämlich das Programm auf die Speicherzelle 0, findet dort den Sprungbefehl und in den nachfolgenden Zellen 1 und 2 die Sprungadresse - und führt den Sprung auch gleich aus.
# Texteinschub Nr. 2: Die Low-/High-Byte-Darstellung
Eine Speicherzelle der kleinen Commodore-Computer VC 20 und C 64 hat eine Länge von 8 Bit = 1 Byte. Mit diesen 8 Bit können Zahlen von 0 bis 255 ($00FF) dargestellt werden. Zur Darstellung von Zahlen über 255 verwenden wir die Low-/High- Byte-Methode.
Wir hängen einfach zwei Speicherzellen zusammen, mit deren 16 Bit wir Zahlen bis maximal 65535 ($FFFF) darstellen können. Die maximale Zahl 65535 ist übrigens auch die höchste Adresse des gesamten Speichers - was natürlich kein Zufall ist.
Ich will Ihnen jetzt zeigen, wie eine Dezimalzahl auf zwei 8-Bit- Speicherzellen verteilt wird, und umgekehrt, wie aus 2 Byte eine Dezimalzahl gebildet wird.
Schauen Sie sich das folgende Beispiel an:
DEZIMAL 47491
DUALZAHL 1011 | 1001 | 1000 | 0011
HEX $ B | 9 | 8 | 3
HIGH-BYTE 185 | -
LOW-BYTE - | 131
Wir gehen von der Dezimalzahl 47491 aus. Ihre duale Darstellung mit 16 Bit - 1011100110000011 - teilen wir einfach in der Mitte und erhalten damit zwei neue Dual-Zahlen mit je 8 Bit = 1 Byte. Das linke Byte nennen wir »High-Byte«, da es den höheren Teil derGesamtzahl darstellt. Das rechte Byte heißt entsprechend »Low-Byte«.
Jedes der beiden Bytes kann für sich allein in einer Speicherzelle untergebracht werden, in der natürlich dann der dezimale Wert des Bytes steht.
In der Tabelle habe ich zur Vollständigkeit noch die hexadezimalen Werte eingefügt, die sehr schön zeigen, daß der Vorteil dieserZahlendarstellung darin liegt, daß jede Einzelziffer der 4-Bit-Dualzahl entspricht, genau so wie jede Zweiergruppe dem Byte (sowohl in Dual-, als auch in Dezimaldarstellung) und die vierstellige Zahl der großen Dezimal- und Dualzahl entspricht.
Zur Umrechnung der Low-/High-Bytes empfehle Ich folgende Kochrezepte:
## Dezimal in Low-/High-Byte
47491:256 = 185 (High-Byte), Rest 131 (Low-Byte)
Der Rest fällt bei der Division per Hand automatisch an. Mit dem (Taschen-)Rechner erhält man den Rest durch:
185*256-47491 = -131
## Low-/High-Byte in Dezimal
High-Byte * 256 + Low Byte = Dezimal
185 * 256 + 131 = 47491
Wichtige Regel: Die Mikroprozessoren von VC 20 und C64 verlangen, daß immer das Low-Byte vor dem High-Byte kommen muß. Die Zahl wird sozusagen von rechts nach links gelesen (131/185).
# Texteinschub Nr. 3: Manipuliertes Basic
Wie Sie durch PRINT PEEK (1) selbst leicht feststellen, steht nach dem Einschalten des Computers im Register 1 die Zahl 55. In dualer Darstellung ist das 110111. Das entspricht dem in der ersten Zeile derTabelle 2 dargestellten »Normalzustand« der einzelnen Bits.
Vergleichen Sie es bitte mit der Auflistung am Anfang der Beschreibung der Speicherzelle 1. Die in Tabelle 2 dargestellten Bits sind also die rechten drei Bits der Zelle 1.
Lassen wir die Bits 3, 4 und 5 unverändert, ergeben die acht Kombinationen der Tabelle 2 die Zahlen 55 bis 48. Durch den Befehl POKE 1,54 können wir nun den Basic-Übersetzer aus- schalten und 8 KByte Speicher gewinnen. Nur nutzt uns das nicht viel, denn was tun - ohne Basic! Es gibt aber doch eine Anwendung. Zuvor will ich Ihnen aber noch beweisen, daß wir tatsächlich den Block A auf RAM umschalten. Der Trick besteht darin, den Basic-Übersetzer vom ROM in den darunter liegenden RAM umzuladen. Wenn er tatsächlich in RAM steht, müßten wir ihn durch POKEn verändern können zu einem Privat-Basic. Geben Sie direkt ein:
FOR J=40960 TO 49151: POKE J,PEEK(J): NEXT J
POKE J, PEEK (J) - das sieht dümmer aus als es ist. Die »Doppeldecker-Speicher« erlauben nämlich ein PEEKen nur aus dem ROM-Bereich. Ein hineinPOKEn dagegen geht nur in den RAM-Teil. Von dort aber kann er - wie gerade gesagt - nicht herausgelesen werden, es sei denn, wir schalten um!
Merken Sie was? Die Zeile oben liest also den Inhalt des Basic- ROMs und schreibt ihn in den RAM mit identischen Adressen. Die Ausführung der Zeile braucht einige Zeit. Wenn der Cursor wieder blinkt, schalten wir das RAM ein mit:
POKE 1,54
Wir merken natürlich noch keinen Unterschied, denn das RAM-Basic ist ja noch dasselbe.
Doch nun werden wir es verändern. In der Speicherzelle 41220 steht das »P« für den Befehl PRINT mit dem ASCII-Codewert 80. Dieses P ersetzen wir durch ein »G« (ASCII-Code = 71).
POKE41220,71
Versuchen Sie bitte, mit dem (nicht durch »?« abgekürzten) PRINT-Befehl ein Zeichen auf den Bildschirm zu drucken. Es wird Ihnen nicht gelingen, denn der Befehl heißt jetzt:
GRINT "A"
was beweist, daß das Basic jetzt im RAM steht. Das Umdefinieren von Befehlen Ist natürlich wenig sinnvoll. Aber wer die Maschinenprogramme des Basic kennt, kann sie auf diese Weise ändern, erweitern, einschränken, solange er sich auf in sich geschlossene Teile beschränkt.
Eine inzwischen oft zitierte Anwendung stammt von Jim Butterfield, den es begreiflicherweise stört, daß der Befehl ASC, welcher den ASCII-Code eines Strings erzeugt, bei einem Null- String das Programm mit ILLEGAL QUANTITY ERROR beendet. Versuchen Sie es:
`PRINT ASC ("A")` ergibt die Zahl 65.
`PRINT ASC (" ")` hat die obige Fehlermeldung zur Folge.
Wenn Basic im RAM steht, können wir das ändern:
POKE 46991,5
Die Wiederholung des Befehls PRINT ASC (””) ergibt jetzt 0 - und, was das Wichtige ist, das Programm läuft weiter.
Durch zusätzliches Umladen des Speicherblocks E und anschließendes Umschalten mit POKE 1,53 ist auch das Betriebssystem veränderbar - ein weites Feld für fortgeschrittene Programmierer in Maschinensprache.
Die wohl wichtigste Anwendung der Umschaltmethode wird den Maschinen-Programmierern geboten, die dadurch eine kostenlose Speichererweiterung von 16 KByte erhalten. Bei gleichzeitiger Verwendung von Basic und Maschinenprogramm kann die Umschaltung besonders vorteilhaft eingesetzt werden. Das Umschaltprogramm muß dann aber ebenfalls in Maschinensprache geschrieben sein und darf nicht im Umschaltbereich liegen.
Das Umschalten von den Ein-/Ausgabe-Registern des Blocks D mit POKE 1,51 erlaubt, die Bitmuster der fest programmierten Zeichen aus dem Zeichen-ROM auszulesen, in einen freien RAM-Bereich zu bringen und dort dann nach eigenen Vorstellungen zu verändern.
# Texteinschub Nr. 4: Zeiger, Vektoren und Flaggen
Zeiger und Vektoren sind Zahlenwerte, die jeweils in zwei benachbarten Speicherzellen stehen und in der Low-/High-Byte-Darstellung eine Adresse bilden.
Wir sprechen von einem »Zeiger«, wenn diese Adresse den Beginn von gespeicherten Daten angibt.
Ein »Vektor« zeigt ebenfalls auf eine Anfangsadresse, allerdings auf die eines Maschinenprogramms. Diese Unterscheidung wird leider nicht immer ganz eindeutig angewendet.
Eine »Flagge« besteht aus einem Zahlenwert in einer Speicherzelle, die von einem Programm dort abgelegt wird, um sich das Resultat einer Operation zu merken, beziehungsweise um es für eine spätere Verwendung bereitzuhalten.
# Texteinschub Nr. 5: Die Zahlendarstellung bei den Commodore-Computern
## Gleitkomma-Zahlen
Für diejenigen Leser, die das Thema der Zahlendarstellung in den Commodore-Handbüchern großzügig übersprungen haben, stelle ich es hier noch einmal vor.
Sie kennen die gängigen vier Zahlentypen:
* ganze Zahlen: 15, 21, 244
* Brüche; 2/3, 26/8, 15/14
* negative Zahlen: -15, -255
* positive Zahlen: 10, 5, 123
Ganze Zahlen bereiten uns und dem Computer keine Probleme.
Bei Brüchen sieht es schon anders aus. Erinnern Sie sich an
die Bruchrechnungsstunden in der Schule? Wieviel ist 51/52 + 3/4!!!
Ohne lange zu überlegen, rechnen wir natürlich um, 51/52 = 0,9807692 und 3/4 = 0,75; addiert ist das Resultat 1,7307692 - und schon sind Sie mitten in den Gleitkomma-Zahlen.
Bei obigem Beispiel gleitet allerdings noch nichts. Bei sehr großen oder aber auch sehr kleinen Bruch-Zahlen reicht uns - und einem Computer - nicht der Platz, um sie darzustellen. Die Zahl 0,000000000000000123 sprengt jeden normalen Rahmen.
Daher schreiben wir sie anders. Wir lassen das Komma nach rechts gleiten, bis es die erste Ziffer, die von 0 verschieden ist, findet und für jede Null, die es passiert, multiplizieren wir die Zahl mit 10.
Die Zahl oben sieht dann so aus: 0,123 x 10 hoch 15 (eine 1 mit 15 Nullen).
Die Grundzahl vorn heißt »Mantisse«, die 10 mit Hochzahl heißt »Exponent«.
Alle Commodore-Computer verarbeiten intern alle Zahlen in dieser Darstellung, also als Gleitkommazahl.
# Texteinschub Nr. 6: Was ist ein Stapelspeicher (Stack)?
Der normale Arbeitsspeicher des Computers, auf englisch »Random Access Memory« oder kurz RAM genannt, hat für jede Speicherzelle eine eigene Adresse, die beim Schreiben in den Speicher oder beim Lesen aus dem Speicher angegeben werden muß.
Als Analogie möge eine Aktenablage dienen, bei der jeder Akt (Brief, Papier, Zeichnung) in einen Ordner kommt, mit Nummer versehen.
Um einen Akt herauszuholen, muß man die Nummer (Adresse) kennen, unter der er abgelegt ist.
Ein Stapelspeicher, auf englisch »Stack« genannt, funktioniert wie eine Aktenablage, bel der jeder Akt einfach oben auf einen Stapel gelegt wird, daher der Name. Diese Ablage erfolgt ohne Kennzeichnung oder Nummer, einfach immer der Reihe nach.
Einen Akt kann man aus einem Stapelspeicher nicht beliebig herausholen, da immer nur der oberste Akt zugänglich ist.
Die Methode der Stapelspeicher bietet sich überall dort an, wo es auf die Reihenfolge der gespeicherten Daten ankommt. Basic merkt sich zum Beispiel der Reihe nach die Adressen, von denen aus mit GOSUB ein Unterprogramm angesprungen wird. Wenn mehrere GOSUBs hintereinander eingesetzt werden, liegt auf dem Stapel Immer die letzte Absprungadresse bereit zum Rücksprung.
Ein Stapelspeicher hat demnach nur eine einzige Adresse, die sowohl zum Abspeichern als auch zum Auslesen dieselbe Ist.
Voraussetzung eines Stapelspeichers ist natürlich eine Routine, welche alle gespeicherten Daten im Stapelspeicher um einen Platz weiterschiebt, wenn eine neue Information »oben auf den Stapel gelegt wird«.
Das Basic der Commodore-Computer verwendet mehrere dieser Stapelspeicher.
Die Programmiersprache Forth ist völlig auf dem Prinzip des Stapelspeichers aufgebaut.
# Texteinschub Nr. 7: Der sichtbare Basic-Speicher
Wenn wir den Variablen A die Adresse des Speicherbeginns der Basic-Programme zuordnen und dann mit einer FOR..NEXT- Schleife den Inhalt dieser und der nächsten 100 Speicherplätze ausdrucken, sehen wir in dezimaler Darstellung die ersten 101 Zahlenwerte, mit denen der Computer ein Basic-Programm speichert.
Ein Verbiegen des Zeigers in Speicherzelle 43/44 kann auf diese Weise in seiner Wirkung sichtbar gemacht werden.
Als Demo-Programm wähle ich zwei Zeilen, welche die Zahlen 1 bis 9 und die Buchstaben A bis I ausdrucken.
10 PRINT "123456789"
20 PRINT "ABCDEFGHI"
100 A=2049 : REM*C 64
4097 : REM*VC 20 ohne Erweiterung
1025 : REM*VC 20 mit 3 KByte
4609 : REM*VC 20 mit 8 KByte oder mehr
110 PRINT CHR$(l47)
Zeile 100 definiert den Speicheranfang. Zeile 110 löscht den Bildschirm.
120 FOR J=A T0 A+100
130 PRINT PEEK (J);
140 NEXT J
Die Befehle in den Zeilen 120 bis 140 drucken den Inhalt der ersten 101 Zellen dieses Basic-Programms aus. SAVEn Sie bitte dieses kleine Programm, denn wir brauchen es noch einmal. Dann geht es los mit RUN. In Bild 3 ist der Bildschirm-Ausdruck des VC 20 mit 8 KByte dargestellt, der des C 64 zeigt praktisch dieselbe Information.
Überspringen Sie bitte zunächst die ersten beiden Zahlen. Die dritte und vierte Zahl ist 10 und 0. Das ist (als Low- und High- Byte) die Nummer der ersten Zeile des Basic-Programms. Dann folgt 153, das ist der interne Codewert für PRINT. Diese Codes für alle Basic-Befehlswörter heißen »TOKEN«, sie sind im Texteinschub Nr. 32 angegeben.
Die nächste Zahl auf dem Bildschirm ist die 34, sie ist der ASCII*Code für den Gänsefuß. Danach folgen in aufsteigender Reihenfolge die ASCII-Codes der Ziffern 1 (48) bis 9 (57). Danach sehen Sie wieder den Gänsefuß (34). Schließlich kommt eine Null als Abstandszeichen zur nächsten Basic-Zeile.
Machen Sie bitte folgendes Experiment: Ausgehend von der Adresse der ersten auf dem Bildschirm ausgedruckten Speicherzellen - zum Beispiel 4609 beim VC 20 mit 8 KByte - zählen Sie die Zellen weiter bis zur Abgrenzungs-Null. In meinem Beispiel steht die Null in Zeile 4625. Das heißt, daß die nächste Basic-Zeile in 4626 anfängt. Und das ist genau die Zahl, die in den ersten beiden Zellen steht, die wir vorhin übersprungen haben; in meinem Beispiel steht da 18 18. Machen wir die Probe: 18 + 256 * 18 = 4626.
Jede Basic-Zeile im Speicher beginnt also mit der Adresse der nächsten Zeile (sie heißt Koppeladresse) und endet mit einer Null.
Ab 4626 folgt dann die nächste Koppeladresse, danach mit 20 0 die Zeilennummer, und Sie erkennen jetzt sicher die Codes der Angaben von Zeile 20 wieder.
So, jetzt wollen wir den Zeiger in 43 und 44 verbiegen. Ich schlage vor, daß wir den Basic-Beginn um zehn Adressen höher schieben. Sie müssen jetzt die in Zeile 100 oben verwendete Zahl für A in die High-/Low-Byte-Darstellung umrechnen und das Low-Byte um 10 erhöhen. Dieses Zahlenpaar POKEn wir in die Zellen 43 und 44. Vorher müssen wir aber noch in Zelle (A + 10) -1 eine Abstands-Null POKEn.
Wir geben diese Befehlssequenz im Direktmodus ein:
* für den C 64:
POKE 2058,0:POKE 43,11:POKE 44,8:NEW
* für den VC 20 (GV):
POKE 5006,0:P0KE 43,143:POKE 44,19:NEW
* für den VC 20 (= 3 KByte):
POKE 1034,0:P0KE 43,11:POKE 44,4:NEW
* für den VC 20(> 8KByte)
POKE 4618,0:P0KE 43,H:POKE 44,18: NEW
Jetzt ist der Anfang des Basic-Speichers versetzt. Um das zu prüfen, geben wir das kleine Programm von oben nochmal ein und lassen es mit RUN laufen. Der resultierende Bildschirmausdruck ist in Bild 4 dargestellt.
Die ersten Zahlen sind genauso wie vorher. Es sind auch die Reste von vorher, da wir den Speicher nicht auf Null gesetzt haben. Aber zählen Sie bitte die ersten zehn Adressen hoch. Da finden Sie unser Programm von vorhin genau wieder, beginnend mit der Abstands-Null. Aber Vorsicht, lassen Sie sich nicht verwirren, denn die Koppeladressen sind natürlich jetzt auch jeweils um 10 höher. Aber hinter den Koppeladressen finden wir wieder unser Programm, in gleicher Weise dargestellt wie beim ersten Mal. Da der Zeiger in 43 und 44 von allen entsprechenden Routinen des Übersetzers und des Betriebssystems abgefragt wird, läuft ein verschobenes Programm fehlerfrei, solange natürlich der Zeiger nicht wieder verändert wird.
# Texteinschub Nr. 8: Normale Variable in Basic
Alle Daten, die in einem Basic-Programm nicht in Form von READ-DATA-Anweisungen vorkommen, werden als »Variable« unmittelbar nach dem Basic-Programm abgespeichert. Wir unterscheiden dabei zwei Typen:
* normale Variable
* Felder (Arrays)
Wir betrachten hier nur die »normalen« Variablen.
Sie erscheinen in dem Speicherbereich, dessen Beginn durch den Zeiger in den Zellen 45 und 46 und dessen Ende durch den Zeiger in 47 und 48 angegeben wird, in derselben Reihenfolge, in welcher sie während des Ablaufes des Basic-Programms auf- treten. Wenn Basic dann auf eine der bereits definierten (und abgespeicherten) Variablen zurückgreifen soll, muß es den gesamten Variablenbereich von Anfang an absuchen, bis es den Namen der gesuchten Variablen gefunden hat. Wenn diese Variable ganz am Ende des Bereiches steht, kann dieser Suchprozeß recht lange dauern.
## Regel 1:
Häufig vorkommende Variable sollen am Anfang des Variablenbereichs stehen. Das wird dadurch erreicht, daß sie als erste Variable in einem Programm »definiert« werden. Falls sie erst später im Programm gebraucht werden (aber dann häufig), werden sie trotzdem am Anfang des Programms angegeben, notfalls mit einem beliebigen Wert, der später dann keine Rolle mehr spielt und ersetzt wird. Man nennt das einen »Dummy«-Wert.
Die Felder-Variablen stehen direkt nach den »normalen« Variablen. Auch hier kann der gewiefte Programmierer Gutes tun. Wenn nämlich nach einer Definition eines Feldes später im Programm noch normale Variable dazukommen, ist natürlich zuerst kein Platz für sie da. Das Betriebssystem des Computers muß erst alle Felder-Variablen weiterschieben, bevor die Neuankömmlinge in dem dadurch erweiterten Variablenbereich gespeichert werden können. Auch das kostet unnötig viel Zeit.
## Regel 2:
Alle normalen Variablen sollen als erste in einem Programm definiert werden. Wer also drauflos programmiert, sollte zumindest am Ende das Programm so umbauen, daß diese simple Regel erfüllt wird.
# Texteinschub Nr. 9: Darstellung der normalen Variablen im Speicher
Die normalen Variablen kommen in drei Arten vor:
* ganzzahlige Variablen
* Gleitkomma-Variablen
* String-Variablen (Zeichenketten)
Der Unterschied zwischen den drei Typen ist in den Commodore-Handbüchern gut erklärt, und ich verzichte hier auf eine Wiederholung. Ich will vielmehr direkt zeigen, wie die Variablen im Speicher abgelegt sind.
Wir können den Speicher direkt sichtbar machen.
Einmal geht das in Maschinencode mittels eines Monitors beziehungsweise Disassemblers.
Zum anderen aber geht das auch in Basic und zwar mit folgendem Trick, den ich Th. und M.L. Beyer (MC 10/1983) abgeschaut habe.
Wir verlegen den Beginn des Basic-Variablenspeichers einfach auf den Beginn des Bildschirmspeichers. Auf diese Weise können wir zwar kein vernünftiges Programm laufen lassen, aber alle direkt eingegebenen Variablen-Definitionen werden sofort sichtbar, weil sie eben im Bildschirmspeicher stehen.
Wir erreichen die Verlegung des Speichers durch »Verbiegen« der Zeiger in den Zellen 45 und 46 und 47 und 48. Die Bedeutung dieser Zeiger ist ja im Kurs erklärt.
Die Speicherverlegung beziehungsweise die Methode dazu ist für den C 64 anders als für den VC 20.
## VC 20:
Alle Angaben gelten für den VC 20 ohne Speichererweiterung, also ziehen Sie bitte alle Speichermodule heraus. Der Speicherbereich für Programme und deren Variablen beginnt jetzt ab Adresse 4096, das ist Block 1 im Bild 5. Der Bildschirmspeicher beginnt ab 7680. Wir verlegen jetzt den Bildschirmspeicher in den Block 1, so daß er ebenfalls ab Adresse 4096 beginnt. Danach müssen wir noch eine Farbe - am besten Schwarz - in den Farbspeicher POKEn, der in dieser neuen Konfiguration von 37888 bis 38399 liegt. Warum das so Ist, erklärt Christoph Sauer in seinem Aufsatz »Der gläserne VC 20«, Teil 4, im 64'er 1/85, Seite 131.
Das High-Byte der Adresse, in welcher der Bildschirmspeicher beginnt, steht in der Speicherzelle 648. Sie können das jederzeit mit PRINT PEEK(648) nachprüfen. Umgekehrt können wir eine Zahl hineinPOKEn, wodurch der Bildschirmspeicher verschoben wird. In unserem Fall erhalten wir das High-Byte für 4096 durch 4096/256 = 16.
Machen Sie jetzt bitte folgende Schritte:
1) direkt eingeben: POKE 648,l6(RETURN),
2) RUN/STOP und RESTORE drücken, bis der Cursor wieder da ist,
3) direkt eingeben:
FOR J = 37888 TO 38399: POKE J,0: NEXT J (RETURN),
4) mit der DELETE-Taste (nicht mit CLR !) den ganzen Text des Bildschirms löschen,
5) mit dem Cursor etwa acht Zeilen nach unten gehen,
6) mit der Commodore- und SHIFT-Taste zusammen auf die Groß- und Kleinschrift umstellen.
Schritt 1 und 3 habe ich oben schon erklärt. Schritt 4 ist nicht absolut notwendig, aber ein leerer Bildschirm ist für uns besser. Die CLR-Taste würde Schritt 3 zunichte machen. Schritt 5 erlaubt uns, weiter unter auf dem Bildschirm Variablen einzugeben, ohne den oberen Teil vollzuschreiben. Schritt 6 schließlich erleichtert das Erkennen der Variablen-Darstelllung.
## C 64:
Beim C 64 beginnt der Bildschirmspeicher ab 1024. In Low-/ High-Byte-Darstellung ist das 0/4 (1024/256=4, Rest 0). Geben Sie bitte direkt ein:
POKE 46,4 :POKE 48,4
Das Low-Byte in 45 und 47 können wir weglassen, da es ja in beiden Fällen 0 ist. Diese Methode gilt für alle neueren C 64, bei denen direkt ein Zeichen in den Bildschirmspeicher gePOKEt werden kann, ohne sich um die Zeichenfarbe kümmern zu müssen. Es gibt noch einige C 64 mit älteren Betriebssystemen, bei denen die Zeichenfarbe auch angegeben werden muß. Hier gilt:
FOR J = 0 TO 1000:POKE 55296*3,14:NEXT J
## Alles weitere gilt für beide Computertypen gleich
Wenn Sie jetzt den Bildschirm löschen, den Cursor ungefähr in die Mitte des Bildschirms fahren und wiederum direkt eingeben:
`VARIABLE = 3` und die RETURN-Taste drücken, dann erscheinen oben sieben Zeichen. Bitte schalten Sie mit der SHIFT- und Commodore-Taste auf den zweiten Zeichensatz um, jetzt können wir besser lesen.
Aus anderen Kursen wissen Sie wahrscheinlich, daß Variable mit 7 Byte dargestellt werden. In der Tat sehen wir oben die ersten beiden Buchstaben des Variablennamens VA und fünf weitere Zeichen. Wir wollen aber systematisch vorgehen und uns zuerst die ganzzahligen Variablen anschauen.
### Ganzzahl-Variable
Wiederholen Sie bitte den Vorgang (Löschen, Cursor auf Mitte, 2. Zeichensatz). Jetzt geben Sie eine Ganzzahl-Variable ein:
VA%=3
Nach RETURN sehen wir als erstes Zeichen ein reverses V, dann ein reverses A, den Klammeraffen @, das kleine c und nochmals drei @. Die beiden ersten Zeichen des Variablennamens (besteht er nur aus einem Zeichen, wird mit einer 0 aufgefüllt) werden mit ihrem ASCII-Code eingegeben, zu dem bei Ganzzahl-Variablen zur Kennzeichnung einer solchen die Zahl 128 addiert wird.
Schauen Sie in einer ASCII-Tabelle (64er, Ausgabe 7/84) nach: Das V hat 86, um 128 erhöht gibt das 214. Wir arbeiten hier aber im Bildschirmspeicher, der die Zahlen auf seine eigene Weise interpretiert, nämlich als Bildschirmcode. Der Bildschirmcode-Tabelle entnehmen wir das Zeichen für den Wert 214 und das ist das invertierte V. Für das A können Sie das selbst nachvollziehen.
Also: In unserer Darstellung erkennen wir Ganzzahl-Variable an den invertierten Zeichen des Namens.
Das 3. und 4. Zeichen sind das High- und Low-Byte des Variablenwertes und zwar im Bildschirmcode. In unserem Beispiel der 3 ist das High-Byte 0, also der Klammeraffe @, das Low-Byte 3, also das c. Die restlichen drei Byte sind mit 0 aufgefüllt.
Wenn Sie mit dem Cursor auf die 3 fahren, es mit einer 5 überschreiben und RETURN drücken, verwandelt sich das c in ein e. Beim Überschreiben mit 255 erscheint als 4. Byte das Zeichen für den Bildschirmcode 255. Beim Überschreiben mit 257 ändern sich beide Bytes. Das 3. (High-)Byte springt auf a (=1), das 4. (Low-)Byte ebenfalls auf a. Nun, 1 * 256+1 = 257.
Während, wie bewiesen, das Low-Byte von 0 bis 255 gehen kann, sind beim High-Byte nur Werte zwischen 0 und 127 zugelassen. Die Werte ab 128 signalisieren negative Zahlen. Probieren Sie es aus:
127 * 256+255=32767
Ein Überschreiben mit 32767 resultiert in einer Darstellung der Zeichen für den Bildschirmcode 127 und 255. Der Wert 32768 wird nicht mehr akzeptiert. Dasselbe machen wir noch schnell für negative Zahlen.
Überschreiben Sie bitte die letzte Zahl mit 0. Wie zu erwarten war, sind Byte 4 und 5 jetzt 0 (Klammeraffe).
Wenn Sie jetzt mit -1 überschreiben, erscheint für beide Bytes das Zeichen mit dem Bildschirmcode 255. Bei -2 sehen wir die Zeichen mit den Code-Werten 255 und 254.
Sie sehen also, daß die negativen Zahlen für ganzzahlige Variable sozusagen vom Ende der Tabelle her dargestellt werden, wobei die höchste negative Zahl wieder 32767 ist. Diese »Rückwärtszählung« ist bedingt durch die Methode der negativen Zahlendarstellung im Zweierkomplement. Der Platz und die Gelegenheit verbieten es mir, näher darauf einzugehen. Aber ich glaube, unser kleines Experiment hat Ihnen zumindest von der Darstellung her den Zusammenhang gezeigt. In Bild 6 ist diese Darstellung der ganzzahligen Variablen im Speicher wiedergegeben.
| 1 | 2 | 3 | 4 | 5 6 7 |
|---------|---------|--------|--------|---------|
| Erstes | Zweites | High- | Low- | |
|-------------------|-----------------|---------|
| Zeichen des | Byte des Varia- | 0 0 0 |
| Variablen-Namens | blenwertes | |
| (ASCII-Wert + 128)| | |
Bild 6. So stehen ganzzahlige Variable im Speicher
### Gleitkomma-Variable
Ich hoffe, Sie verzeihen mir, wenn ich diese Darstellung an dieser Stelle überspringe. Sie ist nämlich nicht ganz leicht zu verstehen, und ich möchte sie lieber dann im Detail erklären, wenn wir zur Diskussion der Speicherzellen 97 bis 101, nämlich des Gleitkomma-Akkumulators kommen. Da geht es in einem Stück. Als Vorgeschmack gebe ich jetzt in Bild 7 nur die Zusammenfassung an.
| 1 | 2 | 3 | 4 5 6 7 |
|---------|---------|----------|--------------------------|
| Erstes | Zweites | | |
|-------------------| | Mantisse mit Genauig- |
| Zeichen des | Exponent | keit von 32 Dualstellen, |
| Variablen-Namens | + 129 | 1. Bit des 1. Bytes ist |
| (ASCII-Wert) | | das Vorzeichen |
Bild 7. Gleitkomma-Variable
### String-Variable
Zuerst ist es erforderlich, den Computer in den Anfangszustand zurückzusetzen. Wenn Sie einen RESET-Schalter haben, bitte diesen drücken, sonst aber aus- und einschalten. Wir geben nach Löschen des Bildschirms in der unteren Hälfte direkt ein:
ZX$="A" <RETURN>
Wir erhalten ein Z, ein invertiertes X, ein kleines a, ein grafisches Zeichen, eine Leerstelle und zwei Klammeraffen.
Fahren Sie bitte jetzt mit dem Cursor auf das A und ändern den String um in BC. Nach RETURN verwandelt sich das a in das b, das 4. Zeichen ändert sich ebenfalls. Die ersten beiden Zeichen sind also wieder der Name der Variable.
Um zu kennzeichnen, daß es eine String-Variable ist, erscheint das 2. Zeichen des Namens invertiert. Wie oben entsteht es dadurch, daß zum ASCII-Code die Zahl 128 addiert wird. Diese Zahl wird aber wieder als Bildschirmcode interpretiert und entsprechend angezeigt (vergleichen Sie es mit den ASCII- und Bildschirmcode-Tabellen).
Das 3. Zeichen gibt die Länge des Strings an, also im ersten Fall mit a (=1 im Bildschirmcode), im 2. Fall mit b (=2). Zeichen 4 und 5 geben als Low- und High-Byte die Adresse an, bei der begonnen wird, den Text des Strings zu speichern. Das können wir nachprüfen.
Wir hatten die beiden Fälle:
1. ZX$ = ”A": 4. Zeichen: (Bildschirmcode: 255) und 5. Zeichen: (Bildschirmcode 156) ergibt als Adresse 40959.
2. ZX$ = ”BC": 4. Zeichen: (Bildschirmcode 253) und 5. Zeichen: (Bildschirmcode 156) ergibt als Adresse 40957.
Der Text der Zeichenketten wird am Ende des Arbeitsspeichers (40959 beim C 64, 7679 beim VC 20 ohne Erweiterung) abgelegt und zwar von hinten nach vorn.
Mit `PRINT PEEK(40957);PEEK(40958);PEEK(40959)` drucken wir den Inhalt dieser Speicherzellen aus und erhalten: 66 67 65. Im ASCII-Code ist das: B C A. Die Zusammenfassung für String-Variable (Bild 8) sieht so aus:
| 1 | 2 | 3 | 4 | 5 | 6 7 |
|---------|---------|---------|---------|---------|------|
| Erstes | Zweites | | High- | Low- | 0 0 |
|-------------------| Anzahl |---------|---------| |
| Zeichen des | der | Byte der Adresse, | |
| Variablen-Namens | Zeichen | ab welcher der | |
| ASCII- | ASCII- | des | Text des Strings | |
| Wert | Wert+128| Strings | abgespeichert ist | |
Bild 8. String-Variable
## Texteinschub Nr. 10: Felder in Basic
Zur Wiederholung: Es gibt zwei Arten von Variablen, normale Variable und Felder. Jede der beiden Arten ihrerseits kann aus Gleitkomma-Zahlen, ganzen Zahlen oder Zeichenketten bestehen.
Eine normale Variable kann immer nur einen Wert haben, ein Feld enthält gleichzeitig viele Werte, alle unter demselben Variablen-Namen.
Wir können uns ein Feld mit dem Namen KARLSTRASSE als eine Liste vorstellen, in der jedes Element zwar auch den Namen Karlstraße hat, sich aber von den anderen Elementen durch eine eigene Hausnummer unterscheidet. Jede Variable in einer Hausnummer hat einen bestimmten Wert.
Während eine normale Variable einfach mit A=3 einen Wert zugewiesen bekommt, muß ein Feld erst definiert werden, nämlich wie viele Elemente es enthält. Wir machen das mit dem Befehl
DIM KARLSTRASSE (12)
Dieses Feld hat 13 Elemente (von 0 bis 12). Jedem Element kann nun ein Variablenwert zugewiesen werden durch
KARLSTRASSE (0)=25
KARLSTRASSE (1)=56
Das Feld KARLSTRASSE hat in der Klammer nur eine Zahl, man sagt, es hat nur eine Dimension.
Ein zweidimensionales Feld entspricht einem Schachbrett, mit Zahlen in der einen und Buchstaben in der anderen Dimension. Wir definieren es mit:
DIM AX (7,7)
AX ist der Name, jede Dimension hat acht Elemente, insgesamt kann das Feld 64 Werte enthalten.
Ein dreidimensionales Feld entspricht einem Quader, oder bei gleicher Elementenzahl pro Dimension (Seite) einem Würfel. Dieses wird dimensioniert mit
DIM BY (125,6,2)
Die Anzahl der Dimensionen wird nur begrenzt durch den verfügbaren Speicherplatz. Wieviel Bytes pro Feld gebraucht wer- den, entnehmen Sie bitte der Erklärung bei der Darstellung der Feld-Variablen (Texteinschub Nr. 11).
Ein Feld, das wie bisher gezeigt dimensioniert wird, enthält Gleitkomma-Zahlen.
Ein Feld mit ganzen Zahlen wird durch das Zeichen % nach dem Namen gekennzeichnet, also:
DIM CZ%(.,.,.)
Ein Feld mit Zeichenketten dagegen hat nach dem Namen das übliche Zeichen $, also:
DIM DT$(..,..,..)
»Wozu brauche ich Felder, wenn ich auch normale Variable verwenden kann?«, werden Sie vielleicht noch fragen.
Felder haben den großen Vorteil, daß immer dann, wenn viele Variable in einem Programm vorkommen, die alle einen gewissen Zusammenhang haben, viel Speicherplatz gespart werden kann.
Eine normale Variable braucht 7 Byte, eine Feld-Variable nur 5 oder bei ganzen Zahlen sogar nur 2 Byte. Zugegeben, vorher steht noch ein längerer Kopf, aber halt nur einmal. Und das zahlt sich bei vielen Variablen sehr rasch aus.
Und schließlich muß ich noch darauf hinweisen, daß die »Hausnummern« oder Indizes der Elemente innerhalb eines Programms durch mathematische Operationen verändert und manipuliert werden können. Aber das ist natürlich höhere Programmierkunst und geht über diese kurze Einführung hinaus.
# Texteinschub Nr. 11: Darstellung der Felder-(Array-)Variablen im Speicher
Die Felder-Variablen kommen in drei Arten vor:
* als ganze Zahlen,
* als Gleitkomma-Zahlen,
* als Zeichenketten.
Sie sind in dem Texteinschub Nr. 10 »Felder in Basic« kurz beschrieben.
Wir wollen sie uns hier mit den Methoden anschauen, welche ich für den C 64 und für den VC 20 in dem Texteinschub Nr. 9 »Darstellung der normalen Variablen im Speicher« beschrieben habe.
Beim C 64 ist allerdings ein Zusatz dabei. Sie müssen, am besten gleich am Anfang, noch eingeben:
POKE 44,4:NEW
Ein eventuell auftretender SYNTAX ERROR soll uns nicht weiter stören.
Wenn Sie also das jeweilige Kochrezept ausgeführt und damit den Bildschirm- und den Variablenspeicher auf dieselbe Adresse gelegt haben, können wir anfangen.
## Gleitkomma-Feld
Geben Sie direkt ein:
DIM AB(1,2,3)
Wir dimensionieren also ein Feld mit dem Namen AB, es hat drei Dimensionen, die erste Dimension hat zwei (0,1) Werte, die zweite hat drei und die dritte hat vier Werte. Sobald Sie die RETURN-Taste drücken, erscheint das Feld auf dem Bildschirm. Wir sehen folgende Zeichen: A, B, invertiertesC , @ c @ d @ c @ b plus 120 Klammeraffen @.
Die ersten zwei Stellen sind der Name des Feldes in der Darstellung für Gleitkomma-Variable, wie in der letzten Folge beschrieben wurde. Die dritte und vierte Stelle geben im Bildschirmcode als Low- und High-Byte die Länge des Feldes an (das inverse C = 131, das © = 0, bitte nachzählen). Die fünfte Stelle zeigt die Anzahl der Dimensionen (c = 3) an. Ab der sechsten Stelle stehen die Anzahl der Elemente der Dimension (diesmal als High- und Low-Byte) und zwar beginnend mit der letzten Dimension. In unserem Falle ist das also in Stelle 6 und 7 ein @ und d (0 - 3 =4=d), Stelle 8 und 9 sind dasselbe für die zweite Dimension und schließlich Stelle 10 und 11 für die erste Dimension (0 - 1=2=b). Danach folgen entsprechend der Anzahl der dimensionierten Elemente (2*3*4=24) 6 Byte pro Element (24*5=120), die vorerst auf 0 = @ stehen, die aber mit den Werten der Elemente aufgefüllt werden.
Dieses Auffüllen wollen wir nachvollziehen. Geben Sie bitte direkt ein:
AB(0,0,0)=5
Wir weisen damit dem allerersten Element des Feldes den Wert 5 zu.
In der oberen Darstellung des Feldes AB ändern sich dadurch Byte 12 und 13. Das neu erschienene inverse C und die Leerstelle mit den drei nachfolgenden @ ist die Gleitkomma- Darstellung (Mantisse und Exponent) der Zahl 5. Auf diese Darstellung werde ich später im Verlauf dieses Kurses bei der Besprechung der Speicherzelle 97 noch genauer eingehen.
Wenn wir jetzt (durch Überschreiben der vorigen Anweisung) zusätzlich noch eingeben:
AB(1,0,0)=6
erreichen wir eine entsprechende Änderung der Bytes 17 und 18, also des zweiten Elements des Feldes.
In Bild 9 sind die Stellen eines Gleitkomma-Feldes grafisch dargestellt.
1 2 3 4 5 6 7 / a b c d e
|---------|---------|------|------|--------|------|------|-\ |------|------|---------|---|---|---|---|-->
| Erstes | Zweites | Low | High | | High | Low | / | High | Low | |
| | Byte | Anzahl | Byte | \ | Byte |Exponent Mantisse |
| Zeichen des |-------------| der |-------------| / |-------------| +125 |
| Feld-Namens | Länge des | Dimen- | Anzahl der | \ | Anzahl der | des 1. Elements| des 2. Elements
| | Feldes | sionen | Elemente | / | Elemente | |
| | | | der letzten | \ | der ersten | |
| | | | Dimension | / | Dimension | |
|---------|---------|------|------|--------|-------------|-\-|-------------|---------|---|---|---|---|-->
|<----------------------- KOPF ----------------------->| /
Bild 9. Gleitkomma-Feld
## Ganzzahliges Feld
Im Vergleich zu dem Gleitkomma-Feld dimensionieren wir als nächstes ein ganzzahliges Feld:
DIM AB%(l,2,3)
Jetzt erscheint auf dem Bildschirm gleich anschließend an das erste Feld eine neue Darstellung: invertiertes A, invertiertes B, ;, @, c@, d, @, c, @b plus 48 Klammeraffen @.
Die ersten 11 Byte haben dieselbe Bedeutung wie beim Gleitkomma-Feld, aber nur deswegen, weil wir dieselben drei Dimensionen mit identischer Elementenzahl dimensioniert haben. Bei mehr Dimensionen wäre dieser Kopf natürlich länger. Die inverse Darstellung des Feldnamens signalisiert ein ganzzahliges Feld. Die dritte Stelle zeigt das »;« - im Bildschirmcode ist das die 59. In der Tat ist das Feld nur 59 Byte lang, also wesentlich weniger als das Gleitkomma-Feld. Die 2 * 3 * 4=24 Elemente benötigen in der Ganzzahl-Darstellung nur je 2 Byte (24*2=48+11=59). Womit bewiesen ist, daß eine Ganzzahl- Darstellung mit dem Zeichen % erheblich Speicherplatz spart - allerdings nur bei Feldern!
Jetzt wollen wir noch den Inhalt des Feldes füllen, so wie vorher mit:
AB%(0,0,0)=5
... und prompt ändert sich Byte Nummer 13 in ein e (e = 5).
Eine Eingabe für das zweite Element:
AB$(1,0,0)=6
verändert das 15. Byte in ein f.
In Bild 10 ist der Inhalt eines Ganzzahl-Feldes grafisch dargestellt.
1 2 3 4 \ a b c d
|---|---|---|---|--/--|------|------|------|------|-->
| \ | Low | High | Low | High |
| / | Byte | Byte |
| KOPF \ |-------------|-------------|
| (wie in Bild 2) / | | |
| \ | des | des | des
| / | 1. Elements | 2. Elements | 2. Elements
| \ | | |
|---|---|---|---|--/--|------|------|------|------|->
\
Bild 10. Ganzzahliges Feld
## Felder mit Zeichenketten
Die Dimensionierung eines Feldes mit Zeichenketten sieht so aus:
DIM AB$(1,2,3)
Auf dem Bildschirm erscheint jetzt ein Feld:
Auch hier zeigen die ersten elf Stellen dieselbe Information wie bei den anderen Feldern. Zur Kennzeichnung des Zeichenketten-Feldes ist das zweite Zeichen des Feldnamens invers dargestellt. Zeichen 3 und 4 geben wieder die Länge des Feldes an. Das S hat den Bildschirmcode 83. (Vorsicht! Da wir im Groß-/Kleinbuchstaben-Modus sind, müssen wir die jeweils rechte Seite der Spalten in der Code-Tabelle nehmen). Die Länge 83 minus 11 Kopfstellen ergibt 72 Byte, geteilt durch 24 (2*3*4 = 24 Elemente) erhalten wir 3 Byte zur Darstellung eines Elements.
Das erste Byte gibt die Länge der Zeichenkette an, das zweite und dritte Byte (Low-/High-Byte) die Adresse, ab der die Zeichenkette im vierten Block gespeichert ist.
Die Methode ist also dieselbe wie bei den »normalen« Zeichenketten-Variablen. Das wollen wir uns auch noch ansehen. Geben Sie direkt ein:
AB$(0,0,0) = "AAAAAA"
In der Darstellung des Feldes ändern sich dadurch die Stellen 12, 13 und 14 und wir sehen
* beim C 64:
* beim VC 20:
Im Bildschirm steht dafür:
* C 64: 6 250 159 das heißt 6 Zeichen, ab Adresse 250+159*256=40959
* VC 20: 6 250 29 das heißt 6 Zeichen, ab Adresse 250+29*256=7674
Jetzt weisen wir dem letzten Element auch noch eine Zeichenkette zu:
AB$(1,2,3)="BB"
Die letzten drei Stellen des Feldes ändern sich ebenfalls, wobei die erste mit dem b eine Zeichenkettenlänge von 2 angibt, dementsprechend muß die Anfangsadresse um 2 niedriger sein als die vorher definierte Kette: Das Low-Byte 250 - 2 = 248, in der Codetabelle finden wir dafür das, was auch im Feld steht. Das High-Byte bleibt unverändert.
Bild 11 zeigt die grafische Darstellung des Zeichenketten-Feldes.
Als letztes zeige ich Ihnen noch die im vierten Block gespeicherten Zeichenketten. Wir drucken einfach den CHR$-Wert der in den betreffenden Speicherzellen stehenden Codezahlen aus mit:
* VC 20:
FOR I=248 TO 255:PRINT CHR$(PEEK(29*256+I));:NEXT
* C 64:
FOR I=248 TO 255:PRINTCHR$(PEEK(159*256+I));:NEXT
... und wir erhalten die beiden Zeichenketten in umgekehrter Reihenfolge, also vom Speicherende her eingespeichert. Interessant ist, daß sich vor die Felder - wenn Sie sie noch auf dem Bildschirm hatten - die neu definierte Gleitkomma-Variable l@ geschoben hat. Auch das ist eine Demonstration des Speicherverfahrens der Variablen, genauso wie ich es Ihnen in der letzten Folge erklärt habe.
1 2 3 4 \ a b c d e f
|---|---|---|---|--/--|----------|-------|-------|-----|-----|-----|-->
| \ | Länge | Low | High | |
| / | der | Byte | |
| KOPF \ | Zeichen- |---------------| |
| (wie in Bild 2) / | kette der Adresse, | |
| \ | ab der der | |
| / | String ge- | |
| \ | | speichert ist | |
|---|---|---|---|--/--|--------------------------|-----------------|-->
\ |<--- 1. Element --->|<- 2. Element ->|
Bild 11. Zeichenketten-Feld
## Texteinschub Nr. 12: Darstellung der Variablen einer selbstdefinierten Funktion
Ich habe Ihnen gezeigt, wie im Programmspeicher abgelegte normale Variablen und Felder-Variablen sichtbar gemacht werden können. Damit konnten wir den Aufbau und die Darstellung der einzelnen Variablenarten studieren.
Heute will ich einen weiteren Variablentyp vorstellen, nämlich den der selbstdefinierten Funktionen.
Sie erinnern sich vielleicht, mit dem Basic-Befehl »DEF FN (Name)(Variable)« können wir komplizierte Funktionen selbst erfinden, definieren und später als »FN (Name)(Variable)< weiter verarbeiten. Diesen Typ wollen wir uns anschauen, wie er im Speicher steht.
Im Prinzip verwenden wir dieselben Methoden zur Sichtbarmachung wie die letzten Male.
Aber ein Unterschied kommt noch dazu. Der Befehl DEF kann leider nicht direkt eingegeben werden, sondern muß immer als Teil einer Programmzeile mit einer Zeilennummer versehen sein.
Deshalb schreiben wir zuerst ein kleines Programm zur Definition der Funktion plus Variable, bevor wir den Variablenspeicher mit dem Bildschirmspeicher zusammenlegen:
10 DEF FNAA(X)=3*SIN(X)+COS(X)
20 X=5
30 PRINT FNAA(X)
Die Funktion hat also den Namen »AA«. Bevor wir weitermachen, überprüfen Sie bitte mit RUN, ob alles stimmt. Nun wird der Speicher verschoben.
**Für den C 64 gilt:**
1. POKE 46,4:POKE 48,4
2. Bildschirm löschen mit CLR-Taste
3. Cursor auf die Mitte fahren
4. LIST (es erscheint das Programm)
5. auf den 2. Zeichensatz umschalten (mit C= und SHIFTTaste)
6. RUN
**Für den VC 20 (ohne. Erweiterung) gilt:**
Nur den Bildschirm auf 4096 zu verschieben, wie das letzte Mal, geht diesmal nicht, da wir ja für DEF ein kleines Programm schreiben müssen.
Also legen wir Bild- und Variablenspeicher ab Adresse 5120 (5120/256=20).
1. POKE 46,20:CLR
2. POKE 648,20
3. STOP/RESTORE-Tasten, bis Cursor wieder da ist
4. Bildschirm löschen mit CLR-Taste
5. dfe ersten vier bis sechs Zeilen mit SPACE-Taste überfahren
6. Cursor ein paar Zeilen nach unten
7. LIST (es erscheint das Programm)
8. mit Commodore- und SHIFTTaste auf 2. Zeichensatz umschalten
9. RUN
Wir sehen jetzt oben zwei Gruppen mit je sieben Zeichen, wie üblich.
Die erste Gruppe stellt die Funktion FNAA(x) dar. Sie ist gekennzeichnet durch das invertierte erste Zeichen des Namens, während das zweite Zeichen normal erscheint.
Das dritte und vierte Zeichen gibt in Low-/High-Byte- Darstellung (im Bildschirmcode) die Adresse an, ab der die Funktion FNAA(x) im Programmspeicher abgelegt ist. Mit `PEEK (3. Zeichen)+256*PEEK (4. Zeichen)` kann das abgefragt werden.
Das fünfte und sechste Zeichen nennt die Adresse, an welcher der Zahlenwert der Funktions-Variablen X anfängt. Das siebente Zeichen schließlich ist das erste Zeichen der Funktion selbst (in unserem Beispiel die 3).
Die zweite Gruppe beschreibt die Variable X der Funktion. Die normale Darstellung der beiden ersten Zeichen, die den Namen darstellen, gibt uns an, daß es sich um eine Gleitkomma-Variable handelt, deren Wert als Mantisse und Exponent dargestellt ist. Der Aufbau einer Funktion ist in Bild 12 zusammengefaßt:
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---------|---------|---------|---------|----------|----------|---------|
| Erstes | Zweites | Low- | High- | Low- | High- | |
|-------------------|---------|---------|----------|----------|---------|
| Zeichen des | Byte der Adresse, | Byte der Adresse, | 1. Zei- |
| Funktionsnamens | ab der die | ab dem der jewei- | chen |
|---------|---------| Funktion abge- | lige Wert der Funk- | der |
| ASCII- | ASCII- | speichert ist | tionsvariablen X | Funk- |
| Wert+128| Wert | | abgespeichert ist | tion |
Bild 12. Selbstdefinierte Funktion
# Texteinschub Nr. 13: Wie zufällig sind Zufallszahlen?
Der Befehl RND(X) ergibt eine Zufallszahl zwischen 0 und 1 - so steht es im Commodore-Handbuch.
Eine Zufallszahl ist definitionsgemäß rein dem Zufall überlassen. Ihr Wert kann nicht vorhergesehen werden. Wie kann aber ein Computer, in dem alle Vorgehensweisen und Arbeitsschritte fest vorprogrammiert sind, eine zufällige Zahl erzeugen? Die Commodore-Computer machen das so:
Der Befehl RND nimmt eine bestimmte Ausgangszahl (auf die ich noch näher eingehen werde), auf englisch »seed« = Samen genannt, multipliziert sie mit 11879546.4 und zählt 3.92767778 * 10^8 dazu. Die 5 Byte der resultierenden Gleitkommazahl werden miteinander vertauscht und in einen positiven Bruch umgewandelt. Diese Manipulation ergibt die »Zufallszahl«, die als neuer »Samen« in den Speicherzellen 139 bis 143 gespeichert wird.
Es ist sicher einzusehen, daß die Zufälligkeit nicht sehr hoch sein kann, es sei denn, die oben genannte und noch nicht erklärte Ausgangszahl ist zufällig.
Die erste Ausgangszahl hängt vom »Argument« des RND(X)-Befehls ab, das heißt vom Wert X, der in der Klammer dahinter steht. Es gibt drei Möglichkeiten für das Argument:
* eine positive Zahl (egal, welcher Wert)
* eine negative Zahl
* die Zahl 0
## Eine positive Zahl
zum Beispiel RND (1) oder RND(56) nimmt als Samen die Zahl 0.811635157, die beim Einschalten des Computers als 5-Byte- Gleitkommazahl in die Speicherzellen 139 bis 143 geschrieben worden ist. In den fünf Zellen stehen die Zahlen 128, 79, 199, 82, 88.
Daraus folgt aber, daß nach dem Einschalten des Computers mit RND(1) immer dieselbe Sequenz von Zufallszahlen erzeugt wird. Schalten Sie bitte den Computer aus und ein und geben Sie ein:
10 PRINT RND(1):G0T0 10
Notieren Sie die ersten paar Zahlen und wiederholen Sie mit Aus-/Einschalten die Prozedur. Sie werden immer dieselben Zahlen sehen.
Zum Austesten von Programmen mit bekannten Zahlensequenzen ist diese Methode sicher wichtig, aber echte Zufallszahlen sind das nicht!
## Eine negative Zahl
zum Beispiel RND(-1)oder RND(-95) bringt als erstes das Argument selbst (in meinem Beispiel -1 oder -95) als Gleitkommazahl in die Speicherzellen 139 bis 143, von wo sie als Samen den schon beschriebenen Manipulationen unterworfen wird. Nur - mit einem bestimmten negativen Argument erhalten Sie immer dieselbe Zufallszahl. Probieren Sie es aus: PRINT RND(-2) ergibt immer dieselbe Zahl.
Es mag Fälle geben, wo die Vorgabe des allerersten Samens wünschenswert ist. Ich will aber von zufälligen Zählen sprechen. Wir können diese Methode des negativen Arguments dadurch verbessern, daß wir als Argument selbst eine Zufallszahl nehmen.
Als derartige Zahl bietet sich der Wert der inneren Uhr TI an, die beim Einschalten des Computers losläuft und 60mal in der Sekunde weitergestellt wird. Da kein Mensch wissen kann, welchen Wert die UhrTI gerade hat, kommt der Befehl RND(-TI) dem absoluten Zufall schon sehr nahe.
## Das Argument (0)
verwendet eine andere Methode. Als Samen nimmt er eine sich ständig ändernde Zahl, die beim VC 20 aus vier Registerinhalten des VIC-lnterface-Bausteins genommen werden. Beim C 64 wird es ähnlich gemacht, nur ist der VIC-Baustein ein anderer Typ.
Mit derselben Methode nach dem Einschalten wie im ersten Fall oben können Sie das leicht überprüfen.
Ich habe eingangs zitiert, daß RND(X) eine Zahl zwischen 0 und 1 erzeugt; das gilt aber nur für ein positives Argument. Wenn Sie hingegen eine Zufallszahl innerhalb eines ganz bestimmten Bereiches brauchen, müssen Sie anders vorgehen.
## Kochrezept Nr. 1
Mit folgender Formel ist derZahlenbereich beliebig vorgebbar: `X=(RND(1)*A)+B`
* Die Zahl A gibt einen Bereich von 0 bis A vor.
* Die Zahl B legt den untersten Wert des Bereiches fest.
Beispiele:
* `10 PRINT (RND(1)*6)+1:GOTO 10` erzeugt Zahlen von 1 bis 6
* `10 PRINT (RND(1)*52)+1:G0T0 10` erzeugt Zahlen von 1 bis 52
* `10 PRINT (RND(1)*6)+10:G0T0 10` erzeugt Zahlen von 10 bis 16
Mit dem Vorschalten der Funktion INT vor den Befehl RND werden die Zufallszahlen auf ganze Zahlen beschränkt.
10 PRINT INT (RND(1)*6)+10:GOTO 10
Noch einmal: Zufallszahlen innerhalb bestimmter Zahlenbereiche sind gekoppelt mit einem positiven Argument. Wir haben aber gesehen, daß gerade so keine echten Zufallszahlen erzeugt werden. Deshalb brauchen wir noch ein zweites Kochrezept.
## Kochrezept Nr. 2
Wenn Sie in einem Programm nach dem Einschalten des Computers immer neue Zufallszahlen brauchen, ist es empfehlenswert, für die allererste Zufallszahl RND(-TI) oder RND(0) zu verwenden, dann aber mit RND(1) fortzufahren.
Dasselbe gilt, wenn ein Programm wegen INPUT oder WAIT eine Pause hat. Nach der Pause sollte zuerst ein neuer Ausgangswert genommen werden.
Als letztes will ich noch beschreiben, wie man Zufallszahlen innerhalb von Maschinenprogrammen erzeugen kann.
Im Betriebssystem steht natürlich eine Routine für den Befehl RND. Im C 64 beginnt sie ab 57495 ($E097), im VC 20 ab 57492 ($E094).
Der Ausgangswert (Samen) wird dabei aus dem Gleitkomma-Akkumulator Nr. 1 geholt, dessen Vorzeichen oder Wert 0 das weitere Vorgehen der Routine bestimmt.
Sie müssen also den Samen in den Akkumulator Nr. 1 laden und dann mit JSR auf die RND-Routine springen. Als Resultat können Sie einen oder mehrere Werte der Zellen 140 bis 143 verwenden und nach Belieben weiterverarbeiten.

341
combine.py Executable file
View file

@ -0,0 +1,341 @@
#!/usr/bin/python
import cgi, re, os
filenames = [
"c64disasm_ms.txt;c64disasm_cbm.txt",
"c64disasm_de.txt",
"c64disasm_en.txt",
"c64disasm_sc.txt",
"c64disasm_mn.txt",
"c64disasm_mm.txt"
]
names = [
"Microsoft/Commodore Source",
"Data Becker [German]",
"Lee Davison",
"Bob Sander-Cederlof [BASIC only]",
"Magnus Nyman [KERNAL only]",
"Marko M&auml;kel&auml;"
]
links = [
"https://github.com/mist64/cbmsrc",
"https://www.pagetable.com/?p=1015",
"https://www.pagetable.com/?p=726",
"https://www.pagetable.com/?p=728",
"https://www.telecomm.at/documents/Jiffydos_Romlisting.doc",
"http://www.unusedino.de/ec64/technical/misc/c64/romlisting.html"
]
descriptions = [
"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)<br/>and the original C64 KERNAL source by Commodore (lots of comments by the original authors)",
"German-language comments from <i>Das neue Commodore-64-intern-Buch</i> by Data Becker, ISBN 3890113079. Some minor corrections have been made.",
"Comments from <i>The almost completely commented C64 ROM disassembly V1.01</i> by Lee Davison. Some minor corrections have been made.",
"Comments adapted from <i>S-C DocuMentor for Applesoft</i> by Bob Sander-Cederlof, for the version of Microsoft BASIC that shipped with the Apple II.",
"Comments from <i>JIFFYDOS version 6.01/version 6.02</i> by Magnus Nyman (Harlekin/FairLight), which were written for the JiffyDOS KERNAL, so some serial code and all tape code is missing comments.",
"Comments from the <i>Commodore 64 BASIC/KERNAL ROM Disassembly Version 1.0 (June 1994)</i> by Marko M&auml;kel&auml;."
]
titlecolor = ["017100", "004D7F", "99195E", "F8BA00", "B51700", "017B76"]
darkcolor = ["D8F2CB", "C6E2FC", "BFB7E8", "FCF6CD", "F4D2E3", "D2F6F0"]
lightcolor = ["E5F2DF","E3F0FC","D5D1E8","FCFAE6","F5E4EC","E1F5F2"]
asm_donor_index = 1
source_index = 0 # we treat the Microsoft/Commodore source differently
f = os.popen("git log -1 --pretty=format:%h .")
revision = f.read()
f = os.popen("git log -1 --date=short --pretty=format:%cd .")
date = f.read()
data = []
linenumber = []
address = []
for filename in filenames:
d = []
for f in filename.split(";"):
d += [line.rstrip() for line in open(f)]
data.append(d)
linenumber.append(0)
address.append(0)
files = len(filenames)
asmaddress = 0
asmlinenumber = 0
for i in range(0, files):
while True:
line = data[i][linenumber[i]]
if len(line) > 0 and line[0] == '.':
break
linenumber[i] = linenumber[i] + 1
print '<meta http-equiv="Content-type" content="text/html; charset=utf-8" />'
print '<title>Ultimate Commodore 64 BASIC & KERNAL ROM Disassembly</title>'
print ''
print '<script language="javascript">'
print ' window.onload = init;'
print ' function init() {'
print ' var tbl = document.getElementById("disassembly_table");'
print ' for (var i = 0; i < ' + str(len(filenames)) + '; i++) {'
print ' var key = "column_" + i;'
print ' var element_name = "checkbox_" + i;'
print ' var checked = localStorage.getItem(key) != "hidden";'
print ' document.getElementById(element_name).checked = checked;'
print ' hideCol(i, checked);'
print ' }'
print ' }'
print ' function hideCol(col, checked) {'
print ' var tbl = document.getElementById("disassembly_table");'
print ' for (var i = 0; i < tbl.rows.length; i++) {'
print ' tbl.rows[i].cells[col+1].style.display = checked ? "" : "none";'
print ' }'
print ' var key = "column_" + col;'
print ' if (checked) {'
print ' localStorage.removeItem(key);'
print ' } else {'
print ' localStorage.setItem(key, "hidden");'
print ' }'
print ' }'
print '</script>'
print ''
# http://tholman.com/github-corners/
print '<a href="https://github.com/mist64/c64disasm" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#004080; color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>'
print '<style type="text/css">'
print ''
print 'body {'
print ' background: #e0f0ff;'
print ' color: #004080;'
print ' font-family: Helvetica'
print '}'
print ''
print 'a {'
print ' color: #0060a0;'
print '}'
print ''
print 'h3 {'
print ' font-family: serif;'
print '}'
print ''
print '.com {'
print ' white-space: pre;'
print '}'
print ''
print 'th.com {'
print ' font-weight: bold;'
print '}'
print ''
print 'div {'
print ' padding: 1em;'
print '}'
print ''
print 'div.disassembly_container {'
print ' padding: 1em 0em 1em 16em;'
print ' overflow: scroll;'
print '}'
print ''
print 'table {'
print ' border-collapse: collapse;'
print ' border: solid 1px #0060a0;'
print ' color: black;'
print '}'
print ''
print 'tr, td, th {'
print ' margin: 0px;'
print ' text-align:left;'
print ' vertical-align: text-top;'
print '}'
print ''
print 'table.disassembly_table {'
print ' border: solid grey;'
print ' border-width:0px 0px 1px 0px;'
print '}'
print ''
print 'table.disassembly_table td, table.disassembly_table th {'
print ' padding: 2px 4px;'
print ' border: solid grey;'
print ' border-width:0px 1px 0px 1px;'
print ' font-family: monospace;'
print '}'
print ''
print 'table.disassembly_table th.top_row {'
print ' border-width: 1px;'
print ' color: #e0f0ff;'
print '}'
print ''
print 'table.disassembly_table th.left_column {'
print ' position: absolute;'
print ' width: 18em;'
print ' left: 8px;'
print ' z-index: 11;'
print ' border: 1px solid #000;'
print ' border-radius: 2px;'
print ' color: #e0f0ff;'
print ' background: #0060a0;'
print '}'
print ''
print 'table.disassembly_table th.left_column a {'
print ' color: #e0f0ff;'
print '}'
print ''
for i in range(0, len(filenames)):
print 'table.disassembly_table th.top_row:nth-of-type(' + str(i+2) + ') {'
print ' background: #' + titlecolor[i] + ';'
print '}'
print ''
print 'table.disassembly_table tr td:nth-of-type(' + str(i+1) + ') {'
print ' background: #' + darkcolor[i] + ';'
print '}'
print ''
print 'table.disassembly_table tr:nth-child(even) td:nth-of-type(' + str(i+1) + ') {'
print ' background: #' + lightcolor[i] + ';'
print '}'
print ''
print 'table.checkbox_table tr:nth-of-type(' + str(i+1) + ') {'
print ' background: #' + lightcolor[i] + ';'
print '}'
print ''
print 'table.checkbox_table tr:nth-of-type(' + str(i+1) + ') td:nth-of-type(2) {'
print ' background: #' + titlecolor[i] + ';'
print '}'
print ''
print 'table.disassembly_table tr {'
print ' background: #f0f0f0;'
print '}'
print ''
print 'table.disassembly_table tr:nth-child(even) {'
print ' background: #ffffff;'
print '}'
print ''
print 'table.checkbox_table {'
print ' border-color: #0060a0;'
print '}'
print ''
print 'table.checkbox_table a {'
print ' color: #e0f0ff;'
print '}'
print ''
print 'table.checkbox_table tr, table.checkbox_table td {'
print ' padding: 4px 8px;'
print ' border: solid #0060a0;'
print ' border-width:1px 0px 1px 0px;'
print '}'
print ''
print '</style>'
print '<body>'
print '<h1>Ultimate Commodore 64 BASIC & KERNAL ROM Disassembly</h1>'
print '<p><i>by <a href="http://www.pagetable.com/">Michael Steil</a>, <a href="https://github.com/mist64/c64disasm">github.com/mist64/c64disasm</a>. Revision ' + revision + ', ' + date + '</i></p>'
print '<b>This allows you to view different commentaries side-by-side. You can enable/disable individual columns:</b><br/><br/>'
print '<table class="checkbox_table">'
for i in range(0, len(filenames)):
print '<tr><td><input type="checkbox" id="checkbox_' + str(i) + '" checked onclick="hideCol(' + str(i) + ', document.getElementById(\'checkbox_' + str(i) + '\').checked);" /></td><td style="white-space: nowrap;"><b><a href="' + links[i] + '">' + names[i] + '</a></b><td>' + descriptions[i] + '</td></tr>'
print '</table>'
print '<div class="disassembly_container">'
print '<table id="disassembly_table" class="disassembly_table">'
print '<tr>'
print '<th class="left_column">Disassembly</th>'
for i in range(0, files):
print '<th class="top_row">' + names[i] + '</th>'
print '</tr>'
count = 0
while(True):
count += 1
# if count > 80:
# break
for i in range(0, files):
if linenumber[i] >= len(data[i]):
continue
while len(data[i][linenumber[i]]) > 0 and (data[i][linenumber[i]][0] == '-' or data[i][linenumber[i]][0] == '#'):
linenumber[i] = linenumber[i] + 1
if asmlinenumber >= len(data[asm_donor_index]):
break
asm = data[asm_donor_index][asmlinenumber][0:32].rstrip()
asmlinenumber = asmlinenumber + 1
if len(asm) == 0:
continue
if asm[0] == '#' or asm[0] == '-':
continue
has_address = False
if asm[0] == '.':
hexaddress = asm[2:6]
asmaddress = int(hexaddress, 16)
has_address = True
hex_numbers = re.findall(r'\$[0-9A-F][0-9A-F][0-9A-F][0-9A-F]', asm)
for hex_number in hex_numbers:
if (hex_number[1] == 'A' or hex_number[1] == 'B' or hex_number[1] == 'E' or hex_number[1] == 'F'):
asm = asm.replace(hex_number, "<a href=\"#" + hex_number[1:] + "\">" + hex_number + "</a>")
print '<tr>'
print '<th class="left_column">'
if has_address:
print "<a name=\"" + hexaddress + "\"/>"
print '<span class="com">' + asm + '</span></th>'
for i in range(0, files):
print '<td>'
comments = []
while True:
if linenumber[i] >= len(data[i]):
break
line = data[i][linenumber[i]]
if line.startswith('.'):
address[i] = int(line[2:6], 16)
if address[i] > asmaddress:
break
comment = line[32:]
comment = cgi.escape(comment)
hex_numbers = re.findall(r'\$[0-9A-F][0-9A-F][0-9A-F][0-9A-F]', comment)
for hex_number in hex_numbers:
if (hex_number[1] == 'A' or hex_number[1] == 'B' or hex_number[1] == 'E' or hex_number[1] == 'F'):
comment = comment.replace(hex_number, "<a href=\"#" + hex_number[1:] + "\">" + hex_number + "</a>")
if comment.startswith('***'):
comment = '<h3>' + comment[3:] + '</h3>'
elif comment.startswith('SUBTTL'):
comment = '<h3>' + comment[6:] + '</h3>'
elif comment.startswith('.LIB '):
comment = '<h3>' + comment + '</h3>'
else:
scomment = comment.lstrip()
if scomment.startswith(';'):
comment = '<b>' + comment + '</b>'
if len(comment) != 0:
comment = '<span class="com">' + comment + '</span><br />'
if len(comment) != 0:
comments.append(comment)
linenumber[i] = linenumber[i] + 1
if len(comments):
for comment in comments:
print comment
else:
print '&nbsp;'
print "</td>"
print "</tr>"
print '</table>'
print '</div>'
print '</body>'

53
kernal/generate.py Executable file
View file

@ -0,0 +1,53 @@
#!/usr/bin/python3
import markdown
import re
#lines = [line.rstrip() for line in open("kernal_prg.txt")]
lines = [line.rstrip() for line in open("kernal_128intern.txt")]
calls_raw = []
call_lines = None
for line in lines:
if line.startswith('#') or line.startswith('-'):
continue
if line.startswith('$'):
if call_lines is not None:
calls_raw.append(call_lines)
call_lines = []
if call_lines is not None:
call_lines.append(line)
calls = []
names = []
for call_lines in calls_raw:
title = call_lines[0]
address = title[1:5]
name = title[7:13].rstrip()
summary = title[15:]
call_lines_stripped = []
for call_line in call_lines[1:]:
call_lines_stripped.append(call_line[15:])
calls.append((address, name, summary, call_lines_stripped))
names.append(name)
print('<table border=1>')
for (address, name, summary, lines) in calls:
print('<tr>')
print('<td>$' + address + '</td>')
print('<td><a name="' + name + '">' + name + '</td>')
print('<td><details open><summary>' + summary + '</summary>')
all_text = '\n'.join(lines)
html = markdown.markdown(all_text, extensions=['tables' , 'sane_lists'])
for replace_name in names:
if replace_name != name:
html = re.sub('\\b' + replace_name + '\\b', '<a href="#"' + replace_name + '">' + replace_name + '</a>', html)
print(html + '</details></td>')
print('</tr>')
print('</table>')

547
kernal/kernal_128intern.txt Normal file
View file

@ -0,0 +1,547 @@
-
- Schieb, Thrun, Wobel: Commodore 128 intern
- ISBN 3-89011-098-3
-
$FF81 CINIT Video-Controller und Editor initialisieren
Es werden die Funktionstasten auf Standard
gelegt, beide Video-Controller initialisiert und der 40/80-
Zeichen-Modus in Abhängigkeit der 40/80-Zeichen-Taste
eingeschaltet. Weiterhin werden der Tastaturbuffer gelöscht
sowie alle Flags rückgesetzt und ein CLRCH ausgeführt.
$FF84 IOINIT Initialisierung der Ein/Ausgabegeräte
Die Ein/Ausgabegeräte werden initialisiert, d.h.
die RESET-Leitung auf dem IEC-Bus wird aktiviert. Ange-
schlossene Drucker werden in den Anfangszustand versetzt und
die Floppy löscht ihre Kanäle - hört sich also an, als ob sie
gerade eingeschaltet worden wäre.
$FF87 RAMTAS BASIC-Warmstart
Diese Routine initialisiert die Zeropage, setzt die
Zeiger für SYSTOP und SYSBOT (also die Speicherunter- und -
obergrenze), setzt die Zeiger für die RS-232-Ein/Ausgabebuffer
und den Kassettenbuffer zurück.
$FF8A RESTOR Systemvektoren initialisieren
Es werden die Systemvektoren ab Adresse $0314
bis $0332 (inkl.) auf Normalwert gesetzt. Diese Routine sollte
aufgerufen werden, wenn Sie zu viele Vektoren verbogen und
die Übersicht verloren haben oder wenn Sie beispielsweise ein
Erweiterungspaket ausschalten wollen. Diese Routine ruft die
folgende VECTOR-Routine mit gelöschtem CARRY auf.
$FF8D VECTOR Systemvektoren kopieren oder rücksetzen
Diese Routine kopiert die 16 Vektoren ab $0314
in den durch das X- (Low) und Y-Register (High) definierten
Speicher, sofern das CARRY-Flag gesetzt ist. Bei gelöschtem
CARRY-Flag werden die Vektoren ab $0314 mit dem durch das
X- und Y-Register angegebenen Bereich geladen.
**Eingabeparameter**: .X, .Y, CARRY
**Beispiel**:
LDX #$00 ;Lo-Byte von $1000
LDY #$10 ;Hi-Byte von $1000
CLC ;Lösche Carry zum Kopieren ($1000)->($0314)
JSR $FF80 ;Belege Vektoren neu
$FF90 SETMSG DOS-Meldungen ermöglichen/verhindern
Die Routine speichert den Wert des <Akku> in
der Zeropage-Adresse $9D. Sollen Systemmeldungen ausgegeben
werden, so ist das Bit 7 des <Akkus> zu setzen. Ist $9D positiv,
so werden Systemmeldungen verhindert.
**Eingabeparameter**: .A
$FF93 SECND Sekundäradresse nach LISTEN senden
Es wird die zu sendende Sekundäradresse im
<Akku> übergeben. Die Routine gibt den <Akku> dann als
Sekundäradresse auf dem IEC-Bus aus.
**Eingabeparameter**: .A
**Beispiel**:
;LISTEN wurde gesendet
LDA #$F0 ;Sekadr. 0 bei CLOSE
JSR $FF93 ;Sekundaradresse senden
$FF96 TKSA Sekundäradresse nach TALK senden
Adäquat zu der vorhergehenden Routine sendet
diese Routine die Sekundäradresse - übergeben im <Akku> -
nach erfolgtem TALK-Signal an den IEC-Bus.
**Eingabeparameter**: .A
$FF99 MEMTOP Setzen/Holen der Speicherobergrenze
Ist das CARRY-Flag gesetzt, so wird im X-
Register (Lo) und Y-Register (Hi) die maximal verfügbare
Speicherstelle übergeben. Wird die Routine mit gelöschtem
CARRY angesprungen, so wird die Speicherobergrenze mit den
beiden Registern belegt.
**Eingabeparameter**: .X, .Y (bei gelöschtem CARRY), CARRY
**Ausgabeparameter**: .X, .Y (bei gesetztem CARRY)
**Beispiel**:
;Auslesen der Speicherobergrenze
SEC ;Auslesen der Obergrenze
JSR $FF99 ;Hole Obergrenze
STX $FC ;zwischenspeichern
STY $FD ;zwischenspeichern
LDX #$00 ;Lo-Byte von $1000
LDY #$10 ;Hi-Byte von $1000
CLC ;Flag zum Setzen des MEMTOP
JSR $FF99 ;Setze Speicherobergrenze
$FF9C MEMBOT Setzen/Holen der Speicheruntergrenze
Genauso wie bei der Routine MEMTOP wird bei
gelöschtem CARRY-Flag die Untergrenze des verfügbaren
Speichers mit den beiden Registern X ^Lo) und Y (Hi) belegt.
Ist das CARRY-Flag gesetzt, so wird die Speicheruntergrenze
ausgelesen und in den beiden Registern übergeben.
**Eingabeparameter**: .X, .Y (bei gelöschtem CARRY), CARRY
**Ausgabeparameter**: .X, .Y (bei gesetztem CARRY)
$FF9F KEY Ermitteln gedrückter Tasten
Diese Routine ist elementar zur Tastatur-
dekodierung. Die Tastatur wird auf eine gedrückte Taste anhand
der Tastaturdekodiertabellen überprüft. Wird eine gedrückte
Taste ermittelt, so wird der ASCII-Wert errechnet und dieser
dem Tastaturbuffer (ab $034A) hinzugefügt.
$FFA2 SETTMO Setzen des Timeout-Flags für IEEE
Die Routine speichert den im <Akku> überge-
benen Wert als Timeout-Flag für die IEEE-Routinen an Adresse
$0A0E. Um den Timeout in den IEEE-Routinen zu
ermöglichen, muß das Bit 7 des <Akkus> gesetzt sein.
**Eingabeparameter**: .A
$FFA5 ACPTR Holt ein Byte vom seriellen Bus
Die Routine holt ein Byte vom seriellen IEC-Bus.
Das geholte Zeichen wird im Akku übergeben. Das Statusbyte
ST an $90 wird entsprechend der Aktion gesetzt.
**Ausgabeparameter**: .A
$FFA8 CIOUT Ausgabe eines Zeichens auf IEC-Bus
Diese Routine ist das Gegenstück zu ACPTR. Das
im <Akku> übergebene Zeichen wird auf dem lEC-Bus ausge-
geben. Auch hier wird das Statusbyte ST an $90 entsprechend
der Aktion geändert.
**Eingabeparameter**: .A
$FFAB UNTLK UNTALK auf lEC-Bus senden
Diese Routine wird beim Schließen bzw. Umlegen
eines Eingabekanals aufgerufen. Sie bringt das zum Reden
(TALK) gebrachte Gerät zum Schweigen.
$FFAE UNLSN UNLISTEN auf IEC-Bus senden
Entsprechend zu UNTALK wird bei dieser
Routine ein empfangendes Gerät vorerst abgeschaltet. Dies wird
beim Schließen oder Umlegen eines Ausgabekanals gemacht.
$FFB1 LISTN Senden von LISTEN an ein Gerät
Es wird ein am IEC-Bus angeschlossenes Gerät
zum Empfang aufgefordert. Dazu wird das Signal LISTEN über
den IEC-Bus geschickt. Im <Akku> wird die Geräteadresse des
anzusprechenden Gerätes übergeben. Beispielsweise wird bei
einem Drucker ein LISTEN gesendet, bevor die Zeichen zur
Ausgabe über den IEC-Bus wandern. Wenn Sie LISTEN ver-
wenden, so müssen Sie die auszugebenden Zeichen über die
Routine CIOUT ausgeben (nicht über BSOUTÜ). Zum Schließen
des Kanals verwenden Sie dann die Routine UNLISTEN. Es
kann immer nur ein Gerät am IEC-Bus aktiv sein. Um diese
komplizierten Arbeiten zu vereinfachen, können Sie im
Betriebssystem Kanäle öffnen und schließen. BSOUT und
BASIN übernehmen dann das Senden von LISTEN und
UNLISTEN sowie TALK und UNTALK.
**Eingabeparameter**: .A
**Beispiel**:
;LISTEN an Drucker senden
LDA #$24 ;Geräteadresse Drucker & LISTEN ein
JSR $FFB1
$FFB4 TALK Senden von TALK an ein Gerät
Entsprechend der Routine LISTN sendet diese
Routine das Kommando TALK an ein beliebiges Gerät. Die
Geräteadresse ist im <Akku> zu übergeben. Das Kommando
TALK fordert ein am IEC-Bus angeschlossenes Gerät zum
Reden, also zum Senden von Informationen auf.
**Eingabeparameter**: .A
$FFB7 READST Holen des I/O-Statusbytes
Es wird der aktuelle Systemstatus im <Akku>
zurückgegeben. Ist die RS232 aktiv, so wird das Statusbyte
übergeben und direkt im Speicher gelöscht. Sollten Sie also das
Statusbyte öfters benötigen, so speichern Sie es zwischen. Ist ein
anderer als der RS232-Kanal geöffnet, so wird das Statusbyte
von Adresse $90 übergeben.
**Ausgabeparameter**: .A
$FFBA SETLFS Fileparameter setzen
Diese Routine wird überall dort benötigt, wo man
Files öffnen muß. Man übergibt die logische File-nummer im
<Akku>, die Geräteadresse im X-Register und die Sekun-
däradresse im Y-Register. Die Routine speichert diese Werte an
den Zeropage-Adressen $B8 bis $BA ab.
**Eingabeparameter**: .A, .X, .Y
$FFBD SETNAM Setzen der Filenamenparameter
In der Routine werden die Informationen für den
Filenamen in der Zeropage gespeichert. Diese Angaben sind alle
vor dem Öffnen eines Kanales zu machen. Im <Akku> wird die
Länge des Filenamens übergeben, im X-Register das Lo-Byte
der Adresse und im Y-Register das Hi-Byte der Adresse, an der
der Filename gespeichert ist. Ferner müssen Sie mit der
SETBNK-Routine die Konfigurationsindizes für den Filenamen
und den zu bearbeitenden Speicherbereich übergeben.
**Eingabeparameter**: .A, .X, .Y
**Beispiel**:
;Eröffnen eines des Directory-Files auf Diskette
LDA #$0C ;Bereich im RAM-Bank 0
TAX ;Filename auch in RAM-Bank 0
JSR $FF68 ;SETBNK aufrufen
LDA #$01 ;Logische Filenummer
LDX #$08 ;Geräteadresse
LDY #$00 ;Sekundäradresse für Lesen
JSR $FFBA ;SETLFS
LDA #$01 ;Länge des Filenamens
LDX #$00 ;Lo-Byte der Adresse, an der der
LDY #$10 ;Filename gespeichert ist ($1000)
JSR $FFBD ;SETNAM
JSR $FFC0 ;OPEN - Öffnen des Kanals
und an Adresse $1000:
01000 24 ....
$FFC0 OPEN Öffnen einer Datei
Es wird die durch die Routinen SETNAM,
SETLFS und SETBNK definierte Datei in die Liste der
logischen Filenummern aufgenommen. Erst ab diesem Augen-
blick können die logischen Filenummern bei den Routinen
CKOUT und CHKIN angegeben werden. Beachten Sie, daß Sie
maximal neun Files auf einmal öffnen können.
$FFC3 CLOSE Schließen einer logischen Datei
Es wird die im <Akku> übergebene logische Datei
geschlossen. Dabei werden alle gespeicherten Werte wie
Geräteadresse, Sekundäradresse etc. in der dafür vorgesehenen
Tabelle gelöscht. Ist die Aktion nicht problemlos verlaufen, so
wird das CARRY-Flag gesetzt.
**Eingabeparameter**: .A
**Ausgabeparameter**: CARRY
**Beispiel**:
;Beispiel für CLOSE
LDA #$01 ;Schließen der Beispieldatei von SETNAM
JSR $FFC3 ;CLOSE ausführen
BCS Error ;Fehler aufgetreten
$FFC6 CHKIN Logische Datei als Eingabekanal definieren
Im X-Register wird die logische Dateinummer
übergeben, die als Eingabekanal benutzt werden soll. Die ange-
gebene logische Dateinummer muß natürlich bereits mit dem
OPEN-Kommando geöffnet worden sein. Wird nach dem Aufruf
des CHKIN-Kommandos die BASIN-Routine aufgerufen, so
erfolgt die Eingabe nicht von Tastatur, sondern von dem
geöffneten Gerät; dies kann beispielsweise die Floppy sein. Zu
beachten ist, daß zum Einlesen von Tastatur kein CHKIN not-
wendig ist, da die Tastatur Standard-Eingabegerät ist. Nach
einem CLOSE oder CLRCH ist die Tastatur automatisch wieder
das Eingabegerät. Auch bei dieser Routine wird das CARRY als
OK-Flag benutzt.
**Eingabeparameter**: .X
**Ausgabeparameter**: CARRY
**Beispiel**:
;Einlesen der Directory
JSR DIROP ;OPEN 1,8,0,"$" (selbstdefinierte Routine)
LDX #$01 ;LFN der eröffneten Datei
JSR $FFC6 ;CHKIN ausführen
JSR $FFCF ;BASIN - Zeichen holen
$FFC9 CKOUT Logische Datei als Ausgabedatei definieren
Entsprechend zu CHKIN definiert diese Routine
ein im X-Register zu übergebene Datei als Ausgabedatei. Die
Datei muß ordnungsgemäß geöffnet worden sein, beispielsweise
würde eine Datei, die mit OPEN l,8,0,"$" geöffnet wurde und
mit CKOUT als Ausgabedatei definiert werden soll, einen
Fehler hervorrufen, weil diese Datei zum Lesen und nicht zum
Schreiben geöffnet wurde. Nach Definition einer Ausgabedatei
ist nicht mehr der Bildschirm, sondern die definierte Datei
Ausgabegerät. Alle über BSOUT auzugebenen Zeichen werden
an dieses Gerät gesandt. Das CARRY-Flag dient als Fehlermel-
der. Ist es gelöscht, war die Aktion erfolgreich.
**Eingabeparameter**: .X
**Ausgabeparameter**: CARRY
$FFCC CLRCH Ein/Ausgabekanäle schließen
Diese Routine löscht evtl, mit CHKIN und/oder
CKOUT definierte Ein- und Ausgabedateien. Es wird an das
Eingabegerät ein UNTALK und an das Ausgabegerät ein
UNLISTEN gesendet. Der Bildschirm ist wieder Ausgabe- und
die Tastatur Eingabegerät. Die Dateien werden nicht geschlossen,
es erfolgt also kein CLOSE. Es werden weder Ein- noch
Ausgabeparameter übergeben.
$FFCF BASIN Ein Zeichen von Eingabekanal holen
Die eröffnete und mit CHKIN als Eingabedatei
definierte Datei (sonst Tastatur) übergibt ein Zeichen im
<Akku>.
**Ausgabeparameter**: .A
$FFD2 BSOUT Ein Zeichen auf Ausgabekanal ausgeben
Es wird das im <Akku> übergebene Zeichen auf
die eröffnete und mit CKOUT als Ausgabedatei definierte Datei
ausgegeben. Ist der Bildschirm Ausgabedatei (Default), so wird
das ASCII-Zeichen in den darzustellenden POKE-Code
umgerechnet (ein recht aufwendiges Verfahren. Interessierte
sollten sich den entsprechenden Teil im Kernal im C-Bereich
ansehen).
**Eingabeparameter**: .A
**Beispiel**:
;Wechseln des 40/80-Zeichen-Modus
LDA #$1B ;<ESC>
JSR BSOUT ;$FFD2, Zeichen ausgeben
LDA #"X" ;<ESC>-X zum Uechseln des Bildschirmstatus
JSR BSOUT ;ausgeben
(Es gibt allerdings eine spezielle Routine, die man anspringen
kann)
$FFD5 LOADSP Laden einer Datei in den Speicher
Bevor mit LOADSP eine Datei geladen werden
kann, muß das Gerät, die Sekundäradresse, der Filename etc.
durch die Routinen SETLFS, SETNAM und SETBNK definiert
worden sein. Im X- (Lo) und Y-Register (Hi) wird die Adresse
angegeben, ab der die zu ladende Datei abgelegt werden soll.
**Eingabeparameter**: .X, .Y
**Beispiel**:
;Laden eines Overlay o.ä.
JSR PREP ;SETLFS, SETBNK, SETNAM etc.
LDX #$00 ;Lo-Byte von $1000
LDY #$10 ;Hi-Byte von $1000 (Ladeadresse)
JSR $FFD5 ;Lade Datei ab $1000
$FFD8 SAVESP Abspeichern eines Bereiches auf Datei
Diese Routine speichert einen Speicherbereich auf
eine Datei (Diskette, Kassette) ab. Dazu muß man, wie bei der
LOADSP-Routine, zunächst Geräteadresse, Sekundäradresse,
RAM-Bank, Filename etc. durch die Routinen SETBNK,
SETLFS und SETNAM definieren. Im Akku wird die Zeropage-
Adresse angegeben, an der die Anfangsadresse des abzu-
speichernden Bereiches steht. Im X- (Lo) und Y-Register (Hi)
wird entsprechend die Endadresse des abzuspeichernden
Bereiches angegeben.
**Eingabeparameter**: .A, .X, .Y, Zeropage
**Beispiel**:
;Abspeichern des Bereiches $1000 bis $1100
JSR PREP ;SETLFS, SETNAM, SETBNK etc. aufrufen
LDA #$00 ;Lo-Byte von $1000
STA $FC ;in Zeropage speichern
LDA #$10 ;Hi-Byte von $1000
STA $FD ;in Zeropage speichern
LDA #$FC ;der Pointer befindet sich an $FC
LDX #$00 ;Lo-Byte der Endadresse $1100
LDY #$11 ;Hi-Byte der Endadresse $1100
JSR $FFD8 ;SAVESP - Speichern des Bereiches $1000-$1100
$FFDB SETTIM Setzen der Systemuhr TI
Die Routine setzt die Systemuhr TI, die ab
Adresse $A0 definiert ist. Diese Uhr wird von der Kernal-IRQ-
Routine gesteuert und ist nicht sehr genau. Legen Sie auf eine
genauere Uhr Wert, so benutzen Sie die Timer in den beiden
CIAs. (Siehe auch entsprechendes Kapitel) Das höchstwertige
Byte der 24-Stunden-Uhr wird im Y-Register übergeben.
**Eingabeparameter**: .A, .X, .Y
**Beispiel**:
;Rücksetzen der Systemuhr
LDA #$00 ;Rücksetzen bedeutet
TAY ;auf 0,0,0 setzen
TAX ;Alle drei Register auf null
JSR $FFDB ;SETTIM
$FFDE RDTIM Auslesen der Systemuhr
Diese Routine liest die 24-Stunden-Uhr aus und
übergibt die drei Bytes den Registern Y (höchstwertig), X und
<Akku> (niederwertig).
**Ausgabeparameter**: .A, .X, .Y
**Beispiel**:
;Auslesen der 24-Stunden-Uhr
JSR $FFDE ;RDTIM aufrufen
STY $FC ;MSB merken
STX $FD ;mittleres Byte merken
STA $FE ;LSB merken
$FFE1 STOP Abfrage der Stop-Taste
Wenn bis zum letzten IRQ-Aufruf die Stop-Taste
betätigt worden ist, so wird das ZERO-Flag gesetzt und es wird
ein CLRCH ausgeführt. Wurde die Stop-Taste nicht betätigt, so
wird das ZERO-Flag gelöscht.
**Ausgabeparameter**: ZERO-Flag
**Beispiel**:
;Auf STOP prüfen
JSR $FFE1 ;STOP-Taste gedrückt?
BEQ Jawoll ;Ist gedrückt
$FFE4 GETIN Holt ein Zeichen aus Tastaturbuffer oder RS232
Holt von der definierten Eingabedatei ein
Zeichen. Ist kein Zeichen bereit gestellt, so wird der <Akku>
mit null übergeben.
**Ausgabeparameter**: .A
$FFE7 CLALL Alle offenen Dateien schließen
Alle mittels OPEN eröffneten Dateien werden
geschlossen oder besser gelöscht - es wird nämlich kein CLOSE
ausgeführt. Beispielsweise bei offenen Floppy-Dateien kann dies
sehr ärgerlich sein (WRITE FILE OPEN ERROR ist eine
Konsequenz). Ferner wird nach dem Löschen der logischen
Dateien ein CLRCH (s.o.) ausgeführt. CLALL ist also mit Vor-
sicht anzuwenden.
$FFEA LIDTIM Systemuhr anpassen (updaten)
Diese Routine wird vornehmlich von der IRQ-
Routine aufgerufen. Es wird die Drei-Byte-24-Stunden-Uhr um
eine Einheit hochgezählt.
$FFED SCRORG Größe des aktuellen Fensters holen
Die Routine SCRORG holt die aktuellen
Fensterwerte in die Register. Der <Akku> enthält nach dem
Aufruf die maximale Spaltenzahl, im Y-Register befindet sich
die Anzahl der Zeilen im Fenster und im X-Register die Anzahl
der Spalten des Fensters.
**Ausgabeparameter**: .A, .X, .Y
$FFF0 PLOT Cursor-Position holen/setzen
Je nach Zustand des CARRY-Flags wird entweder
die Cursorposition geholt oder gesetzt. X- und Y-Register sind
auf jeden Fall die Kommunikationsregister. Das Y-Register
definiert die Zeile (Erste Zeile im Fenster ist null) und das X-
Register die Spalte des Cursors. Ist das CARRY-Flag gesetzt, so
wird die aktuelle Cursorpostion im Fenster in X- und Y-
Register zurückgegeben.
**Eingabeparameter**: .X, .Y, CARRY
**Beispiel**:
;Einen Stern (*) in die Fenstermitte setzen
JSR $FFED ;SCRORG aufrufen
TXA ;Spaltenzahl nach <Akku>
LSR A ;Divisiondurch zwei (Mitte)
TAX ;und als Spalte wieder nach X
TYA ;Zeilenzahl nach <Akku>
LSR A ;Divisiondurch zwei (Mitte)
TAY ;und wieder als Zeile nach Y
CLC ;Gelöschtes Carry=Setzen Cursorposition
JSR $FFF0 ;Setze Cursorposition
LDA #"*" ;<Akku> mit Stern laden
JSR $FFD2 ;und ausgeben.
$FFF3 IOBASE Holt die Basisadresse des I/O-Bereiches
Es wird die Adresse des Ein- und Ausgabebe-
reiches in X- (Lo) und Y-Register (Hi) übergeben. Diese
Adresse ist beim C128 natürlich immer $D000. Für spätere
Erweiterungen bzw. Verschiebungen ist es aus Kompatibilitäts-
gründen ratsam, diese Routine in die Software mit zu integrieren
und sich darauf zu beziehen.
**Ausgabeparameter**: .X, .Y
**Beispiel**:
;Anfang des Programmes:
JSR $FFF3 ;IOBASE
STX $FD ;Lo-Byte merken
STY $FE ;Hi-Byte merken
Im Programm bezieht man diese Adresse dann wie folgt ein:
STA ($FD),Y ;In I/O-Bereich

View file

@ -0,0 +1,99 @@
$FF81 Video-Reset
$FF84 CIAs initialisieren
$FF87 RAM löschen/testen
$FF8A I/O initialisieren
$FF8D I/O Vektoren initialisieren
$FF90 Setzt Flag für Ausgabe von Systemmeldung
$FF93 schickt Sekundäradresse nach einem LISTEN-Befehl
auf den IEC-Bus
$FF96 schickt Sekundäradresse nach einem TALK-Befehl
auf den IEC-Bus
$FF99 holt bei gesetzem Carry-Flag die höchste RAM-
Adresse nach X und Y, bei gelöschtem Carry-
Flag wird die Adresse von X und Y gesetzt.
$FF9C dieselbe Funktion wie $FF99, jedoch für den
RAM-Anfang
$FF9F fragt die Tastatur ab
$FFA2 setzt das Time-out-Flag für den IEC-Bus
$FFA5 holt ein Byte vom IEC-Bus in den Akku
$FFA8 gibt ein Byte aus dem Akku an den IEC-Bus aus
$FFAB sendet UNTALK-Befehl auf den IEC-Bus
$FFAE sendet UNLISTEN-Befehl auf den IEC-Bus
$FFB1 sendet LISTEN-Befehl auf den IEC-Bus
$FFB4 sendet TALK-Befehl zum IEC-Bus
$FFB7 holt das Statuswort in den Akku
$FFBA setzt die Fileparameter, Akku muß logische
Filenummer enthalten, X = Gerätenummer und
Y = Sekundäradresse
$FFBD setzt Parameter des Filenamens, Akku muß
Länge des Namens enthalten, X und Y enthalten
die Adresse des Filenamens (Low- und High-Byte)
$FFC0 OPEN-Befehl, öffnet logische Datei
$FFC3 CLOSE-Befehl, schließt logischeDatei,
Akku muß logische Filenummer enthalten
$FFC6 CHKIN setzt folgende Eingabe auf logische
Datei, die in X übergeben wird.
Die logische Datei muß vorher mit der
OPEN-Routine geöffnet werden.
$FFC9 CKOUT setzt folgende Ausgabe auf logische
Datei, die in X übergeben wird.
Die logische Datei muß vorher mit der
OPEN-Routine geöffnet werden.
$FFCC CLRCH setzt die Ein- und Ausgabe wieder
auf Standard (Tastatur/Bildschirm)
$FFCF BASIN Eingabe, holt ein Zeichen in den Akku
$FFD2 BSOUT Ausgabe, gibt Zeichen im Akku aus
$FFD5 LOAD, lädt Programm in den Speicher
$FFD8 SAVE, speichert Programm ab
$FFDE setzt die laufende Zeit neu
$FFE1 holt die laufende Zeit fragt die STOP-Taste ab
$FFE4 GET, holt ein Zeichen in den Akku
$FFE7 CLALL, setzt a lle Ein-/Ausgabekanäle
zurück, die Dateien werden jedoch
nicht geschlossen
$FFEA erhöht die laufende Zeit um eine
sechzigstel Sekunde
$FFED SCREEN holt die Anzahl der Zeilen und
Spalten des Bildschirms
$FFF0 bei gelöschtem Carry-Flag wird der Cursor
auf die Position X/Y gesetzt, bei gesetztem
Carry-Flag wird die Cursorposition nach X/Y
geholt (X-Reg = Zeile, Y-Reg = Spalte)
$FFF3 holt die Startadresse des I/O-Bausteins

299
kernal/kernal_ct.txt Normal file
View file

@ -0,0 +1,299 @@
-
- Craig Taylor: Kernal 64 / 128
- C=Hacking, Volume 1, Issue 3; July 15, 1992
-
$FF81 CINT Setup VIC, screen values, (128: 8563)...
Registers In : None.
Registers Out : None.
Memory Changed: Screen Editor Locations.
$FF84 IOINIT Initializes pertinant display and i/o devices
Registers In : C64: None. | C128: $0A04/bit 7
| 0 - Full Setup.
| 1 - Partial Setup. (no 8563 char)
Registers Out : .A, .X, .Y destroyed.
Memory Changed: CIA's, VIC, 8502 port, (C128: also optionally 8563).
Note : This routine automatically distinguishes a PAL system from a
NTSC system and sets PALCNT accordingly for use in the
time routines.
$FF87 RAMTAS Clears Z-Page, Sets RS-232 buffers, top/bot Ram.
Registers In : None.
Registers Out : .A, .X, .Y destroyed.
Memory Changed: Z-Page, Rs-232 buffers, top/bot Ram ptrs
$FF8D VECTOR Copies / Stores KERNAL indirect RAM vectors.
Registers In : .C = 0 (Set KERNAL Vectors) | .C = 1 (Duplicate KERNAL vectors)
.XY = address of vectors | .XY = address of user vectors
Registers Out : .A, .Y destroyed | .A, .Y destroyed.
Memory Changed: KERNAL Vectors changed | Vectors written to .XY
Note : This routine is rarely used, usually the vectors are directly
changed themselves. The vectors, in order, are :
C128: IRQ,BRK,NMI,OPEN,CLOSE,CHKIN,CHKOUT,CLRCH,BASIN,BSOUT
STOP,GETIN,CLALL,EXMON (monitor),LOAD,SAVE
C64 : IRQ,BRK,NMI,OPEN,CLOSE,CHKIN,CHKOUT,CLRCH,BASIN,BSOUT
STOP,GETIN,CLALL,USRCMD (not used),LOAD,SAVE
$FF90 SETMSG Set control of KERNAL control and error messages.
Registers In : .A bit 7 = KERNAL Control Messages (1 = on)
bit 6 = KERNAL Error Messages (1 = on)
Registers Out : None.
Note : KERNAL Control messages are those defined as Loading, Found etc
... KERNAL Error messages are I/O ERROR # messages which are
listed as follows:
$FF93 SECND Sends secondary address to device after a LISTN
Registers In : .A = secondary address
Registers Out : .A used.
Memory Changed: None.
Note : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
$FF96 TKSA Sends secondary address to device after TALK
Registers In : .A = secondary address.
Registers Out : .A used.
Memory Changed: None.
Note : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
$FF99 MEMTOP Read or Set top of System Ram
Registers In : .C = 1 (Read MemTop) | .C = 0 (Set MemTop)
| .XY = top of memory
Registers Out : .XY = top of memory | None.
Memory Changed: None. | Top of memory changed.
Note : On the C=128, this routine refers to the top of BANK 0 RAM, not
BANK 1 RAM.
$FF9C MEMBOT Read or Set bottom of System Ram
Registers In : .C = 1 (Read MemBot) | .C = 0 (Set MemBot)
| .XY = bottom of memory.
Registers Out : .XY = bottom of memory | None.
Memory Changed: None. | Bottom of Memory changed.
Note : On the C=128, this routine refers to the bottom of BANK 0 RAM,
not, BANK 1 RAM.
$FF9F KEY Scans Keyboard
Registers In : None.
Registers Out : None.
Memory Changed: Relevant System Keyboard Values
$FFA2 SETMO
This is a routine who's code never made it into any versions
of the KERNAL on the C64, Vic-20 and C128. Thus it is of no
pratical use.
$FFA5 ACPTR Get byte from current talker.
Registers In : None.
Registers Out : .A = data byte.
Memory Changed: None.
Note : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
$FFA8 CIOUT Output byte to current listener.
Registers In : .A = byte.
Registers Out : .A used.
Memory Changed: None.
Note : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
$FFAB UNTLK Commands current TALK device to stop TALKING.
Registers In : None.
Registers Out : .A used.
Memory Changed: None.
Note : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
$FFAE UNLSN Commands current listening device to stop listening.
Registers In : None.
Registers Out : .A used.
Memory Changed: None.
Note : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
$FFB1 LISTN Commands device to begin listening.
Registers In : .A = device #.
Registers Out : .A used.
Note : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
$FFB4 TALK Commands device to begin talking.
Registers In : .A = device #.
Registers Out : .A used.
Memory Changed: None.
Note : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
$FFB7 READSS Return I/O status byte.
Registers In : None.
Registers Out : .A = status byte. (see section on ERROR messages).
Memory Changed: None.
$FFBA SETLFS Set logical file #, device #, secondary # for I/O.
Registers In : .A = logical file #, .X = device #, .Y = secondary #
Registers Out : None.
Memory Changed: None.
$FFBD SETNAM Sets pointer to filename in preperation for OPEN.
Registers In : .A = string length, .XY = string address.
Registers Out : None.
Memory Changed: None.
Note : To specify _no_ filename specify a length of 0.
$FFC0 OPEN Open up file that has been setup by SETNAM,SETLFS
Registers In : None.
Registers Out : .A = error code, .X,.Y destroyed.
.C = 1 if error.
Memory Changed: None.
$FFC3 CLOSE Close a logical file.
Registers In : .A = logical file #.
Registers Out : .A = error code, .X,.Y destroyed.
.C = 1 if error
Memory Changed: None.
$FFC6 CHKIN Sets input channel.
Registers In : .X = logical file #.
Registers Out : .A = error code, .X,.Y destroyed.
.C = 1 if error
Memory Changed: None.
$FFC9 CHKOUT Sets output channel.
Registers In : .X = logical file #.
Registers Out : .A = error code, .X,.Y destroyed.
.C = 1 if error
Memory Changed: None.
$FFCC CLRCH Restore default input and output channels.
Registers In : None.
Registers Out : .A, .X used.
Memory Changed: None.
$FFCF BASIN Read character from current input channel.
Cassette - Returned one character a time from cassette buffer.
Rs-232 - Return one character at a time, waiting until
character is ready.
Serial - Returned one character at time, waiting if nessc.
Screen - Read from current cursor position.
Keyboard - Read characters as a string, then return them
individually upon each call until all characters
have been passed ($0d is the EOL).
Registers In : None.
Registers Out : .A = character or error code, .C = 1 if error.
Memory Changed: None.
$FFD2 BSOUT Output byte to current channel
Registers In : .A = Byte
Registers Out : .C = 1 if ERROR (examine READST)
Memory Changed: Dependent upon current device.
$FFD5 LOAD Loads file into memory (setup via SETLFS,SETNAM)..
Registers In : .A = 0 - Load, Non-0 = Verify
.XY = load address (if secondary address = 0)
Registers Out : .A = error code .C = 1 if error.
.XY = ending address
Memory Changed: As per registers / data file.
$FFD8 SAVE Save section of memory to a file.
Registers In : .A = Z-page ptr to start adress
.XY = end address
Registers Out : .A = error code, .C = 1 if error.
.XY = used.
Memory Changed: None.
$FFDB SETTIM Set internal clock (TI$).
Registers In : .AXY - Clock value in jiffies (1/60 secs).
Registers Out : None.
Memory Changed: Relevant system time locations set.
$FFDE RDTIM Reads internal clock (TI$)
Registers In : None.
Registers Out : .AXY - Clock value in jiffies (1/60 secs).
Memory Changed: None.
$FFE1 STOP Scans STOP key.
Registers In : None.
Registers Out : .A = last keyboard row, .X = destroyed (if stop key)
Memory Changed: None.
Note : The last keyboard row is as follows:
.A -> | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
KEY: |STOP |Q |C= |SPACE|2 |CTRL |<- |1
$FFE4 GETIN Read buffered data from file.
Keyboard - Read from keyboard buffer, else return null ($00).
Rs-232 - Read from Rs-232 buffer, else null is returned.
Serial - See BASIN
Cassette - See BASIN
Screen - See BASIN
Registers In : None.
Registers Out : .A = character, .C = 1 if error.
.XY = used.
Memory Changed: None.
$FFE7 CLALL Close all open files and channels.
Registers In : None.
Registers Out : .AX used.
Memory Changed: None.
Note : This routine does not _actually_ close the files, rather it
removes their prescense from the file tables held in memory.
It's recommended to use close to close files instead of using
this routine.
$FFEA UDTIME Update internal (TI$) clock by 1 jiffie (1/60 sec).
Registers In : None.
Registers Out : .A,.X destroyed.
Memory Changed: Relevant system time locations changed.
$FFED SCRORG Returns current window/screen size
Registers In : None.
Registers Out : .X - Window Row Max
.Y - Window Col Max
.A - Screen Col Max (128 only, 64 unchanged)
Memory Changed: None
$FFF0 PLOT Read or set cursor position.
Registers In : .C = 1 (Read) | .C = 0 (Set)
None. | .X = Col
| .Y = Row
Registers Out : .C = 1 (Read) | .C = 0 (Set)
.X = Current Col | None.
.Y = Current Row |
Memory Changed: None | Screen Editor Locations.
$FFF3 IOBASE Returns base of I/O Block
Registers In : None.
Registers Out : .XY = address of I/O block ($D000)
Memory Changed: Screen Editor Locations.

1901
kernal/kernal_dh.txt Normal file

File diff suppressed because it is too large Load diff

173
kernal/kernal_fk.txt Normal file
View file

@ -0,0 +1,173 @@
-
- C64 KERNAL jump table, composed by Frank Kontros (jeno@kontr.uzhgorod.ua).
- http://www.zimmers.net/anonftp/pub/cbm/c64/programming/documents/c64-kernal.txt
-
$FF81 CINT init VIC & screen editor
- - - - - - A X Y
$FF84 IOINIT initialize CIA & IRQ
- - - - - - A X Y
$FF87 RAMTAS RAM test & search RAM end
- - - - - - A X Y
$FF8A RESTOR restore default I/O vectors
- - - - - - A - Y
$FF8D VECTOR read/set I/O vectors
in: C=0 moves from Y/X to vectors - X Y - X - A - Y
C=1 moves vectors to Y/X - X Y - X - A - Y
$FF90 SETMSG enable/disable KERNAL messages
in: A bit7=1 error msgs on A - - - - - A - -
bit6=1 control msgs on
$FF93 SECOND send secondary addr after listen
in: A=secondary address A - - - - - A - -
$FF96 TKSA send secondary addr after talk
in: A=secondary address A - - - - - A - -
$FF99 MEMTOP read/set top of memory
in: C=0; Y/X address - X Y - X Y - - -
out:C=1; Y/X address - - - - X Y - X Y
$FF9C MEMBOT read/set bottom of memory
in: C=0; Y/X address - X Y - X Y - - -
out:C=1; Y/X address - - - - X Y - X Y
$FF9F SCNKEY scan keyboard
- - - - - - A X Y
$FFA2 SETTMO set IEEE timeout
in: A bit7=1 disable, bit7=0 enable A - - A - - - - -
$FFA5 ACPTR input byte from SERIAL
out:A=byte, C=1 and ST=2 if timeout - - - A - - A - -
$FFA8 CIOUT output byte to SERIAL
in: A=byte, C=1 and ST=3 if timeout A - - A - - - - -
$FFAB UNTLK untalk all SERIAL devices
- - - - - - A - -
$FFAE UNLSN unlisten all SERIAL devices
- - - - - - A - -
$FFB1 LISTEN make SERIAL device listen
in: A=device number A - - - - - A - -
$FFB4 TALK make SERIAL device talk
in: A=device number A - - - - - A - -
$FFB7 READST read I/O status byte
out:A=status byte - - - A - - A - -
$FFBA SETLFS set file parameters
in: A=logical file number A X Y A X Y - - -
X=device number
Y=secondary addr
$FFBD SETNAM set file name
in: A=length of filename A X Y A X Y - - -
Y/X=pointer to name addr
$FFC0 OPEN open log.file after SETLFS,SETNAM
out:A=error# if C=1 - - - - - - A X Y
$FFC3 CLOSE close a logical file
in: A=logical file number A - - - - - A X Y
$FFC6 CHKIN open channel for input
in: X=logical file number - X - - - - A X -
$FFC9 CHKOUT open channel for output
in: X=logical file number - X - - - - A X -
$FFCC CLRCHN restore default devices
- - - - - - A X -
$FFCF CHRIN input character
out:A=character, C=1 and ST=error - - - A - - A - -
$FFD2 CHROUT output character
in: A=character, C=1 and ST=error A - - A - - - - -
$FFD5 LOAD load after call SETLFS,SETNAM
in: A=0 load, a=1 verify A X Y A X Y A X Y
Y/X = dest.addr if sec.addr=0
$FFD8 SAVE save after call SETLFS,SETNAM
in: A=zero page pointer to start.addr A X Y - - - A X Y
Y/X=ending address
$FFDB SETTIM set jiffy clock
in: A=MSB, X=middle, Y=LSB A X Y - - - - - -
$FFDE RDTIM read jiffy clock
out:A=MSB, X=middle, Y=LSB - - - A X Y A X Y
$FFE1 STOP check stop key
out:Z=0 if STOP not used; X unchanged - - - A - - A - -
Z=1 if STOP used; X changed - - - A - - A X -
A=last line of keyboard matrix
$FFE4 GETIN get a byte from channel
out:keyboard:A=0 if puffer empty - - - A - - A X Y
RS232:status byte - - - A - - A - -
serial:status byte - - - A - - A - -
tape:status byte - - - A - - A - Y
$FFE7 CLALL close or abort all files
- - - - - - A X -
$FFEA UDTIM update jiffy clock
- - - - - - A X -
$FFED SCREEN return screen size
out:X=columns, Y=rows - - - - X Y - X Y
$FFF0 PLOT read/set cursor position
in: C=0, X=row, Y=column - X Y - X Y - - -
out:C=1, X=row, Y=column - - - - X Y - X Y
$FFF3 IOBASE returns the addr of I/O devices
out:Y/X=addr($DC00) - - - - X Y - X Y

416
kernal/kernal_ld.txt Normal file
View file

@ -0,0 +1,416 @@
-
- The almost completely commented C64 ROM disassembly. V1.01 Lee Davison 2012
-
$FF81 initialise VIC and screen editor
$FF84 initialise SID, CIA and IRQ, unused
$FF87 RAM test and find RAM end
$FF8A restore default I/O vectors
This routine restores the default values of all system vectors used in KERNAL and
BASIC routines and interrupts.
$FF8D read/set vectored I/O
This routine manages all system vector jump addresses stored in RAM. Calling this
routine 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.
$FF90 control kernal messages
This 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.
$FF93 send secondary address after LISTEN
This routine is used to send a secondary address to an I/O device after a call to
the 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.
$FF96 send secondary address after TALK
This 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.
$FF99 read/set the top of memory
This routine is used to read and set the top of RAM. When this routine is called
with 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.
$FF9C read/set the bottom of memory
This routine is used to read and set the bottom of RAM. When this routine is
called 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.
$FF9F scan the keyboard
This routine will scan the keyboard and check for pressed keys. It is the same
routine called by the interrupt handler. If a key is down, its ASCII value is
placed in the keyboard queue.
$FFA2 set timeout on serial bus
This routine sets the timeout flag for the serial bus. When the timeout flag is
set, 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.
$FFA5 input byte from serial bus
This routine reads a byte of data from the serial bus using full handshaking. the
data 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.
$FFA8 output a byte to serial bus
This routine is used to send information to devices on the serial bus. A call to
this 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.
$FFAB command serial bus to UNTALK
This routine will transmit an UNTALK command on the serial bus. All devices
previously set to TALK will stop sending data when this command is received.
$FFAE command serial bus to UNLISTEN
This routine commands all devices on the serial bus to stop receiving data from
the 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.
$FFB1 command devices on the serial bus to LISTEN
This routine will command a device on the serial bus to receive data. The
accumulator 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.
$FFB4 command serial bus device to TALK
To use this routine the accumulator must first be loaded with a device number
between 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.
$FFB7 read I/O status word
This routine returns the current status of the I/O device in the accumulator. The
routine 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.
$FFBA set logical, first and second addresses
This routine will set the logical file number, device address, and secondary
address, 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.
$FFBD set the filename
This 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.
$FFC0 open a logical file
This routine is used to open a logical file. Once the logical file is set up it
can 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.
$FFC3 close a specified logical file
This routine is used to close a logical file after all I/O operations have been
completed 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.
$FFC6 open channel for input
Any logical file that has already been opened by the OPEN routine, $FFC0, can be
defined 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
$FFC9 open channel for output
Any logical file that has already been opened by the OPEN routine, $FFC0, can be
defined 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
$FFCC close input and output channels
This routine is called to clear all open channels and restore the I/O channels to
their 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.
$FFCF input character from channel
This routine will get a byte of data from the channel already set up as the input
channel 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.
$FFD2 output character to channel
This routine will output a character to an already opened channel. Use the OPEN
routine, $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.
$FFD5 load RAM from a device
This routine will load data bytes from any input device directly into the memory
of 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.
$FFD8 save RAM to a device
This routine saves a section of memory. Memory is saved from an indirect address
on 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.
$FFDB set the real time clock
The system clock is maintained by an interrupt routine that updates the clock
every 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.
$FFDE read the real time clock
This routine returns the time, in jiffies, in AXY. The accumulator contains the
most significant byte.
$FFE1 scan the stop key
If the STOP key on the keyboard is pressed when this routine is called the Z flag
will 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.
$FFE4 get character from input device
In 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.
$FFE7 close all channels and files
This routine closes all open files. When this routine is called, the pointers into
the open file table are reset, closing all files. Also the routine automatically
resets the I/O channels.
$FFEA increment real time clock
This routine updates the system clock. Normally this routine is called by the
normal 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.
$FFED return X,Y organization of screen
This routine returns the x,y organisation of the screen in X,Y
$FFF0 read/set X,Y cursor position
This routine, when called with the carry flag set, loads the current position of
the 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.
$FFF3 return the base address of the I/O devices
This routine will set XY to the address of the memory section where the memory
mapped 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.

438
kernal/kernal_mapc64.txt Normal file
View file

@ -0,0 +1,438 @@
$FF81 CINT Initialize Screen Editor and VIC-II Chip
The start of the routine appears to be a patch that was added to later
versions of the Kernal. It first calls the old routine at 58648
($E518). This initializes the VIC-II chip to the default values, sets
the keyboard as the input device and the screen as the output device,
initializes the cursor flash variables, builds the screen line link
table, clears the screen, and homes the cursor. The new code then
checks the VIC Interrupt register to see if the conditions for a
Raster Compare IRQ have been fulfilled. Since the Raster Register was
initialized to 311, that can only occur when using a PAL system (NTSC
screens do not have that many scan lines). The PAL/NTSC register at
678 ($2A6) is set on the basis of the outcome of this test. The CIA
#1 Timer A is then set to cause an IRQ interrupt every sixtieth of a
second, using the prescaler figures for a PAL or NTSC system, as
appropriate.
$FF84 IOINIT Initialize CIA I/O Devices
This routine intializes the Complex Interface Adapter (CIA)
devices, and turns the volume of the SID chip off. As part of this
initialization, it sets CIA #1 Timer A to cause an IRQ interrupt every
sixtieth of a second.
$FF87 RAMTAS Perform RAM Test and Set Pointers to the Top and Bottom of RAM
This routine performs a number of initialization tasks.
First, it clears Pages 0, 2, and 3 of memory to zeros. Next, it sets
the tape buffer pointer to address 828 ($33C), and performs a
nondestructive test of RAM from 1024 ($400) up. When it reaches a
non-RAM address (presumably the BASIC ROM at 40960 ($A000)), that
address is placed in the top of memory pointer at 643-4 ($283-4). The
bottom of memory pointer at 641-2 ($281-2) is set to point to address
2048 ($800), which is the beginning of BASIC program text. Finally,
the pointer to screen memory at 648 ($288) is set to 4, which lets the
Operating System know that screen memory starts at 1024 ($400).
$FF8A RESTOR Restore RAM Vectors for Default I/O Routines
This routine sets the values for the 16 RAM vectors to the interrupt and
important Kernal I/O routines in the table that starts at 788 ($314)
to the standard values held in the ROM table at 64816 ($FD30).
$FF8D VECTOR Set the RAM Vector Table from the Table Pointed to by .X and .Y
This routine is used to read or change the values for the 16 RAM vectors to the
interrupt and important Kernal I/O routines in the table that starts
at 788 ($314). If the Carry flag is set when the routine is called,
the current value of the 16 vectors will be stored at a table whose
address is pointed to by the values in the .X and .Y registers. If
the Carry flag is cleared, the RAM vectors will be loaded from the
table whose address is pointed to by the .X and .Y registers. Since
this routine can change the vectors for the IRQ and NMI interrupts,
you might expect that the Interrupt disable flag would be set at its
beginning. Such is not the case, however, and therefore it would be
wise to execute an SEI before calling it and a CLI afterwards (as the
power-on RESET routine does) just to be safe.
$FF90 SETMSG Set the Message Control Flag
This routine controls the printing of error messages and control
messages by the Kernal. It Bit 6 is seto to 1 (bit value of 64),
Kernal control messages can be printed. These messages include
SEARCHING FOR, LOADING, and the like. If Bit 6 is cleared to 0, these
messages will not be printed (BASIC will clear this bit when a program
is running so that the messages do not appear when I/O is performed
from a program). Setting Bit 6 will not suppress the PRESS PLAY ON
TAPE or PRESS PLAY & RECORD messages, however.
If Bit 7 is set to 1 (bit value of 128), Kernal error messages can be
printed. If Bit 7 is set to 0, those error messages (for example, I/O
ERROR #nn) will be suppressed. Note that BASIC has its own set of
error messages (such as FILE NOT FOUND ERROR) which it uses in
preference to the Kernal's message.
$FF93 SECOND Send a Secondary Address to a Device on the Serial Bus after LISTEN
This routine sends a secondary address from the
Accumulator to the device on the serial bus that has just been
commanded to LISTEN. This is usually done to give the device more
particular instructions on how the I/O is to be carried out before
information is sent.
$FF96 TKSA Send a Secondary Address to a Device on the Serial Bus after TALK
This routine sends a secondary address from the
Accumulator to the device on the serial bus that has just been
commanded to TALK. This is usually done to give the device more
particular instructions on how the I/O is to be carried out before
information is sent.
$FF99 MEMTOP Read/Set Top of RAM Pointer
This routine can be used to either read or set the top of RAM pointer. If
called with the Carry flag set, the address in the pointer will be
loaded into the .X and .Y registers. If called with the Carry flag
cleared, the pointer will be changed to the address found in the .X
and .Y registers.
$FF9C MEMBOT Read/Set Bottom of RAM Pointer
This routine can be used to either read or set the bottom of RAM pointer. If
called with the Carry flag set, the address in the pointer willbe
loaded into the .X and .Y registers. If called with the Carry flag
cleared, the pointer will be changed to the address found in the .X
and .Y registers.
$FF9F SCNKEY Read the Keyboard
This subroutine is called by the IRQ interrupt handler above to read
the keyboard device which is connected to CIA #1 (see entry for 56320
($DC00) for details on how to read the keyboard).
This routine returns the keycode of the key
currently being pressed in 203 ($CB), sets the shift/control flag if
appropriate, and jumps through the vector at 655 ($28F) to the routine
that sets up the proper table to translate the keycode to PETASCII.
It concludes with the next routine, which places the PETASCII value of
the character in the keyboard buffer.
$FFA2 SETTMO Set Time-Out Flag for IEEE Bus
This routine sets the time-out flag for the IEEE bus. When timeouts
are enabled, the Commodore will wait for a device for 64 milliseconds,
and if it does not receive a response to its signal it will issue a
time-out error. Loading the Accumulator with a value less than 128
and calling this routine will enable time-outs, while using a value
over 128 will disable time-outs.
This routine is for use only with the Commodore IEEE add-on card,
which at the time of this writing was not yet available.
$FFA5 ACPTR Receive a Byte of Data from a Device on the Serial Bus
When called, this routine will get a byte of data from
the current TALKer on the serial bus and store it in the Accumulator.
In order to receive the data, the device must have previously been
sent a command to TALK and a secondary address if it needs one.
$FFA8 CIOUT Send a Byte to an I/O Device over the Serial Bus
This routine's purpose is to send a byte of data over
the serial bus. In order for the data to be received, the serial
device must have first been commanded to LISTEN and been given a
secondary address if necessary. This routine always buffers the
current character, and defers sending it until the next byte is
buffered. When the UNLISTEN command is sent, the last byte will be
sent with an End or Identify (EOI).
$FFAB UNTLK Send UNTALK to a Device on the Serial Bus
When called, this routine sends the UNTALK code (95, $5F) on the
serial bus. This commands any TALKer on the bus to stop sending data.
$FFAE UNLSN Send UNLISTED to a Device on the Serial Bus
This routine sends the UNLISTEN code (63, $3F) on the serial
bus. This commands any LISTENers to get off the serial bus, and frees
up the bus for other users.
$FFB1 LISTEN Send LISTEN to a Device on the Serial Bus
When called, this routine ORs the device number in the
Accumulator with the LISTEN code (32, $20) and sends it on the serial
bus. This commands the device to LISTEN.
$FFB4 TALK Send TALK to a Device on the Serial Bus
When called, this routine ORs the device number in the
Accumulator with the TALK code (64, $40) and sends it on the serial
bus. This commands the device to TALK.
$FFB7 READST Read the I/O Status Word
Whenever an I/O error occurs, a bit of the Status Word is set to
indicate what the problem was. This routine allows you to read the
status word (it is returned in the Accumulator). If the device was
the RS-232, its status register is read and cleared to zero. For the
meanings of the various status codes, see the entry for location 144
($90) or 663 ($297) for the RS-232 device.
$FFBA SETLFS Set Logical File Number, Device Number, and Secondary Address
This routine stores the value in the Accumulator in the location which holds the
current logical file number, the value in the .X register is put in
the location that holds the current device number, and the value in
the .Y register is stored in the location that holds the current
secondary address. If no secondary address is used, the .Y register
should be set to 255 ($FF). It is necessary to set the values of the
current file number, device number, and secondary address before you
OPEN a file, or LOAD or SAVE.
$FFBD SETNAM Set Filename Parameters
This routine puts the value in the Accumulator into the location which stores
the number of characters in the filename, and sets the pointer to the
address of the ASCII text of the filename from the .X and .Y
registers. This sets up the filename for the OPEN, LOAD, or SAVE
routine.
$FFC0 OPEN Open a Logical I/O File
The routine jumps through a RAM vector at 794 ($31A). This routine
assigns a logical file to a device, so that it can be used for
Input/Output operations. In order to specify the logical file number,
the device number, and the secondary address if any, the SETLFS
routine must first be called. Likewise, in order to designate the
filename, the SETNAM routine must be used first. After these two
routines are called, OPEN is then called.
$FFC3 CLOSE Close a Logical I/O File
The routine jumps through a RAM vector at 796 ($31C). It is used to
close a logical file after all I/O operations involving that file have
been completed. This is accomplished by loading the Accumulator with
the logical file number of the file to be closed, and calling this
routine.
Closing an RS-232 file will de-allocate space at the top of memory for
the receiving and trasmit buffers. Closing a cassette file that was
opened for writing will force the last block to be written to
cassette, even if it is not a full 192 bytes. Closing a serial bus
device will send an UNLISTEN command on the bus. Remember, it is
necessary to properly CLOSE a cassette or disk data file in order to
retrieve the file later.
For all types of files, CLOSE removes the file's entry from the tables
of logical files, device, and secondary address at 601, 611, and 621
($259, $263, $26D), and moves all higher entries in the table down one
space.
$FFC6 CHKIN Designate a Logical File As the Current Input Channel
The routine jumps through a RAM vector at 798 ($31E). If you wish to
get data from any device other than the keyboard, this routine must be
called after OPENing the device, before you can get a data byte with
the CHRIN or GETIN routine. When called, the routine will designate
the logical file whose file number is in the .X register as the
current file, its device as the current device, and its secondary
address as the current secondary address. If the device on the
channel is a serial device, which requires a TALK command and
sometimes a secondary address, this routine will send them over the
serial bus.
$FFC9 CHKOUT Designate a Logical File As the Current Output Channel
The routine jumps through a RAM vector at 800 ($320). If you wish to
output data to any device other than the screen, this routine must be
called after OPENing the device, and before you output a data byte
with the CHROUT routine. When called, the routine will designate the
logical file whose file number is in the .X register as the current
file, its device as the current device, and its secondary address as
the current secondary address. If the device on the channel uses the
serial bus, and therefore requires a LISTEN command and possibly a
secondary address, this information will be sent on the bus.
$FFCC CLRCHN Restore Current Input and Output Devices to the Default Devices
The routine jumps through a RAM vector at 802 ($322). It sets the
current input device to the keyboard, and the current output device to
the screen. Also, if the current input device was formerly a serial
device, the routine sends it an UNTALK command on the serial bus, and
if a serial device was formerly the current output device, the routine
sends it an UNLISTEN command.
$FFCF CHRIN Input a Character from the Current Device
The routine jumps through a RAM vector at 804 ($324). Its function is
to get a character from the current input device (whose device number
is stored at 153 ($99)). This device must first have been OPENed and
then designated as the input channel by the CHKIN routine.
When this routine is called, the next byte of data available from this
device is returned in the Accumulator. The only exception is the
routine for the keyboard device (which is the default input device).
It the keyboard is the current input device, this routine blinks the
cursor, fetches characters from the keyboard buffer, and echoes them
to the screen until a carriage return is encountered. When a carriage
return is round, the routine sets a flag to indicate the length of the
last logical line before the return character, and reads the first
character of this logical line from the screen.
Subsequent calls to this routine will cause the next character in the
line to be read from the screen and returned in the Accumulator, until
the carriage return character is returned to indicate the end of the
line. Any call after this character is received will start the whole
process over again.
Note that only the last logical line before the carriage return is
used. Any time you type in more than 80 characters, a new logical
line is started. This routine will ignore any characters on the old
logical line, and process only the most recent 80-character group.
$FFD2 CHROUT Output a Byte
The routine jumps through a RAM vector at 806 ($326).
It is probably one of the best known and most used Kernal routines,
because it sends the character in the Accumulator to the current
output device. Unless a device has been OPENed and designated as the
current output channel using the CHKOUT routine, the character is
printed to the screen, which is the default output device. If the
cassette is the current device, outputting a byte will only add it to
the buffer. No actual transmission of data will occur until the
192-byte buffer is full.
$FFD5 LOAD Load RAM from a Device
The routine jumps through a RAM vector at 816 ($330). LOAD is used to
transfer data froma device directly to RAM. It can also be used to
verify RAM, comparing its contents to those of a disk or tape file.
To choose between these operations you must set the Accumulator with a
0 for LOAD, or a 1 for VERIFY.
Since the LOAD routine performs an OPEN, it must be preceded by a call
to the SETLFS routine to specify the logical file number, device
number, and secondary address, and a call to the SETNAM routine to
specify the filename (a LOAD from tape can be performed without a
filename being specified). Then the .X and .Y registers should be set
with the starting address for the load, and the LOAD routine called.
If the secondary address specified was a 1, this starting address will
be ignored, and the header information will be used to supply the load
address. If the secondary address was a 0, the address supplied by
the call will be used. In either case, upon return from the
subroutine, the .X and .Y registers will contain the address of the
highest RAM location that was loaded.
$FFD8 SAVE Save RAM to a Device
The routine jumps through a RAM vector at 818 ($332). SAVE is used to
transfer data directly from RAM to an I/O device. Since the SAVE
routine performs an OPEN, it must be preceded by a call to the SETLFS
routine to specify the logical file number, device number, and
secondary address, and a call to the SETNAM routine to specify the
filename (although a SAVE to the cassette can be performed without
giving a filename). A Page 0 pointer to the starting address of the
area to be saved should be set up, with the low byte of the address
first. The accumulator should be loaded with the Page 0 offset of
that pointer, then the .X and .Y registers should be set with the
ending address for the save, and the SAVE routine called.
$FFDB SETTIM Set the Software Clock from the .A, .X, and .Y Registers
This routine performs the reverse operation from RDTIM, storing the value in the
.Y register into location 160 ($A0), the .X register into 161 ($A1),
and the Accumulator into 162 ($A2). Interrupts are first disabled, to
make sure that the clock will not be updated while being set.
$FFDE RDTIM Read the Time From the Software Clock into the .A, .X, and .Y Registers
It reads the software clock (which counts sixtieths of a second) into
the internal registers. The .Y register contains the most significant
byte (from location 160 ($A0)), the .X register contains the middle
byte (from location 161 ($A1)), and the Accumulator contains the least
significant byte (from location 162 ($A2)).
$FFE1 STOP Test STOP Key
This routine is vectored through RAM at 808 ($328). The routine checks to see
if the STOP key was pressed during the last UDTIM call. If it was,
the Zero flag is set to 1, the CLRCHN routine is called to set the
input and output devices back to the keyboard and screen, and the
keyboard queue is emptied.
$FFE4 GETIN Get One Byte from the Input Device
The routine jumps through a RAM vector at 810 ($32A).
Its function is to get a character from the current input device
(whose device number is stored at 153 ($99)). In practive, it
operates identically to the CHRIN routine below for all devices except
for the keyboard. If the keyboard is the current input device, this
routine gets one character from the keyboard buffer at 631 ($277). It
depends on the IRQ interrupt routine to rad the keyboard and put
characters into the buffer.
$FFE7 CLALL Close All Logical I/O Files
The routine jumps through a RAM vector at 812 ($32C). It closes all
open files, by resetting the index into open files at 152 ($98) to
zero. It then falls through to the next routine, which restores the
default I/O devices.
$FFEA UDTIM Update the Software Clock and Check for the STOP Key
This routine is normally called by the IRQ interrupt handler once every sixtieth
of a second. It adds one to the value in the three-byte software
jiffy clock at 160-162 ($A0-$A2), and sets the clock back to zero when
it reaches the 24 hour point. In addition, it scans the keyboard row
in which the STOP key is located, and stores the current value of that
key in location 145 ($91). This variable is used by the STOP routine
which checks for the STOP key.
$FFED SCREEN Store Number of Screen Rows and Columns in .Y and .X
When called, this subroutine returns the number of screen columns in
the .X register, and the number of screen rows in .Y. Thus, a program
can detect the screen format of the machine on which it is running,
and make sure that text output is formatted accordingly.
The present version of this routine loads the .X register with 40
($28) and the .Y register with 25 ($19).
$FFF0 PLOT Read/Set Location of the Cursor
The routine allows the user to read or set the position of the cursor.
If the carry flag is set with the SEC instruction before calling this
subroutine, cursor column (X position) will be returned in the .X
register, and the cursor row (Y position) will be returned in the .Y
register. If the carry flag is cleared with a CLC instruction before
entering this routine, and the .Y and .X registers are loaded with the
desired row and column positions respectively, this routine will set
the cursor position accordingly.
The current read routine loads .X and .Y from locations 214 ($D6) and
211 ($D3) respectively. The cursor set routine stores .X and .Y in
these locations, and calls the routine that sets the screen pointers
at 58732 ($E56C).
The user can access this routine from BASIC by loading the .X, .Y, and
.P register values desired to the save area starting at 780 ($30C).
$FFF3 IOBASE Store Base Address of Memory-Mapped I/O Devices in .X and .Y Registers
When called, this routine sets the .X register to the low byte of the
base address of the memory-mapped I/O devices, and puts the high byte
in the .Y register. This allows a user to set up a zero-page pointer
to the device, and to load and store indirectly through that pointer.
A program which uses this method, rather than directly accessing such
devices could be made to function without change on future Commodore
models, even though the I/O chips may be addressed at different
locations. This of course assumes that the CIA or a similar chip will
be used. This routine is of limited value for creating software that
is compatible with both the VIC-20 and the 64 because of the
differences in the VIA I/O chip that the VIC uses.
The current version of this routine loads the .X register with a 0,
and the .Y register with 220 ($DC), thus pointing to CIA #1, which is
at 56320 ($DC00).

939
kernal/kernal_mlr.txt Normal file
View file

@ -0,0 +1,939 @@
-
- Heimarck, Todd D; Parrish, Patrick:
- Machine language routines for the Commodore 64 and 128
-
$FFA5 ACPTR
This low-level I/O routine retrieves a byte from a serial device
without checking for a previous I/O error. If the operation is
successful, the accumulator will hold the byte received from
the device. The contents of .X and .Y are preserved. The suc-
cess of the operation will be indicated by the value in the se-
rial status flag upon return. (See READST for details.)
For the routine to function properly, the serial device
must currently be a talker on the serial bus, which requires a
number of setup steps. Generally, it's preferable to use the
higher-level CHRFN routine instead.
$FFC6 CHKIN
This routine specifies a logical file as the source of input in
preparation for using the CHRIN or GETIN routines. The logi-
cal file should be opened before this routine is called. (See the
OPEN routine.) The desired logical file number should be in
.X when this routine is called. The contents of .Y are un-
affected, but the accumulator value will be changed.
The routine sets the input channel (location $99) to the
device number for the specified file. If the device is RS-232
(device number 2), the CTA #2 interrupts for RS-232 reception
are enabled. Ef a serial device (device number 4 or greater) was
specified, the device is made a talker on the serial bus,
If the file is successfully set for input, the status-register
carry bit will be clear upon return. If carry is set, the operation
was unsuccessful and the accumulator will contain a Kernal
error-code value indicating which error occurred. Possible er-
ror codes include 3 (fiLe was not open), 5 (device did not re-
spond), and 6 (file was not opened for input). The RS-232 and
serial status-flag locations also reflect the success of operations
for those devices. (See READST for details.)
The JMP to the CEDGN execution routine is by way of the
ICHKDN indirect vector at 798-799 ($031E-$031F). You can
modify the actions of CHfQN by changing the vector to point
to a routine of your own.
$FFC9 CHKOUT
This routine (some Commodore references call it CKOUT)
specifies a logical file as the recipient of output in preparation
for using the CHROUT routine. The logical file should be
opened before this routine is called. (See the OPEN routine.)
The desired logical file number should be in .X when this rou-
tine is called. The contents of .Y are unaffected, but the accu-
mulator will be changed.
The routine sets the output channel (location $9A) to the
device number for the specified file. If the device is RS-232
(device number 2), the routine also enables the CLA #2 inter-
rupts for RS-232 transmission. fi a serial device (device num-
ber 4 or greater) is specified, the device is also made a listener
on the serial bus.
If the file is successfully set for output, the status-register
carry bit will be clear upon return. If the carry is set, the op-
eration was unsuccessful, and the accumulator will contain a
Kernal error-code value indicating which error occurred. Pos-
sible error codes include 3 (file was not open), 5 (device did
not respond), and 7 (file was not opened for output). The RS-
232 and serial status-flag locations also reflect the success of
operations for those devices. (See READST for details.)
The JMP to the CHKOUT execution routine is by way of
the ICKOUT indirect vector at $0320-$0321. You can modify
the actions of the routine by changing the vector to point to a
routine of your own.
$FFCF CHRIN
This high-level I/O routine (some Commodore references may
call it BASIN) receives a byte from the logical file currently
specified for input (to change the default input device, see
CHKIN above). Except to use the routine to retrieve input
from the keyboard when the system is set for default I/O, you
must open a logical file to the desired device and specify the
file as the input source before calling this routine. (See the
OPEN and CHKIN routines.)
For keyboard input (device 0), the routine accepts
keypresses until RETURN is pressed, and then returns charac-
ters from the input string one at a time on each subsequent
call. The character code for RETURN, 13, is returned when the
end of an input string is reached. (The Kernal GETIN routine
is better for retrieving individual keypresses.)
For tape (device 1), the routine retrieves the next character
from the cassette buffer. If all characters have been read from
the buffer, the next data block is read from tape into the
buffer.
For RS-232 (device 2), the routine returns the next avail-
able character from the RS-232 input buffer. If the buffer is
empty, the routine waits until a character is received—unless
the RS-232 status flag indicates that the DSR signal from the
external device is missing, in which case a RETURN character
code, 13, is returned.
CHRIN from the screen (device 3) retrieves characters one
at a time from the current screen line, ending with a RETURN
character code when the last nonspace character on the logical
line is reached. (Note that CHRIN from the screen does not
work properly in the original version of the 128 Kernal.) For
serial devices (device numbers 4 and higher), the routine re-
turns the next available character from the serial bus, unless
the serial status flag contains a nonzero value. In that case, the
RETURN character code is returned.
For all input devices, the received byte will be in the
accumulator upon return. The contents of .X and .Y are pre-
served during input from the keyboard, screen, or RS-232. For
input from tape, only .X is preserved. For input from serial de-
vices, only .Y is preserved. For input from the screen, key-
board, or serial devices, the status-register carry bit will always
be clear upon return. For tape input, the carry bit will be clear
unless the operation was aborted by pressing the RUN/STOP
key. For tape, serial, or RS-232 input, the success of the opera-
tion will be indicated by the value in the status-flag location.
(See the entry for READST.) The RS-232 portion of the orig-
inal 128 version of CHRRsJ has a bug: The carry bit will be set
if a byte was successfully received, and will be clear only if
the DSR signal is missing—the opposite of the settings for the
64. It's better to judge the success of an RS-232 operation by
the value in the status-flag location rather than by the carry-
bit setting. (See the READST routine.)
TheJMP to the CHREN execution routine is by way of the
ICHRfN indirect vector at $0324-$0325. You can modify the
actions of the routine by changing the vector to point to a rou-
tine of your own.
$FFD2 CHROUT
This routine (some Commodore references call it BSOUT)
sends a byte to the logical file currently specified for output.
Except to send output to the screen when the system is set for
default I/O, you must open a logical file to the desired device
and specify the file as the output target before calling this rou-
tine. (See the OPEN and CHKOUT routines.)
For output to tape (device 1), the character is stored at the
next available position in the cassette buffer. When the buffer
is full, the data block is written to tape.
For output to RS-232 (device 2), the character is stored in
the next available position in the RS-232 output buffer, if the
buffer is full, the routine waits until a character is sent.
For output to the screen (device 3), the character is
printed at the current cursor position. For serial devices (device
numbers 4 and higher), the CIOUT routine is called.
Regardless of the output device, the contents of the accu-
mulator, .X, and .Y are preserved during this routine. The
status-register carry bit will always be clear upon return, un-
less output to tape is aborted by pressing the RUN/STOP key.
(In that case, the accumulator will also be set to 0, setting the
status-register Z bit as well.) For tape, serial, or RS-232 output,
the success of the operation will be indicated by the value in
the status flag. (See READST for details.)
The JMP to the CHROUT execution routine is by way of
the ICHROUT indirect vector at $0326-$0327. You can modify
the actions of the routine by changing the vector to point to a
routine of your own.
$FF81 CINT
This routine initializes all RAM locations used by the screen
editor, returning screen memory to its default position and set-
ting default screen and border colors. The routine also clears
the screen and homes the cursor. All processor registers are
affected.
For the 64 only, this routine initializes all VIC chip reg-
isters to their default values (that's done during the Kernal
IOINIT routine in the 128). For the 128, CINT clears both dis-
plays and redirects printing to the display indicated by the po-
sition of the 40/80 DISPLAY key. The 128 routine also sets
SID volume to zero and resets programmable function keys to
their default definitions. It does not, however, reinitialize the
80-column character set. (That's also part of IOINIT.)
$FFA8 CIOUT
This low-level I/O routine sends a byte to a serial device. The
accumulator should hold the byte to be sent. All register val-
ues are preserved. The success of the operation will be in-
dicated by the value in the serial status flag. (See READST for
details.)
For the routine to function properly, the target serial de-
vice must currently he a listener on the serial bus, which re-
quires a number of setup steps. However, if you have already
performed all the preparatory steps necessary for CHROUT to
a serial device, then you can freely substitute CIOUT for
CHROUT, since, for a serial device, CHROUT simply jumps to
the CIOUT routine.
$FFE7 CLALL
This routine resets the number of open files (location $98) to
zero, then falls through into the CLRCH routine to reset de-
fault t/O. The contents of .A and .X are changed, but .Y is
unaffected.
Despite its name, the routine doesn't actually close any
files that may be open to tape, disk, or RS-232 devices. Un-
closed files may cause problems, particularly on disks, so this
routine is of limited usefulness. The 128 Kernal provides an
alternate routine that does properly close all files open to a se-
rial device. (See CLOSE_ALL.)
The JMP to the CLALL execution routine is by way of the
JCLALL indirect vector at $032C-$032D. You can modify the
actions of the routine by changing the vector to point to a rou-
tine of your own.
$FFC3 CLOSE
This routine closes a specified logical file. Call the routine with
the accumulator holding the number of the logical file to be
closed. If no file with the specified logical file number is cur-
rently open, no action is taken and no error is indicated. If a
file with the specified number is open, its entry in the logical
file number, device number, and secondary address tables will
be removed. For RS-232 files, the driving CLA #2 interrupts will
also be disabled. For tape files, the final block of data will be
written to tape (followed by an end-of-tape marker, if one was
specified). For disk files, the EOI sequence will be performed.
The 128 version of the routine offers a special close func-
tion for disk files: Ff this routine is called with the status-
register carry bit set, and if the device number for the file is 8
or greater, and if the file was opened with a secondary address
of 15, then the EOI sequence is skipped. (The table entries for
the file are deleted, but that's all.) This solves a problem in
earlier versions of the Kernal for disk files opened with a
secondary address of 15, the command channel to the drive.
An attempt to close the command channel will result in an
EOI sequence that closes all files currently open to the drive,
not just the command-channel file, This special mode allows
the command-channel file to be closed without disturbing
other files that may be open to the drive.
The JMP to the CLOSE execution routine is by way of the
ICLOSE indirect vector at $031C-$031D. You can modify the
actions of the routine by changing the vector to point to a rou-
tine of your own.
$FFCC CLRCHN
This routine restores the default I/O sources for the operating
system. The output channel (location $9A) is reset to device 3,
the video display. (If the previous output channel was a serial
device, it is sent an UNLISTEN command.) The input channel
(location $99) is reset to device 0, the keyboard, (if the pre-
vious input channel was a serial device, it is sent an UNTALK
command.) The contents of .X and .A are changed, but .Y is
unaffected.
The JMP to the CLRCHN execution routine is by way of
the lCLRCH indirect vector at $0322-$0323. You can modify
the actions of the routine by changing the vector to point to a
routine of your own.
$FFE4 GETIN
This routine retrieves a single character from the current input
device. The routine first checks to see whether the input de-
vice number is 0 (keyboard) or 2 (RS-232). If it's not either of
these, the Kernal CHRIN routine is called instead. For key-
board or RS-232, the retrieved character will be in the accu-
mulator upon return, and the status-register carry bit wall be
clear. If no character is available, the accumulator will contain
0. (CHREM, by contrast, will wait for a character.) The contents
of .Y are unaffected, but .X will be changed. For RS-232, bit 3
of the status flag will also be set if no characters are available.
(See READST for details.)
The JMP to the GETIN execution routine is by way of the
IGETIN indirect vector at $032A-$032B. You can modify the
actions of the routine by changing the vector to point to a rou-
tine of your own.
$FFF3 IOBASE
This routine returns a constant 1/0 chip base-address value in
.X (low byte) and .Y (high byte). The accumulator is un-
affected. For the 64, the value returned is $DCOO—the address
of CLA #1. For the 128, the value is $D000—the address of
the VIC chip.
$FF84 IOINIT
This routine initializes the CIA chips' registers to their default
values, along with related RAM locations. All processor reg-
isters are affected. For the 128, the routine also initiatizes the
VIC and VDC chip registers (a step which is part of the Kernal
CINT routine on the 64). In addition, the 128 routine sets all
SID chip registers to zero and calls the Kernal DLCHR routine
to initiahze the character set for the 80-column chip.
$FFB1 LISTEN
This low-level serial I/O routine sends a LISTEN command to
a specified serial device. Call the routine with the accumulator
holding the device number (4-31) of the serial device to re-
ceive the command. The contents of .A and .X will be changed;
.Y is unaffected. The success of the operation will be indicated
by the value in the serial status flag upon return. (See
READST for details.)
$FFD5 LOAD
This routine loads a program file from tape or disk into a
specified area of memory, or verifies a program file against the
contents of a specified area of memory. A number of prepara-
tory routines must be called before LOAD: SETLFS, SETNAM,
and (for the 128 only) SETBNK. See the discussions of those
routines for details.
SETLFS establishes the device number and secondary ad-
dress for the operation. fThe logical file number isn't significant
for loading or verifying.) The secondary-address value deter-
mines whether the load/verify will be absolute or relocating.
If bit 0 of the secondary address is %0 (if the value is 0 or any
even number, for example), a relocating load will be performed:
The file will be loaded starting at the address specified in .X
and .Y. If the bit is %1 (if the value is 1 or any odd number,
for example), an absolute load will be performed: The data
will be loaded starting at the address specified in the file itself.
For tape files, the secondary-address specification can be over-
ridden by the file's internal type specification. Nonrelocatable
tape program files always load at their absolute address,
regardless of the secondary address.
When calling the LOAD routine, the accumulator should
hold the operation type value (0 for a load, or any nonzero
value for a verify). If the secondary address specifies a relocat-
ing load, the starting address at which data is to be loaded
should be stored in .X (low byte) and .Y (high byte). The val-
ues of .X and .Y are irrelevant for an absolute load.
The status-register carry bit will be clear upon return if
the file was successfully loaded, or set if an error occurred or if
the RUN/STOP key was pressed to abort the load. When
carry is se t upon return, the accumulator will hold a Kernal er-
ror-code value indicating the problem. Possible error codes in-
clude 4 (file was not found), 5 (device was not present), 8 (no
name was specified for a serial load), 9 (an illegal device num-
ber was specified).
On the 128 only, the load will be aborted if it extends be-
yond address $FEFF. This prevents corruption of the MMU
configuration register at $FFQ0. Ln this case, an error code of
16 will be returned. The success of the operation will also be
indicated by the value in the tape/serial status flag. (See
READST for details.)
$FF9C MEMBOT
$FF99 MEMTOP
These routines read or set the Kernal's bottom-of-memory
pointer and top-of-memory pointer, respectively. (The bottom-
of-memory pointer is at locations $0281-$0282 for the 64 or
$0A05-$0A06 for the 128; the top-of-memory pointer is at
locations $0283-$0284 for the 64 or $0A07-$0A08 for the
128.) To read the pointer, call the routine with the carry flag
set; the pointer value will be returned in .X (low byte) and .Y
(high byte). To set the pointer, call the routine with the carry
flag clear and with .X and .Y containing the low and high
bytes, respectively, of the desired pointer value.
$FFC0 OPEN
This routine opens a logical file to a specified device in
preparation for input or output. At least one preparatory step
is required before the standard OPEN routine is called:
SETLFS must be called to establish the logical file number, de-
vice number, and secondary address, For tape (device 1), RS-
232 (device 2), or serial (device 4 or higher), SETNAM is also
required to specify the length and address of the associated
filename. Tor the 128, SETBNK must be called to establish the
bank number where the filename can he found.
It is not necessary to load any registers before calling
OPEN, and all processor register values may be changed dur-
ing the routine. The carry will be clear if the file was success-
fully opened, or it will be set if it could not be opened. When
carry is set upon return, the accumulator will hold an error
code indicating the problem. Possible error-code values in-
clude 1 (ten files—the maximum allowed—are already open),
2 (a currently open file already uses the specified logical file
number), and 5 (specified device did not respond). The RS-232
and tape/serial status flags will also reflect the success of the
operation for those devices, (See READST for details.)
On the 128, there is an exception to the carry-bit rule. Be-
cause of a bug in the 128's RS-232 OPEN routine, carry will
be set if the RS-232 device is present when x-line handshaking
is used (if the DSR line is high), or clear if the device is ab-
sent—the opposite of the proper setting.
The JMP to the OPEN execution routine is by way of the
IOPEN indirect vector $031A-$031B. You can modify the ac-
tions of the routine by changing the vector to point to a rou-
tine of your own,
$FFF0 PLOT
This routine reads or sets the cursor position on the active dis-
play, if it is called with the status-register carry bit clear, the
value in .X specifies the new cursor row (vertical position),
and the value in .Y specifies the column (horizontal position).
The carry bit will be set upon return if the specified column or
row values are beyond the right or bottom margins of the cur-
rent output window, or it will be clear if the cursor was
successfully positioned.
If the routine is called with the carry bit set, the row num-
ber for the current cursor position is returned in .X and the
current column number is returned in .Y. For the Commodore
128, the cursor position will be relative to the home position
of the current output window rather than to the upper left cor-
ner of the screen. Of course, in the case of a full-screen output
window—the default condition—the upper left comer of the
screen is the home position of the window,
$FF87 RAMTAS
This routine clears zero-page RAM (locations $02-$FF) and
initializes Kernal memory pointers in zero page. For the 64
only, the routine also clears pages 2 and 3 (locations
$0200-$03FF), tests all RAM locations from $0400 upwards
until ROM is encountered, and sets the top-of-memory
pointer. For the 128, the routine sets the BASIC restart vector
($OAOO) to point to BASIC's cold-start entry address, $4000.
$FFDE RDTIM
This routine returns the current value of the jiffy dock. The
dock value corresponds to the number of jiffies (1 /60-second
intervals) that have elapsed since the system was turned on or
reset, or the number of jiffies since midnight if the dock value
has been set. The low byte of the clock value (location $A2) is
returned in .A, the middle byte (location $A1) in .X, and the
high byte loocation $A0) in .Y.
$FFB7 READST
This routine (some Commodore references call it READSS) re-
turns the status of the most recent I/O operation. The status
value will be in the accumulator upon return; the contents of
.X and .Y are unaffected. If the current device number is 2 (in-
dicating an RS-232 operation), the status value is retrieved
from the RS-232 status flag (location $0297 for the 64 or
$0A14 for the 128), and the flag is cleared. Otherwise, the sta-
tus value is retrieved from the tape/serial status flag (location
$90). That flag is not cleared after being read.
| Bit | Value | Meaning if set Serial | Meaning if set Tape | Meaning if set RS-232 |
|-----|---------|-----------------------|---------------------------------------|--------------------------|
| 0 | 1/$01 | write timeout | | parity error |
| 1 | 2/$02 | read timeout | | framing error |
| 2 | 4/$04 | | short block | receiver buffer overflow |
| 3 | 8/$08 | | long block | receiver buffet empty |
| 4 | 16/$10 | verify mismatch | unrecoverable read or verify mismatch | CTS missing |
| | | | | |
| 5 | 32/$20 | | checksum mismatch | |
| 6 | 64/$40 | EOI (end of file) | end of file | DSR missing |
| 7 | 128/$80 | device nol present | end of tape | break |
$FF8A RESTOR
This routine resets the Kernal indirect vectors ($0314-$0333)
to their default values. All processor registers are affected.
$FFD8 SAVE
This routine saves the contents of a block of memory to disk
or tape. It could be a BASIC or ML program, but it doesn't
have to be. A number of preparatory routines must be called
first: SETLFS, SETNAM, and (for the 128 only) SETBNK. See
the discussions of those routines for details.
SETLFS establishes the device number and secondary ad-
dress for the operation. (The logical file number isn't signifi-
cant for saving.) The secondary address is irrelevant for saves
to serial devices, but for tape it specifies the header type. If bit
0 of the secondary address value is %1 (if the value is 1, for
example), the data will be stored in a nonrelocatable file—one
that will always load to the same memory address from which
it was saved. Otherwise, the data will be stored in a file that
can be loaded to another location. If bit 1 of the secondary ad-
dress is %1 (if the value is 2 or 3, for example), the file will be
followed by an end-of-tape marker.
Before calling SAVE, you must also set up a two-byte
zero-page pointer containing the starting address of the block
of memory to be saved and then store the address of the zero-
page pointer in the accumulator. The ending address (plus
one) for the save should be stored in .X (low byte) and .Y
(high byte). To save the entire contents of the desired area, it's
important to remember that .X and .Y must hold an address
that is one location beyond the desired ending address.
When the save is complete, the carry will be clear if the
file was successfully saved, or set if an error occurred (or if the
RUN/STOP key was pressed to abort the save). When carry is
set upon return, the accumulator will hold the Kernal error
code indicating the problem. Possible error-code values in-
clude 5 (serial device was not present), 8 (no name was speci-
fied for a serial save), and 9 (an illegal device number was
specified). The success of the operation will also be indicated
by the value in the tape/serial status flag. (See READST for
details.)
$FF9F SCNKEY
This routine scans the keyboard matrix to determine which
keys, if any, are currently pressed. The standard KQ service
routine calls SCNKEY, so it's not usually necessary to call it
explicitly to read the keyboard. The character code for the key
currently pressed is loaded into the keyboard buffer, from
where it can be retrieved using the Kernal GETIN routine. The
matrix code of the keypress read during this routine can also
be read in location $CB (64) or $D4 (128), and the status of
the shift keys can be read in location $028D (64) or $D3 (128).
$FFED SCREEN
This routine (Commodore 128 literature calls it SCRORG) re-
turns information on the size of the screen display. For the 64,
the routine always returns the same values—the screen width
in columns (40) in .X and the screen height in rows (25) in .Y.
The accumulator is unaffected. For the 128, the values returned
reflect the size of the current output window. The X register
will contain in the current window the number of columns mi-
nus one, and .Y will contain the number of rows minus one.
The accumulator will hold the maximum column number for
the display currently active (39 for the 40-column screen or 79
for the 80-column screen).
$FF93 SECOND
This low-level serial I/O routine sends a secondary address to
a device which has been commanded to listen. The value in
the serial status flag upon return will indicate whether the op-
eration was successful.
$FFBA SETLFS
This routine assigns the logical file number (location $B8), de-
vice number (location $BA), and secondary address location
$B9) for the current I/O operation. Call the routine with the
accumulator holding the logical file number, .X holding the
device number, and .Y holding the secondary address. All reg-
ister values are preserved during the routine. Refer to the
LOAD and SAVE routines for the special significance of the
secondary address in those cases. When OPENing files to se-
rial devices, it's vital that each logical file have a unique
secondary address, In the 128 Kernal, the LKUPLA and
LKUPSA routines can be used to find unused logical file num-
bers and secondary addresses.
$FF90 SETMSG
SETMSG sets the value of the Kernal message flag (location
$9D). Call the routine with the accumulator holding the de-
sired flag value (.X and .Y are unaffected,) Valid flag values
are 0 (no Kernal messages are displayed), 64 (only error mes-
sages are displayed), 128 (only control messages—PRESS
PLAY ON TAPE, for example—are displayed), and 192 (both
error and control messages are displayed).
$FFBD SETNAM
This routine assigns the length (location $B7) and address
locations $BB-$BC) of the filename for the current I/O opera-
tion. Call the routine with the length of the filename in .A and
the address of the first character of the name in .X (low byte)
and .Y (high byte). If no name is used for the current opera-
tion, load the accumulator with 0; the values in .X and .Y are
then irrelevant, All register values are preserved during this
routine.
$FFDB SETTIM
This routine sets the value in the software jiffy dock. The
value in the accumulator is transferred to the low byte (loca-
tion $A2), the value in .X to the middle byte (location $A1),
and the value in .Y to the high byte (location $A0). The speci-
fied value should be less than $4F1A01, which corresponds to
24:00:00 hours.
$FFA2 SETTMO
The SETTMO routine stores the contents of the accumulator in
the fEEE timeout flag. (.X and .Y are unaffected.) This routine
is superfluous, since the flag isn't used by any 64 or 128 ROM
routine. It is present merely to maintain consistency with pre-
vious versions of the Kernal. For the 64, the flag location is
$0285; for the 128, it's at $0A0E.
$FFE1 STOP
This routine checks whether the RUN/STOP key is currently
pressed. It returns with the status-register Z bit clear if the key
is not pressed, or with the bit set if it is pressed. Additionally,
if RUN/STOP is pressed the CLRCH routine is called to re-
store default I/O channels, and the count of keys in the key-
board buffer is reset to zero.
The JMP to the STOP execution routine is by way of the
ISTOP indirect vector at $0328-$0329. You can modify the ac-
tions of the routine by changing the vector to point to a rou-
tine of your own.
$FFB4 TALK
This low-level 1/0 routine sends a TALK command to a serial
device, Call the routine with the accumulator holding the
number (4-31) of the device. The success of the operation will
be indicated by the value in the serial status flag upon return,
(See READST for details.)
$FF96 TKSA
This low-level serial 1/0 routine sends a secondary address to
a device which has previously been commanded to taLk. The
success of the operation will be indicated by the value in the
serial status flag upon return. (See READST for details.)
$FFEA UDTIM
This routine increments the software jiffy dock and scans the
keyboard column containing the RUN/STOP key. (The 128
version of the routine also decrements a countdown timer.)
This routine is normally called every 1 /60 second as part of
the standard lRQ service routine.
$FFAE UNLSN
This low-level I/O routine sends an UNLISTEN command to
aH devices on the serial bus. Any devices which are currently
listeners will cease accepting data.
$FFAB UNTLK
This low-level 1/0 routine sends an UNTALK command to all
devices on the serial bus. Any devices which are currently
talkers will cease sending data.
$FF8D VECTOR
This routine can be used either to store the current values of
Kernal indirect vectors at $0314-$0333 or to write new values
to the vectors. When calling this routine, .X and .Y should be
loaded with the address of a 32-byte table (low byte in .X,
high byte in .Y). If the status-register carry bit is clear when
the routine is called, the vectors will be loaded with the values
from the table. If carry is set, the 16 two-byte address values
currently in the vectors will be copied to the table.
New 128 Kernal Jump Table
Locations $FF47-$FF7F comprise a new table of jump vectors
to routines found in Commodore 128 ROM, but not in the
Commodore 64.
$FF53 BOOT_CALL
This routine attempts to load and execute boot sectors from a
specified disk drive. Call the routine with .X holding the de-
vice number for the drive (usually 8) and with the accu-
mulator holding the character code corresponding to the drive
number—not the actual drive number. The single drive in
1541 and 1571 units is drive 0; in this case, use 48, the charac-
ter code for zero. If the specified drive is not present or is
tumed off, or if the disk in the drive does not contain a valid
boot sector, the routine will return with the status-register
carry bit set. If a boot sector is found, it will be loaded into
locations $0B00-$0BFF. Additional boot sectors may be loaded
into other areas of memory, and the boot code may not return
to this routine.
$FF4A CLOSE_ALL
This routine closes all files currently opened to a specified de-
vice, providing an improved version of CLALL. Enter the rou-
tine with the accumulator holding the number of the device
on which files are to be closed. Lf the specified device is the
current input or output device, the input or output channel
will be reset to the default device (screen or keyboard). If all
files to the device were successfully closed, the status-register
carry bit w01 clear upon return. A set carry bit indicates that a
device error occurred.
$FF4D C64_MODE
This is the equivalent of the BASIC command GO 64. It per-
forms an immediate cold start of 64 mode. To get back to 128
mode, it is necessary to reset the computer, or to tum it off
and back on.
$FF62 DLCHR
This routine copies character shape data for both standard
ROM character sets into the VDC video chip's private block of
RAM, providing character definitions for the 80-column dis-
play. (The VDC has no character ROM.) This routine is also
called as part of IOEMFI for the 128.
$FF50 DMA_CALL
This routine passes a command to a DMA (Direct Memory Ac-
cess) device. The DMA device will then take control of the
system to execute the command. The routine is written to sup-
port the REC (RAM Expansion Controller) chip in the 1700
and 1750 Memory Expansion Modules, the only DMA periph-
erals currently available. Call the routine with .Y holding the
command for the DMA device and .X holding the bank number
for the operation. Other preparatory steps may be required,
depending on the command.
$FF6B GETCFG
This routine translates a bank number (0-15) into the
corresponding MMU register setting to configure the system
for that bank. Call the routine with .X holding the bank num-
ber. Upon return, the accumulator will hold the corresponding
MMU configuration register value. (.Y is unaffected.) Once you
have this value, you can store it into $FF00 to change banks.
The input bank number is not checked for validity, and a
number outside the acceptable range will return a meaningless
value.
$FF7A INDCMP
This routine compares .A to the number held in a memory
location in a specified bank. In preparing to call EMDCMP,
load a two-byte zero-page pointer with the address of the
location with which the accumulator is to be compared (or
with the base location if a series of bytes is to be compared),
then store the address of this pointer in location $02C8. Call
the routine with the accumulator holding the byte to be com-
pared, .X holding the bank number (0-15) for the target loca-
tion, and .Y holding an offset value which will be added to
the address in the pointer. (Load .Y with 0 if no offset is de-
sired.) Upon return, the accumulator will still hold the byte
value, and the status-register N, Z, and C (carry) bits will re-
flect the result of the comparison. The value in .Y will also be
preserved, but it is necessary to reload .X with the bank num-
ber before every call to this routine. You can compare up to
256 sequential locations without changing the address in the
zero-page pointer by simply incrementing .Y between calls.
$FF74 INDFET
This routine reads the contents of a location in a specified
bank. Prior to calling this routine; you must load a two-byte
zero-page pointer with the address of the location to be read
(or with the base location if a series of bytes is to be read).
Call the routine with the accumulator holding the address
of the zero-page pointer, .X holding the bank number (0-15)
for the target location, and .Y holding an offset value which
will be added to the address in the pointer. (Load .Y with 0 if
no offset is desired.) Upon return, the accumulator will hold
the byte from the specified address. The value in .Y is not
changed.
To read from a series of locations, it is necessary to reload
the accumulator and .X values before every call to this routine,
but you can read up to 256 sequential locations without
changing the address in the zero-page pointer by incrementing
.Y between calls.
$FF77 INDSTA
This routine stores a value at an address in a specified bank.
Before calling the routine, you must load a two-byte zero-page
pointer with the address of the location at which the byte is to
be stored (or with the base location if a series of bytes is to be
stored), and then store the address of this pointer in location
$02B9. Call the routine with the accumulator holding the byte
to be stored, .X holding the bank number (0-15) for the target
location, and .Y holding an offset value which will be added
to the address in the pointer. (Load Y with 0 if no offset is de-
sired.) Upon return, the accumulator will still hold the byte
value; .Y is also preserved. To write to a series of locations,
you must reload .X with the bank number before every call,
but you can write to up to 256 sequential locations without
changing the address in the zero-page pointer by simply in-
crementing .Y between calls.
$FF71 JMPFAR
JMPFAR jumps to a routine in a specified bank, with no return
to the calling bank. Prior to calling this routine, you must store
the bank number (0-15) of the target routine in location 2 and
the address of the target routine in locations 3-4 in high-
byte/low-byte order, opposite from the usual arrangement.
Load location 5 with the value you want placed in the status
register when the target routine is entered. (The behavior of
many operating-system routines is influenced by the status-
register setting, particularly the state of the carry bit. Load 5
with the value 0 to clear carry or with 1 to set carry.) To pass
other register values, store the desired accumulator value in
location 6, the value for .X in 7, and the value for .Y in 8.
$FF6E JSRFAR
This routine jumps to a subroutine in a specified bank and re-
turns to the calling routine in bank 15. Prior to calling this
routine, you must store the bank number (0-15) of the target
routine in location 2 and the address of the target routine in
locations 3-4 (in high-byte/low-byte order, opposite from the
usual arrangement). Load location 5 with the value you want
placed in the status register when the target routine is called.
(The behavior of many operating system routines is influenced
by the status-register setting, particularly the state of the carry
bit. Load 5 with the value 0 to clear carry, or with 1 to set
carry.) To pass other register values to the routine you will be
calling, store the desired accumulator value in location 6, the
value for .X in 7, and the value for .Y in 8. Upon return, loca-
tion 5 will hold the status-register value at the time of exit, 6
will hold the accumulator value, 7 will hold the .X value, 8
will hold the .Y value, and 9 will hold the stack-pointer value.
The system is always configured for bank 15 upon exit.
$FF59 LKUPLA
This routine checks whether a specified logical file number is
currently used. Call the routine with the accumulator holding
the logical-file-number value in question. If that file number is
available, the carry bit will be set upon return. (The logical file
number will still be in the accumulator.) However, if the num-
ber is used for a currently open file, then the carry bit will be
clear upon return, the accumulator will still hold the logical
file number, .X will hold the corresponding device number,
and .Y will hold the corresponding secondary address.
$FF5C LKUPSA
This routine checks whether a specified secondary address is
currently in use. Call the routine with .Y holding the secondary-
address value in question. If that secondary address is not
currently used, the status-register carry bit will be set upon re-
turn. (The secondary-address value will still be in .Y.) How-
ever, ii the number is used for a currently open file, the carry
bit will be clear upon return, .Y will still hold the secondary
address, the accumulator will hold the associated logical file
number, and .X will hold the corresponding device number.
$FF65 PFKEY
When you turn on the 128, its function keys are predefined.
Pressing F3 prints DIRECTORY, F7 holds the LIST command,
and so on. The PFKEY Kernal routine assigns a new definition
to one of the 10 programmable function keys (F1-F8, SHIFT-
RUN/STOP, and HELP).
Call the routine with the accumulator holding the address
of a three-byte zero-page string descriptor, .X holding the key
number (1-10), and .Y holding the length of the new defi-
nition string. The first two bytes of the descriptor in zero page
should contain the address of the definition string (in the
usual low-byte/high-byte order); the final byte should hold
the bank number where the definition string is located. PFKEY
doesn't check the key number for validity; a value outside the
acceptable range may garble existing definitions. Upon return,
the carry bit will be clear if the new definition was success-
fully added, or set if there was insufficient room in the defi-
nition table for the new definition.
$FF56 PHOENIX
This routine initializes function ROMs and attempts to boot a
disk from the default drive. The presence of function ROMs in
cartridges or in the 128's spare ROM socket is recorded during
the power-on/reset sequence. This routine initializes the func-
tion ROMs by calling their recorded cold-start entry addresses.
If ROMs are present, they may or may not return to this rou-
tine, depending on the initialization steps performed. If no
ROMs are present, or if all ROMs return after initialization,
the routine attempts to boot a disk in drive 0 of device 8 using
the BOOT_CALL routine,
$FF7D PRIMM
This routine prints the string of character codes which im-
mediately follows the JSR to this routine. (You must always
call this routine with JSR, never with JMP. Only JSR places the
required address information on the stack.) The routine contin-
ues printing bytes as character codes until a byte containing
zero is encountered. When the ending marker is found, the
routine returns to the address immediately following the zero
byte. All registers (.A, .X, and .Y) are preserved during this
routine.
$FF68 SETBNK
This Kernal routine establishes the current memory bank from
which data will be read or to which data will be written dur-
ing load/save operations, as well as the bank where the file-
name for the I/O operations can be found. Call the routine
with the accumulator holding the bank number for data and
.X holding the bank for the filename. All registers (.A, .X, and
.Y) are preserved during this routine.
$FF47 SPIN_SPOUT
This low-level serial I/O routine sets up the serial bus for fast
(burst mode) communications. Unless you're writing a custom
data-transfer routine, it's not necessary to call this routine
explicitly. All higher-level serial 1/0 routines already include
this setup step. The routine should be called with the status-
register carry bit clear to establish fast serial input or with the
bit set to establish fast serial output.
$FF5F SWAPPER
This routine switches active screen displays. The active display
is the one which has a live cursor, and to which screen
CHROUT output is directed. The routine exchanges the active
and inactive screen-editor variable tables, tab-stop bitmaps,
and line-link bitmaps; and it toggles the active screen flag
(location $D7). The routine doesn't physically tum either
video chip on or off—both chips always remain enabled.

412
kernal/kernal_pm.txt Normal file
View file

@ -0,0 +1,412 @@
-
- https://www.atarimagazines.com/compute/issue40/cracking_the_kernal.php
- Peter Marcotty: Cracking The Kernal
- COMPUTE! #40, September 1983, pp. 268-274
-
- Descriptions of RESTOR, SAVE, SCNKEY and SCREEN are missing from
- the original source.
-
$FFA5 ACPTR Input byte from serial port.
ACPTR is used to get data off the serial bus. TALK and TKSA must be called first.
;Get a byte from the serial bus.
JSR ACPTR
STA $0800
;This example only shows the end result; call TALK and TKSA first.
$FFC6 CHKIN Open channel for input.
CHKIN is used to define any OPENed file as an input file. OPEN must be called first.
;Define logical file #2 as an input channel.
LDX #2
JSR CHKIN
;The X register designates which file #.
$FFC9 CHKOUT Open channel for output.
CHKOUT. Just like CHKIN, but it defines the file for output. OPEN must be called first.
;Define logical file #4 as an output file.
LDX #4
JSR CHKOUT
;Once again the X register defines the file #.
$FFCF CHRIN Input character from channel.
CHRIN will get a character from the current input device. Calling OPEN and CHKIN can change the input device.
;Store a typed string to the screen.
LDY #$00
LOOP JSR CHKIN
STA $0800,Y
INY
CMP #$0D
BNE LOOP
RTS
;This example is like an INPUT statement. Try running it.
$FFD2 CHROUT Output character to channel.
CHROUT. Load the accumulator with your number and call. OPEN and CHKOUT will change the output device.
;Duplicate the command of CMD 4:PRINT "A";
LDX #4
JSR CHKOUT
LDA #'A
JSR CHROUT
RTS
;The letter A is printed to the screen; call OPEN first for the printer.
$FFAB CIOUT Output byte to serial port.
CIOUT will send data to the serial bus. LISTEN and SECOND must be called first. Call UNLSN to finish up neatly.
;Send the letter X to the serial bus.
LDA #'X
JSR CIOUT
RTS
;The accumulator is used to transfer the data.
$FF81 CINT Initialize screen editor.
CINT resets the 6567 video controller chip and the screen editor.
;Reset the 6567 chip and the 6566 VIC chip.
JSR CINT
RTS
;Basically, just like pressing the STOP and RESTORE keys.
$FFE7 CLALL Close all channels and files.
CLALL really does what its name implies-it closes all files and resets all channels.
;Close all files.
JSR CLALL
RTS
;The CLRCHN routine is called automatically.
$FFC3 CLOSE Close a specified logical file.
CLOSE. This routine will CLOSE any logical file that has been OPENed.
Close logical file #2.
LDA #2
JSR CLOSE
;The accumulator designates the file #.
$FFCC CLRCHN Close input and output channels.
CLRCHN resets all channels and I/O registers - the input to keyboard and the output to screen.
;Restore default values to I/O devices.
JSR CLRCHN
RTS
;The accumulator and the X register are altered.
$FFE4 GETIN Get character from keyboard buffer.
GETIN will get one piece of data from the input device. OPEN and CHKIN can be used to change the input device.
;Wait for a key to be pressed.
WAIT JSR GETIN
CMP #0
BEQ WAIT
;If the serial bus is used, then all registers are altered.
$FFF3 IOBASE Return base address of I/O devices.
IOBASE returns the low and high bytes of the starting address of the I/O devices in the X and Y registers.
;Set the Data Direction Register of the user port to 0 (input).
JSR IOBASE
STX POINT
STY POINT+1
LDY #2
LDA #0
STA (POINT),Y
;POINT is a zero-page address used to access the DDR indirectly.
$FF84 IOINIT Initialize input/output.
IOINIT initializes all I/O devices and routines. It is part of the system's powering-up routine.
;Initialize all I/O devices.
JSR IOINIT
RTS
;All registers are altered.
$FFB1 LISTEN Command devices on serial bus to LISTEN.
LISTEN will command any device on the serial bus to receive data.
;Command device #8 to listen.
LDA #8
JSR
LISTEN
;The accumulator designates the device #.
$FFD5 LOAD Load RAM from a device.
LOAD. The computer will perform either the LOAD or the VERIFY command. If the ac cumulator is a 1, then LOAD; if 0, then verify.
;Load a program into memory.
LDA #$08
LDX #$02
LDY #$00
JSR SETLFS
LDA #$04
LDX #L,NAME
LDY #H,NAME
JSR SETNAM
LDA #$00
LDY #$20
JSR LOAD
RTS
NAME .BY 'FILE'
;Program 'FILE' will be loaded into memory starting at 8192 decimal, X being the low byte and Y being the high byte for the load.
$FF9C MEMBOT Read/set bottom of memory.
MEMBOT. If the carry bit is set, then the low byte and the high byte of RAM are returned in the X and Y registers. If the carry bit is clear, the bottom of RAM is set to the X and Y registers.
;Move bottom of memory up one page.
SEC
JSR MEMBOT
INY
CLC
JSR MEMBOT
RTS
;The accumulator is left alone.
$FF99 MEMTOP Read/set top of memory.
MEMTOP. Same principle as MEMBOT, except the top of RAM is affected.
;Protect 1K of memory from BASIC.
SEC
JSR MEMTOP
DEY
CLC
JSR MEMTOP
;The accumulator is left alone.
$FFC0 OPEN Open a logical file.
OPEN. After SETLFS and SETNAM have been called, you can OPEN a logical file.
;Duplicate the command OPEN 15,8,15,'I/O'
LDA #3
LDX #L,NAME
LDY #H,NAME
JSR SETNAM
LDA #15
LDX #8
LDY #15
JSR SETLFS
JSR OPEN
RTS
NAME .BY 'I/O'
;OPEN opens the current name file with the current LFS.
$FFF0 PLOT Read/set X,Y cursor position.
PLOT. If the carry bit of the accumulator is set, then the cursor X,Y is returned in the Y and X registers. If the carry bit is clear, then the cursor is moved to X,Y as determined by the Y and X registers.
;Move cursor to row 12, column 20 (12,20).
LDX #12
LDY #20
CLC
JSR PLOT
;The cursor is now in the middle of the screen.
$FF87 RAMTAS Initialize RAM, reset tape buffer.
RAMTAS is used to test RAM, reset the top and bottom of memory pointers, clear $0000 to $0101 and $0200 to $03FF, and set the screen memory to $0400.
;Do RAM test.
JSR RAMTAS
RTS
;All registers are altered.
$FFDE RDTIM Read realtime clock.
RDTIM. Locations 160-162 are transferred, in order, to the Y and X registers and the accumulator.
;Store system clock to screen.
JSR RDTIM
STA 1026
STX 1025
STY 1024
;The system clock can be translated as hours/minutes/ seconds.
$FFB7 READST Read I/O status word.
READST. When called, READST returns the status of the I/O devices. Any error code can be translated as operator error.
;Check for read error.
JSR READST
CMP #16
BEQ ERROR
;In this case, if the accumulator is 16, a read error occurred.
$FF8A RESTOR Restore I/O default vectors.
$FFDE SAVE Save RAM to device.
$FF9F SCNKEY Scan keyboard.
$FFED SCREEN Return X,Y organization of screen.
SCREEN returns the number of columns and rows the screen has in the X and Y registers.
;Determine the screen size.
JSR SCREEN
STX MAXCOL
STY MAXROW
RTS
;SCREEN allows further compatibility between the 64, the VIC-20, and future versions of the 64.
$FF93 SECOND Send secondary address after LISTEN.
SECOND. After LISTEN has been called, a SECONDary address may be sent.
;Address device #8 with secondary address #15.
LDA #8
JSR LISTEN
LDA #15
JSR SECOND
;The accumulator designates the address number.
$FFBA SETLFS Set logical, first, and second address.
SETLFS stands for SET Logical address, File address, and Secondary address. After SETLFS is called, OPEN may be called.
;Set logical file #1, device #8, secondary address of 15.
LDA #1
LDX #8
LDY #15
JSR SETLFS
;If OPEN is called, the command will be OPEN 1,8,15.
$FF90 SETMSG Control Kernal messages.
SETMSG. Depending on the accumulator, either error messages, control messages, or neither is printed.
;Turn on control messages.
LDA #$40
JSR SETMSG
RTS
;A 128 is for error messages; a zero, for turning both off.
$FFBD SETNAM Set filename.
SETNAM. In order to access the OPEN, LOAD, or SAVE routines, SETNAM must be called first.
;SETNAM will prepare the disk drive for'FILE#1'.
LDA #6
LDX #L,NAME
LDY #H,NAME
JSR SETNAM
NAME.BY 'FILE#l'
;Accumulator is file length, X is low byte, and Y is high byte.
$FFDB SETTIM Set realtime clock.
SETTIM is the opposite of RDTIM: it SETs the system clock instead of ReaDing it.
;Set system clock to 10 minutes =3600 jiffies.
LDA #0
LDX #L,3600
LDY #H,3600
JSR SETTIM
;This allows very accurate timing for many things.
$FFA2 SETTMO Set time-out on serial bus.
SETTMO is used only with an IEEE add-on card to access the serial bus.
;Disable time-outs on serial bus.
LDA #0
JSR SETTMO
;To enable time-outs, set the accumulator to a 128 and call SETTMO.
$FFE1 STOP Check for STOP key.
STOP will set the Z flag of the accumulator if the STOP key was pressed.
;Check for STOP key being pressed.
WAIT JSR STOP
BNE WAIT
RTS
;STOP must be called if the STOP key is to remain functional.
$FFB4 TALK Command serial bus device to TALK.
TALK. This routine will command a device on the serial bus to send data.
;Command device #8 to TALK.
LDA #8
JSR TALK
RTS
;The accumulator designates the file number.
$FF96 TKSA Send secondary address after TALK.
TKSA is used to send a secondary address for a TALK device. TALK must be called first.
;Signal device #4 to talk with command #7.
LDA #4
JSR TALK
LDA #7
JSR TKSA
RTS
;This example will tell the printer to print in uppercase.
$FFEA UDTIM Increment realtime clock.
UDTIM. If you are using your own interrupt system, you can update the system clock by calling UDTIM.
;Update the system clock.
JSR UDTIM
RTS
;It is useful to call UDTIM before calling STOP.
$FFAE UNLSN Command serial bus to UNLISTEN.
UNLSN commands all devices on the serial bus to stop receiving data.
;Command the serial bus to UNLiSteN.
JSR UNLSN
RTS
;The serial bus can now be used for other things.
$FFAB UNTLK Command serial bus to UNTALK.
UNTLK. All devices previously set to TALK will stop sending data.
;Command serial bus to stop sending data.
JSR UNTLK
RTS
;Sending UNTLK commands all talking devices to get off the serial bus.
$FF8D VECTOR Read/set vectored I/O.
VECTOR. If the carry bit of the accumulator is set, the start of a list of the current contents of the RAM vectors is returned in the X and Y registers. If the carry bit is clear, there the user list pointed to by the X and Y registers is transferred to the system RAM vectors.
;Change the input routines to new system.
SEC
JSR VECTOR
LDA #L,MYINP
STA USER+10
LDA #H,MYINP
STA USER+11
LDX #L,USER
LDY #H,USER
CLC
JSR VECTOR
RTS
USER .DE 26
;The new input list can start anywhere. USER is the location for temporary strings, and 35-36 is the utility pointer area.

1280
kernal/kernal_prg.txt Normal file

File diff suppressed because it is too large Load diff

273
kernal/kernal_sta.txt Normal file
View file

@ -0,0 +1,273 @@
$FF81 SCINIT Initialize VIC; restore default input/output to keyboard/screen; clear screen; set PAL/NTSC switch and interrupt timer.
Input:
Output:
Used registers: A, X, Y.
Real address: $FF5B.
$FF84 IOINIT Initialize CIA's, SID volume; setup memory configuration; set and start interrupt timer.
Input:
Output:
Used registers: A, X.
Real address: $FDA3.
$FF87 RAMTAS Clear memory addresses $0002-$0101 and $0200-$03FF; run memory test and set start and end address of BASIC work area accordingly; set screen memory to $0400 and datasette buffer to $033C.
Input:
Output:
Used registers: A, X, Y.
Real address: $FD50.
$FF8A RESTOR Fill vector table at memory addresses $0314-$0333 with default values.
Input:
Output:
Used registers:
Real address: $FD15.
$FF8D VECTOR Copy vector table at memory addresses $0314-$0333 from or into user table.
Input: Carry: 0 = Copy user table into vector table, 1 = Copy vector table into user table; X/Y = Pointer to user table.
Output:
Used registers: A, Y.
Real address: $FD1A.
$FF90 SETMSG Set system error display switch at memory address $009D.
Input: A = Switch value.
Output:
Used registers:
Real address: $FE18.
$FF93 LSTNSA Send LISTEN secondary address to serial bus. (Must call LISTEN beforehands.)
Input: A = Secondary address.
Output:
Used registers: A.
Real address: $EDB9.
$FF96 TALKSA Send TALK secondary address to serial bus. (Must call TALK beforehands.)
Input: A = Secondary address.
Output:
Used registers: A.
Real address: $EDC7.
$FF99 MEMBOT Save or restore start address of BASIC work area.
Input: Carry: 0 = Restore from input, 1 = Save to output; X/Y = Address (if Carry = 0).
Output: X/Y = Address (if Carry = 1).
Used registers: X, Y.
Real address: $FE25.
$FF9C MEMTOP Save or restore end address of BASIC work area.
Input: Carry: 0 = Restore from input, 1 = Save to output; X/Y = Address (if Carry = 0).
Output: X/Y = Address (if Carry = 1).
Used registers: X, Y.
Real address: $FE34.
$FF9F SCNKEY Query keyboard; put current matrix code into memory address $00CB, current status of shift keys into memory address $028D and PETSCII code into keyboard buffer.
Input:
Output:
Used registers: A, X, Y.
Real address: $EA87.
$FFA2 SETTMO Unknown. (Set serial bus timeout.)
Input: A = Timeout value.
Output:
Used registers:
Real address: $FE21.
$FFA5 IECIN Read byte from serial bus. (Must call TALK and TALKSA beforehands.)
Input:
Output: A = Byte read.
Used registers: A.
Real address: $EE13.
$FFA8 IECOUT Write byte to serial bus. (Must call LISTEN and LSTNSA beforehands.)
Input: A = Byte to write.
Output:
Used registers:
Real address: $EDDD.
$FFAB UNTALK Send UNTALK command to serial bus.
Input:
Output:
Used registers: A.
Real address: $EDEF.
$FFAE UNLSTN Send UNLISTEN command to serial bus.
Input:
Output:
Used registers: A.
Real address: $EDFE.
$FFB1 LISTEN Send LISTEN command to serial bus.
Input: A = Device number.
Output:
Used registers: A.
Real address: $ED0C.
$FFB4 TALK Send TALK command to serial bus.
Input: A = Device number.
Output:
Used registers: A.
Real address: $ED09.
$FFB7 READST Fetch status of current input/output device, value of ST variable. (For RS232, status is cleared.)
Input:
Output: A = Device status.
Used registers: A.
Real address: $FE07.
$FFBA SETLFS Set file parameters.
Input: A = Logical number; X = Device number; Y = Secondary address.
Output:
Used registers:
Real address: $FE00.
$FFBD SETNAM Set file name parameters.
Input: A = File name length; X/Y = Pointer to file name.
Output:
Used registers:
Real address: $FDF9.
$FFC0 OPEN Open file. (Must call SETLFS and SETNAM beforehands.)
Input:
Output:
Used registers: A, X, Y.
Real address: ($031A), $F34A.
$FFC3 CLOSE Close file.
Input: A = Logical number.
Output:
Used registers: A, X, Y.
Real address: ($031C), $F291.
$FFC6 CHKIN Define file as default input. (Must call OPEN beforehands.)
Input: X = Logical number.
Output:
Used registers: A, X.
Real address: ($031E), $F20E.
$FFC9 CHKOUT Define file as default output. (Must call OPEN beforehands.)
Input: X = Logical number.
Output:
Used registers: A, X.
Real address: ($0320), $F250.
$FFCC CLRCHN Close default input/output files (for serial bus, send UNTALK and/or UNLISTEN); restore default input/output to keyboard/screen.
Input:
Output:
Used registers: A, X.
Real address: ($0322), $F333.
$FFCF CHRIN Read byte from default input (for keyboard, read a line from the screen). (If not keyboard, must call OPEN and CHKIN beforehands.)
Input:
Output: A = Byte read.
Used registers: A, Y.
Real address: ($0324), $F157.
$FFD2 CHROUT Write byte to default output. (If not screen, must call OPEN and CHKOUT beforehands.)
Input: A = Byte to write.
Output:
Used registers:
Real address: ($0326), $F1CA.
$FFD5 LOAD Load or verify file. (Must call SETLFS and SETNAM beforehands.)
Input: A: 0 = Load, 1-255 = Verify; X/Y = Load address (if secondary address = 0).
Output: Carry: 0 = No errors, 1 = Error; A = KERNAL error code (if Carry = 1); X/Y = Address of last byte loaded/verified (if Carry = 0).
Used registers: A, X, Y.
Real address: $F49E.
$FFD8 SAVE Save file. (Must call SETLFS and SETNAM beforehands.)
Input: A = Address of zero page register holding start address of memory area to save; X/Y = End address of memory area plus 1.
Output: Carry: 0 = No errors, 1 = Error; A = KERNAL error code (if Carry = 1).
Used registers: A, X, Y.
Real address: $F5DD.
$FFDB SETTIM Set Time of Day, at memory address $00A0-$00A2.
Input: A/X/Y = New TOD value.
Output:
Used registers:
Real address: $F6E4.
$FFDE RDTIM read Time of Day, at memory address $00A0-$00A2.
Input:
Output: A/X/Y = Current TOD value.
Used registers: A, X, Y.
Real address: $F6DD.
$FFE1 STOP Query Stop key indicator, at memory address $0091; if pressed, call CLRCHN and clear keyboard buffer.
Input:
Output: Zero: 0 = Not pressed, 1 = Pressed; Carry: 1 = Pressed.
Used registers: A, X.
Real address: ($0328), $F6ED.
$FFE4 GETIN Read byte from default input. (If not keyboard, must call OPEN and CHKIN beforehands.)
Input:
Output: A = Byte read.
Used registers: A, X, Y.
Real address: ($032A), $F13E.
$FFE7 CLALL Clear file table; call CLRCHN.
Input:
Output:
Used registers: A, X.
Real address: ($032C), $F32F.
$FFEA UDTIM Update Time of Day, at memory address $00A0-$00A2, and Stop key indicator, at memory address $0091.
Input:
Output:
Used registers: A, X.
Real address: $F69B.
$FFED SCREEN Fetch number of screen rows and columns.
Input:
Output: X = Number of columns (40); Y = Number of rows (25).
Used registers: X, Y.
Real address: $E505.
$FFF0 PLOT Save or restore cursor position.
Input: Carry: 0 = Restore from input, 1 = Save to output; X = Cursor column (if Carry = 0); Y = Cursor row (if Carry = 0).
Output: X = Cursor column (if Carry = 1); Y = Cursor row (if Carry = 1).
Used registers: X, Y.
Real address: $E50A.
$FFF3 IOBASE Fetch CIA #1 base address.
Input:
Output: X/Y = CIA #1 base address ($DC00).
Used registers: X, Y.
Real address: $E500.

252
style.css
View file

@ -1,252 +0,0 @@
/* Colors */
:root {
--main-background: #e0f0ff;
--main-color: #004080;
--highlight-background: #006ad5;
--border-color: #0060a0;
--title-color-1: #017100;
--title-color-2: #004D7F;
--title-color-3: #99195E;
--title-color-4: #F8BA00;
--title-color-5: #B51700;
--title-color-6: #017B76;
--title-color-7: #595959;
--title-color-8: #714a00;
--dark-color-1: #D8F2CB;
--dark-color-2: #C6E2FC;
--dark-color-3: #BFB7E8;
--dark-color-4: #FCF6CD;
--dark-color-5: #F4D2E3;
--dark-color-6: #D2F6F0;
--dark-color-7: #E0E0E0;
--dark-color-8: #F2E4CB;
--light-color-1: #E5F2DF;
--light-color-2: #E3F0FC;
--light-color-3: #D5D1E8;
--light-color-4: #FCFAE6;
--light-color-5: #F5E4EC;
--light-color-6: #E1F5F2;
--light-color-7: #EDEDED;
--light-color-8: #F2EBDF;
}
/**/
body {
background: var(--main-background);
color: var(--main-color);
font-family: Helvetica;
margin: 0px;
}
a {
color: var(--border-color);
}
div {
padding: 1em;
}
div.body {
padding: 8px;
}
/* Navigation */
.topnav {
background-color: #333;
overflow: hidden;
padding: 0px;
border-bottom: solid 2px var(--main-color);
}
.topnav a, .topnav h1 {
float: left;
text-align: center;
padding: 14px 16px;
margin: 0px;
text-decoration: none;
font-size: 17px;
}
.topnav a {
color: white;
border-right:solid 1px var(--main-background);
}
.topnav h1 {
color: black;
background-color: white;
}
.topnav a:hover {
background-color: var(--main-background);
color: black;
}
.topnav a.active {
background-color: var(--highlight-background);
color: white;
}
/* Tables */
table {
border-collapse: collapse;
border: solid 1px var(--border-color);
color: black;
}
tr, td, th {
margin: 0px;
text-align:left;
vertical-align: text-top;
}
th.com {
font-weight: bold;
}
/* Overview Table */
table.checkbox_table tr, table.checkbox_table td {
padding: 4px 8px;
border: solid var(--border-color);
border-width:1px 0px 1px 0px;
}
table.checkbox_table a {
color: var(--main-background);
}
/* Overview Table: Multicolor */
table.checkbox_table tr:nth-of-type(1) { background: var(--light-color-1); }
table.checkbox_table tr:nth-of-type(1) td:nth-of-type(2) { background: var(--title-color-1);}
table.checkbox_table tr:nth-of-type(2) { background: var(--light-color-2); }
table.checkbox_table tr:nth-of-type(2) td:nth-of-type(2) { background: var(--title-color-2); }
table.checkbox_table tr:nth-of-type(3) { background: var(--light-color-3); }
table.checkbox_table tr:nth-of-type(3) td:nth-of-type(2) { background: var(--title-color-3); }
table.checkbox_table tr:nth-of-type(4) { background: var(--light-color-4); }
table.checkbox_table tr:nth-of-type(4) td:nth-of-type(2) { background: var(--title-color-4); }
table.checkbox_table tr:nth-of-type(5) { background: var(--light-color-5); }
table.checkbox_table tr:nth-of-type(5) td:nth-of-type(2) { background: var(--title-color-5); }
table.checkbox_table tr:nth-of-type(6) { background: var(--light-color-6); }
table.checkbox_table tr:nth-of-type(6) td:nth-of-type(2) { background: var(--title-color-6); }
table.checkbox_table tr:nth-of-type(7) { background: var(--light-color-7); }
table.checkbox_table tr:nth-of-type(7) td:nth-of-type(2) { background: var(--title-color-7); }
table.checkbox_table tr:nth-of-type(8) { background: var(--light-color-8); }
table.checkbox_table tr:nth-of-type(8) td:nth-of-type(2) { background: var(--title-color-8); }
/* Main Table */
table.disassembly_table {
border: solid grey;
border-width:0px 0px 1px 0px;
}
table.disassembly_table td, table.disassembly_table th {
padding: 2px 4px;
border: solid grey;
border-width:0px 1px 0px 1px;
}
table.disassembly_table th.left_column,
table.disassembly_table th.label_column,
table.disassembly_table th.decimal_column {
position: absolute;
border: 1px solid #000;
border-radius: 2px;
color: var(--main-background);
background: var(--border-color);
}
table.disassembly_table th.left_column {
left: 8px;
z-index: 11;
}
th.left_column a {
color: var(--main-background);
}
th.left_column a:target {
color: yellow;
text-shadow: 0px 1px black;
}
/*
th.left_column a:target::before {
content: "▹";
}
*/
table.disassembly_table th.top_row {
color: var(--main-background);
border-width: 1px;
}
table.disassembly_table tr { background: #f0f0f0; }
table.disassembly_table tr:nth-child(even) { background: #ffffff; }
/* Main Table: Multicolor */
table.disassembly_table th:nth-child(1 of .top_row) { background: var(--title-color-1); }
table.disassembly_table th:nth-child(2 of .top_row) { background: var(--title-color-2); }
table.disassembly_table th:nth-child(3 of .top_row) { background: var(--title-color-3); }
table.disassembly_table th:nth-child(4 of .top_row) { background: var(--title-color-4); }
table.disassembly_table th:nth-child(5 of .top_row) { background: var(--title-color-5); }
table.disassembly_table th:nth-child(6 of .top_row) { background: var(--title-color-6); }
table.disassembly_table th:nth-child(7 of .top_row) { background: var(--title-color-7); }
table.disassembly_table th:nth-child(8 of .top_row) { background: var(--title-color-8); }
table.disassembly_table tr td:nth-of-type(1) { background: var(--dark-color-1); }
table.disassembly_table tr:nth-child(even) td:nth-of-type(1) { background: var(--light-color-1); }
table.disassembly_table tr td:nth-of-type(2) { background: var(--dark-color-2); }
table.disassembly_table tr:nth-child(even) td:nth-of-type(2) { background: var(--light-color-2); }
table.disassembly_table tr td:nth-of-type(3) { background: var(--dark-color-3); }
table.disassembly_table tr:nth-child(even) td:nth-of-type(3) { background: var(--light-color-3); }
table.disassembly_table tr td:nth-of-type(4) { background: var(--dark-color-4); }
table.disassembly_table tr:nth-child(even) td:nth-of-type(4) { background: var(--light-color-4); }
table.disassembly_table tr td:nth-of-type(5) { background: var(--dark-color-5); }
table.disassembly_table tr:nth-child(even) td:nth-of-type(5) { background: var(--light-color-5); }
table.disassembly_table tr td:nth-of-type(6) { background: var(--dark-color-6); }
table.disassembly_table tr:nth-child(even) td:nth-of-type(6) { background: var(--light-color-6); }
table.disassembly_table tr td:nth-of-type(7) { background: var(--dark-color-7); }
table.disassembly_table tr:nth-child(even) td:nth-of-type(7) { background: var(--light-color-7); }
table.disassembly_table tr td:nth-of-type(8) { background: var(--dark-color-8); }
table.disassembly_table tr:nth-child(even) td:nth-of-type(8) { background: var(--light-color-8); }