Interp SNES

Pile : Java, SableCC
Dernière mise-à-jour : Avril 2021
Dépôt Github
Présentation

Interp SNES est un interpréteur et compilateur de code assembleur 65816 utilisé par la console Super Nintendo (SNES). Il a été conçu comme projet de session dans le cadre d'un cours de création de langages informatiques de mon Baccalauréat en informatique et génie logiciel. Il a été conçu avec SableCC, un générateur de compilateur codé en Java par Étienne Gagnon, qui est aussi coordinateur et enseignant du cours.

Interp SNES n'est pas complet, il peut compiler de texte à binaire une quinzaine d'instructions du 65816 (pour environ 40 variations de celles-ci alors que le langage complet comprend 256 variations d'instructions). Il supporte aussi différents types (booléen, string et int), les étiquettes (labels), étiquettes anonymes (anonymous labels), instructions if, boucles while, plus de 20 opérations arithmétiques, les macros (avec paramètres ou sans paramètre), des lignes de commentaires et plus encore. Le fichier details.pdf comporte une présentation détaillée du projet ainsi que des explications et exemples concernant ses caractéristiques.

Usage

Pour utiliser Interp SNES, il faut en premier lieu compiler les classe Java de la grammaire assembler.sablecc. Pour ce faire il faut utiliser une commande telle que path/to/sablecc assembler.sablecc dans le dossier interp-snes. Il faut ensuite compiler le code java du projet, ce qui dans mon cas était fait avec l'IDE Eclipse. Finalement, pour compiler un exemple dans le dossier interp-snes/exemples, lancer à la racine du dossier interp-snes une commande telle que java -cp bin assembler.Interp exemples/nomdufichier.txt.

Exemples et tests

Le projet contient 5 fichiers d'exemples pour illustrer ce qu'il est possible de faire et 37 fichiers de tests qui peuvent être tous lancés avec la commande ./tests.sh à la racine du dossier interp-snes. Un test compile le code du fichier texte dans le dossier interp-snes/tests et le compare ensuite avec le résultat binaire attendu correspondant dans le dossier interp-snes/expected.

Voici par exemple le test #33 et sa sortie attendue:

Test 33_prog_a

macro macro_a(int var_a, bool var_b) {
    int var_c = 2;

    label_a:
    sta.l {var_c}   // 8F 02 00 00

    namespace nsa {
        label_a:
        if(var_a - var_c > 1 && var_b) {
            sta.b {var_a + var_c}       // 85 06
            lda label_a+{$200000},x     // BF 07 00 20
            bne label_a                 // D0 F8
        }
        lda.w $100000       // AD 00 00
        beq label_b         // F0 1C
        macro_b(var_a);
    }
}

macro macro_b(int var_a) {
    while(var_a > 0) {
        lda.b {$80 + var_a}         // A5 8?
        sta.l {$200000 + var_a}     // 8F 0? 00 20
        var_a = var_a - 1;
    }
}

// déclarations
int var_a = 4;
bool var_b = true;

lda.w {var_a}           // AD 04 00
macro_a(var_a, var_b);
var_a = var_a - 1;
lda.l {var_a}           // AF 03 00
label_b:

Sortie attendue de 33_prog_a avec tests.sh:

Program 33_prog_a
--------------------
000000: AD 04 00
000003: 8F 02 00 00
000007: 85 06
000009: BF 07 00 20
00000D: D0 F8
00000F: AD 00 00
000012: F0 1C
000014: A5 84
000016: 8F 04 00 20
00001A: A5 83
00001C: 8F 03 00 20
000020: A5 82
000022: 8F 02 00 20
000026: A5 81
000028: 8F 01 00 20
00002C: AF 03 00 00
TEST 33_prog_a: PASSED

Interp SNES

Pile : Java, SableCC
Dernière mise-à-jour : Avril 2021
Dépôt Github
Présentation

Interp SNES est un interpréteur et compilateur de code assembleur 65816 utilisé par la console Super Nintendo (SNES). Il a été conçu comme projet de session dans le cadre d'un cours de création de langages informatiques de mon Baccalauréat en informatique et génie logiciel. Il a été conçu avec SableCC, un générateur de compilateur codé en Java par Étienne Gagnon, qui est aussi coordinateur et enseignant du cours.

Interp SNES n'est pas complet, il peut compiler de texte à binaire une quinzaine d'instructions du 65816 (pour environ 40 variations de celles-ci alors que le langage complet comprend 256 variations d'instructions). Il supporte aussi différents types (booléen, string et int), les étiquettes (labels), étiquettes anonymes (anonymous labels), instructions if, boucles while, plus de 20 opérations arithmétiques, les macros (avec paramètres ou sans paramètre), des lignes de commentaires et plus encore. Le fichier details.pdf comporte une présentation détaillée du projet ainsi que des explications et exemples concernant ses caractéristiques.

Usage

Pour utiliser Interp SNES, il faut en premier lieu compiler les classe Java de la grammaire assembler.sablecc. Pour ce faire il faut utiliser une commande telle que path/to/sablecc assembler.sablecc dans le dossier interp-snes. Il faut ensuite compiler le code java du projet, ce qui dans mon cas était fait avec l'IDE Eclipse. Finalement, pour compiler un exemple dans le dossier interp-snes/exemples, lancer à la racine du dossier interp-snes une commande telle que java -cp bin assembler.Interp exemples/nomdufichier.txt.

Exemples et tests

Le projet contient 5 fichiers d'exemples pour illustrer ce qu'il est possible de faire et 37 fichiers de tests qui peuvent être tous lancés avec la commande ./tests.sh à la racine du dossier interp-snes. Un test compile le code du fichier texte dans le dossier interp-snes/tests et le compare ensuite avec le résultat binaire attendu correspondant dans le dossier interp-snes/expected.

Voici par exemple le test #33 et sa sortie attendue:

Test 33_prog_a

macro macro_a(int var_a, bool var_b) {
    int var_c = 2;

    label_a:
    sta.l {var_c}   // 8F 02 00 00

    namespace nsa {
        label_a:
        if(var_a - var_c > 1 && var_b) {
            sta.b {var_a + var_c}       // 85 06
            lda label_a+{$200000},x     // BF 07 00 20
            bne label_a                 // D0 F8
        }
        lda.w $100000       // AD 00 00
        beq label_b         // F0 1C
        macro_b(var_a);
    }
}

macro macro_b(int var_a) {
    while(var_a > 0) {
        lda.b {$80 + var_a}         // A5 8?
        sta.l {$200000 + var_a}     // 8F 0? 00 20
        var_a = var_a - 1;
    }
}

// déclarations
int var_a = 4;
bool var_b = true;

lda.w {var_a}           // AD 04 00
macro_a(var_a, var_b);
var_a = var_a - 1;
lda.l {var_a}           // AF 03 00
label_b:

Sortie attendue de 33_prog_a avec tests.sh:

Program 33_prog_a
--------------------
000000: AD 04 00
000003: 8F 02 00 00
000007: 85 06
000009: BF 07 00 20
00000D: D0 F8
00000F: AD 00 00
000012: F0 1C
000014: A5 84
000016: 8F 04 00 20
00001A: A5 83
00001C: 8F 03 00 20
000020: A5 82
000022: 8F 02 00 20
000026: A5 81
000028: 8F 01 00 20
00002C: AF 03 00 00
TEST 33_prog_a: PASSED