<commit_before>#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "chip8.h"

#define BYTE3(blob) ((blob & 0x0F00) >> 8)
#define BYTE2(blob) ((blob & 0x00F0) >> 4)
#define BYTE1(blob) ((blob & 0x000F))

chip8_t * chip8_new(void) {
  chip8_t * self = (chip8_t *) malloc(sizeof(chip8_t));

  self->program_counter = 0x200;
  self->index_register  = 0;
  self->stack_pointer   = 0;
  self->sound_timer     = 0;
  self->delay_timer     = 0;
  self->opcode          = 0;

  memcpy(self->memory, chip8_hex_font, sizeof(chip8_hex_font));
  memset(self->registers, 0, sizeof(self->registers));
  memset(self->screen, 0, sizeof(self->screen));
  memset(self->stack, 0, sizeof(self->stack));
  memset(self->keys, 0, sizeof(self->keys));

  srand(time(0));

  return self;
}

void chip8_tick(chip8_t * self) {
  self->opcode = self->memory[PC(self)] << 8 | self->memory[PC(self) + 1];

  switch (self->opcode & 0xF000) {
  case 0x0000:
    switch (self->opcode & 0x00FF) {
    case 0x00E0:
      memset(self->screen, 0, sizeof(self->screen));
      PC(self) += 2;
      break;
    case 0x00EE:
      PC(self) = self->stack[--SP(self)] + 2;
      break;
    default:
      chip8_no_such_opcode(self);
    }
    break;
  case 0x1000:
    PC(self) = self->opcode & 0x0FFF;
    break;
  case 0x2000:
    self->stack[SP(self)++] = PC(self);
    PC(self) = self->opcode & 0x0FFF;
    break;
  case 0x3000:
    (V(self)[BYTE3(self->opcode)] == (self->opcode & 0x00FF))
      ? (PC(self) += 4)
      : (PC(self) += 2);
    break;
  case 0x4000:
    (V(self)[BYTE3(self->opcode)] == (self->opcode & 0x00FF))
      ? (PC(self) += 2)
      : (PC(self) += 4);
    break;
  case 0x5000:
    (V(self)[BYTE3(self->opcode)] == V(self)[BYTE2(self->opcode)])
      ? (PC(self) += 4)
      : (PC(self) += 2);
    break;
  case 0x6000:
    V(self)[BYTE3(self->opcode)] = self->opcode & 0x00FF;
    PC(self) += 2;
    break;
  case 0x7000:
    V(self)[BYTE3(self->opcode)] += self->opcode & 0x00FF;
    PC(self) += 2;
    break;
  case 0x8000:
    switch (self->opcode & 0x000F) {
    case 0x0000:
      V(self)[BYTE3(self->opcode)] = V(self)[BYTE2(self->opcode)];
      PC(self) += 2;
      break;
    case 0x0001:
      V(self)[BYTE3(self->opcode)] |= V(self)[BYTE2(self->opcode)];
      PC(self) += 2;
      break;
    case 0x0002:
      V(self)[BYTE3(self->opcode)] &= V(self)[BYTE2(self->opcode)];
      PC(self) += 2;
      break;
    case 0x0003:
      V(self)[BYTE3(self->opcode)] ^= V(self)[BYTE2(self->opcode)];
      PC(self) += 2;
      break;
    case 0x0004:
      VF(self) = V(self)[BYTE3(self->opcode)] + V(self)[BYTE2(self->opcode)] > 0xFF;
      V(self)[BYTE3(self->opcode)] += V(self)[BYTE2(self->opcode)];
      PC(self) += 2;
      break;
    case 0x0005:
      VF(self) = V(self)[BYTE2(self->opcode)] <= V(self)[BYTE3(self->opcode)];
      V(self)[BYTE3(self->opcode)] -= V(self)[BYTE2(self->opcode)];
      PC(self) += 2;
      break;
    case 0x0006:
      VF(self) = V(self)[BYTE3(self->opcode)] & 1;
      V(self)[BYTE3(self->opcode)] >>= 1;
      PC(self) += 2;
      break;
    case 0x0007:
      VF(self) = V(self)[BYTE3(self->opcode)] <= V(self)[BYTE2(self->opcode)];
      V(self)[BYTE3(self->opcode)] = V(self)[BYTE2(self->opcode)] - V(self)[BYTE3(self->opcode)];
      PC(self) += 2;
      break;
    case 0x000E:
      VF(self) = V(self)[BYTE3(self->opcode)] >> 7;
      V(self)[BYTE3(self->opcode)] <<= 1;
      PC(self) += 2;
      break;
    default:
      chip8_no_such_opcode(self);
    }
    break;
  case 0x9000:
    (V(self)[BYTE3(self->opcode)] == V(self)[BYTE2(self->opcode)])
      ? (PC(self) += 2)
      : (PC(self) += 4);
    break;
  case 0xA000:
    I(self) = self->opcode & 0x0FFF;
    PC(self) += 2;
    break;
  case 0xB000:
    PC(self) = V0(self) + (self->opcode & 0x0FFF);
    break;
  case 0xC000:
    V(self)[BYTE3(self->opcode)] = rand() & (self->opcode & 0x00FF);
    PC(self) += 2;
    break;
  case 0xD000:
    {
      uint8_t i, j, row, pixel;
      uint8_t x_coord = V(self)[BYTE3(self->opcode)];
      uint8_t y_coord = V(self)[BYTE2(self->opcode)];
      uint8_t height  = BYTE1(self->opcode);
      uint8_t width   = 8;

      VF(self) = 0;
      for (i = 0; i < height; i++) {
        row = self->memory[I(self) + i];
        for (j = 0; j < width; j++) {
          if (!(pixel = row & (0x80 >> j))) {
            continue;
          }
          if ((32 * (x_coord + j) + (y_coord + i)) > (64 * 32)) {
            continue;
          }
          if (self->screen[32 * (x_coord + j) + (y_coord + i)]) {
            VF(self) = 1;
          }
          self->screen[32 * (x_coord + j) + (y_coord + i)] ^= 1;
        }
      }
    }
    PC(self) += 2;
    break;
  case 0xE000:
    switch (self->opcode & 0xF0FF) {
    case 0xE09E:
      self->keys[V(self)[BYTE3(self->opcode)]]<commit_msg>DRY-up the draw routine<commit_after>#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "chip8.h"

#define BYTE3(blob) ((blob & 0x0F00) >> 8)
#define BYTE2(blob) ((blob & 0x00F0) >> 4)
#define BYTE1(blob) ((blob & 0x000F))

chip8_t * chip8_new(void) {
  chip8_t * self = (chip8_t *) malloc(sizeof(chip8_t));

  self->program_counter = 0x200;
  self->index_register  = 0;
  self->stack_pointer   = 0;
  self->sound_timer     = 0;
  self->delay_timer     = 0;
  self->opcode          = 0;

  memcpy(self->memory, chip8_hex_font, sizeof(chip8_hex_font));
  memset(self->registers, 0, sizeof(self->registers));
  memset(self->screen, 0, sizeof(self->screen));
  memset(self->stack, 0, sizeof(self->stack));
  memset(self->keys, 0, sizeof(self->keys));

  srand(time(0));

  return self;
}

void chip8_tick(chip8_t * self) {
  self->opcode = self->memory[PC(self)] << 8 | self->memory[PC(self) + 1];

  switch (self->opcode & 0xF000) {
  case 0x0000:
    switch (self->opcode & 0x00FF) {
    case 0x00E0:
      memset(self->screen, 0, sizeof(self->screen));
      PC(self) += 2;
      break;
    case 0x00EE:
      PC(self) = self->stack[--SP(self)] + 2;
      break;
    default:
      chip8_no_such_opcode(self);
    }
    break;
  case 0x1000:
    PC(self) = self->opcode & 0x0FFF;
    break;
  case 0x2000:
    self->stack[SP(self)++] = PC(self);
    PC(self) = self->opcode & 0x0FFF;
    break;
  case 0x3000:
    (V(self)[BYTE3(self->opcode)] == (self->opcode & 0x00FF))
      ? (PC(self) += 4)
      : (PC(self) += 2);
    break;
  case 0x4000:
    (V(self)[BYTE3(self->opcode)] == (self->opcode & 0x00FF))
      ? (PC(self) += 2)
      : (PC(self) += 4);
    break;
  case 0x5000:
    (V(self)[BYTE3(self->opcode)] == V(self)[BYTE2(self->opcode)])
      ? (PC(self) += 4)
      : (PC(self) += 2);
    break;
  case 0x6000:
    V(self)[BYTE3(self->opcode)] = self->opcode & 0x00FF;
    PC(self) += 2;
    break;
  case 0x7000:
    V(self)[BYTE3(self->opcode)] += self->opcode & 0x00FF;
    PC(self) += 2;
    break;
  case 0x8000:
    switch (self->opcode & 0x000F) {
    case 0x0000:
      V(self)[BYTE3(self->opcode)] = V(self)[BYTE2(self->opcode)];
      PC(self) += 2;
      break;
    case 0x0001:
      V(self)[BYTE3(self->opcode)] |= V(self)[BYTE2(self->opcode)];
      PC(self) += 2;
      break;
    case 0x0002:
      V(self)[BYTE3(self->opcode)] &= V(self)[BYTE2(self->opcode)];
      PC(self) += 2;
      break;
    case 0x0003:
      V(self)[BYTE3(self->opcode)] ^= V(self)[BYTE2(self->opcode)];
      PC(self) += 2;
      break;
    case 0x0004:
      VF(self) = V(self)[BYTE3(self->opcode)] + V(self)[BYTE2(self->opcode)] > 0xFF;
      V(self)[BYTE3(self->opcode)] += V(self)[BYTE2(self->opcode)];
      PC(self) += 2;
      break;
    case 0x0005:
      VF(self) = V(self)[BYTE2(self->opcode)] <= V(self)[BYTE3(self->opcode)];
      V(self)[BYTE3(self->opcode)] -= V(self)[BYTE2(self->opcode)];
      PC(self) += 2;
      break;
    case 0x0006:
      VF(self) = V(self)[BYTE3(self->opcode)] & 1;
      V(self)[BYTE3(self->opcode)] >>= 1;
      PC(self) += 2;
      break;
    case 0x0007:
      VF(self) = V(self)[BYTE3(self->opcode)] <= V(self)[BYTE2(self->opcode)];
      V(self)[BYTE3(self->opcode)] = V(self)[BYTE2(self->opcode)] - V(self)[BYTE3(self->opcode)];
      PC(self) += 2;
      break;
    case 0x000E:
      VF(self) = V(self)[BYTE3(self->opcode)] >> 7;
      V(self)[BYTE3(self->opcode)] <<= 1;
      PC(self) += 2;
      break;
    default:
      chip8_no_such_opcode(self);
    }
    break;
  case 0x9000:
    (V(self)[BYTE3(self->opcode)] == V(self)[BYTE2(self->opcode)])
      ? (PC(self) += 2)
      : (PC(self) += 4);
    break;
  case 0xA000:
    I(self) = self->opcode & 0x0FFF;
    PC(self) += 2;
    break;
  case 0xB000:
    PC(self) = V0(self) + (self->opcode & 0x0FFF);
    break;
  case 0xC000:
    V(self)[BYTE3(self->opcode)] = rand() & (self->opcode & 0x00FF);
    PC(self) += 2;
    break;
  case 0xD000:
    {
      uint8_t  i, j, row, pixel;
      uint16_t location;
      uint8_t  x_coord = V(self)[BYTE3(self->opcode)];
      uint8_t  y_coord = V(self)[BYTE2(self->opcode)];
      uint8_t  height  = BYTE1(self->opcode);
      uint8_t  width   = 8;

      VF(self) = 0;
      for (i = 0; i < height; i++) {
        row = self->memory[I(self) + i];
        for (j = 0; j < width; j++) {
          if (!(pixel = row & (0x80 >> j))) {
            continue;
          }
          if ((location = 32 * (x_coord + j) + (y_coord + i)) > (64 * 32)) {
            continue;
          }
          if (self->screen[location]) {
            VF(self) = 1;
          }
          self->screen[location] ^= 1;
        }
      }
    }
    PC(self) += 2;
    break;
  case 0xE000:
    switch (self->opcode & 0xF0FF) {
    case 0xE09E:
      self->keys[V(self)[BYTE3(self->opcode)]]
{'fraction_non_alphanumeric': 0.20172290021536252, 'fraction_numerical': 0.06091682904317506, 'mean_word_length': 2.587932303164091, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 191, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '167376', 'n_tokens_mistral': 4296, 'n_tokens_neox': 3977, 'n_words': 699}