diff options
author | B. Watson <yalhcru@gmail.com> | 2016-01-20 23:46:17 -0500 |
---|---|---|
committer | B. Watson <yalhcru@gmail.com> | 2016-01-20 23:46:17 -0500 |
commit | 9d032c9a1c0eca663c6877f5421957f50cb1eb79 (patch) | |
tree | 3626b074e0beece467318f41d35d42cb146d57e0 | |
parent | 8aec40856588437a20906a0820941382475344ec (diff) | |
download | taipan-9d032c9a1c0eca663c6877f5421957f50cb1eb79.tar.gz |
rewrite sound code in asm, shed 186 bytes
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | soundasm.s | 140 | ||||
-rw-r--r-- | sounds.c | 10 | ||||
-rw-r--r-- | sounds.h | 11 | ||||
-rw-r--r-- | titlecomp.pl | 20 | ||||
-rw-r--r-- | titlecompression.txt | 45 |
6 files changed, 215 insertions, 17 deletions
@@ -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 + @@ -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 */ } @@ -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 |