Эмулятор CHIP-8 не отображает графику, как ожидалось - PullRequest
0 голосов
/ 07 января 2019

Я пытался написать эмулятор CHIP-8 как личный проект, и я застрял в реализации его графики.

На данный момент я пытаюсь реализовать кадровый буфер как массив из 8-битных элементов, где значение каждого элемента должно быть либо 1, либо 0, и устанавливается через XOR, возвращая предыдущее значение указанного элемента вместе с новым. .

Я также попытался написать подпрограмму SDL2, чтобы отобразить ее на экране. Я явно где-то потерпел неудачу, так как все, что он отображает, это половина белого скрена и другой черный, после чего программа перестает отвечать.

Вот инструкция DXYN, как я ее реализовал:

case 0xd:
            {
                gfxflag=1;
                V[0xf]=0;
                cny=(RAM[PC+1]>>4);
                cnx=(((RAM[PC]>>4)<<4)^RAM[PC]);
                //n=((RAM[pc+1] ^ (RAM[pc+1]>>4)))
                //THIS WILL XOR N BYETS OF RAM (N elements of char) INTO 8*N CONSECUTIVE ELEMENTS OF FB LEFT TO RIGHT
                for(gfxcn=0; gfxcn < (((RAM[PC+1]>>4)<<4)^RAM[PC+1]); gfxcn++)
                {
                    FRAMEBUFFER[((cnx*cny)+(8*gfxcn))] = FRAMEBUFFER[((cnx*cny)+(8*gfxcn))] ^ (RAM[I]>>7);
                    FRAMEBUFFER[(((cnx*cny)+1)+(8*gfxcn))] = FRAMEBUFFER[(((cnx*cny)+1)+(8*gfxcn))] ^ (RAM[I+gfxcn]>>6 ^ ((RAM[I+gfxcn]>>7)<<1));
                    FRAMEBUFFER[(((cnx*cny)+2)+(8*gfxcn))] = FRAMEBUFFER[(((cnx*cny)+2)+(8*gfxcn))] ^ (RAM[I+gfxcn]>>5 ^ ((RAM[I+gfxcn]>>6)<<1));
                    FRAMEBUFFER[(((cnx*cny)+3)+(8*gfxcn))] = FRAMEBUFFER[(((cnx*cny)+3)+(8*gfxcn))] ^ (RAM[I+gfxcn]>>4 ^ ((RAM[I+gfxcn]>>5)<<1));
                    FRAMEBUFFER[(((cnx*cny)+4)+(8*gfxcn))] = FRAMEBUFFER[(((cnx*cny)+4)+(8*gfxcn))] ^ (RAM[I+gfxcn]>>3 ^ ((RAM[I+gfxcn]>>4)<<1));
                    FRAMEBUFFER[(((cnx*cny)+5)+(8*gfxcn))] = FRAMEBUFFER[(((cnx*cny)+5)+(8*gfxcn))] ^ (RAM[I+gfxcn]>>2 ^ ((RAM[I+gfxcn]>>3)<<1));
                    FRAMEBUFFER[(((cnx*cny)+6)+(8*gfxcn))] = FRAMEBUFFER[(((cnx*cny)+6)+(8*gfxcn))] ^ (RAM[I+gfxcn]>>1 ^ ((RAM[I+gfxcn]>>2)<<1));
                    FRAMEBUFFER[(((cnx*cny)+7)+(8*gfxcn))] = FRAMEBUFFER[(((cnx*cny)+7)+(8*gfxcn))] ^ (RAM[I+gfxcn] ^ ((RAM[I+gfxcn]>>1)<<1));
                    if (((FRAMEBUFFER[(((cnx*cny)+7)+(8*gfxcn))]) != ((FRAMEBUFFER[(((cnx*cny)+7)+(8*gfxcn))])) ^ ((RAM[I+gfxcn] ^ ((RAM[I+gfxcn]>>1)<<1)))))
                        {
                            V[0xf]=1;
                        }
                }
                PC+=2;
                break;
            }

Вот и код SDL2

gfxflag=0;
for(cnx=0; cnx<64; cnx++)
{
    for(cny=0; cny<32; cny++)
    {
        switch(FRAMEBUFFER[cnx*cny])
        {
            case 0:
                SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
                SDL_RenderDrawPoint(renderer, cnx, cny);
            case 1:
                SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
                SDL_RenderDrawPoint(renderer, cnx, cny);
        }
        SDL_RenderPresent(renderer);
    }
}

Это может иметь или не иметь значение, но я также добавляю всю программу:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include <SDL2/SDL.h>

unsigned short PC=0x200, I=0, STACK[16]={0};
unsigned char V[16], SP=0, DT=0, ST=0, FRAMEBUFFER[64*32]={0};
unsigned char RAM[4096]=
{0xf0, 0x90, 0x90, 0x90, 0xf0,      /* 0 */// 0-4       key 0|map     each font sprite is 8x5 column x row 
0x20, 0x60, 0x20, 0x20, 0x70,       /* 1 */// 5-9       key 1|map     each number is a row, 8 columns wide
0xf0, 0x10, 0xf0, 0x80, 0xf0,       /* 2 */// 10-14     key 2|map     in ram each array element is a row, 8 col/one byte
0xf0, 0x10, 0xf0, 0x10, 0xf0,       /* 3 */// 15-19     key 3|map     total memory occupied by font: 80/0x50 bytes
0x90, 0x90, 0xf0, 0x10, 0x10,       /* 4 */// 20-24     key 4|map 
0xf0, 0x80, 0xf0, 0x10, 0xf0,       /* 5 */// 25-29     key 5|map 
0xf0, 0x80, 0xf0, 0x90, 0xf0,       /* 6 */// 30-34     key 6|map 
0xf0, 0x10, 0x20, 0x40, 0x40,       /* 7 */// 35-39     key 7|map 
0xf0, 0x90, 0xf0, 0x90, 0xf0,       /* 8 */// 40-44     key 8|map 
0xf0, 0x90, 0xf0, 0x10, 0xf0,       /* 9 */// 45-49     key 9|map 
0xf0, 0x90, 0xf0, 0x90, 0x90,       /* A */// 50-54     key 10|map 
0xe0, 0x90, 0xe0, 0x90, 0xe0,       /* B */// 55-59     key 11|map 
0xf0, 0x80, 0x80, 0x80, 0xf0,       /* C */// 60-64     key 12|map 
0xe0, 0x90, 0x90, 0x90, 0xe0,       /* D */// 65-69     key 13|map 
0xf0, 0x80, 0xf0, 0x80, 0xf0,       /* E */// 70-74     key 14|map 
0xf0, 0x80, 0xf0, 0x80, 0x80,       /* F */// 75-79     key 15|map  
0};

unsigned char ponggame[246]=
{0x6A, 0x02 ,0x6B ,0x0C ,0x6C,
0x3F ,0x6D ,0x0C ,0xA2 ,0xEA,
0xDA ,0xB6 ,0xDC ,0xD6 ,0x6E,
0x00 ,0x22 ,0xD4 ,0x66 ,0x03, 
0x68 ,0x02 ,0x60 ,0x60 ,0xF0, 
0x15 ,0xF0 ,0x07 ,0x30 ,0x00, 
0x12 ,0x1A ,0xC7 ,0x17 ,0x77, 
0x08 ,0x69 ,0xFF ,0xA2 ,0xF0, 
0xD6 ,0x71 ,0xA2 ,0xEA ,0xDA, 
0xB6 ,0xDC ,0xD6 ,0x60 ,0x01, 
0xE0 ,0xA1 ,0x7B ,0xFE ,0x60,
0x04 ,0xE0 ,0xA1 ,0x7B ,0x02,
0x60 ,0x1F ,0x8B ,0x02 ,0xDA, 
0xB6 ,0x60 ,0x0C ,0xE0 ,0xA1, 
0x7D ,0xFE ,0x60 ,0x0D ,0xE0, 
0xA1 ,0x7D ,0x02 ,0x60 ,0x1F, 
0x8D ,0x02 ,0xDC ,0xD6 ,0xA2, 
0xF0 ,0xD6 ,0x71 ,0x86 ,0x84, 
0x87 ,0x94 ,0x60 ,0x3F ,0x86,
0x02 ,0x61 ,0x1F ,0x87 ,0x12, 
0x46 ,0x02 ,0x12 ,0x78 ,0x46, 
0x3F ,0x12 ,0x82 ,0x47 ,0x1F, 
0x69 ,0xFF ,0x47 ,0x00 ,0x69, 
0x01 ,0xD6 ,0x71 ,0x12 ,0x2A, 
0x68 ,0x02 ,0x63 ,0x01 ,0x80, 
0x70 ,0x80 ,0xB5 ,0x12 ,0x8A, 
0x68 ,0xFE ,0x63 ,0x0A ,0x80, 
0x70 ,0x80 ,0xD5 ,0x3F ,0x01, 
0x12 ,0xA2 ,0x61 ,0x02 ,0x80, 
0x15 ,0x3F ,0x01 ,0x12 ,0xBA, 
0x80 ,0x15 ,0x3F ,0x01 ,0x12, 
0xC8 ,0x80 ,0x15 ,0x3F ,0x01, 
0x12 ,0xC2 ,0x60 ,0x20 ,0xF0, 
0x18 ,0x22 ,0xD4 ,0x8E ,0x34, 
0x22 ,0xD4 ,0x66 ,0x3E ,0x33, 
0x01 ,0x66 ,0x03 ,0x68 ,0xFE, 
0x33 ,0x01 ,0x68 ,0x02 ,0x12, 
0x16 ,0x79 ,0xFF ,0x49 ,0xFE, 
0x69 ,0xFF ,0x12 ,0xC8 ,0x79, 
0x01 ,0x49 ,0x02 ,0x69 ,0x01, 
0x60 ,0x04 ,0xF0 ,0x18 ,0x76, 
0x01 ,0x46 ,0x40 ,0x76 ,0xFE, 
0x12 ,0x6C ,0xA2 ,0xF2 ,0xFE, 
0x33 ,0xF2 ,0x65 ,0xF1 ,0x29, 
0x64 ,0x14 ,0x65 ,0x00 ,0xD4, 
0x55 ,0x74 ,0x15 ,0xF2 ,0x29, 
0xD4 ,0x55 ,0x00 ,0xEE ,0x80, 
0x80 ,0x80 ,0x80 ,0x80 ,0x80, 
0x80 ,0x00 ,0x00 ,0x00 ,0x00, 
0x00};

 char genflag=0, debugflag=0, imemcounter=0, keybuf, gfxflag;//used to  determine 0nnn//used to toggle debug mode// inst 'f5' and 'f6' gfxcn// used in E insts, retains key//tels interpreter to update screen
 short gfxcn, ldcn, debugcn;    //used in d instruction to aid graphing to framebuffer//used for debug console
short clearcn=0, res8=0, cny=0, cnx=0, cn=0, cn2=0;//used to clear display//used to calculate 8xy5-6 carry according to higher 8 bits//used in d inst x4
short spriteloc[16]={   //stores locations of sprite
00, 05, 10, 15,
20, 25, 30, 35,
40, 45, 50, 55,
60, 65, 70, 75};

int main(int argc, char **argv)
{
init:
for(ldcn=0; ldcn<246; ldcn++)//ROMLOAD
{
    //printf("%x ", RAM[0x200 + ldcn]);
    RAM[0x200+ldcn]=ponggame[ldcn];
    //printf("%x %x ", ldcn, RAM[0x200 + ldcn]);
}
srand(time(NULL));

SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window *window=NULL;
SDL_Renderer *renderer=NULL;
SDL_CreateWindowAndRenderer(64, 32, 0, &window, &renderer);     // surface -> texture -> window

SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
//SDL_RenderClear(renderer);    WHY IS THIS EVEN HERE

emuthread:
returnfromgfx:
while(1)
{
    if(debugflag==1)
    {
        //if(debugcn>=5)
        //{
        //  return 0;
        //}
        //debugcn++;
        printf("%x ", PC);
        printf("%x %x ", RAM[PC], RAM[PC+1]);   //print next instruction to be executed
    }

    if(gfxflag==1)
    {
        goto gfx;
    }
    switch((RAM[PC]>>4))    // CONDITIONAL BASED ON HIGHER 4 BITS OF INSTRUCTION
    {
        case 0x0:
            {
                if(RAM[PC+1]==0xEE) //CONDITIONAL BASED ON SECOND BYTE OF INSTRUCTION
                {
                    PC=STACK[SP];
                    SP--;
                    genflag++;
                }

                if(RAM[PC+1]==0xE0)
                {
                    for(clearcn=0; clearcn<2048; clearcn++)
                    {
                        FRAMEBUFFER[clearcn]=0;
                    }
                    genflag++;
                    PC+=2;
                }

                if(genflag==0)
                {
                    PC = ((((RAM[PC]>>4)<<4) ^ RAM[PC])<<8) ^ RAM[PC+1];
                }

                if(genflag>0)
                {
                    genflag=0;
                }

                break;
            }
        case 0x1:
            {
                PC = ((((RAM[PC]>>4)<<4) ^ RAM[PC])<<8) ^ RAM[PC+1];
                break;
            }
        case 0x2:
            {
                SP++;
                STACK[SP]=PC;
                PC = ((((RAM[PC]>>4)<<4) ^ RAM[PC])<<8) ^ RAM[PC+1];
                break;
            }
        case 0x3:
            {
                if(V[(((RAM[PC]>>4)<<4)^RAM[PC])]==RAM[PC+1])
                {
                    PC+=2;
                }
                PC+=2;
                break;
            }
        case 0x4:
            {
                if(V[(((RAM[PC]>>4)<<4)^RAM[PC])]!=RAM[PC+1])
                {
                    PC+=2;
                }
                PC+=2;
                break;
            }
        case 0x5:
            {
                if(V[(((RAM[PC]>>4)<<4)^RAM[PC])]==(RAM[PC+1]>>4))
                {
                    PC+=2;
                }
                PC+=2;
                break;
            }
        case 0x6:
            {
                V[(((RAM[PC]>>4)<<4)^RAM[PC])]=RAM[PC+1];
                PC+=2;
                break;
            }
        case 0x7:
            {
                V[(((RAM[PC]>>4)<<4)^RAM[PC])] = (RAM[PC+1] + V[(((RAM[PC]>>4)<<4)^RAM[PC])]);
                PC+=2;
                break;
            }
        case 0x8:
            {
                switch((((RAM[PC+1]>>4)<<4)^RAM[PC+1])) //conditional based on lower 4 bits of lower byte
                {
                    case 0x0:
                        {
                            V[(((RAM[PC]>>4)<<4)^RAM[PC])] = (RAM[PC+1]>>4);
                            PC+=2;
                            break;
                        }
                    case 0x1:
                        {
                            V[(((RAM[PC]>>4)<<4)^RAM[PC])] = V[(((RAM[PC]>>4)<<4)^RAM[PC])] | (RAM[PC+1]>>4);
                            PC+=2;
                            break;
                        }
                    case 0x2:
                        {
                            V[(((RAM[PC]>>4)<<4)^RAM[PC])] = V[(((RAM[PC]>>4)<<4)^RAM[PC])] & (RAM[PC+1]>>4);
                            PC+=2;
                            break;
                        }
                    case 0x3:
                        {
                            V[(((RAM[PC]>>4)<<4)^RAM[PC])] = V[(((RAM[PC]>>4)<<4)^RAM[PC])] ^ (RAM[PC+1]>>4);
                            PC+=2;
                            break;
                        }
                    case 0x4:
                        {
                            V[0xf]=0;
                            res8= V[(((RAM[PC]>>4)<<4)^RAM[PC])] + (RAM[PC+1]>>4);
                            if((res8>>8)>0)
                                {
                                    V[0xf]=1;
                                }
                            V[(((RAM[PC]>>4)<<4)^RAM[PC])] = (((res8>>8)<<8)^res8);
                            PC+=2;
                            break;
                        }
                    case 0x5:
                        {
                            V[0xf]=0;
                            if(V[(((RAM[PC]>>4)<<4)^RAM[PC])] > (RAM[PC+1]>>4))
                            {
                                V[0xf]=0;
                            }
                            PC+=2;
                            break;
                        }
                    case 0x6:
                        {
                            V[0xf]=0;
                            if((((V[(((RAM[PC]>>4)<<4)^RAM[PC])]>>1)<<1)^V[(((RAM[PC]>>4)<<4)^RAM[PC])])==1)
                                {
                                    V[0XF]=1;
                                }
                            PC+=2;
                            break;
                        }
                    case 0x7:
                        {
                            V[0xf]=0;
                            if((RAM[PC+1]>>4) > V[(((RAM[PC]>>4)<<4)^RAM[PC])])
                            {
                                V[0xf]=1;
                            }
                            V[(((RAM[PC]>>4)<<4)^RAM[PC])] = (RAM[PC+1]>>4) - V[(((RAM[PC]>>4)<<4)^RAM[PC])];
                            PC+=2;
                            break;
                        }
                    case 0xe:
                        {
                            V[0xf]=0;
                            if((V[(((RAM[PC]>>4)<<4)^RAM[PC])]>>7)==1)
                            {
                                V[0xf]=1;
                            }
                            PC+=2;
                            break;
                        }
                     break;
                }
            }
        case 0x9:
            {
                if(V[(((RAM[PC]>>4)<<4)^RAM[PC])]!=(RAM[PC+1]>>4))
                {
                    PC+=2;
                }
                PC+=2;
                break;
            }
        case 0xa:
            {
                I = ((((RAM[PC]>>4)<<4) ^ RAM[PC])<<8) ^ RAM[PC+1];
                PC+=2;
                break;
            }
        case 0xb:
            {
                PC = (((((RAM[PC]>>4)<<4) ^ RAM[PC])<<8) ^ RAM[PC+1]) + V[0x0];
                PC+=2;
                break;
            }
        case 0xc:
            {
                V[(((RAM[PC]>>4)<<4)^RAM[PC])] = (RAM[PC+1] & (rand() % 256));
                PC+=2;
                break;
            }
        case 0xd:
            {
                gfxflag=1;
                V[0xf]=0;
                cny=(RAM[PC+1]>>4);
                cnx=(((RAM[PC]>>4)<<4)^RAM[PC]);
                //n=((RAM[pc+1] ^ (RAM[pc+1]>>4)))
                //THIS WILL XOR N BYETS OF RAM (N elements of char) INTO 8*N CONSECUTIVE ELEMENTS OF FB LEFT TO RIGHT
                for(gfxcn=0; gfxcn < (((RAM[PC+1]>>4)<<4)^RAM[PC+1]); gfxcn++)
                {
                    FRAMEBUFFER[((cnx*cny)+(8*gfxcn))] = FRAMEBUFFER[((cnx*cny)+(8*gfxcn))] ^ (RAM[I]>>7);
                    FRAMEBUFFER[(((cnx*cny)+1)+(8*gfxcn))] = FRAMEBUFFER[(((cnx*cny)+1)+(8*gfxcn))] ^ (RAM[I+gfxcn]>>6 ^ ((RAM[I+gfxcn]>>7)<<1));
                    FRAMEBUFFER[(((cnx*cny)+2)+(8*gfxcn))] = FRAMEBUFFER[(((cnx*cny)+2)+(8*gfxcn))] ^ (RAM[I+gfxcn]>>5 ^ ((RAM[I+gfxcn]>>6)<<1));
                    FRAMEBUFFER[(((cnx*cny)+3)+(8*gfxcn))] = FRAMEBUFFER[(((cnx*cny)+3)+(8*gfxcn))] ^ (RAM[I+gfxcn]>>4 ^ ((RAM[I+gfxcn]>>5)<<1));
                    FRAMEBUFFER[(((cnx*cny)+4)+(8*gfxcn))] = FRAMEBUFFER[(((cnx*cny)+4)+(8*gfxcn))] ^ (RAM[I+gfxcn]>>3 ^ ((RAM[I+gfxcn]>>4)<<1));
                    FRAMEBUFFER[(((cnx*cny)+5)+(8*gfxcn))] = FRAMEBUFFER[(((cnx*cny)+5)+(8*gfxcn))] ^ (RAM[I+gfxcn]>>2 ^ ((RAM[I+gfxcn]>>3)<<1));
                    FRAMEBUFFER[(((cnx*cny)+6)+(8*gfxcn))] = FRAMEBUFFER[(((cnx*cny)+6)+(8*gfxcn))] ^ (RAM[I+gfxcn]>>1 ^ ((RAM[I+gfxcn]>>2)<<1));
                    FRAMEBUFFER[(((cnx*cny)+7)+(8*gfxcn))] = FRAMEBUFFER[(((cnx*cny)+7)+(8*gfxcn))] ^ (RAM[I+gfxcn] ^ ((RAM[I+gfxcn]>>1)<<1));
                    if (((FRAMEBUFFER[(((cnx*cny)+7)+(8*gfxcn))]) != ((FRAMEBUFFER[(((cnx*cny)+7)+(8*gfxcn))])) ^ ((RAM[I+gfxcn] ^ ((RAM[I+gfxcn]>>1)<<1)))))
                        {
                            V[0xf]=1;
                        }
                }
                PC+=2;
                break;
            }
        case 0xe:
            {
                if(keybuf==V[(((RAM[PC]>>4)<<4)^RAM[PC])])
                {
                    PC+=2;
                }

                if(keybuf!=V[(((RAM[PC]>>4)<<4)^RAM[PC])])
                {
                    PC+=2;
                }

                PC+=2;
                break;
            }
        case 0xf:
            {
                switch(RAM[PC+1]>>4)
                {
                    case 0x0:
                        {
                            if((((RAM[PC+1]>>4)<<4)^RAM[PC+1]>>4)==7)
                            {
                                V[(((RAM[PC]>>4)<<4)^RAM[PC])] = DT;
                            }
                            if((((RAM[PC+1]>>4)<<4)^RAM[PC+1]>>4)==0xa)
                            {
                                goto input;
returnfrominput:                        
                                V[(((RAM[PC]>>4)<<4)^RAM[PC])] = keybuf;
                            }
                            PC+=2;
                            break;
                        }
                    case 0x1:
                        {
                            if((((RAM[PC+1]>>4)<<4)^RAM[PC+1]>>4)==5)
                            {
                                DT = V[(((RAM[PC]>>4)<<4)^RAM[PC])];
                            }
                            if((((RAM[PC+1]>>4)<<4)^RAM[PC+1]>>4)==8)
                            {
                                ST = V[(((RAM[PC]>>4)<<4)^RAM[PC])];
                            }
                            if((((RAM[PC+1]>>4)<<4)^RAM[PC+1]>>4)==0xe)
                            {
                                I = I + V[(((RAM[PC]>>4)<<4)^RAM[PC])];
                            }
                            PC+=2;
                            break;
                        }
                    case 0x2:
                        {
                            I = spriteloc[V[(((RAM[PC]>>4)<<4)^RAM[PC])]];
                            PC+=2;
                            break;
                        }
                    case 0x3:
                        {
                            //mod 100 -> 0xx
                            //then mod 10 -> 00x
                            RAM[I]= ((V[(((RAM[PC]>>4)<<4)^RAM[PC])] ^ ((V[(((RAM[PC]>>4)<<4)^RAM[PC])] % 100) % 10)) - ((V[(((RAM[PC]>>4)<<4)^RAM[PC])] ^ ((V[(((RAM[PC]>>4)<<4)^RAM[PC])] % 100) % 10)) % 100));      //100
                            RAM[I+1]= (((V[(((RAM[PC]>>4)<<4)^RAM[PC])] ^ ((V[(((RAM[PC]>>4)<<4)^RAM[PC])] % 100) % 10)) % 100) / 10);      //10
                            RAM[I+2]= ((V[(((RAM[PC]>>4)<<4)^RAM[PC])] % 100) % 10);    //1
                            PC+=2;
                            break;
                        }
                    case 0x5:
                        {
                            for(imemcounter=0; imemcounter<16; imemcounter++)
                            {
                                RAM[I+imemcounter]=V[imemcounter];
                            }
                            PC+=2;
                            break;
                        }
                    case 0x6:
                        {
                            for(imemcounter=0; imemcounter<16; imemcounter++)
                            {
                                V[imemcounter]=RAM[I+imemcounter];
                            }
                            PC+=2;
                            break;
                        }
                    break;
                }
                break;
            }
    }

    if(DT>0)
    {
        DT--;
    }

    if(ST<0)
    {
        ST--;
    }
}

input:
switch(getch())
{
    case '1':
        keybuf= 1;
    case '2':
        keybuf= 2;
    case '3':
        keybuf= 3;
    case '4':
        keybuf= 12;
    case 'q':
        keybuf= 4;
    case 'w':
        keybuf= 5;
    case 'e':
        keybuf= 6;
    case 'r':
        keybuf= 13;
    case 'a':
        keybuf= 7;
    case 's':
        keybuf= 8;
    case 'd':
        keybuf= 9;
    case 'f':
        keybuf= 14;
    case 'z':
        keybuf= 10;
    case 'x':
        keybuf= 0;
    case 'c':
        keybuf= 11;
    case 'v':
        keybuf= 15;
    default:
        goto input;
}
goto returnfrominput;


gfx:
gfxflag=0;
for(cnx=0; cnx<64; cnx++)
{
    for(cny=0; cny<32; cny++)
    {
        switch(FRAMEBUFFER[cnx*cny])
        {
            case 0:
                SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
                SDL_RenderDrawPoint(renderer, cnx, cny);
            case 1:
                SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
                SDL_RenderDrawPoint(renderer, cnx, cny);
        }
        SDL_RenderPresent(renderer);
    }
}

 goto returnfromgfx;


return 0;
}

После внесения исправлений, предложенных ctx, проблема с цветом, по-видимому, в основном устранена. Тем не менее, программа выводит на экран фигню, или так кажется. Более того, я протестировал код SDL2, заставив его отображать случайные пиксели, и он, кажется, работает, за исключением второй половины, которая по-прежнему черная, но я полагаю, что она на самом деле не имеет отношения к проблеме.

Если подпрограмма способна отрисовывать сама по себе, ошибка должна быть где-то в блоке эмуляции, но я смотрел на нее целыми днями и до сих пор не нашел ее.

...