mirror of
https://github.com/deater/dos33fsprogs.git
synced 2024-12-27 17:29:49 +00:00
96 lines
2.3 KiB
Plaintext
96 lines
2.3 KiB
Plaintext
|
The Challenges of an Apple II chiptune player.
|
||
|
|
||
|
The goal is to design a chiptune player that can play large
|
||
|
(150k+ uncompressed) chiptune files on an Apple II with 48k of RAM
|
||
|
and a Mockingboard sound card.
|
||
|
|
||
|
An interrupt routine wakes at 50Hz to write the registers and a few other
|
||
|
houskeeping things.
|
||
|
|
||
|
Not enough RAM to hold full raw ym5 sound data (one byte for each of 14
|
||
|
registers, every 50Hz). This compresses amazingly. Using LZ4 by at
|
||
|
least a factor of 10. But it won't fit all in RAM so we have to load
|
||
|
the full file from disk (no way to do disk I/O, disk I/O disables interrupts)
|
||
|
then decompress in chunks. So we need room for both the compressed file
|
||
|
plus uncompressed data.
|
||
|
|
||
|
The problem is decompression also takes a while, longer than the 50Hz.
|
||
|
So if we just decompress the next chunk when needed the sound will noticibly
|
||
|
pause for a fraction of a second.
|
||
|
|
||
|
One solution to that is to have two decompress areas and flip between them,
|
||
|
decompressing in the background to one while the other is playing. The problem
|
||
|
is splitting the decompressed data into smaller chunks like this is that
|
||
|
it doesn't compress as well so it takes up more disk/memory space
|
||
|
for the raw file.
|
||
|
|
||
|
|
||
|
|
||
|
Memory Map
|
||
|
(not to scale)
|
||
|
|
||
|
------- $ffff
|
||
|
| ROM/IO|
|
||
|
------- $c000
|
||
|
|DOS3.3 |
|
||
|
-------| $9600
|
||
|
| |
|
||
|
| |
|
||
|
| FREE |
|
||
|
| |
|
||
|
| |
|
||
|
|------- $0c00
|
||
|
|GR pg 1|
|
||
|
|------- $0800
|
||
|
|GR pg 0|
|
||
|
------- $0400
|
||
|
| |
|
||
|
------- $0200
|
||
|
|stack |
|
||
|
------- $0100
|
||
|
|zero pg|
|
||
|
------- $0000
|
||
|
|
||
|
|
||
|
|
||
|
Sizes
|
||
|
|
||
|
time ym5 KRW(3) KRW(2)
|
||
|
~~~~ ~~~ ~~~~~~ ~~~~~~
|
||
|
KORO.KRW 0:54 ? 2740
|
||
|
FIGHTING.KRW 1:40 ? 3086
|
||
|
CAMOUFLAGE.KRW 1:32 1162 4054
|
||
|
DEMO4.KRW 2:05 1393 4061
|
||
|
SDEMO.KRW 2:12 1635 5266
|
||
|
CHRISTMAS.KRW 1:32 1751 4975
|
||
|
SPUTNIK.KRW 2:05 2164 8422
|
||
|
DEATH2.KRW 2:27 2560 8064
|
||
|
CRMOROS.KRW 1:29 2566 8045
|
||
|
TECHNO.KRW 2:23 2630 8934
|
||
|
WAVE.KRW 2:52 2655 8368
|
||
|
LYRA2.KRW 3:04 2870 9826
|
||
|
INTRO2.KRW 2:59 3217 9214
|
||
|
ROBOT.KRW 1:26 3448 7724
|
||
|
UNIVERSE.KRW 1:49 4320 9990
|
||
|
NEURO.KRW 3:47 8681 22376
|
||
|
AXELF.KRW 10:55 9692 47989
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
Interesting bugs that were hard to debug:
|
||
|
|
||
|
+ Bug in qkumba's LZ4 decoder, only happened when a copy-block size was
|
||
|
exactly a multiple of 256, in which case it would copy
|
||
|
an extra time.
|
||
|
|
||
|
+ Bug where the box-drawing was starting at 0 rather than at Y.
|
||
|
Turns out I was padding the filename buffer with A0 but going
|
||
|
one too far and it was writing A0 to the first byte of the
|
||
|
hlin routine, and A0 is a LDY # instruction.
|