diff --git a/mode7_demo/docs/mode7_demo.tex b/mode7_demo/docs/mode7_demo.tex index 2b2377c8..0d543534 100644 --- a/mode7_demo/docs/mode7_demo.tex +++ b/mode7_demo/docs/mode7_demo.tex @@ -16,13 +16,16 @@ While making an inside-joke filled game for my retro system of choice, the Apple II, I needed to create a Final-Fantasy-esque flying-over-the-planet sequence. -I was originally going to fake this, but then I found that it was just barely -possible to achieve this in real time. +I was originally going to fake this, but why fake graphics when you +can laboriously spend weeks implementing the effect for real. +It turns out the Apple II is just barely capable of generating +the effect in real time. + Once I got the code working I realized it would be great as part of a -graphics demo, so off on that tangent I went. -This went well, despite the fact that all I know about the demoscene I learned -from a few viewings of the Future Crew {\em Second Reality} demo mixed with -dimly remembered Commodore 64 and Amiga flamewars. +graphical demo, so off on that tangent I went. +This turned out well, despite the fact that all I knew about the demoscene I +had learned from a few viewings of the Future Crew {\em Second Reality} demo +combined with dimly remembered Commodore 64 and Amiga usenet flamewars. % from a few decades ago. % This started out as some SNES style mode7 pseudo-3d graphics code @@ -33,12 +36,13 @@ dimly remembered Commodore 64 and Amiga flamewars. %lot of time was wasted fitting it under that arbitrary size limitation. While I hope you enjoy the description of the demo and the work that -went into it, I do suspect the whole enterprise is only of note -because so few people write demos for the Apple II platform. +went into it, I suspect this whole enterprise is primarily of note +due to the dearth of demos for the Apple II platform. %So in the end this ends up being impressive mostly because so few people %have bothered to write demos for this particular platform. -I would like to make a shout out to the FrenchTouch group whose Apple II -demos put this one to shame. +If you are truly interested in seeing impressive Apple II demos, +I would like to make a shout out to FrenchTouch whose works +put this one to shame. % The codesize ended up being roughly around 8kB, so I thought I'd % make it into an 8k demo. There aren't many out there for the Apple II. @@ -90,11 +94,13 @@ demos put this one to shame. \section{The Hardware} The Apple II was introduced in 1977. -This demo should run on an original system, though I do not -have hardware quite that old to test on. -I like to troll C64 fans by noting this predates the Commodore 64 by +In theory this demo will run on hardware that old, although I do +not have access to a system of that vintage. +I like to troll Commodore fans by noting this predates the Commodore 64 by five years. + + \vspace{1ex} \noindent {\bf CPU, RAM and Storage:} @@ -147,28 +153,29 @@ Hardware page flip & Yes \\ \end{tabular} \end{center} -The hi-res graphics mode was a complex mess of NTSC hacks by Woz. -You got approximately 280x192 resolution, with 6 colors available. -However the colors were from NTSC artifacts and there were limitations -on which colors could be next to each other (in blocks of 3.5 pixels). -There was plenty of fringing on edges, and colors changed depending on -whether they were drawn at odd or even pixels. +The hi-res graphics mode is a complex mess of NTSC hacks by Woz. +You get approximately 280x192 resolution, with 6 colors available. +The colors are NTSC artifacts with limitations +on which colors can be next to each other (in blocks of 3.5 pixels). +There is plenty of fringing on edges, and colors change depending on +whether they are drawn at odd or even locations. To add to the madness, the framebuffer is interleaved in a complex way, and pixels are drawn least-significant-bit first (all of this to make DRAM refresh better and to shave a few 7400 series logic chips from the design). You do get two pages of graphics, Page 1 is at -\$2000\footnote{On 6502 systems hexadecimal values are -indicated by the dollar sign} -and Page 2 at \$4000. +{\tt \$2000}\footnote{On 6502 systems hexadecimal values are +traditionally indicated by a dollar sign} +and Page 2 at {\tt \$4000}. Optionally 4 lines of text can be shown at the bottom of the screen instead of graphics. The lo-res mode is a bit easier to use. -It provides 40x48 blocks (40x40 if the four -lines of text are displayed at the bottom). +It provides 40x48 blocks, reusing the same memory as the 40x24 text mode. +(As with hi-res you can switch to a 40x40 mode with four lines of +text displayed at the bottom). Fifteen colors are available (there are two greys which are indistinguishable). -Again the addresses are interleaved. Lo-res Page 1 is at \$400 -and Page 2 is at \$800. +Again the addresses are interleaved in a non-linear fashion. +Lo-res Page 1 is at {\tt \$400} and Page 2 is at {\tt \$800}. Some amazing effects can be achieved by cycle counting, reading the floating bus, and racing the beam while toggling graphics @@ -191,10 +198,11 @@ I do all of my coding under Linux, using the nano text editor. I use the ca65 assembler from the cc65 project, which I find to be a reasonable tool although many ``real'' Apple II programmers look down on it for some reason. -I cross-compile the code, construct Apple DOS3.3 disk images using -custom tools I have written, and then do most testing in an emulator. +I cross-compile the code, constructing Apple DOS3.3 disk images using +custom tools I have written. +I test using emulators: AppleWin (run under the wine emulator) is the easiest to use, but -MESS/MAME has cleaner sound. +until recently MESS/MAME had cleaner sound. Once the code appears to work, I put it on a USB stick and transfer to actual hardware using a CFFA3000 disk emulator installed in @@ -260,67 +268,73 @@ well-traveled guinea pig. An Applesoft BASIC ``HELLO'' program loads the binary automatically at bootup. This does not count towards the executable size, as you could manually BRUN -the 8k program if you wanted. +the 8k machine-language program if you wanted. -To make the loading time slightly more interesting the binary is loaded at -address \$2000 (hi-res page1) and BASIC is nice enough to enable -graphics mode first so you can watch the display get filled with the random -pattern of the compressed image. -This entirely fills the 8k of the display, or would -if we POKEd the right address to turn off -the 4 lines of text on the bottom of the screen. +To make the loading time slightly more interesting the HELLO program enables +graphics mode and loads the program to address {\tt \$2000} (hi-res page1). +This causes the display to filled with the colorful pattern corresponding +to the compressed image. +This conveniently fills all 8k of the display RAM, or would have +if we had POKEd the right soft-switch to turn off +the bottom 4 lines of text. -Upon loading, execution starts at address \$2000 +Upon loading, execution starts at address {\tt \$2000}. -\subsection{DECOMPRESSER} +\subsection{DECOMPRESSION} The binary is encoded with the LZ4 algorithm. -We flip to hi-res Page 2 and decompress there so the user continues to get -a show of random noise. +We flip to hi-res Page 2 and decompress to this region so the display +now shows the executable code. The 6502 size-optimized LZ4 decompression code was written by qkumba (Peter Ferrie). % http://pferrie.host22.com/misc/appleii.htm -The program and data decompress to around 22k starting at \$4000. -It over-writes parts of DOS3.3, but since we will not be using the disk -any more this is not an issue. +The program and data decompress to around 22k starting at {\tt \$4000}. +This over-writes parts of DOS3.3, but since we are done with the disk +this is not an issue. If you look carefully at the upper left corner of the screen during decompress you will see my triangular logo, which is supposed to evoke my VMW initials (see Figure~\ref{fig:vmw}). -To do this I had to put the proper bit pattern at the interleaved -addresses of \$4000, \$4400, \$4800, and \$4C00. -This turned out to be way more trouble than it was worth. -As an interesting note, the image data at \$4000 is executed as it maps -to (mostly) harmless code. +To do this I had to put the proper bit pattern inside the code +at the interleaved addresses of {\tt \$4000}, {\tt \$4400}, {\tt \$4800}, +and {\tt \$4C00}. +The image data at {\tt \$4000} maps to (mostly) +harmless code so it is left in place and executed. +Making this work turned out to be more trouble than it was worth, especially +as the logo is not visible in the youtube capture of the demo (the movie +compression does not handle screens full of seemingly random noise well). -The demo was optimized to fit in 8k, and this is difficult when your program -is compressed. +The demo was optimized to fit in 8k. +Optimizing code inside of a compressed image is much more complicated than +regular size optimization. Removing instructions sometimes makes the binary {\em larger} as it no longer compresses as well. Long runs of values (such as 0 padding) are essentially free. This mostly turned into an exercise of guess-and-check until everything fit. -\subsection{FADE EFFECT} +\subsection{TITLE SCREEN} + +Once decompression is done, execution continues at address {\tt \$4000}. +We switch to low-res mode for the rest of the demo. + +\noindent +{\bf FADE EFFECT}: The title screen fades in from black. - This is a software hack as the Apple II does not have palette support. The image is loaded to an off-screen buffer and a lookup table is used to copy in the faded versions on the fly. -\subsection{TITLE SCREEN} - - -Once decompression is done, execution continues at address \$4000. -We switch to low-res mode for the rest of the demo. - -A title screen is loaded, as seen in Figure~\ref{fig:title}. +\noindent +{\bf TITLE GRAPHICS}: +The title screen is shown in Figure~\ref{fig:title}. The image is run-length encoded (RLE) which is -probably unnecessary when being further LZ4 encoded. +probably unnecessary in light of it being further LZ4 encoded. (The LZ4 compression was a late addition to this endeavor). -Why not save some space and just load our demo at \$400 and negate the need +Why not save some space and just load our demo at {\tt \$400} and negate +the need to copy the image in place? Remember the graphics are 40x48 (shared with the text display region). It might be easier to think of it as 40x24 characters, with the top / bottom @@ -332,8 +346,10 @@ There are ``holes'' in the address range that are not displayed, and various pieces of hardware can use these as scratchpad memory. This means just overwriting the whole 1k with data might not work out well unless you know what you are doing. -To this end the RLE decompression code skips the holes just to be safe. +To this end our RLE decompression code skips the holes just to be safe. +\noindent +{\bf SCROLL TEXT}: The title screen has scrolling text at the bottom. This is nothing fancy, the text is in a buffer off screen and a 40x4 chunk of RAM is copied in every so many cycles. @@ -347,20 +363,23 @@ movie encoding conspire to make this look worse than things look in person. \subsection{MOCKINGBOARD MUSIC} No demo is complete without some exciting background music. -I like chiptune music, especially the kind you can find that is made +I like chiptune music, especially the kind written for AY-3-8910 based systems. -I gained some expertise during the long wait for my Mockingboard to arrive -by building a Raspberry Pi chiptune player that is essentially the same -hardware. +During the long time waiting for my Mockingboard hardware to arrive +I designed and built a Raspberry Pi chiptune player that uses +essentially the same hardware. +This allowed me to build up some expertise with the software/hardware +interface in advance. The song being played is a stripped down and re-arranged version of ``Electric Wave'' from CC'00 by EA (Ilya Abrosimov). Most of my sound infrastructure involves YM5 files, a format commonly -used by ZX Spectrum and ATARI ST users. -These are essentially just AY-3-8910 register dumps taken at 50Hz. -To play these back just set up the sound card to interrupt 50 times a second -and then write out the 14 register values from that frame. +used by ZX Spectrum and Atari ST users. +The YM file format is just AY-3-8910 register dumps taken at 50Hz. +To play these back one sets up the sound card to interrupt 50 times a second +and then writes out the 14 register values from each frame in an interrupt +handler. % To program the Mockingboard, each AY-3-8910 chip has 14 sound related % registers that control the 3 channels. Each AY chip has a dedicated @@ -381,7 +400,7 @@ and only write to the registers that have changed. % I have a whole suite of code for manipulating YM sound data, in my % vmw-meter git repository. -Our code detects a Mockingboard at startup, we are lazy and only support +Our code detects the Mockingboard at startup; we are lazy and only support finding the card in Slot 4 (which is a fairly typically location). % The first step for getting this to work is detecting if a Mockingboard is %% there. This can be in any slot 1-7 on the Apple II, though typically @@ -391,9 +410,9 @@ interrupt at 25Hz. % (it has to be an on-board timer as the default % Apple II has no timers). Why 25Hz and not 50Hz? At 50Hz with 14 registers you use 700 bytes/s. -So a 2 minute song would take 84k of RAM, much more than is available. -To allow the song to fit in memory (without the fancy circular buffer -decompression utilized in my VMW Chiptune Player music-disk demo) we have +So a 2 minute song would take 84k of RAM, which is much more than is available. +To allow the song to fit in memory (without a fancy circular buffer +decompression routine utilized in my VMW Chiptune music-disk demo) we have to reduce the size. First the music is changed so it only needs to be updated at 25Hz. Then the register data is compressed from 14 bytes to 11 bytes by stripping off @@ -404,10 +423,10 @@ acceptably catchy chiptune inside of our 8k payload. \subsection{MODE7 BACKGROUND} ``Mode7'' is a Super Nintendo (SNES) graphics mode that takes a tiled -background to be transformed by rotation and scaling. -The most common effect was to squash it out to the horizon, giving +background and transforms it by rotating and scaling. +The most common effect squashes the background out to the horizon, giving a three-dimensional look. -The SNES did these transforms in hardware, but in this demo we implement +The SNES did these transforms in hardware, but our demo must do them in software. % As found on Wikipedia, the transform is of the type @@ -415,138 +434,158 @@ them in software. % [x'] = [a b]([x]-[x0])+[x0] % [y'] [c d]([y] [y0]) [y0] +% http://www.helixsoft.nl/articles/circle/sincos.htm + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Our algorithm is based on code by Martijn van Iersel. -It iterates through each y line on the screen and calculates based on -the camera location: height ({\em spacez}), x and y coordinates -({\em cx} and {\em cy}) and the {\em angle}. +It iterates through each horizontal line on the screen and calculates the color +to output based on the camera height ({\em spacez}) and {\em angle} as well +as the current x and y coordinates ({\em cx} and {\em cy}). -First calculate the distance - d = (z*yscale)/(y+horizon) -Then calculate the horizontal scale (distance between points on -this line) - h = d/xscale -Then calculate delta x and delta y values - dx = -sin(angle)*h - dy = cos(angle)*h -It then calculates the starting offset of the left side of the line in -the tile lookup: - tilex = cx + (d*cos(angle) - (width/2) * dx; - tiley = cy + (d*sin(angle) - (width/2) * dy; -Now iterate the inner loop, where we lookup the tile color for each pixel -on the horizontal line. - putpixel (x, y, tilelookup(tilex,tiley) - tilex += dx; - tiley += dy; +First the distance {\em d} is calculated based on fixed scale and +distance-to-horizon factors. +Instead of a costly division we use a pre-generated lookup table for this. + \[d = \frac{z \times yscale}{y+horizon}\] +Next calculate the horizontal scale (distance between points on +this line): + \[h = \frac{d}{xscale}\] +Then calculate delta x and delta y values between each block on the line. +We use a pre-computed sine/cosine lookup table. + \[dx = -sin(angle) \times h\] + \[dy = cos(angle) \times h\] +The leftmost position in the tile lookup is calculated: + \[tilex = cx + (d*cos(angle) - (width/2) * dx\] + \[tiley = cy + (d*sin(angle) - (width/2) * dy\] +Then an inner loop happens that adds dx and dy as we lookup the color +from the tilemap (just a wrap-around array lookup) for each block +on the line. + \[color = tilelookup(tilex,tiley)\] + \[plot (x, y) \] + \[tilex += dx, tiley+= dy\] -{\bf Optimizations} - -We managed to take this algorithm and speed it up in the following ways: - \begin{itemize} - \item blah - \end{itemize} - - For our code, we managed to reduce things to a small number of additions - and subtractions for each pixel on the screen. Of course the 6502 can't - do floating point, so we do fixed point math. We convert as much as we - can to table lookups that are pre-calculated. We also make liberal use - of self-modifying code. +\noindent +{\bf Optimizations:} +The 6502 processor cannot do floating point, so all of our routines use +8.8 fixed point math. +We eliminate all use of division, and convert as much as possible +to table lookups (which involves limiting the heights and angles a bit). +We also save some cycles by using self-modifying code, +most notably hard-coding the height (z) value and modifying the code +whenever this is changed. +The code started out only capable of roughly 4.9fps in 40x20 resolution +and in the end we improved this to 5.7fps in 40x40 resolution. +Care was taken to optimize the innermost loop, as every cycle saved there +results in 1280 cycles saved overall. +\noindent {\bf Fast Multiply:} +One of the biggest bottlenecks in the mode7 code was the multiply. +Even our optimized algorithm calls for at least seven +16bit x 16bit = 32bit multiplies, something that is {\em really} slow on +the 6502. +A typical implementation takes around 700 cycles +for a 8.8 x 8.8 fixed point multiply. - Despite all of this there are still some cases where we have to do a - 16bit x 16bit = 32bit multiply, something that is *really* slow on 6502, - around 700 cycles (for a 8.8 x 8.8 fixed point multiply). +% Note, this is Quarter-square multiplication, apparently an ancient algorithm +% https://en.wikipedia.org/wiki/Multiplication_algorithm#Quarter_square_multiplication - To make this faster we use a method described by Stephen Judd. +We improved this by using the ancient quarter-square +multiply algorithm, first described for 6502 use by Stephen Judd. - The key to note is that $(a+b)^{2} = a^{2}+2ab+b^{2}$ - and $(a-b)^{2}=a^{2}-2ab+b^{2}$ - and if you add them you can simplify to: - $a\times b =\frac{(a+b)^{2}}{4} - \frac{(a-b)^2}{4}$ +This works by noting these factorizations: + \[(a+b)^{2} = a^{2}+2ab+b^{2}\] + \[(a-b)^{2}=a^{2}-2ab+b^{2}\] +If you subtract these you can simplify to + \[a\times b =\frac{(a+b)^{2}}{4} - \frac{(a-b)^2}{4}\] - This is you have a table of squares from 0..511 (all 8-bit a+b and a-b - will fall in this range) then you can convert a multiply into a table - lookup plus a subtract. +For 8-bit values if you create a table of squares from 0 to 511 +(all 8-bit a+b and a-b fall in this range) then you can convert a multiply +into two table lookups and a subtraction. +This does have the downside of requiring 2kB of lookup tables +(which can be generated at startup) but it reduces the multiply +cost to the order of 250 cycles or so. - The downsize is you will need 2kB of squares lookup tables (which can - be generated at startup). This reduces the multiply cost to the order - of 200 to 250 cycles. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - By using the fast multiply and a lot of careful optimization you can - generate a Mode7 background in 40x40 graphics mode at about 5 frames/second. +\subsection{BALL ON CHECKERBOARD} - The engine can be parameterized with different tilesets to use, which we - do to provide both a black+white checkerboard background, as well as the - island background from the TFV game. - -\subsection{BOUNCING BALL ON CHECKERBOARD} - -The first scence starts out viewing an infinite checkerboard. -Any demo would be incomplete without some sort of bouncing geometric solid, -in our case a pink sphere. -This was accomplished with 16 sprites: -the sphere was modeled in OpenGL inside of a 20 year old game engine -and screenshots were taken then reduced in keeping with the size and -color limitations. -Similarly the shadow is also just sprites. +The first Mode7 scene transpires on an infinite checkerboard. +A demo would be incomplete without some sort of bouncing geometric solid, +in this case we have a pink sphere. +The sphere is represented by 16 sprites that were captured from +a 20 year old OpenGL game engine. +Screenshots were taken then reduced to the proper size and color +limitations. +The shadows are also just sprites. +Note that the Apple II has no dedicated sprite hardware, so these +are drawn completely in software. The clicking noise on bounce is generated by accessing the speaker port -at address \$C030. -This gives some sound for those viewing the demo without a Mockingboard. +at address {\tt \$C030}. +This gives some sound for those viewing the demo without the benefit +of a Mockingboard. \subsection{TFV SPACESHIP FLYING} - This next scene has a spaceship flying over an island. +The Mode7 graphics code is generic enough that only one copy of the code +is needed to generate both the checkerboard and island scenes. The spaceship, water splash, and shadows are all sprites. -They are all drawn in software as the Apple II has no sprite hardware. The path the ship takes is pre-recorded; this is adapted from the Talbot Fantasy~7 game engine with the keyboard code replaced by a hard-coded script of actions to take. \subsection{STARFIELD} -The spaceship takes to the stars. -This is typical starfield code. -Only 16 stars are modeled, and the movement code re-uses the -same fast-multiply routine described previously. +The spaceship now takes to the stars. +This is typical starfield code, where on each iteration the x and y +values are changed by + \[dx=\frac{x}{z}, dy=\frac{y}{z}\] +In order to get a good frame rate and not clutter the lo-res screen +only 16 stars are modeled. +To avoid having to divide, the reciprocal of all possible z values +are stored in a table, and the fast-multiply routine described +previously is used. -The star positions require random number generation, but this is not -fast on the 6502. +The star positions require random number generation, but there is no +easy way to quickly get random data on the Apple II. Originally we had a 256-byte blob of pre-generated ``random'' values included in the code. This wasted space, so now instead we just use our code at address at \$5000 as if it were a block of random numbers. This was arbitrarily chosen, and it is not as random as it could be -as seen when the ship enters hyperspace the lower right quadrant has fewer -starts than one could desire. +as seen when the ship enters hyperspace and the lower-right quadrant +is distressingly star-free. + A simple state machine controls star speed, ship movement, hyperspace, background color (for the blue flash) and the eventual sequence of sprites as the ship vanishes into the distance. \subsection{RASTERBARS/CREDITS} -Once the ship has departed, it is time for the credits as the stars -continue to run. +Once the ship has departed, it is time to run the credits as the stars +continue to fly by. -The text is written to the bottom 4 lines of the screen and appears -to be surrounded by low-res graphics blocks. -Mixed graphics/text would generally not be possible on the Apple II, although +The text is written to the bottom four lines of the screen, seemingly +surrounded by graphics blocks. +Mixed graphics/text is generally not be possible on the Apple II, although with careful cycle counting and mode switching groups such as FrenchTouch have achieved this effect. -I was lazy and instead used inverse-mode space characters which appear the same -as white graphics blocks. +What we see in this demo is the use of inverse-mode (inverted color) +space characters which appear the same as white graphics blocks. -The rasterbar effect is not really rasterbars, it's just a colorful assortment +The rasterbar effect is not really rasterbars, just a colorful assortment of horizontal lines drawn at a location determined with a sine lookup table. -Horizontal lines can take a surprising amount of time to draw, so this -was optimized using inlining and a few other methods. +Horizontal lines can take a surprising amount of time to draw, but these +were optimized using inlining and a few other tricks. -The rotating text is done by just rapidly rotating the output string through -the ASCII table, with the clicking effect again by hitting the speaker -at address \$C030. -The list of people to thank ended up being extremely critical to fitting in 8kB, -as unique text strings do not compress well. +The spinning text is done by just rapidly rotating the output string through +the ASCII table, with the clicking effect again generated +by hitting the speaker at address {\tt \$C030}. +The list of people to thank ended up being the primary limitation to +fitting in 8kB, as unique text strings do not compress well. I apologize to everyone whose moniker got compressed beyond recognition, and I am still not totally happy with the centering of the text. diff --git a/still_alive/Makefile b/still_alive/Makefile new file mode 100644 index 00000000..dbcdde7e --- /dev/null +++ b/still_alive/Makefile @@ -0,0 +1,24 @@ +include ../Makefile.inc + +DOS33 = ../dos33fs-utils/dos33 + +all: still_alive.dsk + +still_alive.dsk: STILL_ALIVE ./SA.KRW + $(DOS33) -y still_alive.dsk BSAVE -a 0x0C00 STILL_ALIVE + $(DOS33) -y still_alive.dsk SAVE B ./SA.KRW + +STILL_ALIVE: still_alive.o + ld65 -o STILL_ALIVE still_alive.o -C ../linker_scripts/apple2_c00.inc + +still_alive.o: still_alive.s \ + ../asm_routines/mockingboard.s \ + ../asm_routines/dos33_routines.s \ + ../asm_routines/lz4_decode.s \ + ../asm_routines/keypress_minimal.s \ + interrupt_handler.s \ + ascii_art.inc zp.inc + ca65 -o still_alive.o still_alive.s -l still_alive.lst + +clean: + rm -f *~ *.o *.lst STILL_ALIVE diff --git a/still_alive/README.still_alive b/still_alive/README.still_alive new file mode 100644 index 00000000..f5c30856 --- /dev/null +++ b/still_alive/README.still_alive @@ -0,0 +1,2 @@ +initial: 2078 +add ascii art: 9142 diff --git a/still_alive/SA.KRW b/still_alive/SA.KRW new file mode 100644 index 00000000..4d580d71 Binary files /dev/null and b/still_alive/SA.KRW differ diff --git a/still_alive/ascii_art.inc b/still_alive/ascii_art.inc new file mode 100644 index 00000000..32c8c4cd --- /dev/null +++ b/still_alive/ascii_art.inc @@ -0,0 +1,223 @@ +aperture: + .asciiz " .,-:;//;:=," + .asciiz " . :H@@@MM@M#H/.,+%;," + .asciiz " ,/X+ +M@@M@MM%=,-%HMMM@X/," + .asciiz " -+@MM; $M@@MH+-,;XMMMM@MMMM@+-" + .asciiz " ;@M@@M- XM@X;. -+XXXXXHHH@M@M#@/." + .asciiz " ,%MM@@MH ,@%= .---=-=:=,." + .asciiz " =@#@@@MX ., -%HX$$%%%+;" + .asciiz " =-./@M@M$ .;@MMMM@MM:" + .asciiz " X@/ -$MM/ .+MM@@@M$" + .asciiz ",@M@H: :@: . =X#@@@@-"; + .asciiz ",@@@MMX, . /H- ;@M@M="; + .asciiz ".H@@@@M@+, %MM+..%#$."; + .asciiz " /MMMM@MMH/. XM@MH; =;" + .asciiz " /%+%$XHH@$= , .H@@@@MX," + .asciiz " .=--------. -%H.,@@@@@MX," + .asciiz " .%MM@@@HHHXX$$$%+- .:$MMX =M@@MM%." + .asciiz " =XMMM@MM@MM#H;,-+HMM@M+ /MMMX=" + .asciiz " =%@M@M#@$-.=$@MM@@@M; %M%=" + .asciiz " ,:+$+-,/H#MMMMMMM@= =," + .asciiz " =++%%%%+/:-." + +radioactive: + .asciiz " =+$HM####@H%;," + .asciiz " /H###############M$," + .asciiz " ,@################+" + .asciiz " .H##############+" + .asciiz " X############/" + .asciiz " $##########/" + .asciiz " %########/" + .asciiz " /X/;;+X/" + .asciiz " " + .asciiz " -XHHX-" + .asciiz " ,######," + .asciiz "#############X .M####M. X#############"; + .asciiz "##############- -//- -##############"; + .asciiz "X##############%, ,+##############X"; + .asciiz "-##############X X##############-"; + .asciiz " %############% %############%" + .asciiz " %##########; ;##########%" + .asciiz " ;#######M= =M#######;" + .asciiz " .+M###@, ,@###M+." + .asciiz " :XH. .HX:" + +atom: + .asciiz " =/;;/-" + .asciiz " +: //" + .asciiz " /; /;" + .asciiz " -X H." + .asciiz ".//;;;:;;-, X= :+ .-;:=;:;%;."; + .asciiz "M- ,=;;;#:, ,:#;;:=, ,@"; + .asciiz ":% :%.=/++++/=.$= %="; + .asciiz " ,%; %/:+/;,,/++:+/ ;+." + .asciiz " ,+/. ,;@+, ,%H;, ,/+," + .asciiz " ;+;;/= @. .H##X -X :///+;" + .asciiz " ;+=;;;.@, .XM@$. =X.//;=%/." + .asciiz " ,;: :@%= =$H: .+%-" + .asciiz " ,%= %;-///==///-// =%," + .asciiz ";+ :%-;;;:;;;;-X- +:"; + .asciiz "@- .-;;;;M- =M/;;;-. -X"; + .asciiz " :;;::;;-. %- :+ ,-;;-;:==" + .asciiz " ,X H." + .asciiz " ;/ %=" + .asciiz " // +;" + .asciiz " ,////," + +broken_heart: + .asciiz " .,---." + .asciiz " ,/XM#MMMX;," + .asciiz " -%##########M%," + .asciiz " -@######% $###@=" + .asciiz " .,--, -H#######$ $###M:" + .asciiz " ,;$M###MMX; .;##########$;HM###X="; + .asciiz " ,/@##########H= ;################+"; + .asciiz "-+#############M/, %##############+"; + .asciiz "%M###############= /##############:"; + .asciiz "H################ .M#############;."; + .asciiz "@###############M ,@###########M:." + .asciiz "X################, -$=X#######@:" + .asciiz "/@##################%- +######$-" + .asciiz ".;##################X .X#####+," + .asciiz " .;H################/ -X####+." + .asciiz " ,;X##############, .MM/" + .asciiz " ,:+$H@M#######M#$- .$$=" + .asciiz " .,-=;+$@###X: ;/=." + .asciiz " .,/X$; .::," + .asciiz " ., .." + +explosion: + .asciiz " .+" + .asciiz " /M;" + .asciiz " H#@: ;," + .asciiz " -###H- -@/" + .asciiz " %####$. -; .%#X" + .asciiz " M#####+;#H :M#M." + .asciiz ".. .+/;%#########X###-" + .asciiz " -/%H%+;-, +##############/" + .asciiz " .:$M###MH$%+############X ,--=;-" + .asciiz " -/H#####################H+=." + .asciiz " .+#################X." + .asciiz " =%M####################H;." + .asciiz " /@###############+;;/%%;," + .asciiz " -%###################$." + .asciiz " ;H######################M=" + .asciiz " ,%#####MH$%;+#####M###-/@####%" + .asciiz " :$H%+;=- -####X.,H# -+M##@-" + .asciiz " . ,###; ; =$##+" + .asciiz " .#H, :XH," + .asciiz " + .;-"; + +file: + .asciiz " -$-" + .asciiz " .H##H," + .asciiz " +######+" + .asciiz " .+#########H." + .asciiz " -$############@." + .asciiz " =H###############@ -X:" + .asciiz " .$##################: @#@-" + .asciiz " ,; .M###################; H###;" + .asciiz " ;@#: @###################@ ,#####:" + .asciiz " -M###. M#################@. ;######H" + .asciiz " M####- +###############$ =@#######X" + .asciiz " H####$ -M###########+ :#########M," + .asciiz " /####X- =########% :M########@/." + .asciiz " ,;%H@X; .$###X :##MM@%+;:-" + .asciiz " .." + .asciiz " -/;:-,. ,,-==+M########H" + .asciiz " -##################@HX%%+%%$%%%+:,," + .asciiz " .-/H%%%+%%$H@###############M@+=:/+:"; + .asciiz "/XHX%:#####MH%= ,---:;;;;/%%XHM,:###$"; + .asciiz "$@#MX %+;- ." + + +check: + .asciiz " :X-"; + .asciiz " :X###" + .asciiz " ;@####@" + .asciiz " ;M######X" + .asciiz " -@########$" + .asciiz " .$##########@" + .asciiz " =M############-"; + .asciiz " +##############$"; + .asciiz " .H############$=." + .asciiz " ,/: ,M##########M;." + .asciiz " -+@###; =##########M;" + .asciiz " =%M#######; :#########M/" + .asciiz "-$M###########; :#########/" + .asciiz " ,;X###########; =########$." + .asciiz " ;H#########+#######M=" + .asciiz " ,+##############+" + .asciiz " /M#########@-" + .asciiz " ;M######%" + .asciiz " +####:" + .asciiz " ,$M-" + +black_mesa: + .asciiz " .-;+$XHHHHHHX$+;-." + .asciiz " ,;X@@X%/;=----=:/%X@@X/," + .asciiz " =$@@%=. .=+H@X:" + .asciiz " -XMX: =XMX=" + .asciiz " /@@: =H@+" + .asciiz " %@X, .$@$" + .asciiz " +@X. $@%" + .asciiz "-@@, .@@="; + .asciiz "%@% +@$"; + .asciiz "H@: :@H"; + .asciiz "H@: :HHHHHHHHHHHHHHHHHHX, =@H"; + .asciiz "%@% ;@M@@@@@@@@@@@@@@@@@H- +@$"; + .asciiz "=@@, :@@@@@@@@@@@@@@@@@@@@@= .@@:"; + .asciiz " +@X :@@@@@@@@@@@@@@@M@@@@@@:%@%" + .asciiz " $@$, ;@@@@@@@@@@@@@@@@@M@@@@@@$." + .asciiz " +@@HHHHHHH@@@@@@@@@@@@@@@@@@@@@@@+" + .asciiz " =X@@@@@@@@@@@@@@@@@@@@@@@@@@@@X=" + .asciiz " :$@@@@@@@@@@@@@@@@@@@M@@@@$:" + .asciiz " ,;$@@@@@@@@@@@@@@@@@@X/-" + .asciiz " .-;+$XXHHHHHX$+;-." + +cake: + .asciiz " ,:/+/-" + .asciiz " /M/ .,-=;//;-" + .asciiz " .:/= ;MH/, ,=/+%$XH@MM#@:" + .asciiz " -$##@+$###@H@MMM#######H:. -/H#"; + .asciiz " .,H@H@ X######@ -H#####@+- -+H###@X"; + .asciiz " .,@##H; +XM##M/, =%@###@X;-" + .asciiz "X%- :M##########$. .:%M###@%:" + .asciiz "M##H, +H@@@$/-. ,;$M###@%, -"; + .asciiz "M####M=,,---,.-%%H####M$: ,+@##"; + .asciiz "@##################@/. :%H##@$-" + .asciiz "M###############H, ;HM##M$=" + .asciiz "#################. .=$M##M$=" + .asciiz "################H..;XM##M$= .:+"; + .asciiz "M###################@%= =+@MH%"; + .asciiz "@################M/. =+H#X%=" + .asciiz "=+M##############M, -/X#X+;." + .asciiz " .;XM##########H= ,/X#H+:," + .asciiz " .=+HM######M+/+HM@+=." + .asciiz " ,:/%XM####H/." + .asciiz " ,.:=-." + + +glados: + .asciiz " #+ @ # # M#@" + .asciiz " . .X X.%##@;# # +@#######X. @#%" + .asciiz " ,==. ,######M+ -#####%M####M- #"; + .asciiz " :H##M%:=##+ .M##M,;#####/+#######% ,M#"; + .asciiz " .M########= =@#@.=#####M=M#######= X#"; + .asciiz " :@@MMM##M. -##M.,#######M#######. = M"; + .asciiz " @##..###:. .H####. @@ X,"; + .asciiz " ############: ###,/####; /##= @#. M" + .asciiz " ,M## ;##,@#M;/M#M @# X#% X#" + .asciiz ".%= ######M## ##.M#: ./#M ,M #M ,#$" + .asciiz "##/ $## #+;#: #### ;#/ M M- @# :"; + .asciiz "#+ #M@MM###M-;M #:$#-##$H# .#X @ + $#. #"; + .asciiz " ######/.: #%=# M#:MM./#.-# @#: H#"; + .asciiz "+,.= @###: /@ %#,@ ##@X #,-#@.##% .@#"; + .asciiz "#####+;/##/ @## @#,+ /#M . X," + .asciiz " ;###M#@ M###H .#M- ,##M ;@@; ###"; + .asciiz " .M#M##H ;####X ,@#######M/ -M###$ -H"; + .asciiz " .M###% X####H .@@MM@; ;@#M@" + .asciiz " H#M /@####/ ,++. / ==-," + .asciiz " ,=/:, .+X@MMH@#H #####$="; + + diff --git a/still_alive/eightycol.inc b/still_alive/eightycol.inc new file mode 100644 index 00000000..6b6eb8ec --- /dev/null +++ b/still_alive/eightycol.inc @@ -0,0 +1,972 @@ +1 REM PORTAL CLOSING CREDITS APPLESOFT +2 REM BASED ON QBASIC VERSION BY Thomas Moss (spinneretsystems) +3 REM WORDS AND MUSIC BY JONATHAN COULTON +' +' Size Opt: Final Version = 20557 +' Move Line 20 to Line 8 = 20182 +' +5 TEXT:PRINT CHR$(4)+"PR#3": REM 80 COLUMN MODE +7 HOME:C$=CHR$(13):GOTO 50 +' +' SLOWTEXT +' +8 FOR C = 1 TO LEN(T$):PRINT MID$(T$, C, 1);:FOR I = 1 TO 1:NEXT I: NEXT C:POKE 768,F:POKE 769,D:CALL 770:RETURN +' +10 REM SET LEFT WINDOW +11 POKE 32,2:POKE 33,35:POKE 34,1:POKE 35,21 +12 RETURN +15 REM SET RIGHT WINDOW +16 POKE 32,39:POKE 33,40:POKE 34,1:POKE 35,23 +17 RETURN +' +' Restore Cursor +' +18 X=PEEK(1403):Y=PEEK(37):RETURN +19 POKE 36,X:POKE 37,Y-1:RETURN +' +30 REM FASTTEXT +31 FOR C = 1 TO LEN(T$) +32 PRINT MID$(T$, C, 1); +33 FOR I = 1 TO 25:NEXT I +34 NEXT C +35 RETURN +' +' Assembly Language audio routine +' See http://eightbitsoundandfury.ld8.org/programming.html +50 FOR L = 770 TO 790: READ V: POKE L,V: NEXT L +51 DATA 173,48,192,136,208,5,206,1,3,240,9,202,208,245,174,0,3,76,2,3,96 +55 PRINT " ------------------------------------ " +57 FOR I=1 TO 20: PRINT "| |":NEXT I +60 PRINT " ------------------------------------ " +65 GOSUB 10 +' +70 HOME +72 T$="Forms FORM-29827281-12:"+C$:GOSUB 30 +74 T$="Test Assessment Report"+C$:GOSUB 30 +76 PRINT:PRINT +78 FOR I=1 TO 1000: NEXT I +' +' This was a triumph. +' +80 T$="This ":D=54:F=85:GOSUB 8 +82 T$="was ":F=91:GOSUB 8 +84 T$="a ":F=102:GOSUB 8 +86 T$="tri":GOSUB 8 +89 T$="umph."+C$:F=91:GOSUB 8 +90 FOR I=1 TO 800:NEXT +' +' I'm making a note here: +' +94 T$="I'm ":F=152:GOSUB 8 +96 T$="ma":F=85:GOSUB 8 +98 T$="king ":F=91:GOSUB 8 +100 T$="a ":F=102:GOSUB 8 +102 T$="note ":D=108:F=102:GOSUB 8 +104 T$ = "here:"+C$:D=54:F=91:GOSUB 8 +105 FOR I=1 TO 160: NEXT +' +' HUGE SUCCESS. +' +106 T$ = "HUGE ":D=108:F=114:GOSUB 8 +108 T$ = "SUC":D=54:F=102:GOSUB 8 +110 T$ = "CESS."+C$:D=108:F=152:GOSUB 8 +111 FOR I=1 TO 480: NEXT +' +' It's hard to overstate +' +112 T$="It's ":D=54:F=152:GOSUB 8 +114 T$="hard ":D=108:F=102:GOSUB 8 +116 T$="to ":D=54:F=91:GOSUB 8 +118 T$="o":D=162:F=85:GOSUB 8 +120 T$="ver":D=54:F=91:GOSUB 8 +122 T$="state"+C$:D=108:F=121:GOSUB 8 +' +' my satisfaction. +' +124 T$="my ":D=162:F=114:GOSUB 8 +126 T$="sa":D=108:F=102:GOSUB 8 +128 T$="tis":D=54:F=152:GOSUB 8 +130 T$="fac":D=108:F=152:GOSUB 8 +132 T$="tion."+C$:F=91:GOSUB 8 +133 FOR I=1 TO 720:NEXT +' +' APERTURE SCIENCE LOGO +134 GOSUB 18:GOSUB 15:HOME:GOSUB 2000:GOSUB 10:GOSUB 19:PRINT +' +' Aperture Science +136 T$="A":D=54:F=85:GOSUB 8 +138 T$="per":F=91:GOSUB 8 +140 T$="ture ":F=102:GOSUB 8 +142 T$="Sci":GOSUB 8 +144 T$="ence"+C$:F=91:GOSUB 8 +145 FOR I=1 TO 800:NEXT +' +' We do what we must +' +146 T$="We ":F=152:GOSUB 8 +148 T$="do ":F=85:GOSUB 8 +150 T$="what ":F=91:GOSUB 8 +152 T$="we ":F=102:GOSUB 8 +154 T$="must"+C$:GOSUB 8 +155 FOR I=1 TO 160: NEXT +' +' because we can. +' +156 T$="be":F=91:GOSUB 8 +158 T$="cause ":F=114:GOSUB 8 +159 FOR I=1 TO 160: NEXT +160 T$="we ":F=102:GOSUB 8 +162 T$="can."+C$:D=162:F=152:GOSUB 8 +163 FOR I=1 TO 560: NEXT +' +' For the good of all of us. +' +164 T$="For ":D=108:F=102:GOSUB 8 +166 T$="the ":D=54:F=91:GOSUB 8 +168 T$="good ":D=162:F=85:GOSUB 8 +170 T$="of ":D=54:F=102:GOSUB 8 +172 T$="all ":D=162:F=121:GOSUB 8 +174 T$="of ":D=54:F=114:GOSUB 8 +176 T$="us."+C$:F=102:GOSUB 8 +'177 FOR I=1 TO 80: NEXT +' +' RADIATION +178 GOSUB 18:GOSUB 15:HOME:GOSUB 2100: GOSUB 10:GOSUB 19:PRINT +' +' Except the ones who are dead. +' +180 T$="Ex":F=152:GOSUB 8 +182 T$="cept ":F=114:GOSUB 8 +184 T$="the ":F=102:GOSUB 8 +186 T$="ones ":F=96:GOSUB 8 +188 T$="who ":F=102:GOSUB 8 +190 T$="are ":F=114:GOSUB 8 +192 T$="dead."+C$:F=128:GOSUB 8 +193 FOR I=1 TO 160: NEXT +' +' APERTURE SCIENCE LOGO +194 GOSUB 18:GOSUB 15:HOME:GOSUB 2000: GOSUB 10:GOSUB 19:PRINT +' +' But there's no sense crying\nover every mistake. +' +196 PRINT +198 T$="But ":F=152:GOSUB 8 +200 T$="there's ":F=143:GOSUB 8 +202 T$="no ":D=108:F=128:GOSUB 8 +204 T$="sense ":F=96:GOSUB 8 +206 T$="cry":D=54:F=102:GOSUB 8 +208 T$="ing"+C$:F=114:GOSUB 8 +210 T$="o":GOSUB 8 +212 T$="ver ":F=128:GOSUB 8 +214 T$="e":F=114:GOSUB 8 +216 T$="very ":F=128:GOSUB 8 +218 T$="mis":D=108:F=128:GOSUB 8 +220 T$="take."+C$:F=128:GOSUB 8 +' +' You just keep on trying\ntill you run out of cake. +' +222 T$="You ":D=54:F=152:GOSUB 8 +224 T$="just ":F=143:GOSUB 8 +226 T$="keep ":D=108:F=128:GOSUB 8 +228 T$="on ":F=96:GOSUB 8 +230 T$="try":D=54:F=85:GOSUB 8 +232 T$="ing"+C$:F=96:GOSUB 8 +234 T$="till ":F=102:GOSUB 8 +236 T$="you ":F=114:GOSUB 8 +238 T$="run ":GOSUB 8 +240 T$="out ":F=102:GOSUB 8 +242 T$="of ":D=108:F=96:GOSUB 8 +244 T$="cake."+C$:F=96:GOSUB 8 +' +' ATOM +' +246 GOSUB 18:GOSUB 15:HOME:GOSUB 2200: GOSUB 10:GOSUB 19:PRINT +' +' And the Science gets done. +' +248 T$="And ":D=54:F=85:GOSUB 8 +250 T$="the ":F=76:GOSUB 8 +252 T$="Sci":F=72:GOSUB 8 +254 T$="ence ":GOSUB 8 +256 T$="gets ":D=108:F=76:GOSUB 8 +258 T$="done."+C$:F=85:GOSUB 8 +' +' And you make a neat gun +' +260 T$="And ":D=54:F=96:GOSUB 8 +262 T$="you ":F=85:GOSUB 8 +264 T$="make ":F=76:GOSUB 8 +266 T$="a ":F=76:GOSUB 8 +268 T$="neat ":D=108:F=85:GOSUB 8 +270 T$="gun."+C$:F=96:GOSUB 8 +' +' APERTURE SCIENCE LOGO +272 GOSUB 18:GOSUB 15:HOME:GOSUB 2000: GOSUB 10:GOSUB 19:PRINT +' +' For the people who are +' +274 T$="For ":D=54:F=114:GOSUB 8 +276 T$="the ":F=128:GOSUB 8 +278 T$="peo":F=114:GOSUB 8 +280 T$="ple ":F=96:GOSUB 8 +282 T$="who ":GOSUB 8 +284 T$="are"+C$:D=108:F=102:GOSUB 8 +' +' still alive. +' +286 T$="still ":D=54:F=102:GOSUB 8 +288 T$="a":F=91:GOSUB 8 +290 T$="live."+C$:D=162:F=91:GOSUB 8 +291 FOR I=1 TO 1900: NEXT +' +' +' +292 HOME:C$=CHR$(13):X=FRE(0) +294 T$="Forms FORM-55551-5:"+C$:GOSUB 30 +296 T$="Personnel File Addendum:"+C$:GOSUB 30 +298 T$=C$+"Dear <>":GOSUB 30 +300 PRINT:PRINT +' +' I'm not even angry. +' +302 T$="I'm ":D=54:F=152:GOSUB 8 +304 T$="not ":F=85:GOSUB 8 +306 T$="e":F=91:GOSUB 8 +308 T$="ven ":F=102:GOSUB 8 +310 T$="an":GOSUB 8 +312 T$="gry."+C$:F=91:GOSUB 8 +313 FOR I=1 TO 800: NEXT +' +' I'm being so sincere right now. +' +314 T$="I'm ":F=85:GOSUB 8 +316 T$="be":F=91:GOSUB 8 +320 T$="ing ":F=102:GOSUB 8 +322 T$="so ":D=162:F=102:GOSUB 8 +324 T$="sin":D=54:F=91:GOSUB 8 +326 T$="cere ":D=108:F=114:GOSUB 8 +328 T$="right ":F=102:GOSUB 8 +330 T$="now."+C$:F=152:GOSUB 8 +331 FOR I=1 TO 560: NEXT +' +' Even though you broke my +' +332 T$="E":F=102:GOSUB 8 +334 T$="ven ":D=54:F=91:GOSUB 8 +336 T$="though ":D=162:F=85:GOSUB 8 +338 T$="you ":D=108:F=102:GOSUB 8 +340 T$="broke ":F=121:GOSUB 8 +342 T$="my ":D=54:F=114:GOSUB 8 +' +' HEART +344 GOSUB 18:GOSUB 15:HOME:GOSUB 2300: GOSUB 10:GOSUB 19:PRINT +345 POKE 36,X +' +' heart.\nAnd killed me. +' +346 T$="heart."+C$:D=162:F=102:GOSUB 8 +348 T$="And ":D=54:F=152:GOSUB 8 +350 T$="killed ":D=108:F=152:GOSUB 8 +352 T$="me."+C$:D=54:F=91:GOSUB 8 +353 FOR I=1 TO 720: NEXT +' +' EXPLOSION +' +354 GOSUB 18:GOSUB 15:HOME:GOSUB 2400: GOSUB 10:GOSUB 19:PRINT +' +' And tore me to pieces. +' +356 T$="And ":F=152:GOSUB 8 +358 T$="tore ":F=85:GOSUB 8 +360 T$="me ":F=91:GOSUB 8 +362 T$="to ":F=102:GOSUB 8 +364 T$="pie":GOSUB 8 +366 T$="ces."+C$:F=91:GOSUB 8 +367 FOR I=1 TO 800:NEXT +' +' And threw every peice into +' +368 T$="And ":F=152:GOSUB 8:REM SOUND 220, 4.8 +370 T$="threw ":F=85:GOSUB 8 +372 T$="ev":F=91:GOSUB 8 +374 T$="ery ":F=102:GOSUB 8 +376 T$="piece ":GOSUB 8 +377 FOR I=1 TO 160: NEXT +378 T$="in":F=91:GOSUB 8 +380 T$="to ":F=114:GOSUB 8 +'381 FOR I=1 TO 160: NEXT +' +' FIRE +382 GOSUB 18:GOSUB 15:HOME:GOSUB 2500: GOSUB 10:GOSUB 19:PRINT +383 POKE 36,X +' +' a fire. +' +384 T$="a ":F=102:GOSUB 8 +386 T$="fire."+C$:D=108:F=152:GOSUB 8 +387 FOR I=1 TO 560:NEXT +' +' As they burned it hurt because +' +388 T$="As ":F=102:GOSUB 8 +390 T$="they ":D=54:F=91:GOSUB 8 +392 T$="burned ":D=162:F=85:GOSUB 8 +394 T$="it ":D=108:F=102:GOSUB 8 +396 T$="hurt ":F=121:GOSUB 8 +398 T$="be":D=54:F=114:GOSUB 8 +400 T$="cause"+C$:F=102:GOSUB 8 +401 FOR I=1 TO 80: NEXT +' +' I was so happy for you! +' +402 T$="I ":F=152:GOSUB 8:REM SOUND 220, 4.8 +404 T$="was ":F=114:GOSUB 8:REM SOUND 293.6, 4.8 +406 T$="so ":F=102:GOSUB 8:REM SOUND 329.6, 4.8 +408 T$="hap":F=96:GOSUB 8:REM SOUND 349.2, 4.8 +410 T$="py ":F=102:GOSUB 8:REM SOUND 329.6, 4.8 +412 T$="for ":F=114:GOSUB 8:REM SOUND 293.6, 4.8 +414 T$="you!"+C$:F=128:GOSUB 8:REM SOUND 261.6, 14.4 +'415 FOR I=1 TO 160: NEXT +' +' CHECK +416 GOSUB 18:GOSUB 15:HOME:GOSUB 2600: GOSUB 10:GOSUB 19:PRINT +' +' Now these points of data\nmake a beautiful line. +' +418 T$="Now ":F=152:GOSUB 8 +420 T$="these ":F=143:GOSUB 8 +422 T$="points ":D=108:F=128:GOSUB 8 +424 T$="of ":F=96:GOSUB 8 +426 T$="da":D=54:F=102:GOSUB 8 +428 T$="ta"+C$:F=114:GOSUB 8 +430 T$="make ":GOSUB 8 +432 T$="a ":F=128:GOSUB 8 +434 T$="beau":F=114:GOSUB 8 +436 T$="ti":F=128:GOSUB 8 +438 T$="ful ":D=108:F=128:GOSUB 8 +440 T$="line."+C$:F=128:GOSUB 8 +' +' And we're out of beta.\nWe're releasing on time. +' +442 T$="And ":D=54:F=152:GOSUB 8 +444 T$="we're ":F=143:GOSUB 8 +446 T$="out ":D=108:F=128:GOSUB 8 +448 T$="of ":F=96:GOSUB 8 +450 T$="be":D=54:F=85:GOSUB 8 +452 T$="ta."+C$:F=96:GOSUB 8 +454 T$="We're ":F=102:GOSUB 8 +456 T$="re":F=114:GOSUB 8 +458 T$="lea":GOSUB 8 +460 T$="sing ":F=102:GOSUB 8 +462 T$="on ":D=108:F=96:GOSUB 8 +464 T$="time."+C$:F=96:GOSUB 8 +' +' EXPLOSION +466 GOSUB 18:GOSUB 15:HOME:GOSUB 2400: GOSUB 10:GOSUB 19:PRINT +' +' So I'm GLaD. I got burned. +' +468 T$="So ":D=54:F=85:GOSUB 8 +470 T$="I'm ":F=76:GOSUB 8 +472 T$="GLaD. ":F=72:GOSUB 8 +474 T$="I ":GOSUB 8 +476 T$="got ": D=108:F=76:GOSUB 8 +478 T$="burned."+C$:F=85:GOSUB 8 +' +' ATOM +' +480 GOSUB 18:GOSUB 15:HOME:GOSUB 2200: GOSUB 10:GOSUB 19:PRINT +' +' Think of all the things we learned +' +482 T$="Think ":D=54:F=96:GOSUB 8 +484 T$="of ":F=85:GOSUB 8 +486 T$="all ":F=76:GOSUB 8 +488 T$="the ":GOSUB 8 +490 T$="things ":F=85:GOSUB 8 +492 T$="we ":F=96:GOSUB 8 +494 T$="learned"+C$:D=108:F=96:GOSUB 8 +' +' APERTURE SCIENCE LOGO +' +496 GOSUB 18:GOSUB 15:HOME:GOSUB 2000: GOSUB 10:GOSUB 19:PRINT +' +' for the people who are +' +498 T$="for ":D=54:F=114:GOSUB 8 +500 T$="the ":F=128:GOSUB 8 +502 T$="peo":F=114:GOSUB 8 +504 T$="ple ":F=96:GOSUB 8 +506 T$="who ":GOSUB 8 +510 T$="are"+C$: D=108:F=102:GOSUB 8 +' +' still alive. +' +512 T$="still ":D=54:F=102:GOSUB 8 +' +' FIXME: CAN WE DO ALIVE SLOWLY LIKE IN THE VIDEO? +' +513 T$="a":F=91:GOSUB 8 +514 T$="live."+C$:D=162:F=91:GOSUB 8 +' +' PAGE 3 +' +516 HOME:C$=CHR$(13) +517 X=FRE(0) +518 T$="Forms FORM-55551-6:"+C$:GOSUB 30 +520 T$="Personnel File Addendum ":GOSUB 30 +522 T$="Addendum:"+C$:GOSUB 30 +523 PRINT +524 T$="One last thing:"+C$:GOSUB 30 +526 PRINT +' +' Go ahead and leave me +' +528 T$="Go ":D=54:F=85:GOSUB 8 +530 T$="a":D=27:F=91:GOSUB 8 +531 T$="head ":GOSUB 8 +532 T$="and ":D=54:F=102:GOSUB 8 +534 T$="leave ":D=108:F=102:GOSUB 8 +536 T$="me"+C$:D=54:F=91:GOSUB 8 +537 FOR I=1 TO 520:NEXT +' +' I think I prefer to stay inside. +' +538 T$="I ":F=152:GOSUB 8 +540 T$="think ":F=85:GOSUB 8 +542 T$="I ":F=91:GOSUB 8 +544 T$="pre":F=102:GOSUB 8 +546 T$="fer ":F=102:GOSUB 8 +547 FOR I=1 TO 160: NEXT +548 T$="to ":F=91:GOSUB 8 +550 T$="stay ":F=114:GOSUB 8 +551 FOR I=1 TO 160: NEXT +552 T$="in":F=102:GOSUB 8 +554 T$="side."+C$:D=108:F=152:GOSUB 8 +555 FOR I=1 TO 560: NEXT +' +' Maybe you'll find someone else +' +556 T$="May":F=102:GOSUB 8 +558 T$="be ":D=54:F=91:GOSUB 8 +560 T$="you'll ":D=162:F=85:GOSUB 8 +562 T$="find ":D=108:F=102:GOSUB 8 +564 T$="some":F=121:GOSUB 8 +566 T$="one ":D=54:F=114:GOSUB 8 +568 T$="else"+C$:D=162:F=102:GOSUB 8 +570 T$="to ":D=54:F=152:GOSUB 8 +572 T$="help ":D=108:F=152:GOSUB 8 +574 T$="you."+C$:D=54:F=91:GOSUB 8 +575 FOR I=1 TO 800:NEXT +' +' Black Mesa +' +576 GOSUB 18:GOSUB 15:HOME:GOSUB 2800: GOSUB 10:GOSUB 19:PRINT +' +' Maybe Black Mesa. +' +578 T$="May":F=85:GOSUB 8 +580 T$="be ":F=91:GOSUB 8 +582 T$="Black ":F=102:GOSUB 8 +584 T$="Me":D=108:F=102:GOSUB 8 +586 T$="sa.":D=54:F=91:GOSUB 8 +587 FOR I=1 TO 800:NEXT I +' +' THAT WAS A JOKE. +' +588 T$=".."+C$:GOSUB 30 +590 T$="THAT ":F=85:GOSUB 8 +591 T$="WAS ":F=91:GOSUB 8 +592 T$="A ":F=102:GOSUB 8 +593 T$="JOKE.":F=102:GOSUB 8 +594 FOR I=1 TO 160: NEXT +' +' HAHA +' +595 T$=" ":F=91:GOSUB 8 +596 T$=" ":F=114:GOSUB 8 +597 FOR I=1 TO 160: NEXT +' +' FAT CHANCE. +' +598 T$="FAT ":F=102:GOSUB 8 +600 T$="CHANCE."+C$:D=108:F=152:GOSUB 8 +601 FOR I=1 TO 560: NEXT +' +' Anyway, this cake is +' +602 T$="A":F=102:GOSUB 8 +604 T$="ny":D=54:F=91:GOSUB 8 +606 T$="way, ":D=162:F=85:GOSUB 8 +608 T$="this ":D=108:F=102:GOSUB 8 +610 T$="cake ":F=121:GOSUB 8 +612 T$="is ":D=54:F=114:GOSUB 8 +' +' CAKE +' +614 GOSUB 18:GOSUB 15:HOME:GOSUB 2900: GOSUB 10:GOSUB 19:PRINT +616 POKE 36,X +' +' great. +' +616 T$="great."+C$:F=102:GOSUB 8 +617 FOR I=1 TO 80: NEXT +' +' It's so delicious and moist. +' +618 T$="It's ":F=152:GOSUB 8 +620 T$="so ":F=114:GOSUB 8 +622 T$="de":F=102:GOSUB 8 +624 T$="li":F=96:GOSUB 8 +626 T$="cious ":F=102:GOSUB 8 +628 T$="and ":F=114:GOSUB 8 +630 T$="moist."+C$:F=128:GOSUB 8 +631 FOR I=1 TO 160: NEXT +' +' GLaDOS +' +632 GOSUB 18:GOSUB 15:HOME:GOSUB 3000: GOSUB 10:GOSUB 19:PRINT +' +' Look at me still talking. +' +634 T$="Look ":F=152:GOSUB 8 +636 T$="at ":F=143:GOSUB 8 +638 T$="me ":D=108:F=128:GOSUB 8 +640 T$="still ":F=96:GOSUB 8 +642 T$="tal":D=54:F=102:GOSUB 8 +644 T$="king"+C$:F=114:GOSUB 8 +' +' when there's +' +646 T$="when ":F=114:GOSUB 8 +648 T$="there's ":F=128:GOSUB 8 +' +' RADIATION +650 GOSUB 18:GOSUB 15:HOME:GOSUB 2100: GOSUB 10:GOSUB 19:PRINT +652 POKE 36,X +' +'Science to do. +' +654 T$="Sci":F=114:GOSUB 8 +656 T$="ence ":F=128:GOSUB 8 +658 T$="to ":D=108:F=128:GOSUB 8 +660 T$="do."+C$:F=128:GOSUB 8 +' +' APERTURE SCIENCE LOGO +' +662 GOSUB 18:GOSUB 15:HOME:GOSUB 2000: GOSUB 10:GOSUB 19:PRINT +' +' When I look out there +' +664 T$="When ":D=54:F=152:GOSUB 8 +666 T$="I ":F=143:GOSUB 8 +668 T$="look ":D=108:F=128:GOSUB 8 +670 T$="out ":F=96:GOSUB 8 +672 T$="there, "+C$:D=54:F=85:GOSUB 8 +' +' it makes me GLaD I'm not you."+C$ +' +674 T$="it ":F=96:GOSUB 8 +676 T$="Makes ":F=102:GOSUB 8 +678 T$="me ":F=114:GOSUB 8 +680 T$="GLaD ":F=114:GOSUB 8 +682 T$="I'm ":F=102:GOSUB 8 +684 T$="not ":D=108:F=96:GOSUB 8 +686 T$="you."+C$:F=96:GOSUB 8 +' +' ATOM +' +688 GOSUB 18:GOSUB 15:HOME:GOSUB 2200: GOSUB 10:GOSUB 19:PRINT +' +' I've experiments to run. +' +690 T$="I've ":D=54:F=85:GOSUB 8 +692 T$="ex":F=76:GOSUB 8 +694 T$="pe":F=72:GOSUB 8 +696 T$="ri":F=72:GOSUB 8 +698 T$="ments ":F=76:GOSUB 8 +700 T$="to ":F=85:GOSUB 8 +702 T$="run."+C$:D=108:F=85:GOSUB 8 +' +' EXPLOSION +' +704 GOSUB 18:GOSUB 15:HOME:GOSUB 2400: GOSUB 10:GOSUB 19:PRINT +' +' There is research to be done" +' +706 T$="There ":D=54:F=96:GOSUB 8 +708 T$="is ":F=85:GOSUB 8 +710 T$="re":F=76:GOSUB 8 +712 T$="search ":F=76:GOSUB 8 +714 T$="to ":F=85:GOSUB 8 +716 T$="be ":F=96:GOSUB 8 +718 T$="done."+C$:D=108:F=96:GOSUB 8 +' +' APERTURE SCIENCE LOGO +' +720 GOSUB 18:GOSUB 15:HOME:GOSUB 2000: GOSUB 10:GOSUB 19:PRINT +' +' On the people who are +' +722 T$="On ":D=54:F=114:GOSUB 8 +724 T$="the ":F=128:GOSUB 8 +726 T$="peo":F=114:GOSUB 8 +728 T$="ple ":F=96:GOSUB 8 +730 T$="who ":F=96:GOSUB 8 +732 T$="are"+C$:D=108:F=102:GOSUB 8 +' +' still alive. +' +734 T$="still ":D=54:F=102:GOSUB 8 +736 T$="a":F=91:GOSUB 8 +738 T$="live."+C$:D=162:F=91:GOSUB 8 +739 FOR I=1 TO 160: NEXT +' +' +' +740 HOME:PRINT:PRINT:PRINT +' +' PS: And believe me I am\nstill alive. +' +742 T$="PS: And ":D=54:F=76:GOSUB 8 +744 T$="be":F=76:GOSUB 8 +746 T$="lieve ":F=68:GOSUB 8 +748 T$="me ":F=76:GOSUB 8 +750 T$="I ":F=91:GOSUB 8 +752 T$="am"+C$:D=108:F=114:GOSUB 8 +754 T$="still ":D=54:F=102:GOSUB 8 +756 T$="a":F=91:GOSUB 8 +758 T$="live."+C$:D=162:F=91:GOSUB 8 +759 FOR I=1 TO 240:NEXT +' +' PPS: I'm doing Science and I'm\nstill alive. +' +760 T$="PPS: ":GOSUB 30 +762 T$="I'm ":D=54:F=76:GOSUB 8 +764 T$="do":F=76:GOSUB 8 +766 T$="ing ":F=76:GOSUB 8 +768 T$="Sci":F=68:GOSUB 8 +770 T$="ence ":F=76:GOSUB 8 +772 T$="and ":F=91:GOSUB 8 +774 T$="I'm"+C$:D=108:F=114:GOSUB 8 +776 T$="still ":D=54:F=102:GOSUB 8 +778 T$="a":F=91:GOSUB 8 +780 T$="live."+C$:D=162:F=91:GOSUB 8 +781 FOR I=1 TO 240:NEXT +' +' PPPS: I feel FANTASTIC and I'm\nstill alive +' +782 T$="PPPS: ":GOSUB 30 +784 T$="I ":D=54:F=76:GOSUB 8 +786 T$="feel ":F=76:GOSUB 8 +788 T$="FAN":F=76:GOSUB 8 +790 T$="TAS":F=68:GOSUB 8 +792 T$="TIC ":F=76:GOSUB 8 +794 T$="and ":F=91:GOSUB 8 +796 T$="I'm"+C$:D=108:F=114:GOSUB 8 +798 T$="still ":D=54:F=102:GOSUB 8 +800 T$="a":F=91:GOSUB 8 +802 T$="live."+C$:D=162:F=91:GOSUB 8 +803 FOR I=1 TO 320:NEXT +804 PRINT +' +' FINAL THOUGHT: +' +806 T$="FINAL THOUGHT:"+C$:GOSUB 30 +' +' While you're dying I'll be\nstill alive. +' +808 T$="While ":D=54:F=76:GOSUB 8 +810 T$="you're ":F=76:GOSUB 8 +812 T$="dy":F=68:GOSUB 8 +814 T$="ing ":F=76:GOSUB 8 +816 T$="I'll ":F=91:GOSUB 8 +818 T$="be"+C$:D=108:F=114:GOSUB 8 +820 T$="still ":D=54:F=102:GOSUB 8 +822 T$="a":F=91:GOSUB 8 +824 T$="live":D=162:F=91:GOSUB 8 +825 FOR I=1 TO 240:NEXT +' +' FINAL THOUGHT PS +' +826 T$=C$+C$+"FINAL THOUGHT PS:"+C$:GOSUB 30 +' +' And when you're dead I will be\nstill alive +' +828 T$="And ":D=54:F=76:GOSUB 8 +830 T$="when ":F=76:GOSUB 8 +832 T$="you're ":F=76:GOSUB 8 +834 T$="dead ":F=68:GOSUB 8 +836 T$="I ":F=76:GOSUB 8 +838 T$="will ":F=91:GOSUB 8 +840 T$="be"+C$:D=108:F=114:GOSUB 8 +842 T$="still ":D=54:F=102:GOSUB 8 +844 T$="a":F=91:GOSUB 8 +846 T$="live"+C$:D=162:F=91:GOSUB 8 +847 FOR I=1 TO 240:NEXT +' +' +' +848 PRINT:PRINT +' +' STILL ALIVE +' +850 T$="STILL ":D=54:F=85:GOSUB 8 +851 T$="A":F=76:GOSUB 8 +852 T$="LIVE":D=162:F=76:GOSUB 8 +853 FOR I=1 TO 240:NEXT +854 PRINT:PRINT +' +' STILL ALIVE +' +855 T$=" ":D=54:F=85:GOSUB 8 +856 T$=" ":F=91:GOSUB 8 +857 T$=" ":D=162:F=91:GOSUB 8 +858 FOR I=1 TO 240:NEXT +' +' +' +860 FOR I=1 TO 500:NEXT I +862 HOME +864 FOR I=1 TO 1000:NEXT I +866 T$="THANK YOU FOR PARTICIPATING"+C$:GOSUB 30 +868 T$="IN THIS"+C$:GOSUB 30 +870 T$="ENRICHMENT CENTER ACTIVITY!!"+C$:GOSUB 30 +872 PRINT:PRINT +874 FOR I=1 TO 3000: NEXT I +1000 PRINT CHR$(4)+"PR#0" +1001 TEXT:HOME +1999 END +' +' +' +2000 REM APERTURE +2001 PRINT " .,-:;//;:=," +2002 PRINT " . :H@@@MM@M#H/.,+%;," +2003 PRINT " ,/X+ +M@@M@MM%=,-%HMMM@X/," +2004 PRINT " -+@MM; $M@@MH+-,;XMMMM@MMMM@+-" +2005 PRINT " ;@M@@M- XM@X;. -+XXXXXHHH@M@M#@/." +2006 PRINT " ,%MM@@MH ,@%= .---=-=:=,." +2007 PRINT " =@#@@@MX ., -%HX$$%%%+;" +2008 PRINT " =-./@M@M$ .;@MMMM@MM:" +2009 PRINT " X@/ -$MM/ .+MM@@@M$" +2010 PRINT ",@M@H: :@: . =X#@@@@-"; +2011 PRINT ",@@@MMX, . /H- ;@M@M="; +2012 PRINT ".H@@@@M@+, %MM+..%#$."; +2013 PRINT " /MMMM@MMH/. XM@MH; =;" +2014 PRINT " /%+%$XHH@$= , .H@@@@MX," +2015 PRINT " .=--------. -%H.,@@@@@MX," +2016 PRINT " .%MM@@@HHHXX$$$%+- .:$MMX =M@@MM%." +2017 PRINT " =XMMM@MM@MM#H;,-+HMM@M+ /MMMX=" +2018 PRINT " =%@M@M#@$-.=$@MM@@@M; %M%=" +2019 PRINT " ,:+$+-,/H#MMMMMMM@= =," +2020 PRINT " =++%%%%+/:-." +2030 RETURN +' +2100 REM RADIOACTIVE +2101 PRINT " =+$HM####@H%;," +2102 PRINT " /H###############M$," +2103 PRINT " ,@################+" +2104 PRINT " .H##############+" +2105 PRINT " X############/" +2106 PRINT " $##########/" +2107 PRINT " %########/" +2108 PRINT " /X/;;+X/" +2109 PRINT +2110 PRINT " -XHHX-" +2111 PRINT " ,######," +2112 PRINT "#############X .M####M. X#############"; +2113 PRINT "##############- -//- -##############"; +2114 PRINT "X##############%, ,+##############X"; +2115 PRINT "-##############X X##############-"; +2116 PRINT " %############% %############%" +2117 PRINT " %##########; ;##########%" +2118 PRINT " ;#######M= =M#######;" +2119 PRINT " .+M###@, ,@###M+." +2120 PRINT " :XH. .HX:" +2130 RETURN +' +2200 REM ATOM +2201 PRINT " =/;;/-" +2202 PRINT " +: //" +2203 PRINT " /; /;" +2204 PRINT " -X H." +2205 PRINT ".//;;;:;;-, X= :+ .-;:=;:;%;."; +2206 PRINT "M- ,=;;;#:, ,:#;;:=, ,@"; +2207 PRINT ":% :%.=/++++/=.$= %="; +2208 PRINT " ,%; %/:+/;,,/++:+/ ;+." +2209 PRINT " ,+/. ,;@+, ,%H;, ,/+," +2210 PRINT " ;+;;/= @. .H##X -X :///+;" +2211 PRINT " ;+=;;;.@, .XM@$. =X.//;=%/." +2212 PRINT " ,;: :@%= =$H: .+%-" +2213 PRINT " ,%= %;-///==///-// =%," +2214 PRINT ";+ :%-;;;:;;;;-X- +:"; +2215 PRINT "@- .-;;;;M- =M/;;;-. -X"; +2216 PRINT " :;;::;;-. %- :+ ,-;;-;:==" +2217 PRINT " ,X H." +2218 PRINT " ;/ %=" +2219 PRINT " // +;" +2220 PRINT " ,////," +2230 RETURN +' +2300 REM BROKEN HEART +2301 PRINT " .,---." +2302 PRINT " ,/XM#MMMX;," +2303 PRINT " -%##########M%," +2304 PRINT " -@######% $###@=" +2305 PRINT " .,--, -H#######$ $###M:" +2306 PRINT " ,;$M###MMX; .;##########$;HM###X="; +2307 PRINT " ,/@##########H= ;################+"; +2308 PRINT "-+#############M/, %##############+"; +2309 PRINT "%M###############= /##############:"; +2310 PRINT "H################ .M#############;."; +2311 PRINT "@###############M ,@###########M:." +2312 PRINT "X################, -$=X#######@:" +2313 PRINT "/@##################%- +######$-" +2314 PRINT ".;##################X .X#####+," +2315 PRINT " .;H################/ -X####+." +2316 PRINT " ,;X##############, .MM/" +2317 PRINT " ,:+$H@M#######M#$- .$$=" +2318 PRINT " .,-=;+$@###X: ;/=." +2319 PRINT " .,/X$; .::," +2320 PRINT " ., .." +2330 RETURN +' +2400 REM EXPLOSION +2401 PRINT " .+" +2402 PRINT " /M;" +2403 PRINT " H#@: ;," +2404 PRINT " -###H- -@/" +2405 PRINT " %####$. -; .%#X" +2406 PRINT " M#####+;#H :M#M." +2407 PRINT ".. .+/;%#########X###-" +2408 PRINT " -/%H%+;-, +##############/" +2409 PRINT " .:$M###MH$%+############X ,--=;-" +2410 PRINT " -/H#####################H+=." +2411 PRINT " .+#################X." +2412 PRINT " =%M####################H;." +2413 PRINT " /@###############+;;/%%;," +2414 PRINT " -%###################$." +2415 PRINT " ;H######################M=" +2416 PRINT " ,%#####MH$%;+#####M###-/@####%" +2417 PRINT " :$H%+;=- -####X.,H# -+M##@-" +2418 PRINT " . ,###; ; =$##+" +2419 PRINT " .#H, :XH," +2420 PRINT " + .;-"; +2430 RETURN +' +2500 REM FIRE +2501 PRINT " -$-" +2502 PRINT " .H##H," +2503 PRINT " +######+" +2504 PRINT " .+#########H." +2505 PRINT " -$############@." +2506 PRINT " =H###############@ -X:" +2507 PRINT " .$##################: @#@-" +2508 PRINT " ,; .M###################; H###;" +2509 PRINT " ;@#: @###################@ ,#####:" +2510 PRINT " -M###. M#################@. ;######H" +2511 PRINT " M####- +###############$ =@#######X" +2512 PRINT " H####$ -M###########+ :#########M," +2513 PRINT " /####X- =########% :M########@/." +2514 PRINT " ,;%H@X; .$###X :##MM@%+;:-" +2515 PRINT " .." +2516 PRINT " -/;:-,. ,,-==+M########H" +2517 PRINT " -##################@HX%%+%%$%%%+:,," +2518 PRINT " .-/H%%%+%%$H@###############M@+=:/+:"; +2519 PRINT "/XHX%:#####MH%= ,---:;;;;/%%XHM,:###$"; +2520 PRINT "$@#MX %+;- ." +2530 RETURN +' +2600 REM CHECK +2601 PRINT " :X-"; +2602 PRINT " :X###" +2603 PRINT " ;@####@" +2604 PRINT " ;M######X" +2605 PRINT " -@########$" +2606 PRINT " .$##########@" +2607 PRINT " =M############-"; +2608 PRINT " +##############$"; +2609 PRINT " .H############$=." +2610 PRINT " ,/: ,M##########M;." +2611 PRINT " -+@###; =##########M;" +2612 PRINT " =%M#######; :#########M/" +2613 PRINT "-$M###########; :#########/" +2614 PRINT " ,;X###########; =########$." +2615 PRINT " ;H#########+#######M=" +2616 PRINT " ,+##############+" +2617 PRINT " /M#########@-" +2618 PRINT " ;M######%" +2619 PRINT " +####:" +2620 PRINT " ,$M-" +2630 RETURN +' +2800 REM BLACK MESA +2801 PRINT " .-;+$XHHHHHHX$+;-." +2802 PRINT " ,;X@@X%/;=----=:/%X@@X/," +2803 PRINT " =$@@%=. .=+H@X:" +2804 PRINT " -XMX: =XMX=" +2805 PRINT " /@@: =H@+" +2806 PRINT " %@X, .$@$" +2807 PRINT " +@X. $@%" +2808 PRINT "-@@, .@@="; +2809 PRINT "%@% +@$"; +2810 PRINT "H@: :@H"; +2811 PRINT "H@: :HHHHHHHHHHHHHHHHHHX, =@H"; +2812 PRINT "%@% ;@M@@@@@@@@@@@@@@@@@H- +@$"; +2813 PRINT "=@@, :@@@@@@@@@@@@@@@@@@@@@= .@@:"; +2814 PRINT " +@X :@@@@@@@@@@@@@@@M@@@@@@:%@%" +2815 PRINT " $@$, ;@@@@@@@@@@@@@@@@@M@@@@@@$." +2816 PRINT " +@@HHHHHHH@@@@@@@@@@@@@@@@@@@@@@@+" +2817 PRINT " =X@@@@@@@@@@@@@@@@@@@@@@@@@@@@X=" +2818 PRINT " :$@@@@@@@@@@@@@@@@@@@M@@@@$:" +2819 PRINT " ,;$@@@@@@@@@@@@@@@@@@X/-" +2820 PRINT " .-;+$XXHHHHHX$+;-." +2830 RETURN +' +2900 REM CAKE DELICIOUS AND MOIST +2901 PRINT " ,:/+/-" +2902 PRINT " /M/ .,-=;//;-" +2903 PRINT " .:/= ;MH/, ,=/+%$XH@MM#@:" +2904 PRINT " -$##@+$###@H@MMM#######H:. -/H#"; +2905 PRINT " .,H@H@ X######@ -H#####@+- -+H###@X"; +2906 PRINT " .,@##H; +XM##M/, =%@###@X;-" +2907 PRINT "X%- :M##########$. .:%M###@%:" +2908 PRINT "M##H, +H@@@$/-. ,;$M###@%, -"; +2909 PRINT "M####M=,,---,.-%%H####M$: ,+@##"; +2910 PRINT "@##################@/. :%H##@$-" +2911 PRINT "M###############H, ;HM##M$=" +2912 PRINT "#################. .=$M##M$=" +2913 PRINT "################H..;XM##M$= .:+"; +2914 PRINT "M###################@%= =+@MH%"; +2915 PRINT "@################M/. =+H#X%=" +2916 PRINT "=+M##############M, -/X#X+;." +2917 PRINT " .;XM##########H= ,/X#H+:," +2918 PRINT " .=+HM######M+/+HM@+=." +2919 PRINT " ,:/%XM####H/." +2920 PRINT " ,.:=-." +2930 RETURN +' +3000 REM GLaDOS +3001 PRINT " #+ @ # # M#@" +3002 PRINT " . .X X.%##@;# # +@#######X. @#%" +3003 PRINT " ,==. ,######M+ -#####%M####M- #"; +3004 PRINT " :H##M%:=##+ .M##M,;#####/+#######% ,M#"; +3005 PRINT " .M########= =@#@.=#####M=M#######= X#"; +3006 PRINT " :@@MMM##M. -##M.,#######M#######. = M"; +3007 PRINT " @##..###:. .H####. @@ X,"; +3008 PRINT " ############: ###,/####; /##= @#. M" +3009 PRINT " ,M## ;##,@#M;/M#M @# X#% X#" +3010 PRINT ".%= ######M## ##.M#: ./#M ,M #M ,#$" +3011 PRINT "##/ $## #+;#: #### ;#/ M M- @# :"; +3012 PRINT "#+ #M@MM###M-;M #:$#-##$H# .#X @ + $#. #"; +3013 PRINT " ######/.: #%=# M#:MM./#.-# @#: H#"; +3014 PRINT "+,.= @###: /@ %#,@ ##@X #,-#@.##% .@#"; +3015 PRINT "#####+;/##/ @## @#,+ /#M . X," +3016 PRINT " ;###M#@ M###H .#M- ,##M ;@@; ###"; +3017 PRINT " .M#M##H ;####X ,@#######M/ -M###$ -H"; +3018 PRINT " .M###% X####H .@@MM@; ;@#M@" +3019 PRINT " H#M /@####/ ,++. / ==-," +3020 PRINT " ,=/:, .+X@MMH@#H #####$="; +3030 RETURN + diff --git a/still_alive/interrupt_handler.s b/still_alive/interrupt_handler.s new file mode 100644 index 00000000..f18a91fd --- /dev/null +++ b/still_alive/interrupt_handler.s @@ -0,0 +1,345 @@ + ;================================ + ;================================ + ; mockingboard interrupt handler + ;================================ + ;================================ + ; On Apple II/6502 the interrupt handler jumps to address in 0xfffe + ; This is in the ROM, which saves the registers + ; on older IIe it saved A to $45 (which could mess with DISK II) + ; newer IIe doesn't do that. + ; It then calculates if it is a BRK or not (which trashes A) + ; Then it sets up the stack like an interrupt and calls 0x3fe + +TIME_OFFSET EQU 13 + +interrupt_handler: + pha ; save A ; 3 + ; Should we save X and Y too? + +; inc $0404 ; debug (flashes char onscreen) + + bit $C404 ; clear 6522 interrupt by reading T1C-L ; 4 + + + lda DONE_PLAYING ; 3 + beq mb_play_music ; if song done, don't play music ; 3/2nt + jmp check_keyboard ; 3 + ;============ + ; 13 + +mb_play_music: + + + ;====================================== + ; Write frames to Mockingboard + ;====================================== + ; actually plays frame loaded at end of + ; last interrupt, so 20ms behind? + +mb_write_frame: + + + ldx #0 ; set up reg count ; 2 + ;============ + ; 2 + + ;================================== + ; loop through the 14 registers + ; reading the value, then write out + ;================================== + ; inlined "write_ay_both" to save up to 156 (12*13) cycles + ; unrolled + +mb_write_loop: + lda REGISTER_DUMP,X ; load register value ; 4 + cmp REGISTER_OLD,X ; compare with old values ; 4 + beq mb_no_write ; 3/2nt + ;============= + ; typ 11 + + ; special case R13. If it is 0xff, then don't update + ; otherwise might spuriously reset the envelope settings + + cpx #13 ; 2 + bne mb_not_13 ; 3/2nt + cmp #$ff ; 2 + beq mb_skip_13 ; 3/2nt + ;============ + ; typ 5 +mb_not_13: + + ; address + stx MOCK_6522_ORA1 ; put address on PA1 ; 4 + stx MOCK_6522_ORA2 ; put address on PA2 ; 4 + lda #MOCK_AY_LATCH_ADDR ; latch_address for PB1 ; 2 + sta MOCK_6522_ORB1 ; latch_address on PB1 ; 4 + sta MOCK_6522_ORB2 ; latch_address on PB2 ; 4 + lda #MOCK_AY_INACTIVE ; go inactive ; 2 + sta MOCK_6522_ORB1 ; 4 + sta MOCK_6522_ORB2 ; 4 + + ; value + lda REGISTER_DUMP,X ; load register value ; 4 + sta MOCK_6522_ORA1 ; put value on PA1 ; 4 + sta MOCK_6522_ORA2 ; put value on PA2 ; 4 + lda #MOCK_AY_WRITE ; ; 2 + sta MOCK_6522_ORB1 ; write on PB1 ; 4 + sta MOCK_6522_ORB2 ; write on PB2 ; 4 + lda #MOCK_AY_INACTIVE ; go inactive ; 2 + sta MOCK_6522_ORB1 ; 4 + sta MOCK_6522_ORB2 ; 4 + + ;=========== + ; 62 +mb_no_write: + inx ; point to next register ; 2 + cpx #14 ; if 14 we're done ; 2 + bmi mb_write_loop ; otherwise, loop ; 3/2nt + ;============ + ; 7 +mb_skip_13: + + + ;===================================== + ; Copy registers to old + ;===================================== + ldx #13 ; 2 +mb_reg_copy: + lda REGISTER_DUMP,X ; load register value ; 4 + sta REGISTER_OLD,X ; compare with old values ; 4 + dex ; 2 + bpl mb_reg_copy ; 2nt/3 + ;============= + ; 171 + + ;=================================== + ; Load all 14 registers in advance + ;=================================== + ; note, assuming not cross page boundary, not any slower + ; then loading from zero page? + +mb_load_values: + + ldx #0 ; set up reg count ; 2 + ldy MB_CHUNK_OFFSET ; get chunk offset ; 3 + ;============= + ; 5 + +mb_load_loop: + lda (INL),y ; load register value ; 5 + sta REGISTER_DUMP,X ; 4 + ;============ + ; 9 + ;==================== + ; point to next page + ;==================== + + clc ; point to next interleaved ; 2 + lda INH ; page by adding CHUNKSIZE (3/1); 3 + adc CHUNKSIZE ; 3 + sta INH ; 3 + + inx ; point to next register ; 2 + cpx #14 ; if 14 we're done ; 2 + bmi mb_load_loop ; otherwise, loop ; 3/2nt + ;============ + ; 18 + + ;========================================= + ; if A_COARSE_TONE is $ff then we are done + + lda A_COARSE_TONE ; 3 + bpl mb_not_done ; 3/2nt + + lda #1 ; set done playing ; 2 + + jmp quiet_exit ; 3 + ;=========== + ; typ 6 +mb_not_done: + + ;============================================== + ; incremement offset. If 0 move to next chunk + ;============================================== + +increment_offset: + + inc MB_CHUNK_OFFSET ; increment offset ; 5 + bne back_to_first_reg ; if not zero, done ; 3/2nt + + + ;===================== + ; move to next state + ;===================== + + clc + rol DECODER_STATE ; next state ; 5 + ; 20 -> 40 -> 80 -> c+00 + bcs wraparound_to_a ; 3/2nt + + bit DECODER_STATE ;bit7->N bit6->V + bvs back_to_first_reg ; do nothing on B ; 3/2nt + +start_c: + lda #1 + sta CHUNKSIZE + + ; setup next three chunks of song + + lda #1 ; start decompressing + sta DECOMPRESS_TIME ; outside of handler + + jmp back_to_first_reg + +wraparound_to_a: + lda #$3 + sta CHUNKSIZE + lda #$20 + sta DECODER_STATE + sta COPY_TIME ; start copying + + lda DECOMPRESS_TIME + beq blah + lda #1 + sta DECODE_ERROR +blah: + ;============================== + ; After 14th reg, reset back to + ; read R0 data + ;============================== + +back_to_first_reg: + lda #0 ; 2 + bit DECODER_STATE ; 3 + bmi back_to_first_reg_c ; 2nt/3 + bvc back_to_first_reg_a ; 2nt/3 + +back_to_first_reg_b: + lda #$1 ; offset by 1 + +back_to_first_reg_a: + clc ; 2 + adc #>UNPACK_BUFFER ; in proper chunk 1 or 2 ; 2 + + jmp update_r0_pointer ; 3 + +back_to_first_reg_c: + lda #>(UNPACK_BUFFER+$2A00) ; in linear C area ; 2 + +update_r0_pointer: + sta INH ; update r0 pointer ; 3 + + + + ;================================= + ; Finally done with this interrupt + ;================================= + +done_interrupt: + + + ;===================== + ; Update time counter + ;===================== +update_time: + inc FRAME_COUNT ; 5 + lda FRAME_COUNT ; 3 + cmp #50 ; 3 + bne done_time ; 3/2nt + + lda #$0 ; 2 + sta FRAME_COUNT ; 3 + +update_second_ones: + inc $7d0+TIME_OFFSET+3 ; 6 + inc $bd0+TIME_OFFSET+3 ; 6 + lda $bd0+TIME_OFFSET+3 ; 4 + cmp #$ba ; one past '9' ; 2 + bne done_time ; 3/2nt + lda #'0'+$80 ; 2 + sta $7d0+TIME_OFFSET+3 ; 4 + sta $bd0+TIME_OFFSET+3 ; 4 +update_second_tens: + inc $7d0+TIME_OFFSET+2 ; 6 + inc $bd0+TIME_OFFSET+2 ; 6 + lda $bd0+TIME_OFFSET+2 ; 4 + cmp #$b6 ; 6 (for 60 seconds) ; 2 + bne done_time ; 3/2nt + lda #'0'+$80 ; 2 + sta $7d0+TIME_OFFSET+2 ; 4 + sta $bd0+TIME_OFFSET+2 ; 4 +update_minutes: + inc $7d0+TIME_OFFSET ; 6 + inc $bd0+TIME_OFFSET ; 6 + ; we don't handle > 9:59 songs yet +done_time: + ;============= + ; 90 worst + + + ;================================= + ; Moved visualization here as a hack + ;================================= + + ;============================ + ; Visualization + ;============================ + +check_keyboard: + + jsr get_key + lda LASTKEY + beq exit_interrupt + + cmp #(' '+$80) + bne key_left +key_space: + lda #$80 + eor DONE_PLAYING + jmp quiet_exit + +key_left: + cmp #'A' + bne key_right + + lda #$40 + bne quiet_exit + +key_right: + cmp #'D' + bne done_key + + lda #$20 + bne quiet_exit + +done_key: + jmp exit_interrupt + +quiet_exit: + sta DONE_PLAYING + jsr clear_ay_both + + ;===================================== + ; clear register area + ;===================================== + ldx #13 ; 2 + lda #0 ; 2 +mb_clear_reg: + sta REGISTER_DUMP,X ; clear register value ; 4 + sta REGISTER_OLD,X ; clear old values ; 4 + dex ; 2 + bpl mb_clear_reg ; 2nt/3 + +exit_interrupt: + + pla ; restore a ; 4 + + rti ; return from interrupt ; 6 + + ;============ + ; typical + ; ???? cycles + + +REGISTER_OLD: + .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0 diff --git a/still_alive/still_alive.dsk b/still_alive/still_alive.dsk new file mode 100644 index 00000000..6a2f45f3 Binary files /dev/null and b/still_alive/still_alive.dsk differ diff --git a/still_alive/still_alive.s b/still_alive/still_alive.s new file mode 100644 index 00000000..6cf1d57d --- /dev/null +++ b/still_alive/still_alive.s @@ -0,0 +1,558 @@ +; And Believe Me, I'm Still Alive + +.include "zp.inc" + ; program is ~4k, so from 0xc00 to 0x1C00 +LZ4_BUFFER EQU $1C00 ; $1C00 - $5C00, 16k for now +UNPACK_BUFFER EQU $5E00 ; $5E00 - $9600, 14k, $3800 + ; trying not to hit DOS at $9600 + ; Reserve 3 chunks plus spare (14k) + +NUM_FILES EQU 15 + + ;============================= + ; Setup + ;============================= + jsr HOME + jsr TEXT + + ; init variables + + lda #0 + sta DRAW_PAGE + sta CH + sta CV + sta DONE_PLAYING + sta XPOS + sta MB_CHUNK_OFFSET + sta DECODE_ERROR + + + lda #0 + sta WHICH_FILE + + ; print detection message + + lda #mocking_message + sta OUTH + jsr move_and_print ; print it + + jsr mockingboard_detect_slot4 ; call detection routine + cpx #$1 + beq mockingboard_found + + lda #not_message + sta OUTH + inc CV + jsr move_and_print + + jmp forever_loop ; and wait forever + +mockingboard_found: +; lda #found_message +; sta OUTH +; inc CV +; jsr move_and_print + + ;============================ + ; Init the Mockingboard + ;============================ + + jsr mockingboard_init + jsr reset_ay_both + jsr clear_ay_both + + ;========================= + ; Setup Interrupt Handler + ;========================= + ; Vector address goes to 0x3fe/0x3ff + ; FIXME: should chain any existing handler + + lda #interrupt_handler + sta $03ff + + ;============================ + ; Enable 50Hz clock on 6522 + ;============================ + + sei ; disable interrupts just in case + + lda #$40 ; Continuous interrupts, don't touch PB7 + sta $C40B ; ACR register + lda #$7F ; clear all interrupt flags + sta $C40E ; IER register (interrupt enable) + + lda #$C0 + sta $C40D ; IFR: 1100, enable interrupt on timer one oflow + sta $C40E ; IER: 1100, enable timer one interrupt + + lda #$E7 + sta $C404 ; write into low-order latch + lda #$4f + sta $C405 ; write into high-order latch, + ; load both values into counter + ; clear interrupt and start counting + + ; 4fe7 / 1e6 = .020s, 50Hz + + + ;============================ + ; Draw title screen + ;============================ + + lda #$4 ; draw page 1 + sta DRAW_PAGE + + jsr clear_screens ; clear both screens + + + ;================== + ; load first song + ;================== + + jsr new_song + + ;============================ + ; Init Background + ;============================ + + ;============================ + ; Enable 6502 interrupts + ;============================ + + cli ; clear interrupt mask + + + ;============================ + ; Loop forever + ;============================ +main_loop: + lda DECODE_ERROR + beq check_copy + sei + brk + +check_copy: + lda COPY_TIME + beq check_decompress ; if zero, skip + + lda #0 + sta COPY_OFFSET +check_copy_loop: + jsr page_copy ;6+3621 + + inc COPY_OFFSET ; (opt: make subtract?) ; 5 + + lda #14 ; NOT HEX URGH! + cmp COPY_OFFSET + bne check_copy_loop + + lda #0 ; we are done + sta COPY_TIME + +check_decompress: + lda DECOMPRESS_TIME + beq check_done ; if zero, skip + + jsr setup_next_subsong ; decompress + + lda MB_CHUNK_OFFSET + sta TIME_TAKEN + + lda #0 + sta DECOMPRESS_TIME + + +check_done: + lda #$ff + bit DONE_PLAYING + beq main_loop ; if was all zeros, loop + bmi main_loop ; if high bit set, paused + bvs minus_song ; if bit 6 set, then left pressed + + ; else, either song finished or + ; right pressed + +plus_song: + sei ; disable interrupts + jsr increment_file + jmp done_play + +minus_song: + sei ; disable interrupts + jsr decrement_file + +done_play: + + lda #0 + sta DONE_PLAYING + + lda #0 + sta CH + + jsr clear_bottoms + + jsr new_song + + cli ; re-enable interrupts + + jmp main_loop + +forever_loop: + jmp forever_loop + + + + ;================= + ; load a new song + ;================= + +new_song: + + ;========================= + ; Init Variables + ;========================= + + lda #$0 + sta FRAME_COUNT + sta A_VOLUME + sta B_VOLUME + sta C_VOLUME + sta COPY_OFFSET + sta DECOMPRESS_TIME + sta COPY_TIME + sta MB_CHUNK_OFFSET + lda #$20 + sta DECODER_STATE + lda #3 + sta CHUNKSIZE + + ;=========================== + ; Print loading message + ;=========================== + + jsr clear_bottoms ; clear bottom of page 0/1 + + lda #0 ; print LOADING message + sta CH + lda #21 + sta CV + + lda #loading_message + sta OUTH + jsr print_both_pages + + + ;=========================== + ; Load in KRW file + ;=========================== + + jsr get_filename + + lda #8 + sta CH + lda #21 + sta CV + + lda INL + sta OUTL + lda INH + sta OUTH + jsr print_both_pages + +disk_buff EQU LZ4_BUFFER +read_size EQU $4000 + + jsr read_file ; read KRW file from disk + + + ;========================= + ; Print Info + ;========================= + + jsr clear_bottoms ; clear bottom of page 0/1 + + lda #>LZ4_BUFFER ; point to LZ4 data + sta OUTH + lda #' + sta $777 + sta $B77 + + + + + + ; Point LZ4 src at proper place + + ldy #0 + lda #>(LZ4_BUFFER+3) + sta LZ4_SRC+1 + lda #<(LZ4_BUFFER+3) + sta LZ4_SRC + + lda (LZ4_SRC),Y ; get header skip + clc + adc LZ4_SRC + sta LZ4_SRC + lda LZ4_SRC+1 + adc #0 + sta LZ4_SRC+1 + + lda #UNPACK_BUFFER + sta INH + + ; Decompress first chunks + + lda #$0 + sta COPY_OFFSET + sta DECOMPRESS_TIME + lda #$3 + sta CHUNKSIZE + lda #$20 + sta DECODER_STATE + sta COPY_TIME + + jsr setup_next_subsong + + rts + + ;================= + ; next sub-song + ;================= +setup_next_subsong: + + ldy #0 + + lda (LZ4_SRC),Y ; get next size value + sta LZ4_END + iny + lda (LZ4_SRC),Y + sta LZ4_END+1 + + lda #2 ; increment pointer + clc + adc LZ4_SRC + sta LZ4_SRC + lda LZ4_SRC+1 + adc #0 + sta LZ4_SRC+1 + + jsr lz4_decode ; decode + + ; tail-call? + + rts + + + + ;=================== + ; print header info + ;=================== + ; shortcut to print header info + ; a = VTAB + +print_header_info: + + sta CV + + iny ; adjust pointer + tya + ldy #0 + clc + adc OUTL + sta OUTL + lda OUTH + adc #$0 + sta OUTH + + lda (OUTL),Y ; get HTAB value + sta CH + + inc OUTL ; increment 16-bits + bne bloop22 + inc OUTH +bloop22: + + jmp print_both_pages ; print, tail call + + + ;============================================== + ; plan: takes 256 50Hz to play a chunk + ; need to copy 14 256-byte blocks + ; PLAY A (copying C) + ; PLAY B (copying C) + ; PLAY D (decompressing A/B/C) + + + ;======================== + ; page copy + ;======================== + ; want to copy: + ; SRC: chunk_buffer+(2*256)+(COPY_OFFSET*3*256) + ; DST: chunk_buffer+$2A00+(COPY_OFFSET*256) +page_copy: + clc ; 2 + lda #>(UNPACK_BUFFER+512) ; 3 + adc COPY_OFFSET ; 3 + adc COPY_OFFSET ; 3 + adc COPY_OFFSET ; 3 + sta page_copy_loop+2 ; self modify ; 5 + + lda #>(UNPACK_BUFFER+$2A00) ; 2 + adc COPY_OFFSET ; 3 + sta page_copy_loop+5 ; self modify ; 5 + + ldx #$00 ; 2 +page_copy_loop: + lda $1000,x ; 4 + sta $1000,X ; 5 + inx ; 2 + bne page_copy_loop ; 2nt/3 + rts ; 6 + ;====================== + ; 2+14*256+6+29= 3621 + + + ;================== + ; Get filename + ;================== + ; WHICH_FILE holds number + ; MAX_FILES has max + ; Scroll through until find + ; point INH:INL to it +get_filename: + + ldy #0 + ldx WHICH_FILE + + lda #krw_file + sta INH + +get_filename_loop: + cpx #0 + beq filename_found + +inner_loop: + iny + lda (INL),Y + bne inner_loop + + iny + + dex + jmp get_filename_loop + +filename_found: + tya + clc + adc INL + sta INL + lda INH + adc #0 + sta INH + + rts + + ;=============================== + ; Increment file we want to load + ;=============================== +increment_file: + inc WHICH_FILE + lda WHICH_FILE + cmp #NUM_FILES + bne done_increment + lda #0 + sta WHICH_FILE +done_increment: + rts + + ;=============================== + ; Decrement file we want to load + ;=============================== +decrement_file: + dec WHICH_FILE + bpl done_decrement + lda #(NUM_FILES-1) + sta WHICH_FILE +done_decrement: + rts + +;========== +; filenames +;========== +krw_file: + .asciiz "SA.KRW" + + + + +;========= +;routines +;========= +.include "../asm_routines/gr_offsets.s" +.include "../asm_routines/text_print.s" +.include "../asm_routines/mockingboard_a.s" +.include "../asm_routines/gr_fast_clear.s" +.include "../asm_routines/pageflip.s" +.include "../asm_routines/gr_setpage.s" +.include "../asm_routines/dos33_routines.s" +.include "../asm_routines/gr_hlin.s" +.include "../asm_routines/lz4_decode.s" +.include "../asm_routines/keypress_minimal.s" + +.include "interrupt_handler.s" + +;========= +; strings +;========= +mocking_message: .asciiz "LOOKING FOR MOCKINGBOARD IN SLOT #4" +not_message: .byte "NOT " +found_message: .asciiz "FOUND" +;done_message: .asciiz "DONE PLAYING" +loading_message: .asciiz "LOADING" + +.include "ascii_art.inc" diff --git a/still_alive/zp.inc b/still_alive/zp.inc new file mode 100644 index 00000000..fff64073 --- /dev/null +++ b/still_alive/zp.inc @@ -0,0 +1,251 @@ +.define EQU = + +LZ4_SRC EQU $00 +LZ4_DST EQU $02 +LZ4_END EQU $04 +COUNT EQU $06 +DELTA EQU $08 + +;; Zero page monitor routines addresses + +WNDLFT EQU $20 +WNDWDTH EQU $21 +WNDTOP EQU $22 +WNDBTM EQU $23 +CH EQU $24 +CV EQU $25 +GBASL EQU $26 +GBASH EQU $27 +BASL EQU $28 +BASH EQU $29 +H2 EQU $2C +V2 EQU $2D +MASK EQU $2E +COLOR EQU $30 + ;INVFLG EQU $32 + +; dos33 zero page = 26-2f, 35-38, 3e 3f 40-4d +; overlap applesoft 67-6a,6f,70,af,b0,ca-cd,d8 + + +; DOS33: Confirmed kills $68 + +RWTSL EQU $60 +RWTSH EQU $61 +DOSBUFL EQU $62 +DOSBUFH EQU $63 +FILEML EQU $64 +FILEMH EQU $65 + ;TURNING EQU $60 + ;SCREEN_X EQU $61 ; not used? + ;SCREEN_Y EQU $62 + + + ;ANGLE EQU $63 + ;HORIZ_SCALE_I EQU $64 + ;HORIZ_SCALE_F EQU $65 + ;FACTOR_I EQU $66 + ;FACTOR_F EQU $67 + ;DX_I EQU $68 + ;DX_F EQU $69 + ;SPACEX_I EQU $6A + ;SPACEX_F EQU $6B + ;CX_I EQU $6C + ;CX_F EQU $6D + ;DY_I EQU $6E + ;DY_F EQU $6F + +REGISTER_DUMP EQU $70 +A_FINE_TONE EQU $70 +A_COARSE_TONE EQU $71 +B_FINE_TONE EQU $72 +B_COARSE_TONE EQU $73 +C_FINE_TONE EQU $74 +C_COARSE_TONE EQU $75 +NOISE EQU $76 +ENABLE EQU $77 +A_VOLUME EQU $78 +B_VOLUME EQU $79 +C_VOLUME EQU $7A +ENVELOPE_FINE EQU $7B +ENVELOPE_COARSE EQU $7C +ENVELOPE_SHAPE EQU $7D +COPY_OFFSET EQU $7E +DECODER_STATE EQU $7F + ;SPACEY_I EQU $70 + ;SPACEY_F EQU $71 + ;CY_I EQU $72 + ;CY_F EQU $73 + ;TEMP_I EQU $74 + ;TEMP_F EQU $75 + ;DISTANCE_I EQU $76 + ;DISTANCE_F EQU $77 + ;SPACEZ_I EQU $78 + ;SPACEZ_F EQU $79 + ;DRAW_SPLASH EQU $7A + ;SPEED EQU $7B + ;SPLASH_COUNT EQU $7C + ;OVER_LAND EQU $7D + ;NUM1L EQU $7E + ;NUM1H EQU $7F +CHUNKSIZE EQU $80 +LZ4_DONE EQU $81 +DECODE_ERROR EQU $82 + +A_COLOR EQU $83 +B_COLOR EQU $84 +C_COLOR EQU $85 +COPY_TIME EQU $86 +DECOMPRESS_TIME EQU $87 +TIME_TAKEN EQU $88 +SCREEN_Y EQU $89 +WHICH_FILE EQU $8A + ;NUM2L EQU $80 + ;NUM2H EQU $81 + ;RESULT EQU $82 ; 83,84,85 + ;NEGATE EQU $86 ; UNUSED? + ;LAST_SPACEX_I EQU $87 + ;LAST_SPACEY_I EQU $88 + ;LAST_MAP_COLOR EQU $89 + ;DRAW_SKY EQU $8A +COLOR_MASK EQU $8B +RASTERBARS_ON EQU $8C + ;KEY_COUNT EQU $8C + ;KEY_OFFSET EQU $8D + ;DRAW_BLUE_SKY EQU $8E +RANDOM_POINTER EQU $8F +FRAME_COUNT EQU $90 +MB_VALUE EQU $91 +;MB_CHUNK EQU $92 +MB_ADDRL EQU $91 +MB_ADDRH EQU $92 +DONE_PLAYING EQU $93 +;MB_FRAME_DIFF EQU $94 +MB_CHUNK_OFFSET EQU $94 + ;LZSS_RL EQU $95 + ;LZSS_RH EQU $96 + ;LZSS_COUNT EQU $97 + ;LZSS_MASK EQU $98 + ;LZSS_ENDL EQU $99 + ;LZSS_ENDH EQU $9A + ;MB_FRAME_DIFF2 EQU $9F + +; More zero-page addresses +; we try not to conflict with anything DOS, MONITOR or BASIC related + + ;COLOR1 EQU $E0 +COLOR2 EQU $E1 + ;MATCH EQU $E2 +XX EQU $E3 + ;YY EQU $E4 + ;SHIPY EQU $E4 + ;YADD EQU $E5 + ;LOOP EQU $E6 + ;MEMPTRL EQU $E7 + ;MEMPTRH EQU $E8 + ;NAMEL EQU $E9 + ;NAMEH EQU $EA + ;NAMEX EQU $EB + ;CHAR EQU $EC +DISP_PAGE EQU $ED +DRAW_PAGE EQU $EE + + ;FIRST EQU $F0 +LASTKEY EQU $F1 + ;PADDLE_STATUS EQU $F2 +XPOS EQU $F3 +YPOS EQU $F4 +TEMP EQU $FA + ;RUN EQU $FA + ;TEMP2 EQU $FB +TEMPY EQU $FB +INL EQU $FC +INH EQU $FD +OUTL EQU $FE +OUTH EQU $FF + + + +KEYPRESS EQU $C000 +KEYRESET EQU $C010 + +;; SOFT SWITCHES +CLR80COL EQU $C000 ; PAGE0/PAGE1 normal +SET80COL EQU $C001 ; PAGE0/PAGE1 switches PAGE0 in Aux instead +EIGHTYCOL EQU $C00D +SPEAKER EQU $C030 +SET_GR EQU $C050 +SET_TEXT EQU $C051 +FULLGR EQU $C052 +TEXTGR EQU $C053 +PAGE0 EQU $C054 +PAGE1 EQU $C055 +LORES EQU $C056 ; Enable LORES graphics +HIRES EQU $C057 ; Enable HIRES graphics +AN3 EQU $C05E ; Annunciator 3 + +PADDLE_BUTTON0 EQU $C061 +PADDL0 EQU $C064 +PTRIG EQU $C070 + +;; BASIC ROUTINES + +NORMAL EQU $F273 + +;; MONITOR ROUTINES + +HLINE EQU $F819 ;; HLINE Y,$2C at A +VLINE EQU $F828 ;; VLINE A,$2D at Y +CLRSCR EQU $F832 ;; Clear low-res screen +CLRTOP EQU $F836 ;; clear only top of low-res screen +SETCOL EQU $F864 ;; COLOR=A +TEXT EQU $FB36 +TABV EQU $FB5B ;; VTAB to A +BASCALC EQU $FBC1 ;; +VTAB EQU $FC22 ;; VTAB to CV +HOME EQU $FC58 ;; Clear the text screen +WAIT EQU $FCA8 ;; delay 1/2(26+27A+5A^2) us +SETINV EQU $FE80 ;; INVERSE +SETNORM EQU $FE84 ;; NORMAL +COUT EQU $FDED ;; output A to screen +COUT1 EQU $FDF0 ;; output A to screen + + + + + + +COLOR_BLACK EQU 0 +COLOR_RED EQU 1 +COLOR_DARKBLUE EQU 2 +COLOR_PURPLE EQU 3 +COLOR_DARKGREEN EQU 4 +COLOR_GREY EQU 5 +COLOR_MEDIUMBLUE EQU 6 +COLOR_LIGHTBLUE EQU 7 +COLOR_BROWN EQU 8 +COLOR_ORANGE EQU 9 +COLOR_GREY2 EQU 10 +COLOR_PINK EQU 11 +COLOR_LIGHTGREEN EQU 12 +COLOR_YELLOW EQU 13 +COLOR_AQUA EQU 14 +COLOR_WHITE EQU 15 + +COLOR_BOTH_BLACK EQU $00 +COLOR_BOTH_RED EQU $11 +COLOR_BOTH_DARKBLUE EQU $22 +COLOR_BOTH_DARKGREEN EQU $44 +COLOR_BOTH_GREY EQU $55 +COLOR_BOTH_MEDIUMBLUE EQU $66 +COLOR_BOTH_LIGHTBLUE EQU $77 +COLOR_BOTH_BROWN EQU $88 +COLOR_BOTH_ORANGE EQU $99 +COLOR_BOTH_PINK EQU $BB +COLOR_BOTH_LIGHTGREEN EQU $CC +COLOR_BOTH_YELLOW EQU $DD +COLOR_BOTH_AQUA EQU $EE +COLOR_BOTH_WHITE EQU $FF + +AUX_BOTH_MEDIUMBLUE EQU $33 ; 0011 0011 +AUX_BOTH_GREY EQU $AA ; 1010 1010