Source

OCaml-Chip8 / src / chip8.ml

Full commit
Pierre Surply 580b59b 








































































































































































































































































(*
** chip8.ml for OCaml-Chip8 in /home/surply_p
** 
** Made by Pierre Surply
** <pierre.surply@gmail.com>
** 
** Started on  Sat Aug  4 21:06:50 2012 Pierre Surply
** Last update Sun Aug  5 18:11:13 2012 Pierre Surply
*)

open Opcode
open Display
open Events

let _ = Random.self_init ()

let mem_size =		0xFFF
let start_addr =	0x200

type t_chip8 =
    {
      mutable mem :	int array;
      mutable v:	int array;
      mutable i:	int;
      mutable pc:	int;
      mutable sp:	int;
      mutable stack:	int array;
      mutable dt:	int;
      mutable st:	int
    }

let chip8 = 
{
  mem =	[||];
  v = [||];
  i = 0;
  pc = 0;
  sp = 0;
  stack = [||];
  dt = 0;
  st = 0
}

let init_chip8 () = 
  begin
    chip8.mem <- Array.make mem_size 0;
    chip8.v <- Array.make 16 0;
    chip8.i <- 0;
    chip8.pc <- start_addr;
    chip8.sp <- 0;
    chip8.stack <- Array.make 16 0;
    chip8.dt <- 0;
    chip8.st <- 0;
    init_opcodes ()
  end

let count () =
  if chip8.dt > 0 then
    chip8.dt <- chip8.dt - 1;
  if chip8.st > 0 then
    chip8.st <- chip8.st - 1

let print_debug () =
  let _ = Sys.command "clear" in
  print_string "*** OCaml-Chip8 Debug ***\n\n";
  for i=0 to 0xF do
    Printf.printf "V%X: %02X " i chip8.v.(i)
  done;
  print_newline ();
  Printf.printf "I: %02X SP: %X DT: %02X ST: %02X\n" chip8.i chip8.sp chip8.dt chip8.st;
  Printf.printf "PC: %03X  -- Mem : %02X%02X [ %02X%02X ] %02X%02X %02X%02X %02X%02X %02X%02X" 
    chip8.pc
    chip8.mem.(chip8.pc - 2)
    chip8.mem.(chip8.pc - 1)
    chip8.mem.(chip8.pc)
    chip8.mem.(chip8.pc + 1)
    chip8.mem.(chip8.pc + 2)
    chip8.mem.(chip8.pc + 3)
    chip8.mem.(chip8.pc + 4)
    chip8.mem.(chip8.pc + 5)
    chip8.mem.(chip8.pc + 6)
    chip8.mem.(chip8.pc + 7)
    chip8.mem.(chip8.pc + 8)
    chip8.mem.(chip8.pc + 9);
  print_newline ()

let getopcode () = 
  (chip8.mem.(chip8.pc) lsl 8) + chip8.mem.(chip8.pc+1)

let check_overflow x =
  if chip8.v.(x) > 0xFF then
    begin
      chip8.v.(x) <- chip8.v.(x) - 0x100;
      chip8.v.(0xF) <- 1
    end
  else
    chip8.v.(0xF) <- 0

let cls () = 
  clear_screen()

let ret () =
  if chip8.sp > 0 then
    begin
      chip8.sp <- chip8.sp - 1;
      chip8.pc <- chip8.stack.(chip8.sp)
    end

let jmp_addr nnn =
  chip8.pc <- nnn-2

let call_addr nnn =
  chip8.stack.(chip8.sp) <- chip8.pc;
  if chip8.sp < 15 then
    chip8.sp <- chip8.sp + 1;
  jmp_addr nnn

let se_vx_byte x kk = 
  if chip8.v.(x) = kk then
    chip8.pc <- chip8.pc + 2

let sne_vx_byte x kk = 
  if chip8.v.(x) != kk then
    chip8.pc <- chip8.pc + 2

let se_vx_vy x y =
  if chip8.v.(x) = chip8.v.(y) then
    chip8.pc <- chip8.pc + 2

let ld_vx_byte x kk =
  chip8.v.(x) <- kk

let add_vx_byte x kk =
  chip8.v.(x) <- chip8.v.(x) + kk;
  check_overflow x

let ld_vx_vy x y =
  chip8.v.(x) <- chip8.v.(y)

let or_vx_vy x y =
  chip8.v.(x) <- chip8.v.(x) lor chip8.v.(y)

let and_vx_vy x y =
  chip8.v.(x) <- chip8.v.(x) land chip8.v.(y)

let xor_vx_vy x y =
  chip8.v.(x) <- chip8.v.(x) lxor chip8.v.(y)

let add_vx_vy x y =
  chip8.v.(x) <- chip8.v.(x) + chip8.v.(y);
  check_overflow x

let sub_vx_vy x y =
  if chip8.v.(x) > chip8.v.(y) then
      chip8.v.(0xF) <- 1
  else
    chip8.v.(0xF) <- 0;
  chip8.v.(x) <- chip8.v.(x) - chip8.v.(y)

let shr_vx_vy x y =
  if chip8.v.(x) mod 2 = 1 then
    chip8.v.(0xF) <- 1
  else
    chip8.v.(0xF) <- 0;
  chip8.v.(x) <- chip8.v.(y) / 2

let subn_vx_vy x y =
  if chip8.v.(x) < chip8.v.(y) then
    begin
      chip8.v.(0xF) <- 1
    end
  else
    chip8.v.(0xF) <- 0;
  chip8.v.(x) <- chip8.v.(y) - chip8.v.(x)

let shl_vx_vy x y =
  if (chip8.v.(x) lsr 7) = 1 then
    chip8.v.(0xF) <- 1
  else
    chip8.v.(0xF) <- 0;
  chip8.v.(x) <- chip8.v.(x) * 2

let sne_vx_vy x y =
  if chip8.v.(x) != chip8.v.(y) then
    chip8.pc <- chip8.pc + 2

let ld_i_addr nnn =
  chip8.i <- nnn

let jp_v0_addr nnn =
  chip8.pc <- chip8.v.(0) + nnn

let rnd_vx_byte x kk =
  chip8.v.(x) <- (Random.int 256) land kk

let drw_vx_vy_nibble x y n = 
  (*chip8.v.(0xF) <- 0;
  for k = 0 to n-1 do
    let code = chip8.mem.(chip8.i+k) in
    let py = (chip8.v.(y)+k) mod h in
    for j = 0 to 7 do
      let px = (chip8.v.(x)+j) mod w in
      let b = code land (1 lsl (7-j)) != 0 in
      let lp = display.pixels.(px + py*w) in
      display.pixels.(px + py*w) <- b;
      if display.pixels.(px + py*w) != lp then
	chip8.v.(0xF) <- 1
    done
  done*)
  chip8.v.(0xF) <- 0;
  for k = 0 to n-1 do
    let code = chip8.mem.(chip8.i+k) in
    let y = (chip8.v.(y)+k) mod h in
    for j = 0 to 7 do
      let x = (chip8.v.(x)+j) mod w in
      if (code land (1 lsl (7-j))) != 0 then
	if display.pixels.(x + y*w) then
	  begin
	    display.pixels.(x + y*w) <- false;
	    chip8.v.(0xF) <- 1
	  end
	else
	  display.pixels.(x + y*w) <- true
    done
  done

let skp_vx x =
  if events.keys.(chip8.v.(x)) then
    chip8.pc <- chip8.pc + 2

let sknp_vx x =
  if not (events.keys.(chip8.v.(x))) then
    chip8.pc <- chip8.pc + 2

let ld_vx_dt x =
  chip8.v.(x) <- chip8.dt

let ld_vx_k x =
  chip8.v.(x) <- wait_events ()

let ld_dt_vx x =
  chip8.dt <- chip8.v.(x)

let ld_st_vx x =
  chip8.st <- chip8.v.(x)

let add_i_vx x =
  chip8.i <- chip8.i + chip8.v.(x)

let ld_f_vx x = 
  chip8.i <- chip8.v.(x) * 5

let ld_b_vx x =
  chip8.mem.(chip8.i) <- chip8.v.(x) / 100;
  chip8.mem.(chip8.i + 1) <- (chip8.v.(x) / 10) mod 10;
  chip8.mem.(chip8.i + 2) <- chip8.v.(x) mod 10

let ld_mem_vx x = 
  for i = 0 to x do
    chip8.mem.(chip8.i + i) <- chip8.v.(i)
  done

let ld_vx_mem x =
  for i = 0 to x do
    chip8.v.(i) <- chip8.mem.(chip8.i + i)
  done