MSX Village forum

La Place des Développeurs Première Mondiale : La première Rom avec Fusion-C !

ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5566

Le 07/12/2020 à 13h53
Ca avance bien ... Ca avance bien...

Je suis très content de présenter la Première ROM 32K réalisée avec Fusion-C 1.3

C'est un petit jeu de Demo, qui tourne sur MSX2
Vous incarner PacMan, vous devez attraper le fantôme pour marquer des points dans le temps imparti.
Mais le fantôme se sauve, ou lache sur vous d'autre fantôme qui vous paralyse.

Voici la ROM
GCHASEc.ROM

Vous pouvez tester...

(Ca ne se joue qu'avec les touches fléchées du clavier)


banniere-ericb59e
Site web    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5566

Le 07/12/2020 à 14h00

Voici le Listing

GCHASEc.txt

Vous remarquez les directive #define en début de listing

Code C :
 
#define __SDK_ADDRCODE__ 0x4050
#define __SDK_ADDRDATA__ 0xC000
#define __SDK_MSXVERSION__ 2
#define __SDK_CRT0__ crt0_MSX32k_ROM4000.rel
#define __SDK_EXT__ ROM 
#define __SDK_ROMSIZE__ 8000  
 


Elles indique à mon script de compilation les paramètres pour créer la ROM.
A la fin du processus de compilation, openMSX un MSX2 avec et la Rom chargée pour la tester.

Changez les directives par celles là :

Code C :
 
#define __SDK_ADDRCODE__ 0x106
#define __SDK_ADDRDATA__ 0x0
#define __SDK_MSXVERSION__ 2
#define __SDK_EXT__ COM
#define __SDK_AUTOEXEC__ 1
#define __SDK_MSXDOS__ 1
 


et la compilation se fera en version MSX-DOS.
A la fin du processus de compilation, openMSX démarrera un MSX2, avec MSX-Dos et lancera le programme .com automatiquement


banniere-ericb59e
Site web    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5566

Le 07/12/2020 à 14h01
ericb59 :

Voici le Listing

GCHASEc.txt

Vous remarquez les directive #define en début de listing

Code C :
 
#define __SDK_ADDRCODE__ 0x4050
#define __SDK_ADDRDATA__ 0xC000
#define __SDK_MSXVERSION__ 2
#define __SDK_CRT0__ crt0_MSX32k_ROM4000.rel
#define __SDK_EXT__ ROM 
#define __SDK_ROMSIZE__ 8000  
 


Elles indiquent à mon script de compilation les paramètres pour créer la ROM.
A la fin du processus de compilation, openMSX un MSX2 avec et la Rom chargée pour la tester.

Changez les directives par celles là :

Code C :
 
#define __SDK_ADDRCODE__ 0x106
#define __SDK_ADDRDATA__ 0x0
#define __SDK_MSXVERSION__ 2
#define __SDK_EXT__ COM
#define __SDK_AUTOEXEC__ 1
#define __SDK_MSXDOS__ 1
 


et la compilation se fera en version MSX-DOS.
A la fin du processus de compilation, openMSX démarrera un MSX2, avec MSX-Dos et lancera le programme .com automatiquement


banniere-ericb59e
Site web    
Bastion Rebel Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 21/09/2013 à 07h42

Messages: 1887

Le 07/12/2020 à 17h11
salut simpa a quand la maj fusion c ??


TURBO-R FS-A1ST 512/128ko MSX2+ NMS 8250 F4 /Fix Audio /Ram 1/4Mb VDP9958 VRAM 192ko 2FDD SANYO WAVY PHC35J MSX2 NMS 8280 Ram 4Mb VDP9938 VRAM 192ko 2FDD NMS 8250 128/128ko 2FDD VG8235/39 128/128ko 1FDD SONY HB-F700D MSX1 MC810 32/16k VG 8020 64k HB75F 64k HX-22 64k RS232/ CX5M 32k HB501F EXT : My Exp 4X/[b] MegaFlashSCC 512ko/BERT R2/BEER CF/SUNRISE 2CF/FUNRICE V2.01/MAXIOL/MEGASCSI HDD-CD/SDMSX 1SD/FMPAC SRAM/NMS1205+1160/RS 232 Harukaze/GR8NET/DOS2/ HOMER V2 RAM512ko/Floppy Pack/MAXduino/ROM1664/FM Pak /GR8NET /AMIGA/ PC/ RaspB Pi(B) / ARDUINO
E-mail    
Jipe Membre non connecté

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 02/10/2009 à 19h41

Messages: 10730

Le 07/12/2020 à 18h28
petite question : pourquoi un programme en C génére t'il autant d'appels aux registres indexés IX et IY ?


:noel
Site web    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5566

Le 07/12/2020 à 18h54
IX est utilisé par Le compilateur SDCC pour ses propres besoins.
Quand on passe des paramètres du C vers une routine ASM, ils se retrouvent dans le stack. Pour les récupérer du côté ASM il faut donc commencer par sauvegarder IX, avant de l’utiliser pour la récupération des donnees, puis à fin de la procédure, récupérer la valeur de IX qui était là avant d’entrer dans la routine ASM.
Sinon ça plante !

Example avec cette routine RAM pour msx2

Code ASM :
 
 
;
; HMMC (void *pixeldatas, int DX, int DY, int NX, int NY, char OP )
; 
; 
;**************************************************************************************
 
        push ix 
        ld ix,#0
        add ix,sp
 
        ld  l,4(ix)   ; Load *buffer PixelData address
        ld  h,5(ix)  
        ld  d,14(ix)
        di 
 
        call  _VDPready
 
        ld     a,#36
        out    (#0x99),a
        ld     a,#128+#17
        out    (#0x99),a    ;R#17 := 32
 
        ld     c,#0x9b
        ld     a,6(ix)  ;
        out    (c),a    ; R36 XS low byte
        ld     a,7(ix)  ;
        out    (c),a    ; R37 XS high byte
        ld     a,8(ix)  ;
        out    (c),a    ; R38 YS low byte
        ld     a,9(ix)  ;
        out    (c),a    ; R39 YS high byte
        ld  a,10(ix)    ;
        out    (c),a    ; R40 DX low byte
        ld  a,11(ix)    ;
        out    (c),a    ; R41 DX high byte
        ld  a,12(ix)    ;
        out    (c),a    ; R42 DY low byte
        ld  a,13(ix)    ;
        out    (c),a    ; R43 DY high byte     
 
 
        ld a,(hl)       ; First Color data to register 44
        out    (c),a    ; R44 
        xor a
        out    (c),a    ; R45 Parameters  DIX=DIY=0 
        ld  a,#0b11110000
        out (c),a       ; R46 command to do it
 
        ld  a,#128+#44
        out (#0x99),a
        ld  a,#128+#17
        out (#0x99),a       ; VDP(17)<=44
   loopHMMC:
         ld  a,#2
         out (#0x99),a
         ld  a,#0x8f
         out (#0x99),a
         in  a,(#0x99)
 
         and #1
         jp z, exitHMMC       ; if CE = 1 Exit
         and #128
         jp nz, loopHMMC      ; if TR = 0 Loop
         inc hl 
         ld a,(hl)
         out  (#0x9b),a
         jp loopHMMC
 
  exitHMMC:
        xor a
 
        out (#0x99),a
        ld  a,#0x8f
        out (#0x99),a
        in  a,(#0x99)
 
        ei
        pop ix
        ret
 
 


banniere-ericb59e
Site web    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5566

Le 07/12/2020 à 19h45
Si tu veux voir ce que le compilateur SDCC à pondu en ASM... voici le fichier ...
J'imagine que ca n'ai pas très optimisé !
Tu peux comparer dans ce fichier, ce qui est demandé en C, et sa traduction en Assembleur.

Ici en gros le compilateur à traité toute la partie logique du jeu, car les fonctions graphiques, ou les player PT3 et FX, par exemple, sont elles codées en Assembleur par moi ou d'autres. Et elles sont donc inclues tel quel dans le code final, à l'étape suivante.

GCHASEc-asm.txt Edité par ericb59 Le 07/12/2020 à 19h49


banniere-ericb59e
Site web    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2904

Le 08/12/2020 à 00h29
Passer par la pile est la façon standard de transmettre des paramètres à une fonction C.
Par contre, je comprends pas pourquoi SDCC s'obstine à passer par le registre IX pour récupérer ces paramètres alors qu'il est beaucoup plus lent qu'un simple pop.
D'après la doc du Z80, pour récupérer un registre 16-bits par ex., un pop de 10-cycles suffit alors qu'il faut deux ld r,(ix+X) de 19-cycles chacun.
Par contre, pour les fonctions qui sont écrites en assembleur comme l'exemple d'Eric, rien nous oblige à faire comme SDCC et à utiliser IX. ^^
Si on ne manipule pas la pile dans la fonction c'est bien plus rapide d'utiliser des pop (même s'il faut pas oublier de remettre l'adresse de retour).
Y a même mieux : SDCC offre une directive qui permet de flagger les fonctions pour demander au compilo de passer ses paramètres directement dans les registres.
Y a quelques restrictions, mais c'est le top en terme de rapidité.


On est toujours ignorant avant de savoir.
Github    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2904

Le 08/12/2020 à 00h55
D'ailleurs, après réflexion, c'est encore plus simple/efficace de récupérer les paramètres de la fonction via des ld r, (hl) qui utilise que 7-cycles (idem pour bc ou de). Ca monopolise un registre 16-bits mais y a pas mal de cas ou ça doit être plus performant.


On est toujours ignorant avant de savoir.
Github    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5566

Le 08/12/2020 à 05h50
Oui il y a d'autres méthodes.
J'utilise aussi la méthode "__z88dk_fastcall" qui permet d'envoyer un paramètre dans HL directement.


banniere-ericb59e
Site web    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2904

Le 08/12/2020 à 09h32
J'sais pas si tu as vu, mais tu peux même utiliser HL et DE !
- 8-bits : H
- 16-bits : HL
- 32-bits : DE+HL
Le seul truc dommage c'est que de base, __z88dk_fastcall ne supporte qu'un seul paramètre.
Mais on peut contourner le problème avec des macros, en concaténant les paramètres tant que le total est inférieur à 32-bits.


On est toujours ignorant avant de savoir.
Github    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5566

Le 09/12/2020 à 06h44
oui je sais.

la méthode que j'utilise surtout c'est de lui passer une structure.


banniere-ericb59e
Site web    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2904

Le 09/12/2020 à 09h51
Si tu passes par un pointer, tu ne vas profiter que de l'usage de HL (pas de DE).


On est toujours ignorant avant de savoir.
Github    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5566

Le 09/12/2020 à 10h38
aoineko :
Si tu passes par un pointer, tu ne vas profiter que de l'usage de [font= courier new]HL[/font] (pas de [font= courier new]DE[/font]).


Oui mais c’est simple, à comprendre et à coder. :top

Routine fPutSprite
La façon la plus rapide que j’ai trouvé pour gérer l’affichage des sprites.

Code ASM :
 
 
|    fPutSprite
|
*/
 
#define FUSION 2019
#include "../../header/msx_fusion.h"
#include "../../header/vdp_sprites.h"
 
void     fPutSprite(void *parameters)   __z88dk_fastcall     __naked
{
    parameters;
 
__asm
 
;----------------------------
;   MODULE    Fast PUTSPRITE
;
;    fPutSprite ( void *parameters );
;    Eric Boez 2020
 
 
    ld  a,(HL)     ; sprite_no
    ex de,HL     ; Save HL
    rlca
    rlca
    ld hl,(ATRBAS); add HL to A
 
    add a,l     ; Address calculation
    ld l,a
    adc a,h 
    sub l 
    ld h,a 
    di 
    call _SetVDPwrite 
    di
    ld  c,#0x98 
    ex de,hl     ; Retrieve HL
    inc hl
 
      outi
      outi
      outi
      outi
      ei
    ret
 
__endasm;
}
 
 



Structure qui gère un sprite :

Code C :
 
 
typedef struct {
    char spr;        // Sprite ID
    char y;          // X destination of the Sprite 
    char x;          // Y destination of the sprite
    char pat;        // Pattern number to use 
    char col;        // Color to use (Not usable with MS2's sprites)
} FastSPRITE;
 
 
 


Du côté du programme C
Une fois la routine fPutSprite dans la boucle du programme,
Il suffit de ne s’occuper que de la variable qui change pour afficher le sprite où il faut.

Par exemple :
sprite1.x=120;


banniere-ericb59e
Site web    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2904

Le 10/12/2020 à 00h40
Yep, dans ce cas, le mieux est d'avoir des structures en mémoire qui correspondent à celle en VRAM et d'envoyer les données par paquet par HMMC (ou via l'écriture séquentielle).

C'est du détail, mais pour tes 4 outi finaux, tu devrais faire le di juste avant le premier, et le ei juste avant le dernier pour limiter le temps ou tu désactives les interruptions. Depuis que je fais mumuse avec le HBlank, je me rends compte de l'importance de limiter au maximum les temps de désactivations des interruptions (mais ça vaut aussi pour la musique par ex.).


On est toujours ignorant avant de savoir.
Github    
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie