SP1 and complex backgrounds (scr files)

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
jordi
Member
Posts: 57
Joined: Sun Oct 28, 2018 3:35 pm

SP1 and complex backgrounds (scr files)

Post by jordi »

Hi,

I do have some .scr files that it would be great to apply to my code. Is there any easy way to load them as binary and add them so SP1 considers them as the background tiles?

I didn't found a tutorial on how to do it, is it possible?

I thought the function sp1_PutTiles might be the one for that, but unfortunatelly I didn't found any example of using it, and might not.

Thank you!!
jordi
Member
Posts: 57
Joined: Sun Oct 28, 2018 3:35 pm

Post by jordi »

I've seen that manic pietro uses .btiles for nirvana, I don't know about that format but might be related?
jordi
Member
Posts: 57
Joined: Sun Oct 28, 2018 3:35 pm

Post by jordi »

jordi wrote:I've seen that manic pietro uses .btiles for nirvana, I don't know about that format but might be related?
This will work, but then sp1 redrawing ...
memcpy(16384, cartoon0, 6912);
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

Nirvana is an entirely separate game engine that supports multi-colour graphics.

In SP1, the tiles are 16-bit. If you print tiles that are only 8-bit (0-255) then the tile graphics are looked up like usual through the tile array. However, if you print 16-bit values such that the MSB is not 0, then this is taken as an address in memory where the eight bytes of tile graphics are found. So you can have an image in memory as background but the format will be different than a standard screen$. This also uses up a lot of memory, so plan on 128k from the get go :)
jordi
Member
Posts: 57
Joined: Sun Oct 28, 2018 3:35 pm

Post by jordi »

alvin wrote:Nirvana is an entirely separate game engine that supports multi-colour graphics.

In SP1, the tiles are 16-bit. If you print tiles that are only 8-bit (0-255) then the tile graphics are looked up like usual through the tile array. However, if you print 16-bit values such that the MSB is not 0, then this is taken as an address in memory where the eight bytes of tile graphics are found. So you can have an image in memory as background but the format will be different than a standard screen$. This also uses up a lot of memory, so plan on 128k from the get go :)
Thanks, so putTitles do work then?

I am also trying to have the minimal code possible if I create a code from scratch to have a SCREEN$ loaded into BANK2 and then load it with memcpy into memory, kind of

Code: Select all

memcpy(16384, cartoon0, 6912);
I tried using the int.asm you provided a month ago or so, but every code I try I finally end with computer reset and USR0 mode. Is it related to stack position?

Code I tried from scratch is very stupid

Code: Select all

void page2() {
   __asm
      ld a,(23388)        ;fetch current value
      and %11111000        ;clear bits 0?2 (bank #)
      or 2                ;select new bank
      ld bc,32765        ;our port
      di
      ld (23388),a        ;write new value back to sys. var
      out (c),a        ;and to port
      ei
   __endasm;
}

void page0() {
   __asm
      ld a,(23388)        ;fetch current value
      and %11111000        ;clear bits 0?2 (bank #)
      or 0                ;select new bank
      ld bc,32765        ;our port
      di                ;condom on
      ld (23388),a        ;write new value back to sys. var
      out (c),a        ;and to port
      ei                ;condom off
   __endasm;
}


int main()
{
  page2();
  memcpy(16384, cartoon0, 6912);
  page0();
  in_wait_key();

  while(1) {

  }
}
While cartoon0 is the SCREEN$ contents

Code: Select all

SECTION BANK_2_DATA


PUBLIC _cartoon0
_cartoon0:
BINARY "intro.scr"
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

jordi wrote:Thanks, so putTitles do work then?
Yes but I think I would use "sp1_IterateUpdateRect(rect,func)" for this instead. If you pass it a rectangle that covers the full screen, this function will visit all the "struct sp1_update" in the screen in left to right, top to bottom order. Each "struct sp1_update" is one character square. So you could do something like this:

Code: Select all

unsigned char screen[6144];

unsigned char csx, csy;
unsigned char *csdst;

void copy_screen(struct sp1_update *u)
{
   unsigned char *p;

   // locate character square on screen

   p = zx_cxy2saddr(csx, csy);

   // store graphic location and colour in struct update

   u->tile = (unsigned int)csdst;
   u->colour = *zx_saddr2aaddr(p);

   // copy screen graphics to screen buffer

   for (unsigned char i = 0; i != 8; ++i)
   {
      *csdst++ = *p;
      p += 256;
   }

   // next character square

   if (++csx == 32)
   {
      csx = 0;
      ++csy;
   }
}

...

// copy screen from memory bank

...
memcpy(16384,...);

// create screen in buffer from screen$

csx = csy = 0;
csdst = screen;

sp1_IterateUpdateRect(&fs, copy_screen);   // fs = sp1_Rect covering full screen
You need 6144 bytes to store the pixels of the screen$ if your display is full size (here I made an array "screen" but you probably want to control where that is placed).

Instead of storing your screens full size you can compress them. zx7 is included in z88dk so you can simply do "zx7 -f intro.scr" to compress the screen$ before including it as a binary. In your program:

Code: Select all

#include <compress/zx7.h>

dzx7_standard(cartoon0, 16384);  // the original author made this src,dst even though c is normally dst,src
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

If you're paging the top 16k, you definitely have to make sure the code running, the stack and interrupt routines (if ints are enabled) are below 0xc000. By default, z88dk is going to place the stack up there and the suggested sp1 stack location is also up there so you will get a crash if you bank without moving your stack.

You can move the stack for your program with a pragma:

#pragma output REGISTER_SP = 0x8000 // or something out of the way

Another option is you move the stack to a temp location while you bank stuff.

You'll have to sketch out a rough memory map and decide where the stack should go, where your program org is, etc, keeping in mind sp1 wants to take a large chunk of the top of ram.

The paging you are doing updates the system variable BANKM. This is not needed unless you're running with basic interrupts enabled or you plan to return to basic. If not, you don't have to bother updating that system variable.

IO ports are defined in z88dk using special function registers and that port (0x7ffd) should be defined already in zx.h. So you could just write to that port from c like this:

IO_7FFD = x;
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

But I think instead of going that intermediate step of copying to screen$ and then generating the screen buffer from that, I would store the screen buffer in the correct format and just decompress it directly the screen buffer location.
Post Reply