]> Shamusworld >> Repos - virtualjaguar/blob - src/vj.cpp
Changes for the upcoming 1.0.5 release
[virtualjaguar] / src / vj.cpp
1 //
2 // Virtual Jaguar Emulator
3 //
4 // by cal2
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Cleanups/fixes by James L. Hammons
7 //
8
9 // Added by SDLEMU (http://sdlemu.ngemu.com)
10 // Added for GCC UNIX compatibility
11 #ifdef __GCCUNIX__
12 #include <unistd.h>
13 #endif  // __GCCUNIX__
14
15 #include <time.h>
16 #include <SDL.h>
17 #include "jaguar.h"
18 #include "crc32.h"
19 #include "unzip.h"
20 #include "gui.h"
21
22 // Uncomment this for speed control
23 //#define SPEED_CONTROL
24
25 // Private function prototypes
26
27 uint32 JaguarLoadROM(uint8 *, char *);
28 void JaguarLoadCart(uint8 *, char *);
29
30 // External variables
31
32 //These two should be local!
33 extern bool jaguar_use_bios;
34 extern bool dsp_enabled;
35
36 extern uint8 * jaguar_mainRam;
37 extern uint8 * jaguar_bootRom;
38 extern uint8 * jaguar_mainRom;
39
40 // Various paths
41
42 static char * jaguar_bootRom_path = "./bios/jagboot.rom";
43 //static char  *jaguar_bootRom_path="c:/jaguarEmu/newload.img";
44 //static char  *jaguar_bootRom_path="./bios/JagOS.bin";
45 char * jaguar_eeproms_path = "./eeproms/";
46 char jaguar_boot_dir[1024];
47
48 SDL_Surface * surface, * mainSurface;
49 SDL_Joystick * joystick;
50 Uint32 mainSurfaceFlags = SDL_SWSURFACE;
51
52 bool finished = false;
53 bool fullscreen = false;
54 bool hardwareTypeNTSC = true;                   // Set to false for PAL
55
56 bool useJoystick = false;
57 bool showGUI = false;
58
59
60 // Added/changed by SDLEMU http://sdlemu.ngemu.com
61
62 uint32 totalFrames;//so we can grab this from elsewhere...
63 int main(int argc, char * argv[])
64 {
65         uint32 startTime;//, totalFrames;//, endTime;//, w, h;
66         uint32 nNormalLast = 0;
67         int32 nNormalFrac = 0; 
68     int32 nFrameskip = 0;                                                               // Default: Show every frame
69     int32 nFrame = 0;                                                                   // No. of Frame
70     int32 nJoyport = 0;                                                                 // Joystick port
71
72         printf("Virtual Jaguar/SDL v1.0.5 (GCC/SDL Port)\n");
73         printf("Based upon Virtual Jaguar core v1.0.0 by cal2 of Potato emulation.\n");
74         printf("Written by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)\n");
75         printf("Portions massaged by James L. Hammons (WIN32)\n");
76         printf("Contact: http://sdlemu.ngemu.com/ | sdlemu@ngemu.com\n");
77
78         // BIOS is now ON by default--use the -nobios switch to turn it off!
79         jaguar_use_bios = true;
80         bool haveCart = false;                                                                  // Assume there is no cartridge...!
81
82         // Checking the switches ;)
83
84         for(int i=1; i<argc || argv[i]!=NULL; i++)
85         {
86                 // This would be the most likely place to do the cart loading...
87                 if (argv[i][0] != '-')
88                         haveCart = true;                                                                // It looks like we have a cartridge!
89
90                 if (!strcmp(argv[i], "-fullscreen")) 
91                         fullscreen = true;
92
93 //We *don't* need this option!
94 /*              if (!strcmp(argv[i], "-window")) 
95 //                      console.option("windowed output");
96                         fullscreen = false;*/
97
98                 if (!strcmp(argv[i], "-joystick")) 
99                         useJoystick = true;
100
101                 if (!strcmp(argv[i], "-joyport"))
102                 {
103                         nJoyport = atoi(argv[++i]) + 1;
104                         if (nJoyport > 3)
105                                 nJoyport = 3;
106                 }
107
108                 if (!strcmp(argv[i], "-frameskip"))
109                 {
110                         nFrameskip = atoi(argv[++i]) + 1;
111                         if (nFrameskip > 10)
112                                 nFrameskip = 10;
113 #ifdef SPEED_CONTROL
114                         nFrameskip = 0;
115 #endif
116                 }
117
118                 if (!strcmp(argv[i], "-nobios"))
119                         jaguar_use_bios = false;
120
121                 if (!strcmp(argv[i], "-dspon"))
122                         dsp_enabled = 1;
123
124                 if (!strcmp(argv[i], "-pal"))
125                         hardwareTypeNTSC = false;
126
127                 if (!strcmp(argv[i], "-help") || !strcmp(argv[i], "-?"))
128                 {
129                     printf("Usage: \n\n");
130                         printf("vj [romfile] [switches]\n");
131                         printf("  -? or -help     : Display usage and switches               \n");
132                         printf("  -fullscreen     : Enable fullscreen mode (windowed default)\n");
133                         printf("  -frameskip 1-10 : Enable frameskip 1 (default) - 10        \n");
134                         printf("  -joystick       : Enable joystick/gamepad                  \n");
135                         printf("  -joyport   0-3  : Select desired joystick port             \n");
136                         printf("  -nobios         : Boot cart without using Jaguar BIOS ROM  \n");
137                         printf("  -dspon          : Force VJ to use the DSP                  \n");
138                         printf("  -pal            : Force VJ to PAL mode (default is NTSC)   \n");
139                         printf("\nInvoking Virtual Jagaur with no ROM file will cause it to boot up\n");
140                         printf("with the Jaguar BIOS.\n");
141                         return 1;
142                 }
143     }
144
145         getcwd(jaguar_boot_dir, 1024);
146         log_init("vj.log");
147         memory_init();
148         version_init();
149         version_display(log_get());
150         jaguar_init();
151
152         // Get the BIOS ROM
153         if (jaguar_use_bios)
154                 JaguarLoadROM(jaguar_bootRom, jaguar_bootRom_path);
155
156         SET32(jaguar_mainRam, 0, 0x00200000);                   // Set top of stack...
157
158         // Get the cartridge ROM (if passed in)
159         if (haveCart)
160                 JaguarLoadCart(jaguar_mainRom, argv[1]);
161
162         jaguar_reset();
163         
164         // Set up the backbuffer
165         int16 * backbuffer = (int16 *)malloc(845 * 525 * sizeof(int16));
166         memset(backbuffer, 0xAA, tom_getVideoModeWidth() * tom_getVideoModeHeight() * sizeof(int16));
167
168         // Set up SDL library
169         if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE) < 0)
170         {
171                 WriteLog("VJ: Could not initialize the SDL library: %s", SDL_GetError());
172                 exit(1);
173         }
174
175         // Let's get proper info about the platform we're running on...
176         const SDL_VideoInfo * info = SDL_GetVideoInfo();
177
178         if (!info)
179         {
180                 WriteLog("VJ: SDL is unable to get the video info: %s\n", SDL_GetError());
181                 exit(1);
182         }
183
184         if (info->hw_available)
185                 mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF;
186
187         if (info->blit_hw)
188                 mainSurfaceFlags |= SDL_HWACCEL;
189
190         if (fullscreen)
191                 mainSurfaceFlags |= SDL_FULLSCREEN;
192
193         // Note: mainSurface is *never* used again!
194         //Not true--had to look at what's what here... It's the primary surface...
195         mainSurface = SDL_SetVideoMode(tom_getVideoModeWidth(), tom_getVideoModeHeight(), 16, mainSurfaceFlags);
196
197         if (mainSurface == NULL)
198         {
199                 WriteLog("VJ: SDL is unable to set the video mode: %s\n", SDL_GetError());
200                 exit(1);
201         }
202
203         SDL_WM_SetCaption("Virtual Jaguar", "Virtual Jaguar");
204
205         // Create the primary SDL display (16 BPP, 5/5/5 RGB format)
206         surface = SDL_CreateRGBSurface(SDL_SWSURFACE, tom_getVideoModeWidth(),
207                 tom_getVideoModeHeight(), 16, 0x7C00, 0x03E0, 0x001F, 0);
208
209         if (surface == NULL)
210         {
211                 WriteLog("VJ: Could not create primary SDL surface: %s\n", SDL_GetError());
212                 exit(1);
213         }
214
215         // Initialize Joystick support under SDL
216         if (useJoystick)
217         {
218                 if (SDL_NumJoysticks() <= 0)
219                 {
220                         useJoystick = false;
221                         printf("VJ: No joystick(s) or joypad(s) detected on your system. Using keyboard...\n");
222                 }
223                 else
224                 {
225                         if ((joystick = SDL_JoystickOpen(nJoyport)) == 0)
226                         {
227                                 useJoystick = false;
228                                 printf("VJ: Unable to open a Joystick on port: %d\n", (int)nJoyport);
229                         }
230                         else
231                                 printf("VJ: Using: %s\n", SDL_JoystickName(nJoyport));
232                 }
233         }
234
235         totalFrames = 0;
236         startTime = clock();
237         nNormalLast = 0;                                                                        // Last value of timeGetTime()
238         nNormalFrac = 0;                                                                        // Extra fraction we did
239         nNormalLast = SDL_GetTicks();                                           //timeGetTime();
240
241         while (!finished)
242         {
243 #ifdef SPEED_CONTROL
244                 nTime = SDL_GetTicks() - nNormalLast;                   // calcule le temps écoulé depuis le dernier affichage
245                                                                                                                 // nTime est en mili-secondes.
246                 // détermine le nombre de trames à passer + 1
247                 nCount = (nTime * 600 - nNormalFrac) / 10000;
248
249                 // si le nombre de trames à passer + 1 est nul ou négatif,
250                 // ne rien faire pendant 2 ms
251                 if (nCount <= 0) 
252                 { 
253                         //Sleep(2); 
254                         //SDL_Delay(1);
255                 } // No need to do anything for a bit
256                 else
257                 {
258                         nNormalFrac += nCount * 10000;                          // 
259                         nNormalLast += nNormalFrac / 600;                       // add the duration of nNormalFrac frames
260                         nNormalFrac %= 600;                                                     // 
261
262                         // Pas plus de 9 (10-1) trames non affichées 
263                         if (nCount > 10)
264                                 nCount = 10;
265                         for(int i=0; i<nCount-1; i++)
266                                 jaguar_exec(backbuffer, false);
267 #endif
268             // Setting up new backbuffer with new pixels and data
269                         JaguarExecute(backbuffer, true);
270                         totalFrames++;
271
272                         // GUI stuff here...
273                         if (showGUI)
274                         {
275                                 extern uint32 gpu_pc;
276                                 extern uint32 dsp_pc;
277                                 DrawText(backbuffer, 8, 0, "Friendly GUI brought to you by JLH ;-)");
278                                 DrawText(backbuffer, 8, 8, "GPU PC: %08X", gpu_pc);
279                                 DrawText(backbuffer, 8, 16, "DSP PC: %08X", dsp_pc);
280                         }
281
282                         // Simple frameskip
283                         if (nFrame == nFrameskip)
284                         {
285                                 if (SDL_MUSTLOCK(surface))
286                                         while (SDL_LockSurface(surface) < 0)
287                                                 SDL_Delay(10);
288
289                                 memcpy(surface->pixels, backbuffer, tom_width * tom_height * 2);
290
291                                 if (SDL_MUSTLOCK(surface))
292                                         SDL_UnlockSurface(surface);
293
294                                 SDL_Rect srcrect, dstrect;
295                                 srcrect.x = srcrect.y = 0, srcrect.w = surface->w, srcrect.h = surface->h;
296                                 dstrect.x = dstrect.y = 0, dstrect.w = surface->w, dstrect.h = surface->h;
297                                 SDL_BlitSurface(surface, &srcrect, mainSurface, &dstrect);
298                             SDL_Flip(mainSurface);      
299                                 nFrame = 0;
300                         }
301                         else
302                                 nFrame++;
303
304                         joystick_exec();
305                         
306 #ifdef SPEED_CONTROL
307                 }
308 #endif
309         }
310
311         int elapsedTime = clock() - startTime;
312         int fps = (1000 * totalFrames) / elapsedTime;
313         fprintf(log_get(), "VJ: Ran at an average of %i FPS.\n", fps);
314
315         jaguar_done();
316         version_done();
317         memory_done();
318         log_done();     
319
320         SDL_JoystickClose(joystick);
321         SDL_FreeSurface(surface);
322         SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_TIMER);
323         SDL_Quit();
324
325     return 0;
326 }
327
328 //
329 // Generic ROM loading
330 //
331 uint32 JaguarLoadROM(uint8 * rom, char * path)
332 {
333         uint32 romSize;
334
335         WriteLog("JagEm: Loading %s...", path);
336
337         char * ext = strrchr(path, '.');
338         if (strcmpi(ext, ".zip") == 0)
339         {
340                 // Handle ZIP file loading here...
341                 WriteLog("(ZIPped)...");
342
343                 if (load_zipped_file(0, 0, path, NULL, &rom, &romSize) == -1)
344                 {
345                         WriteLog("Failed!\n");
346                         log_done();
347                         exit(0);
348                 }
349         }
350         else
351         {
352                 FILE * fp = fopen(path, "rb");
353
354                 if (fp == NULL)
355                 {
356                         WriteLog("Failed!\n");
357                         log_done();
358                         exit(0);
359                 }
360
361                 fseek(fp, 0, SEEK_END);
362                 romSize = ftell(fp);
363                 fseek(fp, 0, SEEK_SET);
364                 fread(rom, 1, romSize, fp);
365                 fclose(fp);
366         }
367
368         WriteLog("OK (%i bytes)\n", romSize);
369         return romSize;
370 }
371
372 //
373 // Jaguar cartridge ROM loading
374 //
375 void JaguarLoadCart(uint8 * mem, char * path)
376 {
377         uint32 romsize = JaguarLoadROM(mem, path);
378         jaguar_mainRom_crc32 = crc32_calcCheckSum(jaguar_mainRom, romsize);
379         WriteLog( "CRC: %08X\n", (unsigned int)jaguar_mainRom_crc32);
380         eeprom_init();
381 }