64 Screen Splitter
Lou Goldstein
This Commodore 64 utility allows you to add extra sprites, mix graphics and text, and achieve other split-screen effects usually seen only in commercial software. It can be used without machine language knowledge.
Ordinarily, the Commodore 64 can display only one screen type at a time, one character set at a time, one set of sprites at a time, and so on. But imagine selecting one set of features for the upper portion of the screen and another for the lower portion. You might, for example, use high-resolution graphics above and standard text below. Or you might want a combination of eight sprites and graphics characters on top, plus extended color mode and eight more sprites on the bottom.
Such seemingly impossible split screens are easily created—if you happen to be an accomplished machine language programmer. With "64 Screen Splitter," you can manage true split screens with absolutely no knowledge of machine language. Screen Splitter adds two new commands to BASIC to permit the simultaneous display of two distinct screens of your choice. Each screen can be either high resolution or text, and can use standard, multi color, or extended color text mode. Each can have its own colors, character set, and sprites. In short, anything you can do with a single screen, you can do with each of your two screens.
Get Ready To Split
Program 1 is the machine language for Screen Splitter, which you must enter with the "MLX" machine language entry program published elsewhere in this issue. Follow the MLX instructions carefully. When you run MLX, you'll be asked for a starting address and an ending address for the data you will be entering. Here are the addresses you will need to type in Screen Splitter:
Starting address: C000 Ending address: C697
Before using Screen Splitter, you must always reserve a safe memory area where it can store high-resolution screens and dot patterns. This is done by moving the start of BASIC program space upward in memory. BASIC workspace normally starts at location 2048. For Screen Splitter, the safest new location is 16384. Here is a short program that performs all of the setup needed to use Screen Splitter:
10 IF A=0 THEN A=1: LOAD "SPLITTER",8,1 20 SYS 49152:POKE 43,1:POKE 44,16*4: POKE 16*1024, 0 30 PRINT "{CLR} {4 DOWN} LOAD" CHRS (34) "MYPROG" CHRS (34)",8" 40 PRINT "{4 DOWN} RUN {HOME}" 50 FOR K=631 TO 640:POKE K, 13:NEXT 60 POKE 198, 10:NEW
Line 10 loads Screen Splitter into memory. When you type line 10, replace SPLITTER with the name you used when saving Screen Splitter with MLX (if you are using tape instead of disk, substitute ,1,1 for ,8,1). Line 20 activates Screen Splitter with SYS 49152 and raises the start of BASIC to location 16384. Lines 30–60 are optional and should be used only if you want to load and run a BASIC program of your own (in which case, you should substitute the name of your program for MYPROG in line 30). If you don't want to load and run a program, add a NEW statement to the end of line 20 and delete lines 30–90.
Program 2 contains a brief demonstration of several Screen Splitter features. Don't forget to load and activate Screen Splitter before you load and run this program.
Split Screen Commands
Screen Splitter adds two new statements to Commodore 64 BASIC: @SCREEN and @SPLIT (note that both statements begin with an @sign). The @SCREEN statement prepares the correct environment for a split-screen display, and @SPLIT actually makes the split screen appear. @SCREEN must always be used before @SPLIT. Here is the general syntax for @SCREEN:
@SCREEN map, topchar, botchar, topmode, botmode
@SCREEN takes five parameters, which can be numbers or numeric variables. The first parameter, map, can be any number from 0–4, and determines where your screens will be stored. Figure 1 shows the five different memory configurations selected by map values 0–4.
The numbers at the left of the figure represent ranges of memory locations and have been abbreviated (8K–16K means locations 8192-16383, and so on). The memory areas shaded with ****** are free for storing definitions (dot patterns) for sprites or custom characters. Each 1K free section can contain data for as many as 128 characters, or 16 sprites.
The area marked with ////// is not usable for sprite patterns or text-screen custom characters, since it is replaced by the ROM image of the Commodore characters whenever the video chip is active. However, it can hold dot patterns of custom characters to be POKEd onto a high-resolution screen, since those POKEs can only be done when the video chip is inactive. In fact, in maps 3 and 4, the same area may be used simultaneously for standard text-screen characters and custom hi-res characters.
In maps 0 and 2, the amount of memory needed for graphics depends on your use of sprites and custom characters. In these configurations, you may be able to raise the start of BASIC to locations 8192 or 10240 instead of 16384, to make more room available for a long program or a large array.
The lower screen of map 2 consists of text written on a video matrix beginning at location 3072 instead of the usual location of 1024. To print on this screen, POKE a value of 12 into address 648; this operation tells the screen editor that the screen begins at location 3072 (12*256). To return to the normal screen, POKE a value of 4 into 648; this represents the normal screen address 1024 (4*256). After you choose the desired screen, PRINT statements work normally. However, printing and clearing the screen affect only the visible portion of the text screen.
The next two parameters for @SCREEN, topchar and botchar, set the address at which each screen will find its character definitions. Legal values are even numbers from 2–14, representing the 1K boundary where the character definitions begin. A value of 4 selects the uppercase/graphics character set. The uppercase/lowercase set requires a value of 6. Use other values to select custom character sets. Since it is not possible to PRINT directly on a hi-res screen, these parameters are ignored for hi-res work (however, you must still supply legal values for topchar and botchar). Screen Splitter does not allow you to change character sets by pressing SHIFT-Commodore.
Figure 1. Memory Allocations for @SCREENThe last two @SCREEN parameters, topmode and botmode, select the upper and lower color modes. These values should be 0 for normal colors or 1 for multicolor mode. A value of 2 (legal for text screens only) selects extended color mode.
If you execute a @SPLIT statement without previously using @SCREEN, you will get a default setup that is equivalent to @SCREEN 0,4,6,0,0 with a blue background and yellow sprites on top, and a yellow background and blue sprites below.
@SPLIT
The second new command, @SPLIT, requires one parameter, the number of lines of the upper screen to be shown. Legal values are in the range 0-25. Values from 1-24 produce split screens of varying sizes. A value of 1, for example, makes the top screen one text line (eight lines of hi-res dots) in height. The remainder of the display is allotted to the lower screen. When the @SPLIT value is 2, the top screen contains two text lines, and so on.
An @SPLIT value of 0 displays only the lower screen, and @SPLIT 25 shows only the top screen. These two configurations do more than simply make the other screen invisible: They turn Screen Splitter off completely, which increases the computer's processing speed and prevents screen flicker during tape or disk access. These configurations can be invaluable in debugging. When your program stops with an error, the error message and READY prompt may be printed on a part of the screen that is invisible to you. If you suspect this has occurred, type @SPLIT 0 or @SPLIT 25 in immediate mode (even if you have to type blind) to examine the entire text screen. In map 1, neither screen contains text, so use @SCREEN 0,4,4,0,0 to check the text screen.
Controlling Video Features
Once you've created a split screen with @SCREEN and @SPLIT, you essentially have two independent screens at your disposal. You may use any of the ordinary graphics techniques appropriate to the current configuration, keeping in mind the reduced size of each screen.
The usual way to control sprites and other video features is by POKEing values into the appropriate VIC-II control registers. A similar method is used with Screen Splitter, but the addresses are different. Instead of POKEing into the control registers themselves, you POKE mock registers and let Screen Splitter transfer the values to the actual control registers when the time is right.
There are 47 VIC-II control registers, which normally begin at location 53248. Screen Splitter provides two sets of mock control registers—one set for the upper screen and one for the lower. The 47 top screen registers begin at location 49235. The 47 mock registers for the bottom screen begin at location 49282. Whenever you POKE a new value into one of the mock registers, Screen Splitter waits until the correct time, then transfers that value into the corresponding control register.
Pointers to sprite dot patterns are normally stored in the last eight bytes of the video matrix (locations 2040-2047). But, since Screen Splitter permits as many as 16 sprites to share the screen in some configurations, it is necessary to use mock sprite pointer registers as well. The mock sprite pointers are always in the same place regardless of the screen's location. The top screen sprite pointers occupy the eight bytes beginning at location 49329. These bytes are preset to point to sprite shape locations 32-39 (locations 2048-2111 contain the data for sprite 0, the next 64 bytes contain the data for sprite 2, and so forth). The lower screen sprite pointers begin at location 49337 and point to sprite locations 40–47. Of course, you can POKE new values into these registers at any time.
At the start of each raster interrupt all the sprite pointers at the end of the current video matrix are reset to point to sprite shape location 11 (addresses 704-767, filled with zero bytes when you first activate Screen Splitter). If this occurs in the middle of a sprite, the video chip continues to send it to the screen, but since the dot pattern is blank, the rest of the sprite becomes invisible. Near the end of the interrupt, the sprite pointers for the new screen are copied into the last eight bytes of its video matrix. The video chip continues to project any remaining upper sprites, but uses the new horizontal position, color, and dot data. As a result, when an upper sprite sinks through the boundary, the bottom few lines of the corresponding lower sprite may appear just below the boundary, at the lower sprite's x position.
Changing the lower sprite's y position or even turning it off completely will not prevent this overlap problem—these controls are ignored once the chip begins projecting a sprite. So when an upper sprite is going to drop through the boundary, the same numbered sprite for the lower screen should contain a blank definition (at least for its bottom several lines), or it must be positioned off the side of the screen. Sprites rising from the lower screen are cut off at the top as they approach the boundary. But when the sprite's y position reaches the split point, the remaining portion of the sprite suddenly disappears.
Advanced Techniques
Most VIC-II registers control only one feature. However, locations 53265 and 53270 each control multiple functions. The @SCREEN statement initializes both of the mock registers corresponding to 53265 with a default value of 27 (three rasters of vertical fine scrolling, 25 rows, blanking off, bitmapping off, extended color off, raster bit 8 off). Both mock registers corresponding to 53270 are set to 8 (no horizontal fine scrolling, 40 columns, multicolor off). Changes are made as needed to turn on extended, multicolor, or bitmap graphics. The default settings may be changed with POKEs to address 49638 for register 53265 and 49646 for register 53270. For more information about these rarely used features, consult Mapping the 64, available from COMPUTE! Books, and the Commodore 64 Programmer's Reference Guide.
You can override @SPLIT's raster control with POKEs. The @SPLIT statement always sets the number of scan lines above the boundary to a multiple of eight, so that text will fit neatly on the screen. For an in-between position, adjust location 49253 to the value 48 plus the number of scan lines of upper screen you want to display. For example, this statement shows 43 scan lines of hi-res screen in the top screen:
POKE 49253, 43 + 48
You may also change the raster setting for the change from lower to upper screen. The normal value is 19 for an offscreen transition. But you can set location 49300 to a value greater than 48, creating a three-part screen with the bottom screen visible both below and above the top screen.
For a strange effect, POKE 49253 with a value of 19 to match the lower register. If the upper and lower screen colors are different, you will see them flicker in alternation. If the colors are the same, you will be able to see up to 16 flickering sprites at once against a steady background. Each sprite will be free to move anywhere on the screen. To display a flicker-free sprite, create a twin in the same position on the other screen.
Screen Splitter uses a delay during the interrupt to insure that any change in background color occurs between scans of the TV's electron beam. The length of the delay is controlled by location 50828, which, in turn, is set by @SCREEN. Maps 3 and 4 usually change colors early in the interrupt, when the screen type changes. @SCREEN sets location 50828 for eight passes of the delay loop. The other maps generally change colors later, when the color registers are copied, so six passes of the delay loop are sufficient. If something in your program disrupts the timing (for example, a sprite may be located at the boundary) the color may change in the middle of a row of pixels. You can correct such an imperfection by changing the value in location 50828.
Most VIC-II registers are intended to be POKEd rather than PEEKed. But four control registers are usually read: locations 53267–53268 for the light pen, and locations 53278–53279 for sprite collisions. Splitter ignores these locations, so you can PEEK them as usual. However, the VIC-II has no way to tell whether a collision involves upper or lower sprites. If there is any possibility of confusion on this point, your program must analyze the sprite positions to clear it up.
Program 1. Screen Splitter
Please refer to the "MLX" article in this issue before entering the following listing.
C000 : AD 15 03 C9 CF 90 0C AD 21 C008 : 14 03 8D C3 C0 AD 15 03 2C C010 : 8D C4 C0 78 A0 06 B9 46 FF C018 : C0 99 03 03 88 D0 F7 58 C0 C020 : A9 08 20 D2 FF A2 3F A9 5C C028 : 00 9D C0 02 CA E0 FF D0 F3 C030 : F8 60 40 53 43 52 45 45 B6 C038 : CE D0 40 53 50 4C 49 D4 AD C040 : D1 00 00 32 C0 3A C0 3D 7B C048 : C1 E2 C0 18 C1 06 C4 B8 65 C050 : C1 50 C3 00 00 00 00 00 3F C058 : 00 00 00 00 00 00 00 00 D9 C060 : 00 00 00 00 1B 80 00 00 BC C068 : 00 08 00 14 01 01 00 00 39 C070 : 00 00 00 06 06 00 00 00 82 C078 : 00 00 08 08 08 08 08 08 F3 C080 : 08 08 00 00 00 00 00 00 08 C088 : 00 00 00 00 00 00 00 00 0A C090 : 00 00 00 1B 13 00 00 00 5C C098 : 08 00 16 01 01 00 00 00 F8 C0A0 : 00 00 08 08 00 00 00 00 A3 C0A8 : 00 06 06 06 06 06 06 06 27 C0B0 : 06 20 21 22 23 24 25 26 9D C0B8 : 27 28 29 2A 2B 2C 2D 2E 32 C0C0 : 2F 00 00 00 00 00 00 00 D9 C0C8 : 00 00 00 00 00 00 00 00 4A C0D0 : 00 A9 2C A0 00 D1 7A F0 79 C0D8 : 05 A2 0B 6C 00 03 20 9B 95 C0E0 : B7 60 08 2C 0F 00 30 0A FC C0E8 : C9 D0 90 06 C9 D2 B0 02 F2 C0F0 : 90 04 28 4C 1A A7 8C 49 57 C0F8 : 00 28 38 E9 D0 0A A8 B9 E3 C100 : 43 C0 85 FD B9 44 C0 85 CB C108 : FE A0 00 B1 FD 30 06 20 2B C110 : D2 FF C8 D0 F6 4C EF A6 92 C118 : 20 73 00 C9 D0 90 06 C9 C3 C120 : D2 B0 02 90 06 20 79 00 26 C128 : 4C E7 A7 38 E9 D0 0A A8 93 C130 : B9 4F C0 85 FD B9 50 C0 0D C138 : 85 FE 6C FD 00 20 7C A5 CA C140 : A0 00 B9 00 02 F0 0C C9 01 C148 : 22 F0 16 C9 40 F0 1E C8 43 C150 : 4C 42 C1 99 02 02 E8 C8 0F C158 : C8 C8 C8 A9 FF 84 71 C8 E3 C160 : 60 C8 B9 00 02 F0 EC C9 F4 C168 : 22 F0 E4 D0 F4 84 FC A2 39 C170 : 00 BD 32 C0 29 7F D9 00 B0 C178 : 02 D0 0A BD 32 C0 30 1A 5D C180 : E8 C8 4C 71 C1 BD 32 C0 75 C188 : 30 03 E8 D0 F8 E8 E8 A4 F0 C190 : FC BD 32 C0 D0 DB C8 4C 28 C198 : 42 C1 E8 BD 32 C0 C8 A6 73 C1A0 : FC 9D 00 02 E8 B9 00 02 5A C1A8 : 9D 00 02 F0 05 C8 E8 4C B3 C1B0 : A5 C1 A4 FC C8 4C 42 C1 99 C1B8 : 20 DE C0 8E C6 C0 20 41 BF C1C0 : C3 20 D1 C0 8E C7 C0 20 A9 C1C8 : 30 C3 20 D1 C0 8E C8 C0 09 C1D0 : 20 30 C3 20 D1 C0 8E C9 63 C1D8 : C0 20 4B C3 20 D1 C0 8E C2 C1E0 : CA C0 20 4B C3 A9 1B 8D 3B C1E8 : CB C0 8D CE C0 A9 08 8D 6B C1F0 : CC C0 8D CF C0 A9 06 8D FF C1F8 : 8C C6 A0 0F A2 07 AD C6 CC C200 : C0 D0 11 A9 10 8D CD C0 E9 C208 : 8D D0 C0 8E 2D C5 8E 6E 95 C210 : C6 4C 80 C2 C9 01 D0 1B 57 C218 : A9 20 0D CB C0 8D CB C0 6D C220 : A9 20 0D CE C0 8D CE C0 AB C228 : A9 18 8D CD C0 8D D0 C0 B5 C230 : 4C 0B C2 C9 02 D0 13 A9 B6 C238 : 10 8D CD C0 A9 30 8D D0 E8 C240 : C0 8E 2D C5 8C 6E C6 4C C3 C248 : 80 C2 A9 08 8D 8C C6 C9 6A C250 : 03 D0 15 A9 10 8D CD C0 DB C258 : A9 20 0D CE C0 8D CE C0 E3 C260 : A9 38 8D D0 C0 4C 41 C2 04 C268 : A9 10 8D D0 C0 A9 20 0D 7F C270 : CB C0 8D CB C0 A9 38 8D 25 C278 : CD C0 8C 2D C5 8E 6E C6 85 C280 : AE C7 C0 AD CB C0 29 20 16 C288 : D0 07 8A 0D CD C0 8D CD B4 C290 : C0 AE C8 C0 AD CE C0 29 9A C298 : 20 D0 07 8A 0D D0 C0 8D A6 C2A0 : D0 C0 AD C9 C0 F0 21 C9 E6 C2A8 : 02 D0 15 AD CB C0 29 20 B4 C2B0 : F0 03 4C 46 C3 AD CB C0 8A C2B8 : 09 40 8D CB C0 4C C8 C2 CC C2C0 : A9 10 0D CC C0 8D CC C0 24 C2C8 : AD CA C0 F0 21 C9 02 D0 04 C2D0 : 15 AD CE C0 29 20 F0 03 E0 C2D8 : 4C 46 C3 AD CE C0 09 40 35 C2E0 : 8D CE C0 4C EE C2 A9 10 A3 C2E8 : 0D CF C0 8D CF C0 AD CB 82 C2F0 : C0 8D 64 C0 AD CD C0 8D 86 C2F8 : 6B C0 AD CC C0 8D 69 C0 B6 C300 : AD CE C0 8D 93 C0 AD D0 CE C308 : C0 8D 9A C0 AD CF C0 8D 6E C310 : 98 C0 AD 2D C5 AE 6E C6 29 C318 : A0 02 8D 0B C4 8E 4C C5 91 C320 : C8 C8 C8 C0 1A D0 F3 8D EC C328 : BC C3 8E DB C3 4C AE A7 E2 C330 : 8A F0 13 6A 90 03 4C 46 B1 C338 : C3 E0 0F 90 03 4C 46 C3 5E C340 : 60 E0 05 B0 01 60 A2 0E B8 C348 : 6C 00 03 E0 03 4C 43 C3 08 C350 : 20 DE C0 8E C6 C0 E0 00 9B C358 : F0 09 E0 19 F0 0B 90 0F 2C C360 : 4C 46 C3 20 C4 C3 4C AE 96 C368 : A7 20 A5 C3 4C AE A7 8A B3 C370 : 0A 0A 0A 18 69 30 8D 65 CE C378 : C0 A9 7F 8D 0D DC 78 A9 0A C380 : C4 8D 15 03 A9 06 8D 14 35 C388 : 03 AD 94 C0 8D 12 D0 AD 9F C390 : 11 D0 29 7F 8D 11 D0 A9 ED C398 : 0F 8D 19 D0 A9 01 8D 1A C1 C3A0 : D0 58 4C AE A7 20 E3 C3 64 C3A8 : A2 2E BD 53 C0 9D 00 D0 47 C3B0 : CA E0 FF D0 F5 A0 07 B9 DC C3B8 : B1 C0 99 F8 07 88 C0 FF E7 C3C0 : D0 F5 58 60 20 E3 C3 A2 F9 C3C8 : 2E BD 82 C0 9D 00 D0 CA 8C C3D0 : E0 FF D0 F5 A0 07 B9 B1 88 C3D8 : C0 99 F8 07 88 C0 FF D0 CE C3E0 : F5 58 60 2C 11 D0 10 FB 30 C3E8 : 78 AD C3 C0 8D 14 03 AD 0D C3F0 : C4 C0 8D 15 03 A9 00 8D 5A C3F8 : 6D C0 8D 9C C0 8D 1A D0 24 C400 : A9 81 8D 0D DC 60 78 A9 44 C408 : 0B 8D F8 07 8D F9 07 8D F9 C410 : FA 07 8D FB 07 8D FC 07 B9 C418 : 8D FD 07 8D FE 07 8D FF D0 C420 : 07 20 8B C6 AD 77 C0 48 28 C428 : AD 76 C0 48 AD 75 C0 48 CF C430 : AD 74 C0 48 AD 73 CO 48 4F C438 : AD 64 C0 AE 69 C0 AC 6B C7 C440 : C0 8D 11 D0 8E 16 D0 8C B7 C448 : 18 D0 68 8D 20 D0 68 8D 9A C450 : 21 D0 68 8D 22 D0 68 8D 37 C458 : 23 D0 68 8D 24 D0 AD 53 A0 C460 : C0 8D 00 D0 AD 54 C0 8D 88 C468 : 01 D0 AD 55 C0 8D 02 D0 C2 C470 : AD 56 C0 8D 03 D0 AD 57 65 C478 : C0 8D 04 D0 AD 58 C0 8D 31 C480 : 05 D0 AD 59 C0 8D 06 D0 25 C488 : AD 5A C0 8D 07 D0 AD 5B A2 C490 : C0 8D 08 D0 AD 5C C0 8D D9 C498 : 09 D0 AD 5D C0 8D 0A D0 87 C4A0 : AD 5E C0 8D 0B D0 AD 5F DF C4A8 : C0 8D 0C D0 AD 60 C0 8D 82 C4B0 : 0D D0 AD 61 C0 8D 0E D0 E9 C4B8 : AD 62 C0 8D 0F D0 AD 63 1D C4C0 : C0 8D 10 D0 AD 6A C0 8D 43 C4C8 : 17 D0 AD 6E C0 8D 1B D0 F1 C4D0 : AD 6F C0 8D 1C D0 AD 70 ED C4D8 : C0 8D 1D D0 AD 78 C0 8D 35 C4E0 : 25 D0 AD 79 C0 8D 26 D0 D7 C4E8 : AD 7A C0 8D 27 D0 AD 7B 2C C4F0 : C0 8D 28 D0 AD 7C C0 8D BE C4F8 : 29 D0 AD 7D C0 8D 2A D0 3A C500 : AD 7E C0 8D 2B D0 AD 7F 6A C508 : C0 8D 2C D0 AD 80 C0 8D 68 C510 : 2D D0 AD 81 C0 8D 2E D0 9D C518 : AD 65 C0 8D 12 D0 A9 01 EC C520 : 8D 19 D0 8D 1A D0 A2 07 0C C528 : BD B1 C0 9D F8 07 CA E0 4B C530 : FF D0 F5 AD 68 C0 8D 15 FF C538 : D0 A9 C5 8D 15 03 A9 47 77 C540 : 8D 14 03 58 6C C3 C0 78 E9 C548 : A9 0B 8D F8 07 8D F9 07 16 C550 : 8D FA 07 8D FB 07 8D FC 2F C558 : 07 8D FD 07 8D FE 07 8D FE C560 : FF 07 20 8B C6 AD A6 C0 65 C568 : 48 AD A5 C0 48 AD A4 C0 47 C570 : 48 AD A3 C0 48 AD A2 C0 0B C578 : 48 AD 93 C0 AE 98 C0 AC 18 C580 : 9A C0 8D 11 D0 8E 16 D0 0A C588 : 8C 18 D0 68 8D 20 D0 68 F7 C590 : 8D 21 D0 68 8D 22 D0 68 CA C598 : 8D 23 D0 68 8D 24 D0 AD A0 C5A0 : 82 C0 8D 00 D0 AD 83 C0 54 C5A8 : 8D 01 D0 AD 84 C0 8D 02 74 C5B0 : D0 AD 85 C0 8D 03 D0 AD 94 C5B8 : 86 C0 8D 04 D0 AD 87 C0 B6 C5C0 : 8D 05 D0 AD 88 C0 8D 06 B1 C5C8 : D0 AD 89 C0 8D 07 D0 AD 3D C5D0 : 8A C0 8D 08 D0 AD 8B C0 19 C5D8 : 8D 09 D0 AD 8C C0 8D 0A EE C5E0 : D0 AD 8D C0 8D 0B D0 AD E5 C5E8 : 8E C0 8D 0C D0 AD 8F C0 7B C5F0 : 8D 0D D0 AD 90 C0 8D 0E 2C C5F8 : D0 AD 91 C0 8D 0F D0 AD 8E C600 : 92 C0 8D 10 D0 AD 99 C0 EA C608 : 8D 17 D0 AD 9D C0 8D 1B 3D C610 : D0 AD 9E C0 8D 1C D0 AD 7D C618 : 9F C0 8D 1D D0 AD A7 C0 76 C620 : 8D 25 D0 AD A8 C0 8D 26 3C C628 : D0 AD A9 C0 8D 27 D0 AD 23 C630 : AA C0 8D 28 D0 AD AB C0 CC C638 : 8D 29 D0 AD AC C0 8D 2A 79 C640 : D0 AD AD C0 8D 2B D0 AD CB C648 : AE C0 8D 2C D0 AD AF C0 2F C650: 8D 2D D0 AD B0 C0 8D 2E B6 C658: D0 AD 94 C0 8D 12 D0 A9 58 C660: 01 8D 19 D0 8D 1A D0 A2 1B C668: 07 BD B9 C0 9D F8 07 CA D5 C670: E0 FF D0 F5 AD 97 C0 8D C2 C678: 15 D0 A9 C4 8D 15 03 A9 B6 C680: 06 8D 14 03 68 A8 68 AA 88 C688: 68 58 40 A2 06 CA 10 FD 0C C690: EA EA 60 00 00 00 00 00 5A
Program 2. Split Screen Demo
For instructions on entering this listing, Please refer to "COMPUTE!'s Guide to Typing In programs" in this issue of COMPUTE!.
MJ 10 PRINT"{CLR} {2 DOWN} {13 RIGHT} PLEASE WAIT" JD 20 FORA = 8192T014192: POKEA, 0: NEXT SG 30 FORX = 100T0200:Y = 30: GOSUB 510: Y = 90: GOSUB510: NEXT: FORY = 30T090: X = 100: GOSUB510 BF 40 X = 200: GOSUB510: NEXT CF 50 FORK = 2048T02111: POKEK, 255: NEXT DH 60 BR = 49282: TR = 49235: POKEBR + 33, 14: POKETR + 33, 6: POKE6 46, 1: POKETR + 32, 8: POKEBR + 32, 8 QB 70 POKE648, 4: @SCREEN0, 4, 6, 0, 0: @SPLIT12: PRINT "{CLR}" FE 80 TY = 95 GA 90 POKETR, 200: POKETR + 21, 1 JG 100 FORK = 1T080 DJ 110 TY = TY + 1 GK 120 POKETR + 1, TY HB 130 FORJ = 1T030: NEXT: NEXT PP 140 POKETR + 21, 0 SB 150 PRINT "{8 DOWN} NOTICE THE CHANGING CHARACTER SETS" PX 160 PRINT "{6 DOWN} ABOVE AND BELOW THE SPLIT." CD 170 FORK = 1TO3 HX 180 @SCREEN0, 6, 4, 0, 0 QJ 190 FORJ = 1TO700: NEXT AQ 200 @SCREEN0, 4, 6, 0, 0 HX 210 FORJ = 1TO700: NEXT DE 220 NEXT: PRINT "{CLR}" SP 230 POKE648, 12: PRINT "{CLR}": @SCREEN2, 4, 4, 0, 0: @SPLIT19 DM 240 POKEBR + 33, 14: POKETR + 33, 14: POKE646, 6 CJ 250 POKE648, 4: PRINT "{CLR} {2 DOWN} THIS IS MAP NUMBER 2. {DOWN}" PH 260 PRINT "THE TOP IS ONE THE 1K TEXT SCREEN. KK 270 PRINT "THE BOTTOM IS ON {SPACE} THE 3K TEXT SCREEN. RD 280 POKE648, 12 GS 290 PRINT "{17 DOWN}" PR 300 PRINT "WATCH WHAT HAPPENS WHEN I REACH THE RB 310 PRINT "BOTTOM OF THE SCREEN. CG 320 FORK = 1TO9:PRINTK "****** SCROLLING *****": FORJ = 1TO600: NEXTJ, K RB 330 POKE648, 4: PRINT "{CLR} {3 DOWN} WHERE DID THE OTHER LINES GO??? {DOWN}" SK 340 PRINT "I'LL EXECUTE @SPLIT 0 SO YOU CAN SEE.": FORK = 1TO2000: NEXT: @SPLIT 0 CF 350 FORK = 1TO2000: NEXT: @SPLIT19 BG 360 PRINT "{CLR} {3 DOWN} PRESS ANY KEY AND I'LL CLEAR THE BOTTOM SCREEN ONLY.": POKE198, 0 EA 370 GETA$: IFA$ = ""THEN 370 KX 380 POKE648, 12: PRINT "{CLR}" EA 390 FORK = 1TO2000: NEXT: @SPLIT25: @SCREEN4, 4, 4, 0, 0: POKE648, 4 ER 400 PRINT "{CLR}{22 DOWN} NOW WE WILL ENTER MAP #4, {SPACE} A HIRES MH 410 PRINT "UPPER SCREEN, WITH A TEXT SCREEN GJ 420 PRINT "BELOW. {2 SPACES} THERE'S A HIRES PICTURE SR 430 PRINT "ON THE SCREEN NOW. PRESS A KEY FK 440 PRINT "AND I'LL SHOW IT {SPACE} TO YOU. EC 450 PRINT "PRESS AGAIN, AND {SPACE} I'LL COME BACK.": POKE198, 0 QR 460 GETA$: IFAS = ""THEN460 AA 470 @SPLIT16 AM 480 GETA$ : IFA$ = ""THEN480 FH 490 @SPLIT0: PRINT "{3 DOWN} THIS ENDS THE DEMONSTRATION." AJ 500 PRINT "{DOWN} FEEL FREE TO CONTINUE IN IMMEDIATE MODE.": END FG 510 CH = INT (X/8): RO = INT (Y/8): LN = YAND7: BY = 8192 + RO*320 + 8*CH + LN: BI = 7 -(XAND7) KM 520 POKEBY, PEEK (BY) OR (2↓BI): RETURN