libretro.c 9.09 KB
Newer Older
's avatar
committed
1
#include "libretro.h"
jdgleaver's avatar
jdgleaver committed
2
#include "libretro_core_options.h"
frangarcj's avatar
frangarcj committed
3
#include "log.h"
's avatar
committed
4
5
#include <string.h>

Libretro-Admin's avatar
Libretro-Admin committed
6
#include "../types.h"
's avatar
committed
7
8
#include "../state.h"
#include "../neopopsound.h"
negativeExponent's avatar
negativeExponent committed
9
#include "../sound.h"
's avatar
committed
10
11
12
#include "../input.h"
#include "../flash.h"
#include "../tlcs900h.h"
13
#include "../race-memory.h"
's avatar
committed
14
#include "../graphics.h"
negativeExponent's avatar
negativeExponent committed
15
#include "../state.h"
's avatar
committed
16
17
18
19
20
21
22
23
24

static retro_log_printf_t log_cb;
static retro_video_refresh_t video_cb;
static retro_audio_sample_batch_t audio_batch_cb;
static retro_environment_t environ_cb;
static retro_input_poll_t input_poll_cb;
static retro_input_state_t input_state_cb;

#define RACE_NAME_MODULE "race"
25
#define RACE_NAME "RACE"
26
#define RACE_VERSION "v2.16"
's avatar
committed
27
28
#define RACE_EXTENSIONS "ngp|ngc|ngpc|npc"
#define RACE_TIMING_FPS 60.25
29
#define RACE_GEOMETRY_BASE_W 160
's avatar
committed
30
31
32
#define RACE_GEOMETRY_BASE_H 152
#define RACE_GEOMETRY_MAX_W 160
#define RACE_GEOMETRY_MAX_H 152
frangarcj's avatar
frangarcj committed
33
#define RACE_GEOMETRY_ASPECT_RATIO 1.05
's avatar
committed
34
35
36
37

#define FB_WIDTH 160
#define FB_HEIGHT 152

38
/* core options */
's avatar
committed
39
40
static int RETRO_SAMPLE_RATE = 44100;

Libretro-Admin's avatar
Libretro-Admin committed
41
struct ngp_screen* screen;
42
int setting_ngp_language; /* 0x6F87 - language */
's avatar
committed
43
int gfx_hacks;
44
int tipo_consola; /* 0x6F91 - OS version */
negativeExponent's avatar
negativeExponent committed
45
static bool libretro_supports_input_bitmasks;
's avatar
committed
46

47
48
char retro_save_directory[2048];

Libretro-Admin's avatar
Libretro-Admin committed
49
50
51
52
53
struct map
{
   unsigned retro;
   unsigned ngp;
};
's avatar
committed
54

Libretro-Admin's avatar
Libretro-Admin committed
55
static struct map btn_map[] = {
frangarcj's avatar
frangarcj committed
56
57
   { RETRO_DEVICE_ID_JOYPAD_A, 0x20 },
   { RETRO_DEVICE_ID_JOYPAD_B, 0x10 },
's avatar
committed
58
59
60
61
   { RETRO_DEVICE_ID_JOYPAD_RIGHT, 0x08 },
   { RETRO_DEVICE_ID_JOYPAD_LEFT, 0x04 },
   { RETRO_DEVICE_ID_JOYPAD_UP, 0x01 },
   { RETRO_DEVICE_ID_JOYPAD_DOWN, 0x02 },
jdgleaver's avatar
jdgleaver committed
62
   { RETRO_DEVICE_ID_JOYPAD_START, 0x40 },
's avatar
committed
63
64
65
66
67
68
69
};

unsigned retro_api_version(void)
{
   return RETRO_API_VERSION;
}

Libretro-Admin's avatar
Libretro-Admin committed
70
void graphics_paint(void)
's avatar
committed
71
{
negativeExponent's avatar
negativeExponent committed
72
   video_cb(screen->pixels, screen->w, screen->h, FB_WIDTH << 1);
's avatar
committed
73
74
75
76
}

static void check_variables(void)
{
jdgleaver's avatar
jdgleaver committed
77
78
   struct retro_variable var  = {0};
   unsigned dark_filter_level = 0;
's avatar
committed
79

80
   var.key = "race_language";
's avatar
committed
81
82
83
84
   var.value = NULL;

   if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
   {
85
86
87
88
      /* user must manually restart core for change to happen
       * > 0: English
       * > 1: Japanese
       */
's avatar
committed
89
90
      if (!strcmp(var.value, "japanese"))
         setting_ngp_language = 1;
jdgleaver's avatar
jdgleaver committed
91
92
      else if (!strcmp(var.value, "english"))
         setting_ngp_language = 0;
's avatar
committed
93
   }
jdgleaver's avatar
jdgleaver committed
94
95
96
97
98

   var.key   = "race_dark_filter_level";
   var.value = NULL;

   if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
Libretro-Admin's avatar
Libretro-Admin committed
99
      dark_filter_level = (unsigned)(atoi(var.value));
jdgleaver's avatar
jdgleaver committed
100
   graphicsSetDarkFilterLevel(dark_filter_level);
's avatar
committed
101
102
103
}
void retro_init(void)
{
frangarcj's avatar
frangarcj committed
104
105
   /* set up some logging */
   init_log(environ_cb);
's avatar
committed
106

107
108
109
110
   char *dir = NULL;
   if (environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &dir) && dir)
      sprintf(retro_save_directory, "%s%c", dir, path_default_slash_c());

jdgleaver's avatar
jdgleaver committed
111
112
   if (log_cb)
      log_cb(RETRO_LOG_INFO, "[RACE]: Save directory: %s.\n", retro_save_directory);
113

's avatar
committed
114
115
   check_variables();

negativeExponent's avatar
negativeExponent committed
116
117
118
   enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565;
   if(!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt) && log_cb)
      log_cb(RETRO_LOG_ERROR, "[could not set RGB565]\n");
negativeExponent's avatar
negativeExponent committed
119
120
121
   
   if (environ_cb(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL))
      libretro_supports_input_bitmasks = true;
's avatar
committed
122
123
124
125
126
127
128
129
130
131
132
133
}

void retro_reset(void)
{
   flashShutdown();
   system_sound_chipreset();
   mainemuinit();
}

void retro_deinit(void)
{
    flashShutdown();
negativeExponent's avatar
negativeExponent committed
134
    libretro_supports_input_bitmasks = false;
's avatar
committed
135
136
137
138
139
}

void retro_set_environment(retro_environment_t cb)
{
   environ_cb = cb;
jdgleaver's avatar
jdgleaver committed
140
141

   libretro_set_core_options(environ_cb);
's avatar
committed
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
}

void retro_set_audio_sample(retro_audio_sample_t cb)
{
}

void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb)
{
   audio_batch_cb = cb;
}

void retro_set_input_poll(retro_input_poll_t cb)
{
   input_poll_cb = cb;
}

void retro_set_input_state(retro_input_state_t cb)
{
   input_state_cb = cb;
}

void retro_set_video_refresh(retro_video_refresh_t cb)
{
   video_cb = cb;
}

negativeExponent's avatar
negativeExponent committed
168
169
170
171
172
static unsigned get_race_input_bitmasks(void)
{
   unsigned i = 0;
   unsigned res = 0;
   unsigned ret = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK);
Libretro-Admin's avatar
Libretro-Admin committed
173
   for (i = 0; i < sizeof(btn_map) / sizeof(struct map); i++)
negativeExponent's avatar
negativeExponent committed
174
175
176
177
      res |= (ret & (1 << btn_map[i].retro)) ? btn_map[i].ngp : 0;
   return res;
}

's avatar
committed
178
179
static unsigned get_race_input(void)
{
negativeExponent's avatar
negativeExponent committed
180
181
   unsigned i = 0;
   unsigned res = 0;
Libretro-Admin's avatar
Libretro-Admin committed
182
   for (i = 0; i < sizeof(btn_map) / sizeof(struct map); i++)
's avatar
committed
183
184
185
186
187
188
189
190
      res |= input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, btn_map[i].retro) ? btn_map[i].ngp : 0;
   return res;
}

static void race_input(void)
{
   ngpInputState = 0;
   input_poll_cb();
negativeExponent's avatar
negativeExponent committed
191
192
193
194
   if (libretro_supports_input_bitmasks)
      ngpInputState = get_race_input_bitmasks();
   else
      ngpInputState = get_race_input();
's avatar
committed
195
196
197
198
199
200
201
202
203
204
205
206
}

static bool race_initialize_sound(void)
{
    system_sound_chipreset();
    return true;
}

static bool race_initialize_system(const char* gamepath)
{
   mainemuinit();

frangarcj's avatar
frangarcj committed
207
208
209
210
   if(!handleInputFile((char *)gamepath)){
      handle_error("ERROR handleInputFile");
      return false;
   }
's avatar
committed
211
212
213
214

   return true;
}

Libretro-Admin's avatar
Libretro-Admin committed
215
void retro_set_controller_port_device(unsigned a, unsigned b) { }
's avatar
committed
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

void retro_get_system_info(struct retro_system_info *info)
{
   memset(info, 0, sizeof(*info));
   info->library_name     = RACE_NAME;
#ifndef GIT_VERSION
#define GIT_VERSION ""
#endif

   info->need_fullpath    = true;
   info->library_version  = RACE_VERSION GIT_VERSION;
   info->valid_extensions = RACE_EXTENSIONS;
   info->block_extract    = false;
}
void retro_get_system_av_info(struct retro_system_av_info *info)
{
   memset(info, 0, sizeof(*info));
   info->timing.fps            = RACE_TIMING_FPS;
   info->timing.sample_rate    = RETRO_SAMPLE_RATE;
   info->geometry.base_width   = RACE_GEOMETRY_BASE_W;
   info->geometry.base_height  = RACE_GEOMETRY_BASE_H;
   info->geometry.max_width    = RACE_GEOMETRY_MAX_W;
   info->geometry.max_height   = RACE_GEOMETRY_MAX_H;
   info->geometry.aspect_ratio = RACE_GEOMETRY_ASPECT_RATIO;
}

negativeExponent's avatar
negativeExponent committed
242
#define CPU_FREQ 6144000
negativeExponent's avatar
negativeExponent committed
243

's avatar
committed
244
245
void retro_run(void)
{
Libretro-Admin's avatar
Libretro-Admin committed
246
247
248
249
250
251
252
   unsigned i;
   bool updated = false;
   static int16_t sampleBuffer[2048];
   static int16_t stereoBuffer[2048];
   int16_t *p = NULL;
   uint16_t samplesPerFrame;

's avatar
committed
253
254
   race_input();

negativeExponent's avatar
negativeExponent committed
255
   tlcs_execute(CPU_FREQ / HOST_FPS);
's avatar
committed
256

frangarcj's avatar
frangarcj committed
257
   /* Get the number of samples in a frame */
Libretro-Admin's avatar
Libretro-Admin committed
258
   samplesPerFrame = RETRO_SAMPLE_RATE / HOST_FPS;
frangarcj's avatar
frangarcj committed
259
260
261

   memset(sampleBuffer, 0, samplesPerFrame * sizeof(int16_t));

262
   sound_update((uint16_t*)sampleBuffer, samplesPerFrame * sizeof(int16_t)); /* Get sound data */
negativeExponent's avatar
negativeExponent committed
263
   dac_update((uint16_t*)sampleBuffer, samplesPerFrame * sizeof(int16_t));
frangarcj's avatar
frangarcj committed
264

Libretro-Admin's avatar
Libretro-Admin committed
265
   p = stereoBuffer;
negativeExponent's avatar
negativeExponent committed
266
   
Libretro-Admin's avatar
Libretro-Admin committed
267
   for (i = 0; i < samplesPerFrame; i++)
frangarcj's avatar
frangarcj committed
268
269
270
271
272
   {
      p[0] = sampleBuffer[i];
      p[1] = sampleBuffer[i];
      p += 2;
   }
273

frangarcj's avatar
frangarcj committed
274
275
   audio_batch_cb(stereoBuffer, samplesPerFrame);

Libretro-Admin's avatar
Libretro-Admin committed
276
   /* TODO/FIXME - shouldn't we check this at the top of this function? */
's avatar
committed
277
278
279
280
281
282
   if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated)
      check_variables();
}

size_t retro_serialize_size(void)
{
283
   return state_get_size();
's avatar
committed
284
285
286
287
}

bool retro_serialize(void *data, size_t size)
{
288
   return state_store_mem(data);
's avatar
committed
289
290
291
292
}

bool retro_unserialize(const void *data, size_t size)
{
Libretro-Admin's avatar
Libretro-Admin committed
293
294
   int ret = state_restore_mem((void*)data);
   return (ret == 1);
's avatar
committed
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
}

bool retro_load_game(const struct retro_game_info *info)
{
   if (!info)
      return false;

   struct retro_input_descriptor desc[] = {
      { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT,  "D-Pad Left" },
      { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP,    "D-Pad Up" },
      { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN,  "D-Pad Down" },
      { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" },
      { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B,     "A" },
      { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A,     "B" },
      { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Option" },

      { 0 },
   };

   environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc);

Libretro-Admin's avatar
Libretro-Admin committed
316
   screen         = (struct ngp_screen*)calloc(1, sizeof(*screen));
317

's avatar
committed
318
319
   if (!screen)
      return false;
320

Libretro-Admin's avatar
Libretro-Admin committed
321
322
   screen->w      = FB_WIDTH;
   screen->h      = FB_HEIGHT;
's avatar
committed
323

negativeExponent's avatar
negativeExponent committed
324
   screen->pixels = calloc(1, FB_WIDTH * FB_HEIGHT * 2);
325

's avatar
committed
326
327
328
329
330
331
   if (!screen->pixels)
   {
      free(screen);
      return false;
   }

Fco Jose Garcia Garcia's avatar
Fco Jose Garcia Garcia committed
332
333
334
335
336
337
338
339
   if (!race_initialize_system(info->path))
      return false;

   if (!race_initialize_sound())
      return false;

   check_variables();

340
341
   /* TODO: Mappings might need updating
    * Size is based on what is exposed in Mednafen NGP */
342
343
344
345
346
347
348
349
   struct retro_memory_descriptor descs = {
      RETRO_MEMDESC_SYSTEM_RAM, mainram, 0, 0, 0, 0, 16384, "RAM"
   };
   struct retro_memory_map retro_map = {
      &descs, 1
   };
   environ_cb(RETRO_ENVIRONMENT_SET_MEMORY_MAPS, &retro_map);

's avatar
committed
350
351
352
   return true;
}

Libretro-Admin's avatar
Libretro-Admin committed
353
bool retro_load_game_special(unsigned a, const struct retro_game_info *b, size_t c)
's avatar
committed
354
355
356
357
358
359
{
   return false;
}

void retro_unload_game(void)
{
negativeExponent's avatar
negativeExponent committed
360
361
362
363
364
   if (screen)
   {
      if (screen->pixels)
         free(screen->pixels);
      free(screen);
negativeExponent's avatar
negativeExponent committed
365
      screen = NULL;
negativeExponent's avatar
negativeExponent committed
366
   }
's avatar
committed
367
368
369
370
371
372
373
374
375
376
}

void retro_cheat_reset(void)
{
}

void retro_cheat_set(unsigned index, bool enabled, const char *code)
{
}

377
unsigned retro_get_region(void)
's avatar
committed
378
379
380
381
382
383
384
385
386
387
388
389
{
   return RETRO_REGION_NTSC;
}

void *retro_get_memory_data(unsigned type)
{
   return NULL;
}

size_t retro_get_memory_size(unsigned type)
{
   return 0;
390
}