From judd@stratus.esam.nwu.edu Tue Nov 24 01:50:05 1998 Newsgroups: comp.binaries.cbm Subject: Binaries From Commodore Hacking #17 From: Stephen Judd Date: 23 Nov 1998 07:20:05 PST *** comp.binaries.cbm is a moderated binaries- *** *** only newsgroup (no discussion or *** *** crossposting allowed) for Commodore 8-bits *** *** *** *** For information on comp.binaries.cbm visit *** *** http://www.concentric.net/~cdkaiser/cbc/ *** *** *** *** This file is also available via FTP from *** *** ftp://videocam.net.au/cbm/incoming *** *** (allow time for submission to be received) *** ######## ################## ###### ###### ##### ##### #### #### ## ##### #### #### #### #### #### ##### ##### ## ## #### ## ## ## ### ## #### ## ## ## ##### ######## ## ## ## ##### ## ## ## ## ## ##### ## ## ######## ## ## ## ### ## ## #### ## ## ##### #### #### #### #### ##### #### #### #### #### #### ###### ##### ## ###### ###### Issue #17 ################## November 15, 1998 ######## [ I've declined to publish the entire issue in comp.binaries.cbm because the large portion of it is non-binary. The pertinent article, however, is enclosed, along with the binary portion. The full issue of Commodore Hacking 17, along with the other issues, is available from the official site at http://stratus.esam.nwu.edu/~judd/fridge/chacking/ -- Cameron Kaiser ] NTSC-PAL fixing, part 1 =============== Russel Reed , Robin Harbron , S. Judd Introduction ============ Just about everyone knows that there are differences between NTSC and PAL machines. Most people are also familiar with at least a few of the technical issues, such as extra raster lines, and know that these differences can cause certain types of programs to fail, in particular games and demos. But how does one actually go about fixing one of these programs? It is that with which this series of articles is concerned. "Fixing" has been a job which a number of 64 hackers have taken on, in order to enjoy programs written in another country. Some of the major game companies imported software from other countries and sometimes had to reprogram the software so it would run correctly. Fixing is not always a simple task, but there are some techniques and strategies which are useful in most cases. There are only a few different classes of problems overall. We decided to approach this problem in a novel way: a pair of yay-hoos (Robin and Steve) would place themselves under the tutelage of an experienced fixer (Russ, a.k.a. Decomp/Style), fix up a program, and write up the results and experiences. The first step was deciding on which program (or programs) to fix. It had to first of all be fixable! Since time is always in short supply it couldn't be a big, complicated project. And finally, since we were just getting our fixing feet wet, the actual fixing job needed to be fairly straightforward (so the big custom track-loading demo will have to wait for a future article). But demos are the natural fixing candidate, and after viewing several different ones, and examining the code to see what would need fixing, we finally decided on the demo "Slow Ideas", written by a couple of crazy Finns way back in 1989. It's a cool demo, was challenging and fun to fix, and turned out to be pedagogically a good choice. It's two pages, and each page had a number of effects in need of fixing. These pages, and the practical side of fixing, will be discussed in some detail below, but first we need to review the differences between PAL and NTSC, and discuss the implications of those differences, and how they manifest themselves in programs. NTSC/PAL Differences ==================== There is really just one primary difference between NTSC and PAL machines: the graphics, which means VIC. But since VIC generates the machine clock cycles, that means the computers run at different speeds. And since they run at different speeds, the CIA timers run at different speeds, the SIDs run at different speeds, and the CPUs run at different speeds. So just having a slightly different graphics format affects nearly every aspect of the machine's operation. VIC and graphics ---------------- The PAL television standard is different from the NTSC standard. The primary difference is actually the way color is encoded, but the main issue for the 64 is the frame rate, the number of raster lines, and the number of cycles per raster line: VIC chip Frame Rate Raster lines Cycles per line 6567R56A (NTSC): 60Hz 262 64 6567R8+ (NTSC): 60Hz 263 65 6569 (PAL) : 50Hz 312 63 As the video raster beam sweeps across the television tube, VIC tells it what to display, one pixel at a time. The CPU clock is exactly 1/8th of the "pixel clock", so that one CPU cycle corresponds to eight pixels on the screen. Thus, it is clear from the above table that a PAL machine has 63*8 = 504 pixels per raster line. 320 of those pixels comprise the visible display, while the other 184 make up the left and right borders. What is important here are the three numbers in the table, though. First consider the number of cycles per line. If a program is exactly synchronized with the raster, then it can make precise changes to the screen merely by letting a certain number of cycles elapse. A simple example is making raster bars; a more involved example is opening the side borders, or generating an FLI display (which you can read about in previous issues of C=Hacking). Needless to say, programs which require exact cycle timings will fail when run on a machine with a different number of cycles per line. (Note that on older computers, like the old Atari 2600, the CPU actually built the screen display, and so _all_ the screen code had to be exactly timed). Next observe the different number of raster lines. The visible display begins on raster line 50, and there are 200 visible raster lines (320x200, you know). That leaves 13 raster lines for the NTSC border, but 62 raster lines for the PAL border. This causes two problems. Code which waits for a raster line greater than 263 will have problems on an NTSC machine. A busy loop such as LDA #$10 ;Wait for line 266 CMP $D012 BNE *-5 LDA $D011 BPL *-12 will never exit, while a raster IRQ will never occur. The code must be adjusted to use a different raster line or another method of timing. Sprite graphics on lines greater than 263 will wrap around on an NTSC screen and in some cases the image will be displayed twice. The sprites must either be moved or their images truncated to correct this. Moreover, the extra raster lines mean extra cycles per PAL frame. Using the table above, an NTSC machine has 263*65 = 17095 cycles per frame, and a PAL machine has 312*63 = 19656 cycles per frame. In many demos and games those extra 2500 cycles are used to perform needed calculations and operations before the next frame begins, which leads to all kinds of trouble on an NTSC machine. Note that NTSC machines have more cycles available in the _visible_ display, while PAL machines have many more cycles available in the borders. Finally, consider the frame rate. On an NTSC machine, there are 17095 cycles per frame, and 60 frames per second, giving 17095*60 = 1025700 cycles per second, or 1.02 MHz. On a PAL machine, there are 19656*50 = 982800 cycles per second, or 0.98 MHz. So although a PAL machine has more cycles per frame, the CPU runs slightly slower than on an NTSC machine. Thus a game like Elite, which involves raw computation, runs a little faster on an NTSC machine. But for most games and demos it is the cycles per frame which is important -- as long as all game calculations can get done before the next frame, the game can run at the full frame rate. Also note that most tunes are synced to the screen, so when a PAL tune, designed to play at 50 calls per second, is suddenly called 60 times each second, it will play noticeably faster. By the way, there actually aren't _exactly_ 50 or 60 frames per second. The frames per second is actually determined by the machine clock rate, not the other way around! The actual system clock rates are 14318181 / 14 = 1022727Hz for NTSC and 17734472 / 18 = 985248Hz for PAL. Dividing by 17095 (PAL=19656) cycles per frame gives 59.826 frames/second NTSC and 50.124 fps PAL. The important thing to remember here is that PAL machines run slightly slower than NTSC machines, but have many more cycles per video frame. Just as a side node, the above calculation should indicate to you that although the AC electricity lines are 60Hz in the US and 50Hz in Europe, that has nothing to do with the 50/60Hz PAL/NTSC frame rates. Not only can an NTSC monitor easily display a 50Hz signal (let alone 59.826Hz), but the actual power frequency fluctuates around that 50/60Hz anyways, so that the AC line frequency is only 50/60Hz on _average_ -- good enough to run a clock, but not nearly precise enough to generate a video signal. Also note that there are two different NTSC VIC chips in the table. The 64 cycles/line VIC was present in the earliest 64s shipped. This is actually a bug in the chip, though, and 65 cycles/line is the "correct", not to mention most common, NTSC VIC chip, and the one which we will refer to in this article. Oh? You don't believe me? Well, from the March 1985 IEEE Spectrum article: In addition to the difficuly with the ROM [sparklies], "I made a logic error," Charpentier recalled. The error, which was corrected sometime after Charpentier left Commodore, caused the early C-64s to generate the wrong number of clock cycles on each horizontal video line. "It was off by one," he said. "Instead of 65 cycles per line, I had 64." As a result, the 180-degree phase shift between the black-and-white and color information, which would have eliminated color transition problems, didn't occur. Depending on their color and the color of the background, the edges of some objects on the screen would appear slightly out of line... There ya go! Machine cycles -------------- The tiny CPU speed difference has a number of important ramifications. It means that the CIA timers on a PAL machine run slightly slower than on an NTSC machine, so timer values may have to be recalibrated; note that the system CIA interrupt has a different setting for PAL and NTSC. Moreover, a disk drive runs at exactly 1MHz -- there are no "PAL disk drives" -- which means cycle-exact fastloaders will not synchronize correctly on different-speed machines. And finally, it means that SID works differently. Not only will the tempo of any interrupt-based tune (raster _or_ CIA) change, but the actual pitch will change as well. SID generates its waveforms by simply updating an internal counter every cycle, so an NTSC SID is essentially playing a digital sample at 1.02 MHz. When that sample is played at 0.98 MHz, it's like slowing a record player down a little -- the pitch decreases. To be specific, the _absolute_ pitch changes, but the _relative_ pitch between notes does not; the tune plays the same, but the pitches are all a little over a quarter-step lower. Practically speaking, this is totally irrelevant to fixing. Only the tune speed is of significant interest. Fixing the Problems =================== The previous section described different classes of problems which can occur from the different cycles per line, lines per frame, cycles per frame, and cycles per second. These problems include screen syncs, bad interrupts and infinite busy-loops, too many cycles per frame, mis-timed timers and fastloaders, and different music tempos. Fixing tunes is easy. For programs in which the interrupt frequency is otherwise unimportant, the interrupt timer source can be adjusted to the correct frequency. In other cases, if the interrupt frequency cannot be changed, the music speed may be adjusted by calling the play routine twice on every sixth interrupt or not calling it on the sixth interrupt. If perfection is needed, the music data might be adjusted or the music routine rewritten to work at the different frequency. Much of the time none of these are necessary, as the music sounds fine at the different speed anyway. Next consider too many cycles per frame. In order to fix this class of problems, we must improve the efficiency of the code. There are three cases here. Sometimes busy waits are used to synchronize the code with a raster line on the screen. This wastes cycles and imposes some restrictions which result in additional wasted cycles. These busy waits may sometimes be replaced by raster interrupts which make better use of the available cycles. At other times, programmers will set up all graphic updates so that the code executes in the vertical borders. NTSC machines have a big disadvantage here, as we've seen earlier. Usually this code can be rearranged to take advantage of the available cycles during the screen display. This can be tricky, as you don't want to be updating the screen at the same time it is being displayed, but by splitting updates up it can usually be pulled off. Finally there are some cases in which neither of these techniques is of use. For a perfect fix, the code must be optimized, often by sacrificing memory. If it can't be optimized, then something has to go; effects can be truncated or updates slowed down so that less is updated each frame. Next consider the different cycles per raster line. In most cases, this difference is not significant. The routines for which it is significant are raster routines, where synchronization with the video chip is established by using exactly the right number of processor cycles. FLI, VSP, and color bars are all affected by this. Color bars will have flicker and look crooked; VSP effects will often be shifted the wrong amount; FLI routines usually either repeat the top row of graphics all the way down the screen or else don't display at all. These problems can all be corrected by adding or subtracting the correct number of cycles per raster line. In most cases, this class of problem is actually the easiest to fix. There are several approaches to putting the right number of cycles in for the fix. If the source is available, inserting a NOP instruction may be all that is required for an NTSC fix. Without the source, a modified routine may be inserted into some empty memory and the original routine bypassed. Sometimes the code may be shuffled around enough to insert a NOP with a machine language monitor. You can sometimes change the opcodes used to use a different number of cycles. Consider the delays that can be added with just two bytes: CMP #$EA ;2 cycles BIT $EA ;3 cycles NOP NOP ;4 cycles INC $EA ;5 cycles CMP ($EA,X) ;6 cycles This gives lots of room to work with, assuming the flags aren't important. If .X or .Y is unused, then STA $1234 can be changed to STA $1234,X or STA $1234,Y to gain an extra cycle (if .Y=0). If .Y is known to contain a fixed value like $FF, the target can be adjusted so that STA $1234 becomes STA $1135,Y. Usually in an FLI routine, you'll see STA $D018, STA $D011, and STA $D016 together. Two of these can be replaced with indexed opcodes to add the two extra cycles needed for an NTSC fix. Also note that when sprites are active, a different amount of cycles may get stolen depending on which instruction is executing when the sprite data is read. C=Hacking #3 discusses this in detail, and explains how it may be used to synchronize code with the raster beam. >From a fixing standpoint, it means that you don't always want to add two instruction cycles to convert a piece of PAL code to NTSC; sometimes, as in the demo below, only _one_ cycle must be added to fix certain routines, with the other cycle being eaten by VIC. Sprites have a few differences between PAL and NTSC as well; like the other differences they are not evident in many programs. The horizontal sprite positions start at zero on the left side of the screen and increase as you move to the right. At some point past position 300, the positions wrap back around to the left side of the screen. For these high horizontal positions, the sprites are 8 pixels farther right on a PAL screen than they would be on an NTSC screen. When these high positions are used to create sprites that extend all the way to the left edge of the visible screen, problems show up. A PAL routine will have an eight pixel wide gap in the sprites on an NTSC machine while an NTSC routine will have eight pixels of overlap on a PAL machine. Often these positions are stored in a table or loaded into a register with immediate addressing. In this case it is trivial to adjust the value by eight in the appropriate direction. The vertical sprite registers present similar behavior, which is seen even less often. As was stated earlier, the 65xx processors in the 64 and 1541 run at close to the same frequency, but the ratio of the 64's processor frequency to the 1541's processor frequency is not exactly 1.0, and the ratio is different on PAL and NTSC systems. This means that although the 6510 in the 64 and the 6502 in the 1541 may be synchronized at the start of a section of code, after executing the same number of cycles they will no longer be synchronized. Cycles may be added or subtracted on either processor to bring them back into sync, but this adjustment varies depending on either a PAL or NTSC system. This is most often seen in fastloaders, where the code depends on the two processors being in sync in order to transmit 8 bits one at a time or four pairs of two bits without the need for handshaking. As with raster routines, a few cycles need to be added or subtracted for a fix. Finding the right place to insert or remove these cycles can be challenging. Instead of trying to remove cycles from the 64 routine, which may be impossible, you can instead e.g. add cycles to the complementary drive routine. Finally, understanding what problems may arise and what should be done to correct them is only part of the skillset needed by a good fixer. In the best case, you'll be working with source code which you've written and understand. In other cases, someone else may have written the code, in which case you must study and understand it before you can start trying to fix any NTSC/PAL problems. Often the source code isn't even available, leaving you to work in a machine language monitor. This imposes some new restraints. In a monitor, it can be difficult to shift blocks of code around. Several techniques are available to work around this. Code can easily be left out by replacing it with NOP instructions or inserting JMPs to branch around sections which aren't needed. Extra code can be patched in with a JMP instruction to the new code and another JMP instruction at its end to return to the old routines. Where cycles need to be added, opcodes may be changed; for example, a LDA $ABCD might be replaced with LDA $ABCD,Y to add an extra cycle. Finally, you may simply have to resort to a symbolic disassembly (i.e. disassemble into source code). This may become an absolute necessity in some cases. Then there are the cases where the object code isn't even readily accessible. Some of the same skills used by crackers to remove copy protection are valuable. Most commonly, games, tools, and demos will be compressed to make the files shorter, adding a single BASIC SYS command line as well. These routines rarely try to be deceptive and are fairly short, so they can be undone, often just by modifying the existing decompression code a bit. It is common practice to have a sequence cruncher on top of an RLE (or equal-byte) packer or linker. Within the "scene", there will be intros to wade past, while commercial software will often have disk or tape copy protection and purposefully obtuse code. Just remember that fixing is often about creativity and diligence. There is a common set of problems encountered and many creative solutions to correct them. With practice, it becomes easier, just like anything else. You'll have an easier time of it if you pick your battles carefully. Remember that some problems just can't be fixed perfectly. If you get stuck, try a different challenge and perhaps come back to the problem later. And most of all, remember to have some fun! With all this in mind, let's have a look at that demo! Slow Ideas, page 1 ---------- Reconnaisance: Page 1 is divided into basically three parts. The upper part of the screen contains a stretching sprite tech-tech extending into the borders, overlayed on top of raster bars. Then the rest of the screen features a large Pu-239 picture/logo. Finally, a bouncing sprite scroll takes place in the lower portion of the screen, extending into the lower (but not side) borders. The screen is built using two interrupt routines, one located at $1240 and the other located at $1280. The $1240 routine is short and occurs at the bottom of the screen (raster $F8 or so). It removes the upper/lower borders, performs some calculations, and calls the music. The $1280 routine basically controlls the screen, and occurs at raster line $xx, at the top of the screen. It generates the tech-tech sideborder display, and performs most of the calculations. Both routines are vectored through $0314, not $FFFE. Fortunately, there is a lot of distance between different routines, that is, there is a lot of empty memory between routines -- probably it was coded in an ML monitor. This means that adding patches, or shifting routines around, is much easier. What a forward-thinking guy that Pasi was, to realize that it would need to be fixed by C=Hacking one day. When run, the demo is a mess. The most prominent defects are that the music plays very slowly, the screen flashes, with the main picture flickering between the top of the screen and the lower portion of the screen, the side borders are not open in the tech-tech, and sometimes the scrolling sprites are off the screen. Too many cycles: The half-speed music and flickering screen indicates that interrupts are getting skipped, which points a finger straight at too many cycles -- if the next interrupt is set *after* it is supposed to occur, then a whole frame will of course pass by before it actually occurs. The first question is, where are the cycles getting eaten? That is, of the two interrupt routines, which is using too many cycles. The answer is immediately obvious: any interrupts that take place totally on the screen have *extra* cycles available -- 2 cycles per raster line. The loss of cycles comes in the lower border, which means the $1240 interrupt: jsr tune jsr blah1 jsr blah2 LDA $D012 CMP #$1E BCC *-7 First note that curious $D012 code. It surely is meant to compare with line $011E, not line $1E. Line $011E doesn't ever occur on an NTSC machine, though, so it actually waits until line $1E, well past the $1280 interrupt. So the first order of business is to BIT that BCC out of existence. Alas, this still does not fix up the flickering. The next step is to BIT ($2C) out the JSR tune call, to see if the problem really is cycles. And sure enough, ditching the tune gives a suddenly stable, or at least mostly stable, screen. BITting out the other two subroutines, but keeping the music, gives an unstable screen; the tune simply has to go somewhere else. Finding extra cycles takes a bit of work; for now, it is enough to $2C-BIT out the JSR TUNE and focus on the other problems. Tech-tech: Let's have a look at the tech-tech routine: $1280 LDA #$96 STA $DD00 LDY #$FF BIT $EA NOP NOP LDX #$09 DEX BNE *-3 $1290 LDX #$5F $1292 LDA $1000,X STA $D018 DEC $D016 ;Open border STA $D021 INC $D016 LDA $1060,X $12A4 STA $D017 STY $D017 LDA $1100,X STA $D011 DEX $12B1 LDA $1000,X STA $D018 DEC $D016 ;Open border STA $D021 INC $D016 LDA $1060,X STA $D017 STY $D017 $12C9 BIT $EA NOP DEX BPL $1292 The routine has three parts: the initial delay at $1280, and a two-part loop, the first part at $1292 and the second at $12B1. The difference between the two is the LDA $1100,X STA $D011 at $12AA; without two parts to the loop, the branch would take too many cycles. Each part will need fixing, since each part uses at least one raster. Opening the side borders requires exact timing, yet the above routine is entered through $0314, which will always have some cycle variance. The trick here is that all eight sprites are active; Pasi himself wrote a nice article in C=Hacking #3 on using sprites to synchronize the raster. The basic idea is to get the CPU to wait on a specific instruction; VIC then frees up the bus on a specific cycle, and you know exactly where you are on the raster line. First to fix is the initial line delay. Since there are +2 extra NTSC cycles per raster line, it seems reasonable to first try adding +2 cycles to the delay: 1287 BIT $EA to AND ($00),Y ;+2 cycles NOP NOP NOP NOP Really, CMP ($EA),Y is in general a better choice since it doesn't affect .A, but it doesn't matter here and we were young and naive, besides. If the above +2 cycles aren't enough, it will be clear soon enough (but it turns out they are enough). Next up is the borders. Although the immediate impulse is to add +2 cycles per raster line -- +2 cycles to both loop parts -- it's not obvious where the raster sync is taking place, and +2 cycles might cause the sync to fail. In fact, what's needed is just +1 cycle per part: 12A4 STA $D017 to STA $CF18,Y ;+1 cycle 12C9 BIT $EA to INC $00EA ;+1 cycle NOP The $12A4 fix uses the fact that .Y=$FF. A NOP NOP NOP would have done the trick at $12C9 and be safer, but we used INC in our reckless youth. And suddenly -- poof! The borders open up and the screen stops flickering. Why should the screen flicker at all? Remember that the loop is split in two because of an STA $D011 instruction. This STA pushes badlines off, so that the timing stays precise; since badlines never occur, the graphics data is never fetched. It's only after the rasterbars that VIC starts fetching graphics data; without the $D011 push, this data will appear on the first visible rasterline (hence the earlier flicker with too many cycles). When an imperfect (from incorrect cycle timing) push takes place, the picture can get the jitters. So now we know why the demo behaved as it did, earlier. Sprite scroll: And yet... the screen still flickers, when sprites bounce down too low. Clearly the sprites are eating into the cycles needed by the lower border routines. The simplest way to fix this is of course to change the y-coordinates of all the sprites. One option is to re-do all the coordinate tables. But a much easier option exists: figure out which code stores the sprite coordinates, and subtract a fixed amount from each of the y-coordinates. This routine just happens to be located at $1590, and the simple insertion of code 15AF STA $D001,Y to CLC ... SBC #$0E STA $D001,Y fixes things up just dandy. Still too many cycles: We still have the problem of what to do about the tune. Since there aren't enough cycles in the $1240 interrupt, they need to be found somewhere else, and the only somewhere else is the $1280 interrupt, during the logo display. The first thing to figure out is how many lines are needed, and how many lines are free. This is easy enough, by simply moving the JSR TUNE to the end of the $1280 routine, sandwiched between an INC $D020 and a DEC $D020. The border will then indicate the end of the $1280 interrupt as well as the size of the tune. The good news is that $1280 has a fair amount of extra cycles available. The bad news is that the music is fairly inefficient, and needs even more cycles. But not many more -- just a good 8-12 raster lines. $1280 is pretty large, so maybe by rewriting some code enough cycles can be gained to make it all work. Note that if $1280 only had a few raster lines to spare, this task would be much more difficult (if not impossible). Towards the end of the $1280 routine, there are a series of subroutine calls. One of them is a JSR $1E50. This code has two loops, one which copies values from a table at $1900 to a table at $1000, and one which ORAs a value into the $1000 table. Instead of copying and then ORAing, why not just combine the two loops? 1E50 LDY $1FC6 1E53 LDX #$5C 1E55 LDA $1900,Y 1E58 STA $1001,Y 1E5B DEY 1E5C DEX 1E5D BPL $1E55 LDY $1FC6 1E5F NOP 1E60 LDA $1FC1 1E63 STA $1E70 1E66 LDA $1FC2 1E69 STA $1E6F 1E6C LDX #$5F LDX #$5C 1E6E LDA $32B6 1E71 ORA $1000,X ORA $1900,Y 1E74 STA $1000,X STA $1001,X 1E77 INC $1E6F 1E7A BNE $1E8B 1E7C INC $1E70 1E7F LDA $1E70 1E82 CMP #$34 1E84 BNE $1E8B 1E86 LDA #$30 1E88 STA $1E70 1E8B DEX DEY 1E8C BPL $1E6E DEX 1E8E RTS BPL $1E6E 1E8F BRK RTS On the right are the patches we added, along with replacing the JSR $1E50 with JSR $1E5D. Instead of copying from $1900 to $1000 and then ORAing into $1000, it simply ORAs to $1900 and stores it in $1000 ($1001 actually, since that's where the first loop stored stuff). Sharp-eyed readers may have noticed that the patch affects $1001-$105D, whereas the second loop affected $1000-$105F; doesn't the patch above lose some bytes? Of course it does, what's your point? :). The ancient hacker technique applies here: try it, and if it works, don't touch it and don't ask questions! Better than a huge rewrite of self-modifying code. Wrapping up: With the above fix in place, and the tune moved to the $1280 interrupt, the demo finally seems to work great. All that remains is to save it and crunch. Figuring out which areas of memory are used is easy enough, by looking at the disassembler and the initialization code (which unpacks the code further). But after crunching -- uh oh, lockup. A program freeze shows that it is still running, but that the interrupts are not occuring. A glance at the setup code shows that $D012 is set, but $D011 is never set -- presumably the high bit is set, so the interrupt occurs on a nonexistant raster line. Adding a simple LDA #$1B STA $D011 to the initialization routine at $1443 fixes that up just fine, and the program decrunches successfully. Woo-hoo! One page down and one to go. Slow Ideas, page 2 ------------------ Reconaissance: Page 2 has essentially four visible parts: a tech-tech at the top of the screen, followed by a swinging FALSTAFF sprite on top of rasters and open borders, followed by the ubiquitous Pu-239 pic/logo, followed finally by a sprite scroll on top of rasters with open side and bottom borders. All this is done with two interrupts, one ($11FE) occuring at raster line $31, the other ($1350) occuring at line $D1. The $31 raster performs the tech-tech, the FALSTAFF rasters, and also performs some calculations for various sprite scroll effects. The $D1 raster handles the lower rasters and scrolling sprites, and also plays the music, scrolls the sprites, and does the calculations for the FALSTAFF sprite. When run, the screen is quite a jumble -- too many rasters -- and needless to say, the screen effects need retiming. The music really sounds better at 50Hz, so it needs to be retimed as well. Top to bottom: Before fixing the timing problems, the extra cycles need to be addressed. In the $D1 interrupt, after the lower rasters are displayed there are a series of subroutine calls at $13B3: $13B3 JSR $211C ;Tune JSR $0F80 ;Scroll sprites JSR $1300 ;Clear $7Fxx tables (used by JSR $0E00 ; in $31 interrupt) JSR $1D00 ;FALSTAFF sprite Deducing the function of each routine is easy enough -- just BIT it out and see what happens. BITting out the first three subroutines frees up enough cycles to make the screen stabilize. Finding cycles is usually more work than fixing up timing -- especially three subroutines worth! -- so it is enough to $2C-BIT out the three subroutine calls for now and fix up the timing first. Tech-tech: At the top of the screen is a normal tech-tech, controlled by the routine at $11FE. The code flows roughly as follows: $11FE Set up $D020/$D021, waste a few cycles to get timing right LDX #$08 $1214 LDA $xxxx,Y STA $D018 LDA $xxxx,Y STA $D016 INY DEX NOP NOP NOP Change VIC bank ($DD00) CPX #$00 BEQ $123F NOP NOP NOP ... CPY #$2F BCC $1214 JMP $125E The thing to recognize here is that there are two loops -- on every eighth line the BEQ $123F branch is taken. A simple cycle count shows that the first loop takes 63 cycles, and the BEQ branch adds an extra 20 cycles: obviously, these are simply timed for the normal and badlines. So all that is needed here is to add 2 cycles to each loop: I changed the CPX #$00 above to INX DEX for the first loop, and changed a NOP NOP to a CMP ($EA,X) in the $123F branch. With the raster timing correct, the next step is the initial timing at $11FE. By doing a little rearranging of code two bytes can be freed up, giving 2-6 cycles to fiddle with: $11FE LDY #$0B LDX #$0B LDA #$01 LDA #$01 STA $D019 STA $D019 LDX #$02 LDY #$02 $1207 DEX DEY BNE $1207 BNE $1207 STY $D020 STX $D020 STY $D021 STX $D021 LDY #$00 NOP NOP LDX #$08 LDX #$08 $1214 tech-tech loop As you can see, by using .Y in the delay loop instead of .X, the LDY #$00 instruction becomes redundant. As it turns out, just +2 cycles are needed. Finally, there is the matter of the last raster line. When the JMP $125E is taken, there is some delay before changing the border and background registers, to get a nice solid line. It turns out that four extra cycles are needed here, and fortunately there just happens to be several padding bytes before $125E. By changing the JMP $125E to a JMP $125C, two extra NOPs are easily inserted. That takes care of the tech-tech. Falstaff rasters: Immediately after the tech-tech are the rasters and open borders behind the FALSTAFF sprite. JSR $0EA0 handles this part. We already fixed a sideborder routine in the first page, and this one is similar: $0EA0 LDX #$05 ;Initial delay DEX BNE *-3 LDX #$15 CMP #$EA $0EA9 BIT $EA ;Change to NOP NOP for +1 cycle LDA $xxxx,X DEC $D016 STA $D021 INC $D016 STA $D020 LDA $xxxx,X STA $D011 NOP NOP NOP DEX BNE $0EA9 LDX #$02 ;Change to LDX #$03 for last line delay loop As before, +1 cycle needs to be added to the border loop, which is easy enough to do by changing the $0EA9 instruction. The end delay also needs a little change, to make the last line nice and solid (there are no sprites active on the last lines). Finally, the initial delay needs to be changed, to line up the routine correctly. I changed a CMP #$EA at $1277, just before the JSR $0EA0 call, to NOP NOP. As usual in this type of thing, it was easy to simply experiment with the initial timing until the borders opened up. Bottom rasters and sprite scroll: Finally, the bottom rasters need fixing up. Once again, the loop looks familiar: $135D LDY #$FF LDX #$55 CMP #$EA NOP NOP NOP $1366 LDA $7F02,X STA $CF18,Y ;Stretch if necessary STY $D017 LDA $1504,X STA $D011 LDA $1C32,X DEC $D016 ;Open border STA $D021 INC $D016 DEX BNE $1366 And once again, we need to add a cycle. As with page 1, .Y=$FF means that the STA $D011 can be changed to a $CF12,Y. Changing the CMP #$EA to EA EA adds the two cycles needed in the init to get everything aligned, and poof -- instant open borders (as long as all the sprites are being displayed correctly). When the scroll is activated, something else becomes apparent: as the sprites scroll into the left border, they "pop" to the left by several extra pixels, i.e. the screen coordinates change by too much. To fix the sprite popping, all that was needed was to add 8 to $0F00 (the sprite coordinate). Too many cycles: Alas, the moment we've been dreading has arrived. Where in the world do we find enough cycles for three subroutines? One option is to get rid of some effects -- for example, the sprite scroller has many time-consuming effects that can occur; by getting rid of those, the tune can be placed in the $31 raster. Working through the code doesn't reveal subroutines that can easily be rewritten. Still, it sure would be nice to get all the effects going; but where to get the cycles? A little thinking suggests something, though -- the PAL routine can't have THAT many extra cycles, simply because it doesn't get cycles until the raster routine is finished, at the bottom of the screen... oh duh. A glance at the raster routine shows that it covers $55 rasters. The interrupt takes place on line $D1, which means that the rasterbars extend all the way down to line $0127 = 294 or so, which is over 30 rasters past the last NTSC line. So suddenly there's a great big chunk of cycles, for free: (Orig PAL) (Fixes) $135D LDY #$FF LDX #$55 LDX #$35 ;Only $35 raster lines CMP #$EA NOP NOP ;+2 cycles NOP NOP NOP $1366 LDA $7F02,X LDA $7F22,X ;Add $20 to compensate for .X STA $CF18,Y STY $D017 LDA $1504,X LDA $1524,X ;Add $20 ... STA $D011 STA $CF12,X ;+1 cycle to open borders LDA $1C32,X LDA $1C52,X ;Fix probably not needed DEC $D016 ;Open border STA $D021 INC $D016 DEX BNE $1366 Note that the table offsets need to be increased; without that, the sprites start stretching all over the place and everything goes weird. With $35 raster lines instead of $55, the rasters go all the way down to the last NTSC lines, and free up just enough cycles for two of the $13B3 subroutines to be re-enabled: $13B3 JSR $211C ;Tune JSR $0F80 ;Scroll sprites BIT $1300 ;Clears $7Fxx tables (sprite scroll) JSR $1D00 ;FALSTAFF swing That pesky $1300 subroutine just pushes it over the edge, though: $1300 LDX #$2F LDA #$00 STA $7F01,X STA $7F2D,X DEX BNE *-9 It doesn't take *that* many cycles, so one option is to use even less than $35 rasters. But this makes the bottom part look awfully small, and obscures parts of the scroll. If you think about it for a moment, there are some free cycles still hanging around elsewhere in the code: in the tech-tech routine! There are lots of NOPs inside of the tech-tech loops; enough to piggy-back the $1300 routine into it without much effort: $11FE LDX #$0B LDX #$0B LDA #$01 LSR $D019 ;Still 6 cycles, -2 bytes STA $D019 LDY #$02 LDY #$02 DEY $1207 DEY BNE $1205 BNE $1207 STA $D020 STX $D020 STX $D021 STX $D021 LDX #$08 $1210 NOP NOP NOP NOP $1212 LDX #$08 LDA $1887,Y LDA $1887,Y STA $D018 STA $D018 LDA $1B87,Y LDA $1B87,Y STA $D016 STA $D016 INY INY ROL ;Replaces LSR LSR ... DEX ROL NOP ROL NOP AND #$03 NOP STA $DD00 LSR LDA #$00 LSR STA $7F01,Y LSR STA $7F2A,Y LSR DEX LSR BEQ $123F ;Every 8th raster LSR STA $DD00 INX DEX BEQ $123F Using LSR $D019 instead of LDA #$01 STA $D019 saves 2-bytes (6502 instructions like LSR use a "read-modify-write" cycle, and write #$FF to the register while LSR is working, which is why LSR $D019 clears $D019!) while still using 6 cycles. Replacing the LSR LSR ... stuff with the ROL code saves another byte. Moving the DEX down saves two more bytes, and getting rid of the NOPs saves three more, for a total of 8 bytes -- just enough for the LDA STA STA which replaces the JSR $1300 code. The new code uses two fewer cycles, however -- but by rearranging the initialization code we can just branch to a NOP at $1211 above. Every eighth raster the branch is made to $123F. This routine performs another INY, which has the effect of skipping every eighth entry in the $7Fxx tables. Thus extra STAs need to be added: $123F BIT $EA BIT $EA CMP ($EA,X) STA $7F02,Y NOP STA $7F2B,Y NOP ... The two STA xxxx,Y each take 5 cycles, so 10 cycles exactly replaces the 10 cycles used by CMP ($EA,X) NOP NOP. But since the STAs take two more bytes, the rest of the routine needs to be moved forwards; luckily, there are empty padding bytes immediately following the routine, so it moves forwards without a hitch... Well, maybe with one hitch. The whole tech-tech routine uses self-modifying code all over the place. The modifying instructions immediately follow the routine, and so need to be adjusted to the new locations. Finally, for some strange reason, the above fixes also affect the FALSTAFF rasters. Adding an extra +2 cycles to the intial FALSTAFF delay fixes that up, though. So much for extra cycles! The Tune: Finally, the tune really does sound better at 50Hz, so a 5/6 delay needs to be added. There is some free memory at $09xx which is ideal: $09E0 DEC $09FF BEQ *+3 JMP $211C ;Play tune LDA #$05 ;Skip tune every 6th frame STA $09FF RTS As the comments say, it simply skips every sixth frame of the tune, to give it an effective play rate of 50Hz. It works! Glitches: Unfortunately, there are still a few glitches in the fix. The bottom rasters have some flicker in the upper right (and occasionally upper- left) corners. Pretty minor stuff, but still annoying. Fixing means rewriting the raster loop. Much worse, though, is that the screen will glitch badly when certain sprite scroll effects are activated. This glitch seems to involve quite a lot of rasters, since even with the tune disabled glitches are still evident. One choice is to reduce the number of bottom rasters, but that doesn't look very good. Another is to eliminate effects, but that's no good. A third is to do a big code rewrite -- bleah. But the easiest is to just call it a 95% fix and say "good enough". Good enough. And there it is -- Our First Fix. Hope u lik3 1t, d00dZ! Next time, we'll have a look at some of the routines which weren't covered this time, such as fastload and FLI routines. Until then, have fun fixin! ....... .... .. . C=H #17 begin 644 slowideas-ntsc M`0@+".\`GC(P-C$```!X+##0Y@&B4[WP")W_`0DGS^DDZ/S]-W3I-]^)NJ8#A@0$H_UAG0"VQE MA\`/P&)M)PGCPIN1\?/CXG?OA&4_/R+Y-$\^M-A/)/?WXG`"!@X>/IB>?>GO MX)43(8#@"C]P&`/QF9FQTXQV!G;%7Q#YB/_G3C/&1\8ST[J$A$VD]^%-E-A- MXT*"%9-Z462:(>$>B/!-$R:<<"GA@>'PJ:`,//W MY5\)H!@*P7,-//7S]U64H__Y%2MSD5?Z.]9("=`8,&!"=?R,7X5>@2$!P)J'J"0Y34Y!TYKT%!3T5)G]!@+PG0>,6%.G7@,!G(F\0>GQ,$!#IZ&R M>])HMDA9EP@33HP<$]]U3DM2P"`P&`P",!(SX0=_P!`<@9\?`0,>```IBQ/CHB(A6/@Q,2$@<)TF MRLWD3=5DW)N2R^$%7GYK,X%LK(WDZ?C\/`TZ0Z++H^/#`3P`0=9>'AP8:PX% M9#)TI$):>"-9/0!6#N/OZ$ MZ!Q\^>%ET+4]/Q`VGI`'ZE?TWC38_OY4?((DP?4,XZN1G2I2@0*$2R:'!7/" MP`%>\5[ZAUK#KF+L?5Y7'J0E)4_^[`#7A'9V9F9V=CX]KQ MLQV9]-RU95O(<#@Y7C;A:Q['_30KRN%TX5N=TP0&M,$`/K).W$JZ,5H0M(]H MH'(*>JHA^N&TPK5PNR/]H2LR6T%1R\LDM/ZNZ#/@!_Z M]>$`KWNQ&G!^/UE7&.ZS)(>6'JE9!T)+8V?EEO+9.40: MWDKO6ZCB.6V$MC=A^?V=VY3+1HX61;MRA`]@`KLMMY2%KRLH*?VMBS4_<9%: M[BZAI`UI=:LK&H!W5[[,@%'`_K+F+599+BW$+:V."EI=P,K+;F8%B MEN'131>*3-CHMLI;$P?H063$MK=1&_/"ZQ!UQ;AL'[,#MR:J==$.Y/]QJ2^& M"O0/!*\LA`KRN[I,!!7D8"%QHX!JV_B,#!CQL>E<4];ELGS&_8#Y<:T1\!/Z MXPP:'C+8D'<-B,&!BML^&*W-@.*X/V!^!ORL!JX#+G.%6\0'8L_"FU M3.L;C'C8T9#UQQF9FQVL`S=ORJX,*ZM/E;SX&/8L*2E++S9F?,QZXIF<8-:V M/`9\:>U,13_W0!\28^0CH'>H00)X14_W<`CI$X1 M7U!M-?A7.%MT1`(!$0YK#&N>&,S;#Y`P4)$[]9:F*0M9`.9F8T77FL-C;S-F M:Q%-C9CL##8XKJ$(!)R$_95&LDA+R`OZNB"Y?L!"@=72P0H+"@]2`0H%"@E2 M"0H-4F4*)$$(%U)1"B=`!]#\!/R$F)P(/#6(,8PL$"P0J!2DFJ">GJ"=XAGD M5&A0;=`NSS/)]\LVPM#@$N#"EC^"\?WV&?87^8_`S'Y_X_`__'.\?[R'+_+] M$_P4&Q0;]1KV"2>H!VCG-]J-%0.I,8T4`W'B,:C/-G<-QHBS["(T69]BK.Y MGV`QHSH+%$/WO`(SH`"90A[IC/INFG@@212B`+T`5&=6!T:'OW6PCW7(C6L_ M!`SK=>K?H5,M&@&[0 M?YB`=751!.5H?M$OL51!R?V<+:$:0Z'1XQ-'Z($<6=3+N*.I86C#S*!B(P[T!-P?$"ZS]`!-AR)-G=A# M^@']V"/UK/W)--`%J3"-9[]V,S]RF=(16E(FD@,:S[KF>;(H6C98_&YX_0`]R0#0P\E`T4O\RCWB!#QK3!'BVYP^C MQC4>[`GW43_>P`VI!Q%\.3L`CZ@$?0`"H]!U'HCZ@$?0`#(+-^BH+T_&IW_U MT[[)T_V;W?1YS^PL//?V4#?&NJMH@:M0I%)_47(`,SO!L3H1LSI@C]2>&?L` MS]J&:0AT/N?ZQAG18!!H#U8PVHLAU\,.:+0! M`#3;RC""N$2!3%$P`$I;,,$PZ9B2B8^#\?Q`$`?W[]_7Q[>OGY>'?V]G5T\_ M-RUL:^MJZFEHZ&?G9N9EY>5DY&/CXV+BXF)AX>%#_C[?8,CNAT MPY8<.-#;R,G*AHYF;G9^AHZ6IJZVOL;6WN;N_P?K[?' MU]_O\`24?$16I-8HT2%9D'5H\:]T._0`^Z'?D@$CM(!`5,(%N3_Z`-)C]3"` M52"E@2I7_5-!2/Q+N6/J.Y/J4@$$#1QVYX_,H^;`K&&T'&E'NFHJ,-,!,B`U M6YB.@8&EB]^:LWO4N[6YR.LH4NOC*GZB!XH*J+U1>](78`:/L$"BX0T)D`T( M3_O$:]S`"B.X.I/^9`="]1:3OP#WJ+2=)]#*$,Q0="^A&CFA'#N@P)_-)?J\ MP,3(S-#2UMK>XN;H[/#T]OK_YM\AH>)BHR.CY&2E)66F)F;G)V>H*&BHZ2EI MZBIJJNKK*VNK^WDL;*RL[.TM+6U[ON[Z_6_KNYT6E).2D9".C8R+BHB'AH6$@H&`?WY\>WIY> M'=U='-R<7!O;FUL:VII:&=F961C8F'MYU]>75U<6UI:65E85U=65E555.?ZG MS_4N?_>OE%0^W_]/#N_*7C?\;/-15YGJW,I8Y_\PN7WFV#G_RS7EY?7^5+#S M_8F)CY_LG/]EY_LW/_N_,_>OFAI^W_]/#QS>-_QL\U.9[%\&OPU'1P;&AGS>E\[R0\.#0T,"^WE">W;MX^WB[?`O;7=QWUX]W';7.3G!S<\ M\#>%!88&AP<'B`B)"@J+"XP,C8X.CQ`0D9(2DY05%9:7F!D9FIN<'1X?'Z"A MHJ,D)28G*"BIJJNLK?B]]?O/[]'[\/S\7SX@/M]^/P#^7]]/WX/'IB[Q@"^7 MX!?;^^G[Z_/7UW[>('^KV^V%]K/Z?OTEOQ0WV=?DR?9:[Z:]''Y"4%_%]]P% M\_@L,\?O/SN;#_'[S\[G/WGYW/*#^P,\?H.`^OWNY^ M7MZZ_7(%?#9^&?XQ_\1(>J'UF0[ MWT[WXN_>ZW\_+]?Y[F>_E_-,_#]A9W['SW,]_>N:9^'[RSLWA;&?A^^O_._> M>>?A,?W%L9^'Y67\[\NYY^'=R;&?A^]\\3/7+<6QGY?OC>%L9^7[YWA'&?Q< M@0'FH("Y^F@P/G>P2%9L9J%AF:AH<'YZH@(Y\Z)">SGAT;`UIG=(!X@'R$BT MSM$Q.4%)`5%986D!<7F!B98V"`S-#4@-M6P%FYN&:-C%@'G!N7V#/586)C9&5F9VAI:FO.5LH&W-<;#'EZ>WQ M]?G\Z@('.6"@X35L0L-#Q&RV(F*;GZ.GJZ^SM[N]?`6":^'CY>9`OA-CT]?;W7%L?"?Q<_-`#T0=<_`^,-N M`/J<9:=`-"I&)T!T,K*J0V9)]"($.2B_U.-(.Z$HE^M4"C`9,YLX"(=Q/(SI$F.WY+T4K,,?J?^ M9)O97@&3!$I,&*CN)U)EH/1K"(&/U@`([;)N!%R`"!13X$2Q"9)\9!,7Q8"_ M4H@`8?L!!?L$G[A$_8`G[`D_8(GZ@$_4$GZA$_0`GZ`D_0(G[@(!-PG[A$_8 M`G[`D_8(GZ6\!-PGZA$_0`GZ`D_0)`Z"?_`4?Z%@22-[2*!.D_2?2"3Z04P*@^0`#K]B-#TZNISLX40^R MYBJ`'F?@_&&FD!B!#W9]!%56T3PP6?62R8XTS@=D'`F?B`FR`=I:<,R($#-@ M$^/9!=[WK2`KS(/\_H@>IH)T0&D.`U.A`UE"'DJ@A@P22&!XD*@`_@!3P^@? M_HL__P/__X4?K\^?CX/PFG@FG!"KH0.=%)A_#_ MS^#^C#31#Q^(_?!8?2/11W/ZV'US(`H//\`>(\T$/P@;_$?7XCT_D=W\>)H\ MIIYK#Z4>B.Y5]/*L]/Y8;GXCN^%AE0"NQ<`17IB=B@(0YIV)BJ)`?Q5]`:KZ M3I5T(B``'3L4;(`?IV4JTZEE@`Z\K``%P7J$T/@%7T#H_1]8>]`#\_\/\?\? M\/\_\"C]?D-9\C]'D?H-^J% MKQ0%(U4!Z%G^CU)+KRMD_/`.$97@C$>$7QXBX'\!5]*/15 MW#BKB5;B-91H*LI&(&#*8=IC^F?R9V)F2F3ZP\?=,YDS<20`"YP%9,*Q>CG[ MOG/[?/?R?>_P__G@_^/A_X?`@1Q`:)\'^$2RD\T;::0*: M")!1%(^@.H6L0#\M8B5<1_^B_S_`?A_@_`_Q_@?X_P/P?X?@/\T5JM#,`!61 MF_+#*1B;#FCJ0H?"/K\.?]%"C]4?2/3^1W?RP[OA'=P'"8X)G`L/I1Z#B8N; MN)`#\5IHL8%>`A__`Q1^O&?\/$?\?@/^?Q.^?[DC]\#Q_^4?OW.'__/(_=8? M_^,/_\-&F`HQTZ`T3'@B2_'-5#?XXFBCZ/?W\>/CX3OM3#!,/U<-/`@,^ M%C&*&)@L/T>?T82F0937Z'J&50!ID:IB>6,3:L\A^ M!^%'ZLZU5G62LZO5=6*U7Q;U,GBU$"E3X1./E&#^H_7S\/WY'Z?/R)5'Z/GZ M)*__`^?15[_P#YZ*OO\`-15^_``\>`H_0#!0=(O<`\`>!%=@(OX!_@0`_PD/ M7(A4R$)<@AA)$Q).5QX`)_``1_@`@_P!`?X"`/\"`'\#`#X(@>!&(D@$R?IO&"+,:GX\3OS\C[/#S_/! MC_&!G_F%\;<`<&`P&/!X/(\C]X_QXQ_XQ?/Q@`:/E.``\<6+W/ M"K]5]X+XHM^.<1^ABKZX4>G!X*TQ^`!6V:S8Q=[0K&8]7C$*/V933#33G5?3 M_A_RM:X'\'P#X!D0,`KI[^%A^O"Y:9D_D`I7C:AZ8/+!2.%5TJO?!>-^K(T? M%AK(T%64C$`U&"!X``@P6&\X+9Z/%XWZLL!0K>"K01E*H4^3[`.#@`''3.Y5 M,`ZLZ%7ZJC$=R.A5Q)]E4GW'RP_1Q5^@*,99?JR\5IRI]42G\HN%23Q<9+?R M?G*D9;?J?J1J?TRY9C6A;-[PNDJ587+W.E7G4JP`5RL<".3`#P'P#@/P'@)3 MELG"\[]1AO`<@(1=+CKT9%>%*.*GL#6>:J>+Y#]6.%NB`?U8L*GV!15`"P_6 M#P`^'@`<-><;F`/@/"(#X6'[X!2,962H M5JWP`RC9`4":L:$`_\`!*QQ0U;2`"P_5>"C)7-^CRC#`5KA+*2`2IKI`63SIR4 M)'"F'8&,"S?_=3#'[B8!]<2]?+U?O];U42"Q>6[#Z2MD)[E^T]+I2`\#3H`+ M719`F\'[9F)IOWB@`RZ8%AZ@*?MK5.+P?MDZZ:ML6*;AQ673]#+9Z4`[H`8` M#7Y5X84AR^YUHM^FP!ZL#KKF;(-8,7C@RNIC7BX;K5CX7&4E\N&&/W$!@>XZ M!`#X*=?D7AQ`+Y'C7S(EZK&^%,0%\ANN2N!U@'>.,#_\+K%ZP\`'9LDQ[UQA MN5W/&]9Q"$`X4_I!@JX%"P0.?V`8:!!S^ZX!#G]QW_C?WKF];W-CUIAXV^+_\B_]YL>M+F9S(\8,!_WJ`\?\AS_[=.YY M.Y[^[]H=WT]^3KZY_6_XV/&ES-\9'C"Y`=SSJ"AW/!W.?=O=X=^1ZY^[?&QX MTN9OC([GM_[Y`>('Q">(?]$7ZE_$WR=\4'*/Q2^JG]%KXN?%YZO__>L#_OX` M>,!P]7OJ[]?_>?!WGGWJ]\.'?R'X,[O5^5C\J7X37PD/A#%A<8&1H;>^WF0$ M)#14=(2DOWT'WGH/_/=IJWV_U7\/:7):4D(Z*AH2`?'AT<&QH9&!<6%).2D9 M"/CHV,BXJ*"0@'AH9Y[4D'!@4$`^W'OAGGJ!@@+YZ5T)"@P-#Q#SVKPN,C8Z M/D)&2DY25_]\@(*FP.F!OX%$PP/%R`)9>@(F6$`@`LP"`Q;S:0##P0)#@%LM0(/9FD)"VH" M'`A`)`H:S^<4I"]IX/9!DP@*EID9G),0!H"P+9!L[&%XDS#=9P2\KEF6P:!6 M?+*$!%'7"S(`P%ETR5#R`#8!MN`RQB`A44>#(%ASLQF4H:0,]R`'9!LD&(9` M\S>;>AP>!H:S4HWQE#7ECTK&"`*,`(&*!@RP[=>`N"O(19?.#T%!A1U=,T`T M/+15FSJ8N/$174L\&YER\NP4"6VV2XD,N2W<;/@.`0QQU-MA[ET""#%&&LF&4`FXD6>#S`X-9I51.]I(GHF\7'Y*AR+(0'B#S M:UA\%L]WBPSLFBQ]QF`D`<"O,3BYQE/9B#!EUFAP6\P]=K4,O,#75X\,@4#W MF'+HK=:H.ZN'74Q,8G.QX90/-H'0.$./,H>9+!H"Y?AP"N'AX?!:\4A=;SS- M-X:C"49%V;#;T%+&P3<)H2\I4"=QT"(JYC]=?3E3`QC(R^I\L^6!KE505U3A[IY?`&/!!!'4JVKS;9F&Z=QEF6WHWJX7"VK\>* MH%&'K!XZD60("".-MTFO%>GO/\]S/$WE+MZL'X\3?"U3VU2]Y4[EI@=B@\8G MC(V+C$R9^G)P\UKVP'O-67.8<`AG"]+(7=$KAB< MS9.V8`64KH[K79#,%@$29`O-/`%Q5@H6[$-AZR_!!42=A2ZGGG.6\M1YARZ+ MGRC@`N$]ZS>/>"!V%#+NE,3$K?"P;BX<4@&>FQHR.*`(9>Y8/%-V9Y0Z^&7+ M,4*#QEX:YB7F;I9`7AB%)2VM*Z3P=W+"^2X9,"H$&`K'P48I.&T9<6Q8^$\G M689/DA7C#$\H038N!+F!!F\Z3Q,5;8!1-W`*SG$A5A72FCF'L89W.-7D>M&3 MFFH#9S`@J)ECV7'20[K;#@OB>5T\:GF2!49&IL0!82S:9-.:4W1\S<#01C&% MN+)[7;PSV*7E8"[LEV?H@S]9DAPH\WRI0P!"!1RF`>(#): M[M!8]&Y<:/%XB"N?A*A`^4K7HMN9B7$B[LE8!"!:&O.1AU3#8V'`H6'L6@FJ M=T^B8J&LY!)R-@H[N=%7>&RP[>=!X*&AC/@G92"#'4#!6YZ"EO%P^1RACE\* M-Z&M4ZA:=[.]4X)7'NP\>;8O"#+'JVKP&0X/>8QLY'4^!XP->:?N%('"'7J](84 M;=W)R&KVQGU.[K/-R!YX*8F7/6#5ZOB[K0>LNK@&#W,1+`-FLXR&=`:Y@_<, MCJS><$[J?,2\R=LXXT@TN?#@\!+YZ07LJO&?L5=.[N3QU`AXD,N-1GJ[:]P2 MLEW$<*N9VP9BJZ`2QW5D[8$3>5N)B#D#G2&[Q774<[FL#'C%`ZA8/AP6U?CR M;NV>=1;?"Y'#1.($2:JA#O&.=TQO694/=V?.RU+'APE3P=" MIY/!8['@A;Q6\0`>OJI3:/_V?#?WQ.\KOW\`#Y:W`#UG`#V7\>[/CWE\>ZWC MWQQ^@.`&PWL.Z?QW+FKZS+Y[* M_@>LSX'_)8?^@9\FPW#E6Z][#8[\O^^O8CGT46)`$UU$+\T9T`U.6GC[Y?]&= M2/QHP8\XT7U#$N+:C!@%NA9_O`9_@,```0,P?]2!&IVM)^9(%X`^2`Z`(F"= MF:SNT!2]9`1O2QOG M6?757;S$XP!DSIL$P8L;QA[<\UMD_W@)9/_H"SAW9RO(J3.6N>$BF-,==&D] M^4P'@'5KCY'YT4O_[C=<;KR0'EUG\Z;/BZPJHN:"UA;VYH6?=\XL02_O')O, M7;&]A;@I\,GPT!^E9\,1A!P$(#,MG+D.N=,"[`@I[!P$N/IQF,YZ5UJ<&@2. M-H$>FU.H[KW=>CCS&&GUCS.HE_$.L-QJ<&3@:`4X^&,7Q?.+UX837AH#GCX# MZJ]/K:-7;&-:>:J)SW7N>[58TU_\MS`R8#0)O'P?G'1229[#6.<.T.-=I)\G M>]AL&B>IJ(,@H0=S+2=3+](G0&_N2BFUG4\G9]DX/Z^K!B_F0' M4:)D`U+TA[H(UZ1S+GEJHX7O[U\MID%)UOI/H&)]/ULD7KT8_'NV([SO>3(* M65+:S(%J3H/?M$Z&WZ$Z9`T>@5?J`8O4=Y8J"U)?(0E(PB2DY$>MZ;7_@"[R M/L0`U9&5UHLSA1P^'#"W#!`EG]&D7_`EO_X^N7$'\0?1!U$'-1,&__C2`W(" MT0)Q`C02`G_HYDF.(07'(>2!TSQ\#O_O6$O@1/)283,82GP2F?\:$6+@+./U MG+DB%@"WK%C0=?93_.%&]<+0AX![C*T`IRT3E>`-T4/3`:?[:%LKF`9]V=[Z ML)/*^N8%GK:.-$#3%BRI6>X)X%&\1NU;4K:=9\4U_>,^\BY9Z##3ZZTWN5#S M*RELO!+O01R7%XRFOMJVC@]F!9%(?&C+CG*6G!N^QR8(U?NMXDO'$QFVAQ\L MPHT_9A%5K\LOXT^O\YFJ8!BB+!D$D#*M9T'':RR<<-:S MD[64SC>3`BRO&9+-T6<<@PUV_;D;?ER%=EQ<\='@MG0'UT_-UJ;X)8,F(MFF M$]G>H_)[V2,)91NG9>//@]Y7(8?>FF^W>R^L-QII!''S(;%YZWUZB7]4<.&7 M]<,0?9N&+]<+XU9T1Q0=-@,T0Q0--*3_N/&M9RN/AGWW,_=`#[F>$8',_1FS MC@VSK-]S#F,,L8@0^XU*8KT0@SR+F;A*K`%S6=\@"=K/LXRM#K>76%.NT M(>UVX4&(3,0F8>.C:]8?M1(!+1"!I*/O"!\B3ACME;\LQIEPS&`*EL_#;*0> M2\W2#PW6*V2),VX%)K=V[-HDAI>V>1([(FW7>'R4M/^Z(LB@-,E&>3]#Q"GA MH"#(9E2S^*?!Q[7I??Z`U>@[D:&>CF+V]"K_I9$L^\D(L#!DSH%+.9R-3VYF MFEX,2V@!.%4O7*H`/@=,Z8XU<< MCE_:`)R?^0!J`$J8#0+8C9B*ZP#\`&T/:@`+EGJF)5HF*%I$.O^]*61K1R<. MXF7V$QM`(J?^=)VF:,:4W'PL&T[,SU7OY:QL9:1KY:7OZ3WC2>[Z3W_B>\F3 MZ_R?4I:5H(0:AS&`;8@/L"N&HN>>'F(>(N17G24>EKRU)1Y&T-^9-)E_YGY^ M2%S;F03B%SO]R^)_N7+*,`-,O:Y@,%%F>Y&IP]WH:"&#A:?:/,]B-3AKO@,' M"T^T>8[4>G"K'?I8>%H]X\PVH].&._2P\/1[Q]@J]1Z<,=^EAX:BWS[!:SPY M8[Y+#PQ%OWV#UGESQWR7'AB+?NMH&K//FC_@NSX9SUQSQC.Z!=G^>?`<(V/Y MYZW#^>>1,5%A<9&AS9_@9DJ+"\R-3@[/T-'2T]465YD:G!W?H:.EI^HL[W)H MU.'N_0(%;9CI2UM>;3:^K:WN+2WNNYY/EZ05=IW`%]\/Y6O%^\8[QSO'>\>[R-O)*\E[R? MV985][TZ7O[>A%\27QO?--5],WUY?7MALV`);"ML2VQE;!\"@H+?3P&'Y]_/ MNWR^]@MQOM\/"2?P"0$@X.$CK\2DY25EI>;S[@(``P=GX"./P%"''X$N/`&< M?`.#!0%0`D`#(`.SX4`1`!C`(#0+`!*`04&]A1!`)EL@0069\;)@`(0`#((5 MG>"D)@($@@F^`*;/@(9X9G@`"3KHS(!#$V5R"$9GBAH3KH9L(5&SX$0C8$&P M0>'P`N/AG1FD"%!@+<-JQP;<&P.@!06%XQ%`01F4"`,<`N/MU^!:$$!+R_7W M?T@^[OC`V.#7ZWY(#0\-CPXX_G\=\1+/>+9^Q@['#KXO9^!=S(<'R@=+A[P^ M0^5>7L]/F&3R:&0R:!0WXGU_P`J+#`+&-WC(@SCY!I$"C`:.9\R8%'`SR^D- MU_`3/R0=?+=X-O5+L_9![?46_&^HEQ]Q@S'/@^)!\F9)$A+&DD@2O#Y)8YY> MST^6+!.AD[&LGAGX'TQ9!6+:&`@<>2S[>7@SO\<3!A&E`D@DWFA%'W".A(J^E7 MBN3K<4U@B"$""@=1;0@5!!BP\A887-Y!ZJ:A!A' M4HEQ$31]J);#L"2,)D5Y-8<"2`3$\85P2&-1[%99$%).FZ(]U'D20Q85PA2C MK($>D,8&4(9PR/8S-?`S\#!5\0BKW79W&_@<02K[4?AJO0^$:1DC0\"[P*_` MJ\"GP)_`D\"+P'_`>\!WP&_`6\!C_P4$BX!1U5G^MO!>)U_^3$)]4(F02=+, MIA99G0#A62N+S!59MA08LO,,6W,CZ1T!2D[,2P,(@R,Z@P0$E9<4P2/Q`2J< M"M'L5NI7"%:/=1[(]U'^HZG,G)X(GA">**<9#OX$R@W1UX:D\$82YOR$,C!2 M4Z-I'Y*(\2HKAE)M&<0CV,5)94B/DV-T9Z2(='AXL/N$/C]'<>'T$CW1\H\8 M(ZE$<:B]59\,9%R(2@1Z((_5E]*)N"/CPZA$=1JJH$:<$L,!#`3$0_1$G_XX&%$)Y^&(06$1,66G MHI;481^C8T+?ZEDPP/@A&$$P=258L%BZV\8)1H00F)"(?_Y,(X@&"292/Q2, M2/15\JO-6)",.&"!2"`P5-VA!0*#(8."H@%13HNT>H=#!X9"!`>'!@1#(\5* MGIN\(CT"O_#B"Q`2J"S)29Q(9J3.,H@N*80K+#`S.#'"" M4\1O)(2":$4$T">*.I1^EBC])U'Z2*/T@4?HVH_1A1^BB-,R+E'Z4J/TF4?I M$H_1U1^C2C]%E'Z(__CAX"$C&H#!#^H_%,>984INA70(?#/HK/48!X(*1\C"D]`=2Q[DK8IU5?;@J^W-0$J86\I6?:;EDH^A]'CE+#T48 M6'4<"3`5%<020A/$%<8P;)RF()X0F9^4G`8$A,\N4PA&")G&.P_B&`I@P&@C M`ND"N$9Q,U7U<#DXC)QZF#D%"TNJ'AX&\(:NN40<8IRX]3)XOS_Y##1RE182 M,E67)88%D@SK+"YF24NW0I';HP)P:F9@7ES!%U^$Y(1D3K\(!T;&'7X+"@B' MB(HY?L=(")U^$C'DL=?A<8,QW7X<'1X?PR"RY/T&$=?;K\/SPZ@F=)PQ_@C. M4=4#H*AC=B2;FK/YS-J2,R"Z4+G7>>'Q^?'D,?';E;V-$(S7,V-\,[21G"\4 M-9WN,UGF\X_WBOT$W-O@]WK5T,##S@N9\Y+YO-FS!#Y.3C\(3,^6WF'R9GNP MK"+P&#($ MP6NM@W.3J&=P8,_F?3/ M5@H=,D'<#3PW2E^1NG)JZW34W_P(`!PYMQ`6W80%Q,#/S\'04$1*RL`'`(0/.N:30&V;RGDHU2(DZ:YW0`S;JGU0)O_ M8M9)S5#D5>!O'.B82#@H6(CY:AK+O*W?$&'SA54,I.TV?\F47RKV MPQ!=J_I)&.BY!:ENM@%,F^L\D><^F?52LA5XWD>2Q')(O[;.!7STC$0\-$R$ M_78.QZ"YTPQE_YE3+2=!F_9Q"5\:AO-@3;NJ&0CXZ56I+O;`C%HK_=&6G?UD MU$O+4N)Z&<%Q*.BP@%@X(!`.?\`\(+".\`GC(P-C'.'@L,,G#F`:)3O?`(G? M\!RM#WHK&]0&>OL`./6@*,J]ER^=:>8^*T/;.,0C.+@B(T.U,%0&``8W@">; MZT`+F^VF"D^*("("\"A?B8H@9Q\$'R`4`!,/#MQ?C0["`19S%J5H(!`2@25( M)#P^L[(>'7DP$@%T0"0$SCU<>%0X_*J],@+@()`&BJ(#<=-,6]#BT8]_3(WW M\*QQPY/_X$G2`40`ZDRX@(P)J%^H;L,2E^^4NAX]%B6R-/(D)OAIR_WKA(+* M7ZE<<.583``02*TD:>Z-QD]P6!@15%2^[0P=$4#>]/(@``*0$NC@"-#R\*.H M/T73M*J77J,,%)G_+@'J`P80#`X/@`(_B.`'#1CI\`4*"XG`H5?&=_A/@!JS M!PAJ06-SV8"U3764XMWS^/07:`R4(#!`7=AF6("0H+V@8&[D#MX@>SL<]O+O M$%-WV"NTY!87&!D:&QP='A\A(B,D)28G*"DJ*RPM+B_>H89LF)EN0S--H:FQ MN<&Y`'I\?H""A(:(BHR.D)*5M>Q+3$U.WB)Z@HJ2FJ*BJK*ZPLK2VN+ MJ\OL#"Q,;(RLS.T;Q&D#:MXC6V-OO]M7.7O]M9N_W_;6\`00/O]M=0N1<-#Q M$3PNQ1!%UAD:01T?(2)!)2;])2TU/GU45)! M55=96UU?86-E9VA!:VUO<7)!=7=Y>WV\2_Y>%.@S4!-,&?&81!AXD^LQ;`4, M,;'GN9&3E9>9FD&=5GS_U4B3@_FIJ.JIH&J)J/H!JO^)JO>L?O['OOQ^KIJN MT?J]'NO&B_O&`__1]-,>-'[(E(_1'_]1*CC^''K2ZQ%'[K2ZT1^[0<.V->]7 MU>U5U:3]H'[JSX>DO_ZJ^'NNBE=5\!=5]BCZW8],EDKNJ[/Q)(>C]#K#Z7=5WM/W4=U_0/U_4?[*+Q_?_WM,!I=94M'[#] M*7H_8?EV7K5>7G5==X_U3&Q0':U4U?QI:]&9&,NV7U[1:/@/K M;HNM;JNM46]-5HKR[`JU^O^7ZP*`&N7`#,$_:;5RP`8P\M`',Y^U%R`"FNJH MHA2I0!D!?YFM/W41D=65H>4YKN`0X8PYAQV[N^#*EWK>H@7 M-33[1"K7#>J>Q7.%M"-(=#N8^BR#0O1(5C1'08Z$W^.B`V-J.3FCDZI&^-NY%EK'95 ML&_(H@Z]``\XTVIFSJ?.5E"'E6A0?DC$@%9/&?A29\%+4@I88R:GAC1`/<-< M84TG#EL>;6P`6`+34TX+7*`7I"'SI`'WJJ&+I@`Y7K3'TT1].,?3@!]'`#Z' M'0F&`20"(>$X$LT4E'#V!,*`_>->&,P,#Q4O\:&Z5G*U/T@4BI M4@,G/4@$+\*8%_L"155.6@&PCY](A&D*`IY)YJ2$_W.?I[/;_/U"S]1<_4C)IS-;22E] M.40!%)#*>$_?A,#V@J3='2B@&HU+'*$/>B[VF?83V^G\PO-^B"U)PSH4`%$, MQAD&@S&!1!#,Z^\.,1HQH)]#<:+:&05)_E('&@&ZCLS/IO,E2K_*\`V>=8!? M*0U4Q<$B3JDL@2:]!6IZ_8RZIC-CDQV,JB!\A28(B3C!PD[A02B[AI/!/W)'-`,J1:-3QJ1 MF-8\NIF9-K;:JFM)00&X'+&I(?0=T:F%:$:FAK:):HJ!:CB4V4](`!N:"B$& M8JR9T`T&2PJ?].JI&$73]2EC1UA;5F"`GV^IU$5SN$LZ6O_&\P;+T@S2T\`] MKZIP`YTG8S/%B))6T")M!29`]3'Z`,I"I4'(W4'&4`K5*";:>CG'TR*R?#AP M)J#.F@XREEIC`#_T1JO&KTB4_S(QGQB0EZ2"LR)9]ZI6'&OADV36XXMG0`KF M/7G4YQ(MQ#O'#QW,2B?K*W7!SC4]R#@"2"`#RP`3W`!VI!FF``88*D.0N<$S MZ3Z(J3=@\..D!:"TY!=H1K4KU)A@)K\8!6[*;;!MX%6X+>);X(6^"0I<](8M MXUN:W1;B(LY`0FF*)_BHJ+,Y!(P,I_C0T-C8XG^.CH\/#Z?ZT(4_R)/\C(R1 MGRJ?Y,G^N_$Z[2\4%*/.FO]>?BM>OBQ?P?BUTUW#+<,!)]^*6K!JH8H4G%9N M"2#$6Q"K1A[1V1R8;4:$9$8$6Q=/\6101,1'-O-$!#4P/7.:&`8A4MZ$(@A! MMI-KP:S@R+BXI;U++>"/CT@DQL9&,>,4UW MQ,?$QT1&Q$9'QX<";\9%1<2Q]#1$4QSQ4;$QC7G$Q29Z[X&K ME-=C^:R&$,9+MC^B&!%?\<[R? M\:R=2:L0R;S6,T]M6["Z4R747%N'`US76UR,;K6L\]P+G9^XVF)_@;'ZGXN;%@6OU=RY>SAUN'"XV*/'9"_GD` MOWE)D`.MY-[30!'"&A1!S.>P<=(Q8!2?80J(IVZ([6C*RAAN&AV1AS$>0?*8 MK!J47^I0JJFGHYZ7CH1Z;F-734,Z M-"\L*RTQ-CU%3EA1A:G)Y?\U8:%@D#GHW-#$O+2NK*ZRN,+.VNCY!Q,?*3$U M.3DU,2LE'14-!P#\^8I_OS_`P<-#]QV9WO[V[N9/?0V5E9FIO=7Z(DY^KM]0 M>=L<2'-T]73S<&QGXDDOBLGY.(?G9OZW6=J;7)V>\E8;N'R'AH2!?WY]XLH" M"AHEJ-D97J9FYB4CXJ#?'5N29V%=6>'I:76+'IS>7Z"X8D,E7IS:V)83T8]- MC$M*RPN,SI"3%=B;GF%$CI:>H_`@I*"G1O:VEG9VAK;G%U>7V`Y-F'X1-H+BF>LT_WOCOB(S$ M69G)Z>G9J5CH9\<65934$V+"0>YS3QTC*C20^2E=C;WJ$C93K=G)J6DHV),R M5?7OPTQ'_)#L3*4"_/1G7N])G!)_AX['JAIJJLQZJ::AG):0BH7-Y]XE8F0F M*&JM+W4+6F:6ML:^KH96#+XK:*6BX!V976;T(&-G;'!T>'OD8,_X+?X`!``. M';X`$?']P@[!U41$0?9IQ\<&"#,*$#,%/M/C3\&$GW!!6$%8(?A!^"U\!"<@ M0QIX4Y_#'C!`^$#N'0%X07_@RQ3@N5<8\$N_&&*FFZY>[MZI^DG^`FBMC>&[ MD`D5,!G4?/I#`FDU.[0%+W3)8U5:0RO=:/IN(=Z*$)@.5BC0J&)I\,3^@$D%V11HOJ,?3%) MND%*G5P9.!H!3'PE4J,)J*FFCVP(HFM`FH^#^G?HENI^TSK\.T.Z[1A]SO\N MS/),U@8BZ)_9W<6M#Q:YR8TX+5SJP M5/;\]4+C@`TQ,(Z7/<$UX$VI-ZAR*!:D#Y._$.\S[N70F&'WPU?4Z?,[J2]! M*=.$;.I1H?ZZ`U>H4'':GHP0WJ%?2`,$V2#6!>A%H%#'./+:[=E@':@`;0]Z;F*O!,)H[:M7^7[K!(!AQZ[YW/5 M^-%NH@0UH`:9,DE*@%(>%=`3VNLEC64DC54DO=5D>[-'NK1[]L>[9'UW4H(2 M2;1M(93`52.$GDA]@9U%RG@R1D1 MN)YNX/N9C)\2_-DDY&UC3D95C*,$.U8(K"JP5&[]#!PH:?:/,]A$:G#74_`+S\UR:=J/3BG?FRL+1[RCS#: MD^7S7R3J/3ACOTL/#46^?8*JL\.6.5I\EAX9D2@C0P+#2B-SOP).>>;@#W#Q-H97D6"%/$Y"HLB+C)I09G@/V2DY46%YD:G M!V?H:/*10P!-HPHH^D<"_\PYQR`G)2PF7B``)VPG!R5/)I2HY-*D(&4E]R4+ M)ALF,"9`)FPF#Y0*#/K\@4UO(']]_'O[_%P?E6Y-UN3]P)4`!_B>@#'Z:`%Q M?H.@H,TG>,X`IF-)"7?(P0I[BT(,-?F*FMJ+?[-0;K4`NOX`!0=7X35Q-$;G MF.!_`T$!M\MWS7`Q"#7%P)^%Q4O"Q/AG5%V%PC MBGK@Q\>$`QX;(`F^(`8BQ\"2?`*0IP$"P$"!5PV*##@@C$(B0K@,GPG(G4G@Q^)X*0@9P M^08$!/_`B`#%D'%HH@(_Q%/]LS/".*(Y2PSKSW$=T1PQ'*2([!"U1Q_Y"*JV M5RK%$$%QZ[J]_>XS;!KGW*"5@`A*%``6,#(`'!]L#)H!A1=;`K':(@!L!%"= MHHBZ/L=>A:,(D$I,-VP2`#ANN#@T3>'EP+!K&6V;0BO`!!U%NB?8>J_G:'SU M?Z>K#_9>TXP/#\4_OZ8'F1N<;J0N3/R;895\3`.,#_C\//%S`H1)Z<$^(!!A MAAF#S-*&&&"4!/6(>>)X1@F(T#/#CYC'M.^PZZ.^9.>N<0RS`\30#,B&_)O= MX<%I5&'@?QL6$1X1'V$0>>&)R@/\$H"/:<<\24>TXH\H]H=! ME^J\I0T=EI(J3X(=[1Z@7B@G56@/@]EA?U'Y0/&$X/\"H0F9]@(6B/9?1_^4 M5I_5TX<<=S4O_,JLS@,(RK#+ML9_F[C]0Y.VH9\\KKNK#RTAIYS,B'J_Z/A\J_YG@_@]AU,6+_6BE<+5?%C7("`8!GD57_CU$$ M\;0HW>".C&1?P;%NV8J=7P<.[OH+JN,T,$F#!LDEV'C'$ M;,>4:6`'S=W^N+^/&CPE8L)[S/?KH)7^=^<(?G_PG5&=G3SSGO<]^$X.#FK_ M.+,Z*@E&V_/"C"\P.S/?_D@=S&(?''^X`:'W^!P["9#L"W^N>)H6\,`%/P&A M@<5>6`R.0:GT+M`O0.__V?Q]SWUGGXXCG_9ABYF9B8=LSC5-C;S-N^9CMC9C M1.)DD!JI`7GY_0;<%M*GX7*UXO#.BQU)MP,"!N0DE0V'JLZJ`-+.^DIFU!SR8<>>4YW'X_YNGQ^6<@%3E6"_Q/0# M!P\?I/\?M`'^LW-G0>&3>0_I+E`8<'#EA]J;&>7,/F)^P'W6-#`^;G3)CHPZ M0&D[&_(#X<"08,3%@O@C%,'`@"F#P9+(`::V.(8342CC:S$^T`.-=^,^=BQ: M_Y\`/)BB,C(>'1A#P;,S%O<8*H&-FJ__,P\7.K8^0#QB[&^0,;\8D>WJBX&? MRIQ^`R49Z\!X/:U4?EG50P,$^2;E4KGL[Z1*S-L0`L968S[.5FF#N2`O9+[* M6ZW#\QD>7`Z89Q]<0*`D,#-#0PO(8,$93A<-5AZN&JQL#E[J^K[[`'_X`=52 M!TJ5E2=(`4\@&T\A\\\G4\\\EYVK_:I.X6I.0!D.0`5`=,PZ_Z_2-.7(!JJI MN`+XL/.W1555/2JM(;W29?O7_J])'<5^G5T&7[JB0-5TP%K@)O2'4]6`X8=( MY=#U==2Y=&J*J50+U(H#5H6+D_?VYL"C6HT`&,"]:`N[]O4@)K^W(,*ME&1J M^BUAL2I+!`5+;KN+6C`5;Z#`N;]U9E\(`'\`QU*IJ_35IO0`/V/Z](5LFFNL M]+T1`#__0HL++]#6E0JB+S/T/Z[DUE50M,"8)?!TFET_0VE0U@I'POW\3]Y* M4_4:W4[CIK`>!``_1CDH9R#7Z=*0&OU*)7J8_:1P_:EI1=.ARW'"T1"=U`1! M3;D'3]VD:TV7SOT]ZBNSK?!$#\`#UB?ZJE`8=4\;F?5#QY1&AZ+;G28!F0'4 M@&'[(&'[2&@":D>/*!L:AZ*.L/T#L/VK`%9P)5?JQ`7=^WS*`7.BL=:!>VP" M!>M`>ED=--![UT_TNG^H@*GQ.0TZY$.D\@//TYR`!?N@-#KB5ZJ_"5J[C)`ZI`X_>H M`4_C(`TWCRU7NHW*N(?9>Z5``U>%0&L!J;4AN$W//%I-I^N7HY=#EN.50F`* MO2@#ZEZ^Z8'^\LBNJK5I``.XA%S)B1U>AU3Y>N?J!]]=>I6LX;@#]#]+*&-7 M]4NU=[R=;?:X@+WL"^+$"D?[4U8[;Z:;-)HESDK%[975'Z(C)+WS`GS`EA:< ME=9H=+OU^G7A6$C6?H-2JH#2;&3QAZT`Y%#D M.OV3I./T-4U3?R7A@:7]!S8QC]_IZ]9'KK2TJUW7SR=T]*O!K!JIVX;@/2Q, MR5?H6)$Q^\J@<8J6+#J?$<:?7[A+4G4DG,G2',]Q``:K\=8`8`&! MSE?W>!\-WLM[R[Z4K7I>5X/UJ(`NA)\4I^1P_=!?Q#GA`.]4CO4U^M)[28PE M:EPI6M]VTS5X+;3]>K;=OUW/1Y*56I^2P&&GK'[+2)'J]=]ZR$@"K^< M@?CKH'ZJI2%XN+7JWO8%\2CYS8?H;>Q@!__=^(K/:^WB`_;RX`*NFW9*>BC] MI8.W8"]#IN7!`IX*:XYB56NO>]#]_ZY!K4<;B@#VXFJU!ZSR-6B6]_(`NW!` MN"#-8_8ZKQ);]SJ2_Z.==#'Z:O+K`)K)O.,,D@G4ZJY M7ZK`4LN,(9J^+$!Z.[&2#G7TY=>H-6``#5K%->/JL$\T[6\+92HOI``GVX"7 MWY^GE#_K#I)PZL'NCWL<6V'>[`_7O(!WC`:T7<[GU3<`1X@39`08X25.'U5& MYGRR-_P/\`,?]_Q$CM>,!#@X?`.'OX3#'X.!P.`KR@.!5A/[0#!!@@0YCY*# MF8!Q54I,`P&!5HW53X.,<%GR:2X='E*`LI#`,+#B`HQI@_:]-G&((X`;9O0) M_KR!@SO5*@(-R5CSG@^!S`_X`WZOE#?T!_P'^K8CH>G>E/FKP__L_]L__O-% M!YRP2X'#;B\'GARA^ZSNV\V_DO+OMUD2)$A04)2G63K(##1$CA(B1@?>/.N$ MA0%!:PG%X7%Q6$V28H68H&0K3`0>`@8*4)`0*"PJ;Z4ZQRB$DB4"(N+"P<%^ M/\`*?($=(T:RK(.`0\.1WXO&Y>6E<\*.<3_3A""$`V;:CG_+&?R$?PA`]"'H M"_\'S<>,B8$O88"!-W/8_9RROJ/[N_GS\W?Z;C.3(W!QL>-FWXKD=\S=^?@< MMPX,'`,P!>"1.45/VY)`0K=/94T&=R9ZF];^$;K7`,!GNHVL"R8BP8"P;(1, M6K)R<.#G7C1!0D2%&LDR0DQ6EI:JF)BQ,C`8#S,R4#P/3"X,*,22T^(335['^\,W-:A5!0D+`K*DI24E4B4I<=M4$[]8&$_VYO';7HR(_ MG"=^$0><37@__)G/>H%7_#OO*\X0]XPQ[9&W;&'7'''I$%`@8(?^`@2E%35" MZTI,U\`,%G_N=@&`4I.A7P?:=%8A&)6S<,`PD*Y/BGV;'63$PR#S"#_"2'^M MP]C-%A@"E\29)DR98]";B`UD!*P:!P0^K$0^$@Z M-07%:O\E*0*P;0<%B/\#_/]5@/QH<8"'"0I8A3`,D"5)B9(B)$B),-WY@[Z) M??[YO'$(!`/7P_@8,'C9]HN)ZFG'_\+!\[/"'%?>$Z^,">2`@32EV0&L\>8X MP0ZF,5#/$^48)FG96GRD^,$COM:V#`6G#)Y,0X($!"/`X%.OZF'R91B_C_P) MDMHC1JDB1$B3B+AJM4,K`P8`X'HR?]_.`R)("'.?X`'_)!I(JJ9ICA!C@CQ`@Q4A1@@IC$R/&##A.6`7_CSY4AGP@'L]BA/W:F?O MG#Q#.`?,7J_!2&>)L+A3'##G@UNAR=Z9\NC!"Q?0`KTX(=5Q3.G,&C_@'_JN MS$"?$"C_IQ;]V`/VMK<=G_+`?]P$.$&/=B/I#=+_!=)])%2KA@+__?V0@$)_ M8>%FG!@LH%TN3^!"#]#"#\3U^KVO(3#`\7(`D$!0$3(!`!$A1/4)6@$,K3Y_ ML4M;@0!Z?H@*EID9G)<0"NVJ;2:H:'D#'IP:8FWG2D`0`AR60:`IV)W!R<(" M&B`*))Z@R>@8UT%`*,`8*("C&6 MF8QVHZ`X"XG(4(4?J:J5S"N*)5*E+%`$H*@HHY1+'ZU=IVB3&:!!XC'@R`F( M`+09!_Q.C["!-/<2-$RUR8F1?_`!A[)T?2F`%3\$G![>`Y#$K"=DM@].=H;3 M/!00)&D2?P#2[0I_0:M=C!4G2@<8I3K]A'A"YPY`<23V09$VNAR5F+!BU2"@ M]$0';+E[M!R;T%Q@4>:U$K'3#<2'=L`$:E"&SC0X373*#4<\-S;\@_D5F.+\ M3]^Q#$.!"KBTX<@^`AH*XE8@P)L@*'I9"@:Q8KF$LV3<;%)!073@`6WE94 M$/7#F539(0%!@]9(`N>]\T-QD7`7D;6B=S%-U4W[6GY:!_P&Z!"#2$;K'"A& MP5(0M-`2PZ,QTI=@K"0D^5V(B+'Z"LOVE:),G\DFFVUQM:CE;D[P/C:"(V@Z M*`DN87B?8@0?TJE>'%:MVW\9/I@W%0)E_+4_F4#/VBX&0=%!5"UEGQ"D0 M\29+<"$G3R*$LCDP*60U"Q(/`DF10)<#L59#E(9'\:9.%AHS#$XRI-SB,0(@0Z!0X#!77!7"DN!1KE9;H"9:W'@W'6RTPRR:" M5[%6XDPRJ`8PSLF6DLO7>&DMKB0#0O=<0(;#\Y,S%.IQ@W2 M:3Z9BY*S,U."!.LI=<*8"8#V6*`>MP=T";DS"R#\!8(N$,7P>6,D6PE4G<*.LR"V^[`8X)H")A;'8V/[9W.L0Y:W)(MABC$&!4U M`E-[]"DFQPH%W$H67^8J$R2$I<'-BP%Q)N]5J_0&:366K%/<-X.S8I6ZQ<`+&*3LNO4+I4,V/-5:+PRYSV(LN9$@K,C8HYX)KAX%):Q0"3,4S)TMMPZ MPK`8DT\N+7H>IZK.J+')@S&@#I9H*,Q"`SG<`U&MHTG6Y5X,*KKK8H/T36[O7<+&I5JJE%&$D3+4&4U6\<)SN.0Z3:G[FN MSF'CG8FQF@S<,X()KF'&O9*XA;L=;>-$L)4[&-.)Q(EDXPEVEFR+$Q!"D)2U MK+7@C5L'ZT<:PA=/UL'F\"T&7J?S+90XB3('^I\%"4J328[+-LMP)N9NB8J( M"0"GTEQ0W9D'-UPLNH'@C%:4EC%&.(,PK%H$,I"M8(R$B!"0N9*N=&#GA=B3 M-*;%K&)S!SCC&H'H;%C-+Y8L$M4#>%\+@+CAS`@JS+<'M3B2+&PCNDNR:QDQ M(,L^2ZX`S%&0MT6))G-L&QM-20"Q0@Y:S=$YN8TSPC,TXN!,V@)Z-,2'I,@X MOR)A@",I[EC3>#DDVE^UQ!C!D@V!A;7`RLS>-$#%"=ZF,'A("R&JV.,UXKK:A!HFXQ%)@I\PE&-)ULV:>F$8'.?[\6 M1\829`3\241299%BS9S2TU@A;QK8=\G<@;0C7_6:UF\ZE=C=7J=86WD+)].; M/,I\6/#FS_N,[YI0:VK[:YK88S@0ALY6M]WC(;F6%1(.=YUWAT2&].4L:;A` MER66\4QK;;)9SP6D_&JYUPUWA*9O+2$!0YI-9/EPMDMW0*`A5K.=\;-H5<`&Q/N-=36T[Y$KCA2H\-Y_@(Y+XZ[D MXM0;..HZT;B@RW@!-=3A5MG*XVP`C7$US-R<-7C-TB;;G/(NNQW>\%<=+YK\ MUZ$PR]1.)A#M%(M/470D#A[K0P%MSKL13C#KE5*@S," MKJ\K":B$S)$'M4Y`A"Y/1QDI!0,5#@05;*EUT!F\&KURVG6D9YC9C=='>C`6TJ93Y/EFK MIP$;RXV\Q)FN1(QE^@1CI9&1T:G*_!/]O_^"7-__\N4 ` end -- Cameron Kaiser * cdkaiser.cris@com * powered by eight bits * operating on faith -- supporting the Commodore 64/128: http://computerworkshops.home.ml.org/ -- head moderator comp.binaries.cbm * cbm special forces unit $ea31 (tincsf) personal page http://calvin.ptloma.edu/~spectre/ * "when in doubt, take a pawn"