Jump to content
IGNORED

Blitter and rb+ help


Sporadic

Recommended Posts

Hi all,

 

I have been messing around with poking the blitter from rb+. The ultimate goal is to either draw coloured lines or copy a chunk of a sprite to another sprite.

 

In a simple program I have got this to work with a sprite copy to another sprite and i've drawn a line (and block of colour) over a sprite too.

 

 

However, I wanted to start using these functions within a loop as a test before using them proper for a game but it seems I get weird behavour/crashes.

 

I have attached an example rb+ project. What it does (for testing purposes) is to copy the top half of a sprite over to another sprite, then it should repeat.

If you run the program as is, you will see this effect working. It loops 32 times and calls " LPOKE B_CMD,LFU_REPLACE|SRCEN " which copies a line and advances to the next line ready for the next iteration.

 

If you then edit the listing and uncomment out the c=0 near the bottom of the listing, you will see the screen just clears and nothing can be seen.

I know ultimately, adding that line in won't visually show anything different because the sprite will just copy over the top of the destination again but it shouldn't make anything disappear either! I would expect the c=0 to force it to start from the top again and copy the top half again.

 

Separately, if you uncomment the vsync at the bottom, you will also see the sprites for a moment and then they vanish. You don't need the vsync to see all the blitter pokes but if this gets incorporated into a game then I imagine I will need a vsync for other sprites to update etc.

 

So there looks like 2 separate problems here. Any help greatly appreciated!

 

 

Thanks

blitter.zip

Edited by Sporadic
Link to comment
Share on other sites

hmm,

 

if I chuck everything in the loop and IF statements then this works; I wanted to reduce the calls to the registers etc.

 

This listing correctly flickers the top and bottom, alternating from each sprite source.

rlist=(RAPTOR_LIST *)strptr(RAPTOR_sprite_table)
basic_r_size=0
basic_r_indx=0

DIM particle%	:particle=0
DIM grass%		:grass=particle+1
DIM road%		:road=grass+1
DIM final%		:final=road+1
LOADCLUT(strptr(SPR_GRASS_clut),1,16)
LOADCLUT(strptr(SPR_ROAD_clut),2,16)
LOADCLUT(strptr(SPR_FINAL_clut),3,16)

dim gfxgrass%
gfxgrass=rlist[grass].gfxbase

dim gfxroad%
gfxroad=rlist[road].gfxbase

dim gfxfinal%
gfxfinal=rlist[final].gfxbase

dpoke BG,32	

dim i% : i=0
dim c% : c=0

DO

	IF c=0 THEN
	
		LPOKE A1_BASE,gfxfinal			
		LPOKE A1_PIXEL,0
		LPOKE PIXEL4|XADDPHR|PITCH1,A1_FLAGS
		
		LPOKE B_COUNT,(1<<16)+(16*1)

		LPOKE A2_BASE,gfxroad		
		LPOKE A2_PIXEL,0
		LPOKE PIXEL4|XADDPHR|PITCH1,A2_FLAGS
		for i = 0 to 32			
			LPOKE B_CMD,LFU_REPLACE|SRCEN			
		next i
			
		LPOKE A2_BASE,gfxgrass
		for i = 0 to 32			
			LPOKE B_CMD,LFU_REPLACE|SRCEN			
		next i
		
		c=1
		
		delay(1)
		
	ELSE
	
		LPOKE A1_BASE,gfxfinal			
		LPOKE A1_PIXEL,0
		LPOKE PIXEL4|XADDPHR|PITCH1,A1_FLAGS
		
		LPOKE B_COUNT,(1<<16)+(16*1)

		LPOKE A2_BASE,gfxgrass		
		LPOKE A2_PIXEL,0
		LPOKE PIXEL4|XADDPHR|PITCH1,A2_FLAGS
		for i = 0 to 32			
			LPOKE B_CMD,LFU_REPLACE|SRCEN			
		next i
			
		LPOKE A2_BASE,gfxroad
		for i = 0 to 32			
			LPOKE B_CMD,LFU_REPLACE|SRCEN			
		next i
		
		c=0
		
		delay(1)

	ENDIF

LOOP

The delay(1) seems to stop it crashing too.

 

Not sure why this listing works and the previous one doesn't. (Ignoring the fact the both do different things)

Edited by Sporadic
Link to comment
Share on other sites

So the previous listing works. This one doesn't.

 

If you take out the c=0 near the bottom it runs and you can see the first iteration of 32 has run correctly (half the sprite has copied over).

 

If you put the c=0 back in it fails and no sprites are drawn (well they disappear after the initial loop of 32), it doesn't seem to like me swapping the src, resetting everything and then iterating the 32 again.


rlist=(RAPTOR_LIST *)strptr(RAPTOR_sprite_table)
basic_r_size=0
basic_r_indx=0

DIM particle%	:particle=0
DIM grass%		:grass=particle+1
DIM road%		:road=grass+1
DIM final%		:final=road+1
LOADCLUT(strptr(SPR_GRASS_clut),1,16)
LOADCLUT(strptr(SPR_ROAD_clut),2,16)
LOADCLUT(strptr(SPR_FINAL_clut),3,16)

dim gfxgrass%
gfxgrass=rlist[grass].gfxbase

dim gfxroad%
gfxroad=rlist[road].gfxbase

dim gfxfinal%
gfxfinal=rlist[final].gfxbase

dpoke BG,32	

dim c% : c = 0


'BASIC BLITTER SETUP TO COPY BLOCK OF DATA

'point to destination
	LPOKE A1_BASE,gfxfinal			
	LPOKE A1_PIXEL,0
	LPOKE PIXEL4|XADDPHR|PITCH1,A1_FLAGS

'point to source
	LPOKE A2_BASE,gfxroad			
	LPOKE A2_PIXEL,0
	LPOKE PIXEL4|XADDPHR|PITCH1,A2_FLAGS

'1 line
	LPOKE B_COUNT,(1<<16)+(16*1)
	
DIM src%	:	src = gfxroad
c = 0

DO

	c++

	IF c < 32 THEN
		
		LPOKE B_CMD,LFU_REPLACE|SRCEN
		
	ELSE
	
		IF src = gfxroad THEN
			src = gfxgrass
		ELSE
			src = gfxroad
		ENDIF
			
		'point to destination and reset counters
		LPOKE A1_BASE,gfxfinal			
		LPOKE A1_PIXEL,0
		LPOKE PIXEL4|XADDPHR|PITCH1,A1_FLAGS

		'point to new source and reset counters
		LPOKE A2_BASE,src			
		LPOKE A2_PIXEL,0
		LPOKE PIXEL4|XADDPHR|PITCH1,A2_FLAGS

		LPOKE B_COUNT,(1<<16)+(16*1)
		
		c=0		
	
	ENDIF
	
LOOP


	
Edited by Sporadic
Link to comment
Share on other sites

You need to wait for the BLITTER to stop being busy before you you start using it again.

Thanks for the reply.

 

I was wondering something like that.

 

Any ideas how I could go about that? I couldn't see anything in the Jag docs.

 

 

EDIT: The status register?

Status Register F02238 Read only

 

0 IDLE When set, the blitter is completely idle and its last bus transaction is completed.

1 STOPPED When set, the blitter is stopped in its collision detection mode - see the collision control register below.

 

Check if it's idle before firing new stuff at it?

Edited by Sporadic
  • Like 1
Link to comment
Share on other sites

Before writing to any BLITTER registers LPEEK the B_CMD register in a loop. If bit 0 is 0 stay in the loop, otherwise quit the loop. Update the BLITTER registers and get on with something else.

Sorry, just wanted to check.

 

It says 0 is idle. so you're basically saying only fire commands at it if bit 0 is 0?

Link to comment
Share on other sites

Can't build the sample code : i got an error during C compiling, but i see some errors :

- all "LPOKE PIXEL4|XADDPHR|PITCH1,A2_FLAGS" are reversed from the correct instruction that should be "LPOKE A2_FLAGS, PIXEL4|XADDPHR|PITCH1"

- in phrase mode (XADDPHR) you can't use pixel size below 8-bit, else the blitter goes to infinite loop.

if you have 4-bit pixel that is multiple of phrase, you can use 8-bit pixel with PIXEL8 and divide by 2 the amount of the X in B_count, else you need to use the pixel mode. :)

 

 

 

For the 68k, you don't need to read the blitter status register, the blitter has higher priority than the 68k and freeze it during his blitt operation.

The blitter release the bus for the 68k only on 68k interrupts, and when blitter operation is in idle or stopped states.

But for compatibility and stability, I highly recommended to add the blitter checking status before using it.

 

 

EDIT :

I think that Raptor use the Blitter in it's OP list updates, probably it will need to use the flag to disable this features but don't know how to do it :P

else blitter regs will be destroyed each VBL.

Edited by SCPCD
  • Like 3
Link to comment
Share on other sites

Can't build the sample code : i got an error during C compiling, but i see some errors :

- all "LPOKE PIXEL4|XADDPHR|PITCH1,A2_FLAGS" are reversed from the correct instruction that should be "LPOKE A2_FLAGS, PIXEL4|XADDPHR|PITCH1"

 

im pretty sure the lpokes are the correct orientation otherwise I wouldnt have seen any output etc.

 

Thanks for the other info, thats great. I'm not 100% sure where I stand on the bit depth when the jag is in 16 bit mode but the sprites are only 4 bit. So I went with what the sprites had which seems to work. It is copying the data over on the first run. Perhaps its getting stuck in that loop, if its not the idle status groovybee suggested. I wont get chance to try it till tomorrow now.

 

Cheers

Link to comment
Share on other sites

im pretty sure the lpokes are the cort orientation otherwise I wouldnt have seen any output etc.

 

Thanks for the other info, thats great. I'm not 100% sure where I stand on the bit depth when the jag is in 16 bit mode but the sprites are only 4 bit. So I went with what the sprites had which seems to work. It is copying the data over on the first run. Perhaps its getting stuck in that loop, if its not the idle status groovybee suggested. I wont get chance to try it till tomorrow now.

 

Cheers

Hang on. Im talking bollocks. I do have them round the wrong way!!! Lmao. Thank you. Thats the first thing to change tomorrow!!!!!!

  • Like 1
Link to comment
Share on other sites

Thanks again for the help everyone. I made the changes to the pokes for the flags (that was a copy paste error from the asm) and changed to PIXEL8.

 

Things kind of work but it crashes if I split the pokes in a loop. As I showed previously. If I but all the blitter pokes in the same iteration of the loop then it works, so perhaps its clashing with something else (raptor for example).

 

I tried adding the status check as suggested but that didn't stop the crash either. I might be ok to use as is, if i'm clever about setting up the registers then I can do all blitter stuff within the loop.

 

I'll keep playing :D

 

 

  • Like 2
Link to comment
Share on other sites

Hi again,

 

I have been getting somewhere with this on VJ. I've just tried on my actual Jag and get weird behaviour.

If anyone could shed some light that would be great.

 

This has one 320x150 sprite in memory and one 320x150 sprite on screen. it is running in 16bit graphics mode and both sprites are 16 bit too.

 

The full program copies 1 whole line at a time from the src image to the screen image, inside a FOR loop.

 

I know the blitter can do whole blocks and iterate for me, but I will need to change coordinates on the fly, so this is why I do 1 line at a time.

 

I have simplified my full listing to show the issue.

 

In VJ, if you run the code below, it (correctly) writes out 2 lines of 320 pixels from the src to the screen sprite.

 

If you run this on the actual Jag, it writes out the whole 150 lines from the src to the screen sprite and then crashes. Why doesn't it just do the 2 lines like in VJ?

 

If I take out one of the "LPOKE B_CMD,LFU_REPLACE|SRCEN" at the end, so there is just 1 then it works correctly in VJ and actual Jag by just writing 1 line of 320 pixels out.

 

So why should having the 2 calls to B_CMD force it to write out the whole sprite and then crash?

 

To me it looks like it gets stuck in a loop, writing out the 150 x 320px lines, gets to the end, hits whatever memory and bombs.

 

If someone wants the whole rb+ project then I can grab that tomorrow and upload.

 

Many thanks.

rlist=(RAPTOR_LIST *)strptr(RAPTOR_sprite_table)
basic_r_indx=0
basic_r_size=0

DIM particles%			:particles=0
DIM roadSrc%			:roadSrc=particles+1
DIM roadCanvas%			:roadCanvas=roadSrc+1

dim gfxroadsrc%
gfxroadsrc=rlist[roadSrc].gfxbase

dim gfxroadcanvas%
gfxroadcanvas=rlist[roadCanvas].gfxbase

dpoke BG,12	

LPOKE A2_FLAGS,PIXEL16|XADDPIX|WID320|PITCH1
LPOKE A2_BASE,gfxroadsrc		
LPOKE A2_PIXEL,0

LPOKE A1_FLAGS,PIXEL16|XADDPIX|WID320|PITCH1
LPOKE A1_BASE,gfxroadcanvas	
LPOKE A1_PIXEL,(0<<16)+0
			
LPOKE B_COUNT,(1<<16)+(320)

LPOKE B_CMD,LFU_REPLACE|SRCEN

LPOKE B_CMD,LFU_REPLACE|SRCEN
Edited by Sporadic
Link to comment
Share on other sites

If your not using the test raptor.o I sent you it'll be raptor using the blitter in the vbi.

 

The new version does a mutex check and drops to using a cpu if the blitter is active.

I think I am using the newer .o file but I will check thanks. Would that possibly not crash on VJ but still crash on real hardware if I did have the right one?

Link to comment
Share on other sites

More info!

 

If I repeat a couple of the other registers then it doesn't crash!. See (cut down) listing below;

 

Looks like, if I specify A1_PIXEL, A2_PIXEL and B_COUNT before the B_CMD each time then it works ok on actual hardware.

 

If I have to do that then so be it but i'd rather not call things every frame that i don't need to. Or is that just how it is?

 

Anyway, bedtime.....

dpoke BG,12	


LPOKE A2_FLAGS,PIXEL16|XADDPIX|WID320|PITCH1
LPOKE A2_BASE,gfxroadsrc		
LPOKE A2_PIXEL,0

LPOKE A1_FLAGS,PIXEL16|XADDPIX|WID320|PITCH1
LPOKE A1_BASE,gfxroadcanvas	
LPOKE A1_PIXEL,(0<<16)+0			
LPOKE B_COUNT,(1<<16)+(320)
LPOKE B_CMD,LFU_REPLACE|SRCEN

		

LPOKE A2_PIXEL,(1<<16)+0
LPOKE A1_PIXEL,(1<<16)+0			
LPOKE B_COUNT,(1<<16)+(320)
LPOKE B_CMD,LFU_REPLACE|SRCEN
  • Like 1
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...