annotate Plugins/Input/console/Snes_Spc.cpp @ 493:c04dff121e1d trunk

[svn] hostile merge, phase 2: reimport based on new plugin code
author nenolod
date Tue, 24 Jan 2006 20:19:01 -0800
parents
children f12d7e208b43
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
493
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
1
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
2 // Game_Music_Emu 0.3.0. http://www.slack.net/~ant/
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
3
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
4 #include "Snes_Spc.h"
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
5
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
6 #include <assert.h>
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
7 #include <string.h>
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
8
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
9 /* Copyright (C) 2004-2006 Shay Green. This module is free software; you
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
10 can redistribute it and/or modify it under the terms of the GNU Lesser
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
11 General Public License as published by the Free Software Foundation; either
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
12 version 2.1 of the License, or (at your option) any later version. This
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
13 module is distributed in the hope that it will be useful, but WITHOUT ANY
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
15 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
16 more details. You should have received a copy of the GNU Lesser General
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
17 Public License along with this module; if not, write to the Free Software
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
19
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
20 #include BLARGG_SOURCE_BEGIN
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
21
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
22 // always in the future (CPU time can go over 0, but not by this much)
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
23 int const timer_disabled_time = 127;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
24
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
25 Snes_Spc::Snes_Spc() : dsp( ram ), cpu( this, ram )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
26 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
27 timer [0].shift = 7; // 8 kHz
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
28 timer [1].shift = 7; // 8 kHz
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
29 timer [2].shift = 4; // 64 kHz
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
30
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
31 // Put STOP instruction past end of memory to catch PC overflow.
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
32 memset( ram + ram_size, 0xff, (sizeof ram) - ram_size );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
33 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
34
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
35 // Load
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
36
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
37 blargg_err_t Snes_Spc::load_spc( const void* data, long size, bool clear_echo_ )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
38 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
39 struct spc_file_t {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
40 char signature [27];
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
41 char unused [10];
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
42 uint8_t pc [2];
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
43 uint8_t a;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
44 uint8_t x;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
45 uint8_t y;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
46 uint8_t status;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
47 uint8_t sp;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
48 char unused2 [212];
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
49 uint8_t ram [0x10000];
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
50 uint8_t dsp [128];
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
51 };
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
52 BOOST_STATIC_ASSERT( sizeof (spc_file_t) == spc_file_size );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
53
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
54 const spc_file_t* spc = (spc_file_t*) data;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
55
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
56 if ( size < spc_file_size )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
57 return "Not an SPC file";
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
58
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
59 if ( strncmp( spc->signature, "SNES-SPC700 Sound File Data", 27 ) != 0 )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
60 return "Not an SPC file";
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
61
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
62 registers_t regs;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
63 regs.pc = spc->pc [1] * 0x100 + spc->pc [0];
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
64 regs.a = spc->a;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
65 regs.x = spc->x;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
66 regs.y = spc->y;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
67 regs.status = spc->status;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
68 regs.sp = spc->sp;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
69
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
70 const char* error = load_state( regs, spc->ram, spc->dsp );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
71
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
72 echo_accessed = false;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
73
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
74 if ( clear_echo_ )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
75 clear_echo();
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
76
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
77 return error;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
78 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
79
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
80 void Snes_Spc::clear_echo()
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
81 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
82 if ( !(dsp.read( 0x6c ) & 0x20) )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
83 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
84 unsigned addr = 0x100 * dsp.read( 0x6d );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
85 unsigned size = 0x800 * dsp.read( 0x7d );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
86 unsigned limit = ram_size - addr;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
87 memset( ram + addr, 0xff, (size < limit) ? size : limit );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
88 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
89 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
90
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
91 // Handle other file formats (emulator save states) in user code, not here.
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
92
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
93 blargg_err_t Snes_Spc::load_state( const registers_t& cpu_state, const void* new_ram,
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
94 const void* dsp_state )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
95 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
96 // cpu
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
97 cpu.r = cpu_state;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
98
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
99 // Allow DSP to generate one sample before code starts
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
100 // (Tengai Makyo Zero, Tenjin's Table Toss first notes are lost since it
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
101 // clears KON 31 cycles from starting execution. It works on the SNES
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
102 // since the SPC player adds a few extra cycles delay after restoring
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
103 // KON from the DSP registers at the end of an SPC file).
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
104 extra_cycles = 32;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
105
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
106 // ram
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
107 memcpy( ram, new_ram, ram_size );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
108 memcpy( extra_ram, ram + rom_addr, sizeof extra_ram );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
109
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
110 // boot rom (have to force enable_rom() to update it)
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
111 rom_enabled = !(ram [0xf1] & 0x80);
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
112 enable_rom( !rom_enabled );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
113
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
114 // dsp
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
115 dsp.reset();
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
116 int i;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
117 for ( i = 0; i < Spc_Dsp::register_count; i++ )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
118 dsp.write( i, ((uint8_t*) dsp_state) [i] );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
119
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
120 // timers
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
121 for ( i = 0; i < timer_count; i++ )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
122 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
123 Timer& t = timer [i];
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
124
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
125 t.next_tick = 0;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
126 t.enabled = (ram [0xf1] >> i) & 1;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
127 if ( !t.enabled )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
128 t.next_tick = timer_disabled_time;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
129 t.count = 0;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
130 t.counter = ram [0xfd + i] & 15;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
131
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
132 int p = ram [0xfa + i];
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
133 t.period = p ? p : 0x100;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
134 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
135
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
136 // Handle registers which already give 0 when read by setting RAM and not changing it.
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
137 // Put STOP instruction in registers which can be read, to catch attempted CPU execution.
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
138 ram [0xf0] = 0;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
139 ram [0xf1] = 0;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
140 ram [0xf3] = 0xff;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
141 ram [0xfa] = 0;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
142 ram [0xfb] = 0;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
143 ram [0xfc] = 0;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
144 ram [0xfd] = 0xff;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
145 ram [0xfe] = 0xff;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
146 ram [0xff] = 0xff;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
147
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
148 return NULL; // success
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
149 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
150
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
151 // Hardware
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
152
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
153 // Current time starts negative and ends at 0
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
154 inline spc_time_t Snes_Spc::time() const
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
155 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
156 return -cpu.remain();
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
157 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
158
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
159 // Keep track of next time to run and avoid a function call if it hasn't been reached.
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
160
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
161 // Timers
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
162
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
163 void Snes_Spc::Timer::run_until_( spc_time_t time )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
164 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
165 if ( !enabled )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
166 dprintf( "next_tick: %ld, time: %ld", (long) next_tick, (long) time );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
167 assert( enabled ); // when disabled, next_tick should always be in the future
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
168
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
169 int elapsed = ((time - next_tick) >> shift) + 1;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
170 next_tick += elapsed << shift;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
171 elapsed += count;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
172 if ( elapsed >= period ) { // avoid costly divide
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
173 int n = elapsed / period;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
174 elapsed -= n * period;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
175 counter = (counter + n) & 15;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
176 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
177 count = elapsed;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
178 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
179
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
180 // DSP
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
181
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
182 const int clocks_per_sample = 32; // 1.024 MHz CPU clock / 32000 samples per second
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
183
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
184 void Snes_Spc::run_dsp_( spc_time_t time )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
185 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
186 int count = ((time - next_dsp) >> 5) + 1; // divide by clocks_per_sample
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
187 sample_t* buf = sample_buf;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
188 if ( buf ) {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
189 sample_buf = buf + count * 2; // stereo
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
190 assert( sample_buf <= buf_end );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
191 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
192 next_dsp += count * clocks_per_sample;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
193 dsp.run( count, buf );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
194 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
195
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
196 inline void Snes_Spc::run_dsp( spc_time_t time )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
197 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
198 if ( time >= next_dsp )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
199 run_dsp_( time );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
200 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
201
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
202 // Debug-only check for read/write within echo buffer, since this might result in
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
203 // inaccurate emulation due to the DSP not being caught up to the present.
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
204 inline void Snes_Spc::check_for_echo_access( spc_addr_t addr )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
205 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
206 if ( !echo_accessed && !(dsp.read( 0x6c ) & 0x20) )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
207 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
208 // ** If echo accesses are found that require running the DSP, cache
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
209 // the start and end address on DSP writes to speed up checking.
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
210
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
211 unsigned start = 0x100 * dsp.read( 0x6d );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
212 unsigned end = start + 0x800 * dsp.read( 0x7d );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
213 if ( start <= addr && addr < end ) {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
214 echo_accessed = true;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
215 dprintf( "Read/write at $%04X within echo buffer\n", (unsigned) addr );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
216 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
217 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
218 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
219
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
220 // Read
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
221
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
222 int Snes_Spc::read( spc_addr_t addr )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
223 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
224 // zero page ram is used most often
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
225 if ( addr < 0xf0 )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
226 return ram [addr];
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
227
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
228 // dsp
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
229 if ( addr == 0xf3 ) {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
230 run_dsp( time() );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
231 if ( ram [0xf2] >= Spc_Dsp::register_count )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
232 dprintf( "DSP read from $%02X\n", (int) ram [0xf2] );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
233 return dsp.read( ram [0xf2] & 0x7f );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
234 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
235
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
236 // counters
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
237 unsigned i = addr - 0xfd; // negative converts to large positive unsigned
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
238 if ( i < timer_count ) {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
239 Timer& t = timer [i];
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
240 t.run_until( time() );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
241 int result = t.counter;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
242 t.counter = 0;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
243 return result;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
244 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
245
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
246 if ( addr == 0xf0 || addr == 0xf1 || addr == 0xf8 ||
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
247 addr == 0xf9 || addr == 0xfa )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
248 dprintf( "Read from register $%02X\n", (int) addr );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
249
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
250 // Registers which always read as 0 are handled by setting ram [reg] to 0
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
251 // at startup then never changing that value.
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
252
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
253 check(( check_for_echo_access( addr ), true ));
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
254
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
255 // ram
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
256 return ram [addr];
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
257 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
258
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
259
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
260 // Write
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
261
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
262 const unsigned char Snes_Spc::boot_rom [rom_size] = { // verified
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
263 0xCD, 0xEF, 0xBD, 0xE8, 0x00, 0xC6, 0x1D, 0xD0,
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
264 0xFC, 0x8F, 0xAA, 0xF4, 0x8F, 0xBB, 0xF5, 0x78,
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
265 0xCC, 0xF4, 0xD0, 0xFB, 0x2F, 0x19, 0xEB, 0xF4,
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
266 0xD0, 0xFC, 0x7E, 0xF4, 0xD0, 0x0B, 0xE4, 0xF5,
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
267 0xCB, 0xF4, 0xD7, 0x00, 0xFC, 0xD0, 0xF3, 0xAB,
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
268 0x01, 0x10, 0xEF, 0x7E, 0xF4, 0x10, 0xEB, 0xBA,
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
269 0xF6, 0xDA, 0x00, 0xBA, 0xF4, 0xC4, 0xF4, 0xDD,
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
270 0x5D, 0xD0, 0xDB, 0x1F, 0x00, 0x00, 0xC0, 0xFF
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
271 };
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
272
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
273 void Snes_Spc::enable_rom( bool enable )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
274 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
275 if ( rom_enabled != enable )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
276 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
277 rom_enabled = enable;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
278 memcpy( ram + rom_addr, (enable ? boot_rom : extra_ram), rom_size );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
279 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
280 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
281
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
282 void Snes_Spc::write( spc_addr_t addr, int data )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
283 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
284 // first page is very common
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
285 if ( addr < 0xf0 ) {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
286 ram [addr] = data;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
287 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
288 else switch ( addr )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
289 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
290 // RAM
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
291 default:
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
292 check(( check_for_echo_access( addr ), true ));
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
293 if ( addr < rom_addr ) {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
294 ram [addr] = data;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
295 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
296 else {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
297 extra_ram [addr - rom_addr] = data;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
298 if ( !rom_enabled )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
299 ram [addr] = data;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
300 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
301 break;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
302
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
303 // DSP
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
304 //case 0xf2: // mapped to RAM
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
305 case 0xf3: {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
306 run_dsp( time() );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
307 int reg = ram [0xf2];
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
308 if ( next_dsp > 0 ) {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
309 // skip mode
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
310
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
311 // key press
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
312 if ( reg == 0x4C )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
313 keys_pressed |= data & ~dsp.read( 0x5C );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
314
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
315 // key release
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
316 if ( reg == 0x5C ) {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
317 keys_released |= data;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
318 keys_pressed &= ~data;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
319 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
320 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
321 if ( reg < Spc_Dsp::register_count ) {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
322 dsp.write( reg, data );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
323 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
324 else {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
325 dprintf( "DSP write to $%02X\n", (int) reg );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
326 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
327 break;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
328 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
329
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
330 case 0xf0: // Test register
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
331 dprintf( "Wrote $%02X to $F0\n", (int) data );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
332 break;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
333
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
334 // Config
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
335 case 0xf1:
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
336 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
337 // timers
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
338 for ( int i = 0; i < timer_count; i++ )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
339 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
340 Timer& t = timer [i];
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
341 if ( !(data & (1 << i)) ) {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
342 t.enabled = 0;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
343 t.next_tick = timer_disabled_time;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
344 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
345 else if ( !t.enabled ) {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
346 // just enabled
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
347 t.enabled = 1;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
348 t.counter = 0;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
349 t.count = 0;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
350 t.next_tick = time();
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
351 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
352 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
353
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
354 // port clears
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
355 if ( data & 0x10 ) {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
356 ram [0xf4] = 0;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
357 ram [0xf5] = 0;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
358 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
359 if ( data & 0x20 ) {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
360 ram [0xf6] = 0;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
361 ram [0xf7] = 0;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
362 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
363
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
364 enable_rom( data & 0x80 );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
365
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
366 break;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
367 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
368
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
369 // Ports
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
370 case 0xf4:
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
371 case 0xf5:
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
372 case 0xf6:
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
373 case 0xf7:
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
374 // to do: handle output ports
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
375 break;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
376
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
377 //case 0xf8: // verified on SNES that these are read/write (RAM)
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
378 //case 0xf9:
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
379
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
380 // Timers
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
381 case 0xfa:
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
382 case 0xfb:
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
383 case 0xfc: {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
384 Timer& t = timer [addr - 0xfa];
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
385 if ( (t.period & 0xff) != data ) {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
386 t.run_until( time() );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
387 t.period = data ? data : 0x100;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
388 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
389 break;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
390 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
391
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
392 // Counters (cleared on write)
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
393 case 0xfd:
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
394 case 0xfe:
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
395 case 0xff:
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
396 dprintf( "Wrote to counter $%02X\n", (int) addr );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
397 timer [addr - 0xfd].counter = 0;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
398 break;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
399 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
400 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
401
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
402 // Play
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
403
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
404 blargg_err_t Snes_Spc::skip( long count )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
405 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
406 if ( count > 4 * 32000L )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
407 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
408 // don't run DSP for long durations (2-3 times faster)
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
409
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
410 const long sync_count = 32000L * 2;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
411
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
412 // keep track of any keys pressed/released (and not subsequently released)
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
413 keys_pressed = 0;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
414 keys_released = 0;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
415 // sentinel tells play to ignore DSP
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
416 BLARGG_RETURN_ERR( play( count - sync_count, skip_sentinel ) );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
417
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
418 // press/release keys now
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
419 dsp.write( 0x5C, keys_released & ~keys_pressed );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
420 dsp.write( 0x4C, keys_pressed );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
421
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
422 clear_echo();
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
423
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
424 // play the last few seconds normally to help synchronize DSP
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
425 count = sync_count;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
426 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
427
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
428 return play( count );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
429 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
430
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
431 blargg_err_t Snes_Spc::play( long count, sample_t* out )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
432 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
433 require( count % 2 == 0 ); // output is always in pairs of samples
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
434
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
435 // CPU time() runs from -duration to 0
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
436 spc_time_t duration = (count / 2) * clocks_per_sample;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
437
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
438 // DSP output is made on-the-fly when the CPU reads/writes DSP registers
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
439 sample_buf = out;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
440 buf_end = out + (out && out != skip_sentinel ? count : 0);
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
441 next_dsp = (out == skip_sentinel) ? clocks_per_sample : -duration + clocks_per_sample;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
442
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
443 // Localize timer next_tick times and run them to the present to prevent a running
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
444 // but ignored timer's next_tick from getting too far behind and overflowing.
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
445 for ( int i = 0; i < timer_count; i++ )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
446 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
447 Timer& t = timer [i];
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
448 if ( t.enabled )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
449 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
450 t.next_tick -= duration;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
451 t.run_until( -duration );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
452 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
453 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
454
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
455 // Run CPU for duration, reduced by any extra cycles from previous run
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
456 int elapsed = cpu.run( duration - extra_cycles );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
457 if ( elapsed > 0 )
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
458 {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
459 dprintf( "Unhandled instruction $%02X, pc = $%04X\n",
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
460 (int) cpu.read( cpu.r.pc ), (unsigned) cpu.r.pc );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
461 return "Emulation error";
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
462 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
463 extra_cycles = -elapsed;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
464
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
465 // Catch DSP up to present.
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
466 run_dsp( 0 );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
467 if ( out ) {
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
468 assert( next_dsp == clocks_per_sample );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
469 assert( out == skip_sentinel || sample_buf - out == count );
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
470 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
471 buf_end = NULL;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
472
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
473 return blargg_success;
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
474 }
c04dff121e1d [svn] hostile merge, phase 2: reimport based on new plugin code
nenolod
parents:
diff changeset
475