Logicielsmoto.com

Nous sommes le 26 Mai 2022, 12:34

Heures au format UTC + 1 heure




Poster un nouveau sujet Répondre au sujet  [ 399 messages ]  Aller à la page Précédente  1 ... 18, 19, 20, 21, 22, 23, 24 ... 27  Suivante
Auteur Message
MessagePosté: 17 Déc 2021, 00:22 
Hors ligne

Inscription: 06 Avr 2010, 01:59
Messages: 447
oups pardon :D

_________________
Image


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 17 Déc 2021, 08:59 
Hors ligne

Inscription: 24 Juil 2010, 16:08
Messages: 438
Localisation: France
Il y a aussi une version Amstrad GX4000 (pareil, avec des sprites, du scrolling, tout ça, c'est plus facile)

[video=]https://www.youtube.com/watch?v=WStLxy-Zacg[/video]

Cela dit il n'y a pas les niveaux bonus en 3D, il me semble.


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 17 Déc 2021, 22:09 
Hors ligne

Inscription: 21 Avr 2019, 21:48
Messages: 290
Localisation: Var
Oui tu as raison pour le special stage scroll hardware n'aide en rien.
Il faudrait que je le termine d'ailleurs, car j'avance sur le moteur de jeu mais ce projet de Sonic est un peu au ralenti en ce moment.
Une version mini game avec juste ce special stage suffirait.

En réalisant les tutos du moteur de jeu (répertoire doc dans le github), je me suis amusé a maquetter un mini game Sonic :
(Bon il faudrait ajouter une cascade pour justifier du courant :lol: et ajouter quelques pyranhas ...

Fichier(s) joint(s):
sonic_surf2.gif
sonic_surf2.gif [ 139.2 Kio | Vu 1056 fois ]

(capture gif animé de dcmoto, photoshop a fait des siennes avec les couleurs, mais vous avez l'idée)


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 17 Déc 2021, 22:15 
Hors ligne

Inscription: 21 Avr 2019, 21:48
Messages: 290
Localisation: Var
Le scroll en parallaxe est généré à partir de cette image, à l'aide d'un générateur maison qui créé une séquence en boucle parfaite :

Fichier(s) joint(s):
water-scroll.png
water-scroll.png [ 1.48 Kio | Vu 1056 fois ]


Je n'ai pas documenté l'outil encore mais en cherchant dans le java vous le trouverez (fr.bento8.to8.image.lineScroll)

Un autre pour le fun :

Fichier(s) joint(s):
ice-scroll.gif
ice-scroll.gif [ 13.31 Kio | Vu 1056 fois ]


source :

Fichier(s) joint(s):
ice-scroll.png
ice-scroll.png [ 1.43 Kio | Vu 1056 fois ]


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 20 Déc 2021, 15:13 
Hors ligne

Inscription: 06 Juin 2004, 08:23
Messages: 472
Ca dechire l'animation de ce mini-game Sonic :love:


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 22 Déc 2021, 10:30 
Hors ligne

Inscription: 06 Juin 2004, 08:23
Messages: 462
Je ne comprends pas comment ça fonctionne 1. pour passer de l'image fixe au scroll différentielle et 2. quelle technique tu utilises pour générer et transférer ça en vidéo côté Thomson. :eek:

Et ça m'embête beaucoup. :L

Tu nous donnes quelques éléments ? Ca m'intéresse énormément. :bien:


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 22 Déc 2021, 11:50 
Hors ligne

Inscription: 21 Avr 2019, 21:48
Messages: 290
Localisation: Var
Voici qq éléments (dernier jour de taf avant le départ en vacances donc c le rush) ...

Description du programme java :
paramètres en entrée
- image source (320x200)
Fichier(s) joint(s):
water-scroll.png
water-scroll.png [ 1.48 Kio | Vu 1009 fois ]

- nombre d'images de l'animation (ici 16)
- image de masque d'avant plan
Fichier(s) joint(s):
mask.png
mask.png [ 1.72 Kio | Vu 1009 fois ]


Algo
On produit n images, pour chaque image :
On traite chaque ligne en décalant les pixels proportionnellement à la longueur de "pixels utiles" de la ligne (de manière a faire boucler la ligne sur n images)

Par conséquent on a bien une boucle parfaite pour chaque ligne, les plus petites bouclent moins vite que les plus grandes.
L'algo analyse les longueurs de lignes dans l'image il n'y a pas besoin de faire de paramétrage.

L'algo complète chaque ligne en répétant le motif de la ligne afin de remplir toute l'image.
L'image en entrée est en 320x200, mais l'image produite est bien réduite en 160x200

Résultat (1 image parmi les 16):
Fichier(s) joint(s):
water-scroll_000.png
water-scroll_000.png [ 1.61 Kio | Vu 1009 fois ]


Code source : https://github.com/wide-dot/thomson-to8-game-engine/blob/main/java-generator/src/main/java/fr/bento8/to8/image/lineScroll.java

Coté TO8 rien de nouveau, on encode l'animation avec le même principe que celui utilisé pour le fond animé du special stage de sonic :
On fait un diff entre chaque image et la précédente, ainsi le sprite compilé ne dessine que l'écart entre deux images.

Quelques trucs sympa :
- Le nombre d'images produites est réduit car la boucle ne se fait pas sur la largeur complète de l'écran (le plus gros motif en bas de l'image ne fait que la moitié de l'écran)
- Imaginons que plusieurs lignes consécutives aient la même largeur : on aurait un scroll uniforme sur ces lignes (pas de parallax, ex un muret ...)
- On peut faire un effet "tunnel" sympa avec une forme en )( ... faudrait essayer avec une image source générée en 3d


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 22 Déc 2021, 11:55 
Hors ligne

Inscription: 21 Avr 2019, 21:48
Messages: 290
Localisation: Var
On ne dessine donc que ça pour passer d'une image a une autre :

Fichier(s) joint(s):
water-scroll_000.png_water-scroll_014_diff.png
water-scroll_000.png_water-scroll_014_diff.png [ 1.25 Kio | Vu 1009 fois ]


Du coup c'est mega rapide ... 3308 cycles par image

Tout dépend du nombre de couleurs des pixels, de la présence d'aplats de couleurs ...


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 21 Jan 2022, 09:08 
Hors ligne

Inscription: 21 Avr 2019, 21:48
Messages: 290
Localisation: Var
Après réception de la carte midi envoyée par Fool, j'ai finalisé la démo que voici :
phpBB [video]


J'ai filmé avec mon iPhone, donc le son n'est pas branché en direct, mais ça donne une bonne idée quand même.

La carte midi est connectée à un Roland MT32 et la démo tourne sur un TO8D depuis une megarom T.2.
Il existe aussi une version .fd/.sd de cette démo (pas besoin d'extension mémoire).

Le fichier midi prend 46Ko pour plus de 4 minutes de musique (sans boucle).

Il y a eu qq ajustements dans le driver que je vais vous expliquer.


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 21 Jan 2022, 09:41 
Hors ligne

Inscription: 21 Avr 2019, 21:48
Messages: 290
Localisation: Var
D'abord le convertisseur midi ...
Fichier(s) joint(s):
MidiConverter.zip [2.57 Kio]
Téléchargé 35 fois


Souvenez vous, le but du convertisseur est de transformer le format du fichier midi classique qui est constitué d'un "delta-time" et d'un évènement associé.
Le delta-time indique le temps entre chaque évenement, un évènement étant une suite de messages midi.

Le format de sortie est un peu différent, on va remplacer le delta-time par un nb de frame (1/50s) a attendre entre chaque évenement.
La nouveauté c'est qu'on compte combien d'octets sont envoyés lors d'un évenement et on va diviser ça par 64 (nombre d'octets qu'on peut envoyer dans une frame).
Ainsi si on a un sysex qui fait 150 octets, suivi d'un autre évenement avec un delta-time de 10 frames, alors :
150 = 2*64 + 22
il faudra donc 2 frames supplémentaires par rapport à celle du début de lecture pour pouvoir envoyer ces octets, donc le delta-time avec l'évènement suivant est ajusté à 10-2 = 8


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 21 Jan 2022, 09:49 
Hors ligne

Inscription: 21 Avr 2019, 21:48
Messages: 290
Localisation: Var
Coté assembleur, la lecture se fait ainsi :

Code:
        jsr   ResetMidi
        jsr   IrqSet50Hz
        ldx   #Smid_intro
        jsr   PlayMusic


Avec du coté de la routine IRQ 50Hz :

Code:
irq_routine       equ $6027
irq_timer_ctrl    equ $E7C5
irq_timer         equ $E7C6
irq_one_frame     equ 312*64-1         ; one frame timer (lines*cycles_per_lines-1), timer launch at -1
       
IrqSet50Hz
        ldb   #$42
        stb   irq_timer_ctrl           ; timer precision x8
        ldd   #IrqSmidi
        std   irq_routine
        ldx   #irq_one_frame           ; on every frame
        stx   irq_timer
        jsr   IrqOn   
        rts
       
IrqOn         
        lda   $6019                           
        ora   #$20
        sta   $6019                    ; STATUS register
        andcc #$EF                     ; tell 6809 to activate irq
        rts
       
IrqOff
        lda   $6019                           
        anda  #$DF
        sta   $6019                    ; STATUS register
        orcc  #$10                     ; tell 6809 to deactivate irq
        rts
       
IrqSmidi
        _GetCartPageA
        sta   IrqSmidi_end+1           ; backup data page
       
        ldd   Vint_runcount
        addd  #1
        std   Vint_runcount
       
        sts   @a+2                     ; backup system stack
        lds   #IRQSysStack             ; set tmp system stack for IRQ
        jsr   MusicFrame
@a      lds   #0                       ; (dynamic) restore system stack   
       
IrqSmidi_end       
        lda   #$00                     ; (dynamic)
        _SetCartPageA                  ; restore data page
        jmp   $E830                    ; return to caller
       
; This space allow the use of system stack inside IRQ calls
; otherwise the writes in sys stack will erase data when S is in use
; (outside of IRQ) for another task than sys stack, ex: stack blast copy
        fill  0,32
IRQSysStack


et du coté player Midi :

Code:
* ---------------------------------------------------------------------------
* SMIDI 6809 - Small Midi playback system for 6809 and EF5860
* ---------------------------------------------------------------------------
* by Bentoc October 2021
* with inputs from Fool-DupleX
* ---------------------------------------------------------------------------

    opt   c,ct

MIDI.CTRL       equ    $E7F2
MIDI.TX         equ    $E7F3
MIDI.TXIRQON    equ    %00110101 ; 8bits, no parity check, stop 1, tx interrupt
MIDI.TXIRQOFF   equ    %00010101 ; 8bits, no parity check, stop 1, no interrupt

FIRQ.ROUTINE    equ    $6023

MusicLoop       fcb   0                ; 0 : do not loop music
MusicIndex      fdb   0                ; first index of all data chuncks (page, address)
MusicIndexPos   fdb   0                ; position in index
MusicPage       fcb   0                ; current memory page of music data
MusicDataPos    fdb   0                ; current playing position in Music Data
MusicStatus     fcb   0                ; 0 : stop playing, 1-255 : play music
WaitFrame       fcb   0                ; number of frames to wait before next play
NbByteInFrame   fcb   0                ; number of bytes already written in current frame

******************************************************************************
* ResetMidi - Reset Midi Controller
*
******************************************************************************

ResetMidi
        pshs  a
        lda   #$03
        sta   MIDI.CTRL                ; reset midi controller
        lda   #MIDI.TXIRQOFF
        sta   MIDI.CTRL
        puls  a,pc

******************************************************************************
* PlayMusic - Load a new music and init midi interface
*
* receives in X the address of the song
* destroys X
******************************************************************************

PlayMusicLoop
        pshs  d
        lda   #$ff
        sta   MusicLoop                ; set the loop flag on
        bra   @a
PlayMusic
        pshs  d
@a      stx   MusicIndex               ; store index for loop restart
        stx   MusicIndexPos            ; init data chunck index position
        lda   sound_page,x             ; get memory page that contains track data
        sta   MusicPage
        sta   MusicStatus              ; no data on page 0, page is used to init status to a non zero value
        ldd   #1
        stb   WaitFrame                ; wait frame is only zero where reading commands, should be init to 1
        ldx   sound_start_addr,x       ; get ptr to track data
        stx   MusicDataPos             ; init data location
        sta   CircularBufferEnd+1      ; init buffer index to 0
        sta   CircularBufferPos+2      ; init buffer index to 0
        ldd   #SampleFIRQ              ; set the FIRQ routine that will be called when the EF5860 tx buffer is empty
        std   FIRQ.ROUTINE
        andcc #$BF                     ; activate FIRQ
        puls  d,pc

******************************************************************************
* MusicFrame - processes a music frame (IRQ - DP $E7)
*
* format:
* -------
* xnn
*   |____ x00               : (1 byte) next page/adr or end of data
*   |____ x01-x7f           : (1 byte) wait xnn frames
*   |____ x80-xff xnn (xnn) : (2 or 3 bytes) command, data1, (data2)
*   |____ xf0 xnn ... xf7   : (x bytes) SysEx
*
* destroys A,B,X,Y
******************************************************************************
_enableFIRQ MACRO
        lda   #MIDI.TXIRQON
        sta   MIDI.CTRL
 ENDM

_writeBuffer MACRO
        sta   b,y                      ; write byte to the buffer
        incb
        addb  #$80
        stb   CircularBufferEnd+1
        addb  #$80
        ; Place here _enableFIRQ for better accuracy but worse performance
        dec   NbByteInFrame
        bne   @a
        ldu   #@b
        lda   #1
        bra   DoWait
@a      lda   ,x+
@b      equ   *
 ENDM

MusicFrame
        lda   MusicStatus              ; check if a music track is to play
        bne   @a
        rts   
@a      dec   WaitFrame
        beq   ReadCommand              ; no more frame to wait, play the next commands
        rts

IsMusicLoop
        lda   MusicLoop
        beq   StopMusic
        ldx   MusicIndex
        lda   ,x
        bra   LoopRestart
   
StopMusic
        sta   MusicStatus
        sta   MusicLoop
        rts

BankSwitch       
        ldx   MusicIndexPos            ; read byte was $00, this is end of data chunk or music track
        leax  sound_meta_size,x        ; move to next index
        lda   sound_page,x             ; get memory page that contains track data
        beq   IsMusicLoop              ; this is an end of track
LoopRestart
        sta   MusicPage                ; store the new page
        stx   MusicIndexPos            ; this is an end of data chunck, save new index
        ldx   sound_start_addr,x       ; get ptr to track data
        bra   @a
        ;
ReadCommand
        lda   #64
        sta   NbByteInFrame
        ldb   CircularBufferEnd+1      ; load next free position in circular buffer
        addb  #$80                     ; adjust offset because write is made with 8 bit offset (-128,+127)
        ldy   #CircularBuffer+128      ; and reading buffer is made by direct address (lda   CircularBuffer)
        ldx   MusicDataPos             ; load current position in music track
        lda   MusicPage
@a      _SetCartPageA
        lda   ,x+                      ; read data byte in new page
NextFrameJump
        jmp   CommandLoop              ; (dynamic) at exit, continue location is stored here

CommandReLoop
        _writeBuffer
CommandLoop
        bmi   DoCommand
        beq   BankSwitch
        ldu   #CommandLoop             ; normal exit
DoWait
        stu   NextFrameJump+1          ; (dynamic) set routine to call next frame
        sta   WaitFrame
        stx   MusicDataPos
        _enableFIRQ
        rts

DoCommand
        cmpa  #$C0
        blo   TXRdy3b                  ; branch (command 8n to Bn, 2 data bytes)
        cmpa  #$E0               
        blo   TXRdy2b                  ; branch (command Cn and Dn, 1 data byte)
        cmpa  #$f0
        beq   DoSysEx                  ; branch (sysex)
                                       ; default (command En, 2 data byte)
TXRdy3b                             
        _writeBuffer

TXRdy2b
        _writeBuffer
        bra   CommandReLoop

DoSysEx
        _writeBuffer
        cmpa  #$f7
        bne   DoSysEx
        lbra   CommandReLoop

******************************************************************************
* SampleFIRQ - send a sample to the midi interface (FIRQ)
*
******************************************************************************

SampleFIRQ
        sta   @a+1                     ; backup register A
        lda   CircularBufferPos+2      ; read current offset in buffer
CircularBufferEnd
        cmpa  #0                       ; (dynamic) end offset in buffer (set by IRQ routine when buffer is written)
        beq   DisableFIRQ              ; branch if no more data to read (todo shutdown midi interface interupt until next buffer write ?)
CircularBufferPos       
        lda   CircularBuffer           ; (dynamic) read the buffer at the current index
        sta   MIDI.TX                  ; send byte to the midi interface           
        inc   CircularBufferPos+2      ; increment the offset in buffer
@a      lda   #0                       ; (dynamic) restore register A
        rti
DisableFIRQ
        lda   #MIDI.TXIRQOFF
        sta   MIDI.CTRL
        bra   @a

        align 256
CircularBuffer
        fill  0,256


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 21 Jan 2022, 10:01 
Hors ligne

Inscription: 21 Avr 2019, 21:48
Messages: 290
Localisation: Var
Vous noterez qu'il a fallut ajouter un système qui permette d'interrompre la lecture des messages midi lorsque la limite de 64 octets est atteinte lors d'une frame.
En coupant le message en plein milieu, il faut sauvegarder la position dans l'algo de lecture, ce qu'on fait en mettant à jour l'adresse directement dans le jmp (NextFrameJump).

Si on ne fait pas ça on va saturer le buffer cyclique et la FIRQ n'aura pas le temps de lire et envoyer les données que l'IRQ aura déjà remplacé les données par d'autres.
Ce cas se produit surtout quand il y a une masse importante de données (en général des sysex), ce qui est le cas sur la démo (ça permet de redéfinir les paramètres des instruments).

Autre point que j'ai du ajuster ... on écrivait dans le buffer avec un offset 8 bits (b,y), mais on lisait avec une adresse directe (auto modifiée)
problème ... l'offset est signé, d'où les addb #$80 qu'il a fallu ajouter.

Bon, au final tout ça marche fort bien. Il y a certainement encore une marge de progression dans l'optim et dans la précision de lecture, mais de mon point de vu c'est largement suffisant pour le moment.

A suivre pour d'autres tests !
et encore merci à Fool pour cette carte, maintenant supportée par le moteur de jeu.


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 21 Jan 2022, 10:26 
Hors ligne

Inscription: 21 Aoû 2006, 09:06
Messages: 1602
Localisation: Brest
Quelques remarques a 2balles:
* Tu peux avantageusement remplacer la suite jsr + rts par JMP. C'est plus court et plus rapide
* LDD var,addd #1,std var est relativement coûteux. Je lui préfère
Code:
inc var+1
Bne Fin
Inc var
Fin:
car 255 fois sur 256 on fait inc +bne ce qui est plus rapide.
* Enfin inc+addb#128 c'est addb#129 direct.
* Sinon tu n'as pas essayé de voir si abx pouvait aider avec les offsets non signés ?

_________________
Good morning, that's a nice Tnetennba


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 21 Jan 2022, 13:33 
Hors ligne

Inscription: 06 Juin 2004, 08:23
Messages: 462
Ouais, ben p'tet que tout le monde est blasé ici, mais moi je suis émerveillé par le résultat. Je n'aurais pas osé imaginer ça sur mon Thomson à l'époque. :love:


Haut
 Profil  
Répondre en citant le message  
MessagePosté: 21 Jan 2022, 14:51 
Hors ligne

Inscription: 21 Aoû 2006, 09:06
Messages: 1602
Localisation: Brest
Je ne crois pas que quiconque soit blasé. Il n'y a peut être pas assez de publicité sur les autres forum et donc pas assez de passage ici. Pour ma part n'ayant pas d'ordi en ce moment, je ne peux pas jouer avec ces avancées :( (et le Natel c'est pas pratique pour taper du code)

_________________
Good morning, that's a nice Tnetennba


Haut
 Profil  
Répondre en citant le message  
Afficher les messages postés depuis:  Trier par  
Poster un nouveau sujet Répondre au sujet  [ 399 messages ]  Aller à la page Précédente  1 ... 18, 19, 20, 21, 22, 23, 24 ... 27  Suivante

Heures au format UTC + 1 heure


Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 4 invités


Vous ne pouvez pas poster de nouveaux sujets
Vous ne pouvez pas répondre aux sujets
Vous ne pouvez pas éditer vos messages
Vous ne pouvez pas supprimer vos messages
Vous ne pouvez pas joindre des fichiers

Rechercher:
Aller à:  
cron
Développé par phpBB® Forum Software © phpBB Group
Traduction par phpBB-fr.com