Mercurial > audlegacy-plugins
diff src/console/Gb_Cpu.h @ 316:fb513e10174e trunk
[svn] - merge libconsole-blargg into mainline libconsole:
+ obsoletes plugins-ugly:sapplug
author | nenolod |
---|---|
date | Thu, 30 Nov 2006 19:54:33 -0800 |
parents | 3da1b8942b8b |
children | 986f098da058 |
line wrap: on
line diff
--- a/src/console/Gb_Cpu.h Wed Nov 29 14:42:11 2006 -0800 +++ b/src/console/Gb_Cpu.h Thu Nov 30 19:54:33 2006 -0800 @@ -1,103 +1,93 @@ - // Nintendo Game Boy CPU emulator +// Treats every instruction as taking 4 cycles -// Game_Music_Emu 0.3.0 - +// Game_Music_Emu 0.5.1 #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 Gbs_Emu; - -// Game Boy CPU emulator. Currently treats every instruction as taking 4 cycles. class Gb_Cpu { + enum { clocks_per_instr = 4 }; +public: typedef BOOST::uint8_t uint8_t; - enum { page_bits = 8 }; - enum { page_count = 0x10000 >> page_bits }; - uint8_t const* code_map [page_count + 1]; - long remain_; - Gbs_Emu* callback_data; -public: - - Gb_Cpu( Gbs_Emu* ); - - // Memory read/write function types. Reader must return value from 0 to 255. - typedef int (*reader_t)( Gbs_Emu*, gb_addr_t ); - typedef void (*writer_t)( Gbs_Emu*, gb_addr_t, int data ); - // Clear registers, unmap memory, and map code pages to unmapped_page. - void reset( const void* unmapped_page = NULL, reader_t read = NULL, writer_t write = NULL ); - - // Memory mapping functions take a block of memory of specified 'start' address - // and 'size' in bytes. Both start address and size must be a multiple of page_size. - enum { page_size = 1L << page_bits }; + // Clear registers and map all pages to unmapped + void reset( void* unmapped = 0 ); - // Map code memory to 'code' (memory accessed via the program counter) - void map_code( gb_addr_t start, unsigned long size, const void* code ); + // 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 ); - // Map data memory to read and write functions - void map_memory( gb_addr_t start, unsigned long size, reader_t, writer_t ); - - // Access memory as the emulated CPU does. - int read( gb_addr_t ); - void write( gb_addr_t, int data ); - uint8_t* get_code( gb_addr_t ); // non-const to allow debugger to modify 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 registers_t { - gb_addr_t pc; // more than 16 bits to allow overflow detection + 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; - uint8_t flags; - uint8_t a; - uint8_t b; - uint8_t c; - uint8_t d; - uint8_t e; - uint8_t h; - uint8_t l; }; registers_t r; // Interrupt enable flag set by EI and cleared by DI - bool interrupts_enabled; + //bool interrupts_enabled; // unused // Base address for RST vectors (normally 0) gb_addr_t rst_base; - // Reasons that run() returns - enum result_t { - result_cycles, // Requested number of cycles (or more) were executed - result_halt, // PC is at HALT instruction - result_badop // PC is at bad (unimplemented) instruction - }; + // If CPU executes opcode 0xFF at this address, it treats as illegal instruction + enum { idle_addr = 0xF00D }; - // Run CPU for at least 'count' cycles, or until one of the above conditions - // arises. Returns reason for stopping. - result_t run( long count ); + // 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 - long remain() const; + 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& ); - reader_t data_reader [page_count + 1]; // extra entry catches address overflow - writer_t data_writer [page_count + 1]; - void set_code_page( int, uint8_t const* ); + 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 long Gb_Cpu::remain() const +inline BOOST::uint8_t* Gb_Cpu::get_code( gb_addr_t addr ) { - return remain_; + return state->code_map [addr >> page_shift] + addr + #if !BLARGG_NONPORTABLE + % (unsigned) page_size + #endif + ; } #endif -