mirror of
https://github.com/deater/dos33fsprogs.git
synced 2024-12-27 02:31:00 +00:00
Merge branch 'master' of https://github.com/deater/dos33fsprogs
This commit is contained in:
commit
f43650e1ef
@ -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.
|
||||
|
||||
|
24
still_alive/Makefile
Normal file
24
still_alive/Makefile
Normal file
@ -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
|
2
still_alive/README.still_alive
Normal file
2
still_alive/README.still_alive
Normal file
@ -0,0 +1,2 @@
|
||||
initial: 2078
|
||||
add ascii art: 9142
|
BIN
still_alive/SA.KRW
Normal file
BIN
still_alive/SA.KRW
Normal file
Binary file not shown.
223
still_alive/ascii_art.inc
Normal file
223
still_alive/ascii_art.inc
Normal file
@ -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 #####$=";
|
||||
|
||||
|
972
still_alive/eightycol.inc
Normal file
972
still_alive/eightycol.inc
Normal file
@ -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 <<Subject Name Here>>":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
|
||||
|
345
still_alive/interrupt_handler.s
Normal file
345
still_alive/interrupt_handler.s
Normal file
@ -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
|
BIN
still_alive/still_alive.dsk
Normal file
BIN
still_alive/still_alive.dsk
Normal file
Binary file not shown.
558
still_alive/still_alive.s
Normal file
558
still_alive/still_alive.s
Normal file
@ -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 ; load loading message
|
||||
sta OUTL
|
||||
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 ; if not found, print that
|
||||
sta OUTL
|
||||
lda #>not_message
|
||||
sta OUTH
|
||||
inc CV
|
||||
jsr move_and_print
|
||||
|
||||
jmp forever_loop ; and wait forever
|
||||
|
||||
mockingboard_found:
|
||||
; lda #<found_message ; print found message
|
||||
; sta OUTL
|
||||
; 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 $03fe
|
||||
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 OUTL
|
||||
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 #<LZ4_BUFFER
|
||||
sta OUTL
|
||||
|
||||
ldy #3 ; skip KRW magic at front
|
||||
|
||||
; print title
|
||||
lda #20 ; VTAB 20: HTAB from file
|
||||
jsr print_header_info
|
||||
|
||||
; Print Author
|
||||
lda #21 ; VTAB 21: HTAB from file
|
||||
jsr print_header_info
|
||||
|
||||
; Print clock
|
||||
lda #23 ; VTAB 23: HTAB from file
|
||||
jsr print_header_info
|
||||
|
||||
; Print Left Arrow (INVERSE)
|
||||
lda #'<'
|
||||
sta $750
|
||||
sta $B50
|
||||
|
||||
lda #'-'
|
||||
sta $751
|
||||
sta $B51
|
||||
|
||||
; Print Rright Arrow (INVERSE)
|
||||
lda #'-'
|
||||
sta $776
|
||||
sta $B76
|
||||
|
||||
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 ; set input pointer
|
||||
sta INL
|
||||
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 ; point to filename
|
||||
sta INL
|
||||
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"
|
251
still_alive/zp.inc
Normal file
251
still_alive/zp.inc
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user