|
Subject: Re: [stella] Climber5 source and binary From: "Andrew Davie" <atari2600@xxxxxxxxxxxxx> Date: Fri, 18 Apr 2003 00:03:03 +1000 |
Had another look at the code, and I'd like to comment on a few things.
In the initialisation, the RAM clear has me a bit undecided...
cld ; clear BCD bit
ldx #$FF
txs ; set stack to the beginning
ldy INTIM ; for random number seed
lda #$00
.clearRAM
sta $00,x
dex
bne .clearRAM
Firstly, it's really clearing RAM *and* hardware registers. If you just
wanted to clear RAM, then you could change the bne .clearRAM to a bmi
.clearRAM (keeping in mind that X would be $7F at the end of that, instead
of 0 - but it doesn't seem to be used anyway). But clearing all of RAM (but
1) seems kind of hackish. Either clear it all, or clear RAM.
Secondly, there were some discussions on a minimal (byte-count) kernel a
long time ago, and I posted an efficient startup at that time. Here it
is... it's a bit bizarre, but very efficient :)
; CLEARS ALL VARIABLES, STACK
; INIT STACK POINTER
; ALSO CLEARS TIA REGISTERS
; DOES THIS BY "WRAPPING" THE STACK - UNUSUAL
LDX #0
TXS
PHA ; BEST WAY TO GET SP=$FF, X=0
TXA
CLEAR PHA
DEX
BNE CLEAR
; 9 BYTES TOTAL FOR CLEARING STACK, MEMORY
; STACK POINTER NOW $FF, A=X==0
I have to say, that's so elegant I have tears in my eyes :)
Somebody better check it, though - the brilliance is blinding me :P
One thing I've noticed about your code, Dennis, is your use of two-digits
for hex bytes, *ALWAYS*. This is not necessary. It's quite OK to go sta
0,x or sta $00,x or sta $0,x -- they are all equivalent. I used to go lda
#$02, too! It's a style thing, I know. But sometimes using #$00 is a bit
of overkill, when #0 is exactly the same, and much more readable (IMHO).
You init the random number from INTIM - yet you don't check if this is 0.
The RandomByte routine documents this must *not* be zero. Looking at the
routine, it should cope with 0 OK - but you should either fix the code or
the comments.
You tend to do a lot of NTSC/PAL checking, with branching sections of code
for loading NTSC or PAL conditions/colours/states. This strikes me as
inefficient. I'd probably check the switch at startup and save the relevant
bit as D0 of a variable (or D1 - see later in this post). Then you could
use that variable as an index to tables.
For example, the title screen colours is currently....
TitleScreenCalculations SUBROUTINE
lda #NTSC_SKY_BLUE ; set the NTSC colors for the title
ldx #NTSC_WOOD_BROWN
bit SWCHB ; check the right difficulty switch
bpl .setTitleScreenColors ; if set to B then use NTSC settings
lda #PAL_SKY_BLUE ; else use PAL settings
ldx #PAL_WOOD_BROWN
.setTitleScreenColors
sta COLUBK
stx COLUPF
With a variable, and tables, that would be...
TitleScreenCalculations SUBROUTINE
ldy PAL_NTSC ; the stored NTSC/PAL switch (bit D0
set or clear)
lda SKYColour,y
sta COLUBK
lda WOODColour,y
sta COLUPF
...
SKYColour .byte NTSC_SKY_BLUE, PAL_SKY_BLUE
WOODColour .byte NTSC_WOOD_BROWN, PAL_WOOD_BROWN
This code only benefits from being constant cycle-time - on average faster,
and more readable. It requries a RAM variable to save the switch state,
though. You do a fair bit of SWCHB checking - it would be nice to clean
those conditional bits of code up. This is optional, though - some people
might prefer your original.
By the way, your use of SUBROUTINE is interesting. Just to clarify things,
this is *NOT* necessary - it just gives a sort of local-scope to the labels
beginning with a dot (.) It would be nice for DASM to be able to associate
overlays with subroutine sections via the use of a name/overlay list as
parameters for the subroutine. Just an idea for me to think about :)
Here's a minor optimisation...
.doDeathAnimation
lda gameClock ; get the game clock for player
animation
lsr ; updated every other frame
and #$01 ; mask all but D0 alternate between 0
and 1
tax ; move value to x for table index
lda LowDeathAnimationTable,x ; load the climber death animation
sta playerPointer ; into the player pointers
lda HighDeathAnimationTable,x ; they will be used to load RAM with the
sta playerPointer+1 ; death animation
OK, so instead of having two tables, have one word-table, and save on the
lsr.
ie:
.doDeathAnimation
lda gameClock
and #$02
tax
lda DeathAnimationTable,x
sta playerPointer
lda DeathAnimationTable+1,x
sta playerPointer+1
...
DeathAnimationTable
.word DeathFrame1, DeathFrame2
Just below that is another example of SWCHB optimisation with a variable.
Use this instead...
lda PAL_NTSC
asl
tax
ldy DeathAnimationColorTable,x ; y holds the low byte of the color
table
lda DeathAnimationColorTable+1,x ; a holds the high byte of the color
table
jmp .setVerticalColorPointer ; set the color pointers
This alone saves 4 bytes (see your label .loadDeathColors for the location).
In fact, if you use SWCHB to pretty much index word tables (or can contrive
to), then you might be better setting D1 of the PAL_NTSC variable instead of
D0. Then you don't need to ASL, or lda.
ldx PAL_NTSC ; 0 or 2
ldy DeathAnimationColorTable,x ; etc
and the earlier code using SWCHB stuff would be as simple as merging the
tables...
ldy PAL_NTSC ; the stored NTSC/PAL switch (bit D1
set or clear)
lda Colour,y
sta COLUBK
lda Colour+1,y
sta COLUPF
...
Colour
.byte NTSC_SKY_BLUE, NTSC_WOOD_BROWN
.byte PAL_SKY_BLUE, PAL_WOOD_BROWN
Finally, your code had....
overlay ds 27 ; overlay place holder (thank you
Andrew)
You are very welcome. Seeing a comment like that makes it all worthwhile -
thank you!
Cheers
A
----------------------------------------------------------------------------------------------
Archives (includes files) at http://www.biglist.com/lists/stella/archives/
Unsub & more at http://www.biglist.com/lists/stella/
| Current Thread |
|---|
|
| <- Previous | Index | Next -> |
|---|---|---|
| Re: [stella] Climber5 source and bi, Andrew Davie | Thread | Re: [stella] Climber5 source and bi, Fabrizio Zavagli |
| Aw: Re: [stella] Everyone loves a n, cybergoth | Date | RE: [stella] Climber5 source and bi, Thomas Jentzsch |
| Month |