aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--strtonum.c57
-rw-r--r--taipan.c8
3 files changed, 65 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index 5233651..143fc9b 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/taipan.c b/taipan.c
index 9380d1d..3c58c47 100644
--- a/taipan.c
+++ b/taipan.c
@@ -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 */