1 // Normal CPU for NSF emulator
2 
3 // $package. http://www.slack.net/~ant/
4 
5 #include "Nsf_Impl.h"
6 
7 #include "blargg_endian.h"
8 
9 #ifdef BLARGG_DEBUG_H
10 	//#define CPU_LOG_START 1000000
11 	//#include "nes_cpu_log.h"
12 	#undef LOG_MEM
13 #endif
14 
15 /* Copyright (C) 2003-2008 Shay Green. This module is free software; you
16 can redistribute it and/or modify it under the terms of the GNU Lesser
17 General Public License as published by the Free Software Foundation; either
18 version 2.1 of the License, or (at your option) any later version. This
19 module is distributed in the hope that it will be useful, but WITHOUT ANY
20 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
22 details. You should have received a copy of the GNU Lesser General Public
23 License along with this module; if not, write to the Free Software Foundation,
24 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
25 
26 #include "blargg_source.h"
27 
28 #ifndef LOG_MEM
29 	#define LOG_MEM( addr, str, data ) data
30 #endif
31 
read_mem(addr_t addr)32 int Nsf_Impl::read_mem( addr_t addr )
33 {
34 	int result = low_ram [addr & (low_ram_size-1)]; // also handles wrap-around
35 	if ( addr & 0xE000 )
36 	{
37 		result = *cpu.get_code( addr );
38 		if ( addr < sram_addr )
39 		{
40 			if ( addr == apu.status_addr )
41 				result = apu.read_status( time() );
42 			else
43 				result = cpu_read( addr );
44 		}
45 	}
46 	return LOG_MEM( addr, ">", result );
47 }
48 
write_mem(addr_t addr,int data)49 void Nsf_Impl::write_mem( addr_t addr, int data )
50 {
51 	(void) LOG_MEM( addr, "<", data );
52 
53 	int offset = addr - sram_addr;
54 	if ( (unsigned) offset < sram_size )
55 	{
56 		sram() [offset] = data;
57 	}
58 	else
59 	{
60 		// after sram because CPU handles most low_ram accesses internally already
61 		int temp = addr & (low_ram_size-1); // also handles wrap-around
62 		if ( !(addr & 0xE000) )
63 		{
64 			low_ram [temp] = data;
65 		}
66 		else
67 		{
68 			int bank = addr - banks_addr;
69 			if ( (unsigned) bank < bank_count )
70 			{
71 				write_bank( bank, data );
72 			}
73 			else if ( (unsigned) (addr - apu.io_addr) < apu.io_size )
74 			{
75 				apu.write_register( time(), addr, data );
76 			}
77 			else
78 			{
79 			#if !NSF_EMU_APU_ONLY
80 				// 0x8000-0xDFFF is writable
81 				int i = addr - 0x8000;
82 				if ( (unsigned) i < fdsram_size && fds_enabled() )
83 					fdsram() [i] = data;
84 				else
85 			#endif
86 				cpu_write( addr, data );
87 			}
88 		}
89 	}
90 }
91 
92 #define READ_LOW(  addr       ) (LOG_MEM( addr, ">", low_ram [addr] ))
93 #define WRITE_LOW( addr, data ) (LOG_MEM( addr, "<", low_ram [addr] = data ))
94 
95 #define CAN_WRITE_FAST( addr )  (addr < low_ram_size)
96 #define WRITE_FAST              WRITE_LOW
97 
98 // addr < 0x2000 || addr >= 0x8000
99 #define CAN_READ_FAST( addr )   ((addr ^ 0x8000) < 0xA000)
100 #define READ_FAST( addr, out  ) (LOG_MEM( addr, ">", out = READ_CODE( addr ) ))
101 
102 #define READ_MEM(  addr       ) read_mem(  addr )
103 #define WRITE_MEM( addr, data ) write_mem( addr, data )
104 
105 #define CPU cpu
106 
107 #define CPU_BEGIN \
108 bool Nsf_Impl::run_cpu_until( time_t end )\
109 {\
110 	cpu.set_end_time( end );\
111 	if ( *cpu.get_code( cpu.r.pc ) != cpu.halt_opcode )\
112 	{
113 		#include "Nes_Cpu_run.h"
114 	}
115 	return cpu.time_past_end() < 0;
116 }
117