diff options
-rw-r--r-- | Makefile | 9 | ||||
-rw-r--r-- | comptitle.s.in | 116 | ||||
-rw-r--r-- | taipan.c | 22 | ||||
-rw-r--r-- | titlecomp.pl | 95 |
4 files changed, 234 insertions, 8 deletions
@@ -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 + @@ -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; |