Jump to content
IGNORED

Anyone think Ballblazer is possible on the 2600?


Recommended Posts

All this and it's only 4k so far? Pretty cool! Can't wait to see what comes of this!

Yep, 1004 bytes ROM and 17 bytes of RAM left so far.

 

That's not much RAM left for the actual game... the need to optimise somewhere or can I smell a superchip around the corner (I wouldn't blame ya here!)?

I'm thinking of lowering the resolution of the ship, that would add 20 bytes. The actual resolution can be seen in the window of the ship. I took such high resolution for fine positioning, but I think I can achieve the same with careful usage of the VDELP0 and VDELP1 registers (left and right part of the ship will be updated every other line then)

Link to comment
Share on other sites

I'm thinking of lowering the resolution of the ship, that would add 20 bytes. The actual resolution can be seen in the window of the ship. I took such high resolution for fine positioning, but I think I can achieve the same with careful usage of the VDELP0 and VDELP1 registers (left and right part of the ship will be updated every other line then)

 

It would be good to keep the high-resolution ship. Is the ship data loaded from ROM or RAM? I wouldn't worry about using ROM space as you can always add more by bankswitching, but 20 bytes of RAM is quite a lot. If you post up the source code, I'm sure the code wizards around here will be able to help you improve things.

 

Chris

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

I'm thinking of lowering the resolution of the ship, that would add 20 bytes. The actual resolution can be seen in the window of the ship. I took such high resolution for fine positioning, but I think I can achieve the same with careful usage of the VDELP0 and VDELP1 registers (left and right part of the ship will be updated every other line then)

 

It would be good to keep the high-resolution ship. Is the ship data loaded from ROM or RAM? I wouldn't worry about using ROM space as you can always add more by bankswitching, but 20 bytes of RAM is quite a lot. If you post up the source code, I'm sure the code wizards around here will be able to help you improve things.

 

Chris

In the sky part the ship is loaded from ROM, in the checkerboard part the ship is loaded from RAM because of speed.

 

Here is the sky code where upper part of sprite is loaded and lower part is put into memory:

		LDY #0
BlueLines
	;ODD LINE
LDA SHIPR,Y
STA GRP1;display right part of ship

	;EVEN LINE
STA WSYNC

LDA SHIPL,Y;;display left part of ship
STA GRP0


TYA		 	
CLC
ADC #20		; add twenty to current line
TAX
LDA SHIPL,X	;Get left part
STA sprite_data_l,Y;Store left part in memory
LDA SHIPR,X	;Get right part
STA sprite_data_r,Y;Store right part in memory

STA WSYNC
INY 
CPY #20
BNE BlueLines

Edited by roland p
Link to comment
Share on other sites

In the sky part the ship is loaded from ROM, in the checkerboard part the ship is loaded from RAM because of speed.

Here is the sky code where upper part of sprite is loaded and lower part is put into memory: <snip>

 

I'm still not clear why you need to put the data in memory - can you post up the code where it is displayed on screen?

 

I think you can do LDA SHIPL+20,Y (4 cycles) instead of adding 20 explicitly to the Y value unless I am missing something.

 

Chris

Link to comment
Share on other sites

I'm still not clear why you need to put the data in memory - can you post up the code where it is displayed on screen?

 

Well the code is a bit strange and long. Here is the code for checkerboard line 7:

	
SBC PlayfieldX_frag;(3)
BCS SkipLine7	;(2/3)
SkipLine7

;7A

LDX tile_pointer + 7
LDY PLAYFIELD_DATA,X
STY COLUBK
INX

LDY sprite_data_l + 7
STY GRP0

SLEEP 4
LDY PLAYFIELD_DATA,X
NOP
NOP
STY COLUBK
INX

LDY PLAYFIELD_DATA,X
NOP
NOP
STY COLUBK
INX

LDY PLAYFIELD_DATA,X
NOP
NOP
STY COLUBK
INX

LDY PLAYFIELD_DATA,X
NOP
NOP
STY COLUBK	



;7B
LDY sprite_data_r + 8
STY GRP1

SLEEP 8
LDX tile_pointer + 7
LDY PLAYFIELD_DATA,X
STY COLUBK
INX

LDY PLAYFIELD_DATA,X
NOP
NOP
STY COLUBK
INX

LDY PLAYFIELD_DATA,X
NOP
NOP
STY COLUBK
INX

LDY PLAYFIELD_DATA,X
NOP
NOP
STY COLUBK
INX

LDY PLAYFIELD_DATA,X
LDX sprite_data_l + 8		   ;prefetch sprite data for next line
STY.w COLUBK

 

 

I think you can do LDA SHIPL+20,Y (4 cycles) instead of adding 20 explicitly to the Y value unless I am missing something.

 

Well, the sprite has to be able to scale and move too, so I left it a bit dynamically. And SHIPL+20 is rendered to a constant value at compile time right?

Link to comment
Share on other sites

Well, the sprite has to be able to scale and move too, so I left it a bit dynamically. And SHIPL+20 is rendered to a constant value at compile time right?

 

Yes, this value will be treated as a constant at compile time, so it won't be suitable for your sprite data. However it looks like you might be able to use this approach in your kernel, e.g. replace INX LDY PLAYFIELD_DATA,X with LDY PLAYFIELD_DATA+1,X? The best approach for displaying the sprite data would probably be just to store a pointer to the sprite data in RAM and then use indirect indexed addressing during the display, e.g. LDA (SpritePtr),Y [5 Cycles]. It looks like you have enough spare cycles to do this in the code that you have posted, but you will need to free up the Y register and things are probably tighter towards the top of the screen?

 

Chris

Link to comment
Share on other sites

Yes, this value will be treated as a constant at compile time, so it won't be suitable for your sprite data. However it looks like you might be able to use this approach in your kernel, e.g. replace INX LDY PLAYFIELD_DATA,X with LDY PLAYFIELD_DATA+1,X? The best approach for displaying the sprite data would probably be just to store a pointer to the sprite data in RAM and then use indirect indexed addressing during the display, e.g. LDA (SpritePtr),Y [5 Cycles]. It looks like you have enough spare cycles to do this in the code that you have posted, but you will need to free up the Y register and things are probably tighter towards the top of the screen?

 

Chris

 

I could load the sprite directly from rom, but I really have to find cycles for it. And I'll have to store every (zoomed) sprite in rom then. Some logic that could scale the sprite would be very nice.

Link to comment
Share on other sites

Well, the sprite has to be able to scale and move too, so I left it a bit dynamically. And SHIPL+20 is rendered to a constant value at compile time right?

 

Yes, this value will be treated as a constant at compile time, so it won't be suitable for your sprite data. However it looks like you might be able to use this approach in your kernel, e.g. replace INX LDY PLAYFIELD_DATA,X with LDY PLAYFIELD_DATA+1,X?

 

Wow... I missed that one :D

Thanks!

Edited by roland p
Link to comment
Share on other sites

I could load the sprite directly from rom, but I really have to find cycles for it. And I'll have to store every (zoomed) sprite in rom then. Some logic that could scale the sprite would be very nice.

 

I could be wrong, but I doubt you will find any quick logic to scale the sprite - much better just to store several different sizes in ROM if possible. In Juno First it looks like the sprites scale up as they approach the front of the screen, but in fact there are only 3 sizes used (small, medium, and large).

 

Chris

Link to comment
Share on other sites

I could load the sprite directly from rom, but I really have to find cycles for it. And I'll have to store every (zoomed) sprite in rom then. Some logic that could scale the sprite would be very nice.

 

I could be wrong, but I doubt you will find any quick logic to scale the sprite - much better just to store several different sizes in ROM if possible. In Juno First it looks like the sprites scale up as they approach the front of the screen, but in fact there are only 3 sizes used (small, medium, and large).

 

Chris

 

The original version of Ballblazer just cuts the ship into 4 parts which slides intelligently so it looks like it's scaling. I would like to do the same, but just store the sprites is much easier.

Link to comment
Share on other sites

I'm working on the drones right now. I managed to get them 16 pixels wide! So I can reasamble the original drones pretty close.

So you concentrate on color writes only for creating the checkerboard, right? After trying to mix color writes and HMOVES, I fully understand your decision. :)

 

And it looks good enough your way already.

Link to comment
Share on other sites

Well, the sprite has to be able to scale and move too, so I left it a bit dynamically.

RAM is much shorter than ROM, so maybe you better use a lot of fixed scales from ROM. Especially for vertical scaling. For horizontal scaling, a lot can be done by partially overlapping the two sprites.

 

BTW: When you see the sprite from the side, you will need even more RAM because it isn't symmetric anymore.

Link to comment
Share on other sites

Well, the sprite has to be able to scale and move too, so I left it a bit dynamically.

RAM is much shorter than ROM, so maybe you better use a lot of fixed scales from ROM. Especially for vertical scaling. For horizontal scaling, a lot can be done by partially overlapping the two sprites.

 

BTW: When you see the sprite from the side, you will need even more RAM because it isn't symmetric anymore.

 

I now use 20 bytes for left and 20 bytes for right. I might reduce that to 10 bytes left and 10 bytes right without sacrificeing too much quality. Currently, thanks to cd-w's optimizations, I have 32 bytes of RAM left.

 

I now use the following code to read a sprite from ram:

	LDY sprite_data_r + 18
STY GRP1

That's 6 cycles

 

If I want to change this to rom it would look like this? :

	LDY #18;Row number
LDA (sprite_ptr_r),Y
STA GRP0

 

That is 2 + 5 + 3 = 10 cycles.

Finding 4 cycles can be very hard if you havn't any.

 

 

I discovered that the goal can be on the left/right side too, meaning that missles must also be integrated into the checkerboard kernel.

Edited by roland p
Link to comment
Share on other sites

If I want to change this to rom it would look like this? :

	
 LDY #18;Row number
 LDA (sprite_ptr_r),Y
 STA GRP0

That is 2 + 5 + 3 = 10 cycles.

Finding 4 cycles can be very hard if you havn't any.

 

You shouldn't need to set Y on every access, so that should be 8 cycles instead of 6? Can you post the tightest part of your kernel so that we can see if any more optimisation is possible?

 

I discovered that the goal can be on the left/right side too, meaning that missiles must also be integrated into the checkerboard kernel.

 

I suppose you could omit this feature from the 2600 version since it isn't essential for the game?

 

Chris

Link to comment
Share on other sites

I think I leave it this way. It ain't broken yet.

The Accumulator is now dedicated for calculation of the horizontal movement only, because putting that in the kernel saved another 400/500 cycles outside the kernel.

 

Yup, you are doing a great job so far - I'm looking forward to seeing how this develops.

 

Chris

Link to comment
Share on other sites

I discovered that the goal can be on the left/right side too, meaning that missles must also be integrated into the checkerboard kernel.

When can that happen? When the other player is having the ball?

 

Anyway, I agree with cd-w, most likely one wouldn't even notice this missing.

Link to comment
Share on other sites

I think I leave it this way. It ain't broken yet.

 

The Accumulator is now dedicated for calculation of the horizontal movement only, because putting that in the kernel saved another 400/500 cycles outside the kernel.

Are you doing a Bresenham inside the kernel?

 

I really would like to see your complete source code, because I am pretty sure, together we can easier find a way to solve a problem.

Link to comment
Share on other sites

When can that happen? When the other player is having the ball?

 

Anyway, I agree with cd-w, most likely one wouldn't even notice this missing.

 

I actually played the game :D

 

Example: When 2 ships are at the left side near a goal and the ball is at the right side near a goal the players will point to the ball and you will see the goal on your left.

 

But I will make turns of 180 degrees instead of 90, the engine is already build like that. It will make things a bit easier. Maybe some indicators that help to indicate where the ball is located when it's off screen.

post-15728-1223382312_thumb.png

Edited by roland p
Link to comment
Share on other sites

I actually played the game :D

So did I! :D

 

Example: When 2 ships are at the left side near a goal and the ball is at the right side near a goal the players will point to the ball and you will see the goal on your left.

 

But I will make turns of 180 degrees instead of 90, the engine is already build like that. It will make things a bit easier. Maybe some indicators that help to indicate where the ball is located when it's off screen.

Interesting idea. I wonder how it will work out.

 

With the ball, the player's ship always points to the opposite goal. So that's 180° anyway. But without the ball, the player's ship always points to the ball. How are you going to handle this? Won't 180° steps make fighting for the ball much different than now?

Link to comment
Share on other sites

I think I leave it this way. It ain't broken yet.

 

The Accumulator is now dedicated for calculation of the horizontal movement only, because putting that in the kernel saved another 400/500 cycles outside the kernel.

Are you doing a Bresenham inside the kernel?

 

I really would like to see your complete source code, because I am pretty sure, together we can easier find a way to solve a problem.

 

I Just saw this post.

 

Here you have the source in it's current state.

 

I think I do a sort of Bresenham. I start with LDA #255

And then for each line:

 

SBC PlayfieldX_frag

BCS *+2

 

When PlayfieldX_frag is 0, carry will never be set and BCS *+2 results in 2 cycles. When PlayfieldX_frag is 255 (max) carry will be set every line and BCS *+2 will result in 3 cycles on every line. This causes every line to scroll 1 pixel in relation to the previous. Any value in between will result in a smooth vector as seen in the game. I found this the coolest find during my ballblazer programming.

ballblazer.zip

Edited by roland p
Link to comment
Share on other sites

I think I do a sort of Bresenham. I start with LDA #255

And then for each line:

 

SBC PlayfieldX_frag

BCS *+2

Yup, that's (some "sort of" ;)) Bresenham. And 5/6 cycles is really as fast as you can get.

 

But you should initialize the A with $80 to be more correct. With different initialization values, you might get some kind of subpixel scrolling.

 

But you also could do those calculations out side the kernel and free A inside, e.g for indirect, indexed sprite graphics. Put the carries into 3 (20/8) variables and ASL them.

 

This will cost you up to (for the first and last bit of each variable you can use BIT instead of ASL) 7/8 cycles instead of 5/6. But if you can afford that, freeing A might give you some necessary flexibility.

Link to comment
Share on other sites

I think I do a sort of Bresenham. I start with LDA #255

And then for each line:

 

SBC PlayfieldX_frag

BCS *+2

Yup, that's (some "sort of" ;)) Bresenham. And 5/6 cycles is really as fast as you can get.

 

But you should initialize the A with $80 to be more correct. With different initialization values, you might get some kind of subpixel scrolling.

 

But you also could do those calculations out side the kernel and free A inside, e.g for indirect, indexed sprite graphics. Put the carries into 3 (20/8) variables and ASL them.

 

This will cost you up to (for the first and last bit of each variable you can use BIT instead of ASL) 7/8 cycles instead of 5/6. But if you can afford that, freeing A might give you some necessary flexibility.

I'll stick with my current solution for now. I'll try to scale the sprite programmatically. If that doesn't work, I can load the sprite from rom anyway.

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