La Place des Développeurs Mes 1ers pas sur MSX ...
Hello la compagnie (je t'ai écouté aoineko )
Je commence à me mettre tout doucement à la programmation sur MSX car je souhaiterai "porter'' 2 de mes jeux coleco (presque finis si je ne tiens pas compte de la musique) et je rencontre une 1ere difficulté : ma routine put_char que je souhaiterai compatible avec celle de la coleco. J'aurais donc besoin de vos lumières
Je dois faire une erreur car le caractère affiché n'est pas le bon alors que la position est correcte et comme d’habitude, ça doit être un truc tout bête mais ayant le nez dans le guidon (en plus de mon grand age), je ne vois plus
Voici la routine
ex : put_char(3,5,60) // x=3, y = 5, le carac a afficher se trouve à l'index 60 dans la patterntable
En espérant avoir été clair.
Merci d'avance pour votre aide les zamis
Eric Edité par Ricco59_bis Le 29/12/2020 à 20h52
Je commence à me mettre tout doucement à la programmation sur MSX car je souhaiterai "porter'' 2 de mes jeux coleco (presque finis si je ne tiens pas compte de la musique) et je rencontre une 1ere difficulté : ma routine put_char que je souhaiterai compatible avec celle de la coleco. J'aurais donc besoin de vos lumières
Je dois faire une erreur car le caractère affiché n'est pas le bon alors que la position est correcte et comme d’habitude, ça doit être un truc tout bête mais ayant le nez dans le guidon (en plus de mon grand age), je ne vois plus
Voici la routine
ex : put_char(3,5,60) // x=3, y = 5, le carac a afficher se trouve à l'index 60 dans la patterntable
En espérant avoir été clair.
Merci d'avance pour votre aide les zamis
Eric Edité par Ricco59_bis Le 29/12/2020 à 20h52
Sector28
Membre non connecté
Villageois
Code ASM :
void put_char0(unsigned int posx, unsigned int posy, unsigned char carac) { posx; posy; carac; __asm ld de,8 push ix pop hl add hl,de push hl ld hl,#0x1800 ld c,4(ix) // bc = X ld b,5(ix) add hl,bc // hl = 0x1800 + x push hl ld l,6(ix) // bc = y ld h,7(ix) add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl pop de add hl,de // de = 0x1800 + y*32 + x push hl pop de // de = 0x1800 + y*32 + x pop hl // hl = 0x0000 + Carac * 8 ld bc,#0x0001 // longueur = 1 carac call 0x005c __endasm; }
DONALD TRUMP IS FAST APPROACHING
NEMESIS ! RETURN IMMEDIATELY !
aoineko
Membre non connecté
Conseiller Municipal
On est toujours ignorant avant de savoir.
@ quelques explications Sector28 ?
@ aoineko > screen 2
merci à vous 2
@ aoineko > screen 2
merci à vous 2
aoineko
Membre non connecté
Conseiller Municipal
Je suis assez noob avec le MSX1 (je ne fais que du MSX2) mais si je devais faire une fonction put_char() je ferais :
- récupérer l'adresse de la Pattern Layout Table en VRAM (stocké par le Bios en RAM à l'adresse F3C7h, nommé GRPNAM)
- j'y ajouterai 32*y+x
- j'écrirais à cette adresse la valeur de mon caractère (directement via l'accès aux ports du processeur graphique)
Tu peux aussi passer par la fonction du Bios en 005Ch (nommé LDIRVM).
Dans ce cas, il te faut ce setup :
- BC : Block length (1 dans ton cas)
- DE : Start address of VRAM
- HL : Start address of memory
A priori, c'est ce que fait ta fonction et celle de Sector28.
J'ai du mal à lire l'assembleur que j'ai pas écris, donc je ne saurai te dire s'il y a une erreur qq part.
Je sais pas si tu as vu, mais dans le cas du Screen mode 2, il y a 3 Pattern Generator Table (font) :
- une pour le haut de l'écran (lignes 0 à 7)
- une pour le milieu (lignes 8 à 15)
- et une pour le bas (lignes 16 à 23)
Donc si tu veux les mêmes caractères partout, il te faut les copier dans ces 3 tables.
- récupérer l'adresse de la Pattern Layout Table en VRAM (stocké par le Bios en RAM à l'adresse F3C7h, nommé GRPNAM)
- j'y ajouterai 32*y+x
- j'écrirais à cette adresse la valeur de mon caractère (directement via l'accès aux ports du processeur graphique)
Tu peux aussi passer par la fonction du Bios en 005Ch (nommé LDIRVM).
Dans ce cas, il te faut ce setup :
- BC : Block length (1 dans ton cas)
- DE : Start address of VRAM
- HL : Start address of memory
A priori, c'est ce que fait ta fonction et celle de Sector28.
J'ai du mal à lire l'assembleur que j'ai pas écris, donc je ne saurai te dire s'il y a une erreur qq part.
Je sais pas si tu as vu, mais dans le cas du Screen mode 2, il y a 3 Pattern Generator Table (font) :
- une pour le haut de l'écran (lignes 0 à 7)
- une pour le milieu (lignes 8 à 15)
- et une pour le bas (lignes 16 à 23)
Donc si tu veux les mêmes caractères partout, il te faut les copier dans ces 3 tables.
On est toujours ignorant avant de savoir.
Merci Aoineko,
Oui, pour les 3 zones c'est comme sur Coleco.
Concernant les ports graphiques, je n'y ai jamais rien compris... Peut etre que ce n'est pas si compliqué mais une chose à la fois
J'ai trouvé la solution, j'utilise Fillvram
hl = 0x1800 + x + y*32
bc = 1 (nb de carac à afficher)
a = le caractère à afficher
La routine citée dans mon 1er post, n'est pas valable dans ce cas car elle attend une adresse en HL. dans ce cas, je dois faire ça :
//déclarations -----------------------------------------------------------
const unsigned char toto[] = {10,5,12,17};
unsigned char *ptoto;
// le code ----------------------------------------------------------------
void put_char0(unsigned int posx, unsigned int posy, char *carac)
{
posx; posy; carac;
__asm
ld l,8(ix)
ld h,9(ix)
push hl
ld hl,#0x1800
ld c,4(ix) // bc = X
ld b,5(ix)
add hl,bc // hl = 0x1800 + x
push hl
ld l,6(ix) // bc = y
ld h,7(ix)
add hl,hl
add hl,hl
add hl,hl
add hl,hl
add hl,hl
pop de
add hl,de
push hl
pop de // de = 0x1800 + y*32 + x
pop hl // hl = adresse table des carac à afficher
ld bc,#0x0001 // longueur = 1 carac
call 0x005c
__endasm;
}
// l'utilisation ---------------------------------------------------------------------
ptoto = (unsigned char *) &toto[0];
put_char0(3,2,ptoto); // dans ce cas n'affichera qu'un carac (10). Il suffit que je rajoute le param LENGTH par ex et je pourrai afficher de 1 à 32 caracs. Si plus il faut que je fasse des calculs pour afficher une zone de 5 caracs sur 5 lignes ou 8 carac sur 44 lignes... j'l'ai pas essayé encore car trop content d'avoir fait mon put_char
Voili voilou
Bonne nuit et merci Edité par Ricco59_bis Le 29/12/2020 à 23h41
Oui, pour les 3 zones c'est comme sur Coleco.
Concernant les ports graphiques, je n'y ai jamais rien compris... Peut etre que ce n'est pas si compliqué mais une chose à la fois
J'ai trouvé la solution, j'utilise Fillvram
hl = 0x1800 + x + y*32
bc = 1 (nb de carac à afficher)
a = le caractère à afficher
put_char1(unsigned int posx, unsigned int posy, unsigned char carac)
{
posx; posy; carac;
__asm
ld hl,#0x1800
ld c,4(ix) // bc = X
ld b,5(ix)
add hl,bc // hl = 0x1800 + x
push hl
ld l,6(ix) // bc = y
ld h,7(ix)
add hl,hl
add hl,hl
add hl,hl
add hl,hl
add hl,hl
pop de
add hl,de // position où doit etre ecrit le carac
ld bc,#0x0001 // longueur = 1 carac
ld a,8(ix)
call 0x0056 // Fill VRAM
__endasm;
}
{
posx; posy; carac;
__asm
ld hl,#0x1800
ld c,4(ix) // bc = X
ld b,5(ix)
add hl,bc // hl = 0x1800 + x
push hl
ld l,6(ix) // bc = y
ld h,7(ix)
add hl,hl
add hl,hl
add hl,hl
add hl,hl
add hl,hl
pop de
add hl,de // position où doit etre ecrit le carac
ld bc,#0x0001 // longueur = 1 carac
ld a,8(ix)
call 0x0056 // Fill VRAM
__endasm;
}
La routine citée dans mon 1er post, n'est pas valable dans ce cas car elle attend une adresse en HL. dans ce cas, je dois faire ça :
//déclarations -----------------------------------------------------------
const unsigned char toto[] = {10,5,12,17};
unsigned char *ptoto;
// le code ----------------------------------------------------------------
void put_char0(unsigned int posx, unsigned int posy, char *carac)
{
posx; posy; carac;
__asm
ld l,8(ix)
ld h,9(ix)
push hl
ld hl,#0x1800
ld c,4(ix) // bc = X
ld b,5(ix)
add hl,bc // hl = 0x1800 + x
push hl
ld l,6(ix) // bc = y
ld h,7(ix)
add hl,hl
add hl,hl
add hl,hl
add hl,hl
add hl,hl
pop de
add hl,de
push hl
pop de // de = 0x1800 + y*32 + x
pop hl // hl = adresse table des carac à afficher
ld bc,#0x0001 // longueur = 1 carac
call 0x005c
__endasm;
}
// l'utilisation ---------------------------------------------------------------------
ptoto = (unsigned char *) &toto[0];
put_char0(3,2,ptoto); // dans ce cas n'affichera qu'un carac (10). Il suffit que je rajoute le param LENGTH par ex et je pourrai afficher de 1 à 32 caracs. Si plus il faut que je fasse des calculs pour afficher une zone de 5 caracs sur 5 lignes ou 8 carac sur 44 lignes... j'l'ai pas essayé encore car trop content d'avoir fait mon put_char
Voili voilou
Bonne nuit et merci Edité par Ricco59_bis Le 29/12/2020 à 23h41
aoineko
Membre non connecté
Conseiller Municipal
Super
Juste un truc, si tu comptes garder le Bios (ce qui est surement le cas), je te conseil de récupérer l'adresse de la Pattern Layout Table dans la RAM plutôt que de l'écrire en dure dans ta fonction.
Si tu utilises le Bios pour initialiser le Screen Mode 2 via les routines du Bios (comme 0072h / INIGRP), tu as l'adresse VRAM de ta table à F3C7h (GRPNAM).
Du coup, normalement tu peux juste remplacer :
ld hl,#0x1800
Par :
ld hl,(#0xF3C7)
Juste un truc, si tu comptes garder le Bios (ce qui est surement le cas), je te conseil de récupérer l'adresse de la Pattern Layout Table dans la RAM plutôt que de l'écrire en dure dans ta fonction.
Si tu utilises le Bios pour initialiser le Screen Mode 2 via les routines du Bios (comme 0072h / INIGRP), tu as l'adresse VRAM de ta table à F3C7h (GRPNAM).
Du coup, normalement tu peux juste remplacer :
ld hl,#0x1800
Par :
ld hl,(#0xF3C7)
On est toujours ignorant avant de savoir.
Salut les zamis
Bon j'ai un gros soucis de connexion avec mon pseudo ricco59. Ce n'est plus le bon pseudo, dorénavant c'est ericm59
@aoineko, je poste un message qui aurait etre posté il y a quelques jours
Concernant GRPNAM (F3C7h > 0x1800), je l'ai implémenté mais quel est l'intéret ? cette adresse
ne change-t-elle pas avec d'autres machines (msx2, 2+ ou turbo) ?
Voici où j'en suis :
- put_char .... ok
- sprites ..... ok
- vsync ....... ok (si on considère que HALT fait l'affaire )
une tite video pour ceux qui veulent
c'est ic > https://youtu.be/-rrW28Qdhbw
j'ai encore un souci pour les sprites tout fonctionne.
Lorsque je déclare mes sprites comme suit...
ZeZone[0].pattern = (13+0)*4; // sprite PRESENTS inférieur
ZeZone[0].colour = 15;
ZeZone[0].x = 13*8+0*16;
ZeZone[0].y = 16*8;
ZeZone[1].pattern = (13+1)*4; // sprite PRESENTS inférieur
ZeZone[1].colour = 15;
ZeZone[1].x = 13*8+1*16;
ZeZone[1].y = 16*8;
ZeZone[2].pattern = (13+2)*4; // sprite PRESENTS inférieur
ZeZone[2].colour = 15;
ZeZone[2].x = 13*8+2*16;
ZeZone[2].y = 16*8;
ZeZone[3].pattern = (13+3)*4; // sprite PRESENTS inférieur
ZeZone[3].colour = 15;
ZeZone[3].x = 13*8+3*16;
ZeZone[3].y = 16*8;
put_vram(0x1b00,ZeZone,128);
... mes sprites s'affichent bien mais lorsque je fais une boucle qui reprend les éléments ci-dessus
for (Ze_Boucle = 0 ; Ze_Boucle < 4 ; ++Ze_Boucle)
{
ZeZone[Ze_Boucle].pattern = (13+Ze_Boucle)*4;
ZeZone[Ze_Boucle].colour = 15;
ZeZone[Ze_Boucle].x = 13*8+Ze_Boucle*16;
ZeZone[Ze_Boucle].y = 16*8;
}
put_vram(0x1b00,ZeZone,128);
rien ne s'affiche. Bizarre non ?? un ptit éclaircissement ?
Prochaine étape : le joystick et le menu et bien sûr d'autres questions
A+ les zamis
Ericm59 (Ricco59) Edité par Ricco59 Le 02/01/2021 à 12h46
Bon j'ai un gros soucis de connexion avec mon pseudo ricco59. Ce n'est plus le bon pseudo, dorénavant c'est ericm59
@aoineko, je poste un message qui aurait etre posté il y a quelques jours
Concernant GRPNAM (F3C7h > 0x1800), je l'ai implémenté mais quel est l'intéret ? cette adresse
ne change-t-elle pas avec d'autres machines (msx2, 2+ ou turbo) ?
Voici où j'en suis :
- put_char .... ok
- sprites ..... ok
- vsync ....... ok (si on considère que HALT fait l'affaire )
une tite video pour ceux qui veulent
c'est ic > https://youtu.be/-rrW28Qdhbw
j'ai encore un souci pour les sprites tout fonctionne.
Lorsque je déclare mes sprites comme suit...
ZeZone[0].pattern = (13+0)*4; // sprite PRESENTS inférieur
ZeZone[0].colour = 15;
ZeZone[0].x = 13*8+0*16;
ZeZone[0].y = 16*8;
ZeZone[1].pattern = (13+1)*4; // sprite PRESENTS inférieur
ZeZone[1].colour = 15;
ZeZone[1].x = 13*8+1*16;
ZeZone[1].y = 16*8;
ZeZone[2].pattern = (13+2)*4; // sprite PRESENTS inférieur
ZeZone[2].colour = 15;
ZeZone[2].x = 13*8+2*16;
ZeZone[2].y = 16*8;
ZeZone[3].pattern = (13+3)*4; // sprite PRESENTS inférieur
ZeZone[3].colour = 15;
ZeZone[3].x = 13*8+3*16;
ZeZone[3].y = 16*8;
put_vram(0x1b00,ZeZone,128);
... mes sprites s'affichent bien mais lorsque je fais une boucle qui reprend les éléments ci-dessus
for (Ze_Boucle = 0 ; Ze_Boucle < 4 ; ++Ze_Boucle)
{
ZeZone[Ze_Boucle].pattern = (13+Ze_Boucle)*4;
ZeZone[Ze_Boucle].colour = 15;
ZeZone[Ze_Boucle].x = 13*8+Ze_Boucle*16;
ZeZone[Ze_Boucle].y = 16*8;
}
put_vram(0x1b00,ZeZone,128);
rien ne s'affiche. Bizarre non ?? un ptit éclaircissement ?
Prochaine étape : le joystick et le menu et bien sûr d'autres questions
A+ les zamis
Ericm59 (Ricco59) Edité par Ricco59 Le 02/01/2021 à 12h46
Salut Eric
Pour garder ma comptabilité avec la colecovision, j'ai gardé cette structure
typedef struct
{
char y;
char x;
char pattern;
char colour;
} sprite_t;
le Y et X sont inversés sur MSX
Pour garder ma comptabilité avec la colecovision, j'ai gardé cette structure
typedef struct
{
char y;
char x;
char pattern;
char colour;
} sprite_t;
le Y et X sont inversés sur MSX
aoineko
Membre non connecté
Conseiller Municipal
Salut Ricco,
Si tu veux, je peux renommer ton nouveau compte en ricco59 (et l'ancien en ricco59_bis par ex.).
Pour GRPNAM, c'est justement le meilleur moyen d'assurer la compatibilité avec tous les MSX et surtout, ça permet que ta fonction marche, même si tu déplaces les données des sprites en VRAM.
Je sais pas pour la Colleco, mais sur MSX, tu peux organiser les données en VRAM comme ça t'arrange (ce qui est très pratique pour certains jeux).
Pour la structure des attribues de sprites en VRAM, tu as raisons. C'est bien le Y en premier.
Par contre, je comprends pas pourquoi ta boucle fonctionne pas alors que la version déroulé fonctionne.
Il faudrait voir le reste du code pour te dire.
Si tu veux, je peux renommer ton nouveau compte en ricco59 (et l'ancien en ricco59_bis par ex.).
Pour GRPNAM, c'est justement le meilleur moyen d'assurer la compatibilité avec tous les MSX et surtout, ça permet que ta fonction marche, même si tu déplaces les données des sprites en VRAM.
Je sais pas pour la Colleco, mais sur MSX, tu peux organiser les données en VRAM comme ça t'arrange (ce qui est très pratique pour certains jeux).
Pour la structure des attribues de sprites en VRAM, tu as raisons. C'est bien le Y en premier.
Par contre, je comprends pas pourquoi ta boucle fonctionne pas alors que la version déroulé fonctionne.
Il faudrait voir le reste du code pour te dire.
On est toujours ignorant avant de savoir.
Salut Aoineko,
oui, tu peux transformer ericm59 en ricco59, no soucaille
@Eric, voici mon put_vram
Voili, voilou
Pendant 1h, je me suis battu avec gtstck et gttrig et bien... je me suis pris une raclée hihihi
Je ne m'avoue pas vaincu
Bonne soirée les zamis
oui, tu peux transformer ericm59 en ricco59, no soucaille
@Eric, voici mon put_vram
void put_vram(int vramaddr, void* block, int size)
{
vramaddr; block; size;
__asm
ld l,6(ix)
ld h,7(ix)
ld e,4(ix)
ld d,5(ix)
ld c,8(ix)
ld b,9(ix)
call LDIRVM
__endasm;
}
{
vramaddr; block; size;
__asm
ld l,6(ix)
ld h,7(ix)
ld e,4(ix)
ld d,5(ix)
ld c,8(ix)
ld b,9(ix)
call LDIRVM
__endasm;
}
Voili, voilou
Pendant 1h, je me suis battu avec gtstck et gttrig et bien... je me suis pris une raclée hihihi
Je ne m'avoue pas vaincu
Bonne soirée les zamis
ericb59
Membre non connecté
Conseiller Municipal
Par Ła barbe du grand cornu ! Oui je me suis trompais, c'est bien la coordonnée Y en premier, dire que j'ai écrit l'inverse dans ma DOC ! J'ai corrigé ! Ouf ! J'espère que je ne serai pas damné pour ça !
Pour ta routine, ne faudrait il pas écrire ceci ?
Pour la routine de lecture de joystick :
ou bien comme ça :
JoyNumber :
0 = clavier
1 = port A
2 = port B Edité par ericb59 Le 02/01/2021 à 20h05
Pour ta routine, ne faudrait il pas écrire ceci ?
Code C :
void put_vram(int vramaddr, void* block, int size) { vramaddr; block; size; _asm push ix ld ix,#0 add ix,sp ld l,6(ix) ld h,7(ix) ld e,4(ix) ld d,5(ix) ld c,8(ix) ld b,9(ix) call LDIRVM pop ix ret __endasm; }
Pour la routine de lecture de joystick :
Code C :
char Joystick(char JoyNumber) __naked { JoyNumber; __asm push ix ld ix,#0 add ix,sp ld a,4(ix) call #0xD5 ; GTSTCK ld l,a pop ix ret __endasm; }
ou bien comme ça :
Code C :
char Joystick(char JoyNumber) __z88dk_fastcall __naked { JoyNumber; __asm ld a,l call #0xD5 ; GTSTCK ld l,a ret __endasm; }
JoyNumber :
0 = clavier
1 = port A
2 = port B Edité par ericb59 Le 02/01/2021 à 20h05
hello,
@Guillaume, merci pour la modif
@Eric
>> n'oublie pas de mofier le ab02 pattern number par 1b02
il me semble que sdcc ajoute automatiquement
au debut de ta fonction asm
push ix
ld ix,#0
add ix,sp
et à la fin
pop ix
sauf si tu lui mets __naked
pour gtstck,
voila ce que je fais
Si je comprends ta 2e routine,
ld a,l est equivalent à ld a,4(ix)
et pour
ld l,a le registre 'l' récupère directement la 'direction' ??
je pourrais donc écrire : direction = Joystick(0); par exemple pour le clavier
et faire
switch (direction) ou directement switch ( Joystick(0))
case 0 : blabla; break;
case 1 : blabla; break;
case 2 : blabla; break;
..
..
case 8 : blabla; break;
?
j'ai encore bcp à apprendre
Merci en tout cas
Bonne soirée
Eric Edité par Ricco59 Le 02/01/2021 à 21h04
@Guillaume, merci pour la modif
@Eric
>> n'oublie pas de mofier le ab02 pattern number par 1b02
il me semble que sdcc ajoute automatiquement
au debut de ta fonction asm
push ix
ld ix,#0
add ix,sp
et à la fin
pop ix
sauf si tu lui mets __naked
pour gtstck,
voila ce que je fais
unsigned char get_stick(unsigned char choix)
{
choix;
__asm
ld a,4(ix)
call 0x005d
ld hl,#_Direction // direction = variable globale dans laquelle est stockée l'une des 8 directions
ld (hl),a
__endasm;
}
{
choix;
__asm
ld a,4(ix)
call 0x005d
ld hl,#_Direction // direction = variable globale dans laquelle est stockée l'une des 8 directions
ld (hl),a
__endasm;
}
Si je comprends ta 2e routine,
ld a,l est equivalent à ld a,4(ix)
et pour
ld l,a le registre 'l' récupère directement la 'direction' ??
je pourrais donc écrire : direction = Joystick(0); par exemple pour le clavier
et faire
switch (direction) ou directement switch ( Joystick(0))
case 0 : blabla; break;
case 1 : blabla; break;
case 2 : blabla; break;
..
..
case 8 : blabla; break;
?
j'ai encore bcp à apprendre
Merci en tout cas
Bonne soirée
Eric Edité par Ricco59 Le 02/01/2021 à 21h04
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie