/* big number functions needed by taipan.c. The implementation will actually use the Atari ROM floating point routines. To port Taipan to a new cc65 platform, the functions listed here will have to be rewritten, but taipan.c itself shouldn't need changing (at least, not in relation to bignums!) Why call them "bignums" instead of "Float" or something? because the whole implementation might get ripped out & replaced with 64-bit integers, or some other data type. The API shouldn't change in that case. to declare a bignum: bignum(foo); ...foo actually ends up a pointer (a bignump), which can be passed around to the various big_* functions. to use the constants: bignum(foo) = BIG_0; which looks a little weird I admit. */ #define bignum(x) char x[6] #define bignump char * /* zero */ #define BIG_0 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } /* constant initializer for 1.005 goes here */ #define BIG_1_005 { 0x40, 0x01, 0x00, 0x50, 0x00, 0x00 } /* bignum 100, used for score calculations in final_stats() */ #define BIG_100 { 0x41, 0x01, 0x00, 0x00, 0x00, 0x00 } /* one million, one hundred million, and one billion */ #define BIG_1M { 0x43, 0x01, 0x00, 0x00, 0x00, 0x00 } #define BIG_100M { 0x44, 0x01, 0x00, 0x00, 0x00, 0x00 } #define BIG_1B { 0x44, 0x10, 0x00, 0x00, 0x00, 0x00 } /* max value for a ulong */ #define BIG_MAX_ULONG { 0x44, 0x42, 0x94, 0x96, 0x72, 0x95 } extern void __fastcall__ big_copy(bignump dest, bignump src); // void int_to_big(int i, bignum *b); // void uint_to_big(unsigned int i, bignum *b); extern void __fastcall__ ulong_to_big(const unsigned long l, bignump b); /* 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); /* basic math functions. conceptually they return a boolean for success, but only division has error checking. all can be read as: dest = arg2 OP arg3; modulus isn't implemented as taipan doesn't use it for the bank. These are __cdecl__ *not* __fastcall__ !! */ extern char __cdecl__ big_add(bignump dest, bignump addend1, bignump addend2); extern char __cdecl__ big_sub(bignump dest, bignump minuend, bignump subtrahend); extern char __cdecl__ big_mul(bignump dest, bignump multiplicand, bignump multiplier); extern char __cdecl__ big_div(bignump dest, bignump dividend, bignump divisor); /* returns true if the bank is maxed out. We do this by checking the exponent byte, so the "max" is tied to the bignum implementation, which is why its prototype is here rather than bank.h. For Atari floats, it's 1.0e+14, or 100 trillion. If you deposit 1 in the bank at the start of the game and never deposit more, the interest will max it out in 1915 (661 turns of play). */ 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);