Posté le 13/11/2022 14:03
Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2024 | Il y a 231 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements
Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd
Citer : Posté le 13/11/2022 14:08 | #
Cool, tu continues l'émulateur !?
libMicrofx : https://www.planet-casio.com/Fr/forums/topic17259-2-libmicrofx-remplacez-fxlib-pour-faire-des-add-ins-tres-legers.html !
Racer3D : https://www.planet-casio.com/Fr/programmes/programme4444-1-racer3d-mb88-jeux-add-ins.html
Citer : Posté le 13/11/2022 14:11 | #
j'essaye, j'ai un peu de temps libre.
Citer : Posté le 13/11/2022 14:57 | #
Le clavier est connecté comme ceci :
Son fonctionnement est le suivant : chaque touche relie une certaine ligne à une certaine colonne. Par exemple, la touche EXE relie la ligne ROW1 à la colonne COL2. Lorsque la touche EXE est pressée, une connexion électrique (pour simplifier) se fait entre cette ligne et cette colonne. Donc, si j'envoie un signal à 1 dans la ligne ROW1 et que la touche EXE est pressée, je récupère un signal à 1 dans COL2.
Toutes les lignes et les colonnes sont reliées à des ports I/O du MPU ; elles sont réparties entre les ports A, B et M sur SH3, et le ports M, N et Z sur SH4.
Pour effectuer un scan du clavier, on envoie un signal à 1 dans une des lignes et on regarde si le signal ressort dans une ou plusieurs colonnes. Par exemple, si j'active la ligne ROW1 et que je vois un signal arriver dans les colonnes COL2 et COL3, alors je sais que EXE est pressée (puisque le signal arrive dans COL2), que (-) est pressée (puisqu'il arrive dans COL3), et que toutes les autres touches de la ligne ne sont pas pressées.
Ce scan se fait ligne par ligne pour s'assurer qu'il n'y ait pas d'interférence entre les lignes. Si j'activais les lignes ROW1 et ROW2 en même temps, par exemple, je ne saurais pas si un signal sur COL2 viendrait de EXE ou de MINUS. Donc, on active une seule ligne à la fois.
En pratique :
Chaque port I/O a deux registres : un registre de contrôle (P*CR) et un registre de données (P*DR). Le registre de contrôle sert à indiquer si chaque signal est une entrée ou une sortie, tandis que le registre de données contient le signal à proprement parler.
Pour le clavier, les lignes sont des sorties (ie. le CPU écrit dans les lignes) et les colonnes sont des entrées (ie. le CPU lit les colonnes). Cette orientation ne change jamais, et le driver clavier n'a pas besoin lire les contenus de P*CR pour fonctionner. Donc : pour commencer tu peux ignorer les écritures dans P*CR et renvoyer 0 pour les lectures.
Tu as surtout besoin d'émuler P*DR. Quand le CPU écrit dedans, tu stockes la valeur (au moins pour les ports B/M sur SH3 et M/N sur SH4). Quand le CPU lit, si c'est le port des colonnes (PADR sur SH3, PZDR sur SH4), tu calcules l'état du signal des colonnes (sinon tu renvoies la valeur du port).
Pour calculer l'état du signal des colonnes, tu regardes chaque colonne C dans l'ordre et :
Par exemple, si sur SH4 le processeur lit PZDR, je vais regarder les colonnes une par une. Prenons par exemple la deuxième colonne, COL1. Pour déterminer si le deuxième bit de PZDR doit être à 1 je regarde successivement les touches STORE, TAN, ..., F6. Si {la touche STORE est pressée et le bit d'entrée de ROW5 vaut 1} ou {la touche TAN est pressée et le bit d'entrée de ROW6 vaut 1} ou ... ou {F6 est pressée et le bit d'entrée de ROW9 vaut 1}, alors le deuxième bit de PZDR vaudra effectivement 1.
Les bits d'entrée sont comme suit :
PBDR = [COL7 COL6 COL5 COL4 COL3 COL2 COL1 COL0]
PMDR = [xxxx xxxx xxxx xxxx xxxx xxxx COL9 COL8]
SH4:
PMDR = [xxxx xxxx COL5 COL4 COL3 COL2 COL1 COL0]
PNDR = [xxxx xxxx xxxx xxxx COL9 COL8 COL7 COL6]
Pour résumer :
Durant un scan du clavier, le programme va jouer avec le P*CR. Ça tu peux l'ignorer. Ensuite il va modifier les P*DR des lignes pour activer les lignes une par une, et après chaque activation il va lire le P*DR des colonnes pour déterminer quelles touches sont pressées sur la ligne qui est active. C'est là que tu as la majorité de ton travail.
Citer : Posté le 15/11/2022 19:34 | #
https://bible.planet-casio.com/yatis/hardware/sh7305/registers_list.html
c'est du sh4?
Citer : Posté le 15/11/2022 19:38 | #
Oui, SH7305 c'est SH4 tandis que SH7355/SH7337 c'est du SH3.
C'est la même que celle que je t'ai indiquée l'autre jour à peu de choses près.
Note que gint accède au port L (spécifiquement PLCR) à l'adresse SH3 sur toutes les calculatrices. C'est comme ça que les SH3 et les SH4 sont différenciées (sur la SH3 les valeurs écrites sont retenues tandis que sur la SH4 rien n'est retenu et ça renvoie toujours 0).
Citer : Posté le 16/11/2022 07:41 | #
les port que OTRONSH4 lit ne correspond pas.
Citer : Posté le 16/11/2022 09:56 | #
Et quels sont les ports que OTRONSH4 lit ? Je ne vais pas les deviner tu sais (ou écrire un émulateur pour le trouver...)
Citer : Posté le 16/11/2022 10:06 | #
pc: 309346 syscall 135
pc: 3057f8 syscall 28
pc: 305eec syscall 420
pc: 3091d6 syscall 15
unknow port a4000118. returned 1d2d
unknow port a4000122. recevied 7f
unknow port a4000138. returned a7
unknow port a4000138. recevied af
unknow port a4000120. returned 2c
unknow port a4000118. returned 4424
unknow port a4000118. returned 249e
pc: 3091d6 syscall 15
unknow port a4000118. returned 17f0
unknow port a4000122. recevied ff
unknow port a4000138. returned 6b
unknow port a4000138. recevied fe
unknow port a4000120. returned d3
unknow port a4000118. returned 0426
unknow port a4000118. returned 6f71
pc: 3091d6 syscall 15
unknow port a4000118. returned 3ae0
unknow port a4000122. recevied ff
unknow port a4000138. returned f4
unknow port a4000138. recevied fe
unknow port a4000120. returned 1f
unknow port a4000118. returned 0336
unknow port a4000118. returned 01af
pc: 3091d6 syscall 15
unknow port a4000118. returned 7907
unknow port a4000122. recevied ff
unknow port a4000138. returned 06
unknow port a4000138. recevied fe
unknow port a4000120. returned 1a
unknow port a4000118. returned 34fd
unknow port a4000118. returned 70e2
pc: 3057e8 syscall 143
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
voila l'output
Citer : Posté le 16/11/2022 10:13 | #
En effet, c'est curieux. C'est peut-être un reste du SH4 Compatibility Tool ? Pour les registres qui n'existent pas sur SH4, renvoie 0 durant une lecture, ignore les écritures, et vois si ça passe.
Citer : Posté le 16/11/2022 10:27 | #
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 305f6c syscall c4f
pc: 3057f8 syscall 28
pc: 305eec syscall 420
pc: 3091d6 syscall 15
unknow port a4000118. returned 0000
unknow port a4000122. recevied 7f
unknow port a4000138. returned 00
unknow port a4000138. recevied 0f
unknow port a4000120. returned 00
unknow port a4000118. returned 0000
unknow port a4000118. returned 0000
pc: 309346 syscall 135
pc: 3091d6 syscall 15
unknow port a4000118. returned 0000
unknow port a4000122. recevied fd
unknow port a4000138. returned 00
unknow port a4000138. recevied 0f
unknow port a4000120. returned 00
unknow port a4000118. returned 0000
unknow port a4000118. returned 0000
pc: 305858 syscall 90f
pc: 3091d6 syscall 15
unknow port a4000118. returned 0000
unknow port a4000122. recevied ff
unknow port a4000138. returned 00
unknow port a4000138. recevied fe
unknow port a4000120. returned 00
unknow port a4000118. returned 0000
unknow port a4000118. returned 0000
pc: 3091d6 syscall 15
unknow port a4000118. returned 0000
unknow port a4000122. recevied ff
unknow port a4000138. returned 00
unknow port a4000138. recevied fe
unknow port a4000120. returned 00
unknow port a4000118. returned 0000
unknow port a4000118. returned 0000
pc: 3057e8 syscall 143
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 309346 syscall 135
pc: 305f6c syscall c4f
pc: 3057f8 syscall 28
pc: 305eec syscall 420
pc: 3091d6 syscall 15
unknow port a4000118. returned 0000
unknow port a4000122. recevied 7f
unknow port a4000138. returned 00
unknow port a4000138. recevied 0f
unknow port a4000120. returned 00
unknow port a4000118. returned 0000
unknow port a4000118. returned 0000
pc: 309346 syscall 135
pc: 3091d6 syscall 15
unknow port a4000118. returned 0000
unknow port a4000122. recevied fd
unknow port a4000138. returned 00
unknow port a4000138. recevied 0f
unknow port a4000120. returned 00
unknow port a4000118. returned 0000
unknow port a4000118. returned 0000
pc:
ça ne change pas
Citer : Posté le 17/11/2022 13:31 | #
pc: 3041c8 memory read error at f6000000 | 32 bit
pc: 3041c8 memory read error at f6000100 | 32 bit
pc: 3041c8 memory read error at f6000200 | 32 bit
pc: 3041c8 memory read error at f6000300 | 32 bit
pc: 3041c8 memory read error at f6000400 | 32 bit
pc: 3041c8 memory read error at f6000500 | 32 bit
pc: 3041c8 memory read error at f6000600 | 32 bit
pc: 3041c8 memory read error at f6000700 | 32 bit
pc: 3041c8 memory read error at f6000800 | 32 bit
pc: 3041c8 memory read error at f6000900 | 32 bit
pc: 3041c8 memory read error at f6000a00 | 32 bit
pc: 3041c8 memory read error at f6000b00 | 32 bit
pc: 3041c8 memory read error at f6000c00 | 32 bit
pc: 3041c8 memory read error at f6000d00 | 32 bit
pc: 3041c8 memory read error at f6000e00 | 32 bit
pc: 3041c8 memory read error at f6000f00 | 32 bit
pc: 3041c8 memory read error at f6001000 | 32 bit
pc: 3041c8 memory read error at f6001100 | 32 bit
pc: 3041c8 memory read error at f6001200 | 32 bit
pc: 3041c8 memory read error at f6001300 | 32 bit
pc: 3041c8 memory read error at f6001400 | 32 bit
pc: 3041c8 memory read error at f6001500 | 32 bit
pc: 3041c8 memory read error at f6001600 | 32 bit
pc: 3041c8 memory read error at f6001700 | 32 bit
pc: 3041c8 memory read error at f6001800 | 32 bit
pc: 3041c8 memory read error at f6001900 | 32 bit
pc: 3041c8 memory read error at f6001a00 | 32 bit
pc: 3041c8 memory read error at f6001b00 | 32 bit
pc: 3041c8 memory read error at f6001c00 | 32 bit
pc: 3041c8 memory read error at f6001d00 | 32 bit
pc: 3041c8 memory read error at f6001e00 | 32 bit
pc: 3041c8 memory read error at f6001f00 | 32 bit
pc: 3041c8 memory read error at f6002000 | 32 bit
pc: 3041c8 memory read error at f6002100 | 32 bit
pc: 3041c8 memory read error at f6002200 | 32 bit
pc: 3041c8 memory read error at f6002300 | 32 bit
pc: 3041c8 memory read error at f6002400 | 32 bit
pc: 3041c8 memory read error at f6002500 | 32 bit
pc: 3041c8 memory read error at f6002600 | 32 bit
pc: 3041c8 memory read error at f6002700 | 32 bit
pc: 3041c8 memory read error at f6002800 | 32 bit
pc: 3041c8 memory read error at f6002900 | 32 bit
pc: 3041c8 memory read error at f6002a00 | 32 bit
pc: 3041c8 memory read error at f6002b00 | 32 bit
pc: 3041c8 memory read error at f6002c00 | 32 bit
pc: 3041c8 memory read error at f6002d00 | 32 bit
pc: 3041c8 memory read error at f6002e00 | 32 bit
pc: 3041c8 memory read error at f6002f00 | 32 bit
pc: 3041c8 memory read error at f6003000 | 32 bit
pc: 3041c8 memory read error at f6003100 | 32 bit
pc: 3041c8 memory read error at f6003200 | 32 bit
pc: 3041c8 memory read error at f6003300 | 32 bit
pc: 3041c8 memory read error at f6003400 | 32 bit
pc: 3041c8 memory read error at f6003500 | 32 bit
pc: 3041c8 memory read error at f6003600 | 32 bit
pc: 3041c8 memory read error at f6003700 | 32 bit
pc: 3041c8 memory read error at f6003800 | 32 bit
pc: 3041c8 memory read error at f6003900 | 32 bit
pc: 3041c8 memory read error at f6003a00 | 32 bit
pc: 3041c8 memory read error at f6003b00 | 32 bit
pc: 3041c8 memory read error at f6003c00 | 32 bit
pc: 3041c8 memory read error at f6003d00 | 32 bit
pc: 3041c8 memory read error at f6003e00 | 32 bit
pc: 3041c8 memory read error at f6003f00 | 32 bit
pc: 304274 memory read error at f6000000 | 32 bit
pc: 304274 memory read error at f6000100 | 32 bit
pc: 304274 memory read error at f6000200 | 32 bit
pc: 304274 memory read error at f6000300 | 32 bit
pc: 304274 memory read error at f6000400 | 32 bit
pc: 304274 memory read error at f6000500 | 32 bit
pc: 304274 memory read error at f6000600 | 32 bit
pc: 304274 memory read error at f6000700 | 32 bit
pc: 304274 memory read error at f6000800 | 32 bit
pc: 304274 memory read error at f6000900 | 32 bit
pc: 304274 memory read error at f6000a00 | 32 bit
pc: 304274 memory read error at f6000b00 | 32 bit
pc: 304274 memory read error at f6000c00 | 32 bit
pc: 304274 memory read error at f6000d00 | 32 bit
Citer : Posté le 17/11/2022 14:04 | #
C'est ce code-là. gint accède aux données du MMU pour connaître à quelle adresse mémoire l'adresse 08100000 correspond. C'est la zone de mémoire dans laquelle les données de l'add-in ainsi que la pile sont chargés. Plus tard gint se resservira de ces "registres" pour déterminer combien de mémoire est disponible à 08100000.
Émuler ça proprement est tout à fait possible, il faut juste se poser pour comprendre. Il y a ma documentation ici notamment.
Le MMU contient 64 entrées pouvant associer une page (région) de mémoire virtuelle à une page de mémoire physique. Sur ces 64, les 55 premières servent au le code, et dans ton émulateur ce n'est pas un problème, donc on pourra les ignorer et renvoyer des valeurs bidon. Les 8 suivantes gèrent la RAM utilisateur à l'adresse 08100000. La dernière mappe NULL.
Si ton adresse est de la forme 0xf6...... ou 0xf7...... alors gint est en train d'accéder aux informations sur ces 64 entrées. Il faut donc répondre de façon appropriée. D'abord tu détectes les adresses concernées et tu calcules le numéro de l'entrée, E :
int top8 == (addr >> 24) & 0xff;
if(top8 == 0xf6 || top8 == 0xf7) {
int E = (addr >> 8) & 0x3f; /* 0 ≤ E < 64 */
/* (le code ci-dessous va ici) */
}
Pour chaque entrée il y a un morceau "adresse" et un morceau "données" qu'on distingue selon si l'adresse d'accès était en 0xf6 ou en 0xf7. Commençons par le plus simple, le côté "adresse". La valeur à renvoyer ici contient 4 composants que tu peux retrouver dans la structure utlb_addr_t dans <gint/mpu/mmu.h>.
int VPN, D=0, V=1, ASID=0;
uin32_t virt_addr;
if(E < 55)
virt_addr = 0x00300000 + 4096 * E;
else if(E >= 55 && E < 63)
virt_addr = 0x08100000 + 4096 * (E - 55);
else if(E == 63)
virt_addr = 0;
VPN = virt_addr >> 10;
return (VPN << 10) | (D << 9) | (V << 8) | ASID;
}
Le VPN indique l'adresse virtuelle à mapper. Pour les pages 0 à 54 gint ne s'en sert pas donc on met 0 ; pour les pages 55 à 62 c'est 08100000 et successeurs, pour la page 3 c'est NULL. Le reste tu n'as pas trop besoin de savoir ce que c'est.
Le côté "données" donnes des informations en plus, que tu peux voir dans la structure utlb_data_t dans le même header. Là aussi il y a pas mal de champs inutiles donc je ne détaille pas le rôle. Le seul qui est important ici c'est le PPN qui indique l'adresse physique correspondante.
int PPN, V=1, SZ=1, PR=3, C=1, D=0, SH=0, WT=0;
int phys_addr;
if(E < 55)
phys_addr = 0;
else if(E >= 55 && E < 63)
phys_addr = 0x08048000; /* Graph 35+E II ; pour une Graph 75+E, mettre 0x0801c000 */
else if(E == 63)
phys_addr = 0;
PPN = phys_addr >> 10;
return (PPN << 10) | (V << 8) | ((SZ >> 1) << 7) | (PR << 5) | ((SZ & 1) << 4) | (C << 3) | (D << 2) | (SH << 1) | WT;
}
Donc ici ce qu'on est en train de dire c'est que :
Voilà je pense que j'ai fait le tour. gint n'écrit jamais à cet endroit donc tu peux ignorer les écritures. Note que tout ça c'est SH4 seulement, sur SH3 le même concept existe mais toutes les adresses et les structures sont différentes.
Citer : Posté le 17/11/2022 15:02 | #
ok merci. je vais essayer de réécrire tout le système de mémoire: un grand tableau d'octet unique et un système de mappage. plus je le fait tôt plus ce sera facile.
Citer : Posté le 17/11/2022 15:08 | #
ça marche comment le mappage? c'est plein de petits tableaux de 4ko?
Citer : Posté le 17/11/2022 20:26 | #
ok merci. je vais essayer de réécrire tout le système de mémoire: un grand tableau d'octet unique et un système de mappage. plus je le fait tôt plus ce sera facile.
Ce ne serait pas tout à fait fidèle, puisqu'en fait la mémoire est composé de plusieurs morceaux un peu éparpillés... je ne suis pas sûr que tu puisses faire beaucoup mieux que ce que tu as déjà.
ça marche comment le mappage? c'est plein de petits tableaux de 4ko?
J'ai un bout de tutoriel entier qui explique tout l'histoire proprement, que tu peux voir dans ce post.
Pour faire simple, le MMU associe des pages de mémoire virtuelle à des pages de mémoire physique. Une "page" c'est juste une zone de mémoire, et la taille peut varier. Il se trouve que sur la Graph 35+E II seules des pages de 4 kio sont utilisées (SZ=1).
La mémoire physique est bien en gros blocs, eg. de 8 Mio pour la ROM et de 512 kio pour la RAM. Il n'y a pas tant de "tableaux" de 4 kio, il y a juste une association entre 4 kio de pointeurs et 4 kio de mémoire physique. (Autrement dit, dans ton émulateur, ne crée pas la ROM et la RAM comme des paquets de tableaux de 4 kio, ce serait incorrect.)