diff options
-rw-r--r-- | GAMEPLAY.txt | 34 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | NOTES.txt | 20 | ||||
-rw-r--r-- | arrayutils.s | 60 | ||||
-rw-r--r-- | taipan.c | 34 | ||||
-rw-r--r-- | timed_getch.s | 13 |
6 files changed, 122 insertions, 41 deletions
diff --git a/GAMEPLAY.txt b/GAMEPLAY.txt index ab937ee..74d39c9 100644 --- a/GAMEPLAY.txt +++ b/GAMEPLAY.txt @@ -43,18 +43,6 @@ You also might get attacked by pirates. If this happens, you enter the combat phase of the turn. Otherwise, you'll arrive in port and begin your next turn. -During combat, you have three choices: Fight, Run, or Throw Cargo. If -your ship doesn't have any guns, don't bother trying to fight. Running -away is always an option, but the enemy will chase you, so you can't -always escape right away. Throw Cargo means you have your crew throw -some of your cargo into the water, in hopes that it will distract the -pirates or satisfy their greed, allowing you to get away safely. - -When the battle first starts, you choose between Fight, Run, or Throw -Cargo. During the fight, you can change your orders at any time by -pressing the key for the new order (F, R, or T). - - Details ------- @@ -85,7 +73,7 @@ The next screen offers you the choice of starting with either: 2 - 5 guns, no cash, and no debt. Your ship has a cargo capacity of 60 units either way, but each gun -takes up 10 units so option 2 gives you only 10 units for carrying +takes up 10 units, so option 2 gives you only 10 units for carrying cargo. Later in the game, you'll get the options to buy guns and upgrade your ship to higher capacity. @@ -126,3 +114,23 @@ Opium - A highly addictive drug, but not without medical uses. It's risky to trade in opium becase it's illegal in most ports. However, the potential gains may be worth the risk. +Combat +------ + +During combat, you have three choices: Fight, Run, or Throw Cargo. If +your ship doesn't have any guns, don't bother trying to fight. Running +away is always an option, but the enemy will chase you, so you can't +always escape right away. Throw Cargo means you have your crew throw +some of your cargo into the water, in hopes that it will distract the +pirates or satisfy their greed, allowing you to get away safely. + +When the battle first starts, you choose between Fight, Run, or Throw +Cargo. During the fight, you can change your orders at any time by +pressing the key for the new order (f, r, or t). + +If you get impatient during combat, you can use "Turbo" mode: +hold Shift when you press F or R (Fight or Run). This disables the +animations and delays, so each combat round happens very quickly. If +the fight starts going badly, you can press any key to exit Turbo mode +and return to normal speed. + @@ -106,7 +106,7 @@ XEX=taipan.xex # All the C and asm sources for taimain.xex: TAIMAIN_HDRS=sounds.h TAIMAIN_C_SRC=taipan.c strtonum.c -TAIMAIN_ASM_SRC=rand.s draw_lorcha.s timed_getch.s portstat.s console.s cprintul.s soundasm.s explosion.s textdecomp.s +TAIMAIN_ASM_SRC=rand.s draw_lorcha.s timed_getch.s portstat.s console.s cprintul.s soundasm.s explosion.s textdecomp.s arrayutils.s TAIMAIN_LIBS=conio/conio.lib # Comment these lines out to build without big number support. @@ -23,38 +23,40 @@ arcade game). Deliberate differences between the Apple II and Atari ports: -0. The Atari version is noticeably faster than the Apple version on II+ or +0. Turbo mode, in combat. See MANUAL.txt. + +1. The Atari version is noticeably faster than the Apple version on II+ or IIe. This is because it's written in C and assembly, not interpreted BASIC. A IIgs on the other hand... -1. "Press ESC for help" rather than ESC to start. Starting the game is +2. "Press ESC for help" rather than ESC to start. Starting the game is done with the space bar or return key. -2. I made it possible to disable the sound, since it's kinda repetitive +3. I made it possible to disable the sound, since it's kinda repetitive and annoying, plus the game "freezes" while sounds are playing (no threading on Atari!) which slows down gameplay. -3. Added a way to change the background color and text brightness. Only +4. Added a way to change the background color and text brightness. Only 4 brightness levels, but all 16 Atari hues are available. -4. Prompts that only accept one character no longer require pressing Enter. +5. 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 an amount of cash or items (but not if you hit A for "all") -5. "We have 5 guns" is in an inverse video box. I think it looks nicer, and +6. "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. -6. The + that indicates more ships offscreen is inverse video. I find +7. The + that indicates more ships offscreen is inverse video. I find that I don't notice it's there, if it's normal video. -7. "You're ship is overloaded" => "Your ship is overloaded". Sorry, +8. "You're ship is overloaded" => "Your ship is overloaded". Sorry, grammar nazi. -8. Updating the port status screen, and text printing in general, happens +9. Updating the port status screen, and text printing in general, happens faster and cleaner-looking, due to using C and asm rather than BASIC, and also because the static parts of the screen aren't redrawn unless they need to be. (Grammar nazi? That's a run-on sentence...) diff --git a/arrayutils.s b/arrayutils.s new file mode 100644 index 0000000..188ace4 --- /dev/null +++ b/arrayutils.s @@ -0,0 +1,60 @@ +; extern void clear_ships_on_screen(void); + +; optimized bzero() replacement. +; the real bzero() in cc65-2.19 is 129 bytes long. +; it's optimized for speed (has an unrolled loop) and shares +; code with memset(). we can do it in a lot less code here, +; especially since we only need to clear exactly 20 bytes +; located at a known absolute address. + +; in C, we could write: for(i=0; i<len; i++) { arr[i] = 0; } +; ...which takes up around 64 bytes of code. +; instead, this: clear_ships_on_screen(); +; ...takes 3 bytes for the function call, plus ~20 bytes for +; the function, or around 1/3 the size of the for loop, or under 1/4 +; the size of bzero() plus its function call. + + .import _ships_on_screen + .export _have_ships_on_screen, _clear_ships_on_screen + + .include "atari.inc" + + .proc _clear_ships_on_screen + ldx #$14 + lda #0 +@l: + sta _ships_on_screen-1,x + dex + bne @l + rts + .endproc + +; extern char have_ships_on_screen(void); + +; optimized (both size and speed) replacement for: + +; if ((ships_on_screen[0] == 0) && (ships_on_screen[1] == 0) && +; (ships_on_screen[2] == 0) && (ships_on_screen[3] == 0) && +; (ships_on_screen[4] == 0) && (ships_on_screen[5] == 0) && +; (ships_on_screen[6] == 0) && (ships_on_screen[7] == 0) && +; (ships_on_screen[8] == 0) && (ships_on_screen[9] == 0)) + +; ...which compiles to ~100 bytes of code. a for loop would be +; around 64 bytes (like the clearing loop above). this is 3 bytes +; for the function call plus 11 bytes for the function, plus a +; couple more bytes for the ! in front of the function call (since +; the result is opposite what the original code did). +; I could save the 3 bytes by inlining this as asm() in the C code, +; but it would be more fragile than making a separate function. + + .proc _have_ships_on_screen + ldx #$14 ; sizeof(ships_on_screen) +@l: + lda _ships_on_screen-1,x + bne @done ; found a non-0 byte, A and X are both non-zero + dex + bne @l + ; end of loop. if we get here, A and X are both zero +@done: + rts + .endproc @@ -75,6 +75,9 @@ extern unsigned char __fastcall__ yngetc(char dflt); /* sleep for j jiffies (no PAL adjustment at the moment) */ extern void __fastcall__ jsleep(unsigned int j); +/* sleep for j jiffies unless turbo is true */ +extern void __fastcall__ tjsleep(unsigned int j); + /* flash screen when we're hit in combat */ extern void explosion(void); @@ -1012,10 +1015,13 @@ void set_orders(void) { /* sea_battle only ever returns 1 to 4. making the return type a char saved 61 bytes! */ +int ships_on_screen[10]; +extern char have_ships_on_screen(void); +extern void clear_ships_on_screen(void); + char sea_battle(char id, int num_ships) { /* These locals seem to eat too much stack and cause weird behaviour, so they're static now. */ - static int ships_on_screen[10]; static int time, s0, ok, @@ -1025,15 +1031,16 @@ char sea_battle(char id, int num_ships) { char choice, flashctr, num_on_screen, status; unsigned long amount, total; - turbo = 0; port_stat_dirty = 1; + ik = 1; + ok = 0; + turbo = 0; orders = 0; num_on_screen = 0; + time = get_time(); s0 = num_ships; - ok = 0; - ik = 1; booty = (time / 4 * 1000 * num_ships) + randi()%1000 + 250; if(would_overflow(cash, booty)) { @@ -1088,7 +1095,7 @@ char sea_battle(char id, int num_ships) { for(i = 0; i <= 9; i++) { if (num_ships > num_on_screen) { if (ships_on_screen[i] == 0) { - if(!turbo) jsleep(5); + tjsleep(5); ships_on_screen[i] = (randi() % ec) + 20; draw_lorcha(i); num_on_screen++; @@ -1146,12 +1153,7 @@ char sea_battle(char id, int num_ships) { set_orders(); for(i = 1; i <= guns; i++) { - if ((ships_on_screen[0] == 0) && (ships_on_screen[1] == 0) && - (ships_on_screen[2] == 0) && (ships_on_screen[3] == 0) && - (ships_on_screen[4] == 0) && (ships_on_screen[5] == 0) && - (ships_on_screen[6] == 0) && (ships_on_screen[7] == 0) && - (ships_on_screen[8] == 0) && (ships_on_screen[9] == 0)) - { + if(!have_ships_on_screen()) { static int j; for (j = 0; j <= 9; j++) { @@ -1176,9 +1178,9 @@ char sea_battle(char id, int num_ships) { /* flash_lorcha must be called an even number of times to leave the lorcha in an unflashed state after. */ - if(!turbo) for(flashctr = 0; flashctr < 6; flashctr++) { + for(flashctr = 0; flashctr < 6; flashctr++) { flash_lorcha(targeted); - jsleep(2); + tjsleep(2); } damage_lorcha(targeted); @@ -1205,7 +1207,7 @@ char sea_battle(char id, int num_ships) { if(num_ships == 0) { i += guns; } else { - if(!turbo) jsleep(10); + tjsleep(10); } } gotox0y(3); @@ -1248,7 +1250,7 @@ char sea_battle(char id, int num_ships) { num_on_screen--; clear_lorcha(i); - if(!turbo) jsleep(5); + tjsleep(5); } } if(num_ships == num_on_screen) { @@ -1419,7 +1421,7 @@ char sea_battle(char id, int num_ships) { num_on_screen--; clear_lorcha(i); - jsleep(5); + tjsleep(5); } } plus_or_space(num_ships > num_on_screen); diff --git a/timed_getch.s b/timed_getch.s index eaf7ab3..5c5ff7c 100644 --- a/timed_getch.s +++ b/timed_getch.s @@ -1,7 +1,7 @@ .export _timed_getch, _set_jiffy_timer, _agetc, _numgetc - .export _yngetc, _lcgetc, _jsleep, _get_item - .import _cgetc, _cblank, putchar, _rand + .export _yngetc, _lcgetc, _jsleep, _get_item, _tjsleep + .import _cgetc, _cblank, putchar, _rand, _turbo .include "atari.inc" @@ -13,6 +13,14 @@ ; keyboard and timer functions for taipan. +; sleep for j jiffies, unless _turbo is set. +; extern void __fastcall__ tjsleep(unsigned int j); +_tjsleep: + sta FR0+4 + lda _turbo + bne jret + lda FR0+4 + ; sleep for j jiffies. ; extern void __fastcall__ jsleep(unsigned int j); _jsleep: @@ -21,6 +29,7 @@ jiffy_wait: lda CDTMV3 ora CDTMV3+1 bne jiffy_wait +jret: rts ; extern void __fastcall__ set_jiffy_timer(unsigned int jiffies); |