#define BEGIN do{ #define END }while(0) #define X_C8_PRELUDE \ chip8* c8 = usrdat; \ assert(c8); \ \ if(c8->pc >= sizeof(c8->mem)) \ { \ report(ERR, "CHIP-8: PC(%04X) Overflow!\n", c8->pc); \ c8->running = false; \ } \ \ if(c8->pc & 0x0001) \ { \ report(ERR, "CHIP-8: PC(%04X) is not aligned!\n", c8->pc); \ c8->running = false; \ } #define X_C8_EPILOGUE \ BEGIN \ c8->cycles++; \ if((c8->cycles % C8_CYCLES_PER_FRAME) == 0) \ { \ if(c8->dt) c8->dt--; \ if(c8->st) c8->st--; \ } \ c8->pc += 2; \ END #define X_C8_ILL \ BEGIN \ c8->running = false; \ report(ERR, "Illegal instruction (%04X) @ %04X\n", instr, offset); \ END #define X_C8_CLS \ BEGIN \ int i, lines = lengthof(c8->DISPLAY); \ for(i = 0; i < lines; i++) c8->DISPLAY[i] = 0; \ END #define X_C8_RET \ BEGIN \ c8->pc = c8->STACK[--c8->sp]; \ END #define X_C8_SYS X_C8_ILL #define X_C8_JP \ BEGIN \ c8->pc = nnn - 2; \ END #define X_C8_CALL \ BEGIN \ c8->STACK[c8->sp++] = c8->pc; \ c8->pc = nnn; \ END #define X_C8_LDI \ BEGIN \ c8->i = nnn; \ END #define X_C8_JPV \ BEGIN \ c8->pc = nnn + c8->V[0] - 2; \ END #define X_C8_SEB \ BEGIN \ if(c8->V[x] == kk) c8->pc += 2; \ END #define X_C8_SNEB \ BEGIN \ if(c8->V[x] != kk) c8->pc += 2; \ END #define X_C8_LD \ BEGIN \ c8->V[x] = kk; \ END #define X_C8_ADDB \ BEGIN \ int tmp = (int)c8->V[x] + (int)kk; \ c8->V[x] = tmp & 0xFF; \ END #define X_C8_RND \ BEGIN \ c8->V[x] = (rand() % 255) & kk; \ END #define X_C8_SKP \ BEGIN \ if(c8->keys & c8->V[x]) c8->pc += 2; \ END #define X_C8_SKNP \ BEGIN \ if(!(c8->keys & c8->V[x])) c8->pc += 2; \ END #define X_C8_MVDT \ BEGIN \ c8->V[x] = c8->dt; \ END /* TODO: implement */ #define X_C8_LDK \ BEGIN \ if(!c8->keys) c8->pc -= 2; \ END #define X_C8_LDDT \ BEGIN \ c8->dt = c8->V[x]; \ END #define X_C8_LDST \ BEGIN \ c8->st = c8->V[x]; \ END #define X_C8_ADDI \ BEGIN \ c8->i += c8->V[x]; \ END #define X_C8_HEX \ BEGIN \ usize m = (usize)(c8->RAM); \ usize f = (usize)(c8->FONT); \ c8->i = (f - m) + c8->V[x] * 5; \ END #define X_C8_BCD \ BEGIN \ c8->RAM[c8->i] = c8->V[x] / 100; \ c8->RAM[c8->i + 1] = c8->V[x] % 100 / 10; \ c8->RAM[c8->i + 2] = c8->V[x] % 10; \ END #define X_C8_SAVE \ BEGIN \ u8 i; \ for(i = 0; i < x; i++) c8->RAM[c8->i + i] = c8->V[i]; \ END #define X_C8_RESTORE \ BEGIN \ u8 i; \ for(i = 0; i < x; i++) c8->V[i] = c8->RAM[c8->i + i]; \ END #define X_C8_SE \ BEGIN \ if(c8->V[x] == c8->V[y]) c8->pc += 2; \ END #define X_C8_MOVE \ BEGIN \ c8->V[x] = c8->V[y]; \ END #define X_C8_OR \ BEGIN \ c8->V[x] |= c8->V[y]; \ END #define X_C8_AND \ BEGIN \ c8->V[x] &= c8->V[y]; \ END #define X_C8_XOR \ BEGIN \ c8->V[x] ^= c8->V[y]; \ END #define X_C8_ADD \ BEGIN \ int tmp = (int)c8->V[x] + (int)c8->V[y]; \ c8->V[0xf] = tmp > 255; \ c8->V[x] = tmp; \ END #define X_C8_SUB \ BEGIN \ int tmp = (int)c8->V[x] - (int)c8->V[y]; \ c8->V[0xf] = tmp > 0; \ c8->V[x] = tmp; \ END #define X_C8_SHR \ BEGIN \ c8->V[0xf] = (c8->V[y] & 0x1) ? 1 : 0; \ c8->V[x] = c8->V[y] >> 1; \ END #define X_C8_SUBN \ BEGIN \ int tmp = (int)c8->V[y] - (int)c8->V[x]; \ c8->V[0xf] = tmp > 0; \ c8->V[x] = tmp; \ END #define X_C8_SHL \ BEGIN \ c8->V[0xf] = (c8->V[y] & 0x80) ? 1 : 0; \ c8->V[x] = c8->V[y] << 1; \ END #define X_C8_SNE \ BEGIN \ if(c8->V[x] != c8->V[y]) c8->pc += 2; \ END /* TODO: actually implement */ #define X_C8_DRW \ BEGIN \ u8 l; \ u8 cx = c8->V[x]; \ u8 cy = c8->V[y]; \ \ for(l = 0; l < n; l++) \ c8->DISPLAY[cy + l * cx] ^= c8->RAM[c8->i + l]; \ END c8_decode_generate(exec) #undef BEGIN #undef END #include "undef.c"