Jump to content
IGNORED

Anyone think Ballblazer is possible on the 2600?


Recommended Posts

Two players should be possible. I'll take just small steps for now :)

I'm now doubling the vertical resolution, the tiles at the sides will benefit from this, well... it makes everything look better.

 

I also want to make a finer grained control of the movement to get that 'techy'-look. The horizontal movement is now 20 pixels, I precalculated a vector that turns 45 degrees in 20 steps and used that to control the movement of the grid. I like to calculate 256 pixels heigh vector and use only the upper 20 pixels of it so the horizontal movement has 256 possible positions. Anyone know how to calculate vectors?

 

For vertical tiles I have to make a sort of sinus-table to make the tiles smaller in the distance. Any ideas on this are also welcome.

 

The brown border of the checkerboard needs als to be done. I'll get to this when I've the checkerboard the way I want.

 

Very nice so far, and I'm watching this with interest too. The lines are sometimes a bit wonky, but it does show potential. I'd like to see the source code; I'm sure if you shared you'd get some great contributions from some of the regulars here. Keep up the good work.

Cheers

A

Link to comment
Share on other sites

Very nice work! It looks like you are creating the stripes simply by changing the background colour at the right time? This is a nice approach as you should be able to create the checkerboard simply by fliping the colours at various points down the screen.

Yep, lots of STY, STY.w, STX, STX.w and NOP's. Trail and error based ;D. flipping colors happens already when you've moved 1 tile to the right/left.

 

It also frees up the PF/ball colour to be used for other things. However, this approach won't leave you much time for displaying the sprites over the board.

 

What is needed for sprites? I'm programming the 2600 since Thursday and I've read some tutorials. Positioning is tricky, could that be done outside the board? Then data has to be loaded at the beginning of a scanline right?

 

The alternative is to display an asymmetrical playfield, but this will require a lot of different patterns to be stored.

Lot's of shifting around I guess. Now I have the bonus of 3pixel resolution instead of 4. scrolling a part of the checkerboard is now just wait for 1 cycle and everything that comes next is moved 1 cycles (I don't wait for WSYNC) :cool:

Link to comment
Share on other sites

the board says 'Upload failed. You are not permitted to upload this type of file'...

 

The project in it's current state:

It's a modified 'hello' demo. Maybe It's ugly, and not cleaned up... Please shoot on it :D

 

File main3.asm:

	processor 6502
include vcs.h
include macro.h
include lines.h

org $F000
      
Temp       = $80
PlayfieldY = $90
Direction  = $91
ScanLine   = $92
SubLineCount = $93

offsetLine0_7 = $94
offsetLine8_15 = $95
offsetLine16_19 = $96


PositionX   = $97
invert		= $98

Start
SEI  ; Disable interrupts, if there are any.
CLD  ; Clear BCD math bit.

LDX  #$FF
TXS  ; Set stack to beginning.
;
; Now the memory and TIA registers must be cleared.  You may feel the
; need to write a subroutine that only clears out a certain section of
; memory, but for now a simple loop will suffice.
;
; Since X is already loaded to 0xFF, our task becomes simply to ocunt
; everything off.
;
LDA #0
B1      STA 0,X
DEX
BNE B1
;
; The above routine does not clear location 0, which is VSYNC.  We will
; take care of that later.
;
; At this point in the code we would set up things like the data
; direction registers for the joysticks and such.  
;
JSR  GameInit
;
; Here is a representation of our program flow.
;
MainLoop
JSR  VerticalBlank ;Execute the vertical blank.
JSR  CheckSwitches ;Check console switches.
JSR  GameCalc      ;Do calculations during Vblank
JSR  DrawScreen    ;Draw the screen
JSR  OverScan      ;Do more calculations during overscan
JMP  MainLoop      ;Continue forever.


VerticalBlank  ;*********************** VERTICAL BLANK HANDLER
LDX  #0
LDA  #2
STA  WSYNC  
STA  WSYNC
STA  WSYNC
STA  VSYNC ;Begin vertical sync.
STA  WSYNC ; First line of VSYNC
STA  WSYNC ; Second line of VSYNC.

;
; But before we finish off the third line of VSYNC, why don't we
; use this time to set the timer?  This will save us a few cycles
; which would be more useful in the overscan area.
;
; To insure that we begin to draw the screen at the proper time,
; we must set the timer to go off just slightly before the end of
; the vertical blank space, so that we can WSYNC up to the ACTUAL
; end of the vertical blank space.  Of course, the scanline we're
; going to omit is the same scanline we were about to waste VSYNCing,
; so it all evens out.
;
; Atari says we have to have 37 scanlines of VBLANK time.  Since
; each scanline uses 76 cycles, that makes 37*76=2888 cycles.
; We must also subtract the five cycles it will take to set the
; timer, and the three cycles it will take to STA WSYNC to the next
; line.  Plus the checking loop is only accurate to six cycles, making
; a total of fourteen cycles we have to waste.  2888-14=2876.
;
; We almost always use TIM64T for this, since the math just won't
; work out with the other intervals.  2880/64=44.something.  It
; doesn't matter what that something is, we have to round DOWN.
;
LDA  #44
STA  TIM64T
;
; And now's as good a time as any to clear the collision latches.
;
LDA #0
STA CXCLR
;
; Now we can end the VSYNC period.
;
STA  WSYNC ; Third line of VSYNC.
STA  VSYNC ; (0)
;
; At this point in time the screen is scanning normally, but
; the TIA's output is suppressed.  It will begin again once
; 0 is written back into VBLANK.
;
RTS  
;
; Checking the game switches is relatively simple.  
;
; It just so happens that I'm not going to check any game switches
; here.  I'm just going to set up the colors, without even checking
; the B&W switch!  HA!
;
CheckSwitches ;*************************** CONSOLE SWITCH HANDLER
      LDA #0
      STA COLUBK  ; Background will be black.
      RTS
;
; Minimal game calculations, just to get the ball rolling.
;
GameCalc ;******************************* GAME CALCULATION ROUTINES
CLC

LDX PositionX

LDA SWCHA	;read joystick
AND #$80
CMP #$80
BCS CONT

INX
STX PositionX

CPX #20
BCC CONT
LDA invert
EOR #$01
STA invert
LDX #0
STX PositionX
CONT	


LDA SWCHA	;read joystick
AND #$40
CMP #$40
BCS CONT2

DEX
STX PositionX

CPX #255
BCC CONT2
LDA invert
EOR #$01
STA invert
LDX #19
STX PositionX
CONT2






LDA OFFSET_DATA_0_7,X
STA offsetLine0_7

LDA OFFSET_DATA_8_15,X
STA offsetLine8_15

LDA OFFSET_DATA_16_19,X
STA offsetLine16_19






RTS



ChangeDir
LDA Direction
EOR #$FE
STA Direction
RTS

;
; This is the scariest thing I've done all month.
;
DrawScreen ;**************************** SCREEN DRAWING ROUTINES
LDA INTIM
BNE DrawScreen ; Whew!
STA WSYNC
STA VBLANK  ;End the VBLANK period with a zero.

LDA  #2
STA  CTRLPF

LDA #171
STA ScanLine

BlueLines	
JSR BlueLine
DEC ScanLine
LDA ScanLine
CMP #120
BNE BlueLines


LDA #$88
STA COLUBK
DEC ScanLine
STA WSYNC

LDA #$8A
STA COLUBK
DEC ScanLine

LDX	invert
LDY	#$CC
LDX	#$C4

LDA invert
CMP #$01
BNE NOT_INVERT
LDX	#$CC
LDY	#$C4
NOT_INVERT

STA WSYNC

LDA #$9B
STA COLUBK
DEC ScanLine


LDA PositionX
CMP #07
BCS Skip1
Skip1

CMP #14
BCS Skip2
Skip2

SLEEP 62




;LINE 0
SLEEP 12

LINEX 3
LINEY 3
LINEX 3
LINEY 3
LINEX 3
LINEY 3
LINEX 3
LINEY 3
LINEX 3
LINEY 3
LINEX 3
LINEY 3
LINEX 3
LINEY 3
LINEX 3
LINEY 3
LINEX 3
LINEY 3
LINEX 3



SLEEP 14


LINEX 4
LINEY 3
LINEX 4
LINEY 3
LINEX 4
LINEY 3
LINEX 4
LINEY 3
LINEX 4 ; center L
LINEY 3 ;center R
LINEX 3
LINEY 4
LINEX 3
LINEY 4
LINEX 3
LINEY 4
LINEX 3
LINEY 4


;LINE 1
LDA offsetLine0_7
AND #%00000010
BNE Line1NoOffset
Line1NoOffset


SLEEP 13
LINEY 4
LINEX 4
LINEY 4
LINEX 4
LINEY 4
LINEX 4
LINEY 4
LINEX 4
LINEY 4
LINEX 4
LINEY 4
LINEX 4
LINEY 4

SLEEP 18



STX.w COLUBK 
STY.w COLUBK 
STX.w COLUBK 
nop
STY COLUBK 
STX.w COLUBK 

STY.w COLUBK 
nop
STX COLUBK ;L
STY.w COLUBK ;R
STX.w COLUBK 
nop
STY COLUBK 
STX.w COLUBK 
STY.w COLUBK 
STX.w COLUBK 
STY.w COLUBK 

;LINEX 4	
;LINEY 4
;LINEX 4
;LINEY 4
;LINEX 4
;LINEY 4
;LINEX 5;L
;LINEY 4;R
;LINEX 4
;LINEY 4
;LINEX 4
;LINEY 4
;LINEX 4
;LINEY 4



;LINE 2
LDA offsetLine0_7
AND #%00000100
BNE Line2NoOffset
Line2NoOffset

SLEEP 11
LINEY 5
LINEX 5
LINEY 5
LINEX 5
LINEY 5
LINEX 5	;L
LINEY 5	;R
LINEX 5
LINEY 5
LINEX 5
LINEY 5
LINEX 5




SLEEP 13
LINEY 5
LINEX 6
LINEY 5
LINEX 6
LINEY 5
LINEX 6	;L
LINEY 5	;R
LINEX 5
LINEY 6
LINEX 5
LINEY 6
LINEX 5

;LINE 3
LDA offsetLine0_7
AND #%00001000
BNE Line3NoOffset
Line3NoOffset
SLEEP 12
LINEY 6
LINEX 6
LINEY 6
LINEX 6
LINEY 6
LINEX 6
LINEY 6
LINEX 6


SLEEP 27
LINEY 6
LINEX 6
LINEY 6
nop
LINEX 5;L
LINEY 6;R
LINEX 6
nop
LINEY 5
LINEX 5

;LINE 4
LDA offsetLine0_7
AND #%00010000
BNE Line4NoOffset
Line4NoOffset
SLEEP 18
LINEY 7
LINEX 7
LINEY 7
LINEX 7
LINEY 7
LINEX 7
LINEY 7
LINEX 7


SLEEP 19
LINEY 7
LINEX 7
LINEY 7
LINEX 8;R
LINEY 7;L
LINEX 7
LINEY 8
LINEX 7


;LINE 5
LDA offsetLine0_7
AND #%00100000
BNE Line5NoOffset
Line5NoOffset
SLEEP 7
LINEY 8
LINEX 8
LINEY 8
LINEX 8
LINEY 8
LINEX 8
LINEY 8
LINEX 4


SLEEP 15
LINEY 8
LINEX 8
LINEY 8
nop
LINEX 7 ;L
LINEY 8 ;R
LINEX 8
nop
LINEY 7
LINEX 8
LINEY 4



;LINE 6
LDA offsetLine0_7
AND #%01000000
BNE Line6NoOffset
Line6NoOffset

SLEEP 6
LINEX 9
LINEY 9
LINEX 9
LINEY 9
LINEX 9
LINEY 9
LINEX 9
LINEY 3


SLEEP 9
LINEX 9
LINEY 9
LINEX 10 ;L
LINEY 9 ;R
LINEX 9
LINEY 10


;LINE 7
LDA offsetLine0_7
AND #%10000000
BNE Line7NoOffset
Line7NoOffset
SLEEP 10
LINEX 10
LINEY 10
LINEX 10
LINEY 10
LINEX 10
LINEY 10


SLEEP 16
LINEX 10
LINEY 10
LINEX 10
LINEY 10
LINEX 10
LINEY 10

;line 8
LDA offsetLine8_15
AND #%00000001
BNE Line8NoOffset
Line8NoOffset
SLEEP 7
LINEX 11
LINEY 11
LINEX 11
LINEY 11
LINEX 11
LINEY 5


SLEEP 15
LINEX 11
LINEY 11
LINEX 10 ;L
nop
LINEY 11 ;R
LINEX 11
LINEY 3

;line 9
LDA offsetLine8_15
AND #%00000010
BNE Line9NoOffset
Line9NoOffset
SLEEP 7
LINEX 12
LINEY 12
LINEX 12
LINEY 12
LINEX 12
LINEY 4

SLEEP 12
LINEX 12
LINEY 12
LINEX 12
LINEY 12
LINEX 12
LINEY 4
LINEX 8

;line 10
LDA offsetLine8_15
AND #%00000100
BNE Line10NoOffset
Line10NoOffset

SLEEP 8
LINEY 13
LINEX 13
LINEY 13
LINEX 13
LINEY 3
LINEX 3

SLEEP 18
LINEY 13
LINEX 13
LINEY 13
LINEX 13
LINEY 3
LINEX 3

;line 11
LDA offsetLine8_15
AND #%00001000
BNE Line11NoOffset
Line11NoOffset
;SLEEP 18
SLEEP 8
LINEY 14
LINEX 14
LINEY 14
LINEX 14

SLEEP 20
LINEY 14
LINEX 14
LINEY 14
LINEX 4

;line 12
LDA offsetLine8_15
AND #%00010000
BNE Line12NoOffset
Line12NoOffset
SLEEP 22
LINEY 15
LINEX 15
LINEY 15
LINEX 3

SLEEP 28
LINEY 15
LINEX 15
LINEY 15
LINEX 3


;line 13
LDA offsetLine8_15
AND #%00100000
BNE Line13NoOffset
Line13NoOffset
SLEEP 18
LINEY 16
LINEX 16
LINEY 16
LINEX 4

SLEEP 24
LINEY 16
LINEX 16
LINEY 16
LINEX 4


;line 14
LDA offsetLine8_15
AND #%01000000
BNE Line14NoOffset
Line14NoOffset
SLEEP 16
LINEY 17
LINEX 17
LINEY 17
LINEX 3

SLEEP 22
LINEY 17
LINEX 17
LINEY 17
LINEX 3

;line 15
LDA offsetLine8_15
AND #%10000000
BNE Line15NoOffset
Line15NoOffset
SLEEP 12
LINEY 18
LINEX 18
LINEY 18
LINEX 4

SLEEP 18
LINEY 18
LINEX 18
LINEY 18
LINEX 4

;line 16
LDA offsetLine16_19
AND #%00000001
BNE Line16NoOffset
Line16NoOffset
SLEEP 10
LINEY 19
LINEX 19
LINEY 19
LINEX 3

SLEEP 16
LINEY 19
LINEX 19
LINEY 19
LINEX 3

;line 17
LDA offsetLine16_19
AND #%00000010
BNE Line17NoOffset
Line17NoOffset
SLEEP 6
LINEY 20
LINEX 20
LINEY 20
LINEX 4

SLEEP 12
LINEY 20
LINEX 20
LINEY 20
LINEX 4

;line 18
LDA offsetLine16_19
AND #%00000100
BNE Line18NoOffset
Line18NoOffset
SLEEP 4
LINEY 21
LINEX 21
LINEY 21
LINEX 3

SLEEP 10
LINEY 21
LINEX 21
LINEY 21
LINEX 3

;line 19
LDA offsetLine16_19
AND #%00001000
BNE Line19NoOffset
Line19NoOffset
;SLEEP 7
LINEY 22
LINEX 22
LINEY 22
LINEX 4

SLEEP 6
LINEY 22
LINEX 22
LINEY 22
LINEX 6

LDA #$0
STA COLUBK


; Draw other lines	
DrawLines
STA WSYNC
DEC ScanLine
BNE DrawLines

STA WSYNC  ;Finish this scanline.
STA VBLANK ; Make TIA output invisible,
RTS






;
; For the Overscan routine, one might take the time to process such
; things as collisions.  I, however, would rather waste a bunch of
; scanlines, since I haven't drawn any players yet.
;
OverScan   ;***************************** OVERSCAN CALCULATIONS
LDX #30
KillLines
 STA WSYNC
 DEX
 BNE KillLines
RTS

BlueLine
LDA #$85
STA COLUBK
STA WSYNC
RTS



Line1
STA COLUBK 
NOP

SLEEP 4

LINEX 5
LINEY 5
LINEX 5
LINEY 5
LINEX 5
LINEY 5
LINEX 5
LINEY 5
LINEX 5
LINEY 5

STA WSYNC
RTS



Line2
STX.w COLUBK
SLEEP 5

LINEY 6
LINEX 6
LINEY 6
LINEX 6
LINEY 6
LINEX 6
LINEY 6
LINEX 6

STA WSYNC
RTS


Line3
SLEEP 6

LINEY 7
LINEX 7
LINEY 7
LINEX 7
LINEY 7
LINEX 7
LINEY 7
LINEX 3

STA WSYNC
RTS




Line4
SLEEP 9

LINEX 8
LINEY 8
LINEX 8
LINEY 8
LINEX 8
LINEY 8
LINEX 3

STA WSYNC
RTS








Line5
SLEEP 7

LINEX 9
LINEY 9
LINEX 9
LINEY 9
LINEX 9
LINEY 9


STA WSYNC
RTS


Line6
SLEEP 3

LINEX 10
LINEY 10
LINEX 10
LINEY 10
LINEX 10
LINEY 8

STA WSYNC
RTS



Line7
;SLEEP 1

LINEX 12
LINEY 11
LINEX 11
LINEY 11
LINEX 11
LINEY 3


STA WSYNC
RTS



Line8
;SLEEP 1

LINEX 9
LINEY 12
LINEX 12
LINEY 12
LINEX 12
LINEY 4

STA WSYNC
RTS

Line9
;SLEEP 1

LINEX 8
LINEY 13
LINEX 13
LINEY 13
LINEX 3

STA WSYNC
RTS

Line10
;SLEEP 1

LINEX 5
LINEY 14
LINEX 14
LINEY 4
LINEY 11
LINEX 3

STA WSYNC
RTS



;
; GameInit could conceivably be called when the Select key is pressed,
; or some other event.
;
GameInit
LDA #0
STA PlayfieldY
LDA #1
STA Direction; Set Direction to 1

LDA #0
STA PositionX

LDA #0
STA invert


RTS

;
; Graphics are placed so that the extra cycle in the PFData,X indexes
; is NEVER taken, by making sure it never has to index across a page
; boundary.  This way our cycle count holds true.
;

org $FF00 ; *********************** GRAPHICS DATA
;
; This is the tricky part of drawing a playfield: actually
; drawing it.  Well, the display routine and all that binary
; math was a bit tricky, too, but still, listen up.
;
; Playfield data isn't stored the way most bitmaps are, even
; one-dimensional bitmaps.  We will use the left side of the
; screen only, knowing that the right side is either repeated
; or reflected from it.
;
; In PF0 and PF2, the most significant bit (bit 7) is on the RIGHT
; side.  In PF1, the most significant bit is on the LEFT side.  This
; means that relative to PF0 and PF2, PF1 has a reversed bit order.
; It's just really weird.
;
;    PF0  |     PF1       |      PF2
;  4 5 6 7|7 6 5 4 3 2 1 0|0 1 2 3 4 5 6 7
;
; This is important to remember when doing calculations on bytes intended
; for the PF registers.  Defender gives a good example of this.
;
; It will become necessary to write a program that makes this easier,
; because it is easy to become confused when dealing with this system.
;
   
OFFSET_DATA_0_7
	.byte $0,$0,$80,$20,$10,$88,$48,$24,$94,$54,$B4,$AC,$6C,$DA,$BA,$76,$F6,$DE,$FE,$FE
OFFSET_DATA_8_15       
	.byte $0,$4,$20,$84,$11,$24,$4A,$95,$2A,$55,$AA,$B5,$DB,$6E,$BB,$DF,$FB,$7F,$FB,$FF
	
OFFSET_DATA_16_19
	.byte $0,$0,$0,$0,$2,$4,$4,$8,$2A,$A,$2A,$C,$C,$36,$36,$1A,$3A,$3E,$1E,$1E
   
org $FFFC
.word Start
.word Start


 

File Lines.h:

 



		MAC LINEY
		
.CYCLES     SET {1}

			IF .CYCLES < 3
				ECHO "MACRO ERROR: 'SLEEP': Duration must be > 2"
				ERR
			ENDIF
			
			IF .CYCLES & 1
				STY COLUBK 
.CYCLES             SET .CYCLES - 3
			ELSE
				STY.w COLUBK 
.CYCLES             SET .CYCLES - 4
			ENDIF

			
			REPEAT .CYCLES / 2
				nop
			REPEND
		ENDM


		
		
		MAC LINEX
		
.CYCLES     SET {1}

			IF .CYCLES < 3
				ECHO "MACRO ERROR: 'SLEEP': Duration must be > 2"
				ERR
			ENDIF
			
			IF .CYCLES & 1
				STX COLUBK 
.CYCLES             SET .CYCLES - 3
			ELSE
				STX.w COLUBK 
.CYCLES             SET .CYCLES - 4
			ENDIF

			
			REPEAT .CYCLES / 2
				nop
			REPEND
		ENDM
		


		
		
					MAC LINEY2
		
.CYCLES     SET {1}

			IF .CYCLES < 3
				ECHO "MACRO ERROR: 'SLEEP': Duration must be > 2"
				ERR
			ENDIF
			
			IF .CYCLES & 1
.CYCLES2            SET .CYCLES - 3
			ELSE
.CYCLES2            SET .CYCLES - 4
			ENDIF

			REPEAT .CYCLES2 / 2
				nop
			REPEND
			
			IF .CYCLES & 1
				STY COLUBK 
			ELSE
				STY.w COLUBK 
			ENDIF
		ENDM


		

		
		MAC LINEX2
		
.CYCLES     SET {1}

			IF .CYCLES < 3
				ECHO "MACRO ERROR: 'SLEEP': Duration must be > 2"
				ERR
			ENDIF
			
			IF .CYCLES & 1
.CYCLES2            SET .CYCLES - 3
			ELSE
.CYCLES2            SET .CYCLES - 4
			ENDIF

			REPEAT .CYCLES2 / 2
				nop
			REPEND
			
			IF .CYCLES & 1
				STX COLUBK 
			ELSE
				STX.w COLUBK 
			ENDIF
		ENDM




; EOF

Link to comment
Share on other sites

I'll make it cleaner when I have the time.

 

Edit:

As Andrew suggested, the project is now opensource!

I truly believe it will be better if everyone is able to put their part in it.

 

There is lot's to be done like game play-code, sounds.

Edited by roland p
Link to comment
Share on other sites

Yep, lots of STY, STY.w, STX, STX.w and NOP's. Trail and error based ;D. flipping colors happens already when you've moved 1 tile to the right/left.

 

If you also flip the colours as you move down the screen then you can create the checkerboard. My Juno First game displays moving lines to simulate movement. If you used this kind of approach to determine when to flip the colours then I think you would have a nice fully-functioning checkerboard.

 

What is needed for sprites? I'm programming the 2600 since Thursday and I've read some tutorials. Positioning is tricky, could that be done outside the board? Then data has to be loaded at the beginning of a scanline right?

 

Horizontal sprite positioning can be done outside the kernel. Inside the kernel you need to decide what sprite data to display on each line. I think Ballblazer only has two sprites that overlap the board (the other player, and the goalposts)? You will need to switch on/off these sprites on the right lines while drawing the grid. A good summary of the different approaches (skipdraw, switchdraw etc.) was posted in this thread.

 

Lot's of shifting around I guess. Now I have the bonus of 3pixel resolution instead of 4. scrolling a part of the checkerboard is now just wait for 1 cycle and everything that comes next is moved 1 cycles (I don't wait for WSYNC) :cool:

 

If you stored all of the different possible patterns in ROM then you could just display the appropriate one on each frame, but I think this would require a LOT of ROM space!

 

Thanks for sharing the code - you should get some good feedback from this. To upload code directly onto the forum, place it inside a ZIP file first.

 

Chris

Edited by cd-w
Link to comment
Share on other sites

Just a small update to keep it alive. I did not have much time to work on the project but some improvements have been made.

Things improved this time:

 

1. vertical resolution is now doubled.

2. precalculation of the movement is now correct :) maybe some small glitches, but much better then before.

3. I use a vanishing point up in the sky, where it really is.

4. the horizontal scrolling is now at a high precision at 1 virtual colorclock :cool:

 

The precalculated vector for the movement is still at half the vertical resolution of the checkerboard....

ballblazer.bin

Edited by roland p
Link to comment
Share on other sites

Just a small update to keep it alive. I did not have much time to work on the project but some improvements have been made.

Things improved this time:

 

1. vertical resolution is now doubled.

2. precalculation of the movement is now correct :) maybe some small glitches, but much better then before.

3. I use a vanishing point up in the sky, where it really is.

4. the horizontal scrolling is now at a high precision at 1 virtual colorclock :cool:

 

The precalculated vector for the movement is still at half the vertical resolution of the checkerboard....

 

This is very nice; well done!

 

If it were me, the next thing I'd do would be put a bit of inertia on the movement, so when you move in a direction, it takes a little while to accelerate, and when you let go, it takes a little while to stop. I think this would really accentuate the effect. Also, I'm wondering how much better it will look with the squares done -- that is, alternating the colours and making it a real chequerboard.

 

You could also just repeat the first bunch of scanlines again to give yourself a dual-window display, which would be pretty cool too.

 

Good work so far, keep going!

 

Cheers

A

Link to comment
Share on other sites

This is very nice; well done!

thanx!

 

If it were me, the next thing I'd do would be put a bit of inertia on the movement, so when you move in a direction, it takes a little while to accelerate, and when you let go, it takes a little while to stop. I think this would really accentuate the effect.

You're right. that would look cool. I've downloaded the Atari 5200 version of Ballblazer see what's really going on.

 

Also, I'm wondering how much better it will look with the squares done -- that is, alternating the colours and making it a real chequerboard.

Yep, it's about time :) I will work something out.

Link to comment
Share on other sites

Maybe you could try to use flicker to simulate antialiasing? At least it would be interesting to see the result. :ponder:

mmmh... interesting. by increasing/decreasing horizontal movement by a pixel every other frame. Maybe that looks nice.

 

I've seen in the atari 5200 version that there is a sort of antialiassing in the vertical direction, the 2600 should be able to do that too.

Link to comment
Share on other sites

mmmh... interesting. by increasing/decreasing horizontal movement by a pixel every other frame. Maybe that looks nice.

Interesting idea. Didn't think about this.

 

My idea is to use a different vertical offset for the "line" drawing. E.g. when you more one pixel of center, the pixel "jump" now is visible around the lower third. Which is probably the correct position when there is more than 50% of the pixel on the other side. With vertical antialiasing, you could do the pixel jump for the even frame a bit above and for the odd frame a bit below (e.g. after 25 and 75%) the current position.

 

Anyway, do whatever looks better. :)

 

I've seen in the atari 5200 version that there is a sort of antialiassing in the vertical direction, the 2600 should be able to do that too.

Yup, we would have vertical antialiasing here too.

Link to comment
Share on other sites

Interesting idea. Didn't think about this.

 

My idea is to use a different vertical offset for the "line" drawing. E.g. when you more one pixel of center, the pixel "jump" now is visible around the lower third. Which is probably the correct position when there is more than 50% of the pixel on the other side. With vertical antialiasing, you could do the pixel jump for the even frame a bit above and for the odd frame a bit below (e.g. after 25 and 75%) the current position.

 

Anyway, do whatever looks better.

 

I've now used a 2 pixel offset every other frame. It looks not bad. I've to change my tables a bit to make it look even better, but now you have REAL antialiassing!

ballblazer.bin

Link to comment
Share on other sites

Interesting idea. Didn't think about this.

 

My idea is to use a different vertical offset for the "line" drawing. E.g. when you more one pixel of center, the pixel "jump" now is visible around the lower third. Which is probably the correct position when there is more than 50% of the pixel on the other side. With vertical antialiasing, you could do the pixel jump for the even frame a bit above and for the odd frame a bit below (e.g. after 25 and 75%) the current position.

 

Anyway, do whatever looks better.

 

I've now used a 2 pixel offset every other frame. It looks not bad. I've to change my tables a bit to make it look even better, but now you have REAL antialiassing!

 

 

Noooo! This is a bad bad idea! It was so very clean, without any flickering. You're spoiling it with this totally unnecessary stuff. Stick to getting the checquerboard working, don't fix something that wasn't broken! Seriously, stay focused... don't get diverted!

 

Cheers

A

Link to comment
Share on other sites

Noooo! This is a bad bad idea! It was so very clean, without any flickering.

It doesn't look good on emulators and due to syncing problems most likely never will. But it might look good on a real TV if done right. Maybe as a switchable option.

 

But I agree, for now other stuff is more important.

Link to comment
Share on other sites

Noooo! This is a bad bad idea! It was so very clean, without any flickering. You're spoiling it with this totally unnecessary stuff. Stick to getting the checquerboard working, don't fix something that wasn't broken! Seriously, stay focused... don't get diverted!

Yeah, it looked better the old way. I bet this will look pretty darn good when it's done.

Link to comment
Share on other sites

Hi there,

 

My 4K is reaching its limits. The code for drawing the lines is a bit big because it's completely based on processor cycles. And besides the code, I use some tables for the horizontal movement wich occupies 207 bytes. The sinus table for vertical movement (which is needed to complete the tiles) is another 69 bytes. This results in >4K of ROM.

 

Now I've tried to calculate the vector in real time to save those 207 bytes. This is possible and takes now about 700 cycles. That's cool, but I'll get into memory problems anway. So what I want to do is:

 

1. Ditch the vector routine, nothing beats LDA OFFSET_DATA_0_7,X. Don't fix anything that's not broken ;)

2. Add some bankswitching

 

Is this the way to go? When I do bankswitching, I would want to go for the full 32K. What's the best way to do that?

 

 

Btw. I've downloaded a 6502 simulator to test small parts of code: http://home.pacbell.net/michal_k/6502.html You can exactly see what is going on. Really nice!

Link to comment
Share on other sites

1. Ditch the vector routine, nothing beats LDA OFFSET_DATA_0_7,X. Don't fix anything that's not broken ;)

2. Add some bankswitching

 

Is this the way to go? When I do bankswitching, I would want to go for the full 32K. What's the best way to do that?

Yes, add bankswitching. You'll never get a decent (or even playable :ponder:) Ballblazer clone in 4K.

 

Bankswitching is pretty easy, you just have to organize your code and data carefully. To set up your source code, just ORG each 4K block to wherever (make sure the 32K is consecutive) and RORG it to $Fxxx. You can search the forums for more information.

 

Or you can get crazy and use the wacky 32K bankswitching scheme I came up with. :ponder: No one else seems to think it's that cool, but I love it. :)

Link to comment
Share on other sites

@vdub_bobby,

I get to the backswitching later. I have fixed the issue now by altering some 'org' declarations.

 

Due to extremely short spare time in the checkerboard edges, I've not enough time/memory to update all sprites every line. Therefore I thought of the following: update everyline one sprite, giving a vertical resolution of 4 pixels per sprite, and change the update pattern every frame to get a interlaced like effect.

Unfortunatly, it does not work.

 

Can anyone tell me why the following code does not work?

	LDA GRP1
STA SPRITE_POINTERA

LDX #0
LDA #%10101010
STA (SPRITE_POINTERA,X)

And why the following code DOES work?

	LDA GRP0
STA SPRITE_POINTERA

LDX #0
LDA #%10101010
STA (SPRITE_POINTERA,X)

 

Maybe I'm doing something very stupid and it is not possible at all...

Link to comment
Share on other sites

@vdub_bobby,

I get to the backswitching later. I have fixed the issue now by altering some 'org' declarations.

 

Due to extremely short spare time in the checkerboard edges, I've not enough time/memory to update all sprites every line. Therefore I thought of the following: update everyline one sprite, giving a vertical resolution of 4 pixels per sprite, and change the update pattern every frame to get a interlaced like effect.

Unfortunatly, it does not work.

 

Can anyone tell me why the following code does not work?

	LDA GRP1
STA SPRITE_POINTERA

LDX #0
LDA #%10101010
STA (SPRITE_POINTERA,X)

And why the following code DOES work?

	LDA GRP0
STA SPRITE_POINTERA

LDX #0
LDA #%10101010
STA (SPRITE_POINTERA,X)

 

Maybe I'm doing something very stupid and it is not possible at all...

 

I never once found the need to use indexed indirect (addr,x) addressing. Not once!

Why can't this code be written...

 

	ldx #0
lda #%10101010
sta GRP0,x

 

Or even just drop the indexing and use absolute writes. It's quicker!

 

Anyway, to answer your question... read this...

 

Indexed Indirect Addressing

---------------------------

 

Find the 16-bit address starting at the given location plus the

current X register. The value is the contents of that address. For

example,

 

LDA ($B4,X) where X contains 6

 

gives an address of $B4 + 6 = $BA. If $BA and $BB contain $12 and

$EE respectively, then the final address is $EE12. The value at

location $EE12 is put in the accumulator.

 

 

 

 

So, looks like you're retrieving a 16 bit address from the location SPRITE_POINTERA, SPRITE_POINTERA+1 (which is uninitialised) and then you're adding the X register to that, and writing to that resulting address. Could be anything. Pure chance either of your examples works at all, I'd say. Um, well actually since we have mirrored memory, in theory you are still writing to zero page. This code will work OK with the # as Manuel said, but it will fail on some bankswitching schemes when you switch later. It's broken, so fix it :)

 

Cheers

A

Link to comment
Share on other sites

Funny that 'GRP0' does work. Probably the value $1B is stored at that adres? :D

 

Chances are usually good that the you get the last value returned from the bus, which indeed was GRP0. The exact behaviour may depend on the machine model and certain race conditions though I think. I'm sure somewhere on this board you'll find an essay from supercat detailling what exactly happens ;)

Link to comment
Share on other sites

The code looks pretty weird anyway, what are you trying to do there? I have yet to see some useful code using ($$,X) indexing ;)

 

I've (hope) just enough time to update 1 sprite/line. And I have 4 sprites to draw. so the kernel could look like this:

 

at line 1 update sprite 1 with data1

at line 2 update sprite 2 with data2

at line 3 update missle with data3

at line 4 update ball with data4

...

...

at line 37 update sprite 1 with data37

at line 38 update sprite 2 with data38

at line 39 update missle with data39

at line 40 update ball with data40

 

etc. (data1..40 is memory)

 

That could work, but will look funny. because every sprite is drawn on another line.

By using pointers, I could change on wich line wich sprite is updated, that would look like this:

 

at line 1 update @pointerA with data1

at line 2 update @pointerB with data2

at line 3 update @pointerC with data3

at line 4 update @pointerD with data4

 

PointerA would point to sprite 1 at frame 1, and to sprite 2 at frame 2 etc.

 

I hope I'm clear.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...