Basic support for CPU opcodes.
Support for 2 opcodes: nop and jump. These are the first opcodes encountered in Super Mario Land.
This commit is contained in:
		
							parent
							
								
									fa09906bcb
								
							
						
					
					
						commit
						b2c7e7b947
					
				
					 3 changed files with 80 additions and 27 deletions
				
			
		
							
								
								
									
										68
									
								
								src/cpu.ml
									
										
									
									
									
								
							
							
						
						
									
										68
									
								
								src/cpu.ml
									
										
									
									
									
								
							|  | @ -1,26 +1,68 @@ | ||||||
| (** http://bgb.bircd.org/pandocs.htm#cpuregistersandflags *) | open Printf | ||||||
|  | 
 | ||||||
|  | (** http://bgb.bircd.org/pandocs.htm#cpuregistersandflags | ||||||
|  |     http://gameboy.mongenel.com/dmg/lesson1.html *) | ||||||
| 
 | 
 | ||||||
| type registers = { | type registers = { | ||||||
|   a : char; (* accumulator *) |   mutable a : char; (* accumulator *) | ||||||
|   b : char; |   mutable f : char; (* flags *) | ||||||
|   c : char; |   mutable b : char; | ||||||
|   d : char; |   mutable c : char; | ||||||
|   e : char; |   mutable d : char; | ||||||
|   h : char; |   mutable e : char; | ||||||
|   l : char; |   mutable h : char; | ||||||
|  |   mutable l : char; | ||||||
| 
 | 
 | ||||||
|   sp : int; (* stack pointer *) |   mutable sp : int; (* stack pointer *) | ||||||
|   pc : int; (* program counter *) |   mutable pc : int; (* program counter *) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type flags = { | (* type flags = { | ||||||
|   z  : bool; (* zero *) |   z  : bool; (* zero *) | ||||||
|   n  : bool; (* substraction *) |   n  : bool; (* substraction *) | ||||||
|   h  : bool; (* half-carry *) |   h  : bool; (* half-carry *) | ||||||
|   cy : bool; (* carry *) |   cy : bool; (* carry *) | ||||||
| } | } *) | ||||||
| 
 | 
 | ||||||
| type t = { | type t = { | ||||||
|   reg : registers; |   reg : registers; | ||||||
|   flags : flags; |   mutable cycles : int; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | (** http://bgb.bircd.org/pandocs.htm#powerupsequence *) | ||||||
|  | let init_registers = | ||||||
|  |   { | ||||||
|  |     a = '\x00'; | ||||||
|  |     f = '\x00'; | ||||||
|  |     b = '\x00'; | ||||||
|  |     c = '\x00'; | ||||||
|  |     d = '\x00'; | ||||||
|  |     e = '\x00'; | ||||||
|  |     h = '\x00'; | ||||||
|  |     l = '\x00'; | ||||||
|  |     sp = 0xFFFE; | ||||||
|  |     pc = 0x0100; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | let init_cpu = | ||||||
|  |   { reg = init_registers; cycles = 0 } | ||||||
|  | 
 | ||||||
|  | let inc_pc cpu count = | ||||||
|  |   cpu.reg.pc <- cpu.reg.pc + count | ||||||
|  | 
 | ||||||
|  | let inc_cycles cpu count = | ||||||
|  |   cpu.cycles <- cpu.cycles + count | ||||||
|  | 
 | ||||||
|  | let read_2B b addr = | ||||||
|  |   let low = Bytes.get b addr in | ||||||
|  |   let high = Bytes.get b (addr + 1) in | ||||||
|  |   (int_of_char high) * 256 + (int_of_char low) | ||||||
|  | 
 | ||||||
|  | (** http://imrannazar.com/GameBoy-Z80-Opcode-Map *) | ||||||
|  | let run cpu (cartridge: Cartridge.t) = | ||||||
|  | (*  Hexa.print_slice cartridge.full_rom cpu.reg.pc (cpu.reg.pc + 7) ~width:16; *) | ||||||
|  |   match Bytes.get cartridge.full_rom cpu.reg.pc with | ||||||
|  |   | '\x00' -> printf "  nop\n"; inc_pc cpu 1; inc_cycles cpu 4 | ||||||
|  |   | '\xC3' -> let addr = read_2B cartridge.full_rom (cpu.reg.pc + 1) in | ||||||
|  |               printf "  jp 0x%02x\n" addr; cpu.reg.pc <- addr; inc_cycles cpu 16 | ||||||
|  |   | _ as x -> eprintf "OpCode %02X\n" (int_of_char x); failwith "Unimplemented opcode." | ||||||
|  |  | ||||||
							
								
								
									
										22
									
								
								src/hexa.ml
									
										
									
									
									
								
							
							
						
						
									
										22
									
								
								src/hexa.ml
									
										
									
									
									
								
							|  | @ -1,14 +1,14 @@ | ||||||
| open Printf | open Printf | ||||||
| 
 | 
 | ||||||
| let print_bytes b ?(width=8) = | let rec print_slice ?(width=8) b start last = | ||||||
|  |   if start < last then | ||||||
|  |     let max = min (start + width - 1) last in | ||||||
|  |     for i = start to max do | ||||||
|  |       printf "%02X " (Bytes.get b i |> int_of_char) | ||||||
|  |     done; | ||||||
|  |     print_newline (); | ||||||
|  |     print_slice ~width b (start + width) last | ||||||
|  | 
 | ||||||
|  | let print_bytes ?(width=8) b width = | ||||||
|   let l = Bytes.length b in |   let l = Bytes.length b in | ||||||
|   let rec print_line b start last = |   print_slice ~width b 0 l | ||||||
|     if start < last then |  | ||||||
|       let max = min (start + width - 1) last in |  | ||||||
|       for i = start to max do |  | ||||||
|         printf "%02X " (Bytes.get b i |> int_of_char) |  | ||||||
|       done; |  | ||||||
|       print_newline (); |  | ||||||
|       print_line b (start + width) last |  | ||||||
|   in |  | ||||||
|   print_line b 0 l |  | ||||||
|  |  | ||||||
							
								
								
									
										17
									
								
								src/oboy.ml
									
										
									
									
									
								
							
							
						
						
									
										17
									
								
								src/oboy.ml
									
										
									
									
									
								
							|  | @ -1,5 +1,9 @@ | ||||||
| open Printf | open Printf | ||||||
| 
 | 
 | ||||||
|  | let rec run (cpu: Cpu.t) (cartridge: Cartridge.t) = | ||||||
|  |   Cpu.run cpu cartridge; | ||||||
|  |   run cpu cartridge | ||||||
|  | 
 | ||||||
| (** Power up sequence | (** Power up sequence | ||||||
|     http://bgb.bircd.org/pandocs.htm#powerupsequence *) |     http://bgb.bircd.org/pandocs.htm#powerupsequence *) | ||||||
| let power_up cartridge = | let power_up cartridge = | ||||||
|  | @ -10,12 +14,19 @@ let power_up cartridge = | ||||||
|     print_endline "Valid ROM."; |     print_endline "Valid ROM."; | ||||||
|     printf "Title: %s\n" cartridge.title; |     printf "Title: %s\n" cartridge.title; | ||||||
|     printf "ROM size: %iKB\n" cartridge.rom_size; |     printf "ROM size: %iKB\n" cartridge.rom_size; | ||||||
|     printf "RAM size: %iKB\n" cartridge.ram_size |     printf "RAM size: %iKB\n" cartridge.ram_size; | ||||||
|  | 
 | ||||||
|  |     let cpu = Cpu.init_cpu in | ||||||
|  |     run cpu cartridge | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| let () = | let () = | ||||||
|   if Array.length Sys.argv < 2 |   if Array.length Sys.argv < 2 then | ||||||
|   then print_endline "Please specify a ROM."; |   begin | ||||||
|  |     prerr_endline "Please specify a ROM."; | ||||||
|  |     eprintf "Usage: %s path/to/rom\n" Sys.argv.(0); | ||||||
|  |     exit 1; | ||||||
|  |   end; | ||||||
| 
 | 
 | ||||||
|   let cartridge = Cartridge.read_cartridge Sys.argv.(1) in |   let cartridge = Cartridge.read_cartridge Sys.argv.(1) in | ||||||
|   match cartridge with |   match cartridge with | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue