Add fps to main loop
This commit is contained in:
		
							parent
							
								
									fb5eeed6ba
								
							
						
					
					
						commit
						013fd9abe4
					
				
					 3 changed files with 64 additions and 34 deletions
				
			
		
							
								
								
									
										2
									
								
								_tags
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								_tags
									
										
									
									
									
								
							| 
						 | 
					@ -1,2 +1,2 @@
 | 
				
			||||||
true: package(unix), package(graphics), warn(A-40-42)
 | 
					true: package(unix), thread, package(graphics), warn(A-40-42)
 | 
				
			||||||
<test/*>: package(ounit)
 | 
					<test/*>: package(ounit)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										66
									
								
								src/cpu.ml
									
										
									
									
									
								
							
							
						
						
									
										66
									
								
								src/cpu.ml
									
										
									
									
									
								
							| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
open Printf
 | 
					open Printf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let frequence = 4194304
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(** http://bgb.bircd.org/pandocs.htm#cpuregistersandflags
 | 
					(** http://bgb.bircd.org/pandocs.htm#cpuregistersandflags
 | 
				
			||||||
    http://gameboy.mongenel.com/dmg/lesson1.html *)
 | 
					    http://gameboy.mongenel.com/dmg/lesson1.html *)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -133,12 +135,11 @@ let pop_stack cpu mem =
 | 
				
			||||||
  https://github.com/sinamas/gambatte/blob/master/libgambatte/src/cpu.cpp
 | 
					  https://github.com/sinamas/gambatte/blob/master/libgambatte/src/cpu.cpp
 | 
				
			||||||
*)
 | 
					*)
 | 
				
			||||||
let run cpu (mem: Memory.map) =
 | 
					let run cpu (mem: Memory.map) =
 | 
				
			||||||
  printf "\n";
 | 
					 | 
				
			||||||
  print_cpu_state cpu;
 | 
					  print_cpu_state cpu;
 | 
				
			||||||
  let opcode = read_pc_byte cpu mem |> char_of_int in
 | 
					  let opcode = read_pc_byte cpu mem |> char_of_int in
 | 
				
			||||||
(*  Hexa.print_slice cartridge.full_rom cpu.reg.pc (cpu.reg.pc + 7); *)
 | 
					(*  Hexa.print_slice cartridge.full_rom cpu.reg.pc (cpu.reg.pc + 7); *)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let inst = match opcode with
 | 
					  let inst, cycles = match opcode with
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (* 8-bit load *)
 | 
					  (* 8-bit load *)
 | 
				
			||||||
  (* LD   r,(HL) *)
 | 
					  (* LD   r,(HL) *)
 | 
				
			||||||
| 
						 | 
					@ -146,20 +147,20 @@ let run cpu (mem: Memory.map) =
 | 
				
			||||||
              let hl = merge_bytes cpu.reg.l cpu.reg.h in
 | 
					              let hl = merge_bytes cpu.reg.l cpu.reg.h in
 | 
				
			||||||
              cpu.reg.a <- Memory.get mem hl;
 | 
					              cpu.reg.a <- Memory.get mem hl;
 | 
				
			||||||
              inc_cycles cpu 8;
 | 
					              inc_cycles cpu 8;
 | 
				
			||||||
              inst
 | 
					              inst, 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  | '\x36' -> let n = read_pc_byte cpu mem in
 | 
					  | '\x36' -> let n = read_pc_byte cpu mem in
 | 
				
			||||||
              let inst = sprintf "LD \t(HL) 0x%02X" n in
 | 
					              let inst = sprintf "LD \t(HL) 0x%02X" n in
 | 
				
			||||||
              let hl = merge_bytes cpu.reg.l cpu.reg.h in
 | 
					              let hl = merge_bytes cpu.reg.l cpu.reg.h in
 | 
				
			||||||
              Memory.set mem hl (char_of_int n);
 | 
					              Memory.set mem hl (char_of_int n);
 | 
				
			||||||
              inc_cycles cpu 12;
 | 
					              inc_cycles cpu 12;
 | 
				
			||||||
              inst
 | 
					              inst, 12
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (* CPU control *)
 | 
					  (* CPU control *)
 | 
				
			||||||
  | '\x00' -> let inst = sprintf "NOP" in
 | 
					  | '\x00' -> let inst = sprintf "NOP" in
 | 
				
			||||||
              inc_cycles cpu 4;
 | 
					              inc_cycles cpu 4;
 | 
				
			||||||
              inst
 | 
					              inst, 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (* jump *)
 | 
					  (* jump *)
 | 
				
			||||||
| 
						 | 
					@ -170,30 +171,34 @@ let run cpu (mem: Memory.map) =
 | 
				
			||||||
              begin
 | 
					              begin
 | 
				
			||||||
                inc_pc cpu (s - 2); (* we read 2 bytes from PC, opcode and n *)
 | 
					                inc_pc cpu (s - 2); (* we read 2 bytes from PC, opcode and n *)
 | 
				
			||||||
                inc_cycles cpu 12;
 | 
					                inc_cycles cpu 12;
 | 
				
			||||||
              end else
 | 
					                inst, 12
 | 
				
			||||||
 | 
					              end else begin
 | 
				
			||||||
                inc_cycles cpu 8;
 | 
					                inc_cycles cpu 8;
 | 
				
			||||||
              inst
 | 
					                inst, 8
 | 
				
			||||||
 | 
					              end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  | '\xC9' -> let inst = sprintf "RET" in
 | 
					  | '\xC9' -> let inst = sprintf "RET" in
 | 
				
			||||||
              cpu.reg.pc <- pop_stack cpu mem;
 | 
					              cpu.reg.pc <- pop_stack cpu mem;
 | 
				
			||||||
              inc_cycles cpu 16;
 | 
					              inc_cycles cpu 16;
 | 
				
			||||||
              inst
 | 
					              inst, 16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  | '\xC0' -> let inst = sprintf "RET \tNZ" in
 | 
					  | '\xC0' -> let inst = sprintf "RET \tNZ" in
 | 
				
			||||||
              if cpu.flag.z = false then
 | 
					              if cpu.flag.z = false then
 | 
				
			||||||
              begin
 | 
					              begin
 | 
				
			||||||
                cpu.reg.pc <- pop_stack cpu mem;
 | 
					                cpu.reg.pc <- pop_stack cpu mem;
 | 
				
			||||||
                inc_cycles cpu 20;
 | 
					                inc_cycles cpu 20;
 | 
				
			||||||
              end else
 | 
					                inst, 20
 | 
				
			||||||
 | 
					              end else begin
 | 
				
			||||||
                inc_cycles cpu 8;
 | 
					                inc_cycles cpu 8;
 | 
				
			||||||
              inst
 | 
					                inst, 8
 | 
				
			||||||
 | 
					              end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  | '\x03' -> let inst = sprintf "INC \tBC" in
 | 
					  | '\x03' -> let inst = sprintf "INC \tBC" in
 | 
				
			||||||
              inc_BC cpu;
 | 
					              inc_BC cpu;
 | 
				
			||||||
              inc_cycles cpu 8;
 | 
					              inc_cycles cpu 8;
 | 
				
			||||||
              inst
 | 
					              inst, 8
 | 
				
			||||||
              
 | 
					              
 | 
				
			||||||
  | '\x05' -> let inst = sprintf "DEC \tB" in
 | 
					  | '\x05' -> let inst = sprintf "DEC \tB" in
 | 
				
			||||||
              let dec = int_of_char(cpu.reg.b) - 1 in
 | 
					              let dec = int_of_char(cpu.reg.b) - 1 in
 | 
				
			||||||
| 
						 | 
					@ -202,18 +207,18 @@ let run cpu (mem: Memory.map) =
 | 
				
			||||||
              cpu.flag.h <- dec < 0; 
 | 
					              cpu.flag.h <- dec < 0; 
 | 
				
			||||||
              cpu.reg.b <- char_of_int @@ if dec >= 0 then dec else 0;
 | 
					              cpu.reg.b <- char_of_int @@ if dec >= 0 then dec else 0;
 | 
				
			||||||
              inc_cycles cpu 4;
 | 
					              inc_cycles cpu 4;
 | 
				
			||||||
              inst
 | 
					              inst, 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  | '\x06' -> let n = read_pc_byte cpu mem in
 | 
					  | '\x06' -> let n = read_pc_byte cpu mem in
 | 
				
			||||||
              let inst = sprintf "LD \tB, 0x%02X" n in
 | 
					              let inst = sprintf "LD \tB, 0x%02X" n in
 | 
				
			||||||
              cpu.reg.b <- char_of_int n;
 | 
					              cpu.reg.b <- char_of_int n;
 | 
				
			||||||
              inc_cycles cpu 8;
 | 
					              inc_cycles cpu 8;
 | 
				
			||||||
              inst
 | 
					              inst, 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  | '\x18' -> let n = read_pc_byte cpu mem in
 | 
					  | '\x18' -> let n = read_pc_byte cpu mem in
 | 
				
			||||||
              let inst = sprintf "JP \t0x%02X" n in
 | 
					              let inst = sprintf "JP \t0x%02X" n in
 | 
				
			||||||
              inc_pc cpu (n - 1); inc_cycles cpu 12;
 | 
					              inc_pc cpu (n - 1); inc_cycles cpu 12;
 | 
				
			||||||
              inst
 | 
					              inst, 12
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  | '\x21' -> let nn = read_pc_2bytes cpu mem in
 | 
					  | '\x21' -> let nn = read_pc_2bytes cpu mem in
 | 
				
			||||||
              let inst = sprintf "LD \tHL, 0x%04X" nn in
 | 
					              let inst = sprintf "LD \tHL, 0x%04X" nn in
 | 
				
			||||||
| 
						 | 
					@ -221,7 +226,7 @@ let run cpu (mem: Memory.map) =
 | 
				
			||||||
              cpu.reg.h <- high;
 | 
					              cpu.reg.h <- high;
 | 
				
			||||||
              cpu.reg.l <- low;
 | 
					              cpu.reg.l <- low;
 | 
				
			||||||
              inc_cycles cpu 12;
 | 
					              inc_cycles cpu 12;
 | 
				
			||||||
              inst
 | 
					              inst, 12
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  | '\x22' -> let inst = sprintf "LDI \t(HL), A" in
 | 
					  | '\x22' -> let inst = sprintf "LDI \t(HL), A" in
 | 
				
			||||||
              let hl = merge_bytes cpu.reg.l cpu.reg.h in
 | 
					              let hl = merge_bytes cpu.reg.l cpu.reg.h in
 | 
				
			||||||
| 
						 | 
					@ -230,7 +235,7 @@ let run cpu (mem: Memory.map) =
 | 
				
			||||||
              cpu.reg.h <- high;
 | 
					              cpu.reg.h <- high;
 | 
				
			||||||
              cpu.reg.l <- low;
 | 
					              cpu.reg.l <- low;
 | 
				
			||||||
              inc_cycles cpu 8;
 | 
					              inc_cycles cpu 8;
 | 
				
			||||||
              inst
 | 
					              inst, 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  | '\x28' -> let n = read_pc_byte cpu mem in
 | 
					  | '\x28' -> let n = read_pc_byte cpu mem in
 | 
				
			||||||
| 
						 | 
					@ -238,9 +243,11 @@ let run cpu (mem: Memory.map) =
 | 
				
			||||||
              if cpu.flag.z = true then
 | 
					              if cpu.flag.z = true then
 | 
				
			||||||
              begin
 | 
					              begin
 | 
				
			||||||
                inc_pc cpu (n - 1); inc_cycles cpu 12;
 | 
					                inc_pc cpu (n - 1); inc_cycles cpu 12;
 | 
				
			||||||
              end else
 | 
					                inst, 12
 | 
				
			||||||
 | 
					              end else begin
 | 
				
			||||||
                inc_cycles cpu 8;
 | 
					                inc_cycles cpu 8;
 | 
				
			||||||
              inst
 | 
					                inst, 8
 | 
				
			||||||
 | 
					              end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  | '\x34' -> let inst = sprintf "INC \t(HL)" in
 | 
					  | '\x34' -> let inst = sprintf "INC \t(HL)" in
 | 
				
			||||||
              let hl = merge_bytes cpu.reg.l cpu.reg.h in
 | 
					              let hl = merge_bytes cpu.reg.l cpu.reg.h in
 | 
				
			||||||
| 
						 | 
					@ -250,65 +257,64 @@ let run cpu (mem: Memory.map) =
 | 
				
			||||||
              cpu.flag.h <- v = 0b00001111;
 | 
					              cpu.flag.h <- v = 0b00001111;
 | 
				
			||||||
              Memory.set mem hl (char_of_int (v + 1));
 | 
					              Memory.set mem hl (char_of_int (v + 1));
 | 
				
			||||||
              inc_cycles cpu 12;
 | 
					              inc_cycles cpu 12;
 | 
				
			||||||
              inst
 | 
					              inst, 12
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  | '\x3E' -> let n = read_pc_byte cpu mem in
 | 
					  | '\x3E' -> let n = read_pc_byte cpu mem in
 | 
				
			||||||
              let inst = sprintf "LD \tA, 0x%02X" n in
 | 
					              let inst = sprintf "LD \tA, 0x%02X" n in
 | 
				
			||||||
              cpu.reg.a <- char_of_int n;
 | 
					              cpu.reg.a <- char_of_int n;
 | 
				
			||||||
              inc_cycles cpu 8;
 | 
					              inc_cycles cpu 8;
 | 
				
			||||||
              inst
 | 
					              inst, 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  | '\xAF' -> let inst = sprintf "XOR \tA, A" in
 | 
					  | '\xAF' -> let inst = sprintf "XOR \tA, A" in
 | 
				
			||||||
              let int_A = int_of_char cpu.reg.a in
 | 
					              let int_A = int_of_char cpu.reg.a in
 | 
				
			||||||
              cpu.reg.a <- char_of_int @@ int_A lxor int_A;
 | 
					              cpu.reg.a <- char_of_int @@ int_A lxor int_A;
 | 
				
			||||||
              inc_cycles cpu 4;
 | 
					              inc_cycles cpu 4;
 | 
				
			||||||
              inst
 | 
					              inst, 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  | '\xC3' -> let addr = read_pc_2bytes cpu mem in
 | 
					  | '\xC3' -> let addr = read_pc_2bytes cpu mem in
 | 
				
			||||||
              let inst = sprintf "JP \t0x%04X" addr in
 | 
					              let inst = sprintf "JP \t0x%04X" addr in
 | 
				
			||||||
              cpu.reg.pc <- addr; inc_cycles cpu 16;
 | 
					              cpu.reg.pc <- addr; inc_cycles cpu 16;
 | 
				
			||||||
              inst
 | 
					              inst, 16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  | '\xE0' -> let n = read_pc_byte cpu mem in
 | 
					  | '\xE0' -> let n = read_pc_byte cpu mem in
 | 
				
			||||||
              let inst = sprintf "LDH \t(0xFF%02X), A" n in
 | 
					              let inst = sprintf "LDH \t(0xFF%02X), A" n in
 | 
				
			||||||
              Memory.set mem (0xFF00 + n) cpu.reg.a;
 | 
					              Memory.set mem (0xFF00 + n) cpu.reg.a;
 | 
				
			||||||
              inc_cycles cpu 12;
 | 
					              inc_cycles cpu 12;
 | 
				
			||||||
              inst
 | 
					              inst, 12
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  | '\xEA' -> let addr = read_pc_2bytes cpu mem in
 | 
					  | '\xEA' -> let addr = read_pc_2bytes cpu mem in
 | 
				
			||||||
              let inst = sprintf "LD \t(0X%04X), A" addr in
 | 
					              let inst = sprintf "LD \t(0X%04X), A" addr in
 | 
				
			||||||
              Memory.set mem addr cpu.reg.a;
 | 
					              Memory.set mem addr cpu.reg.a;
 | 
				
			||||||
              inc_cycles cpu 16;
 | 
					              inc_cycles cpu 16;
 | 
				
			||||||
              inst
 | 
					              inst, 16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  | '\xF0' -> let n = read_pc_byte cpu mem in
 | 
					  | '\xF0' -> let n = read_pc_byte cpu mem in
 | 
				
			||||||
              let inst = sprintf "LDH \tA, (0xFF%02X)" n in
 | 
					              let inst = sprintf "LDH \tA, (0xFF%02X)" n in
 | 
				
			||||||
              cpu.reg.a <- Memory.get mem (0xFF00 + n);
 | 
					              cpu.reg.a <- Memory.get mem (0xFF00 + n);
 | 
				
			||||||
              inc_cycles cpu 12;
 | 
					              inc_cycles cpu 12;
 | 
				
			||||||
              inst
 | 
					              inst, 12
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  | '\xF3' -> let inst = sprintf "DI" in
 | 
					  | '\xF3' -> let inst = sprintf "DI" in
 | 
				
			||||||
              (* fixme *)
 | 
					              (* fixme *)
 | 
				
			||||||
              inc_cycles cpu 4;
 | 
					              inc_cycles cpu 4;
 | 
				
			||||||
              inst
 | 
					              inst, 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  | '\xFE' -> let n = read_pc_byte cpu mem in
 | 
					  | '\xFE' -> let n = read_pc_byte cpu mem in
 | 
				
			||||||
              let inst = sprintf "CP \t0x%02X" n in
 | 
					              let inst = sprintf "CP \t0x%02X" n in
 | 
				
			||||||
              cmp_A cpu n;
 | 
					              cmp_A cpu n;
 | 
				
			||||||
              inc_cycles cpu 8;
 | 
					              inc_cycles cpu 8;
 | 
				
			||||||
              inst
 | 
					              inst, 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  | '\xFB' -> let inst = sprintf "EI" in
 | 
					  | '\xFB' -> let inst = sprintf "EI" in
 | 
				
			||||||
              (* enable interrupts, IME=1 *)
 | 
					              (* enable interrupts, IME=1 *)
 | 
				
			||||||
              inc_cycles cpu 4;
 | 
					              inc_cycles cpu 4;
 | 
				
			||||||
              inst
 | 
					              inst, 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  |  x -> eprintf "opcode 0x%02X\n" (int_of_char x);
 | 
					  |  x -> eprintf "opcode 0x%02X\n" (int_of_char x);
 | 
				
			||||||
          eprintf "#cycles: %d\n" cpu.cycles;
 | 
					          eprintf "#cycles: %d\n" cpu.cycles;
 | 
				
			||||||
          failwith "Unimplemented opcode."
 | 
					          failwith "Unimplemented opcode."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  in
 | 
					  in
 | 
				
			||||||
 | 
					  inst, cycles
 | 
				
			||||||
  printf "[Instruction] %s\n" inst
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										30
									
								
								src/oboy.ml
									
										
									
									
									
								
							
							
						
						
									
										30
									
								
								src/oboy.ml
									
										
									
									
									
								
							| 
						 | 
					@ -1,7 +1,31 @@
 | 
				
			||||||
open Printf
 | 
					open Printf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let fps = 60
 | 
				
			||||||
 | 
					let cycles_per_frame = Cpu.frequence / fps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let rec run (cpu: Cpu.t) (mem: Memory.map) (screen: Screen.t) =
 | 
					let rec run (cpu: Cpu.t) (mem: Memory.map) (screen: Screen.t) =
 | 
				
			||||||
  Cpu.run cpu mem;
 | 
					  printf "\n";
 | 
				
			||||||
 | 
					  let start = Unix.gettimeofday () in
 | 
				
			||||||
 | 
					  printf "start %f\n" start;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let rec run_for cpu mem cycles_remaining =
 | 
				
			||||||
 | 
					    if cycles_remaining > 0 then
 | 
				
			||||||
 | 
					    begin
 | 
				
			||||||
 | 
					      let inst, cycles = Cpu.run cpu mem in
 | 
				
			||||||
 | 
					      printf "[Instruction] %s\n" inst;
 | 
				
			||||||
 | 
					      run_for cpu mem (cycles_remaining - cycles)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  in
 | 
				
			||||||
 | 
					  run_for cpu mem cycles_per_frame;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let stop = Unix.gettimeofday () in
 | 
				
			||||||
 | 
					  let delay = (1. -. (stop -. start)) /. (float_of_int fps) in
 | 
				
			||||||
 | 
					  printf "stop %f\n" stop;
 | 
				
			||||||
 | 
					  printf "delta %f\n" (stop -. start);
 | 
				
			||||||
 | 
					  printf "delay %f\n" delay;
 | 
				
			||||||
 | 
					  flush_all ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if delay > 0. then Thread.delay delay;
 | 
				
			||||||
  run cpu mem screen
 | 
					  run cpu mem screen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(** Power up sequence
 | 
					(** Power up sequence
 | 
				
			||||||
| 
						 | 
					@ -18,9 +42,9 @@ let power_up cartridge =
 | 
				
			||||||
    let mem = Memory.init cartridge in
 | 
					    let mem = Memory.init cartridge in
 | 
				
			||||||
    let screen = Screen.init in
 | 
					    let screen = Screen.init in
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Graphics.open_graph "";
 | 
					    (*Graphics.open_graph "";
 | 
				
			||||||
    Graphics.resize_window Screen.width Screen.height;
 | 
					    Graphics.resize_window Screen.width Screen.height;
 | 
				
			||||||
 | 
					    *)
 | 
				
			||||||
    run cpu mem screen
 | 
					    run cpu mem screen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue