Subject: [stella] Combat REFPx mystery From: Glenn Saunders <mos6507@xxxxxxxxxxx> Date: Mon, 22 Aug 2005 23:34:21 -0400 |
Here is something that's been bugging me for a long time. Maybe Dennis can comment on this. The first time I looked at the Indy 500 disassembly (or Combat for that matter which this appears to come from) I wondered why it stores the player graphics like this: CarGraphics .byte $EE ; |XXX.XXX.| .byte $EE ; |XXX.XXX.| .byte $44 ; |.X...X..| .byte $7F ; |.XXXXXXX| .byte $7F ; |.XXXXXXX| .byte $44 ; |.X...X..| .byte $EE ; |XXX.XXX.| .byte $EE ; |XXX.XXX.| .byte $18 ; |...XX...| .byte $D8 ; |XX.XX...| .byte $CB ; |XX..X.XX| .byte $5E ; |.X.XXXX.| .byte $7E ; |.XXXXXX.| .byte $64 ; |.XX..X..| .byte $36 ; |..XX.XX.| .byte $36 ; |..XX.XX.| .byte $30 ; |..XX....| .byte $32 ; |..XX..X.| .byte $CC ; |XX..XX..| .byte $DC ; |XX.XXX..| .byte $3B ; |..XXX.XX| .byte $33 ; |..XX..XX| .byte $0C ; |....XX..| .byte $0C ; |....XX..| .byte $04 ; |.....X..| .byte $CC ; |XX..XX..| .byte $F8 ; |XXXXX...| .byte $1F ; |...XXXXX| .byte $DB ; |XX.XX.XX| .byte $F0 ; |XXXX....| .byte $3E ; |..XXXXX.| .byte $06 ; |.....XX.| .byte $18 ; |...XX...| .byte $DB ; |XX.XX.XX| .byte $FF ; |XXXXXXXX| .byte $DB ; |XX.XX.XX| .byte $18 ; |...XX...| .byte $DB ; |XX.XX.XX| .byte $FF ; |XXXXXXXX| .byte $C3 ; |XX....XX| .byte $20 ; |..X.....| .byte $33 ; |..XX..XX| .byte $1F ; |...XXXXX| .byte $F8 ; |XXXXX...| .byte $DB ; |XX.XX.XX| .byte $0F ; |....XXXX| .byte $7C ; |.XXXXX..| .byte $60 ; |.XX.....| .byte $0C ; |....XX..| .byte $4C ; |.X..XX..| .byte $33 ; |..XX..XX| .byte $3B ; |..XXX.XX| .byte $DC ; |XX.XXX..| .byte $CC ; |XX..XX..| .byte $30 ; |..XX....| .byte $30 ; |..XX....| .byte $18 ; |...XX...| .byte $1B ; |...XX.XX| .byte $D3 ; |XX.X..XX| .byte $7A ; |.XXXX.X.| .byte $3E ; |..XXXXX.| .byte $26 ; |..X..XX.| .byte $6C ; |.XX.XX..| .byte $6C ; |.XX.XX..| It's storing the top half of the rotation. This requires 8 sets of graphics. So depending on the rotational position, it appears to load up an 8-byte buffer in RAM by either INCing or DECing through the ROM. This seems very wasteful of RAM to me. But not only that, it's also still necessary to reflect the sprite, like to have the car point left instead of right. Some of that code is below: LoadCarGraphics lda frameCount ; get the current frame count and #1 ; alternate between player 1 and 2 each tax ; frame lda playerDirections,x ; get the player's direction sta REFP0,x ; set the player's reflect state asl ; multiply the value by 8 (i.e number asl ; of rotations) asl cmp #MAX_CAR_SPRITES-1 clc bmi .setCarGraphicsOffset sec eor #$47 If it really wanted to save ROM it could have stored only 5 sprite shapes for the top-right quarter-rotation and better utilized REFPx, but it doesn't do this! For Death Derby, I store 9 car shapes which represents the complete right-hand half of the rotation: Car_Rotation_Frame0:;UP (ACTUAL) ;.byte %00000000 .byte %01011010; .X.XX.X. .byte %01111110; .XXXXXX. .byte %01100110; .XX..XX. .byte %00011000; ...XX... .byte %01011010; .X.XX.X. .byte %01111110; .XXXXXX. .byte %01011010; .X.XX.X. .byte %00011000; ...XX... Car_Rotation_Frame1: ;.byte %00000000 .byte %00001100; ....XX.. .byte %00111100; ..XXXX.. .byte %11101000; XXX.X... .byte %11011010; XX.XX.X. .byte %00011010; ...XX.X. .byte %01011111; .X.XXXXX .byte %00111100; ..XXXX.. .byte %00101100; ..X.XX.. Car_Rotation_Frame2: ;.byte %00000000 .byte %00011000; ...XX... .byte %01111000; .XXXX... .byte %01000010; .X....X. .byte %11011011; XX.XX.XX .byte %11011100; XX.XXX.. .byte %00011110; ...XXXX. .byte %00110110; ..XX.XX. .byte %00010000; ...X.... Car_Rotation_Frame3: ;.byte %00000000 .byte %00110000; ..XX.... .byte %00110010; ..XX.X.. .byte %01100011; .XX...XX .byte %01011110; .X.XXXX. .byte %11111111; XXXXXXXX .byte %11000111; XX...XXX .byte %00011100; ...XXX.. .byte %00000100; .....X.. Car_Rotation_Frame4:;RIGHT|LEFT;OK ;.byte %00000000 .byte %00000000; ........ .byte %11101110; XXX.XXX. .byte %01100100; .XX..X.. .byte %11011111; XX.XXXXX .byte %11011111; XX.XXXXX .byte %01100100; .XX..X.. .byte %11101110; XXX.XXX. .byte %00000000; ........ Car_Rotation_Frame5:;OK ;.byte %00000000 .byte %00000100; .....X.. .byte %00011100; ...XXX.. .byte %11000111; XX...XXX .byte %11111111; XXXXXXXX .byte %01011110; .X.XXXX. .byte %01100011; .XX...XX .byte %00110010; ..XX.X.. .byte %00110000; ..XX.... Car_Rotation_Frame6: ;.byte %00000000 .byte %00010000; ...X.... .byte %00110110; ..XX.XX. .byte %00011110; ...XXXX. .byte %11011100; XX.XXX.. .byte %11011011; XX.XX.XX .byte %01000010; .X....X. .byte %01111000; .XXXX... .byte %00011000; ...XX... Car_Rotation_Frame7: ;.byte %00000000 .byte %00101100; ..X.XX.. .byte %00111100; ..XXXX.. .byte %01011111; .X.XXXXX .byte %00011010; ...XX.X. .byte %11011010; XX.XX.X. .byte %11101000; XXX.X... .byte %00111100; ..XXXX.. .byte %00001100; ....XX.. Car_Rotation_Frame8:;DOWN (ACTUAL) ;.byte %00000000 .byte %00011000; ...XX... .byte %01011010; .X.XX.X. .byte %01111110; .XXXXXX. .byte %01011010; .X.XX.X. .byte %00011000; ...XX... .byte %01100110; .XX..XX. .byte %01111110; .XXXXXX. .byte %01011010; .X.XX.X. I then have a lookup table that provides adjusted pointers to these frames for each rotational value: Car_Rotation_Sequence: ;NO FLIP BIT - FACE RIGHT .byte <Car_Rotation_Frame0 - TOMBSTONE_ROWS*TOMBSTONE_HEIGHT - CAR_HEIGHT;0 - point up .byte <Car_Rotation_Frame1 - TOMBSTONE_ROWS*TOMBSTONE_HEIGHT - CAR_HEIGHT;1 - .byte <Car_Rotation_Frame2 - TOMBSTONE_ROWS*TOMBSTONE_HEIGHT - CAR_HEIGHT;2 - .byte <Car_Rotation_Frame3 - TOMBSTONE_ROWS*TOMBSTONE_HEIGHT - CAR_HEIGHT;3 - .byte <Car_Rotation_Frame4 - TOMBSTONE_ROWS*TOMBSTONE_HEIGHT - CAR_HEIGHT;4 - point right .byte <Car_Rotation_Frame5 - TOMBSTONE_ROWS*TOMBSTONE_HEIGHT - CAR_HEIGHT;5 - .byte <Car_Rotation_Frame6 - TOMBSTONE_ROWS*TOMBSTONE_HEIGHT - CAR_HEIGHT;6 - .byte <Car_Rotation_Frame7 - TOMBSTONE_ROWS*TOMBSTONE_HEIGHT - CAR_HEIGHT;7 - .byte <Car_Rotation_Frame8 - TOMBSTONE_ROWS*TOMBSTONE_HEIGHT - CAR_HEIGHT;8 - point down ; WITH FlipThreshold - FACE LEFT .byte <Car_Rotation_Frame7 - TOMBSTONE_ROWS*TOMBSTONE_HEIGHT - CAR_HEIGHT;9 - .byte <Car_Rotation_Frame6 - TOMBSTONE_ROWS*TOMBSTONE_HEIGHT - CAR_HEIGHT;10 - .byte <Car_Rotation_Frame5 - TOMBSTONE_ROWS*TOMBSTONE_HEIGHT - CAR_HEIGHT;11 - .byte <Car_Rotation_Frame4 - TOMBSTONE_ROWS*TOMBSTONE_HEIGHT - CAR_HEIGHT;12 - point left .byte <Car_Rotation_Frame3 - TOMBSTONE_ROWS*TOMBSTONE_HEIGHT - CAR_HEIGHT;13 - .byte <Car_Rotation_Frame2 - TOMBSTONE_ROWS*TOMBSTONE_HEIGHT - CAR_HEIGHT;14 - .byte <Car_Rotation_Frame1 - TOMBSTONE_ROWS*TOMBSTONE_HEIGHT - CAR_HEIGHT;15 - The logic is then relatively simple to figure out which shape to load and whether or not to reflect the sprite (rotation > 8). My implementation could use some optimization. But in theory, it's simple. Then the shape is brought in via indirect Y loads. Because of Thomas' kernel it's possible to do this and maintain the dyanmic playfield display, whereas the amount of work in the Indy 500 or Combat kernel is significantly less involved. I don't think they really needed the speed boost of using RAM to store the current frame. Plus, since during the design of the 2600 they were flirting with 64-byte variations of the 6502, 16 bytes would have eaten up a 1/4 of the system RAM right there! I'm just wondering if anyone knew a distinct advantage in the Combat approach? It seems that REFPx was tailor-made to save ROM for rotating sprites. I'm not sure why Jay Miner decided to put that feature in if it wasn't going to be better utilized by the initial crop of games. All you'd have to do is reserve 8 more bytes in Indy 500 or Combat to complete the top-half of the rotation and you wouldn't have needed it at all. Archives (includes files) at http://www.biglist.com/lists/stella/archives/ Unsub & more at http://stella.biglist.com
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [stella] Computer Space, Glenn Saunders | Thread | Re: [stella] Combat REFPx mystery, Thomas Jentzsch |
RE: [stella] Computer Space, Fred Quimby | Date | Re: [stella] Computer Space, Piero Cavina |
Month |