[stella] DD new build

Subject: [stella] DD new build
From: Glenn Saunders <cybpunks2@xxxxxxxxxxxxx>
Date: Sun, 14 Oct 2001 01:27:15 -0700
Here is build 6.

In order to implement Thomas' techniques I had to go back and change a lot of stuff.

For now the sprites are not being displayed. It's back to shoring up the playfield routines.

Y is the scanline counter and it updates only every other scanline. This had the added benefit of being able to eliminate some redundant code and free up more time for other stuff during the kernel. For now, the alternating safe-zone stripe is back (it was in my earliest demo), this time updated every 2 instead of one line. (The reason I say for now is that the free time during the tombstone scanlines is going to probably get filled up with missile-handling code because the missiles can't take advantage of VDEL and therefore need to be enabled and modified on every scanline.).
That's the only cosmetic difference that I can see on the emulator. I have yet to run it on my 2600 ;) I'm hoping the stuff at the top of the screen that Thomas mentioned before isn't there anymore.


I also went through and tried to optimize a little bit to help eliminate some badly timed playfield rewrites around the border area. Changed some labels and other minor stuff.

I also realigned the sprite graphics and put in as much of the sprite setup code as I could without actually running it. Actually, a lot of it is running, it just never draws sprites. I'm hoping Thomas and Manuel can take a look at it to see if I'm setting this all up correctly. I don't completely understand how it works yet but I'm pretty close to getting there... I spent a good amount of time reading and rereading those two messages and trying to apply them to this code, expanding where necessary.

I'm starting to get a little more familiar with the status bits and how to use the branching instructions and how not to totally mess up the TIA timings. I'm pretty happy that after hours of hacking and modifying the code without testing that when I did actually test it I wound up with a stable display on the emulator. That's better than when I first started hacking HowToDraw A Playfield where every little change was generating a black display (or an assembler error message).

I do have a question though, regarding the sprite stuff.

If it takes all 76 cycles to get to the point where a sprite's graphics are written to the register, then that does prevent the sprite from appearing on that scanline, doesn't it? Or more to the point, if the sprite is going to show up in mid screen, if it takes longer than half of 76 cycles to figure out whether to draw the sprite and if so, where to get the sprite graphics, then you aren't going to be able to display him in time.

I was wondering what the effect of this timing tends to be.

I'm a little concerned that if it takes me all of every other scanline to figure out how to position all 4 objects and write to their registers that on those scanlines I'll have weird problems with sprites getting rewritten in the middle (like a tearing effect) or just not showing up at.



Glenn Saunders - Producer - Cyberpunks Entertainment
Personal homepage: http://www.geocities.com/Hollywood/1698
Cyberpunks Entertainment: http://cyberpunks.uni.cc
;Death Derby 2001
; By Glenn Saunders

;LINEAGE:

; How to Draw an Asymmetric Reflected Playfield
; by Roger Williams

; with a lot of help from Nick Bensema
; (this started out as his "How to Draw a Playfield")

	processor 6502
	include vcs.h

; CONSTANTS

; SCREEN GEOMETRY 	 CTR  ACTUAL 	SUBTOTAL
;----------------------- ---- --------- --------
ScoreHeight 		= 20; 20	20
; 	TopBorder	= 2   2		22
PlayfieldHeight		= 88; (176)	198
;	BottomBorder	= 2   2		200
;			 		---
;					200 visible lines

OverScanHeight		= 22; 22	222
;			 		---
;					222 total lines


;INITIAL COUNTER VALUES
TombstoneHeight 	= 8  ; 8*2 = 16 (single scanlines) high per tombstone
TombstoneRowsPerScreen 	= 11-1 ; 11 rows of tombstones per screen
CarHeight 	= 8-1  ; 8 doubled scanlines (used as offset)



; constants that reference rotation index pointers
PointUp 	= 0
PointRight 	= 4
PointDown 	= 8
PointLeft 	= 12

TurnOnSpriteReflect = %00000100
TurnOffSpriteReflect = 0

CarPage		= $FF;00
CarDataAlign	=    $65

InitialSafeZone	= %10010000 ; initial safezone border graphics
SafeZone2	= %10000000 
FlipThreshold	= 9 ; flip sprite when
		    ;P0_CurrentRotationIndex >= 9









    SEG.U vars
    org $80

;TEMPORARY VARIABLES

Temp       	ds 1


;CurrentScanLine ds 1
; use Y instead

;CurrentTombstoneRow	ds 1; 11->0 outer loop counter
; use X instead

CurrentTombstoneSubRow 	ds 1; 7->0 inner loop counter


; ALTERNATING SAFEZONE BORDER STRIP
CurrentSafeZone ds 1
; PLAYFIELD BITMAP
PF1DataRAM	ds TombstoneRowsPerScreen+1
PF2DataRAM	ds TombstoneRowsPerScreen+1
PF1bDataRAM	ds TombstoneRowsPerScreen+1
PF2bDataRAM	ds TombstoneRowsPerScreen+1

;sprite positiong
P0_X		ds 1
P0_Y		ds 1

P1_X		ds 1
P1_Y		ds 1

M0_X		ds 1
M0_Y		ds 1

M1_X		ds 1
M1_Y		ds 1


;sprite graphics pointers
P0_CurrentRotationSequence ds 1; 0-15
P1_CurrentRotationSequence ds 1; 0-15

;these above reference addresses that get stored below

P0_CurrentFramePtr ds 2; this will wind up being a constant $FF in the high byte
P1_CurrentFramePtr ds 2; this will wind up being a constant $FF in the high byte

M0_CurrentFramePtr ds 2
M1_CurrentFramePtr ds 2

;P0_CurrentRowCounter ds 1
;P1_CurrentRowCounter ds 1
;M0_CurrentRowCounter ds 1
;M1_CurrentRowCounter ds 1


; stolen from OUTLAW source
PF0Array            ds 1   ; PF0 array, 18 Bytes
ScoreshapeLow01     ds 1   ; Shape of player 1 lower score digit
ScoreshapeLow02     ds 1   ; Shape of player 2 lower score digit
ScoreshapeHi01      ds 1   ; Shape of player 1 higher score digit
ScoreshapeHi02      ds 1   ; Shape of player 2 higher score digit
bcdScore01Backup    ds 1   ; Backups score for player 1
rightScoreOnOff     ds 1   ; 0F for Right score on, 00 for off
gameState           ds 1   ; 0F running/EF saver/00 select/XX counter



    SEG code
    org  $F000

;FrameCounter = $93 was going to try some color cycling


Start
	SEI  ; Disable interrupts, if there are any.
	CLD  ; Clear BCD math bit.
	LDX  #$FF
	TXS  ; Set stack to beginning.
	

	; CLEAR OUT RAM
	LDA #0
KeepZeroing
	STA 0,X
	DEX
	BNE KeepZeroing

SetColors
	LDA #0
	STA COLUBK  ; Background will be black.
	
	LDA #$34 ; set playfield color to deep red
	STA COLUPF
	
	LDA #PF_Reflect
	STA CTRLPF  ; set playfield to reflect

	LDA #$FF; set the cars to white for now
	STA COLUP0
	STA COLUP1
	
	
InitializeSprites
; set high byte for frame pointers
	; this should only have to be done once for the whole game
	LDA CarPage; $FF
	STA >P0_CurrentFramePtr
	STA >P1_CurrentFramePtr

	
; set initial X,Y of P0, P1
	LDA #30; start P0 on the left
	STA P0_X
	LDA #50; start P0 halfway down
	STA P0_Y

	LDA #130; start P1 on the right
	STA P1_X
	LDA #50; start P1 halfway down
	STA P1_Y


; set initial rotations
	LDX #PointRight; start P0 car pointing right
	LDA RotationSequence,X; get low byte pointer from index 4
	STX P0_CurrentRotationSequence; store for later
	STA <P0_CurrentFramePtr; store low byte pointer

	LDX #PointLeft; start P1 car pointing left
	LDA RotationSequence,X; get low byte pointer from index 4
	STX P1_CurrentRotationSequence; store for later
	STA <P1_CurrentFramePtr; store low byte pointer


	LDX #TombstoneRowsPerScreen
InitializeTombstones; copy from ROM to RAM

	LDA #InitialSafeZone
	STA CurrentSafeZone

	LDA PF1Data,X
	STA PF1DataRAM,X

	LDA PF2Data,X
	STA PF2DataRAM,X

	LDA PF1bData,X
	STA PF1bDataRAM,X

	LDA PF2bData,X
	STA PF2bDataRAM,X
	
    	DEX
    	BPL InitializeTombstones

MainLoop
	JSR VBArea
	JSR DrawScreen
	JSR OverScan
	JMP MainLoop      ;Continue forever.

;SUB
ClearTombstones
	LDX #TombstoneRowsPerScreen
KeepClearing 
	DEX
	STA <PF1DataRAM,X
	STA <PF2DataRAM,X
	STA <PF1bDataRAM,X
	STA <PF2bDataRAM,X
	BNE KeepClearing
	RTS  

;SUB
OverScan
	LDX #OverScanHeight

KillLines
	STA WSYNC
	DEX
	BNE KillLines
	RTS

;HORIZONTAL POSITIONING SUBROUTINE FROM MANUEL POLIK's GUNFIGHT	
;SUB (alternate beginning of below)
PosP1
            CLC 
            ADC #$08
;SUB
PosP0
            CMP #$A0
            BCC NH2
            SBC #$A0
NH2
            TAY
            LSR
            LSR
            LSR
            LSR
            STA Temp
            TYA
            AND #15
            CLC
            ADC Temp
            LDY Temp
            CMP #15
            BCC NH
            SBC #15
            INY
NH
            EOR #7
            ASL
            ASL
            ASL
            ASL
            STA HMP0,X
            INY                         ; Waste 5 cycles, 1 Byte
            STA WSYNC
            INY                         ; Waste 7(!) cycles, 1 Byte
            BIT 0                       ; Waste 3 cycles, 2 Byte
PosDelay    DEY
            BPL PosDelay
            STA RESP0,X
            RTS
;/HORIZONTAL POSITIONING SUBROUTINE	
	
;SUB
VBArea
        LDX #0 ; store to HMP0
        LDA P0_X; load current X value of P0
        JSR PosP0; call coarse pos calc routine for P0

	;LDA  #2
	STA  WSYNC

        LDX #1; store to HMP1
        LDA P1_X; load current X value of P1
        JSR PosP1; call coarse pos calc routine for P1
        
	;LDA  #2
	STA  WSYNC

	;later on we need to add the horizontal positioning
	;of the two missiles


;The calculation of the object pointer (done outside the kernel, if
;Thomas didnt make that clear enough) looks like this:

UpdateCurrentFramePtr
	;this will have been modified by the controller routines
	LDX P0_CurrentRotationSequence;0-15
	
	; load low byte pointer to the start
	; of gfx for the current frame
	LDA RotationSequence,X
	; update the pointer to be used during active kernel
	; indirect Y addressing
	STA <P0_CurrentFramePtr

UpdateSpriteReflect
	;LDA <P0_CurrentFramePtr
	
	CMP #FlipThreshold

	; A < #FlipThreshold  --->  N=1, Z=0, C=0
	; A = #FlipThreshold  --->  N=0, Z=1, C=1
	; A > #FlipThreshold  --->  N=0, Z=0, C=1

	LDY #TurnOffSpriteReflect; initialize to no flip
	BMI .Continue   ; if A < 9 then sigN will be 1
			; so do not flip, just .Continue
FlipSprite
	LDY #TurnOnSpriteReflect

.Continue
	STY REFP0


        SEC ; set carry bit
        
	; subtract the Y position of P0
        SBC #P0_Y
	; POINTER is initialized as offset -PO_Y away from the last scanline
	; of CarRotation0 graphics.


	; STORE THE LOW BYTE POINTER
        STA <P0_CurrentFramePtr


; this shouldn't be necessary because the high byte is always constant
	; load a pointer to the page of memory
	; data for the CarRotation0 frame (HIGH BYTE)
        LDA CarPage; $FF

	; SUBTRACT 0 with carry.  Why?
        SBC #0

	; STORE as the HIGH BYTE pointer to P0 graphics
	; therefore this should remain the same as the last
	; row of graphics for CarRotation0 frame (HIGH BYTE)
        STA >P0_CurrentFramePtr
; /this shouldn't be necessary because the high byte is always constant



; MANUEL'S NOTES (edited):
; Where P0_Y represents the scanline-pair where the oject starts.
; In the given example P0_Y might be set to any value between #0 and #100
; and we're subtracting it! 


; So it's as simple as: If we fall below zero here, we cross a page later,
; so our data must start above any possible value of P0_Y.

; To allow for complete movement across the screen, assuming 100-0,
; (SCANLINE COUNTER DECREMENTING) 
; then data must aligned at 100 or above on the given page in order to
; prevent subtraction rollovers/extra cycle time.
; in this game, however, if you subtract the score and the border,
; the range is constrained to XX-0 (FILL THIS IN LATER)


;(Hm... uhm... Thomas: Why isn't the size of the displayed thing taken
;into account here? Could it be... Oh my god... if one'd already let dasm
;calculate it... that'd be LDA #<CarRotation0+CarHeight ... then... Oh-oh...
;I've to quit now, there's probably an optimisation run in gunfight
;necessary...)

;/UpdateCurrentFramePtr

	
HMOVEDelay          
	DEX
        BNE HMOVEDelay
        STA HMOVE ; Do it on cycle 74!!!
	STA WSYNC

	
	STA VSYNC ;Begin vertical sync.
	STA WSYNC ;  First line of VSYNC
	STA WSYNC ;  Second line of VSYNC.

	LDA #44   ;init timer for overscan
	STA TIM64T

	STA WSYNC ;  Third line of VSYNC.
	STA VSYNC ;  (0)


VBLOOP	LDA INTIM
	BNE VBLOOP ; Whew!
	
	STA WSYNC
	STA VBLANK  ;End the VBLANK period with a zero.
	

	LDA #0
	STA PF0
	STA PF1
	STA PF2; zero out playfield
	RTS

;SUB
DrawScreen
	LDX #ScoreHeight; burn through 20 total scanlines
DrawScore
	STA WSYNC
	DEX
	BNE DrawScore

TopBorder ; 2 lines
	LDA #$FF 
	STA PF0 ; draw a solid line
	STA PF1
	STA PF2
	LDA #InitialSafeZone
	STA WSYNC
	; draw a solid line except for the safezone border
	STA PF0 

	;ScanGo will finish the line off

FinalInitialization
	;INITIALIZE TOMBSTONE ROW COUNTERS
	LDX #TombstoneRowsPerScreen+1
	
	;TombstoneRowsPerScreen held in X register through kernel
	LDA #TombstoneHeight+1
	; NOTE: pad these by one because the first time through it decrements
	; at the top of the loop

	STA CurrentTombstoneSubRow; store TombstoneHeight to RAM

	

	LDY #PlayfieldHeight ; store scanline counter in Y throughout
		; the whole kernel.  Decrement every other scanline





;THIS AREA IS A 2-LINE KERNEL

;START FIRST LINE OF LINE-PAIR
ScanLoop1
	;INNER LOOP
	DEC CurrentTombstoneSubRow ;next row of current tombstone
	BNE ScanGo1

	LDA #TombstoneHeight; if counter reaches zero, reset to 7
	STA CurrentTombstoneSubRow; and store back to RAM
	DEX ;CurrentTombstoneRow = CurrentTombstoneRow - 1
	    ;outer loop - indexes next tombstone row
ScanGo1
	STA WSYNC
	; Time to begin cycle counting

				;	0
	;STA.W HMOVE		;+4	4
	
	NOP 			;+2	2
	NOP			;+2	4
	
	;will probably have to do an HMOVE on every line to 
	;simplify logic.  HMOVE is only necessary for the missiles

	LDA <PF1DataRAM-1,X       ;+4	8

	;I'm not sure why the -1 is necessary here to make it work


	STA PF1               	;+3  = *11*  < 29	;PF1 visible
	
	LDA <PF2DataRAM-1,X       ;+4	15
	STA PF2                 ;+3  = *19*  < 40	;PF2 visible

	NOP			;+2	20
	NOP			;+2	22
	NOP			;+2	24
	NOP			;+2	26
	NOP			;+2	28
	NOP			;+2 	30
	NOP			;+2	32
	NOP			;+2	34
	
	LDA <PF1bDataRAM-1,X	;+4	38

	;PF1 no longer visible, safe to rewrite
	STA PF1			;+3 = *41*


	LDA <PF2bDataRAM-1,X	;+3     44
	
	;PF2 rewrite must begin at exactly cycle 45!!, no more, no less
	STA PF2			;+3  = *47*  ; > 46 PF2 no longer visible
	LDA #0			;+2	49
	TXS			;+2	51
	;preserve X register
				
	NOP			;+2	53
	NOP			;+2	55
	NOP			;+2	57
	NOP			;+2	59
	NOP			;+2	61
	; CLEAR OUT PLAYFIELD FOR SPRITE HANDLING BELOW

	STA PF2			;+3	64
	STA PF1			;+3	67
	LDA CurrentSafeZone	;+2	69
	EOR #SafeZone2		;+2 	71

	STA CurrentSafeZone	;+2	73
	STA PF0                 ;+3	76


	
	;PERFECT TIMING, NO WSYNC NECESSARY
	; PUT ONE BACK IN IF THE NOPs are replaced with code
	; that has varying timing
	
;START SECOND LINE OF LINE-PAIR
ScanGo2	; do all the sprite routines here
	; WSYNC PUT BACK IN IF NECESSARY
	; start cycle counting again
				; 	0

; THOMAS' SAMPLE CODE
;P0Loop
;       TYA ; current scanline (updated every other line)
;       SEC
;       SBC SpriteStart         ; contains the line where the car starts+1
;       ADC #SPRITEHEIGHT       ; assuming the height is constant (i.E. 8)
;       BCC .skipDraw
;       LDA (P0_CurrentFramePtr),Y
;       STA GRP0
;.skipDraw:

;CONVERTED CODE
;P0Loop
;       TXA
;       SEC
;       SBC  P0_YC
;       ADC #8
;       BCC .skipDraw
;       LDY $FF

	;TAY

;.skipDraw:
	;STY GRP0

	TSX; grab tombstone counter back again
	DEY ; Decrement ScanlinePair counter
	BNE ScanLoop1; keep going until scanline counter reaches 0
DoBorder
	LDA #$FF ; this may overload the timing of the sprite kernel line
		 ; and have to be moved under WSYNC!!

	STA WSYNC; finish last line of sprites
	STA PF0 ; draw a straight line
	STA PF1
	STA PF2
	STA WSYNC; line 1 of bottom border
	STA WSYNC; line 2 of bottom border

EndKernel
	STA VBLANK ; Make TIA output invisible,
	; Y is already zero
	STY PF0
	STY PF1
	STY PF2
	STY GRP0
	STY GRP1
	STY ENAM0
	STY ENAM1
	STY ENABL
	RTS; END DrawScreen

;THE GRAPHICS        
	org $FE00

scoreshapedata: .byte $0E ; |    XXX |
                .byte $0A ; |    X X |
                .byte $0A ; |    X X |
                .byte $0A ; |    X X |
                .byte $0E ; |    XXX |

                .byte $22 ; |  X   X |
                .byte $22 ; |  X   X |
                .byte $22 ; |  X   X |
                .byte $22 ; |  X   X |
                .byte $22 ; |  X   X |

                .byte $EE ; |XXX XXX |
                .byte $22 ; |  X   X |
                .byte $EE ; |XXX XXX |
                .byte $88 ; |X   X   |
                .byte $EE ; |XXX XXX |

                .byte $EE ; |XXX XXX |
                .byte $22 ; |  X   X |
                .byte $66 ; | XX  XX |
                .byte $22 ; |  X   X |
                .byte $EE ; |XXX XXX |

                .byte $AA ; |X X X X |
                .byte $AA ; |X X X X |
                .byte $EE ; |XXX XXX |
                .byte $22 ; |  X   X |
                .byte $22 ; |  X   X |

                .byte $EE ; |XXX XXX |
                .byte $88 ; |X   X   |
                .byte $EE ; |XXX XXX |
                .byte $22 ; |  X   X |
                .byte $EE ; |XXX XXX |

                .byte $EE ; |XXX XXX |
                .byte $88 ; |X   X   |
                .byte $EE ; |XXX XXX |
                .byte $AA ; |X X X X |
                .byte $EE ; |XXX XXX |

                .byte $EE ; |XXX XXX |
                .byte $22 ; |  X   X |
                .byte $22 ; |  X   X |
                .byte $22 ; |  X   X |
                .byte $22 ; |  X   X |

                .byte $EE ; |XXX XXX |
                .byte $AA ; |X X X X |
                .byte $EE ; |XXX XXX |
                .byte $AA ; |X X X X |
                .byte $EE ; |XXX XXX |

                .byte $EE ; |XXX XXX |
                .byte $AA ; |X X X X |
                .byte $EE ; |XXX XXX |
                .byte $22 ; |  X   X |
                .byte $EE ; |XXX XXX |

	org $FF00
;               REFLECTED  PLAYFIELD            
;                                               
; PF0|   PF1  |  PF2   ||   PF2b |   PF1b |PF0b|
;4567|76543210|01234567||76543210|01234567|7654|


;INITIAL TITLE GRAPHICS
;TO BE COPIED TO RAM

;SafeZone ;     7654----
;	.byte %10011001


PF1Data  ;D    76543210
	.byte %01111001
	.byte %01000101
	.byte %01000101
	.byte %01000101
	.byte %01111001
	.byte %00000000
	.byte %01111001
	.byte %01000101
	.byte %01000101
	.byte %01000101
	.byte %01111001

	
PF2Data  ;EA   01234567
	.byte %00101111
	.byte %10100000
	.byte %11100111
	.byte %00100000
	.byte %11101111
	.byte %00000000
	.byte %00101111
	.byte %00100000
	.byte %11100111
	.byte %00100000
	.byte %11101111	


PF2bData ;     76543210;<--- scanning order

	.byte %11011110
	.byte %00010001
	.byte %10011110
	.byte %01010001
	.byte %10011110
	.byte %00000000
	.byte %01000100
	.byte %01000100
	.byte %11000100
	.byte %01000100
	.byte %11011111

	
PF1bData;      01234567;<--- scanning order


	.byte %00111110
	.byte %00100000
	.byte %00111110
	.byte %00100010
	.byte %00100010
	.byte %00000000
	.byte %00100010
	.byte %00100010
	.byte %00111110
	.byte %00100010	
	.byte %00100010	


; THE ROTATION SEQUENCE POINTERS

; when writing the driving controller code, I will
; index through this table of pointers which rotates
; through the frames.  These pointers only store the low byte
; value.  The high value is always going to be $FF anyway.


; since the shapes are stored upside down, the actual orientation
; is indicated in the notes.  the shapes in the sourcecode will
; appear upside-down

RotationSequence
	;NO FLIP BIT - FACE RIGHT
	.byte <CarRotation0;0  - point up
	.byte <CarRotation1;1  - 
	.byte <CarRotation2;2  - 
	.byte <CarRotation3;3  - 
	.byte <CarRotation4;4  - point right
	.byte <CarRotation5;5  - 
	.byte <CarRotation6;6  - 
	.byte <CarRotation7;7  - 
	.byte <CarRotation8;8  - point down
	; WITH FlipThreshold - FACE LEFT
	.byte <CarRotation7;9  - 
	.byte <CarRotation6;10 - 
	.byte <CarRotation5;11 - 
	.byte <CarRotation4;12 - point left
	.byte <CarRotation3;13 - 
	.byte <CarRotation2;14 - 
	.byte <CarRotation1;15 - 

	
	org $FF00+CarDataAlign
	; make sure all sprite graphics are at least 'CarDataAlign' bytes
	; above the page in order to make sure that the vertical
	; logic routine will work properly


; THIS STORES HALF OF THE ROTATIONS.
; THE OTHER HALF ARE GENERATED BY USING THE HARDWARE PLAYER FLIP FUNCTION

; note that this rotation frame doesn't need an upside down version because it is symmetrical


;9 frames * 8 bytes per frame = 56 bytes used

CarRotation0;UP (ACTUAL)
  .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...

CarRotation1
  .byte %00000110; ....XX..
  .byte %00011110; ..XXXX..
  .byte %01110100; XXX.X...
  .byte %00011010; XX.XX.X.
  .byte %00011010; ...XX.X.
  .byte %01011111; .X.XXXXX
  .byte %00111100; ..XXXX..
  .byte %00101100; ..X.XX..

CarRotation2
  .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....

CarRotation3
  .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..

CarRotation4;RIGHT|LEFT  
  .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; ........

CarRotation5   
  .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....

CarRotation6
  .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...

CarRotation7   
  .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..

CarRotation8;DOWN (ACTUAL)
  .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.


  
  
;missiles are used as pseudoplayers
;data is encoded as width and pixel offsets.

;76543210
;XXXX    <- OFFSET (typically 0 through +8 pixels)
;    XX  <- NUSIZ data

;EXAMPLE:
;LDA (M0_ShapeFrame),Y	;
;STA HMM0		;
;LSL			;
;LSL			;
;STA NUSIZ0		;

;32 bytes used

Ped1_1;   OOOOWW__
   .byte %11110100 ; .XX.....
   .byte %11100000 ; ..X.....
   .byte %11011000 ; ...XXXX.
   .byte %11010100 ; ...XX...
   .byte %11111000 ; .XXXX...
   .byte %00000000 ; ........
   .byte %11010100 ; ...XX...
   .byte %11010100 ; ...XX...
   
Ped1_2;   OOOOWW__
   .byte %11010100 ; ...XX...
   .byte %11010100 ; ...XX...
   .byte %11010100 ; ...XX...
   .byte %11010100 ; ...XX...
   .byte %11010100 ; ...XX...
   .byte %00000000 ; ........
   .byte %11010100 ; ...XX...
   .byte %11010100 ; ...XX...

Ped1_3;   OOOOWW__
   .byte %11110100 ; .XX.....
   .byte %00000000 ; ..X.....
   .byte %11011100 ; ...XXXX.
   .byte %11100100 ; ..XX....
   .byte %11010100 ; ...XX...
   .byte %00000000 ; ........
   .byte %11010100 ; ...XX...
   .byte %11010100 ; ...XX...

Ped1_4;   OOOOWW__
   .byte %11011100 ; ...XXXX.
   .byte %11010000 ; ...X....
   .byte %11011100 ; ...XXXX.
   .byte %11010100 ; ...XX...
   .byte %00001100 ; XXXX....
   .byte %11101100 ; ..XXXX..
   .byte %11110100 ; .XX.....
   .byte %11110100 ; .XX.....





;add score graphics later	
	org $FFFC
        .word Start
        .word Start

Attachment: DD_0006.bin
Description: Binary data

Current Thread