view src/console/Gb_Cpu.h @ 952:87666f9bf6d0 trunk

[svn] Upstream commit "Vastly enhanced generic Protracker player and modified loaders accordingly. Copl now supports a getchip() method. A2M loader enhanced for OPL3 features." manually applied by decoding the actual changes from an ocean of whitespace damage. It compiles, but do test it.
author chainsaw
date Fri, 13 Apr 2007 09:09:50 -0700
parents 986f098da058
children
line wrap: on
line source

// Nintendo Game Boy CPU emulator
// Treats every instruction as taking 4 cycles

// Game_Music_Emu 0.5.2
#ifndef GB_CPU_H
#define GB_CPU_H

#include "blargg_common.h"
#include "blargg_endian.h"

typedef unsigned gb_addr_t; // 16-bit CPU address

class Gb_Cpu {
	enum { clocks_per_instr = 4 };
public:
	typedef BOOST::uint8_t uint8_t;
	
	// Clear registers and map all pages to unmapped
	void reset( void* unmapped = 0 );
	
	// Map code memory (memory accessed via the program counter). Start and size
	// must be multiple of page_size.
	enum { page_size = 0x2000 };
	void map_code( gb_addr_t start, unsigned size, void* code );
	
	uint8_t* get_code( gb_addr_t );
	
	// Push a byte on the stack
	void push_byte( int );
	
	// Game Boy Z80 registers. *Not* kept updated during a call to run().
	struct core_regs_t {
	#if BLARGG_BIG_ENDIAN
		uint8_t b, c, d, e, h, l, flags, a;
	#else
		uint8_t c, b, e, d, l, h, a, flags;
	#endif
	};
	
	struct registers_t : core_regs_t {
		long pc; // more than 16 bits to allow overflow detection
		BOOST::uint16_t sp;
	};
	registers_t r;
	
	// Interrupt enable flag set by EI and cleared by DI
	//bool interrupts_enabled; // unused
	
	// Base address for RST vectors (normally 0)
	gb_addr_t rst_base;
	
	// If CPU executes opcode 0xFF at this address, it treats as illegal instruction
	enum { idle_addr = 0xF00D };
	
	// Run CPU for at least 'count' cycles and return false, or return true if
	// illegal instruction is encountered.
	bool run( blargg_long count );
	
	// Number of clock cycles remaining for most recent run() call
	blargg_long remain() const { return state->remain * clocks_per_instr; }
	
	// Can read this many bytes past end of a page
	enum { cpu_padding = 8 };
	
public:
	Gb_Cpu() : rst_base( 0 ) { state = &state_; }
	enum { page_shift = 13 };
	enum { page_count = 0x10000 >> page_shift };
private:
	// noncopyable
	Gb_Cpu( const Gb_Cpu& );
	Gb_Cpu& operator = ( const Gb_Cpu& );
	
	struct state_t {
		uint8_t* code_map [page_count + 1];
		blargg_long remain;
	};
	state_t* state; // points to state_ or a local copy within run()
	state_t state_;
	
	void set_code_page( int, uint8_t* );
};

inline BOOST::uint8_t* Gb_Cpu::get_code( gb_addr_t addr )
{
	return state->code_map [addr >> page_shift] + addr
	#if !BLARGG_NONPORTABLE
		% (unsigned) page_size
	#endif
	;
}

#endif