mirror of
https://github.com/deater/dos33fsprogs.git
synced 2024-08-14 10:29:46 +00:00
doc: more edits
This commit is contained in:
parent
dac25a8724
commit
016bfcac63
@ -163,9 +163,9 @@ 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
|
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).
|
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
|
You do get two pages of graphics, Page 1 is at
|
||||||
\$2000\footnote{On 6502 systems hexadecimal values are
|
{\tt \$2000}\footnote{On 6502 systems hexadecimal values are
|
||||||
indicated by the dollar sign}
|
indicated by the dollar sign}
|
||||||
and Page 2 at \$4000.
|
and Page 2 at {\tt \$4000}.
|
||||||
Optionally 4 lines of text can be shown at the bottom of the
|
Optionally 4 lines of text can be shown at the bottom of the
|
||||||
screen instead of graphics.
|
screen instead of graphics.
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ It provides 40x48 blocks, reusing the same memory as the 40x24 text mode.
|
|||||||
text displayed at the bottom).
|
text displayed at the bottom).
|
||||||
Fifteen colors are available (there are two greys which are indistinguishable).
|
Fifteen colors are available (there are two greys which are indistinguishable).
|
||||||
Again the addresses are interleaved in a non-linear fashion.
|
Again the addresses are interleaved in a non-linear fashion.
|
||||||
Lo-res Page 1 is at \$400 and Page 2 is at \$800.
|
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
|
Some amazing effects can be achieved by cycle counting, reading
|
||||||
the floating bus, and racing the beam while toggling graphics
|
the floating bus, and racing the beam while toggling graphics
|
||||||
@ -198,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
|
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
|
tool although many ``real'' Apple II programmers look down on it for some
|
||||||
reason.
|
reason.
|
||||||
I cross-compile the code, construct Apple DOS3.3 disk images using
|
I cross-compile the code, constructing Apple DOS3.3 disk images using
|
||||||
custom tools I have written, and then do most testing in an emulator.
|
custom tools I have written.
|
||||||
|
I test using emulators:
|
||||||
AppleWin (run under the wine emulator) is the easiest to use, but
|
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
|
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
|
to actual hardware using a CFFA3000 disk emulator installed in
|
||||||
@ -267,67 +268,73 @@ well-traveled guinea pig.
|
|||||||
|
|
||||||
An Applesoft BASIC ``HELLO'' program loads the binary automatically at bootup.
|
An Applesoft BASIC ``HELLO'' program loads the binary automatically at bootup.
|
||||||
This does not count towards the executable size, as you could manually BRUN
|
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
|
To make the loading time slightly more interesting the HELLO program enables
|
||||||
address \$2000 (hi-res page1) and BASIC is nice enough to enable
|
graphics mode and loads the program to address {\tt \$2000} (hi-res page1).
|
||||||
graphics mode first so you can watch the display get filled with the random
|
This causes the display to filled with the colorful pattern corresponding
|
||||||
pattern of the compressed image.
|
to the compressed image.
|
||||||
This entirely fills the 8k of the display, or would
|
This conveniently fills all 8k of the display RAM, or would have
|
||||||
if we POKEd the right address to turn off
|
if we had POKEd the right soft-switch to turn off
|
||||||
the 4 lines of text on the bottom of the screen.
|
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.
|
The binary is encoded with the LZ4 algorithm.
|
||||||
We flip to hi-res Page 2 and decompress there so the user continues to get
|
We flip to hi-res Page 2 and decompress to this region so the display
|
||||||
a show of random noise.
|
now shows the executable code.
|
||||||
|
|
||||||
The 6502 size-optimized LZ4 decompression code was written by qkumba
|
The 6502 size-optimized LZ4 decompression code was written by qkumba
|
||||||
(Peter Ferrie).
|
(Peter Ferrie).
|
||||||
% http://pferrie.host22.com/misc/appleii.htm
|
% http://pferrie.host22.com/misc/appleii.htm
|
||||||
The program and data decompress to around 22k starting at \$4000.
|
The program and data decompress to around 22k starting at {\tt \$4000}.
|
||||||
It over-writes parts of DOS3.3, but since we will not be using the disk
|
This over-writes parts of DOS3.3, but since we will not be using the disk
|
||||||
any more this is not an issue.
|
any more this is not an issue.
|
||||||
|
|
||||||
If you look carefully at the upper left corner of the screen during
|
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
|
decompress you will see my triangular logo, which is supposed to evoke
|
||||||
my VMW initials (see Figure~\ref{fig:vmw}).
|
my VMW initials (see Figure~\ref{fig:vmw}).
|
||||||
To do this I had to put the proper bit pattern at the interleaved
|
To do this I had to put the proper bit pattern inside the code
|
||||||
addresses of \$4000, \$4400, \$4800, and \$4C00.
|
at the interleaved addresses of {\tt \$4000}, {\tt \$4400}, {\tt \$4800},
|
||||||
This turned out to be way more trouble than it was worth.
|
and {\tt \$4C00}.
|
||||||
As an interesting note, the image data at \$4000 is executed as it maps
|
The image data at {\tt \$4000} maps to (mostly)
|
||||||
to (mostly) harmless code.
|
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 MP4 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
|
The demo was optimized to fit in 8k.
|
||||||
is compressed.
|
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
|
Removing instructions sometimes makes the binary {\em larger} as it no longer
|
||||||
compresses as well.
|
compresses as well.
|
||||||
Long runs of values (such as 0 padding) are essentially free.
|
Long runs of values (such as 0 padding) are essentially free.
|
||||||
This mostly turned into an exercise of guess-and-check until everything fit.
|
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.
|
The title screen fades in from black.
|
||||||
|
|
||||||
This is a software hack as the Apple II does not have palette support.
|
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
|
The image is loaded to an off-screen buffer and a lookup table is used to
|
||||||
copy in the faded versions on the fly.
|
copy in the faded versions on the fly.
|
||||||
|
|
||||||
\subsection{TITLE SCREEN}
|
\noindent
|
||||||
|
{\bf TITLE GRAPHICS}:
|
||||||
|
The title screen is shown in Figure~\ref{fig:title}.
|
||||||
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}.
|
|
||||||
The image is run-length encoded (RLE) which is
|
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).
|
(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?
|
to copy the image in place?
|
||||||
Remember the graphics are 40x48 (shared with the text display region).
|
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
|
It might be easier to think of it as 40x24 characters, with the top / bottom
|
||||||
@ -339,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.
|
various pieces of hardware can use these as scratchpad memory.
|
||||||
This means just overwriting the whole 1k with data might not work out well
|
This means just overwriting the whole 1k with data might not work out well
|
||||||
unless you know what you are doing.
|
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.
|
The title screen has scrolling text at the bottom.
|
||||||
This is nothing fancy, the text is in a buffer off screen and a 40x4
|
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.
|
chunk of RAM is copied in every so many cycles.
|
||||||
@ -354,20 +363,23 @@ movie encoding conspire to make this look worse than things look in person.
|
|||||||
\subsection{MOCKINGBOARD MUSIC}
|
\subsection{MOCKINGBOARD MUSIC}
|
||||||
|
|
||||||
No demo is complete without some exciting background 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.
|
for AY-3-8910 based systems.
|
||||||
I gained some expertise during the long wait for my Mockingboard to arrive
|
During the long time waiting for my Mockingboard hardware to arrive
|
||||||
by building a Raspberry Pi chiptune player that is essentially the same
|
I designed and built a Raspberry Pi chiptune player that uses
|
||||||
hardware.
|
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
|
The song being played is a stripped down and re-arranged version of
|
||||||
``Electric Wave'' from CC'00 by EA (Ilya Abrosimov).
|
``Electric Wave'' from CC'00 by EA (Ilya Abrosimov).
|
||||||
|
|
||||||
Most of my sound infrastructure involves YM5 files, a format commonly
|
Most of my sound infrastructure involves YM5 files, a format commonly
|
||||||
used by ZX Spectrum and ATARI ST users.
|
used by ZX Spectrum and ATARI ST users.
|
||||||
These are essentially just AY-3-8910 register dumps taken at 50Hz.
|
The YM file format is 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
|
To play these back one sets up the sound card to interrupt 50 times a second
|
||||||
and then write out the 14 register values from that frame.
|
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
|
% 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
|
% registers that control the 3 channels. Each AY chip has a dedicated
|
||||||
@ -388,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
|
% I have a whole suite of code for manipulating YM sound data, in my
|
||||||
% vmw-meter git repository.
|
% 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).
|
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
|
% 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
|
%% there. This can be in any slot 1-7 on the Apple II, though typically
|
||||||
@ -398,9 +410,9 @@ interrupt at 25Hz.
|
|||||||
% (it has to be an on-board timer as the default
|
% (it has to be an on-board timer as the default
|
||||||
% Apple II has no timers).
|
% Apple II has no timers).
|
||||||
Why 25Hz and not 50Hz? At 50Hz with 14 registers you use 700 bytes/s.
|
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.
|
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 the fancy circular buffer
|
To allow the song to fit in memory (without a fancy circular buffer
|
||||||
decompression utilized in my VMW Chiptune Player music-disk demo) we have
|
decompression routine utilized in my VMW Chiptune music-disk demo) we have
|
||||||
to reduce the size.
|
to reduce the size.
|
||||||
First the music is changed so it only needs to be updated at 25Hz.
|
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
|
Then the register data is compressed from 14 bytes to 11 bytes by stripping off
|
||||||
@ -411,10 +423,10 @@ acceptably catchy chiptune inside of our 8k payload.
|
|||||||
\subsection{MODE7 BACKGROUND}
|
\subsection{MODE7 BACKGROUND}
|
||||||
|
|
||||||
``Mode7'' is a Super Nintendo (SNES) graphics mode that takes a tiled
|
``Mode7'' is a Super Nintendo (SNES) graphics mode that takes a tiled
|
||||||
background to be transformed by rotation and scaling.
|
background and transforms it by rotating and scaling.
|
||||||
The most common effect was to squash it out to the horizon, giving
|
The most common effect squashes the background out to the horizon, giving
|
||||||
a three-dimensional look.
|
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.
|
them in software.
|
||||||
|
|
||||||
% As found on Wikipedia, the transform is of the type
|
% As found on Wikipedia, the transform is of the type
|
||||||
@ -422,6 +434,8 @@ them in software.
|
|||||||
% [x'] = [a b]([x]-[x0])+[x0]
|
% [x'] = [a b]([x]-[x0])+[x0]
|
||||||
% [y'] [c d]([y] [y0]) [y0]
|
% [y'] [c d]([y] [y0]) [y0]
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
Our algorithm is based on code by Martijn van Iersel.
|
Our algorithm is based on code by Martijn van Iersel.
|
||||||
It iterates through each y line on the screen and calculates based on
|
It iterates through each y line on the screen and calculates based on
|
||||||
the camera location: height ({\em spacez}), x and y coordinates
|
the camera location: height ({\em spacez}), x and y coordinates
|
||||||
@ -485,25 +499,28 @@ We managed to take this algorithm and speed it up in the following ways:
|
|||||||
The engine can be parameterized with different tilesets to use, which we
|
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
|
do to provide both a black+white checkerboard background, as well as the
|
||||||
island background from the TFV game.
|
island background from the TFV game.
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
\subsection{BOUNCING BALL ON CHECKERBOARD}
|
\subsection{BOUNCING BALL ON CHECKERBOARD}
|
||||||
|
|
||||||
The first scence starts out viewing an infinite checkerboard.
|
The first Mode7 scene transpires on an infinite checkerboard.
|
||||||
Any demo would be incomplete without some sort of bouncing geometric solid,
|
A demo would be incomplete without some sort of bouncing geometric solid,
|
||||||
in our case a pink sphere.
|
in this case we have a pink sphere.
|
||||||
This was accomplished with 16 sprites:
|
The sphere is represented by 16 sprites that were captured from
|
||||||
the sphere was modeled in OpenGL inside of a 20 year old game engine
|
a 20 year old OpenGL game engine.
|
||||||
and screenshots were taken then reduced in keeping with the size and
|
Screenshots were taken then reduced to the proper size and color
|
||||||
color limitations.
|
limitations.
|
||||||
Similarly the shadow is also just sprites.
|
The shadows are also just sprites.
|
||||||
|
|
||||||
The clicking noise on bounce is generated by accessing the speaker port
|
The clicking noise on bounce is generated by accessing the speaker port
|
||||||
at address \$C030.
|
at address {\tt \$C030}.
|
||||||
This gives some sound for those viewing the demo without a Mockingboard.
|
This gives some sound for those viewing the demo without the benefit
|
||||||
|
of a Mockingboard.
|
||||||
|
|
||||||
|
|
||||||
\subsection{TFV SPACESHIP FLYING}
|
\subsection{TFV SPACESHIP FLYING}
|
||||||
|
|
||||||
|
|
||||||
This next scene has a spaceship flying over an island.
|
This next scene has a spaceship flying over an island.
|
||||||
The spaceship, water splash, and shadows are all sprites.
|
The spaceship, water splash, and shadows are all sprites.
|
||||||
They are all drawn in software as the Apple II has no sprite hardware.
|
They are all drawn in software as the Apple II has no sprite hardware.
|
||||||
|
Loading…
Reference in New Issue
Block a user