aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Watson <yalhcru@gmail.com>2016-01-20 23:46:17 -0500
committerB. Watson <yalhcru@gmail.com>2016-01-20 23:46:17 -0500
commit9d032c9a1c0eca663c6877f5421957f50cb1eb79 (patch)
tree3626b074e0beece467318f41d35d42cb146d57e0
parent8aec40856588437a20906a0820941382475344ec (diff)
downloadtaipan-9d032c9a1c0eca663c6877f5421957f50cb1eb79.tar.gz
rewrite sound code in asm, shed 186 bytes
-rw-r--r--Makefile6
-rw-r--r--soundasm.s140
-rw-r--r--sounds.c10
-rw-r--r--sounds.h11
-rw-r--r--titlecomp.pl20
-rw-r--r--titlecompression.txt45
6 files changed, 215 insertions, 17 deletions
diff --git a/Makefile b/Makefile
index c3a46b4..6d14f27 100644
--- a/Makefile
+++ b/Makefile
@@ -88,8 +88,8 @@ XEX=taipan.xex
# All the C and asm sources for taimain.xex:
TAIMAIN_HDRS=sounds.h
-TAIMAIN_C_SRC=taipan.c sounds.c
-TAIMAIN_ASM_SRC=rand.s draw_lorcha.s timed_getch.s jsleep.s portstat.s clrtobot.s ultostr.s
+TAIMAIN_C_SRC=taipan.c
+TAIMAIN_ASM_SRC=rand.s draw_lorcha.s timed_getch.s jsleep.s portstat.s clrtobot.s ultostr.s soundasm.s
# Comment these lines out to build without big number support.
# This will stop being possible at some point.
@@ -140,7 +140,7 @@ titledata.dat: newtitle.pl newtitle.png
# compressed title, for faster loading. see titlecompression.txt
# for gory details.
comptitle.xex: titledata.dat titlecomp.pl comptitle.s.in
- perl titlecomp.pl 151 < titledata.dat
+ perl titlecomp.pl 133 < titledata.dat
cl65 -l comptitle.lst -o comptitle.xex -t none --asm-define destination=$(TITLE_DATA_ADDR) comptitle.s
# Init segment that loads after the title screen data. It sets up
diff --git a/soundasm.s b/soundasm.s
new file mode 100644
index 0000000..512ec81
--- /dev/null
+++ b/soundasm.s
@@ -0,0 +1,140 @@
+; Sounds for Taipan! Atari 800 port.
+
+; Made by capturing the Apple II audio and taking wild guesses,
+; then refining them.
+
+; I'm not shooting for Atari sounds that are identical to the
+; Apple ones: (a) it's impossible anyway, and (b) the Apple
+; sounds are a bit harsh to the ear. Hopefully these sound
+; a little smoother while still being pretty close.
+
+; This is an asm rewrite of sounds.c. Sounds the same, but weighs
+; in at 186 bytes less code
+
+; general form from sounds.c:
+; for(j=0; j<repeats; j++) {
+; for(i=0; i<Yreg; i++) {
+; POKEY_WRITE.audf1 = Areg-i*Xreg;
+; jsleep(delay);
+; }
+; }
+
+ .include "atari.inc"
+
+ .import _jsleep
+ .export _bad_joss_sound, _good_joss_sound, _under_attack_sound
+ .importzp tmp1, tmp2, tmp3, tmp4, sreg
+
+initialpitch = sreg
+delay = sreg+1
+pitch = tmp1
+decrement = tmp2
+counter = tmp3
+repeats = tmp4
+
+; this must agree with newtitle.s
+; 0 = enabled, 1 = disabled
+sound_disabled = $06ff
+
+_under_attack_sound:
+; C version was:
+; for(j=0; j<3; j++) {
+; for(i=0; i<3; i++) {
+; POKEY_WRITE.audf1 = 20-i*3;
+; jsleep(3);
+; }
+; }
+ lda #$03
+ sta delay
+ sta repeats
+ tax
+ tay
+ lda #$14
+; fall through to make_sound
+
+; call make_sound with:
+; A = initial pitch
+; X = decrement amount per frame
+; Y = inner loop count (i)
+; repeats = outer loop count (j)
+; delay = jiffies to delay per inner loop
+make_sound:
+ sta initialpitch
+ stx decrement
+ sty counter
+
+ ; if sound is disabled, don't play it at all.
+ lda sound_disabled
+ bne stop_sound
+
+ ; init sound
+ lda #0
+ sta AUDCTL
+ lda #3
+ sta SKCTL
+ lda #$AA ; pure tone, volume 10
+ sta AUDC1
+
+@repeatloop:
+ ldy counter
+ lda initialpitch
+ sta pitch
+@noteloop:
+ lda pitch
+ sta AUDF1
+ sec
+ sbc decrement
+ sta pitch
+ ldx #0
+ lda delay
+ jsr _jsleep
+
+ ; if user pressed a key, abort the sound entirely.
+ ; disabled for now.
+ ;lda CH
+ ;cmp #$FF
+ ;bne stop_sound
+
+ dey
+ bne @noteloop
+ dec repeats
+ bne @repeatloop
+
+stop_sound:
+ lda #0
+ sta AUDC1
+ rts
+
+_bad_joss_sound:
+; C version was:
+; for(i=0; i<10; i++) {
+; POKEY_WRITE.audf1 = 80-i*8;
+; jsleep(1);
+; }
+; which writes 80 72 64 56 48 40 32 24 16 8 to AUDF1
+ lda #$01
+ sta repeats
+ sta delay
+ lda #$50
+ ldx #$08
+ ldy #$0a
+ bne make_sound
+
+_good_joss_sound:
+; C version was:
+; for(j=0; j<3; j++) {
+; for(i=0; i<4; i++) {
+; POKEY_WRITE.audf1 = 20-i*5;
+; jsleep(2);
+; }
+; }
+; which writes 20 15 10 5 to AUDF1, 3 times
+ lda #$03
+ sta repeats
+ lda #$02
+ sta delay
+ lda #$14
+ ldx #$05
+ ldy #$04
+ bne make_sound
+
diff --git a/sounds.c b/sounds.c
index f6a4ac0..6fd43e2 100644
--- a/sounds.c
+++ b/sounds.c
@@ -1,3 +1,6 @@
+/* this file is no longer used. the sound code was rewritten in asm,
+ and lives in soundasm.s. This file is kept purely for reference. */
+
/* Sounds for Taipan! Atari 800 port.
Made by capturing the Apple II audio and taking wild guesses,
@@ -13,7 +16,10 @@
#include <peekpoke.h>
#include "sounds.h"
-int sound_disabled = 0x06ff;
+/* location we will look at, to see if sound is disabled.
+ 0 = enabled, 1 = disabled. If you change this here,
+ change it in newtitle.s also! */
+static int sound_disabled = 0x06ff;
/* to build standalone xex that just plays the 3 sounds:
cl65 -DTESTXEX -t atari -o sounds.xex sounds.c
@@ -30,6 +36,7 @@ void jsleep(unsigned int j) {
extern void __fastcall__ jsleep(unsigned int j);
#endif
+/* set volume 10, distortion 10 on audio channel 0 */
void init_sound(unsigned char audc1) {
if(PEEK(sound_disabled)) return;
@@ -39,6 +46,7 @@ void init_sound(unsigned char audc1) {
POKEY_WRITE.audc1 = audc1; /* SOUND 0,x,audc1>>4,audc1&0x0f */
}
+/* silence audio channel 0 */
void stop_sound(void) {
POKEY_WRITE.audc1 = 0x00; /* SOUND 0,x,0,0 */
}
diff --git a/sounds.h b/sounds.h
index d121a70..d876aae 100644
--- a/sounds.h
+++ b/sounds.h
@@ -1,14 +1,3 @@
-/* location we will look at, to see if sound is disabled.
- 0 = enabled, 1 = disabled. If you change this here,
- change it in newtitle.s also! */
-extern int sound_disabled;
-
-/* set volume 10, distortion 10 on audio channel 0 */
-void init_sound(unsigned char audc1);
-
-/* silence audio channel 0 */
-void stop_sound(void);
-
/* played when something bad happens */
void bad_joss_sound(void);
diff --git a/titlecomp.pl b/titlecomp.pl
index 58ce0d3..a62b715 100644
--- a/titlecomp.pl
+++ b/titlecomp.pl
@@ -16,11 +16,31 @@ for(split //, $data) {
}
$firstcode = shift || 128; # must be >=128
+if($firstcode eq '-l') {
+ $list_codes = 1;
+ $firstcode = 128;
+ $tabsize = shift || 25;
+}
+
for($firstcode..255) {
push @available_codes, $_ unless $got{$_};
}
print scalar keys %got, " unique byte values\n";
print scalar @available_codes . " available run codes >= $firstcode\n";
+if($list_codes) {
+ $lowest = 256;
+ $best = 0;
+# print join("\t", @available_codes) . "\n";
+ for($i = 0; $i < @available_codes - $tabsize - 1; $i++) {
+ $used = $available_codes[$i + $tabsize - 1] - $available_codes[$i] + 1;
+ if($used < $lowest) {
+ $lowest = $used, $best = $available_codes[$i];
+ }
+ print $available_codes[$i] . " " . $used . "\n";
+ }
+ print "== optimum firstcode value is $best\n";
+ exit(0);
+}
sub allocate_code {
if(!@available_codes) {
diff --git a/titlecompression.txt b/titlecompression.txt
index 9c30232..456ddf2 100644
--- a/titlecompression.txt
+++ b/titlecompression.txt
@@ -214,8 +214,49 @@ containing the table definition and the rest of the decoding code.
If you look at titlecomp.pl, you'll see it takes an optional argument,
forcing it to use a particular byte value as the first code value. This
-number is determined by running the script repeatedly with different
-arguments, to find the one with the smallest table size.
+number is determined by:
+
+$ perl titlecomp.pl < titledata.dat
+200 unique byte values
+36 available run codes >= 128
+1st code 128, last 189, table size 62
+3437 bytes compressed data, 58.3% ratio
+used 25 codes
+
+The table size worked out to 62 bytes. We can likely do better than that,
+but the process isn't automated. The "used 25 codes" bit is important:
+we call titlecomp.pl with that number as an argument to its -l option:
+
+$ perl titlecomp.pl -l 25 < titledata.dat
+200 unique byte values
+36 available run codes >= 128
+133 57
+147 57
+148 62
+149 65
+151 64
+154 62
+162 57
+163 67
+164 71
+166 70
+== optimum firstcode value is 133
+
+So now we compress the file for real, using 133 as the first code:
+
+$ perl titlecomp.pl 133 < titledata.dat
+200 unique byte values
+36 available run codes >= 133
+1st code 133, last 189, table size 57
+3437 bytes compressed data, 58.3% ratio
+used 25 codes
+
+Plug the number 133 into the Makefile (under the comptitle.xex target) and
+we're done. Whew, that was a lot of work just to save 5 bytes... the good
+news is that this procedure only needs to be repeated if newtitle.png is
+edited. The other good news is, those 5 bytes wouldn't have hurt anything
+anyway. Worst case scenario, they would have added 1 sector to the file
+size (and made it take ever so slightly longer to load).
Wait, what do I mean by smallest table size? Well, I said the table
contains one entry for each byte value 0 to 255... This isn't really