Karoshi MSX Community
05 de Julio de 2021, 03:39:25 pm *
Bienvenido(a), Visitante. Por favor, ingresa o regístrate.

Ingresar con nombre de usuario, contraseña y duración de la sesión
Noticias:
 
   Inicio   Ayuda Buscar Ingresar Registrarse  
Páginas: [1] 2 3 ... 6
  Imprimir  
Autor Tema: Evitando la "Regla del 5º Sprite" (antes "Snippets")  (Leído 37528 veces)
0 Usuarios y 1 Visitante están viendo este tema.
burguera
Visitante
« : 02 de Octubre de 2006, 09:00:13 pm »

Viendo los snippets que hay en el tema "snippets" (a más de uno le voy a sacar provecho) echo en falta uno en particular. Estaría bien alguno que mostrara como ir alternando los sprites visibles cuando se superan los cuatro en línea (y producir el inevitable parpadeo)
« Última modificación: 19 de Octubre de 2006, 09:40:56 pm por Viejo_archivero » En línea
pitpan
Karoshi Forum's Guru
*******
Mensajes: 1812


« Respuesta #1 : 02 de Octubre de 2006, 09:23:08 pm »

Pues bien sencillo: no copies directamente a VRAM las posiciones de los sprites, sino simplemente a RAM. Reprocesa en RAM con alguna rutina "inteligente" y copia a VRAM entonces.

Lo mejor es sencillamente "darle la vuelta". Es decir, copiar a VRAM en los frames pares 1-2-3-4-5-... y en los frames impares 32-31-30-29-... Por supuesto esta técnica sólo funciona correctamente en ciertas condiciones. Lo más adecuado es comparar las coordenadas verticales y para los coincidentes, alternar sus posiciones relativas en la tabla de atributos de sprites.

Creo que no me he explicado nada bien  Undecided
En línea
ARTRAG
Visitante
« Respuesta #2 : 02 de Octubre de 2006, 09:44:09 pm »

Código:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;   interrupt
;

    org 0038h

SAT equ   0x1b00       ; Sprite Attribute Table   

    global  _vdps0, _curr_plan, _n_sprt, _sprt, _ready

;   RST 38 handler

       
    ex  af,af'
    exx
   
    ld  a,(_ready)          ; no action if not ready
    or  a

    in  a,(0x99)
    ld  (_vdps0),a

    jp  z,_end
   

    bit 06h,a
    jp  z,3f           
               
    and 31
    add a,a
    add a,a
    ld  b,a
    ld  a,(_curr_plan)
    add a,b
    ld  e,a                 ; curr_plan + = (vdps0 & 31)*4;

    ld  a,(_n_sprt)
    ld  c,a

;   In A rest of E / C

    ld   a,e
1:  sub  c
    jp   nc,1b
    add  a,c

    jp  z,3f                       

    ld  (_curr_plan),a      ; curr_plan -= (curr_plan/(n_sprt)) * (n_sprt);
    ld  e,a

    ld  a,SAT & 255
    out (0x99),a
    ld  a,SAT/256 | 64
    out (0x99),a

    ld  hl,_sprt
    ld  d,0
    add hl,de           ; hl = sprt + curr_plan
    ld  c,0x98
    ld  a,(_n_sprt)
    sub e
    ld  b,a             ;  b = n_sprt -curr_plan
    otir
    ld  hl,_sprt        ; hl = sprt
    ld  b,e             ;  b = curr_plan
    otir
    jp    1f
3:
    ld  a,SAT & 255
    out (0x99),a
    ld  a,SAT/256 | 64
    out (0x99),a

    xor a
    ld  (_curr_plan),a

    ld  hl,_sprt
    ld  c,0x98
    ld  a,(_n_sprt)
    ld  b,a
    otir
   
1:
    ld  a,208
    out (0x98),a   
    xor a
    ld  (_ready),a

_end:       
    ex  af,af'
    exx
    ei
    ret

Some explanations:

The vdp status register holds the plane of the 5th sprite, the best method for reordering the
sprite is to plot on plane 0 (the max priority) the sprite whose plane was indicated by the status
register as 5th sprite.

Some variables:
sprt is the 32*4=128 copy of the SAT in RAM,
n_sprt holds the number of valid bytes in sprt,
curr_plan is the VDP sprite plan in sprt that is currently mapped on plane 0 (max priority)

Note: you need to set set "_ready" to 1 at each interrupt, each time you update the SAT.
This part is unessential and could be skipped, the sole reason for having a "_ready" signal is to
avoid that the the routine that writes in the SAT in RAM has not jet completed its update when
the int occurs.
The best way to handle this kind of issues is to have a double SAT in RAM, one for sprite scramble,
one to be updated by the main.
When update is finished you swap the two SAT, but this routine is still under development...



Código:
« Última modificación: 26 de Octubre de 2006, 02:55:03 pm por ARTRAG » En línea
jltursan
Karoshi Forum's Guru
*******
Mensajes: 1516


¿Que es lo que has aprendido hoy?


WWW Email
« Respuesta #3 : 03 de Octubre de 2006, 09:09:23 am »

Thanks for sharing this routine! Smiley. Could be very handy to implement working behind a BASIC program (just an idea).

Only a question, the routine seems a bit C oriented (globals, labels and so...). What's the format of the jump labels?, they are neither standard labels nor offsets... Huh
En línea

Doom dee doom dee doom
ARTRAG
Visitante
« Respuesta #4 : 03 de Octubre de 2006, 02:32:40 pm »

The routine is integrated in my C programs
to move it to plain ASM,
1) ignore global statemets
2) the "_" is a a simple character, substitute it with anything you like
3) the numbers are temporary labels, in jumps "f" means forward, "b" means backward, so "JP 1f" goes to the first temporary label "1:" following that jump
« Última modificación: 03 de Octubre de 2006, 02:43:45 pm por ARTRAG » En línea
jltursan
Karoshi Forum's Guru
*******
Mensajes: 1516


¿Que es lo que has aprendido hoy?


WWW Email
« Respuesta #5 : 03 de Octubre de 2006, 03:00:53 pm »

Citar
the numbers are temporary labels, in jumps "f" means forward, "b" means backward, so "JP 1f" goes to the first temporary label "1:" following that jump

Yep!, that's the info!. Now I see... Smiley.
Btw, I'm experimenting a bit with the demo version of Hitech 7.50 for windows and I agree, it's a very nice compiler!
En línea

Doom dee doom dee doom
nerlaska
Karoshi Excellent Member
******
Mensajes: 1102


Programador


WWW Email
« Respuesta #6 : 03 de Octubre de 2006, 03:56:40 pm »

el SDCC 2.6.0 es mas chuli :-)
En línea

MSX4EVER2GETHER
www.nerlaska.com
ARTRAG
Visitante
« Respuesta #7 : 03 de Octubre de 2006, 04:06:38 pm »

In v7.8 you get all the sources of the libs and of the runtime code... Cheesy
I have found also a way to get megarom on ascii 8K rom mappers   Smiley
The compiler can handle by itself up to 1M Rom of code and data and all you need
is to specify which functions and data should go in the same rom page!!
Actually, the ASCII mapper isn't very far from what the C compiler expected to have
when you compile in large model (all you need is to change a line in the lcall and lret routines).
Grin

I think that it is a great compier, even if to use it I have to move the date
of my PC to 2005  Wink

« Última modificación: 03 de Octubre de 2006, 05:55:00 pm por ARTRAG » En línea
burguera
Visitante
« Respuesta #8 : 03 de Octubre de 2006, 06:02:46 pm »

Gracias por los consejos, Robsy.
And thanks for the code, ARTRAG.

De momento no tengo planes de pasarme al C (ya tengo suficiente "alto nivel" en otros aspectos menos lúdicos de mi vida -lease trabajo-), aunque después de leer estos comentarios del Hitech y los de Nerlaska sobre el SDCC la verdad es que apetece. Todo se andará.
En línea
ARTRAG
Visitante
« Respuesta #9 : 03 de Octubre de 2006, 07:19:10 pm »

Note that my solution is different from Robsy's one.

In my case you are always sure that the 5th sprite will be displayed (well at least one 5th sprite will be dispayed).
In Robsy's solution, this isn't guaranteed, moreover look at this effect

assume you have sprites on planes

1  2 3 4 5

on the same line: the sprite on plane 5 disappears.

reverse them

5 4 3 2 1

now sprite that was on plane 1 disappears.

Repeat this process at refresh rate:
Result: only sprite 1 & sprite 5 flicker at half of the refresh rate (25Hz if you go @50Hz)
Robsy's solution implies a very noticeable effect.

with my proposal sprites on planes

1 2 3 4 5

disappear in turn, at each frame one different sprite disappear

Result: all sprites flicker but the flickering is at 1/5 of the refresh rate (10 Hz if you go @50Hz)
This implies a much better visual effect as the flickering is at very low frequency
« Última modificación: 03 de Octubre de 2006, 07:24:09 pm por ARTRAG » En línea
pitpan
Karoshi Forum's Guru
*******
Mensajes: 1812


« Respuesta #10 : 03 de Octubre de 2006, 09:51:22 pm »

You're right, Artag: flickering in my routine is very common. Of course, my approach is the simplest solution.

On the other side, it handles properly up to 8 sprites in the same line, whereas yours will not work always in that case - the weakest point is that the interrupt routine only returns the 5th sprite number. But what happens if there are more than 5 sprites? Several sprites could be totally hidden.

I have used my approach in my current project, where I have commonly 8 sprites in line. It works pretty well and it does not use much CPU.

The best solution, as always, depends on the concept and design of the game. I agree that your solution is more generalistic and will work better in most situations, but perhaps not in all cases, as I've shown.

It's good to discuss this programming issues here. IMHO, the best sprite-flickering routine is the one used in Golvellius. Ever noticed the amount of sprites at the same time? Amazing.  Shocked
En línea
ARTRAG
Visitante
« Respuesta #11 : 03 de Octubre de 2006, 11:24:38 pm »

Hi robsy,
I see you point, but I am not sure that the case you posed isn't handled by my approach

let's see
assume 8 sprites on 8 adjacent planes

1 2 3 4 5 6 7 8

sprites 5 6 7 8 disappear, S0 returns plane 5, so next int, my routine reorders
the sprites putting sprite 5 and the following on top

you get :
5 6 7 8 1 2 3 4

now sprites 1 2 3 4 disappears
S0 returns plane 5, i.e. sprite #1, next int my routine reorders the sprites
putting sprite 1 and the following on top

you get
1 2 3 4 5 6 7 8

As you can see my approach can safely handle up to 8 sprites per line.

Actually you're right when you say that solution for all seasons doesn't exist,
Also my approach has problems, they occur when there are two lines with 5 or more sprites

Look at this case, 10 sprites on two lines, 1 2 3 4 5 on the first line
6 7 8 9 10 on the second line
the sprite planes are
1 2 3 4 5 6 7 8 9 10
where on the screen you see
1 2 3 4 5
6 7 8 9 10

Sprite 5 and 10 disappear (5 is covered by 1 2 3 4 and 10 by 6 7 8 9)
S0 points to plane 5 (only the first 5th sprite is revealed, but the problem is similar if S0 reveals the last 5h sprite)

my routine does this reordering
5 6 7 8 9 10 1 2 3 4

on the screen now sprite 4 disappears (covered by 1 2 3 5), sprite 5 appears, and sprite 10 stay hidden !!
S0 points to plane 10 (i.e to sprite 4)

my routine does this reordering
4 5 6 7 8 9 10 1 2 3

on the screen now sprite 3 disappears (covered by 1 2 4 5), sprite 4 appears, but sprite 10 stay hidden
S0 points to plane 10 (i.e. to sprite 3)

my routine does this reordering
3 4 5 6 7 8 9 10 1 2
on the screen now sprite 2 disappears (covered by 1 3 4 5), sprite 3 appears, but sprite 10 stay hidden

actually you can go on and see that sprite 10 stay hidden for a large number of frames
only the first line of sprites flickers correctly, the second line is almost unaffected.

In this case your approach is better as it has the advantage to revert all the planes,
so one frame sprites 5 and 10 disappear, on one frame sprites 1 and 6 disappear.
Your solution goes better, but all depends on the game design and on the prob. of having two
or more lines with 5 sprites or more



« Última modificación: 03 de Octubre de 2006, 11:26:21 pm por ARTRAG » En línea
Jon_Cortazar
Administrator
Karoshi Forum's God
********
Mensajes: 2777



WWW Email
« Respuesta #12 : 04 de Octubre de 2006, 08:54:41 am »

In the game Infinty (it will be released soon), I used another way of making a flickering routine:

I had a RAM buffer for sprite atributes. As the max sprite number on screen in the game is 10, the RAM buffer occupies 40 bytes (4 bytes per sprite -atributes-). Well, so what I do at every frame is to create a mirror of those 40 bytes right after the first 40 bytes:

; RAM buffers
SPRITE_ATRIBUTES1: ds 40
SPRITE_ATRIBUTES2: ds 40 ;mirror

This can be done with a simple ldir. Well, once I have that pair of sprite atribute data, all I must do is to 'add' a variable to the source adress when sending to VRAM. In other words, I won't send to VRAM from SPRITE_ATRIBUTES1, but from SPRITE_ATRIBUTES1+[variable]:

So:

flickering_offset=0

.flicker_routine
create the mirror from SPRITE_ATRIBUTES1 into SPRITE_ATRIBUTES2
final_adress=SPRITE_ATRIBUTES1+flickering_offset
send to vram (spratr) from FINAL_ADRESS the amount of 40 bytes
flickering_offset=flickering_offset+4
if flickering_offset=40 then flickering_offset=0
end

It is easy, quite fast and it works for an undefined number of sprites. In Infinity the flickering looks pretty good, I promise. When I arrive home I'll share the routine source. The only downside in this routine is that you must double the RAM usage for your sprite attribute buffer, but if we take in account that the max spratr you'll ever use will be 256 bytes long, the max you'll get will be 512 bytes, and that is pretty affordable thinking on a 16kb RAM system.
« Última modificación: 04 de Octubre de 2006, 09:20:37 am por Viejo_archivero » En línea

Jon Cortázar Abraido (aka El Viejo Archivero)
RELEVO Videogames
[Dioniso: La cafeína está haciendo su trabajo; yo espero hacer el mío.]
[pitpan: Me sigue pareciendo más productivo jugar al SNAIL MAZE que seguir esta discusión.]
ARTRAG
Visitante
« Respuesta #13 : 04 de Octubre de 2006, 09:33:36 am »

if you use as flickering_offset the 5th sprite in S0 you get exactly my strategy,
the difference is that I do not mirror the SAT twice but I send to the VRAM
the SAT in two steps, from flickering_offset to the max used position first,
and, then, the initial part as second.
(I need to handle up to 20-24 sprites on the screen, so copying the SAT can
be CPU expensive)

Using as flickering_offset the 5th sprite in S0 is better when sprites are one line
If sprites are on two or more lines, the second line, in my approach isn't handled correctly
and your "blind" scramble is better
En línea
Jon_Cortazar
Administrator
Karoshi Forum's God
********
Mensajes: 2777



WWW Email
« Respuesta #14 : 04 de Octubre de 2006, 09:49:07 am »

if you use as flickering_offset the 5th sprite in S0 you get exactly my strategy,
the difference is that I do not mirror the SAT twice but I send to the VRAM
the SAT in two steps
Yep, but, as VRAM transfers are always a hell, I prefer to do those the less steps the better. Smiley

Using as flickering_offset the 5th sprite in S0 is better when sprites are one line
If sprites are on two or more lines, the second line, in my approach isn't handled correctly
and your "blind" scramble is better
Agree on that... your strategy with the colision detection is pretty nice, but as I cycle the sprites on a regular sequence, mine is better for generic purposes.
En línea

Jon Cortázar Abraido (aka El Viejo Archivero)
RELEVO Videogames
[Dioniso: La cafeína está haciendo su trabajo; yo espero hacer el mío.]
[pitpan: Me sigue pareciendo más productivo jugar al SNAIL MAZE que seguir esta discusión.]
Páginas: [1] 2 3 ... 6
  Imprimir  
 
Ir a:  

Impulsado por MySQL Impulsado por PHP Powered by SMF 1.1.21 | SMF © 2013, Simple Machines XHTML 1.0 válido! CSS válido!