-
Notifications
You must be signed in to change notification settings - Fork 78
/
c64mem_mapc64.txt
3382 lines (2669 loc) · 218 KB
/
c64mem_mapc64.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
- C64 RAM Map (Mapping The Commodore 64)
-
- Leemon, Sheldon:
- Mapping the Commodore 64
- Greensboro: COMPUTE! Publications, 1984.
- ISBN 0-942386-23-X
-
- MAPC6410.TXT, May 1998, etext #352#
- typed by
- David Holz <david_holz@hotmail.com>
- formatted to 71 columns and somewhat proofed by
- Cris Berneburg <pcgeek@compuserve.com>
-
- Corrections (typos as well as content), translations etc.
- welcome at: https://github.com/mist64/c64ref
-
------------------------------------------------------------
-
# 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 I/O DATA Direction Register
* Bit 0: Direction of Bit 0 I/O on port at next address. Default = 1 (output)
* Bit 1: Direction of Bit 1 I/O on port at next address. Default = 1 (output)
* Bit 2: Direction of Bit 2 I/O on port at next address. Default = 1 (output)
* Bit 3: Direction of Bit 3 I/O on port at next address. Default = 1 (output)
* Bit 4: Direction of Bit 4 I/O on port at next address. Default = 0 (input)
* Bit 5: Direction of Bit 5 I/O on port at next address. Default = 1 (output)
* Bit 6: Direction of Bit 6 I/O on port at next address. Not used.
* Bit 7: Direction of Bit 7 I/O on port at next address. Not used.
This location is the first of a number of hardware registers that we
will discuss. Although they can be written to and/or read like RAM,
they are connected to hardware devices, and their contents affect the
operation of the devices.
Each bit of this Data Direction Register determines whether the
contents of the corresponding bit on the Internal I/O Port (see
location 1) can be written to by peripheral devices. If the bit is
set to 0, it indicates the direction of data flow as Input, which
means that the corresponding bit of the I/O port will be affected by
peripheral defices. If the bit is set to 1, it indicates Output. On
the 64, only Bits 0-5 are significant. On power-up, this register is
set to 239 ($EF), which indicates that all bits, except for Bit 4
(which senses the cassette switch), are set up for Output.
$0001 R6510 6510 On-Chip I/O Port
* Bit 0: LORAM signal. Selects ROM or RAM at 40960 ($A000). 1=BASIC, 0=RAM
* Bit 1: HIRAM signal. Selects ROM or RAM at 57344 ($E000). 1=Kernal, 0=RAM
* Bit 2: CHAREN signal. Selects character ROM or I/O devices. 1=I/O, 0=ROM
* Bit 3: Cassette Data Output line.
* Bit 4: Cassette Switch Sense. Reads 0 if a button is pressed, 1 if not.
* Bit 5: Cassette Motor Switch Control. A 1 turns the motor on, 0 turns it off.
* Bits 6-7: Not connected--no function presently defined.
The chief function of this register is to determine which blocks of
RAM and ROM the 6510 microprocessor will address. The Commodore 64
comes with 64K RAM, even though it normally does not use all of that
RAM at once. In addition, it has an 8K BASIC Interpreter ROM, an 8K
Operating System Kernal ROM, a 4K Character Generator ROM, a Sound
Interface Device (SID), a 6566 Video Interface Controller (VIC-II),
and two 6526 Complex Interface adapter chips.
To address all of these at once would require 88K, 24K past the
addressing limit of the 6510 microprocessor. In order to allocate
address space, the I/O Port is used to affect the addressing lines,
and thus determine which segments of RAM and ROM will be addressed at
any one time.
Bit 0. This bit controls the LORAM signal. A 0 in this bit position
switches the BASIC ROM out, and replaces it with RAM at addresses
40960-49151 ($A000-$BFFF). The default value of this bit is 1.
Bit 1. Bit 1 controls the HIRAM signal. A 0 in this bit position
switches the Kernal ROM out, and replaces it with RAM at 57344-65535
($E000-$FFFF). As the BASIC interpreter uses the Kernal, it is also
switched out and replaced by RAM. The default value of this bit is 1.
The system allows a wide range of combinations of RAM and ROM to be
utilized. Of course, the BASIC programmer will have little need, in
the ordinary course of events, to switch out the BASIC ROM and the
Kernal. To do so would just hang the system up. But one way to make
use of this feature is to move the contents of ROM to the
corresponding RAM addresses. That way, you can easily modify and
customize the BASIC interpreter and OS Kernal routines, which are
ordinarily fixed in ROM. For examples, to move BASIC into RAM, just
type:
FOR I=40960 TO 49151:POKE I,PEEK(I):NEXT
Though it appears that such a program would not do anything, it in
fact copies bytes from ROM to RAM. This is because any data which is
written to a ROM location is stored in the RAM which resides at the
same address. So while you are PEEKing ROM, you are POKEing RAM. To
switch to your RAM copy of BASIC, type in:
POKE 1,PEEK(1) AND 254.
Now you are ready to make modifications. Examples of simple
modifications include changing the text which the interpreter prints,
such as the READY prompt, the power-up message, or the keyword table.
An example of the latter would be POKE 41122,69. This changes the FOR
keyword to FER, so that BASIC would respond normally to a FER-NEXT
loop, but fail to recognize FOR as syntactically correct.
On the more practical side, you could change the prompt that INPUT
issues to a colon, rather than a question mark:
POKE 43846,58
You are not limited to just cosmetic changes of text. Jim Butterfield
has given an example in COMPUTE! magazine of changing the interpreter
so that it assigns a null string the ASCII value 0. In the ROM
version, the command PRINT ASC("") will return ?ILLEGAL QUANTITY
ERROR. This is inconvenient when INPUTting a string, because if the
user presses RETURN and you try to check the ASCII value of the string
that has been entered, you will get this error. By entering POKE
46991,5, this is changed so that PRINT ASC("") now responds with a
zero.
For the more serious machine language programmer, it is quite feasible
to add new commands or modify existing ones by diverting the vectors
which are discussed in the section covering the BASIC interpreter ROM.
For a good example of this technique, see the article "Hi-Res Graphics
Made Simple" by Paul Schatz in COMPUTE!'s First Book of Commodore 64
Sound and Graphics. The program example there inserts new graphics
commands into a RAM version of BASIC. When you want to switch back to
the ROM BASIC, enter POKE 1,PEEK(1) OR 1.
For machine language applications, it would be possible to replace the
ROM programs with an entirely different operating system, or an
application that has its own screen editing and I/O functions
included. Such an application would first have to be loaded from disk
into RAM. A language other than BASIC could be loaded, and could then
just switch out the BASIC ROM, while still using the OS Kernal.
Or a spreadsheet application that contained its own I/O routines could
switch out all ROMs and have the use of all of RAM that is not
actually needed for the program itself, for data. It should be
remembered, however, that before switching the Kernal out, it is
necessary to disable interrupts, as the vectors for these interrupts
are contained in the Kernal.
Bit 2. This bit controls the CHAREN signal. A 0 in this position
switches the character generator ROM in, so that it can be read by the
6510 at addresses 53248-57343 ($D000-$DFFF). Normally, this bit is
set to 1, so that while the VIC-II chip has access to the character
generator ROM for purposes of creating the screen display, the user
cannot PEEK into it. Since this ROM is switched into the system in
the same location as the I/O devices (SID chip, VIC-II chip, and 6526
CIA's), o I/O can occur when this ROM is switched in.
The ability to switch in the character generator ROM is very useful to
the programmer who wishes to expirement with user-defined characters.
Modified character graphics is one of the more powerful graphics
tools available, but often the user will not want to redefine a whole
character set at one time. By reading the character ROM and
duplicating its contents in RAM, the user can replace only a few
characters in the set. The method for reading this ROM into RAM from
BASIC is as follows:
10 POKE 56333,127:POKE1,PEEK(1) AND 251:FOR I=0 TO 2048
20 POKE BASE+I,PEEK(53248+I):NEXT:POKE 1,PEEK(1) OR 4:POKE 56333,129
The first POKE is necessary to turn off the system timer interrupt.
Since the I/O devices are addressed in the same space as the character
ROM, switching that ROM in switches all I/O out, making it necessary
to turn off any interrupts which use these devices.
The second POKE is the one which switches in the character ROM. The
program loop then reads this ROM memory into RAM, starting with the
address BASE. Note that this address should start on an even 2K
boundary (an address evenly divisible by 2048) within the block of
memory presently being addresses by the VIC-II chip (for more
information on where to put user-defined character sets, and how to
use them, see the section on the VIC-II chip, under location 53272
($D018), the section on the character ROM at 49152 ($C000), and the
section on banking VIC-II memory at 56576 ($DD00)). After reading the
contents of ROM into RAM, the next POKEs switch out the character ROM
and restore the interrupt.
It should be noted that while Bits 0-2 of this register allow software
control of some signals that determine the memory configuration that
is used by the Commodore 64 at any given time, they are not the only
determining factor. Signals can also be generated by means of plug-in
expansion cartridges which are connected to the expansion port, and
these can change the memory map.
Two lines located on the exapansion port are called GAME and EXROM.
When used in conjunction with the software-controlled lines noted
above, these two hardware lines can enable cartridge ROM to replace
various segments of ROM and/or RAM.
Possible configurations include 8K of cartridge ROM to be switched in
at $8000-$9FFF, for a BASIC enhancement program; an 8K cartridge ROM
at $A000-$BFFF, replacing BASIC, or at $E000-$FFFF, replacing the
Kernal, or a 16k cartridge at $8000-$C000.
When cartridge ROM is selected to replace the Kernal, a Max emulator
mode is entered, which mimics the specification of the ill-fated Max
Machine, a game machine which Commodore never produced for sale in the
U.S. In this mode, only the first 6K of RAM are used, there is no
access to the character ROM, and graphics data such as charactger
dot-data is mapped down from 57344 ($E000) to 8192 ($2000). Further
hardware information may be obtained from the Commodore 64
Programmer's Reference Guide.
Bits 3-5 of this register have functions connected with the Datasette
recorder. These are as follows:
Bit 3. This is the Cassette Data Output line. This line is connected
to the Cassette Data Write line on the cassette port, and is used to
send the data which is written to tape.
Bit 4. This bit is the Cassette Switch Sense line. This bit enables
a program to tell whether or not one of the buttons that moves the
recorder is pressed down. If the switch on the recorder is down, this
bit will have a value of 1. Remember that Bit 4 of the data direction
register at location 0 must contain a 0 for this bit to properly
reflect the status of the switch.
Bit 5. Bit 5 is the Cassette Motor Control. Setting this bit to zero
allows the motor to turn when you press one of the buttons on the
recorder, while setting it to one disables it from turning.
Most of the time, the setting of this bit will be controlled by the
interrupt routine that is used to read the keyboard every sixtieth of
a second. If none of the buttons on the recorder is pressed, that
interrupt routine shuts the motor off and sets the interlock at
location 192 ($C0) to zero. When a button is pressed, if the
interlock location is zero, Bit 5 of this register is set to zero to
turn the motor on.
When the interlock location contains a zero, the keyscan routine will
not let you control the setting of this bit of the register (and the
interlock is always set to zero when no buttons are pressed). In
order for you to gain control of the motor, you must POKE a nonzero
value into 192 after a button on the recorder has been pressed. You
can then shut off the motor and turn it back on as you please, by
manipulating this bit, so long as a button stays pressed.
$0002 Unused
$0003-$0004 ADRAY1 Vector: Routine to Convert a Number from Floating Point to Signed
Integer
This vector points to the address of the BASIC routine which converts
a floating point number to an integer. In the current Kernal version,
the address that it points to is 45482 ($B1AA). Disassembly of the
ROMs indicates that BASIC does not use this vector. However, it may
be of real assistance to the programmer who wishes to use data that is
stored in floating point format. The parameter that is passed by the
USR command is available only in that format, for example.
Since it is extremely difficult to decipher and use a floating point
number, the simplest way to deal with such data is to use the
conversion routines that are built into BASIC to change it into a
two-byte signed integer. This could be accomplished by jumping
directly into the BASIC ROM, if you know the location of the routine.
Therefore, if the address changes in future versions of the 64 or
future Commodore computers, you won't have to modify your program to
make it work with them.
See the entry for the USR vector at 785 ($0311) for an explanation of
how to use this routine in connection with the USR command.
$0005-$0006 ADRAY2 Vector: Routine to Convert a Number from Integer to Floating Point
This vector points to the address of the BASIC routine which converts
an integer to a floating point number. This routine is currently
located at 45969 ($B391). BASIC does not appear to reference this
location. It is available for use by the programmer who needs to make
such a conversion for a machine language program that interacts with
BASIC. For an explanation of how to use this routine in connection
with the USR command, see the entry for the USR vector at 785 ($0311).
$0007 CHARAC Search Character for Scanning BASIC Text Input
This location and the next are used heavily by the BASIC routines that
scan the text that comes into the buffer at 512 ($0200), in order to
detect significant characters such as quotes, comma, the colon which
separates BASIC statements, and end-of-line. The ASCII values of such
special characters are usually stored here.
This location is also used as a work area by other BASIC routines that
do not involve scanning text.
$0008 ENDCHR Search Character for Statement Termination or Quote
Like location 7, this location is used as a work byte during the
tokenization of a BASIC statement. Most of the time, its value is 0
or 34.
$0009 TRMPOS Column position of the Cursor before the Last TAB or SPC
TRMPOS is used by TAB and SPC. The cursor column position prior to
the TAB or SPC is moved here from 211 ($00D3), and is used to calculate
where the cursor ends up after one of these functions is invoked.
Note that the value contained here shows the position of the cursor on
a logical line. Since one logical line can be up to two physical
lines long, the value stored here can range from 0 to 79.
$000A VERCK Flag: LOAD or VERIFY
BASIC uses one Kernal routine to perform either the LOAD or VERIFY
function, depending on whether the Accumulator (.A) is set to 0 or 1
upon entry to the routine. BASIC sets the value of VERCK to 0 for a
LOAD, or 1 for a VERIFY. Its contents are passed to the Kernal LOAD
routine, which in turn stores it in location 147 ($0093).
$000B COUNT Index into the Text Input Buffer/Number of Array Subscripts
The routines that convert the text in the input buffer at 512 ($0200)
into lines of executable program tokes, and the routines that link
these program lines together, use this location as an index into the
input buffer area. When the job of converting text to tokens is
finished, the value in this location is equal to the length of the
tokenized line.
The routines which build an array or locate an element in an array use
this location to calculate the number of DIMensions called for and the
amount of storage required for a newly created array, or the number of
subscripts specified when referencing an array element.
$000C DIMFLG Flags for the Routines That Locate or Build an Array
This location is used as a flag by the routines that build an array or
reference an existing array. It is used to determine whether a
variable is in an array, whether the array has already been
DIMensioned, and whether a new array should assume the default
dimensions.
$000D VALTYP Flag: Type of Data (String or Numeric)
This flag is used internally to indicate whether data being operated
upon is string or numeric. A value of 255 ($FF) in this location
indicates string data, while a 0 indicates numeric data. This
determination is made every time a variable is located or created.
$000E INTFLG Flat: Type of Numeric Data (Integer or Floating Point)
If data which BASIC is using is determined to be numeric, it is
further classified here as either a floating point number or as an
integer. A 128 ($80) in this location identifies the number as an
integer, and a 0 indicates a floating point number.
$000F GARBFL Flag for LIST, Garbage Collection, and Program Tokenization
The LIST routine uses this byte as a flag to let it know when it has
come to a character string in quotes. It will then print the string,
rather than search it for BASIC keyword tokens.
The garbage collection routine uses this location as a flag to
indicate that garbage collection has already been tried before adding
a new string. If there is still not enough memory, an OUT OF MEMORY
message will result.
This location is also used as a work byte for the process of
converting a line of text in the BASIC input buffer (512, $0200) into a
linked program line of BASIC keyword tokens.
$0010 SUBFLG Flag: Subscript Reference to an Array or User-Defined Function Call (FN)
This flag is used by the PTRGET routine which finds or creates a
variable, at the time it checks whether the name of a variable is
valid. If an opening parenthesis is found, this flag is set to
indicate that the variable in question is either an array variable or
a user-defined function.
You should note that it is perfectly legal for a user-defined function
(FN) to have the same name as a floating point variable. Moreover, it
is also legal to redefine a function. Using a FN name in an already
defined function results in the new definition of the function.
$0011 INPFLG Flag: Is Data Input to GET, READ or INPUT?
Since the keywords GET, INPUT, and READ perform similar functions,
BASIC executes some of the same instructions for all three. There are
also many areas of difference, however, and this flag indicates which
of the three keywords is currently being executed, so that BASIC will
know whether or not to execute the instructions which relate to the
areas in which the commands differ (152 ($98)=READ, 64 ($40)=GET,
0=INPUT).
As a result, INPUT will show the ? prompt, will echo characters back
to the screen, and will wait for a whole line of text ended by a
carriage return. GET gives no prompt and accepts one character
without waiting. The colon character and the comma are valid data for
GET, but are treated as delimiters between data by INPUT and READ.
As each command has its own error messages, this flag is used to
determine the appropriate message to issue in case of an error.
$0012 TANSGN Flag: Sign of the Result of the TAN or SIN Function
This location is used to determine whether the sign of the value
returned by the functions SIN or TAN is positive or negative.
$0012 DOMASK
Additionally, the string and numeric comparison routines use this
location to indicate the outcome of the comparison. For a comparison
of variable A to variable B, the value here will be 1 if A is greater
than B, 2 if A equals B, and 4 if a is less than B. If more than one
comparison operator was used to compare the two variables (e.g., >= or
<=), the value here will be a combination of the above values.
$0013 CHANNL Current I/O Channel (CMD Logical File) Number
Whenever BASIC inputs or outputs data, it looks here to determine
which I/O device is currently active for the purpose of prompting or
output control. It uses location 184 ($00B8) for purposes of deciding
what device actually to put input from or output to.
When the default input device (number 0, the keyboard) or output
device (number 3, the display screen) is used, the value here will be
a zero, and the format of prompting and output will be the standard
screen output format.
When another device is used, the logical file number (CMD channel
number) will be placed here. This lets the system now that it may
have to make some subtle changes in the way it performs the I/O
operation. For example, if TAB is used with the PRINT command, cursor
right characters are used if the device PRINTed to is the screen.
Otherwise, spaces are output when the number here is other than zero
(the assumption being that you can't tab a printer like you can the
screen).
Likewise, the ? prompt for INPUT is suppressed if the file number here
is nonzero, as is the EXTRA IGNORED message, and input of a carriage
return by itself is ignored, rather than being treated as a null
string (""). Therefore, by OPENing the screen as a device, and
issuing the CMD statement, you can force the suppression of the ?
prompt, and the other effects above.
CMD places the new output file number here, and calls the Kernal to
open the device for output, leaving it LISTENing for output (such as
the READY prompt, which is diverted to the new device).
Many routines reset this location and UNLISTEN the device, defeating
the CMD and once again sending the output to the screen. If an error
message has to be displayed, for example, this location will be reset
and the message will be displayed on the screen. GET, GET#, INPUT,
INPUT#, and PRINT# all will reset this location after the I/O is
completed, effectively redirecting output back to the screen. PRINT
and LIST are the only I/O operations that will not undo the CMD.
This location can also be used to fool BASIC into thinking that data
it is reading from the tape is actually being entered into the
keyboard in immediate mode.
For a look at a technique that uses a different approach to accomplish
the same thing for disk or tape users, see location 512 ($0200), the
keyboard buffer.
$0014-$0015 LINNUM Integer Line Number Value
The target line number for GOTO, LIST, ON, and GOSUB is stored here in
low- byte, high-byte integer format, as is the number of a BASIC line
that is to be added or replaced.
LIST saves the highest line number to list (or 65535 ($FFFF) if
program is to be listed to the end) at this location.
GOTO tests the target line number to see if it is greater than the
line number currently being executed. If it is greater, GOTO starts
its search for the target line at the current line number. If it is
not greater, GOTO must search for the target line from the first line
of the program. It is interesting to note that the test is of the
most significant byte only. Therefore, INT(TARGETLINE/256) must be
greater than INT(CURRENTLINE/256) in order for the search to start
with the current line, instead of at the beginning of the program.
PEEK, POKE, WAIT, and SYS use this location as a pointer to the
address which is the subject of the command.
$0016 TEMPPT Pointer to the Next Available Space in the Temporary String Stack
This location points to the next available slot in the temporary
string descriptor stack located at 25-33 ($0019-$0021). Since that stack
has room for three descriptors of three bytes each, this location will
point to 25 ($0019) if the stack is empty, to 28 ($001C) if there is one
entry, to 31 ($001F) if there are two entries, and to 34 ($0022) if the
stack is full.
If BASIC needs to add an entry to the temporary string descriptor
stack, and this location holds a 34, indicating that the stack is
full, the FORMULA TOO COMPLEX error message is issued. Otherwise, the
entry is added, and three is added to this pointer.
$0017-$0018 LASTPT Pointer to the Address of the Last String in the Temporary String
Stack
This pointer indicates the last slot used in the temporary string
descriptor stack. Therefore, the value stored at 23 ($0017) should be 3
less than that stored at 22 ($0016), while 24 ($0018) will contain a 0.
$0019-$0021 TEMPST Descriptor Stack for Temporary Strings
The temporary string descriptor stack contains information about
temporary strings which hve not yet been assigned to a string
variable. An examples of such a temporary string is the literal
string "HELLO" in the statement PRINT "HELLO".
Each three-byte descriptor in this stack contains the length of the
string, and its starting and ending locations, expresses as
displacements within the BASIC storage area.
$0022-$0025 INDEX Miscellaneous Temporary Pointers and Save Area
This area is used by many BASIC routines to hold temporary pointers
and calculation results.
$0026-$002A RES Floating Point Multiplication Work Area
This location is used by BASIC multiplication and division routines.
It is also used by the routines which compute the size of the area
required to store an array which is being created.
$002B-$002C TXTTAB Pointer to the Start of BASIC Program Text
This two-byte pointer lets BASIC know where program text is stored.
Ordinarily, such text is located beginning at 2049 ($0801). Using this
pointer, it is possible to change the program text area. Typical
reasons for doing this include:
1. Conforming the memory configuration to that of other Commodore
computers. On 32K PET and CBM computers, for example, screen memory
starts at 32768 ($8000), and BASIC text begins at 1025 ($0401). You
can emulate this configuration with the 64 with the following short
program:
10 POKE 55,0:POKE 56,128: CLR: REM LOWER TOP OF MEMORY TO 32768
20 POKE 56576,PEEK(56576) AND 253: REM ENABLE BANK 2
30 POKE 53272,4: REM TEXT DISPLAY MEMORY NOW STARTS AT 32768
40 POKE 648,128:REM OPERATING SYSTEM PRINTS TO SCREEN AT 32768 (128*256)
50 POKE 44,4:POKE 1024,0: REM MOVE START OF BASIC TO 1025 (4*256+1)
60 POKE 792,193: REM DISABLE RESTORE KEY
70 PRINT CHR$(147);"NOW CONFIGURED LIKE PET":NEW
80 REM ALSO SEE ENTRIES FOR LOCATION 55, 56576, AND 648
Such reconfiguring can be helpful in transferring programs from the 64
to the PET, or vice versa. Since the 64 automatically relocates BASIC
program text, it can load and list PET programs even though the
program file indicates a loading addresss that is different from the
64 start of BASIC. The PET does not have this automatic relocation
feature, however, and it loads all BASIC programs at the two-byte
address indicated at the beginning of the disk or tape file.
So if the PET loads a 64 program at its normal starting address of
2049 ($0801), it will not recognize its presence because it expects a
BASIC program to start at 1025 ($0401). Therefore, if you want to let
a PET and 64 share a program, you must either reconfigure the 64 to
start BASIC where the PET does, or reconfigure the PET to start BASIC
where the 64 does (with a POKE 41,8:POKE 2048,0).
2. Raising the lowest location used for BASIC text in order to create
a safe area in low memory. For example, if you wish to use the
high-resolution graphics mode, you may want to put the start of screen
memory at 8192 ($2000). The high-resolution moe requires 8K of
memory, and you cannot use the lowest 8K for this purpose because it
is already being used for the zero-page assignments.
Since BASIC program text normally starts at 2048 ($0801), this means
that you only have 6k for program text before your program runs over
into screen memory. One way around this is by moving the start of
basic to 16385 ($4001) by typing in direct entry mode:
POKE 44,64: POKE 64*256,0:NEW
Other uses might include setting aside a storage area for sprite shape
data, or user-defined character sets.
3. Keeping two or more programs in memory simultaneously. By
changing this pointer, you can keep more than one BASIC program in
memory at one time, and switch back and forth betwenn them. Examples
of this application can be found in COMPUTE!'s First Book of PET/CBM,
pages 66 and 163.
This technique has a number of offshoots that are perhaps of more
practical use.
a) You can store two programs in memory simultaneously for the purpose
of appending one to the other. This technique requires that the line
numbers of the two programs do not overlap. (See Programming the
PET/CBM by Raeto Collin West, pages 41-42, for a discussion of this
technique).
b) You can have two programs in memory at once and use the concept in
(2) above to allow an easier way to create a safe area in low memory.
The first program is just onw line that sets the start of BASIC
pointer to the address of the second program which is located higher
in memory, and then runs that second program.
4. Since this address is used as the address of the first byte to
SAVE, you can save any section of memory by changing this pointer to
indicate the starting address, and the pointer 45-46 ($002D-$002D) to
indicate the address of the byte after the last byte that you wish to
save.
$002D-$002E VARTAB Pointer to the Start of the BASIC Variable Storage Area
This location points to the address which marks the end of the BASIC
program text area, and the beginning of the variable storage area.
All nonarray variables are stored here, as are string descriptors (for
the address of the area where the actual text of strings is stored,
see location 51 ($0033)).
Seven bytes of memory are allocated for each variable. The first two
bytes are used for the variable name, which consists of the ASCII
value of the first two letters of the variable name. If the variable
name is a single letter, the second byte will contain a zero.
The seventh bit of one or both of these bytes can be set (which would
add 128 to the ASCII value of the letter). This indicates the
variable type. If neither byte has the seventh bit set, the variable
is the regular floating point type. If only the first byte has its
seventh bit set, the variable is a string. If only the second byte
has its seventh bit set, the variable is a defined function (FN). If
both bytes have the seventh bit set, the variable is an integer.
The use of the other five bytes depends on the type of variable. A
floating point variable will use the five bytes to store the value of
the variable in floating point format. An integer will have its value
stored in the third and fourth bytes, high byte first, and the other
three will be unused.
A string variable will use the third byte for its length, and the
fourth and fifth bytes for a pointer to the address of the string
text, leaving the last two bytes unused. Note that the acrual string
text that is pointed to is located either in the part of the BASIC
program where the string is first assigned a value, or in the string
text storage area pointed to by location 51 ($0033).
A function definition will use the third and fourth bytes for a
pointer to the address in the BASIC program text where the function
definition starts. It uses the fifth and sixth bytes for a pointer to
the dependent variable (the X of FN A(X)). The final byte is not
used.
Knowing something about how variables are created can help your BASIC
programming. For example, you can see that nonarray integer variables
take up no less space than floating point variables, and since most
BASIC commands convert the integers to floating point, they do not
offer a speed advantage either, and in many cases will actually slow
the program down. As will be seen below, however, integer arrays can
save a considerable amount of space.
Variables are stored in the order in which they are created.
Likewise, when BASIC goes looking for a variable, it starts its search
at the beginning of this area. If commonly used variables are defined
at the end of the program, and are thus at the back of this area, it
will take longer to find them. It may help program execution speed to
define the variables that will be used most frequently right at the
beginning of the program.
Also, remember that once created, variables do not go away during
program execution. Even if they are never used again, they still take
up space in the variable storage area, and they slow down the routine
that is used to search for variables that are referenced.
Another point to consider about the order in which to define variables
is that arrays are created in a separate area of memory which starts
at the end of the nonarray variable area. Therefore, every time a
nonarray variable is created, all of the arrays must be moved seven
bytes higher in memory in order to make room for the new variable.
Therefore, it may help performance to avoid defining nonarray
variables after defining arrays.
This pointer will be reset to one byte past the end of the BASIC
program text whenever you execute the statements CLR, NEW, RUN, or
LOAD. Adding or modifying a BASIC statement will have the same
effect, because the higher numbered BASIC statements have to be moved
up into memory to make room for the new statements, and can therefore
overwrite the variable storage area. This means that if you wish to
check the value of a variable after stopping a program, you can only
do so before modifying the program.
The exception to the above is when the LOAD command is issued from a
program. The purpose of not resetting this pointer in such a case is
to allow the chaining of programs by having one program load and then
run the next (that is also why a LOAD issued from a program causes a
RUN from the beginning of the program). This allows the second
program to share variables with the first. There are problems with
this, however. Some string variable descriptors and function
definitions have their pointers set to areas within the program text.
When this text is replaced by a load, these pointers are no longer
valid, which will lead to errors if the FN or string value is
referenced. And if the second program text area is larger than that
of the first, the second program will overwrite some of the first
program's variables, and their values will be lost.
The ability to chain short programs is a holdover from the days of the
8K PET, for which this BASIC was written, but with the vastly
increased memory of the 64, program chaining should not be necessary.
You should also note that SAVE uses this pointer as the address of the
byte after the last byte to SAVE.
$002F-$0030 ARYTAB Pointer to the Start of the BASIC Array Storage Area
This location points to the address of the end of nonarray variable
storage, and the beginning of array variable storage. The format for
array storage is as follows:
The first two bytes hold the array name. The format and high-bit
patterns are the same as for nonarray variables (see 45 ($002D) above),
except that there is no equivalent to the function definition.
Next comes a two-byte offset to the start of the next array, low byte
first. Then there is a one-byte value for the number of array
dimensions (e.g., 2 for a two-dimensional array like A(x,y)). That
byte is followed by pairs of bytes which hold the value of each array
dimension+1 (DIMensioning an array always makes space for 0, so A(0)
can be used).
Finally come the values of the variables themselves. The format for
these values is the same as with nonarray values, but each value only
takes up the space required; that is, floating point variables use
five bytes each, integers two bytes, and string descriptors three
bytes each.
Remember that as with nonarray string, the actual string text is
stored elsewhere, in the area which starts at the location pointed to
in 51-52 ($0033-$0034).
$0031-$0032 STREND Pointer to End of the BASIC Array Storage Area (+1), and the Start of
Free RAM
This location points to the address of the end of BASIC array storage
space and the start of free RAM. Since string text starts at the top
of memory and builds downwards, this location can also be thought of
as the last possible address of the string storage area. Defining new
variables pushes this pointer upward, toward the last string text.
If a string for which space is being allocated would cross over this
boundary into the array storage area, garbage collection is performed,
and if there still is not enough room, an OUT OF MEMORY error occurs.
FRE performs garbage collection, and returns the difference between
the addresses pointed to here and the address of the end of string
text storage pointed to by location 51 ($0033).
$0033-$0034 FRETOP Pointer to the Bottom of the String Text Storage Area
This pointer marks the current end of the string text area, and the
top of free RAM (strings are built from the top of memory downward).
Additional string texts are added, to the area below the address
pointed to here. After they are added, this pointer is lowered to
point below the newly added string text. The garbage collection
routine (which is also called by FRE) readjusts this pointer upward.
While the power-on/reset routines set this pointer to the top of RAM,
the CLR command sets this pointer to the end of BASIC memory, as
indicated in location 55 ($0037). This allows the user to set aside an
area of BASIC memory that will not be disturbed by the program, as
detailed at location 55 ($0037).
$0035-$0036 FRESPC Temporary Pointer for Strings
This is used as a temporary pointer to the most current string added
by the routines which build strings or move them in memory.
$0037-$0038 MEMSIZ Pointer to the Highest Address Used by BASIC
The power-on/reset routine tests each byte of RAM until it comes to
the BASIC ROM, and sets this pointer to the adress of the highest byte
of consecutive RAM found (40959, $9FFF).
There are two circumstances under which this pointer may be changed
after power-up to reflect an address lower than the actual top of
consecutive RAM:
1. Users may wish to lower this pointer themselves, in order to set
aside an area of free RAM that will not be disturbed by BASIC. For
example, to set aside a 1K area at the top of BASIC, start your
program with the line:
POKE 56,PEEK(56)-4:CLR
The CLR is necessary to insure that the string text will start below
your safe area.
You may wish to store machine language programs, sprites, or alternate
character sets in such an area. For the latter two applications,
however, keep in mind the 16K addressing range limitation of the
VIC-II chip. If you do not assign the VIC-II to a bank other than the
default memory bank of 0-16383 ($0-$3FFF), you must lower the top of
memory below 16383 ($3FFF) if you wish your sprite or character data
area to be within its addressing range.
2. Then the RS-232 device (number 2) is opened, this pointer and the
pointer to the end of user RAM at 643 are lowered by 512 bytes in
order to create two 256-byte buffers, one for input and the other for
output.
Since the contents of these buffers will overwrite any variables at
the top of memory, a CLR command is issued at the time device 2 is
opened. Therefore, the RS-232 device should be opened before defining
any variables, and before setting aside a safe area for machine
language programs or other uses, as described above.
$0039-$003A CURLIN Current BASIC Line Number
This location contains the line number of the BASIC statement which is
currently being executed, in LSB/MSB format. A value of 255 ($FF) in
location 58 ($003A), which translates to a line number of 65280 or above
(well over the 63999 limit for a program line), means that BASIC is
currently in immediate mode, rather than RUN mode.
BASIC keywords that are illegal in direct mode check 58 ($003A) to
determine whether or not this is the current mode.
When in RUN mode, this location is updated as each new BASIC line is
fetched for execution. Therefore, a TRACE function could be added by
diverting the vector at 776 ($0308), which points to the routine that
executes the next token, to a user-written routine which prints the
line number indicated by this location before jumping to the token
execution routine. (LISTing the line itself would be somewhat harder,
because LIST uses many Page 0 locations that would have to be
preserved and restored afterwards.)
This line number is used by BREAK and error messages to show where
program execution stopped. The value here is copied to 59 ($003B) by
STOP, END, and the stop-key BREAK, and copied back by CONT.
$003B-$003C OLDLIN Previous BASIC Line Number
When program execution ends, the last line number executed is stored
here, and restored to location 57 ($0039) by CONT.
$003D-$003E OLDTXT Pointer to the Address of the Current BASIC Statement
This location contains the address (not the line number) of the text
of the BASIC statement that is being executed. The value of TXTPTR
(122, $007A), the pointer tot he address of the BASIC text character
currently being scanned, is stored here each time a new BASIC line
begins execution.
END, STOP, and the STOP-key BREAK save the value of TXTPTR here, and
CONT restores this value to TXTPTR. CONT will not continue if 62
($003E) has been changed to a zero by a LOAD, a modification to the
program text, or by error routines.
$003F-$0040 DATLIN Current DATA Line Number
This location holds the line number of the current DATA statement
being READ. It should be noted that this information is not used to
determine where the next DATA item is read from (that is the job of
the pointer at 65-66 ($0041-$0042) below). But if an error concerning the
DATA occurs, this number will be moved to 57 ($0039), so that the error
message will show that the error occurred in the line that contains
the DATA statement, rather than in the line that contains the READ
statement.
$0041-$0042 DATPTR Pointer to the Address of the Current DATA Item
This location points to the address (not the line number) within the
BASIC program text area where DATA is currently being READ. RESTORE
sets this pointer back to the address indicated by the start of BASIC
pointer at location 43 ($002B).
The sample program below shows how the order in which DATA statements
are READ can be changed using this pointer. The current address of
the statement before the DATA statement is stored in a variable, and
then used to change this pointer.
10 A1=PEEK(61):A2=PEEK(62)
20 DATA THIS DATA WILL BE USED SECOND
30 B1=PEEK(61):B2=PEEK(62)
40 DATA THIS DATA WILL BE USED FIRST
50 C1=PEEK(61):C2=PEEK(62)
60 DATA THIS DATA WILL BE USED THIRD
70 POKE 65,B1:POKE 66,B2:READ A$:PRINT A$
80 POKE 65,A1:POKE 66,A2:READ A$:PRINT A$
90 POKE 65,C1:POKE 66,C2:READ A$:PRINT A$
$0043-$0044 INPPTR Pointer in the Source of GET, READ, or INPUT Information
READ, INPUT and GET all use this as a pointer to the address of the
source of incoming data, such as DATA statements, or the text input
buffer at 512 ($0200).
$0045-$0046 VARNAM Current BASIC Variable Name
The current variable name being searched for is stored here, in the
same two- byte format as in the variable value storage area located at
the address pointed to by 45 ($002D). See that location for an
explanation of the format.
$0047-$0048 VARPNT Pointer to the Current BASIC Variable Value
This location points to the address of the descriptor of the current
BASIC variable (see location 45 ($002D) for the format of a variable
descriptor). Specifically, it points to the byte just after the
two-character variable name.
During a FN call, this location does not point to the dependent
variable (the A of FN A), so that a real variable of the same name
will not have its value changed by the call.
$0049-$004A FORPNT Temporary Pointer to the Index Variable Used by FOR
The address of the BASIC variable which is the subject of a FOR/NEXT
loop is first stored here, but is then pushed onto the stack. That
leaves this location free to be used as a work area by such statements
as INPUT, GET, READ, LIST, WAIT, CLOSE, LOAD, SAVE, RETURN, and GOSUB.
For a description of the stack entries made by FOR, see location 256
($0100).
$004B-$004C OPPTR Math Operator Table Displacement
This location is used during the evaluation of mathematical
expressions to hold the displacement of the current math operator in
an operator table. It is also used as a save area for the pointer to
the address of program text which is currently being read.
$004D OPMASK Mask for Comparison Operation
The expression evaluation routine creates a mask here which lets it
know whether the current comparieson operation is a less-than (1),
equals (2), or greater-than (4) comparison.
$004E-$004F DEFPNT Pointer to the Current FN Descriptor
During function definition (DEF FN) this location is used as a pointer
to the descriptor that is created. During function execution (FN) it
points to the FN descriptor in which the evaluation results should be
saved.
$0050-$0052 DSCPNT Temporary Pointer to the Current String Descriptor
The string assignment and handling routines use the first two bytes as
a temporary pointer to the current string descriptor, and the third to
hold the value of the string length.
$0053 FOUR6 Constant for Garbage Collection
The constant contained here lets the garbage collection routines know
whether a three- or seven-byte string descriptor is being collected.
$0054-$0056 JMPER Jump to Function Instruction
The first byte is the 6502 JMP instruction ($4C), followed by the
address of the required function taken from the table at 41042
($A052).
$0057-$0060 BASIC Numeric Work Area
This is a very busy work area, used by many routines.
$0061-$0066 FAC Floating Point Accumulator #1
The Floating Point Accumulator is central to the execution of any
BASIC mathematical operation. It is used in the conversion of
integers to floating point numbers, strings to floating point numbers,
and vice versa. The results of most evaluations are stored in this
location.
The internal format of floating point numbers is not particularly easy
to understand (or explain). Generally speaking, the number is broken
into the normalized mantissa, which represents a number between 1 and
1.99999..., and an exponent value, which represents a power of 2.
Multiplying the mantissa by 2 raised to the value of the exponent
gives you the value of the floating point number.
Fortunately, the BASIC interpreter contains many routines for the
manipulation and conversion of floating point number, and these
routines can be called by the user. See the entries for locations 3
and 5
Floating Point Accumulator #1 can be further divided into the
following locations:
$0061 FACEXP Floating Point Accumulator #1: Exponent
This exponent represents the closest power of two to the number, with
129 added to take care of the sign problem for negative exponents. An
exponent of 128 is used for the value 0; an exponent of 129 represents
2 to the 0 power, or 1; an exponent of 130 represents 2 to the first
power, or 2; 131 is 2 squared, or 4; 132 is 2 cubed, or 8; and so on.
$0062-$0065 FACHO Floating Point Accumulator #1: Mantissa