aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile19
-rw-r--r--README.txt36
-rw-r--r--mkver.pl26
-rw-r--r--newtitle.pl5
-rw-r--r--newtitle.s41
-rw-r--r--taipan.c441
-rw-r--r--timed_getch.s108
-rw-r--r--ver.datbin0 -> 40 bytes
8 files changed, 482 insertions, 194 deletions
diff --git a/Makefile b/Makefile
index 92b1611..4973550 100644
--- a/Makefile
+++ b/Makefile
@@ -13,9 +13,14 @@ SYS=atari
#COPT=-Oirs
COPT=-O
-# This is used for embedding the date and git hash in the game binary.
-# It'll appear on the "name your firm" screen.
-VERSION="v0.99alpha-`date +%Y%m%d`-`git rev-parse --short HEAD 2>/dev/null || echo UNKNOWN`"
+# This is used for embedding the date and git info in the game binary.
+# It'll appear on the title screen.
+VER=0.99alpha
+TODAY=`date +%Y%m%d`
+#BRANCH=`( git branch 2> /dev/null || echo ' NOGIT' )| cut -d' ' -f2`
+REV=`git rev-parse --short HEAD 2>/dev/null || echo UNKNOWN`
+#VERSION="v$(VER)-$(TODAY)-$(BRANCH)-$(REV)"
+VERSION="v$(VER)-$(TODAY)-$(REV)"
# for older cc65, we need a custom linker file.
#CFLAGS=-t $(SYS) -C custom.cfg -I. -L. $(COPT)
@@ -30,7 +35,8 @@ VERSION="v0.99alpha-`date +%Y%m%d`-`git rev-parse --short HEAD 2>/dev/null || ec
# and I never missed it.
# The meaning of the -l flag is different between cc65-2.13.3
# and the later github cc65, so it's been removed here.
-CFLAGS=-t $(SYS) -T -I. -L. -DVERSION=\"$(VERSION)\" -Wl -D__SYSTEM_CHECK__=1 -Wl -D__RESERVED_MEMORY__=1056 $(COPT)
+#CFLAGS=-t $(SYS) -T -I. -L. -DVERSION=\"$(VERSION)\" -Wl -D__SYSTEM_CHECK__=1 -Wl -D__RESERVED_MEMORY__=1056 $(COPT)
+CFLAGS=-t $(SYS) -T -I. -L. -Wl -D__SYSTEM_CHECK__=1 -Wl -D__RESERVED_MEMORY__=1056 $(COPT)
AS=ca65
ASFLAGS=
AR=ar65
@@ -87,9 +93,12 @@ titledata.xex: newtitle.pl newtitle.png
# since it's a lot easier to homebrew an init segment than it is
# to get cc65 to build an init segment (would need a custom linker
# script at least).
-newtitle.xex: newtitle.s
+newtitle.xex: newtitle.s ver.dat
cl65 -o newtitle.xex -t none newtitle.s
+ver.dat: mkver.pl
+ perl mkver.pl $(VERSION) > ver.dat
+
# former textmode title screen, was generated by TITLE.LST. Replaced
# by graphical title screen.
#title.xex: TITLE.DAT
diff --git a/README.txt b/README.txt
index c0e1c1e..065557a 100644
--- a/README.txt
+++ b/README.txt
@@ -141,14 +141,6 @@ Bugs! At least these:
- A few things in the screen layout are slightly off comapred to
the Apple version. Would really like to get it exact.
-- Control and graphics characters should be ignored at all input
- prompts. Inverse video input should either be converted to
- normal, or completely ignored.
-
-- Pressing either the inverse or caps-lock key at a timed prompt stops
- the timer from ever expiring (until you press a regular key). This
- can be fixed in timed_getch().
-
- The 'Please limit your firm name to 22 characters' prompt is missing.
The Apple version actually allows you to type all you want until you
press Enter. This port works like the Linux version: as soon as you type
@@ -158,8 +150,10 @@ Bugs! At least these:
- Damaged ship graphics need work. I don't have enough unused font
characters to duplicate the Apple bitmapped graphics exactly, plus
- each damage location must fit entirely within a character cell... but
- a couple of my damaged sections are pretty hokey-looking.
+ each damage location must fit entirely within a character cell... but a
+ couple of my damaged sections are pretty hokey-looking. Also, now that
+ I'm using the graphical title screen, I have a few more characters I
+ can redefine as damaged ship sections.
- fancy_numbers() maybe should round when it's showing a decimal point.
If you have e.g. 1,190,000, that should show as 1.2 million, not 1.1...
@@ -169,8 +163,9 @@ Bugs! At least these:
said 4 billion ships were attacking (number of ships must have gone
negative).
-- After a fight, "Arriving at Manila" or such appears on the fight screen
- without clearing it first (if you ran away, you can still see ships).
+- After a fight, "Arriving at Manila" or such sometimes appears on the
+ fight screen without clearing it first (if you ran away, you can still
+ see ships).
Differences between the Apple II original and Linux port:
@@ -200,9 +195,24 @@ version is annoying anyway).
Right now, items 1, 2, 4, 5, 7, 8, and 9 are implemented Apple-style;
and 3, 6, 10 are Linux-style.
+I've made a few changes to the UI, compared to the Apple version:
+
+- Prompts that only accept one character no longer require pressing Enter.
+ Gameplay is more streamlined this way. Apple and Linux are inconsistent:
+ some prompts need Enter, some don't. In the Atari port, the only prompts
+ that require Enter are:
+ - naming your firm
+ - entering a cash amount (but not if you hit a for "all")
+
+- "We have 5 guns" is in an inverse video box. I think it looks nicer, and
+ it matches the "You can afford 5" inverse video box on the trading
+ screen.
+
+- "You're ship is overloaded" => "Your ship is overloaded".
+
Other things that need doing to the code:
-- Size optimization. Right now, the executable is almost 29K of code. I'd
+- Size optimization. Right now, the executable is almost 27K of code. I'd
like it to at least fit on a 16K cartridge. A lot of the C code is
redundant, and some things can be rewritten in asm if need be. I've
already eliminated all uses of printf() and its ilk, which removed 2K
diff --git a/mkver.pl b/mkver.pl
new file mode 100644
index 0000000..c76ccc8
--- /dev/null
+++ b/mkver.pl
@@ -0,0 +1,26 @@
+#!/usr/bin/perl -w
+
+# turn version string into raw screen data, so we can easily display
+# it on the title screen.
+
+use bytes;
+my $ver = shift;
+
+if(length($ver) > 32) {
+ warn "$0: version string > 32 chars, will be cut off!\n";
+ substr($ver, 32) = "";
+}
+
+$blanks = 40;
+for(map { ord } split "", $ver) {
+ my $byte = $_;
+ if($_ < 32) {
+ $byte += 64;
+ } elsif($_ >= 32 && $_ <= 96) {
+ $byte -= 32;
+ }
+ print chr($byte);
+ $blanks--;
+}
+
+print chr(0) x $blanks;
diff --git a/newtitle.pl b/newtitle.pl
index 8daae62..a5cf2d2 100644
--- a/newtitle.pl
+++ b/newtitle.pl
@@ -30,8 +30,9 @@ for $y (0..183) {
# have an LMS for the 2nd half. Since we're using narrow
# playfield mode, we don't have to leave a hole in the data,
# just make sure it gets loaded to an address aligned to a
-# 32-byte boundary. I choose $3000 for now.
-$load = 0x3000;
+# 32-byte boundary. It's getting loaded at $9000 so it can
+# stay in memory while the rest of the game loads.
+$load = 0x9000;
$len = scalar @bytes;
$end = $load + $len - 1;
print chr(0xff), chr(0xff);
diff --git a/newtitle.s b/newtitle.s
index ae54481..f52ac57 100644
--- a/newtitle.s
+++ b/newtitle.s
@@ -5,16 +5,19 @@
.include "atari.inc"
; where our screen was loaded (see newtitle.pl)
-screendata = $3000
+screendata = $9000
; homebrew atari xex header
.word $ffff
- .word start
+ .word version
.word end-1
- .org $5000 ; anywhere that doesn't step on the title data at
- ; $3000, and doesn't cross a 1K boundary (since there's
- ; a display list included here)
+ ; needs to be above the BSS (see taipan.map). we'll place it right at
+ ; the end of screendata.
+ .org $a800
+
+version:
+ .incbin "ver.dat"
; executable code here
start:
@@ -60,18 +63,20 @@ wait4key:
sta CH
; restore OS's display list
- lda #0
- sta SDMCTL ; disable screen again
- lda FR0
- sta SDLSTL
- lda FR0+1
- sta SDLSTH
+ ;lda #0
+ ;sta SDMCTL ; disable screen again
+ ;lda FR0
+ ;sta SDLSTL
+ ;lda FR0+1
+ ;sta SDLSTH
- jsr wait1jiffy
+ ;jsr wait1jiffy
- ; switch to normal playfield, enable screen
- lda #$22
- sta SDMCTL
+ ; switch to normal playfield, enable screen. this is now
+ ; done in atari_text_setup() in taipan.c, so the title screen
+ ; can keep displaying.
+ ;lda #$22
+ ;sta SDMCTL
rts ; return to DOS
@@ -87,7 +92,7 @@ dlist:
.byte $70 ; 24 scanlines of blanks
.byte $70
.byte $70
- .byte $30 ; 4 more since image is only 184 lines tall
+; .byte $30 ; 4 more since image is only 184 lines tall
.byte $0f | $40 ; LMS, BASIC mode 8
.word screendata
@@ -100,7 +105,9 @@ dlist:
.repeat 55
.byte $0f ; 55 more scanlines of mode 8
.endrepeat
- .byte $30 ; blank 4 lines to match GR.8 (does it even matter?)
+; .byte $30 ; blank 4 lines to match GR.8 (does it even matter?)
+ .byte $02 | $40 ; LMS, 1 line of GR.0 for the version
+ .word version
.byte $41 ; JVB, jump & wait for vblank
.word dlist
diff --git a/taipan.c b/taipan.c
index 8080d13..2a8bc2d 100644
--- a/taipan.c
+++ b/taipan.c
@@ -20,12 +20,6 @@
/**** atari-specific stuff */
-void atari_text_setup() {
- POKE(710, 0xc0); // green background
- POKE(709, 0x0c); // bright text
- POKE(756, 0xb8); // use our custom font
-}
-
/* values returned by cgetc() for backspace & enter keys */
#define BKSP 0x7e
#define ENTER 0x9b
@@ -40,6 +34,22 @@ void atari_text_setup() {
/* wait up to j jiffies for a keypress. returns -1 if no key pressed */
extern int __fastcall__ timed_getch(unsigned int j);
+/* custom Atari-aware cgetc() wrapper. returns only non-inverse
+ plain ASCII characters, except EOL and BS. Unlike the real cgetc(),
+ it's an unsigned char, and can't return -1 for failure (but, it will never
+ fail. real cgetc() never fails either, even if user hits Break) */
+extern unsigned char agetc(void);
+
+/* wrapper for agetc(): lowercases letters */
+extern unsigned char lcgetc(void);
+
+/* wrapper for agetc(): returns only numbers, enter, backspace */
+extern unsigned char numgetc(void);
+
+/* wrapper for agetc(): returns only y or n.
+ dflt is 'y' 'n' to set the default answer, or 0 for no default. */
+extern unsigned char __fastcall__ yngetc(char dflt);
+
/* sleep for j jiffies (no PAL adjustment at the moment) */
extern void __fastcall__ jsleep(unsigned int j);
@@ -53,7 +63,10 @@ extern void __fastcall__ jsleep(unsigned int j);
*/
#define initrand() /* no-op on Atari */
+/* random positive int, 0 to 32767 */
extern unsigned int __fastcall__ randi(void);
+
+/* random long, 0 to 2**32-1 */
extern unsigned long __fastcall__ randl(void);
/* defined in portstat.s, this is the contents of PORTSTAT.DAT.
@@ -68,9 +81,29 @@ char port_stat_dirty = 1;
/* asm curses/conio funcs from clrtobot.s. Old C versions moved to
oldcurses.c for reference. */
-extern void clrtobot();
-extern void clrtoeol();
+extern void clrtobot(void);
+extern void clrtoeol(void);
+/* asm funcs from draw_lorcha.s for drawing/animating enemy ships.
+ used by sea_battle() */
+extern void __fastcall__ draw_lorcha(int which);
+extern void __fastcall__ flash_lorcha(int which);
+extern void __fastcall__ damage_lorcha(int which);
+extern void __fastcall__ sink_lorcha(int which);
+extern void __fastcall__ clear_lorcha(int which);
+
+void atari_text_setup() {
+ jsleep(1);
+ POKE(560, PEEK(212)); // restore the
+ POKE(561, PEEK(213)); // display list
+ jsleep(1);
+ POKE(559, 34); // turn on the screen (normal playfield)
+ jsleep(1);
+ POKE(710, 0xc0); // green background
+ POKE(709, 0x0c); // bright text
+ POKE(756, 0xb8); // use our custom font
+ POKE(731, 1); // disable keyclick on XL/XE (does nothing on 400/800)
+}
/**** End of atari-specific stuff */
@@ -85,38 +118,48 @@ unsigned long randclamp(unsigned long clamp) {
return r % clamp;
}
-/* wrapper for cgetc() that returns letters as lowercase only
- (and everything else normally). Avoids a bunch of reduntant
- if(foo == 'A' || foo == 'a') tests. */
-int lcgetc() {
- return tolower(cgetc());
-}
-
/* print 'count' spaces, but leave the cursor where it was.
- doesn't work if the cursor wraps to the next line!
- TODO: rewrite in asm.
- */
+ TODO: rewrite in asm. */
void cblank(unsigned char count) {
char oldx = wherex();
+ char oldy = wherey();
while(count--) cputc(' ');
- gotox(oldx);
+ gotoxy(oldx, oldy);
}
/* conio doesn't back up the cursor if you cputc(BS), it
- prints the graphics character instead. So: */
+ prints the graphics character instead. Could use putchar(),
+ but using stdio links a bunch of extra support code. So: */
+/* TODO: rewrite in asm */
void backspace() {
gotox(wherex()-1);
cblank(1);
}
+unsigned char get_item(unsigned char allow_all) {
+ unsigned char i;
+ for(;;) {
+ i = lcgetc();
+ switch(i) {
+ case 'o': return 0;
+ case 's': return 1;
+ case 'a': return 2;
+ case 'g': return 3;
+ case '*': if(allow_all) return 4; /* else fall thru */
+ default: break;
+ }
+ }
+}
/* taipan functions (modified as little as possible) */
#define GENERIC 1
#define LI_YUEN 2
+/* title screen now a separate xex segment (see Makefile for details) */
// void splash_intro(void);
+
int get_one(void);
-unsigned long get_num(int maxlen);
+long get_num(void);
void name_firm(void);
void cash_or_guns(void);
void set_prices(void);
@@ -135,11 +178,6 @@ void quit(void);
void overload(void);
void fancy_numbers(unsigned long num, char *fancy);
int sea_battle(int id, int num_ships);
-extern void __fastcall__ draw_lorcha(int which);
-extern void __fastcall__ flash_lorcha(int which);
-extern void __fastcall__ damage_lorcha(int which);
-extern void __fastcall__ sink_lorcha(int which);
-extern void __fastcall__ clear_lorcha(int which);
void fight_stats(int ships, int orders);
void mchenry(void);
void retire(void);
@@ -194,6 +232,7 @@ int newdamage;
// void cprintfancy(unsigned long ul) {
// }
/* print an int or long as a string, conio-style */
+
void cprintulong(unsigned long ul) {
cputs(ultoa(ul, fancy_num, 10));
}
@@ -229,16 +268,14 @@ void captains_report() {
}
-void overload(void)
-{
+void overload(void) {
compradores_report();
cputs("Your ship is overloaded, Taipan!!");
timed_getch(TMOUT_5S);
return;
}
-void new_ship(void)
-{
+void new_ship(void) {
int choice = 0,
time;
@@ -248,8 +285,7 @@ void new_ship(void)
time = ((year - 1860) * 12) + month;
amount = randi()%(1000 * (time + 5) / 6) * (capacity / 50) + 1000;
- if (cash < amount)
- {
+ if(cash < amount) {
return;
}
@@ -257,8 +293,7 @@ void new_ship(void)
compradores_report();
cputs("Do you wish to trade in your ");
- if (damage > 0)
- {
+ if(damage > 0) {
revers(1);
cputs("damaged");
revers(0);
@@ -270,6 +305,15 @@ void new_ship(void)
cputs(fancy_num);
cputs(", Taipan? ");
+ choice = yngetc(0);
+ if(choice == 'y') {
+ cash -= amount;
+ hold += 50;
+ capacity += 50;
+ damage = 0;
+ }
+
+ /*
while ((choice != 'Y') && (choice != 'y') &&
(choice != 'N') && (choice != 'n'))
{
@@ -283,6 +327,7 @@ void new_ship(void)
capacity += 50;
damage = 0;
}
+ */
if ((randi()%2 == 0) && (guns < 1000))
{
@@ -316,6 +361,14 @@ void new_gun(void)
cputs(fancy_num);
cputs(", Taipan? ");
+ choice = yngetc(0);
+ if(choice == 'y') {
+ cash -= amount;
+ hold -= 10;
+ guns += 1;
+ }
+
+ /*
while ((choice != 'Y') && (choice != 'y') &&
(choice != 'N') && (choice != 'n'))
{
@@ -328,6 +381,7 @@ void new_gun(void)
hold -= 10;
guns += 1;
}
+ */
port_stats();
@@ -336,10 +390,6 @@ void new_gun(void)
void fancy_numbers(unsigned long num, char *fancy)
{
- /* note to self: find out why there's graphic corruption
- if this isn't static. It's caused by sprintf() or strcpy()
- writing to the font, which is supposed to be above cc65's max
- usable address! */
static char number[18];
char mil = 0;
unsigned int num1, num2;
@@ -499,12 +549,11 @@ int sea_battle(int id, int num_ships) {
if(orders == 0) {
input = timed_getch(TMOUT_3S);
- if (input == 'f')
- {
+ if (input == 'f') {
orders = 1;
- } else if ((input == 'R') || (input == 'r')) {
+ } else if(input == 'r') {
orders = 2;
- } else if ((input == 'T') || (input == 't')) {
+ } else if(input == 't') {
orders = 3;
} else {
gotoxy(0, 3);
@@ -521,9 +570,9 @@ int sea_battle(int id, int num_ships) {
clrtoeol();
gotoxy(0, 4);
clrtoeol();
- if (input == 'f') {
+ if(input == 'f') {
orders = 1;
- } else if (input == 'r') {
+ } else if(input == 'r') {
orders = 2;
} else {
orders = 3;
@@ -701,14 +750,15 @@ int sea_battle(int id, int num_ships) {
clrtoeol();
cputs("What shall I throw overboard, Taipan? ");
- /* TODO: this, buy(), sell() have common code */
+ choice = get_item(1);
+ /*
while ((choice != 'o') &&
(choice != 's') &&
(choice != 'a') &&
(choice != 'g') &&
(choice != '*'))
{
- choice = tolower(get_one());
+ choice = lcgetc();
}
if(choice == 'o') {
@@ -722,13 +772,14 @@ int sea_battle(int id, int num_ships) {
} else {
choice = 4;
}
+ */
if(choice < 4) {
gotoxy(0, 3);
clrtoeol();
cputs("How much, Taipan? ");
- amount = get_num(9);
+ amount = get_num();
if((hold_[choice] > 0) && ((amount == -1) || (amount > hold_[choice])))
{
amount = hold_[choice];
@@ -799,7 +850,6 @@ int sea_battle(int id, int num_ships) {
fight_stats(num_ships, orders);
gotoxy(0, 3);
clrtoeol();
- // printw("But we escaped from %d of 'em!", lost);
cputs("But we escaped from ");
cprintulong(lost);
cputs(" of 'em!");
@@ -815,12 +865,6 @@ int sea_battle(int id, int num_ships) {
}
}
plus_or_space(num_ships > num_on_screen);
- /*
- if(num_ships == num_on_screen) {
- gotoxy(39, 7);
- cputc(' ');
- }
- */
}
gotoxy(0, 16);
@@ -943,7 +987,23 @@ int sea_battle(int id, int num_ships) {
}
}
-/* TODO: rewrite in asm */
+#if 0
+/* TODO: rewrite in asm
+ get_one() gets one character of input, but waits for Enter
+ to be pressed, and allows backspacing over it.
+ Honestly I don't see the value in using this instead of
+ cgetc(). Plenty of prompts in the game (e.g. Buy/Sell/Quit Trading),
+ and all the stuff in combat, just accept one character without
+ need to press Enter.
+ This is called from:
+ mchenry() (y or n)
+ cash_or_guns() (1 or 2)
+ final_stats() (play again, y or n)
+ li_yuen_extortion() (y or n, twice)
+ elder_brother_wu() (y or n, twice)
+ buy() (for picking item)
+ sell() (idem)
+ */
int get_one(void)
{
int input,
@@ -978,11 +1038,18 @@ int get_one(void)
return choice;
}
+#else
+int get_one(void) {
+ cursor(1);
+ cblank(1);
+ return agetc();
+}
+#endif
/* TODO: rewrite in asm. Maybe. */
+#if 0
unsigned long get_num(int maxlen)
{
- /* see comment in fancy_numbers for why this is static */
static char number[20];
int input,
@@ -1029,6 +1096,33 @@ unsigned long get_num(int maxlen)
cursor(0);
return amount;
}
+#else
+long get_num(void) {
+ static char number[20];
+ unsigned char count = 0;
+ int input;
+
+ cursor(1);
+ cblank(1);
+
+ while((input = numgetc()) != '\n') {
+ if(input == BKSP) {
+ if(!count) continue;
+ backspace();
+ number[count] = '\0';
+ count--;
+ } else if(input == 'a') {
+ if(!count) return -1;
+ } else {
+ cputc(input);
+ number[count] = input;
+ count++;
+ }
+ }
+ cursor(0);
+ return strtol(number, (char **)NULL, 10);
+}
+#endif
/* TODO: rewrite in asm */
void cash_or_guns(void)
@@ -1215,7 +1309,6 @@ void port_stats(void)
cputsxy(30, 6, location[port]);
revers(0);
- // gotoxy(33, 9);
gotoy(9);
fancy_numbers(debt, fancy_num);
gotox(33 - strlen(fancy_num) / 2);
@@ -1245,48 +1338,9 @@ void port_stats(void)
cputs(fancy_num);
}
-/* Unlike the Linux port, splash_intro() doesn't have to draw
- the "programmed by" etc. text in the intro screen, as it's
- preloaded into screen memory as a xex segment... but it
- means splash_intro() can *only* be called by main(), once,
- at program startup. So we don't get a 2nd splash intro
- when answering Y to 'Play Again?".
- Ideally, I should redefine enough graphics characters
- that I can draw a nice ATASCII trading ship. But for
- now I'll just draw 6 of the lorchas.
- */
-#if 0
-void splash_intro(void)
-{
- int i;
-
- cursor(0);
- gotoxy(0,23);
-#ifdef VERSION
- cputs(VERSION);
-#else
- cputs("(no version info)");
-#endif
-
- /* if we print anything in this function, the character at (2,0)
- gets inversed because the OS placed a cursor there. Fix it: */
- gotoxy(2,0);
- cputc(0xa0);
-
- for(i=0; i<3; i++) draw_lorcha(i);
- for(i=5; i<8; i++) draw_lorcha(i);
-
- timed_getch(TMOUT_5M);
-
- flushinp();
- return;
-}
-#endif
-
void mchenry(void)
{
static int choice;
- choice = 0;
compradores_report();
cputs("Taipan, Mc Henry from the Hong Kong\r\n");
@@ -1294,14 +1348,16 @@ void mchenry(void)
cputs("ye've a wee bit of damage to yer ship.'\r\n");
cputs("Will ye be wanting repairs? ");
+ choice = yngetc('y');
+ /*
while ((choice != 'Y') && (choice != 'y') &&
(choice != 'N') && (choice != 'n'))
{
choice = get_one();
}
+ */
- if ((choice == 'Y') || (choice == 'y'))
- {
+ if(choice == 'y') {
static int percent, time;
static long br, repair_price, amount;
// int percent = ((float) damage / capacity) * 100,
@@ -1329,7 +1385,7 @@ void mchenry(void)
for (;;) {
gotoxy(24, 21);
- amount = get_num(9);
+ amount = get_num();
if(amount == -1) {
if(cash > repair_price)
amount = repair_price;
@@ -1468,6 +1524,11 @@ void final_stats(void)
chline(31);
cputc(3); // lower right corner
+ gotoxy(0, 22);
+ cputs("Play again? ");
+ choice = yngetc(0);
+
+ /*
while ((choice != 'Y') && (choice != 'y') &&
(choice != 'N') && (choice != 'n'))
{
@@ -1475,9 +1536,9 @@ void final_stats(void)
cputs("Play again? ");
choice = get_one();
}
+ */
- if ((choice == 'Y') || (choice == 'y'))
- {
+ if(choice == 'y') {
bank = 0;
hkw_[0] = 0;
hkw_[1] = 0;
@@ -1494,7 +1555,6 @@ void final_stats(void)
year = 1860;
port = 1;
- // splash_intro();
name_firm();
cash_or_guns();
set_prices();
@@ -1537,7 +1597,7 @@ void transfer(void)
cputs(item[i]);
cputs(" shall I move\r\nto the warehouse, Taipan? ");
- amount = get_num(9);
+ amount = get_num();
if (amount == -1)
{
amount = hold_[i];
@@ -1584,7 +1644,7 @@ void transfer(void)
cputs(item[i]);
cputs(" shall I move\r\naboard ship, Taipan? ");
- amount = get_num(9);
+ amount = get_num();
if (amount == -1)
{
amount = hkw_[i];
@@ -1629,7 +1689,7 @@ void quit(void)
gotoxy(13, 21);
clrtobot();
- choice = get_num(1);
+ choice = numgetc() - '0';
if (choice == port)
{
@@ -1951,7 +2011,8 @@ void elder_brother_wu(void)
{
gotoxy(21, 19);
- choice = get_one();
+ // choice = get_one();
+ choice = yngetc('n');
if ((choice == 'N') || (choice == 'n') || choice == 0)
{
break;
@@ -2008,7 +2069,7 @@ void elder_brother_wu(void)
cputs("How much do you wish to repay\r\n");
cputs("him? ");
- wu = get_num(9);
+ wu = get_num();
if (wu == -1)
{
wu = cash;
@@ -2048,7 +2109,7 @@ void elder_brother_wu(void)
cputs("How much do you wish to\r\n");
cputs("borrow? ");
- wu = get_num(9);
+ wu = get_num();
if (wu == -1)
{
wu = (cash * 2);
@@ -2092,12 +2153,15 @@ void elder_brother_wu(void)
void good_prices(void)
{
- /* see comment in fancy_numbers for why this is static */
- static char item[14];
+ // static char item[14];
+ unsigned char i = randi()%4;
+ /*
int i = randi()%4,
j = randi()%2;
+ */
+ /*
if (i == 0)
{
strcpy(item, "Opium");
@@ -2108,11 +2172,23 @@ void good_prices(void)
} else {
strcpy(item, "General Cargo");
}
+ */
compradores_report();
cputs("Taipan!! The price of ");
- cputs(item);
+ // cputs(item);
+ cputs(item[i]);
cputs("\r\n has ");
+ if(randi()&1) {
+ price[i] *= (randi()%5 + 5);
+ cputs("risen");
+ } else {
+ price[i] /= 5;
+ cputs("dropped");
+ }
+ cputs(" to ");
+
+ /*
if (j == 0)
{
price[i] = price[i] / 5;
@@ -2122,12 +2198,15 @@ void good_prices(void)
cputs("risen");
}
cputs(" to ");
+ */
+
cprintulong(price[i]);
cputs("!!\r\n");
timed_getch(TMOUT_3S);
}
+#if 0
int port_choices(void)
{
int choice = 0;
@@ -2159,13 +2238,13 @@ int port_choices(void)
cputs("cargo, Quit trading, or Retire?");
cursor(1); cputc(' ');
- choice = cgetc();
- if ((choice == 'B') || (choice == 'b') ||
- (choice == 'S') || (choice == 's') ||
- (choice == 'V') || (choice == 'v') ||
- (choice == 'T') || (choice == 't') ||
- (choice == 'Q') || (choice == 'q') ||
- (choice == 'R') || (choice == 'r'))
+ choice = agetc();
+ if ((choice == 'b') ||
+ (choice == 's') ||
+ (choice == 'v') ||
+ (choice == 't') ||
+ (choice == 'q') ||
+ (choice == 'r'))
{
break;
}
@@ -2174,12 +2253,12 @@ int port_choices(void)
cputs("cargo, or Quit trading?");
cursor(1); cputc(' ');
- choice = cgetc();
- if ((choice == 'B') || (choice == 'b') ||
- (choice == 'S') || (choice == 's') ||
- (choice == 'V') || (choice == 'v') ||
- (choice == 'T') || (choice == 't') ||
- (choice == 'Q') || (choice == 'q'))
+ choice = agetc();
+ if ((choice == 'b') ||
+ (choice == 's') ||
+ (choice == 'v') ||
+ (choice == 't') ||
+ (choice == 'q'))
{
break;
}
@@ -2188,10 +2267,10 @@ int port_choices(void)
cputs("Shall I Buy, Sell, or Quit trading?");
cursor(1); cputc(' ');
- choice = cgetc();
- if ((choice == 'B') || (choice == 'b') ||
- (choice == 'S') || (choice == 's') ||
- (choice == 'Q') || (choice == 'q'))
+ choice = agetc();
+ if ((choice == 'b') ||
+ (choice == 's') ||
+ (choice == 'q'))
{
break;
}
@@ -2201,22 +2280,67 @@ int port_choices(void)
return choice;
}
+#else
+int port_choices(void) {
+ int choice = 0;
+ char retire_ok;
+
+ compradores_report();
+ cputs("Taipan, present prices per unit here are"); /* NB: exactly 40 cols */
+ cputs(" Opium: Silk:\r\n");
+ cputs(" Arms: General:\r\n");
+ gotoxy(11, 19);
+ cprintulong(price[0]);
+ gotoxy(29, 19);
+ cprintulong(price[1]);
+ gotoxy(11, 20);
+ cprintulong(price[2]);
+ gotoxy(29, 20);
+ cprintulong(price[3]);
+
+ gotoxy(0, 22);
+ clrtobot();
+ cursor(0);
+
+ retire_ok = (port == 1 && ((cash + bank) >= 1000000));
+ cputs("Shall I Buy, Sell, ");
+ if(port ==1) {
+ cputs("Visit bank, Transfer\r\ncargo, ");
+ }
+ if(!retire_ok) cputs("or ");
+ cputs("Quit trading");
+ if(retire_ok) cputs(", or Retire");
+ cursor(1);
+ cputs("? ");
+
+ for(;;) {
+ choice = lcgetc();
+ if(choice == 'b' || choice == 's' || choice == 'q')
+ break;
+ if(port == 1) {
+ if(retire_ok && choice == 'r')
+ break;
+ if(choice == 't' || choice == 'v')
+ break;
+ }
+ }
+ cursor(0);
+ return choice;
+}
+#endif
/* TODO: rewrite in asm, or at least better C */
void name_firm(void)
{
+ /*
int input,
character = 0;
+ */
+ unsigned char input, count = 0;
cursor(0);
clrscr();
- gotoxy(0,23);
-#ifdef VERSION
- cputs(VERSION);
-#else
- cputs("(no version info)");
-#endif
chlinexy(1, 7, 38);
chlinexy(1, 16, 38);
@@ -2238,6 +2362,22 @@ void name_firm(void)
gotoxy(12, 13);
+ while(((input = agetc()) != ENTER) && (count < 22)) {
+ if(input == BKSP) {
+ if(count) {
+ backspace();
+ firm[count--] = '\0';
+ }
+ } else {
+ cputc(input);
+ firm[count++] = input;
+ }
+ }
+
+ cursor(0);
+ firm[count] = '\0';
+
+ /*
while (((input = cgetc()) != ENTER) && (character < 22))
{
if (((input == BKSP) || (input == 127)) && (character == 0))
@@ -2260,12 +2400,12 @@ void name_firm(void)
cursor(0);
firm[character] = '\0';
+ */
return;
}
-void buy(void)
-{
+void buy(void) {
/* see comment in fancy_numbers for why this is static */
// static char space[5];
@@ -2274,6 +2414,12 @@ void buy(void)
long afford,
amount;
+ gotoxy(0, 22);
+ clrtobot();
+ cputs("What do you wish me to buy, Taipan? ");
+ choice = get_item(0);
+
+ /*
for (;;)
{
gotoxy(0, 22);
@@ -2281,7 +2427,6 @@ void buy(void)
cputs("What do you wish me to buy, Taipan? ");
- /* TODO: buy() sell() and throwing cargo, common code in get_item() */
choice = tolower(get_one());
if(choice == 'o') {
choice = 0;
@@ -2297,6 +2442,7 @@ void buy(void)
break;
}
}
+ */
for (;;)
{
@@ -2346,7 +2492,7 @@ void buy(void)
gotoxy(0, 23);
cputs("I buy, Taipan: ");
- amount = get_num(9);
+ amount = get_num();
if(amount == -1) {
amount = afford;
}
@@ -2367,6 +2513,12 @@ void sell(void) {
long amount;
+ gotoxy(0, 22);
+ clrtobot();
+ cputs("What do you wish me to buy, Taipan? ");
+ choice = get_item(0);
+
+ /*
for (;;)
{
gotoxy(0, 22);
@@ -2374,7 +2526,6 @@ void sell(void) {
cputs("What do you wish me to sell, Taipan? ");
- /* TODO: buy() sell() and throwing cargo, common code in get_item() */
choice = tolower(get_one());
if(choice == 'o') {
choice = 0;
@@ -2390,6 +2541,7 @@ void sell(void) {
break;
}
}
+ */
for (;;)
{
@@ -2401,7 +2553,7 @@ void sell(void) {
cputs(" shall\r\n");
cputs("I sell, Taipan: ");
- amount = get_num(9);
+ amount = get_num();
if (amount == -1)
{
@@ -2429,7 +2581,7 @@ void visit_bank(void)
compradores_report();
cputs("How much will you deposit? ");
- amount = get_num(9);
+ amount = get_num();
if (amount == -1)
{
amount = cash;
@@ -2457,7 +2609,7 @@ void visit_bank(void)
compradores_report();
cputs("How much will you withdraw? ");
- amount = get_num(9);
+ amount = get_num();
if (amount == -1)
{
amount = bank;
@@ -2491,10 +2643,10 @@ int main(void) {
while(1) {
clrscr();
cputs("dmg? ");
- damage = get_num(9);
+ damage = get_num();
cputs("\r\n");
cputs("cap? ");
- capacity = get_num(9);
+ capacity = get_num();
mchenry();
}
}
@@ -2502,7 +2654,6 @@ int main(void) {
atari_text_setup();
initrand();
- // splash_intro();
name_firm();
cash_or_guns();
set_prices();
diff --git a/timed_getch.s b/timed_getch.s
index 8675290..a5ac4d5 100644
--- a/timed_getch.s
+++ b/timed_getch.s
@@ -1,26 +1,110 @@
- .export _timed_getch, _set_jiffy_timer
- .import _cgetc
+ .export _timed_getch, _set_jiffy_timer, _agetc, _numgetc, _yngetc, _lcgetc
+ .import _cgetc, _cblank
-_set_jiffy_timer:
- sei
- sta 540
- stx 541
+ .include "atari.inc"
+
+_set_jiffy_timer: ; called by jsleep() also.
+ sei ; disable IRQ while setting timer
+ sta CDTMV3
+ stx CDTMV3+1
cli
rts
_timed_getch:
jsr _set_jiffy_timer
wait4key:
- lda 540
- ora 541
- beq done
- ldx 764
- inx
+ lda CDTMV3 ; has timer counted down to 0?
+ ora CDTMV3+1
+ beq done ; yes, return(-1)
+ lda CH ; no, check for a keypress
+ ; ...but don't let the capslock or inverse keys count
+ ; as a keypress, here.
+
+ cmp #$ff ; no key pressed
+ beq wait4key
+ and #$3f ; mask shift/control bits
+ cmp #$3c ; caps-lock
+ beq wait4key
+ cmp #$27 ; inverse (atari) key
beq wait4key
- jmp _cgetc
+ jmp _agetc ; user hit a key, read it.
+
done:
lda #$ff ; return -1
tax
rts
+
+; _agetc removes the inverse-video bit, and if
+; a control key is pressed, it turns it into the non-control version
+; (e.g. ^A = lowercase a). Keys that can't be mapped to regular ASCII
+; (such as clear, delete, escape) are replaced with a space.
+; extern char lcgetc();
+_agetc:
+; lda #0 ; show cursor
+; sta CRSINH
+; lda #$20
+; jsr _cblank
+
+ jsr _cgetc ; get ATASCII code of keypress
+
+ ; special cases
+ cmp #$9b ; enter key, return as-is
+ beq ok
+ cmp #$7e ; backspace
+ beq ok
+
+ ; everything else
+ and #$7f ; strip bit 7 (inverse)
+ bne notnull
+ lda #$20 ; map null (heart, ctrl-,) to space
+notnull:
+ cmp #$20
+ bcs notcontrol
+ ora #$60 ; 1 - 31 map to 96 - 127
+notcontrol:
+ cmp #$7c ; | (pipe, vertical bar) allowed as-is.
+ beq ok
+ cmp #$7a ; rest of range $7b - $7f is unmappable.
+ bcc ok ; (remember, $7e, backspace, was handled above)
+ lda #$20
+ok:
+; ldx #$01 ; hide cursor
+; stx CRSINH
+ rts
+
+_lcgetc:
+ jsr _agetc
+ cmp #'A'
+ bcc ok
+ cmp #'Z'+1
+ bcs ok
+ eor #$20 ; lowercase it
+ bcc ok
+
+_numgetc:
+ jsr _agetc
+ cmp #$9b
+ beq ok
+ cmp #$7e
+ beq ok
+ cmp #$61 ; allow 'a' for "all"
+ beq ok
+ cmp #'0'
+ bcc _numgetc
+ cmp #'9'+1
+ bcc ok
+ bcs _numgetc
+
+_yngetc:
+ sta FR0 ; stash default arg
+ jsr _lcgetc
+ cmp #'y' ; return y or n immediately
+ beq ok
+ cmp #'n'
+ beq ok
+ lda FR0 ; otherwise, check for default arg
+ beq _yngetc ; no default, get another keypress
+ rts ; else return the default
+
diff --git a/ver.dat b/ver.dat
new file mode 100644
index 0000000..d03fad4
--- /dev/null
+++ b/ver.dat
Binary files differ