aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Watson <yalhcru@gmail.com>2016-01-06 01:55:41 -0500
committerB. Watson <yalhcru@gmail.com>2016-01-06 01:55:41 -0500
commitad615f1eb4febb59f5148ba356d9ad91dc72db09 (patch)
tree1ac19501a81295c9e7df255ef6196c63545cf7fa
parent78955cb3856cfc0115c7e2f2813132cc46c4fd23 (diff)
downloadtaipan-ad615f1eb4febb59f5148ba356d9ad91dc72db09.tar.gz
compressed title image, loads faster
-rw-r--r--Makefile9
-rw-r--r--comptitle.s.in116
-rw-r--r--taipan.c22
-rw-r--r--titlecomp.pl95
4 files changed, 234 insertions, 8 deletions
diff --git a/Makefile b/Makefile
index a515ea0..56a81b4 100644
--- a/Makefile
+++ b/Makefile
@@ -84,8 +84,8 @@ taipan.atr: all
# The game binary is a multi-part binary load file. This rule
# depends on all the pieces, and just concatenates them.
-$(XEX): taimain.xex taifont.xex newtitle.xex titledata.xex
- cat titledata.xex newtitle.xex taifont.xex taimain.xex > $(XEX)
+$(XEX): taimain.xex taifont.xex newtitle.xex comptitle.xex
+ cat comptitle.xex newtitle.xex taifont.xex taimain.xex > $(XEX)
# Bitmap data for the title screen, 256x184 = 47104 pixels, 8 bits
# per pixel, or 5888 bytes. Displayed in ANTIC mode F (aka GR.8),
@@ -96,6 +96,11 @@ $(XEX): taimain.xex taifont.xex newtitle.xex titledata.xex
titledata.xex: newtitle.pl newtitle.png
perl newtitle.pl > titledata.xex
+# compressed title, for faster loading.
+comptitle.xex: titledata.xex titlecomp.pl comptitle.s.in
+ perl titlecomp.pl 151 < titledata.xex
+ cl65 -o comptitle.xex -t none comptitle.s
+
# Init segment that loads after the title screen data. It sets up
# a custom display list and sets the GTIA for narrow playfield,
# then waits for a keypress. Afterwards, it restores the OS's
diff --git a/comptitle.s.in b/comptitle.s.in
new file mode 100644
index 0000000..7862b3d
--- /dev/null
+++ b/comptitle.s.in
@@ -0,0 +1,116 @@
+
+; cl65 -o comptitle.xex -t none comptitle.s
+
+; comptitle.s.in is used by titlecomp.pl, to generate comptitle.s.
+; __VARIABLE__ stuff is filled in by titlecomp.pl, q.v.
+; DON'T bother to edit comptitle.s (edit the .in file instead)!
+
+ .include "atari.inc"
+
+ ; size of uncompressed image, in bytes (but, needs to be
+ ; a multiple of $100).
+;imgsize = __SIZE__
+imgsize = $1700
+
+ ; these both need to be page-aligned. destination also needs
+ ; to be aligned on a 4K boundary.
+start = $2000
+destination = $9000
+
+srcptr = FR0
+dstptr = FR0+2
+pagecount = FR0+4
+tmp = FR0+5
+
+ .word $ffff
+ .word start
+ .word end-1
+
+ .org start
+
+compdata:
+ .incbin "comptitle.dat"
+
+; table runs __FIRSTCODE__ to __LASTCODE__
+table:
+ __TABLE__
+
+ ; decompression code starts here
+init:
+ lda #>imgsize
+ sta pagecount
+ lda #>compdata
+ sta srcptr+1
+ lda #>destination
+ sta dstptr+1
+ lda #0
+ sta srcptr
+ sta dstptr
+ tay
+
+copyloop:
+ lda (srcptr),y
+ bpl storebyte ; 0-127 always represent themselves
+ cmp #__LASTCODE__+1
+ bcs storebyte ; anything above the last code represents itself
+ sta tmp
+ sec
+ sbc #__FIRSTCODE__
+ bcc notcode ; anything below the 1st code represents itself
+ tax
+ lda table,x
+ beq notcode
+
+ ; got a zero-run code. A = number of bytes of zeroes to store.
+ jmp storezerorun
+
+notcode:
+ lda tmp
+
+storebyte:
+ sty tmp
+ ldy #0
+ sta (dstptr),y
+ jsr incdest
+ beq done
+nohi:
+ ldy tmp
+
+storedone:
+ iny
+ bne copyloop
+ inc srcptr+1
+ bne copyloop ; always branch (since srcptr never wraps around to 0)
+
+done:
+ rts
+
+storezerorun:
+ sty tmp
+ tay
+ dey
+ lda #0
+szloop:
+ sta (dstptr),y
+ jsr incdest
+ beq done
+nohi2:
+ dey
+ bpl szloop
+
+ ldy tmp
+ jmp storedone
+
+incdest:
+ inc dstptr
+ bne iddone
+ inc dstptr+1
+ dec pagecount
+iddone:
+ rts
+
+end:
+ .word INITAD
+ .word INITAD+1
+ .word init
+
diff --git a/taipan.c b/taipan.c
index 4792896..af755e4 100644
--- a/taipan.c
+++ b/taipan.c
@@ -43,11 +43,12 @@ extern unsigned char agetc(void);
/* wrapper for agetc(): lowercases letters */
extern unsigned char lcgetc(void);
-/* wrapper for agetc(): returns only numbers, enter, backspace */
+/* wrapper for agetc(): returns only numbers, a, enter, backspace */
extern unsigned char numgetc(void);
/* wrapper for agetc(): returns only y or n.
- dflt is 'y' 'n' to set the default answer, or 0 for no default. */
+ dflt is 'y' or 'n' to set the default answer if the user presses Enter,
+ or 0 for no default (waits until user presses either y or n) */
extern unsigned char __fastcall__ yngetc(char dflt);
/* sleep for j jiffies (no PAL adjustment at the moment) */
@@ -130,7 +131,7 @@ void cblank(unsigned char count) {
gotoxy(oldx, oldy);
}
-/* conio doesn't back up the cursor if you cputc(BS), it
+/* conio doesn't back up the cursor if you cputc(BKSP), it
prints the graphics character instead. Could use putchar(),
but using stdio links a bunch of extra support code. So: */
/* TODO: rewrite in asm */
@@ -139,6 +140,9 @@ void backspace() {
cblank(1);
}
+/* get an inventory item, return its index into items[].
+ if allow_all is true, allows '*', which is used for
+ 'throw cargo' in sea_battle. */
unsigned char get_item(unsigned char allow_all) {
unsigned char i;
for(;;) {
@@ -201,7 +205,7 @@ char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
char *st[] = { "Critical", " Poor", " Fair",
" Good", " Prime", "Perfect" };
-unsigned long cash = 0,
+unsigned long cash = 0,
bank = 0,
debt = 0,
booty = 0,
@@ -894,6 +898,9 @@ int sea_battle(int id, int num_ships) {
timed_getch(TMOUT_3S);
flushinp();
+ /* screen flash doesn't change the hue bit of
+ COLOR2 register, since we now support changing
+ it on the title screen. */
for(i = 0; i < 3; i++) {
unsigned char color = PEEK(710) & 0xf0;
POKE(710, color | 0x0c);
@@ -953,9 +960,11 @@ int sea_battle(int id, int num_ships) {
// 0 or 1: the intended result would just be 0 or 1 anyway.
newdamage = ((ed * i * id)/2) + (i / 2);
+ if(newdamage <= 0) newdamage = 1; // how the hell could this happen?
if(newdamage > 1)
newdamage = randi() % newdamage;
damage += newdamage;
+ if(damage > capacity) damage = capacity; /* just in case */
#ifdef DAMAGE_TEST
gotoxy(0, 23);
@@ -971,7 +980,6 @@ int sea_battle(int id, int num_ships) {
cgetc();
#endif
- if(damage > capacity) damage = capacity; /* just in case */
if((id == GENERIC) && (randi()%20 == 0)) {
return 2;
}
@@ -2743,7 +2751,9 @@ int main(void) {
{
// float fine = ((cash / 1.8) * ((float) randi() / RAND_MAX)) + 1;
// the 1.8 is now a 2
- unsigned long fine = randclamp(cash >> 1) + 1;
+ unsigned long fine = 0;
+ if(cash > 0)
+ fine = randclamp(cash >> 1) + 1;
hold += hold_[0];
hold_[0] = 0;
diff --git a/titlecomp.pl b/titlecomp.pl
new file mode 100644
index 0000000..2e17a92
--- /dev/null
+++ b/titlecomp.pl
@@ -0,0 +1,95 @@
+#!/usr/bin/perl -w
+
+$datasize = 0x1700;
+
+use bytes;
+
+# skip xex header
+read(STDIN, our $junk, 6);
+
+read(STDIN, $data, $datasize);
+
+for(split //, $data) {
+ $got{ord($_)}++;
+}
+
+$firstcode = shift || 128; # must be >=128
+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";
+
+sub allocate_code {
+ if(!@available_codes) {
+ die "out of run codes!\n";
+ }
+
+ return shift @available_codes;
+}
+
+# add a $ff to the end, to force the last run to be written
+# if the file ends in a run. Remove it afterwards.
+$run = 0;
+$output = "";
+for(split //, $data . chr(0xff)) {
+ if($_ eq "\0") {
+ if($run) {
+ $run++;
+ } else {
+ $run = 1;
+ }
+ } else {
+ if($run > 1) {
+ if($runlengths{$run}) {
+ $output .= chr($runlengths{$run});
+ } else {
+ my $code = allocate_code();
+ $runlengths{$run} = $code;
+ $used_codes{$code} = $run;
+ $output .= chr($code);
+ $lastcode = $code;
+ }
+ } elsif($run == 1) {
+ $output .= "\0";
+ }
+ $run = 0;
+ $output .= $_;
+ }
+}
+
+# remove the $ff we added above.
+substr($output, -1) = "";
+
+open $out, ">comptitle.dat";
+print $out $output;
+close $out;
+
+$pct = int(length($output) * 1000 / length($data))/ 10;
+print "1st code $firstcode, last $lastcode, table size " . ($lastcode - $firstcode + 1) . "\n";
+print length($output) . " bytes compressed data, $pct% ratio\n";
+print "used " . keys(%runlengths) . " codes\n";
+
+
+for($firstcode..$lastcode) {
+ $table .= " .byte ";
+ if(exists($used_codes{$_})) {
+ $table .= '$' . sprintf("%02x", $used_codes{$_}) . " ; " . sprintf("%02x", $_);
+ } else {
+ $table .= "\$00 ; SELF";
+ }
+ $table .= "\n";
+}
+
+open $in, "<comptitle.s.in" or die $!;
+open $out, ">comptitle.s" or die $!;
+
+while(<$in>) {
+ s/__TABLE__/$table/;
+ s/__FIRSTCODE__/$firstcode/g;
+ s/__LASTCODE__/$lastcode/g;
+ print $out $_;
+}
+
+close $in;
+close $out;