aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--console.s68
-rw-r--r--cprintul.s109
-rw-r--r--messages.pl2
-rw-r--r--taipan.c163
5 files changed, 287 insertions, 57 deletions
diff --git a/Makefile b/Makefile
index 6d46230..f852219 100644
--- a/Makefile
+++ b/Makefile
@@ -99,7 +99,7 @@ XEX=taipan.xex
# All the C and asm sources for taimain.xex:
TAIMAIN_HDRS=sounds.h
TAIMAIN_C_SRC=taipan.c strtonum.c
-TAIMAIN_ASM_SRC=rand.s draw_lorcha.s timed_getch.s portstat.s console.s ultostr.s soundasm.s explosion.s textdecomp.s
+TAIMAIN_ASM_SRC=rand.s draw_lorcha.s timed_getch.s portstat.s console.s cprintul.s soundasm.s explosion.s textdecomp.s
TAIMAIN_LIBS=conio/conio.lib
# Comment these lines out to build without big number support.
diff --git a/console.s b/console.s
index b02403d..7837ce1 100644
--- a/console.s
+++ b/console.s
@@ -1,7 +1,7 @@
.include "atari.inc"
- .export _clrtobot, _clrtoeol, _clr_screen, _clrtoline, _cspaces, _cblank, _backspace
+ .export _clrtobot, _clrtoeol, _clr_screen, _clrtoline, _cspaces, _cblank, _backspace, _cprint_pipe, _cprint_bang, _cspace, _cputc_s, _comma_space, _cprint_colon_space, _cprint_question_space, _cprint_period, _cprint_taipan_prompt
.export _rvs_on, _rvs_off
.import mul40 ; from cc65's runtime
@@ -9,7 +9,8 @@
.import _revflag ; conio/revers.s
.import bump_destptr ; these two are
.importzp destptr ; from draw_lorcha.s
- .import _cspace
+ .importzp sreg
+ .import _cprintulong, _cputc, _cprint_taipan
.ifdef CART_TARGET
.segment "HIGHCODE"
@@ -117,3 +118,66 @@ _rvs_off:
lda #0
sta _revflag
rts
+
+ ; micro-optimizations here.
+ ; the stuff below might be a bit hard to follow, but it saves code.
+ ; calling this: cputs("? ");
+ ; emits code like this:
+ ; lda #<Lxxx
+ ; ldx #>Lxxx
+ ; jsr _cputs
+ ; ...which is 9 bytes per call (plus 3 bytes for the "? " string itself).
+ ; replacing each cputs("? "); with cprint_question_space() means 3 bytes
+ ; per call (a JSR). there are 3 'some char followed by a space' routines
+ ; here, totalling 10 bytes. the actual space is printed by code shared
+ ; with cspace().
+ ; also, there are 5 'print a single character' routines. each one would
+ ; normally be cputc('X'), which compiles to:
+ ; lda #'X'
+ ; jsr _cputc
+ ; ...or 5 bytes each. we have 5 of them, so 25 bytes. using fall-thru
+ ; and the BIT trick, they condense down to 17 bytes.
+ ; if you're not familiar with the "BIT trick" to skip a 2-byte instruction,
+ ; the stuff below looks like gibberish, sorry.
+
+ ; ", Taipan? "
+ ; using fall-thru here saves 3 bytes (normally the last instruction
+ ; would be "jmp _cprint_question_space")
+_cprint_taipan_prompt:
+ jsr _comma_space
+ jsr _cprint_taipan
+ ; fall thru
+
+ ; each entry point here prints one character followed by a space
+ ; "? "
+_cprint_question_space:
+ lda #'?'
+ .byte $2c
+
+ ; ": "
+_cprint_colon_space:
+ lda #':'
+ .byte $2c
+
+ ; ", "
+_comma_space:
+ lda #','
+ jsr _cputc
+ ; fall thru
+
+ ; each entry point here prints one character
+_cspace:
+ lda #' '
+ .byte $2c
+_cprint_pipe:
+ lda #'|'
+ .byte $2c
+_cputc_s:
+ lda #'s'
+ .byte $2c
+_cprint_period:
+ lda #'.'
+ .byte $2c
+_cprint_bang:
+ lda #'!'
+ jmp _cputc
diff --git a/cprintul.s b/cprintul.s
new file mode 100644
index 0000000..cf90574
--- /dev/null
+++ b/cprintul.s
@@ -0,0 +1,109 @@
+; cprintul.s - print an unsigned long, int, or char
+
+; Modified from cc65's libsrc/common/ltoa.s
+; Originally by Ullrich von Bassewitz, 11.06.1998
+
+; modified version by B. Watson
+
+; - print the characters with cputs instead of storing in a buffer
+; - rename ultoa => cprintul, change its prototype
+; - add cprintuchar and cprintuint wrappers
+; - got rid of ltoa (don't need it)
+; - hardcode radix to 10
+; - don't need __hextab since we don't do hex (saves 16 bytes)
+; - get rid of dopop subroutine, since the return type is now
+; void, and we don't take a buffer argument that needs returning.
+
+; void __fastcall__ cprintul(unsigned long value);
+
+ .export _cprintulong, _cprintuchar, _cprintuint
+ .import popax, _cputc
+ .importzp sreg, ptr2
+
+radix = 10
+
+ .ifdef CART_TARGET
+ .segment "HIGHCODE"
+ .else
+ .code
+ .endif
+
+ ; char and int wrappers for cprintulong(). basically these are
+ ; the 'casting' code cc65 would emit any time cprintulong() is
+ ; called with a char or int argument. it happens often enough in
+ ; taipan.c that it's worth doing this way:
+
+ ; cprintulong(1) compiles to 11 bytes:
+ ; ldx #$00
+ ; stx sreg
+ ; stx sreg+1
+ ; lda #$01
+ ; jsr _cprintulong
+
+ ; whereas cprintuchar(1) is 5 bytes (saves 6):
+ ; lda #$01
+ ; jsr _cprintuchar
+
+ ; cprintuint(1) is 7 bytes (saves 4, add 'ldx #$00' to the above).
+
+ ; the wrappers are 10 bytes together. so long as we remember to *use*
+ ; them, we only have to use cprintuchar() 2 times and/or cprintuint()
+ ; 3 times to start saving bytes.
+
+_cprintuchar:
+ ldx #0
+_cprintuint:
+ pha
+ lda #0
+ sta sreg
+ sta sreg+1
+ pla
+
+ ; main routine
+_cprintulong:
+ ; high word passed to us in sreg
+ ; low word in ptr2
+ sta ptr2
+ stx ptr2+1
+
+; Convert to string by dividing and push the result onto the stack
+
+ lda #$00
+ pha ; sentinel
+
+; Divide val/radix -> val, remainder in a
+
+L5: ldy #32 ; 32 bit
+ lda #0 ; remainder
+L6: asl ptr2
+ rol ptr2+1
+ rol sreg
+ rol sreg+1
+ rol a
+ cmp #radix
+ bcc L7
+ sbc #radix
+ inc ptr2
+L7: dey
+ bne L6
+
+ ora #'0' ; get ascii character
+ pha ; save char value on stack
+
+ lda ptr2
+ ora ptr2+1
+ ora sreg
+ ora sreg+1
+ bne L5
+
+; Get the characters from the stack, print them.
+
+@print: pla
+ beq @done ; exit if sentinel
+ pha
+ jsr _cputc
+ pla
+ bne @print ; branch always
+
+@done:
+ rts
diff --git a/messages.pl b/messages.pl
index ad53d87..65ade0f 100644
--- a/messages.pl
+++ b/messages.pl
@@ -48,6 +48,7 @@ print "// ratio: " . sprintf("%.1f", $total_out * 100 / $total_in) .
illion "illion" # somehow this wastes 2 bytes
fine "fine"
run "Run" # too short to be worth compression
+how_much_spc "How much "
=cut
__END__
@@ -67,7 +68,6 @@ saigon "Saigon"
manila "Manila"
singapore "Singapore"
batavia "Batavia"
-how_much_spc "How much "
will_you "will you "
bad_joss "Bad Joss!!\r\n"
crlf "\n"
diff --git a/taipan.c b/taipan.c
index 7531ada..e221fc5 100644
--- a/taipan.c
+++ b/taipan.c
@@ -117,6 +117,19 @@ extern void clrtoeol(void);
/* print 'count' spaces: */
extern void __fastcall__ cspaces(unsigned char count);
+/* each prints one specific character */
+extern void cspace(void);
+extern void cputc_s(void);
+extern void cprint_bang(void);
+extern void cprint_pipe(void);
+extern void cprint_period(void);
+
+/* each print 2 characters */
+extern void comma_space(void);
+extern void cprint_question_space(void);
+extern void cprint_colon_space(void);
+extern void cprint_taipan_prompt(void);
+
/* our own clr_screen(), don't use conio's clrscr() */
extern void clr_screen(void);
@@ -182,14 +195,18 @@ unsigned char one_chance_in(unsigned char odds) {
}
/* print 1 space */
+/*
void cspace(void) {
cputc(' ');
}
+*/
/* print the letter s (for pluralization) */
+/*
void cputc_s(void) {
cputc('s');
}
+*/
/* print 'count' spaces, but leave the cursor where it was.
been rewritten in asm, see console.s */
@@ -273,7 +290,11 @@ void retire(void);
void final_stats(void);
void you_only_have(unsigned char in_bank);
-void cprintulong(unsigned long ul);
+/* these 3 are from cprintul.s */
+extern void cprintulong(unsigned long ul);
+extern void cprintuint(unsigned int ui);
+extern void cprintuchar(unsigned char uc);
+
void cprintfancy(unsigned long num);
void cprintfancy_centered(unsigned long num);
void too_much_cash(void);
@@ -414,9 +435,15 @@ long damage = 0, capacity = 60, newdamage;
there are diminishing returns. Anything that only occurs twice
might or might not be worth turning into a function. */
+#ifdef CART_TARGET
+# pragma code-name (push, "HIGHCODE")
+#endif
+
void how_much(void) {
// cputs("How much ");
- print_msg(M_how_much_spc);
+ // print_msg(M_how_much_spc);
+ print_msg(M_how_much);
+ cspace();
}
void how_much_will_you(void) {
@@ -440,24 +467,29 @@ void cprint_taipan(void) {
print_msg(M_taipan);
}
+/*
void comma_space(void) {
cputs(", ");
}
+*/
void cprint_taipan_comma(void) {
cprint_taipan();
comma_space();
}
+/*
void cprint_colon_space(void) {
cputs(": ");
}
+*/
void cprint_taipan_colon(void) {
cprint_taipan();
cprint_colon_space();
}
+/*
void cprint_bang(void) {
cputc('!');
}
@@ -465,6 +497,7 @@ void cprint_bang(void) {
void cprint_pipe(void) {
cputc('|');
}
+*/
void cprint_taipan_bang(void) {
comma_space();
@@ -480,18 +513,23 @@ void cprint_taipan_bangbang(void) {
void cprint_taipan_period(void) {
comma_space();
cprint_taipan();
- cputc('.');
+ // cputc('.');
+ cprint_period();
}
+ /*
void cprint_question_space(void) {
cputs("? ");
}
+*/
+/*
void cprint_taipan_prompt(void) {
comma_space();
cprint_taipan();
cprint_question_space();
}
+*/
void do_you_wish(void) {
// cputs("do you wish ");
@@ -524,6 +562,9 @@ void cprint_firm_colon(void) {
char get_ship_status(void) {
return 100 - ((damage * 100L) / capacity);
}
+#ifdef CART_TARGET
+# pragma code-name (pop)
+#endif
#ifdef BIGNUM
bignum(big1T) = BIG_1T;
@@ -587,9 +628,11 @@ void cprintfancy_big(bignump b) {
cprintulong(leftdigits);
if(rightdigits) {
- cputc('.');
+ // cputc('.');
+ cprint_period();
if(leading0) cputc('0');
- cprintulong((unsigned long)rightdigits);
+ // cprintulong((unsigned long)rightdigits);
+ cprintuchar(rightdigits);
}
if(letter) {
@@ -601,14 +644,20 @@ void cprintfancy_big(bignump b) {
}
#endif
+#ifdef CART_TARGET
+# pragma code-name (push, "HIGHCODE")
+#endif
+
int get_time(void) {
return ((year - 1860) * 12) + month;
}
/* print an int or long as a string, conio-style */
+/*
void cprintulong(unsigned long ul) {
cputs(ultostr(ul, num_buf));
}
+*/
void at_sea(void) {
gotoxy(30, 6);
@@ -659,6 +708,10 @@ void overload(void) {
unsigned int gunamt(void) {
return randi()%(1000 * (get_time() + 5) / 6);
}
+#ifdef CART_TARGET
+# pragma code-name (pop)
+#endif
+
void new_ship(void) {
unsigned long amount;
@@ -679,7 +732,7 @@ void new_ship(void) {
}
// cputs("\r\nship for one with 50 more capacity by\r\npaying an additional ");
print_msg(M_ship_for_one);
- cprintulong(50);
+ cprintuchar(50);
print_msg(M_more_capacity);
cprintfancy(amount);
cprint_taipan_prompt();
@@ -778,7 +831,8 @@ void cprintfancy(unsigned long num) {
tmp = (num % 1000000L) / 100000L;
cprintulong(num / 1000000L);
if(tmp) {
- cputc('.');
+ // cputc('.');
+ cprint_period();
cprintulong(tmp);
}
} else if (num >= 1000000L) {
@@ -789,7 +843,8 @@ void cprintfancy(unsigned long num) {
tmp = (num % 1000000L) / 10000L;
cprintulong(num / 1000000L);
if(tmp) {
- cputc('.');
+ // cputc('.');
+ cprint_period();
if(tmp < 10L) cputc('0');
cprintulong(tmp);
}
@@ -817,19 +872,8 @@ void justify_int(unsigned int num) {
if(num < 1000) cspace();
if(num < 100) cspace();
if(num < 10) cspace();
- cprintulong(num);
-}
-#ifdef CART_TARGET
-# pragma code-name (pop)
-#endif
-
-/*
-void hide_cursor() {
- gotoxy(0,23);
- cspace();
+ cprintuint(num);
}
-*/
-
void update_guns() {
rvs_on();
gotoxy(31, 1);
@@ -866,17 +910,6 @@ void fight_stats(int ships, int orders) {
default: break;
}
- /*
- // switch() saves 15 bytes over this:
- if(orders == 1)
- cputs("Fight");
- else if(orders == 2)
- cputs("Run");
- else if(orders == 3)
- cputs("Throw Cargo");
- */
-
- // hide_cursor();
}
/* print an inverse video plus if there are offscreen ships,
@@ -897,6 +930,10 @@ void set_orders(void) {
}
}
+#ifdef CART_TARGET
+# pragma code-name (pop)
+#endif
+
/* sea_battle only ever returns 1 to 4. making the
return type a char saved 61 bytes! */
char sea_battle(char id, int num_ships) {
@@ -967,7 +1004,7 @@ char sea_battle(char id, int num_ships) {
print_msg(M_cur_seaworth);
cputs(st[status / 20]);
cputs(" (");
- cprintulong(status);
+ cprintuchar(status);
cputs("%)");
gotoxy(0, 4);
@@ -1095,7 +1132,7 @@ char sea_battle(char id, int num_ships) {
if(sk > 0) {
// cputs("Sunk ");
print_msg(M_sunk);
- cprintulong(sk);
+ cprintuint(sk);
// cputs(" of the buggers");
print_msg(M_of_the_buggers);
cprint_taipan_bang();
@@ -1117,7 +1154,7 @@ char sea_battle(char id, int num_ships) {
fight_stats(num_ships, orders);
gotoxy(0, 3);
clrtoeol();
- cprintulong(ran);
+ cprintuint(ran);
// cputs(" ran away");
print_msg(M_ran_away);
cprint_taipan_bang();
@@ -1285,7 +1322,7 @@ char sea_battle(char id, int num_ships) {
clrtoeol();
// cputs("But we escaped from ");
print_msg(M_but_we_escaped);
- cprintulong(lost);
+ cprintuint(lost);
// cputs(" of 'em!");
print_msg(M_of_em);
@@ -1610,16 +1647,16 @@ void port_stats(void)
gotoxy(21, 4);
in_use = warehouse_in_use();
cblank(5);
- cprintulong(in_use);
+ cprintuint(in_use);
gotoxy(21, 6);
cblank(5);
- cprintulong(10000 - in_use);
+ cprintuint(10000 - in_use);
for(i = 0; i < 4; ++i) {
gotoxy(12, i + 3);
cblank(5);
- cprintulong(hkw_[i]);
+ cprintuint(hkw_[i]);
}
/*
@@ -1650,7 +1687,7 @@ void port_stats(void)
gotoxy(22, 8);
cblank(5);
- cprintulong(guns);
+ cprintuint(guns);
for(i = 0; i < 4; ++i) {
gotoxy(12, i + 9);
@@ -1681,7 +1718,7 @@ void port_stats(void)
cputs(months + 4 * (month - 1));
// rvs_off();
cspace();
- cprintulong(year);
+ cprintuint(year);
gotoxy(30, 6);
cblank(10);
@@ -1701,7 +1738,7 @@ void port_stats(void)
// if(i < 2) rvs_on();
cputs(st[i]);
cputc(':');
- cprintulong(status);
+ cprintuint(status);
// rvs_off();
gotoxy(6, 14);
@@ -1747,7 +1784,7 @@ void mchenry(void) {
clear_msg_window();
// cputs("Och, 'tis a pity to be ");
print_msg(M_tis_a_pity);
- cprintulong(percent);
+ cprintuint(percent);
// cputs("% damaged.\r\nWe can fix yer whole ship for ");
print_msg(M_percent_damaged);
cprintulong(repair_price);
@@ -1903,11 +1940,11 @@ void final_stats(void)
cprintulong(capacity);
// cputs(" units with ");
print_msg(M_units_with);
- cprintulong(guns);
+ cprintuint(guns);
// cputs(" guns\r\n\n"
// "You traded for ");
print_msg(M_you_traded_for);
- cprintulong(years);
+ cprintuint(years);
// cputs(" year");
print_msg(M_spc_year);
if (years != 1)
@@ -1916,7 +1953,7 @@ void final_stats(void)
}
// cputs(" and ");
print_msg(M_spc_and_spc);
- cprintulong(month);
+ cprintuchar(month);
// cputs(" month");
print_msg(M_spc_month);
if (month > 1)
@@ -2072,10 +2109,17 @@ char have_no_cargo(void) {
return 1;
}
+#ifdef CART_TARGET
+# pragma code-name (push, "HIGHCODE")
+#endif
void you_have_only(void) {
// cputs("You have only ");
print_msg(M_you_have_only);
}
+#ifdef CART_TARGET
+# pragma code-name (pop)
+#endif
+
void transfer(void)
{
@@ -2134,7 +2178,7 @@ void transfer(void)
gotoxy(0, 21);
// cputs("Your warehouse will only hold an\r\nadditional ");
print_msg(M_whouse_only_hold);
- cprintulong(10000 - in_use);
+ cprintuint(10000 - in_use);
cprint_taipan_bang();
good_joss_sound();
@@ -2184,7 +2228,7 @@ void transfer(void)
// gotoxy(0, 18);
// clrtobot();
you_have_only();
- cprintulong(hkw_[i]);
+ cprintuint(hkw_[i]);
cprint_taipan_period();
// cputs("\r\n");
crlf();
@@ -2264,7 +2308,7 @@ void quit(void)
{
num_ships = 9999;
}
- cprintulong(num_ships);
+ cprintuint(num_ships);
// cputs(" hostile ship");
print_msg(M_hostile_ship);
if(num_ships != 1) cputc_s();
@@ -2320,7 +2364,7 @@ void quit(void)
static int num_ships;
num_ships = randi()%((capacity / 5) + guns) + 5;
- cprintulong(num_ships);
+ cprintuint(num_ships);
/* "ships" will always be plural (at least 5 of them) */
// cputs(" ships of Li Yuen's pirate\r\nfleet");
print_msg(M_ships_of_fleet);
@@ -2666,10 +2710,10 @@ void elder_brother_wu(void)
"additional ");
*/
print_msg(M_aware_of_your_plight);
- cprintulong(i);
+ cprintuint(i);
// cputs(" if you will pay back\r\n");
print_msg(M_if_you_will_pay_back);
- cprintulong(j);
+ cprintuint(j);
// cputs(". Are you willing");
print_msg(M_are_you_willing);
cprint_taipan_prompt();
@@ -2779,7 +2823,7 @@ void elder_brother_wu(void)
compradores_report();
cprint_bad_joss();
- cprintulong(num);
+ cprintuint(num);
/*
cputs(" of your bodyguards have been killed\r\n"
"by cutthroats and you have been robbed\r\n"
@@ -2931,11 +2975,17 @@ int port_choices(void) {
return choice;
}
+#ifdef CART_TARGET
+# pragma code-name (push, "HIGHCODE")
+#endif
void print_bar_line(void) {
cprint_pipe();
cspaces(38);
cprint_pipe();
}
+#ifdef CART_TARGET
+# pragma code-name (pop)
+#endif
/* TODO: rewrite in asm, or at least better C */
void name_firm(void) {
@@ -3146,6 +3196,9 @@ void sell(void) {
return;
}
+#ifdef CART_TARGET
+# pragma code-name (push, "HIGHCODE")
+#endif
char would_overflow(unsigned long a, unsigned long b) {
return ((UINT32_MAX - b) <= a);
}
@@ -3160,6 +3213,10 @@ void too_much_cash(void) {
bad_joss_sound();
timed_getch();
}
+#ifdef CART_TARGET
+# pragma code-name (pop)
+#endif
+
void visit_bank(void)
{
@@ -3355,7 +3412,7 @@ int main(void) {
cprint_elder_brother_wu();
// cputs("has sent ");
print_msg(M_has_sent);
- cprintulong(braves);
+ cprintuint(braves);
// cputs(" braves\r\nto escort you to the Wu mansion");
print_msg(M_braves_to_escort);
cprint_taipan_period();