diff options
author | B. Watson <yalhcru@gmail.com> | 2016-01-15 14:35:01 -0500 |
---|---|---|
committer | B. Watson <yalhcru@gmail.com> | 2016-01-15 14:35:01 -0500 |
commit | ad7bbde98916040e8b527068ead084d009c899d4 (patch) | |
tree | 235d55e35b06a4a38366e9310f859600ddee2ff8 | |
parent | 06f2620ead18279afdd2501c3fef409252aa7ea0 (diff) | |
download | taipan-ad7bbde98916040e8b527068ead084d009c899d4.tar.gz |
check for cash int overflow, WIP
-rw-r--r-- | bignum.h | 36 | ||||
-rw-r--r-- | taipan.c | 124 |
2 files changed, 98 insertions, 62 deletions
@@ -24,6 +24,7 @@ #define bignum(x) char x[6] #define bignump char * +/****** constants ******/ /* zero */ #define BIG_0 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } @@ -41,17 +42,36 @@ /* max value for a ulong */ #define BIG_MAX_ULONG { 0x44, 0x42, 0x94, 0x96, 0x72, 0x95 } +/****** functions ******/ + +/* copy dest to src. could be a wrapper for memcpy() */ extern void __fastcall__ big_copy(bignump dest, bignump src); +/* these 2 would be easy to implement, but aren't really needed */ // void int_to_big(int i, bignum *b); // void uint_to_big(unsigned int i, bignum *b); +/* convert an unsigned long to a bignum */ extern void __fastcall__ ulong_to_big(const unsigned long l, bignump b); -/* returns 0 for success, nonzero for fail (overflow or negative) */ +/* convert a bignum to an unsigned long + returns 0 for success, nonzero for fail (overflow or negative) */ extern char __fastcall__ big_to_ulong(bignump b, unsigned long *l); -// extern unsigned long __fastcall__ cformat_big(char *magnitude, const bignum *b); +/* compare two bignums. like Perl's spaceship operator, <=> + returns | if + ---------+---------------- + 0 | a == b + positive| a > b + negative| a < b + +BEWARE: unlike perl's <=>, the return value is *not* guaranteed to + be 0, 1, or -1. This is more like C's strcmp() or memcmp(). + Do not depend on any particular positive or negative return + value from this: + if(big_cmp(a, b) == -1) // WRONG! + if(big_cmp(a, b) < 0) // Right. */ +extern signed char __fastcall__ big_cmp(bignump a, bignump b); /* basic math functions. conceptually they return a boolean for success, but only division has error checking. @@ -74,19 +94,7 @@ extern char __cdecl__ big_div(bignump dest, bignump dividend, bignump divisor); */ extern char __fastcall__ bank_maxed_out(bignump b); -/* comparison. Perl spaceship operator, <=> - returns | if - ---------+---------------- - 0 | a == b - positive| a > b - negative| a < b - -BEWARE: unlike perl's <=>, the return value is *not* guaranteed to - be 0, 1, or -1. This is more like C's strcmp() or memcmp(). - */ // signed char big_cmp(const bignum *a, const bignum *b) -extern signed char __fastcall__ big_cmp(bignump a, bignump b); - extern unsigned long cformat_big(char *magnitude, bignump b); extern void cprintfancy_big(bignump b); @@ -5,6 +5,7 @@ #include <ctype.h> #include <string.h> /* only for memcpy() */ #include <peekpoke.h> +#include <stdint.h> #include "sounds.h" @@ -208,7 +209,6 @@ char wu_assassin = 0; /* title screen now a separate xex segment (see Makefile for details) */ // void splash_intro(void); -// int get_one(void); #define get_one() agetc(); long get_num(void); void name_firm(void); @@ -227,7 +227,6 @@ void visit_bank(void); void transfer(void); void quit(void); void overload(void); -// void fancy_numbers(unsigned long num, char *fancy); int sea_battle(int id, int num_ships); void fight_stats(int ships, int orders); void mchenry(void); @@ -238,14 +237,12 @@ void you_only_have(unsigned char in_bank); void cprintulong(unsigned long ul); void cprintfancy_ctr(unsigned long num, unsigned char center); #define cprintfancy(num) cprintfancy_ctr(num, 0) +void too_much_cash(void); +char would_overflow(unsigned long a, unsigned long b); unsigned char firmpos; -/* -char firm[23], - fancy_num[24]; - */ - +/* use page 6 for these buffers */ char *firm = (char *) 0x680; char *fancy_buf = (char *) 0x600; @@ -310,6 +307,7 @@ long damage = 0, capacity = 60, newdamage; bignum(big1M) = BIG_1M; bignum(big100M) = BIG_100M; bignum(big1B) = BIG_1B; +bignum(big0) = BIG_0; /* Requires a bit of explanation. b's value will always be zero or @@ -353,10 +351,8 @@ void cprintfancy_big(bignump b) { cprintulong(l); } else { if(l > 100) { - // cprintf("%lu ", l / 10L); cprintulong(l / 10L); } else { - // cprintf("%lu.%lu ", l / 10L, l % 10L); cprintulong(l / 10L); cputc('.'); cprintulong(l % 10L); @@ -423,7 +419,6 @@ void new_ship(void) { int choice = 0, time; - // float amount; unsigned long amount; time = ((year - 1860) * 12) + month; @@ -433,8 +428,6 @@ void new_ship(void) { return; } - // fancy_numbers(amount, fancy_num); - compradores_report(); cputs("Do you wish to trade in your "); if(damage > 0) { @@ -446,7 +439,6 @@ void new_ship(void) { } cputs("\r\nship for one with 50 more capacity by\r\n"); cputs("paying an additional "); - // cputs(fancy_num); cprintfancy(amount); cputs(", Taipan? "); @@ -692,6 +684,9 @@ int sea_battle(int id, int num_ships) { ik = 1; booty = (time / 4 * 1000 * num_ships) + randi()%1000 + 250; + if(would_overflow(cash, booty)) { + booty = 0L; + } for(i = 0; i <= 9; i++) { ships_on_screen[i] = 0; @@ -1577,24 +1572,46 @@ void retire(void) void final_stats(void) { -#ifdef BIGNUM -#else - /* TODO: write cprintlong() to print signed value */ - long finalcash; - int years = year - 1860, time = ((year - 1860) * 12) + month, choice = 0; +#ifdef BIGNUM + long score; + bignum(finalcash); + bignum(big_100) = BIG_100; + bignum(bigscore); + bignum(bigtmp); + + ulong_to_big(cash, finalcash); + ulong_to_big(debt, bigtmp); + big_add(finalcash, finalcash, bank); + big_sub(finalcash, finalcash, bigtmp); + + big_div(bigscore, finalcash, big_100); + ulong_to_big((unsigned long)time, bigtmp); + big_div(bigscore, bigscore, bigtmp); + + if(big_cmp(bigscore, big1M) > 0) + score = 1000000L; + else + big_to_ulong(bigscore, (unsigned long*)&score); +#else + /* TODO: write cprintlong() to print signed value */ + long finalcash = cash + bank - debt; + long score = finalcash / 100 / time; +#endif + port_stat_dirty = 1; clrscr(); cputs("Your final status:\r\n\r\n"); - finalcash = cash + bank - debt; - // fancy_numbers(finalcash, fancy_num); cputs("Net cash: "); - // cputs(fancy_num); +#ifdef BIGNUM + cprintfancy_big(finalcash); +#else cprintfancy(finalcash); +#endif cputs("\r\nShip size: "); cprintulong(capacity); cputs(" units with "); @@ -1615,16 +1632,19 @@ void final_stats(void) cputc('s'); } cputs("\r\n\r\n"); - finalcash = finalcash / 100 / time; revers(1); cputs("Your score is "); - cprintulong(finalcash); +#ifdef BIGNUM + cprintfancy_big(bigscore); +#else + cprintulong(score); cputs(".\r\n"); +#endif revers(0); - if ((finalcash < 100) && (finalcash >= 0)) + if ((score < 100) && (score >= 0)) { cputs("Have you considered a land based job?\r\n\r\n\r\n"); - } else if (finalcash < 0) { + } else if (score < 0) { cputs("The crew has requested that you stay on\r\n"); cputs("shore for their safety!!\r\n\r\n"); } else { @@ -1637,7 +1657,7 @@ void final_stats(void) cputs("\r\n"); cputc('|'); - if (finalcash > 49999L) + if (score > 49999L) { revers(1); } @@ -1646,7 +1666,7 @@ void final_stats(void) cputs(" 50,000 and over |\r\n"); cputc('|'); - if ((finalcash < 50000L) && (finalcash > 7999L)) + if ((score < 50000L) && (score > 7999L)) { revers(1); } @@ -1655,7 +1675,7 @@ void final_stats(void) cputs(" 8,000 to 49,999|\r\n"); cputc('|'); - if ((finalcash < 8000L) && (finalcash > 999L)) + if ((score < 8000L) && (score > 999L)) { revers(1); } @@ -1664,7 +1684,7 @@ void final_stats(void) cputs(" 1,000 to 7,999|\r\n"); cputc('|'); - if ((finalcash < 1000) && (finalcash > 499)) + if ((score < 1000) && (score > 499)) { revers(1); } @@ -1673,7 +1693,7 @@ void final_stats(void) cputs(" 500 to 999|\r\n"); cputc('|'); - if (finalcash < 500) + if (score < 500) { revers(1); } @@ -1689,19 +1709,9 @@ void final_stats(void) cputs("Play again? "); choice = yngetc(0); - /* - while ((choice != 'Y') && (choice != 'y') && - (choice != 'N') && (choice != 'n')) - { - gotoxy(0, 22); - cputs("Play again? "); - choice = get_one(); - } - */ - if(choice == 'y') { #ifdef BIGNUM - bank = BIG_0; + big_copy(bank, big0); #else bank = 0; #endif @@ -1726,7 +1736,6 @@ void final_stats(void) return; } -#endif /* restore ROM character set. TODO: save old PEEK(756) in newtitle.s, restore that here instead of using hardcoded value. */ @@ -2336,11 +2345,11 @@ void elder_brother_wu(void) cputs("borrow? "); wu = get_num(); - if (wu == -1) + if(wu == -1) { wu = (cash * 2); } - if (wu <= (cash * 2)) + if((wu <= (cash * 2)) && !would_overflow(cash, wu)) { cash += wu; debt += wu; @@ -2708,6 +2717,12 @@ void sell(void) { { amount = hold_[choice]; } + + if(would_overflow(cash, amount)) { + too_much_cash(); + continue; + } + if (hold_[choice] >= amount) { hold_[choice] -= amount; @@ -2721,6 +2736,18 @@ void sell(void) { return; } +char would_overflow(unsigned long a, unsigned long b) { + return ((UINT32_MAX - b) <= a); +} + +void too_much_cash(void) { + cputs("\r\nYou cannot carry so much cash, Taipan!"); + cputs("\r\nYour ship would sink under the weight"); + cputs("\r\nof your riches.\r\n"); + bad_joss_sound(); + timed_getch(TMOUT_3S); +} + void visit_bank(void) { long amount = 0; @@ -2772,6 +2799,8 @@ void visit_bank(void) ulong_to_big(cash, bigcash); big_sub(biglimit, big_max_ulong, bigcash); + + /* cputs("\rcash "); cprintfancy_big(bigcash); agetc(); @@ -2781,11 +2810,10 @@ void visit_bank(void) cputs("\rlimit "); cprintfancy_big(biglimit); agetc(); + */ + if(big_cmp(bigamt, biglimit) >= 0) { -// hangx: goto hangx; - cputs("\r\nYou cannot carry so much cash, Taipan!"); - bad_joss_sound(); - timed_getch(TMOUT_1S); + too_much_cash(); continue; } |