Foreground blocks in SP1 with sp1_cs

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
amateus
Member
Posts: 46
Joined: Fri Nov 15, 2019 9:13 am

Foreground blocks in SP1 with sp1_cs

Post by amateus »

Hi there,

There are 3 ways in wich we can create foreground tiles with SP1:
  • By validating squares before rendering (see example ex5b from z88dk)
    by removing tiles from the render array (see example ex5c from z88dk)
    by using the free sprite characters structure, sp1_cs
While the first two have examples, the last one does not, and it's rather interesting, as it allows to have tiles (or "free sprites") in front, with or without mask, or at the back of the main sprite.

The code is available at https://github.com/antoniocmateus/z88dk ... ound_tiles and is fully commented.

Happy foreground blocks :)

António
Timmy
Well known member
Posts: 392
Joined: Sat Mar 10, 2012 4:18 pm

Re: Foreground blocks in SP1 with sp1_cs

Post by Timmy »

Thanks!

I never knew I could have foreground tiles with masking in it!

That's a cool idea to use the planes for it.
amateus
Member
Posts: 46
Joined: Fri Nov 15, 2019 9:13 am

Re: Foreground blocks in SP1 with sp1_cs

Post by amateus »

Thanks.

This allows us some nice effects on it, for example some sprites waling behind a window and others in front of it, or behind fences.

sp1_cs is a rather interesting little structure, and the ability to change it on the fly allows us some cool effects (z_order anyone? ;) )
fraespre
Member
Posts: 56
Joined: Mon Aug 19, 2019 8:08 pm

Re: Foreground blocks in SP1 with sp1_cs

Post by fraespre »

hi amateus and the rest,
I'm trying to improve your foregrounds example to another one more complex.

Specifically, I'm trying to build a screen with several foreground-tiles (instances) repeated. I mean same graphic in several positions.
And I try to remove them (reset the screen) after. But I have doubts about the best way to do it.

Some changes from the amateus code in github:

main:

Code: Select all

  create_foreground();	// create scene
  clear_foreground();	// delete scene
  create_foreground();	// create scene
  clear_foreground();	// delete scene
	
	while(1) {			// We should watch a black screen with the bubble
        get_movement();
        sp1_MoveSprPix(bubble.s, &full_screen, 0, bubble.x, bubble.y);
        intrinsic_halt();
        sp1_UpdateNow();
    }
create foreground:

Code: Select all

void create_foreground() {
	//I want to create a screen with the same foreground-tile repeated in several positions
	
    sp1_InitCharStruct(&window_object, SP1_DRAW_MASK2NR, SP1_TYPE_2BYTE, &window, 5);   
      bricks_update = sp1_GetUpdateStruct(11, 10);                                        
      sp1_InsertCharStruct(bricks_update, &window_object);

    sp1_InitCharStruct(&window_object, SP1_DRAW_MASK2NR, SP1_TYPE_2BYTE, &window, 5);   
      bricks_update = sp1_GetUpdateStruct(12, 10);                                        
      sp1_InsertCharStruct(bricks_update, &window_object);

    sp1_InitCharStruct(&window_object2, SP1_DRAW_MASK2NR, SP1_TYPE_2BYTE, &window, 5);   
      bricks_update = sp1_GetUpdateStruct(11, 13);                                        
      sp1_InsertCharStruct(bricks_update, &window_object2);

    sp1_InitCharStruct(&window_object2, SP1_DRAW_MASK2NR, SP1_TYPE_2BYTE, &window, 5);   
      bricks_update = sp1_GetUpdateStruct(12, 13);                                        
      sp1_InsertCharStruct(bricks_update, &window_object2);
	
	sp1_Invalidate(&full_screen);
	sp1_UpdateNow();
}
clear foreground:

Code: Select all

void clear_foreground() {
	//After, I want to figure out how I can reset the screen as easily as possible
	//... otherwise sp1 reset the machine
/*	
	// 1.- KO: This is the established call to do it, but when you have several repetitions it only removes the last one
	sp1_RemoveCharStruct(&window_object);  
	sp1_RemoveCharStruct(&window_object2);
*/
/*
	// 2.- KO: I try to repeat the call to figure out if the first instance can be deleted, but not
	sp1_RemoveCharStruct(&window_object);  sp1_RemoveCharStruct(&window_object);  
	sp1_RemoveCharStruct(&window_object2); sp1_RemoveCharStruct(&window_object2); 
*/
/*
	// 3.- OK: Using the API, I reset every used position of the screen => But, I need to note all positions
	bricks_update = sp1_GetUpdateStruct(11, 10); sp1_RemoveUpdateStruct(bricks_update); sp1_RestoreUpdateStruct(bricks_update);
	bricks_update = sp1_GetUpdateStruct(12, 10); sp1_RemoveUpdateStruct(bricks_update); sp1_RestoreUpdateStruct(bricks_update);
	bricks_update = sp1_GetUpdateStruct(11, 13); sp1_RemoveUpdateStruct(bricks_update); sp1_RestoreUpdateStruct(bricks_update);
	bricks_update = sp1_GetUpdateStruct(12, 13); sp1_RemoveUpdateStruct(bricks_update); sp1_RestoreUpdateStruct(bricks_update);
*/
/*
	// 4.- KO: Trying to simplify case 2, I make a loop to reset all the screen positions
        for(uint8_t y=0; y<22; y++) {
	  for(uint8_t x=0; x<32; x++) {
             bricks_update= sp1_GetUpdateStruct(y, x); 
             sp1_RemoveUpdateStruct(bricks_update); 
             sp1_RestoreUpdateStruct(bricks_update);
          }
        }	
*/
	sp1_Invalidate(&full_screen);
	sp1_UpdateNow();
}
In the below link you can find the complete source code of my exercise:
https://ufile.io/0hncx0oi

I'll appreciate any help or idea. Thanks in advance,
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: Foreground blocks in SP1 with sp1_cs

Post by jorgegv »

Hi @fraespre,

I think you cannot do what you want, at least directly. You can't reuse a sp1_cs struct for several positions on screen. The sp1_cs struct is defined like this:

Code: Select all

struct sp1_cs {                       // "char structs" - 24 bytes - Every sprite is broken into pieces fitting into a tile, each of
   struct sp1_cs     *next_in_spr;    // +0  BIG ENDIAN ; next sprite char within same sprite in row major order (MSB = 0 if none)
   struct sp1_update *update;         // +2  BIG ENDIAN ; tile this sprite char currently occupies (MSB = 0 if none)
   uint8_t              plane;          // +4  plane sprite occupies, 0 = closest to viewer
(...)
The "update" field is initialized to the position that tile occupies on-screen, and as it can be seen, it can be only one. I.e. when you use it for the first time, you position it in one place, and when you use it for the second time, you move it (it can't be in 2 positions at the same time).

You will need to create a new sp1_cs struct for each of the tile positions on screen where a tile of this characteristics must exist.

Indeed, the reason for this is that these "masked tiles" are not real background tiles, but more like "non-moving sprites". And them being sprites, they can't be in two places at the same time, even if they are not moving. They have just one position.

Masked background tiles are really interesting. but it should be taken into account that they occupy much more memory than regular background tiles. To aid in memory reuse, they could probably be dynamically assigned during the game as needed, in the same way as sprites are.
fraespre
Member
Posts: 56
Joined: Mon Aug 19, 2019 8:08 pm

Re: Foreground blocks in SP1 with sp1_cs

Post by fraespre »

Thanks Jorge, your answer opened my eyes.

Following on from what you said, I did some tests using only one instance of the foregrounds and yes, all the problems vanished.
I had the thought to use them like "special" tiles (with mask), reusing their cs structs. However, I have already seen they are closer to the sprites (without rotation), but you can't reuse them.

So, as you told me, the conclusion is that the needed amount of memory is much bigger compared with the simple tiles, very especially if you wanted to reuse them.

Thanks again, this fact makes me have to re-think some things about my game jajaja
Post Reply