Câu lệnh PHP nào sẽ lưu trữ 111 trong biến num?

Câu lệnh/câu lệnh php nào sau đây sẽ lưu trữ 111 trong biến num?1. int $num = 111;2. int mẹ = 111;3. $num = 111;4. 111 = số $;

MỘT]. Cả 1 và 2

b]. Tất cả những điều được đề cập

C]. Chỉ 3

Đ]. Chỉ 1

1 câu trả lời

Đã trả lời bởi Khách vào 2021-06-14 03. 51. 51. phiếu bầu 1. #

Chỉ 3

Bạn không cần chỉ định kiểu dữ liệu trong php

Tham gia nhóm Telegram

Trả lời câu hỏi này

Tên. E-mail. Câu trả lời. Tổng của [3+2]Gửi

Câu lệnh/câu lệnh php nào sau đây sẽ lưu trữ 111 trong biến num?

i] int$num = 111;

ii] intnum = 111;

iii] $num = 111;

iv] 111 = $num;

a] Cả i] và ii]

[b] Tất cả những điều được đề cập

[c] Chỉ iii]

[d] Chỉ i]

Locations zero to 255 [$0 to $FF] are called "page zero" and have
special importance for assembly language programmers since these
locations are accessed faster and easier by the machine.

Locations zero to 127 [$0 to $7F] are reserved as the OS page zero,
while 128 to 255 [$80 to $FF] are the BASIC and the user zero page
RAM. Locations zero to 1792 [$0 to $700] are all used as the OS and [if
the cartridge is present] 8K BASIC RAM [except page six]. Locations
zero to 8191 [$0 to $1FFF] are the minimum required for operation
[8K].

Locations two through seven are not cleared on any start operation.

DECIMAL HEX LABEL

CASINI for initialization. JSR through DOSVEC [10 and 11; $A,$B] to transfer control to the application.

RAMTOP, location 106 [$6A]. Reads one when the BASIC or the A [left] cartridge is plugged in.

RAMLO, TRAMSZ and TSTDAT are all used in testing the RAM size on powerup. On DOS boot, RAMLO and TRAMSZ also act as temporary storage for the boot continuation address. TRAMSZ and TSTDAT are used later to flag whether or not the A [left] and/or B [right] cartridges, respectively, are plugged in [non- zero equals cartridge plugged in] and whether the disk is to be hooted. Locations eight through 15 [$8-$F] are cleared on coldstart only.

WARMST is initialized to zero and will not change values unless POKEd or until the first time the RESET button is pressed. It will then read 255 [$FF]. Warmstart normally vectors to location 58484 [$E474]. WARMST is checked by the NMI status register at 54287 [$D40F] when RESET is pressed to see whether or not to re-initialize the software or to re-boot the disk.

DOS vector at 10 and 11 [$A and $B]. Coldstart attempts both a cassette and a disk boot and flags this location with the success or failure of the boots. BOOT? is checked during both disk and cassette boot.

DOS. Can be set by user to point to your own routine, but RESET will return DOSVEC to the original address. To prevent this, POKE 5446 with the LSB and 5450 with the MSB of your vector address and re-save DOS using the WRITE DOS FILES option in the menu. Locations 10 and 11 are usually loaded with 159 and 23 [$9F and $17], respectively. This allows the DUPSYS section of DOS to be loaded when called. It is initially set to blackboard mode vector [58481; $E471--called by typing "BYE" or "B." from BASIC]; it will also vector to the cassette run address if no DOS vector is loaded in. If you create an AUTORUN.SYS file that doesn't end with an RTS instruction, you should set BOOT? to one and 580 [$244] to zero.

CASINI [2, 3]. When you powerup without either the disk or an autoboot cassette tape, DOSINI will read zero in both locations.

APPMHI, then the screen is set up for GRAPHICS mode zero; MEMTOP [locations 741, 742; $2E5, $2E6] is updated and an error is returned to the user. Otherwise, the memory is not too small for the screen editor; the mode change will take effect and MEMTOP will be updated. This is one of five locations used by the OS to keep track of the user and display memory. Initialized to zero by the OS at powerup. Remember, you cannot set up a screen display below the location specified here. If you use the area below the Display List for your character sets, PM graphics or whatever, be sure to set APPMHI above the last address used so that the screen or the DL data will not descend and destroy your own data. See RAMTOP location 106 [$6A], MEMTOP at 741, 742 [$2E5, $2E6], PMBASE at 54279 [$D407] and CHBASE at 54281 [$D409] for more information. Locations 16 through 127 [$10-$7F] are cleared on either cold- or warmstart.

STATUS [48; $30]. It is also checked during all I/O and scroll/draw routines. During the keyboard handler routine, the status code is stored in DSTAT [76; $4C]. BRKKEY is turned off at powerup. BREAK key abort status is flagged by setting BIT 7 of 53774 [$D20E]. See the note on the BREAK key vector, above.

DOS; used as vector to FMS.

BUFADR by DOS, it points to the area saved for a buffer for the utilities package [data buffer; DBUF] or for the program area [MEMLO; 743, 744; $2E7, $2E8].

PBUFSZ is initialized to 40. The printer handler checks to see if the same value is in PBPNT and, if so, sends the contents of the buffer to the printer.

DOS to in- dicate the maximum number of devices. Initialized to one.

STATUS command.

STATUS, etc.

STATUS uses location 793 [$319] as temporary storage. STATUS is also used as a storage register for the timeout, BREAK abort and error values during SIO routines.

ICAX2Z] in the ZIOCB, stored there from DAUX2 [779; $30B] by the user. Normal gaps are a non-zero positive number; continuous gaps are zero [negative number].

CRITIC to a non-zero value suspends a number of OS processes including system software timer coun- ting [timers two, three, four and five; see locations 536 to 558; $218 to $22E]. It is suggested that you do not set CRITIC for any length of time. When one timer is being set, CRITIC stops the other timers to do so, causing a tiny amount of time to be "lost." When CRITIC is zero, both stage one and stage two VBLANK procedures will be executed. When non-zero, only the stage one VBLANK will be processed.

CKEY is set. Autoboot cassettes are loaded by pressing the START console key while turning the power on. In response to the beep, press the PLAY button on the recorder.

ATRACT reaches 127 [$7F], it is then set to 254 [$FE] un- til attract mode is terminated. This sets the flag to reduce the luminance and rotate the colors when the Atari is sitting idle. POKE with 128 [$80] to see this effect immediately: it normally takes seven to nine minutes to enable the attract mode. The OS cannot "attract" color generated by DLI's, although your DLI routine can, at a loss of time. Joysticks alone will not reset location 77 to zero. You will have to add a POKE 77,0 to your program periodically or frequently call in a subroutine to prevent the Atari from entering attract mode if you are not using any keyboard input.

COLRSH contains the current value of location 19, therefore is given a new color value every 4.27 seconds. Bytes 80 to 122 [$50 to $7A] are used by the screen editor and display handler.

LMARGN is initialized to two. You can POKE the margin locations to set them to your specific program needs, such as POKE 82,10 to make the left margin start ten locations from the edge of the screen.

LINE and INSERT LINE keys delete or insert 40 character lines [or delete one program line], which always start at the left margin and wrap around the screen edge back to the left margin again. The right margin is ignored in the process. Also, logical lines are always three physical lines no matter how long or short you make those lines. The beep you hear when you are coming to the end of the logical line works by screen position independent of the margins. Try setting your left margin at 25 [POKE 82,25] and typing a few lines of characters. Although you have just a few characters beyond 60, the buzzer will still sound on the third line of text.

ROWCRS and COLCRS define the cursor location for the next element to be read from or written to in the main screen segment of the display. For the text window cursor, values in locations 656 to 667 [$290 to $29B] are exchanged with the current values in locations 84 to 95 [$54 to $5F], and location 123 [$7B] is set to 255 [$FF] to indicate the swap has taken place. ROWCRS and COLCRS are also used in the DRAW and FILL functions to contain the values of the endpoint of the line being drawn. The color of the line is kept in location 763 [$2FB]. These values are loaded into locations 96 to 98 [$60 to $62] so that ROWCRS and COLCRS may be altered during the operation. BASIC's LOCATE statement not only examines the screen, but also moves the cursor one position to the right at the next PRINT or PUT statement. It does this by updating locations 84 and 85, above. You can override the cursor advance by saving the contents of the screen before the LOCATE command, then restoring them after the LOCATE. Try: 100 REM: THE SCREEN MUST HAVE BEEN 0 PENED FOR READ OR READ/WRITE PREV IOUSLY 110 LOOK = PEEK[84]: SEE = PEEK[85] 120 LOCATE X,Y,THIS 130 POKE 84, LOOK: POKE 65, SEE Note that CHR$[253] is a non-printing character---the bell-- and doesn't affect the cursor position. See COMPUTE!, August 198l, for an example of using COLCRS for dynamic data restore and updating with the screen editor and the IOCBs.

DINDEX contains the number obtained from the low order four bits of most recent open AUX1 byte. It can be used to fool the OS into thinking you are in a different GRAPHICS mode by POKEing DINDEX with a number from zero to 11. POKE with seven after you have entered GRAPHICS mode eight, and it will give you a split screen with mode seven on top and mode eight below. However, in order to use both halves of the screen, you will have to modify location 89 [below] to point to the area of the screen you wish to DRAW in. [See Your Atan 400/800, pp. 280 - 283.] Watch for the cursor out-of-range errors [number 141] when changing GRAPHICS modes in this manner and either PRINTing or DRAWing to the new mode screen. POKE 87 with the BASIC mode number, not the ANTIC mode number. Did you know you can use PLOT and DRAWTO in GR.0? Try this: 10 GR.0 20 PLOT 0,0: DRAWTO 10,10: DRAWTO 0 ,10 30 DRAWTO 39,0: DRAWTO 20,23: DRAWT O 0,20 40 GOTO 40 You can also set the text window for PRINT and PLOT modes by POKEing 87 with the graphics mode for the window. Then you must POKE the address of the top left corner of the text window into 88 and 89 [$58, $59]. The screen mode of the text window is stored at location 659 [$293]. You may have already discovered that you cannot call up the GTIA modes from a direct command. Like the + 16 GRAPHICS modes, they can only be called up during a program, and the screen display will be reset to GR.0 on the first INPUT or PRINT [not PRINT#6] statement executed in these modes. Since this location only takes BASIC modes, you can't POKE it with the other ANTIC modes such as "E", the famous "seven-and- a-half" mode which offers higher resolution than seven and a four color display [used in Datasoft's Micropainter program]. If you're not drawing to the screen, simply using it for display purposes, you can always go into the Display List and change the instructions there. But if you try to draw to the screen, you risk an out-of-bounds error [error number 141]. See Creative Computing, March 1982, for an excellent look at mode 7.5. The short subroutine below can be used to change the Display List to GR.7.5: 1000 GRAPHICS 8+16: DLIST = PEEK[560] ] + PEEK[561] * 256:POKE DLIST + 3,78 1010 FOR CHANGE = DLIST + 6 TO DLIST + 204: IF PEEK[CHANGE] = 15 THE N POKE CHANGE,14 1020 IF PEEK [CHANGE] = 79 THEN POKE CHANGE,78: NEXT CHANGE 1030 POKE 87,7:RETURN DOWNLOAD MODE75.BAS [Actually, 15 [$F] is the DL number for the maximum memory mode; it also indicates modes eight through eleven. The DL's for these modes are identical.] Fourteen is the ANTIC E mode; GR.7.5 This program merely changes GR.8 to mode E in the Display List. The value 79 is 64 + 15; mode eight screen with BIT 6 set for a Load Memory Scan [LMS] instruction [see the DL information in locations 560, 561; $230, $231]. It does not check for other DL bits. You can also POKE 87 with the GTIA values [nine to eleven]. To get a pseudo-text window in GTIA modes, POKE the mode number here and then POKE 623 with 64 for mode nine, 128 for mode ten, and 192 for mode eleven, then POKE 703 with four, in program mode. [In command mode, you will be returned to GR.0.] You won't be able to read the text in the window, but you will be able to write to it. However, to get a true text window, you'll need to use a Display List Interrupt [see COMPUTE!, September 1982]. If you don't have the GTIA chip, it is still possible to simulate those GRAPHICS modes by using DINDEX with changes to the Display List Interrupt. See COMPUTE!, July 1981, for an example of simulating GR.10.

SAVEMSC1.BAS You will notice that you get the Atari internal character code, not the ATASCII code. See also locations 560, 561 [$230, $231] and 57344 [$E000]. How do you find the entire screen RAM? First, look at the chart below and find your GRAPHICS mode. Then you multiply the number of rows-per-screen type by the number of bytes-per-line. This will tell you how many bytes each screen uses. Add this value, minus one, to the address specified by SAVMSC. However, if you subtract MEMTOP [locations 741, 742; $2E5, $2E6] from RAMTOP [106; $6A * 256 for the number of bytes], you will see that there is more memory reserved than just the screen area. The extra is taken up by the display list or the text window, or is simply not used [see the second chart below]. Mode 0 1 2 3 4 5 6 7 8 9-12 Rows Full 24 24 12 24 48 48 96 96 192 192 Split -- 20 10 20 40 40 80 80 160 -- Bytes per Line 40 20 20 10 10 20 20 40 40 40 Columns per Line 40 20 20 40 80 80 160 160 320 80 Memory [1] 993 513 261 273 537 1017 2025 3945 7900 7900 Memory [2] Full 992 672 420 432 696 1176 2184 4200 8138 8138 Split -- 674 424 434 694 1174 2174 4190 8112 -- [1] According to the Atari BASIC Reference Manual, p.45; OS User's Manual, p.172, and Your Atari 400/800, p.360. [2] According to Your Atari 400/800, p.274, and Atari Microsoft Basic Manual, p.69. This is also the value you get when you subtract MEMTOP from RAMTOP [see above]. For example, to POKE the entire screen RAM in GR.4, you would find the start address of the screen [PEEK[88] + PEEK[89] * 256], then use a FOR-NEXT loop to POKE all the locations specified above: 10 GRAPHICS 4: SCRN = PEEK[88] + PE EK[89] * 256 20 FOR LOOP = SCRN to SCRN + 479: R EM 48 ROWS * 10 BYTES - 1 30 POKE LOOP,35: NEXT LOOP DOWNLOAD SAVEMSC2.BAS Why the minus one in the calculation? The first byte of the screen is the first byte in the loop. If we add the total size, we will go one byte past the end of the soreen, so we subtract one from the total. Here's how to arrive at the value for the total amount ot memory located for screen use, display list and Text window: Total memory allocation for the screen Screen display Display List ----------------------------------------------------------- Text unused bytes screen unused used GR window always cond. use bytes bytes Total ----------------------------------------------------------- 0 .. none none 960 none 32 992 1 160 none 80 400 none 34 674 2 160 none 40 200 none 24 424 3 160 none 40 200 none 34 434 4 160 none 80 400 none 54 694 5 160 none 160 800 none 54 1174 6 160 none 320 1600 none 94 2174 7 160 none 640 3200 96 94 4190 8 160 16 1280 6400 80 176 8112 The number of bytes from RAMTOP [location 106; $6A] is counted from the left text window column towards the total column. MEMTOP [741, 742; $2E5, $2E6] points to one byte below RAMTOP * 256 minus the number of bytes in the total column. If 16 is added to the GRAPHICS mode [no text window], then the conditional unused bytes are added to the total. Then the bytes normally added for the text window become unused, and the Display List expands slightly. [See COMPUTE!, September 1981.] When you normally PRINT CHR$[125] [clear screen], Atari sends zeroes to the memory starting at locations 88 and 89. It continues to do this until it reaches one byte less than the contents of RAMTQP [location 106; $6A]. Here is a potential source of conflict with your program, however: CHR$[125]--CLEAR SCREEN--and any GRAPHICS command actually continue to clear the first 64 [$40] bytes above RAMTOP! It would have no effect on BASIC since BASIC is a ROM cartridge. The OS Source Listing seems to indicate that it ends at RAMTOP, but Atari assumed that there would be nothing after RAMTOP, so no checks were provided. Don't reserve any data within 64 bytes of RAMTOP or else it will be eaten by the CLEAR SCREEN routine, or avoid using a CLEAR SCREEN or a GRAPHICS command. Scrolling the text window also clears 800 bytes of memory above RAMTOP. You can use this to clear other areas of memory by POKEing the LSB and MSB of the area to be cleared into these locations. Your routine should always end on a $FF boundary [RAMTOP indicates the number of pages]. Remember to POKE back the proper screen locations or use a GRAPHICS command immediately after doing so to set the screen right. Try this: 10 BOTTOM = 30000: TOP = 36863: REM LOWEST AND HIGHEST ADDRESS TO CLEA R = $7530 & $8FFF 20 RAMTOP = PEEK[106]: POKE 106, INT [TOP + 1 / 256] 30 TEST = INT[BOTTOM / 256]: POKE89, TEST 40 POKE 88. BOTTOM - 256 * TEST 50 PRINT CHR$[125]: POKE 106, RAMTOP 60 GRAPHICS 0 DOWNLOAD SAVEMSC3.BAS This will clear the specified memory area and update the address of screen memory. If you don't specify TOP, the CLEAR SCREEN will continue merrily cleaning out memory and, most likely, will cause your program to crash. Use it with caution. Here's a means to SAVE your current GR.7 screen display to disk using BASIC: 1000 SCREEN = PEEK[88] + PEEK[89] * 256 1010 OPEN #2,8,0,"D:picturename" 1020 MODE = PEEK[87]: PUT #2, MODE: REM SAVE GR. MODE 1030 FOR SCN = 0 TO 4: COL PEEK[70 8 + SCN]: PUT #2,COL: NEXT SCN: REM SAVE COLOR REGISTERS 1040 FOR TV = SCREEN TO SCREEN + 319 9:BYTE = PEEK[TV]: PUT #2, BYTE: NEXT TV: CLOSE #2 DOWNLOAD SAVEMSC4.BAS To use this with other screen modes, you will have to change the value of 3199 in line 1040 to suit your screen RAM [see the chart above]. For example, GR.7 + 16 would require 3839 bytes [3840 minus one]. You can use the same routine with cassette by using device C:. To retrieve your picture, you use GET#2 and POKE commands. You will, however, find both routines very slow. Using THE CIO routine at 58454 [$E456] and the IOCBs, try this machine language save routine: 10 DIM ML$[10]: B$[10]: GR.8+16 20 B$ = "your picture name":Q = PEEK [559] 30 FOR N = 1 TO 6: READ BYTE: ML$[N, N] = CHR$[BYTE]: NEXT N 35 DATA 104,162,16,76,86,228 36 REM PLA,LDX,$10,JMP $E456 40 OPEN #1,4,0,B$ 50 POKE 849,1: POKE 850,7: POKE 852, PEEK[88]: POKE 853,PEEK[89]: POKE 856,70: POKE 857,30: POKE 858,4 55 REM THESE POKES SET UP THE IOCB 60 POKE 559,0: REM TURN OFF THE SCRE EN TO SPEED THINGS UP 70 X = USR[ADR[ML$]]: CLOSE #1 80 POKE 559,Q: REM TURN IT BACK ON A GAIN DOWNLOAD SAVEMSC5.BAS Note that there is no provision to SAVE the color registers in this program, so I suggest you have them SAVEd after you have SAVEd the picture. It will make it easier to retrieve them if they are at the end of the file. You will have to make suitable adjustments when SAVEing a picture in other than GR.8 + 16 -- such as changing the total amount of screen memory to be SAVEd, POKEd into 856 and 857. Also, you will need a line such as 1000 GOTO 1000 to keep a GTIA or + 16 mode screen intact. See the Atari column in InfoAge Magazine, July 1982, for more on this idea. See location 54277 [$D405] for some ideas on scrolling the screen RAM. ------------------------------------------------------------------------ A SHORT DIGRESSION There are two techniques used in this hook for calling a machine language program from BASIC with the USR command. One method is to POKE the values into a specific address -- say, page six -- and use the starting address for the USR call, such as X = USR[1536]. For an example of this technique, see location 632 [$278]. The other technique, used above, is to make a string [ML$] out of the routine by assigning to the elements of the string the decimal equivalents of the machine language code by using a FOR-NEXT and READ-DATA loop. To call this routine, you would use X = USR[ADR[ML$]]. This tells the Atari to call the machine language routine located at the address where ML$ is stored. This address will change with program size and memory use. The string method won't be overwritten by another routine or data since it floats around safely in memory. The address of the string itself is stored by the string/array table at location 140 [$8C]. ------------------------------------------------------------------------

DRAW or FILL

NEWROW and NEWCOL are initialized to the values in ROWCRS and COLCRS [84 to 86; $54 to $56] above, which represent the destination end point of the DRAW and FILL functions. This is done so that ROWCRS and COLCRS can be altered during these routines.

LOGCOL can range between zero and 119. Used by the display handler.

MEMTOP value after DL entry, row column address, DMASK value, data to the right of cursor, scroll, delete, the clear screen routine and for the screen address memory [locations 88, 89; $58, $59].

ADRESS above for the data under the cursor and in moving line data on the screen.

TRAMSZ [location 6], given in the total number of available pages [one page equals 256 bytes, so PEEK[106] * 256 will tell you where the Atari thinks the last usable address --byte-- of RAM is]. MEMIOP [741, 742; $2E5. $2E6] may not extend below this value. In a 48K Atari, RAMTOP is initialized to 160 [$A0], which points to location 40960 [$A000]. The user's highest address will be one byte less than this value. This is initially the same value as in location 740. PEEK[740] / 4 or PEEK[106] / 4 gives the number of 1K blocks. You can fool the computer into thinking you have less memory than you actually have, thus reserving a relatively safe area for data [for your new character set or player/missile characters, for example] or machine language subroutines by: POKE[106], PEEK[106] - # of pages you want to reserve. The value here is the number of memory pages [256-byte blocks] present. This is useful to know when changing GR.7 and GR.8 screen RAM. If you are reserving memory for PM graphics, POKE 54279, PEEK[106] - # of pages you are reserving before you actually POKE 106 with that value. To test to see if you have exceeded your memory by reserving too much memory space, you can use: 10 SIZE = [PEEK[106] - # of pages] * 256 20 IF SIZE < = PEEK[144] + PEEK[145 ] * 256 THEN PRINT "TOO MUCH MEMOR Y USED" If you move RAMTOP to reserve memory, always issue a GRAPHICS command [even issuing one to the same GRAPHICS mode you are in will work] immediately so that the display list and data are moved beneath the new RAMTOP. You should note that a GRAPHICS command and a CLEAR command [or PRINT CHR$[125]] actually clear the first 64 bytes above RAMTOP [see location 88; $58 for further discussion]. Scrolling the text window of a GRAPHICS mode clears up to 800 [$320] bytes above RAMTOP [the text window scroll actually scrolls an entire GR.0 screen-worth of data, so the unseen 20 lines * 40 bytes equals 800 bytes]. PM graphics may be safe [unless you scroll the text window] since the first 384 or 768 bytes [double or single line resolution, respectively] are unused. However, you should take both of these effects into account when writing your programs. To discover the exact end of memory, use this routine [it's a tad slow]: 10 RAMTOP = 106: TOP = PEEK[RAMTOP] 20 BYTE = TOP * 256: TEST = 255 - PE EK[BYTE]: POKE BYTE,TEST 30 IF PEEK[BYTE] = TEST THEN TOP = T OP +1: POKE BYTE, 255 - TEST 40 GOTO 20 50 PRINT "MEMORY ENDS AT "; BYTE One caution: BASIC cannot always handle setting up a display list and display memory for GRAPHICS 7 and GRAPHICS 8 when you modify this location by less than 4K [16 pages; 4096 bytes]. Some bizarre results may occur if you use PEEK[106] - 8 in these modes, for example. Use a minimum of 4K [PEEK[106] - 16] to avoid trouble. This may explain why some people have difficulties with player/missile graphics in the hi-res [high resolution; GR.7 and GR.8] modes. See location 54279 [$D407]. Another alternative to reserving memory in high RAM is to save an area below MEMLO, location 743 [$2E7: below your BASIC program]. See also MEMTOP, locations 741, 742 [$2E5, $2E6].

BUFCNT above.

ROWAC and COLAC [below] are both working accumulators for the control of row and column point plotting and the increment and decrement functions.

DELTAR or DELTAC [locations 118 and 119, below] to be used in conjunction with ROWAC/COLAC [locations 112 and 114, above] to control the plotting of line points.

ROWCRS [location 84; $54].

NEWCOL [location 97; $61] minus the value in COLCRS [location 85; $55]. These delta register values, along with locations 121 and 122 below, are used to define the slope of the line to be drawn.

ROWINC and COLINC control the direction of the line drawing routine. The values represent the signs derived from the value in NEWROW [location 96; $60] minus the value in ROWCRS [location 84; $54] and the value in NEWCOL [locations 97, 98; $61, $62] minus the value in COLCRS [locations 85, 86; $55, $56].

SWPFLG helps to keep track of which data set is in these locations.

DELTAR [location 118; $76] or DELTAC [location 119; $77]. This is the number of iterations required to draw a line. As each point on a line is drawn, this value is decremented. When the byte equals zero, the line is complete [drawn]. --------------------------------------------------------------------- User and/or BASIC page zero RAM begins here. Locations 128 to 145 [$80 to $91] are for BASIC program pointers; 146 to 202 [$92 to $CA] are for miscellaneous BASIC RAM; 203 to 209 [$CB to $D1] are unused by BASIC, and 210 to 255 [$D2 to $FF] are the floating point routine work area. The Assembler Editor cartridge uses locations 128 to 176 [$80 to $B0] for its page zero RAM. Since the OS doesn't use this area, you are free to use it in any non-BASIC or non-cartridge environment. If you are using another language such as FORTH, check that program's memory map to see if any conflict will occur. See COMPUTE!'s First Book of Atari, pages 26 to 53, for a discussion of Atari BASIC structure, especially that using locations 130 to 137 [$82 to $89]. Included in the tutorials are a memory analysis, a line dump, and a renumber utility. See also De Re Atari, BYTE, February 1982, and the locations for the BASIC ROM 40960 to 49151 [$A000 to $BFFF].

MEMLO [locations 743, 744; $2E7, $2E8] on initialization or the execution of a NEW command [not on RESET!]. Remember to update this value when changing MEMLO to reserve space for drivers or buffers. When a BASIC SAVE is made, two blocks of information are written: the first block is the seven pointers from LOMEM to STARP [128 to 141; $80 to $8D]. The value of LOMEM is subtracted from each of these two-byte pointers in the process, so the first two bytes written will both be zero. The second block contains the following: the variable name table, the variable value table, the tokenized program, and the immediate mode line. When a BASIC LOAD is made, BASIC adds the value at MEMLO [743, 744; $2E7, $2E8] to each of the two-byte pointers SAVEd as above. The pointers are placed back in page zero, and the values of RUNSTK [142, 143; $8E, $8F] and MEMTOP [144, 145; $90, $91] are set to the value in STARP. Then 256 bytes are reserved above the value in MEMLO for the token output buffer, and the program is read in immediately following this buffer. When you don't have DOS or any other application program using low memory loaded, LOMEM points to 1792 [$700]. When DOS 2.0 is present, it points to 7420 [$1CFC]. When you change your drive and data buffer defaults [see 1801, 1802; $709, $70A], you will raise or lower this figure by 128 bytes for each buffer added or deleted, respectively. When you boot up the RS-232 handler, add another 1728 [$6C0] bytes used. LOMEM is also called ARGOPS by BASIC when used in expression evaluation. When BASIC encounters any kind of expression, it puts the immediate results into a stack. ARGOPS points to the same 256 byte area; for this operation it is reserved for both the argument and operator stack. It is also called OUTBUFF for another operation, pointing to the same 256 byte buffer as ARGOPS points to. Used by BASIC when checking a line for syntax and converting it to tokens. This buffer temporarily stores the tokens before moving them to the program.

VNTP.BAS See COMPUTE!, October 1981.

VNTD1.BAS Or try this, for a possibly less opaque example of the same routine: 1000 NUM = 0: FOR LOOP = PEEK [130] + PEEK[131] * 256 TO PEEK[132] + PEEK[133] * 256 - 1 1010 IF PEEK[LOOP] < 128 THEN PRINT CHR$[PEEK[LOOP]];: GOTO 1030 1020 PRINT CHR$[PEEK[LOOP] - 128]: N UM - NUM + 1 1030 NEXT LOOP: PRINT; PRINT NUM; " VARIABLES IN USE": END DOWNLOAD VNTD2.BAS

STARP String;DIMed 129 var # offset length DIM unDIMed 128 from STARP In scalar [undimensioned numeric] variables, bytes three to eight are the FP number; byte three is the exponent; byte four contains the least significant two decimal digits, and byte eight contains the most significant two decimal digits. In array variables, bytes five and six contain the size plus one of the first dimension of the array [DIM + 1; LSB/MSB], and bytes seven and eight contain the size plus one of the second dimension [the second DIM + 1; LSB/MSB]. In string variables, bytes five and six contain the current length of the variable [LSB MSB], and bytes seven and eight contain the actual dimension [up to 32767]. There is an undocumented BASIC statement, "COM," mentioned only in the BASIC Reference Manual's index, which executes exactly the same as the "DIM" statement [see Your Atari 400/800, p.346]. Originally, it was to be used to implement "common" variables. In all cases, the first byte is always one of the number listed on the chart above [you will seldom, if ever, see the undimensioned values in a program]. This number defines what type of variable information will follow. The next byte, var # [variable number], is in the range from zero to 127. Offset is the number of bytes from the beginning of STARP at locations 140 and 141 [$8C, $8D]. Since each variable is assigned eight bytes, you could find the values for each variable by: 1000 VVTP = PEEK[134] + PEEK[135] * 256: INPUT VAR: REM VARIABLE NUM BER 1010 FOR LOOP = 0 TO 7: PRINT PEEK[V VTP + LOOP + 8 * VAR]: NEXT LOOP where VAR is the variable number from zero to 127. If you wish to assign the same value to every element in a DIMed string variable use this simple technique: 10 DIM TEST$[100] 20 TEST$ = "*": REM or use TEST$[1] 30 TEST$[100] = TEST$ 40 TEST$[2] = TEST$: PRINT TEST$ By assigning the first, last and second variables in the array in that order, your Atari will then assign the same value to the rest of the array. Make sure you make the second and last elements equal to the string, not the character value [i.e don't use TEXT$[2] = "*"]. See De Re Atari for an example of SAVEing the six-byte BCD numbers to a disk file -- very useful when dealing with fixed record lengths.

STMTAB = PEEK[136] + PEEK[137]*2 56 20 NUM = PEEK[STMTAB] + PEEK [STMTAB +1]*256 30 IF NUM = 32768 THEN END 40 PRINT"LINE NUMBER: ";NUM;" ADDRE SS: ";STMTAB 50 STMTAB = STMTAB + PEEK[STMTAB+2] 60 GOTO 20 The August 1982 issue of ANTIC provided a useful program to delete a range of BASIC line numbers. The routine can be appended to your program and even be used to delete itself.

ADRESS OF A$ + 10 BYTE S = ADDRESS OF B$ This table is expanded as each dimension is processed by BASIC, reducing available memory. A ten-element numeric array will require 60 bytes for storage. An array variable such as DIM A[100] will cost the program 600 bytes [100 * six per dimensioned number equals 600]. On the other hand, a string array such as DIM A$[100] will only cost 100 bytes! It would save a lot of memory to write your arrays as strings and retrieve the array values using the VAL statement. For example: 10 DIM A$[10]: A$ = "1234567890" 20 PRINT VAL[A$] 30 PRINT VAL[A$[4,4]] 40 PRINT VAL[A$[3,3]]+VAL[A$[8,9]] See COMPUTE!, June 1982, for a discussion of STARP and VVTP. See De Re Atari for a means to SAVE the string/array area with your program.

RUNSTK is also called ENDSTAR; it is used by BASIC to point to the end of the string/array space pointed to by STARR above.

FRE[0] command [which actually subtracts the MEMTOP value that is at locations 741 and 742; $2E5, $2E6]. Not to be confused with locations 741 and 742, which have the same name but are an OS variable. MEMTOP is also called TOPSTK; it points to the top of the stack space pointed to by RUNSTK above. When reserving memory using location 106 [$6A] and MEMTOP, here's a short error-trapping routine you can add: 10 SIZE = [PEEK[106] - # of pages yo u are reserving] * 256 20 IF SIZE < = PEEK[144] + PEEK[145 ] * 256 THEN PRINT " PROGRAM TOO L ARGE": END Locations 146 to 202 [$92 to $CA] are reserved for use by the 8K BASIC ROM. Locations 176 to 207 [$B0 to $CF] are reserved by the Assembler Editor cartridge for the user's page zero use. The Assembler debug routine also reserves 30 bytes in page zero, scattered from location 164 [$A4] to 255 [$FF], but they cannot be used outside the debug process. [See De Re Atari, Rev. 1, Appendix A for a list of these available bytes.]

TABMAP [locations 675 to 689; $2A3 - $2B1]. PTABW is not reset to the default value by pressing RESET or changing GRAPHICS modes [unlike TABMAP]. PTABW works in all GRAPHICS modes, not merely in text modes. The size of the spaces between items depends on the pixel size in the GRAPHICS mode in use. For example, in GR.0, each space is one character wide, while in GR.8 each space is one-half color clock [one dot] wide.

FR0 can be used by a machine language routine, provided FR0 isn't used and no FP functions are used by that routine. To use 16 bit values in FP, you would place the two bytes of the number into the least two bytes of FR0 [212, 213; $D4, $D5], and then do a JSR to $D9AA [55722], which will convert the integer to its FP representation, leaving the result in FR0. To reverse this operation, do a JSR to $D9D2 [55762].

FR0. The FP package frequently transfers data between these two registers and uses both for two-number arithmetic operations.

INBUFF below.

RADFLG to radians.

DOS and BASIC. This area is page one. Machine language JSR, PHA and interrupts all cause data to be written to page one, and RTS, PLA and RTI instructions all read data from page one. On powerup or RESET, the stack pointer is initialized to point to location 511 [$1FF]. The stack then pushes downward with each entry to 256 [$100]. In case of overflow, the stack will wrap around from 256 back to 511 again. ---------------------------------------------------------------------------

PAGES TWO TO FOUR

Locations 512 to 1151 [$200 to $47F] are used by the OS for working variables, tables and data buffers. In this area, locations 512 to 553 [$200 to $229] are used for interrupt vectors, and locations 554 to 623 [$22A to $26F] are for miscellaneous use. Much of pages two through five cannot be used except by the OS unless specifically noted. A number of bytes are marked as "spare", i.e., not in use currently. The status of these bytes may change with an Atari upgrade, so their use is not recommended. There are two types of interrupts: Non-Maskable Interrupts [NMI] processed by the ANTIC chip and Interrupt Requests [IRQ] processed by the POKEY and the PIA chips. NMI's are for the VBLANK interrupts [VBI's; 546 to 549, $222 to $225], display list interrupts [DLI] and RESET key interrupts. They initiate the stage one and stage two VBLANK procedures; usually vectored through an OS service routine, they can be vectored to point to a user routine. IRQ's are for the timer interrupts, peripheral and serial bus interrupts, BREAK and other key interrupts, and 6502 BRK instruction interrupts. They can usually be used to vector to user routines. See NMIST 54287 [$D40F] and IRQEN 53774 [$D20E] for more information. NMI interrupt vectors are marked NMI; IRQ interrupt vectors are marked IRQ. Refer to the chart below location 534 for a list of the interrupt vectors in the new OS "B" version ROMs.

VDSLST to the routine written by the user. DLI's are disabled on powerup, but VBI's are enabled [see 546 to 549; $222 to $225]. VDSLST is initialized to point to 59315 [$E7B3], which is merely an RTI instruction. To enable DLI's, you must first POKE 54286 [$D40E] with 192 [$C0]; otherwise, ANTIC will ignore your request. You then POKE 512 and 513 with the address [LSB/MSB] of the first assembly language routine to execute during the DLI. You must then set BIT 7 of the Display List instruction[s] where the DLI is to occur. You have only between 14 and 61 machine cycles available for your DLI, depending on your GRAPHICS mode. You must first push any 6502 registers onto the stack, and you must end your DLI with an RTI instruction. Because you are dealing with machine language for your DLI, you can POKE directly into the hardware registers you plan to change, rather than using the shadow registers that BASIC uses. There is, unfortunately, only one DLI vector address. If you use more than one DLI and they are to perform different activities, then changing the vectoring to point to a different routine must be done by the previous DLI's themselves. Another way to accomplish interrupts is during the VBLANK interval with a VBI. One small problem with using DLI's is that the keyboard "click" routine interferes with the DLI by throwing off the timing, since the click is provided by several calls to the WSYNC register at 54282 [$D40A]. Chris Crawford discusses several solutions in De Re Atari, but the easiest of them is not to allow input from the keyboard! See Micro, December 1981, Creative Computing, July 1981 and December 1981. Here's a short example of a DLI. It will print the lower half of your text screen upside down: 10 START = PEEK[560] + PEEK[561] * 256: POKE START + 16,130 20 PAGE = 1536: FOR PGM = PAGE TO P AGE + 7: READ BYTE: POKE PGM, BYTE : NEXT PGM 30 DATA 72,169,4,141,1,212,104,64 40 POKE 512,0: POKE 513,6: POKE 542 86,192 50 FOR TEST = 1 TO 240: PRINT"SEE " ;: NEXT TEST 60 GOTO 60 DOWNLOAD VDSLST.BAS Another example of a DLI changes the color of the bottom half of the screen. To use it, simply change the PAGE + 7 to PAGE + 10 in the program above and replace line 30 with: 30 DATA 72,169,222,141,10,212,141,2 4,208,104,64 Finally, delete lines 50 and 60. See also location 54282 [$D40A].

VKEYBD can be used to process the key code before it undergoes conversion to ATASCII form. Initialized to 65470 [$FFBE] which is the OS keyboard IRQ routine.

DOS, it is used as an interrupt vector location for an SIO patch. DOS changes this vector to 6691 [$1A23], the start of the DOS interrupt ready service routine. IRQ.

DOS changes this vector to 6630 [$19E6], the start of the DOS output needed interrupt routine. IRQ.

VSEROR] or the input ready [VSERIN] IRQ is generated according to the direction of the data flow. This causes the next byte to be processed until the entire buffer has been sent or is full, and a flag for "transmission done" is set. At this point, SIO exits back to the calling routine. You can see that SIO wastes time waiting for POKEY to send or receive the information on the bus.

AUDF1 [53760; $D200] counts down to zero. Values in the AUDF registers are loaded into STIMER at 53769 [$D209]. IRQ.

AUDF2 [53762, $D202], initialized to 59314 [$E7B2]. IRQ.

AUDF4 [53766, $D206], initialized to 59314 [$E7B2]. This IRQ is only vectored in the "B" version of the OS ROMs.

VDSLST 59280 [$E790] VPRCED 59279 [$E78F] VINTER 59279 [$E78F] VBREAK 59279 [$E78F] VKEYBD NO CHANGE VSERIN 60175 [$EB0F] VSEROR NO CHANGE VSEROC 60111 [$EACF] VTIMR 1-4 59279 [$E78F] VIMIRQ 59142 [$E706] VVBLKI 59310 [$E7AE] VVBLKD 59653 [$E905] --------------------------------------------------------------------------- The locations from 536 to 558 [$218 to $22E] are used for the system software timers. Hardware timers are located in the POKEY chip and use the AUDF registers. These timers count backwards every 1/60 second [stage one VBLANK] or 1/30 second [stage two VBLANK] interval until they reach zero. If the VBLANK process is disabled or intercepted, the timers will not be updated. See De Re Atari for information regarding setting these timers in an assembly routine using the SETVBV register [58460; $E45C]. These locations are user- accessible and can be made to count time for music duration, game I/O, game clock and other functions. Software timers are used for durations greater than one VBLANK interval [1/60 second]. For periods of shorter duration, use the hardware registers.

CRITIC flag [location 66; $42]. This timer may miss [skip] a count when time-critical code [CRITIC equals non-zero] is being executed. It performs a JSR through location 552, 553 [$228, $229] when the value counts down to zero.

CRITIC flag to non-zero as well. The OS uses timer three to OPEN the cassette recorder and to set the length of time to read and write tape headers. Any prior value in the register during this function will be lost.

VVBLKI. If not critical, the deferred interrupt VVBLKD is used. Normally the VBLANK interrupt bits are enabled [BIT 6 at location 54286; $D40E is set to one]. To disable them, clear BIT 6 [set to zero]. The normal seguence for VBLANK interrupt events is: after the OS test, JMP to the user immediate VBLANK interrupt routine through the vector at 546, 547 [above], then through SYSVBV at 58463 [$E45F]. This is directed by the OS through the VBLANK interrupt service routine at 59345 [$E7D1] and then on to the user-deferred VBLANK interrupt routine vectored at 548, 549. it then exits the VBLANK interrupt routine through 58466 [$E462] and an RTI instruction. If you are changing the VBLANK vectors during the interrupt routine, use the SETVBV routine at 58460 [$E45C]. An immediate VBI has about 3800 machine cycles of time to use a deferred VBI has about 20,000 cycles. Since many of these cycles are executed while the electron beam is being drawn, it is suggested that you do not execute graphics routines in deferred VBI's. See the table of VBLANK processes at the end of the map area. if you create your own VBI's, terminate an immediate VBI with a JMP to 58463 [$E45F] and a deferred VBI with a JMP to 58466 [$E462]. To bypass the OS VBI routine at 59345 [$E7D1] entirely, terminate your immediate VBI with a JMP to 58466 [$E462]. Here's an example of using a VBI to create a flashing cursor. It will also blink any text you display in inverse mode. 10 FOR BLINK = 1664 TO 1680: READ B YTE: POKE BLINK, BYTE: NEXT BLINK 20 POKE 548,128: POKE 549,6 30 DATA 8,72,165,20,41,16,74,74,74, 141 40 DATA 243,2,104,40,76,62,233 DOWNLOAD VVBLKD.BAS To restore the normal cursor and display, POKE 548,62 and POKE 549,233.

DOS as a timeout flag.

STIMER is set to 48 [$30]. Whenever SRTIMR is equal to zero and a key is being continuously pressed, the value of that key is continually stored in CH, location 764 [$2FC].

SDMCTL. Note that you must choose only one of the four playfield options appearing at the beginning of the list: Option Decimal Bit No playfield 0 0 Narrow playfield 1 0 Standard playfield 2 0,1 Wide playfield 3 0,1 Enable missle DMA 4 2 Enable player DMA 8 3 Enable player and missile DMA 12 2,3 One line player resolution 16 4 Enable instructions to fetch DMA 32 5 [see below] Note that two-line player resolution is the default and that it is not necessary to add a value to 559 to obtain it. I have included the appropriate bits affected in the table above. The default is 34 [$22]. The playfield is the area of the TV screen you will use for display, text, and graphics. Narrow playfield is 128 color clocks [32 characters wide in GR.0], standard playfield is 160 color clocks [40 characters], and wide playfield is 192 color clocks wide [48 characters]. A color clock is a physical measure of horizontal distance on the TV screen. There are a total of 228 color clocks on a line, but only some of these [usually 176 maximum] will be visible due to screen limitations. A pixel, on the other hand, is a logical unit which varies in size with the GRAPHICS mode. Due to the limitations of most TV sets, you will not be able to see all of the wide playfield unless you scroll into the offscreen portions. BIT 5 must be set to enable ANTIC operation; it enables DMA for fetching the display list instructions.

RAMTOP]. Note that the GTIA modes have no text window. If you don't have the GTIA chip, your Atari will default to GRAPHICS 8, but with GTIA formatting. 1 TRAP 10: GRAPHICS Z 5 SCREEN = PEEK[560] + PEEK[561] * 256 6 TV = SCREEN + 4: TELE = SCREEN + 5 8 DISPLAY = PEEK[TV] + PEEK[TELE] * 256 10 FOR N = 0 TO 255: POKE DISPLAY + N,N: NEXT N 20 DISPLAY = DISPLAY + N 30 IF DISPLAY > 40959 THEN Z = Z + 1 : GOTO 1 40 GOTO 10 50 Z = Z + 1:IF Z > 60 THEN END 60 GOTO 1 Here's another short program which will allow you to examine the DL in any GRAPHICS mode: 10 REM CLEAR SCREEN FIRST 20 PRINT"ENTER GRAPHICS MODE": REM A DD 16 TO THE MODE TO SUPPRESS THE TEXT WINDOW 30 INPUT A: GRAPHICS A 40 DLIST = PEEK[560] + PEEIK[561] * 2 56 50 LOOK = PEEK[DLIST]: PRINT LOOK;" "; 60 IF LOOK 65 THEN DLIST = DLIST + 1: GOTO 50 70 LPRINT PEEK[DLIST + 1];" ";PEEK[D LIST + 2] 80 END The value 65 in the DL is the last instruction encountered. It tells ANTIC to jump to the address in the next two bytes to re-execute the DL, and wait for the next VBLANK. If you don't have a printer, change the LPRINT commands to PRINT and modify the routine to save the data in an array and PRINT it to the screen after [in GR.0]. If you would like to examine the locations of the start of the Display List, screen, and text window, try: 5 REM CLEAR SCREEN FIRST 6 INPUT A: GRAPHICS A 10 DIM DLIST$[10], SAVMSC$[10], TXT$ [10] 15 DLIST$ = "DLIST": SAVMSC$ = "SAVM SC": TXT$ = "TEXT" 20 DLIST = PEEK[560] + PEEK[561] * 2 56 30 SAV = PEEK[88] + PEEK[89] * 256: TXT = PEEK[660] + PEEK[66l] * 256 40 PRINT DLIST$;" "; DLIST,SAVMSC$;" ";SAV 50 PRINT TXT$;" "; TEXT 60 INPUT A: GRAPHICS A: GOTO 20 Since an LMS is simply a map mode [graphics] or character mode [text] instruction with BIT six set, you can make any or all of these instructions into LMS instructions quite easily, pointing each line to a different RAM area if necessary. This is discussed in De Re Atari on implementing horizontal scrolling. DL's can be used to help generate some of the ANTIC screen modes that aren't supported by BASIC, such as 7.5 [ANTIC mode E] or ANTIC mode three, the lowercase with descenders mode [very interesting; ten scan lines in height which allow true descenders on lowercase letters]. If you create your own custom DL, you POKE its address here. Hitting BESET or changing GRAPHICS modes will restore the OS DL address, however. The display list instruction is loaded into a special register called the Display Instruction Register [IR]. which processes the three DL instructions [blank, jump, or display]. It cannot be accessed directly by the programmer in either BASIC or machine language. A DL cannot cross a 1K boundary unless a jump instruction is used. There are only four display list instructions: blank line [uses BAK color], map mode, text mode, and jump. Text [character mode] instructions and map mode [graphics] instructions range from two to 15 [$2 to $F] and are the same as the ANTIC GRAPHICS modes. A DL instruction byte uses the following conventions [functions are enabled when the bit is set to one]: Bit Decimal Function 7 128 Display List Interrupt when set [enabled equals one] 6 64 Load Memory Scan. Next two bytes are the LSB/MSB of the data to load. 5 32 Enable vertical fine scrolling. 4 16 Enable horizontal fine scrolling. 3-0 8-1 Mode 0 0 1 0 Character to Modes 0 1 1 1 . . . . . . . 1 0 0 0 Map to Modes 1 1 1 1 The above bits may be combined [i.e., DLI, scrolling and LMS together] if the user wishes. Special DL instructions [with decimal values]: Blank 1 line = 0 5 lines = 64 2 lines = 16 6 lines = 80 3 lines = 32 7 lines = 96 4 lines = 48 8 lines = 112 Jump instruction [JMP] = zero [three-byte instruction]. Jump and wait for Vertical Blank [JVP] = 65 [three-byte instruction]. Special instructions may be combined only with DL interrupt instructions. A Display List Interrupt is a special form of interrupt that takes place during the screen display when the ANTIC encounters a DL instruction with the interrupt BIT 7 set. See location 512 [$200] for DLI information. Since DL's are too large a topic to cover properly in this manual, I suggest you look in the many magazines [i.e., Creative Computing, July 1981, August 1981; Micro, December 1981; Softside, #30 to 32, and BYTE, December 1981] for a more detailed explanation

VCOUNT register for two-line resolution [see 54283; $D40B]. Both light pen values are modified when the trigger is pressed [pulled low]. The light pen positions are not the same as the normal screen row and column positions. There are 96 vertical positions, numbered from 16 at the top to 111 at the bottom, each one equivalent to a scan line. Horizontal positions are marked in color clocks. There are 228 horizontal positions, numbered from 67 at the left. When the LPENH value reaches 255, it is reset to zero and begins counting again by one to the rightmost edge, which has a value of seven. Obviously, because of the number of positions readable and the small size of each, a certain leeway must be given by the programmer when using light pen readouts on a program. At the time of this writing, Atari had not yet released its light pen onto the market, although other companies have.

CDEVIC is used for the SIO bus ID number The other three CFB bytes are:

DOS, this address is 1792 [$700], the value also stored temporarily in RAMLO at 4, 5. Address 62189 [$F2ED] is the OS disk boot routine entry point [DOBOOT].

DOS menu selection "L" into an auto-boot file simply by renaming it "AUTORUN.SYS". Be careful not to use the same name for any two files on the same disk. When this is combined with the disabling of the BREAK key discussed in location 16 [$10] and the program protection scheme discussed in location 138 [$8A], you have the means to protect your BASIC software fairly effectively from being LISTed or examined, although not from being copied.

LINE = 1 TO 2 40 FOR TEST = 1 TO 25: PLOT 4 + TES T, LOOP + LINE + SPACE: NEXT TEST 45 NEXT LINE 50 SPACE = SPACE + 4 60 NEXT LOOP 70 GOTO 70: REM WITHOUT THIS LINE, SCREEN WILL RETURN TO GR.0 DOWNLOAD GTIA9.BAS In GTIA mode ten, you have all nine color registers available; hue and luminance may be set separately for each [it would otherwise allow 16 colors, but there are only nine registers]. Try this to see: 10 N = 0: GRAPHICS 10 20 FOR Q = 1 TO 2 30 FOR B = 0 TO 8: POKE 704 + B, N * 16 + A 35 IF A > 15 THEN A = 0 40 COLOR B 45 A = A + 1: N = N + 1 50 IF N > 15 THEN N = 0 60 NEXT B 65 TRAP 70: NEXT Q 70 POP: N = N + 1: FOR Z = 1 TO 200 : NEXT Z 75 GOTO 30 DOWNLOAD GTIA10.BAS GTIA mode eleven is similar to mode nine except that it allows 16 different hues, all of the same luminance. In BASIC, use SETCOLOR 4,O,luminance. Try this for a GTIA mode eleven demonstration: 10 GRAPHICS 11 20 FOR LOOP = 0 TO 79: COLOR LOOP: PLOT LOOP,0: DRAWTO LOOP,191: NEXT LOOP 30 GOTO 30 DOWNLOAD GTIA11.BAS You can use these examples with the routine to rotate colors, described in the text preceding location 704. GTIA mode pixels are long and skinny; they have a four to one horizontal length to height ratio. This obviously isn't very good for drawing curves and circles! GTIA modes are cleared on the OPEN command. How can you tell if you have the GTIA chip? Try POKE 623,64. If you have the GTIA, the screen will go all black. If not, you don't have it. Here is a short routine, written by Craig Chamberlain and Sheldon Leemon for COMPUTE!, which allows an Atari to test itself for the presence of a CTIA or GTIA chip. The routine flashes the answer on the screen, hut can easily be modified so a program will "know" which chip is present so it can adapt itself accordingly: 10 POKE 66,1:GRAPHICS 8:POKE 709,0:PO KE 710,0:POKE 66,0:POKE 623,64:P0K E 53248,42:POKE 5326l,3:PUT#6,1 20 POKE 53278,0:FOR K=1 TO 300:NEXT K :GRAPHICS 18:POKE 53248,0:POSITION 8,5:? #6;CHR$[71-PEEK[53252]];"TI A" 30 POKE 708,PEEK[20]:GOTO 30 DOWNLOAD CTIAGTIA.BAS How can you get the GTIA if you don't have one? Ask your local Atari service representative or dealer, or write directly to Atari in Sunnyvale, California. See the GTIA/CTIA introduction at location 53248 [$D000] for more discussion of the chip. See BYTE, May 1982, COMPUTE!, July through September 1982, and De Re Atari for more on the GTIA chip, and the GTIA Demonstration Diskette from the Atari Program Exchange [APX]. --------------------------------------------------------------------------- Locations 624 to 647 [$270 to $287] are used for game controllers: paddle, joystick and lightpen values.

STICK0.BAS See locations 88, 89 [$58, $59] for an example of a USR call using a string instead of a fixed memory location.

BLIM is drawn from the control bytes that precede every cassette record, as explained in location 1021.

RAMTOP [see location 106; $6A]. See location 88 [$58] for a chart of screen RAM use.

TXTROW specifies where the next read or write in the text window will occur

DINDEX [location 87; $57] and is always equal to zero when location 128 [$7B] equals zero. Initialized to zero [which represents GR.0]. You can alter the display list to change the text window into any GRAPHICS mode desired. If you do so, remember to change TINDEX to reflect that alteration.

OLDROW [90; $5A], OLDCOL [91, 92; $5B, $5C], OLDCHR [location 93, $5D] and OLDADR [locations 94, 95; $5E, $5F]. They hold the split-screen cursor data.

DMASK contains zeroes tor all bits which do not correspond to the specific pixel to be operated upon, and ones for bits which do correspond, according to the GRAPHICS mode in use, as follows: 11111111 Modes 0, 1 and 2: one pixel per screen display byte. 11110000 Modes 9, 10 and 11: two pixels per byte. 00001111 11000000 Modes 3, 5 and 7: four pixels per byte. 00110000 00001100 00000011 10000000 Modes 4, 6 and 8: eight pixels per byte. 01000000 etc. to: 00000001 A pixel [short for picture cell or picture element] is a logical unit of video size which depends on the GRAPHICS mode in use for its dimensions. The smallest pixel is in GR.8 where it is only .5 color clock wide and one scan line high. In GR.0 it is also only .5 color clock wide, but it is eight scan lines high. Here is a chart of the pixel sizes for each mode: Text Modes Graphics modes GR. mode 0 1 2 3 4 5 6 7 8 Scan lines per pixel 8 8 16 8 4 4 2 2 1 Bits per pixel 1 1 1 2 1 2 1 2 1 Color clocks per pixel .5 1 1 4 2 2 1 1 .5 Characters per line 40 20 20 -- -- -- -- -- -- Pixels per width -- -- -- 40 80 80 160 160 320 The number of pixels per screen width is based on the normal playfield screen. See location 559 [$22F] for information on playfield size.

TABMAP also works for the lines in the text display window in split-screen formats. TABMAP is reset to the default values on pressing RESET or changing GRAPHICS modes. See location 201 [$C9] about changing the TAB settings used when a PRINT statement encounters a comma.

INVFLG with 128 [$80] to get inverse characters [BIT 7 equals one]. This register is normally set by toggling the Atari logo key; however, it can be user-altered. The display handler XOR's the ATASCII codes with the value in INVFLG at all times. See location 702 [$2BE] below. INVFLG works to change the input, not the output. For example, if you have A$ = "HELLO", POKE 694, 128 will not change A$ when you PRINT it to the screen. However, if you POKE 694, 128 before an INPUT A$, the string will be entered as inverse.

DRAW command. If the current operation is a DRAW, then this register reads zero. If it is non-zero, the operation is a FILL.

ROWCRS [location 84; $54].

COLCRS [locations 85, 86; $55, $56].

SCRFLG ranges from zero to two. Scrolling the text window is the equivalent to scrolling an entire GR.0 screen. An additional 20-line equivalent of bytes [800] is scrolled upwards in the memory below the text window address. This can play havoc with any data such as P/M graphics you have stored above RAMTOP

DRAW command only; used to save and restore the value in ATACHR [location 763; $2FB] during the FILL process.

SHFLOK will set characters to all caps during your program if 64 is POKEd here. Returns the value 128 [$80; control-lock] when the CTRL key is pressed. Forced control-lock will cause all keys to output their control-code functions or graphics figures. Other values POKEd here may cause the system to crash. You can use this location with 694 [$2B6] above to convert all keyboard entries to uppercase, normal display by: 10 OPEN #2,4,0,"K:" 20 GET #2,A 30 GOSUB 1000 40 PRINT CHR$[A];: GOTO 20 . . . 1000 IF A = 155 THEN 1030: REM RETURN KEY 1010 IF A > = 128 THEN A = A - 128: R EM RESTORE TO NORMAL DISPLAY 1020 IF PEEK [702] = 0 AND A > 96 THEN A = A - 32: REM LOWERCASE TO UP PER 1030 POKE 702,64: POKE 694,0 1040 RETURN DOWNLOAD SHFLOK.BAS

DOS menu. --------------------------------------------------------------------------- Locations 704 to 712 [$2C0 to $2C8] are the color registers for players, missiles, and playfields. These are the RAM shadow registers for locations 53266 to 53274 [$D012 to $D01A]. For the latter, you can use the SETCOLOR command from BASIC. For all registers you can POKE the desired color into the location by using this formula: COLOR = HUE * 16 + LUMINANCE It is possible to get more colors in GR.8 than the one [and a half] that Atari says is possible by using a technique called artifacting. There is a small example of artifacting shown at location 710 [$2C6]. See De Re Atari, Your Atari 400/800, Creative Computing, June 1981, and COMPUTE!, May 1982. Here are the 16 colors the Atari produces, along with their POKE values for the color registers. The POKE values assume a luminance of zero. Add the luminance value to the numbers to brighten the color. The color registers ignore BIT 0; that's why there are no "odd" values for luminance, just even values. Color Value Color Value Black 0, 0 Medium blue 8, 128 Rust 1, 16 Dark blue 9, 144 Red-orange 2, 32 Blue-grey 10, 160 Dark orange 3, 48 Olive green 11, 176 Red 4, 64 Medium green 12, 192 Dk lavender 5, 80 Dark green 13, 208 Cobalt blue 6, 96 Orange-green 14, 224 Ultramarine 7, 112 Orange 15, 240 The bit use of the PCOLR and COLOR registers is as follows: Bit 7 6 5 4 3 2 1 0 --color-- luminance unused Grey 0 0 0 0 0 0 0 Darkest Rust 0 0 0 1 0 0 1 etc. to: etc. to: Orange 1 1 1 1 1 1 1 Lightest When you enable the color overlap at location 623 [$26F], ANTIC performs a logical OR on the overlap areas. For example: 01000010 Red, luminance two OR 10011010 Darkblue,luminance ten -------- Result = 10011010 Dark green, luminance ten Here's a short machine language routine which will rotate the colors in registers 705 to 712: 10 DIM ROT$[30] 20 FOR LOOP = 1 TO 27: READ BYTE: R OT$[LOOP,LOOP] = CHR$[BYTE]: NEXT LOOP . . PUT YOUR GRAPHICS ROUTINE HERE . 100 CHANGE = USR[ADR[ROT$]] 105 FOR LOOP = 1 TO 200: NEXT LOOP: GOTO 100 110 DATA 104,162,0,172,193,2,189,194 ,2,157 120 DATA 193,2,232,224,8,144,245,140 ,200,2 130 DATA 96,65,65,65,65,65,65 If you wish to rotate the colors in registers 704 to 711 instead, change lines 110 and 120 to read as follows: 110 DATA 104,162,0,172,192,2,189,193 ,2,157 120 DATA 192,2,232,224,8,144,245,140 ,199,2 DOWNLOAD BOTSCR.BAS If you wish to include all of the registers 704 to 712 in the routine, make the changes as above and change the eight in line 120 to nine and restore the 199 to 200 in line 120. This routine works well with the GTIA demos at location 623 [$26F]. For further detail, refer to your Atari BASIC Reference Manual, pp. 45 -56, and the GTIA Demo Disk from APX.

COLOR3]. Shadow for 53269 [$D015].

COLOR1 is also used to store the luminance value of the color used in GR.0 and GR.8. Shadow for 53271 [$D017].

COLOR1 for the luminance value. Despite the official limitations of color selection in GR.8, it is possible to generate additional colors by "artifacting", turning on specific pixels [.5 color clock each] on the screen. Taking advantage of the physical structure of the TV set itself, we selectively turn on vertical lines of pixels which all show the same color. For example: 10 A = 40: B = 30: C = 70: D = 5: F = 20 GRAPHICS 8: POKE 87,7: P0K E 710,0: POKE 709,15: COLOR 1 30 PLOT A,D: DRAWTO A,C: COLOR 2: P LOT F,D: DRAWTO F,C: 40 PLOT A + 1,D: DRAWTO A + 1,C 50 COLOR 3: PLOT B,D: DRAWTO B,C 60 GOTO 60 DOWNLOAD COLOR2.BAS A little experimentation with this will show you that the colors obtained depend on which pixels are turned on and how close together the pixel columns are. There are four "colors" you can obtain, as shown before. Pixels marked one are on; marked zero means they are off. Each pair of pixels is one color clock. Three color clocks are shown together for clarity: 00:01:00 = color A 00:11:00 = color B 00:10:00 = color C 00:01:10 = color D See BYTE, May 1982, De Re Atari, and Your Atari 400/800.

DOS users. For DOS users they are used as below:

DOS for the run address read from the disk sector one or from a binary file. Upon completion of any binary load, control will normally be passed back to the DOS menu. However, DOS can be forced to pass control to any specific address by storing that address here. If RUNAD is set to 40960 [$A000], then the left cartridge [BASIC if inserted] will be called when the program is booted. With DOS 1.0, if you POKE the address of your binary load file here, the file will be automatically run upon using the DOS Binary Load [selection L]. Using DOS 1.0's append [/A] option when saving a binary file to disk, you can cause the load address POKEd here to be saved with the data. In DOS 2.0, you may specify the initialization and the run address with the program name when you save it to disk [i.e., GAME.OBJ,2000,4FFF,4F00,4000]. DOS 2.0 uses the /A option to merge files. In order to prevent your binary files from running automatically upon loading in DOS 2.0, use the /N appendage to the file name when loading the file. For users of CompuServe, there is an excellent little BASIC program [with machine language subroutines] to create autoboot files, chain machine language files with BASIC and to add an 850 autoboot file in the Popular Electronics Magazine [PEM] access area. It is available free for downloading.

RUNAD above or INITAD. The code pointed to by INITAD will be run as soon as that location is loaded. The code pointed to by RUNAD will be executed only after the entire load process has been completed. To return control to DOS after the execution of your program, end your code with an RTS instruction.

RAMTOP, location 106 [$6A], passed here from TRAMSZ, location 6. Space saved by moving RAMSIZ or RAMTOP has the advantage of being above the display area. Initialized to 160 for a 48K Atari.

TRAMSZ, location 6 after powerup. This address is the highest free location in RAM for programs and data. The value is updated on powerup, when RESET is pressed, when you change GRAPHICS mode, or when a channel [IOCB] is OPENed to the display. The display list starts at the next byte above MEMTOP. The screen handler will only OPEN the S: device if no RAM is needed below this value [i.e. there is enough free RAM below here to accommodate the requested GRAPHICS mode change]. Memory above this address is used for the display list and the screen display RAM. Also, if a screen mode change would extend the screen mode memory below APPMHI [locations 14, 15: $E, $F], then the screen is set back for GR.0, MEMTOP is updated, and an error is returned to the user. Otherwise the mode change will take place and MEMTOP will be updated. Space saved by moving MEMTOP is below the display list. Be careful not to overwrite it if you change GRAPHICS modes in mid-program. When using memory below MEMTOP for storage, make sure to set APPMHI above your data to avoid having the screen data descend into it and destroy it.

DOS or any other low-memory application program. It is used by the OS; the BASIC pointer to the bottom of free memory is at locations 128, 129 [$80, $81]. The value in MEMLO is never altered by the OS after powerup. This is the address of the first free location in RAM available for program use. Set after all FMS buffers have been allocated [see locations 1801 and 1802; $709 and $70A]. The address of the last sector buffer is incremented by 128 [the buffer size in bytes] and the value placed in MEMLO. The value updates on powerup or when RESET is pressed. This value is passed back to locations 128, 129 [$80, $81] on the execution of the BASIC NEW command, but not RUN, LOAD or RESET. If you are reserving space for your own device driver[s] or reserving buffer space, you load your routine into the address specified by MEMLO, add the size of your routine to the MEMLO value, and POKE the new value plus one back into MEMLO. When you don't have DOS or any other application program using low-memory resident, MEMLO points to 1792 [$700. With DOS 2.0 present, MEMLO points to 7420 [$1CFC]. If you change the buffer defaults mentioned earlier, you will raise or lower this latter value by 128 [$80] bytes for every buffer added or deleted, respectively. When you boot up the 850 Interface with or without disk, you add another 1728 [$6C0] bytes to the value in MEMLO. You can alter MEMLO to protect an area of memory below your program. This is an alternative to protecting an area above RAMTOP [location 106; $6A] and avoids the problem of the CLEAR SCREEN routine destroying data. However, unless you have created a MEM.SAV file, the data will be wiped out when you call DOS. To alter MEMLO, you start by POKEing WARMST [location 8] with zero, then doing a JMP to the BASIC cartridge entry point at 40960[$A000] after defining your area to protect. For example, try this: 10 DIM MEM$[24]:PROTECT=700:REM NUMBE R OF BYTES TO CHANGE 15 HIBYTE=INT[PROTECT/256]:LOBYTE=PRO TECT-256*HIBYTE 20 FOR N=1 TO 24:READ PRG:MEM$[N]=CHR $[PRG]:NEXT N 30 MEM$[6,6]=CHR$[LOBYTE]:MEM$[14,14] =CHR$[HIBYTE] 40 RESERVE=USR[ADR[MEM$]] 50 DATA 24,173,231,2,105,0,141,231,2, 173,232,2,105 60 DATA 0,141,232,2,169,0,133,8,76,0, 160 DOWNLOAD MEMLO.BAS You will find the address of your reserved memory by: PRINT PEEK[743] + PEEK[744] * 256 before you run the program. This program will wipe itself out when run. Altering MEMLO is the method used by both DOS and the RS-232 port driver in the 850 Interface. See COMPUTE!, July 1981.

STATUS command returns the number of characters in the input buffer to locations 747 and 748, and the number of characters in the output buffer to location 749.

CRSINH change with a cursor movement [i.e., up, down] sequence. This register is set to zero [cursor restored] on powerup, RESET, BREAK, or an OPEN command to either the display handler [S:] or screen editor [E:]. See location 755 for another means to turn off the cursor.

KEYDEL is greater than zero, it is ignored as "bounce." See COMPUTE!, December 1981, for a routine to change the keyboard delay to suit your own typing needs.

CH1, then the code is accepted only if a suitable key debounce delay has taken place since the prior value was accepted.

CHACT is initialized to two. Here's an example of blinking text using this register: 10 CHACT=755:REM USE INVERSE FOR WORD S BELOW 15 PRINT "[THIS IS A TEST OF BLINKING ] [TEXT]" 20 POKE CHACT,INT[RND[0]*4] 30 FOR N=1 TO 100:NEXT N:GOTO 15 See COMPUTE!, December 1981. Using a machine language routine and page six space, try: 10 PAGE=1536:EXIT=1568 20 FOR N=PAGE TO EXIT:READ BYTE:POKE N,BYTE:NEXT N 30 PGM=USR[PAGE] 40 PRINT "[THIS] IS A [TEST] OF [BLINKING] TEXT":REM MAKE SOME WORDS INVERSE 50 GOTO 50 60 DATA 104,169,17,141,40,2,169,6,141 ,41 70 DATA 2,169,30,141,26,2,98,173,243, 2 80 DATA 41,1,73,1,141,243,2,169,30,14 1,26,2,96 DOWNLOAD CHACT.BAS The blink frequency is set .5 second; to change it, change the 30 in line 80 to any number from one [1/30 second] to 255 [eight .5 seconds]. For another way to make the cursor visible or invisible, see locations 752 above.

CHBAS with 226 [$E2] to get the lowercase and the graphics characters in GR.1 and GR.2. In GR.0 you get the entire set displayed to the screen, but in GR.1 and GR.2, you must POKE 756 for the appropriate half-set to be displayed. How do you create an altered character set? First you must reserve an area in memory for your set [512 or 1024 bytes; look at location 106; $6A to see how]. Then either you move the ROM set [or half set, if that's all you intend to change] into that area and alter the selected characters, or you fill up the space with bytes which make up your own set. Then you POKE 756 with the MSB of the location of your set so the computer knows where to find it. What does an altered character set look like? Each character is a block one byte wide by eight bytes high. You set the bits for the points on the screen you wish to be "on" when displayed. Here are two examples: one byte wide: 00100000 = 32 # 00010000 = 16 # 00010000 = 16 # 00010000 = 16 # 00011110 = 30 #### 00000010 = 2 # 00001100 = 12 ## 00010000 = 16 # Hebrew letter Lamed one byte wide: 10000001 = 129 # # 10011001 = 153 # ## # 10111101 = 189 # #### # 11111111 = 255 ######## 11111111 = 255 ######## 10111101 = 189 # #### # 10011001 = 153 # ## # 10000001 = 129 # # Tie-fighter You can turn these characters into DATA statements to be POKEd into your reserved area by using the values for the bytes as in the above examples. To change the ROM set once it is moved, you look at the internal code [see the BASIC Reference Manual, p. 55] and find the value of the letter you want to replace--such as the letter A--code 33. Multiply this by eight bytes for each code number from the start of the set [33 * eight equals 264]. You then replace the eight bytes used by the letter A, using a FOR-NEXT loop with the values for your own character. For example, add these lines to the machine language found a few pages further on: 1000 FOR LOOP=1 TO 4:READ CHAR:SET=CH ACT+CHAR*8 1010 FOR TIME=0 TO 7:READ BYTE:POKE S ET+TIME,BYTE: NEXT TIME 1020 NEXT LOOP 1030 DATA 33,0,120,124,22,22,124,120, 0 1040 DATA 34,0,126,82,82,82,108,0,0 1050 DATA 35,56,84,254,238,254,68,56, 0 1060 DATA 36,100,84,76,0,48,72,72,48 2000 END RUN it and type the letters A to D. Why 224 and 226? Translated to hex, these values are $E0 and $E2, respectively. These are the high bytes [MSB] for the location of the character set stored in ROM: $E000 [57344] is the address for the start of the set [which begins with punctuation, numbers and uppercase letters], and $E200 [57856], for the second half of the ROM set, lowercase and graphic control characters [both start on page boundaries]. The ROM set uses the internal order given on page 55 of your BASIC Reference Manual, not the ATASCII order. See also location 57344 [$E000]. You will notice that using the PRINT#6 command will show you that your characters have more than one color available to them in GR.1 and GR.2. Try PRINTing lowercase or inverse characters when you are using the uppercase set. This effect can be very useful in creating colorful text pages. Uppercase letters, numbers, and special characters use color register zero [location 708; $2C4 - orange] for normal display, and color register two [710; $2C6 - blue] for inverse display. Lowercase letters use register one [709; $2C5 - aqua] for normal display and register three [711; $2C7 - pink] for inverse. See COMPUTE!, December 1981, page 98, for a discussion of using the CTRL keys with letter keys to get different color effects. One problem with POKEing 756 with 226 is that there is no blank space character in the second set: you get a screen full of hearts. You have two choices: you can change the color of register zero to the same as the background and lose those characters which use register zero--the control characters--but get your blanks [and you still have registers one, two and three left]. Or you can redefine your own set with a blank character in it. The latter is obviously more work. See "Ask The Readers," COMPUTE!, July 1982. It is seldom mentioned in the manuals, but you cannot set 756 to 225 [$El] or any other odd number. Doing so will only give you screen garbage. The page number 756 points to must be evenly divisible by two. When you create your own character set and store it in memory, you need to reserve at least 1K for a full character set [1024 bytes --$400 or four pages], and you must begin on a page boundary. In hex these are the numbers ending with $XX00 such as $C000 or $600 because you store the pointer to your set here in 756; it can only hold the MSB of the address and assumes that the LSB is always zero--or rather a page boundary. You can reserve memory by: POKE 106,PEEK[106]-4 [or any multiple of four] And do a GRAPHICS command immediately after to have your new memory value accepted by the computer. If you are using only one half of the entire set, for GR.1 or GR.2, you need only reserve 512 bytes, and it may begin on a .5K boundary [like $E200; these are hexadecimal memory locations that end in $X200]. If you plan to switch to different character sets, you will need to reserve the full 1K or more, according to the number of different character sets you need to display. RAM for half-K sets can be reserved by: POKE 106,PEEK[106]-2 [or a multiple of two] The location for your set will then begin at PEEK[106]*256. Because BASIC cannot always handle setting up a display list for GR.7 and GR.8 when you modify location 106 by less than 4K [16 pages], you may find you must use PEEK[106]-16. See location 88,89 [$58,$59] and 54279 [$D407] for information regarding screen use and reserving memory. Make sure you don't have your character set overlap with your player/missile graphics. Be very careful when using altered character sets in high memory. Changing GRAPHICS modes, a CLEAR command, or scrolling the text window all clear memory past the screen display. When you scroll the text window, you don't simply scroll the four lines; you actually scroll a full 24 [20 additional lines * 40 bytes equals 800 bytes scrolled past memory]! This messes up the memory past the window display address, so position your character sets below all possible interference [or don't scroll or clear the screen]. You can create and store as many character sets as your memory will allow. You switch back and forth between them and the ROM set by simply POKEing the MSB of the address into 756. Of course, you can display only one set at a time unless you use an altered display list and DLI to call up other sets. There are no restrictions outside of memory requirements on using altered character sets with P/M graphics as long as the areas reserved for them do not overlap. A GRAPHICS command such as GR.0, RESET or a DOS call restores the character set pointer to the ROM location, so you must always POKE it again with the correct location of your new set after any such command. A useful place to store these sets is one page after the end of RAM, assuming you've gone back to location 106 [$6A] and subtracted the correct number of pages from the value it holds [by POKE 106,PEEK[106] minus the number of pages to be reserved; see above]. Then you can reset the character set location by simply using POKE 756,PEEK[106]+1 [the plus one simply makes sure you start at the first byte of your set]. A full character set requires 1024 bytes [1K: four pages] be reserved for it. Why? Because there are 128 characters, each represented by eight bytes, so 128 * eight equals 1024. If you are using a graphics mode that uses only half the character set, you need only reserve 512 bytes [64 * eight equals 512]. Remember to begin either one on a page boundary [1K boundary for full sets or .5K for half sets]. By switching back and forth between two character sets, you could create the illusion of animation. Many magazines have published good utilities to aid in the design of altered character sets, such as the January 1982 Creative Computing, and SuperFont in COMPUTE!, January 1982. I suggest that you examine The Next Step from Online, Instedit from APX, or FontEdit from the Code Works for very useful set generators. One potentially useful way to alter just a few of the characters is to duplicate the block of memory which holds the ROM set by moving it byte by byte into RAM. A BASIC FOR-NEXT loop can accomplish this, although it's very slow. For example: 5 CH=57344 10 START=PEEK[106]-4:PLACE=START*256: POKE 106,PEEK[106]-5:GRAPHICS 0: RE M RESERVE EXTRA IN CASE OF SCREEN CLEAR 20 FOR LOOP=0 TO 1023:POKE PLACE+LOOP ,PEEK[CH+LOOP]:NEXT LOOP:REM MOVE THE ROM SET 30 POKE 756,PLACE/256:REM TELL ANTIC WHERE CHSET IS Here's a machine language routine to move the set: 10 DIM BYTE$[80] 15 REM MEM-1 TO PROTECT SET FROM CLEA R SCREEN DESTRUCTION [SEE LOC.88] 20 MEM=PEEK[106]-4:POKE 106,MEM-1: CHA CT=MEM*256:GRAPHICS 0 30 FOR LOOP=1 TO 32:READ PGM:BYTE$[LO OP,LOOP]=CHR$[PGM]:NEXT LOOP 40 DATA 104,104,133,213,104,133,212 50 DATA 104,133,215,104,133,214,162 60 DATA 4,160,0,177,212,145,214 70 DATA 200,208,249,230,213,230,215 80 DATA 202,208,240,96 90 Z=USR[ADR[BYTE$],224*256,CHACT] . . ADD YOUR OWN ALTERATION PROGRAM OR THE EARLIER EXAMPLE HERE . . 1500 POKE MEM-1,0:POKE 756,MEM If you have Microsoft BASIC or BASIC A+, you can do this very easily with the MOVE command! Remember, when altering the ROM set, that the characters aren't in ATASCII order; rather they are in their own internal order. Your own set will have to follow this order if you wish to have the characters correlate to the keyboard and the ATASCII values. See page 55 of your BASIC Reference Manual for a listing of the internal order. Creative Computing, January 1982, had a good article on character sets, as well as a useful method of transferring the ROM set to RAM using string manipulation. See also "Using Text Plot for Animated Games" in COMPUTE!, April 1982, for an example of using character sets for animated graphics.

ATACHR below]. This register is difficult to use with PEEK statements since it returns the most recent character; most often the cursor value [128, $80 for a visible, zero for an invisible cursor].

ATACHR is used in converting the ATASCII code to the internal character code passed to or from CIO. It also returns the value of the graphics point. The FILL and DRAW commands use this location for the color of the line drawn, ATACHR being temporarily loaded with the value in FILDAT, location 765; $2FD. To force a color change in the line, POKE the desired color number here [color * sixteen + luminance]. To see this register in use as character storage, try: 10 OPEN#2,4,0,"K:" 20 GET#2,A 30 PRINT PEEK[763];" "; CHR$[A] 40 GOTO 20 Make sure the PEEK statement comes before the PRINT CHR$ statement, or you will not get the proper value returned. When the RETURN key is the last key pressed, ATACHR will show a value of 155.

CH with 255 [$FF; no key pressed] to clear it. The keyboard handler gets all of its key data from CH. It stores the value 255 here to indicate the key code has been accepted, then passes the code to CH1, location 754 [$2F2]. If the value in CH is the same as in CH1, a key code will be accepted only if the proper key debounce delay time has transpired. If the code is the CTRL-1 combination [the CTRL and the "1" keys pressed simultaneously], then the start/stop flag at 767 [$2FF] is complemented, but the value is not stored in CH. The auto repeat logic will also store store key information here as a result of the continuous pressing of a key. This is neither the ATASCII nor the internal code value; it is the "raw" keyboard matrix code for the key pressed. The table for translation of this code to ATASCII is on page 50 of the OS User's Manual. In a two-key operation, BIT 7 is set if the CTRL key is pressed, BIT 6 if the SHIFT key is pressed. The rest of the bytes are the code [ignored if both BITs 7 and 6 are set]. Only the code for the last key pressed is stored here [it is a global variable for keyboard]. When a read request is issued to the keyboard, CH is set to 255 by the handler routine. After a keycode has been read from this register, it is reset to 255. BREAK doesn't show here, and CTRL and SHIFT will not show here on their own. However, the inverse toggle [Atari logo key], CAPS/LOWR, TAB and the ESC keys will show by themselves. You can examine this register with: 10 LOOK=PEEK[764] 20 PRINT "KEY PRESSED = ";LOOK 30 POKE 764,255 40 FOR LOOP=1 TO 250:NEXT LOOP 50 GOTO 10 See COMPUTE!'s First Book of Atari for an example of using this register as a replacement for joystick input.

DRAW or graphics routine, a LISTing or a PRINTing. When the value is zero, the screen output is not stopped. When the value is 255 [$FF; the one's complement], the output to the screen is stopped, and the machine waits for the value to become zero again before continuing with the scrolling display. Normally SSFLAG is toggled by the user during these operations by pressing the CTRL-1 keys combination to both start and stop the scroll. Set to zero by RESET and powerup. ---------------------------------------------------------------------------

PAGE THREE

Locations 768 to 831 [$300 to $33F] are used for the device handler and vectors to the handler routines [devices S:, P:, E:, D:, C:, R: and K:]. A device handler is a routine used by the OS to control the transfer of data in that particular device for the task allotted [such as read, write, save, etc.]. The resident D: handler does not conform entirely with the other handler--SIO calling routines. Instead, you use the DCB to communicate directly with the disk handler. The device handler for R: is loaded in from the 850 interface module. See De Re Atari, the 850 Interface Manual, and the OS Listings pages 64 - 65. Locations 768 to 779 [$300 to $30B] are the resident Device Control Block [DCB] addresses, used for I/O operations that require the serial bus; also used as the disk DCB. DUP.SYS uses this block to interface the FMS with the disk handler. The Atari disk drive uses a serial access at 19,200 baud [about 20 times slower than the Apple!]. It has its own microprocessor, a 6507, plus 128 bytes of RAM, a 2316 2K masked ROM chip [like a 2716], a 2332 RAM-I/O timer chip with another 128 bytes of RAM [like the PIA chip] and a WD 1771 FD controller chip. See the "Outpost Atari" column, Creative Computing, May 1982, for an example of using the disk DCB. All of the parameters passed to SIO are contained in the DCB. SIO uses the DCB information and returns the status in the DCB for subsequent use by the device handler.

STATUS request [83; $53] and FORMAT entire disk [33; $21]. There is no command to FORMAT a portion of the disk; this is done by the INS 1771-1 formatter/controller chip in the drive itself and isn't user-accessible. There is a new disk drive ROM to replace the current "C" version. It is the "E" ROM. Not only is it faster than the older ROMs, but it also allows for selective formatting of disk sectors. Atari has not announced yet whether this new 810 ROM will be made available. For more information, see the OS User's Manual. Locations 780 to 793 [$30C to $319] are for miscellaneous use. Locations 794 to 831 [$31A to $33F] are handler address tables. To use these DCBs, the user must provide the required parameters to this block and then do a machine language JSR to $E453 [58451] for disk I/O or $E459 [58457; the SIO entry point] for other devices.

VCOUNT value [54283; $D40B], and the second byte contains the current realtime clock value from location 20 [$14]. The difference between the timer values is used in a lookup table to compute the interval for the new values for the baud rate passed on to location 750, 751 [$2EE, $2EF].

VCOUNT calculation during baud timer routines. See location 54283 [$D40B].

HATABS table is copied from ROM. Devices to be booted, such as the disk drive, add their handler information to the end of the table. Each entry has the character device name [C,D,E,K,P,S,R] in ATASCII code and the handler address [LSB/MSB]. Unused bytes are all set to zero. FMS searches HATABS from the top for a device "D:" entry, and when it doesn't find it, it then sets the device vector at the end of the table to point to the FMS vector at 1995 [$7CB]. CIO searches for a handler character from the bottom up. This allows new handlers to take precedence over the old. Pressing RESET clears HATABS of all but the resident handler entries! 794 31A Printer device ID [P:], initialized to 58416 [$E430]. 797 31D Cassette device ID [C:], initialized to 58432 [$E440]. 800 320 Display editor ID [E:], initialized to 58368 [$E400]. 803 323 Screen handler ID [S:], initialized to 58384 [$E410]. 806 326 Keyboard handler ID [K:], initialized to 58400 [$E420]. HATABS unused entry points: 809 [$329], 812 [$32C], 815 [$32F], 818 [$332], 821 [$335], 824 [$338], 827 [$33B], and 830 [$33E]. These are numbered sequentially from one to eight. There are only two bytes in the last entry [unused], both of which are set to zero. When DOS is present, it adds an entry to the table with the ATASCII code for the letter "D" and a vector to address 1995 [$7CB]. The format for the HATABS table is: Device name Handler vector table address More entries Zero fill to the end of the table The device handler address table entry above for the specific handler points to the first byte [low byte/high byte] of the vector table which starts at 58368 [$E400]. Each handler is designed with the following format: OPEN vector CLOSE vector GET BYTE vector PUT BYTE vector GET STATUS vector SPECIAL vector Jump to initialization code [JMP LSB/MSB] CIO uses the ZIOCB [see location 32; $20] to pass parameters to the originating IOCB, the A, Y and X registers and CIO. It is possible to add your own device driver[s] to OS by following these rules: 1] Load your routine, with necessary buffers at the address pointed to by MEMLO: location 743 [$2E7]. 2] Add the size of your routine to the MEMLO value and POKE the result back into MEMLO. 3] Store the name and address of your driver in the handler address table; HATABS. 4] Change the vectors so that the OS will re-execute the above steps if RESET has been pressed. This is usually done by adjusting locations 12 [$C: DOSINIT] and 10 [$A; DOSVEC]. See the "Insight: Atari" columns in COMPUTE!, January and April 1982, for details. The APX program "T: A Text Display Device" is a good example of a device handler application. See De Re Atari for more information on the DCB and HATABS, including the use of a null handler. --------------------------------------------------------------------------- Locations 832 to 959 [$340 to $3BF] are reserved for the eight IOCB's [input/output control blocks]. IOCB's are channels for the transfer of information [data bytes] into and out of the Atari, or between devices. You use them to tell the computer what operation to perform, how much data to move and, if necessary, where the data to be moved is located. Each block has 16 bytes reserved for it. What is an IOCB? Every time you PRINT something on the screen or the printer, every time you LOAD or SAVE a file, every time you OPEN a channel, you are using an IOCB. In some cases, operations have automatic OPEN and CLOSE functions built in--like LPRINT. In others, you must tell the Atari to do each step as you need it. Some IOCB's are dedicated to specific use, such as zero for the screen display. Others can be used for any I/O function you wish. The information you place after the OPEN command tells CIO how you want the data transferred to or from the device. It is SIO and the device handlers that do the actual transfer of data. You can easily POKE the necessary values into the memory locations and use a machine language subroutine through a USR function to call the CIO directly [you must still use an OPEN and CLOSE statement for the channel, however]. This is useful because BASIC only supports either record or single byte data transfer, while the CIO will handle complete buffer I/O. See the CIO entry address, location 58454 [$E456], for more details. These blocks are used the same way as the page zero IOCB [locations 32 to 47; $20 to $2F]. The OS takes the information here, moves it to the ZIOCB for use by the ROM CIO, then returns the updated information back to the user area when the operation is done. Note that when BASIC encounters a DOS command, it CLOSEs all channels except zero. Refer to the Atari Hardware Manual and the 850 Interface Manual for more detailed use of these locations.

FORCREAD.BAS See COMPUTE!, August 1981, for a sample of this powerful technique. See Santa Cruz's Tricky Tutorial #1 [display lists] for another application. The last four bytes [844 to 847; $34C to $34F in this case] are spare [auxiliary] bytes in all IOCB's. When you are in a GRAPHICS mode other than zero, channel zero is OPENed for the text window area. If the window is absent and you OPEN channel zero, the whole screen returns to mode zero. A BASIC NEW or RUN command closes all channels except zero. OPENing a channel to S: or E: always clears the display screen. See COMPUTE!, October 1981,for an example of using an IOCB with the cassette program recorder, and September 1981 for another use with the Atari 825 printer.

STATUS request in BASIC. See the OS User's Manual, pp. 165-166, fora list of status byte values. ICBAL/H 4,5 2 Two-byte [LSB,MSB] buffer address for data transfer or the address of the file name for OPEN, STATUS, etc. ICPTL/H 6,7 2 Address of the device's put- one-byte routine minus one. Set by the OS at OPEN command, but not actually used by the OS [it is used by BASIC, however]. Points to CIO's "IOCB NOT OPEN" message at powerup. ICBLL/H 8,9 2 Buffer length set to the maximum number of bytes to transfer in PUT and GET operations. Decremented by one for each byte transferred; updated after each READ or WRITE operation. Records the number of bytes actually transferred in and out of the buffer after each operation. ICAX1 10 1 Auxiliary byte number one, referred to as AUX1. Used in the OPEN statement to specify the type of file access: four for READ, eight for WRITE, twelve for both [UPDATE]. Not all devices can use both kinds of operations. This byte can be used in user-written drivers for other purposes and can be altered in certain cases once the IOCB has been OPENed [see the program example above]. For the S: device, if AUX1 equals 32, it means inhibit the screen clear function when changing GRAPHICS modes. Bit use is as follows for most applications: Bit 7 6 5 4 3 2 1 0 Use ....unused... W R D A W equals write, R equals read, D equals directory, A equals append. ICAX2 11 1 Auxiliary byte two, referred to as AUX2. Special use by each device driver; some serial port functions may use this byte. Auxiliary bytes two to five have no fixed use; they are used to contain device-dependent and/or user-established data. ICAX3/4 12,13 2 Auxiliary bytes three and four; used to maintain a record of the disk sector number for the BASIC NOTE and POINT commands. ICAX5 14 1 Auxiliary byte five. Used by NOTE and POINT to maintain a record of the byte within a sector. It stores the relative displacement in sector from zero to 124 [$7C]. Bytes 125 and 126 of a sector are used for sector-link values, and byte 127 [$7F] is used as a count of the number of data bytes in actual use in that sector. ICAX6 15 1 Spare auxiliary byte. Offset is the number you would add to the start of the IOCB in order to POKE a value into the right field, such as POKE 832 + OFFSET, 12. The following is a list of the values associated with OPEN parameter number 1. Most of these values are listed in Your Atari 400/800. These are the values found in ICAX1, not the ICCOM values. Device Task # Description ---------------------------------------------------------------------- Cassette 4 Read recorder 8 Write [can do either, not both] Disk 4 Read file 6 Read disk directory 8 Write new file. Any file OPENed in this mode will be deleted, and the first byte written will be at the start of the file. 9 Write--append. In this mode the file is left intact, and bytes written are put at the end of the file. 12 Read and write--update. Bytes read or written will start at the first byte in the file. D: if BIT 0 equals one and BIT 3 equals one in AUX1,then operation will be appended output. Screen 8 Screen output editor 12 Keyboard input and screen output [E:] 13 Screen input and output E: BIT 0 equals one is a forced read [GET command]. Keyboard 4 Read Printer 8 Write RS-232 5 Concurrent read serial 8 Block write port 9 Concurrent write 13 Concurrent read and write Clear Text Read Screen Window Oper- after GR. also ation Screen 8 yes no no display 12 yes no yes [S:] 24 yes yes no 28 yes yes yes 40 no no no 44 no no yes 56 no yes no 60 no yes yes Note that with S:, the screen is always cleared in GR.0 and there is no separate text window in GR.0 unless specifically user- designed. Without the screen clear, the previous material will remain on screen between GRAPHICS mode changes, but will not be legible in other modes. The values with S: are placed in the first auxiliary byte of the IOCB. All of the screen values above are also a write operation. The second parameter in an OPEN statement [placed in the second auxiliary byte] is far more restricted in its use. Usually set to zero. If set to 128 [$80] for the cassette, it changes from normal to short inter-record gaps [AUX2]. With the Atari 820 printer, 83 [$53; AUX byte two] means sideways characters [Atari 820 printer only]. Other printer variables [all for AUX2 as well] are: 70 [$4E] for normal 40 character per line printing and 87 [$57] for wide printing mode. With the screen [S:], a number can be used to specify the GRAPHICS modes zero through eleven. If mode zero is chosen, then the AUX1 options as above are ignored. For the ICCOM field, the following values apply [BASIC XIO commands use the same values]: Command Decimal Hex ---------------------------------------------------------------------- Open channel 3 3 Get text record [line] 5 5 BASIC: INPUT #n,A Get binary record [buffer] 7 7 BASIC: GET #n,A Put text record [line] 9 9 Put binary record [buffer] 11 B BASIC: PUT #n,A Close 12 C Dynamic [channel] status 13 D BASIC uses a special "put byte" vector in the IOCB to talk directly to the handler for the PRINT#n,A$ command. Disk File Management System Commands [BASIC XIO command]: Rename 32 20 Erase [delete] 33 21 Protect [lock] 35 23 Unprotect [unlock] 36 24 Point 37 25 Note 38 26 Format 254 FE In addition, XIO supports the following commands: Get character 7 7 Put character 11 B Draw line 17 11 Display handler only. Fill area 18 12 Display handler only. FILL is done in BASIC with XIO 18,#6,12,0,"S:" [see the BASIC Reference Manual for details]. For the RS-232 [R:], XIO supports: Output partial block 32 20 Control RTS,XMT,DTR 34 22 Baud, stop bits, word size 36 24 Translation mode 38 26 Concurrent mode 40 28 [see the 850 Interface Manual for details] CIO treats any command byte value greater than 13 [$D] as a special case, and transfers control over to the device handler for processing. For more information on IOCB use, read Bill Wilkinson's "Insight: Atari" columns in COMPUTE!, November and December 1981, and in Microcomputing, August 1982. Also refer to the OS User's Manual and De Re Atari. ---------------------------------------------------------------------------

LINE = 1 TO 24: POSITION PE EK[82],LINE 1010 FOR COL = 1 TO 38: GET#2,CHAR: TEXT$[COL,COL]=CHR$[CHAR] 1020 NEXT COL: GET#2,COL 1030 LPRINT TEXT$ 1040 NEXT LINE 1050 RETURN You can use the PTABW register at location 201 [$C9] to set the number of spaces between print elements separated by a comma. The minimum number of spaces accepted is two. LPRINT automatically uses channel seven for output. No OPEN statement is necessary and CLOSE is automatic. --------------------------------------------------------------------------- Locations 1000 to 1020 [$3E8 to $3FC] are a reserved spare buffer area.

CASBUF is also used in the disk boot process; the first disk record is read into this buffer. A cassette record consists of 132 bytes: two control bytes set to 85 [$55; alternating zeros and ones] for speed measurement in the baud rate correction routine; one control byte [see below]; 128 data bytes [compared to 125 data bytes for a disk sector], and a checksum byte. Only the data bytes are stored in the cassette buffer. See De Re Atari for more ~nformaUon on the cassette recorder.

CONTROL BYTE VALUES

Value Meaning 250 [$FA] Partial record follows. The actual number of bytes is stored in the last byte of the record [127]. 252 [$FC] Record full; 128 bytes follow. 254 [$FE] End of File [EOF] record; followed by 128 zero bytes. --------------------------------------------------------------------------- Locations 1152 to 1791 [$480 to $6FF] are for user RAM [outer environment] requirements, depending on the amount of RAM available in the machine. Provided you don't use the FP package or BASIC, you have 640 [$280] free bytes here. Locations 1152 to 1279 [$480 to $4FF] are 128 [$80] spare bytes. The floating point package, when used, requires locations 1406 to 1535 [$57E to $5FF].

LBUFF prefix one.

LBUFF prefix two.

LOMEM [locations 128, 129; [$80, $81] - the pointer to BASIC low memory] are also used by DOS and the File Management System [FMS]. Refer to the DOS source code and Inside Atari DOS for details. The addresses which follow are those for DOS 2.0S, the official Atari DOS at the time of this writing. Another DOS is available as an alternative to DOS 2.0 -- K-DOS [TM], from K-BYTE [R]. K-DOS is not menu driven but command driven. It does not use all of the same memory locations as the Atari DOS although it does use a modified version of the Atari FMS. [Another command-driven DOS, called OS/A+, is completely compatible with DOS 2.OS and is available from OSS, the creators of DOS 2.0S.]

DOS when called by BASIC.

MEMLO 1D7C-3306 [maximum]

Non-resident portion of DUP.SYS, DOS utility routines. DUP provides the utilities chosen from the DOS menu page, not from BASIC. It is not resident in RAM when you are using BASIC or another cartridge; rather it is loaded when DOS is called from BASIC or on autoboot powerup [and no cartridge supersedes it]. When DUP is loaded, it overwrites the lower portion of memory. If you wish to save your program from destruction, you must have created a MEM.SAV file on disk before you called DOS from your program. See the DOS Reference Manual. --------------------------------------------------------------------------- Locations 1792 to 2047 [$700 to $7FF; page seven] are the user boot area. MEMLO and LOMEM point to 1792 when no DOS or DUP program is loaded. This area can then be used for your BASIC or machine language programs. The lowest free memory address is 1792, and programs may extend upwards from here. There is a one-page buffer before the program space used for the tokenization of BASIC statements, pointed to by locations 128, 129 [$80, $81]. Actually a program may start from any address above 1792 and below the screen display list as long as it does not overwrite this buffer if it is a BASIC program. Also, 1792 is the start of the FMS portion of DOS when resident. When software is booted, the MEMLO pointer at 743,744 [$2E7,$2E8] in the OS data base [locations 512 to 1151; $512 to $47F] points to the first free memory location above that software; otherwise, it points to 1792. The DUP portion of DOS is partly resident here, starting at 5440 [$1540] and running to 13062 [$1540 to $3306]. The location of the OS disk boot entry routine [DOBOOT] is 62189 [$F2ED]. The standard Atari DOS 2.OS takes up sectors one through 83 [$53] on a disk. Sector one is the boot sector. Sectors two through 40 [$28] are the FMS portion, and sectors 41 [$29] through 83 are the DUP.SYS portion of DOS. For more information, see the DOS and OS source listings and Inside Atari DOS. ---------------------------------------------------------------------------

DOS.SYS and DUP.SYS

Disk boot records [sector one on a disk] are read into 1792 [$700]. Starting from $700 [1792], the format is: Byte Hex Label and use 0 700 BFLAG: Boot flag equals zero [unused]. 1 701 BRCNT: Number of consecutive sectors to read [if the file is DOS, then BRCNT equals one]. 2,3 702,703 BLDADR: Boot sector load address [$700]. 4,5 704,705 BIWTARR: Initialization address. 6 706 JMP XBCONT: Boot continuation vector; $4C [76]: JMP command to next address in bytes seven and eight. 7,8 707,708 Boot read continuation address [LSB/MSB]. 9 709 SABYTE: Maximum number of concurrently OPEN files. The default is three [see 1801 below]. 10 70A DRVBYT: Drive bits: the maximum number of drives attached to the system. The default is two [see 1802 below]. 11 70B [unused] Buffer allocation direction, set to zero. 12,13 70C,70D SASA: Buffer allocation start address. Points to 1995 [$7CB] when DOS is loaded. 14 70E DSFLG: DOS flag. Boot flag set to non-zero Must be non-zero for the second phase of boot process. Indicates that the file DOS.SYS has been written to the disk; zero equals no DOS file, one equals 128 byte sector disk, two equals 256 byte sector disk. 15,16 70F,710 DFLINK: Pointer to the first sector of DOS.SYS file. 17 711 BLDISP: Displacement to the sector link byte 125 [$7D]. The sector link byte is the pointer to the next disk sector to be read. If it is zero, the end of the file has been reached. 18,19 712,713 DFLADR: Address of the start of DOS.SYS file. 20+ 714+ Continuation of the boot load file. See the OS User's Manual and Chapter 20 of Inside Atari DOS. Data from the boot sector is placed in locations 1792 to 1916 [$700 to $77C]. Data from the rest of DOS.SYS is located starting from 1917 [$77D]. All binary file loads start with 255 [$FF]. The next four bytes are the start and end addresses [LSB/MSB], respectively.

IOCB0 is used for the screen display]. Each available file takes 128 bytes for a buffer, if you increase the number of buffers, you decrease your RAM space accordingly. You can POKE 1801 with your new number to increase or decrease the number of files and then rewrite DOS [by calling DOS from BASIC and choosing menu selection "H"] and have this number as your default on the new DOS.

DOS 2.0 default value is two. The least four bits are used to record which drives are available, so if you have drives one, three and four, this location would read: 00001101 or 13 in decimal. Each drive has a separate buffer of 128 bytes reserved for it in RAM. If you have more or less than the default [two], then POKE 1802 with the appropriate number: 1 drive = 1 BIT 0 Binary 00000001 2 drives = 3 BITS 0 & 1 00000011 3 drives = 7 BITS 0, 1 & 2 00000111 4 drives = 15 BITS 0, 1, 2 & 3 00001111 This assumes you have them numbered sequentially. If not, POKE the appropriate decimal translation for the correct binary code: each drive is specified by one of the least four bits from one in BIT 0 to four in BIT 3. If you PEEK [1802] and get back three, for example, it means drives one and two are allocated, not three drives. You can save your modification to a new disk by calling up DOS and choosing menu selection "H." This new DOS will then boot up with the number of drives and buffers you have allocated. A one-drive system can save 128 bytes this way [256 if one less data buffer is chosen]. See the DOS Manual, page G.87.

DOS [as above with menu selection "H"] without write verify as your new default by writing DOS to a new disk. See the DOS Manual, page F.85. K-DOS's write-verify flag is located at 1907 [$773].

HATABS [locations 794 to 831; $31A to $33F] by the FMS initialization routine. When CIO needs to call an FMS function, it will locate the address of that function via the handler address table. See Chapters 8-11 of Inside Atari DOS, published by COMPUTE! Books.

DOS uses the same location for its initialization routine.

DOS 2.0 [see also Inside Atari DOS, Chapter 12]. This will cause update writes to work properly, but update reads to be bad. The following POKEs will correct the problem. Remember to save DOS back to a new disk. POKE 2592,130 [$A20,82] POKE 2593,19 [$A21,13] POKE 2594,73 [$A22,49] POKE 2595,12 [$A23,0C] POKE 2596,240 [$A24,F0] POKE 2597,36 [$A25,24] POKE 2598,106 [$A26,6A] POKE 2599,234 [$A27,EA] POKE 2625,16 [$A41,10] POKE 2773,31 [$AD5,1F] [Note that the July 1982 issue of COMPUTE! contained a typo where the value to be POKEd into 2773 was mistakenly listed as 13, not 31!] Wilkinson points out that one way to completely disable BURST I/O [useful in some circumstances such as using the DOS BINARY SAVE to save the contents of ROM to disk!] is by: POKE 2606,0 [$A2E,0] This, however, will make the system LOAD and SAVE files considerably more slowly, so it's not recommended as a permanent change to DOS.

STATUS routines.

DOS Manual for information regarding these two BASIC commands, and see De Re Atari for a sample use.

ZBUFP at locations 67, 68 [$43, $44].

DOS to any other character of your choice. Your altered DOS can be saved back to disk with DOS menu selection "H".

DOS to accept file names with punctuation, numbers and lowercase as valid; 33 is the low range of the ATASCII code and 127 the high range [lower or higher values are control and graphics codes and inverse characters]. Of course, any unmodified DOS still won't accept such file names. You could actually change the range to any value from zero to 255 at your discretion. This, however, may cause other problems with such ATASCII codes as spaces and the wildcard [*; see above]. Can be saved back to disk with menu selection "H".

SETUP -- initialization of the FMS parameters. Prepares FMS to deal with the operation to be performed and to access a particular file. See Inside Atari DOS, Chapter seven.

DOS.SYS file to disk routine, including new FMS file to DOS.SYS file.

FCB's]. FCB's are used to store information about files currently being processed. The eight FCB's are 16-byte blocks that correspond in a one-on-one manner with the IOCB's. Each FCB consist of: Label Bytes Purpose FCBFNO 1 File number of the current file being processed. FCBOTC 1 Which mode the file has been OPENed for: append is one, directory read is two, input is four, output is eight, update is twelve. SPARE 1 Not used. FCBSLT 1 Flag for the sector length type; 128 or 256 bytes FCBFLG 1 Working flag. If equal to 128 [$80], then the file has been OPENed for output or append and may acquire new data sectors. If the value is 64, then sector is in the memory buffer awaiting writing to disk. FCBMLN 1 Maximum sector data length; 125 or 253 bytes depending on drive type [single or double density]. The last three sector bytes are reserved for sector link and byte count data. FCBDLN 1 Current byte to be read or modified in the operation in a data sector. FCBBUF 1 Tell FMS which buffer has been allocated to the file being processed. FCBCSN 2 Sector number of the sector currently in the buffer. FCBLSN 2 Number of the next sector in data chain. FCBSSN 2 Starting sectors for appended data if the file has been OPENed for append. FCBCNT 2 Sector count for the current file. DUP doesn't use these FCB's; it writes to the IOCB's directly. CIO transfers the control to FMS as the operation demands, then on to SIO.

DOS; the RAM-resident portion of DUP. Used for the same purpose in K- DOS.

DOS VEC [location 10; $A]. This is the pointer to the address BASIC will jump to when DOS is called.

DOS utility MEMSAVE copies the lower 6000 bytes of memory to disk to save your BASIC program from being destroyed when you call DOS, which then loads DUP.SYS into that area of memory.

DOSINI [see location 12, 13; $C, $D] vector save location. Entry point to DOS on a call from BASIC.

DOS must load MEM.SAV from the disk before it does a run at cartridge address, then jumps to the cartridge address.

DOS must load MEM.SAV before it performs a run at address command from the DOS menu.

DOS; it's well worth examining. See also "The Atari Wedge," COMPUTE!, December 1982. 663C 19E6 ISRODN Start of the serial interrupt service routine to output data needed routines in DUP.SYS.

MEMLO [743, 744; $2E7, $2E8] points here when DOS is resident unless the buffer allocation has been altered. MEMLO will point to 7164 for a one drive, two data buffer setup, a saving of 256 bytes. Loading the RS-232 handler from the 850 Interface will move MEMLO up another 1728 bytes. The RS-232 handler in the 850 Interface will only boot [load into memory] if you first boot the AUTORUN.SYS file on your Atari master diskette or use another RS-232 boot program such as a terminal package. The RS-232 handler will boot up into memory if you do not have a disk attached and you have turned it on before turning on the computer. You may still use the printer [parallel] port on the 850 even if the RS-232 handler is not booted.

DOS, you must have a minimum of 16K. ---------------------------------------------------------------------------

DOS.SYS or DUP.SYS loaded in, they also use a portion of this area to 13062 [$3306] as below:

DOS utility monitor, including the utilities called when a menu selection function is completed and the display of the "SELECT ITEM" message.

DOS/DUP files to disk.

DOS. DOS.20S is the latest official DOS, considerably improved over the earlier DOS 1.0. The S stands for single density. Atari had planned to release a dual density drive [the 815], but pulled it out of the production line at the last minute for some obscure high-level reason. A double density drive is available from the Percom company.

FRE[0], you will see, however, that you have 8K less RAM to use; and PEEKing through this area will show that the ASED program is indeed in memory, but that control was passed to BASIC. Control will pass to the ASED cartridge if the cartridges are reversed. This is because the last six bytes of the cartridge programs tell the OS where the program begins -- in both cases, it is a location in the area dedicated to the left cartridge. The six bytes are as follows: Byte Purpose Left [A] Right[B] 49146 [$BFFA] 40954 [$9FFA] Cartridge start address [low byte] 49147 [$BFFB] 40955 [$9FFB] Cartridge start address [high byte] 49148 [$BFFC] 40956,[$9FFC] Reads zero if a cartridge is inserted, non-zero when no cartridge is present. This information is passed down to the page zero RAM: if the A cartridge is plugged in, then location 6 will read one; if the B cartridge is plugged in, then location 7 will read one; otherwise they will read zero. 49149 [$BFFD] 40957 [$9FFD] Option byte. If BIT 0 equals one, then boot the disk [else there is no disk boot]. If BIT 2 equals one, then initialize and start the cartridge [else initialize but do not start]. If BIT 7 equals one, then the cartridge is a diagnostic cartridge which will take control, but not initialize the OS [else non-diagnostic cartridge]. Diagnostic cartridges were used by Atari in the development of the system and are not available to the public. 49150 [$BFFE] 40958 [$9FFE] Cartridge initialization address low byte. 49151 [$BFFF] 40959 [$9FFF] Cartridge initialization address high byte. This is the address to which the OS will jump during all powerup and RESETs. The OS makes temporary use of locations 36876 to 36896 [$900C to $9020] to set up vectors for the interrupt handler. See the OS listings pages 31 and 81. This code was only used in the development system used to design the Atari. ---------------------------------------------------------------------------

STATMENT.BAS 42509-43134 A60D-A87E Syntax tables. The OPERATOR token list begins at 42979 [$A7E3]. You can print a list of these tokens by: 5 ADDRESS = 42979: TOKEN = 16 10 IF NOT PEEK [ADDRESS] THEN PRINT: END 15 PRINT TOKEN, 20 BYTE = PEEK[ADDRESS]: ADDRESS = A DDRESS + 1 30 IF BYTE < 128 THEN PRINT CHR$[BYT E];: GOTO 20 40 PRINT CHR$[BYTE - 128] 50 TOKEN = TOKEN + 1 60 GOTO 10 DOWNLOAD OPERATOR.BAS See COMPUTE!, January and February 1982; BYTE, February 1982, and De Re Atari for an explanation of BASIC tokens. 43135-43358 A87F-A95E Memory manager. 43359-43519 A95F-A9FF Execute CONT statement. 43520-43631 AA00-AA6F Statement table. 43632-43743 AA70-AADF Operator table. 43744-44094 AAE0-AC3E Execute expression routine. 44095-44163 AC3F-AC83 Operator precedence routine. 44164-45001 AC84-AFC9 Execute operator routine. 45002-45320 AFCA-B108 Execute function routine. 45321-47127 B109-B817 Execute statement routine. 47128-47381 B818-B915 CONT statement subroutines. 47382-47542 B916-B9B6 Error handling routines. 47543-47732 B9B7-BA74 Graphics handling routines. 47733-48548 BA75-BDA4 I/O routines. 48549-49145 BDA5-BFF9 Floating point routines [see below].

SIN[FR0]. Checks DEGFLG [location 251; $FB] to see if trigonometric calculations are in radians [DEGFLG equals zero] or degrees [DEGFLG equals six].

FR0] with carry. FR0 is Floating Point register zero, locations 212-217; $D4-$D9. See the Floating Point package entry points from location 55296 on.

FR0, with carry.

FR0] with carry. Note that there is some conflict of addresses for the above routines. The addresses given are from the first edition of De Re Atari. The Atari OS Source Code Listing gives the following addresses for these FP routines: These are entry points, not actual start addresses. SIN 48513 [$BD81] COS 48499 [$BD73] ATAN 48707 [$BE43] SQR 48817 [$BEB1] However, after disassembling the BASIC ROMs, I found that the addresses in De Re Atari appear to be correct. 49146,7 BFFA,B Left cartridge start address. 49148 BFFC A non-zero number here tells the OS that there is no cartridge in the left slot. 49149 BFFD Option byte. A cartridge which does not specify a disk boot may use all of the memory from 1152 [$480] to MEMTOP any way it sees fit. 49150,1 BFFE,F Cartridge initialization address. See the above section on the right slot, 32768 to 40959, for more information. --------------------------------------------------------------------------- When a BASIC program is SAVEd, only 14 of the more than 50 page zero locations BASIC uses are written to the disk or cassette with the program. The rest are all recalculated with a NEW or SAVE command, sometimes with RUN or GOTO. These 14 locations are: 128,129 80,81 LOMEM 130,131 82,83 VNTP 132,133 84,85 VNTD 134,135 86,87 VVTP 136,137 88,89 STMTAB 138,139 8A,8B STMCUR 140,141 8C,8D STARP The string/array space is not loaded; STARP is included only to point to the end of the BASIC program. The two other critical BASIC page zero pointers, which are not SAVEd with the program, are: 142,143 8E,8F RUNSTK 144,145 90,91 MEMTOP For more information concerning Atari BASIC, see the appendix. For detailed description, refer to the Atari BASIC Reference Manual. For more technical information, see De Re Atari, BYTE, February 1982, and COMPUTE!'s First Book of Atari and COMPUTE!'s Second Book of Atari. --------------------------------------------------------------------------- Locations 49152 to 53247 [$C000 to $CFFF] are unused. Unfortunately, this rather large 4K block of memory cannot be written to by the user, so it is presently useless. Apparently, this area of ROM is reserved for future expansion. Rumors abound about new Atari OS's that allow 3-D graphics, 192K of on-board RAM and other delights. Most likely this space will be consumed in the next OS upgrade. PEEKing this area will show it not to be completely empty; it was apparently used for system development in Atari's paleozoic age. Although the Atari is technically a 64K machine [1K equals 1024 bytes, so 64K equals 65536 bytes], you don't really have all 64K to use. The OS takes up 10K; there is the 4K block here that's unused, plus a few other unused areas in the ROM and, of course, there are the hardware chips. BASIC [or any cartridge] uses another 8K. The bottom 1792 bytes are used by the OS, BASIC, and floating point package. Then DOS and DUP take up their memory space, not to mention the 850 handler if booted -- leaving you with more or less 38K of RAM to use for your BASIC programming. --------------------------------------------------------------------------- Locations 53248 to 55295 [$D000 to $D7FF] are for ROM for the special I/O chips that Atari uses. The CTIA [or GTIA, depending on which you have] uses memory locations 53248 to 53503 [$D000 to $D0FF]. POKEY uses 53760 to 54015 [$D200 to $D2FF]. PIA uses 54016 to 54271 [$D300 to $D3FF]. ANTIC uses 54272 to 54783 [$D400 to $D5FF]. ANTIC, POKEY and G/CTIA are Large Scale Integration [LSI] circuit chips. Don't confuse this chip ROM with the OS ROM which is be found in higher memory. For the most extensive description of these chips, see the Atari Hardware Manual. There are two blocks of unused, unavailable memory in the I/O areas: 53504 to 53759 [$D100 to $D1FF] and 54784 to 55295 [$D600 to $D7FF]. Many of the following registers can't be read directly, since they are hardware registers. Writing to them can often be difficult because in most cases the registers change every 30th second [stage two VBLANK] or even every 60th second [stage one VBLANK]! That's where the shadow registers mentioned earlier come in. The values written into these ROM locations are drawn from the shadow registers; to effect any "permanent" change in BASIC [i.e., while your program is running], you have to write to these shadow registers [in direct mode or while your program is running; these values will all be reset to their initialization state on RESET or powerup]. Shadow register locations are enclosed in parentheses; see these locations for further descriptions. If no shadow register is mentioned, you may be able to write to the location directly in BASIC. Machine language is fast enough to write to the ROM locations and may be able to bypass the shadow registers entirely. Another feature of many of these registers is their dual nature. They are read for one value and written to for another. The differences between these functions are noted by the [R] for read and [W] for write functions. You will notice that many of these dual-purpose registers also have two labels. ---------------------------------------------------------------------------

PMBASE=KEEP*256 40 FOR LOOP=PMBASE+512 TO PMBASE+640: POKE LOOP,0:NEXT LOOP:REM CLEAR OU T MEMORY FIRST 50 X=100:Y=10:POKE 53248,X 60 FOR LOOP=0 TO 7:READ BYTE:POKE PMB ASE+512+Y+LOOP,BYTE:NEXT LOOP:REM PLAYER GRAPHICS INTO MEMORY 70 DATA 129,153,189,255,255,189,153,1 29 80 REM LINES 100 TO 170 SET UP MACHIN E LANGUAGE ROUTINE 100 DIM UP$[21],DOWN$[21]:UP=ADR[UP$] :DOWN=ADR[DOWN$] 110 FOR LOOP=UP TO UP+20:READ BYTE:PO KE LOOP,BYTE:NEXT LOOP 120 FOR LOOP=DOWN TO DOWN+20:READ BYT E:POKE LOOP,BYTE:NEXT LOOP 130 DATA 104,104,133,204,104,133,203, 160,1,177 140 DATA 203,136,145,203,200,200,192, 11,208,245,96 150 DATA 104,104,133,204,104,133,203, 160,10,177 160 DATA 203,200,145,203,136,136,192, 255,208,245,96 200 REM VERTICAL CONTROL 210 IF STICK[0]=14 THEN GOSUB 300 220 IF STICK[0]=13 THEN D=USR[DOWN,PM BASE+511+Y]:Y=Y+1 250 GOTO 210 300 U=USR[UP,PMBASE+511+Y]:Y=Y-l 310 RETURN DOWNLOAD MOVEPM.BAS This will move any nine-line [or less] size player vertically with the joystick. If you have a larger player size, increase the 11 in line 140 to a number two larger than the number of vertical lines the player uses, and change the ten in line 150 to one greater than the number of lines. To add horizontal movement, add the following lines: 6 HPOS = 53248 230 IF STICK[0] = 11 THEN X = X - 1: POKE HPOS, X 240 IF STICK[0] = 7 THEN X = X + 1: POKE HPOS, X You can use the routine to move any player by changing the number 511 in the USR calls to one less than the start address of the object to be moved. See the appendix for a map of P/M graphics memory use. Missiles are more difficult to move vertically with this routine, since it moves an entire byte, not bits. It would be useful for moving all four missiles vertically if you need to do so; they could still be moved horizontally in an individual manner. See COMPUTE!, December 1981, February 1982, and May 1982, for some solutions and some machine language move routines, and COMPUTE!, October 1981, for a solution with animation involving P/M graphics.

M0PF

[R] Missile 0 to playfield collision. This register will tell you which playfield the object has "collided" with, i.e., overlapped. If missile 0 collides with playfield two, the register would read four and so on. Bit use is: Bit 7 6 5 4 3 2 1 0 Playfield .....unused.... 3 2 1 0 Decimal ............... 8 4 2 1

PCOLR0 [location 704; $2C0] rather than the usual COLOR4 [location 712; $2C8], which will affect the priority detection. In GR.10, playfield colors set by PCOLR0 to PCOLR3 [704 to 707; $2C0 to $2C3] behave like players where priority is concerned. Bit use is: Bit 7 6 5 4 3 2 1 0 Playfield .....unused.... 3 2 1 0 Decimal ............... 8 4 2 1

GRACTL and DACTL [53277 and 54272; $D0lD and $D400]: 10 POKE 623,1: POKE 559,54: POKE 542 79, 224: POKE 53277,1 20 FOR N = 53252 TO 53255: POKE N, 1 00 + X: X = X + 10: NEXT N: X = 0 30 INPUT SIZE: POKE 53260, SIZE 40 GOTO 30 See 54279 [$D407] for more information on P/M graphics.

P0PL

[R] Player 0 to player collisions. Bit use is: Bit 7 6 5 4 3 2 1 0 Player ...unused... 3 2 1 0 Decimal ............ 8 4 2 1

GRACTL at 53277]. If DMA is enabled, then the graphics registers will be loaded automatically from the area specified by PMBASE [54279; $D407]. The GRAF registers can only write a single byte to the playfield, but it runs the entire height of the screen. Try this to see: 10 POKE 53248, 160: REM SET HORIZONT AL POSITION OF PLAYER 0 20 POKE 704, 245: REM SET PLAYER 0 C OLOUR TO ORANGE 30 POKE 53261, 203: REM BIT PATTERN 11001011 To remove it, POKE 53261 with zero. The bit order runs from seven to zero, left to right across the TV screen. Each bit set will appear as a vertical line on the screen. A value of 255 means all bits are set, creating a wide vertical line. You can also use the size registers to change the player width. Using the GRAF registers will allow you to use players and missiles for such things as boundaries on game or text fields quite easily.

P1PL

[R] Player 1 to player collisions.

GRACTL [53277; $D01D] is set to one, then all TRIG BITs 0 are latched when the button is pressed [set to zero] and are only reset to one [not pressed] when BIT 2 of GRACTL is reset to zero. The effect of latching the triggers is to return a constant "button pressed" read until reset.

GRAFM works the same as GRAFP0 above. Each pair of bits represents one missile, with the same allocation as in 53260 [$D00C] above. Bit 7 6 5 4 3 2 1 0 Missile -3- -2- -1- -0- Each bit set will create a vertical line running the entire height of the TV screen. Missile graphics shapes may be set separately from each other by using the appropriate bit pairs. To mask out unwanted players, write zeros to the bits as above.

TRIG1

[R] Joystick trigger 1 [645]. Controller jack two, pin six.

PRIOR establishes which objects on the screen [players, missiles, and playfields] will be in front of other objects. Values used in this register are also described at location 623 [$26F], the shadow register. If you use conflicting priorities, objects whose priorities are in conflict will turn black in their overlap region. Priority order [Decimal values in brackets]: Bit 0 = 1 [1]: Bit 1 = 1 [2]: Player 0 Player 0 Player 1 Player 1 Player 2 Playfield 0 Player 3 Playfield 1 Playfield 0 Playfield 2 Playfield 1 Playfield 3 and Player 5 Playfield 2 Player 2 Playfield 3 and Player 5 Player 3 Background Background Bit 2 = 1 [4]: Bit 3 = 1 [8]: Playfield 0 Playfield 0 Playfield 1 Playfield 1 Playfield 2 Player 0 Playfield 3 and Player 5 Player 1 Player 0 Player 2 Player 1 Player 3 Player 2 Playfield 2 Player 3 Playfield 3 and Player 5 Background Background Bit 4 = 1: Enable a fifth player out of the four missiles. Bit 5 = 1: Overlap of players 0 and 1, 2 and 3 is third color [else overlap is black]. The resulting color is a logical OR of the two player colors. Bits 6 and 7 are used to select GTIA modes: 0 0 = no GTIA modes 0 1 = GTIA GR.9 1 0 = GTIA GR.10 1 1 = GTIA GR.11

VDELAY to one moves the corresponding object down by one TV line. If DMA is enabled, then moving an object by more than one line is accomplished by moving bits in the memory map instead. Bit Decimal Object 7 128 Player 3 6 64 Player 2 5 32 Player 1 4 16 Player 0 3 8 Missile 3 2 4 Missile 2 1 2 Missile 1 0 1 Missile 0

DMACTL [location 54272; $D400] to latch all stick and paddle triggers [to remember if triggers on joysticks or paddles have been pressed], to turn on players and to turn on missiles. To get the values to be POKEd here, add the following options together for the desired function: Decimal Bit To turn on missiles 1 0 To turn on players 2 1 To latch trigger inputs 4 2 To revoke P/M authorization and turn off both players and missiles, POKE 53277,0. Once latched, triggers will give a continuous "button pressed" read the first time they are pressed until BIT 2 is restored to zero. Triggers are placed in "latched" mode when each individual trigger is pressed, but you cannot set the latch mode for individual triggers. Have you ever hit BREAK during a program and still had players or their residue left on the screen? Sometimes hitting RESET doesn't clear this material from the screen. There are ways to get rid of it: POKE 623,4: This moves all players behind playfields. POKE 53277,0: This should turn them off. POKE 559,2: This should return you to a blank screen. Make sure you SAVE your program before POKEing, just in case!

HITCLR just before an event which may lead to a collision; for example, right before a joystick or paddle is "read" to move a player or fire a missile. Then test for a collision immediately after the action has taken place. Remember that multiple collisions cause sums of the collision values to be written to the collision registers; if you do not clear HITCLR often enough, a program checking for individual collisions will be thrown off by these sums.

CONSOL with eight. POKEing any number from zero to eight will cause a click from the speaker. A FOR-NEXT loop that alternately POKEs CONSOL with eight and zero or just zero, since the OS put in an 8 every 1/60 second, will produce a buzz. Values PEEKed will range from zero to seven according to the following table: |Key Value 0 1 2 3 4 5 6 7 | | | +------------------------------------------------------------+ | | |OPTION X X X X | |SELECT X X X X | |START X X X X | | | +------------------------------------------------------------+ Bits 2 0 0 0 0 1 1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 0 1 0 1 0 1 Where zero means all keys have been pressed, one means OPTION and SELECT have been pressed, etc., to seven, which means no keys have been pressed. CONSOL is updated every stage two VBLANK procedure with the value eight. It is possible to use the console speaker to generate different sounds. Here is one idea based on an article in COMPUTE!, August 1981: 10 GOSUB 1000 20 TEST = USR[1536] 999 END 1000 FOR LOOP = 0 TO 26: READ BYTE: P OKE 1536 + LOOP, BYTE: NEXT LOOP : RETURN 1010 DATA 104,162,255,169,255,141,31, 208,169 1020 DATA 0,160,240,136,208,253,141,3 1,208,160 1030 DATA 240,136,208,253,202,208,233 ,96 To change the tone, you POKE 1547 and 1555 with a higher or lower value [both are set to 240 above]. To change the tone duration, you POKE 1538 with a lower value [it is set to 255 in the routine above]. Do these before you do your USR call or alter the DATA statements to permanently change the values in your own program. Turn off DMA [see location 559] to get clearer tones. --------------------------------------------------------------------------- Locations 53280 to 53503 [$D020 to $D0FF] are repeats of locations 53248 to 53279 [$D000 to $D01F]. You can't use any of the repeated locations; consider them "filler." They maybe used for other purposes in any Atari OS upgrade. --------------------------------------------------------------------------- Locations 53504 to 53759 [$D100 to $D1FF] are unused. These loca- tions are not empty; you can PEEK into them and find out what's there. They cannot, however, be user-altered. ---------------------------------------------------------------------------

AUDCTL register with the number for the desired clock frequency. You then set the volume to zero in the AUDC register associated with the AUDF register you plan to use as a timer. You load the AUDF register itself with the number of clock intervals you wish to count. Then you load your interrupt routine into memory, and POKE the address into the appropriate timer vector between locations 528 and 533 [$210 and $215]. You must set the proper bit[s] in IRQEN and its shadow register POKMSK at location 16 [$10] to enable the interrupt. Finally, you load STIMER with any value to load and start the timer[s]. The OS will force a jump to the timer vector and then to your routine when the AUDF register counts down to zero. Timer processing can be preempted by ANTIC's DMA, a DLI, or the VBLANK process. POT values are for the paddles, ranging from zero to 240, increasing as the paddle knob is turned counterclockwise, but values less than 40 and greater than 200 represent an area on either edge of the screen that may not be visible on all TV sets or monitors.

POTGO command or after ALLPOT changes [see 53768; $D208 and 53771; $D20B]. POT registers continually count down to zero, decrementing every scan line. They are reset to 228 when they reach zero or by the values read from the shadow registers. This makes them useful as system timers. See COMPUTE!, February 1982, for an example of this use. The POTGO sequence [see 53771; $D20B] resets the POT registers to zero, then reads them 228 scan lines later. For the fast pot scan, BIT 2 of SKCTL at 53775 [$D20F] must be set.

AUDF3 to store the 19200 baud rate for SIO.

POT2

[R] Pot 2 [626].

AUDF3 above and with AUDF4 to store the 600 baud rate for SIO.

POT4

[R] Pot 4 [628].

AUDCTL with zero and POKE 53775,3 [$D20F]. These two are the equivalent of the BASIC statement SOUND 0,0,0,0. AUDCTL is the option byte which affects all sound channels. This bit assignment is: Bit Description: 7 Makes the 17 bit poly counter into nine bit poly [see below] 6 Clock channel one with 1.79 MHz 5 Clock channel three with 1.79 MHz 4 Join channels two and one [16 bit] 3 Join channels four and three [16 bit] 2 Insert high pass filter into channel one, clocked by channel two 1 Insert high pass filter into channel two, clocked by channel four 0 Switch main clock base from 64 KHz to 15 KHz Poly [polynomial] counters are used as a source of random pulses for noise generation. There are three polys: four, five and 17 bits long. The shorter polys create repeatable sound patterns, while the longer poly has no apparent repetition. Therefore, setting BIT 7 above, making the 17-bit into a nine-bit poly will make the pattern in the distortion more evident. You chose which poly[s] to use by setting the high three bits in the AUDC registers. The 17-bit poly is also used in the generation of random numbers; see 53770 [$D20A]. The clock bits allow the user to speed up or slow down the clock timers, respectively, making higher or lower frequency ranges possible. Setting the channels to the 1.79 MHz will produce a much higher sound, the 64 KHz clock will be lower, and the 15 KHz clock the lowest. The clock is also used when setting the frequency for the AUDF timers. Two bits [three and four] allow the user to combine channels one and two or three and four for what amounts to a nine octave range instead of the usual five. Here's an example from De Re Atari of this increased range, which uses two paddles to change the frequency: the right paddle makes coarse adjustments, the left paddle makes fine adjustments: 10 SOUND 0,0,0,0:POKE 53768,80:REM SE T CLOCK AND JOIN CHANNELS 1 AND 2 20 POKE 53761,160:POKE 53763,168:REM TURN OFF CHANNEL 1 AND SET 2 TO PU RE TONE GENERATION 50 POKE 53760,PADDLE[0]:POKE 53762,PA DDLE[1]:GOTO 30 High pass filters allow only frequencies higher than the clock value to pass through. These are mostly used for special effects. Try: 10 SOUND 0,0,0,0:POKE 53768,4:REM HIG H PASS FILTER ON CHANNEL 1 20 POKE 53761,168:POKE 53765,168:REM PURE TONES 30 POKE 53760,254:POKE 53764,127 40 GOTO 40 See the excellent chapter on sound in De Re Atari: it is the best explanation of sound functions in the Atari available. See also the Hardware Manual for complete details.

ALLPOT

[R] Eight line pot port state; reads all of the eight POTs together. Each bit represents a pot [paddle] of the same number. If a bit is set to zero, then the register value for that pot is valid [it's in use]; if it is one, then the value is not valid. ALLPOT is used with the POTGO command at 53771 [$D20B]. ----------------------------------------------------------------------

IRQEN below, these AUDF registers generate timer interrupts when they count down from the number you POKEd there to zero. The vectors for the AUDF1, AUDF2 and AUDF4 timer interrupts are located between 528 and 533 [$210 and $215]. POKEY timer four interrupt is only enabled in the new "B" OS ROMs.

KBCODE

[R] Holds the keyboard code which is then loaded into the shadow register [764; $2FC] when a key is hit. Usually read in response to the keyboard interrupt. Compares the value with that in CH1 at 754 [$2F2]. If both values are the same, then the new code is accepted only if a suitable key debounce delay time has passed. The routines which test to see if the key code will be accepted start at 65470 [$FFBE]. BIT 7 is the control key flag, BIT 6 is the shift key flag.

AUDCTL is set] for the value of the number. You can use this location in a program to generate a random integer between zero and 255 by: 10 PRINT PEEK[53770] This is a more elegant solution than INT[RND[0] * 256]. For a test of the values in this register, use this simple program: 10 FOR N = 1 TO 20: PRINT PEEK[53770]: NEXT N

POTGO resets the POT registers to zero. Written by the stage two VBLANK sequence.

VTIMR1 [528; $210] 1 2 Timer 2 [counted down to zero] VTIMR2 [530; $212] 2 4 Timer 4 [counted down to zero] VTIMR4 [532; $214], OS "B" ROMs only] 3 8 Serial output transmission done VSEROC [526; $20E] 4 16 Serial output data needed VSEROR [524; $20C] 5 32 Serial input data ready VSERIN [522; $20A] 6 64 Other key pressed VKEYBD [520; $208] 7 128 BREAK key pressed see below Here is the procedure for the BREAK key interrupt: clear the interrupt register. Set BRKKEY [17; $11] to zero; clear the start/stop flag SSFLAG at 767 [$2FF]; clear the cursor inhibit flag CRSINH at 752 [$2F0]; clear the attract mode flag at 77 [$4D], and return from the interrupt after restoring the 6502 A register. [There is now [in the OS "B" ROMs] a proper vector for BREAK key interrupts at 566, 567 [$236, $237] which is initialized to point to 59220 [$E754].] If the interrupt was due to a serial I/O bus proceed line interrupt, then vector through VPRCED at 514 [$202]. If due to a serial I/O bus interrupt line interrupt, then vector through VINTER at 516 [$204]. If due to a 6502 BRK instruction, then vector through VBREAK at 518 [$206]. Timers relate to audio dividers of the same number [an interrupt is processed when the dividers count down to zero]. These bits in IRQEN are not set on powerup and must be initiated by the user program before enabling the processor IRQ. There are two other interrupts, processed by PIA, generated over the serial bus Proceed and Interrupt lines, set by the bits in the PACTL and PBCTL registers [54018 and 54019; $D302, $D303]: Bit Decimal Locution Interrupt 0 1 PACTL Peripheral A [PORTA] interrupt enable bit. 7 128 PACTL Peripheral A interrupt status bit. 0 1 PBCTL Peripheral B [PORTB] interrupt enable bit. 7 128 PBCTL Peripheral B interrupt status bit. The latter PORT interrupts are automatically disabled on powerup. Only the BREAK key and data key interrupts are enabled on powerup. The shadow register is 16 [$10].

IRQST

[R] Interrupt request status. Bit functions are the same as IRQEN except that they register the interrupt request when it is zero rather than the enable when a bit equals one. IRQST is used to determine the cause of interrupt request with IRQEN, PACTL and PBCTL as above. All IRQ interrupts are normally vectored through 65534 [$FFFE] to the IRQ service routine at 59123 [$E6F3], which determines the cause of the interrupt. The IRQ global RAM vector VIMIRQ at 534 [$216] ordinarily points to the IRQ processor at 59126 [$E6F6]. The processor then examines 53774 [$D20E] and the PIA registers at 54018 and 54019 to determine the interrupt cause. Once determined, the routine vectors through one of the IRQ RAM vectors in locations 514 to 526 [$202 to $20E]. For Non-Maskable Interrupts [NMI's], see locations 54286 to 54287 [$D40E; $D40F]. See the OS User's Manual for complete details.

SKCTL [W] register are normally zero and perform the functions below when set to one. The status when used as [R] is listed below the write [W] function: Bit Function 0 [W] Enable keyboard debounce circuits. [R] Not used by SKSTAT. 1 [W] Enable keyboard scanning circuit. [R] Serial input shift register busy. 2 [W] Fast pot scan: the pot scan counter completes its sequence in two TV line times instead of one frame time [228 scan lines]. Not as accurate as the normal pot scan, however. [R] the last key is still pressed. 3 [W] Serial output is transmitted as a two-tone signal rather than a logic true/false. POKEY two-tone mode. [R] The shift key is pressed. 4,5,6 [W] Serial port mode control used to set the bi-directional clock lines so that you can either receive external clock data or provide clock data to external devices [see the Hardware Manual, p. II.27]. There are two pins on the serial port for Clock IN and Clock OUT data. See the OS User's Manual, p. 133. 4 [R] Data can be read directly from the serial input port, ignoring the shift register. 5 [R] Keyboard over-run. Reset BITs 7 to 5 [latches] to one using SKRES at 53770 [$D20A]. 6 [R] Serial data input over-run. Reset latches as above. 7 [W] Force break [serial output to zero]. [R] Serial data input frame error caused by missing or extra bits. Beset latches as above. BIT 2 is first set to zero to reset POT registers to zero [dumping the capacitors used to change the POT registers]. Then BIT 2 is set to one to enable the fast scan. Fast scan is not as accurate as the normal scan routine. BIT 2 must be reset to zero to enable the normal scan mode; otherwise, the capacitors will never dump. --------------------------------------------------------------------------- Locations 53776 to 54015 [$D210 to $D2FF] are duplications of locations 53760 to 53775 and have no particular use at present. ---------------------------------------------------------------------------

VINTER and VPRCED, vectored at locations 514 to 517 [$202 to $205]. These interrupts are unused by the OS, but also may be used to provide greater control over external devices.

PACTL [location 54018] is one. Writes to direction control if BIT 2 of PACTL is zero. These two port registers also control the direction of data flow to the port, if the controller register [54018, below] is POKEd with 48 [$30]. Then, if the bits in the register read zero, it is in input [R] mode; if they read one, it is in output [W] mode. A zero POKEd here makes all bits input, a 255 [$FF] makes all bits output. BITs 0 to 3 address pins one to four on jack one, BITs 4 to 7 address pins one to four on jack two. POKE 54018 with 52 to make this location into a data register again. Shadow registers are: STICK0 [632; $278, jack one], STICK1 [633; $279, jack two] and PTRIG0-3 [636-639; $27C-$27F]. Bits used as data register 7 6 5 4 3 2 1 0 --Jack 0-- --Jack 1-- --Stick 1-- --Stick 0-- Forward = BIT 0, 4 = 1 Backward = BIT 1, 5 = 1 Left = BIT 2,6 = 1 Right = BIT 3,7 = 1 Neutral = All four jack bits = 1 PORTA is also used to test if the paddle 0-3 triggers [PTRIG] have been pressed, using these bits: Bit 7 6 5 4 3 2 1 0 PTRIG 3 2 - - 1 0 - - Where zero in the appropriate bit equals trigger pressed, one equals trigger not pressed. The PORT registers are also used in the keyboard controller [used with a keypad] operation where: Bit 7 6 5 4 3 2 1 0 Row 4 3 2 Top 4 3 2 Top Jack ..........2......... ..........1........... Columns for the keyboard operation are read through the POT [PADDL] and TRIG registers. See Micro, May 1982, and the Hardware Manual for more information on jacks and ports.

PORTA, above, for the respective jacks. Shadow registers are: STICK2 [634; $27A, jack three], STICK3 [635, $27B, jack four], and PTRIG4-7 [640-643; $280-$283].

PACTL can be used for other external applications by the user. Bit use is as follows: Bit Function 7 [read only] Peripheral A interrupt [IRQ] status bit. Set by Peripheral [PORT] A. Reset by reading PORTA [53774; $D20E]. 6 Set to zero. 5 Set to one. 4 Set to one. 3 [write] Peripheral motor control line [turn the cassette on or off; zero equals on]. 2 [write] Controls PORTA addressing. One equals PORTA register; zero equals direction control register. 1 Set to zero. 0 [write] Peripheral A interrupt [IRQ] enable. One equals enable. Set by the OS but available to the user; reset on powerup.

PBCTL is the same as PACTL, above, with the following exception [this may actually perform the same function as in PACTL, but I am not sure of the distinction between descriptions]: Bit Function 3 Peripheral command identification [serial bus command], initialized to 60 [$3C]. Ports can be used for external control applications by the technically minded reader who is willing to do some soldering to develop cables and connectors. A good example can be found in COMPUTE!, February 1981, where the author gives directions for using jacks three and four as a printer port. The Macrotronic printer cables use just this method, bypassing the 830 interface entirely [one way of reducing your hardware costs]. Theoretically, the entire Atari can be controlled through the ports! --------------------------------------------------------------------------- Locations 54020 to 54271 [$D304 to $D3FF] are repeats of locations 54016 to 54019 [$D300 to $D303]. ---------------------------------------------------------------------------

GRACTL at 53277 [$D01D]. Both must be set properly or no display will result. BIT 5 enables DMA to fetch the display list instructions. If BIT 5 is not set [BIT 5 equals zero], ANTIC will not work. DMACTL is initialized to 34 [$22]. A player in single line resolution might look like this: 00011000 ## 00111100 #### 01111110 ###### 11111111 ######## 11111111 ######## 01111110 ###### 00111100 #### 00011000 ## so that each byte is displayed on one TV line. The same player in double line resolution would look like this: 00011000 ## 00011000 ## 00111100 #### 00111100 #### 01111110 ###### 01111110 ###### 11111111 ######## 11111111 ######## 11111111 ######## 11111111 ######## 01111110 ###### 01111110 ###### 00111100 #### 00111100 #### 00011000 ## 00011000 ## where every byte is displayed over two TV lines.

HSCROL with from zero to 16 clock cycles for the number of cycles to scroll. Horizontal fine scrolls can be used only if BIT 4 of the display list instruction is set. The difficulty in horizontal scrolling lies in arranging the screen data to be scrolled in such a manner as to prevent wraparound [i.e., the bit or byte scrolled off screen in one line becomes the bit or byte scrolled on screen in an adjacent line]. Normal data arranged for TV display looks like this on the screen: +----------+ |..........| |..........| |..........| |..........| |..........| |..........| +----------+ where it is a one-dimensional memory area "folded" at the proper places to create the image of a two dimensional screen. This is done by the DL character or map mode instruction. Without other instructions, it reads the memory continuously from the first specified location, each line taking the correct number of bytes for the GRAPHICS mode specified. To properly scroll it horizontally, you must arrange it in relation to the TV screen like this: +----------+ .....|..........|..... .....|..........|..... .....|..........|..... .....|..........|..... .....|..........|..... .....|..........|..... +----------+ Now you will have to make each display instruction for each line into a Load Memory Scan [LMS] instruction. To direct each LMS to the proper screen RAM for that line, you will have to increment each memory location by the total length of the line. For example, if you want to scroll a 256-byte horizontal screen, each LMS instruction will have to point to a location in memory 256 bytes above the last one. Of course, you will have to implement error-trapping routines so that your screen does not extend beyond your desired boundaries. Coarse scrolling, one byte at a time, can be done without setting the HSCROL register by the method described above. For smooth scrolling, you will have to use this register. See De Re Atari.

VSCROL with from zero to 16 scan lines, depending on the GRAPHICS mode of the screen for the number of scan lines to scroll. Vertical fine scrolls can be used only if BIT 5 of the display list instruction has been set. Coarse scrolling can be done without using this register, simply by moving the top of the screen address [as defined by the DL LMS instruction] up or down one mode line [plus or minus 40 or 20 bytes, depending on the GRAPHICS mode]. The top of the screen address can be found by: 10 DLIST = PEEK[560] + PEEK[561] * 2 56 20 SCRNLO = DLIST + 4: SCRNHI = DLIS T + 5: REM LSB/MSB OF SCREEN ADDRE SS 25 PRINT "SCREEN ADDRESS = " PEEK[SC RNLO] + PEEK[SCRNHI] * 256 You could then add a routine to this for a coarse - scroll vertically through the memory with a joystick, such as: 30 LOBYTE = 0: HIBYTE = 0 40 IF STICK[0] = 14 THEN LOBYTE = LO BYTE + 40:GOTO 100 50 IF STICK[0] = 13 THEN LOBYTE = LO BYTE - 40 60 IF LOBYTE < 0 THEN LOBYTE = LOBYT E + 256: HIBYTE = HIBYTE - 1 70 IF HIBYTE < 0 THEN HIBYTE = 0 80 GOTO 200 100 IF LOBYTE 255 THEN LOBYTE = LOB YTE - 256 110 HIBYTE = HIBYTE + 1 200 POKE SCRNLOW, LOBYTE: POKE SCRNHI , HIBYTE 210 GOTO 40 DOWNLOAD VSCROL.BAS Coarse scrolling is relatively easy to implement in the Atari: one basically alters the screen RAM to display the new material. Fine scrolling is more difficult: each scroll register must be POKEd with the number of units to be scrolled -- color clocks or scan lines -- and the corresponding display list instructions must have the proper bits set. This means you can selectively fine scroll any mode lines you wish by setting only those bits of the lines you intend to scroll. Other lines will be displayed normally. You can set a DL instruction for both horizontal and vertical scroll enable. See the Hardware Manual for a discussion of the problems in fine scrolling. Fine scrolling will allow only a certain amount of data to be scrolled before the register must be reset [16 clock bits or scan lines maximum]. In order to make the scrolling activity continuous, the register involved must be reset to zero when the desired value is reached, a coarse scroll must be implemented [usually during a DLI or VBLANK interval] and a new fine scroll begun. This is not easily done in BASIC since it is too slow, and changing registers during ANTIC's display process usually causes rough or jerky motion. Assembly routines are suggested for smooth display. See De Re Atari, Micro, November 1981, BYTE, January 1982, and Santa Cruz's Tricky Tutorial #2 for more information.

PMBASE * 256. P/M graphics are tricky to use since there are no direct Atari 8K BASIC commands to either create or move them [there are, however, commands for P/M graphics in BASIC A+ and in valFORTH utilities]. Your P/M graphics must always begin on a 1K boundary [PEEK[RAMTOP]-4 for double line resolution players] or 2K boundary [PEEK[RAMTOP]-5 for single line resolution], so the LSB is always zero [page numbers always end in $XX00]. For example: 10 POKE 106, PEEK[106] - 8: GRAPHIC S 8: SETCOLOR 2,3,4 20 POKE 559,62: POKE 53248,100: POK E 704,160: POKE 53256,2 30 MEM = PEEK[106] - 8 40 POKE 54279, MEM: POKE 53277,3: S TART = MEM * 256 + 1024 50 FOR LOOP = 100 TO 119: READ BYTE : POKE START + LOOP, BYTE: NEXT LO OP 60 DATA 16,16,56,40,40,56,40,40,40 70 DATA 124,84,124,84,254,146,254,1 70,170,68 100 END You can change the color, width, resolution, and horizontal position of the player in the example by altering the registers used above. Each player is one byte [eight bits] wide. Single line resolution P/M characters [POKE 559,62] can be up to 256 bytes high. Double line resolution P/M characters [POKE 559,46] can be up to 128 bytes high. In either case, they can map to the height of the screen. Missiles have the same height, but are only two bits wide each. Four missiles can be combined into a fifth player by setting BIT 4 of location 623 [$26F]. You need not fill the entire height of a P/M character, but you should POKE unused bytes with zero to eliminate any screen garbage. You can do this by: FOR N = PMBASE + 1024 TO PMBASE + 2048: POKE N,0: NEXT N where PMBASE is the starting address of the reserve memory area. In double line resolution, change the loop value to N = PMBASE + 512 TO PMBASE + 1024. Here's a short machine language routine to do the same thing. You would put the start address of the area to be loaded with zero and the number of bytes to be cleared in with the USR call as the first two parameters. In this example, I have arbitrarily chosen 38012 and 2048 for these values. 10 START = 38012: BYTE = 2048: DIM PGM$[42] 20 FOR LOOP = 1 TO 42: READ ML: PGM $[LOOP, LOOP] = CHR$[ML]: NEXT LOO P 30 DATA 104,104,133,204,104,133,203 ,104,133,206,104 40 DATA 133,205,166,206,160,0,169,0 ,145,203,136 50 DATA 208,251,230,204,202,48,6,20 8,244,164 60 DATA 205,208,240,198,204,160,0,1 45,203,96 70 A = USR[ADR[PGM$],START,BYTE] You can use this routine to clear out memory anywhere in the Atari. You can also use it to load any one value into memory by changing the second zero [after the 169] in line 40 to the value desired. Locating your graphics tables at the high end of memory may cause addressing problems for playfield graphics, or may leave some of the display unusable and cause PLOT to malfunction. If you locate your tables just before the screen display, it may be erased if you change graphics modes. You can look at your highest RAM use graphics statement and plan accordingly. To calculate a safe starting address below the display list, try: 100 DLIST = PEEK[560] + PEEK[561] * 256: PMBASE = INT [DLIST/SIZE -1] * SIZE where SIZE is 2048 for single line resolution, 1024 for double line. Once you have the starting address, determine the ending address of your table by adding the correct number of bytes for the size [same as the SIZE variable above], and POKE this number [LSB/MSB] into APPMHI at locations 14 and 15 [$E, $F]. This sets the lower limit for playfield graphics memory use. If you change graphics modes in the program now, it should leave your player tables intact. For example, if the DL is at 39968, the PMBASE will equal 36864 in the equation above. Add 2048 [single line resolution] to get 38912. This is $9800. In decimal, the LSB is zero and the MSB is 152. POKE these values into APPMHI. This sets the lowest limit to which the screen and DL data may descend. The unused portion of the RAM set aside for P/M use, or any RAM reserved for players, but not used, may be used for other purposes in your program such as machine language routines. See the appendix for a map of P/M memory use. The register stores the address as below: Bit 7 6 5 4 3 2 1 0 One line resolution: ......MSB...... ...unused... Two line resolution: ........MSB........ unused.. There are some restrictions on locating your P/M data above the display list. If not positioned far enough above your screen data, you may end up with both the normal and screen data being displayed at once, resulting in garbage on the screen. A display list may not cross a 1K boundary without a jump instruction, and the screen display RAM cannot cross a 4K boundary without an LMS instruction to point to the proper byte[s]. Due to problems that arise when moving the GR.7 and GR.8 screens and data less than 4K, you should never reserve less than 16 pages above RAMTOP in these modes. If you are reserving more, add the pages in blocks of 4K [16 pages]. See COMPUTE!, September 1981, for a discussion of the problems of positioning P/M graphics in memory, and using P/M graphics for animation. See De Re Atari, COMPUTE!, June 1982, and Creative Computing, April 1982, for a discussion of using string manipulation with P/M graphics. See Your Atari 400/800 for a general discussion of P/M graphics. Most of the popular magazines have also carried articles on simplifying P/M graphics.

WSYNC register, type in the second example of a Display List Interrupt at location 512. RUN it and observe that it causes a clean separation of the colors at the change boundary. Now change line 50 to: 50 DATA 72,169,222,234,234,234,141,24,208,104,64 This eliminates the WSYNC command. RUN it and see the difference in the boundary line. The keyboard handler sets WSYNC repeatedly while generating the keyboard click on the console speaker at 53279 [$D01F]. When interrupts are generated during the WSYNC period, they get delayed by one scan line. To bypass this, examine the VCOUNT register below and delay the interrupt processing by one line when no WSYNC delay has occurred.

VCOUNT value [above] when the pen trigger is pressed. See the Hardware Manual, p. II-32, for a description of light pen operation.

NMIEN is set to 64 [$40] by the OS IRQ code on powerup, enabling VBI's, but disabling DLI's. All NMI interrupts are vectored through 65530 [$FFFA] to the NMI service routine at 59316 [$E7B4] to determine their cause. Bit 7 6 5 4 3 2 1 0 Interrupt: DLI VBI RESET ... unused ....

NMIEN above. If a DLI is pending, a jump is made through the global RAM vector VDSLST [512; $200]. The OS doesn't use DLI's, so 512 is initialized to point to an RTI instruction and must be changed by the user before a DLI is allowed. If the interrupt is not a DLI, then a test is made to see if the interrupt was caused by pressing RESET key and, if so, a jump is made to 58484 [$E474]. If not a RESET interrupt, then the system assumes the interrupt was a VBLANK interrupt, and a jump is made through VVBLKI at 546 [$222], which normally points to the stage one VBLANK processor. From there it checks the flag at CRITIC [66; $42] and, if not from a critical section, jumps through VVBLKD at 548 [$224], which normally points to the VBLANK exit routine. On powerup, the VBLANK interrupts are enabled while the display list interrupts are disabled. See the end of the memory map for a description of the VBLANK procedures. For IRQ interrupts, see location 53744 [$D20E]. --------------------------------------------------------------------------- Locations 54288 to 54303 [$D410 to $D41F] are repeats of locations 54272 to 54287 [$D400 to $D40F]. --------------------------------------------------------------------------- Locations 54784 to 55295 [$D600 to $D7FF] are unused but not empty nor user alterable. See the note at 53504 [$D100]. ---------------------------------------------------------------------------

FR0 at 212 to 217, $D4 to $DB]:

FR0 at 212 to 217 [$D4-$DB] by setting all bytes to zero.

FR1, locations 224 to 229 [$E0 to $E5], by setting all bytes to zero. Also called AF1 by De Re Atari.

FR0 minus the value in FR1.

FR0 plus FR1.

FR0 times FR1.

FR0 divided by FR1.

FR0 from the 6502 X,Y registers.

FR0 from user routine, using FLPTR at 252 [$FC].

FR1 from the 6502 X,Y registers.

FR1 from user program, using FLPTR.

FR0.

FR0, using FLPTR.

FR0 to FR1.

CHBASE = 57344 20 DIM A$[128],BYTE[128],WANT[128] 27 PRINT "INPUT A 40 CHARACTER STRIN G:" 30 INPUT A$ 35 TIME = TIME + 1 40 FOR LOOK = 1 TO LEN[A$] 50 BYTE[LOOK] = ASC[A$[LOOK,LOOK]] 51 IF BYTE[LOOK] > 127 THEN BYTE[LOO K] = BYTE[LOOK] - 128 52 IF BYTE[LOOK] < 32 THEN BYTE[LOOK ] = BVTE[LOOK] + 64: GOTO 55 53 IF BYTE[LOOK] < 97 THEN BVTE[LOOK ] = BYTE[LOOK] - 32 55 NEXT LOOK 59 FOR EXTRA = 0 TO 7 60 FOR LOOK = 1 TO LEN[A$] 70 WANT[LOOK] = PEEK[CHBASE + EXTRA + BYTE[LOOK]*8] 80 POKE TV + EXTRA, WANT[LOOK]: TV = TV + 1 82 NEXT LOOK 85 SCREEN = SCREEN + 39: TV = SCREEN 90 NEXT EXTRA 100 SCREEN = REAL + TIME*320 110 IF SCREEN > REAL + 6080 THEN TIM E = 0: GOTO 100 120 GOTO 30 DOWNLOAD BITMAP8.BAS This program simply takes the bytes which represent the letters you input as A$ and finds their places in the ROM character set. It then proceeds to POKE the bytes into the screen RAM, using a FOR-NEXT loop. To convert ATASCII codes to the internal codes, use this table: ATASCII value Operation for internal code 0 -- 31 add 64 32 -- 95 subtract 32 96 -- 127 remains the same 128 -- 159 add 64 160 -- 223 subtract 32 224 -- 255 remains the same See COMPUTE!, November 1981, for the program "TextPlot" which displays text in different sizes in GRAPHICS modes three to eight, and January 1982 for a program to edit character sets, "SuperFont." --------------------------------------------------------------------------- Locations 58368 to 58447 [$E400 to $E44F] are the vector tables, stored as LSB, MSB. These base addresses are used by resident handlers. Handler vectors use the following format: OPEN vector CLOSE vector GET BYTE vector PUT BYTE vector GET STATUS vector SPECIAL vector Jump to handler initialization routine [JMP LSB/MSB] The device tables in location 794 [$31A] point to the particular vector[s] used in each appropriate table. In each case, the 6502 X register is used to point to the originating IOCB.

CIOV directly will allow the user to input or output a buffer of characters at a time, such as loading a machine language program directly into memory from a disk file. This is considerably faster than using BASIC functions such as GET. Here is a typical machine language subroutine to do this: PLA, PLA, PLA, TAX, JMP $E456 [104,104,104,170,76,86,228] [$68,$68,$68,$AA,$4C,$56,$E4] This gets the IOCB number into the 6502 X register and the return address on the stack. CIOV expects to find the IOCB number 16 in the 6502 X register [i.e., IOCB zero is zero, IOCB one is 16; $10, IOCB two is 32, $20, etc.]. $E456 is the CIO initialization entry point [this address]. To use CIOV in a program, first you must have OPENed a channel for the appropriate actions, POKEd the correct IOCB [locations 848 to 959; $350 to $3BF] with the correct values, and established a location in which to load your file [IOCB address plus four and plus five]. One use is calling up a high-res picture from a disk and storing it in the screen memory [locations 88, 89; $58, $59]. You can POKE the appropriate decimal values into memory and call it with a USR call, or make it into a string [START$ = "hhh*LVd" where the * and the d are both inverse characters] and call it by: JUMP = USR[ADR[START$]] This method is used to start the concurrent mode in the RS-232 of the 850 interface in the 850 Interface Manual. See location 88, 89 [$58, $59] for another example of the machine language routine technique. Still another use of this method can be found in De Re Atari. Initialized to 58564 [$E4C4].

SETVBV insures that both bytes of the vector addressed will be updated while VBLANK is enabled. You can JSR here when creating your own timer routines. See COMPUTE!, November 1981, for an application. Initialized to 59666 [$E912] old ROMs, 59629 [$E8ED] new ROMs.

VVBLKI [546, 547; $222, $223]. It is initialized to 59345 [$E7D1], which is the VBLANK routine entry. Initialized to 59345 [$E7D1] old ROMs, 59310 [$E7AE] new ROMs.

VVBLKD [548, 549; $224, $225]. Initialized to 59710 [$E93E], which is the VBLANK exit routine. It is used to restore the computer to its pre-interrupt state and to resume normal processing. Initialized to 59710 [$E93E] old ROMs, 59653 [$E905] new ROMs.

DOS handlers previously booted. Initialized to 61987 [$F223].

STATUS and special command routines.

ISRSIR;

is the serial input ready IRQ vector. This is 60175 [$EB0F] in the new OS ROMs.

VCOUNT timer. The tables for the AUDF and VCOUNT values are between 60882 and 60905 [$EDD2 and $EDE9].

EGETCH gets a line from the screen and keyboard, but only one character at a time. You must do a JSR $F63E for each character input. This is also the address of the beginning of the screen editor routines.

VKEYBD at locations 520, 521 [$208, $209] to 65470 [$FFBE]. This is the keyboard service routine. It processes debounce, and SHIFT- CTRL logic [see location 559; $22F]; saves the internal keyboard code in 754 [$2F2] and 764 [$2FC]; sets the ATTRACT mode flag at 77 [$4D] and sets location 555 [$22B -- SRTIMR] to 48 [$30].

65528 FFF8 CHKSUN

According to Softside Magazine, December 1981, if a PEEK here returns 255, then you have the older OS ROM[s]. There were some troubles with cassette loads in the older ROMs that sometimes require the following to cure: Do an LPRINT without a printer attached before CLOAD. This clears the cassette buffer. Press RESET before CSAVEing or CLOADing will restore the system to its initialization parameters and help with loading and saving routines. There is a new OS available from Atari which fixes a bug that would cause the I/O operations to "time out" for a few seconds. It apparently does not alter any of the routines mentioned here. The chip reset interrupt [powerup] vectors through location 65532 [$FFFC] to 58487 [$E477] where a JMP vector to the powerup routine is located. A chip reset is not the same as pressing the RESET key, which in itself does not generate a chip reset. The NMI interrupts are vectored through 65530 [$FFFA] to the NMI service routine [ISR] at 59316 [$E7B4], and all IRQ interrupts are vectored through 65534 [$FFFE] to the IRQ service routine at 59123 [$E6F3]. In these service routine areas, the cause of the interrupt is determined, and the appropriate action is taken, either by the OS or through a JMP to a RAM vector where a user routine exists.
Quay trở lại bảng nội dung. Chương trước. Chương tiếp theo

Câu lệnh PHP nào sau đây sẽ lưu trữ 111 trong một biến num I INT $num 111 II INT num 111 III $num 111 IV 111 $num *?

[b] Tất cả những điều đã đề cập .

Câu lệnh PHP nào sau đây sẽ xuất Hello World trên màn hình?

Câu lệnh PHP nào sau đây sẽ xuất Hello World trên màn hình? . echo[], print[] và printf[] cả ba đều có thể được sử dụng để xuất câu lệnh lên màn hình.

Chủ Đề