MSX Village forum

La Place des Développeurs Mon premier jeu en assembleur

zone Membre non connecté

Touriste

Rang

Avatar

Inscrit le : 11/10/2023 à 19h25

Messages: 66

Le 25/11/2023 à 20h03

Reprise du message précédent

La sauvegarde dans la zone horloge, c'est un peu chaud quand même, personnellement je ne m'y risquerais pas.

La solution SRAM est bien mieux (tu supportes vraiment une tonne de trucs dans MSXgl, pourquoi je m'emmerde en assembleur moi ?).
Le seul inconvénient que je vois est pour quelqu'un qui souhaite faire une vraie cartouche.

Sinon on peut peut-être sauver tout bêtement sur disquette ? Avec une disquette dédiée dont on lit/écrit les premiers secteurs, sans se soucier du FS. Avec un « magic » écrit à l'init de la disquette, puis un checksum sur chaque fichier pour éviter de charger / écrire n'importe quelle disquette. Edité par zone Le 25/11/2023 à 20h04
   
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2657

Le 25/11/2023 à 22h21
zone :
La sauvegarde dans la zone horloge, c'est un peu chaud quand même, personnellement je ne m'y risquerais pas.


Il y a 4 zones mémoires dans la RTC (real-time clock) ; la 4e est libre pour les utilisateurs. Ca ne fait que 6 octets, mais cela peut suffire pour certains jeux.
Tu peux tester le sample "clock" de MSXgl (appuis sur F1): https://webmsx.org/?ROM=https://github.com/aoineko-fr/MSXgl/raw/main/projects/samples/emul/rom/s_clock.rom
Ca me semble assez "safe" mais oui, il y a des solutions plus pérenne.

zone :
La solution SRAM est bien mieux (tu supportes vraiment une tonne de trucs dans MSXgl, pourquoi je m'emmerde en assembleur moi ?).


Tout dépend de ton objectif. En assembleur tu vas probablement réinventer la roue et il te faudra beaucoup de temps pour avoir un jeu un peu poussé, mais cela peut être amusant. :)

zone :
Le seul inconvénient que je vois est pour quelqu'un qui souhaite faire une vraie cartouche.


De quel inconvénient parles-tu avec une cartouche ?
La plupart des jeux qui utilisent une cartouche PAC ont le jeu dans un slot (ou sur disquette) et la cartouche PAC dans l'autre slot.
Pour info, on peut aussi sauvegarder sur cartouche Game Master II de Konami, mais le format de "fichier" semble perdu et il faut encore que je fasse un peu de rétro-ingénierie pour le reconstituer et l'ajouter à MSXgl.

zone :
Sinon on peut peut-être sauver tout bêtement sur disquette ? Avec une disquette dédiée dont on lit/écrit les premiers secteurs, sans se soucier du FS. Avec un « magic » écrit à l'init de la disquette, puis un checksum sur chaque fichier pour éviter de charger / écrire n'importe quelle disquette.


Oui, c'est très facile pour un jeu en disquette... mais pour un jeu en cartouche, c'est une autre pair de manche.
Dans ce genre de cas, il faut que la cartouche rende la main au système pour qu'il puisse initialiser le driver de lecteur de disquette et reprenne la main ensuite.
Il y a un "hook" pour ça.
Et oui, c'est supporté dans MSXgl ;) Edité par aoineko Le 25/11/2023 à 22h22


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

Touriste

Rang

Avatar

Inscrit le : 11/10/2023 à 19h25

Messages: 66

Le 26/11/2023 à 11h56
aoineko :


Tout dépend de ton objectif. En assembleur tu vas probablement réinventer la roue et il te faudra beaucoup de temps pour avoir un jeu un peu poussé, mais cela peut être amusant. :)



Oui c'est le but :)

aoineko :

zone :
Le seul inconvénient que je vois est pour quelqu'un qui souhaite faire une vraie cartouche.


De quel inconvénient parles-tu avec une cartouche ?


Je pensais à l'intégration de la puce pour la sauvegarde sur la cartouche.
C'est plus compliqué et ça augmente le coût de fabrication.

Mais d'après ce que tu dis, on peut utiliser une cartouche dédiée pour cela (si le MSX a deux slots physiques disponibles).

aoineko :

Oui, c'est très facile pour un jeu en disquette... mais pour un jeu en cartouche, c'est une autre pair de manche.
Dans ce genre de cas, il faut que la cartouche rende la main au système pour qu'il puisse initialiser le driver de lecteur de disquette et reprenne la main ensuite.


Ah je vois: le temps de l'accès disque, il faut replacer le bios disque à la place du bios classique.

On ne peut pas le faire à coups de in/out ? Il n'y a pas d'adresse fixe, comme pour le VDP où tout le monde semble adresser directement $98 , $99 et suivants ?


aoineko :

Il y a un "hook" pour ça.
Et oui, c'est supporté dans MSXgl ;)


Cool :)
   
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2657

Le 26/11/2023 à 13h27
zone :
Ah je vois: le temps de l'accès disque, il faut replacer le bios disque à la place du bios classique.

On ne peut pas le faire à coups de in/out ? Il n'y a pas d'adresse fixe, comme pour le VDP où tout le monde semble adresser directement $98 , $99 et suivants ?


Non, il ne s'agit pas de ça.
Au boot d'un MSX, le système va chercher la présence d'une ROM exécutable (avec la balise "AB" en 4000h ou 8000h) dans chaque slot.
Dès qu'il en trouve une, il donne la main au programme de la cartouche.
Normalement, pour un jeu, la cartouche garde la main et ne la rend jamais au système (l'utilisateur reboot son MSX s'il veut faire autre chose).
Le soucis, c'est que la ROM qui contient le driver du lecteur de disquette est généralement sur un slot après celui des 2 ports cartouches et elle n'est donc pas exécuté au moment ou le jeu dans la cartouche commence.
L'astuce, c'est de rendre la main au système depuis l'initialisation du jeu cartouche et de s'enregistrer dans un hook pour qu'une fois que le système à fini de scanner tous les slots (et donc d'avoir trouvé et exécuté la ROM du driver), le système redonne encore une fois la main au jeu. :)
C'est une gymnastique un peu particulière, mais cela fonctionne bien (à quelques exceptions prêt). Edité par aoineko Le 26/11/2023 à 13h53


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

Touriste

Rang

Avatar

Inscrit le : 11/10/2023 à 19h25

Messages: 66

Le 26/11/2023 à 14h21
C'est un jump inter-slot, c'est ça ?

Merci pour toutes tes explications.

Pour le disque et les sauvagardes, c'est un peu par curiosité, car je ne suis pas sûr d'aller jusque là.
   
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2657

Le 26/11/2023 à 14h43
zone :
C'est un jump inter-slot, c'est ça ?


Oui. Tu as 5 octets dédié au hook H.STKE dans l'espace mémoire du BIOS.
Il faut donc copier un code en RAM à cet emplacement qui renverra vers ton programme via un appel inter-slot (vu que la cartouche ne sera plus sélectionné à ce moment-là).
L'instruction "rst 30h" (inter-slot call) fait très bien l'affaire pour ça.

Mais oui, la sauvegarde sur une cartouche de SRAM est bien plus simple (et bien géré par les émulateurs). Edité par aoineko Le 26/11/2023 à 14h48


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

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 02/10/2009 à 19h41

Messages: 10255

Le 26/11/2023 à 18h09
Citation :
Pour info, on peut aussi sauvegarder sur cartouche Game Master II de Konami, mais le format de "fichier" semble perdu et il faut encore que je fasse un peu de rétro-ingénierie pour le reconstituer et l'ajouter à MSXgl.



Utilitaires de sauvegarde Sram GM2 pour aider

Citation :
The Game Master 2 (Konami RC 755)

This is a 1 megabit ROM cartridge with 8 Kb SRAM. Because of the SRAM, the mappers have special features.

Since the size of the mapper is 8Kb, the memory banks are:

Bank 1: 4000h - 5FFFh
Bank 2: 6000h - 7FFFh
Bank 3: 8000h - 9FFFh
Bank 4: A000h - BFFFh

And the addresses to change banks:

Bank 1: <none>
Bank 2: 6000h - 6FFFh (6000h used)
Bank 3: 8000h - 8FFFh (8000h used)
Bank 4: A000h - AFFFh (A000h used)
SRAM write: B000h - BFFFh

If SRAM is selected in bank 4, you can write to it in the memory area B000h - BFFFh.

The value you write to change banks also determines whether you select ROM or SRAM. SRAM can be in any memory bank (except bank 1 which can't be modified) but it can only be written too in bank 4.

bit | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
----------------------------------------------------------
function | R0 | R1 | R2 | R3 | 1=SRAM/0=ROM | S0 | X | X |

If bit 4 is reset, bits 0 - 3 select the ROM page as you would expect them to do. Bits 5 - 7 are ignored now. If bit 4 is set, bit 5 selects the SRAM page (first or second 4Kb of the 8Kb). Bits 6 - 7 and bits 0 - 3 are ignored now.

Since you can only select 4Kb of the SRAM at once in a memory bank and a memory bank is 8Kb in size, the first and second 4Kb of the memory bank read the same 4Kb of SRAM if SRAM is selected.

I have verified all of this on the real cartridge, many thanks to Klaas de Wind.


:noel
Site web    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2657

Le 26/11/2023 à 19h38
Ecrire sur la SRAM de la Game Master 2 ne pose aucun soucis, mais je parlais du format de "fichier" utilisé par Konami pour que chaque block sauvegardé ait un nom visible et qu'on puisse éviter de les écraser.

J'imagine que le format est simple (un entête avec la taille du block à skip jusqu'au suivant, un nom et p'être quelques autres infos), mais j'ai pas encore regardé.

Il faudrait prendre la Game Master 2 via un émulateur puis :
- la "formater",
- exporter les données de la SRAM,
- sauver un jeu Konami compatible dessus,
- exporter les données de la SRAM,
- sauver sur le même emplacement avec le même jeu après avoir changé quelque chose en jeu (dépenser un objet, perdre quelques points de vie, ex.),
- exporter les données de la SRAM,
- recommencer 3 fois avec des jeux différents.

En faisant des "diff" sur les fichiers de SRAM exportés, ça serait assez facile à mon avis, d'en déterminer le format.
C'est dans ma todo-list, mais j'ai pas encore eu le temps de me pencher dessus. Edité par aoineko Le 27/11/2023 à 12h35


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

Touriste

Rang

Avatar

Inscrit le : 11/10/2023 à 19h25

Messages: 66

Le 26/11/2023 à 20h02
À propos des accès VRAM: à l'init, je configure comme il faut l'adresse de départ de la VRAM pour la première écriture.
C'est à dire que pour le screen 4, je me place en $1800.
Je mets à zéro la partie haute (A14-A16), puis je m'occupe des deux octets bas.

Pour les modifications en cours de jeu, vu que la partie haute n'est pas utile, je me contente de modifier A0-A13.
Ça permet de gagner 2 OUT.
Je pars du principe que n'appellant pas du tout le BIOS, il y a peu de chance pour que A14-A16 soient modifiés, et vu qu'ils sont à la bonne valeur…
Ça a l'air de bien fonctionner, pouvez-vous confirmer qu'il n'y a pas de problèmes à procéder de cette façon ?
   
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2657

Le 27/11/2023 à 00h20
Tu utilises le BIOS même si tu n'utilises pas le BIOS. ^^
En fait, le gestionnaire d'interruption (ISR) du BIOS pourrait très bien changer ce registre du VDP.
C'est très probablement pas le cas, mais avec le BIOS ont peut jamais être 100% sûr.

Reste la solution de remplacer l'ISR du BIOS par le tiens.
Tu as 2 solutions :
- Créer une ROM visible sur la page 0 (adresses 0000-3FFFh) avec ton propre ISR en 0038h. Tu peux utiliser une ROM 48 KB (sur les pages 0-2), une ROM 32 KB (sur les pages 0 et 1), ou n'importe quel taille de ROM qui supporte le mirroring (dans ce cas une ROM 32 KB sur les pages 1 et 2 par ex., peut aussi être visible sur les pages 3 et 0).
- Sélectionner de la RAM en page 0 et y copier un ISR à 0038h. Ne fonctionne qu'avec les MSX avec au moins 64 KB de RAM (donc 100% des MSX à partir des MSX 2).
(et "oui", MSXgl supporte ces deux solutions :p )

Mais sinon, oui, une fois que tu es sûr d'être d'en un environnement maitrisé (donc BIOS-free), c'est une bonne idée de ne mettre à jour que les registres qui en ont vraiment besoin. Edité par aoineko Le 27/11/2023 à 00h21


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

Touriste

Rang

Avatar

Inscrit le : 11/10/2023 à 19h25

Messages: 66

Le 27/11/2023 à 13h37
Han ça se complique là.

Mon ISR à moi, ça serait juste un RET. C'est possible ?
Je pense que la solution 2 est la plus simple à mettre en place. En plus, cela permet d'avoir un peu plus de ram en ligne plutôt qu'un inutile BIOS.
Vu que je suis sous BASIC pour mes tests, je vais quand même laisser le BIOS tranquille pour l'instant.

À propos de RAM:
Puis-je considérer que j'ai 16Ko de RAM à dispo à partir de 0xC000, par défaut ?
Disons 15Ko, pour éviter d'écraser la stack et la zone bios.

Je devrais vraiment relire l'organisation segments/slots, j'ai des lacunes… Edité par zone Le 27/11/2023 à 13h38
   
Jipe Membre non connecté

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 02/10/2009 à 19h41

Messages: 10255

Le 27/11/2023 à 14h49
Citation :
À propos de RAM:
Puis-je considérer que j'ai 16Ko de RAM à dispo à partir de 0xC000, par défaut ?
Disons 15Ko, pour éviter d'écraser la stack et la zone bios.


la ram de C000h à FFFFh n'est pas entièrement disponible

sans lecteur de disquette on dispose de la zone C000h à F380h le reste est réservé pour les variables système et les hooks

avec un controleur de lecteur de disquette on à jusqu'à F1C9h

regarde le tableau ici : https://www.msx.org/wiki/RAM_and_Memory_Mappers


:noel
Site web    
zone Membre non connecté

Touriste

Rang

Avatar

Inscrit le : 11/10/2023 à 19h25

Messages: 66

Le 27/11/2023 à 16h55
Ok merci pour le lien de synthèse.

Donc j'en déduis qu'il y a toujours un peu de ram de 0xC000 à environ 0xF000.

Jusque là tout allait bien, mais alors ça se complique pour ma megarom.
J'ai créé une rom avec des blocs de 16ko qui se suivent, donc 0xC000 est recouvert…
La ROM elle-même est placée de $4000 à $8000
Ensuite, il y a 7 pages de 16Ko définies ainsi:

Code :

seg1:
    db "segment 1",LF,CR,0
  block $4000+seg1-$, '1'
; et ainsi de suite…
seg7:
    db "segment 7",LF,CR,0
  block $4000+seg7-$, '7'


Alors tout allouer en statique n'est peut-être pas la bonne façon de faire.
Car au segment 2, 0xC000 est recouvert… enfin je ne sais pas comment c'est mappé ensuite en mémoire.
Peut-être (surement) que seul le segment $4000 est alloué au démarrage, le reste (tout ce qui est défini en statique à coups de « block ») étant du ressort du mapper de la cartouche.
Et donc un ORG $C000 suffirait pour les variables en écriture du programme.

En résumé, ma question est: comment avoir une zone de données en lecture/écriture avec une megarom. Edité par zone Le 27/11/2023 à 16h56
   
Jipe Membre non connecté

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 02/10/2009 à 19h41

Messages: 10255

Le 27/11/2023 à 18h52
une megarom avec des banks de 16K est obligatoirement un Mapper ASCII

dans ce type de megarom il n'y a que 2 pages visibles

4000h à 7FFFh avec des pages de 16k commutables par écriture d'une valeur dans les adresses de 6000h à 67FFh
8000h à BFFFh avec des pages de 16k commutables par écriture d'une valeur dans les adresses de 7000h à 77FFh

donc on ne peut pas empiéter dans la zone au dessus de BFFFh qui est libre pour l'utilisateur mais n'est pas située dans le même slot


:noel
Site web    
zone Membre non connecté

Touriste

Rang

Avatar

Inscrit le : 11/10/2023 à 19h25

Messages: 66

Le 27/11/2023 à 19h26
J'ai fait un test en rajoutant (plein d'espoir) un segment défini comme étant à $8000 après mes définitions statiques:

Code :

seg7:
    db "Text from segment 7",LF,CR,0
  block $4000+seg7-$, '7'

  .org $8000
data_rw:
  db "AAAAAAAAAAAH !",LF,CR,0


J'ai un warning du compilo qui me prévient que c'est en train de déborder.
Ensuite, un print de «data_rw» m'affiche «Text from segment 7». Ça a débordé et il a pris au bord de la cartouche.

Bon pour l'instant ce n'est pas grave, mais il va falloir que je trouve une autre méthode pour avoir un espace où je peux lire et écrire.
Je ne sais pas si c'est possible sans magouiller avec la gestion des slots. L'idéal serait bien sûr que je puisse définir cela directement dans le source.
   
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2657

Le 27/11/2023 à 20h54
Ton problème n'est qu'un problème d'assembleur. Il y a une disjonction entre les adresses physique de ton jeu dans la ROM et les adresses où il sera vu par le Z80.

Comme a expliqué Jipe, tout le contenu de ta ROM ne sera vu par le Z80 qu'à travers l'une des banques (pages) de la ROM qui seront toutes entre 4000h et BFFFh.

Par contre dans ton fichier ROM, les segments vont être empilés les uns dernières les autres. Le premier à l'offset 0000h, puis 4000h, 8000h, C000h, 10000h, 14000h, etc. (pour un mapper 16 KB).

Il faut que tu trouves un moyen avec ton assembleur de gérer ça. Notamment, si tu as du code dans tes segments, il faut qu'ils soit compilés pour être exécuté à l'emplacement final où il sera vu par le Z80. Sinon les symboles pour les call, les jump, etc. ne seront pas bons.

Évidemment, "oui"... :D
Mais j'ai dû créer un outil MSXhex pour bien gérer les mappeurs avec SDCC. Edité par aoineko Le 27/11/2023 à 20h56


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