diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | strtonum.c | 57 | ||||
-rw-r--r-- | taipan.c | 8 |
3 files changed, 65 insertions, 2 deletions
@@ -98,7 +98,7 @@ XEX=taipan.xex # All the C and asm sources for taimain.xex: TAIMAIN_HDRS=sounds.h -TAIMAIN_C_SRC=taipan.c +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 # Comment these lines out to build without big number support. diff --git a/strtonum.c b/strtonum.c new file mode 100644 index 0000000..65bd718 --- /dev/null +++ b/strtonum.c @@ -0,0 +1,57 @@ +#include <limits.h> + +/* Convert a string to a long unsigned int, tiny version. + Based on strtoul.c from cc65 libsrc, but stripped down: + - only supports base 10. + - no leading +, -, 0, 0x support. + - does not skip leading spaces. + - returns ULONG_MAX on overflow, but does not set errno. + - overflows at 4294967290 rather than 4294967296. + - no endptr argument, so no way to tell how many character + were converted. + + taipan's input routines stop the player from typing invalid + characters, so nobody will miss the error checking. using + this instead of strtoul saves 743 bytes. + */ + +/* ULONG_MAX / 10 */ +#define MAX_VAL 429496729 + +unsigned long __fastcall__ strtonum(const char* nptr) { + unsigned long ret = 0; + unsigned char digit; + + /* Convert the number */ + while(*nptr >= '0' && *nptr <= '9') { + /* Convert the digit into a numeric value */ + digit = *nptr - '0'; + + /* Don't accept anything that makes the final value invalid */ + if(ret > MAX_VAL) + return ULONG_MAX; + + /* Calculate the next value if digit is not invalid */ + ret = (ret * 10) + digit; + + /* Next character from input */ + ++nptr; + } + + /* Return the result */ + return ret; +} + +#ifdef STRTONUM_TEST +#include <stdio.h> +int main(void) { + printf("%lu\n", strtonum("123")); + printf("%lu\n", strtonum("98765")); + printf("%lu\n", strtonum("429496730")); + printf("%lu\n", strtonum("4294967295")); + printf("%lu\n", strtonum("5555555555")); + printf("%lu\n", strtonum(" ")); +hang: goto hang; + return 0; +} +#endif @@ -1,3 +1,5 @@ +// TODO: replace conio with coffio + #include <conio.h> #include <time.h> #include <stdlib.h> @@ -250,6 +252,9 @@ void cprint_taipan_prompt(void); void cprint_elder_brother_wu(void); void cprint_li_yuen(void); +/* local replacement for strtoul, see strtonum.c */ +unsigned long __fastcall__ strtonum(const char* nptr); + unsigned char firmpos; /* use page 6 for these buffers, for .xex build. Otherwise they'e BSS. */ @@ -1362,7 +1367,8 @@ unsigned long get_num(void) { } // cursor(0); num_buf[count] = '\0'; - return strtoul(num_buf, (char **)NULL, 10); + // return strtoul(num_buf, (char **)NULL, 10); + return strtonum(num_buf); } /* TODO: rewrite in asm */ |