diff options
author | B. Watson <yalhcru@gmail.com> | 2016-01-12 03:43:23 -0500 |
---|---|---|
committer | B. Watson <yalhcru@gmail.com> | 2016-01-12 03:43:23 -0500 |
commit | f90842d4decc6f9453e53785174c73674dc86a51 (patch) | |
tree | ec749af9e26555c8ea07d60e5de66ce174efc2ae | |
parent | 235efa90197fe69b4c2cf681a277d10ed2eed4d2 (diff) | |
download | taipan-f90842d4decc6f9453e53785174c73674dc86a51.tar.gz |
move memory layout around to free more code space
-rw-r--r-- | Makefile | 47 | ||||
-rw-r--r-- | README.txt | 110 | ||||
-rw-r--r-- | comptitle.s.in | 4 | ||||
-rw-r--r-- | convfont.c | 4 | ||||
-rw-r--r-- | newtitle.pl | 15 | ||||
-rw-r--r-- | newtitle.s | 125 | ||||
-rw-r--r-- | size.pl | 19 | ||||
-rw-r--r-- | taipan.c | 2 | ||||
-rw-r--r-- | titlecomp.pl | 2 |
9 files changed, 200 insertions, 128 deletions
@@ -22,6 +22,30 @@ REV=`git rev-parse --short HEAD 2>/dev/null || echo UNKNOWN` #VERSION="v$(VER)-$(TODAY)-$(BRANCH)-$(REV)" VERSION="v$(VER)-$(TODAY)-$(REV)" +# Memory layout. Controlled by the Makefile from now on, no longer +# hardcoded addresses in various scripts. These are in hex. If any +# of them are changed, you *must* run 'make clean'. + +# Font. +FONT_ADDR=0x2000 + +# Title screen data will be decompressed to this address. +TITLE_DATA_ADDR=0x2400 + +# Title display list, decompression code, and menu code. Should be +# TITLE_DATA_ADDR plus 0x1744. +TITLE_CODE_ADDR=0x3b44 + +# Main game start address. All the code in TAIMAIN_C_SRC and +# TAIMAIN_ASM_SRC loads here. We get this address by looking for +# 'C code can load at' message when making newtitle.xex. It's the +# next byte after the end of the display list. +#TAIMAIN_ADDR=0x3d00 +TAIMAIN_ADDR=0x3cc7 + +# Size of cc65 parameter stack in bytes. +STACK_SIZE=0x200 + # for older cc65, we need a custom linker file. #CFLAGS=-t $(SYS) -C custom.cfg -I. -L. $(COPT) @@ -35,8 +59,8 @@ VERSION="v$(VER)-$(TODAY)-$(REV)" # 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. -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) +CFLAGS=-t $(SYS) -T -I. -L. -Wl -D__SYSTEM_CHECK__=1 -DFONT_ADDR=$(FONT_ADDR) --start-addr $(TAIMAIN_ADDR) -Wl -D__STACKSIZE__=$(STACK_SIZE) $(COPT) AS=ca65 ASFLAGS= AR=ar65 @@ -93,17 +117,17 @@ $(XEX): taimain.xex taifont.xex newtitle.xex comptitle.xex # using GTIA narrow playfield. The original title screen for the Apple # is a 280x192 bitmap with a few blank lines at the top & bottom. I # squished it horizontally to 256 pixels and got rid of the blank lines, -# to save load time. Note that titledata.xex is no longer built into +# to save load time. Note that titledata.dat is not built into # the game binary as-is: it's now used as input for creating # comptitle.xex, the compressed title screen. -titledata.xex: newtitle.pl newtitle.png - perl newtitle.pl > titledata.xex +titledata.dat: newtitle.pl newtitle.png + perl newtitle.pl > titledata.dat # compressed title, for faster loading. see titlecompression.txt # for gory details. -comptitle.xex: titledata.xex titlecomp.pl comptitle.s.in - perl titlecomp.pl 151 < titledata.xex - cl65 -l comptitle.lst -o comptitle.xex -t none comptitle.s +comptitle.xex: titledata.dat titlecomp.pl comptitle.s.in + perl titlecomp.pl 151 < titledata.dat + cl65 -l comptitle.lst -o comptitle.xex -t none --asm-define destination=$(TITLE_DATA_ADDR) comptitle.s # Init segment that loads after the title screen data. It sets up # a custom display list and sets the GTIA for narrow playfield, @@ -114,7 +138,7 @@ comptitle.xex: titledata.xex titlecomp.pl comptitle.s.in # to get cc65 to build an init segment (would need a custom linker # script at least). newtitle.xex: newtitle.s ver.dat help.dat - cl65 -l newtitle.lst -m newtitle.map -o newtitle.xex -t none newtitle.s + cl65 -l newtitle.lst -m newtitle.map -o newtitle.xex -t none --asm-define screendata=$(TITLE_DATA_ADDR) --asm-define origin=$(TITLE_CODE_ADDR) newtitle.s # Version number in Atari screen-data form ver.dat: text2screen.pl @@ -175,7 +199,7 @@ PORTSTAT.DAT: mkportstats.xex # I converted them manually from eyeballing a screenshot of the Apple # combat screen). convfont: convfont.c - $(HOSTCC) $(HOSTCFLAGS) -o convfont convfont.c + $(HOSTCC) $(HOSTCFLAGS) -DFONT_ADDR=$(FONT_ADDR) -o convfont convfont.c # Rules for building various file types with the cc65 toolchain. .s.o: @@ -197,6 +221,9 @@ distclean: clean push: sh push.sh +size: clean all + perl size.pl $(STACK_SIZE) + # Cruft. Was used for testing the enemy ship animation. lorchatest: lorchatest.c draw_lorcha.s taifont.xex cl65 -t atari -O -T -o lorchatest1.xex lorchatest.c draw_lorcha.s @@ -121,18 +121,15 @@ arcade game). Bugs! At least these: -- Semi-fixed: When exiting to DOS and reloading, the title screen - graphics are messed up. The playtester who reported this was running - on real hardware (not an emulator). Getting the BSS below $9000 seems - to have fixed it. I can't see how this is happening, but I expect it's - related to this: +- Exiting the game (Play again? N) needs to at minimum restore the + original text/background colors. - The BSS can overlap the start of the title screen (it's very close anyway). Consequences: There is a momentary graphics glitch when the main game is done loading and before it shows the "name your firm" screen. Also, we can't go back and display the title screen (but that's not something really necessary anyway). The fix: make the damn code - smaller! + smaller! Also, rearrange memory layout (see memory_layout.txt). - After a battle, the prices don't get reset (or, not always?) when entering the new port (confirm?). @@ -168,20 +165,63 @@ Bugs! At least these: 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... - or maybe not (need to double-check against the Apple version). - - One of my playtesters reported that, when running away from combat, it said 4 billion ships were attacking (number of ships must have gone negative). I was never able to reproduce this. -- After a fight, "Arriving at Manila" or such would sometimes appears on the - fight screen without clearing it first (if you ran away, you can still - see ships). I *think* this is fixed, but I don't understand what caused - it so I'm leaving it in this list in case I'm wrong.... and I'm wrong, - because it just happened to me again. sea_battle() is returning something - unexpected, but how? +- After a fight, "Arriving at Manila" or such will sometimes appear on the + fight screen without clearing it first (ships still visible). + sea_battle() is returning something unexpected, but how? + +Deliberate differences between the Apple II and Atari ports: + +1. Atari: "Press ESC for help" rather than ESC to start. + +2. 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 + 3 brightness levels available, and only 3 colors: green, amber, and + black (to mimic the 3 most popular types of monitor used with Apple + computers back in the day). + +4. 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") + +5. "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 + that I don't notice it's there, if it's normal video. + +7. "You're ship is overloaded" => "Your ship is overloaded". Sorry, + grammar nazi. + +8. 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. + +9. The title screen now has a help menu and some key commands to change the + screen colors and enable/disable sound. The "Press 'ESC' to start" + has been changed to "Press 'ESC' for help", and any non-command key + starts the game. + +10. Apple uses floating point, no practical limit on cash/bank/debt. + Atari currently uses 32-bit unsigned longs, though float support + is soon to be added (at least for the bank). + +11. On Apple, price of General Cargo isn't always an integer (e.g. 6.5). + +12. On Apple, dead enemy ships sink one scanline at a time, and there are + at least 2 sinking speeds. On Atari, it's one character, 8 scanlines, at a time. + Differences between the Apple II original and Linux port: @@ -213,44 +253,6 @@ and 6, 10 are Linux-style. Added a few features not in the Apple or Linux versions: -- 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. - -- Added a way to change the background color and text brightness. Only - 3 brightness levels available, and only 3 colors: green, amber, and - black (to mimic the 3 most popular types of monitor used with Apple - computers back in the day). - -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. - -- The + that indicates more ships offscreen is inverse video. I find - that I don't notice it's there, if it's normal video. - -- "You're ship is overloaded" => "Your ship is overloaded". Sorry, - grammar nazi. - -- 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. - -- The title screen now has a help menu and some key commands to change the - screen colors and enable/disable sound. The "Press 'ESC' to start" - has been changed to "Press 'ESC' for help", and any non-command key - starts the game. - Other things that need doing to the code: - Decide what to do about integer overflow. Possibilities: diff --git a/comptitle.s.in b/comptitle.s.in index 824cded..940136a 100644 --- a/comptitle.s.in +++ b/comptitle.s.in @@ -15,8 +15,8 @@ imgsize = $1700 ; these both need to be page-aligned. destination also needs ; to be aligned on a 4K boundary. -start = $2000 -destination = $9000 +start = $9000 +;destination = $2400 srcptr = FR0 dstptr = FR0+2 @@ -167,8 +167,8 @@ int main(int argc, char **argv) { if(argc > 1) { xex[0] = xex[1] = 0xff; - xex[2] = 0x00; xex[3] = 0xb8; /* load address $B800 */ - xex[4] = 0xff; xex[5] = 0xbb; /* end address $bbff */ + xex[2] = FONT_ADDR % 256; xex[3] = FONT_ADDR / 256; /* load address $2000 */ + xex[4] = 0xff; xex[5] = 0x23; /* end address $23ff */ write(1, xex, 6); } write(1, font, 1024); diff --git a/newtitle.pl b/newtitle.pl index a5cf2d2..623b411 100644 --- a/newtitle.pl +++ b/newtitle.pl @@ -26,20 +26,7 @@ for $y (0..183) { } } -# we got over 4K of data, so the display list will have to -# 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. 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); -print chr($load % 256); -print chr(int($load / 256)); -print chr($end % 256); -print chr(int($end / 256)); +# just output the raw data, no xex header. print chr($_) for @bytes; @@ -10,16 +10,15 @@ sound_disabled = $06ff ; where our screen was loaded (see newtitle.pl) -screendata = $9000 +;screendata = $2400 ; homebrew atari xex header .word $ffff - .word version + .word origin .word end-1 - ; needs to be above the BSS (see taipan.map). we'll place it right at - ; the end of screendata. - .org $a800 +; .org $a800 + .org origin version: .incbin "ver.dat" @@ -43,21 +42,89 @@ helplotbl: .byte <(help+96) .byte 0 -helpshowing = FR1 - -; N<space> or FF (inverse) -sounddisp = help + 78 - colorchoices: .byte $c0,$10,$00 - colorcount = (*-colorchoices)-1 - textchoices: .byte $0c,$0e,$0a - textcount = (*-textchoices)-1 +wait1jiffy: + lda RTCLOK+2 +wait: + cmp RTCLOK+2 + beq wait + rts + +; this is needed to prevent the DL from crossing a 1K boundary. +filler: + .repeat 3 + .byte $aa + .endrepeat + +; since the screen data crosses a 4K boundary, we have to +; include a LMS. screendata needs to be on a 32-byte boundary for +; these calculations to work. + .if(screendata .mod $20) + .error "screendata must be on a 32-byte boundary!" + .endif + +totalscanlines = 184 ; aka image size / $20 +topscanlines = (($1000 - (screendata .mod $1000)) / $20) +bottomscanlines = totalscanlines - topscanlines + + .out .sprintf("topscanlines = %d", topscanlines) + .out .sprintf("bottomscanlines = %d", bottomscanlines) + +; if the display list crosses a 1K boundary, it needs to contain a +; jmp instruction ($01). + .macro dlbyte arg + .if((* .mod $400) = $3fd) + .out .sprintf("emitting DL jump to $%x at $%x", * + 3, *) + .byte $01 + .word (* + 2) + .endif + .byte arg + .endmacro + + .macro dl3byte ins, arg + .local bytes + bytes = $400 - (* .mod $400) + .if(bytes < 3) + .error .sprintf("$%x %d: display list dl3byte when <3 bytes left in 1K block, sorry", *, bytes) + .endif + .byte ins + .word arg + .endmacro + + ; display list here +dlist: + dlbyte $70 ; 24 scanlines of blanks + dlbyte $70 + dlbyte $70 + + dl3byte $0f | $40, screendata ; LMS, BASIC mode 8 + .repeat topscanlines - 1 + dlbyte $0f ; 127 more scanlines of mode 8 + .endrepeat + + dl3byte $0f | $40, screendata+(topscanlines * $20) ; Hit 4K boundary, LMS again + .repeat bottomscanlines + dlbyte $0f ; 55 more scanlines of mode 8 + .endrepeat + dl3byte $02 | $40, version ; LMS, 1 line of GR.0 for the version +help_lms = * - 2 + dl3byte $41, dlist ; JVB, jump & wait for vblank + + .out .sprintf("dl start $%x, end $%x, size %d", dlist, *, (* - dlist) + 1) + + .out .sprintf("C code can load at $%x", * + 1) + +helpshowing = FR1 + +; here is where we store N<space> or FF (inverse) +sounddisp = help + 78 + ; executable code here start: ; setup color registers @@ -162,13 +229,6 @@ keyok: sta CH rts ; return to DOS (which loads the rest of the game) -wait1jiffy: - lda RTCLOK+2 -wait: - cmp RTCLOK+2 - beq wait - rts - enable_disable_sound: lda #2 sta helpshowing @@ -187,30 +247,7 @@ now_on: sta sounddisp+1 rts - ; display list here -dlist: - .byte $70 ; 24 scanlines of blanks - .byte $70 - .byte $70 -; .byte $30 ; 4 more since image is only 184 lines tall - - .byte $0f | $40 ; LMS, BASIC mode 8 - .word screendata - .repeat 127 - .byte $0f ; 127 more scanlines of mode 8 - .endrepeat - - .byte $0f | $40 ; Hit 4K boundary, LMS again - .word screendata+$1000 - .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 $02 | $40 ; LMS, 1 line of GR.0 for the version -help_lms: - .word version - .byte $41 ; JVB, jump & wait for vblank - .word dlist + .out .sprintf("code ends at $%x", *) end: .word INITAD @@ -0,0 +1,19 @@ +#!/usr/bin/perl -w + +my $stack_size = oct(shift) || die "no stack size"; + +open MAP, "<taipan.map" or die $!; +while(<MAP>) { + next unless /^BSS/; + (undef, $bss_start, $bss_end, undef) = split /\s+/; + $bss_start = hex $bss_start; + $bss_end = hex $bss_end; +} +close MAP; + +$free = (0xbc20 - $stack_size) - $bss_end + 1; + +printf " code ends at \$%04x\n", ($bss_start - 1); +printf " BSS ends at \$%04x\n", $bss_end; +printf "stack starts at \$%04x\n", 0xbc20 - $stack_size; +printf "free code space \$%04x (%d, %.1fK)\n", $free, $free, $free / 1024; @@ -123,7 +123,7 @@ void atari_text_setup() { jsleep(1); POKE(559, 34); // turn on the screen (normal playfield) jsleep(1); - POKE(756, 0xb8); // use our custom font + POKE(756, FONT_ADDR / 256); // use our custom font POKE(731, 1); // disable keyclick on XL/XE (does nothing on 400/800) } diff --git a/titlecomp.pl b/titlecomp.pl index c8da677..58ce0d3 100644 --- a/titlecomp.pl +++ b/titlecomp.pl @@ -7,7 +7,7 @@ $datasize = 0x1700; use bytes; # skip xex header -read(STDIN, our $junk, 6); +#read(STDIN, our $junk, 6); # no longer need read(STDIN, $data, $datasize); |