-
Notifications
You must be signed in to change notification settings - Fork 0
/
nesemu.c
350 lines (303 loc) · 9.14 KB
/
nesemu.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
/***************************************************************************
* Copyright (C) 2006-2009 by Dead_Body *
* jamesholodnak@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdio.h>
#include <string.h>
#include "nes/nes.h"
#include "nes/rom/rom.h"
#include "system/system.h"
#include "gui2/gui2.h"
#include "nes/state/state.h"
#include "log.h"
#include "misc.h"
#include "splash.h"
#include "nes/romdb/romdb.h"
#ifdef SDL
#include <SDL/SDL.h>
#endif
//must include the path on the target system, this variable
//provides the path used when loading the config file.
//without it, config files and logs end of everywhere, along
//with the directories created by config_load().
char *argv0;
//bios rom data
u8 genie_rom[0x6000];
u8 disksys_rom[0x2000];
u8 hle_fds_rom[0x2000];
u8 nsfbios_rom[0x1000];
//bios rom filenames
static char genie_path[1024] = "genie.rom";
static char disksys_path[1024] = "disksys.rom";
static char hle_fds_path[1024] = "hle_fds.bin";
static char nsfbios_path[1024] = "nsf_bios.bin";
int gui_active = 0;
char curdir[1024]; //base directory of nesemu.exe (or on ps2 it = "mc0:/nesemu")
char path_config[1024]; //path to configuration file (set by config_defaults() or
config_t config; //some other system dependent init call)
u8 *nesscr;
//is the emulator currently executing the nes?
int running = 1;
//is it time to quit?
int quit = 0;
static char *lines_init[] = {"Loading...","NESEMU v"VERSION,"","http://ps2.fapexpert.com","http://code.google.com/p/nesemu",0};
void nesemu_init()
{
init_system();
file_init();
log_init();
log_message("inited system, file and log ok\n");
log_message("argv0 = '%s'\n",argv0);
log_message("initing filesystem\n");
filesystem_init();
config_load();
log_message("inited config\n");
video_init();
log_message("initing gui\n");
gui2_init();
gui_draw_setscreensize(256,240);
gui_draw_setscreen((u8*)nesscr,256+8);
splash_start(nesscr);
splash_adddot();
log_message("inited video\n");
splash_adddot();
input_init();
splash_adddot();
log_message("inited input\n");
log_message("initing sound\n");
sound_init();
splash_adddot();
log_message("init done, saving config\n");
config_save();
splash_adddot();
if(config.soundenabled == 0)
apu_disable();
splash_adddot();
}
void nesemu_kill()
{
log_message("killing system\n");
config_save();
unloadrom();
filesystem_kill();
gui2_kill();
log_message("killing sound...\n");
sound_kill();
log_message("killing input...\n");
input_kill();
log_message("killing video...\n");
video_kill();
log_message("killing logger...\n");
log_kill();
file_kill();
log_message("killing system dependent stuff...\n");
kill_system();
}
#ifdef PS2
int system_setupsavelocation(int loc);
#endif
int main(int argc,char *argv[])
{
char *p,*rom_filename = 0;
int i,doloadstate = 0;
memset(path_config,0,1024);
log_message("nesemu - version "VERSION"\n\n");
/*************/{
/* romdb_t *romdb = 0;
char fn[2][256] = {
"romdb/nesemu.romdb",
"../romdb/romdb.xml",
};
if((romdb = romdb_load(fn[1])) == 0)
log_error("failed to load rom database\n");
*/
/*************/}
//set running state to starting up
running = -1;
//set our base filename
argv0 = argv[0];
//zero out curdir
memset(curdir,0,1024);
//determine current directory
#ifdef PS2
strcpy(curdir,"mc0:/nesemu");
#elif defined(WII)
strcpy(curdir,"sd:/nesemu");
#elif (defined(LINUX) || defined(OSX))
{
char *homedir = getenv("HOME");
if(homedir) {
sprintf(curdir,"%s/.nesemu/",homedir);
mkdir(curdir);
}
}
#else
//TODO: win32 target can use documents and settings folder, to be like
//the cool kids, if it fails to exist, it can default on the argv0 method.
strcpy(curdir,argv0);
#ifdef WIN32
//convert windows path to unix path
for(i=0;curdir[i];i++) {
if(curdir[i] == '\\')
curdir[i] = '/';
}
#endif
#endif
//safety check
if((p = strrchr(curdir,'/')) == 0) {
log_error("platform must include path in argv[0]\n");
exit(0);
}
*p = 0;
log_message("determined executable directory to be '%s'\n",curdir);
sprintf(path_config,"%s/nesemu.cfg",curdir);
//parse command line arguments (if they are given)
if(argc > 1) {
for(i=1;i<argc;i++) {
if(strcmp("--mappers",argv[i]) == 0) {
showmappers();
return(0);
}
else if(strcmp("--config",argv[i]) == 0) {
i++;
if(i < argc) {
strncpy(path_config,argv[i],1024);
log_message("using configuration file '%s'\n",path_config);
}
else {
log_message("please specify a filename after --config\n");
return(0);
}
}
else if(strcmp("--loadstate",argv[i]) == 0)
doloadstate = 1;
#ifndef PS2
else if(strcmp("--windowed",argv[i]) == 0)
config.windowed = 1;
#else
else if(strcmp("--setupmc0",argv[i]) == 0)
system_setupsavelocation(0);
else if(strcmp("--setupmc1",argv[i]) == 0)
system_setupsavelocation(1);
#endif
else if(strcmp("--rom",argv[i]) == 0) {
i++;
if(i < argc) {
rom_filename = argv[i];
log_message("auto-loading rom '%s'\n",rom_filename);
}
else {
log_message("please specify a filename after --rom\n");
return(0);
}
}
else {
log_message("ignoring invalid command line argument '%s'\n",argv[i]);
}
}
}
//screen buffer (currently only used by the gui)
nesscr = (u8*)malloc(256 * (256 + 16) * sizeof(u8));
memset(nesscr,0,256 * (256 + 16) * sizeof(u8));
//initialize system
nesemu_init();
//initialize nes
nes_init();
splash_adddot();
//set input devices
nes_setinput(0,config.devices[0]);
nes_setinput(1,config.devices[1]);
nes_setexp(config.expdevice);
splash_adddot();
//try to load game genie bios
if(load_bios(genie_path,genie_rom,0x6000) == 0)
nes->genie_rom = genie_rom;
splash_adddot();
//try to load real nintendo fds bios
if(load_bios(disksys_path,disksys_rom,0x2000) == 0)
nes->disksys_rom = disksys_rom;
splash_adddot();
//try to load the hle fds bios
if(load_bios(hle_fds_path,hle_fds_rom,0x2000) == 0)
nes->hle_fds_rom = hle_fds_rom;
splash_adddot();
//try to load the nsf player bios
if(load_bios(nsfbios_path,nsfbios_rom,0x1000) == 0)
{}//nes->nsfbios_rom = nsfbios_rom;
splash_adddot();
//no nintendo bios, hle loaded, make sure config has correct selection
if(nes->disksys_rom == 0 && nes->hle_fds_rom != 0) config.fdsbios = 1;
//and the opposite effect, to ensure the fds bios is ok
if(nes->disksys_rom != 0 && nes->hle_fds_rom == 0) config.fdsbios = 0;
log_message("trying to load rom passed as parameter\n");
//if a rom filename was passed and that rom is loaded ok
if(rom_filename && (loadrom(rom_filename) == 0)) {
splash_adddot();
//set gui to inactive
gui_active = 0;
//start playing sound
sound_play();
//if the load state command line parameter was passed
if(doloadstate) {
loadstate();
splash_adddot();
}
}
//else activate the gui and stop the sound
else {
gui_active = 1;
sound_pause();
}
splash_adddot();
//debug message
log_message("everything initialized ok, beginning main loop\n");
splash_stop();
//start the main loop
while(quit == 0) {
//poll the input
input_poll();
//check os events
check_events();
//poll gui input
gui2_poll();
//if the gui is active, draw it
if(gui_active) {
gui2_draw(((u8*)nesscr),256+8);
video_update(nesscr,256+8);
}
//or if a rom is loaded and the running state is positive
else if(nes->rom && running) {
//execute a nes frame, if error exit to the gui
if(nes_frame() == 1) {
unloadrom();
gui_active = 1;
}
else
//update the sound output
sound_update();
}
}
log_message("exiting...\n");
unloadrom();
nes_kill();
log_message("freeing screen buffer\n");
free(nesscr);
nesemu_kill();
log_message("nesemu exiting...\n");
return(0);
}