Jump to content
Mikes360

Tricky Graphics Suggestions

Recommended Posts

It seems to me that for some reason my ORG commands are not working correctly When I assemble the code using DASM this is a sample from the output of a table aligned to $F300

110  c23f		       38		      .byte.b	#%00111000
    111  c240
    112  c240							
;==============================================================================
    113  c240							
;				 R A I L - D A T A
    114  c240							
;==============================================================================
    115  c300					      ORG	BANK_ORIGIN + $300
    116  c300				   RailData
    117  c300		       00 0a	   RAIL_START =	10
    118  c300		       00 2e	   RAIL_HEIGHT =	23 * 2
    119  c300
    120  c300		       ea		      nop
    121  c301				   RailTable1 SUBROUTINE

Here is the code that sets a pointer to this table (standard macro from macro.h):

	SET_POINTER railGfxPtr1, RailTable1-1

And the value in the two bytes for railGfxPtr1 is $F240.

 

Any idea why its not getting aligned correctly?

Share this post


Link to post
Share on other sites

The ORG looks fine to me, RailTable starts at $C301. How to you setup the two bytes of the pointer?

Share this post


Link to post
Share on other sites

It looks like the pointer for railGfxPtr1 is getting set before BANK_ORIGIN is getting resolved. You can see c240 above the c300 in the code snippet. So if BANK_ORIGIN is known before the macro it should work. It might be with the order of your includes.

Share this post


Link to post
Share on other sites

Could it be that you base your pointer on RailData and not RailTable1?

 

And BANK_ORIGIN is a constant, no?

Edited by Thomas Jentzsch

Share this post


Link to post
Share on other sites

BANK_ORIGIN is first set like this

 

BANK_ORIGIN SET $C000

 

For the start of each new bank I use this

	MAC NEW_BANK
	
	SEG {1}
	ORG BANK_ORIGIN
	RORG $F000 
	
	ENDM

For the end of each bank I use this.

	MAC END_BANK
	
	ORG BANK_ORIGIN + $FFA
	RORG $FFFA

	.word {1}   ; NMI
	.word {2}   ; RESET
	.word {3}	; IRQ 
	
BANK_ORIGIN SET BANK_ORIGIN + $1000
CURRENT_BANK SET CURRENT_BANK + 1
	
	ENDM
Edited by Mikes360

Share this post


Link to post
Share on other sites

consider using align to make your data line up on page boundaries:

   align 256
YourData:
   .byte xx
   .byte xx
   .byte xx
   .byte xx
...

This way you don't have to make any changes if the code before YourData expands in size.

  • Like 1

Share this post


Link to post
Share on other sites

Hi SpiceWare,

 

That does work thank you very much for your recommendation, I have no idea what was going wrong before it looks ok in the debug output but in Stella itself it clearly was not getting aligned properly.

 

This is a very handy way to line up data ill read more about it.

Edited by Mikes360

Share this post


Link to post
Share on other sites

If you are willing to accept that the railing pole (at least on top) is only 3 pixels high, then you can draw the whole rail and suppport poles by skewing the P1 sprite.

The sprite starts on the left and moves 2 pixels to the right each line:
01234567
    XXXX
      X XX
      X   XX
      X     XX
      01234567XX
                XX
                  XX

Then of course the sprite image data is skewed to make the support pole straight:
%00001111
%00001011
%00100011
%10000011
%00000011 .. repeat this line for the height of the railing
%00001000
%00100000
%10000000

Share this post


Link to post
Share on other sites

If you are willing to accept that the railing pole (at least on top) is only 3 pixels high, then you can draw the whole rail and suppport poles by skewing the P1 sprite.

The sprite starts on the left and moves 2 pixels to the right each line:
01234567
    XXXX
      X XX
      X   XX
      X     XX
      01234567XX
                XX
                  XX

Then of course the sprite image data is skewed to make the support pole straight:
%00001111
%00001011
%00100011
%10000011
%00000011 .. repeat this line for the height of the railing
%00001000
%00100000
%10000000

 

That's pretty tricky, drawing the entire rail with player1!

You could use its missile, being the railing color, to extend the top post.

The bottom post could just continue down the screen as player1, right?

Share this post


Link to post
Share on other sites

That's pretty tricky, drawing the entire rail with player1!

You could use its missile, being the railing color, to extend the top post.

The bottom post could just continue down the screen as player1, right?

 

Yes, you can extend the sprite to any height at the bottom pole as long as you stop the skewing action. If you skew the sprite one pixel at a time rather than 2 you can get a pole 7 pixels high, but the railing angle is much steeper.

Share this post


Link to post
Share on other sites

That's a really cool method!

Yeah. Although it goes back to Stampede and Dolphin, SpiceWare used it for the Medieval Mayhem dragon, and the big Space Rocks to make them less blocky.

I also like the mangled missiles and the ball object that smooth the PlayField chunky diagonals in Escape From The Mindmaster. Quite a lot of tricks if you view Stella Debug Colors.

Something I can not do with batari Basic. :(

Share this post


Link to post
Share on other sites

Some interesting ideas thanks Robert,

 

I am not sure what you mean by skewing the sprite would you mind providing a example in code?

 

Along with the rail at 2 scan line resolution I have to draw an asymmetrical play field at 2 scan line resolution and the player sprite at single line resolution so I am a bit tight for kernel time.

 

I am using a form of Masked Draw at the moment as it seems simpler and faster than using switch draw in this context.

Share this post


Link to post
Share on other sites

I am not sure what you mean by skewing the sprite would you mind providing a example in code?

 

 

I talk about that here, basically you update HMP1 and hit HMOVE on every scanline in order to shift player1 left/right. I use that technique in Medieval Mayhem (the dragon and knight), Space Rocks (large asteroids) and Draconian (space stations).

 

Look for KernelGameDragonCode in the source for Medieval Mayem.

Edited by SpiceWare

Share this post


Link to post
Share on other sites

The idea of drawing the whole rail with one sprite is very appealing but I will need to see if the height of the first pole is too much of a compromise.

Share this post


Link to post
Share on other sites

Hi Guys,

I have finally completed a first version of my kernel for this and it gives me the following
  • 2 scanline resolution asymmetrical scrolling playfield
  • 2 scanline resolution handrail
  • 1 scanline resolution player
The playfield data is loaded from a RAM buffer, the rail and player is drawn using masking. Its not perfect by any stretch and I think some of you guys could optimise this more so i though I would post it here and see if you can spot any obvious improvements.
Here is the main kernel:
DrawFrame SUBROUTINE
	ldy #PLAYFIELD_START
	ldx #PF_BUFFER_SIZE - PF_COL_COUNT
	
	lda #PF_BLOCK_HEIGHT
	sta pfBlockCount
	sec 
	sta WSYNC
	Sleep 76 - 13
;===========================
.drawLoop
	PLAYER_DRAW				; 13

;*****						; first scanline

	sta HMOVE				; 3
	PLAYFIELD_DRAW_LEFT 	; 21
	dey					; 2
	Sleep 2					; 3
	PLAYFIELD_DRAW_RIGHT 	; 21
	PLAYER_DRAW				; 13
	dey 					; 2
	dec pfBlockCount		; 5
	CLEAR_PLAYFIELD_GFX		; 11

;*****						; second scanline 

	RAIL_DRAW				; 43
	lda pfBlockCount		; 3
	
	bne .skipNewBlock		; 2,3

	txa						; 2
	sbc #PF_COL_COUNT		; 2
	tax						; 2
	lda #PF_BLOCK_HEIGHT	; 2
	sta pfBlockCount		; 3

	bcs .drawLoop			; 2,3 - 15,16
	jmp Endframe

.skipNewBlock	
	Sleep 11
	jmp .drawLoop			; 3

Endframe
	CLEAR_PLAYFIELD_GFX
	sta GRP0 ; a = zero from macro 
	sta ENAM0
	sta ENAM1

	jmp Bottom
There are a number of macros in here which I added to make the logic more readable they are below:
;============================================================================== 
	MAC PLAYFIELD_DRAW_LEFT
	lda pfBuffer,x			; 4
	sta PF0 				; 3
	lda pfBuffer+1,x 		; 4
	sta PF1 				; 3
	lda pfBuffer+2,x 		; 4
	sta PF2 				; 3 - 21
	ENDM
;============================================================================== 
	MAC PLAYFIELD_DRAW_RIGHT
	lda pfBuffer+3,x 		; 4
	sta PF0 				; 3
	lda pfBuffer+4,x 		; 4
	sta PF1 				; 3 
	lda pfBuffer+5,x		; 4
	sta PF2 				; 3 - 21
	ENDM
;============================================================================== 
	MAC CLEAR_PLAYFIELD_GFX
	lda #0					; 2
	sta PF0					; 3
	sta PF1					; 3
	sta PF2					; 3 - 11
	ENDM
;============================================================================== 
	MAC RAIL_DRAW
	lda (railGfxPtr1),y 	;5
	and (railMaskPtr),y 	;5
	sta ENAM0				;3

	lda (railGfxPtr2),y 	;5
	and (railMaskPtr),y 	;5
	sta ENAM1				;3

	lda (railMovePtr),y		;5
	and (railMaskPtr),y 	;5
	sta HMM1				;3
	ENDM
;==============================================================================
	MAC PLAYER_DRAW 	
	lda (playerGfxPtr),y	;5
	and (playerMaskPtr),y	;5
	sta GRP0				;3 - 13
	ENDM
;============================================================================== 
If anyone is interested in seeing the full source code let me know and ill post it.
Edited by Mikes360

Share this post


Link to post
Share on other sites

Here is a couple of new screen shots showing the player, rail and playfield all being drawn together.

 

post-34963-0-84632300-1420752127_thumb.png post-34963-0-37506100-1420752153_thumb.png

  • Like 1

Share this post


Link to post
Share on other sites

Thanks I am pretty happy with the result graphically.

 

However in order to achieve this I have had to use a masking technique for both the player and rail which adds 20 cycles. 5 cycles every time you and the graphics or move value with a mask before storing it a register.

 

I think its definitely better than skip draw which I used in my point zero game but there are looking forward some tricky challenges with ensuring the graphics is laid out in a way to never cross a page boundary when I load it from the relevant tables.

 

I am planning on this being an F6 16K game so I am willing to take the hit on the ROM for the graphics tables in order to achieve the efficiency in the main drawing kernel.

Share this post


Link to post
Share on other sites

I have been in the process of trying to optimise what I have to get some more cycles back in the Kernel, I have found a simple but significant saving for both the kernel and ROM.

 

The kinked and bottom vertical part of the rail are always being drawn when the mask is off so you can completely remove the need for a table to draw this.

 

So now drawing the rail goes from this

	MAC RAIL_DRAW
	lda (railGfxPtr1),y 	;5
	and (railMaskPtr),y 	;5
	sta ENAM0				;3

	lda (railGfxPtr2),y 	;5
	and (railMaskPtr),y 	;5
	sta ENAM1				;3

	lda (railMovePtr),y		;5
	and (railMaskPtr),y 	;5
	sta HMM1				;3
	ENDM

To this

	MAC RAIL_DRAW
	lda (railGfxPtr1),y 	;5
	and (railMaskPtr),y 	;5
	sta ENAM0				;3

	lda #2
	and (railMaskPtr),y 	;5
	sta ENAM1				;3

	lda (railMovePtr),y		;5
	and (railMaskPtr),y 	;5
	sta HMM1				;3
	ENDM

Saving 3 cycles in the kernel and loads of ROM space as the table needed padding for the masking.

Share this post


Link to post
Share on other sites

Secondly I have clipped the playfield by mirroring it and not setting PF0.

 

I noticed walaber is doing this in the Moto X game and with the HMOVE lines issue it just seems like a no brainer.

 

This saves me 14 cycles a total of 17 when coupled with the first saving, there is also an additional RAM saving with this too as I was actually using 2 bytes for each row of my playfield for the PF0 data.

 

I should now be able to get kinked and sparks going on now!

Share this post


Link to post
Share on other sites

I think you could also use the SAX command, which ANDs A and X and then stores the result.

 

That way you only load the mask once and reuse it multiple times

 

LDA (maskPtr),Y

TAX

...

 

LDA (gfxPtr),Y

SAX ENAM1

 

LDA (movePtr),Y

SAX HMM1

  • Like 1

Share this post


Link to post
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...