diff options
author | Benjamin Drung <bdrung@ubuntu.com> | 2010-07-22 20:51:38 +0200 |
---|---|---|
committer | Benjamin Drung <bdrung@ubuntu.com> | 2010-07-22 20:51:38 +0200 |
commit | f2fe41914ec32e767ec333a0cd7342e9d9bf4e13 (patch) | |
tree | 8b185d5ab501e1c1a8e8e9dd66529c84f723fcb7 /src | |
parent | 43e43d5922dd91aafb58be41f2112797fdd627db (diff) |
Imported Upstream version 2.4~beta1
Diffstat (limited to 'src')
277 files changed, 41845 insertions, 5925 deletions
diff --git a/src/CoreAudio/audio.c b/src/CoreAudio/audio.c index f06dab7..7c0e47d 100644 --- a/src/CoreAudio/audio.c +++ b/src/CoreAudio/audio.c @@ -53,7 +53,7 @@ short conv_buf[OUTPUT_BUFSIZE]; /* buffer used to hold format converted input /* * The format of the data from the input plugin - * This will never change during a song. + * This will never change during a song. */ struct format_info input; @@ -90,7 +90,7 @@ static int osx_calc_bitrate(int osx_fmt, int rate, int channels) return bitrate; } -static gboolean osx_format_is_neutral(AFormat fmt) +static gboolean osx_format_is_neutral(gint fmt) { gboolean ret = FALSE; @@ -109,7 +109,7 @@ static gboolean osx_format_is_neutral(AFormat fmt) return ret; } -static int osx_get_format(AFormat fmt) +static int osx_get_format(gint fmt) { int format = 0; @@ -137,7 +137,7 @@ static int osx_get_format(AFormat fmt) return format; } -static int osx_get_conv_format(AFormat fmt) +static int osx_get_conv_format(gint fmt) { int format = 0; @@ -248,7 +248,7 @@ OSStatus play_callback(AudioDeviceID inDevice, const AudioTimeStamp * inNow, con memset(dest,0,(src_size_float - num_output_samples) * sizeof(float)); } - + // move unwritten data to beginning of buffer { dest = buffer; @@ -283,7 +283,7 @@ OSStatus play_callback(AudioDeviceID inDevice, const AudioTimeStamp * inNow, con } -static void osx_setup_format(AFormat fmt, int rate, int nch) +static void osx_setup_format(gint fmt, int rate, int nch) { //printf("osx_setup_format(): fmt %d, rate %d, nch %d\n",fmt,rate,nch); @@ -328,7 +328,7 @@ gint osx_get_output_time(void) retval = output_time_offset + ((output_total * sample_size * 1000) / output.bps); retval = (int)((float)retval / user_pitch); - + //printf("osx_get_output_time(): time is %d\n",retval); return retval; @@ -380,7 +380,7 @@ gint osx_free(void) // get number of free samples bytes_free = buffer_size - buffer_index; - + // adjust for mono if (input.channels == 1) { @@ -422,12 +422,12 @@ void osx_write(gpointer ptr, int length) if (osx_convert_func != NULL) osx_convert_func(&ptr, length); - // step through audio + // step through audio while (num_samples > 0) { // get # of samples to write to the buffer count = MIN(num_samples, osx_free()/sample_size); - + src = ptr+offset; if (dbconvert((char*)src,count * sample_size) == -1) @@ -438,7 +438,7 @@ void osx_write(gpointer ptr, int length) { src = output_buf; dest = (float*)(buffer + buffer_index); - + //printf("output_buf_length is %d\n",output_buf_length); for (i = 0; i < output_buf_length; i++) @@ -478,7 +478,7 @@ void osx_close(void) playing_flag = 0; // close audio device - AudioDeviceStop(device_id, play_callback); + AudioDeviceStop(device_id, play_callback); AudioDeviceRemoveIOProc(device_id, play_callback); g_free(device_name); @@ -522,7 +522,7 @@ void osx_set_audio_params(void) //printf("osx_set_audio_params(): fmt %d, freq %d, nch %d\n",output.format.osx,output.frequency,output.channels); - // set audio format + // set audio format // set num channels @@ -532,10 +532,10 @@ void osx_set_audio_params(void) case 2: stereo_multiplier = 1; break; default: stereo_multiplier = 1; break; } - + switch (input.format.xmms) { - case FMT_U8: + case FMT_U8: case FMT_S8: format_multiplier = 2; sample_size = 1; @@ -557,7 +557,7 @@ void osx_set_audio_params(void) } -gint osx_open(AFormat fmt, gint rate, gint nch) +gint osx_open(gint fmt, gint rate, gint nch) { char s[32]; long m; diff --git a/src/CoreAudio/coreaudio.h b/src/CoreAudio/coreaudio.h index 4cee2f0..222bfb4 100644 --- a/src/CoreAudio/coreaudio.h +++ b/src/CoreAudio/coreaudio.h @@ -53,11 +53,11 @@ extern OutputPlugin op; -struct format_info +struct format_info { - union + union { - AFormat xmms; + gint xmms; int osx; } format; @@ -95,7 +95,7 @@ void osx_write(void *ptr, int length); void osx_close(void); void osx_flush(int time); void osx_pause(short p); -int osx_open(AFormat fmt, int rate, int nch); +int osx_open(gint fmt, int rate, int nch); int osx_get_output_time(void); int osx_get_written_time(void); void osx_set_audio_params(void); diff --git a/src/OSS/OSS.c b/src/OSS/OSS.c index 9e7e35d..db88577 100644 --- a/src/OSS/OSS.c +++ b/src/OSS/OSS.c @@ -22,6 +22,8 @@ #include "OSS.h" #include <glib.h> + +#include <audacious/configdb.h> #include <audacious/i18n.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> diff --git a/src/OSS/OSS.h b/src/OSS/OSS.h index 43c41e4..04cf688 100644 --- a/src/OSS/OSS.h +++ b/src/OSS/OSS.h @@ -60,10 +60,10 @@ void oss_write(void *ptr, int length); void oss_close(void); void oss_flush(int time); void oss_pause(short p); -int oss_open(AFormat fmt, int rate, int nch); +int oss_open(gint fmt, int rate, int nch); int oss_get_output_time(void); int oss_get_written_time(void); void oss_set_audio_params(void); -void oss_tell(AFormat * fmt, gint * rate, gint * nch); +void oss_tell(gint * fmt, gint * rate, gint * nch); #endif diff --git a/src/OSS/audio.c b/src/OSS/audio.c index c03ac94..1edf718 100644 --- a/src/OSS/audio.c +++ b/src/OSS/audio.c @@ -30,6 +30,8 @@ extern void close_mixer_device(); #include <sys/ioctl.h> #include <sys/time.h> +#include <audacious/audconfig.h> + #include "OSS.h" @@ -50,7 +52,7 @@ static gboolean select_works; struct format_info { union { - AFormat xmms; + gint xmms; int oss; } format; int frequency; @@ -98,7 +100,7 @@ oss_calc_bitrate(int oss_fmt, int rate, int channels) } static int -oss_get_format(AFormat fmt) +oss_get_format(gint fmt) { int format = 0; @@ -129,7 +131,7 @@ oss_get_format(AFormat fmt) } static void -oss_setup_format(AFormat fmt, int rate, int nch) +oss_setup_format(gint fmt, int rate, int nch) { output.bps = oss_calc_bitrate(oss_get_format(fmt), rate, nch); output.format.oss = oss_get_format(fmt); @@ -394,7 +396,7 @@ oss_set_audio_params(void) } gint -oss_open(AFormat fmt, gint rate, gint nch) +oss_open(gint fmt, gint rate, gint nch) { if (oss_cfg.use_alt_audio_device && oss_cfg.alt_audio_device) @@ -450,7 +452,7 @@ oss_open(AFormat fmt, gint rate, gint nch) return 1; } -void oss_tell(AFormat * fmt, gint * rate, gint * nch) +void oss_tell(gint * fmt, gint * rate, gint * nch) { (*fmt) = input.format.xmms; (*rate) = input.frequency; diff --git a/src/OSS/configure.c b/src/OSS/configure.c index 594928c..d952a65 100644 --- a/src/OSS/configure.c +++ b/src/OSS/configure.c @@ -26,9 +26,9 @@ #include <stdio.h> #include <string.h> +#include <audacious/configdb.h> #include <audacious/i18n.h> - static GtkWidget *configure_win = NULL; static GtkWidget *mixer_usemaster_check, *buffer_pre_spin; static GtkWidget *adevice_use_alt_check, *audio_alt_device_entry; diff --git a/src/aac/libmp4.c b/src/aac/libmp4.c index 2fe2ce5..1e77785 100644 --- a/src/aac/libmp4.c +++ b/src/aac/libmp4.c @@ -9,6 +9,7 @@ #include <audacious/plugin.h> #include <audacious/i18n.h> +#include <libaudcore/audstrings.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> @@ -60,7 +61,7 @@ static guint32 mp4_read_callback(void *data, void *buffer, guint32 len) if (data == NULL || buffer == NULL) return -1; - return aud_vfs_fread(buffer, 1, len, (VFSFile *) data); + return vfs_fread(buffer, 1, len, (VFSFile *) data); } static guint32 mp4_seek_callback (void * data, guint64 pos) @@ -68,7 +69,7 @@ static guint32 mp4_seek_callback (void * data, guint64 pos) g_return_val_if_fail (data != NULL, -1); g_return_val_if_fail (pos <= G_MAXLONG, -1); - return aud_vfs_fseek((VFSFile *) data, pos, SEEK_SET); + return vfs_fseek((VFSFile *) data, pos, SEEK_SET); } static void mp4_init(void) @@ -195,7 +196,7 @@ static gboolean parse_aac_stream (VFSFile * stream) size = 0; /* avoid bogus uninitialized variable warning */ - if (aud_vfs_fread (data, 1, sizeof data, stream) != sizeof data) + if (vfs_fread (data, 1, sizeof data, stream) != sizeof data) { PROBE_DEBUG ("Read failed.\n"); return FALSE; @@ -268,12 +269,12 @@ static gint mp4_is_our_fd(const gchar *filename, VFSFile* file) gchar magic[8]; extension = strrchr(filename, '.'); - aud_vfs_fread(magic, 1, 8, file); - aud_vfs_rewind(file); + vfs_fread(magic, 1, 8, file); + vfs_rewind(file); if (parse_aac_stream(file) == TRUE) return 1; - aud_vfs_fseek (file, 0, SEEK_SET); + vfs_fseek (file, 0, SEEK_SET); return is_mp4_aac_file (file); } @@ -310,7 +311,7 @@ static void calc_aac_info (VFSFile * handle, gint * length, gint * bitrate, NeAACDecHandle decoder; NeAACDecFrameInfo frame; gboolean initted = FALSE; - gint size = aud_vfs_fsize (handle); + gint size = vfs_fsize (handle); guchar buffer[BUFFER_SIZE]; gint offset = 0, filled = 0; gint found, bytes_used = 0, time_used = 0; @@ -324,7 +325,7 @@ static void calc_aac_info (VFSFile * handle, gint * length, gint * bitrate, /* look for a representative bitrate in the middle of the file */ if (size > 0) - aud_vfs_fseek (handle, size / 2, SEEK_SET); + vfs_fseek (handle, size / 2, SEEK_SET); for (found = 0; found < 32; found ++) { @@ -333,7 +334,7 @@ static void calc_aac_info (VFSFile * handle, gint * length, gint * bitrate, memmove (buffer, buffer + offset, filled); offset = 0; - if (aud_vfs_fread (buffer + filled, 1, BUFFER_SIZE - filled, handle) + if (vfs_fread (buffer + filled, 1, BUFFER_SIZE - filled, handle) != BUFFER_SIZE - filled) { PROBE_DEBUG ("Read failed.\n"); @@ -417,7 +418,7 @@ static Tuple * aac_get_tuple (const gchar * filename, VFSFile * handle) tuple_associate_string (tuple, FIELD_CODEC, NULL, "MPEG-2/4 AAC"); - if (! aud_vfs_is_remote (filename)) + if (! vfs_is_remote (filename)) { calc_aac_info (handle, & length, & bitrate, & samplerate, & channels); @@ -428,21 +429,21 @@ static Tuple * aac_get_tuple (const gchar * filename, VFSFile * handle) tuple_associate_int (tuple, FIELD_BITRATE, NULL, bitrate); } - temp = aud_vfs_get_metadata (handle, "track-name"); + temp = vfs_get_metadata (handle, "track-name"); if (temp != NULL) { tuple_associate_string (tuple, FIELD_TITLE, NULL, temp); g_free (temp); } - temp = aud_vfs_get_metadata (handle, "stream-name"); + temp = vfs_get_metadata (handle, "stream-name"); if (temp != NULL) { tuple_associate_string (tuple, FIELD_ALBUM, NULL, temp); g_free (temp); } - temp = aud_vfs_get_metadata (handle, "content-bitrate"); + temp = vfs_get_metadata (handle, "content-bitrate"); if (temp != NULL) { tuple_associate_int (tuple, FIELD_BITRATE, NULL, atoi (temp) / 1000); @@ -456,7 +457,7 @@ static gboolean aac_title_changed (const gchar * filename, VFSFile * handle, Tuple * tuple) { const gchar * old = tuple_get_string (tuple, FIELD_TITLE, NULL); - gchar * new = aud_vfs_get_metadata (handle, "track-name"); + gchar * new = vfs_get_metadata (handle, "track-name"); gboolean changed = FALSE; changed = (new != NULL && (old == NULL || strcmp (old, new))); @@ -544,7 +545,7 @@ static Tuple * mp4_get_tuple (const gchar * filename, VFSFile * handle) if (parse_aac_stream (handle)) return aac_get_tuple (filename, handle); - aud_vfs_fseek (handle, 0, SEEK_SET); + vfs_fseek (handle, 0, SEEK_SET); mp4cb.read = mp4_read_callback; mp4cb.seek = mp4_seek_callback; @@ -718,8 +719,7 @@ static int my_decode_mp4( InputPlayback *playback, char *filename, mp4ff_t *mp4f bufferSize=0; } - playback->pass_audio (playback, FMT_S16_NE, channels, 2 * - frameInfo.samples, sampleBuffer, NULL); + playback->output->write_audio (sampleBuffer, 2 * frameInfo.samples); } playback->output->close_audio(); @@ -737,8 +737,8 @@ void my_decode_aac( InputPlayback *playback, char *filename, VFSFile *file ) guchar channels = 0; gulong buffervalid = 0; gulong ret = 0; - gboolean remote = aud_str_has_prefix_nocase(filename, "http:") || - aud_str_has_prefix_nocase(filename, "https:"); + gboolean remote = str_has_prefix_nocase(filename, "http:") || + str_has_prefix_nocase(filename, "https:"); gboolean paused = FALSE; Tuple * tuple; gint bitrate = 0; @@ -753,17 +753,17 @@ void my_decode_aac( InputPlayback *playback, char *filename, VFSFile *file ) bitrate = 1000 * MAX (0, bitrate); } - aud_vfs_rewind(file); + vfs_rewind(file); if((decoder = NeAACDecOpen()) == NULL){ g_print("AAC: Open Decoder Error\n"); - aud_vfs_fclose(file); + vfs_fclose(file); playback->playing = FALSE; return; } - if((buffervalid = aud_vfs_fread(streambuffer, 1, BUFFER_SIZE, file))==0){ + if((buffervalid = vfs_fread(streambuffer, 1, BUFFER_SIZE, file))==0){ g_print("AAC: Error reading file\n"); - aud_vfs_fclose(file); + vfs_fclose(file); NeAACDecClose(decoder); playback->playing = FALSE; @@ -772,19 +772,19 @@ void my_decode_aac( InputPlayback *playback, char *filename, VFSFile *file ) if(!strncmp((char*)streambuffer, "ID3", 3)){ gint size = 0; - aud_vfs_fseek(file, 0, SEEK_SET); + vfs_fseek(file, 0, SEEK_SET); size = (streambuffer[6]<<21) | (streambuffer[7]<<14) | (streambuffer[8]<<7) | streambuffer[9]; size+=10; - aud_vfs_fread(streambuffer, 1, size, file); - buffervalid = aud_vfs_fread(streambuffer, 1, BUFFER_SIZE, file); + vfs_fread(streambuffer, 1, size, file); + buffervalid = vfs_fread(streambuffer, 1, BUFFER_SIZE, file); } bufferconsumed = aac_probe(streambuffer, buffervalid); if(bufferconsumed) { buffervalid -= bufferconsumed; memmove(streambuffer, &streambuffer[bufferconsumed], buffervalid); - buffervalid += aud_vfs_fread(&streambuffer[buffervalid], 1, + buffervalid += vfs_fread(&streambuffer[buffervalid], 1, BUFFER_SIZE-buffervalid, file); } @@ -798,7 +798,7 @@ void my_decode_aac( InputPlayback *playback, char *filename, VFSFile *file ) #endif if(playback->output->open_audio(FMT_S16_NE,samplerate,channels) == FALSE){ NeAACDecClose(decoder); - aud_vfs_fclose(file); + vfs_fclose(file); playback->playing = FALSE; playback->error = TRUE; return; @@ -841,7 +841,7 @@ void my_decode_aac( InputPlayback *playback, char *filename, VFSFile *file ) { buffervalid -= bufferconsumed; memmove(streambuffer, &streambuffer[bufferconsumed], buffervalid); - ret = aud_vfs_fread(&streambuffer[buffervalid], 1, + ret = vfs_fread(&streambuffer[buffervalid], 1, BUFFER_SIZE-buffervalid, file); buffervalid += ret; bufferconsumed = 0; @@ -868,7 +868,7 @@ void my_decode_aac( InputPlayback *playback, char *filename, VFSFile *file ) memmove(streambuffer, &streambuffer[1], buffervalid); if(buffervalid < BUFFER_SIZE) { buffervalid += - aud_vfs_fread(&streambuffer[buffervalid], 1, BUFFER_SIZE-buffervalid, file); + vfs_fread(&streambuffer[buffervalid], 1, BUFFER_SIZE-buffervalid, file); } bufferconsumed = aac_probe(streambuffer, buffervalid); if(bufferconsumed) { @@ -886,12 +886,11 @@ void my_decode_aac( InputPlayback *playback, char *filename, VFSFile *file ) continue; } - playback->pass_audio (playback, FMT_S16_LE, channels, 2 * - samplesdecoded, sample_buffer, NULL); + playback->output->write_audio (sample_buffer, 2 * samplesdecoded); } playback->output->close_audio(); NeAACDecClose(decoder); - aud_vfs_fclose(file); + vfs_fclose(file); if (tuple != NULL) mowgli_object_unref (tuple); @@ -909,7 +908,7 @@ static void *mp4_decode( void *args ) InputPlayback *playback = args; char *filename = playback->filename; - mp4fh = aud_vfs_fopen (filename, "r"); + mp4fh = vfs_fopen (filename, "r"); if (mp4fh == NULL) return NULL; @@ -917,10 +916,10 @@ static void *mp4_decode( void *args ) ret = parse_aac_stream(mp4fh); if( ret == TRUE ) - aud_vfs_fseek(mp4fh, 0, SEEK_SET); + vfs_fseek(mp4fh, 0, SEEK_SET); else { - aud_vfs_fclose(mp4fh); - mp4fh = aud_vfs_fopen(filename, "rb"); + vfs_fclose(mp4fh); + mp4fh = vfs_fopen(filename, "rb"); } mp4cb->read = mp4_read_callback; diff --git a/src/adplug/adplug-xmms.cc b/src/adplug/adplug-xmms.cc index 795e92f..88bf3fe 100644 --- a/src/adplug/adplug-xmms.cc +++ b/src/adplug/adplug-xmms.cc @@ -29,10 +29,14 @@ #include "emuopl.h" #include "silentopl.h" #include "players.h" + +extern "C" { +#include <audacious/configdb.h> #include <audacious/i18n.h> -extern "C" -{ +#include <audacious/misc.h> #include <audacious/plugin.h> +#include <libaudcore/tuple_formatter.h> +#include <libaudcore/vfs_buffered_file.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> } @@ -481,7 +485,7 @@ extern "C" void adplug_info_box (const gchar *filename) { CSilentopl tmpopl; - VFSFile *fd = aud_vfs_buffered_file_new_from_uri (filename); + VFSFile *fd = vfs_buffered_file_new_from_uri (filename); if (!fd) return; @@ -655,7 +659,7 @@ adplug_get_tuple (const gchar *filename) { Tuple * ti = NULL; CSilentopl tmpopl; - VFSFile *fd = aud_vfs_buffered_file_new_from_uri (filename); + VFSFile *fd = vfs_buffered_file_new_from_uri (filename); if (!fd) return NULL; @@ -664,32 +668,32 @@ adplug_get_tuple (const gchar *filename) if (p) { - ti = aud_tuple_new_from_filename (filename); + ti = tuple_new_from_filename (filename); if (! p->getauthor().empty()) - aud_tuple_associate_string(ti, FIELD_ARTIST, NULL, p->getauthor().c_str()); + tuple_associate_string(ti, FIELD_ARTIST, NULL, p->getauthor().c_str()); if (! p->gettitle().empty()) - aud_tuple_associate_string(ti, FIELD_TITLE, NULL, p->gettitle().c_str()); + tuple_associate_string(ti, FIELD_TITLE, NULL, p->gettitle().c_str()); else if (! p->getdesc().empty()) - aud_tuple_associate_string(ti, FIELD_TITLE, NULL, p->getdesc().c_str()); + tuple_associate_string(ti, FIELD_TITLE, NULL, p->getdesc().c_str()); else - aud_tuple_associate_string(ti, FIELD_TITLE, NULL, g_path_get_basename(filename)); - aud_tuple_associate_string(ti, FIELD_CODEC, NULL, p->gettype().c_str()); - aud_tuple_associate_string(ti, FIELD_QUALITY, NULL, "sequenced"); - aud_tuple_associate_int(ti, FIELD_LENGTH, NULL, p->songlength (plr.subsong)); + tuple_associate_string(ti, FIELD_TITLE, NULL, g_path_get_basename(filename)); + tuple_associate_string(ti, FIELD_CODEC, NULL, p->gettype().c_str()); + tuple_associate_string(ti, FIELD_QUALITY, NULL, "sequenced"); + tuple_associate_int(ti, FIELD_LENGTH, NULL, p->songlength (plr.subsong)); delete p; } - aud_vfs_fclose (fd); + vfs_fclose (fd); return ti; } static char* format_and_free_ti( Tuple* ti, int* length ) { - char* result = aud_tuple_formatter_make_title_string(ti, aud_get_gentitle_format()); + char* result = tuple_formatter_make_title_string(ti, aud_get_gentitle_format()); if ( result ) - *length = aud_tuple_get_int(ti, FIELD_LENGTH, NULL); - aud_tuple_free((void *) ti); + *length = tuple_get_int(ti, FIELD_LENGTH, NULL); + tuple_free((void *) ti); return result; } @@ -736,7 +740,7 @@ play_loop (void *data) // we use VfsBufferedFile class here because adplug does a lot of // probing. a short delay before probing begins is better than // a lot of delay during probing. - VFSFile *fd = aud_vfs_buffered_file_new_from_uri (playback->filename); + VFSFile *fd = vfs_buffered_file_new_from_uri (playback->filename); if (!fd) return (NULL); @@ -881,7 +885,7 @@ play_loop (void *data) } free (sndbuf); dbg_printf (".\n"); - aud_vfs_fclose (fd); + vfs_fclose (fd); return (NULL); } @@ -1031,7 +1035,7 @@ adplug_init (void) { std::string userdb; userdb = "file://" + std::string(g_get_home_dir()) + "/" ADPLUG_CONFDIR "/" + ADPLUGDB_FILE; - if (aud_vfs_file_test(userdb.c_str(),G_FILE_TEST_EXISTS)) { + if (vfs_file_test(userdb.c_str(),G_FILE_TEST_EXISTS)) { plr.db->load (userdb); // load user's database dbg_printf (" (userdb=\"%s\")", userdb.c_str()); } diff --git a/src/adplug/core/adplug.cxx b/src/adplug/core/adplug.cxx index 0fe4ae4..c9e243e 100644 --- a/src/adplug/core/adplug.cxx +++ b/src/adplug/core/adplug.cxx @@ -154,7 +154,7 @@ CAdPlug::factory (VFSFile * fd, Copl * opl, const CPlayers & pl, if (fp.extension (fd->uri, (*i)->get_extension (j))) { AdPlug_LogWrite ("Trying direct hit: %s\n", (*i)->filetype.c_str ()); - aud_vfs_rewind (fd); + vfs_rewind (fd); if ((p = (*i)->factory (opl))) { if (p->load (fd, fp)) diff --git a/src/adplug/core/adtrack.cxx b/src/adplug/core/adtrack.cxx index 86c1cb2..9ae565b 100644 --- a/src/adplug/core/adtrack.cxx +++ b/src/adplug/core/adtrack.cxx @@ -70,12 +70,12 @@ CadtrackLoader::load (VFSFile * fd, const CFileProvider & fp) AdPlug_LogWrite ("CadtrackLoader::load(,\"%s\"): Checking for \"%s\"...\n", filename.c_str (), instfilename.c_str ()); - VFSFile *instfd = aud_vfs_fopen (instfilename.c_str (), "rb"); + VFSFile *instfd = vfs_fopen (instfilename.c_str (), "rb"); instf = fp.open (instfd); if (!instf || fp.filesize (instf) != 468) { fp.close (f); - aud_vfs_fclose (instfd); + vfs_fclose (instfd); return false; } diff --git a/src/adplug/core/binio_virtual.h b/src/adplug/core/binio_virtual.h index 265063b..8b2f27a 100644 --- a/src/adplug/core/binio_virtual.h +++ b/src/adplug/core/binio_virtual.h @@ -30,24 +30,24 @@ public: }; vfsistream(const char *file) { - this->fd = aud_vfs_fopen(file, "rb"); + this->fd = vfs_fopen(file, "rb"); }; vfsistream(std::string &file) { - this->fd = aud_vfs_fopen(file.c_str(), "rb"); + this->fd = vfs_fopen(file.c_str(), "rb"); }; void open(const char *file) { - this->fd = aud_vfs_fopen(file, "rb"); + this->fd = vfs_fopen(file, "rb"); }; void open(std::string &file) { - this->fd = aud_vfs_fopen(file.c_str(), "rb"); + this->fd = vfs_fopen(file.c_str(), "rb"); }; // XXX: this sucks because binio won't let us do sanity checking Byte getByte(void) { - int c = aud_vfs_getc(this->fd); + int c = vfs_getc(this->fd); if (c == EOF) err |= Eof; @@ -58,21 +58,21 @@ public: switch (offs) { case Add: - aud_vfs_fseek(this->fd, pos, SEEK_CUR); + vfs_fseek(this->fd, pos, SEEK_CUR); break; case End: - aud_vfs_fseek(this->fd, pos, SEEK_END); + vfs_fseek(this->fd, pos, SEEK_END); break; case Set: default: - aud_vfs_fseek(this->fd, pos, SEEK_SET); + vfs_fseek(this->fd, pos, SEEK_SET); break; } } long pos(void) { - return aud_vfs_ftell(this->fd); + return vfs_ftell(this->fd); } }; @@ -90,45 +90,45 @@ public: }; vfsostream(const char *file) { - this->fd = aud_vfs_fopen(file, "wb"); + this->fd = vfs_fopen(file, "wb"); }; vfsostream(std::string &file) { - this->fd = aud_vfs_fopen(file.c_str(), "wb"); + this->fd = vfs_fopen(file.c_str(), "wb"); }; void open(const char *file) { - this->fd = aud_vfs_fopen(file, "wb"); + this->fd = vfs_fopen(file, "wb"); }; void open(std::string &file) { - this->fd = aud_vfs_fopen(file.c_str(), "wb"); + this->fd = vfs_fopen(file.c_str(), "wb"); }; // XXX: this sucks because binio won't let us do sanity checking void putByte(Byte b) { - aud_vfs_fwrite(&b, 1, 1, this->fd); + vfs_fwrite(&b, 1, 1, this->fd); }; void seek(long pos, Offset offs = Set) { switch (offs) { case Add: - aud_vfs_fseek(this->fd, pos, SEEK_CUR); + vfs_fseek(this->fd, pos, SEEK_CUR); break; case End: - aud_vfs_fseek(this->fd, pos, SEEK_END); + vfs_fseek(this->fd, pos, SEEK_END); break; case Set: default: - aud_vfs_fseek(this->fd, pos, SEEK_SET); + vfs_fseek(this->fd, pos, SEEK_SET); break; } } long pos(void) { - return aud_vfs_ftell(this->fd); + return vfs_ftell(this->fd); } }; diff --git a/src/adplug/core/ksm.cxx b/src/adplug/core/ksm.cxx index 4a8c3c3..6d3d259 100644 --- a/src/adplug/core/ksm.cxx +++ b/src/adplug/core/ksm.cxx @@ -67,7 +67,7 @@ CksmPlayer::load (VFSFile * fd, const CFileProvider & fp) break; strcpy (fn + i + 1, "insts.dat"); AdPlug_LogWrite ("Instruments file: \"%s\"\n", fn); - VFSFile *instfd = aud_vfs_fopen (fn, "rb"); + VFSFile *instfd = vfs_fopen (fn, "rb"); f = fp.open (instfd); delete[]fn; if (!f) @@ -78,7 +78,7 @@ CksmPlayer::load (VFSFile * fd, const CFileProvider & fp) } loadinsts (f); fp.close (f); - aud_vfs_fclose (instfd); + vfs_fclose (instfd); f = fp.open (fd); if (!f) diff --git a/src/adplug/core/mid.cxx b/src/adplug/core/mid.cxx index 036b597..da918a6 100644 --- a/src/adplug/core/mid.cxx +++ b/src/adplug/core/mid.cxx @@ -183,12 +183,12 @@ CmidPlayer::load_sierra_ins (const std::string & fname, } sprintf (pfilename + j + 3, "patch.003"); - VFSFile *instfd = aud_vfs_fopen (pfilename, "rb"); + VFSFile *instfd = vfs_fopen (pfilename, "rb"); f = fp.open (instfd); free (pfilename); if (!f) { - aud_vfs_fclose (instfd); + vfs_fclose (instfd); return false; } @@ -228,7 +228,7 @@ CmidPlayer::load_sierra_ins (const std::string & fname, } fp.close (f); - aud_vfs_fclose (instfd); + vfs_fclose (instfd); memcpy (smyinsbank, myinsbank, 128 * 16); return true; } diff --git a/src/adplug/core/rol.cxx b/src/adplug/core/rol.cxx index 67bc584..96df802 100644 --- a/src/adplug/core/rol.cxx +++ b/src/adplug/core/rol.cxx @@ -469,7 +469,7 @@ void CrolPlayer::load_tempo_events( binistream *f ) bool CrolPlayer::load_voice_data( binistream *f, std::string const &bnk_filename, const CFileProvider &fp ) { SBnkHeader bnk_header; - VFSFile *fd = aud_vfs_fopen(bnk_filename.c_str(), "rb"); + VFSFile *fd = vfs_fopen(bnk_filename.c_str(), "rb"); binistream *bnk_file = fp.open(fd); if( bnk_file ) @@ -492,7 +492,7 @@ bool CrolPlayer::load_voice_data( binistream *f, std::string const &bnk_filename } fp.close(bnk_file); - aud_vfs_fclose(fd); + vfs_fclose(fd); return true; } diff --git a/src/alarm/alarm.c b/src/alarm/alarm.c index 0a034c2..ca1baeb 100644 --- a/src/alarm/alarm.c +++ b/src/alarm/alarm.c @@ -38,14 +38,18 @@ #include <string.h> #include <stdio.h> -#include <audacious/plugin.h> -#include <audacious/auddrct.h> + #include <gdk/gdk.h> #include <gtk/gtk.h> #include <pthread.h> #include <assert.h> #include <math.h> +#include <audacious/configdb.h> +#include <audacious/debug.h> +#include <audacious/drct.h> +#include <audacious/plugin.h> + #include "alarm.h" #include "interface.h" #include "callbacks.h" @@ -181,11 +185,11 @@ void alarm_save(GtkButton *w, gpointer data) /* * update the live values and write them out */ - alarm_h = alarm_conf.default_hour = + alarm_h = alarm_conf.default_hour = gtk_spin_button_get_value_as_int(alarm_conf.alarm_h); aud_cfg_db_set_int(conf, "alarm", "alarm_h", alarm_h); - alarm_m = alarm_conf.default_min = + alarm_m = alarm_conf.default_min = gtk_spin_button_get_value_as_int(alarm_conf.alarm_m); aud_cfg_db_set_int(conf, "alarm", "alarm_m", alarm_m); @@ -206,13 +210,13 @@ void alarm_save(GtkButton *w, gpointer data) alarm_conf.day[daynum].flags = 0; else alarm_conf.day[daynum].flags = ALARM_OFF; - + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(alarm_conf.day[daynum].cb_def))) alarm_conf.day[daynum].flags |= ALARM_DEFAULT; - alarm_conf.day[daynum].hour = + alarm_conf.day[daynum].hour = gtk_spin_button_get_value_as_int(alarm_conf.day[daynum].spin_hr); - alarm_conf.day[daynum].min = + alarm_conf.day[daynum].min = gtk_spin_button_get_value_as_int(alarm_conf.day[daynum].spin_min); aud_cfg_db_set_int(conf, "alarm", day_flags[daynum], alarm_conf.day[daynum].flags); @@ -277,8 +281,8 @@ void alarm_save(GtkButton *w, gpointer data) alarm_conf.reminder_msg = gtk_editable_get_chars(GTK_EDITABLE(alarm_conf.reminder), 0, -1); aud_cfg_db_set_string(conf, "alarm", "reminder_msg", alarm_conf.reminder_msg); - - alarm_conf.reminder_on = + + alarm_conf.reminder_on = gtk_toggle_button_get_active(alarm_conf.reminder_cb); aud_cfg_db_set_bool(conf, "alarm", "reminder_on", alarm_conf.reminder_on); @@ -493,7 +497,7 @@ static void alarm_configure(void) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(alarm_conf.day[daynum].cb_def), alarm_conf.day[daynum].flags & ALARM_DEFAULT); - + /* Changed to show default time instead of set time when ALARM_DEFAULT set, * as suggested by Mark Brown */ @@ -649,7 +653,7 @@ void alarm_current_volume(GtkButton *button, gpointer data) AUDDBG("on_current_button_clicked\n"); - audacious_drct_get_volume_main(&vol); + aud_drct_get_volume_main(&vol); adj = gtk_range_get_adjustment(alarm_conf.volume); gtk_adjustment_set_value(adj, (gfloat)vol); @@ -677,7 +681,7 @@ static inline pthread_t alarm_thread_create(void *(*start_routine)(void *), void if(detach != 0) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - + pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); pthread_attr_setschedpolicy(&attr, SCHED_OTHER); pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); @@ -698,7 +702,7 @@ static void *alarm_fade(void *arg) pthread_mutex_lock(&fader_lock); /* slide volume */ - /* the Kaspar Giger way of fading, check the current mixer volume and + /* the Kaspar Giger way of fading, check the current mixer volume and * increment from there so that if you have some other app lowering the * volume at the same time xmms-alarm will not ignore it. If you have some * other app increasing the volume, then it could get louder that you expect @@ -714,20 +718,20 @@ static void *alarm_fade(void *arg) inc = -1; else inc = 1; - - audacious_drct_set_volume_main((gint)vols->start); + + aud_drct_set_volume_main((gint)vols->start); //for(i=0;i<(vols->end - vols->start);i++) for(i=0;i<adiff;i++) { //threadsleep((gfloat)fading / (vols->end - vols->start)); threadsleep((gfloat)fading / (gfloat)adiff); - audacious_drct_get_volume_main(&v); - audacious_drct_set_volume_main(v + inc); + aud_drct_get_volume_main(&v); + aud_drct_set_volume_main(v + inc); } /* Setting the volume to the end volume sort of defeats the point if having * the code in there to allow other apps to control volume too :) */ - //audacious_drct_set_volume_main((gint)vols->end); + //aud_drct_set_volume_main((gint)vols->end); /* and */ pthread_mutex_unlock(&fader_lock); @@ -755,7 +759,7 @@ static void *alarm_stop_thread( void *args ) if (dialog_visible(alarm_dialog)) gtk_widget_destroy(alarm_dialog); - audacious_drct_get_volume_main(&currvol), + aud_drct_get_volume_main(&currvol), /* fade back to zero */ fade_vols.start = currvol; @@ -765,13 +769,13 @@ static void *alarm_stop_thread( void *args ) f_tid = alarm_thread_create(alarm_fade, &fade_vols, 0); pthread_join(f_tid, NULL); - audacious_drct_stop(); + aud_drct_stop(); /* might as well set the volume to something higher than zero so we * dont confuse the poor people who just woke up and cant work out why * theres no music playing when they press the little play button :) */ - audacious_drct_set_volume_main(currvol); + aud_drct_set_volume_main(currvol); AUDDBG("alarm_stop done\n"); return(NULL); @@ -863,20 +867,20 @@ static void *alarm_start_thread(void *args) list.prev = list.next = NULL; list.data = playlist; - audacious_drct_pl_clear(); - audacious_drct_pl_add(&list); + aud_drct_pl_clear(); + aud_drct_pl_add_list (& list, -1); } if(fading) { fader fade_vols; - + AUDDBG("Fading is true\n"); - audacious_drct_set_volume_main(quietvol); + aud_drct_set_volume_main(quietvol); /* start playing */ play_start = time(NULL); - audacious_drct_play(); + aud_drct_play(); /* fade volume */ fade_vols.start = quietvol; @@ -890,11 +894,11 @@ static void *alarm_start_thread(void *args) /* no fading */ /* set volume */ - audacious_drct_set_volume_main(volume); + aud_drct_set_volume_main(volume); /* start playing */ play_start = time(NULL); - audacious_drct_play(); + aud_drct_play(); } if(alarm_conf.reminder_on == TRUE) diff --git a/src/alsa/alsa.c b/src/alsa/alsa.c index 8470336..b407a9e 100755 --- a/src/alsa/alsa.c +++ b/src/alsa/alsa.c @@ -37,6 +37,7 @@ * before joining the thread. */ +#include <assert.h> #include <errno.h> #include <poll.h> #include <stdint.h> @@ -46,6 +47,9 @@ #include <alsa/asoundlib.h> #include <glib.h> +#include <audacious/audconfig.h> +#include <audacious/debug.h> + #include "alsa.h" #define CHECK_VAL_RECOVER(value, function, ...) \ @@ -64,7 +68,7 @@ do { \ } while (0) static snd_pcm_t * alsa_handle; -static int alsa_initted; +static char alsa_initted; pthread_mutex_t alsa_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t alsa_cond = PTHREAD_COND_INITIALIZER; @@ -75,26 +79,27 @@ static void * alsa_buffer; static int alsa_buffer_length, alsa_buffer_data_start, alsa_buffer_data_length; static int64_t alsa_time; /* microseconds */ -static int alsa_paused, alsa_paused_time; +static char alsa_prebuffer, alsa_paused; +static int alsa_paused_time; static int poll_pipe[2]; -static int poll_count; +static int poll_count; static struct pollfd * poll_handles; -static int pump_quit; +static char pump_quit; static pthread_t pump_thread; static snd_mixer_t * alsa_mixer; static snd_mixer_elem_t * alsa_mixer_element; -static int poll_setup (void) +static char poll_setup (void) { if (pipe (poll_pipe)) { ERROR ("Failed to create pipe: %s.\n", strerror (errno)); return 0; } - + if (fcntl (poll_pipe[0], F_SETFL, O_NONBLOCK)) { ERROR ("Failed to set O_NONBLOCK on pipe: %s.\n", strerror (errno)); @@ -118,7 +123,7 @@ static void poll_sleep (void) char c; poll (poll_handles, poll_count, -1); - + if (poll_handles[0].revents & POLLIN) { while (read (poll_pipe[0], & c, 1) == 1) @@ -149,7 +154,7 @@ static void * pump (void * unused) while (! pump_quit) { - if (alsa_paused || ! alsa_buffer_data_length) + if (alsa_prebuffer || alsa_paused || ! alsa_buffer_data_length) { pthread_cond_wait (& alsa_cond, & alsa_mutex); continue; @@ -212,14 +217,10 @@ static void pump_stop (void) static void start_playback (void) { AUDDBG ("Starting playback.\n"); - - if (snd_pcm_state (alsa_handle) == SND_PCM_STATE_PAUSED) - CHECK (snd_pcm_pause, alsa_handle, 0); - else - CHECK (snd_pcm_prepare, alsa_handle); + CHECK (snd_pcm_prepare, alsa_handle); FAILED: - alsa_paused = 0; + alsa_prebuffer = 0; pthread_cond_broadcast (& alsa_cond); } @@ -304,7 +305,7 @@ static int convert_aud_format (int aud_format) return SND_PCM_FORMAT_UNKNOWN; } -int alsa_open_audio (AFormat aud_format, int rate, int channels) +int alsa_open_audio (gint aud_format, int rate, int channels) { int format = convert_aud_format (aud_format); snd_pcm_hw_params_t * params; @@ -352,7 +353,8 @@ int alsa_open_audio (AFormat aud_format, int rate, int channels) alsa_buffer_data_length = 0; alsa_time = 0; - alsa_paused = 1; /* for buffering */ + alsa_prebuffer = 1; + alsa_paused = 0; alsa_paused_time = 0; if (! poll_setup ()) @@ -391,42 +393,53 @@ FAILED: pthread_mutex_unlock (& alsa_mutex); } +int alsa_buffer_free (void) +{ + pthread_mutex_lock (& alsa_mutex); + int avail = alsa_buffer_length - alsa_buffer_data_length; + pthread_mutex_unlock (& alsa_mutex); + return avail; +} + void alsa_write_audio (void * data, int length) { pthread_mutex_lock (& alsa_mutex); - while (1) + int start = (alsa_buffer_data_start + alsa_buffer_data_length) % + alsa_buffer_length; + + assert (length <= alsa_buffer_length - alsa_buffer_data_length); + + if (length > alsa_buffer_length - start) { - int writable = MIN (alsa_buffer_length - alsa_buffer_data_length, - length); - int start = (alsa_buffer_data_start + alsa_buffer_data_length) % - alsa_buffer_length; + int part = alsa_buffer_length - start; - if (writable > alsa_buffer_length - start) - { - int part = alsa_buffer_length - start; + memcpy ((char *) alsa_buffer + start, data, part); + memcpy (alsa_buffer, (char *) data + part, length - part); + } + else + memcpy ((char *) alsa_buffer + start, data, length); - memcpy ((char *) alsa_buffer + start, data, part); - memcpy (alsa_buffer, (char *) data + part, writable - part); - } - else - memcpy ((char *) alsa_buffer + start, data, writable); + alsa_buffer_data_length += length; + alsa_time += (int64_t) snd_pcm_bytes_to_frames (alsa_handle, length) * + 1000000 / alsa_rate; - data = (char *) data + writable; - length -= writable; + pthread_mutex_unlock (& alsa_mutex); +} - alsa_buffer_data_length += writable; - alsa_time += (int64_t) snd_pcm_bytes_to_frames (alsa_handle, writable) * - 1000000 / alsa_rate; +void alsa_period_wait (void) +{ + pthread_mutex_lock (& alsa_mutex); + while (alsa_buffer_data_length == alsa_buffer_length) + { if (! alsa_paused) - pthread_cond_broadcast (& alsa_cond); - - if (! length) - break; - - if (alsa_paused) - start_playback (); + { + if (alsa_prebuffer) + start_playback (); + else + pthread_cond_broadcast (& alsa_cond); + } pthread_cond_wait (& alsa_cond, & alsa_mutex); } @@ -436,12 +449,14 @@ void alsa_write_audio (void * data, int length) void alsa_drain (void) { - int state; + int state; AUDDBG ("Drain.\n"); pthread_mutex_lock (& alsa_mutex); - if (alsa_paused) + assert (! alsa_paused); + + if (alsa_prebuffer) start_playback (); while (alsa_buffer_data_length > 0) @@ -451,24 +466,28 @@ void alsa_drain (void) if (alsa_config_drain_workaround) { - int _delay = get_delay () * 1000 / alsa_rate; - struct timespec delay = {.tv_sec = _delay / 1000, .tv_nsec = _delay % - 1000 * 1000000}; - + int d = get_delay () * 1000 / alsa_rate; + struct timespec delay = {.tv_sec = d / 1000, .tv_nsec = d % 1000 * + 1000000}; + pthread_mutex_unlock (& alsa_mutex); nanosleep (& delay, NULL); pthread_mutex_lock (& alsa_mutex); } - else while (1) + else { - CHECK_VAL (state, snd_pcm_state, alsa_handle); + while (1) + { + CHECK_VAL (state, snd_pcm_state, alsa_handle); - if (state != SND_PCM_STATE_RUNNING && state != SND_PCM_STATE_DRAINING) - break; - - pthread_mutex_unlock (& alsa_mutex); - poll_sleep (); - pthread_mutex_lock (& alsa_mutex); + if (state != SND_PCM_STATE_RUNNING && state != + SND_PCM_STATE_DRAINING) + break; + + pthread_mutex_unlock (& alsa_mutex); + poll_sleep (); + pthread_mutex_lock (& alsa_mutex); + } } pump_start (); @@ -502,7 +521,7 @@ int alsa_output_time (void) pthread_mutex_lock (& alsa_mutex); - if (alsa_paused) + if (alsa_prebuffer || alsa_paused) time = alsa_paused_time; else time = get_output_time (); @@ -524,9 +543,11 @@ FAILED: alsa_buffer_data_length = 0; alsa_time = (int64_t) time * 1000; - alsa_paused = 1; /* for buffering */ + alsa_prebuffer = 1; alsa_paused_time = time; + pthread_cond_broadcast (& alsa_cond); /* interrupt period wait */ + pump_start (); pthread_mutex_unlock (& alsa_mutex); @@ -537,10 +558,12 @@ void alsa_pause (short pause) AUDDBG ("%sause.\n", pause ? "P" : "Unp"); pthread_mutex_lock (& alsa_mutex); - if (pause) + alsa_paused = pause; + + if (! alsa_prebuffer) { - alsa_paused = 1; - alsa_paused_time = get_output_time (); + if (pause) + alsa_paused_time = get_output_time (); CHECK (snd_pcm_pause, alsa_handle, pause); } diff --git a/src/alsa/alsa.h b/src/alsa/alsa.h index 019c589..b522b3a 100644 --- a/src/alsa/alsa.h +++ b/src/alsa/alsa.h @@ -60,19 +60,21 @@ extern pthread_mutex_t alsa_mutex; OutputPluginInitStatus alsa_init (void); void alsa_soft_init (void); void alsa_cleanup (void); -int alsa_open_audio (AFormat aud_format, int rate, int channels); +int alsa_open_audio (gint aud_format, int rate, int channels); void alsa_close_audio (void); +int alsa_buffer_free (void); void alsa_write_audio (void * data, int length); +void alsa_period_wait (void); void alsa_drain (void); void alsa_set_written_time (int time); int alsa_written_time (void); int alsa_output_time (void); void alsa_flush (int time); void alsa_pause (short pause); -void alsa_get_volume (int * left, int * right); -void alsa_set_volume (int left, int right); void alsa_open_mixer (void); void alsa_close_mixer (void); +void alsa_get_volume (int * left, int * right); +void alsa_set_volume (int left, int right); /* config.c */ extern char * alsa_config_pcm, * alsa_config_mixer, * alsa_config_mixer_element; diff --git a/src/alsa/config.c b/src/alsa/config.c index d3e7b39..a5c2231 100644 --- a/src/alsa/config.c +++ b/src/alsa/config.c @@ -20,6 +20,7 @@ #include <alsa/asoundlib.h> #include <gtk/gtk.h> +#include <audacious/configdb.h> #include <audacious/i18n.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> @@ -52,7 +53,7 @@ static GtkTreeIter * list_lookup_member (GtkListStore * list, const char * text) free (iter_text); return & iter; } - + free (iter_text); } while (gtk_tree_model_iter_next ((GtkTreeModel *) list, & iter)); diff --git a/src/alsa/plugin.c b/src/alsa/plugin.c index eaff3e8..812f209 100644 --- a/src/alsa/plugin.c +++ b/src/alsa/plugin.c @@ -35,7 +35,9 @@ static OutputPlugin plugin = .cleanup = alsa_cleanup, .open_audio = alsa_open_audio, .close_audio = alsa_close_audio, + .buffer_free = alsa_buffer_free, .write_audio = alsa_write_audio, + .period_wait = alsa_period_wait, .drain = alsa_drain, .set_written_time = alsa_set_written_time, .written_time = alsa_written_time, diff --git a/src/amidi-plug/amidi-plug.c b/src/amidi-plug/amidi-plug.c index 525eb0d..fb46bda 100644 --- a/src/amidi-plug/amidi-plug.c +++ b/src/amidi-plug/amidi-plug.c @@ -18,8 +18,11 @@ * */ -#include "amidi-plug.h" +#include <audacious/drct.h> #include <audacious/plugin.h> +#include <libaudcore/eventqueue.h> + +#include "amidi-plug.h" InputPlugin *amidiplug_iplist[] = { &amidiplug_ip, NULL }; @@ -221,7 +224,7 @@ static gint amidiplug_get_time( InputPlayback * playback ) { g_mutex_unlock( amidiplug_playing_mutex ); DEBUGMSG( "GETTIME on halted song (an error occurred?), returning -1 and stopping the player\n" ); - audacious_drct_stop(); + aud_drct_stop(); return -1; } } @@ -252,7 +255,7 @@ static gint amidiplug_set_volume( gint l , gint r ) static Tuple * amidiplug_get_song_tuple( const gchar *filename_uri ) { /* song title, get it from the filename */ - Tuple *tuple = aud_tuple_new_from_filename(filename_uri); + Tuple *tuple = tuple_new_from_filename(filename_uri); gchar *title, *filename = g_filename_from_uri(filename_uri, NULL, NULL); midifile_t mf; @@ -263,12 +266,12 @@ static Tuple * amidiplug_get_song_tuple( const gchar *filename_uri ) else title = g_strdup(filename_uri); - aud_tuple_associate_string(tuple, FIELD_TITLE, NULL, title); + tuple_associate_string(tuple, FIELD_TITLE, NULL, title); g_free(title); g_free(filename); if ( i_midi_parse_from_filename( filename_uri , &mf ) ) - aud_tuple_associate_int(tuple, FIELD_LENGTH, NULL, mf.length / 1000); + tuple_associate_int(tuple, FIELD_LENGTH, NULL, mf.length / 1000); i_midi_free( &mf ); @@ -317,7 +320,7 @@ static void amidiplug_play( InputPlayback * playback ) port_count = backend.seq_get_port_count(); if ( port_count < 1 ) { - aud_event_queue ("interface show error", _("You have not selected any " + event_queue ("interface show error", _("You have not selected any " "sequencer ports for MIDI playback. You can do so in the MIDI plugin " "preferences.")); amidiplug_playing_status = AMIDIPLUG_ERR; diff --git a/src/amidi-plug/amidi-plug.h b/src/amidi-plug/amidi-plug.h index 00d2502..67f1ef2 100644 --- a/src/amidi-plug/amidi-plug.h +++ b/src/amidi-plug/amidi-plug.h @@ -29,7 +29,7 @@ #include "i_common.h" #include <audacious/plugin.h> -#include <audacious/auddrct.h> + #include "i_vfslayer.h" #include "i_backend.h" #include "i_configure.h" @@ -92,7 +92,7 @@ InputPlugin amidiplug_ip = .get_song_tuple = amidiplug_get_song_tuple, /* get_song_info */ .file_info_box = amidiplug_file_info_box, /* file_info_box */ .is_our_file_from_vfs = amidiplug_is_our_file_from_vfs, /* is_our_file_from_vfs */ - .vfs_extensions = amidiplug_vfs_extensions /* aud_vfs_extensions */ + .vfs_extensions = amidiplug_vfs_extensions /* vfs_extensions */ }; #endif /* !_I_AMIDIPLUG_H */ diff --git a/src/amidi-plug/i_configure.c b/src/amidi-plug/i_configure.c index ac14a4c..d0d9df0 100644 --- a/src/amidi-plug/i_configure.c +++ b/src/amidi-plug/i_configure.c @@ -18,6 +18,9 @@ * */ +#include <audacious/drct.h> +#include <audacious/misc.h> +#include <audacious/plugin.h> #include "i_configure.h" #include "i_configure_private.h" @@ -27,10 +30,6 @@ #include "i_configure-alsa.h" #include "i_configure-fluidsynth.h" #include "i_utils.h" -#include <audacious/plugin.h> -#include <audacious/auddrct.h> -#include <audacious/plugin.h> - amidiplug_cfg_backend_t * amidiplug_cfg_backend; @@ -91,8 +90,8 @@ void i_configure_ev_browse_for_entry( GtkWidget * target_entry ) static void commit_cb (GtkWidget * button, void * unused) { - if (audacious_drct_get_playing ()) - audacious_drct_stop (); + if (aud_drct_get_playing ()) + aud_drct_stop (); g_signal_emit_by_name (button, "ap-commit"); } @@ -381,7 +380,7 @@ void i_configure_cfg_ap_save( void ) gchar * i_configure_cfg_get_file( void ) { - gchar * config_datadir = (gchar*)audacious_get_localdir(); + gchar * config_datadir = (gchar*)aud_util_get_localdir(); gchar * config_pathfilename = g_build_filename( config_datadir , "amidi-plug.conf" , NULL ); g_free( config_datadir ); return config_pathfilename; diff --git a/src/amidi-plug/i_vfslayer.h b/src/amidi-plug/i_vfslayer.h index 6debd10..dec2eea 100644 --- a/src/amidi-plug/i_vfslayer.h +++ b/src/amidi-plug/i_vfslayer.h @@ -26,13 +26,13 @@ #include <audacious/plugin.h> -#define VFS_FOPEN( x , y ) aud_vfs_fopen( x , y ) -#define VFS_FCLOSE( x ) aud_vfs_fclose( x ) -#define VFS_FREAD( x , y , z , w ) aud_vfs_fread( x , y , z , w ) -#define VFS_FSEEK( x , y , z ) aud_vfs_fseek( x , y , z ) -#define VFS_FEOF( x ) aud_vfs_feof( x ) -#define VFS_GETC( x ) aud_vfs_getc( x ) -#define VFS_UNGETC( x , y ) aud_vfs_ungetc( x , y ) +#define VFS_FOPEN( x , y ) vfs_fopen( x , y ) +#define VFS_FCLOSE( x ) vfs_fclose( x ) +#define VFS_FREAD( x , y , z , w ) vfs_fread( x , y , z , w ) +#define VFS_FSEEK( x , y , z ) vfs_fseek( x , y , z ) +#define VFS_FEOF( x ) vfs_feof( x ) +#define VFS_GETC( x ) vfs_getc( x ) +#define VFS_UNGETC( x , y ) vfs_ungetc( x , y ) #endif /* !_I_VFSLAYER_H */ diff --git a/src/aosd/aosd_cfg.c b/src/aosd/aosd_cfg.c index 978fd4a..e1803f0 100644 --- a/src/aosd/aosd_cfg.c +++ b/src/aosd/aosd_cfg.c @@ -22,8 +22,9 @@ #include "aosd_style.h" #include <glib.h> #include <stdlib.h> -#include <audacious/plugin.h> +#include <audacious/configdb.h> +#include <audacious/plugin.h> static gint aosd_cfg_util_str_to_color ( gchar * str , aosd_color_t * color ) @@ -296,7 +297,7 @@ aosd_cfg_load ( aosd_cfg_t * cfg ) "decoration_code" , &(cfg->osd->decoration.code) ) ) cfg->osd->decoration.code = aosd_deco_style_get_first_code(); - /* TODO not implemented yet + /* TODO not implemented yet if ( !aud_cfg_db_get_string( cfgfile , "aosd" , "decoration_skin_file" , &(cfg->osd->decoration.skin_file) ) ) cfg->osd->decoration.skin_file = g_strdup( "" ); diff --git a/src/aosd/aosd_trigger.c b/src/aosd/aosd_trigger.c index 43fe4b9..9da06a7 100644 --- a/src/aosd/aosd_trigger.c +++ b/src/aosd/aosd_trigger.c @@ -18,15 +18,19 @@ * */ +#include <glib.h> + +#include <audacious/drct.h> +#include <audacious/i18n.h> +#include <audacious/playlist.h> +#include <audacious/plugin.h> +#include <libaudcore/audstrings.h> +#include <libaudcore/hook.h> + #include "aosd_trigger.h" #include "aosd_trigger_private.h" #include "aosd_cfg.h" #include "aosd_osd.h" -#include <glib.h> -#include <audacious/i18n.h> -#include <audacious/hook.h> -#include <audacious/auddrct.h> -#include <audacious/plugin.h> extern aosd_cfg_t * global_config; @@ -136,8 +140,8 @@ aosd_trigger_start ( aosd_cfg_osd_trigger_t * cfg_trigger ) } /* When called, this hook will display the text of the user pointer or the current playing song, if NULL */ - aud_hook_register("aosd toggle"); - aud_hook_associate( "aosd toggle" , aosd_trigger_func_hook_cb , NULL ); + hook_register("aosd toggle"); + hook_associate( "aosd toggle" , aosd_trigger_func_hook_cb , NULL ); return; } @@ -146,7 +150,7 @@ void aosd_trigger_stop ( aosd_cfg_osd_trigger_t * cfg_trigger ) { gint i = 0; - aud_hook_dissociate( "aosd toggle" , aosd_trigger_func_hook_cb ); + hook_dissociate( "aosd toggle" , aosd_trigger_func_hook_cb ); for ( i = 0 ; i < cfg_trigger->active->len ; i++ ) { gint trig_code = g_array_index( cfg_trigger->active , gint , i ); @@ -158,11 +162,10 @@ aosd_trigger_stop ( aosd_cfg_osd_trigger_t * cfg_trigger ) /* HELPER FUNCTIONS */ -static gchar * -aosd_trigger_utf8convert ( gchar * str ) +static gchar * aosd_trigger_utf8convert (const gchar * str) { if ( global_config->osd->text.utf8conv_disable == FALSE ) - return aud_str_to_utf8( str ); + return str_to_utf8( str ); else return g_strdup( str ); } @@ -174,16 +177,16 @@ static void aosd_trigger_func_pb_start_onoff(gboolean turn_on) { if (turn_on == TRUE) - aud_hook_associate("playback begin", aosd_trigger_func_pb_start_cb, NULL); + hook_associate("playback begin", aosd_trigger_func_pb_start_cb, NULL); else - aud_hook_dissociate("playback begin", aosd_trigger_func_pb_start_cb); + hook_dissociate("playback begin", aosd_trigger_func_pb_start_cb); return; } static void aosd_trigger_func_pb_start_cb(gpointer hook_data, gpointer user_data) { - gchar *title = audacious_drct_pl_get_title(audacious_drct_pl_get_pos()); + gchar *title = aud_drct_pl_get_title(aud_drct_pl_get_pos()); if (title != NULL) { @@ -218,11 +221,11 @@ aosd_trigger_func_pb_titlechange_onoff ( gboolean turn_on ) prevs = g_malloc0(sizeof(aosd_pb_titlechange_prevs_t)); prevs->title = NULL; prevs->filename = NULL; - aud_hook_associate( "title change" , aosd_trigger_func_pb_titlechange_cb , prevs ); + hook_associate( "title change" , aosd_trigger_func_pb_titlechange_cb , prevs ); } else { - aud_hook_dissociate( "title change" , aosd_trigger_func_pb_titlechange_cb ); + hook_dissociate( "title change" , aosd_trigger_func_pb_titlechange_cb ); if ( prevs != NULL ) { if ( prevs->title != NULL ) g_free( prevs->title ); @@ -237,13 +240,15 @@ aosd_trigger_func_pb_titlechange_onoff ( gboolean turn_on ) static void aosd_trigger_func_pb_titlechange_cb ( gpointer plentry_gp , gpointer prevs_gp ) { - if (audacious_drct_get_playing ()) + if (aud_drct_get_playing ()) { aosd_pb_titlechange_prevs_t *prevs = prevs_gp; gint playlist = aud_playlist_get_playing(); gint pl_entry = aud_playlist_get_position(playlist); - gchar *pl_entry_filename = (gchar*) aud_playlist_entry_get_filename(playlist, pl_entry); - gchar *pl_entry_title = (gchar*) aud_playlist_entry_get_title(playlist, pl_entry); + const gchar * pl_entry_filename = aud_playlist_entry_get_filename (playlist, + pl_entry); + const gchar * pl_entry_title = aud_playlist_entry_get_title (playlist, + pl_entry, FALSE); /* same filename but title changed, useful to detect http stream song changes */ @@ -293,9 +298,9 @@ static void aosd_trigger_func_vol_change_onoff ( gboolean turn_on ) { if ( turn_on == TRUE ) - aud_hook_associate( "volume set" , aosd_trigger_func_vol_change_cb , NULL ); + hook_associate( "volume set" , aosd_trigger_func_vol_change_cb , NULL ); else - aud_hook_dissociate( "volume set" , aosd_trigger_func_vol_change_cb ); + hook_dissociate( "volume set" , aosd_trigger_func_vol_change_cb ); return; } @@ -350,9 +355,9 @@ static void aosd_trigger_func_pb_pauseon_onoff ( gboolean turn_on ) { if ( turn_on == TRUE ) - aud_hook_associate( "playback pause" , aosd_trigger_func_pb_pauseon_cb , NULL ); + hook_associate( "playback pause" , aosd_trigger_func_pb_pauseon_cb , NULL ); else - aud_hook_dissociate( "playback pause" , aosd_trigger_func_pb_pauseon_cb ); + hook_dissociate( "playback pause" , aosd_trigger_func_pb_pauseon_cb ); return; } @@ -371,9 +376,9 @@ static void aosd_trigger_func_pb_pauseoff_onoff ( gboolean turn_on ) { if ( turn_on == TRUE ) - aud_hook_associate( "playback unpause" , aosd_trigger_func_pb_pauseoff_cb , NULL ); + hook_associate( "playback unpause" , aosd_trigger_func_pb_pauseoff_cb , NULL ); else - aud_hook_dissociate( "playback unpause" , aosd_trigger_func_pb_pauseoff_cb ); + hook_dissociate( "playback unpause" , aosd_trigger_func_pb_pauseoff_cb ); return; } @@ -382,18 +387,19 @@ aosd_trigger_func_pb_pauseoff_cb ( gpointer unused1 , gpointer unused2 ) { gint active = aud_playlist_get_active(); gint pos = aud_playlist_get_position(active); - gchar *title, *utf8_title, *utf8_title_markup; + const gchar * title; + gchar *utf8_title, *utf8_title_markup; gint time_cur, time_tot; gint time_cur_m, time_cur_s, time_tot_m, time_tot_s; - time_tot = aud_playlist_entry_get_length(active, pos) / 1000; - time_cur = audacious_drct_get_time() / 1000; + time_tot = aud_playlist_entry_get_length (active, pos, FALSE) / 1000; + time_cur = aud_drct_get_time() / 1000; time_cur_s = time_cur % 60; time_cur_m = (time_cur - time_cur_s) / 60; time_tot_s = time_tot % 60; time_tot_m = (time_tot - time_tot_s) / 60; - title = (gchar*) aud_playlist_entry_get_title(active, pos); + title = aud_playlist_entry_get_title (active, pos, FALSE); utf8_title = aosd_trigger_utf8convert( title ); utf8_title_markup = g_markup_printf_escaped( "<span font_desc='%s'>%s (%i:%02i/%i:%02i)</span>" , @@ -405,7 +411,7 @@ aosd_trigger_func_pb_pauseoff_cb ( gpointer unused1 , gpointer unused2 ) } -/* Call with aud_hook_call("aosd toggle", param); +/* Call with hook_call("aosd toggle", param); If param != NULL, display the supplied text in the OSD If param == NULL, display the current playing song */ static void @@ -417,7 +423,7 @@ aosd_trigger_func_hook_cb ( gpointer markup_text , gpointer unused ) aosd_osd_display( markup_text , global_config->osd , FALSE ); } else { /* Display currently playing song */ - aosd_trigger_func_pb_start_cb ( GINT_TO_POINTER(audacious_drct_pl_get_pos()), NULL ); + aosd_trigger_func_pb_start_cb ( GINT_TO_POINTER(aud_drct_pl_get_pos()), NULL ); } return; } diff --git a/src/bluetooth/bluetooth.c b/src/bluetooth/bluetooth.c index 9ee09c5..0d17184 100644 --- a/src/bluetooth/bluetooth.c +++ b/src/bluetooth/bluetooth.c @@ -258,8 +258,8 @@ void play_call() printf("play callback\n"); close_window(); aud_output_plugin_cleanup(); -// audacious_drct_stop(); - audacious_drct_play(); +// aud_drct_stop(); + aud_drct_play(); } diff --git a/src/blur_scope/blur_scope.c b/src/blur_scope/blur_scope.c index f3cf84f..f688832 100644 --- a/src/blur_scope/blur_scope.c +++ b/src/blur_scope/blur_scope.c @@ -22,10 +22,13 @@ #include "config.h" #include <glib.h> -#include <audacious/i18n.h> #include <gtk/gtk.h> #include <string.h> + +#include <audacious/configdb.h> +#include <audacious/i18n.h> #include <audacious/plugin.h> + #include "blur_scope.h" static GtkWidget *area = NULL; @@ -211,11 +214,11 @@ draw_vert_line(guchar * buffer, gint x, gint y1, gint y2) { int y; if (y1 < y2) { - for (y = y1; y <= y2; y++) + for (y = y1 + 1; y <= y2; y++) draw_pixel_8(buffer, x, y, 0xFF); } else if (y2 < y1) { - for (y = y2; y <= y1; y++) + for (y = y2; y < y1; y++) draw_pixel_8(buffer, x, y, 0xFF); } else @@ -230,13 +233,11 @@ bscope_render_pcm(gint16 data[2][512]) g_static_mutex_lock(&rgb_buf_mutex); bscope_blur_8(rgb_buf, width, height, bpl); - prev_y = y = (height / 2) + (data[0][0] >> 9); + prev_y = (height / 2) + (data[0][0] >> 9); + prev_y = CLAMP (prev_y, 0, height - 1); for (i = 0; i < width; i++) { - y = (height / 2) + (data[0][i >> 1] >> 9); - if (y < 0) - y = 0; - if (y >= height) - y = height - 1; + y = (height / 2) + (data[0][i * 512 / width] >> 9); + y = CLAMP (y, 0, height - 1); draw_vert_line(rgb_buf, i, prev_y, y); prev_y = y; } diff --git a/src/blur_scope/config.c b/src/blur_scope/config.c index b014d15..229fff1 100644 --- a/src/blur_scope/config.c +++ b/src/blur_scope/config.c @@ -1,10 +1,12 @@ #include "config.h" #include <glib.h> -#include <audacious/i18n.h> #include <gtk/gtk.h> +#include <audacious/configdb.h> +#include <audacious/i18n.h> #include <audacious/plugin.h> + #include "blur_scope.h" diff --git a/src/bs2b/plugin.c b/src/bs2b/plugin.c index 087c8af..5cd6937 100644 --- a/src/bs2b/plugin.c +++ b/src/bs2b/plugin.c @@ -91,6 +91,7 @@ static EffectPlugin audaciousBs2b = { .finish = bs2b_finish, .decoder_to_output_time = bs2b_decoder_to_output_time, .output_to_decoder_time = bs2b_output_to_decoder_time, + .preserves_format = TRUE, }; static EffectPlugin * plugins[] = { &audaciousBs2b, NULL }; diff --git a/src/cd-menu-items/cd-menu-items.c b/src/cd-menu-items/cd-menu-items.c index aee7394..1337bc5 100644 --- a/src/cd-menu-items/cd-menu-items.c +++ b/src/cd-menu-items/cd-menu-items.c @@ -24,9 +24,10 @@ #include <glib.h> #include <gtk/gtk.h> +#include <audacious/drct.h> #include <audacious/i18n.h> +#include <audacious/misc.h> #include <audacious/plugin.h> -#include <audacious/ui_plugin_menu.h> #define N_ITEMS 2 #define N_MENUS 3 @@ -39,12 +40,12 @@ static GtkWidget * items[N_ITEMS * N_MENUS]; static void cd_play (void) { - audacious_drct_pl_open ("cdda://"); + aud_drct_pl_open ("cdda://"); } static void cd_add (void) { - audacious_drct_pl_add_url_string ("cdda://"); + aud_drct_pl_add ("cdda://", -1); } static void (* funcs[N_ITEMS]) (void) = {cd_play, cd_add}; diff --git a/src/cdaudio-ng/cdaudio-ng.c b/src/cdaudio-ng/cdaudio-ng.c index 5b2446e..7b75dec 100644 --- a/src/cdaudio-ng/cdaudio-ng.c +++ b/src/cdaudio-ng/cdaudio-ng.c @@ -36,8 +36,14 @@ #include <glib.h> -#include <audacious/plugin.h> +#include <audacious/audconfig.h> +#include <audacious/configdb.h> +#include <audacious/debug.h> #include <audacious/i18n.h> +#include <audacious/misc.h> +#include <audacious/playlist.h> +#include <audacious/plugin.h> +#include <libaudcore/eventqueue.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> @@ -138,7 +144,7 @@ static void cdaudio_error (const gchar * message_format, ...) msg = g_markup_vprintf_escaped (message_format, args); va_end (args); - aud_event_queue_with_data_free ("interface show error", msg); + event_queue_with_data_free ("interface show error", msg); } /* main thread only */ @@ -617,7 +623,7 @@ static Tuple *create_tuple_from_trackinfo_and_filename (const gchar * filename) if (!strcmp (filename, "cdda://")) { - tuple = aud_tuple_new_from_filename (filename); + tuple = tuple_new_from_filename (filename); tuple->nsubtunes = 1 + lasttrackno - firsttrackno; tuple->subtunes = g_malloc (sizeof *tuple->subtunes * tuple->nsubtunes); @@ -635,27 +641,27 @@ static Tuple *create_tuple_from_trackinfo_and_filename (const gchar * filename) goto DONE; } - tuple = aud_tuple_new_from_filename (filename); + tuple = tuple_new_from_filename (filename); if (strlen (trackinfo[trackno].performer)) { - aud_tuple_associate_string (tuple, FIELD_ARTIST, NULL, + tuple_associate_string (tuple, FIELD_ARTIST, NULL, trackinfo[trackno].performer); } if (strlen (trackinfo[0].name)) { - aud_tuple_associate_string (tuple, FIELD_ALBUM, NULL, + tuple_associate_string (tuple, FIELD_ALBUM, NULL, trackinfo[0].name); } if (strlen (trackinfo[trackno].name)) { - aud_tuple_associate_string (tuple, FIELD_TITLE, NULL, + tuple_associate_string (tuple, FIELD_TITLE, NULL, trackinfo[trackno].name); } - aud_tuple_associate_int (tuple, FIELD_TRACK_NUMBER, NULL, trackno); + tuple_associate_int (tuple, FIELD_TRACK_NUMBER, NULL, trackno); - aud_tuple_associate_int (tuple, FIELD_LENGTH, NULL, + tuple_associate_int (tuple, FIELD_LENGTH, NULL, calculate_track_length (trackinfo[trackno]. startlsn, trackinfo[trackno]. @@ -663,7 +669,7 @@ static Tuple *create_tuple_from_trackinfo_and_filename (const gchar * filename) if (strlen (trackinfo[trackno].genre)) { - aud_tuple_associate_string (tuple, FIELD_GENRE, NULL, + tuple_associate_string (tuple, FIELD_GENRE, NULL, trackinfo[trackno].genre); } diff --git a/src/compressor/plugin.c b/src/compressor/plugin.c index 6675178..3ddba4a 100644 --- a/src/compressor/plugin.c +++ b/src/compressor/plugin.c @@ -21,6 +21,7 @@ #include "config.h" +#include <audacious/configdb.h> #include <audacious/i18n.h> #include <audacious/plugin.h> #include <libaudgui/libaudgui.h> @@ -155,6 +156,7 @@ EffectPlugin compressor_plugin = .finish = compressor_finish, .decoder_to_output_time = compressor_decoder_to_output_time, .output_to_decoder_time = compressor_output_to_decoder_time, + .preserves_format = TRUE, }; EffectPlugin * compressor_list[] = {& compressor_plugin, NULL}; diff --git a/src/console/Audacious_Driver.cxx b/src/console/Audacious_Driver.cxx index 40ba342..86d9989 100644 --- a/src/console/Audacious_Driver.cxx +++ b/src/console/Audacious_Driver.cxx @@ -8,9 +8,12 @@ #include "config.h" #include <math.h> + extern "C" { +#include <libaudcore/audstrings.h> #include <audacious/plugin.h> } + #include "configure.h" #include "Music_Emu.h" #include "Gzip_Reader.h" @@ -45,14 +48,14 @@ public: gint m_track; // track number (0 = first track) Music_Emu* m_emu; // set to 0 to take ownership gme_type_t m_type; - + // Parses path and identifies file type ConsoleFileHandler(const gchar* path, VFSFile *fd = NULL); - + // Creates emulator and returns 0. If this wasn't a music file or // emulator couldn't be created, returns 1. gint load(gint sample_rate); - + // Deletes owned emu and closes file ~ConsoleFileHandler(); @@ -68,10 +71,10 @@ ConsoleFileHandler::ConsoleFileHandler(const gchar *path, VFSFile *fd) m_type = 0; m_track = -1; - m_path = aud_filename_split_subtune(path, &m_track); + m_path = filename_split_subtune(path, &m_track); if (m_path == NULL) return; - + m_track -= 1; // open vfs @@ -79,11 +82,11 @@ ConsoleFileHandler::ConsoleFileHandler(const gchar *path, VFSFile *fd) vfs_in.reset(fd); else if (log_err(vfs_in.open(m_path))) return; - + // now open gzip_reader on top of vfs if (log_err(gzip_in.open(&vfs_in))) return; - + // read and identify header if (!log_err(gzip_in.read(m_header, sizeof(m_header)))) { @@ -107,23 +110,23 @@ gint ConsoleFileHandler::load(gint sample_rate) { if (!m_type) return 1; - + m_emu = gme_new_emu(m_type, sample_rate); if (m_emu == NULL) { log_err("Out of memory allocating emulator engine. Fatal error."); return 1; } - + // combine header with remaining file data Remaining_Reader reader(m_header, sizeof(m_header), &gzip_in); if (log_err(m_emu->load(reader))) return 1; - + // files can be closed now gzip_in.close(); vfs_in.close(); - + log_warning(m_emu); #if 0 @@ -136,7 +139,7 @@ gint ConsoleFileHandler::load(gint sample_rate) g_free(m3u_path); m3u_path = ext; } - + Vfs_File_Reader m3u; if (!m3u.open(m3u_path)) { @@ -150,28 +153,26 @@ gint ConsoleFileHandler::load(gint sample_rate) static Tuple * get_track_ti(const gchar *path, const track_info_t *info, const gint track) { - Tuple *ti = aud_tuple_new_from_filename(path); - - g_print("file: %s\n", path); + Tuple *ti = tuple_new_from_filename(path); if (ti != NULL) { gint length; - aud_tuple_associate_string(ti, FIELD_ARTIST, NULL, info->author); - aud_tuple_associate_string(ti, FIELD_ALBUM, NULL, info->game); - aud_tuple_associate_string(ti, -1, "game", info->game); - aud_tuple_associate_string(ti, FIELD_TITLE, NULL, info->song ? info->song : g_path_get_basename(path)); - aud_tuple_associate_string(ti, FIELD_COPYRIGHT, NULL, info->copyright); - aud_tuple_associate_string(ti, -1, "console", info->system); - aud_tuple_associate_string(ti, FIELD_CODEC, NULL, info->system); - aud_tuple_associate_string(ti, FIELD_QUALITY, NULL, "sequenced"); - aud_tuple_associate_string(ti, -1, "dumper", info->dumper); - aud_tuple_associate_string(ti, FIELD_COMMENT, NULL, info->comment); + tuple_associate_string(ti, FIELD_ARTIST, NULL, info->author); + tuple_associate_string(ti, FIELD_ALBUM, NULL, info->game); + tuple_associate_string(ti, -1, "game", info->game); + tuple_associate_string(ti, FIELD_TITLE, NULL, info->song ? info->song : g_path_get_basename(path)); + tuple_associate_string(ti, FIELD_COPYRIGHT, NULL, info->copyright); + tuple_associate_string(ti, -1, "console", info->system); + tuple_associate_string(ti, FIELD_CODEC, NULL, info->system); + tuple_associate_string(ti, FIELD_QUALITY, NULL, "sequenced"); + tuple_associate_string(ti, -1, "dumper", info->dumper); + tuple_associate_string(ti, FIELD_COMMENT, NULL, info->comment); if (track >= 0) { - aud_tuple_associate_int(ti, FIELD_TRACK_NUMBER, NULL, track + 1); - aud_tuple_associate_int(ti, FIELD_SUBSONG_ID, NULL, track + 1); - aud_tuple_associate_int(ti, FIELD_SUBSONG_NUM, NULL, info->track_count); + tuple_associate_int(ti, FIELD_TRACK_NUMBER, NULL, track + 1); + tuple_associate_int(ti, FIELD_SUBSONG_ID, NULL, track + 1); + tuple_associate_int(ti, FIELD_SUBSONG_NUM, NULL, info->track_count); } else { @@ -185,7 +186,7 @@ static Tuple * get_track_ti(const gchar *path, const track_info_t *info, const g length = audcfg.loop_length * 1000; else if (length >= fade_threshold) length += fade_length; - aud_tuple_associate_int(ti, FIELD_LENGTH, NULL, length); + tuple_associate_int(ti, FIELD_LENGTH, NULL, length); } return ti; @@ -194,7 +195,7 @@ static Tuple * get_track_ti(const gchar *path, const track_info_t *info, const g extern "C" Tuple * console_probe_for_tuple(const gchar *filename, VFSFile *fd) { ConsoleFileHandler fh(filename, fd); - + if (!fh.m_type) return NULL; @@ -211,7 +212,7 @@ extern "C" Tuple * console_probe_for_tuple(const gchar *filename, VFSFile *fd) extern "C" Tuple * console_get_file_tuple(const gchar *filename) { ConsoleFileHandler fh(filename); - + if (!fh.m_type) return NULL; @@ -234,10 +235,10 @@ extern "C" void console_play_file(InputPlayback *playback) ConsoleFileHandler fh(playback->filename); if (!fh.m_type) return; - + if (fh.m_track < 0) fh.m_track = 0; - + // select sample rate sample_rate = 0; if (fh.m_type == gme_spc_type) @@ -246,46 +247,46 @@ extern "C" void console_play_file(InputPlayback *playback) sample_rate = audcfg.resample_rate; if (sample_rate == 0) sample_rate = 44100; - + // create emulator and load file if (fh.load(sample_rate)) return; - + // stereo echo depth gme_set_stereo_depth(fh.m_emu, 1.0 / 100 * audcfg.echo); - + // set equalizer if (audcfg.treble || audcfg.bass) { Music_Emu::equalizer_t eq; - + // bass - logarithmic, 2 to 8194 Hz double bass = 1.0 - (audcfg.bass / 200.0 + 0.5); eq.bass = (long) (2.0 + pow( 2.0, bass * 13 )); - + // treble - -50 to 0 to +5 dB double treble = audcfg.treble / 100.0; eq.treble = treble * (treble < 0 ? 50.0 : 5.0); - + fh.m_emu->set_equalizer(eq); } - + // get info length = -1; if (!log_err(fh.m_emu->track_info(&info, fh.m_track))) { if (fh.m_type == gme_spc_type && audcfg.ignore_spc_length) info.length = -1; - + Tuple *ti = get_track_ti(fh.m_path, &info, fh.m_track); if (ti != NULL) { - length = aud_tuple_get_int(ti, FIELD_LENGTH, NULL); + length = tuple_get_int(ti, FIELD_LENGTH, NULL); tuple_free(ti); playback->set_params(playback, NULL, NULL, fh.m_emu->voice_count() * 1000, sample_rate, 2); } } - + // start track if (log_err(fh.m_emu->start_track(fh.m_track))) return; @@ -294,18 +295,18 @@ extern "C" void console_play_file(InputPlayback *playback) if (!playback->output->open_audio(FMT_S16_NE, sample_rate, 2)) return; - + // set fade time if (length <= 0) length = audcfg.loop_length * 1000; if (length >= fade_threshold + fade_length) length -= fade_length / 2; fh.m_emu->set_fade(length, fade_length); - + playback->playing = 1; end_delay = 0; playback->set_pb_ready(playback); - + while (playback->playing) { /* Perform seek, if requested */ @@ -318,7 +319,7 @@ extern "C" void console_play_file(InputPlayback *playback) g_cond_signal(seek_cond); } g_mutex_unlock(seek_mutex); - + /* Fill and play buffer of audio */ gint const buf_size = 1024; Music_Emu::sample_t buf[buf_size]; @@ -337,10 +338,10 @@ extern "C" void console_play_file(InputPlayback *playback) end_delay = (fh.m_emu->sample_rate() * 3 * 2) / buf_size; } } - + playback->output->write_audio(buf, sizeof(buf)); } - + // stop playing playback->output->close_audio(); playback->playing = 0; diff --git a/src/console/Vfs_File.cxx b/src/console/Vfs_File.cxx index b818105..a53a546 100644 --- a/src/console/Vfs_File.cxx +++ b/src/console/Vfs_File.cxx @@ -13,7 +13,7 @@ void Vfs_File_Reader::reset( VFSFile* f ) Vfs_File_Reader::error_t Vfs_File_Reader::open( const char* path ) { close(); - file_ = owned_file_ = aud_vfs_fopen( path, "rb" ); + file_ = owned_file_ = vfs_fopen( path, "rb" ); if ( !file_ ) return "Couldn't open file"; return 0; @@ -22,27 +22,27 @@ Vfs_File_Reader::error_t Vfs_File_Reader::open( const char* path ) long Vfs_File_Reader::size() const { long pos = tell(); - aud_vfs_fseek( file_, 0, SEEK_END ); + vfs_fseek( file_, 0, SEEK_END ); long result = tell(); - aud_vfs_fseek( file_, pos, SEEK_SET ); + vfs_fseek( file_, pos, SEEK_SET ); return result; } long Vfs_File_Reader::read_avail( void* p, long s ) { - return (long) aud_vfs_fread( p, 1, s, file_ ); + return (long) vfs_fread( p, 1, s, file_ ); } long Vfs_File_Reader::tell() const { - return aud_vfs_ftell( file_ ); + return vfs_ftell( file_ ); } Vfs_File_Reader::error_t Vfs_File_Reader::seek( long n ) { if ( n == 0 ) // optimization - aud_vfs_rewind( file_ ); - else if ( aud_vfs_fseek( file_, n, SEEK_SET ) != 0 ) + vfs_rewind( file_ ); + else if ( vfs_fseek( file_, n, SEEK_SET ) != 0 ) return eof_error; return 0; } @@ -52,7 +52,7 @@ void Vfs_File_Reader::close() file_ = 0; if ( owned_file_ ) { - aud_vfs_fclose( owned_file_ ); + vfs_fclose( owned_file_ ); owned_file_ = 0; } } diff --git a/src/console/abstract_file.cxx b/src/console/abstract_file.cxx index 894fa43..b97a748 100644 --- a/src/console/abstract_file.cxx +++ b/src/console/abstract_file.cxx @@ -143,7 +143,7 @@ Std_File_Reader::~Std_File_Reader() { error_t Std_File_Reader::open( const char* path ) { - file_ = aud_vfs_fopen( path, "rb" ); + file_ = vfs_fopen( path, "rb" ); if ( !file_ ) RAISE_ERROR( "Couldn't open file" ); return NULL; @@ -152,23 +152,23 @@ error_t Std_File_Reader::open( const char* path ) long Std_File_Reader::size() const { long pos = tell(); - aud_vfs_fseek( file_, 0, SEEK_END ); + vfs_fseek( file_, 0, SEEK_END ); long result = tell(); - aud_vfs_fseek( file_, pos, SEEK_SET ); + vfs_fseek( file_, pos, SEEK_SET ); return result; } long Std_File_Reader::read_avail( void* p, long s ) { - return (long) aud_vfs_fread( p, 1, s, file_ ); + return (long) vfs_fread( p, 1, s, file_ ); } long Std_File_Reader::tell() const { - return aud_vfs_ftell( file_ ); + return vfs_ftell( file_ ); } error_t Std_File_Reader::seek( long n ) { - if ( aud_vfs_fseek( file_, n, SEEK_SET ) != 0 ) + if ( vfs_fseek( file_, n, SEEK_SET ) != 0 ) RAISE_ERROR( "Error seeking in file" ); return NULL; } @@ -176,7 +176,7 @@ error_t Std_File_Reader::seek( long n ) void Std_File_Reader::close() { if ( file_ ) { - aud_vfs_fclose( file_ ); + vfs_fclose( file_ ); file_ = NULL; } } @@ -192,7 +192,7 @@ Std_File_Writer::~Std_File_Writer() { error_t Std_File_Writer::open( const char* path ) { - file_ = aud_vfs_fopen( path, "wb" ); + file_ = vfs_fopen( path, "wb" ); if ( !file_ ) RAISE_ERROR( "Couldn't open file for writing" ); @@ -204,7 +204,7 @@ error_t Std_File_Writer::open( const char* path ) error_t Std_File_Writer::write( const void* p, long s ) { - long result = (long) aud_vfs_fwrite( p, 1, s, file_ ); + long result = (long) vfs_fwrite( p, 1, s, file_ ); if ( result != s ) RAISE_ERROR( "Couldn't write to file" ); return NULL; @@ -213,7 +213,7 @@ error_t Std_File_Writer::write( const void* p, long s ) void Std_File_Writer::close() { if ( file_ ) { - aud_vfs_fclose( file_ ); + vfs_fclose( file_ ); file_ = NULL; } } diff --git a/src/console/configure.c b/src/console/configure.c index ffdb2f6..d73eb77 100644 --- a/src/console/configure.c +++ b/src/console/configure.c @@ -12,6 +12,8 @@ #include "configure.h" #include <glib.h> #include <gtk/gtk.h> + +#include <audacious/configdb.h> #include <audacious/i18n.h> #include <audacious/plugin.h> diff --git a/src/crossfade/crossfade.c b/src/crossfade/crossfade.c index f7bf1ed..1aa1410 100644 --- a/src/crossfade/crossfade.c +++ b/src/crossfade/crossfade.c @@ -17,12 +17,12 @@ * the use of this software. */ -#include <audacious/plugin.h> #include <glib.h> -#include <stdio.h> -#include <stdlib.h> #include <string.h> +#include <audacious/debug.h> +#include <audacious/plugin.h> + #include "crossfade.h" enum diff --git a/src/crossfade/plugin.c b/src/crossfade/plugin.c index 67dac07..c3602b9 100644 --- a/src/crossfade/plugin.c +++ b/src/crossfade/plugin.c @@ -19,13 +19,13 @@ #include <gtk/gtk.h> -#include "config.h" - +#include <audacious/configdb.h> #include <audacious/i18n.h> #include <audacious/plugin.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> +#include "config.h" #include "crossfade.h" void crossfade_config_load (void) diff --git a/src/crystalizer/crystalizer.c b/src/crystalizer/crystalizer.c index 46e5805..9967f4c 100644 --- a/src/crystalizer/crystalizer.c +++ b/src/crystalizer/crystalizer.c @@ -21,6 +21,8 @@ #include "config.h" #include <gtk/gtk.h> + +#include <audacious/configdb.h> #include <audacious/i18n.h> #include <audacious/plugin.h> @@ -44,6 +46,7 @@ EffectPlugin crystalizer_ep = .finish = cryst_finish, .decoder_to_output_time = cryst_decoder_to_output_time, .output_to_decoder_time = cryst_output_to_decoder_time, + .preserves_format = TRUE, }; static GtkWidget *conf_dialog = NULL; diff --git a/src/cue/Makefile b/src/cue/Makefile index cdf10d3..badba11 100644 --- a/src/cue/Makefile +++ b/src/cue/Makefile @@ -7,6 +7,6 @@ include ../../extra.mk plugindir := ${plugindir}/${CONTAINER_PLUGIN_DIR} +CPPFLAGS += -std=gnu99 ${PLUGIN_CPPFLAGS} ${CUE_CFLAGS} CFLAGS += ${PLUGIN_CFLAGS} -CPPFLAGS += ${PLUGIN_CPPFLAGS} ${MOWGLI_CFLAGS} ${CUE_CFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} ${ARCH_DEFINES} ${XML_CPPFLAGS} -I../.. -Wall -LIBS += ${GTK_LIBS} ${GLIB_LIBS} ${XML_LIBS} ${CUE_LIBS} +LIBS += ${CUE_LIBS} diff --git a/src/cue/cue.c b/src/cue/cue.c index a294f11..909a049 100644 --- a/src/cue/cue.c +++ b/src/cue/cue.c @@ -1,6 +1,7 @@ /* * Audacious: A cross-platform multimedia player * Copyright (c) 2009 William Pitcock <nenolod@dereferenced.org> + * Copyright (c) 2010 John Lindgren <john.lindgren@tds.net> * * 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 @@ -32,6 +33,9 @@ #include <sys/stat.h> #include <sys/errno.h> +#include <audacious/debug.h> +#include <audacious/misc.h> +#include <audacious/playlist.h> #include <audacious/plugin.h> #include <libcue/libcue.h> @@ -66,67 +70,95 @@ tuple_attach_cdtext(Tuple *tuple, Track *track, gint tuple_type, gint pti) tuple_associate_string(tuple, tuple_type, NULL, text); } -static void -playlist_load_cue(const gchar * filename, gint pos) +static void playlist_load_cue (const gchar * cue_filename, gint at) { - gchar *uri = NULL, *buffer; - gsize len; - Cd *cd; - gint iter, plen; - gint playlist; - struct index *uris = NULL; - struct index *tuples = NULL; - - uri = g_filename_to_uri(filename, NULL, NULL); - - aud_vfs_file_get_contents(uri ? uri : filename, &buffer, &len); - - g_free(uri); uri = NULL; - + void * buffer; + gint64 size; + vfs_file_get_contents (cue_filename, & buffer, & size); if (buffer == NULL) return; - cd = cue_parse_string(buffer); + buffer = g_realloc (buffer, size + 1); + ((gchar *) buffer)[size] = 0; + Cd * cd = cue_parse_string (buffer); + g_free (buffer); if (cd == NULL) return; - uris = index_new(); - tuples = index_new(); + gint tracks = cd_get_ntrack (cd); + if (tracks == 0) + return; + + struct index * filenames = index_new (); + struct index * tuples = index_new (); + + Track * current = cd_get_track (cd, 1); + g_return_if_fail (current != NULL); + gchar * filename = aud_construct_uri (track_get_filename (current), + cue_filename); + + Tuple * base_tuple = NULL; - playlist = aud_playlist_get_active(); - for (iter = 0, plen = cd_get_ntrack(cd); iter < plen; iter++) + for (gint track = 1; track <= tracks; track ++) { - gchar *fn, *uri; - Track *t; - glong begin, length; - Tuple *tu; - gint iter2; - - t = cd_get_track(cd, 1 + iter); - fn = track_get_filename(t); - begin = (track_get_start(t) / 75) * 1000; - length = (track_get_length(t) / 75) * 1000; - uri = aud_construct_uri(fn, filename); - tu = tuple_new(); - - for (iter2 = 0; iter2 < G_N_ELEMENTS(pti_map); iter2++) + g_return_if_fail (current != NULL); + g_return_if_fail (filename != NULL); + + if (base_tuple == NULL) { - tuple_attach_cdtext(tu, t, pti_map[iter2].tuple_type, pti_map[iter2].pti); + InputPlugin * decoder = aud_file_find_decoder (filename, TRUE); + if (decoder != NULL) + base_tuple = aud_file_read_tuple (filename, decoder); } - tuple_associate_int(tu, FIELD_LENGTH, NULL, length); - tuple_associate_int(tu, FIELD_SEGMENT_START, NULL, begin); - tuple_associate_int(tu, FIELD_SEGMENT_END, NULL, begin + length); - tuple_associate_int(tu, FIELD_TRACK_NUMBER, NULL, cd_get_track(cd, iter+1)); + Track * next = (track + 1 <= tracks) ? cd_get_track (cd, track + 1) : + NULL; + gchar * next_filename = (next != NULL) ? aud_construct_uri + (track_get_filename (next), cue_filename) : NULL; + gboolean last_track = (next_filename == NULL || strcmp (next_filename, + filename)); - index_append(uris, uri); - index_append(tuples, tu); - } + Tuple * tuple = (base_tuple != NULL) ? tuple_copy (base_tuple) : + tuple_new_from_filename (filename); + tuple_associate_int (tuple, FIELD_TRACK_NUMBER, NULL, track); + + gint begin = (gint64) track_get_start (current) * 1000 / 75; + tuple_associate_int (tuple, FIELD_SEGMENT_START, NULL, begin); - aud_playlist_entry_insert_batch(playlist, pos, uris, tuples); + if (last_track) + { + if (base_tuple != NULL && tuple_get_value_type (base_tuple, + FIELD_LENGTH, NULL) == TUPLE_INT) + tuple_associate_int (tuple, FIELD_LENGTH, NULL, tuple_get_int + (base_tuple, FIELD_LENGTH, NULL) - begin); + } + else + { + gint length = (gint64) track_get_length (current) * 1000 / 75; + tuple_associate_int (tuple, FIELD_LENGTH, NULL, length); + tuple_associate_int (tuple, FIELD_SEGMENT_END, NULL, begin + length); + } + + for (gint i = 0; i < G_N_ELEMENTS (pti_map); i ++) + tuple_attach_cdtext (tuple, current, pti_map[i].tuple_type, + pti_map[i].pti); + + index_append (filenames, filename); + index_append (tuples, tuple); + + current = next; + filename = next_filename; + + if (last_track && base_tuple != NULL) + { + tuple_free (base_tuple); + base_tuple = NULL; + } + } - g_free(buffer); + aud_playlist_entry_insert_batch (aud_playlist_get_active (), at, filenames, + tuples); } static void diff --git a/src/daap/daap.c b/src/daap/daap.c index 284a17d..2b11c86 100644 --- a/src/daap/daap.c +++ b/src/daap/daap.c @@ -306,7 +306,7 @@ GList * daap_discovery_get_devices_impl(void) -VFSFile * daap_aud_vfs_fopen_impl(const gchar * path, const gchar * mode) +VFSFile * daap_vfs_fopen_impl(const gchar * path, const gchar * mode) { VFSFile *file=NULL; daap_handle_t *handle = g_new0(daap_handle_t, 1); @@ -330,7 +330,7 @@ VFSFile * daap_aud_vfs_fopen_impl(const gchar * path, const gchar * mode) if (handle->fd < 0) { - g_print("aud_vfs_fopen got a negative FD \n"); + g_print("vfs_fopen got a negative FD \n"); g_free(file); file = NULL; } @@ -339,7 +339,7 @@ VFSFile * daap_aud_vfs_fopen_impl(const gchar * path, const gchar * mode) return file; } -gint daap_aud_vfs_fclose_impl(VFSFile * file) +gint daap_vfs_fclose_impl(VFSFile * file) { gint ret=0; daap_handle_t * handle = (daap_handle_t *)file->handle; @@ -363,7 +363,7 @@ gint daap_aud_vfs_fclose_impl(VFSFile * file) return -1; } -size_t daap_aud_vfs_fread_impl(gpointer ptr, size_t size, size_t nmemb, VFSFile * file) +size_t daap_vfs_fread_impl(gpointer ptr, size_t size, size_t nmemb, VFSFile * file) { daap_handle_t *handle= (daap_handle_t *)file->handle; size_t ret=0; @@ -378,12 +378,12 @@ else return 0; } -size_t daap_aud_vfs_fwrite_impl(gconstpointer ptr, size_t size, size_t nmemb, VFSFile * file) +size_t daap_vfs_fwrite_impl(gconstpointer ptr, size_t size, size_t nmemb, VFSFile * file) { return -1; } -gint daap_aud_vfs_getc_impl(VFSFile * file) +gint daap_vfs_getc_impl(VFSFile * file) { guchar ret=EOF; daap_handle_t *handle = (daap_handle_t *)file->handle; @@ -401,44 +401,44 @@ g_print ("fgetc failed\n"); } } -gint daap_aud_vfs_fseek_impl(VFSFile * file, glong offset, gint whence) +gint daap_vfs_fseek_impl(VFSFile * file, glong offset, gint whence) { return -1; } -gint daap_aud_vfs_ungetc_impl(gint c, VFSFile * stream) +gint daap_vfs_ungetc_impl(gint c, VFSFile * stream) { return c; } -void daap_aud_vfs_rewind_impl(VFSFile * stream) +void daap_vfs_rewind_impl(VFSFile * stream) { return; } -glong daap_aud_vfs_ftell_impl(VFSFile * stream) +glong daap_vfs_ftell_impl(VFSFile * stream) { daap_handle_t *handle=stream->handle; return handle->pos; } -gboolean daap_aud_vfs_feof_impl(VFSFile * file) +gboolean daap_vfs_feof_impl(VFSFile * file) { daap_handle_t *handle=file->handle; - off_t at = daap_aud_vfs_ftell_impl(file); + off_t at = daap_vfs_ftell_impl(file); return (gboolean) (at >= handle->length) ? TRUE : FALSE; } -gint daap_aud_vfs_truncate_impl(VFSFile * file, glong size) +gint daap_vfs_truncate_impl(VFSFile * file, glong size) { return -1; } -off_t daap_aud_vfs_fsize_impl(VFSFile * file) +off_t daap_vfs_fsize_impl(VFSFile * file) { return 0; } -gchar *daap_aud_vfs_metadata_impl(VFSFile * file, const gchar * field) +gchar *daap_vfs_metadata_impl(VFSFile * file, const gchar * field) { daap_handle_t *handle; g_print("Requested metadata: '%s' \n",field); @@ -462,26 +462,26 @@ return NULL; VFSConstructor daap_const = { "daap://", - daap_aud_vfs_fopen_impl, - daap_aud_vfs_fclose_impl, - daap_aud_vfs_fread_impl, - daap_aud_vfs_fwrite_impl, - daap_aud_vfs_getc_impl, - daap_aud_vfs_ungetc_impl, - daap_aud_vfs_fseek_impl, - daap_aud_vfs_rewind_impl, - daap_aud_vfs_ftell_impl, - daap_aud_vfs_feof_impl, - daap_aud_vfs_truncate_impl, - daap_aud_vfs_fsize_impl, - daap_aud_vfs_metadata_impl + daap_vfs_fopen_impl, + daap_vfs_fclose_impl, + daap_vfs_fread_impl, + daap_vfs_fwrite_impl, + daap_vfs_getc_impl, + daap_vfs_ungetc_impl, + daap_vfs_fseek_impl, + daap_vfs_rewind_impl, + daap_vfs_ftell_impl, + daap_vfs_feof_impl, + daap_vfs_truncate_impl, + daap_vfs_fsize_impl, + daap_vfs_metadata_impl }; static void init(void) { mutex_init = g_mutex_new(); mutex_discovery = g_mutex_new(); - aud_vfs_register_transport(&daap_const); + vfs_register_transport(&daap_const); daap_mdns_initialize (); if (!login_sessions) login_sessions = g_hash_table_new (g_str_hash, g_str_equal); diff --git a/src/dockalbumart/dockalbumart.c b/src/dockalbumart/dockalbumart.c index 974f697..4790eef 100644 --- a/src/dockalbumart/dockalbumart.c +++ b/src/dockalbumart/dockalbumart.c @@ -81,8 +81,8 @@ pixbuf_find_and_load(Tuple *tuple) gchar *tmp; const gchar *file_path, *file_name; - file_name = aud_tuple_get_string(tuple, FIELD_FILE_NAME, NULL); - file_path = aud_tuple_get_string(tuple, FIELD_FILE_PATH, NULL); + file_name = tuple_get_string(tuple, FIELD_FILE_NAME, NULL); + file_path = tuple_get_string(tuple, FIELD_FILE_PATH, NULL); if (file_name != NULL && file_path != NULL) { @@ -134,8 +134,8 @@ dockart_trigger_func_pb_end_cb(gpointer plentry_p, gpointer unused) static void dockart_init(void) { - aud_hook_associate("playback begin", dockart_trigger_func_pb_start_cb, NULL); - aud_hook_associate("playback end", dockart_trigger_func_pb_end_cb, NULL); + hook_associate("playback begin", dockart_trigger_func_pb_start_cb, NULL); + hook_associate("playback end", dockart_trigger_func_pb_end_cb, NULL); } static void @@ -143,8 +143,8 @@ dockart_cleanup(void) { GdkPixbuf *new; - aud_hook_dissociate("playback begin", dockart_trigger_func_pb_start_cb); - aud_hook_dissociate("playback end", dockart_trigger_func_pb_end_cb); + hook_dissociate("playback begin", dockart_trigger_func_pb_start_cb); + hook_dissociate("playback end", dockart_trigger_func_pb_end_cb); /* reset dock tile */ new = gdk_pixbuf_new_from_xpm_data((const gchar **) audacious_player_xpm); diff --git a/src/echo_plugin/echo.c b/src/echo_plugin/echo.c index ec30f13..168f657 100644 --- a/src/echo_plugin/echo.c +++ b/src/echo_plugin/echo.c @@ -1,127 +1,132 @@ #include "config.h" -#include <audacious/plugin.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <gtk/gtk.h> + +#include <audacious/configdb.h> #include <audacious/i18n.h> +#include <audacious/plugin.h> + #include "echo.h" static void init(void); static void cleanup(void); -static int mod_samples(gpointer * d, gint length, AFormat afmt, gint srate, gint nch); -static void query_format(AFormat * fmt, gint * rate, gint * nch); #define MAX_SRATE 50000 #define MAX_CHANNELS 2 -#define BYTES_PS 2 +#define BYTES_PS sizeof(gfloat) #define BUFFER_SAMPLES (MAX_SRATE * MAX_DELAY / 1000) #define BUFFER_SHORTS (BUFFER_SAMPLES * MAX_CHANNELS) #define BUFFER_BYTES (BUFFER_SHORTS * BYTES_PS) -EffectPlugin echo_ep = -{ - .description = "Echo Plugin", /* Description */ - .init = init, - .cleanup = cleanup, - .about = echo_about, - .configure = echo_configure, - .mod_samples = mod_samples, - .query_format = query_format, -}; - -static gint16 *buffer = NULL; +static gfloat *buffer = NULL; gint echo_delay = 500, echo_feedback = 50, echo_volume = 50; -gboolean echo_surround_enable = FALSE; static int w_ofs; -EffectPlugin *echo_eplist[] = { &echo_ep, NULL }; - -DECLARE_PLUGIN(echo, NULL, NULL, NULL, NULL, echo_eplist, NULL, NULL, NULL); - static void init(void) { mcs_handle_t *cfg; - - if (sizeof(short) != sizeof(gint16)) - abort(); cfg = aud_cfg_db_open(); aud_cfg_db_get_int(cfg, "echo_plugin", "delay", &echo_delay); aud_cfg_db_get_int(cfg, "echo_plugin", "feedback", &echo_feedback); aud_cfg_db_get_int(cfg, "echo_plugin", "volume", &echo_volume); - aud_cfg_db_get_bool(cfg, "echo_plugin", "enable_surround", &echo_surround_enable); aud_cfg_db_close(cfg); } static void cleanup(void) { g_free(buffer); - buffer = NULL; + buffer = NULL; } -static void query_format(AFormat * fmt, gint * rate, gint * nch) -{ - if (!(*fmt == FMT_S16_NE || - (*fmt == FMT_S16_LE && G_BYTE_ORDER == G_LITTLE_ENDIAN) || - (*fmt == FMT_S16_BE && G_BYTE_ORDER == G_BIG_ENDIAN))) - *fmt = FMT_S16_NE; -} +static gint echo_channels = 0; +static gint echo_rate = 0; -static int mod_samples(gpointer * d, gint length, AFormat afmt, gint srate, gint nch) +static void echo_start(gint *channels, gint *rate) { - gint i, in, out, buf, r_ofs, fb_div; - gint16 *data = (gint16 *) * d; static gint old_srate, old_nch; - if (!(afmt == FMT_S16_NE || - (afmt == FMT_S16_LE && G_BYTE_ORDER == G_LITTLE_ENDIAN) || - (afmt == FMT_S16_BE && G_BYTE_ORDER == G_BIG_ENDIAN))) - return length; + if (buffer == NULL) + buffer = g_malloc0(BUFFER_BYTES + sizeof(gfloat)); - if (!buffer) - buffer = g_malloc0(BUFFER_BYTES + 2); + echo_channels = *channels; + echo_rate = *rate; - if (nch != old_nch || srate != old_srate) + if (echo_channels != old_nch || echo_rate != old_srate) { memset(buffer, 0, BUFFER_BYTES); w_ofs = 0; - old_nch = nch; - old_srate = srate; + old_nch = echo_channels; + old_srate = echo_rate; } +} + +static void echo_flush(void) +{ + +} - if (echo_surround_enable && nch == 2) - fb_div = 200; - else - fb_div = 100; +static gint echo_decoder_to_output_time(gint time) +{ + return time; +} + +static gint echo_output_to_decoder_time(gint time) +{ + return time; +} + +static void echo_process(gfloat **d, gint *samples) +{ + gfloat in, out, buf; + gint r_ofs; + gfloat *data = *d; + gfloat *end = *d + *samples; - r_ofs = w_ofs - (srate * echo_delay / 1000) * nch; + r_ofs = w_ofs - (echo_rate * echo_delay / 1000) * echo_channels; if (r_ofs < 0) r_ofs += BUFFER_SHORTS; - for (i = 0; i < length / BYTES_PS; i++) + for (; data < end; data++) { - in = data[i]; + in = *data; + buf = buffer[r_ofs]; - if (echo_surround_enable && nch == 2) - { - if (i & 1) - buf -= buffer[r_ofs - 1]; - else - buf -= buffer[r_ofs + 1]; - } out = in + buf * echo_volume / 100; - buf = in + buf * echo_feedback / fb_div; - out = CLAMP(out, -32768, 32767); - buf = CLAMP(buf, -32768, 32767); + buf = in + buf * echo_feedback / 100; buffer[w_ofs] = buf; - data[i] = out; + *data = out; + if (++r_ofs >= BUFFER_SHORTS) r_ofs -= BUFFER_SHORTS; if (++w_ofs >= BUFFER_SHORTS) w_ofs -= BUFFER_SHORTS; } +} - return length; +static void echo_finish(gfloat **d, gint *samples) +{ + echo_process(d, samples); } + +EffectPlugin echo_ep = +{ + .description = "Echo Plugin", /* Description */ + .init = init, + .cleanup = cleanup, + .about = echo_about, + .configure = echo_configure, + .start = echo_start, + .process = echo_process, + .flush = echo_flush, + .finish = echo_finish, + .decoder_to_output_time = echo_decoder_to_output_time, + .output_to_decoder_time = echo_output_to_decoder_time +}; + +EffectPlugin *echo_eplist[] = { &echo_ep, NULL }; + +SIMPLE_EFFECT_PLUGIN(echo, echo_eplist); diff --git a/src/echo_plugin/gui.c b/src/echo_plugin/gui.c index e66a676..6c0a873 100644 --- a/src/echo_plugin/gui.c +++ b/src/echo_plugin/gui.c @@ -1,6 +1,8 @@ #include "config.h" #include <gtk/gtk.h> + +#include <audacious/configdb.h> #include <audacious/plugin.h> #include <audacious/i18n.h> #include <libaudgui/libaudgui.h> @@ -13,7 +15,7 @@ N_("Echo Plugin\n" "By Johan Levin 1999.\n\n" "Surround echo by Carl van Schaik 1999"); -static GtkWidget *conf_dialog = NULL, *surround_btn; +static GtkWidget *conf_dialog = NULL; static GtkObject *echo_delay_adj, *echo_feedback_adj, *echo_volume_adj; void echo_about (void) @@ -30,14 +32,11 @@ static void apply_changes(void) echo_delay = GTK_ADJUSTMENT(echo_delay_adj)->value; echo_feedback = GTK_ADJUSTMENT(echo_feedback_adj)->value; echo_volume = GTK_ADJUSTMENT(echo_volume_adj)->value; - echo_surround_enable = - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(surround_btn)); cfg = aud_cfg_db_open(); aud_cfg_db_set_int(cfg, "echo_plugin", "delay", echo_delay); aud_cfg_db_set_int(cfg, "echo_plugin", "feedback", echo_feedback); aud_cfg_db_set_int(cfg, "echo_plugin", "volume", echo_volume); - aud_cfg_db_set_bool(cfg, "echo_plugin", "enable_surround", echo_surround_enable); aud_cfg_db_close(cfg); } @@ -113,14 +112,6 @@ void echo_configure(void) gtk_table_attach_defaults(GTK_TABLE(table), hscale, 1, 2, 2, 3); gtk_widget_show(hscale); - surround_btn = gtk_check_button_new_with_label(_("Surround echo")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(surround_btn), - echo_surround_enable); - gtk_widget_show(surround_btn); - - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(conf_dialog)->vbox), surround_btn, - TRUE, TRUE, 5); - bbox = gtk_hbutton_box_new(); gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5); diff --git a/src/esd/Makefile b/src/esd/Makefile deleted file mode 100644 index 9c2a29b..0000000 --- a/src/esd/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -PLUGIN = ESD${PLUGIN_SUFFIX} - -SRCS = esd.c \ - mixer.c \ - about.c \ - configure.c \ - audio.c \ - init.c - -include ../../buildsys.mk -include ../../extra.mk - -plugindir := ${plugindir}/${OUTPUT_PLUGIN_DIR} - -CFLAGS += ${PLUGIN_CFLAGS} -CPPFLAGS += ${PLUGIN_CPPFLAGS} ${MOWGLI_CFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} ${ESD_CFLAGS} -I../.. -I.. -LIBS += ${GTK_LIBS} ${GLIB_LIBS} ${ESD_LIBS} ${OSS_LIBS} diff --git a/src/esd/about.c b/src/esd/about.c deleted file mode 100644 index dfacaad..0000000 --- a/src/esd/about.c +++ /dev/null @@ -1,47 +0,0 @@ -/* xmms - esound output plugin - * Copyright (C) 1999 Galex Yen - * 3/9/99 - * - * this program is free software - * - * Description: - * This program is an output plugin for xmms v0.9 or greater. - * The program uses the esound daemon to output audio in order - * to allow more than one program to play audio on the same - * device at the same time. - * - * Contains code Copyright (C) 1998-1999 Mikael Alm, Olle Hallnas, - * Thomas Nillson and 4Front Technologies - */ - -#include "esdout.h" - -#include <glib.h> -#include <audacious/i18n.h> -#include <gtk/gtk.h> - -#include <libaudgui/libaudgui.h> -#include <libaudgui/libaudgui-gtk.h> - -void -esdout_about(void) -{ - static GtkWidget *dialog = NULL; - - audgui_simple_message(&dialog, GTK_MESSAGE_INFO, _("About ESounD Plugin"), - _("Audacious ESounD Plugin\n\n " - "This program is free software; you can redistribute it and/or modify\n" - "it under the terms of the GNU General Public License as published by\n" - "the Free Software Foundation; either version 2 of the License, or\n" - "(at your option) any later version.\n" - "\n" - "This program is distributed in the hope that it will be useful,\n" - "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" - "GNU General Public License for more details.\n" - "\n" - "You should have received a copy of the GNU General Public License\n" - "along with this program; if not, write to the Free Software\n" - "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n" - "USA.")); -} diff --git a/src/esd/audio.c b/src/esd/audio.c deleted file mode 100644 index cca982b..0000000 --- a/src/esd/audio.c +++ /dev/null @@ -1,435 +0,0 @@ -/* BMP - Cross-platform multimedia player - * Copyright (C) 2003-2004 BMP development team. - * - * Based on XMMS: - * Copyright (C) 1998-2003 XMMS development team. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include <glib.h> -#include <stdlib.h> -#include <string.h> -#include <esd.h> - -#include <unistd.h> - -#include "esdout.h" - - -static gint fd = 0; -static gpointer buffer; -static gboolean going = FALSE, paused = FALSE, prebuffer, remove_prebuffer; -static gint buffer_size, prebuffer_size, blk_size = 4096; -static gint rd_index = 0, wr_index = 0; -static gint output_time_offset = 0; -static guint64 written = 0, output_bytes = 0; -static gint bps, ebps; -static gint flush; -static gint format, channels, frequency, latency; -static esd_format_t esd_format; -static gint input_bps, input_format, input_frequency, input_channels; -static GThread *buffer_thread; -static void *(*esd_translate) (void *, gint); -static int player_id_unique = 0; - -static gint -get_latency(void) -{ - int fd, amount = 0; - -#ifndef HAVE_ESD_GET_LATENCY - esd_server_info_t *info; -#endif - - fd = esd_open_sound(esd_cfg.hostname); - - if (fd == -1) - return 0; - -#ifdef HAVE_ESD_GET_LATENCY - amount = esd_get_latency(fd); -#else - info = esd_get_server_info(fd); - if (info) { - if (info->format & ESD_STEREO) { - if (info->format & ESD_BITS16) - amount = (44100 * (ESD_BUF_SIZE + 64)) / info->rate; - else - amount = (44100 * (ESD_BUF_SIZE + 128)) / info->rate; - } - else { - if (info->format & ESD_BITS16) - amount = (2 * 44100 * (ESD_BUF_SIZE + 128)) / info->rate; - else - amount = (2 * 44100 * (ESD_BUF_SIZE + 256)) / info->rate; - } - free(info); - } - amount += ESD_BUF_SIZE * 2; -#endif - esd_close(fd); - return amount; -} - -static void * -esd_stou8(void *data, gint length) -{ - int len = length; - unsigned char *dat = (unsigned char *) data; - while (len-- > 0) - *dat++ ^= 0x80; - return data; -} - -static void * -esd_utos16sw(void *data, gint length) -{ - int len = length; - short *dat = data; - while (len > 0) { - *dat = GUINT16_SWAP_LE_BE(*dat) ^ 0x8000; - dat++; - len -= 2; - } - return data; -} - -static void * -esd_utos16(void *data, gint length) -{ - int len = length; - short *dat = data; - while (len > 0) { - *dat ^= 0x8000; - dat++; - len -= 2; - } - return data; -} - -static void * -esd_16sw(void *data, gint length) -{ - int len = length; - short *dat = data; - while (len > 0) { - *dat = GUINT16_SWAP_LE_BE(*dat); - dat++; - len -= 2; - } - return data; -} - -static void -esdout_setup_format(AFormat fmt, gint rate, gint nch) -{ - gboolean swap_sign = FALSE; - gboolean swap_16 = FALSE; - - format = fmt; - frequency = rate; - channels = nch; - switch (fmt) { - case FMT_S8: - swap_sign = TRUE; - case FMT_U8: - esd_format = ESD_BITS8; - break; - case FMT_U16_LE: - case FMT_U16_BE: - swap_sign = TRUE; - case FMT_S16_LE: - case FMT_S16_BE: - esd_format = ESD_BITS16; - break; - default: - /* for warning suppression */ - break; - } - -#if (G_BYTE_ORDER == G_BIG_ENDIAN) - if (fmt == FMT_U16_LE || fmt == FMT_S16_LE) -#else - if (fmt == FMT_U16_BE || fmt == FMT_S16_BE) -#endif - swap_16 = TRUE; - - esd_translate = (void *(*)()) NULL; - if (esd_format == ESD_BITS8) { - if (swap_sign == TRUE) - esd_translate = esd_stou8; - } - else { - if (swap_sign == TRUE) { - if (swap_16 == TRUE) - esd_translate = esd_utos16sw; - else - esd_translate = esd_utos16; - } - else { - if (swap_16 == TRUE) - esd_translate = esd_16sw; - } - } - - bps = rate * nch; - if (esd_format == ESD_BITS16) - bps *= 2; - if (nch == 1) - esd_format |= ESD_MONO; - else - esd_format |= ESD_STEREO; - esd_format |= ESD_STREAM | ESD_PLAY; - - latency = ((get_latency() * frequency) / 44100) * channels; - if (format != FMT_U8 && format != FMT_S8) - latency *= 2; -} - - -gint -esdout_get_written_time(void) -{ - if (!going) - return 0; - return (gint) ((written * 1000) / input_bps); -} - -gint -esdout_get_output_time(void) -{ - guint64 bytes; - - if (!fd || !going) - return 0; - - bytes = output_bytes; - if (!paused) - bytes -= (bytes < latency ? bytes : latency); - - return output_time_offset + (gint) ((bytes * 1000) / ebps); -} - -gint -esdout_used(void) -{ - if (wr_index >= rd_index) - return wr_index - rd_index; - - return buffer_size - (rd_index - wr_index); -} - -gint -esdout_playing(void) -{ - if (!going) - return FALSE; - if (!esdout_used()) - return FALSE; - - return TRUE; -} - -gint -esdout_free(void) -{ - if (remove_prebuffer && prebuffer) { - prebuffer = FALSE; - remove_prebuffer = FALSE; - } - - if (prebuffer) - remove_prebuffer = TRUE; - - if (rd_index > wr_index) - return (rd_index - wr_index) - 1; - - return (buffer_size - (wr_index - rd_index)) - 1; -} - -static void -esdout_write_audio(gpointer data, gint length) -{ - while (length > 0) { - int num_written; - if (esd_translate) - num_written = write(fd, esd_translate(data, length), length); - else - num_written = write(fd, data, length); - if (num_written <= 0) - break; - length -= num_written; - data += num_written; - output_bytes += num_written; - } -} - - -void -esdout_write(gpointer ptr, gint length) -{ - gint cnt, off = 0; - - remove_prebuffer = FALSE; - - written += length; - while (length > 0) { - cnt = MIN(length, buffer_size - wr_index); - memcpy((gchar *) buffer + wr_index, (gchar *) ptr + off, cnt); - wr_index = (wr_index + cnt) % buffer_size; - length -= cnt; - off += cnt; - } -} - -void -esdout_close(void) -{ - if (!going) - return; - - going = 0; - - g_thread_join(buffer_thread); - - wr_index = 0; - rd_index = 0; - g_free(esd_cfg.playername); - esd_cfg.playername = NULL; -} - -void -esdout_flush(gint time) -{ - flush = time; - - while (flush != -1) - g_usleep(10000); -} - -void -esdout_pause(short p) -{ - paused = p; -} - -gpointer -esdout_loop(gpointer arg) -{ - gint length, cnt; - - - while (going) { - if (esdout_used() > prebuffer_size) - prebuffer = FALSE; - if (esdout_used() > 0 && !paused && !prebuffer) { - length = MIN(blk_size, esdout_used()); - while (length > 0) { - cnt = MIN(length, buffer_size - rd_index); - esdout_write_audio((gchar *) buffer + rd_index, cnt); - rd_index = (rd_index + cnt) % buffer_size; - length -= cnt; - } - } - else - g_usleep(10000); - - if (flush != -1) { - output_time_offset = flush; - written = (guint64) (flush / 10) * (guint64) (input_bps / 100); - rd_index = wr_index = output_bytes = 0; - flush = -1; - prebuffer = TRUE; - } - - } - - esd_close(fd); - g_free(buffer); - return NULL; -} - -void -esdout_set_audio_params(void) -{ - fd = esd_play_stream(esd_format, frequency, - esd_cfg.hostname, esd_cfg.playername); - /* Set the stream's mixer */ - if (fd != -1) - esdout_mixer_init(); - ebps = frequency * channels; - if (format == FMT_U16_BE || format == FMT_U16_LE || - format == FMT_S16_BE || format == FMT_S16_LE) - ebps *= 2; -} - -gint -esdout_open(AFormat fmt, gint rate, gint nch) -{ - esdout_setup_format(fmt, rate, nch); - - input_format = format; - input_channels = channels; - input_frequency = frequency; - input_bps = bps; - - buffer_size = (esd_cfg.buffer_size * input_bps) / 1000; - if (buffer_size < 8192) - buffer_size = 8192; - prebuffer_size = (buffer_size * esd_cfg.prebuffer) / 100; - if (buffer_size - prebuffer_size < 4096) - prebuffer_size = buffer_size - 4096; - - buffer = g_malloc0(buffer_size); - - flush = -1; - prebuffer = 1; - wr_index = rd_index = output_time_offset = written = output_bytes = 0; - paused = FALSE; - remove_prebuffer = FALSE; - - esd_cfg.playername = g_strdup_printf("xmms - plugin (%d) [%d]", getpid(), player_id_unique++); - - if (esd_cfg.hostname) - g_free(esd_cfg.hostname); - if (esd_cfg.use_remote) - esd_cfg.hostname = - g_strdup_printf((strchr(esd_cfg.server, ':')) ? "[%s]:%d" : "%s:%d", - esd_cfg.server, esd_cfg.port); - else - esd_cfg.hostname = NULL; - - esdout_set_audio_params(); - if (fd == -1) { - g_free(esd_cfg.playername); - esd_cfg.playername = NULL; - g_free(buffer); - return 0; - } - going = 1; - - buffer_thread = g_thread_create(esdout_loop, NULL, TRUE, NULL); - - return 1; -} - -void -esdout_tell(AFormat * fmt, gint * rate, gint * nch) -{ - (*fmt) = format; - (*rate) = frequency; - (*nch) = channels; -} diff --git a/src/esd/configure.c b/src/esd/configure.c deleted file mode 100644 index 3a71054..0000000 --- a/src/esd/configure.c +++ /dev/null @@ -1,232 +0,0 @@ -/* BMP - Cross-platform multimedia player - * Copyright (C) 2003-2004 BMP development team. - * - * Based on XMMS: - * Copyright (C) 1998-2003 XMMS development team. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "esdout.h" - -#include <glib.h> -#include <audacious/plugin.h> -#include <audacious/i18n.h> -#include <gtk/gtk.h> -#include <stdlib.h> - - - -static GtkWidget *configure_win; -static GtkWidget *server_use_remote, *server_oss_mixer, *server_host_entry; -static GtkWidget *server_port_entry, *buffer_size_spin, *buffer_pre_spin; - - -static void -configure_win_ok_cb(GtkWidget * w, gpointer data) -{ - mcs_handle_t *db; - - esd_cfg.use_remote = - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(server_use_remote)); - esd_cfg.use_oss_mixer = - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(server_oss_mixer)); - if (esd_cfg.server) - g_free(esd_cfg.server); - esd_cfg.server = - g_strdup(gtk_entry_get_text(GTK_ENTRY(server_host_entry))); - esd_cfg.port = atoi(gtk_entry_get_text(GTK_ENTRY(server_port_entry))); - esd_cfg.buffer_size = - gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(buffer_size_spin)); - esd_cfg.prebuffer = - gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(buffer_pre_spin)); - - db = aud_cfg_db_open(); - - aud_cfg_db_set_bool(db, "ESD", "use_remote", esd_cfg.use_remote); - aud_cfg_db_set_bool(db, "ESD", "use_oss_mixer", esd_cfg.use_oss_mixer); - aud_cfg_db_set_string(db, "ESD", "remote_host", esd_cfg.server); - aud_cfg_db_set_int(db, "ESD", "remote_port", esd_cfg.port); - aud_cfg_db_set_int(db, "ESD", "buffer_size", esd_cfg.buffer_size); - aud_cfg_db_set_int(db, "ESD", "prebuffer", esd_cfg.prebuffer); - aud_cfg_db_close(db); - -} - -static void -use_remote_cb(GtkWidget * w, gpointer data) -{ - gboolean use_remote; - GtkWidget *box = data; - - use_remote = - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(server_use_remote)); - - gtk_widget_set_sensitive(box, use_remote); -} - -void -esdout_configure(void) -{ - GtkWidget *vbox, *notebook; - GtkWidget *server_frame, *server_vbox, *server_hbox, *server_btn_hbox; - GtkWidget *server_host_label, *server_port_label; - GtkWidget *buffer_frame, *buffer_vbox, *buffer_table; - GtkWidget *buffer_size_box, *buffer_size_label; - GtkObject *buffer_size_adj, *buffer_pre_adj; - GtkWidget *buffer_pre_box, *buffer_pre_label; - GtkWidget *bbox, *ok, *cancel; - gchar *temp; - - if (configure_win) { - gtk_window_present(GTK_WINDOW(configure_win)); - return; - } - - configure_win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - g_signal_connect(G_OBJECT(configure_win), "destroy", - G_CALLBACK(gtk_widget_destroyed), &configure_win); - gtk_window_set_title(GTK_WINDOW(configure_win), - _("ESD Output Plugin configuration")); - gtk_window_set_type_hint(GTK_WINDOW(configure_win), - GDK_WINDOW_TYPE_HINT_DIALOG); - gtk_window_set_resizable(GTK_WINDOW(configure_win), FALSE); - gtk_container_border_width(GTK_CONTAINER(configure_win), 10); - - vbox = gtk_vbox_new(FALSE, 10); - gtk_container_add(GTK_CONTAINER(configure_win), vbox); - - notebook = gtk_notebook_new(); - gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0); - - server_frame = gtk_frame_new(_("Host:")); - gtk_container_set_border_width(GTK_CONTAINER(server_frame), 5); - - server_vbox = gtk_vbox_new(FALSE, 5); - gtk_container_set_border_width(GTK_CONTAINER(server_vbox), 5); - gtk_container_add(GTK_CONTAINER(server_frame), server_vbox); - - server_btn_hbox = gtk_hbox_new(FALSE, 5); - gtk_box_pack_start(GTK_BOX(server_vbox), - server_btn_hbox, FALSE, FALSE, 0); - - server_use_remote = gtk_check_button_new_with_label(_("Use remote host")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(server_use_remote), - esd_cfg.use_remote); - gtk_box_pack_start(GTK_BOX(server_btn_hbox), server_use_remote, - FALSE, FALSE, 0); - - server_oss_mixer = - gtk_check_button_new_with_label(_("Volume controls OSS mixer")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(server_oss_mixer), - esd_cfg.use_oss_mixer); - gtk_box_pack_start(GTK_BOX(server_btn_hbox), - server_oss_mixer, TRUE, TRUE, 0); -#if !defined(HAVE_SYS_SOUNDCARD_H) && !defined(HAVE_MACHINE_SOUNDCARD_H) - gtk_widget_set_sensitive(server_oss_mixer, FALSE); -#endif - server_hbox = gtk_hbox_new(FALSE, 5); - gtk_widget_set_sensitive(server_hbox, esd_cfg.use_remote); - gtk_box_pack_start(GTK_BOX(server_vbox), server_hbox, FALSE, FALSE, 0); - - server_host_label = gtk_label_new(_("Host:")); - gtk_box_pack_start(GTK_BOX(server_hbox), server_host_label, - FALSE, FALSE, 0); - - server_host_entry = gtk_entry_new(); - gtk_entry_set_text(GTK_ENTRY(server_host_entry), esd_cfg.server); - gtk_box_pack_start(GTK_BOX(server_hbox), server_host_entry, - TRUE, TRUE, 0); - - server_port_label = gtk_label_new(_("Port:")); - gtk_box_pack_start(GTK_BOX(server_hbox), server_port_label, - FALSE, FALSE, 0); - - server_port_entry = gtk_entry_new(); - gtk_widget_set_usize(server_port_entry, 50, -1); - temp = g_strdup_printf("%d", esd_cfg.port); - gtk_entry_set_text(GTK_ENTRY(server_port_entry), temp); - g_free(temp); - gtk_box_pack_start(GTK_BOX(server_hbox), server_port_entry, - FALSE, FALSE, 0); - - g_signal_connect(G_OBJECT(server_use_remote), "clicked", - G_CALLBACK(use_remote_cb), server_hbox); - - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), server_frame, - gtk_label_new(_("Server"))); - - buffer_frame = gtk_frame_new(_("Buffering:")); - gtk_container_set_border_width(GTK_CONTAINER(buffer_frame), 5); - - buffer_vbox = gtk_vbox_new(FALSE, 0); - gtk_container_add(GTK_CONTAINER(buffer_frame), buffer_vbox); - - buffer_table = gtk_table_new(2, 1, TRUE); - gtk_container_set_border_width(GTK_CONTAINER(buffer_table), 5); - gtk_box_pack_start(GTK_BOX(buffer_vbox), buffer_table, FALSE, FALSE, 0); - - buffer_size_box = gtk_hbox_new(FALSE, 5); - gtk_table_attach_defaults(GTK_TABLE(buffer_table), - buffer_size_box, 0, 1, 0, 1); - buffer_size_label = gtk_label_new(_("Buffer size (ms):")); - gtk_box_pack_start(GTK_BOX(buffer_size_box), - buffer_size_label, FALSE, FALSE, 0); - buffer_size_adj = gtk_adjustment_new(esd_cfg.buffer_size, - 200, 10000, 100, 100, 100); - buffer_size_spin = - gtk_spin_button_new(GTK_ADJUSTMENT(buffer_size_adj), 8, 0); - gtk_widget_set_usize(buffer_size_spin, 60, -1); - gtk_box_pack_start(GTK_BOX(buffer_size_box), - buffer_size_spin, FALSE, FALSE, 0); - - buffer_pre_box = gtk_hbox_new(FALSE, 5); - gtk_table_attach_defaults(GTK_TABLE(buffer_table), - buffer_pre_box, 1, 2, 0, 1); - buffer_pre_label = gtk_label_new(_("Pre-buffer (percent):")); - gtk_box_pack_start(GTK_BOX(buffer_pre_box), - buffer_pre_label, FALSE, FALSE, 0); - buffer_pre_adj = gtk_adjustment_new(esd_cfg.prebuffer, 0, 90, 1, 1, 1); - buffer_pre_spin = - gtk_spin_button_new(GTK_ADJUSTMENT(buffer_pre_adj), 1, 0); - gtk_widget_set_usize(buffer_pre_spin, 60, -1); - gtk_box_pack_start(GTK_BOX(buffer_pre_box), - buffer_pre_spin, FALSE, FALSE, 0); - - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), - buffer_frame, gtk_label_new(_("Buffering"))); - - bbox = gtk_hbutton_box_new(); - gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); - gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5); - gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0); - - cancel = gtk_button_new_from_stock(GTK_STOCK_CLOSE); - g_signal_connect_swapped(G_OBJECT(cancel), "clicked", - G_CALLBACK(gtk_widget_destroy), - GTK_OBJECT(configure_win)); - GTK_WIDGET_SET_FLAGS(cancel, GTK_CAN_DEFAULT); - gtk_box_pack_start(GTK_BOX(bbox), cancel, TRUE, TRUE, 0); - - ok = gtk_button_new_from_stock(GTK_STOCK_APPLY); - g_signal_connect(G_OBJECT(ok), "clicked", - G_CALLBACK(configure_win_ok_cb), NULL); - GTK_WIDGET_SET_FLAGS(ok, GTK_CAN_DEFAULT); - gtk_box_pack_start(GTK_BOX(bbox), ok, TRUE, TRUE, 0); - gtk_widget_grab_default(ok); - - gtk_window_set_position(GTK_WINDOW(configure_win), GTK_WIN_POS_CENTER); - gtk_widget_show_all(configure_win); -} diff --git a/src/esd/esd.c b/src/esd/esd.c deleted file mode 100644 index bd9c245..0000000 --- a/src/esd/esd.c +++ /dev/null @@ -1,45 +0,0 @@ -/* xmms - esound output plugin - * Copyright (C) 1999 Galex Yen - * - * this program is free software - * - * Description: - * This program is an output plugin for xmms v0.9 or greater. - * The program uses the esound daemon to output audio in order - * to allow more than one program to play audio on the same - * device at the same time. - * - * Contains code Copyright (C) 1998-1999 Mikael Alm, Olle Hallnas, - * Thomas Nillson and 4Front Technologies - * - */ - -#include "esdout.h" - -#include <glib.h> -#include <audacious/i18n.h> - - -OutputPlugin esd_op = { - .description = "ESD Output Plugin", - .probe_priority = 2, - .init = esdout_init, - .about = esdout_about, - .configure = esdout_configure, - .get_volume = esdout_get_volume, - .set_volume = esdout_set_volume, - .open_audio = esdout_open, - .write_audio = esdout_write, - .close_audio = esdout_close, - .flush = esdout_flush, - .pause = esdout_pause, - .buffer_free = esdout_free, - .buffer_playing = esdout_playing, - .output_time = esdout_get_output_time, - .written_time = esdout_get_written_time, - .tell_audio = esdout_tell -}; - -OutputPlugin *esd_oplist[] = { &esd_op, NULL }; - -DECLARE_PLUGIN(esd, NULL, NULL, NULL, esd_oplist, NULL, NULL, NULL, NULL); diff --git a/src/esd/esdout.h b/src/esd/esdout.h deleted file mode 100644 index 8b3a3a2..0000000 --- a/src/esd/esdout.h +++ /dev/null @@ -1,68 +0,0 @@ -/* BMP - Cross-platform multimedia player - * Copyright (C) 2003-2004 BMP development team. - * - * Based on XMMS: - * Copyright (C) 1998-2003 XMMS development team. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef ESDOUT_H -#define ESDOUT_H - -#include "config.h" - -#include <glib.h> - -#include <audacious/plugin.h> - - -extern OutputPlugin op; - -typedef struct { - gboolean use_remote; - gboolean use_oss_mixer; - char *server; - char *hostname; - char *playername; - int port; - int buffer_size; - int prebuffer; -} ESDConfig; - -extern ESDConfig esd_cfg; - -OutputPluginInitStatus esdout_init(void); -void esdout_about(void); -void esdout_configure(void); - -void esdout_get_volume(int *l, int *r); -void esdout_fetch_volume(int *l, int *r); -void esdout_set_volume(int l, int r); -void esdout_mixer_init(void); - -int esdout_playing(void); -int esdout_free(void); -void esdout_write(void *ptr, int length); -void esdout_close(void); -void esdout_flush(int time); -void esdout_pause(short p); -int esdout_open(AFormat fmt, int rate, int nch); -int esdout_get_output_time(void); -int esdout_get_written_time(void); -void esdout_set_audio_params(void); -void esdout_tell(AFormat * fmt, gint * rate, gint * nch); - -#endif diff --git a/src/esd/init.c b/src/esd/init.c deleted file mode 100644 index cd5ef32..0000000 --- a/src/esd/init.c +++ /dev/null @@ -1,92 +0,0 @@ -/* xmms - esound output plugin - * Copyright (C) 1999 Galex Yen - * - * this program is free software - * - * Description: - * This program is an output plugin for xmms v0.9 or greater. - * The program uses the esound daemon to output audio in order - * to allow more than one program to play audio on the same - * device at the same time. - * - * Contains code Copyright (C) 1998-1999 Mikael Alm, Olle Hallnas, - * Thomas Nillson and 4Front Technologies - * - */ - -#include <glib.h> -#include <stdlib.h> -#include <string.h> -#include <esd.h> -#include <audacious/plugin.h> -#include "esdout.h" - - -ESDConfig esd_cfg; -esd_info_t *all_info; -esd_player_info_t *player_info; - - -OutputPluginInitStatus -esdout_init(void) -{ - mcs_handle_t *db; - char *env; - int lp = 80 , rp = 80; - int fd; - - memset(&esd_cfg, 0, sizeof(ESDConfig)); - esd_cfg.port = ESD_DEFAULT_PORT; - esd_cfg.buffer_size = 3000; - esd_cfg.prebuffer = 25; - - db = aud_cfg_db_open(); - - if ((env = getenv("ESPEAKER")) != NULL) { - char *temp = NULL; - esd_cfg.use_remote = TRUE; - esd_cfg.server = g_strdup(env); - if (esd_cfg.server[0] == '[' && - NULL != (temp = strchr(esd_cfg.server + 1, ']')) && - temp[1] == ':') { - *temp = '\0'; - memmove(esd_cfg.server, esd_cfg.server + 1, temp - esd_cfg.server); - temp++; - } else if (NULL != (temp = strchr(esd_cfg.server, ':'))) { - if (strchr(temp + 1, ':')) temp = NULL; - } - if (temp != NULL) { - *temp = '\0'; - esd_cfg.port = atoi(temp + 1); - if (esd_cfg.port == 0) - esd_cfg.port = ESD_DEFAULT_PORT; - } - } - else { - aud_cfg_db_get_bool(db, "ESD", "use_remote", &esd_cfg.use_remote); - aud_cfg_db_get_string(db, "ESD", "remote_host", &esd_cfg.server); - aud_cfg_db_get_int(db, "ESD", "remote_port", &esd_cfg.port); - } - aud_cfg_db_get_bool(db, "ESD", "use_oss_mixer", &esd_cfg.use_oss_mixer); - aud_cfg_db_get_int(db, "ESD", "buffer_size", &esd_cfg.buffer_size); - aud_cfg_db_get_int(db, "ESD", "prebuffer", &esd_cfg.prebuffer); - - /* restore volume levels */ - aud_cfg_db_get_int(db, "ESD", "volume_left", &lp); - aud_cfg_db_get_int(db, "ESD", "volume_right", &rp); - esdout_set_volume(lp, rp); - - aud_cfg_db_close(db); - - if (!esd_cfg.server) - esd_cfg.server = g_strdup("localhost"); - - fd = esd_open_sound(esd_cfg.hostname); - if (fd >= 0) - { - esd_close(fd); - return OUTPUT_PLUGIN_INIT_FOUND_DEVICES; - } - else - return OUTPUT_PLUGIN_INIT_NO_DEVICES; -} diff --git a/src/esd/mixer.c b/src/esd/mixer.c deleted file mode 100644 index 624dd63..0000000 --- a/src/esd/mixer.c +++ /dev/null @@ -1,234 +0,0 @@ -/* BMP - Cross-platform multimedia player - * Copyright (C) 2003-2004 BMP development team. - * - * Based on XMMS: - * Copyright (C) 1998-2003 XMMS development team. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <esd.h> -#include <audacious/plugin.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/ioctl.h> -#include <sys/stat.h> - -#include "esdout.h" - -#ifdef HAVE_OSS -# ifdef HAVE_SYS_SOUNDCARD_H -# include <sys/soundcard.h> -# else -# include <soundcard.h> -# endif -# define OSS_AVAILABLE TRUE -#else -# define OSS_AVAILABLE FALSE -#endif - - -#define QUERY_PLAYER_ID_ATTEMPTS 5 - -static void esdout_get_oss_volume(int *l, int *r); -static void esdout_set_oss_volume(int l, int r); - - -static int player = -1; -static int lp = 100, rp = 100; - -/* - * Find the stream id, and set stream volume to 'persistent' value. - */ -void -esdout_mixer_init(void) -{ - int i; - - /* reset player id */ - player = -1; - - /* query n-time for player id */ - for(i=0; (i<QUERY_PLAYER_ID_ATTEMPTS) && (player == (-1)) ; i++) - esdout_fetch_volume(NULL, NULL); - - if (!(OSS_AVAILABLE && esd_cfg.use_oss_mixer && !esd_cfg.use_remote)) - esdout_set_volume(lp, rp); -} - -/* - * Grab the stream volume from the server. The problem here is that - * ESD does not have a built-in function for finding the player ID of - * a specific player - nor does it let us know what the player ID is - * when the player is created! So, we grab 'allinfo' and scan the - * returned player list for the string which we know is our player - * name (esd_cfg.playername) This function seems to take a long time - * to run... I'm not sure where to start optimizing, however... - */ -void -esdout_fetch_volume(int *l, int *r) -{ - int fd; - esd_info_t *all_info = NULL; - esd_player_info_t *info; - - fd = esd_open_sound(esd_cfg.hostname); - all_info = esd_get_all_info(fd); - - /* scan linked list for our playername */ - for (info = all_info->player_list; info != NULL; info = info->next) - if (!strcmp(esd_cfg.playername, info->name)) - break; - - if (info) { - player = info->source_id; - if (l && r) { - /* - * Sometimes we call with NULL - * args to fetch the player num - */ - *l = (info->left_vol_scale * 100) / 256; - *r = (info->right_vol_scale * 100) / 256; - } - } - else - g_warning("xmms: Couldn't find our player " - "(was looking for %s) at the server", esd_cfg.playername); - - if (all_info) - esd_free_all_info(all_info); - esd_close(fd); -} - -void -esdout_get_volume(int *l, int *r) -{ - if (OSS_AVAILABLE && esd_cfg.use_oss_mixer && !esd_cfg.use_remote) { - esdout_get_oss_volume(l, r); - lp = *l; - rp = *r; - } - else { - /* - * We assume that the volume hasn't changed from the - * 'persistant' value. Constantly polling takes too - * much time/resources. Commenting this section out - * will consistently check the ESD server to see if - * someone else changed our stream volume. - */ - *l = lp; - *r = rp; -/* esdout_fetch_volume(l, r); */ - } -} - -void -esdout_set_volume(int l, int r) -{ - mcs_handle_t *db; - lp = l; - rp = r; - - if (OSS_AVAILABLE && esd_cfg.use_oss_mixer && !esd_cfg.use_remote) { - esdout_set_oss_volume(l, r); - } - else if (player != -1 && esd_cfg.playername != NULL) { - int fd = esd_open_sound(esd_cfg.hostname); - if (fd >= 0) { - esd_set_stream_pan(fd, player, (l * 256) / 100, (r * 256) / 100); - esd_close(fd); - } - } - - /* save volume values in db */ - db = aud_cfg_db_open(); - aud_cfg_db_set_int(db, "ESD", "volume_left", lp); - aud_cfg_db_set_int(db, "ESD", "volume_right", rp); - aud_cfg_db_close(db); -} - -#ifdef HAVE_OSS - -static void -esdout_get_oss_volume(int *l, int *r) -{ - int fd, v, devs; - long cmd; - - if (esd_cfg.use_remote) - return; - - fd = open(DEV_MIXER, O_RDONLY); - if (fd != -1) { - ioctl(fd, SOUND_MIXER_READ_DEVMASK, &devs); - if (devs & SOUND_MASK_PCM) - cmd = SOUND_MIXER_READ_PCM; - else if (devs & SOUND_MASK_VOLUME) - cmd = SOUND_MIXER_READ_VOLUME; - else { - close(fd); - return; - } - ioctl(fd, cmd, &v); - *r = (v & 0xFF00) >> 8; - *l = (v & 0x00FF); - close(fd); - } -} - -static void -esdout_set_oss_volume(int l, int r) -{ - int fd, v, devs; - long cmd; - - if (esd_cfg.use_remote) - return; - - fd = open(DEV_MIXER, O_RDONLY); - - if (fd != -1) { - ioctl(fd, SOUND_MIXER_READ_DEVMASK, &devs); - if (devs & SOUND_MASK_PCM) - cmd = SOUND_MIXER_WRITE_PCM; - else if (devs & SOUND_MASK_VOLUME) - cmd = SOUND_MIXER_WRITE_VOLUME; - else { - close(fd); - return; - } - v = (r << 8) | l; - ioctl(fd, cmd, &v); - close(fd); - } -} - -#else - -static void -esdout_get_oss_volume(int *l, int *r) -{ -} - -static void -esdout_set_oss_volume(int l, int r) -{ -} - -#endif diff --git a/src/evdev-plug/ed.c b/src/evdev-plug/ed.c index b19e713..a2c2c94 100644 --- a/src/evdev-plug/ed.c +++ b/src/evdev-plug/ed.c @@ -24,9 +24,10 @@ #include "ed_actions.h" #include "ed_ui.h" #include "ed_common.h" -#include <audacious/i18n.h> -#include <audacious/auddrct.h> +#include <audacious/drct.h> +#include <audacious/i18n.h> +#include <libaudcore/hook.h> GeneralPlugin *evdevplug_gplist[] = { &ed_gp, NULL }; SIMPLE_GENERAL_PLUGIN(evdev-plug, evdevplug_gplist); @@ -141,84 +142,84 @@ ed_action_call ( gint code , gpointer param ) void ed_action_pb_play ( gpointer param ) { - audacious_drct_play(); + aud_drct_play(); } void ed_action_pb_stop ( gpointer param ) { - audacious_drct_stop(); + aud_drct_stop(); } void ed_action_pb_pause ( gpointer param ) { - if (audacious_drct_get_playing() || audacious_drct_get_paused()) - audacious_drct_pause(); + if (aud_drct_get_playing() || aud_drct_get_paused()) + aud_drct_pause(); else - audacious_drct_play(); + aud_drct_play(); } void ed_action_pb_prev ( gpointer param ) { - audacious_drct_pl_prev(); + aud_drct_pl_prev(); } void ed_action_pb_next ( gpointer param ) { - audacious_drct_pl_next(); + aud_drct_pl_next(); } void ed_action_pb_eject ( gpointer param ) { - audacious_drct_eject(); + hook_call ("filebrowser show", GINT_TO_POINTER (TRUE)); } void ed_action_pl_repeat ( gpointer param ) { - audacious_drct_pl_repeat_toggle(); + aud_drct_pl_repeat_toggle(); } void ed_action_pl_shuffle ( gpointer param ) { - audacious_drct_pl_shuffle_toggle(); + aud_drct_pl_shuffle_toggle(); } void ed_action_vol_up5 ( gpointer param ) { gint vl, vr; - audacious_drct_get_volume( &vl , &vr ); - audacious_drct_set_volume( CLAMP(vl + 5, 0, 100) , CLAMP(vr + 5, 0, 100) ); + aud_drct_get_volume( &vl , &vr ); + aud_drct_set_volume( CLAMP(vl + 5, 0, 100) , CLAMP(vr + 5, 0, 100) ); } void ed_action_vol_down5 ( gpointer param ) { gint vl, vr; - audacious_drct_get_volume( &vl , &vr ); - audacious_drct_set_volume( CLAMP(vl - 5, 0, 100) , CLAMP(vr - 5, 0, 100) ); + aud_drct_get_volume( &vl , &vr ); + aud_drct_set_volume( CLAMP(vl - 5, 0, 100) , CLAMP(vr - 5, 0, 100) ); } void ed_action_vol_up10 ( gpointer param ) { gint vl, vr; - audacious_drct_get_volume( &vl , &vr ); - audacious_drct_set_volume( CLAMP(vl + 10, 0, 100) , CLAMP(vr + 10, 0, 100) ); + aud_drct_get_volume( &vl , &vr ); + aud_drct_set_volume( CLAMP(vl + 10, 0, 100) , CLAMP(vr + 10, 0, 100) ); } void ed_action_vol_down10 ( gpointer param ) { gint vl, vr; - audacious_drct_get_volume( &vl , &vr ); - audacious_drct_set_volume( CLAMP(vl - 10, 0, 100) , CLAMP(vr - 10, 0, 100) ); + aud_drct_get_volume( &vl , &vr ); + aud_drct_set_volume( CLAMP(vl - 10, 0, 100) , CLAMP(vr - 10, 0, 100) ); } void @@ -229,26 +230,26 @@ ed_action_vol_mute ( gpointer param ) if ( vl == -1 ) /* no previous memory of volume before mute action */ { - audacious_drct_get_volume( &vl , &vr ); /* memorize volume before mute */ - audacious_drct_set_volume( 0 , 0 ); /* mute */ + aud_drct_get_volume( &vl , &vr ); /* memorize volume before mute */ + aud_drct_set_volume( 0 , 0 ); /* mute */ } else /* memorized volume values exist */ { gint vl_now = 0; gint vr_now = 0; - audacious_drct_get_volume( &vl_now , &vr_now ); + aud_drct_get_volume( &vl_now , &vr_now ); if (( vl_now == 0 ) && ( vr_now == 0 )) { /* the volume is still muted, restore the old values */ - audacious_drct_set_volume( vl , vr ); + aud_drct_set_volume( vl , vr ); vl = -1; vr = -1; /* reset these for next use */ } else { /* the volume has been raised with other commands, act as if there wasn't a previous memory */ - audacious_drct_get_volume( &vl , &vr ); /* memorize volume before mute */ - audacious_drct_set_volume( 0 , 0 ); /* mute */ + aud_drct_get_volume( &vl , &vr ); /* memorize volume before mute */ + aud_drct_set_volume( 0 , 0 ); /* mute */ } } } @@ -256,23 +257,27 @@ ed_action_vol_mute ( gpointer param ) void ed_action_win_main ( gpointer param ) { - audacious_drct_main_win_toggle( !audacious_drct_main_win_is_visible() ); + hook_call ("interface toggle visibility", NULL); } void ed_action_win_playlist ( gpointer param ) { - audacious_drct_pl_win_toggle( !audacious_drct_pl_win_is_visible () ); +#if 0 + aud_drct_pl_win_toggle( !aud_drct_pl_win_is_visible () ); +#endif } void ed_action_win_equalizer ( gpointer param ) { - audacious_drct_eq_win_toggle( !audacious_drct_eq_win_is_visible () ); +#if 0 + aud_drct_eq_win_toggle( !aud_drct_eq_win_is_visible () ); +#endif } void ed_action_win_jtf ( gpointer param ) { - audacious_drct_jtf_show(); + hook_call ("interface show jump to track", NULL); } diff --git a/src/evdev-plug/ed_internals.c b/src/evdev-plug/ed_internals.c index b7b3423..c12555a 100644 --- a/src/evdev-plug/ed_internals.c +++ b/src/evdev-plug/ed_internals.c @@ -35,11 +35,12 @@ #include <regex.h> /* for variadic */ #include <stdarg.h> -#include <audacious/plugin.h> -#include <audacious/i18n.h> #include <glib.h> #include <glib/gstdio.h> +#include <audacious/i18n.h> +#include <audacious/misc.h> + static gboolean ed_device_giofunc ( GIOChannel * , GIOCondition , gpointer ); static gint ed_util_get_data_from_keyfile( GKeyFile * , gchar * , ... ); @@ -476,7 +477,7 @@ ed_device_get_list_from_config ( void ) gchar *config_datadir = NULL; gint i = 0; - config_datadir = (gchar*)audacious_get_localdir(); + config_datadir = (gchar*)aud_util_get_localdir(); config_pathfilename = g_build_filename( config_datadir , PLAYER_LOCALRC_FILE , NULL ); g_free( config_datadir ); keyfile = g_key_file_new(); @@ -570,7 +571,7 @@ ed_device_start_listening_from_config ( void ) GList *system_devices_list = NULL; gint i = 0; - config_datadir = (gchar*)audacious_get_localdir(); + config_datadir = (gchar*)aud_util_get_localdir(); config_pathfilename = g_build_filename( config_datadir , PLAYER_LOCALRC_FILE , NULL ); g_free( config_datadir ); keyfile = g_key_file_new(); @@ -802,7 +803,7 @@ ed_config_save_from_list ( GList * config_devices_list ) gchar *config_pathfilename = NULL; gchar *config_datadir = NULL; - config_datadir = (gchar*)audacious_get_localdir(); + config_datadir = (gchar*)aud_util_get_localdir(); config_pathfilename = g_build_filename( config_datadir , PLAYER_LOCALRC_FILE , NULL ); keyfile = g_key_file_new(); @@ -885,7 +886,7 @@ ed_util_get_data_from_keyfile( GKeyFile * keyfile , gchar * device_name , ... ) *device_file = g_key_file_get_string( keyfile , device_name , "filename" , &gerr ); if ( gerr != NULL ) { - g_clear_error( &gerr ); + g_clear_error( &gerr ); g_warning( _("event-device-plugin: configuration, unable to get filename value for device \"%s\"" ", skipping it.\n") , device_name ); is_failed = TRUE; @@ -917,7 +918,7 @@ ed_util_get_data_from_keyfile( GKeyFile * keyfile , gchar * device_name , ... ) *is_custom = g_key_file_get_integer( keyfile , device_name , "is_custom" , &gerr ); if ( gerr != NULL ) { - g_clear_error( &gerr ); + g_clear_error( &gerr ); g_warning( _("event-device-plugin: configuration, unable to get is_custom value for device \"%s\"" ", skipping it.\n") , device_name ); is_failed = TRUE; @@ -931,7 +932,7 @@ ed_util_get_data_from_keyfile( GKeyFile * keyfile , gchar * device_name , ... ) *is_active = g_key_file_get_boolean( keyfile , device_name , "is_active" , &gerr ); if ( gerr != NULL ) { - g_clear_error( &gerr ); + g_clear_error( &gerr ); g_warning( _("event-device-plugin: configuration, unable to get is_active value for device \"%s\"" ", skipping it.\n") , device_name ); is_failed = TRUE; diff --git a/src/ffaudio/ffaudio-audvfs.c b/src/ffaudio/ffaudio-audvfs.c index 90ef99c..6fadebe 100644 --- a/src/ffaudio/ffaudio-audvfs.c +++ b/src/ffaudio/ffaudio-audvfs.c @@ -21,36 +21,18 @@ #include <libavutil/avstring.h> -static int audvfs_open(URLContext *h, const char *filename, int flags) -{ - VFSFile *file; - - av_strstart(filename, "audvfs:", &filename); - - if (flags & URL_WRONLY) { - file = aud_vfs_fopen(filename, "wb"); - } else { - file = aud_vfs_fopen(filename, "rb"); - } - - if (file == NULL) - return -ENOENT; - h->priv_data = file; - return 0; -} - static int audvfs_read(URLContext *h, unsigned char *buf, int size) { VFSFile *file; file = h->priv_data; - return aud_vfs_fread(buf, 1, size, file); + return vfs_fread(buf, 1, size, file); } static int audvfs_write(URLContext *h, const unsigned char *buf, int size) { VFSFile *file; file = h->priv_data; - return aud_vfs_fwrite(buf, 1, size, file); + return vfs_fwrite(buf, 1, size, file); } /* XXX: use llseek */ @@ -59,7 +41,7 @@ static int64_t audvfs_seek(URLContext *h, int64_t pos, int whence) int64_t res, siz; VFSFile *file; file = h->priv_data; - siz = aud_vfs_fsize(file); + siz = vfs_fsize(file); if (whence == AVSEEK_SIZE) return siz; @@ -67,12 +49,12 @@ static int64_t audvfs_seek(URLContext *h, int64_t pos, int whence) if (whence == SEEK_SET && pos > siz) return AVERROR(EPIPE); - if (aud_vfs_fseek(file, pos, whence) == 0) + if (vfs_fseek(file, pos, whence) == 0) { if (whence == SEEK_SET) res = pos; else - res = aud_vfs_ftell(file); + res = vfs_ftell(file); } else res = AVERROR(EPIPE); @@ -83,18 +65,9 @@ static int audvfs_close(URLContext *h) { VFSFile *file; file = h->priv_data; - return aud_vfs_fclose(file); + return vfs_fclose(file); } -URLProtocol audvfs_protocol = { - .name = "audvfs", - .url_open = audvfs_open, - .url_read = audvfs_read, - .url_write = audvfs_write, - .url_seek = audvfs_seek, - .url_close = audvfs_close, -}; - static int audvfsptr_open(URLContext *h, const char *filename, int flags) { VFSFile *p; @@ -102,8 +75,8 @@ static int audvfsptr_open(URLContext *h, const char *filename, int flags) av_strstart(filename, "audvfsptr:", &filename); p = (VFSFile *) strtoul(filename, NULL, 16); - h->priv_data = aud_vfs_dup(p); - aud_vfs_rewind(p); + h->priv_data = vfs_dup(p); + vfs_rewind(p); return 0; } diff --git a/src/ffaudio/ffaudio-core.c b/src/ffaudio/ffaudio-core.c index 33e6dc4..25bd02a 100644 --- a/src/ffaudio/ffaudio-core.c +++ b/src/ffaudio/ffaudio-core.c @@ -47,9 +47,6 @@ ffaudio_init(void) avcodec_init(); av_register_all(); - _DEBUG("registering audvfs protocol"); - av_register_protocol(&audvfs_protocol); - _DEBUG("registering audvfsptr protocol"); av_register_protocol(&audvfsptr_protocol); @@ -192,13 +189,13 @@ ffaudio_get_meta(Tuple *tuple, AVFormatContext *ic, const ffaudio_meta_t *m) switch (m->ttype) { case TUPLE_STRING: - tmp = aud_str_to_utf8(tag->value); - aud_tuple_associate_string(tuple, m->field, key_name, tmp); + tmp = str_to_utf8(tag->value); + tuple_associate_string(tuple, m->field, key_name, tmp); g_free(tmp); break; case TUPLE_INT: - aud_tuple_associate_int(tuple, m->field, key_name, atoi(tag->value)); + tuple_associate_int(tuple, m->field, key_name, atoi(tag->value)); break; default: @@ -219,40 +216,29 @@ ffaudio_get_tuple_data(Tuple *tuple, AVFormatContext *ic, AVCodecContext *c, AVC ffaudio_get_meta(tuple, ic, &metaentries[i]); #endif - aud_tuple_associate_int(tuple, FIELD_LENGTH, NULL, ic->duration / 1000); - } - - if (c != NULL) - { - aud_tuple_associate_int(tuple, FIELD_BITRATE, NULL, c->bit_rate / 1000); + tuple_associate_int(tuple, FIELD_LENGTH, NULL, ic->duration / 1000); + tuple_associate_int(tuple, FIELD_BITRATE, NULL, ic->bit_rate / 1000); } if (codec != NULL && codec->long_name != NULL) { - aud_tuple_associate_string(tuple, FIELD_CODEC, NULL, codec->long_name); + tuple_associate_string(tuple, FIELD_CODEC, NULL, codec->long_name); } } -static Tuple * -ffaudio_get_song_tuple(const gchar *filename) +static Tuple * read_tuple (const gchar * filename, VFSFile * file) { - Tuple *tuple = aud_tuple_new_from_filename(filename); AVCodec *codec = NULL; AVCodecContext *c = NULL; AVFormatContext *ic = NULL; AVStream *s = NULL; - gchar *uribuf; gint i; - if (tuple == NULL) return NULL; + gchar uribuf[64]; + snprintf (uribuf, sizeof uribuf, "audvfsptr:%p", (void *) file); - uribuf = g_alloca(strlen(filename) + 8); - sprintf(uribuf, "audvfs:%s", filename); if (av_open_input_file(&ic, uribuf, NULL, 0, NULL) < 0) - { - tuple_free(tuple); return NULL; - } for (i = 0; i < ic->nb_streams; i++) { @@ -267,6 +253,7 @@ ffaudio_get_song_tuple(const gchar *filename) } } + Tuple *tuple = tuple_new_from_filename(filename); ffaudio_get_tuple_data(tuple, ic, c, codec); av_close_input_file (ic); @@ -277,19 +264,17 @@ ffaudio_get_song_tuple(const gchar *filename) static Tuple * ffaudio_probe_for_tuple(const gchar *filename, VFSFile *fd) { - Tuple *t; - - t = ffaudio_get_song_tuple(filename); + Tuple * t = read_tuple (filename, fd); if (t == NULL) return NULL; - aud_vfs_fseek(fd, 0, SEEK_SET); + vfs_fseek(fd, 0, SEEK_SET); tag_tuple_read(t, fd); return t; } -static gboolean ffaudio_write_tag(Tuple *tuple, VFSFile *file) +static gboolean ffaudio_write_tag (const Tuple * tuple, VFSFile * file) { gchar *file_uri = g_ascii_strdown(file->uri, -4); @@ -304,9 +289,12 @@ static gboolean ffaudio_write_tag(Tuple *tuple, VFSFile *file) } #endif -static void -ffaudio_play_file(InputPlayback *playback) +static gboolean ffaudio_play (InputPlayback * playback, const gchar * filename, + VFSFile * file, gint start_time, gint stop_time, gboolean pause) { + if (file == NULL) + return FALSE; + AVCodec *codec = NULL; AVCodecContext *c = NULL; AVFormatContext *ic = NULL; @@ -317,20 +305,16 @@ ffaudio_play_file(InputPlayback *playback) gint in_sample_size, out_sample_size, chunk_size; ReSampleContext *resctx = NULL; gboolean codec_opened = FALSE, do_resampling = FALSE; - AFormat out_fmt; - gchar *uribuf; + gint out_fmt; #ifndef FFAUDIO_USE_AUDTAG Tuple *tuple; #endif gboolean paused = FALSE, seekable; - uribuf = g_alloca(strlen(playback->filename) + 8); - sprintf(uribuf, "audvfs:%s", playback->filename); - - _DEBUG("opening %s", uribuf); - + gchar uribuf[64]; + snprintf (uribuf, sizeof uribuf, "audvfsptr:%p", (void *) file); if (av_open_input_file(&ic, uribuf, NULL, 0, NULL) < 0) - return; + return FALSE; for (i = 0; i < ic->nb_streams; i++) { @@ -405,26 +389,25 @@ ffaudio_play_file(InputPlayback *playback) _DEBUG("setting parameters"); #ifndef FFAUDIO_USE_AUDTAG - tuple = aud_tuple_new_from_filename(playback->filename); + tuple = tuple_new_from_filename(playback->filename); ffaudio_get_tuple_data(tuple, ic, c, codec); playback->set_tuple(playback, tuple); #endif - playback->set_params(playback, NULL, 0, c->bit_rate, c->sample_rate, c->channels); + playback->set_params(playback, NULL, 0, ic->bit_rate, c->sample_rate, c->channels); g_mutex_lock(ctrl_mutex); playback->playing = TRUE; - seek_value = -1; - pause_flag = FALSE; + seek_value = (start_time > 0) ? start_time : -1; + pause_flag = pause; playback->set_pb_ready(playback); errcount = 0; seekable = ffaudio_codec_is_seekable(codec); g_mutex_unlock(ctrl_mutex); - - /* ctrl_mutex is locked at loop entry */ - while (playback->playing) + while (playback->playing && (stop_time < 0 || + playback->output->written_time () < stop_time)) { AVPacket tmp; gint ret; @@ -433,8 +416,9 @@ ffaudio_play_file(InputPlayback *playback) if (seek_value >= 0 && seekable) { - playback->output->flush(seek_value * 1000); - if (av_seek_frame(ic, -1, seek_value * AV_TIME_BASE, AVSEEK_FLAG_ANY) < 0) + playback->output->flush (seek_value); + if (av_seek_frame (ic, -1, (gint64) seek_value * AV_TIME_BASE / + 1000, AVSEEK_FLAG_ANY) < 0) { _ERROR("error while seeking"); } else @@ -540,7 +524,8 @@ ffaudio_play_file(InputPlayback *playback) outbuf_p = outbuf; /* Output audio in small blocks */ - while (out_size > 0 && playback->playing) + while (out_size > 0 && playback->playing && (stop_time < 0 || + playback->output->written_time () < stop_time)) { gint writeoff = MIN (chunk_size, out_size); @@ -600,6 +585,7 @@ error_exit: av_close_input_file(ic); _DEBUG("exiting thread"); + return ! playback->error; } static void ffaudio_stop(InputPlayback * playback) @@ -626,7 +612,7 @@ static void ffaudio_pause(InputPlayback * playback, gshort p) g_mutex_unlock(ctrl_mutex); } -static void ffaudio_seek(InputPlayback * playback, gint time) +static void ffaudio_seek (InputPlayback * playback, gulong time) { g_mutex_lock(ctrl_mutex); @@ -668,6 +654,9 @@ static gchar *ffaudio_fmts[] = { /* WAV (there are some WAV formats sndfile can't handle) */ "wav", + /* Handle OGG streams (FLAC/Vorbis etc.) */ + "ogg", + /* end of table */ NULL }; @@ -711,13 +700,10 @@ InputPlugin ffaudio_ip = { #ifdef FFAUDIO_USE_AUDTAG .probe_for_tuple = ffaudio_probe_for_tuple, #endif - .play_file = ffaudio_play_file, + .play = ffaudio_play, .stop = ffaudio_stop, .pause = ffaudio_pause, - .seek = ffaudio_seek, -#ifndef FFAUDIO_USE_AUDTAG - .get_song_tuple = ffaudio_get_song_tuple, -#endif + .mseek = ffaudio_seek, .about = ffaudio_about, .description = "FFaudio Plugin", .vfs_extensions = ffaudio_fmts, diff --git a/src/ffaudio/ffaudio-stdinc.h b/src/ffaudio/ffaudio-stdinc.h index c28fdc2..fe19309 100644 --- a/src/ffaudio/ffaudio-stdinc.h +++ b/src/ffaudio/ffaudio-stdinc.h @@ -27,7 +27,6 @@ #include <libavcodec/avcodec.h> #include <libavutil/avutil.h> -URLProtocol audvfs_protocol; URLProtocol audvfsptr_protocol; #endif diff --git a/src/filewriter/convert.c b/src/filewriter/convert.c index fb1095b..5a0b212 100644 --- a/src/filewriter/convert.c +++ b/src/filewriter/convert.c @@ -2,10 +2,10 @@ gpointer convert_output = NULL; static gint nch; -static AFormat in_fmt; -static AFormat out_fmt; +static gint in_fmt; +static gint out_fmt; -gboolean convert_init(AFormat input_fmt, AFormat output_fmt, gint channels) +gboolean convert_init(gint input_fmt, gint output_fmt, gint channels) { in_fmt = input_fmt; out_fmt = output_fmt; diff --git a/src/filewriter/convert.h b/src/filewriter/convert.h index b827bfd..ba417af 100644 --- a/src/filewriter/convert.h +++ b/src/filewriter/convert.h @@ -5,7 +5,7 @@ gpointer convert_output; -gboolean convert_init(AFormat input_fmt, AFormat output_fmt, gint channels); +gboolean convert_init(gint input_fmt, gint output_fmt, gint channels); gint convert_process(gpointer ptr, gint length); diff --git a/src/filewriter/filewriter.c b/src/filewriter/filewriter.c index cef86a7..5ca3752 100644 --- a/src/filewriter/filewriter.c +++ b/src/filewriter/filewriter.c @@ -20,6 +20,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include <audacious/configdb.h> +#include <audacious/misc.h> +#include <audacious/playlist.h> +#include <libaudcore/audstrings.h> +#include <libaudcore/tuple_formatter.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> @@ -82,13 +87,13 @@ static gboolean prependnumber = FALSE; static gchar *file_path = NULL; VFSFile *output_file = NULL; -Tuple *tuple = NULL; +const Tuple *tuple = NULL; static gint64 samples_written; static OutputPluginInitStatus file_init(void); static void file_about(void); -static gint file_open(AFormat fmt, gint rate, gint nch); +static gint file_open(gint fmt, gint rate, gint nch); static void file_write(void *ptr, gint length); static gint file_write_output(void *ptr, gint length); static void file_close(void); @@ -142,7 +147,7 @@ static void set_plugin(void) static OutputPluginInitStatus file_init(void) { - ConfigDb *db; + mcs_handle_t *db; db = aud_cfg_db_open(); aud_cfg_db_get_int(db, FILEWRITER_CFGID, "fileext", &fileext); @@ -192,8 +197,8 @@ void file_about (void) static VFSFile * safe_create (const gchar * filename) { - if (! aud_vfs_file_test (filename, G_FILE_TEST_EXISTS)) - return aud_vfs_fopen (filename, "w"); + if (! vfs_file_test (filename, G_FILE_TEST_EXISTS)) + return vfs_fopen (filename, "w"); const gchar * extension = strrchr (filename, '.'); gint length = strlen (filename); @@ -208,14 +213,14 @@ static VFSFile * safe_create (const gchar * filename) sprintf (scratch, "%.*s-%d%s", (gint) (extension - filename), filename, count, extension); - if (! aud_vfs_file_test (scratch, G_FILE_TEST_EXISTS)) - return aud_vfs_fopen (scratch, "w"); + if (! vfs_file_test (scratch, G_FILE_TEST_EXISTS)) + return vfs_fopen (scratch, "w"); } return NULL; } -static gint file_open(AFormat fmt, gint rate, gint nch) +static gint file_open(gint fmt, gint rate, gint nch) { gchar *filename = NULL, *temp = NULL; gchar * directory; @@ -232,13 +237,13 @@ static gint file_open(AFormat fmt, gint rate, gint nch) return 0; pos = aud_playlist_get_position(playlist); - tuple = (Tuple*) aud_playlist_entry_get_tuple(playlist, pos); + tuple = aud_playlist_entry_get_tuple (playlist, pos, FALSE); if (tuple == NULL) return 0; if (filenamefromtags) { - gchar *utf8 = aud_tuple_formatter_make_title_string(tuple, aud_get_gentitle_format()); + gchar *utf8 = tuple_formatter_make_title_string(tuple, aud_get_gentitle_format()); string_replace_char (utf8, '/', ' '); filename = string_encode_percent (utf8, FALSE); @@ -259,7 +264,7 @@ static gint file_open(AFormat fmt, gint rate, gint nch) if (prependnumber) { - gint number = aud_tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL); + gint number = tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL); if (!tuple || !number) number = pos + 1; @@ -315,7 +320,7 @@ static void file_write(void *ptr, gint length) static gint file_write_output(void *ptr, gint length) { - return aud_vfs_fwrite(ptr, 1, length, output_file); + return vfs_fwrite(ptr, 1, length, output_file); } static void file_close(void) @@ -324,7 +329,7 @@ static void file_close(void) convert_free(); if (output_file != NULL) - aud_vfs_fclose(output_file); + vfs_fclose(output_file); output_file = NULL; } @@ -352,7 +357,7 @@ static gint file_get_time (void) static void configure_ok_cb(gpointer data) { - ConfigDb *db; + mcs_handle_t *db; fileext = gtk_combo_box_get_active(GTK_COMBO_BOX(fileext_combo)); diff --git a/src/filewriter/filewriter.h b/src/filewriter/filewriter.h index f893ad8..bffdf81 100644 --- a/src/filewriter/filewriter.h +++ b/src/filewriter/filewriter.h @@ -34,7 +34,7 @@ struct format_info { - AFormat format; + gint format; int frequency; int channels; }; @@ -43,7 +43,7 @@ extern struct format_info input; extern VFSFile *output_file; extern guint64 offset; -extern Tuple *tuple; +extern const Tuple * tuple; typedef gint (*write_output_callback)(void *ptr, gint length); @@ -54,7 +54,7 @@ typedef struct _FileWriter gint (*open)(void); void (*write)(void *ptr, gint length); void (*close)(void); - AFormat format_required; + gint format_required; } FileWriter; #endif diff --git a/src/filewriter/flac.c b/src/filewriter/flac.c index 4fe051a..6e14c05 100644 --- a/src/filewriter/flac.c +++ b/src/filewriter/flac.c @@ -45,7 +45,7 @@ static FLAC__StreamEncoder *flac_encoder; static FLAC__StreamEncoderWriteStatus flac_write_cb(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, gpointer data) { - aud_vfs_fwrite(buffer, bytes, 1, (VFSFile *) data); + vfs_fwrite(buffer, bytes, 1, (VFSFile *) data); return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; } @@ -55,7 +55,7 @@ static FLAC__StreamEncoderSeekStatus flac_seek_cb(const FLAC__StreamEncoder *enc { VFSFile *file = (VFSFile *) data; - if (aud_vfs_fseek(file, absolute_byte_offset, SEEK_SET) < 0) + if (vfs_fseek(file, absolute_byte_offset, SEEK_SET) < 0) return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR; return FLAC__STREAM_ENCODER_SEEK_STATUS_OK; @@ -66,7 +66,7 @@ static FLAC__StreamEncoderTellStatus flac_tell_cb(const FLAC__StreamEncoder *enc { VFSFile *file = (VFSFile *) data; - *absolute_byte_offset = aud_vfs_ftell(file); + *absolute_byte_offset = vfs_ftell(file); return FLAC__STREAM_ENCODER_TELL_STATUS_OK; } @@ -98,14 +98,14 @@ static gint flac_open(void) meta = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT); - INSERT_VORBIS_COMMENT(aud_tuple_get_string(tuple, FIELD_TITLE, NULL), "title=%s"); - INSERT_VORBIS_COMMENT(aud_tuple_get_string(tuple, FIELD_ARTIST, NULL), "artist=%s"); - INSERT_VORBIS_COMMENT(aud_tuple_get_string(tuple, FIELD_ALBUM, NULL), "album=%s"); - INSERT_VORBIS_COMMENT(aud_tuple_get_string(tuple, FIELD_GENRE, NULL), "genre=%s"); - INSERT_VORBIS_COMMENT(aud_tuple_get_string(tuple, FIELD_COMMENT, NULL), "comment=%s"); - INSERT_VORBIS_COMMENT(aud_tuple_get_string(tuple, FIELD_DATE, NULL), "date=%s"); - INSERT_VORBIS_COMMENT(aud_tuple_get_int(tuple, FIELD_YEAR, NULL), "year=%d"); - INSERT_VORBIS_COMMENT(aud_tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL), "tracknumber=%d"); + INSERT_VORBIS_COMMENT(tuple_get_string(tuple, FIELD_TITLE, NULL), "title=%s"); + INSERT_VORBIS_COMMENT(tuple_get_string(tuple, FIELD_ARTIST, NULL), "artist=%s"); + INSERT_VORBIS_COMMENT(tuple_get_string(tuple, FIELD_ALBUM, NULL), "album=%s"); + INSERT_VORBIS_COMMENT(tuple_get_string(tuple, FIELD_GENRE, NULL), "genre=%s"); + INSERT_VORBIS_COMMENT(tuple_get_string(tuple, FIELD_COMMENT, NULL), "comment=%s"); + INSERT_VORBIS_COMMENT(tuple_get_string(tuple, FIELD_DATE, NULL), "date=%s"); + INSERT_VORBIS_COMMENT(tuple_get_int(tuple, FIELD_YEAR, NULL), "year=%d"); + INSERT_VORBIS_COMMENT(tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL), "tracknumber=%d"); FLAC__stream_encoder_set_metadata(flac_encoder, &meta, 1); } diff --git a/src/filewriter/mp3.c b/src/filewriter/mp3.c index 843d533..e1b323f 100644 --- a/src/filewriter/mp3.c +++ b/src/filewriter/mp3.c @@ -28,6 +28,9 @@ #include <lame/lame.h> +#include <audacious/configdb.h> +#include <audacious/debug.h> + static void mp3_init(write_output_callback write_output_func); static void mp3_configure(void); static gint mp3_open(void); @@ -156,7 +159,7 @@ static void lame_debugf(const char *format, va_list ap) static void mp3_init(write_output_callback write_output_func) { - ConfigDb *db = aud_cfg_db_open(); + mcs_handle_t *db = aud_cfg_db_open(); aud_cfg_db_get_int(db, "filewriter_mp3", "vbr_on", &vbr_on); aud_cfg_db_get_int(db, "filewriter_mp3", "vbr_type", &vbr_type); aud_cfg_db_get_int(db, "filewriter_mp3", "vbr_min_val", &vbr_min_val); @@ -207,27 +210,27 @@ static gint mp3_open(void) if (tuple) { /* XXX write UTF-8 even though libmp3lame does id3v2.3. --yaz */ lameid3.track_name = - g_strdup(aud_tuple_get_string(tuple, FIELD_TITLE, NULL)); + g_strdup(tuple_get_string(tuple, FIELD_TITLE, NULL)); id3tag_set_title(gfp, lameid3.track_name); lameid3.performer = - g_strdup(aud_tuple_get_string(tuple, FIELD_ARTIST, NULL)); + g_strdup(tuple_get_string(tuple, FIELD_ARTIST, NULL)); id3tag_set_artist(gfp, lameid3.performer); lameid3.album_name = - g_strdup(aud_tuple_get_string(tuple, FIELD_ALBUM, NULL)); + g_strdup(tuple_get_string(tuple, FIELD_ALBUM, NULL)); id3tag_set_album(gfp, lameid3.album_name); lameid3.genre = - g_strdup(aud_tuple_get_string(tuple, FIELD_GENRE, NULL)); + g_strdup(tuple_get_string(tuple, FIELD_GENRE, NULL)); id3tag_set_genre(gfp, lameid3.genre); lameid3.year = - g_strdup_printf("%d", aud_tuple_get_int(tuple, FIELD_YEAR, NULL)); + g_strdup_printf("%d", tuple_get_int(tuple, FIELD_YEAR, NULL)); id3tag_set_year(gfp, lameid3.year); lameid3.track_number = - g_strdup_printf("%d", aud_tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL)); + g_strdup_printf("%d", tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL)); id3tag_set_track(gfp, lameid3.track_number); if (force_v2_val) { @@ -360,7 +363,7 @@ static void mp3_close(void) /* update v2 tag */ imp3 = lame_get_id3v2_tag(gfp, encbuffer, sizeof(encbuffer)); if (imp3 > 0) { - if (aud_vfs_fseek(output_file, 0, SEEK_SET) != 0) { + if (vfs_fseek(output_file, 0, SEEK_SET) != 0) { AUDDBG("can't rewind\n"); } else { @@ -370,7 +373,7 @@ static void mp3_close(void) /* update lame tag */ if (id3v2_size) { - if (aud_vfs_fseek(output_file, id3v2_size, SEEK_SET) != 0) { + if (vfs_fseek(output_file, id3v2_size, SEEK_SET) != 0) { AUDDBG("fatal error: can't update LAME-tag frame!\n"); } else { @@ -646,7 +649,7 @@ static void id3_only_version(GtkToggleButton * togglebutton, static void configure_ok_cb(gpointer data) { - ConfigDb *db; + mcs_handle_t *db; if (vbr_min_val > vbr_max_val) vbr_max_val = vbr_min_val; diff --git a/src/filewriter/vorbis.c b/src/filewriter/vorbis.c index 52193a7..6ec91c3 100644 --- a/src/filewriter/vorbis.c +++ b/src/filewriter/vorbis.c @@ -27,6 +27,8 @@ #include <stdlib.h> #include <stdint.h> +#include <audacious/configdb.h> + static void vorbis_init(write_output_callback write_output_func); static void vorbis_configure(void); static gint vorbis_open(void); @@ -57,7 +59,7 @@ static vorbis_comment vc; static void vorbis_init(write_output_callback write_output_func) { - ConfigDb *db = aud_cfg_db_open(); + mcs_handle_t *db = aud_cfg_db_open(); aud_cfg_db_get_float(db, "filewriter_vorbis", "base_quality", &v_base_quality); @@ -84,26 +86,26 @@ static gint vorbis_open(void) gchar tmpstr[32]; gint scrint; - if ((scratch = aud_tuple_get_string(tuple, FIELD_TITLE, NULL))) + if ((scratch = tuple_get_string(tuple, FIELD_TITLE, NULL))) vorbis_comment_add_tag(&vc, "title", (gchar *) scratch); - if ((scratch = aud_tuple_get_string(tuple, FIELD_ARTIST, NULL))) + if ((scratch = tuple_get_string(tuple, FIELD_ARTIST, NULL))) vorbis_comment_add_tag(&vc, "artist", (gchar *) scratch); - if ((scratch = aud_tuple_get_string(tuple, FIELD_ALBUM, NULL))) + if ((scratch = tuple_get_string(tuple, FIELD_ALBUM, NULL))) vorbis_comment_add_tag(&vc, "album", (gchar *) scratch); - if ((scratch = aud_tuple_get_string(tuple, FIELD_GENRE, NULL))) + if ((scratch = tuple_get_string(tuple, FIELD_GENRE, NULL))) vorbis_comment_add_tag(&vc, "genre", (gchar *) scratch); - if ((scratch = aud_tuple_get_string(tuple, FIELD_DATE, NULL))) + if ((scratch = tuple_get_string(tuple, FIELD_DATE, NULL))) vorbis_comment_add_tag(&vc, "date", (gchar *) scratch); - if ((scratch = aud_tuple_get_string(tuple, FIELD_COMMENT, NULL))) + if ((scratch = tuple_get_string(tuple, FIELD_COMMENT, NULL))) vorbis_comment_add_tag(&vc, "comment", (gchar *) scratch); - if ((scrint = aud_tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL))) + if ((scrint = tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL))) { g_snprintf(tmpstr, sizeof(tmpstr), "%d", scrint); vorbis_comment_add_tag(&vc, "tracknumber", tmpstr); } - if ((scrint = aud_tuple_get_int(tuple, FIELD_YEAR, NULL))) + if ((scrint = tuple_get_int(tuple, FIELD_YEAR, NULL))) { g_snprintf(tmpstr, sizeof(tmpstr), "%d", scrint); vorbis_comment_add_tag(&vc, "year", tmpstr); @@ -215,7 +217,7 @@ static void quality_change(GtkAdjustment *adjustment, gpointer user_data) static void configure_ok_cb(gpointer data) { - ConfigDb *db = aud_cfg_db_open(); + mcs_handle_t *db = aud_cfg_db_open(); aud_cfg_db_set_float(db, "filewrite_vorbis", "base_quality", v_base_quality); diff --git a/src/filewriter/wav.c b/src/filewriter/wav.c index 369b971..c815337 100644 --- a/src/filewriter/wav.c +++ b/src/filewriter/wav.c @@ -75,7 +75,7 @@ static gint wav_open(void) header.byte_p_spl = GUINT16_TO_LE((GUINT16_FROM_LE(header.bit_p_spl) / (8 / input.channels))); memcpy(&header.data_chunk, "data", 4); header.data_length = GUINT32_TO_LE(0); - aud_vfs_fwrite(&header, sizeof (struct wavhead), 1, output_file); + vfs_fwrite(&header, sizeof (struct wavhead), 1, output_file); written = 0; @@ -84,7 +84,7 @@ static gint wav_open(void) static void wav_write(void *ptr, gint length) { - written += aud_vfs_fwrite(ptr, 1, length, output_file); + written += vfs_fwrite(ptr, 1, length, output_file); } static void wav_close(void) @@ -94,7 +94,7 @@ static void wav_close(void) header.length = GUINT32_TO_LE(written + sizeof (struct wavhead) - 8); header.data_length = GUINT32_TO_LE(written); - aud_vfs_fseek(output_file, 0, SEEK_SET); - aud_vfs_fwrite(&header, sizeof (struct wavhead), 1, output_file); + vfs_fseek(output_file, 0, SEEK_SET); + vfs_fwrite(&header, sizeof (struct wavhead), 1, output_file); } } diff --git a/src/flacng/debug.h b/src/flacng/debug.h deleted file mode 100644 index 961e44b..0000000 --- a/src/flacng/debug.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * A FLAC decoder plugin for the Audacious Media Player - * Copyright (C) 2005 Ralf Ertzinger - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#ifndef DEBUG_H -#define DEBUG_H - -#include <stdio.h> - -#define _ENTER _DEBUG("enter") -#define _LEAVE _DEBUG("leave"); return - -#define _ERROR(...) do { printf ("flacng: " __VA_ARGS__); putchar ('\n'); } while (0) - -#ifdef FLACNG_DEBUG -#define _DEBUG _ERROR -#else -#define _DEBUG(...) -#endif - -#endif diff --git a/src/flacng/flac_compat112.c b/src/flacng/flac_compat112.c index a735c09..e8727ad 100644 --- a/src/flacng/flac_compat112.c +++ b/src/flacng/flac_compat112.c @@ -19,7 +19,6 @@ #include <FLAC/all.h> #include "flac_compat112.h" -#include "debug.h" #if !defined(FLAC_API_VERSION_CURRENT) @@ -35,10 +34,6 @@ FLAC__SeekableStreamDecoderState FLAC__stream_decoder_init_stream( FLAC__SeekableStreamDecoderErrorCallback error_callback, void * client_data) { - FLAC__SeekableStreamDecoderState ret; - - _ENTER; - FLAC__seekable_stream_decoder_set_read_callback(decoder, read_callback); FLAC__seekable_stream_decoder_set_seek_callback(decoder, seek_callback); FLAC__seekable_stream_decoder_set_tell_callback(decoder, tell_callback); @@ -49,9 +44,7 @@ FLAC__SeekableStreamDecoderState FLAC__stream_decoder_init_stream( FLAC__seekable_stream_decoder_set_error_callback(decoder, error_callback); FLAC__seekable_stream_decoder_set_client_data(decoder, client_data); - ret = FLAC__seekable_stream_decoder_init(decoder); - - _LEAVE ret; + return FLAC__seekable_stream_decoder_init(decoder); } #endif diff --git a/src/flacng/flacng.h b/src/flacng/flacng.h index 9c1484e..aef1d7d 100644 --- a/src/flacng/flacng.h +++ b/src/flacng/flacng.h @@ -23,6 +23,11 @@ #include <glib.h> #include <audacious/plugin.h> #include <audacious/i18n.h> +#include <FLAC/all.h> + +#define ERROR(...) do { \ + printf("flacng: " __VA_ARGS__); \ +} while (0) #define OUTPUT_BLOCK_SIZE (1024u) #define MAX_SUPPORTED_CHANNELS (2u) @@ -73,7 +78,6 @@ struct stream_comment { */ struct stream_replaygain { gboolean has_rg; - gchar* ref_loud; gchar* track_gain; gchar* track_peak; gchar* album_gain; @@ -83,19 +87,17 @@ struct stream_replaygain { typedef struct callback_info { GMutex* mutex; + FLAC__StreamMetadata *metadata; gint32* output_buffer; gint32* write_pointer; guint buffer_free; guint buffer_used; - VFSFile* input_stream; + VFSFile* fd; struct stream_info stream; struct stream_comment comment; struct stream_replaygain replaygain; gboolean metadata_changed; struct frame_info frame; - glong read_max; - gboolean testing; - gchar* name; gint bitrate; } callback_info; diff --git a/src/flacng/plugin.c b/src/flacng/plugin.c index a001e01..09c39ce 100644 --- a/src/flacng/plugin.c +++ b/src/flacng/plugin.c @@ -18,130 +18,103 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "flacng.h" +#include <audacious/debug.h> #include <audacious/i18n.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> +#include "flacng.h" + #include "tools.h" #include "seekable_stream_callbacks.h" #include "version.h" -#include "debug.h" -FLAC__StreamDecoder* test_decoder; -FLAC__StreamDecoder* main_decoder; -callback_info* test_info; -callback_info* main_info; +FLAC__StreamDecoder *test_decoder; +FLAC__StreamDecoder *main_decoder; +callback_info *test_info; +callback_info *main_info; gboolean plugin_initialized = FALSE; static GMutex *seek_mutex; static GCond *seek_cond; -static gboolean pause_flag; static gint seek_value; -/* === */ - static void flac_init(void) { - FLAC__StreamDecoderInitStatus ret; - _ENTER; + /* Callback structure and decoder for file test purposes */ - /* - * Callback structure and decoder for file test - * purposes - */ - if (NULL == (test_info = init_callback_info("test"))) { - _ERROR("Could not initialize the test callback structure!"); - _LEAVE; + if ((test_info = init_callback_info()) == NULL) + { + ERROR("Could not initialize the test callback structure!\n"); + return; } - _DEBUG("Test callback structure at %p", test_info); - if (NULL == (test_decoder = FLAC__stream_decoder_new())) { - _ERROR("Could not create the test FLAC decoder instance!"); - _LEAVE; + if ((test_decoder = FLAC__stream_decoder_new()) == NULL) + { + ERROR("Could not create the test FLAC decoder instance!\n"); + return; } - - /* - * We want the VORBISCOMMENT metadata, for the file tags - * and SEEKTABLE - */ FLAC__stream_decoder_set_metadata_respond(test_decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT); - FLAC__stream_decoder_set_metadata_respond(test_decoder, FLAC__METADATA_TYPE_SEEKTABLE); - - /* - * Callback structure and decoder for main decoding - * loop - */ - if (NULL == (main_info = init_callback_info("main"))) { - _ERROR("Could not initialize the main callback structure!"); - _LEAVE; - } - _DEBUG("Main callback structure at %p", main_info); - if (NULL == (main_decoder = FLAC__stream_decoder_new())) { - _ERROR("Could not create the main FLAC decoder instance!"); - _LEAVE; + if (FLAC__STREAM_DECODER_INIT_STATUS_OK != (ret = FLAC__stream_decoder_init_stream( + test_decoder, + read_callback, + seek_callback, + tell_callback, + length_callback, + eof_callback, + write_callback, + metadata_callback, + error_callback, + test_info))) + { + ERROR("Could not initialize the test FLAC decoder: %s(%d)\n", + FLAC__StreamDecoderInitStatusString[ret], ret); + return; } + /* Callback structure and decoder for main decoding loop */ - /* - * We want the VORBISCOMMENT metadata, for the file tags - * and SEEKTABLE - */ - FLAC__stream_decoder_set_metadata_respond(main_decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT); - FLAC__stream_decoder_set_metadata_respond(main_decoder, FLAC__METADATA_TYPE_SEEKTABLE); + if ((main_info = init_callback_info()) == NULL) + { + ERROR("Could not initialize the main callback structure!\n"); + return; + } - /* - * Initialize decoders - */ - if (FLAC__STREAM_DECODER_INIT_STATUS_OK != (ret = FLAC__stream_decoder_init_stream( - test_decoder, - read_callback, - seek_callback, - tell_callback, - length_callback, - eof_callback, - write_callback, - metadata_callback, - error_callback, - test_info))) { - _ERROR("Could not initialize test FLAC decoder: %s(%d)", - FLAC__StreamDecoderInitStatusString[ret], ret); - _LEAVE; - } + if ((main_decoder = FLAC__stream_decoder_new()) == NULL) + { + ERROR("Could not create the main FLAC decoder instance!\n"); + return; + } if (FLAC__STREAM_DECODER_INIT_STATUS_OK != (ret = FLAC__stream_decoder_init_stream( - main_decoder, - read_callback, - seek_callback, - tell_callback, - length_callback, - eof_callback, - write_callback, - metadata_callback, - error_callback, - main_info))) { - _ERROR("Could not initialize main FLAC decoder: %s(%d)", - FLAC__StreamDecoderInitStatusString[ret], ret); - _LEAVE; - } + main_decoder, + read_callback, + seek_callback, + tell_callback, + length_callback, + eof_callback, + write_callback, + metadata_callback, + error_callback, + main_info))) + { + ERROR("Could not initialize the main FLAC decoder: %s(%d)\n", + FLAC__StreamDecoderInitStatusString[ret], ret); + return; + } seek_mutex = g_mutex_new(); seek_cond = g_cond_new(); - _DEBUG("plugin initialized OK!"); - plugin_initialized = TRUE; - _LEAVE; + AUDDBG("Plugin initialized.\n"); + plugin_initialized = TRUE; } -/* --- */ - static void flac_cleanup(void) { - _ENTER; - g_mutex_free(seek_mutex); g_cond_free(seek_cond); @@ -152,242 +125,199 @@ static void flac_cleanup(void) clean_callback_info(test_info); plugin_initialized = FALSE; - - _LEAVE; } -/* --- */ - -gboolean flac_is_our_fd(const gchar* filename, VFSFile* fd) { - - _ENTER; - - if (!plugin_initialized) { - _ERROR("Plugin not initialized!"); - _LEAVE FALSE; - } - - _DEBUG("Testing fd for file: %s", filename); - - INFO_LOCK(test_info); - - if (FALSE == read_metadata(fd, test_decoder, test_info)) { - _DEBUG("File not handled by this plugin!"); - INFO_UNLOCK(test_info); - _LEAVE FALSE; - } - - /* - * See if the metadata has changed - */ - if (FALSE == test_info->metadata_changed) { - _DEBUG("No metadata found in stream"); - INFO_UNLOCK(test_info); - _LEAVE FALSE; - } +gboolean flac_is_our_fd(const gchar *filename, VFSFile *fd) +{ + AUDDBG("Probe for FLAC.\n"); - /* - * If we get here, the file is supported by FLAC. - * The stream characteristics have been filled in by - * the metadata callback. - */ - - _DEBUG("Stream encoded at %d Hz, %d bps, %d channels", - test_info->stream.samplerate, - test_info->stream.bits_per_sample, - test_info->stream.channels); - - if (MAX_SUPPORTED_CHANNELS < test_info->stream.channels) { - _ERROR("This number of channels (%d) is currently not supported, stream not handled by this plugin", - test_info->stream.channels); - INFO_UNLOCK(test_info); - _LEAVE FALSE; - } + gchar *buf = g_new0(gchar, 4); + gboolean flac; - if ((8 != test_info->stream.bits_per_sample) && - (16 != test_info->stream.bits_per_sample) && - (24 != test_info->stream.bits_per_sample) && - (32 != test_info->stream.bits_per_sample)) { - _ERROR("This number of bits (%d) is currently not supported, stream not handled by this plugin", - test_info->stream.bits_per_sample); - INFO_UNLOCK(test_info); - _LEAVE FALSE; + if (vfs_fseek(fd, 0, SEEK_SET)) + { + g_free(buf); + return FALSE; } - /* - * Looks good. - */ - - _DEBUG("Accepting file %s", filename); + vfs_fread(buf, 4, 1, fd); + flac = strncmp(buf, "fLaC", 4); + g_free(buf); - reset_info(test_info, FALSE); - INFO_UNLOCK(test_info); - - _LEAVE TRUE; + if (!flac) + return TRUE; + else + return FALSE; } -/* --- */ - -void squeeze_audio(gint32* src, void* dst, guint count, guint res) { - +static void squeeze_audio(gint32* src, void* dst, guint count, guint res) +{ gint i; gint32* rp = src; - gint8* wp = dst; + gint8* wp = dst; gint16* wp2 = dst; gint32* wp4 = dst; - _ENTER; + switch (res) + { + case 8: + for (i = 0; i < count; i++, wp++, rp++) + *wp = *rp & 0xff; + break; - _DEBUG("Converting %d samples to %d bit", count, res); + case 16: + for (i = 0; i < count; i++, wp2++, rp++) + *wp2 = *rp & 0xffff; + break; - if (res % 8 != 0) { - _ERROR("Can not convert to %d bps: not a multiple of 8", res); - _LEAVE; - } + case 24: + case 32: + for (i = 0; i < count; i++, wp4++, rp++) + *wp4 = *rp; + break; - if (res == 8) { - for (i=0; i<count; i++, wp++, rp++) { - *wp = *rp & 0xff; - } - } else if (res == 16) { - for (i=0; i<count; i++, wp2++, rp++) { - *wp2 = *rp & 0xffff; - } - } else if (res == 24 || res == 32) { /* 24bit value stored in lowest 3 bytes */ - for (i=0; i<count; i++, wp4++, rp++) { - *wp4 = *rp; - } + default: + ERROR("Can not convert to %d bps\n", res); } - - _LEAVE; } -/* --- */ - -static gpointer flac_play_loop(gpointer arg) +static gboolean flac_play (InputPlayback * playback, const gchar * filename, + VFSFile * file, gint start_time, gint stop_time, gboolean pause) { - /* - * The main play loop. - * Decode a frame, push the decoded data to the output plugin - * chunkwise. Repeat until finished. - */ + if (file == NULL) + return FALSE; - gint32* read_pointer; + gint32 *read_pointer; gint elements_left; - FLAC__StreamDecoderState state; struct stream_info stream_info; guint sample_count; - void* play_buffer; - InputPlayback* playback = (InputPlayback *) arg; - gboolean paused = FALSE; + gpointer play_buffer = NULL; + + if (!plugin_initialized) + { + ERROR("Plugin not initialized!\n"); + return FALSE; + } - _ENTER; + main_info->fd = file; - if (NULL == (play_buffer = g_malloc(BUFFER_SIZE_BYTE))) { - _ERROR("Could not allocate conversion buffer"); - playback->playing = FALSE; - reset_info(main_info, TRUE); - _LEAVE NULL; + if (read_metadata(main_decoder, main_info) == FALSE) + { + ERROR("Could not prepare file for playing!\n"); + goto CLEANUP; } - stream_info.samplerate = main_info->stream.samplerate; - stream_info.channels = main_info->stream.channels; - main_info->metadata_changed = FALSE; + if (main_info->stream.channels > MAX_SUPPORTED_CHANNELS) + { + ERROR("This number of channels (%d) is currently not supported, stream not handled by this plugin.\n", + main_info->stream.channels); + goto CLEANUP; + } + + if (main_info->stream.bits_per_sample != 8 && + main_info->stream.bits_per_sample != 16 && + main_info->stream.bits_per_sample != 24 && + main_info->stream.bits_per_sample != 32) + { + ERROR("This number of bits (%d) is currently not supported, stream not handled by this plugin.\n", + main_info->stream.bits_per_sample); + goto CLEANUP; + } + seek_value = (start_time > 0) ? start_time : -1; + playback->playing = TRUE; - if (!playback->output->open_audio(SAMPLE_FMT(main_info->stream.bits_per_sample), - main_info->stream.samplerate, - main_info->stream.channels)) { - g_free(play_buffer); - reset_info(main_info, TRUE); - playback->playing = FALSE; - _ERROR("Could not open output plugin!"); - _LEAVE NULL; + if ((play_buffer = g_malloc0(BUFFER_SIZE_BYTE)) == NULL) + { + ERROR("Could not allocate conversion buffer\n"); + goto CLEANUP; } - playback->set_gain_from_playlist(playback); + if (! playback->output->open_audio (SAMPLE_FMT + (main_info->stream.bits_per_sample), main_info->stream.samplerate, + main_info->stream.channels)) + { + ERROR("Could not open output plugin!\n"); + goto CLEANUP; + } + if (pause) + playback->output->pause (TRUE); - while (TRUE == playback->playing) { + playback->set_params(playback, NULL, 0, main_info->bitrate, + main_info->stream.samplerate, main_info->stream.channels); + playback->set_pb_ready(playback); - /* - * Try to decode a single frame of audio - */ - if (FALSE == FLAC__stream_decoder_process_single(main_decoder)) { - /* - * Something went wrong - */ - _ERROR("Error while decoding!"); - break; - } + stream_info.samplerate = main_info->stream.samplerate; + stream_info.channels = main_info->stream.channels; + main_info->metadata_changed = FALSE; - /* - * Maybe the metadata changed midstream. Check. - */ + playback->set_gain_from_playlist(playback); + + while (playback->playing) + { + if (stop_time >= 0 && playback->output->written_time () >= stop_time) + goto DRAIN; + + /* Try to decode a single frame of audio */ + if (FLAC__stream_decoder_process_single(main_decoder) == FALSE) + { + ERROR("Error while decoding!\n"); + goto CLEANUP; + } - if (main_info->metadata_changed) { - /* - * Samplerate and channels are important - */ - if (stream_info.samplerate != main_info->stream.samplerate) { - _ERROR("Samplerate changed midstream (now: %d, was: %d). This is not supported yet.", + /* Maybe the metadata changed midstream. Check. */ + if (main_info->metadata_changed) + { + /* Samplerate and channels are important */ + if (stream_info.samplerate != main_info->stream.samplerate) + { + ERROR("Samplerate changed midstream (now: %d, was: %d). This is not supported yet.\n", main_info->stream.samplerate, stream_info.samplerate); - break; + goto CLEANUP; } - if (stream_info.channels != main_info->stream.channels) { - _ERROR("Number of channels changed midstream (now: %d, was: %d). This is not supported yet.", + if (stream_info.channels != main_info->stream.channels) + { + ERROR("Number of channels changed midstream (now: %d, was: %d). This is not supported yet.\n", main_info->stream.channels, stream_info.channels); - break; + goto CLEANUP; } main_info->metadata_changed = FALSE; } - /* - * Compare the frame metadata to the current stream metadata - */ - if (main_info->stream.samplerate != main_info->frame.samplerate) { - _ERROR("Frame samplerate mismatch (stream: %d, frame: %d)!", + /* Compare the frame metadata to the current stream metadata */ + if (main_info->stream.samplerate != main_info->frame.samplerate) + { + ERROR("Frame samplerate mismatch (stream: %d, frame: %d)!\n", main_info->stream.samplerate, main_info->frame.samplerate); - break; + goto CLEANUP; } - if (main_info->stream.channels != main_info->frame.channels) { - _ERROR("Frame channel mismatch (stream: %d, frame: %d)!", + if (main_info->stream.channels != main_info->frame.channels) + { + ERROR("Frame channel mismatch (stream: %d, frame: %d)!\n", main_info->stream.channels, main_info->frame.channels); - break; + goto CLEANUP; } g_mutex_lock(seek_mutex); if (seek_value >= 0) { - playback->output->flush(1000 * seek_value); - FLAC__stream_decoder_seek_absolute(main_decoder, (long long) seek_value * main_info->stream.samplerate); + playback->output->flush (seek_value); + FLAC__stream_decoder_seek_absolute (main_decoder, (gint64) + seek_value * main_info->stream.samplerate / 1000); seek_value = -1; g_cond_signal(seek_cond); } - if (pause_flag != paused) - { - playback->output->pause(pause_flag); - paused = pause_flag; - g_cond_signal(seek_cond); - } - - if (paused) - { - g_cond_wait(seek_cond, seek_mutex); - g_mutex_unlock(seek_mutex); - continue; - } - g_mutex_unlock(seek_mutex); /* * If the frame decoded was an audio frame we now - * have data in info->output_buffer + * have data in main_info->output_buffer * * The data in this buffer is in 32 bit wide samples, even if the * real sample width is smaller. It has to be converted before @@ -399,109 +329,62 @@ static gpointer flac_play_loop(gpointer arg) read_pointer = main_info->output_buffer; elements_left = main_info->buffer_used; - while ((TRUE == playback->playing) && (0 != elements_left)) { + while (playback->playing && elements_left != 0) + { + if (stop_time >= 0 && playback->output->written_time () >= stop_time) + goto DRAIN; sample_count = MIN(OUTPUT_BLOCK_SIZE, elements_left); squeeze_audio(read_pointer, play_buffer, sample_count, main_info->stream.bits_per_sample); - _DEBUG("Copying %d samples to output plugin", sample_count); - playback->output->write_audio(play_buffer, sample_count * SAMPLE_SIZE(main_info->stream.bits_per_sample)); read_pointer += sample_count; elements_left -= sample_count; - - _DEBUG("%d elements left to be output", elements_left); } - /* - * Clear the buffer. - */ + /* Clear the buffer. */ main_info->write_pointer = main_info->output_buffer; main_info->buffer_free = BUFFER_SIZE_SAMP; main_info->buffer_used = 0; + /* Have we reached the end of the stream? */ + if (elements_left == 0 && + FLAC__stream_decoder_get_state(main_decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) + { + /* Yes. Drain the output buffer and stop playing. */ + AUDDBG("End of stream reached, draining output buffer\n"); - /* - * Have we reached the end of the stream? - */ - state = FLAC__stream_decoder_get_state(main_decoder); - if (0 == elements_left && (FLAC__STREAM_DECODER_END_OF_STREAM == state)) { - /* - * Yes. Drain the output buffer and stop playing. - */ - - _DEBUG("End of stream reached, draining output buffer"); - - while (playback->output->buffer_playing() && playback->playing == TRUE) { - g_usleep(40000); - } +DRAIN: + while (playback->output->buffer_playing() && playback->playing) + g_usleep(20000); - playback->playing = FALSE; + goto CLEANUP; } } - /* - * Clean up a bit - */ +CLEANUP: + g_mutex_lock(seek_mutex); playback->playing = FALSE; - _DEBUG("Closing audio device"); - playback->output->close_audio(); - _DEBUG("Audio device closed"); - - g_free(play_buffer); - reset_info(main_info, TRUE); - - if (FALSE == FLAC__stream_decoder_flush(main_decoder)) { - _ERROR("Could not flush decoder state!"); - } - - _LEAVE NULL; -} - -/* --- */ - -void flac_play_file(InputPlayback *playback) -{ - VFSFile *fd; - - _ENTER; - - if (!plugin_initialized) { - _ERROR("plugin not initialized!"); - _LEAVE; - } - - /* - * Open the file - */ - if (NULL == (fd = aud_vfs_fopen(playback->filename, "rb"))) { - _ERROR("Could not open file for reading! (%s)", playback->filename); - _LEAVE; - } + g_cond_signal(seek_cond); /* wake up any waiting request */ + g_mutex_unlock(seek_mutex); - if (FALSE == read_metadata(fd, main_decoder, main_info)) { - reset_info(main_info, TRUE); - _ERROR("Could not prepare file for playing!"); - _LEAVE; - } + AUDDBG("Closing audio device.\n"); + playback->output->close_audio(); + AUDDBG("Audio device closed.\n"); - seek_value = -1; - pause_flag = FALSE; - playback->playing = TRUE; + if (play_buffer) + g_free(play_buffer); - playback->set_params (playback, NULL, 0, main_info->bitrate, - main_info->stream.samplerate, main_info->stream.channels); - playback->set_pb_ready(playback); + reset_info(main_info); - flac_play_loop(playback); + if (FLAC__stream_decoder_flush(main_decoder) == FALSE) + ERROR("Could not flush decoder state!\n"); - _LEAVE; + return ! playback->error; } -/* --- */ - static void flac_stop(InputPlayback *playback) { g_mutex_lock(seek_mutex); @@ -509,42 +392,31 @@ static void flac_stop(InputPlayback *playback) if (playback->playing) { playback->playing = FALSE; + playback->output->abort_write(); g_cond_signal(seek_cond); - g_mutex_unlock(seek_mutex); - g_thread_join(playback->thread); - playback->thread = NULL; - - reset_info(main_info, TRUE); } - else - g_mutex_unlock (seek_mutex); -} -/* --- */ + g_mutex_unlock (seek_mutex); +} -static void flac_pause(InputPlayback *playback, gshort p) +static void flac_pause(InputPlayback *playback, gshort pause) { g_mutex_lock(seek_mutex); if (playback->playing) - { - pause_flag = p; - g_cond_signal(seek_cond); - g_cond_wait(seek_cond, seek_mutex); - } + playback->output->pause(pause); g_mutex_unlock(seek_mutex); } -/* --- */ - -static void flac_seek(InputPlayback *playback, gint time) +static void flac_seek (InputPlayback * playback, gulong time) { g_mutex_lock(seek_mutex); if (playback->playing) { seek_value = time; + playback->output->abort_write(); g_cond_signal(seek_cond); g_cond_wait(seek_cond, seek_mutex); } @@ -552,31 +424,26 @@ static void flac_seek(InputPlayback *playback, gint time) g_mutex_unlock(seek_mutex); } -/* --- */ - static Tuple *flac_probe_for_tuple(const gchar *filename, VFSFile *fd) { + AUDDBG("Probe for tuple.\n"); Tuple *tuple = NULL; - _ENTER; - - _DEBUG("Testing file: %s", filename); + g_mutex_lock(test_info->mutex); - INFO_LOCK(test_info); + test_info->fd = fd; - if (read_metadata(fd, test_decoder, test_info)) - tuple = get_tuple_from_file(filename, fd, test_info); + if (read_metadata(test_decoder, test_info)) + tuple = get_tuple_from_file(filename, test_info); else - _ERROR ("Could not read metadata tuple for file <%s>", filename); + ERROR("Could not read metadata tuple for file <%s>\n", filename); - reset_info(test_info, TRUE); - INFO_UNLOCK(test_info); + reset_info(test_info); + g_mutex_unlock(test_info->mutex); - _LEAVE tuple; + return tuple; } -/* --- */ - static void flac_aboutbox(void) { static GtkWidget* about_window; @@ -599,11 +466,12 @@ static void flac_aboutbox(void) g_free(about_text); } -static void insert_str_tuple_to_vc(FLAC__StreamMetadata *vc_block, Tuple *tuple, gint tuple_name, gchar *field_name) +static void insert_str_tuple_to_vc (FLAC__StreamMetadata * vc_block, + const Tuple * tuple, gint tuple_name, gchar * field_name) { FLAC__StreamMetadata_VorbisComment_Entry entry; gchar *str; - gchar *val = (gchar *) aud_tuple_get_string(tuple, tuple_name, NULL); + gchar *val = (gchar *) tuple_get_string(tuple, tuple_name, NULL); if (val == NULL) return; @@ -615,11 +483,12 @@ static void insert_str_tuple_to_vc(FLAC__StreamMetadata *vc_block, Tuple *tuple, g_free(str); } -static void insert_int_tuple_to_vc(FLAC__StreamMetadata *vc_block, Tuple *tuple, gint tuple_name, gchar *field_name) +static void insert_int_tuple_to_vc (FLAC__StreamMetadata * vc_block, + const Tuple * tuple, gint tuple_name, gchar * field_name) { FLAC__StreamMetadata_VorbisComment_Entry entry; gchar *str; - gint val = aud_tuple_get_int(tuple, tuple_name, NULL); + gint val = tuple_get_int(tuple, tuple_name, NULL); if (val <= 0) return; @@ -635,14 +504,19 @@ static void insert_int_tuple_to_vc(FLAC__StreamMetadata *vc_block, Tuple *tuple, g_free(str); } -gboolean -flac_update_song_tuple(Tuple *tuple, VFSFile *fd) +gboolean flac_update_song_tuple (const Tuple * tuple, VFSFile * fd) { + AUDDBG("Update song tuple.\n"); FLAC__Metadata_SimpleIterator *iter; FLAC__StreamMetadata *vc_block; - gchar *filename = g_filename_from_uri(fd->uri, NULL, NULL); + gchar *filename; FLAC__bool ret; + if (fd != NULL) + filename = g_filename_from_uri(fd->uri, NULL, NULL); + else + return FALSE; + iter = FLAC__metadata_simple_iterator_new(); g_return_val_if_fail(iter != NULL, FALSE); @@ -688,6 +562,58 @@ flac_update_song_tuple(Tuple *tuple, VFSFile *fd) return TRUE; } +static gboolean flac_get_image(const gchar *filename, VFSFile *fd, void **data, gint *length) +{ + AUDDBG("Probe for song image.\n"); + + FLAC__Metadata_SimpleIterator *iter; + FLAC__StreamMetadata *metadata = NULL; + FLAC__bool ret; + gboolean has_image = FALSE; + + if (fd != NULL) + filename = g_filename_from_uri(fd->uri, NULL, NULL); + else + return FALSE; + + iter = FLAC__metadata_simple_iterator_new(); + g_return_val_if_fail(iter != NULL, FALSE); + + ret = FLAC__metadata_simple_iterator_init(iter, filename, false, false); + + if (!ret) + goto CLEANUP; + + while (FLAC__metadata_simple_iterator_get_block_type(iter) != FLAC__METADATA_TYPE_PICTURE) + { + if (!FLAC__metadata_simple_iterator_next(iter)) + break; + } + + if (FLAC__metadata_simple_iterator_get_block_type(iter) == FLAC__METADATA_TYPE_PICTURE) + { + metadata = FLAC__metadata_simple_iterator_get_block(iter); + + if (metadata->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER) + { + AUDDBG("FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER found."); + + *data = g_memdup(metadata->data.picture.data, metadata->data.picture.data_length); + *length = (guint32) metadata->data.picture.data_length; + has_image = TRUE; + goto CLEANUP; + } + } + +CLEANUP: + FLAC__metadata_simple_iterator_delete(iter); + + if (metadata) + FLAC__metadata_object_delete(metadata); + + return has_image; +} + static gchar *flac_fmts[] = { "flac", "fla", NULL }; InputPlugin flac_ip = { @@ -695,14 +621,16 @@ InputPlugin flac_ip = { .init = flac_init, .cleanup = flac_cleanup, .about = flac_aboutbox, - .play_file = flac_play_file, + .play = flac_play, .stop = flac_stop, .pause = flac_pause, - .seek = flac_seek, + .mseek = flac_seek, .probe_for_tuple = flac_probe_for_tuple, .is_our_file_from_vfs = flac_is_our_fd, .vfs_extensions = flac_fmts, - .update_song_tuple = flac_update_song_tuple + .update_song_tuple = flac_update_song_tuple, + .get_song_image = flac_get_image, + .priority = 1 }; InputPlugin *flac_iplist[] = { &flac_ip, NULL }; diff --git a/src/flacng/seekable_stream_callbacks.c b/src/flacng/seekable_stream_callbacks.c index db9b056..7d7c561 100644 --- a/src/flacng/seekable_stream_callbacks.c +++ b/src/flacng/seekable_stream_callbacks.c @@ -20,198 +20,124 @@ #include <string.h> #include <FLAC/all.h> #include <glib.h> + +#include <audacious/debug.h> + #include "flacng.h" #include "tools.h" #include "seekable_stream_callbacks.h" -#include "debug.h" - -/* === */ -FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) { - - callback_info* info; - gint to_read; +FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) +{ + callback_info* info = (callback_info*) client_data; size_t read; - _ENTER; - - info = (callback_info*) client_data; - _DEBUG("Using callback_info %s", info->name); - - if (NULL == info->input_stream) { - _ERROR("Trying to read data from an uninitialized file!"); - _LEAVE FLAC__STREAM_DECODER_READ_STATUS_ABORT; - } - - if (0 <= info->read_max) { - to_read = MIN(*bytes, info->read_max); - _DEBUG("Reading restricted to %ld bytes", info->read_max); - } else { - to_read = *bytes; - } - - if (0 == to_read) { - _LEAVE FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; + if (info->fd == NULL) + { + ERROR("Trying to read data from an uninitialized file!\n"); + return FLAC__STREAM_DECODER_READ_STATUS_ABORT; } - read = aud_vfs_fread(buffer, 1, to_read, info->input_stream); + if (*bytes == 0) + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; - if ((0 < read) && (0 < info->read_max)) { - info->read_max -= read; - } - - _DEBUG("Wanted %d bytes, got %d bytes", *bytes, read); + read = vfs_fread(buffer, 1, *bytes, info->fd); *bytes = read; - switch(read) { + switch (read) + { case -1: - _ERROR("Error while reading from stream!"); - _LEAVE FLAC__STREAM_DECODER_READ_STATUS_ABORT; - break; + ERROR("Error while reading from stream!\n"); + return FLAC__STREAM_DECODER_READ_STATUS_ABORT; case 0: - _DEBUG("Stream reached EOF"); - _LEAVE FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; - break; + AUDDBG("Stream reached EOF\n"); + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; default: - _LEAVE FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; } } -/* --- */ - -FLAC__StreamDecoderSeekStatus seek_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data) { +FLAC__StreamDecoderSeekStatus seek_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 offset, void *client_data) +{ + callback_info *info = (callback_info*) client_data; - callback_info* info; - - _ENTER; - - info = (callback_info*) client_data; - _DEBUG("Using callback_info %s", info->name); - - _DEBUG("Seeking to %lld", absolute_byte_offset); - - if (0 != aud_vfs_fseek(info->input_stream, absolute_byte_offset, SEEK_SET)) { - _ERROR("Could not seek to %lld!", (long long)absolute_byte_offset); - _LEAVE FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; + if (vfs_fseek(info->fd, offset, SEEK_SET) != 0) + { + ERROR("Could not seek to %lld!\n", (long long)offset); + return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; } - _LEAVE FLAC__STREAM_DECODER_SEEK_STATUS_OK; + return FLAC__STREAM_DECODER_SEEK_STATUS_OK; } -/* --- */ - -FLAC__StreamDecoderTellStatus tell_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) { +FLAC__StreamDecoderTellStatus tell_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *offset, void *client_data) +{ + callback_info *info = (callback_info*) client_data; - callback_info* info; - glong position; - - _ENTER; - - info = (callback_info*) client_data; - _DEBUG("Using callback_info %s", info->name); - - if (-1 == (position = aud_vfs_ftell(info->input_stream))) { - _ERROR("Could not tell current position!"); - _LEAVE FLAC__STREAM_DECODER_TELL_STATUS_ERROR; + if ((*offset = vfs_ftell(info->fd)) == -1) + { + ERROR("Could not tell current position!\n"); + return FLAC__STREAM_DECODER_TELL_STATUS_ERROR; } - _DEBUG("Current position: %ld", position); + AUDDBG("Current position: %ld\n", *offset); - *absolute_byte_offset = position; - - _LEAVE FLAC__STREAM_DECODER_TELL_STATUS_OK; + return FLAC__STREAM_DECODER_TELL_STATUS_OK; } -/* --- */ - -FLAC__bool eof_callback(const FLAC__StreamDecoder *decoder, void *client_data) { - - callback_info* info; - gboolean eof; - - _ENTER; - - info = (callback_info*) client_data; - _DEBUG("Using callback_info %s", info->name); - - /* - * If we are testing a stream and use restricted reading, - * return EOF if we have exhausted our alotted reading - * quota - */ - if (0 == info->read_max) { - _DEBUG("read_max exhausted, faking EOF"); - _LEAVE TRUE; - } - - eof = aud_vfs_feof(info->input_stream); - - _LEAVE eof; +FLAC__bool eof_callback(const FLAC__StreamDecoder *decoder, void *client_data) +{ + callback_info *info = (callback_info*) client_data; + return vfs_feof(info->fd); } -/* --- */ - -FLAC__StreamDecoderLengthStatus length_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) { +FLAC__StreamDecoderLengthStatus length_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *length, void *client_data) +{ + callback_info *info = (callback_info*) client_data; - callback_info* info; - off_t size; - - _ENTER; - - info = (callback_info*) client_data; - _DEBUG("Using callback_info %s", info->name); - - if (-1 == (size = aud_vfs_fsize(info->input_stream))) { + if ((*length = vfs_fsize(info->fd)) == -1) + { /* * Could not get the stream size. This is not necessarily an * error, maybe the stream has no fixed size (think streaming * audio) */ - _DEBUG("Stream length unknown"); - *stream_length = 0; - _LEAVE FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED; + AUDDBG("Stream length is unknown.\n"); + *length = 0; + return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED; } - _DEBUG("Stream length is %ld bytes", size); - *stream_length = size; + AUDDBG("Stream length is %ld bytes\n", *length); - _LEAVE FLAC__STREAM_DECODER_LENGTH_STATUS_OK; + return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; } -/* --- */ - -FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) { - - glong i; - gshort j; - callback_info* info; - - _ENTER; - - info = (callback_info*) client_data; - _DEBUG("Using callback_info %s", info->name); - - _DEBUG("Frame decoded: %d samples per channel, %d channels, %d bps", - frame->header.blocksize, frame->header.channels, frame->header.bits_per_sample); +FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data) +{ + glong sample; + gshort channel; + callback_info *info = (callback_info*) client_data; /* * Check if there is more data decoded than we have space * for. This _should_ not happen given how our buffer is sized, * but you never know. */ - if (info->buffer_free < (frame->header.blocksize * frame->header.channels)) { - _ERROR("BUG! Too much data decoded from stream!"); - _LEAVE FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + if (info->buffer_free < (frame->header.blocksize * frame->header.channels)) + { + ERROR("BUG! Too much data decoded from stream!\n"); + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; } - if ((frame->header.bits_per_sample != 8) && - (frame->header.bits_per_sample != 16) && - (frame->header.bits_per_sample != 24) && - (frame->header.bits_per_sample != 32)) { - _ERROR("Unsupported bitrate found in stream: %d!", frame->header.bits_per_sample); - _LEAVE FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + if (frame->header.bits_per_sample != 8 && + frame->header.bits_per_sample != 16 && + frame->header.bits_per_sample != 24 && + frame->header.bits_per_sample != 32) + { + ERROR("Unsupported bitrate found in stream: %d!\n", frame->header.bits_per_sample); + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; } /* @@ -223,144 +149,107 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder info->frame.samplerate = frame->header.sample_rate; info->frame.bits_per_sample = frame->header.bits_per_sample; - for (i=0; i < frame->header.blocksize; i++) { - for (j=0; j < frame->header.channels; j++) { - *(info->write_pointer++) = buffer[j][i]; + for (sample = 0; sample < frame->header.blocksize; sample++) + { + for (channel = 0; channel < frame->header.channels; channel++) + { + *(info->write_pointer++) = buffer[channel][sample]; info->buffer_free -= 1; info->buffer_used += 1; } } - _DEBUG("free space in buffer after copying: %d samples", info->buffer_free); - - _LEAVE FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; } -/* --- */ - -void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) { - - callback_info* info = (callback_info*) client_data; - - _ENTER; - - _DEBUG("Using callback_info %s", info->name); - - if (!info->testing) { - _ERROR("FLAC decoder error callback was called: %d", status); - } else { - _DEBUG("FLAC decoder error callback was called: %d", status); - } - - _LEAVE; - +void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) +{ + ERROR("FLAC decoder error callback was called: %d\n", status); } -/* --- */ - -void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) { - - callback_info* info; +void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) +{ + callback_info *info = (callback_info*) client_data; gint i; - FLAC__StreamMetadata_VorbisComment_Entry* entry; - FLAC__StreamMetadata* metadata_copy; - gchar* key; - gchar* value; - int artist_offset; + FLAC__StreamMetadata *metadata_copy; + FLAC__StreamMetadata_VorbisComment_Entry *entry; + gchar *key; + gchar *value; + gsize size; - _ENTER; + switch (metadata->type) + { + case FLAC__METADATA_TYPE_STREAMINFO: + /* Basic stream information. Sample rate, channels and stuff */ + AUDDBG("FLAC__METADATA_TYPE_STREAMINFO found.\n"); - info = (callback_info*) client_data; - _DEBUG("Using callback_info %s", info->name); + info->stream.samples = metadata->data.stream_info.total_samples; + AUDDBG("total_samples=%lld\n", (long long) metadata->data.stream_info.total_samples); - /* - * We have found a metadata block. Enable unrestricted reading - */ - info->read_max = -1; + info->stream.bits_per_sample = metadata->data.stream_info.bits_per_sample; + AUDDBG("bits_per_sample=%d\n", metadata->data.stream_info.bits_per_sample); - if (FLAC__METADATA_TYPE_STREAMINFO == metadata->type) { - /* - * Basic stream information. Sample rate, channels and stuff - */ - _DEBUG("FLAC__METADATA_TYPE_STREAMINFO found"); - - info->stream.samples = metadata->data.stream_info.total_samples; - _DEBUG("total_samples=%lld", metadata->data.stream_info.total_samples); - info->stream.bits_per_sample = metadata->data.stream_info.bits_per_sample; - _DEBUG("bits_per_sample=%d", metadata->data.stream_info.bits_per_sample); - info->stream.channels = metadata->data.stream_info.channels; - _DEBUG("channels=%d", metadata->data.stream_info.channels); - info->stream.samplerate = metadata->data.stream_info.sample_rate; - _DEBUG("sample_rate=%d", metadata->data.stream_info.sample_rate); - - info->metadata_changed = TRUE; - } + info->stream.channels = metadata->data.stream_info.channels; + AUDDBG("channels=%d\n", metadata->data.stream_info.channels); - if (FLAC__METADATA_TYPE_VORBIS_COMMENT == metadata->type) { - /* - * We will possibly need to modify some of the entries - * in the metadata field, so we make a copy of it - * first. - * The original structure must not be modified. - */ - metadata_copy = FLAC__metadata_object_clone(metadata); + info->stream.samplerate = metadata->data.stream_info.sample_rate; + AUDDBG("sample_rate=%d\n", metadata->data.stream_info.sample_rate); - /* - * A vorbis type comment field. - */ - _DEBUG("FLAC__METADATA_TYPE_VORBIS_COMMENT found"); - _DEBUG("Vorbis comment contains %d fields", metadata_copy->data.vorbis_comment.num_comments); - _DEBUG("Vendor string: %s", metadata_copy->data.vorbis_comment.vendor_string.entry); + size = vfs_fsize(info->fd); - /* - * Find an ARTIST field - */ - if (0 <= (artist_offset = FLAC__metadata_object_vorbiscomment_find_entry_from(metadata_copy, 0, "ARTIST"))) { - _DEBUG("ARTIST field found @ %d: %s", artist_offset, - metadata_copy->data.vorbis_comment.comments[artist_offset].entry); - } + if (size == -1) + info->bitrate = 0; + else + info->bitrate = 8 * size * (gint64) info->stream.samplerate / info->stream.samples; + AUDDBG("bitrate=%d\n", info->bitrate); - /* - * Enumerate the comment entries - */ - entry = metadata_copy->data.vorbis_comment.comments; - for (i=0; i < metadata_copy->data.vorbis_comment.num_comments; i++,entry++) { - _DEBUG("Comment[%d]: %s", i, entry->entry); + info->metadata_changed = TRUE; + break; + case FLAC__METADATA_TYPE_VORBIS_COMMENT: /* - * Try and parse the comment. - * If FLAC__metadata_object_vorbiscomment_entry_to_name_value_pair() succeeds, - * it allocates memory for the key and value which we have to take - * care of. + * We will possibly need to modify some of the entries + * in the metadata field, so we make a copy of it + * first. + * The original structure must not be modified. */ - if (false == FLAC__metadata_object_vorbiscomment_entry_to_name_value_pair(*entry, &key, &value)) { - _DEBUG("Could not parse comment"); - } else { - _DEBUG("Key: <%s>, Value <%s>", key, value); - add_comment(info, key, value); - free(key); - free(value); + metadata_copy = FLAC__metadata_object_clone(metadata); + + /* A vorbis type comment field. */ + AUDDBG("FLAC__METADATA_TYPE_VORBIS_COMMENT found.\n"); + AUDDBG("Vorbis comment contains %d fields\n", metadata_copy->data.vorbis_comment.num_comments); + AUDDBG("Vendor string: %s\n", metadata_copy->data.vorbis_comment.vendor_string.entry); + + /* Enumerate the comment entries */ + entry = metadata_copy->data.vorbis_comment.comments; + + for (i = 0; i < metadata_copy->data.vorbis_comment.num_comments; i++, entry++) + { + /* + * Try and parse the comment. + * If FLAC__metadata_object_vorbiscomment_entry_to_name_value_pair() succeeds, + * it allocates memory for the key and value which we have to take + * care of. + */ + if (FLAC__metadata_object_vorbiscomment_entry_to_name_value_pair(*entry, &key, &value) == false) + AUDDBG("Could not parse comment\n"); + else + { + add_comment(info, key, value); + g_free(key); + g_free(value); + } } - } - /* - * Free our metadata copy - */ - FLAC__metadata_object_delete(metadata_copy); + /* Free our metadata copy */ + FLAC__metadata_object_delete(metadata_copy); - info->metadata_changed = TRUE; - } + info->metadata_changed = TRUE; + break; - if (FLAC__METADATA_TYPE_SEEKTABLE == metadata->type) { - /* - * We have found a seektable, which means that we can seek - * without telling FLAC the length of the file (which we can not - * do, since Audacious lacks the functions for that) - */ - _DEBUG("FLAC__METADATA_TYPE_SEEKTABLE found"); - info->stream.has_seektable = TRUE; + default: + break; } - - _LEAVE; + return; } diff --git a/src/flacng/tools.c b/src/flacng/tools.c index a575f19..56d6ff1 100644 --- a/src/flacng/tools.c +++ b/src/flacng/tools.c @@ -1,6 +1,8 @@ /* * A FLAC decoder plugin for the Audacious Media Player * Copyright (C) 2005 Ralf Ertzinger + * Copyright (C) 2010 John Lindgren + * Copyright (C) 2010 MichaÅ‚ Lipski <tallica@o2.pl> * * 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 @@ -19,79 +21,50 @@ #include <string.h> #include <strings.h> -#include "tools.h" -#include "debug.h" - -/* === */ - -callback_info* init_callback_info(gchar* name) { - callback_info* info; +#include <audacious/debug.h> - _ENTER; +#include "tools.h" - if (NULL == name) { - _ERROR("Can not allocate callback structure without a name"); - _LEAVE NULL; - } +callback_info *init_callback_info(void) +{ + callback_info *info; - if (NULL == (info = g_malloc0(sizeof(callback_info)))) { - _ERROR("Could not allocate memory for callback structure!"); - _LEAVE NULL; + if ((info = g_slice_new0(callback_info)) == NULL) + { + ERROR("Could not allocate memory for callback structure!"); + return NULL; } - if (NULL == (info->output_buffer = g_malloc(BUFFER_SIZE_BYTE))) { - _ERROR("Could not allocate memory for output buffer!"); - _LEAVE NULL; + if ((info->output_buffer = g_malloc0(BUFFER_SIZE_BYTE)) == NULL) + { + ERROR("Could not allocate memory for output buffer!"); + return NULL; } - /* - * We need to set this manually to NULL because - * reset_info will try to close the file pointed to - * by input_stream if it is non-NULL. - * Same for info->comment.x - */ - info->name = name; - reset_info(info, FALSE); + reset_info(info); info->mutex = g_mutex_new(); - _DEBUG("Playback buffer allocated for %d samples, %d bytes", BUFFER_SIZE_SAMP, BUFFER_SIZE_BYTE); + AUDDBG("Playback buffer allocated for %d samples, %d bytes\n", BUFFER_SIZE_SAMP, BUFFER_SIZE_BYTE); - _LEAVE info; + return info; } -/* --- */ - -void clean_callback_info(callback_info* info) +void clean_callback_info(callback_info *info) { g_mutex_free(info->mutex); g_free(info->output_buffer); - g_free(info); + g_slice_free(callback_info, info); } -/* --- */ - -void reset_info(callback_info* info, gboolean close_fd) { - - _ENTER; - - _DEBUG("Using callback_info %s", info->name); - - if (close_fd) { - info->input_stream = NULL; - } - - // memset(info->output_buffer, 0, BUFFER_SIZE * sizeof(int16_t)); +void reset_info(callback_info *info) +{ info->buffer_free = BUFFER_SIZE_SAMP; info->buffer_used = 0; info->write_pointer = info->output_buffer; - info->read_max = -1; - info->testing = FALSE; - /* - * Clear the stream and frame information - */ + /* Clear the stream and frame information */ memset(&(info->stream), 0, sizeof(info->stream)); memset(&(info->frame), 0, sizeof(info->frame)); @@ -104,7 +77,6 @@ void reset_info(callback_info* info, gboolean close_fd) { g_free(info->comment.date); memset(&(info->comment), 0, sizeof(info->comment)); - g_free(info->replaygain.ref_loud); g_free(info->replaygain.track_gain); g_free(info->replaygain.track_peak); g_free(info->replaygain.album_gain); @@ -112,246 +84,238 @@ void reset_info(callback_info* info, gboolean close_fd) { memset(&(info->replaygain), 0, sizeof(info->replaygain)); info->metadata_changed = FALSE; - - _LEAVE; } -/* --- */ - -static gint get_bitrate (VFSFile * handle, callback_info * info) +gboolean read_metadata(FLAC__StreamDecoder *decoder, callback_info *info) { - gsize size = aud_vfs_fsize (handle); - - if (size == -1) - return 0; - - return 8 * size * (gint64) info->stream.samplerate / info->stream.samples; -} - -gboolean read_metadata(VFSFile* fd, FLAC__StreamDecoder* decoder, callback_info* info) { - FLAC__StreamDecoderState ret; - _ENTER; - - _DEBUG("Using callback_info %s", info->name); + reset_info(info); - reset_info(info, FALSE); - - info->input_stream = fd; + /* Reset the decoder */ + if (FLAC__stream_decoder_reset(decoder) == false) + { + ERROR("Could not reset the decoder!\n"); + return FALSE; + } - /* - * Reset the decoder - */ - if (false == FLAC__stream_decoder_reset(decoder)) { - _ERROR("Could not reset the decoder!"); - _LEAVE FALSE; + /* Try to decode the metadata */ + if (FLAC__stream_decoder_process_until_end_of_metadata(decoder) == false) + { + ret = FLAC__stream_decoder_get_state(decoder); + AUDDBG("Could not read the metadata: %s(%d)!\n", + FLAC__StreamDecoderStateString[ret], ret); + reset_info(info); + return FALSE; } - /* - * Just scan the first 8k for the start of metadata - */ + return TRUE; +} - info->read_max = 8192; +static void parse_gain_text(const gchar *text, gint *value, gint *unit) +{ + gint sign = 1; - /* - * We are not sure if this is an actual flac file, so do not - * complain too much about errors in the stream - */ - info->testing = TRUE; + *value = 0; + *unit = 1; - /* - * Try to decode the metadata - */ - if (false == FLAC__stream_decoder_process_until_end_of_metadata(decoder)) { - ret = FLAC__stream_decoder_get_state(decoder); - _DEBUG("Could not read the metadata: %s(%d)!", - FLAC__StreamDecoderStateString[ret], ret); - /* Do not close the filehandle, it was passed to us */ - reset_info(info, FALSE); - _LEAVE FALSE; + if (*text == '-') + { + sign = -1; + text++; } - /* - * Seems to be a FLAC stream. Allow further reading - */ + while (*text >= '0' && *text <= '9') + { + *value = *value * 10 + (*text - '0'); + text++; + } - info->read_max = -1; - info->testing = FALSE; + if (*text == '.') + { + text++; - info->bitrate = get_bitrate (fd, info); + while (*text >= '0' && *text <= '9' && *value < G_MAXINT / 10) + { + *value = *value * 10 + (*text - '0'); + *unit = *unit * 10; + text++; + } + } - _LEAVE TRUE; + *value = *value * sign; } -/* --- */ - -Tuple* get_tuple_from_file(const gchar *filename, VFSFile *fd, callback_info *info) +static void set_gain_info(Tuple *tuple, gint field, gint unit_field, const gchar *text) { - Tuple *out; + gint value, unit; - _ENTER; + parse_gain_text(text, &value, &unit); - _DEBUG("Using callback_info %s", info->name); + if (tuple_get_value_type(tuple, unit_field, NULL) == TUPLE_INT) + value = value * (gint64) tuple_get_int(tuple, unit_field, NULL) / unit; + else + tuple_associate_int(tuple, unit_field, NULL, unit); - out = aud_tuple_new_from_filename(filename); + tuple_associate_int(tuple, field, NULL, value); +} - aud_tuple_associate_string(out, FIELD_CODEC, NULL, "Free Lossless Audio Codec (FLAC)"); - aud_tuple_associate_string(out, FIELD_QUALITY, NULL, "lossless"); +Tuple* get_tuple_from_file(const gchar *filename, callback_info *info) +{ + Tuple *tuple; - aud_tuple_associate_string(out, FIELD_ARTIST, NULL, info->comment.artist); - aud_tuple_associate_string(out, FIELD_TITLE, NULL, info->comment.title); - aud_tuple_associate_string(out, FIELD_ALBUM, NULL, info->comment.album); - aud_tuple_associate_string(out, FIELD_GENRE, NULL, info->comment.genre); - aud_tuple_associate_string(out, FIELD_COMMENT, NULL, info->comment.comment); + tuple = tuple_new_from_filename(filename); + + tuple_associate_string(tuple, FIELD_CODEC, NULL, "Free Lossless Audio Codec (FLAC)"); + tuple_associate_string(tuple, FIELD_QUALITY, NULL, "lossless"); + + tuple_associate_string(tuple, FIELD_ARTIST, NULL, info->comment.artist); + tuple_associate_string(tuple, FIELD_TITLE, NULL, info->comment.title); + tuple_associate_string(tuple, FIELD_ALBUM, NULL, info->comment.album); + tuple_associate_string(tuple, FIELD_GENRE, NULL, info->comment.genre); + tuple_associate_string(tuple, FIELD_COMMENT, NULL, info->comment.comment); if (info->comment.tracknumber != NULL) - aud_tuple_associate_int(out, FIELD_TRACK_NUMBER, NULL, atoi(info->comment.tracknumber)); + tuple_associate_int(tuple, FIELD_TRACK_NUMBER, NULL, atoi(info->comment.tracknumber)); if (info->comment.date != NULL) - aud_tuple_associate_int(out, FIELD_YEAR, NULL, atoi(info->comment.date)); - - /* - * Calculate the stream length (milliseconds) - */ - if (0 == info->stream.samplerate) { - _ERROR("Invalid sample rate for stream!"); - aud_tuple_associate_int(out, FIELD_LENGTH, NULL, -1); - } else { - aud_tuple_associate_int(out, FIELD_LENGTH, NULL, (info->stream.samples / info->stream.samplerate) * 1000); - _DEBUG("Stream length: %d seconds", aud_tuple_get_int(out, FIELD_LENGTH, NULL)); + tuple_associate_int(tuple, FIELD_YEAR, NULL, atoi(info->comment.date)); + + /* Calculate the stream length (milliseconds) */ + if (info->stream.samplerate == 0) + { + ERROR("Invalid sample rate for stream!\n"); + tuple_associate_int(tuple, FIELD_LENGTH, NULL, -1); + } + else + { + tuple_associate_int(tuple, FIELD_LENGTH, NULL, (info->stream.samples / info->stream.samplerate) * 1000); + AUDDBG("Stream length: %d seconds\n", tuple_get_int(tuple, FIELD_LENGTH, NULL)); } if (info->bitrate > 0) - aud_tuple_associate_int (out, FIELD_BITRATE, NULL, (info->bitrate + 500) - / 1000); + tuple_associate_int(tuple, FIELD_BITRATE, NULL, (info->bitrate + 500) / 1000); if (info->replaygain.has_rg) { if (info->replaygain.album_gain != NULL) - aud_tuple_associate_int (out, FIELD_GAIN_ALBUM_GAIN, NULL, atof - (info->replaygain.album_gain) * 100); + set_gain_info(tuple, FIELD_GAIN_ALBUM_GAIN, FIELD_GAIN_GAIN_UNIT, + info->replaygain.album_gain); if (info->replaygain.album_peak != NULL) - aud_tuple_associate_int (out, FIELD_GAIN_ALBUM_PEAK, NULL, atof - (info->replaygain.album_peak) * 100); + set_gain_info(tuple, FIELD_GAIN_ALBUM_PEAK, FIELD_GAIN_PEAK_UNIT, + info->replaygain.album_peak); if (info->replaygain.track_gain != NULL) - aud_tuple_associate_int (out, FIELD_GAIN_TRACK_GAIN, NULL, atof - (info->replaygain.track_gain) * 100); + set_gain_info(tuple, FIELD_GAIN_TRACK_GAIN, FIELD_GAIN_GAIN_UNIT, + info->replaygain.track_gain); if (info->replaygain.track_peak != NULL) - aud_tuple_associate_int (out, FIELD_GAIN_TRACK_PEAK, NULL, atof - (info->replaygain.track_peak) * 100); - - aud_tuple_associate_int(out, FIELD_GAIN_GAIN_UNIT, NULL, 100); - aud_tuple_associate_int(out, FIELD_GAIN_PEAK_UNIT, NULL, 100); + set_gain_info(tuple, FIELD_GAIN_TRACK_PEAK, FIELD_GAIN_PEAK_UNIT, + info->replaygain.track_peak); } - _DEBUG("Tuple created: [%p]", out); - - _LEAVE out; + return tuple; } -/* --- */ - -void add_comment(callback_info* info, gchar* key, gchar* value) { - - /* - * We are currently interested in comments of type - * - ARTIST - * - ALBUM - * - TITLE - * - TRACKNUMBER - * - * We have to create copies of the value string. - */ - - gchar** destination = NULL; +void add_comment(callback_info *info, gchar *key, gchar *value) +{ + gchar **destination = NULL; gboolean rg = FALSE; - _ENTER; - - _DEBUG("Using callback_info %s", info->name); - - if (0 == strcasecmp(key, "ARTIST")) { - _DEBUG("Found key ARTIST"); + if (strcasecmp(key, "ARTIST") == 0) + { + AUDDBG("Found key ARTIST <%s>\n", value); destination = &(info->comment.artist); } - if (0 == strcasecmp(key, "ALBUM")) { - _DEBUG("Found key ALBUM"); + if (strcasecmp(key, "ALBUM") == 0) + { + AUDDBG("Found key ALBUM <%s>\n", value); destination = &(info->comment.album); } - if (0 == strcasecmp(key, "TITLE")) { - _DEBUG("Found key TITLE"); + if (strcasecmp(key, "TITLE") == 0) + { + AUDDBG("Found key TITLE <%s>\n", value); destination = &(info->comment.title); } - if (0 == strcasecmp(key, "TRACKNUMBER")) { - _DEBUG("Found key TRACKNUMBER"); + if (strcasecmp(key, "TRACKNUMBER") == 0) + { + AUDDBG("Found key TRACKNUMBER <%s>\n", value); destination = &(info->comment.tracknumber); } - if (0 == strcasecmp(key, "COMMENT")) { - _DEBUG("Found key COMMENT"); + if (strcasecmp(key, "COMMENT") == 0) + { + AUDDBG("Found key COMMENT <%s>\n", value); destination = &(info->comment.comment); } - if (0 == strcasecmp(key, "REPLAYGAIN_REFERENCE_LOUDNESS")) { - _DEBUG("Found key REPLAYGAIN_REFERENCE_LOUDNESS"); + if (strcasecmp(key, "DATE") == 0) + { + AUDDBG("Found key DATE <%s>\n", value); + destination = &(info->comment.date); + } + + if (strcasecmp(key, "GENRE") == 0) + { + AUDDBG("Found key GENRE <%s>\n", value); + destination = &(info->comment.genre); + } + +#if 0 + if (strcasecmp(key, "REPLAYGAIN_REFERENCE_LOUDNESS") == 0) + { + AUDDBG("Found key REPLAYGAIN_REFERENCE_LOUDNESS <%s>\n", value); destination = &(info->replaygain.ref_loud); rg = TRUE; } +#endif - if (0 == strcasecmp(key, "REPLAYGAIN_TRACK_GAIN")) { - _DEBUG("Found key REPLAYGAIN_TRACK_GAIN"); + if (strcasecmp(key, "REPLAYGAIN_TRACK_GAIN") == 0) + { + AUDDBG("Found key REPLAYGAIN_TRACK_GAIN <%s>\n", value); destination = &(info->replaygain.track_gain); rg = TRUE; } - if (0 == strcasecmp(key, "REPLAYGAIN_TRACK_PEAK")) { - _DEBUG("Found key REPLAYGAIN_TRACK_PEAK"); + if (strcasecmp(key, "REPLAYGAIN_TRACK_PEAK") == 0) + { + AUDDBG("Found key REPLAYGAIN_TRACK_PEAK <%s>\n", value); destination = &(info->replaygain.track_peak); rg = TRUE; } - if (0 == strcasecmp(key, "REPLAYGAIN_ALBUM_GAIN")) { - _DEBUG("Found key REPLAYGAIN_ALBUM_GAIN"); + if (strcasecmp(key, "REPLAYGAIN_ALBUM_GAIN") == 0) + { + AUDDBG("Found key REPLAYGAIN_ALBUM_GAIN <%s>\n", value); destination = &(info->replaygain.album_gain); rg = TRUE; } - if (0 == strcasecmp(key, "REPLAYGAIN_ALBUM_PEAK")) { - _DEBUG("Found key REPLAYGAIN_ALBUM_PEAK"); + if (strcasecmp(key, "REPLAYGAIN_ALBUM_PEAK") == 0) + { + AUDDBG("Found key REPLAYGAIN_ALBUM_PEAK <%s>\n", value); destination = &(info->replaygain.album_peak); rg = TRUE; } - if (0 == strcasecmp(key, "DATE")) { - _DEBUG("Found key DATE"); - destination = &(info->comment.date); - } - - if (0 == strcasecmp(key, "GENRE")) { - _DEBUG("Found key GENRE"); - destination = &(info->comment.genre); - } - - if (NULL != destination) { + if (destination != NULL) + { g_free(*destination); - if (NULL == (*destination = g_strdup(value))) { - _ERROR("Could not allocate memory for comment!"); - _LEAVE; + if ((*destination = g_strdup(value)) == NULL) + { + ERROR("Could not allocate memory for comment!\n"); + return; } } - if (rg) { + if (rg) info->replaygain.has_rg = TRUE; - } - _LEAVE; + return; } diff --git a/src/flacng/tools.h b/src/flacng/tools.h index 17db455..5b668c2 100644 --- a/src/flacng/tools.h +++ b/src/flacng/tools.h @@ -23,27 +23,12 @@ #include <FLAC/all.h> #include "flacng.h" #include "flac_compat.h" -#include "debug.h" -#define INFO_LOCK(__info) \ - do { \ - _DEBUG("Trying to lock info %s", (__info)->name); \ - g_mutex_lock((__info)->mutex); \ - _DEBUG("Locked info %s", (__info)->name); \ - } while(0) - -#define INFO_UNLOCK(__info) \ - do { \ - _DEBUG("Unlocking info %s", (__info)->name); \ - g_mutex_unlock((__info)->mutex); \ - _DEBUG("Unlocked info %s", (__info)->name); \ - } while(0) - -callback_info* init_callback_info(gchar* name); +callback_info* init_callback_info(void); void clean_callback_info(callback_info* info); -void reset_info(callback_info* info, gboolean close_fd); -Tuple *get_tuple_from_file(const gchar *filename, VFSFile *fd, callback_info *info); +void reset_info(callback_info* info); +Tuple *get_tuple_from_file(const gchar *filename, callback_info *info); void add_comment(callback_info* info, gchar* key, gchar* value); -gboolean read_metadata(VFSFile* fd, FLAC__StreamDecoder* decoder, callback_info* info); +gboolean read_metadata(FLAC__StreamDecoder* decoder, callback_info* info); #endif diff --git a/src/gio/gio.c b/src/gio/gio.c index 96644cb..a79fd74 100644 --- a/src/gio/gio.c +++ b/src/gio/gio.c @@ -38,7 +38,7 @@ typedef struct { static GVfs *gvfs = NULL; VFSFile * -gio_aud_vfs_fopen_impl(const gchar *path, const gchar *mode) +gio_vfs_fopen_impl(const gchar *path, const gchar *mode) { VFSFile *file; VFSGIOHandle *handle; @@ -84,7 +84,7 @@ gio_aud_vfs_fopen_impl(const gchar *path, const gchar *mode) } gint -gio_aud_vfs_fclose_impl(VFSFile * file) +gio_vfs_fclose_impl(VFSFile * file) { gint ret = 0; @@ -109,7 +109,7 @@ gio_aud_vfs_fclose_impl(VFSFile * file) return ret; } -gint64 gio_aud_vfs_fread_impl (void * ptr, gint64 size, gint64 nmemb, VFSFile * +gint64 gio_vfs_fread_impl (void * ptr, gint64 size, gint64 nmemb, VFSFile * file) { VFSGIOHandle *handle; @@ -139,7 +139,7 @@ gint64 gio_aud_vfs_fread_impl (void * ptr, gint64 size, gint64 nmemb, VFSFile * return (size > 0) ? ret / size : 0; } -gint64 gio_aud_vfs_fwrite_impl (const void * ptr, gint64 size, gint64 nmemb, +gint64 gio_vfs_fwrite_impl (const void * ptr, gint64 size, gint64 nmemb, VFSFile * file) { VFSGIOHandle *handle; @@ -155,7 +155,7 @@ gint64 gio_aud_vfs_fwrite_impl (const void * ptr, gint64 size, gint64 nmemb, } gint -gio_aud_vfs_getc_impl(VFSFile *file) +gio_vfs_getc_impl(VFSFile *file) { guchar buf; VFSGIOHandle *handle; @@ -178,7 +178,7 @@ gio_aud_vfs_getc_impl(VFSFile *file) } gint -gio_aud_vfs_ungetc_impl(gint c, VFSFile * file) +gio_vfs_ungetc_impl(gint c, VFSFile * file) { VFSGIOHandle *handle; @@ -194,7 +194,7 @@ gio_aud_vfs_ungetc_impl(gint c, VFSFile * file) } gint -gio_aud_vfs_fseek_impl(VFSFile * file, +gio_vfs_fseek_impl(VFSFile * file, glong offset, gint whence) { @@ -232,7 +232,7 @@ gio_aud_vfs_fseek_impl(VFSFile * file, } void -gio_aud_vfs_rewind_impl(VFSFile * file) +gio_vfs_rewind_impl(VFSFile * file) { g_return_if_fail(file != NULL); @@ -240,7 +240,7 @@ gio_aud_vfs_rewind_impl(VFSFile * file) } glong -gio_aud_vfs_ftell_impl(VFSFile * file) +gio_vfs_ftell_impl(VFSFile * file) { VFSGIOHandle *handle; @@ -252,18 +252,18 @@ gio_aud_vfs_ftell_impl(VFSFile * file) return (glong) (g_seekable_tell(handle->seekable) - g_slist_length(handle->stream_stack)); } -gboolean gio_aud_vfs_feof_impl (VFSFile * file) +gboolean gio_vfs_feof_impl (VFSFile * file) { guchar test; - if (gio_aud_vfs_fread_impl (& test, 1, 1, file) < 1) + if (gio_vfs_fread_impl (& test, 1, 1, file) < 1) return TRUE; - gio_aud_vfs_ungetc_impl (test, file); + gio_vfs_ungetc_impl (test, file); return FALSE; } -gint gio_aud_vfs_ftruncate_impl (VFSFile * file, gint64 size) +gint gio_vfs_ftruncate_impl (VFSFile * file, gint64 size) { VFSGIOHandle *handle; @@ -275,7 +275,7 @@ gint gio_aud_vfs_ftruncate_impl (VFSFile * file, gint64 size) } off_t -gio_aud_vfs_fsize_impl(VFSFile * file) +gio_vfs_fsize_impl(VFSFile * file) { GFileInfo *info; VFSGIOHandle *handle; @@ -316,19 +316,19 @@ static void init(void) c = g_slice_new0(VFSConstructor); c->uri_id = g_strdup_printf("%s://", schemes[i]); - c->vfs_fopen_impl = gio_aud_vfs_fopen_impl; - c->vfs_fclose_impl = gio_aud_vfs_fclose_impl; - c->vfs_fread_impl = gio_aud_vfs_fread_impl; - c->vfs_fwrite_impl = gio_aud_vfs_fwrite_impl; - c->vfs_getc_impl = gio_aud_vfs_getc_impl; - c->vfs_ungetc_impl = gio_aud_vfs_ungetc_impl; - c->vfs_fseek_impl = gio_aud_vfs_fseek_impl; - c->vfs_rewind_impl = gio_aud_vfs_rewind_impl; - c->vfs_ftell_impl = gio_aud_vfs_ftell_impl; - c->vfs_feof_impl = gio_aud_vfs_feof_impl; - c->vfs_ftruncate_impl = gio_aud_vfs_ftruncate_impl; - c->vfs_fsize_impl = gio_aud_vfs_fsize_impl; - aud_vfs_register_transport(c); + c->vfs_fopen_impl = gio_vfs_fopen_impl; + c->vfs_fclose_impl = gio_vfs_fclose_impl; + c->vfs_fread_impl = gio_vfs_fread_impl; + c->vfs_fwrite_impl = gio_vfs_fwrite_impl; + c->vfs_getc_impl = gio_vfs_getc_impl; + c->vfs_ungetc_impl = gio_vfs_ungetc_impl; + c->vfs_fseek_impl = gio_vfs_fseek_impl; + c->vfs_rewind_impl = gio_vfs_rewind_impl; + c->vfs_ftell_impl = gio_vfs_ftell_impl; + c->vfs_feof_impl = gio_vfs_feof_impl; + c->vfs_ftruncate_impl = gio_vfs_ftruncate_impl; + c->vfs_fsize_impl = gio_vfs_fsize_impl; + vfs_register_transport(c); } } @@ -336,7 +336,7 @@ static void cleanup(void) { g_object_unref(gvfs); #if 0 - aud_vfs_unregister_transport(&file_const); + vfs_unregister_transport(&file_const); #endif } diff --git a/src/gnomeshortcuts/gnomeshortcuts.c b/src/gnomeshortcuts/gnomeshortcuts.c index 54867a7..6c3e786 100644 --- a/src/gnomeshortcuts/gnomeshortcuts.c +++ b/src/gnomeshortcuts/gnomeshortcuts.c @@ -28,9 +28,8 @@ #include <dbus/dbus-glib-bindings.h> #include <glib-object.h> +#include <audacious/drct.h> #include <audacious/plugin.h> -#include <audacious/auddrct.h> - #include <audacious/i18n.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> @@ -97,10 +96,10 @@ on_media_player_key_pressed (DBusGProxy *proxy, const gchar *application, const gboolean play, mute; /* playing or not */ - play = audacious_drct_is_playing (); + play = aud_drct_get_playing (); /* get current volume */ - audacious_drct_get_volume_main (¤t_volume); + aud_drct_get_volume_main (¤t_volume); old_volume = current_volume; if (current_volume) { @@ -117,10 +116,10 @@ on_media_player_key_pressed (DBusGProxy *proxy, const gchar *application, const if (!mute) { volume_static = current_volume; - audacious_drct_set_main_volume (0); + aud_drct_set_volume_main (0); mute = TRUE; } else { - audacious_drct_set_main_volume (volume_static); + aud_drct_set_volume_main (volume_static); mute = FALSE; } return; @@ -181,9 +180,9 @@ on_media_player_key_pressed (DBusGProxy *proxy, const gchar *application, const { if (!play) { - audacious_drct_play (); + aud_drct_play (); } else { - audacious_drct_pause (); + aud_drct_pause (); } return; } @@ -191,8 +190,8 @@ on_media_player_key_pressed (DBusGProxy *proxy, const gchar *application, const /* pause */ if (strcmp ("Pause", key) == 0) { - if (!play) audacious_drct_play (); - else audacious_drct_pause (); + if (!play) aud_drct_play (); + else aud_drct_pause (); return; } @@ -200,21 +199,21 @@ on_media_player_key_pressed (DBusGProxy *proxy, const gchar *application, const /* stop */ if (strcmp ("Stop", key) == 0) { - audacious_drct_stop (); + aud_drct_stop (); return; } /* prev track */ if (strcmp ("Previous", key) == 0) { - audacious_drct_playlist_prev (); + aud_drct_pl_prev (); return; } /* next track */ if (strcmp ("Next", key) == 0) { - audacious_drct_playlist_next (); + aud_drct_pl_next (); return; } } diff --git a/src/gntui/fileselector.c b/src/gntui/fileselector.c index b8ab068..5cf34c8 100644 --- a/src/gntui/fileselector.c +++ b/src/gntui/fileselector.c @@ -38,7 +38,7 @@ file_add_cb(GntWidget *widget, GntFileSel **selector) if (uri == NULL) return; - audacious_drct_pl_add_url_string (uri); + aud_drct_pl_add_url_string (uri); gnt_widget_destroy(GNT_WIDGET(*selector)); *selector = NULL; diff --git a/src/gntui/gntui.c b/src/gntui/gntui.c index 0790555..d9f3e8b 100644 --- a/src/gntui/gntui.c +++ b/src/gntui/gntui.c @@ -35,9 +35,9 @@ static gint update_song_timeout_source = 0; static gchar *playing_status() { - if (audacious_drct_get_playing()) + if (aud_drct_get_playing()) { - if (!audacious_drct_get_paused()) + if (!aud_drct_get_paused()) { return ("|>"); } @@ -85,7 +85,7 @@ static void fill_playlist() static gboolean update_song_time(gpointer data) { - gint time = audacious_drct_get_output_time() / 1000; + gint time = aud_drct_get_output_time() / 1000; gchar *text; text = g_strdup_printf("[%02i:%02i]", time / 60, time % 60); @@ -126,20 +126,20 @@ static gboolean mainwin_keypress_cb(GntWidget *widget, const char *text, gpointe switch (text[0]) { case 'z': - audacious_drct_pl_prev(); + aud_drct_pl_prev(); update_playback_title(); break; case 'x': - audacious_drct_play(); + aud_drct_play(); break; case 'c': - audacious_drct_pause(); + aud_drct_pause(); break; case 'v': - audacious_drct_stop(); + aud_drct_stop(); break; case 'b': - audacious_drct_pl_next(); + aud_drct_pl_next(); update_playback_title(); break; default: @@ -156,8 +156,8 @@ static gboolean playlist_keypress_cb(GntTree *widget, const gchar * text, gpoint aud_playlist_set_position(playlist, pos); - if (!audacious_drct_get_playing()) - audacious_drct_play(); + if (!aud_drct_get_playing()) + aud_drct_play(); return TRUE; } @@ -272,11 +272,11 @@ static gboolean ui_initialize(InterfaceCbs * cbs) gnt_register_action(_("Add Files"), add_files); gnt_register_action(_("Open Files"), open_files); - aud_hook_associate("title change", set_song_info, NULL); - aud_hook_associate("playback begin", ui_playback_begin, NULL); - aud_hook_associate("playback stop", ui_playback_stop, NULL); - aud_hook_associate("playback end", ui_playback_end, NULL); - aud_hook_associate("playlist update", ui_playlist_update, NULL); + hook_associate("title change", set_song_info, NULL); + hook_associate("playback begin", ui_playback_begin, NULL); + hook_associate("playback stop", ui_playback_stop, NULL); + hook_associate("playback end", ui_playback_end, NULL); + hook_associate("playlist update", ui_playlist_update, NULL); cbs->run_filebrowser = run_fileselector; cbs->hide_filebrowser = hide_fileselector; @@ -290,11 +290,11 @@ static gboolean ui_initialize(InterfaceCbs * cbs) static gboolean ui_finalize(void) { - aud_hook_dissociate("title change", set_song_info); - aud_hook_dissociate("playback begin", ui_playback_begin); - aud_hook_dissociate("playback stop", ui_playback_stop); - aud_hook_dissociate("playback end", ui_playback_end); - aud_hook_dissociate("playlist update", ui_playlist_update); + hook_dissociate("title change", set_song_info); + hook_dissociate("playback begin", ui_playback_begin); + hook_dissociate("playback stop", ui_playback_stop); + hook_dissociate("playback end", ui_playback_end); + hook_dissociate("playlist update", ui_playlist_update); if (update_song_timeout_source) { diff --git a/src/gtkui/Makefile b/src/gtkui/Makefile index 9626171..80ccce1 100644 --- a/src/gtkui/Makefile +++ b/src/gtkui/Makefile @@ -7,6 +7,7 @@ SRCS = gtkui_cfg.c \ ui_playlist_widget.c \ ui_playlist_model.c \ ui_playlist_notebook.c \ + ui_statusbar.c \ util.c \ playlist_util.c \ actions.c diff --git a/src/gtkui/actions-mainwin.h b/src/gtkui/actions-mainwin.h index b0d6787..c19699b 100644 --- a/src/gtkui/actions-mainwin.h +++ b/src/gtkui/actions-mainwin.h @@ -46,6 +46,7 @@ void action_show_playlist_editor(GtkToggleAction *); void action_view_playlist(GtkToggleAction *); void action_view_infoarea(GtkToggleAction *); void action_view_menu(GtkToggleAction *); +void action_view_statusbar(GtkToggleAction *); /* radio actions (one for each radio action group) */ void action_anafoff(GtkAction *, GtkRadioAction *); diff --git a/src/gtkui/actions-playlist.h b/src/gtkui/actions-playlist.h index 477be0a..2769f54 100644 --- a/src/gtkui/actions-playlist.h +++ b/src/gtkui/actions-playlist.h @@ -50,11 +50,9 @@ void action_playlist_copy(void); void action_playlist_cut(void); void action_playlist_paste(void); -/* void action_playlist_add_cd(void); - this is no longer needed, as the respective menu entry is added from within the cdaudio plugin */ void action_playlist_add_url(void); void action_playlist_add_files(void); -void action_playlist_randomize_list(void); void action_playlist_reverse_list(void); void action_playlist_sort_by_title(void); diff --git a/src/gtkui/actions.c b/src/gtkui/actions.c index 77acc6d..42c2967 100644 --- a/src/gtkui/actions.c +++ b/src/gtkui/actions.c @@ -47,7 +47,12 @@ #include <regex.h> #endif -#include <audacious/plugin.h> +#include <audacious/audconfig.h> +#include <audacious/drct.h> +#include <audacious/misc.h> +#include <audacious/playlist.h> +#include <libaudcore/audstrings.h> +#include <libaudcore/hook.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> @@ -56,11 +61,7 @@ #include "playlist_util.h" #include "gtkui_cfg.h" #include "ui_infoarea.h" - -extern GtkWidget *window; -extern GtkWidget *menu; -extern GtkWidget *playlist_box; -extern GtkWidget *infoarea; +#include "ui_statusbar.h" static GtkWidget *mainwin_jtt = NULL; @@ -91,7 +92,7 @@ void action_stop_after_current_song (GtkToggleAction * action) if (active != aud_cfg->stopaftersong) { aud_cfg->stopaftersong = active; - aud_hook_call ("toggle stop after song", NULL); + hook_call ("toggle stop after song", NULL); } } @@ -105,10 +106,20 @@ void action_view_infoarea(GtkToggleAction *action) { config.infoarea_visible = gtk_toggle_action_get_active (action); - if (config.infoarea_visible) + if (config.infoarea_visible && ! infoarea) + { + infoarea = ui_infoarea_new (); + gtk_box_pack_end ((GtkBox *) vbox, infoarea, FALSE, FALSE, 0); + gtk_box_reorder_child(GTK_BOX(vbox), infoarea, -1); + gtk_widget_show (infoarea); - else - gtk_widget_hide (infoarea); + } + + if (! config.infoarea_visible && infoarea) + { + gtk_widget_destroy (infoarea); + infoarea = NULL; + } setup_panes (); } @@ -125,6 +136,30 @@ void action_view_menu(GtkToggleAction *action) setup_panes (); } +void action_view_statusbar(GtkToggleAction *action) +{ + config.statusbar_visible = gtk_toggle_action_get_active(action); + + if (config.statusbar_visible && !statusbar) + { + statusbar = ui_statusbar_new(); + gtk_box_pack_end(GTK_BOX(vbox), statusbar, FALSE, FALSE, 3); + + if (infoarea != NULL) + gtk_box_reorder_child(GTK_BOX(vbox), infoarea, -1); + + gtk_widget_show_all(statusbar); + } + + if (!config.statusbar_visible && statusbar) + { + gtk_widget_destroy(statusbar); + statusbar = NULL; + } + + setup_panes(); +} + /* actionentries actions */ void action_about_audacious(void) @@ -139,29 +174,29 @@ void action_play_file(void) void action_play_location(void) { - audgui_show_add_url_window(); + audgui_show_add_url_window (TRUE); } void action_ab_set(void) { - if (audacious_drct_get_length() > 0) + if (aud_drct_get_length() > 0) { if (ab_position_a == -1) { - ab_position_a = audacious_drct_get_time(); + ab_position_a = aud_drct_get_time(); ab_position_b = -1; /* info-text: Loop-Point A position set */ } else if (ab_position_b == -1) { - int time = audacious_drct_get_time(); + int time = aud_drct_get_time(); if (time > ab_position_a) ab_position_b = time; /* release info text */ } else { - ab_position_a = audacious_drct_get_time(); + ab_position_a = aud_drct_get_time(); ab_position_b = -1; /* info-text: Loop-Point A position reset */ } @@ -187,7 +222,7 @@ void action_jump_to_file(void) void action_jump_to_playlist_start(void) { - audacious_drct_pl_set_pos(0); + aud_drct_pl_set_pos(0); } static void mainwin_jump_to_time_cb(GtkWidget * widget, GtkWidget * entry) @@ -204,7 +239,7 @@ static void mainwin_jump_to_time_cb(GtkWidget * widget, GtkWidget * entry) else return; - audacious_drct_seek(time); + aud_drct_seek(time); gtk_widget_destroy(mainwin_jtt); } @@ -217,7 +252,7 @@ void mainwin_jump_to_time(void) guint tindex; gchar time_str[10]; - if (!audacious_drct_get_playing()) + if (!aud_drct_get_playing()) { dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("Can't jump to time when no track is being played.\n")); gtk_dialog_run(GTK_DIALOG(dialog)); @@ -286,7 +321,7 @@ void mainwin_jump_to_time(void) gtk_container_add(GTK_CONTAINER(bbox), jump); g_signal_connect(jump, "clicked", G_CALLBACK(mainwin_jump_to_time_cb), time_entry); - tindex = audacious_drct_get_time() / 1000; + tindex = aud_drct_get_time() / 1000; g_snprintf(time_str, sizeof(time_str), "%u:%2.2u", tindex / 60, tindex % 60); gtk_entry_set_text(GTK_ENTRY(time_entry), time_str); @@ -305,32 +340,35 @@ void action_jump_to_time(void) void action_playback_next(void) { - audacious_drct_pl_next(); + aud_drct_pl_next(); } void action_playback_previous(void) { - audacious_drct_pl_prev(); + aud_drct_pl_prev(); } void action_playback_play(void) { if (ab_position_a != -1) - audacious_drct_seek(ab_position_a); - else if (audacious_drct_get_playing () && audacious_drct_get_paused ()) - audacious_drct_pause(); + aud_drct_seek(ab_position_a); + else if (aud_drct_get_playing () && aud_drct_get_paused ()) + aud_drct_pause(); else - audacious_drct_play(); + { + aud_playlist_set_playing (aud_playlist_get_active ()); + aud_drct_play(); + } } void action_playback_pause(void) { - audacious_drct_pause(); + aud_drct_pause(); } void action_playback_stop(void) { - audacious_drct_stop(); + aud_drct_stop(); } void action_preferences(void) @@ -340,7 +378,7 @@ void action_preferences(void) void action_quit(void) { - audacious_drct_quit(); + aud_drct_quit(); } void action_playlist_track_info(void) @@ -366,13 +404,17 @@ void action_playlist_track_info(void) void action_queue_toggle(void) { - gint playlist = aud_playlist_get_active(); - gint queued = aud_playlist_queue_count(playlist); + gint playlist = aud_playlist_get_active (); + gint focus = treeview_get_focus (playlist_get_treeview (playlist)); + gint at; + + if (focus < 0) + return; - if (queued == 0) - aud_playlist_queue_insert_selected(playlist, 0); + if ((at = aud_playlist_queue_find_entry (playlist, focus)) < 0) + aud_playlist_queue_insert (playlist, -1, focus); else - aud_playlist_queue_delete(playlist, 0, queued); + aud_playlist_queue_delete (playlist, at, 1); } void action_playlist_sort_by_track_number(void) @@ -445,11 +487,6 @@ void action_playlist_sort_selected_by_filename(void) aud_playlist_sort_selected_by_scheme(aud_playlist_get_active(), PLAYLIST_SORT_FILENAME); } -void action_playlist_randomize_list(void) -{ - aud_playlist_randomize(aud_playlist_get_active()); -} - void action_playlist_reverse_list(void) { aud_playlist_reverse(aud_playlist_get_active()); @@ -513,7 +550,7 @@ void action_playlist_add_files(void) void action_playlist_add_url(void) { - audgui_show_add_url_window(); + audgui_show_add_url_window (FALSE); } void action_playlist_new(void) @@ -543,30 +580,10 @@ void action_playlist_delete(void) audgui_confirm_playlist_delete (aud_playlist_get_active ()); } -#if 0 -static void on_static_toggle(GtkToggleButton * button, gpointer data) -{ - Playlist *playlist = aud_playlist_get_active(); - - playlist->attribute = gtk_toggle_button_get_active(button) ? playlist->attribute | PLAYLIST_STATIC : playlist->attribute & ~PLAYLIST_STATIC; -} - -static void on_relative_toggle(GtkToggleButton * button, gpointer data) -{ - Playlist *playlist = aud_playlist_get_active(); - - playlist->attribute = gtk_toggle_button_get_active(button) ? playlist->attribute | PLAYLIST_USE_RELATIVE : playlist->attribute & ~PLAYLIST_USE_RELATIVE; -} -#endif - static gchar *playlist_file_selection_save(const gchar * title, const gchar * default_filename) { GtkWidget *dialog; gchar *filename; -#if 0 - GtkWidget *hbox; - GtkWidget *toggle, *toggle2; -#endif g_return_val_if_fail(title != NULL, NULL); @@ -574,25 +591,6 @@ static gchar *playlist_file_selection_save(const gchar * title, const gchar * de gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), aud_cfg->playlist_path); gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), default_filename); -#if 0 - hbox = gtk_hbox_new(FALSE, 5); - - /* static playlist */ - toggle = gtk_check_button_new_with_label(_("Save as Static Playlist")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), (aud_playlist_get_active()->attribute & PLAYLIST_STATIC) ? TRUE : FALSE); - g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(on_static_toggle), dialog); - gtk_box_pack_start(GTK_BOX(hbox), toggle, FALSE, FALSE, 0); - - /* use relative path */ - toggle2 = gtk_check_button_new_with_label(_("Use Relative Path")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle2), (aud_playlist_get_active()->attribute & PLAYLIST_USE_RELATIVE) ? TRUE : FALSE); - g_signal_connect(G_OBJECT(toggle2), "toggled", G_CALLBACK(on_relative_toggle), dialog); - gtk_box_pack_start(GTK_BOX(hbox), toggle2, FALSE, FALSE, 0); - - gtk_widget_show_all(hbox); - gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(dialog), hbox); -#endif - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); else @@ -633,35 +631,9 @@ static gboolean show_playlist_overwrite_prompt(GtkWindow * parent, const gchar * return (result == GTK_RESPONSE_YES); } -static void show_playlist_save_format_error(GtkWindow * parent, const gchar * filename) -{ - const gchar *markup = N_("<b><big>Unable to save playlist.</big></b>\n\n" "Unknown file type for '%s'.\n"); - - GtkWidget *dialog; - - g_return_if_fail(GTK_IS_WINDOW(parent)); - g_return_if_fail(filename != NULL); - - dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(parent), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _(markup), filename); - - gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER); /* centering */ - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); -} - static void playlistwin_save_playlist(const gchar * filename) { - PlaylistContainer *plc; - gchar *ext = strrchr(filename, '.') + 1; - - plc = aud_playlist_container_find(ext); - if (plc == NULL) - { - show_playlist_save_format_error(NULL, filename); - return; - } - - aud_str_replace_in(&aud_cfg->playlist_path, g_path_get_dirname(filename)); + str_replace_in(&aud_cfg->playlist_path, g_path_get_dirname(filename)); if (g_file_test(filename, G_FILE_TEST_IS_REGULAR)) if (!show_playlist_overwrite_prompt(NULL, filename)) @@ -676,7 +648,8 @@ void action_playlist_save_list(void) const gchar *default_filename = aud_playlist_get_filename(aud_playlist_get_active()); gchar *dot = NULL, *basename = NULL; - gchar *filename = playlist_file_selection_save(_("Save Playlist"), default_filename); + gchar * filename = playlist_file_selection_save (_("Export Playlist"), + default_filename); if (filename) { @@ -712,7 +685,7 @@ static void playlistwin_load_playlist(const gchar * filename) g_return_if_fail(filename != NULL); - aud_str_replace_in(&aud_cfg->playlist_path, g_path_get_dirname(filename)); + str_replace_in(&aud_cfg->playlist_path, g_path_get_dirname(filename)); aud_playlist_entry_delete(playlist, 0, aud_playlist_entry_count(playlist)); aud_playlist_insert_playlist(playlist, 0, filename); @@ -747,7 +720,8 @@ static gchar *playlist_file_selection_load(const gchar * title, const gchar * de void action_playlist_load_list(void) { const gchar *default_filename = aud_playlist_get_filename(aud_playlist_get_active()); - gchar *filename = playlist_file_selection_load(_("Load Playlist"), default_filename); + gchar * filename = playlist_file_selection_load (_("Import Playlist"), + default_filename); if (filename) { @@ -794,7 +768,7 @@ void action_playlist_select_all(void) void action_playlist_save_all_playlists(void) { - aud_save_all_playlists(); + aud_save_playlists(); } void action_playlist_copy(void) diff --git a/src/gtkui/gtkui_cfg.c b/src/gtkui/gtkui_cfg.c index 3e8d003..42c08a2 100644 --- a/src/gtkui/gtkui_cfg.c +++ b/src/gtkui/gtkui_cfg.c @@ -17,6 +17,7 @@ * Audacious or using our public API to be a derived work. */ +#include <audacious/configdb.h> #include <audacious/plugin.h> #include "gtkui_cfg.h" @@ -37,6 +38,7 @@ gtkui_cfg_t gtkui_default_config = { .playlist_height = 0, .infoarea_visible = TRUE, .menu_visible = TRUE, + .statusbar_visible = TRUE, }; typedef struct gtkui_cfg_boolent_t @@ -53,6 +55,7 @@ static gtkui_cfg_boolent gtkui_boolents[] = { {"playlist_visible", &config.playlist_visible, TRUE}, {"infoarea_visible", &config.infoarea_visible, TRUE}, {"menu_visible", &config.menu_visible, TRUE}, + {"statusbar_visible", &config.statusbar_visible, TRUE}, }; static gint ncfgbent = G_N_ELEMENTS(gtkui_boolents); diff --git a/src/gtkui/gtkui_cfg.h b/src/gtkui/gtkui_cfg.h index 6cf56db..b2a2a21 100644 --- a/src/gtkui/gtkui_cfg.h +++ b/src/gtkui/gtkui_cfg.h @@ -48,6 +48,7 @@ typedef struct gboolean multi_column_view; gboolean infoarea_visible; gboolean menu_visible; + gboolean statusbar_visible; } gtkui_cfg_t; extern gtkui_cfg_t config; diff --git a/src/gtkui/playlist_util.c b/src/gtkui/playlist_util.c index e083ab3..ae162c3 100644 --- a/src/gtkui/playlist_util.c +++ b/src/gtkui/playlist_util.c @@ -24,6 +24,7 @@ #include <stdlib.h> #include <string.h> +#include <audacious/playlist.h> #include <audacious/plugin.h> #include <libaudgui/libaudgui.h> @@ -124,7 +125,8 @@ void playlist_scroll_to_row (GtkTreeView * tree, gint row) UiPlaylistModel * model = (UiPlaylistModel *) gtk_tree_view_get_model (tree); aud_playlist_select_all (model->playlist, FALSE); - aud_playlist_entry_set_selected (model->playlist, row, TRUE); + if (row >= 0) + aud_playlist_entry_set_selected (model->playlist, row, TRUE); treeview_set_focus (tree, row); } @@ -254,7 +256,7 @@ void playlist_selected_to_indexes (gint list, struct index * * namesp, index_append (* namesp, g_strdup (aud_playlist_entry_get_filename (list, count))); - if ((tuple = aud_playlist_entry_get_tuple (list, count))) + if ((tuple = aud_playlist_entry_get_tuple (list, count, FALSE))) mowgli_object_ref ((Tuple *) tuple); index_append (* tuplesp, (Tuple *) tuple); diff --git a/src/gtkui/ui/player.ui b/src/gtkui/ui/player.ui index ec3d338..168979a 100644 --- a/src/gtkui/ui/player.ui +++ b/src/gtkui/ui/player.ui @@ -38,9 +38,6 @@ <menuitem action="playlist new" /> <menuitem action="playlist delete" /> <separator /> - <menuitem action="playlist select next" /> - <menuitem action="playlist select previous" /> - <separator /> <menuitem action="playlist load" /> <menuitem action="playlist save" /> <menuitem action="playlist save all" /> @@ -58,9 +55,12 @@ </menu> <menu action="view"> + <menuitem action="iface menu" /> + <separator /> <menuitem action="view menu" /> <menuitem action="view playlists" /> <menuitem action="view infoarea" /> + <menuitem action="view statusbar" /> </menu> <menu action="help"> diff --git a/src/gtkui/ui_gtk.c b/src/gtkui/ui_gtk.c index 1ddede7..bd4a1ca 100644 --- a/src/gtkui/ui_gtk.c +++ b/src/gtkui/ui_gtk.c @@ -21,7 +21,13 @@ #include <gtk/gtk.h> #include <gdk/gdkkeysyms.h> +#include <audacious/audconfig.h> +#include <audacious/debug.h> +#include <audacious/drct.h> +#include <audacious/interface.h> +#include <audacious/playlist.h> #include <audacious/plugin.h> +#include <libaudcore/hook.h> #include <libaudgui/libaudgui.h> #include "config.h" @@ -30,6 +36,7 @@ #include "ui_playlist_notebook.h" #include "ui_manager.h" #include "ui_infoarea.h" +#include "ui_statusbar.h" #include "playlist_util.h" #include "actions-mainwin.h" #include "actions-playlist.h" @@ -42,8 +49,10 @@ static GtkWidget *volume; static GtkWidget *visualizer = NULL; GtkWidget *playlist_box; GtkWidget *window; /* the main window */ +GtkWidget *vbox; /* the main vertical box */ GtkWidget *menu; -GtkWidget *infoarea; +GtkWidget *infoarea = NULL; +GtkWidget *statusbar = NULL; static gulong slider_change_handler_id; static gboolean slider_is_moving = FALSE; @@ -60,7 +69,7 @@ static gboolean _ui_finalize(void); Interface gtkui_interface = { .id = "gtkui", - .desc = N_("GTK Foobar-like Interface"), + .desc = N_("GTK Interface"), .init = _ui_initialize, .fini = _ui_finalize, }; @@ -199,7 +208,7 @@ static void ui_stop_gtk_plugin(GtkWidget *parent) static gboolean window_delete() { - audacious_drct_quit (); + aud_drct_quit (); return TRUE; } @@ -241,32 +250,32 @@ static void button_add_pressed() static void button_play_pressed() { - audacious_drct_play(); + aud_drct_play(); } static void button_pause_pressed() { - audacious_drct_pause(); + aud_drct_pause(); } static void button_stop_pressed() { - audacious_drct_stop(); + aud_drct_stop(); } static void button_previous_pressed() { - audacious_drct_pl_prev(); + aud_drct_pl_prev(); } static void button_next_pressed() { - audacious_drct_pl_next(); + aud_drct_pl_next(); } static void ui_set_song_info(void *unused, void *another) { - gchar *title = aud_playback_get_title(); + gchar *title = aud_drct_get_title(); gchar *title_s = g_strdup_printf("%s - Audacious", title); gtk_window_set_title(GTK_WINDOW(window), title_s); @@ -344,7 +353,7 @@ static void ui_show_error(const gchar * markup) static void ui_update_time_info(gint time) { gchar text[128]; - gint length = audacious_drct_get_length(); + gint length = aud_drct_get_length(); time /= 1000; length /= 1000; @@ -355,7 +364,7 @@ static void ui_update_time_info(gint time) static gboolean ui_update_song_info(gpointer hook_data, gpointer user_data) { - if (!audacious_drct_get_playing()) + if (!aud_drct_get_playing()) { if (GTK_IS_WIDGET(slider)) gtk_range_set_value(GTK_RANGE(slider), 0.0); @@ -365,7 +374,7 @@ static gboolean ui_update_song_info(gpointer hook_data, gpointer user_data) if (slider_is_moving) return TRUE; - gint time = audacious_drct_get_time(); + gint time = aud_drct_get_time(); if (!g_signal_handler_is_connected(slider, slider_change_handler_id)) return TRUE; @@ -389,16 +398,8 @@ static void ui_clear_song_info() static gboolean ui_slider_value_changed_cb(GtkRange * range, gpointer user_data) { - gint seek_; - - seek_ = gtk_range_get_value(range); - - /* XXX: work around a horrible bug in playback_seek(), also - we should do mseek here. --nenolod */ - audacious_drct_seek(seek_ != 0 ? seek_ : 1); - + aud_drct_seek (gtk_range_get_value (range)); slider_is_moving = FALSE; - return TRUE; } @@ -435,7 +436,7 @@ static gboolean ui_slider_button_release_cb(GtkWidget * widget, GdkEventButton * static gboolean ui_volume_value_changed_cb(GtkButton * button, gdouble volume, gpointer user_data) { - audacious_drct_set_volume((gint) volume, (gint) volume); + aud_drct_set_volume((gint) volume, (gint) volume); return TRUE; } @@ -458,7 +459,7 @@ static gboolean ui_volume_slider_update(gpointer data) if (volume_slider_is_moving || data == NULL) return TRUE; - audacious_drct_get_volume_main(&volume); + aud_drct_get_volume_main(&volume); if (last_volume == volume) return TRUE; @@ -502,7 +503,7 @@ static void ui_playback_begin(gpointer hook_data, gpointer user_data) /* update song info 4 times a second */ update_song_timeout_source = g_timeout_add(250, (GSourceFunc) ui_update_song_info, NULL); - set_slider_length (audacious_drct_get_length ()); + set_slider_length (aud_drct_get_length ()); } static void ui_playback_stop(gpointer hook_data, gpointer user_data) @@ -582,21 +583,23 @@ static gboolean ui_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer case GDK_Left: case GDK_KP_Left: case GDK_KP_7: - audacious_drct_seek(audacious_drct_get_time() - 5000); + if (aud_drct_get_playing ()) + aud_drct_seek (aud_drct_get_time () - 5000); break; case GDK_Right: case GDK_KP_Right: case GDK_KP_9: - audacious_drct_seek(audacious_drct_get_time() + 5000); + if (aud_drct_get_playing ()) + aud_drct_seek (aud_drct_get_time () + 5000); break; case GDK_KP_4: - audacious_drct_pl_prev(); + aud_drct_pl_prev(); break; case GDK_KP_6: - audacious_drct_pl_next(); + aud_drct_pl_next(); break; case GDK_KP_Insert: @@ -604,21 +607,22 @@ static gboolean ui_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer break; case GDK_space: - if (audacious_drct_get_playing()) - audacious_drct_pause(); + if (aud_drct_get_playing()) + aud_drct_pause(); else - audacious_drct_play(); + aud_drct_play(); break; case GDK_Escape: - if (ui_playlist_notebook_tab_title_editing == NULL) - { - gint playing = aud_playlist_get_playing(); - gtk_notebook_set_current_page(UI_PLAYLIST_NOTEBOOK, playing); - playlist_scroll_to_row(playlist_get_playing_treeview(), - aud_playlist_get_position(playing)); - break; - } + ; /* bleah, label must come before statement */ + gint list = aud_playlist_get_active (); + playlist_scroll_to_row (playlist_get_treeview (list), + aud_playlist_get_position (list)); + + if (ui_playlist_notebook_tab_title_editing != NULL) + return FALSE; + + break; case GDK_Tab: action_playlist_next(); @@ -658,39 +662,39 @@ static void stop_after_song_toggled (void * data, void * user) static void ui_hooks_associate(void) { - aud_hook_associate("title change", ui_set_song_info, NULL); - aud_hook_associate("playback seek", (HookFunction) ui_update_song_info, NULL); - aud_hook_associate("playback begin", ui_playback_begin, NULL); - aud_hook_associate("playback stop", ui_playback_stop, NULL); - aud_hook_associate("playback end", ui_playback_end, NULL); - aud_hook_associate("playlist insert", ui_playlist_created, NULL); - aud_hook_associate("playlist delete", ui_playlist_destroyed, NULL); - aud_hook_associate("mainwin show", ui_mainwin_toggle_visibility, NULL); - aud_hook_associate("playlist update", ui_playlist_notebook_update, NULL); - aud_hook_associate("toggle stop after song", stop_after_song_toggled, NULL); + hook_associate("title change", ui_set_song_info, NULL); + hook_associate("playback seek", (HookFunction) ui_update_song_info, NULL); + hook_associate("playback begin", ui_playback_begin, NULL); + hook_associate("playback stop", ui_playback_stop, NULL); + hook_associate("playback end", ui_playback_end, NULL); + hook_associate("playlist insert", ui_playlist_created, NULL); + hook_associate("playlist delete", ui_playlist_destroyed, NULL); + hook_associate("mainwin show", ui_mainwin_toggle_visibility, NULL); + hook_associate("playlist update", ui_playlist_notebook_update, NULL); + hook_associate("toggle stop after song", stop_after_song_toggled, NULL); } static void ui_hooks_disassociate(void) { - aud_hook_dissociate("title change", ui_set_song_info); - aud_hook_dissociate("playback seek", (HookFunction) ui_update_song_info); - aud_hook_dissociate("playback begin", ui_playback_begin); - aud_hook_dissociate("playback stop", ui_playback_stop); - aud_hook_dissociate("playback end", ui_playback_end); - aud_hook_dissociate("playlist insert", ui_playlist_created); - aud_hook_dissociate("playlist delete", ui_playlist_destroyed); - aud_hook_dissociate("mainwin show", ui_mainwin_toggle_visibility); - aud_hook_dissociate("playlist update", ui_playlist_notebook_update); - aud_hook_dissociate("toggle stop after song", stop_after_song_toggled); + hook_dissociate("title change", ui_set_song_info); + hook_dissociate("playback seek", (HookFunction) ui_update_song_info); + hook_dissociate("playback begin", ui_playback_begin); + hook_dissociate("playback stop", ui_playback_stop); + hook_dissociate("playback end", ui_playback_end); + hook_dissociate("playlist insert", ui_playlist_created); + hook_dissociate("playlist delete", ui_playlist_destroyed); + hook_dissociate("mainwin show", ui_mainwin_toggle_visibility); + hook_dissociate("playlist update", ui_playlist_notebook_update); + hook_dissociate("toggle stop after song", stop_after_song_toggled); } static gboolean _ui_initialize(InterfaceCbs * cbs) { - GtkWidget *vbox; /* the main vertical box */ GtkWidget *tophbox; /* box to contain toolbar and shbox */ GtkWidget *buttonbox; /* contains buttons like "open", "next" */ GtkWidget *shbox; /* box for volume control + slider + time combo --nenolod */ GtkWidget *button_open, *button_add, *button_play, *button_pause, *button_stop, *button_previous, *button_next; + GtkWidget *evbox; GtkAccelGroup *accel; gint lvol = 0, rvol = 0; /* Left and Right for the volume control */ @@ -741,8 +745,13 @@ static gboolean _ui_initialize(InterfaceCbs * cbs) gtk_box_pack_start(GTK_BOX(tophbox), buttonbox, FALSE, FALSE, 0); + /* The slider and time display are packed in an event box so that they can + * be redrawn separately as they are updated. */ + evbox = gtk_event_box_new (); + gtk_box_pack_start ((GtkBox *) tophbox, evbox, TRUE, TRUE, 0); + shbox = gtk_hbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(tophbox), shbox, TRUE, TRUE, 0); + gtk_container_add ((GtkContainer *) evbox, shbox); slider = gtk_hscale_new(NULL); gtk_scale_set_draw_value(GTK_SCALE(slider), FALSE); @@ -761,7 +770,7 @@ static gboolean _ui_initialize(InterfaceCbs * cbs) gtk_widget_set_can_focus(volume, FALSE); /* Set the default volume to the balance average. (I'll add balance control later) -Ryan */ - audacious_drct_get_volume(&lvol, &rvol); + aud_drct_get_volume(&lvol, &rvol); gtk_scale_button_set_value(GTK_SCALE_BUTTON(volume), (lvol + rvol) / 2); gtk_box_pack_start(GTK_BOX(shbox), volume, FALSE, FALSE, 0); @@ -770,7 +779,14 @@ static gboolean _ui_initialize(InterfaceCbs * cbs) /* Create playlist notebook */ ui_playlist_notebook_new (); - g_object_ref ((GObject *) UI_PLAYLIST_NOTEBOOK); + g_object_ref (G_OBJECT(UI_PLAYLIST_NOTEBOOK)); + + if (config.statusbar_visible) + { + AUDDBG("statusbar setup\n"); + statusbar = ui_statusbar_new(); + gtk_box_pack_end(GTK_BOX(vbox), statusbar, FALSE, FALSE, 3); + } if (config.vis_position == VIS_IN_TABS) { @@ -779,9 +795,12 @@ static gboolean _ui_initialize(InterfaceCbs * cbs) UI_PLAYLIST_NOTEBOOK, TRUE, TRUE, 0); } - AUDDBG("infoarea setup\n"); - infoarea = ui_infoarea_new(); - gtk_box_pack_end(GTK_BOX(vbox), infoarea, FALSE, FALSE, 0); + if (config.infoarea_visible) + { + AUDDBG ("infoarea setup\n"); + infoarea = ui_infoarea_new (); + gtk_box_pack_end (GTK_BOX(vbox), infoarea, FALSE, FALSE, 0); + } AUDDBG("hooks associate\n"); ui_hooks_associate(); @@ -807,15 +826,12 @@ static gboolean _ui_initialize(InterfaceCbs * cbs) if (!config.menu_visible) gtk_widget_hide(menu); - if (!config.infoarea_visible) - gtk_widget_hide(infoarea); - setup_panes (); if (config.player_visible) ui_mainwin_toggle_visibility(GINT_TO_POINTER(config.player_visible), NULL); - if (audacious_drct_get_playing()) + if (aud_drct_get_playing()) { ui_set_song_info(NULL, NULL); ui_playback_begin(NULL, NULL); @@ -827,6 +843,7 @@ static gboolean _ui_initialize(InterfaceCbs * cbs) check_set(toggleaction_group_others, "view menu", config.menu_visible); check_set(toggleaction_group_others, "view playlists", config.playlist_visible); check_set(toggleaction_group_others, "view infoarea", config.infoarea_visible); + check_set(toggleaction_group_others, "view statusbar", config.statusbar_visible); check_set(toggleaction_group_others, "playback repeat", aud_cfg->repeat); check_set(toggleaction_group_others, "playback shuffle", aud_cfg->shuffle); check_set(toggleaction_group_others, "playback no playlist advance", aud_cfg->no_playlist_advance); @@ -847,9 +864,6 @@ static gboolean _ui_initialize(InterfaceCbs * cbs) cbs->run_gtk_plugin = (void *) ui_run_gtk_plugin; cbs->stop_gtk_plugin = (void *) ui_stop_gtk_plugin; - AUDDBG("launch\n"); - gtk_main(); - return TRUE; } @@ -871,6 +885,11 @@ static gboolean _ui_finalize(void) gtkui_cfg_save(); gtkui_cfg_free(); ui_hooks_disassociate(); + + /* ui_manager_destroy() must be called to detach plugin services menus + * before any widget are destroyed. -jlindgren */ + ui_manager_destroy (); + g_object_unref ((GObject *) UI_PLAYLIST_NOTEBOOK); gtk_widget_destroy (window); return TRUE; diff --git a/src/gtkui/ui_gtk.h b/src/gtkui/ui_gtk.h index 4021e61..a8d74b2 100644 --- a/src/gtkui/ui_gtk.h +++ b/src/gtkui/ui_gtk.h @@ -24,6 +24,13 @@ extern gboolean multi_columns_view; extern Interface gtkui_interface; +extern GtkWidget *window; +extern GtkWidget *vbox; +extern GtkWidget *menu; +extern GtkWidget *playlist_box; +extern GtkWidget *infoarea; +extern GtkWidget *statusbar; + void setup_panes (void); void show_preferences_window(gboolean show); diff --git a/src/gtkui/ui_infoarea.c b/src/gtkui/ui_infoarea.c index 714bc62..22d8933 100644 --- a/src/gtkui/ui_infoarea.c +++ b/src/gtkui/ui_infoarea.c @@ -21,7 +21,11 @@ #include <glib/gi18n.h> #include <gtk/gtk.h> -#include <audacious/plugin.h> +#include <audacious/debug.h> +#include <audacious/drct.h> +#include <audacious/misc.h> +#include <audacious/playlist.h> +#include <libaudcore/hook.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> @@ -60,12 +64,11 @@ static void ui_infoarea_draw_visualizer (UIInfoArea * area); /****************************************************************************/ -static void -ui_infoarea_visualization_timeout(gpointer hook_data, UIInfoArea *area) +static void ui_infoarea_visualization_timeout (const VisNode * vis, UIInfoArea * + area) { const gfloat xscale[SPECT_BANDS + 1] = {0.00, 0.59, 1.52, 3.00, 5.36, 9.10, 15.0, 24.5, 39.4, 63.2, 101, 161, 256}; /* logarithmic scale - 1 */ - VisNode *vis = (VisNode*) hook_data; gint16 mono_freq[2][256]; aud_calc_mono_freq(mono_freq, vis->data, vis->nch); @@ -76,14 +79,21 @@ ui_infoarea_visualization_timeout(gpointer hook_data, UIInfoArea *area) gint b = floor (xscale[i + 1]); gint n = 0; - if (a > 0) - n += mono_freq[0][a - 1] * (a - xscale[i]); - for (; a < b; a ++) - n += mono_freq[0][a]; - if (b < 256) - n += mono_freq[0][b] * (xscale[i + 1] - b); - - n = 32 * log10 (n / 327.67); /* 40 dB range */ + if (b < a) + n += mono_freq[0][b] * (xscale[i + 1] - xscale[i]); + else + { + if (a > 0) + n += mono_freq[0][a - 1] * (a - xscale[i]); + for (; a < b; a ++) + n += mono_freq[0][a]; + if (b < 256) + n += mono_freq[0][b] * (xscale[i + 1] - b); + } + + /* 40 dB range */ + /* 0.00305 == 1 / 32767 * 10^(40/20) */ + n = 32 * log10 (n * 0.00305); n = CLAMP (n, 0, 64); area->visdata[i] = MAX (area->visdata[i] - 3, n); } @@ -98,7 +108,7 @@ ui_infoarea_visualization_timeout(gpointer hook_data, UIInfoArea *area) static void vis_clear_cb (void * hook_data, UIInfoArea * area) { - memset (area->visdata, 0, 20); + memset (area->visdata, 0, sizeof area->visdata); } /****************************************************************************/ @@ -138,24 +148,92 @@ static void ui_infoarea_draw_text (UIInfoArea * area, gint x, gint y, gint /****************************************************************************/ -static struct { - guint8 red; - guint8 green; - guint8 blue; -} colors[] = { - { 0xff, 0xb1, 0x6f }, - { 0xff, 0xc8, 0x7f }, - { 0xff, 0xcf, 0x7e }, - { 0xf6, 0xe6, 0x99 }, - { 0xf1, 0xfc, 0xd4 }, - { 0xbd, 0xd8, 0xab }, - { 0xcd, 0xe6, 0xd0 }, - { 0xce, 0xe0, 0xea }, - { 0xd5, 0xdd, 0xea }, - { 0xee, 0xc1, 0xc8 }, - { 0xee, 0xaa, 0xb7 }, - { 0xec, 0xce, 0xb6 }, -}; +static void rgb_to_hsv (gfloat r, gfloat g, gfloat b, gfloat * h, gfloat * s, + gfloat * v) +{ + gfloat max, min; + + max = r; + if (g > max) + max = g; + if (b > max) + max = b; + + min = r; + if (g < min) + min = g; + if (b < min) + min = b; + + * v = max; + + if (max == min) + { + * h = 0; + * s = 0; + return; + } + + if (r == max) + * h = 1 + (g - b) / (max - min); + else if (g == max) + * h = 3 + (b - r) / (max - min); + else + * h = 5 + (r - g) / (max - min); + + * s = (max - min) / max; +} + +static void hsv_to_rgb (gfloat h, gfloat s, gfloat v, gfloat * r, gfloat * g, + gfloat * b) +{ + for (; h >= 2; h -= 2) + { + gfloat * p = r; + r = g; + g = b; + b = p; + } + + if (h < 1) + { + * r = 1; + * g = 0; + * b = 1 - h; + } + else + { + * r = 1; + * g = h - 1; + * b = 0; + } + + * r = v * (1 - s * (1 - * r)); + * g = v * (1 - s * (1 - * g)); + * b = v * (1 - s * (1 - * b)); +} + +static void get_color (GtkWidget * widget, gint i, gfloat * r, gfloat * g, + gfloat * b) +{ + GdkColor * c = widget->style->base + GTK_STATE_SELECTED; + gfloat h, s, v, n; + + rgb_to_hsv (c->red / 65535.0, c->green / 65535.0, c->blue / 65535.0, & h, + & s, & v); + + if (s < 0.1) /* monochrome theme? use blue instead */ + { + h = 5; + s = 0.75; + } + + n = sqrt (i / 11.0); + s = sqrt (s) * (1 - 0.75 * n); + v = 0.75 + 0.25 * n; + + hsv_to_rgb (h, s, v, r, g, b); +} static void ui_infoarea_draw_visualizer (UIInfoArea * area) { @@ -167,24 +245,16 @@ static void ui_infoarea_draw_visualizer (UIInfoArea * area) for (auto gint i = 0; i < SPECT_BANDS; i++) { - gint x, y, w, h; - - x = alloc.width - VIS_OFFSET + 10 + 12 * i; - w = 9; - - y = 10; - h = 64 - area->visdata[i]; + gint x = alloc.width - VIS_OFFSET + 10 + 12 * i; + gfloat r, g, b; cairo_set_source_rgb (cr, 0, 0, 0); - cairo_rectangle (cr, x, y, w, h); + cairo_rectangle (cr, x, 10, 9, 64 - area->visdata[i]); cairo_fill (cr); - y = 10 + 64 - area->visdata[i]; - h = area->visdata[i]; - - cairo_set_source_rgb (cr, colors[i].red / 255.0, colors[i].green / - 255.0, colors[i].blue / 255.0); - cairo_rectangle (cr, x, y, w, h); + get_color (area->parent, i, & r, & g, & b); + cairo_set_source_rgb (cr, r, g, b); + cairo_rectangle (cr, x, 74 - area->visdata[i], 9, area->visdata[i]); cairo_fill (cr); } @@ -194,9 +264,9 @@ static void ui_infoarea_draw_visualizer (UIInfoArea * area) static GdkPixbuf * get_current_album_art (void) { gint playlist = aud_playlist_get_playing (); - gint position = aud_playlist_get_position (playlist); - const gchar * filename = aud_playlist_entry_get_filename (playlist, position); - InputPlugin * decoder = aud_playlist_entry_get_decoder (playlist, position); + const gchar * filename = aud_playlist_entry_get_filename (playlist, + aud_playlist_get_position (playlist)); + InputPlugin * decoder = aud_file_find_decoder (filename, FALSE); void * data; gint size; GdkPixbuf * pixbuf; @@ -214,26 +284,26 @@ void ui_infoarea_draw_album_art (UIInfoArea * area) { cairo_t * cr; - if (audacious_drct_get_playing () && ! area->pb) + if (aud_drct_get_playing () && area->pb == NULL) { area->pb = get_current_album_art (); - if (! area->pb) + if (area->pb == NULL) area->pb = gdk_pixbuf_new_from_file (DEFAULT_ARTWORK, NULL); - if (area->pb) + if (area->pb != NULL) audgui_pixbuf_scale_within (& area->pb, ICON_SIZE); } cr = gdk_cairo_create (area->parent->window); - if (area->pb) + if (area->pb != NULL) { gdk_cairo_set_source_pixbuf (cr, area->pb, 10.0, 10.0); cairo_paint_with_alpha (cr, area->alpha); } - if (area->last_pb) + if (area->last_pb != NULL) { gdk_cairo_set_source_pixbuf (cr, area->last_pb, 10.0, 10.0); cairo_paint_with_alpha (cr, area->last_alpha); @@ -250,22 +320,22 @@ void ui_infoarea_draw_title (UIInfoArea * area) gtk_widget_get_allocation (area->parent, & alloc); width = alloc.width - (86 + VIS_OFFSET + 6); - if (area->title) + if (area->title != NULL) ui_infoarea_draw_text (area, 86, 8, width, 1, 1, 1, area->alpha, "Sans 18", area->title); - if (area->last_title) + if (area->last_title != NULL) ui_infoarea_draw_text (area, 86, 8, width, 1, 1, 1, area->last_alpha, "Sans 18", area->last_title); - if (area->artist) + if (area->artist != NULL) ui_infoarea_draw_text (area, 86, 42, width, 1, 1, 1, area->alpha, "Sans 9", area->artist); - if (area->last_artist) + if (area->last_artist != NULL) ui_infoarea_draw_text (area, 86, 42, width, 1, 1, 1, area->last_alpha, "Sans 9", area->last_artist); - if (area->album) + if (area->album != NULL) ui_infoarea_draw_text (area, 86, 58, width, 0.7, 0.7, 0.7, area->alpha, "Sans 9", area->album); - if (area->last_album) + if (area->last_album != NULL) ui_infoarea_draw_text (area, 86, 58, width, 0.7, 0.7, 0.7, area->last_alpha, "Sans 9", area->last_album); } @@ -305,7 +375,7 @@ static gboolean ui_infoarea_do_fade (UIInfoArea * area) { gboolean ret = FALSE; - if (audacious_drct_get_playing () && area->alpha < 1) + if (aud_drct_get_playing () && area->alpha < 1) { area->alpha += alpha_step; ret = TRUE; @@ -329,7 +399,7 @@ void ui_infoarea_set_title (void * data, UIInfoArea * area) { gint playlist = aud_playlist_get_playing (); gint entry = aud_playlist_get_position (playlist); - const Tuple * tuple = aud_playlist_entry_get_tuple (playlist, entry); + const Tuple * tuple = aud_playlist_entry_get_tuple (playlist, entry, FALSE); const gchar * s; g_free (area->title); @@ -342,7 +412,8 @@ void ui_infoarea_set_title (void * data, UIInfoArea * area) if (tuple && (s = tuple_get_string (tuple, FIELD_TITLE, NULL))) area->title = g_strdup (s); else - area->title = g_strdup (aud_playlist_entry_get_title (playlist, entry)); + area->title = g_strdup (aud_playlist_entry_get_title (playlist, entry, + FALSE)); if (tuple && (s = tuple_get_string (tuple, FIELD_ARTIST, NULL))) area->artist = g_strdup (s); @@ -384,6 +455,8 @@ static void ui_infoarea_playback_start (void * data, UIInfoArea * area) infoarea_next (area); area->stopped = FALSE; + ui_infoarea_set_title (NULL, area); + if (! area->fade_timeout) area->fade_timeout = g_timeout_add (30, (GSourceFunc) ui_infoarea_do_fade, area); @@ -401,14 +474,13 @@ static void ui_infoarea_playback_stop (void * data, UIInfoArea * area) static void destroy_cb (GtkObject * parent, UIInfoArea * area) { - aud_hook_dissociate ("title change", (HookFunction) ui_infoarea_set_title); - aud_hook_dissociate ("playback begin", (HookFunction) + hook_dissociate ("title change", (HookFunction) ui_infoarea_set_title); + hook_dissociate ("playback begin", (HookFunction) ui_infoarea_playback_start); - aud_hook_dissociate ("playback stop", (HookFunction) + hook_dissociate ("playback stop", (HookFunction) ui_infoarea_playback_stop); - aud_hook_dissociate ("visualization timeout", (HookFunction) - ui_infoarea_visualization_timeout); - aud_hook_dissociate ("visualization clear", (HookFunction) vis_clear_cb); + hook_dissociate ("visualization clear", (HookFunction) vis_clear_cb); + aud_vis_runner_remove_hook ((VisHookFunc) ui_infoarea_visualization_timeout); g_free (area->title); g_free (area->artist); @@ -440,15 +512,16 @@ GtkWidget * ui_infoarea_new (void) g_signal_connect_swapped(area->parent, "expose-event", G_CALLBACK(ui_infoarea_expose_event), area); - aud_hook_associate("title change", (HookFunction) ui_infoarea_set_title, area); - aud_hook_associate("playback begin", (HookFunction) ui_infoarea_playback_start, area); - aud_hook_associate("playback stop", (HookFunction) ui_infoarea_playback_stop, area); - aud_hook_associate("visualization timeout", (HookFunction) ui_infoarea_visualization_timeout, area); - aud_hook_associate("visualization clear", (HookFunction) vis_clear_cb, area); + hook_associate("title change", (HookFunction) ui_infoarea_set_title, area); + hook_associate("playback begin", (HookFunction) ui_infoarea_playback_start, area); + hook_associate("playback stop", (HookFunction) ui_infoarea_playback_stop, area); + hook_associate("visualization clear", (HookFunction) vis_clear_cb, area); + aud_vis_runner_add_hook ((VisHookFunc) ui_infoarea_visualization_timeout, + area); g_signal_connect (area->parent, "destroy", (GCallback) destroy_cb, area); - if (audacious_drct_get_playing ()) + if (aud_drct_get_playing ()) ui_infoarea_playback_start (NULL, area); return area->parent; diff --git a/src/gtkui/ui_manager.c b/src/gtkui/ui_manager.c index a8181d4..60792cb 100644 --- a/src/gtkui/ui_manager.c +++ b/src/gtkui/ui_manager.c @@ -23,8 +23,7 @@ #include "actions-mainwin.h" #include "actions-playlist.h" -#include <audacious/plugin.h> -#include <audacious/ui_plugin_menu.h> +#include <audacious/misc.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> @@ -53,6 +52,9 @@ static GtkToggleActionEntry toggleaction_entries_others[] = { {"view menu", NULL, N_("Show main menu"), "<Shift><Ctrl>M", N_("Show/hide main menu"), G_CALLBACK(action_view_menu), FALSE}, + + {"view statusbar", NULL, N_("Show statusbar"), "<Shift><Ctrl>S", + N_("Show/hide statusbar"), G_CALLBACK(action_view_statusbar), FALSE}, }; /* normal actions */ @@ -84,19 +86,13 @@ static GtkActionEntry action_entries_playlist[] = { {"playlist new", GTK_STOCK_NEW, N_("New Playlist"), "<Shift>N", N_("New Playlist"), G_CALLBACK(action_playlist_new)}, - {"playlist select next", GTK_STOCK_MEDIA_NEXT, N_("Select Next Playlist"), "<Ctrl>Page_Down", - N_("Select Next Playlist"), G_CALLBACK(action_playlist_next)}, - - {"playlist select previous", GTK_STOCK_MEDIA_PREVIOUS, N_("Select Previous Playlist"), "<Ctrl>Page_Up", - N_("Select Previous Playlist"), G_CALLBACK(action_playlist_prev)}, - {"playlist delete", GTK_STOCK_DELETE, N_("Delete Playlist"), "<Shift>D", N_("Delete Playlist"), G_CALLBACK(action_playlist_delete)}, - {"playlist load", GTK_STOCK_OPEN, N_("Load List"), "O", + {"playlist load", GTK_STOCK_OPEN, N_("Import Playlist ..."), "O", N_("Loads a playlist file into the selected playlist."), G_CALLBACK(action_playlist_load_list)}, - {"playlist save", GTK_STOCK_SAVE, N_("Save List"), "<Shift>S", + {"playlist save", GTK_STOCK_SAVE, N_("Export Playlist ..."), "<Shift>S", N_("Saves the selected playlist."), G_CALLBACK(action_playlist_save_list)}, {"playlist save all", GTK_STOCK_SAVE, N_("Save All Playlists"), "<Alt>S", @@ -104,19 +100,19 @@ static GtkActionEntry action_entries_playlist[] = { "is done automatically when Audacious quits."), G_CALLBACK(action_playlist_save_all_playlists)}, - {"playlist refresh", GTK_STOCK_REFRESH, N_("Refresh List"), "F5", + {"playlist refresh", GTK_STOCK_REFRESH, N_("Refresh"), "F5", N_("Refreshes metadata associated with a playlist entry."), G_CALLBACK(action_playlist_refresh_list)}, - {"playlist manager", AUD_STOCK_PLAYLIST, N_("List Manager"), "P", + {"playlist manager", AUD_STOCK_PLAYLIST, N_("Playlist Manager"), "P", N_("Opens the playlist manager."), G_CALLBACK(action_open_list_manager)}, - {"playlist add url", GTK_STOCK_NETWORK, N_("Add Internet Address..."), "<Ctrl>H", + {"playlist add url", GTK_STOCK_NETWORK, N_("Add URL ..."), "<Ctrl>H", N_("Adds a remote track to the playlist."), G_CALLBACK(action_playlist_add_url)}, - {"playlist add files", GTK_STOCK_ADD, N_("Add Files..."), "F", + {"playlist add files", GTK_STOCK_ADD, N_("Add Files ..."), "F", N_("Adds files to the playlist."), G_CALLBACK(action_playlist_add_files)}, @@ -144,9 +140,8 @@ static GtkActionEntry action_entries_output[] = }; static GtkActionEntry action_entries_view[] = { - - {"view", NULL, N_("View")} -}; + {"view", NULL, N_("View")}, + {"iface menu", NULL, N_("Interface")}}; static GtkActionEntry action_entries_others[] = { @@ -167,10 +162,10 @@ static GtkActionEntry action_entries_others[] = { {"about audacious", GTK_STOCK_DIALOG_INFO, N_("About Audacious"), NULL, N_("About Audacious"), G_CALLBACK(action_about_audacious)}, - {"play file", GTK_STOCK_OPEN, N_("Play File"), "L", + {"play file", GTK_STOCK_OPEN, N_("Open Files ..."), "L", N_("Load and play a file"), G_CALLBACK(action_play_file)}, - {"play location", GTK_STOCK_NETWORK, N_("Play Location"), "<Ctrl>L", + {"play location", GTK_STOCK_NETWORK, N_("Open URL ..."), "<Ctrl>L", N_("Play media from the selected location"), G_CALLBACK(action_play_location)}, {"plugins", NULL, N_("Plugin services")}, @@ -294,14 +289,21 @@ void ui_manager_create_menus(void) return; } - gtk_menu_item_set_submenu(GTK_MENU_ITEM(gtk_ui_manager_get_widget(ui_manager, "/mainwin-menus/plugins-menu")), aud_get_plugin_menu(AUDACIOUS_MENU_MAIN)); + gtk_menu_item_set_submenu ((GtkMenuItem *) gtk_ui_manager_get_widget + (ui_manager, "/mainwin-menus/plugins-menu"), aud_get_plugin_menu + (AUDACIOUS_MENU_MAIN)); gtk_menu_item_set_submenu ((GtkMenuItem *) gtk_ui_manager_get_widget (ui_manager, "/mainwin-menus/output/effects menu"), audgui_create_effects_menu ()); + gtk_menu_item_set_submenu ((GtkMenuItem *) gtk_ui_manager_get_widget + (ui_manager, "/mainwin-menus/view/iface menu"), + audgui_create_iface_menu ()); playlistwin_popup_menu = ui_manager_get_popup_menu(ui_manager, "/playlist-menus/playlist-rightclick-menu"); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(gtk_ui_manager_get_widget(ui_manager, "/playlist-menus/playlist-rightclick-menu/plugins-menu")), aud_get_plugin_menu(AUDACIOUS_MENU_PLAYLIST_RCLICK)); + gtk_menu_item_set_submenu ((GtkMenuItem *) gtk_ui_manager_get_widget + (ui_manager, "/playlist-menus/playlist-rightclick-menu/plugins-menu"), + aud_get_plugin_menu (AUDACIOUS_MENU_PLAYLIST_RCLICK)); } @@ -351,6 +353,10 @@ void ui_manager_popup_menu_show(GtkMenu * menu, gint x, gint y, guint button, gu void ui_manager_destroy(void) { + gtk_menu_detach ((GtkMenu *) aud_get_plugin_menu (AUDACIOUS_MENU_MAIN)); + gtk_menu_detach ((GtkMenu *) aud_get_plugin_menu + (AUDACIOUS_MENU_PLAYLIST_RCLICK)); + g_object_unref((GObject *) toggleaction_group_others); g_object_unref((GObject *) action_group_playback); g_object_unref((GObject *) action_group_playlist); diff --git a/src/gtkui/ui_playlist_model.c b/src/gtkui/ui_playlist_model.c index 56c0ee9..74195ff 100644 --- a/src/gtkui/ui_playlist_model.c +++ b/src/gtkui/ui_playlist_model.c @@ -19,7 +19,11 @@ */ #include "config.h" -#include <audacious/plugin.h> + +#include <audacious/debug.h> +#include <audacious/playlist.h> +#include <libaudcore/hook.h> + #include "ui_playlist_model.h" #include "ui_playlist_widget.h" #include "playlist_util.h" @@ -125,6 +129,7 @@ ui_playlist_model_init(UiPlaylistModel *model) model->column_types[PLAYLIST_MULTI_COLUMN_ALBUM] = G_TYPE_STRING; model->column_types[PLAYLIST_MULTI_COLUMN_TITLE] = G_TYPE_STRING; model->column_types[PLAYLIST_MULTI_COLUMN_TRACK_NUM] = G_TYPE_UINT; + model->column_types[PLAYLIST_MULTI_COLUMN_QUEUED] = G_TYPE_STRING; model->column_types[PLAYLIST_MULTI_COLUMN_TIME] = G_TYPE_STRING; model->column_types[PLAYLIST_MULTI_COLUMN_WEIGHT] = PANGO_TYPE_WEIGHT; } @@ -135,6 +140,7 @@ ui_playlist_model_init(UiPlaylistModel *model) model->column_types = g_new0(GType, PLAYLIST_N_COLUMNS); model->column_types[PLAYLIST_COLUMN_NUM] = G_TYPE_UINT; model->column_types[PLAYLIST_COLUMN_TEXT] = G_TYPE_STRING; + model->column_types[PLAYLIST_COLUMN_QUEUED] = G_TYPE_STRING; model->column_types[PLAYLIST_COLUMN_TIME] = G_TYPE_STRING; model->column_types[PLAYLIST_COLUMN_WEIGHT] = PANGO_TYPE_WEIGHT; } @@ -151,6 +157,7 @@ ui_playlist_model_finalize(GObject *object) ui_playlist_model_dissociate_hooks(model); + g_list_free (model->queue); g_free(model->column_types); (* parent_class->finalize) (object); @@ -230,7 +237,8 @@ ui_playlist_model_get_path(GtkTreeModel *tree_model, GtkTreeIter *iter) static void ui_playlist_model_get_value_time(UiPlaylistModel *model, GValue *value, gint position) { - gint length = aud_playlist_entry_get_length(model->playlist, position) / 1000; + gint length = aud_playlist_entry_get_length (model->playlist, position, + TRUE) / 1000; gchar * len = g_strdup_printf("%02i:%02i", length / 60, length % 60); g_value_set_string(value, len); g_free(len); @@ -240,7 +248,7 @@ static void ui_playlist_model_get_value(GtkTreeModel *tree_model, GtkTreeIter *iter, gint column, GValue *value) { UiPlaylistModel *model; - gint n; + gint n, i; g_return_if_fail(UI_IS_PLAYLIST_MODEL(tree_model)); g_return_if_fail(iter != NULL); @@ -257,7 +265,8 @@ ui_playlist_model_get_value(GtkTreeModel *tree_model, GtkTreeIter *iter, gint co if (multi_column_view) { - Tuple *tu = (Tuple*) aud_playlist_entry_get_tuple(model->playlist, n); + const Tuple * tu = aud_playlist_entry_get_tuple (model->playlist, n, + TRUE); switch (column) { @@ -280,12 +289,20 @@ ui_playlist_model_get_value(GtkTreeModel *tree_model, GtkTreeIter *iter, gint co { const gchar *title = tuple_get_string(tu, FIELD_TITLE, NULL); if (title == NULL) - g_value_set_string(value, aud_playlist_entry_get_title(model->playlist, n)); + g_value_set_string (value, aud_playlist_entry_get_title + (model->playlist, n, TRUE)); else g_value_set_string(value, title); break; } + case PLAYLIST_MULTI_COLUMN_QUEUED: + if ((i = aud_playlist_queue_find_entry (model->playlist, n)) < 0) + g_value_set_string (value, ""); + else + g_value_take_string (value, g_strdup_printf ("#%d", 1 + i)); + break; + case PLAYLIST_MULTI_COLUMN_TIME: ui_playlist_model_get_value_time(model, value, n); break; @@ -309,7 +326,15 @@ ui_playlist_model_get_value(GtkTreeModel *tree_model, GtkTreeIter *iter, gint co break; case PLAYLIST_COLUMN_TEXT: - g_value_set_string(value, aud_playlist_entry_get_title(model->playlist, n)); + g_value_set_string (value, aud_playlist_entry_get_title + (model->playlist, n, TRUE)); + break; + + case PLAYLIST_COLUMN_QUEUED: + if ((i = aud_playlist_queue_find_entry (model->playlist, n)) < 0) + g_value_set_string (value, ""); + else + g_value_take_string (value, g_strdup_printf ("#%d", 1 + i)); break; case PLAYLIST_COLUMN_TIME: @@ -435,6 +460,7 @@ ui_playlist_model_new(gint playlist) model->playlist = playlist; model->num_rows = aud_playlist_entry_count(playlist); model->position = aud_playlist_get_position (playlist); + model->queue = NULL; model->song_changed = FALSE; model->focus_changed = FALSE; model->selection_changed = FALSE; @@ -518,6 +544,29 @@ static void ui_playlist_model_playlist_position (void * hook_data, void * model->song_changed = TRUE; } +static void update_queue_row_changed (void * row, void * model) +{ + ui_playlist_model_row_changed (model, GPOINTER_TO_INT (row)); +} + +static void update_queue (UiPlaylistModel * model) +{ + gint i; + + /* update previously queued rows */ + g_list_foreach (model->queue, update_queue_row_changed, model); + + g_list_free (model->queue); + model->queue = NULL; + + for (i = aud_playlist_queue_count (model->playlist); i --; ) + model->queue = g_list_prepend (model->queue, GINT_TO_POINTER + (aud_playlist_queue_get_entry (model->playlist, i))); + + /* update currently queued rows */ + g_list_foreach (model->queue, update_queue_row_changed, model); +} + static void ui_playlist_model_playlist_update(gpointer hook_data, gpointer user_data) { @@ -577,6 +626,8 @@ ui_playlist_model_playlist_update(gpointer hook_data, gpointer user_data) AUDDBG("playlist metadata update\n"); ui_playlist_model_playlist_rearraged(model); } + else if (type == PLAYLIST_UPDATE_SELECTION) + update_queue (model); if (model->song_changed) { @@ -623,15 +674,15 @@ ui_playlist_model_playlist_delete(gpointer hook_data, gpointer user_data) static void ui_playlist_model_associate_hooks(UiPlaylistModel *model) { - aud_hook_associate("playlist update", ui_playlist_model_playlist_update, model); - aud_hook_associate("playlist delete", ui_playlist_model_playlist_delete, model); - aud_hook_associate("playlist position", ui_playlist_model_playlist_position, model); + hook_associate("playlist update", ui_playlist_model_playlist_update, model); + hook_associate("playlist delete", ui_playlist_model_playlist_delete, model); + hook_associate("playlist position", ui_playlist_model_playlist_position, model); } static void ui_playlist_model_dissociate_hooks(UiPlaylistModel *model) { - aud_hook_dissociate_full("playlist update", ui_playlist_model_playlist_update, model); - aud_hook_dissociate_full("playlist delete", ui_playlist_model_playlist_delete, model); - aud_hook_dissociate_full("playlist position", ui_playlist_model_playlist_position, model); + hook_dissociate_full("playlist update", ui_playlist_model_playlist_update, model); + hook_dissociate_full("playlist delete", ui_playlist_model_playlist_delete, model); + hook_dissociate_full("playlist position", ui_playlist_model_playlist_position, model); } diff --git a/src/gtkui/ui_playlist_model.h b/src/gtkui/ui_playlist_model.h index 8af1c8c..57b510e 100644 --- a/src/gtkui/ui_playlist_model.h +++ b/src/gtkui/ui_playlist_model.h @@ -35,6 +35,7 @@ enum { PLAYLIST_COLUMN_NUM = 0, PLAYLIST_COLUMN_TEXT, + PLAYLIST_COLUMN_QUEUED, PLAYLIST_COLUMN_TIME, PLAYLIST_COLUMN_WEIGHT, /* PANGO_WEIGHT_BOLD or PANGO_WEIGHT_NORMAL, denotes currently played song */ PLAYLIST_N_COLUMNS, @@ -48,6 +49,7 @@ enum PLAYLIST_MULTI_COLUMN_ALBUM, PLAYLIST_MULTI_COLUMN_TRACK_NUM, PLAYLIST_MULTI_COLUMN_TITLE, + PLAYLIST_MULTI_COLUMN_QUEUED, PLAYLIST_MULTI_COLUMN_TIME, PLAYLIST_MULTI_COLUMN_WEIGHT, /* PANGO_WEIGHT_BOLD or PANGO_WEIGHT_NORMAL, denotes currently played song */ PLAYLIST_N_MULTI_COLUMNS, @@ -63,6 +65,7 @@ struct _UiPlaylistModel guint num_rows; gint playlist; /* associated playlist number */ gint position; + GList * queue; gboolean song_changed, focus_changed, selection_changed; gint focus; diff --git a/src/gtkui/ui_playlist_notebook.c b/src/gtkui/ui_playlist_notebook.c index d312527..3f948d5 100644 --- a/src/gtkui/ui_playlist_notebook.c +++ b/src/gtkui/ui_playlist_notebook.c @@ -22,6 +22,8 @@ #include <gtk/gtk.h> #include <gdk/gdkkeysyms.h> +#include <audacious/debug.h> +#include <audacious/playlist.h> #include <audacious/plugin.h> #include "ui_playlist_notebook.h" diff --git a/src/gtkui/ui_playlist_widget.c b/src/gtkui/ui_playlist_widget.c index 356f9ea..dce08b2 100644 --- a/src/gtkui/ui_playlist_widget.c +++ b/src/gtkui/ui_playlist_widget.c @@ -1,6 +1,6 @@ /* Audacious - Cross-platform multimedia player * Copyright (C) 2008 Tomasz MoÅ„ <desowin@gmail.com> - * Copyright (C) 2009 William Pitcock <nenolod@atheme.org> + * Copyright (C) 2009-2010 William Pitcock <nenolod@atheme.org> * Copyright (C) 2010 MichaÅ‚ Lipski <tallica@o2.pl> * * This program is free software; you can redistribute it and/or modify @@ -23,7 +23,9 @@ #include <gtk/gtk.h> #include <gdk/gdkkeysyms.h> -#include <audacious/plugin.h> +#include <audacious/audconfig.h> +#include <audacious/drct.h> +#include <audacious/playlist.h> #include <libaudgui/libaudgui.h> #include "ui_manager.h" @@ -53,8 +55,7 @@ static void _ui_playlist_widget_drag_begin(GtkWidget *widget, GdkDragContext * c t->source = (GtkTreeView *) widget; t->source_playlist = playlist; - t->source_pos = GPOINTER_TO_INT (g_object_get_data ((GObject *) widget, - "recently clicked")); + t->source_pos = treeview_get_focus (t->source); t->dest_path = NULL; t->append = FALSE; } @@ -239,8 +240,8 @@ static void ui_playlist_widget_change_song(GtkTreeView * treeview, guint pos) aud_playlist_set_playing(playlist); aud_playlist_set_position(playlist, pos); - if (!audacious_drct_get_playing()) - audacious_drct_play(); + if (!aud_drct_get_playing()) + aud_drct_play(); } static void ui_playlist_widget_row_activated(GtkTreeView * treeview, GtkTreePath * path, GtkTreeViewColumn *column, gpointer user_data) @@ -274,14 +275,16 @@ static gboolean ui_playlist_widget_keypress_cb(GtkWidget * widget, GdkEventKey * case GDK_MOD1_MASK: { if ((event->keyval == GDK_Up) || (event->keyval == GDK_Down)) { - gint playlist = playlist_get_playlist_from_treeview(GTK_TREE_VIEW(widget)); - /* Copy the event, so we can get the selection to move as well */ - GdkEvent * ev = gdk_event_copy((GdkEvent *) event); - ((GdkEventKey *) ev)->state = 0; - - aud_playlist_shift_selected(playlist, (event->keyval == GDK_Up) ? -1 : 1); - gtk_propagate_event(widget, ev); - gdk_event_free(ev); + gint focus = treeview_get_focus ((GtkTreeView *) widget); + if (focus < 0) + return TRUE; + + gint playlist = playlist_get_playlist_from_treeview ((GtkTreeView *) + widget); + aud_playlist_entry_set_selected (playlist, focus, TRUE); + focus += aud_playlist_shift (playlist, focus, (event->keyval == + GDK_Up) ? -1 : 1); + treeview_set_focus ((GtkTreeView *) widget, focus); return TRUE; } } @@ -296,7 +299,6 @@ static gint pos[2]; static gboolean ui_playlist_widget_button_press_cb(GtkWidget * widget, GdkEventButton * event) { GtkTreePath *path = NULL; - GtkTreeSelection *sel = NULL; gint state = event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK); gtk_tree_view_get_path_at_pos ((GtkTreeView *) widget, event->x, event->y, @@ -304,8 +306,8 @@ static gboolean ui_playlist_widget_button_press_cb(GtkWidget * widget, GdkEventB /* Save the row clicked on for drag and drop. */ if (path) - g_object_set_data ((GObject *) widget, "recently clicked", - GINT_TO_POINTER (gtk_tree_path_get_indices (path)[0])); + treeview_set_focus ((GtkTreeView *) widget, gtk_tree_path_get_indices + (path)[0]); if (event->button == 1 && !state) { @@ -316,27 +318,19 @@ static gboolean ui_playlist_widget_button_press_cb(GtkWidget * widget, GdkEventB if (event->button == 1 && state) goto NOT_HANDLED; - sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); - if (event->type == GDK_BUTTON_PRESS && event->button == 3) ui_manager_popup_menu_show(GTK_MENU(playlistwin_popup_menu), event->x_root, event->y_root + 2, 3, event->time); - if (path == NULL) - goto NOT_HANDLED; - - if (event->button == 1 && !state && event->type == GDK_2BUTTON_PRESS) + /* Hack: Keep GTK from messing with a multiple selection. As this blocks + * double click, we handle that case also. */ + if (path && gtk_tree_selection_path_is_selected + (gtk_tree_view_get_selection ((GtkTreeView *) widget), path)) { - gtk_tree_view_row_activated(GTK_TREE_VIEW(widget), path, NULL); - pos[0] = -1; - goto HANDLED; - } + if (event->type == GDK_2BUTTON_PRESS) + gtk_tree_view_row_activated ((GtkTreeView *) widget, path, NULL); - if (gtk_tree_selection_path_is_selected(sel, path) && - playlist_get_selected_length(GTK_TREE_VIEW(widget)) > 1 && - event->type == GDK_BUTTON_PRESS) goto HANDLED; - - pos[0] = -1; + } NOT_HANDLED: if (path) @@ -373,7 +367,7 @@ static gboolean ui_playlist_widget_button_release_cb(GtkWidget * widget, GdkEven return FALSE; } -static void ui_playlist_widget_set_column(GtkWidget *treeview, gchar *title, gint column_id, gint width, gboolean ellipsize, gboolean resizable) +static void ui_playlist_widget_set_column(GtkWidget *treeview, gchar *title, gint column_id, gint width, gboolean ellipsize, gboolean resizable, gboolean expand) { GtkCellRenderer *renderer; GtkTreeViewColumn *column; @@ -390,6 +384,9 @@ static void ui_playlist_widget_set_column(GtkWidget *treeview, gchar *title, gin if (resizable) gtk_tree_view_column_set_resizable(column, TRUE); + if (expand) + gtk_tree_view_column_set_expand(column, TRUE); + if (ellipsize) g_object_set(G_OBJECT(renderer), "ypad", 1, "xpad", 1, "ellipsize-set", TRUE, "ellipsize", PANGO_ELLIPSIZE_END, NULL); else @@ -424,13 +421,14 @@ GtkWidget *ui_playlist_widget_new(gint playlist) if (aud_cfg->show_numbers_in_pl) ui_playlist_widget_set_column (treeview, NULL, PLAYLIST_MULTI_COLUMN_NUM, calculate_column_width (treeview, - model->num_rows), FALSE, FALSE); - - ui_playlist_widget_set_column(treeview, "Artist", PLAYLIST_MULTI_COLUMN_ARTIST, 150, TRUE, TRUE); - ui_playlist_widget_set_column(treeview, "Album", PLAYLIST_MULTI_COLUMN_ALBUM, 200, TRUE, TRUE); - ui_playlist_widget_set_column(treeview, "No", PLAYLIST_MULTI_COLUMN_TRACK_NUM, 40, FALSE, TRUE); - ui_playlist_widget_set_column(treeview, "Title", PLAYLIST_MULTI_COLUMN_TITLE, 250, TRUE, TRUE); - ui_playlist_widget_set_column(treeview, "Time", PLAYLIST_MULTI_COLUMN_TIME, 50, FALSE, FALSE); + model->num_rows), FALSE, FALSE, FALSE); + + ui_playlist_widget_set_column(treeview, "Artist", PLAYLIST_MULTI_COLUMN_ARTIST, 150, TRUE, TRUE, FALSE); + ui_playlist_widget_set_column(treeview, "Album", PLAYLIST_MULTI_COLUMN_ALBUM, 200, TRUE, TRUE, FALSE); + ui_playlist_widget_set_column(treeview, "No", PLAYLIST_MULTI_COLUMN_TRACK_NUM, 40, FALSE, TRUE, FALSE); + ui_playlist_widget_set_column(treeview, "Title", PLAYLIST_MULTI_COLUMN_TITLE, 250, TRUE, TRUE, TRUE); + ui_playlist_widget_set_column(treeview, "Queue", PLAYLIST_MULTI_COLUMN_QUEUED, 50, FALSE, TRUE, FALSE); + ui_playlist_widget_set_column(treeview, "Time", PLAYLIST_MULTI_COLUMN_TIME, 50, FALSE, FALSE, FALSE); } else { @@ -452,6 +450,12 @@ GtkWidget *ui_playlist_widget_new(gint playlist) gtk_tree_view_column_set_attributes(column, renderer, "text", PLAYLIST_COLUMN_TEXT, "weight", PLAYLIST_COLUMN_WEIGHT, NULL); g_object_set(G_OBJECT(renderer), "ypad", 1, "xpad", 1, "ellipsize-set", TRUE, "ellipsize", PANGO_ELLIPSIZE_END, NULL); + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_column_pack_start (column, renderer, FALSE); + gtk_tree_view_column_set_attributes (column, renderer, "text", + PLAYLIST_COLUMN_QUEUED, "weight", PLAYLIST_COLUMN_WEIGHT, NULL); + g_object_set ((GObject *) renderer, "ypad", 1, "xpad", 1, NULL); + renderer = gtk_cell_renderer_text_new(); gtk_tree_view_column_pack_start(column, renderer, FALSE); gtk_tree_view_column_set_attributes(column, renderer, "text", PLAYLIST_COLUMN_TIME, "weight", PLAYLIST_COLUMN_WEIGHT, NULL); diff --git a/src/gtkui/ui_statusbar.c b/src/gtkui/ui_statusbar.c new file mode 100644 index 0000000..a757b7e --- /dev/null +++ b/src/gtkui/ui_statusbar.c @@ -0,0 +1,151 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2010 Audacious development team + * + * 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; under version 3 of the License. + * + * 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, see <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <glib.h> +#include <glib/gi18n.h> +#include <gdk/gdk.h> +#include <gdk/gdkkeysyms.h> +#include <gtk/gtk.h> +#include <string.h> +#include <inttypes.h> +#include <unistd.h> +#include <errno.h> + +#include <audacious/drct.h> +#include <audacious/playlist.h> +#include <libaudcore/hook.h> + +#include "ui_statusbar.h" + +static void +ui_statusbar_update_playlist_length(gpointer unused, GtkWidget *label) +{ + gint playlist = aud_playlist_get_active(); + gint64 selection, total; + gchar *sel_text, *tot_text, *text; + + total = aud_playlist_get_total_length (playlist, TRUE) / 1000; + selection = aud_playlist_get_selected_length (playlist, TRUE) / 1000; + + if (selection >= 3600) + sel_text = g_strdup_printf ("%" PRId64 ":%02" PRId64 ":%02" PRId64, + selection / 3600, selection / 60 % 60, selection % 60); + else + sel_text = g_strdup_printf ("%" PRId64 ":%02" PRId64, + selection / 60, selection % 60); + + if (total >= 3600) + tot_text = g_strdup_printf ("%" PRId64 ":%02" PRId64 ":%02" PRId64, + total / 3600, total / 60 % 60, total % 60); + else + tot_text = g_strdup_printf ("%" PRId64 ":%02" PRId64, + total / 60, total % 60); + + text = g_strconcat(sel_text, "/", tot_text, NULL); + gtk_label_set_text(GTK_LABEL(label), text); + + g_free(text); + g_free(tot_text); + g_free(sel_text); +} + +static void +ui_statusbar_info_change(gpointer unused, GtkWidget *label) +{ + gint bitrate, samplerate, channels; + gchar *text, *ch_text; + const Tuple *tuple; + gint playlist, entry; + const gchar *codec; + + /* may be called asynchronously */ + if (!aud_drct_get_playing()) + return; + + playlist = aud_playlist_get_active(); + entry = aud_playlist_get_position(playlist); + tuple = aud_playlist_entry_get_tuple (playlist, entry, FALSE); + codec = tuple != NULL ? tuple_get_string(tuple, FIELD_CODEC, NULL) : "???"; + + aud_drct_get_info(&bitrate, &samplerate, &channels); + + switch (channels) + { + case 1: + ch_text = g_strdup(_("mono")); + break; + case 2: + ch_text = g_strdup(_("stereo")); + break; + default: + ch_text = g_strdup_printf(_("%d channels"), channels); + break; + } + + text = g_strdup_printf(_("%s: %d kbps, %d Hz, %s"), codec, bitrate / 1000, samplerate, ch_text); + gtk_label_set_text(GTK_LABEL(label), text); + + g_free(text); + g_free(ch_text); +} + +static void +ui_statusbar_playback_stop(gpointer unused, GtkWidget *label) +{ + gtk_label_set_text(GTK_LABEL(label), ""); +} + +static void ui_statusbar_destroy_cb(GtkWidget *widget, gpointer user_data) +{ + hook_dissociate("info change", (HookFunction) ui_statusbar_info_change); + hook_dissociate("playback stop", (HookFunction) ui_statusbar_playback_stop); + hook_dissociate("playlist update", (HookFunction) ui_statusbar_update_playlist_length); + hook_dissociate("info change", (HookFunction) ui_statusbar_update_playlist_length); +} + +GtkWidget * +ui_statusbar_new(void) +{ + GtkWidget *hbox; + GtkWidget *status, *length; + + hbox = gtk_hbox_new(FALSE, 3); + + status = gtk_widget_new(GTK_TYPE_LABEL, "xalign", 0.0, NULL); + gtk_box_pack_start(GTK_BOX(hbox), status, TRUE, TRUE, 5); + + hook_associate("info change", (HookFunction) ui_statusbar_info_change, status); + hook_associate("playback stop", (HookFunction) ui_statusbar_playback_stop, status); + + length = gtk_widget_new(GTK_TYPE_LABEL, "xalign", 1.0, NULL); + gtk_box_pack_start(GTK_BOX(hbox), length, FALSE, FALSE, 5); + ui_statusbar_update_playlist_length(NULL, length); + + hook_associate("playlist update", (HookFunction) ui_statusbar_update_playlist_length, length); + hook_associate("info change", (HookFunction) ui_statusbar_update_playlist_length, length); + + g_signal_connect(G_OBJECT(hbox), "destroy", G_CALLBACK(ui_statusbar_destroy_cb), NULL); + + if (aud_drct_get_playing()) + { + ui_statusbar_info_change(NULL, status); + } + + return hbox; +} diff --git a/src/gtkui/ui_statusbar.h b/src/gtkui/ui_statusbar.h new file mode 100644 index 0000000..e02af5a --- /dev/null +++ b/src/gtkui/ui_statusbar.h @@ -0,0 +1,27 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2010 Audacious development team + * + * 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; under version 3 of the License. + * + * 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, see <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef __UI_STATUSBAR_H +#define __UI_STATUSBAR_H + +#include <gtk/gtk.h> + +GtkWidget *ui_statusbar_new(void); + +#endif diff --git a/src/gtkui/util.c b/src/gtkui/util.c index 9d4ff77..29971ff 100644 --- a/src/gtkui/util.c +++ b/src/gtkui/util.c @@ -23,9 +23,10 @@ * Audacious or using our public API to be a derived work. */ -#include "util.h" -#include <audacious/plugin.h> #include <gtk/gtk.h> +#include <libaudcore/hook.h> + +#include "util.h" GtkWidget *make_filebrowser(const gchar * title, gboolean save) { @@ -57,5 +58,5 @@ void check_set(GtkActionGroup * action_group, const gchar * action_name, gboolea g_return_if_fail (action != NULL); gtk_toggle_action_set_active ((GtkToggleAction *) action, is_on); - aud_hook_call (action_name, GINT_TO_POINTER (is_on)); + hook_call (action_name, GINT_TO_POINTER (is_on)); } diff --git a/src/hotkey/plugin.c b/src/hotkey/plugin.c index ea2de01..c2c1bfb 100644 --- a/src/hotkey/plugin.c +++ b/src/hotkey/plugin.c @@ -4,7 +4,7 @@ * Copyright (c) 2007 - 2008 Sascha Hlusiak <contact@saschahlusiak.de> * Name: plugin.c * Description: plugin.c - * + * * Part of this code is from itouch-ctrl plugin. * Authors of itouch-ctrl are listed below: * @@ -39,10 +39,12 @@ #include <X11/XF86keysym.h> #include <gdk/gdkx.h> -#include <audacious/plugin.h> -#include <audacious/auddrct.h> +#include <audacious/configdb.h> +#include <audacious/drct.h> #include <audacious/i18n.h> +#include <audacious/plugin.h> +#include <libaudcore/hook.h> #include "plugin.h" #include "gui.h" @@ -80,7 +82,7 @@ PluginConfig* get_config(void) } -/* +/* * plugin activated */ static void init (void) @@ -98,12 +100,12 @@ gboolean handle_keyevent (EVENT event) gint current_volume, old_volume; static gint volume_static = 0; gboolean play, mute; - + /* playing or not */ - play = audacious_drct_is_playing (); - + play = aud_drct_get_playing (); + /* get current volume */ - audacious_drct_get_volume_main (¤t_volume); + aud_drct_get_volume_main (¤t_volume); old_volume = current_volume; if (current_volume) { @@ -120,15 +122,15 @@ gboolean handle_keyevent (EVENT event) if (!mute) { volume_static = current_volume; - audacious_drct_set_main_volume (0); + aud_drct_set_volume_main (0); mute = TRUE; } else { - audacious_drct_set_main_volume (volume_static); + aud_drct_set_volume_main (volume_static); mute = FALSE; } return TRUE; } - + /* decreace volume */ if (event == EVENT_VOL_DOWN) { @@ -138,21 +140,21 @@ gboolean handle_keyevent (EVENT event) old_volume = 0; mute = FALSE; } - + if ((current_volume -= plugin_cfg.vol_decrement) < 0) { current_volume = 0; } - + if (current_volume != old_volume) { - audacious_drct_set_main_volume (current_volume); + aud_drct_set_volume_main (current_volume); } - + old_volume = current_volume; return TRUE; } - + /* increase volume */ if (event == EVENT_VOL_UP) { @@ -162,108 +164,93 @@ gboolean handle_keyevent (EVENT event) old_volume = 0; mute = FALSE; } - + if ((current_volume += plugin_cfg.vol_increment) > 100) { current_volume = 100; } - + if (current_volume != old_volume) { - audacious_drct_set_main_volume (current_volume); + aud_drct_set_volume_main (current_volume); } - + old_volume = current_volume; return TRUE; } - + /* play */ if (event == EVENT_PLAY) { - audacious_drct_play (); + aud_drct_play (); return TRUE; } /* pause */ if (event == EVENT_PAUSE) { - if (!play) audacious_drct_play (); - else audacious_drct_pause (); + if (!play) aud_drct_play (); + else aud_drct_pause (); return TRUE; } - + /* stop */ if (event == EVENT_STOP) { - audacious_drct_stop (); + aud_drct_stop (); return TRUE; } - - /* prev track */ + + /* prev track */ if (event == EVENT_PREV_TRACK) { - audacious_drct_playlist_prev (); + aud_drct_pl_prev (); return TRUE; } - + /* next track */ if (event == EVENT_NEXT_TRACK) { - audacious_drct_playlist_next (); + aud_drct_pl_next (); return TRUE; } /* forward */ if (event == EVENT_FORWARD) { - gint time = audacious_drct_get_output_time(); - time += 5000; /* Jump 5s into future */ - audacious_drct_jump_to_time(time); + aud_drct_seek (aud_drct_get_time () + 5000); return TRUE; } /* backward */ if (event == EVENT_BACKWARD) { - gint time = audacious_drct_get_output_time(); + gint time = aud_drct_get_time (); if (time > 5000) time -= 5000; /* Jump 5s back */ else time = 0; - audacious_drct_jump_to_time(time); + aud_drct_seek (time); return TRUE; } /* Open Jump-To-File dialog */ if (event == EVENT_JUMP_TO_FILE) { - audacious_drct_show_jtf_box(); + hook_call ("interface show jump to track", NULL); return TRUE; } /* Toggle Windows */ if (event == EVENT_TOGGLE_WIN) { - static gboolean is_main, is_eq, is_pl; - is_main = audacious_drct_main_win_is_visible(); - if (is_main) { /* Hide windows */ - is_pl = audacious_drct_pl_win_is_visible(); - is_eq = audacious_drct_eq_win_is_visible(); - audacious_drct_main_win_toggle(FALSE); - audacious_drct_pl_win_toggle(FALSE); - audacious_drct_eq_win_toggle(FALSE); - } else { /* Show hidden windows */ - audacious_drct_main_win_toggle(TRUE); - audacious_drct_pl_win_toggle(is_pl); - audacious_drct_eq_win_toggle(is_eq); - audacious_drct_activate(); - } + hook_call ("interface toggle visibility", NULL); return TRUE; } /* Show OSD through AOSD plugin*/ if (event == EVENT_SHOW_AOSD) { - aud_hook_call("aosd toggle", NULL); + hook_call("aosd toggle", NULL); return TRUE; } @@ -321,7 +308,7 @@ void load_config (void) mcs_handle_t *cfdb; HotkeyConfiguration *hotkey; int i,max; - + /* default volume level */ plugin_cfg.vol_increment = 4; plugin_cfg.vol_decrement = 4; diff --git a/src/jack/configure.c b/src/jack/configure.c index 880fd6f..daf0fe5 100644 --- a/src/jack/configure.c +++ b/src/jack/configure.c @@ -24,8 +24,10 @@ #include "jack.h" +#include <audacious/configdb.h> #include <audacious/plugin.h> #include <audacious/i18n.h> + #include "config.h" #include <gtk/gtk.h> diff --git a/src/jack/jack.c b/src/jack/jack.c index dd41b7f..fd04335 100644 --- a/src/jack/jack.c +++ b/src/jack/jack.c @@ -6,18 +6,18 @@ * This code maps xmms calls into the jack translation library */ -#include <audacious/plugin.h> #include <dlfcn.h> -#include <libaudgui/libaudgui.h> -#include <libaudgui/libaudgui-gtk.h> -#include <audacious/i18n.h> #include <stdio.h> #include "config.h" #include "bio2jack.h" /* includes for the bio2jack library */ #include "jack.h" #include <string.h> - +#include <audacious/configdb.h> +#include <audacious/i18n.h> +#include <audacious/plugin.h> +#include <libaudgui/libaudgui.h> +#include <libaudgui/libaudgui-gtk.h> /* set to 1 for verbose output */ #define VERBOSE_OUTPUT 0 @@ -44,7 +44,7 @@ jackconfig jack_cfg; static int driver = 0; /* handle to the jack output device */ typedef struct format_info { - AFormat format; + gint format; long frequency; int channels; long bps; @@ -230,7 +230,7 @@ static OutputPluginInitStatus jack_init(void) jack_set_port_connection_mode(); output_opened = FALSE; - + /* Always return OK, as we don't know about physical devices here */ return OUTPUT_PLUGIN_INIT_FOUND_DEVICES; } @@ -283,7 +283,7 @@ static void jack_close(void) /* Open the device up */ -static gint jack_open(AFormat fmt, gint sample_rate, gint num_channels) +static gint jack_open(gint fmt, gint sample_rate, gint num_channels) { int bits_per_sample; int floating_point = FALSE; @@ -440,12 +440,12 @@ static void jack_about(void) audgui_simple_message (& aboutbox, GTK_MESSAGE_INFO, _("About JACK Output Plugin 0.17"), description); - + g_free(description); } } -static void jack_tell_audio(AFormat * fmt, gint * srate, gint * nch) +static void jack_tell_audio(gint * fmt, gint * srate, gint * nch) { (*fmt) = input.format; (*srate) = input.frequency; diff --git a/src/ladspa/ladspa.c b/src/ladspa/ladspa.c index 76c5f44..92afdb9 100644 --- a/src/ladspa/ladspa.c +++ b/src/ladspa/ladspa.c @@ -17,6 +17,7 @@ */ /* BMP-ladspa port by Giacomo Lozito <city_hunter@users.sf.net> */ +/* Audacious 2.4 port by John Lindgren <john.lindgren@tds.net>, 2010 */ #include "config.h" @@ -29,8 +30,9 @@ #include <sys/types.h> #include <gtk/gtk.h> -#include <audacious/plugin.h> +#include <audacious/configdb.h> #include <audacious/i18n.h> +#include <audacious/plugin.h> #include "ladspa.h" @@ -69,7 +71,6 @@ typedef struct static void start(void); static void stop(void); -static int apply_effect(gpointer * d, gint length, AFormat afmt, gint srate, gint nch); static void configure(void); static void restore(void); @@ -106,30 +107,15 @@ static plugin_instance *selected_instance; static struct { - AFormat afmt; gint srate; gint nch; gboolean ignore; gboolean running; gboolean initialised; -} state = -{ -0, 0, 0, FALSE, FALSE, FALSE}; +} state = {0, 0, FALSE, FALSE, FALSE}; static GtkWidget *config_window = NULL, *run_clist = NULL; -static EffectPlugin ladspa_ep = { - .description = PLUGIN_NAME, - .init = start, - .cleanup = stop, - .configure = configure, - .mod_samples = apply_effect, -}; - -EffectPlugin *ladspa_eplist[] = { &ladspa_ep, NULL }; - -DECLARE_PLUGIN(ladspa, NULL, NULL, NULL, NULL, ladspa_eplist, NULL, NULL, NULL); - static void start(void) { if (state.initialised == FALSE) @@ -395,102 +381,58 @@ static void reboot_plugins(void) G_UNLOCK(running_plugins); } -static int apply_effect(gpointer * d, gint length, AFormat afmt, gint srate, gint nch) +static void ladspa_process (gfloat * * datap, gint * samplesp) { - gint16 *raw16 = *d; + gfloat * const data = * datap; + const gint samples = * samplesp; GSList *list; plugin_instance *instance; int k; - if (running_plugins == NULL || state.running == FALSE) - { - return length; - } - - if (state.afmt != afmt || state.srate != srate || state.nch != nch) - { - state.afmt = afmt; - state.srate = srate; - state.nch = nch; - - if (nch < 1 || nch > 2) - state.ignore = 1; - else if (afmt == FMT_S16_NE) - state.ignore = 0; -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - else if (afmt == FMT_S16_LE) - state.ignore = 0; -#elif G_BYTE_ORDER == G_BIG_ENDIAN - else if (afmt == FMT_S16_BE) - state.ignore = 0; -#endif - else - state.ignore = 1; - - reboot_plugins(); - } - - if (state.ignore || length > MAX_SAMPLES * 2) - { - return length; - } + if (running_plugins == NULL || state.running == FALSE || state.ignore || + samples > MAX_SAMPLES) + return; if (state.nch == 1) { - for (k = 0; k < length / 2; ++k) - { - left[k] = ((LADSPA_Data) raw16[k]) * (1.0f / 32768.0f); - } + for (k = 0; k < samples; k ++) + left[k] = data[k]; + G_LOCK(running_plugins); for (list = running_plugins; list != NULL; list = g_slist_next(list)) { instance = (plugin_instance *) list->data; if (instance->handle) - { - instance->descriptor->run(instance->handle, length / 2); - } + instance->descriptor->run(instance->handle, samples); } G_UNLOCK(running_plugins); - for (k = 0; k < length / 2; ++k) - { - raw16[k] = CLAMP((int)(left[k] * 32768.0f), -32768, 32767); - } + + for (k = 0; k < samples; k ++) + data[k] = left[k]; } else { - for (k = 0; k < length / 2; k += 2) - { - left[k / 2] = ((LADSPA_Data) raw16[k]) * (1.0f / 32768.0f); - } - for (k = 1; k < length / 2; k += 2) - { - right[k / 2] = ((LADSPA_Data) raw16[k]) * (1.0f / 32768.0f); - } + for (k = 0; k < samples; k += 2) + left[k >> 1] = data[k]; + for (k = 1; k < samples; k += 2) + right[k >> 1] = data[k]; + G_LOCK(running_plugins); for (list = running_plugins; list != NULL; list = g_slist_next(list)) { instance = (plugin_instance *) list->data; if (instance->handle) - { - instance->descriptor->run(instance->handle, length / 4); - } + instance->descriptor->run(instance->handle, samples / 2); if (instance->handle2) - { - instance->descriptor->run(instance->handle2, length / 4); - } + instance->descriptor->run(instance->handle2, samples / 2); } G_UNLOCK(running_plugins); - for (k = 0; k < length / 2; k += 2) - { - raw16[k] = CLAMP((int)(left[k / 2] * 32768.0f), -32768, 32767); - } - for (k = 1; k < length / 2; k += 2) - { - raw16[k] = CLAMP((int)(right[k / 2] * 32768.0f), -32768, 32767); - } - } - return length; + for (k = 0; k < samples; k += 2) + data[k] = left[k >> 1]; + for (k = 1; k < samples; k += 2) + data[k] = right[k >> 1]; + } } static void port_assign(plugin_instance * instance) @@ -1127,3 +1069,47 @@ static void configure(void) gtk_widget_show_all(config_window); } + +void ladspa_start (gint * channels, gint * rate) +{ + state.nch = * channels; + state.srate = * rate; + state.ignore = (* channels < 1 || * channels > 2); + reboot_plugins (); +} + +void ladspa_flush (void) +{ +} + +void ladspa_finish (gfloat * * data, gint * samples) +{ + ladspa_process (data, samples); +} + +gint ladspa_decoder_to_output_time (gint time) +{ + return time; +} + +gint ladspa_output_to_decoder_time (gint time) +{ + return time; +} + +static EffectPlugin header = { + .description = PLUGIN_NAME, + .init = start, + .cleanup = stop, + .configure = configure, + .start = ladspa_start, + .process = ladspa_process, + .flush = ladspa_flush, + .finish = ladspa_finish, + .decoder_to_output_time = ladspa_decoder_to_output_time, + .output_to_decoder_time = ladspa_output_to_decoder_time, + .preserves_format = TRUE, +}; + +EffectPlugin * header_list[] = {& header, NULL}; +SIMPLE_EFFECT_PLUGIN (ladspa, header_list) diff --git a/src/lirc/lirc.c b/src/lirc/lirc.c index 0860cac..1cb6529 100644 --- a/src/lirc/lirc.c +++ b/src/lirc/lirc.c @@ -34,15 +34,14 @@ #include <stdlib.h> #include <ctype.h> +#include <glib.h> #include <gtk/gtk.h> +#include <lirc/lirc_client.h> -#include <glib.h> +#include <audacious/drct.h> #include <audacious/i18n.h> - #include <audacious/plugin.h> -#include <audacious/auddrct.h> - -#include <lirc/lirc_client.h> +#include <libaudcore/hook.h> #include "lirc.h" @@ -77,7 +76,7 @@ gint tid; void init_lirc(void) { int flags; - + if((lirc_fd=lirc_init("audacious",1))==-1) { fprintf(stderr,_("%s: could not init LIRC support\n"), @@ -122,7 +121,7 @@ gboolean reconnect_lirc(gpointer data) gboolean jump_to(gpointer data) { - audacious_drct_pl_set_pos(atoi(track_no)-1); + aud_drct_pl_set_pos(atoi(track_no)-1); track_no_pos=0; tid=0; return FALSE; @@ -137,43 +136,45 @@ void lirc_input_callback(gpointer data,gint source, int ret; char *ptr; gint balance; +#if 0 gboolean show_pl; - int n; +#endif + int n; gchar *utf8_title_markup; - + while((ret=lirc_nextcode(&code))==0 && code!=NULL) { while((ret=lirc_code2char(config,code,&c))==0 && c!=NULL) { if(strcasecmp("PLAY",c)==0) { - audacious_drct_play(); + aud_drct_play(); } else if(strcasecmp("STOP",c)==0) { - audacious_drct_stop(); + aud_drct_stop(); } else if(strcasecmp("PAUSE",c)==0) { - audacious_drct_pause(); + aud_drct_pause(); } else if(strcasecmp("PLAYPAUSE",c) == 0) { - if(audacious_drct_get_playing()) - audacious_drct_pause(); + if(aud_drct_get_playing()) + aud_drct_pause(); else - audacious_drct_play(); + aud_drct_play(); } else if(strncasecmp("NEXT",c,4)==0) { ptr=c+4; while(isspace(*ptr)) ptr++; n=atoi(ptr); - + if(n<=0) n=1; for(;n>0;n--) { - audacious_drct_pl_next(); + aud_drct_pl_next(); } } else if(strncasecmp("PREV",c,4)==0) @@ -181,34 +182,34 @@ void lirc_input_callback(gpointer data,gint source, ptr=c+4; while(isspace(*ptr)) ptr++; n=atoi(ptr); - + if(n<=0) n=1; for(;n>0;n--) { - audacious_drct_pl_prev(); + aud_drct_pl_prev(); } } else if(strcasecmp("SHUFFLE",c)==0) { - audacious_drct_pl_shuffle_toggle(); + aud_drct_pl_shuffle_toggle(); } else if(strcasecmp("REPEAT",c)==0) { - audacious_drct_pl_repeat_toggle(); + aud_drct_pl_repeat_toggle(); } else if(strncasecmp("FWD",c,3)==0) { ptr=c+3; while(isspace(*ptr)) ptr++; n=atoi(ptr)*1000; - + if(n<=0) n=5000; - output_time=audacious_drct_get_time(); - playlist_pos=audacious_drct_pl_get_pos(); - playlist_time=audacious_drct_pl_get_time(playlist_pos); + output_time=aud_drct_get_time(); + playlist_pos=aud_drct_pl_get_pos(); + playlist_time=aud_drct_pl_get_time(playlist_pos); if(playlist_time-output_time<n) output_time=playlist_time-n; - audacious_drct_seek(output_time+n); + aud_drct_seek(output_time+n); } else if(strncasecmp("BWD",c,3)==0) { @@ -217,10 +218,10 @@ void lirc_input_callback(gpointer data,gint source, n=atoi(ptr)*1000; if(n<=0) n=5000; - output_time=audacious_drct_get_time(); + output_time=aud_drct_get_time(); if(output_time<n) output_time=n; - audacious_drct_seek(output_time-n); + aud_drct_seek(output_time-n); } else if(strncasecmp("VOL_UP",c,6)==0) { @@ -229,24 +230,24 @@ void lirc_input_callback(gpointer data,gint source, n=atoi(ptr); if(n<=0) n=5; - audacious_drct_get_volume_main(&v); + aud_drct_get_volume_main(&v); if(v > (100-n)) v=100-n; - audacious_drct_set_volume_main(v+n); + aud_drct_set_volume_main(v+n); } else if(strncasecmp("VOL_DOWN",c,8)==0) - { + { ptr=c+8; while (isspace(*ptr)) ptr++; n=atoi(ptr); if(n<=0) n=5; - audacious_drct_get_volume_main(&v); + aud_drct_get_volume_main(&v); if(v<n) v=n; - audacious_drct_set_volume_main(v-n); + aud_drct_set_volume_main(v-n); } else if(strcasecmp("QUIT",c)==0) { - audacious_drct_quit(); + aud_drct_quit(); } else if(strcasecmp("MUTE",c)==0) { @@ -255,13 +256,13 @@ void lirc_input_callback(gpointer data,gint source, mute=1; /* store the master volume so we can restore it on unmute. */ - audacious_drct_get_volume_main(&mute_vol); - audacious_drct_set_volume_main(0); + aud_drct_get_volume_main(&mute_vol); + aud_drct_set_volume_main(0); } else { mute=0; - audacious_drct_set_volume_main(mute_vol); + aud_drct_set_volume_main(mute_vol); } } else if(strncasecmp("BAL_LEFT",c,8)==0) @@ -270,11 +271,11 @@ void lirc_input_callback(gpointer data,gint source, while(isspace(*ptr)) ptr++; n=atoi(ptr); if(n<=0) n=5; - - audacious_drct_get_volume_balance(&balance); + + aud_drct_get_volume_balance(&balance); balance-=n; if(balance<-100) balance=-100; - audacious_drct_set_volume_balance(balance); + aud_drct_set_volume_balance(balance); } else if(strncasecmp("BAL_RIGHT",c,9)==0) { @@ -283,44 +284,36 @@ void lirc_input_callback(gpointer data,gint source, n=atoi(ptr); if(n<=0) n=5; - audacious_drct_get_volume_balance(&balance); + aud_drct_get_volume_balance(&balance); balance+=n; if(balance>100) balance=100; - audacious_drct_set_volume_balance(balance); + aud_drct_set_volume_balance(balance); } else if(strcasecmp("BAL_CENTER",c)==0) { balance=0; - audacious_drct_set_volume_balance(balance); + aud_drct_set_volume_balance(balance); } else if(strcasecmp("LIST",c)==0) { - show_pl=audacious_drct_pl_win_is_visible(); +#if 0 + show_pl=aud_drct_pl_win_is_visible(); show_pl=(show_pl) ? 0:1; - audacious_drct_pl_win_toggle(show_pl); + aud_drct_pl_win_toggle(show_pl); +#endif } else if(strcasecmp("PLAYLIST_CLEAR",c)==0) { - gboolean pl_visible; - - pl_visible=audacious_drct_pl_win_is_visible(); - audacious_drct_stop(); - audacious_drct_pl_clear(); - /* This is to refresh window content */ - audacious_drct_pl_win_toggle(pl_visible); + aud_drct_stop(); + aud_drct_pl_clear(); } else if(strncasecmp("PLAYLIST_ADD ",c,13)==0) { - gboolean pl_visible; GList list; - - pl_visible=audacious_drct_pl_win_is_visible(); list.prev=list.next=NULL; list.data=c+13; - audacious_drct_pl_add(&list); - /* This is to refresh window content */ - audacious_drct_pl_win_toggle(pl_visible); - } + aud_drct_pl_add_list (& list, -1); + } else if((strlen(c)==1) && ((*c>='0') || (*c<='9'))) { if (track_no_pos<63) @@ -331,7 +324,7 @@ void lirc_input_callback(gpointer data,gint source, tid=g_timeout_add(1500, jump_to, NULL); utf8_title_markup = g_markup_printf_escaped( "<span font_desc='%s'>%s</span>", aosd_font, track_no); - aud_hook_call("aosd toggle", utf8_title_markup); + hook_call("aosd toggle", utf8_title_markup); } } else diff --git a/src/lirc/lirc_cfg.c b/src/lirc/lirc_cfg.c index 8b7347f..8636fc6 100644 --- a/src/lirc/lirc_cfg.c +++ b/src/lirc/lirc_cfg.c @@ -15,7 +15,7 @@ gchar *aosd_font = NULL; void load_cfg(void) { - ConfigDb *db; + mcs_handle_t *db; db = aud_cfg_db_open(); aud_cfg_db_get_int(db, LIRC_CFGID, "enable_reconnect", &b_enable_reconnect); aud_cfg_db_get_int(db, LIRC_CFGID, "reconnect_timeout", &reconnect_timeout); @@ -31,7 +31,7 @@ void load_cfg(void) void save_cfg(void) { - ConfigDb *db; + mcs_handle_t *db; db = aud_cfg_db_open(); aud_cfg_db_set_int(db, LIRC_CFGID, "enable_reconnect", b_enable_reconnect); aud_cfg_db_set_int(db, LIRC_CFGID, "reconnect_timeout", reconnect_timeout); diff --git a/src/lyricwiki/Makefile b/src/lyricwiki/Makefile new file mode 100644 index 0000000..14309ca --- /dev/null +++ b/src/lyricwiki/Makefile @@ -0,0 +1,12 @@ +PLUGIN = lyricwiki${PLUGIN_SUFFIX} + +SRCS = lyricwiki.c urlencode.c + +include ../../buildsys.mk +include ../../extra.mk + +plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR} + +CFLAGS += ${PLUGIN_CFLAGS} +CPPFLAGS += ${PLUGIN_CPPFLAGS} ${MOWGLI_CFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} ${ARCH_DEFINES} ${XML_CPPFLAGS} -I../.. +LIBS += ${GTK_LIBS} ${GLIB_LIBS} ${XML_LIBS} diff --git a/src/lyricwiki/lyricwiki.c b/src/lyricwiki/lyricwiki.c new file mode 100644 index 0000000..a54ff57 --- /dev/null +++ b/src/lyricwiki/lyricwiki.c @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2010 William Pitcock <nenolod@dereferenced.org> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * TODO: + * - do the VFS operations in another thread + * - why don't we have a url encoding function? + * ... or do we and I'm just smoking crack? + * - no idea what this code does if lyricwiki is down - probably crashes! + */ + +#include <stdio.h> +#include <glib.h> +#include <glib/gi18n.h> +#include <string.h> +#include <gtk/gtk.h> +#include <libxml/parser.h> +#include <libxml/tree.h> +#include <libxml/HTMLparser.h> +#include <libxml/xpath.h> +#include <mowgli.h> + +#include <audacious/drct.h> +#include <audacious/misc.h> +#include <audacious/playlist.h> +#include <audacious/plugin.h> +#include <audacious/plugins.h> +#include <libaudcore/hook.h> +#include <libaudcore/vfs_async.h> + +#include "urlencode.h" + +/* + * Suppress libxml warnings, because lyricwiki does not generate anything near + * valid HTML. + */ +void +libxml_error_handler(void *ctx, const char *msg, ...) +{ + +} + +/* Oh, this is going to be fun... */ +gchar * +scrape_lyrics_from_lyricwiki_edit_page(const gchar *buf, gsize len) +{ + xmlDocPtr doc; + gchar *ret = NULL; + + /* + * temporarily set our error-handling functor to our suppression function, + * but we have to set it back because other components of Audacious depend + * on libxml and we don't want to step on their code paths. + * + * unfortunately, libxml is anti-social and provides us with no way to get + * the previous error functor, so we just have to set it back to default after + * parsing and hope for the best. + */ + xmlSetGenericErrorFunc(NULL, libxml_error_handler); + doc = htmlReadMemory(buf, (int) len, NULL, "utf-8", (HTML_PARSE_RECOVER | HTML_PARSE_NONET)); + xmlSetGenericErrorFunc(NULL, NULL); + + if (doc != NULL) + { + xmlXPathContextPtr xpath_ctx = NULL; + xmlXPathObjectPtr xpath_obj = NULL; + xmlNodePtr node = NULL; + + xpath_ctx = xmlXPathNewContext(doc); + if (xpath_ctx == NULL) + goto give_up; + + xpath_obj = xmlXPathEvalExpression((xmlChar *) "//*[@id=\"wpTextbox1\"]", xpath_ctx); + if (xpath_obj == NULL) + goto give_up; + + if (!xpath_obj->nodesetval->nodeMax) + goto give_up; + + node = xpath_obj->nodesetval->nodeTab[0]; +give_up: + if (xpath_obj != NULL) + xmlXPathFreeObject(xpath_obj); + + if (xpath_ctx != NULL) + xmlXPathFreeContext(xpath_ctx); + + if (node != NULL) + { + xmlChar *lyric = xmlNodeGetContent(node); + + if (lyric != NULL) + { + GMatchInfo *match_info; + GRegex *reg; + + reg = g_regex_new("<(lyrics?)>(.*)</\\1>", (G_REGEX_MULTILINE | G_REGEX_DOTALL), 0, NULL); + g_regex_match(reg, (gchar *) lyric, G_REGEX_MATCH_NEWLINE_ANY, &match_info); + + ret = g_match_info_fetch(match_info, 2); + if (!g_utf8_collate(ret, "\n\n<!-- PUT LYRICS HERE (and delete this entire line) -->\n\n")) + { + g_free(ret); + ret = NULL; + } + } + + xmlFree(lyric); + } + } + + return ret; +} + +gchar * +scrape_uri_from_lyricwiki_search_result(const gchar *buf, gsize len) +{ + xmlDocPtr doc; + gchar *uri = NULL; + + /* + * temporarily set our error-handling functor to our suppression function, + * but we have to set it back because other components of Audacious depend + * on libxml and we don't want to step on their code paths. + * + * unfortunately, libxml is anti-social and provides us with no way to get + * the previous error functor, so we just have to set it back to default after + * parsing and hope for the best. + */ + xmlSetGenericErrorFunc(NULL, libxml_error_handler); + doc = xmlParseMemory(buf, (int) len); + xmlSetGenericErrorFunc(NULL, NULL); + + if (doc != NULL) + { + xmlNodePtr root, cur; + + root = xmlDocGetRootElement(doc); + + MOWGLI_ITER_FOREACH(cur, root->xmlChildrenNode) + { + if (xmlStrEqual(cur->name, (xmlChar *) "url")) + { + xmlChar *lyric; + gchar *basename; + + lyric = xmlNodeGetContent(cur); + basename = g_path_get_basename((gchar *) lyric); + + uri = g_strdup_printf("http://lyrics.wikia.com/index.php?action=edit&title=%s", basename); + g_free(basename); + xmlFree(lyric); + } + } + } + + return uri; +} + +void update_lyrics_window(const Tuple *tu, const gchar *lyrics); + +gboolean +get_lyrics_step_3(gchar *buf, gint64 len, Tuple *tu) +{ + gchar *lyrics = NULL; + + if (buf != NULL) + { + lyrics = scrape_lyrics_from_lyricwiki_edit_page(buf, len); + g_free(buf); + } + + update_lyrics_window(tu, lyrics); + mowgli_object_unref(tu); + + if (lyrics != NULL) + g_free(lyrics); + + return buf == NULL ? FALSE : TRUE; +} + +gboolean +get_lyrics_step_2(gchar *buf, gint64 len, Tuple *tu) +{ + gchar *uri; + + uri = scrape_uri_from_lyricwiki_search_result(buf, len); + + vfs_async_file_get_contents(uri, (VFSConsumer) get_lyrics_step_3, tu); + + g_free(buf); + + return TRUE; +} + +void +get_lyrics_step_1(const Tuple *tu) +{ + gchar *uri; + gchar *artist, *title; + Tuple *tuple = tuple_copy(tu); + + artist = lyricwiki_url_encode(tuple_get_string(tu, FIELD_ARTIST, NULL)); + title = lyricwiki_url_encode(tuple_get_string(tu, FIELD_TITLE, NULL)); + + uri = g_strdup_printf("http://lyrics.wikia.com/api.php?action=lyrics&artist=%s&song=%s&fmt=xml", artist, title); + + g_free(artist); + g_free(title); + + vfs_async_file_get_contents(uri, (VFSConsumer) get_lyrics_step_2, tuple); + + g_free(uri); +} + +GtkWidget *window, *textview; +GtkTextBuffer *textbuffer; + +static gboolean window_delete(); + +GtkWidget * +build_widget(void) +{ + GtkWidget *scrollview, *vbox; + + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(window), _("LyricWiki")); + gtk_window_set_default_size(GTK_WINDOW(window), 300, 500); + + textview = gtk_text_view_new(); + gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), FALSE); + gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(textview), FALSE); + gtk_text_view_set_left_margin(GTK_TEXT_VIEW(textview), 12); + gtk_text_view_set_right_margin(GTK_TEXT_VIEW(textview), 12); + gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(textview), GTK_WRAP_WORD); + textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); + + scrollview = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollview), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + vbox = gtk_vbox_new(FALSE, 10); + + gtk_container_add(GTK_CONTAINER(scrollview), textview); + + gtk_box_pack_start(GTK_BOX(vbox), scrollview, TRUE, TRUE, 0); + + gtk_container_add(GTK_CONTAINER(window), vbox); + + gtk_widget_show(textview); + gtk_widget_show(scrollview); + gtk_widget_show(vbox); + gtk_widget_show(window); + + gtk_text_buffer_create_tag(GTK_TEXT_BUFFER(textbuffer), "weight_bold", "weight", PANGO_WEIGHT_BOLD, NULL); + gtk_text_buffer_create_tag(GTK_TEXT_BUFFER(textbuffer), "size_x_large", "scale", PANGO_SCALE_X_LARGE, NULL); + gtk_text_buffer_create_tag(GTK_TEXT_BUFFER(textbuffer), "style_italic", "style", PANGO_STYLE_ITALIC, NULL); + + g_signal_connect(G_OBJECT(window), "delete-event", G_CALLBACK(window_delete), NULL); + + return window; +} + +void +clear_lyrics_window(void) +{ + GtkTextIter iter1, iter2; + + gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(textbuffer), &iter1); + gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(textbuffer), &iter2); + + gtk_text_buffer_delete(GTK_TEXT_BUFFER(textbuffer), &iter1, &iter2); +} + +void +update_lyrics_window(const Tuple *tu, const gchar *lyrics) +{ + GtkTextIter iter; + const gchar *artist, *title; + const gchar *real_lyrics; + gchar *f_name, *f_ext = NULL; + + if (textbuffer == NULL) + return; + + clear_lyrics_window(); + + gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(textbuffer), &iter); + + title = tuple_get_string(tu, FIELD_TITLE, NULL); + artist = tuple_get_string(tu, FIELD_ARTIST, NULL); + + if (title == NULL) + { + f_name = (gchar *) tuple_get_string(tu, FIELD_FILE_NAME, NULL); + f_ext = (gchar *) tuple_get_string(tu, FIELD_FILE_EXT, NULL); + + title = g_strdup(f_name); + + f_name = g_strrstr(title, f_ext); + if (f_name != NULL && f_name != title) + { + f_name--; + f_name[0] = '\0'; + } + } + gtk_text_buffer_insert_with_tags_by_name(GTK_TEXT_BUFFER(textbuffer), &iter, + title, strlen(title), "weight_bold", "size_x_large", NULL); + if (f_ext != NULL) + g_free((gpointer) title); + + gtk_text_buffer_insert(GTK_TEXT_BUFFER(textbuffer), &iter, "\n", 1); + + if (artist != NULL) + { + gtk_text_buffer_insert_with_tags_by_name(GTK_TEXT_BUFFER(textbuffer), + &iter, artist, strlen(artist), "style_italic", NULL); + + gtk_text_buffer_insert(GTK_TEXT_BUFFER(textbuffer), &iter, "\n", 1); + } + + real_lyrics = lyrics != NULL ? lyrics : _("\nNo lyrics were found."); + + gtk_text_buffer_insert(GTK_TEXT_BUFFER(textbuffer), &iter, real_lyrics, strlen(real_lyrics)); +} + +void +lyricwiki_playback_began(void) +{ + gint playlist, pos; + const Tuple *tu; + + if (!aud_drct_get_playing()) + return; + + playlist = aud_playlist_get_active(); + pos = aud_playlist_get_position(playlist); + tu = aud_playlist_entry_get_tuple (playlist, pos, FALSE); + + get_lyrics_step_1(tu); +} + +static void +init(void) +{ + hook_associate("playback begin", (HookFunction) lyricwiki_playback_began, NULL); + + build_widget(); + + lyricwiki_playback_began(); +} + +static void +cleanup(void) +{ + hook_dissociate("playback begin", (HookFunction) lyricwiki_playback_began); + + gtk_widget_destroy(window); + window = NULL; + textbuffer = NULL; +} + +GeneralPlugin lyricwiki = +{ + .description = "LyricWiki", + .init = init, + .cleanup = cleanup, +}; + +GeneralPlugin *lyricwiki_gplist[] = { &lyricwiki, NULL }; +SIMPLE_GENERAL_PLUGIN(lyricwiki, lyricwiki_gplist); + +static gboolean window_delete(void) +{ + aud_general_plugin_enable (aud_plugin_by_header (& lyricwiki), FALSE); + return TRUE; +} diff --git a/src/lyricwiki/urlencode.c b/src/lyricwiki/urlencode.c new file mode 100644 index 0000000..c6e5483 --- /dev/null +++ b/src/lyricwiki/urlencode.c @@ -0,0 +1,120 @@ +/* the original code was taken from wget-1.10.2 */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <glib.h> +#include <ctype.h> +#include "urlencode.h" + +enum { + /* rfc1738 reserved chars + "$" and ",". */ + urlchr_reserved = 1, + + /* rfc1738 unsafe chars, plus non-printables. */ + urlchr_unsafe = 2 +}; + +#define urlchr_test(c, mask) (urlchr_table[(unsigned char)(c)] & (mask)) +#define URL_RESERVED_CHAR(c) urlchr_test(c, urlchr_reserved) +#define URL_UNSAFE_CHAR(c) urlchr_test(c, urlchr_unsafe) +#define XNUM_TO_DIGIT(x) ("0123456789ABCDEF"[x] + 0) +#define ISXDIGIT(x) (isxdigit((unsigned char)(x))) +#define X2DIGITS_TO_NUM(h1, h2) ((XDIGIT_TO_NUM (h1) << 4) + XDIGIT_TO_NUM (h2)) +#define XDIGIT_TO_NUM(h) ((h) < 'A' ? (h) - '0' : toupper (h) - 'A' + 10) + +/* Shorthands for the table: */ +#define R urlchr_reserved +#define U urlchr_unsafe +#define RU R|U + +static const unsigned char urlchr_table[256] = +{ + U, U, U, U, U, U, U, U, /* NUL SOH STX ETX EOT ENQ ACK BEL */ + U, U, U, U, U, U, U, U, /* BS HT LF VT FF CR SO SI */ + U, U, U, U, U, U, U, U, /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */ + U, U, U, U, U, U, U, U, /* CAN EM SUB ESC FS GS RS US */ + U, 0, U, RU, R, U, R, 0, /* SP ! " # $ % & ' */ + 0, 0, 0, R, R, 0, 0, R, /* ( ) * + , - . / */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0 1 2 3 4 5 6 7 */ + 0, 0, RU, R, U, R, U, R, /* 8 9 : ; < = > ? */ + RU, 0, 0, 0, 0, 0, 0, 0, /* @ A B C D E F G */ + 0, 0, 0, 0, 0, 0, 0, 0, /* H I J K L M N O */ + 0, 0, 0, 0, 0, 0, 0, 0, /* P Q R S T U V W */ + 0, 0, 0, RU, U, RU, U, 0, /* X Y Z [ \ ] ^ _ */ + U, 0, 0, 0, 0, 0, 0, 0, /* ` a b c d e f g */ + 0, 0, 0, 0, 0, 0, 0, 0, /* h i j k l m n o */ + 0, 0, 0, 0, 0, 0, 0, 0, /* p q r s t u v w */ + 0, 0, 0, U, U, U, 0, U, /* x y z { | } ~ DEL */ + + U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, + U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, + U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, + U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, + + U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, + U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, + U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, + U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, +}; +#undef R +#undef U +#undef RU + +/* The core of url_escape_* functions. Escapes the characters that + match the provided mask in urlchr_table. + + If ALLOW_PASSTHROUGH is non-zero, a string with no unsafe chars + will be returned unchanged. If ALLOW_PASSTHROUGH is zero, a + freshly allocated string will be returned in all cases. */ + +static char * +url_escape_1 (const char *s, unsigned char mask, int allow_passthrough) +{ + const char *p1; + char *p2, *newstr; + int newlen; + int addition = 0; + + for (p1 = s; *p1; p1++) + if (urlchr_test (*p1, mask)) + addition += 2; /* Two more characters (hex digits) */ + + if (!addition) + return allow_passthrough ? (char *)s : strdup (s); + + newlen = (p1 - s) + addition; + newstr = (char *)g_malloc (newlen + 1); + + p1 = s; + p2 = newstr; + while (*p1) + { + /* Quote the characters that match the test mask. */ + if (urlchr_test (*p1, mask)) + { + unsigned char c = *p1++; + *p2++ = '%'; + *p2++ = XNUM_TO_DIGIT (c >> 4); + *p2++ = XNUM_TO_DIGIT (c & 0xf); + } + else + *p2++ = *p1++; + } + g_return_val_if_fail (p2 - newstr == newlen, NULL); + *p2 = '\0'; + + return newstr; +} + +/* URL-escape the unsafe characters (see urlchr_table) in a given + string, returning a freshly allocated string. */ + +char * +lyricwiki_url_encode (const char *s) +{ + if (s == NULL) + return g_strdup(""); + + return url_escape_1 (s, urlchr_unsafe, 0); +} diff --git a/src/lyricwiki/urlencode.h b/src/lyricwiki/urlencode.h new file mode 100644 index 0000000..86bbaef --- /dev/null +++ b/src/lyricwiki/urlencode.h @@ -0,0 +1,2 @@ +/* prototypes */ +char *lyricwiki_url_encode(const char *path); diff --git a/src/m3u/m3u.c b/src/m3u/m3u.c index 8f0d37c..55e255d 100644 --- a/src/m3u/m3u.c +++ b/src/m3u/m3u.c @@ -33,7 +33,11 @@ #include <sys/stat.h> #include <sys/errno.h> +#include <audacious/debug.h> +#include <audacious/misc.h> +#include <audacious/playlist.h> #include <audacious/plugin.h> +#include <libaudcore/audstrings.h> static void parse_extm3u_info(const gchar * info, gchar ** title, gint * length) @@ -48,7 +52,7 @@ parse_extm3u_info(const gchar * info, gchar ** title, gint * length) *title = NULL; *length = -1; - if (!aud_str_has_prefix_nocase(info, "#EXTINF:")) { + if (!str_has_prefix_nocase(info, "#EXTINF:")) { g_message("Invalid m3u metadata (%s)", info); return; } @@ -85,7 +89,7 @@ playlist_load_m3u(const gchar * filename, gint pos) uri = g_filename_to_uri(filename, NULL, NULL); - if ((file = aud_vfs_fopen(uri ? uri : filename, "rb")) == NULL) + if ((file = vfs_fopen(uri ? uri : filename, "rb")) == NULL) return; g_free(uri); uri = NULL; @@ -93,24 +97,24 @@ playlist_load_m3u(const gchar * filename, gint pos) add = index_new (); line = g_malloc(line_len); - while (aud_vfs_fgets(line, line_len, file)) { + while (vfs_fgets(line, line_len, file)) { while (strlen(line) == line_len - 1 && line[strlen(line) - 1] != '\n') { line_len += 1024; line = g_realloc(line, line_len); - aud_vfs_fgets(&line[strlen(line)], 1024, file); + vfs_fgets(&line[strlen(line)], 1024, file); } while (line[strlen(line) - 1] == '\r' || line[strlen(line) - 1] == '\n') line[strlen(line) - 1] = '\0'; - if (aud_str_has_prefix_nocase(line, "#EXTM3U")) { + if (str_has_prefix_nocase(line, "#EXTM3U")) { is_extm3u = TRUE; continue; } - if (is_extm3u && aud_str_has_prefix_nocase(line, "#EXTINF:")) { - aud_str_replace_in(&ext_info, g_strdup(line)); + if (is_extm3u && str_has_prefix_nocase(line, "#EXTINF:")) { + str_replace_in(&ext_info, g_strdup(line)); continue; } @@ -135,11 +139,11 @@ playlist_load_m3u(const gchar * filename, gint pos) if (uri != NULL) index_append (add, uri); - aud_str_replace_in(&ext_title, NULL); + str_replace_in(&ext_title, NULL); ext_len = -1; } - aud_vfs_fclose(file); + vfs_fclose(file); g_free(line); aud_playlist_entry_insert_batch (aud_playlist_get_active (), pos, add, NULL); @@ -158,7 +162,7 @@ playlist_save_m3u(const gchar *filename, gint pos) g_return_if_fail(filename != NULL); fn = g_filename_to_uri(filename, NULL, NULL); - file = aud_vfs_fopen(fn ? fn : filename, "wb"); + file = vfs_fopen(fn ? fn : filename, "wb"); g_free(fn); g_return_if_fail(file != NULL); @@ -166,28 +170,30 @@ playlist_save_m3u(const gchar *filename, gint pos) { const gchar * filename = aud_playlist_entry_get_filename (playlist, count); - const gchar * title = aud_playlist_entry_get_title (playlist, count); - gint seconds = aud_playlist_entry_get_length (playlist, count) / 1000; + const gchar * title = aud_playlist_entry_get_title (playlist, count, + FALSE); + gint seconds = aud_playlist_entry_get_length (playlist, count, FALSE) / + 1000; if (title != NULL) { outstr = g_locale_from_utf8 (title, -1, NULL, NULL, NULL); if(outstr) { - aud_vfs_fprintf(file, "#EXTINF:%d,%s\n", seconds, outstr); + vfs_fprintf(file, "#EXTINF:%d,%s\n", seconds, outstr); g_free(outstr); outstr = NULL; } else - aud_vfs_fprintf (file, "#EXTINF:%d,%s\n", seconds, title); + vfs_fprintf (file, "#EXTINF:%d,%s\n", seconds, title); } fn = g_filename_from_uri (filename, NULL, NULL); - aud_vfs_fprintf (file, "%s\n", fn != NULL ? fn : filename); + vfs_fprintf (file, "%s\n", fn != NULL ? fn : filename); g_free(fn); } - aud_vfs_fclose(file); + vfs_fclose(file); } PlaylistContainer plc_m3u = { diff --git a/src/metronom/metronom.c b/src/metronom/metronom.c index 595297e..908b012 100644 --- a/src/metronom/metronom.c +++ b/src/metronom/metronom.c @@ -18,10 +18,13 @@ */ #include "config.h" -#include <audacious/plugin.h> + #include <audacious/i18n.h> +#include <audacious/misc.h> +#include <audacious/plugin.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> + #include <glib.h> #define MIN_BPM 1 @@ -239,12 +242,12 @@ static void metronom_pause(InputPlayback * playback, short paused) static Tuple *metronom_get_song_tuple(const gchar * filename) { - Tuple *tuple = aud_tuple_new_from_filename(filename); + Tuple *tuple = tuple_new_from_filename(filename); metronom_t metronom; gchar *tmp = NULL; if (metronom_get_cp(filename, &metronom, &tmp)) - aud_tuple_associate_string(tuple, FIELD_TITLE, NULL, tmp); + tuple_associate_string(tuple, FIELD_TITLE, NULL, tmp); g_free(tmp); diff --git a/src/mms/mms.c b/src/mms/mms.c index c66f7f2..ec28174 100644 --- a/src/mms/mms.c +++ b/src/mms/mms.c @@ -41,7 +41,7 @@ typedef struct { } MMSHandle; VFSFile * -mms_aud_vfs_fopen_impl(const gchar * path, +mms_vfs_fopen_impl(const gchar * path, const gchar * mode) { VFSFile *file; @@ -72,7 +72,7 @@ mms_aud_vfs_fopen_impl(const gchar * path, } gint -mms_aud_vfs_fclose_impl(VFSFile * file) +mms_vfs_fclose_impl(VFSFile * file) { gint ret = 0; @@ -91,7 +91,7 @@ mms_aud_vfs_fclose_impl(VFSFile * file) return ret; } -gint64 mms_aud_vfs_fread_impl (void * ptr, gint64 size, gint64 nmemb, VFSFile * +gint64 mms_vfs_fread_impl (void * ptr, gint64 size, gint64 nmemb, VFSFile * file) { MMSHandle *handle; @@ -113,14 +113,14 @@ gint64 mms_aud_vfs_fread_impl (void * ptr, gint64 size, gint64 nmemb, VFSFile * return ret; } -gint64 mms_aud_vfs_fwrite_impl (const void * ptr, gint64 size, gint64 nmemb, +gint64 mms_vfs_fwrite_impl (const void * ptr, gint64 size, gint64 nmemb, VFSFile * file) { return 0; } gint -mms_aud_vfs_getc_impl(VFSFile *stream) +mms_vfs_getc_impl(VFSFile *stream) { MMSHandle *handle = (MMSHandle *) stream->handle; guchar c; @@ -141,7 +141,7 @@ mms_aud_vfs_getc_impl(VFSFile *stream) } gint -mms_aud_vfs_ungetc_impl(gint c, VFSFile *stream) +mms_vfs_ungetc_impl(gint c, VFSFile *stream) { MMSHandle *handle = (MMSHandle *) stream->handle; @@ -154,7 +154,7 @@ mms_aud_vfs_ungetc_impl(gint c, VFSFile *stream) } gint -mms_aud_vfs_fseek_impl(VFSFile * file, +mms_vfs_fseek_impl(VFSFile * file, glong offset, gint whence) { @@ -162,13 +162,13 @@ mms_aud_vfs_fseek_impl(VFSFile * file, } void -mms_aud_vfs_rewind_impl(VFSFile * file) +mms_vfs_rewind_impl(VFSFile * file) { return; } glong -mms_aud_vfs_ftell_impl(VFSFile * file) +mms_vfs_ftell_impl(VFSFile * file) { MMSHandle *handle = (MMSHandle *) file->handle; @@ -176,7 +176,7 @@ mms_aud_vfs_ftell_impl(VFSFile * file) } gboolean -mms_aud_vfs_feof_impl(VFSFile * file) +mms_vfs_feof_impl(VFSFile * file) { MMSHandle *handle = (MMSHandle *) file->handle; @@ -185,42 +185,42 @@ mms_aud_vfs_feof_impl(VFSFile * file) } gint -mms_aud_vfs_truncate_impl(VFSFile * file, glong size) +mms_vfs_truncate_impl(VFSFile * file, glong size) { return -1; } off_t -mms_aud_vfs_fsize_impl(VFSFile * file) +mms_vfs_fsize_impl(VFSFile * file) { return -1; } VFSConstructor mms_const = { "mms://", - mms_aud_vfs_fopen_impl, - mms_aud_vfs_fclose_impl, - mms_aud_vfs_fread_impl, - mms_aud_vfs_fwrite_impl, - mms_aud_vfs_getc_impl, - mms_aud_vfs_ungetc_impl, - mms_aud_vfs_fseek_impl, - mms_aud_vfs_rewind_impl, - mms_aud_vfs_ftell_impl, - mms_aud_vfs_feof_impl, - mms_aud_vfs_truncate_impl, - mms_aud_vfs_fsize_impl + mms_vfs_fopen_impl, + mms_vfs_fclose_impl, + mms_vfs_fread_impl, + mms_vfs_fwrite_impl, + mms_vfs_getc_impl, + mms_vfs_ungetc_impl, + mms_vfs_fseek_impl, + mms_vfs_rewind_impl, + mms_vfs_ftell_impl, + mms_vfs_feof_impl, + mms_vfs_truncate_impl, + mms_vfs_fsize_impl }; static void init(void) { - aud_vfs_register_transport(&mms_const); + vfs_register_transport(&mms_const); } static void cleanup(void) { #if 0 - aud_vfs_unregister_transport(&mms_const); + vfs_unregister_transport(&mms_const); #endif } diff --git a/src/modplug/archive/arch_raw.cxx b/src/modplug/archive/arch_raw.cxx index 8628cef..307d439 100644 --- a/src/modplug/archive/arch_raw.cxx +++ b/src/modplug/archive/arch_raw.cxx @@ -17,7 +17,7 @@ arch_Raw::arch_Raw(const string& aFileName) { - mFileDesc = aud_vfs_fopen(aFileName.c_str(), "rb"); + mFileDesc = vfs_fopen(aFileName.c_str(), "rb"); //open and mmap the file if(mFileDesc == NULL) @@ -25,12 +25,12 @@ arch_Raw::arch_Raw(const string& aFileName) mSize = 0; return; } - aud_vfs_fseek(mFileDesc, 0, SEEK_END); - mSize = aud_vfs_ftell(mFileDesc); - aud_vfs_fseek(mFileDesc, 0, SEEK_SET); + vfs_fseek(mFileDesc, 0, SEEK_END); + mSize = vfs_ftell(mFileDesc); + vfs_fseek(mFileDesc, 0, SEEK_SET); mMap = malloc(mSize); - aud_vfs_fread(mMap, 1, mSize, mFileDesc); + vfs_fread(mMap, 1, mSize, mFileDesc); } arch_Raw::~arch_Raw() @@ -38,7 +38,7 @@ arch_Raw::~arch_Raw() if(mSize != 0) { free(mMap); - aud_vfs_fclose(mFileDesc); + vfs_fclose(mFileDesc); } } diff --git a/src/modplug/modplugbmp.cxx b/src/modplug/modplugbmp.cxx index cff60fe..f1c784d 100644 --- a/src/modplug/modplugbmp.cxx +++ b/src/modplug/modplugbmp.cxx @@ -9,6 +9,10 @@ #include <unistd.h> #include <math.h> +extern "C" { +#include <audacious/configdb.h> +} + #include "modplugbmp.h" #include "stdafx.h" #include "sndfile.h" @@ -100,7 +104,7 @@ bool ModplugXMMS::CanPlayFileFromVFS(const string& aFilename, VFSFile *file) const int magicSize = 32; char magic[magicSize]; - aud_vfs_fread(magic, 1, magicSize, file); + vfs_fread(magic, 1, magicSize, file); if (!memcmp(magic, UMX_MAGIC, 4)) return true; if (!memcmp(magic, "Extended Module:", 16)) @@ -114,13 +118,13 @@ bool ModplugXMMS::CanPlayFileFromVFS(const string& aFilename, VFSFile *file) if (!memcmp(magic, PSM_MAGIC, 4)) return true; - aud_vfs_fseek(file, 44, SEEK_SET); - aud_vfs_fread(magic, 1, 4, file); + vfs_fseek(file, 44, SEEK_SET); + vfs_fread(magic, 1, 4, file); if (!memcmp(magic, S3M_MAGIC, 4)) return true; - aud_vfs_fseek(file, 1080, SEEK_SET); - aud_vfs_fread(magic, 1, 4, file); + vfs_fseek(file, 1080, SEEK_SET); + vfs_fread(magic, 1, 4, file); // Check for Fast Tracker multichannel modules (xCHN, xxCH) if (magic[1] == 'C' && magic[2] == 'H' && magic[3] == 'N') { @@ -468,7 +472,7 @@ Tuple* ModplugXMMS::GetSongTuple(const string& aFilename) return NULL; } - Tuple *ti = aud_tuple_new_from_filename(aFilename.c_str()); + Tuple *ti = tuple_new_from_filename(aFilename.c_str()); lSoundFile = new CSoundFile; lSoundFile->Create((uchar*)lArchive->Map(), lArchive->Size()); @@ -497,15 +501,15 @@ Tuple* ModplugXMMS::GetSongTuple(const string& aFilename) case MOD_TYPE_PSM: tmps = "Protracker Studio Module"; break; default: tmps = "ModPlug unknown"; break; } - aud_tuple_associate_string(ti, FIELD_CODEC, NULL, tmps); - aud_tuple_associate_string(ti, FIELD_QUALITY, NULL, "sequenced"); - aud_tuple_associate_int(ti, FIELD_LENGTH, NULL, lSoundFile->GetSongTime() * 1000); + tuple_associate_string(ti, FIELD_CODEC, NULL, tmps); + tuple_associate_string(ti, FIELD_QUALITY, NULL, "sequenced"); + tuple_associate_int(ti, FIELD_LENGTH, NULL, lSoundFile->GetSongTime() * 1000); gchar *tmps2 = MODPLUG_CONVERT(lSoundFile->GetTitle()); // Chop any leading spaces off. They are annoying in the playlist. gchar *tmps3 = tmps2; // Make another pointer so tmps2 can still be free()d while ( *tmps3 == ' ' ) tmps3++ ; - aud_tuple_associate_string(ti, FIELD_TITLE, NULL, tmps3); + tuple_associate_string(ti, FIELD_TITLE, NULL, tmps3); g_free(tmps2); //unload the file diff --git a/src/modplug/modplugbmp.h b/src/modplug/modplugbmp.h index c9c1380..3d545d1 100644 --- a/src/modplug/modplugbmp.h +++ b/src/modplug/modplugbmp.h @@ -110,7 +110,7 @@ private: Settings mModProps; - AFormat mFormat; + gint mFormat; uint32 mBufTime; //milliseconds diff --git a/src/modplug/plugin.cxx b/src/modplug/plugin.cxx index b6019b5..4efbbd6 100644 --- a/src/modplug/plugin.cxx +++ b/src/modplug/plugin.cxx @@ -8,6 +8,7 @@ #include "gui/main.h" extern "C" { +#include <audacious/debug.h> #include <audacious/plugin.h> diff --git a/src/mpg123/libmpg123/README b/src/mpg123/libmpg123/README index 7bbb01c..0e986a4 100644 --- a/src/mpg123/libmpg123/README +++ b/src/mpg123/libmpg123/README @@ -13,10 +13,14 @@ John Lindgren, June 9, 2010: * Imported libmpg123 1.10.0. * Removed some configuration stuff from mpg123.h.in and renamed it mpg123.h. * Added local config.h. - + John Lindgren, June 21, 2010: * Updated to libmpg123 1.12.2. +John Lindgren, July 16, 2010: + * Updated to libmpg123 1.12.3. + * Imported upstream revision 2760 (fixes an unused variable warning). + ====== * * * * * * * * * * * * * * * * * * * * * * * * * * * * diff --git a/src/mpg123/libmpg123/id3.c b/src/mpg123/libmpg123/id3.c index 30c3110..ef7e26a 100644 --- a/src/mpg123/libmpg123/id3.c +++ b/src/mpg123/libmpg123/id3.c @@ -536,7 +536,6 @@ int parse_new_id3(mpg123_handle *fr, unsigned long first4bytes) unsigned char flags = 0; int ret = 1; int ret2; - unsigned char* tagdata = NULL; unsigned char major = first4bytes & 0xff; debug1("ID3v2: major tag version: %i", major); if(major == 0xff) return 0; /* Invalid... */ @@ -599,6 +598,7 @@ int parse_new_id3(mpg123_handle *fr, unsigned long first4bytes) } else { + unsigned char* tagdata = NULL; fr->id3v2.version = major; /* try to interpret that beast */ if((tagdata = (unsigned char*) malloc(length+1)) != NULL) diff --git a/src/mpg123/libmpg123/mpg123.h b/src/mpg123/libmpg123/mpg123.h index fa2fa26..0ff1f35 100644 --- a/src/mpg123/libmpg123/mpg123.h +++ b/src/mpg123/libmpg123/mpg123.h @@ -1,5 +1,5 @@ /* - libmpg123: MPEG Audio Decoder library (version 1.12.2) + libmpg123: MPEG Audio Decoder library (version 1.12.3) copyright 1995-2009 by the mpg123 project - free software under the terms of the LGPL 2.1 see COPYING and AUTHORS files in distribution or http://mpg123.org diff --git a/src/mpg123/libmpg123/readers.c b/src/mpg123/libmpg123/readers.c index 9bf19f0..1233456 100644 --- a/src/mpg123/libmpg123/readers.c +++ b/src/mpg123/libmpg123/readers.c @@ -121,7 +121,7 @@ static ssize_t icy_fullread(mpg123_handle *fr, unsigned char *buf, ssize_t count if(fr->icy.next > 0) { cut_pos = fr->icy.next; - ret = fr->rdat.fdread(fr,buf,cut_pos); + ret = fr->rdat.fdread(fr,buf+cnt,cut_pos); if(ret < 1) { if(ret == 0) break; /* Just EOF. */ @@ -129,7 +129,8 @@ static ssize_t icy_fullread(mpg123_handle *fr, unsigned char *buf, ssize_t count return READER_ERROR; } - fr->rdat.filepos += ret; + + if(!(fr->rdat.flags & READER_BUFFERED)) fr->rdat.filepos += ret; cnt += ret; fr->icy.next -= ret; if(fr->icy.next > 0) diff --git a/src/mpg123/mpg123.c b/src/mpg123/mpg123.c index 87925c4..01a1f34 100644 --- a/src/mpg123/mpg123.c +++ b/src/mpg123/mpg123.c @@ -26,17 +26,22 @@ # define MPG123_IODBG(...) do { } while (0) #endif +#include <libaudcore/audstrings.h> +#include <audacious/debug.h> +#include <audacious/i18n.h> #include <audacious/plugin.h> #include <audacious/audtag.h> #include "libmpg123/mpg123.h" +/* Define to read all frame headers when calculating file length */ +/* #define FULL_SCAN */ + /* id3skip.c */ gint id3_header_size (const guchar * data, gint size); static GMutex *ctrl_mutex = NULL; static GCond *ctrl_cond = NULL; -static gboolean pause_flag; /** utility functions **/ static gboolean mpg123_prefill (mpg123_handle * decoder, VFSFile * handle, @@ -48,7 +53,7 @@ static gboolean mpg123_prefill (mpg123_handle * decoder, VFSFile * handle, do { - if ((length = aud_vfs_fread (buffer, 1, 16384, handle)) <= 0) + if ((length = vfs_fread (buffer, 1, 16384, handle)) <= 0) return FALSE; result = mpg123_decode (decoder, buffer, length, NULL, 0, NULL); @@ -62,88 +67,14 @@ static gboolean mpg123_prefill (mpg123_handle * decoder, VFSFile * handle, return TRUE; } -static gint -mpg123_get_length(VFSFile *fd) +static ssize_t replace_read (void * file, void * buffer, size_t length) { - mpg123_handle *decoder; - mpg123_pars *params; - const glong *rates; - gsize num_rates; - gint ret; - gint i; - glong rate; - gint channels, encoding; - gint samples; - - g_return_val_if_fail(fd != NULL, -2); - - AUDDBG("starting probe of %s\n", fd->uri); - - mpg123_rates(&rates, &num_rates); - - params = mpg123_new_pars(&ret); - g_return_val_if_fail(params != NULL, -2); - - mpg123_par(params, MPG123_ADD_FLAGS, MPG123_QUIET, 0); - mpg123_par(params, MPG123_ADD_FLAGS, MPG123_GAPLESS, 0); - mpg123_par(params, MPG123_ADD_FLAGS, MPG123_SEEKBUFFER, 0); - mpg123_par(params, MPG123_RVA, MPG123_RVA_OFF, 0); - - decoder = mpg123_parnew(params, NULL, &ret); - if (decoder == NULL) - { - AUDDBG("mpg123 error: %s", mpg123_plain_strerror(ret)); - mpg123_delete_pars(params); - return -2; - } - - if ((ret = mpg123_open_feed(decoder)) != MPG123_OK) - { - AUDDBG("mpg123 error: %s", mpg123_plain_strerror(ret)); - mpg123_delete(decoder); - mpg123_delete_pars(params); - return -2; - } - - mpg123_format_none(decoder); - for (i = 0; i < num_rates; i++) - mpg123_format(decoder, rates[i], (MPG123_MONO | MPG123_STEREO), MPG123_ENC_SIGNED_16); - - if (! mpg123_prefill (decoder, fd, & ret) || ret != MPG123_NEW_FORMAT) - { - mpg123_delete(decoder); - mpg123_delete_pars(params); - return -2; - } - - mpg123_getformat(decoder, &rate, &channels, &encoding); - - AUDDBG("stream identified as MPEG; %ldHz %d channels, encoding %d\n", - rate, channels, encoding); - - if (aud_vfs_is_streaming(fd)) - { - mpg123_delete(decoder); - mpg123_delete_pars(params); - return -1; - } - - mpg123_scan(decoder); - samples = mpg123_length(decoder); - - if (samples <= 0) - { - off_t filesize = vfs_fsize(fd); - mpg123_set_filesize(decoder, filesize); - samples = mpg123_length(decoder); - } - - mpg123_delete(decoder); - mpg123_delete_pars(params); - - AUDDBG("song has %d samples; length %ld seconds\n", samples, (samples / rate)); + return vfs_fread (buffer, 1, length, file); +} - return samples * (gint64) 1000 / rate; +static off_t replace_lseek (void * file, off_t to, int whence) +{ + return (! vfs_fseek (file, to, whence)) ? vfs_ftell (file) : -1; } /** plugin glue **/ @@ -183,17 +114,17 @@ static gboolean mpg123_probe_for_fd (const gchar * filename, VFSFile * handle) if (mpg123_open_feed (decoder) < 0) goto ERROR_FREE; - if (aud_vfs_fread (buffer, 1, sizeof buffer, handle) != sizeof buffer) + if (vfs_fread (buffer, 1, sizeof buffer, handle) != sizeof buffer) goto ERROR_FREE; if ((result = id3_header_size (buffer, sizeof buffer)) > 0) { AUDDBG ("Skip %d bytes of ID3 tag.\n", result); - if (aud_vfs_fseek (handle, result, SEEK_SET)) + if (vfs_fseek (handle, result, SEEK_SET)) goto ERROR_FREE; - if (aud_vfs_fread (buffer, 1, sizeof buffer, handle) != sizeof buffer) + if (vfs_fread (buffer, 1, sizeof buffer, handle) != sizeof buffer) goto ERROR_FREE; } @@ -213,78 +144,64 @@ ERROR_FREE: return FALSE; } -static gboolean mpg123_get_info (VFSFile * handle, struct mpg123_frameinfo * - info) +static Tuple * mpg123_probe_for_tuple (const gchar * filename, VFSFile * file) { + static const gchar * versions[] = {"1", "2", "2.5"}; + mpg123_handle * decoder = mpg123_new (NULL, NULL); gint result; + glong rate; + gint channels, encoding; + struct mpg123_frameinfo info; + gchar scratch[32]; - g_return_val_if_fail (decoder != NULL, FALSE); - - /* Turn off annoying messages. */ + g_return_val_if_fail (decoder, NULL); mpg123_param (decoder, MPG123_ADD_FLAGS, MPG123_QUIET, 0); + mpg123_replace_reader_handle (decoder, replace_read, replace_lseek, NULL); + + if ((result = mpg123_open_handle (decoder, file)) < 0) + goto ERROR; + if ((result = mpg123_getformat (decoder, & rate, & channels, & encoding)) < + 0) + goto ERROR; + if ((result = mpg123_info (decoder, & info)) < 0) + goto ERROR; + + Tuple * tuple = tuple_new_from_filename (filename); + snprintf (scratch, sizeof scratch, "MPEG-%s layer %d", + versions[info.version], info.layer); + tuple_associate_string (tuple, FIELD_CODEC, NULL, scratch); + snprintf (scratch, sizeof scratch, "%s, %d Hz", (channels == 2) + ? _("Stereo") : (channels > 2) ? _("Surround") : _("Mono"), (gint) rate); + tuple_associate_string (tuple, FIELD_QUALITY, NULL, scratch); + tuple_associate_int (tuple, FIELD_BITRATE, NULL, info.bitrate); + + if (! vfs_is_streaming (file)) + { + gint64 size = vfs_fsize (file); + gint64 samples = mpg123_length (decoder); + gint length = (samples > 0) ? samples * 1000 / rate : 0; + + if (length > 0) + tuple_associate_int (tuple, FIELD_LENGTH, NULL, length); + if (size > 0 && length > 0) + tuple_associate_int (tuple, FIELD_BITRATE, NULL, 8 * size / length); + } - if (mpg123_open_feed (decoder) < 0) - goto ERROR_FREE; - - if (! mpg123_prefill (decoder, handle, & result) || result != - MPG123_NEW_FORMAT) - goto ERROR_FREE; - - if (mpg123_info (decoder, info) < 0) - goto ERROR_FREE; - - mpg123_delete (decoder); - return TRUE; - -ERROR_FREE: mpg123_delete (decoder); - return FALSE; -} - -static Tuple * -mpg123_probe_for_tuple(const gchar *filename, VFSFile *fd) -{ - struct mpg123_frameinfo info; - Tuple *tu; - gint len; - gsize size; - - AUDDBG("starting probe of %p\n", fd); - - aud_vfs_fseek(fd, 0, SEEK_SET); - len = mpg123_get_length(fd); - - if (len == -2) - return NULL; - - tu = aud_tuple_new_from_filename(filename); - - aud_vfs_fseek (fd, 0, SEEK_SET); - if (mpg123_get_info (fd, & info)) + if (! vfs_is_streaming (file)) { - static const gchar * versions[] = {"1", "2", "2.5"}; - gchar format[32]; - - snprintf (format, sizeof format, "MPEG-%s layer %d", - versions[info.version], info.layer); - tuple_associate_string (tu, FIELD_CODEC, NULL, format); + vfs_fseek (file, 0, SEEK_SET); + tag_tuple_read (tuple, file); } - aud_vfs_fseek(fd, 0, SEEK_SET); - tag_tuple_read(tu, fd); - - if (tuple_get_int(tu, FIELD_LENGTH, NULL) == 0) - tuple_associate_int (tu, FIELD_LENGTH, NULL, len); - - size = aud_vfs_fsize (fd); - - if (size > 0 && len > 0) - tuple_associate_int (tu, FIELD_BITRATE, NULL, 8 * size / len); + return tuple; - AUDDBG("returning tuple %p for file %p\n", tu, fd); - return tu; +ERROR: + fprintf (stderr, "mpg123 error: %s\n", mpg123_plain_strerror (result)); + mpg123_delete (decoder); + return NULL; } typedef struct { @@ -302,8 +219,8 @@ typedef struct { static gchar * get_stream_metadata(VFSFile *file, const gchar *name) { - gchar *raw = aud_vfs_get_metadata(file, name); - gchar *converted = (raw != NULL && raw[0]) ? aud_str_to_utf8(raw) : NULL; + gchar *raw = vfs_get_metadata(file, name); + gchar *converted = (raw != NULL && raw[0]) ? str_to_utf8(raw) : NULL; g_free(raw); return converted; @@ -312,19 +229,19 @@ get_stream_metadata(VFSFile *file, const gchar *name) static gboolean update_stream_metadata(VFSFile *file, const gchar *name, Tuple *tuple, gint item) { - const gchar *old = aud_tuple_get_string(tuple, item, NULL); + const gchar *old = tuple_get_string(tuple, item, NULL); gchar *new = get_stream_metadata(file, name); gboolean changed = (new != NULL && (old == NULL || strcmp(old, new))); if (changed) - aud_tuple_associate_string(tuple, item, NULL, new); + tuple_associate_string(tuple, item, NULL, new); g_free(new); return changed; } -static void -mpg123_playback_worker(InputPlayback *data) +static gboolean mpg123_playback_worker (InputPlayback * data, const gchar * + filename, VFSFile * file, gint start_time, gint stop_time, gboolean pause) { MPG123PlaybackContext ctx; gint ret; @@ -333,7 +250,6 @@ mpg123_playback_worker(InputPlayback *data) gsize num_rates; gint bitrate = 0, bitrate_sum = 0, bitrate_count = 0; gint bitrate_updated = -1000; /* >= a second away from any position */ - gboolean paused = FALSE; struct mpg123_frameinfo fi; gint error_count = 0; @@ -342,7 +258,7 @@ mpg123_playback_worker(InputPlayback *data) AUDDBG("playback worker started for %s\n", data->filename); - ctx.seek = -1; + ctx.seek = (start_time > 0) ? start_time : -1; data->data = &ctx; AUDDBG("decoder setup\n"); @@ -359,7 +275,8 @@ mpg123_playback_worker(InputPlayback *data) { AUDDBG("mpg123 error: %s", mpg123_plain_strerror(ret)); mpg123_delete_pars(ctx.params); - return; + data->error = TRUE; + return FALSE; } if ((ret = mpg123_open_feed(ctx.decoder)) != MPG123_OK) @@ -367,7 +284,8 @@ mpg123_playback_worker(InputPlayback *data) AUDDBG("mpg123 error: %s", mpg123_plain_strerror(ret)); mpg123_delete(ctx.decoder); mpg123_delete_pars(ctx.params); - return; + data->error = TRUE; + return FALSE; } AUDDBG("decoder format configuration\n"); @@ -376,11 +294,10 @@ mpg123_playback_worker(InputPlayback *data) mpg123_format (ctx.decoder, rates[i], (MPG123_MONO | MPG123_STEREO), MPG123_ENC_SIGNED_16); - ctx.fd = aud_vfs_fopen(data->filename, "r"); - AUDDBG("opened stream transport @%p\n", ctx.fd); + ctx.fd = file; AUDDBG("checking if stream @%p is seekable\n", ctx.fd); - if (aud_vfs_is_streaming(ctx.fd)) + if (vfs_is_streaming(ctx.fd)) { AUDDBG(" ... it's not.\n"); ctx.stream = TRUE; @@ -391,7 +308,10 @@ mpg123_playback_worker(InputPlayback *data) AUDDBG("decoder format identification\n"); if (! mpg123_prefill (ctx.decoder, ctx.fd, & ret) || ret != MPG123_NEW_FORMAT) + { + data->error = TRUE; goto cleanup; + } mpg123_getformat(ctx.decoder, &ctx.rate, &ctx.channels, &ctx.encoding); @@ -400,7 +320,13 @@ mpg123_playback_worker(InputPlayback *data) AUDDBG("opening audio\n"); if (! data->output->open_audio (FMT_S16_NE, ctx.rate, ctx.channels)) + { + data->error = TRUE; goto cleanup; + } + + if (pause) + data->output->pause (TRUE); data->set_gain_from_playlist (data); @@ -409,11 +335,11 @@ mpg123_playback_worker(InputPlayback *data) AUDDBG("starting decode\n"); data->playing = TRUE; data->set_pb_ready(data); - pause_flag = FALSE; g_mutex_unlock(ctrl_mutex); - while (data->playing == TRUE) + while (data->playing && (stop_time < 0 || data->output->written_time () < + stop_time)) { gint16 outbuf[ctx.channels * (ctx.rate / 100)]; gsize outbuf_size; @@ -439,7 +365,7 @@ mpg123_playback_worker(InputPlayback *data) gboolean changed = FALSE; if (!ctx.tu) - ctx.tu = aud_tuple_new_from_filename(data->filename); + ctx.tu = tuple_new_from_filename(data->filename); changed = changed || update_stream_metadata(ctx.fd, "track-name", ctx.tu, FIELD_TITLE); changed = changed || update_stream_metadata(ctx.fd, "stream-name", ctx.tu, FIELD_ALBUM); @@ -460,7 +386,7 @@ mpg123_playback_worker(InputPlayback *data) { MPG123_IODBG("mpg123 requested more data\n"); - len = aud_vfs_fread(buf, 1, 16384, ctx.fd); + len = vfs_fread(buf, 1, 16384, ctx.fd); if (len <= 0) { if (len == 0) @@ -489,9 +415,12 @@ mpg123_playback_worker(InputPlayback *data) if (ret < 0) { fprintf (stderr, "mpg123 error: %s\n", mpg123_plain_strerror (ret)); - + if (++ error_count >= 10) + { + data->error = TRUE; goto decode_cleanup; + } } else error_count = 0; @@ -508,7 +437,8 @@ mpg123_playback_worker(InputPlayback *data) { off_t byteoff, sampleoff; - sampleoff = mpg123_feedseek(ctx.decoder, (ctx.seek * ctx.rate), SEEK_SET, &byteoff); + sampleoff = mpg123_feedseek (ctx.decoder, (gint64) ctx.seek * + ctx.rate / 1000, SEEK_SET, & byteoff); if (sampleoff < 0) { fprintf (stderr, "mpg123 error: %s\n", mpg123_strerror (ctx.decoder)); @@ -519,27 +449,13 @@ mpg123_playback_worker(InputPlayback *data) } AUDDBG("seeking to %ld (byte %ld)\n", ctx.seek, byteoff); - data->output->flush(ctx.seek * 1000); - aud_vfs_fseek(ctx.fd, byteoff, SEEK_SET); + data->output->flush (ctx.seek); + vfs_fseek(ctx.fd, byteoff, SEEK_SET); ctx.seek = -1; g_cond_signal(ctrl_cond); } - if (pause_flag != paused) - { - data->output->pause(pause_flag); - paused = pause_flag; - g_cond_signal(ctrl_cond); - } - - if (paused) - { - g_cond_wait(ctrl_cond, ctrl_mutex); - g_mutex_unlock(ctrl_mutex); - continue; - } - g_mutex_unlock(ctrl_mutex); } @@ -549,64 +465,59 @@ decode_cleanup: g_usleep(10000); AUDDBG("decode complete\n"); + g_mutex_lock (ctrl_mutex); + data->playing = FALSE; + g_cond_signal (ctrl_cond); /* wake up any waiting request */ + g_mutex_unlock (ctrl_mutex); + data->output->close_audio(); cleanup: mpg123_delete(ctx.decoder); mpg123_delete_pars(ctx.params); - aud_vfs_fclose(ctx.fd); - - data->playing = FALSE; + return ! data->error; } -static void -mpg123_stop_playback_worker(InputPlayback *data) +static void mpg123_stop_playback_worker (InputPlayback * data) { - AUDDBG("signalling playback worker to die\n"); - g_mutex_lock(ctrl_mutex); - data->playing = FALSE; - g_cond_signal(ctrl_cond); - g_mutex_unlock(ctrl_mutex); + g_mutex_lock (ctrl_mutex); - AUDDBG("waiting for playback worker to die\n"); - g_thread_join(data->thread); - data->thread = NULL; + if (data->playing) + { + data->output->abort_write (); + data->playing = FALSE; + g_cond_signal (ctrl_cond); + } - AUDDBG("playback worker died\n"); + g_mutex_unlock (ctrl_mutex); } -static void -mpg123_pause_playback_worker(InputPlayback *data, gshort p) +static void mpg123_pause_playback_worker (InputPlayback * data, gshort pause) { - g_mutex_lock(ctrl_mutex); + g_mutex_lock (ctrl_mutex); if (data->playing) - { - pause_flag = p; - g_cond_signal(ctrl_cond); - g_cond_wait(ctrl_cond, ctrl_mutex); - } + data->output->pause (pause); - g_mutex_unlock(ctrl_mutex); + g_mutex_unlock (ctrl_mutex); } -static void -mpg123_seek_time(InputPlayback *data, gint time) +static void mpg123_seek_time (InputPlayback * data, gulong time) { - g_mutex_lock(ctrl_mutex); + g_mutex_lock (ctrl_mutex); if (data->playing) { - MPG123PlaybackContext *ctx = data->data; - ctx->seek = time; - g_cond_signal(ctrl_cond); - g_cond_wait(ctrl_cond, ctrl_mutex); + ((MPG123PlaybackContext *) data->data)->seek = time; + data->output->abort_write (); + g_cond_signal (ctrl_cond); + g_cond_wait (ctrl_cond, ctrl_mutex); } - g_mutex_unlock(ctrl_mutex); + g_mutex_unlock (ctrl_mutex); } -static gboolean mpg123_write_tag (Tuple * tuple, VFSFile * handle) +static gboolean mpg123_write_tag (const Tuple * tuple, VFSFile * handle) { return tag_tuple_write (tuple, handle, TAG_TYPE_APE); } @@ -614,7 +525,7 @@ static gboolean mpg123_write_tag (Tuple * tuple, VFSFile * handle) static gboolean mpg123_get_image (const gchar * filename, VFSFile * handle, void * * data, gint * length) { - if (handle == NULL) + if (handle == NULL || vfs_is_streaming (handle)) return FALSE; return tag_image_read (handle, data, length); @@ -630,9 +541,9 @@ static InputPlugin mpg123_ip = { .vfs_extensions = (gchar **) mpg123_fmts, .is_our_file_from_vfs = mpg123_probe_for_fd, .probe_for_tuple = mpg123_probe_for_tuple, - .play_file = mpg123_playback_worker, + .play = mpg123_playback_worker, .stop = mpg123_stop_playback_worker, - .seek = mpg123_seek_time, + .mseek = mpg123_seek_time, .pause = mpg123_pause_playback_worker, .update_song_tuple = mpg123_write_tag, .get_song_image = mpg123_get_image, diff --git a/src/mtp_up/mtp.c b/src/mtp_up/mtp.c index 4d04bd1..155c428 100644 --- a/src/mtp_up/mtp.c +++ b/src/mtp_up/mtp.c @@ -2,7 +2,7 @@ * Audacious MTP upload plugin * * Copyright (c) 2007 Cristian Magherusan <majeru@atheme.org> - * + * * 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; under version 3 of the License. @@ -21,9 +21,11 @@ #include <glib.h> #include <sys/types.h> #include <libmtp.h> -#include <audacious/plugin.h> -#include <audacious/ui_plugin_menu.h> + #include <audacious/i18n.h> +#include <audacious/misc.h> +#include <audacious/playlist.h> +#include <audacious/plugin.h> #include <gtk/gtk.h> #include "filetype.h" @@ -32,7 +34,7 @@ #define UP_DEFAULT_LABEL _("Upload selected track(s)") -GMutex * mutex = NULL; +GMutex * mutex = NULL; gboolean mtp_initialised = FALSE; LIBMTP_mtpdevice_t *mtp_device = NULL; LIBMTP_progressfunc_t *callback; @@ -92,13 +94,13 @@ gboolean free_device(void) gtk_widget_hide(mtp_submenu_item_free); } g_mutex_unlock(mutex); - return TRUE; + return TRUE; } GList * get_upload_list(void) { - Tuple *tuple; + const Tuple * tuple; GList *up_list=NULL; gint current_play = aud_playlist_get_active(); gint i = (aud_playlist_entry_count(current_play) - 1); @@ -107,9 +109,9 @@ get_upload_list(void) { if (aud_playlist_entry_get_selected(current_play, i)) { - tuple = aud_playlist_entry_get_tuple(current_play, i); + tuple = aud_playlist_entry_get_tuple (current_play, i, FALSE); aud_playlist_entry_set_selected(current_play, i, FALSE); - up_list = g_list_prepend(up_list, tuple); + up_list = g_list_prepend (up_list, (void *) tuple); } } @@ -125,27 +127,27 @@ LIBMTP_track_t *track_metadata(Tuple *from_tuple) uint32_t parent_id = 0; struct stat sb; - uri_path = g_strdup_printf("%s/%s", aud_tuple_get_string(from_tuple, FIELD_FILE_PATH, NULL), aud_tuple_get_string(from_tuple, FIELD_FILE_NAME, NULL)); + uri_path = g_strdup_printf("%s/%s", tuple_get_string(from_tuple, FIELD_FILE_PATH, NULL), tuple_get_string(from_tuple, FIELD_FILE_NAME, NULL)); gchar *tmp = g_strescape(uri_path,NULL); filename=g_filename_from_uri(tmp,NULL,NULL); - g_free(tmp); + g_free(tmp); /* dealing the stream upload (invalidating)*/ if(filename) { - f = aud_vfs_fopen(uri_path,"r"); + f = vfs_fopen(uri_path,"r"); g_free(uri_path); - if(aud_vfs_is_streaming(f)) + if(vfs_is_streaming(f)) { - aud_vfs_fclose(f); + vfs_fclose(f); g_free(filename); return NULL; } - } - else + } + else { g_print("Warning! the filename is NULL, exiting"); return NULL; - + } if ( stat(filename, &sb) == -1 ) @@ -161,15 +163,15 @@ LIBMTP_track_t *track_metadata(Tuple *from_tuple) /* track metadata*/ tr = LIBMTP_new_track_t(); - tr->title = g_strdup((gchar*) aud_tuple_get_string(from_tuple, FIELD_TITLE, NULL)); - tr->artist = g_strdup((gchar*) aud_tuple_get_string(from_tuple, FIELD_ARTIST, NULL)); - tr->album = g_strdup((gchar*)aud_tuple_get_string(from_tuple, FIELD_ALBUM, NULL)); + tr->title = g_strdup((gchar*) tuple_get_string(from_tuple, FIELD_TITLE, NULL)); + tr->artist = g_strdup((gchar*) tuple_get_string(from_tuple, FIELD_ARTIST, NULL)); + tr->album = g_strdup((gchar*)tuple_get_string(from_tuple, FIELD_ALBUM, NULL)); tr->filesize = filesize; - tr->filename = g_strdup(aud_tuple_get_string(from_tuple, FIELD_FILE_NAME, NULL)); - tr->duration = (uint32_t)aud_tuple_get_int(from_tuple, FIELD_LENGTH, NULL); + tr->filename = g_strdup(tuple_get_string(from_tuple, FIELD_FILE_NAME, NULL)); + tr->duration = (uint32_t)tuple_get_int(from_tuple, FIELD_LENGTH, NULL); tr->filetype = find_filetype (filename); - tr->genre = g_strdup((gchar*)aud_tuple_get_string(from_tuple, FIELD_GENRE, NULL)); - tr->date = g_strdup_printf("%d",aud_tuple_get_int(from_tuple, FIELD_YEAR, NULL)); + tr->genre = g_strdup((gchar*)tuple_get_string(from_tuple, FIELD_GENRE, NULL)); + tr->date = g_strdup_printf("%d",tuple_get_int(from_tuple, FIELD_YEAR, NULL)); g_free(filename); return tr; } @@ -178,10 +180,9 @@ gint upload_file(Tuple *from_tuple) { int ret; gchar *tmp, *from_path = NULL, *filename; - uint32_t parent_id = 0; LIBMTP_track_t *gentrack; gentrack = track_metadata(from_tuple); - from_path = g_strdup_printf("%s/%s", aud_tuple_get_string(from_tuple, FIELD_FILE_PATH, NULL), aud_tuple_get_string(from_tuple, FIELD_FILE_NAME, NULL)); + from_path = g_strdup_printf("%s/%s", tuple_get_string(from_tuple, FIELD_FILE_PATH, NULL), tuple_get_string(from_tuple, FIELD_FILE_NAME, NULL)); if(gentrack == NULL) return 1; tmp = g_strescape(from_path,NULL); filename=g_filename_from_uri(tmp,NULL,NULL); @@ -195,7 +196,7 @@ gint upload_file(Tuple *from_tuple) gentrack->parent_id = mtp_device->default_music_folder; ret = LIBMTP_Send_Track_From_File(mtp_device, filename , gentrack, NULL , NULL); LIBMTP_destroy_track_t(gentrack); - if (ret == 0) + if (ret == 0) g_print("Track upload finished!\n"); else { @@ -217,13 +218,13 @@ gpointer upload(gpointer arg) gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(mtp_submenu_item_up))),UP_DEFAULT_LABEL); gtk_widget_set_sensitive(mtp_submenu_item_up, TRUE); return NULL; - } - g_mutex_lock(mutex); + } + g_mutex_lock(mutex); if(!mtp_device) - { + { gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(mtp_submenu_item_up))),UP_DEFAULT_LABEL); gtk_widget_set_sensitive(mtp_submenu_item_up, TRUE); - g_mutex_unlock(mutex); + g_mutex_unlock(mutex); return NULL; } @@ -251,10 +252,10 @@ gpointer upload(gpointer arg) g_list_free(up_list); gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(mtp_submenu_item_up))),UP_DEFAULT_LABEL); gtk_widget_set_sensitive(mtp_submenu_item_up, TRUE); - g_mutex_unlock(mutex); + g_mutex_unlock(mutex); #if DEBUG g_print("MTP upload process finished\n"); -#endif +#endif gtk_widget_show(mtp_submenu_item_free); g_thread_exit(NULL); return NULL; @@ -262,7 +263,7 @@ gpointer upload(gpointer arg) gboolean mtp_press() { - if(!mutex) + if(!mutex) return TRUE; g_mutex_lock(mutex); if(!mtp_initialised) @@ -277,11 +278,11 @@ gboolean mtp_press() } g_mutex_unlock(mutex); - if(mtp_device == NULL) + if(mtp_device == NULL) { #if DEBUG g_print("No MTP devices have been found !!!\n"); -#endif +#endif /* show_dialog("No MTP devices have been found !!!"); */ mtp_initialised = FALSE; return TRUE; @@ -289,7 +290,7 @@ gboolean mtp_press() } gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(mtp_submenu_item_up))), _("Upload in progress...")); gtk_widget_set_sensitive(mtp_submenu_item_up, FALSE); - g_thread_create(upload,NULL,FALSE,NULL); + g_thread_create(upload,NULL,FALSE,NULL); return TRUE; } @@ -313,9 +314,9 @@ void mtp_init(void) gtk_widget_show (mtp_root_menuitem); - audacious_menu_plugin_item_add(AUDACIOUS_MENU_PLAYLIST_RCLICK, mtp_root_menuitem); - g_signal_connect (G_OBJECT (mtp_submenu_item_up), "button_press_event",G_CALLBACK (mtp_press), NULL); - g_signal_connect (G_OBJECT (mtp_submenu_item_free), "button_press_event",G_CALLBACK (free_device), NULL); + aud_menu_plugin_item_add(AUDACIOUS_MENU_PLAYLIST_RCLICK, mtp_root_menuitem); + g_signal_connect (G_OBJECT (mtp_submenu_item_up), "button_press_event",G_CALLBACK (mtp_press), NULL); + g_signal_connect (G_OBJECT (mtp_submenu_item_free), "button_press_event",G_CALLBACK (free_device), NULL); mutex = g_mutex_new(); plugin_active = TRUE; @@ -351,7 +352,7 @@ void mtp_cleanup(void) if(mtp_initialised) g_print("The MTP mutex has been unlocked\n"); #endif - audacious_menu_plugin_item_remove(AUDACIOUS_MENU_PLAYLIST_RCLICK, mtp_root_menuitem); + aud_menu_plugin_item_remove(AUDACIOUS_MENU_PLAYLIST_RCLICK, mtp_root_menuitem); gtk_widget_destroy(mtp_submenu_item_up); gtk_widget_destroy(mtp_submenu_item_up); diff --git a/src/neon/cert_verification.c b/src/neon/cert_verification.c index f6576b2..84e0f62 100644 --- a/src/neon/cert_verification.c +++ b/src/neon/cert_verification.c @@ -377,7 +377,7 @@ gboolean validate_directory_certs( * Checks if given certificate is valid certificate according to certificates * found from SSL_CERT_FILE or SSL_CERT_DIR environmental variables. */ -int neon_aud_vfs_verify_environment_ssl_certs( +int neon_vfs_verify_environment_ssl_certs( void* userdata, int failures, const ne_ssl_certificate* serverCert diff --git a/src/neon/cert_verification.h b/src/neon/cert_verification.h index 584795b..95318b5 100644 --- a/src/neon/cert_verification.h +++ b/src/neon/cert_verification.h @@ -19,7 +19,7 @@ #include <ne_ssl.h> -int neon_aud_vfs_verify_environment_ssl_certs( +int neon_vfs_verify_environment_ssl_certs( void* userdata, int failures, const ne_ssl_certificate* serverCert diff --git a/src/neon/neon.c b/src/neon/neon.c index b67b860..fd00bd0 100644 --- a/src/neon/neon.c +++ b/src/neon/neon.c @@ -25,6 +25,7 @@ #include "neon.h" +#include <audacious/configdb.h> #include <audacious/plugin.h> #include <ne_socket.h> @@ -43,55 +44,55 @@ #define NEON_RETRY_COUNT 6 -VFSFile *neon_aud_vfs_fopen_impl(const gchar* path, const gchar* mode); -gint neon_aud_vfs_fclose_impl(VFSFile* file); -gint64 neon_aud_vfs_fread_impl (void * ptr, gint64 size, gint64 nmemb, VFSFile * +VFSFile *neon_vfs_fopen_impl(const gchar* path, const gchar* mode); +gint neon_vfs_fclose_impl(VFSFile* file); +gint64 neon_vfs_fread_impl (void * ptr, gint64 size, gint64 nmemb, VFSFile * file); -gint64 neon_aud_vfs_fwrite_impl (const void * ptr, gint64 size, gint64 nmemb, +gint64 neon_vfs_fwrite_impl (const void * ptr, gint64 size, gint64 nmemb, VFSFile * file); -gint neon_aud_vfs_getc_impl(VFSFile* file); -gint neon_aud_vfs_ungetc_impl(gint c, VFSFile* file); -void neon_aud_vfs_rewind_impl(VFSFile* file); -gint64 neon_aud_vfs_ftell_impl (VFSFile * file); -gboolean neon_aud_vfs_feof_impl(VFSFile* file); -gint neon_aud_vfs_truncate_impl (VFSFile * file, gint64 size); -gint neon_aud_vfs_fseek_impl (VFSFile * file, gint64 offset, gint whence); -gchar *neon_aud_vfs_metadata_impl(VFSFile* file, const gchar * field); -gint64 neon_aud_vfs_fsize_impl (VFSFile * file); +gint neon_vfs_getc_impl(VFSFile* file); +gint neon_vfs_ungetc_impl(gint c, VFSFile* file); +void neon_vfs_rewind_impl(VFSFile* file); +gint64 neon_vfs_ftell_impl (VFSFile * file); +gboolean neon_vfs_feof_impl(VFSFile* file); +gint neon_vfs_truncate_impl (VFSFile * file, gint64 size); +gint neon_vfs_fseek_impl (VFSFile * file, gint64 offset, gint whence); +gchar *neon_vfs_metadata_impl(VFSFile* file, const gchar * field); +gint64 neon_vfs_fsize_impl (VFSFile * file); VFSConstructor neon_http_const = { "http://", - neon_aud_vfs_fopen_impl, - neon_aud_vfs_fclose_impl, - neon_aud_vfs_fread_impl, - neon_aud_vfs_fwrite_impl, - neon_aud_vfs_getc_impl, - neon_aud_vfs_ungetc_impl, - neon_aud_vfs_fseek_impl, - neon_aud_vfs_rewind_impl, - neon_aud_vfs_ftell_impl, - neon_aud_vfs_feof_impl, - neon_aud_vfs_truncate_impl, - neon_aud_vfs_fsize_impl, - neon_aud_vfs_metadata_impl + neon_vfs_fopen_impl, + neon_vfs_fclose_impl, + neon_vfs_fread_impl, + neon_vfs_fwrite_impl, + neon_vfs_getc_impl, + neon_vfs_ungetc_impl, + neon_vfs_fseek_impl, + neon_vfs_rewind_impl, + neon_vfs_ftell_impl, + neon_vfs_feof_impl, + neon_vfs_truncate_impl, + neon_vfs_fsize_impl, + neon_vfs_metadata_impl }; VFSConstructor neon_https_const = { "https://", - neon_aud_vfs_fopen_impl, - neon_aud_vfs_fclose_impl, - neon_aud_vfs_fread_impl, - neon_aud_vfs_fwrite_impl, - neon_aud_vfs_getc_impl, - neon_aud_vfs_ungetc_impl, - neon_aud_vfs_fseek_impl, - neon_aud_vfs_rewind_impl, - neon_aud_vfs_ftell_impl, - neon_aud_vfs_feof_impl, - neon_aud_vfs_truncate_impl, - neon_aud_vfs_fsize_impl, - neon_aud_vfs_metadata_impl + neon_vfs_fopen_impl, + neon_vfs_fclose_impl, + neon_vfs_fread_impl, + neon_vfs_fwrite_impl, + neon_vfs_getc_impl, + neon_vfs_ungetc_impl, + neon_vfs_fseek_impl, + neon_vfs_rewind_impl, + neon_vfs_ftell_impl, + neon_vfs_feof_impl, + neon_vfs_truncate_impl, + neon_vfs_fsize_impl, + neon_vfs_metadata_impl }; @@ -108,11 +109,11 @@ static void neon_plugin_init(void) { return; } - aud_vfs_register_transport(&neon_http_const); + vfs_register_transport(&neon_http_const); if (0 != ne_has_support(NE_FEATURE_SSL)) { _DEBUG("neon compiled with thread-safe SSL, enabling https:// transport"); - aud_vfs_register_transport(&neon_https_const); + vfs_register_transport(&neon_https_const); } } @@ -167,10 +168,17 @@ static void handle_free(struct neon_handle* h) { ne_uri_free(h->purl); g_free(h->purl); destroy_rb(&h->rb); + + if (h->reader_status.mutex != NULL) + g_mutex_free(h->reader_status.mutex); + if (h->reader_status.cond != NULL) + g_cond_free(h->reader_status.cond); + g_free(h->icy_metadata.stream_name); g_free(h->icy_metadata.stream_title); g_free(h->icy_metadata.stream_url); g_free(h->icy_metadata.stream_contenttype); + g_free(h->url); g_free(h); } @@ -692,7 +700,7 @@ static gint open_handle(struct neon_handle* handle, gulong startbyte) { if (! strcmp("https", handle->purl->scheme)) { ne_ssl_trust_default_ca(handle->session); - ne_ssl_set_verify(handle->session, neon_aud_vfs_verify_environment_ssl_certs, handle->session); + ne_ssl_set_verify(handle->session, neon_vfs_verify_environment_ssl_certs, handle->session); } _DEBUG("<%p> Creating request", handle); @@ -823,7 +831,7 @@ static gpointer reader_thread(void* data) { * ----- */ -VFSFile* neon_aud_vfs_fopen_impl(const gchar* path, const gchar* mode) { +VFSFile* neon_vfs_fopen_impl(const gchar* path, const gchar* mode) { VFSFile* file; struct neon_handle* handle; @@ -842,7 +850,7 @@ VFSFile* neon_aud_vfs_fopen_impl(const gchar* path, const gchar* mode) { _DEBUG("Allocated new handle: %p", handle); - if (NULL == (handle->url = strdup(path))) { + if (NULL == (handle->url = g_strdup(path))) { _ERROR ("<%p> Could not copy URL string", (void *) handle); handle_free(handle); g_free(file); @@ -866,7 +874,7 @@ VFSFile* neon_aud_vfs_fopen_impl(const gchar* path, const gchar* mode) { * ---- */ -gint neon_aud_vfs_fclose_impl(VFSFile* file) { +gint neon_vfs_fclose_impl(VFSFile* file) { struct neon_handle* h = (struct neon_handle *)file->handle; @@ -1103,7 +1111,7 @@ static gint64 neon_fread_real (void * ptr_, gint64 size, gint64 nmemb, /* neon_fread_real will do only a partial read if the buffer underruns, so we * must call it repeatedly until we have read the full request. */ -gint64 neon_aud_vfs_fread_impl (void * buffer, gint64 size, gint64 count, +gint64 neon_vfs_fread_impl (void * buffer, gint64 size, gint64 count, VFSFile * handle) { gsize total = 0, new; @@ -1126,7 +1134,7 @@ gint64 neon_aud_vfs_fread_impl (void * buffer, gint64 size, gint64 count, * ----- */ -gint64 neon_aud_vfs_fwrite_impl (const void * ptr, gint64 size, gint64 nmemb, +gint64 neon_vfs_fwrite_impl (const void * ptr, gint64 size, gint64 nmemb, VFSFile * file) { _ERROR ("<%p> NOT IMPLEMENTED", (void *) file->handle); @@ -1138,10 +1146,10 @@ gint64 neon_aud_vfs_fwrite_impl (const void * ptr, gint64 size, gint64 nmemb, * ----- */ -gint neon_aud_vfs_getc_impl(VFSFile* file) { +gint neon_vfs_getc_impl(VFSFile* file) { unsigned char c; - if (1 != neon_aud_vfs_fread_impl(&c, 1, 1, file)) { + if (1 != neon_vfs_fread_impl(&c, 1, 1, file)) { _ERROR ("<%p> Could not getc()!", (void *) file->handle); return -1; } @@ -1153,7 +1161,7 @@ gint neon_aud_vfs_getc_impl(VFSFile* file) { * ----- */ -gint neon_aud_vfs_ungetc_impl(gint c, VFSFile* stream) { +gint neon_vfs_ungetc_impl(gint c, VFSFile* stream) { _ERROR ("<%p> NOT IMPLEMENTED", (void *) stream->handle); return 0; @@ -1163,15 +1171,15 @@ gint neon_aud_vfs_ungetc_impl(gint c, VFSFile* stream) { * ----- */ -void neon_aud_vfs_rewind_impl(VFSFile* file) { - (void)neon_aud_vfs_fseek_impl(file, 0L, SEEK_SET); +void neon_vfs_rewind_impl(VFSFile* file) { + (void)neon_vfs_fseek_impl(file, 0L, SEEK_SET); } /* * ----- */ -gint64 neon_aud_vfs_ftell_impl (VFSFile * file) +gint64 neon_vfs_ftell_impl (VFSFile * file) { struct neon_handle* h = (struct neon_handle *)file->handle; @@ -1184,7 +1192,7 @@ gint64 neon_aud_vfs_ftell_impl (VFSFile * file) * ----- */ -gboolean neon_aud_vfs_feof_impl(VFSFile* file) { +gboolean neon_vfs_feof_impl(VFSFile* file) { struct neon_handle* h = (struct neon_handle*)file->handle; @@ -1197,7 +1205,7 @@ gboolean neon_aud_vfs_feof_impl(VFSFile* file) { * ----- */ -gint neon_aud_vfs_truncate_impl (VFSFile * file, gint64 size) +gint neon_vfs_truncate_impl (VFSFile * file, gint64 size) { _ERROR ("<%p> NOT IMPLEMENTED", (void *) file->handle); @@ -1208,7 +1216,7 @@ gint neon_aud_vfs_truncate_impl (VFSFile * file, gint64 size) * ----- */ -gint neon_aud_vfs_fseek_impl (VFSFile * file, gint64 offset, gint whence) +gint neon_vfs_fseek_impl (VFSFile * file, gint64 offset, gint whence) { struct neon_handle* h = (struct neon_handle*)file->handle; glong newpos; @@ -1305,7 +1313,7 @@ gint neon_aud_vfs_fseek_impl (VFSFile * file, gint64 offset, gint whence) * ----- */ -gchar *neon_aud_vfs_metadata_impl(VFSFile* file, const gchar* field) { +gchar *neon_vfs_metadata_impl(VFSFile* file, const gchar* field) { struct neon_handle* h = (struct neon_handle*)file->handle; @@ -1334,7 +1342,7 @@ gchar *neon_aud_vfs_metadata_impl(VFSFile* file, const gchar* field) { * ----- */ -gint64 neon_aud_vfs_fsize_impl (VFSFile * file) +gint64 neon_vfs_fsize_impl (VFSFile * file) { struct neon_handle* h = (struct neon_handle*)file->handle; diff --git a/src/notify/Makefile b/src/notify/Makefile new file mode 100644 index 0000000..1a8f485 --- /dev/null +++ b/src/notify/Makefile @@ -0,0 +1,14 @@ +PLUGIN = notify${PLUGIN_SUFFIX} + +SRCS = libnotify-aosd.c \ + libnotify-aosd_event.c \ + libnotify-aosd_osd.c + +include ../../buildsys.mk +include ../../extra.mk + +plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR} + +CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GTK_CFLAGS} ${NOTIFY_CFLAGS} -DPACKAGE_VERSION=\"0.1.1\" +CFLAGS += ${PLUGIN_CFLAGS} +LIBS += ${GTK_LIBS} ${NOTIFY_LIBS} diff --git a/src/notify/libnotify-aosd.c b/src/notify/libnotify-aosd.c new file mode 100644 index 0000000..1e72de1 --- /dev/null +++ b/src/notify/libnotify-aosd.c @@ -0,0 +1,71 @@ +/************************************************************************ + * libnotify-aosd.c * + * * + * Copyright (C) 2010 Maximilian Bogner <max@mbogner.de> * + * * + * 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 3 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, see <http://www.gnu.org/licenses/>. * + ************************************************************************/ + +#include <glib.h> +#include <gtk/gtk.h> +#include <audacious/plugin.h> +#include "libnotify-aosd_common.h" + +// The pointers to the functions of the plugin +GeneralPlugin plugin_gp = { + .description = PLUGIN_NAME " " PLUGIN_VERSION, + .init = plugin_init, + .about = plugin_about, + .cleanup = plugin_cleanup +}; + +GeneralPlugin *plugin_gplist[] = {&plugin_gp, NULL}; +SIMPLE_GENERAL_PLUGIN(libnotifyaosd, plugin_gplist); + +short plugin_active = 0; + +void plugin_init() { + DEBUG_PRINT("[%s] plugin_init: started!\n", __FILE__); + if(!osd_init()) { + DEBUG_PRINT("[%s] plugin_init: osd_init failed!\n", __FILE__); + return; + } + event_init(); + + plugin_active = 1; + DEBUG_PRINT("[%s] plugin_init: done!\n", __FILE__); +} + + +void plugin_cleanup() { + if(plugin_active) { + DEBUG_PRINT("[%s] plugin_cleanup: started!\n", __FILE__); + event_uninit(); + osd_uninit(); + plugin_active = 0; + DEBUG_PRINT("[%s] plugin_cleanup: done!\n", __FILE__); + } +} + +void plugin_about() { + const gchar *authors[] = {PLUGIN_AUTHORS, NULL}; + + gtk_show_about_dialog(NULL, "program-name", PLUGIN_NAME, + "version", PLUGIN_VERSION, + "license", PLUGIN_LICENSE, + "wrap-license", TRUE, + "copyright", PLUGIN_COPYRIGHT, + "authors", authors, + "website", PLUGIN_WEBSITE, NULL); +} diff --git a/src/notify/libnotify-aosd.h b/src/notify/libnotify-aosd.h new file mode 100644 index 0000000..0b54630 --- /dev/null +++ b/src/notify/libnotify-aosd.h @@ -0,0 +1,27 @@ +/************************************************************************ + * libnotify-aosd.h * + * * + * Copyright (C) 2010 Maximilian Bogner <max@mbogner.de> * + * * + * 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 3 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, see <http://www.gnu.org/licenses/>. * + ************************************************************************/ + +#include <glib.h> +#include <gtk/gtk.h> +#include <audacious/plugin.h> + +// Prototypes +void plugin_init(); +void plugin_cleanup(); +void plugin_about(); diff --git a/src/notify/libnotify-aosd_common.h b/src/notify/libnotify-aosd_common.h new file mode 100644 index 0000000..3857ef0 --- /dev/null +++ b/src/notify/libnotify-aosd_common.h @@ -0,0 +1,35 @@ +/************************************************************************ + * libnotify-aosd_common.h * + * * + * Copyright (C) 2010 Maximilian Bogner <max@mbogner.de> * + * * + * 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 3 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, see <http://www.gnu.org/licenses/>. * + ************************************************************************/ + +#define PLUGIN_NAME "libnotify-aosd" +#define PLUGIN_VERSION PACKAGE_VERSION +#define PLUGIN_AUTHORS "Maximilian Bogner <max@mbogner.de>" +#define PLUGIN_COPYRIGHT "Copyright (C) 2010 Maximilian Bogner" +#define PLUGIN_WEBSITE "http://www.mbogner.de/projects/libnotify-aosd/" +#define PLUGIN_LICENSE "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 3 of the License, or (at your option) any later version.\n\nThis 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.\n\nYou should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>." + +#ifdef DEBUG + #define DEBUG_PRINT(...) { g_print(__VA_ARGS__); } +#else + #define DEBUG_PRINT(...) { } +#endif + +#include "libnotify-aosd.h" +#include "libnotify-aosd_event.h" +#include "libnotify-aosd_osd.h" diff --git a/src/notify/libnotify-aosd_event.c b/src/notify/libnotify-aosd_event.c new file mode 100644 index 0000000..b0aa870 --- /dev/null +++ b/src/notify/libnotify-aosd_event.c @@ -0,0 +1,70 @@ +/************************************************************************ + * libnotify-aosd_event.c * + * * + * Copyright (C) 2010 Maximilian Bogner <max@mbogner.de> * + * * + * 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 3 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, see <http://www.gnu.org/licenses/>. * + ************************************************************************/ + +#include <glib.h> + +#include <audacious/drct.h> +#include <audacious/plugin.h> +#include <libaudcore/audstrings.h> +#include <libaudcore/hook.h> + +#include "libnotify-aosd_common.h" + +void event_init() { + DEBUG_PRINT("[%s] event_init: started!\n", __FILE__); + hook_associate("playback begin", event_playback_begin, NULL); + hook_associate("playback pause", event_playback_pause, NULL); + hook_associate("playback unpause", event_playback_begin, NULL); + DEBUG_PRINT("[%s] event_init: done!\n", __FILE__); +} + +void event_uninit() { + DEBUG_PRINT("[%s] event_uninit: started!\n", __FILE__); + hook_dissociate("playback begin", event_playback_begin); + hook_dissociate("playback pause", event_playback_pause); + hook_dissociate("playback unpause", event_playback_begin); + DEBUG_PRINT("[%s] event_uninit: done!\n", __FILE__); +} + +void event_playback_begin(gpointer p1, gpointer p2) { + gchar *aud_title = NULL, *title = NULL; + DEBUG_PRINT("[%s] event_playback_begin: started!\n", __FILE__); + + aud_title = aud_drct_pl_get_title(aud_drct_pl_get_pos()); + + if(aud_title != NULL) { + title = str_to_utf8(aud_title); + if(g_utf8_validate(title, -1, NULL)) { + osd_show(title, "notification-audio-play"); + } else { + DEBUG_PRINT("[%s] event_playback_begin: unvalid utf8 title!\n", __FILE__); + } + g_free(title); + } else { + DEBUG_PRINT("[%s] event_playback_begin: no aud title!\n", __FILE__); + } + + DEBUG_PRINT("[%s] event_playback_begin: done!\n", __FILE__); +} + +void event_playback_pause(gpointer p1, gpointer p2) { + DEBUG_PRINT("[%s] event_playback_pause: started!\n", __FILE__); + osd_show("Playback paused", "notification-audio-pause"); + DEBUG_PRINT("[%s] event_playback_pause: done!\n", __FILE__); +} diff --git a/src/notify/libnotify-aosd_event.h b/src/notify/libnotify-aosd_event.h new file mode 100644 index 0000000..8ebbef8 --- /dev/null +++ b/src/notify/libnotify-aosd_event.h @@ -0,0 +1,28 @@ +/************************************************************************ + * libnotify-aosd_event.h * + * * + * Copyright (C) 2010 Maximilian Bogner <max@mbogner.de> * + * * + * 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 3 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, see <http://www.gnu.org/licenses/>. * + ************************************************************************/ + +#include <glib.h> +#include <libaudcore/hook.h> +#include <audacious/plugin.h> + +// Prototypes +void event_init(); +void event_uninit(); +void event_playback_begin(gpointer p1, gpointer p2); +void event_playback_pause(gpointer p1, gpointer p2); diff --git a/src/notify/libnotify-aosd_osd.c b/src/notify/libnotify-aosd_osd.c new file mode 100644 index 0000000..4331805 --- /dev/null +++ b/src/notify/libnotify-aosd_osd.c @@ -0,0 +1,61 @@ +/************************************************************************ + * libnotify-aosd_osd.c * + * * + * Copyright (C) 2010 Maximilian Bogner <max@mbogner.de> * + * * + * 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 3 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, see <http://www.gnu.org/licenses/>. * + ************************************************************************/ + +#include <glib.h> +#include <libnotify/notify.h> +#include "libnotify-aosd_common.h" + +NotifyNotification *notification = NULL; + +gboolean osd_init() { + notification = NULL; + return notify_init(PLUGIN_NAME); +} + +void osd_uninit() { + notify_uninit(); +} + +void osd_closed_handler(NotifyNotification *notification2, gpointer data) { + if(notification != NULL) { + g_object_unref(G_OBJECT(notification)); + notification = NULL; + DEBUG_PRINT("[%s] osd_closed_handler: notification unrefed!\n", __FILE__); + } +} + +void osd_show(gchar *text, gchar *icon) { + GError *error = NULL; + + if(notification == NULL) { + notification = notify_notification_new(text, NULL, icon, NULL); + g_signal_connect(G_OBJECT(notification), "closed", G_CALLBACK(osd_closed_handler), NULL); + DEBUG_PRINT("[%s] osd_show: new osd created! (notification=%p)\n", __FILE__, notification); + } else { + if(notify_notification_update(notification, text, NULL, icon)) { + DEBUG_PRINT("[%s] osd_show: old osd updated! (notification=%p)\n", __FILE__, notification); + } else { + DEBUG_PRINT("[%s] osd_show: could not update old osd! (notification=%p)\n", __FILE__, notification); + } + } + + if(!notify_notification_show(notification, &error)) + DEBUG_PRINT("[%s] osd_show: %s!\n", __FILE__, error->message); + +} diff --git a/src/notify/libnotify-aosd_osd.h b/src/notify/libnotify-aosd_osd.h new file mode 100644 index 0000000..f1777cc --- /dev/null +++ b/src/notify/libnotify-aosd_osd.h @@ -0,0 +1,27 @@ +/************************************************************************ + * libnotify-aosd_osd.h * + * * + * Copyright (C) 2010 Maximilian Bogner <max@mbogner.de> * + * * + * 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 3 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, see <http://www.gnu.org/licenses/>. * + ************************************************************************/ + +#include <glib.h> +#include <libnotify/notify.h> + +// Prototypes +gboolean osd_init(); +void osd_uninit(); +void osd_closed_handler(NotifyNotification *notification2, gpointer data); +void osd_show(gchar *text, gchar *icon); diff --git a/src/null/null.c b/src/null/null.c index 3b1de35..35df86d 100644 --- a/src/null/null.c +++ b/src/null/null.c @@ -22,6 +22,8 @@ #include "config.h" #include <glib.h> #include <gtk/gtk.h> + +#include <audacious/configdb.h> #include <audacious/plugin.h> #include <audacious/i18n.h> #include <libaudgui/libaudgui.h> @@ -34,7 +36,7 @@ static gboolean real_time = TRUE; static gboolean paused, started; static GtkWidget *configurewin; static struct { - AFormat format; + gint format; gint frequency; gint channels; } input_format; @@ -120,7 +122,7 @@ static void null_configure(void) gtk_widget_show_all(configurewin); } -static int null_open(AFormat fmt, int rate, int nch) +static int null_open(gint fmt, int rate, int nch) { offset_time = 0; written = 0; diff --git a/src/oss4/configure.c b/src/oss4/configure.c index e6ed5d5..57523fc 100644 --- a/src/oss4/configure.c +++ b/src/oss4/configure.c @@ -19,6 +19,7 @@ #include "oss.h" #include <gtk/gtk.h> +#include <audacious/configdb.h> static GtkWidget *window; static oss_cfg_t *tmp_cfg; @@ -55,7 +56,7 @@ static void vol_toggled_cb(GtkToggleButton *widget, gpointer data) } static void button_ok_clicked_cb(GtkButton *button, gpointer data) -{ +{ g_free(oss_cfg); oss_cfg = g_memdup(tmp_cfg, sizeof(oss_cfg_t)); oss_cfg->alt_device = gtk_editable_get_chars(GTK_EDITABLE(GTK_WIDGET(data)), 0, -1); @@ -69,12 +70,12 @@ static GtkTreeModel *get_device_list(void) GtkTreeIter iter; oss_sysinfo sysinfo; gint mixerfd, i, a = 1; - + list = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); - + if ((mixerfd = open(DEFAULT_MIXER, O_RDWR)) == -1) goto FAILED; - + if (ioctl(mixerfd, SNDCTL_SYSINFO, &sysinfo) == -1) goto FAILED; @@ -83,15 +84,15 @@ static GtkTreeModel *get_device_list(void) errno = ENXIO; goto FAILED; } - + gtk_list_store_append(list, &iter); gtk_list_store_set(list, &iter, 0, _("1. Default device"), 1, DEFAULT_DSP, -1); - + for (i = 0; i < sysinfo.numaudios; i++) { oss_audioinfo ainfo; ainfo.dev = i; - + if (ioctl(mixerfd, SNDCTL_AUDIOINFO, &ainfo) == -1) goto FAILED; @@ -105,9 +106,9 @@ static GtkTreeModel *get_device_list(void) } close(mixerfd); - + return GTK_TREE_MODEL(list); - + FAILED: SHOW_ERROR_MSG; close(mixerfd); @@ -135,7 +136,7 @@ static void select_combo_item(GtkComboBox *combo, gchar *text) } static void window_destroy(void) -{ +{ g_free(tmp_cfg); } @@ -163,83 +164,83 @@ static void window_create(void) gtk_box_pack_start(GTK_BOX(dev_list_box), dev_label, FALSE, FALSE, 5); dev_list_model = get_device_list(); - + if (!GTK_IS_TREE_MODEL(dev_list_model)) { gtk_widget_destroy(window); return; } - + dev_list_combo = gtk_combo_box_new_with_model(dev_list_model); - + cell = gtk_cell_renderer_text_new(); gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(dev_list_combo), cell, TRUE); gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(dev_list_combo), cell, "text", 0, NULL); g_object_unref(G_OBJECT(dev_list_model)); - + select_combo_item(GTK_COMBO_BOX(dev_list_combo), tmp_cfg->device); - + gtk_box_pack_start(GTK_BOX(dev_list_box), dev_list_combo, TRUE, TRUE, 5); - + alt_dev_box = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), alt_dev_box, FALSE, FALSE, 0); - + alt_dev_check = gtk_check_button_new_with_label(_("Use alternate device:")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(alt_dev_check), tmp_cfg->use_alt_device); - + gtk_box_pack_start(GTK_BOX(alt_dev_box), alt_dev_check, FALSE, FALSE, 5); - + alt_dev_text = gtk_entry_new(); gtk_entry_set_text(GTK_ENTRY(alt_dev_text), tmp_cfg->alt_device); gtk_widget_set_sensitive(alt_dev_text, tmp_cfg->use_alt_device); gtk_box_pack_start(GTK_BOX(alt_dev_box), alt_dev_text, TRUE, TRUE, 5); - + option_box = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), option_box, FALSE, FALSE, 0); - + vol_check = gtk_check_button_new_with_label(_("Save volume between sessions")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(vol_check), tmp_cfg->save_volume); gtk_box_pack_start(GTK_BOX(option_box), vol_check, FALSE, FALSE, 5); - + cookedmode_check = gtk_check_button_new_with_label(_("Enable format conversions made by the OSS software.")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cookedmode_check), tmp_cfg->cookedmode); gtk_box_pack_start(GTK_BOX(option_box), cookedmode_check, FALSE, FALSE, 5); - + button_box = gtk_hbutton_box_new(); gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_END); gtk_button_box_set_spacing(GTK_BUTTON_BOX(button_box), 5); gtk_box_pack_start(GTK_BOX(vbox), button_box, TRUE, TRUE, 5); - + button_cancel = gtk_button_new_from_stock(GTK_STOCK_CANCEL); gtk_box_pack_start(GTK_BOX(button_box), button_cancel, FALSE, FALSE, 5); - + button_ok = gtk_button_new_from_stock(GTK_STOCK_OK); gtk_box_pack_start(GTK_BOX(button_box), button_ok, FALSE, FALSE, 5); - + gtk_widget_grab_default(button_ok); - + g_signal_connect(G_OBJECT(dev_list_combo), "changed", G_CALLBACK(dev_list_changed_cb), NULL); - + g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(window_destroy), NULL); - + g_signal_connect(G_OBJECT(alt_dev_check), "toggled", G_CALLBACK(alt_dev_toggled_cb), alt_dev_text); - + g_signal_connect(G_OBJECT(vol_check), "toggled", G_CALLBACK(vol_toggled_cb), NULL); - + g_signal_connect(G_OBJECT(cookedmode_check), "toggled", G_CALLBACK(cookedmode_toggled_cb), NULL); - + g_signal_connect_swapped(G_OBJECT(button_cancel), "clicked", G_CALLBACK(gtk_widget_destroy), window); - + g_signal_connect(G_OBJECT(button_ok), "clicked", G_CALLBACK(button_ok_clicked_cb), alt_dev_text); - + gtk_widget_show_all(window); } diff --git a/src/oss4/oss.c b/src/oss4/oss.c index 687e591..a49088d 100644 --- a/src/oss4/oss.c +++ b/src/oss4/oss.c @@ -1,10 +1,10 @@ /* * OSS4 Output Plugin for Audacious * Copyright 2010 MichaÅ‚ Lipski <tallica@o2.pl> - * - * I would like to thank people on #audacious, especially Tony Vroon and + * + * I would like to thank people on #audacious, especially Tony Vroon and * John Lindgren and of course the authors of the previous OSS plugin. - * + * * 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 3 of the License, or @@ -34,11 +34,10 @@ static audio_buf_info oss_buffer_info; static gint oss_delay; /* miliseconds */ static gboolean oss_ioctl_vol = FALSE; - OutputPluginInitStatus oss_init(void) { AUDDBG("Init.\n"); - + oss_data = g_new0(oss_data_t, 1); oss_cfg = g_new0(oss_cfg_t, 1); oss_data->fd = -1; @@ -48,9 +47,9 @@ OutputPluginInitStatus oss_init(void) oss_cfg->save_volume = TRUE; oss_cfg->volume = 0x3232; oss_cfg->cookedmode = TRUE; - + oss_config_load(); - + if (oss_hardware_present()) return OUTPUT_PLUGIN_INIT_FOUND_DEVICES; else @@ -70,18 +69,18 @@ void oss_cleanup(void) static gboolean set_format(gint format, gint rate, gint channels) { gint param; - + AUDDBG("Audio format: %s, sample rate: %dHz, number of channels: %d.\n", oss_format_to_text(format), rate, channels); - + /* Enable/disable format conversions made by the OSS software */ if (ioctl(oss_data->fd, SNDCTL_DSP_COOKEDMODE, &oss_cfg->cookedmode) == -1) DEBUG_MSG; - + param = format; if (ioctl(oss_data->fd, SNDCTL_DSP_SETFMT, ¶m) == -1) goto FAILED; - + if (param != format) { ERROR("Selected audio format is not supported by the device.\n"); @@ -103,7 +102,7 @@ static gboolean set_format(gint format, gint rate, gint channels) if (ioctl(oss_data->fd, SNDCTL_DSP_CHANNELS, ¶m) == -1) goto FAILED; - + if (param != channels) { ERROR("Selected number of channels is not supported by the device.\n"); @@ -114,15 +113,15 @@ static gboolean set_format(gint format, gint rate, gint channels) oss_data->rate = rate; oss_data->channels = channels; oss_data->bits_per_sample = oss_format_to_bits(oss_data->format); - + return TRUE; - + FAILED: ERROR_MSG; return FALSE; } -gint oss_open_audio(AFormat aud_format, gint rate, gint channels) +gint oss_open_audio(gint aud_format, gint rate, gint channels) { AUDDBG("Opening audio.\n"); @@ -146,7 +145,7 @@ gint oss_open_audio(AFormat aud_format, gint rate, gint channels) format = oss_convert_aud_format(aud_format); if (!set_format(format, rate, channels)) - goto FAILED; + goto FAILED; /*gint policy = 8; ioctl(oss_data->fd, SNDCTL_DSP_POLICY, &policy);*/ @@ -166,18 +165,18 @@ gint oss_open_audio(AFormat aud_format, gint rate, gint channels) oss_ioctl_vol = TRUE; AUDDBG("Internal OSS buffer size: %dms.\n", oss_delay); - + if (oss_cfg->save_volume) { vol_right = (oss_cfg->volume & 0xFF00) >> 8; vol_left = (oss_cfg->volume & 0x00FF); - + oss_set_volume(vol_left, vol_right); } return 1; - FAILED: + FAILED: close(oss_data->fd); oss_data->fd = -1; return 0; @@ -186,7 +185,7 @@ gint oss_open_audio(AFormat aud_format, gint rate, gint channels) void oss_close_audio(void) { AUDDBG ("Closing audio.\n"); - + if (ioctl(oss_data->fd, SNDCTL_DSP_HALT_OUTPUT, NULL) == -1) DEBUG_MSG; @@ -199,14 +198,16 @@ void oss_write_audio(void *data, gint length) { gint written = 0, start = 0; - if (oss_paused) return; + if (oss_paused) + return; while (1) { - if (oss_paused) break; - + if (oss_paused) + break; + written = write(oss_data->fd, data + start, length); - + if (written < 0) { ERROR_MSG; @@ -216,14 +217,14 @@ void oss_write_audio(void *data, gint length) break; } - + if (length >= written) length -= written; - + start += written; oss_time += (gint64) oss_bytes_to_frames(written) * 1000000 / oss_data->rate; -#if HARD_DEBUG == 1 +#if HARD_DEBUG == 1 ioctl(oss_data->fd, SNDCTL_DSP_GETOSPACE, &oss_buffer_info); printf("fragstotal: \t%d\tfragsize: \t%d\tbytes: \t%d\tlength: \t%d\n", @@ -236,10 +237,25 @@ void oss_write_audio(void *data, gint length) } } -void oss_drain(void) +gint oss_buffer_playing(void) { - AUDDBG("Drain.\n"); - /* TODO? */ + AUDDBG("Buffer playing.\n"); + + ioctl(oss_data->fd, SNDCTL_DSP_GETOSPACE, &oss_buffer_info); + + if ((oss_buffer_info.fragstotal * oss_buffer_info.fragsize) - oss_buffer_info.bytes > oss_buffer_info.fragsize) + return TRUE; + + return FALSE; +} + +gint oss_buffer_free(void) +{ + if (oss_paused) + return 0; + + ioctl(oss_data->fd, SNDCTL_DSP_GETOSPACE, &oss_buffer_info); + return oss_buffer_info.bytes; } void oss_set_written_time(gint time) @@ -278,9 +294,9 @@ void oss_flush(gint time) { AUDDBG("Flush.\n"); - if(ioctl(oss_data->fd, SNDCTL_DSP_HALT_OUTPUT, NULL) == -1) + if (ioctl(oss_data->fd, SNDCTL_DSP_HALT_OUTPUT, NULL) == -1) DEBUG_MSG; - + if (ioctl(oss_data->fd, SNDCTL_DSP_SKIP, NULL) == -1) DEBUG_MSG; @@ -296,14 +312,14 @@ void oss_pause(gshort pause) { oss_paused = TRUE; oss_paused_time = real_output_time(); - + if (ioctl(oss_data->fd, SNDCTL_DSP_SILENCE, NULL) == -1) DEBUG_MSG; } else - { + { oss_paused = FALSE; - + if (ioctl(oss_data->fd, SNDCTL_DSP_SKIP, NULL) == -1) DEBUG_MSG; } @@ -312,7 +328,7 @@ void oss_pause(gshort pause) void oss_get_volume(gint *left, gint *right) { gint vol; - + if (oss_data->fd == -1 || !oss_ioctl_vol) { if (oss_cfg->save_volume) @@ -343,10 +359,10 @@ void oss_set_volume(gint left, gint right) gint vol; vol = (right << 8) | left; - + if (oss_cfg->save_volume) oss_cfg->volume = vol; - + if (oss_data->fd == -1 || !oss_ioctl_vol) return; diff --git a/src/oss4/oss.h b/src/oss4/oss.h index 641970c..35bd990 100644 --- a/src/oss4/oss.h +++ b/src/oss4/oss.h @@ -35,6 +35,7 @@ #include <audacious/plugin.h> #include <audacious/i18n.h> +#include <audacious/debug.h> #define ERROR(...) fprintf(stderr, "OSS4: " __VA_ARGS__) @@ -93,10 +94,11 @@ extern gchar *oss_message; /* oss.c */ OutputPluginInitStatus oss_init(void); void oss_cleanup(void); -gint oss_open_audio(AFormat aud_format, gint rate, gint channels); +gint oss_open_audio(gint aud_format, gint rate, gint channels); void oss_close_audio(void); void oss_write_audio(void *data, gint length); -void oss_drain(void); +gint oss_buffer_playing(void); +gint oss_buffer_free(void); void oss_set_written_time(gint time); gint oss_written_time(void); gint oss_output_time(void); @@ -114,7 +116,7 @@ void oss_configure(void); void oss_about(void); /* utils.c */ -gint oss_convert_aud_format(AFormat aud_format); +gint oss_convert_aud_format(gint aud_format); gchar *oss_format_to_text(gint format); gint oss_format_to_bits(gint format); gint oss_frames_to_bytes(gint frames); diff --git a/src/oss4/plugin.c b/src/oss4/plugin.c index ead3b2e..63999de 100644 --- a/src/oss4/plugin.c +++ b/src/oss4/plugin.c @@ -30,7 +30,8 @@ static OutputPlugin plugin = { .open_audio = oss_open_audio, .close_audio = oss_close_audio, .write_audio = oss_write_audio, - .drain = oss_drain, + .buffer_playing = oss_buffer_playing, + .buffer_free = oss_buffer_free, .set_written_time = oss_set_written_time, .written_time = oss_written_time, .output_time = oss_output_time, @@ -56,7 +57,7 @@ void oss_about(void) "I would like to thank people on #audacious, especially Tony Vroon and " "John Lindgren and of course the authors of the previous OSS plugin.\n\n" "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 " + "it under the terms of the GNU General Public License as published by " "the Free Software Foundation, either version 3 of the License, or " "(at your option) any later version.\n\n" "This program is distributed in the hope that it will be useful, " diff --git a/src/oss4/utils.c b/src/oss4/utils.c index e437aea..71830b8 100644 --- a/src/oss4/utils.c +++ b/src/oss4/utils.c @@ -1,7 +1,7 @@ /* * OSS4 Output Plugin for Audacious * Copyright 2010 MichaÅ‚ Lipski <tallica@o2.pl> - * + * * 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 3 of the License, or @@ -56,11 +56,11 @@ gchar *oss_format_to_text(gint format) return "FMT_UNKNOWN"; } -gint oss_convert_aud_format(AFormat aud_format) +gint oss_convert_aud_format(gint aud_format) { const struct { - AFormat aud_format; + gint aud_format; gint format; } table[] = @@ -165,12 +165,12 @@ gchar *oss_describe_error(void) if (table[count].error == errno) return g_strdup(table[count].text); } - + return g_strdup_printf("Unknown OSS error (%d)\n", errno); } gboolean oss_hardware_present(void) -{ +{ gint mixerfd; oss_sysinfo sysinfo; @@ -190,7 +190,7 @@ gboolean oss_hardware_present(void) errno = ENXIO; goto FAILED; } - + FAILED: SHOW_ERROR_MSG; close(mixerfd); @@ -200,6 +200,6 @@ gboolean oss_hardware_present(void) void oss_show_error(const gchar *message) { static GtkWidget *dialog = NULL; - + audgui_simple_message (&dialog, GTK_MESSAGE_ERROR, _("OSS4 error"), message); } diff --git a/src/paranormal/Makefile b/src/paranormal/Makefile index ca99e8c..6847ede 100644 --- a/src/paranormal/Makefile +++ b/src/paranormal/Makefile @@ -30,4 +30,4 @@ plugindir := ${plugindir}/${VISUALIZATION_PLUGIN_DIR} CFLAGS += ${PLUGIN_CFLAGS} CPPFLAGS += ${PLUGIN_CPPFLAGS} ${MOWGLI_CFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} ${ARCH_DEFINES} ${XML_CPPFLAGS} ${SDL_CFLAGS} -I../.. -I. -LIBS += ${GTK_LIBS} ${GLIB_LIBS} ${XML_LIBS} ${SDL_LIBS} +LIBS += -lm ${GTK_LIBS} ${GLIB_LIBS} ${XML_LIBS} ${SDL_LIBS} diff --git a/src/paranormal/cfg.c b/src/paranormal/cfg.c index 5b03973..9e271dc 100644 --- a/src/paranormal/cfg.c +++ b/src/paranormal/cfg.c @@ -24,10 +24,11 @@ #include <glib.h> #include <gtk/gtk.h> -#include <audacious/plugin.h> - #include <math.h> +#include <audacious/configdb.h> +#include <audacious/plugin.h> + #include "paranormal.h" #include "actuators.h" #include "containers.h" @@ -222,7 +223,7 @@ row_select_cb (GtkCTree *ctree, GtkCTreeNode *node, gtk_tooltips_set_tip (actuator_tooltips, GTK_WIDGET(w), a->desc->option_descs[j].doc, NULL); } - break; + break; case OPT_TYPE_COLOR_INDEX: adj = gtk_adjustment_new (a->options[j].val.ival, 0, 255, @@ -286,7 +287,7 @@ add_actuator_cb (GtkButton *button, gpointer data) { char *actuator_name; struct pn_actuator *a; - + gtk_label_get (GTK_LABEL (GTK_BIN (actuator_add_opmenu)->child), &actuator_name); @@ -495,7 +496,7 @@ pn_configure (void) GtkWidget *notebook, *label, *scrollwindow, *menu, *menuitem; GtkWidget *paned, *vbox, *table, *bbox, *button; int i; - + if (! cfg_dialog) { @@ -539,7 +540,7 @@ pn_configure (void) actuator_tree); table = gtk_table_new (3, 2, TRUE); gtk_widget_show (table); - gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 3); + gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 3); actuator_add_opmenu = gtk_option_menu_new (); gtk_widget_show (actuator_add_opmenu); menu = gtk_menu_new (); diff --git a/src/paranormal/libcalc/parser.c b/src/paranormal/libcalc/parser.c index b50e423..1ca2035 100644 --- a/src/paranormal/libcalc/parser.c +++ b/src/paranormal/libcalc/parser.c @@ -1380,7 +1380,7 @@ int yylex (YYSTYPE *yylval, void *yyparam) { parser_control *pc = (parser_control *) yyparam; /* Ignore whitespace, get first nonwhite character. */ - while ((c = aud_vfs_getc (pc->input)) == ' ' || c == '\t' || c == '\n'); + while ((c = vfs_getc (pc->input)) == ' ' || c == '\t' || c == '\n'); /* End of input ? */ if (c == EOF) @@ -1388,7 +1388,7 @@ int yylex (YYSTYPE *yylval, void *yyparam) { /* Char starts a number => parse the number. */ if (isdigit (c)) { - aud_vfs_fseek (pc->input, -1, SEEK_CUR); /* Put the char back. */ + vfs_fseek (pc->input, -1, SEEK_CUR); /* Put the char back. */ { char *old_locale, *saved_locale; @@ -1399,10 +1399,10 @@ int yylex (YYSTYPE *yylval, void *yyparam) { while (isdigit(c) || c == '.') { - c = aud_vfs_getc(pc->input); + c = vfs_getc(pc->input); } - aud_vfs_fseek(pc->input, -1, SEEK_CUR); + vfs_fseek(pc->input, -1, SEEK_CUR); setlocale (LC_ALL, saved_locale); g_free (saved_locale); @@ -1420,10 +1420,10 @@ int yylex (YYSTYPE *yylval, void *yyparam) { sym_name = g_string_append_c (sym_name, c); /* Get another character. */ - c = aud_vfs_getc (pc->input); + c = vfs_getc (pc->input); } while (c != EOF && isalnum (c)); - aud_vfs_fseek (pc->input, -1, SEEK_CUR); + vfs_fseek (pc->input, -1, SEEK_CUR); yylval->s_value = sym_name->str; @@ -1504,7 +1504,7 @@ expression_t *expr_compile_string (const char* str, symbol_dict_t *dict) g_return_val_if_fail(str != NULL && dict != NULL, NULL); - stream = aud_vfs_buffer_new_from_string ( (char *) str ); + stream = vfs_buffer_new_from_string ( (char *) str ); pc.input = stream; pc.expr = expr_new (); @@ -1516,7 +1516,7 @@ expression_t *expr_compile_string (const char* str, symbol_dict_t *dict) pc.expr = NULL; } - aud_vfs_fclose (stream); + vfs_fclose (stream); return pc.expr; } diff --git a/src/pls/Makefile b/src/pls/Makefile index 2afab81..4b231c9 100644 --- a/src/pls/Makefile +++ b/src/pls/Makefile @@ -1,5 +1,5 @@ PLUGIN = pls${PLUGIN_SUFFIX} -SRCS = pls.c +SRCS = pls.c util.c include ../../buildsys.mk include ../../extra.mk diff --git a/src/pls/pls.c b/src/pls/pls.c index 74fc3d3..c8d15ba 100644 --- a/src/pls/pls.c +++ b/src/pls/pls.c @@ -33,7 +33,13 @@ #include <sys/stat.h> #include <sys/errno.h> +#include <audacious/debug.h> +#include <audacious/misc.h> +#include <audacious/playlist.h> #include <audacious/plugin.h> +#include <libaudcore/audstrings.h> + +#include "util.h" static void playlist_load_pls(const gchar * filename, gint pos) @@ -46,17 +52,17 @@ playlist_load_pls(const gchar * filename, gint pos) g_return_if_fail(filename != NULL); - if (!aud_str_has_suffix_nocase(filename, ".pls")) + if (!str_has_suffix_nocase(filename, ".pls")) return; uri = g_filename_to_uri(filename, NULL, NULL); - INIFile *inifile = aud_open_ini_file(uri ? uri : filename); + INIFile *inifile = open_ini_file(uri ? uri : filename); g_free(uri); uri = NULL; - if (!(line = aud_read_ini_string(inifile, "playlist", "NumberOfEntries"))) + if (!(line = read_ini_string(inifile, "playlist", "NumberOfEntries"))) { - aud_close_ini_file(inifile); + close_ini_file(inifile); return; } @@ -67,7 +73,7 @@ playlist_load_pls(const gchar * filename, gint pos) for (i = 1; i <= count; i++) { g_snprintf(line_key, sizeof(line_key), "File%d", i); - if ((line = aud_read_ini_string(inifile, "playlist", line_key))) + if ((line = read_ini_string(inifile, "playlist", line_key))) { gchar *uri = aud_construct_uri(line, filename); g_free(line); @@ -77,7 +83,7 @@ playlist_load_pls(const gchar * filename, gint pos) } } - aud_close_ini_file(inifile); + close_ini_file(inifile); aud_playlist_entry_insert_batch (aud_playlist_get_active (), pos, add, NULL); } @@ -88,7 +94,7 @@ playlist_save_pls(const gchar *filename, gint pos) gint playlist = aud_playlist_get_active (); gint entries = aud_playlist_entry_count (playlist); gchar *uri = g_filename_to_uri(filename, NULL, NULL); - VFSFile *file = aud_vfs_fopen(uri, "wb"); + VFSFile *file = vfs_fopen(uri, "wb"); gint count; AUDDBG("filename=%s\n", filename); @@ -96,8 +102,8 @@ playlist_save_pls(const gchar *filename, gint pos) g_return_if_fail(file != NULL); - aud_vfs_fprintf(file, "[playlist]\n"); - aud_vfs_fprintf(file, "NumberOfEntries=%d\n", entries - pos); + vfs_fprintf(file, "[playlist]\n"); + vfs_fprintf(file, "NumberOfEntries=%d\n", entries - pos); for (count = pos; count < entries; count ++) { @@ -105,16 +111,16 @@ playlist_save_pls(const gchar *filename, gint pos) count); gchar *fn; - if (aud_vfs_is_remote (filename)) + if (vfs_is_remote (filename)) fn = g_strdup (filename); else fn = g_filename_from_uri (filename, NULL, NULL); - aud_vfs_fprintf (file, "File%d=%s\n", 1 + pos + count, fn); + vfs_fprintf (file, "File%d=%s\n", 1 + pos + count, fn); g_free(fn); } - aud_vfs_fclose(file); + vfs_fclose(file); } PlaylistContainer plc_pls = { diff --git a/src/pls/util.c b/src/pls/util.c new file mode 100644 index 0000000..9d605a2 --- /dev/null +++ b/src/pls/util.c @@ -0,0 +1,284 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005-2009 Audacious development team + * + * Based on BMP: + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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, see <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <stdlib.h> +#include <string.h> + +#include <audacious/plugin.h> + +#include "util.h" + +static void strip_string(GString *string) +{ + while (string->len > 0 && string->str[0] == ' ') + g_string_erase(string, 0, 1); + + while (string->len > 0 && string->str[string->len - 1] == ' ') + g_string_erase(string, string->len - 1, 1); +} + +static void strip_lower_string(GString *string) +{ + gchar *lower; + strip_string(string); + + lower = g_ascii_strdown(string->str, -1); + g_free(string->str); + string->str = lower; +} + +static void close_ini_file_free_value(gpointer value) +{ + g_free((gchar *)value); +} + +static void close_ini_file_free_section(gpointer section) +{ + g_hash_table_destroy((GHashTable *)section); +} + +INIFile *open_ini_file(const gchar *filename) +{ + GHashTable *ini_file = NULL; + GHashTable *section = NULL; + GString *section_name, *key_name, *value; + gpointer section_hash, key_hash; + guchar * buffer = NULL; + gsize off = 0; + gint64 filesize = 0; + + unsigned char x[] = { 0xff, 0xfe, 0x00 }; + + g_return_val_if_fail(filename, NULL); + vfs_file_get_contents(filename, (void * *) &buffer, &filesize); + if (buffer == NULL) + return NULL; + + /* + * Convert UTF-16 into something useful. Original implementation + * by incomp@#audacious. Cleanups \nenolod + * FIXME: can't we use a GLib function for that? -- 01mf02 + */ + if (filesize > 2 && !memcmp(&buffer[0], &x, 2)) + { + guchar *outbuf = g_malloc (filesize); /* it's safe to waste memory. */ + guint counter; + + for (counter = 2; counter < filesize; counter += 2) + { + if (!memcmp(&buffer[counter + 1], &x[2], 1)) + { + outbuf[(counter - 2) / 2] = buffer[counter]; + } + else + { + g_free(buffer); + g_free(outbuf); + return NULL; + } + } + + outbuf[(counter - 2) / 2] = '\0'; + + if ((filesize - 2) / 2 == (counter - 2) / 2) + { + g_free(buffer); + buffer = outbuf; + } + else + { + g_free(buffer); + g_free(outbuf); + return NULL; /* XXX wrong encoding */ + } + } + + section_name = g_string_new(""); + key_name = g_string_new(NULL); + value = g_string_new(NULL); + + ini_file = + g_hash_table_new_full(NULL, NULL, NULL, close_ini_file_free_section); + section = + g_hash_table_new_full(NULL, NULL, NULL, close_ini_file_free_value); + /* make a nameless section which should store all entries that are not + * embedded in a section */ + section_hash = GINT_TO_POINTER(g_string_hash(section_name)); + g_hash_table_insert(ini_file, section_hash, section); + + while (off < filesize) + { + /* ignore the following characters */ + if (buffer[off] == '\r' || buffer[off] == '\n' || buffer[off] == ' ' + || buffer[off] == '\t') + { + if (buffer[off] == '\n') + { + g_string_free(key_name, TRUE); + g_string_free(value, TRUE); + key_name = g_string_new(NULL); + value = g_string_new(NULL); + } + + off++; + continue; + } + + /* if we encounter a possible section statement */ + if (buffer[off] == '[') + { + g_string_free(section_name, TRUE); + section_name = g_string_new(NULL); + off++; + + if (off >= filesize) + goto return_sequence; + + while (buffer[off] != ']') + { + /* if the section statement has not been closed before a + * linebreak */ + if (buffer[off] == '\n') + break; + + g_string_append_c(section_name, buffer[off]); + off++; + if (off >= filesize) + goto return_sequence; + } + if (buffer[off] == '\n') + continue; + if (buffer[off] == ']') + { + off++; + if (off >= filesize) + goto return_sequence; + + strip_lower_string(section_name); + section_hash = GINT_TO_POINTER(g_string_hash(section_name)); + + /* if this section already exists, we don't make a new one, + * but reuse the old one */ + if (g_hash_table_lookup(ini_file, section_hash) != NULL) + section = g_hash_table_lookup(ini_file, section_hash); + else + { + section = + g_hash_table_new_full(NULL, NULL, NULL, + close_ini_file_free_value); + g_hash_table_insert(ini_file, section_hash, section); + } + + continue; + } + } + + if (buffer[off] == '=') + { + off++; + if (off >= filesize) + goto return_sequence; + + while (buffer[off] != '\n' && buffer[off] != '\r') + { + g_string_append_c(value, buffer[off]); + off++; + if (off >= filesize) + break; + } + + strip_lower_string(key_name); + key_hash = GINT_TO_POINTER(g_string_hash(key_name)); + strip_string(value); + + if (key_name->len > 0 && value->len > 0) + g_hash_table_insert(section, key_hash, g_strdup(value->str)); + } + else + { + g_string_append_c(key_name, buffer[off]); + off++; + if (off >= filesize) + goto return_sequence; + } + } + + return_sequence: + g_string_free(section_name, TRUE); + g_string_free(key_name, TRUE); + g_string_free(value, TRUE); + g_free(buffer); + return ini_file; +} + +/** + * Frees the memory allocated for inifile. + */ +void close_ini_file(INIFile *inifile) +{ + g_return_if_fail(inifile); + g_hash_table_destroy(inifile); +} + +/** + * Returns a string that corresponds to correct section and key in inifile. + * + * Returns NULL if value was not found in inifile. Otherwise returns a copy + * of string pointed by "section" and "key". Returned string should be freed + * after use. + */ +gchar *read_ini_string(INIFile *inifile, const gchar *section, const gchar *key) +{ + GString *section_string; + GString *key_string; + gchar *value = NULL; + gpointer section_hash, key_hash; + GHashTable *section_table; + + g_return_val_if_fail(inifile, NULL); + + section_string = g_string_new(section); + key_string = g_string_new(key); + value = NULL; + + strip_lower_string(section_string); + strip_lower_string(key_string); + section_hash = GINT_TO_POINTER(g_string_hash(section_string)); + key_hash = GINT_TO_POINTER(g_string_hash(key_string)); + section_table = g_hash_table_lookup(inifile, section_hash); + + if (section_table) + { + value = + g_strdup(g_hash_table_lookup + (section_table, GINT_TO_POINTER(key_hash))); + } + + g_string_free(section_string, TRUE); + g_string_free(key_string, TRUE); + + g_return_val_if_fail(value, NULL); + return value; +} diff --git a/src/pls/util.h b/src/pls/util.h new file mode 100644 index 0000000..db2d141 --- /dev/null +++ b/src/pls/util.h @@ -0,0 +1,38 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005-2009 Audacious development team + * + * Based on BMP: + * Copyright (C) 2003-2004 BMP development team + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team + * + * 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; under version 3 of the License. + * + * 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, see <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef UTIL_H +#define UTIL_H + +#include <glib.h> + +typedef GHashTable INIFile; + +INIFile *open_ini_file(const gchar *filename); +void close_ini_file(INIFile *key_file); +gchar *read_ini_string(INIFile *key_file, const gchar *section, + const gchar *key); + +#endif diff --git a/src/projectm-1.0/gtk_projectm_impl.cxx b/src/projectm-1.0/gtk_projectm_impl.cxx index d9e5cb7..ab7809b 100755 --- a/src/projectm-1.0/gtk_projectm_impl.cxx +++ b/src/projectm-1.0/gtk_projectm_impl.cxx @@ -27,13 +27,14 @@ #include <GL/gl.h> #define CONFIG_FILE "/share/projectM/config.inp" -// Forward declarations +// Forward declarations static std::string read_config(); int SDLThreadWrapper(void *); void handle_playback_trigger(void *, void *); static void _gtk_projectm_realize_impl(GtkWidget *widget, gpointer data); +static void unrealize_cb (GtkWidget * widget, struct _GtkProjectMPrivate * priv); static gboolean _gtk_projectm_redraw_impl(GtkWidget *widget); static gboolean _gtk_projectm_expose_impl(GtkWidget *widget, GdkEventExpose *event, gpointer data); static gboolean _gtk_projectm_configure_impl(GtkWidget *widget, GdkEventConfigure *event, gpointer data); @@ -66,6 +67,8 @@ gtk_projectm_new(void) g_signal_connect_after(G_OBJECT(priv->drawing_area), "realize", G_CALLBACK(_gtk_projectm_realize_impl), priv); + g_signal_connect (priv->drawing_area, "unrealize", (GCallback) unrealize_cb, + priv); g_signal_connect(G_OBJECT(priv->drawing_area), "expose_event", G_CALLBACK(_gtk_projectm_expose_impl), priv); g_signal_connect(G_OBJECT(priv->drawing_area), "destroy", @@ -85,9 +88,9 @@ gtk_projectm_add_pcm_data(GtkWidget *widget, gint16 pcm_data[2][512]) struct _GtkProjectMPrivate *priv = (struct _GtkProjectMPrivate *) g_object_get_data(G_OBJECT(widget), "GtkProjectMPrivate"); g_return_if_fail(priv != NULL); - g_return_if_fail(priv->pm != NULL); - priv->pm->pcm()->addPCM16(pcm_data); + if (priv->pm != NULL) + priv->pm->pcm()->addPCM16 (pcm_data); } extern "C" void @@ -135,6 +138,7 @@ _gtk_projectm_realize_impl(GtkWidget *widget, gpointer data) std::string configFile = read_config(); priv->pm = new projectM(configFile); + priv->pm->projectM_resetGL(widget->allocation.width, widget->allocation.height); gdk_gl_drawable_swap_buffers(gldrawable); @@ -148,6 +152,21 @@ _gtk_projectm_realize_impl(GtkWidget *widget, gpointer data) priv->drawing_area); } +static void unrealize_cb (GtkWidget * widget, struct _GtkProjectMPrivate * priv) +{ + if (priv->idle_id) + { + g_source_remove (priv->idle_id); + priv->idle_id = 0; + } + + if (priv->pm != NULL) + { + delete priv->pm; + priv->pm = NULL; + } +} + static gboolean _gtk_projectm_configure_impl(GtkWidget *widget, GdkEventConfigure *event, gpointer data) { @@ -155,6 +174,9 @@ _gtk_projectm_configure_impl(GtkWidget *widget, GdkEventConfigure *event, gpoint GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget); struct _GtkProjectMPrivate *priv = (struct _GtkProjectMPrivate *) data; + if (priv->pm == NULL) + return FALSE; + if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) return FALSE; diff --git a/src/projectm-1.0/main.c b/src/projectm-1.0/main.c index 3bbe68f..6e8161e 100644 --- a/src/projectm-1.0/main.c +++ b/src/projectm-1.0/main.c @@ -13,30 +13,19 @@ #include "gtk_projectm_impl.h" -GtkWidget *projectm = NULL; -GtkWidget *window = NULL; - -void -projectM_init(void) -{ - projectm = gtk_projectm_new(); - gtk_container_add(GTK_CONTAINER(window), projectm); - gtk_widget_show(projectm); -} +static GtkWidget *projectm = NULL; GtkWidget * projectM_get_widget(void) { - return projectm; -} - -void -projectM_cleanup(void) -{ - g_return_if_fail(window != NULL); + if (projectm == NULL) + { + projectm = gtk_projectm_new (); + g_signal_connect (projectm, "destroy", (GCallback) gtk_widget_destroyed, + & projectm); + } - gtk_widget_destroy(window); - window = NULL; + return projectm; } void @@ -50,8 +39,6 @@ projectM_render_pcm(gint16 pcm_data[2][512]) VisPlugin projectM_vtable = { .description = "projectM", .num_pcm_chs_wanted = 2, - .init = projectM_init, - .cleanup = projectM_cleanup, .render_pcm = projectM_render_pcm, .get_widget = projectM_get_widget, }; diff --git a/src/projectm/main.c b/src/projectm/main.c index 8dd7633..b7ece38 100644 --- a/src/projectm/main.c +++ b/src/projectm/main.c @@ -132,10 +132,10 @@ int get_xmms_title(void) { } #endif - pos = audacious_drct_pl_get_pos(); + pos = aud_drct_pl_get_pos(); /* Only check every 1 second for title change, otherwise check pos */ if(check_title || pos != last_pos) { - title = audacious_drct_pl_get_title(pos); + title = aud_drct_pl_get_title(pos); if(title && (!last_title || strcmp(last_title,title))) { globalPM->title = title; globalPM->drawtitle = 1; diff --git a/src/psf/plugin.c b/src/psf/plugin.c index 44e24ab..b6f1de5 100644 --- a/src/psf/plugin.c +++ b/src/psf/plugin.c @@ -28,7 +28,9 @@ #include <stdlib.h> #include <string.h> +#include <audacious/misc.h> #include <audacious/plugin.h> +#include <libaudcore/tuple_formatter.h> #include "ao.h" #include "corlett.h" @@ -78,7 +80,7 @@ static gchar *path; int ao_get_lib(char *filename, uint8 **buffer, uint64 *length) { - guchar *filebuf; + void *filebuf; gint64 size; char buf[PATH_MAX]; gchar path2[PATH_MAX]; @@ -86,7 +88,7 @@ int ao_get_lib(char *filename, uint8 **buffer, uint64 *length) g_strlcpy(path2, path, PATH_MAX); snprintf(buf, PATH_MAX, "%s/%s", dirname(path2), filename); - aud_vfs_file_get_contents (buf, & filebuf, & size); + vfs_file_get_contents (buf, & filebuf, & size); *buffer = filebuf; *length = (uint64)size; @@ -100,10 +102,10 @@ Tuple *psf2_tuple(const gchar *filename) { Tuple *t; corlett_t *c; - guchar *buf; + void *buf; gint64 sz; - aud_vfs_file_get_contents (filename, & buf, & sz); + vfs_file_get_contents (filename, & buf, & sz); if (!buf) return NULL; @@ -111,17 +113,17 @@ Tuple *psf2_tuple(const gchar *filename) if (corlett_decode(buf, sz, NULL, NULL, &c) != AO_SUCCESS) return NULL; - t = aud_tuple_new_from_filename(filename); + t = tuple_new_from_filename(filename); - aud_tuple_associate_int(t, FIELD_LENGTH, NULL, c->inf_length ? psfTimeToMS(c->inf_length) + psfTimeToMS(c->inf_fade) : -1); - aud_tuple_associate_string(t, FIELD_ARTIST, NULL, c->inf_artist); - aud_tuple_associate_string(t, FIELD_ALBUM, NULL, c->inf_game); - aud_tuple_associate_string(t, -1, "game", c->inf_game); - aud_tuple_associate_string(t, FIELD_TITLE, NULL, c->inf_title); - aud_tuple_associate_string(t, FIELD_COPYRIGHT, NULL, c->inf_copy); - aud_tuple_associate_string(t, FIELD_QUALITY, NULL, "sequenced"); - aud_tuple_associate_string(t, FIELD_CODEC, NULL, "PlayStation 1/2 Audio"); - aud_tuple_associate_string(t, -1, "console", "PlayStation 1/2"); + tuple_associate_int(t, FIELD_LENGTH, NULL, c->inf_length ? psfTimeToMS(c->inf_length) + psfTimeToMS(c->inf_fade) : -1); + tuple_associate_string(t, FIELD_ARTIST, NULL, c->inf_artist); + tuple_associate_string(t, FIELD_ALBUM, NULL, c->inf_game); + tuple_associate_string(t, -1, "game", c->inf_game); + tuple_associate_string(t, FIELD_TITLE, NULL, c->inf_title); + tuple_associate_string(t, FIELD_COPYRIGHT, NULL, c->inf_copy); + tuple_associate_string(t, FIELD_QUALITY, NULL, "sequenced"); + tuple_associate_string(t, FIELD_CODEC, NULL, "PlayStation 1/2 Audio"); + tuple_associate_string(t, -1, "console", "PlayStation 1/2"); free(c); g_free(buf); @@ -136,9 +138,9 @@ gchar *psf2_title(gchar *filename, gint *length) if (tuple != NULL) { - title = aud_tuple_formatter_make_title_string(tuple, aud_get_gentitle_format()); - *length = aud_tuple_get_int(tuple, FIELD_LENGTH, NULL); - aud_tuple_free(tuple); + title = tuple_formatter_make_title_string(tuple, aud_get_gentitle_format()); + *length = tuple_get_int(tuple, FIELD_LENGTH, NULL); + tuple_free(tuple); } else { @@ -151,7 +153,7 @@ gchar *psf2_title(gchar *filename, gint *length) void psf2_play(InputPlayback *data) { - guchar *buffer; + void *buffer; gint64 size; gint length; gchar *title = psf2_title(data->filename, &length); @@ -159,7 +161,7 @@ void psf2_play(InputPlayback *data) PSFEngineFunctors *f; path = g_strdup(data->filename); - aud_vfs_file_get_contents (data->filename, & buffer, & size); + vfs_file_get_contents (data->filename, & buffer, & size); eng = psf_probe(buffer); if (eng == ENG_NONE || eng == ENG_COUNT) @@ -263,7 +265,7 @@ void psf2_pause(InputPlayback *playback, short p) int psf2_is_our_fd(const gchar *filename, VFSFile *file) { uint8 magic[4]; - aud_vfs_fread(magic, 1, 4, file); + vfs_fread(magic, 1, 4, file); return (psf_probe(magic) != ENG_NONE); } diff --git a/src/pulse_audio/pulse_audio.c b/src/pulse_audio/pulse_audio.c index 18f3140..96fbfa6 100644 --- a/src/pulse_audio/pulse_audio.c +++ b/src/pulse_audio/pulse_audio.c @@ -27,11 +27,14 @@ #include <limits.h> #include <gtk/gtk.h> +#include <pulse/pulseaudio.h> + +#include <audacious/debug.h> +#include <audacious/drct.h> #include <audacious/plugin.h> #include <audacious/i18n.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> -#include <pulse/pulseaudio.h> #define ERROR(...) do {fprintf (stderr, "pulseaudio: " __VA_ARGS__); putchar ('\n');} while (0) @@ -66,15 +69,15 @@ do { \ if (!connected) return retval; \ } while (0); -static const char* get_song_name(void) { - static char t[256]; - char *str, *u; - - if (!(str = aud_playback_get_title())) - return "Playback Stream"; - snprintf(t, sizeof(t), "%s", u = pa_locale_to_utf8(str)); - pa_xfree(u); +static const gchar * get_song_name (void) +{ + if (! aud_drct_get_playing ()) /* just probing? */ + return ""; + gchar * title = aud_drct_get_title (); + static gchar t[512]; + snprintf (t, sizeof (t), "%s", title); + g_free (title); return t; } @@ -508,7 +511,7 @@ static void pulse_close(void) volume_time_event = NULL; } -static int pulse_open(AFormat fmt, int rate, int nch) { +static int pulse_open(gint fmt, int rate, int nch) { pa_sample_spec ss; pa_operation *o = NULL; int success; diff --git a/src/resample/plugin.c b/src/resample/plugin.c index 8ebf62d..8017f69 100644 --- a/src/resample/plugin.c +++ b/src/resample/plugin.c @@ -19,13 +19,13 @@ #include <gtk/gtk.h> -#include "config.h" - +#include <audacious/configdb.h> #include <audacious/i18n.h> #include <audacious/plugin.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> +#include "config.h" #include "resample.h" int common_rates[] = {8000, 16000, 22050, 44100, 48000, 96000, 192000}; diff --git a/src/roaraudio/KNOWN-ISSUES b/src/roaraudio/KNOWN-ISSUES new file mode 100644 index 0000000..5fc2322 --- /dev/null +++ b/src/roaraudio/KNOWN-ISSUES @@ -0,0 +1,6 @@ +- volume is not retained across restarts: + we could save our preferred volume as a preference. + +- in some instances, roaraudio may suspend itself and our connection is lost: + we can send roar_noop() every so often to keep the connection and soundserver + alive. diff --git a/src/roaraudio/Makefile b/src/roaraudio/Makefile index 3748687..01d29ac 100644 --- a/src/roaraudio/Makefile +++ b/src/roaraudio/Makefile @@ -1,12 +1,12 @@ PLUGIN = roar${PLUGIN_SUFFIX} -SRCS = roar.c gui.c +SRCS = roar.c include ../../buildsys.mk include ../../extra.mk plugindir := ${plugindir}/${OUTPUT_PLUGIN_DIR} -CFLAGS += ${PLUGIN_CFLAGS} -CPPFLAGS += ${PLUGIN_CPPFLAGS} ${BEEP_DEFINES} ${MOWGLI_CFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} -I../.. -LIBS += -lroar ${GTK_LIBS} ${GLIB_LIBS} +CFLAGS += ${PLUGIN_CFLAGS} -std=gnu99 +CPPFLAGS += ${PLUGIN_CPPFLAGS} ${BEEP_DEFINES} ${MOWGLI_CFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} ${LIBROAR_CFLAGS} -I../.. +LIBS += ${LIBROAR_LIBS} ${GTK_LIBS} ${GLIB_LIBS} diff --git a/src/roaraudio/all.h b/src/roaraudio/all.h index 2693b65..e7cbba5 100644 --- a/src/roaraudio/all.h +++ b/src/roaraudio/all.h @@ -27,6 +27,8 @@ #ifndef _ALL_H_ #define _ALL_H_ +#include <config.h> + #include <roaraudio.h> #include <gtk/gtk.h> @@ -34,62 +36,66 @@ #include <stdio.h> #include <string.h> +#include <audacious/debug.h> #include <audacious/configdb.h> -#include <audacious/util.h> +#include <audacious/playlist.h> #include <audacious/plugin.h> -#include <audacious/audctrl.h> +#include <audacious/i18n.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> +OutputPluginInitStatus aud_roar_init(void); -#define _(x) (x) - -gint ctrlsocket_get_session_id(void); - -OutputPluginInitStatus roar_init(void); -void roar_about(void); -void roar_configure(void); - -void roar_get_volume(int *l, int *r); -void roar_set_volume(int l, int r); -void roar_mixer_init(void); -void roar_mixer_init_vol(int l, int r); +void aud_roar_get_volume(int *l, int *r); +void aud_roar_set_volume(int l, int r); +void aud_roar_mixer_init(void); +void aud_roar_mixer_init_vol(int l, int r); -int roar_playing(void); -int roar_free(void); -void roar_write(void *ptr, int length); -void roar_close(void); -void roar_flush(int time); -void roar_pause(short p); -int roar_open(AFormat fmt, int rate, int nch); -int roar_get_output_time(void); -int roar_get_written_time(void); +void aud_roar_drain(void); +void aud_roar_write(void *ptr, int length); +void aud_roar_close(void); +void aud_roar_flush(int time); +void aud_roar_pause(short p); +int aud_roar_open(gint fmt, int rate, int nch); +int aud_roar_get_output_time(void); +int aud_roar_get_written_time(void); +gboolean aud_roar_buffer_is_playing(void); +gint aud_roar_buffer_get_size(void); +void aud_roar_period_wait(void); -int roar_update_metadata(void); -int roar_chk_metadata(void); +int aud_roar_update_metadata(void); +int aud_roar_chk_metadata(void); #define STATE_CONNECTED 1 #define STATE_PLAYING 2 #define STATE_NORECONNECT 4 -struct xmms_roar_out { - int state; - char * server; - struct roar_connection con; - struct roar_stream stream; - int data_fh; - long unsigned int written; - long unsigned int bps; - int session; - int pause; - struct { - int server_type; - int port; - int * proxy_type; - char * proxy; - char * player_name; - } cfg; +struct xmms_aud_roar_out +{ + int state; + char *server; + struct roar_vio_calls vio; + struct roar_connection con; + struct roar_stream stream; + long unsigned int written; + long unsigned int bps; + int pause; + int rate; + int nch; + int bits; + int codec; + int mixer[2]; + gsize block_size; + gint64 sampleoff; + struct + { + int server_type; + int port; + int *proxy_type; + char *proxy; + char *player_name; + } cfg; } g_inst; #endif diff --git a/src/roaraudio/gui.c b/src/roaraudio/gui.c deleted file mode 100644 index 63741ba..0000000 --- a/src/roaraudio/gui.c +++ /dev/null @@ -1,339 +0,0 @@ -//gui.c: - -/* - * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008, - * Daniel Duntemann <dauxx@dauxx.org> - 2009 - * - * This file is part of the XMMS RoarAudio output plugin a part of RoarAudio, - * a cross-platform sound system for both, home and professional use. - * See README for details. - * - * This file is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 - * as published by the Free Software Foundation. - * - * RoarAudio 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 software; see the file COPYING. If not, write to - * the Free Software Foundation, 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include "all.h" - -// ABOUT: - -void roar_about(void) { - static GtkWidget *window = NULL; - - audgui_simple_message(&window, GTK_MESSAGE_INFO, - _("About RoarAudio Plugin"), - _("RoarAudio Audacious Plugin..." - )); -} - -// CONFIG: - -void on_button_ok_enter(GtkButton * button, gpointer user_data) { -} - -void roar_configure(void) { - GtkWidget *config_win; - GtkWidget *vbox_main; - GtkWidget *tabs_main; - GtkWidget *frame_server; - GtkWidget *alignment_server; - GtkWidget *table1; - GtkWidget *label_server_type; - GtkWidget *label_server_host; - GtkWidget *label_server_port; - GtkObject *input_server_port_adj; - GtkWidget *input_server_port; - GtkWidget *input_server_host; -/* - GtkWidget *input_server_type; -*/ - GtkWidget *label_host; - GtkWidget *label_server; - GtkWidget *frame_proxy; - GtkWidget *alignment_proxy; - GtkWidget *table2; - GtkWidget *label_proxy_type; - GtkWidget *label_proxy_addr; - GtkWidget *input_proxy_host; -/* - GtkWidget *input_proxy_type; -*/ - GtkWidget *label_frame_proxy; - GtkWidget *label_proxy; - GtkWidget *vbox_meta; - GtkWidget *frame_meta_player; - GtkWidget *alignment1; - GtkWidget *hbox_meta_player; - GtkWidget *label_player_name; - GtkWidget *input_meta_player_name; - GtkWidget *label_player; - GtkWidget *frame_meta_title; - GtkWidget *alignment2; - GtkWidget *hbox_meta_title; -/* - GtkWidget *input_meta_send_title; - GtkWidget *input_meta_send_filename; -*/ - GtkWidget *label_meta_title; - GtkWidget *label_meta; - GtkWidget *hbox_buttons; - GtkWidget *button_ok; - GtkWidget *button_cancel; - - config_win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(config_win), _("RoarAudio Plugin - Configuration")); -// gtk_window_set_destroy_with_parent(GTK_WINDOW(config_win), TRUE); -// gtk_window_set_icon_name(GTK_WINDOW(config_win), "gtk-preferences"); - - gtk_widget_show (config_win); - - vbox_main = gtk_vbox_new (FALSE, 0); - gtk_widget_show (vbox_main); - gtk_container_add (GTK_CONTAINER (config_win), vbox_main); - - tabs_main = gtk_notebook_new (); - gtk_widget_show (tabs_main); - gtk_box_pack_start (GTK_BOX (vbox_main), tabs_main, TRUE, TRUE, 0); - - frame_server = gtk_frame_new (NULL); - gtk_widget_show (frame_server); - gtk_container_add (GTK_CONTAINER (tabs_main), frame_server); - gtk_frame_set_shadow_type (GTK_FRAME (frame_server), GTK_SHADOW_NONE); - - alignment_server = gtk_alignment_new (0.5, 0.5, 1, 1); - gtk_widget_show (alignment_server); - gtk_container_add (GTK_CONTAINER (frame_server), alignment_server); -// gtk_alignment_set_padding (GTK_ALIGNMENT (alignment_server), 0, 0, 12, 0); - - table1 = gtk_table_new (3, 2, FALSE); - gtk_widget_show (table1); - gtk_container_add (GTK_CONTAINER (alignment_server), table1); - - label_server_type = gtk_label_new (_("Server Type:")); - gtk_widget_show (label_server_type); - gtk_table_attach (GTK_TABLE (table1), label_server_type, 0, 1, 0, 1, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - gtk_misc_set_alignment (GTK_MISC (label_server_type), 0, 0.5); - - label_server_host = gtk_label_new (_("Host or Path:")); - gtk_widget_show (label_server_host); - gtk_table_attach (GTK_TABLE (table1), label_server_host, 0, 1, 1, 2, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - gtk_misc_set_alignment (GTK_MISC (label_server_host), 0, 0.5); - - label_server_port = gtk_label_new (_("Port:")); - gtk_widget_show (label_server_port); - gtk_table_attach (GTK_TABLE (table1), label_server_port, 0, 1, 2, 3, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - gtk_misc_set_alignment (GTK_MISC (label_server_port), 0, 0.5); - - input_server_port_adj = gtk_adjustment_new (16002, 0, 65535, 1, 10, 10); - input_server_port = gtk_spin_button_new (GTK_ADJUSTMENT (input_server_port_adj), 1, 0); - gtk_widget_show (input_server_port); - gtk_table_attach (GTK_TABLE (table1), input_server_port, 1, 2, 2, 3, - (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - - input_server_host = gtk_entry_new (); - gtk_widget_show (input_server_host); - gtk_table_attach (GTK_TABLE (table1), input_server_host, 1, 2, 1, 2, - (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - -/* - input_server_type = gtk_combo_box_entry_new_text (); - gtk_widget_show (input_server_type); - gtk_table_attach (GTK_TABLE (table1), input_server_type, 1, 2, 0, 1, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (GTK_FILL), 0, 0); - gtk_combo_box_append_text (GTK_COMBO_BOX (input_server_type), _("Local")); - gtk_combo_box_append_text (GTK_COMBO_BOX (input_server_type), _("TCP/IP")); - gtk_combo_box_append_text (GTK_COMBO_BOX (input_server_type), _("DECnet")); - gtk_combo_box_append_text (GTK_COMBO_BOX (input_server_type), _("Fork")); -*/ - label_host = gtk_label_new (_("<b>Host:</b>")); - gtk_widget_show (label_host); -// gtk_frame_set_label_widget (GTK_FRAME (frame_server), label_host); -// gtk_label_set_use_markup (GTK_LABEL (label_host), TRUE); - - label_server = gtk_label_new (_("Server & Network")); - gtk_widget_show (label_server); - gtk_notebook_set_tab_label (GTK_NOTEBOOK (tabs_main), gtk_notebook_get_nth_page (GTK_NOTEBOOK (tabs_main), 0), label_server); - - frame_proxy = gtk_frame_new (NULL); - gtk_widget_show (frame_proxy); - gtk_container_add (GTK_CONTAINER (tabs_main), frame_proxy); - gtk_frame_set_shadow_type (GTK_FRAME (frame_proxy), GTK_SHADOW_NONE); - - alignment_proxy = gtk_alignment_new (0.5, 0.5, 1, 1); - gtk_widget_show (alignment_proxy); - gtk_container_add (GTK_CONTAINER (frame_proxy), alignment_proxy); -// gtk_alignment_set_padding (GTK_ALIGNMENT (alignment_proxy), 0, 0, 12, 0); - - table2 = gtk_table_new (2, 2, FALSE); - gtk_widget_show (table2); - gtk_container_add (GTK_CONTAINER (alignment_proxy), table2); - - label_proxy_type = gtk_label_new (_("Type:")); - gtk_widget_show (label_proxy_type); - gtk_table_attach (GTK_TABLE (table2), label_proxy_type, 0, 1, 0, 1, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - gtk_misc_set_alignment (GTK_MISC (label_proxy_type), 0, 0.5); - - label_proxy_addr = gtk_label_new (_("Proxy Address")); - gtk_widget_show (label_proxy_addr); - gtk_table_attach (GTK_TABLE (table2), label_proxy_addr, 0, 1, 1, 2, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - gtk_misc_set_alignment (GTK_MISC (label_proxy_addr), 0, 0.5); - - input_proxy_host = gtk_entry_new (); - gtk_widget_show (input_proxy_host); - gtk_table_attach (GTK_TABLE (table2), input_proxy_host, 1, 2, 1, 2, - (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - -/* - input_proxy_type = gtk_combo_box_entry_new_text (); - gtk_widget_show (input_proxy_type); - gtk_table_attach (GTK_TABLE (table2), input_proxy_type, 1, 2, 0, 1, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (GTK_FILL), 0, 0); - gtk_combo_box_append_text (GTK_COMBO_BOX (input_proxy_type), _("None")); - gtk_combo_box_append_text (GTK_COMBO_BOX (input_proxy_type), _("SOCKS4")); - gtk_combo_box_append_text (GTK_COMBO_BOX (input_proxy_type), _("SOCKS4a")); - gtk_combo_box_append_text (GTK_COMBO_BOX (input_proxy_type), _("SOCKS4d")); - gtk_combo_box_append_text (GTK_COMBO_BOX (input_proxy_type), _("HTTP Connect")); - gtk_combo_box_append_text (GTK_COMBO_BOX (input_proxy_type), _("SSH")); -*/ - - label_frame_proxy = gtk_label_new (_("<b>Proxy</b>")); - gtk_widget_show (label_frame_proxy); -/* - gtk_frame_set_label_widget (GTK_FRAME (frame_proxy), label_frame_proxy); - gtk_label_set_use_markup (GTK_LABEL (label_frame_proxy), TRUE); -*/ - - label_proxy = gtk_label_new (_("Proxy")); - gtk_widget_show (label_proxy); - gtk_notebook_set_tab_label (GTK_NOTEBOOK (tabs_main), gtk_notebook_get_nth_page (GTK_NOTEBOOK (tabs_main), 1), label_proxy); - - vbox_meta = gtk_vbox_new (FALSE, 0); - gtk_widget_show (vbox_meta); - gtk_container_add (GTK_CONTAINER (tabs_main), vbox_meta); - - frame_meta_player = gtk_frame_new (NULL); - gtk_widget_show (frame_meta_player); - gtk_box_pack_start (GTK_BOX (vbox_meta), frame_meta_player, TRUE, TRUE, 0); - gtk_frame_set_shadow_type (GTK_FRAME (frame_meta_player), GTK_SHADOW_NONE); - - alignment1 = gtk_alignment_new (0.5, 0.5, 1, 1); - gtk_widget_show (alignment1); - gtk_container_add (GTK_CONTAINER (frame_meta_player), alignment1); -// gtk_alignment_set_padding (GTK_ALIGNMENT (alignment1), 0, 0, 12, 0); - - hbox_meta_player = gtk_hbox_new (FALSE, 0); - gtk_widget_show (hbox_meta_player); - gtk_container_add (GTK_CONTAINER (alignment1), hbox_meta_player); - - label_player_name = gtk_label_new (_("Player Name:")); - gtk_widget_show (label_player_name); - gtk_box_pack_start (GTK_BOX (hbox_meta_player), label_player_name, FALSE, FALSE, 0); - - input_meta_player_name = gtk_entry_new (); - gtk_widget_show (input_meta_player_name); - gtk_box_pack_start (GTK_BOX (hbox_meta_player), input_meta_player_name, TRUE, TRUE, 0); - gtk_entry_set_text (GTK_ENTRY (input_meta_player_name), _("Audacious")); - - label_player = gtk_label_new (_("<b>Player</b>")); - gtk_widget_show (label_player); -/* - gtk_frame_set_label_widget (GTK_FRAME (frame_meta_player), label_player); - gtk_label_set_use_markup (GTK_LABEL (label_player), TRUE); -*/ - - frame_meta_title = gtk_frame_new (NULL); - gtk_widget_show (frame_meta_title); - gtk_box_pack_start (GTK_BOX (vbox_meta), frame_meta_title, TRUE, TRUE, 0); - gtk_frame_set_shadow_type (GTK_FRAME (frame_meta_title), GTK_SHADOW_NONE); - - alignment2 = gtk_alignment_new (0.5, 0.5, 1, 1); - gtk_widget_show (alignment2); - gtk_container_add (GTK_CONTAINER (frame_meta_title), alignment2); -// gtk_alignment_set_padding (GTK_ALIGNMENT (alignment2), 0, 0, 12, 0); - - hbox_meta_title = gtk_hbox_new (FALSE, 0); - gtk_widget_show (hbox_meta_title); - gtk_container_add (GTK_CONTAINER (alignment2), hbox_meta_title); - -/* - input_meta_send_title = gtk_check_button_new_with_mnemonic (_("Send song title to server")); - gtk_widget_show (input_meta_send_title); - gtk_box_pack_start (GTK_BOX (hbox_meta_title), input_meta_send_title, FALSE, FALSE, 0); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (input_meta_send_title), TRUE); - - input_meta_send_filename = gtk_check_button_new_with_mnemonic (_("Send song filename to server")); - gtk_widget_show (input_meta_send_filename); - gtk_box_pack_start (GTK_BOX (hbox_meta_title), input_meta_send_filename, FALSE, FALSE, 0); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (input_meta_send_filename), TRUE); -*/ - - label_meta_title = gtk_label_new (_("<b>Current Song</b>")); - gtk_widget_show (label_meta_title); -/* - gtk_frame_set_label_widget (GTK_FRAME (frame_meta_title), label_meta_title); - gtk_label_set_use_markup (GTK_LABEL (label_meta_title), TRUE); -*/ - - label_meta = gtk_label_new (_("Meta Data")); - gtk_widget_show (label_meta); - gtk_notebook_set_tab_label (GTK_NOTEBOOK (tabs_main), gtk_notebook_get_nth_page (GTK_NOTEBOOK (tabs_main), 2), label_meta); - - hbox_buttons = gtk_hbox_new (FALSE, 0); - gtk_widget_show (hbox_buttons); - gtk_box_pack_start (GTK_BOX (vbox_main), hbox_buttons, TRUE, TRUE, 0); - - - button_ok = gtk_button_new_with_label(_("OK")); - gtk_box_pack_start (GTK_BOX (hbox_buttons), button_ok, FALSE, FALSE, 0); - - button_cancel = gtk_button_new_with_label(_("Cancel")); - gtk_signal_connect_object(GTK_OBJECT(button_cancel), "clicked", - GTK_SIGNAL_FUNC(gtk_widget_destroy), - GTK_OBJECT(config_win)); - gtk_box_pack_start (GTK_BOX (hbox_buttons), button_cancel, FALSE, FALSE, 0); - -/* - button_ok = gtk_button_new_from_stock ("gtk-ok"); - gtk_widget_show (button_ok); - gtk_box_pack_start (GTK_BOX (hbox_buttons), button_ok, FALSE, FALSE, 0); - - button_cancel = gtk_button_new_from_stock ("gtk-cancel"); - gtk_widget_show (button_cancel); - gtk_box_pack_start (GTK_BOX (hbox_buttons), button_cancel, FALSE, FALSE, 0); - - g_signal_connect_swapped ((gpointer) button_ok, "clicked", - G_CALLBACK (on_button_ok_enter), - GTK_OBJECT (config_win)); - g_signal_connect_swapped ((gpointer) button_cancel, "clicked", - G_CALLBACK (gtk_widget_destroy), - GTK_OBJECT (config_win)); -*/ -} - -//ll diff --git a/src/roaraudio/roar.c b/src/roaraudio/roar.c index 71b0f69..6c43c22 100644 --- a/src/roaraudio/roar.c +++ b/src/roaraudio/roar.c @@ -1,8 +1,7 @@ -//roar.c: - /* - * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008, - * Daniel Duntemann <dauxx@dauxx.org> - 2009 + * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2010, + * Daniel Duntemann <dauxx@dauxx.org> - 2009, + * William Pitcock <nenolod@atheme.org> - 2010. * * This file is part of the Audacious RoarAudio output plugin a part of RoarAudio, * a cross-platform sound system for both, home and professional use. @@ -24,361 +23,424 @@ * */ -#include "all.h" +/* + * NOTE: Do not spam with requests. You WILL get kicked out on Linux. + */ -// FIXME: This interface has been changed -gint ctrlsocket_get_session_id(void) { - return -1; -} +#include "all.h" OutputPlugin roar_op = { - .description = "RoarAudio Output Plugin", - .init = roar_init, - .cleanup = NULL, - .about = roar_about, - .configure = roar_configure, - .get_volume = roar_get_volume, - .set_volume = roar_set_volume, - .open_audio = roar_open, - .write_audio = roar_write, - .close_audio = roar_close, - .flush = roar_flush, - .pause = roar_pause, - .buffer_free = roar_free, - .buffer_playing = roar_playing, - .output_time = roar_get_output_time, - .written_time = roar_get_written_time, - .tell_audio = NULL + .description = "RoarAudio Output Plugin", + .init = aud_roar_init, + .cleanup = NULL, + .get_volume = aud_roar_get_volume, + .set_volume = aud_roar_set_volume, + .open_audio = aud_roar_open, + .write_audio = aud_roar_write, + .close_audio = aud_roar_close, + .flush = aud_roar_flush, + .pause = aud_roar_pause, + .output_time = aud_roar_get_output_time, + .written_time = aud_roar_get_written_time, + .buffer_playing = aud_roar_buffer_is_playing, + .buffer_free = aud_roar_buffer_get_size, +// .period_wait = aud_roar_period_wait, }; OutputPlugin *roar_oplist[] = { &roar_op, NULL }; +SIMPLE_OUTPUT_PLUGIN(roaraudio, roar_oplist); +OutputPluginInitStatus aud_roar_init(void) +{ + mcs_handle_t *cfgfile; -SIMPLE_OUTPUT_PLUGIN("RoarAudio Audacious Plugin",roar_oplist); - -OutputPlugin *get_oplugin_info(void) { - return &roar_op; -} - -OutputPluginInitStatus roar_init(void) { - mcs_handle_t * cfgfile; - - cfgfile = aud_cfg_db_open(); + cfgfile = aud_cfg_db_open(); - g_inst.state = 0; - g_inst.server = NULL; - g_inst.session = ctrlsocket_get_session_id(); + g_inst.state = 0; + g_inst.server = NULL; + g_inst.mixer[0] = g_inst.mixer[1] = 100; - aud_cfg_db_get_string(cfgfile, "ROAR", "server", &g_inst.server); + aud_cfg_db_close(cfgfile); - aud_cfg_db_get_string(cfgfile, "ROAR", "player_name", &g_inst.cfg.player_name); + if (!(g_inst.state & STATE_CONNECTED)) + { + if (roar_simple_connect(&(g_inst.con), NULL, "Audacious") == -1) + return OUTPUT_PLUGIN_INIT_FAIL; - aud_cfg_db_close(cfgfile); + g_inst.state |= STATE_CONNECTED; + } - if ( g_inst.cfg.player_name == NULL ) - g_inst.cfg.player_name = "Audacious"; + return OUTPUT_PLUGIN_INIT_FOUND_DEVICES; +} - ROAR_DBG("roar_init(*) = (void)"); - return OUTPUT_PLUGIN_INIT_FOUND_DEVICES; +void aud_roar_write(void *ptr, int length) +{ + int r; + + while (length) + { + if ((r = roar_vio_write(&(g_inst.vio), ptr, length >= g_inst.block_size ? g_inst.block_size : length)) != -1) + { + g_inst.written += r; + ptr += r; + length -= r; + } + else + { + return; + } + } } -int roar_playing(void) { - return FALSE; +gboolean aud_roar_initialize_stream(struct roar_vio_calls *calls, struct roar_connection *con, struct roar_stream *stream, int rate, int nch, int bits, int codec, int dir) +{ + struct roar_stream_info info; + + if (roar_vio_simple_new_stream_obj(&(g_inst.vio), &(g_inst.con), &(g_inst.stream), rate, nch, bits, codec, ROAR_DIR_PLAY) == -1) + return FALSE; + + g_inst.bits = bits; + g_inst.nch = nch; + g_inst.rate = rate; + g_inst.codec = codec; + g_inst.written = 0; + g_inst.pause = 0; + g_inst.sampleoff = 0; + g_inst.state |= STATE_PLAYING; + g_inst.block_size = 0; + + if (roar_stream_get_info(&(g_inst.con), &(g_inst.stream), &info) != -1) + { + /* XXX: this is wrong. */ + g_inst.block_size = info.block_size * 2; + AUDDBG("setting block size to %d\n", g_inst.block_size); + } + + roar_stream_set_role(&(g_inst.con), &(g_inst.stream), ROAR_ROLE_MUSIC); + aud_roar_set_volume(g_inst.mixer[0], g_inst.mixer[1]); + + return TRUE; } -void roar_write(void *ptr, int length) { - int r; +int aud_roar_open(gint fmt, int rate, int nch) +{ + int codec = ROAR_CODEC_DEFAULT; + int bits; + + bits = 16; + switch (fmt) + { + case FMT_S8: + bits = 8; + codec = ROAR_CODEC_DEFAULT; + break; + case FMT_U8: + bits = 8; + codec = ROAR_CODEC_PCM_U_LE; // _LE, _BE, _PDP,... all the same for 8 bit output + break; + case FMT_U16_LE: + codec = ROAR_CODEC_PCM_U_LE; + break; + case FMT_U16_BE: + codec = ROAR_CODEC_PCM_U_BE; + break; + case FMT_S16_LE: + codec = ROAR_CODEC_PCM_S_LE; + break; + case FMT_S16_BE: + codec = ROAR_CODEC_PCM_S_BE; + break; +#if 0 +/* RoarAudio don't use this stupid 24bit-in-lower-part-of-32bit-int format */ + case FMT_U24_LE: /* stored in lower 3 bytes of 32-bit value, highest byte must be 0 */ + codec = ROAR_CODEC_PCM_U_LE; + bits = 24; + break; + case FMT_U24_BE: + codec = ROAR_CODEC_PCM_U_BE; + bits = 24; + break; + case FMT_S24_LE: + bits = 24; + codec = ROAR_CODEC_PCM_S_LE; + break; + case FMT_S24_BE: + bits = 24; + codec = ROAR_CODEC_PCM_S_BE; + break; +#endif + case FMT_U32_LE: /* highest byte must be 0 */ + codec = ROAR_CODEC_PCM_U_LE; + bits = 32; + break; + case FMT_U32_BE: + codec = ROAR_CODEC_PCM_U_BE; + bits = 32; + break; + case FMT_S32_LE: + bits = 32; + codec = ROAR_CODEC_PCM_S_LE; + break; + case FMT_S32_BE: + bits = 32; + codec = ROAR_CODEC_PCM_S_BE; + break; + case FMT_FLOAT: + default: + return FALSE; + break; + } + + g_inst.bps = nch * rate * bits / 8; + + if (!aud_roar_initialize_stream(&(g_inst.vio), &(g_inst.con), &(g_inst.stream), rate, nch, bits, codec, ROAR_DIR_PLAY)) + return FALSE; + + aud_roar_update_metadata(); + + return TRUE; +} - if ( g_inst.pause ) - return; +void aud_roar_close(void) +{ + gint id; - ROAR_DBG("roar_write(ptr=%p, length=%i) = (void)", ptr, length); + id = roar_stream_get_id(&(g_inst.stream)); + roar_kick(&(g_inst.con), ROAR_OT_STREAM, id); + roar_vio_close(&(g_inst.vio)); - while (length) { - if ( (r = write(g_inst.data_fh, ptr, length >= 17640 ? 17640 : length)) != -1 ) { - g_inst.written += r; - ptr += r; - length -= r; - } else { - return; - } - } + g_inst.state &= ~STATE_PLAYING; + g_inst.written = 0; } -int roar_open(AFormat fmt, int rate, int nch) { - int codec = ROAR_CODEC_DEFAULT; - int bits; - - if ( !(g_inst.state & STATE_CONNECTED) ) { - if ( roar_simple_connect(&(g_inst.con), g_inst.server, g_inst.cfg.player_name) == -1 ) { - return FALSE; - } - g_inst.state |= STATE_CONNECTED; - } - - bits = 16; - switch (fmt) { - case FMT_S8: - bits = 8; - codec = ROAR_CODEC_DEFAULT; - break; - case FMT_U8: - bits = 8; - codec = ROAR_CODEC_PCM_U_LE; // _LE, _BE, _PDP,... all the same for 8 bit output - break; - case FMT_U16_LE: - codec = ROAR_CODEC_PCM_U_LE; - break; - case FMT_U16_BE: - codec = ROAR_CODEC_PCM_U_BE; - break; - case FMT_S16_LE: - codec = ROAR_CODEC_PCM_S_LE; - break; - case FMT_S16_BE: - codec = ROAR_CODEC_PCM_S_BE; - break; - case FMT_U24_LE: /* stored in lower 3 bytes of 32-bit value, highest byte must be 0 */ - codec = ROAR_CODEC_PCM_U_LE; - bits = 24; - break; - case FMT_U24_BE: - codec = ROAR_CODEC_PCM_U_BE; - bits = 24; - break; - case FMT_S24_LE: - bits = 24; - codec = ROAR_CODEC_PCM_S_LE; - break; - case FMT_S24_BE: - bits = 24; - codec = ROAR_CODEC_PCM_S_BE; - break; - case FMT_U32_LE: /* highest byte must be 0 */ - codec = ROAR_CODEC_PCM_U_LE; - bits = 32; - break; - case FMT_U32_BE: - codec = ROAR_CODEC_PCM_U_BE; - bits = 32; - break; - case FMT_S32_LE: - bits = 32; - codec = ROAR_CODEC_PCM_S_LE; - break; - case FMT_S32_BE: - bits = 32; - codec = ROAR_CODEC_PCM_S_BE; - break; - case FMT_FLOAT: - ROAR_DBG("roar_open(*): FMT_FLOAT"); - break; - } - - ROAR_DBG("roar_open(*): fmt %i", fmt); - - g_inst.bps = nch * rate * bits / 8; - - roar_close(); - - if ( (g_inst.data_fh = roar_simple_new_stream_obj(&(g_inst.con), &(g_inst.stream), - rate, nch, bits, codec, ROAR_DIR_PLAY)) == -1) { - roar_disconnect(&(g_inst.con)); - g_inst.state |= STATE_CONNECTED; - g_inst.state -= STATE_CONNECTED; - if ( !(g_inst.state & STATE_NORECONNECT) ) { - g_inst.state |= STATE_NORECONNECT; - usleep(100000); - return roar_open(fmt, rate, nch); - } else { - g_inst.state -= STATE_NORECONNECT; - return FALSE; - } - } - g_inst.state |= STATE_PLAYING; - - g_inst.written = 0; - g_inst.pause = 0; - -#ifdef _WITH_BROKEN_CODE - roar_update_metadata(); -#endif +void aud_roar_pause(short p) +{ + if (p) + roar_stream_set_flags(&(g_inst.con), &(g_inst.stream), ROAR_FLAG_PAUSE, ROAR_SET_FLAG); + else + roar_stream_set_flags(&(g_inst.con), &(g_inst.stream), ROAR_FLAG_PAUSE, ROAR_RESET_FLAG); - return TRUE; + g_inst.pause = p; } -void roar_close(void) { - if ( g_inst.data_fh != -1 ) - close(g_inst.data_fh); - g_inst.data_fh = -1; - g_inst.state |= STATE_PLAYING; - g_inst.state -= STATE_PLAYING; - g_inst.written = 0; - ROAR_DBG("roar_close(void) = (void)"); -} +void aud_roar_flush(int time) +{ + gint64 r = time; -void roar_pause(short p) { - g_inst.pause = p; -} + r *= g_inst.bps; + r /= 1000; -int roar_free(void) { - if ( g_inst.pause ) - return 0; - else - return 1000000; // ??? + aud_roar_close(); + if (!aud_roar_initialize_stream(&(g_inst.vio), &(g_inst.con), &(g_inst.stream), + g_inst.rate, g_inst.nch, g_inst.bits, g_inst.codec, ROAR_DIR_PLAY)) + return; + + g_inst.written = r; + g_inst.sampleoff = ((time / 1000) * g_inst.rate) * g_inst.nch; } -void roar_flush(int time) { - gint64 r = time; +gint64 aud_roar_get_adjusted_sample_count(void) +{ + gint id; + gint64 samples; - r *= g_inst.bps; - r /= 1000; + /* first update our stream record. */ + id = roar_stream_get_id(&(g_inst.stream)); + roar_get_stream(&(g_inst.con), &(g_inst.stream), id); - g_inst.written = r; -} + /* calculate the time, given our sample count. */ + samples = g_inst.stream.pos; + samples += g_inst.sampleoff; -int roar_get_output_time(void) { - return roar_get_written_time(); + return samples; } -int roar_get_written_time(void) { - gint64 r; +int aud_roar_get_output_time(void) +{ + gint64 samples; - if ( !g_inst.bps ) { - ROAR_DBG("roar_get_written_time(void) = 0"); - return 0; - } + samples = aud_roar_get_adjusted_sample_count(); - r = g_inst.written; - r *= 1000; // sec -> msec - r /= g_inst.bps; - ROAR_DBG("roar_get_written_time(void) = %lu", r); - - return r; + return (samples * 1000) / (g_inst.rate * g_inst.nch); } +int aud_roar_get_written_time(void) +{ + gint64 r; -// META DATA: + if (!g_inst.bps) + return 0; -int roar_update_metadata(void) { -#ifdef _WITH_BROKEN_CODE - struct roar_meta meta; - char empty = 0; - char * info = NULL; - int pos; + r = g_inst.written; + r *= 1000; // sec -> msec + r /= g_inst.bps; - pos = audacious_remote_get_playlist_pos(g_inst.session); + return r; +} - meta.value = ∅ - meta.key[0] = 0; - meta.type = ROAR_META_TYPE_NONE; +// META DATA: +int aud_roar_update_metadata(void) +{ + struct roar_meta meta; + char empty = 0; + const gchar *info = NULL; + gint pos, playlist; + const Tuple *songtuple; + gint i; + static struct { int ac_metatype, ra_metatype; } metamap[] = { + {FIELD_ARTIST, ROAR_META_TYPE_ARTIST}, + {FIELD_TITLE, ROAR_META_TYPE_TITLE}, + {FIELD_ALBUM, ROAR_META_TYPE_ALBUM}, + {FIELD_COMMENT, ROAR_META_TYPE_COMMENT}, + {FIELD_GENRE, ROAR_META_TYPE_GENRE}, + {FIELD_PERFORMER, ROAR_META_TYPE_PERFORMER}, + {FIELD_COPYRIGHT, ROAR_META_TYPE_COPYRIGHT}, + {FIELD_DATE, ROAR_META_TYPE_DATE}, + }; + + playlist = aud_playlist_get_active(); + pos = aud_playlist_get_position(playlist); + + meta.value = ∅ + meta.key[0] = 0; + meta.type = ROAR_META_TYPE_NONE; + + roar_stream_meta_set(&(g_inst.con), &(g_inst.stream), ROAR_META_MODE_CLEAR, &meta); + + info = aud_playlist_entry_get_filename(playlist, pos); + if (info) + { + if (strncmp(info, "http://", 7) == 0) + meta.type = ROAR_META_TYPE_FILEURL; + else + meta.type = ROAR_META_TYPE_FILENAME; + + meta.value = g_strdup(info); + roar_stream_meta_set(&(g_inst.con), &(g_inst.stream), ROAR_META_MODE_SET, &meta); + + free(meta.value); + } + + songtuple = aud_playlist_entry_get_tuple(playlist, pos, TRUE); + if (songtuple) + { + for (i = 0; i < sizeof(metamap)/sizeof(*metamap); i++) + { + if ((info = tuple_get_string(songtuple, metamap[i].ac_metatype, NULL))) + { + meta.type = metamap[i].ra_metatype; + meta.value = g_strdup(info); + + roar_stream_meta_set(&(g_inst.con), &(g_inst.stream), ROAR_META_MODE_SET, &meta); + + free(meta.value); + } + } + } + + meta.value = ∅ + meta.type = ROAR_META_TYPE_NONE; + roar_stream_meta_set(&(g_inst.con), &(g_inst.stream), ROAR_META_MODE_FINALIZE, &meta); + + return 0; +} - roar_stream_meta_set(&(g_inst.con), &(g_inst.stream), ROAR_META_MODE_CLEAR, &meta); +// MIXER: +void aud_roar_get_volume(int *l, int *r) +{ + struct roar_mixer_settings mixer; + int channels; + float fs; - info = audacious_remote_get_playlist_file(g_inst.session, pos); + if (!(g_inst.state & STATE_CONNECTED)) + return; - if ( info ) { - if ( strncmp(info, "http:", 5) == 0 ) - meta.type = ROAR_META_TYPE_FILEURL; - else - meta.type = ROAR_META_TYPE_FILENAME; +#ifdef NOTYET + if (roar_get_vol(&(g_inst.con), g_inst.stream.id, &mixer, &channels) == -1) + return; - meta.value = info; - ROAR_DBG("roar_update_metadata(*): setting meta data: type=%i, strlen(value)=%i", meta.type, strlen(info)); - roar_stream_meta_set(&(g_inst.con), &(g_inst.stream), ROAR_META_MODE_SET, &meta); + if (channels == 1) + mixer.mixer[1] = mixer.mixer[0]; - free(info); - } + fs = (float)mixer.scale/100.; - info = audacious_remote_get_playlist_title(g_inst.session, pos); - if ( info ) { - meta.type = ROAR_META_TYPE_TITLE; + *l = g_inst.mixer[0] = mixer.mixer[0] / fs; + *r = g_inst.mixer[1] = mixer.mixer[1] / fs; +#else + *l = g_inst.mixer[0]; + *r = g_inst.mixer[1]; +#endif +} - meta.value = info; - roar_stream_meta_set(&(g_inst.con), &(g_inst.stream), ROAR_META_MODE_SET, &meta); +void aud_roar_set_volume(int l, int r) +{ + struct roar_mixer_settings mixer; - free(info); - } + if (!(g_inst.state & STATE_CONNECTED)) + return; - meta.value = ∅ - meta.type = ROAR_META_TYPE_NONE; - roar_stream_meta_set(&(g_inst.con), &(g_inst.stream), ROAR_META_MODE_FINALIZE, &meta); + mixer.mixer[0] = g_inst.mixer[0] = l; + mixer.mixer[1] = g_inst.mixer[1] = r; -#endif - return 0; + mixer.scale = 100; + + roar_set_vol(&(g_inst.con), g_inst.stream.id, &mixer, 2); } -int roar_chk_metadata(void) { -#ifdef _WITH_BROKEN_CODE - static int old_pos = -1; - static char * old_title = "NEW TITLE"; - int pos; - char * title; - int need_update = 0; - - pos = audacious_remote_get_playlist_pos(g_inst.session); - - if ( pos != old_pos ) { - old_pos = pos; - need_update = 1; - } else { - title = audacious_remote_get_playlist_title(g_inst.session, pos); - - if ( strcmp(title, old_title) ) { - free(old_title); - old_title = title; - need_update = 1; - } else { - free(title); - } - } - - if ( need_update ) { - roar_update_metadata(); - } +gboolean aud_roar_buffer_is_playing(void) +{ + struct roar_stream_info info; -#endif - return 0; -} + if (!(g_inst.state & STATE_CONNECTED)) + return FALSE; -// MIXER: + if (!(g_inst.state & STATE_PLAYING)) + return FALSE; + if (roar_stream_get_info(&(g_inst.con), &(g_inst.stream), &info) == -1) + return FALSE; -void roar_get_volume(int *l, int *r) { - struct roar_mixer_settings mixer; - int channels; - float fs; + if (info.post_underruns) + return FALSE; - if ( !(g_inst.state & STATE_CONNECTED) ) - return; + return TRUE; +} - if ( roar_get_vol(&(g_inst.con), g_inst.stream.id, &mixer, &channels) == -1 ) { - *l = *r = 100; - return; - } +/* this really sucks. */ +gboolean aud_roar_vio_is_writable(struct roar_vio_calls *vio) +{ + struct roar_vio_select vios[1]; - fs = (float)mixer.scale/100.; + ROAR_VIO_SELECT_SETVIO(&vios[0], vio, ROAR_VIO_SELECT_WRITE); - if ( channels == 1 ) { - *l = *r = mixer.mixer[0]/fs; - } else { - *l = mixer.mixer[0]/fs; - *r = mixer.mixer[1]/fs; - } + return roar_vio_select(vios, 1, &(struct roar_vio_selecttv){ .nsec = 1 }, NULL); } -void roar_set_volume(int l, int r) { - struct roar_mixer_settings mixer; +gint aud_roar_buffer_get_size(void) +{ + if (!(g_inst.state & STATE_CONNECTED)) + return 0; - if ( !(g_inst.state & STATE_CONNECTED) ) - return; + if (!(g_inst.state & STATE_PLAYING)) + return 0; - mixer.mixer[0] = l; - mixer.mixer[1] = r; + if (!aud_roar_vio_is_writable(&(g_inst.vio))) + return 0; - mixer.scale = 100; + if (g_inst.block_size != 0) + return g_inst.block_size; - roar_set_vol(&(g_inst.con), g_inst.stream.id, &mixer, 2); + return 0; } -//ll +void aud_roar_period_wait(void) +{ + struct roar_vio_select vios[1]; + + if (!(g_inst.state & STATE_PLAYING)) + return; + + ROAR_VIO_SELECT_SETVIO(&vios[0], &(g_inst.vio), ROAR_VIO_SELECT_WRITE); + + roar_vio_select(vios, 1, NULL, NULL); +} diff --git a/src/scrobbler/Makefile b/src/scrobbler/Makefile index 797246f..eebfa3d 100644 --- a/src/scrobbler/Makefile +++ b/src/scrobbler/Makefile @@ -5,9 +5,6 @@ SRCS = fmt.c \ scrobbler.c \ plugin.c -DATA = images/audioscrobbler.png \ - images/audioscrobbler_badge.png - include ../../buildsys.mk include ../../extra.mk diff --git a/src/scrobbler/configure.c b/src/scrobbler/configure.c index bad295d..a545a88 100644 --- a/src/scrobbler/configure.c +++ b/src/scrobbler/configure.c @@ -9,13 +9,14 @@ #include <stdio.h> #include <glib.h> -#include <audacious/plugin.h> -#include <libaudcore/md5.h> -#include <audacious/i18n.h> - #include <gdk/gdkkeysyms.h> #include <gtk/gtk.h> +#include <audacious/configdb.h> +#include <audacious/i18n.h> +#include <audacious/preferences.h> +#include <libaudcore/md5.h> + #include "plugin.h" GtkWidget *entry1, *entry2, *entry3, *ge_entry1, *ge_entry2, *cfgdlg; @@ -164,7 +165,6 @@ create_cfgdlg(void) GtkWidget *label1; GtkWidget *label2; GtkWidget *label4; - GtkWidget *himage1; GtkWidget *align1; GtkWidget *notebook1; GtkStyle *style; @@ -234,7 +234,7 @@ create_cfgdlg(void) NULL); gtk_widget_show (entry2); gtk_table_attach_defaults (GTK_TABLE (table1), entry2, 1, 2, 3, 4); - + entry3 = gtk_entry_new (); gtk_widget_show (entry3); gtk_table_attach_defaults (GTK_TABLE (table1), entry3, 1, 2, 4, 5); @@ -246,11 +246,6 @@ create_cfgdlg(void) // common gtk_box_pack_start (GTK_BOX (vbox2), notebook1, TRUE, TRUE, 6); - himage1 = gtk_image_new_from_file (DATA_DIR "/images/audioscrobbler_badge.png"); - gtk_widget_show (himage1); - gtk_box_pack_start (GTK_BOX (vbox2), himage1, FALSE, FALSE, 0); - gtk_misc_set_alignment (GTK_MISC (himage1), 1, 0.5); - gtk_entry_set_text(GTK_ENTRY(entry1), ""); gtk_entry_set_text(GTK_ENTRY(ge_entry1), ""); @@ -265,14 +260,14 @@ create_cfgdlg(void) g_free(username); username = NULL; } - + aud_cfg_db_get_string(db, "audioscrobbler", "sc_url", &sc_url); if (sc_url) { gtk_entry_set_text(GTK_ENTRY(entry3), sc_url); g_free(sc_url); sc_url = NULL; } - + aud_cfg_db_close(db); } @@ -285,15 +280,13 @@ create_cfgdlg(void) /* TODO: don't use WIDGET_CUSTOM there */ static PreferencesWidget settings[] = { - {WIDGET_CUSTOM, NULL, NULL, NULL, NULL, FALSE, {.populate = create_cfgdlg}}, + {WIDGET_CUSTOM, NULL, NULL, NULL, NULL, FALSE, {.populate = create_cfgdlg}}, }; PluginPreferences preferences = { .title = N_("Scrobbler"), - .imgurl = DATA_DIR "/images/audioscrobbler.png", .prefs = settings, .n_prefs = G_N_ELEMENTS(settings), - .type = PREFERENCES_PAGE, .apply = configure_apply, .cleanup = configure_cleanup, }; diff --git a/src/scrobbler/images/audioscrobbler.png b/src/scrobbler/images/audioscrobbler.png Binary files differdeleted file mode 100644 index 784ce4b..0000000 --- a/src/scrobbler/images/audioscrobbler.png +++ /dev/null diff --git a/src/scrobbler/images/audioscrobbler_badge.png b/src/scrobbler/images/audioscrobbler_badge.png Binary files differdeleted file mode 100644 index 3fe05f0..0000000 --- a/src/scrobbler/images/audioscrobbler_badge.png +++ /dev/null diff --git a/src/scrobbler/plugin.c b/src/scrobbler/plugin.c index f839e43..c998759 100644 --- a/src/scrobbler/plugin.c +++ b/src/scrobbler/plugin.c @@ -7,9 +7,13 @@ #include <gdk/gdkkeysyms.h> #include <gtk/gtk.h> +#include <audacious/configdb.h> +#include <audacious/debug.h> +#include <audacious/playlist.h> #include <audacious/plugin.h> #include <audacious/preferences.h> -#include <audacious/hook.h> +#include <libaudcore/audstrings.h> +#include <libaudcore/hook.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> @@ -43,7 +47,7 @@ Tuple *submit_tuple = NULL; static gboolean ishttp(const char *a) { g_return_val_if_fail(a != NULL, FALSE); - return aud_str_has_prefix_nocase(a, "http://") || aud_str_has_prefix_nocase(a, "https://"); + return str_has_prefix_nocase(a, "http://") || str_has_prefix_nocase(a, "https://"); } static void aud_hook_playback_begin(gpointer hook_data, gpointer user_data) @@ -52,7 +56,7 @@ static void aud_hook_playback_begin(gpointer hook_data, gpointer user_data) gint pos = aud_playlist_get_position(playlist); const Tuple *tuple; - if (aud_playlist_entry_get_length(playlist, pos) < (glong)30) + if (aud_playlist_entry_get_length (playlist, pos, FALSE) < 30) { AUDDBG(" *** not submitting due to entry->length < 30"); return; @@ -66,7 +70,7 @@ static void aud_hook_playback_begin(gpointer hook_data, gpointer user_data) sc_idle(m_scrobbler); - tuple = aud_playlist_entry_get_tuple(playlist, pos); + tuple = aud_playlist_entry_get_tuple (playlist, pos, FALSE); if (tuple == NULL) return; @@ -74,7 +78,7 @@ static void aud_hook_playback_begin(gpointer hook_data, gpointer user_data) mowgli_object_unref(submit_tuple); submit_tuple = tuple_copy(tuple); - sc_addentry(m_scrobbler, submit_tuple, aud_tuple_get_int(submit_tuple, FIELD_LENGTH, NULL) / 1000); + sc_addentry(m_scrobbler, submit_tuple, tuple_get_int(submit_tuple, FIELD_LENGTH, NULL) / 1000); if (!track_timeout) track_timeout = g_timeout_add_seconds(1, sc_timeout, NULL); @@ -110,7 +114,7 @@ void start(void) { aud_cfg_db_get_string(cfgfile, "audioscrobbler", "password", &password); aud_cfg_db_get_string(cfgfile, "audioscrobbler", "sc_url", - &sc_url); + &sc_url); aud_cfg_db_get_string(cfgfile, "audioscrobbler", "ge_username", &ge_username); aud_cfg_db_get_string(cfgfile, "audioscrobbler", "ge_password", @@ -132,11 +136,11 @@ void start(void) { g_free(password); g_free(sc_url); } - + m_scrobbler = g_mutex_new(); - aud_hook_associate("playback begin", aud_hook_playback_begin, NULL); - aud_hook_associate("playback stop", aud_hook_playback_end, NULL); + hook_associate("playback begin", aud_hook_playback_begin, NULL); + hook_associate("playback stop", aud_hook_playback_end, NULL); AUDDBG("plugin started"); sc_idle(m_scrobbler); @@ -155,8 +159,8 @@ void stop(void) { g_mutex_free(m_scrobbler); - aud_hook_dissociate("playback begin", aud_hook_playback_begin); - aud_hook_dissociate("playback stop", aud_hook_playback_end); + hook_dissociate("playback begin", aud_hook_playback_begin); + hook_dissociate("playback stop", aud_hook_playback_end); } static void init(void) diff --git a/src/scrobbler/scrobbler.c b/src/scrobbler/scrobbler.c index 0104543..daf5b4d 100644 --- a/src/scrobbler/scrobbler.c +++ b/src/scrobbler/scrobbler.c @@ -1,4 +1,3 @@ -#define DEBUG #include <pthread.h> #include <limits.h> #include <stdlib.h> @@ -12,6 +11,9 @@ #include "settings.h" #include <glib.h> +#include <audacious/drct.h> +#include <audacious/debug.h> +#include <audacious/misc.h> #include <audacious/plugin.h> #include <libaudcore/md5.h> @@ -144,14 +146,14 @@ static item_t *create_item(Tuple *tuple, int len) item = malloc(sizeof(item_t)); - item->artist = fmt_escape(aud_tuple_get_string(tuple, FIELD_ARTIST, NULL)); - item->title = fmt_escape(aud_tuple_get_string(tuple, FIELD_TITLE, NULL)); + item->artist = fmt_escape(tuple_get_string(tuple, FIELD_ARTIST, NULL)); + item->title = fmt_escape(tuple_get_string(tuple, FIELD_TITLE, NULL)); item->len = len; - item->track = aud_tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL); + item->track = tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL); item->timeplayed = 0; item->utctime = time(NULL); - album = aud_tuple_get_string(tuple, FIELD_ALBUM, NULL); + album = tuple_get_string(tuple, FIELD_ALBUM, NULL); if (album) item->album = fmt_escape((char*) album); else @@ -216,7 +218,7 @@ static int q_get(void) if (q_nitems == 0) return 0; - + item = q_queue; if(item == NULL) @@ -249,7 +251,7 @@ gboolean sc_timeout(gpointer data) { if (np_item) { - if (audacious_drct_get_playing() && !audacious_drct_get_paused()) + if (aud_drct_get_playing() && !aud_drct_get_paused()) np_item->timeplayed+=1; /* @@ -447,7 +449,7 @@ static unsigned char *md5_string(char *pass, int len) { aud_md5state_t md5state; static unsigned char md5pword[16]; - + aud_md5_init(&md5state); aud_md5_append(&md5state, (unsigned const char *)pass, len); aud_md5_finish(&md5state, md5pword); @@ -462,7 +464,7 @@ static void hexify(char *pass, int len) int i; memset(sc_response_hash, 0, sizeof(sc_response_hash)); - + for(i = 0; i < len; i++) { *(bp++) = hexchars[(pass[i] >> 4) & 0x0f]; *(bp++) = hexchars[pass[i] & 0x0f]; @@ -473,12 +475,15 @@ static void hexify(char *pass, int len) } static int sc_parse_sb_res(void); +static GStaticMutex submit_mutex = G_STATIC_MUTEX_INIT; gpointer sc_curl_perform_thread(gpointer data) { int status; CURL *curl = (CURL *) data; + g_static_mutex_lock(&submit_mutex); + status = curl_easy_perform(curl); curl_easy_cleanup(curl); @@ -487,11 +492,16 @@ gpointer sc_curl_perform_thread(gpointer data) sc_free_res(); AUDDBG("Retrying in %d secs, %d elements in queue\n", sc_submit_interval, q_nitems); + + g_static_mutex_unlock(&submit_mutex); + g_thread_exit(NULL); return NULL; } - sc_free_res(); + g_static_mutex_unlock(&submit_mutex); + + sc_free_res(); g_thread_exit(NULL); return NULL; } @@ -529,7 +539,7 @@ static int sc_handshake(void) curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1); curl_easy_setopt(curl, CURLOPT_URL, buf); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, sc_store_res); memset(sc_curl_errbuf, 0, sizeof(sc_curl_errbuf)); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, sc_curl_errbuf); @@ -556,7 +566,7 @@ static int sc_handshake(void) if (sc_challenge_hash != NULL) { aud_md5state_t md5state; unsigned char md5pword[16]; - + aud_md5_init(&md5state); /*AUDDBG("Pass Hash: %s", sc_password));*/ aud_md5_append(&md5state, (unsigned const char *)sc_password, @@ -574,7 +584,7 @@ static int sc_handshake(void) sc_free_res(); - AUDDBG("submiturl: %s - interval: %d\n", + AUDDBG("submiturl: %s - interval: %d\n", sc_submit_url, sc_submit_interval); return 0; @@ -691,7 +701,7 @@ static int sc_parse_sb_res(void) static gchar *sc_itemtag(char c, int n, char *str) { - static char buf[SCROBBLER_SB_MAXLEN]; + static char buf[SCROBBLER_SB_MAXLEN]; g_snprintf(buf, SCROBBLER_SB_MAXLEN, "&%c[%d]=%s", c, n, str); return buf; } @@ -765,15 +775,15 @@ static int sc_submit_np(Tuple *tuple) curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); /*cfa(&post, &last, "debug", "failed");*/ - char *field_artist = fmt_escape(aud_tuple_get_string(tuple, FIELD_ARTIST, NULL)); - char *field_title = fmt_escape(aud_tuple_get_string(tuple, FIELD_TITLE, NULL)); - char *field_album = aud_tuple_get_string(tuple, FIELD_ALBUM, NULL) ? fmt_escape(aud_tuple_get_string(tuple, FIELD_ALBUM, NULL)) : fmt_escape(""); + char *field_artist = fmt_escape(tuple_get_string(tuple, FIELD_ARTIST, NULL)); + char *field_title = fmt_escape(tuple_get_string(tuple, FIELD_TITLE, NULL)); + char *field_album = tuple_get_string(tuple, FIELD_ALBUM, NULL) ? fmt_escape(tuple_get_string(tuple, FIELD_ALBUM, NULL)) : fmt_escape(""); snprintf(entry, 16384, "s=%s&a=%s&t=%s&b=%s&l=%d&n=%d&m=", sc_session_id, field_artist, field_title, field_album, - aud_tuple_get_int(tuple, FIELD_LENGTH, NULL) / 1000, - aud_tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL)); + tuple_get_int(tuple, FIELD_LENGTH, NULL) / 1000, + tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL)); curl_free(field_artist); curl_free(field_title); curl_free(field_album); @@ -881,7 +891,7 @@ static void sc_handlequeue(GMutex *mutex) ( ((sc_sb_errors - 5) < 7) ? (60 << (sc_sb_errors-5)) : 7200 ); - + sc_submit_timeout = time(NULL) + wait; AUDDBG("Error while submitting. " @@ -901,7 +911,7 @@ static void read_cache(void) item_t *item; gchar* config_datadir; - config_datadir = audacious_get_localdir(); + config_datadir = aud_util_get_localdir(); g_snprintf(buf, sizeof(buf), "%s/scrobblerqueue.txt", config_datadir); g_free(config_datadir); @@ -935,21 +945,21 @@ static void read_cache(void) * we'll continue to check the value anyway, for backwards-compatibility reasons. */ if (!strncmp(entry[5], "L", 1)) { - Tuple *tuple = aud_tuple_new(); + Tuple *tuple = tuple_new(); gchar* string_value; string_value = xmms_urldecode_plain(artist); - aud_tuple_associate_string(tuple, FIELD_ARTIST, NULL, string_value); + tuple_associate_string(tuple, FIELD_ARTIST, NULL, string_value); g_free(string_value); string_value = xmms_urldecode_plain(title); - aud_tuple_associate_string(tuple, FIELD_TITLE, NULL, string_value); + tuple_associate_string(tuple, FIELD_TITLE, NULL, string_value); g_free(string_value); string_value = xmms_urldecode_plain(album); - aud_tuple_associate_string(tuple, FIELD_ALBUM, NULL, string_value); + tuple_associate_string(tuple, FIELD_ALBUM, NULL, string_value); g_free(string_value); - aud_tuple_associate_int(tuple, FIELD_TRACK_NUMBER, NULL, track); + tuple_associate_int(tuple, FIELD_TRACK_NUMBER, NULL, track); item = q_put(tuple, t, len); - aud_tuple_free(tuple); + tuple_free(tuple); AUDDBG("a[%d]=%s t[%d]=%s l[%d]=%d i[%d]=%d b[%d]=%s\n", i, I_ARTIST(item), @@ -986,7 +996,7 @@ static void dump_queue(void) return; } - config_datadir = audacious_get_localdir(); + config_datadir = aud_util_get_localdir(); g_snprintf(buf, sizeof(buf), "%s/scrobblerqueue.txt", config_datadir); g_free(config_datadir); diff --git a/src/sid/Makefile b/src/sid/Makefile index 7dd4b99..920bdf3 100644 --- a/src/sid/Makefile +++ b/src/sid/Makefile @@ -26,4 +26,4 @@ plugindir := ${plugindir}/${INPUT_PLUGIN_DIR} CFLAGS += ${PLUGIN_CFLAGS} CXXFLAGS += ${PLUGIN_CFLAGS} CPPFLAGS += ${PLUGIN_CPPFLAGS} -D_REENTRANT -I../.. -DAUDACIOUS_PLUGIN ${MOWGLI_CFLAGS} ${SIDPLAY1_CFLAGS} ${SIDPLAY2_CFLAGS} ${BUILDERS_CFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} -LIBS += ${BUILDERS_LDFLAGS} ${SIDPLAY1_LIBS} ${SIDPLAY2_LIBS} ${BUILDERS_LIBS} ${GTK_LIBS} ${GLIB_LIBS} -lstdc++ +LIBS += -lm ${BUILDERS_LDFLAGS} ${SIDPLAY1_LIBS} ${SIDPLAY2_LIBS} ${BUILDERS_LIBS} ${GTK_LIBS} ${GLIB_LIBS} -lstdc++ diff --git a/src/sid/xmms-sid.c b/src/sid/xmms-sid.c index 756fedf..f7a167b 100644 --- a/src/sid/xmms-sid.c +++ b/src/sid/xmms-sid.c @@ -22,11 +22,11 @@ */ #include "xmms-sid.h" -#ifdef HAVE_STDLIB_H #include <stdlib.h> -#endif - #include <stdarg.h> + +#include <libaudcore/audstrings.h> + #include "xs_config.h" #include "xs_length.h" #include "xs_stil.h" @@ -191,7 +191,7 @@ void xs_play_file(InputPlayback *pb) XSDEBUG("play '%s'\n", pb->filename); - tmpFilename = aud_filename_split_subtune(pb->filename, &subTune); + tmpFilename = filename_split_subtune(pb->filename, &subTune); if (tmpFilename == NULL) return; /* Get tune information */ @@ -288,7 +288,7 @@ void xs_play_file(InputPlayback *pb) /* Set song information for current subtune */ XSDEBUG("foobar #1\n"); xs_status.sidPlayer->plrUpdateSIDInfo(&xs_status); - tmpTuple = aud_tuple_new_from_filename(tmpTune->sidFilename); + tmpTuple = tuple_new_from_filename(tmpTune->sidFilename); xs_get_song_tuple_info(tmpTuple, tmpTune, xs_status.currSong); XS_MUTEX_UNLOCK(xs_status); pb->set_tuple(pb, tmpTuple); @@ -324,7 +324,7 @@ void xs_play_file(InputPlayback *pb) bufPointer = audioBuffer; while (bufRemaining > 0 && pb->playing) { gint blockSize = MIN(bufChunkSize, bufRemaining); - + pb->pass_audio(pb, xs_status.audioFormat, xs_status.audioChannels, blockSize, bufPointer, NULL); @@ -439,11 +439,11 @@ static void xs_get_song_tuple_info(Tuple *tuple, xs_tuneinfo_t *info, gint subTu { gchar *tmpStr, tmpStr2[64]; - aud_tuple_associate_string_rel(tuple, FIELD_TITLE, NULL, aud_str_to_utf8(info->sidName)); - aud_tuple_associate_string_rel(tuple, FIELD_ARTIST, NULL, aud_str_to_utf8(info->sidComposer)); - aud_tuple_associate_string_rel(tuple, FIELD_COPYRIGHT, NULL, aud_str_to_utf8(info->sidCopyright)); - aud_tuple_associate_string(tuple, -1, "sid-format", info->sidFormat); - aud_tuple_associate_string(tuple, FIELD_CODEC, NULL, "Commodore 64 SID PlaySID/RSID"); + tuple_associate_string_rel(tuple, FIELD_TITLE, NULL, str_to_utf8(info->sidName)); + tuple_associate_string_rel(tuple, FIELD_ARTIST, NULL, str_to_utf8(info->sidComposer)); + tuple_associate_string_rel(tuple, FIELD_COPYRIGHT, NULL, str_to_utf8(info->sidCopyright)); + tuple_associate_string(tuple, -1, "sid-format", info->sidFormat); + tuple_associate_string(tuple, FIELD_CODEC, NULL, "Commodore 64 SID PlaySID/RSID"); switch (info->sidModel) { case XS_SIDMODEL_6581: tmpStr = "6581"; break; @@ -451,7 +451,7 @@ static void xs_get_song_tuple_info(Tuple *tuple, xs_tuneinfo_t *info, gint subTu case XS_SIDMODEL_ANY: tmpStr = "ANY"; break; default: tmpStr = "?"; break; } - aud_tuple_associate_string(tuple, -1, "sid-model", tmpStr); + tuple_associate_string(tuple, -1, "sid-model", tmpStr); /* Get sub-tune information, if available */ if (subTune < 0 || info->startTune > info->nsubTunes) @@ -459,7 +459,7 @@ static void xs_get_song_tuple_info(Tuple *tuple, xs_tuneinfo_t *info, gint subTu if (subTune > 0 && subTune <= info->nsubTunes) { gint tmpInt = info->subTunes[subTune - 1].tuneLength; - aud_tuple_associate_int(tuple, FIELD_LENGTH, NULL, (tmpInt < 0) ? -1 : tmpInt * 1000); + tuple_associate_int(tuple, FIELD_LENGTH, NULL, (tmpInt < 0) ? -1 : tmpInt * 1000); tmpInt = info->subTunes[subTune - 1].tuneSpeed; if (tmpInt > 0) { @@ -477,25 +477,25 @@ static void xs_get_song_tuple_info(Tuple *tuple, xs_tuneinfo_t *info, gint subTu } else tmpStr = "?"; - aud_tuple_associate_string(tuple, -1, "sid-speed", tmpStr); + tuple_associate_string(tuple, -1, "sid-speed", tmpStr); } else subTune = 1; - aud_tuple_associate_int(tuple, FIELD_SUBSONG_NUM, NULL, info->nsubTunes); - aud_tuple_associate_int(tuple, FIELD_SUBSONG_ID, NULL, subTune); - aud_tuple_associate_int(tuple, FIELD_TRACK_NUMBER, NULL, subTune); + tuple_associate_int(tuple, FIELD_SUBSONG_NUM, NULL, info->nsubTunes); + tuple_associate_int(tuple, FIELD_SUBSONG_ID, NULL, subTune); + tuple_associate_int(tuple, FIELD_TRACK_NUMBER, NULL, subTune); if (xs_cfg.titleOverride) - aud_tuple_associate_string(tuple, FIELD_FORMATTER, NULL, xs_cfg.titleFormat); + tuple_associate_string(tuple, FIELD_FORMATTER, NULL, xs_cfg.titleFormat); } static void xs_fill_subtunes(Tuple *tuple, xs_tuneinfo_t *info) { gint count, found; - + tuple->subtunes = g_new(gint, info->nsubTunes); - + for (found = count = 0; count < info->nsubTunes; count++) { if (count + 1 == info->startTune || !xs_cfg.subAutoMinOnly || info->subTunes[count].tuneLength >= xs_cfg.subAutoMinTime) @@ -514,10 +514,10 @@ Tuple * xs_get_song_tuple(const gchar *filename) gint tune = -1; /* Get information from URL */ - tmpFilename = aud_filename_split_subtune(filename, &tune); + tmpFilename = filename_split_subtune(filename, &tune); if (tmpFilename == NULL) return NULL; - tuple = aud_tuple_new_from_filename(tmpFilename); + tuple = tuple_new_from_filename(tmpFilename); if (tuple == NULL) { g_free(tmpFilename); return NULL; @@ -564,10 +564,10 @@ Tuple * xs_probe_for_tuple(const gchar *filename, xs_file_t *fd) XS_MUTEX_UNLOCK(xs_status); /* Get information from URL */ - tmpFilename = aud_filename_split_subtune(filename, &tune); + tmpFilename = filename_split_subtune(filename, &tune); if (tmpFilename == NULL) return NULL; - tuple = aud_tuple_new_from_filename(tmpFilename); + tuple = tuple_new_from_filename(tmpFilename); if (tuple == NULL) { g_free(tmpFilename); return NULL; diff --git a/src/sid/xs_config.c b/src/sid/xs_config.c index 80f61f2..c4b90d1 100644 --- a/src/sid/xs_config.c +++ b/src/sid/xs_config.c @@ -1,11 +1,11 @@ -/* +/* XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS) Configuration dialog - + Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org> (C) Copyright 1999-2009 Tecnic Software productions (TNSP) - + 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 @@ -23,7 +23,10 @@ #include "xs_config.h" #ifdef AUDACIOUS_PLUGIN + +#include <audacious/configdb.h> #include <audacious/plugin.h> + #define XS_CONFIG_FILE mcs_handle_t #define XS_CONFIG_OPEN aud_cfg_db_open #define XS_CONFIG_FREE aud_cfg_db_close @@ -73,7 +76,7 @@ static GtkWidget *xs_configwin = NULL, /* Samplerates */ static const gchar *xs_samplerates_table[] = { - "8000", "11025", "22050", + "8000", "11025", "22050", "44100", "48000", "64000", "96000" }; @@ -211,7 +214,7 @@ void xs_init_configuration(void) XS_MUTEX_LOCK(xs_cfg); memset(&xs_cfg, 0, sizeof(xs_cfg)); - + /* Initialize values with sensible defaults */ xs_cfg.audioBitsPerSample = XS_RES_16BIT; xs_cfg.audioChannels = XS_CHN_MONO; @@ -312,7 +315,7 @@ static void xs_filters_error(const gchar *fmt, ...) va_end(ap); #else gchar *msg; - + va_start(ap, fmt); msg = g_strdup_vprintf(fmt, ap); va_end(ap); @@ -342,27 +345,27 @@ static gboolean xs_filter_load_into(XS_CONFIG_FILE *cfg, gint nFilter, xs_sid_fi g_snprintf(tmpKey, sizeof(tmpKey), "filter%dType", nFilter); if (!XS_CFG_GET_INT(tmpKey, &(filter->type))) return FALSE; - + g_snprintf(tmpKey, sizeof(tmpKey), "filter%dName", nFilter); if (!XS_CFG_GET_STRING(tmpKey, &tmpStr)) return FALSE; - + filter->name = g_strdup(tmpStr); if (filter->name == NULL) return FALSE; - + if (filter->type == 1) { gint i, j; - + /* Types 1 has points */ g_snprintf(tmpKey, sizeof(tmpKey), "filter%dNPoints", nFilter); if (!XS_CFG_GET_INT(tmpKey, &(filter->npoints))) return FALSE; - + g_snprintf(tmpKey, sizeof(tmpKey), "filter%dPoints", nFilter); if (!XS_CFG_GET_STRING(tmpKey, &tmpStr)) return FALSE; - + for (i = 0, j = 0; i < filter->npoints; i++, j += XS_FITEM) { if (sscanf(&tmpStr[j], "%4x%4x", &(filter->points[i].x), @@ -374,33 +377,33 @@ static gboolean xs_filter_load_into(XS_CONFIG_FILE *cfg, gint nFilter, xs_sid_fi g_snprintf(tmpKey, sizeof(tmpKey), "filter%dData", nFilter); if (!XS_CFG_GET_STRING(tmpKey, &tmpStr)) return FALSE; - + if (sscanf(tmpStr, "%f,%f,%f,%f", &filter->rate, &filter->point, &filter->voice_nonlinearity, &filter->cf_treshold) != 4) return FALSE; - + g_snprintf(tmpKey, sizeof(tmpKey), "filter%dData3", nFilter); if (!XS_CFG_GET_STRING(tmpKey, &tmpStr)) return FALSE; - + if (sscanf(tmpStr, "%f,%f,%f,%f", &filter->baseresistance, &filter->offset, &filter->steepness, &filter->minimumfetresistance) != 4) return FALSE; - + } else if (filter->type == 4) { /* Type 4 has fewer tunables */ g_snprintf(tmpKey, sizeof(tmpKey), "filter%dData4", nFilter); if (!XS_CFG_GET_STRING(tmpKey, &tmpStr)) return FALSE; - + if (sscanf(tmpStr, "%f,%f", &filter->k, &filter->b) != 2) return FALSE; } else { xs_error("Unknown filter type %d for '%s' (#%d).\n", filter->type, filter->name, nFilter); return FALSE; } - + return TRUE; } @@ -408,11 +411,11 @@ static gboolean xs_filter_load_into(XS_CONFIG_FILE *cfg, gint nFilter, xs_sid_fi static xs_sid_filter_t * xs_filter_load(XS_CONFIG_FILE *cfg, gint nFilter) { xs_sid_filter_t *filter; - + /* Allocate filter struct */ if ((filter = g_malloc0(sizeof(xs_sid_filter_t))) == NULL) return NULL; - + if (!xs_filter_load_into(cfg, nFilter, filter)) { xs_error("Error loading filter %d from configuration.\n", nFilter); xs_filter_free(filter); @@ -427,29 +430,29 @@ static gboolean xs_filter_save(XS_CONFIG_FILE *cfg, xs_sid_filter_t *pFilter, gi { gchar *tmpValue, tmpKey[64]; gint i, j; - + /* Allocate memory for value string */ tmpValue = g_malloc(sizeof(gchar) * XS_FITEM * (pFilter->npoints + 1)); if (tmpValue == NULL) return FALSE; - + /* Make value string */ for (i = 0, j = 0; i < pFilter->npoints; i++, j += XS_FITEM) { g_snprintf(&tmpValue[j], XS_FITEM+1, "%04x%04x", pFilter->points[i].x, pFilter->points[i].y); } - + /* Write into the configuration */ g_snprintf(tmpKey, sizeof(tmpKey), "filter%dName", nFilter); XS_CFG_SET_STRING(tmpKey, pFilter->name); - + g_snprintf(tmpKey, sizeof(tmpKey), "filter%dNPoints", nFilter); XS_CFG_SET_INT(tmpKey, pFilter->npoints); g_snprintf(tmpKey, sizeof(tmpKey), "filter%dPoints", nFilter); XS_CFG_SET_STRING(tmpKey, tmpValue); - + g_free(tmpValue); return TRUE; } @@ -462,14 +465,14 @@ static gboolean xs_filter_save(XS_CONFIG_FILE *cfg, xs_sid_filter_t *pFilter, gi static gboolean xs_fgetitem(gchar *inLine, size_t *linePos, gchar sep, gchar *tmpStr, size_t tmpMax) { size_t i; - + for (i = 0; i < tmpMax && inLine[*linePos] && inLine[*linePos] != sep; i++, (*linePos)++) tmpStr[i] = inLine[*linePos]; - + tmpStr[i] = 0; while (--i > 0 && isspace(tmpStr[i])) tmpStr[i] = 0; - + xs_findnext(inLine, linePos); return (inLine[*linePos] == sep); } @@ -508,13 +511,13 @@ fprintf(stderr, "xs_filters_import(%s)\n", filename); } fprintf(stderr, "importing...\n"); - + inSection = FALSE; lineNum = 0; while (fgets(inLine, XS_BUF_SIZE, inFile) != NULL && !isError) { size_t linePos = 0; lineNum++; - + xs_findnext(inLine, &linePos); if (isalpha(inLine[linePos])) { /* A new key/value pair */ @@ -524,17 +527,17 @@ fprintf(stderr, "importing...\n"); } else if (inSection) { linePos++; xs_findnext(inLine, &linePos); - + if (xs_chkf(filter, tmpStr, "points", 1)) { - + } else if (xs_chkf(filter, tmpStr, "point", 1)) { - + } else if (!g_strncasecmp(tmpStr, "type", 4)) { if (filter->type != -1) { xs_error("Filter type %d already set for '%s'\n", filter->type, sectName); } - + } else { xs_error("Unsupported definition '%s' @ '%s'\n", tmpStr, sectName); @@ -548,17 +551,17 @@ fprintf(stderr, "importing...\n"); if ((filter = g_malloc0(sizeof(xs_sid_filter_t))) == NULL) { fprintf(stderr, "could not allocate ..\n"); } else { - + } g_free(sectName); } - + /* New filter(?) section starts */ linePos++; for (i = 0; i < XS_BUF_SIZE-1 && inLine[linePos] && inLine[linePos] != ']'; i++, linePos++) tmpStr[i] = inLine[linePos]; tmpStr[i] = 0; - + if (inLine[linePos] != ']') { fprintf(stderr, "invalid! expected ']': %s\n", inLine); } else { @@ -577,7 +580,7 @@ fprintf(stderr, "importing...\n"); isError = TRUE; } } - + fclose(inFile); return TRUE; } @@ -589,11 +592,11 @@ static gboolean xs_filter_export(FILE *outFile, xs_sid_filter_t *filter) "[Filter%s]\n" "type=%d\n", filter->name, filter->type); - + if (filter->type == 1) { gint i; fprintf(outFile, "points=%d\n", filter->npoints); - + for (i = 0; i < filter->npoints; i++) { fprintf(outFile, "point%d=%d,%d\n", @@ -610,7 +613,7 @@ static gboolean xs_filter_export(FILE *outFile, xs_sid_filter_t *filter) filter->rate, filter->point, filter->voice_nonlinearity, filter->cf_treshold); - + fprintf(outFile, "Type3BaseResistance = %f\n" "Type3Offset = %f\n" @@ -618,7 +621,7 @@ static gboolean xs_filter_export(FILE *outFile, xs_sid_filter_t *filter) "Type3MinimumFETResistance = %f\n", filter->baseresistance, filter->offset, filter->steepness, filter->minimumfetresistance); - + } else if (filter->type == 4) { fprintf(outFile, "Type4K=%f\n" @@ -629,7 +632,7 @@ static gboolean xs_filter_export(FILE *outFile, xs_sid_filter_t *filter) filter->name, filter->type); return FALSE; } - + fprintf(outFile, "\n"); return TRUE; } @@ -640,18 +643,18 @@ static gboolean xs_filters_export(const gchar *filename, xs_sid_filter_t **filte gboolean result = TRUE; FILE *outFile; gint n; - + /* Open/create the file */ if ((outFile = fopen(filename, "wa")) == NULL) { xs_filters_error("Could not open '%s' for writing! Not exporting.", filename); return FALSE; } - + /* Header */ fprintf(outFile, "; SIDPlay2 compatible filter definition file\n" "; Exported by " PACKAGE_STRING "\n\n"); - + /* Write each filter spec in "INI"-style format */ for (n = 0; n < nFilters; n++) { if (!xs_filter_export(outFile, filters[n])) { @@ -659,12 +662,12 @@ static gboolean xs_filters_export(const gchar *filename, xs_sid_filter_t **filte break; } } - + fclose(outFile); - + if (!result) xs_filters_error("Some filters could not be exported!"); - + return result; } @@ -706,7 +709,7 @@ void xs_read_configuration(void) XS_CFG_GET_FLOAT(xs_cfgtable[i].itemName, (gfloat *) xs_cfgtable[i].itemData); break; - + case CTYPE_STR: if (XS_CFG_GET_STRING(xs_cfgtable[i].itemName, (gchar **) &tmpStr)) { @@ -716,10 +719,10 @@ void xs_read_configuration(void) break; } } - + /* Filters and presets are a special case */ xs_filter_load_into(cfg, 0, &xs_cfg.sid2Filter); - + if (xs_cfg.sid2NFilterPresets > 0) { xs_cfg.sid2FilterPresets = g_malloc0(xs_cfg.sid2NFilterPresets * sizeof(xs_sid_filter_t *)); if (!xs_cfg.sid2FilterPresets) { @@ -806,7 +809,7 @@ void xs_cfg_ok(void) gfloat tmpValue; gint tmpInt; const gchar *tmpStr; - + xs_stop(NULL); /* Get lock on configuration */ @@ -832,7 +835,7 @@ void xs_cfg_ok(void) *((gint *) xs_widtable[i].itemData) = tmpInt; break; - + case WTYPE_SPIN: case WTYPE_SCALE: /* Get the value */ @@ -844,7 +847,7 @@ void xs_cfg_ok(void) case WTYPE_SCALE: tmpValue = gtk_range_get_adjustment(GTK_RANGE(LUW(xs_widtable[i].widName)))->value; break; - + default: tmpValue = -1; break; @@ -875,7 +878,7 @@ void xs_cfg_ok(void) break; } } - + /* Get filter settings */ /* if (!xs_curve_get_points(XS_CURVE(LUW("")), &xs_cfg.sid2Filter.points, &xs_cfg.sid2Filter.npoints)) { @@ -885,7 +888,7 @@ void xs_cfg_ok(void) /* Release lock */ XS_MUTEX_UNLOCK(xs_cfg); - + /* Close window */ gtk_widget_destroy(xs_configwin); xs_configwin = NULL; @@ -905,7 +908,7 @@ gboolean xs_confirmwin_delete(GtkWidget *widget, GdkEvent *event, gpointer user_ (void) widget; (void) event; (void) user_data; - + return FALSE; } @@ -935,7 +938,7 @@ void xs_sldb_fs_ok(GtkButton *button, gpointer user_data) { (void) button; (void) user_data; - + /* Selection was accepted! */ gtk_entry_set_text(GTK_ENTRY(LUW("cfg_sld_dbpath")), gtk_file_selection_get_filename(GTK_FILE_SELECTION(xs_sldb_fileselector))); @@ -1044,7 +1047,7 @@ void xs_cfg_sp2_filter_update(XSCurve *curve, xs_sid_filter_t *f) { assert(curve); assert(f); - + xs_curve_reset(curve); xs_curve_set_range(curve, 0,0, XS_SIDPLAY2_NFPOINTS, XS_SIDPLAY2_FMAX); if (!xs_curve_set_points(curve, f->points, f->npoints)) { @@ -1058,12 +1061,12 @@ void xs_cfg_sp2_presets_update(void) { GList *tmpList = NULL; gint i; - + for (i = 0; i < xs_cfg.sid2NFilterPresets; i++) { tmpList = g_list_append(tmpList, (gpointer) xs_cfg.sid2FilterPresets[i]->name); } - + gtk_combo_set_popdown_strings(GTK_COMBO(LUW("cfg_sp2_filter_combo")), tmpList); g_list_free(tmpList); } @@ -1073,12 +1076,12 @@ void xs_cfg_sp2_filter_load(GtkButton *button, gpointer user_data) { const gchar *tmpStr; gint i, j; - + (void) button; (void) user_data; - + XS_MUTEX_LOCK(xs_cfg); - + tmpStr = gtk_entry_get_text(GTK_ENTRY(LUW("cfg_sp2_filter_combo_entry"))); for (i = 0, j = -1; i < xs_cfg.sid2NFilterPresets; i++) { if (!strcmp(tmpStr, xs_cfg.sid2FilterPresets[i]->name)) { @@ -1086,7 +1089,7 @@ void xs_cfg_sp2_filter_load(GtkButton *button, gpointer user_data) break; } } - + if (j != -1) { fprintf(stderr, "Updating from '%s'\n", tmpStr); xs_cfg_sp2_filter_update( @@ -1096,7 +1099,7 @@ void xs_cfg_sp2_filter_load(GtkButton *button, gpointer user_data) /* error/warning: no such filter preset */ fprintf(stderr, "No such filter preset '%s'!\n", tmpStr); } - + XS_MUTEX_UNLOCK(xs_cfg); } @@ -1107,17 +1110,17 @@ void xs_cfg_sp2_filter_save(GtkButton *button, gpointer user_data) 1) check if textentry matches any current filter name yes) ask if saving over ok? no) ... - - 2) save current filter to the name + + 2) save current filter to the name */ const gchar *tmpStr; gint i, j; - + (void) button; (void) user_data; - + XS_MUTEX_LOCK(xs_cfg); - + tmpStr = gtk_entry_get_text(GTK_ENTRY(LUW("cfg_sp2_filter_combo_entry"))); for (i = 0, j = -1; i < xs_cfg.sid2NFilterPresets; i++) { if (!strcmp(tmpStr, xs_cfg.sid2FilterPresets[i]->name)) { @@ -1125,15 +1128,15 @@ void xs_cfg_sp2_filter_save(GtkButton *button, gpointer user_data) break; } } - + if (j != -1) { fprintf(stderr, "Found, confirm overwrite?\n"); } - + fprintf(stderr, "saving!\n"); - + xs_cfg_sp2_presets_update(); - + XS_MUTEX_UNLOCK(xs_cfg); } @@ -1169,7 +1172,7 @@ void xs_filter_import_fs_ok(GtkButton *button, gpointer user_data) const gchar *tmpStr; (void) button; (void) user_data; - + XS_MUTEX_LOCK(xs_cfg); /* Selection was accepted! */ @@ -1416,7 +1419,7 @@ void xs_configure(void) /* Create the window */ xs_configwin = create_xs_configwin(); - + /* Get lock on configuration */ XS_MUTEX_LOCK(xs_cfg); @@ -1427,7 +1430,7 @@ void xs_configure(void) } gtk_combo_set_popdown_strings(GTK_COMBO(LUW("cfg_samplerate_combo")), tmpList); g_list_free(tmpList); - + /* Create the custom filter curve widget for libSIDPlay2 */ xs_cfg_sp2_presets_update(); tmpCurve = xs_curve_new(); @@ -1490,7 +1493,7 @@ void xs_configure(void) g_snprintf(tmpStr, sizeof(tmpStr), "%d", *(gint *) xs_widtable[i].itemData); gtk_entry_set_text(GTK_ENTRY(LUW(xs_widtable[i].widName)), tmpStr); break; - + case WTYPE_SPIN: case WTYPE_SCALE: /* Get the value */ diff --git a/src/sid/xs_fileinfo.c b/src/sid/xs_fileinfo.c index 404927d..4814876 100644 --- a/src/sid/xs_fileinfo.c +++ b/src/sid/xs_fileinfo.c @@ -23,6 +23,8 @@ #include <gdk/gdkkeysyms.h> #include <gtk/gtk.h> +#include <libaudcore/audstrings.h> + #include "xs_fileinfo.h" #include "xs_player.h" #include "xs_support.h" @@ -78,7 +80,7 @@ static void xs_fileinfo_subtune(GtkWidget * widget, void *data) tmpNode = (stil_subnode_t *) data; if (!tmpNode && xs_fileinfostil) tmpNode = xs_fileinfostil->subTunes[0]; - + if (tmpNode) { subName = tmpNode->name; subAuthor = tmpNode->author; @@ -109,7 +111,7 @@ void xs_fileinfo(const gchar * filename) /* Current implementation leaves old fileinfo window untouched if * no information can be found for the new file. Hmm... */ - tmpFilename = aud_filename_split_subtune(filename, &n); + tmpFilename = filename_split_subtune(filename, &n); /* Get new tune information */ XS_MUTEX_LOCK(xs_fileinfowin); @@ -158,7 +160,7 @@ void xs_fileinfo(const gchar * filename) if (xs_fileinfostil && n <= xs_fileinfostil->nsubTunes && xs_fileinfostil->subTunes[n]) { gboolean isSet = FALSE; tmpNode = xs_fileinfostil->subTunes[n]; - + g_snprintf(tmpStr, sizeof(tmpStr), _("Tune #%i: "), n); if (tmpNode->name) { diff --git a/src/sid/xs_filter.c b/src/sid/xs_filter.c index 38db183..e046fed 100644 --- a/src/sid/xs_filter.c +++ b/src/sid/xs_filter.c @@ -1,8 +1,8 @@ -/* +/* XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS) Audio rate-conversion filter - + Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org> (C) Copyright 1999-2007 Tecnic Software productions (TNSP) @@ -40,7 +40,7 @@ static gint32 xs_filter_mbn = 0; -gint xs_filter_rateconv(void *destBuf, void *srcBuf, const AFormat audioFormat, +gint xs_filter_rateconv(void *destBuf, void *srcBuf, const gint audioFormat, const gint oversampleFactor, const gint bufSize) { static gint32 tmp; diff --git a/src/sid/xs_filter.h b/src/sid/xs_filter.h index 091917b..1251253 100644 --- a/src/sid/xs_filter.h +++ b/src/sid/xs_filter.h @@ -13,7 +13,7 @@ typedef struct { void xs_filter_init(t_xs_filter *); */ -gint xs_filter_rateconv(void *, void *, const AFormat, const gint, const gint); +gint xs_filter_rateconv(void *, void *, const gint, const gint, const gint); #ifdef __cplusplus } diff --git a/src/sid/xs_player.h b/src/sid/xs_player.h index f66498f..1da7219 100644 --- a/src/sid/xs_player.h +++ b/src/sid/xs_player.h @@ -30,7 +30,7 @@ typedef struct xs_status_t { audioChannels, audioBitsPerSample, oversampleFactor; /* Factor of oversampling */ - AFormat audioFormat; + gint audioFormat; gboolean oversampleEnable; /* TRUE after sidEngine initialization, if xs_cfg.oversampleEnable == TRUE and emulation backend supports oversampling. diff --git a/src/sid/xs_support.c b/src/sid/xs_support.c index 2267095..5aec318 100644 --- a/src/sid/xs_support.c +++ b/src/sid/xs_support.c @@ -51,7 +51,7 @@ gint xs_fload_buffer(const gchar *filename, guint8 **buf, size_t *bufSize) return -1; #ifdef __AUDACIOUS_NEWVFS__ - seekPos = aud_vfs_fsize(f); + seekPos = vfs_fsize(f); #else xs_fseek(f, 0L, SEEK_END); seekPos = xs_ftell(f); diff --git a/src/sid/xs_support.h b/src/sid/xs_support.h index 909a06c..41b5706 100644 --- a/src/sid/xs_support.h +++ b/src/sid/xs_support.h @@ -64,16 +64,16 @@ extern "C" { /* VFS replacement functions */ -#ifdef __AUDACIOUS_NEWVFS__ +#ifdef AUDACIOUS_PLUGIN #define xs_file_t VFSFile -#define xs_fopen(a,b) aud_vfs_fopen(a,b) -#define xs_fclose(a) aud_vfs_fclose(a) -#define xs_fgetc(a) aud_vfs_getc(a) -#define xs_fread(a,b,c,d) aud_vfs_fread(a,b,c,d) -#define xs_feof(a) aud_vfs_feof(a) +#define xs_fopen(a,b) vfs_fopen(a,b) +#define xs_fclose(a) vfs_fclose(a) +#define xs_fgetc(a) vfs_getc(a) +#define xs_fread(a,b,c,d) vfs_fread(a,b,c,d) +#define xs_feof(a) vfs_feof(a) #define xs_ferror(a) (0) -#define xs_ftell(a) aud_vfs_ftell(a) -#define xs_fseek(a,b,c) aud_vfs_fseek(a,b,c) +#define xs_ftell(a) vfs_ftell(a) +#define xs_fseek(a,b,c) vfs_fseek(a,b,c) #else #define xs_file_t FILE #define xs_fopen(a,b) fopen(a,b) diff --git a/src/skins/Makefile b/src/skins/Makefile index 441bf86..dba350c 100644 --- a/src/skins/Makefile +++ b/src/skins/Makefile @@ -256,6 +256,6 @@ DATA = Skins/Classic/balance.png \ plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR} +CPPFLAGS += -std=gnu99 ${PLUGIN_CPPFLAGS} -I../.. CFLAGS += ${PLUGIN_CFLAGS} ${BEEP_DEFINES} -CPPFLAGS += ${PLUGIN_CPPFLAGS} ${MOWGLI_CFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} ${PANGO_CFLAGS} ${CAIRO_CFLAGS} ${PANGOCAIRO_CFLAGS} ${XRENDER_CFLAGS} ${XCOMPOSITE_CFLAGS} -I../.. LIBS += ${GTK_LIBS} ${GLIB_LIBS} ${PANGO_LIBS} ${CAIRO_LIBS} ${PANGOCAIRO_LIBS} ${XRENDER_LIBS} ${XCOMPOSITE_LIBS} ${MOWGLI_LIBS} -laudgui -lm diff --git a/src/skins/actions-playlist.h b/src/skins/actions-playlist.h index 8e8ce35..cc2b606 100644 --- a/src/skins/actions-playlist.h +++ b/src/skins/actions-playlist.h @@ -52,7 +52,6 @@ void action_playlist_paste (void); void action_playlist_add_url(void); void action_playlist_add_files(void); -void action_playlist_randomize_list(void); void action_playlist_reverse_list(void); void action_playlist_sort_by_title(void); diff --git a/src/skins/plugin.c b/src/skins/plugin.c index 7b9bc51..6f1bdbd 100644 --- a/src/skins/plugin.c +++ b/src/skins/plugin.c @@ -27,6 +27,9 @@ #include "ui_manager.h" #include "ui_main_evlisteners.h" #include "ui_playlist_evlisteners.h" + +#include <audacious/audconfig.h> +#include <audacious/drct.h> #include <audacious/i18n.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> @@ -38,7 +41,7 @@ gchar * skins_paths[SKINS_PATH_COUNT]; Interface skins_interface = { .id = "skinned", - .desc = "Audacious Skinned GUI", + .desc = "Winamp Classic Interface", .init = skins_init, .fini = skins_cleanup }; @@ -107,11 +110,12 @@ gboolean skins_init (InterfaceCbs * cbs) init_skins(config.skin); mainwin_setup_menus(); - if (audacious_drct_get_playing ()) + if (aud_drct_get_playing ()) { ui_main_evlistener_playback_begin (NULL, NULL); + info_change (); - if (audacious_drct_get_paused ()) + if (aud_drct_get_paused ()) ui_main_evlistener_playback_pause (NULL, NULL); } else @@ -139,7 +143,6 @@ gboolean skins_init (InterfaceCbs * cbs) eq_init_hooks (); update_source = g_timeout_add (250, update_cb, NULL); - gtk_main (); return TRUE; } @@ -152,9 +155,6 @@ gboolean skins_cleanup (void) eq_end_hooks (); g_source_remove (update_source); - gtk_widget_destroy (mainwin); - gtk_widget_destroy (equalizerwin); - gtk_widget_destroy (playlistwin); skins_cfg_save(); audgui_playlist_manager_destroy(); @@ -166,8 +166,6 @@ gboolean skins_cleanup (void) plugin_is_active = FALSE; } - gtk_main_quit(); - return TRUE; } diff --git a/src/skins/plugin.h b/src/skins/plugin.h index 1804441..a750677 100644 --- a/src/skins/plugin.h +++ b/src/skins/plugin.h @@ -22,7 +22,10 @@ #define PLUGIN_SKINS_H #include <glib.h> + +#include <audacious/interface.h> #include <audacious/plugin.h> + #include "skins_cfg.h" #include "ui_main.h" #include "ui_equalizer.h" diff --git a/src/skins/skins_cfg.c b/src/skins/skins_cfg.c index 1dfe538..02fa0f2 100644 --- a/src/skins/skins_cfg.c +++ b/src/skins/skins_cfg.c @@ -18,6 +18,15 @@ * Audacious or using our public API to be a derived work. */ +#include <glib.h> +#include <stdlib.h> + +#include <audacious/configdb.h> +#include <audacious/debug.h> +#include <audacious/i18n.h> +#include <audacious/misc.h> +#include <audacious/preferences.h> +#include <libaudcore/audstrings.h> #include "skins_cfg.h" #include "ui_dock.h" @@ -32,10 +41,6 @@ #include "plugin.h" #include "dnd.h" #include "util.h" -#include <glib.h> -#include <stdlib.h> -#include <audacious/i18n.h> -#include <libintl.h> skins_cfg_t config; GtkWidget *skin_view; @@ -511,11 +516,11 @@ on_skin_view_drag_data_received(GtkWidget * widget, /* FIXME: use a real URL validator/parser */ - if (aud_str_has_prefix_nocase(path, "file:///")) { + if (str_has_prefix_nocase(path, "file:///")) { path[strlen(path) - 2] = 0; /* Why the hell a CR&LF? */ path += 7; } - else if (aud_str_has_prefix_nocase(path, "file:")) { + else if (str_has_prefix_nocase(path, "file:")) { path += 5; } diff --git a/src/skins/ui/mainwin.ui b/src/skins/ui/mainwin.ui index 2d078ad..e3cbc25 100644 --- a/src/skins/ui/mainwin.ui +++ b/src/skins/ui/mainwin.ui @@ -101,6 +101,8 @@ <!-- <menuitem action="playlist delete" /> --> </menu> <menu action="view"> + <menuitem action="iface menu" /> + <separator /> <menuitem action="show player" /> <menuitem action="show playlist editor" /> <menuitem action="show equalizer" /> diff --git a/src/skins/ui/playlist.ui b/src/skins/ui/playlist.ui index 244f922..05fd5f4 100644 --- a/src/skins/ui/playlist.ui +++ b/src/skins/ui/playlist.ui @@ -56,7 +56,6 @@ <menu action="dummy" name="misc-menu"> <menuitem action="plugins-menu" /> <separator /> - <menuitem action="playlist randomize list" /> <menuitem action="playlist reverse list" /> <separator /> <menu action="playlist sort menu"> diff --git a/src/skins/ui_equalizer.c b/src/skins/ui_equalizer.c index 1c6a99d..7a88bfa 100644 --- a/src/skins/ui_equalizer.c +++ b/src/skins/ui_equalizer.c @@ -43,9 +43,12 @@ #include "ui_main.h" #include "ui_playlist.h" +#include <audacious/audconfig.h> +#include <audacious/drct.h> #include <audacious/i18n.h> -#include <audacious/plugin.h> -#include <audacious/equalizer_preset.h> +#include <audacious/misc.h> +#include <audacious/playlist.h> +#include <libaudcore/hook.h> #include <libaudgui/libaudgui-gtk.h> #include "images/audacious_eq.xpm" @@ -194,7 +197,7 @@ equalizerwin_eq_changed(void) aud_cfg->equalizer_bands[i] = equalizerwin_get_band(i); ui_skinned_equalizer_graph_update (equalizerwin_graph); - aud_hook_call("equalizer changed", NULL); + hook_call("equalizer changed", NULL); } static void @@ -276,7 +279,7 @@ static gboolean equalizerwin_delete(GtkWidget *widget, void *data) if (config.show_wm_decorations) equalizerwin_show(FALSE); else - audacious_drct_quit(); + aud_drct_quit(); return TRUE; } @@ -683,7 +686,7 @@ equalizerwin_read_winamp_eqf(VFSFile * file) static gboolean equalizerwin_read_aud_preset (const gchar * file) { - EqualizerPreset * preset = aud_equalizer_read_aud_preset (file); + EqualizerPreset * preset = aud_load_preset_file (file); if (preset == NULL) return FALSE; @@ -842,7 +845,7 @@ open_vfs_file(const gchar *filename, const gchar *mode) VFSFile *file; GtkWidget *dialog; - if (!(file = aud_vfs_fopen(filename, mode))) { + if (!(file = vfs_fopen(filename, mode))) { dialog = gtk_message_dialog_new (GTK_WINDOW (mainwin), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, @@ -865,7 +868,7 @@ load_winamp_file(const gchar * filename) return; equalizerwin_read_winamp_eqf(file); - aud_vfs_fclose(file); + vfs_fclose(file); } static void @@ -881,7 +884,7 @@ import_winamp_file(const gchar * filename) equalizer_presets = g_list_concat(equalizer_presets, list); aud_equalizer_write_preset_file(equalizer_presets, "eq.preset"); - aud_vfs_fclose(file); + vfs_fclose(file); } static void @@ -896,19 +899,19 @@ save_winamp_file(const gchar * filename) if (!(file = open_vfs_file(filename, "wb"))) return; - aud_vfs_fwrite("Winamp EQ library file v1.1\x1a!--", 1, 31, file); + vfs_fwrite("Winamp EQ library file v1.1\x1a!--", 1, 31, file); memset(name, 0, 257); g_strlcpy(name, "Entry1", 257); - aud_vfs_fwrite(name, 1, 257, file); + vfs_fwrite(name, 1, 257, file); for (i = 0; i < AUD_EQUALIZER_NBANDS; i++) bands[i] = 63 - (((equalizerwin_get_band(i) + EQUALIZER_MAX_GAIN) * 63) / EQUALIZER_MAX_GAIN / 2); bands[AUD_EQUALIZER_NBANDS] = 63 - (((equalizerwin_get_preamp() + EQUALIZER_MAX_GAIN) * 63) / EQUALIZER_MAX_GAIN / 2); - aud_vfs_fwrite(bands, 1, 11, file); - aud_vfs_fclose(file); + vfs_fwrite(bands, 1, 11, file); + vfs_fclose(file); } static GtkWidget * @@ -1184,7 +1187,7 @@ action_equ_save_auto_preset(void) G_CALLBACK(equalizerwin_save_auto_ok), G_CALLBACK(equalizerwin_save_auto_select)); - name = audacious_drct_pl_get_file (audacious_drct_pl_get_pos ()); + name = aud_drct_pl_get_file (aud_drct_pl_get_pos ()); if (name != NULL) { @@ -1223,7 +1226,7 @@ action_equ_save_preset_file(void) g_free(file_uri); } - songname = audacious_drct_pl_get_file (audacious_drct_pl_get_pos ()); + songname = aud_drct_pl_get_file (aud_drct_pl_get_pos ()); if (songname != NULL) { @@ -1359,10 +1362,10 @@ void eq_init_hooks (void) if (playlist != -1) position_cb (GINT_TO_POINTER (playlist), NULL); - aud_hook_associate ("playlist position", position_cb, NULL); + hook_associate ("playlist position", position_cb, NULL); } void eq_end_hooks (void) { - aud_hook_dissociate ("playlist position", position_cb); + hook_dissociate ("playlist position", position_cb); } diff --git a/src/skins/ui_main.c b/src/skins/ui_main.c index 807eb31..f2a0c13 100644 --- a/src/skins/ui_main.c +++ b/src/skins/ui_main.c @@ -36,7 +36,12 @@ #include <string.h> #include <sys/types.h> +#include <audacious/audconfig.h> +#include <audacious/drct.h> #include <audacious/i18n.h> +#include <audacious/playlist.h> +#include <libaudcore/audstrings.h> +#include <libaudcore/hook.h> #include <libaudgui/libaudgui.h> /* GDK including */ @@ -70,7 +75,6 @@ #include "ui_skinned_monostereo.h" #include "ui_skinned_playlist.h" #include "ui_main_evlisteners.h" -#include <audacious/plugin.h> #include "skins_cfg.h" #include "util.h" @@ -217,6 +221,8 @@ static void mainwin_vis_set_analyzer_type(AnalyzerType mode) { config.analyzer_type = mode; + ui_vis_clear_data (mainwin_vis); + ui_svis_clear_data (mainwin_svis); } void @@ -255,7 +261,7 @@ mainwin_vis_set_type_menu_cb(VisType mode) ui_vis_clear_data (mainwin_vis); ui_svis_clear_data (mainwin_svis); - start_stop_visual (); + start_stop_visual (FALSE); } static void @@ -661,10 +667,10 @@ mainwin_scrolled(GtkWidget *widget, GdkEventScroll *event, mainwin_set_volume_diff (-5); break; case GDK_SCROLL_LEFT: - audacious_drct_seek (audacious_drct_get_time () - 5000); + aud_drct_seek (aud_drct_get_time () - 5000); break; case GDK_SCROLL_RIGHT: - audacious_drct_seek (audacious_drct_get_time () + 5000); + aud_drct_seek (aud_drct_get_time () + 5000); break; } } @@ -737,24 +743,24 @@ gboolean mainwin_keypress (GtkWidget * widget, GdkEventKey * event, case GDK_Left: case GDK_KP_Left: case GDK_KP_7: - audacious_drct_seek (audacious_drct_get_time () - 5000); + aud_drct_seek (aud_drct_get_time () - 5000); break; case GDK_Right: case GDK_KP_Right: case GDK_KP_9: - audacious_drct_seek (audacious_drct_get_time () + 5000); + aud_drct_seek (aud_drct_get_time () + 5000); break; case GDK_KP_4: - audacious_drct_pl_prev (); + aud_drct_pl_prev (); break; case GDK_KP_6: - audacious_drct_pl_next (); + aud_drct_pl_next (); break; case GDK_KP_Insert: action_jump_to_file(); break; case GDK_space: - audacious_drct_pause(); + aud_drct_pause(); break; case GDK_Tab: /* GtkUIManager does not handle tab, apparently. */ if (event->state & GDK_SHIFT_MASK) @@ -789,7 +795,7 @@ mainwin_jump_to_time_cb(GtkWidget * widget, else return; - audacious_drct_seek (time*1000); + aud_drct_seek (time*1000); gtk_widget_destroy (mainwin_jtt); } @@ -803,7 +809,7 @@ mainwin_jump_to_time(void) guint tindex; gchar time_str[10]; - if (!audacious_drct_get_playing()) { + if (!aud_drct_get_playing()) { dialog = gtk_message_dialog_new (GTK_WINDOW (mainwin), GTK_DIALOG_DESTROY_WITH_PARENT, @@ -858,7 +864,7 @@ mainwin_jump_to_time(void) label = gtk_label_new(_("Track length:")); gtk_box_pack_start(GTK_BOX(hbox_total), label, FALSE, FALSE, 5); - gint len = audacious_drct_get_length () / 1000; + gint len = aud_drct_get_length () / 1000; g_snprintf(time_str, sizeof(time_str), "%u:%2.2u", len / 60, len % 60); label = gtk_label_new(time_str); @@ -881,7 +887,7 @@ mainwin_jump_to_time(void) g_signal_connect(jump, "clicked", G_CALLBACK(mainwin_jump_to_time_cb), time_entry); - tindex = audacious_drct_get_time() / 1000; + tindex = aud_drct_get_time() / 1000; g_snprintf(time_str, sizeof(time_str), "%u:%2.2u", tindex / 60, tindex % 60); gtk_entry_set_text(GTK_ENTRY(time_entry), time_str); @@ -916,7 +922,7 @@ mainwin_drag_data_received(GtkWidget * widget, g_return_if_fail(selection_data != NULL); g_return_if_fail(selection_data->data != NULL); - if (aud_str_has_prefix_nocase((gchar *) selection_data->data, "fonts:///")) + if (str_has_prefix_nocase((gchar *) selection_data->data, "fonts:///")) { gchar *path = (gchar *) selection_data->data; gchar *decoded = g_filename_from_uri(path, NULL, NULL); @@ -933,9 +939,9 @@ mainwin_drag_data_received(GtkWidget * widget, } /* perhaps make suffix check case-insensitive -- desowin */ - if (aud_str_has_prefix_nocase((char*)selection_data->data, "file:///")) { - if (aud_str_has_suffix_nocase((char*)selection_data->data, ".wsz\r\n") || - aud_str_has_suffix_nocase((char*)selection_data->data, ".zip\r\n")) { + if (str_has_prefix_nocase((char*)selection_data->data, "file:///")) { + if (str_has_suffix_nocase((char*)selection_data->data, ".wsz\r\n") || + str_has_suffix_nocase((char*)selection_data->data, ".zip\r\n")) { on_skin_view_drag_data_received(GTK_WIDGET(user_data), context, x, y, selection_data, info, time, NULL); return; } @@ -1130,9 +1136,9 @@ static gboolean seek_release (GtkWidget * widget, GdkEventButton * event, if (held < SEEK_THRESHOLD) { if (GPOINTER_TO_INT (rewind)) - audacious_drct_pl_prev (); + aud_drct_pl_prev (); else - audacious_drct_pl_next (); + aud_drct_pl_next (); } else mainwin_position_release_cb (mainwin_position, @@ -1148,15 +1154,15 @@ void mainwin_play_pushed(void) { if (ab_position_a != -1) - audacious_drct_seek(ab_position_a / 1000); + aud_drct_seek(ab_position_a / 1000); - audacious_drct_play (); + aud_drct_play (); } void mainwin_stop_pushed(void) { - audacious_drct_stop(); + aud_drct_stop(); mainwin_clear_song_info(); ab_position_a = ab_position_b = -1; } @@ -1227,10 +1233,10 @@ mainwin_spos_motion_cb(GtkWidget *widget, gint pos) pos--; - time = audacious_drct_get_length () / 1000 * pos / 12; + time = aud_drct_get_length () / 1000 * pos / 12; if (config.timer_mode == TIMER_REMAINING) { - time = audacious_drct_get_length () / 1000 - time; + time = aud_drct_get_length () / 1000 - time; time_msg = g_strdup_printf("-%2.2d", time / 60); ui_skinned_textbox_set_text(mainwin_stime_min, time_msg); g_free(time_msg); @@ -1249,7 +1255,7 @@ mainwin_spos_motion_cb(GtkWidget *widget, gint pos) void mainwin_spos_release_cb(GtkWidget *widget, gint pos) { - audacious_drct_seek (audacious_drct_get_length () * (pos - 1) / 12); + aud_drct_seek (aud_drct_get_length () * (pos - 1) / 12); } void @@ -1258,7 +1264,7 @@ mainwin_position_motion_cb(GtkWidget *widget, gint pos) gint length, time; gchar *seek_msg; - length = audacious_drct_get_length () / 1000; + length = aud_drct_get_length () / 1000; time = (length * pos) / 219; seek_msg = g_strdup_printf(_("Seek to: %d:%-2.2d/%d:%-2.2d (%d%%)"), time / 60, time % 60, @@ -1273,9 +1279,9 @@ mainwin_position_release_cb(GtkWidget *widget, gint pos) { gint length, time; - length = audacious_drct_get_length(); + length = aud_drct_get_length(); time = (gint64) length * pos / 219; - audacious_drct_seek(time); + aud_drct_seek(time); mainwin_release_info_text(); } @@ -1294,12 +1300,8 @@ mainwin_adjust_volume_motion(gint v) mainwin_lock_info_text(volume_msg); g_free(volume_msg); - if (balance < 0) - audacious_drct_set_volume(v, (v * (100 - abs(balance))) / 100); - else if (balance > 0) - audacious_drct_set_volume((v * (100 - abs(balance))) / 100, v); - else - audacious_drct_set_volume(v, v); + aud_drct_set_volume_main (v); + aud_drct_set_volume_balance (balance); } void @@ -1312,23 +1314,17 @@ void mainwin_adjust_balance_motion(gint b) { gchar *balance_msg; - gint v, pvl, pvr; balance = b; - aud_input_get_volume(&pvl, &pvr); - v = MAX(pvl, pvr); - if (b < 0) { + aud_drct_set_volume_balance (b); + + if (b < 0) balance_msg = g_strdup_printf(_("Balance: %d%% left"), -b); - audacious_drct_set_volume(v, (gint) rint(((100 + b) / 100.0) * v)); - } - else if (b == 0) { + else if (b == 0) balance_msg = g_strdup_printf(_("Balance: center")); - audacious_drct_set_volume(v, v); - } - else { /* b > 0 */ + else balance_msg = g_strdup_printf(_("Balance: %d%% right"), b); - audacious_drct_set_volume((gint) rint(((100 - b) / 100.0) * v), v); - } + mainwin_lock_info_text(balance_msg); g_free(balance_msg); } @@ -1390,12 +1386,9 @@ mainwin_balance_release_cb(GtkWidget *widget, gint pos) void mainwin_set_volume_diff(gint diff) { - gint vl, vr, vol; - - aud_input_get_volume(&vl, &vr); - vol = MAX(vl, vr); - vol = CLAMP(vol + diff, 0, 100); + gint vol; + aud_drct_get_volume_main (& vol); mainwin_adjust_volume_motion(vol); mainwin_set_volume_slider(vol); equalizerwin_set_volume_slider(vol); @@ -1418,14 +1411,14 @@ mainwin_set_balance_diff(gint diff) static void mainwin_real_show (void) { - start_stop_visual (); + start_stop_visual (FALSE); gtk_window_present(GTK_WINDOW(mainwin)); } static void mainwin_real_hide (void) { gtk_widget_hide(mainwin); - start_stop_visual (); + start_stop_visual (FALSE); } void mainwin_show (gboolean show) @@ -1535,34 +1528,34 @@ mainwin_general_menu_callback(gpointer data, equalizerwin_show (GTK_CHECK_MENU_ITEM (item)->active); break; case MAINWIN_GENERAL_PREV: - audacious_drct_pl_prev (); + aud_drct_pl_prev (); break; case MAINWIN_GENERAL_PLAY: mainwin_play_pushed(); break; case MAINWIN_GENERAL_PAUSE: - audacious_drct_pause(); + aud_drct_pause(); break; case MAINWIN_GENERAL_STOP: mainwin_stop_pushed(); break; case MAINWIN_GENERAL_NEXT: - audacious_drct_pl_next (); + aud_drct_pl_next (); break; #if 0 case MAINWIN_GENERAL_BACK5SEC: - if (audacious_drct_get_playing() + if (aud_drct_get_playing() && aud_playlist_get_current_length(playlist) != -1) playback_seek_relative(-5); break; case MAINWIN_GENERAL_FWD5SEC: - if (audacious_drct_get_playing() + if (aud_drct_get_playing() && aud_playlist_get_current_length(playlist) != -1) playback_seek_relative(5); break; #endif case MAINWIN_GENERAL_START: - audacious_drct_pl_set_pos (0); + aud_drct_pl_set_pos (0); break; case MAINWIN_GENERAL_JTT: mainwin_jump_to_time(); @@ -1571,29 +1564,29 @@ mainwin_general_menu_callback(gpointer data, action_jump_to_file(); break; case MAINWIN_GENERAL_EXIT: - audacious_drct_quit (); + aud_drct_quit (); break; case MAINWIN_GENERAL_SETAB: - if (audacious_drct_get_length () > 0) + if (aud_drct_get_length () > 0) { if (ab_position_a == -1) { - ab_position_a = audacious_drct_get_time(); + ab_position_a = aud_drct_get_time(); ab_position_b = -1; mainwin_lock_info_text("'Loop-Point A Position' set."); } else if (ab_position_b == -1) { - int time = audacious_drct_get_time(); + int time = aud_drct_get_time(); if (time > ab_position_a) ab_position_b = time; mainwin_release_info_text(); } else { - ab_position_a = audacious_drct_get_time(); + ab_position_a = aud_drct_get_time(); ab_position_b = -1; mainwin_lock_info_text("'Loop-Point A Position' reset."); } } break; case MAINWIN_GENERAL_CLEARAB: - if (audacious_drct_get_length () > 0) + if (aud_drct_get_length () > 0) { ab_position_a = ab_position_b = -1; mainwin_release_info_text(); @@ -1683,19 +1676,10 @@ mainwin_mr_release(GtkWidget *widget, MenuRowItem i, GdkEventButton *event) void ui_main_set_initial_volume(void) { - gint vl, vr, b, v; - - aud_input_get_volume(&vl, &vr); + gint b, v; - vl = CLAMP(vl, 0, 100); - vr = CLAMP(vr, 0, 100); - v = MAX(vl, vr); - if (vl > vr) - b = (gint) rint(((gdouble) vr / vl) * 100) - 100; - else if (vl < vr) - b = 100 - (gint) rint(((gdouble) vl / vr) * 100); - else - b = 0; + aud_drct_get_volume_main (& v); + aud_drct_get_volume_balance (& b); mainwin_set_volume_slider(v); equalizerwin_set_volume_slider(v); @@ -1734,20 +1718,20 @@ static void change_timer_mode(void) { set_timer_mode(TIMER_REMAINING); else set_timer_mode(TIMER_ELAPSED); - if (audacious_drct_get_playing()) + if (aud_drct_get_playing()) mainwin_update_song_info(); } static void mainwin_aud_playlist_prev(void) { - audacious_drct_pl_prev (); + aud_drct_pl_prev (); } static void mainwin_aud_playlist_next(void) { - audacious_drct_pl_next (); + aud_drct_pl_next (); } void @@ -1939,7 +1923,7 @@ mainwin_create_widgets(void) mainwin_close = ui_skinned_button_new(); ui_skinned_push_button_setup(mainwin_close, SKINNED_WINDOW(mainwin)->normal, 264, 3, 9, 9, 18, 0, 18, 9, SKIN_TITLEBAR); - g_signal_connect ((GObject *) mainwin_close, "clicked", audacious_drct_quit, + g_signal_connect ((GObject *) mainwin_close, "clicked", aud_drct_quit, 0); mainwin_rew = ui_skinned_button_new(); @@ -1966,7 +1950,7 @@ mainwin_create_widgets(void) mainwin_pause = ui_skinned_button_new(); ui_skinned_push_button_setup(mainwin_pause, SKINNED_WINDOW(mainwin)->normal, 62, 88, 23, 18, 46, 0, 46, 18, SKIN_CBUTTONS); - g_signal_connect(mainwin_pause, "clicked", audacious_drct_pause, NULL ); + g_signal_connect(mainwin_pause, "clicked", aud_drct_pause, NULL ); mainwin_stop = ui_skinned_button_new(); ui_skinned_push_button_setup(mainwin_stop, SKINNED_WINDOW(mainwin)->normal, @@ -2081,7 +2065,7 @@ mainwin_create_widgets(void) ui_skinned_push_button_setup(mainwin_shaded_close, SKINNED_WINDOW(mainwin)->shaded, 264, 3, 9, 9, 18, 0, 18, 9, SKIN_TITLEBAR); g_signal_connect ((GObject *) mainwin_shaded_close, "clicked", - audacious_drct_quit, 0); + aud_drct_quit, 0); mainwin_srew = ui_skinned_button_new(); ui_skinned_small_button_setup(mainwin_srew, SKINNED_WINDOW(mainwin)->shaded, 169, 4, 8, 7); @@ -2093,7 +2077,7 @@ mainwin_create_widgets(void) mainwin_spause = ui_skinned_button_new(); ui_skinned_small_button_setup(mainwin_spause, SKINNED_WINDOW(mainwin)->shaded, 187, 4, 10, 7); - g_signal_connect(mainwin_spause, "clicked", audacious_drct_pause, NULL); + g_signal_connect(mainwin_spause, "clicked", aud_drct_pause, NULL); mainwin_sstop = ui_skinned_button_new(); ui_skinned_small_button_setup(mainwin_sstop, SKINNED_WINDOW(mainwin)->shaded, 197, 4, 9, 7); @@ -2168,7 +2152,7 @@ static gboolean state_cb (GtkWidget * widget, GdkEventWindowState * event, static gboolean delete_cb (GtkWidget * widget, GdkEvent * event, void * unused) { - audacious_drct_quit (); + aud_drct_quit (); return TRUE; } @@ -2222,8 +2206,9 @@ void mainwin_unhook (void) seek_source = 0; } - aud_hook_dissociate ("show main menu", (HookFunction) show_main_menu); + hook_dissociate ("show main menu", (HookFunction) show_main_menu); ui_main_evlistener_dissociate (); + start_stop_visual (TRUE); } void @@ -2236,7 +2221,7 @@ mainwin_create(void) mainwin_create_widgets(); show_widgets (); - aud_hook_associate ("show main menu", (HookFunction) show_main_menu, 0); + hook_associate ("show main menu", (HookFunction) show_main_menu, 0); status_message_enabled = TRUE; } @@ -2244,8 +2229,8 @@ static void mainwin_update_volume (void) { gint volume, balance; - audacious_drct_get_volume_main (& volume); - audacious_drct_get_volume_balance (& balance); + aud_drct_get_volume_main (& volume); + aud_drct_get_volume_balance (& balance); mainwin_set_volume_slider (volume); mainwin_set_balance_slider (balance); } @@ -2321,16 +2306,16 @@ void mainwin_update_song_info (void) mainwin_update_volume (); - if (! audacious_drct_get_playing ()) + if (! aud_drct_get_playing ()) return; - time = audacious_drct_get_time (); - length = audacious_drct_get_length (); + time = aud_drct_get_time (); + length = aud_drct_get_length (); /* Ugh, this does NOT belong here. -jlindgren */ if (ab_position_a > -1 && ab_position_b > -1 && time >= ab_position_b) { - audacious_drct_seek (ab_position_a); + aud_drct_seek (ab_position_a); return; } @@ -2390,7 +2375,7 @@ void action_stop_after_current_song (GtkToggleAction * action) show_status_message (_("Not stopping after song.")); aud_cfg->stopaftersong = active; - aud_hook_call ("toggle stop after song", NULL); + hook_call ("toggle stop after song", NULL); } } @@ -2536,30 +2521,30 @@ action_play_file( void ) void action_play_location( void ) { - audgui_show_add_url_window(); + audgui_show_add_url_window (TRUE); } void action_ab_set( void ) { - if (audacious_drct_get_length () > 0) + if (aud_drct_get_length () > 0) { if (ab_position_a == -1) { - ab_position_a = audacious_drct_get_time(); + ab_position_a = aud_drct_get_time(); ab_position_b = -1; mainwin_lock_info_text("LOOP-POINT A POSITION SET."); } else if (ab_position_b == -1) { - int time = audacious_drct_get_time(); + int time = aud_drct_get_time(); if (time > ab_position_a) ab_position_b = time; mainwin_release_info_text(); } else { - ab_position_a = audacious_drct_get_time(); + ab_position_a = aud_drct_get_time(); ab_position_b = -1; mainwin_lock_info_text("LOOP-POINT A POSITION RESET."); } @@ -2569,7 +2554,7 @@ action_ab_set( void ) void action_ab_clear( void ) { - if (audacious_drct_get_length () > 0) + if (aud_drct_get_length () > 0) { ab_position_a = ab_position_b = -1; mainwin_release_info_text(); @@ -2591,7 +2576,7 @@ action_jump_to_file( void ) void action_jump_to_playlist_start( void ) { - audacious_drct_pl_set_pos (0); + aud_drct_pl_set_pos (0); } void @@ -2603,13 +2588,13 @@ action_jump_to_time( void ) void action_playback_next( void ) { - audacious_drct_pl_next (); + aud_drct_pl_next (); } void action_playback_previous( void ) { - audacious_drct_pl_prev (); + aud_drct_pl_prev (); } void @@ -2621,7 +2606,7 @@ action_playback_play( void ) void action_playback_pause( void ) { - audacious_drct_pause(); + aud_drct_pause(); } void @@ -2639,5 +2624,5 @@ action_preferences( void ) void action_quit( void ) { - audacious_drct_quit (); + aud_drct_quit (); } diff --git a/src/skins/ui_main_evlisteners.c b/src/skins/ui_main_evlisteners.c index e078228..4a2b0df 100644 --- a/src/skins/ui_main_evlisteners.c +++ b/src/skins/ui_main_evlisteners.c @@ -21,8 +21,10 @@ #include <glib.h> #include <math.h> -#include <audacious/plugin.h> -#include <audacious/input.h> +#include <audacious/audconfig.h> +#include <audacious/drct.h> +#include <audacious/misc.h> +#include <libaudcore/hook.h> #include "skins_cfg.h" #include "ui_equalizer.h" @@ -39,10 +41,10 @@ static void ui_main_evlistener_title_change (void * data, void * user_data) gchar * title; /* may be called asynchronously */ - if (! audacious_drct_get_playing ()) + if (! aud_drct_get_playing ()) return; - title = aud_playback_get_title (); + title = aud_drct_get_title (); mainwin_set_song_title (title); g_free (title); } @@ -66,7 +68,7 @@ void ui_main_evlistener_playback_begin (void * hook_data, void * user_data) gtk_widget_show (mainwin_10sec_num); gtk_widget_show (mainwin_sec_num); - if (audacious_drct_get_length () > 0) + if (aud_drct_get_length () > 0) { gtk_widget_show (mainwin_position); gtk_widget_show (mainwin_sposition); @@ -114,15 +116,15 @@ static void vis_clear_cb (void * unused, void * another) ui_svis_clear_data (mainwin_svis); } -static void info_change (void * hook_data, void * user_data) +void info_change (void) { gint bitrate, samplerate, channels; /* may be called asynchronously */ - if (! audacious_drct_get_playing ()) + if (! aud_drct_get_playing ()) return; - audacious_drct_get_info (& bitrate, & samplerate, & channels); + aud_drct_get_info (& bitrate, & samplerate, & channels); mainwin_set_song_info (bitrate, samplerate, channels); } @@ -147,11 +149,9 @@ ui_main_evlistener_equalizerwin_show(gpointer hook_data, gpointer user_data) equalizerwin_show(*show); } -static void -ui_main_evlistener_visualization_timeout(gpointer hook_data, gpointer user_data) +static void ui_main_evlistener_visualization_timeout (const VisNode * vis, + void * user) { - VisNode *vis = (VisNode*) hook_data; - guint8 intern_vis_data[512]; gint16 mono_freq[2][256]; gboolean mono_freq_calced = FALSE; @@ -162,67 +162,81 @@ ui_main_evlistener_visualization_timeout(gpointer hook_data, gpointer user_data) if (! vis || config.vis_type == VIS_OFF) return; - if (config.vis_type == VIS_ANALYZER) { - /* Spectrum analyzer */ - /* 76 values */ - const gint long_xscale[] = - { 0, 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, 61, 66, 71, 76, 81, 87, 93, - 100, 107, - 114, 122, 131, 140, 150, 161, 172, 184, 255 - }; - /* 20 values */ - const int short_xscale[] = - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 15, 20, 27, - 36, 47, 62, 82, 107, 141, 184, 255 - }; - const double y_scale = 3.60673760222; /* 20.0 / log(256) */ - const int *xscale; - gint j, y, max; + if (config.vis_type == VIS_ANALYZER) + { + /* logarithmic scale - 1 */ + const gfloat xscale13[14] = {0.00, 0.53, 1.35, 2.60, 4.51, 7.45, 12.0, + 18.8, 29.4, 45.6, 70.4, 108, 167, 256}; + const gfloat xscale19[20] = {0.00, 0.34, 0.79, 1.40, 2.22, 3.31, 4.77, + 6.72, 9.34, 12.9, 17.6, 23.8, 32.3, 43.6, 58.7, 78.9, 106, 142, 191, + 256}; + const gfloat xscale37[38] = {0.00, 0.16, 0.35, 0.57, 0.82, 1.12, 1.46, + 1.86, 2.32, 2.86, 3.48, 4.21, 5.05, 6.03, 7.16, 8.48, 10.0, 11.8, 13.9, + 16.3, 19.1, 22.3, 26.1, 30.5, 35.6, 41.5, 48.4, 56.4, 65.6, 76.4, 88.9, + 104, 120, 140, 163, 189, 220, 256}; + const gfloat xscale75[76] = {0.00, 0.08, 0.16, 0.25, 0.34, 0.45, 0.56, + 0.68, 0.81, 0.95, 1.10, 1.26, 1.43, 1.62, 1.82, 2.03, 2.27, 2.52, 2.79, + 3.08, 3.39, 3.73, 4.09, 4.48, 4.90, 5.36, 5.85, 6.37, 6.94, 7.55, 8.20, + 8.91, 9.67, 10.5, 11.4, 12.3, 13.3, 14.4, 15.6, 16.9, 18.3, 19.8, 21.4, + 23.1, 24.9, 26.9, 29.1, 31.4, 33.9, 36.5, 39.4, 42.5, 45.9, 49.5, 53.3, + 57.5, 62.0, 66.9, 72.0, 77.7, 83.7, 90.2, 97.2, 105, 113, 122, 131, + 141, 152, 164, 177, 190, 205, 221, 238, 256}; + + const gfloat * xscale; + gint bands, i; + + if (config.analyzer_type == ANALYZER_BARS) + { + if (config.player_shaded) + { + bands = 13; + xscale = xscale13; + } + else + { + bands = 19; + xscale = xscale19; + } + } + else + { + if (config.player_shaded) + { + bands = 37; + xscale = xscale37; + } + else + { + bands = 75; + xscale = xscale75; + } + } - if (!mono_freq_calced) - aud_calc_mono_freq(mono_freq, vis->data, vis->nch); + aud_calc_mono_freq (mono_freq, vis->data, vis->nch); - memset(intern_vis_data, 0, 75); + for (i = 0; i < bands; i ++) + { + gint a = ceil (xscale[i]); + gint b = floor (xscale[i + 1]); + gint n = 0; - if (config.analyzer_type == ANALYZER_BARS) { - if (config.player_shaded) { - max = 13; - } - else { - max = 19; - } - xscale = short_xscale; - } - else { - if (config.player_shaded) { - max = 37; - } - else { - max = 75; - } - xscale = long_xscale; + if (b < a) + n += mono_freq[0][b] * (xscale[i + 1] - xscale[i]); + else + { + if (a > 0) + n += mono_freq[0][a - 1] * (a - xscale[i]); + for (; a < b; a ++) + n += mono_freq[0][a]; + if (b < 256) + n += mono_freq[0][b] * (xscale[i + 1] - b); } - for (i = 0; i < max; i++) { - for (j = xscale[i], y = 0; j < xscale[i + 1]; j++) { - if (mono_freq[0][j] > y) - y = mono_freq[0][j]; - } - y >>= 7; - if (y != 0) { - intern_vis_data[i] = log(y) * y_scale; - if (intern_vis_data[i] > 15) - intern_vis_data[i] = 15; - } - else - intern_vis_data[i] = 0; - } + /* 30 dB range, amplified 10 dB + extra for narrower bands */ + /* 0.000235 == 1 / 13 / 32767 * 10^(40/20) */ + n = 10 * log10 (n * bands * 0.000235); + intern_vis_data[i] = CLAMP (n, 0, 15); + } } else if(config.vis_type == VIS_VOICEPRINT){ if (config.player_shaded) { @@ -305,53 +319,52 @@ ui_main_evlistener_visualization_timeout(gpointer hook_data, gpointer user_data) void ui_main_evlistener_init(void) { - aud_hook_associate("title change", ui_main_evlistener_title_change, NULL); - aud_hook_associate("hide seekbar", ui_main_evlistener_hide_seekbar, NULL); - aud_hook_associate("playback begin", ui_main_evlistener_playback_begin, NULL); - aud_hook_associate("playback stop", ui_main_evlistener_playback_stop, NULL); - aud_hook_associate("playback pause", ui_main_evlistener_playback_pause, NULL); - aud_hook_associate("playback unpause", ui_main_evlistener_playback_unpause, NULL); - aud_hook_associate("playback play file", ui_main_evlistener_playback_play_file, NULL); - aud_hook_associate ("visualization clear", vis_clear_cb, NULL); - aud_hook_associate ("info change", info_change, NULL); - aud_hook_associate("mainwin set always on top", ui_main_evlistener_mainwin_set_always_on_top, NULL); - aud_hook_associate("mainwin show", ui_main_evlistener_mainwin_show, NULL); - aud_hook_associate("equalizerwin show", ui_main_evlistener_equalizerwin_show, NULL); - - aud_hook_associate("playback seek", (HookFunction) mainwin_update_song_info, NULL); - aud_hook_associate ("toggle stop after song", stop_after_song_toggled, NULL); + hook_associate("title change", ui_main_evlistener_title_change, NULL); + hook_associate("hide seekbar", ui_main_evlistener_hide_seekbar, NULL); + hook_associate("playback begin", ui_main_evlistener_playback_begin, NULL); + hook_associate("playback stop", ui_main_evlistener_playback_stop, NULL); + hook_associate("playback pause", ui_main_evlistener_playback_pause, NULL); + hook_associate("playback unpause", ui_main_evlistener_playback_unpause, NULL); + hook_associate("playback play file", ui_main_evlistener_playback_play_file, NULL); + hook_associate ("visualization clear", vis_clear_cb, NULL); + hook_associate ("info change", (HookFunction) info_change, NULL); + hook_associate("mainwin set always on top", ui_main_evlistener_mainwin_set_always_on_top, NULL); + hook_associate("mainwin show", ui_main_evlistener_mainwin_show, NULL); + hook_associate("equalizerwin show", ui_main_evlistener_equalizerwin_show, NULL); + + hook_associate("playback seek", (HookFunction) mainwin_update_song_info, NULL); + hook_associate ("toggle stop after song", stop_after_song_toggled, NULL); } void ui_main_evlistener_dissociate(void) { - aud_hook_dissociate("title change", ui_main_evlistener_title_change); - aud_hook_dissociate("hide seekbar", ui_main_evlistener_hide_seekbar); - aud_hook_dissociate("playback begin", ui_main_evlistener_playback_begin); - aud_hook_dissociate("playback stop", ui_main_evlistener_playback_stop); - aud_hook_dissociate("playback pause", ui_main_evlistener_playback_pause); - aud_hook_dissociate("playback unpause", ui_main_evlistener_playback_unpause); - aud_hook_dissociate("playback play file", ui_main_evlistener_playback_play_file); - aud_hook_dissociate ("visualization clear", vis_clear_cb); - aud_hook_dissociate ("info change", info_change); - aud_hook_dissociate("mainwin set always on top", ui_main_evlistener_mainwin_set_always_on_top); - aud_hook_dissociate("mainwin show", ui_main_evlistener_mainwin_show); - aud_hook_dissociate("equalizerwin show", ui_main_evlistener_equalizerwin_show); - - aud_hook_dissociate("playback seek", (HookFunction) mainwin_update_song_info); - aud_hook_dissociate ("toggle stop after song", stop_after_song_toggled); + hook_dissociate("title change", ui_main_evlistener_title_change); + hook_dissociate("hide seekbar", ui_main_evlistener_hide_seekbar); + hook_dissociate("playback begin", ui_main_evlistener_playback_begin); + hook_dissociate("playback stop", ui_main_evlistener_playback_stop); + hook_dissociate("playback pause", ui_main_evlistener_playback_pause); + hook_dissociate("playback unpause", ui_main_evlistener_playback_unpause); + hook_dissociate("playback play file", ui_main_evlistener_playback_play_file); + hook_dissociate ("visualization clear", vis_clear_cb); + hook_dissociate ("info change", (HookFunction) info_change); + hook_dissociate("mainwin set always on top", ui_main_evlistener_mainwin_set_always_on_top); + hook_dissociate("mainwin show", ui_main_evlistener_mainwin_show); + hook_dissociate("equalizerwin show", ui_main_evlistener_equalizerwin_show); + + hook_dissociate("playback seek", (HookFunction) mainwin_update_song_info); + hook_dissociate ("toggle stop after song", stop_after_song_toggled); } -void start_stop_visual (void) +void start_stop_visual (gboolean exiting) { static char started = 0; - if (config.player_visible && config.vis_type != VIS_OFF) + if (config.player_visible && config.vis_type != VIS_OFF && ! exiting) { if (! started) { - aud_hook_associate ("visualization timeout", - ui_main_evlistener_visualization_timeout, 0); + aud_vis_runner_add_hook(ui_main_evlistener_visualization_timeout, NULL); started = 1; } } @@ -359,8 +372,7 @@ void start_stop_visual (void) { if (started) { - aud_hook_dissociate ("visualization timeout", - ui_main_evlistener_visualization_timeout); + aud_vis_runner_remove_hook(ui_main_evlistener_visualization_timeout); started = 0; } } diff --git a/src/skins/ui_main_evlisteners.h b/src/skins/ui_main_evlisteners.h index 2dade41..8337fbd 100644 --- a/src/skins/ui_main_evlisteners.h +++ b/src/skins/ui_main_evlisteners.h @@ -28,7 +28,8 @@ void ui_main_evlistener_dissociate(void); void ui_main_evlistener_playback_begin (void * hook_data, void * user_data); void ui_main_evlistener_playback_pause (void * hook_data, void * user_data); +void info_change (void); -void start_stop_visual (void); +void start_stop_visual (gboolean exiting); #endif /* AUDACIOUS_UI_MAIN_EVLISTENERS_H */ diff --git a/src/skins/ui_manager.c b/src/skins/ui_manager.c index 90c9f24..527faa7 100644 --- a/src/skins/ui_manager.c +++ b/src/skins/ui_manager.c @@ -26,11 +26,6 @@ #include "actions-playlist.h" #include "actions-equalizer.h" -#if 0 -/* this header contains prototypes for plugin-available menu functions */ -#include "ui_plugin_menu.h" -#endif - /* TODO ui_main.h is only included because ui_manager.c needs the values of TimerMode enum; move that enum elsewhere so we can get rid of this include */ #include "ui_main.h" @@ -41,10 +36,12 @@ #include "plugin.h" #include <audacious/i18n.h> -#include <audacious/ui_plugin_menu.h> +#include <audacious/misc.h> #include <libaudgui/libaudgui.h> +#include <libaudgui/libaudgui-gtk.h> static GtkUIManager *ui_manager = NULL; +static GList * attached_menus = NULL; /* toggle action entries */ @@ -232,9 +229,8 @@ static GtkActionEntry action_entries_playlist[] = { }; static GtkActionEntry action_entries_view[] = { - - { "view", NULL, N_("View") } -}; + {"view", NULL, N_("View")}, + {"iface menu", NULL, N_("Interface")}}; static GtkActionEntry action_entries_playlist_add[] = { { "playlist add url", GTK_STOCK_NETWORK, N_("Add Internet Address..."), "<Ctrl>H", @@ -301,10 +297,6 @@ static GtkActionEntry action_entries_playlist_delete[] = { }; static GtkActionEntry action_entries_playlist_sort[] = { - { "playlist randomize list", AUD_STOCK_RANDOMIZEPL , N_("Randomize List"), "<Ctrl><Shift>R", - N_("Randomizes the playlist."), - G_CALLBACK(action_playlist_randomize_list) }, - { "playlist reverse list", GTK_STOCK_GO_UP , N_("Reverse List"), NULL, N_("Reverses the playlist."), G_CALLBACK(action_playlist_reverse_list) }, @@ -678,6 +670,9 @@ ui_manager_create_menus ( void ) } } +static GtkWidget * menus[UI_MENUS] = {NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL}; + static GtkWidget * create_menu (gint id) { const struct @@ -710,9 +705,6 @@ static GtkWidget * create_menu (gint id) {"/equalizer-menus/preset-menu", NULL, 0}, }; - static GtkWidget * menus[UI_MENUS] = {NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL}; - if (menus[id] == NULL) { menus[id] = ui_manager_get_popup_menu(ui_manager, templates[id].name); @@ -724,12 +716,30 @@ static GtkWidget * create_menu (gint id) GtkWidget * sub = aud_get_plugin_menu (templates[id].plug_id); gtk_menu_item_set_submenu (GTK_MENU_ITEM(item), sub); + attached_menus = g_list_prepend (attached_menus, sub); } + + if (id == UI_MENU_MAIN) + gtk_menu_item_set_submenu ((GtkMenuItem *) gtk_ui_manager_get_widget + (ui_manager, "/mainwin-menus/main-menu/view/iface menu"), + audgui_create_iface_menu ()); } return menus[id]; } +static void destroy_menus (void) +{ + for (gint i = 0; i < G_N_ELEMENTS (menus); i ++) + { + if (menus[i] != NULL) + { + gtk_widget_destroy (menus[i]); + menus[i] = NULL; + } + } +} + GtkAccelGroup * ui_manager_get_accel_group ( void ) { @@ -808,6 +818,12 @@ void ui_popup_menu_show(gint id, gint x, gint y, gboolean leftward, gboolean void ui_manager_destroy( void ) { + g_list_foreach (attached_menus, (GFunc) gtk_menu_detach, NULL); + g_list_free (attached_menus); + attached_menus = NULL; + + destroy_menus (); + g_object_unref(G_OBJECT(toggleaction_group_others)); g_object_unref(G_OBJECT(radioaction_group_anamode)); g_object_unref(G_OBJECT(radioaction_group_anatype)); diff --git a/src/skins/ui_playlist.c b/src/skins/ui_playlist.c index 3128465..25c0ae7 100644 --- a/src/skins/ui_playlist.c +++ b/src/skins/ui_playlist.c @@ -39,6 +39,17 @@ #include <unistd.h> #include <errno.h> +#include <audacious/audconfig.h> +#include <audacious/debug.h> +#include <audacious/drct.h> +#include <audacious/i18n.h> +#include <audacious/misc.h> +#include <audacious/playlist.h> +#include <libaudcore/audstrings.h> +#include <libaudcore/hook.h> +#include <libaudgui/libaudgui.h> +#include <libaudgui/libaudgui-gtk.h> + #include "actions-playlist.h" #include "dnd.h" #include "plugin.h" @@ -48,17 +59,12 @@ #include "ui_manager.h" #include "ui_playlist_evlisteners.h" #include "util.h" - #include "ui_skinned_window.h" #include "ui_skinned_button.h" #include "ui_skinned_textbox.h" #include "ui_skinned_playlist_slider.h" #include "ui_skinned_playlist.h" -#include <audacious/i18n.h> -#include <libaudgui/libaudgui.h> -#include <libaudgui/libaudgui-gtk.h> - #include "images/audacious_playlist.xpm" gint active_playlist; @@ -132,8 +138,8 @@ static void playlistwin_update_info (void) gchar *text, *sel_text, *tot_text; gint64 selection, total; - total = aud_playlist_get_total_length (active_playlist) / 1000; - selection = aud_playlist_get_selected_length (active_playlist) / 1000; + total = aud_playlist_get_total_length (active_playlist, TRUE) / 1000; + selection = aud_playlist_get_selected_length (active_playlist, TRUE) / 1000; if (selection >= 3600) sel_text = g_strdup_printf ("%" PRId64 ":%02" PRId64 ":%02" PRId64, @@ -166,13 +172,13 @@ static void update_rollup_text (void) if (entry > -1) { - gint length = aud_playlist_entry_get_length (playlist, entry); + gint length = aud_playlist_entry_get_length (playlist, entry, FALSE); if (aud_cfg->show_numbers_in_pl) snprintf (scratch, sizeof scratch, "%d. ", 1 + entry); snprintf (scratch + strlen (scratch), sizeof scratch - strlen (scratch), - "%s", aud_playlist_entry_get_title (playlist, entry)); + "%s", aud_playlist_entry_get_title (playlist, entry, FALSE)); if (length > 0) snprintf (scratch + strlen (scratch), sizeof scratch - strlen @@ -462,24 +468,24 @@ playlistwin_select_search(void) case GTK_RESPONSE_ACCEPT: { /* create a TitleInput tuple with user search data */ - Tuple *tuple = aud_tuple_new(); + Tuple *tuple = tuple_new(); gchar *searchdata = NULL; searchdata = (gchar*)gtk_entry_get_text( GTK_ENTRY(searchdlg_entry_title) ); AUDDBG("title=\"%s\"\n", searchdata); - aud_tuple_associate_string(tuple, FIELD_TITLE, NULL, searchdata); + tuple_associate_string(tuple, FIELD_TITLE, NULL, searchdata); searchdata = (gchar*)gtk_entry_get_text( GTK_ENTRY(searchdlg_entry_album) ); AUDDBG("album=\"%s\"\n", searchdata); - aud_tuple_associate_string(tuple, FIELD_ALBUM, NULL, searchdata); + tuple_associate_string(tuple, FIELD_ALBUM, NULL, searchdata); searchdata = (gchar*)gtk_entry_get_text( GTK_ENTRY(searchdlg_entry_performer) ); AUDDBG("performer=\"%s\"\n", searchdata); - aud_tuple_associate_string(tuple, FIELD_ARTIST, NULL, searchdata); + tuple_associate_string(tuple, FIELD_ARTIST, NULL, searchdata); searchdata = (gchar*)gtk_entry_get_text( GTK_ENTRY(searchdlg_entry_file_name) ); AUDDBG("filename=\"%s\"\n", searchdata); - aud_tuple_associate_string(tuple, FIELD_FILE_NAME, NULL, searchdata); + tuple_associate_string(tuple, FIELD_FILE_NAME, NULL, searchdata); /* check if previous selection should be cleared before searching */ if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(searchdlg_checkbt_clearprevsel)) == TRUE ) @@ -672,44 +678,9 @@ show_playlist_overwrite_prompt(GtkWindow * parent, } static void -show_playlist_save_format_error(GtkWindow * parent, - const gchar * filename) -{ - const gchar *markup = - N_("<b><big>Unable to save playlist.</big></b>\n\n" - "Unknown file type for '%s'.\n"); - - GtkWidget *dialog; - - g_return_if_fail(GTK_IS_WINDOW(parent)); - g_return_if_fail(filename != NULL); - - dialog = - gtk_message_dialog_new_with_markup(GTK_WINDOW(parent), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - _(markup), - filename); - - gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER); /* centering */ - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); -} - -static void playlistwin_save_playlist(const gchar * filename) { - PlaylistContainer *plc; - gchar *ext = strrchr(filename, '.') + 1; - - plc = aud_playlist_container_find(ext); - if (plc == NULL) { - show_playlist_save_format_error(GTK_WINDOW(playlistwin), filename); - return; - } - - aud_str_replace_in(&aud_cfg->playlist_path, g_path_get_dirname(filename)); + str_replace_in(&aud_cfg->playlist_path, g_path_get_dirname(filename)); if (g_file_test(filename, G_FILE_TEST_IS_REGULAR)) if (!show_playlist_overwrite_prompt(GTK_WINDOW(playlistwin), filename)) @@ -722,7 +693,7 @@ playlistwin_save_playlist(const gchar * filename) static void playlistwin_load_playlist(const gchar * filename) { - aud_str_replace_in(&aud_cfg->playlist_path, g_path_get_dirname(filename)); + str_replace_in(&aud_cfg->playlist_path, g_path_get_dirname(filename)); aud_playlist_entry_delete (active_playlist, 0, aud_playlist_entry_count (active_playlist)); @@ -962,7 +933,7 @@ static gboolean playlistwin_delete(GtkWidget *widget, void *data) if (config.show_wm_decorations) playlistwin_show(FALSE); else - audacious_drct_quit(); + aud_drct_quit(); return TRUE; } @@ -1017,13 +988,13 @@ static void drag_data_received (GtkWidget * widget, GdkDragContext * context, static void local_playlist_prev(void) { - audacious_drct_pl_prev (); + aud_drct_pl_prev (); } static void local_playlist_next(void) { - audacious_drct_pl_next (); + aud_drct_pl_next (); } static void playlistwin_hide (void) @@ -1113,7 +1084,7 @@ playlistwin_create_widgets(void) ui_skinned_small_button_setup(playlistwin_spause, SKINNED_WINDOW(playlistwin)->normal, playlistwin_get_width() - 128, config.playlist_height - 16, 10, 7); - g_signal_connect(playlistwin_spause, "clicked", audacious_drct_pause, NULL); + g_signal_connect(playlistwin_spause, "clicked", aud_drct_pause, NULL); /* stop button */ playlistwin_sstop = ui_skinned_button_new(); @@ -1291,14 +1262,14 @@ playlistwin_create(void) ui_skinned_playlist_follow (playlistwin_list); song_changed = FALSE; - aud_hook_associate ("playlist position", follow_cb, 0); - aud_hook_associate ("playlist update", update_cb, 0); + hook_associate ("playlist position", follow_cb, 0); + hook_associate ("playlist update", update_cb, 0); } void playlistwin_unhook (void) { - aud_hook_dissociate ("playlist position", follow_cb); - aud_hook_dissociate ("playlist update", update_cb); + hook_dissociate ("playlist position", follow_cb); + hook_dissociate ("playlist update", update_cb); ui_playlist_evlistener_dissociate (); } @@ -1432,11 +1403,6 @@ void action_playlist_sort_selected_by_filename (void) aud_playlist_sort_selected_by_scheme (active_playlist, PLAYLIST_SORT_FILENAME); } -void action_playlist_randomize_list (void) -{ - aud_playlist_randomize (active_playlist); -} - void action_playlist_reverse_list (void) { aud_playlist_reverse (active_playlist); @@ -1530,7 +1496,7 @@ action_playlist_add_files(void) void action_playlist_add_url(void) { - audgui_show_add_url_window(); + audgui_show_add_url_window (FALSE); } void action_playlist_new (void) @@ -1564,7 +1530,7 @@ void action_playlist_save_list (void) void action_playlist_save_all_playlists (void) { - aud_save_all_playlists (); + aud_save_playlists (); } void action_playlist_load_list (void) diff --git a/src/skins/ui_playlist_evlisteners.c b/src/skins/ui_playlist_evlisteners.c index 6bbe665..6d0cb08 100644 --- a/src/skins/ui_playlist_evlisteners.c +++ b/src/skins/ui_playlist_evlisteners.c @@ -18,10 +18,11 @@ * Audacious or using our public API to be a derived work. */ -#include "ui_playlist_evlisteners.h" - #include <glib.h> +#include <libaudcore/hook.h> + #include "ui_playlist.h" +#include "ui_playlist_evlisteners.h" static void ui_playlist_evlistener_playlistwin_show(gpointer hook_data, gpointer user_data) @@ -32,10 +33,10 @@ ui_playlist_evlistener_playlistwin_show(gpointer hook_data, gpointer user_data) void ui_playlist_evlistener_init(void) { - aud_hook_associate("playlistwin show", ui_playlist_evlistener_playlistwin_show, NULL); + hook_associate("playlistwin show", ui_playlist_evlistener_playlistwin_show, NULL); } void ui_playlist_evlistener_dissociate(void) { - aud_hook_dissociate("playlistwin show", ui_playlist_evlistener_playlistwin_show); + hook_dissociate("playlistwin show", ui_playlist_evlistener_playlistwin_show); } diff --git a/src/skins/ui_skin.c b/src/skins/ui_skin.c index 14ac844..06a9841 100644 --- a/src/skins/ui_skin.c +++ b/src/skins/ui_skin.c @@ -35,9 +35,11 @@ #include <stdlib.h> #include <string.h> #include <ctype.h> -#include "plugin.h" +#include <audacious/debug.h> #include <audacious/plugin.h> + +#include "plugin.h" #include "ui_skin.h" #include "util.h" #include "ui_main.h" @@ -249,6 +251,14 @@ skin_free(Skin * skin) skin->path = NULL; skin_set_default_vis_color(skin); + + if (original_gtk_theme != NULL) + { + gtk_settings_set_string_property (gtk_settings_get_default (), + "gtk-theme-name", original_gtk_theme, "audacious"); + g_free (original_gtk_theme); + original_gtk_theme = NULL; + } } void @@ -559,6 +569,13 @@ void cleanup_skins() { skin_destroy(aud_active_skin); aud_active_skin = NULL; + + gtk_widget_destroy (mainwin); + mainwin = NULL; + gtk_widget_destroy (playlistwin); + playlistwin = NULL; + gtk_widget_destroy (equalizerwin); + equalizerwin = NULL; } @@ -650,11 +667,11 @@ skin_parse_hints(Skin * skin, gchar *path_p) if (filename == NULL) return; - inifile = aud_open_ini_file(filename); + inifile = open_ini_file(filename); if (!inifile) return; - tmp = aud_read_ini_string(inifile, "skin", "mainwinOthertext"); + tmp = read_ini_string(inifile, "skin", "mainwinOthertext"); if (tmp != NULL) { @@ -662,7 +679,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinVisX"); + tmp = read_ini_string(inifile, "skin", "mainwinVisX"); if (tmp != NULL) { @@ -670,7 +687,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinVisY"); + tmp = read_ini_string(inifile, "skin", "mainwinVisY"); if (tmp != NULL) { @@ -678,7 +695,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinVisWidth"); + tmp = read_ini_string(inifile, "skin", "mainwinVisWidth"); if (tmp != NULL) { @@ -686,7 +703,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinTextX"); + tmp = read_ini_string(inifile, "skin", "mainwinTextX"); if (tmp != NULL) { @@ -694,7 +711,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinTextY"); + tmp = read_ini_string(inifile, "skin", "mainwinTextY"); if (tmp != NULL) { @@ -702,7 +719,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinTextWidth"); + tmp = read_ini_string(inifile, "skin", "mainwinTextWidth"); if (tmp != NULL) { @@ -710,7 +727,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinInfoBarX"); + tmp = read_ini_string(inifile, "skin", "mainwinInfoBarX"); if (tmp != NULL) { @@ -718,7 +735,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinInfoBarY"); + tmp = read_ini_string(inifile, "skin", "mainwinInfoBarY"); if (tmp != NULL) { @@ -726,7 +743,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinNumber0X"); + tmp = read_ini_string(inifile, "skin", "mainwinNumber0X"); if (tmp != NULL) { @@ -734,7 +751,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinNumber0Y"); + tmp = read_ini_string(inifile, "skin", "mainwinNumber0Y"); if (tmp != NULL) { @@ -742,7 +759,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinNumber1X"); + tmp = read_ini_string(inifile, "skin", "mainwinNumber1X"); if (tmp != NULL) { @@ -750,7 +767,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinNumber1Y"); + tmp = read_ini_string(inifile, "skin", "mainwinNumber1Y"); if (tmp != NULL) { @@ -758,7 +775,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinNumber2X"); + tmp = read_ini_string(inifile, "skin", "mainwinNumber2X"); if (tmp != NULL) { @@ -766,7 +783,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinNumber2Y"); + tmp = read_ini_string(inifile, "skin", "mainwinNumber2Y"); if (tmp != NULL) { @@ -774,7 +791,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinNumber3X"); + tmp = read_ini_string(inifile, "skin", "mainwinNumber3X"); if (tmp != NULL) { @@ -782,7 +799,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinNumber3Y"); + tmp = read_ini_string(inifile, "skin", "mainwinNumber3Y"); if (tmp != NULL) { @@ -790,7 +807,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinNumber4X"); + tmp = read_ini_string(inifile, "skin", "mainwinNumber4X"); if (tmp != NULL) { @@ -798,7 +815,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinNumber4Y"); + tmp = read_ini_string(inifile, "skin", "mainwinNumber4Y"); if (tmp != NULL) { @@ -806,7 +823,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinPlayStatusX"); + tmp = read_ini_string(inifile, "skin", "mainwinPlayStatusX"); if (tmp != NULL) { @@ -814,7 +831,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinPlayStatusY"); + tmp = read_ini_string(inifile, "skin", "mainwinPlayStatusY"); if (tmp != NULL) { @@ -822,7 +839,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinMenurowVisible"); + tmp = read_ini_string(inifile, "skin", "mainwinMenurowVisible"); if (tmp != NULL) { @@ -830,7 +847,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinVolumeX"); + tmp = read_ini_string(inifile, "skin", "mainwinVolumeX"); if (tmp != NULL) { @@ -838,7 +855,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinVolumeY"); + tmp = read_ini_string(inifile, "skin", "mainwinVolumeY"); if (tmp != NULL) { @@ -846,7 +863,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinBalanceX"); + tmp = read_ini_string(inifile, "skin", "mainwinBalanceX"); if (tmp != NULL) { @@ -854,7 +871,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinBalanceY"); + tmp = read_ini_string(inifile, "skin", "mainwinBalanceY"); if (tmp != NULL) { @@ -862,7 +879,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinPositionX"); + tmp = read_ini_string(inifile, "skin", "mainwinPositionX"); if (tmp != NULL) { @@ -870,7 +887,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinPositionY"); + tmp = read_ini_string(inifile, "skin", "mainwinPositionY"); if (tmp != NULL) { @@ -878,7 +895,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinOthertextIsStatus"); + tmp = read_ini_string(inifile, "skin", "mainwinOthertextIsStatus"); if (tmp != NULL) { @@ -886,7 +903,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinOthertextVisible"); + tmp = read_ini_string(inifile, "skin", "mainwinOthertextVisible"); if (tmp != NULL) { @@ -894,7 +911,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinTextVisible"); + tmp = read_ini_string(inifile, "skin", "mainwinTextVisible"); if (tmp != NULL) { @@ -902,7 +919,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinVisVisible"); + tmp = read_ini_string(inifile, "skin", "mainwinVisVisible"); if (tmp != NULL) { @@ -910,7 +927,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinPreviousX"); + tmp = read_ini_string(inifile, "skin", "mainwinPreviousX"); if (tmp != NULL) { @@ -918,7 +935,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinPreviousY"); + tmp = read_ini_string(inifile, "skin", "mainwinPreviousY"); if (tmp != NULL) { @@ -926,7 +943,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinPlayX"); + tmp = read_ini_string(inifile, "skin", "mainwinPlayX"); if (tmp != NULL) { @@ -934,7 +951,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinPlayY"); + tmp = read_ini_string(inifile, "skin", "mainwinPlayY"); if (tmp != NULL) { @@ -942,7 +959,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinPauseX"); + tmp = read_ini_string(inifile, "skin", "mainwinPauseX"); if (tmp != NULL) { @@ -950,7 +967,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinPauseY"); + tmp = read_ini_string(inifile, "skin", "mainwinPauseY"); if (tmp != NULL) { @@ -958,7 +975,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinStopX"); + tmp = read_ini_string(inifile, "skin", "mainwinStopX"); if (tmp != NULL) { @@ -966,7 +983,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinStopY"); + tmp = read_ini_string(inifile, "skin", "mainwinStopY"); if (tmp != NULL) { @@ -974,7 +991,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinNextX"); + tmp = read_ini_string(inifile, "skin", "mainwinNextX"); if (tmp != NULL) { @@ -982,7 +999,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinNextY"); + tmp = read_ini_string(inifile, "skin", "mainwinNextY"); if (tmp != NULL) { @@ -990,7 +1007,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinEjectX"); + tmp = read_ini_string(inifile, "skin", "mainwinEjectX"); if (tmp != NULL) { @@ -998,7 +1015,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinEjectY"); + tmp = read_ini_string(inifile, "skin", "mainwinEjectY"); if (tmp != NULL) { @@ -1006,7 +1023,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinWidth"); + tmp = read_ini_string(inifile, "skin", "mainwinWidth"); if (tmp != NULL) { @@ -1016,7 +1033,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) skin_mask_info[0].width = skin->properties.mainwin_width; - tmp = aud_read_ini_string(inifile, "skin", "mainwinHeight"); + tmp = read_ini_string(inifile, "skin", "mainwinHeight"); if (tmp != NULL) { @@ -1026,7 +1043,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) skin_mask_info[0].height = skin->properties.mainwin_height; - tmp = aud_read_ini_string(inifile, "skin", "mainwinAboutX"); + tmp = read_ini_string(inifile, "skin", "mainwinAboutX"); if (tmp != NULL) { @@ -1034,7 +1051,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinAboutY"); + tmp = read_ini_string(inifile, "skin", "mainwinAboutY"); if (tmp != NULL) { @@ -1042,7 +1059,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinShuffleX"); + tmp = read_ini_string(inifile, "skin", "mainwinShuffleX"); if (tmp != NULL) { @@ -1050,7 +1067,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinShuffleY"); + tmp = read_ini_string(inifile, "skin", "mainwinShuffleY"); if (tmp != NULL) { @@ -1058,7 +1075,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinRepeatX"); + tmp = read_ini_string(inifile, "skin", "mainwinRepeatX"); if (tmp != NULL) { @@ -1066,7 +1083,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinRepeatY"); + tmp = read_ini_string(inifile, "skin", "mainwinRepeatY"); if (tmp != NULL) { @@ -1074,7 +1091,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinEQButtonX"); + tmp = read_ini_string(inifile, "skin", "mainwinEQButtonX"); if (tmp != NULL) { @@ -1082,7 +1099,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinEQButtonY"); + tmp = read_ini_string(inifile, "skin", "mainwinEQButtonY"); if (tmp != NULL) { @@ -1090,7 +1107,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinPLButtonX"); + tmp = read_ini_string(inifile, "skin", "mainwinPLButtonX"); if (tmp != NULL) { @@ -1098,7 +1115,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinPLButtonY"); + tmp = read_ini_string(inifile, "skin", "mainwinPLButtonY"); if (tmp != NULL) { @@ -1106,7 +1123,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "textboxBitmapFontWidth"); + tmp = read_ini_string(inifile, "skin", "textboxBitmapFontWidth"); if (tmp != NULL) { @@ -1114,7 +1131,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "textboxBitmapFontHeight"); + tmp = read_ini_string(inifile, "skin", "textboxBitmapFontHeight"); if (tmp != NULL) { @@ -1122,7 +1139,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinMinimizeX"); + tmp = read_ini_string(inifile, "skin", "mainwinMinimizeX"); if (tmp != NULL) { @@ -1130,7 +1147,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinMinimizeY"); + tmp = read_ini_string(inifile, "skin", "mainwinMinimizeY"); if (tmp != NULL) { @@ -1138,7 +1155,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinShadeX"); + tmp = read_ini_string(inifile, "skin", "mainwinShadeX"); if (tmp != NULL) { @@ -1146,7 +1163,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinShadeY"); + tmp = read_ini_string(inifile, "skin", "mainwinShadeY"); if (tmp != NULL) { @@ -1154,7 +1171,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinCloseX"); + tmp = read_ini_string(inifile, "skin", "mainwinCloseX"); if (tmp != NULL) { @@ -1162,7 +1179,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) g_free(tmp); } - tmp = aud_read_ini_string(inifile, "skin", "mainwinCloseY"); + tmp = read_ini_string(inifile, "skin", "mainwinCloseY"); if (tmp != NULL) { @@ -1173,7 +1190,7 @@ skin_parse_hints(Skin * skin, gchar *path_p) if (filename != NULL) g_free(filename); - aud_close_ini_file(inifile); + close_ini_file(inifile); } static guint @@ -1202,7 +1219,7 @@ skin_load_color(INIFile *inifile, if (inifile || default_hex) { if (inifile) { - value = aud_read_ini_string(inifile, section, key); + value = read_ini_string(inifile, section, key); if (value == NULL) { value = g_strdup(default_hex); } @@ -1269,22 +1286,22 @@ skin_create_transparent_mask(const gchar * path, if (!filename) return create_default_mask(window, width, height); - inifile = aud_open_ini_file(filename); + inifile = open_ini_file(filename); - if ((num = aud_read_ini_array(inifile, section, "NumPoints")) == NULL) { + if ((num = read_ini_array(inifile, section, "NumPoints")) == NULL) { g_free(filename); - aud_close_ini_file(inifile); + close_ini_file(inifile); return NULL; } - if ((point = aud_read_ini_array(inifile, section, "PointList")) == NULL) { + if ((point = read_ini_array(inifile, section, "PointList")) == NULL) { g_array_free(num, TRUE); g_free(filename); - aud_close_ini_file(inifile); + close_ini_file(inifile); return NULL; } - aud_close_ini_file(inifile); + close_ini_file(inifile); mask = gdk_pixmap_new(window, width, height, 1); gc = gdk_gc_new(mask); @@ -1415,7 +1432,7 @@ skin_load_pixmaps(Skin * skin, const gchar * path) skin_numbers_generate_dash(skin); filename = find_file_case_uri (path, "pledit.txt"); - inifile = (filename != NULL) ? aud_open_ini_file (filename) : NULL; + inifile = (filename != NULL) ? open_ini_file (filename) : NULL; skin->colors[SKIN_PLEDIT_NORMAL] = skin_load_color(inifile, "Text", "Normal", "#2499ff"); @@ -1427,7 +1444,7 @@ skin_load_pixmaps(Skin * skin, const gchar * path) skin_load_color(inifile, "Text", "SelectedBG", "#0a124a"); if (inifile) - aud_close_ini_file(inifile); + close_ini_file(inifile); if (filename) g_free(filename); @@ -1486,7 +1503,6 @@ skin_check_pixmaps(const Skin * skin, const gchar * skin_path) static gboolean skin_load_nolock(Skin * skin, const gchar * path, gboolean force) { - GtkSettings *settings; gchar *gtkrcpath; gchar *newpath, *skin_path; int archive = 0; @@ -1545,23 +1561,13 @@ skin_load_nolock(Skin * skin, const gchar * path, gboolean force) return FALSE; } - /* restore gtk theme if changed by previous skin */ - settings = gtk_settings_get_default(); - - if (original_gtk_theme != NULL) { - gtk_settings_set_string_property(settings, "gtk-theme-name", - original_gtk_theme, "audacious"); - g_free(original_gtk_theme); - original_gtk_theme = NULL; - } - #ifndef _WIN32 if (! config.disable_inline_gtk && ! archive) { gtkrcpath = g_strdup_printf ("%s/gtk-2.0/gtkrc", skin->path); if (g_file_test (gtkrcpath, G_FILE_TEST_IS_REGULAR)) - skin_set_gtk_theme (settings, skin); + skin_set_gtk_theme (gtk_settings_get_default (), skin); g_free (gtkrcpath); } diff --git a/src/skins/ui_skinned_equalizer_graph.c b/src/skins/ui_skinned_equalizer_graph.c index 9d68aca..2ab99a7 100644 --- a/src/skins/ui_skinned_equalizer_graph.c +++ b/src/skins/ui_skinned_equalizer_graph.c @@ -26,7 +26,7 @@ #include "skins_cfg.h" #include "util.h" -#include <audacious/plugin.h> +#include <audacious/audconfig.h> #define UI_TYPE_SKINNED_EQUALIZER_GRAPH (ui_skinned_equalizer_graph_get_type()) diff --git a/src/skins/ui_skinned_playlist.c b/src/skins/ui_skinned_playlist.c index 6c3ba3b..c351091 100644 --- a/src/skins/ui_skinned_playlist.c +++ b/src/skins/ui_skinned_playlist.c @@ -52,7 +52,10 @@ #include "ui_skin.h" #include "util.h" #include "skins_cfg.h" -#include <audacious/plugin.h> + +#include <audacious/audconfig.h> +#include <audacious/drct.h> +#include <audacious/playlist.h> #include <libaudgui/libaudgui.h> #define UI_SKINNED_PLAYLIST_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ui_skinned_playlist_get_type(), UiSkinnedPlaylistPrivate)) @@ -410,7 +413,7 @@ static gboolean ui_skinned_playlist_expose(GtkWidget *widget, GdkEventExpose *ev for (i = priv->first; i < priv->first + priv->rows && i < active_length; i ++) { - gint i_length = aud_playlist_entry_get_length (active_playlist, i); + gint i_length = aud_playlist_entry_get_length (active_playlist, i, TRUE); if (i_length > 0) g_snprintf (length, sizeof (length), "%d:%02d", i_length / 60000, @@ -433,8 +436,9 @@ static gboolean ui_skinned_playlist_expose(GtkWidget *widget, GdkEventExpose *ev for (i = priv->first; i < priv->first + priv->rows && i < active_length; i ++) { - const gchar * title = aud_playlist_entry_get_title (active_playlist, i); - gint i_length = aud_playlist_entry_get_length (active_playlist, i); + const gchar * title = aud_playlist_entry_get_title (active_playlist, i, + TRUE); + gint i_length = aud_playlist_entry_get_length (active_playlist, i, TRUE); gint pos = aud_playlist_queue_find_entry (active_playlist, i); tail[0] = 0; @@ -816,7 +820,7 @@ gboolean ui_skinned_playlist_key (GtkWidget * widget, GdkEventKey * event) select_single (private, TRUE, 0); aud_playlist_set_playing (active_playlist); aud_playlist_set_position (active_playlist, private->focused); - audacious_drct_play (); + aud_drct_play (); break; case GDK_Escape: select_single (private, FALSE, aud_playlist_get_position @@ -1060,7 +1064,7 @@ static gboolean ui_skinned_playlist_button_press (GtkWidget * widget, aud_playlist_set_playing (active_playlist); aud_playlist_set_position (active_playlist, position); - audacious_drct_play (); + aud_drct_play (); break; default: return TRUE; diff --git a/src/skins/ui_skinned_textbox.c b/src/skins/ui_skinned_textbox.c index e22a66e..4022a8e 100644 --- a/src/skins/ui_skinned_textbox.c +++ b/src/skins/ui_skinned_textbox.c @@ -24,11 +24,13 @@ * Audacious or using our public API to be a derived work. */ +#include <string.h> + +#include <libaudcore/audstrings.h> + #include "ui_skinned_textbox.h" #include "skins_cfg.h" #include "plugin.h" -#include <string.h> - #include "util.h" #define UI_SKINNED_TEXTBOX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ui_skinned_textbox_get_type(), UiSkinnedTextboxPrivate)) @@ -531,7 +533,7 @@ void ui_skinned_textbox_set_text(GtkWidget *widget, const gchar *text) { if (textbox->text) g_free(textbox->text); - textbox->text = aud_str_to_utf8(text); + textbox->text = str_to_utf8(text); priv->scroll_back = FALSE; if (widget_really_drawable (widget)) diff --git a/src/skins/ui_svis.c b/src/skins/ui_svis.c index 2bb9dab..2b7f8ff 100644 --- a/src/skins/ui_svis.c +++ b/src/skins/ui_svis.c @@ -29,13 +29,16 @@ #include "ui_vis.h" #include "util.h" #include "skins_cfg.h" -#include <audacious/plugin.h> + #include <string.h> #include <ctype.h> #include <gtk/gtkmain.h> #include <gtk/gtkmarshal.h> #include <gtk/gtkimage.h> +#include <audacious/drct.h> +#include <audacious/plugin.h> + #define UI_TYPE_SVIS (ui_svis_get_type()) /* FIXME: Are the svis_scope_colors correct? */ @@ -322,8 +325,8 @@ static gboolean ui_svis_expose (GtkWidget * widget, GdkEventExpose * event) if (!config.scaled) { memset (rgb_data, 0, SVIS_WIDTH * SVIS_HEIGHT); - if (config.vis_type == VIS_ANALYZER && !audacious_drct_get_paused () - && audacious_drct_get_playing ()) + if (config.vis_type == VIS_ANALYZER && !aud_drct_get_paused () + && aud_drct_get_playing ()) { for (y = 0; y < SVIS_HEIGHT; y++) { @@ -402,8 +405,8 @@ static gboolean ui_svis_expose (GtkWidget * widget, GdkEventExpose * event) memset (rgb_data, 0, SVIS_WIDTH * config.scale_factor * SVIS_HEIGHT * config.scale_factor); - if (config.vis_type == VIS_ANALYZER && !audacious_drct_get_paused () - && audacious_drct_get_playing ()) + if (config.vis_type == VIS_ANALYZER && !aud_drct_get_paused () + && aud_drct_get_playing ()) { for (y = 0; y < SVIS_HEIGHT; y++) { diff --git a/src/skins/util.c b/src/skins/util.c index 072f97f..da3a467 100644 --- a/src/skins/util.c +++ b/src/skins/util.c @@ -42,8 +42,10 @@ # include <fts.h> #endif +#include <audacious/debug.h> #include <audacious/i18n.h> #include <libaudcore/audstrings.h> +#include <libaudcore/hook.h> #include "plugin.h" @@ -122,20 +124,20 @@ gchar * load_text_file (const gchar * filename) gint size; gchar * buffer; - file = aud_vfs_fopen (filename, "r"); + file = vfs_fopen (filename, "r"); if (file == NULL) return NULL; - size = aud_vfs_fsize (file); + size = vfs_fsize (file); size = MAX (0, size); buffer = g_malloc (size + 1); - size = aud_vfs_fread (buffer, 1, size, file); + size = vfs_fread (buffer, 1, size, file); size = MAX (0, size); buffer[size] = 0; - aud_vfs_fclose (file); + vfs_fclose (file); return buffer; } @@ -452,7 +454,7 @@ INIFile *open_ini_file(const gchar *filename) unsigned char x[] = { 0xff, 0xfe, 0x00 }; g_return_val_if_fail(filename, NULL); - aud_vfs_file_get_contents(filename, &buffer, &filesize); + vfs_file_get_contents(filename, (void * *) &buffer, &filesize); if (buffer == NULL) return NULL; @@ -659,7 +661,6 @@ gchar *read_ini_string(INIFile *inifile, const gchar *section, const gchar *key) g_string_free(section_string, TRUE); g_string_free(key_string, TRUE); - g_return_val_if_fail(value, NULL); return value; } @@ -868,5 +869,5 @@ void check_set (GtkActionGroup * action_group, const gchar * action_name, g_return_if_fail (action != NULL); gtk_toggle_action_set_active ((GtkToggleAction *) action, is_on); - aud_hook_call (action_name, GINT_TO_POINTER (is_on)); + hook_call (action_name, GINT_TO_POINTER (is_on)); } diff --git a/src/skins/util.h b/src/skins/util.h index 2d78e47..a0cfacc 100644 --- a/src/skins/util.h +++ b/src/skins/util.h @@ -45,6 +45,7 @@ void del_directory(const gchar *dirname); gboolean dir_foreach(const gchar *path, DirForeachFunc function, gpointer user_data, GError **error); +typedef GHashTable INIFile; INIFile *open_ini_file(const gchar *filename); void close_ini_file(INIFile *key_file); diff --git a/src/smb/smb.c b/src/smb/smb.c index b3fb5ab..c9a23a9 100644 --- a/src/smb/smb.c +++ b/src/smb/smb.c @@ -41,7 +41,7 @@ typedef struct _SMBFile { } SMBFile; /* TODO: make writing work. */ -VFSFile *smb_aud_vfs_fopen_impl(const gchar * path, const gchar * mode) +VFSFile *smb_vfs_fopen_impl(const gchar * path, const gchar * mode) { VFSFile *file; SMBFile *handle; @@ -66,7 +66,7 @@ VFSFile *smb_aud_vfs_fopen_impl(const gchar * path, const gchar * mode) return file; } -gint smb_aud_vfs_fclose_impl(VFSFile * file) +gint smb_vfs_fclose_impl(VFSFile * file) { gint ret = 0; SMBFile *handle; @@ -85,7 +85,7 @@ gint smb_aud_vfs_fclose_impl(VFSFile * file) return ret; } -size_t smb_aud_vfs_fread_impl(gpointer ptr, size_t size, size_t nmemb, VFSFile * file) +size_t smb_vfs_fread_impl(gpointer ptr, size_t size, size_t nmemb, VFSFile * file) { SMBFile *handle; if (file == NULL) @@ -94,12 +94,12 @@ size_t smb_aud_vfs_fread_impl(gpointer ptr, size_t size, size_t nmemb, VFSFile * return smbc_read(handle->fd, ptr, size * nmemb); } -size_t smb_aud_vfs_fwrite_impl(gconstpointer ptr, size_t size, size_t nmemb, VFSFile * file) +size_t smb_vfs_fwrite_impl(gconstpointer ptr, size_t size, size_t nmemb, VFSFile * file) { return 0; } -gint smb_aud_vfs_getc_impl(VFSFile *file) +gint smb_vfs_getc_impl(VFSFile *file) { SMBFile *handle; char temp; @@ -108,7 +108,7 @@ gint smb_aud_vfs_getc_impl(VFSFile *file) return (gint) temp; } -gint smb_aud_vfs_fseek_impl(VFSFile * file, glong offset, gint whence) +gint smb_vfs_fseek_impl(VFSFile * file, glong offset, gint whence) { SMBFile *handle; glong roffset = offset; @@ -138,19 +138,19 @@ gint smb_aud_vfs_fseek_impl(VFSFile * file, glong offset, gint whence) return ret; } -gint smb_aud_vfs_ungetc_impl(gint c, VFSFile *file) +gint smb_vfs_ungetc_impl(gint c, VFSFile *file) { - smb_aud_vfs_fseek_impl(file, -1, SEEK_CUR); + smb_vfs_fseek_impl(file, -1, SEEK_CUR); return c; } -void smb_aud_vfs_rewind_impl(VFSFile * file) +void smb_vfs_rewind_impl(VFSFile * file) { - smb_aud_vfs_fseek_impl(file, 0, SEEK_SET); + smb_vfs_fseek_impl(file, 0, SEEK_SET); } glong -smb_aud_vfs_ftell_impl(VFSFile * file) +smb_vfs_ftell_impl(VFSFile * file) { SMBFile *handle; handle = (SMBFile *)file->handle; @@ -158,25 +158,25 @@ smb_aud_vfs_ftell_impl(VFSFile * file) } gboolean -smb_aud_vfs_feof_impl(VFSFile * file) +smb_vfs_feof_impl(VFSFile * file) { SMBFile *handle; off_t at; - at = smb_aud_vfs_ftell_impl(file); + at = smb_vfs_ftell_impl(file); //printf("%d %d %ld %ld\n",sizeof(int), sizeof(off_t), at, handle->length); return (gboolean) (at == handle->length) ? TRUE : FALSE; } gint -smb_aud_vfs_truncate_impl(VFSFile * file, glong size) +smb_vfs_truncate_impl(VFSFile * file, glong size) { return -1; } off_t -smb_aud_vfs_fsize_impl(VFSFile * file) +smb_vfs_fsize_impl(VFSFile * file) { SMBFile *handle = (SMBFile *)file->handle; @@ -185,18 +185,18 @@ smb_aud_vfs_fsize_impl(VFSFile * file) VFSConstructor smb_const = { "smb://", - smb_aud_vfs_fopen_impl, - smb_aud_vfs_fclose_impl, - smb_aud_vfs_fread_impl, - smb_aud_vfs_fwrite_impl, - smb_aud_vfs_getc_impl, - smb_aud_vfs_ungetc_impl, - smb_aud_vfs_fseek_impl, - smb_aud_vfs_rewind_impl, - smb_aud_vfs_ftell_impl, - smb_aud_vfs_feof_impl, - smb_aud_vfs_truncate_impl, - smb_aud_vfs_fsize_impl + smb_vfs_fopen_impl, + smb_vfs_fclose_impl, + smb_vfs_fread_impl, + smb_vfs_fwrite_impl, + smb_vfs_getc_impl, + smb_vfs_ungetc_impl, + smb_vfs_fseek_impl, + smb_vfs_rewind_impl, + smb_vfs_ftell_impl, + smb_vfs_feof_impl, + smb_vfs_truncate_impl, + smb_vfs_fsize_impl }; static void init(void) @@ -210,13 +210,13 @@ static void init(void) return; } - aud_vfs_register_transport(&smb_const); + vfs_register_transport(&smb_const); } static void cleanup(void) { #if 0 - aud_vfs_unregister_transport(&smb_const); + vfs_unregister_transport(&smb_const); #endif } diff --git a/src/sndfile/plugin.c b/src/sndfile/plugin.c index 99ab7ce..d9af8c9 100644 --- a/src/sndfile/plugin.c +++ b/src/sndfile/plugin.c @@ -1,5 +1,5 @@ /* Audacious - Cross-platform multimedia player - * Copyright (C) 2005,2009 Audacious development team. + * Copyright (C) 2005-2010 Audacious development team * * Based on the xmms_sndfile input plugin: * Copyright (C) 2000, 2002 Erik de Castro Lopo @@ -60,31 +60,31 @@ static glong seek_value; static sf_count_t sf_get_filelen (void *user_data) { - return aud_vfs_fsize (user_data); + return vfs_fsize (user_data); } static sf_count_t sf_vseek (sf_count_t offset, int whence, void *user_data) { - return aud_vfs_fseek(user_data, offset, whence); + return vfs_fseek(user_data, offset, whence); } static sf_count_t sf_vread (void *ptr, sf_count_t count, void *user_data) { - return aud_vfs_fread(ptr, 1, count, user_data); + return vfs_fread(ptr, 1, count, user_data); } static sf_count_t sf_vwrite (const void *ptr, sf_count_t count, void *user_data) { - return aud_vfs_fwrite(ptr, 1, count, user_data); + return vfs_fwrite(ptr, 1, count, user_data); } static sf_count_t sf_tell (void *user_data) { - return aud_vfs_ftell(user_data); + return vfs_ftell(user_data); } static SF_VIRTUAL_IO sf_virtual_io = @@ -101,14 +101,14 @@ static SNDFILE * open_sndfile_from_uri(const gchar *filename, VFSFile **vfsfile, SF_INFO *sfinfo) { SNDFILE *snd_file = NULL; - *vfsfile = aud_vfs_fopen(filename, "rb"); + *vfsfile = vfs_fopen(filename, "rb"); if (*vfsfile == NULL) return NULL; snd_file = sf_open_virtual (&sf_virtual_io, SFM_READ, sfinfo, *vfsfile); if (snd_file == NULL) - aud_vfs_fclose(*vfsfile); + vfs_fclose(*vfsfile); return snd_file; } @@ -119,7 +119,7 @@ close_sndfile(SNDFILE *snd_file, VFSFile *vfsfile) if (snd_file != NULL) sf_close(snd_file); if (vfsfile != NULL) - aud_vfs_fclose(vfsfile); + vfs_fclose(vfsfile); } @@ -154,18 +154,18 @@ static Tuple * get_song_tuple (const gchar * filename) ti = tuple_new_from_filename (filename); if (sf_get_string(sndfile, SF_STR_TITLE) != NULL) - aud_tuple_associate_string(ti, FIELD_TITLE, NULL, sf_get_string(sndfile, SF_STR_TITLE)); + tuple_associate_string(ti, FIELD_TITLE, NULL, sf_get_string(sndfile, SF_STR_TITLE)); - aud_tuple_associate_string(ti, FIELD_ARTIST, NULL, sf_get_string(sndfile, SF_STR_ARTIST)); - aud_tuple_associate_string(ti, FIELD_COMMENT, NULL, sf_get_string(sndfile, SF_STR_COMMENT)); - aud_tuple_associate_string(ti, FIELD_DATE, NULL, sf_get_string(sndfile, SF_STR_DATE)); - aud_tuple_associate_string(ti, -1, "software", sf_get_string(sndfile, SF_STR_SOFTWARE)); + tuple_associate_string(ti, FIELD_ARTIST, NULL, sf_get_string(sndfile, SF_STR_ARTIST)); + tuple_associate_string(ti, FIELD_COMMENT, NULL, sf_get_string(sndfile, SF_STR_COMMENT)); + tuple_associate_string(ti, FIELD_DATE, NULL, sf_get_string(sndfile, SF_STR_DATE)); + tuple_associate_string(ti, -1, "software", sf_get_string(sndfile, SF_STR_SOFTWARE)); close_sndfile (sndfile, vfsfile); if (sfinfo.samplerate > 0) { - aud_tuple_associate_int(ti, FIELD_LENGTH, NULL, + tuple_associate_int(ti, FIELD_LENGTH, NULL, (gint) ceil (1000.0 * sfinfo.frames / sfinfo.samplerate)); } @@ -326,10 +326,10 @@ static Tuple * get_song_tuple (const gchar * filename) else codec = g_strdup_printf("%s", format); - aud_tuple_associate_string(ti, FIELD_CODEC, NULL, codec); + tuple_associate_string(ti, FIELD_CODEC, NULL, codec); g_free(codec); - aud_tuple_associate_string(ti, FIELD_QUALITY, NULL, lossy ? "lossy" : "lossless"); + tuple_associate_string(ti, FIELD_QUALITY, NULL, lossy ? "lossy" : "lossless"); return ti; } @@ -354,40 +354,38 @@ is_our_file (const gchar *filename) return TRUE; } -static void -play_start (InputPlayback *playback) +static gboolean play_start (InputPlayback * playback, const gchar * filename, + VFSFile * file, gint start_time, gint stop_time, gboolean pause) { - SNDFILE *sndfile = NULL; - SF_INFO sfinfo; - VFSFile *vfsfile = NULL; - gfloat * buffer; - gint size, samples; - gboolean paused = FALSE, stopped = FALSE; + if (file == NULL) + return FALSE; - sndfile = open_sndfile_from_uri(playback->filename, &vfsfile, &sfinfo); + SF_INFO sfinfo; + SNDFILE * sndfile = sf_open_virtual (& sf_virtual_io, SFM_READ, & sfinfo, + file); if (sndfile == NULL) - return; + return FALSE; if (! playback->output->open_audio (FMT_FLOAT, sfinfo.samplerate, sfinfo.channels)) { - close_sndfile (sndfile, vfsfile); - playback->error = TRUE; - return; + sf_close (sndfile); + return FALSE; } playback->set_params (playback, NULL, 0, 8 * sizeof (gfloat) * sfinfo.channels * sfinfo.samplerate, sfinfo.samplerate, sfinfo.channels); playback->playing = TRUE; - pause_flag = FALSE; - seek_value = -1; + pause_flag = pause; + seek_value = (start_time > 0) ? start_time : -1; playback->set_pb_ready(playback); - size = sfinfo.channels * (sfinfo.samplerate / 50); - buffer = g_malloc (sizeof (gfloat) * size); + gint size = sfinfo.channels * (sfinfo.samplerate / 50); + gfloat * buffer = g_malloc (sizeof (gfloat) * size); + gboolean paused = FALSE, stopped = FALSE; - while (1) + while (stop_time < 0 || playback->output->written_time () < stop_time) { g_mutex_lock (control_mutex); @@ -430,13 +428,12 @@ play_start (InputPlayback *playback) g_mutex_unlock (control_mutex); - samples = sf_read_float (sndfile, buffer, size); + gint samples = sf_read_float (sndfile, buffer, size); if (! samples) break; - playback->pass_audio (playback, FMT_FLOAT, sfinfo.channels, - sizeof (gfloat) * samples, buffer, NULL); + playback->output->write_audio (buffer, sizeof (gfloat) * samples); } sf_close (sndfile); @@ -452,8 +449,10 @@ play_start (InputPlayback *playback) g_mutex_lock (control_mutex); playback->playing = FALSE; - g_cond_signal (control_cond); + g_cond_signal (control_cond); /* wake up any waiting request */ g_mutex_unlock (control_mutex); + + return TRUE; } static void play_pause (InputPlayback * playback, gshort pause) @@ -556,7 +555,7 @@ static InputPlugin sndfile_ip = { .init = plugin_init, .about = plugin_about, .is_our_file = is_our_file, - .play_file = play_start, + .play = play_start, .stop = play_stop, .pause = play_pause, .cleanup = plugin_cleanup, diff --git a/src/sndstretch/sndstretch_xmms.c b/src/sndstretch/sndstretch_xmms.c index adf0dda..1aa5181 100644 --- a/src/sndstretch/sndstretch_xmms.c +++ b/src/sndstretch/sndstretch_xmms.c @@ -27,14 +27,15 @@ #include "FB_logo.xpm" #include "config.h" -#include <audacious/plugin.h> -#include <audacious/i18n.h> #include <gtk/gtk.h> #include <math.h> #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <audacious/configdb.h> +#include <audacious/i18n.h> +#include <audacious/plugin.h> #include <libaudcore/audio.h> #define SNDSTRETCH_VERSION_STRING "0.7" @@ -61,6 +62,7 @@ EffectPlugin sndstretch_ep = { .finish = sndstretch_finish, .decoder_to_output_time = sndstretch_decoder_to_output_time, .output_to_decoder_time = sndstretch_output_to_decoder_time, + .preserves_format = TRUE, }; EffectPlugin *sndstretch_eplist[] = { &sndstretch_ep, NULL }; diff --git a/src/song_change/song_change.c b/src/song_change/song_change.c index 402b73e..184762a 100644 --- a/src/song_change/song_change.c +++ b/src/song_change/song_change.c @@ -15,12 +15,15 @@ #include <string.h> -#include <audacious/plugin.h> -#include <audacious/auddrct.h> -#include "formatter.h" +#include <audacious/configdb.h> +#include <audacious/drct.h> #include <audacious/i18n.h> -#include <audacious/hook.h> +#include <audacious/plugin.h> #include <audacious/preferences.h> +#include <libaudcore/hook.h> +#include <libaudcore/audstrings.h> + +#include "formatter.h" static PluginPreferences preferences; @@ -104,10 +107,10 @@ do_command(char *cmd, const char *current_file, int pos) if (cmd && strlen(cmd) > 0) { formatter = formatter_new(); - str = audacious_drct_pl_get_title(pos); + str = aud_drct_pl_get_title(pos); if (str) { - temp = aud_escape_shell_chars(str); + temp = escape_shell_chars(str); formatter_associate(formatter, 's', temp); formatter_associate(formatter, 'n', temp); g_free(str); @@ -121,7 +124,7 @@ do_command(char *cmd, const char *current_file, int pos) if (current_file) { - temp = aud_escape_shell_chars(current_file); + temp = escape_shell_chars(current_file); formatter_associate(formatter, 'f', temp); g_free(temp); } @@ -129,7 +132,7 @@ do_command(char *cmd, const char *current_file, int pos) formatter_associate(formatter, 'f', ""); g_snprintf(numbuf, sizeof(numbuf), "%02d", pos + 1); formatter_associate(formatter, 't', numbuf); - length = audacious_drct_pl_get_time(pos); + length = aud_drct_pl_get_time(pos); if (length != -1) { g_snprintf(numbuf, sizeof(numbuf), "%d", length); @@ -137,14 +140,14 @@ do_command(char *cmd, const char *current_file, int pos) } else formatter_associate(formatter, 'l', "0"); - audacious_drct_get_info(&rate, &freq, &nch); + aud_drct_get_info(&rate, &freq, &nch); g_snprintf(numbuf, sizeof(numbuf), "%d", rate); formatter_associate(formatter, 'r', numbuf); g_snprintf(numbuf, sizeof(numbuf), "%d", freq); formatter_associate(formatter, 'F', numbuf); g_snprintf(numbuf, sizeof(numbuf), "%d", nch); formatter_associate(formatter, 'c', numbuf); - playing = audacious_drct_get_playing(); + playing = aud_drct_get_playing(); g_snprintf(numbuf, sizeof(numbuf), "%d", playing); formatter_associate(formatter, 'p', numbuf); shstring = formatter_format(formatter, cmd); @@ -177,10 +180,10 @@ static void read_config(void) static void cleanup(void) { - aud_hook_dissociate("playback begin", songchange_playback_begin); - aud_hook_dissociate("playback end", songchange_playback_end); - aud_hook_dissociate("playlist end reached", songchange_playlist_eof); -// aud_hook_dissociate( "playlist set info" , songchange_playback_ttc); + hook_dissociate("playback begin", songchange_playback_begin); + hook_dissociate("playback end", songchange_playback_end); + hook_dissociate("playlist end reached", songchange_playlist_eof); +// hook_dissociate( "playlist set info" , songchange_playback_ttc); if ( ttc_prevs != NULL ) { @@ -253,14 +256,14 @@ static void init(void) { read_config(); - aud_hook_associate("playback begin", songchange_playback_begin, NULL); - aud_hook_associate("playback end", songchange_playback_end, NULL); - aud_hook_associate("playlist end reached", songchange_playlist_eof, NULL); + hook_associate("playback begin", songchange_playback_begin, NULL); + hook_associate("playback end", songchange_playback_end, NULL); + hook_associate("playlist end reached", songchange_playlist_eof, NULL); ttc_prevs = g_malloc0(sizeof(songchange_playback_ttc_prevs_t)); ttc_prevs->title = NULL; ttc_prevs->filename = NULL; -// aud_hook_associate( "playlist set info" , songchange_playback_ttc , ttc_prevs ); +// hook_associate( "playlist set info" , songchange_playback_ttc , ttc_prevs ); } static void @@ -269,8 +272,8 @@ songchange_playback_begin(gpointer unused, gpointer unused2) int pos; char *current_file; - pos = audacious_drct_pl_get_pos(); - current_file = audacious_drct_pl_get_file(pos); + pos = aud_drct_pl_get_pos(); + current_file = aud_drct_pl_get_file(pos); do_command(cmd_line, current_file, pos); @@ -283,8 +286,8 @@ songchange_playback_end(gpointer unused, gpointer unused2) int pos; char *current_file; - pos = audacious_drct_pl_get_pos(); - current_file = audacious_drct_pl_get_file(pos); + pos = aud_drct_pl_get_pos(); + current_file = aud_drct_pl_get_file(pos); do_command(cmd_line_after, current_file, pos); @@ -308,8 +311,8 @@ songchange_playback_ttc(gpointer plentry_gp, gpointer prevs_gp) { if ( ( pl_entry->title != NULL ) && ( strcmp(pl_entry->title,prevs->title) ) ) { - int pos = audacious_drct_pl_get_pos(); - char *current_file = audacious_drct_pl_get_file(pos); + int pos = aud_drct_pl_get_pos(); + char *current_file = aud_drct_pl_get_file(pos); do_command(cmd_line_ttc, current_file, pos); g_free(current_file); g_free(prevs->title); @@ -345,8 +348,8 @@ songchange_playlist_eof(gpointer unused, gpointer unused2) gint pos; gchar *current_file; - pos = audacious_drct_pl_get_pos(); - current_file = audacious_drct_pl_get_file(pos); + pos = aud_drct_pl_get_pos(); + current_file = aud_drct_pl_get_file(pos); do_command(cmd_line_end, current_file, pos); @@ -482,8 +485,6 @@ static PluginPreferences preferences = { .imgurl = DATA_DIR "/images/plugins.png", .prefs = settings, .n_prefs = G_N_ELEMENTS(settings), - .type = PREFERENCES_PAGE, .init = configure_init, - /* TODO: .apply = configure_apply, */ .cleanup = configure_cleanup, }; diff --git a/src/statusicon/config.c b/src/statusicon/config.c index a2f0bb8..c37321c 100644 --- a/src/statusicon/config.c +++ b/src/statusicon/config.c @@ -20,6 +20,8 @@ * */ +#include <audacious/configdb.h> + #include "statusicon.h" si_cfg_t si_cfg; diff --git a/src/statusicon/statusicon.c b/src/statusicon/statusicon.c index 7941a9f..a2a1704 100644 --- a/src/statusicon/statusicon.c +++ b/src/statusicon/statusicon.c @@ -21,7 +21,10 @@ */ #include "statusicon.h" + +#include <audacious/drct.h> #include <audacious/i18n.h> +#include <libaudcore/hook.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> @@ -69,22 +72,22 @@ static gboolean si_cb_btpress(GtkStatusIcon * icon, GdkEventButton * event, gpoi case 1: { if (event->state & GDK_SHIFT_MASK) - audacious_drct_pl_next(); + aud_drct_pl_next(); else - aud_interface_toggle_visibility(); + hook_call ("interface toggle visibility", NULL); break; } case 2: { - audacious_drct_pause(); + aud_drct_pause(); break; } case 3: { if (event->state & GDK_SHIFT_MASK) - audacious_drct_pl_prev(); + aud_drct_pl_prev(); else { switch (si_cfg.rclick_menu) @@ -97,7 +100,7 @@ static gboolean si_cb_btpress(GtkStatusIcon * icon, GdkEventButton * event, gpoi break; case SI_CFG_RCLICK_MENU_AUD: default: - aud_hook_call("show main menu", event); + hook_call("show main menu", event); break; } break; @@ -272,7 +275,7 @@ static GtkWidget *si_smallmenu_create(void) gtk_menu_shell_append(GTK_MENU_SHELL(si_smenu), si_smenu_sep_item); gtk_widget_show(si_smenu_sep_item); si_smenu_quit_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL); - g_signal_connect_swapped(si_smenu_quit_item, "activate", G_CALLBACK(audacious_drct_quit), NULL); + g_signal_connect_swapped(si_smenu_quit_item, "activate", G_CALLBACK(aud_drct_quit), NULL); gtk_menu_shell_append(GTK_MENU_SHELL(si_smenu), si_smenu_quit_item); gtk_widget_show(si_smenu_quit_item); } @@ -320,7 +323,7 @@ static void si_enable(gboolean enable) si_smenu = si_smallmenu_create(); g_object_set_data(G_OBJECT(si_applet), "smenu", si_smenu); - aud_hook_associate("title change", si_popup_reshow, si_applet); + hook_associate("title change", si_popup_reshow, si_applet); } else if (si_applet != NULL) { @@ -330,7 +333,7 @@ static void si_enable(gboolean enable) g_object_unref(si_applet); si_applet = NULL; - aud_hook_dissociate("title change", si_popup_reshow); + hook_dissociate("title change", si_popup_reshow); } } diff --git a/src/statusicon/statusicon.h b/src/statusicon/statusicon.h index 4901a59..91efaae 100644 --- a/src/statusicon/statusicon.h +++ b/src/statusicon/statusicon.h @@ -26,7 +26,6 @@ #include "config.h" #include <glib.h> #include <audacious/plugin.h> -#include <audacious/auddrct.h> enum { SI_CFG_RCLICK_MENU_AUD, diff --git a/src/statusicon/util.c b/src/statusicon/util.c index 573ef5c..4668f1b 100644 --- a/src/statusicon/util.c +++ b/src/statusicon/util.c @@ -20,13 +20,16 @@ * */ +#include <audacious/drct.h> +#include <libaudcore/hook.h> + #include "statusicon.h" void si_volume_change(gint value) { gint vl, vr; - audacious_drct_get_volume(&vl, &vr); - audacious_drct_set_volume(CLAMP(vl + value, 0, 100), CLAMP(vr + value, 0, 100)); + aud_drct_get_volume(&vl, &vr); + aud_drct_set_volume(CLAMP(vl + value, 0, 100), CLAMP(vr + value, 0, 100)); } void si_playback_skip(gint numsong) @@ -55,27 +58,27 @@ void si_playback_ctrl(gpointer ctrl_code_gp) switch (ctrl_code) { case SI_PLAYBACK_CTRL_PREV: - audacious_drct_pl_prev(); + aud_drct_pl_prev(); break; case SI_PLAYBACK_CTRL_PLAY: - audacious_drct_play(); + aud_drct_play(); break; case SI_PLAYBACK_CTRL_PAUSE: - audacious_drct_pause(); + aud_drct_pause(); break; case SI_PLAYBACK_CTRL_STOP: - audacious_drct_stop(); + aud_drct_stop(); break; case SI_PLAYBACK_CTRL_NEXT: - audacious_drct_pl_next(); + aud_drct_pl_next(); break; case SI_PLAYBACK_CTRL_EJECT: - audacious_drct_eject(); + hook_call ("interface show filebrowser", GINT_TO_POINTER (TRUE)); break; } } diff --git a/src/stereo_plugin/stereo.c b/src/stereo_plugin/stereo.c index 1854a89..38861ef 100644 --- a/src/stereo_plugin/stereo.c +++ b/src/stereo_plugin/stereo.c @@ -4,6 +4,8 @@ #include "config.h" #include <gtk/gtk.h> + +#include <audacious/configdb.h> #include <audacious/i18n.h> #include <audacious/plugin.h> #include <libaudgui/libaudgui.h> @@ -32,6 +34,7 @@ EffectPlugin stereo_ep = .finish = stereo_finish, .decoder_to_output_time = stereo_decoder_to_output_time, .output_to_decoder_time = stereo_output_to_decoder_time, + .preserves_format = TRUE, }; static const char *about_text = N_("Extra Stereo Plugin\n\n" diff --git a/src/streambrowser/bookmarks.c b/src/streambrowser/bookmarks.c index 3340ef0..4406570 100644 --- a/src/streambrowser/bookmarks.c +++ b/src/streambrowser/bookmarks.c @@ -19,6 +19,8 @@ #include <string.h> #include <glib.h> + +#include <audacious/debug.h> #include <audacious/plugin.h> #include "streambrowser.h" diff --git a/src/streambrowser/shoutcast.c b/src/streambrowser/shoutcast.c index 2babbb1..6d690d1 100644 --- a/src/streambrowser/shoutcast.c +++ b/src/streambrowser/shoutcast.c @@ -21,6 +21,8 @@ #include <glib.h> #include <libxml/parser.h> #include <libxml/tree.h> + +#include <audacious/debug.h> #include <audacious/plugin.h> #include "streambrowser.h" diff --git a/src/streambrowser/streambrowser.c b/src/streambrowser/streambrowser.c index 283fba8..5ff167a 100644 --- a/src/streambrowser/streambrowser.c +++ b/src/streambrowser/streambrowser.c @@ -20,8 +20,12 @@ #include <stdlib.h> #include <gtk/gtk.h> #include <glib.h> + +#include <audacious/configdb.h> +#include <audacious/debug.h> +#include <audacious/misc.h> +#include <audacious/playlist.h> #include <audacious/plugin.h> -#include <audacious/ui_plugin_menu.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> @@ -100,17 +104,17 @@ void failure (const char *fmt, ...) gboolean fetch_remote_to_local_file (gchar * remote_url, gchar * local_url) { - VFSFile *remote_file = aud_vfs_fopen (remote_url, "r"); + VFSFile *remote_file = vfs_fopen (remote_url, "r"); if (remote_file == NULL) { failure ("failed to fetch file '%s'\n", remote_url); return FALSE; } - VFSFile *local_file = aud_vfs_fopen (local_url, "w"); + VFSFile *local_file = vfs_fopen (local_url, "w"); if (local_file == NULL) { - aud_vfs_fclose (remote_file); + vfs_fclose (remote_file); failure ("failed to create local file '%s'\n", local_file); return FALSE; @@ -118,28 +122,28 @@ gboolean fetch_remote_to_local_file (gchar * remote_url, gchar * local_url) unsigned char buff[DEF_BUFFER_SIZE]; int size; - while (!aud_vfs_feof (remote_file)) + while (!vfs_feof (remote_file)) { - size = aud_vfs_fread (buff, 1, DEF_BUFFER_SIZE, remote_file); + size = vfs_fread (buff, 1, DEF_BUFFER_SIZE, remote_file); - // i don't know why aud_vfs_feof() doesn't ever return TRUE + // i don't know why vfs_feof() doesn't ever return TRUE // so this is a workaround to properly end the loop if (size == 0) break; - size = aud_vfs_fwrite (buff, 1, size, local_file); + size = vfs_fwrite (buff, 1, size, local_file); if (size == 0) { - aud_vfs_fclose (local_file); - aud_vfs_fclose (remote_file); + vfs_fclose (local_file); + vfs_fclose (remote_file); failure ("failed to write to local file '%s'\n", local_file); return FALSE; } } - aud_vfs_fclose (local_file); - aud_vfs_fclose (remote_file); + vfs_fclose (local_file); + vfs_fclose (remote_file); return TRUE; } @@ -357,7 +361,7 @@ static void gui_init () gtk_widget_show (playlist_menu_item); g_signal_connect (G_OBJECT (playlist_menu_item), "activate", G_CALLBACK (on_plugin_services_menu_item_click), NULL); - audacious_menu_plugin_item_add (AUDACIOUS_MENU_PLAYLIST_RCLICK, + aud_menu_plugin_item_add (AUDACIOUS_MENU_PLAYLIST_RCLICK, playlist_menu_item); main_menu_item = gtk_image_menu_item_new_with_label (_("Streambrowser")); @@ -367,7 +371,7 @@ static void gui_init () gtk_widget_show (main_menu_item); g_signal_connect (G_OBJECT (main_menu_item), "activate", G_CALLBACK (on_plugin_services_menu_item_click), NULL); - audacious_menu_plugin_item_add (AUDACIOUS_MENU_MAIN, main_menu_item); + aud_menu_plugin_item_add (AUDACIOUS_MENU_MAIN, main_menu_item); /* main streambrowser window */ streambrowser_win_init (); @@ -383,9 +387,9 @@ static void gui_init () static void gui_done () { /* the plugin services menu */ - audacious_menu_plugin_item_remove (AUDACIOUS_MENU_PLAYLIST_RCLICK, + aud_menu_plugin_item_remove (AUDACIOUS_MENU_PLAYLIST_RCLICK, playlist_menu_item); - audacious_menu_plugin_item_remove (AUDACIOUS_MENU_MAIN, main_menu_item); + aud_menu_plugin_item_remove (AUDACIOUS_MENU_MAIN, main_menu_item); /* main streambrowser window */ streambrowser_win_hide (); @@ -710,7 +714,7 @@ static gpointer update_thread_core (gpointer user_data) static void streaminfo_add_to_playlist (streaminfo_t * streaminfo) { gint playlist = aud_playlist_get_active (); - gchar * unix_name = g_build_filename (audacious_get_localdir (), + gchar * unix_name = g_build_filename (aud_util_get_localdir (), PLAYLIST_TEMP_FILE, NULL); gchar * uri_name = g_filename_to_uri (unix_name, NULL, NULL); diff --git a/src/streambrowser/xiph.c b/src/streambrowser/xiph.c index 15da77c..028f8ad 100644 --- a/src/streambrowser/xiph.c +++ b/src/streambrowser/xiph.c @@ -21,7 +21,9 @@ #include <glib.h> #include <libxml/parser.h> #include <libxml/tree.h> -#include <audacious/plugin.h> + +#include <audacious/debug.h> +#include <audacious/misc.h> #include "streambrowser.h" #include "xiph.h" @@ -138,7 +140,7 @@ gboolean xiph_category_fetch (streamdir_t * streamdir, category_t * category) } } - /* if the requested category is the last one in the list ("other"), + /* if the requested category is the last one in the list ("other"), we fill it with all the entries that don't match the rest of categories */ if (xiph_category == &xiph_categories[xiph_category_count - 1]) { @@ -190,7 +192,7 @@ streamdir_t *xiph_streamdir_fetch (void) static void refresh_streamdir (void) { - gchar * unix_name = g_build_filename (audacious_get_localdir (), + gchar * unix_name = g_build_filename (aud_util_get_localdir (), XIPH_TEMP_FILENAME, NULL); gchar * uri_name = g_filename_to_uri (unix_name, NULL, NULL); @@ -216,7 +218,7 @@ static void refresh_streamdir (void) XIPH_STREAMDIR_URL, uri_name); xmlDoc * doc = xmlReadFile (uri_name, NULL, 0); - + if (doc == NULL) { failure ("xiph: failed to read stream directory file\n"); diff --git a/src/sun/audio.c b/src/sun/audio.c index 5363515..ab45566 100644 --- a/src/sun/audio.c +++ b/src/sun/audio.c @@ -24,9 +24,9 @@ #include "resample.h" static int sun_bps(int, int, int); -static int sun_format(AFormat); +static int sun_format(gint); -static void sun_setformat(AFormat, int, int); +static void sun_setformat(gint, int, int); static void sun_setparams(void); static void *sun_loop(void *); static int sun_downsample(gpointer, guint, guint, guint); @@ -46,7 +46,7 @@ static guint64 written; /* * The format of the data from the input plugin - * This will never change during a song. + * This will never change during a song. */ struct sun_format input; @@ -83,7 +83,7 @@ static int sun_bps(int sunfmt, int rate, int nch) return (bitrate); } -static int sun_format(AFormat fmt) +static int sun_format(gint fmt) { switch (fmt) { @@ -115,10 +115,10 @@ static int sun_format(AFormat fmt) return -1; } -static void sun_setformat(AFormat fmt, int rate, int nch) +static void sun_setformat(gint fmt, int rate, int nch) { int sun; - + sun = sun_format(fmt); effect.format.sun = sun; @@ -465,7 +465,7 @@ static void* sun_loop(void *arg) pthread_exit(NULL); } -int sun_open(AFormat fmt, int rate, int nch) +int sun_open(gint fmt, int rate, int nch) { audio_info_t info; diff --git a/src/sun/sun.h b/src/sun/sun.h index e6f6b33..d835778 100644 --- a/src/sun/sun.h +++ b/src/sun/sun.h @@ -82,7 +82,7 @@ struct sun_format { char name[16]; union { - AFormat xmms; + gint xmms; gint sun; } format; int frequency; @@ -136,7 +136,7 @@ void sun_about(void); void sun_configure(void); void sun_cleanup(void); -gint sun_open(AFormat, int, int); +gint sun_open(gint, int, int); void sun_write(void *, int); void sun_close(void); void sun_flush(int); diff --git a/src/tonegen/tonegen.c b/src/tonegen/tonegen.c index 4e102c1..86d25f3 100644 --- a/src/tonegen/tonegen.c +++ b/src/tonegen/tonegen.c @@ -17,8 +17,10 @@ */ #include "config.h" -#include <audacious/plugin.h> + #include <audacious/i18n.h> +#include <audacious/misc.h> +#include <audacious/plugin.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> @@ -192,7 +194,7 @@ static void tone_pause(InputPlayback * playback, gshort paused) static Tuple *tone_get_song_tuple(const gchar * filename) { - Tuple *tuple = aud_tuple_new_from_filename(filename); + Tuple *tuple = tuple_new_from_filename(filename); gchar *tmp; if (tuple == NULL) @@ -200,7 +202,7 @@ static Tuple *tone_get_song_tuple(const gchar * filename) if ((tmp = tone_title(filename)) != NULL) { - aud_tuple_associate_string(tuple, FIELD_TITLE, NULL, tmp); + tuple_associate_string(tuple, FIELD_TITLE, NULL, tmp); g_free(tmp); } diff --git a/src/unix-io/unix-io.c b/src/unix-io/unix-io.c index 5e56b8d..b7c9ae0 100644 --- a/src/unix-io/unix-io.c +++ b/src/unix-io/unix-io.c @@ -28,6 +28,7 @@ #include <glib.h> +#include <audacious/debug.h> #include <audacious/plugin.h> #define error(...) fprintf (stderr, "unix-io: " __VA_ARGS__) @@ -269,7 +270,7 @@ static VFSConstructor constructor = static void unix_init (void) { - aud_vfs_register_transport (& constructor); + vfs_register_transport (& constructor); } DECLARE_PLUGIN (unix_io, unix_init, NULL) diff --git a/src/usf/Makefile b/src/usf/Makefile new file mode 100644 index 0000000..a17bdb6 --- /dev/null +++ b/src/usf/Makefile @@ -0,0 +1,43 @@ +PLUGIN = usf${PLUGIN_SUFFIX} + +SRCS = audio.c \ + audio_hle_main.c \ + audio_ucode1.c \ + audio_ucode2.c \ + audio_ucode3.c \ + audio_ucode3mp3.c \ + cpu.c \ + dma.c \ + exception.c \ + interpreter_cpu.c \ + interpreter_ops.c \ + main.c \ + memory.c \ + pif.c \ + psftag.c \ + recompiler_cpu.c \ + recompiler_fpu_ops.c \ + recompiler_ops.c \ + registers.c \ + rsp.c \ + rsp_interpreter_cpu.c \ + rsp_mmx.c \ + rsp_recompiler_analysis.c \ + rsp_recompiler_cpu.c \ + rsp_recompiler_ops.c \ + rsp_sse.c \ + rsp_x86.c \ + tlb.c \ + usf.c \ + x86.c \ + x86_fpu.c + +include ../../buildsys.mk +include ../../extra.mk + +plugindir := ${plugindir}/${INPUT_PLUGIN_DIR} + +CFLAGS += ${PLUGIN_CFLAGS} -O0 +CXXFLAGS += ${PLUGIN_CFLAGS} -O0 +CPPFLAGS += ${PLUGIN_CPPFLAGS} ${MOWGLI_CFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} -I../.. -Ispu/ -I. +LIBS += ${GTK_LIBS} ${GLIB_LIBS} ${MOWGLI_LIBS} -lz diff --git a/src/usf/audio.c b/src/usf/audio.c new file mode 100644 index 0000000..403009a --- /dev/null +++ b/src/usf/audio.c @@ -0,0 +1,112 @@ +#include "usf.h"
+#include "audio_hle.h"
+#include "memory.h"
+#include "audio.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <linux/soundcard.h>
+
+#include <audacious/plugin.h>
+
+#include <unistd.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+extern InputPlayback * pcontext;
+int32_t SampleRate = 0;
+static int16_t samplebuf[16384];
+
+void OpenSound(void)
+{
+ if (pcontext->output->open_audio(FMT_S16_NE, SampleRate, 2) == 0) {
+ cpu_running = 0;
+ printf("Fail Starting audio\n");
+ g_thread_exit(NULL);
+ } else {
+ }
+}
+
+void AddBuffer(unsigned char *buf, unsigned int length) {
+ int32_t i = 0, out = 0;
+ double vol = 1.0;
+
+ if(!cpu_running)
+ return;
+
+ if(is_seeking) {
+ play_time += (((double)(length >> 2) / (double)SampleRate) * 1000.0);
+ if(play_time > (double)seek_time) {
+ is_seeking = 0;
+ }
+ return;
+ }
+
+ if(play_time > track_time) {
+ vol = 1.0f - (((double)play_time - (double)track_time) / (double)fade_time);
+ }
+
+ for(out = i = 0; i < (length >> 1); i+=2)
+ {
+ samplebuf[out++] = (int16_t)(vol * (double)((int16_t*)buf)[i+1]);
+ samplebuf[out++] = (int16_t)(vol * (double)((int16_t*)buf)[i]);
+ }
+
+ pcontext->playing = play_time < (track_time + fade_time);
+ pcontext->eof = play_time >= (track_time + fade_time);
+
+ play_time += (((double)(length >> 2) / (double)SampleRate) * 1000.0);
+
+ pcontext->output->write_audio (samplebuf, length);
+
+ if(play_time > (track_time + fade_time))
+ {
+ cpu_running = 0;
+ }
+
+}
+
+void AiLenChanged(void) {
+ int32_t length = 0;
+ uint32_t address = (AI_DRAM_ADDR_REG & 0x00FFFFF8);
+
+ length = AI_LEN_REG & 0x3FFF8;
+
+ while(is_paused && !is_seeking && cpu_running)
+ g_usleep(10000);
+
+
+ AddBuffer(RDRAM+address, length);
+
+ if(length && !(AI_STATUS_REG&0x80000000)) {
+ const float VSyncTiming = 789000.0f;
+ double BytesPerSecond = 48681812.0 / (AI_DACRATE_REG + 1) * 4;
+ double CountsPerSecond = (double)((((double)VSyncTiming) * (double)60.0)) * 2.0;
+ double CountsPerByte = (double)CountsPerSecond / (double)BytesPerSecond;
+ unsigned int IntScheduled = (unsigned int)((double)AI_LEN_REG * CountsPerByte);
+
+ ChangeTimer(AiTimer,IntScheduled);
+ }
+
+ if(enableFIFOfull) {
+ if(AI_STATUS_REG&0x40000000)
+ AI_STATUS_REG|=0x80000000;
+ }
+
+ AI_STATUS_REG|=0x40000000;
+
+}
+
+unsigned int AiReadLength(void) {
+ AI_LEN_REG = 0;
+ return AI_LEN_REG;
+}
+
+void AiDacrateChanged(unsigned int value) {
+ AI_DACRATE_REG = value;
+ SampleRate = 48681812 / (AI_DACRATE_REG + 1);
+
+}
diff --git a/src/usf/audio.h b/src/usf/audio.h new file mode 100644 index 0000000..e5dc94a --- /dev/null +++ b/src/usf/audio.h @@ -0,0 +1,13 @@ +#ifndef _AUDIO_H_
+#define _AUDIO_H_
+
+#include "usf.h"
+#include "cpu.h"
+#include "memory.h"
+
+uint32_t AiReadLength(void);
+void AiLenChanged(void);
+void AiDacrateChanged(uint32_t value);
+void OpenSound(void);
+
+#endif
diff --git a/src/usf/audio_hle.h b/src/usf/audio_hle.h new file mode 100644 index 0000000..2f0e3cb --- /dev/null +++ b/src/usf/audio_hle.h @@ -0,0 +1,140 @@ +/**
+ * Mupen64 hle rsp - hle.c
+ * Copyright (C) 2002 Hacktarux
+ *
+ * Mupen64 homepage: http://mupen64.emulation64.com
+ * email address: hacktarux@yahoo.fr
+ *
+ * If you want to contribute to the project please contact
+ * me first (maybe someone is already making what you are
+ * planning to do).
+ *
+ *
+ * This program is free software; you can redistribute it and/
+ * or modify it under the terms of the GNU General Public Li-
+ * cence as published by the Free Software Foundation; either
+ * version 2 of the Licence, or any later version.
+ *
+ * This program is distributed in the hope that it will be use-
+ * ful, but WITHOUT ANY WARRANTY; without even the implied war-
+ * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public Licence for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * Licence along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+**/
+
+#ifndef HLE_H
+#define HLE_H
+
+#ifndef _BIG_ENDIAN
+#define S 0
+#define S8 0
+#else
+#define S 1
+#define S8 3
+#endif
+
+// types
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned long long u64;
+
+typedef signed char s8;
+typedef signed short s16;
+typedef signed int s32;
+typedef signed long long s64;
+
+/*
+ * Audio flags
+ */
+
+#define A_INIT 0x01
+#define A_CONTINUE 0x00
+#define A_LOOP 0x02
+#define A_OUT 0x02
+#define A_LEFT 0x02
+#define A_RIGHT 0x00
+#define A_VOL 0x04
+#define A_RATE 0x00
+#define A_AUX 0x08
+#define A_NOAUX 0x00
+#define A_MAIN 0x00
+#define A_MIX 0x10
+
+typedef struct
+{
+ unsigned int type;
+ unsigned int flags;
+
+ unsigned int ucode_boot;
+ unsigned int ucode_boot_size;
+
+ unsigned int ucode;
+ unsigned int ucode_size;
+
+ unsigned int ucode_data;
+ unsigned int ucode_data_size;
+
+ unsigned int dram_stack;
+ unsigned int dram_stack_size;
+
+ unsigned int output_buff;
+ unsigned int output_buff_size;
+
+ unsigned int data_ptr;
+ unsigned int data_size;
+
+ unsigned int yield_data_ptr;
+ unsigned int yield_data_size;
+} OSTask_t;
+
+extern u32 inst1, inst2;
+//extern u16 AudioInBuffer, AudioOutBuffer, AudioCount;
+//extern u16 AudioAuxA, AudioAuxC, AudioAuxE;
+extern u32 loopval; // Value set by A_SETLOOP : Possible conflict with SETVOLUME???
+//extern u32 UCData, UDataLen;
+
+extern u32 SEGMENTS[0x10]; // 0x0320
+// T8 = 0x360
+extern u16 AudioInBuffer; // 0x0000(T8)
+extern u16 AudioOutBuffer; // 0x0002(T8)
+extern u16 AudioCount; // 0x0004(T8)
+extern s16 Vol_Left; // 0x0006(T8)
+extern s16 Vol_Right; // 0x0008(T8)
+extern u16 AudioAuxA; // 0x000A(T8)
+extern u16 AudioAuxC; // 0x000C(T8)
+extern u16 AudioAuxE; // 0x000E(T8)
+extern u32 loopval; // 0x0010(T8) // Value set by A_SETLOOP : Possible conflict with SETVOLUME???
+extern s16 VolTrg_Left; // 0x0010(T8)
+extern s32 VolRamp_Left; // m_LeftVolTarget
+//u16 VolRate_Left; // m_LeftVolRate
+extern s16 VolTrg_Right; // m_RightVol
+extern s32 VolRamp_Right; // m_RightVolTarget
+//u16 VolRate_Right; // m_RightVolRate
+extern s16 Env_Dry; // 0x001C(T8)
+extern s16 Env_Wet; // 0x001E(T8)
+
+
+extern u8 BufferSpace[0x10000];
+
+extern short hleMixerWorkArea[256];
+extern u16 adpcmtable[0x88];
+extern int firstHLE, goldeneye;
+
+
+extern int audio_ucode(OSTask_t *task);
+//extern unsigned char *RDRAM,*DMEM, *IMEM, *ROM;
+//extern unsigned int N64MEM_Pages[0x80];
+#include "usf.h"
+#include "memory.h"
+#include "cpu.h"
+
+
+
+
+#endif
diff --git a/src/usf/audio_hle_main.c b/src/usf/audio_hle_main.c new file mode 100644 index 0000000..e7c25f2 --- /dev/null +++ b/src/usf/audio_hle_main.c @@ -0,0 +1,83 @@ +
+#include "usf.h"
+#include "audio_hle.h"
+#include "memory.h"
+#include "audio.h"
+// "Mupen64 HLE RSP plugin v0.2 with Azimers code by Hacktarux"
+
+
+static int audio_ucode_detect ( OSTask_t *task )
+{
+
+ if ( (*(uint8_t*) ( N64MEM + task->ucode_data )) != 0x1 )
+ {
+ if ( (*(uint8_t*) ( N64MEM + task->ucode_data )) == 0xF )
+ return 4;
+ else
+ return 3;
+ }
+ else
+ {
+ if ( (*(uint32_t*) (N64MEM + task->ucode_data + 0x30 )) == 0xF0000F00 ) {
+ if ((*(uint32_t*) (N64MEM + task->ucode_data + 0x28 )) == 0x1dc8138c)
+ return 5; //goldeneye
+ else
+ return 1;
+
+ }
+ else
+ return 2;
+ }
+}
+
+extern void ( *ABI1[0x20] ) ();
+extern void ( *ABI2[0x20] ) ();
+extern void ( *ABI3[0x20] ) ();
+
+void ( *ABI[0x20] ) ();
+
+u32 inst1, inst2;
+
+int audio_ucode ( OSTask_t *task )
+{
+
+ unsigned int i;
+
+ goldeneye = 0;
+
+ switch ( audio_ucode_detect ( task ) )
+ {
+ case 1: // mario ucode
+ memcpy ( ABI, ABI1, sizeof ( ABI[0] ) *0x20 );
+ //cprintf("Ucode1\n");
+ break;
+ case 2: // banjo kazooie ucode
+ memcpy ( ABI, ABI2, sizeof ( ABI[0] ) *0x20 );
+ //cprintf("Ucode2\n");
+ break;
+ case 3: // zelda ucode
+ memcpy ( ABI, ABI3, sizeof ( ABI[0] ) *0x20 );
+ //cprintf("Ucode3\n");
+ break;
+ case 5:
+ goldeneye = 1;
+ memcpy ( ABI, ABI1, sizeof ( ABI[0] ) *0x20 );
+ break;
+ default:
+ {
+
+ return -1;
+ }
+ }
+
+ for ( i = 0; i < ( task->data_size/4 ); i += 2 )
+ {
+ inst1 = (*(uint32_t*) ( N64MEM + task->data_ptr + ( i*4 ) ));
+ inst2 = (*(uint32_t*) ( N64MEM + task->data_ptr + ( ( i+1 ) *4 ) ));
+ //printf("%x\t%x\n",inst1 >> 24,inst1);
+ ABI[inst1 >> 24]();
+
+ }
+
+ return 0;
+}
diff --git a/src/usf/audio_ucode1.c b/src/usf/audio_ucode1.c new file mode 100644 index 0000000..7f2f1e1 --- /dev/null +++ b/src/usf/audio_ucode1.c @@ -0,0 +1,755 @@ +#include "usf.h"
+#include "audio_hle.h"
+
+
+static void SPNOOP () {
+ //MessageBox (NULL, "Unknown Audio Command in ABI 1", "Audio HLE Error", MB_OK);
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+u32 SEGMENTS[0x10]; // 0x0320
+// T8 = 0x360
+u16 AudioInBuffer; // 0x0000(T8)
+u16 AudioOutBuffer; // 0x0002(T8)
+u16 AudioCount; // 0x0004(T8)
+s16 Vol_Left; // 0x0006(T8)
+s16 Vol_Right; // 0x0008(T8)
+u16 AudioAuxA; // 0x000A(T8)
+u16 AudioAuxC; // 0x000C(T8)
+u16 AudioAuxE; // 0x000E(T8)
+u32 loopval; // 0x0010(T8) // Value set by A_SETLOOP : Possible conflict with SETVOLUME???
+s16 VolTrg_Left; // 0x0010(T8)
+s32 VolRamp_Left; // m_LeftVolTarget
+//u16 VolRate_Left; // m_LeftVolRate
+s16 VolTrg_Right; // m_RightVol
+s32 VolRamp_Right; // m_RightVolTarget
+//u16 VolRate_Right; // m_RightVolRate
+s16 Env_Dry; // 0x001C(T8)
+s16 Env_Wet; // 0x001E(T8)
+int firstHLE = 0, goldeneye = 0;
+
+u8 BufferSpace[0x10000];
+
+short hleMixerWorkArea[256];
+u16 adpcmtable[0x88];
+
+
+u16 ResampleLUT [0x200] = {
+ 0x0C39, 0x66AD, 0x0D46, 0xFFDF, 0x0B39, 0x6696, 0x0E5F, 0xFFD8,
+ 0x0A44, 0x6669, 0x0F83, 0xFFD0, 0x095A, 0x6626, 0x10B4, 0xFFC8,
+ 0x087D, 0x65CD, 0x11F0, 0xFFBF, 0x07AB, 0x655E, 0x1338, 0xFFB6,
+ 0x06E4, 0x64D9, 0x148C, 0xFFAC, 0x0628, 0x643F, 0x15EB, 0xFFA1,
+ 0x0577, 0x638F, 0x1756, 0xFF96, 0x04D1, 0x62CB, 0x18CB, 0xFF8A,
+ 0x0435, 0x61F3, 0x1A4C, 0xFF7E, 0x03A4, 0x6106, 0x1BD7, 0xFF71,
+ 0x031C, 0x6007, 0x1D6C, 0xFF64, 0x029F, 0x5EF5, 0x1F0B, 0xFF56,
+ 0x022A, 0x5DD0, 0x20B3, 0xFF48, 0x01BE, 0x5C9A, 0x2264, 0xFF3A,
+ 0x015B, 0x5B53, 0x241E, 0xFF2C, 0x0101, 0x59FC, 0x25E0, 0xFF1E,
+ 0x00AE, 0x5896, 0x27A9, 0xFF10, 0x0063, 0x5720, 0x297A, 0xFF02,
+ 0x001F, 0x559D, 0x2B50, 0xFEF4, 0xFFE2, 0x540D, 0x2D2C, 0xFEE8,
+ 0xFFAC, 0x5270, 0x2F0D, 0xFEDB, 0xFF7C, 0x50C7, 0x30F3, 0xFED0,
+ 0xFF53, 0x4F14, 0x32DC, 0xFEC6, 0xFF2E, 0x4D57, 0x34C8, 0xFEBD,
+ 0xFF0F, 0x4B91, 0x36B6, 0xFEB6, 0xFEF5, 0x49C2, 0x38A5, 0xFEB0,
+ 0xFEDF, 0x47ED, 0x3A95, 0xFEAC, 0xFECE, 0x4611, 0x3C85, 0xFEAB,
+ 0xFEC0, 0x4430, 0x3E74, 0xFEAC, 0xFEB6, 0x424A, 0x4060, 0xFEAF,
+ 0xFEAF, 0x4060, 0x424A, 0xFEB6, 0xFEAC, 0x3E74, 0x4430, 0xFEC0,
+ 0xFEAB, 0x3C85, 0x4611, 0xFECE, 0xFEAC, 0x3A95, 0x47ED, 0xFEDF,
+ 0xFEB0, 0x38A5, 0x49C2, 0xFEF5, 0xFEB6, 0x36B6, 0x4B91, 0xFF0F,
+ 0xFEBD, 0x34C8, 0x4D57, 0xFF2E, 0xFEC6, 0x32DC, 0x4F14, 0xFF53,
+ 0xFED0, 0x30F3, 0x50C7, 0xFF7C, 0xFEDB, 0x2F0D, 0x5270, 0xFFAC,
+ 0xFEE8, 0x2D2C, 0x540D, 0xFFE2, 0xFEF4, 0x2B50, 0x559D, 0x001F,
+ 0xFF02, 0x297A, 0x5720, 0x0063, 0xFF10, 0x27A9, 0x5896, 0x00AE,
+ 0xFF1E, 0x25E0, 0x59FC, 0x0101, 0xFF2C, 0x241E, 0x5B53, 0x015B,
+ 0xFF3A, 0x2264, 0x5C9A, 0x01BE, 0xFF48, 0x20B3, 0x5DD0, 0x022A,
+ 0xFF56, 0x1F0B, 0x5EF5, 0x029F, 0xFF64, 0x1D6C, 0x6007, 0x031C,
+ 0xFF71, 0x1BD7, 0x6106, 0x03A4, 0xFF7E, 0x1A4C, 0x61F3, 0x0435,
+ 0xFF8A, 0x18CB, 0x62CB, 0x04D1, 0xFF96, 0x1756, 0x638F, 0x0577,
+ 0xFFA1, 0x15EB, 0x643F, 0x0628, 0xFFAC, 0x148C, 0x64D9, 0x06E4,
+ 0xFFB6, 0x1338, 0x655E, 0x07AB, 0xFFBF, 0x11F0, 0x65CD, 0x087D,
+ 0xFFC8, 0x10B4, 0x6626, 0x095A, 0xFFD0, 0x0F83, 0x6669, 0x0A44,
+ 0xFFD8, 0x0E5F, 0x6696, 0x0B39, 0xFFDF, 0x0D46, 0x66AD, 0x0C39
+};
+#ifdef __cplusplus
+}
+#endif
+
+
+static void CLEARBUFF () {
+ u32 addr = (u32)(inst1 & 0xffff);
+ u32 count = (u32)(inst2 & 0xffff);
+ addr &= 0xFFFC;
+ memset(BufferSpace+addr, 0, (count+3)&0xFFFC);
+}
+
+
+static void ENVMIXER () {
+
+ u8 flags = (u8)((inst1 >> 16) & 0xff);
+ u32 addy = (inst2 & 0xFFFFFF);
+ short *inp=(short *)(BufferSpace+AudioInBuffer);
+ short *out=(short *)(BufferSpace+AudioOutBuffer);
+ short *aux1=(short *)(BufferSpace+AudioAuxA);
+ short *aux2=(short *)(BufferSpace+AudioAuxC);
+ short *aux3=(short *)(BufferSpace+AudioAuxE);
+ s32 MainR;
+ s32 MainL;
+ s32 AuxR;
+ s32 AuxL;
+ int i1,o1,a1,a2=0,a3=0;
+ unsigned short AuxIncRate=1;
+ short zero[8];
+ s32 LVol, RVol;
+ s32 LAcc, RAcc;
+ s32 LTrg, RTrg;
+ s16 Wet, Dry;
+ u32 ptr = 0;
+ s32 RRamp, LRamp;
+ s32 LAdderStart, RAdderStart, LAdderEnd, RAdderEnd;
+ s32 oMainR, oMainL, oAuxR, oAuxL;
+ int x = 0, y = 0;
+
+ memset(zero,0,16);
+
+ if (flags & A_INIT) {
+
+ if(goldeneye) {
+ //Vol_Left = Vol_Right;
+ // VolTrg_Left = VolTrg_Right;
+ Vol_Left = (Vol_Right >> 8) << 8;
+ VolTrg_Left = (VolTrg_Right >> 8) << 8;
+ //Vol_Right = (Vol_Right & 0xff) << 8;
+ //VolTrg_Right = (VolTrg_Right & 0xff) << 8;
+ }
+
+ LVol = ((Vol_Left * (s32)VolRamp_Left));
+ RVol = ((Vol_Right * (s32)VolRamp_Right));
+
+ Wet = (s16)Env_Wet;
+ Dry = (s16)Env_Dry; // Save Wet/Dry values
+ LTrg = (VolTrg_Left << 16);
+ RTrg = (VolTrg_Right << 16); // Save Current Left/Right Targets
+ LAdderStart = Vol_Left << 16;
+ RAdderStart = Vol_Right << 16;
+ LAdderEnd = LVol ;
+ RAdderEnd = RVol ;
+ RRamp = VolRamp_Right;
+ LRamp = VolRamp_Left;
+ } else {
+ // Load LVol, RVol, LAcc, and RAcc (all 32bit)
+ // Load Wet, Dry, LTrg, RTrg
+ memcpy((u8*)hleMixerWorkArea, (u8*)RDRAM+addy, 80);
+ Wet = *(s16 *)(hleMixerWorkArea + 0); // 0-1
+ Dry = *(s16 *)(hleMixerWorkArea + 2); // 2-3
+ LTrg = *(s32 *)(hleMixerWorkArea + 4); // 4-5
+ RTrg = *(s32 *)(hleMixerWorkArea + 6); // 6-7
+ LRamp= *(s32 *)(hleMixerWorkArea + 8); // 8-9 (hleMixerWorkArea is a 16bit pointer)
+ RRamp= *(s32 *)(hleMixerWorkArea + 10); // 10-11
+ LAdderEnd = *(s32 *)(hleMixerWorkArea + 12); // 12-13
+ RAdderEnd = *(s32 *)(hleMixerWorkArea + 14); // 14-15
+ LAdderStart = *(s32 *)(hleMixerWorkArea + 16); // 12-13
+ RAdderStart = *(s32 *)(hleMixerWorkArea + 18); // 14-15
+ }
+
+ if(!(flags&A_AUX)) {
+ AuxIncRate=0;
+ aux2=aux3=zero;
+ }
+
+ oMainL = (Dry * (LTrg>>16) + 0x4000) >> 15;
+ oAuxL = (Wet * (LTrg>>16) + 0x4000) >> 15;
+ oMainR = (Dry * (RTrg>>16) + 0x4000) >> 15;
+ oAuxR = (Wet * (RTrg>>16) + 0x4000) >> 15;
+
+ for (y = 0; y < AudioCount; y += 0x10) {
+
+ if (LAdderStart != LTrg) {
+ LAcc = LAdderStart;
+ LVol = (LAdderEnd - LAdderStart) >> 3;
+ LAdderEnd = ((s64)LAdderEnd * (s64)LRamp) >> 16;
+ LAdderStart = ((s64)LAcc * (s64)LRamp) >> 16;
+ } else {
+ LAcc = LTrg;
+ LVol = 0;
+ }
+
+ if (RAdderStart != RTrg) {
+ RAcc = RAdderStart;
+ RVol = (RAdderEnd - RAdderStart) >> 3;
+ RAdderEnd = ((s64)RAdderEnd * (s64)RRamp) >> 16;
+ RAdderStart = ((s64)RAcc * (s64)RRamp) >> 16;
+ } else {
+ RAcc = RTrg;
+ RVol = 0;
+ }
+
+ for (x = 0; x < 8; x++) {
+ i1=(int)inp[ptr^1];
+ o1=(int)out[ptr^1];
+ a1=(int)aux1[ptr^1];
+ if (AuxIncRate) {
+ a2=(int)aux2[ptr^1];
+ a3=(int)aux3[ptr^1];
+ }
+
+ LAcc += LVol;
+ RAcc += RVol;
+
+ if (LVol <= 0) { // Decrementing
+ if (LAcc < LTrg) {
+ LAcc = LTrg;
+ LAdderStart = LTrg;
+ MainL = oMainL;
+ AuxL = oAuxL;
+ } else {
+ MainL = (Dry * ((s32)LAcc>>16) + 0x4000) >> 15;
+ AuxL = (Wet * ((s32)LAcc>>16) + 0x4000) >> 15;
+ }
+ } else {
+ if (LAcc > LTrg) {
+ LAcc = LTrg;
+ LAdderStart = LTrg;
+ MainL = oMainL;
+ AuxL = oAuxL;
+ } else {
+ MainL = (Dry * ((s32)LAcc>>16) + 0x4000) >> 15;
+ AuxL = (Wet * ((s32)LAcc>>16) + 0x4000) >> 15;
+ }
+ }
+
+ if (RVol <= 0) { // Decrementing
+ if (RAcc < RTrg) {
+ RAcc = RTrg;
+ RAdderStart = RTrg;
+ MainR = oMainR;
+ AuxR = oAuxR;
+ } else {
+ MainR = (Dry * ((s32)RAcc>>16) + 0x4000) >> 15;
+ AuxR = (Wet * ((s32)RAcc>>16) + 0x4000) >> 15;
+ }
+ } else {
+ if (RAcc > RTrg) {
+ RAcc = RTrg;
+ RAdderStart = RTrg;
+ MainR = oMainR;
+ AuxR = oAuxR;
+ } else {
+ MainR = (Dry * ((s32)RAcc>>16) + 0x4000) >> 15;
+ AuxR = (Wet * ((s32)RAcc>>16) + 0x4000) >> 15;
+ }
+ }
+
+ o1+=((i1*MainR)+0x4000)>>15;
+ a1+=((i1*MainL)+0x4000)>>15;
+
+ if(o1>32767) o1=32767;
+ else if(o1<-32768) o1=-32768;
+
+ if(a1>32767) a1=32767;
+ else if(a1<-32768) a1=-32768;
+
+ out[ptr^1]=o1;
+ aux1[ptr^1]=a1;
+ if (AuxIncRate) {
+ a2+=((i1*AuxR)+0x4000)>>15;
+ a3+=((i1*AuxL)+0x4000)>>15;
+
+ if(a2>32767) a2=32767;
+ else if(a2<-32768) a2=-32768;
+
+ if(a3>32767) a3=32767;
+ else if(a3<-32768) a3=-32768;
+
+ aux2[ptr^1]=a2;
+ aux3[ptr^1]=a3;
+ }
+ ptr++;
+ }
+ }
+
+ *(s16 *)(hleMixerWorkArea + 0) = Wet; // 0-1
+ *(s16 *)(hleMixerWorkArea + 2) = Dry; // 2-3
+ *(s32 *)(hleMixerWorkArea + 4) = LTrg; // 4-5
+ *(s32 *)(hleMixerWorkArea + 6) = RTrg; // 6-7
+ *(s32 *)(hleMixerWorkArea + 8) = LRamp; // 8-9 (hleMixerWorkArea is a 16bit pointer)
+ *(s32 *)(hleMixerWorkArea + 10) = RRamp; // 10-11
+ *(s32 *)(hleMixerWorkArea + 12) = LAdderEnd; // 12-13
+ *(s32 *)(hleMixerWorkArea + 14) = RAdderEnd; // 14-15
+ *(s32 *)(hleMixerWorkArea + 16) = LAdderStart; // 12-13
+ *(s32 *)(hleMixerWorkArea + 18) = RAdderStart; // 14-15
+
+ memcpy((u8*)RDRAM+addy,(u8*)hleMixerWorkArea,80);
+}
+
+static void RESAMPLE () {
+ unsigned int Accum=0;
+ unsigned int location;
+ s16 *lut/*, *lut2*/;
+ short *dst;
+ s16 *src;
+ s32 temp;
+ s32 accum,addy;
+ u32 srcPtr, dstPtr;
+ unsigned char Flags;
+ unsigned int Pitch;
+ int x = 0, i = 0;
+
+ dst=(short *)(BufferSpace);
+ src=(s16 *)(BufferSpace);
+ srcPtr=(AudioInBuffer/2);
+ dstPtr=(AudioOutBuffer/2);
+
+
+ addy = (inst2 & 0xffffff);// + SEGMENTS[(inst2>>24)&0xf];
+ Flags=(u8)((inst1>>16)&0xff);
+ Pitch=((inst1&0xffff))<<1;
+
+ srcPtr -= 4;
+
+ if ((Flags & 0x1) == 0) {
+ for (x=0; x < 4; x++)
+ src[(srcPtr+x)^1] = *(u16 *)(N64MEM+(addy+(x*2)));
+
+ Accum = *(u16 *)(N64MEM+addy+10);
+ } else {
+ for (x=0; x < 4; x++)
+ src[(srcPtr+x)^1] = 0;
+ }
+
+
+ for(i = 0; i < ((AudioCount+0xf)&0xFFF0)/2;i++) {
+
+ location = (Accum >> 0xa) << 0x3;
+ lut = (s16 *)(((u8 *)ResampleLUT) + location);
+
+ temp = ((s32)*(s16*)(src+((srcPtr+0)^1))*((s32)((s16)lut[0])));
+ accum = (s32)(temp >> 15);
+
+ temp = ((s32)*(s16*)(src+((srcPtr+1)^1))*((s32)((s16)lut[1])));
+ accum += (s32)(temp >> 15);
+
+ temp = ((s32)*(s16*)(src+((srcPtr+2)^1))*((s32)((s16)lut[2])));
+ accum += (s32)(temp >> 15);
+
+ temp = ((s32)*(s16*)(src+((srcPtr+3)^1))*((s32)((s16)lut[3])));
+ accum += (s32)(temp >> 15);
+
+ if (accum > 32767) accum = 32767;
+ if (accum < -32768) accum = -32768;
+
+ dst[dstPtr^1] = (accum);
+ dstPtr++;
+ Accum += Pitch;
+ srcPtr += (Accum>>16);
+ Accum&=0xffff;
+ }
+ for (x = 0; x < 4; x++)
+ *(u16 *)(N64MEM+(addy+(x*2))) = src[(srcPtr+x)^1];
+
+ *(u16 *)(N64MEM+addy+10) = Accum;
+}
+static void SETVOL () {
+// Might be better to unpack these depending on the flags...
+ u8 flags = (u8)((inst1 >> 16) & 0xff);
+ u16 vol = (s16)(inst1 & 0xffff);
+ u16 voltarg =(u16)((inst2 >> 16)&0xffff);
+ u16 volrate = (u16)((inst2 & 0xffff));
+
+ if (flags & A_AUX) {
+ Env_Dry = (s16)vol; // m_MainVol
+ Env_Wet = (s16)volrate; // m_AuxVol
+ return;
+ }
+
+ if(flags & A_VOL) { // Set the Source(start) Volumes
+ if(flags & A_LEFT) {
+ Vol_Left = (s16)vol; // m_LeftVolume
+ } else { // A_RIGHT
+ Vol_Right = (s16)vol; // m_RightVolume
+ }
+ return;
+ }
+
+ if(flags & A_LEFT) { // Set the Ramping values Target, Ramp
+ VolTrg_Left = *(s16 *)&inst1; // m_LeftVol
+ if(goldeneye)
+ VolRamp_Left = voltarg;
+ else
+ VolRamp_Left = (s32)volrate;//*(s32 *)&inst2;//(u16)(inst2) | (s32)(s16)(inst2 << 0x10);
+ } else { // A_RIGHT
+ VolTrg_Right = *(s16 *)&inst1; // m_RightVol
+ if(goldeneye)
+ VolRamp_Right = voltarg;
+ else
+ VolRamp_Right = (s32)volrate;//*(s32 *)&inst2;//(u16)(inst2 >> 0x10) | (s32)(s16)(inst2 << 0x10);
+ }
+}
+
+static void UNKNOWN () {}
+
+static void SETLOOP () {
+ loopval = (inst2 & 0xffffff);
+}
+
+static void ADPCM () { // Work in progress! :)
+ unsigned short inPtr=0;
+ unsigned char icode;
+ unsigned char code;
+ int vscale;
+ unsigned short index;
+ unsigned short j;
+ int a[8];
+ short *book1,*book2;
+ int l1,l2;
+ int inp1[8];
+ int inp2[8];
+ short *out, count;
+
+ unsigned char Flags=(u8)(inst1>>16)&0xff;
+ unsigned int Address=(inst2 & 0xffffff);
+
+ out=(short *)(BufferSpace+AudioOutBuffer);
+ count=(short)AudioCount;
+
+ memset(out,0,32);
+
+ if(!(Flags&0x1))
+ {
+ if(Flags&0x2) {
+ memcpy((u8*)out,(u8*)RDRAM+Address,32);
+ } else {
+ memcpy((u8*)out,(u8*)RDRAM+Address,32);
+ }
+ }
+
+ l1=out[15];
+ l2=out[14];
+ out+=16;
+ while(count>0)
+ {
+ // the first interation through, these values are
+ // either 0 in the case of A_INIT, from a special
+ // area of memory in the case of A_LOOP or just
+ // the values we calculated the last time
+
+ code=BufferSpace[(AudioInBuffer+inPtr)^3];
+ index=code&0xf;
+ index<<=4; // index into the adpcm code table
+ book1=(short *)&adpcmtable[index];
+ book2=book1+8;
+ code>>=4; // upper nibble is scale
+ vscale=(0x8000>>((12-code)-1)); // very strange. 0x8000 would be .5 in 16:16 format
+ // so this appears to be a fractional scale based
+ // on the 12 based inverse of the scale value. note
+ // that this could be negative, in which case we do
+ // not use the calculated vscale value... see the
+ // if(code>12) check below
+
+ inPtr++; // coded adpcm data lies next
+ j=0;
+ while(j<8) // loop of 8, for 8 coded nibbles from 4 bytes
+ // which yields 8 short pcm values
+ {
+ icode=BufferSpace[(AudioInBuffer+inPtr)^3];
+ inPtr++;
+
+ inp1[j]=(s16)((icode&0xf0)<<8); // this will in effect be signed
+ if(code<12)
+ inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16);
+ j++;
+
+ inp1[j]=(s16)((icode&0xf)<<12);
+ if(code<12)
+ inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16);
+ j++;
+ }
+ j=0;
+ while(j<8)
+ {
+ icode=BufferSpace[(AudioInBuffer+inPtr)^3];
+ inPtr++;
+
+ inp2[j]=(short)((icode&0xf0)<<8); // this will in effect be signed
+ if(code<12)
+ inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16);
+ j++;
+
+ inp2[j]=(short)((icode&0xf)<<12);
+ if(code<12)
+ inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16);
+ j++;
+ }
+
+ a[0]= (int)book1[0]*(int)l1;
+ a[0]+=(int)book2[0]*(int)l2;
+ a[0]+=(int)inp1[0]*(int)2048;
+
+ a[1] =(int)book1[1]*(int)l1;
+ a[1]+=(int)book2[1]*(int)l2;
+ a[1]+=(int)book2[0]*inp1[0];
+ a[1]+=(int)inp1[1]*(int)2048;
+
+ a[2] =(int)book1[2]*(int)l1;
+ a[2]+=(int)book2[2]*(int)l2;
+ a[2]+=(int)book2[1]*inp1[0];
+ a[2]+=(int)book2[0]*inp1[1];
+ a[2]+=(int)inp1[2]*(int)2048;
+
+ a[3] =(int)book1[3]*(int)l1;
+ a[3]+=(int)book2[3]*(int)l2;
+ a[3]+=(int)book2[2]*inp1[0];
+ a[3]+=(int)book2[1]*inp1[1];
+ a[3]+=(int)book2[0]*inp1[2];
+ a[3]+=(int)inp1[3]*(int)2048;
+
+ a[4] =(int)book1[4]*(int)l1;
+ a[4]+=(int)book2[4]*(int)l2;
+ a[4]+=(int)book2[3]*inp1[0];
+ a[4]+=(int)book2[2]*inp1[1];
+ a[4]+=(int)book2[1]*inp1[2];
+ a[4]+=(int)book2[0]*inp1[3];
+ a[4]+=(int)inp1[4]*(int)2048;
+
+ a[5] =(int)book1[5]*(int)l1;
+ a[5]+=(int)book2[5]*(int)l2;
+ a[5]+=(int)book2[4]*inp1[0];
+ a[5]+=(int)book2[3]*inp1[1];
+ a[5]+=(int)book2[2]*inp1[2];
+ a[5]+=(int)book2[1]*inp1[3];
+ a[5]+=(int)book2[0]*inp1[4];
+ a[5]+=(int)inp1[5]*(int)2048;
+
+ a[6] =(int)book1[6]*(int)l1;
+ a[6]+=(int)book2[6]*(int)l2;
+ a[6]+=(int)book2[5]*inp1[0];
+ a[6]+=(int)book2[4]*inp1[1];
+ a[6]+=(int)book2[3]*inp1[2];
+ a[6]+=(int)book2[2]*inp1[3];
+ a[6]+=(int)book2[1]*inp1[4];
+ a[6]+=(int)book2[0]*inp1[5];
+ a[6]+=(int)inp1[6]*(int)2048;
+
+ a[7] =(int)book1[7]*(int)l1;
+ a[7]+=(int)book2[7]*(int)l2;
+ a[7]+=(int)book2[6]*inp1[0];
+ a[7]+=(int)book2[5]*inp1[1];
+ a[7]+=(int)book2[4]*inp1[2];
+ a[7]+=(int)book2[3]*inp1[3];
+ a[7]+=(int)book2[2]*inp1[4];
+ a[7]+=(int)book2[1]*inp1[5];
+ a[7]+=(int)book2[0]*inp1[6];
+ a[7]+=(int)inp1[7]*(int)2048;
+
+ for(j=0;j<8;j++)
+ {
+ a[j^1]>>=11;
+ if(a[j^1]>32767) a[j^1]=32767;
+ else if(a[j^1]<-32768) a[j^1]=-32768;
+ *(out++)=a[j^1];
+ }
+ l1=a[6];
+ l2=a[7];
+
+ a[0]= (int)book1[0]*(int)l1;
+ a[0]+=(int)book2[0]*(int)l2;
+ a[0]+=(int)inp2[0]*(int)2048;
+
+ a[1] =(int)book1[1]*(int)l1;
+ a[1]+=(int)book2[1]*(int)l2;
+ a[1]+=(int)book2[0]*inp2[0];
+ a[1]+=(int)inp2[1]*(int)2048;
+
+ a[2] =(int)book1[2]*(int)l1;
+ a[2]+=(int)book2[2]*(int)l2;
+ a[2]+=(int)book2[1]*inp2[0];
+ a[2]+=(int)book2[0]*inp2[1];
+ a[2]+=(int)inp2[2]*(int)2048;
+
+ a[3] =(int)book1[3]*(int)l1;
+ a[3]+=(int)book2[3]*(int)l2;
+ a[3]+=(int)book2[2]*inp2[0];
+ a[3]+=(int)book2[1]*inp2[1];
+ a[3]+=(int)book2[0]*inp2[2];
+ a[3]+=(int)inp2[3]*(int)2048;
+
+ a[4] =(int)book1[4]*(int)l1;
+ a[4]+=(int)book2[4]*(int)l2;
+ a[4]+=(int)book2[3]*inp2[0];
+ a[4]+=(int)book2[2]*inp2[1];
+ a[4]+=(int)book2[1]*inp2[2];
+ a[4]+=(int)book2[0]*inp2[3];
+ a[4]+=(int)inp2[4]*(int)2048;
+
+ a[5] =(int)book1[5]*(int)l1;
+ a[5]+=(int)book2[5]*(int)l2;
+ a[5]+=(int)book2[4]*inp2[0];
+ a[5]+=(int)book2[3]*inp2[1];
+ a[5]+=(int)book2[2]*inp2[2];
+ a[5]+=(int)book2[1]*inp2[3];
+ a[5]+=(int)book2[0]*inp2[4];
+ a[5]+=(int)inp2[5]*(int)2048;
+
+ a[6] =(int)book1[6]*(int)l1;
+ a[6]+=(int)book2[6]*(int)l2;
+ a[6]+=(int)book2[5]*inp2[0];
+ a[6]+=(int)book2[4]*inp2[1];
+ a[6]+=(int)book2[3]*inp2[2];
+ a[6]+=(int)book2[2]*inp2[3];
+ a[6]+=(int)book2[1]*inp2[4];
+ a[6]+=(int)book2[0]*inp2[5];
+ a[6]+=(int)inp2[6]*(int)2048;
+
+ a[7] =(int)book1[7]*(int)l1;
+ a[7]+=(int)book2[7]*(int)l2;
+ a[7]+=(int)book2[6]*inp2[0];
+ a[7]+=(int)book2[5]*inp2[1];
+ a[7]+=(int)book2[4]*inp2[2];
+ a[7]+=(int)book2[3]*inp2[3];
+ a[7]+=(int)book2[2]*inp2[4];
+ a[7]+=(int)book2[1]*inp2[5];
+ a[7]+=(int)book2[0]*inp2[6];
+ a[7]+=(int)inp2[7]*(int)2048;
+
+ for(j=0;j<8;j++)
+ {
+ a[j^1]>>=11;
+ if(a[j^1]>32767) a[j^1]=32767;
+ else if(a[j^1]<-32768) a[j^1]=-32768;
+ *(out++)=a[j^1];
+ }
+ l1=a[6];
+ l2=a[7];
+
+ count-=32;
+ }
+ out-=16;
+
+ memcpy((u8*)RDRAM+Address,(u8*) out, 32);
+}
+
+static void LOADBUFF () { // memcpy causes static... endianess issue :(
+ u32 v0;
+ if (AudioCount == 0)
+ return;
+ v0 = (inst2 & 0xfffffc);
+
+ memcpy(BufferSpace+(AudioInBuffer&0xFFFC), (u8*)RDRAM+v0, (AudioCount+3)&0xFFFC);
+
+}
+
+static void SAVEBUFF () { // memcpy causes static... endianess issue :(
+ u32 v0;
+ if (AudioCount == 0)
+ return;
+ v0 = (inst2 & 0xfffffc);
+
+ memcpy((unsigned char*)RDRAM+v0, BufferSpace+(AudioOutBuffer&0xFFFC), (AudioCount+3)&0xFFFC);
+}
+
+static void SETBUFF () { // Should work ;-)
+ if ((inst1 >> 0x10) & 0x8) { // A_AUX - Auxillary Sound Buffer Settings
+ AudioAuxA = (u16)(inst1);
+ AudioAuxC = (u16)((inst2 >> 0x10));
+ AudioAuxE = (u16)(inst2);
+ } else { // A_MAIN - Main Sound Buffer Settings
+ AudioInBuffer = (u16)(inst1); // 0x00
+ AudioOutBuffer = (u16)((inst2 >> 0x10)); // 0x02
+ AudioCount = (u16)(inst2); // 0x04
+ }
+}
+
+static void DMEMMOVE () { // Doesn't sound just right?... will fix when HLE is ready - 03-11-01
+ u32 v0, v1;
+ u32 cnt;
+ u32 count = ((inst2+3) & 0xfffc);
+ if ((inst2 & 0xffff)==0)
+ return;
+ v0 = (inst1 & 0xFFFF);
+ v1 = (inst2 >> 0x10);
+
+ for (cnt = 0; cnt < count; cnt++) {
+ *(u8 *)(BufferSpace+((cnt+v1)^3)) = *(u8 *)(BufferSpace+((cnt+v0)^3));
+ }
+}
+
+static void LOADADPCM () { // Loads an ADPCM table - Works 100% Now 03-13-01
+ u32 v0, x;
+ v0 = (inst2 & 0xffffff);
+
+ for (x = 0; x < ((inst1 & 0xffff) >> 0x4); x++) {
+
+ u16 *table = (u16 *)(N64MEM+v0+(x<<4));
+
+ adpcmtable[0x1+(x<<3)] = table[0];
+ adpcmtable[0x0+(x<<3)] = table[1];
+
+ adpcmtable[0x3+(x<<3)] = table[2];
+ adpcmtable[0x2+(x<<3)] = table[3];
+
+ adpcmtable[0x5+(x<<3)] = table[4];
+ adpcmtable[0x4+(x<<3)] = table[5];
+
+ adpcmtable[0x7+(x<<3)] = table[6];
+ adpcmtable[0x6+(x<<3)] = table[7];
+
+ }
+}
+
+
+static void INTERLEAVE () { // Works... - 3-11-01
+ u32 inL, inR;
+ u16 *inSrcR;
+ u16 *inSrcL;
+ u16 Left, Right;
+ u16 *outbuff = (u16 *)(AudioOutBuffer+BufferSpace);
+ int x;
+
+ inL = inst2 & 0xFFFF;
+ inR = (inst2 >> 16) & 0xFFFF;
+
+ inSrcR = (u16 *)(BufferSpace+inR);
+ inSrcL = (u16 *)(BufferSpace+inL);
+
+ for (x = 0; x < (AudioCount/4); x++) {
+ Left=*(inSrcL++);
+ Right=*(inSrcR++);
+
+ *(outbuff++)=*(inSrcR++);
+ *(outbuff++)=*(inSrcL++);
+ *(outbuff++)=(u16)Right;
+ *(outbuff++)=(u16)Left;
+ }
+}
+
+
+static void MIXER () { // Fixed a sign issue... 03-14-01
+ u32 dmemin = (u16)(inst2 >> 0x10);
+ u32 dmemout = (u16)(inst2 & 0xFFFF);
+ s32 gain = (s16)(inst1 & 0xFFFF);
+ s32 temp;
+ int x;
+
+ if (AudioCount == 0)
+ return;
+
+ for (x = 0; x < AudioCount; x+=2) { // I think I can do this a lot easier
+ temp = (*(s16 *)(BufferSpace+dmemin+x) * gain) >> 15;
+ temp += *(s16 *)(BufferSpace+dmemout+x);
+
+ if ((s32)temp > 32767)
+ temp = 32767;
+ if ((s32)temp < -32768)
+ temp = -32768;
+
+ *(u16 *)(BufferSpace+dmemout+x) = (u16)(temp & 0xFFFF);
+ }
+}
+
+
+void (*ABI1[0x20])() = { // TOP Performace Hogs: MIXER, RESAMPLE, ENVMIXER
+ SPNOOP , ADPCM , CLEARBUFF, ENVMIXER , LOADBUFF, RESAMPLE , SAVEBUFF, UNKNOWN,
+ SETBUFF, SETVOL, DMEMMOVE , LOADADPCM , MIXER , INTERLEAVE, UNKNOWN , SETLOOP,
+ SPNOOP , SPNOOP, SPNOOP , SPNOOP , SPNOOP , SPNOOP , SPNOOP , SPNOOP,
+ SPNOOP , SPNOOP, SPNOOP , SPNOOP , SPNOOP , SPNOOP , SPNOOP , SPNOOP
+};
diff --git a/src/usf/audio_ucode2.c b/src/usf/audio_ucode2.c new file mode 100644 index 0000000..551265c --- /dev/null +++ b/src/usf/audio_ucode2.c @@ -0,0 +1,904 @@ +#include <stdbool.h>
+#include <stdio.h>
+#include "usf.h"
+#include "audio_hle.h"
+#include "memory.h"
+
+
+
+
+extern u8 BufferSpace[0x10000];
+
+static void SPNOOP () {
+ char buff[0x100];
+}
+
+extern u16 AudioInBuffer; // 0x0000(T8)
+extern u16 AudioOutBuffer; // 0x0002(T8)
+extern u16 AudioCount; // 0x0004(T8)
+extern u32 loopval; // 0x0010(T8)
+extern u32 SEGMENTS[0x10];
+extern u16 adpcmtable[0x88];
+extern u16 ResampleLUT [0x200];
+
+bool isMKABI = false;
+bool isZeldaABI = false;
+
+#define PageRAM2(x) ((uintptr_t) (RDRAM + (x)))
+#define memcpyfn64(a,b,c) memcpy((a),(void*)((uintptr_t)RDRAM + (uintptr_t)(b)),(c))
+#define memcpy2n64(a,b,c) memcpy((void*)((uintptr_t)RDRAM + (uintptr_t)(a)),(b),(c))
+
+static void LOADADPCM2 () { // Loads an ADPCM table - Works 100% Now 03-13-01
+ u32 v0;
+ v0 = (inst2 & 0xffffff);// + SEGMENTS[(inst2>>24)&0xf];
+ u32 x;
+
+ for (x = 0; x < ((inst1&0xffff)>>0x4); x++) {
+ u16 *table = (u16*)PageRAM2(v0+(x*16));
+
+
+ adpcmtable[0x1+(x<<3)] = table[0];
+ adpcmtable[0x0+(x<<3)] = table[1];
+
+ adpcmtable[0x3+(x<<3)] = table[2];
+ adpcmtable[0x2+(x<<3)] = table[3];
+
+ adpcmtable[0x5+(x<<3)] = table[4];
+ adpcmtable[0x4+(x<<3)] = table[5];
+
+ adpcmtable[0x7+(x<<3)] = table[6];
+ adpcmtable[0x6+(x<<3)] = table[7];
+ // table += 8;
+ }
+}
+
+static void SETLOOP2 () {
+ loopval = inst2 & 0xffffff; // No segment?
+}
+
+static void SETBUFF2 () {
+ AudioInBuffer = (u16)(inst1); // 0x00
+ AudioOutBuffer = (u16)((inst2 >> 0x10)); // 0x02
+ AudioCount = (u16)(inst2); // 0x04
+}
+
+static void ADPCM2 () { // Verified to be 100% Accurate...
+ unsigned char Flags=(u8)(inst1>>16)&0xff;
+ //WORD Gain=(u16)(inst1&0xffff);
+ unsigned int Address=(inst2 & 0xffffff);// + SEGMENTS[(inst2>>24)&0xf];
+ unsigned short inPtr=0;
+ //short *out=(s16 *)(testbuff+(AudioOutBuffer>>2));
+ short *out=(short *)(BufferSpace+AudioOutBuffer);
+ //BYTE *in=(unsigned char *)(BufferSpace+AudioInBuffer);
+ short count=(short)AudioCount;
+ unsigned char icode;
+ unsigned char code;
+ int vscale;
+ unsigned short index;
+ unsigned short j;
+ int a[8];
+ short *book1,*book2;
+
+ u8 srange;
+ u8 inpinc;
+ u8 mask1;
+ u8 mask2;
+ u8 shifter;
+
+ memset(out,0,32);
+
+ if (Flags & 0x4) { // Tricky lil Zelda MM and ABI2!!! hahaha I know your secrets! :DDD
+ srange = 0xE;
+ inpinc = 0x5;
+ mask1 = 0xC0;
+ mask2 = 0x30;
+ shifter = 10;
+ } else {
+ srange = 0xC;
+ inpinc = 0x9;
+ mask1 = 0xf0;
+ mask2 = 0x0f;
+ shifter = 12;
+ }
+
+ if(!(Flags&0x1))
+ {
+ if(Flags&0x2)
+ {/*
+ for(int i=0;i<16;i++)
+ {
+ out[i]=*(short *)&rsp.RDRAM[(loopval+i*2)^2];
+ }*/
+ memcpyfn64((u8 *)out,(u8 *)loopval,32);
+ }
+ else
+ {/*
+ for(int i=0;i<16;i++)
+ {
+ out[i]=*(short *)&rsp.RDRAM[(Address+i*2)^2];
+ }*/
+
+ memcpyfn64((u8 *)out,(u8 *)Address,32);
+ }
+ }
+
+ int l1=out[15];
+ int l2=out[14];
+ int inp1[8];
+ int inp2[8];
+ out+=16;
+ while(count>0) {
+ code=BufferSpace[(AudioInBuffer+inPtr)^3];
+ index=code&0xf;
+ index<<=4;
+ book1=(short *)&adpcmtable[index];
+ book2=book1+8;
+ code>>=4;
+ vscale=(0x8000>>((srange-code)-1));
+
+ inPtr++;
+ j=0;
+
+ while(j<8) {
+ icode=BufferSpace[(AudioInBuffer+inPtr)^3];
+ inPtr++;
+
+ inp1[j]=(s16)((icode&mask1) << 8); // this will in effect be signed
+ if(code<srange) inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16);
+ //else int catchme=1;
+ j++;
+
+ inp1[j]=(s16)((icode&mask2)<<shifter);
+ if(code<srange) inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16);
+ //else int catchme=1;
+ j++;
+
+ if (Flags & 4) {
+ inp1[j]=(s16)((icode&0xC) << 12); // this will in effect be signed
+ if(code < 0xE) inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16);
+ //else int catchme=1;
+ j++;
+
+ inp1[j]=(s16)((icode&0x3) << 14);
+ if(code < 0xE) inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16);
+ //else int catchme=1;
+ j++;
+ } // end flags
+ } // end while
+
+
+
+ j=0;
+ while(j<8) {
+ icode=BufferSpace[(AudioInBuffer+inPtr)^3];
+ inPtr++;
+
+ inp2[j]=(s16)((icode&mask1) << 8);
+ if(code<srange) inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16);
+ //else int catchme=1;
+ j++;
+
+ inp2[j]=(s16)((icode&mask2)<<shifter);
+ if(code<srange) inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16);
+ //else int catchme=1;
+ j++;
+
+ if (Flags & 4) {
+ inp2[j]=(s16)((icode&0xC) << 12);
+ if(code < 0xE) inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16);
+ //else int catchme=1;
+ j++;
+
+ inp2[j]=(s16)((icode&0x3) << 14);
+ if(code < 0xE) inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16);
+ //else int catchme=1;
+ j++;
+ } // end flags
+ }
+
+ a[0]= (int)book1[0]*(int)l1;
+ a[0]+=(int)book2[0]*(int)l2;
+ a[0]+=(int)inp1[0]*(int)2048;
+
+ a[1] =(int)book1[1]*(int)l1;
+ a[1]+=(int)book2[1]*(int)l2;
+ a[1]+=(int)book2[0]*inp1[0];
+ a[1]+=(int)inp1[1]*(int)2048;
+
+ a[2] =(int)book1[2]*(int)l1;
+ a[2]+=(int)book2[2]*(int)l2;
+ a[2]+=(int)book2[1]*inp1[0];
+ a[2]+=(int)book2[0]*inp1[1];
+ a[2]+=(int)inp1[2]*(int)2048;
+
+ a[3] =(int)book1[3]*(int)l1;
+ a[3]+=(int)book2[3]*(int)l2;
+ a[3]+=(int)book2[2]*inp1[0];
+ a[3]+=(int)book2[1]*inp1[1];
+ a[3]+=(int)book2[0]*inp1[2];
+ a[3]+=(int)inp1[3]*(int)2048;
+
+ a[4] =(int)book1[4]*(int)l1;
+ a[4]+=(int)book2[4]*(int)l2;
+ a[4]+=(int)book2[3]*inp1[0];
+ a[4]+=(int)book2[2]*inp1[1];
+ a[4]+=(int)book2[1]*inp1[2];
+ a[4]+=(int)book2[0]*inp1[3];
+ a[4]+=(int)inp1[4]*(int)2048;
+
+ a[5] =(int)book1[5]*(int)l1;
+ a[5]+=(int)book2[5]*(int)l2;
+ a[5]+=(int)book2[4]*inp1[0];
+ a[5]+=(int)book2[3]*inp1[1];
+ a[5]+=(int)book2[2]*inp1[2];
+ a[5]+=(int)book2[1]*inp1[3];
+ a[5]+=(int)book2[0]*inp1[4];
+ a[5]+=(int)inp1[5]*(int)2048;
+
+ a[6] =(int)book1[6]*(int)l1;
+ a[6]+=(int)book2[6]*(int)l2;
+ a[6]+=(int)book2[5]*inp1[0];
+ a[6]+=(int)book2[4]*inp1[1];
+ a[6]+=(int)book2[3]*inp1[2];
+ a[6]+=(int)book2[2]*inp1[3];
+ a[6]+=(int)book2[1]*inp1[4];
+ a[6]+=(int)book2[0]*inp1[5];
+ a[6]+=(int)inp1[6]*(int)2048;
+
+ a[7] =(int)book1[7]*(int)l1;
+ a[7]+=(int)book2[7]*(int)l2;
+ a[7]+=(int)book2[6]*inp1[0];
+ a[7]+=(int)book2[5]*inp1[1];
+ a[7]+=(int)book2[4]*inp1[2];
+ a[7]+=(int)book2[3]*inp1[3];
+ a[7]+=(int)book2[2]*inp1[4];
+ a[7]+=(int)book2[1]*inp1[5];
+ a[7]+=(int)book2[0]*inp1[6];
+ a[7]+=(int)inp1[7]*(int)2048;
+
+ for(j=0;j<8;j++)
+ {
+ a[j^1]>>=11;
+ if(a[j^1]>32767) a[j^1]=32767;
+ else if(a[j^1]<-32768) a[j^1]=-32768;
+ *(out++)=a[j^1];
+ }
+ l1=a[6];
+ l2=a[7];
+
+ a[0]= (int)book1[0]*(int)l1;
+ a[0]+=(int)book2[0]*(int)l2;
+ a[0]+=(int)inp2[0]*(int)2048;
+
+ a[1] =(int)book1[1]*(int)l1;
+ a[1]+=(int)book2[1]*(int)l2;
+ a[1]+=(int)book2[0]*inp2[0];
+ a[1]+=(int)inp2[1]*(int)2048;
+
+ a[2] =(int)book1[2]*(int)l1;
+ a[2]+=(int)book2[2]*(int)l2;
+ a[2]+=(int)book2[1]*inp2[0];
+ a[2]+=(int)book2[0]*inp2[1];
+ a[2]+=(int)inp2[2]*(int)2048;
+
+ a[3] =(int)book1[3]*(int)l1;
+ a[3]+=(int)book2[3]*(int)l2;
+ a[3]+=(int)book2[2]*inp2[0];
+ a[3]+=(int)book2[1]*inp2[1];
+ a[3]+=(int)book2[0]*inp2[2];
+ a[3]+=(int)inp2[3]*(int)2048;
+
+ a[4] =(int)book1[4]*(int)l1;
+ a[4]+=(int)book2[4]*(int)l2;
+ a[4]+=(int)book2[3]*inp2[0];
+ a[4]+=(int)book2[2]*inp2[1];
+ a[4]+=(int)book2[1]*inp2[2];
+ a[4]+=(int)book2[0]*inp2[3];
+ a[4]+=(int)inp2[4]*(int)2048;
+
+ a[5] =(int)book1[5]*(int)l1;
+ a[5]+=(int)book2[5]*(int)l2;
+ a[5]+=(int)book2[4]*inp2[0];
+ a[5]+=(int)book2[3]*inp2[1];
+ a[5]+=(int)book2[2]*inp2[2];
+ a[5]+=(int)book2[1]*inp2[3];
+ a[5]+=(int)book2[0]*inp2[4];
+ a[5]+=(int)inp2[5]*(int)2048;
+
+ a[6] =(int)book1[6]*(int)l1;
+ a[6]+=(int)book2[6]*(int)l2;
+ a[6]+=(int)book2[5]*inp2[0];
+ a[6]+=(int)book2[4]*inp2[1];
+ a[6]+=(int)book2[3]*inp2[2];
+ a[6]+=(int)book2[2]*inp2[3];
+ a[6]+=(int)book2[1]*inp2[4];
+ a[6]+=(int)book2[0]*inp2[5];
+ a[6]+=(int)inp2[6]*(int)2048;
+
+ a[7] =(int)book1[7]*(int)l1;
+ a[7]+=(int)book2[7]*(int)l2;
+ a[7]+=(int)book2[6]*inp2[0];
+ a[7]+=(int)book2[5]*inp2[1];
+ a[7]+=(int)book2[4]*inp2[2];
+ a[7]+=(int)book2[3]*inp2[3];
+ a[7]+=(int)book2[2]*inp2[4];
+ a[7]+=(int)book2[1]*inp2[5];
+ a[7]+=(int)book2[0]*inp2[6];
+ a[7]+=(int)inp2[7]*(int)2048;
+
+ for(j=0;j<8;j++)
+ {
+ a[j^1]>>=11;
+ if(a[j^1]>32767) a[j^1]=32767;
+ else if(a[j^1]<-32768) a[j^1]=-32768;
+ *(out++)=a[j^1];
+ }
+ l1=a[6];
+ l2=a[7];
+
+ count-=32;
+ }
+ out-=16;
+ memcpy2n64((u8 *)Address,(u8 *)out,32);
+}
+
+static void CLEARBUFF2 () {
+ u16 addr = (u16)(inst1 & 0xffff);
+ u16 count = (u16)(inst2 & 0xffff);
+ if (count > 0)
+ memset(BufferSpace+addr, 0, count);
+}
+
+static void LOADBUFF2 () { // Needs accuracy verification...
+ u32 v0;
+ u32 cnt = (((inst1 >> 0xC)+3)&0xFFC);
+ v0 = (inst2 & 0xfffffc);// + SEGMENTS[(inst2>>24)&0xf];
+
+ memcpyfn64 ((u8 *)BufferSpace+(inst1&0xfffc), (u8 *)v0, (cnt+3)&0xFFFC);
+}
+
+static void SAVEBUFF2 () { // Needs accuracy verification...
+ u32 v0;
+ u32 cnt = (((inst1 >> 0xC)+3)&0xFFC);
+ v0 = (inst2 & 0xfffffc);// + SEGMENTS[(inst2>>24)&0xf];
+ memcpy2n64 ((u8 *)v0, (u8 *)BufferSpace+(inst1&0xfffc), (cnt+3)&0xFFFC);
+}
+
+
+static void MIXER2 () { // Needs accuracy verification...
+ u16 dmemin = (u16)(inst2 >> 0x10);
+ u16 dmemout = (u16)(inst2 & 0xFFFF);
+ u32 count = ((inst1 >> 12) & 0xFF0);
+ s32 gain = (s16)(inst1 & 0xFFFF)*2;
+ s32 temp;
+ unsigned int x;
+
+ for (x=0; x < count; x+=2) { // I think I can do this a lot easier
+
+ temp = (*(s16 *)(BufferSpace+dmemin+x) * gain) >> 16;
+ temp += *(s16 *)(BufferSpace+dmemout+x);
+
+ if ((s32)temp > 32767)
+ temp = 32767;
+ if ((s32)temp < -32768)
+ temp = -32768;
+
+ *(u16 *)(BufferSpace+dmemout+x) = (u16)(temp & 0xFFFF);
+ }
+}
+
+
+
+static void RESAMPLE2 () {
+ unsigned char Flags=(u8)((inst1>>16)&0xff);
+ unsigned int Pitch=((inst1&0xffff))<<1;
+ u32 addy = (inst2 & 0xffffff);// + SEGMENTS[(inst2>>24)&0xf];
+ unsigned int Accum=0;
+ unsigned int location;
+ s16 *lut;
+ short *dst;
+ s16 *src;
+ dst=(short *)(BufferSpace);
+ src=(s16 *)(BufferSpace);
+ u32 srcPtr=(AudioInBuffer/2);
+ u32 dstPtr=(AudioOutBuffer/2);
+ s32 temp;
+ s32 accum;
+ int x, i;
+
+ if (addy > (1024*1024*8))
+ addy = (inst2 & 0xffffff);
+
+ srcPtr -= 4;
+
+ if ((Flags & 0x1) == 0) {
+ for (x=0; x < 4; x++)
+ src[(srcPtr+x)^1] = *(u16*)(PageRAM2(addy+(x^1)));
+ Accum = *(u16 *)(PageRAM2(addy+10));
+ } else {
+ for (x=0; x < 4; x++)
+ src[(srcPtr+x)^1] = 0;//*(u16 *)(rsp.RDRAM+((addy+x)^2));
+ }
+
+ for(i=0;i < ((AudioCount+0xf)&0xFFF0)/2;i++) {
+ location = (((Accum * 0x40) >> 0x10) * 8);
+ //location = (Accum >> 0xa) << 0x3;
+ lut = (s16 *)(((u8 *)ResampleLUT) + location);
+
+ temp = ((s32)*(s16*)(src+((srcPtr+0)^1))*((s32)((s16)lut[0])));
+ accum = (s32)(temp >> 15);
+
+ temp = ((s32)*(s16*)(src+((srcPtr+1)^1))*((s32)((s16)lut[1])));
+ accum += (s32)(temp >> 15);
+
+ temp = ((s32)*(s16*)(src+((srcPtr+2)^1))*((s32)((s16)lut[2])));
+ accum += (s32)(temp >> 15);
+
+ temp = ((s32)*(s16*)(src+((srcPtr+3)^1))*((s32)((s16)lut[3])));
+ accum += (s32)(temp >> 15);
+
+ if (accum > 32767) accum = 32767;
+ if (accum < -32768) accum = -32768;
+
+ dst[dstPtr^1] = (s16)(accum);
+ dstPtr++;
+ Accum += Pitch;
+ srcPtr += (Accum>>16);
+ Accum&=0xffff;
+ }
+ for (x=0; x < 4; x++)
+ *(u16*)(PageRAM2(addy+(x^1))) = src[(srcPtr+x)^1];
+
+ *(u16 *)(PageRAM2(addy+10)) = Accum;
+
+}
+
+static void DMEMMOVE2 () { // Needs accuracy verification...
+ u32 v0, v1;
+ u32 cnt;
+ if ((inst2 & 0xffff)==0)
+ return;
+ v0 = (inst1 & 0xFFFF);
+ v1 = (inst2 >> 0x10);
+ //assert ((v1 & 0x3) == 0);
+ //assert ((v0 & 0x3) == 0);
+ u32 count = ((inst2+3) & 0xfffc);
+ //v0 = (v0) & 0xfffc;
+ //v1 = (v1) & 0xfffc;
+
+ //memcpy (dmem+v1, dmem+v0, count-1);
+ for (cnt = 0; cnt < count; cnt++) {
+ *(u8 *)(BufferSpace+((cnt+v1)^3)) = *(u8 *)(BufferSpace+((cnt+v0)^3));
+ }
+}
+
+u32 t3, s5, s6;
+u16 env[8];
+
+static void ENVSETUP1 () {
+ u32 tmp;
+
+ //fprintf (dfile, "ENVSETUP1: inst1 = %08X, inst2 = %08X\n", inst1, inst2);
+ t3 = inst1 & 0xFFFF;
+ tmp = (inst1 >> 0x8) & 0xFF00;
+ env[4] = (u16)tmp;
+ tmp += t3;
+ env[5] = (u16)tmp;
+ s5 = inst2 >> 0x10;
+ s6 = inst2 & 0xFFFF;
+ //fprintf (dfile, " t3 = %X / s5 = %X / s6 = %X / env[4] = %X / env[5] = %X\n", t3, s5, s6, env[4], env[5]);
+}
+
+static void ENVSETUP2 () {
+ u32 tmp;
+
+ //fprintf (dfile, "ENVSETUP2: inst1 = %08X, inst2 = %08X\n", inst1, inst2);
+ tmp = (inst2 >> 0x10);
+ env[0] = (u16)tmp;
+ tmp += s5;
+ env[1] = (u16)tmp;
+ tmp = inst2 & 0xffff;
+ env[2] = (u16)tmp;
+ tmp += s6;
+ env[3] = (u16)tmp;
+ //fprintf (dfile, " env[0] = %X / env[1] = %X / env[2] = %X / env[3] = %X\n", env[0], env[1], env[2], env[3]);
+}
+
+static void ENVMIXER2 () {
+ //fprintf (dfile, "ENVMIXER: inst1 = %08X, inst2 = %08X\n", inst1, inst2);
+
+ s16 *bufft6, *bufft7, *buffs0, *buffs1;
+ s16 *buffs3;
+ s32 count;
+ u32 adder;
+
+ s16 vec9, vec10;
+
+ s16 v2[8];
+
+ //__asm int 3;
+
+ buffs3 = (s16 *)(BufferSpace + ((inst1 >> 0x0c)&0x0ff0));
+ bufft6 = (s16 *)(BufferSpace + ((inst2 >> 0x14)&0x0ff0));
+ bufft7 = (s16 *)(BufferSpace + ((inst2 >> 0x0c)&0x0ff0));
+ buffs0 = (s16 *)(BufferSpace + ((inst2 >> 0x04)&0x0ff0));
+ buffs1 = (s16 *)(BufferSpace + ((inst2 << 0x04)&0x0ff0));
+
+ v2[0] = 0 - (s16)((inst1 & 0x2) >> 1);
+ v2[1] = 0 - (s16)((inst1 & 0x1));
+ v2[2] = 0 - (s16)((inst1 & 0x8) >> 1);
+ v2[3] = 0 - (s16)((inst1 & 0x4) >> 1);
+
+ count = (inst1 >> 8) & 0xff;
+
+ if (!isMKABI) {
+ s5 *= 2; s6 *= 2; t3 *= 2;
+ adder = 0x10;
+ } else {
+ inst1 = 0;
+ adder = 0x8;
+ t3 = 0;
+ }
+
+
+ while (count > 0) {
+ int temp, x;
+ for (x=0; x < 0x8; x++) {
+ vec9 = (s16)(((s32)buffs3[x^1] * (u32)env[0]) >> 0x10) ^ v2[0];
+ vec10 = (s16)(((s32)buffs3[x^1] * (u32)env[2]) >> 0x10) ^ v2[1];
+ temp = bufft6[x^1] + vec9;
+ if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
+ bufft6[x^1] = temp;
+ temp = bufft7[x^1] + vec10;
+ if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
+ bufft7[x^1] = temp;
+ vec9 = (s16)(((s32)vec9 * (u32)env[4]) >> 0x10) ^ v2[2];
+ vec10 = (s16)(((s32)vec10 * (u32)env[4]) >> 0x10) ^ v2[3];
+ if (inst1 & 0x10) {
+ temp = buffs0[x^1] + vec10;
+ if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
+ buffs0[x^1] = temp;
+ temp = buffs1[x^1] + vec9;
+ if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
+ buffs1[x^1] = temp;
+ } else {
+ temp = buffs0[x^1] + vec9;
+ if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
+ buffs0[x^1] = temp;
+ temp = buffs1[x^1] + vec10;
+ if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
+ buffs1[x^1] = temp;
+ }
+ }
+
+ if (!isMKABI)
+ for (x=0x8; x < 0x10; x++) {
+ vec9 = (s16)(((s32)buffs3[x^1] * (u32)env[1]) >> 0x10) ^ v2[0];
+ vec10 = (s16)(((s32)buffs3[x^1] * (u32)env[3]) >> 0x10) ^ v2[1];
+ temp = bufft6[x^1] + vec9;
+ if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
+ bufft6[x^1] = temp;
+ temp = bufft7[x^1] + vec10;
+ if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
+ bufft7[x^1] = temp;
+ vec9 = (s16)(((s32)vec9 * (u32)env[5]) >> 0x10) ^ v2[2];
+ vec10 = (s16)(((s32)vec10 * (u32)env[5]) >> 0x10) ^ v2[3];
+ if (inst1 & 0x10) {
+ temp = buffs0[x^1] + vec10;
+ if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
+ buffs0[x^1] = temp;
+ temp = buffs1[x^1] + vec9;
+ if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
+ buffs1[x^1] = temp;
+ } else {
+ temp = buffs0[x^1] + vec9;
+ if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
+ buffs0[x^1] = temp;
+ temp = buffs1[x^1] + vec10;
+ if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
+ buffs1[x^1] = temp;
+ }
+ }
+ bufft6 += adder; bufft7 += adder;
+ buffs0 += adder; buffs1 += adder;
+ buffs3 += adder; count -= adder;
+ env[0] += (u16)s5; env[1] += (u16)s5;
+ env[2] += (u16)s6; env[3] += (u16)s6;
+ env[4] += (u16)t3; env[5] += (u16)t3;
+ }
+}
+
+static void DUPLICATE2() {
+ unsigned short Count = (inst1 >> 16) & 0xff;
+ unsigned short In = inst1&0xffff;
+ unsigned short Out = (inst2>>16);
+
+ unsigned short buff[64];
+
+ memcpy(buff,BufferSpace+In,128);
+
+ while(Count) {
+ memcpy(BufferSpace+Out,buff,128);
+ Out+=128;
+ Count--;
+ }
+}
+/*
+static void INTERL2 () { // Make your own...
+ short Count = inst1 & 0xffff;
+ unsigned short Out = inst2 & 0xffff;
+ unsigned short In = (inst2 >> 16);
+
+ short *src,*dst,tmp;
+ src=(short *)&BufferSpace[In];
+ dst=(short *)&BufferSpace[Out];
+ while(Count)
+ {
+ *(dst++)=*(src++);
+ src++;
+ *(dst++)=*(src++);
+ src++;
+ *(dst++)=*(src++);
+ src++;
+ *(dst++)=*(src++);
+ src++;
+ *(dst++)=*(src++);
+ src++;
+ *(dst++)=*(src++);
+ src++;
+ *(dst++)=*(src++);
+ src++;
+ *(dst++)=*(src++);
+ src++;
+ Count-=8;
+ }
+}
+*/
+
+static void INTERL2 () {
+ short Count = inst1 & 0xffff;
+ unsigned short Out = inst2 & 0xffff;
+ unsigned short In = (inst2 >> 16);
+
+ unsigned char *src,*dst/*,tmp*/;
+ src=(unsigned char *)(BufferSpace);//[In];
+ dst=(unsigned char *)(BufferSpace);//[Out];
+ while(Count) {
+ *(short *)(dst+(Out^3)) = *(short *)(src+(In^3));
+ Out += 2;
+ In += 4;
+ Count--;
+ }
+}
+
+static void INTERLEAVE2 () { // Needs accuracy verification...
+ u32 inL, inR;
+ u16 *outbuff;
+ u16 *inSrcR;
+ u16 *inSrcL;
+ u16 Left, Right;
+ u32 count;
+ u32 x;
+ count = ((inst1 >> 12) & 0xFF0);
+ if (count == 0) {
+ outbuff = (u16 *)(AudioOutBuffer+BufferSpace);
+ count = AudioCount;
+ } else {
+ outbuff = (u16 *)((inst1&0xFFFF)+BufferSpace);
+ }
+
+ inR = inst2 & 0xFFFF;
+ inL = (inst2 >> 16) & 0xFFFF;
+
+ inSrcR = (u16 *)(BufferSpace+inR);
+ inSrcL = (u16 *)(BufferSpace+inL);
+
+ for (x = 0; x < (count/4); x++) {
+ Left=*(inSrcL++);
+ Right=*(inSrcR++);
+
+ *(outbuff++)=*(inSrcR++);
+ *(outbuff++)=*(inSrcL++);
+ *(outbuff++)=(u16)Right;
+ *(outbuff++)=(u16)Left;
+ }
+}
+
+static void ADDMIXER () {
+ short Count = (inst1 >> 12) & 0x00ff0;
+ u16 InBuffer = (inst2 >> 16);
+ u16 OutBuffer = inst2 & 0xffff;
+ int cntr;
+
+ s16 *inp, *outp;
+ s32 temp;
+ inp = (s16 *)(BufferSpace + InBuffer);
+ outp = (s16 *)(BufferSpace + OutBuffer);
+ for (cntr = 0; cntr < Count; cntr+=2) {
+ temp = *outp + *inp;
+ if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768;
+ outp++; inp++;
+ }
+}
+
+static void HILOGAIN () {
+ u16 cnt = inst1 & 0xffff;
+ u16 out = (inst2 >> 16) & 0xffff;
+ s16 hi = (s16)((inst1 >> 4) & 0xf000);
+ u16 lo = (inst1 >> 20) & 0xf;
+ s16 *src;
+
+ src = (s16 *)(BufferSpace+out);
+ s32 tmp, val;
+
+ while(cnt) {
+ val = (s32)*src;
+ //tmp = ((val * (s32)hi) + ((u64)(val * lo) << 16) >> 16);
+ tmp = ((val * (s32)hi) >> 16) + (u32)(val * lo);
+ if ((s32)tmp > 32767) tmp = 32767;
+ else if ((s32)tmp < -32768) tmp = -32768;
+ *src = tmp;
+ src++;
+ cnt -= 2;
+ }
+}
+
+static void FILTER2 () {
+ static int cnt = 0;
+ static s16 *lutt6;
+ static s16 *lutt5;
+
+ u32 addy = inst2&0xFFFFFF;
+
+ u8 *save = (u8*)PageRAM2(addy&0xFFFFFF); //+RDRAM
+ u8 t4 = (u8)((inst1 >> 0x10) & 0xFF);
+ int x;
+
+ if (t4 > 1) { // Then set the cnt variable
+ cnt = (inst1 & 0xFFFF);
+ lutt6 = (s16 *)PageRAM2(addy&0xFFFFFF);
+// memcpy (dmem+0xFE0, rsp.RDRAM+(inst2&0xFFFFFF), 0x10);
+ return;
+ }
+
+ if (t4 == 0) {
+// memcpy (dmem+0xFB0, rsp.RDRAM+(inst2&0xFFFFFF), 0x20);
+ lutt5 = (short *)PageRAM2((addy+0x10)&0xFFFFFF);
+ }
+
+ lutt5 = (short *)PageRAM2((addy+0x10)&0xFFFFFF);
+
+// lutt5 = (short *)(dmem + 0xFC0);
+// lutt6 = (short *)(dmem + 0xFE0);
+ for (x = 0; x < 8; x++) {
+ s32 a;
+ a = (lutt5[x] + lutt6[x]) >> 1;
+ lutt5[x] = lutt6[x] = (short)a;
+ }
+ short *inp1, *inp2;
+ s32 out1[8];
+ s16 outbuff[0x3c0], *outp;
+ u32 inPtr = (u32)(inst1&0xffff);
+ outp = outbuff;
+ inp1 = (short *)(save);
+ inp2 = (short *)(BufferSpace+inPtr);
+
+ for (x = 0; x < cnt; x+=0x10) {
+ out1[1] = inp1[0]*lutt6[6];
+ out1[1] += inp1[3]*lutt6[7];
+ out1[1] += inp1[2]*lutt6[4];
+ out1[1] += inp1[5]*lutt6[5];
+ out1[1] += inp1[4]*lutt6[2];
+ out1[1] += inp1[7]*lutt6[3];
+ out1[1] += inp1[6]*lutt6[0];
+ out1[1] += inp2[1]*lutt6[1]; // 1
+
+ out1[0] = inp1[3]*lutt6[6];
+ out1[0] += inp1[2]*lutt6[7];
+ out1[0] += inp1[5]*lutt6[4];
+ out1[0] += inp1[4]*lutt6[5];
+ out1[0] += inp1[7]*lutt6[2];
+ out1[0] += inp1[6]*lutt6[3];
+ out1[0] += inp2[1]*lutt6[0];
+ out1[0] += inp2[0]*lutt6[1];
+
+ out1[3] = inp1[2]*lutt6[6];
+ out1[3] += inp1[5]*lutt6[7];
+ out1[3] += inp1[4]*lutt6[4];
+ out1[3] += inp1[7]*lutt6[5];
+ out1[3] += inp1[6]*lutt6[2];
+ out1[3] += inp2[1]*lutt6[3];
+ out1[3] += inp2[0]*lutt6[0];
+ out1[3] += inp2[3]*lutt6[1];
+
+ out1[2] = inp1[5]*lutt6[6];
+ out1[2] += inp1[4]*lutt6[7];
+ out1[2] += inp1[7]*lutt6[4];
+ out1[2] += inp1[6]*lutt6[5];
+ out1[2] += inp2[1]*lutt6[2];
+ out1[2] += inp2[0]*lutt6[3];
+ out1[2] += inp2[3]*lutt6[0];
+ out1[2] += inp2[2]*lutt6[1];
+
+ out1[5] = inp1[4]*lutt6[6];
+ out1[5] += inp1[7]*lutt6[7];
+ out1[5] += inp1[6]*lutt6[4];
+ out1[5] += inp2[1]*lutt6[5];
+ out1[5] += inp2[0]*lutt6[2];
+ out1[5] += inp2[3]*lutt6[3];
+ out1[5] += inp2[2]*lutt6[0];
+ out1[5] += inp2[5]*lutt6[1];
+
+ out1[4] = inp1[7]*lutt6[6];
+ out1[4] += inp1[6]*lutt6[7];
+ out1[4] += inp2[1]*lutt6[4];
+ out1[4] += inp2[0]*lutt6[5];
+ out1[4] += inp2[3]*lutt6[2];
+ out1[4] += inp2[2]*lutt6[3];
+ out1[4] += inp2[5]*lutt6[0];
+ out1[4] += inp2[4]*lutt6[1];
+
+ out1[7] = inp1[6]*lutt6[6];
+ out1[7] += inp2[1]*lutt6[7];
+ out1[7] += inp2[0]*lutt6[4];
+ out1[7] += inp2[3]*lutt6[5];
+ out1[7] += inp2[2]*lutt6[2];
+ out1[7] += inp2[5]*lutt6[3];
+ out1[7] += inp2[4]*lutt6[0];
+ out1[7] += inp2[7]*lutt6[1];
+
+ out1[6] = inp2[1]*lutt6[6];
+ out1[6] += inp2[0]*lutt6[7];
+ out1[6] += inp2[3]*lutt6[4];
+ out1[6] += inp2[2]*lutt6[5];
+ out1[6] += inp2[5]*lutt6[2];
+ out1[6] += inp2[4]*lutt6[3];
+ out1[6] += inp2[7]*lutt6[0];
+ out1[6] += inp2[6]*lutt6[1];
+ outp[1] = /*CLAMP*/((out1[1]+0x4000) >> 0xF);
+ outp[0] = /*CLAMP*/((out1[0]+0x4000) >> 0xF);
+ outp[3] = /*CLAMP*/((out1[3]+0x4000) >> 0xF);
+ outp[2] = /*CLAMP*/((out1[2]+0x4000) >> 0xF);
+ outp[5] = /*CLAMP*/((out1[5]+0x4000) >> 0xF);
+ outp[4] = /*CLAMP*/((out1[4]+0x4000) >> 0xF);
+ outp[7] = /*CLAMP*/((out1[7]+0x4000) >> 0xF);
+ outp[6] = /*CLAMP*/((out1[6]+0x4000) >> 0xF);
+ inp1 = inp2;
+ inp2 += 8;
+ outp += 8;
+ }
+// memcpy (rsp.RDRAM+(inst2&0xFFFFFF), dmem+0xFB0, 0x20);
+ memcpy (save, inp2-8, 0x10);
+ memcpy (BufferSpace+(inst1&0xffff), outbuff, cnt);
+}
+
+static void SEGMENT2 () {
+ if (isZeldaABI) {
+ FILTER2 ();
+ return;
+ }
+ if ((inst1 & 0xffffff) == 0) {
+ isMKABI = true;
+ //SEGMENTS[(inst2>>24)&0xf] = (inst2 & 0xffffff);
+ } else {
+ isMKABI = false;
+ isZeldaABI = true;
+ FILTER2 ();
+ }
+}
+
+static void UNKNOWN () {
+}
+
+void (*ABI2[0x20])() = {
+ SPNOOP , ADPCM2, CLEARBUFF2, UNKNOWN, ADDMIXER, RESAMPLE2, UNKNOWN, SEGMENT2,
+ SETBUFF2 , DUPLICATE2, DMEMMOVE2, LOADADPCM2, MIXER2, INTERLEAVE2, HILOGAIN, SETLOOP2,
+ SPNOOP, INTERL2 , ENVSETUP1, ENVMIXER2, LOADBUFF2, SAVEBUFF2, ENVSETUP2, SPNOOP,
+ HILOGAIN , SPNOOP, DUPLICATE2 , UNKNOWN , SPNOOP , SPNOOP , SPNOOP , SPNOOP
+};
+
+/* NOTES:
+
+ FILTER/SEGMENT - Still needs to be finished up... add FILTER?
+ UNKNOWWN #27 - Is this worth doing? Looks like a pain in the ass just for WaveRace64
+*/
diff --git a/src/usf/audio_ucode3.c b/src/usf/audio_ucode3.c new file mode 100644 index 0000000..7611c59 --- /dev/null +++ b/src/usf/audio_ucode3.c @@ -0,0 +1,666 @@ +#include <stdio.h>
+#include <stdbool.h>
+#include "usf.h"
+#include "audio_hle.h"
+#include "memory.h"
+
+
+static void SPNOOP () {
+ //char buff[0x100];
+ //sprintf (buff, "Unknown/Unimplemented Audio Command %i in ABI 3", (int)(inst1 >> 24));
+ //printf( "Audio HLE Error: %s\n", buff );
+}
+
+extern u16 ResampleLUT [0x200];
+
+extern u32 loopval;
+
+extern s16 Env_Dry;
+extern s16 Env_Wet;
+extern s16 Vol_Left;
+extern s16 Vol_Right;
+extern s16 VolTrg_Left;
+extern s32 VolRamp_Left;
+//extern u16 VolRate_Left;
+extern s16 VolTrg_Right;
+extern s32 VolRamp_Right;
+//extern u16 VolRate_Right;
+
+
+extern short hleMixerWorkArea[256];
+extern u16 adpcmtable[0x88];
+
+extern u8 BufferSpace[0x10000];
+
+/*
+static void SETVOL3 () { // Swapped Rate_Left and Vol
+ u8 Flags = (u8)(inst1 >> 0x10);
+ if (Flags & 0x4) { // 288
+ if (Flags & 0x2) { // 290
+ VolTrg_Left = *(s16*)&inst1;
+ VolRamp_Left = *(s32*)&inst2;
+ } else {
+ VolTrg_Right = *(s16*)&inst1;
+ VolRamp_Right = *(s32*)&inst2;
+ }
+ } else {
+ Vol_Left = *(s16*)&inst1;
+ Env_Dry = (s16)(*(s32*)&inst2 >> 0x10);
+ Env_Wet = *(s16*)&inst2;
+ }
+}
+*/
+static void SETVOL3 () {
+ u8 Flags = (u8)(inst1 >> 0x10);
+ if (Flags & 0x4) { // 288
+ if (Flags & 0x2) { // 290
+ Vol_Left = *(s16*)&inst1; // 0x50
+ Env_Dry = (s16)(*(s32*)&inst2 >> 0x10); // 0x4E
+ Env_Wet = *(s16*)&inst2; // 0x4C
+ } else {
+ VolTrg_Right = *(s16*)&inst1; // 0x46
+ //VolRamp_Right = (u16)(inst2 >> 0x10) | (s32)(s16)(inst2 << 0x10);
+ VolRamp_Right = *(s32*)&inst2; // 0x48/0x4A
+ }
+ } else {
+ VolTrg_Left = *(s16*)&inst1; // 0x40
+ VolRamp_Left = *(s32*)&inst2; // 0x42/0x44
+ }
+}
+
+static void ENVMIXER3 () {
+ u8 flags;
+ u32 addy;
+
+ short *inp=(short *)(BufferSpace+0x4F0);
+ short *out=(short *)(BufferSpace+0x9D0);
+ short *aux1=(short *)(BufferSpace+0xB40);
+ short *aux2=(short *)(BufferSpace+0xCB0);
+ short *aux3=(short *)(BufferSpace+0xE20);
+ s32 MainR;
+ s32 MainL;
+ s32 AuxR;
+ s32 AuxL;
+
+ int i1,o1,a1,a2,a3,y;
+ //WORD AuxIncRate=1;
+ short zero[8];
+ memset(zero,0,16);
+
+ flags = (u8)((inst1 >> 16) & 0xff);
+ addy = (inst2 & 0xFFFFFF);
+
+ s32 LAdder, LAcc, LVol;
+ s32 RAdder, RAcc, RVol;
+ s16 RSig, LSig; // Most significant part of the Ramp Value
+ s16 Wet, Dry;
+ s16 LTrg, RTrg;
+
+
+ Vol_Right = (*(s16 *)&inst1);
+
+ if (flags & A_INIT) {
+ LAdder = VolRamp_Left / 8;
+ LAcc = 0;
+ LVol = Vol_Left;
+ LSig = (s16)(VolRamp_Left >> 16);
+
+ RAdder = VolRamp_Right / 8;
+ RAcc = 0;
+ RVol = Vol_Right;
+ RSig = (s16)(VolRamp_Right >> 16);
+
+ Wet = (s16)Env_Wet; Dry = (s16)Env_Dry; // Save Wet/Dry values
+ LTrg = VolTrg_Left; RTrg = VolTrg_Right; // Save Current Left/Right Targets
+ } else {
+ memcpy((u8 *)hleMixerWorkArea, N64MEM+addy, 80);
+ Wet = *(s16 *)(hleMixerWorkArea + 0); // 0-1
+ Dry = *(s16 *)(hleMixerWorkArea + 2); // 2-3
+ LTrg = *(s16 *)(hleMixerWorkArea + 4); // 4-5
+ RTrg = *(s16 *)(hleMixerWorkArea + 6); // 6-7
+ LAdder = *(s32 *)(hleMixerWorkArea + 8); // 8-9 (hleMixerWorkArea is a 16bit pointer)
+ RAdder = *(s32 *)(hleMixerWorkArea + 10); // 10-11
+ LAcc = *(s32 *)(hleMixerWorkArea + 12); // 12-13
+ RAcc = *(s32 *)(hleMixerWorkArea + 14); // 14-15
+ LVol = *(s32 *)(hleMixerWorkArea + 16); // 16-17
+ RVol = *(s32 *)(hleMixerWorkArea + 18); // 18-19
+ LSig = *(s16 *)(hleMixerWorkArea + 20); // 20-21
+ RSig = *(s16 *)(hleMixerWorkArea + 22); // 22-23
+ //u32 test = *(s32 *)(hleMixerWorkArea + 24); // 22-23
+ //if (test != 0x13371337)
+ // __asm int 3;
+ }
+
+
+ //if(!(flags&A_AUX)) {
+ // AuxIncRate=0;
+ // aux2=aux3=zero;
+ //}
+
+ for (y = 0; y < (0x170/2); y++) {
+
+ // Left
+ LAcc += LAdder;
+ LVol += (LAcc >> 16);
+ LAcc &= 0xFFFF;
+
+ // Right
+ RAcc += RAdder;
+ RVol += (RAcc >> 16);
+ RAcc &= 0xFFFF;
+// ****************************************************************
+ // Clamp Left
+ if (LSig >= 0) { // VLT
+ if (LVol > LTrg) {
+ LVol = LTrg;
+ }
+ } else { // VGE
+ if (LVol < LTrg) {
+ LVol = LTrg;
+ }
+ }
+
+ // Clamp Right
+ if (RSig >= 0) { // VLT
+ if (RVol > RTrg) {
+ RVol = RTrg;
+ }
+ } else { // VGE
+ if (RVol < RTrg) {
+ RVol = RTrg;
+ }
+ }
+// ****************************************************************
+ MainL = ((Dry * LVol) + 0x4000) >> 15;
+ MainR = ((Dry * RVol) + 0x4000) >> 15;
+
+ o1 = out [y^1];
+ a1 = aux1[y^1];
+ i1 = inp [y^1];
+
+ o1+=((i1*MainL)+0x4000)>>15;
+ a1+=((i1*MainR)+0x4000)>>15;
+
+// ****************************************************************
+
+ if(o1>32767) o1=32767;
+ else if(o1<-32768) o1=-32768;
+
+ if(a1>32767) a1=32767;
+ else if(a1<-32768) a1=-32768;
+
+// ****************************************************************
+
+ out[y^1]=o1;
+ aux1[y^1]=a1;
+
+// ****************************************************************
+ //if (!(flags&A_AUX)) {
+ a2 = aux2[y^1];
+ a3 = aux3[y^1];
+
+ AuxL = ((Wet * LVol) + 0x4000) >> 15;
+ AuxR = ((Wet * RVol) + 0x4000) >> 15;
+
+ a2+=((i1*AuxL)+0x4000)>>15;
+ a3+=((i1*AuxR)+0x4000)>>15;
+
+ if(a2>32767) a2=32767;
+ else if(a2<-32768) a2=-32768;
+
+ if(a3>32767) a3=32767;
+ else if(a3<-32768) a3=-32768;
+
+ aux2[y^1]=a2;
+ aux3[y^1]=a3;
+ }
+ //}
+
+ *(s16 *)(hleMixerWorkArea + 0) = Wet; // 0-1
+ *(s16 *)(hleMixerWorkArea + 2) = Dry; // 2-3
+ *(s16 *)(hleMixerWorkArea + 4) = LTrg; // 4-5
+ *(s16 *)(hleMixerWorkArea + 6) = RTrg; // 6-7
+ *(s32 *)(hleMixerWorkArea + 8) = LAdder; // 8-9 (hleMixerWorkArea is a 16bit pointer)
+ *(s32 *)(hleMixerWorkArea + 10) = RAdder; // 10-11
+ *(s32 *)(hleMixerWorkArea + 12) = LAcc; // 12-13
+ *(s32 *)(hleMixerWorkArea + 14) = RAcc; // 14-15
+ *(s32 *)(hleMixerWorkArea + 16) = LVol; // 16-17
+ *(s32 *)(hleMixerWorkArea + 18) = RVol; // 18-19
+ *(s16 *)(hleMixerWorkArea + 20) = LSig; // 20-21
+ *(s16 *)(hleMixerWorkArea + 22) = RSig; // 22-23
+ //*(u32 *)(hleMixerWorkArea + 24) = 0x13371337; // 22-23
+ memcpy(N64MEM+addy, (u8 *)hleMixerWorkArea,80);
+}
+
+static void CLEARBUFF3 () {
+ u16 addr = (u16)(inst1 & 0xffff);
+ u16 count = (u16)(inst2 & 0xffff);
+ memset(BufferSpace+addr+0x4f0, 0, count);
+}
+
+static void MIXER3 () { // Needs accuracy verification...
+ u16 dmemin = (u16)(inst2 >> 0x10) + 0x4f0;
+ u16 dmemout = (u16)(inst2 & 0xFFFF) + 0x4f0;
+ s32 gain = (s16)(inst1 & 0xFFFF)*2;
+ s32 temp;
+ int x;
+
+ for (x = 0; x < 0x170; x+=2) { // I think I can do this a lot easier
+ temp = (*(s16 *)(BufferSpace+dmemin+x) * gain) >> 16;
+ temp += *(s16 *)(BufferSpace+dmemout+x);
+
+ if ((s32)temp > 32767)
+ temp = 32767;
+ if ((s32)temp < -32768)
+ temp = -32768;
+
+ *(u16 *)(BufferSpace+dmemout+x) = (u16)(temp & 0xFFFF);
+ }
+}
+
+static void LOADBUFF3 () {
+ u32 v0;
+ u32 cnt = (((inst1 >> 0xC)+3)&0xFFC);
+ v0 = (inst2 & 0xfffffc);
+ u32 src = (inst1&0xffc)+0x4f0;
+ memcpy (BufferSpace+src, (u8 *)N64MEM+v0, cnt);
+}
+
+static void SAVEBUFF3 () {
+ u32 v0;
+ u32 cnt = (((inst1 >> 0xC)+3)&0xFFC);
+ v0 = (inst2 & 0xfffffc);
+ u32 src = (inst1&0xffc)+0x4f0;
+ memcpy (N64MEM+v0, (u8 *)BufferSpace+src, cnt);
+}
+
+static void LOADADPCM3 () { // Loads an ADPCM table - Works 100% Now 03-13-01
+ u32 v0, x;
+ v0 = (inst2 & 0xffffff);
+
+ u16 *table = (u16 *)(RDRAM+v0);
+ for (x = 0; x < ((inst1&0xffff)>>0x4); x++) {
+ adpcmtable[0x1+(x<<3)] = table[0];
+ adpcmtable[0x0+(x<<3)] = table[1];
+
+ adpcmtable[0x3+(x<<3)] = table[2];
+ adpcmtable[0x2+(x<<3)] = table[3];
+
+ adpcmtable[0x5+(x<<3)] = table[4];
+ adpcmtable[0x4+(x<<3)] = table[5];
+
+ adpcmtable[0x7+(x<<3)] = table[6];
+ adpcmtable[0x6+(x<<3)] = table[7];
+ table += 8;
+ }
+}
+
+static void DMEMMOVE3 () { // Needs accuracy verification...
+ u32 v0, v1;
+ u32 cnt;
+ v0 = (inst1 & 0xFFFF) + 0x4f0;
+ v1 = (inst2 >> 0x10) + 0x4f0;
+ u32 count = ((inst2+3) & 0xfffc);
+
+ for (cnt = 0; cnt < count; cnt++) {
+ *(u8 *)(BufferSpace+((cnt+v1)^3)) = *(u8 *)(BufferSpace+((cnt+v0)^3));
+ }
+}
+
+static void SETLOOP3 () {
+ loopval = (inst2 & 0xffffff);
+}
+
+static void ADPCM3 () { // Verified to be 100% Accurate...
+ short count = 0;
+ unsigned char icode, code, Flags;
+ int vscale, a[8];
+ unsigned short index, j, inPtr;
+ short *book1,*book2,*out;
+ unsigned int Address;
+
+ Flags=(u8)(inst2>>0x1c)&0xff;
+ Address=(inst1 & 0xffffff);
+ inPtr=(inst2>>12)&0xf;
+
+ out=(short *)(BufferSpace+(inst2&0xfff)+0x4f0);
+ count=(short)((inst2 >> 16)&0xfff);
+
+
+ memset(out,0,32);
+
+ if(!(Flags&0x1))
+ {
+ if(Flags&0x2)
+ {
+ memcpy(out,&RDRAM[loopval],32);
+ }
+ else
+ {
+ memcpy(out,&RDRAM[Address],32);
+ }
+ }
+
+ int l1=out[15];
+ int l2=out[14];
+ int inp1[8];
+ int inp2[8];
+ out+=16;
+ while(count>0)
+ {
+ // the first interation through, these values are
+ // either 0 in the case of A_INIT, from a special
+ // area of memory in the case of A_LOOP or just
+ // the values we calculated the last time
+
+ code=BufferSpace[(0x4f0+inPtr)^3];
+ index=code&0xf;
+ index<<=4; // index into the adpcm code table
+ book1=(short *)&adpcmtable[index];
+ book2=book1+8;
+ code>>=4; // upper nibble is scale
+ vscale=(0x8000>>((12-code)-1)); // very strange. 0x8000 would be .5 in 16:16 format
+ // so this appears to be a fractional scale based
+ // on the 12 based inverse of the scale value. note
+ // that this could be negative, in which case we do
+ // not use the calculated vscale value... see the
+ // if(code>12) check below
+
+ inPtr++; // coded adpcm data lies next
+ j=0;
+ while(j<8) // loop of 8, for 8 coded nibbles from 4 bytes
+ // which yields 8 short pcm values
+ {
+ icode=BufferSpace[(0x4f0+inPtr)^3];
+ inPtr++;
+
+ inp1[j]=(s16)((icode&0xf0)<<8); // this will in effect be signed
+ if(code<12)
+ inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16);
+ j++;
+
+ inp1[j]=(s16)((icode&0xf)<<12);
+ if(code<12)
+ inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16);
+ j++;
+ }
+ j=0;
+ while(j<8)
+ {
+ icode=BufferSpace[(0x4f0+inPtr)^3];
+ inPtr++;
+
+ inp2[j]=(short)((icode&0xf0)<<8); // this will in effect be signed
+ if(code<12)
+ inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16);
+ j++;
+
+ inp2[j]=(short)((icode&0xf)<<12);
+ if(code<12)
+ inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16);
+ j++;
+ }
+
+ a[0]= (int)book1[0]*(int)l1;
+ a[0]+=(int)book2[0]*(int)l2;
+ a[0]+=(int)inp1[0]*(int)2048;
+
+ a[1] =(int)book1[1]*(int)l1;
+ a[1]+=(int)book2[1]*(int)l2;
+ a[1]+=(int)book2[0]*inp1[0];
+ a[1]+=(int)inp1[1]*(int)2048;
+
+ a[2] =(int)book1[2]*(int)l1;
+ a[2]+=(int)book2[2]*(int)l2;
+ a[2]+=(int)book2[1]*inp1[0];
+ a[2]+=(int)book2[0]*inp1[1];
+ a[2]+=(int)inp1[2]*(int)2048;
+
+ a[3] =(int)book1[3]*(int)l1;
+ a[3]+=(int)book2[3]*(int)l2;
+ a[3]+=(int)book2[2]*inp1[0];
+ a[3]+=(int)book2[1]*inp1[1];
+ a[3]+=(int)book2[0]*inp1[2];
+ a[3]+=(int)inp1[3]*(int)2048;
+
+ a[4] =(int)book1[4]*(int)l1;
+ a[4]+=(int)book2[4]*(int)l2;
+ a[4]+=(int)book2[3]*inp1[0];
+ a[4]+=(int)book2[2]*inp1[1];
+ a[4]+=(int)book2[1]*inp1[2];
+ a[4]+=(int)book2[0]*inp1[3];
+ a[4]+=(int)inp1[4]*(int)2048;
+
+ a[5] =(int)book1[5]*(int)l1;
+ a[5]+=(int)book2[5]*(int)l2;
+ a[5]+=(int)book2[4]*inp1[0];
+ a[5]+=(int)book2[3]*inp1[1];
+ a[5]+=(int)book2[2]*inp1[2];
+ a[5]+=(int)book2[1]*inp1[3];
+ a[5]+=(int)book2[0]*inp1[4];
+ a[5]+=(int)inp1[5]*(int)2048;
+
+ a[6] =(int)book1[6]*(int)l1;
+ a[6]+=(int)book2[6]*(int)l2;
+ a[6]+=(int)book2[5]*inp1[0];
+ a[6]+=(int)book2[4]*inp1[1];
+ a[6]+=(int)book2[3]*inp1[2];
+ a[6]+=(int)book2[2]*inp1[3];
+ a[6]+=(int)book2[1]*inp1[4];
+ a[6]+=(int)book2[0]*inp1[5];
+ a[6]+=(int)inp1[6]*(int)2048;
+
+ a[7] =(int)book1[7]*(int)l1;
+ a[7]+=(int)book2[7]*(int)l2;
+ a[7]+=(int)book2[6]*inp1[0];
+ a[7]+=(int)book2[5]*inp1[1];
+ a[7]+=(int)book2[4]*inp1[2];
+ a[7]+=(int)book2[3]*inp1[3];
+ a[7]+=(int)book2[2]*inp1[4];
+ a[7]+=(int)book2[1]*inp1[5];
+ a[7]+=(int)book2[0]*inp1[6];
+ a[7]+=(int)inp1[7]*(int)2048;
+
+ for(j=0;j<8;j++)
+ {
+ a[j^1]>>=11;
+ if(a[j^1]>32767) a[j^1]=32767;
+ else if(a[j^1]<-32768) a[j^1]=-32768;
+ *(out++)=a[j^1];
+ }
+
+ l1=a[6];
+ l2=a[7];
+
+ a[0]= (int)book1[0]*(int)l1;
+ a[0]+=(int)book2[0]*(int)l2;
+ a[0]+=(int)inp2[0]*(int)2048;
+
+ a[1] =(int)book1[1]*(int)l1;
+ a[1]+=(int)book2[1]*(int)l2;
+ a[1]+=(int)book2[0]*inp2[0];
+ a[1]+=(int)inp2[1]*(int)2048;
+
+ a[2] =(int)book1[2]*(int)l1;
+ a[2]+=(int)book2[2]*(int)l2;
+ a[2]+=(int)book2[1]*inp2[0];
+ a[2]+=(int)book2[0]*inp2[1];
+ a[2]+=(int)inp2[2]*(int)2048;
+
+ a[3] =(int)book1[3]*(int)l1;
+ a[3]+=(int)book2[3]*(int)l2;
+ a[3]+=(int)book2[2]*inp2[0];
+ a[3]+=(int)book2[1]*inp2[1];
+ a[3]+=(int)book2[0]*inp2[2];
+ a[3]+=(int)inp2[3]*(int)2048;
+
+ a[4] =(int)book1[4]*(int)l1;
+ a[4]+=(int)book2[4]*(int)l2;
+ a[4]+=(int)book2[3]*inp2[0];
+ a[4]+=(int)book2[2]*inp2[1];
+ a[4]+=(int)book2[1]*inp2[2];
+ a[4]+=(int)book2[0]*inp2[3];
+ a[4]+=(int)inp2[4]*(int)2048;
+
+ a[5] =(int)book1[5]*(int)l1;
+ a[5]+=(int)book2[5]*(int)l2;
+ a[5]+=(int)book2[4]*inp2[0];
+ a[5]+=(int)book2[3]*inp2[1];
+ a[5]+=(int)book2[2]*inp2[2];
+ a[5]+=(int)book2[1]*inp2[3];
+ a[5]+=(int)book2[0]*inp2[4];
+ a[5]+=(int)inp2[5]*(int)2048;
+
+ a[6] =(int)book1[6]*(int)l1;
+ a[6]+=(int)book2[6]*(int)l2;
+ a[6]+=(int)book2[5]*inp2[0];
+ a[6]+=(int)book2[4]*inp2[1];
+ a[6]+=(int)book2[3]*inp2[2];
+ a[6]+=(int)book2[2]*inp2[3];
+ a[6]+=(int)book2[1]*inp2[4];
+ a[6]+=(int)book2[0]*inp2[5];
+ a[6]+=(int)inp2[6]*(int)2048;
+
+ a[7] =(int)book1[7]*(int)l1;
+ a[7]+=(int)book2[7]*(int)l2;
+ a[7]+=(int)book2[6]*inp2[0];
+ a[7]+=(int)book2[5]*inp2[1];
+ a[7]+=(int)book2[4]*inp2[2];
+ a[7]+=(int)book2[3]*inp2[3];
+ a[7]+=(int)book2[2]*inp2[4];
+ a[7]+=(int)book2[1]*inp2[5];
+ a[7]+=(int)book2[0]*inp2[6];
+ a[7]+=(int)inp2[7]*(int)2048;
+
+ for(j=0;j<8;j++)
+ {
+ a[j^1]>>=11;
+ if(a[j^1]>32767) a[j^1]=32767;
+ else if(a[j^1]<-32768) a[j^1]=-32768;
+ *(out++)=a[j^1];
+ }
+ l1=a[6];
+ l2=a[7];
+
+ count-=32;
+ }
+ out-=16;
+ memcpy(&RDRAM[Address],out,32);
+}
+
+static void RESAMPLE3 () {
+ s32 temp;
+ s32 accum;
+ s16 *lut;
+ short *dst;
+ s16 *src;
+ unsigned char Flags;
+ u32 dstPtr, srcPtr, x, addy, Pitch, location, Accum, i;
+ Flags=(u8)((inst2>>0x1e));
+ Pitch=((inst2>>0xe)&0xffff)<<1;
+ addy = (inst1 & 0xffffff);
+ Accum=0;
+ dst=(short *)(BufferSpace);
+ src=(s16 *)(BufferSpace);
+ srcPtr=((((inst2>>2)&0xfff)+0x4f0)/2);
+
+ srcPtr -= 4;
+
+ if (inst2 & 0x3) {
+ dstPtr = 0x660/2;
+ } else {
+ dstPtr = 0x4f0/2;
+ }
+
+ if ((Flags & 0x1) == 0) {
+ for (x=0; x < 4; x++) //memcpy (src+srcPtr, rsp.RDRAM+addy, 0x8);
+ src[(srcPtr+x)^1] = ((u16 *)RDRAM)[((addy/2)+x)^1];
+ Accum = *(u16 *)(RDRAM+addy+10);
+ } else {
+ for (x=0; x < 4; x++)
+ src[(srcPtr+x)^1] = 0;//*(u16 *)(rsp.RDRAM+((addy+x)^2));
+ }
+
+ //if ((Flags & 0x2))
+ // __asm int 3;
+
+ for(i=0;i < 0x170/2;i++) {
+ location = (((Accum * 0x40) >> 0x10) * 8);
+ //location = (Accum >> 0xa) << 0x3;
+ lut = (s16 *)(((u8 *)ResampleLUT) + location);
+
+ temp = ((s32)*(s16*)(src+((srcPtr+0)^1))*((s32)((s16)lut[0])));
+ accum = (s32)(temp >> 15);
+
+ temp = ((s32)*(s16*)(src+((srcPtr+1)^1))*((s32)((s16)lut[1])));
+ accum += (s32)(temp >> 15);
+
+ temp = ((s32)*(s16*)(src+((srcPtr+2)^1))*((s32)((s16)lut[2])));
+ accum += (s32)(temp >> 15);
+
+ temp = ((s32)*(s16*)(src+((srcPtr+3)^1))*((s32)((s16)lut[3])));
+ accum += (s32)(temp >> 15);
+
+ if (accum > 32767) accum = 32767;
+ if (accum < -32768) accum = -32768;
+
+ dst[dstPtr^1] = (accum);
+ dstPtr++;
+ Accum += Pitch;
+ srcPtr += (Accum>>16);
+ Accum&=0xffff;
+ }
+ for (x=0; x < 4; x++)
+ ((u16 *)RDRAM)[((addy/2)+x)^1] = src[(srcPtr+x)^1];
+ *(u16 *)(RDRAM+addy+10) = Accum;
+}
+
+static void INTERLEAVE3 () { // Needs accuracy verification...
+ //u32 inL, inR;
+ int x = 0;
+ u16 *inSrcR;
+ u16 *inSrcL;
+ u16 Left, Right;
+
+ u16 *outbuff = (u16 *)(BufferSpace + 0x4f0);//(u16 *)(AudioOutBuffer+dmem);
+
+ inSrcR = (u16 *)(BufferSpace+0xb40);
+ inSrcL = (u16 *)(BufferSpace+0x9d0);
+
+ for (x = 0; x < (0x170/4); x++) {
+ Left=*(inSrcL++);
+ Right=*(inSrcR++);
+
+ *(outbuff++)=*(inSrcR++);
+ *(outbuff++)=*(inSrcL++);
+ *(outbuff++)=(u16)Right;
+ *(outbuff++)=(u16)Left;
+ }
+}
+
+static void WHATISTHIS () {
+}
+
+u32 setaddr;
+static void MP3ADDY () {
+ setaddr = (inst2 & 0xffffff);
+}
+
+void rsp_run();
+void mp3setup (unsigned int inst1, unsigned int inst2, unsigned int t8);
+
+extern u32 base, dmembase;
+extern char *pDMEM;
+
+void MP3 ();
+
+static void DISABLE () {
+}
+
+
+void (*ABI3[0x20])() = {
+ DISABLE , ADPCM3 , CLEARBUFF3, ENVMIXER3 , LOADBUFF3, RESAMPLE3 , SAVEBUFF3, MP3,
+ MP3ADDY, SETVOL3, DMEMMOVE3 , LOADADPCM3 , MIXER3 , INTERLEAVE3, WHATISTHIS , SETLOOP3,
+ SPNOOP , SPNOOP, SPNOOP , SPNOOP , SPNOOP , SPNOOP , SPNOOP , SPNOOP,
+ SPNOOP , SPNOOP, SPNOOP , SPNOOP , SPNOOP , SPNOOP , SPNOOP , SPNOOP
+};
diff --git a/src/usf/audio_ucode3mp3.c b/src/usf/audio_ucode3mp3.c new file mode 100644 index 0000000..72d2e45 --- /dev/null +++ b/src/usf/audio_ucode3mp3.c @@ -0,0 +1,588 @@ +#include <stdio.h>
+#include "usf.h"
+#include "audio_hle.h"
+#include "memory.h"
+
+
+
+static u16 DeWindowLUT [0x420] = {
+ 0x0000, 0xFFF3, 0x005D, 0xFF38, 0x037A, 0xF736, 0x0B37, 0xC00E,
+ 0x7FFF, 0x3FF2, 0x0B37, 0x08CA, 0x037A, 0x00C8, 0x005D, 0x000D,
+ 0x0000, 0xFFF3, 0x005D, 0xFF38, 0x037A, 0xF736, 0x0B37, 0xC00E,
+ 0x7FFF, 0x3FF2, 0x0B37, 0x08CA, 0x037A, 0x00C8, 0x005D, 0x000D,
+ 0x0000, 0xFFF2, 0x005F, 0xFF1D, 0x0369, 0xF697, 0x0A2A, 0xBCE7,
+ 0x7FEB, 0x3CCB, 0x0C2B, 0x082B, 0x0385, 0x00AF, 0x005B, 0x000B,
+ 0x0000, 0xFFF2, 0x005F, 0xFF1D, 0x0369, 0xF697, 0x0A2A, 0xBCE7,
+ 0x7FEB, 0x3CCB, 0x0C2B, 0x082B, 0x0385, 0x00AF, 0x005B, 0x000B,
+ 0x0000, 0xFFF1, 0x0061, 0xFF02, 0x0354, 0xF5F9, 0x0905, 0xB9C4,
+ 0x7FB0, 0x39A4, 0x0D08, 0x078C, 0x038C, 0x0098, 0x0058, 0x000A,
+ 0x0000, 0xFFF1, 0x0061, 0xFF02, 0x0354, 0xF5F9, 0x0905, 0xB9C4,
+ 0x7FB0, 0x39A4, 0x0D08, 0x078C, 0x038C, 0x0098, 0x0058, 0x000A,
+ 0x0000, 0xFFEF, 0x0062, 0xFEE6, 0x033B, 0xF55C, 0x07C8, 0xB6A4,
+ 0x7F4D, 0x367E, 0x0DCE, 0x06EE, 0x038F, 0x0080, 0x0056, 0x0009,
+ 0x0000, 0xFFEF, 0x0062, 0xFEE6, 0x033B, 0xF55C, 0x07C8, 0xB6A4,
+ 0x7F4D, 0x367E, 0x0DCE, 0x06EE, 0x038F, 0x0080, 0x0056, 0x0009,
+ 0x0000, 0xFFEE, 0x0063, 0xFECA, 0x031C, 0xF4C3, 0x0671, 0xB38C,
+ 0x7EC2, 0x335D, 0x0E7C, 0x0652, 0x038E, 0x006B, 0x0053, 0x0008,
+ 0x0000, 0xFFEE, 0x0063, 0xFECA, 0x031C, 0xF4C3, 0x0671, 0xB38C,
+ 0x7EC2, 0x335D, 0x0E7C, 0x0652, 0x038E, 0x006B, 0x0053, 0x0008,
+ 0x0000, 0xFFEC, 0x0064, 0xFEAC, 0x02F7, 0xF42C, 0x0502, 0xB07C,
+ 0x7E12, 0x3041, 0x0F14, 0x05B7, 0x038A, 0x0056, 0x0050, 0x0007,
+ 0x0000, 0xFFEC, 0x0064, 0xFEAC, 0x02F7, 0xF42C, 0x0502, 0xB07C,
+ 0x7E12, 0x3041, 0x0F14, 0x05B7, 0x038A, 0x0056, 0x0050, 0x0007,
+ 0x0000, 0xFFEB, 0x0064, 0xFE8E, 0x02CE, 0xF399, 0x037A, 0xAD75,
+ 0x7D3A, 0x2D2C, 0x0F97, 0x0520, 0x0382, 0x0043, 0x004D, 0x0007,
+ 0x0000, 0xFFEB, 0x0064, 0xFE8E, 0x02CE, 0xF399, 0x037A, 0xAD75,
+ 0x7D3A, 0x2D2C, 0x0F97, 0x0520, 0x0382, 0x0043, 0x004D, 0x0007,
+ 0xFFFF, 0xFFE9, 0x0063, 0xFE6F, 0x029E, 0xF30B, 0x01D8, 0xAA7B,
+ 0x7C3D, 0x2A1F, 0x1004, 0x048B, 0x0377, 0x0030, 0x004A, 0x0006,
+ 0xFFFF, 0xFFE9, 0x0063, 0xFE6F, 0x029E, 0xF30B, 0x01D8, 0xAA7B,
+ 0x7C3D, 0x2A1F, 0x1004, 0x048B, 0x0377, 0x0030, 0x004A, 0x0006,
+ 0xFFFF, 0xFFE7, 0x0062, 0xFE4F, 0x0269, 0xF282, 0x001F, 0xA78D,
+ 0x7B1A, 0x271C, 0x105D, 0x03F9, 0x036A, 0x001F, 0x0046, 0x0006,
+ 0xFFFF, 0xFFE7, 0x0062, 0xFE4F, 0x0269, 0xF282, 0x001F, 0xA78D,
+ 0x7B1A, 0x271C, 0x105D, 0x03F9, 0x036A, 0x001F, 0x0046, 0x0006,
+ 0xFFFF, 0xFFE4, 0x0061, 0xFE2F, 0x022F, 0xF1FF, 0xFE4C, 0xA4AF,
+ 0x79D3, 0x2425, 0x10A2, 0x036C, 0x0359, 0x0010, 0x0043, 0x0005,
+ 0xFFFF, 0xFFE4, 0x0061, 0xFE2F, 0x022F, 0xF1FF, 0xFE4C, 0xA4AF,
+ 0x79D3, 0x2425, 0x10A2, 0x036C, 0x0359, 0x0010, 0x0043, 0x0005,
+ 0xFFFF, 0xFFE2, 0x005E, 0xFE10, 0x01EE, 0xF184, 0xFC61, 0xA1E1,
+ 0x7869, 0x2139, 0x10D3, 0x02E3, 0x0346, 0x0001, 0x0040, 0x0004,
+ 0xFFFF, 0xFFE2, 0x005E, 0xFE10, 0x01EE, 0xF184, 0xFC61, 0xA1E1,
+ 0x7869, 0x2139, 0x10D3, 0x02E3, 0x0346, 0x0001, 0x0040, 0x0004,
+ 0xFFFF, 0xFFE0, 0x005B, 0xFDF0, 0x01A8, 0xF111, 0xFA5F, 0x9F27,
+ 0x76DB, 0x1E5C, 0x10F2, 0x025E, 0x0331, 0xFFF3, 0x003D, 0x0004,
+ 0xFFFF, 0xFFE0, 0x005B, 0xFDF0, 0x01A8, 0xF111, 0xFA5F, 0x9F27,
+ 0x76DB, 0x1E5C, 0x10F2, 0x025E, 0x0331, 0xFFF3, 0x003D, 0x0004,
+ 0xFFFF, 0xFFDE, 0x0057, 0xFDD0, 0x015B, 0xF0A7, 0xF845, 0x9C80,
+ 0x752C, 0x1B8E, 0x1100, 0x01DE, 0x0319, 0xFFE7, 0x003A, 0x0003,
+ 0xFFFF, 0xFFDE, 0x0057, 0xFDD0, 0x015B, 0xF0A7, 0xF845, 0x9C80,
+ 0x752C, 0x1B8E, 0x1100, 0x01DE, 0x0319, 0xFFE7, 0x003A, 0x0003,
+ 0xFFFE, 0xFFDB, 0x0053, 0xFDB0, 0x0108, 0xF046, 0xF613, 0x99EE,
+ 0x735C, 0x18D1, 0x10FD, 0x0163, 0x0300, 0xFFDC, 0x0037, 0x0003,
+ 0xFFFE, 0xFFDB, 0x0053, 0xFDB0, 0x0108, 0xF046, 0xF613, 0x99EE,
+ 0x735C, 0x18D1, 0x10FD, 0x0163, 0x0300, 0xFFDC, 0x0037, 0x0003,
+ 0xFFFE, 0xFFD8, 0x004D, 0xFD90, 0x00B0, 0xEFF0, 0xF3CC, 0x9775,
+ 0x716C, 0x1624, 0x10EA, 0x00EE, 0x02E5, 0xFFD2, 0x0033, 0x0003,
+ 0xFFFE, 0xFFD8, 0x004D, 0xFD90, 0x00B0, 0xEFF0, 0xF3CC, 0x9775,
+ 0x716C, 0x1624, 0x10EA, 0x00EE, 0x02E5, 0xFFD2, 0x0033, 0x0003,
+ 0xFFFE, 0xFFD6, 0x0047, 0xFD72, 0x0051, 0xEFA6, 0xF16F, 0x9514,
+ 0x6F5E, 0x138A, 0x10C8, 0x007E, 0x02CA, 0xFFC9, 0x0030, 0x0003,
+ 0xFFFE, 0xFFD6, 0x0047, 0xFD72, 0x0051, 0xEFA6, 0xF16F, 0x9514,
+ 0x6F5E, 0x138A, 0x10C8, 0x007E, 0x02CA, 0xFFC9, 0x0030, 0x0003,
+ 0xFFFE, 0xFFD3, 0x0040, 0xFD54, 0xFFEC, 0xEF68, 0xEEFC, 0x92CD,
+ 0x6D33, 0x1104, 0x1098, 0x0014, 0x02AC, 0xFFC0, 0x002D, 0x0002,
+ 0xFFFE, 0xFFD3, 0x0040, 0xFD54, 0xFFEC, 0xEF68, 0xEEFC, 0x92CD,
+ 0x6D33, 0x1104, 0x1098, 0x0014, 0x02AC, 0xFFC0, 0x002D, 0x0002,
+ 0x0030, 0xFFC9, 0x02CA, 0x007E, 0x10C8, 0x138A, 0x6F5E, 0x9514,
+ 0xF16F, 0xEFA6, 0x0051, 0xFD72, 0x0047, 0xFFD6, 0xFFFE, 0x0003,
+ 0x0030, 0xFFC9, 0x02CA, 0x007E, 0x10C8, 0x138A, 0x6F5E, 0x9514,
+ 0xF16F, 0xEFA6, 0x0051, 0xFD72, 0x0047, 0xFFD6, 0xFFFE, 0x0003,
+ 0x0033, 0xFFD2, 0x02E5, 0x00EE, 0x10EA, 0x1624, 0x716C, 0x9775,
+ 0xF3CC, 0xEFF0, 0x00B0, 0xFD90, 0x004D, 0xFFD8, 0xFFFE, 0x0003,
+ 0x0033, 0xFFD2, 0x02E5, 0x00EE, 0x10EA, 0x1624, 0x716C, 0x9775,
+ 0xF3CC, 0xEFF0, 0x00B0, 0xFD90, 0x004D, 0xFFD8, 0xFFFE, 0x0003,
+ 0x0037, 0xFFDC, 0x0300, 0x0163, 0x10FD, 0x18D1, 0x735C, 0x99EE,
+ 0xF613, 0xF046, 0x0108, 0xFDB0, 0x0053, 0xFFDB, 0xFFFE, 0x0003,
+ 0x0037, 0xFFDC, 0x0300, 0x0163, 0x10FD, 0x18D1, 0x735C, 0x99EE,
+ 0xF613, 0xF046, 0x0108, 0xFDB0, 0x0053, 0xFFDB, 0xFFFE, 0x0003,
+ 0x003A, 0xFFE7, 0x0319, 0x01DE, 0x1100, 0x1B8E, 0x752C, 0x9C80,
+ 0xF845, 0xF0A7, 0x015B, 0xFDD0, 0x0057, 0xFFDE, 0xFFFF, 0x0003,
+ 0x003A, 0xFFE7, 0x0319, 0x01DE, 0x1100, 0x1B8E, 0x752C, 0x9C80,
+ 0xF845, 0xF0A7, 0x015B, 0xFDD0, 0x0057, 0xFFDE, 0xFFFF, 0x0004,
+ 0x003D, 0xFFF3, 0x0331, 0x025E, 0x10F2, 0x1E5C, 0x76DB, 0x9F27,
+ 0xFA5F, 0xF111, 0x01A8, 0xFDF0, 0x005B, 0xFFE0, 0xFFFF, 0x0004,
+ 0x003D, 0xFFF3, 0x0331, 0x025E, 0x10F2, 0x1E5C, 0x76DB, 0x9F27,
+ 0xFA5F, 0xF111, 0x01A8, 0xFDF0, 0x005B, 0xFFE0, 0xFFFF, 0x0004,
+ 0x0040, 0x0001, 0x0346, 0x02E3, 0x10D3, 0x2139, 0x7869, 0xA1E1,
+ 0xFC61, 0xF184, 0x01EE, 0xFE10, 0x005E, 0xFFE2, 0xFFFF, 0x0004,
+ 0x0040, 0x0001, 0x0346, 0x02E3, 0x10D3, 0x2139, 0x7869, 0xA1E1,
+ 0xFC61, 0xF184, 0x01EE, 0xFE10, 0x005E, 0xFFE2, 0xFFFF, 0x0005,
+ 0x0043, 0x0010, 0x0359, 0x036C, 0x10A2, 0x2425, 0x79D3, 0xA4AF,
+ 0xFE4C, 0xF1FF, 0x022F, 0xFE2F, 0x0061, 0xFFE4, 0xFFFF, 0x0005,
+ 0x0043, 0x0010, 0x0359, 0x036C, 0x10A2, 0x2425, 0x79D3, 0xA4AF,
+ 0xFE4C, 0xF1FF, 0x022F, 0xFE2F, 0x0061, 0xFFE4, 0xFFFF, 0x0006,
+ 0x0046, 0x001F, 0x036A, 0x03F9, 0x105D, 0x271C, 0x7B1A, 0xA78D,
+ 0x001F, 0xF282, 0x0269, 0xFE4F, 0x0062, 0xFFE7, 0xFFFF, 0x0006,
+ 0x0046, 0x001F, 0x036A, 0x03F9, 0x105D, 0x271C, 0x7B1A, 0xA78D,
+ 0x001F, 0xF282, 0x0269, 0xFE4F, 0x0062, 0xFFE7, 0xFFFF, 0x0006,
+ 0x004A, 0x0030, 0x0377, 0x048B, 0x1004, 0x2A1F, 0x7C3D, 0xAA7B,
+ 0x01D8, 0xF30B, 0x029E, 0xFE6F, 0x0063, 0xFFE9, 0xFFFF, 0x0006,
+ 0x004A, 0x0030, 0x0377, 0x048B, 0x1004, 0x2A1F, 0x7C3D, 0xAA7B,
+ 0x01D8, 0xF30B, 0x029E, 0xFE6F, 0x0063, 0xFFE9, 0xFFFF, 0x0007,
+ 0x004D, 0x0043, 0x0382, 0x0520, 0x0F97, 0x2D2C, 0x7D3A, 0xAD75,
+ 0x037A, 0xF399, 0x02CE, 0xFE8E, 0x0064, 0xFFEB, 0x0000, 0x0007,
+ 0x004D, 0x0043, 0x0382, 0x0520, 0x0F97, 0x2D2C, 0x7D3A, 0xAD75,
+ 0x037A, 0xF399, 0x02CE, 0xFE8E, 0x0064, 0xFFEB, 0x0000, 0x0007,
+ 0x0050, 0x0056, 0x038A, 0x05B7, 0x0F14, 0x3041, 0x7E12, 0xB07C,
+ 0x0502, 0xF42C, 0x02F7, 0xFEAC, 0x0064, 0xFFEC, 0x0000, 0x0007,
+ 0x0050, 0x0056, 0x038A, 0x05B7, 0x0F14, 0x3041, 0x7E12, 0xB07C,
+ 0x0502, 0xF42C, 0x02F7, 0xFEAC, 0x0064, 0xFFEC, 0x0000, 0x0008,
+ 0x0053, 0x006B, 0x038E, 0x0652, 0x0E7C, 0x335D, 0x7EC2, 0xB38C,
+ 0x0671, 0xF4C3, 0x031C, 0xFECA, 0x0063, 0xFFEE, 0x0000, 0x0008,
+ 0x0053, 0x006B, 0x038E, 0x0652, 0x0E7C, 0x335D, 0x7EC2, 0xB38C,
+ 0x0671, 0xF4C3, 0x031C, 0xFECA, 0x0063, 0xFFEE, 0x0000, 0x0009,
+ 0x0056, 0x0080, 0x038F, 0x06EE, 0x0DCE, 0x367E, 0x7F4D, 0xB6A4,
+ 0x07C8, 0xF55C, 0x033B, 0xFEE6, 0x0062, 0xFFEF, 0x0000, 0x0009,
+ 0x0056, 0x0080, 0x038F, 0x06EE, 0x0DCE, 0x367E, 0x7F4D, 0xB6A4,
+ 0x07C8, 0xF55C, 0x033B, 0xFEE6, 0x0062, 0xFFEF, 0x0000, 0x000A,
+ 0x0058, 0x0098, 0x038C, 0x078C, 0x0D08, 0x39A4, 0x7FB0, 0xB9C4,
+ 0x0905, 0xF5F9, 0x0354, 0xFF02, 0x0061, 0xFFF1, 0x0000, 0x000A,
+ 0x0058, 0x0098, 0x038C, 0x078C, 0x0D08, 0x39A4, 0x7FB0, 0xB9C4,
+ 0x0905, 0xF5F9, 0x0354, 0xFF02, 0x0061, 0xFFF1, 0x0000, 0x000B,
+ 0x005B, 0x00AF, 0x0385, 0x082B, 0x0C2B, 0x3CCB, 0x7FEB, 0xBCE7,
+ 0x0A2A, 0xF697, 0x0369, 0xFF1D, 0x005F, 0xFFF2, 0x0000, 0x000B,
+ 0x005B, 0x00AF, 0x0385, 0x082B, 0x0C2B, 0x3CCB, 0x7FEB, 0xBCE7,
+ 0x0A2A, 0xF697, 0x0369, 0xFF1D, 0x005F, 0xFFF2, 0x0000, 0x000D,
+ 0x005D, 0x00C8, 0x037A, 0x08CA, 0x0B37, 0x3FF2, 0x7FFF, 0xC00E,
+ 0x0B37, 0xF736, 0x037A, 0xFF38, 0x005D, 0xFFF3, 0x0000, 0x000D,
+ 0x005D, 0x00C8, 0x037A, 0x08CA, 0x0B37, 0x3FF2, 0x7FFF, 0xC00E,
+ 0x0B37, 0xF736, 0x037A, 0xFF38, 0x005D, 0xFFF3, 0x0000, 0x0000
+};
+
+//static u16 myVector[32][8];
+
+static u8 mp3data[0x1000];
+
+static s32 v[32];
+
+static void MP3AB0 () {
+ // Part 2 - 100% Accurate
+ const u16 LUT2[8] = { 0xFEC4, 0xF4FA, 0xC5E4, 0xE1C4,
+ 0x1916, 0x4A50, 0xA268, 0x78AE };
+ const u16 LUT3[4] = { 0xFB14, 0xD4DC, 0x31F2, 0x8E3A };
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ v[16+i] = v[0+i] + v[8+i];
+ v[24+i] = ((v[0+i] - v[8+i]) * LUT2[i]) >> 0x10;
+ }
+
+ // Part 3: 4-wide butterflies
+
+ for (i=0; i < 4; i++) {
+ v[0+i] = v[16+i] + v[20+i];
+ v[4+i] = ((v[16+i] - v[20+i]) * LUT3[i]) >> 0x10;
+
+ v[8+i] = v[24+i] + v[28+i];
+ v[12+i] = ((v[24+i] - v[28+i]) * LUT3[i]) >> 0x10;
+ }
+
+ // Part 4: 2-wide butterflies - 100% Accurate
+
+ for (i = 0; i < 16; i+=4) {
+ v[16+i] = v[0+i] + v[2+i];
+ v[18+i] = ((v[0+i] - v[2+i]) * 0xEC84) >> 0x10;
+
+ v[17+i] = v[1+i] + v[3+i];
+ v[19+i] = ((v[1+i] - v[3+i]) * 0x61F8) >> 0x10;
+ }
+}
+
+static void InnerLoop ();
+
+ u32 inPtr, outPtr;
+
+ u32 t6;// = 0x08A0; // I think these are temporary storage buffers
+ u32 t5;// = 0x0AC0;
+ u32 t4;// = (inst1 & 0x1E);
+
+void MP3 () {
+ // Initialization Code
+ u32 readPtr; // s5
+ u32 writePtr; // s6
+ //u32 Count = 0x0480; // s4
+ u32 tmp;
+ //u32 inPtr, outPtr;
+ int cnt, cnt2;
+
+ t6 = 0x08A0; // I think these are temporary storage buffers
+ t5 = 0x0AC0;
+ t4 = (inst1 & 0x1E);
+
+ writePtr = inst2 & 0xFFFFFF;
+ readPtr = writePtr;
+ memcpy (mp3data+0xCE8, N64MEM+(readPtr), 8); // Just do that for efficiency... may remove and use directly later anyway
+ readPtr += 8; // This must be a header byte or whatnot
+
+ for (cnt = 0; cnt < 0x480; cnt += 0x180) {
+ memcpy (mp3data+0xCF0, N64MEM+(readPtr), 0x180); // DMA: 0xCF0 <- RDRAM[s5] : 0x180
+ inPtr = 0xCF0; // s7
+ outPtr = 0xE70; // s3
+// --------------- Inner Loop Start --------------------
+ for (cnt2 = 0; cnt2 < 0x180; cnt2 += 0x40) {
+ t6 &= 0xFFE0;
+ t5 &= 0xFFE0;
+ t6 |= t4;
+ t5 |= t4;
+ InnerLoop ();
+ t4 = (t4-2)&0x1E;
+ tmp = t6;
+ t6 = t5;
+ t5 = tmp;
+ //outPtr += 0x40;
+ inPtr += 0x40;
+ }
+// --------------- Inner Loop End --------------------
+ memcpy ((u8*)N64MEM+writePtr, mp3data+0xe70, 0x180);
+ writePtr += 0x180;
+ readPtr += 0x180;
+ }
+}
+
+
+
+static void InnerLoop () {
+ // Part 1: 100% Accurate
+
+ int i;
+ v[0] = *(s16 *)(mp3data+inPtr+(0x00^2)); v[31] = *(s16 *)(mp3data+inPtr+(0x3E^2)); v[0] += v[31];
+ v[1] = *(s16 *)(mp3data+inPtr+(0x02^2)); v[30] = *(s16 *)(mp3data+inPtr+(0x3C^2)); v[1] += v[30];
+ v[2] = *(s16 *)(mp3data+inPtr+(0x06^2)); v[28] = *(s16 *)(mp3data+inPtr+(0x38^2)); v[2] += v[28];
+ v[3] = *(s16 *)(mp3data+inPtr+(0x04^2)); v[29] = *(s16 *)(mp3data+inPtr+(0x3A^2)); v[3] += v[29];
+
+ v[4] = *(s16 *)(mp3data+inPtr+(0x0E^2)); v[24] = *(s16 *)(mp3data+inPtr+(0x30^2)); v[4] += v[24];
+ v[5] = *(s16 *)(mp3data+inPtr+(0x0C^2)); v[25] = *(s16 *)(mp3data+inPtr+(0x32^2)); v[5] += v[25];
+ v[6] = *(s16 *)(mp3data+inPtr+(0x08^2)); v[27] = *(s16 *)(mp3data+inPtr+(0x36^2)); v[6] += v[27];
+ v[7] = *(s16 *)(mp3data+inPtr+(0x0A^2)); v[26] = *(s16 *)(mp3data+inPtr+(0x34^2)); v[7] += v[26];
+
+ v[8] = *(s16 *)(mp3data+inPtr+(0x1E^2)); v[16] = *(s16 *)(mp3data+inPtr+(0x20^2)); v[8] += v[16];
+ v[9] = *(s16 *)(mp3data+inPtr+(0x1C^2)); v[17] = *(s16 *)(mp3data+inPtr+(0x22^2)); v[9] += v[17];
+ v[10]= *(s16 *)(mp3data+inPtr+(0x18^2)); v[19] = *(s16 *)(mp3data+inPtr+(0x26^2)); v[10]+= v[19];
+ v[11]= *(s16 *)(mp3data+inPtr+(0x1A^2)); v[18] = *(s16 *)(mp3data+inPtr+(0x24^2)); v[11]+= v[18];
+
+ v[12]= *(s16 *)(mp3data+inPtr+(0x10^2)); v[23] = *(s16 *)(mp3data+inPtr+(0x2E^2)); v[12]+= v[23];
+ v[13]= *(s16 *)(mp3data+inPtr+(0x12^2)); v[22] = *(s16 *)(mp3data+inPtr+(0x2C^2)); v[13]+= v[22];
+ v[14]= *(s16 *)(mp3data+inPtr+(0x16^2)); v[20] = *(s16 *)(mp3data+inPtr+(0x28^2)); v[14]+= v[20];
+ v[15]= *(s16 *)(mp3data+inPtr+(0x14^2)); v[21] = *(s16 *)(mp3data+inPtr+(0x2A^2)); v[15]+= v[21];
+
+ // Part 2-4
+
+ MP3AB0 ();
+
+ // Part 5 - 1-Wide Butterflies - 100% Accurate but need SSVs!!!
+
+ u32 t0 = t6 + 0x100;
+ u32 t1 = t6 + 0x200;
+ u32 t2 = t5 + 0x100;
+ u32 t3 = t5 + 0x200;
+ /*RSP_GPR[0x8].W = t0;
+ RSP_GPR[0x9].W = t1;
+ RSP_GPR[0xA].W = t2;
+ RSP_GPR[0xB].W = t3;
+
+ RSP_Vect[0].DW[1] = 0xB504A57E00016A09;
+ RSP_Vect[0].DW[0] = 0x0002D4130005A827;
+*/
+ if ((t1 | t2 | t3 | t5 | t6) & 0x1)
+// __asm int 3;
+ do {} while (0);
+
+ // 0x13A8
+ v[1] = 0;
+ v[11] = ((v[16] - v[17]) * 0xB504) >> 0x10;
+
+ v[16] = -v[16] -v[17];
+ v[2] = v[18] + v[19];
+ // ** Store v[11] -> (T6 + 0)**
+ *(s16 *)(mp3data+((t6+(short)0x0))) = (short)v[11];
+
+
+ v[11] = -v[11];
+ // ** Store v[16] -> (T3 + 0)**
+ *(s16 *)(mp3data+((t3+(short)0x0))) = (short)v[16];
+ // ** Store v[11] -> (T5 + 0)**
+ *(s16 *)(mp3data+((t5+(short)0x0))) = (short)v[11];
+ // 0x13E8 - Verified....
+ v[2] = -v[2];
+ // ** Store v[2] -> (T2 + 0)**
+ *(s16 *)(mp3data+((t2+(short)0x0))) = (short)v[2];
+ v[3] = (((v[18] - v[19]) * 0x16A09) >> 0x10) + v[2];
+ // ** Store v[3] -> (T0 + 0)**
+ *(s16 *)(mp3data+((t0+(short)0x0))) = (short)v[3];
+ // 0x1400 - Verified
+ v[4] = -v[20] -v[21];
+ v[6] = v[22] + v[23];
+ v[5] = ((v[20] - v[21]) * 0x16A09) >> 0x10;
+ // ** Store v[4] -> (T3 + 0xFF80)
+ *(s16 *)(mp3data+((t3+(short)0xFF80))) = (short)v[4];
+ v[7] = ((v[22] - v[23]) * 0x2D413) >> 0x10;
+ v[5] = v[5] - v[4];
+ v[7] = v[7] - v[5];
+ v[6] = v[6] + v[6];
+ v[5] = v[5] - v[6];
+ v[4] = -v[4] - v[6];
+ // *** Store v[7] -> (T1 + 0xFF80)
+ *(s16 *)(mp3data+((t1+(short)0xFF80))) = (short)v[7];
+ // *** Store v[4] -> (T2 + 0xFF80)
+ *(s16 *)(mp3data+((t2+(short)0xFF80))) = (short)v[4];
+ // *** Store v[5] -> (T0 + 0xFF80)
+ *(s16 *)(mp3data+((t0+(short)0xFF80))) = (short)v[5];
+ v[8] = v[24] + v[25];
+
+
+ v[9] = ((v[24] - v[25]) * 0x16A09) >> 0x10;
+ v[2] = v[8] + v[9];
+ v[11] = ((v[26] - v[27]) * 0x2D413) >> 0x10;
+ v[13] = ((v[28] - v[29]) * 0x2D413) >> 0x10;
+
+ v[10] = v[26] + v[27]; v[10] = v[10] + v[10];
+ v[12] = v[28] + v[29]; v[12] = v[12] + v[12];
+ v[14] = v[30] + v[31];
+ v[3] = v[8] + v[10];
+ v[14] = v[14] + v[14];
+ v[13] = (v[13] - v[2]) + v[12];
+ v[15] = (((v[30] - v[31]) * 0x5A827) >> 0x10) - (v[11] + v[2]);
+ v[14] = -(v[14] + v[14]) + v[3];
+ v[17] = v[13] - v[10];
+ v[9] = v[9] + v[14];
+ // ** Store v[9] -> (T6 + 0x40)
+ *(s16 *)(mp3data+((t6+(short)0x40))) = (short)v[9];
+ v[11] = v[11] - v[13];
+ // ** Store v[17] -> (T0 + 0xFFC0)
+ *(s16 *)(mp3data+((t0+(short)0xFFC0))) = (short)v[17];
+ v[12] = v[8] - v[12];
+ // ** Store v[11] -> (T0 + 0x40)
+ *(s16 *)(mp3data+((t0+(short)0x40))) = (short)v[11];
+ v[8] = -v[8];
+ // ** Store v[15] -> (T1 + 0xFFC0)
+ *(s16 *)(mp3data+((t1+(short)0xFFC0))) = (short)v[15];
+ v[10] = -v[10] -v[12];
+ // ** Store v[12] -> (T2 + 0x40)
+ *(s16 *)(mp3data+((t2+(short)0x40))) = (short)v[12];
+ // ** Store v[8] -> (T3 + 0xFFC0)
+ *(s16 *)(mp3data+((t3+(short)0xFFC0))) = (short)v[8];
+ // ** Store v[14] -> (T5 + 0x40)
+ *(s16 *)(mp3data+((t5+(short)0x40))) = (short)v[14];
+ // ** Store v[10] -> (T2 + 0xFFC0)
+ *(s16 *)(mp3data+((t2+(short)0xFFC0))) = (short)v[10];
+ // 0x14FC - Verified...
+
+ // Part 6 - 100% Accurate
+
+ v[0] = *(s16 *)(mp3data+inPtr+(0x00^2)); v[31] = *(s16 *)(mp3data+inPtr+(0x3E^2)); v[0] -= v[31];
+ v[1] = *(s16 *)(mp3data+inPtr+(0x02^2)); v[30] = *(s16 *)(mp3data+inPtr+(0x3C^2)); v[1] -= v[30];
+ v[2] = *(s16 *)(mp3data+inPtr+(0x06^2)); v[28] = *(s16 *)(mp3data+inPtr+(0x38^2)); v[2] -= v[28];
+ v[3] = *(s16 *)(mp3data+inPtr+(0x04^2)); v[29] = *(s16 *)(mp3data+inPtr+(0x3A^2)); v[3] -= v[29];
+
+ v[4] = *(s16 *)(mp3data+inPtr+(0x0E^2)); v[24] = *(s16 *)(mp3data+inPtr+(0x30^2)); v[4] -= v[24];
+ v[5] = *(s16 *)(mp3data+inPtr+(0x0C^2)); v[25] = *(s16 *)(mp3data+inPtr+(0x32^2)); v[5] -= v[25];
+ v[6] = *(s16 *)(mp3data+inPtr+(0x08^2)); v[27] = *(s16 *)(mp3data+inPtr+(0x36^2)); v[6] -= v[27];
+ v[7] = *(s16 *)(mp3data+inPtr+(0x0A^2)); v[26] = *(s16 *)(mp3data+inPtr+(0x34^2)); v[7] -= v[26];
+
+ v[8] = *(s16 *)(mp3data+inPtr+(0x1E^2)); v[16] = *(s16 *)(mp3data+inPtr+(0x20^2)); v[8] -= v[16];
+ v[9] = *(s16 *)(mp3data+inPtr+(0x1C^2)); v[17] = *(s16 *)(mp3data+inPtr+(0x22^2)); v[9] -= v[17];
+ v[10]= *(s16 *)(mp3data+inPtr+(0x18^2)); v[19] = *(s16 *)(mp3data+inPtr+(0x26^2)); v[10]-= v[19];
+ v[11]= *(s16 *)(mp3data+inPtr+(0x1A^2)); v[18] = *(s16 *)(mp3data+inPtr+(0x24^2)); v[11]-= v[18];
+
+ v[12]= *(s16 *)(mp3data+inPtr+(0x10^2)); v[23] = *(s16 *)(mp3data+inPtr+(0x2E^2)); v[12]-= v[23];
+ v[13]= *(s16 *)(mp3data+inPtr+(0x12^2)); v[22] = *(s16 *)(mp3data+inPtr+(0x2C^2)); v[13]-= v[22];
+ v[14]= *(s16 *)(mp3data+inPtr+(0x16^2)); v[20] = *(s16 *)(mp3data+inPtr+(0x28^2)); v[14]-= v[20];
+ v[15]= *(s16 *)(mp3data+inPtr+(0x14^2)); v[21] = *(s16 *)(mp3data+inPtr+(0x2A^2)); v[15]-= v[21];
+
+ //0, 1, 3, 2, 7, 6, 4, 5, 7, 6, 4, 5, 0, 1, 3, 2
+ const u16 LUT6[16] = { 0xFFB2, 0xFD3A, 0xF10A, 0xF854,
+ 0xBDAE, 0xCDA0, 0xE76C, 0xDB94,
+ 0x1920, 0x4B20, 0xAC7C, 0x7C68,
+ 0xABEC, 0x9880, 0xDAE8, 0x839C };
+ for (i = 0; i < 16; i++) {
+ v[0+i] = (v[0+i] * LUT6[i]) >> 0x10;
+ }
+ v[0] = v[0] + v[0]; v[1] = v[1] + v[1];
+ v[2] = v[2] + v[2]; v[3] = v[3] + v[3]; v[4] = v[4] + v[4];
+ v[5] = v[5] + v[5]; v[6] = v[6] + v[6]; v[7] = v[7] + v[7];
+ v[12] = v[12] + v[12]; v[13] = v[13] + v[13]; v[15] = v[15] + v[15];
+
+ MP3AB0 ();
+
+ // Part 7: - 100% Accurate + SSV - Unoptimized
+
+ v[0] = ( v[17] + v[16] ) >> 1;
+ v[1] = ((v[17] * (int)((short)0xA57E * 2)) + (v[16] * 0xB504)) >> 0x10;
+ v[2] = -v[18] -v[19];
+ v[3] = ((v[18] - v[19]) * 0x16A09) >> 0x10;
+ v[4] = v[20] + v[21] + v[0];
+ v[5] = (((v[20] - v[21]) * 0x16A09) >> 0x10) + v[1];
+ v[6] = (((v[22] + v[23]) << 1) + v[0]) - v[2];
+ v[7] = (((v[22] - v[23]) * 0x2D413) >> 0x10) + v[0] + v[1] + v[3];
+ // 0x16A8
+ // Save v[0] -> (T3 + 0xFFE0)
+ *(s16 *)(mp3data+((t3+(short)0xFFE0))) = (short)-v[0];
+ v[8] = v[24] + v[25];
+ v[9] = ((v[24] - v[25]) * 0x16A09) >> 0x10;
+ v[10] = ((v[26] + v[27]) << 1) + v[8];
+ v[11] = (((v[26] - v[27]) * 0x2D413) >> 0x10) + v[8] + v[9];
+ v[12] = v[4] - ((v[28] + v[29]) << 1);
+ // ** Store v12 -> (T2 + 0x20)
+ *(s16 *)(mp3data+((t2+(short)0x20))) = (short)v[12];
+ v[13] = (((v[28] - v[29]) * 0x2D413) >> 0x10) - v[12] - v[5];
+ v[14] = v[30] + v[31];
+ v[14] = v[14] + v[14];
+ v[14] = v[14] + v[14];
+ v[14] = v[6] - v[14];
+ v[15] = (((v[30] - v[31]) * 0x5A827) >> 0x10) - v[7];
+ // Store v14 -> (T5 + 0x20)
+ *(s16 *)(mp3data+((t5+(short)0x20))) = (short)v[14];
+ v[14] = v[14] + v[1];
+ // Store v[14] -> (T6 + 0x20)
+ *(s16 *)(mp3data+((t6+(short)0x20))) = (short)v[14];
+ // Store v[15] -> (T1 + 0xFFE0)
+ *(s16 *)(mp3data+((t1+(short)0xFFE0))) = (short)v[15];
+ v[9] = v[9] + v[10];
+ v[1] = v[1] + v[6];
+ v[6] = v[10] - v[6];
+ v[1] = v[9] - v[1];
+ // Store v[6] -> (T5 + 0x60)
+ *(s16 *)(mp3data+((t5+(short)0x60))) = (short)v[6];
+ v[10] = v[10] + v[2];
+ v[10] = v[4] - v[10];
+ // Store v[10] -> (T2 + 0xFFA0)
+ *(s16 *)(mp3data+((t2+(short)0xFFA0))) = (short)v[10];
+ v[12] = v[2] - v[12];
+ // Store v[12] -> (T2 + 0xFFE0)
+ *(s16 *)(mp3data+((t2+(short)0xFFE0))) = (short)v[12];
+ v[5] = v[4] + v[5];
+ v[4] = v[8] - v[4];
+ // Store v[4] -> (T2 + 0x60)
+ *(s16 *)(mp3data+((t2+(short)0x60))) = (short)v[4];
+ v[0] = v[0] - v[8];
+ // Store v[0] -> (T3 + 0xFFA0)
+ *(s16 *)(mp3data+((t3+(short)0xFFA0))) = (short)v[0];
+ v[7] = v[7] - v[11];
+ // Store v[7] -> (T1 + 0xFFA0)
+ *(s16 *)(mp3data+((t1+(short)0xFFA0))) = (short)v[7];
+ v[11] = v[11] - v[3];
+ // Store v[1] -> (T6 + 0x60)
+ *(s16 *)(mp3data+((t6+(short)0x60))) = (short)v[1];
+ v[11] = v[11] - v[5];
+ // Store v[11] -> (T0 + 0x60)
+ *(s16 *)(mp3data+((t0+(short)0x60))) = (short)v[11];
+ v[3] = v[3] - v[13];
+ // Store v[3] -> (T0 + 0x20)
+ *(s16 *)(mp3data+((t0+(short)0x20))) = (short)v[3];
+ v[13] = v[13] + v[2];
+ // Store v[13] -> (T0 + 0xFFE0)
+ *(s16 *)(mp3data+((t0+(short)0xFFE0))) = (short)v[13];
+ //v[2] = ;
+ v[2] = (v[5] - v[2]) - v[9];
+ // Store v[2] -> (T0 + 0xFFA0)
+ *(s16 *)(mp3data+((t0+(short)0xFFA0))) = (short)v[2];
+ // 0x7A8 - Verified...
+
+ // Step 8 - Dewindowing
+
+ //u64 *DW = (u64 *)&DeWindowLUT[0x10-(t4>>1)];
+ u32 offset = 0x10-(t4>>1);
+
+ u32 addptr = t6 & 0xFFE0;
+ offset = 0x10-(t4>>1);
+
+ s32 v2=0, v4=0, v6=0, v8=0;
+ //s32 z2=0, z4=0, z6=0, z8=0;
+
+ offset = 0x10-(t4>>1);// + x*0x40;
+ int x;
+ for (x = 0; x < 8; x++) {
+ v2 = v4 = v6 = v8 = 0;
+
+ //addptr = t1;
+
+ for (i = 7; i >= 0; i--) {
+ v2 += ((int)*(s16 *)(mp3data+(addptr)+0x00) * (short)DeWindowLUT[offset+0x00] + 0x4000) >> 0xF;
+ v4 += ((int)*(s16 *)(mp3data+(addptr)+0x10) * (short)DeWindowLUT[offset+0x08] + 0x4000) >> 0xF;
+ v6 += ((int)*(s16 *)(mp3data+(addptr)+0x20) * (short)DeWindowLUT[offset+0x20] + 0x4000) >> 0xF;
+ v8 += ((int)*(s16 *)(mp3data+(addptr)+0x30) * (short)DeWindowLUT[offset+0x28] + 0x4000) >> 0xF;
+ addptr+=2; offset++;
+ }
+ s32 v0 = v2 + v4;
+ s32 v18 = v6 + v8;
+ //Clamp(v0);
+ //Clamp(v18);
+ // clamp???
+ *(s16 *)(mp3data+(outPtr^2)) = v0;
+ *(s16 *)(mp3data+((outPtr+2)^2)) = v18;
+ outPtr+=4;
+ addptr += 0x30;
+ offset += 0x38;
+ }
+
+ offset = 0x10-(t4>>1) + 8*0x40;
+ v2 = v4 = 0;
+ for (i = 0; i < 4; i++) {
+ v2 += ((int)*(s16 *)(mp3data+(addptr)+0x00) * (short)DeWindowLUT[offset+0x00] + 0x4000) >> 0xF;
+ v2 += ((int)*(s16 *)(mp3data+(addptr)+0x10) * (short)DeWindowLUT[offset+0x08] + 0x4000) >> 0xF;
+ addptr+=2; offset++;
+ v4 += ((int)*(s16 *)(mp3data+(addptr)+0x00) * (short)DeWindowLUT[offset+0x00] + 0x4000) >> 0xF;
+ v4 += ((int)*(s16 *)(mp3data+(addptr)+0x10) * (short)DeWindowLUT[offset+0x08] + 0x4000) >> 0xF;
+ addptr+=2; offset++;
+ }
+ s32 mult6 = *(s32 *)(mp3data+0xCE8);
+ s32 mult4 = *(s32 *)(mp3data+0xCEC);
+ if (t4 & 0x2) {
+ v2 = (v2 * *(u32 *)(mp3data+0xCE8)) >> 0x10;
+ *(s16 *)(mp3data+(outPtr^2)) = v2;
+ } else {
+ v4 = (v4 * *(u32 *)(mp3data+0xCE8)) >> 0x10;
+ *(s16 *)(mp3data+(outPtr^2)) = v4;
+ mult4 = *(u32 *)(mp3data+0xCE8);
+ }
+ addptr -= 0x50;
+
+ for (x = 0; x < 8; x++) {
+ v2 = v4 = v6 = v8 = 0;
+
+ offset = (0x22F-(t4>>1) + x*0x40);
+
+ for (i = 0; i < 4; i++) {
+ v2 += ((int)*(s16 *)(mp3data+(addptr )+0x20) * (short)DeWindowLUT[offset+0x00] + 0x4000) >> 0xF;
+ v2 -= ((int)*(s16 *)(mp3data+((addptr+2))+0x20) * (short)DeWindowLUT[offset+0x01] + 0x4000) >> 0xF;
+ v4 += ((int)*(s16 *)(mp3data+(addptr )+0x30) * (short)DeWindowLUT[offset+0x08] + 0x4000) >> 0xF;
+ v4 -= ((int)*(s16 *)(mp3data+((addptr+2))+0x30) * (short)DeWindowLUT[offset+0x09] + 0x4000) >> 0xF;
+ v6 += ((int)*(s16 *)(mp3data+(addptr )+0x00) * (short)DeWindowLUT[offset+0x20] + 0x4000) >> 0xF;
+ v6 -= ((int)*(s16 *)(mp3data+((addptr+2))+0x00) * (short)DeWindowLUT[offset+0x21] + 0x4000) >> 0xF;
+ v8 += ((int)*(s16 *)(mp3data+(addptr )+0x10) * (short)DeWindowLUT[offset+0x28] + 0x4000) >> 0xF;
+ v8 -= ((int)*(s16 *)(mp3data+((addptr+2))+0x10) * (short)DeWindowLUT[offset+0x29] + 0x4000) >> 0xF;
+ addptr+=4; offset+=2;
+ }
+ s32 v0 = v2 + v4;
+ s32 v18 = v6 + v8;
+ //Clamp(v0);
+ //Clamp(v18);
+ // clamp???
+ *(s16 *)(mp3data+((outPtr+2)^2)) = v0;
+ *(s16 *)(mp3data+((outPtr+4)^2)) = v18;
+ outPtr+=4;
+ addptr -= 0x50;
+ }
+
+ int tmp = outPtr;
+ s32 hi0 = mult6;
+ s32 hi1 = mult4;
+ s32 v;
+ /*
+ if (hi0 & 0xffff)
+ __asm int 3;
+ if (hi1 & 0xffff)
+ __asm int 3;*/
+ hi0 = (int)hi0 >> 0x10;
+ hi1 = (int)hi1 >> 0x10;
+ for (i = 0; i < 8; i++) {
+ // v0
+ v = (*(s16 *)(mp3data+((tmp-0x40)^2)) * hi0);
+ if (v > 32767) v = 32767; else if (v < -32767) v = -32767;
+ *(s16 *)((u8 *)mp3data+((tmp-0x40)^2)) = (s16)v;
+ // v17
+ v = (*(s16 *)(mp3data+((tmp-0x30)^2)) * hi0);
+ if (v > 32767) v = 32767; else if (v < -32767) v = -32767;
+ *(s16 *)((u8 *)mp3data+((tmp-0x30)^2)) = v;
+ // v2
+ v = (*(s16 *)(mp3data+((tmp-0x1E)^2)) * hi1);
+ if (v > 32767) v = 32767; else if (v < -32767) v = -32767;
+ *(s16 *)((u8 *)mp3data+((tmp-0x1E)^2)) = v;
+ // v4
+ v = (*(s16 *)(mp3data+((tmp-0xE)^2)) * hi1);
+ if (v > 32767) v = 32767; else if (v < -32767) v = -32767;
+ *(s16 *)((u8 *)mp3data+((tmp-0xE)^2)) = v;
+ tmp += 2;
+ }
+}
diff --git a/src/usf/config.h b/src/usf/config.h new file mode 100644 index 0000000..ab09878 --- /dev/null +++ b/src/usf/config.h @@ -0,0 +1,63 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Name of package */ +#define PACKAGE "lazyusf" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "lazyusf" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "lazyusf 1.0.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "lazyusf" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.0.0" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.0.0" + +/* Define to 1 if the X Window System is missing or not being used. */ +/* #undef X_DISPLAY_MISSING */ diff --git a/src/usf/cpu.c b/src/usf/cpu.c new file mode 100644 index 0000000..8cb4966 --- /dev/null +++ b/src/usf/cpu.c @@ -0,0 +1,640 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+
+#include <stdint.h>
+#include "main.h"
+#include "cpu.h"
+#include "usf.h"
+#include "audio.h"
+#include "audio_hle.h"
+#include "recompiler_cpu.h"
+#include "x86.h"
+#include "registers.h"
+#include "rsp.h"
+
+#include <audacious/plugin.h>
+
+#include <unistd.h>
+#include <pthread.h>
+#include <stdlib.h>
+extern InputPlayback * pcontext;
+extern GThread * decode_thread;
+
+uint32_t NextInstruction = 0, JumpToLocation = 0, AudioIntrReg = 0;
+CPU_ACTION * CPU_Action = 0;
+SYSTEM_TIMERS * Timers = 0;
+OPCODE Opcode;
+uint32_t CPURunning = 0, SPHack = 0;
+uint32_t * WaitMode = 0, CPU_Type = CPU_Recompiler;
+
+
+void ChangeCompareTimer(void) {
+ uint32_t NextCompare = COMPARE_REGISTER - COUNT_REGISTER;
+ if ((NextCompare & 0x80000000) != 0) { NextCompare = 0x7FFFFFFF; }
+ if (NextCompare == 0) { NextCompare = 0x1; }
+ ChangeTimer(CompareTimer,NextCompare);
+}
+
+void ChangeTimer(int32_t Type, int32_t Value) {
+ if (Value == 0) {
+ Timers->NextTimer[Type] = 0;
+ Timers->Active[Type] = 0;
+ return;
+ }
+ Timers->NextTimer[Type] = Value - Timers->Timer;
+ Timers->Active[Type] = 1;
+ CheckTimer();
+}
+
+void CheckTimer (void) {
+ int32_t count;
+
+ for (count = 0; count < MaxTimers; count++) {
+ if (!Timers->Active[count]) { continue; }
+ if (!(count == CompareTimer && Timers->NextTimer[count] == 0x7FFFFFFF)) {
+ Timers->NextTimer[count] += Timers->Timer;
+ }
+ }
+ Timers->CurrentTimerType = -1;
+ Timers->Timer = 0x7FFFFFFF;
+ for (count = 0; count < MaxTimers; count++) {
+ if (!Timers->Active[count]) { continue; }
+ if (Timers->NextTimer[count] >= Timers->Timer) { continue; }
+ Timers->Timer = Timers->NextTimer[count];
+ Timers->CurrentTimerType = count;
+ }
+ if (Timers->CurrentTimerType == -1) {
+ DisplayError("No active timers ???\nEmulation Stoped");
+ StopEmulation();
+ }
+ for (count = 0; count < MaxTimers; count++) {
+ if (!Timers->Active[count]) { continue; }
+ if (!(count == CompareTimer && Timers->NextTimer[count] == 0x7FFFFFFF)) {
+ Timers->NextTimer[count] -= Timers->Timer;
+ }
+ }
+
+ if (Timers->NextTimer[CompareTimer] == 0x7FFFFFFF) {
+ uint32_t NextCompare = COMPARE_REGISTER - COUNT_REGISTER;
+ if ((NextCompare & 0x80000000) == 0 && NextCompare != 0x7FFFFFFF) {
+ ChangeCompareTimer();
+ }
+ }
+}
+
+
+
+void CloseCpu (void) {
+ uint32_t count = 0;
+
+ if(!MemChunk) return;
+ if (!cpu_running) { return; }
+
+ cpu_running = 0;
+ g_print("cpu_running = %d\n", cpu_running);
+
+ for (count = 0; count < 3; count ++ ) {
+ CPU_Action->CloseCPU = 1;
+ CPU_Action->DoSomething = 1;
+ }
+
+ CPURunning = 0;
+}
+
+int32_t DelaySlotEffectsCompare (uint32_t PC, uint32_t Reg1, uint32_t Reg2) {
+ OPCODE Command;
+
+ if (!r4300i_LW_VAddr(PC + 4, (uint32_t*)&Command.Hex)) {
+ return 1;
+ }
+
+ switch (Command.op) {
+ case R4300i_SPECIAL:
+ switch (Command.funct) {
+ case R4300i_SPECIAL_SLL:
+ case R4300i_SPECIAL_SRL:
+ case R4300i_SPECIAL_SRA:
+ case R4300i_SPECIAL_SLLV:
+ case R4300i_SPECIAL_SRLV:
+ case R4300i_SPECIAL_SRAV:
+ case R4300i_SPECIAL_MFHI:
+ case R4300i_SPECIAL_MTHI:
+ case R4300i_SPECIAL_MFLO:
+ case R4300i_SPECIAL_MTLO:
+ case R4300i_SPECIAL_DSLLV:
+ case R4300i_SPECIAL_DSRLV:
+ case R4300i_SPECIAL_DSRAV:
+ case R4300i_SPECIAL_ADD:
+ case R4300i_SPECIAL_ADDU:
+ case R4300i_SPECIAL_SUB:
+ case R4300i_SPECIAL_SUBU:
+ case R4300i_SPECIAL_AND:
+ case R4300i_SPECIAL_OR:
+ case R4300i_SPECIAL_XOR:
+ case R4300i_SPECIAL_NOR:
+ case R4300i_SPECIAL_SLT:
+ case R4300i_SPECIAL_SLTU:
+ case R4300i_SPECIAL_DADD:
+ case R4300i_SPECIAL_DADDU:
+ case R4300i_SPECIAL_DSUB:
+ case R4300i_SPECIAL_DSUBU:
+ case R4300i_SPECIAL_DSLL:
+ case R4300i_SPECIAL_DSRL:
+ case R4300i_SPECIAL_DSRA:
+ case R4300i_SPECIAL_DSLL32:
+ case R4300i_SPECIAL_DSRL32:
+ case R4300i_SPECIAL_DSRA32:
+ if (Command.rd == 0) { return 0; }
+ if (Command.rd == Reg1) { return 1; }
+ if (Command.rd == Reg2) { return 1; }
+ break;
+ case R4300i_SPECIAL_MULT:
+ case R4300i_SPECIAL_MULTU:
+ case R4300i_SPECIAL_DIV:
+ case R4300i_SPECIAL_DIVU:
+ case R4300i_SPECIAL_DMULT:
+ case R4300i_SPECIAL_DMULTU:
+ case R4300i_SPECIAL_DDIV:
+ case R4300i_SPECIAL_DDIVU:
+ break;
+ default:
+ return 1;
+ }
+ break;
+ case R4300i_CP0:
+ switch (Command.rs) {
+ case R4300i_COP0_MT: break;
+ case R4300i_COP0_MF:
+ if (Command.rt == 0) { return 0; }
+ if (Command.rt == Reg1) { return 1; }
+ if (Command.rt == Reg2) { return 1; }
+ break;
+ default:
+ if ( (Command.rs & 0x10 ) != 0 ) {
+ switch( Opcode.funct ) {
+ case R4300i_COP0_CO_TLBR: break;
+ case R4300i_COP0_CO_TLBWI: break;
+ case R4300i_COP0_CO_TLBWR: break;
+ case R4300i_COP0_CO_TLBP: break;
+ default:
+ return 1;
+ }
+ return 1;
+ }
+ }
+ break;
+ case R4300i_CP1:
+ switch (Command.fmt) {
+ case R4300i_COP1_MF:
+ if (Command.rt == 0) { return 0; }
+ if (Command.rt == Reg1) { return 1; }
+ if (Command.rt == Reg2) { return 1; }
+ break;
+ case R4300i_COP1_CF: break;
+ case R4300i_COP1_MT: break;
+ case R4300i_COP1_CT: break;
+ case R4300i_COP1_S: break;
+ case R4300i_COP1_D: break;
+ case R4300i_COP1_W: break;
+ case R4300i_COP1_L: break;
+ return 1;
+ }
+ break;
+ case R4300i_ANDI:
+ case R4300i_ORI:
+ case R4300i_XORI:
+ case R4300i_LUI:
+ case R4300i_ADDI:
+ case R4300i_ADDIU:
+ case R4300i_SLTI:
+ case R4300i_SLTIU:
+ case R4300i_DADDI:
+ case R4300i_DADDIU:
+ case R4300i_LB:
+ case R4300i_LH:
+ case R4300i_LW:
+ case R4300i_LWL:
+ case R4300i_LWR:
+ case R4300i_LDL:
+ case R4300i_LDR:
+ case R4300i_LBU:
+ case R4300i_LHU:
+ case R4300i_LD:
+ case R4300i_LWC1:
+ case R4300i_LDC1:
+ if (Command.rt == 0) { return 0; }
+ if (Command.rt == Reg1) { return 1; }
+ if (Command.rt == Reg2) { return 1; }
+ break;
+ case R4300i_CACHE: break;
+ case R4300i_SB: break;
+ case R4300i_SH: break;
+ case R4300i_SW: break;
+ case R4300i_SWR: break;
+ case R4300i_SWL: break;
+ case R4300i_SWC1: break;
+ case R4300i_SDC1: break;
+ case R4300i_SD: break;
+ default:
+
+ return 1;
+ }
+ return 0;
+}
+
+int32_t DelaySlotEffectsJump (uint32_t JumpPC) {
+ OPCODE Command;
+
+ if (!r4300i_LW_VAddr(JumpPC, &Command.Hex)) { return 1; }
+
+ switch (Command.op) {
+ case R4300i_SPECIAL:
+ switch (Command.funct) {
+ case R4300i_SPECIAL_JR: return DelaySlotEffectsCompare(JumpPC,Command.rs,0);
+ case R4300i_SPECIAL_JALR: return DelaySlotEffectsCompare(JumpPC,Command.rs,31);
+ }
+ break;
+ case R4300i_REGIMM:
+ switch (Command.rt) {
+ case R4300i_REGIMM_BLTZ:
+ case R4300i_REGIMM_BGEZ:
+ case R4300i_REGIMM_BLTZL:
+ case R4300i_REGIMM_BGEZL:
+ case R4300i_REGIMM_BLTZAL:
+ case R4300i_REGIMM_BGEZAL:
+ return DelaySlotEffectsCompare(JumpPC,Command.rs,0);
+ }
+ break;
+ case R4300i_JAL:
+ case R4300i_SPECIAL_JALR: return DelaySlotEffectsCompare(JumpPC,31,0); break;
+ case R4300i_J: return 0;
+ case R4300i_BEQ:
+ case R4300i_BNE:
+ case R4300i_BLEZ:
+ case R4300i_BGTZ:
+ return DelaySlotEffectsCompare(JumpPC,Command.rs,Command.rt);
+ case R4300i_CP1:
+ switch (Command.fmt) {
+ case R4300i_COP1_BC:
+ switch (Command.ft) {
+ case R4300i_COP1_BC_BCF:
+ case R4300i_COP1_BC_BCT:
+ case R4300i_COP1_BC_BCFL:
+ case R4300i_COP1_BC_BCTL:
+ {
+ int32_t EffectDelaySlot;
+ OPCODE NewCommand;
+
+ if (!r4300i_LW_VAddr(JumpPC + 4, &NewCommand.Hex)) { return 1; }
+
+ EffectDelaySlot = 0;
+ if (NewCommand.op == R4300i_CP1) {
+ if (NewCommand.fmt == R4300i_COP1_S && (NewCommand.funct & 0x30) == 0x30 ) {
+ EffectDelaySlot = 1;
+ }
+ if (NewCommand.fmt == R4300i_COP1_D && (NewCommand.funct & 0x30) == 0x30 ) {
+ EffectDelaySlot = 1;
+ }
+ }
+ return EffectDelaySlot;
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ case R4300i_BEQL:
+ case R4300i_BNEL:
+ case R4300i_BLEZL:
+ case R4300i_BGTZL:
+ return DelaySlotEffectsCompare(JumpPC,Command.rs,Command.rt);
+ }
+ return 1;
+}
+
+void DoSomething ( void ) {
+ if (CPU_Action->CloseCPU) {
+ //StopEmulation();
+ cpu_running = 0;
+ //printf("Stopping?\n");
+ if(!(fake_seek_stopping&3))
+ g_thread_exit(NULL);
+ }
+ if (CPU_Action->CheckInterrupts) {
+ CPU_Action->CheckInterrupts = 0;
+ CheckInterrupts();
+ }
+ if (CPU_Action->DoInterrupt) {
+ CPU_Action->DoInterrupt = 0;
+ DoIntrException(0);
+ }
+
+
+ CPU_Action->DoSomething = 0;
+
+ if (CPU_Action->DoInterrupt) { CPU_Action->DoSomething = 1; }
+}
+
+void InPermLoop (void) {
+ // *** Changed ***/
+ if (CPU_Action->DoInterrupt) { return; }
+
+ /* Interrupts enabled */
+ if (( STATUS_REGISTER & STATUS_IE ) == 0 ) { goto InterruptsDisabled; }
+ if (( STATUS_REGISTER & STATUS_EXL ) != 0 ) { goto InterruptsDisabled; }
+ if (( STATUS_REGISTER & STATUS_ERL ) != 0 ) { goto InterruptsDisabled; }
+ if (( STATUS_REGISTER & 0xFF00) == 0) { goto InterruptsDisabled; }
+
+ /* check sound playing */
+
+ /* check RSP running */
+ /* check RDP running */
+ if (Timers->Timer >= 0) {
+ COUNT_REGISTER += Timers->Timer + 1;
+ Timers->Timer = -1;
+ }
+ return;
+
+InterruptsDisabled:
+ DisplayError("Stuck in Permanent Loop");
+ StopEmulation();
+}
+
+void ReadFromMem(const void * source, void * target, uint32_t length, uint32_t *offset) {
+ memcpy((uint8_t*)target,((uint8_t*)source)+*offset,length);
+ *offset+=length;
+}
+
+
+uint32_t Machine_LoadStateFromRAM(void * savestatespace) {
+ uint8_t LoadHeader[0x40];
+ uint32_t Value, count, SaveRDRAMSize, offset=0;
+
+ ReadFromMem( savestatespace,&Value,sizeof(Value),&offset);
+ if (Value != 0x23D8A6C8) { return 0; }
+ ReadFromMem( savestatespace,&SaveRDRAMSize,sizeof(SaveRDRAMSize),&offset);
+ ReadFromMem( savestatespace,&LoadHeader,0x40,&offset);
+
+ if (CPU_Type != CPU_Interpreter) {
+ ResetRecompCode();
+ }
+
+ Timers->CurrentTimerType = -1;
+ Timers->Timer = 0;
+ for (count = 0; count < MaxTimers; count ++) { Timers->Active[count] = 0; }
+
+ //fix rdram size
+ if (SaveRDRAMSize != RdramSize) {
+ // dothis :)
+ }
+
+ RdramSize = SaveRDRAMSize;
+
+ ReadFromMem( savestatespace,&Value,sizeof(Value),&offset);
+ ChangeTimer(ViTimer,Value);
+ ReadFromMem( savestatespace,&PROGRAM_COUNTER,sizeof(PROGRAM_COUNTER),&offset);
+ ReadFromMem( savestatespace,GPR,sizeof(int64_t)*32,&offset);
+ ReadFromMem( savestatespace,FPR,sizeof(int64_t)*32,&offset);
+ ReadFromMem( savestatespace,CP0,sizeof(uint32_t)*32,&offset);
+ ReadFromMem( savestatespace,FPCR,sizeof(uint32_t)*32,&offset);
+ ReadFromMem( savestatespace,&HI,sizeof(int64_t),&offset);
+ ReadFromMem( savestatespace,&LO,sizeof(int64_t),&offset);
+ ReadFromMem( savestatespace,RegRDRAM,sizeof(uint32_t)*10,&offset);
+ ReadFromMem( savestatespace,RegSP,sizeof(uint32_t)*10,&offset);
+ ReadFromMem( savestatespace,RegDPC,sizeof(uint32_t)*10,&offset);
+ ReadFromMem( savestatespace,RegMI,sizeof(uint32_t)*4,&offset);
+ ReadFromMem( savestatespace,RegVI,sizeof(uint32_t)*14,&offset);
+ ReadFromMem( savestatespace,RegAI,sizeof(uint32_t)*6,&offset);
+ ReadFromMem( savestatespace,RegPI,sizeof(uint32_t)*13,&offset);
+ ReadFromMem( savestatespace,RegRI,sizeof(uint32_t)*8,&offset);
+ ReadFromMem( savestatespace,RegSI,sizeof(uint32_t)*4,&offset);
+ ReadFromMem( savestatespace,tlb,sizeof(TLB)*32,&offset);
+ ReadFromMem( savestatespace,(uint8_t*)PIF_Ram,0x40,&offset);
+ ReadFromMem( savestatespace,RDRAM,SaveRDRAMSize,&offset);
+ ReadFromMem( savestatespace,DMEM,0x1000,&offset);
+ ReadFromMem( savestatespace,IMEM,0x1000,&offset);
+
+ CP0[32] = 0;
+
+ SetupTLB();
+ ChangeCompareTimer();
+ AI_STATUS_REG = 0;
+ AiDacrateChanged(AI_DACRATE_REG);
+
+// StartAiInterrupt();
+
+ SetFpuLocations(); // important if FR=1
+
+ return 1;
+}
+extern int32_t RSP_Cpu;
+extern int32_t SampleRate;
+void StartEmulationFromSave ( void * savestate ) {
+ uint32_t count = 0;
+ if(use_interpreter)
+ CPU_Type = CPU_Interpreter;
+
+ //printf("Starting generic Cpu\n");
+
+ //CloseCpu();
+ memset(N64MEM, 0, RdramSize);
+
+ memset(DMEM, 0, 0x1000);
+ memset(IMEM, 0, 0x1000);
+ memset(TLB_Map, 0, 0x100000 * sizeof(uintptr_t) + 0x10000);
+ if(!use_interpreter) {
+ memset(JumpTable, 0, 0x200000 * sizeof(uintptr_t));
+ memset(RecompCode, 0xcc, NormalCompileBufferSize); // fill with Breakpoints
+ memset(DelaySlotTable, 0, ((0x1000000) >> 0xA));
+ }
+
+ memset(CPU_Action,0,sizeof(CPU_Action));
+ WrittenToRom = 0;
+
+ InitilizeTLB();
+
+ SetupRegisters(Registers);
+
+ BuildInterpreter();
+ RecompPos = RecompCode;
+
+ Timers->CurrentTimerType = -1;
+ Timers->Timer = 0;
+
+ for (count = 0; count < MaxTimers; count ++) { Timers->Active[count] = 0; }
+ ChangeTimer(ViTimer,5000);
+ ChangeCompareTimer();
+ ViFieldNumber = 0;
+ CPURunning = 1;
+ *WaitMode = 0;
+
+ init_rsp();
+
+ Machine_LoadStateFromRAM(savestate);
+
+ SampleRate = 48681812 / (AI_DACRATE_REG + 1);
+
+ OpenSound();
+
+ pcontext->set_params(pcontext, NULL, 0, SampleRate * 4, SampleRate, 2);
+
+ if(enableFIFOfull) {
+ const float VSyncTiming = 789000.0f;
+ double BytesPerSecond = 48681812.0 / (AI_DACRATE_REG + 1) * 4;
+ double CountsPerSecond = (double)(((double)VSyncTiming) * (double)60.0);
+ double CountsPerByte = (double)CountsPerSecond / (double)BytesPerSecond;
+ uint32_t IntScheduled = (uint32_t)((double)AI_LEN_REG * CountsPerByte);
+
+ ChangeTimer(AiTimer,IntScheduled);
+ AI_STATUS_REG|=0x40000000;
+ }
+
+ cpu_stopped = 0;
+ cpu_running = 1;
+ fake_seek_stopping = 0;
+
+ switch (CPU_Type) {
+ case CPU_Interpreter: StartInterpreterCPU(); break;
+ case CPU_Recompiler: StartRecompilerCPU(); break;
+ default:
+ DisplayError("Unhandled CPU %d",CPU_Type);
+ }
+
+}
+
+
+void RefreshScreen (void ){
+ ChangeTimer(ViTimer, 300000);
+
+}
+
+void RunRsp (void) {
+ if ( ( SP_STATUS_REG & SP_STATUS_HALT ) == 0) {
+ if ( ( SP_STATUS_REG & SP_STATUS_BROKE ) == 0 ) {
+
+ uint32_t Task = *( uint32_t *)(DMEM + 0xFC0);
+
+ switch (Task) {
+ case 1: {
+ MI_INTR_REG |= 0x20;
+
+ SP_STATUS_REG |= (0x0203 );
+ if ((SP_STATUS_REG & SP_STATUS_INTR_BREAK) != 0 )
+ MI_INTR_REG |= 1;
+
+ CheckInterrupts();
+
+ DPC_STATUS_REG &= ~0x0002;
+ return;
+
+ }
+ break;
+ case 2: {
+
+ if(use_audiohle && !is_seeking) {
+ OSTask_t *task = (OSTask_t*)(DMEM + 0xFC0);
+ if(audio_ucode(task))
+ break;
+
+ } else
+ break;
+
+ SP_STATUS_REG |= (0x0203 );
+ if ((SP_STATUS_REG & SP_STATUS_INTR_BREAK) != 0 ) {
+ MI_INTR_REG |= 1;
+ CheckInterrupts();
+ }
+
+ return;
+
+ }
+ break;
+ default:
+
+ break;
+ }
+
+ if(!is_seeking)
+ real_run_rsp(100);
+ SP_STATUS_REG |= (0x0203 );
+ if ((SP_STATUS_REG & SP_STATUS_INTR_BREAK) != 0 ) {
+ MI_INTR_REG |= 1;
+ CheckInterrupts();
+ }
+
+ }
+ }
+}
+
+void TimerDone (void) {
+ switch (Timers->CurrentTimerType) {
+ case CompareTimer:
+ if(enablecompare)
+ FAKE_CAUSE_REGISTER |= CAUSE_IP7;
+ //CheckInterrupts();
+ ChangeCompareTimer();
+ break;
+ case ViTimer:
+ RefreshScreen();
+ MI_INTR_REG |= MI_INTR_VI;
+ CheckInterrupts();
+ //CompileCheckInterrupts();
+ *WaitMode=0;
+ break;
+ case AiTimer:
+ ChangeTimer(AiTimer,0);
+ AI_STATUS_REG=0;
+ AudioIntrReg|=4;
+ //CheckInterrupts();
+ break;
+ }
+ CheckTimer();
+}
+
+void Int3() {
+ asm("int $3");
+}
+
+void _Emms() {
+ asm("emms");
+}
+
+
+
+#include <fpu_control.h>
+
+void controlfp(uint32_t control) {
+ uint32_t OldControl = 0;
+
+ _FPU_GETCW(OldControl);
+ OldControl &= ~(_FPU_RC_ZERO | _FPU_RC_UP | _FPU_RC_DOWN | _FPU_RC_NEAREST);
+
+ OldControl |= control;
+
+ _FPU_SETCW(OldControl);
+
+}
+
diff --git a/src/usf/cpu.h b/src/usf/cpu.h new file mode 100644 index 0000000..48510fe --- /dev/null +++ b/src/usf/cpu.h @@ -0,0 +1,108 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+#ifndef _CPU_H_
+#define _CPU_H_
+
+#include "interpreter_cpu.h"
+#include "interpreter_ops.h"
+#include "recompiler_cpu.h"
+#include "registers.h"
+#include "recompiler_ops.h"
+#include "tlb.h"
+#include "memory.h"
+#include "dma.h"
+#include "exception.h"
+#include "pif.h"
+#include "opcode.h"
+#include "usf.h"
+
+#ifdef __LP64__
+#define USEX86
+#define EXTREGS
+#endif
+
+typedef struct {
+ int32_t DoSomething;
+ int32_t CloseCPU;
+ int32_t CheckInterrupts;
+ int32_t DoInterrupt;
+} CPU_ACTION;
+
+#define MaxTimers 3
+#define CompareTimer 0
+#define ViTimer 1
+#define AiTimer 2
+
+typedef struct {
+ int32_t NextTimer[MaxTimers];
+ int32_t Active[MaxTimers];
+ int32_t CurrentTimerType;
+ int32_t Timer;
+} SYSTEM_TIMERS;
+
+void ChangeCompareTimer ( void );
+void ChangeTimer ( int32_t Type, int32_t Value );
+void CheckTimer ( void );
+void CloseCpu ( void );
+int32_t DelaySlotEffectsCompare ( uint32_t PC, uint32_t Reg1, uint32_t Reg2 );
+int32_t DelaySlotEffectsJump (uint32_t JumpPC);
+void DoSomething ( void );
+void InPermLoop ( void );
+void InitiliazeCPUFlags ( void );
+void RefreshScreen ( void );
+void RunRsp ( void );
+void StartEmulation ( void );
+void TimerDone ( void );
+void RecompileTimerDone ( void );
+void controlfp (uint32_t mask);
+void StartEmulationFromSave ( void * savestate );
+
+#define NORMAL 0
+#define DO_DELAY_SLOT 1
+#define DO_END_DELAY_SLOT 2
+#define DELAY_SLOT 3
+#define END_DELAY_SLOT 4
+#define LIKELY_DELAY_SLOT 5
+#define JUMP 6
+#define DELAY_SLOT_DONE 7
+#define LIKELY_DELAY_SLOT_DONE 8
+#define END_BLOCK 9
+
+enum SaveType {
+ Auto,
+ Eeprom_4K,
+ Eeprom_16K,
+ Sram,
+ FlashRam
+};
+
+
+extern uint32_t NextInstruction, JumpToLocation, ManualPaused, CPU_Paused, CountPerOp, AudioIntrReg, * WaitMode, CPU_Type;
+extern CPU_ACTION * CPU_Action;
+extern SYSTEM_TIMERS * Timers;
+extern OPCODE Opcode;
+extern uint32_t CPURunning;
+#endif
diff --git a/src/usf/dma.c b/src/usf/dma.c new file mode 100644 index 0000000..a4e078a --- /dev/null +++ b/src/usf/dma.c @@ -0,0 +1,177 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+#include "main.h"
+#include "cpu.h"
+
+void PI_DMA_READ (void) {
+
+ PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
+ MI_INTR_REG |= MI_INTR_PI;
+ CheckInterrupts();
+ return;
+}
+
+#include <stdio.h>
+extern FILE *fil;
+void PI_DMA_WRITE (void) {
+ uint32_t i;
+ PI_STATUS_REG |= PI_STATUS_DMA_BUSY;
+ //fprintf(fil,"PI DMA from %08x to %08x len %08x\n", PI_CART_ADDR_REG, PI_DRAM_ADDR_REG, PI_WR_LEN_REG);
+ if ( PI_DRAM_ADDR_REG + PI_WR_LEN_REG + 1 > RdramSize) {
+ PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
+ MI_INTR_REG |= MI_INTR_PI;
+ CheckInterrupts();
+ return;
+ }
+
+ if ( PI_CART_ADDR_REG >= 0x08000000 && PI_CART_ADDR_REG <= 0x08010000) {
+ return;
+ }
+
+ if ( PI_CART_ADDR_REG >= 0x10000000 && PI_CART_ADDR_REG <= 0x1FBFFFFF) {
+ PI_CART_ADDR_REG -= 0x10000000;
+ for (i = 0; i < PI_WR_LEN_REG + 1; i ++) {
+ *(N64MEM+((PI_DRAM_ADDR_REG + i) ^ 3)) = *PageROM((PI_CART_ADDR_REG + i) ^ 3);
+ }
+ PI_CART_ADDR_REG += 0x10000000;
+
+ PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
+ MI_INTR_REG |= MI_INTR_PI;
+ CheckInterrupts();
+ CheckTimer();
+ return;
+ }
+
+ PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
+ MI_INTR_REG |= MI_INTR_PI;
+ CheckInterrupts();
+}
+
+
+void SI_DMA_READ (void) {
+
+ if ((int32_t)SI_DRAM_ADDR_REG > (int32_t)RdramSize) {
+ return;
+ }
+
+ PifRamRead();
+ SI_DRAM_ADDR_REG &= 0xFFFFFFF8;
+ if ((int32_t)SI_DRAM_ADDR_REG < 0) {
+ int32_t count, RdramPos;
+
+ RdramPos = (int32_t)SI_DRAM_ADDR_REG;
+ for (count = 0; count < 0x40; count++, RdramPos++) {
+ if (RdramPos < 0) { continue; }
+ N64MEM[RdramPos ^3] = PIF_Ram[count];
+ }
+ } else {
+ int32_t count, RdramPos;
+
+ RdramPos = (uint32_t)SI_DRAM_ADDR_REG;
+ for (count = 0; count < 0x40; count++, RdramPos++) {
+ if (RdramPos < 0) { continue; }
+ N64MEM[RdramPos ^3] = PIF_Ram[count];
+ }
+ }
+
+ MI_INTR_REG |= MI_INTR_SI;
+ SI_STATUS_REG |= SI_STATUS_INTERRUPT;
+ CheckInterrupts();
+}
+
+
+void SI_DMA_WRITE (void) {
+
+ if ((int32_t)SI_DRAM_ADDR_REG > (int32_t)RdramSize) {
+ return;
+ }
+
+ SI_DRAM_ADDR_REG &= 0xFFFFFFF8;
+ if ((int32_t)SI_DRAM_ADDR_REG < 0) {
+ int32_t count, RdramPos;
+
+ RdramPos = (int32_t)SI_DRAM_ADDR_REG;
+ for (count = 0; count < 0x40; count++, RdramPos++) {
+ if (RdramPos < 0) { PIF_Ram[count] = 0; continue; }
+ PIF_Ram[count] = N64MEM[RdramPos ^3];
+ }
+ } else {
+ int32_t count, RdramPos;
+
+ RdramPos = (int32_t)SI_DRAM_ADDR_REG;
+ for (count = 0; count < 0x40; count++, RdramPos++) {
+ if (RdramPos < 0) { PIF_Ram[count] = 0; continue; }
+ PIF_Ram[count] = N64MEM[RdramPos ^3];
+ }
+ }
+
+ PifRamWrite();
+
+ MI_INTR_REG |= MI_INTR_SI;
+ SI_STATUS_REG |= SI_STATUS_INTERRUPT;
+ CheckInterrupts();
+
+}
+
+void SP_DMA_READ (void) {
+ SP_DRAM_ADDR_REG &= 0x1FFFFFFF;
+
+ if (SP_DRAM_ADDR_REG > RdramSize) {
+ SP_DMA_BUSY_REG = 0;
+ SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY;
+ return;
+ }
+
+ if (SP_RD_LEN_REG + 1 + (SP_MEM_ADDR_REG & 0xFFF) > 0x1000) {
+ return;
+ }
+
+ memcpy( DMEM + (SP_MEM_ADDR_REG & 0x1FFF), N64MEM + SP_DRAM_ADDR_REG,
+ SP_RD_LEN_REG + 1 );
+
+ SP_DMA_BUSY_REG = 0;
+ SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY;
+ MI_INTR_REG &= ~MI_INTR_SP;
+ CheckInterrupts();
+ CheckTimer();
+}
+
+void SP_DMA_WRITE (void) {
+ if (SP_DRAM_ADDR_REG > RdramSize) {
+ return;
+ }
+
+ if (SP_WR_LEN_REG + 1 + (SP_MEM_ADDR_REG & 0xFFF) > 0x1000) {
+ return;
+ }
+
+ memcpy( N64MEM + SP_DRAM_ADDR_REG, DMEM + (SP_MEM_ADDR_REG & 0x1FFF),
+ SP_WR_LEN_REG + 1);
+
+ SP_DMA_BUSY_REG = 0;
+ SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY;
+}
+
diff --git a/src/usf/dma.h b/src/usf/dma.h new file mode 100644 index 0000000..aae1c71 --- /dev/null +++ b/src/usf/dma.h @@ -0,0 +1,34 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+void PI_DMA_READ ( void );
+void PI_DMA_WRITE ( void );
+void SI_DMA_READ ( void );
+void SI_DMA_WRITE ( void );
+void SP_DMA_READ ( void );
+void SP_DMA_WRITE ( void );
+
+
+
diff --git a/src/usf/exception.c b/src/usf/exception.c new file mode 100644 index 0000000..b48b50d --- /dev/null +++ b/src/usf/exception.c @@ -0,0 +1,228 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+
+#include "main.h"
+#include "cpu.h"
+#include "recompiler_cpu.h"
+#include "x86.h"
+
+void CheckInterrupts ( void ) {
+
+ MI_INTR_REG &= ~MI_INTR_AI;
+ MI_INTR_REG |= (AudioIntrReg & MI_INTR_AI);
+ if ((MI_INTR_MASK_REG & MI_INTR_REG) != 0) {
+ FAKE_CAUSE_REGISTER |= CAUSE_IP2;
+ } else {
+ FAKE_CAUSE_REGISTER &= ~CAUSE_IP2;
+ }
+
+ if (( STATUS_REGISTER & STATUS_IE ) == 0 ) { return; }
+ if (( STATUS_REGISTER & STATUS_EXL ) != 0 ) { return; }
+ if (( STATUS_REGISTER & STATUS_ERL ) != 0 ) { return; }
+
+ if (( STATUS_REGISTER & FAKE_CAUSE_REGISTER & 0xFF00) != 0) {
+ if (!CPU_Action->DoInterrupt) {
+ CPU_Action->DoSomething = 1;
+ CPU_Action->DoInterrupt = 1;
+ }
+ }
+}
+
+void DoAddressError ( uint32_t DelaySlot, uint32_t BadVaddr, uint32_t FromRead) {
+ if (FromRead) {
+ CAUSE_REGISTER = EXC_RADE;
+ } else {
+ CAUSE_REGISTER = EXC_WADE;
+ }
+ BAD_VADDR_REGISTER = BadVaddr;
+ if (DelaySlot) {
+ CAUSE_REGISTER |= CAUSE_BD;
+ EPC_REGISTER = PROGRAM_COUNTER - 4;
+ } else {
+ EPC_REGISTER = PROGRAM_COUNTER;
+ }
+ STATUS_REGISTER |= STATUS_EXL;
+ PROGRAM_COUNTER = 0x80000180;
+}
+
+void DoBreakException ( uint32_t DelaySlot) {
+ CAUSE_REGISTER = EXC_BREAK;
+ if (DelaySlot) {
+ CAUSE_REGISTER |= CAUSE_BD;
+ EPC_REGISTER = PROGRAM_COUNTER - 4;
+ } else {
+ EPC_REGISTER = PROGRAM_COUNTER;
+ }
+ STATUS_REGISTER |= STATUS_EXL;
+ PROGRAM_COUNTER = 0x80000180;
+}
+
+void DoCopUnusableException ( uint32_t DelaySlot, uint32_t Coprocessor ) {
+ CAUSE_REGISTER = EXC_CPU;
+ if (Coprocessor == 1) { CAUSE_REGISTER |= 0x10000000; }
+ if (DelaySlot) {
+ CAUSE_REGISTER |= CAUSE_BD;
+ EPC_REGISTER = PROGRAM_COUNTER - 4;
+ } else {
+ EPC_REGISTER = PROGRAM_COUNTER;
+ }
+ STATUS_REGISTER |= STATUS_EXL;
+ PROGRAM_COUNTER = 0x80000180;
+}
+
+void DoIntrException ( uint32_t DelaySlot ) {
+
+ if (( STATUS_REGISTER & STATUS_IE ) == 0 ) { return; }
+ if (( STATUS_REGISTER & STATUS_EXL ) != 0 ) { return; }
+ if (( STATUS_REGISTER & STATUS_ERL ) != 0 ) { return; }
+ CAUSE_REGISTER = FAKE_CAUSE_REGISTER;
+ CAUSE_REGISTER |= EXC_INT;
+ EPC_REGISTER = PROGRAM_COUNTER;
+ if (DelaySlot) {
+ CAUSE_REGISTER |= CAUSE_BD;
+ EPC_REGISTER -= 4;
+ }
+ STATUS_REGISTER |= STATUS_EXL;
+ PROGRAM_COUNTER = 0x80000180;
+}
+
+/*
+#ifdef USEX64
+void CompileDoIntrException(void) {
+ uint8_t * Jump, * Jump2;
+
+ MoveVariableToX86reg(&STATUS_REGISTER, x86_TEMPD);
+ AndConstToX86Reg(x86_TEMPD,7);
+ CompConstToX86reg(x86_TEMPD,1);
+ JneLabel8(0);
+ Jump = RecompPos - 1;
+ Push(x86_RAX);
+
+ MoveVariableToX86reg(&FAKE_CAUSE_REGISTER, x86_EAX);
+ OrConstToX86Reg(EXC_INT, x86_EAX);
+
+ CompConstToX86reg(x86_ECX,0);
+ MoveVariableToX86reg(&PROGRAM_COUNTER, x86_ECX);
+ JeLabel8(0);
+ Jump2 = RecompPos - 1;
+ OrConstToX86Reg(CAUSE_BD, x86_EAX);
+ SubConstFromX86Reg(x86_ECX,4);
+
+ SetJump8(Jump2, RecompPos);
+
+ MoveX86regToVariable(x86_ECX, &EPC_REGISTER);
+ MoveX86regToVariable(x86_EAX, &CAUSE_REGISTER);
+
+ OrConstToVariable(STATUS_EXL, &STATUS_REGISTER);
+ MoveConstToVariable(0x80000180, &PROGRAM_COUNTER);
+ Pop(x86_RAX);
+ SetJump8(Jump, RecompPos);
+
+}
+#endif
+
+#ifdef USEX64
+void CompileCheckInterrupts(void) {
+ uint8_t * Jump, * Jump2, * Jump3;
+
+ BreakPoint();
+ Push(x86_EAX);
+ Push(x86_EDX);
+
+ MoveVariableToX86reg(&MI_INTR_REG, x86_EAX);
+ MoveVariableToX86reg(&FAKE_CAUSE_REGISTER, x86_EDX);
+ AndConstToX86Reg(x86_EAX, ~MI_INTR_AI);
+ OrConstToX86Reg(CAUSE_IP2, x86_EDX);
+ TestVariableToX86Reg(x86_EAX, &MI_INTR_MASK_REG);
+ JnzLabel8(0);
+ Jump = RecompPos - 1;
+ AndConstToX86Reg(x86_EDX, ~CAUSE_IP2);
+ SetJump8(Jump, RecompPos);
+
+ MoveVariableToX86reg(&STATUS_REGISTER, x86_TEMPD);
+ AndConstToX86Reg(x86_TEMPD,7);
+ CompConstToX86reg(x86_TEMPD,1);
+ JneLabel8(0);
+ Jump2 = RecompPos - 1;
+
+ MoveVariableToX86reg(&STATUS_REGISTER, x86_TEMPD);
+ AddX86RegToX86Reg(x86_TEMPD, x86_EDX);
+ AndConstToX86Reg(x86_TEMPD,0xFF00);
+
+ CompConstToVariable(0, &CPU_Action->DoInterrupt);
+ JneLabel8(0);
+ Jump = RecompPos - 1;
+
+ MoveConstToVariable(1, &CPU_Action->DoInterrupt);
+ MoveConstToVariable(1, &CPU_Action->DoSomething);
+
+ SetJump8(Jump, RecompPos);
+ SetJump8(Jump2, RecompPos);
+
+ MoveX86regToVariable(x86_EAX, &MI_INTR_REG);
+ MoveX86regToVariable(x86_EDX, &FAKE_CAUSE_REGISTER);
+ Pop(x86_EDX);
+ Pop(x86_EAX);
+}
+#endif
+*/
+
+void DoTLBMiss ( uint32_t DelaySlot, uint32_t BadVaddr ) {
+
+ CAUSE_REGISTER = EXC_RMISS;
+ BAD_VADDR_REGISTER = BadVaddr;
+ CONTEXT_REGISTER &= 0xFF80000F;
+ CONTEXT_REGISTER |= (BadVaddr >> 9) & 0x007FFFF0;
+ ENTRYHI_REGISTER = (BadVaddr & 0xFFFFE000);
+ if ((STATUS_REGISTER & STATUS_EXL) == 0) {
+ if (DelaySlot) {
+ CAUSE_REGISTER |= CAUSE_BD;
+ EPC_REGISTER = PROGRAM_COUNTER - 4;
+ } else {
+ EPC_REGISTER = PROGRAM_COUNTER;
+ }
+ if (AddressDefined(BadVaddr)) {
+ PROGRAM_COUNTER = 0x80000180;
+ } else {
+ PROGRAM_COUNTER = 0x80000000;
+ }
+ STATUS_REGISTER |= STATUS_EXL;
+ } else {
+ PROGRAM_COUNTER = 0x80000180;
+ }
+}
+
+void DoSysCallException ( uint32_t DelaySlot) {
+ CAUSE_REGISTER = EXC_SYSCALL;
+ if (DelaySlot) {
+ CAUSE_REGISTER |= CAUSE_BD;
+ EPC_REGISTER = PROGRAM_COUNTER - 4;
+ } else {
+ EPC_REGISTER = PROGRAM_COUNTER;
+ }
+ STATUS_REGISTER |= STATUS_EXL;
+ PROGRAM_COUNTER = 0x80000180;
+}
diff --git a/src/usf/exception.h b/src/usf/exception.h new file mode 100644 index 0000000..476a1d7 --- /dev/null +++ b/src/usf/exception.h @@ -0,0 +1,75 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+#define EXC_CODE(x) ((x)<<2)
+#define EXC_INT EXC_CODE(0) /* interrupt */
+#define EXC_MOD EXC_CODE(1) /* TLB mod */
+#define EXC_RMISS EXC_CODE(2) /* Read TLB Miss */
+#define EXC_WMISS EXC_CODE(3) /* Write TLB Miss */
+#define EXC_RADE EXC_CODE(4) /* Read Address Error */
+#define EXC_WADE EXC_CODE(5) /* Write Address Error */
+#define EXC_IBE EXC_CODE(6) /* Instruction Bus Error */
+#define EXC_DBE EXC_CODE(7) /* Data Bus Error */
+#define EXC_SYSCALL EXC_CODE(8) /* SYSCALL */
+#define EXC_BREAK EXC_CODE(9) /* BREAKpoint */
+#define EXC_II EXC_CODE(10)/* Illegal Instruction */
+#define EXC_CPU EXC_CODE(11)/* CoProcessor Unusable */
+#define EXC_OV EXC_CODE(12)/* OVerflow */
+#define EXC_TRAP EXC_CODE(13)/* Trap exception */
+#define EXC_VCEI EXC_CODE(14)/* Virt. Coherency on Inst. fetch */
+#define EXC_FPE EXC_CODE(15)/* Floating Point Exception */
+#define EXC_WATCH EXC_CODE(23)/* Watchpoint reference */
+#define EXC_VCED EXC_CODE(31)/* Virt. Coherency on data read */
+
+#define Exception_Name(Except)\
+ (Except) == EXC_INT ? "interrupt" :\
+ (Except) == EXC_MOD ? "TLB mod" :\
+ (Except) == EXC_RMISS ? "Read TLB Miss" :\
+ (Except) == EXC_WMISS ? "Write TLB Miss" :\
+ (Except) == EXC_RADE ? "Read Address Error" :\
+ (Except) == EXC_WADE ? "Write Address Error" :\
+ (Except) == EXC_IBE ? "Instruction Bus Error" :\
+ (Except) == EXC_DBE ? "Data Bus Error" :\
+ (Except) == EXC_SYSCALL ? "SYSCALL" :\
+ (Except) == EXC_BREAK ? "Break" :\
+ (Except) == EXC_II ? "Illegal Instruction" :\
+ (Except) == EXC_CPU ? "CoProcessor Unusable" :\
+ (Except) == EXC_OV ? "OVerflow" :\
+ (Except) == EXC_TRAP ? "Trap exception" :\
+ (Except) == EXC_VCEI ? "Virt. Coherency on Inst. fetch" :\
+ (Except) == EXC_FPE ? "Floating Point Exception" :\
+ (Except) == EXC_WATCH ? "Watchpoint reference" :\
+ (Except) == EXC_VCED ? "Virt. Coherency on data read" :\
+ "Unkown"
+
+void AiCheckInterrupts ( void );
+void CheckInterrupts ( void );
+void DoAddressError ( uint32_t DelaySlot, uint32_t BadVaddr, uint32_t FromRead );
+void DoBreakException ( uint32_t DelaySlot );
+void DoCopUnusableException ( uint32_t DelaySlot, uint32_t Coprocessor );
+void DoIntrException ( uint32_t DelaySlot );
+void DoTLBMiss ( uint32_t DelaySlot, uint32_t BadVaddr );
+void DoSysCallException ( uint32_t DelaySlot);
+
diff --git a/src/usf/interpreter_cpu.c b/src/usf/interpreter_cpu.c new file mode 100644 index 0000000..f0eb7ed --- /dev/null +++ b/src/usf/interpreter_cpu.c @@ -0,0 +1,738 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+#include <float.h>
+#include <fpu_control.h>
+#include "main.h"
+#include "cpu.h"
+#include "usf.h"
+#include "memory.h"
+
+#include <stdio.h>
+
+void (* R4300i_Opcode[64])();
+void (* R4300i_Special[64])();
+void (* R4300i_Regimm[32])();
+void (* R4300i_CoP0[32])();
+void (* R4300i_CoP0_Function[64])();
+void (* R4300i_CoP1[32])();
+void (* R4300i_CoP1_BC[32])();
+void (* R4300i_CoP1_S[64])();
+void (* R4300i_CoP1_D[64])();
+void (* R4300i_CoP1_W[64])();
+void (* R4300i_CoP1_L[64])();
+
+void R4300i_opcode_SPECIAL (void) {
+ ((void (*)()) R4300i_Special[ Opcode.funct ])();
+}
+
+void R4300i_opcode_REGIMM (void) {
+ ((void (*)()) R4300i_Regimm[ Opcode.rt ])();
+}
+
+void R4300i_opcode_COP0 (void) {
+ ((void (*)()) R4300i_CoP0[ Opcode.rs ])();
+}
+
+void R4300i_opcode_COP0_CO (void) {
+ ((void (*)()) R4300i_CoP0_Function[ Opcode.funct ])();
+}
+
+void R4300i_opcode_COP1 (void) {
+ ((void (*)()) R4300i_CoP1[ Opcode.fmt ])();
+}
+
+void R4300i_opcode_COP1_BC (void) {
+ ((void (*)()) R4300i_CoP1_BC[ Opcode.ft ])();
+}
+
+void R4300i_opcode_COP1_S (void) {
+ controlfp(RoundingModel);
+ ((void (*)()) R4300i_CoP1_S[ Opcode.funct ])();
+}
+
+void R4300i_opcode_COP1_D (void) {
+ controlfp(RoundingModel);
+ ((void (*)()) R4300i_CoP1_D[ Opcode.funct ])();
+}
+
+void R4300i_opcode_COP1_W (void) {
+ ((void (*)()) R4300i_CoP1_W[ Opcode.funct ])();
+}
+
+void R4300i_opcode_COP1_L (void) {
+ ((void (*)()) R4300i_CoP1_L[ Opcode.funct ])();
+}
+
+
+void BuildInterpreter (void ) {
+ R4300i_Opcode[ 0] = R4300i_opcode_SPECIAL;
+ R4300i_Opcode[ 1] = R4300i_opcode_REGIMM;
+ R4300i_Opcode[ 2] = r4300i_J;
+ R4300i_Opcode[ 3] = r4300i_JAL;
+ R4300i_Opcode[ 4] = r4300i_BEQ;
+ R4300i_Opcode[ 5] = r4300i_BNE;
+ R4300i_Opcode[ 6] = r4300i_BLEZ;
+ R4300i_Opcode[ 7] = r4300i_BGTZ;
+ R4300i_Opcode[ 8] = r4300i_ADDI;
+ R4300i_Opcode[ 9] = r4300i_ADDIU;
+ R4300i_Opcode[10] = r4300i_SLTI;
+ R4300i_Opcode[11] = r4300i_SLTIU;
+ R4300i_Opcode[12] = r4300i_ANDI;
+ R4300i_Opcode[13] = r4300i_ORI;
+ R4300i_Opcode[14] = r4300i_XORI;
+ R4300i_Opcode[15] = r4300i_LUI;
+ R4300i_Opcode[16] = R4300i_opcode_COP0;
+ R4300i_Opcode[17] = R4300i_opcode_COP1;
+ R4300i_Opcode[18] = R4300i_UnknownOpcode;
+ R4300i_Opcode[19] = R4300i_UnknownOpcode;
+ R4300i_Opcode[20] = r4300i_BEQL;
+ R4300i_Opcode[21] = r4300i_BNEL;
+ R4300i_Opcode[22] = r4300i_BLEZL;
+ R4300i_Opcode[23] = r4300i_BGTZL;
+ R4300i_Opcode[24] = R4300i_UnknownOpcode;
+ R4300i_Opcode[25] = r4300i_DADDIU;
+ R4300i_Opcode[26] = r4300i_LDL;
+ R4300i_Opcode[27] = r4300i_LDR;
+ R4300i_Opcode[28] = R4300i_UnknownOpcode;
+ R4300i_Opcode[29] = R4300i_UnknownOpcode;
+ R4300i_Opcode[30] = R4300i_UnknownOpcode;
+ R4300i_Opcode[31] = R4300i_UnknownOpcode;
+ R4300i_Opcode[32] = r4300i_LB;
+ R4300i_Opcode[33] = r4300i_LH;
+ R4300i_Opcode[34] = r4300i_LWL;
+ R4300i_Opcode[35] = r4300i_LW;
+ R4300i_Opcode[36] = r4300i_LBU;
+ R4300i_Opcode[37] = r4300i_LHU;
+ R4300i_Opcode[38] = r4300i_LWR;
+ R4300i_Opcode[39] = r4300i_LWU;
+ R4300i_Opcode[40] = r4300i_SB;
+ R4300i_Opcode[41] = r4300i_SH;
+ R4300i_Opcode[42] = r4300i_SWL;
+ R4300i_Opcode[43] = r4300i_SW;
+ R4300i_Opcode[44] = r4300i_SDL;
+ R4300i_Opcode[45] = r4300i_SDR;
+ R4300i_Opcode[46] = r4300i_SWR;
+ R4300i_Opcode[47] = r4300i_CACHE;
+ R4300i_Opcode[48] = r4300i_LL;
+ R4300i_Opcode[49] = r4300i_LWC1;
+ R4300i_Opcode[50] = R4300i_UnknownOpcode;
+ R4300i_Opcode[51] = R4300i_UnknownOpcode;
+ R4300i_Opcode[52] = R4300i_UnknownOpcode;
+ R4300i_Opcode[53] = r4300i_LDC1;
+ R4300i_Opcode[54] = R4300i_UnknownOpcode;
+ R4300i_Opcode[55] = r4300i_LD;
+ R4300i_Opcode[56] = r4300i_SC;
+ R4300i_Opcode[57] = r4300i_SWC1;
+ R4300i_Opcode[58] = R4300i_UnknownOpcode;
+ R4300i_Opcode[59] = R4300i_UnknownOpcode;
+ R4300i_Opcode[60] = R4300i_UnknownOpcode;
+ R4300i_Opcode[61] = r4300i_SDC1;
+ R4300i_Opcode[62] = R4300i_UnknownOpcode;
+ R4300i_Opcode[63] = r4300i_SD;
+
+ R4300i_Special[ 0] = r4300i_SPECIAL_SLL;
+ R4300i_Special[ 1] = R4300i_UnknownOpcode;
+ R4300i_Special[ 2] = r4300i_SPECIAL_SRL;
+ R4300i_Special[ 3] = r4300i_SPECIAL_SRA;
+ R4300i_Special[ 4] = r4300i_SPECIAL_SLLV;
+ R4300i_Special[ 5] = R4300i_UnknownOpcode;
+ R4300i_Special[ 6] = r4300i_SPECIAL_SRLV;
+ R4300i_Special[ 7] = r4300i_SPECIAL_SRAV;
+ R4300i_Special[ 8] = r4300i_SPECIAL_JR;
+ R4300i_Special[ 9] = r4300i_SPECIAL_JALR;
+ R4300i_Special[10] = R4300i_UnknownOpcode;
+ R4300i_Special[11] = R4300i_UnknownOpcode;
+ R4300i_Special[12] = r4300i_SPECIAL_SYSCALL;
+ R4300i_Special[13] = r4300i_SPECIAL_BREAK;
+ R4300i_Special[14] = R4300i_UnknownOpcode;
+ R4300i_Special[15] = r4300i_SPECIAL_SYNC;
+ R4300i_Special[16] = r4300i_SPECIAL_MFHI;
+ R4300i_Special[17] = r4300i_SPECIAL_MTHI;
+ R4300i_Special[18] = r4300i_SPECIAL_MFLO;
+ R4300i_Special[19] = r4300i_SPECIAL_MTLO;
+ R4300i_Special[20] = r4300i_SPECIAL_DSLLV;
+ R4300i_Special[21] = R4300i_UnknownOpcode;
+ R4300i_Special[22] = r4300i_SPECIAL_DSRLV;
+ R4300i_Special[23] = r4300i_SPECIAL_DSRAV;
+ R4300i_Special[24] = r4300i_SPECIAL_MULT;
+ R4300i_Special[25] = r4300i_SPECIAL_MULTU;
+ R4300i_Special[26] = r4300i_SPECIAL_DIV;
+ R4300i_Special[27] = r4300i_SPECIAL_DIVU;
+ R4300i_Special[28] = r4300i_SPECIAL_DMULT;
+ R4300i_Special[29] = r4300i_SPECIAL_DMULTU;
+ R4300i_Special[30] = r4300i_SPECIAL_DDIV;
+ R4300i_Special[31] = r4300i_SPECIAL_DDIVU;
+ R4300i_Special[32] = r4300i_SPECIAL_ADD;
+ R4300i_Special[33] = r4300i_SPECIAL_ADDU;
+ R4300i_Special[34] = r4300i_SPECIAL_SUB;
+ R4300i_Special[35] = r4300i_SPECIAL_SUBU;
+ R4300i_Special[36] = r4300i_SPECIAL_AND;
+ R4300i_Special[37] = r4300i_SPECIAL_OR;
+ R4300i_Special[38] = r4300i_SPECIAL_XOR;
+ R4300i_Special[39] = r4300i_SPECIAL_NOR;
+ R4300i_Special[40] = R4300i_UnknownOpcode;
+ R4300i_Special[41] = R4300i_UnknownOpcode;
+ R4300i_Special[42] = r4300i_SPECIAL_SLT;
+ R4300i_Special[43] = r4300i_SPECIAL_SLTU;
+ R4300i_Special[44] = r4300i_SPECIAL_DADD;
+ R4300i_Special[45] = r4300i_SPECIAL_DADDU;
+ R4300i_Special[46] = r4300i_SPECIAL_DSUB;
+ R4300i_Special[47] = r4300i_SPECIAL_DSUBU;
+ R4300i_Special[48] = R4300i_UnknownOpcode;
+ R4300i_Special[49] = R4300i_UnknownOpcode;
+ R4300i_Special[50] = R4300i_UnknownOpcode;
+ R4300i_Special[51] = R4300i_UnknownOpcode;
+ R4300i_Special[52] = r4300i_SPECIAL_TEQ;
+ R4300i_Special[53] = R4300i_UnknownOpcode;
+ R4300i_Special[54] = R4300i_UnknownOpcode;
+ R4300i_Special[55] = R4300i_UnknownOpcode;
+ R4300i_Special[56] = r4300i_SPECIAL_DSLL;
+ R4300i_Special[57] = R4300i_UnknownOpcode;
+ R4300i_Special[58] = r4300i_SPECIAL_DSRL;
+ R4300i_Special[59] = r4300i_SPECIAL_DSRA;
+ R4300i_Special[60] = r4300i_SPECIAL_DSLL32;
+ R4300i_Special[61] = R4300i_UnknownOpcode;
+ R4300i_Special[62] = r4300i_SPECIAL_DSRL32;
+ R4300i_Special[63] = r4300i_SPECIAL_DSRA32;
+
+ R4300i_Regimm[ 0] = r4300i_REGIMM_BLTZ;
+ R4300i_Regimm[ 1] = r4300i_REGIMM_BGEZ;
+ R4300i_Regimm[ 2] = r4300i_REGIMM_BLTZL;
+ R4300i_Regimm[ 3] = r4300i_REGIMM_BGEZL;
+ R4300i_Regimm[ 4] = R4300i_UnknownOpcode;
+ R4300i_Regimm[ 5] = R4300i_UnknownOpcode;
+ R4300i_Regimm[ 6] = R4300i_UnknownOpcode;
+ R4300i_Regimm[ 7] = R4300i_UnknownOpcode;
+ R4300i_Regimm[ 8] = R4300i_UnknownOpcode;
+ R4300i_Regimm[ 9] = R4300i_UnknownOpcode;
+ R4300i_Regimm[10] = R4300i_UnknownOpcode;
+ R4300i_Regimm[11] = R4300i_UnknownOpcode;
+ R4300i_Regimm[12] = R4300i_UnknownOpcode;
+ R4300i_Regimm[13] = R4300i_UnknownOpcode;
+ R4300i_Regimm[14] = R4300i_UnknownOpcode;
+ R4300i_Regimm[15] = R4300i_UnknownOpcode;
+ R4300i_Regimm[16] = r4300i_REGIMM_BLTZAL;
+ R4300i_Regimm[17] = r4300i_REGIMM_BGEZAL;
+ R4300i_Regimm[18] = R4300i_UnknownOpcode;
+ R4300i_Regimm[19] = R4300i_UnknownOpcode;
+ R4300i_Regimm[20] = R4300i_UnknownOpcode;
+ R4300i_Regimm[21] = R4300i_UnknownOpcode;
+ R4300i_Regimm[22] = R4300i_UnknownOpcode;
+ R4300i_Regimm[23] = R4300i_UnknownOpcode;
+ R4300i_Regimm[24] = R4300i_UnknownOpcode;
+ R4300i_Regimm[25] = R4300i_UnknownOpcode;
+ R4300i_Regimm[26] = R4300i_UnknownOpcode;
+ R4300i_Regimm[27] = R4300i_UnknownOpcode;
+ R4300i_Regimm[28] = R4300i_UnknownOpcode;
+ R4300i_Regimm[29] = R4300i_UnknownOpcode;
+ R4300i_Regimm[30] = R4300i_UnknownOpcode;
+ R4300i_Regimm[31] = R4300i_UnknownOpcode;
+
+ R4300i_CoP0[ 0] = r4300i_COP0_MF;
+ R4300i_CoP0[ 1] = R4300i_UnknownOpcode;
+ R4300i_CoP0[ 2] = R4300i_UnknownOpcode;
+ R4300i_CoP0[ 3] = R4300i_UnknownOpcode;
+ R4300i_CoP0[ 4] = r4300i_COP0_MT;
+ R4300i_CoP0[ 5] = R4300i_UnknownOpcode;
+ R4300i_CoP0[ 6] = R4300i_UnknownOpcode;
+ R4300i_CoP0[ 7] = R4300i_UnknownOpcode;
+ R4300i_CoP0[ 8] = R4300i_UnknownOpcode;
+ R4300i_CoP0[ 9] = R4300i_UnknownOpcode;
+ R4300i_CoP0[10] = R4300i_UnknownOpcode;
+ R4300i_CoP0[11] = R4300i_UnknownOpcode;
+ R4300i_CoP0[12] = R4300i_UnknownOpcode;
+ R4300i_CoP0[13] = R4300i_UnknownOpcode;
+ R4300i_CoP0[14] = R4300i_UnknownOpcode;
+ R4300i_CoP0[15] = R4300i_UnknownOpcode;
+ R4300i_CoP0[16] = R4300i_opcode_COP0_CO;
+ R4300i_CoP0[17] = R4300i_opcode_COP0_CO;
+ R4300i_CoP0[18] = R4300i_opcode_COP0_CO;
+ R4300i_CoP0[19] = R4300i_opcode_COP0_CO;
+ R4300i_CoP0[20] = R4300i_opcode_COP0_CO;
+ R4300i_CoP0[21] = R4300i_opcode_COP0_CO;
+ R4300i_CoP0[22] = R4300i_opcode_COP0_CO;
+ R4300i_CoP0[23] = R4300i_opcode_COP0_CO;
+ R4300i_CoP0[24] = R4300i_opcode_COP0_CO;
+ R4300i_CoP0[25] = R4300i_opcode_COP0_CO;
+ R4300i_CoP0[26] = R4300i_opcode_COP0_CO;
+ R4300i_CoP0[27] = R4300i_opcode_COP0_CO;
+ R4300i_CoP0[28] = R4300i_opcode_COP0_CO;
+ R4300i_CoP0[29] = R4300i_opcode_COP0_CO;
+ R4300i_CoP0[30] = R4300i_opcode_COP0_CO;
+ R4300i_CoP0[31] = R4300i_opcode_COP0_CO;
+
+ R4300i_CoP0_Function[ 0] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[ 1] = r4300i_COP0_CO_TLBR;
+ R4300i_CoP0_Function[ 2] = r4300i_COP0_CO_TLBWI;
+ R4300i_CoP0_Function[ 3] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[ 4] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[ 5] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[ 6] = r4300i_COP0_CO_TLBWR;
+ R4300i_CoP0_Function[ 7] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[ 8] = r4300i_COP0_CO_TLBP;
+ R4300i_CoP0_Function[ 9] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[10] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[11] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[12] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[13] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[14] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[15] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[16] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[17] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[18] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[19] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[20] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[21] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[22] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[23] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[24] = r4300i_COP0_CO_ERET;
+ R4300i_CoP0_Function[25] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[26] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[27] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[28] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[29] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[30] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[31] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[32] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[33] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[34] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[35] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[36] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[37] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[38] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[39] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[40] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[41] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[42] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[43] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[44] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[45] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[46] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[47] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[48] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[49] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[50] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[51] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[52] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[53] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[54] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[55] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[56] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[57] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[58] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[59] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[60] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[61] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[62] = R4300i_UnknownOpcode;
+ R4300i_CoP0_Function[63] = R4300i_UnknownOpcode;
+
+ R4300i_CoP1[ 0] = r4300i_COP1_MF;
+ R4300i_CoP1[ 1] = r4300i_COP1_DMF;
+ R4300i_CoP1[ 2] = r4300i_COP1_CF;
+ R4300i_CoP1[ 3] = R4300i_UnknownOpcode;
+ R4300i_CoP1[ 4] = r4300i_COP1_MT;
+ R4300i_CoP1[ 5] = r4300i_COP1_DMT;
+ R4300i_CoP1[ 6] = r4300i_COP1_CT;
+ R4300i_CoP1[ 7] = R4300i_UnknownOpcode;
+ R4300i_CoP1[ 8] = R4300i_opcode_COP1_BC;
+ R4300i_CoP1[ 9] = R4300i_UnknownOpcode;
+ R4300i_CoP1[10] = R4300i_UnknownOpcode;
+ R4300i_CoP1[11] = R4300i_UnknownOpcode;
+ R4300i_CoP1[12] = R4300i_UnknownOpcode;
+ R4300i_CoP1[13] = R4300i_UnknownOpcode;
+ R4300i_CoP1[14] = R4300i_UnknownOpcode;
+ R4300i_CoP1[15] = R4300i_UnknownOpcode;
+ R4300i_CoP1[16] = R4300i_opcode_COP1_S;
+ R4300i_CoP1[17] = R4300i_opcode_COP1_D;
+ R4300i_CoP1[18] = R4300i_UnknownOpcode;
+ R4300i_CoP1[19] = R4300i_UnknownOpcode;
+ R4300i_CoP1[20] = R4300i_opcode_COP1_W;
+ R4300i_CoP1[21] = R4300i_opcode_COP1_L;
+ R4300i_CoP1[22] = R4300i_UnknownOpcode;
+ R4300i_CoP1[23] = R4300i_UnknownOpcode;
+ R4300i_CoP1[24] = R4300i_UnknownOpcode;
+ R4300i_CoP1[25] = R4300i_UnknownOpcode;
+ R4300i_CoP1[26] = R4300i_UnknownOpcode;
+ R4300i_CoP1[27] = R4300i_UnknownOpcode;
+ R4300i_CoP1[28] = R4300i_UnknownOpcode;
+ R4300i_CoP1[29] = R4300i_UnknownOpcode;
+ R4300i_CoP1[30] = R4300i_UnknownOpcode;
+ R4300i_CoP1[31] = R4300i_UnknownOpcode;
+
+ R4300i_CoP1_BC[ 0] = r4300i_COP1_BCF;
+ R4300i_CoP1_BC[ 1] = r4300i_COP1_BCT;
+ R4300i_CoP1_BC[ 2] = r4300i_COP1_BCFL;
+ R4300i_CoP1_BC[ 3] = r4300i_COP1_BCTL;
+ R4300i_CoP1_BC[ 4] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[ 5] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[ 6] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[ 7] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[ 8] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[ 9] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[10] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[11] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[12] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[13] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[14] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[15] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[16] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[17] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[18] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[19] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[20] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[21] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[22] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[23] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[24] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[25] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[26] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[27] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[28] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[29] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[30] = R4300i_UnknownOpcode;
+ R4300i_CoP1_BC[31] = R4300i_UnknownOpcode;
+
+ R4300i_CoP1_S[ 0] = r4300i_COP1_S_ADD;
+ R4300i_CoP1_S[ 1] = r4300i_COP1_S_SUB;
+ R4300i_CoP1_S[ 2] = r4300i_COP1_S_MUL;
+ R4300i_CoP1_S[ 3] = r4300i_COP1_S_DIV;
+ R4300i_CoP1_S[ 4] = r4300i_COP1_S_SQRT;
+ R4300i_CoP1_S[ 5] = r4300i_COP1_S_ABS;
+ R4300i_CoP1_S[ 6] = r4300i_COP1_S_MOV;
+ R4300i_CoP1_S[ 7] = r4300i_COP1_S_NEG;
+ R4300i_CoP1_S[ 8] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[ 9] = r4300i_COP1_S_TRUNC_L;
+ R4300i_CoP1_S[10] = r4300i_COP1_S_CEIL_L; //added by Witten
+ R4300i_CoP1_S[11] = r4300i_COP1_S_FLOOR_L; //added by Witten
+ R4300i_CoP1_S[12] = r4300i_COP1_S_ROUND_W;
+ R4300i_CoP1_S[13] = r4300i_COP1_S_TRUNC_W;
+ R4300i_CoP1_S[14] = r4300i_COP1_S_CEIL_W; //added by Witten
+ R4300i_CoP1_S[15] = r4300i_COP1_S_FLOOR_W;
+ R4300i_CoP1_S[16] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[17] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[18] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[19] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[20] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[21] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[22] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[23] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[24] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[25] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[26] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[27] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[28] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[29] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[30] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[31] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[32] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[33] = r4300i_COP1_S_CVT_D;
+ R4300i_CoP1_S[34] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[35] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[36] = r4300i_COP1_S_CVT_W;
+ R4300i_CoP1_S[37] = r4300i_COP1_S_CVT_L;
+ R4300i_CoP1_S[38] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[39] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[40] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[41] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[42] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[43] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[44] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[45] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[46] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[47] = R4300i_UnknownOpcode;
+ R4300i_CoP1_S[48] = r4300i_COP1_S_CMP;
+ R4300i_CoP1_S[49] = r4300i_COP1_S_CMP;
+ R4300i_CoP1_S[50] = r4300i_COP1_S_CMP;
+ R4300i_CoP1_S[51] = r4300i_COP1_S_CMP;
+ R4300i_CoP1_S[52] = r4300i_COP1_S_CMP;
+ R4300i_CoP1_S[53] = r4300i_COP1_S_CMP;
+ R4300i_CoP1_S[54] = r4300i_COP1_S_CMP;
+ R4300i_CoP1_S[55] = r4300i_COP1_S_CMP;
+ R4300i_CoP1_S[56] = r4300i_COP1_S_CMP;
+ R4300i_CoP1_S[57] = r4300i_COP1_S_CMP;
+ R4300i_CoP1_S[58] = r4300i_COP1_S_CMP;
+ R4300i_CoP1_S[59] = r4300i_COP1_S_CMP;
+ R4300i_CoP1_S[60] = r4300i_COP1_S_CMP;
+ R4300i_CoP1_S[61] = r4300i_COP1_S_CMP;
+ R4300i_CoP1_S[62] = r4300i_COP1_S_CMP;
+ R4300i_CoP1_S[63] = r4300i_COP1_S_CMP;
+
+ R4300i_CoP1_D[ 0] = r4300i_COP1_D_ADD;
+ R4300i_CoP1_D[ 1] = r4300i_COP1_D_SUB;
+ R4300i_CoP1_D[ 2] = r4300i_COP1_D_MUL;
+ R4300i_CoP1_D[ 3] = r4300i_COP1_D_DIV;
+ R4300i_CoP1_D[ 4] = r4300i_COP1_D_SQRT;
+ R4300i_CoP1_D[ 5] = r4300i_COP1_D_ABS;
+ R4300i_CoP1_D[ 6] = r4300i_COP1_D_MOV;
+ R4300i_CoP1_D[ 7] = r4300i_COP1_D_NEG;
+ R4300i_CoP1_D[ 8] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[ 9] = r4300i_COP1_D_TRUNC_L; //added by Witten
+ R4300i_CoP1_D[10] = r4300i_COP1_D_CEIL_L; //added by Witten
+ R4300i_CoP1_D[11] = r4300i_COP1_D_FLOOR_L; //added by Witten
+ R4300i_CoP1_D[12] = r4300i_COP1_D_ROUND_W;
+ R4300i_CoP1_D[13] = r4300i_COP1_D_TRUNC_W;
+ R4300i_CoP1_D[14] = r4300i_COP1_D_CEIL_W; //added by Witten
+ R4300i_CoP1_D[15] = r4300i_COP1_D_FLOOR_W; //added by Witten
+ R4300i_CoP1_D[16] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[17] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[18] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[19] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[20] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[21] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[22] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[23] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[24] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[25] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[26] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[27] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[28] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[29] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[30] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[31] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[32] = r4300i_COP1_D_CVT_S;
+ R4300i_CoP1_D[33] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[34] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[35] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[36] = r4300i_COP1_D_CVT_W;
+ R4300i_CoP1_D[37] = r4300i_COP1_D_CVT_L;
+ R4300i_CoP1_D[38] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[39] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[40] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[41] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[42] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[43] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[44] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[45] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[46] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[47] = R4300i_UnknownOpcode;
+ R4300i_CoP1_D[48] = r4300i_COP1_D_CMP;
+ R4300i_CoP1_D[49] = r4300i_COP1_D_CMP;
+ R4300i_CoP1_D[50] = r4300i_COP1_D_CMP;
+ R4300i_CoP1_D[51] = r4300i_COP1_D_CMP;
+ R4300i_CoP1_D[52] = r4300i_COP1_D_CMP;
+ R4300i_CoP1_D[53] = r4300i_COP1_D_CMP;
+ R4300i_CoP1_D[54] = r4300i_COP1_D_CMP;
+ R4300i_CoP1_D[55] = r4300i_COP1_D_CMP;
+ R4300i_CoP1_D[56] = r4300i_COP1_D_CMP;
+ R4300i_CoP1_D[57] = r4300i_COP1_D_CMP;
+ R4300i_CoP1_D[58] = r4300i_COP1_D_CMP;
+ R4300i_CoP1_D[59] = r4300i_COP1_D_CMP;
+ R4300i_CoP1_D[60] = r4300i_COP1_D_CMP;
+ R4300i_CoP1_D[61] = r4300i_COP1_D_CMP;
+ R4300i_CoP1_D[62] = r4300i_COP1_D_CMP;
+ R4300i_CoP1_D[63] = r4300i_COP1_D_CMP;
+
+ R4300i_CoP1_W[ 0] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[ 1] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[ 2] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[ 3] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[ 4] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[ 5] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[ 6] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[ 7] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[ 8] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[ 9] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[10] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[11] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[12] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[13] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[14] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[15] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[16] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[17] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[18] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[19] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[20] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[21] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[22] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[23] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[24] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[25] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[26] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[27] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[28] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[29] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[30] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[31] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[32] = r4300i_COP1_W_CVT_S;
+ R4300i_CoP1_W[33] = r4300i_COP1_W_CVT_D;
+ R4300i_CoP1_W[34] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[35] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[36] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[37] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[38] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[39] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[40] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[41] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[42] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[43] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[44] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[45] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[46] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[47] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[48] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[49] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[50] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[51] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[52] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[53] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[54] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[55] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[56] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[57] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[58] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[59] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[60] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[61] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[62] = R4300i_UnknownOpcode;
+ R4300i_CoP1_W[63] = R4300i_UnknownOpcode;
+
+ R4300i_CoP1_L[ 0] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[ 1] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[ 2] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[ 3] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[ 4] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[ 5] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[ 6] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[ 7] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[ 8] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[ 9] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[10] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[11] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[12] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[13] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[14] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[15] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[16] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[17] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[18] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[19] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[20] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[21] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[22] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[23] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[24] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[25] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[26] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[27] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[28] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[29] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[30] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[31] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[32] = r4300i_COP1_L_CVT_S;
+ R4300i_CoP1_L[33] = r4300i_COP1_L_CVT_D;
+ R4300i_CoP1_L[34] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[35] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[36] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[37] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[38] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[39] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[40] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[41] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[42] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[43] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[44] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[45] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[46] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[47] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[48] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[49] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[50] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[51] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[52] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[53] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[54] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[55] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[56] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[57] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[58] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[59] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[60] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[61] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[62] = R4300i_UnknownOpcode;
+ R4300i_CoP1_L[63] = R4300i_UnknownOpcode;
+}
+
+
+void ExecuteInterpreterOpCode (void) {
+
+
+ if (*WaitMode) Timers->Timer = -1;
+
+ if (!r4300i_LW_VAddr(PROGRAM_COUNTER, &Opcode.Hex)) {
+ DoTLBMiss(NextInstruction == JUMP,PROGRAM_COUNTER);
+ NextInstruction = NORMAL;
+ return;
+ }
+
+ COUNT_REGISTER += 2;
+ Timers->Timer -= 2;
+
+ RANDOM_REGISTER -= 1;
+ if ((int32_t)RANDOM_REGISTER < (int32_t)WIRED_REGISTER) {
+ RANDOM_REGISTER = 31;
+ }
+
+ R4300i_Opcode[ Opcode.op ]();
+
+ if (GPR[0].DW != 0) {
+ GPR[0].DW = 0;
+ }
+
+ switch (NextInstruction) {
+ case NORMAL:
+ PROGRAM_COUNTER += 4;
+ break;
+ case DELAY_SLOT:
+ NextInstruction = JUMP;
+ PROGRAM_COUNTER += 4;
+ break;
+ case JUMP:
+ PROGRAM_COUNTER = JumpToLocation;
+ NextInstruction = NORMAL;
+ if ((int32_t)Timers->Timer < 0) { TimerDone(); }
+ if (CPU_Action->DoSomething) { DoSomething(); }
+
+ }
+}
+
+void StartInterpreterCPU (void ) {
+ NextInstruction = NORMAL;
+
+ while(cpu_running) {
+ ExecuteInterpreterOpCode();
+ }
+
+ cpu_stopped = 1;
+
+}
+
+void TestInterpreterJump (uint32_t PC, uint32_t TargetPC, int32_t Reg1, int32_t Reg2) {
+ if (PC != TargetPC) { return; }
+ if (DelaySlotEffectsCompare(PC,Reg1,Reg2)) { return; }
+ if (CPU_Type != CPU_Interpreter) { return; }
+ InPermLoop();
+}
diff --git a/src/usf/interpreter_cpu.h b/src/usf/interpreter_cpu.h new file mode 100644 index 0000000..22f9bc2 --- /dev/null +++ b/src/usf/interpreter_cpu.h @@ -0,0 +1,37 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+#include <stdint.h>
+
+void BuildInterpreter ( void );
+void ExecuteInterpreterOpCode ( void );
+void StartInterpreterCPU ( void );
+void TestInterpreterJump ( uint32_t PC, uint32_t TargetPC, int32_t Reg1, int32_t Reg2 );
+
+
+
+
+
+extern void (* R4300i_Opcode[64])();
diff --git a/src/usf/interpreter_ops.c b/src/usf/interpreter_ops.c new file mode 100644 index 0000000..65c94f3 --- /dev/null +++ b/src/usf/interpreter_ops.c @@ -0,0 +1,1362 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+#include <stdio.h>
+#include <math.h>
+#include <float.h>
+#include <fpu_control.h>
+#include "main.h"
+#include "cpu.h"
+
+int32_t RoundingModel = _FPU_RC_NEAREST;
+
+#define ADDRESS_ERROR_EXCEPTION(Address,FromRead) \
+ DoAddressError(NextInstruction == JUMP,Address,FromRead);\
+ NextInstruction = JUMP;\
+ JumpToLocation = PROGRAM_COUNTER;\
+ return;
+
+//#define TEST_COP1_USABLE_EXCEPTION
+#define TEST_COP1_USABLE_EXCEPTION \
+ if ((STATUS_REGISTER & STATUS_CU1) == 0) {\
+ DoCopUnusableException(NextInstruction == JUMP,1);\
+ NextInstruction = JUMP;\
+ JumpToLocation = PROGRAM_COUNTER;\
+ return;\
+ }
+
+#define TLB_READ_EXCEPTION(Address) \
+ DoTLBMiss(NextInstruction == JUMP,Address);\
+ NextInstruction = JUMP;\
+ JumpToLocation = PROGRAM_COUNTER;\
+ return;
+
+/************************* OpCode functions *************************/
+void r4300i_J (void) {
+ NextInstruction = DELAY_SLOT;
+ JumpToLocation = (PROGRAM_COUNTER & 0xF0000000) + (Opcode.target << 2);
+ TestInterpreterJump(PROGRAM_COUNTER,JumpToLocation,0,0);
+}
+
+void r4300i_JAL (void) {
+ NextInstruction = DELAY_SLOT;
+ JumpToLocation = (PROGRAM_COUNTER & 0xF0000000) + (Opcode.target << 2);
+ TestInterpreterJump(PROGRAM_COUNTER,JumpToLocation,0,0);
+ GPR[31].DW= (int32_t)(PROGRAM_COUNTER + 8);
+}
+
+void r4300i_BEQ (void) {
+ NextInstruction = DELAY_SLOT;
+ if (GPR[Opcode.rs].DW == GPR[Opcode.rt].DW) {
+ JumpToLocation = PROGRAM_COUNTER + ((int16_t)Opcode.offset << 2) + 4;
+ TestInterpreterJump(PROGRAM_COUNTER,JumpToLocation,Opcode.rs,Opcode.rt);
+ } else {
+ JumpToLocation = PROGRAM_COUNTER + 8;
+ }
+}
+
+void r4300i_BNE (void) {
+ NextInstruction = DELAY_SLOT;
+ if (GPR[Opcode.rs].DW != GPR[Opcode.rt].DW) {
+ JumpToLocation = PROGRAM_COUNTER + ((int16_t)Opcode.offset << 2) + 4;
+ TestInterpreterJump(PROGRAM_COUNTER,JumpToLocation,Opcode.rs,Opcode.rt);
+ } else {
+ JumpToLocation = PROGRAM_COUNTER + 8;
+ }
+}
+
+void r4300i_BLEZ (void) {
+ NextInstruction = DELAY_SLOT;
+ if (GPR[Opcode.rs].DW <= 0) {
+ JumpToLocation = PROGRAM_COUNTER + ((int16_t)Opcode.offset << 2) + 4;
+ TestInterpreterJump(PROGRAM_COUNTER,JumpToLocation,Opcode.rs,0);
+ } else {
+ JumpToLocation = PROGRAM_COUNTER + 8;
+ }
+}
+
+void r4300i_BGTZ (void) {
+ NextInstruction = DELAY_SLOT;
+ if (GPR[Opcode.rs].DW > 0) {
+ JumpToLocation = PROGRAM_COUNTER + ((int16_t)Opcode.offset << 2) + 4;
+ TestInterpreterJump(PROGRAM_COUNTER,JumpToLocation,Opcode.rs,0);
+ } else {
+ JumpToLocation = PROGRAM_COUNTER + 8;
+ }
+}
+
+void r4300i_ADDI (void) {
+ if (Opcode.rt == 0) { return; }
+ GPR[Opcode.rt].DW = (GPR[Opcode.rs].W[0] + ((int16_t)Opcode.immediate));
+}
+
+void r4300i_ADDIU (void) {
+ GPR[Opcode.rt].DW = (GPR[Opcode.rs].W[0] + ((int16_t)Opcode.immediate));
+}
+
+void r4300i_SLTI (void) {
+ if (GPR[Opcode.rs].DW < (int64_t)((int16_t)Opcode.immediate)) {
+ GPR[Opcode.rt].DW = 1;
+ } else {
+ GPR[Opcode.rt].DW = 0;
+ }
+}
+
+void r4300i_SLTIU (void) {
+ int32_t imm32 = (int16_t)Opcode.immediate;
+ int64_t imm64;
+
+ imm64 = imm32;
+ GPR[Opcode.rt].DW = GPR[Opcode.rs].UDW < (uint64_t)imm64?1:0;
+}
+
+void r4300i_ANDI (void) {
+ GPR[Opcode.rt].DW = GPR[Opcode.rs].DW & Opcode.immediate;
+}
+
+void r4300i_ORI (void) {
+ GPR[Opcode.rt].DW = GPR[Opcode.rs].DW | Opcode.immediate;
+}
+
+void r4300i_XORI (void) {
+ GPR[Opcode.rt].DW = GPR[Opcode.rs].DW ^ Opcode.immediate;
+}
+
+void r4300i_LUI (void) {
+ if (Opcode.rt == 0) { return; }
+ GPR[Opcode.rt].DW = (int32_t)((int16_t)Opcode.offset << 16);
+}
+
+void r4300i_BEQL (void) {
+ if (GPR[Opcode.rs].DW == GPR[Opcode.rt].DW) {
+ NextInstruction = DELAY_SLOT;
+ JumpToLocation = PROGRAM_COUNTER + ((int16_t)Opcode.offset << 2) + 4;
+ TestInterpreterJump(PROGRAM_COUNTER,JumpToLocation,Opcode.rs,Opcode.rt);
+ } else {
+ NextInstruction = JUMP;
+ JumpToLocation = PROGRAM_COUNTER + 8;
+ }
+}
+
+void r4300i_BNEL (void) {
+ if (GPR[Opcode.rs].DW != GPR[Opcode.rt].DW) {
+ NextInstruction = DELAY_SLOT;
+ JumpToLocation = PROGRAM_COUNTER + ((int16_t)Opcode.offset << 2) + 4;
+ TestInterpreterJump(PROGRAM_COUNTER,JumpToLocation,Opcode.rs,Opcode.rt);
+ } else {
+ NextInstruction = JUMP;
+ JumpToLocation = PROGRAM_COUNTER + 8;
+ }
+}
+
+void r4300i_BLEZL (void) {
+ if (GPR[Opcode.rs].DW <= 0) {
+ NextInstruction = DELAY_SLOT;
+ JumpToLocation = PROGRAM_COUNTER + ((int16_t)Opcode.offset << 2) + 4;
+ TestInterpreterJump(PROGRAM_COUNTER,JumpToLocation,Opcode.rs,0);
+ } else {
+ NextInstruction = JUMP;
+ JumpToLocation = PROGRAM_COUNTER + 8;
+ }
+}
+
+void r4300i_BGTZL (void) {
+ if (GPR[Opcode.rs].DW > 0) {
+ NextInstruction = DELAY_SLOT;
+ JumpToLocation = PROGRAM_COUNTER + ((int16_t)Opcode.offset << 2) + 4;
+ TestInterpreterJump(PROGRAM_COUNTER,JumpToLocation,Opcode.rs,0);
+ } else {
+ NextInstruction = JUMP;
+ JumpToLocation = PROGRAM_COUNTER + 8;
+ }
+}
+
+void r4300i_DADDIU (void) {
+ GPR[Opcode.rt].DW = GPR[Opcode.rs].DW + (int64_t)((int16_t)Opcode.immediate);
+}
+
+uint64_t LDL_MASK[8] = { 0ULL,0xFFULL,0xFFFFULL,0xFFFFFFULL,0xFFFFFFFFULL,0xFFFFFFFFFFULL, 0xFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFULL };
+int32_t LDL_SHIFT[8] = { 0, 8, 16, 24, 32, 40, 48, 56 };
+
+void r4300i_LDL (void) {
+ uint32_t Offset, Address;
+ uint64_t Value;
+
+ Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ Offset = Address & 7;
+
+ if (!r4300i_LD_VAddr((Address & ~7),&Value)) {
+ return;
+ }
+ GPR[Opcode.rt].DW = GPR[Opcode.rt].DW & LDL_MASK[Offset];
+ GPR[Opcode.rt].DW += Value << LDL_SHIFT[Offset];
+}
+
+uint64_t LDR_MASK[8] = { 0xFFFFFFFFFFFFFF00ULL, 0xFFFFFFFFFFFF0000ULL,
+ 0xFFFFFFFFFF000000ULL, 0xFFFFFFFF00000000ULL,
+ 0xFFFFFF0000000000ULL, 0xFFFF000000000000ULL,
+ 0xFF00000000000000ULL, 0 };
+int32_t LDR_SHIFT[8] = { 56, 48, 40, 32, 24, 16, 8, 0 };
+
+void r4300i_LDR (void) {
+ uint32_t Offset, Address;
+ uint64_t Value;
+
+ Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ Offset = Address & 7;
+
+ if (!r4300i_LD_VAddr((Address & ~7),&Value)) {
+ return;
+ }
+
+ GPR[Opcode.rt].DW = GPR[Opcode.rt].DW & LDR_MASK[Offset];
+ GPR[Opcode.rt].DW += Value >> LDR_SHIFT[Offset];
+
+}
+
+void r4300i_LB (void) {
+ uint32_t Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ if (Opcode.rt == 0) { return; }
+ if (!r4300i_LB_VAddr(Address,&GPR[Opcode.rt].UB[0])) {
+ TLB_READ_EXCEPTION(Address);
+ } else {
+ GPR[Opcode.rt].DW = GPR[Opcode.rt].B[0];
+ }
+}
+
+void r4300i_LH (void) {
+ uint32_t Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ if ((Address & 1) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); }
+ if (!r4300i_LH_VAddr(Address,&GPR[Opcode.rt].UHW[0])) {
+ //if (ShowTLBMisses) {
+ DisplayError("LH TLB: %X",Address);
+ //}
+ TLB_READ_EXCEPTION(Address);
+ } else {
+ GPR[Opcode.rt].DW = GPR[Opcode.rt].HW[0];
+ }
+}
+
+uint32_t LWL_MASK[4] = { 0,0xFF,0xFFFF,0xFFFFFF };
+int32_t LWL_SHIFT[4] = { 0, 8, 16, 24};
+
+void r4300i_LWL (void) {
+ uint32_t Offset, Address, Value;
+
+ Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ Offset = Address & 3;
+
+ if (!r4300i_LW_VAddr((Address & ~3),&Value)) {
+ return;
+ }
+
+ GPR[Opcode.rt].DW = (int32_t)(GPR[Opcode.rt].W[0] & LWL_MASK[Offset]);
+ GPR[Opcode.rt].DW += (int32_t)(Value << LWL_SHIFT[Offset]);
+}
+
+void r4300i_LW (void) {
+ uint32_t Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+
+
+// if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); }
+
+ if (Opcode.rt == 0) { return; }
+
+
+ if (!r4300i_LW_VAddr(Address,&GPR[Opcode.rt].UW[0])) {
+ //if (ShowTLBMisses) {
+ printf("LW TLB: %X",Address);
+ //}
+ TLB_READ_EXCEPTION(Address);
+ } else {
+ GPR[Opcode.rt].DW = GPR[Opcode.rt].W[0];
+ }
+}
+
+void r4300i_LBU (void) {
+ uint32_t Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ if (!r4300i_LB_VAddr(Address,&GPR[Opcode.rt].UB[0])) {
+ //if (ShowTLBMisses) {
+ DisplayError("LBU TLB: %X",Address);
+ //}
+ TLB_READ_EXCEPTION(Address);
+ } else {
+ GPR[Opcode.rt].UDW = GPR[Opcode.rt].UB[0];
+ }
+}
+
+void r4300i_LHU (void) {
+ uint32_t Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ if ((Address & 1) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); }
+ if (!r4300i_LH_VAddr(Address,&GPR[Opcode.rt].UHW[0])) {
+ //if (ShowTLBMisses) {
+ DisplayError("LHU TLB: %X",Address);
+ //}
+ TLB_READ_EXCEPTION(Address);
+ } else {
+ GPR[Opcode.rt].UDW = GPR[Opcode.rt].UHW[0];
+ }
+}
+
+uint32_t LWR_MASK[4] = { 0xFFFFFF00, 0xFFFF0000, 0xFF000000, 0 };
+int32_t LWR_SHIFT[4] = { 24, 16 ,8, 0 };
+
+void r4300i_LWR (void) {
+ uint32_t Offset, Address, Value;
+
+ Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ Offset = Address & 3;
+
+ if (!r4300i_LW_VAddr((Address & ~3),&Value)) {
+ return;
+ }
+
+ GPR[Opcode.rt].DW = (int32_t)(GPR[Opcode.rt].W[0] & LWR_MASK[Offset]);
+ GPR[Opcode.rt].DW += (int32_t)(Value >> LWR_SHIFT[Offset]);
+}
+
+void r4300i_LWU (void) {
+ uint32_t Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); }
+ if (Opcode.rt == 0) { return; }
+
+ if (!r4300i_LW_VAddr(Address,&GPR[Opcode.rt].UW[0])) {
+ //if (ShowTLBMisses) {
+ DisplayError("LWU TLB: %X",Address);
+ //}
+ TLB_READ_EXCEPTION(Address);
+ } else {
+ GPR[Opcode.rt].UDW = GPR[Opcode.rt].UW[0];
+ }
+}
+
+void r4300i_SB (void) {
+ uint32_t Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ if (!r4300i_SB_VAddr(Address,GPR[Opcode.rt].UB[0])) {
+ }
+}
+
+void r4300i_SH (void) {
+ uint32_t Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ if ((Address & 1) != 0) { ADDRESS_ERROR_EXCEPTION(Address,0); }
+ if (!r4300i_SH_VAddr(Address,GPR[Opcode.rt].UHW[0])) {
+ }
+}
+
+uint32_t SWL_MASK[4] = { 0,0xFF000000,0xFFFF0000,0xFFFFFF00 };
+int32_t SWL_SHIFT[4] = { 0, 8, 16, 24 };
+
+void r4300i_SWL (void) {
+ uint32_t Offset, Address, Value;
+
+ Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ Offset = Address & 3;
+
+ if (!r4300i_LW_VAddr((Address & ~3),&Value)) {
+ return;
+ }
+
+ Value &= SWL_MASK[Offset];
+ Value += GPR[Opcode.rt].UW[0] >> SWL_SHIFT[Offset];
+
+ if (!r4300i_SW_VAddr((Address & ~0x03),Value)) {
+ }
+}
+
+
+void r4300i_SW (void) {
+ uint32_t Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,0); }
+ if (!r4300i_SW_VAddr(Address,GPR[Opcode.rt].UW[0])) {
+ }
+ //TranslateVaddr(&Address);
+ //if (Address == 0x00090AA0) {
+ // LogMessage("%X: Write %X to %X",PROGRAM_COUNTER,GPR[Opcode.rt].UW[0],GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset);
+ //}
+}
+
+uint64_t SDL_MASK[8] = { 0,0xFF00000000000000ULL,
+ 0xFFFF000000000000ULL,
+ 0xFFFFFF0000000000ULL,
+ 0xFFFFFFFF00000000ULL,
+ 0xFFFFFFFFFF000000ULL,
+ 0xFFFFFFFFFFFF0000ULL,
+ 0xFFFFFFFFFFFFFF00ULL
+ };
+int32_t SDL_SHIFT[8] = { 0, 8, 16, 24, 32, 40, 48, 56 };
+
+void r4300i_SDL (void) {
+ uint32_t Offset, Address;
+ uint64_t Value;
+
+ Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ Offset = Address & 7;
+
+ if (!r4300i_LD_VAddr((Address & ~7),&Value)) {
+ return;
+ }
+
+ Value &= SDL_MASK[Offset];
+ Value += GPR[Opcode.rt].UDW >> SDL_SHIFT[Offset];
+
+ if (!r4300i_SD_VAddr((Address & ~7),Value)) {
+ }
+}
+
+uint64_t SDR_MASK[8] = { 0x00FFFFFFFFFFFFFFULL,
+ 0x0000FFFFFFFFFFFFULL,
+ 0x000000FFFFFFFFFFULL,
+ 0x00000000FFFFFFFFULL,
+ 0x0000000000FFFFFFULL,
+ 0x000000000000FFFFULL,
+ 0x00000000000000FFULL,
+ 0x0000000000000000ULL
+ };
+int32_t SDR_SHIFT[8] = { 56,48,40,32,24,16,8,0 };
+
+void r4300i_SDR (void) {
+ uint32_t Offset, Address;
+ uint64_t Value;
+
+ Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ Offset = Address & 7;
+
+ if (!r4300i_LD_VAddr((Address & ~7),&Value)) {
+ return;
+ }
+
+ Value &= SDR_MASK[Offset];
+ Value += GPR[Opcode.rt].UDW << SDR_SHIFT[Offset];
+
+ if (!r4300i_SD_VAddr((Address & ~7),Value)) {
+ }
+}
+
+uint32_t SWR_MASK[4] = { 0x00FFFFFF,0x0000FFFF,0x000000FF,0x00000000 };
+int32_t SWR_SHIFT[4] = { 24, 16 , 8, 0 };
+
+void r4300i_SWR (void) {
+ uint32_t Offset, Address, Value;
+
+ Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ Offset = Address & 3;
+
+ if (!r4300i_LW_VAddr((Address & ~3),&Value)) {
+ return;
+ }
+
+ Value &= SWR_MASK[Offset];
+ Value += GPR[Opcode.rt].UW[0] << SWR_SHIFT[Offset];
+
+ if (!r4300i_SW_VAddr((Address & ~0x03),Value)) {
+ }
+}
+
+void r4300i_CACHE (void) {
+}
+
+void r4300i_LL (void) {
+ uint32_t Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ uintptr_t ll = 0;
+ if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); }
+
+ if (Opcode.rt == 0) { return; }
+
+ if (!r4300i_LW_VAddr(Address,&GPR[Opcode.rt].UW[0])) {
+ //if (ShowTLBMisses) {
+ DisplayError("LW TLB: %X",Address);
+ //}
+ TLB_READ_EXCEPTION(Address);
+ } else {
+ GPR[Opcode.rt].DW = GPR[Opcode.rt].W[0];
+ }
+ LLBit = 1;
+ LLAddr = Address;
+ ll = LLAddr;
+ TranslateVaddr(&ll);
+ LLAddr = ll;
+
+}
+
+void r4300i_LWC1 (void) {
+ uint32_t Address = GPR[Opcode.base].UW[0] + (uint32_t)((int16_t)Opcode.offset);
+ TEST_COP1_USABLE_EXCEPTION
+ if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); }
+ if (!r4300i_LW_VAddr(Address,&*(uint32_t *)FPRFloatLocation[Opcode.ft])) {
+ //if (ShowTLBMisses) {
+ DisplayError("LWC1 TLB: %X",Address);
+ //}
+ TLB_READ_EXCEPTION(Address);
+ }
+}
+
+void r4300i_SC (void) {
+ uint32_t Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,0); }
+ if (LLBit == 1) {
+ if (!r4300i_SW_VAddr(Address,GPR[Opcode.rt].UW[0])) {
+ DisplayError("SW TLB: %X",Address);
+ }
+ }
+ GPR[Opcode.rt].UW[0] = LLBit;
+}
+
+void r4300i_LD (void) {
+ uint32_t Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ if ((Address & 7) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); }
+ if (!r4300i_LD_VAddr(Address,&GPR[Opcode.rt].UDW)) {
+ }
+}
+
+
+void r4300i_LDC1 (void) {
+ uint32_t Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+
+ TEST_COP1_USABLE_EXCEPTION
+ if ((Address & 7) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); }
+ if (!r4300i_LD_VAddr(Address,&*(uint64_t *)FPRDoubleLocation[Opcode.ft])) {
+ }
+}
+
+void r4300i_SWC1 (void) {
+ uint32_t Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ TEST_COP1_USABLE_EXCEPTION
+ if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,0); }
+
+ if (!r4300i_SW_VAddr(Address,*(uint32_t *)FPRFloatLocation[Opcode.ft])) {
+ }
+}
+
+void r4300i_SDC1 (void) {
+ uint32_t Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+
+ TEST_COP1_USABLE_EXCEPTION
+ if ((Address & 7) != 0) { ADDRESS_ERROR_EXCEPTION(Address,0); }
+ if (!r4300i_SD_VAddr(Address,*(int64_t *)FPRDoubleLocation[Opcode.ft])) {
+ }
+}
+
+void r4300i_SD (void) {
+ uint32_t Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
+ if ((Address & 7) != 0) { ADDRESS_ERROR_EXCEPTION(Address,0); }
+ if (!r4300i_SD_VAddr(Address,GPR[Opcode.rt].UDW)) {
+ }
+}
+/********************** R4300i OpCodes: Special **********************/
+void r4300i_SPECIAL_SLL (void) {
+ GPR[Opcode.rd].DW = (GPR[Opcode.rt].W[0] << Opcode.sa);
+}
+
+void r4300i_SPECIAL_SRL (void) {
+ GPR[Opcode.rd].DW = (int32_t)(GPR[Opcode.rt].UW[0] >> Opcode.sa);
+}
+
+void r4300i_SPECIAL_SRA (void) {
+ GPR[Opcode.rd].DW = (GPR[Opcode.rt].W[0] >> Opcode.sa);
+}
+
+void r4300i_SPECIAL_SLLV (void) {
+ if (Opcode.rd == 0) { return; }
+ GPR[Opcode.rd].DW = (GPR[Opcode.rt].W[0] << (GPR[Opcode.rs].UW[0] & 0x1F));
+}
+
+void r4300i_SPECIAL_SRLV (void) {
+ GPR[Opcode.rd].DW = (int32_t)(GPR[Opcode.rt].UW[0] >> (GPR[Opcode.rs].UW[0] & 0x1F));
+}
+
+void r4300i_SPECIAL_SRAV (void) {
+ GPR[Opcode.rd].DW = (GPR[Opcode.rt].W[0] >> (GPR[Opcode.rs].UW[0] & 0x1F));
+}
+
+void r4300i_SPECIAL_JR (void) {
+ NextInstruction = DELAY_SLOT;
+ JumpToLocation = GPR[Opcode.rs].UW[0];
+}
+
+void r4300i_SPECIAL_JALR (void) {
+ NextInstruction = DELAY_SLOT;
+ JumpToLocation = GPR[Opcode.rs].UW[0];
+ GPR[Opcode.rd].DW = (int32_t)(PROGRAM_COUNTER + 8);
+}
+
+void r4300i_SPECIAL_SYSCALL (void) {
+ DoSysCallException(NextInstruction == JUMP);
+ NextInstruction = JUMP;
+ JumpToLocation = PROGRAM_COUNTER;
+}
+
+void r4300i_SPECIAL_BREAK (void) {
+ *WaitMode=1;
+}
+
+void r4300i_SPECIAL_SYNC (void) {
+}
+
+void r4300i_SPECIAL_MFHI (void) {
+ GPR[Opcode.rd].DW = HI.DW;
+}
+
+void r4300i_SPECIAL_MTHI (void) {
+ HI.DW = GPR[Opcode.rs].DW;
+}
+
+void r4300i_SPECIAL_MFLO (void) {
+ GPR[Opcode.rd].DW = LO.DW;
+}
+
+void r4300i_SPECIAL_MTLO (void) {
+ LO.DW = GPR[Opcode.rs].DW;
+}
+
+void r4300i_SPECIAL_DSLLV (void) {
+ GPR[Opcode.rd].DW = GPR[Opcode.rt].DW << (GPR[Opcode.rs].UW[0] & 0x3F);
+}
+
+void r4300i_SPECIAL_DSRLV (void) {
+ GPR[Opcode.rd].UDW = GPR[Opcode.rt].UDW >> (GPR[Opcode.rs].UW[0] & 0x3F);
+}
+
+void r4300i_SPECIAL_DSRAV (void) {
+ GPR[Opcode.rd].DW = GPR[Opcode.rt].DW >> (GPR[Opcode.rs].UW[0] & 0x3F);
+}
+
+void r4300i_SPECIAL_MULT (void) {
+ HI.DW = (int64_t)(GPR[Opcode.rs].W[0]) * (int64_t)(GPR[Opcode.rt].W[0]);
+ LO.DW = HI.W[0];
+ HI.DW = HI.W[1];
+}
+
+void r4300i_SPECIAL_MULTU (void) {
+ HI.DW = (uint64_t)(GPR[Opcode.rs].UW[0]) * (uint64_t)(GPR[Opcode.rt].UW[0]);
+ LO.DW = HI.W[0];
+ HI.DW = HI.W[1];
+}
+
+void r4300i_SPECIAL_DIV (void) {
+ if ( GPR[Opcode.rt].UDW != 0 ) {
+ LO.DW = GPR[Opcode.rs].W[0] / GPR[Opcode.rt].W[0];
+ HI.DW = GPR[Opcode.rs].W[0] % GPR[Opcode.rt].W[0];
+ } else {
+ }
+}
+
+void r4300i_SPECIAL_DIVU (void) {
+ if ( GPR[Opcode.rt].UDW != 0 ) {
+ LO.DW = (int32_t)(GPR[Opcode.rs].UW[0] / GPR[Opcode.rt].UW[0]);
+ HI.DW = (int32_t)(GPR[Opcode.rs].UW[0] % GPR[Opcode.rt].UW[0]);
+ } else {
+ }
+}
+
+void r4300i_SPECIAL_DMULT (void) {
+ MIPS_DWORD Tmp[3];
+
+ LO.UDW = (uint64_t)GPR[Opcode.rs].UW[0] * (uint64_t)GPR[Opcode.rt].UW[0];
+ Tmp[0].UDW = (int64_t)GPR[Opcode.rs].W[1] * (int64_t)(uint64_t)GPR[Opcode.rt].UW[0];
+ Tmp[1].UDW = (int64_t)(uint64_t)GPR[Opcode.rs].UW[0] * (int64_t)GPR[Opcode.rt].W[1];
+ HI.UDW = (int64_t)GPR[Opcode.rs].W[1] * (int64_t)GPR[Opcode.rt].W[1];
+
+ Tmp[2].UDW = (uint64_t)LO.UW[1] + (uint64_t)Tmp[0].UW[0] + (uint64_t)Tmp[1].UW[0];
+ LO.UDW += ((uint64_t)Tmp[0].UW[0] + (uint64_t)Tmp[1].UW[0]) << 32;
+ HI.UDW += (uint64_t)Tmp[0].W[1] + (uint64_t)Tmp[1].W[1] + Tmp[2].UW[1];
+}
+
+void r4300i_SPECIAL_DMULTU (void) {
+ MIPS_DWORD Tmp[3];
+
+ LO.UDW = (uint64_t)GPR[Opcode.rs].UW[0] * (uint64_t)GPR[Opcode.rt].UW[0];
+ Tmp[0].UDW = (uint64_t)GPR[Opcode.rs].UW[1] * (uint64_t)GPR[Opcode.rt].UW[0];
+ Tmp[1].UDW = (uint64_t)GPR[Opcode.rs].UW[0] * (uint64_t)GPR[Opcode.rt].UW[1];
+ HI.UDW = (uint64_t)GPR[Opcode.rs].UW[1] * (uint64_t)GPR[Opcode.rt].UW[1];
+
+ Tmp[2].UDW = (uint64_t)LO.UW[1] + (uint64_t)Tmp[0].UW[0] + (uint64_t)Tmp[1].UW[0];
+ LO.UDW += ((uint64_t)Tmp[0].UW[0] + (uint64_t)Tmp[1].UW[0]) << 32;
+ HI.UDW += (uint64_t)Tmp[0].UW[1] + (uint64_t)Tmp[1].UW[1] + Tmp[2].UW[1];
+}
+
+void r4300i_SPECIAL_DDIV (void) {
+ if ( GPR[Opcode.rt].UDW != 0 ) {
+ LO.DW = GPR[Opcode.rs].DW / GPR[Opcode.rt].DW;
+ HI.DW = GPR[Opcode.rs].DW % GPR[Opcode.rt].DW;
+ } else {
+ }
+}
+
+void r4300i_SPECIAL_DDIVU (void) {
+ if ( GPR[Opcode.rt].UDW != 0 ) {
+ LO.UDW = GPR[Opcode.rs].UDW / GPR[Opcode.rt].UDW;
+ HI.UDW = GPR[Opcode.rs].UDW % GPR[Opcode.rt].UDW;
+ } else {
+ }
+}
+
+void r4300i_SPECIAL_ADD (void) {
+ GPR[Opcode.rd].DW = GPR[Opcode.rs].W[0] + GPR[Opcode.rt].W[0];
+}
+
+void r4300i_SPECIAL_ADDU (void) {
+ GPR[Opcode.rd].DW = GPR[Opcode.rs].W[0] + GPR[Opcode.rt].W[0];
+}
+
+void r4300i_SPECIAL_SUB (void) {
+ GPR[Opcode.rd].DW = GPR[Opcode.rs].W[0] - GPR[Opcode.rt].W[0];
+}
+
+void r4300i_SPECIAL_SUBU (void) {
+ GPR[Opcode.rd].DW = GPR[Opcode.rs].W[0] - GPR[Opcode.rt].W[0];
+}
+
+void r4300i_SPECIAL_AND (void) {
+ GPR[Opcode.rd].DW = GPR[Opcode.rs].DW & GPR[Opcode.rt].DW;
+}
+
+void r4300i_SPECIAL_OR (void) {
+ GPR[Opcode.rd].DW = GPR[Opcode.rs].DW | GPR[Opcode.rt].DW;
+}
+
+void r4300i_SPECIAL_XOR (void) {
+ GPR[Opcode.rd].DW = GPR[Opcode.rs].DW ^ GPR[Opcode.rt].DW;
+}
+
+void r4300i_SPECIAL_NOR (void) {
+ GPR[Opcode.rd].DW = ~(GPR[Opcode.rs].DW | GPR[Opcode.rt].DW);
+}
+
+void r4300i_SPECIAL_SLT (void) {
+ if (GPR[Opcode.rs].DW < GPR[Opcode.rt].DW) {
+ GPR[Opcode.rd].DW = 1;
+ } else {
+ GPR[Opcode.rd].DW = 0;
+ }
+}
+
+void r4300i_SPECIAL_SLTU (void) {
+ if (GPR[Opcode.rs].UDW < GPR[Opcode.rt].UDW) {
+ GPR[Opcode.rd].DW = 1;
+ } else {
+ GPR[Opcode.rd].DW = 0;
+ }
+}
+
+void r4300i_SPECIAL_DADD (void) {
+ GPR[Opcode.rd].DW = GPR[Opcode.rs].DW + GPR[Opcode.rt].DW;
+}
+
+void r4300i_SPECIAL_DADDU (void) {
+ GPR[Opcode.rd].DW = GPR[Opcode.rs].DW + GPR[Opcode.rt].DW;
+}
+
+void r4300i_SPECIAL_DSUB (void) {
+ GPR[Opcode.rd].DW = GPR[Opcode.rs].DW - GPR[Opcode.rt].DW;
+}
+
+void r4300i_SPECIAL_DSUBU (void) {
+ GPR[Opcode.rd].DW = GPR[Opcode.rs].DW - GPR[Opcode.rt].DW;
+}
+
+void r4300i_SPECIAL_TEQ (void) {
+ if (GPR[Opcode.rs].DW == GPR[Opcode.rt].DW) {
+ }
+}
+
+void r4300i_SPECIAL_DSLL (void) {
+ GPR[Opcode.rd].DW = (GPR[Opcode.rt].DW << Opcode.sa);
+}
+
+void r4300i_SPECIAL_DSRL (void) {
+ GPR[Opcode.rd].UDW = (GPR[Opcode.rt].UDW >> Opcode.sa);
+}
+
+void r4300i_SPECIAL_DSRA (void) {
+ GPR[Opcode.rd].DW = (GPR[Opcode.rt].DW >> Opcode.sa);
+}
+
+void r4300i_SPECIAL_DSLL32 (void) {
+ GPR[Opcode.rd].DW = (GPR[Opcode.rt].DW << (Opcode.sa + 32));
+}
+
+void r4300i_SPECIAL_DSRL32 (void) {
+ GPR[Opcode.rd].UDW = (GPR[Opcode.rt].UDW >> (Opcode.sa + 32));
+}
+
+void r4300i_SPECIAL_DSRA32 (void) {
+ GPR[Opcode.rd].DW = (GPR[Opcode.rt].DW >> (Opcode.sa + 32));
+}
+
+/********************** R4300i OpCodes: RegImm **********************/
+void r4300i_REGIMM_BLTZ (void) {
+ NextInstruction = DELAY_SLOT;
+ if (GPR[Opcode.rs].DW < 0) {
+ JumpToLocation = PROGRAM_COUNTER + ((int16_t)Opcode.offset << 2) + 4;
+ TestInterpreterJump(PROGRAM_COUNTER,JumpToLocation,Opcode.rs,0);
+ } else {
+ JumpToLocation = PROGRAM_COUNTER + 8;
+ }
+}
+
+void r4300i_REGIMM_BGEZ (void) {
+ NextInstruction = DELAY_SLOT;
+ if (GPR[Opcode.rs].DW >= 0) {
+ JumpToLocation = PROGRAM_COUNTER + ((int16_t)Opcode.offset << 2) + 4;
+ TestInterpreterJump(PROGRAM_COUNTER,JumpToLocation,Opcode.rs,0);
+ } else {
+ JumpToLocation = PROGRAM_COUNTER + 8;
+ }
+}
+
+void r4300i_REGIMM_BLTZL (void) {
+ if (GPR[Opcode.rs].DW < 0) {
+ NextInstruction = DELAY_SLOT;
+ JumpToLocation = PROGRAM_COUNTER + ((int16_t)Opcode.offset << 2) + 4;
+ TestInterpreterJump(PROGRAM_COUNTER,JumpToLocation,Opcode.rs,0);
+ } else {
+ NextInstruction = JUMP;
+ JumpToLocation = PROGRAM_COUNTER + 8;
+ }
+}
+
+void r4300i_REGIMM_BGEZL (void) {
+ if (GPR[Opcode.rs].DW >= 0) {
+ NextInstruction = DELAY_SLOT;
+ JumpToLocation = PROGRAM_COUNTER + ((int16_t)Opcode.offset << 2) + 4;
+ TestInterpreterJump(PROGRAM_COUNTER,JumpToLocation,Opcode.rs,0);
+ } else {
+ NextInstruction = JUMP;
+ JumpToLocation = PROGRAM_COUNTER + 8;
+ }
+}
+
+void r4300i_REGIMM_BLTZAL (void) {
+ NextInstruction = DELAY_SLOT;
+ if (GPR[Opcode.rs].DW < 0) {
+ JumpToLocation = PROGRAM_COUNTER + ((int16_t)Opcode.offset << 2) + 4;
+ TestInterpreterJump(PROGRAM_COUNTER,JumpToLocation,Opcode.rs,0);
+ } else {
+ JumpToLocation = PROGRAM_COUNTER + 8;
+ }
+ GPR[31].DW= (int32_t)(PROGRAM_COUNTER + 8);
+}
+
+void r4300i_REGIMM_BGEZAL (void) {
+ NextInstruction = DELAY_SLOT;
+ if (GPR[Opcode.rs].DW >= 0) {
+ JumpToLocation = PROGRAM_COUNTER + ((int16_t)Opcode.offset << 2) + 4;
+ TestInterpreterJump(PROGRAM_COUNTER,JumpToLocation,Opcode.rs,0);
+ } else {
+ JumpToLocation = PROGRAM_COUNTER + 8;
+ }
+ GPR[31].DW = (int32_t)(PROGRAM_COUNTER + 8);
+}
+/************************** COP0 functions **************************/
+void r4300i_COP0_MF (void) {
+ GPR[Opcode.rt].DW = (int32_t)CP0[Opcode.rd];
+}
+
+void r4300i_COP0_MT (void) {
+ switch (Opcode.rd) {
+ case 0: //Index
+ case 2: //EntryLo0
+ case 3: //EntryLo1
+ case 5: //PageMask
+ case 6: //Wired
+ case 10: //Entry Hi
+ case 14: //EPC
+ case 16: //Config
+ case 18: //WatchLo
+ case 19: //WatchHi
+ case 28: //Tag lo
+ case 29: //Tag Hi
+ case 30: //ErrEPC
+ CP0[Opcode.rd] = GPR[Opcode.rt].UW[0];
+ break;
+ case 4: //Context
+ CP0[Opcode.rd] = GPR[Opcode.rt].UW[0] & 0xFF800000;
+ break;
+ case 9: //Count
+ CP0[Opcode.rd]= GPR[Opcode.rt].UW[0];
+ ChangeCompareTimer();
+ break;
+ case 11: //Compare
+ CP0[Opcode.rd] = GPR[Opcode.rt].UW[0];
+ FAKE_CAUSE_REGISTER &= ~CAUSE_IP7;
+ ChangeCompareTimer();
+ break;
+ case 12: //Status
+ if ((CP0[Opcode.rd] ^ GPR[Opcode.rt].UW[0]) != 0) {
+ CP0[Opcode.rd] = GPR[Opcode.rt].UW[0];
+ SetFpuLocations();
+ } else {
+ CP0[Opcode.rd] = GPR[Opcode.rt].UW[0];
+ }
+ if ((CP0[Opcode.rd] & 0x18) != 0) {
+ }
+ CheckInterrupts();
+ break;
+ case 13: //cause
+ CP0[Opcode.rd] &= 0xFFFFCFF;
+ break;
+ default:
+ R4300i_UnknownOpcode();
+ }
+
+}
+
+/************************** COP0 CO functions ***********************/
+void r4300i_COP0_CO_TLBR (void) {
+ TLB_Read();
+}
+
+void r4300i_COP0_CO_TLBWI (void) {
+ WriteTLBEntry(INDEX_REGISTER & 0x1F);
+}
+
+void r4300i_COP0_CO_TLBWR (void) {
+ WriteTLBEntry(RANDOM_REGISTER & 0x1F);
+}
+
+void r4300i_COP0_CO_TLBP (void) {
+ TLB_Probe();
+}
+
+void r4300i_COP0_CO_ERET (void) {
+ NextInstruction = JUMP;
+ if ((STATUS_REGISTER & STATUS_ERL) != 0) {
+ JumpToLocation = ERROREPC_REGISTER;
+ STATUS_REGISTER &= ~STATUS_ERL;
+ } else {
+ JumpToLocation = EPC_REGISTER;
+ STATUS_REGISTER &= ~STATUS_EXL;
+ }
+ LLBit = 0;
+ CheckInterrupts();
+}
+
+/************************** COP1 functions **************************/
+void r4300i_COP1_MF (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ GPR[Opcode.rt].DW = *(int32_t *)FPRFloatLocation[Opcode.fs];
+}
+
+void r4300i_COP1_DMF (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ GPR[Opcode.rt].DW = *(int64_t *)FPRDoubleLocation[Opcode.fs];
+}
+
+void r4300i_COP1_CF (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ if (Opcode.fs != 31 && Opcode.fs != 0) {
+ return;
+ }
+ GPR[Opcode.rt].DW = (int32_t)FPCR[Opcode.fs];
+}
+
+void r4300i_COP1_MT (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ *(int32_t *)FPRFloatLocation[Opcode.fs] = GPR[Opcode.rt].W[0];
+}
+
+void r4300i_COP1_DMT (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ *(int64_t *)FPRDoubleLocation[Opcode.fs] = GPR[Opcode.rt].DW;
+}
+
+void r4300i_COP1_CT (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ if (Opcode.fs == 31) {
+ FPCR[Opcode.fs] = GPR[Opcode.rt].W[0];
+ switch((FPCR[Opcode.fs] & 3)) {
+ case 0: RoundingModel = _FPU_RC_NEAREST; break;
+ case 1: RoundingModel = _FPU_RC_ZERO; break;
+ case 2: RoundingModel = _FPU_RC_UP; break;
+ case 3: RoundingModel = _FPU_RC_DOWN; break;
+ }
+ return;
+ }
+}
+
+/************************* COP1: BC1 functions ***********************/
+void r4300i_COP1_BCF (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ NextInstruction = DELAY_SLOT;
+ if ((FPCR[31] & FPCSR_C) == 0) {
+ JumpToLocation = PROGRAM_COUNTER + ((int16_t)Opcode.offset << 2) + 4;
+ } else {
+ JumpToLocation = PROGRAM_COUNTER + 8;
+ }
+}
+
+void r4300i_COP1_BCT (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ NextInstruction = DELAY_SLOT;
+ if ((FPCR[31] & FPCSR_C) != 0) {
+ JumpToLocation = PROGRAM_COUNTER + ((int16_t)Opcode.offset << 2) + 4;
+ } else {
+ JumpToLocation = PROGRAM_COUNTER + 8;
+ }
+}
+
+void r4300i_COP1_BCFL (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ if ((FPCR[31] & FPCSR_C) == 0) {
+ NextInstruction = DELAY_SLOT;
+ JumpToLocation = PROGRAM_COUNTER + ((int16_t)Opcode.offset << 2) + 4;
+ } else {
+ NextInstruction = JUMP;
+ JumpToLocation = PROGRAM_COUNTER + 8;
+ }
+}
+
+void r4300i_COP1_BCTL (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ if ((FPCR[31] & FPCSR_C) != 0) {
+ NextInstruction = DELAY_SLOT;
+ JumpToLocation = PROGRAM_COUNTER + ((int16_t)Opcode.offset << 2) + 4;
+ } else {
+ NextInstruction = JUMP;
+ JumpToLocation = PROGRAM_COUNTER + 8;
+ }
+}
+/************************** COP1: S functions ************************/
+__inline void Float_RoundToInteger32( int32_t * Dest, float * Source ) {
+ *Dest = (int32_t)*Source;
+}
+
+__inline void Float_RoundToInteger64( int64_t * Dest, float * Source ) {
+ *Dest = (int64_t)*Source;
+}
+
+void r4300i_COP1_S_ADD (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(RoundingModel);
+ *(float *)FPRFloatLocation[Opcode.fd] = (*(float *)FPRFloatLocation[Opcode.fs] + *(float *)FPRFloatLocation[Opcode.ft]);
+}
+
+void r4300i_COP1_S_SUB (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(RoundingModel);
+ *(float *)FPRFloatLocation[Opcode.fd] = (*(float *)FPRFloatLocation[Opcode.fs] - *(float *)FPRFloatLocation[Opcode.ft]);
+}
+
+void r4300i_COP1_S_MUL (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(RoundingModel);
+ *(float *)FPRFloatLocation[Opcode.fd] = (*(float *)FPRFloatLocation[Opcode.fs] * *(float *)FPRFloatLocation[Opcode.ft]);
+}
+
+void r4300i_COP1_S_DIV (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(RoundingModel);
+ *(float *)FPRFloatLocation[Opcode.fd] = (*(float *)FPRFloatLocation[Opcode.fs] / *(float *)FPRFloatLocation[Opcode.ft]);
+}
+
+void r4300i_COP1_S_SQRT (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(RoundingModel);
+ *(float *)FPRFloatLocation[Opcode.fd] = (float)sqrt(*(float *)FPRFloatLocation[Opcode.fs]);
+}
+
+void r4300i_COP1_S_ABS (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(RoundingModel);
+ *(float *)FPRFloatLocation[Opcode.fd] = (float)fabs(*(float *)FPRFloatLocation[Opcode.fs]);
+}
+
+void r4300i_COP1_S_MOV (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(RoundingModel);
+ *(float *)FPRFloatLocation[Opcode.fd] = *(float *)FPRFloatLocation[Opcode.fs];
+}
+
+void r4300i_COP1_S_NEG (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(RoundingModel);
+ *(float *)FPRFloatLocation[Opcode.fd] = (*(float *)FPRFloatLocation[Opcode.fs] * -1.0f);
+}
+
+void r4300i_COP1_S_TRUNC_L (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ //_controlfp(_RC_CHOP,_MCW_RC);
+ Float_RoundToInteger64(&*(int64_t *)FPRDoubleLocation[Opcode.fd],&*(float *)FPRFloatLocation[Opcode.fs]);
+}
+
+void r4300i_COP1_S_CEIL_L (void) { //added by Witten
+ TEST_COP1_USABLE_EXCEPTION
+ //_controlfp(_RC_UP,_MCW_RC);
+ Float_RoundToInteger64(&*(int64_t *)FPRDoubleLocation[Opcode.fd],&*(float *)FPRFloatLocation[Opcode.fs]);
+}
+
+void r4300i_COP1_S_FLOOR_L (void) { //added by Witten
+ TEST_COP1_USABLE_EXCEPTION
+ //_controlfp(_FPU_RC_DOWN,_MCW_RC);
+ Float_RoundToInteger64(&*(int64_t *)FPRDoubleLocation[Opcode.fd],&*(float *)FPRFloatLocation[Opcode.fs]);
+}
+
+void r4300i_COP1_S_ROUND_W (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ //_controlfp(_FPU_RC_NEAREST,_MCW_RC);
+ Float_RoundToInteger32(&*(int32_t *)FPRFloatLocation[Opcode.fd],&*(float *)FPRFloatLocation[Opcode.fs]);
+}
+
+void r4300i_COP1_S_TRUNC_W (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ //_controlfp(_RC_CHOP,_MCW_RC);
+ Float_RoundToInteger32(&*(int32_t *)FPRFloatLocation[Opcode.fd],&*(float *)FPRFloatLocation[Opcode.fs]);
+}
+
+void r4300i_COP1_S_CEIL_W (void) { //added by Witten
+ TEST_COP1_USABLE_EXCEPTION
+ //_controlfp(_RC_UP,_MCW_RC);
+ Float_RoundToInteger32(&*(int32_t *)FPRFloatLocation[Opcode.fd],&*(float *)FPRFloatLocation[Opcode.fs]);
+}
+
+void r4300i_COP1_S_FLOOR_W (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ //_controlfp(_FPU_RC_DOWN,_MCW_RC);
+ Float_RoundToInteger32(&*(int32_t *)FPRFloatLocation[Opcode.fd],&*(float *)FPRFloatLocation[Opcode.fs]);
+}
+
+void r4300i_COP1_S_CVT_D (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(RoundingModel);
+ *(double *)FPRDoubleLocation[Opcode.fd] = (double)(*(float *)FPRFloatLocation[Opcode.fs]);
+}
+
+void r4300i_COP1_S_CVT_W (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(RoundingModel);
+ Float_RoundToInteger32(&*(int32_t *)FPRFloatLocation[Opcode.fd],&*(float *)FPRFloatLocation[Opcode.fs]);
+}
+
+void r4300i_COP1_S_CVT_L (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(RoundingModel);
+ Float_RoundToInteger64(&*(int64_t *)FPRDoubleLocation[Opcode.fd],&*(float *)FPRFloatLocation[Opcode.fs]);
+}
+
+void r4300i_COP1_S_CMP (void) {
+ int32_t less, equal, unorded, condition;
+ float Temp0, Temp1;
+
+ TEST_COP1_USABLE_EXCEPTION
+
+ Temp0 = *(float *)FPRFloatLocation[Opcode.fs];
+ Temp1 = *(float *)FPRFloatLocation[Opcode.ft];
+
+ if(0) {
+ //if (_isnan(Temp0) || _isnan(Temp1)) {
+ less = 0;
+ equal = 0;
+ unorded = 1;
+ if ((Opcode.funct & 8) != 0) {
+ }
+ } else {
+ less = Temp0 < Temp1;
+ equal = Temp0 == Temp1;
+ unorded = 0;
+ }
+
+ condition = ((Opcode.funct & 4) && less) | ((Opcode.funct & 2) && equal) |
+ ((Opcode.funct & 1) && unorded);
+
+ if (condition) {
+ FPCR[31] |= FPCSR_C;
+ } else {
+ FPCR[31] &= ~FPCSR_C;
+ }
+
+}
+
+/************************** COP1: D functions ************************/
+__inline void Double_RoundToInteger32( int32_t * Dest, double * Source ) {
+ *Dest = (int32_t)*Source;
+}
+
+__inline void Double_RoundToInteger64( int64_t * Dest, double * Source ) {
+ *Dest = (int64_t)*Source;
+}
+
+void r4300i_COP1_D_ADD (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ *(double *)FPRDoubleLocation[Opcode.fd] = *(double *)FPRDoubleLocation[Opcode.fs] + *(double *)FPRDoubleLocation[Opcode.ft];
+}
+
+void r4300i_COP1_D_SUB (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ *(double *)FPRDoubleLocation[Opcode.fd] = *(double *)FPRDoubleLocation[Opcode.fs] - *(double *)FPRDoubleLocation[Opcode.ft];
+}
+
+void r4300i_COP1_D_MUL (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ *(double *)FPRDoubleLocation[Opcode.fd] = *(double *)FPRDoubleLocation[Opcode.fs] * *(double *)FPRDoubleLocation[Opcode.ft];
+}
+
+void r4300i_COP1_D_DIV (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ *(double *)FPRDoubleLocation[Opcode.fd] = *(double *)FPRDoubleLocation[Opcode.fs] / *(double *)FPRDoubleLocation[Opcode.ft];
+}
+
+void r4300i_COP1_D_SQRT (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ *(double *)FPRDoubleLocation[Opcode.fd] = (double)sqrt(*(double *)FPRDoubleLocation[Opcode.fs]);
+}
+
+void r4300i_COP1_D_ABS (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ *(double *)FPRDoubleLocation[Opcode.fd] = fabs(*(double *)FPRDoubleLocation[Opcode.fs]);
+}
+
+void r4300i_COP1_D_MOV (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ *(int64_t *)FPRDoubleLocation[Opcode.fd] = *(int64_t *)FPRDoubleLocation[Opcode.fs];
+}
+
+void r4300i_COP1_D_NEG (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ *(double *)FPRDoubleLocation[Opcode.fd] = (*(double *)FPRDoubleLocation[Opcode.fs] * -1.0);
+}
+
+void r4300i_COP1_D_TRUNC_L (void) { //added by Witten
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(_FPU_RC_ZERO);
+ Double_RoundToInteger64(&*(int64_t *)FPRFloatLocation[Opcode.fd],&*(double *)FPRDoubleLocation[Opcode.fs] );
+}
+
+void r4300i_COP1_D_CEIL_L (void) { //added by Witten
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(_FPU_RC_UP);
+ Double_RoundToInteger64(&*(int64_t *)FPRFloatLocation[Opcode.fd],&*(double *)FPRDoubleLocation[Opcode.fs] );
+}
+
+void r4300i_COP1_D_FLOOR_L (void) { //added by Witten
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(_FPU_RC_DOWN);
+ Double_RoundToInteger64(&*(int64_t *)FPRDoubleLocation[Opcode.fd],&*(double *)FPRFloatLocation[Opcode.fs]);
+}
+
+void r4300i_COP1_D_ROUND_W (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(_FPU_RC_NEAREST);
+ Double_RoundToInteger32(&*(int32_t *)FPRFloatLocation[Opcode.fd],&*(double *)FPRDoubleLocation[Opcode.fs] );
+}
+
+void r4300i_COP1_D_TRUNC_W (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(_FPU_RC_ZERO);
+ Double_RoundToInteger32(&*(int32_t *)FPRFloatLocation[Opcode.fd],&*(double *)FPRDoubleLocation[Opcode.fs] );
+}
+
+void r4300i_COP1_D_CEIL_W (void) { //added by Witten
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(_FPU_RC_UP);
+ Double_RoundToInteger32(&*(int32_t *)FPRFloatLocation[Opcode.fd],&*(double *)FPRDoubleLocation[Opcode.fs] );
+}
+
+void r4300i_COP1_D_FLOOR_W (void) { //added by Witten
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(_FPU_RC_DOWN);
+ Double_RoundToInteger32(&*(int32_t *)FPRDoubleLocation[Opcode.fd],&*(double *)FPRFloatLocation[Opcode.fs]);
+}
+
+void r4300i_COP1_D_CVT_S (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(RoundingModel);
+ *(float *)FPRFloatLocation[Opcode.fd] = (float)*(double *)FPRDoubleLocation[Opcode.fs];
+}
+
+void r4300i_COP1_D_CVT_W (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(RoundingModel);
+ Double_RoundToInteger32(&*(int32_t *)FPRFloatLocation[Opcode.fd],&*(double *)FPRDoubleLocation[Opcode.fs] );
+}
+
+void r4300i_COP1_D_CVT_L (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(RoundingModel);
+ Double_RoundToInteger64(&*(int64_t *)FPRDoubleLocation[Opcode.fd],&*(double *)FPRDoubleLocation[Opcode.fs]);
+}
+
+void r4300i_COP1_D_CMP (void) {
+ int32_t less, equal, unorded, condition;
+ MIPS_DWORD Temp0, Temp1;
+
+ TEST_COP1_USABLE_EXCEPTION
+
+ Temp0.DW = *(int64_t *)FPRDoubleLocation[Opcode.fs];
+ Temp1.DW = *(int64_t *)FPRDoubleLocation[Opcode.ft];
+
+ if(0) {
+ //if (_isnan(Temp0.D) || _isnan(Temp1.D)) {
+ less = 0;
+ equal = 0;
+ unorded = 1;
+ if ((Opcode.funct & 8) != 0) {
+ }
+ } else {
+ less = Temp0.D < Temp1.D;
+ equal = Temp0.D == Temp1.D;
+ unorded = 0;
+ }
+
+ condition = ((Opcode.funct & 4) && less) | ((Opcode.funct & 2) && equal) |
+ ((Opcode.funct & 1) && unorded);
+
+ if (condition) {
+ FPCR[31] |= FPCSR_C;
+ } else {
+ FPCR[31] &= ~FPCSR_C;
+ }
+}
+
+/************************** COP1: W functions ************************/
+void r4300i_COP1_W_CVT_S (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(RoundingModel);
+ *(float *)FPRFloatLocation[Opcode.fd] = (float)*(int32_t *)FPRFloatLocation[Opcode.fs];
+}
+
+void r4300i_COP1_W_CVT_D (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(RoundingModel);
+ *(double *)FPRDoubleLocation[Opcode.fd] = (double)*(int32_t *)FPRFloatLocation[Opcode.fs];
+}
+
+/************************** COP1: L functions ************************/
+void r4300i_COP1_L_CVT_S (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(RoundingModel);
+ *(float *)FPRFloatLocation[Opcode.fd] = (float)*(int64_t *)FPRDoubleLocation[Opcode.fs];
+}
+
+void r4300i_COP1_L_CVT_D (void) {
+ TEST_COP1_USABLE_EXCEPTION
+ controlfp(RoundingModel);
+ *(double *)FPRDoubleLocation[Opcode.fd] = (double)*(int64_t *)FPRDoubleLocation[Opcode.fs];
+}
+
+/************************** Other functions **************************/
+void R4300i_UnknownOpcode (void) {
+ DisplayError("Unkniown X86 Opcode.\tPC:%08x\tOp:%08x\n", PROGRAM_COUNTER,Opcode.Hex);
+ StopEmulation();
+}
diff --git a/src/usf/interpreter_ops.h b/src/usf/interpreter_ops.h new file mode 100644 index 0000000..01a6bbd --- /dev/null +++ b/src/usf/interpreter_ops.h @@ -0,0 +1,210 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+/************************* OpCode functions *************************/
+void r4300i_J ( void );
+void r4300i_JAL ( void );
+void r4300i_BNE ( void );
+void r4300i_BEQ ( void );
+void r4300i_BLEZ ( void );
+void r4300i_BGTZ ( void );
+void r4300i_ADDI ( void );
+void r4300i_ADDIU ( void );
+void r4300i_SLTI ( void );
+void r4300i_SLTIU ( void );
+void r4300i_ANDI ( void );
+void r4300i_ORI ( void );
+void r4300i_XORI ( void );
+void r4300i_LUI ( void );
+void r4300i_BEQL ( void );
+void r4300i_BNEL ( void );
+void r4300i_BLEZL ( void );
+void r4300i_BGTZL ( void );
+void r4300i_DADDIU ( void );
+void r4300i_LDL ( void );
+void r4300i_LDR ( void );
+void r4300i_LB ( void );
+void r4300i_LH ( void );
+void r4300i_LWL ( void );
+void r4300i_LW ( void );
+void r4300i_LBU ( void );
+void r4300i_LHU ( void );
+void r4300i_LWR ( void );
+void r4300i_LWU ( void );
+void r4300i_SB ( void );
+void r4300i_SH ( void );
+void r4300i_SWL ( void );
+void r4300i_SW ( void );
+void r4300i_SDL ( void );
+void r4300i_SDR ( void );
+void r4300i_SWR ( void );
+void r4300i_CACHE ( void );
+void r4300i_LL ( void );
+void r4300i_LWC1 ( void );
+void r4300i_LDC1 ( void );
+void r4300i_LD ( void );
+void r4300i_SC ( void );
+void r4300i_SWC1 ( void );
+void r4300i_SDC1 ( void );
+void r4300i_SD ( void );
+
+/********************** R4300i OpCodes: Special **********************/
+void r4300i_SPECIAL_SLL ( void );
+void r4300i_SPECIAL_SRL ( void );
+void r4300i_SPECIAL_SRA ( void );
+void r4300i_SPECIAL_SLLV ( void );
+void r4300i_SPECIAL_SRLV ( void );
+void r4300i_SPECIAL_SRAV ( void );
+void r4300i_SPECIAL_JR ( void );
+void r4300i_SPECIAL_JALR ( void );
+void r4300i_SPECIAL_SYSCALL ( void );
+void r4300i_SPECIAL_BREAK ( void );
+void r4300i_SPECIAL_SYNC ( void );
+void r4300i_SPECIAL_MFHI ( void );
+void r4300i_SPECIAL_MTHI ( void );
+void r4300i_SPECIAL_MFLO ( void );
+void r4300i_SPECIAL_MTLO ( void );
+void r4300i_SPECIAL_DSLLV ( void );
+void r4300i_SPECIAL_DSRLV ( void );
+void r4300i_SPECIAL_DSRAV ( void );
+void r4300i_SPECIAL_MULT ( void );
+void r4300i_SPECIAL_MULTU ( void );
+void r4300i_SPECIAL_DIV ( void );
+void r4300i_SPECIAL_DIVU ( void );
+void r4300i_SPECIAL_DMULT ( void );
+void r4300i_SPECIAL_DMULTU ( void );
+void r4300i_SPECIAL_DDIV ( void );
+void r4300i_SPECIAL_DDIVU ( void );
+void r4300i_SPECIAL_ADD ( void );
+void r4300i_SPECIAL_ADDU ( void );
+void r4300i_SPECIAL_SUB ( void );
+void r4300i_SPECIAL_SUBU ( void );
+void r4300i_SPECIAL_AND ( void );
+void r4300i_SPECIAL_OR ( void );
+void r4300i_SPECIAL_XOR ( void );
+void r4300i_SPECIAL_NOR ( void );
+void r4300i_SPECIAL_SLT ( void );
+void r4300i_SPECIAL_SLTU ( void );
+void r4300i_SPECIAL_DADD ( void );
+void r4300i_SPECIAL_DADDU ( void );
+void r4300i_SPECIAL_DSUB ( void );
+void r4300i_SPECIAL_DSUBU ( void );
+void r4300i_SPECIAL_TEQ ( void );
+void r4300i_SPECIAL_DSLL ( void );
+void r4300i_SPECIAL_DSRL ( void );
+void r4300i_SPECIAL_DSRA ( void );
+void r4300i_SPECIAL_DSLL32 ( void );
+void r4300i_SPECIAL_DSRL32 ( void );
+void r4300i_SPECIAL_DSRA32 ( void );
+
+/********************** R4300i OpCodes: RegImm **********************/
+void r4300i_REGIMM_BLTZ ( void );
+void r4300i_REGIMM_BGEZ ( void );
+void r4300i_REGIMM_BLTZL ( void );
+void r4300i_REGIMM_BGEZL ( void );
+void r4300i_REGIMM_BLTZAL ( void );
+void r4300i_REGIMM_BGEZAL ( void );
+
+/************************** COP0 functions **************************/
+void r4300i_COP0_MF ( void );
+void r4300i_COP0_MT ( void );
+
+/************************** COP0 CO functions ***********************/
+void r4300i_COP0_CO_TLBR ( void );
+void r4300i_COP0_CO_TLBWI ( void );
+void r4300i_COP0_CO_TLBWR ( void );
+void r4300i_COP0_CO_TLBP ( void );
+void r4300i_COP0_CO_ERET ( void );
+
+/************************** COP1 functions **************************/
+void r4300i_COP1_MF ( void );
+void r4300i_COP1_DMF ( void );
+void r4300i_COP1_CF ( void );
+void r4300i_COP1_MT ( void );
+void r4300i_COP1_DMT ( void );
+void r4300i_COP1_CT ( void );
+
+/************************* COP1: BC1 functions ***********************/
+void r4300i_COP1_BCF ( void );
+void r4300i_COP1_BCT ( void );
+void r4300i_COP1_BCFL ( void );
+void r4300i_COP1_BCTL ( void );
+
+/************************** COP1: S functions ************************/
+void r4300i_COP1_S_ADD ( void );
+void r4300i_COP1_S_SUB ( void );
+void r4300i_COP1_S_MUL ( void );
+void r4300i_COP1_S_DIV ( void );
+void r4300i_COP1_S_SQRT ( void );
+void r4300i_COP1_S_ABS ( void );
+void r4300i_COP1_S_MOV ( void );
+void r4300i_COP1_S_NEG ( void );
+void r4300i_COP1_S_TRUNC_L ( void );
+void r4300i_COP1_S_CEIL_L ( void ); //added by Witten
+void r4300i_COP1_S_FLOOR_L ( void ); //added by Witten
+void r4300i_COP1_S_ROUND_W ( void );
+void r4300i_COP1_S_TRUNC_W ( void );
+void r4300i_COP1_S_CEIL_W ( void ); //added by Witten
+void r4300i_COP1_S_FLOOR_W ( void );
+void r4300i_COP1_S_CVT_D ( void );
+void r4300i_COP1_S_CVT_W ( void );
+void r4300i_COP1_S_CVT_L ( void );
+void r4300i_COP1_S_CMP ( void );
+
+/************************** COP1: D functions ************************/
+void r4300i_COP1_D_ADD ( void );
+void r4300i_COP1_D_SUB ( void );
+void r4300i_COP1_D_MUL ( void );
+void r4300i_COP1_D_DIV ( void );
+void r4300i_COP1_D_SQRT ( void );
+void r4300i_COP1_D_ABS ( void );
+void r4300i_COP1_D_MOV ( void );
+void r4300i_COP1_D_NEG ( void );
+void r4300i_COP1_D_TRUNC_L ( void ); //added by Witten
+void r4300i_COP1_D_CEIL_L ( void ); //added by Witten
+void r4300i_COP1_D_FLOOR_L ( void ); //added by Witten
+void r4300i_COP1_D_ROUND_W ( void );
+void r4300i_COP1_D_TRUNC_W ( void );
+void r4300i_COP1_D_CEIL_W ( void ); //added by Witten
+void r4300i_COP1_D_FLOOR_W ( void ); //added by Witten
+void r4300i_COP1_D_CVT_S ( void );
+void r4300i_COP1_D_CVT_W ( void );
+void r4300i_COP1_D_CVT_L ( void );
+void r4300i_COP1_D_CMP ( void );
+
+/************************** COP1: W functions ************************/
+void r4300i_COP1_W_CVT_S ( void );
+void r4300i_COP1_W_CVT_D ( void );
+
+/************************** COP1: L functions ************************/
+void r4300i_COP1_L_CVT_S ( void );
+void r4300i_COP1_L_CVT_D ( void );
+
+/************************** Other functions **************************/
+void R4300i_UnknownOpcode ( void );
+
+extern uint32_t SWL_MASK[4], SWR_MASK[4], LWL_MASK[4], LWR_MASK[4];
+extern int32_t SWL_SHIFT[4], SWR_SHIFT[4], LWL_SHIFT[4], LWR_SHIFT[4];
+extern int32_t RoundingModel;
diff --git a/src/usf/main.c b/src/usf/main.c new file mode 100644 index 0000000..e065a45 --- /dev/null +++ b/src/usf/main.c @@ -0,0 +1,41 @@ +
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "usf.h"
+#include "cpu.h"
+#include "memory.h"
+
+
+int InitalizeApplication ( void )
+{
+
+ return 1;
+}
+
+void StopEmulation(void)
+{
+ //asm("int $3");
+ //printf("Arrivederci!\n\n");
+ //Release_Memory();
+ //exit(0);
+ cpu_running = 0;
+}
+
+void DisplayError (char * Message, ...) {
+ char Msg[1000];
+ va_list ap;
+
+ va_start( ap, Message );
+ vsprintf( Msg, Message, ap );
+ va_end( ap );
+
+ printf("Error: %s\n", Msg);
+}
+
+void UsfSleep(int32_t time)
+{
+ usleep(time * 1000);
+}
diff --git a/src/usf/main.h b/src/usf/main.h new file mode 100644 index 0000000..f2e75b7 --- /dev/null +++ b/src/usf/main.h @@ -0,0 +1,10 @@ +#include <stdint.h>
+
+#define CPU_Default -1
+#define CPU_Interpreter 0
+#define CPU_Recompiler 1
+
+int InitalizeApplication ( void );
+void DisplayError (char * Message, ...);
+void StopEmulation(void);
+void UsfSleep(int32_t);
diff --git a/src/usf/memory.c b/src/usf/memory.c new file mode 100644 index 0000000..0570bbb --- /dev/null +++ b/src/usf/memory.c @@ -0,0 +1,1890 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <malloc.h>
+#include <memory.h>
+#include <sys/mman.h>
+
+#include <signal.h>
+
+
+#include "main.h"
+#include "cpu.h"
+#include "x86.h"
+#include "audio.h"
+#include "rsp.h"
+#include "usf.h"
+
+uintptr_t *TLB_Map = 0;
+uint8_t * MemChunk = 0;
+uint32_t RdramSize = 0x800000, SystemRdramSize = 0x800000, RomFileSize = 0x4000000;
+uint8_t * N64MEM = 0, * RDRAM = 0, * DMEM = 0, * IMEM = 0, * ROMPages[0x400], * savestatespace = 0, * NOMEM = 0;
+void ** JumpTable = 0, ** DelaySlotTable = 0;
+uint8_t * RecompCode = 0, * RecompPos = 0;
+
+uint32_t WrittenToRom = 0;
+uint32_t WroteToRom = 0;
+uint32_t TempValue = 0;
+uint32_t MemoryState = 0;
+
+uint8_t EmptySpace = 0;
+
+uint8_t * PageROM(uint32_t addr) {
+ return (ROMPages[addr/0x10000])?ROMPages[addr/0x10000]+(addr%0x10000):&EmptySpace;
+}
+
+/* MAP_32BIT is needed to make this work on amd64. --nenolod. */
+#ifndef MAP_32BIT
+# define MAP_32BIT (0)
+#endif
+
+#define PAGE_SIZE 4096
+void *malloc_exec(uint32_t bytes)
+{
+ void *ptr = NULL;
+
+ ptr = mmap(0,bytes,PROT_EXEC|PROT_READ|PROT_WRITE,MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, 0, 0);
+
+ return ptr;
+
+}
+
+
+int32_t Allocate_Memory ( void ) {
+ //RdramSize = 0x800000;
+
+ // Allocate the N64MEM and TLB_Map so that they are in each others 4GB range
+ // Also put the registers there :)
+
+
+ // the mmap technique works craptacular when the regions don't overlay
+
+ MemChunk = mmap(NULL, 0x100000 * sizeof(uintptr_t) + 0x1D000 + RdramSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+
+ TLB_Map = (uintptr_t*)MemChunk;
+ if (TLB_Map == NULL) {
+ return 0;
+ }
+
+ memset(TLB_Map, 0, 0x100000 * sizeof(uintptr_t) + 0x10000);
+
+ N64MEM = mmap((uintptr_t)MemChunk + 0x100000 * sizeof(uintptr_t) + 0x10000, 0xD000 + RdramSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0);
+ if(N64MEM == NULL) {
+ DisplayError("Failed to allocate N64MEM");
+ return 0;
+ }
+
+ memset(N64MEM, 0, RdramSize);
+
+ NOMEM = mmap((uintptr_t)N64MEM + RdramSize, 0xD000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0);
+
+ if(RdramSize == 0x400000)
+ {
+ // munmap(N64MEM + 0x400000, 0x400000);
+ }
+
+ Registers = (N64_REGISTERS *)((uintptr_t)MemChunk + 0x100000 * sizeof(uintptr_t));
+ TLBLoadAddress = (uint32_t *)((uintptr_t)Registers + 0x500);
+ Timers = (SYSTEM_TIMERS*)(TLBLoadAddress + 4);
+ WaitMode = (uint32_t *)(Timers + sizeof(SYSTEM_TIMERS));
+ CPU_Action = (CPU_ACTION *)(WaitMode + 4);
+ RSP_GPR = (REGISTER32 *)(CPU_Action + sizeof(CPU_ACTION));
+ DMEM = (uint8_t *)(RSP_GPR + (32 * 8));
+ RSP_ACCUM = (REGISTER *)(DMEM + 0x2000);
+ RSP_Vect = (VECTOR *)((char*)RSP_ACCUM + (sizeof(REGISTER)*32));
+
+
+ if(!use_interpreter) {
+ JumpTable = (void **)malloc(0x200000 * sizeof(uintptr_t));
+
+ if( JumpTable == NULL )
+ return 0;
+
+ memset(JumpTable, 0, 0x200000 * sizeof(uintptr_t));
+
+ RecompCode = malloc_exec(NormalCompileBufferSize);
+
+ memset(RecompCode, 0xcc, NormalCompileBufferSize); // fill with Breakpoints
+
+ DelaySlotTable = (void **) malloc((0x1000000) >> 0xA);
+ if( DelaySlotTable == NULL )
+ return 0;
+
+ memset(DelaySlotTable, 0, ((0x1000000) >> 0xA));
+
+ } else {
+ JumpTable = NULL;
+ RecompCode = NULL;
+ DelaySlotTable = NULL;
+ }
+ RDRAM = (uint8_t *)(N64MEM);
+ IMEM = DMEM + 0x1000;
+
+ MemoryState = 1;
+
+ return 1;
+}
+
+int PreAllocate_Memory(void) {
+ int i = 0;
+
+ // Moved the savestate allocation here :) (for better management later)
+ savestatespace = malloc(0x80275C);
+
+ if(savestatespace == 0)
+ return 0;
+
+ memset(savestatespace, 0, 0x80275C);
+
+ for (i = 0; i < 0x400; i++) {
+ ROMPages[i] = 0;
+ }
+
+ return 1;
+}
+
+void Release_Memory ( void ) {
+ uint32_t i;
+
+ for (i = 0; i < 0x400; i++) {
+ if (ROMPages[i]) {
+ free(ROMPages[i]); ROMPages[i] = 0;
+ }
+ }
+ printf("Freeing memory\n");
+
+ MemoryState = 0;
+
+ if (MemChunk != 0) {munmap(MemChunk, 0x100000 * sizeof(uintptr_t)) + 0x1D000 + RdramSize; MemChunk=0;}
+ if (N64MEM != 0) {munmap(N64MEM, RdramSize); N64MEM=0;}
+ if (NOMEM != 0) {munmap(NOMEM, 0xD000); NOMEM=0;}
+
+ if (DelaySlotTable != NULL) {free( DelaySlotTable); DelaySlotTable=NULL;}
+ if (JumpTable != NULL) {free( JumpTable); JumpTable=NULL;}
+ if (RecompCode != NULL){munmap( RecompCode, NormalCompileBufferSize); RecompCode=NULL;}
+ if (RSPRecompCode != NULL){munmap( RSPRecompCode, RSP_RECOMPMEM_SIZE + RSP_SECRECOMPMEM_SIZE); RSPRecompCode=NULL;}
+
+ if (RSPJumpTables != NULL) {free( RSPJumpTables); RSPJumpTables=NULL;}
+ if (JumpTable != NULL) {free( JumpTable); JumpTable=NULL;}
+
+
+ if(savestatespace)
+ free(savestatespace);
+ savestatespace = NULL;
+
+}
+
+
+
+void Compile_LB ( int32_t Reg, uint32_t addr, uint32_t SignExtend ) {
+ uintptr_t Addr = addr;
+ if (!TranslateVaddr(&Addr)) {
+ MoveConstToX86reg(0,Reg);
+ return;
+ }
+
+ switch (Addr & 0xFFF00000) {
+ case 0x00000000:
+ case 0x00100000:
+ case 0x00200000:
+ case 0x00300000:
+ case 0x00400000:
+ case 0x00500000:
+ case 0x00600000:
+ case 0x00700000:
+ case 0x10000000:
+
+ if (SignExtend) {
+ MoveSxVariableToX86regByte(Addr + N64MEM,Reg);
+ } else {
+ MoveZxVariableToX86regByte(Addr + N64MEM,Reg);
+ }
+ break;
+ default:
+ MoveConstToX86reg(0,Reg);
+ }
+}
+
+void Compile_LH ( int32_t Reg, uint32_t addr, uint32_t SignExtend) {
+ uintptr_t Addr = addr;
+ if (!TranslateVaddr(&Addr)) {
+ MoveConstToX86reg(0,Reg);
+ return;
+ }
+
+ switch (Addr & 0xFFF00000) {
+ case 0x00000000:
+ case 0x00100000:
+ case 0x00200000:
+ case 0x00300000:
+ case 0x00400000:
+ case 0x00500000:
+ case 0x00600000:
+ case 0x00700000:
+ case 0x10000000:
+
+ if (SignExtend) {
+ MoveSxVariableToX86regHalf(Addr + N64MEM,Reg);
+ } else {
+ MoveZxVariableToX86regHalf(Addr + N64MEM,Reg);
+ }
+ break;
+ default:
+ MoveConstToX86reg(0,Reg);
+ }
+}
+
+void Compile_LW ( int32_t Reg, uint32_t addr ) {
+ uintptr_t Addr = addr;
+ if (!TranslateVaddr(&Addr)) {
+ MoveConstToX86reg(0,Reg);
+ }
+
+ switch (Addr & 0xFFF00000) {
+ case 0x00000000:
+ case 0x00100000:
+ case 0x00200000:
+ case 0x00300000:
+ case 0x00400000:
+ case 0x00500000:
+ case 0x00600000:
+ case 0x00700000:
+ case 0x10000000:
+ MoveVariableToX86reg(Addr + N64MEM,Reg);
+ break;
+ case 0x04000000:
+ if (Addr < 0x04002000) {
+ MoveVariableToX86reg(Addr + N64MEM,Reg);
+ break;
+ }
+ switch (Addr) {
+ case 0x04040010: MoveVariableToX86reg(&SP_STATUS_REG,Reg); break;
+ case 0x04040014: MoveVariableToX86reg(&SP_DMA_FULL_REG,Reg); break;
+ case 0x04040018: MoveVariableToX86reg(&SP_DMA_BUSY_REG,Reg); break;
+ case 0x04080000: MoveVariableToX86reg(&SP_PC_REG,Reg); break;
+ default: MoveConstToX86reg(0,Reg); break;
+ }
+ break;
+ case 0x04100000: MoveVariableToX86reg(Addr + N64MEM,Reg); break;
+ case 0x04300000:
+ switch (Addr) {
+ case 0x04300000: MoveVariableToX86reg(&MI_MODE_REG,Reg); break;
+ case 0x04300004: MoveVariableToX86reg(&MI_VERSION_REG,Reg); break;
+ case 0x04300008: MoveVariableToX86reg(&MI_INTR_REG,Reg); break;
+ case 0x0430000C: MoveVariableToX86reg(&MI_INTR_MASK_REG,Reg); break;
+ default: MoveConstToX86reg(0,Reg); break;
+ }
+ break;
+ case 0x04400000:
+ switch (Addr) {
+ case 0x04400010:
+ Pushad();
+ Call_Direct(&UpdateCurrentHalfLine);
+ Popad();
+ MoveVariableToX86reg(&HalfLine,Reg);
+ break;
+ default: MoveConstToX86reg(0,Reg); break;
+ }
+ break;
+ case 0x04500000: /* AI registers */
+ switch (Addr) {
+ case 0x04500004:
+ Pushad();
+ Call_Direct(AiReadLength);
+ MoveX86regToVariable(x86_EAX,&TempValue);
+ Popad();
+ MoveVariableToX86reg(&TempValue,Reg);
+ break;
+ case 0x0450000C: MoveVariableToX86reg(&AI_STATUS_REG,Reg); break;
+ case 0x04500010: MoveVariableToX86reg(&AI_DACRATE_REG,Reg); break;
+ default: MoveConstToX86reg(0,Reg); break;
+ }
+ break;
+ case 0x04600000:
+ switch (Addr) {
+ case 0x04600010: MoveVariableToX86reg(&PI_STATUS_REG,Reg); break;
+ case 0x04600014: MoveVariableToX86reg(&PI_DOMAIN1_REG,Reg); break;
+ case 0x04600018: MoveVariableToX86reg(&PI_BSD_DOM1_PWD_REG,Reg); break;
+ case 0x0460001C: MoveVariableToX86reg(&PI_BSD_DOM1_PGS_REG,Reg); break;
+ case 0x04600020: MoveVariableToX86reg(&PI_BSD_DOM1_RLS_REG,Reg); break;
+ case 0x04600024: MoveVariableToX86reg(&PI_DOMAIN2_REG,Reg); break;
+ case 0x04600028: MoveVariableToX86reg(&PI_BSD_DOM2_PWD_REG,Reg); break;
+ case 0x0460002C: MoveVariableToX86reg(&PI_BSD_DOM2_PGS_REG,Reg); break;
+ case 0x04600030: MoveVariableToX86reg(&PI_BSD_DOM2_RLS_REG,Reg); break;
+ default: MoveConstToX86reg(0,Reg); break;
+ }
+ break;
+ case 0x04700000:
+ switch (Addr) {
+ case 0x0470000C: MoveVariableToX86reg(&RI_SELECT_REG,Reg); break;
+ case 0x04700010: MoveVariableToX86reg(&RI_REFRESH_REG,Reg); break;
+ default: MoveConstToX86reg(0,Reg); break;
+ }
+ break;
+ case 0x04800000:
+ switch (Addr) {
+ case 0x04800018: MoveVariableToX86reg(&SI_STATUS_REG,Reg); break;
+ default: MoveConstToX86reg(0,Reg); break;
+ }
+ break;
+ case 0x1FC00000: MoveVariableToX86reg(Addr + N64MEM,Reg); break;
+ default: MoveConstToX86reg(((Addr & 0xFFFF) << 16) | (Addr & 0xFFFF),Reg);
+ }
+}
+
+void Compile_SB_Const ( uint8_t Value, uint32_t addr ) {
+ uintptr_t Addr = addr;
+ if (!TranslateVaddr(&Addr)) {
+ return;
+ }
+
+ switch (Addr & 0xFFF00000) {
+ case 0x00000000:
+ case 0x00100000:
+ case 0x00200000:
+ case 0x00300000:
+ case 0x00400000:
+ case 0x00500000:
+ case 0x00600000:
+ case 0x00700000:
+ MoveConstByteToVariable(Value,Addr + N64MEM);
+ break;
+ }
+}
+
+void Compile_SB_Register ( int32_t x86Reg, uint32_t addr ) {
+ uintptr_t Addr = addr;
+ if (!TranslateVaddr(&Addr)) {
+ return;
+ }
+
+ switch (Addr & 0xFFF00000) {
+ case 0x00000000:
+ case 0x00100000:
+ case 0x00200000:
+ case 0x00300000:
+ case 0x00400000:
+ case 0x00500000:
+ case 0x00600000:
+ case 0x00700000:
+ MoveX86regByteToVariable(x86Reg,Addr + N64MEM);
+ break;
+ }
+}
+
+void Compile_SH_Const ( uint16_t Value, uint32_t addr ) {
+ uintptr_t Addr = addr;
+ if (!TranslateVaddr(&Addr)) {
+ return;
+ }
+
+ switch (Addr & 0xFFF00000) {
+ case 0x00000000:
+ case 0x00100000:
+ case 0x00200000:
+ case 0x00300000:
+ case 0x00400000:
+ case 0x00500000:
+ case 0x00600000:
+ case 0x00700000:
+ MoveConstHalfToVariable(Value,Addr + N64MEM);
+ break;
+ }
+}
+
+void Compile_SH_Register ( int32_t x86Reg, uint32_t addr ) {
+ uintptr_t Addr = addr;
+ if (!TranslateVaddr(&Addr)) {
+ return;
+ }
+
+ switch (Addr & 0xFFF00000) {
+ case 0x00000000:
+ case 0x00100000:
+ case 0x00200000:
+ case 0x00300000:
+ case 0x00400000:
+ case 0x00500000:
+ case 0x00600000:
+ case 0x00700000:
+ MoveX86regHalfToVariable(x86Reg,Addr + N64MEM);
+ break;
+ }
+}
+
+void Compile_SW_Const ( uint32_t Value, uint32_t addr ) {
+ uintptr_t Addr = addr;
+ if (!TranslateVaddr(&Addr)) {
+ return;
+ }
+
+ switch (Addr & 0xFFF00000) {
+ case 0x00000000:
+ case 0x00100000:
+ case 0x00200000:
+ case 0x00300000:
+ case 0x00400000:
+ case 0x00500000:
+ case 0x00600000:
+ case 0x00700000:
+ MoveConstToVariable(Value,Addr + N64MEM);
+ break;
+ case 0x03F00000:
+ switch (Addr) {
+ case 0x03F00000: MoveConstToVariable(Value,&RDRAM_CONFIG_REG); break;
+ case 0x03F00004: MoveConstToVariable(Value,&RDRAM_DEVICE_ID_REG); break;
+ case 0x03F00008: MoveConstToVariable(Value,&RDRAM_DELAY_REG); break;
+ case 0x03F0000C: MoveConstToVariable(Value,&RDRAM_MODE_REG); break;
+ case 0x03F00010: MoveConstToVariable(Value,&RDRAM_REF_INTERVAL_REG); break;
+ case 0x03F00014: MoveConstToVariable(Value,&RDRAM_REF_ROW_REG); break;
+ case 0x03F00018: MoveConstToVariable(Value,&RDRAM_RAS_INTERVAL_REG); break;
+ case 0x03F0001C: MoveConstToVariable(Value,&RDRAM_MIN_INTERVAL_REG); break;
+ case 0x03F00020: MoveConstToVariable(Value,&RDRAM_ADDR_SELECT_REG); break;
+ case 0x03F00024: MoveConstToVariable(Value,&RDRAM_DEVICE_MANUF_REG); break;
+ case 0x03F04004: break;
+ case 0x03F08004: break;
+ case 0x03F80004: break;
+ case 0x03F80008: break;
+ case 0x03F8000C: break;
+ case 0x03F80014: break;
+ }
+ break;
+ case 0x04000000:
+ if (Addr < 0x04002000) {
+ MoveConstToVariable(Value,Addr + N64MEM);
+ break;
+ }
+ switch (Addr) {
+ case 0x04040000: MoveConstToVariable(Value,&SP_MEM_ADDR_REG); break;
+ case 0x04040004: MoveConstToVariable(Value,&SP_DRAM_ADDR_REG); break;
+ case 0x04040008:
+ MoveConstToVariable(Value,&SP_RD_LEN_REG);
+ Pushad();
+ Call_Direct(&SP_DMA_READ);
+ Popad();
+ break;
+ case 0x04040010:
+ {
+ uint32_t ModValue = 0;
+ if ( ( Value & SP_CLR_HALT ) != 0 ) { ModValue |= SP_STATUS_HALT; }
+ if ( ( Value & SP_CLR_BROKE ) != 0 ) { ModValue |= SP_STATUS_BROKE; }
+ if ( ( Value & SP_CLR_SSTEP ) != 0 ) { ModValue |= SP_STATUS_SSTEP; }
+ if ( ( Value & SP_CLR_INTR_BREAK ) != 0 ) { ModValue |= SP_STATUS_INTR_BREAK; }
+ if ( ( Value & SP_CLR_SIG0 ) != 0 ) { ModValue |= SP_STATUS_SIG0; }
+ if ( ( Value & SP_CLR_SIG1 ) != 0 ) { ModValue |= SP_STATUS_SIG1; }
+ if ( ( Value & SP_CLR_SIG2 ) != 0 ) { ModValue |= SP_STATUS_SIG2; }
+ if ( ( Value & SP_CLR_SIG3 ) != 0 ) { ModValue |= SP_STATUS_SIG3; }
+ if ( ( Value & SP_CLR_SIG4 ) != 0 ) { ModValue |= SP_STATUS_SIG4; }
+ if ( ( Value & SP_CLR_SIG5 ) != 0 ) { ModValue |= SP_STATUS_SIG5; }
+ if ( ( Value & SP_CLR_SIG6 ) != 0 ) { ModValue |= SP_STATUS_SIG6; }
+ if ( ( Value & SP_CLR_SIG7 ) != 0 ) { ModValue |= SP_STATUS_SIG7; }
+
+ if (ModValue != 0) {
+ AndConstToVariable(~ModValue,&SP_STATUS_REG);
+ }
+
+ ModValue = 0;
+ if ( ( Value & SP_SET_HALT ) != 0 ) { ModValue |= SP_STATUS_HALT; }
+ if ( ( Value & SP_SET_SSTEP ) != 0 ) { ModValue |= SP_STATUS_SSTEP; }
+ if ( ( Value & SP_SET_INTR_BREAK ) != 0) { ModValue |= SP_STATUS_INTR_BREAK; }
+ if ( ( Value & SP_SET_SIG0 ) != 0 ) { ModValue |= SP_STATUS_SIG0; }
+ if ( ( Value & SP_SET_SIG1 ) != 0 ) { ModValue |= SP_STATUS_SIG1; }
+ if ( ( Value & SP_SET_SIG2 ) != 0 ) { ModValue |= SP_STATUS_SIG2; }
+ if ( ( Value & SP_SET_SIG3 ) != 0 ) { ModValue |= SP_STATUS_SIG3; }
+ if ( ( Value & SP_SET_SIG4 ) != 0 ) { ModValue |= SP_STATUS_SIG4; }
+ if ( ( Value & SP_SET_SIG5 ) != 0 ) { ModValue |= SP_STATUS_SIG5; }
+ if ( ( Value & SP_SET_SIG6 ) != 0 ) { ModValue |= SP_STATUS_SIG6; }
+ if ( ( Value & SP_SET_SIG7 ) != 0 ) { ModValue |= SP_STATUS_SIG7; }
+ if (ModValue != 0) {
+ OrConstToVariable(ModValue,&SP_STATUS_REG);
+ }
+
+ if ( ( Value & SP_CLR_INTR ) != 0) {
+ AndConstToVariable(~MI_INTR_SP,&MI_INTR_REG);
+ Pushad();
+ Call_Direct(RunRsp);
+ Call_Direct(CheckInterrupts);
+ Popad();
+ } else {
+ Pushad();
+ Call_Direct(RunRsp);
+ Popad();
+ }
+ }
+ break;
+ case 0x0404001C: MoveConstToVariable(0,&SP_SEMAPHORE_REG); break;
+ case 0x04080000: MoveConstToVariable(Value & 0xFFC,&SP_PC_REG); break;
+ }
+ break;
+ case 0x04300000:
+ switch (Addr) {
+ case 0x04300000:
+ {
+ uint32_t ModValue = 0x7F;
+ if ( ( Value & MI_CLR_INIT ) != 0 ) { ModValue |= MI_MODE_INIT; }
+ if ( ( Value & MI_CLR_EBUS ) != 0 ) { ModValue |= MI_MODE_EBUS; }
+ if ( ( Value & MI_CLR_RDRAM ) != 0 ) { ModValue |= MI_MODE_RDRAM; }
+ if (ModValue != 0) {
+ AndConstToVariable(~ModValue,&MI_MODE_REG);
+ }
+
+ ModValue = (Value & 0x7F);
+ if ( ( Value & MI_SET_INIT ) != 0 ) { ModValue |= MI_MODE_INIT; }
+ if ( ( Value & MI_SET_EBUS ) != 0 ) { ModValue |= MI_MODE_EBUS; }
+ if ( ( Value & MI_SET_RDRAM ) != 0 ) { ModValue |= MI_MODE_RDRAM; }
+ if (ModValue != 0) {
+ OrConstToVariable(ModValue,&MI_MODE_REG);
+ }
+ if ( ( Value & MI_CLR_DP_INTR ) != 0 ) {
+ AndConstToVariable(~MI_INTR_DP,&MI_INTR_REG);
+ }
+ }
+ break;
+ case 0x0430000C:
+ {
+ uint32_t ModValue;
+ ModValue = 0;
+ if ( ( Value & MI_INTR_MASK_CLR_SP ) != 0 ) { ModValue |= MI_INTR_MASK_SP; }
+ if ( ( Value & MI_INTR_MASK_CLR_SI ) != 0 ) { ModValue |= MI_INTR_MASK_SI; }
+ if ( ( Value & MI_INTR_MASK_CLR_AI ) != 0 ) { ModValue |= MI_INTR_MASK_AI; }
+ if ( ( Value & MI_INTR_MASK_CLR_VI ) != 0 ) { ModValue |= MI_INTR_MASK_VI; }
+ if ( ( Value & MI_INTR_MASK_CLR_PI ) != 0 ) { ModValue |= MI_INTR_MASK_PI; }
+ if ( ( Value & MI_INTR_MASK_CLR_DP ) != 0 ) { ModValue |= MI_INTR_MASK_DP; }
+ if (ModValue != 0) {
+ AndConstToVariable(~ModValue,&MI_INTR_MASK_REG);
+ }
+
+ ModValue = 0;
+ if ( ( Value & MI_INTR_MASK_SET_SP ) != 0 ) { ModValue |= MI_INTR_MASK_SP; }
+ if ( ( Value & MI_INTR_MASK_SET_SI ) != 0 ) { ModValue |= MI_INTR_MASK_SI; }
+ if ( ( Value & MI_INTR_MASK_SET_AI ) != 0 ) { ModValue |= MI_INTR_MASK_AI; }
+ if ( ( Value & MI_INTR_MASK_SET_VI ) != 0 ) { ModValue |= MI_INTR_MASK_VI; }
+ if ( ( Value & MI_INTR_MASK_SET_PI ) != 0 ) { ModValue |= MI_INTR_MASK_PI; }
+ if ( ( Value & MI_INTR_MASK_SET_DP ) != 0 ) { ModValue |= MI_INTR_MASK_DP; }
+ if (ModValue != 0) {
+ OrConstToVariable(ModValue,&MI_INTR_MASK_REG);
+ }
+ }
+ break;
+ }
+ break;
+ case 0x04400000:
+ switch (Addr) {
+ case 0x04400000:
+ MoveConstToVariable(Value,&VI_STATUS_REG);
+ break;
+ case 0x04400004: MoveConstToVariable((Value & 0xFFFFFF),&VI_ORIGIN_REG); break;
+ case 0x04400008:
+ MoveConstToVariable(Value,&VI_WIDTH_REG);
+ break;
+ case 0x0440000C: MoveConstToVariable(Value,&VI_INTR_REG); break;
+ case 0x04400010:
+ AndConstToVariable(~MI_INTR_VI,&MI_INTR_REG);
+ Pushad();
+ Call_Direct(CheckInterrupts);
+ Popad();
+ break;
+ case 0x04400014: MoveConstToVariable(Value,&VI_BURST_REG); break;
+ case 0x04400018: MoveConstToVariable(Value,&VI_V_SYNC_REG); break;
+ case 0x0440001C: MoveConstToVariable(Value,&VI_H_SYNC_REG); break;
+ case 0x04400020: MoveConstToVariable(Value,&VI_LEAP_REG); break;
+ case 0x04400024: MoveConstToVariable(Value,&VI_H_START_REG); break;
+ case 0x04400028: MoveConstToVariable(Value,&VI_V_START_REG); break;
+ case 0x0440002C: MoveConstToVariable(Value,&VI_V_BURST_REG); break;
+ case 0x04400030: MoveConstToVariable(Value,&VI_X_SCALE_REG); break;
+ case 0x04400034: MoveConstToVariable(Value,&VI_Y_SCALE_REG); break;
+ }
+ break;
+ case 0x04500000: /* AI registers */
+ switch (Addr) {
+ case 0x04500000: MoveConstToVariable(Value,&AI_DRAM_ADDR_REG); break;
+ case 0x04500004:
+ MoveConstToVariable(Value,&AI_LEN_REG);
+ Pushad();
+ //Pushad();
+ //PushImm32(Value);
+ Call_Direct(AiLenChanged);
+ //AddConstToX86Reg(x86_ESP,8);
+
+ Popad();
+ break;
+ case 0x04500008: MoveConstToVariable((Value & 1),&AI_CONTROL_REG); break;
+ case 0x0450000C:
+ /* Clear Interrupt */;
+ AndConstToVariable(~MI_INTR_AI,&MI_INTR_REG);
+ AndConstToVariable(~MI_INTR_AI,&AudioIntrReg);
+ Pushad();
+ Call_Direct(CheckInterrupts);
+ Popad();
+ break;
+ case 0x04500010:
+ Addr|=0xa0000000;
+ MoveConstToVariable(Value,Addr + N64MEM);
+ break;
+ case 0x04500014: MoveConstToVariable(Value,&AI_BITRATE_REG); break;
+ }
+ break;
+ case 0x04600000:
+ switch (Addr) {
+ case 0x04600000: MoveConstToVariable(Value,&PI_DRAM_ADDR_REG); break;
+ case 0x04600004: MoveConstToVariable(Value,&PI_CART_ADDR_REG); break;
+ case 0x04600008:
+ MoveConstToVariable(Value,&PI_RD_LEN_REG);
+ Pushad();
+ Call_Direct(&PI_DMA_READ);
+ Popad();
+ break;
+ case 0x0460000C:
+ MoveConstToVariable(Value,&PI_WR_LEN_REG);
+ Pushad();
+ Call_Direct(&PI_DMA_WRITE);
+ Popad();
+ break;
+ case 0x04600010:
+ if ((Value & PI_CLR_INTR) != 0 ) {
+ AndConstToVariable(~MI_INTR_PI,&MI_INTR_REG);
+ Pushad();
+ Call_Direct(CheckInterrupts);
+ Popad();
+ }
+ break;
+ case 0x04600014: MoveConstToVariable((Value & 0xFF),&PI_DOMAIN1_REG); break;
+ case 0x04600018: MoveConstToVariable((Value & 0xFF),&PI_BSD_DOM1_PWD_REG); break;
+ case 0x0460001C: MoveConstToVariable((Value & 0xFF),&PI_BSD_DOM1_PGS_REG); break;
+ case 0x04600020: MoveConstToVariable((Value & 0xFF),&PI_BSD_DOM1_RLS_REG); break;
+ }
+ break;
+ case 0x04700000:
+ switch (Addr) {
+ case 0x04700000: MoveConstToVariable(Value,&RI_MODE_REG); break;
+ case 0x04700004: MoveConstToVariable(Value,&RI_CONFIG_REG); break;
+ case 0x04700008: MoveConstToVariable(Value,&RI_CURRENT_LOAD_REG); break;
+ case 0x0470000C: MoveConstToVariable(Value,&RI_SELECT_REG); break;
+ }
+ break;
+ case 0x04800000:
+ switch (Addr) {
+ case 0x04800000: MoveConstToVariable(Value,&SI_DRAM_ADDR_REG); break;
+ case 0x04800004:
+ MoveConstToVariable(Value,&SI_PIF_ADDR_RD64B_REG);
+ Pushad();
+ Call_Direct(&SI_DMA_READ);
+ Popad();
+ break;
+ case 0x04800010:
+ MoveConstToVariable(Value,&SI_PIF_ADDR_WR64B_REG);
+ Pushad();
+ Call_Direct(&SI_DMA_WRITE);
+ Popad();
+ break;
+ case 0x04800018:
+ AndConstToVariable(~MI_INTR_SI,&MI_INTR_REG);
+ AndConstToVariable(~SI_STATUS_INTERRUPT,&SI_STATUS_REG);
+ Pushad();
+ Call_Direct(CheckInterrupts);
+ Popad();
+ break;
+ }
+ break;
+ }
+}
+
+void Compile_SW_Register ( int32_t x86Reg, uint32_t addr ) {
+ uintptr_t Addr = addr;
+
+
+ if (!TranslateVaddr(&Addr)) {
+ return;
+ }
+
+ switch (Addr & 0xFFF00000) {
+ case 0x00000000:
+ case 0x00100000:
+ case 0x00200000:
+ case 0x00300000:
+ case 0x00400000:
+ case 0x00500000:
+ case 0x00600000:
+ case 0x00700000:
+ MoveX86regToVariable(x86Reg,Addr + N64MEM);
+ break;
+ case 0x04000000:
+ switch (Addr) {
+ case 0x04040000: MoveX86regToVariable(x86Reg,&SP_MEM_ADDR_REG); break;
+ case 0x04040004: MoveX86regToVariable(x86Reg,&SP_DRAM_ADDR_REG); break;
+ case 0x04040008:
+ MoveX86regToVariable(x86Reg,&SP_RD_LEN_REG);
+ Pushad();
+ Call_Direct(&SP_DMA_READ);
+ Popad();
+ break;
+ case 0x0404000C:
+ MoveX86regToVariable(x86Reg,&SP_WR_LEN_REG);
+ Pushad();
+ Call_Direct(&SP_DMA_WRITE);
+ Popad();
+ break;
+ case 0x04040010:
+ MoveX86regToVariable(x86Reg,&RegModValue);
+ Pushad();
+ Call_Direct(ChangeSpStatus);
+ Popad();
+ break;
+ case 0x0404001C: MoveConstToVariable(0,&SP_SEMAPHORE_REG); break;
+ case 0x04080000:
+ MoveX86regToVariable(x86Reg,&SP_PC_REG);
+ AndConstToVariable(0xFFC,&SP_PC_REG);
+ break;
+ default:
+ if (Addr < 0x04002000)
+ MoveX86regToVariable(x86Reg,Addr + N64MEM);
+ }
+ break;
+ case 0x04100000:
+ break;
+ //MoveX86regToVariable(x86Reg,Addr + N64MEM);
+ case 0x04300000:
+ switch (Addr) {
+ case 0x04300000:
+ MoveX86regToVariable(x86Reg,&RegModValue);
+ Pushad();
+ Call_Direct(ChangeMiIntrMask);
+ Popad();
+ break;
+ case 0x0430000C:
+ MoveX86regToVariable(x86Reg,&RegModValue);
+ Pushad();
+ Call_Direct(ChangeMiIntrMask);
+ Popad();
+ break;
+ }
+ break;
+
+ case 0x04400000:
+ switch (Addr) {
+ case 0x04400000:
+ // inserted in place of compiled stuff
+ MoveX86regToVariable(x86Reg,&VI_STATUS_REG);
+ break;
+ case 0x04400004:
+ MoveX86regToVariable(x86Reg,&VI_ORIGIN_REG);
+ AndConstToVariable(0xFFFFFF,&VI_ORIGIN_REG);
+ break;
+ case 0x04400008:
+ // inserted in place of compiled stuff
+ MoveX86regToVariable(x86Reg,&VI_WIDTH_REG);
+ break;
+ case 0x0440000C: MoveX86regToVariable(x86Reg,&VI_INTR_REG); break;
+ case 0x04400010:
+ AndConstToVariable(~MI_INTR_VI,&MI_INTR_REG);
+ Pushad();
+ Call_Direct(CheckInterrupts);
+ Popad();
+ break;
+ case 0x04400014: MoveX86regToVariable(x86Reg,&VI_BURST_REG); break;
+ case 0x04400018: MoveX86regToVariable(x86Reg,&VI_V_SYNC_REG); break;
+ case 0x0440001C: MoveX86regToVariable(x86Reg,&VI_H_SYNC_REG); break;
+ case 0x04400020: MoveX86regToVariable(x86Reg,&VI_LEAP_REG); break;
+ case 0x04400024: MoveX86regToVariable(x86Reg,&VI_H_START_REG); break;
+ case 0x04400028: MoveX86regToVariable(x86Reg,&VI_V_START_REG); break;
+ case 0x0440002C: MoveX86regToVariable(x86Reg,&VI_V_BURST_REG); break;
+ case 0x04400030: MoveX86regToVariable(x86Reg,&VI_X_SCALE_REG); break;
+ case 0x04400034: MoveX86regToVariable(x86Reg,&VI_Y_SCALE_REG); break;
+ }
+ break;
+ case 0x04500000: /* AI registers */
+ switch (Addr) {
+ case 0x04500000: MoveX86regToVariable(x86Reg,&AI_DRAM_ADDR_REG); break;
+ case 0x04500004:
+ MoveX86regToVariable(x86Reg,&AI_LEN_REG);
+ Pushad();
+ //MoveX86RegToX86Reg(x86_ESP, x86_EAX);
+ //AndConstToX86Reg(x86_EAX, 8);
+ //SubX86RegToX86Reg(x86_ESP,x86_EAX);
+ //Push(x86_EAX);
+ Call_Direct(AiLenChanged);
+ //Pop(x86_EAX);
+ //AddX86RegToX86Reg(x86_ESP,x86_EAX);
+ Popad();
+ break;
+ case 0x04500008:
+ MoveX86regToVariable(x86Reg,&AI_CONTROL_REG);
+ AndConstToVariable(1,&AI_CONTROL_REG);
+ case 0x0450000C:
+ /* Clear Interrupt */;
+ AndConstToVariable(~MI_INTR_AI,&MI_INTR_REG);
+ AndConstToVariable(~MI_INTR_AI,&AudioIntrReg);
+ Pushad();
+ Call_Direct(CheckInterrupts);
+ Popad();
+ break;
+ case 0x04500010:
+ MoveX86regToVariable(x86Reg,Addr + N64MEM);
+ break;
+ default:
+ MoveX86regToVariable(x86Reg,Addr + N64MEM);
+ }
+ break;
+ case 0x04600000:
+ switch (Addr) {
+ case 0x04600000: MoveX86regToVariable(x86Reg,&PI_DRAM_ADDR_REG); break;
+ case 0x04600004: MoveX86regToVariable(x86Reg,&PI_CART_ADDR_REG); break;
+ case 0x04600008:
+ MoveX86regToVariable(x86Reg,&PI_RD_LEN_REG);
+ Pushad();
+ Call_Direct(&PI_DMA_READ);
+ Popad();
+ break;
+ case 0x0460000C:
+ MoveX86regToVariable(x86Reg,&PI_WR_LEN_REG);
+ Pushad();
+ Call_Direct(&PI_DMA_WRITE);
+ Popad();
+ break;
+ case 0x04600010:
+ AndConstToVariable(~MI_INTR_PI,&MI_INTR_REG);
+ Pushad();
+ Call_Direct(CheckInterrupts);
+ Popad();
+ break;
+ MoveX86regToVariable(x86Reg,&VI_ORIGIN_REG);
+ AndConstToVariable(0xFFFFFF,&VI_ORIGIN_REG);
+ case 0x04600014:
+ MoveX86regToVariable(x86Reg,&PI_DOMAIN1_REG);
+ AndConstToVariable(0xFF,&PI_DOMAIN1_REG);
+ break;
+ case 0x04600018:
+ MoveX86regToVariable(x86Reg,&PI_BSD_DOM1_PWD_REG);
+ AndConstToVariable(0xFF,&PI_BSD_DOM1_PWD_REG);
+ break;
+ case 0x0460001C:
+ MoveX86regToVariable(x86Reg,&PI_BSD_DOM1_PGS_REG);
+ AndConstToVariable(0xFF,&PI_BSD_DOM1_PGS_REG);
+ break;
+ case 0x04600020:
+ MoveX86regToVariable(x86Reg,&PI_BSD_DOM1_RLS_REG);
+ AndConstToVariable(0xFF,&PI_BSD_DOM1_RLS_REG);
+ break;
+ }
+ break;
+ case 0x04700000:
+ switch (Addr) {
+ case 0x04700010: MoveX86regToVariable(x86Reg,&RI_REFRESH_REG); break;
+ }
+ break;
+ case 0x04800000:
+ switch (Addr) {
+ case 0x04800000: MoveX86regToVariable(x86Reg,&SI_DRAM_ADDR_REG); break;
+ case 0x04800004:
+ MoveX86regToVariable(x86Reg,&SI_PIF_ADDR_RD64B_REG);
+ Pushad();
+ Call_Direct(&SI_DMA_READ);
+ Popad();
+ break;
+ case 0x04800010:
+ MoveX86regToVariable(x86Reg,&SI_PIF_ADDR_WR64B_REG);
+ Pushad();
+ Call_Direct(&SI_DMA_WRITE);
+ Popad();
+ break;
+ case 0x04800018:
+ AndConstToVariable(~MI_INTR_SI,&MI_INTR_REG);
+ AndConstToVariable(~SI_STATUS_INTERRUPT,&SI_STATUS_REG);
+ Pushad();
+ Call_Direct(CheckInterrupts);
+ Popad();
+ break;
+ }
+ break;
+ case 0x1FC00000:
+ MoveX86regToVariable(x86Reg,Addr + N64MEM);
+ break;
+ }
+}
+
+int32_t r4300i_LB_NonMemory ( uint32_t PAddr, uint32_t * Value, uint32_t SignExtend ) {
+ if (PAddr >= 0x10000000 && PAddr < 0x16000000) {
+ if (WrittenToRom) { return 0; }
+ if ((PAddr & 2) == 0) { PAddr = (PAddr + 4) ^ 2; }
+ if ((PAddr - 0x10000000) < RomFileSize) {
+ if (SignExtend) {
+ *Value = (char)*PageROM((PAddr - 0x10000000)^3);
+
+ } else {
+ *Value = *PageROM((PAddr - 0x10000000)^3);
+ }
+ return 1;
+ } else {
+ *Value = 0;
+ return 0;
+ }
+ }
+
+ switch (PAddr & 0xFFF00000) {
+ default:
+ * Value = 0;
+ return 0;
+ break;
+ }
+ return 1;
+}
+
+uint32_t r4300i_LB_VAddr ( uint32_t VAddr, uint8_t * Value ) {
+ if (TLB_Map[VAddr >> 12] == 0) { return 0; }
+ *Value = *(uint8_t *)(TLB_Map[VAddr >> 12] + (VAddr ^ 3));
+ return 1;
+}
+
+uint32_t r4300i_LD_VAddr ( uint32_t VAddr, uint64_t * Value ) {
+ if (TLB_Map[VAddr >> 12] == 0) { return 0; }
+ *((uint32_t *)(Value) + 1) = *(uint32_t *)(TLB_Map[VAddr >> 12] + VAddr);
+ *((uint32_t *)(Value)) = *(uint32_t *)(TLB_Map[VAddr >> 12] + VAddr + 4);
+ return 1;
+}
+
+int32_t r4300i_LH_NonMemory ( uint32_t PAddr, uint32_t * Value, int32_t SignExtend ) {
+ switch (PAddr & 0xFFF00000) {
+ default:
+ * Value = 0;
+ return 0;
+ break;
+ }
+ return 1;
+}
+
+uint32_t r4300i_LH_VAddr ( uint32_t VAddr, uint16_t * Value ) {
+ if (TLB_Map[VAddr >> 12] == 0) { return 0; }
+ *Value = *(uint16_t *)(TLB_Map[VAddr >> 12] + (VAddr ^ 2));
+ return 1;
+}
+
+int32_t r4300i_LW_NonMemory ( uint32_t PAddr, uint32_t * Value ) {
+ if (PAddr >= 0x10000000 && PAddr < 0x16000000) {
+ if (WrittenToRom) {
+ *Value = WroteToRom;
+ //LogMessage("%X: Read crap from Rom %X from %X",PROGRAM_COUNTER,*Value,PAddr);
+ WrittenToRom = 0;
+ return 1;
+ }
+ if ((PAddr - 0x10000000) < RomFileSize) {
+ *Value = *(uint32_t *)PageROM((PAddr - 0x10000000));
+ return 1;
+ } else {
+ *Value = PAddr & 0xFFFF;
+ *Value = (*Value << 16) | *Value;
+ return 0;
+ }
+ }
+
+ switch (PAddr & 0xFFF00000) {
+ case 0x03F00000:
+ switch (PAddr) {
+ case 0x03F00000: * Value = RDRAM_CONFIG_REG; break;
+ case 0x03F00004: * Value = RDRAM_DEVICE_ID_REG; break;
+ case 0x03F00008: * Value = RDRAM_DELAY_REG; break;
+ case 0x03F0000C: * Value = RDRAM_MODE_REG; break;
+ case 0x03F00010: * Value = RDRAM_REF_INTERVAL_REG; break;
+ case 0x03F00014: * Value = RDRAM_REF_ROW_REG; break;
+ case 0x03F00018: * Value = RDRAM_RAS_INTERVAL_REG; break;
+ case 0x03F0001C: * Value = RDRAM_MIN_INTERVAL_REG; break;
+ case 0x03F00020: * Value = RDRAM_ADDR_SELECT_REG; break;
+ case 0x03F00024: * Value = RDRAM_DEVICE_MANUF_REG; break;
+ default:
+ * Value = 0;
+ return 0;
+ }
+ break;
+ case 0x04000000:
+ switch (PAddr) {
+ case 0x04040010: *Value = SP_STATUS_REG; break;
+ case 0x04040014: *Value = SP_DMA_FULL_REG; break;
+ case 0x04040018: *Value = SP_DMA_BUSY_REG; break;
+ case 0x04080000: *Value = SP_PC_REG; break;
+ default:
+ * Value = 0;
+ return 0;
+ }
+ break;
+ case 0x04100000:
+ switch (PAddr) {
+ case 0x0410000C: *Value = DPC_STATUS_REG; break;
+ case 0x04100010: *Value = DPC_CLOCK_REG; break;
+ case 0x04100014: *Value = DPC_BUFBUSY_REG; break;
+ case 0x04100018: *Value = DPC_PIPEBUSY_REG; break;
+ case 0x0410001C: *Value = DPC_TMEM_REG; break;
+ default:
+ * Value = 0;
+ return 0;
+ }
+ break;
+ case 0x04300000:
+ switch (PAddr) {
+ case 0x04300000: * Value = MI_MODE_REG; break;
+ case 0x04300004: * Value = MI_VERSION_REG; break;
+ case 0x04300008: * Value = MI_INTR_REG; break;
+ case 0x0430000C: * Value = MI_INTR_MASK_REG; break;
+ default:
+ * Value = 0;
+ return 0;
+ }
+ break;
+ case 0x04400000:
+ switch (PAddr) {
+ case 0x04400000: *Value = VI_STATUS_REG; break;
+ case 0x04400004: *Value = VI_ORIGIN_REG; break;
+ case 0x04400008: *Value = VI_WIDTH_REG; break;
+ case 0x0440000C: *Value = VI_INTR_REG; break;
+ case 0x04400010:
+ *Value = 0;
+ break;
+ case 0x04400014: *Value = VI_BURST_REG; break;
+ case 0x04400018: *Value = VI_V_SYNC_REG; break;
+ case 0x0440001C: *Value = VI_H_SYNC_REG; break;
+ case 0x04400020: *Value = VI_LEAP_REG; break;
+ case 0x04400024: *Value = VI_H_START_REG; break;
+ case 0x04400028: *Value = VI_V_START_REG ; break;
+ case 0x0440002C: *Value = VI_V_BURST_REG; break;
+ case 0x04400030: *Value = VI_X_SCALE_REG; break;
+ case 0x04400034: *Value = VI_Y_SCALE_REG; break;
+ default:
+ * Value = 0;
+ return 0;
+ }
+ break;
+ case 0x04500000:
+ switch (PAddr) {
+ case 0x04500004: *Value = AiReadLength(); break;
+ case 0x0450000C: *Value = AI_STATUS_REG; break;
+ default:
+ * Value = 0;
+ return 0;
+ }
+ break;
+ case 0x04600000:
+ switch (PAddr) {
+ case 0x04600010: *Value = PI_STATUS_REG; break;
+ case 0x04600014: *Value = PI_DOMAIN1_REG; break;
+ case 0x04600018: *Value = PI_BSD_DOM1_PWD_REG; break;
+ case 0x0460001C: *Value = PI_BSD_DOM1_PGS_REG; break;
+ case 0x04600020: *Value = PI_BSD_DOM1_RLS_REG; break;
+ case 0x04600024: *Value = PI_DOMAIN2_REG; break;
+ case 0x04600028: *Value = PI_BSD_DOM2_PWD_REG; break;
+ case 0x0460002C: *Value = PI_BSD_DOM2_PGS_REG; break;
+ case 0x04600030: *Value = PI_BSD_DOM2_RLS_REG; break;
+ default:
+ * Value = 0;
+ return 0;
+ }
+ break;
+ case 0x04700000:
+ switch (PAddr) {
+ case 0x04700000: * Value = RI_MODE_REG; break;
+ case 0x04700004: * Value = RI_CONFIG_REG; break;
+ case 0x04700008: * Value = RI_CURRENT_LOAD_REG; break;
+ case 0x0470000C: * Value = RI_SELECT_REG; break;
+ case 0x04700010: * Value = RI_REFRESH_REG; break;
+ case 0x04700014: * Value = RI_LATENCY_REG; break;
+ case 0x04700018: * Value = RI_RERROR_REG; break;
+ case 0x0470001C: * Value = RI_WERROR_REG; break;
+ default:
+ * Value = 0;
+ return 0;
+ }
+ break;
+ case 0x04800000:
+ switch (PAddr) {
+ case 0x04800018: *Value = SI_STATUS_REG; break;
+ default:
+ *Value = 0;
+ return 0;
+ }
+ break;
+ case 0x05000000:
+ *Value = PAddr & 0xFFFF;
+ *Value = (*Value << 16) | *Value;
+ return 0;
+ case 0x08000000:
+ *Value = 0;
+ break;
+ default:
+ *Value = PAddr & 0xFFFF;
+ *Value = (*Value << 16) | *Value;
+ return 0;
+ break;
+ }
+ return 1;
+}
+
+void r4300i_LW_PAddr ( uint32_t PAddr, uint32_t * Value ) {
+ *Value = *(uint32_t *)(N64MEM+PAddr);
+}
+
+uint32_t r4300i_LW_VAddr ( uint32_t VAddr, uint32_t * Value ) {
+ uintptr_t address = (TLB_Map[VAddr >> 12] + VAddr);
+
+ if (TLB_Map[VAddr >> 12] == 0) { return 0; }
+
+ if((address - (uintptr_t)RDRAM) > RdramSize) {
+ address = address - (uintptr_t)RDRAM;
+ return r4300i_LW_NonMemory(address, Value);
+ }
+ *Value = *(uint32_t *)address;
+ return 1;
+}
+
+int32_t r4300i_SB_NonMemory ( uint32_t PAddr, uint8_t Value ) {
+ switch (PAddr & 0xFFF00000) {
+ case 0x00000000:
+ case 0x00100000:
+ case 0x00200000:
+ case 0x00300000:
+ case 0x00400000:
+ case 0x00500000:
+ case 0x00600000:
+ case 0x00700000:
+ if (PAddr < RdramSize) {
+
+ *(uint8_t *)(N64MEM+PAddr) = Value;
+ if (N64_Blocks.NoOfRDRamBlocks[(PAddr & 0x00FFFFF0) >> 12] == 0) { break; }
+ N64_Blocks.NoOfRDRamBlocks[(PAddr & 0x00FFFFF0) >> 12] = 0;
+ memset(JumpTable+((PAddr & 0xFFFFF000) >> 2),0,0x1000);
+ *(DelaySlotTable + ((PAddr & 0xFFFFF000) >> 12)) = NULL;
+ }
+ break;
+ default:
+ return 0;
+ break;
+ }
+ return 1;
+}
+
+uint32_t r4300i_SB_VAddr ( uint32_t VAddr, uint8_t Value ) {
+ if (TLB_Map[VAddr >> 12] == 0) { return 0; }
+ *(uint8_t *)(TLB_Map[VAddr >> 12] + (VAddr ^ 3)) = Value;
+
+ return 1;
+}
+
+int32_t r4300i_SH_NonMemory ( uint32_t PAddr, uint16_t Value ) {
+ switch (PAddr & 0xFFF00000) {
+ case 0x00000000:
+ case 0x00100000:
+ case 0x00200000:
+ case 0x00300000:
+ case 0x00400000:
+ case 0x00500000:
+ case 0x00600000:
+ case 0x00700000:
+ if (PAddr < RdramSize) {
+ *(uint16_t *)(N64MEM+PAddr) = Value;
+ if (N64_Blocks.NoOfRDRamBlocks[(PAddr & 0x00FFFFF0) >> 12] == 0) { break; }
+ N64_Blocks.NoOfRDRamBlocks[(PAddr & 0x00FFFFF0) >> 12] = 0;
+ memset(JumpTable+((PAddr & 0xFFFFF000) >> 2),0,0x1000);
+ *(DelaySlotTable + ((PAddr & 0xFFFFF000) >> 12)) = NULL;
+ }
+ break;
+ default:
+ return 0;
+ break;
+ }
+ return 1;
+}
+
+uint32_t r4300i_SD_VAddr ( uint32_t VAddr, uint64_t Value ) {
+ if (TLB_Map[VAddr >> 12] == 0) { return 0; }
+ *(uint32_t *)(TLB_Map[VAddr >> 12] + VAddr) = *((uint32_t *)(&Value) + 1);
+ *(uint32_t *)(TLB_Map[VAddr >> 12] + VAddr + 4) = *((uint32_t *)(&Value));
+ return 1;
+}
+
+uint32_t r4300i_SH_VAddr ( uint32_t VAddr, uint16_t Value ) {
+ if (TLB_Map[VAddr >> 12] == 0) { return 0; }
+ *(uint16_t *)(TLB_Map[VAddr >> 12] + (VAddr ^ 2)) = Value;
+ return 1;
+}
+
+int32_t r4300i_SW_NonMemory ( uint32_t PAddr, uint32_t Value ) {
+ if (PAddr >= 0x10000000 && PAddr < 0x16000000) {
+ if ((PAddr - 0x10000000) < RomFileSize) {
+ WrittenToRom = 1;
+ WroteToRom = Value;
+ } else {
+ return 0;
+ }
+ }
+
+ switch (PAddr & 0xFFF00000) {
+ case 0x00000000:
+ case 0x00100000:
+ case 0x00200000:
+ case 0x00300000:
+ case 0x00400000:
+ case 0x00500000:
+ case 0x00600000:
+ case 0x00700000:
+ if (PAddr < RdramSize) {
+ *(uint32_t *)(N64MEM+PAddr) = Value;
+ if (N64_Blocks.NoOfRDRamBlocks[(PAddr & 0x00FFFFF0) >> 12] == 0) { break; }
+ N64_Blocks.NoOfRDRamBlocks[(PAddr & 0x00FFFFF0) >> 12] = 0;
+ memset(JumpTable+((PAddr & 0xFFFFF000) >> 2),0,0x1000);
+ *(DelaySlotTable + ((PAddr & 0xFFFFF000) >> 12)) = NULL;
+ }
+ break;
+ case 0x03F00000:
+ switch (PAddr) {
+ case 0x03F00000: RDRAM_CONFIG_REG = Value; break;
+ case 0x03F00004: RDRAM_DEVICE_ID_REG = Value; break;
+ case 0x03F00008: RDRAM_DELAY_REG = Value; break;
+ case 0x03F0000C: RDRAM_MODE_REG = Value; break;
+ case 0x03F00010: RDRAM_REF_INTERVAL_REG = Value; break;
+ case 0x03F00014: RDRAM_REF_ROW_REG = Value; break;
+ case 0x03F00018: RDRAM_RAS_INTERVAL_REG = Value; break;
+ case 0x03F0001C: RDRAM_MIN_INTERVAL_REG = Value; break;
+ case 0x03F00020: RDRAM_ADDR_SELECT_REG = Value; break;
+ case 0x03F00024: RDRAM_DEVICE_MANUF_REG = Value; break;
+ case 0x03F04004: break;
+ case 0x03F08004: break;
+ case 0x03F80004: break;
+ case 0x03F80008: break;
+ case 0x03F8000C: break;
+ case 0x03F80014: break;
+ default:
+ return 0;
+ }
+ break;
+ case 0x04000000:
+ if (PAddr < 0x04002000) {
+ *(uint32_t *)(N64MEM+PAddr) = Value;
+ if (PAddr < 0x04001000) {
+ if (N64_Blocks.NoOfDMEMBlocks == 0) { break; }
+ N64_Blocks.NoOfDMEMBlocks = 0;
+ } else {
+ if (N64_Blocks.NoOfIMEMBlocks == 0) { break; }
+ N64_Blocks.NoOfIMEMBlocks = 0;
+ }
+ memset(JumpTable+((PAddr & 0xFFFFF000) >> 2),0,0x1000);
+ *(DelaySlotTable + ((PAddr & 0xFFFFF000) >> 12)) = NULL;
+ return 1;
+ }
+ switch (PAddr) {
+ case 0x04040000: SP_MEM_ADDR_REG = Value; break;
+ case 0x04040004: SP_DRAM_ADDR_REG = Value; break;
+ case 0x04040008:
+ SP_RD_LEN_REG = Value;
+ SP_DMA_READ();
+ break;
+ case 0x0404000C:
+ SP_WR_LEN_REG = Value;
+ SP_DMA_WRITE();
+ break;
+ case 0x04040010:
+ if ( ( Value & SP_CLR_HALT ) != 0) { SP_STATUS_REG &= ~SP_STATUS_HALT; }
+ if ( ( Value & SP_SET_HALT ) != 0) { SP_STATUS_REG |= SP_STATUS_HALT; }
+ if ( ( Value & SP_CLR_BROKE ) != 0) { SP_STATUS_REG &= ~SP_STATUS_BROKE; }
+ if ( ( Value & SP_CLR_INTR ) != 0) {
+ MI_INTR_REG &= ~MI_INTR_SP;
+ CheckInterrupts();
+ }
+ if ( ( Value & SP_CLR_SSTEP ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SSTEP; }
+ if ( ( Value & SP_SET_SSTEP ) != 0) { SP_STATUS_REG |= SP_STATUS_SSTEP; }
+ if ( ( Value & SP_CLR_INTR_BREAK ) != 0) { SP_STATUS_REG &= ~SP_STATUS_INTR_BREAK; }
+ if ( ( Value & SP_SET_INTR_BREAK ) != 0) { SP_STATUS_REG |= SP_STATUS_INTR_BREAK; }
+ if ( ( Value & SP_CLR_SIG0 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG0; }
+ if ( ( Value & SP_SET_SIG0 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG0; }
+ if ( ( Value & SP_CLR_SIG1 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG1; }
+ if ( ( Value & SP_SET_SIG1 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG1; }
+ if ( ( Value & SP_CLR_SIG2 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG2; }
+ if ( ( Value & SP_SET_SIG2 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG2; }
+ if ( ( Value & SP_CLR_SIG3 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG3; }
+ if ( ( Value & SP_SET_SIG3 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG3; }
+ if ( ( Value & SP_CLR_SIG4 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG4; }
+ if ( ( Value & SP_SET_SIG4 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG4; }
+ if ( ( Value & SP_CLR_SIG5 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG5; }
+ if ( ( Value & SP_SET_SIG5 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG5; }
+ if ( ( Value & SP_CLR_SIG6 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG6; }
+ if ( ( Value & SP_SET_SIG6 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG6; }
+ if ( ( Value & SP_CLR_SIG7 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG7; }
+ if ( ( Value & SP_SET_SIG7 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG7; }
+
+ RunRsp();
+
+ break;
+ case 0x0404001C: SP_SEMAPHORE_REG = 0; break;
+ case 0x04080000: SP_PC_REG = Value & 0xFFC; break;
+ default:
+ return 0;
+ }
+ break;
+ case 0x04100000:
+ switch (PAddr) {
+ case 0x04100000:
+ DPC_START_REG = Value;
+ DPC_CURRENT_REG = Value;
+ break;
+ case 0x04100004:
+ DPC_END_REG = Value;
+ //if (ProcessRDPList) { ProcessRDPList(); }
+ break;
+ case 0x04100008: DPC_CURRENT_REG = Value; break;
+ case 0x0410000C:
+ if ( ( Value & DPC_CLR_XBUS_DMEM_DMA ) != 0) { DPC_STATUS_REG &= ~DPC_STATUS_XBUS_DMEM_DMA; }
+ if ( ( Value & DPC_SET_XBUS_DMEM_DMA ) != 0) { DPC_STATUS_REG |= DPC_STATUS_XBUS_DMEM_DMA; }
+ if ( ( Value & DPC_CLR_FREEZE ) != 0) { DPC_STATUS_REG &= ~DPC_STATUS_FREEZE; }
+ if ( ( Value & DPC_SET_FREEZE ) != 0) { DPC_STATUS_REG |= DPC_STATUS_FREEZE; }
+ if ( ( Value & DPC_CLR_FLUSH ) != 0) { DPC_STATUS_REG &= ~DPC_STATUS_FLUSH; }
+ if ( ( Value & DPC_SET_FLUSH ) != 0) { DPC_STATUS_REG |= DPC_STATUS_FLUSH; }
+ if ( ( Value & DPC_CLR_FREEZE ) != 0)
+ {
+ if ( ( SP_STATUS_REG & SP_STATUS_HALT ) == 0)
+ {
+ if ( ( SP_STATUS_REG & SP_STATUS_BROKE ) == 0 )
+ {
+ RunRsp();
+ }
+ }
+ }
+ break;
+ default:
+ return 0;
+ }
+ break;
+ case 0x04300000:
+ switch (PAddr) {
+ case 0x04300000:
+ MI_MODE_REG &= ~0x7F;
+ MI_MODE_REG |= (Value & 0x7F);
+ if ( ( Value & MI_CLR_INIT ) != 0 ) { MI_MODE_REG &= ~MI_MODE_INIT; }
+ if ( ( Value & MI_SET_INIT ) != 0 ) { MI_MODE_REG |= MI_MODE_INIT; }
+ if ( ( Value & MI_CLR_EBUS ) != 0 ) { MI_MODE_REG &= ~MI_MODE_EBUS; }
+ if ( ( Value & MI_SET_EBUS ) != 0 ) { MI_MODE_REG |= MI_MODE_EBUS; }
+ if ( ( Value & MI_CLR_DP_INTR ) != 0 ) {
+ MI_INTR_REG &= ~MI_INTR_DP;
+ CheckInterrupts();
+ }
+ if ( ( Value & MI_CLR_RDRAM ) != 0 ) { MI_MODE_REG &= ~MI_MODE_RDRAM; }
+ if ( ( Value & MI_SET_RDRAM ) != 0 ) { MI_MODE_REG |= MI_MODE_RDRAM; }
+ break;
+ case 0x0430000C:
+ if ( ( Value & MI_INTR_MASK_CLR_SP ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_SP; }
+ if ( ( Value & MI_INTR_MASK_SET_SP ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_SP; }
+ if ( ( Value & MI_INTR_MASK_CLR_SI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_SI; }
+ if ( ( Value & MI_INTR_MASK_SET_SI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_SI; }
+ if ( ( Value & MI_INTR_MASK_CLR_AI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_AI; }
+ if ( ( Value & MI_INTR_MASK_SET_AI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_AI; }
+ if ( ( Value & MI_INTR_MASK_CLR_VI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_VI; }
+ if ( ( Value & MI_INTR_MASK_SET_VI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_VI; }
+ if ( ( Value & MI_INTR_MASK_CLR_PI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_PI; }
+ if ( ( Value & MI_INTR_MASK_SET_PI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_PI; }
+ if ( ( Value & MI_INTR_MASK_CLR_DP ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_DP; }
+ if ( ( Value & MI_INTR_MASK_SET_DP ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_DP; }
+ break;
+ default:
+ return 0;
+ }
+ break;
+ case 0x04400000:
+ switch (PAddr) {
+ case 0x04400000:
+ //if (VI_STATUS_REG != Value) {
+ VI_STATUS_REG = Value;
+ // if (ViStatusChanged != NULL ) { ViStatusChanged(); }
+ //}
+ break;
+ case 0x04400004:
+
+ VI_ORIGIN_REG = (Value & 0xFFFFFF);
+ //if (UpdateScreen != NULL ) { UpdateScreen(); }
+ break;
+ case 0x04400008:
+ //if (VI_WIDTH_REG != Value) {
+ VI_WIDTH_REG = Value;
+ // if (ViWidthChanged != NULL ) { ViWidthChanged(); }
+ //}
+ break;
+ case 0x0440000C: VI_INTR_REG = Value; break;
+ case 0x04400010:
+ MI_INTR_REG &= ~MI_INTR_VI;
+ CheckInterrupts();
+ break;
+ case 0x04400014: VI_BURST_REG = Value; break;
+ case 0x04400018: VI_V_SYNC_REG = Value; break;
+ case 0x0440001C: VI_H_SYNC_REG = Value; break;
+ case 0x04400020: VI_LEAP_REG = Value; break;
+ case 0x04400024: VI_H_START_REG = Value; break;
+ case 0x04400028: VI_V_START_REG = Value; break;
+ case 0x0440002C: VI_V_BURST_REG = Value; break;
+ case 0x04400030: VI_X_SCALE_REG = Value; break;
+ case 0x04400034: VI_Y_SCALE_REG = Value; break;
+ default:
+ return 0;
+ }
+ break;
+ case 0x04500000:
+ switch (PAddr) {
+ case 0x04500000: AI_DRAM_ADDR_REG = Value; break;
+ case 0x04500004:
+ AI_LEN_REG = Value;
+ if (AiLenChanged != NULL) { AiLenChanged(); }
+ break;
+ case 0x04500008: AI_CONTROL_REG = (Value & 0x1); break;
+ case 0x0450000C:
+ /* Clear Interrupt */;
+ MI_INTR_REG &= ~MI_INTR_AI;
+ AudioIntrReg &= ~MI_INTR_AI;
+ CheckInterrupts();
+ break;
+ case 0x04500010:
+ AI_DACRATE_REG = Value;
+ //if (AiDacrateChanged != NULL) { AiDacrateChanged(SYSTEM_NTSC); }
+ break;
+ case 0x04500014: AI_BITRATE_REG = Value; break;
+ default:
+ return 0;
+ }
+ break;
+ case 0x04600000:
+ switch (PAddr) {
+ case 0x04600000: PI_DRAM_ADDR_REG = Value; break;
+ case 0x04600004: PI_CART_ADDR_REG = Value; break;
+ case 0x04600008:
+ PI_RD_LEN_REG = Value;
+ PI_DMA_READ();
+ break;
+ case 0x0460000C:
+ PI_WR_LEN_REG = Value;
+ PI_DMA_WRITE();
+ break;
+ case 0x04600010:
+ //if ((Value & PI_SET_RESET) != 0 ) { DisplayError("reset Controller"); }
+ if ((Value & PI_CLR_INTR) != 0 ) {
+ MI_INTR_REG &= ~MI_INTR_PI;
+ CheckInterrupts();
+ }
+ break;
+ case 0x04600014: PI_DOMAIN1_REG = (Value & 0xFF); break;
+ case 0x04600018: PI_BSD_DOM1_PWD_REG = (Value & 0xFF); break;
+ case 0x0460001C: PI_BSD_DOM1_PGS_REG = (Value & 0xFF); break;
+ case 0x04600020: PI_BSD_DOM1_RLS_REG = (Value & 0xFF); break;
+ default:
+ return 0;
+ }
+ break;
+ case 0x04700000:
+ switch (PAddr) {
+ case 0x04700000: RI_MODE_REG = Value; break;
+ case 0x04700004: RI_CONFIG_REG = Value; break;
+ case 0x04700008: RI_CURRENT_LOAD_REG = Value; break;
+ case 0x0470000C: RI_SELECT_REG = Value; break;
+ case 0x04700010: RI_REFRESH_REG = Value; break;
+ case 0x04700014: RI_LATENCY_REG = Value; break;
+ case 0x04700018: RI_RERROR_REG = Value; break;
+ case 0x0470001C: RI_WERROR_REG = Value; break;
+ default:
+ return 0;
+ }
+ break;
+ case 0x04800000:
+ switch (PAddr) {
+ case 0x04800000: SI_DRAM_ADDR_REG = Value; break;
+ case 0x04800004:
+ SI_PIF_ADDR_RD64B_REG = Value;
+ SI_DMA_READ ();
+ break;
+ case 0x04800010:
+ SI_PIF_ADDR_WR64B_REG = Value;
+ SI_DMA_WRITE();
+ break;
+ case 0x04800018:
+ MI_INTR_REG &= ~MI_INTR_SI;
+ SI_STATUS_REG &= ~SI_STATUS_INTERRUPT;
+ CheckInterrupts();
+ break;
+ default:
+ return 0;
+ }
+ break;
+ case 0x08000000:
+ if (PAddr != 0x08010000) { return 0; }
+ //WriteToFlashCommand(Value);
+ break;
+ case 0x1FC00000:
+ if (PAddr < 0x1FC007C0) {
+ return 0;
+ } else if (PAddr < 0x1FC00800) {
+
+ if (PAddr == 0x1FC007FC) {
+ PifRamWrite();
+ }
+ return 1;
+ }
+ return 0;
+ break;
+ default:
+ return 0;
+ break;
+ }
+ return 1;
+}
+
+uint32_t r4300i_SW_VAddr ( uint32_t VAddr, uint32_t Value ) {
+ uintptr_t address = (TLB_Map[VAddr >> 12] + VAddr);
+
+ if (TLB_Map[VAddr >> 12] == 0) { return 0; }
+
+ if((address - (uintptr_t)RDRAM) > RdramSize) {
+ address = address - (uintptr_t)RDRAM;
+ return r4300i_SW_NonMemory(address, Value);
+ }
+ *(uint32_t *)address = Value;
+ return 1;
+}
+
+void ResetRecompCode (void) {
+ uint32_t count;
+ RecompPos = RecompCode;
+ TargetIndex = 0;
+
+ //Jump Table
+ for (count = 0; count < (RdramSize >> 12); count ++ ) {
+ if (N64_Blocks.NoOfRDRamBlocks[count] > 0) {
+ N64_Blocks.NoOfRDRamBlocks[count] = 0;
+ memset(JumpTable + (count << 10),0,0x1000);
+ *(DelaySlotTable + count) = NULL;
+
+ }
+ }
+
+ if (N64_Blocks.NoOfDMEMBlocks > 0) {
+ N64_Blocks.NoOfDMEMBlocks = 0;
+ memset(JumpTable + (0x04000000 >> 2),0,0x1000);
+ *(DelaySlotTable + (0x04000000 >> 12)) = NULL;
+ }
+ if (N64_Blocks.NoOfIMEMBlocks > 0) {
+ N64_Blocks.NoOfIMEMBlocks = 0;
+ memset(JumpTable + (0x04001000 >> 2),0,0x1000);
+ *(DelaySlotTable + (0x04001000 >> 12)) = NULL;
+ }
+}
+
+#ifndef __USE_GNU
+#define __USE_GNU
+#endif
+#include <sys/ucontext.h>
+
+static struct sigaction act;
+static struct sigaction oact;
+static sigset_t sset;
+void sig_handler(int signo, siginfo_t * info, ucontext_t * context);
+
+void InitExceptionHandler() {
+
+ sigset_t blockset;
+
+ sigemptyset(&blockset);
+ sigaddset(&blockset, SIGSEGV);
+
+ pthread_sigmask(SIG_UNBLOCK, &blockset, NULL);
+
+ sigemptyset(&sset);
+ sigaddset(&sset, SIGSEGV);
+
+ act.sa_flags = SA_SIGINFO ;
+ act.sa_mask = sset;
+ act.sa_sigaction = (void (*)(int, siginfo_t*, void*)) sig_handler;
+
+ if(sigaction(SIGSEGV, (const struct sigaction *) &act, &oact))
+ printf("error setting up exception handler\n");
+}
+
+int r4300i_CPU_MemoryFilter64_2( uintptr_t MemAddress, ucontext_t * context);
+
+void sig_handler(int signo, siginfo_t * info, ucontext_t * context)
+{
+ int i = 0;
+
+ if(signo==SIGSEGV) {
+ uintptr_t MemAddress = ((char *)info->si_addr - (char *)N64MEM);
+
+ /*
+ A Hack to fix some crappy GCC thing when R15 gets overwritten.
+ R15 should _never_ be overwritten. >:(
+ */
+#ifdef USEX64
+ if(context->uc_mcontext.gregs[REG_R15] != (uintptr_t)TLB_Map) {
+ context->uc_mcontext.gregs[REG_R15] = (uintptr_t)TLB_Map;
+ return;
+ }
+#endif
+ i = r4300i_CPU_MemoryFilter64_2(MemAddress,context);
+ if(i==0)
+ return;
+ }
+
+ return;
+}
+
+static int32_t CONV_REG64(int32_t dest_reg) {
+ switch(dest_reg) {
+ case 0: return 13; break;
+ case 1: return 14; break;
+ case 2: return 12; break;
+ case 3: return 11; break;
+ case 6: return 9; break;
+ case 7: return 8; break;
+ case 8: return 0; break;
+ case 9: return 1; break;
+ case 10: return 2; break;
+ case 11: return 3; break;
+ case 12: return 4; break;
+ case 13: return 5; break;
+ case 14: return 6; break;
+ case 15: return 7; break;
+ default:
+ asm("int $3");
+
+ break;
+ }
+}
+
+
+#ifdef __LP64__
+int r4300i_CPU_MemoryFilter64_2( uintptr_t MemAddress, ucontext_t * context) {
+ uint8_t * ip = context->uc_mcontext.gregs[REG_RIP];
+
+ if(MemAddress == 0) {
+ return 1;
+ }
+
+ if((*ip & 0x40) && (*(ip+1) == 0xf) && (*(ip+2) == 0xb7)) {
+ uint8_t dest_reg = (*(ip+3) % 0x40) / 8;
+ int32_t half = 0;
+ if(*ip & 4) dest_reg += 8;
+ r4300i_LH_NonMemory(MemAddress, &half, 1);
+
+ context->uc_mcontext.gregs[CONV_REG64(dest_reg)] = (int32_t)half;
+
+
+ context->uc_mcontext.gregs[REG_RIP]+=4;
+
+ if((*(ip+3) & 0x7)==4)
+ context->uc_mcontext.gregs[REG_RIP]++;
+
+ if((*(ip+3) & 0xC0) == 0x80)
+ context->uc_mcontext.gregs[REG_RIP]+=4;
+ else if((*(ip+3) & 0xC0) == 0x40)
+ context->uc_mcontext.gregs[REG_RIP]+=1;
+
+ return 0;
+
+ } else if((*ip & 0x40) && (*(ip+1) ==0x89)) { // MOV [Rxx + Rxx], Exx
+ uint8_t dest_reg = (*(ip+2) % 0x40) / 8;
+ uint64_t dest = 0;
+
+ if(*ip & 4) dest_reg += 8;
+
+ dest = context->uc_mcontext.gregs[CONV_REG64(dest_reg)];
+
+ r4300i_SW_NonMemory(MemAddress, dest);
+
+ if((*(ip+2) & 0x7)==4)
+ context->uc_mcontext.gregs[REG_RIP]+=4;
+ else
+ context->uc_mcontext.gregs[REG_RIP]+=3;
+
+ if((*(ip+2) & 0xC0) == 0x80)
+ context->uc_mcontext.gregs[REG_RIP]+=4;
+ else if((*(ip+2) & 0xC0) == 0x40)
+ context->uc_mcontext.gregs[REG_RIP]+=1;
+
+ return 0;
+
+ } else if((*ip & 0x40) && (*(ip+1) ==0xC7)) { // MOV [Rxx + Rxx], Imm32
+ uint32_t imm32 = *(uint32_t*)(ip+4);
+ r4300i_SW_NonMemory(MemAddress, imm32);
+ context->uc_mcontext.gregs[REG_RIP]+=7;
+
+ // 40 C7 04 07 0F 00 00 00
+
+ //if(*(ip+2)&0x4)
+ if((*(ip+2) & 0x7)==4)
+ context->uc_mcontext.gregs[REG_RIP]++;
+ if((*(ip+2) & 0xC0) == 0x80)
+ context->uc_mcontext.gregs[REG_RIP]+=4;
+ else if((*(ip+2) & 0xC0) == 0x40)
+ context->uc_mcontext.gregs[REG_RIP]+=1;
+
+ return 0;
+ } else if ((*ip & 0x40) && (*(ip + 1) == 0x8B )) {
+ uint8_t dest_reg = (*(ip+2) % 0x40) / 8;
+ uint32_t word = 0;
+
+ //41 8B BF 30 D0 00 01
+
+ if(*ip & 4) dest_reg += 8;
+
+
+ r4300i_LW_NonMemory(MemAddress, &word);
+ context->uc_mcontext.gregs[CONV_REG64(dest_reg)] = word;
+
+ //if(*(ip+2) & 0x4)
+ if((*(ip+2) & 0x7)==4)
+ context->uc_mcontext.gregs[REG_RIP]+=4;
+ else
+ context->uc_mcontext.gregs[REG_RIP]+=3;
+
+ if((*(ip+2) & 0xC0) == 0x80)
+ context->uc_mcontext.gregs[REG_RIP]+=4;
+ else if((*(ip+2) & 0xC0) == 0x40)
+ context->uc_mcontext.gregs[REG_RIP]+=1;
+
+
+ return 0;
+
+ }
+
+ //asm("int $3");
+ return 1;
+}
+
+#else
+
+static int32_t CONV_REG(int32_t dest_reg) {
+ switch(dest_reg) {
+ case 0: return 5; break;
+ case 1: return 4; break;
+ case 2: return 3; break;
+ case 3: return 2; break;
+ case 6: return 1; break;
+ case 7: return 0; break;
+ default:
+ asm volatile("int $3");
+ break;
+ }
+}
+
+int r4300i_CPU_MemoryFilter64_2( uintptr_t MemAddress, ucontext_t * context) {
+ uint8_t * ip = context->uc_mcontext.gregs[REG_EIP];
+
+ if(MemAddress == 0) {
+ return 1;
+ }
+
+ if((*(ip) == 0xf) && (*(ip+1) == 0xb7)) {
+ uint8_t dest_reg = (*(ip+2) % 0x40) / 8;
+ int32_t half = 0;
+ r4300i_LH_NonMemory(MemAddress, &half, 1);
+
+ //((uint32_t*)(&lpEP->ContextRecord->Edi))[CONV_REG(dest_reg)] = (int32_t)half;
+ context->uc_mcontext.gregs[CONV_REG64(dest_reg)] = (int32_t)half;
+
+ context->uc_mcontext.gregs[REG_EIP]+=3;
+
+ if((*(ip+2) & 0x7)==4)
+ context->uc_mcontext.gregs[REG_EIP]++;
+ else if((*(ip+1) & 0x7)==5)
+ context->uc_mcontext.gregs[REG_EIP]+=4;
+
+
+ if((*(ip+2) & 0xC0) == 0x80)
+ context->uc_mcontext.gregs[REG_EIP]+=4;
+ else if((*(ip+2) & 0xC0) == 0x40)
+ context->uc_mcontext.gregs[REG_EIP]+=1;
+
+ return 0;
+
+ } else if((*(ip) ==0x89)) { // MOV [Rxx + Rxx], Exx
+ uint8_t dest_reg = (*(ip+1) % 0x40) / 8;
+ uint32_t dest = 0;
+
+ dest = context->uc_mcontext.gregs[CONV_REG64(dest_reg)];
+
+ r4300i_SW_NonMemory(MemAddress, dest);
+
+ if((*(ip+1) & 0x7)==4)
+ context->uc_mcontext.gregs[REG_EIP]+=3;
+ else
+ context->uc_mcontext.gregs[REG_EIP]+=2;
+
+ if((*(ip+1) & 0xC0) == 0x80)
+ context->uc_mcontext.gregs[REG_EIP]+=4;
+ else if((*(ip+1) & 0xC0) == 0x40)
+ context->uc_mcontext.gregs[REG_EIP]+=1;
+
+ return 0;
+
+ } else if((*(ip) ==0xC7)) { // MOV [Rxx + Rxx], Imm32
+ uint32_t imm32 = *(uint32_t*)(ip+2);
+ r4300i_SW_NonMemory(MemAddress, imm32);
+ context->uc_mcontext.gregs[REG_EIP]+=6;
+
+
+ // 40 C7 04 07 0F 00 00 00
+
+ //if(*(ip+2)&0x4)
+ if((*(ip+1) & 0x7)==4)
+ context->uc_mcontext.gregs[REG_EIP]++;
+ if((*(ip+1) & 0xC0) == 0x80)
+ context->uc_mcontext.gregs[REG_EIP]+=4;
+ else if((*(ip+1) & 0xC0) == 0x40)
+ context->uc_mcontext.gregs[REG_EIP]+=1;
+
+ return 0;
+ } else if (*ip == 0x8B ) {
+ uint8_t dest_reg = CONV_REG((*(ip+1) % 0x40) / 8);
+ uint32_t word = 0;
+ uint32_t *dest = 0;
+
+ dest = context->uc_mcontext.gregs[CONV_REG64(dest_reg)];
+ r4300i_LW_NonMemory(MemAddress, &word);
+ *dest = word;
+ //*dest = 0;
+ //if(*(ip+2) & 0x4)
+ if((*(ip+1) & 0x7)==4)
+ context->uc_mcontext.gregs[REG_EIP]+=3;
+ else if((*(ip+1) & 0x7)==5)
+ context->uc_mcontext.gregs[REG_EIP]+=6;
+ else
+ context->uc_mcontext.gregs[REG_EIP]+=2;
+
+ if((*(ip+1) & 0xC0) == 0x80)
+ context->uc_mcontext.gregs[REG_EIP]+=4;
+ else if((*(ip+1) & 0xC0) == 0x40)
+ context->uc_mcontext.gregs[REG_EIP]+=1;
+
+
+ return 0;
+
+ }
+
+ return 1;
+
+}
+
+
+#endif
diff --git a/src/usf/memory.h b/src/usf/memory.h new file mode 100644 index 0000000..de6952a --- /dev/null +++ b/src/usf/memory.h @@ -0,0 +1,84 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+#define LargeCompileBufferSize 0x03200000
+#define NormalCompileBufferSize 0x01500000
+
+#define RSP_RECOMPMEM_SIZE 0x400000
+#define RSP_SECRECOMPMEM_SIZE 0x200000
+
+#define ROM_IN_MAPSPACE
+
+extern uint32_t RdramSize, SystemRdramSize, RomFileSize;
+extern uintptr_t *TLB_Map;
+extern uint8_t * MemChunk;
+
+extern uint8_t *N64MEM, *RDRAM, *DMEM, *IMEM, * ROMPages[0x400], *savestatespace, * NOMEM;
+extern void ** JumpTable, ** DelaySlotTable;
+extern uint8_t *RecompCode, *RecompPos;
+extern uint32_t WrittenToRom, MemoryState;
+
+/* Memory Control */
+int Allocate_ROM ( void );
+int Allocate_Memory ( void );
+void Release_Memory ( void );
+int PreAllocate_Memory(void);
+
+void *malloc_exec(uint32_t bytes);
+void *jmalloc(uint32_t bytes);
+
+/* CPU memory functions */
+//int r4300i_Command_MemoryFilter ( uint32_t dwExptCode, LPEXCEPTION_POINTERS lpEP );
+//int r4300i_CPU_MemoryFilter ( uint32_t dwExptCode, LPEXCEPTION_POINTERS lpEP );
+int32_t r4300i_LB_NonMemory ( uint32_t PAddr, uint32_t * Value, uint32_t SignExtend );
+uint32_t r4300i_LB_VAddr ( uint32_t VAddr, uint8_t * Value );
+uint32_t r4300i_LD_VAddr ( uint32_t VAddr, uint64_t * Value );
+int32_t r4300i_LH_NonMemory ( uint32_t PAddr, uint32_t * Value, int32_t SignExtend );
+uint32_t r4300i_LH_VAddr ( uint32_t VAddr, uint16_t * Value );
+int32_t r4300i_LW_NonMemory ( uint32_t PAddr, uint32_t * Value );
+void r4300i_LW_PAddr ( uint32_t PAddr, uint32_t * Value );
+uint32_t r4300i_LW_VAddr ( uint32_t VAddr, uint32_t * Value );
+int32_t r4300i_SB_NonMemory ( uint32_t PAddr, uint8_t Value );
+uint32_t r4300i_SB_VAddr ( uint32_t VAddr, uint8_t Value );
+uint32_t r4300i_SD_VAddr ( uint32_t VAddr, uint64_t Value );
+int32_t r4300i_SH_NonMemory ( uint32_t PAddr, uint16_t Value );
+uint32_t r4300i_SH_VAddr ( uint32_t VAddr, uint16_t Value );
+int32_t r4300i_SW_NonMemory ( uint32_t PAddr, uint32_t Value );
+uint32_t r4300i_SW_VAddr ( uint32_t VAddr, uint32_t Value );
+
+/* Recompiler Memory Functions */
+void Compile_LB ( int32_t Reg, uint32_t Addr, uint32_t SignExtend );
+void Compile_LH ( int32_t Reg, uint32_t Addr, uint32_t SignExtend );
+void Compile_LW ( int32_t Reg, uint32_t Addr );
+void Compile_SB_Const ( uint8_t Value, uint32_t Addr );
+void Compile_SB_Register ( int32_t x86Reg, uint32_t Addr );
+void Compile_SH_Const ( uint16_t Value, uint32_t Addr );
+void Compile_SH_Register ( int32_t x86Reg, uint32_t Addr );
+void Compile_SW_Const ( uint32_t Value, uint32_t Addr );
+void Compile_SW_Register ( int32_t x86Reg, uint32_t Addr );
+void ResetRecompCode ( void );
+void InitExceptionHandler ();
+
+uint8_t * PageROM(uint32_t addr);
diff --git a/src/usf/opcode.h b/src/usf/opcode.h new file mode 100644 index 0000000..cf2fe39 --- /dev/null +++ b/src/usf/opcode.h @@ -0,0 +1,274 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+#ifndef __OpCode
+#define __OpCode
+
+#include "types.h"
+
+typedef struct {
+ union {
+
+ uint32_t Hex;
+ uint8_t Ascii[4];
+
+ struct {
+ unsigned offset : 16;
+ unsigned rt : 5;
+ unsigned rs : 5;
+ unsigned op : 6;
+ };
+
+ struct {
+ unsigned immediate : 16;
+ unsigned : 5;
+ unsigned base : 5;
+ unsigned : 6;
+ };
+
+ struct {
+ unsigned target : 26;
+ unsigned : 6;
+ };
+
+ struct {
+ unsigned funct : 6;
+ unsigned sa : 5;
+ unsigned rd : 5;
+ unsigned : 5;
+ unsigned : 5;
+ unsigned : 6;
+ };
+
+ struct {
+ unsigned : 6;
+ unsigned fd : 5;
+ unsigned fs : 5;
+ unsigned ft : 5;
+ unsigned fmt : 5;
+ unsigned : 6;
+ };
+ };
+
+} OPCODE;
+
+//R4300i OpCodes
+#define R4300i_SPECIAL 0
+#define R4300i_REGIMM 1
+#define R4300i_J 2
+#define R4300i_JAL 3
+#define R4300i_BEQ 4
+#define R4300i_BNE 5
+#define R4300i_BLEZ 6
+#define R4300i_BGTZ 7
+#define R4300i_ADDI 8
+#define R4300i_ADDIU 9
+#define R4300i_SLTI 10
+#define R4300i_SLTIU 11
+#define R4300i_ANDI 12
+#define R4300i_ORI 13
+#define R4300i_XORI 14
+#define R4300i_LUI 15
+#define R4300i_CP0 16
+#define R4300i_CP1 17
+#define R4300i_BEQL 20
+#define R4300i_BNEL 21
+#define R4300i_BLEZL 22
+#define R4300i_BGTZL 23
+#define R4300i_DADDI 24
+#define R4300i_DADDIU 25
+#define R4300i_LDL 26
+#define R4300i_LDR 27
+#define R4300i_LB 32
+#define R4300i_LH 33
+#define R4300i_LWL 34
+#define R4300i_LW 35
+#define R4300i_LBU 36
+#define R4300i_LHU 37
+#define R4300i_LWR 38
+#define R4300i_LWU 39
+#define R4300i_SB 40
+#define R4300i_SH 41
+#define R4300i_SWL 42
+#define R4300i_SW 43
+#define R4300i_SDL 44
+#define R4300i_SDR 45
+#define R4300i_SWR 46
+#define R4300i_CACHE 47
+#define R4300i_LL 48
+#define R4300i_LWC1 49
+#define R4300i_LWC2 0x32
+#define R4300i_LLD 0x34
+#define R4300i_LDC1 53
+#define R4300i_LDC2 0x36
+#define R4300i_LD 55
+#define R4300i_SC 0x38
+#define R4300i_SWC1 57
+#define R4300i_SWC2 0x3A
+#define R4300i_SCD 0x3C
+#define R4300i_SDC1 61
+#define R4300i_SDC2 62
+#define R4300i_SD 63
+
+/* R4300i Special opcodes */
+#define R4300i_SPECIAL_SLL 0
+#define R4300i_SPECIAL_SRL 2
+#define R4300i_SPECIAL_SRA 3
+#define R4300i_SPECIAL_SLLV 4
+#define R4300i_SPECIAL_SRLV 6
+#define R4300i_SPECIAL_SRAV 7
+#define R4300i_SPECIAL_JR 8
+#define R4300i_SPECIAL_JALR 9
+#define R4300i_SPECIAL_SYSCALL 12
+#define R4300i_SPECIAL_BREAK 13
+#define R4300i_SPECIAL_SYNC 15
+#define R4300i_SPECIAL_MFHI 16
+#define R4300i_SPECIAL_MTHI 17
+#define R4300i_SPECIAL_MFLO 18
+#define R4300i_SPECIAL_MTLO 19
+#define R4300i_SPECIAL_DSLLV 20
+#define R4300i_SPECIAL_DSRLV 22
+#define R4300i_SPECIAL_DSRAV 23
+#define R4300i_SPECIAL_MULT 24
+#define R4300i_SPECIAL_MULTU 25
+#define R4300i_SPECIAL_DIV 26
+#define R4300i_SPECIAL_DIVU 27
+#define R4300i_SPECIAL_DMULT 28
+#define R4300i_SPECIAL_DMULTU 29
+#define R4300i_SPECIAL_DDIV 30
+#define R4300i_SPECIAL_DDIVU 31
+#define R4300i_SPECIAL_ADD 32
+#define R4300i_SPECIAL_ADDU 33
+#define R4300i_SPECIAL_SUB 34
+#define R4300i_SPECIAL_SUBU 35
+#define R4300i_SPECIAL_AND 36
+#define R4300i_SPECIAL_OR 37
+#define R4300i_SPECIAL_XOR 38
+#define R4300i_SPECIAL_NOR 39
+#define R4300i_SPECIAL_SLT 42
+#define R4300i_SPECIAL_SLTU 43
+#define R4300i_SPECIAL_DADD 44
+#define R4300i_SPECIAL_DADDU 45
+#define R4300i_SPECIAL_DSUB 46
+#define R4300i_SPECIAL_DSUBU 47
+#define R4300i_SPECIAL_TGE 48
+#define R4300i_SPECIAL_TGEU 49
+#define R4300i_SPECIAL_TLT 50
+#define R4300i_SPECIAL_TLTU 51
+#define R4300i_SPECIAL_TEQ 52
+#define R4300i_SPECIAL_TNE 54
+#define R4300i_SPECIAL_DSLL 56
+#define R4300i_SPECIAL_DSRL 58
+#define R4300i_SPECIAL_DSRA 59
+#define R4300i_SPECIAL_DSLL32 60
+#define R4300i_SPECIAL_DSRL32 62
+#define R4300i_SPECIAL_DSRA32 63
+
+/* R4300i RegImm opcodes */
+#define R4300i_REGIMM_BLTZ 0
+#define R4300i_REGIMM_BGEZ 1
+#define R4300i_REGIMM_BLTZL 2
+#define R4300i_REGIMM_BGEZL 3
+#define R4300i_REGIMM_TGEI 0x08
+#define R4300i_REGIMM_TGEIU 0x09
+#define R4300i_REGIMM_TLTI 0x0A
+#define R4300i_REGIMM_TLTIU 0x0B
+#define R4300i_REGIMM_TEQI 0x0C
+#define R4300i_REGIMM_TNEI 0x0E
+#define R4300i_REGIMM_BLTZAL 0x10
+#define R4300i_REGIMM_BGEZAL 17
+#define R4300i_REGIMM_BLTZALL 0x12
+#define R4300i_REGIMM_BGEZALL 0x13
+
+/* R4300i COP0 opcodes */
+#define R4300i_COP0_MF 0
+#define R4300i_COP0_MT 4
+
+/* R4300i COP0 CO opcodes */
+#define R4300i_COP0_CO_TLBR 1
+#define R4300i_COP0_CO_TLBWI 2
+#define R4300i_COP0_CO_TLBWR 6
+#define R4300i_COP0_CO_TLBP 8
+#define R4300i_COP0_CO_ERET 24
+
+/* R4300i COP1 opcodes */
+#define R4300i_COP1_MF 0
+#define R4300i_COP1_DMF 1
+#define R4300i_COP1_CF 2
+#define R4300i_COP1_MT 4
+#define R4300i_COP1_DMT 5
+#define R4300i_COP1_CT 6
+#define R4300i_COP1_BC 8
+#define R4300i_COP1_S 16
+#define R4300i_COP1_D 17
+#define R4300i_COP1_W 20
+#define R4300i_COP1_L 21
+
+/* R4300i COP1 BC opcodes */
+#define R4300i_COP1_BC_BCF 0
+#define R4300i_COP1_BC_BCT 1
+#define R4300i_COP1_BC_BCFL 2
+#define R4300i_COP1_BC_BCTL 3
+
+#define R4300i_COP1_FUNCT_ADD 0
+#define R4300i_COP1_FUNCT_SUB 1
+#define R4300i_COP1_FUNCT_MUL 2
+#define R4300i_COP1_FUNCT_DIV 3
+#define R4300i_COP1_FUNCT_SQRT 4
+#define R4300i_COP1_FUNCT_ABS 5
+#define R4300i_COP1_FUNCT_MOV 6
+#define R4300i_COP1_FUNCT_NEG 7
+#define R4300i_COP1_FUNCT_ROUND_L 8
+#define R4300i_COP1_FUNCT_TRUNC_L 9
+#define R4300i_COP1_FUNCT_CEIL_L 10
+#define R4300i_COP1_FUNCT_FLOOR_L 11
+#define R4300i_COP1_FUNCT_ROUND_W 12
+#define R4300i_COP1_FUNCT_TRUNC_W 13
+#define R4300i_COP1_FUNCT_CEIL_W 14
+#define R4300i_COP1_FUNCT_FLOOR_W 15
+#define R4300i_COP1_FUNCT_CVT_S 32
+#define R4300i_COP1_FUNCT_CVT_D 33
+#define R4300i_COP1_FUNCT_CVT_W 36
+#define R4300i_COP1_FUNCT_CVT_L 37
+#define R4300i_COP1_FUNCT_C_F 48
+#define R4300i_COP1_FUNCT_C_UN 49
+#define R4300i_COP1_FUNCT_C_EQ 50
+#define R4300i_COP1_FUNCT_C_UEQ 51
+#define R4300i_COP1_FUNCT_C_OLT 52
+#define R4300i_COP1_FUNCT_C_ULT 53
+#define R4300i_COP1_FUNCT_C_OLE 54
+#define R4300i_COP1_FUNCT_C_ULE 55
+#define R4300i_COP1_FUNCT_C_SF 56
+#define R4300i_COP1_FUNCT_C_NGLE 57
+#define R4300i_COP1_FUNCT_C_SEQ 58
+#define R4300i_COP1_FUNCT_C_NGL 59
+#define R4300i_COP1_FUNCT_C_LT 60
+#define R4300i_COP1_FUNCT_C_NGE 61
+#define R4300i_COP1_FUNCT_C_LE 62
+#define R4300i_COP1_FUNCT_C_NGT 63
+
+#endif
+
+
diff --git a/src/usf/pif.c b/src/usf/pif.c new file mode 100644 index 0000000..1e43118 --- /dev/null +++ b/src/usf/pif.c @@ -0,0 +1,97 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+#include "main.h"
+#include "cpu.h"
+
+// Skeletal support so USFs that read the controller won't fail (bad practice, though)
+
+void ProcessControllerCommand ( int32_t Control, uint8_t * Command);
+
+uint8_t *PIF_Ram = 0;
+
+void PifRamRead (void) {
+ int32_t Channel, CurPos;
+
+ Channel = 0;
+ CurPos = 0;
+
+ do {
+ switch(PIF_Ram[CurPos]) {
+ case 0x00:
+ Channel += 1;
+ if (Channel > 6) { CurPos = 0x40; }
+ break;
+ case 0xFE: CurPos = 0x40; break;
+ case 0xFF: break;
+ case 0xB4: case 0x56: case 0xB8: break; /* ??? */
+ default:
+ if ((PIF_Ram[CurPos] & 0xC0) == 0) {
+ CurPos += PIF_Ram[CurPos] + (PIF_Ram[CurPos + 1] & 0x3F) + 1;
+ Channel += 1;
+ } else {
+ CurPos = 0x40;
+ }
+ break;
+ }
+ CurPos += 1;
+ } while( CurPos < 0x40 );
+}
+
+void PifRamWrite (void) {
+ int Channel, CurPos;
+
+ Channel = 0;
+
+ for (CurPos = 0; CurPos < 0x40; CurPos++){
+ switch(PIF_Ram[CurPos]) {
+ case 0x00:
+ Channel += 1;
+ if (Channel > 6) { CurPos = 0x40; }
+ break;
+ case 0xFE: CurPos = 0x40; break;
+ case 0xFF: break;
+ case 0xB4: case 0x56: case 0xB8: break; /* ??? */
+ default:
+ if ((PIF_Ram[CurPos] & 0xC0) == 0) {
+ if (Channel < 4) {
+ ProcessControllerCommand(Channel,&PIF_Ram[CurPos]);
+ }
+ CurPos += PIF_Ram[CurPos] + (PIF_Ram[CurPos + 1] & 0x3F) + 1;
+ Channel += 1;
+ } else
+ CurPos = 0x40;
+
+ break;
+ }
+ }
+ PIF_Ram[0x3F] = 0;
+}
+
+// always return failure
+void ProcessControllerCommand ( int32_t Control, uint8_t * Command) {
+ Command[1] |= 0x80;
+}
+
diff --git a/src/usf/pif.h b/src/usf/pif.h new file mode 100644 index 0000000..23082c1 --- /dev/null +++ b/src/usf/pif.h @@ -0,0 +1,31 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+extern uint8_t *PIF_Ram;
+
+int32_t GetCicChipID ( int8_t * RomData );
+int32_t LoadPifRom ( int32_t country );
+void PifRamWrite ( void );
+void PifRamRead ( void );
diff --git a/src/usf/psftag.c b/src/usf/psftag.c new file mode 100644 index 0000000..5665552 --- /dev/null +++ b/src/usf/psftag.c @@ -0,0 +1,528 @@ +
+/////////////////////////////////////////////////////////////////////////////
+//
+// tag handling
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "psftag.h"
+
+#if !defined(__WIN32__) && !defined(_MSC_VER)
+#include <unistd.h>
+#else
+#include <windows.h>
+static void truncate(const char *filename, int size) {
+
+ HANDLE f = CreateFile(
+ filename,
+ GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+ if(f == INVALID_HANDLE_VALUE) return;
+ SetFilePointer(f, size, NULL, FILE_BEGIN);
+ if(GetLastError() == NO_ERROR) SetEndOfFile(f);
+ CloseHandle(f);
+}
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+/*
+** Returns index, or -1 if not found
+** Returns the index starting at the first non-whitespace character of
+** the actual variable name
+*/
+static int find_tag_var_start(const char *tagbuffer, const char *varname) {
+ int i, j;
+ if(!tagbuffer || !varname) return -1;
+ for(i = 0;;) {
+ /*
+ ** Find first non-whitespace
+ ** (this is the variable name on the current line)
+ */
+ for(;; i++) {
+ unsigned u = ((unsigned)(tagbuffer[i])) & 0xFF;
+ /* If the tag ends here, we wouldn't have had any data anyway */
+ if(!u) return -1;
+ if(u <= 0x20) continue;
+ break;
+ }
+ /*
+ ** Compare case-insensitively to the var name
+ */
+ for(j = 0;; j++) {
+ unsigned ucmp = ((unsigned)(varname [ j])) & 0xFF;
+ unsigned u = ((unsigned)(tagbuffer[i + j])) & 0xFF;
+ /* if the varname ends, we'll break here and do the equals check */
+ if(!ucmp) break;
+ /* If the tag ends here, we wouldn't have had any data anyway */
+ if(!u) return -1;
+ /* lowercase */
+ if(ucmp >= 'A' && ucmp <= 'Z') { ucmp -= 'A'; ucmp += 'a'; }
+ if(u >= 'A' && u <= 'Z') { u -= 'A'; u += 'a'; }
+ /* if they're unequal, break... */
+ if(u != ucmp) break;
+ }
+ /*
+ ** Only if we exhausted the varname will we do the equals check
+ */
+ if(!varname[j]) {
+ /*
+ ** Ensure that the next non-whitespace character in [i+j] is an '='
+ */
+ for(;; j++) {
+ unsigned u = ((unsigned)(tagbuffer[i + j])) & 0xFF;
+ /* If the tag ends here, we wouldn't have had any data anyway */
+ if(!u) return -1;
+ /* quit at the first '=' - success! */
+ if(u == '=') return i;
+ /* shouldn't be a newline here! */
+ if(u == 0x0A) break;
+ /* ignore whitespace */
+ if(u <= 0x20) continue;
+ /* any other character is an error */
+ break;
+ }
+ }
+ i += j + 1;
+ /*
+ ** Find newline or end-of-tag
+ */
+ for(;; i++) {
+ unsigned u = ((unsigned)(tagbuffer[i])) & 0xFF;
+ /* If the tag ends here, we wouldn't have had any data anyway */
+ if(!u) return -1;
+ if(u == 0x0A) break;
+ }
+ }
+ return -1;
+}
+
+/*
+** Returns the index at which the current variable ends
+** (Includes any ending newline and possibly whitespace after that)
+**
+** Buffer points to the first non-whitespace character of the variable name
+*/
+static int find_tag_var_end(const char *tagbuffer) {
+ int i, j;
+ if(!tagbuffer) return 0;
+ for(i = 0;;) {
+ /*
+ ** Find first non-whitespace
+ ** (this is the variable name on the current line)
+ */
+ for(;; i++) {
+ unsigned u = ((unsigned)(tagbuffer[i])) & 0xFF;
+ if(!u) return i;
+ if(u <= 0x20) continue;
+ break;
+ }
+ /*
+ ** Compare case-insensitively to the original var name
+ */
+ for(j = 0;; j++) {
+ unsigned ucmp = ((unsigned)(tagbuffer[ j])) & 0xFF;
+ unsigned u = ((unsigned)(tagbuffer[i + j])) & 0xFF;
+ /* If the tag ends here, we wouldn't have had any data anyway */
+ if(!u) return i;
+ /* lowercase */
+ if(ucmp >= 'A' && ucmp <= 'Z') { ucmp -= 'A'; ucmp += 'a'; }
+ if(u >= 'A' && u <= 'Z') { u -= 'A'; u += 'a'; }
+ /* if they're both whitespace or '=', we win */
+ if((u <= 0x20 || u == '=') && (ucmp <= 0x20 || ucmp == '=')) break;
+ /* if they're unequal, we lose */
+ if(u != ucmp) return i;
+ /* otherwise, keep trying */
+ }
+ /*
+ ** Ensure that the next non-whitespace character in [i+j] is an '='
+ */
+ for(;; j++) {
+ unsigned u = ((unsigned)(tagbuffer[i + j])) & 0xFF;
+ if(!u) return i;
+ /* quit at the first '=' */
+ if(u == '=') break;
+ /* shouldn't be a newline here! */
+ if(u == 0x0A) return i;
+ /* ignore whitespace */
+ if(u <= 0x20) continue;
+ /* any other character is an error */
+ break;
+ }
+ i += j + 1;
+ /*
+ ** Find newline or end-of-tag
+ */
+ for(;; i++) {
+ unsigned u = ((unsigned)(tagbuffer[i])) & 0xFF;
+ if(!u) return i;
+ if(u == 0x0A) break;
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/*
+** Get tag variable
+** The destination value buffer must be as big as the entire tag
+*/
+int psftag_raw_getvar(
+ const char *tag,
+ const char *variable,
+ char *value_out,
+ int value_out_size
+) {
+ char *v = value_out;
+ char *vmax = v + value_out_size;
+ char *v_linebegin;
+ int i, i_end;
+ //
+ // Safety check
+ //
+ if(value_out_size < 1) return -1;
+ /*
+ ** Default to empty string
+ */
+ *v = 0;
+ /*
+ ** Find the variable start/end index
+ */
+ i = find_tag_var_start(tag, variable);
+ if(i < 0) return -1;
+ i_end = i + find_tag_var_end(tag + i);
+ /*
+ ** Extract the variable data
+ */
+ while(i < i_end) {
+ /*
+ ** Skip to first '='
+ */
+ while((tag[i] != '=') && (i < i_end)) { i++; }
+ if(i >= i_end) break;
+ /*
+ ** If this is not the first line, add a newline
+ */
+ if(v > value_out) {
+ if(v < vmax) { *v++ = 0x0A; }
+ }
+ /*
+ ** Now that we're at a '=', skip past it
+ */
+ i++;
+ if(i >= i_end) break;
+ /*
+ ** Skip past any whitespace except newlines
+ */
+ for(; i < i_end; i++) {
+ unsigned u = ((unsigned)(tag[i])) & 0xFF;
+ if(u == 0x0A) break;
+ if(u <= 0x20) continue;
+ break;
+ }
+ if(i >= i_end) break;
+ /*
+ ** Consume line data
+ */
+ v_linebegin = v;
+ while(i < i_end) {
+ unsigned u = ((unsigned)(tag[i++])) & 0xFF;
+ if(u == 0x0A) break;
+ if(v < vmax) { *v++ = u; }
+ }
+ /*
+ ** Eat end-of-line whitespace
+ */
+ while(v > v_linebegin && (((unsigned)(v[-1]))&0xFF) <= 0x20) {
+ v--;
+ }
+ }
+ /*
+ ** Set variable end
+ */
+ if(v >= vmax) { v = vmax - 1; }
+ *v = 0;
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void psftag_raw_setvar(
+ char *tag,
+ int tag_max_size,
+ const char *variable,
+ const char *value
+) {
+ int tag_l = strlen(tag);
+ int i, i_end, z;
+ int insert_i;
+ int insert_l;
+ int value_exists = 0;
+ int tag_max_usable_size = tag_max_size - 1;
+ //
+ // Safety check
+ //
+ if(tag_max_size < 1) return;
+ //
+ // We will assume we can at least use what's there
+ //
+ if(tag_max_usable_size < tag_l) {
+ tag_max_usable_size = tag_l;
+ tag_max_size = tag_l + 1;
+ }
+ /*
+ ** Determine the insertion length of the new variable
+ */
+ { const char *v;
+ int nl = strlen(variable);
+ insert_l = nl + 2;
+ for(v = value; *v; v++) {
+ insert_l++;
+ if(*v == 0x0A) {
+ /* Value exists if it's multi-line */
+ value_exists = 1;
+ insert_l += nl + 1;
+ } else if((((unsigned)(*v))&0xFF) > 0x20) {
+ /* Value exists if there are non-whitespace characters */
+ value_exists = 1;
+ }
+ }
+ }
+ /*
+ ** If the value is blank, force the insert length to zero
+ */
+ if(!value_exists) insert_l = 0;
+ /*
+ ** Find the variable start index
+ */
+ i = find_tag_var_start(tag, variable);
+ /*
+ ** If not found, add a new variable
+ */
+ if(i < 0) {
+ /* Insert position is at the end */
+ insert_i = tag_l;
+ /* Eat trailing whitespace in the file */
+ while(insert_i && (((unsigned)(tag[insert_i - 1]))&0xFF) <= 0x20) { insert_i--; }
+ /* Insert a newline if there's room and if there's stuff before */
+ if(insert_i && (insert_i < tag_max_usable_size)) { tag[insert_i++] = 0x0A; }
+ /* Clamp insert length */
+ if((insert_i + insert_l) > tag_max_usable_size) { insert_l = tag_max_usable_size - insert_i; }
+ z = insert_i + insert_l;
+ /*
+ ** Otherwise, find the variable end index
+ */
+ } else {
+ int movel;
+ insert_i = i;
+ /* Clamp insert length */
+ if((insert_i + insert_l) > tag_max_usable_size) { insert_l = tag_max_usable_size - insert_i; }
+ i_end = i + find_tag_var_end(tag + i);
+ /* Move remaining file data */
+ movel = tag_l - i_end;
+ if(movel > (tag_max_usable_size-(insert_i+insert_l))) { movel = tag_max_usable_size - (insert_i+insert_l); }
+ /* perform the move */
+ if(movel && ((insert_i+insert_l) != i_end)) {
+ memmove(tag+insert_i+insert_l, tag+i_end, movel);
+ }
+ z = insert_i+insert_l+movel;
+ }
+ /* Add terminating null ahead of time */
+ if(z > tag_max_usable_size) z = tag_max_usable_size;
+ tag[z] = 0;
+ /*
+ ** Write the variable to index insert_i, max length insert_l
+ */
+ insert_l += insert_i;
+ while(insert_i < insert_l) {
+ const char *v;
+ for(v = variable; (*v) && (insert_i < insert_l); v++) {
+ tag[insert_i++] = *v;
+ }
+ if(insert_i >= insert_l) break;
+ tag[insert_i++] = '=';
+ if(insert_i >= insert_l) break;
+ for(; (*value) && ((*value) != 0x0A) && (insert_i < insert_l); value++) {
+ tag[insert_i++] = *value;
+ }
+ if(insert_i >= insert_l) break;
+ tag[insert_i++] = 0x0A;
+ if(insert_i >= insert_l) break;
+ if(!(*value)) break;
+ if((*value) == 0x0A) value++;
+ }
+
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define TAGMAX (50000)
+#define ERRORMAX (256)
+
+struct PSFTAG {
+ char str[TAGMAX + 1];
+};
+
+/*void *psftag_create(void) {
+ struct PSFTAG *p = malloc(sizeof(struct PSFTAG));
+ if(!p) return NULL;
+ p->str[0] = 0;
+ //p->errorstring[0] = 0;
+ return p;
+}
+
+void psftag_delete(void *psftag) {
+ free(psftag);
+}*/
+
+/////////////////////////////////////////////////////////////////////////////
+
+/*const char *psftag_getlasterror(void *psftag) {
+ return ((struct PSFTAG*)psftag)->errorstring;
+}*/
+
+/////////////////////////////////////////////////////////////////////////////
+
+void psftag_getraw(void *psftag, char *raw_out, int raw_out_size) {
+ if(raw_out_size < 1) return;
+ strncpy(raw_out, ((struct PSFTAG*)psftag)->str, raw_out_size);
+ raw_out[raw_out_size - 1] = 0;
+}
+
+void psftag_setraw(void *psftag, const char *raw_in) {
+ strncpy(((struct PSFTAG*)psftag)->str, raw_in, TAGMAX + 1);
+ ((struct PSFTAG*)psftag)->str[TAGMAX] = 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+int psftag_getvar(void *psftag, const char *variable, char *value_out, int value_out_size) {
+ return psftag_raw_getvar(((struct PSFTAG*)psftag)->str, variable, value_out, value_out_size);
+}
+
+void psftag_setvar(void *psftag, const char *variable, const char *value) {
+ psftag_raw_setvar(((struct PSFTAG*)psftag)->str, TAGMAX + 1, variable, value);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+int psftag_readfromfile(void *psftag, const char *path) {
+ struct PSFTAG *t = (struct PSFTAG*)psftag;
+ FILE *f = NULL;
+ int l;
+ int rsize, exesize, tagstart;
+ char hdr[12];
+
+ f = fopen(path, "rb");
+ if(!f) {
+ //strncpy(t->errorstring, strerror(errno), ERRORMAX);
+ //t->errorstring[ERRORMAX-1] = 0;
+ return -1;
+ }
+
+ if(fread(hdr, 1, 12, f) != 12) goto invalidformat;
+ if(memcmp(hdr, "PSF", 3)) goto invalidformat;
+
+ rsize =
+ ((((unsigned)(hdr[ 4])) & 0xFF) << 0) |
+ ((((unsigned)(hdr[ 5])) & 0xFF) << 8) |
+ ((((unsigned)(hdr[ 6])) & 0xFF) << 16) |
+ ((((unsigned)(hdr[ 7])) & 0xFF) << 24);
+ exesize =
+ ((((unsigned)(hdr[ 8])) & 0xFF) << 0) |
+ ((((unsigned)(hdr[ 9])) & 0xFF) << 8) |
+ ((((unsigned)(hdr[10])) & 0xFF) << 16) |
+ ((((unsigned)(hdr[11])) & 0xFF) << 24);
+
+ tagstart = 16 + rsize + exesize;
+
+ fseek(f, tagstart, SEEK_SET);
+
+ if(fread(hdr, 1, 5, f) != 5) goto notpresent;
+ if(memcmp(hdr, "[TAG]", 5)) goto invalidformat;
+
+ tagstart += 5;
+ fseek(f, 0, SEEK_END);
+ l = ftell(f);
+ fseek(f, tagstart, SEEK_SET);
+ l -= tagstart;
+ if(l < 0) l = 0;
+ if(l > TAGMAX) l = TAGMAX;
+
+ memset(t->str, 0, TAGMAX + 1);
+ fread(t->str, 1, l, f);
+
+ fclose(f);
+ return 0;
+
+invalidformat:
+// strcpy(t->errorstring, "Invalid file format");
+ goto error;
+notpresent:
+// strcpy(t->errorstring, "Tag not present");
+ goto error;
+error:
+ if(f) fclose(f);
+ return -1;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+int psftag_writetofile(void *psftag, const char *path) {
+ struct PSFTAG *t = (struct PSFTAG*)psftag;
+ FILE *f = NULL;
+ int l;
+ int rsize, exesize, tagstart;
+ char hdr[12];
+
+ f = fopen(path, "r+b");
+ if(!f) {
+ //strncpy(t->errorstring, strerror(errno), ERRORMAX);
+ //t->errorstring[ERRORMAX-1] = 0;
+ return -1;
+ }
+
+ if(fread(hdr, 1, 12, f) != 12) goto invalidformat;
+ if(memcmp(hdr, "PSF", 3)) goto invalidformat;
+
+ rsize =
+ ((((unsigned)(hdr[ 4])) & 0xFF) << 0) |
+ ((((unsigned)(hdr[ 5])) & 0xFF) << 8) |
+ ((((unsigned)(hdr[ 6])) & 0xFF) << 16) |
+ ((((unsigned)(hdr[ 7])) & 0xFF) << 24);
+ exesize =
+ ((((unsigned)(hdr[ 8])) & 0xFF) << 0) |
+ ((((unsigned)(hdr[ 9])) & 0xFF) << 8) |
+ ((((unsigned)(hdr[10])) & 0xFF) << 16) |
+ ((((unsigned)(hdr[11])) & 0xFF) << 24);
+
+ tagstart = 16 + rsize + exesize;
+
+ fseek(f, tagstart, SEEK_SET);
+
+ l = strlen(t->str);
+
+ fwrite("[TAG]", 1, 5, f);
+ fwrite(t->str, 1, l, f);
+ fclose(f);
+
+ truncate(path, tagstart + 5 + l);
+
+ return 0;
+
+invalidformat:
+// strcpy(t->errorstring, "Invalid file format");
+ goto error;
+error:
+ if(f) fclose(f);
+ return -1;
+}
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/src/usf/psftag.h b/src/usf/psftag.h new file mode 100644 index 0000000..7fbee5f --- /dev/null +++ b/src/usf/psftag.h @@ -0,0 +1,57 @@ +/////////////////////////////////////////////////////////////////////////////
+//
+// tag handling
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __PSF_PSFTAG_H__
+#define __PSF_PSFTAG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void *psftag_create(void);
+void psftag_delete(void *psftag);
+
+int psftag_readfromfile(void *psftag, const char *path);
+int psftag_writetofile(void *psftag, const char *path);
+const char *psftag_getlasterror(void *psftag);
+
+//
+// Retrieve a tag variable.
+// Guarantees null termination of output.
+// Returns 0 if the variable was found
+// Otherwise, returns -1 and sets the output to an empty terminated string
+//
+int psftag_getvar(void *psftag, const char *variable, char *value_out, int value_out_size);
+
+//
+// Set a tag variable.
+//
+void psftag_setvar(void *psftag, const char *variable, const char *value);
+
+void psftag_getraw(void *psftag, char *raw_out, int raw_out_size);
+void psftag_setraw(void *psftag, const char *raw_in);
+
+//
+// Retrieve a tag variable. The input tag data must be null-terminated.
+// Guarantees null termination of output.
+// Returns 0 if the variable was found
+// Otherwise, returns -1 and sets the output to an empty terminated string
+//
+int psftag_raw_getvar(const char *tag, const char *variable, char *value_out, int value_out_size);
+
+//
+// Set a tag variable.
+// Provide the maximum growable tag size _including_ space for the null terminator.
+// Note that this function assumes it can overwrite *tag up to the length of the
+// existing string, regardless of tag_max_size.
+//
+void psftag_raw_setvar(char *tag, int tag_max_size, const char *variable, const char *value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/usf/recompiler_cpu.c b/src/usf/recompiler_cpu.c new file mode 100644 index 0000000..7a86b94 --- /dev/null +++ b/src/usf/recompiler_cpu.c @@ -0,0 +1,2780 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include "main.h"
+#include "cpu.h"
+#include "x86.h"
+#include "usf.h"
+#include "types.h"
+
+
+void CreateSectionLinkage (BLOCK_SECTION * Section);
+void DetermineLoop(BLOCK_SECTION * Section, uint32_t Test, uint32_t Test2, uint32_t TestID);
+uint32_t DisplaySectionInformation (BLOCK_SECTION * Section, uint32_t ID, uint32_t Test);
+BLOCK_SECTION * ExistingSection(BLOCK_SECTION * StartSection, uint32_t Addr, uint32_t Test);
+void FillSectionInfo(BLOCK_SECTION * Section);
+void FixConstants ( BLOCK_SECTION * Section, uint32_t Test,int * Changed );
+uint32_t GenerateX86Code (BLOCK_SECTION * Section, uint32_t Test );
+uint32_t GetNewTestValue( void );
+void InheritConstants(BLOCK_SECTION * Section);
+uint32_t InheritParentInfo (BLOCK_SECTION * Section);
+void InitilzeSection(BLOCK_SECTION * Section, BLOCK_SECTION * Parent, uint32_t StartAddr, uint32_t ID);
+void InitilizeRegSet(REG_INFO * RegSet);
+uint32_t IsAllParentLoops(BLOCK_SECTION * Section, BLOCK_SECTION * Parent, uint32_t IgnoreIfCompiled, uint32_t Test);
+void MarkCodeBlock (uint32_t PAddr);
+void SyncRegState (BLOCK_SECTION * Section, REG_INFO * SyncTo);
+
+N64_Blocks_t N64_Blocks;
+uint32_t * TLBLoadAddress = 0, TargetIndex;
+TARGET_INFO * TargetInfo = NULL;
+BLOCK_INFO BlockInfo;
+
+void InitilizeInitialCompilerVariable ( void)
+{
+ memset(&BlockInfo,0,sizeof(BlockInfo));
+}
+
+void AddParent(BLOCK_SECTION * Section, BLOCK_SECTION * Parent){
+ int NoOfParents, count;
+
+
+ if (Section == NULL) { return; }
+ if (Parent == NULL) {
+ InitilizeRegSet(&Section->RegStart);
+ memcpy(&Section->RegWorking,&Section->RegStart,sizeof(REG_INFO));
+ return;
+ }
+
+ if (Section->ParentSection != NULL) {
+ for (NoOfParents = 0;Section->ParentSection[NoOfParents] != NULL;NoOfParents++) {
+ if (Section->ParentSection[NoOfParents] == Parent) {
+ return;
+ }
+ }
+ for (NoOfParents = 0;Section->ParentSection[NoOfParents] != NULL;NoOfParents++);
+ NoOfParents += 1;
+ } else {
+ NoOfParents = 1;
+ }
+
+ if (NoOfParents == 1) {
+ Section->ParentSection = malloc((NoOfParents + 1)*sizeof(void *));
+ } else {
+ Section->ParentSection = realloc(Section->ParentSection,(NoOfParents + 1)*sizeof(void *));
+ }
+ Section->ParentSection[NoOfParents - 1] = Parent;
+ Section->ParentSection[NoOfParents] = NULL;
+
+ if (NoOfParents == 1) {
+ if (Parent->ContinueSection == Section) {
+ memcpy(&Section->RegStart,&Parent->Cont.RegSet,sizeof(REG_INFO));
+ } else if (Parent->JumpSection == Section) {
+ memcpy(&Section->RegStart,&Parent->Jump.RegSet,sizeof(REG_INFO));
+ } else {
+ }
+ memcpy(&Section->RegWorking,&Section->RegStart,sizeof(REG_INFO));
+ } else {
+ if (Parent->ContinueSection == Section) {
+ for (count = 0; count < 32; count++) {
+ if (Section->RegStart.MIPS_RegState[count] != Parent->Cont.RegSet.MIPS_RegState[count]) {
+ Section->RegStart.MIPS_RegState[count] = STATE_UNKNOWN;
+ }
+ }
+ }
+ if (Parent->JumpSection == Section) {
+ for (count = 0; count < 32; count++) {
+ if (Section->RegStart.MIPS_RegState[count] != Parent->Jump.RegSet.MIPS_RegState[count]) {
+ Section->RegStart.MIPS_RegState[count] = STATE_UNKNOWN;
+ }
+ }
+ }
+ memcpy(&Section->RegWorking,&Section->RegStart,sizeof(REG_INFO));
+ }
+}
+
+void AnalyseBlock (void) {
+ int Changed;
+
+ BLOCK_SECTION * Section = &BlockInfo.BlockInfo;
+
+ BlockInfo.NoOfSections = 1;
+ InitilzeSection (Section, NULL, BlockInfo.StartVAddr, BlockInfo.NoOfSections);
+ CreateSectionLinkage (Section);
+ DetermineLoop(Section,GetNewTestValue(),GetNewTestValue(), Section->SectionID);
+ do {
+ Changed = 0;
+ FixConstants(Section,GetNewTestValue(),&Changed);
+ } while (Changed == 1);
+
+}
+
+int ConstantsType (int64_t Value) {
+ if (((Value >> 32) == -1) && ((Value & 0x80000000) != 0)) { return STATE_CONST_32; }
+ if (((Value >> 32) == 0) && ((Value & 0x80000000) == 0)) { return STATE_CONST_32; }
+ return STATE_CONST_64;
+}
+
+
+uint8_t * Compiler4300iBlock(void) {
+ uintptr_t StartAddress;
+ int count;
+
+ //reset BlockInfo
+ if (BlockInfo.ExitInfo)
+ {
+ for (count = 0; count < BlockInfo.ExitCount; count ++) {
+ free(BlockInfo.ExitInfo[count]);
+ BlockInfo.ExitInfo[count] = NULL;
+ }
+ if (BlockInfo.ExitInfo) { free(BlockInfo.ExitInfo); }
+ BlockInfo.ExitInfo = NULL;
+ }
+
+ memset(&BlockInfo,0,sizeof(BlockInfo));
+ BlockInfo.CompiledLocation = RecompPos;
+ BlockInfo.StartVAddr = PROGRAM_COUNTER;
+
+ AnalyseBlock();
+
+ StartAddress = BlockInfo.StartVAddr;
+ TranslateVaddr(&StartAddress);
+
+ //BreakPoint();
+ //MoveConstQwordToX86reg(Registers, x64_R14);
+
+ MarkCodeBlock(StartAddress);
+
+ while (GenerateX86Code(&BlockInfo.BlockInfo,GetNewTestValue()));
+ for (count = 0; count < BlockInfo.ExitCount; count ++) {
+ SetJump32(BlockInfo.ExitInfo[count]->JumpLoc,RecompPos);
+ NextInstruction = BlockInfo.ExitInfo[count]->NextInstruction;
+ CompileExit(BlockInfo.ExitInfo[count]->TargetPC,&BlockInfo.ExitInfo[count]->ExitRegSet,
+ BlockInfo.ExitInfo[count]->reason,1,NULL);
+ }
+ FreeSection (BlockInfo.BlockInfo.ContinueSection,&BlockInfo.BlockInfo);
+ FreeSection (BlockInfo.BlockInfo.JumpSection,&BlockInfo.BlockInfo);
+ for (count = 0; count < BlockInfo.ExitCount; count ++) {
+ free(BlockInfo.ExitInfo[count]);
+ BlockInfo.ExitInfo[count] = NULL;
+ }
+ if (BlockInfo.ExitInfo) { free(BlockInfo.ExitInfo); }
+ BlockInfo.ExitInfo = NULL;
+ BlockInfo.ExitCount = 0;
+
+ return BlockInfo.CompiledLocation;
+}
+
+
+uint8_t * CompileDelaySlot(void) {
+ uintptr_t StartAddress = PROGRAM_COUNTER;
+ BLOCK_SECTION *Section, DelaySection;
+ uint8_t * Block = RecompPos;
+ int count, x86Reg;
+
+ Section = &DelaySection;
+
+ if ((StartAddress & 0xFFC) != 0) {
+ StopEmulation();
+ }
+ if (!r4300i_LW_VAddr(StartAddress, &Opcode.Hex)) {
+ StopEmulation();
+ }
+
+ TranslateVaddr(&StartAddress);
+
+ MarkCodeBlock(StartAddress);
+
+ InitilzeSection (Section, NULL, PROGRAM_COUNTER, 0);
+ InitilizeRegSet(&Section->RegStart);
+ memcpy(&Section->RegWorking,&Section->RegStart,sizeof(REG_INFO));
+
+ BlockCycleCount += 2;
+ BlockRandomModifier += 1;
+
+ switch (Opcode.op) {
+ case R4300i_SPECIAL:
+ switch (Opcode.funct) {
+ case R4300i_SPECIAL_BREAK: Compile_R4300i_SPECIAL_BREAK(Section); break;
+ case R4300i_SPECIAL_SLL: Compile_R4300i_SPECIAL_SLL(Section); break;
+ case R4300i_SPECIAL_SRL: Compile_R4300i_SPECIAL_SRL(Section); break;
+ case R4300i_SPECIAL_SRA: Compile_R4300i_SPECIAL_SRA(Section); break;
+ case R4300i_SPECIAL_SLLV: Compile_R4300i_SPECIAL_SLLV(Section); break;
+ case R4300i_SPECIAL_SRLV: Compile_R4300i_SPECIAL_SRLV(Section); break;
+ case R4300i_SPECIAL_SRAV: Compile_R4300i_SPECIAL_SRAV(Section); break;
+ case R4300i_SPECIAL_MFLO: Compile_R4300i_SPECIAL_MFLO(Section); break;
+ case R4300i_SPECIAL_MTLO: Compile_R4300i_SPECIAL_MTLO(Section); break;
+ case R4300i_SPECIAL_MFHI: Compile_R4300i_SPECIAL_MFHI(Section); break;
+ case R4300i_SPECIAL_MTHI: Compile_R4300i_SPECIAL_MTHI(Section); break;
+ case R4300i_SPECIAL_MULT: Compile_R4300i_SPECIAL_MULT(Section); break;
+ case R4300i_SPECIAL_DIV: Compile_R4300i_SPECIAL_DIV(Section); break;
+ case R4300i_SPECIAL_DIVU: Compile_R4300i_SPECIAL_DIVU(Section); break;
+ case R4300i_SPECIAL_MULTU: Compile_R4300i_SPECIAL_MULTU(Section); break;
+ case R4300i_SPECIAL_DMULTU: Compile_R4300i_SPECIAL_DMULTU(Section); break;
+ case R4300i_SPECIAL_DDIVU: Compile_R4300i_SPECIAL_DDIVU(Section); break;
+ case R4300i_SPECIAL_ADD: Compile_R4300i_SPECIAL_ADD(Section); break;
+ case R4300i_SPECIAL_ADDU: Compile_R4300i_SPECIAL_ADDU(Section); break;
+ case R4300i_SPECIAL_SUB: Compile_R4300i_SPECIAL_SUB(Section); break;
+ case R4300i_SPECIAL_SUBU: Compile_R4300i_SPECIAL_SUBU(Section); break;
+ case R4300i_SPECIAL_AND: Compile_R4300i_SPECIAL_AND(Section); break;
+ case R4300i_SPECIAL_OR: Compile_R4300i_SPECIAL_OR(Section); break;
+ case R4300i_SPECIAL_XOR: Compile_R4300i_SPECIAL_XOR(Section); break;
+ case R4300i_SPECIAL_SLT: Compile_R4300i_SPECIAL_SLT(Section); break;
+ case R4300i_SPECIAL_SLTU: Compile_R4300i_SPECIAL_SLTU(Section); break;
+ case R4300i_SPECIAL_DADD: Compile_R4300i_SPECIAL_DADD(Section); break;
+ case R4300i_SPECIAL_DADDU: Compile_R4300i_SPECIAL_DADDU(Section); break;
+ case R4300i_SPECIAL_DSLL32: Compile_R4300i_SPECIAL_DSLL32(Section); break;
+ case R4300i_SPECIAL_DSRA32: Compile_R4300i_SPECIAL_DSRA32(Section); break;
+ default:
+ Compile_R4300i_UnknownOpcode(Section); break;
+ }
+ break;
+ case R4300i_ADDI: Compile_R4300i_ADDI(Section); break;
+ case R4300i_ADDIU: Compile_R4300i_ADDIU(Section); break;
+ case R4300i_SLTI: Compile_R4300i_SLTI(Section); break;
+ case R4300i_SLTIU: Compile_R4300i_SLTIU(Section); break;
+ case R4300i_ANDI: Compile_R4300i_ANDI(Section); break;
+ case R4300i_ORI: Compile_R4300i_ORI(Section); break;
+ case R4300i_XORI: Compile_R4300i_XORI(Section); break;
+ case R4300i_LUI: Compile_R4300i_LUI(Section); break;
+ case R4300i_CP1:
+ switch (Opcode.rs) {
+ case R4300i_COP1_CF: Compile_R4300i_COP1_CF(Section); break;
+ case R4300i_COP1_MT: Compile_R4300i_COP1_MT(Section); break;
+ case R4300i_COP1_CT: Compile_R4300i_COP1_CT(Section); break;
+ case R4300i_COP1_MF: Compile_R4300i_COP1_MF(Section); break;
+ case R4300i_COP1_S:
+ switch (Opcode.funct) {
+ case R4300i_COP1_FUNCT_ADD: Compile_R4300i_COP1_S_ADD(Section); break;
+ case R4300i_COP1_FUNCT_SUB: Compile_R4300i_COP1_S_SUB(Section); break;
+ case R4300i_COP1_FUNCT_MUL: Compile_R4300i_COP1_S_MUL(Section); break;
+ case R4300i_COP1_FUNCT_DIV: Compile_R4300i_COP1_S_DIV(Section); break;
+ case R4300i_COP1_FUNCT_ABS: Compile_R4300i_COP1_S_ABS(Section); break;
+ case R4300i_COP1_FUNCT_NEG: Compile_R4300i_COP1_S_NEG(Section); break;
+ case R4300i_COP1_FUNCT_SQRT: Compile_R4300i_COP1_S_SQRT(Section); break;
+ case R4300i_COP1_FUNCT_MOV: Compile_R4300i_COP1_S_MOV(Section); break;
+ case R4300i_COP1_FUNCT_CVT_D: Compile_R4300i_COP1_S_CVT_D(Section); break;
+ case R4300i_COP1_FUNCT_ROUND_W: Compile_R4300i_COP1_S_ROUND_W(Section); break;
+ case R4300i_COP1_FUNCT_TRUNC_W: Compile_R4300i_COP1_S_TRUNC_W(Section); break;
+ case R4300i_COP1_FUNCT_FLOOR_W: Compile_R4300i_COP1_S_FLOOR_W(Section); break;
+ case R4300i_COP1_FUNCT_C_F: case R4300i_COP1_FUNCT_C_UN:
+ case R4300i_COP1_FUNCT_C_EQ: case R4300i_COP1_FUNCT_C_UEQ:
+ case R4300i_COP1_FUNCT_C_OLT: case R4300i_COP1_FUNCT_C_ULT:
+ case R4300i_COP1_FUNCT_C_OLE: case R4300i_COP1_FUNCT_C_ULE:
+ case R4300i_COP1_FUNCT_C_SF: case R4300i_COP1_FUNCT_C_NGLE:
+ case R4300i_COP1_FUNCT_C_SEQ: case R4300i_COP1_FUNCT_C_NGL:
+ case R4300i_COP1_FUNCT_C_LT: case R4300i_COP1_FUNCT_C_NGE:
+ case R4300i_COP1_FUNCT_C_LE: case R4300i_COP1_FUNCT_C_NGT:
+ Compile_R4300i_COP1_S_CMP(Section); break;
+ default:
+ Compile_R4300i_UnknownOpcode(Section); break;
+ }
+ break;
+ case R4300i_COP1_D:
+ switch (Opcode.funct) {
+ case R4300i_COP1_FUNCT_ADD: Compile_R4300i_COP1_D_ADD(Section); break;
+ case R4300i_COP1_FUNCT_SUB: Compile_R4300i_COP1_D_SUB(Section); break;
+ case R4300i_COP1_FUNCT_MUL: Compile_R4300i_COP1_D_MUL(Section); break;
+ case R4300i_COP1_FUNCT_DIV: Compile_R4300i_COP1_D_DIV(Section); break;
+ case R4300i_COP1_FUNCT_ABS: Compile_R4300i_COP1_D_ABS(Section); break;
+ case R4300i_COP1_FUNCT_NEG: Compile_R4300i_COP1_D_NEG(Section); break;
+ case R4300i_COP1_FUNCT_SQRT: Compile_R4300i_COP1_D_SQRT(Section); break;
+ case R4300i_COP1_FUNCT_MOV: Compile_R4300i_COP1_D_MOV(Section); break;
+ case R4300i_COP1_FUNCT_TRUNC_W: Compile_R4300i_COP1_D_TRUNC_W(Section); break;
+ case R4300i_COP1_FUNCT_CVT_S: Compile_R4300i_COP1_D_CVT_S(Section); break;
+ case R4300i_COP1_FUNCT_CVT_W: Compile_R4300i_COP1_D_CVT_W(Section); break;
+ case R4300i_COP1_FUNCT_C_F: case R4300i_COP1_FUNCT_C_UN:
+ case R4300i_COP1_FUNCT_C_EQ: case R4300i_COP1_FUNCT_C_UEQ:
+ case R4300i_COP1_FUNCT_C_OLT: case R4300i_COP1_FUNCT_C_ULT:
+ case R4300i_COP1_FUNCT_C_OLE: case R4300i_COP1_FUNCT_C_ULE:
+ case R4300i_COP1_FUNCT_C_SF: case R4300i_COP1_FUNCT_C_NGLE:
+ case R4300i_COP1_FUNCT_C_SEQ: case R4300i_COP1_FUNCT_C_NGL:
+ case R4300i_COP1_FUNCT_C_LT: case R4300i_COP1_FUNCT_C_NGE:
+ case R4300i_COP1_FUNCT_C_LE: case R4300i_COP1_FUNCT_C_NGT:
+ Compile_R4300i_COP1_D_CMP(Section); break;
+ default:
+ Compile_R4300i_UnknownOpcode(Section); break;
+ }
+ break;
+ case R4300i_COP1_W:
+ switch (Opcode.funct) {
+ case R4300i_COP1_FUNCT_CVT_S: Compile_R4300i_COP1_W_CVT_S(Section); break;
+ case R4300i_COP1_FUNCT_CVT_D: Compile_R4300i_COP1_W_CVT_D(Section); break;
+ default:
+ Compile_R4300i_UnknownOpcode(Section); break;
+ }
+ break;
+ default:
+ Compile_R4300i_UnknownOpcode(Section); break;
+ }
+ break;
+ case R4300i_LB: Compile_R4300i_LB(Section); break;
+ case R4300i_LH: Compile_R4300i_LH(Section); break;
+ case R4300i_LW: Compile_R4300i_LW(Section); break;
+ case R4300i_LBU: Compile_R4300i_LBU(Section); break;
+ case R4300i_LHU: Compile_R4300i_LHU(Section); break;
+ case R4300i_SB: Compile_R4300i_SB(Section); break;
+ case R4300i_SH: Compile_R4300i_SH(Section); break;
+ case R4300i_SW: Compile_R4300i_SW(Section); break;
+ case R4300i_SWR: Compile_R4300i_SWR(Section); break;
+ case R4300i_CACHE: Compile_R4300i_CACHE(Section); break;
+ case R4300i_LWC1: Compile_R4300i_LWC1(Section); break;
+ case R4300i_LDC1: Compile_R4300i_LDC1(Section); break;
+ case R4300i_LD: Compile_R4300i_LD(Section); break;
+ case R4300i_SWC1: Compile_R4300i_SWC1(Section); break;
+ case R4300i_SDC1: Compile_R4300i_SDC1(Section); break;
+ case R4300i_SD: Compile_R4300i_SD(Section); break;
+ default:
+ Compile_R4300i_UnknownOpcode(Section); break;
+ }
+
+ for (count = 1; count < 64; count ++) { x86Protected(count) = 0; }
+
+ WriteBackRegisters(Section);
+ if (BlockCycleCount != 0) {
+ AddConstToVariable(BlockCycleCount,&CP0[9]);
+ SubConstFromVariable(BlockCycleCount,&Timers->Timer);
+ }
+ if (BlockRandomModifier != 0) { SubConstFromVariable(BlockRandomModifier,&CP0[1]); }
+ x86Reg = Map_TempReg(Section,x86_Any,-1,0);
+ MoveVariableToX86reg(&JumpToLocation,x86Reg);
+ MoveX86regToVariable(x86Reg,&PROGRAM_COUNTER);
+ MoveConstToVariable(NORMAL,&NextInstruction);
+ Ret();
+ return Block;
+}
+
+void CompileExit (uint32_t TargetPC, REG_INFO * ExitRegSet, int reason, int CompileNow, void (*x86Jmp)(uintptr_t Value)) {
+ BLOCK_SECTION Section;
+ uint8_t * Jump, * Jump2;
+
+ if (!CompileNow) {
+ if (BlockInfo.ExitCount == 0) {
+ BlockInfo.ExitInfo = malloc(sizeof(void *));
+ } else {
+ BlockInfo.ExitInfo = realloc(BlockInfo.ExitInfo,(BlockInfo.ExitCount + 1) * sizeof(void *));
+ }
+ if (x86Jmp == NULL) {
+ StopEmulation();
+ }
+ x86Jmp(0);
+ BlockInfo.ExitInfo[BlockInfo.ExitCount] = malloc(sizeof(EXIT_INFO));
+ BlockInfo.ExitInfo[BlockInfo.ExitCount]->TargetPC = TargetPC;
+ BlockInfo.ExitInfo[BlockInfo.ExitCount]->ExitRegSet = *ExitRegSet;
+ BlockInfo.ExitInfo[BlockInfo.ExitCount]->reason = reason;
+ BlockInfo.ExitInfo[BlockInfo.ExitCount]->NextInstruction = NextInstruction;
+ BlockInfo.ExitInfo[BlockInfo.ExitCount]->JumpLoc = RecompPos - 4;
+ BlockInfo.ExitCount += 1;
+ return;
+ }
+
+ InitilzeSection (&Section, NULL, (uint32_t)-1, 0);
+ memcpy(&Section.RegWorking, ExitRegSet, sizeof(REG_INFO));
+
+
+ //if(TargetPC > 0x90000000)
+ //BreakPoint();
+
+ if (TargetPC != (uint32_t)-1) { MoveConstToVariable(TargetPC,&PROGRAM_COUNTER); }
+ if (ExitRegSet->CycleCount != 0) {
+ AddConstToVariable(ExitRegSet->CycleCount,&CP0[9]);
+ SubConstFromVariable(ExitRegSet->CycleCount,&Timers->Timer);
+ }
+ if (ExitRegSet->RandomModifier != 0) { SubConstFromVariable(ExitRegSet->RandomModifier,&CP0[1]); }
+ WriteBackRegisters(&Section);
+
+ switch (reason) {
+ case Normal: case Normal_NoSysCheck:
+ Section.RegWorking.RandomModifier = 0;
+ Section.RegWorking.CycleCount = 0;
+ if (reason == Normal) { CompileSystemCheck(0,(uint32_t)-1,Section.RegWorking); }
+
+ if (TargetPC >= 0x80000000 && TargetPC < 0x90000000) {
+ uint32_t pAddr = TargetPC & 0x1FFFFFFF;
+ MoveConstToX86reg(pAddr,x86_ECX);
+ ShiftRightDoubleImmed(x86_ECX,x86_ECX,2);
+#ifdef USEX64
+ MoveVariableDispToX86Reg(JumpTable,x86_RCX,x86_RCX,8);
+#else
+ MoveVariableDispToX86Reg(JumpTable,x86_ECX,x86_ECX,4);
+#endif
+ Jump2 = NULL;
+ } else if (TargetPC >= 0x90000000 && TargetPC < 0xC0000000) {
+ } else {
+#ifdef USEX64
+ MoveConstToX86reg((TargetPC >> 12),x86_RCX);
+ MoveConstToX86reg(TargetPC,x86_EBX);
+ //MoveVariableDispToX86Reg(TLB_Map,x86_RCX,x86_RCX,8);
+ MoveX86RegDispToX86Reg(x86_RCX, x86_R15, x86_RCX, 8);
+ TestX86RegToX86Reg(x86_RCX,x86_RCX);
+ JeLabel8(0);
+ Jump2 = RecompPos - 1;
+ AddX86RegToX86Reg(x86_RCX,x86_EBX);
+ MoveConstQwordToX86reg((uintptr_t)N64MEM, x86_RBX);
+ SubX86RegToX86Reg(x86_RCX,x86_RBX);
+ ShiftRightDoubleImmed(x86_RCX,x86_RCX,2);
+ ShiftLeftDoubleImmed(x86_RCX,x86_RCX,3);
+ MoveConstQwordToX86reg((uintptr_t)JumpTable, x86_RBX);
+ AddX86RegToX86Reg(x86_RCX,x86_RBX);
+ MoveX86PointerToX86reg(x86_RCX,x86_RCX);
+#else
+ MoveConstToX86reg((TargetPC >> 12),x86_ECX);
+ MoveConstToX86reg(TargetPC,x86_EBX);
+ MoveVariableDispToX86Reg(TLB_Map,x86_ECX,x86_ECX,4);
+ TestX86RegToX86Reg(x86_ECX,x86_ECX);
+ JeLabel8(0);
+ Jump2 = RecompPos - 1;
+ AddConstToX86Reg(x86_ECX,(int32_t)JumpTable - (int32_t)N64MEM);
+ MoveX86regPointerToX86reg(x86_ECX, x86_EBX,x86_ECX);
+#endif
+ }
+ if (TargetPC < 0x90000000 || TargetPC >= 0xC0000000)
+ {
+ JecxzLabel8(0);
+ Jump = RecompPos - 1;
+ // printf("TargetPC %08x\n", TargetPC);
+
+
+ JmpDirectReg(x86_ECX);
+ *((uint8_t *)(Jump))=(uint8_t)(RecompPos - Jump - 1);
+ if (Jump2 != NULL) {
+ *((uint8_t *)(Jump2))=(uint8_t)(RecompPos - Jump2 - 1);
+ }
+ }
+
+ Ret();
+ break;
+ case DoCPU_Action:
+ Pushad();
+ //BreakPoint();
+ Call_Direct(DoSomething);
+ //RecompileDoSomething();
+ Popad();
+ Ret();
+ break;
+ case DoBreak:
+ Ret();
+ break;
+ case DoSysCall:
+ MoveConstToX86reg(NextInstruction == JUMP || NextInstruction == DELAY_SLOT,x86_EDI);
+ printf("extinjg 1\n");
+ exit(0);
+ Pushad();
+ Call_Direct(DoSysCallException);
+ Popad();
+ Ret();
+ break;
+ case COP1_Unuseable:
+ Pushad();
+ MoveConstToX86reg(NextInstruction == JUMP || NextInstruction == DELAY_SLOT,x86_EDI);
+ MoveConstToX86reg(1,x86_ESI);
+ Call_Direct(DoCopUnusableException);
+ Popad();
+ Ret();
+ break;
+ case ExitResetRecompCode:
+ if (NextInstruction == JUMP || NextInstruction == DELAY_SLOT) {
+ BreakPoint();
+ }
+ Pushad();
+ BreakPoint();
+ Call_Direct(ResetRecompCode);
+ Popad();
+ Ret();
+ break;
+ case TLBReadMiss:
+ MoveConstToX86reg(NextInstruction == JUMP || NextInstruction == DELAY_SLOT,x86_EDI);
+ MoveVariableToX86reg(TLBLoadAddress,x86_ESI);
+ Pushad();
+#ifdef USEX64
+ Call_Direct(DoTLBMiss);
+#else
+ Push(x86_EDX);
+ Push(x86_ECX);
+ Call_Direct(DoTLBMiss);
+ AddConstToX86Reg(x86_ESP, 0x8);
+#endif
+ Popad();
+ Ret();
+ break;
+ }
+}
+
+void CompileSystemCheck (uint32_t TimerModifier, uint32_t TargetPC, REG_INFO RegSet) {
+ BLOCK_SECTION Section;
+ uint8_t *Jump, *Jump2;
+
+ CompConstToVariable(0,WaitMode);
+ JeLabel8(0);
+ Jump = RecompPos - 1;
+ MoveConstToVariable(-1, &Timers->Timer);
+
+ SetJump8(Jump, RecompPos);
+
+ // Timer
+ if (TimerModifier != 0) {
+ SubConstFromVariable(TimerModifier,&Timers->Timer);
+ } else {
+ CompConstToVariable(0,&Timers->Timer);
+ }
+ JnsLabel32(0);
+ Jump = RecompPos - 4;
+ Pushad();
+ if (TargetPC != (uint32_t)-1) { MoveConstToVariable(TargetPC,&PROGRAM_COUNTER); }
+ InitilzeSection (&Section, NULL, (uint32_t)-1, 0);
+ memcpy(&Section.RegWorking, &RegSet, sizeof(REG_INFO));
+ WriteBackRegisters(&Section);
+ Call_Direct(TimerDone);
+ //Call_Direct(RecompileTimerDone);
+ //RecompileTimerDone();
+ //RecompileTimerDone();
+
+ Popad();
+
+ //Interrupt
+ CompConstToVariable(0,&CPU_Action->DoSomething);
+ JeLabel32(0);
+ Jump2 = RecompPos - 4;
+ CompileExit(-1,&Section.RegWorking,DoCPU_Action,1,NULL);
+
+ SetJump32(Jump2,RecompPos);
+ Ret();
+
+ SetJump32(Jump,RecompPos);
+
+ //Interrupt 2
+ CompConstToVariable(0,&CPU_Action->DoSomething);
+ JeLabel32(0);
+ Jump = RecompPos - 4;
+ if (TargetPC != (uint32_t)-1) { MoveConstToVariable(TargetPC,&PROGRAM_COUNTER); }
+ InitilzeSection (&Section, NULL, (uint32_t)-1, 0);
+ memcpy(&Section.RegWorking, &RegSet, sizeof(REG_INFO));
+ WriteBackRegisters(&Section);
+ CompileExit(-1,&Section.RegWorking,DoCPU_Action,1,NULL);
+ SetJump32(Jump,RecompPos);
+ return;
+}
+
+void CreateSectionLinkage (BLOCK_SECTION * Section) {
+ BLOCK_SECTION ** TargetSection[2];
+ uint32_t * TargetPC[2], count;
+
+ InheritConstants(Section);
+ //__try {
+ FillSectionInfo(Section);
+/* } __except( r4300i_CPU_MemoryFilter( GetExceptionCode(), GetExceptionInformation()) ) {
+ DisplayError(GS(MSG_UNKNOWN_MEM_ACTION));
+ ExitThread(0);
+ }*/
+
+ if (Section->Jump.TargetPC < Section->Cont.TargetPC) {
+ TargetSection[0] = (BLOCK_SECTION **)&Section->JumpSection;
+ TargetSection[1] = (BLOCK_SECTION **)&Section->ContinueSection;
+ TargetPC[0] = &Section->Jump.TargetPC;
+ TargetPC[1] = &Section->Cont.TargetPC;
+ } else {
+ TargetSection[0] = (BLOCK_SECTION **)&Section->ContinueSection;
+ TargetSection[1] = (BLOCK_SECTION **)&Section->JumpSection;
+ TargetPC[0] = &Section->Cont.TargetPC;
+ TargetPC[1] = &Section->Jump.TargetPC;
+ }
+
+ for (count = 0; count < 2; count ++) {
+ if (*TargetPC[count] != (uint32_t)-1 && *TargetSection[count] == NULL) {
+ *TargetSection[count] = ExistingSection(BlockInfo.BlockInfo.ContinueSection,*TargetPC[count],GetNewTestValue());
+ if (*TargetSection[count] == NULL) {
+ *TargetSection[count] = ExistingSection(BlockInfo.BlockInfo.JumpSection,*TargetPC[count],GetNewTestValue());
+ }
+ if (*TargetSection[count] == NULL) {
+ BlockInfo.NoOfSections += 1;
+ *TargetSection[count] = malloc(sizeof(BLOCK_SECTION));
+ InitilzeSection (*TargetSection[count], Section, *TargetPC[count], BlockInfo.NoOfSections);
+ CreateSectionLinkage(*TargetSection[count]);
+ } else {
+ AddParent(*TargetSection[count],Section);
+ }
+ }
+ }
+}
+
+void DetermineLoop(BLOCK_SECTION * Section, uint32_t Test, uint32_t Test2, uint32_t TestID) {
+ if (Section == NULL) { return; }
+ if (Section->SectionID != TestID) {
+ if (Section->Test2 == Test2) {
+ return;
+ }
+ Section->Test2 = Test2;
+ DetermineLoop(Section->ContinueSection,Test,Test2,TestID);
+ DetermineLoop(Section->JumpSection,Test,Test2,TestID);
+ return;
+ }
+ if (Section->Test2 == Test2) {
+ Section->InLoop = 1;
+ return;
+ }
+ Section->Test2 = Test2;
+ DetermineLoop(Section->ContinueSection,Test,Test2,TestID);
+ DetermineLoop(Section->JumpSection,Test,Test2,TestID);
+ if (Section->Test == Test) { return; }
+ Section->Test = Test;
+ if (Section->ContinueSection != NULL) {
+ DetermineLoop(Section->ContinueSection,Test,GetNewTestValue(),((BLOCK_SECTION *)Section->ContinueSection)->SectionID);
+ }
+ if (Section->JumpSection != NULL) {
+ DetermineLoop(Section->JumpSection,Test,GetNewTestValue(),((BLOCK_SECTION *)Section->JumpSection)->SectionID);
+ }
+}
+
+uint32_t DisplaySectionInformation (BLOCK_SECTION * Section, uint32_t ID, uint32_t Test) {
+ return 1;
+}
+
+BLOCK_SECTION * ExistingSection(BLOCK_SECTION * StartSection, uint32_t Addr, uint32_t Test) {
+ BLOCK_SECTION * Section;
+
+ if (StartSection == NULL) { return NULL; }
+ if (StartSection->StartPC == Addr) { return StartSection; }
+ if (StartSection->Test == Test) { return NULL; }
+ StartSection->Test = Test;
+ Section = ExistingSection(StartSection->JumpSection,Addr,Test);
+ if (Section != NULL) { return Section; }
+ Section = ExistingSection(StartSection->ContinueSection,Addr,Test);
+ if (Section != NULL) { return Section; }
+ return NULL;
+}
+
+void FillSectionInfo(BLOCK_SECTION * Section) {
+ OPCODE Command;
+
+ if (Section->CompiledLocation != NULL) { return; }
+ Section->CompilePC = Section->StartPC;
+ memcpy(&Section->RegWorking,&Section->RegStart,sizeof(REG_INFO));
+ NextInstruction = NORMAL;
+ do {
+ if (!r4300i_LW_VAddr(Section->CompilePC, &Command.Hex)) {
+ //DisplayError(GS(MSG_FAIL_LOAD_WORD));
+ StopEmulation();
+ }
+
+ switch (Command.op) {
+ case R4300i_SPECIAL:
+ switch (Command.funct) {
+ case R4300i_SPECIAL_SLL:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && Command.rt == Command.rd) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt)) {
+ MipsRegState(Command.rd) = STATE_CONST_32;
+ MipsRegLo(Command.rd) = MipsRegLo(Command.rt) << Command.sa;
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_SRL:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && Command.rt == Command.rd) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt)) {
+ MipsRegState(Command.rd) = STATE_CONST_32;
+ MipsRegLo(Command.rd) = MipsRegLo(Command.rt) >> Command.sa;
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_SRA:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && Command.rt == Command.rd) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt)) {
+ MipsRegState(Command.rd) = STATE_CONST_32;
+ MipsRegLo(Command.rd) = MipsRegLo_S(Command.rt) >> Command.sa;
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_SLLV:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt) && IsConst(Command.rs)) {
+ MipsRegState(Command.rd) = STATE_CONST_32;
+ MipsRegLo(Command.rd) = MipsRegLo(Command.rt) << (MipsRegLo(Command.rs) & 0x1F);
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_SRLV:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt) && IsConst(Command.rs)) {
+ MipsRegState(Command.rd) = STATE_CONST_32;
+ MipsRegLo(Command.rd) = MipsRegLo(Command.rt) >> (MipsRegLo(Command.rs) & 0x1F);
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_SRAV:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt) && IsConst(Command.rs)) {
+ MipsRegState(Command.rd) = STATE_CONST_32;
+ MipsRegLo(Command.rd) = MipsRegLo_S(Command.rt) >> (MipsRegLo(Command.rs) & 0x1F);
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_JR:
+ if (IsConst(Command.rs)) {
+ Section->Jump.TargetPC = MipsRegLo(Command.rs);
+ } else {
+ Section->Jump.TargetPC = (uint32_t)-1;
+ }
+ NextInstruction = DELAY_SLOT;
+ break;
+ case R4300i_SPECIAL_JALR:
+ MipsRegLo(Opcode.rd) = Section->CompilePC + 8;
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ if (IsConst(Command.rs)) {
+ Section->Jump.TargetPC = MipsRegLo(Command.rs);
+ } else {
+ Section->Jump.TargetPC = (uint32_t)-1;
+ }
+ NextInstruction = DELAY_SLOT;
+ break;
+ case R4300i_SPECIAL_BREAK: break;
+ case R4300i_SPECIAL_SYSCALL:
+ //case R4300i_SPECIAL_BREAK:
+ NextInstruction = END_BLOCK;
+ Section->CompilePC -= 4;
+ break;
+ case R4300i_SPECIAL_MFHI: MipsRegState(Command.rd) = STATE_UNKNOWN; break;
+ case R4300i_SPECIAL_MTHI: break;
+ case R4300i_SPECIAL_MFLO: MipsRegState(Command.rd) = STATE_UNKNOWN; break;
+ case R4300i_SPECIAL_MTLO: break;
+ case R4300i_SPECIAL_DSLLV:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt) && IsConst(Command.rs)) {
+ MipsRegState(Command.rd) = STATE_CONST_64;
+ MipsReg(Command.rd) = Is64Bit(Command.rt)?MipsReg(Command.rt):(QWORD)MipsRegLo_S(Command.rt) << (MipsRegLo(Command.rs) & 0x3F);
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_DSRLV:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt) && IsConst(Command.rs)) {
+ MipsRegState(Command.rd) = STATE_CONST_64;
+ MipsReg(Command.rd) = Is64Bit(Command.rt)?MipsReg(Command.rt):(QWORD)MipsRegLo_S(Command.rt) >> (MipsRegLo(Command.rs) & 0x3F);
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_DSRAV:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt) && IsConst(Command.rs)) {
+ MipsRegState(Command.rd) = STATE_CONST_64;
+ MipsReg(Command.rd) = Is64Bit(Command.rt)?MipsReg_S(Command.rt):(int64_t)MipsRegLo_S(Command.rt) >> (MipsRegLo(Command.rs) & 0x3F);
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_MULT: break;
+ case R4300i_SPECIAL_MULTU: break;
+ case R4300i_SPECIAL_DIV: break;
+ case R4300i_SPECIAL_DIVU: break;
+ case R4300i_SPECIAL_DMULT: break;
+ case R4300i_SPECIAL_DMULTU: break;
+ case R4300i_SPECIAL_DDIV: break;
+ case R4300i_SPECIAL_DDIVU: break;
+ case R4300i_SPECIAL_ADD:
+ case R4300i_SPECIAL_ADDU:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt) && IsConst(Command.rs)) {
+ MipsRegLo(Command.rd) = MipsRegLo(Command.rs) + MipsRegLo(Command.rt);
+ MipsRegState(Command.rd) = STATE_CONST_32;
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_SUB:
+ case R4300i_SPECIAL_SUBU:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt) && IsConst(Command.rs)) {
+ MipsRegLo(Command.rd) = MipsRegLo(Command.rs) - MipsRegLo(Command.rt);
+ MipsRegState(Command.rd) = STATE_CONST_32;
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_AND:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt) && IsConst(Command.rs)) {
+ if (Is64Bit(Command.rt) && Is64Bit(Command.rs)) {
+ MipsReg(Command.rd) = MipsReg(Command.rt) & MipsReg(Command.rs);
+ MipsRegState(Command.rd) = STATE_CONST_64;
+ } else if (Is64Bit(Command.rt) || Is64Bit(Command.rs)) {
+ if (Is64Bit(Command.rt)) {
+ MipsReg(Command.rd) = MipsReg(Command.rt) & MipsRegLo(Command.rs);
+ } else {
+ MipsReg(Command.rd) = MipsRegLo(Command.rt) & MipsReg(Command.rs);
+ }
+ MipsRegState(Command.rd) = ConstantsType(MipsReg(Command.rd));
+ } else {
+ MipsRegLo(Command.rd) = MipsRegLo(Command.rt) & MipsRegLo(Command.rs);
+ MipsRegState(Command.rd) = STATE_CONST_32;
+ }
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_OR:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt) && IsConst(Command.rs)) {
+ if (Is64Bit(Command.rt) && Is64Bit(Command.rs)) {
+ MipsReg(Command.rd) = MipsReg(Command.rt) | MipsReg(Command.rs);
+ MipsRegState(Command.rd) = STATE_CONST_64;
+ } else if (Is64Bit(Command.rt) || Is64Bit(Command.rs)) {
+ if (Is64Bit(Command.rt)) {
+ MipsReg(Command.rd) = MipsReg(Command.rt) | MipsRegLo(Command.rs);
+ } else {
+ MipsReg(Command.rd) = MipsRegLo(Command.rt) | MipsReg(Command.rs);
+ }
+ MipsRegState(Command.rd) = STATE_CONST_64;
+ } else {
+ MipsRegLo(Command.rd) = MipsRegLo(Command.rt) | MipsRegLo(Command.rs);
+ MipsRegState(Command.rd) = STATE_CONST_32;
+ }
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_XOR:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt) && IsConst(Command.rs)) {
+ if (Is64Bit(Command.rt) && Is64Bit(Command.rs)) {
+ MipsReg(Command.rd) = MipsReg(Command.rt) ^ MipsReg(Command.rs);
+ MipsRegState(Command.rd) = STATE_CONST_64;
+ } else if (Is64Bit(Command.rt) || Is64Bit(Command.rs)) {
+ if (Is64Bit(Command.rt)) {
+ MipsReg(Command.rd) = MipsReg(Command.rt) ^ MipsRegLo(Command.rs);
+ } else {
+ MipsReg(Command.rd) = MipsRegLo(Command.rt) ^ MipsReg(Command.rs);
+ }
+ MipsRegState(Command.rd) = STATE_CONST_64;
+ } else {
+ MipsRegLo(Command.rd) = MipsRegLo(Command.rt) ^ MipsRegLo(Command.rs);
+ MipsRegState(Command.rd) = STATE_CONST_32;
+ }
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_NOR:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt) && IsConst(Command.rs)) {
+ if (Is64Bit(Command.rt) && Is64Bit(Command.rs)) {
+ MipsReg(Command.rd) = ~(MipsReg(Command.rt) | MipsReg(Command.rs));
+ MipsRegState(Command.rd) = STATE_CONST_64;
+ } else if (Is64Bit(Command.rt) || Is64Bit(Command.rs)) {
+ if (Is64Bit(Command.rt)) {
+ MipsReg(Command.rd) = ~(MipsReg(Command.rt) | MipsRegLo(Command.rs));
+ } else {
+ MipsReg(Command.rd) = ~(MipsRegLo(Command.rt) | MipsReg(Command.rs));
+ }
+ MipsRegState(Command.rd) = STATE_CONST_64;
+ } else {
+ MipsRegLo(Command.rd) = ~(MipsRegLo(Command.rt) | MipsRegLo(Command.rs));
+ MipsRegState(Command.rd) = STATE_CONST_32;
+ }
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_SLT:
+ if (Command.rd == 0) { break; }
+ if (IsConst(Command.rt) && IsConst(Command.rs)) {
+ if (Is64Bit(Command.rt) || Is64Bit(Command.rs)) {
+ if (Is64Bit(Command.rt)) {
+ MipsRegLo(Command.rd) = (MipsRegLo_S(Command.rs) < MipsReg_S(Command.rt))?1:0;
+ } else {
+ MipsRegLo(Command.rd) = (MipsReg_S(Command.rs) < MipsRegLo_S(Command.rt))?1:0;
+ }
+ } else {
+ MipsRegLo(Command.rd) = (MipsRegLo_S(Command.rs) < MipsRegLo_S(Command.rt))?1:0;
+ }
+ MipsRegState(Command.rd) = STATE_CONST_32;
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_SLTU:
+ if (Command.rd == 0) { break; }
+ if (IsConst(Command.rt) && IsConst(Command.rs)) {
+ if (Is64Bit(Command.rt) || Is64Bit(Command.rs)) {
+ if (Is64Bit(Command.rt)) {
+ MipsRegLo(Command.rd) = (MipsRegLo(Command.rs) < MipsReg(Command.rt))?1:0;
+ } else {
+ MipsRegLo(Command.rd) = (MipsReg(Command.rs) < MipsRegLo(Command.rt))?1:0;
+ }
+ } else {
+ MipsRegLo(Command.rd) = (MipsRegLo(Command.rs) < MipsRegLo(Command.rt))?1:0;
+ }
+ MipsRegState(Command.rd) = STATE_CONST_32;
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_DADD:
+ case R4300i_SPECIAL_DADDU:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt) && IsConst(Command.rs)) {
+ MipsReg(Command.rd) =
+ Is64Bit(Command.rs)?MipsReg(Command.rs):(int64_t)MipsRegLo_S(Command.rs) +
+ Is64Bit(Command.rt)?MipsReg(Command.rt):(int64_t)MipsRegLo_S(Command.rt);
+ MipsRegState(Command.rd) = STATE_CONST_64;
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_DSUB:
+ case R4300i_SPECIAL_DSUBU:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt) && IsConst(Command.rs)) {
+ MipsReg(Command.rd) =
+ Is64Bit(Command.rs)?MipsReg(Command.rs):(int64_t)MipsRegLo_S(Command.rs) -
+ Is64Bit(Command.rt)?MipsReg(Command.rt):(int64_t)MipsRegLo_S(Command.rt);
+ MipsRegState(Command.rd) = STATE_CONST_64;
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_DSLL:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && Command.rt == Command.rd) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt)) {
+ MipsRegState(Command.rd) = STATE_CONST_64;
+ MipsReg(Command.rd) = Is64Bit(Command.rt)?MipsReg(Command.rt):(int64_t)MipsRegLo_S(Command.rt) << Command.sa;
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_DSRL:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && Command.rt == Command.rd) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt)) {
+ MipsRegState(Command.rd) = STATE_CONST_64;
+ MipsReg(Command.rd) = Is64Bit(Command.rt)?MipsReg(Command.rt):(QWORD)MipsRegLo_S(Command.rt) >> Command.sa;
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_DSRA:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && Command.rt == Command.rd) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt)) {
+ MipsRegState(Command.rd) = STATE_CONST_64;
+ MipsReg_S(Command.rd) = Is64Bit(Command.rt)?MipsReg_S(Command.rt):(int64_t)MipsRegLo_S(Command.rt) >> Command.sa;
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_DSLL32:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && Command.rt == Command.rd) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt)) {
+ MipsRegState(Command.rd) = STATE_CONST_64;
+ MipsReg(Command.rd) = MipsRegLo(Command.rt) << (Command.sa + 32);
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_DSRL32:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && Command.rt == Command.rd) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt)) {
+ MipsRegState(Command.rd) = STATE_CONST_32;
+ MipsRegLo(Command.rd) = (uint32_t)(MipsReg(Command.rt) >> (Command.sa + 32));
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SPECIAL_DSRA32:
+ if (Command.rd == 0) { break; }
+ if (Section->InLoop && Command.rt == Command.rd) {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rt)) {
+ MipsRegState(Command.rd) = STATE_CONST_32;
+ MipsRegLo(Command.rd) = (uint32_t)(MipsReg_S(Command.rt) >> (Command.sa + 32));
+ } else {
+ MipsRegState(Command.rd) = STATE_UNKNOWN;
+ }
+ break;
+ default:
+ NextInstruction = END_BLOCK;
+ Section->CompilePC -= 4;
+ }
+ break;
+ case R4300i_REGIMM:
+ switch (Command.rt) {
+ case R4300i_REGIMM_BLTZ:
+ case R4300i_REGIMM_BGEZ:
+ NextInstruction = DELAY_SLOT;
+ Section->Cont.TargetPC = Section->CompilePC + 8;
+ Section->Jump.TargetPC = Section->CompilePC + ((short)Command.offset << 2) + 4;
+ if (Section->CompilePC == Section->Jump.TargetPC) {
+ if (!DelaySlotEffectsCompare(Section->CompilePC,Command.rs,0)) {
+ Section->Jump.PermLoop = 1;
+ }
+ }
+ break;
+ case R4300i_REGIMM_BLTZL:
+ case R4300i_REGIMM_BGEZL:
+ NextInstruction = LIKELY_DELAY_SLOT;
+ Section->Cont.TargetPC = Section->CompilePC + 8;
+ Section->Jump.TargetPC = Section->CompilePC + ((short)Command.offset << 2) + 4;
+ if (Section->CompilePC == Section->Jump.TargetPC) {
+ if (!DelaySlotEffectsCompare(Section->CompilePC,Command.rs,0)) {
+ Section->Jump.PermLoop = 1;
+ }
+ }
+ break;
+ case R4300i_REGIMM_BLTZAL:
+ case R4300i_REGIMM_BGEZAL:
+ NextInstruction = DELAY_SLOT;
+ MipsRegLo(31) = Section->CompilePC + 8;
+ MipsRegState(31) = STATE_CONST_32;
+ Section->Cont.TargetPC = Section->CompilePC + 8;
+ Section->Jump.TargetPC = Section->CompilePC + ((short)Command.offset << 2) + 4;
+ if (Section->CompilePC == Section->Jump.TargetPC) {
+ if (!DelaySlotEffectsCompare(Section->CompilePC,Command.rs,0)) {
+ Section->Jump.PermLoop = 1;
+ }
+ }
+ break;
+ default:
+ NextInstruction = END_BLOCK;
+ Section->CompilePC -= 4;
+ }
+ break;
+ case R4300i_JAL:
+ NextInstruction = DELAY_SLOT;
+ MipsRegLo(31) = Section->CompilePC + 8;
+ MipsRegState(31) = STATE_CONST_32;
+ Section->Jump.TargetPC = (Section->CompilePC & 0xF0000000) + (Command.target << 2);
+ if (Section->CompilePC == Section->Jump.TargetPC) {
+ if (!DelaySlotEffectsCompare(Section->CompilePC,31,0)) {
+ Section->Jump.PermLoop = 1;
+ }
+ }
+ break;
+ case R4300i_J:
+ NextInstruction = DELAY_SLOT;
+ Section->Jump.TargetPC = (Section->CompilePC & 0xF0000000) + (Command.target << 2);
+ if (Section->CompilePC == Section->Jump.TargetPC) { Section->Jump.PermLoop = 1; }
+ break;
+ case R4300i_BEQ:
+ case R4300i_BNE:
+ case R4300i_BLEZ:
+ case R4300i_BGTZ:
+ NextInstruction = DELAY_SLOT;
+ Section->Cont.TargetPC = Section->CompilePC + 8;
+ Section->Jump.TargetPC = Section->CompilePC + ((short)Command.offset << 2) + 4;
+ if (Section->CompilePC == Section->Jump.TargetPC) {
+ if (!DelaySlotEffectsCompare(Section->CompilePC,Command.rs,Command.rt)) {
+ Section->Jump.PermLoop = 1;
+ }
+ }
+ break;
+ case R4300i_ADDI:
+ case R4300i_ADDIU:
+ if (Command.rt == 0) { break; }
+ if (Section->InLoop && Command.rs == Command.rt) {
+ MipsRegState(Command.rt) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rs)) {
+ MipsRegLo(Command.rt) = MipsRegLo(Command.rs) + (short)Command.immediate;
+ MipsRegState(Command.rt) = STATE_CONST_32;
+ } else {
+ MipsRegState(Command.rt) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SLTI:
+ if (Command.rt == 0) { break; }
+ if (IsConst(Command.rs)) {
+ if (Is64Bit(Command.rs)) {
+ MipsRegLo(Command.rt) = (MipsReg_S(Command.rs) < (int64_t)((short)Command.immediate))?1:0;
+ } else {
+ MipsRegLo(Command.rt) = (MipsRegLo_S(Command.rs) < (int)((short)Command.immediate))?1:0;
+ }
+ MipsRegState(Command.rt) = STATE_CONST_32;
+ } else {
+ MipsRegState(Command.rt) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_SLTIU:
+ if (Command.rt == 0) { break; }
+ if (IsConst(Command.rs)) {
+ if (Is64Bit(Command.rs)) {
+ MipsRegLo(Command.rt) = (MipsReg(Command.rs) < (int64_t)((short)Command.immediate))?1:0;
+ } else {
+ MipsRegLo(Command.rt) = (MipsRegLo(Command.rs) < (uint32_t)((short)Command.immediate))?1:0;
+ }
+ MipsRegState(Command.rt) = STATE_CONST_32;
+ } else {
+ MipsRegState(Command.rt) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_LUI:
+ if (Command.rt == 0) { break; }
+ MipsRegLo(Command.rt) = ((short)Command.offset << 16);
+ MipsRegState(Command.rt) = STATE_CONST_32;
+ break;
+ case R4300i_ANDI:
+ if (Command.rt == 0) { break; }
+ if (Section->InLoop && Command.rs == Command.rt) {
+ MipsRegState(Command.rt) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rs)) {
+ MipsRegState(Command.rt) = STATE_CONST_32;
+ MipsRegLo(Command.rt) = MipsRegLo(Command.rs) & Command.immediate;
+ } else {
+ MipsRegState(Command.rt) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_ORI:
+ if (Command.rt == 0) { break; }
+ if (Section->InLoop && Command.rs == Command.rt) {
+ MipsRegState(Command.rt) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rs)) {
+ MipsRegState(Command.rt) = STATE_CONST_32;
+ MipsRegLo(Command.rt) = MipsRegLo(Command.rs) | Command.immediate;
+ } else {
+ MipsRegState(Command.rt) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_XORI:
+ if (Command.rt == 0) { break; }
+ if (Section->InLoop && Command.rs == Command.rt) {
+ MipsRegState(Command.rt) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rs)) {
+ MipsRegState(Command.rt) = STATE_CONST_32;
+ MipsRegLo(Command.rt) = MipsRegLo(Command.rs) ^ Command.immediate;
+ } else {
+ MipsRegState(Command.rt) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_CP0:
+ switch (Command.rs) {
+ case R4300i_COP0_MF:
+ if (Command.rt == 0) { break; }
+ MipsRegState(Command.rt) = STATE_UNKNOWN;
+ break;
+ case R4300i_COP0_MT: break;
+ default:
+ if ( (Command.rs & 0x10 ) != 0 ) {
+ switch( Command.funct ) {
+ case R4300i_COP0_CO_TLBR: break;
+ case R4300i_COP0_CO_TLBWI: break;
+ case R4300i_COP0_CO_TLBWR: break;
+ case R4300i_COP0_CO_TLBP: break;
+ case R4300i_COP0_CO_ERET: NextInstruction = END_BLOCK; break;
+ default:
+ NextInstruction = END_BLOCK;
+ Section->CompilePC -= 4;
+ }
+ } else {
+ NextInstruction = END_BLOCK;
+ Section->CompilePC -= 4;
+ }
+ }
+ break;
+ case R4300i_CP1:
+ switch (Command.fmt) {
+ case R4300i_COP1_CF:
+ case R4300i_COP1_MF:
+ case R4300i_COP1_DMF:
+ if (Command.rt == 0) { break; }
+ MipsRegState(Command.rt) = STATE_UNKNOWN;
+ break;
+ case R4300i_COP1_BC:
+ switch (Command.ft) {
+ case R4300i_COP1_BC_BCF:
+ case R4300i_COP1_BC_BCT:
+ case R4300i_COP1_BC_BCFL:
+ case R4300i_COP1_BC_BCTL:
+ NextInstruction = DELAY_SLOT;
+ Section->Cont.TargetPC = Section->CompilePC + 8;
+ Section->Jump.TargetPC = Section->CompilePC + ((short)Command.offset << 2) + 4;
+ if (Section->CompilePC == Section->Jump.TargetPC) {
+ int EffectDelaySlot;
+ OPCODE NewCommand;
+
+ if (!r4300i_LW_VAddr(Section->CompilePC + 4, &NewCommand.Hex)) {
+ //DisplayError(GS(MSG_FAIL_LOAD_WORD));
+ //ExitThread(0);
+ StopEmulation();
+ }
+
+ EffectDelaySlot = 0;
+ if (NewCommand.op == R4300i_CP1) {
+ if (NewCommand.fmt == R4300i_COP1_S && (NewCommand.funct & 0x30) == 0x30 ) {
+ EffectDelaySlot = 1;
+ }
+ if (NewCommand.fmt == R4300i_COP1_D && (NewCommand.funct & 0x30) == 0x30 ) {
+ EffectDelaySlot = 1;
+ }
+ }
+ if (!EffectDelaySlot) {
+ Section->Jump.PermLoop = 1;
+ }
+ }
+ break;
+ }
+ break;
+ case R4300i_COP1_MT: break;
+ case R4300i_COP1_DMT: break;
+ case R4300i_COP1_CT: break;
+ case R4300i_COP1_S: break;
+ case R4300i_COP1_D: break;
+ case R4300i_COP1_W: break;
+ case R4300i_COP1_L: break;
+ default:
+ NextInstruction = END_BLOCK;
+ Section->CompilePC -= 4;
+ }
+ break;
+ case R4300i_BEQL:
+ case R4300i_BNEL:
+ case R4300i_BLEZL:
+ case R4300i_BGTZL:
+ NextInstruction = LIKELY_DELAY_SLOT;
+ Section->Cont.TargetPC = Section->CompilePC + 8;
+ Section->Jump.TargetPC = Section->CompilePC + ((short)Command.offset << 2) + 4;
+ if (Section->CompilePC == Section->Jump.TargetPC) {
+ if (!DelaySlotEffectsCompare(Section->CompilePC,Command.rs,Command.rt)) {
+ Section->Jump.PermLoop = 1;
+ }
+ }
+ break;
+ case R4300i_DADDI:
+ case R4300i_DADDIU:
+ if (Command.rt == 0) { break; }
+ if (Section->InLoop && Command.rs == Command.rt) {
+ MipsRegState(Command.rt) = STATE_UNKNOWN;
+ }
+ if (IsConst(Command.rs)) {
+ if (Is64Bit(Command.rs)) {
+ int imm32 = (short)Opcode.immediate;
+ int64_t imm64 = imm32;
+ MipsReg_S(Command.rt) = MipsRegLo_S(Command.rs) + imm64;
+ } else {
+ MipsReg_S(Command.rt) = MipsRegLo_S(Command.rs) + (short)Command.immediate;
+ }
+ MipsRegState(Command.rt) = STATE_CONST_64;
+ } else {
+ MipsRegState(Command.rt) = STATE_UNKNOWN;
+ }
+ break;
+ case R4300i_LDR:
+ case R4300i_LDL:
+ case R4300i_LB:
+ case R4300i_LH:
+ case R4300i_LWL:
+ case R4300i_LW:
+ case R4300i_LWU:
+ case R4300i_LL:
+ case R4300i_LBU:
+ case R4300i_LHU:
+ case R4300i_LWR:
+ case R4300i_SC:
+ if (Command.rt == 0) { break; }
+ MipsRegState(Command.rt) = STATE_UNKNOWN;
+ break;
+ case R4300i_SB: break;
+ case R4300i_SH: break;
+ case R4300i_SWL: break;
+ case R4300i_SW: break;
+ case R4300i_SWR: break;
+ case R4300i_SDL: break;
+ case R4300i_SDR: break;
+ case R4300i_CACHE: break;
+ case R4300i_LWC1: break;
+ case R4300i_SWC1: break;
+ case R4300i_LDC1: break;
+ case R4300i_LD:
+ if (Command.rt == 0) { break; }
+ MipsRegState(Command.rt) = STATE_UNKNOWN;
+ break;
+ case R4300i_SDC1: break;
+ case R4300i_SD: break;
+ default:
+ NextInstruction = END_BLOCK;
+ Section->CompilePC -= 4;
+ if (Command.Hex == 0x7C1C97C0) { break; }
+ if (Command.Hex == 0x7FFFFFFF) { break; }
+ if (Command.Hex == 0xF1F3F5F7) { break; }
+ if (Command.Hex == 0xC1200000) { break; }
+ if (Command.Hex == 0x4C5A5353) { break; }
+ }
+
+ switch (NextInstruction) {
+ case NORMAL:
+ Section->CompilePC += 4;
+ break;
+ case DELAY_SLOT:
+ NextInstruction = DELAY_SLOT_DONE;
+ Section->CompilePC += 4;
+ break;
+ case LIKELY_DELAY_SLOT:
+ memcpy(&Section->Cont.RegSet,&Section->RegWorking,sizeof(REG_INFO));
+ NextInstruction = LIKELY_DELAY_SLOT_DONE;
+ Section->CompilePC += 4;
+ break;
+ case DELAY_SLOT_DONE:
+ memcpy(&Section->Cont.RegSet,&Section->RegWorking,sizeof(REG_INFO));
+ memcpy(&Section->Jump.RegSet,&Section->RegWorking,sizeof(REG_INFO));
+ NextInstruction = END_BLOCK;
+ break;
+ case LIKELY_DELAY_SLOT_DONE:
+ memcpy(&Section->Jump.RegSet,&Section->RegWorking,sizeof(REG_INFO));
+ NextInstruction = END_BLOCK;
+ break;
+ }
+ if ((Section->CompilePC & 0xFFFFF000) != (Section->StartPC & 0xFFFFF000)) {
+ if (NextInstruction != END_BLOCK && NextInstruction != NORMAL) {
+ // DisplayError("Branch running over delay slot ???\nNextInstruction == %d",NextInstruction);
+ Section->Cont.TargetPC = (uint32_t)-1;
+ Section->Jump.TargetPC = (uint32_t)-1;
+ }
+ NextInstruction = END_BLOCK;
+ Section->CompilePC -= 4;
+ }
+ } while (NextInstruction != END_BLOCK);
+
+ if (Section->Cont.TargetPC != (uint32_t)-1) {
+ if ((Section->Cont.TargetPC & 0xFFFFF000) != (Section->StartPC & 0xFFFFF000)) {
+ Section->Cont.TargetPC = (uint32_t)-1;
+ }
+ }
+ if (Section->Jump.TargetPC != (uint32_t)-1) {
+ if ((Section->Jump.TargetPC & 0xFFFFF000) != (Section->StartPC & 0xFFFFF000)) {
+ Section->Jump.TargetPC = (uint32_t)-1;
+ }
+ }
+}
+
+void FixConstants (BLOCK_SECTION * Section, uint32_t Test, int * Changed) {
+ BLOCK_SECTION * Parent;
+ int count, NoOfParents;
+ REG_INFO Original[2];
+
+ if (Section == NULL) { return; }
+ if (Section->Test == Test) { return; }
+ Section->Test = Test;
+
+ InheritConstants(Section);
+
+ memcpy(&Original[0],&Section->Cont.RegSet,sizeof(REG_INFO));
+ memcpy(&Original[1],&Section->Jump.RegSet,sizeof(REG_INFO));
+
+ if (Section->ParentSection) {
+ for (NoOfParents = 0;Section->ParentSection[NoOfParents] != NULL;NoOfParents++) {
+ Parent = Section->ParentSection[NoOfParents];
+ if (Parent->ContinueSection == Section) {
+ for (count = 0; count < 32; count++) {
+ if (Section->RegStart.MIPS_RegState[count] != Parent->Cont.RegSet.MIPS_RegState[count]) {
+ Section->RegStart.MIPS_RegState[count] = STATE_UNKNOWN;
+ //*Changed = 1;
+ }
+ Section->RegStart.MIPS_RegState[count] = STATE_UNKNOWN;
+ }
+ }
+ if (Parent->JumpSection == Section) {
+ for (count = 0; count < 32; count++) {
+ if (Section->RegStart.MIPS_RegState[count] != Parent->Jump.RegSet.MIPS_RegState[count]) {
+ Section->RegStart.MIPS_RegState[count] = STATE_UNKNOWN;
+ //*Changed = 1;
+ }
+ }
+ }
+ memcpy(&Section->RegWorking,&Section->RegStart,sizeof(REG_INFO));
+ }
+ }
+ FillSectionInfo(Section);
+ if (memcmp(&Original[0],&Section->Cont.RegSet,sizeof(REG_INFO)) != 0) { *Changed = 1; }
+ if (memcmp(&Original[1],&Section->Jump.RegSet,sizeof(REG_INFO)) != 0) { *Changed = 1; }
+
+ if (Section->JumpSection) { FixConstants(Section->JumpSection,Test,Changed); }
+ if (Section->ContinueSection) { FixConstants(Section->ContinueSection,Test,Changed); }
+}
+
+void FixRandomReg (void) {
+// while ((int)Registers.CP0[1] < (int)Registers.CP0[6]) {
+// Registers.CP0[1] += 32 - Registers.CP0[6];
+// }
+}
+
+void FreeSection (BLOCK_SECTION * Section, BLOCK_SECTION * Parent) {
+ if (Section == NULL) { return; }
+
+ if (Section->ParentSection) {
+ int NoOfParents, count;
+
+ for (NoOfParents = 0;Section->ParentSection[NoOfParents] != NULL;NoOfParents++);
+
+ for (count = 0; count < NoOfParents; count++) {
+ if (Section->ParentSection[count] == Parent) {
+ if (NoOfParents == 1) {
+ free(Section->ParentSection);
+ Section->ParentSection = NULL;
+ } else {
+ memmove(&Section->ParentSection[count],&Section->ParentSection[count + 1],
+ sizeof(void*) * (NoOfParents - count));
+ Section->ParentSection = realloc(Section->ParentSection,NoOfParents*sizeof(void *));
+ }
+ NoOfParents -= 1;
+ }
+ }
+
+ if (Parent->JumpSection == Section) { Parent->JumpSection = NULL; }
+ if (Parent->ContinueSection == Section) { Parent->ContinueSection = NULL; }
+
+ if (Section->ParentSection) {
+ for (count = 0; count < NoOfParents; count++) {
+ if (!IsAllParentLoops(Section,Section->ParentSection[count],0,GetNewTestValue())) { return; }
+ }
+ for (count = 0; count < NoOfParents; count++) {
+ Parent = Section->ParentSection[count];
+ if (Parent->JumpSection == Section) { Parent->JumpSection = NULL; }
+ if (Parent->ContinueSection == Section) { Parent->ContinueSection = NULL; }
+ }
+ free(Section->ParentSection);
+ Section->ParentSection = NULL;
+ }
+ }
+ if (Section->ParentSection == NULL) {
+ FreeSection(Section->JumpSection,Section);
+ FreeSection(Section->ContinueSection,Section);
+ Section->JumpSection = NULL;
+ Section->ContinueSection = NULL;
+ free(Section);
+ Section = 0;
+ }
+}
+
+void GenerateBasicSectionLinkage (BLOCK_SECTION * Section) {
+ //_asm int 3
+}
+
+void GenerateSectionLinkage (BLOCK_SECTION * Section) {
+ BLOCK_SECTION * TargetSection[2], *Parent;
+ JUMP_INFO * JumpInfo[2];
+ uint8_t * Jump;
+ int count;
+
+ TargetSection[0] = Section->ContinueSection;
+ TargetSection[1] = Section->JumpSection;
+ JumpInfo[0] = &Section->Cont;
+ JumpInfo[1] = &Section->Jump;
+
+ for (count = 0; count < 2; count ++) {
+ if (JumpInfo[count]->LinkLocation == NULL && JumpInfo[count]->FallThrough == 0) {
+ JumpInfo[count]->TargetPC = -1;
+ }
+ }
+ if ((Section->CompilePC & 0xFFC) == 0xFFC) {
+ //Handle Fall througth
+ Jump = NULL;
+ for (count = 0; count < 2; count ++) {
+ if (!JumpInfo[count]->FallThrough) { continue; }
+ JumpInfo[count]->FallThrough = 0;
+ if (JumpInfo[count]->LinkLocation != NULL) {
+ SetJump32(JumpInfo[count]->LinkLocation,RecompPos);
+ JumpInfo[count]->LinkLocation = NULL;
+ if (JumpInfo[count]->LinkLocation2 != NULL) {
+ SetJump32(JumpInfo[count]->LinkLocation2,RecompPos);
+ JumpInfo[count]->LinkLocation2 = NULL;
+ }
+ }
+ MoveConstToVariable(JumpInfo[count]->TargetPC,&JumpToLocation);
+ if (JumpInfo[(count + 1) & 1]->LinkLocation == NULL) { break; }
+ JmpLabel8(0);
+ Jump = RecompPos - 1;
+ }
+ for (count = 0; count < 2; count ++) {
+ if (JumpInfo[count]->LinkLocation == NULL) { continue; }
+ JumpInfo[count]->FallThrough = 0;
+ if (JumpInfo[count]->LinkLocation != NULL) {
+ SetJump32(JumpInfo[count]->LinkLocation,RecompPos);
+ JumpInfo[count]->LinkLocation = NULL;
+ if (JumpInfo[count]->LinkLocation2 != NULL) {
+ SetJump32(JumpInfo[count]->LinkLocation2,RecompPos);
+ JumpInfo[count]->LinkLocation2 = NULL;
+ }
+ }
+ MoveConstToVariable(JumpInfo[count]->TargetPC,&JumpToLocation);
+ if (JumpInfo[(count + 1) & 1]->LinkLocation == NULL) { break; }
+ JmpLabel8(0);
+ Jump = RecompPos - 1;
+ }
+ if (Jump != NULL) {
+ SetJump8(Jump,RecompPos);
+ }
+ MoveConstToVariable(Section->CompilePC + 4,&PROGRAM_COUNTER);
+ if (BlockCycleCount != 0) {
+ AddConstToVariable(BlockCycleCount,&CP0[9]);
+ SubConstFromVariable(BlockCycleCount,&Timers->Timer);
+ }
+ if (BlockRandomModifier != 0) { SubConstFromVariable(BlockRandomModifier,&CP0[1]); }
+ WriteBackRegisters(Section);
+ MoveConstToVariable(DELAY_SLOT,&NextInstruction);
+ Ret();
+ return;
+ }
+
+ if (TargetSection[0] != TargetSection[1] || TargetSection[0] == NULL) {
+ for (count = 0; count < 2; count ++) {
+ if (JumpInfo[count]->LinkLocation == NULL && JumpInfo[count]->FallThrough == 0) {
+ FreeSection(TargetSection[count],Section);
+ } else if (TargetSection[count] == NULL && JumpInfo[count]->FallThrough) {
+ if (JumpInfo[count]->LinkLocation != NULL) {
+ SetJump32(JumpInfo[count]->LinkLocation,RecompPos);
+ JumpInfo[count]->LinkLocation = NULL;
+ if (JumpInfo[count]->LinkLocation2 != NULL) {
+ SetJump32(JumpInfo[count]->LinkLocation2,RecompPos);
+ JumpInfo[count]->LinkLocation2 = NULL;
+ }
+ }
+ if (JumpInfo[count]->TargetPC > (Section->CompilePC + 4)) {
+ CompileExit (JumpInfo[count]->TargetPC,&JumpInfo[count]->RegSet,Normal,1,NULL);
+ } else {
+ CompileExit (JumpInfo[count]->TargetPC,&JumpInfo[count]->RegSet,Normal,1,NULL);
+ }
+ JumpInfo[count]->FallThrough = 0;
+ } else if (TargetSection[count] != NULL && JumpInfo[count] != NULL) {
+ if (!JumpInfo[count]->FallThrough) { continue; }
+ if (JumpInfo[count]->TargetPC == TargetSection[count]->StartPC) { continue; }
+ if (JumpInfo[count]->LinkLocation != NULL) {
+ SetJump32(JumpInfo[count]->LinkLocation,RecompPos);
+ JumpInfo[count]->LinkLocation = NULL;
+ if (JumpInfo[count]->LinkLocation2 != NULL) {
+ SetJump32(JumpInfo[count]->LinkLocation2,RecompPos);
+ JumpInfo[count]->LinkLocation2 = NULL;
+ }
+ }
+ CompileExit (JumpInfo[count]->TargetPC,&JumpInfo[count]->RegSet,Normal,1,NULL);
+ FreeSection(TargetSection[count],Section);
+ }
+ }
+ } else {
+ if (Section->Cont.LinkLocation == NULL && Section->Cont.FallThrough == 0) { Section->ContinueSection = NULL; }
+ if (Section->Jump.LinkLocation == NULL && Section->Jump.FallThrough == 0) { Section->JumpSection = NULL; }
+ if (Section->JumpSection == NULL && Section->ContinueSection == NULL) {
+ FreeSection(TargetSection[0],Section);
+ }
+ }
+
+ TargetSection[0] = Section->ContinueSection;
+ TargetSection[1] = Section->JumpSection;
+
+ for (count = 0; count < 2; count ++) {
+ if (TargetSection[count] == NULL) { continue; }
+ if (!JumpInfo[count]->FallThrough) { continue; }
+
+ if (TargetSection[count]->CompiledLocation != NULL) {
+ //char Label[100];
+ JumpInfo[count]->FallThrough = 0;
+ if (JumpInfo[count]->LinkLocation != NULL) {
+ SetJump32(JumpInfo[count]->LinkLocation,RecompPos);
+ JumpInfo[count]->LinkLocation = NULL;
+ if (JumpInfo[count]->LinkLocation2 != NULL) {
+ SetJump32(JumpInfo[count]->LinkLocation2,RecompPos);
+ JumpInfo[count]->LinkLocation2 = NULL;
+ }
+ }
+ if (JumpInfo[count]->RegSet.RandomModifier != 0) {
+ SubConstFromVariable(JumpInfo[count]->RegSet.RandomModifier,&CP0[1]);
+ JumpInfo[count]->RegSet.RandomModifier = 0;
+ }
+ if (JumpInfo[count]->RegSet.CycleCount != 0) {
+ AddConstToVariable(JumpInfo[count]->RegSet.CycleCount,&CP0[9]);
+ }
+ if (JumpInfo[count]->TargetPC <= Section->CompilePC) {
+ uint32_t CycleCount = JumpInfo[count]->RegSet.CycleCount;
+ JumpInfo[count]->RegSet.CycleCount = 0;
+
+ if (JumpInfo[count]->PermLoop) {
+ MoveConstToVariable(JumpInfo[count]->TargetPC,&PROGRAM_COUNTER);
+ Pushad();
+ Call_Direct(InPermLoop);
+ Popad();
+ CompileSystemCheck(0,-1,JumpInfo[count]->RegSet);
+ } else {
+ CompileSystemCheck(CycleCount,JumpInfo[count]->TargetPC,JumpInfo[count]->RegSet);
+ }
+ } else {
+ if (JumpInfo[count]->RegSet.CycleCount != 0) {
+ SubConstFromVariable(JumpInfo[count]->RegSet.CycleCount,&Timers->Timer);
+ JumpInfo[count]->RegSet.CycleCount = 0;
+ }
+ }
+ memcpy(&Section->RegWorking, &JumpInfo[count]->RegSet,sizeof(REG_INFO));
+ SyncRegState(Section,&TargetSection[count]->RegStart);
+ JmpLabel32(0);
+ SetJump32((uint32_t *)RecompPos - 1,TargetSection[count]->CompiledLocation);
+ }
+ }
+ //Section->CycleCount = 0;
+ //Section->RandomModifier = 0;
+
+ for (count = 0; count < 2; count ++) {
+ int count2;
+
+ if (TargetSection[count] == NULL) { continue; }
+ if (TargetSection[count]->ParentSection == NULL) { continue; }
+
+ for (count2 = 0;TargetSection[count]->ParentSection[count2] != NULL;count2++) {
+ Parent = TargetSection[count]->ParentSection[count2];
+ if (Parent->CompiledLocation != NULL) { continue; }
+ if (JumpInfo[count]->FallThrough) {
+ JumpInfo[count]->FallThrough = 0;
+ //JmpLabel32(JumpInfo[count]->BranchLabel,0);
+ JmpLabel32(0);
+ JumpInfo[count]->LinkLocation = RecompPos - 4;
+ }
+ }
+ }
+
+ for (count = 0; count < 2; count ++) {
+ if (JumpInfo[count]->FallThrough) {
+ if (JumpInfo[count]->TargetPC < Section->CompilePC) {
+ uint32_t CycleCount = JumpInfo[count]->RegSet.CycleCount;;
+
+ if (JumpInfo[count]->RegSet.RandomModifier != 0) {
+ SubConstFromVariable(JumpInfo[count]->RegSet.RandomModifier,&CP0[1]);
+ JumpInfo[count]->RegSet.RandomModifier = 0;
+ }
+ if (JumpInfo[count]->RegSet.CycleCount != 0) {
+ AddConstToVariable(JumpInfo[count]->RegSet.CycleCount,&CP0[9]);
+ }
+ JumpInfo[count]->RegSet.CycleCount = 0;
+
+ CompileSystemCheck(CycleCount,JumpInfo[count]->TargetPC,JumpInfo[count]->RegSet);
+ }
+ }
+ }
+
+ for (count = 0; count < 2; count ++) {
+ if (JumpInfo[count]->FallThrough) {
+ GenerateX86Code(TargetSection[count],GetNewTestValue());
+ }
+ }
+
+ for (count = 0; count < 2; count ++) {
+ if (JumpInfo[count]->LinkLocation == NULL) { continue; }
+ if (TargetSection[count] == NULL) {
+ SetJump32(JumpInfo[count]->LinkLocation,RecompPos);
+ JumpInfo[count]->LinkLocation = NULL;
+ if (JumpInfo[count]->LinkLocation2 != NULL) {
+ SetJump32(JumpInfo[count]->LinkLocation2,RecompPos);
+ JumpInfo[count]->LinkLocation2 = NULL;
+ }
+ CompileExit (JumpInfo[count]->TargetPC,&JumpInfo[count]->RegSet,Normal,1,NULL);
+ continue;
+ }
+ if (JumpInfo[count]->TargetPC != TargetSection[count]->StartPC) {
+ //DisplayError("I need to add more code in GenerateSectionLinkage cause this is going to cause an exception");
+ //_asm int 3
+ }
+ if (TargetSection[count]->CompiledLocation == NULL) {
+ GenerateX86Code(TargetSection[count],GetNewTestValue());
+ } else {
+ //char Label[100];
+
+ SetJump32(JumpInfo[count]->LinkLocation,RecompPos);
+ JumpInfo[count]->LinkLocation = NULL;
+ if (JumpInfo[count]->LinkLocation2 != NULL) {
+ SetJump32(JumpInfo[count]->LinkLocation2,RecompPos);
+ JumpInfo[count]->LinkLocation2 = NULL;
+ }
+ memcpy(&Section->RegWorking,&JumpInfo[count]->RegSet,sizeof(REG_INFO));
+ if (JumpInfo[count]->RegSet.RandomModifier != 0) {
+ SubConstFromVariable(JumpInfo[count]->RegSet.RandomModifier,&CP0[1]);
+ JumpInfo[count]->RegSet.RandomModifier = 0;
+ }
+ if (JumpInfo[count]->RegSet.CycleCount != 0) {
+ AddConstToVariable(JumpInfo[count]->RegSet.CycleCount,&CP0[9]);
+ }
+ if (JumpInfo[count]->TargetPC <= Section->CompilePC) {
+ uint32_t CycleCount = JumpInfo[count]->RegSet.CycleCount;
+ JumpInfo[count]->RegSet.CycleCount = 0;
+
+ if (JumpInfo[count]->PermLoop) {
+ MoveConstToVariable(JumpInfo[count]->TargetPC,&PROGRAM_COUNTER);
+ Pushad();
+ Call_Direct(InPermLoop);
+ Popad();
+ CompileSystemCheck(0,-1,JumpInfo[count]->RegSet);
+ } else {
+ CompileSystemCheck(CycleCount,JumpInfo[count]->TargetPC,JumpInfo[count]->RegSet);
+ }
+ } else {
+ if (JumpInfo[count]->RegSet.CycleCount != 0) {
+ SubConstFromVariable(JumpInfo[count]->RegSet.CycleCount,&Timers->Timer);
+ JumpInfo[count]->RegSet.CycleCount = 0;
+ }
+ }
+ memcpy(&Section->RegWorking, &JumpInfo[count]->RegSet,sizeof(REG_INFO));
+ SyncRegState(Section,&TargetSection[count]->RegStart);
+ //JmpLabel32(Label,0);
+ JmpLabel32(0);
+ SetJump32((uint32_t *)RecompPos - 1,TargetSection[count]->CompiledLocation);
+ }
+ }
+}
+
+
+uint32_t GenerateX86Code (BLOCK_SECTION * Section, uint32_t Test) {
+ int count;
+
+ if (Section == NULL) { return 0; }
+ if (Section->CompiledLocation != NULL) {
+ if (Section->Test == Test) { return 0; }
+ Section->Test = Test;
+ if (GenerateX86Code(Section->ContinueSection,Test)) { return 1; }
+ if (GenerateX86Code(Section->JumpSection,Test)) { return 1; }
+ return 0;
+ }
+ if (Section->ParentSection) {
+ for (count = 0;Section->ParentSection[count] != NULL;count++) {
+ BLOCK_SECTION * Parent;
+
+ Parent = Section->ParentSection[count];
+ if (Parent->CompiledLocation != NULL) { continue; }
+ if (IsAllParentLoops(Section,Parent,1,GetNewTestValue())) { continue; }
+ return 0;
+ }
+ }
+ if (!InheritParentInfo(Section)) { return 0; }
+ Section->CompiledLocation = RecompPos;
+ Section->CompilePC = Section->StartPC;
+ NextInstruction = NORMAL;
+
+#ifdef USEX64
+ MoveConstQwordToX86reg(TLB_Map, x86_R15);
+#endif
+
+ do {
+ //__try {
+ if (!r4300i_LW_VAddr(Section->CompilePC, &Opcode.Hex)) {
+ //DisplayError(GS(MSG_FAIL_LOAD_WORD));
+ //ExitThread(0);
+ StopEmulation();
+ }
+
+ BlockCycleCount += 2;
+
+ BlockRandomModifier += 1;
+
+ for (count = 1; count < 64; count ++) { x86Protected(count) = 0; }
+
+ switch (Opcode.op) {
+ case R4300i_SPECIAL:
+ switch (Opcode.funct) {
+ case R4300i_SPECIAL_SLL: Compile_R4300i_SPECIAL_SLL(Section); break;
+ case R4300i_SPECIAL_SRL: Compile_R4300i_SPECIAL_SRL(Section); break;
+ case R4300i_SPECIAL_SRA: Compile_R4300i_SPECIAL_SRA(Section); break;
+ case R4300i_SPECIAL_SLLV: Compile_R4300i_SPECIAL_SLLV(Section); break;
+ case R4300i_SPECIAL_SRLV: Compile_R4300i_SPECIAL_SRLV(Section); break;
+ case R4300i_SPECIAL_SRAV: Compile_R4300i_SPECIAL_SRAV(Section); break;
+ case R4300i_SPECIAL_JR: Compile_R4300i_SPECIAL_JR(Section); break;
+ case R4300i_SPECIAL_JALR: Compile_R4300i_SPECIAL_JALR(Section); break;
+ case R4300i_SPECIAL_MFLO: Compile_R4300i_SPECIAL_MFLO(Section); break;
+ case R4300i_SPECIAL_SYSCALL: Compile_R4300i_SPECIAL_SYSCALL(Section); break;
+ case R4300i_SPECIAL_BREAK: Compile_R4300i_SPECIAL_BREAK(Section); break;
+ case R4300i_SPECIAL_MTLO: Compile_R4300i_SPECIAL_MTLO(Section); break;
+ case R4300i_SPECIAL_MFHI: Compile_R4300i_SPECIAL_MFHI(Section); break;
+ case R4300i_SPECIAL_MTHI: Compile_R4300i_SPECIAL_MTHI(Section); break;
+ case R4300i_SPECIAL_DSLLV: Compile_R4300i_SPECIAL_DSLLV(Section); break;
+ case R4300i_SPECIAL_DSRLV: Compile_R4300i_SPECIAL_DSRLV(Section); break;
+ case R4300i_SPECIAL_DSRAV: Compile_R4300i_SPECIAL_DSRAV(Section); break;
+ case R4300i_SPECIAL_MULT: Compile_R4300i_SPECIAL_MULT(Section); break;
+ case R4300i_SPECIAL_DIV: Compile_R4300i_SPECIAL_DIV(Section); break;
+ case R4300i_SPECIAL_DIVU: Compile_R4300i_SPECIAL_DIVU(Section); break;
+ case R4300i_SPECIAL_MULTU: Compile_R4300i_SPECIAL_MULTU(Section); break;
+ case R4300i_SPECIAL_DMULT: Compile_R4300i_SPECIAL_DMULT(Section); break;
+ case R4300i_SPECIAL_DMULTU: Compile_R4300i_SPECIAL_DMULTU(Section); break;
+ case R4300i_SPECIAL_DDIV: Compile_R4300i_SPECIAL_DDIV(Section); break;
+ case R4300i_SPECIAL_DDIVU: Compile_R4300i_SPECIAL_DDIVU(Section); break;
+ case R4300i_SPECIAL_ADD: Compile_R4300i_SPECIAL_ADD(Section); break;
+ case R4300i_SPECIAL_ADDU: Compile_R4300i_SPECIAL_ADDU(Section); break;
+ case R4300i_SPECIAL_SUB: Compile_R4300i_SPECIAL_SUB(Section); break;
+ case R4300i_SPECIAL_SUBU: Compile_R4300i_SPECIAL_SUBU(Section); break;
+ case R4300i_SPECIAL_AND: Compile_R4300i_SPECIAL_AND(Section); break;
+ case R4300i_SPECIAL_OR: Compile_R4300i_SPECIAL_OR(Section); break;
+ case R4300i_SPECIAL_XOR: Compile_R4300i_SPECIAL_XOR(Section); break;
+ case R4300i_SPECIAL_NOR: Compile_R4300i_SPECIAL_NOR(Section); break;
+ case R4300i_SPECIAL_SLT: Compile_R4300i_SPECIAL_SLT(Section); break;
+ case R4300i_SPECIAL_SLTU: Compile_R4300i_SPECIAL_SLTU(Section); break;
+ case R4300i_SPECIAL_DADD: Compile_R4300i_SPECIAL_DADD(Section); break;
+ case R4300i_SPECIAL_DADDU: Compile_R4300i_SPECIAL_DADDU(Section); break;
+ case R4300i_SPECIAL_DSUB: Compile_R4300i_SPECIAL_DSUB(Section); break;
+ case R4300i_SPECIAL_DSUBU: Compile_R4300i_SPECIAL_DSUBU(Section); break;
+ case R4300i_SPECIAL_DSLL: Compile_R4300i_SPECIAL_DSLL(Section); break;
+ case R4300i_SPECIAL_DSRL: Compile_R4300i_SPECIAL_DSRL(Section); break;
+ case R4300i_SPECIAL_DSRA: Compile_R4300i_SPECIAL_DSRA(Section); break;
+ case R4300i_SPECIAL_DSLL32: Compile_R4300i_SPECIAL_DSLL32(Section); break;
+ case R4300i_SPECIAL_DSRL32: Compile_R4300i_SPECIAL_DSRL32(Section); break;
+ case R4300i_SPECIAL_DSRA32: Compile_R4300i_SPECIAL_DSRA32(Section); break;
+ default:
+ Compile_R4300i_UnknownOpcode(Section); break;
+ }
+ break;
+ case R4300i_REGIMM:
+ switch (Opcode.rt) {
+ case R4300i_REGIMM_BLTZ:Compile_R4300i_Branch(Section,BLTZ_Compare,BranchTypeRs, 0); break;
+ case R4300i_REGIMM_BGEZ:Compile_R4300i_Branch(Section,BGEZ_Compare,BranchTypeRs, 0); break;
+ case R4300i_REGIMM_BLTZL:Compile_R4300i_BranchLikely(Section,BLTZ_Compare, 0); break;
+ case R4300i_REGIMM_BGEZL:Compile_R4300i_BranchLikely(Section,BGEZ_Compare, 0); break;
+ case R4300i_REGIMM_BLTZAL:Compile_R4300i_Branch(Section,BLTZ_Compare,BranchTypeRs, 1); break;
+ case R4300i_REGIMM_BGEZAL:Compile_R4300i_Branch(Section,BGEZ_Compare,BranchTypeRs, 1); break;
+ default:
+ Compile_R4300i_UnknownOpcode(Section); break;
+ }
+ break;
+ case R4300i_BEQ: Compile_R4300i_Branch(Section,BEQ_Compare,BranchTypeRsRt,0); break;
+ case R4300i_BNE: Compile_R4300i_Branch(Section,BNE_Compare,BranchTypeRsRt,0); break;
+ case R4300i_BGTZ:Compile_R4300i_Branch(Section,BGTZ_Compare,BranchTypeRs,0); break;
+ case R4300i_BLEZ:Compile_R4300i_Branch(Section,BLEZ_Compare,BranchTypeRs,0); break;
+ case R4300i_J: Compile_R4300i_J(Section); break;
+ case R4300i_JAL: Compile_R4300i_JAL(Section); break;
+ case R4300i_ADDI: Compile_R4300i_ADDI(Section); break;
+ case R4300i_ADDIU: Compile_R4300i_ADDIU(Section); break;
+ case R4300i_SLTI: Compile_R4300i_SLTI(Section); break;
+ case R4300i_SLTIU: Compile_R4300i_SLTIU(Section); break;
+ case R4300i_ANDI: Compile_R4300i_ANDI(Section); break;
+ case R4300i_ORI: Compile_R4300i_ORI(Section); break;
+ case R4300i_XORI: Compile_R4300i_XORI(Section); break;
+ case R4300i_LUI: Compile_R4300i_LUI(Section); break;
+ case R4300i_CP0:
+ switch (Opcode.rs) {
+ case R4300i_COP0_MF: Compile_R4300i_COP0_MF(Section); break;
+ case R4300i_COP0_MT: Compile_R4300i_COP0_MT(Section); break;
+ default:
+ if ( (Opcode.rs & 0x10 ) != 0 ) {
+ switch( Opcode.funct ) {
+ case R4300i_COP0_CO_TLBR: Compile_R4300i_COP0_CO_TLBR(Section); break;
+ case R4300i_COP0_CO_TLBWI: Compile_R4300i_COP0_CO_TLBWI(Section); break;
+ case R4300i_COP0_CO_TLBWR: Compile_R4300i_COP0_CO_TLBWR(Section); break;
+ case R4300i_COP0_CO_TLBP: Compile_R4300i_COP0_CO_TLBP(Section); break;
+ case R4300i_COP0_CO_ERET: Compile_R4300i_COP0_CO_ERET(Section); break;
+ default: Compile_R4300i_UnknownOpcode(Section); break;
+ }
+ } else {
+ Compile_R4300i_UnknownOpcode(Section);
+ }
+ }
+ break;
+ case R4300i_CP1:
+ switch (Opcode.rs) {
+ case R4300i_COP1_MF: Compile_R4300i_COP1_MF(Section); break;
+ case R4300i_COP1_DMF: Compile_R4300i_COP1_DMF(Section); break;
+ case R4300i_COP1_CF: Compile_R4300i_COP1_CF(Section); break;
+ case R4300i_COP1_MT: Compile_R4300i_COP1_MT(Section); break;
+ case R4300i_COP1_DMT: Compile_R4300i_COP1_DMT(Section); break;
+ case R4300i_COP1_CT: Compile_R4300i_COP1_CT(Section); break;
+ case R4300i_COP1_BC:
+ switch (Opcode.ft) {
+ case R4300i_COP1_BC_BCF: Compile_R4300i_Branch(Section,COP1_BCF_Compare,BranchTypeCop1,0); break;
+ case R4300i_COP1_BC_BCT: Compile_R4300i_Branch(Section,COP1_BCT_Compare,BranchTypeCop1,0); break;
+ case R4300i_COP1_BC_BCFL: Compile_R4300i_BranchLikely(Section,COP1_BCF_Compare,0); break;
+ case R4300i_COP1_BC_BCTL: Compile_R4300i_BranchLikely(Section,COP1_BCT_Compare,0); break;
+ default:
+ Compile_R4300i_UnknownOpcode(Section); break;
+ }
+ break;
+ case R4300i_COP1_S:
+ switch (Opcode.funct) {
+ case R4300i_COP1_FUNCT_ADD: Compile_R4300i_COP1_S_ADD(Section); break;
+ case R4300i_COP1_FUNCT_SUB: Compile_R4300i_COP1_S_SUB(Section); break;
+ case R4300i_COP1_FUNCT_MUL: Compile_R4300i_COP1_S_MUL(Section); break;
+ case R4300i_COP1_FUNCT_DIV: Compile_R4300i_COP1_S_DIV(Section); break;
+ case R4300i_COP1_FUNCT_ABS: Compile_R4300i_COP1_S_ABS(Section); break;
+ case R4300i_COP1_FUNCT_NEG: Compile_R4300i_COP1_S_NEG(Section); break;
+ case R4300i_COP1_FUNCT_SQRT: Compile_R4300i_COP1_S_SQRT(Section); break;
+ case R4300i_COP1_FUNCT_MOV: Compile_R4300i_COP1_S_MOV(Section); break;
+ case R4300i_COP1_FUNCT_TRUNC_L: Compile_R4300i_COP1_S_TRUNC_L(Section); break;
+ case R4300i_COP1_FUNCT_CEIL_L: Compile_R4300i_COP1_S_CEIL_L(Section); break; //added by Witten
+ case R4300i_COP1_FUNCT_FLOOR_L: Compile_R4300i_COP1_S_FLOOR_L(Section); break; //added by Witten
+ case R4300i_COP1_FUNCT_ROUND_W: Compile_R4300i_COP1_S_ROUND_W(Section); break;
+ case R4300i_COP1_FUNCT_TRUNC_W: Compile_R4300i_COP1_S_TRUNC_W(Section); break;
+ case R4300i_COP1_FUNCT_CEIL_W: Compile_R4300i_COP1_S_CEIL_W(Section); break; //added by Witten
+ case R4300i_COP1_FUNCT_FLOOR_W: Compile_R4300i_COP1_S_FLOOR_W(Section); break;
+ case R4300i_COP1_FUNCT_CVT_D: Compile_R4300i_COP1_S_CVT_D(Section); break;
+ case R4300i_COP1_FUNCT_CVT_W: Compile_R4300i_COP1_S_CVT_W(Section); break;
+ case R4300i_COP1_FUNCT_CVT_L: Compile_R4300i_COP1_S_CVT_L(Section); break;
+ case R4300i_COP1_FUNCT_C_F: case R4300i_COP1_FUNCT_C_UN:
+ case R4300i_COP1_FUNCT_C_EQ: case R4300i_COP1_FUNCT_C_UEQ:
+ case R4300i_COP1_FUNCT_C_OLT: case R4300i_COP1_FUNCT_C_ULT:
+ case R4300i_COP1_FUNCT_C_OLE: case R4300i_COP1_FUNCT_C_ULE:
+ case R4300i_COP1_FUNCT_C_SF: case R4300i_COP1_FUNCT_C_NGLE:
+ case R4300i_COP1_FUNCT_C_SEQ: case R4300i_COP1_FUNCT_C_NGL:
+ case R4300i_COP1_FUNCT_C_LT: case R4300i_COP1_FUNCT_C_NGE:
+ case R4300i_COP1_FUNCT_C_LE: case R4300i_COP1_FUNCT_C_NGT:
+ Compile_R4300i_COP1_S_CMP(Section); break;
+ default:
+ Compile_R4300i_UnknownOpcode(Section); break;
+ }
+ break;
+ case R4300i_COP1_D:
+ switch (Opcode.funct) {
+ case R4300i_COP1_FUNCT_ADD: Compile_R4300i_COP1_D_ADD(Section); break;
+ case R4300i_COP1_FUNCT_SUB: Compile_R4300i_COP1_D_SUB(Section); break;
+ case R4300i_COP1_FUNCT_MUL: Compile_R4300i_COP1_D_MUL(Section); break;
+ case R4300i_COP1_FUNCT_DIV: Compile_R4300i_COP1_D_DIV(Section); break;
+ case R4300i_COP1_FUNCT_ABS: Compile_R4300i_COP1_D_ABS(Section); break;
+ case R4300i_COP1_FUNCT_NEG: Compile_R4300i_COP1_D_NEG(Section); break;
+ case R4300i_COP1_FUNCT_SQRT: Compile_R4300i_COP1_D_SQRT(Section); break;
+ case R4300i_COP1_FUNCT_MOV: Compile_R4300i_COP1_D_MOV(Section); break;
+ case R4300i_COP1_FUNCT_TRUNC_L: Compile_R4300i_COP1_D_TRUNC_L(Section); break; //added by Witten
+ case R4300i_COP1_FUNCT_CEIL_L: Compile_R4300i_COP1_D_CEIL_L(Section); break; //added by Witten
+ case R4300i_COP1_FUNCT_FLOOR_L: Compile_R4300i_COP1_D_FLOOR_L(Section); break; //added by Witten
+ case R4300i_COP1_FUNCT_ROUND_W: Compile_R4300i_COP1_D_ROUND_W(Section); break;
+ case R4300i_COP1_FUNCT_TRUNC_W: Compile_R4300i_COP1_D_TRUNC_W(Section); break;
+ case R4300i_COP1_FUNCT_CEIL_W: Compile_R4300i_COP1_D_CEIL_W(Section); break; //added by Witten
+ case R4300i_COP1_FUNCT_FLOOR_W: Compile_R4300i_COP1_D_FLOOR_W(Section); break; //added by Witten
+ case R4300i_COP1_FUNCT_CVT_S: Compile_R4300i_COP1_D_CVT_S(Section); break;
+ case R4300i_COP1_FUNCT_CVT_W: Compile_R4300i_COP1_D_CVT_W(Section); break;
+ case R4300i_COP1_FUNCT_CVT_L: Compile_R4300i_COP1_D_CVT_L(Section); break;
+ case R4300i_COP1_FUNCT_C_F: case R4300i_COP1_FUNCT_C_UN:
+ case R4300i_COP1_FUNCT_C_EQ: case R4300i_COP1_FUNCT_C_UEQ:
+ case R4300i_COP1_FUNCT_C_OLT: case R4300i_COP1_FUNCT_C_ULT:
+ case R4300i_COP1_FUNCT_C_OLE: case R4300i_COP1_FUNCT_C_ULE:
+ case R4300i_COP1_FUNCT_C_SF: case R4300i_COP1_FUNCT_C_NGLE:
+ case R4300i_COP1_FUNCT_C_SEQ: case R4300i_COP1_FUNCT_C_NGL:
+ case R4300i_COP1_FUNCT_C_LT: case R4300i_COP1_FUNCT_C_NGE:
+ case R4300i_COP1_FUNCT_C_LE: case R4300i_COP1_FUNCT_C_NGT:
+ Compile_R4300i_COP1_D_CMP(Section); break;
+ default:
+ Compile_R4300i_UnknownOpcode(Section); break;
+ }
+ break;
+ case R4300i_COP1_W:
+ switch (Opcode.funct) {
+ case R4300i_COP1_FUNCT_CVT_S: Compile_R4300i_COP1_W_CVT_S(Section); break;
+ case R4300i_COP1_FUNCT_CVT_D: Compile_R4300i_COP1_W_CVT_D(Section); break;
+ default:
+ Compile_R4300i_UnknownOpcode(Section); break;
+ }
+ break;
+ case R4300i_COP1_L:
+ switch (Opcode.funct) {
+ case R4300i_COP1_FUNCT_CVT_S: Compile_R4300i_COP1_L_CVT_S(Section); break;
+ case R4300i_COP1_FUNCT_CVT_D: Compile_R4300i_COP1_L_CVT_D(Section); break;
+ default:
+ Compile_R4300i_UnknownOpcode(Section); break;
+ }
+ break;
+ default:
+ Compile_R4300i_UnknownOpcode(Section); break;
+ }
+ break;
+ case R4300i_BEQL: Compile_R4300i_BranchLikely(Section,BEQ_Compare,0); break;
+ case R4300i_BNEL: Compile_R4300i_BranchLikely(Section,BNE_Compare,0); break;
+ case R4300i_BGTZL:Compile_R4300i_BranchLikely(Section,BGTZ_Compare,0); break;
+ case R4300i_BLEZL:Compile_R4300i_BranchLikely(Section,BLEZ_Compare,0); break;
+ case R4300i_DADDIU: Compile_R4300i_DADDIU(Section); break;
+ case R4300i_LDL: Compile_R4300i_LDL(Section); break;
+ case R4300i_LDR: Compile_R4300i_LDR(Section); break;
+ case R4300i_LB: Compile_R4300i_LB(Section); break;
+ case R4300i_LH: Compile_R4300i_LH(Section); break;
+ case R4300i_LWL: Compile_R4300i_LWL(Section); break;
+ case R4300i_LW: Compile_R4300i_LW(Section); break;
+ case R4300i_LBU: Compile_R4300i_LBU(Section); break;
+ case R4300i_LHU: Compile_R4300i_LHU(Section); break;
+ case R4300i_LWR: Compile_R4300i_LWR(Section); break;
+ case R4300i_LWU: Compile_R4300i_LWU(Section); break; //added by Witten
+ case R4300i_SB: Compile_R4300i_SB(Section); break;
+ case R4300i_SH: Compile_R4300i_SH(Section); break;
+ case R4300i_SWL: Compile_R4300i_SWL(Section); break;
+ case R4300i_SW: Compile_R4300i_SW(Section); break;
+ case R4300i_SWR: Compile_R4300i_SWR(Section); break;
+ case R4300i_SDL: Compile_R4300i_SDL(Section); break;
+ case R4300i_SDR: Compile_R4300i_SDR(Section); break;
+ case R4300i_CACHE: Compile_R4300i_CACHE(Section); break;
+ case R4300i_LL: Compile_R4300i_LL(Section); break;
+ case R4300i_LWC1: Compile_R4300i_LWC1(Section); break;
+ case R4300i_LDC1: Compile_R4300i_LDC1(Section); break;
+ case R4300i_SC: Compile_R4300i_SC(Section); break;
+ case R4300i_LD: Compile_R4300i_LD(Section); break;
+ case R4300i_SWC1: Compile_R4300i_SWC1(Section); break;
+ case R4300i_SDC1: Compile_R4300i_SDC1(Section); break;
+ case R4300i_SD: Compile_R4300i_SD(Section); break;
+ default:
+ Compile_R4300i_UnknownOpcode(Section); break;
+ }
+
+ for (count = 1; count < 64; count ++) { x86Protected(count) = 0; }
+
+ UnMap_AllFPRs(Section);
+
+ if ((Section->CompilePC &0xFFC) == 0xFFC) {
+ if (NextInstruction == DO_DELAY_SLOT) {
+ }
+ if (NextInstruction == NORMAL) {
+ CompileExit (Section->CompilePC + 4,&Section->RegWorking,Normal,1,NULL);
+ NextInstruction = END_BLOCK;
+ }
+ }
+
+ switch (NextInstruction) {
+ case NORMAL:
+ Section->CompilePC += 4;
+ break;
+ case DO_DELAY_SLOT:
+ NextInstruction = DELAY_SLOT;
+ Section->CompilePC += 4;
+ break;
+ case DELAY_SLOT:
+ NextInstruction = DELAY_SLOT_DONE;
+ BlockCycleCount -= 2;
+ BlockRandomModifier -= 1;
+ Section->CompilePC -= 4;
+ break;
+ }
+
+ } while (NextInstruction != END_BLOCK);
+
+ return 1;
+}
+
+uint32_t GetNewTestValue(void) {
+ static uint32_t LastTest = 0;
+ if (LastTest == 0xFFFFFFFF) { LastTest = 0; }
+ LastTest += 1;
+ return LastTest;
+}
+
+void InitilizeRegSet(REG_INFO * RegSet) {
+ int count;
+
+ RegSet->MIPS_RegState[0] = STATE_CONST_32;
+ RegSet->MIPS_RegVal[0].DW = 0;
+ for (count = 1; count < 32; count ++ ) {
+ RegSet->MIPS_RegState[count] = STATE_UNKNOWN;
+ RegSet->MIPS_RegVal[count].DW = 0;
+
+ }
+ for (count = 0; count < 64; count ++ ) {
+ RegSet->x86reg_MappedTo[count] = NotMapped;
+ RegSet->x86reg_Protected[count] = 0;
+ RegSet->x86reg_MapOrder[count] = 0;
+ }
+ RegSet->CycleCount = 0;
+ RegSet->RandomModifier = 0;
+
+ RegSet->Stack_TopPos = 0;
+ for (count = 0; count < 8; count ++ ) {
+ RegSet->x86fpu_MappedTo[count] = -1;
+ RegSet->x86fpu_State[count] = FPU_Unkown;
+ RegSet->x86fpu_RoundingModel[count] = RoundDefault;
+ }
+ RegSet->Fpu_Used = 0;
+ RegSet->RoundingModel = RoundUnknown;
+}
+
+void InheritConstants(BLOCK_SECTION * Section) {
+ int NoOfParents, count;
+ BLOCK_SECTION * Parent;
+ REG_INFO * RegSet;
+
+
+ if (Section->ParentSection == NULL) {
+ InitilizeRegSet(&Section->RegStart);
+ memcpy(&Section->RegWorking,&Section->RegStart,sizeof(REG_INFO));
+ return;
+ }
+
+ Parent = Section->ParentSection[0];
+ RegSet = Section == Parent->ContinueSection?&Parent->Cont.RegSet:&Parent->Jump.RegSet;
+ memcpy(&Section->RegStart,RegSet,sizeof(REG_INFO));
+ memcpy(&Section->RegWorking,&Section->RegStart,sizeof(REG_INFO));
+
+ for (NoOfParents = 1;Section->ParentSection[NoOfParents] != NULL;NoOfParents++) {
+ Parent = Section->ParentSection[NoOfParents];
+ RegSet = Section == Parent->ContinueSection?&Parent->Cont.RegSet:&Parent->Jump.RegSet;
+
+ for (count = 0; count < 32; count++) {
+ if (IsConst(count)) {
+ if (MipsRegState(count) != RegSet->MIPS_RegState[count]) {
+ MipsRegState(count) = STATE_UNKNOWN;
+ } else if (Is32Bit(count) && MipsRegLo(count) != RegSet->MIPS_RegVal[count].UW[0]) {
+ MipsRegState(count) = STATE_UNKNOWN;
+ } else if (Is64Bit(count) && MipsReg(count) != RegSet->MIPS_RegVal[count].UDW) {
+ MipsRegState(count) = STATE_UNKNOWN;
+ }
+ }
+ }
+ }
+ memcpy(&Section->RegStart,&Section->RegWorking,sizeof(REG_INFO));
+}
+
+uint32_t InheritParentInfo (BLOCK_SECTION * Section) {
+ int count, start, NoOfParents, NoOfCompiledParents, FirstParent,CurrentParent;
+ BLOCK_PARENT * SectionParents;
+ BLOCK_SECTION * Parent;
+ JUMP_INFO * JumpInfo;
+ //char Label[100];
+ uint32_t NeedSync;
+
+ DisplaySectionInformation(Section,Section->SectionID,GetNewTestValue());
+
+ if (Section->ParentSection == NULL) {
+ InitilizeRegSet(&Section->RegStart);
+ memcpy(&Section->RegWorking,&Section->RegStart,sizeof(REG_INFO));
+ return 1;
+ }
+
+ NoOfParents = 0;
+ for (count = 0;Section->ParentSection[count] != NULL;count++) {
+ Parent = Section->ParentSection[count];
+ NoOfParents += Parent->JumpSection != Parent->ContinueSection?1:2;
+ }
+
+ if (NoOfParents == 0) {
+ return 0;
+ } else if (NoOfParents == 1) {
+ Parent = Section->ParentSection[0];
+ if (Section == Parent->ContinueSection) { JumpInfo = &Parent->Cont; }
+ else if (Section == Parent->JumpSection) { JumpInfo = &Parent->Jump; }
+ else {
+ }
+
+ memcpy(&Section->RegStart,&JumpInfo->RegSet,sizeof(REG_INFO));
+ if (JumpInfo->LinkLocation != NULL) {
+ SetJump32(JumpInfo->LinkLocation,RecompPos);
+ if (JumpInfo->LinkLocation2 != NULL) {
+ SetJump32(JumpInfo->LinkLocation2,RecompPos);
+ }
+ }
+ memcpy(&Section->RegWorking,&Section->RegStart,sizeof(REG_INFO));
+ return 1;
+ }
+
+ //Multiple Parents
+ for (count = 0, NoOfCompiledParents = 0;Section->ParentSection[count] != NULL;count++) {
+ Parent = Section->ParentSection[count];
+ if (Parent->CompiledLocation != NULL) {
+ NoOfCompiledParents += Parent->JumpSection != Parent->ContinueSection?1:2;
+ }
+ }
+ if (NoOfCompiledParents == 0){ return 0; }
+ SectionParents = (BLOCK_PARENT *)malloc(NoOfParents * sizeof(BLOCK_PARENT));
+
+ for (count = 0, NoOfCompiledParents = 0;Section->ParentSection[count] != NULL;count++) {
+ Parent = Section->ParentSection[count];
+ if (Parent->CompiledLocation == NULL) { continue; }
+ if (Parent->JumpSection != Parent->ContinueSection) {
+ SectionParents[NoOfCompiledParents].Parent = Parent;
+ SectionParents[NoOfCompiledParents].JumpInfo =
+ Section == Parent->ContinueSection?&Parent->Cont:&Parent->Jump;
+ NoOfCompiledParents += 1;
+ } else {
+ SectionParents[NoOfCompiledParents].Parent = Parent;
+ SectionParents[NoOfCompiledParents].JumpInfo = &Parent->Cont;
+ NoOfCompiledParents += 1;
+ SectionParents[NoOfCompiledParents].Parent = Parent;
+ SectionParents[NoOfCompiledParents].JumpInfo = &Parent->Jump;
+ NoOfCompiledParents += 1;
+ }
+ }
+
+ start = NoOfCompiledParents;
+ for (count = 0;Section->ParentSection[count] != NULL;count++) {
+ Parent = Section->ParentSection[count];
+ if (Parent->CompiledLocation != NULL) { continue; }
+ if (Parent->JumpSection != Parent->ContinueSection) {
+ SectionParents[start].Parent = Parent;
+ SectionParents[start].JumpInfo =
+ Section == Parent->ContinueSection?&Parent->Cont:&Parent->Jump;
+ start += 1;
+ } else {
+ SectionParents[start].Parent = Parent;
+ SectionParents[start].JumpInfo = &Parent->Cont;
+ start += 1;
+ SectionParents[start].Parent = Parent;
+ SectionParents[start].JumpInfo = &Parent->Jump;
+ start += 1;
+ }
+ }
+ FirstParent = 0;
+ for (count = 1;count < NoOfCompiledParents;count++) {
+ if (SectionParents[count].JumpInfo->FallThrough) {
+ FirstParent = count; break;
+ }
+ }
+
+ //Link First Parent to start
+ Parent = SectionParents[FirstParent].Parent;
+ JumpInfo = SectionParents[FirstParent].JumpInfo;
+
+ memcpy(&Section->RegWorking,&JumpInfo->RegSet,sizeof(REG_INFO));
+ if (JumpInfo->LinkLocation != NULL) {
+ SetJump32(JumpInfo->LinkLocation,RecompPos);
+ JumpInfo->LinkLocation = NULL;
+ if (JumpInfo->LinkLocation2 != NULL) {
+ SetJump32(JumpInfo->LinkLocation2,RecompPos);
+ JumpInfo->LinkLocation2 = NULL;
+ }
+ }
+ if (BlockRandomModifier != 0) { SubConstFromVariable(BlockRandomModifier,&CP0[1]); }
+ if (BlockCycleCount != 0) {
+ AddConstToVariable(BlockCycleCount,&CP0[9]);
+ SubConstFromVariable(BlockCycleCount,&Timers->Timer);
+ }
+ JumpInfo->FallThrough = 0;
+
+ //Fix up initial state
+ UnMap_AllFPRs(Section);
+ for (count = 0;count < NoOfParents;count++) {
+ int count2, count3;
+ REG_INFO * RegSet;
+
+ if (count == FirstParent) { continue; }
+ Parent = SectionParents[count].Parent;
+ RegSet = &SectionParents[count].JumpInfo->RegSet;
+
+ if (CurrentRoundingModel != RegSet->RoundingModel) { CurrentRoundingModel = RoundUnknown; }
+ if (NoOfParents != NoOfCompiledParents) { CurrentRoundingModel = RoundUnknown; }
+
+ for (count2 = 1; count2 < 32; count2++) {
+ if (Is32BitMapped(count2)) {
+ switch (RegSet->MIPS_RegState[count2]) {
+ case STATE_MAPPED_64: Map_GPR_64bit(Section,count2,count2); break;
+ case STATE_MAPPED_32_ZERO: break;
+ case STATE_MAPPED_32_SIGN:
+ if (IsUnsigned(count2)) {
+ MipsRegState(count2) = STATE_MAPPED_32_SIGN;
+ }
+ break;
+ case STATE_CONST_64: Map_GPR_64bit(Section,count2,count2); break;
+ case STATE_CONST_32:
+ if ((RegSet->MIPS_RegVal[count2].W[0] < 0) && IsUnsigned(count2)) {
+ MipsRegState(count2) = STATE_MAPPED_32_SIGN;
+ }
+ break;
+ case STATE_UNKNOWN:
+ //Map_GPR_32bit(Section,count2,1,count2);
+ Map_GPR_64bit(Section,count2,count2); //??
+ //UnMap_GPR(Section,count2,1); ??
+ break;
+ }
+ }
+ if (IsConst(count2)) {
+ if (MipsRegState(count2) != RegSet->MIPS_RegState[count2]) {
+ if (Is32Bit(count2)) {
+ Map_GPR_32bit(Section,count2,1,count2);
+ } else {
+ Map_GPR_32bit(Section,count2,1,count2);
+ }
+ } else if (Is32Bit(count2) && MipsRegLo(count2) != RegSet->MIPS_RegVal[count2].UW[0]) {
+ Map_GPR_32bit(Section,count2,1,count2);
+ } else if (Is64Bit(count2) && MipsReg(count2) != RegSet->MIPS_RegVal[count2].UDW) {
+ Map_GPR_32bit(Section,count2,1,count2);
+ }
+ }
+ for (count3 = 1; count3 < 64; count3 ++) { x86Protected(count3) = 0; }
+ }
+ }
+ memcpy(&Section->RegStart,&Section->RegWorking,sizeof(REG_INFO));
+
+ //Sync registers for different blocks
+// sprintf(Label,"Section_%d",Section->SectionID);
+ CurrentParent = FirstParent;
+ NeedSync = 0;
+ for (count = 0;count < NoOfCompiledParents;count++) {
+ REG_INFO * RegSet;
+ int count2;
+
+ if (count == FirstParent) { continue; }
+ Parent = SectionParents[count].Parent;
+ JumpInfo = SectionParents[count].JumpInfo;
+ RegSet = &SectionParents[count].JumpInfo->RegSet;
+
+ if (JumpInfo->RegSet.CycleCount != 0) { NeedSync = 1; }
+ if (JumpInfo->RegSet.RandomModifier != 0) { NeedSync = 1; }
+
+ for (count2 = 0; count2 < 8; count2++) {
+ if (FpuMappedTo(count2) == (uint32_t)-1) {
+ NeedSync = 1;
+ }
+ }
+
+ for (count2 = 0; count2 < 32; count2++) {
+ if (NeedSync == 1) { break; }
+ if (MipsRegState(count2) != RegSet->MIPS_RegState[count2]) {
+ NeedSync = 1;
+ continue;
+ }
+ switch (MipsRegState(count2)) {
+ case STATE_UNKNOWN: break;
+ case STATE_MAPPED_64:
+ if (MipsReg(count2) != RegSet->MIPS_RegVal[count2].UDW) {
+ NeedSync = 1;
+ }
+ break;
+ case STATE_MAPPED_32_ZERO:
+ case STATE_MAPPED_32_SIGN:
+ if (MipsRegLo(count2) != RegSet->MIPS_RegVal[count2].UW[0]) {
+ //DisplayError("Parent: %d",Parent->SectionID);
+ NeedSync = 1;
+ }
+ break;
+ case STATE_CONST_32:
+ if (MipsRegLo(count2) != RegSet->MIPS_RegVal[count2].UW[0]) {
+ NeedSync = 1;
+ }
+ break;
+ }
+ }
+ if (NeedSync == 0) { continue; }
+ Parent = SectionParents[CurrentParent].Parent;
+ JumpInfo = SectionParents[CurrentParent].JumpInfo;
+ //JmpLabel32(Label,0);
+ JmpLabel32(0);
+ JumpInfo->LinkLocation = RecompPos - 4;
+ JumpInfo->LinkLocation2 = NULL;
+
+ CurrentParent = count;
+ Parent = SectionParents[CurrentParent].Parent;
+ JumpInfo = SectionParents[CurrentParent].JumpInfo;
+ if (JumpInfo->LinkLocation != NULL) {
+ SetJump32(JumpInfo->LinkLocation,RecompPos);
+ JumpInfo->LinkLocation = NULL;
+ if (JumpInfo->LinkLocation2 != NULL) {
+ SetJump32(JumpInfo->LinkLocation2,RecompPos);
+ JumpInfo->LinkLocation2 = NULL;
+ }
+ }
+ memcpy(&Section->RegWorking,&JumpInfo->RegSet,sizeof(REG_INFO));
+ if (BlockRandomModifier != 0) { SubConstFromVariable(BlockRandomModifier,&CP0[1]); }
+ if (BlockCycleCount != 0) {
+ AddConstToVariable(BlockCycleCount,&CP0[9]);
+ SubConstFromVariable(BlockCycleCount,&Timers->Timer);
+ }
+ SyncRegState(Section,&Section->RegStart); //Sync
+ memcpy(&Section->RegStart,&Section->RegWorking,sizeof(REG_INFO));
+
+ }
+
+ for (count = 0;count < NoOfCompiledParents;count++) {
+ Parent = SectionParents[count].Parent;
+ JumpInfo = SectionParents[count].JumpInfo;
+
+ if (JumpInfo->LinkLocation != NULL) {
+ SetJump32(JumpInfo->LinkLocation,RecompPos);
+ JumpInfo->LinkLocation = NULL;
+ if (JumpInfo->LinkLocation2 != NULL) {
+ SetJump32(JumpInfo->LinkLocation2,RecompPos);
+ JumpInfo->LinkLocation2 = NULL;
+ }
+ }
+ }
+
+ BlockCycleCount = 0;
+ BlockRandomModifier = 0;
+ free(SectionParents);
+ SectionParents = NULL;
+ return 1;
+}
+
+uint32_t IsAllParentLoops(BLOCK_SECTION * Section, BLOCK_SECTION * Parent, uint32_t IgnoreIfCompiled, uint32_t Test) {
+ int count;
+
+ if (IgnoreIfCompiled && Parent->CompiledLocation != NULL) { return 1; }
+ if (!Section->InLoop) { return 0; }
+ if (!Parent->InLoop) { return 0; }
+ if (Parent->ParentSection == NULL) { return 0; }
+ if (Section == Parent) { return 1; }
+ if (Parent->Test == Test) { return 1; }
+ Parent->Test = Test;
+
+ for (count = 0;Parent->ParentSection[count] != NULL;count++) {
+ if (!IsAllParentLoops(Section,Parent->ParentSection[count],IgnoreIfCompiled,Test)) { return 0; }
+ }
+ return 1;
+}
+
+void InitilzeSection (BLOCK_SECTION * Section, BLOCK_SECTION * Parent, uint32_t StartAddr, uint32_t ID) {
+ Section->ParentSection = NULL;
+ Section->JumpSection = NULL;
+ Section->ContinueSection = NULL;
+ Section->CompiledLocation = NULL;
+
+ Section->SectionID = ID;
+ Section->Test = 0;
+ Section->Test2 = 0;
+ Section->InLoop = 0;
+
+ Section->StartPC = StartAddr;
+ Section->CompilePC = Section->StartPC;
+
+ Section->Jump.LinkLocation = NULL;
+ Section->Jump.LinkLocation2 = NULL;
+ Section->Jump.FallThrough = 0;
+ Section->Jump.PermLoop = 0;
+ Section->Jump.TargetPC = (uint32_t)-1;
+ Section->Cont.LinkLocation = NULL;
+ Section->Cont.LinkLocation2 = NULL;
+ Section->Cont.FallThrough = 0;
+ Section->Cont.PermLoop = 0;
+ Section->Cont.TargetPC = (uint32_t)-1;
+
+ AddParent(Section,Parent);
+}
+
+void MarkCodeBlock (uint32_t PAddr) {
+ if (PAddr < RdramSize) {
+ N64_Blocks.NoOfRDRamBlocks[PAddr >> 12] += 1;
+ } else if (PAddr >= 0x04000000 && PAddr <= 0x04000FFC) {
+ N64_Blocks.NoOfDMEMBlocks += 1;
+ } else if (PAddr >= 0x04001000 && PAddr <= 0x04001FFC) {
+ N64_Blocks.NoOfIMEMBlocks += 1;
+ } else if (PAddr >= 0x1FC00000 && PAddr <= 0x1FC00800) {
+ N64_Blocks.NoOfPifRomBlocks += 1;
+ } else {
+ }
+}
+
+extern uint8_t * MemChunk;
+
+void CallBlock(void (*block)(void)) {
+
+#ifdef USEX64
+ // Make sure the Memory block pointer is in register R15
+ __asm__ __volatile__("mov %%rax, %%r15" : : "a"(MemChunk));
+ __asm__ __volatile__("pushq %rbx");
+ __asm__ __volatile__("pushq %rcx");
+ __asm__ __volatile__("pushq %rdx");
+ __asm__ __volatile__("pushq %r9");
+ __asm__ __volatile__("pushq %r10");
+ __asm__ __volatile__("pushq %r11");
+ __asm__ __volatile__("pushq %r12");
+ __asm__ __volatile__("pushq %r13");
+ __asm__ __volatile__("pushq %r14");
+ __asm__ __volatile__("pushq %r15");
+
+ block();
+
+ __asm__ __volatile__("popq %r15");
+ __asm__ __volatile__("popq %r14");
+ __asm__ __volatile__("popq %r13");
+ __asm__ __volatile__("popq %r12");
+ __asm__ __volatile__("popq %r11");
+ __asm__ __volatile__("popq %r10");
+ __asm__ __volatile__("popq %r9");
+ __asm__ __volatile__("popq %rdx");
+ __asm__ __volatile__("popq %rcx");
+ __asm__ __volatile__("popq %rbx");
+#else
+ __asm__ __volatile__("pusha");
+ block();
+ __asm__ __volatile__("popa");
+#endif
+
+}
+//#include <windows.h>
+//int r4300i_CPU_MemoryFilter64( DWORD dwExptCode, LPEXCEPTION_POINTERS lpEP);
+
+uint32_t lastgood = 0;
+
+
+void StartRecompilerCPU (void ) {
+ uintptr_t Addr;
+ void (*Block)(void) = 0;
+
+ InitExceptionHandler();
+
+ ResetRecompCode();
+ memset(&N64_Blocks,0,sizeof(N64_Blocks));
+ NextInstruction = NORMAL;
+
+ //__try {
+
+ //for (;;) {
+ while(cpu_running == 1) {
+
+ if(PROGRAM_COUNTER < 0x90000000)
+ lastgood = PROGRAM_COUNTER;
+ Addr = PROGRAM_COUNTER;
+ if (!TranslateVaddr(&Addr)) {
+ DoTLBMiss(NextInstruction == DELAY_SLOT,PROGRAM_COUNTER);
+ NextInstruction = NORMAL;
+ Addr = PROGRAM_COUNTER;
+ if (!TranslateVaddr(&Addr)) {
+ StopEmulation();
+ }
+ }
+ if (NextInstruction == DELAY_SLOT) {
+ Block = *(DelaySlotTable + (Addr >> 12));
+
+ if (Block == NULL) {
+ Block = CompileDelaySlot();
+
+ *(DelaySlotTable + (Addr >> 12)) = Block;
+
+ NextInstruction = NORMAL;
+ }
+
+ CallBlock(Block);
+
+ continue;
+ }
+
+
+ if (Addr > 0x10000000)
+ {
+ if (PROGRAM_COUNTER >= 0xB0000000 && PROGRAM_COUNTER < (RomFileSize | 0xB0000000)) {
+ while (PROGRAM_COUNTER >= 0xB0000000 && PROGRAM_COUNTER < (RomFileSize | 0xB0000000)) {
+ ExecuteInterpreterOpCode();
+ }
+ continue;
+ } else {
+
+ StopEmulation();
+ }
+ }
+
+ Block = *(JumpTable + (Addr >> 2));
+
+
+ if (Block == NULL) {
+ Block = Compiler4300iBlock();
+
+ *(JumpTable + (Addr >> 2)) = Block;
+
+ NextInstruction = NORMAL;
+ }
+
+
+ CallBlock(Block);
+ }
+
+ cpu_stopped = 1;
+}
+
+
+void SyncRegState (BLOCK_SECTION * Section, REG_INFO * SyncTo) {
+ int count, x86Reg,x86RegHi, changed;
+
+ changed = 0;
+ UnMap_AllFPRs(Section);
+ if (CurrentRoundingModel != SyncTo->RoundingModel) { CurrentRoundingModel = RoundUnknown; }
+
+ for (count = 1; count < 32; count ++) {
+ if (MipsRegState(count) == SyncTo->MIPS_RegState[count]) {
+ switch (MipsRegState(count)) {
+ case STATE_UNKNOWN: continue;
+ case STATE_MAPPED_64:
+ if (MipsReg(count) == SyncTo->MIPS_RegVal[count].UDW) {
+ continue;
+ }
+ break;
+ case STATE_MAPPED_32_ZERO:
+ case STATE_MAPPED_32_SIGN:
+ if (MipsRegLo(count) == SyncTo->MIPS_RegVal[count].UW[0]) {
+ continue;
+ }
+ break;
+ case STATE_CONST_64:
+ if (MipsReg(count) != SyncTo->MIPS_RegVal[count].UDW) {
+ }
+ continue;
+ case STATE_CONST_32:
+ if (MipsRegLo(count) != SyncTo->MIPS_RegVal[count].UW[0]) {
+ }
+ continue;
+ }
+ }
+ changed = 1;
+
+ switch (SyncTo->MIPS_RegState[count]) {
+ case STATE_UNKNOWN: UnMap_GPR(Section,count,1); break;
+ case STATE_MAPPED_64:
+ x86Reg = SyncTo->MIPS_RegVal[count].UW[0];
+ x86RegHi = SyncTo->MIPS_RegVal[count].UW[1];
+ UnMap_X86reg(Section,x86Reg);
+ UnMap_X86reg(Section,x86RegHi);
+ switch (MipsRegState(count)) {
+ case STATE_UNKNOWN:
+ MoveVariableToX86reg(&GPR[count].UW[0],x86Reg);
+ MoveVariableToX86reg(&GPR[count].UW[1],x86RegHi);
+ break;
+ case STATE_MAPPED_64:
+ MoveX86RegToX86Reg(MipsRegLo(count),x86Reg);
+ x86Mapped(MipsRegLo(count)) = NotMapped;
+ MoveX86RegToX86Reg(MipsRegHi(count),x86RegHi);
+ x86Mapped(MipsRegHi(count)) = NotMapped;
+ break;
+ case STATE_MAPPED_32_SIGN:
+ MoveX86RegToX86Reg(MipsRegLo(count),x86RegHi);
+ ShiftRightSignImmed(x86RegHi,31);
+ MoveX86RegToX86Reg(MipsRegLo(count),x86Reg);
+ x86Mapped(MipsRegLo(count)) = NotMapped;
+ break;
+ case STATE_MAPPED_32_ZERO:
+ XorX86RegToX86Reg(x86RegHi,x86RegHi);
+ MoveX86RegToX86Reg(MipsRegLo(count),x86Reg);
+ x86Mapped(MipsRegLo(count)) = NotMapped;
+ break;
+ case STATE_CONST_64:
+ MoveConstToX86reg(MipsRegHi(count),x86RegHi);
+ MoveConstToX86reg(MipsRegLo(count),x86Reg);
+ break;
+ case STATE_CONST_32:
+ MoveConstToX86reg(MipsRegLo_S(count) >> 31,x86RegHi);
+ MoveConstToX86reg(MipsRegLo(count),x86Reg);
+ break;
+ default:
+ continue;
+ }
+ MipsRegLo(count) = x86Reg;
+ MipsRegHi(count) = x86RegHi;
+ MipsRegState(count) = STATE_MAPPED_64;
+ x86Mapped(x86Reg) = GPR_Mapped;
+ x86Mapped(x86RegHi) = GPR_Mapped;
+ x86MapOrder(x86Reg) = 1;
+ x86MapOrder(x86RegHi) = 1;
+ break;
+ case STATE_MAPPED_32_SIGN:
+ x86Reg = SyncTo->MIPS_RegVal[count].UW[0];
+ UnMap_X86reg(Section,x86Reg);
+ switch (MipsRegState(count)) {
+ case STATE_UNKNOWN: MoveVariableToX86reg(&GPR[count].UW[0],x86Reg); break;
+ case STATE_CONST_32: MoveConstToX86reg(MipsRegLo(count),x86Reg); break;
+ case STATE_MAPPED_32_SIGN:
+ MoveX86RegToX86Reg(MipsRegLo(count),x86Reg);
+ x86Mapped(MipsRegLo(count)) = NotMapped;
+ break;
+ case STATE_MAPPED_32_ZERO:
+ if (MipsRegLo(count) != (uint32_t)x86Reg) {
+ MoveX86RegToX86Reg(MipsRegLo(count),x86Reg);
+ x86Mapped(MipsRegLo(count)) = NotMapped;
+ }
+ break;
+ case STATE_MAPPED_64:
+ MoveX86RegToX86Reg(MipsRegLo(count),x86Reg);
+ x86Mapped(MipsRegLo(count)) = NotMapped;
+ x86Mapped(MipsRegHi(count)) = NotMapped;
+ break;
+ }
+ MipsRegLo(count) = x86Reg;
+ MipsRegState(count) = STATE_MAPPED_32_SIGN;
+ x86Mapped(x86Reg) = GPR_Mapped;
+ x86MapOrder(x86Reg) = 1;
+ break;
+ case STATE_MAPPED_32_ZERO:
+ x86Reg = SyncTo->MIPS_RegVal[count].UW[0];
+ UnMap_X86reg(Section,x86Reg);
+ switch (MipsRegState(count)) {
+ case STATE_MAPPED_64:
+ case STATE_UNKNOWN:
+ MoveVariableToX86reg(&GPR[count].UW[0],x86Reg);
+ break;
+ case STATE_MAPPED_32_ZERO:
+ MoveX86RegToX86Reg(MipsRegLo(count),x86Reg);
+ x86Mapped(MipsRegLo(count)) = NotMapped;
+ break;
+ case STATE_CONST_32:
+ if (MipsRegLo_S(count) < 0) {
+ }
+ MoveConstToX86reg(MipsRegLo(count),x86Reg);
+ break;
+ }
+ MipsRegLo(count) = x86Reg;
+ MipsRegState(count) = SyncTo->MIPS_RegState[count];
+ x86Mapped(x86Reg) = GPR_Mapped;
+ x86MapOrder(x86Reg) = 1;
+ break;
+ default:
+ changed = 0;
+ }
+ }
+}
diff --git a/src/usf/recompiler_cpu.h b/src/usf/recompiler_cpu.h new file mode 100644 index 0000000..fd1aa77 --- /dev/null +++ b/src/usf/recompiler_cpu.h @@ -0,0 +1,240 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+#ifndef _RECOMPILER_CPU_H_
+#define _RECOMPILER_CPU_H_
+
+#include "types.h"
+
+#pragma pack(push,1)
+
+#define MaxCodeBlocks 50000
+#define MaxOrigMem 65000
+
+#define NotMapped 0
+#define GPR_Mapped 1
+#define Temp_Mapped 2
+#define Stack_Mapped 3
+
+#define BranchTypeCop1 0
+#define BranchTypeRs 1
+#define BranchTypeRsRt 2
+
+//Exit Block Methods
+#define Normal 0
+#define Normal_NoSysCheck 1
+#define DoCPU_Action 2
+#define COP1_Unuseable 3
+#define DoSysCall 4
+#define TLBReadMiss 5
+#define ExitResetRecompCode 6
+#define DoBreak 7
+
+#define STATE_KNOWN_VALUE 1
+//#define STATE_UNKNOW_VALUE
+
+#define STATE_X86_MAPPED 2
+//#define STATE_CONST
+
+#define STATE_SIGN 4
+//#define STATE_ZERO
+
+#define STATE_32BIT 8
+//#define STATE_64BIT
+
+#define STATE_UNKNOWN 0
+
+//STATE_MAPPED_64 = 3;
+//STATE_MAPPED_32_ZERO = 11
+//STATE_MAPPED_32_SIGN = 15
+#define STATE_MAPPED_64 (STATE_KNOWN_VALUE | STATE_X86_MAPPED)
+#define STATE_MAPPED_32_ZERO (STATE_KNOWN_VALUE | STATE_X86_MAPPED | STATE_32BIT)
+#define STATE_MAPPED_32_SIGN (STATE_KNOWN_VALUE | STATE_X86_MAPPED | STATE_32BIT | STATE_SIGN)
+
+//STATE_CONST_64 = 1
+//STATE_CONST_32 = 13
+#define STATE_CONST_64 (STATE_KNOWN_VALUE)
+#define STATE_CONST_32 (STATE_KNOWN_VALUE | STATE_32BIT | STATE_SIGN)
+
+#define IsKnown(Reg) ((MipsRegState(Reg) & STATE_KNOWN_VALUE) != 0)
+#define IsUnknown(Reg) (!IsKnown(Reg))
+
+#define IsMapped(Reg) (IsKnown(Reg) && (MipsRegState(Reg) & STATE_X86_MAPPED) != 0)
+#define IsConst(Reg) (IsKnown(Reg) && !IsMapped(Reg))
+
+#define IsSigned(Reg) (IsKnown(Reg) && (MipsRegState(Reg) & STATE_SIGN) != 0)
+#define IsUnsigned(Reg) (IsKnown(Reg) && !IsSigned(Reg))
+
+#define Is32Bit(Reg) (IsKnown(Reg) && (MipsRegState(Reg) & STATE_32BIT) != 0)
+#define Is64Bit(Reg) (IsKnown(Reg) && !Is32Bit(Reg))
+
+#define Is32BitMapped(Reg) (Is32Bit(Reg) && (MipsRegState(Reg) & STATE_X86_MAPPED) != 0)
+#define Is64BitMapped(Reg) (Is64Bit(Reg) && !Is32BitMapped(Reg))
+
+#define MipsRegState(Reg) Section->RegWorking.MIPS_RegState[Reg]
+#define MipsReg(Reg) Section->RegWorking.MIPS_RegVal[Reg].UDW
+#define MipsReg_S(Reg) Section->RegWorking.MIPS_RegVal[Reg].DW
+#define MipsRegLo(Reg) Section->RegWorking.MIPS_RegVal[Reg].UW[0]
+#define MipsRegLo_S(Reg) Section->RegWorking.MIPS_RegVal[Reg].W[0]
+#define MipsRegHi(Reg) Section->RegWorking.MIPS_RegVal[Reg].UW[1]
+#define MipsRegHi_S(Reg) Section->RegWorking.MIPS_RegVal[Reg].W[1]
+
+#define x86MapOrder(Reg) Section->RegWorking.x86reg_MapOrder[Reg]
+#define x86Protected(Reg) Section->RegWorking.x86reg_Protected[Reg]
+#define x86Mapped(Reg) Section->RegWorking.x86reg_MappedTo[Reg]
+
+#define BlockCycleCount Section->RegWorking.CycleCount
+#define BlockRandomModifier Section->RegWorking.RandomModifier
+
+
+#define StackTopPos Section->RegWorking.Stack_TopPos
+#define FpuMappedTo(Reg) Section->RegWorking.x86fpu_MappedTo[Reg]
+#define FpuState(Reg) Section->RegWorking.x86fpu_State[Reg]
+#define FpuRoundingModel(Reg) Section->RegWorking.x86fpu_RoundingModel[Reg]
+#define FpuBeenUsed Section->RegWorking.Fpu_Used
+#define CurrentRoundingModel Section->RegWorking.RoundingModel
+
+typedef struct {
+ //r4k
+ int32_t MIPS_RegState[32];
+ MIPS_DWORD MIPS_RegVal[32];
+
+ uint32_t x86reg_MappedTo[64];
+ uint32_t x86reg_MapOrder[64];
+ uint32_t x86reg_Protected[64];
+
+ uint32_t CycleCount;
+ uint32_t RandomModifier;
+
+ //FPU
+ uint32_t Stack_TopPos;
+ uint32_t x86fpu_MappedTo[16];
+ uint32_t x86fpu_State[16];
+ uint32_t x86fpu_RoundingModel[16];
+
+ uint32_t Fpu_Used;
+ uint32_t RoundingModel;
+} REG_INFO;
+
+typedef struct {
+ uint32_t TargetPC;
+ //uint8_t * BranchLabel;
+ uint8_t * LinkLocation;
+ uint8_t * LinkLocation2;
+ uint32_t FallThrough;
+ uint32_t PermLoop;
+ uint32_t DoneDelaySlot;
+ REG_INFO RegSet;
+} JUMP_INFO;
+
+typedef struct {
+ /* Block Connection info */
+ void ** ParentSection;
+ void * ContinueSection;
+ void * JumpSection;
+ uint8_t * CompiledLocation;
+
+
+ uint32_t SectionID;
+ uint32_t Test;
+ uint32_t Test2;
+ uint32_t InLoop;
+
+ uint32_t StartPC;
+ uint32_t CompilePC;
+
+ /* Register Info */
+ REG_INFO RegStart;
+ REG_INFO RegWorking;
+
+ /* Jump Info */
+ JUMP_INFO Jump;
+ JUMP_INFO Cont;
+} BLOCK_SECTION;
+
+typedef struct {
+ BLOCK_SECTION * Parent;
+ JUMP_INFO * JumpInfo;
+} BLOCK_PARENT;
+
+typedef struct {
+ uint32_t TargetPC;
+ REG_INFO ExitRegSet;
+ int32_t reason;
+ int32_t NextInstruction;
+ uint8_t * JumpLoc; //32bit jump
+} EXIT_INFO;
+
+typedef struct {
+ uint32_t StartVAddr;
+ uint8_t * CompiledLocation;
+ int32_t NoOfSections;
+ BLOCK_SECTION BlockInfo;
+ EXIT_INFO ** ExitInfo;
+ int32_t ExitCount;
+} BLOCK_INFO;
+
+typedef struct {
+ void * CodeBlock;
+ QWORD OriginalMemory;
+} TARGET_INFO;
+
+typedef struct {
+ uint32_t PAddr;
+ uint32_t VAddr;
+ uint32_t OriginalValue;
+ void * CompiledLocation;
+} ORIGINAL_MEMMARKER;
+
+typedef struct {
+ uint32_t NoOfRDRamBlocks[2048];
+ uint32_t NoOfDMEMBlocks;
+ uint32_t NoOfIMEMBlocks;
+ uint32_t NoOfPifRomBlocks;
+} N64_Blocks_t;
+
+extern N64_Blocks_t N64_Blocks;
+
+#pragma pack(pop)
+
+uint8_t *Compiler4300iBlock ( void );
+uint8_t *CompileDelaySlot ( void );
+void CompileExit ( uint32_t TargetPC, REG_INFO * ExitRegSet, int32_t reason, int32_t CompileNow, void (*x86Jmp)(uintptr_t Value));
+void CompileSystemCheck ( uint32_t TimerModifier, uint32_t TargetPC, REG_INFO RegSet );
+void FixRandomReg ( void );
+void FreeSection ( BLOCK_SECTION * Section, BLOCK_SECTION * Parent);
+void StartRecompilerCPU ( void );
+void GenerateSectionLinkage ( BLOCK_SECTION * Section );
+void InitilizeInitialCompilerVariable ( void);
+int UnMap_TempRegSet (REG_INFO * RegWorking);
+
+extern uint32_t * TLBLoadAddress, TargetIndex;
+extern TARGET_INFO * TargetInfo;
+extern uint16_t FPU_RoundingMode;
+
+#define SetJump32(Loc,JumpLoc) *(uint32_t *)(Loc)= (uint32_t)(((uint32_t)(JumpLoc)) - (((uint32_t)(Loc)) + 4));
+#define SetJump8(Loc,JumpLoc) *(uint8_t *)(Loc)= (uint8_t )(((uint8_t )(JumpLoc)) - (((uint8_t )(Loc)) + 1));
+
+#endif
diff --git a/src/usf/recompiler_fpu_ops.c b/src/usf/recompiler_fpu_ops.c new file mode 100644 index 0000000..8411dcc --- /dev/null +++ b/src/usf/recompiler_fpu_ops.c @@ -0,0 +1,1089 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+
+#include "main.h"
+#include "cpu.h"
+#include "x86.h"
+#include "types.h"
+
+uint16_t FPU_RoundingMode = 0x0000;//_RC_NEAR
+char Name[50];
+
+void ChangeDefaultRoundingModel (void) {
+ switch((FPCR[31] & 3)) {
+ case 0: FPU_RoundingMode = 0x0000; break; //_RC_NEAR
+ case 1: FPU_RoundingMode = 0x0C00; break; //_RC_CHOP
+ case 2: FPU_RoundingMode = 0x0800; break; //_RC_UP
+ case 3: FPU_RoundingMode = 0x0400; break; //_RC_UP
+ }
+}
+
+void CompileCop1Test (BLOCK_SECTION * Section) {
+ if (FpuBeenUsed) { return; }
+ TestVariable(STATUS_CU1,&STATUS_REGISTER);
+ CompileExit(Section->CompilePC,&Section->RegWorking,COP1_Unuseable,0,JeLabel32);
+ FpuBeenUsed = 1;
+}
+
+/********************** Load/store functions ************************/
+void Compile_R4300i_LWC1 (BLOCK_SECTION * Section) {
+ uint32_t TempReg1, TempReg2, TempReg3;
+ CompileCop1Test(Section);
+ if ((Opcode.ft & 1) != 0) {
+ if (RegInStack(Section,Opcode.ft-1,FPU_Double) || RegInStack(Section,Opcode.ft-1,FPU_Qword)) {
+ UnMap_FPR(Section,Opcode.ft-1,1);
+ }
+ }
+ if (RegInStack(Section,Opcode.ft,FPU_Double) || RegInStack(Section,Opcode.ft,FPU_Qword)) {
+ UnMap_FPR(Section,Opcode.ft,1);
+ } else {
+ UnMap_FPR(Section,Opcode.ft,0);
+ }
+ if (IsConst(Opcode.base)) {
+ uint32_t Address = MipsRegLo(Opcode.base) + (short)Opcode.offset;
+
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ Compile_LW(TempReg1,Address);
+
+ TempReg2 = Map_TempReg(Section,x86_Any,-1,0);
+ MovePointerToX86reg(&FPRFloatLocation[Opcode.ft],TempReg2);
+ MoveX86regToX86Pointer(TempReg1,TempReg2);
+ return;
+ }
+ if (IsMapped(Opcode.base) && Opcode.offset == 0) {
+ ProtectGPR(Section,Opcode.base);
+ TempReg1 = MipsRegLo(Opcode.base);
+
+ } else {
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ UnProtectGPR(Section,Opcode.base);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+ }
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+ CompileReadTLBMiss(Section,TempReg1,TempReg2);
+
+ TempReg3 = Map_TempReg(Section,x86_Any,-1,0);
+ MoveX86regPointerToX86reg(TempReg1, TempReg2,TempReg3);
+
+ MovePointerToX86reg(&FPRFloatLocation[Opcode.ft],TempReg2);
+ MoveX86regToX86Pointer(TempReg3,TempReg2);
+}
+
+void Compile_R4300i_LDC1 (BLOCK_SECTION * Section) {
+ uint32_t TempReg1, TempReg2, TempReg3;
+
+
+
+ CompileCop1Test(Section);
+
+ UnMap_FPR(Section,Opcode.ft,0);
+ if (IsConst(Opcode.base)) {
+ uint32_t Address = MipsRegLo(Opcode.base) + (short)Opcode.offset;
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ Compile_LW(TempReg1,Address);
+
+ TempReg2 = Map_TempReg(Section,x86_Any,-1,0);
+ MovePointerToX86reg(&FPRDoubleLocation[Opcode.ft],TempReg2);
+ AddConstToX86Reg(TempReg2 | x64_Reg,4);
+ MoveX86regToX86Pointer(TempReg1,TempReg2);
+
+ Compile_LW(TempReg1,Address + 4);
+ MovePointerToX86reg(&FPRDoubleLocation[Opcode.ft],TempReg2);
+ MoveX86regToX86Pointer(TempReg1,TempReg2);
+ return;
+ }
+ if (IsMapped(Opcode.base) && Opcode.offset == 0) {
+ ProtectGPR(Section,Opcode.base);
+ TempReg1 = MipsRegLo(Opcode.base);
+
+ } else {
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+ }
+
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+ CompileReadTLBMiss(Section,TempReg1,TempReg2);
+ TempReg3 = Map_TempReg(Section,x86_Any,-1,0);
+ MoveX86regPointerToX86reg(TempReg1, TempReg2,TempReg3);
+ Push(TempReg2);
+ MoveVariableToX86reg(&FPRDoubleLocation[Opcode.ft],TempReg2 | x64_Reg);
+ AddConstToX86Reg(TempReg2 | x64_Reg,4);
+ MoveX86regToX86Pointer(TempReg3,TempReg2);
+ Pop(TempReg2);
+ MoveX86regPointerToX86regDisp8(TempReg1, TempReg2,TempReg3,4);
+ MoveVariableToX86reg(&FPRDoubleLocation[Opcode.ft],TempReg2 | x64_Reg);
+ MoveX86regToX86Pointer(TempReg3,TempReg2);
+
+}
+
+void Compile_R4300i_SWC1 (BLOCK_SECTION * Section){
+ uint32_t TempReg1, TempReg2, TempReg3;
+
+
+
+ CompileCop1Test(Section);
+
+ if (IsConst(Opcode.base)) {
+ uint32_t Address = MipsRegLo(Opcode.base) + (short)Opcode.offset;
+
+ UnMap_FPR(Section,Opcode.ft,1);
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+
+ MovePointerToX86reg(&FPRFloatLocation[Opcode.ft],TempReg1);
+ MoveX86PointerToX86reg(TempReg1,TempReg1);
+ Compile_SW_Register(TempReg1, Address);
+ return;
+ }
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+ //For tlb miss
+ //0041C522 85 C0 test eax,eax
+ //0041C524 75 01 jne 0041C527
+
+ UnMap_FPR(Section,Opcode.ft,1);
+ TempReg3 = Map_TempReg(Section,x86_Any,-1,0);
+
+ MovePointerToX86reg(&FPRFloatLocation[Opcode.ft],TempReg3);
+ MoveX86PointerToX86reg(TempReg3,TempReg3);
+ MoveX86regToX86regPointer(TempReg3,TempReg1, TempReg2);
+
+}
+
+void Compile_R4300i_SDC1 (BLOCK_SECTION * Section){
+ uint32_t TempReg1, TempReg2, TempReg3;
+
+ CompileCop1Test(Section);
+
+
+
+ if (IsConst(Opcode.base)) {
+ uint32_t Address = MipsRegLo(Opcode.base) + (short)Opcode.offset;
+
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+
+ MovePointerToX86reg((uint8_t *)&FPRDoubleLocation[Opcode.ft],TempReg1);
+ AddConstToX86Reg(TempReg1 | x64_Reg,4);
+ MoveX86PointerToX86reg(TempReg1,TempReg1);
+ Compile_SW_Register(TempReg1, Address);
+
+
+ MovePointerToX86reg(&FPRDoubleLocation[Opcode.ft],TempReg1);
+ MoveX86PointerToX86reg(TempReg1,TempReg1);
+ Compile_SW_Register(TempReg1, Address + 4);
+ return;
+ }
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+ //For tlb miss
+ //0041C522 85 C0 test eax,eax
+ //0041C524 75 01 jne 0041C527
+
+ TempReg3 = Map_TempReg(Section,x86_Any,-1,0);
+
+ MoveVariableToX86reg((uint8_t *)&FPRDoubleLocation[Opcode.ft],TempReg3 | x64_Reg);
+
+ AddConstToX86Reg(TempReg3 | x64_Reg,4);
+ MoveX86PointerToX86reg(TempReg3,TempReg3);
+ MoveX86regToX86regPointer(TempReg3,TempReg1, TempReg2);
+ AddConstToX86Reg(TempReg1,4);
+
+
+ MovePointerToX86reg((uint8_t *)&FPRDoubleLocation[Opcode.ft],TempReg3);
+ MoveX86PointerToX86reg(TempReg3,TempReg3);
+ MoveX86regToX86regPointer(TempReg3,TempReg1, TempReg2);
+
+
+}
+
+/************************** COP1 functions **************************/
+void Compile_R4300i_COP1_MF (BLOCK_SECTION * Section) {
+ uint32_t TempReg;
+
+
+ CompileCop1Test(Section);
+
+ UnMap_FPR(Section,Opcode.fs,1);
+ Map_GPR_32bit(Section,Opcode.rt, 1, -1);
+ TempReg = Map_TempReg(Section,x86_Any,-1,0);
+
+
+ MovePointerToX86reg((uint8_t *)&FPRFloatLocation[Opcode.fs],TempReg);
+ MoveX86PointerToX86reg(MipsRegLo(Opcode.rt),TempReg);
+}
+
+void Compile_R4300i_COP1_DMF (BLOCK_SECTION * Section) {
+ uint32_t TempReg;
+
+
+ CompileCop1Test(Section);
+
+ UnMap_FPR(Section,Opcode.fs,1);
+ Map_GPR_64bit(Section,Opcode.rt, -1);
+ TempReg = Map_TempReg(Section,x86_Any,-1,0);
+
+ MovePointerToX86reg((uint8_t *)&FPRDoubleLocation[Opcode.fs],TempReg);
+ AddConstToX86Reg(TempReg | x64_Reg,4);
+ MoveX86PointerToX86reg(MipsRegHi(Opcode.rt),TempReg);
+
+ MovePointerToX86reg((uint8_t *)&FPRDoubleLocation[Opcode.fs],TempReg);
+ MoveX86PointerToX86reg(MipsRegLo(Opcode.rt),TempReg);
+}
+
+void Compile_R4300i_COP1_CF(BLOCK_SECTION * Section) {
+
+
+ CompileCop1Test(Section);
+
+ if (Opcode.fs != 31 && Opcode.fs != 0) { Compile_R4300i_UnknownOpcode (Section); return; }
+ Map_GPR_32bit(Section,Opcode.rt,1,-1);
+ MoveVariableToX86reg(&FPCR[Opcode.fs],MipsRegLo(Opcode.rt));
+}
+
+void Compile_R4300i_COP1_MT( BLOCK_SECTION * Section) {
+ uint32_t TempReg;
+
+
+ CompileCop1Test(Section);
+
+ if ((Opcode.fs & 1) != 0) {
+ if (RegInStack(Section,Opcode.fs-1,FPU_Double) || RegInStack(Section,Opcode.fs-1,FPU_Qword)) {
+ UnMap_FPR(Section,Opcode.fs-1,1);
+ }
+ }
+ UnMap_FPR(Section,Opcode.fs,1);
+ TempReg = Map_TempReg(Section,x86_Any,-1,0);
+
+ MovePointerToX86reg((uint8_t *)&FPRFloatLocation[Opcode.fs],TempReg);
+
+ if (IsConst(Opcode.rt)) {
+ MoveConstToX86Pointer(MipsRegLo(Opcode.rt),TempReg);
+ } else if (IsMapped(Opcode.rt)) {
+ MoveX86regToX86Pointer(MipsRegLo(Opcode.rt),TempReg);
+ } else {
+ MoveX86regToX86Pointer(Map_TempReg(Section,x86_Any, Opcode.rt, 0),TempReg);
+ }
+}
+
+void Compile_R4300i_COP1_DMT( BLOCK_SECTION * Section) {
+ uint32_t TempReg;
+
+
+ CompileCop1Test(Section);
+
+ if ((Opcode.fs & 1) == 0) {
+ if (RegInStack(Section,Opcode.fs+1,FPU_Float) || RegInStack(Section,Opcode.fs+1,FPU_Dword)) {
+ UnMap_FPR(Section,Opcode.fs+1,1);
+ }
+ }
+ UnMap_FPR(Section,Opcode.fs,1);
+ TempReg = Map_TempReg(Section,x86_Any,-1,0);
+
+ MovePointerToX86reg((uint8_t *)&FPRDoubleLocation[Opcode.fs],TempReg);
+
+ if (IsConst(Opcode.rt)) {
+ MoveConstToX86Pointer(MipsRegLo(Opcode.rt),TempReg);
+ AddConstToX86Reg(TempReg,4);
+ if Is64Bit(Opcode.rt) {
+ MoveConstToX86Pointer(MipsRegHi(Opcode.rt),TempReg);
+ } else {
+ MoveConstToX86Pointer(MipsRegLo_S(Opcode.rt) >> 31,TempReg);
+ }
+ } else if (IsMapped(Opcode.rt)) {
+ MoveX86regToX86Pointer(MipsRegLo(Opcode.rt),TempReg);
+ AddConstToX86Reg64(TempReg,4);
+ if Is64Bit(Opcode.rt) {
+ MoveX86regToX86Pointer(MipsRegHi(Opcode.rt),TempReg);
+ } else {
+ MoveX86regToX86Pointer(Map_TempReg(Section,x86_Any, Opcode.rt, 1),TempReg);
+ }
+ } else {
+ int x86Reg = Map_TempReg(Section,x86_Any, Opcode.rt, 0);
+ MoveX86regToX86Pointer(x86Reg,TempReg);
+ AddConstToX86Reg64(TempReg,4);
+ MoveX86regToX86Pointer(Map_TempReg(Section,x86Reg, Opcode.rt, 1),TempReg);
+ }
+}
+
+
+void Compile_R4300i_COP1_CT(BLOCK_SECTION * Section) {
+
+
+ CompileCop1Test(Section);
+ if (Opcode.fs != 31) { Compile_R4300i_UnknownOpcode (Section); return; }
+
+ if (IsConst(Opcode.rt)) {
+ MoveConstToVariable(MipsRegLo(Opcode.rt),&FPCR[Opcode.fs]);
+ } else if (IsMapped(Opcode.rt)) {
+ MoveX86regToVariable(MipsRegLo(Opcode.rt),&FPCR[Opcode.fs]);
+ } else {
+ MoveX86regToVariable(Map_TempReg(Section,x86_Any,Opcode.rt,0),&FPCR[Opcode.fs]);
+ }
+ Pushad();
+ Call_Direct(ChangeDefaultRoundingModel);
+ Popad();
+ CurrentRoundingModel = RoundUnknown;
+}
+
+/************************** COP1: S functions ************************/
+void Compile_R4300i_COP1_S_ADD (BLOCK_SECTION * Section) {
+ uint32_t Reg1 = Opcode.ft == Opcode.fd?Opcode.ft:Opcode.fs;
+ uint32_t Reg2 = Opcode.ft == Opcode.fd?Opcode.fs:Opcode.ft;
+
+
+
+ CompileCop1Test(Section);
+
+ Load_FPR_ToTop(Section,Opcode.fd,Reg1, FPU_Float);
+ if (RegInStack(Section,Reg2, FPU_Float)) {
+ fpuAddReg(StackPosition(Section,Reg2));
+ } else {
+ uint32_t TempReg;
+
+ UnMap_FPR(Section,Reg2,1);
+ TempReg = Map_TempReg(Section,x86_Any,-1,0);
+
+ MovePointerToX86reg((uint8_t *)&FPRFloatLocation[Reg2],TempReg);
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fd, FPU_Float);
+ fpuAddDwordRegPointer(TempReg);
+ }
+ UnMap_FPR(Section,Opcode.fd,1);
+}
+
+void Compile_R4300i_COP1_S_SUB (BLOCK_SECTION * Section) {
+ uint32_t Reg1 = Opcode.ft == Opcode.fd?Opcode.ft:Opcode.fs;
+ uint32_t Reg2 = Opcode.ft == Opcode.fd?Opcode.fs:Opcode.ft;
+ uint32_t TempReg;
+
+
+
+ CompileCop1Test(Section);
+
+ if (Opcode.fd == Opcode.ft) {
+ UnMap_FPR(Section,Opcode.fd,1);
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Float);
+
+ TempReg = Map_TempReg(Section,x86_Any,-1,0);
+
+ MovePointerToX86reg((uint8_t *)&FPRFloatLocation[Opcode.ft],TempReg);
+ fpuSubDwordRegPointer(TempReg);
+ } else {
+ Load_FPR_ToTop(Section,Opcode.fd,Reg1, FPU_Float);
+ if (RegInStack(Section,Reg2, FPU_Float)) {
+ fpuSubReg(StackPosition(Section,Reg2));
+ } else {
+ UnMap_FPR(Section,Reg2,1);
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fd, FPU_Float);
+
+ TempReg = Map_TempReg(Section,x86_Any,-1,0);
+
+ MovePointerToX86reg((uint8_t *)&FPRFloatLocation[Reg2],TempReg);
+ fpuSubDwordRegPointer(TempReg);
+ }
+ }
+ UnMap_FPR(Section,Opcode.fd,1);
+}
+
+void Compile_R4300i_COP1_S_MUL (BLOCK_SECTION * Section) {
+ uint32_t Reg1 = Opcode.ft == Opcode.fd?Opcode.ft:Opcode.fs;
+ uint32_t Reg2 = Opcode.ft == Opcode.fd?Opcode.fs:Opcode.ft;
+ uint32_t TempReg;
+
+
+
+ CompileCop1Test(Section);
+
+ Load_FPR_ToTop(Section,Opcode.fd,Reg1, FPU_Float);
+ if (RegInStack(Section,Reg2, FPU_Float)) {
+ fpuMulReg(StackPosition(Section,Reg2));
+ } else {
+ UnMap_FPR(Section,Reg2,1);
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fd, FPU_Float);
+
+ TempReg = Map_TempReg(Section,x86_Any,-1,0);
+
+ MovePointerToX86reg((uint8_t *)&FPRFloatLocation[Reg2],TempReg);
+ fpuMulDwordRegPointer(TempReg);
+ }
+ UnMap_FPR(Section,Opcode.fd,1);
+}
+
+void Compile_R4300i_COP1_S_DIV (BLOCK_SECTION * Section) {
+ uint32_t Reg1 = Opcode.ft == Opcode.fd?Opcode.ft:Opcode.fs;
+ uint32_t Reg2 = Opcode.ft == Opcode.fd?Opcode.fs:Opcode.ft;
+ uint32_t TempReg;
+
+
+
+ CompileCop1Test(Section);
+
+ if (Opcode.fd == Opcode.ft) {
+ UnMap_FPR(Section,Opcode.fd,1);
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Float);
+
+ TempReg = Map_TempReg(Section,x86_Any,-1,0);
+
+ MovePointerToX86reg((uint8_t *)&FPRFloatLocation[Opcode.ft],TempReg);
+ fpuDivDwordRegPointer(TempReg);
+ } else {
+ Load_FPR_ToTop(Section,Opcode.fd,Reg1, FPU_Float);
+ if (RegInStack(Section,Reg2, FPU_Float)) {
+ fpuDivReg(StackPosition(Section,Reg2));
+ } else {
+ UnMap_FPR(Section,Reg2,1);
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fd, FPU_Float);
+
+ TempReg = Map_TempReg(Section,x86_Any,-1,0);
+
+ MovePointerToX86reg((uint8_t *)&FPRFloatLocation[Reg2],TempReg);
+ fpuDivDwordRegPointer(TempReg);
+ }
+ }
+
+ UnMap_FPR(Section,Opcode.fd,1);
+}
+
+void Compile_R4300i_COP1_S_ABS (BLOCK_SECTION * Section) {
+
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Float);
+ fpuAbs();
+ UnMap_FPR(Section,Opcode.fd,1);
+}
+
+void Compile_R4300i_COP1_S_NEG (BLOCK_SECTION * Section) {
+
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Float);
+ fpuNeg();
+ UnMap_FPR(Section,Opcode.fd,1);
+}
+
+void Compile_R4300i_COP1_S_SQRT (BLOCK_SECTION * Section) {
+
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Float);
+ fpuSqrt();
+ UnMap_FPR(Section,Opcode.fd,1);
+}
+
+void Compile_R4300i_COP1_S_MOV (BLOCK_SECTION * Section) {
+
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Float);
+}
+
+void Compile_R4300i_COP1_S_TRUNC_L (BLOCK_SECTION * Section) {
+
+
+ CompileCop1Test(Section);
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Float)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Float);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Float,FPU_Qword,RoundTruncate);
+}
+
+void Compile_R4300i_COP1_S_CEIL_L (BLOCK_SECTION * Section) { //added by Witten
+
+
+ CompileCop1Test(Section);
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Float)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Float);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Float,FPU_Qword,RoundUp);
+}
+
+void Compile_R4300i_COP1_S_FLOOR_L (BLOCK_SECTION * Section) { //added by Witten
+
+
+ CompileCop1Test(Section);
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Float)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Float);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Float,FPU_Qword,RoundDown);
+}
+
+void Compile_R4300i_COP1_S_ROUND_W (BLOCK_SECTION * Section) {
+
+
+ CompileCop1Test(Section);
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Float)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Float);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Float,FPU_Dword,RoundNearest);
+}
+
+void Compile_R4300i_COP1_S_TRUNC_W (BLOCK_SECTION * Section) {
+
+
+ CompileCop1Test(Section);
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Float)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Float);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Float,FPU_Dword,RoundTruncate);
+}
+
+void Compile_R4300i_COP1_S_CEIL_W (BLOCK_SECTION * Section) { // added by Witten
+
+
+ CompileCop1Test(Section);
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Float)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Float);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Float,FPU_Dword,RoundUp);
+}
+
+void Compile_R4300i_COP1_S_FLOOR_W (BLOCK_SECTION * Section) {
+
+
+ CompileCop1Test(Section);
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Float)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Float);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Float,FPU_Dword,RoundDown);
+}
+
+void Compile_R4300i_COP1_S_CVT_D (BLOCK_SECTION * Section) {
+
+
+ CompileCop1Test(Section);
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Float)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Float);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Float,FPU_Double,RoundDefault);
+}
+
+void Compile_R4300i_COP1_S_CVT_W (BLOCK_SECTION * Section) {
+
+
+ CompileCop1Test(Section);
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Float)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Float);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Float,FPU_Dword,RoundDefault);
+}
+
+void Compile_R4300i_COP1_S_CVT_L (BLOCK_SECTION * Section) {
+
+
+ CompileCop1Test(Section);
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Float)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Float);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Float,FPU_Qword,RoundDefault);
+}
+
+void Compile_R4300i_COP1_S_CMP (BLOCK_SECTION * Section) {
+ uint32_t Reg1 = RegInStack(Section,Opcode.ft, FPU_Float)?Opcode.ft:Opcode.fs;
+ uint32_t Reg2 = RegInStack(Section,Opcode.ft, FPU_Float)?Opcode.fs:Opcode.ft;
+ int x86reg, cmp = 0;
+
+
+
+
+ CompileCop1Test(Section);
+ //if ((Opcode.funct & 1) != 0) { Compile_R4300i_UnknownOpcode(Section); }
+ if ((Opcode.funct & 2) != 0) { cmp |= 0x4000; }
+ if ((Opcode.funct & 4) != 0) { cmp |= 0x0100; }
+
+ Load_FPR_ToTop(Section,Reg1,Reg1, FPU_Float);
+ Map_TempReg(Section,x86_EAX, 0, 0);
+ if (RegInStack(Section,Reg2, FPU_Float)) {
+ fpuComReg(StackPosition(Section,Reg2),0);
+ } else {
+ uint32_t TempReg;
+
+ UnMap_FPR(Section,Reg2,1);
+ Load_FPR_ToTop(Section,Reg1,Reg1, FPU_Float);
+
+ TempReg = Map_TempReg(Section,x86_Any,-1,0);
+
+ MovePointerToX86reg((uint8_t *)&FPRFloatLocation[Reg2],TempReg);
+ fpuComDwordRegPointer(TempReg,0);
+ }
+ AndConstToVariable(~FPCSR_C, &FSTATUS_REGISTER);
+ fpuStoreStatus();
+ x86reg = Map_TempReg(Section,x86_Any8Bit, 0, 0);
+ TestConstToX86Reg(cmp,x86_EAX);
+ Setnz(x86reg);
+
+ if (cmp != 0) {
+ TestConstToX86Reg(cmp,x86_EAX);
+ Setnz(x86reg);
+
+ if ((Opcode.funct & 1) != 0) {
+ int x86reg2 = Map_TempReg(Section,x86_Any8Bit, 0, 0);
+ AndConstToX86Reg(x86_EAX, 0x4300);
+ CompConstToX86reg(x86_EAX, 0x4300);
+ Setz(x86reg2);
+
+ OrX86RegToX86Reg(x86reg, x86reg2);
+ }
+ } else if ((Opcode.funct & 1) != 0) {
+ AndConstToX86Reg(x86_EAX, 0x4300);
+ CompConstToX86reg(x86_EAX, 0x4300);
+ Setz(x86reg);
+ }
+ ShiftLeftSignImmed(x86reg, 23);
+ OrX86RegToVariable(&FPCR[31], x86reg);
+}
+
+/************************** COP1: D functions ************************/
+void Compile_R4300i_COP1_D_ADD (BLOCK_SECTION * Section) {
+ uint32_t Reg1 = Opcode.ft == Opcode.fd?Opcode.ft:Opcode.fs;
+ uint32_t Reg2 = Opcode.ft == Opcode.fd?Opcode.fs:Opcode.ft;
+
+
+
+ CompileCop1Test(Section);
+
+ Load_FPR_ToTop(Section,Opcode.fd,Reg1, FPU_Double);
+ if (RegInStack(Section,Reg2, FPU_Double)) {
+ fpuAddReg(StackPosition(Section,Reg2));
+ } else {
+ uint32_t TempReg;
+
+ UnMap_FPR(Section,Reg2,1);
+ TempReg = Map_TempReg(Section,x86_Any,-1,0);
+
+ MovePointerToX86reg((uint8_t *)&FPRDoubleLocation[Reg2],TempReg);
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fd, FPU_Double);
+ fpuAddQwordRegPointer(TempReg);
+ }
+}
+
+void Compile_R4300i_COP1_D_SUB (BLOCK_SECTION * Section) {
+ uint32_t Reg1 = Opcode.ft == Opcode.fd?Opcode.ft:Opcode.fs;
+ uint32_t Reg2 = Opcode.ft == Opcode.fd?Opcode.fs:Opcode.ft;
+ uint32_t TempReg;
+
+
+
+ CompileCop1Test(Section);
+
+ if (Opcode.fd == Opcode.ft) {
+ UnMap_FPR(Section,Opcode.fd,1);
+ TempReg = Map_TempReg(Section,x86_Any,-1,0);
+
+ MovePointerToX86reg((uint8_t *)&FPRDoubleLocation[Opcode.ft],TempReg);
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Double);
+ fpuSubQwordRegPointer(TempReg);
+ } else {
+ Load_FPR_ToTop(Section,Opcode.fd,Reg1, FPU_Double);
+ if (RegInStack(Section,Reg2, FPU_Double)) {
+ fpuSubReg(StackPosition(Section,Reg2));
+ } else {
+ UnMap_FPR(Section,Reg2,1);
+
+ TempReg = Map_TempReg(Section,x86_Any,-1,0);
+
+ MovePointerToX86reg((uint8_t *)&FPRDoubleLocation[Reg2],TempReg);
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fd, FPU_Double);
+ fpuSubQwordRegPointer(TempReg);
+ }
+ }
+}
+
+void Compile_R4300i_COP1_D_MUL (BLOCK_SECTION * Section) {
+ uint32_t Reg1 = Opcode.ft == Opcode.fd?Opcode.ft:Opcode.fs;
+ uint32_t Reg2 = Opcode.ft == Opcode.fd?Opcode.fs:Opcode.ft;
+ uint32_t TempReg;
+
+
+
+ CompileCop1Test(Section);
+
+ Load_FPR_ToTop(Section,Opcode.fd,Reg1, FPU_Double);
+ if (RegInStack(Section,Reg2, FPU_Double)) {
+ fpuMulReg(StackPosition(Section,Reg2));
+ } else {
+ UnMap_FPR(Section,Reg2,1);
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fd, FPU_Double);
+ TempReg = Map_TempReg(Section,x86_Any,-1,0);
+
+ MovePointerToX86reg((uint8_t *)&FPRDoubleLocation[Reg2],TempReg);
+ fpuMulQwordRegPointer(TempReg);
+ }
+}
+
+void Compile_R4300i_COP1_D_DIV (BLOCK_SECTION * Section) {
+ uint32_t Reg1 = Opcode.ft == Opcode.fd?Opcode.ft:Opcode.fs;
+ uint32_t Reg2 = Opcode.ft == Opcode.fd?Opcode.fs:Opcode.ft;
+ uint32_t TempReg;
+
+
+
+ CompileCop1Test(Section);
+
+ if (Opcode.fd == Opcode.ft) {
+ UnMap_FPR(Section,Opcode.fd,1);
+ TempReg = Map_TempReg(Section,x86_Any,-1,0);
+
+ MovePointerToX86reg((uint8_t *)&FPRDoubleLocation[Opcode.ft],TempReg);
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Double);
+ fpuDivQwordRegPointer(TempReg);
+ } else {
+ Load_FPR_ToTop(Section,Opcode.fd,Reg1, FPU_Double);
+ if (RegInStack(Section,Reg2, FPU_Double)) {
+ fpuDivReg(StackPosition(Section,Reg2));
+ } else {
+ UnMap_FPR(Section,Reg2,1);
+ TempReg = Map_TempReg(Section,x86_Any,-1,0);
+
+ MovePointerToX86reg((uint8_t *)&FPRDoubleLocation[Reg2],TempReg);
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fd, FPU_Double);
+ fpuDivQwordRegPointer(TempReg);
+ }
+ }
+}
+
+void Compile_R4300i_COP1_D_ABS (BLOCK_SECTION * Section) {
+
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Double);
+ fpuAbs();
+}
+
+void Compile_R4300i_COP1_D_NEG (BLOCK_SECTION * Section) {
+
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Double);
+ fpuNeg();
+}
+
+void Compile_R4300i_COP1_D_SQRT (BLOCK_SECTION * Section) {
+
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Double);
+ fpuSqrt();
+}
+
+void Compile_R4300i_COP1_D_MOV (BLOCK_SECTION * Section) {
+
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Double);
+}
+
+void Compile_R4300i_COP1_D_TRUNC_L (BLOCK_SECTION * Section) { //added by Witten
+
+
+ CompileCop1Test(Section);
+ if (RegInStack(Section,Opcode.fs,FPU_Double) || RegInStack(Section,Opcode.fs,FPU_Qword)) {
+ UnMap_FPR(Section,Opcode.fs,1);
+ }
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Double)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Double);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Double,FPU_Qword,RoundTruncate);
+}
+
+void Compile_R4300i_COP1_D_CEIL_L (BLOCK_SECTION * Section) { //added by Witten
+
+
+ CompileCop1Test(Section);
+ if (RegInStack(Section,Opcode.fs,FPU_Double) || RegInStack(Section,Opcode.fs,FPU_Qword)) {
+ UnMap_FPR(Section,Opcode.fs,1);
+ }
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Double)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Double);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Double,FPU_Qword,RoundUp);
+}
+
+void Compile_R4300i_COP1_D_FLOOR_L (BLOCK_SECTION * Section) { //added by Witten
+
+
+ CompileCop1Test(Section);
+ if (RegInStack(Section,Opcode.fs,FPU_Double) || RegInStack(Section,Opcode.fs,FPU_Qword)) {
+ UnMap_FPR(Section,Opcode.fs,1);
+ }
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Double)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Double);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Double,FPU_Qword,RoundDown);
+}
+
+void Compile_R4300i_COP1_D_ROUND_W (BLOCK_SECTION * Section) {
+
+
+ CompileCop1Test(Section);
+ if (RegInStack(Section,Opcode.fs,FPU_Double) || RegInStack(Section,Opcode.fs,FPU_Qword)) {
+ UnMap_FPR(Section,Opcode.fs,1);
+ }
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Double)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Double);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Double,FPU_Dword,RoundNearest);
+}
+
+void Compile_R4300i_COP1_D_TRUNC_W (BLOCK_SECTION * Section) {
+
+
+ CompileCop1Test(Section);
+ if (RegInStack(Section,Opcode.fs,FPU_Double) || RegInStack(Section,Opcode.fs,FPU_Qword)) {
+ UnMap_FPR(Section,Opcode.fs,1);
+ }
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Double)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Double);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Double,FPU_Dword,RoundTruncate);
+}
+
+void Compile_R4300i_COP1_D_CEIL_W (BLOCK_SECTION * Section) { // added by Witten
+
+
+ CompileCop1Test(Section);
+ if (RegInStack(Section,Opcode.fs,FPU_Double) || RegInStack(Section,Opcode.fs,FPU_Qword)) {
+ UnMap_FPR(Section,Opcode.fs,1);
+ }
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Double)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Double);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Double,FPU_Dword,RoundUp);
+}
+
+void Compile_R4300i_COP1_D_FLOOR_W (BLOCK_SECTION * Section) { //added by Witten
+
+
+ CompileCop1Test(Section);
+ if (RegInStack(Section,Opcode.fs,FPU_Double) || RegInStack(Section,Opcode.fs,FPU_Qword)) {
+ UnMap_FPR(Section,Opcode.fs,1);
+ }
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Double)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Double);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Double,FPU_Dword,RoundDown);
+}
+
+void Compile_R4300i_COP1_D_CVT_S (BLOCK_SECTION * Section) {
+
+
+ CompileCop1Test(Section);
+ if (RegInStack(Section,Opcode.fs,FPU_Double) || RegInStack(Section,Opcode.fs,FPU_Qword)) {
+ UnMap_FPR(Section,Opcode.fs,1);
+ }
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Double)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Double);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Double,FPU_Float,RoundDefault);
+}
+
+void Compile_R4300i_COP1_D_CVT_W (BLOCK_SECTION * Section) {
+
+
+ CompileCop1Test(Section);
+ if (RegInStack(Section,Opcode.fs,FPU_Double) || RegInStack(Section,Opcode.fs,FPU_Qword)) {
+ UnMap_FPR(Section,Opcode.fs,1);
+ }
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Double)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Double);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Double,FPU_Dword,RoundDefault);
+}
+
+void Compile_R4300i_COP1_D_CVT_L (BLOCK_SECTION * Section) {
+
+
+ CompileCop1Test(Section);
+ if (RegInStack(Section,Opcode.fs,FPU_Double) || RegInStack(Section,Opcode.fs,FPU_Qword)) {
+ UnMap_FPR(Section,Opcode.fs,1);
+ }
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Double)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Double);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Double,FPU_Qword,RoundDefault);
+}
+
+void Compile_R4300i_COP1_D_CMP (BLOCK_SECTION * Section) {
+ uint32_t Reg1 = RegInStack(Section,Opcode.ft, FPU_Float)?Opcode.ft:Opcode.fs;
+ uint32_t Reg2 = RegInStack(Section,Opcode.ft, FPU_Float)?Opcode.fs:Opcode.ft;
+ int x86reg, cmp = 0;
+
+
+
+
+ CompileCop1Test(Section);
+ //if ((Opcode.funct & 1) != 0) { Compile_R4300i_UnknownOpcode(Section); }
+ if ((Opcode.funct & 2) != 0) { cmp |= 0x4000; }
+ if ((Opcode.funct & 4) != 0) { cmp |= 0x0100; }
+
+ Load_FPR_ToTop(Section,Reg1,Reg1, FPU_Double);
+ Map_TempReg(Section,x86_EAX, 0, 0);
+ if (RegInStack(Section,Reg2, FPU_Double)) {
+ fpuComReg(StackPosition(Section,Reg2),0);
+ } else {
+ uint32_t TempReg;
+
+ UnMap_FPR(Section,Reg2,1);
+ TempReg = Map_TempReg(Section,x86_Any,-1,0);
+
+ MovePointerToX86reg((uint8_t *)&FPRDoubleLocation[Reg2],TempReg);
+ Load_FPR_ToTop(Section,Reg1,Reg1, FPU_Double);
+ fpuComQwordRegPointer(TempReg,0);
+ }
+ AndConstToVariable(~FPCSR_C, &FSTATUS_REGISTER);
+ fpuStoreStatus();
+ x86reg = Map_TempReg(Section,x86_Any8Bit, 0, 0);
+ TestConstToX86Reg(cmp,x86_EAX);
+ Setnz(x86reg);
+ if (cmp != 0) {
+ TestConstToX86Reg(cmp,x86_EAX);
+ Setnz(x86reg);
+
+ if ((Opcode.funct & 1) != 0) {
+ int x86reg2 = Map_TempReg(Section,x86_Any8Bit, 0, 0);
+ AndConstToX86Reg(x86_EAX, 0x4300);
+ CompConstToX86reg(x86_EAX, 0x4300);
+ Setz(x86reg2);
+
+ OrX86RegToX86Reg(x86reg, x86reg2);
+ }
+ } else if ((Opcode.funct & 1) != 0) {
+ AndConstToX86Reg(x86_EAX, 0x4300);
+ CompConstToX86reg(x86_EAX, 0x4300);
+ Setz(x86reg);
+ }
+ ShiftLeftSignImmed(x86reg, 23);
+ OrX86RegToVariable(&FPCR[31], x86reg);
+}
+
+/************************** COP1: W functions ************************/
+void Compile_R4300i_COP1_W_CVT_S (BLOCK_SECTION * Section) {
+
+
+ CompileCop1Test(Section);
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Dword)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Dword);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Dword,FPU_Float,RoundDefault);
+}
+
+void Compile_R4300i_COP1_W_CVT_D (BLOCK_SECTION * Section) {
+
+
+ CompileCop1Test(Section);
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Dword)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Dword);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Dword,FPU_Double,RoundDefault);
+}
+
+/************************** COP1: L functions ************************/
+void Compile_R4300i_COP1_L_CVT_S (BLOCK_SECTION * Section) {
+
+
+ CompileCop1Test(Section);
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Qword)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Qword);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Qword,FPU_Float,RoundDefault);
+}
+
+void Compile_R4300i_COP1_L_CVT_D (BLOCK_SECTION * Section) {
+
+
+ CompileCop1Test(Section);
+ if (Opcode.fd != Opcode.fs || !RegInStack(Section,Opcode.fd,FPU_Qword)) {
+ Load_FPR_ToTop(Section,Opcode.fd,Opcode.fs,FPU_Qword);
+ }
+ ChangeFPURegFormat(Section,Opcode.fd,FPU_Qword,FPU_Double,RoundDefault);
+}
diff --git a/src/usf/recompiler_ops.c b/src/usf/recompiler_ops.c new file mode 100644 index 0000000..522e8fb --- /dev/null +++ b/src/usf/recompiler_ops.c @@ -0,0 +1,4657 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+#include "main.h"
+#include "cpu.h"
+#include "x86.h"
+#include "types.h"
+
+uint32_t BranchCompare = 0;
+
+void CompileReadTLBMiss (BLOCK_SECTION * Section, int32_t AddressReg, int32_t LookUpReg ) {
+#ifdef USEX64
+ MoveX86regToMemory(AddressReg, x86_R15, (uintptr_t)TLBLoadAddress-(uintptr_t)TLB_Map);
+#else
+ MoveX86regToVariable(AddressReg,TLBLoadAddress);
+#endif
+ TestX86RegToX86Reg(LookUpReg,LookUpReg);
+ CompileExit(Section->CompilePC,&Section->RegWorking,TLBReadMiss,0,JeLabel32);
+}
+
+/************************** Branch functions ************************/
+void Compile_R4300i_Branch (BLOCK_SECTION * Section, void (*CompareFunc)(BLOCK_SECTION * Section), int32_t BranchType, uint32_t Link) {
+ static int32_t EffectDelaySlot;
+ static REG_INFO RegBeforeDelay;
+ int32_t count;
+
+ if ( NextInstruction == NORMAL ) {
+
+ if ((Section->CompilePC & 0xFFC) != 0xFFC) {
+ switch (BranchType) {
+ case BranchTypeRs: EffectDelaySlot = DelaySlotEffectsCompare(Section->CompilePC,Opcode.rs,0); break;
+ case BranchTypeRsRt: EffectDelaySlot = DelaySlotEffectsCompare(Section->CompilePC,Opcode.rs,Opcode.rt); break;
+ case BranchTypeCop1:
+ {
+ OPCODE Command;
+
+ if (!r4300i_LW_VAddr(Section->CompilePC + 4, &Command.Hex)) {
+ //DisplayError(GS(MSG_FAIL_LOAD_WORD));
+ StopEmulation();
+ }
+
+ EffectDelaySlot = 0;
+ if (Command.op == R4300i_CP1) {
+ if (Command.fmt == R4300i_COP1_S && (Command.funct & 0x30) == 0x30 ) {
+ EffectDelaySlot = 1;
+ }
+ if (Command.fmt == R4300i_COP1_D && (Command.funct & 0x30) == 0x30 ) {
+ EffectDelaySlot = 1;
+ }
+ }
+ }
+ break;
+
+ }
+ } else {
+ EffectDelaySlot = 1;
+ }
+ Section->Jump.TargetPC = Section->CompilePC + ((short)Opcode.offset << 2) + 4;
+ Section->Jump.LinkLocation = NULL;
+ Section->Jump.LinkLocation2 = NULL;
+ Section->Jump.DoneDelaySlot = 0;
+ Section->Cont.TargetPC = Section->CompilePC + 8;
+ Section->Cont.LinkLocation = NULL;
+ Section->Cont.LinkLocation2 = NULL;
+ Section->Cont.DoneDelaySlot = 0;
+ if (Section->Jump.TargetPC < Section->Cont.TargetPC) {
+ Section->Cont.FallThrough = 0;
+ Section->Jump.FallThrough = 1;
+ } else {
+ Section->Cont.FallThrough = 1;
+ Section->Jump.FallThrough = 0;
+ }
+ if (Link) {
+ UnMap_GPR(Section, 31, 0);
+ MipsRegLo(31) = Section->CompilePC + 8;
+ MipsRegState(31) = STATE_CONST_32;
+ }
+ if (EffectDelaySlot) {
+ CompareFunc(Section);
+
+ if ((Section->CompilePC & 0xFFC) == 0xFFC) {
+ GenerateSectionLinkage(Section);
+ NextInstruction = END_BLOCK;
+ return;
+ }
+ if (!Section->Jump.FallThrough && !Section->Cont.FallThrough) {
+ if (Section->Jump.LinkLocation != NULL) {
+ SetJump32((uint32_t *)Section->Jump.LinkLocation,(uint32_t *)RecompPos);
+ Section->Jump.LinkLocation = NULL;
+ if (Section->Jump.LinkLocation2 != NULL) {
+ SetJump32((uint32_t *)Section->Jump.LinkLocation2,(uint32_t *)RecompPos);
+ Section->Jump.LinkLocation2 = NULL;
+ }
+ Section->Jump.FallThrough = 1;
+ } else if (Section->Cont.LinkLocation != NULL){
+
+ SetJump32((uint32_t *)Section->Cont.LinkLocation,(uint32_t *)RecompPos);
+ Section->Cont.LinkLocation = NULL;
+ if (Section->Cont.LinkLocation2 != NULL) {
+ SetJump32((uint32_t *)Section->Cont.LinkLocation2,(uint32_t *)RecompPos);
+ Section->Cont.LinkLocation2 = NULL;
+ }
+ Section->Cont.FallThrough = 1;
+ }
+ }
+ for (count = 1; count < 64; count ++) { x86Protected(count) = 0; }
+ memcpy(&RegBeforeDelay,&Section->RegWorking,sizeof(REG_INFO));
+ }
+ NextInstruction = DO_DELAY_SLOT;
+ } else if (NextInstruction == DELAY_SLOT_DONE ) {
+ if (EffectDelaySlot) {
+ JUMP_INFO * FallInfo = Section->Jump.FallThrough?&Section->Jump:&Section->Cont;
+ JUMP_INFO * JumpInfo = Section->Jump.FallThrough?&Section->Cont:&Section->Jump;
+
+ if (FallInfo->FallThrough && !FallInfo->DoneDelaySlot) {
+ for (count = 1; count < 64; count ++) { x86Protected(count) = 0; }
+ memcpy(&FallInfo->RegSet,&Section->RegWorking,sizeof(REG_INFO));
+ FallInfo->DoneDelaySlot = 1;
+ if (!JumpInfo->DoneDelaySlot) {
+ FallInfo->FallThrough = 0;
+ JmpLabel32(0);
+ FallInfo->LinkLocation = RecompPos - 4;
+
+ if (JumpInfo->LinkLocation != NULL) {
+ SetJump32((uint32_t *)JumpInfo->LinkLocation,(uint32_t *)RecompPos);
+ JumpInfo->LinkLocation = NULL;
+ if (JumpInfo->LinkLocation2 != NULL) {
+ SetJump32((uint32_t *)JumpInfo->LinkLocation2,(uint32_t *)RecompPos);
+ JumpInfo->LinkLocation2 = NULL;
+ }
+ JumpInfo->FallThrough = 1;
+ NextInstruction = DO_DELAY_SLOT;
+ memcpy(&Section->RegWorking,&RegBeforeDelay,sizeof(REG_INFO));
+ return;
+ }
+ }
+ }
+ } else {
+ int32_t count;
+
+ CompareFunc(Section);
+ for (count = 1; count < 64; count ++) { x86Protected(count) = 0; }
+ memcpy(&Section->Cont.RegSet,&Section->RegWorking,sizeof(REG_INFO));
+ memcpy(&Section->Jump.RegSet,&Section->RegWorking,sizeof(REG_INFO));
+ }
+ GenerateSectionLinkage(Section);
+ NextInstruction = END_BLOCK;
+ } else {
+
+ }
+}
+
+void Compile_R4300i_BranchLikely (BLOCK_SECTION * Section, void (*CompareFunc)(BLOCK_SECTION * Section), uint32_t Link) {
+ int32_t count;
+
+ if ( NextInstruction == NORMAL ) {
+ Section->Jump.TargetPC = Section->CompilePC + ((short)Opcode.offset << 2) + 4;
+ Section->Jump.FallThrough = 1;
+ Section->Jump.LinkLocation = NULL;
+ Section->Jump.LinkLocation2 = NULL;
+ Section->Cont.TargetPC = Section->CompilePC + 8;
+ Section->Cont.FallThrough = 0;
+ Section->Cont.LinkLocation = NULL;
+ Section->Cont.LinkLocation2 = NULL;
+ if (Link) {
+ UnMap_GPR(Section, 31, 0);
+ MipsRegLo(31) = Section->CompilePC + 8;
+ MipsRegState(31) = STATE_CONST_32;
+ }
+ CompareFunc(Section);
+ for (count = 1; count < 64; count ++) { x86Protected(count) = 0; }
+ memcpy(&Section->Cont.RegSet,&Section->RegWorking,sizeof(REG_INFO));
+
+ if (Section->Cont.FallThrough) {
+ if (Section->Jump.LinkLocation != NULL) {
+ }
+ GenerateSectionLinkage(Section);
+ NextInstruction = END_BLOCK;
+ } else {
+ if ((Section->CompilePC & 0xFFC) == 0xFFC) {
+ Section->Jump.FallThrough = 0;
+ if (Section->Jump.LinkLocation != NULL) {
+ SetJump32(Section->Jump.LinkLocation,RecompPos);
+ Section->Jump.LinkLocation = NULL;
+ if (Section->Jump.LinkLocation2 != NULL) {
+ SetJump32(Section->Jump.LinkLocation2,RecompPos);
+ Section->Jump.LinkLocation2 = NULL;
+ }
+ }
+ JmpLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ if (Section->Cont.LinkLocation != NULL) {
+ SetJump32(Section->Cont.LinkLocation,RecompPos);
+ Section->Cont.LinkLocation = NULL;
+ if (Section->Cont.LinkLocation2 != NULL) {
+ SetJump32(Section->Cont.LinkLocation2,RecompPos);
+ Section->Cont.LinkLocation2 = NULL;
+ }
+ }
+ CompileExit (Section->CompilePC + 8,&Section->RegWorking,Normal,1,NULL);
+ GenerateSectionLinkage(Section);
+ NextInstruction = END_BLOCK;
+ } else {
+ NextInstruction = DO_DELAY_SLOT;
+ }
+ }
+ } else if (NextInstruction == DELAY_SLOT_DONE ) {
+ for (count = 1; count < 64; count ++) { x86Protected(count) = 0; }
+ memcpy(&Section->Jump.RegSet,&Section->RegWorking,sizeof(REG_INFO));
+ GenerateSectionLinkage(Section);
+ NextInstruction = END_BLOCK;
+ } else {
+ }
+}
+
+void BNE_Compare (BLOCK_SECTION * Section) {
+ uint8_t *Jump;
+
+ if (IsKnown(Opcode.rs) && IsKnown(Opcode.rt)) {
+ if (IsConst(Opcode.rs) && IsConst(Opcode.rt)) {
+ if (Is64Bit(Opcode.rs) || Is64Bit(Opcode.rt)) {
+ Compile_R4300i_UnknownOpcode(Section);
+ } else if (MipsRegLo(Opcode.rs) != MipsRegLo(Opcode.rt)) {
+ Section->Jump.FallThrough = 1;
+ Section->Cont.FallThrough = 0;
+ } else {
+ Section->Jump.FallThrough = 0;
+ Section->Cont.FallThrough = 1;
+ }
+ } else if (IsMapped(Opcode.rs) && IsMapped(Opcode.rt)) {
+ if (Is64Bit(Opcode.rs) || Is64Bit(Opcode.rt)) {
+ ProtectGPR(Section,Opcode.rs);
+ ProtectGPR(Section,Opcode.rt);
+
+ CompX86RegToX86Reg(
+ Is32Bit(Opcode.rs)?Map_TempReg(Section,x86_Any,Opcode.rs,1):MipsRegHi(Opcode.rs),
+ Is32Bit(Opcode.rt)?Map_TempReg(Section,x86_Any,Opcode.rt,1):MipsRegHi(Opcode.rt)
+ );
+
+ if (Section->Jump.FallThrough) {
+ JneLabel8(0);
+ Jump = RecompPos - 1;
+ } else {
+ JneLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+ CompX86RegToX86Reg(MipsRegLo(Opcode.rs),MipsRegLo(Opcode.rt));
+ if (Section->Cont.FallThrough) {
+ JneLabel32 ( 0 );
+ Section->Jump.LinkLocation2 = RecompPos - 4;
+ } else if (Section->Jump.FallThrough) {
+ JeLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ SetJump8(Jump,RecompPos);
+ } else {
+ JeLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation2 = RecompPos - 4;
+ }
+ } else {
+ CompX86RegToX86Reg(MipsRegLo(Opcode.rs),MipsRegLo(Opcode.rt));
+ if (Section->Cont.FallThrough) {
+ JneLabel32 ( 0 );
+ Section->Jump.LinkLocation = RecompPos - 4;
+ } else if (Section->Jump.FallThrough) {
+ JeLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ } else {
+ JeLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+ }
+ } else {
+ uint32_t ConstReg = IsConst(Opcode.rt)?Opcode.rt:Opcode.rs;
+ uint32_t MappedReg = IsConst(Opcode.rt)?Opcode.rs:Opcode.rt;
+
+ if (Is64Bit(ConstReg) || Is64Bit(MappedReg)) {
+ if (Is32Bit(ConstReg) || Is32Bit(MappedReg)) {
+ ProtectGPR(Section,MappedReg);
+ if (Is32Bit(MappedReg)) {
+ CompConstToX86reg(Map_TempReg(Section,x86_Any,MappedReg,1),MipsRegHi(ConstReg));
+ } else {
+ CompConstToX86reg(MipsRegHi(MappedReg),(int32_t)MipsRegLo(ConstReg) >> 31);
+ }
+ } else {
+ CompConstToX86reg(MipsRegHi(MappedReg),MipsRegHi(ConstReg));
+ }
+ if (Section->Jump.FallThrough) {
+ JneLabel8(0);
+ Jump = RecompPos - 1;
+ } else {
+ JneLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+ if (MipsRegLo(ConstReg) == 0) {
+ OrX86RegToX86Reg(MipsRegLo(MappedReg),MipsRegLo(MappedReg));
+ } else {
+ CompConstToX86reg(MipsRegLo(MappedReg),MipsRegLo(ConstReg));
+ }
+ if (Section->Cont.FallThrough) {
+ JneLabel32 ( 0 );
+ Section->Jump.LinkLocation2 = RecompPos - 4;
+ } else if (Section->Jump.FallThrough) {
+ JeLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+
+
+ SetJump8(Jump,RecompPos);
+ } else {
+ JeLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation2 = RecompPos - 4;
+ }
+ } else {
+ if (MipsRegLo(ConstReg) == 0) {
+ OrX86RegToX86Reg(MipsRegLo(MappedReg),MipsRegLo(MappedReg));
+ } else {
+ CompConstToX86reg(MipsRegLo(MappedReg),MipsRegLo(ConstReg));
+ }
+ if (Section->Cont.FallThrough) {
+ JneLabel32 ( 0 );
+ Section->Jump.LinkLocation = RecompPos - 4;
+ } else if (Section->Jump.FallThrough) {
+ JeLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ } else {
+ JeLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+ }
+ }
+ } else if (IsKnown(Opcode.rs) || IsKnown(Opcode.rt)) {
+ uint32_t KnownReg = IsKnown(Opcode.rt)?Opcode.rt:Opcode.rs;
+ uint32_t UnknownReg = IsKnown(Opcode.rt)?Opcode.rs:Opcode.rt;
+
+ if (IsConst(KnownReg)) {
+ if (Is64Bit(KnownReg)) {
+ CompConstToVariable(MipsRegHi(KnownReg),&GPR[UnknownReg].W[1]);
+ } else if (IsSigned(KnownReg)) {
+ CompConstToVariable(((int32_t)MipsRegLo(KnownReg) >> 31),&GPR[UnknownReg].W[1]);
+ } else {
+ CompConstToVariable(0,&GPR[UnknownReg].W[1]);
+ }
+ } else {
+ if (Is64Bit(KnownReg)) {
+ CompX86regToVariable(MipsRegHi(KnownReg),&GPR[UnknownReg].W[1]);
+ } else if (IsSigned(KnownReg)) {
+ ProtectGPR(Section,KnownReg);
+ CompX86regToVariable(Map_TempReg(Section,x86_Any,KnownReg,1),&GPR[UnknownReg].W[1]);
+ } else {
+ CompConstToVariable(0,&GPR[UnknownReg].W[1]);
+ }
+ }
+ if (Section->Jump.FallThrough) {
+ JneLabel8(0);
+ Jump = RecompPos - 1;
+ } else {
+ JneLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+ if (IsConst(KnownReg)) {
+ CompConstToVariable(MipsRegLo(KnownReg),&GPR[UnknownReg].W[0]);
+ } else {
+ CompX86regToVariable(MipsRegLo(KnownReg),&GPR[UnknownReg].W[0]);
+ }
+ if (Section->Cont.FallThrough) {
+ JneLabel32 ( 0 );
+ Section->Jump.LinkLocation2 = RecompPos - 4;
+ } else if (Section->Jump.FallThrough) {
+ JeLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+
+
+ SetJump8(Jump,RecompPos);
+ } else {
+ JeLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation2 = RecompPos - 4;
+ }
+ } else {
+ int32_t x86Reg;
+
+ x86Reg = Map_TempReg(Section,x86_Any,Opcode.rt,1);
+ CompX86regToVariable(x86Reg,&GPR[Opcode.rs].W[1]);
+ if (Section->Jump.FallThrough) {
+ JneLabel8(0);
+ Jump = RecompPos - 1;
+ } else {
+ JneLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+
+ x86Reg = Map_TempReg(Section,x86Reg,Opcode.rt,0);
+ CompX86regToVariable(x86Reg,&GPR[Opcode.rs].W[0]);
+ if (Section->Cont.FallThrough) {
+ JneLabel32 ( 0 );
+ Section->Jump.LinkLocation2 = RecompPos - 4;
+ } else if (Section->Jump.FallThrough) {
+ JeLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+
+
+ SetJump8(Jump,RecompPos);
+ } else {
+ JeLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation2 = RecompPos - 4;
+ }
+ }
+}
+
+void BEQ_Compare (BLOCK_SECTION * Section) {
+ uint8_t *Jump;
+
+ if (IsKnown(Opcode.rs) && IsKnown(Opcode.rt)) {
+ if (IsConst(Opcode.rs) && IsConst(Opcode.rt)) {
+ if (Is64Bit(Opcode.rs) || Is64Bit(Opcode.rt)) {
+ Compile_R4300i_UnknownOpcode(Section);
+ } else if (MipsRegLo(Opcode.rs) == MipsRegLo(Opcode.rt)) {
+ Section->Jump.FallThrough = 1;
+ Section->Cont.FallThrough = 0;
+ } else {
+ Section->Jump.FallThrough = 0;
+ Section->Cont.FallThrough = 1;
+ }
+ } else if (IsMapped(Opcode.rs) && IsMapped(Opcode.rt)) {
+ if (Is64Bit(Opcode.rs) || Is64Bit(Opcode.rt)) {
+ ProtectGPR(Section,Opcode.rs);
+ ProtectGPR(Section,Opcode.rt);
+
+ CompX86RegToX86Reg(
+ Is32Bit(Opcode.rs)?Map_TempReg(Section,x86_Any,Opcode.rs,1):MipsRegHi(Opcode.rs),
+ Is32Bit(Opcode.rt)?Map_TempReg(Section,x86_Any,Opcode.rt,1):MipsRegHi(Opcode.rt)
+ );
+ if (Section->Cont.FallThrough) {
+ JneLabel8(0);
+ Jump = RecompPos - 1;
+ } else {
+ JneLabel32(0);
+ Section->Cont.LinkLocation = RecompPos - 4;
+ }
+ CompX86RegToX86Reg(MipsRegLo(Opcode.rs),MipsRegLo(Opcode.rt));
+ if (Section->Cont.FallThrough) {
+ JeLabel32 ( 0 );
+ Section->Jump.LinkLocation = RecompPos - 4;
+
+
+ SetJump8(Jump,RecompPos);
+ } else if (Section->Jump.FallThrough) {
+ JneLabel32 ( 0 );
+ Section->Cont.LinkLocation2 = RecompPos - 4;
+ } else {
+ JneLabel32 ( 0 );
+ Section->Cont.LinkLocation2 = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+ } else {
+ CompX86RegToX86Reg(MipsRegLo(Opcode.rs),MipsRegLo(Opcode.rt));
+ if (Section->Cont.FallThrough) {
+ JeLabel32 ( 0 );
+ Section->Jump.LinkLocation = RecompPos - 4;
+ } else if (Section->Jump.FallThrough) {
+ JneLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ } else {
+ JneLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+ }
+ } else {
+ uint32_t ConstReg = IsConst(Opcode.rt)?Opcode.rt:Opcode.rs;
+ uint32_t MappedReg = IsConst(Opcode.rt)?Opcode.rs:Opcode.rt;
+
+ if (Is64Bit(ConstReg) || Is64Bit(MappedReg)) {
+ if (Is32Bit(ConstReg) || Is32Bit(MappedReg)) {
+ if (Is32Bit(MappedReg)) {
+ ProtectGPR(Section,MappedReg);
+ CompConstToX86reg(Map_TempReg(Section,x86_Any,MappedReg,1),MipsRegHi(ConstReg));
+ } else {
+ CompConstToX86reg(MipsRegHi(MappedReg),(int32_t)MipsRegLo(ConstReg) >> 31);
+ }
+ } else {
+ CompConstToX86reg(MipsRegHi(MappedReg),MipsRegHi(ConstReg));
+ }
+ if (Section->Cont.FallThrough) {
+ JneLabel8(0);
+ Jump = RecompPos - 1;
+ } else {
+ JneLabel32(0);
+ Section->Cont.LinkLocation = RecompPos - 4;
+ }
+ if (MipsRegLo(ConstReg) == 0) {
+ OrX86RegToX86Reg(MipsRegLo(MappedReg),MipsRegLo(MappedReg));
+ } else {
+ CompConstToX86reg(MipsRegLo(MappedReg),MipsRegLo(ConstReg));
+ }
+ if (Section->Cont.FallThrough) {
+ JeLabel32 ( 0 );
+ Section->Jump.LinkLocation = RecompPos - 4;
+
+
+ SetJump8(Jump,RecompPos);
+ } else if (Section->Jump.FallThrough) {
+ JneLabel32 ( 0 );
+ Section->Cont.LinkLocation2 = RecompPos - 4;
+ } else {
+ JneLabel32 ( 0 );
+ Section->Cont.LinkLocation2 = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+ } else {
+ if (MipsRegLo(ConstReg) == 0) {
+ OrX86RegToX86Reg(MipsRegLo(MappedReg),MipsRegLo(MappedReg));
+ } else {
+ CompConstToX86reg(MipsRegLo(MappedReg),MipsRegLo(ConstReg));
+ }
+ if (Section->Cont.FallThrough) {
+ JeLabel32 ( 0 );
+ Section->Jump.LinkLocation = RecompPos - 4;
+ } else if (Section->Jump.FallThrough) {
+ JneLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ } else {
+ JneLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+ }
+ }
+ } else if (IsKnown(Opcode.rs) || IsKnown(Opcode.rt)) {
+ uint32_t KnownReg = IsKnown(Opcode.rt)?Opcode.rt:Opcode.rs;
+ uint32_t UnknownReg = IsKnown(Opcode.rt)?Opcode.rs:Opcode.rt;
+
+ if (IsConst(KnownReg)) {
+ if (Is64Bit(KnownReg)) {
+ CompConstToVariable(MipsRegHi(KnownReg),&GPR[UnknownReg].W[1]);
+ } else if (IsSigned(KnownReg)) {
+ CompConstToVariable((int32_t)MipsRegLo(KnownReg) >> 31,&GPR[UnknownReg].W[1]);
+ } else {
+ CompConstToVariable(0,&GPR[UnknownReg].W[1]);
+ }
+ } else {
+ ProtectGPR(Section,KnownReg);
+ if (Is64Bit(KnownReg)) {
+ CompX86regToVariable(MipsRegHi(KnownReg),&GPR[UnknownReg].W[1]);
+ } else if (IsSigned(KnownReg)) {
+ CompX86regToVariable(Map_TempReg(Section,x86_Any,KnownReg,1),&GPR[UnknownReg].W[1]);
+ } else {
+ CompConstToVariable(0,&GPR[UnknownReg].W[1]);
+ }
+ }
+ if (Section->Cont.FallThrough) {
+ JneLabel8(0);
+ Jump = RecompPos - 1;
+ } else {
+ JneLabel32(0);
+ Section->Cont.LinkLocation = RecompPos - 4;
+ }
+ if (IsConst(KnownReg)) {
+ CompConstToVariable(MipsRegLo(KnownReg),&GPR[UnknownReg].W[0]);
+ } else {
+ CompX86regToVariable(MipsRegLo(KnownReg),&GPR[UnknownReg].W[0]);
+ }
+ if (Section->Cont.FallThrough) {
+ JeLabel32 ( 0 );
+ Section->Jump.LinkLocation = RecompPos - 4;
+
+
+ SetJump8(Jump,RecompPos);
+ } else if (Section->Jump.FallThrough) {
+ JneLabel32 ( 0 );
+ Section->Cont.LinkLocation2 = RecompPos - 4;
+ } else {
+ JneLabel32 ( 0 );
+ Section->Cont.LinkLocation2 = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+ } else {
+ int32_t x86Reg = Map_TempReg(Section,x86_Any,Opcode.rs,1);
+ CompX86regToVariable(x86Reg,&GPR[Opcode.rt].W[1]);
+ if (Section->Cont.FallThrough) {
+ JneLabel8(0);
+ Jump = RecompPos - 1;
+ } else {
+ JneLabel32(0);
+ Section->Cont.LinkLocation = RecompPos - 4;
+ }
+ CompX86regToVariable(Map_TempReg(Section,x86Reg,Opcode.rs,0),&GPR[Opcode.rt].W[0]);
+ if (Section->Cont.FallThrough) {
+ JeLabel32 ( 0 );
+ Section->Jump.LinkLocation = RecompPos - 4;
+
+
+ SetJump8(Jump,RecompPos);
+ } else if (Section->Jump.FallThrough) {
+ JneLabel32 ( 0 );
+ Section->Cont.LinkLocation2 = RecompPos - 4;
+ } else {
+ JneLabel32 ( 0 );
+ Section->Cont.LinkLocation2 = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+ }
+}
+
+void BGTZ_Compare (BLOCK_SECTION * Section) {
+ if (IsConst(Opcode.rs)) {
+ if (Is64Bit(Opcode.rs)) {
+ if (MipsReg_S(Opcode.rs) > 0) {
+ Section->Jump.FallThrough = 1;
+ Section->Cont.FallThrough = 0;
+ } else {
+ Section->Jump.FallThrough = 0;
+ Section->Cont.FallThrough = 1;
+ }
+ } else {
+ if (MipsRegLo_S(Opcode.rs) > 0) {
+ Section->Jump.FallThrough = 1;
+ Section->Cont.FallThrough = 0;
+ } else {
+ Section->Jump.FallThrough = 0;
+ Section->Cont.FallThrough = 1;
+ }
+ }
+ } else if (IsMapped(Opcode.rs) && Is32Bit(Opcode.rs)) {
+ CompConstToX86reg(MipsRegLo(Opcode.rs),0);
+ if (Section->Jump.FallThrough) {
+ JleLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ } else if (Section->Cont.FallThrough) {
+ JgLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ } else {
+ JleLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+ } else {
+ uint8_t *Jump;
+
+ if (IsMapped(Opcode.rs)) {
+ CompConstToX86reg(MipsRegHi(Opcode.rs),0);
+ } else {
+ CompConstToVariable(0,&GPR[Opcode.rs].W[1]);
+ }
+ if (Section->Jump.FallThrough) {
+ JlLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JgLabel8(0);
+ Jump = RecompPos - 1;
+ } else if (Section->Cont.FallThrough) {
+ JlLabel8(0);
+ Jump = RecompPos - 1;
+ JgLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ } else {
+ JlLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JgLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+
+ if (IsMapped(Opcode.rs)) {
+ CompConstToX86reg(MipsRegLo(Opcode.rs),0);
+ } else {
+ CompConstToVariable(0,&GPR[Opcode.rs].W[0]);
+ }
+ if (Section->Jump.FallThrough) {
+ JeLabel32 ( 0 );
+ Section->Cont.LinkLocation2 = RecompPos - 4;
+
+ *((uint8_t *)(Jump))=(uint8_t)(RecompPos - Jump - 1);
+ } else if (Section->Cont.FallThrough) {
+ JneLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+
+ *((uint8_t *)(Jump))=(uint8_t)(RecompPos - Jump - 1);
+ } else {
+ JneLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ JmpLabel32 ( 0 );
+ Section->Cont.LinkLocation2 = RecompPos - 4;
+ }
+ }
+}
+
+void BLEZ_Compare (BLOCK_SECTION * Section) {
+ if (IsConst(Opcode.rs)) {
+ if (Is64Bit(Opcode.rs)) {
+ if (MipsReg_S(Opcode.rs) <= 0) {
+ Section->Jump.FallThrough = 1;
+ Section->Cont.FallThrough = 0;
+ } else {
+ Section->Jump.FallThrough = 0;
+ Section->Cont.FallThrough = 1;
+ }
+ } else if (IsSigned(Opcode.rs)) {
+ if (MipsRegLo_S(Opcode.rs) <= 0) {
+ Section->Jump.FallThrough = 1;
+ Section->Cont.FallThrough = 0;
+ } else {
+ Section->Jump.FallThrough = 0;
+ Section->Cont.FallThrough = 1;
+ }
+ } else {
+ if (MipsRegLo(Opcode.rs) == 0) {
+ Section->Jump.FallThrough = 1;
+ Section->Cont.FallThrough = 0;
+ } else {
+ Section->Jump.FallThrough = 0;
+ Section->Cont.FallThrough = 1;
+ }
+ }
+ } else {
+ if (IsMapped(Opcode.rs) && Is32Bit(Opcode.rs)) {
+ CompConstToX86reg(MipsRegLo(Opcode.rs),0);
+ if (Section->Jump.FallThrough) {
+ JgLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ } else if (Section->Cont.FallThrough) {
+ JleLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ } else {
+ JgLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+ } else {
+ uint8_t *Jump;
+
+ if (IsMapped(Opcode.rs)) {
+ CompConstToX86reg(MipsRegHi(Opcode.rs),0);
+ } else {
+ CompConstToVariable(0,&GPR[Opcode.rs].W[1]);
+ }
+ if (Section->Jump.FallThrough) {
+ JgLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JlLabel8(0);
+ Jump = RecompPos - 1;
+ } else if (Section->Cont.FallThrough) {
+ JgLabel8(0);
+ Jump = RecompPos - 1;
+ JlLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ } else {
+ JgLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JlLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+
+ if (IsMapped(Opcode.rs)) {
+ CompConstToX86reg(MipsRegLo(Opcode.rs),0);
+ } else {
+ CompConstToVariable(0,&GPR[Opcode.rs].W[0]);
+ }
+ if (Section->Jump.FallThrough) {
+ JneLabel32 ( 0 );
+ Section->Cont.LinkLocation2 = RecompPos - 4;
+
+ *((uint8_t *)(Jump))=(uint8_t)(RecompPos - Jump - 1);
+ } else if (Section->Cont.FallThrough) {
+ JeLabel32 ( 0 );
+ Section->Jump.LinkLocation2 = RecompPos - 4;
+
+ *((uint8_t *)(Jump))=(uint8_t)(RecompPos - Jump - 1);
+ } else {
+ JneLabel32 ( 0 );
+ Section->Cont.LinkLocation2 = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation2 = RecompPos - 4;
+ }
+ }
+ }
+}
+
+void BLTZ_Compare (BLOCK_SECTION * Section) {
+ if (IsConst(Opcode.rs)) {
+ if (Is64Bit(Opcode.rs)) {
+ if (MipsReg_S(Opcode.rs) < 0) {
+ Section->Jump.FallThrough = 1;
+ Section->Cont.FallThrough = 0;
+ } else {
+ Section->Jump.FallThrough = 0;
+ Section->Cont.FallThrough = 1;
+ }
+ } else if (IsSigned(Opcode.rs)) {
+ if (MipsRegLo_S(Opcode.rs) < 0) {
+ Section->Jump.FallThrough = 1;
+ Section->Cont.FallThrough = 0;
+ } else {
+ Section->Jump.FallThrough = 0;
+ Section->Cont.FallThrough = 1;
+ }
+ } else {
+ Section->Jump.FallThrough = 0;
+ Section->Cont.FallThrough = 1;
+ }
+ } else if (IsMapped(Opcode.rs)) {
+ if (Is64Bit(Opcode.rs)) {
+ CompConstToX86reg(MipsRegHi(Opcode.rs),0);
+ if (Section->Jump.FallThrough) {
+ JgeLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ } else if (Section->Cont.FallThrough) {
+ JlLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ } else {
+ JgeLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+ } else if (IsSigned(Opcode.rs)) {
+ CompConstToX86reg(MipsRegLo(Opcode.rs),0);
+ if (Section->Jump.FallThrough) {
+ JgeLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ } else if (Section->Cont.FallThrough) {
+ JlLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ } else {
+ JgeLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+ } else {
+ Section->Jump.FallThrough = 0;
+ Section->Cont.FallThrough = 1;
+ }
+ } else if (IsUnknown(Opcode.rs)) {
+ CompConstToVariable(0,&GPR[Opcode.rs].W[1]);
+ if (Section->Jump.FallThrough) {
+ JgeLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ } else if (Section->Cont.FallThrough) {
+ JlLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ } else {
+ JlLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ JmpLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ }
+ }
+}
+
+void BGEZ_Compare (BLOCK_SECTION * Section) {
+ if (IsConst(Opcode.rs)) {
+ if (Is64Bit(Opcode.rs)) {
+#ifndef EXTERNAL_RELEASE
+ DisplayError("BGEZ 1");
+#endif
+ Compile_R4300i_UnknownOpcode(Section);
+ } else if IsSigned(Opcode.rs) {
+ if (MipsRegLo_S(Opcode.rs) >= 0) {
+ Section->Jump.FallThrough = 1;
+ Section->Cont.FallThrough = 0;
+ } else {
+ Section->Jump.FallThrough = 0;
+ Section->Cont.FallThrough = 1;
+ }
+ } else {
+ Section->Jump.FallThrough = 1;
+ Section->Cont.FallThrough = 0;
+ }
+ } else if (IsMapped(Opcode.rs)) {
+ if (Is64Bit(Opcode.rs)) {
+ CompConstToX86reg(MipsRegHi(Opcode.rs),0);
+ if (Section->Cont.FallThrough) {
+ JgeLabel32 ( 0 );
+ Section->Jump.LinkLocation = RecompPos - 4;
+ } else if (Section->Jump.FallThrough) {
+ JlLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ } else {
+ JlLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+ } else if (IsSigned(Opcode.rs)) {
+ CompConstToX86reg(MipsRegLo(Opcode.rs),0);
+ if (Section->Cont.FallThrough) {
+ JgeLabel32 ( 0 );
+ Section->Jump.LinkLocation = RecompPos - 4;
+ } else if (Section->Jump.FallThrough) {
+ JlLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ } else {
+ JlLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+ } else {
+ Section->Jump.FallThrough = 1;
+ Section->Cont.FallThrough = 0;
+ }
+ } else {
+ CompConstToVariable(0,&GPR[Opcode.rs].W[1]);
+ if (Section->Cont.FallThrough) {
+ JgeLabel32 ( 0 );
+ Section->Jump.LinkLocation = RecompPos - 4;
+ } else if (Section->Jump.FallThrough) {
+ JlLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ } else {
+ JlLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+ }
+}
+
+void COP1_BCF_Compare (BLOCK_SECTION * Section) {
+ TestVariable(FPCSR_C,&FPCR[31]);
+ if (Section->Cont.FallThrough) {
+ JeLabel32 ( 0 );
+ Section->Jump.LinkLocation = RecompPos - 4;
+ } else if (Section->Jump.FallThrough) {
+ JneLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ } else {
+ JneLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+}
+
+void COP1_BCT_Compare (BLOCK_SECTION * Section) {
+ TestVariable(FPCSR_C,&FPCR[31]);
+ if (Section->Cont.FallThrough) {
+ JneLabel32 ( 0 );
+ Section->Jump.LinkLocation = RecompPos - 4;
+ } else if (Section->Jump.FallThrough) {
+ JeLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ } else {
+ JeLabel32 ( 0 );
+ Section->Cont.LinkLocation = RecompPos - 4;
+ JmpLabel32(0);
+ Section->Jump.LinkLocation = RecompPos - 4;
+ }
+}
+/************************* OpCode functions *************************/
+void Compile_R4300i_J (BLOCK_SECTION * Section) {
+ if ( NextInstruction == NORMAL ) {
+ Section->Jump.TargetPC = (Section->CompilePC & 0xF0000000) + (Opcode.target << 2);;
+ Section->Jump.FallThrough = 1;
+ Section->Jump.LinkLocation = NULL;
+ Section->Jump.LinkLocation2 = NULL;
+ NextInstruction = DO_DELAY_SLOT;
+ if ((Section->CompilePC & 0xFFC) == 0xFFC) {
+ memcpy(&Section->Jump.RegSet,&Section->RegWorking,sizeof(REG_INFO));
+ GenerateSectionLinkage(Section);
+ NextInstruction = END_BLOCK;
+ }
+ } else if (NextInstruction == DELAY_SLOT_DONE ) {
+ memcpy(&Section->Jump.RegSet,&Section->RegWorking,sizeof(REG_INFO));
+ GenerateSectionLinkage(Section);
+ NextInstruction = END_BLOCK;
+ } else {
+#ifndef EXTERNAL_RELEASE
+ DisplayError("WTF\n\nJal\nNextInstruction = %X", NextInstruction);
+#endif
+ }
+}
+
+void Compile_R4300i_JAL (BLOCK_SECTION * Section) {
+
+ //UnMap_TempReg(Section);
+ if ( NextInstruction == NORMAL ) {
+
+ UnMap_GPR(Section, 31, 0);
+ MipsRegLo(31) = Section->CompilePC + 8;
+ MipsRegState(31) = STATE_CONST_32;
+ if ((Section->CompilePC & 0xFFC) == 0xFFC) {
+ MoveConstToVariable((Section->CompilePC & 0xF0000000) + (Opcode.target << 2),&JumpToLocation);
+ MoveConstToVariable(Section->CompilePC + 4,&PROGRAM_COUNTER);
+ if (BlockCycleCount != 0) {
+ AddConstToVariable(BlockCycleCount,&CP0[9]);
+ SubConstFromVariable(BlockCycleCount,&Timers->Timer);
+ }
+ if (BlockRandomModifier != 0) { SubConstFromVariable(BlockRandomModifier,&CP0[1]); }
+ WriteBackRegisters(Section);
+ MoveConstToVariable(DELAY_SLOT,&NextInstruction);
+ Ret();
+ NextInstruction = END_BLOCK;
+ return;
+ }
+ NextInstruction = DO_DELAY_SLOT;
+ } else if (NextInstruction == DELAY_SLOT_DONE ) {
+ MoveConstToVariable((Section->CompilePC & 0xF0000000) + (Opcode.target << 2),&PROGRAM_COUNTER);
+ CompileExit((uint32_t)-1,&Section->RegWorking,Normal,1,NULL);
+ NextInstruction = END_BLOCK;
+ } else {
+#ifndef EXTERNAL_RELEASE
+ DisplayError("WTF\n\nBranch\nNextInstruction = %X", NextInstruction);
+#endif
+ }
+ return;
+
+ if ( NextInstruction == NORMAL ) {
+
+
+ UnMap_GPR(Section, 31, 0);
+ MipsRegLo(31) = Section->CompilePC + 8;
+ MipsRegState(31) = STATE_CONST_32;
+ NextInstruction = DO_DELAY_SLOT;
+
+ Section->Jump.TargetPC = (Section->CompilePC & 0xF0000000) + (Opcode.target << 2);
+ Section->Jump.FallThrough = 1;
+ Section->Jump.LinkLocation = NULL;
+ Section->Jump.LinkLocation2 = NULL;
+ if ((Section->CompilePC & 0xFFC) == 0xFFC) {
+ memcpy(&Section->Jump.RegSet,&Section->RegWorking,sizeof(REG_INFO));
+ GenerateSectionLinkage(Section);
+ NextInstruction = END_BLOCK;
+ }
+ } else if (NextInstruction == DELAY_SLOT_DONE ) {
+ memcpy(&Section->Jump.RegSet,&Section->RegWorking,sizeof(REG_INFO));
+ GenerateSectionLinkage(Section);
+ NextInstruction = END_BLOCK;
+ } else {
+#ifndef EXTERNAL_RELEASE
+ DisplayError("WTF\n\nJal\nNextInstruction = %X", NextInstruction);
+#endif
+ }
+}
+
+void Compile_R4300i_ADDI (BLOCK_SECTION * Section) {
+
+ if (Opcode.rt == 0) { return; }
+ if (IsConst(Opcode.rs)) {
+ if (IsMapped(Opcode.rt)) { UnMap_GPR(Section,Opcode.rt, 0); }
+ MipsRegLo(Opcode.rt) = MipsRegLo(Opcode.rs) + (short)Opcode.immediate;
+ MipsRegState(Opcode.rt) = STATE_CONST_32;
+ return;
+ }
+ Map_GPR_32bit(Section,Opcode.rt,1,Opcode.rs);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(MipsRegLo(Opcode.rt));
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(MipsRegLo(Opcode.rt));
+ } else {
+ AddConstToX86Reg(MipsRegLo(Opcode.rt),(short)Opcode.immediate);
+ }
+
+}
+
+void Compile_R4300i_ADDIU (BLOCK_SECTION * Section) {
+
+
+
+ if (Opcode.rt == 0) { return; }
+
+ if (IsConst(Opcode.rs)) {
+ if (IsMapped(Opcode.rt)) { UnMap_GPR(Section,Opcode.rt, 0); }
+ MipsRegLo(Opcode.rt) = MipsRegLo(Opcode.rs) + (short)Opcode.immediate;
+ MipsRegState(Opcode.rt) = STATE_CONST_32;
+ return;
+ }
+ Map_GPR_32bit(Section,Opcode.rt,1,Opcode.rs);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(MipsRegLo(Opcode.rt));
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(MipsRegLo(Opcode.rt));
+ } else {
+ AddConstToX86Reg(MipsRegLo(Opcode.rt),(short)Opcode.immediate);
+ }
+}
+
+void Compile_R4300i_SLTIU (BLOCK_SECTION * Section) {
+
+ if (Opcode.rt == 0) { return; }
+
+ if (IsConst(Opcode.rs)) {
+ uint32_t Result;
+
+ if (Is64Bit(Opcode.rs)) {
+ int64_t Immediate = (int64_t)((short)Opcode.immediate);
+ Result = MipsReg(Opcode.rs) < ((unsigned)(Immediate))?1:0;
+ } else if (Is32Bit(Opcode.rs)) {
+ Result = MipsRegLo(Opcode.rs) < ((unsigned)((short)Opcode.immediate))?1:0;
+ }
+ UnMap_GPR(Section,Opcode.rt, 0);
+ MipsRegState(Opcode.rt) = STATE_CONST_32;
+ MipsRegLo(Opcode.rt) = Result;
+ } else if (IsMapped(Opcode.rs)) {
+ if (Is64Bit(Opcode.rs)) {
+ uint8_t * Jump[2];
+
+ CompConstToX86reg(MipsRegHi(Opcode.rs),((short)Opcode.immediate >> 31));
+ JeLabel8(0);
+ Jump[0] = RecompPos - 1;
+ SetbVariable(&BranchCompare);
+ JmpLabel8(0);
+ Jump[1] = RecompPos - 1;
+
+
+ *((uint8_t *)(Jump[0]))=(uint8_t)(RecompPos - Jump[0] - 1);
+ CompConstToX86reg(MipsRegLo(Opcode.rs),(short)Opcode.immediate);
+ SetbVariable(&BranchCompare);
+
+
+ *((uint8_t *)(Jump[1]))=(uint8_t)(RecompPos - Jump[1] - 1);
+ Map_GPR_32bit(Section,Opcode.rt,0, -1);
+ MoveVariableToX86reg(&BranchCompare,MipsRegLo(Opcode.rt));
+ } else {
+ CompConstToX86reg(MipsRegLo(Opcode.rs),(short)Opcode.immediate);
+ SetbVariable(&BranchCompare);
+ Map_GPR_32bit(Section,Opcode.rt,0, -1);
+ MoveVariableToX86reg(&BranchCompare,MipsRegLo(Opcode.rt));
+ }
+ } else {
+ uint8_t * Jump;
+
+ CompConstToVariable(((short)Opcode.immediate >> 31),&GPR[Opcode.rs].W[1]);
+ JneLabel8(0);
+ Jump = RecompPos - 1;
+ CompConstToVariable((short)Opcode.immediate,&GPR[Opcode.rs].W[0]);
+
+
+ *((uint8_t *)(Jump))=(uint8_t)(RecompPos - Jump - 1);
+ SetbVariable(&BranchCompare);
+ Map_GPR_32bit(Section,Opcode.rt,0, -1);
+ MoveVariableToX86reg(&BranchCompare,MipsRegLo(Opcode.rt));
+
+
+ /*SetbVariable(&BranchCompare);
+ JmpLabel8(0);
+ Jump[1] = RecompPos - 1;
+
+
+ *((uint8_t *)(Jump[0]))=(uint8_t)(RecompPos - Jump[0] - 1);
+ CompConstToVariable((short)Opcode.immediate,&GPR[Opcode.rs].W[0]);
+ SetbVariable(&BranchCompare);
+
+
+ *((uint8_t *)(Jump[1]))=(uint8_t)(RecompPos - Jump[1] - 1);
+ Map_GPR_32bit(Section,Opcode.rt,0, -1);
+ MoveVariableToX86reg(&BranchCompare,MipsRegLo(Opcode.rt));*/
+ }
+}
+
+void Compile_R4300i_SLTI (BLOCK_SECTION * Section) {
+
+ if (Opcode.rt == 0) { return; }
+
+ if (IsConst(Opcode.rs)) {
+ uint32_t Result;
+
+ if (Is64Bit(Opcode.rs)) {
+ int64_t Immediate = (int64_t)((short)Opcode.immediate);
+ Result = (int64_t)MipsReg(Opcode.rs) < Immediate?1:0;
+ } else if (Is32Bit(Opcode.rs)) {
+ Result = MipsRegLo_S(Opcode.rs) < (short)Opcode.immediate?1:0;
+ }
+ UnMap_GPR(Section,Opcode.rt, 0);
+ MipsRegState(Opcode.rt) = STATE_CONST_32;
+ MipsRegLo(Opcode.rt) = Result;
+ } else if (IsMapped(Opcode.rs)) {
+ if (Is64Bit(Opcode.rs)) {
+ uint8_t * Jump[2];
+
+ CompConstToX86reg(MipsRegHi(Opcode.rs),((short)Opcode.immediate >> 31));
+ JeLabel8(0);
+ Jump[0] = RecompPos - 1;
+ SetlVariable(&BranchCompare);
+ JmpLabel8(0);
+ Jump[1] = RecompPos - 1;
+
+
+ *((uint8_t *)(Jump[0]))=(uint8_t)(RecompPos - Jump[0] - 1);
+ CompConstToX86reg(MipsRegLo(Opcode.rs),(short)Opcode.immediate);
+ SetbVariable(&BranchCompare);
+
+
+ *((uint8_t *)(Jump[1]))=(uint8_t)(RecompPos - Jump[1] - 1);
+ Map_GPR_32bit(Section,Opcode.rt,0, -1);
+ MoveVariableToX86reg(&BranchCompare,MipsRegLo(Opcode.rt));
+ } else {
+ /* CompConstToX86reg(MipsRegLo(Opcode.rs),(short)Opcode.immediate);
+ SetlVariable(&BranchCompare);
+ Map_GPR_32bit(Section,Opcode.rt,0, -1);
+ MoveVariableToX86reg(&BranchCompare,MipsRegLo(Opcode.rt));
+ */
+ ProtectGPR(Section, Opcode.rs);
+ Map_GPR_32bit(Section,Opcode.rt,0, -1);
+ CompConstToX86reg(MipsRegLo(Opcode.rs),(short)Opcode.immediate);
+
+ if (MipsRegLo(Opcode.rt) > x86_EDX) {
+ SetlVariable(&BranchCompare);
+ MoveVariableToX86reg(&BranchCompare,MipsRegLo(Opcode.rt));
+ } else {
+ Setl(MipsRegLo(Opcode.rt));
+ AndConstToX86Reg(MipsRegLo(Opcode.rt), 1);
+ }
+ }
+ } else {
+ uint8_t * Jump[2];
+
+ CompConstToVariable(((short)Opcode.immediate >> 31),&GPR[Opcode.rs].W[1]);
+ JeLabel8(0);
+ Jump[0] = RecompPos - 1;
+ SetlVariable(&BranchCompare);
+ JmpLabel8(0);
+ Jump[1] = RecompPos - 1;
+
+
+ *((uint8_t *)(Jump[0]))=(uint8_t)(RecompPos - Jump[0] - 1);
+ CompConstToVariable((short)Opcode.immediate,&GPR[Opcode.rs].W[0]);
+ SetbVariable(&BranchCompare);
+
+
+ *((uint8_t *)(Jump[1]))=(uint8_t)(RecompPos - Jump[1] - 1);
+ Map_GPR_32bit(Section,Opcode.rt,0, -1);
+ MoveVariableToX86reg(&BranchCompare,MipsRegLo(Opcode.rt));
+ }
+}
+
+void Compile_R4300i_ANDI (BLOCK_SECTION * Section) {
+
+
+ if (Opcode.rt == 0) { return;}
+
+ if (IsConst(Opcode.rs)) {
+ if (IsMapped(Opcode.rt)) { UnMap_GPR(Section,Opcode.rt, 0); }
+ MipsRegState(Opcode.rt) = STATE_CONST_32;
+ MipsRegLo(Opcode.rt) = MipsRegLo(Opcode.rs) & Opcode.immediate;
+ } else if (Opcode.immediate != 0) {
+ Map_GPR_32bit(Section,Opcode.rt,0,Opcode.rs);
+ AndConstToX86Reg(MipsRegLo(Opcode.rt),Opcode.immediate);
+ } else {
+ Map_GPR_32bit(Section,Opcode.rt,0,0);
+ }
+}
+
+void Compile_R4300i_ORI (BLOCK_SECTION * Section) {
+
+ if (Opcode.rt == 0) { return;}
+
+ if (IsConst(Opcode.rs)) {
+ if (IsMapped(Opcode.rt)) { UnMap_GPR(Section,Opcode.rt, 0); }
+ MipsRegState(Opcode.rt) = MipsRegState(Opcode.rs);
+ MipsRegHi(Opcode.rt) = MipsRegHi(Opcode.rs);
+ MipsRegLo(Opcode.rt) = MipsRegLo(Opcode.rs) | Opcode.immediate;
+ } else if (IsMapped(Opcode.rs)) {
+ if (Is64Bit(Opcode.rs)) {
+ Map_GPR_64bit(Section,Opcode.rt,Opcode.rs);
+ } else {
+ Map_GPR_32bit(Section,Opcode.rt,IsSigned(Opcode.rs),Opcode.rs);
+ }
+ OrConstToX86Reg(Opcode.immediate,MipsRegLo(Opcode.rt));
+ } else {
+ Map_GPR_64bit(Section,Opcode.rt,Opcode.rs);
+ OrConstToX86Reg(Opcode.immediate,MipsRegLo(Opcode.rt));
+ }
+}
+
+void Compile_R4300i_XORI (BLOCK_SECTION * Section) {
+
+ if (Opcode.rt == 0) { return;}
+
+ if (IsConst(Opcode.rs)) {
+ if (Opcode.rs != Opcode.rt) { UnMap_GPR(Section,Opcode.rt, 0); }
+ MipsRegState(Opcode.rt) = MipsRegState(Opcode.rs);
+ MipsRegHi(Opcode.rt) = MipsRegHi(Opcode.rs);
+ MipsRegLo(Opcode.rt) = MipsRegLo(Opcode.rs) ^ Opcode.immediate;
+ } else {
+ if (IsMapped(Opcode.rs) && Is32Bit(Opcode.rs)) {
+ Map_GPR_32bit(Section,Opcode.rt,IsSigned(Opcode.rs),Opcode.rs);
+ } else {
+ Map_GPR_64bit(Section,Opcode.rt,Opcode.rs);
+ }
+ if (Opcode.immediate != 0) { XorConstToX86Reg(MipsRegLo(Opcode.rt),Opcode.immediate); }
+ }
+}
+
+void Compile_R4300i_LUI (BLOCK_SECTION * Section) {
+
+ if (Opcode.rt == 0) { return;}
+
+ UnMap_GPR(Section,Opcode.rt, 0);
+ MipsRegLo(Opcode.rt) = ((short)Opcode.offset << 16);
+ MipsRegState(Opcode.rt) = STATE_CONST_32;
+}
+
+void Compile_R4300i_DADDIU (BLOCK_SECTION * Section) {
+
+
+ if (Opcode.rs != 0) { UnMap_GPR(Section,Opcode.rs,1); }
+ if (Opcode.rs != 0) { UnMap_GPR(Section,Opcode.rt,1); }
+ Pushad();
+ MoveConstToVariable(Opcode.Hex, &Opcode.Hex );
+ Call_Direct(r4300i_DADDIU);
+ Popad();
+}
+
+void Compile_R4300i_LDL (BLOCK_SECTION * Section) {
+
+ if (Opcode.base != 0) { UnMap_GPR(Section,Opcode.base,1); }
+ if (Opcode.rt != 0) { UnMap_GPR(Section,Opcode.rt,1); }
+ Pushad();
+ MoveConstToVariable(Opcode.Hex, &Opcode.Hex );
+ Call_Direct(r4300i_LDL);
+ Popad();
+
+}
+
+void Compile_R4300i_LDR (BLOCK_SECTION * Section) {
+
+ if (Opcode.base != 0) { UnMap_GPR(Section,Opcode.base,1); }
+ if (Opcode.rt != 0) { UnMap_GPR(Section,Opcode.rt,1); }
+ Pushad();
+ MoveConstToVariable(Opcode.Hex, &Opcode.Hex );
+ Call_Direct(r4300i_LDR);
+ Popad();
+}
+
+
+void Compile_R4300i_LB (BLOCK_SECTION * Section) {
+ uint32_t TempReg1, TempReg2;
+
+ if (Opcode.rt == 0) return;
+
+// UnMap_TempReg(Section); //hax
+ if (IsConst(Opcode.base)) {
+ uint32_t Address = (MipsRegLo(Opcode.base) + (short)Opcode.offset) ^ 3;
+ Map_GPR_32bit(Section,Opcode.rt,1,0);
+ Compile_LB(MipsRegLo(Opcode.rt),Address,1);
+ return;
+ }
+ if (IsMapped(Opcode.rt)) { ProtectGPR(Section,Opcode.rt); }
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+
+
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+
+ CompileReadTLBMiss(Section,TempReg1,TempReg2);
+ XorConstToX86Reg(TempReg1|x64_Reg,3);
+ Map_GPR_32bit(Section,Opcode.rt,1,-1);
+ MoveSxByteX86regPointerToX86reg(TempReg1, TempReg2,MipsRegLo(Opcode.rt));
+}
+
+
+void Compile_R4300i_LH (BLOCK_SECTION * Section) {
+ uint32_t TempReg1, TempReg2;
+
+
+
+ if (Opcode.rt == 0) return;
+
+ if (IsConst(Opcode.base)) {
+ uint32_t Address = (MipsRegLo(Opcode.base) + (short)Opcode.offset) ^ 2;
+ Map_GPR_32bit(Section,Opcode.rt,1,0);
+ Compile_LH(MipsRegLo(Opcode.rt),Address,1);
+ return;
+ }
+ if (IsMapped(Opcode.rt)) { ProtectGPR(Section,Opcode.rt); }
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+ CompileReadTLBMiss(Section,TempReg1,TempReg2);
+ XorConstToX86Reg(TempReg1,2);
+ Map_GPR_32bit(Section,Opcode.rt,1,-1);
+ MoveSxHalfX86regPointerToX86reg(TempReg1, TempReg2,MipsRegLo(Opcode.rt));
+
+}
+
+void Compile_R4300i_LWL (BLOCK_SECTION * Section) {
+ uint32_t TempReg1, TempReg2, Offset, shift;
+
+
+
+ if (Opcode.rt == 0) return;
+
+ if (IsConst(Opcode.base)) {
+ uint32_t Address, Value;
+
+ Address = MipsRegLo(Opcode.base) + (short)Opcode.offset;
+ Offset = Address & 3;
+
+ Map_GPR_32bit(Section,Opcode.rt,1,Opcode.rt);
+ Value = Map_TempReg(Section,x86_Any,-1,0);
+ Compile_LW(Value,(Address & ~3));
+ AndConstToX86Reg(MipsRegLo(Opcode.rt),LWL_MASK[Offset]);
+ ShiftLeftSignImmed(Value,(uint8_t)LWL_SHIFT[Offset]);
+ AddX86RegToX86Reg(MipsRegLo(Opcode.rt),Value);
+ return;
+ }
+
+ shift = Map_TempReg(Section,x86_ECX,-1,0);
+ if (IsMapped(Opcode.rt)) { ProtectGPR(Section,Opcode.rt); }
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ UnProtectGPR(Section,Opcode.base);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+
+ CompileReadTLBMiss(Section,TempReg1,TempReg2);
+
+ Offset = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, Offset);
+ AndConstToX86Reg(Offset,3);
+ AndConstToX86Reg(TempReg1,~3);
+
+ Map_GPR_32bit(Section,Opcode.rt,1,Opcode.rt);
+ AndVariableDispToX86Reg(LWL_MASK,MipsRegLo(Opcode.rt),Offset,4);
+ MoveVariableDispToX86Reg(LWL_SHIFT,shift,Offset,4);
+
+ MoveX86regPointerToX86reg(TempReg1, TempReg2,TempReg1);
+
+ ShiftLeftSign(TempReg1);
+ AddX86RegToX86Reg(MipsRegLo(Opcode.rt),TempReg1);
+}
+
+void Compile_R4300i_LW (BLOCK_SECTION * Section) {
+ uint32_t TempReg1, TempReg2;
+
+ if (Opcode.rt == 0) return;
+
+ {
+ if (IsConst(Opcode.base)) {
+ uint32_t Address = MipsRegLo(Opcode.base) + (short)Opcode.offset;
+ Map_GPR_32bit(Section,Opcode.rt,1,-1);
+ Compile_LW(MipsRegLo(Opcode.rt),Address);
+ return;
+ }
+
+ if (IsMapped(Opcode.rt)) { ProtectGPR(Section,Opcode.rt); }
+ if (IsMapped(Opcode.base) && Opcode.offset == 0) {
+ ProtectGPR(Section,Opcode.base);
+ TempReg1 = MipsRegLo(Opcode.base);
+ } else {
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+ }
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+ Map_GPR_32bit(Section,Opcode.rt,1,-1);
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+ CompileReadTLBMiss(Section,TempReg1,TempReg2);
+ MoveX86regPointerToX86reg(TempReg1, TempReg2,MipsRegLo(Opcode.rt));
+ }
+}
+
+void Compile_R4300i_LBU (BLOCK_SECTION * Section) {
+ uint32_t TempReg1, TempReg2;
+
+
+
+ if (Opcode.rt == 0) return;
+
+ if (IsConst(Opcode.base)) {
+ uint32_t Address = (MipsRegLo(Opcode.base) + (short)Opcode.offset) ^ 3;
+ Map_GPR_32bit(Section,Opcode.rt,0,0);
+ Compile_LB(MipsRegLo(Opcode.rt),Address,0);
+ return;
+ }
+ if (IsMapped(Opcode.rt)) { ProtectGPR(Section,Opcode.rt); }
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+ CompileReadTLBMiss(Section,TempReg1,TempReg2);
+ XorConstToX86Reg(TempReg1,3);
+ Map_GPR_32bit(Section,Opcode.rt,0,-1);
+ MoveZxByteX86regPointerToX86reg(TempReg1, TempReg2,MipsRegLo(Opcode.rt));
+
+}
+
+void Compile_R4300i_LHU (BLOCK_SECTION * Section) {
+ uint32_t TempReg1, TempReg2;
+
+
+
+ if (Opcode.rt == 0) return;
+
+ if (IsConst(Opcode.base)) {
+ uint32_t Address = (MipsRegLo(Opcode.base) + (short)Opcode.offset) ^ 2;
+ Map_GPR_32bit(Section,Opcode.rt,0,0);
+ Compile_LH(MipsRegLo(Opcode.rt),Address,0);
+ return;
+ }
+ if (IsMapped(Opcode.rt)) { ProtectGPR(Section,Opcode.rt); }
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+ CompileReadTLBMiss(Section,TempReg1,TempReg2);
+ XorConstToX86Reg(TempReg1,2);
+ Map_GPR_32bit(Section,Opcode.rt,0,-1);
+ MoveZxHalfX86regPointerToX86reg(TempReg1, TempReg2,MipsRegLo(Opcode.rt));
+
+}
+
+void Compile_R4300i_LWR (BLOCK_SECTION * Section) {
+ uint32_t TempReg1, TempReg2, Offset, shift;
+
+
+
+ if (Opcode.rt == 0) return;
+
+ if (IsConst(Opcode.base)) {
+ uint32_t Address, Value;
+
+ Address = MipsRegLo(Opcode.base) + (short)Opcode.offset;
+ Offset = Address & 3;
+
+ Map_GPR_32bit(Section,Opcode.rt,1,Opcode.rt);
+ Value = Map_TempReg(Section,x86_Any,-1,0);
+ Compile_LW(Value,(Address & ~3));
+ AndConstToX86Reg(MipsRegLo(Opcode.rt),LWR_MASK[Offset]);
+ ShiftRightUnsignImmed(Value,(uint8_t)LWR_SHIFT[Offset]);
+ AddX86RegToX86Reg(MipsRegLo(Opcode.rt),Value);
+ return;
+ }
+
+ shift = Map_TempReg(Section,x86_ECX,-1,0);
+ if (IsMapped(Opcode.rt)) { ProtectGPR(Section,Opcode.rt); }
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ UnProtectGPR(Section,Opcode.base);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+
+
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+
+ CompileReadTLBMiss(Section,TempReg1,TempReg2);
+
+ Offset = Map_TempReg(Section,x64_Any,-1,0);
+ //BreakPoint();
+ MoveX86RegToX86Reg(TempReg1, Offset);
+ AndConstToX86Reg(Offset,3);
+ AndConstToX86Reg(TempReg1,~3);
+
+ Map_GPR_32bit(Section,Opcode.rt,1,Opcode.rt);
+ AndVariableDispToX86Reg(LWR_MASK,MipsRegLo(Opcode.rt),Offset,4);
+ MoveVariableDispToX86Reg(LWR_SHIFT,shift,Offset,4);
+
+ MoveX86regPointerToX86reg(TempReg1, TempReg2,TempReg1);
+
+ ShiftRightUnsign(TempReg1);
+ AddX86RegToX86Reg(MipsRegLo(Opcode.rt),TempReg1);
+}
+
+void Compile_R4300i_LWU (BLOCK_SECTION * Section) { //added by Witten
+ uint32_t TempReg1, TempReg2;
+
+
+
+ if (Opcode.rt == 0) return;
+
+ if (IsConst(Opcode.base)) {
+ uint32_t Address = (MipsRegLo(Opcode.base) + (short)Opcode.offset);
+ Map_GPR_32bit(Section,Opcode.rt,0,0);
+ Compile_LW(MipsRegLo(Opcode.rt),Address);
+ return;
+ }
+ if (IsMapped(Opcode.rt)) { ProtectGPR(Section,Opcode.rt); }
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ //MoveVariableDispToX86Reg(TLB_Map,TempReg2,TempReg2,8);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+ CompileReadTLBMiss(Section,TempReg1,TempReg2);
+ Map_GPR_32bit(Section,Opcode.rt,0,-1);
+ MoveZxHalfX86regPointerToX86reg(TempReg1, TempReg2,MipsRegLo(Opcode.rt));
+
+}
+
+void Compile_R4300i_SB (BLOCK_SECTION * Section){
+ uint32_t TempReg1, TempReg2;
+
+
+
+ if (IsConst(Opcode.base)) {
+ uint32_t Address = (MipsRegLo(Opcode.base) + (short)Opcode.offset) ^ 3;
+
+ if (IsConst(Opcode.rt)) {
+ Compile_SB_Const((uint8_t)MipsRegLo(Opcode.rt), Address);
+ } else if (IsMapped(Opcode.rt) && Is8BitReg(MipsRegLo(Opcode.rt))) {
+ Compile_SB_Register(MipsRegLo(Opcode.rt), Address);
+ } else {
+ Compile_SB_Register(Map_TempReg(Section,x86_Any8Bit,Opcode.rt,0), Address);
+ }
+ return;
+ }
+ if (IsMapped(Opcode.rt)) { ProtectGPR(Section,Opcode.rt); }
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ UnProtectGPR(Section,Opcode.base);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ //MoveVariableDispToX86Reg(TLB_Map,TempReg2,TempReg2,8);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+ //For tlb miss
+ //0041C522 85 C0 test eax,eax
+ //0041C524 75 01 jne 0041C527
+
+ XorConstToX86Reg(TempReg1 | x64_Reg,3);
+ if (IsConst(Opcode.rt)) {
+ MoveConstByteToX86regPointer((uint8_t)MipsRegLo(Opcode.rt),TempReg1, TempReg2);
+ } else if (IsMapped(Opcode.rt) && Is8BitReg(MipsRegLo(Opcode.rt))) {
+ MoveX86regByteToX86regPointer(MipsRegLo(Opcode.rt),TempReg1, TempReg2);
+ } else {
+
+ UnProtectGPR(Section,Opcode.rt);
+ MoveX86regByteToX86regPointer(Map_TempReg(Section,x86_Any8Bit,Opcode.rt,0),TempReg1, TempReg2);
+ }
+
+}
+
+void Compile_R4300i_SH (BLOCK_SECTION * Section){
+ uint32_t TempReg1, TempReg2;
+
+
+
+ if (IsConst(Opcode.base)) {
+ uint32_t Address = (MipsRegLo(Opcode.base) + (short)Opcode.offset) ^ 2;
+
+ if (IsConst(Opcode.rt)) {
+ Compile_SH_Const((uint16_t)MipsRegLo(Opcode.rt), Address);
+ } else if (IsMapped(Opcode.rt)) {
+ Compile_SH_Register(MipsRegLo(Opcode.rt), Address);
+ } else {
+ Compile_SH_Register(Map_TempReg(Section,x86_Any,Opcode.rt,0), Address);
+ }
+ return;
+ }
+ if (IsMapped(Opcode.rt)) { ProtectGPR(Section,Opcode.rt); }
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ UnProtectGPR(Section,Opcode.base);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ //MoveVariableDispToX86Reg(TLB_Map,TempReg2,TempReg2,8);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+ //For tlb miss
+ //0041C522 85 C0 test eax,eax
+ //0041C524 75 01 jne 0041C527
+
+ XorConstToX86Reg(TempReg1,2);
+ if (IsConst(Opcode.rt)) {
+ MoveConstHalfToX86regPointer((uint16_t)MipsRegLo(Opcode.rt),TempReg1, TempReg2);
+ } else if (IsMapped(Opcode.rt)) {
+ MoveX86regHalfToX86regPointer(MipsRegLo(Opcode.rt),TempReg1, TempReg2);
+ } else {
+ MoveX86regHalfToX86regPointer(Map_TempReg(Section,x86_Any,Opcode.rt,0),TempReg1, TempReg2);
+ }
+
+}
+
+void Compile_R4300i_SWL (BLOCK_SECTION * Section) {
+ uint32_t TempReg1, TempReg2, Value, Offset, shift;
+
+
+
+ if (IsConst(Opcode.base)) {
+ uint32_t Address;
+
+ Address = MipsRegLo(Opcode.base) + (short)Opcode.offset;
+ Offset = Address & 3;
+
+ Value = Map_TempReg(Section,x86_Any,-1,0);
+ Compile_LW(Value,(Address & ~3));
+ AndConstToX86Reg(Value,SWL_MASK[Offset]);
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.rt,0);
+ ShiftRightUnsignImmed(TempReg1,(uint8_t)SWL_SHIFT[Offset]);
+ AddX86RegToX86Reg(Value,TempReg1);
+ Compile_SW_Register(Value, (Address & ~3));
+ return;
+ }
+ shift = Map_TempReg(Section,x86_ECX,-1,0);
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ UnProtectGPR(Section,Opcode.base);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ //MoveVariableDispToX86Reg(TLB_Map,TempReg2,TempReg2,8);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+
+ //For tlb miss
+ //0041C522 85 C0 test eax,eax
+ //0041C524 75 01 jne 0041C527
+
+ Offset = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, Offset);
+ AndConstToX86Reg(Offset,3);
+ AndConstToX86Reg(TempReg1,~3);
+
+ Value = Map_TempReg(Section,x86_Any,-1,0);
+
+ MoveX86regPointerToX86reg(TempReg1, TempReg2,Value);
+
+
+ AndVariableDispToX86Reg(SWL_MASK,Value,Offset,4);
+ if (!IsConst(Opcode.rt) || MipsRegLo(Opcode.rt) != 0) {
+ MoveVariableDispToX86Reg(SWL_SHIFT,shift,Offset,4);
+ if (IsConst(Opcode.rt)) {
+ MoveConstToX86reg(MipsRegLo(Opcode.rt),Offset);
+ } else if (IsMapped(Opcode.rt)) {
+ MoveX86RegToX86Reg(MipsRegLo(Opcode.rt),Offset);
+ } else {
+ MoveVariableToX86reg(&GPR[Opcode.rt].UW[0],Offset);
+ }
+ ShiftRightUnsign(Offset);
+ AddX86RegToX86Reg(Value,Offset);
+ }
+
+
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ //MoveVariableDispToX86Reg(TLB_Map,TempReg2,TempReg2,8);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+
+ MoveX86regToX86regPointer(Value,TempReg1, TempReg2);
+
+}
+
+void Compile_R4300i_SW (BLOCK_SECTION * Section) {
+ uint32_t TempReg1, TempReg2;
+
+ {
+ if (IsConst(Opcode.base)) {
+ uint32_t Address = MipsRegLo(Opcode.base) + (short)Opcode.offset;
+
+
+ if (IsConst(Opcode.rt)) {
+ Compile_SW_Const(MipsRegLo(Opcode.rt), Address);
+ } else if (IsMapped(Opcode.rt)) {
+ Compile_SW_Register(MipsRegLo(Opcode.rt), Address);
+ } else {
+ Compile_SW_Register(Map_TempReg(Section,x86_Any,Opcode.rt,0), Address);
+ }
+ return;
+ }
+ if (IsMapped(Opcode.rt)) { ProtectGPR(Section,Opcode.rt); }
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ UnProtectGPR(Section,Opcode.base);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+ //For tlb miss
+ //0041C522 85 C0 test eax,eax
+ //0041C524 75 01 jne 0041C527
+
+ if (IsConst(Opcode.rt)) {
+ MoveConstToX86regPointer(MipsRegLo(Opcode.rt),TempReg1, TempReg2);
+ } else if (IsMapped(Opcode.rt)) {
+ MoveX86regToX86regPointer(MipsRegLo(Opcode.rt),TempReg1, TempReg2);
+ } else {
+ MoveX86regToX86regPointer(Map_TempReg(Section,x86_Any,Opcode.rt,0),TempReg1, TempReg2);
+ }
+
+ }
+}
+
+void Compile_R4300i_SWR (BLOCK_SECTION * Section) {
+ uint32_t TempReg1, TempReg2, Value, Offset, shift;
+
+
+
+ if (IsConst(Opcode.base)) {
+ uint32_t Address;
+
+ Address = MipsRegLo(Opcode.base) + (short)Opcode.offset;
+ Offset = Address & 3;
+
+ Value = Map_TempReg(Section,x86_Any,-1,0);
+ Compile_LW(Value,(Address & ~3));
+ AndConstToX86Reg(Value,SWR_MASK[Offset]);
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.rt,0);
+ ShiftLeftSignImmed(TempReg1,(uint8_t)SWR_SHIFT[Offset]);
+ AddX86RegToX86Reg(Value,TempReg1);
+ Compile_SW_Register(Value, (Address & ~3));
+ return;
+ }
+ shift = Map_TempReg(Section,x86_ECX,-1,0);
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ UnProtectGPR(Section,Opcode.base);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ //MoveVariableDispToX86Reg(TLB_Map,TempReg2,TempReg2,8);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+
+ //For tlb miss
+ //0041C522 85 C0 test eax,eax
+ //0041C524 75 01 jne 0041C527
+
+ Offset = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, Offset);
+ AndConstToX86Reg(Offset,3);
+ AndConstToX86Reg(TempReg1,~3);
+
+ Value = Map_TempReg(Section,x86_Any,-1,0);
+
+ MoveX86regPointerToX86reg(TempReg1, TempReg2,Value);
+
+ AndVariableDispToX86Reg(SWR_MASK,Value,Offset,4);
+ if (!IsConst(Opcode.rt) || MipsRegLo(Opcode.rt) != 0) {
+ MoveVariableDispToX86Reg(SWR_SHIFT,shift,Offset,4);
+ if (IsConst(Opcode.rt)) {
+ MoveConstToX86reg(MipsRegLo(Opcode.rt),Offset);
+ } else if (IsMapped(Opcode.rt)) {
+ MoveX86RegToX86Reg(MipsRegLo(Opcode.rt),Offset);
+ } else {
+ MoveVariableToX86reg(&GPR[Opcode.rt].UW[0],Offset);
+ }
+ ShiftLeftSign(Offset);
+ AddX86RegToX86Reg(Value,Offset);
+ }
+
+
+
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ //MoveVariableDispToX86Reg(TLB_Map,TempReg2,TempReg2,8);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+
+ MoveX86regToX86regPointer(Value,TempReg1, TempReg2);
+
+}
+
+void Compile_R4300i_SDL (BLOCK_SECTION * Section) {
+
+ if (Opcode.base != 0) { UnMap_GPR(Section,Opcode.base,1); }
+ if (Opcode.rt != 0) { UnMap_GPR(Section,Opcode.rt,1); }
+ Pushad();
+ MoveConstToVariable(Opcode.Hex, &Opcode.Hex );
+ Call_Direct(r4300i_SDL);
+ Popad();
+
+}
+
+void Compile_R4300i_SDR (BLOCK_SECTION * Section) {
+
+ if (Opcode.base != 0) { UnMap_GPR(Section,Opcode.base,1); }
+ if (Opcode.rt != 0) { UnMap_GPR(Section,Opcode.rt,1); }
+ Pushad();
+ MoveConstToVariable(Opcode.Hex, &Opcode.Hex );
+ Call_Direct(r4300i_SDR);
+ Popad();
+
+}
+
+void ClearRecomplierCache (uint32_t Address) {
+ if (!TranslateVaddr(&Address)) { DisplayError("Cache: Failed to translate: %X",Address); return; }
+ if (Address < RdramSize) {
+ uint32_t Block = Address >> 12;
+ if (N64_Blocks.NoOfRDRamBlocks[Block] > 0) {
+ N64_Blocks.NoOfRDRamBlocks[Block] = 0;
+ memset(JumpTable + (Block << 10),0,0x1000);
+ *(DelaySlotTable + Block) = NULL;
+ }
+ } else {
+#ifndef EXTERNAL_RELEASE
+ DisplayError("ClearRecomplierCache: %X",Address);
+#endif
+ }
+}
+
+void Compile_R4300i_CACHE (BLOCK_SECTION * Section){
+/*
+ if (SelfModCheck != ModCode_Cache && SelfModCheck != ModCode_ChangeMemory && SelfModCheck != ModCode_CheckMemory2 && SelfModCheck != ModCode_CheckMemoryCache) {
+ return;
+ }
+
+ switch(Opcode.rt) {
+ case 0:
+ case 16:
+ Pushad();
+ if (IsConst(Opcode.base)) {
+ uint32_t Address = MipsRegLo(Opcode.base) + (short)Opcode.offset;
+ MoveConstToX86reg(Address,x86_ECX);
+ } else if (IsMapped(Opcode.base)) {
+ if (MipsRegLo(Opcode.base) == x86_ECX) {
+ AddConstToX86Reg(x86_ECX,(short)Opcode.offset);
+ } else {
+ LeaSourceAndOffset(x86_ECX,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ }
+ } else {
+ MoveVariableToX86reg(&GPR[Opcode.base].UW[0],x86_ECX);
+ AddConstToX86Reg(x86_ECX,(short)Opcode.offset);
+ }
+ Call_Direct(ClearRecomplierCache);
+ Popad();
+ break;
+ case 1:
+ case 3:
+ case 13:
+ case 5:
+ case 8:
+ case 9:
+ case 17:
+ case 21:
+ case 25:
+ break;
+#ifndef EXTERNAL_RELEASE
+ default:
+ DisplayError("cache: %d",Opcode.rt);
+#endif
+ }
+ */
+}
+
+void Compile_R4300i_LL (BLOCK_SECTION * Section) {
+ uint32_t TempReg1, TempReg2;
+
+
+
+ if (Opcode.rt == 0) return;
+
+ if (IsConst(Opcode.base)) {
+ uint32_t Address = MipsRegLo(Opcode.base) + (short)Opcode.offset;
+ Map_GPR_32bit(Section,Opcode.rt,1,-1);
+ Compile_LW(MipsRegLo(Opcode.rt),Address);
+ MoveConstToVariable(1,&LLBit);
+ TranslateVaddr(&Address);
+ MoveConstToVariable(Address,&LLAddr);
+ return;
+ }
+
+ if (IsMapped(Opcode.rt)) { ProtectGPR(Section,Opcode.rt); }
+ if (IsMapped(Opcode.base) && Opcode.offset == 0) {
+ ProtectGPR(Section,Opcode.base);
+ TempReg1 = MipsRegLo(Opcode.base);
+ } else {
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+ }
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ //MoveVariableDispToX86Reg(TLB_Map,TempReg2,TempReg2,8);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+ CompileReadTLBMiss(Section,TempReg1,TempReg2);
+ Map_GPR_32bit(Section,Opcode.rt,1,-1);
+ MoveX86regPointerToX86reg(TempReg1, TempReg2,MipsRegLo(Opcode.rt));
+ MoveConstToVariable(1,&LLBit);
+ MoveX86regToVariable(TempReg1,&LLAddr);
+ AddX86regToVariable(TempReg2,&LLAddr);
+ SubConstFromVariable((uintptr_t)N64MEM,&LLAddr);
+
+}
+
+void Compile_R4300i_SC (BLOCK_SECTION * Section){
+ uint32_t TempReg1, TempReg2;
+ uint8_t * Jump;
+
+
+
+ CompConstToVariable(1,&LLBit);
+ JneLabel32(0);
+ Jump = RecompPos - 4;
+ if (IsConst(Opcode.base)) {
+ uint32_t Address = MipsRegLo(Opcode.base) + (short)Opcode.offset;
+
+ if (IsConst(Opcode.rt)) {
+ Compile_SW_Const(MipsRegLo(Opcode.rt), Address);
+ } else if (IsMapped(Opcode.rt)) {
+ Compile_SW_Register(MipsRegLo(Opcode.rt), Address);
+ } else {
+ Compile_SW_Register(Map_TempReg(Section,x86_Any,Opcode.rt,0), Address);
+ }
+
+ *((uint32_t *)(Jump))=(uint8_t)(RecompPos - Jump - 4);
+ Map_GPR_32bit(Section,Opcode.rt,0,-1);
+ MoveVariableToX86reg(&LLBit,MipsRegLo(Opcode.rt));
+ return;
+ }
+ if (IsMapped(Opcode.rt)) { ProtectGPR(Section,Opcode.rt); }
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ UnProtectGPR(Section,Opcode.base);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ //MoveVariableDispToX86Reg(TLB_Map,TempReg2,TempReg2,8);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+ //For tlb miss
+ //0041C522 85 C0 test eax,eax
+ //0041C524 75 01 jne 0041C527
+
+ if (IsConst(Opcode.rt)) {
+ MoveConstToX86regPointer(MipsRegLo(Opcode.rt),TempReg1, TempReg2);
+ } else if (IsMapped(Opcode.rt)) {
+ MoveX86regToX86regPointer(MipsRegLo(Opcode.rt),TempReg1, TempReg2);
+ } else {
+ MoveX86regToX86regPointer(Map_TempReg(Section,x86_Any,Opcode.rt,0),TempReg1, TempReg2);
+ }
+
+
+ *((uint32_t *)(Jump))=(uint8_t)(RecompPos - Jump - 4);
+ Map_GPR_32bit(Section,Opcode.rt,0,-1);
+ MoveVariableToX86reg(&LLBit,MipsRegLo(Opcode.rt));
+
+}
+
+void Compile_R4300i_LD (BLOCK_SECTION * Section) {
+ uint32_t TempReg1, TempReg2;
+
+
+
+ if (Opcode.rt == 0) return;
+
+ if (IsConst(Opcode.base)) {
+ uint32_t Address = MipsRegLo(Opcode.base) + (short)Opcode.offset;
+ Map_GPR_64bit(Section,Opcode.rt,-1);
+ Compile_LW(MipsRegHi(Opcode.rt),Address);
+ Compile_LW(MipsRegLo(Opcode.rt),Address + 4);
+ return;
+ }
+ if (IsMapped(Opcode.rt)) { ProtectGPR(Section,Opcode.rt); }
+ if (IsMapped(Opcode.base) && Opcode.offset == 0) {
+
+ ProtectGPR(Section,Opcode.base);
+ TempReg1 = MipsRegLo(Opcode.base);
+
+ } else {
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+ }
+
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ //MoveVariableDispToX86Reg(TLB_Map,TempReg2,TempReg2,8);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+ //For tlb miss
+ //0041C522 85 C0 test eax,eax
+ //0041C524 75 01 jne 0041C527
+ Map_GPR_64bit(Section,Opcode.rt,-1);
+ MoveX86regPointerToX86reg(TempReg1, TempReg2,MipsRegHi(Opcode.rt));
+ MoveX86regPointerToX86regDisp8(TempReg1, TempReg2,MipsRegLo(Opcode.rt),4);
+
+
+}
+
+void Compile_R4300i_SD (BLOCK_SECTION * Section){
+ uint32_t TempReg1, TempReg2;
+
+
+
+ if (IsConst(Opcode.base)) {
+ uint32_t Address = MipsRegLo(Opcode.base) + (short)Opcode.offset;
+
+ if (IsConst(Opcode.rt)) {
+ if (Is64Bit(Opcode.rt)) {
+ Compile_SW_Const(MipsRegHi(Opcode.rt), Address);
+ } else {
+ Compile_SW_Const((MipsRegLo_S(Opcode.rt) >> 31), Address);
+ }
+ Compile_SW_Const(MipsRegLo(Opcode.rt), Address + 4);
+ } else if (IsMapped(Opcode.rt)) {
+ if (Is64Bit(Opcode.rt)) {
+ Compile_SW_Register(MipsRegHi(Opcode.rt), Address);
+ } else {
+ Compile_SW_Register(Map_TempReg(Section,x86_Any,Opcode.rt,1), Address);
+ }
+ Compile_SW_Register(MipsRegLo(Opcode.rt), Address + 4);
+ } else {
+ Compile_SW_Register(TempReg1 = Map_TempReg(Section,x86_Any,Opcode.rt,1), Address);
+ Compile_SW_Register(Map_TempReg(Section,TempReg1,Opcode.rt,0), Address + 4);
+ }
+ return;
+ }
+ if (IsMapped(Opcode.rt)) { ProtectGPR(Section,Opcode.rt); }
+ if (IsMapped(Opcode.base)) {
+ ProtectGPR(Section,Opcode.base);
+ if (Opcode.offset != 0) {
+ TempReg1 = Map_TempReg(Section,x86_Any,-1,0);
+ LeaSourceAndOffset(TempReg1,MipsRegLo(Opcode.base),(short)Opcode.offset);
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ }
+ } else {
+ TempReg1 = Map_TempReg(Section,x86_Any,Opcode.base,0);
+ if (Opcode.immediate == 0) {
+ } else if (Opcode.immediate == 1) {
+ IncX86reg(TempReg1);
+ } else if (Opcode.immediate == 0xFFFF) {
+ DecX86reg(TempReg1);
+ } else {
+ AddConstToX86Reg(TempReg1,(short)Opcode.immediate);
+ }
+ }
+
+ TempReg2 = Map_TempReg(Section,x64_Any,-1,0);
+ MoveX86RegToX86Reg(TempReg1, TempReg2);
+ ShiftRightUnsignImmed(TempReg2,12);
+ //MoveVariableDispToX86Reg(TLB_Map,TempReg2,TempReg2,8);
+ LOAD_FROM_TLB(TempReg2, TempReg2);
+ //For tlb miss
+ //0041C522 85 C0 test eax,eax
+ //0041C524 75 01 jne 0041C527
+
+ if (IsConst(Opcode.rt)) {
+ if (Is64Bit(Opcode.rt)) {
+ MoveConstToX86regPointer(MipsRegHi(Opcode.rt),TempReg1, TempReg2);
+ } else {
+ MoveConstToX86regPointer((MipsRegLo_S(Opcode.rt) >> 31),TempReg1, TempReg2);
+ }
+ AddConstToX86Reg(TempReg1,4);
+ MoveConstToX86regPointer(MipsRegLo(Opcode.rt),TempReg1, TempReg2);
+ } else if (IsMapped(Opcode.rt)) {
+ if (Is64Bit(Opcode.rt)) {
+ MoveX86regToX86regPointer(MipsRegHi(Opcode.rt),TempReg1, TempReg2);
+ } else {
+ MoveX86regToX86regPointer(Map_TempReg(Section,x86_Any,Opcode.rt,1),TempReg1, TempReg2);
+ }
+ AddConstToX86Reg(TempReg1,4);
+ MoveX86regToX86regPointer(MipsRegLo(Opcode.rt),TempReg1, TempReg2);
+ } else {
+ int32_t X86Reg = Map_TempReg(Section,x86_Any,Opcode.rt,1);
+ MoveX86regToX86regPointer(X86Reg,TempReg1, TempReg2);
+ AddConstToX86Reg(TempReg1,4);
+ MoveX86regToX86regPointer(Map_TempReg(Section,X86Reg,Opcode.rt,0),TempReg1, TempReg2);
+ }
+
+}
+
+/********************** R4300i OpCodes: Special **********************/
+void Compile_R4300i_SPECIAL_SLL (BLOCK_SECTION * Section) {
+
+
+ if (Opcode.rd == 0) { return; }
+ if (IsConst(Opcode.rt)) {
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+ MipsRegLo(Opcode.rd) = MipsRegLo(Opcode.rt) << Opcode.sa;
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ return;
+ }
+ if (Opcode.rd != Opcode.rt && IsMapped(Opcode.rt)) {
+ switch (Opcode.sa) {
+ case 0:
+ Map_GPR_32bit(Section,Opcode.rd,1,Opcode.rt);
+ break;
+ case 1:
+ ProtectGPR(Section,Opcode.rt);
+ Map_GPR_32bit(Section,Opcode.rd,1,-1);
+ LeaRegReg(MipsRegLo(Opcode.rd),MipsRegLo(Opcode.rt), 2);
+ break;
+ case 2:
+ ProtectGPR(Section,Opcode.rt);
+ Map_GPR_32bit(Section,Opcode.rd,1,-1);
+ LeaRegReg(MipsRegLo(Opcode.rd),MipsRegLo(Opcode.rt), 4);
+ break;
+ case 3:
+ ProtectGPR(Section,Opcode.rt);
+ Map_GPR_32bit(Section,Opcode.rd,1,-1);
+ LeaRegReg(MipsRegLo(Opcode.rd),MipsRegLo(Opcode.rt), 8);
+ break;
+ default:
+ Map_GPR_32bit(Section,Opcode.rd,1,Opcode.rt);
+ ShiftLeftSignImmed(MipsRegLo(Opcode.rd),(uint8_t)Opcode.sa);
+ }
+ } else {
+ Map_GPR_32bit(Section,Opcode.rd,1,Opcode.rt);
+ ShiftLeftSignImmed(MipsRegLo(Opcode.rd),(uint8_t)Opcode.sa);
+ }
+}
+
+void Compile_R4300i_SPECIAL_SRL (BLOCK_SECTION * Section) {
+
+ if (Opcode.rd == 0) { return; }
+
+ if (IsConst(Opcode.rt)) {
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+ MipsRegLo(Opcode.rd) = MipsRegLo(Opcode.rt) >> Opcode.sa;
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ return;
+ }
+ Map_GPR_32bit(Section,Opcode.rd,1,Opcode.rt);
+ ShiftRightUnsignImmed(MipsRegLo(Opcode.rd),(uint8_t)Opcode.sa);
+}
+
+void Compile_R4300i_SPECIAL_SRA (BLOCK_SECTION * Section) {
+
+ if (Opcode.rd == 0) { return; }
+
+ if (IsConst(Opcode.rt)) {
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+ MipsRegLo(Opcode.rd) = MipsRegLo_S(Opcode.rt) >> Opcode.sa;
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ return;
+ }
+ Map_GPR_32bit(Section,Opcode.rd,1,Opcode.rt);
+ ShiftRightSignImmed(MipsRegLo(Opcode.rd),(uint8_t)Opcode.sa);
+}
+
+void Compile_R4300i_SPECIAL_SLLV (BLOCK_SECTION * Section) {
+
+ if (Opcode.rd == 0) { return; }
+
+ if (IsConst(Opcode.rs)) {
+ uint32_t Shift = (MipsRegLo(Opcode.rs) & 0x1F);
+ if (IsConst(Opcode.rt)) {
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+ MipsRegLo(Opcode.rd) = MipsRegLo(Opcode.rt) << Shift;
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else {
+ Map_GPR_32bit(Section,Opcode.rd,1,Opcode.rt);
+ ShiftLeftSignImmed(MipsRegLo(Opcode.rd),(uint8_t)Shift);
+ }
+ return;
+ }
+ Map_TempReg(Section,x86_ECX,Opcode.rs,0);
+ AndConstToX86Reg(x86_ECX,0x1F);
+ Map_GPR_32bit(Section,Opcode.rd,1,Opcode.rt);
+ ShiftLeftSign(MipsRegLo(Opcode.rd));
+}
+
+void Compile_R4300i_SPECIAL_SRLV (BLOCK_SECTION * Section) {
+
+ if (Opcode.rd == 0) { return; }
+
+ if (IsKnown(Opcode.rs) && IsConst(Opcode.rs)) {
+ uint32_t Shift = (MipsRegLo(Opcode.rs) & 0x1F);
+ if (IsConst(Opcode.rt)) {
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+ MipsRegLo(Opcode.rd) = MipsRegLo(Opcode.rt) >> Shift;
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ return;
+ }
+ Map_GPR_32bit(Section,Opcode.rd,1,Opcode.rt);
+ ShiftRightUnsignImmed(MipsRegLo(Opcode.rd),(uint8_t)Shift);
+ return;
+ }
+ Map_TempReg(Section,x86_ECX,Opcode.rs,0);
+ AndConstToX86Reg(x86_ECX,0x1F);
+ Map_GPR_32bit(Section,Opcode.rd,1,Opcode.rt);
+ ShiftRightUnsign(MipsRegLo(Opcode.rd));
+}
+
+void Compile_R4300i_SPECIAL_SRAV (BLOCK_SECTION * Section) {
+
+ if (Opcode.rd == 0) { return; }
+
+ if (IsKnown(Opcode.rs) && IsConst(Opcode.rs)) {
+ uint32_t Shift = (MipsRegLo(Opcode.rs) & 0x1F);
+ if (IsConst(Opcode.rt)) {
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+ MipsRegLo(Opcode.rd) = MipsRegLo_S(Opcode.rt) >> Shift;
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ return;
+ }
+ Map_GPR_32bit(Section,Opcode.rd,1,Opcode.rt);
+ ShiftRightSignImmed(MipsRegLo(Opcode.rd),(uint8_t)Shift);
+ return;
+ }
+ Map_TempReg(Section,x86_ECX,Opcode.rs,0);
+ AndConstToX86Reg(x86_ECX,0x1F);
+ Map_GPR_32bit(Section,Opcode.rd,1,Opcode.rt);
+ ShiftRightSign(MipsRegLo(Opcode.rd));
+}
+
+void Compile_R4300i_SPECIAL_JR (BLOCK_SECTION * Section) {
+
+ if ( NextInstruction == NORMAL ) {
+
+ if (IsConst(Opcode.rs)) {
+ Section->Jump.TargetPC = MipsRegLo(Opcode.rs);
+ Section->Jump.FallThrough = 1;
+ Section->Jump.LinkLocation = NULL;
+ Section->Jump.LinkLocation2 = NULL;
+ Section->Cont.FallThrough = 0;
+ Section->Cont.LinkLocation = NULL;
+ Section->Cont.LinkLocation2 = NULL;
+ if ((Section->CompilePC & 0xFFC) == 0xFFC) {
+ GenerateSectionLinkage(Section);
+ NextInstruction = END_BLOCK;
+ return;
+ }
+ }
+ if ((Section->CompilePC & 0xFFC) == 0xFFC) {
+ if (IsMapped(Opcode.rs)) {
+ MoveX86regToVariable(MipsRegLo(Opcode.rs),&JumpToLocation);
+ } else {
+ MoveX86regToVariable(Map_TempReg(Section,x86_Any,Opcode.rs,0),&JumpToLocation);
+ }
+ MoveConstToVariable(Section->CompilePC + 4,&PROGRAM_COUNTER);
+ if (BlockCycleCount != 0) {
+ AddConstToVariable(BlockCycleCount,&CP0[9]);
+ SubConstFromVariable(BlockCycleCount,&Timers->Timer);
+ }
+ if (BlockRandomModifier != 0) { SubConstFromVariable(BlockRandomModifier,&CP0[1]); }
+ WriteBackRegisters(Section);
+ MoveConstToVariable(DELAY_SLOT,&NextInstruction);
+ Ret();
+ NextInstruction = END_BLOCK;
+ return;
+ }
+ if (DelaySlotEffectsCompare(Section->CompilePC,Opcode.rs,0)) {
+ if (IsConst(Opcode.rs)) {
+ MoveConstToVariable(MipsRegLo(Opcode.rs),&PROGRAM_COUNTER);
+ } else if (IsMapped(Opcode.rs)) {
+ MoveX86regToVariable(MipsRegLo(Opcode.rs),&PROGRAM_COUNTER);
+ } else {
+ MoveX86regToVariable(Map_TempReg(Section,x86_Any,Opcode.rs,0),&PROGRAM_COUNTER);
+ }
+ }
+ NextInstruction = DO_DELAY_SLOT;
+ } else if (NextInstruction == DELAY_SLOT_DONE ) {
+ if (DelaySlotEffectsCompare(Section->CompilePC,Opcode.rs,0)) {
+
+ CompileExit((uint32_t)-1,&Section->RegWorking,Normal,1,NULL);
+ } else {
+ if (IsConst(Opcode.rs)) {
+ memcpy(&Section->Jump.RegSet,&Section->RegWorking,sizeof(REG_INFO));
+ GenerateSectionLinkage(Section);
+ } else {
+ if (IsMapped(Opcode.rs)) {
+
+ MoveX86regToVariable(MipsRegLo(Opcode.rs),&PROGRAM_COUNTER);
+ } else {
+ MoveX86regToVariable(Map_TempReg(Section,x86_Any,Opcode.rs,0),&PROGRAM_COUNTER);
+ }
+ CompileExit((uint32_t)-1,&Section->RegWorking,Normal,1,NULL);
+ }
+ }
+ NextInstruction = END_BLOCK;
+ } else {
+#ifndef EXTERNAL_RELEASE
+ DisplayError("WTF\n\nBranch\nNextInstruction = %X", NextInstruction);
+#endif
+ }
+}
+
+void Compile_R4300i_SPECIAL_JALR (BLOCK_SECTION * Section) {
+ if ( NextInstruction == NORMAL ) {
+
+ if (DelaySlotEffectsCompare(Section->CompilePC,Opcode.rs,0)) {
+ Compile_R4300i_UnknownOpcode(Section);
+ }
+ UnMap_GPR(Section, Opcode.rd, 0);
+ MipsRegLo(Opcode.rd) = Section->CompilePC + 8;
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ if ((Section->CompilePC & 0xFFC) == 0xFFC) {
+ if (IsMapped(Opcode.rs)) {
+ MoveX86regToVariable(MipsRegLo(Opcode.rs),&JumpToLocation);
+ } else {
+ MoveX86regToVariable(Map_TempReg(Section,x86_Any,Opcode.rs,0),&JumpToLocation);
+ }
+ MoveConstToVariable(Section->CompilePC + 4,&PROGRAM_COUNTER);
+ if (BlockCycleCount != 0) {
+ AddConstToVariable(BlockCycleCount,&CP0[9]);
+ SubConstFromVariable(BlockCycleCount,&Timers->Timer);
+ }
+ if (BlockRandomModifier != 0) { SubConstFromVariable(BlockRandomModifier,&CP0[1]); }
+ WriteBackRegisters(Section);
+ MoveConstToVariable(DELAY_SLOT,&NextInstruction);
+ Ret();
+ NextInstruction = END_BLOCK;
+ return;
+ }
+ NextInstruction = DO_DELAY_SLOT;
+ } else if (NextInstruction == DELAY_SLOT_DONE ) {
+ if (IsConst(Opcode.rs)) {
+ memcpy(&Section->Jump.RegSet,&Section->RegWorking,sizeof(REG_INFO));
+ Section->Jump.TargetPC = MipsRegLo(Opcode.rs);
+ Section->Jump.FallThrough = 1;
+ Section->Jump.LinkLocation = NULL;
+ Section->Jump.LinkLocation2 = NULL;
+ Section->Cont.FallThrough = 0;
+ Section->Cont.LinkLocation = NULL;
+ Section->Cont.LinkLocation2 = NULL;
+
+ GenerateSectionLinkage(Section);
+ } else {
+ if (IsMapped(Opcode.rs)) {
+ MoveX86regToVariable(MipsRegLo(Opcode.rs),&PROGRAM_COUNTER);
+ } else {
+ MoveX86regToVariable(Map_TempReg(Section,x86_Any,Opcode.rs,0),&PROGRAM_COUNTER);
+ }
+ CompileExit((uint32_t)-1,&Section->RegWorking,Normal,1,NULL);
+ }
+ NextInstruction = END_BLOCK;
+ } else {
+ }
+}
+
+void Compile_R4300i_SPECIAL_SYSCALL (BLOCK_SECTION * Section) {
+ CompileExit(Section->CompilePC,&Section->RegWorking,DoSysCall,1,NULL);
+}
+
+void Compile_R4300i_SPECIAL_BREAK (BLOCK_SECTION * Section) {
+ //CompileExit(Section->CompilePC,Section->RegWorking,DoBreak,1,NULL);
+ MoveConstToVariable(1,WaitMode);
+}
+
+
+void Compile_R4300i_SPECIAL_MFLO (BLOCK_SECTION * Section) {
+
+ if (Opcode.rd == 0) { return; }
+
+ Map_GPR_64bit(Section,Opcode.rd,-1);
+ MoveVariableToX86reg(&LO.UW[0],MipsRegLo(Opcode.rd));
+ MoveVariableToX86reg(&LO.UW[1],MipsRegHi(Opcode.rd));
+}
+
+void Compile_R4300i_SPECIAL_MTLO (BLOCK_SECTION * Section) {
+
+
+ if (IsKnown(Opcode.rs) && IsConst(Opcode.rs)) {
+ if (Is64Bit(Opcode.rs)) {
+ MoveConstToVariable(MipsRegHi(Opcode.rs),&LO.UW[1]);
+ } else if (IsSigned(Opcode.rs) && ((MipsRegLo(Opcode.rs) & 0x80000000) != 0)) {
+ MoveConstToVariable(0xFFFFFFFF,&LO.UW[1]);
+ } else {
+ MoveConstToVariable(0,&LO.UW[1]);
+ }
+ MoveConstToVariable(MipsRegLo(Opcode.rs), &LO.UW[0]);
+ } else if (IsKnown(Opcode.rs) && IsMapped(Opcode.rs)) {
+ if (Is64Bit(Opcode.rs)) {
+ MoveX86regToVariable(MipsRegHi(Opcode.rs),&LO.UW[1]);
+ } else if (IsSigned(Opcode.rs)) {
+ MoveX86regToVariable(Map_TempReg(Section,x86_Any,Opcode.rs,1),&LO.UW[1]);
+ } else {
+ MoveConstToVariable(0,&LO.UW[1]);
+ }
+ MoveX86regToVariable(MipsRegLo(Opcode.rs), &LO.UW[0]);
+ } else {
+ int32_t x86reg = Map_TempReg(Section,x86_Any,Opcode.rs,1);
+ MoveX86regToVariable(x86reg,&LO.UW[1]);
+ MoveX86regToVariable(Map_TempReg(Section,x86reg,Opcode.rs,0), &LO.UW[0]);
+ }
+}
+
+void Compile_R4300i_SPECIAL_MFHI (BLOCK_SECTION * Section) {
+
+ if (Opcode.rd == 0) { return; }
+
+ Map_GPR_64bit(Section,Opcode.rd,-1);
+ MoveVariableToX86reg(&HI.UW[0],MipsRegLo(Opcode.rd));
+ MoveVariableToX86reg(&HI.UW[1],MipsRegHi(Opcode.rd));
+}
+
+void Compile_R4300i_SPECIAL_MTHI (BLOCK_SECTION * Section) {
+
+ if (IsKnown(Opcode.rs) && IsConst(Opcode.rs)) {
+ if (Is64Bit(Opcode.rs)) {
+ MoveConstToVariable(MipsRegHi(Opcode.rs),&HI.UW[1]);
+ } else if (IsSigned(Opcode.rs) && ((MipsRegLo(Opcode.rs) & 0x80000000) != 0)) {
+ MoveConstToVariable(0xFFFFFFFF,&HI.UW[1]);
+ } else {
+ MoveConstToVariable(0,&HI.UW[1]);
+ }
+ MoveConstToVariable(MipsRegLo(Opcode.rs), &HI.UW[0]);
+ } else if (IsKnown(Opcode.rs) && IsMapped(Opcode.rs)) {
+ if (Is64Bit(Opcode.rs)) {
+ MoveX86regToVariable(MipsRegHi(Opcode.rs),&HI.UW[1]);
+ } else if (IsSigned(Opcode.rs)) {
+ MoveX86regToVariable(Map_TempReg(Section,x86_Any,Opcode.rs,1),&HI.UW[1]);
+ } else {
+ MoveConstToVariable(0,&HI.UW[1]);
+ }
+ MoveX86regToVariable(MipsRegLo(Opcode.rs), &HI.UW[0]);
+ } else {
+ int32_t x86reg = Map_TempReg(Section,x86_Any,Opcode.rs,1);
+ MoveX86regToVariable(x86reg,&HI.UW[1]);
+ MoveX86regToVariable(Map_TempReg(Section,x86reg,Opcode.rs,0), &HI.UW[0]);
+ }
+}
+
+void Compile_R4300i_SPECIAL_DSLLV (BLOCK_SECTION * Section) {
+ uint8_t * Jump[2];
+
+
+ if (Opcode.rd == 0) { return; }
+
+ if (IsConst(Opcode.rs)) {
+ uint32_t Shift = (MipsRegLo(Opcode.rs) & 0x3F);
+ Compile_R4300i_UnknownOpcode(Section);
+ return;
+ }
+ Map_TempReg(Section,x86_ECX,Opcode.rs,0);
+ AndConstToX86Reg(x86_ECX,0x3F);
+ Map_GPR_64bit(Section,Opcode.rd,Opcode.rt);
+ CompConstToX86reg(x86_ECX,0x20);
+ JaeLabel8( 0);
+ Jump[0] = RecompPos - 1;
+ ShiftLeftDouble(MipsRegHi(Opcode.rd),MipsRegLo(Opcode.rd));
+ ShiftLeftSign(MipsRegLo(Opcode.rd));
+ JmpLabel8( 0);
+ Jump[1] = RecompPos - 1;
+
+ //MORE32:
+
+
+ *((uint8_t *)(Jump[0]))=(uint8_t)(RecompPos - Jump[0] - 1);
+ MoveX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegHi(Opcode.rd));
+ XorX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(Opcode.rd));
+ AndConstToX86Reg(x86_ECX,0x1F);
+ ShiftLeftSign(MipsRegHi(Opcode.rd));
+
+ //continue:
+
+
+ *((uint8_t *)(Jump[1]))=(uint8_t)(RecompPos - Jump[1] - 1);
+}
+
+void Compile_R4300i_SPECIAL_DSRLV (BLOCK_SECTION * Section) {
+ uint8_t * Jump[2];
+
+
+ if (Opcode.rd == 0) { return; }
+
+ if (IsConst(Opcode.rs)) {
+ uint32_t Shift = (MipsRegLo(Opcode.rs) & 0x3F);
+ if (IsConst(Opcode.rt)) {
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+ MipsReg(Opcode.rd) = Is64Bit(Opcode.rt)?MipsReg(Opcode.rt):(int64_t)MipsRegLo_S(Opcode.rt);
+ MipsReg(Opcode.rd) = MipsReg(Opcode.rd) >> Shift;
+ if ((MipsRegHi(Opcode.rd) == 0) && (MipsRegLo(Opcode.rd) & 0x80000000) == 0) {
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else if ((MipsRegHi(Opcode.rd) == 0xFFFFFFFF) && (MipsRegLo(Opcode.rd) & 0x80000000) != 0) {
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else {
+ MipsRegState(Opcode.rd) = STATE_CONST_64;
+ }
+ return;
+ }
+ //if (Shift < 0x20) {
+ //} else {
+ //}
+ //Compile_R4300i_UnknownOpcode(Section);
+ //return;
+ }
+ Map_TempReg(Section,x86_ECX,Opcode.rs,0);
+ AndConstToX86Reg(x86_ECX,0x3F);
+ Map_GPR_64bit(Section,Opcode.rd,Opcode.rt);
+ CompConstToX86reg(x86_ECX,0x20);
+ JaeLabel8( 0);
+ Jump[0] = RecompPos - 1;
+ ShiftRightDouble(MipsRegLo(Opcode.rd),MipsRegHi(Opcode.rd));
+ ShiftRightUnsign(MipsRegHi(Opcode.rd));
+ JmpLabel8( 0);
+ Jump[1] = RecompPos - 1;
+
+ //MORE32:
+
+
+ *((uint8_t *)(Jump[0]))=(uint8_t)(RecompPos - Jump[0] - 1);
+ MoveX86RegToX86Reg(MipsRegHi(Opcode.rd),MipsRegLo(Opcode.rd));
+ XorX86RegToX86Reg(MipsRegHi(Opcode.rd),MipsRegHi(Opcode.rd));
+ AndConstToX86Reg(x86_ECX,0x1F);
+ ShiftRightUnsign(MipsRegLo(Opcode.rd));
+
+ //continue:
+
+
+ *((uint8_t *)(Jump[1]))=(uint8_t)(RecompPos - Jump[1] - 1);
+}
+
+void Compile_R4300i_SPECIAL_DSRAV (BLOCK_SECTION * Section) {
+ uint8_t * Jump[2];
+
+
+ if (Opcode.rd == 0) { return; }
+
+ if (IsConst(Opcode.rs)) {
+ uint32_t Shift = (MipsRegLo(Opcode.rs) & 0x3F);
+ Compile_R4300i_UnknownOpcode(Section);
+ return;
+ }
+ Map_TempReg(Section,x86_ECX,Opcode.rs,0);
+ AndConstToX86Reg(x86_ECX,0x3F);
+ Map_GPR_64bit(Section,Opcode.rd,Opcode.rt);
+ CompConstToX86reg(x86_ECX,0x20);
+ JaeLabel8( 0);
+ Jump[0] = RecompPos - 1;
+ ShiftRightDouble(MipsRegLo(Opcode.rd),MipsRegHi(Opcode.rd));
+ ShiftRightSign(MipsRegHi(Opcode.rd));
+ JmpLabel8( 0);
+ Jump[1] = RecompPos - 1;
+
+ //MORE32:
+
+
+ *((uint8_t *)(Jump[0]))=(uint8_t)(RecompPos - Jump[0] - 1);
+ MoveX86RegToX86Reg(MipsRegHi(Opcode.rd),MipsRegLo(Opcode.rd));
+ ShiftRightSignImmed(MipsRegHi(Opcode.rd),0x1F);
+ AndConstToX86Reg(x86_ECX,0x1F);
+ ShiftRightSign(MipsRegLo(Opcode.rd));
+
+ //continue:
+
+
+ *((uint8_t *)(Jump[1]))=(uint8_t)(RecompPos - Jump[1] - 1);
+}
+
+void Compile_R4300i_SPECIAL_MULT ( BLOCK_SECTION * Section) {
+
+
+ x86Protected(x86_EDX) = 1;
+ Map_TempReg(Section,x86_EAX,Opcode.rs,0);
+ x86Protected(x86_EDX) = 0;
+ Map_TempReg(Section,x86_EDX,Opcode.rt,0);
+
+ imulX86reg(x86_EDX);
+
+ MoveX86regToVariable(x86_EAX,&LO.UW[0]);
+ MoveX86regToVariable(x86_EDX,&HI.UW[0]);
+ ShiftRightSignImmed(x86_EAX,31); /* paired */
+ ShiftRightSignImmed(x86_EDX,31);
+ MoveX86regToVariable(x86_EAX,&LO.UW[1]);
+ MoveX86regToVariable(x86_EDX,&HI.UW[1]);
+}
+
+void Compile_R4300i_SPECIAL_MULTU (BLOCK_SECTION * Section) {
+
+
+ x86Protected(x86_EDX) = 1;
+ Map_TempReg(Section,x86_EAX,Opcode.rs,0);
+ x86Protected(x86_EDX) = 0;
+ Map_TempReg(Section,x86_EDX,Opcode.rt,0);
+
+ MulX86reg(x86_EDX);
+
+ MoveX86regToVariable(x86_EAX,&LO.UW[0]);
+ MoveX86regToVariable(x86_EDX,&HI.UW[0]);
+ ShiftRightSignImmed(x86_EAX,31); /* paired */
+ ShiftRightSignImmed(x86_EDX,31);
+ MoveX86regToVariable(x86_EAX,&LO.UW[1]);
+ MoveX86regToVariable(x86_EDX,&HI.UW[1]);
+}
+
+void Compile_R4300i_SPECIAL_DIV (BLOCK_SECTION * Section) {
+ uint8_t *Jump[2];
+
+
+
+ if (IsConst(Opcode.rt)) {
+ if (MipsRegLo(Opcode.rt) == 0) {
+ MoveConstToVariable(0, &LO.UW[0]);
+ MoveConstToVariable(0, &LO.UW[1]);
+ MoveConstToVariable(0, &HI.UW[0]);
+ MoveConstToVariable(0, &HI.UW[1]);
+ return;
+ }
+ Jump[1] = NULL;
+ } else {
+ if (IsMapped(Opcode.rt)) {
+ CompConstToX86reg(MipsRegLo(Opcode.rt),0);
+ } else {
+ CompConstToVariable(0, &GPR[Opcode.rt].W[0]);
+ }
+ JneLabel8( 0);
+ Jump[0] = RecompPos - 1;
+
+ MoveConstToVariable(0, &LO.UW[0]);
+ MoveConstToVariable(0, &LO.UW[1]);
+ MoveConstToVariable(0, &HI.UW[0]);
+ MoveConstToVariable(0, &HI.UW[1]);
+
+ JmpLabel8( 0);
+ Jump[1] = RecompPos - 1;
+
+
+
+ *((uint8_t *)(Jump[0]))=(uint8_t)(RecompPos - Jump[0] - 1);
+ }
+ /* lo = (SD)rs / (SD)rt;
+ hi = (SD)rs % (SD)rt; */
+
+ x86Protected(x86_EDX) = 1;
+ Map_TempReg(Section,x86_EAX,Opcode.rs,0);
+
+ /* edx is the signed portion to eax */
+ x86Protected(x86_EDX) = 0;
+ Map_TempReg(Section,x86_EDX, -1, 0);
+
+ MoveX86RegToX86Reg(x86_EAX, x86_EDX);
+ ShiftRightSignImmed(x86_EDX,31);
+
+ if (IsMapped(Opcode.rt)) {
+ idivX86reg(MipsRegLo(Opcode.rt));
+ } else {
+ idivX86reg(Map_TempReg(Section,x86_Any,Opcode.rt,0));
+ }
+
+
+ MoveX86regToVariable(x86_EAX,&LO.UW[0]);
+ MoveX86regToVariable(x86_EDX,&HI.UW[0]);
+ ShiftRightSignImmed(x86_EAX,31); /* paired */
+ ShiftRightSignImmed(x86_EDX,31);
+ MoveX86regToVariable(x86_EAX,&LO.UW[1]);
+ MoveX86regToVariable(x86_EDX,&HI.UW[1]);
+
+ if( Jump[1] != NULL ) {
+
+
+ *((uint8_t *)(Jump[1]))=(uint8_t)(RecompPos - Jump[1] - 1);
+ }
+}
+
+void Compile_R4300i_SPECIAL_DIVU ( BLOCK_SECTION * Section) {
+ uint8_t *Jump[2];
+ int32_t x86reg;
+
+
+
+ if (IsConst(Opcode.rt)) {
+ if (MipsRegLo(Opcode.rt) == 0) {
+ MoveConstToVariable(0, &LO.UW[0]);
+ MoveConstToVariable(0, &LO.UW[1]);
+ MoveConstToVariable(0, &HI.UW[0]);
+ MoveConstToVariable(0, &HI.UW[1]);
+ return;
+ }
+ Jump[1] = NULL;
+ } else {
+ if (IsMapped(Opcode.rt)) {
+ CompConstToX86reg(MipsRegLo(Opcode.rt),0);
+ } else {
+ CompConstToVariable(0, &GPR[Opcode.rt].W[0]);
+ }
+ JneLabel8( 0);
+ Jump[0] = RecompPos - 1;
+
+ MoveConstToVariable(0, &LO.UW[0]);
+ MoveConstToVariable(0, &LO.UW[1]);
+ MoveConstToVariable(0, &HI.UW[0]);
+ MoveConstToVariable(0, &HI.UW[1]);
+
+ JmpLabel8( 0);
+ Jump[1] = RecompPos - 1;
+
+
+
+ *((uint8_t *)(Jump[0]))=(uint8_t)(RecompPos - Jump[0] - 1);
+ }
+
+
+ /* lo = (UD)rs / (UD)rt;
+ hi = (UD)rs % (UD)rt; */
+
+ x86Protected(x86_EAX) = 1;
+ Map_TempReg(Section,x86_EDX, 0, 0);
+ x86Protected(x86_EAX) = 0;
+
+ Map_TempReg(Section,x86_EAX,Opcode.rs,0);
+ x86reg = Map_TempReg(Section,x86_Any,Opcode.rt,0);
+
+ DivX86reg(x86reg);
+
+ MoveX86regToVariable(x86_EAX,&LO.UW[0]);
+ MoveX86regToVariable(x86_EDX,&HI.UW[0]);
+
+ /* wouldnt these be zero (???) */
+
+ ShiftRightSignImmed(x86_EAX,31); /* paired */
+ ShiftRightSignImmed(x86_EDX,31);
+ MoveX86regToVariable(x86_EAX,&LO.UW[1]);
+ MoveX86regToVariable(x86_EDX,&HI.UW[1]);
+
+ if( Jump[1] != NULL ) {
+
+
+ *((uint8_t *)(Jump[1]))=(uint8_t)(RecompPos - Jump[1] - 1);
+ }
+}
+
+void Compile_R4300i_SPECIAL_DMULT (BLOCK_SECTION * Section) {
+
+
+ if (Opcode.rs != 0) { UnMap_GPR(Section,Opcode.rs,1); }
+ if (Opcode.rs != 0) { UnMap_GPR(Section,Opcode.rt,1); }
+ Pushad();
+ MoveConstToVariable(Opcode.Hex, &Opcode.Hex );
+ Call_Direct(r4300i_SPECIAL_DMULT);
+ Popad();
+}
+
+void Compile_R4300i_SPECIAL_DMULTU (BLOCK_SECTION * Section) {
+
+
+ /* LO.UDW = (uint64)GPR[Opcode.rs].UW[0] * (uint64)GPR[Opcode.rt].UW[0]; */
+ x86Protected(x86_EDX) = 1;
+ Map_TempReg(Section,x86_EAX,Opcode.rs,0);
+ x86Protected(x86_EDX) = 0;
+ Map_TempReg(Section,x86_EDX,Opcode.rt,0);
+
+ MulX86reg(x86_EDX);
+ MoveX86regToVariable(x86_EAX, &LO.UW[0]);
+ MoveX86regToVariable(x86_EDX, &LO.UW[1]);
+
+ /* HI.UDW = (uint64)GPR[Opcode.rs].UW[1] * (uint64)GPR[Opcode.rt].UW[1]; */
+ Map_TempReg(Section,x86_EAX,Opcode.rs,1);
+ Map_TempReg(Section,x86_EDX,Opcode.rt,1);
+
+ MulX86reg(x86_EDX);
+ MoveX86regToVariable(x86_EAX, &HI.UW[0]);
+ MoveX86regToVariable(x86_EDX, &HI.UW[1]);
+
+ /* Tmp[0].UDW = (uint64)GPR[Opcode.rs].UW[1] * (uint64)GPR[Opcode.rt].UW[0]; */
+ Map_TempReg(Section,x86_EAX,Opcode.rs,1);
+ Map_TempReg(Section,x86_EDX,Opcode.rt,0);
+
+ Map_TempReg(Section,x86_EBX,-1,0);
+ Map_TempReg(Section,x86_ECX,-1,0);
+
+ MulX86reg(x86_EDX);
+ MoveX86RegToX86Reg(x86_EAX, x86_EBX); /* EDX:EAX -> ECX:EBX */
+ MoveX86RegToX86Reg(x86_EDX, x86_ECX);
+
+ /* Tmp[1].UDW = (uint64)GPR[Opcode.rs].UW[0] * (uint64)GPR[Opcode.rt].UW[1]; */
+ Map_TempReg(Section,x86_EAX,Opcode.rs,0);
+ Map_TempReg(Section,x86_EDX,Opcode.rt,1);
+
+ MulX86reg(x86_EDX);
+ Map_TempReg(Section,x86_ESI,-1,0);
+ Map_TempReg(Section,x86_EDI,-1,0);
+ MoveX86RegToX86Reg(x86_EAX, x86_ESI); /* EDX:EAX -> EDI:ESI */
+ MoveX86RegToX86Reg(x86_EDX, x86_EDI);
+
+ /* Tmp[2].UDW = (uint64)LO.UW[1] + (uint64)Tmp[0].UW[0] + (uint64)Tmp[1].UW[0]; */
+ XorX86RegToX86Reg(x86_EDX, x86_EDX);
+ MoveVariableToX86reg(&LO.UW[1], x86_EAX);
+ AddX86RegToX86Reg(x86_EAX, x86_EBX);
+ AddConstToX86Reg(x86_EDX, 0);
+ AddX86RegToX86Reg(x86_EAX, x86_ESI);
+ AddConstToX86Reg(x86_EDX, 0); /* EDX:EAX */
+
+ /* LO.UDW += ((uint64)Tmp[0].UW[0] + (uint64)Tmp[1].UW[0]) << 32; */
+ /* [low+4] += ebx + esi */
+
+ AddX86regToVariable(x86_EBX, &LO.UW[1]);
+ AddX86regToVariable(x86_ESI, &LO.UW[1]);
+
+ /* HI.UDW += (uint64)Tmp[0].UW[1] + (uint64)Tmp[1].UW[1] + Tmp[2].UW[1]; */
+ /* [hi] += ecx + edi + edx */
+
+ /*AddX86regToVariable(x86_ECX, &HI.UW[0]);
+ AdcConstToVariable(&HI.UW[1], 0);
+
+ AddX86regToVariable(x86_EDI, &HI.UW[0]);
+ AdcConstToVariable(&HI.UW[1], 0);
+
+ AddX86regToVariable(x86_EDX, &HI.UW[0]);
+ AdcConstToVariable(&HI.UW[1], 0);*/
+}
+
+void Compile_R4300i_SPECIAL_DDIV (BLOCK_SECTION * Section) {
+
+
+ UnMap_GPR(Section,Opcode.rs,1);
+ UnMap_GPR(Section,Opcode.rt,1);
+ Pushad();
+ MoveConstToVariable(Opcode.Hex, &Opcode.Hex );
+ Call_Direct(r4300i_SPECIAL_DDIV);
+ Popad();
+}
+
+void Compile_R4300i_SPECIAL_DDIVU (BLOCK_SECTION * Section) {
+
+
+ UnMap_GPR(Section,Opcode.rs,1);
+ UnMap_GPR(Section,Opcode.rt,1);
+ Pushad();
+ MoveConstToVariable(Opcode.Hex, &Opcode.Hex );
+ Call_Direct(r4300i_SPECIAL_DDIVU);
+ Popad();
+}
+
+void Compile_R4300i_SPECIAL_ADD (BLOCK_SECTION * Section) {
+ int32_t source1 = Opcode.rd == Opcode.rt?Opcode.rt:Opcode.rs;
+ int32_t source2 = Opcode.rd == Opcode.rt?Opcode.rs:Opcode.rt;
+
+
+ if (Opcode.rd == 0) { return; }
+
+ if (IsConst(source1) && IsConst(source2)) {
+ uint32_t temp = MipsRegLo(source1) + MipsRegLo(source2);
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+ MipsRegLo(Opcode.rd) = temp;
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ return;
+ }
+
+ Map_GPR_32bit(Section,Opcode.rd,1, source1);
+ if (IsConst(source2)) {
+ if (MipsRegLo(source2) != 0) {
+ AddConstToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(source2));
+ }
+ } else if (IsKnown(source2) && IsMapped(source2)) {
+ AddX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(source2));
+ } else {
+ AddVariableToX86reg(MipsRegLo(Opcode.rd),&GPR[source2].W[0]);
+ }
+}
+
+void Compile_R4300i_SPECIAL_ADDU (BLOCK_SECTION * Section) {
+ int32_t source1 = Opcode.rd == Opcode.rt?Opcode.rt:Opcode.rs;
+ int32_t source2 = Opcode.rd == Opcode.rt?Opcode.rs:Opcode.rt;
+
+
+ if (Opcode.rd == 0) { return; }
+
+ if (IsConst(source1) && IsConst(source2)) {
+ uint32_t temp = MipsRegLo(source1) + MipsRegLo(source2);
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+ MipsRegLo(Opcode.rd) = temp;
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ return;
+ }
+
+ Map_GPR_32bit(Section,Opcode.rd,1, source1);
+ if (IsConst(source2)) {
+ if (MipsRegLo(source2) != 0) {
+ AddConstToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(source2));
+ }
+ } else if (IsKnown(source2) && IsMapped(source2)) {
+ AddX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(source2));
+ } else {
+ AddVariableToX86reg(MipsRegLo(Opcode.rd),&GPR[source2].W[0]);
+ }
+}
+
+void Compile_R4300i_SPECIAL_SUB (BLOCK_SECTION * Section) {
+
+ if (Opcode.rd == 0) { return; }
+
+ if (IsConst(Opcode.rt) && IsConst(Opcode.rs)) {
+ uint32_t temp = MipsRegLo(Opcode.rs) - MipsRegLo(Opcode.rt);
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+ MipsRegLo(Opcode.rd) = temp;
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else {
+ if (Opcode.rd == Opcode.rt) {
+ int32_t x86Reg = Map_TempReg(Section,x86_Any,Opcode.rt,0);
+ Map_GPR_32bit(Section,Opcode.rd,1, Opcode.rs);
+ SubX86RegToX86Reg(MipsRegLo(Opcode.rd),x86Reg);
+ return;
+ }
+ Map_GPR_32bit(Section,Opcode.rd,1, Opcode.rs);
+ if (IsConst(Opcode.rt)) {
+ SubConstFromX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(Opcode.rt));
+ } else if (IsMapped(Opcode.rt)) {
+ SubX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(Opcode.rt));
+ } else {
+ SubVariableFromX86reg(MipsRegLo(Opcode.rd),&GPR[Opcode.rt].W[0]);
+ }
+ }
+}
+
+void Compile_R4300i_SPECIAL_SUBU (BLOCK_SECTION * Section) {
+
+ if (Opcode.rd == 0) { return; }
+
+ if (IsConst(Opcode.rt) && IsConst(Opcode.rs)) {
+ uint32_t temp = MipsRegLo(Opcode.rs) - MipsRegLo(Opcode.rt);
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+ MipsRegLo(Opcode.rd) = temp;
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else {
+ if (Opcode.rd == Opcode.rt) {
+ int32_t x86Reg = Map_TempReg(Section,x86_Any,Opcode.rt,0);
+ Map_GPR_32bit(Section,Opcode.rd,1, Opcode.rs);
+ SubX86RegToX86Reg(MipsRegLo(Opcode.rd),x86Reg);
+ return;
+ }
+ Map_GPR_32bit(Section,Opcode.rd,1, Opcode.rs);
+ if (IsConst(Opcode.rt)) {
+ SubConstFromX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(Opcode.rt));
+ } else if (IsMapped(Opcode.rt)) {
+ SubX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(Opcode.rt));
+ } else {
+ SubVariableFromX86reg(MipsRegLo(Opcode.rd),&GPR[Opcode.rt].W[0]);
+ }
+ }
+}
+
+void Compile_R4300i_SPECIAL_AND (BLOCK_SECTION * Section) {
+
+ if (IsKnown(Opcode.rt) && IsKnown(Opcode.rs)) {
+ if (IsConst(Opcode.rt) && IsConst(Opcode.rs)) {
+ if (Is64Bit(Opcode.rt) || Is64Bit(Opcode.rs)) {
+ MipsReg(Opcode.rd) =
+ (Is64Bit(Opcode.rt)?MipsReg(Opcode.rt):(int64_t)MipsRegLo_S(Opcode.rt)) &
+ (Is64Bit(Opcode.rs)?MipsReg(Opcode.rs):(int64_t)MipsRegLo_S(Opcode.rs));
+
+ if (MipsRegLo_S(Opcode.rd) < 0 && MipsRegHi_S(Opcode.rd) == -1){
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else if (MipsRegLo_S(Opcode.rd) >= 0 && MipsRegHi_S(Opcode.rd) == 0){
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else {
+ MipsRegState(Opcode.rd) = STATE_CONST_64;
+ }
+ } else {
+ MipsReg(Opcode.rd) = MipsRegLo(Opcode.rt) & MipsReg(Opcode.rs);
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ }
+ } else if (IsMapped(Opcode.rt) && IsMapped(Opcode.rs)) {
+ int32_t source1 = Opcode.rd == Opcode.rt?Opcode.rt:Opcode.rs;
+ int32_t source2 = Opcode.rd == Opcode.rt?Opcode.rs:Opcode.rt;
+
+ ProtectGPR(Section,source1);
+ ProtectGPR(Section,source2);
+ if (Is32Bit(source1) && Is32Bit(source2)) {
+ int32_t Sign = (IsSigned(Opcode.rt) && IsSigned(Opcode.rs))?1:0;
+ Map_GPR_32bit(Section,Opcode.rd,Sign,source1);
+ AndX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(source2));
+ } else if (Is32Bit(source1) || Is32Bit(source2)) {
+ if (IsUnsigned(Is32Bit(source1)?source1:source2)) {
+ Map_GPR_32bit(Section,Opcode.rd,0,source1);
+ AndX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(source2));
+ } else {
+ Map_GPR_64bit(Section,Opcode.rd,source1);
+ if (Is32Bit(source2)) {
+ AndX86RegToX86Reg(MipsRegHi(Opcode.rd),Map_TempReg(Section,x86_Any,source2,1));
+ } else {
+ AndX86RegToX86Reg(MipsRegHi(Opcode.rd),MipsRegHi(source2));
+ }
+ AndX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(source2));
+ }
+ } else {
+ Map_GPR_64bit(Section,Opcode.rd,source1);
+ AndX86RegToX86Reg(MipsRegHi(Opcode.rd),MipsRegHi(source2));
+ AndX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(source2));
+ }
+ } else {
+ int32_t ConstReg = IsConst(Opcode.rt)?Opcode.rt:Opcode.rs;
+ int32_t MappedReg = IsConst(Opcode.rt)?Opcode.rs:Opcode.rt;
+
+ if (Is64Bit(ConstReg)) {
+ if (Is32Bit(MappedReg) && IsUnsigned(MappedReg)) {
+ if (MipsRegLo(ConstReg) == 0) {
+ Map_GPR_32bit(Section,Opcode.rd,0, 0);
+ } else {
+ uint32_t Value = MipsRegLo(ConstReg);
+ Map_GPR_32bit(Section,Opcode.rd,0, MappedReg);
+ AndConstToX86Reg(MipsRegLo(Opcode.rd),Value);
+ }
+ } else {
+ int64_t Value = MipsReg(ConstReg);
+ Map_GPR_64bit(Section,Opcode.rd,MappedReg);
+ AndConstToX86Reg(MipsRegHi(Opcode.rd),(uint32_t)(Value >> 32));
+ AndConstToX86Reg(MipsRegLo(Opcode.rd),(uint32_t)Value);
+ }
+ } else if (Is64Bit(MappedReg)) {
+ uint32_t Value = MipsRegLo(ConstReg);
+ if (Value != 0) {
+ Map_GPR_32bit(Section,Opcode.rd,IsSigned(ConstReg)?1:0,MappedReg);
+ AndConstToX86Reg(MipsRegLo(Opcode.rd),(uint32_t)Value);
+ } else {
+ Map_GPR_32bit(Section,Opcode.rd,IsSigned(ConstReg)?1:0, 0);
+ }
+ } else {
+ uint32_t Value = MipsRegLo(ConstReg);
+ int32_t Sign = 0;
+ if (IsSigned(ConstReg) && IsSigned(MappedReg)) { Sign = 1; }
+ if (Value != 0) {
+ Map_GPR_32bit(Section,Opcode.rd,Sign,MappedReg);
+ AndConstToX86Reg(MipsRegLo(Opcode.rd),Value);
+ } else {
+ Map_GPR_32bit(Section,Opcode.rd,0, 0);
+ }
+ }
+ }
+ } else if (IsKnown(Opcode.rt) || IsKnown(Opcode.rs)) {
+ uint32_t KnownReg = IsKnown(Opcode.rt)?Opcode.rt:Opcode.rs;
+ uint32_t UnknownReg = IsKnown(Opcode.rt)?Opcode.rs:Opcode.rt;
+
+ if (IsConst(KnownReg)) {
+ if (Is64Bit(KnownReg)) {
+ uint64_t Value = MipsReg(KnownReg);
+ Map_GPR_64bit(Section,Opcode.rd,UnknownReg);
+ AndConstToX86Reg(MipsRegHi(Opcode.rd),(uint32_t)(Value >> 32));
+ AndConstToX86Reg(MipsRegLo(Opcode.rd),(uint32_t)Value);
+ } else {
+ uint32_t Value = MipsRegLo(KnownReg);
+ Map_GPR_32bit(Section,Opcode.rd,IsSigned(KnownReg),UnknownReg);
+ AndConstToX86Reg(MipsRegLo(Opcode.rd),(uint32_t)Value);
+ }
+ } else {
+ ProtectGPR(Section,KnownReg);
+ if (KnownReg == Opcode.rd) {
+ if (Is64Bit(KnownReg)) {
+ Map_GPR_64bit(Section,Opcode.rd,KnownReg);
+ AndVariableToX86Reg(&GPR[UnknownReg].W[1],MipsRegHi(Opcode.rd));
+ AndVariableToX86Reg(&GPR[UnknownReg].W[0],MipsRegLo(Opcode.rd));
+ } else {
+ Map_GPR_32bit(Section,Opcode.rd,IsSigned(KnownReg),KnownReg);
+ AndVariableToX86Reg(&GPR[UnknownReg].W[0],MipsRegLo(Opcode.rd));
+ }
+ } else {
+ if (Is64Bit(KnownReg)) {
+ Map_GPR_64bit(Section,Opcode.rd,UnknownReg);
+ AndX86RegToX86Reg(MipsRegHi(Opcode.rd),MipsRegHi(KnownReg));
+ AndX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(KnownReg));
+ } else {
+ Map_GPR_32bit(Section,Opcode.rd,IsSigned(KnownReg),UnknownReg);
+ AndX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(KnownReg));
+ }
+ }
+ }
+ } else {
+ Map_GPR_64bit(Section,Opcode.rd,Opcode.rt);
+ AndVariableToX86Reg(&GPR[Opcode.rs].W[1],MipsRegHi(Opcode.rd));
+ AndVariableToX86Reg(&GPR[Opcode.rs].W[0],MipsRegLo(Opcode.rd));
+ }
+}
+
+void Compile_R4300i_SPECIAL_OR (BLOCK_SECTION * Section) {
+
+
+ if (IsKnown(Opcode.rt) && IsKnown(Opcode.rs)) {
+ if (IsConst(Opcode.rt) && IsConst(Opcode.rs)) {
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+ if (Is64Bit(Opcode.rt) || Is64Bit(Opcode.rs)) {
+ MipsReg(Opcode.rd) =
+ (Is64Bit(Opcode.rt)?MipsReg(Opcode.rt):(int64_t)MipsRegLo_S(Opcode.rt)) |
+ (Is64Bit(Opcode.rs)?MipsReg(Opcode.rs):(int64_t)MipsRegLo_S(Opcode.rs));
+ if (MipsRegLo_S(Opcode.rd) < 0 && MipsRegHi_S(Opcode.rd) == -1){
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else if (MipsRegLo_S(Opcode.rd) >= 0 && MipsRegHi_S(Opcode.rd) == 0){
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else {
+ MipsRegState(Opcode.rd) = STATE_CONST_64;
+ }
+ } else {
+ MipsRegLo(Opcode.rd) = MipsRegLo(Opcode.rt) | MipsRegLo(Opcode.rs);
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ }
+ } else if (IsMapped(Opcode.rt) && IsMapped(Opcode.rs)) {
+ int32_t source1 = Opcode.rd == Opcode.rt?Opcode.rt:Opcode.rs;
+ int32_t source2 = Opcode.rd == Opcode.rt?Opcode.rs:Opcode.rt;
+
+ ProtectGPR(Section,Opcode.rt);
+ ProtectGPR(Section,Opcode.rs);
+ if (Is64Bit(Opcode.rt) || Is64Bit(Opcode.rs)) {
+ Map_GPR_64bit(Section,Opcode.rd,source1);
+ if (Is64Bit(source2)) {
+ OrX86RegToX86Reg(MipsRegHi(Opcode.rd),MipsRegHi(source2));
+ } else {
+ OrX86RegToX86Reg(MipsRegHi(Opcode.rd),Map_TempReg(Section,x86_Any,source2,1));
+ }
+ } else {
+ ProtectGPR(Section,source2);
+ Map_GPR_32bit(Section,Opcode.rd,1,source1);
+ }
+ OrX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(source2));
+ } else {
+ uint32_t ConstReg = IsConst(Opcode.rt)?Opcode.rt:Opcode.rs;
+ uint32_t MappedReg = IsConst(Opcode.rt)?Opcode.rs:Opcode.rt;
+
+ if (Is64Bit(Opcode.rt) || Is64Bit(Opcode.rs)) {
+ uint64_t Value;
+
+ if (Is64Bit(ConstReg)) {
+ Value = MipsReg(ConstReg);
+ } else {
+ Value = IsSigned(ConstReg)?MipsRegLo_S(ConstReg):MipsRegLo(ConstReg);
+ }
+ Map_GPR_64bit(Section,Opcode.rd,MappedReg);
+ if ((Value >> 32) != 0) {
+ OrConstToX86Reg((uint32_t)(Value >> 32),MipsRegHi(Opcode.rd));
+ }
+ if ((uint32_t)Value != 0) {
+ OrConstToX86Reg((uint32_t)Value,MipsRegLo(Opcode.rd));
+ }
+ } else {
+ int32_t Value = MipsRegLo(ConstReg);
+ Map_GPR_32bit(Section,Opcode.rd,1, MappedReg);
+ if (Value != 0) { OrConstToX86Reg(Value,MipsRegLo(Opcode.rd)); }
+ }
+ }
+ } else if (IsKnown(Opcode.rt) || IsKnown(Opcode.rs)) {
+ int32_t KnownReg = IsKnown(Opcode.rt)?Opcode.rt:Opcode.rs;
+ int32_t UnknownReg = IsKnown(Opcode.rt)?Opcode.rs:Opcode.rt;
+
+ if (IsConst(KnownReg)) {
+ uint64_t Value;
+
+ Value = Is64Bit(KnownReg)?MipsReg(KnownReg):MipsRegLo_S(KnownReg);
+ Map_GPR_64bit(Section,Opcode.rd,UnknownReg);
+ if ((Value >> 32) != 0) {
+ OrConstToX86Reg((uint32_t)(Value >> 32),MipsRegHi(Opcode.rd));
+ }
+ if ((uint32_t)Value != 0) {
+ OrConstToX86Reg((uint32_t)Value,MipsRegLo(Opcode.rd));
+ }
+ } else {
+ Map_GPR_64bit(Section,Opcode.rd,KnownReg);
+ OrVariableToX86Reg(&GPR[UnknownReg].W[1],MipsRegHi(Opcode.rd));
+ OrVariableToX86Reg(&GPR[UnknownReg].W[0],MipsRegLo(Opcode.rd));
+ }
+ } else {
+ Map_GPR_64bit(Section,Opcode.rd,Opcode.rt);
+ OrVariableToX86Reg(&GPR[Opcode.rs].W[1],MipsRegHi(Opcode.rd));
+ OrVariableToX86Reg(&GPR[Opcode.rs].W[0],MipsRegLo(Opcode.rd));
+ }
+}
+
+void Compile_R4300i_SPECIAL_XOR (BLOCK_SECTION * Section) {
+
+ if (Opcode.rd == 0) { return; }
+
+ //BreakPoint();
+
+ if (Opcode.rt == Opcode.rs) {
+ UnMap_GPR(Section, Opcode.rd, 0);
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ MipsRegLo(Opcode.rd) = 0;
+ return;
+ }
+ if (IsKnown(Opcode.rt) && IsKnown(Opcode.rs)) {
+ if (IsConst(Opcode.rt) && IsConst(Opcode.rs)) {
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+ if (Is64Bit(Opcode.rt) || Is64Bit(Opcode.rs)) {
+#ifndef EXTERNAL_RELEASE
+ DisplayError("XOR 1");
+#endif
+ Compile_R4300i_UnknownOpcode(Section);
+ } else {
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ MipsRegLo(Opcode.rd) = MipsRegLo(Opcode.rt) ^ MipsRegLo(Opcode.rs);
+ }
+ } else if (IsMapped(Opcode.rt) && IsMapped(Opcode.rs)) {
+ int32_t source1 = Opcode.rd == Opcode.rt?Opcode.rt:Opcode.rs;
+ int32_t source2 = Opcode.rd == Opcode.rt?Opcode.rs:Opcode.rt;
+
+ ProtectGPR(Section,source1);
+ ProtectGPR(Section,source2);
+ if (Is64Bit(Opcode.rt) || Is64Bit(Opcode.rs)) {
+ Map_GPR_64bit(Section,Opcode.rd,source1);
+ if (Is64Bit(source2)) {
+ XorX86RegToX86Reg(MipsRegHi(Opcode.rd),MipsRegHi(source2));
+ } else if (IsSigned(source2)) {
+ XorX86RegToX86Reg(MipsRegHi(Opcode.rd),Map_TempReg(Section,x86_Any,source2,1));
+ }
+ XorX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(source2));
+ } else {
+ if (IsSigned(Opcode.rt) != IsSigned(Opcode.rs)) {
+ Map_GPR_32bit(Section,Opcode.rd,1,source1);
+ } else {
+ Map_GPR_32bit(Section,Opcode.rd,IsSigned(Opcode.rt),source1);
+ }
+ XorX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(source2));
+ }
+ } else {
+ uint32_t ConstReg = IsConst(Opcode.rt)?Opcode.rt:Opcode.rs;
+ uint32_t MappedReg = IsConst(Opcode.rt)?Opcode.rs:Opcode.rt;
+
+ if (Is64Bit(Opcode.rt) || Is64Bit(Opcode.rs)) {
+ uint32_t ConstHi, ConstLo;
+
+ ConstHi = Is32Bit(ConstReg)?(uint32_t)(MipsRegLo_S(ConstReg) >> 31):MipsRegHi(ConstReg);
+ ConstLo = MipsRegLo(ConstReg);
+ Map_GPR_64bit(Section,Opcode.rd,MappedReg);
+ if (ConstHi != 0) { XorConstToX86Reg(MipsRegHi(Opcode.rd),ConstHi); }
+ if (ConstLo != 0) { XorConstToX86Reg(MipsRegLo(Opcode.rd),ConstLo); }
+ } else {
+ int32_t Value = MipsRegLo(ConstReg);
+ if (IsSigned(Opcode.rt) != IsSigned(Opcode.rs)) {
+ Map_GPR_32bit(Section,Opcode.rd,1, MappedReg);
+ } else {
+ Map_GPR_32bit(Section,Opcode.rd,IsSigned(MappedReg)?1:0, MappedReg);
+ }
+ if (Value != 0) { XorConstToX86Reg(MipsRegLo(Opcode.rd),Value); }
+ }
+ }
+ } else if (IsKnown(Opcode.rt) || IsKnown(Opcode.rs)) {
+ int32_t KnownReg = IsKnown(Opcode.rt)?Opcode.rt:Opcode.rs;
+ int32_t UnknownReg = IsKnown(Opcode.rt)?Opcode.rs:Opcode.rt;
+
+ if (IsConst(KnownReg)) {
+ uint64_t Value;
+
+ if (Is64Bit(KnownReg)) {
+ Value = MipsReg(KnownReg);
+ } else {
+ if (IsSigned(KnownReg)) {
+ Value = (int32_t)MipsRegLo(KnownReg);
+ } else {
+ Value = MipsRegLo(KnownReg);
+ }
+ }
+ Map_GPR_64bit(Section,Opcode.rd,UnknownReg);
+ if ((Value >> 32) != 0) {
+ XorConstToX86Reg(MipsRegHi(Opcode.rd),(uint32_t)(Value >> 32));
+ }
+ if ((uint32_t)Value != 0) {
+ XorConstToX86Reg(MipsRegLo(Opcode.rd),(uint32_t)Value);
+ }
+ } else {
+ Map_GPR_64bit(Section,Opcode.rd,KnownReg);
+ XorVariableToX86reg(&GPR[UnknownReg].W[1],MipsRegHi(Opcode.rd));
+ XorVariableToX86reg(&GPR[UnknownReg].W[0],MipsRegLo(Opcode.rd));
+ }
+ } else {
+ Map_GPR_64bit(Section,Opcode.rd,Opcode.rt);
+ XorVariableToX86reg(&GPR[Opcode.rs].W[1],MipsRegHi(Opcode.rd));
+ XorVariableToX86reg(&GPR[Opcode.rs].W[0],MipsRegLo(Opcode.rd));
+ }
+}
+
+void Compile_R4300i_SPECIAL_NOR (BLOCK_SECTION * Section) {
+
+
+ if (IsKnown(Opcode.rt) && IsKnown(Opcode.rs)) {
+ if (IsConst(Opcode.rt) && IsConst(Opcode.rs)) {
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+ if (Is64Bit(Opcode.rt) || Is64Bit(Opcode.rs)) {
+ Compile_R4300i_UnknownOpcode(Section);
+ } else {
+ MipsRegLo(Opcode.rd) = ~(MipsRegLo(Opcode.rt) | MipsRegLo(Opcode.rs));
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ }
+ } else if (IsMapped(Opcode.rt) && IsMapped(Opcode.rs)) {
+ int32_t source1 = Opcode.rd == Opcode.rt?Opcode.rt:Opcode.rs;
+ int32_t source2 = Opcode.rd == Opcode.rt?Opcode.rs:Opcode.rt;
+
+ ProtectGPR(Section,source1);
+ ProtectGPR(Section,source2);
+ if (Is64Bit(Opcode.rt) || Is64Bit(Opcode.rs)) {
+ Map_GPR_64bit(Section,Opcode.rd,source1);
+ if (Is64Bit(source2)) {
+ OrX86RegToX86Reg(MipsRegHi(Opcode.rd),MipsRegHi(source2));
+ } else {
+ OrX86RegToX86Reg(MipsRegHi(Opcode.rd),Map_TempReg(Section,x86_Any,source2,1));
+ }
+ OrX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(source2));
+ NotX86Reg(MipsRegHi(Opcode.rd));
+ NotX86Reg(MipsRegLo(Opcode.rd));
+ } else {
+ ProtectGPR(Section,source2);
+ if (IsSigned(Opcode.rt) != IsSigned(Opcode.rs)) {
+ Map_GPR_32bit(Section,Opcode.rd,1,source1);
+ } else {
+ Map_GPR_32bit(Section,Opcode.rd,IsSigned(Opcode.rt),source1);
+ }
+ OrX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(source2));
+ NotX86Reg(MipsRegLo(Opcode.rd));
+ }
+ } else {
+ uint32_t ConstReg = IsConst(Opcode.rt)?Opcode.rt:Opcode.rs;
+ uint32_t MappedReg = IsConst(Opcode.rt)?Opcode.rs:Opcode.rt;
+
+ if (Is64Bit(Opcode.rt) || Is64Bit(Opcode.rs)) {
+ uint64_t Value;
+
+ if (Is64Bit(ConstReg)) {
+ Value = MipsReg(ConstReg);
+ } else {
+ Value = IsSigned(ConstReg)?MipsRegLo_S(ConstReg):MipsRegLo(ConstReg);
+ }
+ Map_GPR_64bit(Section,Opcode.rd,MappedReg);
+ if ((Value >> 32) != 0) {
+ OrConstToX86Reg((uint32_t)(Value >> 32),MipsRegHi(Opcode.rd));
+ }
+ if ((uint32_t)Value != 0) {
+ OrConstToX86Reg((uint32_t)Value,MipsRegLo(Opcode.rd));
+ }
+ NotX86Reg(MipsRegHi(Opcode.rd));
+ NotX86Reg(MipsRegLo(Opcode.rd));
+ } else {
+ int32_t Value = MipsRegLo(ConstReg);
+ if (IsSigned(Opcode.rt) != IsSigned(Opcode.rs)) {
+ Map_GPR_32bit(Section,Opcode.rd,1, MappedReg);
+ } else {
+ Map_GPR_32bit(Section,Opcode.rd,IsSigned(MappedReg)?1:0, MappedReg);
+ }
+ if (Value != 0) { OrConstToX86Reg(Value,MipsRegLo(Opcode.rd)); }
+ NotX86Reg(MipsRegLo(Opcode.rd));
+ }
+ }
+ } else if (IsKnown(Opcode.rt) || IsKnown(Opcode.rs)) {
+ int32_t KnownReg = IsKnown(Opcode.rt)?Opcode.rt:Opcode.rs;
+ int32_t UnknownReg = IsKnown(Opcode.rt)?Opcode.rs:Opcode.rt;
+
+ if (IsConst(KnownReg)) {
+ uint64_t Value;
+
+ Value = Is64Bit(KnownReg)?MipsReg(KnownReg):MipsRegLo_S(KnownReg);
+ Map_GPR_64bit(Section,Opcode.rd,UnknownReg);
+ if ((Value >> 32) != 0) {
+ OrConstToX86Reg((uint32_t)(Value >> 32),MipsRegHi(Opcode.rd));
+ }
+ if ((uint32_t)Value != 0) {
+ OrConstToX86Reg((uint32_t)Value,MipsRegLo(Opcode.rd));
+ }
+ } else {
+ Map_GPR_64bit(Section,Opcode.rd,KnownReg);
+ OrVariableToX86Reg(&GPR[UnknownReg].W[1],MipsRegHi(Opcode.rd));
+ OrVariableToX86Reg(&GPR[UnknownReg].W[0],MipsRegLo(Opcode.rd));
+ }
+ NotX86Reg(MipsRegHi(Opcode.rd));
+ NotX86Reg(MipsRegLo(Opcode.rd));
+ } else {
+ Map_GPR_64bit(Section,Opcode.rd,Opcode.rt);
+ OrVariableToX86Reg(&GPR[Opcode.rs].W[1],MipsRegHi(Opcode.rd));
+ OrVariableToX86Reg(&GPR[Opcode.rs].W[0],MipsRegLo(Opcode.rd));
+ NotX86Reg(MipsRegHi(Opcode.rd));
+ NotX86Reg(MipsRegLo(Opcode.rd));
+ }
+}
+
+void Compile_R4300i_SPECIAL_SLT (BLOCK_SECTION * Section) {
+
+
+ if (IsKnown(Opcode.rt) && IsKnown(Opcode.rs)) {
+ if (IsConst(Opcode.rt) && IsConst(Opcode.rs)) {
+ if (Is64Bit(Opcode.rt) || Is64Bit(Opcode.rs)) {
+ DisplayError("1");
+ Compile_R4300i_UnknownOpcode(Section);
+ } else {
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ if (MipsRegLo_S(Opcode.rs) < MipsRegLo_S(Opcode.rt)) {
+ MipsRegLo(Opcode.rd) = 1;
+ } else {
+ MipsRegLo(Opcode.rd) = 0;
+ }
+ }
+ } else if (IsMapped(Opcode.rt) && IsMapped(Opcode.rs)) {
+ ProtectGPR(Section,Opcode.rt);
+ ProtectGPR(Section,Opcode.rs);
+ if (Is64Bit(Opcode.rt) || Is64Bit(Opcode.rs)) {
+ uint8_t *Jump[2];
+
+ CompX86RegToX86Reg(
+ Is64Bit(Opcode.rs)?MipsRegHi(Opcode.rs):Map_TempReg(Section,x86_Any,Opcode.rs,1),
+ Is64Bit(Opcode.rt)?MipsRegHi(Opcode.rt):Map_TempReg(Section,x86_Any,Opcode.rt,1)
+ );
+ JeLabel8(0);
+ Jump[0] = RecompPos - 1;
+ SetlVariable(&BranchCompare);
+ JmpLabel8(0);
+ Jump[1] = RecompPos - 1;
+
+
+
+ *((uint8_t *)(Jump[0]))=(uint8_t)(RecompPos - Jump[0] - 1);
+ CompX86RegToX86Reg(MipsRegLo(Opcode.rs), MipsRegLo(Opcode.rt));
+ SetbVariable(&BranchCompare);
+
+
+ *((uint8_t *)(Jump[1]))=(uint8_t)(RecompPos - Jump[1] - 1);
+ Map_GPR_32bit(Section,Opcode.rd,1, -1);
+ MoveVariableToX86reg(&BranchCompare,MipsRegLo(Opcode.rd));
+ } else {
+ Map_GPR_32bit(Section,Opcode.rd,1, -1);
+ CompX86RegToX86Reg(MipsRegLo(Opcode.rs), MipsRegLo(Opcode.rt));
+
+ if (MipsRegLo(Opcode.rd) > x86_EDX) {
+ SetlVariable(&BranchCompare);
+ MoveVariableToX86reg(&BranchCompare,MipsRegLo(Opcode.rd));
+ } else {
+ Setl(MipsRegLo(Opcode.rd));
+ AndConstToX86Reg(MipsRegLo(Opcode.rd), 1);
+ }
+ }
+ } else {
+ uint32_t ConstReg = IsConst(Opcode.rs)?Opcode.rs:Opcode.rt;
+ uint32_t MappedReg = IsConst(Opcode.rs)?Opcode.rt:Opcode.rs;
+
+ ProtectGPR(Section,MappedReg);
+ if (Is64Bit(Opcode.rt) || Is64Bit(Opcode.rs)) {
+ uint8_t *Jump[2];
+
+ CompConstToX86reg(
+ Is64Bit(MappedReg)?MipsRegHi(MappedReg):Map_TempReg(Section,x86_Any,MappedReg,1),
+ Is64Bit(ConstReg)?MipsRegHi(ConstReg):(MipsRegLo_S(ConstReg) >> 31)
+ );
+ JeLabel8(0);
+ Jump[0] = RecompPos - 1;
+ if (MappedReg == Opcode.rs) {
+ SetlVariable(&BranchCompare);
+ } else {
+ SetgVariable(&BranchCompare);
+ }
+ JmpLabel8(0);
+ Jump[1] = RecompPos - 1;
+
+
+
+ *((uint8_t *)(Jump[0]))=(uint8_t)(RecompPos - Jump[0] - 1);
+ CompConstToX86reg(MipsRegLo(MappedReg), MipsRegLo(ConstReg));
+ if (MappedReg == Opcode.rs) {
+ SetbVariable(&BranchCompare);
+ } else {
+ SetaVariable(&BranchCompare);
+ }
+
+
+ *((uint8_t *)(Jump[1]))=(uint8_t)(RecompPos - Jump[1] - 1);
+ Map_GPR_32bit(Section,Opcode.rd,1, -1);
+ MoveVariableToX86reg(&BranchCompare,MipsRegLo(Opcode.rd));
+ } else {
+ uint32_t Constant = MipsRegLo(ConstReg);
+ Map_GPR_32bit(Section,Opcode.rd,1, -1);
+ CompConstToX86reg(MipsRegLo(MappedReg), Constant);
+
+ if (MipsRegLo(Opcode.rd) > x86_EDX) {
+ if (MappedReg == Opcode.rs) {
+ SetlVariable(&BranchCompare);
+ } else {
+ SetgVariable(&BranchCompare);
+ }
+ MoveVariableToX86reg(&BranchCompare,MipsRegLo(Opcode.rd));
+ } else {
+ if (MappedReg == Opcode.rs) {
+ Setl(MipsRegLo(Opcode.rd));
+ } else {
+ Setg(MipsRegLo(Opcode.rd));
+ }
+ AndConstToX86Reg(MipsRegLo(Opcode.rd), 1);
+ }
+ }
+ }
+ } else if (IsKnown(Opcode.rt) || IsKnown(Opcode.rs)) {
+ uint32_t KnownReg = IsKnown(Opcode.rt)?Opcode.rt:Opcode.rs;
+ uint32_t UnknownReg = IsKnown(Opcode.rt)?Opcode.rs:Opcode.rt;
+ uint8_t *Jump[2];
+
+ if (IsConst(KnownReg)) {
+ if (Is64Bit(KnownReg)) {
+ CompConstToVariable(MipsRegHi(KnownReg),&GPR[UnknownReg].W[1]);
+ } else {
+ CompConstToVariable(((int32_t)MipsRegLo(KnownReg) >> 31),&GPR[UnknownReg].W[1]);
+ }
+ } else {
+ if (Is64Bit(KnownReg)) {
+ CompX86regToVariable(MipsRegHi(KnownReg),&GPR[UnknownReg].W[1]);
+ } else {
+ ProtectGPR(Section,KnownReg);
+ CompX86regToVariable(Map_TempReg(Section,x86_Any,KnownReg,1),&GPR[UnknownReg].W[1]);
+ }
+ }
+ JeLabel8(0);
+ Jump[0] = RecompPos - 1;
+ if (KnownReg == (IsConst(KnownReg)?Opcode.rs:Opcode.rt)) {
+ SetgVariable(&BranchCompare);
+ } else {
+ SetlVariable(&BranchCompare);
+ }
+ JmpLabel8(0);
+ Jump[1] = RecompPos - 1;
+
+
+
+ *((uint8_t *)(Jump[0]))=(uint8_t)(RecompPos - Jump[0] - 1);
+ if (IsConst(KnownReg)) {
+ CompConstToVariable(MipsRegLo(KnownReg),&GPR[UnknownReg].W[0]);
+ } else {
+ CompX86regToVariable(MipsRegLo(KnownReg),&GPR[UnknownReg].W[0]);
+ }
+ if (KnownReg == (IsConst(KnownReg)?Opcode.rs:Opcode.rt)) {
+ SetaVariable(&BranchCompare);
+ } else {
+ SetbVariable(&BranchCompare);
+ }
+
+
+ *((uint8_t *)(Jump[1]))=(uint8_t)(RecompPos - Jump[1] - 1);
+ Map_GPR_32bit(Section,Opcode.rd,1, -1);
+ MoveVariableToX86reg(&BranchCompare,MipsRegLo(Opcode.rd));
+ } else {
+ uint8_t *Jump[2];
+ int32_t x86Reg;
+
+ x86Reg = Map_TempReg(Section,x86_Any,Opcode.rs,1);
+ CompX86regToVariable(x86Reg,&GPR[Opcode.rt].W[1]);
+ JeLabel8(0);
+ Jump[0] = RecompPos - 1;
+ SetlVariable(&BranchCompare);
+ JmpLabel8(0);
+ Jump[1] = RecompPos - 1;
+
+
+
+ *((uint8_t *)(Jump[0]))=(uint8_t)(RecompPos - Jump[0] - 1);
+ CompX86regToVariable(Map_TempReg(Section,x86Reg,Opcode.rs,0),&GPR[Opcode.rt].W[0]);
+ SetbVariable(&BranchCompare);
+
+
+ *((uint8_t *)(Jump[1]))=(uint8_t)(RecompPos - Jump[1] - 1);
+ Map_GPR_32bit(Section,Opcode.rd,1, -1);
+ MoveVariableToX86reg(&BranchCompare,MipsRegLo(Opcode.rd));
+ }
+}
+
+void Compile_R4300i_SPECIAL_SLTU (BLOCK_SECTION * Section) {
+
+ if (Opcode.rd == 0) { return; }
+
+ if (IsKnown(Opcode.rt) && IsKnown(Opcode.rs)) {
+ if (IsConst(Opcode.rt) && IsConst(Opcode.rs)) {
+ if (Is64Bit(Opcode.rt) || Is64Bit(Opcode.rs)) {
+#ifndef EXTERNAL_RELEASE
+ DisplayError("1");
+#endif
+ Compile_R4300i_UnknownOpcode(Section);
+ } else {
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ if (MipsRegLo(Opcode.rs) < MipsRegLo(Opcode.rt)) {
+ MipsRegLo(Opcode.rd) = 1;
+ } else {
+ MipsRegLo(Opcode.rd) = 0;
+ }
+ }
+ } else if (IsMapped(Opcode.rt) && IsMapped(Opcode.rs)) {
+ ProtectGPR(Section,Opcode.rt);
+ ProtectGPR(Section,Opcode.rs);
+ if (Is64Bit(Opcode.rt) || Is64Bit(Opcode.rs)) {
+ uint8_t *Jump[2];
+
+ CompX86RegToX86Reg(
+ Is64Bit(Opcode.rs)?MipsRegHi(Opcode.rs):Map_TempReg(Section,x86_Any,Opcode.rs,1),
+ Is64Bit(Opcode.rt)?MipsRegHi(Opcode.rt):Map_TempReg(Section,x86_Any,Opcode.rt,1)
+ );
+ JeLabel8(0);
+ Jump[0] = RecompPos - 1;
+ SetbVariable(&BranchCompare);
+ JmpLabel8(0);
+ Jump[1] = RecompPos - 1;
+
+
+
+ *((uint8_t *)(Jump[0]))=(uint8_t)(RecompPos - Jump[0] - 1);
+ CompX86RegToX86Reg(MipsRegLo(Opcode.rs), MipsRegLo(Opcode.rt));
+ SetbVariable(&BranchCompare);
+
+
+ *((uint8_t *)(Jump[1]))=(uint8_t)(RecompPos - Jump[1] - 1);
+ Map_GPR_32bit(Section,Opcode.rd,1, -1);
+ MoveVariableToX86reg(&BranchCompare,MipsRegLo(Opcode.rd));
+ } else {
+ CompX86RegToX86Reg(MipsRegLo(Opcode.rs), MipsRegLo(Opcode.rt));
+ SetbVariable(&BranchCompare);
+ Map_GPR_32bit(Section,Opcode.rd,1, -1);
+ MoveVariableToX86reg(&BranchCompare,MipsRegLo(Opcode.rd));
+ }
+ } else {
+ if (Is64Bit(Opcode.rt) || Is64Bit(Opcode.rs)) {
+ uint32_t MappedRegHi, MappedRegLo, ConstHi, ConstLo, MappedReg, ConstReg;
+ uint8_t *Jump[2];
+
+ ConstReg = IsConst(Opcode.rt)?Opcode.rt:Opcode.rs;
+ MappedReg = IsConst(Opcode.rt)?Opcode.rs:Opcode.rt;
+
+ ConstLo = MipsRegLo(ConstReg);
+ ConstHi = (int32_t)ConstLo >> 31;
+ if (Is64Bit(ConstReg)) { ConstHi = MipsRegHi(ConstReg); }
+
+ ProtectGPR(Section,MappedReg);
+ MappedRegLo = MipsRegLo(MappedReg);
+ MappedRegHi = MipsRegHi(MappedReg);
+ if (Is32Bit(MappedReg)) {
+ MappedRegHi = Map_TempReg(Section,x86_Any,MappedReg,1);
+ }
+
+
+ Map_GPR_32bit(Section,Opcode.rd,1, -1);
+ CompConstToX86reg(MappedRegHi, ConstHi);
+ JeLabel8(0);
+ Jump[0] = RecompPos - 1;
+ if (MappedReg == Opcode.rs) {
+ SetbVariable(&BranchCompare);
+ } else {
+ SetaVariable(&BranchCompare);
+ }
+ JmpLabel8(0);
+ Jump[1] = RecompPos - 1;
+
+
+
+ *((uint8_t *)(Jump[0]))=(uint8_t)(RecompPos - Jump[0] - 1);
+ CompConstToX86reg(MappedRegLo, ConstLo);
+ if (MappedReg == Opcode.rs) {
+ SetbVariable(&BranchCompare);
+ } else {
+ SetaVariable(&BranchCompare);
+ }
+
+
+ *((uint8_t *)(Jump[1]))=(uint8_t)(RecompPos - Jump[1] - 1);
+ Map_GPR_32bit(Section,Opcode.rd,1, -1);
+ MoveVariableToX86reg(&BranchCompare,MipsRegLo(Opcode.rd));
+ } else {
+ uint32_t Const = IsConst(Opcode.rs)?MipsRegLo(Opcode.rs):MipsRegLo(Opcode.rt);
+ uint32_t MappedReg = IsConst(Opcode.rt)?Opcode.rs:Opcode.rt;
+
+ CompConstToX86reg(MipsRegLo(MappedReg), Const);
+ if (MappedReg == Opcode.rs) {
+ SetbVariable(&BranchCompare);
+ } else {
+ SetaVariable(&BranchCompare);
+ }
+ Map_GPR_32bit(Section,Opcode.rd,1, -1);
+ MoveVariableToX86reg(&BranchCompare,MipsRegLo(Opcode.rd));
+ }
+ }
+ } else if (IsKnown(Opcode.rt) || IsKnown(Opcode.rs)) {
+ uint32_t KnownReg = IsKnown(Opcode.rt)?Opcode.rt:Opcode.rs;
+ uint32_t UnknownReg = IsKnown(Opcode.rt)?Opcode.rs:Opcode.rt;
+ uint8_t *Jump[2];
+
+ if (IsConst(KnownReg)) {
+ if (Is64Bit(KnownReg)) {
+ CompConstToVariable(MipsRegHi(KnownReg),&GPR[UnknownReg].W[1]);
+ } else {
+ CompConstToVariable(((int32_t)MipsRegLo(KnownReg) >> 31),&GPR[UnknownReg].W[1]);
+ }
+ } else {
+ if (Is64Bit(KnownReg)) {
+ CompX86regToVariable(MipsRegHi(KnownReg),&GPR[UnknownReg].W[1]);
+ } else {
+ ProtectGPR(Section,KnownReg);
+ CompX86regToVariable(Map_TempReg(Section,x86_Any,KnownReg,1),&GPR[UnknownReg].W[1]);
+ }
+ }
+ JeLabel8(0);
+ Jump[0] = RecompPos - 1;
+ if (KnownReg == (IsConst(KnownReg)?Opcode.rs:Opcode.rt)) {
+ SetaVariable(&BranchCompare);
+ } else {
+ SetbVariable(&BranchCompare);
+ }
+ JmpLabel8(0);
+ Jump[1] = RecompPos - 1;
+
+
+
+ *((uint8_t *)(Jump[0]))=(uint8_t)(RecompPos - Jump[0] - 1);
+ if (IsConst(KnownReg)) {
+ CompConstToVariable(MipsRegLo(KnownReg),&GPR[UnknownReg].W[0]);
+ } else {
+ CompX86regToVariable(MipsRegLo(KnownReg),&GPR[UnknownReg].W[0]);
+ }
+ if (KnownReg == (IsConst(KnownReg)?Opcode.rs:Opcode.rt)) {
+ SetaVariable(&BranchCompare);
+ } else {
+ SetbVariable(&BranchCompare);
+ }
+
+
+ *((uint8_t *)(Jump[1]))=(uint8_t)(RecompPos - Jump[1] - 1);
+ Map_GPR_32bit(Section,Opcode.rd,1, -1);
+ MoveVariableToX86reg(&BranchCompare,MipsRegLo(Opcode.rd));
+ } else {
+ uint8_t *Jump[2];
+ int32_t x86Reg;
+
+ x86Reg = Map_TempReg(Section,x86_Any,Opcode.rs,1);
+ CompX86regToVariable(x86Reg,&GPR[Opcode.rt].W[1]);
+ JeLabel8(0);
+ Jump[0] = RecompPos - 1;
+ SetbVariable(&BranchCompare);
+ JmpLabel8(0);
+ Jump[1] = RecompPos - 1;
+
+
+
+ *((uint8_t *)(Jump[0]))=(uint8_t)(RecompPos - Jump[0] - 1);
+ CompX86regToVariable(Map_TempReg(Section,x86Reg,Opcode.rs,0),&GPR[Opcode.rt].W[0]);
+ SetbVariable(&BranchCompare);
+
+
+ *((uint8_t *)(Jump[1]))=(uint8_t)(RecompPos - Jump[1] - 1);
+ Map_GPR_32bit(Section,Opcode.rd,1, -1);
+ MoveVariableToX86reg(&BranchCompare,MipsRegLo(Opcode.rd));
+ }
+}
+
+void Compile_R4300i_SPECIAL_DADD (BLOCK_SECTION * Section) {
+
+ if (Opcode.rd == 0) { return; }
+
+ if (IsConst(Opcode.rt) && IsConst(Opcode.rs)) {
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+ MipsReg(Opcode.rd) =
+ Is64Bit(Opcode.rs)?MipsReg(Opcode.rs):(int64_t)MipsRegLo_S(Opcode.rs) +
+ Is64Bit(Opcode.rt)?MipsReg(Opcode.rt):(int64_t)MipsRegLo_S(Opcode.rt);
+ if (MipsRegLo_S(Opcode.rd) < 0 && MipsRegHi_S(Opcode.rd) == -1){
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else if (MipsRegLo_S(Opcode.rd) >= 0 && MipsRegHi_S(Opcode.rd) == 0){
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else {
+ MipsRegState(Opcode.rd) = STATE_CONST_64;
+ }
+ } else {
+ Map_GPR_64bit(Section,Opcode.rd,Opcode.rs);
+ if (IsConst(Opcode.rt)) {
+ AddConstToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(Opcode.rt));
+ AddConstToX86Reg(MipsRegHi(Opcode.rd),MipsRegHi(Opcode.rt));
+ } else if (IsMapped(Opcode.rt)) {
+ int32_t HiReg = Is64Bit(Opcode.rt)?MipsRegHi(Opcode.rt):Map_TempReg(Section,x86_Any,Opcode.rt,1);
+ ProtectGPR(Section,Opcode.rt);
+ AddX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(Opcode.rt));
+ AdcX86RegToX86Reg(MipsRegHi(Opcode.rd),HiReg);
+ } else {
+ AddVariableToX86reg(MipsRegLo(Opcode.rd),&GPR[Opcode.rt].W[0]);
+ AdcVariableToX86reg(MipsRegHi(Opcode.rd),&GPR[Opcode.rt].W[1]);
+ }
+ }
+}
+
+void Compile_R4300i_SPECIAL_DADDU (BLOCK_SECTION * Section) {
+
+ if (Opcode.rd == 0) { return; }
+
+ if (IsConst(Opcode.rt) && IsConst(Opcode.rs)) {
+ int64_t ValRs = Is64Bit(Opcode.rs)?MipsReg(Opcode.rs):(int64_t)MipsRegLo_S(Opcode.rs);
+ int64_t ValRt = Is64Bit(Opcode.rt)?MipsReg(Opcode.rt):(int64_t)MipsRegLo_S(Opcode.rt);
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+ MipsReg(Opcode.rd) = ValRs + ValRt;
+ if ((MipsRegHi(Opcode.rd) == 0) && (MipsRegLo(Opcode.rd) & 0x80000000) == 0) {
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else if ((MipsRegHi(Opcode.rd) == 0xFFFFFFFF) && (MipsRegLo(Opcode.rd) & 0x80000000) != 0) {
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else {
+ MipsRegState(Opcode.rd) = STATE_CONST_64;
+ }
+ } else {
+ Map_GPR_64bit(Section,Opcode.rd,Opcode.rs);
+ if (IsConst(Opcode.rt)) {
+ AddConstToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(Opcode.rt));
+ AddConstToX86Reg(MipsRegHi(Opcode.rd),MipsRegHi(Opcode.rt));
+ } else if (IsMapped(Opcode.rt)) {
+ int32_t HiReg = Is64Bit(Opcode.rt)?MipsRegHi(Opcode.rt):Map_TempReg(Section,x86_Any,Opcode.rt,1);
+ ProtectGPR(Section,Opcode.rt);
+ AddX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(Opcode.rt));
+ AdcX86RegToX86Reg(MipsRegHi(Opcode.rd),HiReg);
+ } else {
+ AddVariableToX86reg(MipsRegLo(Opcode.rd),&GPR[Opcode.rt].W[0]);
+ AdcVariableToX86reg(MipsRegHi(Opcode.rd),&GPR[Opcode.rt].W[1]);
+ }
+ }
+}
+
+void Compile_R4300i_SPECIAL_DSUB (BLOCK_SECTION * Section) {
+
+ if (Opcode.rd == 0) { return; }
+
+ if (IsConst(Opcode.rt) && IsConst(Opcode.rs)) {
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+ MipsReg(Opcode.rd) =
+ Is64Bit(Opcode.rs)?MipsReg(Opcode.rs):(int64_t)MipsRegLo_S(Opcode.rs) -
+ Is64Bit(Opcode.rt)?MipsReg(Opcode.rt):(int64_t)MipsRegLo_S(Opcode.rt);
+ if (MipsRegLo_S(Opcode.rd) < 0 && MipsRegHi_S(Opcode.rd) == -1){
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else if (MipsRegLo_S(Opcode.rd) >= 0 && MipsRegHi_S(Opcode.rd) == 0){
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else {
+ MipsRegState(Opcode.rd) = STATE_CONST_64;
+ }
+ } else {
+ if (Opcode.rd == Opcode.rt) {
+ int32_t HiReg = Map_TempReg(Section,x86_Any,Opcode.rt,1);
+ int32_t LoReg = Map_TempReg(Section,x86_Any,Opcode.rt,0);
+ Map_GPR_64bit(Section,Opcode.rd,Opcode.rs);
+ SubX86RegToX86Reg(MipsRegLo(Opcode.rd),LoReg);
+ SbbX86RegToX86Reg(MipsRegHi(Opcode.rd),HiReg);
+ return;
+ }
+ Map_GPR_64bit(Section,Opcode.rd,Opcode.rs);
+ if (IsConst(Opcode.rt)) {
+ SubConstFromX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(Opcode.rt));
+ SbbConstFromX86Reg(MipsRegHi(Opcode.rd),MipsRegHi(Opcode.rt));
+ } else if (IsMapped(Opcode.rt)) {
+ int32_t HiReg = Is64Bit(Opcode.rt)?MipsRegHi(Opcode.rt):Map_TempReg(Section,x86_Any,Opcode.rt,1);
+ ProtectGPR(Section,Opcode.rt);
+ SubX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(Opcode.rt));
+ SbbX86RegToX86Reg(MipsRegHi(Opcode.rd),HiReg);
+ } else {
+ SubVariableFromX86reg(MipsRegLo(Opcode.rd),&GPR[Opcode.rt].W[0]);
+ SbbVariableFromX86reg(MipsRegHi(Opcode.rd),&GPR[Opcode.rt].W[1]);
+ }
+ }
+}
+
+void Compile_R4300i_SPECIAL_DSUBU (BLOCK_SECTION * Section) {
+
+ if (Opcode.rd == 0) { return; }
+
+ if (IsConst(Opcode.rt) && IsConst(Opcode.rs)) {
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+ MipsReg(Opcode.rd) =
+ Is64Bit(Opcode.rs)?MipsReg(Opcode.rs):(int64_t)MipsRegLo_S(Opcode.rs) -
+ Is64Bit(Opcode.rt)?MipsReg(Opcode.rt):(int64_t)MipsRegLo_S(Opcode.rt);
+ if (MipsRegLo_S(Opcode.rd) < 0 && MipsRegHi_S(Opcode.rd) == -1){
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else if (MipsRegLo_S(Opcode.rd) >= 0 && MipsRegHi_S(Opcode.rd) == 0){
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else {
+ MipsRegState(Opcode.rd) = STATE_CONST_64;
+ }
+ } else {
+ if (Opcode.rd == Opcode.rt) {
+ int32_t HiReg = Map_TempReg(Section,x86_Any,Opcode.rt,1);
+ int32_t LoReg = Map_TempReg(Section,x86_Any,Opcode.rt,0);
+ Map_GPR_64bit(Section,Opcode.rd,Opcode.rs);
+ SubX86RegToX86Reg(MipsRegLo(Opcode.rd),LoReg);
+ SbbX86RegToX86Reg(MipsRegHi(Opcode.rd),HiReg);
+ return;
+ }
+ Map_GPR_64bit(Section,Opcode.rd,Opcode.rs);
+ if (IsConst(Opcode.rt)) {
+ SubConstFromX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(Opcode.rt));
+ SbbConstFromX86Reg(MipsRegHi(Opcode.rd),MipsRegHi(Opcode.rt));
+ } else if (IsMapped(Opcode.rt)) {
+ int32_t HiReg = Is64Bit(Opcode.rt)?MipsRegHi(Opcode.rt):Map_TempReg(Section,x86_Any,Opcode.rt,1);
+ ProtectGPR(Section,Opcode.rt);
+ SubX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(Opcode.rt));
+ SbbX86RegToX86Reg(MipsRegHi(Opcode.rd),HiReg);
+ } else {
+ SubVariableFromX86reg(MipsRegLo(Opcode.rd),&GPR[Opcode.rt].W[0]);
+ SbbVariableFromX86reg(MipsRegHi(Opcode.rd),&GPR[Opcode.rt].W[1]);
+ }
+ }
+}
+
+void Compile_R4300i_SPECIAL_DSLL (BLOCK_SECTION * Section) {
+
+
+ if (Opcode.rd == 0) { return; }
+ if (IsConst(Opcode.rt)) {
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+
+ MipsReg(Opcode.rd) = Is64Bit(Opcode.rt)?MipsReg(Opcode.rt):(int64_t)MipsRegLo_S(Opcode.rt) << Opcode.sa;
+ if (MipsRegLo_S(Opcode.rd) < 0 && MipsRegHi_S(Opcode.rd) == -1){
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else if (MipsRegLo_S(Opcode.rd) >= 0 && MipsRegHi_S(Opcode.rd) == 0){
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else {
+ MipsRegState(Opcode.rd) = STATE_CONST_64;
+ }
+ return;
+ }
+
+ Map_GPR_64bit(Section,Opcode.rd,Opcode.rt);
+ ShiftLeftDoubleImmed(MipsRegHi(Opcode.rd),MipsRegLo(Opcode.rd),(uint8_t)Opcode.sa);
+ ShiftLeftSignImmed( MipsRegLo(Opcode.rd),(uint8_t)Opcode.sa);
+}
+
+void Compile_R4300i_SPECIAL_DSRL (BLOCK_SECTION * Section) {
+
+
+ if (Opcode.rd == 0) { return; }
+ if (IsConst(Opcode.rt)) {
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+
+ MipsReg(Opcode.rd) = Is64Bit(Opcode.rt)?MipsReg(Opcode.rt):(QWORD)MipsRegLo_S(Opcode.rt) >> Opcode.sa;
+ if (MipsRegLo_S(Opcode.rd) < 0 && MipsRegHi_S(Opcode.rd) == -1){
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else if (MipsRegLo_S(Opcode.rd) >= 0 && MipsRegHi_S(Opcode.rd) == 0){
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else {
+ MipsRegState(Opcode.rd) = STATE_CONST_64;
+ }
+ return;
+ }
+ Map_GPR_64bit(Section,Opcode.rd,Opcode.rt);
+ ShiftRightDoubleImmed(MipsRegLo(Opcode.rd),MipsRegHi(Opcode.rd),(uint8_t)Opcode.sa);
+ ShiftRightUnsignImmed(MipsRegHi(Opcode.rd),(uint8_t)Opcode.sa);
+}
+
+void Compile_R4300i_SPECIAL_DSRA (BLOCK_SECTION * Section) {
+
+
+ if (Opcode.rd == 0) { return; }
+ if (IsConst(Opcode.rt)) {
+ if (IsMapped(Opcode.rd)) { UnMap_GPR(Section,Opcode.rd, 0); }
+
+ MipsReg_S(Opcode.rd) = Is64Bit(Opcode.rt)?MipsReg_S(Opcode.rt):(int64_t)MipsRegLo_S(Opcode.rt) >> Opcode.sa;
+ if (MipsRegLo_S(Opcode.rd) < 0 && MipsRegHi_S(Opcode.rd) == -1){
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else if (MipsRegLo_S(Opcode.rd) >= 0 && MipsRegHi_S(Opcode.rd) == 0){
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else {
+ MipsRegState(Opcode.rd) = STATE_CONST_64;
+ }
+ return;
+ }
+ Map_GPR_64bit(Section,Opcode.rd,Opcode.rt);
+ ShiftRightDoubleImmed(MipsRegLo(Opcode.rd),MipsRegHi(Opcode.rd),(uint8_t)Opcode.sa);
+ ShiftRightSignImmed(MipsRegHi(Opcode.rd),(uint8_t)Opcode.sa);
+}
+
+void Compile_R4300i_SPECIAL_DSLL32 (BLOCK_SECTION * Section) {
+
+
+ if (Opcode.rd == 0) { return; }
+ if (IsConst(Opcode.rt)) {
+ if (Opcode.rt != Opcode.rd) { UnMap_GPR(Section,Opcode.rd, 0); }
+ MipsRegHi(Opcode.rd) = MipsRegLo(Opcode.rt) << Opcode.sa;
+ MipsRegLo(Opcode.rd) = 0;
+ if (MipsRegLo_S(Opcode.rd) < 0 && MipsRegHi_S(Opcode.rd) == -1){
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else if (MipsRegLo_S(Opcode.rd) >= 0 && MipsRegHi_S(Opcode.rd) == 0){
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ } else {
+ MipsRegState(Opcode.rd) = STATE_CONST_64;
+ }
+
+ } else if (IsMapped(Opcode.rt)) {
+ ProtectGPR(Section,Opcode.rt);
+ Map_GPR_64bit(Section,Opcode.rd,-1);
+ if (Opcode.rt != Opcode.rd) {
+ MoveX86RegToX86Reg(MipsRegLo(Opcode.rt),MipsRegHi(Opcode.rd));
+ } else {
+ int32_t HiReg = MipsRegHi(Opcode.rt);
+ MipsRegHi(Opcode.rt) = MipsRegLo(Opcode.rt);
+ MipsRegLo(Opcode.rt) = HiReg;
+ }
+ if ((uint8_t)Opcode.sa != 0) {
+ ShiftLeftSignImmed(MipsRegHi(Opcode.rd),(uint8_t)Opcode.sa);
+ }
+ XorX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(Opcode.rd));
+ } else {
+ Map_GPR_64bit(Section,Opcode.rd,-1);
+ MoveVariableToX86reg(&GPR[Opcode.rt],MipsRegHi(Opcode.rd));
+ if ((uint8_t)Opcode.sa != 0) {
+ ShiftLeftSignImmed(MipsRegHi(Opcode.rd),(uint8_t)Opcode.sa);
+ }
+ XorX86RegToX86Reg(MipsRegLo(Opcode.rd),MipsRegLo(Opcode.rd));
+ }
+}
+
+void Compile_R4300i_SPECIAL_DSRL32 (BLOCK_SECTION * Section) {
+
+ if (IsConst(Opcode.rt)) {
+ if (Opcode.rt != Opcode.rd) { UnMap_GPR(Section,Opcode.rd, 0); }
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ MipsRegLo(Opcode.rd) = (uint32_t)(MipsReg(Opcode.rt) >> (Opcode.sa + 32));
+ } else if (IsMapped(Opcode.rt)) {
+ ProtectGPR(Section,Opcode.rt);
+ if (Is64Bit(Opcode.rt)) {
+ if (Opcode.rt == Opcode.rd) {
+ int32_t HiReg = MipsRegHi(Opcode.rt);
+ MipsRegHi(Opcode.rt) = MipsRegLo(Opcode.rt);
+ MipsRegLo(Opcode.rt) = HiReg;
+ Map_GPR_32bit(Section,Opcode.rd,0,-1);
+ } else {
+ Map_GPR_32bit(Section,Opcode.rd,0,-1);
+ MoveX86RegToX86Reg(MipsRegHi(Opcode.rt),MipsRegLo(Opcode.rd));
+ }
+ if ((uint8_t)Opcode.sa != 0) {
+ ShiftRightUnsignImmed(MipsRegLo(Opcode.rd),(uint8_t)Opcode.sa);
+ }
+ } else {
+ Compile_R4300i_UnknownOpcode(Section);
+ }
+ } else {
+ Map_GPR_32bit(Section,Opcode.rd,0,-1);
+ MoveVariableToX86reg(&GPR[Opcode.rt].UW[1],MipsRegLo(Opcode.rd));
+ if ((uint8_t)Opcode.sa != 0) {
+ ShiftRightUnsignImmed(MipsRegLo(Opcode.rd),(uint8_t)Opcode.sa);
+ }
+ }
+}
+
+void Compile_R4300i_SPECIAL_DSRA32 (BLOCK_SECTION * Section) {
+
+ if (IsConst(Opcode.rt)) {
+ if (Opcode.rt != Opcode.rd) { UnMap_GPR(Section,Opcode.rd, 0); }
+ MipsRegState(Opcode.rd) = STATE_CONST_32;
+ MipsRegLo(Opcode.rd) = (uint32_t)(MipsReg_S(Opcode.rt) >> (Opcode.sa + 32));
+ } else if (IsMapped(Opcode.rt)) {
+ ProtectGPR(Section,Opcode.rt);
+ if (Is64Bit(Opcode.rt)) {
+ if (Opcode.rt == Opcode.rd) {
+ int32_t HiReg = MipsRegHi(Opcode.rt);
+ MipsRegHi(Opcode.rt) = MipsRegLo(Opcode.rt);
+ MipsRegLo(Opcode.rt) = HiReg;
+ Map_GPR_32bit(Section,Opcode.rd,1,-1);
+ } else {
+ Map_GPR_32bit(Section,Opcode.rd,1,-1);
+ MoveX86RegToX86Reg(MipsRegHi(Opcode.rt),MipsRegLo(Opcode.rd));
+ }
+ if ((uint8_t)Opcode.sa != 0) {
+ ShiftRightSignImmed(MipsRegLo(Opcode.rd),(uint8_t)Opcode.sa);
+ }
+ } else {
+ Compile_R4300i_UnknownOpcode(Section);
+ }
+ } else {
+ Map_GPR_32bit(Section,Opcode.rd,1,-1);
+ MoveVariableToX86reg(&GPR[Opcode.rt].UW[1],MipsRegLo(Opcode.rd));
+ if ((uint8_t)Opcode.sa != 0) {
+ ShiftRightSignImmed(MipsRegLo(Opcode.rd),(uint8_t)Opcode.sa);
+ }
+ }
+}
+
+/************************** COP0 functions **************************/
+void Compile_R4300i_COP0_MF(BLOCK_SECTION * Section) {
+
+
+ switch (Opcode.rd) {
+ case 9: //Count
+ AddConstToVariable(BlockCycleCount,&CP0[9]);
+ SubConstFromVariable(BlockCycleCount,&Timers->Timer);
+ BlockCycleCount = 0;
+ }
+ Map_GPR_32bit(Section,Opcode.rt,1,-1);
+ MoveVariableToX86reg(&CP0[Opcode.rd],MipsRegLo(Opcode.rt));
+}
+
+void Compile_R4300i_COP0_MT (BLOCK_SECTION * Section) {
+ int32_t OldStatusReg;
+ uint8_t *Jump;
+
+
+
+ switch (Opcode.rd) {
+ case 0: //Index
+ case 2: //EntryLo0
+ case 3: //EntryLo1
+ case 4: //Context
+ case 5: //PageMask
+ case 9: //Count
+ case 10: //Entry Hi
+ case 11: //Compare
+ case 14: //EPC
+ case 16: //Config
+ case 18: //WatchLo
+ case 19: //WatchHi
+ case 28: //Tag lo
+ case 29: //Tag Hi
+ case 30: //ErrEPC
+ if (IsConst(Opcode.rt)) {
+ MoveConstToVariable(MipsRegLo(Opcode.rt), &CP0[Opcode.rd]);
+ } else if (IsMapped(Opcode.rt)) {
+ MoveX86regToVariable(MipsRegLo(Opcode.rt), &CP0[Opcode.rd]);
+ } else {
+ MoveX86regToVariable(Map_TempReg(Section,x86_Any,Opcode.rt,0), &CP0[Opcode.rd]);
+ }
+ switch (Opcode.rd) {
+ case 4: //Context
+ AndConstToVariable(0xFF800000,&CP0[Opcode.rd]);
+ break;
+ case 9: //Count
+ BlockCycleCount = 0;
+ Pushad();
+ Call_Direct(ChangeCompareTimer);
+ Popad();
+ break;
+ case 11: //Compare
+ AddConstToVariable(BlockCycleCount,&CP0[9]);
+ SubConstFromVariable(BlockCycleCount,&Timers->Timer);
+ BlockCycleCount = 0;
+ AndConstToVariable(~CAUSE_IP7,&FAKE_CAUSE_REGISTER);
+ Pushad();
+ Call_Direct(ChangeCompareTimer);
+ Popad();
+ }
+ break;
+ case 12: //Status
+ OldStatusReg = Map_TempReg(Section,x86_Any,-1,0);
+ MoveVariableToX86reg(&CP0[Opcode.rd],OldStatusReg);
+ if (IsConst(Opcode.rt)) {
+ MoveConstToVariable(MipsRegLo(Opcode.rt), &CP0[Opcode.rd]);
+ } else if (IsMapped(Opcode.rt)) {
+ MoveX86regToVariable(MipsRegLo(Opcode.rt), &CP0[Opcode.rd]);
+ } else {
+ MoveX86regToVariable(Map_TempReg(Section,x86_Any,Opcode.rt,0), &CP0[Opcode.rd]);
+ }
+ XorVariableToX86reg(&CP0[Opcode.rd],OldStatusReg);
+ TestConstToX86Reg(STATUS_FR,OldStatusReg);
+ JeLabel8(0);
+ Jump = RecompPos - 1;
+ Pushad();
+ Call_Direct(SetFpuLocations);
+ Popad();
+ *(uint8_t *)(Jump)= (uint8_t )(((uint8_t )(RecompPos)) - (((uint8_t )(Jump)) + 1));
+
+ //TestConstToX86Reg(STATUS_FR,OldStatusReg);
+ //CompileExit(Section->CompilePC+4,Section->RegWorking,ExitResetRecompCode,0,JneLabel32);
+ Pushad();
+ Call_Direct(CheckInterrupts);
+ Popad();
+ break;
+ case 6: //Wired
+ Pushad();
+ if (BlockRandomModifier != 0) { SubConstFromVariable(BlockRandomModifier,&CP0[1]); }
+ BlockRandomModifier = 0;
+ Call_Direct(FixRandomReg);
+ Popad();
+ if (IsConst(Opcode.rt)) {
+ MoveConstToVariable(MipsRegLo(Opcode.rt), &CP0[Opcode.rd]);
+ } else if (IsMapped(Opcode.rt)) {
+ MoveX86regToVariable(MipsRegLo(Opcode.rt), &CP0[Opcode.rd]);
+ } else {
+ MoveX86regToVariable(Map_TempReg(Section,x86_Any,Opcode.rt,0), &CP0[Opcode.rd]);
+ }
+ break;
+ case 13: //cause
+ if (IsConst(Opcode.rt)) {
+ AndConstToVariable(0xFFFFCFF,&CP0[Opcode.rd]);
+#ifndef EXTERNAL_RELEASE
+ if ((MipsRegLo(Opcode.rt) & 0x300) != 0 ){ DisplayError("Set IP0 or IP1"); }
+#endif
+ } else {
+ Compile_R4300i_UnknownOpcode(Section);
+ }
+ Pushad();
+ Call_Direct(CheckInterrupts);
+ Popad();
+ break;
+ default:
+ Compile_R4300i_UnknownOpcode(Section);
+ }
+}
+
+/************************** COP0 CO functions ***********************/
+void Compile_R4300i_COP0_CO_TLBR( BLOCK_SECTION * Section) {
+ Pushad();
+ Call_Direct(TLB_Read);
+ Popad();
+}
+
+void Compile_R4300i_COP0_CO_TLBWI( BLOCK_SECTION * Section) {
+ Pushad();
+ MoveVariableToX86reg(&INDEX_REGISTER,x86_EDI);
+ AndConstToX86Reg(x86_EDI,0x1F);
+#ifdef USEX64
+ Call_Direct(WriteTLBEntry);
+#else
+ Push(x86_ECX);
+ Call_Direct(WriteTLBEntry);
+ AddConstToX86Reg(x86_ESP, 0x4);
+#endif
+ Popad();
+}
+
+void Compile_R4300i_COP0_CO_TLBWR( BLOCK_SECTION * Section) {
+ if (BlockRandomModifier != 0) { SubConstFromVariable(BlockRandomModifier,&CP0[1]); }
+ BlockRandomModifier = 0;
+ Pushad();
+ //Call_Direct(FixRandomReg);
+ MoveVariableToX86reg(&RANDOM_REGISTER,x86_EDI);
+ AndConstToX86Reg(x86_EDI,0x1F);
+ //BreakPoint();
+ //Push(x86_ECX);
+#ifdef USEX64
+ Call_Direct(WriteTLBEntry);
+#else
+ Push(x86_ECX);
+ Call_Direct(WriteTLBEntry);
+ AddConstToX86Reg(x86_ESP, 0x4);
+#endif
+
+ //AddConstToX86Reg(x86_ESP,4);
+ Popad();
+}
+
+
+
+void Compile_R4300i_COP0_CO_TLBP( BLOCK_SECTION * Section) {
+ Pushad();
+ Call_Direct(TLB_Probe);
+ Popad();
+}
+
+void compiler_COP0_CO_ERET (void) {
+ if ((STATUS_REGISTER & STATUS_ERL) != 0) {
+ PROGRAM_COUNTER = ERROREPC_REGISTER;
+ STATUS_REGISTER &= ~STATUS_ERL;
+ } else {
+ PROGRAM_COUNTER = EPC_REGISTER;
+ STATUS_REGISTER &= ~STATUS_EXL;
+ }
+ LLBit = 0;
+ CheckInterrupts();
+}
+
+void Compile_R4300i_COP0_CO_ERET( BLOCK_SECTION * Section) {
+ WriteBackRegisters(Section);
+ Pushad();
+ Call_Direct(compiler_COP0_CO_ERET);
+ Popad();
+ CompileExit((uint32_t)-1,&Section->RegWorking,Normal,1,NULL);
+ NextInstruction = END_BLOCK;
+}
+
+/************************** Other functions **************************/
+void Compile_R4300i_UnknownOpcode (BLOCK_SECTION * Section) {
+
+// Int3();
+ FreeSection(Section->ContinueSection,Section);
+ FreeSection(Section->JumpSection,Section);
+ BlockCycleCount -= 2;
+ BlockRandomModifier -= 1;
+ MoveConstToVariable(Section->CompilePC,&PROGRAM_COUNTER);
+ WriteBackRegisters(Section);
+ AddConstToVariable(BlockCycleCount,&CP0[9]);
+ SubConstFromVariable(BlockRandomModifier,&CP0[1]);
+ MoveConstToVariable(Opcode.Hex,&Opcode.Hex);
+ Pushad();
+ Call_Direct(R4300i_UnknownOpcode);
+ Popad();
+ Ret();
+ if (NextInstruction == NORMAL) { NextInstruction = END_BLOCK; }
+}
+
diff --git a/src/usf/recompiler_ops.h b/src/usf/recompiler_ops.h new file mode 100644 index 0000000..b1e5809 --- /dev/null +++ b/src/usf/recompiler_ops.h @@ -0,0 +1,196 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+void CompileReadTLBMiss (BLOCK_SECTION * Section, int32_t AddressReg, int32_t LookUpReg );
+
+/************************** Branch functions ************************/
+void Compile_R4300i_Branch ( BLOCK_SECTION * Section, void (*CompareFunc)(BLOCK_SECTION * Section), int32_t BranchType, uint32_t Link);
+void Compile_R4300i_BranchLikely ( BLOCK_SECTION * Section, void (*CompareFunc)(BLOCK_SECTION * Section), uint32_t Link);
+void BNE_Compare ( BLOCK_SECTION * Section );
+void BEQ_Compare ( BLOCK_SECTION * Section );
+void BGTZ_Compare ( BLOCK_SECTION * Section );
+void BLEZ_Compare ( BLOCK_SECTION * Section );
+void BLTZ_Compare ( BLOCK_SECTION * Section );
+void BGEZ_Compare ( BLOCK_SECTION * Section );
+void COP1_BCF_Compare ( BLOCK_SECTION * Section );
+void COP1_BCT_Compare ( BLOCK_SECTION * Section );
+
+/************************* OpCode functions *************************/
+void Compile_R4300i_J ( BLOCK_SECTION * Section );
+void Compile_R4300i_JAL ( BLOCK_SECTION * Section );
+void Compile_R4300i_ADDI ( BLOCK_SECTION * Section );
+void Compile_R4300i_ADDIU ( BLOCK_SECTION * Section );
+void Compile_R4300i_SLTI ( BLOCK_SECTION * Section );
+void Compile_R4300i_SLTIU ( BLOCK_SECTION * Section );
+void Compile_R4300i_ANDI ( BLOCK_SECTION * Section );
+void Compile_R4300i_ORI ( BLOCK_SECTION * Section );
+void Compile_R4300i_XORI ( BLOCK_SECTION * Section );
+void Compile_R4300i_LUI ( BLOCK_SECTION * Section );
+void Compile_R4300i_DADDIU ( BLOCK_SECTION * Section );
+void Compile_R4300i_LDL ( BLOCK_SECTION * Section );
+void Compile_R4300i_LDR ( BLOCK_SECTION * Section );
+void Compile_R4300i_LB ( BLOCK_SECTION * Section );
+void Compile_R4300i_LH ( BLOCK_SECTION * Section );
+void Compile_R4300i_LWL ( BLOCK_SECTION * Section );
+void Compile_R4300i_LW ( BLOCK_SECTION * Section );
+void Compile_R4300i_LBU ( BLOCK_SECTION * Section );
+void Compile_R4300i_LHU ( BLOCK_SECTION * Section );
+void Compile_R4300i_LWR ( BLOCK_SECTION * Section );
+void Compile_R4300i_LWU ( BLOCK_SECTION * Section ); //added by Witten
+void Compile_R4300i_SB ( BLOCK_SECTION * Section );
+void Compile_R4300i_SH ( BLOCK_SECTION * Section );
+void Compile_R4300i_SWL ( BLOCK_SECTION * Section );
+void Compile_R4300i_SW ( BLOCK_SECTION * Section );
+void Compile_R4300i_SWR ( BLOCK_SECTION * Section );
+void Compile_R4300i_SDL ( BLOCK_SECTION * Section );
+void Compile_R4300i_SDR ( BLOCK_SECTION * Section );
+void Compile_R4300i_CACHE ( BLOCK_SECTION * Section );
+void Compile_R4300i_LL ( BLOCK_SECTION * Section );
+void Compile_R4300i_LWC1 ( BLOCK_SECTION * Section );
+void Compile_R4300i_LDC1 ( BLOCK_SECTION * Section );
+void Compile_R4300i_LD ( BLOCK_SECTION * Section );
+void Compile_R4300i_SC ( BLOCK_SECTION * Section );
+void Compile_R4300i_SWC1 ( BLOCK_SECTION * Section );
+void Compile_R4300i_SDC1 ( BLOCK_SECTION * Section );
+void Compile_R4300i_SD ( BLOCK_SECTION * Section );
+
+/********************** R4300i OpCodes: Special **********************/
+void Compile_R4300i_SPECIAL_SLL ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_SRL ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_SRA ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_SLLV ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_SRLV ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_SRAV ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_JR ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_JALR ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_SYSCALL( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_MFLO ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_MTLO ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_MFHI ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_MTHI ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_DSLLV ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_DSRLV ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_DSRAV ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_MULT ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_MULTU ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_DIV ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_DIVU ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_DMULT ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_DMULTU ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_DDIV ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_DDIVU ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_ADD ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_ADDU ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_SUB ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_SUBU ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_AND ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_OR ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_XOR ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_NOR ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_SLT ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_SLTU ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_DADD ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_DADDU ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_DSUB ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_DSUBU ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_DSLL ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_DSRL ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_DSRA ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_DSLL32 ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_DSRL32 ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_DSRA32 ( BLOCK_SECTION * Section );
+void Compile_R4300i_SPECIAL_BREAK ( BLOCK_SECTION * Section );
+
+/************************** COP0 functions **************************/
+void Compile_R4300i_COP0_MF ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP0_MT ( BLOCK_SECTION * Section );
+
+/************************** COP0 CO functions ***********************/
+void Compile_R4300i_COP0_CO_TLBR ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP0_CO_TLBWI ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP0_CO_TLBWR ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP0_CO_TLBP ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP0_CO_ERET ( BLOCK_SECTION * Section );
+
+/************************** COP1 functions **************************/
+void Compile_R4300i_COP1_MF ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_DMF ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_CF ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_MT ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_DMT ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_CT ( BLOCK_SECTION * Section );
+
+/************************** COP1: S functions ************************/
+void Compile_R4300i_COP1_S_ADD ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_S_SUB ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_S_MUL ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_S_DIV ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_S_ABS ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_S_NEG ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_S_SQRT ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_S_MOV ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_S_TRUNC_L ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_S_CEIL_L ( BLOCK_SECTION * Section ); //added by Witten
+void Compile_R4300i_COP1_S_FLOOR_L ( BLOCK_SECTION * Section ); //added by Witten
+void Compile_R4300i_COP1_S_ROUND_W ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_S_TRUNC_W ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_S_CEIL_W ( BLOCK_SECTION * Section ); //added by Witten
+void Compile_R4300i_COP1_S_FLOOR_W ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_S_CVT_D ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_S_CVT_W ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_S_CVT_L ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_S_CMP ( BLOCK_SECTION * Section );
+
+/************************** COP1: D functions ************************/
+void Compile_R4300i_COP1_D_ADD ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_D_SUB ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_D_MUL ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_D_DIV ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_D_ABS ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_D_NEG ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_D_SQRT ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_D_MOV ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_D_TRUNC_L ( BLOCK_SECTION * Section ); //added by Witten
+void Compile_R4300i_COP1_D_CEIL_L ( BLOCK_SECTION * Section ); //added by Witten
+void Compile_R4300i_COP1_D_FLOOR_L ( BLOCK_SECTION * Section ); //added by Witten
+void Compile_R4300i_COP1_D_ROUND_W ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_D_TRUNC_W ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_D_CEIL_W ( BLOCK_SECTION * Section ); //added by Witten
+void Compile_R4300i_COP1_D_FLOOR_W ( BLOCK_SECTION * Section ); //added by Witten
+void Compile_R4300i_COP1_D_CVT_S ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_D_CVT_W ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_D_CVT_L ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_D_CMP ( BLOCK_SECTION * Section );
+
+/************************** COP1: W functions ************************/
+void Compile_R4300i_COP1_W_CVT_S ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_W_CVT_D ( BLOCK_SECTION * Section );
+
+/************************** COP1: L functions ************************/
+void Compile_R4300i_COP1_L_CVT_S ( BLOCK_SECTION * Section );
+void Compile_R4300i_COP1_L_CVT_D ( BLOCK_SECTION * Section );
+
+/************************** Other functions **************************/
+void Compile_R4300i_UnknownOpcode ( BLOCK_SECTION * Section );
diff --git a/src/usf/registers.c b/src/usf/registers.c new file mode 100644 index 0000000..8971d1a --- /dev/null +++ b/src/usf/registers.c @@ -0,0 +1,1054 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+
+// #ifdef EXT_REGS
+
+#include "main.h"
+#include "cpu.h"
+#include "x86.h"
+#include "types.h"
+
+uint32_t PROGRAM_COUNTER, * CP0,*FPCR,*RegRDRAM,*RegSP,*RegDPC,*RegMI,*RegVI,*RegAI,*RegPI,
+ *RegRI,*RegSI, HalfLine, RegModValue, ViFieldNumber, LLBit, LLAddr;
+void * FPRDoubleLocation[32], * FPRFloatLocation[32];
+MIPS_DWORD *GPR, *FPR, HI, LO;
+int32_t fpuControl;
+N64_REGISTERS * Registers = 0;
+
+void SetupRegisters(N64_REGISTERS * n64_Registers) {
+ PROGRAM_COUNTER = n64_Registers->PROGRAM_COUNTER;
+ HI.DW = n64_Registers->HI.DW;
+ LO.DW = n64_Registers->LO.DW;
+ CP0 = n64_Registers->CP0;
+ GPR = n64_Registers->GPR;
+ FPR = n64_Registers->FPR;
+ FPCR = n64_Registers->FPCR;
+ RegRDRAM = n64_Registers->RDRAM;
+ RegSP = n64_Registers->SP;
+ RegDPC = n64_Registers->DPC;
+ RegMI = n64_Registers->MI;
+ RegVI = n64_Registers->VI;
+ RegAI = n64_Registers->AI;
+ RegPI = n64_Registers->PI;
+ RegRI = n64_Registers->RI;
+ RegSI = n64_Registers->SI;
+ PIF_Ram = n64_Registers->PIF_Ram;
+}
+
+int fUnMap_8BitTempReg (BLOCK_SECTION * Section);
+int UnMap_TempReg (BLOCK_SECTION * Section);
+uint32_t UnMap_X86reg (BLOCK_SECTION * Section, uint32_t x86Reg);
+
+void ChangeFPURegFormat (BLOCK_SECTION * Section, int32_t Reg, int32_t OldFormat, int32_t NewFormat, int32_t RoundingModel) {
+ int32_t i;
+
+ for (i = 0; i < 8; i++) {
+ if (FpuMappedTo(i) == (uint32_t)Reg) {
+ if (FpuState(i) != (uint32_t)OldFormat) {
+ UnMap_FPR(Section,Reg,1);
+ Load_FPR_ToTop(Section,Reg,Reg,OldFormat);
+ ChangeFPURegFormat(Section,Reg,OldFormat,NewFormat,RoundingModel);
+ return;
+ }
+ FpuRoundingModel(i) = RoundingModel;
+ FpuState(i) = NewFormat;
+ return;
+ }
+ }
+
+}
+
+void ChangeMiIntrMask (void) {
+ if ( ( RegModValue & MI_INTR_MASK_CLR_SP ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_SP; }
+ if ( ( RegModValue & MI_INTR_MASK_SET_SP ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_SP; }
+ if ( ( RegModValue & MI_INTR_MASK_CLR_SI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_SI; }
+ if ( ( RegModValue & MI_INTR_MASK_SET_SI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_SI; }
+ if ( ( RegModValue & MI_INTR_MASK_CLR_AI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_AI; }
+ if ( ( RegModValue & MI_INTR_MASK_SET_AI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_AI; }
+ if ( ( RegModValue & MI_INTR_MASK_CLR_VI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_VI; }
+ if ( ( RegModValue & MI_INTR_MASK_SET_VI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_VI; }
+ if ( ( RegModValue & MI_INTR_MASK_CLR_PI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_PI; }
+ if ( ( RegModValue & MI_INTR_MASK_SET_PI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_PI; }
+ if ( ( RegModValue & MI_INTR_MASK_CLR_DP ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_DP; }
+ if ( ( RegModValue & MI_INTR_MASK_SET_DP ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_DP; }
+}
+
+void ChangeMiModeReg (void) {
+ MI_MODE_REG &= ~0x7F;
+ MI_MODE_REG |= (RegModValue & 0x7F);
+ if ( ( RegModValue & MI_CLR_INIT ) != 0 ) { MI_MODE_REG &= ~MI_MODE_INIT; }
+ if ( ( RegModValue & MI_SET_INIT ) != 0 ) { MI_MODE_REG |= MI_MODE_INIT; }
+ if ( ( RegModValue & MI_CLR_EBUS ) != 0 ) { MI_MODE_REG &= ~MI_MODE_EBUS; }
+ if ( ( RegModValue & MI_SET_EBUS ) != 0 ) { MI_MODE_REG |= MI_MODE_EBUS; }
+ if ( ( RegModValue & MI_CLR_DP_INTR ) != 0 ) { MI_INTR_REG &= ~MI_INTR_DP; }
+ if ( ( RegModValue & MI_CLR_RDRAM ) != 0 ) { MI_MODE_REG &= ~MI_MODE_RDRAM; }
+ if ( ( RegModValue & MI_SET_RDRAM ) != 0 ) { MI_MODE_REG |= MI_MODE_RDRAM; }
+}
+
+void ChangeSpStatus (void) {
+ if ( ( RegModValue & SP_CLR_HALT ) != 0) { SP_STATUS_REG &= ~SP_STATUS_HALT; }
+ if ( ( RegModValue & SP_SET_HALT ) != 0) { SP_STATUS_REG |= SP_STATUS_HALT; }
+ if ( ( RegModValue & SP_CLR_BROKE ) != 0) { SP_STATUS_REG &= ~SP_STATUS_BROKE; }
+ if ( ( RegModValue & SP_CLR_INTR ) != 0) {
+ MI_INTR_REG &= ~MI_INTR_SP;
+ CheckInterrupts();
+ }
+
+ if ( ( RegModValue & SP_CLR_SSTEP ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SSTEP; }
+ if ( ( RegModValue & SP_SET_SSTEP ) != 0) { SP_STATUS_REG |= SP_STATUS_SSTEP; }
+ if ( ( RegModValue & SP_CLR_INTR_BREAK ) != 0) { SP_STATUS_REG &= ~SP_STATUS_INTR_BREAK; }
+ if ( ( RegModValue & SP_SET_INTR_BREAK ) != 0) { SP_STATUS_REG |= SP_STATUS_INTR_BREAK; }
+ if ( ( RegModValue & SP_CLR_SIG0 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG0; }
+ if ( ( RegModValue & SP_SET_SIG0 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG0; }
+ if ( ( RegModValue & SP_CLR_SIG1 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG1; }
+ if ( ( RegModValue & SP_SET_SIG1 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG1; }
+ if ( ( RegModValue & SP_CLR_SIG2 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG2; }
+ if ( ( RegModValue & SP_SET_SIG2 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG2; }
+ if ( ( RegModValue & SP_CLR_SIG3 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG3; }
+ if ( ( RegModValue & SP_SET_SIG3 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG3; }
+ if ( ( RegModValue & SP_CLR_SIG4 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG4; }
+ if ( ( RegModValue & SP_SET_SIG4 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG4; }
+ if ( ( RegModValue & SP_CLR_SIG5 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG5; }
+ if ( ( RegModValue & SP_SET_SIG5 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG5; }
+ if ( ( RegModValue & SP_CLR_SIG6 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG6; }
+ if ( ( RegModValue & SP_SET_SIG6 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG6; }
+ if ( ( RegModValue & SP_CLR_SIG7 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG7; }
+ if ( ( RegModValue & SP_SET_SIG7 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG7; }
+
+ RunRsp();
+
+}
+
+int32_t Free8BitX86Reg (BLOCK_SECTION * Section) {
+ int32_t x86Reg, count, MapCount[64], MapReg[64];
+
+ //if (x86Mapped(x86_EBX) == NotMapped && !x86Protected(x86_EBX)) {return x86_EBX; }
+ //if (x86Mapped(x86_EAX) == NotMapped && !x86Protected(x86_EAX)) {return x86_EAX; }
+ //if (x86Mapped(x86_EDX) == NotMapped && !x86Protected(x86_EDX)) {return x86_EDX; }
+ //if (x86Mapped(x86_ECX) == NotMapped && !x86Protected(x86_ECX)) {return x86_ECX; }
+ if (x86Mapped(x86_EBX&0x2f) == NotMapped && !x86Protected(x86_EBX&0x2f)) {return x86_EBX; }
+ if (x86Mapped(x86_EDX&0x2f) == NotMapped && !x86Protected(x86_EDX&0x2f)) {return x86_EDX; }
+ if (x86Mapped(x86_ECX&0x2f) == NotMapped && !x86Protected(x86_ECX&0x2f)) {return x86_ECX; }
+ if (x86Mapped(x86_EAX&0x2f) == NotMapped && !x86Protected(x86_EAX&0x2f)) {return x86_EAX; }
+#ifdef EXT_REGS
+ if (x86Mapped(x86_R9D&0x2f) == NotMapped && !x86Protected(x86_R9D&0x2f)) {return x86_R9D; }
+ if (x86Mapped(x86_R10D&0x2f) == NotMapped && !x86Protected(x86_R10D&0x2f)) {return x86_R10D; }
+ if (x86Mapped(x86_R11D&0x2f) == NotMapped && !x86Protected(x86_R11D&0x2f)) {return x86_R11D; }
+ if (x86Mapped(x86_R14D&0x2f) == NotMapped && !x86Protected(x86_R14D&0x2f)) {return x86_R14D; }
+#endif
+
+ x86Reg = UnMap_8BitTempReg(Section);
+ if (x86Reg >= 0) { return x86Reg; }
+
+ for (count = 0; count < 64; count ++) {
+ MapCount[count] = x86MapOrder(count);
+ MapReg[count] = count;
+ }
+ for (count = 0; count < 64; count ++) {
+ int i;
+
+ for (i = 0; i < 63; i ++) {
+ int temp;
+
+ if (MapCount[i] < MapCount[i+1]) {
+ temp = MapCount[i];
+ MapCount[i] = MapCount[i+1];
+ MapCount[i+1] = temp;
+ temp = MapReg[i];
+ MapReg[i] = MapReg[i+1];
+ MapReg[i+1] = temp;
+ }
+ }
+
+ }
+ for (count = 0; count < 64; count ++) {
+ if (MapCount[count] > 0) {
+ if (!Is8BitReg(count)) { continue; }
+ if (UnMap_X86reg(Section,count)) {
+ return count;
+ }
+ }
+ }
+
+ return -1;
+}
+
+
+int32_t FreeX86Reg (BLOCK_SECTION * Section) {
+ int32_t x86Reg, count, MapCount[64], MapReg[64], StackReg;
+
+ if (x86Mapped(x86_ESI&0x2f) == NotMapped && !x86Protected(x86_ESI&0x2f)) {return x86_ESI; }
+ if (x86Mapped(x86_EDI&0x2f) == NotMapped && !x86Protected(x86_EDI&0x2f)) {return x86_EDI; }
+ if (x86Mapped(x86_EBX&0x2f) == NotMapped && !x86Protected(x86_EBX&0x2f)) {return x86_EBX; }
+ if (x86Mapped(x86_EDX&0x2f) == NotMapped && !x86Protected(x86_EDX&0x2f)) {return x86_EDX; }
+ if (x86Mapped(x86_ECX&0x2f) == NotMapped && !x86Protected(x86_ECX&0x2f)) {return x86_ECX; }
+ if (x86Mapped(x86_EAX&0x2f) == NotMapped && !x86Protected(x86_EAX&0x2f)) {return x86_EAX; }
+#ifdef EXT_REGS
+ if (x86Mapped(x86_R9D&0x2f) == NotMapped && !x86Protected(x86_R9D&0x2f)) {return x86_R9D; }
+ if (x86Mapped(x86_R10D&0x2f) == NotMapped && !x86Protected(x86_R10D&0x2f)) {return x86_R10D; }
+ if (x86Mapped(x86_R11D&0x2f) == NotMapped && !x86Protected(x86_R11D&0x2f)) {return x86_R11D; }
+ if (x86Mapped(x86_R12D&0x2f) == NotMapped && !x86Protected(x86_R12D&0x2f)) {return x86_R12D; }
+ if (x86Mapped(x86_R13D&0x2f) == NotMapped && !x86Protected(x86_R13D&0x2f)) {return x86_R13D; }
+ if (x86Mapped(x86_R14D&0x2f) == NotMapped && !x86Protected(x86_R14D&0x2f)) {return x86_R14D; }
+#endif
+
+ x86Reg = UnMap_TempReg(Section);
+ if (x86Reg > 0) { return x86Reg; }
+
+ for (count = 0; count < 64; count ++) {
+ MapCount[count] = x86MapOrder(count);
+ MapReg[count] = count;
+ }
+ for (count = 0; count < 64; count ++) {
+ int i;
+
+ for (i = 0; i < 63; i ++) {
+ int temp;
+
+ if (MapCount[i] < MapCount[i+1]) {
+ temp = MapCount[i];
+ MapCount[i] = MapCount[i+1];
+ MapCount[i+1] = temp;
+ temp = MapReg[i];
+ MapReg[i] = MapReg[i+1];
+ MapReg[i+1] = temp;
+ }
+ }
+
+ }
+ StackReg = -1;
+ for (count = 0; count < 64; count ++) {
+ if (MapCount[count] > 0 && x86Mapped(MapReg[count]) != Stack_Mapped) {
+ if (UnMap_X86reg(Section,MapReg[count])) {
+ return MapReg[count];
+ }
+ }
+ if (x86Mapped(MapReg[count]) == Stack_Mapped) { StackReg = MapReg[count]; }
+ }
+ if (StackReg >= 0) {
+ UnMap_X86reg(Section,StackReg);
+ return StackReg;
+ }
+ return -1;
+}
+
+
+uint32_t Is8BitReg (int32_t x86Reg) {
+ if (x86Reg == x86_EAX) { return 1; }
+ if (x86Reg == x86_EBX) { return 1; }
+ if (x86Reg == x86_ECX) { return 1; }
+ if (x86Reg == x86_EDX) { return 1; }
+#ifdef EXT_REGS
+ if (x86Reg == x86_R9D) { return 1; }
+ if (x86Reg == x86_R10D) { return 1; }
+ if (x86Reg == x86_R11D) { return 1; }
+ if (x86Reg == x86_R14D) { return 1; }
+#endif
+ return 0;
+}
+
+void Load_FPR_ToTop (BLOCK_SECTION * Section, int32_t Reg, int32_t RegToLoad, int32_t Format) {
+ int32_t i;
+
+ if (RegToLoad < 0) { return; }
+ if (Reg < 0) { return; }
+
+ if (Format == FPU_Double || Format == FPU_Qword) {
+ UnMap_FPR(Section,Reg + 1,1);
+ UnMap_FPR(Section,RegToLoad + 1,1);
+ } else {
+ if ((Reg & 1) != 0) {
+ for (i = 0; i < 8; i++) {
+ if (FpuMappedTo(i) == (uint32_t)(Reg - 1)) {
+ if (FpuState(i) == FPU_Double || FpuState(i) == FPU_Qword) {
+ UnMap_FPR(Section,Reg,1);
+ }
+ i = 8;
+ }
+ }
+ }
+ if ((RegToLoad & 1) != 0) {
+ for (i = 0; i < 8; i++) {
+ if (FpuMappedTo(i) == (uint32_t)(RegToLoad - 1)) {
+ if (FpuState(i) == FPU_Double || FpuState(i) == FPU_Qword) {
+ UnMap_FPR(Section,RegToLoad,1);
+ }
+ i = 8;
+ }
+ }
+ }
+ }
+
+ if (Reg == RegToLoad) {
+ //if different format then unmap original reg from stack
+ for (i = 0; i < 8; i++) {
+ if (FpuMappedTo(i) == (uint32_t)Reg) {
+ if (FpuState(i) != (uint32_t)Format) {
+ UnMap_FPR(Section,Reg,1);
+ }
+ i = 8;
+ }
+ }
+ } else {
+ UnMap_FPR(Section,Reg,0);
+ }
+
+ if (RegInStack(Section,RegToLoad,Format)) {
+ if (Reg != RegToLoad) {
+ if (FpuMappedTo((StackTopPos - 1) & 7) != (uint32_t)RegToLoad) {
+ UnMap_FPR(Section,FpuMappedTo((StackTopPos - 1) & 7),1);
+ fpuLoadReg(&StackTopPos,StackPosition(Section,RegToLoad));
+ FpuRoundingModel(StackTopPos) = RoundDefault;
+ FpuMappedTo(StackTopPos) = Reg;
+ FpuState(StackTopPos) = Format;
+ } else {
+ UnMap_FPR(Section,FpuMappedTo((StackTopPos - 1) & 7),1);
+ Load_FPR_ToTop (Section,Reg, RegToLoad, Format);
+ }
+ } else {
+ uint32_t RegPos, StackPos, i;
+
+ for (i = 0; i < 8; i++) {
+ if (FpuMappedTo(i) == (uint32_t)Reg) {
+ RegPos = i;
+ i = 8;
+ }
+ }
+
+ if (RegPos == StackTopPos) {
+ return;
+ }
+ StackPos = StackPosition(Section,Reg);
+
+ FpuRoundingModel(RegPos) = FpuRoundingModel(StackTopPos);
+ FpuMappedTo(RegPos) = FpuMappedTo(StackTopPos);
+ FpuState(RegPos) = FpuState(StackTopPos);
+
+ fpuExchange(StackPos);
+
+ FpuRoundingModel(StackTopPos) = RoundDefault;
+ FpuMappedTo(StackTopPos) = Reg;
+ FpuState(StackTopPos) = Format;
+ }
+ } else {
+ int TempReg;
+
+ UnMap_FPR(Section,FpuMappedTo((StackTopPos - 1) & 7),1);
+ for (i = 0; i < 8; i++) {
+ if (FpuMappedTo(i) == (uint32_t)RegToLoad) {
+ UnMap_FPR(Section,RegToLoad,1);
+ i = 8;
+ }
+ }
+ TempReg = Map_TempReg(Section,x86_Any,-1,0);
+ switch (Format) {
+ case FPU_Dword:
+ MovePointerToX86reg(&FPRFloatLocation[RegToLoad],TempReg);
+ MovePointerToX86reg(&FPRFloatLocation[RegToLoad],TempReg);
+
+ fpuLoadIntegerDwordFromX86Reg(&StackTopPos,TempReg);
+ break;
+ case FPU_Qword:
+ MovePointerToX86reg(&FPRDoubleLocation[RegToLoad],TempReg);
+ fpuLoadIntegerQwordFromX86Reg(&StackTopPos,TempReg);
+ break;
+ case FPU_Float:
+ MovePointerToX86reg(&FPRFloatLocation[RegToLoad],TempReg);
+ fpuLoadDwordFromX86Reg(&StackTopPos,TempReg);
+ break;
+ case FPU_Double:
+ MovePointerToX86reg(&FPRDoubleLocation[RegToLoad],TempReg);
+ fpuLoadQwordFromX86Reg(&StackTopPos,TempReg);
+ break;
+ }
+ x86Protected(TempReg) = 0;
+ FpuRoundingModel(StackTopPos) = RoundDefault;
+ FpuMappedTo(StackTopPos) = Reg;
+ FpuState(StackTopPos) = Format;
+ }
+
+ //CurrentRoundingModel,FpuRoundingModel(StackTopPos));
+}
+
+void Map_GPR_32bit (BLOCK_SECTION * Section, int32_t Reg, uint32_t SignValue, int32_t MipsRegToLoad) {
+ int x86Reg,count;
+
+ if (Reg == 0) {
+ return;
+ }
+
+ if (IsUnknown(Reg) || IsConst(Reg)) {
+ x86Reg = FreeX86Reg(Section);
+ if (x86Reg < 0) {
+ printf("out of registers\n");
+ return;
+ }
+ } else {
+ if (Is64Bit(Reg)) {
+ x86MapOrder(MipsRegHi(Reg)) = 0;
+ x86Mapped(MipsRegHi(Reg)) = NotMapped;
+ x86Protected(MipsRegHi(Reg)) = 0;
+ MipsRegHi(Reg) = 0;
+ }
+ x86Reg = MipsRegLo(Reg);
+ }
+ for (count = 0; count < 64; count ++) {
+ if (x86MapOrder(count) > 0) {
+ x86MapOrder(count) += 1;
+ }
+ }
+ x86MapOrder(x86Reg) = 1;
+
+ if (MipsRegToLoad > 0) {
+ if (IsUnknown(MipsRegToLoad)) {
+ MoveVariableToX86reg(&GPR[MipsRegToLoad].UW[0],x86Reg);
+ } else if (IsMapped(MipsRegToLoad)) {
+ if (Reg != MipsRegToLoad) {
+ MoveX86RegToX86Reg(MipsRegLo(MipsRegToLoad),x86Reg);
+ }
+ } else {
+ if (MipsRegLo(MipsRegToLoad) != 0) {
+ MoveConstToX86reg(MipsRegLo(MipsRegToLoad),x86Reg);
+ } else {
+ XorX86RegToX86Reg(x86Reg,x86Reg);
+ }
+ }
+ } else if (MipsRegToLoad == 0) {
+ XorX86RegToX86Reg(x86Reg,x86Reg);
+ }
+ x86Mapped(x86Reg) = GPR_Mapped;
+ x86Protected(x86Reg) = 1;
+ MipsRegLo(Reg) = x86Reg;
+ MipsRegState(Reg) = SignValue ? STATE_MAPPED_32_SIGN : STATE_MAPPED_32_ZERO;
+}
+
+void Map_GPR_64bit (BLOCK_SECTION * Section, int32_t Reg, int32_t MipsRegToLoad) {
+ int x86Hi, x86lo, count;
+
+ if (Reg == 0) {
+
+ return;
+ }
+
+ ProtectGPR(Section,Reg);
+ if (IsUnknown(Reg) || IsConst(Reg)) {
+ x86Hi = FreeX86Reg(Section);
+ if (x86Hi < 0) { printf("out of registers\n"); return; }
+ x86Protected(x86Hi) = 1;
+
+ x86lo = FreeX86Reg(Section);
+ if (x86lo < 0) { printf("out of registers\n"); return; }
+ x86Protected(x86lo) = 1;
+
+ } else {
+ x86lo = MipsRegLo(Reg);
+ if (Is32Bit(Reg)) {
+ x86Protected(x86lo) = 1;
+ x86Hi = FreeX86Reg(Section);
+ if (x86Hi < 0) { printf("out of registers\n"); return; }
+ x86Protected(x86Hi) = 1;
+ } else {
+ x86Hi = MipsRegHi(Reg);
+ }
+ }
+
+ for (count = 0; count < 64; count ++) {
+ if (x86MapOrder(count) > 0) { x86MapOrder(count) += 1; }
+ }
+
+ x86MapOrder(x86Hi) = 1;
+ x86MapOrder(x86lo) = 1;
+ if (MipsRegToLoad > 0) {
+ if (IsUnknown(MipsRegToLoad)) {
+ MoveVariableToX86reg(&GPR[MipsRegToLoad].UW[1],x86Hi);
+ MoveVariableToX86reg(&GPR[MipsRegToLoad].UW[0],x86lo);
+ } else if (IsMapped(MipsRegToLoad)) {
+ if (Is32Bit(MipsRegToLoad)) {
+ if (IsSigned(MipsRegToLoad)) {
+
+ MoveX86RegToX86Reg(MipsRegLo(MipsRegToLoad),x86Hi);
+ ShiftRightSignImmed(x86Hi,31);
+ } else {
+ XorX86RegToX86Reg(x86Hi,x86Hi);
+ }
+ if (Reg != MipsRegToLoad) {
+ MoveX86RegToX86Reg(MipsRegLo(MipsRegToLoad),x86lo);
+ }
+ } else {
+ if (Reg != MipsRegToLoad) {
+ MoveX86RegToX86Reg(MipsRegHi(MipsRegToLoad),x86Hi);
+ MoveX86RegToX86Reg(MipsRegLo(MipsRegToLoad),x86lo);
+ }
+ }
+ } else {
+ if (Is32Bit(MipsRegToLoad)) {
+ if (IsSigned(MipsRegToLoad)) {
+ if (MipsRegLo((int)MipsRegLo(MipsRegToLoad) >> 31) != 0) {
+ MoveConstToX86reg((int)MipsRegLo(MipsRegToLoad) >> 31,x86Hi);
+ } else {
+ XorX86RegToX86Reg(x86Hi,x86Hi);
+ }
+ } else {
+ XorX86RegToX86Reg(x86Hi,x86Hi);
+ }
+ } else {
+ if (MipsRegHi(MipsRegToLoad) != 0) {
+ MoveConstToX86reg(MipsRegHi(MipsRegToLoad),x86Hi);
+ } else {
+ XorX86RegToX86Reg(x86Hi,x86Hi);
+ }
+ }
+ if (MipsRegLo(MipsRegToLoad) != 0) {
+ MoveConstToX86reg(MipsRegLo(MipsRegToLoad),x86lo);
+ } else {
+ XorX86RegToX86Reg(x86lo,x86lo);
+ }
+ }
+ } else if (MipsRegToLoad == 0) {
+ XorX86RegToX86Reg(x86Hi,x86Hi);
+ XorX86RegToX86Reg(x86lo,x86lo);
+ }
+ x86Mapped(x86Hi) = GPR_Mapped;
+ x86Mapped(x86lo) = GPR_Mapped;
+ MipsRegHi(Reg) = x86Hi;
+ MipsRegLo(Reg) = x86lo;
+ MipsRegState(Reg) = STATE_MAPPED_64;
+}
+
+int32_t Map_TempReg (BLOCK_SECTION * Section, int32_t x86Reg, int32_t MipsReg, uint32_t LoadHiWord) {
+ int32_t count, x64reg = 0;
+
+ //if((x86Reg & x64_Reg) || (x86Reg & x64_Any))
+ //Int3();
+ x64reg = (x86Reg & x64_Reg) || (x86Reg & x64_Any);
+ x86Reg &= ~x64_Reg;
+
+ if ((x86Reg == x86_Any) || (x86Reg == x64_Any)) {
+ for (count = 0; count < 64; count ++ ) {
+ if (x86Mapped(count) == Temp_Mapped) {
+ if (x86Protected(count) == 0) { x86Reg = count; }
+ }
+ }
+
+ if ((x86Reg == x86_Any) || (x86Reg == x64_Any)) {
+ x86Reg = FreeX86Reg(Section);
+ if (x86Reg < 0) {
+ x86Reg = FreeX86Reg(Section);
+ return -1;
+ }
+ }
+ } else if (x86Reg == x86_Any8Bit) {
+ if (x86Mapped(x86_EBX&0x2f) == Temp_Mapped && !x86Protected(x86_EBX&0x2f)) { x86Reg = x86_EBX; }
+ if (x86Mapped(x86_EAX&0x2f) == Temp_Mapped && !x86Protected(x86_EAX&0x2f)) { x86Reg = x86_EAX; }
+ if (x86Mapped(x86_EDX&0x2f) == Temp_Mapped && !x86Protected(x86_EDX&0x2f)) { x86Reg = x86_EDX; }
+ if (x86Mapped(x86_ECX&0x2f) == Temp_Mapped && !x86Protected(x86_ECX&0x2f)) { x86Reg = x86_ECX; }
+
+#ifdef EXT_REGS
+ if (x86Mapped(x86_R9D&0x2f) == Temp_Mapped && !x86Protected(x86_R9D&0x2f)) { x86Reg = x86_R9D; }
+ if (x86Mapped(x86_R10D&0x2f) == Temp_Mapped && !x86Protected(x86_R10D&0x2f)) { x86Reg = x86_R10D; }
+ if (x86Mapped(x86_R11D&0x2f) == Temp_Mapped && !x86Protected(x86_R11D&0x2f)) { x86Reg = x86_R11D; }
+ if (x86Mapped(x86_R14D&0x2f) == Temp_Mapped && !x86Protected(x86_R14D&0x2f)) { x86Reg = x86_R14D; }
+#endif
+
+ if (x86Reg == x86_Any8Bit) {
+ x86Reg = Free8BitX86Reg(Section);
+ if (x86Reg < 0) {
+ return -1;
+ }
+ }
+ } else {
+ int NewReg;
+
+ if (x86Mapped(x86Reg) == GPR_Mapped) {
+ if (x86Protected(x86Reg) == 1) {
+ return -1;
+ }
+ x86Protected(x86Reg) = 1;
+ NewReg = FreeX86Reg(Section);
+ for (count = 1; count < 32; count ++) {
+ if (IsMapped(count)) {
+ if (MipsRegLo(count) == (uint32_t)x86Reg) {
+ if (NewReg < 0) {
+ UnMap_GPR(Section,count,1);
+ count = 32;
+ continue;
+ }
+
+ x86Mapped(NewReg) = GPR_Mapped;
+ x86MapOrder(NewReg) = x86MapOrder(x86Reg);
+ MipsRegLo(count) = NewReg;
+ MoveX86RegToX86Reg(x86Reg,NewReg);
+ if (MipsReg == count && LoadHiWord == 0) { MipsReg = -1; }
+ count = 32;
+ }
+ if (Is64Bit(count) && MipsRegHi(count) == (uint32_t)x86Reg) {
+ if (NewReg < 0) {
+ UnMap_GPR(Section,count,1);
+ count = 32;
+ continue;
+ }
+ x86Mapped(NewReg) = GPR_Mapped;
+ x86MapOrder(NewReg) = x86MapOrder(x86Reg);
+ MipsRegHi(count) = NewReg;
+ MoveX86RegToX86Reg(x86Reg,NewReg);
+ if (MipsReg == count && LoadHiWord == 1) { MipsReg = -1; }
+ count = 32;
+ }
+ }
+ }
+ }
+ if (x86Mapped(x86Reg) == Stack_Mapped) {
+ UnMap_X86reg(Section,x86Reg);
+ }
+ }
+ if (MipsReg >= 0) {
+ if (LoadHiWord) {
+ if (IsUnknown(MipsReg)) {
+ MoveVariableToX86reg(&GPR[MipsReg].UW[1],x86Reg);
+ } else if (IsMapped(MipsReg)) {
+ if (Is64Bit(MipsReg)) {
+ MoveX86RegToX86Reg(MipsRegHi(MipsReg),x86Reg);
+ } else if (IsSigned(MipsReg)){
+ MoveX86RegToX86Reg(MipsRegLo(MipsReg),x86Reg);
+
+ ShiftRightSignImmed(x86Reg,31);
+ } else {
+ MoveConstToX86reg(0,x86Reg);
+ }
+ } else {
+ if (Is64Bit(MipsReg)) {
+ if (MipsRegHi(MipsReg) != 0) {
+ MoveConstToX86reg(MipsRegHi(MipsReg),x86Reg);
+ } else {
+ XorX86RegToX86Reg(x86Reg,x86Reg);
+ }
+ } else {
+ if ((int)MipsRegLo(MipsReg) >> 31 != 0) {
+ MoveConstToX86reg((int)MipsRegLo(MipsReg) >> 31,x86Reg);
+ } else {
+ XorX86RegToX86Reg(x86Reg,x86Reg);
+ }
+ }
+ }
+ } else {
+ if (IsUnknown(MipsReg)) {
+ MoveVariableToX86reg(&GPR[MipsReg].UW[0],x86Reg);
+ } else if (IsMapped(MipsReg)) {
+ MoveX86RegToX86Reg(MipsRegLo(MipsReg),x86Reg);
+ } else {
+ if (MipsRegLo(MipsReg) != 0) {
+ MoveConstToX86reg(MipsRegLo(MipsReg),x86Reg);
+ } else {
+ XorX86RegToX86Reg(x86Reg,x86Reg);
+ }
+ }
+ }
+ }
+ x86Mapped(x86Reg) = Temp_Mapped;
+ x86Protected(x86Reg) = 1;
+ for (count = 0; count < 64; count ++) {
+ if (x86MapOrder(count) > 0) {
+ x86MapOrder(count) += 1;
+ }
+ }
+ x86MapOrder(x86Reg) = 1;
+ if(x64reg) x86Reg |= x64_Reg;
+ return x86Reg;
+}
+
+void ProtectGPR(BLOCK_SECTION * Section, uint32_t Reg) {
+ if (IsUnknown(Reg)) { return; }
+ if (IsConst(Reg)) { return; }
+ if (Is64Bit(Reg)) {
+ x86Protected(MipsRegHi(Reg)) = 1;
+ }
+ x86Protected(MipsRegLo(Reg)) = 1;
+}
+
+uint32_t RegInStack(BLOCK_SECTION * Section,int32_t Reg, int32_t Format) {
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ if (FpuMappedTo(i) == (uint32_t)Reg) {
+ if (FpuState(i) == (uint32_t)Format) { return 1; }
+ else if (Format == -1) { return 1; }
+ return 0;
+ }
+ }
+ return 0;
+}
+
+void SetFpuLocations (void) {
+ int count;
+
+ if ((STATUS_REGISTER & STATUS_FR) == 0) {
+ for (count = 0; count < 32; count ++) {
+ FPRFloatLocation[count] = (void *)(&FPR[count >> 1].W[count & 1]);
+ //FPRDoubleLocation[count] = FPRFloatLocation[count];
+ FPRDoubleLocation[count] = (void *)(&FPR[count >> 1].DW);
+ }
+ } else {
+ for (count = 0; count < 32; count ++) {
+ FPRFloatLocation[count] = (void *)(&FPR[count].W[1]);
+ //FPRFloatLocation[count] = (void *)(&FPR[count].W[1]);
+ //FPRDoubleLocation[count] = FPRFloatLocation[count];
+ FPRDoubleLocation[count] = (void *)(&FPR[count].DW);
+ }
+ }
+}
+
+int32_t StackPosition (BLOCK_SECTION * Section, int32_t Reg) {
+ int32_t i;
+
+ for (i = 0; i < 8; i++) {
+ if (FpuMappedTo(i) == (uint32_t)Reg) {
+ return ((i - StackTopPos) & 7);
+ }
+ }
+ return -1;
+}
+
+int UnMap_8BitTempReg (BLOCK_SECTION * Section) {
+ int32_t count;
+
+ for (count = 0; count < 64; count ++) {
+ if (!Is8BitReg(count)) { continue; }
+ if (MipsRegState(count) == Temp_Mapped) {
+ if (x86Protected(count) == 0) {
+ x86Mapped(count) = NotMapped;
+ return count;
+ }
+ }
+ }
+ return -1;
+}
+
+void UnMap_AllFPRs ( BLOCK_SECTION * Section ) {
+ int32_t StackPos;
+
+ for (;;) {
+ int i, StartPos;
+ StackPos = StackTopPos;
+ if (FpuMappedTo(StackTopPos) != -1 ) {
+ UnMap_FPR(Section,FpuMappedTo(StackTopPos),1);
+ continue;
+ }
+ //see if any more registers mapped
+ StartPos = StackTopPos;
+ for (i = 0; i < 8; i++) {
+ if (FpuMappedTo((StartPos + i) & 7) != -1 ) { fpuIncStack(&StackTopPos); }
+ }
+ if (StackPos != StackTopPos) { continue; }
+ return;
+ }
+}
+
+void UnMap_FPR (BLOCK_SECTION * Section, int32_t Reg, int32_t WriteBackValue ) {
+ int32_t TempReg;
+ int32_t i;
+
+ if (Reg < 0) { return; }
+ for (i = 0; i < 8; i++) {
+ if (FpuMappedTo(i) != (uint32_t)Reg) { continue; }
+ if (WriteBackValue) {
+ int RegPos;
+
+ if (((i - StackTopPos + 8) & 7) != 0) {
+ uint32_t RoundingModel, MappedTo, RegState;
+
+ RoundingModel = FpuRoundingModel(StackTopPos);
+ MappedTo = FpuMappedTo(StackTopPos);
+ RegState = FpuState(StackTopPos);
+ FpuRoundingModel(StackTopPos) = FpuRoundingModel(i);
+ FpuMappedTo(StackTopPos) = FpuMappedTo(i);
+ FpuState(StackTopPos) = FpuState(i);
+ FpuRoundingModel(i) = RoundingModel;
+ FpuMappedTo(i) = MappedTo;
+ FpuState(i) = RegState;
+ fpuExchange((i - StackTopPos) & 7);
+ }
+
+ if (CurrentRoundingModel != FpuRoundingModel(i)) {
+ int x86reg;
+
+ fpuControl = 0;
+ fpuStoreControl(&fpuControl);
+ x86reg = Map_TempReg(Section,x86_Any,-1,0);
+ MoveVariableToX86reg(&fpuControl, x86reg);
+ AndConstToX86Reg(x86reg, 0xF3FF);
+
+ switch (FpuRoundingModel(i)) {
+ case RoundDefault: OrVariableToX86Reg(&FPU_RoundingMode,x86reg); break;
+ case RoundTruncate: OrConstToX86Reg(0x0C00, x86reg); break;
+ case RoundNearest: /*OrConstToX86Reg(0x0000, x86reg);*/ break;
+ case RoundDown: OrConstToX86Reg(0x0400, x86reg); break;
+ case RoundUp: OrConstToX86Reg(0x0800, x86reg); break;
+ }
+ MoveX86regToVariable(x86reg, &fpuControl);
+ fpuLoadControl(&fpuControl);
+ CurrentRoundingModel = FpuRoundingModel(i);
+ }
+
+ RegPos = StackTopPos;
+ TempReg = Map_TempReg(Section,x86_Any,-1,0);
+ switch (FpuState(StackTopPos)) {
+ case FPU_Dword:
+ MovePointerToX86reg(&FPRFloatLocation[FpuMappedTo(StackTopPos)],TempReg);
+ fpuStoreIntegerDwordFromX86Reg(&StackTopPos,TempReg, 1);
+ break;
+ case FPU_Qword:
+ MovePointerToX86reg(&FPRDoubleLocation[FpuMappedTo(StackTopPos)],TempReg);
+ fpuStoreIntegerQwordFromX86Reg(&StackTopPos,TempReg, 1);
+ break;
+ case FPU_Float:
+ MovePointerToX86reg(&FPRFloatLocation[FpuMappedTo(StackTopPos)],TempReg);
+ fpuStoreDwordFromX86Reg(&StackTopPos,TempReg, 1);
+ break;
+ case FPU_Double:
+ MovePointerToX86reg(&FPRDoubleLocation[FpuMappedTo(StackTopPos)],TempReg);
+ fpuStoreQwordFromX86Reg(&StackTopPos,TempReg, 1);
+ break;
+ }
+ x86Protected(TempReg) = 0;
+ FpuRoundingModel(RegPos) = RoundDefault;
+ FpuMappedTo(RegPos) = -1;
+ FpuState(RegPos) = FPU_Unkown;
+ } else {
+ fpuFree((i - StackTopPos) & 7);
+ FpuRoundingModel(i) = RoundDefault;
+ FpuMappedTo(i) = -1;
+ FpuState(i) = FPU_Unkown;
+ }
+ return;
+ }
+}
+
+void UnMap_GPR (BLOCK_SECTION * Section, uint32_t Reg, int32_t WriteBackValue) {
+ if (Reg == 0) {
+ return;
+ }
+ if (IsUnknown(Reg)) { return; }
+ if (IsConst(Reg)) {
+ if (!WriteBackValue) {
+ MipsRegState(Reg) = STATE_UNKNOWN;
+ return;
+ }
+ if (Is64Bit(Reg)) {
+ MoveConstToVariable(MipsRegHi(Reg),&GPR[Reg].UW[1]);
+ MoveConstToVariable(MipsRegLo(Reg),&GPR[Reg].UW[0]);
+ MipsRegState(Reg) = STATE_UNKNOWN;
+ return;
+ }
+ if ((MipsRegLo(Reg) & 0x80000000) != 0) {
+ MoveConstToVariable(0xFFFFFFFF,&GPR[Reg].UW[1]);
+ } else {
+ MoveConstToVariable(0,&GPR[Reg].UW[1]);
+ }
+ MoveConstToVariable(MipsRegLo(Reg),&GPR[Reg].UW[0]);
+ MipsRegState(Reg) = STATE_UNKNOWN;
+ return;
+ }
+ if (Is64Bit(Reg)) {
+ x86Mapped(MipsRegHi(Reg)) = NotMapped;
+ x86Protected(MipsRegHi(Reg)) = 0;
+ }
+ x86Mapped(MipsRegLo(Reg)) = NotMapped;
+ x86Protected(MipsRegLo(Reg)) = 0;
+ if (!WriteBackValue) {
+ MipsRegState(Reg) = STATE_UNKNOWN;
+ return;
+ }
+ MoveX86regToVariable(MipsRegLo(Reg),&GPR[Reg].UW[0]);
+ if (Is64Bit(Reg)) {
+ MoveX86regToVariable(MipsRegHi(Reg),&GPR[Reg].UW[1]);
+ } else {
+ if (IsSigned(Reg)) {
+ ShiftRightSignImmed(MipsRegLo(Reg),31);
+ MoveX86regToVariable(MipsRegLo(Reg),&GPR[Reg].UW[1]);
+ } else {
+ MoveConstToVariable(0,&GPR[Reg].UW[1]);
+ }
+ }
+ MipsRegState(Reg) = STATE_UNKNOWN;
+}
+
+int UnMap_TempReg (BLOCK_SECTION * Section) {
+ int count;
+
+ for (count = 0; count < 64; count ++) {
+ if (x86Mapped(count) == Temp_Mapped) {
+ if (x86Protected(count) == 0) {
+ x86Mapped(count) = NotMapped;
+ return count & 0xff;
+ }
+ }
+ }
+ return -1;
+}
+
+int UnMap_TempRegSet (REG_INFO * RegWorking) {
+ int count;
+
+ for (count = 0; count < 64; count ++) {
+ if (RegWorking->x86reg_MappedTo[count] == Temp_Mapped) {
+ if (RegWorking->x86reg_Protected[count] == 0) {
+ RegWorking->x86reg_MappedTo[count] = NotMapped;
+ return count;
+ }
+ }
+ }
+ return -1;
+}
+
+
+uint32_t UnMap_X86reg (BLOCK_SECTION * Section, uint32_t x86Reg) {
+ int count;
+
+ if (x86Mapped(x86Reg) == NotMapped && x86Protected(x86Reg) == 0) { return 1; }
+ if (x86Mapped(x86Reg) == Temp_Mapped) {
+ if (x86Protected(x86Reg) == 0) {
+ x86Mapped(x86Reg) = NotMapped;
+ return 1;
+ }
+ return 0;
+ }
+ for (count = 1; count < 32; count ++) {
+ if (IsMapped(count)) {
+ if (Is64Bit(count)) {
+ if (MipsRegHi(count) == x86Reg) {
+ if (x86Protected(x86Reg) == 0) {
+ UnMap_GPR(Section,count,1);
+ return 1;
+ }
+ break;
+ }
+ }
+ if (MipsRegLo(count) == x86Reg) {
+ if (x86Protected(x86Reg) == 0) {
+ UnMap_GPR(Section,count,1);
+ return 1;
+ }
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+void UnProtectGPR(BLOCK_SECTION * Section, uint32_t Reg) {
+ if (IsUnknown(Reg)) { return; }
+ if (IsConst(Reg)) { return; }
+ if (Is64Bit(Reg)) {
+ x86Protected(MipsRegHi(Reg)) = 0;
+ }
+ x86Protected(MipsRegLo(Reg)) = 0;
+}
+
+void UpdateCurrentHalfLine (void) {
+ if (Timers->Timer < 0) {
+ HalfLine = 0;
+ return;
+ }
+ HalfLine = (Timers->Timer / 1500);
+ HalfLine &= ~1;
+ HalfLine += ViFieldNumber;
+
+}
+
+void WriteBackRegisters (BLOCK_SECTION * Section) {
+ int32_t count;
+ uint32_t bEdiZero = 0;
+ uint32_t bEsiSign = 0;
+ /*** coming soon ***/
+ //uint32_t bEaxGprLo = 0;
+ //uint32_t bEbxGprHi = 0;
+
+ for (count = 1; count < 64; count ++) { x86Protected(count) = 0; }
+ for (count = 1; count < 64; count ++) { UnMap_X86reg (Section, count); }
+
+ /*************************************/
+
+ for (count = 1; count < 32; count ++) {
+ switch (MipsRegState(count)) {
+ case STATE_UNKNOWN: break;
+ case STATE_CONST_32:
+ if (!bEdiZero && (!MipsRegLo(count) || !(MipsRegLo(count) & 0x80000000))) {
+ XorX86RegToX86Reg(x86_EDI, x86_EDI);
+ bEdiZero = 1;
+ }
+ if (!bEsiSign && (MipsRegLo(count) & 0x80000000)) {
+ MoveConstToX86reg(0xFFFFFFFF, x86_ESI);
+ bEsiSign = 1;
+ }
+
+ if ((MipsRegLo(count) & 0x80000000) != 0) {
+ MoveX86regToVariable(x86_ESI,&GPR[count].UW[1]);
+ } else {
+ MoveX86regToVariable(x86_EDI,&GPR[count].UW[1]);
+ }
+
+ if (MipsRegLo(count) == 0) {
+ MoveX86regToVariable(x86_EDI,&GPR[count].UW[0]);
+ } else if (MipsRegLo(count) == 0xFFFFFFFF) {
+ MoveX86regToVariable(x86_ESI,&GPR[count].UW[0]);
+ } else
+ MoveConstToVariable(MipsRegLo(count),&GPR[count].UW[0]);
+
+ MipsRegState(count) = STATE_UNKNOWN;
+ break;
+ case STATE_CONST_64:
+ if (MipsRegLo(count) == 0 || MipsRegHi(count) == 0) {
+ XorX86RegToX86Reg(x86_EDI, x86_EDI);
+ bEdiZero = 1;
+ }
+ if (MipsRegLo(count) == 0xFFFFFFFF || MipsRegHi(count) == 0xFFFFFFFF) {
+ MoveConstToX86reg(0xFFFFFFFF, x86_ESI);
+ bEsiSign = 1;
+ }
+
+ if (MipsRegHi(count) == 0) {
+ MoveX86regToVariable(x86_EDI,&GPR[count].UW[1]);
+ } else if (MipsRegLo(count) == 0xFFFFFFFF) {
+ MoveX86regToVariable(x86_ESI,&GPR[count].UW[1]);
+ } else {
+ MoveConstToVariable(MipsRegHi(count),&GPR[count].UW[1]);
+ }
+
+ if (MipsRegLo(count) == 0) {
+ MoveX86regToVariable(x86_EDI,&GPR[count].UW[0]);
+ } else if (MipsRegLo(count) == 0xFFFFFFFF) {
+ MoveX86regToVariable(x86_ESI,&GPR[count].UW[0]);
+ } else {
+ MoveConstToVariable(MipsRegLo(count),&GPR[count].UW[0]);
+ }
+ MipsRegState(count) = STATE_UNKNOWN;
+ break;
+
+ }
+ }
+ UnMap_AllFPRs(Section);
+}
+
diff --git a/src/usf/registers.h b/src/usf/registers.h new file mode 100644 index 0000000..4c9b1b3 --- /dev/null +++ b/src/usf/registers.h @@ -0,0 +1,403 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+
+#ifndef REGISTERS_H
+#define REGISTERS_H
+
+#include "recompiler_cpu.h"
+#include "types.h"
+
+#define INDEX_REGISTER CP0[0]
+#define RANDOM_REGISTER CP0[1]
+#define ENTRYLO0_REGISTER CP0[2]
+#define ENTRYLO1_REGISTER CP0[3]
+#define CONTEXT_REGISTER CP0[4]
+#define PAGE_MASK_REGISTER CP0[5]
+#define WIRED_REGISTER CP0[6]
+#define BAD_VADDR_REGISTER CP0[8]
+#define COUNT_REGISTER CP0[9]
+#define ENTRYHI_REGISTER CP0[10]
+#define COMPARE_REGISTER CP0[11]
+#define STATUS_REGISTER CP0[12]
+#define CAUSE_REGISTER CP0[13]
+#define EPC_REGISTER CP0[14]
+#define CONFIG_REGISTER CP0[16]
+#define TAGLO_REGISTER CP0[28]
+#define TAGHI_REGISTER CP0[29]
+#define ERROREPC_REGISTER CP0[30]
+#define FAKE_CAUSE_REGISTER CP0[32]
+
+#define COMPARE_REGISTER_NO 11
+#define STATUS_REGISTER_NO 12
+#define CAUSE_REGISTER_NO 13
+
+#define REVISION_REGISTER FPCR[0]
+#define FSTATUS_REGISTER FPCR[31]
+
+#define GPR_S0 GPR[16]
+#define GPR_S1 GPR[17]
+#define GPR_S2 GPR[18]
+#define GPR_S3 GPR[19]
+#define GPR_S4 GPR[20]
+#define GPR_S5 GPR[21]
+#define GPR_S6 GPR[22]
+#define GPR_S7 GPR[23]
+#define GPR_SP GPR[29]
+#define GPR_RA GPR[31]
+
+#define RDRAM_CONFIG_REG RegRDRAM[0]
+#define RDRAM_DEVICE_TYPE_REG RegRDRAM[0]
+#define RDRAM_DEVICE_ID_REG RegRDRAM[1]
+#define RDRAM_DELAY_REG RegRDRAM[2]
+#define RDRAM_MODE_REG RegRDRAM[3]
+#define RDRAM_REF_INTERVAL_REG RegRDRAM[4]
+#define RDRAM_REF_ROW_REG RegRDRAM[5]
+#define RDRAM_RAS_INTERVAL_REG RegRDRAM[6]
+#define RDRAM_MIN_INTERVAL_REG RegRDRAM[7]
+#define RDRAM_ADDR_SELECT_REG RegRDRAM[8]
+#define RDRAM_DEVICE_MANUF_REG RegRDRAM[9]
+
+#define SP_MEM_ADDR_REG RegSP[0]
+#define SP_DRAM_ADDR_REG RegSP[1]
+#define SP_RD_LEN_REG RegSP[2]
+#define SP_WR_LEN_REG RegSP[3]
+#define SP_STATUS_REG RegSP[4]
+#define SP_DMA_FULL_REG RegSP[5]
+#define SP_DMA_BUSY_REG RegSP[6]
+#define SP_SEMAPHORE_REG RegSP[7]
+#define SP_PC_REG RegSP[8]
+#define SP_IBIST_REG RegSP[9]
+
+#define DPC_START_REG RegDPC[0]
+#define DPC_END_REG RegDPC[1]
+#define DPC_CURRENT_REG RegDPC[2]
+#define DPC_STATUS_REG RegDPC[3]
+#define DPC_CLOCK_REG RegDPC[4]
+#define DPC_BUFBUSY_REG RegDPC[5]
+#define DPC_PIPEBUSY_REG RegDPC[6]
+#define DPC_TMEM_REG RegDPC[7]
+
+#define MI_INIT_MODE_REG RegMI[0]
+#define MI_MODE_REG RegMI[0]
+#define MI_VERSION_REG RegMI[1]
+#define MI_NOOP_REG RegMI[1]
+#define MI_INTR_REG RegMI[2]
+#define MI_INTR_MASK_REG RegMI[3]
+
+#define VI_STATUS_REG RegVI[0]
+#define VI_CONTROL_REG RegVI[0]
+#define VI_ORIGIN_REG RegVI[1]
+#define VI_DRAM_ADDR_REG RegVI[1]
+#define VI_WIDTH_REG RegVI[2]
+#define VI_H_WIDTH_REG RegVI[2]
+#define VI_INTR_REG RegVI[3]
+#define VI_V_INTR_REG RegVI[3]
+#define VI_CURRENT_REG RegVI[4]
+#define VI_V_CURRENT_LINE_REG RegVI[4]
+#define VI_BURST_REG RegVI[5]
+#define VI_TIMING_REG RegVI[5]
+#define VI_V_SYNC_REG RegVI[6]
+#define VI_H_SYNC_REG RegVI[7]
+#define VI_LEAP_REG RegVI[8]
+#define VI_H_SYNC_LEAP_REG RegVI[8]
+#define VI_H_START_REG RegVI[9]
+#define VI_H_VIDEO_REG RegVI[9]
+#define VI_V_START_REG RegVI[10]
+#define VI_V_VIDEO_REG RegVI[10]
+#define VI_V_BURST_REG RegVI[11]
+#define VI_X_SCALE_REG RegVI[12]
+#define VI_Y_SCALE_REG RegVI[13]
+
+#define AI_DRAM_ADDR_REG RegAI[0]
+#define AI_LEN_REG RegAI[1]
+#define AI_CONTROL_REG RegAI[2]
+#define AI_STATUS_REG RegAI[3]
+#define AI_DACRATE_REG RegAI[4]
+#define AI_BITRATE_REG RegAI[5]
+
+#define PI_DRAM_ADDR_REG RegPI[0]
+#define PI_CART_ADDR_REG RegPI[1]
+#define PI_RD_LEN_REG RegPI[2]
+#define PI_WR_LEN_REG RegPI[3]
+#define PI_STATUS_REG RegPI[4]
+#define PI_BSD_DOM1_LAT_REG RegPI[5]
+#define PI_DOMAIN1_REG RegPI[5]
+#define PI_BSD_DOM1_PWD_REG RegPI[6]
+#define PI_BSD_DOM1_PGS_REG RegPI[7]
+#define PI_BSD_DOM1_RLS_REG RegPI[8]
+#define PI_BSD_DOM2_LAT_REG RegPI[9]
+#define PI_DOMAIN2_REG RegPI[9]
+#define PI_BSD_DOM2_PWD_REG RegPI[10]
+#define PI_BSD_DOM2_PGS_REG RegPI[11]
+#define PI_BSD_DOM2_RLS_REG RegPI[12]
+
+#define RI_MODE_REG RegRI[0]
+#define RI_CONFIG_REG RegRI[1]
+#define RI_CURRENT_LOAD_REG RegRI[2]
+#define RI_SELECT_REG RegRI[3]
+#define RI_COUNT_REG RegRI[4]
+#define RI_REFRESH_REG RegRI[4]
+#define RI_LATENCY_REG RegRI[5]
+#define RI_RERROR_REG RegRI[6]
+#define RI_WERROR_REG RegRI[7]
+
+#define SI_DRAM_ADDR_REG RegSI[0]
+#define SI_PIF_ADDR_RD64B_REG RegSI[1]
+#define SI_PIF_ADDR_WR64B_REG RegSI[2]
+#define SI_STATUS_REG RegSI[3]
+
+#define STATUS_IE 0x00000001
+#define STATUS_EXL 0x00000002
+#define STATUS_ERL 0x00000004
+#define STATUS_IP0 0x00000100
+#define STATUS_IP1 0x00000200
+#define STATUS_IP2 0x00000400
+#define STATUS_IP3 0x00000800
+#define STATUS_IP4 0x00001000
+#define STATUS_IP5 0x00002000
+#define STATUS_IP6 0x00004000
+#define STATUS_IP7 0x00008000
+#define STATUS_BEV 0x00400000
+#define STATUS_FR 0x04000000
+#define STATUS_CU0 0x10000000
+#define STATUS_CU1 0x20000000
+
+#define CAUSE_EXC_CODE 0xFF
+#define CAUSE_IP0 0x100
+#define CAUSE_IP1 0x200
+#define CAUSE_IP2 0x400
+#define CAUSE_IP3 0x800
+#define CAUSE_IP4 0x1000
+#define CAUSE_IP5 0x2000
+#define CAUSE_IP6 0x4000
+#define CAUSE_IP7 0x8000
+#define CAUSE_BD 0x80000000
+
+#define SP_CLR_HALT 0x00001 /* Bit 0: clear halt */
+#define SP_SET_HALT 0x00002 /* Bit 1: set halt */
+#define SP_CLR_BROKE 0x00004 /* Bit 2: clear broke */
+#define SP_CLR_INTR 0x00008 /* Bit 3: clear intr */
+#define SP_SET_INTR 0x00010 /* Bit 4: set intr */
+#define SP_CLR_SSTEP 0x00020 /* Bit 5: clear sstep */
+#define SP_SET_SSTEP 0x00040 /* Bit 6: set sstep */
+#define SP_CLR_INTR_BREAK 0x00080 /* Bit 7: clear intr on break */
+#define SP_SET_INTR_BREAK 0x00100 /* Bit 8: set intr on break */
+#define SP_CLR_SIG0 0x00200 /* Bit 9: clear signal 0 */
+#define SP_SET_SIG0 0x00400 /* Bit 10: set signal 0 */
+#define SP_CLR_SIG1 0x00800 /* Bit 11: clear signal 1 */
+#define SP_SET_SIG1 0x01000 /* Bit 12: set signal 1 */
+#define SP_CLR_SIG2 0x02000 /* Bit 13: clear signal 2 */
+#define SP_SET_SIG2 0x04000 /* Bit 14: set signal 2 */
+#define SP_CLR_SIG3 0x08000 /* Bit 15: clear signal 3 */
+#define SP_SET_SIG3 0x10000 /* Bit 16: set signal 3 */
+#define SP_CLR_SIG4 0x20000 /* Bit 17: clear signal 4 */
+#define SP_SET_SIG4 0x40000 /* Bit 18: set signal 4 */
+#define SP_CLR_SIG5 0x80000 /* Bit 19: clear signal 5 */
+#define SP_SET_SIG5 0x100000 /* Bit 20: set signal 5 */
+#define SP_CLR_SIG6 0x200000 /* Bit 21: clear signal 6 */
+#define SP_SET_SIG6 0x400000 /* Bit 22: set signal 6 */
+#define SP_CLR_SIG7 0x800000 /* Bit 23: clear signal 7 */
+#define SP_SET_SIG7 0x1000000 /* Bit 24: set signal 7 */
+
+#define SP_STATUS_HALT 0x001 /* Bit 0: halt */
+#define SP_STATUS_BROKE 0x002 /* Bit 1: broke */
+#define SP_STATUS_DMA_BUSY 0x004 /* Bit 2: dma busy */
+#define SP_STATUS_DMA_FULL 0x008 /* Bit 3: dma full */
+#define SP_STATUS_IO_FULL 0x010 /* Bit 4: io full */
+#define SP_STATUS_SSTEP 0x020 /* Bit 5: single step */
+#define SP_STATUS_INTR_BREAK 0x040 /* Bit 6: interrupt on break */
+#define SP_STATUS_SIG0 0x080 /* Bit 7: signal 0 set */
+#define SP_STATUS_SIG1 0x100 /* Bit 8: signal 1 set */
+#define SP_STATUS_SIG2 0x200 /* Bit 9: signal 2 set */
+#define SP_STATUS_SIG3 0x400 /* Bit 10: signal 3 set */
+#define SP_STATUS_SIG4 0x800 /* Bit 11: signal 4 set */
+#define SP_STATUS_SIG5 0x1000 /* Bit 12: signal 5 set */
+#define SP_STATUS_SIG6 0x2000 /* Bit 13: signal 6 set */
+#define SP_STATUS_SIG7 0x4000 /* Bit 14: signal 7 set */
+
+#define DPC_CLR_XBUS_DMEM_DMA 0x0001 /* Bit 0: clear xbus_dmem_dma */
+#define DPC_SET_XBUS_DMEM_DMA 0x0002 /* Bit 1: set xbus_dmem_dma */
+#define DPC_CLR_FREEZE 0x0004 /* Bit 2: clear freeze */
+#define DPC_SET_FREEZE 0x0008 /* Bit 3: set freeze */
+#define DPC_CLR_FLUSH 0x0010 /* Bit 4: clear flush */
+#define DPC_SET_FLUSH 0x0020 /* Bit 5: set flush */
+#define DPC_CLR_TMEM_CTR 0x0040 /* Bit 6: clear tmem ctr */
+#define DPC_CLR_PIPE_CTR 0x0080 /* Bit 7: clear pipe ctr */
+#define DPC_CLR_CMD_CTR 0x0100 /* Bit 8: clear cmd ctr */
+#define DPC_CLR_CLOCK_CTR 0x0200 /* Bit 9: clear clock ctr */
+
+#define DPC_STATUS_XBUS_DMEM_DMA 0x001 /* Bit 0: xbus_dmem_dma */
+#define DPC_STATUS_FREEZE 0x002 /* Bit 1: freeze */
+#define DPC_STATUS_FLUSH 0x004 /* Bit 2: flush */
+#define DPC_STATUS_START_GCLK 0x008 /* Bit 3: start gclk */
+#define DPC_STATUS_TMEM_BUSY 0x010 /* Bit 4: tmem busy */
+#define DPC_STATUS_PIPE_BUSY 0x020 /* Bit 5: pipe busy */
+#define DPC_STATUS_CMD_BUSY 0x040 /* Bit 6: cmd busy */
+#define DPC_STATUS_CBUF_READY 0x080 /* Bit 7: cbuf ready */
+#define DPC_STATUS_DMA_BUSY 0x100 /* Bit 8: dma busy */
+#define DPC_STATUS_END_VALID 0x200 /* Bit 9: end valid */
+#define DPC_STATUS_START_VALID 0x400 /* Bit 10: start valid */
+
+#define MI_CLR_INIT 0x0080 /* Bit 7: clear init mode */
+#define MI_SET_INIT 0x0100 /* Bit 8: set init mode */
+#define MI_CLR_EBUS 0x0200 /* Bit 9: clear ebus test */
+#define MI_SET_EBUS 0x0400 /* Bit 10: set ebus test mode */
+#define MI_CLR_DP_INTR 0x0800 /* Bit 11: clear dp interrupt */
+#define MI_CLR_RDRAM 0x1000 /* Bit 12: clear RDRAM reg */
+#define MI_SET_RDRAM 0x2000 /* Bit 13: set RDRAM reg mode */
+
+#define MI_MODE_INIT 0x0080 /* Bit 7: init mode */
+#define MI_MODE_EBUS 0x0100 /* Bit 8: ebus test mode */
+#define MI_MODE_RDRAM 0x0200 /* Bit 9: RDRAM reg mode */
+
+#define MI_INTR_MASK_CLR_SP 0x0001 /* Bit 0: clear SP mask */
+#define MI_INTR_MASK_SET_SP 0x0002 /* Bit 1: set SP mask */
+#define MI_INTR_MASK_CLR_SI 0x0004 /* Bit 2: clear SI mask */
+#define MI_INTR_MASK_SET_SI 0x0008 /* Bit 3: set SI mask */
+#define MI_INTR_MASK_CLR_AI 0x0010 /* Bit 4: clear AI mask */
+#define MI_INTR_MASK_SET_AI 0x0020 /* Bit 5: set AI mask */
+#define MI_INTR_MASK_CLR_VI 0x0040 /* Bit 6: clear VI mask */
+#define MI_INTR_MASK_SET_VI 0x0080 /* Bit 7: set VI mask */
+#define MI_INTR_MASK_CLR_PI 0x0100 /* Bit 8: clear PI mask */
+#define MI_INTR_MASK_SET_PI 0x0200 /* Bit 9: set PI mask */
+#define MI_INTR_MASK_CLR_DP 0x0400 /* Bit 10: clear DP mask */
+#define MI_INTR_MASK_SET_DP 0x0800 /* Bit 11: set DP mask */
+
+#define MI_INTR_MASK_SP 0x01 /* Bit 0: SP intr mask */
+#define MI_INTR_MASK_SI 0x02 /* Bit 1: SI intr mask */
+#define MI_INTR_MASK_AI 0x04 /* Bit 2: AI intr mask */
+#define MI_INTR_MASK_VI 0x08 /* Bit 3: VI intr mask */
+#define MI_INTR_MASK_PI 0x10 /* Bit 4: PI intr mask */
+#define MI_INTR_MASK_DP 0x20 /* Bit 5: DP intr mask */
+
+#define MI_INTR_SP 0x01 /* Bit 0: SP intr */
+#define MI_INTR_SI 0x02 /* Bit 1: SI intr */
+#define MI_INTR_AI 0x04 /* Bit 2: AI intr */
+#define MI_INTR_VI 0x08 /* Bit 3: VI intr */
+#define MI_INTR_PI 0x10 /* Bit 4: PI intr */
+#define MI_INTR_DP 0x20 /* Bit 5: DP intr */
+
+#define PI_STATUS_DMA_BUSY 0x01
+#define PI_STATUS_IO_BUSY 0x02
+#define PI_STATUS_ERROR 0x04
+
+#define PI_SET_RESET 0x01
+#define PI_CLR_INTR 0x02
+
+#define SI_STATUS_DMA_BUSY 0x0001
+#define SI_STATUS_RD_BUSY 0x0002
+#define SI_STATUS_DMA_ERROR 0x0008
+#define SI_STATUS_INTERRUPT 0x1000
+
+#define FPCSR_FS 0x01000000 /* flush denorm to zero */
+#define FPCSR_C 0x00800000 /* condition bit */
+#define FPCSR_CE 0x00020000 /* cause: unimplemented operation */
+#define FPCSR_CV 0x00010000 /* cause: invalid operation */
+#define FPCSR_CZ 0x00008000 /* cause: division by zero */
+#define FPCSR_CO 0x00004000 /* cause: overflow */
+#define FPCSR_CU 0x00002000 /* cause: underflow */
+#define FPCSR_CI 0x00001000 /* cause: inexact operation */
+#define FPCSR_EV 0x00000800 /* enable: invalid operation */
+#define FPCSR_EZ 0x00000400 /* enable: division by zero */
+#define FPCSR_EO 0x00000200 /* enable: overflow */
+#define FPCSR_EU 0x00000100 /* enable: underflow */
+#define FPCSR_EI 0x00000080 /* enable: inexact operation */
+#define FPCSR_FV 0x00000040 /* flag: invalid operation */
+#define FPCSR_FZ 0x00000020 /* flag: division by zero */
+#define FPCSR_FO 0x00000010 /* flag: overflow */
+#define FPCSR_FU 0x00000008 /* flag: underflow */
+#define FPCSR_FI 0x00000004 /* flag: inexact operation */
+#define FPCSR_RM_MASK 0x00000003 /* rounding mode mask */
+#define FPCSR_RM_RN 0x00000000 /* round to nearest */
+#define FPCSR_RM_RZ 0x00000001 /* round to zero */
+#define FPCSR_RM_RP 0x00000002 /* round to positive infinity */
+#define FPCSR_RM_RM 0x00000003 /* round to negative infinity */
+
+#define FPR_Type(Reg) (Reg) == R4300i_COP1_S ? "S" : (Reg) == R4300i_COP1_D ? "D" :\
+ (Reg) == R4300i_COP1_W ? "W" : "L"
+
+typedef struct {
+ uint32_t PROGRAM_COUNTER;
+ MIPS_DWORD GPR[32];
+ MIPS_DWORD FPR[32];
+ uint32_t CP0[33];
+ uint32_t FPCR[32];
+ MIPS_DWORD HI;
+ MIPS_DWORD LO;
+ uint32_t RDRAM[10];
+ uint32_t SP[10];
+ uint32_t DPC[10];
+ uint32_t MI[4];
+ uint32_t VI[14];
+ uint32_t AI[6];
+ uint32_t PI[13];
+ uint32_t RI[8];
+ uint32_t SI[4];
+ int8_t PIF_Ram[0x40];
+} N64_REGISTERS;
+
+
+extern uint32_t PROGRAM_COUNTER, * CP0,*FPCR,*RegRDRAM,*RegSP,*RegDPC,*RegMI,*RegVI,*RegAI,*RegPI,
+ *RegRI,*RegSI, HalfLine, RegModValue, ViFieldNumber, LLBit, LLAddr;
+extern void * FPRDoubleLocation[32], * FPRFloatLocation[32];
+extern MIPS_DWORD *GPR, *FPR, HI, LO;
+extern N64_REGISTERS * Registers;
+
+enum FPU_Format {
+ FPU_Unkown,FPU_Dword, FPU_Qword, FPU_Float, FPU_Double
+};
+
+enum FPU_RoundingModel {
+ RoundUnknown, RoundDefault, RoundTruncate, RoundNearest, RoundDown, RoundUp
+};
+
+void ChangeFPURegFormat ( BLOCK_SECTION * Section, int32_t Reg, int32_t OldFormat, int32_t NewFormat, int32_t RoundingModel );
+void ChangeMiIntrMask ( void );
+void ChangeMiModeReg ( void );
+void ChangeSpStatus ( void );
+void InitalizeR4300iRegisters ( void );
+uint32_t Is8BitReg ( int32_t x86Reg);
+void Load_FPR_ToTop ( BLOCK_SECTION * Section, int32_t Reg, int32_t RegToLoad, int32_t Format);
+void Map_GPR_32bit ( BLOCK_SECTION * Section, int32_t Reg, uint32_t SignValue, int32_t MipsRegToLoad );
+void Map_GPR_64bit ( BLOCK_SECTION * Section, int32_t Reg, int32_t MipsRegToLoad );
+int32_t Map_TempReg ( BLOCK_SECTION * Section, int32_t x86Reg, int32_t MipsReg, uint32_t LoadHiWord );
+uint32_t RegInStack ( BLOCK_SECTION * Section, int32_t Reg, int32_t Format );
+void ProtectGPR ( BLOCK_SECTION * Section, uint32_t Reg );
+void SetFpuLocations ( void );
+int32_t StackPosition ( BLOCK_SECTION * Section, int32_t Reg );
+int UnMap_8BitTempReg (BLOCK_SECTION * Section);
+void UnMap_AllFPRs ( BLOCK_SECTION * Section );
+void UnMap_FPR ( BLOCK_SECTION * Section, int32_t Reg, int32_t WriteBackValue );
+void UnMap_GPR ( BLOCK_SECTION * Section, uint32_t Reg, int32_t WriteBackValue );
+uint32_t UnMap_X86reg ( BLOCK_SECTION * Section, uint32_t x86Reg );
+void UnProtectGPR ( BLOCK_SECTION * Section, uint32_t Reg );
+void UpdateCurrentHalfLine ( void );
+void WriteBackRegisters ( BLOCK_SECTION * Section );
+
+
+void SetupRegisters(N64_REGISTERS * n64_Registers);
+
+#endif
diff --git a/src/usf/rsp.c b/src/usf/rsp.c new file mode 100644 index 0000000..2a5cea3 --- /dev/null +++ b/src/usf/rsp.c @@ -0,0 +1,1065 @@ +#include <stdlib.h>
+#include <stdint.h>
+#include "usf.h"
+#include "cpu.h"
+#include "memory.h"
+#include "audio.h"
+#include "rsp.h"
+#include "types.h"
+#include "main.h"
+
+#include "rsp_recompiler_cpu.h"
+
+
+
+uint32_t NoOfMaps, MapsCRC[MaxMaps], Table,ConditionalMove=0;
+uint8_t * RSPRecompCode = 0, * RSPRecompCodeSecondary, * RSPRecompPos, *RSPJumpTables;
+void ** RSPJumpTable;
+
+
+RSP_COMPILER Compiler;
+//REGISTER32 RSP_GPR[32], RSP_Flags[4];
+REGISTER32 *RSP_GPR, RSP_Flags[4];
+REGISTER * RSP_ACCUM;
+VECTOR * RSP_Vect;
+
+REGISTER EleSpec[32], Indx[32];
+RSPOPCODE RSPOpC;
+uint32_t *PrgCount = 0, RSPNextInstruction = 0;
+uint32_t RSP_NextInstruction = 0;
+REGISTER32 Recp, RecpResult, SQroot, SQrootResult;
+
+uint32_t RSP_NextInstruction, RSP_JumpTo;
+uint32_t RSP_Running = 0;
+int32_t RSP_Cpu = 0;
+
+
+void RSPReInitMemory()
+{
+
+ if(RSPRecompCode == NULL) {
+ printf("enough memory for RSP RSPRecompCode!");
+ return;
+ }
+
+ RSPRecompCodeSecondary = RSPRecompCode + RSP_RECOMPMEM_SIZE;
+
+
+ if( RSPJumpTables == NULL ) {
+ DisplayError("Not enough memory for Jump Table!");
+ return;
+ }
+
+ memset((uint8_t*)RSPJumpTables, 0, 0x2000 * MaxMaps);
+ memset((uint8_t*)RSPRecompCode, 0, 0x00400000);
+ memset((uint8_t*)RSPRecompCodeSecondary, 0, 0x00200000);
+
+
+ RSPJumpTable = (void **)RSPJumpTables;
+ RSPRecompPos = RSPRecompCode;
+ NoOfMaps = 0;
+}
+
+int32_t RSPAllocateMemory (void) {
+
+ RSPRecompCode=(uint8_t *) malloc_exec(RSP_RECOMPMEM_SIZE + RSP_SECRECOMPMEM_SIZE);
+ if(RSPRecompCode == NULL) {
+ DisplayError("Not enough memory for RSP RSPRecompCode!");
+ return 0;
+ }
+
+ RSPRecompCodeSecondary = RSPRecompCode + RSP_RECOMPMEM_SIZE;
+
+ RSPJumpTables = malloc(0x2000 * MaxMaps);
+
+ if( RSPJumpTables == NULL ) {
+ DisplayError("Not enough memory for Jump Table!");
+ return 0;
+ }
+
+ memset((uint8_t*)RSPJumpTables, 0, 0x2000 * MaxMaps);
+ memset((uint8_t*)RSPRecompCode, 0, 0x00400000);
+ memset((uint8_t*)RSPRecompCodeSecondary, 0, 0x00200000);
+
+ RSPJumpTable = (void **)RSPJumpTables;
+ RSPRecompPos = RSPRecompCode;
+ NoOfMaps = 0;
+ return 1;
+}
+
+FILE *qfil = 0;
+
+void real_run_rsp(uint32_t cycles)
+{
+//replace with interpreter
+if(RSP_Cpu) {
+ RSP_Running = 1;
+
+ while(RSP_Running) {
+ // int32_t last = -1, count = 0, el, del;
+ RSP_LW_IMEM(*PrgCount, &RSPOpC.Hex);
+
+ /*if(*PrgCount == 0x100) {
+ int32_t i= 0;
+ FILE *fil4 = fopen("sc2000i.dmem","wb");
+ for(i = 0; i < 0x2000;i+=4) {
+ uint32_t dat = 0;
+ dat = *(int32_t*)(DMEM + i);
+ DoBswap(&dat);
+ fwrite(&dat,1,4,fil4);
+ }
+ fclose(fil4);
+ printf("RSP: %x\n", RSP_GPR[26].UW);
+// Int3();
+// RSPBreakPoint();
+ }*/
+/*
+ if(!qfil) qfil = fopen("rsplogi.log","wb");
+ fprintf(qfil,"PC = %08x ", *PrgCount);
+ fprintf(qfil,"r0=%08x at=%08x v0=%08x v1=%08x a0=%08x a1=%08x a2=%08x a3=%08x t0=%08x t1=%08x t2=%08x t3=%08x t4=%08x t5=%08x t6=%08x t7=%08x s0=%08x s1=%08x s2=%08x s3=%08x s4=%08x s5=%08x s6=%08x s7=%08x t8=%08x t9=%08x k0=%08x k1=%08x gp=%08x sp=%08x s8=%08x ra=%08x\n",
+ RSP_GPR[0].UW,RSP_GPR[1].UW,RSP_GPR[2].UW,RSP_GPR[3].UW,
+ RSP_GPR[4].UW,RSP_GPR[5].UW,RSP_GPR[6].UW,RSP_GPR[7].UW,
+ RSP_GPR[8].UW,RSP_GPR[9].UW,RSP_GPR[10].UW,RSP_GPR[11].UW,RSP_GPR[12].UW,
+ RSP_GPR[13].UW,RSP_GPR[14].UW,RSP_GPR[15].UW,RSP_GPR[16].UW,
+ RSP_GPR[17].UW,RSP_GPR[18].UW,RSP_GPR[19].UW,RSP_GPR[20].UW,
+ RSP_GPR[21].UW,RSP_GPR[22].UW,RSP_GPR[23].UW,RSP_GPR[24].UW,
+ RSP_GPR[25].UW,RSP_GPR[26].UW,RSP_GPR[27].UW,RSP_GPR[28].UW,
+ RSP_GPR[29].UW,RSP_GPR[30].UW,RSP_GPR[31].UW);
+*/
+ /*if((RSPOpC.op == 18) && (RSPOpC.rs & 0x10)) {
+ for (count = 0; count < 8; count ++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+ if((last >= 0) && (last != del))
+ printf("not same!\t%d\n", RSPOpC.funct);
+ // 16,19,20,22
+ // funct: 0,16,6,14,44,15,7
+ last = del;
+ }
+ }*/
+
+ //if(RSPOpC.rs < 0x10) printf("%d\n", RSPOpC.rs);
+
+ (RSP_Opcode[ RSPOpC.op ])();
+
+ switch (RSP_NextInstruction) {
+ case NORMAL:
+ *PrgCount = (*PrgCount + 4) & 0xFFC;
+ break;
+ case DELAY_SLOT:
+ RSP_NextInstruction = JUMP;
+ *PrgCount = (*PrgCount + 4) & 0xFFC;
+ break;
+ case JUMP:
+ RSP_NextInstruction = NORMAL;
+
+ *PrgCount = RSP_JumpTo;
+ break;
+ }
+
+ }
+
+ *PrgCount -= 4;
+
+ return;
+
+ } else {
+ RunRecompilerCPU(cycles);
+ }
+
+}
+
+void RSP_SP_DMA_READ (void) {
+ uint32_t i, j, Length, Skip, Count;
+ uint8_t *Dest, *Source;
+
+ SP_DRAM_ADDR_REG &= 0x00FFFFFF;
+
+ if (SP_DRAM_ADDR_REG > 0x800000) {
+ printf("SP DMA READ\nSP_DRAM_ADDR_REG not in RDRam space");
+ return;
+ }
+
+ if ((SP_RD_LEN_REG & 0xFFF) + 1 + (SP_MEM_ADDR_REG & 0xFFF) > 0x1000) {
+ printf("SP DMA READ\ncould not fit copy in memory segement\nSP_RD_LEN_REG=%08x\nSP_MEM_ADDR_REG=%08x",SP_RD_LEN_REG,SP_MEM_ADDR_REG);
+ return;
+ }
+
+ Length = ((SP_RD_LEN_REG & 0xFFF) | 7) + 1;
+ Skip = (SP_RD_LEN_REG >> 20) + Length;
+ Count = ((SP_RD_LEN_REG >> 12) & 0xFF) + 1;
+
+ if ((SP_MEM_ADDR_REG & 0x1000) != 0) {
+ Dest = IMEM + ((SP_MEM_ADDR_REG & 0x0FFF) & ~7);
+ } else {
+ Dest = DMEM + ((SP_MEM_ADDR_REG & 0x0FFF) & ~7);
+ }
+ Source = RDRAM + (SP_DRAM_ADDR_REG & ~7);
+
+#if defined(RSP_SAFE_DMA)
+ for (j = 0 ; j < Count; j++) {
+ for (i = 0 ; i < Length; i++) {
+ *(uint8_t *)(((uint32_t)Dest + j * Length + i) ^ 3) = *(uint8_t *)(((uint32_t)Source + j * Skip + i) ^ 3);
+ }
+ }
+#else
+ if ((Skip & 0x3) == 0) {
+ for (j = 0; j < Count; j++) {
+ memcpy(Dest, Source, Length);
+ Source += Skip;
+ Dest += Length;
+ }
+ } else {
+ for (j = 0 ; j < Count; j++) {
+ for (i = 0 ; i < Length; i++) {
+ *(uint8_t *)(((uint32_t)Dest + i) ^ 3) = *(uint8_t *)(((uint32_t)Source + i) ^ 3);
+ }
+ Source += Skip;
+ Dest += Length;
+ }
+ }
+#endif
+ if ((!RSP_Cpu) && ((SP_MEM_ADDR_REG & 0x1000) != 0)) {
+ RSPSetJumpTable();
+ }
+
+
+
+ SP_DMA_BUSY_REG = 0;
+ SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY;
+}
+
+void RSP_SP_DMA_WRITE (void) {
+ uint32_t i, j, Length, Skip, Count;
+ uint8_t *Dest, *Source;
+
+ SP_DRAM_ADDR_REG &= 0x00FFFFFF;
+
+ if (SP_DRAM_ADDR_REG > 0x800000) {
+ printf("SP DMA WRITE\nSP_DRAM_ADDR_REG not in RDRam space");
+ return;
+ }
+
+ if ((SP_WR_LEN_REG & 0xFFF) + 1 + (SP_MEM_ADDR_REG & 0xFFF) > 0x1000) {
+ printf("SP DMA READ\ncould not fit copy in memory segement\nSP_WR_LEN_REG=%08x\nSP_MEM_ADDR_REG=%08x",SP_WR_LEN_REG,SP_MEM_ADDR_REG);
+ return;
+ }
+
+ Length = ((SP_WR_LEN_REG & 0xFFF) | 7) + 1;
+ Skip = (SP_WR_LEN_REG >> 20) + Length;
+ Count = ((SP_WR_LEN_REG >> 12) & 0xFF) + 1;
+ Dest = RDRAM + (SP_DRAM_ADDR_REG & ~7);
+ Source = DMEM + ((SP_MEM_ADDR_REG & 0x1FFF) & ~7);
+
+#if defined(RSP_SAFE_DMA)
+ for (j = 0 ; j < Count; j++) {
+ for (i = 0 ; i < Length; i++) {
+ *(uint8_t *)(((uint32_t)Dest + j * Skip + i) ^ 3) = *(uint8_t *)(((uint32_t)Source + j * Length + i) ^ 3);
+ }
+ }
+#else
+ if ((Skip & 0x3) == 0) {
+ for (j = 0; j < Count; j++) {
+ memcpy(Dest, Source, Length);
+ Source += Length;
+ Dest += Skip;
+ }
+ } else {
+ for (j = 0 ; j < Count; j++) {
+ for (i = 0 ; i < Length; i++) {
+ *(uint8_t *)(((uint32_t)Dest + i) ^ 3) = *(uint8_t *)(((uint32_t)Source + i) ^ 3);
+ }
+ Source += Length;
+ Dest += Skip;
+ }
+ }
+#endif
+ SP_DMA_BUSY_REG = 0;
+ SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY;
+}
+
+void RSP_LB_DMEM ( uint32_t Addr, uint8_t * Value ) {
+ * Value = *(uint8_t *)(DMEM + ((Addr ^ 3) & 0xFFF)) ;
+}
+
+void RSP_LBV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ RSP_Vect[vect].B[15 - element] = *(DMEM + ((Addr ^ 3) & 0xFFF));
+}
+
+void RSP_LDV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ int32_t length, Count;
+
+ length = 8;
+ if (length > 16 - element) {
+ length = 16 - element;
+ }
+ for (Count = element; Count < (length + element); Count ++ ){
+ RSP_Vect[vect].B[15 - Count] = *(DMEM + ((Addr ^ 3) & 0xFFF));
+ Addr += 1;
+ }
+
+}
+
+void RSP_LFV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ int32_t length, count;
+ VECTOR Temp;
+
+ length = 8;
+ if (length > 16 - element) {
+ length = 16 - element;
+ }
+
+ Temp.HW[7] = *(DMEM + (((Addr + element) ^3) & 0xFFF)) << 7;
+ Temp.HW[6] = *(DMEM + (((Addr + ((0x4 - element) ^ 3) & 0xf)) & 0xFFF)) << 7;
+ Temp.HW[5] = *(DMEM + (((Addr + ((0x8 - element) ^ 3) & 0xf)) & 0xFFF)) << 7;
+ Temp.HW[4] = *(DMEM + (((Addr + ((0xC - element) ^ 3) & 0xf)) & 0xFFF)) << 7;
+ Temp.HW[3] = *(DMEM + (((Addr + ((0x8 - element) ^ 3) & 0xf)) & 0xFFF)) << 7;
+ Temp.HW[2] = *(DMEM + (((Addr + ((0xC - element) ^ 3) & 0xf)) & 0xFFF)) << 7;
+ Temp.HW[1] = *(DMEM + (((Addr + ((0x10 - element) ^ 3) & 0xf)) & 0xFFF)) << 7;
+ Temp.HW[0] = *(DMEM + (((Addr + ((0x4 - element) ^ 3) & 0xf)) & 0xFFF)) << 7;
+
+ for (count = element; count < (length + element); count ++ ){
+ RSP_Vect[vect].B[15 - count] = Temp.B[15 - count];
+ }
+}
+
+void RSP_LH_DMEM ( uint32_t Addr, uint16_t * Value ) {
+ if ((Addr & 0x1) != 0) {
+ if (Addr > 0xFFE) {
+ printf("hmmmm.... Problem with:\nRSP_LH_DMEM");
+ return;
+ }
+ Addr &= 0xFFF;
+ *Value = *(uint8_t *)(DMEM + (Addr^ 3)) << 8;
+ *Value += *(uint8_t *)(DMEM + ((Addr + 1)^ 3));
+ return;
+ }
+ * Value = *(uint16_t *)(DMEM + ((Addr ^ 2 ) & 0xFFF));
+
+}
+
+void RSP_LHV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ RSP_Vect[vect].HW[7] = *(DMEM + ((Addr + ((0x10 - element) & 0xF) ^3) & 0xFFF)) << 7;
+ RSP_Vect[vect].HW[6] = *(DMEM + ((Addr + ((0x10 - element + 2) & 0xF) ^3) & 0xFFF)) << 7;
+ RSP_Vect[vect].HW[5] = *(DMEM + ((Addr + ((0x10 - element + 4) & 0xF) ^3) & 0xFFF)) << 7;
+ RSP_Vect[vect].HW[4] = *(DMEM + ((Addr + ((0x10 - element + 6) & 0xF) ^3) & 0xFFF)) << 7;
+ RSP_Vect[vect].HW[3] = *(DMEM + ((Addr + ((0x10 - element + 8) & 0xF) ^3) & 0xFFF)) << 7;
+ RSP_Vect[vect].HW[2] = *(DMEM + ((Addr + ((0x10 - element + 10) & 0xF) ^3) & 0xFFF)) << 7;
+ RSP_Vect[vect].HW[1] = *(DMEM + ((Addr + ((0x10 - element + 12) & 0xF) ^3) & 0xFFF)) << 7;
+ RSP_Vect[vect].HW[0] = *(DMEM + ((Addr + ((0x10 - element + 14) & 0xF) ^3) & 0xFFF)) << 7;
+}
+
+void RSP_LLV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ int32_t length, Count;
+
+ length = 4;
+ if (length > 16 - element) {
+ length = 16 - element;
+ }
+ for (Count = element; Count < (length + element); Count ++ ){
+ RSP_Vect[vect].B[15 - Count] = *(DMEM + ((Addr ^ 3) & 0xFFF));
+ Addr += 1;
+ }
+
+}
+
+void RSP_LPV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ RSP_Vect[vect].HW[7] = *(DMEM + ((Addr + ((0x10 - element) & 0xF)^3) & 0xFFF)) << 8;
+ RSP_Vect[vect].HW[6] = *(DMEM + ((Addr + ((0x10 - element + 1) & 0xF)^3) & 0xFFF)) << 8;
+ RSP_Vect[vect].HW[5] = *(DMEM + ((Addr + ((0x10 - element + 2) & 0xF)^3) & 0xFFF)) << 8;
+ RSP_Vect[vect].HW[4] = *(DMEM + ((Addr + ((0x10 - element + 3) & 0xF)^3) & 0xFFF)) << 8;
+ RSP_Vect[vect].HW[3] = *(DMEM + ((Addr + ((0x10 - element + 4) & 0xF)^3) & 0xFFF)) << 8;
+ RSP_Vect[vect].HW[2] = *(DMEM + ((Addr + ((0x10 - element + 5) & 0xF)^3) & 0xFFF)) << 8;
+ RSP_Vect[vect].HW[1] = *(DMEM + ((Addr + ((0x10 - element + 6) & 0xF)^3) & 0xFFF)) << 8;
+ RSP_Vect[vect].HW[0] = *(DMEM + ((Addr + ((0x10 - element + 7) & 0xF)^3) & 0xFFF)) << 8;
+}
+
+void RSP_LRV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ int32_t length, Count, offset;
+
+ offset = (Addr & 0xF) - 1;
+ length = (Addr & 0xF) - element;
+ Addr &= 0xFF0;
+ for (Count = element; Count < (length + element); Count ++ ){
+ RSP_Vect[vect].B[offset - Count] = *(DMEM + ((Addr ^ 3) & 0xFFF));
+ Addr += 1;
+ }
+
+}
+
+void RSP_LQV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ int32_t length, Count;
+
+ length = ((Addr + 0x10) & ~0xF) - Addr;
+ if (length > 16 - element) {
+ length = 16 - element;
+ }
+ for (Count = element; Count < (length + element); Count ++ ){
+ RSP_Vect[vect].B[15 - Count] = *(DMEM + ((Addr ^ 3) & 0xFFF));
+ Addr += 1;
+ }
+
+}
+
+void RSP_LSV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ int32_t length, Count;
+
+ length = 2;
+ if (length > 16 - element) {
+ length = 16 - element;
+ }
+ for (Count = element; Count < (length + element); Count ++ ){
+ RSP_Vect[vect].B[15 - Count] = *(DMEM + ((Addr ^ 3) & 0xFFF));
+ Addr += 1;
+ }
+}
+
+void RSP_LTV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ int32_t del, count, length;
+
+ length = 8;
+ if (length > 32 - vect) {
+ length = 32 - vect;
+ }
+
+ Addr = ((Addr + 8) & 0xFF0) + (element & 0x1);
+ for (count = 0; count < length; count ++) {
+ del = ((8 - (element >> 1) + count) << 1) & 0xF;
+ RSP_Vect[vect + count].B[15 - del] = *(DMEM + (Addr ^ 3));
+ RSP_Vect[vect + count].B[14 - del] = *(DMEM + ((Addr + 1) ^ 3));
+ Addr += 2;
+ }
+}
+
+void RSP_LUV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ RSP_Vect[vect].HW[7] = *(DMEM + ((Addr + ((0x10 - element) & 0xF)^3) & 0xFFF)) << 7;
+ RSP_Vect[vect].HW[6] = *(DMEM + ((Addr + ((0x10 - element + 1) & 0xF)^3) & 0xFFF)) << 7;
+ RSP_Vect[vect].HW[5] = *(DMEM + ((Addr + ((0x10 - element + 2) & 0xF)^3) & 0xFFF)) << 7;
+ RSP_Vect[vect].HW[4] = *(DMEM + ((Addr + ((0x10 - element + 3) & 0xF)^3) & 0xFFF)) << 7;
+ RSP_Vect[vect].HW[3] = *(DMEM + ((Addr + ((0x10 - element + 4) & 0xF)^3) & 0xFFF)) << 7;
+ RSP_Vect[vect].HW[2] = *(DMEM + ((Addr + ((0x10 - element + 5) & 0xF)^3) & 0xFFF)) << 7;
+ RSP_Vect[vect].HW[1] = *(DMEM + ((Addr + ((0x10 - element + 6) & 0xF)^3) & 0xFFF)) << 7;
+ RSP_Vect[vect].HW[0] = *(DMEM + ((Addr + ((0x10 - element + 7) & 0xF)^3) & 0xFFF)) << 7;
+}
+
+void RSP_LW_DMEM ( uint32_t Addr, uint32_t * Value ) {
+ if ((Addr & 0x3) != 0) {
+ Addr &= 0xFFF;
+ if (Addr > 0xFFC) {
+ printf("hmmmm.... Problem with:\nRSP_LW_DMEM");
+ return;
+ }
+ *Value = *(uint8_t *)(DMEM + (Addr^ 3)) << 0x18;
+ *Value += *(uint8_t *)(DMEM + ((Addr + 1)^ 3)) << 0x10;
+ *Value += *(uint8_t *)(DMEM + ((Addr + 2)^ 3)) << 8;
+ *Value += *(uint8_t *)(DMEM + ((Addr + 3)^ 3));
+ return;
+ }
+ * Value = *(uint32_t *)(DMEM + (Addr & 0xFFF));
+}
+
+void RSP_LW_IMEM ( uint32_t Addr, uint32_t * Value ) {
+ if ((Addr & 0x3) != 0) {
+ printf("Unaligned RSP_LW_IMEM");
+ }
+ * Value = *(uint32_t *)(IMEM + (Addr & 0xFFF));
+}
+
+void RSP_SB_DMEM ( uint32_t Addr, uint8_t Value ) {
+ *(uint8_t *)(DMEM + ((Addr ^ 3) & 0xFFF)) = Value;
+}
+
+void RSP_SBV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ *(DMEM + ((Addr ^ 3) & 0xFFF)) = RSP_Vect[vect].B[15 - element];
+}
+
+void RSP_SDV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ int32_t Count;
+
+ for (Count = element; Count < (8 + element); Count ++ ){
+ *(DMEM + ((Addr ^ 3) & 0xFFF)) = RSP_Vect[vect].B[15 - (Count & 0xF)];
+ Addr += 1;
+ }
+}
+
+void RSP_SFV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ int32_t offset = Addr & 0xF;
+ Addr &= 0xFF0;
+
+ switch (element) {
+ case 0:
+ *(DMEM + ((Addr + offset)^3)) = RSP_Vect[vect].UHW[7] >> 7;
+ *(DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = RSP_Vect[vect].UHW[6] >> 7;
+ *(DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = RSP_Vect[vect].UHW[5] >> 7;
+ *(DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = RSP_Vect[vect].UHW[4] >> 7;
+ break;
+ case 1:
+ *(DMEM + ((Addr + offset)^3)) = RSP_Vect[vect].UHW[1] >> 7;
+ *(DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = RSP_Vect[vect].UHW[0] >> 7;
+ *(DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = RSP_Vect[vect].UHW[3] >> 7;
+ *(DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = RSP_Vect[vect].UHW[2] >> 7;
+ break;
+ case 2:
+ *(DMEM + ((Addr + offset)^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = 0;
+ break;
+ case 3:
+ *(DMEM + ((Addr + offset)^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 12) & 0xF)^3))) = 0;
+ break;
+ case 4:
+ *(DMEM + ((Addr + offset)^3)) = RSP_Vect[vect].UHW[6] >> 7;
+ *(DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = RSP_Vect[vect].UHW[5] >> 7;
+ *(DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = RSP_Vect[vect].UHW[4] >> 7;
+ *(DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = RSP_Vect[vect].UHW[7] >> 7;
+ break;
+ case 5:
+ *(DMEM + ((Addr + offset)^3)) = RSP_Vect[vect].UHW[0] >> 7;
+ *(DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = RSP_Vect[vect].UHW[3] >> 7;
+ *(DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = RSP_Vect[vect].UHW[2] >> 7;
+ *(DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = RSP_Vect[vect].UHW[1] >> 7;
+ break;
+ case 6:
+ *(DMEM + ((Addr + offset)^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = 0;
+ break;
+ case 7:
+ *(DMEM + ((Addr + offset)^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = 0;
+ break;
+ case 8:
+ *(DMEM + ((Addr + offset)^3)) = RSP_Vect[vect].UHW[3] >> 7;
+ *(DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = RSP_Vect[vect].UHW[2] >> 7;
+ *(DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = RSP_Vect[vect].UHW[1] >> 7;
+ *(DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = RSP_Vect[vect].UHW[0] >> 7;
+ break;
+ case 9:
+ *(DMEM + ((Addr + offset)^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = 0;
+ break;
+ case 10:
+ *(DMEM + ((Addr + offset)^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = 0;
+ break;
+ case 11:
+ *(DMEM + ((Addr + offset)^3)) = RSP_Vect[vect].UHW[4] >> 7;
+ *(DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = RSP_Vect[vect].UHW[7] >> 7;
+ *(DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = RSP_Vect[vect].UHW[6] >> 7;
+ *(DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = RSP_Vect[vect].UHW[5] >> 7;
+ break;
+ case 12:
+ *(DMEM + ((Addr + offset)^3)) = RSP_Vect[vect].UHW[2] >> 7;
+ *(DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = RSP_Vect[vect].UHW[1] >> 7;
+ *(DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = RSP_Vect[vect].UHW[0] >> 7;
+ *(DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = RSP_Vect[vect].UHW[3] >> 7;
+ break;
+ case 13:
+ *(DMEM + ((Addr + offset)^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = 0;
+ break;
+ case 14:
+ *(DMEM + ((Addr + offset)^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = 0;
+ *(DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = 0;
+ break;
+ case 15:
+ *(DMEM + ((Addr + offset)^3)) = RSP_Vect[vect].UHW[7] >> 7;
+ *(DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = RSP_Vect[vect].UHW[6] >> 7;
+ *(DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = RSP_Vect[vect].UHW[5] >> 7;
+ *(DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = RSP_Vect[vect].UHW[4] >> 7;
+ break;
+ }
+}
+
+void RSP_SH_DMEM ( uint32_t Addr, uint16_t Value ) {
+ if ((Addr & 0x1) != 0) {
+ printf("Unaligned RSP_SH_DMEM");
+ return;
+ }
+ *(uint16_t *)(DMEM + ((Addr ^ 2) & 0xFFF)) = Value;
+}
+
+void RSP_SHV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ *(DMEM + ((Addr^3) & 0xFFF)) = (RSP_Vect[vect].UB[(15 - element) & 0xF] << 1) +
+ (RSP_Vect[vect].UB[(14 - element) & 0xF] >> 7);
+ *(DMEM + (((Addr + 2)^3) & 0xFFF)) = (RSP_Vect[vect].UB[(13 - element) & 0xF] << 1) +
+ (RSP_Vect[vect].UB[(12 - element) & 0xF] >> 7);
+ *(DMEM + (((Addr + 4)^3) & 0xFFF)) = (RSP_Vect[vect].UB[(11 - element) & 0xF] << 1) +
+ (RSP_Vect[vect].UB[(10 - element) & 0xF] >> 7);
+ *(DMEM + (((Addr + 6)^3) & 0xFFF)) = (RSP_Vect[vect].UB[(9 - element) & 0xF] << 1) +
+ (RSP_Vect[vect].UB[(8 - element) & 0xF] >> 7);
+ *(DMEM + (((Addr + 8)^3) & 0xFFF)) = (RSP_Vect[vect].UB[(7 - element) & 0xF] << 1) +
+ (RSP_Vect[vect].UB[(6 - element) & 0xF] >> 7);
+ *(DMEM + (((Addr + 10)^3) & 0xFFF)) = (RSP_Vect[vect].UB[(5 - element) & 0xF] << 1) +
+ (RSP_Vect[vect].UB[(4 - element) & 0xF] >> 7);
+ *(DMEM + (((Addr + 12)^3) & 0xFFF)) = (RSP_Vect[vect].UB[(3 - element) & 0xF] << 1) +
+ (RSP_Vect[vect].UB[(2 - element) & 0xF] >> 7);
+ *(DMEM + (((Addr + 14)^3) & 0xFFF)) = (RSP_Vect[vect].UB[(1 - element) & 0xF] << 1) +
+ (RSP_Vect[vect].UB[(0 - element) & 0xF] >> 7);
+}
+
+void RSP_SLV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ int32_t Count;
+
+ for (Count = element; Count < (4 + element); Count ++ ){
+ *(DMEM + ((Addr ^3) & 0xFFF)) = RSP_Vect[vect].B[15 - (Count & 0xF)];
+ Addr += 1;
+ }
+}
+
+void RSP_SPV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ int32_t Count;
+
+ for (Count = element; Count < (8 + element); Count ++ ){
+ if (((Count) & 0xF) < 8) {
+ *(DMEM + ((Addr ^ 3) & 0xFFF)) = RSP_Vect[vect].UB[15 - ((Count & 0xF) << 1)];
+ } else {
+ *(DMEM + ((Addr ^ 3) & 0xFFF)) = (RSP_Vect[vect].UB[15 - ((Count & 0x7) << 1)] << 1) +
+ (RSP_Vect[vect].UB[14 - ((Count & 0x7) << 1)] >> 7);
+ }
+ Addr += 1;
+ }
+}
+
+void RSP_SQV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ int32_t length, Count;
+
+ length = ((Addr + 0x10) & ~0xF) - Addr;
+ for (Count = element; Count < (length + element); Count ++ ){
+ *(DMEM + ((Addr ^ 3) & 0xFFF)) = RSP_Vect[vect].B[15 - (Count & 0xF)];
+ Addr += 1;
+ }
+}
+
+void RSP_SRV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ int32_t length, Count, offset;
+
+ length = (Addr & 0xF);
+ offset = (0x10 - length) & 0xF;
+ Addr &= 0xFF0;
+ for (Count = element; Count < (length + element); Count ++ ){
+ *(DMEM + ((Addr ^ 3) & 0xFFF)) = RSP_Vect[vect].B[15 - ((Count + offset) & 0xF)];
+ Addr += 1;
+ }
+}
+
+void RSP_SSV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ int32_t Count;
+
+ for (Count = element; Count < (2 + element); Count ++ ){
+ *(DMEM + ((Addr ^ 3) & 0xFFF)) = RSP_Vect[vect].B[15 - (Count & 0xF)];
+ Addr += 1;
+ }
+}
+
+void RSP_STV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ int32_t del, count, length;
+
+ length = 8;
+ if (length > 32 - vect) {
+ length = 32 - vect;
+ }
+ length = length << 1;
+ del = element >> 1;
+ for (count = 0; count < length; count += 2) {
+ *(DMEM + ((Addr ^ 3) & 0xFFF)) = RSP_Vect[vect + del].UB[15 - count];
+ *(DMEM + (((Addr + 1) ^ 3) & 0xFFF)) = RSP_Vect[vect + del].UB[14 - count];
+ del = (del + 1) & 7;
+ Addr += 2;
+ }
+}
+
+void RSP_SUV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ int32_t Count;
+
+ for (Count = element; Count < (8 + element); Count ++ ){
+ if (((Count) & 0xF) < 8) {
+ *(DMEM + ((Addr ^ 3) & 0xFFF)) = (RSP_Vect[vect].UB[15 - ((Count & 0x7) << 1)] << 1) +
+ (RSP_Vect[vect].UB[14 - ((Count & 0x7) << 1)] >> 7);
+ } else {
+ *(DMEM + ((Addr ^ 3) & 0xFFF)) = RSP_Vect[vect].UB[15 - ((Count & 0x7) << 1)];
+ }
+ Addr += 1;
+ }
+}
+
+void RSP_SW_DMEM ( uint32_t Addr, uint32_t Value ) {
+ Addr &= 0xFFF;
+
+ if ((Addr & 0x3) != 0) {
+ if (Addr > 0xFFC) {
+ printf("hmmmm.... Problem with:\nRSP_SW_DMEM");
+ return;
+ }
+ *(uint8_t *)(DMEM + (Addr ^ 3)) = (uint8_t)(Value >> 0x18);
+ *(uint8_t *)(DMEM + ((Addr + 1) ^ 3)) = (uint8_t)(Value >> 0x10);
+ *(uint8_t *)(DMEM + ((Addr + 2) ^ 3)) = (uint8_t)(Value >> 0x8);
+ *(uint8_t *)(DMEM + ((Addr + 3) ^ 3)) = (uint8_t)(Value);
+ return;
+ }
+ *(uint32_t *)(DMEM + Addr) = Value;
+}
+
+void RSP_SWV_DMEM ( uint32_t Addr, int32_t vect, int32_t element ) {
+ int32_t Count, offset;
+
+ offset = Addr & 0xF;
+ Addr &= 0xFF0;
+ for (Count = element; Count < (16 + element); Count ++ ){
+ *(DMEM + ((Addr + (offset & 0xF)) ^ 3)) = RSP_Vect[vect].B[15 - (Count & 0xF)];
+ offset += 1;
+ }
+}
+
+int runcount = 0;
+
+int32_t init_rsp(void)
+{
+
+
+ int32_t i = 0, CpuFeatures = 0;
+ runcount++;
+
+ RSP_Running = 0;
+
+
+ NoOfMaps = 0;
+ Table = 0;
+ ConditionalMove = 0;
+
+
+ RSP_NextInstruction = 0;
+ RSP_JumpTo = 0;
+
+ dwBuffer = MainBuffer;
+
+ pLastSecondary == NULL;
+ pLastPrimary = NULL;
+ RSPBlockID = 1;
+
+ memset(RSP_GPR,0,sizeof(RSP_GPR));
+ memset(RSP_Vect,0,sizeof(RSP_Vect));
+ memset(RSP_ACCUM,0,sizeof(RSP_ACCUM));
+ memset(RSP_Flags,0,sizeof(RSP_Flags));
+
+ for(i = 0; i < 64; i++) {
+ RSP_Opcode[i]= rsp_UnknownOpcode;
+ RSP_RegImm[i>>1]= rsp_UnknownOpcode;
+ RSP_Special[i]= rsp_UnknownOpcode;
+ RSP_Cop0[i>>1]= rsp_UnknownOpcode;
+ RSP_Cop2[i>>1]= rsp_UnknownOpcode;
+ RSP_Vector[i] = rsp_UnknownOpcode;
+ RSP_Lc2[i>>1] = rsp_UnknownOpcode;
+ RSP_Sc2[i>>1] = rsp_UnknownOpcode;
+ }
+
+
+ RSP_Opcode[ 0] = RSP_Opcode_SPECIAL;
+ RSP_Opcode[ 1] = RSP_Opcode_REGIMM;
+ RSP_Opcode[ 2] = RSP_Opcode_J;
+ RSP_Opcode[ 3] = RSP_Opcode_JAL;
+ RSP_Opcode[ 4] = RSP_Opcode_BEQ;
+ RSP_Opcode[ 5] = RSP_Opcode_BNE;
+ RSP_Opcode[ 6] = RSP_Opcode_BLEZ;
+ RSP_Opcode[ 7] = RSP_Opcode_BGTZ;
+ RSP_Opcode[ 8] = RSP_Opcode_ADDI;
+ RSP_Opcode[ 9] = RSP_Opcode_ADDIU;
+ RSP_Opcode[10] = RSP_Opcode_SLTI;
+ RSP_Opcode[11] = RSP_Opcode_SLTIU;
+ RSP_Opcode[12] = RSP_Opcode_ANDI;
+ RSP_Opcode[13] = RSP_Opcode_ORI;
+ RSP_Opcode[14] = RSP_Opcode_XORI;
+ RSP_Opcode[15] = RSP_Opcode_LUI;
+ RSP_Opcode[16] = RSP_Opcode_COP0;
+ RSP_Opcode[18] = RSP_Opcode_COP2;
+ RSP_Opcode[32] = RSP_Opcode_LB;
+ RSP_Opcode[33] = RSP_Opcode_LH;
+ RSP_Opcode[35] = RSP_Opcode_LW;
+ RSP_Opcode[36] = RSP_Opcode_LBU;
+ RSP_Opcode[37] = RSP_Opcode_LHU;
+ RSP_Opcode[40] = RSP_Opcode_SB;
+ RSP_Opcode[41] = RSP_Opcode_SH;
+ RSP_Opcode[43] = RSP_Opcode_SW;
+ RSP_Opcode[50] = RSP_Opcode_LC2;
+ RSP_Opcode[58] = RSP_Opcode_SC2;
+
+ RSP_Special[ 0] = RSP_Special_SLL;
+ RSP_Special[ 2] = RSP_Special_SRL;
+ RSP_Special[ 3] = RSP_Special_SRA;
+ RSP_Special[ 4] = RSP_Special_SLLV;
+ RSP_Special[ 6] = RSP_Special_SRLV;
+ RSP_Special[ 7] = RSP_Special_SRAV;
+ RSP_Special[ 8] = RSP_Special_JR;
+ RSP_Special[ 9] = RSP_Special_JALR;
+ RSP_Special[13] = RSP_Special_BREAK;
+ RSP_Special[32] = RSP_Special_ADD;
+ RSP_Special[33] = RSP_Special_ADDU;
+ RSP_Special[34] = RSP_Special_SUB;
+ RSP_Special[35] = RSP_Special_SUBU;
+ RSP_Special[36] = RSP_Special_AND;
+ RSP_Special[37] = RSP_Special_OR;
+ RSP_Special[38] = RSP_Special_XOR;
+ RSP_Special[39] = RSP_Special_NOR;
+ RSP_Special[42] = RSP_Special_SLT;
+ RSP_Special[43] = RSP_Special_SLTU;
+
+ RSP_RegImm[ 0] = RSP_Opcode_BLTZ;
+ RSP_RegImm[ 1] = RSP_Opcode_BGEZ;
+ RSP_RegImm[16] = RSP_Opcode_BLTZAL;
+
+ RSP_Cop0[ 0] = RSP_Cop0_MF;
+ RSP_Cop0[ 4] = RSP_Cop0_MT;
+
+ RSP_Cop2[ 0] = RSP_Cop2_MF;
+ RSP_Cop2[ 2] = RSP_Cop2_CF;
+ RSP_Cop2[ 4] = RSP_Cop2_MT;
+ RSP_Cop2[ 6] = RSP_Cop2_CT;
+ RSP_Cop2[16] = RSP_COP2_VECTOR;
+ RSP_Cop2[17] = RSP_COP2_VECTOR;
+ RSP_Cop2[18] = RSP_COP2_VECTOR;
+ RSP_Cop2[19] = RSP_COP2_VECTOR;
+ RSP_Cop2[20] = RSP_COP2_VECTOR;
+ RSP_Cop2[21] = RSP_COP2_VECTOR;
+ RSP_Cop2[22] = RSP_COP2_VECTOR;
+ RSP_Cop2[23] = RSP_COP2_VECTOR;
+ RSP_Cop2[24] = RSP_COP2_VECTOR;
+ RSP_Cop2[25] = RSP_COP2_VECTOR;
+ RSP_Cop2[26] = RSP_COP2_VECTOR;
+ RSP_Cop2[27] = RSP_COP2_VECTOR;
+ RSP_Cop2[28] = RSP_COP2_VECTOR;
+ RSP_Cop2[29] = RSP_COP2_VECTOR;
+ RSP_Cop2[30] = RSP_COP2_VECTOR;
+ RSP_Cop2[31] = RSP_COP2_VECTOR;
+
+ RSP_Vector[ 0] = RSP_Vector_VMULF;
+ RSP_Vector[ 1] = RSP_Vector_VMULU;
+ RSP_Vector[ 4] = RSP_Vector_VMUDL;
+ RSP_Vector[ 5] = RSP_Vector_VMUDM;
+ RSP_Vector[ 6] = RSP_Vector_VMUDN;
+ RSP_Vector[ 7] = RSP_Vector_VMUDH;
+ RSP_Vector[ 8] = RSP_Vector_VMACF;
+ RSP_Vector[ 9] = RSP_Vector_VMACU;
+ RSP_Vector[11] = RSP_Vector_VMACQ;
+ RSP_Vector[12] = RSP_Vector_VMADL;
+ RSP_Vector[13] = RSP_Vector_VMADM;
+ RSP_Vector[14] = RSP_Vector_VMADN;
+ RSP_Vector[15] = RSP_Vector_VMADH;
+ RSP_Vector[16] = RSP_Vector_VADD;
+ RSP_Vector[17] = RSP_Vector_VSUB;
+ RSP_Vector[19] = RSP_Vector_VABS;
+ RSP_Vector[20] = RSP_Vector_VADDC;
+ RSP_Vector[21] = RSP_Vector_VSUBC;
+ RSP_Vector[29] = RSP_Vector_VSAW;
+ RSP_Vector[32] = RSP_Vector_VLT;
+ RSP_Vector[33] = RSP_Vector_VEQ;
+ RSP_Vector[34] = RSP_Vector_VNE;
+ RSP_Vector[35] = RSP_Vector_VGE;
+ RSP_Vector[36] = RSP_Vector_VCL;
+ RSP_Vector[37] = RSP_Vector_VCH;
+ RSP_Vector[38] = RSP_Vector_VCR;
+ RSP_Vector[39] = RSP_Vector_VMRG;
+ RSP_Vector[40] = RSP_Vector_VAND;
+ RSP_Vector[41] = RSP_Vector_VNAND;
+ RSP_Vector[42] = RSP_Vector_VOR;
+ RSP_Vector[43] = RSP_Vector_VNOR;
+ RSP_Vector[44] = RSP_Vector_VXOR;
+ RSP_Vector[45] = RSP_Vector_VNXOR;
+ RSP_Vector[48] = RSP_Vector_VRCP;
+ RSP_Vector[49] = RSP_Vector_VRCPL;
+ RSP_Vector[50] = RSP_Vector_VRCPH;
+ RSP_Vector[51] = RSP_Vector_VMOV;
+ RSP_Vector[52] = RSP_Vector_VRSQ;
+ RSP_Vector[53] = RSP_Vector_VRSQL;
+ RSP_Vector[54] = RSP_Vector_VRSQH;
+ RSP_Vector[55] = RSP_Vector_VNOOP;
+
+ RSP_Lc2[ 0] = RSP_Opcode_LBV;
+ RSP_Lc2[ 1] = RSP_Opcode_LSV;
+ RSP_Lc2[ 2] = RSP_Opcode_LLV;
+ RSP_Lc2[ 3] = RSP_Opcode_LDV;
+ RSP_Lc2[ 4] = RSP_Opcode_LQV;
+ RSP_Lc2[ 5] = RSP_Opcode_LRV;
+ RSP_Lc2[ 6] = RSP_Opcode_LPV;
+ RSP_Lc2[ 7] = RSP_Opcode_LUV;
+ RSP_Lc2[ 8] = RSP_Opcode_LHV;
+ RSP_Lc2[ 9] = RSP_Opcode_LFV;
+ RSP_Lc2[11] = RSP_Opcode_LTV;
+
+ RSP_Sc2[ 0] = RSP_Opcode_SBV;
+ RSP_Sc2[ 1] = RSP_Opcode_SSV;
+ RSP_Sc2[ 2] = RSP_Opcode_SLV;
+ RSP_Sc2[ 3] = RSP_Opcode_SDV;
+ RSP_Sc2[ 4] = RSP_Opcode_SQV;
+ RSP_Sc2[ 5] = RSP_Opcode_SRV;
+ RSP_Sc2[ 6] = RSP_Opcode_SPV;
+ RSP_Sc2[ 7] = RSP_Opcode_SUV;
+ RSP_Sc2[ 8] = RSP_Opcode_SHV;
+ RSP_Sc2[ 9] = RSP_Opcode_SFV;
+ RSP_Sc2[10] = RSP_Opcode_SWV;
+ RSP_Sc2[11] = RSP_Opcode_STV;
+
+ EleSpec[ 0].DW = 0;
+ EleSpec[ 1].DW = 0;
+ EleSpec[ 2].DW = 0;
+ EleSpec[ 3].DW = 0;
+ EleSpec[ 4].DW = 0;
+ EleSpec[ 5].DW = 0;
+ EleSpec[ 6].DW = 0;
+ EleSpec[ 7].DW = 0;
+ EleSpec[ 8].DW = 0;
+ EleSpec[ 9].DW = 0;
+ EleSpec[10].DW = 0;
+ EleSpec[11].DW = 0;
+ EleSpec[12].DW = 0;
+ EleSpec[13].DW = 0;
+ EleSpec[14].DW = 0;
+ EleSpec[15].DW = 0;
+ EleSpec[16].DW = 0x0001020304050607ULL; /* None */
+ EleSpec[17].DW = 0x0001020304050607ULL; /* None */
+ EleSpec[18].DW = 0x0000020204040606ULL; /* 0q */
+ EleSpec[19].DW = 0x0101030305050707ULL; /* 1q */
+ EleSpec[20].DW = 0x0000000004040404ULL; /* 0h */
+ EleSpec[21].DW = 0x0101010105050505ULL; /* 1h */
+ EleSpec[22].DW = 0x0202020206060606ULL; /* 2h */
+ EleSpec[23].DW = 0x0303030307070707ULL; /* 3h */
+ EleSpec[24].DW = 0x0000000000000000ULL; /* 0 */
+ EleSpec[25].DW = 0x0101010101010101ULL; /* 1 */
+ EleSpec[26].DW = 0x0202020202020202ULL; /* 2 */
+ EleSpec[27].DW = 0x0303030303030303ULL; /* 3 */
+ EleSpec[28].DW = 0x0404040404040404ULL; /* 4 */
+ EleSpec[29].DW = 0x0505050505050505ULL; /* 5 */
+ EleSpec[30].DW = 0x0606060606060606ULL; /* 6 */
+ EleSpec[31].DW = 0x0707070707070707ULL; /* 7 */
+
+ Indx[ 0].DW = 0;
+ Indx[ 1].DW = 0;
+ Indx[ 2].DW = 0;
+ Indx[ 3].DW = 0;
+ Indx[ 4].DW = 0;
+ Indx[ 5].DW = 0;
+ Indx[ 6].DW = 0;
+ Indx[ 7].DW = 0;
+ Indx[ 8].DW = 0;
+ Indx[ 9].DW = 0;
+ Indx[10].DW = 0;
+ Indx[11].DW = 0;
+ Indx[12].DW = 0;
+ Indx[13].DW = 0;
+ Indx[14].DW = 0;
+ Indx[15].DW = 0;
+
+ Indx[16].DW = 0x0001020304050607ULL; /* None */
+ Indx[17].DW = 0x0001020304050607ULL; /* None */
+ Indx[18].DW = 0x0103050700020406ULL; /* 0q */
+ Indx[19].DW = 0x0002040601030507ULL; /* 1q */
+ Indx[20].DW = 0x0102030506070004ULL; /* 0h */
+ Indx[21].DW = 0x0002030406070105ULL; /* 1h */
+ Indx[22].DW = 0x0001030405070206ULL; /* 2h */
+ Indx[23].DW = 0x0001020405060307ULL; /* 3h */
+ Indx[24].DW = 0x0102030405060700ULL; /* 0 */
+ Indx[25].DW = 0x0002030405060701ULL; /* 1 */
+ Indx[26].DW = 0x0001030405060702ULL; /* 2 */
+ Indx[27].DW = 0x0001020405060703ULL; /* 3 */
+ Indx[28].DW = 0x0001020305060704ULL; /* 4 */
+ Indx[29].DW = 0x0001020304060705ULL; /* 5 */
+ Indx[30].DW = 0x0001020304050706ULL; /* 6 */
+ Indx[31].DW = 0x0001020304050607ULL; /* 7 */
+
+ for (i = 16; i < 32; i ++) {
+ int32_t count;
+
+ for (count = 0; count < 8; count ++) {
+ Indx[i].B[count] = 7 - Indx[i].B[count];
+ EleSpec[i].B[count] = 7 - EleSpec[i].B[count];
+ }
+ for (count = 0; count < 4; count ++) {
+ uint8_t Temp;
+
+ Temp = Indx[i].B[count];
+ Indx[i].B[count] = Indx[i].B[7 - count];
+ Indx[i].B[7 - count] = Temp;
+ }
+ }
+
+ PrgCount = &SP_PC_REG;
+
+ memset(&Compiler, 0, sizeof(Compiler));
+
+ Compiler.bAlignGPR = 1;
+ Compiler.bAlignVector = 1;
+ Compiler.bFlags = 1;
+ Compiler.bReOrdering = 1;
+ Compiler.bSections = 0; //do i really need to do this?
+ Compiler.bDest = 1;
+ Compiler.bAccum = 1;
+ Compiler.bGPRConstants = 1;
+
+ if(!fake_seek_stopping) {
+ RSPAllocateMemory();
+ } else {
+ RSPReInitMemory();
+ }
+
+ memset(RSP_GPR,0,sizeof(RSP_GPR));
+ memset(RSP_Vect,0,sizeof(RSP_Vect));
+
+#ifndef USEX64
+ asm volatile("push %%ebx; mov $1, %%eax; cpuid; pop %%ebx" : : "a"(CpuFeatures) : "edx","ecx");
+#else
+ asm volatile("push %%rbx; mov $1, %%eax; cpuid; pop %%rbx" : : "a"(CpuFeatures) : "rdx","rcx");
+#endif
+
+
+ Compiler.mmx2 = CpuFeatures & 0x4000000;
+ Compiler.sse = CpuFeatures & 0x2000000;
+ Compiler.mmx = CpuFeatures & 0x800000;
+
+ if(!RSP_Cpu)
+ BuildRecompilerCPU();
+
+ ClearAllx86Code();
+
+}
+
+void RSPSetJumpTable (void) {
+ uint32_t CRC, count;
+
+ CRC = 0;
+ for (count = 0; count < 0x800; count += 0x40) {
+ CRC += *(uint32_t *)(IMEM + count);
+ }
+
+ for (count = 0; count < NoOfMaps; count++ ) {
+ if (CRC == MapsCRC[count]) {
+ RSPJumpTable = (void **)(RSPJumpTables + (count * (sizeof(void*) * 0x400)));
+ Table = count;
+ return;
+ }
+ }
+
+ if (NoOfMaps == MaxMaps) {
+ DisplayError("Used up all the Jump tables in the rsp");
+ StopEmulation();
+ }
+
+ MapsCRC[NoOfMaps] = CRC;
+
+ RSPJumpTable = (void **)(RSPJumpTables + (NoOfMaps * (sizeof(void*) * 0x400) ));
+ Table = NoOfMaps;
+ NoOfMaps += 1;
+}
diff --git a/src/usf/rsp.h b/src/usf/rsp.h new file mode 100644 index 0000000..2921dea --- /dev/null +++ b/src/usf/rsp.h @@ -0,0 +1,423 @@ +#ifndef _RSP_H_
+#define _RSP_H_
+
+#include <stdint.h>
+#include <string.h>
+#include <math.h>
+#include "types.h"
+
+#define CPU_Message(...)
+//#define DisplayError printf
+
+#pragma pack(push,1)
+
+typedef struct tagOPCODE {
+ union {
+
+ uint32_t Hex;
+ uint8_t Ascii[4];
+
+ struct {
+ unsigned offset : 16;
+ unsigned rt : 5;
+ unsigned rs : 5;
+ unsigned op : 6;
+ };
+
+ struct {
+ unsigned immediate : 16;
+ unsigned : 5;
+ unsigned base : 5;
+ unsigned : 6;
+ };
+
+ struct {
+ unsigned target : 26;
+ unsigned : 6;
+ };
+
+ struct {
+ unsigned funct : 6;
+ unsigned sa : 5;
+ unsigned rd : 5;
+ unsigned : 5;
+ unsigned : 5;
+ unsigned : 6;
+ };
+
+ struct {
+ signed voffset : 7;
+ unsigned del : 4;
+ unsigned : 5;
+ unsigned dest : 5;
+ unsigned : 5;
+ unsigned : 6;
+ };
+
+ };
+} RSPOPCODE;
+
+#pragma pack(pop)
+
+#define REGISTER32 MIPS_WORD
+#define REGISTER MIPS_DWORD
+
+
+//RSP OpCodes
+#define RSP_SPECIAL 0
+#define RSP_REGIMM 1
+#define RSP_J 2
+#define RSP_JAL 3
+#define RSP_BEQ 4
+#define RSP_BNE 5
+#define RSP_BLEZ 6
+#define RSP_BGTZ 7
+#define RSP_ADDI 8
+#define RSP_ADDIU 9
+#define RSP_SLTI 10
+#define RSP_SLTIU 11
+#define RSP_ANDI 12
+#define RSP_ORI 13
+#define RSP_XORI 14
+#define RSP_LUI 15
+#define RSP_CP0 16
+#define RSP_CP2 18
+#define RSP_LB 32
+#define RSP_LH 33
+#define RSP_LW 35
+#define RSP_LBU 36
+#define RSP_LHU 37
+#define RSP_SB 40
+#define RSP_SH 41
+#define RSP_SW 43
+#define RSP_LC2 50
+#define RSP_SC2 58
+
+/* RSP Special opcodes */
+#define RSP_SPECIAL_SLL 0
+#define RSP_SPECIAL_SRL 2
+#define RSP_SPECIAL_SRA 3
+#define RSP_SPECIAL_SLLV 4
+#define RSP_SPECIAL_SRLV 6
+#define RSP_SPECIAL_SRAV 7
+#define RSP_SPECIAL_JR 8
+#define RSP_SPECIAL_JALR 9
+#define RSP_SPECIAL_BREAK 13
+#define RSP_SPECIAL_ADD 32
+#define RSP_SPECIAL_ADDU 33
+#define RSP_SPECIAL_SUB 34
+#define RSP_SPECIAL_SUBU 35
+#define RSP_SPECIAL_AND 36
+#define RSP_SPECIAL_OR 37
+#define RSP_SPECIAL_XOR 38
+#define RSP_SPECIAL_NOR 39
+#define RSP_SPECIAL_SLT 42
+#define RSP_SPECIAL_SLTU 43
+
+/* RSP RegImm opcodes */
+#define RSP_REGIMM_BLTZ 0
+#define RSP_REGIMM_BGEZ 1
+#define RSP_REGIMM_BLTZAL 16
+#define RSP_REGIMM_BGEZAL 17
+
+/* RSP COP0 opcodes */
+#define RSP_COP0_MF 0
+#define RSP_COP0_MT 4
+
+/* RSP COP2 opcodes */
+#define RSP_COP2_MF 0
+#define RSP_COP2_CF 2
+#define RSP_COP2_MT 4
+#define RSP_COP2_CT 6
+
+/* RSP Vector opcodes */
+#define RSP_VECTOR_VMULF 0
+#define RSP_VECTOR_VMULU 1
+#define RSP_VECTOR_VRNDP 2
+#define RSP_VECTOR_VMULQ 3
+#define RSP_VECTOR_VMUDL 4
+#define RSP_VECTOR_VMUDM 5
+#define RSP_VECTOR_VMUDN 6
+#define RSP_VECTOR_VMUDH 7
+#define RSP_VECTOR_VMACF 8
+#define RSP_VECTOR_VMACU 9
+#define RSP_VECTOR_VRNDN 10
+#define RSP_VECTOR_VMACQ 11
+#define RSP_VECTOR_VMADL 12
+#define RSP_VECTOR_VMADM 13
+#define RSP_VECTOR_VMADN 14
+#define RSP_VECTOR_VMADH 15
+#define RSP_VECTOR_VADD 16
+#define RSP_VECTOR_VSUB 17
+#define RSP_VECTOR_VABS 19
+#define RSP_VECTOR_VADDC 20
+#define RSP_VECTOR_VSUBC 21
+#define RSP_VECTOR_VSAW 29
+#define RSP_VECTOR_VLT 32
+#define RSP_VECTOR_VEQ 33
+#define RSP_VECTOR_VNE 34
+#define RSP_VECTOR_VGE 35
+#define RSP_VECTOR_VCL 36
+#define RSP_VECTOR_VCH 37
+#define RSP_VECTOR_VCR 38
+#define RSP_VECTOR_VMRG 39
+#define RSP_VECTOR_VAND 40
+#define RSP_VECTOR_VNAND 41
+#define RSP_VECTOR_VOR 42
+#define RSP_VECTOR_VNOR 43
+#define RSP_VECTOR_VXOR 44
+#define RSP_VECTOR_VNXOR 45
+#define RSP_VECTOR_VRCP 48
+#define RSP_VECTOR_VRCPL 49
+#define RSP_VECTOR_VRCPH 50
+#define RSP_VECTOR_VMOV 51
+#define RSP_VECTOR_VRSQ 52
+#define RSP_VECTOR_VRSQL 53
+#define RSP_VECTOR_VRSQH 54
+#define RSP_VECTOR_VNOOP 55
+
+/* RSP LSC2 opcodes */
+#define RSP_LSC2_BV 0
+#define RSP_LSC2_SV 1
+#define RSP_LSC2_LV 2
+#define RSP_LSC2_DV 3
+#define RSP_LSC2_QV 4
+#define RSP_LSC2_RV 5
+#define RSP_LSC2_PV 6
+#define RSP_LSC2_UV 7
+#define RSP_LSC2_HV 8
+#define RSP_LSC2_FV 9
+#define RSP_LSC2_WV 10
+#define RSP_LSC2_TV 11
+
+
+/************************* OpCode functions *************************/
+void RSP_Opcode_SPECIAL ( void );
+void RSP_Opcode_REGIMM ( void );
+void RSP_Opcode_J ( void );
+void RSP_Opcode_JAL ( void );
+void RSP_Opcode_BEQ ( void );
+void RSP_Opcode_BNE ( void );
+void RSP_Opcode_BLEZ ( void );
+void RSP_Opcode_BGTZ ( void );
+void RSP_Opcode_ADDI ( void );
+void RSP_Opcode_ADDIU ( void );
+void RSP_Opcode_SLTI ( void );
+void RSP_Opcode_SLTIU ( void );
+void RSP_Opcode_ANDI ( void );
+void RSP_Opcode_ORI ( void );
+void RSP_Opcode_XORI ( void );
+void RSP_Opcode_LUI ( void );
+void RSP_Opcode_COP0 ( void );
+void RSP_Opcode_COP2 ( void );
+void RSP_Opcode_LB ( void );
+void RSP_Opcode_LH ( void );
+void RSP_Opcode_LW ( void );
+void RSP_Opcode_LBU ( void );
+void RSP_Opcode_LHU ( void );
+void RSP_Opcode_SB ( void );
+void RSP_Opcode_SH ( void );
+void RSP_Opcode_SW ( void );
+void RSP_Opcode_LC2 ( void );
+void RSP_Opcode_SC2 ( void );
+/********************** R4300i OpCodes: Special **********************/
+void RSP_Special_SLL ( void );
+void RSP_Special_SRL ( void );
+void RSP_Special_SRA ( void );
+void RSP_Special_SLLV ( void );
+void RSP_Special_SRLV ( void );
+void RSP_Special_SRAV ( void );
+void RSP_Special_JR ( void );
+void RSP_Special_JALR ( void );
+void RSP_Special_BREAK ( void );
+void RSP_Special_ADD ( void );
+void RSP_Special_ADDU ( void );
+void RSP_Special_SUB ( void );
+void RSP_Special_SUBU ( void );
+void RSP_Special_AND ( void );
+void RSP_Special_OR ( void );
+void RSP_Special_XOR ( void );
+void RSP_Special_NOR ( void );
+void RSP_Special_SLT ( void );
+void RSP_Special_SLTU ( void );
+/********************** R4300i OpCodes: RegImm **********************/
+void RSP_Opcode_BLTZ ( void );
+void RSP_Opcode_BGEZ ( void );
+void RSP_Opcode_BLTZAL ( void );
+void RSP_Opcode_BGEZAL ( void );
+/************************** Cop0 functions *************************/
+void RSP_Cop0_MF ( void );
+void RSP_Cop0_MT ( void );
+/************************** Cop2 functions *************************/
+void RSP_Cop2_MF ( void );
+void RSP_Cop2_CF ( void );
+void RSP_Cop2_MT ( void );
+void RSP_Cop2_CT ( void );
+void RSP_COP2_VECTOR ( void );
+/************************** Vect functions **************************/
+void RSP_Vector_VMULF ( void );
+void RSP_Vector_VMULU ( void );
+void RSP_Vector_VMUDL ( void );
+void RSP_Vector_VMUDM ( void );
+void RSP_Vector_VMUDN ( void );
+void RSP_Vector_VMUDH ( void );
+void RSP_Vector_VMACF ( void );
+void RSP_Vector_VMACU ( void );
+void RSP_Vector_VMACQ ( void );
+void RSP_Vector_VMADL ( void );
+void RSP_Vector_VMADM ( void );
+void RSP_Vector_VMADN ( void );
+void RSP_Vector_VMADH ( void );
+void RSP_Vector_VADD ( void );
+void RSP_Vector_VSUB ( void );
+void RSP_Vector_VABS ( void );
+void RSP_Vector_VADDC ( void );
+void RSP_Vector_VSUBC ( void );
+void RSP_Vector_VSAW ( void );
+void RSP_Vector_VLT ( void );
+void RSP_Vector_VEQ ( void );
+void RSP_Vector_VNE ( void );
+void RSP_Vector_VGE ( void );
+void RSP_Vector_VCL ( void );
+void RSP_Vector_VCH ( void );
+void RSP_Vector_VCR ( void );
+void RSP_Vector_VMRG ( void );
+void RSP_Vector_VAND ( void );
+void RSP_Vector_VNAND ( void );
+void RSP_Vector_VOR ( void );
+void RSP_Vector_VNOR ( void );
+void RSP_Vector_VXOR ( void );
+void RSP_Vector_VNXOR ( void );
+void RSP_Vector_VRCP ( void );
+void RSP_Vector_VRCPL ( void );
+void RSP_Vector_VRCPH ( void );
+void RSP_Vector_VMOV ( void );
+void RSP_Vector_VRSQ ( void );
+void RSP_Vector_VRSQL ( void );
+void RSP_Vector_VRSQH ( void );
+void RSP_Vector_VNOOP ( void );
+/************************** lc2 functions **************************/
+void RSP_Opcode_LBV ( void );
+void RSP_Opcode_LSV ( void );
+void RSP_Opcode_LLV ( void );
+void RSP_Opcode_LDV ( void );
+void RSP_Opcode_LQV ( void );
+void RSP_Opcode_LRV ( void );
+void RSP_Opcode_LPV ( void );
+void RSP_Opcode_LUV ( void );
+void RSP_Opcode_LHV ( void );
+void RSP_Opcode_LFV ( void );
+void RSP_Opcode_LTV ( void );
+/************************** lc2 functions **************************/
+void RSP_Opcode_SBV ( void );
+void RSP_Opcode_SSV ( void );
+void RSP_Opcode_SLV ( void );
+void RSP_Opcode_SDV ( void );
+void RSP_Opcode_SQV ( void );
+void RSP_Opcode_SRV ( void );
+void RSP_Opcode_SPV ( void );
+void RSP_Opcode_SUV ( void );
+void RSP_Opcode_SHV ( void );
+void RSP_Opcode_SFV ( void );
+void RSP_Opcode_STV ( void );
+void RSP_Opcode_SWV ( void );
+/************************** Other functions **************************/
+void rsp_UnknownOpcode ( void );
+void RSPSetJumpTable ( void );
+
+extern void (*RSP_Opcode[64])();
+extern void (*RSP_RegImm[32])();
+extern void (*RSP_Special[64])();
+extern void (*RSP_Cop0[32])();
+extern void (*RSP_Cop2[32])();
+extern void (*RSP_Vector[64])();
+extern void (*RSP_Lc2[32])();
+extern void (*RSP_Sc2[32])();
+
+void RSP_SP_DMA_READ (void);
+void RSP_SP_DMA_WRITE(void);
+
+/******************* Function prototypes are hard ********************/
+void RSP_LB_DMEM ( uint32_t Addr, uint8_t * Value );
+void RSP_LH_DMEM ( uint32_t Addr, uint16_t * Value );
+void RSP_LW_DMEM ( uint32_t Addr, uint32_t * Value );
+void RSP_LW_IMEM ( uint32_t Addr, uint32_t * Value );
+void RSP_SB_DMEM ( uint32_t Addr, uint8_t Value );
+void RSP_SH_DMEM ( uint32_t Addr, uint16_t Value );
+void RSP_SW_DMEM ( uint32_t Addr, uint32_t Value );
+void RSP_LBV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_LSV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_LLV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_SFV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_STV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_SWV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_LDV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_LQV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_LRV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_LBV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_LDV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_LFV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_LHV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_LLV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_LPV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_LRV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_LQV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_LSV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_LTV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_LUV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_SBV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_SDV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_SFV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_SHV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_SLV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_SPV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_SQV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_SRV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_SSV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_STV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_SUV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+void RSP_SWV_DMEM ( uint32_t Addr, int32_t vect, int32_t element );
+
+extern REGISTER32 *RSP_GPR, RSP_Flags[4];
+extern REGISTER *RSP_ACCUM;
+extern VECTOR *RSP_Vect;
+
+extern REGISTER EleSpec[32], Indx[32];
+extern RSPOPCODE RSPOpC;
+extern uint32_t *PrgCount, RSPNextInstruction;
+extern uint32_t RSP_NextInstruction;
+extern REGISTER32 Recp, RecpResult, SQroot, SQrootResult;
+
+extern uint32_t RSP_NextInstruction, RSP_JumpTo;
+
+
+extern uint32_t RSP_Running;
+
+
+//extern uint8_t * RSPRecompPos, * RSPRecompCode, * RSPRecompCodeSecondary;
+//extern uint8_t * RSPJumpTable;
+#define MaxMaps 32
+
+extern uint32_t NoOfMaps, MapsCRC[MaxMaps], Table, ConditionalMove;
+extern uint8_t * RSPRecompCode, * RSPRecompCodeSecondary, * RSPRecompPos, *RSPJumpTables;
+extern void ** RSPJumpTable;
+
+
+#define NORMAL 0
+#define DO_DELAY_SLOT 1
+#define DO_END_DELAY_SLOT 2
+#define DELAY_SLOT 3
+#define END_DELAY_SLOT 4
+#define LIKELY_DELAY_SLOT 5
+#define JUMP 6
+#define DELAY_SLOT_DONE 7
+#define LIKELY_DELAY_SLOT_DONE 8
+#define END_BLOCK 9
+#define FINISH_BLOCK 10 // from RSP Recompiler CPU
+#define FINISH_SUB_BLOCK 11 // from RSP Recompiler CPU
+
+void real_run_rsp(uint32_t cycles);
+int32_t init_rsp(void);
+
+
+#endif
diff --git a/src/usf/rsp_interpreter_cpu.c b/src/usf/rsp_interpreter_cpu.c new file mode 100644 index 0000000..2fba36a --- /dev/null +++ b/src/usf/rsp_interpreter_cpu.c @@ -0,0 +1,1706 @@ +#include <stdlib.h>
+#include <stdint.h>
+#include "usf.h"
+#include "cpu.h"
+#include "memory.h"
+#include "audio.h"
+#include "rsp.h"
+
+
+void (*RSP_Opcode[64])();
+void (*RSP_RegImm[32])();
+void (*RSP_Special[64])();
+void (*RSP_Cop0[32])();
+void (*RSP_Cop2[32])();
+void (*RSP_Vector[64])();
+void (*RSP_Lc2[32])();
+void (*RSP_Sc2[32])();
+
+void RSP_Opcode_SPECIAL ( void ) {
+ (RSP_Special[ RSPOpC.funct ])();
+}
+
+void RSP_Opcode_REGIMM ( void ) {
+ (RSP_RegImm[ RSPOpC.rt ])();
+}
+
+void RSP_Opcode_J ( void ) {
+ RSP_NextInstruction = DELAY_SLOT;
+ RSP_JumpTo = (RSPOpC.target << 2) & 0xFFC;
+}
+
+void RSP_Opcode_JAL ( void ) {
+ RSP_NextInstruction = DELAY_SLOT;
+ RSP_GPR[31].UW = ( *PrgCount + 8 ) & 0xFFC;
+ RSP_JumpTo = (RSPOpC.target << 2) & 0xFFC;
+}
+
+void RSP_Opcode_BEQ ( void ) {
+ RSP_NextInstruction = DELAY_SLOT;
+ if (RSP_GPR[RSPOpC.rs].W == RSP_GPR[RSPOpC.rt].W) {
+ RSP_JumpTo = ( *PrgCount + ((int16_t)RSPOpC.offset << 2) + 4 ) & 0xFFC;
+ } else {
+ RSP_JumpTo = ( *PrgCount + 8 ) & 0xFFC;
+ }
+}
+
+void RSP_Opcode_BNE ( void ) {
+ RSP_NextInstruction = DELAY_SLOT;
+ if (RSP_GPR[RSPOpC.rs].W != RSP_GPR[RSPOpC.rt].W) {
+ RSP_JumpTo = ( *PrgCount + ((int16_t)RSPOpC.offset << 2) + 4 ) & 0xFFC;
+ } else {
+ RSP_JumpTo = ( *PrgCount + 8 ) & 0xFFC;
+ }
+}
+
+void RSP_Opcode_BLEZ ( void ) {
+ RSP_NextInstruction = DELAY_SLOT;
+ if (RSP_GPR[RSPOpC.rs].W <= 0) {
+ RSP_JumpTo = ( *PrgCount + ((int16_t)RSPOpC.offset << 2) + 4 ) & 0xFFC;
+ } else {
+ RSP_JumpTo = ( *PrgCount + 8 ) & 0xFFC;
+ }
+}
+
+void RSP_Opcode_BGTZ ( void ) {
+ RSP_NextInstruction = DELAY_SLOT;
+ if (RSP_GPR[RSPOpC.rs].W > 0) {
+ RSP_JumpTo = ( *PrgCount + ((int16_t)RSPOpC.offset << 2) + 4 ) & 0xFFC;
+ } else {
+ RSP_JumpTo = ( *PrgCount + 8 ) & 0xFFC;
+ }
+}
+
+void RSP_Opcode_ADDI ( void ) {
+ if (RSPOpC.rt != 0) {
+ RSP_GPR[RSPOpC.rt].W = RSP_GPR[RSPOpC.rs].W + (int16_t)RSPOpC.immediate;
+ }
+}
+
+void RSP_Opcode_ADDIU ( void ) {
+ if (RSPOpC.rt != 0) {
+ RSP_GPR[RSPOpC.rt].UW = RSP_GPR[RSPOpC.rs].UW + (uint32_t)((int16_t)RSPOpC.immediate);
+ }
+}
+
+void RSP_Opcode_SLTI (void) {
+ if (RSPOpC.rt == 0) { return; }
+ if (RSP_GPR[RSPOpC.rs].W < (int16_t)RSPOpC.immediate) {
+ RSP_GPR[RSPOpC.rt].W = 1;
+ } else {
+ RSP_GPR[RSPOpC.rt].W = 0;
+ }
+}
+
+void RSP_Opcode_SLTIU (void) {
+ if (RSPOpC.rt == 0) { return; }
+ if (RSP_GPR[RSPOpC.rs].UW < (uint32_t)(int16_t)RSPOpC.immediate) {
+ RSP_GPR[RSPOpC.rt].W = 1;
+ } else {
+ RSP_GPR[RSPOpC.rt].W = 0;
+ }
+}
+
+void RSP_Opcode_ANDI ( void ) {
+ if (RSPOpC.rt != 0) {
+ RSP_GPR[RSPOpC.rt].W = RSP_GPR[RSPOpC.rs].W & RSPOpC.immediate;
+ }
+}
+
+void RSP_Opcode_ORI ( void ) {
+ if (RSPOpC.rt != 0) {
+ RSP_GPR[RSPOpC.rt].W = RSP_GPR[RSPOpC.rs].W | RSPOpC.immediate;
+ }
+}
+
+void RSP_Opcode_XORI ( void ) {
+ if (RSPOpC.rt != 0) {
+ RSP_GPR[RSPOpC.rt].W = RSP_GPR[RSPOpC.rs].W ^ RSPOpC.immediate;
+ }
+}
+
+void RSP_Opcode_LUI (void) {
+ if (RSPOpC.rt != 0) {
+ RSP_GPR[RSPOpC.rt].W = (int16_t)RSPOpC.offset << 16;
+ }
+}
+
+void RSP_Opcode_COP0 (void) {
+ (RSP_Cop0[ RSPOpC.rs ])();
+}
+
+void RSP_Opcode_COP2 (void) {
+ (RSP_Cop2[ RSPOpC.rs ])();
+}
+
+void RSP_Opcode_LB ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (int16_t)RSPOpC.offset) & 0xFFF);
+ RSP_LB_DMEM( Address, &RSP_GPR[RSPOpC.rt].UB[0] );
+ RSP_GPR[RSPOpC.rt].W = RSP_GPR[RSPOpC.rt].B[0];
+}
+
+void RSP_Opcode_LH ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (int16_t)RSPOpC.offset) & 0xFFF);
+ RSP_LH_DMEM( Address, &RSP_GPR[RSPOpC.rt].UHW[0] );
+ RSP_GPR[RSPOpC.rt].W = RSP_GPR[RSPOpC.rt].HW[0];
+}
+
+void RSP_Opcode_LW ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (int16_t)RSPOpC.offset) & 0xFFF);
+ RSP_LW_DMEM( Address, &RSP_GPR[RSPOpC.rt].UW );
+}
+
+void RSP_Opcode_LBU ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (int16_t)RSPOpC.offset) & 0xFFF);
+ RSP_LB_DMEM( Address, &RSP_GPR[RSPOpC.rt].UB[0] );
+ RSP_GPR[RSPOpC.rt].UW = RSP_GPR[RSPOpC.rt].UB[0];
+}
+
+void RSP_Opcode_LHU ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (int16_t)RSPOpC.offset) & 0xFFF);
+ RSP_LH_DMEM( Address, &RSP_GPR[RSPOpC.rt].UHW[0] );
+ RSP_GPR[RSPOpC.rt].UW = RSP_GPR[RSPOpC.rt].UHW[0];
+}
+
+void RSP_Opcode_SB ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (int16_t)RSPOpC.offset) & 0xFFF);
+ RSP_SB_DMEM( Address, RSP_GPR[RSPOpC.rt].UB[0] );
+}
+
+void RSP_Opcode_SH ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (int16_t)RSPOpC.offset) & 0xFFF);
+ //if(Address == 0x370) {
+ // printf("%08x\nOpcode: %08x\n%08x\nRA: %08x\n", RSPCompilePC, RSPOpC.Hex, (int16_t)RSPOpC.offset,RSP_GPR[31].UW);
+ //}
+
+ RSP_SH_DMEM( Address, RSP_GPR[RSPOpC.rt].UHW[0] );
+}
+
+void RSP_Opcode_SW ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (int16_t)RSPOpC.offset) & 0xFFF);
+ RSP_SW_DMEM( Address, RSP_GPR[RSPOpC.rt].UW );
+}
+
+void RSP_Opcode_LC2 (void) {
+ (RSP_Lc2 [ RSPOpC.rd ])();
+}
+
+void RSP_Opcode_SC2 (void) {
+ (RSP_Sc2 [ RSPOpC.rd ])();
+}
+/********************** R4300i OpCodes: Special **********************/
+void RSP_Special_SLL ( void ) {
+ if (RSPOpC.rd != 0) {
+ RSP_GPR[RSPOpC.rd].W = RSP_GPR[RSPOpC.rt].W << RSPOpC.sa;
+ }
+}
+
+void RSP_Special_SRL ( void ) {
+ if (RSPOpC.rd != 0) {
+ RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rt].UW >> RSPOpC.sa;
+ }
+}
+
+void RSP_Special_SRA ( void ) {
+ if (RSPOpC.rd != 0) {
+ RSP_GPR[RSPOpC.rd].W = RSP_GPR[RSPOpC.rt].W >> RSPOpC.sa;
+ }
+}
+
+void RSP_Special_SLLV (void) {
+ if (RSPOpC.rd != 0) {
+ RSP_GPR[RSPOpC.rd].W = RSP_GPR[RSPOpC.rt].W << (RSP_GPR[RSPOpC.rs].W & 0x1F);
+ }
+}
+
+void RSP_Special_SRLV (void) {
+ if (RSPOpC.rd != 0) {
+ RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rt].UW >> (RSP_GPR[RSPOpC.rs].W & 0x1F);
+ }
+}
+
+void RSP_Special_SRAV (void) {
+ if (RSPOpC.rd != 0) {
+ RSP_GPR[RSPOpC.rd].W = RSP_GPR[RSPOpC.rt].W >> (RSP_GPR[RSPOpC.rs].W & 0x1F);
+ }
+}
+
+void RSP_Special_JR (void) {
+ RSP_NextInstruction = DELAY_SLOT;
+ RSP_JumpTo = (RSP_GPR[RSPOpC.rs].W & 0xFFC);
+}
+
+void RSP_Special_JALR (void) {
+ RSP_NextInstruction = DELAY_SLOT;
+ RSP_GPR[RSPOpC.rd].W = (*PrgCount + 8) & 0xFFC;
+ RSP_JumpTo = (RSP_GPR[RSPOpC.rs].W & 0xFFC);
+}
+
+#define R4300i_SP_Intr 0x1
+
+void RSP_Special_BREAK ( void ) {
+ RSP_Running = 0;
+ SP_STATUS_REG |= (SP_STATUS_HALT | SP_STATUS_BROKE );
+ if ((SP_STATUS_REG & SP_STATUS_INTR_BREAK) != 0 ) {
+ MI_INTR_REG |= R4300i_SP_Intr;
+ CheckInterrupts();
+ }
+}
+
+void RSP_Special_ADD (void) {
+ if (RSPOpC.rd != 0) {
+ RSP_GPR[RSPOpC.rd].W = RSP_GPR[RSPOpC.rs].W + RSP_GPR[RSPOpC.rt].W;
+ }
+}
+
+void RSP_Special_ADDU (void) {
+ if (RSPOpC.rd != 0) {
+ RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rs].UW + RSP_GPR[RSPOpC.rt].UW;
+ }
+}
+
+void RSP_Special_SUB (void) {
+ if (RSPOpC.rd != 0) {
+ RSP_GPR[RSPOpC.rd].W = RSP_GPR[RSPOpC.rs].W - RSP_GPR[RSPOpC.rt].W;
+ }
+}
+
+void RSP_Special_SUBU (void) {
+ if (RSPOpC.rd != 0) {
+ RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rs].UW - RSP_GPR[RSPOpC.rt].UW;
+ }
+}
+
+void RSP_Special_AND (void) {
+ if (RSPOpC.rd != 0) {
+ RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rs].UW & RSP_GPR[RSPOpC.rt].UW;
+ }
+}
+
+void RSP_Special_OR (void) {
+ if (RSPOpC.rd != 0) {
+ RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rs].UW | RSP_GPR[RSPOpC.rt].UW;
+ }
+}
+
+void RSP_Special_XOR (void) {
+ if (RSPOpC.rd != 0) {
+ RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rs].UW ^ RSP_GPR[RSPOpC.rt].UW;
+ }
+}
+
+void RSP_Special_NOR (void) {
+ if (RSPOpC.rd != 0) {
+ RSP_GPR[RSPOpC.rd].UW = ~(RSP_GPR[RSPOpC.rs].UW | RSP_GPR[RSPOpC.rt].UW);
+ }
+}
+
+void RSP_Special_SLT (void) {
+ if (RSPOpC.rd == 0) { return; }
+ if (RSP_GPR[RSPOpC.rs].W < RSP_GPR[RSPOpC.rt].W) {
+ RSP_GPR[RSPOpC.rd].UW = 1;
+ } else {
+ RSP_GPR[RSPOpC.rd].UW = 0;
+ }
+}
+
+void RSP_Special_SLTU (void) {
+ if (RSPOpC.rd == 0) { return; }
+ if (RSP_GPR[RSPOpC.rs].UW < RSP_GPR[RSPOpC.rt].UW) {
+ RSP_GPR[RSPOpC.rd].UW = 1;
+ } else {
+ RSP_GPR[RSPOpC.rd].UW = 0;
+ }
+}
+/********************** R4300i OpCodes: RegImm **********************/
+void RSP_Opcode_BLTZ ( void ) {
+ RSP_NextInstruction = DELAY_SLOT;
+ if (RSP_GPR[RSPOpC.rs].W < 0) {
+ RSP_JumpTo = ( *PrgCount + ((int16_t)RSPOpC.offset << 2) + 4 ) & 0xFFC;
+ } else {
+ RSP_JumpTo = ( *PrgCount + 8 ) & 0xFFC;
+ }
+}
+
+void RSP_Opcode_BGEZ ( void ) {
+ RSP_NextInstruction = DELAY_SLOT;
+ if (RSP_GPR[RSPOpC.rs].W >= 0) {
+ RSP_JumpTo = ( *PrgCount + ((int16_t)RSPOpC.offset << 2) + 4 ) & 0xFFC;
+ } else {
+ RSP_JumpTo = ( *PrgCount + 8 ) & 0xFFC;
+ }
+}
+
+void RSP_Opcode_BLTZAL ( void ) {
+ RSP_NextInstruction = DELAY_SLOT;
+ RSP_GPR[31].UW = ( *PrgCount + 8 ) & 0xFFC;
+ if (RSP_GPR[RSPOpC.rs].W < 0) {
+ RSP_JumpTo = ( *PrgCount + ((int16_t)RSPOpC.offset << 2) + 4 ) & 0xFFC;
+ } else {
+ RSP_JumpTo = ( *PrgCount + 8 ) & 0xFFC;
+ }
+}
+
+void RSP_Opcode_BGEZAL ( void ) {
+ RSP_NextInstruction = DELAY_SLOT;
+ RSP_GPR[31].UW = ( *PrgCount + 8 ) & 0xFFC;
+ if (RSP_GPR[RSPOpC.rs].W >= 0) {
+ RSP_JumpTo = ( *PrgCount + ((int16_t)RSPOpC.offset << 2) + 4 ) & 0xFFC;
+ } else {
+ RSP_JumpTo = ( *PrgCount + 8 ) & 0xFFC;
+ }
+}
+/************************** Cop0 functions *************************/
+void RSP_Cop0_MF (void) {
+ switch (RSPOpC.rd) {
+ case 4: RSP_GPR[RSPOpC.rt].UW = SP_STATUS_REG; break;
+ case 5: RSP_GPR[RSPOpC.rt].UW = SP_DMA_FULL_REG; break;
+ case 6: RSP_GPR[RSPOpC.rt].UW = SP_DMA_BUSY_REG; break;
+ case 7:
+ RSP_GPR[RSPOpC.rt].W = 0;
+ //RSP_GPR[RSPOpC.rt].W = SP_SEMAPHORE_REG;
+ //SP_SEMAPHORE_REG = 1;
+ break;
+ case 8: RSP_GPR[RSPOpC.rt].UW = DPC_START_REG ; break;
+ case 9: RSP_GPR[RSPOpC.rt].UW = DPC_END_REG ; break;
+ case 10: RSP_GPR[RSPOpC.rt].UW = DPC_CURRENT_REG; break;
+ case 11: RSP_GPR[RSPOpC.rt].W = DPC_STATUS_REG; break;
+ case 12: RSP_GPR[RSPOpC.rt].W = DPC_CLOCK_REG; break;
+ default:
+ printf("have not implemented RSP MF cpu->CP0 reg (%d)",RSPOpC.rd);
+ }
+}
+
+void RSP_Cop0_MT (void) {
+ switch (RSPOpC.rd) {
+ case 0: SP_MEM_ADDR_REG = RSP_GPR[RSPOpC.rt].UW; break;
+ case 1: SP_DRAM_ADDR_REG = RSP_GPR[RSPOpC.rt].UW; break;
+ case 2:
+ SP_RD_LEN_REG = RSP_GPR[RSPOpC.rt].UW;
+ RSP_SP_DMA_READ();
+ break;
+ case 3:
+ SP_WR_LEN_REG = RSP_GPR[RSPOpC.rt].UW;
+ RSP_SP_DMA_WRITE();
+ break;
+ case 4:
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_HALT ) != 0) { SP_STATUS_REG &= ~SP_STATUS_HALT; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_HALT ) != 0) { SP_STATUS_REG |= SP_STATUS_HALT; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_BROKE ) != 0) { SP_STATUS_REG &= ~SP_STATUS_BROKE; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_INTR ) != 0) { MI_INTR_REG &= ~R4300i_SP_Intr; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_INTR ) != 0) { printf("SP_SET_INTR"); }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_SSTEP ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SSTEP; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_SSTEP ) != 0) { SP_STATUS_REG |= SP_STATUS_SSTEP; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_INTR_BREAK ) != 0) { SP_STATUS_REG &= ~SP_STATUS_INTR_BREAK; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_INTR_BREAK ) != 0) { SP_STATUS_REG |= SP_STATUS_INTR_BREAK; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_SIG0 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG0; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_SIG0 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG0; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_SIG1 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG1; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_SIG1 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG1; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_SIG2 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG2; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_SIG2 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG2; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_SIG3 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG3; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_SIG3 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG3; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_SIG4 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG4; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_SIG4 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG4; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_SIG5 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG5; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_SIG5 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG5; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_SIG6 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG6; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_SIG6 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG6; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_SIG7 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG7; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_SIG7 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG7; }
+ break;
+ case 7: SP_SEMAPHORE_REG = 0; break;
+ case 8:
+ DPC_START_REG = RSP_GPR[RSPOpC.rt].UW;
+ DPC_CURRENT_REG = RSP_GPR[RSPOpC.rt].UW;
+ break;
+ case 9:
+ DPC_END_REG = RSP_GPR[RSPOpC.rt].UW;
+ break;
+ case 10: DPC_CURRENT_REG = RSP_GPR[RSPOpC.rt].UW; break;
+ case 11:
+ if ( ( RSP_GPR[RSPOpC.rt].W & DPC_CLR_XBUS_DMEM_DMA ) != 0) { DPC_STATUS_REG &= ~DPC_STATUS_XBUS_DMEM_DMA; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & DPC_SET_XBUS_DMEM_DMA ) != 0) { DPC_STATUS_REG |= DPC_STATUS_XBUS_DMEM_DMA; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & DPC_CLR_FREEZE ) != 0) { DPC_STATUS_REG &= ~DPC_STATUS_FREEZE; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & DPC_SET_FREEZE ) != 0) { DPC_STATUS_REG |= DPC_STATUS_FREEZE; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & DPC_CLR_FLUSH ) != 0) { DPC_STATUS_REG &= ~DPC_STATUS_FLUSH; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & DPC_SET_FLUSH ) != 0) { DPC_STATUS_REG |= DPC_STATUS_FLUSH; }
+ if ( ( RSP_GPR[RSPOpC.rt].W & DPC_CLR_TMEM_CTR ) != 0) { /* printf("RSP: DPC_STATUS_REG: DPC_CLR_TMEM_CTR"); */ }
+ if ( ( RSP_GPR[RSPOpC.rt].W & DPC_CLR_PIPE_CTR ) != 0) { printf("RSP: DPC_STATUS_REG: DPC_CLR_PIPE_CTR"); }
+ if ( ( RSP_GPR[RSPOpC.rt].W & DPC_CLR_CMD_CTR ) != 0) { printf("RSP: DPC_STATUS_REG: DPC_CLR_CMD_CTR"); }
+ if ( ( RSP_GPR[RSPOpC.rt].W & DPC_CLR_CLOCK_CTR ) != 0) { /* printf("RSP: DPC_STATUS_REG: DPC_CLR_CLOCK_CTR"); */ }
+ break;
+ default:
+ printf("have not implemented RSP MT cpu->CP0 reg (%d)",RSPOpC.rd);
+ }
+}
+
+/************************** Cop2 functions *************************/
+void RSP_Cop2_MF (void) {
+ int32_t element = (RSPOpC.sa >> 1);
+ RSP_GPR[RSPOpC.rt].B[1] = RSP_Vect[RSPOpC.rd].B[15 - element];
+ RSP_GPR[RSPOpC.rt].B[0] = RSP_Vect[RSPOpC.rd].B[15 - ((element + 1) % 16)];
+ RSP_GPR[RSPOpC.rt].W = RSP_GPR[RSPOpC.rt].HW[0];
+}
+
+void RSP_Cop2_CF (void) {
+ switch ((RSPOpC.rd & 0x03)) {
+ case 0: RSP_GPR[RSPOpC.rt].W = RSP_Flags[0].HW[0]; break;
+ case 1: RSP_GPR[RSPOpC.rt].W = RSP_Flags[1].HW[0]; break;
+ case 2: RSP_GPR[RSPOpC.rt].W = RSP_Flags[2].HW[0]; break;
+ case 3: RSP_GPR[RSPOpC.rt].W = RSP_Flags[2].HW[0]; break;
+ }
+}
+
+void RSP_Cop2_MT (void) {
+ int32_t element = 15 - (RSPOpC.sa >> 1);
+ RSP_Vect[RSPOpC.rd].B[element] = RSP_GPR[RSPOpC.rt].B[1];
+ if (element != 0) {
+ RSP_Vect[RSPOpC.rd].B[element - 1] = RSP_GPR[RSPOpC.rt].B[0];
+ }
+}
+
+void RSP_Cop2_CT (void) {
+ switch ((RSPOpC.rd & 0x03)) {
+ case 0: RSP_Flags[0].HW[0] = RSP_GPR[RSPOpC.rt].HW[0]; break;
+ case 1: RSP_Flags[1].HW[0] = RSP_GPR[RSPOpC.rt].HW[0]; break;
+ case 2: RSP_Flags[2].B[0] = RSP_GPR[RSPOpC.rt].B[0]; break;
+ case 3: RSP_Flags[2].B[0] = RSP_GPR[RSPOpC.rt].B[0]; break;
+ }
+}
+
+void RSP_COP2_VECTOR (void) {
+//((void (*)()) RSP_Vector[ RSPOpC.funct ])();
+ (RSP_Vector[ RSPOpC.funct ])();
+}
+/************************** Vect functions **************************/
+ /*
+ vmulf $v27, $v31[14]
+
+ Format: VMULF $v<dest>, $v<s1>, $v<s2>[el]
+ sa rd rt rs
+ */
+void RSP_Vector_VMULF (void) {
+ int32_t count, el, del;
+ REGISTER32 temp;
+
+ for (count = 0; count < 8; count ++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ if (RSP_Vect[RSPOpC.rd].UHW[el] != 0x8000 || RSP_Vect[RSPOpC.rt].UHW[del] != 0x8000) {
+ temp.W = ((int32_t)RSP_Vect[RSPOpC.rd].HW[el] * (int32_t)RSP_Vect[RSPOpC.rt].HW[del]) << 1;
+ temp.UW += 0x8000;
+ RSP_ACCUM[el].HW[2] = temp.HW[1];
+ RSP_ACCUM[el].HW[1] = temp.HW[0];
+ if ( RSP_ACCUM[el].HW[2] < 0 ) {
+ RSP_ACCUM[el].HW[3] = -1;
+ } else {
+ RSP_ACCUM[el].HW[3] = 0;
+ }
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2];
+ } else {
+ temp.W = 0x80000000;
+ RSP_ACCUM[el].UHW[3] = 0;
+ RSP_ACCUM[el].UHW[2] = 0x8000;
+ RSP_ACCUM[el].UHW[1] = 0x8000;
+ RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF;
+ }
+ }
+}
+
+void RSP_Vector_VMULU (void) {
+ int32_t count, el, del;
+
+ for (count = 0; count < 8; count ++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+ RSP_ACCUM[el].DW = (int64_t)(RSP_Vect[RSPOpC.rd].HW[el] * RSP_Vect[RSPOpC.rt].HW[del]) << 17;
+ RSP_ACCUM[el].DW += 0x80000000;
+ if (RSP_ACCUM[el].DW < 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = 0;
+ } else if ((int16_t)(RSP_ACCUM[el].UHW[3] ^ RSP_ACCUM[el].UHW[2]) < 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = -1;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2];
+ }
+ }
+}
+
+/*
+ vmudl $v23, $v30, $v24[10]
+ rs=10, rt=24, rd=30, sa=23
+
+ Format: VMUDM $v<dest>, $v<s1>, $v<s2>[el]
+ sa rd rt rs
+ vmudm $v23, $v20, $v24[10]
+ rs=10, rt=24, rd=20, sa=23
+
+*/
+
+void RSP_Vector_VMUDL (void) {
+ int32_t count, el, del;
+ REGISTER32 temp;
+
+ /*if(((*PrgCount) & 0xFFC) == 0xC08) {
+ for(int32_t i = 0; i < 32; i++) {
+ cprintf("i = %d : ", i);
+ for (count = 0; count < 8; count ++ ) {
+ cprintf("%d,%d ", Indx[i].B[count], EleSpec[i].B[Indx[i].B[count]]);
+ }
+ cprintf("\n");
+ }
+
+ }*/
+
+
+ for (count = 0; count < 8; count ++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ temp.UW = (uint32_t)RSP_Vect[RSPOpC.rd].UHW[el] * (uint32_t)RSP_Vect[RSPOpC.rt].UHW[del];
+
+ RSP_ACCUM[el].W[1] = 0;
+ RSP_ACCUM[el].HW[1] = temp.HW[1];
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[1];
+
+ }
+
+}
+
+void RSP_Vector_VMUDM (void) {
+ int32_t count, el, del;
+ REGISTER32 temp;
+
+// cprintf("%08x%08x x %08x%08x = ", RSP_Vect[RSPOpC.rd].DW[0], RSP_Vect[RSPOpC.rd].DW[1],RSP_Vect[RSPOpC.rt].DW[0],RSP_Vect[RSPOpC.rt].DW[1])
+
+
+ for (count = 0; count < 8; count ++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ temp.UW = (uint32_t)((int32_t)RSP_Vect[RSPOpC.rd].HW[el]) * (uint32_t)RSP_Vect[RSPOpC.rt].UHW[del];
+ if (temp.W < 0) {
+ RSP_ACCUM[el].HW[3] = -1;
+ } else {
+ RSP_ACCUM[el].HW[3] = 0;
+ }
+ RSP_ACCUM[el].HW[2] = temp.HW[1];
+ RSP_ACCUM[el].HW[1] = temp.HW[0];
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2];
+ }
+ //cprintf("%08x%08x\n", RSP_Vect[RSPOpC.sa].DW[0],RSP_Vect[RSPOpC.sa].DW[1]);
+}
+
+
+void RSP_Vector_VMUDN (void) {
+ int32_t count, el, del;
+ REGISTER32 temp;
+
+ for (count = 0; count < 8; count ++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+
+ temp.UW = (uint32_t)RSP_Vect[RSPOpC.rd].UHW[el] * (uint32_t)(int32_t)(RSP_Vect[RSPOpC.rt].HW[del]);
+ if (temp.W < 0) {
+ RSP_ACCUM[el].HW[3] = -1;
+ } else {
+ RSP_ACCUM[el].HW[3] = 0;
+ }
+ RSP_ACCUM[el].HW[2] = temp.HW[1];
+ RSP_ACCUM[el].HW[1] = temp.HW[0];
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[1];
+ }
+
+}
+
+void RSP_Vector_VMUDH (void) {
+ int32_t count, el, del;
+
+ for (count = 0; count < 8; count ++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ RSP_ACCUM[el].W[1] = (int32_t)RSP_Vect[RSPOpC.rd].HW[el] * (int32_t)RSP_Vect[RSPOpC.rt].HW[del];
+ RSP_ACCUM[el].HW[1] = 0;
+ if (RSP_ACCUM[el].HW[3] < 0) {
+ if (RSP_ACCUM[el].UHW[3] != 0xFFFF) {
+ RSP_Vect[RSPOpC.sa].HW[el] = (uint16_t)0x8000;
+ } else {
+ if (RSP_ACCUM[el].HW[2] >= 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = (uint16_t)0x8000;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2];
+ }
+ }
+ } else {
+ if (RSP_ACCUM[el].UHW[3] != 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF;
+ } else {
+ if (RSP_ACCUM[el].HW[2] < 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2];
+ }
+ }
+ }
+ }
+}
+
+void RSP_Vector_VMACF (void) {
+ int32_t count, el, del;
+ //UWORD temp, temp2;
+ REGISTER32 temp;
+
+ for (count = 0; count < 8; count ++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ /*temp.W = (int32_t)RSP_Vect[RSPOpC.rd].HW[el] * (int32_t)(uint32_t)RSP_Vect[RSPOpC.rt].HW[del];
+ RSP_ACCUM[el].UHW[3] += (uint16_t)(temp.W >> 31);
+ temp.UW = temp.UW << 1;
+ temp2.UW = temp.UHW[0] + RSP_ACCUM[el].UHW[1];
+ RSP_ACCUM[el].HW[1] = temp2.HW[0];
+ temp2.UW = temp.UHW[1] + RSP_ACCUM[el].UHW[2] + temp2.UHW[1];
+ RSP_ACCUM[el].HW[2] = temp2.HW[0];
+ RSP_ACCUM[el].HW[3] += temp2.HW[1];*/
+ temp.W = (int32_t)RSP_Vect[RSPOpC.rd].HW[el] * (int32_t)(uint32_t)RSP_Vect[RSPOpC.rt].HW[del];
+ RSP_ACCUM[el].DW += ((int64_t)temp.W) << 17;
+ if (RSP_ACCUM[el].HW[3] < 0) {
+ if (RSP_ACCUM[el].UHW[3] != 0xFFFF) {
+ RSP_Vect[RSPOpC.sa].HW[el] = (uint16_t)0x8000;
+ } else {
+ if (RSP_ACCUM[el].HW[2] >= 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = (uint16_t)0x8000;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2];
+ }
+ }
+ } else {
+ if (RSP_ACCUM[el].UHW[3] != 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF;
+ } else {
+ if (RSP_ACCUM[el].HW[2] < 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2];
+ }
+ }
+ }
+ }
+}
+
+void RSP_Vector_VMACU (void) {
+ int32_t count, el, del;
+ REGISTER32 temp, temp2;
+
+ for (count = 0; count < 8; count ++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ temp.W = (int32_t)RSP_Vect[RSPOpC.rd].HW[el] * (int32_t)(uint32_t)RSP_Vect[RSPOpC.rt].HW[del];
+ RSP_ACCUM[el].UHW[3] += (uint16_t)(temp.W >> 31);
+ temp.UW = temp.UW << 1;
+ temp2.UW = temp.UHW[0] + RSP_ACCUM[el].UHW[1];
+ RSP_ACCUM[el].HW[1] = temp2.HW[0];
+ temp2.UW = temp.UHW[1] + RSP_ACCUM[el].UHW[2] + temp2.UHW[1];
+ RSP_ACCUM[el].HW[2] = temp2.HW[0];
+ RSP_ACCUM[el].HW[3] += temp2.HW[1];
+ if (RSP_ACCUM[el].HW[3] < 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = 0;
+ } else {
+ if (RSP_ACCUM[el].UHW[3] != 0) {
+ RSP_Vect[RSPOpC.sa].UHW[el] = 0xFFFF;
+ } else {
+ if (RSP_ACCUM[el].HW[2] < 0) {
+ RSP_Vect[RSPOpC.sa].UHW[el] = 0xFFFF;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2];
+ }
+ }
+ }
+ }
+}
+
+void RSP_Vector_VMACQ (void) {
+ int32_t count, el, del;
+ REGISTER32 temp;
+
+ for (count = 0; count < 8; count ++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ if (RSP_ACCUM[el].W[1] > 0x20) {
+ if ((RSP_ACCUM[el].W[1] & 0x20) == 0) {
+ RSP_ACCUM[el].W[1] -= 0x20;
+ }
+ } else if (RSP_ACCUM[el].W[1] < -0x20) {
+ if ((RSP_ACCUM[el].W[1] & 0x20) == 0) {
+ RSP_ACCUM[el].W[1] += 0x20;
+ }
+ }
+ temp.W = RSP_ACCUM[el].W[1] >> 1;
+ if (temp.HW[1] < 0) {
+ if (temp.UHW[1] != 0xFFFF) {
+ RSP_Vect[RSPOpC.sa].HW[el] = (uint16_t)0x8000;
+ } else {
+ if (temp.HW[0] >= 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = (uint16_t)0x8000;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = (uint16_t)(temp.UW & 0xFFF0);
+ }
+ }
+ } else {
+ if (temp.UHW[1] != 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = 0x7FF0;
+ } else {
+ if (temp.HW[0] < 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = 0x7FF0;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = (uint16_t)(temp.UW & 0xFFF0);
+ }
+ }
+ }
+ }
+}
+
+void RSP_Vector_VMADL (void) {
+ int32_t count, el, del;
+ REGISTER32 temp, temp2;
+
+
+
+ for (count = 0; count < 8; count ++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ temp.UW = (uint32_t)RSP_Vect[RSPOpC.rd].UHW[el] * (uint32_t)RSP_Vect[RSPOpC.rt].UHW[del];
+ temp2.UW = temp.UHW[1] + RSP_ACCUM[el].UHW[1];
+ RSP_ACCUM[el].HW[1] = temp2.HW[0];
+ temp2.UW = RSP_ACCUM[el].UHW[2] + temp2.UHW[1];
+ RSP_ACCUM[el].HW[2] = temp2.HW[0];
+ RSP_ACCUM[el].HW[3] += temp2.HW[1];
+ if (RSP_ACCUM[el].HW[3] < 0) {
+ if (RSP_ACCUM[el].UHW[3] != 0xFFFF) {
+ RSP_Vect[RSPOpC.sa].HW[el] = 0;
+ } else {
+ if (RSP_ACCUM[el].HW[2] >= 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = 0;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[1];
+ }
+ }
+ } else {
+ if (RSP_ACCUM[el].UHW[3] != 0) {
+ RSP_Vect[RSPOpC.sa].UHW[el] = 0xFFFF;
+ } else {
+ if (RSP_ACCUM[el].HW[2] < 0) {
+ RSP_Vect[RSPOpC.sa].UHW[el] = 0xFFFF;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[1];
+ }
+ }
+ }
+ }
+
+}
+
+void RSP_Vector_VMADM (void) {
+ int32_t count, el, del;
+ REGISTER32 temp, temp2;
+
+ for (count = 0; count < 8; count ++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ temp.UW = (uint32_t)((int32_t)RSP_Vect[RSPOpC.rd].HW[el]) * (uint32_t)RSP_Vect[RSPOpC.rt].UHW[del];
+ temp2.UW = temp.UHW[0] + RSP_ACCUM[el].UHW[1];
+ RSP_ACCUM[el].HW[1] = temp2.HW[0];
+ temp2.UW = temp.UHW[1] + RSP_ACCUM[el].UHW[2] + temp2.UHW[1];
+ RSP_ACCUM[el].HW[2] = temp2.HW[0];
+ RSP_ACCUM[el].HW[3] += temp2.HW[1];
+ if (temp.W < 0) {
+ RSP_ACCUM[el].HW[3] -= 1;
+ }
+ if (RSP_ACCUM[el].HW[3] < 0) {
+ if (RSP_ACCUM[el].UHW[3] != 0xFFFF) {
+ RSP_Vect[RSPOpC.sa].HW[el] = (uint16_t)0x8000;
+ } else {
+ if (RSP_ACCUM[el].HW[2] >= 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = (uint16_t)0x8000;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2];
+ }
+ }
+ } else {
+ if (RSP_ACCUM[el].UHW[3] != 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF;
+ } else {
+ if (RSP_ACCUM[el].HW[2] < 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2];
+ }
+ }
+ }
+ //RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2];
+ }
+}
+
+void RSP_Vector_VMADN (void) {
+ int32_t count, el, del;
+ REGISTER32 temp, temp2;
+
+ for (count = 0; count < 8; count ++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ temp.UW = (uint32_t)RSP_Vect[RSPOpC.rd].UHW[el] * (uint32_t)((int32_t)RSP_Vect[RSPOpC.rt].HW[del]);
+ temp2.UW = temp.UHW[0] + RSP_ACCUM[el].UHW[1];
+ RSP_ACCUM[el].HW[1] = temp2.HW[0];
+ temp2.UW = temp.UHW[1] + RSP_ACCUM[el].UHW[2] + temp2.UHW[1];
+ RSP_ACCUM[el].HW[2] = temp2.HW[0];
+ RSP_ACCUM[el].HW[3] += temp2.HW[1];
+ if (temp.W < 0) {
+ RSP_ACCUM[el].HW[3] -= 1;
+ }
+ if (RSP_ACCUM[el].HW[3] < 0) {
+ if (RSP_ACCUM[el].UHW[3] != 0xFFFF) {
+ RSP_Vect[RSPOpC.sa].HW[el] = 0;
+ } else {
+ if (RSP_ACCUM[el].HW[2] >= 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = 0;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[1];
+ }
+ }
+ } else {
+ if (RSP_ACCUM[el].UHW[3] != 0) {
+ RSP_Vect[RSPOpC.sa].UHW[el] = 0xFFFF;
+ } else {
+ if (RSP_ACCUM[el].HW[2] < 0) {
+ RSP_Vect[RSPOpC.sa].UHW[el] = 0xFFFF;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[1];
+ }
+ }
+ }
+ }
+}
+
+void RSP_Vector_VMADH (void) {
+ int32_t count, el, del;
+
+ for (count = 0; count < 8; count ++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ RSP_ACCUM[el].W[1] += (int32_t)RSP_Vect[RSPOpC.rd].HW[el] * (int32_t)RSP_Vect[RSPOpC.rt].HW[del];
+ if (RSP_ACCUM[el].HW[3] < 0) {
+ if (RSP_ACCUM[el].UHW[3] != 0xFFFF) {
+ RSP_Vect[RSPOpC.sa].HW[el] = (uint16_t)0x8000;
+ } else {
+ if (RSP_ACCUM[el].HW[2] >= 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = (uint16_t)0x8000;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2];
+ }
+ }
+ } else {
+ if (RSP_ACCUM[el].UHW[3] != 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF;
+ } else {
+ if (RSP_ACCUM[el].HW[2] < 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2];
+ }
+ }
+ }
+ }
+}
+
+void RSP_Vector_VADD (void) {
+ int32_t count, el, del;
+ REGISTER32 temp;
+
+ for ( count = 0; count < 8; count++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ temp.W = (int32_t)RSP_Vect[RSPOpC.rd].HW[el] + (int32_t)RSP_Vect[RSPOpC.rt].HW[del] +
+ ((RSP_Flags[0].UW >> (7 - el)) & 0x1);
+ RSP_ACCUM[el].HW[1] = temp.HW[0];
+ if ((temp.HW[0] & 0x8000) == 0) {
+ if (temp.HW[1] != 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = (uint16_t)0x8000;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = temp.HW[0];
+ }
+ } else {
+ if (temp.HW[1] != -1 ) {
+ RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = temp.HW[0];
+ }
+ }
+ }
+ RSP_Flags[0].UW = 0;
+}
+
+void RSP_Vector_VSUB (void) {
+ int32_t count, el, del;
+ REGISTER32 temp;
+
+ for ( count = 0; count < 8; count++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ temp.W = (int32_t)RSP_Vect[RSPOpC.rd].HW[el] - (int32_t)RSP_Vect[RSPOpC.rt].HW[del] -
+ ((RSP_Flags[0].UW >> (7 - el)) & 0x1);
+ RSP_ACCUM[el].HW[1] = temp.HW[0];
+ if ((temp.HW[0] & 0x8000) == 0) {
+ if (temp.HW[1] != 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = (uint16_t)0x8000;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = temp.HW[0];
+ }
+ } else {
+ if (temp.HW[1] != -1 ) {
+ RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = temp.HW[0];
+ }
+ }
+ }
+ RSP_Flags[0].UW = 0;
+}
+
+void RSP_Vector_VABS (void) {
+ int32_t count, el, del;
+
+ for ( count = 0; count < 8; count++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ if (RSP_Vect[RSPOpC.rd].HW[el] > 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rt].UHW[del];
+ } else if (RSP_Vect[RSPOpC.rd].HW[el] < 0) {
+ if (RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[el]] == 0x8000) {
+ RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF;
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rt].HW[del] * -1;
+ }
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = 0;
+ }
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el];
+ }
+}
+
+void RSP_Vector_VADDC (void) {
+ int32_t count, el, del;
+ REGISTER32 temp;
+
+ RSP_Flags[0].UW = 0;
+ for ( count = 0; count < 8; count++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ temp.UW = (int32_t)RSP_Vect[RSPOpC.rd].UHW[el] + (int32_t)RSP_Vect[RSPOpC.rt].UHW[del];
+ RSP_ACCUM[el].HW[1] = temp.HW[0];
+ RSP_Vect[RSPOpC.sa].HW[el] = temp.HW[0];
+ if (temp.UW & 0xffff0000) {
+ RSP_Flags[0].UW |= ( 1 << (7 - el) );
+ }
+ }
+}
+
+void RSP_Vector_VSUBC (void) {
+ int32_t count, el, del;
+ REGISTER32 temp;
+
+ RSP_Flags[0].UW = 0x0;
+ for ( count = 0; count < 8; count++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ temp.UW = (int32_t)RSP_Vect[RSPOpC.rd].UHW[el] - (int32_t)RSP_Vect[RSPOpC.rt].UHW[del];
+ RSP_ACCUM[el].HW[1] = temp.HW[0];
+ RSP_Vect[RSPOpC.sa].HW[el] = temp.HW[0];
+ if (temp.HW[0] != 0) {
+ RSP_Flags[0].UW |= ( 0x1 << (15 - el) );
+ }
+ if (temp.UW & 0xffff0000) {
+ RSP_Flags[0].UW |= ( 0x1 << (7 - el) );
+ }
+ }
+}
+
+void RSP_Vector_VSAW (void) {
+ switch ((RSPOpC.rs & 0xF)) {
+ case 8:
+ RSP_Vect[RSPOpC.sa].HW[0] = RSP_ACCUM[0].HW[3];
+ RSP_Vect[RSPOpC.sa].HW[1] = RSP_ACCUM[1].HW[3];
+ RSP_Vect[RSPOpC.sa].HW[2] = RSP_ACCUM[2].HW[3];
+ RSP_Vect[RSPOpC.sa].HW[3] = RSP_ACCUM[3].HW[3];
+ RSP_Vect[RSPOpC.sa].HW[4] = RSP_ACCUM[4].HW[3];
+ RSP_Vect[RSPOpC.sa].HW[5] = RSP_ACCUM[5].HW[3];
+ RSP_Vect[RSPOpC.sa].HW[6] = RSP_ACCUM[6].HW[3];
+ RSP_Vect[RSPOpC.sa].HW[7] = RSP_ACCUM[7].HW[3];
+ break;
+ case 9:
+ RSP_Vect[RSPOpC.sa].HW[0] = RSP_ACCUM[0].HW[2];
+ RSP_Vect[RSPOpC.sa].HW[1] = RSP_ACCUM[1].HW[2];
+ RSP_Vect[RSPOpC.sa].HW[2] = RSP_ACCUM[2].HW[2];
+ RSP_Vect[RSPOpC.sa].HW[3] = RSP_ACCUM[3].HW[2];
+ RSP_Vect[RSPOpC.sa].HW[4] = RSP_ACCUM[4].HW[2];
+ RSP_Vect[RSPOpC.sa].HW[5] = RSP_ACCUM[5].HW[2];
+ RSP_Vect[RSPOpC.sa].HW[6] = RSP_ACCUM[6].HW[2];
+ RSP_Vect[RSPOpC.sa].HW[7] = RSP_ACCUM[7].HW[2];
+ break;
+ case 10:
+ RSP_Vect[RSPOpC.sa].HW[0] = RSP_ACCUM[0].HW[1];
+ RSP_Vect[RSPOpC.sa].HW[1] = RSP_ACCUM[1].HW[1];
+ RSP_Vect[RSPOpC.sa].HW[2] = RSP_ACCUM[2].HW[1];
+ RSP_Vect[RSPOpC.sa].HW[3] = RSP_ACCUM[3].HW[1];
+ RSP_Vect[RSPOpC.sa].HW[4] = RSP_ACCUM[4].HW[1];
+ RSP_Vect[RSPOpC.sa].HW[5] = RSP_ACCUM[5].HW[1];
+ RSP_Vect[RSPOpC.sa].HW[6] = RSP_ACCUM[6].HW[1];
+ RSP_Vect[RSPOpC.sa].HW[7] = RSP_ACCUM[7].HW[1];
+ break;
+ default:
+ RSP_Vect[RSPOpC.sa].DW[1] = 0;
+ RSP_Vect[RSPOpC.sa].DW[0] = 0;
+ }
+}
+
+void RSP_Vector_VLT (void) {
+ int32_t count, el, del;
+
+ RSP_Flags[1].UW = 0;
+ for ( count = 0; count < 8; count++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ if (RSP_Vect[RSPOpC.rd].HW[el] < RSP_Vect[RSPOpC.rt].HW[del]) {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].UHW[el];
+ RSP_Flags[1].UW |= ( 1 << (7 - el) );
+ } else if (RSP_Vect[RSPOpC.rd].HW[el] != RSP_Vect[RSPOpC.rt].HW[del]) {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rt].UHW[del];
+ RSP_Flags[1].UW &= ~( 1 << (7 - el) );
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].UHW[el];
+ if ( (RSP_Flags[0].UW & (0x101 << (7 - el))) == (uint16_t)(0x101 << (7 - el))) {
+ RSP_Flags[1].UW |= ( 1 << (7 - el) );
+ } else {
+ RSP_Flags[1].UW &= ~( 1 << (7 - el) );
+ }
+ }
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el];
+ }
+ RSP_Flags[0].UW = 0;
+}
+
+void RSP_Vector_VEQ (void) {
+ int32_t count, el, del;
+
+ RSP_Flags[1].UW = 0;
+ for ( count = 0; count < 8; count++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rt].UHW[del];
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rt].UHW[del];
+ if (RSP_Vect[RSPOpC.rd].UHW[el] == RSP_Vect[RSPOpC.rt].UHW[del]) {
+ if ( (RSP_Flags[0].UW & (1 << (15 - el))) == 0) {
+ RSP_Flags[1].UW |= ( 1 << (7 - el));
+ }
+ }
+ }
+ RSP_Flags[0].UW = 0;
+}
+
+void RSP_Vector_VNE (void) {
+ int32_t count, el, del;
+
+ RSP_Flags[1].UW = 0;
+ for ( count = 0; count < 8; count++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].UHW[el];
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rd].UHW[el];
+ if (RSP_Vect[RSPOpC.rd].UHW[el] != RSP_Vect[RSPOpC.rt].UHW[del]) {
+ RSP_Flags[1].UW |= ( 1 << (7 - el) );
+ } else {
+ if ( (RSP_Flags[0].UW & (1 << (15 - el))) != 0) {
+ RSP_Flags[1].UW |= ( 1 << (7 - el) );
+ }
+ }
+ }
+ RSP_Flags[0].UW = 0;
+}
+
+void RSP_Vector_VGE (void) {
+ int32_t count, el, del;
+
+ RSP_Flags[1].UW = 0;
+ for ( count = 0; count < 8; count++ ) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ if (RSP_Vect[RSPOpC.rd].HW[el] == RSP_Vect[RSPOpC.rt].HW[del]) {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].UHW[el];
+ if ( (RSP_Flags[0].UW & (0x101 << (7 - el))) == (uint16_t)(0x101 << (7 - el))) {
+ RSP_Flags[1].UW &= ~( 1 << (7 - el) );
+ } else {
+ RSP_Flags[1].UW |= ( 1 << (7 - el) );
+ }
+ } else if (RSP_Vect[RSPOpC.rd].HW[el] > RSP_Vect[RSPOpC.rt].HW[del]) {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].UHW[el];
+ RSP_Flags[1].UW |= ( 1 << (7 - el) );
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rt].UHW[del];
+ RSP_Flags[1].UW &= ~( 1 << (7 - el) );
+ }
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el];
+ }
+ RSP_Flags[0].UW = 0;
+}
+
+void RSP_Vector_VCL (void) {
+ int32_t count, el, del;
+
+ for (count = 0;count < 8; count++) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ if ((RSP_Flags[0].UW & ( 1 << (7 - el))) != 0 ) {
+ if ((RSP_Flags[0].UW & ( 1 << (15 - el))) != 0 ) {
+ if ((RSP_Flags[1].UW & ( 1 << (7 - el))) != 0 ) {
+ RSP_ACCUM[el].HW[1] = -RSP_Vect[RSPOpC.rt].UHW[del];
+ } else {
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rd].HW[el];
+ }
+ } else {
+ if ((RSP_Flags[2].UW & ( 1 << (7 - el)))) {
+ if ( RSP_Vect[RSPOpC.rd].UHW[el] + RSP_Vect[RSPOpC.rt].UHW[del] > 0x10000) {
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rd].HW[el];
+ RSP_Flags[1].UW &= ~(1 << (7 - el));
+ } else {
+ RSP_ACCUM[el].HW[1] = -RSP_Vect[RSPOpC.rt].UHW[del];
+ RSP_Flags[1].UW |= (1 << (7 - el));
+ }
+ } else {
+ if (RSP_Vect[RSPOpC.rt].UHW[del] + RSP_Vect[RSPOpC.rd].UHW[el] != 0) {
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rd].HW[el];
+ RSP_Flags[1].UW &= ~(1 << (7 - el));
+ } else {
+ RSP_ACCUM[el].HW[1] = -RSP_Vect[RSPOpC.rt].UHW[del];
+ RSP_Flags[1].UW |= (1 << (7 - el));
+ }
+ }
+ }
+ } else {
+ if ((RSP_Flags[0].UW & ( 1 << (15 - el))) != 0 ) {
+ if ((RSP_Flags[1].UW & ( 1 << (15 - el))) != 0 ) {
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rt].HW[del];
+ } else {
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rd].HW[el];
+ }
+ } else {
+ if ( RSP_Vect[RSPOpC.rd].UHW[el] - RSP_Vect[RSPOpC.rt].UHW[del] >= 0) {
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rt].UHW[del];
+ RSP_Flags[1].UW |= (1 << (15 - el));
+ } else {
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rd].HW[el];
+ RSP_Flags[1].UW &= ~(1 << (15 - el));
+ }
+ }
+ }
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[1];
+ }
+ RSP_Flags[0].UW = 0;
+ RSP_Flags[2].UW = 0;
+}
+
+void RSP_Vector_VCH (void) {
+ int32_t count, el, del;
+
+ RSP_Flags[0].UW = 0;
+ RSP_Flags[1].UW = 0;
+ RSP_Flags[2].UW = 0;
+
+ for (count = 0;count < 8; count++) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ if ((RSP_Vect[RSPOpC.rd].HW[el] ^ RSP_Vect[RSPOpC.rt].HW[del]) < 0) {
+ RSP_Flags[0].UW |= ( 1 << (7 - el));
+ if (RSP_Vect[RSPOpC.rt].HW[del] < 0) {
+ RSP_Flags[1].UW |= ( 1 << (15 - el));
+
+ }
+ if (RSP_Vect[RSPOpC.rd].HW[el] + RSP_Vect[RSPOpC.rt].HW[del] <= 0) {
+ if (RSP_Vect[RSPOpC.rd].HW[el] + RSP_Vect[RSPOpC.rt].HW[del] == -1) {
+ RSP_Flags[2].UW |= ( 1 << (7 - el));
+ }
+ RSP_Flags[1].UW |= ( 1 << (7 - el));
+ RSP_Vect[RSPOpC.sa].HW[el] = -RSP_Vect[RSPOpC.rt].UHW[del];
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el];
+ }
+ if (RSP_Vect[RSPOpC.rd].HW[el] + RSP_Vect[RSPOpC.rt].HW[del] != 0) {
+ if (RSP_Vect[RSPOpC.rd].HW[el] != ~RSP_Vect[RSPOpC.rt].HW[del]) {
+ RSP_Flags[0].UW |= ( 1 << (15 - el));
+ }
+ }
+ } else {
+ if (RSP_Vect[RSPOpC.rt].HW[del] < 0) {
+ RSP_Flags[1].UW |= ( 1 << (7 - el));
+ }
+ if (RSP_Vect[RSPOpC.rd].HW[el] - RSP_Vect[RSPOpC.rt].HW[del] >= 0) {
+ RSP_Flags[1].UW |= ( 1 << (15 - el));
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rt].UHW[del];
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el];
+ }
+ if (RSP_Vect[RSPOpC.rd].HW[el] - RSP_Vect[RSPOpC.rt].HW[del] != 0) {
+ if (RSP_Vect[RSPOpC.rd].HW[el] != ~RSP_Vect[RSPOpC.rt].HW[del]) {
+ RSP_Flags[0].UW |= ( 1 << (15 - el));
+ }
+ }
+ }
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el];
+ }
+}
+
+void RSP_Vector_VCR (void) {
+ int32_t count, el, del;
+
+ RSP_Flags[0].UW = 0;
+ RSP_Flags[1].UW = 0;
+ RSP_Flags[2].UW = 0;
+ for (count = 0;count < 8; count++) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ if ((RSP_Vect[RSPOpC.rd].HW[el] ^ RSP_Vect[RSPOpC.rt].HW[del]) < 0) {
+ if (RSP_Vect[RSPOpC.rt].HW[del] < 0) {
+ RSP_Flags[1].UW |= ( 1 << (15 - el));
+ }
+ if (RSP_Vect[RSPOpC.rd].HW[el] + RSP_Vect[RSPOpC.rt].HW[del] <= 0) {
+ RSP_ACCUM[el].HW[1] = ~RSP_Vect[RSPOpC.rt].UHW[del];
+ RSP_Flags[1].UW |= ( 1 << (7 - el));
+ } else {
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rd].HW[el];
+ }
+ } else {
+ if (RSP_Vect[RSPOpC.rt].HW[del] < 0) {
+ RSP_Flags[1].UW |= ( 1 << (7 - el));
+ }
+ if (RSP_Vect[RSPOpC.rd].HW[el] - RSP_Vect[RSPOpC.rt].HW[del] >= 0) {
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rt].UHW[del];
+ RSP_Flags[1].UW |= ( 1 << (15 - el));
+ } else {
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rd].HW[el];
+ }
+ }
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[1];
+ }
+}
+
+void RSP_Vector_VMRG (void) {
+ int32_t count, el, del;
+
+ for ( count = 0; count < 8; count ++ ){
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ if ((RSP_Flags[1].UW & ( 1 << (7 - el))) != 0) {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el];
+ } else {
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rt].HW[del];
+ }
+ }
+}
+
+void RSP_Vector_VAND (void) {
+ int32_t count, el, del;
+
+ for ( count = 0; count < 8; count ++ ){
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el] & RSP_Vect[RSPOpC.rt].HW[del];
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el];
+ }
+}
+
+void RSP_Vector_VNAND (void) {
+ int32_t count, el, del;
+
+ for ( count = 0; count < 8; count ++ ){
+ el = 7 - count;
+ del = EleSpec[RSPOpC.rs].B[el];
+ RSP_Vect[RSPOpC.sa].HW[el] = ~(RSP_Vect[RSPOpC.rd].HW[el] & RSP_Vect[RSPOpC.rt].HW[del]);
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el];
+ }
+}
+
+void RSP_Vector_VOR (void) {
+ int32_t count, el, del;
+
+ for ( count = 0; count < 8; count ++ ){
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el] | RSP_Vect[RSPOpC.rt].HW[del];
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el];
+ }
+}
+
+void RSP_Vector_VNOR (void) {
+ int32_t count, el, del;
+
+ for ( count = 0; count < 8; count ++ ){
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+ RSP_Vect[RSPOpC.sa].HW[el] = ~(RSP_Vect[RSPOpC.rd].HW[el] | RSP_Vect[RSPOpC.rt].HW[del]);
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el];
+ }
+}
+
+void RSP_Vector_VXOR (void) {
+ int32_t count, el, del;
+
+ for ( count = 0; count < 8; count ++ ){
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+ RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el] ^ RSP_Vect[RSPOpC.rt].HW[del];
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el];
+ }
+}
+
+void RSP_Vector_VNXOR (void) {
+ int32_t count, el, del;
+
+ for ( count = 0; count < 8; count ++ ){
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+ RSP_Vect[RSPOpC.sa].HW[el] = ~(RSP_Vect[RSPOpC.rd].HW[el] ^ RSP_Vect[RSPOpC.rt].HW[del]);
+ RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el];
+ }
+}
+
+void RSP_Vector_VRCP (void) {
+ int32_t count, neg;
+
+ RecpResult.W = RSP_Vect[RSPOpC.rt].HW[EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)]];
+ if (RecpResult.UW == 0) {
+ RecpResult.UW = 0x7FFFFFFF;
+ } else {
+ if (RecpResult.W < 0) {
+ neg = 1;
+ RecpResult.W = ~RecpResult.W + 1;
+ } else {
+ neg = 0;
+ }
+ for (count = 15; count > 0; count--) {
+ if ((RecpResult.W & (1 << count))) {
+ RecpResult.W &= (0xFFC0 >> (15 - count) );
+ count = 0;
+ }
+ }
+ RecpResult.W = (int32_t)((0x7FFFFFFF / (double)RecpResult.W));
+ for (count = 31; count > 0; count--) {
+ if ((RecpResult.W & (1 << count))) {
+ RecpResult.W &= (0xFFFF8000 >> (31 - count) );
+ count = 0;
+ }
+ }
+ if (neg == 1) {
+ RecpResult.W = ~RecpResult.W;
+ }
+ }
+ for ( count = 0; count < 8; count++ ) {
+ RSP_ACCUM[count].HW[1] = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[count]];
+ }
+ RSP_Vect[RSPOpC.sa].HW[7 - (RSPOpC.rd & 0x7)] = RecpResult.UHW[0];
+}
+
+void RSP_Vector_VRCPL (void) {
+ int32_t count, neg;
+
+ RecpResult.UW = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)]] | Recp.W;
+ if (RecpResult.UW == 0) {
+ RecpResult.UW = 0x7FFFFFFF;
+ } else {
+ if (RecpResult.W < 0) {
+ neg = 1;
+ if (RecpResult.UHW[1] == 0xFFFF && RecpResult.HW[0] < 0) {
+ RecpResult.W = ~RecpResult.W + 1;
+ } else {
+ RecpResult.W = ~RecpResult.W;
+ }
+ } else {
+ neg = 0;
+ }
+ for (count = 31; count > 0; count--) {
+ if ((RecpResult.W & (1 << count))) {
+ RecpResult.W &= (0xFFC00000 >> (31 - count) );
+ count = 0;
+ }
+ }
+ RecpResult.W = 0x7FFFFFFF / RecpResult.W;
+ for (count = 31; count > 0; count--) {
+ if ((RecpResult.W & (1 << count))) {
+ RecpResult.W &= (0xFFFF8000 >> (31 - count) );
+ count = 0;
+ }
+ }
+ if (neg == 1) {
+ RecpResult.W = ~RecpResult.W;
+ }
+ }
+ for ( count = 0; count < 8; count++ ) {
+ RSP_ACCUM[count].HW[1] = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[count]];
+ }
+ RSP_Vect[RSPOpC.sa].HW[7 - (RSPOpC.rd & 0x7)] = RecpResult.UHW[0];
+}
+
+void RSP_Vector_VRCPH (void) {
+ int32_t count;
+
+ Recp.UHW[1] = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)]];
+ for ( count = 0; count < 8; count++ ) {
+ RSP_ACCUM[count].HW[1] = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[count]];
+ }
+ RSP_Vect[RSPOpC.sa].UHW[7 - (RSPOpC.rd & 0x7)] = RecpResult.UHW[1];
+}
+
+void RSP_Vector_VMOV (void) {
+ RSP_Vect[RSPOpC.sa].UHW[7 - (RSPOpC.rd & 0x7)] =
+ RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)]];
+}
+
+void RSP_Vector_VRSQ (void) {
+ int32_t count, neg;
+
+ SQrootResult.W = RSP_Vect[RSPOpC.rt].HW[EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)]];
+ if (SQrootResult.UW == 0) {
+ SQrootResult.UW = 0x7FFFFFFF;
+ } else if (SQrootResult.UW == 0xFFFF8000) {
+ SQrootResult.UW = 0xFFFF0000;
+ } else {
+ if (SQrootResult.W < 0) {
+ neg = 1;
+ SQrootResult.W = ~SQrootResult.W + 1;
+ } else {
+ neg = 0;
+ }
+ for (count = 15; count > 0; count--) {
+ if ((SQrootResult.W & (1 << count))) {
+ SQrootResult.W &= (0xFF80 >> (15 - count) );
+ count = 0;
+ }
+ }
+ //SQrootResult.W = sqrt(SQrootResult.W);
+ SQrootResult.W = (int32_t)(0x7FFFFFFF / (int32_t) sqrt((double) SQrootResult.W));
+ for (count = 31; count > 0; count--) {
+ if ((SQrootResult.W & (1 << count))) {
+ SQrootResult.W &= (0xFFFF8000 >> (31 - count) );
+ count = 0;
+ }
+ }
+ if (neg == 1) {
+ SQrootResult.W = ~SQrootResult.W;
+ }
+ }
+ for ( count = 0; count < 8; count++ ) {
+ RSP_ACCUM[count].HW[1] = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[count]];
+ }
+ RSP_Vect[RSPOpC.sa].HW[7 - (RSPOpC.rd & 0x7)] = SQrootResult.UHW[0];
+}
+
+void RSP_Vector_VRSQL (void) {
+ int32_t count, neg;
+
+ SQrootResult.UW = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)]] | SQroot.W;
+ if (SQrootResult.UW == 0) {
+ SQrootResult.UW = 0x7FFFFFFF;
+ } else if (SQrootResult.UW == 0xFFFF8000) {
+ SQrootResult.UW = 0xFFFF0000;
+ } else {
+ if (SQrootResult.W < 0) {
+ neg = 1;
+ if (SQrootResult.UHW[1] == 0xFFFF && SQrootResult.HW[0] < 0) {
+ SQrootResult.W = ~SQrootResult.W + 1;
+ } else {
+ SQrootResult.W = ~SQrootResult.W;
+ }
+ } else {
+ neg = 0;
+ }
+ for (count = 31; count > 0; count--) {
+ if ((SQrootResult.W & (1 << count))) {
+ SQrootResult.W &= (0xFF800000 >> (31 - count) );
+ count = 0;
+ }
+ }
+ SQrootResult.W = (int32_t)(0x7FFFFFFF / (int32_t) sqrt((double) SQrootResult.W));
+
+ for (count = 31; count > 0; count--) {
+ if ((SQrootResult.W & (1 << count))) {
+ SQrootResult.W &= (0xFFFF8000 >> (31 - count) );
+ count = 0;
+ }
+ }
+ if (neg == 1) {
+ SQrootResult.W = ~SQrootResult.W;
+ }
+ }
+ for ( count = 0; count < 8; count++ ) {
+ RSP_ACCUM[count].HW[1] = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[count]];
+ }
+ RSP_Vect[RSPOpC.sa].HW[7 - (RSPOpC.rd & 0x7)] = SQrootResult.UHW[0];
+}
+
+void RSP_Vector_VRSQH (void) {
+ int32_t count;
+
+ SQroot.UHW[1] = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)]];
+ for ( count = 0; count < 8; count++ ) {
+ RSP_ACCUM[count].HW[1] = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[count]];
+ }
+ RSP_Vect[RSPOpC.sa].UHW[7 - (RSPOpC.rd & 0x7)] = SQrootResult.UHW[1];
+}
+
+void RSP_Vector_VNOOP (void) {}
+/************************** lc2 functions **************************/
+void RSP_Opcode_LBV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset)) &0xFFF);
+ RSP_LBV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_LSV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 1)) &0xFFF);
+ RSP_LSV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_LLV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 2)) &0xFFF);
+ RSP_LLV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_LDV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 3)) &0xFFF);
+ RSP_LDV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_LQV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 4)) &0xFFF);
+ RSP_LQV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_LRV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 4)) &0xFFF);
+ RSP_LRV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_LPV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 3)) &0xFFF);
+ RSP_LPV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_LUV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 3)) &0xFFF);
+ RSP_LUV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_LHV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 4)) &0xFFF);
+ RSP_LHV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_LFV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 4)) &0xFFF);
+ RSP_LFV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_LTV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 4)) &0xFFF);
+ RSP_LTV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+/************************** sc2 functions **************************/
+void RSP_Opcode_SBV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset)) &0xFFF);
+ RSP_SBV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_SSV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 1)) &0xFFF);
+ RSP_SSV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_SLV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 2)) &0xFFF);
+ RSP_SLV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_SDV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 3)) &0xFFF);
+ RSP_SDV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_SQV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 4)) &0xFFF);
+ RSP_SQV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_SRV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 4)) &0xFFF);
+ RSP_SRV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_SPV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 3)) &0xFFF);
+ RSP_SPV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_SUV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 3)) &0xFFF);
+ RSP_SUV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_SHV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 4)) &0xFFF);
+ RSP_SHV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_SFV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 4)) &0xFFF);
+ RSP_SFV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_STV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 4)) &0xFFF);
+ RSP_STV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+void RSP_Opcode_SWV ( void ) {
+ uint32_t Address = ((RSP_GPR[RSPOpC.base].UW + (uint32_t)(RSPOpC.voffset << 4)) & 0xFFF);
+ RSP_SWV_DMEM( Address, RSPOpC.rt, RSPOpC.del);
+}
+
+/************************** Other functions **************************/
+
+void rsp_UnknownOpcode (void) {
+
+ printf("Unhandled RSP opcode (%08x)\n", RSPOpC.Hex);
+ //ExitThread(0);
+ exit(0);
+}
+
diff --git a/src/usf/rsp_mmx.c b/src/usf/rsp_mmx.c new file mode 100644 index 0000000..24d4022 --- /dev/null +++ b/src/usf/rsp_mmx.c @@ -0,0 +1,143 @@ +/*
+ * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator).
+ *
+ * (c) Copyright 2001 jabo (jabo@emulation64.com) and
+ * zilmar (zilmar@emulation64.com)
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+
+#include "rsp.h"
+#include "rsp_x86.h"
+#include "recompiler_cpu.h"
+#include "memory.h"
+
+#define PUTDST8(dest,value) (*((uint8_t *)(dest))=(uint8_t)(value)); dest += 1;
+#define PUTDST16(dest,value) (*((uint16_t *)(dest))=(uint16_t)(value)); dest += 2;
+#define PUTDST32(dest,value) (*((uint32_t *)(dest))=(uint32_t)(value)); dest += 4;
+#define PUTDST64(dest,value) {(*((uint64_t *)(dest))=(uint64_t)(value)); dest += 8;}
+
+void RSPMmxEmptyMultimediaState(void) {
+ PUTDST16(RSPRecompPos,0x770f);
+}
+
+void RSPMmxMoveRegToReg(int32_t Dest, int32_t Source) {
+ OPCODE_REG_REG(16,0x7f0f,Source,Dest);
+}
+
+void RSPMmxMoveQwordVariableToReg(int32_t Dest, void *Variable) {
+ OPCODE_REG_VARIABLE(,16,0x6f0f,Dest,Variable);
+}
+
+void RSPMmxMoveQwordRegToVariable(int32_t Dest, void *Variable) {
+ OPCODE_REG_VARIABLE(,16,0x7f0f,Dest,Variable);
+}
+
+void RSPMmxPorRegToReg(int32_t Dest, int32_t Source) {
+ OPCODE_REG_REG(16,0x7f0f,Source,Dest);
+}
+
+void RSPMmxPorVariableToReg(void * Variable, int32_t Dest) {
+ OPCODE_REG_VARIABLE(,16,0xeb0f,Dest,Variable);
+}
+
+void RSPMmxPandRegToReg(int32_t Dest, int32_t Source) {
+ OPCODE_REG_REG(16,0xdb0f,Dest,Source);
+}
+
+void RSPMmxPandVariableToReg(void * Variable, int32_t Dest) {
+ OPCODE_REG_VARIABLE(,16,0xdb0f,Dest,Variable);
+}
+
+void RSPMmxPandnRegToReg(int32_t Dest, int32_t Source) {
+ OPCODE_REG_REG(16,0xdf0f,Dest,Source);
+}
+
+void RSPMmxXorRegToReg(int32_t Dest, int32_t Source) {
+ OPCODE_REG_REG(16,0xef0f,Dest,Source);
+}
+
+void RSPMmxShuffleMemoryToReg(int32_t Dest, void * Variable, uint8_t Immed) {
+ OPCODE_REG_VARIABLE(,16,0x700f,Dest,(uint8_t*)Variable);
+ PUTDST8(RSPRecompPos, Immed);
+}
+
+void RSPMmxPmullwRegToReg(int32_t Dest, int32_t Source) {
+ OPCODE_REG_REG(16,0xd50f,Dest,Source);
+}
+
+void RSPMmxPmullwVariableToReg(int32_t Dest, void * Variable) {
+ OPCODE_REG_VARIABLE(,16,0xd50f,Dest,Variable);
+}
+
+void RSPMmxPmulhuwRegToReg(int32_t Dest, int32_t Source) {
+ OPCODE_REG_REG(16,0xe40f,Dest,Source);
+}
+
+void RSPMmxPmulhwRegToReg(int32_t Dest, int32_t Source) {
+ OPCODE_REG_REG(16,0xe50f,Dest,Source);
+}
+
+void RSPMmxPmulhwRegToVariable(int32_t Dest, void * Variable) {
+ OPCODE_REG_VARIABLE(,16,0xe50f,Dest,Variable);
+}
+
+void RSPMmxPsrlwImmed(int32_t Dest, uint8_t Immed) {
+ OPCODE_REG_REG(16,0xe50f,OP_D2,Dest);
+ PUTDST8(RSPRecompPos, Immed);
+}
+
+void RSPMmxPsrawImmed(int32_t Dest, uint8_t Immed) {
+ OPCODE_REG_REG(16,0x710f,OP_D4,Dest);
+ PUTDST8(RSPRecompPos, Immed);
+}
+
+void RSPMmxPsllwImmed(int32_t Dest, uint8_t Immed) {
+ OPCODE_REG_REG(16,0x710f,OP_D6,Dest);
+ PUTDST8(RSPRecompPos, Immed);
+}
+
+void RSPMmxPaddswRegToReg(int32_t Dest, int32_t Source) {
+ OPCODE_REG_REG(16,0xed0f,Dest,Source);
+}
+
+void RSPMmxPaddswVariableToReg(int32_t Dest, void * Variable) {
+ OPCODE_REG_VARIABLE(,16,0xed0f,Dest,Variable);
+}
+
+void RSPMmxPaddwRegToReg(int32_t Dest, int32_t Source) {
+ OPCODE_REG_REG(16,0xfd0f,Dest,Source);
+}
+
+void RSPMmxPackSignedDwords(int32_t Dest, int32_t Source) {
+ OPCODE_REG_REG(16,0x6b0f,Dest,Source);
+}
+
+void RSPMmxUnpackLowWord(int32_t Dest, int32_t Source) {
+ OPCODE_REG_REG(16,0x610f,Dest,Source);
+}
+
+void RSPMmxUnpackHighWord(int32_t Dest, int32_t Source) {
+ OPCODE_REG_REG(16,0x690f,Dest,Source);
+}
+
+void RSPMmxCompareGreaterWordRegToReg(int32_t Dest, int32_t Source) {
+ OPCODE_REG_REG(16,0x650f,Dest,Source);
+}
diff --git a/src/usf/rsp_recompiler_analysis.c b/src/usf/rsp_recompiler_analysis.c new file mode 100644 index 0000000..4c2877a --- /dev/null +++ b/src/usf/rsp_recompiler_analysis.c @@ -0,0 +1,1780 @@ +/*
+ * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator).
+ *
+ * (c) Copyright 2001 jabo (jabo@emulation64.com) and
+ * zilmar (zilmar@emulation64.com)
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+
+#include "rsp.h"
+#include "rsp_recompiler_cpu.h"
+
+#define RSP_SAFE_ANALYSIS /* makes optimization less risky (dlist useful) */
+
+/************************************************************
+** IsOpcodeNop
+**
+** Output: BOOLean whether opcode at PC is a NOP
+** Input: PC
+*************************************************************/
+
+int32_t IsOpcodeNop(uint32_t PC) {
+ RSPOPCODE RspOp;
+ RSP_LW_IMEM(PC, &RspOp.Hex);
+
+ if (RspOp.op == RSP_SPECIAL && RspOp.funct == RSP_SPECIAL_SLL) {
+ return (RspOp.rd == 0) ? 1 : 0;
+ }
+
+ return 0;
+}
+
+/************************************************************
+** IsNextInstructionMmx
+**
+** Output: determines EMMS status
+** Input: PC
+*************************************************************/
+
+int32_t IsNextInstructionMmx(uint32_t PC) {
+ RSPOPCODE RspOp;
+
+ if (IsMmxEnabled == 0)
+ return 0;
+
+ PC += 4;
+ if (PC >= 0x1000) return 0;
+ RSP_LW_IMEM(PC, &RspOp.Hex);
+
+ if (RspOp.op != RSP_CP2)
+ return 0;
+
+ if ((RspOp.rs & 0x10) != 0) {
+ switch (RspOp.funct) {
+ case RSP_VECTOR_VMULF:
+ case RSP_VECTOR_VMUDL: /* Warning: Not all handled? */
+ case RSP_VECTOR_VMUDM:
+ case RSP_VECTOR_VMUDN:
+ case RSP_VECTOR_VMUDH:
+ if (1 == WriteToAccum(7, PC)) {
+ return 0;
+ } else if ((RspOp.rs & 0x0f) >= 2 && (RspOp.rs & 0x0f) <= 7 && IsMmx2Enabled == 0) {
+ return 0;
+ } else
+ return 1;
+
+ case RSP_VECTOR_VAND:
+ case RSP_VECTOR_VOR:
+ case RSP_VECTOR_VXOR:
+ if (1 == WriteToAccum(Low16BitAccum, PC)) {
+ return 0;
+ } else if ((RspOp.rs & 0x0f) >= 2 && (RspOp.rs & 0x0f) <= 7 && IsMmx2Enabled == 0) {
+ return 0;
+ } else
+ return 1;
+
+ case RSP_VECTOR_VADD:
+ /* Requires no accumulator write! & No flags! */
+ if (WriteToAccum(Low16BitAccum, RSPCompilePC) == 1) {
+ return 0;
+ } else if (UseRspFlags(RSPCompilePC) == 1) {
+ return 0;
+ } else if ((RspOp.rs & 0x0f) >= 2 && (RspOp.rs & 0x0f) <= 7 && IsMmx2Enabled == 0) {
+ return 0;
+ } else
+ return 1;
+
+ default:
+ return 0;
+ }
+ } else
+ return 0;
+}
+
+/************************************************************
+** WriteToAccum2
+**
+** Output:
+** 1: Accumulation series
+** 0: Accumulator is reset after this op
+**
+** Input: PC, Location in accumulator
+*************************************************************/
+
+#define HIT_BRANCH 0x2
+
+uint32_t WriteToAccum2 (int32_t Location, int32_t PC, int32_t RecursiveCall) {
+ RSPOPCODE RspOp;
+ uint32_t BranchTarget = 0;
+ int32_t BranchImmed = 0;
+ uint32_t JumpTarget = 0;
+ int32_t JumpUncond = 0;
+
+ int32_t Instruction_State = RSPNextInstruction;
+
+ if (Compiler.bAccum == 0) return 1;
+
+ if (Instruction_State == DELAY_SLOT) {
+ return 1;
+ }
+
+ do {
+ PC += 4;
+ if (PC >= 0x1000) { return 1; }
+ RSP_LW_IMEM(PC, &RspOp.Hex);
+
+ switch (RspOp.op) {
+ case RSP_REGIMM:
+ switch (RspOp.rt) {
+ case RSP_REGIMM_BLTZ:
+ case RSP_REGIMM_BGEZ:
+ case RSP_REGIMM_BLTZAL:
+ case RSP_REGIMM_BGEZAL:
+ Instruction_State = DO_DELAY_SLOT;
+ break;
+ default:
+ CompilerWarning("Unkown opcode in WriteToAccum\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ break;
+ case RSP_SPECIAL:
+ switch (RspOp.funct) {
+ case RSP_SPECIAL_SLL:
+ case RSP_SPECIAL_SRL:
+ case RSP_SPECIAL_SRA:
+ case RSP_SPECIAL_SLLV:
+ case RSP_SPECIAL_SRLV:
+ case RSP_SPECIAL_SRAV:
+ case RSP_SPECIAL_ADD:
+ case RSP_SPECIAL_ADDU:
+ case RSP_SPECIAL_SUB:
+ case RSP_SPECIAL_SUBU:
+ case RSP_SPECIAL_AND:
+ case RSP_SPECIAL_OR:
+ case RSP_SPECIAL_XOR:
+ case RSP_SPECIAL_NOR:
+ case RSP_SPECIAL_SLT:
+ case RSP_SPECIAL_SLTU:
+ case RSP_SPECIAL_BREAK:
+ break;
+
+ case RSP_SPECIAL_JR:
+ Instruction_State = DO_DELAY_SLOT;
+ break;
+
+ default:
+ CompilerWarning("Unkown opcode in WriteToAccum\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ break;
+ case RSP_J:
+ case RSP_JAL:
+ if (!JumpTarget) {
+ JumpUncond = 1;
+ JumpTarget = (RspOp.target << 2) & 0xFFC;
+ }
+ Instruction_State = DO_DELAY_SLOT;
+ break;
+
+ case RSP_BEQ:
+ case RSP_BNE:
+ case RSP_BLEZ:
+ case RSP_BGTZ:
+ Instruction_State = DO_DELAY_SLOT;
+ BranchTarget = (PC + ((int16_t)RspOp.offset << 2) + 4) & 0xFFC;
+ BranchImmed = (int16_t)RspOp.offset;
+ break;
+ case RSP_ADDI:
+ case RSP_ADDIU:
+ case RSP_SLTI:
+ case RSP_SLTIU:
+ case RSP_ANDI:
+ case RSP_ORI:
+ case RSP_XORI:
+ case RSP_LUI:
+ case RSP_CP0:
+ break;
+
+ case RSP_CP2:
+ if ((RspOp.rs & 0x10) != 0) {
+ switch (RspOp.funct) {
+ case RSP_VECTOR_VMULF:
+ case RSP_VECTOR_VMUDL:
+ case RSP_VECTOR_VMUDM:
+ case RSP_VECTOR_VMUDN:
+ case RSP_VECTOR_VMUDH:
+ return 0;
+ case RSP_VECTOR_VMACF:
+ case RSP_VECTOR_VMADL:
+ case RSP_VECTOR_VMADM:
+ case RSP_VECTOR_VMADN:
+ case RSP_VECTOR_VMADH:
+ return 1;
+ case RSP_VECTOR_VABS: // hope this is ok
+ case RSP_VECTOR_VADD:
+ case RSP_VECTOR_VADDC:
+ case RSP_VECTOR_VSUB:
+ case RSP_VECTOR_VSUBC:
+ case RSP_VECTOR_VAND:
+ case RSP_VECTOR_VOR:
+ case RSP_VECTOR_VXOR:
+ case RSP_VECTOR_VNXOR:
+ case RSP_VECTOR_VCR:
+ case RSP_VECTOR_VCH:
+ case RSP_VECTOR_VCL:
+ case RSP_VECTOR_VRCP:
+ case RSP_VECTOR_VRCPL: // hope this is ok
+ case RSP_VECTOR_VRCPH:
+ case RSP_VECTOR_VRSQL:
+ case RSP_VECTOR_VRSQH: // hope this is ok
+ case RSP_VECTOR_VLT:
+ case RSP_VECTOR_VEQ:
+ case RSP_VECTOR_VGE:
+ if (Location == Low16BitAccum) { return 0; }
+ break;
+
+ case RSP_VECTOR_VMOV:
+ case RSP_VECTOR_VMRG:
+ break;
+ case RSP_VECTOR_VSAW:
+ return 1;
+ default:
+ CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ } else {
+ switch (RspOp.rs) {
+ case RSP_COP2_CF:
+ case RSP_COP2_CT:
+ case RSP_COP2_MT:
+ case RSP_COP2_MF:
+ break;
+ default:
+ CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ }
+ break;
+ case RSP_LB:
+ case RSP_LH:
+ case RSP_LW:
+ case RSP_LBU:
+ case RSP_LHU:
+ case RSP_SB:
+ case RSP_SH:
+ case RSP_SW:
+ break;
+ case RSP_LC2:
+ switch (RspOp.rd) {
+ case RSP_LSC2_SV:
+ case RSP_LSC2_DV:
+ case RSP_LSC2_RV:
+ case RSP_LSC2_QV:
+ case RSP_LSC2_LV:
+ case RSP_LSC2_UV:
+ case RSP_LSC2_PV:
+ case RSP_LSC2_TV:
+ break;
+ default:
+ CompilerWarning("Unkown opcode in WriteToAccum\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ break;
+ case RSP_SC2:
+ switch (RspOp.rd) {
+ case RSP_LSC2_BV:
+ case RSP_LSC2_SV:
+ case RSP_LSC2_LV:
+ case RSP_LSC2_DV:
+ case RSP_LSC2_QV:
+ case RSP_LSC2_RV:
+ case RSP_LSC2_PV:
+ case RSP_LSC2_UV:
+ case RSP_LSC2_HV:
+ case RSP_LSC2_FV:
+ case RSP_LSC2_WV:
+ case RSP_LSC2_TV:
+ break;
+ default:
+ CompilerWarning("Unkown opcode in WriteToAccum\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ break;
+ default:
+ CompilerWarning("Unkown opcode in WriteToAccum\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ switch (Instruction_State) {
+ case NORMAL: break;
+ case DO_DELAY_SLOT:
+ Instruction_State = DELAY_SLOT;
+ break;
+ case DELAY_SLOT:
+ if (JumpUncond) {
+ PC = JumpTarget - 0x04;
+ Instruction_State = NORMAL;
+ } else {
+ Instruction_State = FINISH_BLOCK;
+ }
+ JumpUncond = 0;
+ break;
+ }
+ } while (Instruction_State != FINISH_BLOCK);
+
+ /***
+ ** This is a tricky situation because most of the
+ ** microcode does loops, so looping back and checking
+ ** can prove effective, but it's still a branch..
+ ***/
+
+ if (BranchTarget != 0 && RecursiveCall == 0) {
+ uint32_t BranchTaken, BranchFall;
+
+ /* analysis of branch taken */
+ BranchTaken = WriteToAccum2(Location, BranchTarget - 4, 1);
+ /* analysis of branch as nop */
+ BranchFall = WriteToAccum2(Location, PC, 1);
+
+ if (BranchImmed < 0) {
+ if (BranchTaken != 0) {
+ /*
+ ** took this back branch and couldnt find a place
+ ** that resets the accum or hit a branch etc
+ **/
+ return 1;
+ } else if (BranchFall == HIT_BRANCH) {
+ /* risky? the loop ended, hit another branch after loop-back */
+
+#if !defined(RSP_SAFE_ANALYSIS)
+ CPU_Message("WriteToDest: Backward branch hit, BranchFall = Hit branch (returning 0)");
+ return 0;
+#endif
+ return 1;
+ } else {
+ /* otherwise this is completely valid */
+ return BranchFall;
+ }
+ } else {
+ if (BranchFall != 0) {
+ /*
+ ** took this forward branch and couldnt find a place
+ ** that resets the accum or hit a branch etc
+ **/
+ return 1;
+ } else if (BranchTaken == HIT_BRANCH) {
+ /* risky? jumped forward, hit another branch */
+
+#if !defined(RSP_SAFE_ANALYSIS)
+ CPU_Message("WriteToDest: Forward branch hit, BranchTaken = Hit branch (returning 0)");
+ return 0;
+#endif
+
+ return 1;
+ } else {
+ /* otherwise this is completely valid */
+ return BranchTaken;
+ }
+ }
+ } else {
+ return HIT_BRANCH;
+ }
+}
+
+int32_t WriteToAccum (int32_t Location, int32_t PC) {
+ uint32_t value = WriteToAccum2(Location, PC, 0);
+
+ if (value == HIT_BRANCH) {
+ return 1; /* ??? */
+ } else
+ return value;
+}
+
+/************************************************************
+** WriteToVectorDest
+**
+** Output:
+** 1: Destination is over-written later
+** 0: Destination is used as a source later
+**
+** Input: PC, Register
+*************************************************************/
+
+int32_t WriteToVectorDest2 (uint32_t DestReg, int32_t PC, int32_t RecursiveCall) {
+ RSPOPCODE RspOp;
+ uint32_t BranchTarget = 0;
+ int32_t BranchImmed = 0;
+ uint32_t JumpTarget = 0;
+ int32_t JumpUncond = 0;
+
+ int32_t Instruction_State = RSPNextInstruction;
+
+ if (Compiler.bDest == 0) return 1;
+
+ if (Instruction_State == DELAY_SLOT) {
+ return 1;
+ }
+
+ do {
+ PC += 4;
+ if (PC >= 0x1000) { return 1; }
+ RSP_LW_IMEM(PC, &RspOp.Hex);
+
+ switch (RspOp.op) {
+
+ case RSP_REGIMM:
+ switch (RspOp.rt) {
+ case RSP_REGIMM_BLTZ:
+ case RSP_REGIMM_BGEZ:
+ case RSP_REGIMM_BLTZAL:
+ case RSP_REGIMM_BGEZAL:
+ Instruction_State = DO_DELAY_SLOT;
+ break;
+ default:
+ CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ break;
+ case RSP_SPECIAL:
+ switch (RspOp.funct) {
+ case RSP_SPECIAL_SLL:
+ case RSP_SPECIAL_SRL:
+ case RSP_SPECIAL_SRA:
+ case RSP_SPECIAL_SLLV:
+ case RSP_SPECIAL_SRLV:
+ case RSP_SPECIAL_SRAV:
+ case RSP_SPECIAL_ADD:
+ case RSP_SPECIAL_ADDU:
+ case RSP_SPECIAL_SUB:
+ case RSP_SPECIAL_SUBU:
+ case RSP_SPECIAL_AND:
+ case RSP_SPECIAL_OR:
+ case RSP_SPECIAL_XOR:
+ case RSP_SPECIAL_NOR:
+ case RSP_SPECIAL_SLT:
+ case RSP_SPECIAL_SLTU:
+ case RSP_SPECIAL_BREAK:
+ break;
+
+ case RSP_SPECIAL_JR:
+ Instruction_State = DO_DELAY_SLOT;
+ break;
+
+ default:
+ CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ break;
+ case RSP_J:
+ case RSP_JAL:
+ if (!JumpTarget) {
+ JumpUncond = 1;
+ JumpTarget = (RspOp.target << 2) & 0xFFC;
+ }
+ Instruction_State = DO_DELAY_SLOT;
+ break;
+ case RSP_BEQ:
+ case RSP_BNE:
+ case RSP_BLEZ:
+ case RSP_BGTZ:
+ Instruction_State = DO_DELAY_SLOT;
+ BranchTarget = (PC + ((int16_t)RspOp.offset << 2) + 4) & 0xFFC;
+ BranchImmed = (int16_t)RspOp.offset;
+ break;
+ case RSP_ADDI:
+ case RSP_ADDIU:
+ case RSP_SLTI:
+ case RSP_SLTIU:
+ case RSP_ANDI:
+ case RSP_ORI:
+ case RSP_XORI:
+ case RSP_LUI:
+ case RSP_CP0:
+ break;
+
+ case RSP_CP2:
+ if ((RspOp.rs & 0x10) != 0) {
+ switch (RspOp.funct) {
+ case RSP_VECTOR_VMULF:
+ case RSP_VECTOR_VMUDL:
+ case RSP_VECTOR_VMUDM:
+ case RSP_VECTOR_VMUDN:
+ case RSP_VECTOR_VMUDH:
+ case RSP_VECTOR_VMACF:
+ case RSP_VECTOR_VMADL:
+ case RSP_VECTOR_VMADM:
+ case RSP_VECTOR_VMADN:
+ case RSP_VECTOR_VMADH:
+ case RSP_VECTOR_VADD:
+ case RSP_VECTOR_VADDC:
+ case RSP_VECTOR_VSUB:
+ case RSP_VECTOR_VSUBC:
+ case RSP_VECTOR_VAND:
+ case RSP_VECTOR_VOR:
+ case RSP_VECTOR_VXOR:
+ case RSP_VECTOR_VNXOR:
+ case RSP_VECTOR_VABS:
+ if (DestReg == RspOp.rd) { return 1; }
+ if (DestReg == RspOp.rt) { return 1; }
+ if (DestReg == RspOp.sa) { return 0; }
+ break;
+
+ case RSP_VECTOR_VMOV:
+ if (DestReg == RspOp.rt) { return 1; }
+ break;
+
+ case RSP_VECTOR_VCR:
+ case RSP_VECTOR_VRCP:
+ case RSP_VECTOR_VRCPH:
+ case RSP_VECTOR_VRSQH:
+ case RSP_VECTOR_VCH:
+ case RSP_VECTOR_VCL:
+ return 1;
+
+ case RSP_VECTOR_VMRG:
+ case RSP_VECTOR_VLT:
+ case RSP_VECTOR_VEQ:
+ case RSP_VECTOR_VGE:
+ if (DestReg == RspOp.rd) { return 1; }
+ if (DestReg == RspOp.rt) { return 1; }
+ if (DestReg == RspOp.sa) { return 0; }
+ break;
+ case RSP_VECTOR_VSAW:
+ if (DestReg == RspOp.sa) { return 0; }
+ break;
+ default:
+ CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ } else {
+ switch (RspOp.rs) {
+ case RSP_COP2_CF:
+ case RSP_COP2_CT:
+ break;
+ case RSP_COP2_MT:
+ /* if (DestReg == RspOp.rd) { return 0; } */
+ break;
+ case RSP_COP2_MF:
+ if (DestReg == RspOp.rd) { return 1; }
+ break;
+ default:
+ CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ }
+ break;
+ case RSP_LB:
+ case RSP_LH:
+ case RSP_LW:
+ case RSP_LBU:
+ case RSP_LHU:
+ case RSP_SB:
+ case RSP_SH:
+ case RSP_SW:
+ break;
+ case RSP_LC2:
+ switch (RspOp.rd) {
+ case RSP_LSC2_SV:
+ case RSP_LSC2_DV:
+ case RSP_LSC2_RV:
+ break;
+
+ case RSP_LSC2_QV:
+ case RSP_LSC2_LV:
+ case RSP_LSC2_UV:
+ case RSP_LSC2_PV:
+ case RSP_LSC2_TV:
+ break;
+
+ default:
+ CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ break;
+ case RSP_SC2:
+ switch (RspOp.rd) {
+ case RSP_LSC2_BV:
+ case RSP_LSC2_SV:
+ case RSP_LSC2_LV:
+ case RSP_LSC2_DV:
+ case RSP_LSC2_QV:
+ case RSP_LSC2_RV:
+ case RSP_LSC2_PV:
+ case RSP_LSC2_UV:
+ case RSP_LSC2_HV:
+ case RSP_LSC2_FV:
+ case RSP_LSC2_WV:
+ case RSP_LSC2_TV:
+ if (DestReg == RspOp.rt) { return 1; }
+ break;
+ default:
+ CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ break;
+ default:
+ CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ switch (Instruction_State) {
+ case NORMAL: break;
+ case DO_DELAY_SLOT:
+ Instruction_State = DELAY_SLOT;
+ break;
+ case DELAY_SLOT:
+ if (JumpUncond) {
+ PC = JumpTarget - 0x04;
+ Instruction_State = NORMAL;
+ } else {
+ Instruction_State = FINISH_BLOCK;
+ }
+ JumpUncond = 0;
+ break;
+ }
+ } while (Instruction_State != FINISH_BLOCK);
+
+ /***
+ ** This is a tricky situation because most of the
+ ** microcode does loops, so looping back and checking
+ ** can prove effective, but it's still a branch..
+ ***/
+
+ if (BranchTarget != 0 && RecursiveCall == 0) {
+ uint32_t BranchTaken, BranchFall;
+
+ /* analysis of branch taken */
+ BranchTaken = WriteToVectorDest2(DestReg, BranchTarget - 4, 1);
+ /* analysis of branch as nop */
+ BranchFall = WriteToVectorDest2(DestReg, PC, 1);
+
+ if (BranchImmed < 0) {
+ if (BranchTaken != 0) {
+ /*
+ ** took this back branch and found a place
+ ** that needs this vector as a source
+ **/
+ return 1;
+ } else if (BranchFall == HIT_BRANCH) {
+ /* (dlist) risky? the loop ended, hit another branch after loop-back */
+
+#if !defined(RSP_SAFE_ANALYSIS)
+ CPU_Message("WriteToDest: Backward branch hit, BranchFall = Hit branch (returning 0)");
+ return 0;
+#endif
+
+ return 1;
+ } else {
+ /* otherwise this is completely valid */
+ return BranchFall;
+ }
+ } else {
+ if (BranchFall != 0) {
+ /*
+ ** took this forward branch and found a place
+ ** that needs this vector as a source
+ **/
+ return 1;
+ } else if (BranchTaken == HIT_BRANCH) {
+ /* (dlist) risky? jumped forward, hit another branch */
+
+#if !defined(RSP_SAFE_ANALYSIS)
+ CPU_Message("WriteToDest: Forward branch hit, BranchTaken = Hit branch (returning 0)");
+ return 0;
+#endif
+
+ return 1;
+ } else {
+ /* otherwise this is completely valid */
+ return BranchTaken;
+ }
+ }
+ } else {
+ return HIT_BRANCH;
+ }
+}
+
+int32_t WriteToVectorDest (uint32_t DestReg, int32_t PC) {
+ uint32_t value = WriteToVectorDest2(DestReg, PC, 0);
+
+ if (value == HIT_BRANCH) {
+ return 1; /* ??? */
+ } else
+ return value;
+}
+
+/************************************************************
+** UseRspFlags
+**
+** Output:
+** 1: Flags are determined not in use
+** 0: Either unable to determine or are in use
+**
+** Input: PC
+*************************************************************/
+
+/* TODO: consider delay slots and such in a branch? */
+int32_t UseRspFlags (int32_t PC) {
+ RSPOPCODE RspOp;
+ int32_t Instruction_State = RSPNextInstruction;
+
+ if (Compiler.bFlags == 0) return 1;
+
+ if (Instruction_State == DELAY_SLOT) {
+ return 1;
+ }
+
+ do {
+ PC -= 4;
+ if (PC < 0) { return 1; }
+ RSP_LW_IMEM(PC, &RspOp.Hex);
+
+ switch (RspOp.op) {
+
+ case RSP_REGIMM:
+ switch (RspOp.rt) {
+ case RSP_REGIMM_BLTZ:
+ case RSP_REGIMM_BGEZ:
+ Instruction_State = DO_DELAY_SLOT;
+ break;
+ default:
+ CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ break;
+ case RSP_SPECIAL:
+ switch (RspOp.funct) {
+ case RSP_SPECIAL_SLL:
+ case RSP_SPECIAL_SRL:
+ case RSP_SPECIAL_SRA:
+ case RSP_SPECIAL_SLLV:
+ case RSP_SPECIAL_SRLV:
+ case RSP_SPECIAL_SRAV:
+ case RSP_SPECIAL_ADD:
+ case RSP_SPECIAL_ADDU:
+ case RSP_SPECIAL_SUB:
+ case RSP_SPECIAL_SUBU:
+ case RSP_SPECIAL_AND:
+ case RSP_SPECIAL_OR:
+ case RSP_SPECIAL_XOR:
+ case RSP_SPECIAL_NOR:
+ case RSP_SPECIAL_SLT:
+ case RSP_SPECIAL_SLTU:
+ case RSP_SPECIAL_BREAK:
+ break;
+
+ case RSP_SPECIAL_JR:
+ Instruction_State = DO_DELAY_SLOT;
+ break;
+
+ default:
+ CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ break;
+ case RSP_J:
+ case RSP_JAL:
+ case RSP_BEQ:
+ case RSP_BNE:
+ case RSP_BLEZ:
+ case RSP_BGTZ:
+ Instruction_State = DO_DELAY_SLOT;
+ break;
+ case RSP_ADDI:
+ case RSP_ADDIU:
+ case RSP_SLTI:
+ case RSP_SLTIU:
+ case RSP_ANDI:
+ case RSP_ORI:
+ case RSP_XORI:
+ case RSP_LUI:
+ case RSP_CP0:
+ break;
+
+ case RSP_CP2:
+ if ((RspOp.rs & 0x10) != 0) {
+ switch (RspOp.funct) {
+ case RSP_VECTOR_VMULF:
+ case RSP_VECTOR_VMUDL:
+ case RSP_VECTOR_VMUDM:
+ case RSP_VECTOR_VMUDN:
+ case RSP_VECTOR_VMUDH:
+ break;
+ case RSP_VECTOR_VMACF:
+ case RSP_VECTOR_VMADL:
+ case RSP_VECTOR_VMADM:
+ case RSP_VECTOR_VMADN:
+ case RSP_VECTOR_VMADH:
+ break;
+
+ case RSP_VECTOR_VSUB:
+ case RSP_VECTOR_VADD:
+ return 0;
+ case RSP_VECTOR_VSUBC:
+ case RSP_VECTOR_VADDC:
+ return 1;
+
+ case RSP_VECTOR_VABS:
+ case RSP_VECTOR_VAND:
+ case RSP_VECTOR_VOR:
+ case RSP_VECTOR_VXOR:
+ case RSP_VECTOR_VRCPH:
+ case RSP_VECTOR_VRSQL:
+ case RSP_VECTOR_VRSQH:
+ case RSP_VECTOR_VRCPL:
+ case RSP_VECTOR_VRCP:
+ break;
+
+ case RSP_VECTOR_VCR:
+ case RSP_VECTOR_VCH:
+ case RSP_VECTOR_VCL:
+ case RSP_VECTOR_VLT:
+ case RSP_VECTOR_VEQ:
+ case RSP_VECTOR_VGE:
+ case RSP_VECTOR_VMRG:
+ return 1;
+
+ case RSP_VECTOR_VSAW:
+ case RSP_VECTOR_VMOV:
+ break;
+
+ default:
+ CompilerWarning("Unkown opcode in UseRspFlags\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ } else {
+ switch (RspOp.rs) {
+ case RSP_COP2_CT:
+ return 1;
+
+ case RSP_COP2_CF:
+ case RSP_COP2_MT:
+ case RSP_COP2_MF:
+ break;
+ default:
+ CompilerWarning("Unkown opcode in UseRspFlags\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ }
+ break;
+ case RSP_LB:
+ case RSP_LH:
+ case RSP_LW:
+ case RSP_LBU:
+ case RSP_LHU:
+ case RSP_SB:
+ case RSP_SH:
+ case RSP_SW:
+ break;
+ case RSP_LC2:
+ switch (RspOp.rd) {
+ case RSP_LSC2_SV:
+ case RSP_LSC2_DV:
+ case RSP_LSC2_RV:
+ case RSP_LSC2_QV:
+ case RSP_LSC2_LV:
+ case RSP_LSC2_UV:
+ case RSP_LSC2_PV:
+ case RSP_LSC2_TV:
+ break;
+ default:
+ CompilerWarning("Unkown opcode in UseRspFlags\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ break;
+ case RSP_SC2:
+ switch (RspOp.rd) {
+ case RSP_LSC2_BV:
+ case RSP_LSC2_SV:
+ case RSP_LSC2_LV:
+ case RSP_LSC2_DV:
+ case RSP_LSC2_QV:
+ case RSP_LSC2_RV:
+ case RSP_LSC2_PV:
+ case RSP_LSC2_UV:
+ case RSP_LSC2_HV:
+ case RSP_LSC2_FV:
+ case RSP_LSC2_WV:
+ case RSP_LSC2_TV:
+ break;
+ default:
+ CompilerWarning("Unkown opcode in UseRspFlags\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ break;
+ default:
+ CompilerWarning("Unkown opcode in UseRspFlags\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ return 1;
+ }
+ switch (Instruction_State) {
+ case NORMAL: break;
+ case DO_DELAY_SLOT:
+ Instruction_State = DELAY_SLOT;
+ break;
+ case DELAY_SLOT:
+ Instruction_State = FINISH_BLOCK;
+ break;
+ }
+ } while ( Instruction_State != FINISH_BLOCK);
+ return 1;
+}
+
+/************************************************************
+** IsRegisterConstant
+**
+** Output:
+** 1: Register is constant throughout
+** 0: Register is not constant at all
+**
+** Input: PC, Pointer to constant to fill
+*************************************************************/
+
+int32_t IsRegisterConstant (uint32_t Reg, uint32_t * Constant) {
+ uint32_t PC = 0;
+ uint32_t References = 0;
+ uint32_t Const = 0;
+ RSPOPCODE RspOp;
+
+ if (Compiler.bGPRConstants == 0)
+ return 0;
+
+ while (PC < 0x1000) {
+
+ RSP_LW_IMEM(PC, &RspOp.Hex);
+ PC += 4;
+
+ switch (RspOp.op) {
+ case RSP_REGIMM:
+ break;
+
+ case RSP_SPECIAL:
+ switch (RspOp.funct) {
+ case RSP_SPECIAL_SLL:
+ case RSP_SPECIAL_SRL:
+ case RSP_SPECIAL_SRA:
+ case RSP_SPECIAL_SLLV:
+ case RSP_SPECIAL_SRLV:
+ case RSP_SPECIAL_SRAV:
+ case RSP_SPECIAL_ADD:
+ case RSP_SPECIAL_ADDU:
+ case RSP_SPECIAL_SUB:
+ case RSP_SPECIAL_SUBU:
+ case RSP_SPECIAL_AND:
+ case RSP_SPECIAL_OR:
+ case RSP_SPECIAL_XOR:
+ case RSP_SPECIAL_NOR:
+ case RSP_SPECIAL_SLT:
+ case RSP_SPECIAL_SLTU:
+ if (RspOp.rd == Reg) { return 0; }
+ break;
+
+ case RSP_SPECIAL_BREAK:
+ case RSP_SPECIAL_JR:
+ break;
+
+ default:
+ // CompilerWarning("Unkown opcode in IsRegisterConstant\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ // return 0;
+ break;
+ }
+ break;
+
+ case RSP_J:
+ case RSP_JAL:
+ case RSP_BEQ:
+ case RSP_BNE:
+ case RSP_BLEZ:
+ case RSP_BGTZ:
+ break;
+
+ case RSP_ADDI:
+ case RSP_ADDIU:
+ if (RspOp.rt == Reg) {
+ if (!RspOp.rs) {
+ if (References > 0) { return 0; }
+ Const = (int16_t)RspOp.immediate;
+ References++;
+ } else
+ return 0;
+ }
+ break;
+ case RSP_ORI:
+ if (RspOp.rt == Reg) {
+ if (!RspOp.rs) {
+ if (References > 0) { return 0; }
+ Const = (uint16_t)RspOp.immediate;
+ References++;
+ } else
+ return 0;
+ }
+ break;
+
+ case RSP_LUI:
+ if (RspOp.rt == Reg) {
+ if (References > 0) { return 0; }
+ Const = (int16_t)RspOp.offset << 16;
+ References++;
+ }
+ break;
+
+ case RSP_ANDI:
+ case RSP_XORI:
+ case RSP_SLTI:
+ case RSP_SLTIU:
+ if (RspOp.rt == Reg) { return 0; }
+ break;
+
+ case RSP_CP0:
+ switch (RspOp.rs) {
+ case RSP_COP0_MF:
+ if (RspOp.rt == Reg) { return 0; }
+ case RSP_COP0_MT:
+ break;
+ }
+ break;
+
+ case RSP_CP2:
+ if ((RspOp.rs & 0x10) == 0) {
+ switch (RspOp.rs) {
+ case RSP_COP2_CT:
+ case RSP_COP2_MT:
+ break;
+
+ case RSP_COP2_CF:
+ case RSP_COP2_MF:
+ if (RspOp.rt == Reg) { return 0; }
+ break;
+
+ default:
+ // CompilerWarning("Unkown opcode in IsRegisterConstant\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ // return 0;
+ break;
+ }
+ }
+ break;
+
+ case RSP_LB:
+ case RSP_LH:
+ case RSP_LW:
+ case RSP_LBU:
+ case RSP_LHU:
+ if (RspOp.rt == Reg) { return 0; }
+ break;
+
+ case RSP_SB:
+ case RSP_SH:
+ case RSP_SW:
+ break;
+ case RSP_LC2:
+ break;
+ case RSP_SC2:
+ break;
+ default:
+ // CompilerWarning("Unkown opcode in IsRegisterConstant\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ // return 0;
+ break;
+ }
+ }
+
+ if (References > 0) {
+ *Constant = Const;
+ return 1;
+ } else {
+ *Constant = 0;
+ return 0;
+ }
+}
+
+/************************************************************
+** IsOpcodeBranch
+**
+** Output:
+** 1: opcode is a branch
+** 0: opcode is not a branch
+**
+** Input: PC
+*************************************************************/
+
+int32_t IsOpcodeBranch(uint32_t PC, RSPOPCODE RspOp) {
+ switch (RspOp.op) {
+ case RSP_REGIMM:
+ switch (RspOp.rt) {
+ case RSP_REGIMM_BLTZ:
+ case RSP_REGIMM_BGEZ:
+ case RSP_REGIMM_BLTZAL:
+ case RSP_REGIMM_BGEZAL:
+ return 1;
+ default:
+ //CompilerWarning("Unknown opcode in IsOpcodeBranch\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ break;
+ }
+ break;
+ case RSP_SPECIAL:
+ switch (RspOp.funct) {
+ case RSP_SPECIAL_SLL:
+ case RSP_SPECIAL_SRL:
+ case RSP_SPECIAL_SRA:
+ case RSP_SPECIAL_SLLV:
+ case RSP_SPECIAL_SRLV:
+ case RSP_SPECIAL_SRAV:
+ case RSP_SPECIAL_ADD:
+ case RSP_SPECIAL_ADDU:
+ case RSP_SPECIAL_SUB:
+ case RSP_SPECIAL_SUBU:
+ case RSP_SPECIAL_AND:
+ case RSP_SPECIAL_OR:
+ case RSP_SPECIAL_XOR:
+ case RSP_SPECIAL_NOR:
+ case RSP_SPECIAL_SLT:
+ case RSP_SPECIAL_SLTU:
+ case RSP_SPECIAL_BREAK:
+ break;
+
+ case RSP_SPECIAL_JALR:
+ case RSP_SPECIAL_JR:
+ return 1;
+
+ default:
+ //CompilerWarning("Unknown opcode in IsOpcodeBranch\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ break;
+ }
+ break;
+ case RSP_J:
+ case RSP_JAL:
+ case RSP_BEQ:
+ case RSP_BNE:
+ case RSP_BLEZ:
+ case RSP_BGTZ:
+ return 1;
+
+ case RSP_ADDI:
+ case RSP_ADDIU:
+ case RSP_SLTI:
+ case RSP_SLTIU:
+ case RSP_ANDI:
+ case RSP_ORI:
+ case RSP_XORI:
+ case RSP_LUI:
+
+ case RSP_CP0:
+ case RSP_CP2:
+ break;
+
+ case RSP_LB:
+ case RSP_LH:
+ case RSP_LW:
+ case RSP_LBU:
+ case RSP_LHU:
+ case RSP_SB:
+ case RSP_SH:
+ case RSP_SW:
+ break;
+
+ case RSP_LC2:
+ case RSP_SC2:
+ break;
+
+ default:
+ //CompilerWarning("Unknown opcode in IsOpcodeBranch\n%s",RSPOpcodeName(RspOp.Hex,PC));
+ break;
+ }
+
+ return 0;
+}
+
+/************************************************************
+** GetInstructionInfo
+**
+** Output: None in regard to return value
+**
+** Input:
+** pointer to info structure, fills this
+** with valid opcode data
+*************************************************************/
+
+/* 3 possible values, GPR, VEC, VEC & GPR, NOOP is zero */
+#define GPR_Instruction 0x0001 /* GPR Instruction flag */
+#define VEC_Instruction 0x0002 /* Vec Instruction flag */
+#define Instruction_Mask (GPR_Instruction | VEC_Instruction)
+
+/* 3 possible values, one flag must be set only */
+#define Load_Operation 0x0004 /* Load Instruction flag */
+#define Store_Operation 0x0008 /* Store Instruction flag */
+#define Accum_Operation 0x0010 /* Vector op uses accum - loads & stores dont */
+#define MemOperation_Mask (Load_Operation | Store_Operation)
+#define Operation_Mask (MemOperation_Mask | Accum_Operation)
+
+/* Per situation basis flags */
+#define VEC_ResetAccum 0x0000 /* Vector op resets acc */
+#define VEC_Accumulate 0x0020 /* Vector op accumulates */
+
+#define InvalidOpcode 0x0040
+
+typedef struct {
+ union {
+ uint32_t DestReg;
+ uint32_t StoredReg;
+ };
+ union {
+ uint32_t SourceReg0;
+ uint32_t IndexReg;
+ };
+ uint32_t SourceReg1;
+ uint32_t flags;
+} OPCODE_INFO;
+
+void GetInstructionInfo(uint32_t PC, RSPOPCODE * RspOp, OPCODE_INFO * info) {
+ switch (RspOp->op) {
+ case RSP_REGIMM:
+ switch (RspOp->rt) {
+ case RSP_REGIMM_BLTZ:
+ case RSP_REGIMM_BLTZAL:
+ case RSP_REGIMM_BGEZ:
+ case RSP_REGIMM_BGEZAL:
+ info->flags = InvalidOpcode;
+ info->SourceReg0 = RspOp->rs;
+ info->SourceReg1 = -1;
+ break;
+
+ default:
+ CompilerWarning("Unkown opcode in GetInstructionInfo\n%s",RSPOpcodeName(RspOp->Hex,PC));
+ info->flags = InvalidOpcode;
+ break;
+ }
+ break;
+ case RSP_SPECIAL:
+ switch (RspOp->funct) {
+ case RSP_SPECIAL_BREAK:
+ info->DestReg = -1;
+ info->SourceReg0 = -1;
+ info->SourceReg1 = -1;
+ info->flags = GPR_Instruction;
+ break;
+
+ case RSP_SPECIAL_SLL:
+ case RSP_SPECIAL_SRL:
+ case RSP_SPECIAL_SRA:
+ info->DestReg = RspOp->rd;
+ info->SourceReg0 = RspOp->rt;
+ info->SourceReg1 = -1;
+ info->flags = GPR_Instruction;
+ break;
+ case RSP_SPECIAL_SLLV:
+ case RSP_SPECIAL_SRLV:
+ case RSP_SPECIAL_SRAV:
+ case RSP_SPECIAL_ADD:
+ case RSP_SPECIAL_ADDU:
+ case RSP_SPECIAL_SUB:
+ case RSP_SPECIAL_SUBU:
+ case RSP_SPECIAL_AND:
+ case RSP_SPECIAL_OR:
+ case RSP_SPECIAL_XOR:
+ case RSP_SPECIAL_NOR:
+ case RSP_SPECIAL_SLT:
+ case RSP_SPECIAL_SLTU:
+ info->DestReg = RspOp->rd;
+ info->SourceReg0 = RspOp->rs;
+ info->SourceReg1 = RspOp->rt;
+ info->flags = GPR_Instruction;
+ break;
+
+ case RSP_SPECIAL_JR:
+ info->flags = InvalidOpcode;
+ info->SourceReg0 = -1;
+ info->SourceReg1 = -1;
+ break;
+
+ default:
+ CompilerWarning("Unkown opcode in GetInstructionInfo\n%s",RSPOpcodeName(RspOp->Hex,PC));
+ info->flags = InvalidOpcode;
+ break;
+ }
+ break;
+ case RSP_J:
+ case RSP_JAL:
+ info->flags = InvalidOpcode;
+ info->SourceReg0 = -1;
+ info->SourceReg1 = -1;
+ break;
+ case RSP_BEQ:
+ case RSP_BNE:
+ info->flags = InvalidOpcode;
+ info->SourceReg0 = RspOp->rt;
+ info->SourceReg1 = RspOp->rs;
+ break;
+ case RSP_BLEZ:
+ case RSP_BGTZ:
+ info->flags = InvalidOpcode;
+ info->SourceReg0 = RspOp->rs;
+ info->SourceReg1 = -1;
+ break;
+
+ case RSP_ADDI:
+ case RSP_ADDIU:
+ case RSP_SLTI:
+ case RSP_SLTIU:
+ case RSP_ANDI:
+ case RSP_ORI:
+ case RSP_XORI:
+ info->DestReg = RspOp->rt;
+ info->SourceReg0 = RspOp->rs;
+ info->SourceReg1 = -1;
+ info->flags = GPR_Instruction;
+ break;
+
+ case RSP_LUI:
+ info->DestReg = RspOp->rt;
+ info->SourceReg0 = -1;
+ info->SourceReg1 = -1;
+ info->flags = GPR_Instruction;
+ break;
+
+ case RSP_CP0:
+ switch (RspOp->rs) {
+ case RSP_COP0_MF:
+ info->DestReg = RspOp->rt;
+ info->SourceReg0 = -1;
+ info->SourceReg1 = -1;
+ info->flags = GPR_Instruction | Load_Operation;
+ break;
+
+ case RSP_COP0_MT:
+ info->StoredReg = RspOp->rt;
+ info->SourceReg0 = -1;
+ info->SourceReg1 = -1;
+ info->flags = GPR_Instruction | Store_Operation;
+ break;
+ }
+ break;
+
+ case RSP_CP2:
+ if ((RspOp->rs & 0x10) != 0) {
+ switch (RspOp->funct) {
+ case RSP_VECTOR_VNOOP:
+ info->DestReg = -1;
+ info->SourceReg0 = -1;
+ info->SourceReg1 = -1;
+ info->flags = VEC_Instruction;
+ break;
+
+ case RSP_VECTOR_VMULF:
+ case RSP_VECTOR_VMUDL:
+ case RSP_VECTOR_VMUDM:
+ case RSP_VECTOR_VMUDN:
+ case RSP_VECTOR_VMUDH:
+ info->DestReg = RspOp->sa;
+ info->SourceReg0 = RspOp->rd;
+ info->SourceReg1 = RspOp->rt;
+ info->flags = VEC_Instruction | VEC_ResetAccum | Accum_Operation;
+ break;
+ case RSP_VECTOR_VMACF:
+ case RSP_VECTOR_VMADL:
+ case RSP_VECTOR_VMADM:
+ case RSP_VECTOR_VMADN:
+ case RSP_VECTOR_VMADH:
+ info->DestReg = RspOp->sa;
+ info->SourceReg0 = RspOp->rd;
+ info->SourceReg1 = RspOp->rt;
+ info->flags = VEC_Instruction | VEC_Accumulate | Accum_Operation;
+ break;
+ case RSP_VECTOR_VABS:
+ case RSP_VECTOR_VADD:
+ case RSP_VECTOR_VADDC:
+ case RSP_VECTOR_VSUB:
+ case RSP_VECTOR_VSUBC:
+ case RSP_VECTOR_VAND:
+ case RSP_VECTOR_VOR:
+ case RSP_VECTOR_VXOR:
+ case RSP_VECTOR_VNXOR:
+ case RSP_VECTOR_VCR:
+ case RSP_VECTOR_VCH:
+ case RSP_VECTOR_VCL:
+ case RSP_VECTOR_VRCP:
+ case RSP_VECTOR_VRCPL:
+ case RSP_VECTOR_VRCPH:
+ case RSP_VECTOR_VRSQL:
+ case RSP_VECTOR_VRSQH:
+ case RSP_VECTOR_VLT:
+ case RSP_VECTOR_VEQ:
+ case RSP_VECTOR_VGE:
+ info->DestReg = RspOp->sa;
+ info->SourceReg0 = RspOp->rd;
+ info->SourceReg1 = RspOp->rt;
+ info->flags = VEC_Instruction | VEC_ResetAccum | Accum_Operation;
+ break;
+
+ case RSP_VECTOR_VMOV:
+ info->flags = InvalidOpcode;
+ /* info->DestReg = RspOp->sa;
+ info->SourceReg0 = RspOp->rt;
+ info->SourceReg1 = -1;
+ info->flags = VEC_Instruction; /* Assume reset? */
+ break;
+
+ case RSP_VECTOR_VMRG:
+ info->flags = InvalidOpcode;
+ /* info->DestReg = RspOp->sa;
+ info->SourceReg0 = RspOp->rt;
+ info->SourceReg1 = RspOp->rd;
+ info->flags = VEC_Instruction; /* Assum reset? */
+ break;
+
+ case RSP_VECTOR_VSAW:
+ // info->flags = InvalidOpcode;
+ info->DestReg = RspOp->sa;
+ info->SourceReg0 = -1;
+ info->SourceReg1 = -1;
+ info->flags = VEC_Instruction | Accum_Operation | VEC_Accumulate;
+ break;
+
+ default:
+ CompilerWarning("Unkown opcode in GetInstructionInfo\n%s",RSPOpcodeName(RspOp->Hex,PC));
+ info->flags = InvalidOpcode;
+ break;
+ }
+ } else {
+ switch (RspOp->rs) {
+ case RSP_COP2_CT:
+ info->StoredReg = RspOp->rt;
+ info->SourceReg0 = -1;
+ info->SourceReg1 = -1;
+ info->flags = GPR_Instruction | Store_Operation;
+ break;
+ case RSP_COP2_CF:
+ info->DestReg = RspOp->rt;
+ info->SourceReg0 = -1;
+ info->SourceReg1 = -1;
+ info->flags = GPR_Instruction | Load_Operation;
+ break;
+
+ /* RD is always the vector register, RT is always GPR */
+ case RSP_COP2_MT:
+ info->DestReg = RspOp->rd;
+ info->SourceReg0 = RspOp->rt;
+ info->SourceReg1 = -1;
+ info->flags = VEC_Instruction | GPR_Instruction | Load_Operation;
+ break;
+ case RSP_COP2_MF:
+ info->DestReg = RspOp->rt;
+ info->SourceReg0 = RspOp->rd;
+ info->SourceReg1 = -1;
+ info->flags = VEC_Instruction | GPR_Instruction | Store_Operation;
+ break;
+ default:
+ CompilerWarning("Unkown opcode in GetInstructionInfo\n%s",RSPOpcodeName(RspOp->Hex,PC));
+ info->flags = InvalidOpcode;
+ break;
+ }
+ }
+ break;
+ case RSP_LB:
+ case RSP_LH:
+ case RSP_LW:
+ case RSP_LBU:
+ case RSP_LHU:
+ info->DestReg = RspOp->rt;
+ info->IndexReg = RspOp->base;
+ info->SourceReg1 = -1;
+ info->flags = Load_Operation | GPR_Instruction;
+ break;
+ case RSP_SB:
+ case RSP_SH:
+ case RSP_SW:
+ info->StoredReg = RspOp->rt;
+ info->IndexReg = RspOp->base;
+ info->SourceReg1 = -1;
+ info->flags = Store_Operation | GPR_Instruction;
+ break;
+ case RSP_LC2:
+ switch (RspOp->rd) {
+ case RSP_LSC2_SV:
+ case RSP_LSC2_DV:
+ case RSP_LSC2_RV:
+ case RSP_LSC2_QV:
+ case RSP_LSC2_LV:
+ case RSP_LSC2_UV:
+ case RSP_LSC2_PV:
+ info->DestReg = RspOp->rt;
+ info->IndexReg = RspOp->base;
+ info->SourceReg1 = -1;
+ info->flags = Load_Operation | VEC_Instruction;
+ break;
+
+ case RSP_LSC2_TV:
+ info->flags = InvalidOpcode;
+ break;
+ default:
+ CompilerWarning("Unkown opcode in GetInstructionInfo\n%s",RSPOpcodeName(RspOp->Hex,PC));
+ info->flags = InvalidOpcode;
+ break;
+ }
+ break;
+ case RSP_SC2:
+ switch (RspOp->rd) {
+ case RSP_LSC2_BV:
+ case RSP_LSC2_SV:
+ case RSP_LSC2_LV:
+ case RSP_LSC2_DV:
+ case RSP_LSC2_QV:
+ case RSP_LSC2_RV:
+ case RSP_LSC2_PV:
+ case RSP_LSC2_UV:
+ case RSP_LSC2_HV:
+ case RSP_LSC2_FV:
+ case RSP_LSC2_WV:
+ info->DestReg = RspOp->rt;
+ info->IndexReg = RspOp->base;
+ info->SourceReg1 = -1;
+ info->flags = Store_Operation | VEC_Instruction;
+ break;
+ case RSP_LSC2_TV:
+ info->flags = InvalidOpcode;
+ break;
+ default:
+ CompilerWarning("Unkown opcode in GetInstructionInfo\n%s",RSPOpcodeName(RspOp->Hex,PC));
+ info->flags = InvalidOpcode;
+ break;
+ }
+ break;
+ default:
+ /* CompilerWarning("Unkown opcode in GetInstructionInfo\n%s",RSPOpcodeName(RspOp->Hex,PC));
+ */ info->flags = InvalidOpcode;
+ break;
+ }
+}
+
+/************************************************************
+** DelaySlotAffectBranch
+**
+** Output:
+** 1: Delay slot does affect the branch
+** 0: Registers do not affect each other
+**
+** Input: PC
+*************************************************************/
+
+int32_t DelaySlotAffectBranch(uint32_t PC) {
+ RSPOPCODE Branch, Delay;
+ OPCODE_INFO infoBranch, infoDelay;
+
+ if (IsOpcodeNop(PC + 4) == 1) {
+ return 0;
+ }
+
+ RSP_LW_IMEM(PC, &Branch.Hex);
+ RSP_LW_IMEM(PC+4, &Delay.Hex);
+
+ memset(&infoDelay,0,sizeof(infoDelay));
+ memset(&infoBranch,0,sizeof(infoBranch));
+
+ GetInstructionInfo(PC, &Branch, &infoBranch);
+ GetInstructionInfo(PC+4, &Delay, &infoDelay);
+
+ if ((infoDelay.flags & Instruction_Mask) == VEC_Instruction) {
+ return 0;
+ }
+
+ if (infoBranch.SourceReg0 == infoDelay.DestReg) { return 1; }
+ if (infoBranch.SourceReg1 == infoDelay.DestReg) { return 1; }
+
+ return 0;
+}
+
+/************************************************************
+** CompareInstructions
+**
+** Output:
+** 1: The opcodes are fine, no dependency
+** 0: Watch it, these ops cant be touched
+**
+** Input:
+** Top, not the current operation, the one above
+** Bottom: the current opcode for re-ordering bubble style
+*************************************************************/
+
+int32_t CompareInstructions(uint32_t PC, RSPOPCODE * Top, RSPOPCODE * Bottom) {
+
+ OPCODE_INFO info0, info1;
+ uint32_t InstructionType;
+
+ GetInstructionInfo(PC - 4, Top, &info0);
+ GetInstructionInfo(PC, Bottom, &info1);
+
+ /* usually branches and such */
+ if ((info0.flags & InvalidOpcode) != 0) return 0;
+ if ((info1.flags & InvalidOpcode) != 0) return 0;
+
+ InstructionType = (info0.flags & Instruction_Mask) << 2;
+ InstructionType |= info1.flags & Instruction_Mask;
+ InstructionType &= 0x0F; /* Paranoia */
+
+ /* 4 bit range, 16 possible combinations */
+ switch (InstructionType) {
+ /*
+ ** Detect noop instruction, 7 cases, (see flags) */
+ case 0x01: case 0x02: case 0x03: /* First is a noop */
+ return 1;
+ case 0x00: /* Both ??? */
+ case 0x10: case 0x20: case 0x30: /* Second is a noop */
+ return 0;
+
+ case 0x06: /* GPR than Vector - 01,10 */
+ if ((info0.flags & MemOperation_Mask) != 0 && (info1.flags & MemOperation_Mask) != 0) {
+ /* TODO: We have a vector & GPR memory operation */
+ return 0;
+ } else if ((info1.flags & MemOperation_Mask) != 0) {
+ /* We have a vector memory operation */
+ return (info1.IndexReg == info0.DestReg) ? 0 : 1;
+ } else {
+ /* We could have memory or normal gpr instruction here
+ ** paired with some kind of vector operation
+ */
+ return 1;
+ }
+ return 0;
+
+ case 0x0A: /* Vector than Vector - 10,10 */
+
+ /*
+ ** Check for Vector Store than Vector multiply (VMULF)
+ **
+ ** This basically gives preferences to putting stores
+ ** as close to the finish of an operation as possible
+ */
+ if ((info0.flags & Store_Operation) != 0 && (info1.flags & Accum_Operation) != 0
+ && !(info1.flags & VEC_Accumulate)) { return 0; }
+
+ /*
+ ** Look for loads and than some kind of vector operation
+ ** that does no accumulating, there is no reason to reorder
+ */
+ if ((info0.flags & Load_Operation) != 0 && (info1.flags & Accum_Operation) != 0
+ && !(info1.flags & VEC_Accumulate)) { return 0; }
+
+ if ((info0.flags & MemOperation_Mask) != 0 && (info1.flags & MemOperation_Mask) != 0) {
+ /*
+ ** TODO: This is a bitch, its best to leave it alone
+ **/
+ return 0;
+ } else if ((info1.flags & MemOperation_Mask) != 0) {
+ /* Remember stored reg & loaded reg are the same */
+ if (info0.DestReg == info1.DestReg) { return 0; }
+
+ if (info1.flags & Load_Operation) {
+ if (info0.SourceReg0 == info1.DestReg) { return 0; }
+ if (info0.SourceReg1 == info1.DestReg) { return 0; }
+ } else if (info1.flags & Store_Operation) {
+ /* It can store source regs */
+ return 1;
+ }
+
+ return 1;
+ } else if ((info0.flags & MemOperation_Mask) != 0) {
+ /* Remember stored reg & loaded reg are the same */
+ if (info0.DestReg == info1.DestReg) { return 0; }
+
+ if (info0.flags & Load_Operation) {
+ if (info1.SourceReg0 == info0.DestReg) { return 0; }
+ if (info1.SourceReg1 == info0.DestReg) { return 0; }
+ } else if (info0.flags & Store_Operation) {
+ /* It can store source regs */
+ return 1;
+ }
+
+ return 1;
+ } else if ((info0.flags & VEC_Accumulate) != 0) {
+ /*
+ ** Example:
+ ** VMACF
+ ** VMUDH or VMADH or VADD
+ */
+
+ return 0;
+ } else if ((info1.flags & VEC_Accumulate) != 0) {
+ /*
+ ** Example:
+ ** VMULF
+ ** VMADH
+ */
+
+ return 0;
+ } else {
+ /*
+ ** Example:
+ ** VMULF or VADDC
+ ** VADD or VMUDH
+ */
+
+ return 0;
+ }
+ break;
+
+ case 0x09: /* Vector than GPR - 10,01 */
+ /**********
+ ** this is where the bias comes into play, otherwise
+ ** we can sit here all day swapping these 2 types
+ ***********/
+ return 0;
+
+ case 0x05: /* GPR than GPR - 01,01 */
+ case 0x07: /* GPR than Cop2 - 01, 11 */
+ case 0x0D: /* Cop2 than GPR - 11, 01 */
+ case 0x0F: /* Cop2 than Cop2 - 11, 11 */
+ return 0;
+
+ case 0x0B: /* Vector than Cop2 - 10, 11 */
+ if (info1.flags & Load_Operation) {
+ /* Move To Cop2 (dest) from GPR (source) */
+ if (info1.DestReg == info0.DestReg) { return 0; }
+ if (info1.DestReg == info0.SourceReg0) { return 0; }
+ if (info1.DestReg == info0.SourceReg1) { return 0; }
+ } else if (info1.flags & Store_Operation) {
+ /* Move From Cop2 (source) to GPR (dest) */
+ if (info1.SourceReg0 == info0.DestReg) { return 0; }
+ if (info1.SourceReg0 == info0.SourceReg0) { return 0; }
+ if (info1.SourceReg0 == info0.SourceReg1) { return 0; }
+ } else {
+ //CompilerWarning("ReOrder: Unhandled Vector than Cop2");
+ }
+ // we want vectors on top
+ return 0;
+
+ case 0x0E: /* Cop2 than Vector - 11, 10 */
+ if (info0.flags & Load_Operation) {
+ /* Move To Cop2 (dest) from GPR (source) */
+ if (info0.DestReg == info1.DestReg) { return 0; }
+ if (info0.DestReg == info1.SourceReg0) { return 0; }
+ if (info0.DestReg == info1.SourceReg1) { return 0; }
+ } else if (info0.flags & Store_Operation) {
+ /* Move From Cop2 (source) to GPR (dest) */
+ if (info0.SourceReg0 == info1.DestReg) { return 0; }
+ if (info0.SourceReg0 == info1.SourceReg0) { return 0; }
+ if (info0.SourceReg0 == info1.SourceReg1) { return 0; }
+ } else {
+ //CompilerWarning("ReOrder: Unhandled Cop2 than Vector");
+ }
+ // we want this at the top
+ return 1;
+
+ default:
+ CompilerWarning("ReOrder: Unhandled instruction type: %i", InstructionType);
+ }
+
+ return 0;
+}
diff --git a/src/usf/rsp_recompiler_cpu.c b/src/usf/rsp_recompiler_cpu.c new file mode 100644 index 0000000..f26f075 --- /dev/null +++ b/src/usf/rsp_recompiler_cpu.c @@ -0,0 +1,954 @@ +/*
+ * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator).
+ *
+ * (c) Copyright 2001 jabo (jabo@emulation64.com) and
+ * zilmar (zilmar@emulation64.com)
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <float.h>
+#include "rsp.h"
+#include "rsp_recompiler_cpu.h"
+#include "rsp_recompiler_ops.h"
+#include "rsp_x86.h"
+#include "recompiler_cpu.h"
+#include "memory.h"
+#include "main.h"
+#include "usf.h"
+#include "types.h"
+
+/* #define REORDER_BLOCK_VERBOSE */
+#define LINK_BRANCHES_VERBOSE /* no choice really */
+#define X86_RECOMP_VERBOSE
+#define BUILD_BRANCHLABELS_VERBOSE
+
+uint32_t RSPCompilePC, RSPBlockID = 0;
+uint32_t dwBuffer = MainBuffer;
+
+RSP_BLOCK RSPCurrentBlock;
+RSP_CODE RspCode;
+
+uint8_t * pLastSecondary = NULL, * pLastPrimary = NULL;
+
+void BuildRecompilerCPU ( void ) {
+ RSP_Opcode[ 0] = RSPCompile_SPECIAL;
+ RSP_Opcode[ 1] = RSPCompile_REGIMM;
+ RSP_Opcode[ 2] = RSPCompile_J;
+ RSP_Opcode[ 3] = RSPCompile_JAL;
+ RSP_Opcode[ 4] = RSPCompile_BEQ;
+ RSP_Opcode[ 5] = RSPCompile_BNE;
+ RSP_Opcode[ 6] = RSPCompile_BLEZ;
+ RSP_Opcode[ 7] = RSPCompile_BGTZ;
+ RSP_Opcode[ 8] = RSPCompile_ADDI;
+ RSP_Opcode[ 9] = RSPCompile_ADDIU;
+ RSP_Opcode[10] = RSPCompile_SLTI;
+ RSP_Opcode[11] = RSPCompile_SLTIU;
+ RSP_Opcode[12] = RSPCompile_ANDI;
+ RSP_Opcode[13] = RSPCompile_ORI;
+ RSP_Opcode[14] = RSPCompile_XORI;
+ RSP_Opcode[15] = RSPCompile_LUI;
+ RSP_Opcode[16] = RSPCompile_COP0;
+ RSP_Opcode[17] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[18] = RSPCompile_COP2;
+ RSP_Opcode[19] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[20] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[21] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[22] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[23] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[24] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[25] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[26] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[27] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[28] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[29] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[30] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[31] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[32] = RSPCompile_LB;
+ RSP_Opcode[33] = RSPCompile_LH;
+ RSP_Opcode[34] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[35] = RSPCompile_LW;
+ RSP_Opcode[36] = RSPCompile_LBU;
+ RSP_Opcode[37] = RSPCompile_LHU;
+ RSP_Opcode[38] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[39] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[40] = RSPCompile_SB;
+ RSP_Opcode[41] = RSPCompile_SH;
+ RSP_Opcode[42] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[43] = RSPCompile_SW;
+ RSP_Opcode[44] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[45] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[46] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[47] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[48] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[49] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[50] = RSPCompile_LC2;
+ RSP_Opcode[51] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[52] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[53] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[54] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[55] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[56] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[57] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[58] = RSPCompile_SC2;
+ RSP_Opcode[59] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[60] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[61] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[62] = RSPCompile_UnknownOpcode;
+ RSP_Opcode[63] = RSPCompile_UnknownOpcode;
+
+ RSP_Special[ 0] = RSPCompile_Special_SLL;
+ RSP_Special[ 1] = RSPCompile_UnknownOpcode;
+ RSP_Special[ 2] = RSPCompile_Special_SRL;
+ RSP_Special[ 3] = RSPCompile_Special_SRA;
+ RSP_Special[ 4] = RSPCompile_Special_SLLV;
+ RSP_Special[ 5] = RSPCompile_UnknownOpcode;
+ RSP_Special[ 6] = RSPCompile_Special_SRLV;
+ RSP_Special[ 7] = RSPCompile_Special_SRAV;
+ RSP_Special[ 8] = RSPCompile_Special_JR;
+ RSP_Special[ 9] = RSPCompile_Special_JALR;
+ RSP_Special[10] = RSPCompile_UnknownOpcode;
+ RSP_Special[11] = RSPCompile_UnknownOpcode;
+ RSP_Special[12] = RSPCompile_UnknownOpcode;
+ RSP_Special[13] = RSPCompile_Special_BREAK;
+ RSP_Special[14] = RSPCompile_UnknownOpcode;
+ RSP_Special[15] = RSPCompile_UnknownOpcode;
+ RSP_Special[16] = RSPCompile_UnknownOpcode;
+ RSP_Special[17] = RSPCompile_UnknownOpcode;
+ RSP_Special[18] = RSPCompile_UnknownOpcode;
+ RSP_Special[19] = RSPCompile_UnknownOpcode;
+ RSP_Special[20] = RSPCompile_UnknownOpcode;
+ RSP_Special[21] = RSPCompile_UnknownOpcode;
+ RSP_Special[22] = RSPCompile_UnknownOpcode;
+ RSP_Special[23] = RSPCompile_UnknownOpcode;
+ RSP_Special[24] = RSPCompile_UnknownOpcode;
+ RSP_Special[25] = RSPCompile_UnknownOpcode;
+ RSP_Special[26] = RSPCompile_UnknownOpcode;
+ RSP_Special[27] = RSPCompile_UnknownOpcode;
+ RSP_Special[28] = RSPCompile_UnknownOpcode;
+ RSP_Special[29] = RSPCompile_UnknownOpcode;
+ RSP_Special[30] = RSPCompile_UnknownOpcode;
+ RSP_Special[31] = RSPCompile_UnknownOpcode;
+ RSP_Special[32] = RSPCompile_Special_ADD;
+ RSP_Special[33] = RSPCompile_Special_ADDU;
+ RSP_Special[34] = RSPCompile_Special_SUB;
+ RSP_Special[35] = RSPCompile_Special_SUBU;
+ RSP_Special[36] = RSPCompile_Special_AND;
+ RSP_Special[37] = RSPCompile_Special_OR;
+ RSP_Special[38] = RSPCompile_Special_XOR;
+ RSP_Special[39] = RSPCompile_Special_NOR;
+ RSP_Special[40] = RSPCompile_UnknownOpcode;
+ RSP_Special[41] = RSPCompile_UnknownOpcode;
+ RSP_Special[42] = RSPCompile_Special_SLT;
+ RSP_Special[43] = RSPCompile_Special_SLTU;
+ RSP_Special[44] = RSPCompile_UnknownOpcode;
+ RSP_Special[45] = RSPCompile_UnknownOpcode;
+ RSP_Special[46] = RSPCompile_UnknownOpcode;
+ RSP_Special[47] = RSPCompile_UnknownOpcode;
+ RSP_Special[48] = RSPCompile_UnknownOpcode;
+ RSP_Special[49] = RSPCompile_UnknownOpcode;
+ RSP_Special[50] = RSPCompile_UnknownOpcode;
+ RSP_Special[51] = RSPCompile_UnknownOpcode;
+ RSP_Special[52] = RSPCompile_UnknownOpcode;
+ RSP_Special[53] = RSPCompile_UnknownOpcode;
+ RSP_Special[54] = RSPCompile_UnknownOpcode;
+ RSP_Special[55] = RSPCompile_UnknownOpcode;
+ RSP_Special[56] = RSPCompile_UnknownOpcode;
+ RSP_Special[57] = RSPCompile_UnknownOpcode;
+ RSP_Special[58] = RSPCompile_UnknownOpcode;
+ RSP_Special[59] = RSPCompile_UnknownOpcode;
+ RSP_Special[60] = RSPCompile_UnknownOpcode;
+ RSP_Special[61] = RSPCompile_UnknownOpcode;
+ RSP_Special[62] = RSPCompile_UnknownOpcode;
+ RSP_Special[63] = RSPCompile_UnknownOpcode;
+
+ RSP_RegImm[ 0] = RSPCompile_RegImm_BLTZ;
+ RSP_RegImm[ 1] = RSPCompile_RegImm_BGEZ;
+ RSP_RegImm[ 2] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[ 3] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[ 4] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[ 5] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[ 6] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[ 7] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[ 8] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[ 9] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[10] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[11] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[12] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[13] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[14] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[15] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[16] = RSPCompile_RegImm_BLTZAL;
+ RSP_RegImm[17] = RSPCompile_RegImm_BGEZAL;
+ RSP_RegImm[18] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[19] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[20] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[21] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[22] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[23] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[24] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[25] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[26] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[27] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[28] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[29] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[30] = RSPCompile_UnknownOpcode;
+ RSP_RegImm[31] = RSPCompile_UnknownOpcode;
+
+ RSP_Cop0[ 0] = RSPCompile_Cop0_MF;
+ RSP_Cop0[ 1] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[ 2] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[ 3] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[ 4] = RSPCompile_Cop0_MT;
+ RSP_Cop0[ 5] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[ 6] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[ 7] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[ 8] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[ 9] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[10] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[11] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[12] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[13] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[14] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[15] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[16] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[17] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[18] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[19] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[20] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[21] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[22] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[23] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[24] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[25] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[26] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[27] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[28] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[29] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[30] = RSPCompile_UnknownOpcode;
+ RSP_Cop0[31] = RSPCompile_UnknownOpcode;
+
+ RSP_Cop2[ 0] = RSPCompile_Cop2_MF;
+ RSP_Cop2[ 1] = RSPCompile_UnknownOpcode;
+ RSP_Cop2[ 2] = RSPCompile_Cop2_CF;
+ RSP_Cop2[ 3] = RSPCompile_UnknownOpcode;
+ RSP_Cop2[ 4] = RSPCompile_Cop2_MT;
+ RSP_Cop2[ 5] = RSPCompile_UnknownOpcode;
+ RSP_Cop2[ 6] = RSPCompile_Cop2_CT;
+ RSP_Cop2[ 7] = RSPCompile_UnknownOpcode;
+ RSP_Cop2[ 8] = RSPCompile_UnknownOpcode;
+ RSP_Cop2[ 9] = RSPCompile_UnknownOpcode;
+ RSP_Cop2[10] = RSPCompile_UnknownOpcode;
+ RSP_Cop2[11] = RSPCompile_UnknownOpcode;
+ RSP_Cop2[12] = RSPCompile_UnknownOpcode;
+ RSP_Cop2[13] = RSPCompile_UnknownOpcode;
+ RSP_Cop2[14] = RSPCompile_UnknownOpcode;
+ RSP_Cop2[15] = RSPCompile_UnknownOpcode;
+ RSP_Cop2[16] = RSPCompile_COP2_VECTOR;
+ RSP_Cop2[17] = RSPCompile_COP2_VECTOR;
+ RSP_Cop2[18] = RSPCompile_COP2_VECTOR;
+ RSP_Cop2[19] = RSPCompile_COP2_VECTOR;
+ RSP_Cop2[20] = RSPCompile_COP2_VECTOR;
+ RSP_Cop2[21] = RSPCompile_COP2_VECTOR;
+ RSP_Cop2[22] = RSPCompile_COP2_VECTOR;
+ RSP_Cop2[23] = RSPCompile_COP2_VECTOR;
+ RSP_Cop2[24] = RSPCompile_COP2_VECTOR;
+ RSP_Cop2[25] = RSPCompile_COP2_VECTOR;
+ RSP_Cop2[26] = RSPCompile_COP2_VECTOR;
+ RSP_Cop2[27] = RSPCompile_COP2_VECTOR;
+ RSP_Cop2[28] = RSPCompile_COP2_VECTOR;
+ RSP_Cop2[29] = RSPCompile_COP2_VECTOR;
+ RSP_Cop2[30] = RSPCompile_COP2_VECTOR;
+ RSP_Cop2[31] = RSPCompile_COP2_VECTOR;
+
+ RSP_Vector[ 0] = RSPCompile_Vector_VMULF;
+ RSP_Vector[ 1] = RSPCompile_Vector_VMULU;
+ RSP_Vector[ 2] = RSPCompile_UnknownOpcode;
+ RSP_Vector[ 3] = RSPCompile_UnknownOpcode;
+ RSP_Vector[ 4] = RSPCompile_Vector_VMUDL;
+ RSP_Vector[ 5] = RSPCompile_Vector_VMUDM;
+ RSP_Vector[ 6] = RSPCompile_Vector_VMUDN;
+ RSP_Vector[ 7] = RSPCompile_Vector_VMUDH;
+ RSP_Vector[ 8] = RSPCompile_Vector_VMACF;
+ RSP_Vector[ 9] = RSPCompile_Vector_VMACU;
+ RSP_Vector[10] = RSPCompile_UnknownOpcode;
+ RSP_Vector[11] = RSPCompile_Vector_VMACQ;
+ RSP_Vector[12] = RSPCompile_Vector_VMADL;
+ RSP_Vector[13] = RSPCompile_Vector_VMADM;
+ RSP_Vector[14] = RSPCompile_Vector_VMADN;
+ RSP_Vector[15] = RSPCompile_Vector_VMADH;
+ RSP_Vector[16] = RSPCompile_Vector_VADD;
+ RSP_Vector[17] = RSPCompile_Vector_VSUB;
+ RSP_Vector[18] = RSPCompile_UnknownOpcode;
+ RSP_Vector[19] = RSPCompile_Vector_VABS;
+ RSP_Vector[20] = RSPCompile_Vector_VADDC;
+ RSP_Vector[21] = RSPCompile_Vector_VSUBC;
+ RSP_Vector[22] = RSPCompile_UnknownOpcode;
+ RSP_Vector[23] = RSPCompile_UnknownOpcode;
+ RSP_Vector[24] = RSPCompile_UnknownOpcode;
+ RSP_Vector[25] = RSPCompile_UnknownOpcode;
+ RSP_Vector[26] = RSPCompile_UnknownOpcode;
+ RSP_Vector[27] = RSPCompile_UnknownOpcode;
+ RSP_Vector[28] = RSPCompile_UnknownOpcode;
+ RSP_Vector[29] = RSPCompile_Vector_VSAW;
+ RSP_Vector[30] = RSPCompile_UnknownOpcode;
+ RSP_Vector[31] = RSPCompile_UnknownOpcode;
+ RSP_Vector[32] = RSPCompile_Vector_VLT;
+ RSP_Vector[33] = RSPCompile_Vector_VEQ;
+ RSP_Vector[34] = RSPCompile_Vector_VNE;
+ RSP_Vector[35] = RSPCompile_Vector_VGE;
+ RSP_Vector[36] = RSPCompile_Vector_VCL;
+ RSP_Vector[37] = RSPCompile_Vector_VCH;
+ RSP_Vector[38] = RSPCompile_Vector_VCR;
+ RSP_Vector[39] = RSPCompile_Vector_VMRG;
+ RSP_Vector[40] = RSPCompile_Vector_VAND;
+ RSP_Vector[41] = RSPCompile_Vector_VNAND;
+ RSP_Vector[42] = RSPCompile_Vector_VOR;
+ RSP_Vector[43] = RSPCompile_Vector_VNOR;
+ RSP_Vector[44] = RSPCompile_Vector_VXOR;
+ RSP_Vector[45] = RSPCompile_Vector_VNXOR;
+ RSP_Vector[46] = RSPCompile_UnknownOpcode;
+ RSP_Vector[47] = RSPCompile_UnknownOpcode;
+ RSP_Vector[48] = RSPCompile_Vector_VRCP;
+ RSP_Vector[49] = RSPCompile_Vector_VRCPL;
+ RSP_Vector[50] = RSPCompile_Vector_VRCPH;
+ RSP_Vector[51] = RSPCompile_Vector_VMOV;
+ RSP_Vector[52] = RSPCompile_Vector_VRSQ;
+ RSP_Vector[53] = RSPCompile_Vector_VRSQL;
+ RSP_Vector[54] = RSPCompile_Vector_VRSQH;
+ RSP_Vector[55] = RSPCompile_Vector_VNOOP;
+ RSP_Vector[56] = RSPCompile_UnknownOpcode;
+ RSP_Vector[57] = RSPCompile_UnknownOpcode;
+ RSP_Vector[58] = RSPCompile_UnknownOpcode;
+ RSP_Vector[59] = RSPCompile_UnknownOpcode;
+ RSP_Vector[60] = RSPCompile_UnknownOpcode;
+ RSP_Vector[61] = RSPCompile_UnknownOpcode;
+ RSP_Vector[62] = RSPCompile_UnknownOpcode;
+ RSP_Vector[63] = RSPCompile_UnknownOpcode;
+
+ RSP_Lc2[ 0] = RSPCompile_Opcode_LBV;
+ RSP_Lc2[ 1] = RSPCompile_Opcode_LSV;
+ RSP_Lc2[ 2] = RSPCompile_Opcode_LLV;
+ RSP_Lc2[ 3] = RSPCompile_Opcode_LDV;
+ RSP_Lc2[ 4] = RSPCompile_Opcode_LQV;
+ RSP_Lc2[ 5] = RSPCompile_Opcode_LRV;
+ RSP_Lc2[ 6] = RSPCompile_Opcode_LPV;
+ RSP_Lc2[ 7] = RSPCompile_Opcode_LUV;
+ RSP_Lc2[ 8] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[ 9] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[10] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[11] = RSPCompile_Opcode_LTV;
+ RSP_Lc2[12] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[13] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[14] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[15] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[16] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[17] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[18] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[19] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[20] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[21] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[22] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[23] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[24] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[25] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[26] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[27] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[28] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[29] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[30] = RSPCompile_UnknownOpcode;
+ RSP_Lc2[31] = RSPCompile_UnknownOpcode;
+
+ RSP_Sc2[ 0] = RSPCompile_Opcode_SBV;
+ RSP_Sc2[ 1] = RSPCompile_Opcode_SSV;
+ RSP_Sc2[ 2] = RSPCompile_Opcode_SLV;
+ RSP_Sc2[ 3] = RSPCompile_Opcode_SDV;
+ RSP_Sc2[ 4] = RSPCompile_Opcode_SQV;
+ RSP_Sc2[ 5] = RSPCompile_Opcode_SRV;
+ RSP_Sc2[ 6] = RSPCompile_Opcode_SPV;
+ RSP_Sc2[ 7] = RSPCompile_Opcode_SUV;
+ RSP_Sc2[ 8] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[ 9] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[10] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[11] = RSPCompile_Opcode_STV;
+ RSP_Sc2[12] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[13] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[14] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[15] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[16] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[17] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[18] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[19] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[20] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[21] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[22] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[23] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[24] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[25] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[26] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[27] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[28] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[29] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[30] = RSPCompile_UnknownOpcode;
+ RSP_Sc2[31] = RSPCompile_UnknownOpcode;
+
+ RSPBlockID = 0;
+}
+
+/******************************************************
+** ReOrderSubBlock
+**
+** Desc:
+** this can be done, but will be interesting to put
+** between branches labels, and actual branches, whichever
+** occurs first in code
+**
+********************************************************/
+
+void ReOrderInstructions(uint32_t StartPC, uint32_t EndPC) {
+ uint32_t InstructionCount = EndPC - StartPC;
+ uint32_t Count, ReorderedOps, CurrentPC;
+ RSPOPCODE PreviousOp, CurrentOp, RspOp;
+
+ PreviousOp.Hex = *(uint32_t*)(IMEM + StartPC);
+
+ if (1 == IsOpcodeBranch(StartPC, PreviousOp)) {
+ /* the sub block ends here anyway */
+ return;
+ }
+
+ if (IsOpcodeNop(StartPC) && IsOpcodeNop(StartPC + 4) && IsOpcodeNop(StartPC + 8)) {
+ /* Dont even bother */
+ return;
+ }
+
+ CPU_Message("***** Doing reorder (%X to %X) *****", StartPC, EndPC);
+
+ if (InstructionCount < 0x0010) { return; }
+ if (InstructionCount > 0x0A00) { return; }
+
+ CPU_Message(" Before:");
+ for (Count = StartPC; Count < EndPC; Count += 4) {
+ RSP_LW_IMEM(Count, &RspOp.Hex);
+ //CPU_Message(" %X %s",Count,RSPOpcodeName(RspOp.Hex,Count));
+ }
+
+ for (Count = 0; Count < InstructionCount; Count += 4) {
+ CurrentPC = StartPC;
+ PreviousOp.Hex = *(uint32_t*)(IMEM + CurrentPC);
+ ReorderedOps = 0;
+
+ for (;;) {
+ CurrentPC += 4;
+ if (CurrentPC >= EndPC) { break; }
+ CurrentOp.Hex = *(uint32_t*)(IMEM + CurrentPC);
+
+ if (1 == CompareInstructions(CurrentPC, &PreviousOp, &CurrentOp)) {
+ /* Move current opcode up */
+ *(uint32_t*)(IMEM + CurrentPC - 4) = CurrentOp.Hex;
+ *(uint32_t*)(IMEM + CurrentPC) = PreviousOp.Hex;
+
+ ReorderedOps++;
+ #ifdef REORDER_BLOCK_VERBOSE
+ CPU_Message("Swapped %X and %X", CurrentPC - 4, CurrentPC);
+ #endif
+ }
+ PreviousOp.Hex = *(uint32_t*)(IMEM + CurrentPC);
+
+ if (IsOpcodeNop(CurrentPC) && IsOpcodeNop(CurrentPC + 4) && IsOpcodeNop(CurrentPC + 8)) {
+ CurrentPC = EndPC;
+ }
+ }
+
+ if (ReorderedOps == 0) {
+ Count = InstructionCount;
+ }
+ }
+
+ CPU_Message(" After:");
+ for (Count = StartPC; Count < EndPC; Count += 4) {
+ RSP_LW_IMEM(Count, &RspOp.Hex);
+ //CPU_Message(" %X %s",Count,RSPOpcodeName(RspOp.Hex,Count));
+ }
+ CPU_Message("");
+}
+
+void ReOrderSubBlock(RSP_BLOCK * Block) {
+ uint32_t end = 0x0ffc;
+ uint32_t count;
+
+ //return; //fixthis
+ if (!Compiler.bReOrdering) {
+ return;
+ }
+ if (Block->CurrPC > 0xFF0) {
+ return;
+ }
+
+ /* find the label or jump closest to us */
+ if (RspCode.LabelCount) {
+ for (count = 0; count < RspCode.LabelCount; count++) {
+ if (RspCode.BranchLabels[count] < end &&
+ RspCode.BranchLabels[count] > Block->CurrPC) {
+ end = RspCode.BranchLabels[count];
+ }
+ }
+ }
+ if (RspCode.BranchCount) {
+ for (count = 0; count < RspCode.BranchCount; count++) {
+ if (RspCode.BranchLocations[count] < end &&
+ RspCode.BranchLocations[count] > Block->CurrPC) {
+ end = RspCode.BranchLocations[count];
+ }
+ }
+ }
+
+ /* it wont actually re-order the op at the end */
+ ReOrderInstructions(Block->CurrPC, end);
+}
+
+/******************************************************
+** DetectGPRConstants
+**
+** Desc:
+** this needs to be called on a sub-block basis, like
+** after every time we hit a branch and delay slot
+**
+********************************************************/
+
+void DetectGPRConstants(RSP_CODE * code) {
+ uint32_t Count, Constant = 0;
+
+ memset(&code->bIsRegConst, 0, sizeof(int32_t) * 0x20);
+ memset(&code->MipsRegConst, 0, sizeof(uint32_t) * 0x20);
+
+ if (!Compiler.bGPRConstants) {
+ return;
+ }
+ CPU_Message("***** Detecting constants *****");
+
+ /*** Setup R0 ***/
+ code->bIsRegConst[0] = 1;
+ code->MipsRegConst[0] = 0;
+
+ /* Do your global search for them */
+ for (Count = 1; Count < 32; Count++) {
+ if (IsRegisterConstant(Count, &Constant) == 1) {
+ //CPU_Message("Global: %s is a constant of: %08X", GPR_Name(Count), Constant);
+ code->bIsRegConst[Count] = 1;
+ code->MipsRegConst[Count] = Constant;
+ }
+ }
+ CPU_Message("");
+}
+
+/******************************************************
+** CompilerToggleBuffer and ClearX86Code
+**
+** Desc:
+** 1> toggles the compiler buffer, useful for poorly
+** taken branches like alignment
+**
+** 2> clears all the x86 code, jump tables etc
+**
+********************************************************/
+
+void CompilerToggleBuffer(void) {
+ if (dwBuffer == MainBuffer) {
+ dwBuffer = SecondaryBuffer;
+ pLastPrimary = RSPRecompPos;
+
+ if (pLastSecondary == NULL) {
+ pLastSecondary = RSPRecompCodeSecondary;
+ }
+
+ RSPRecompPos = pLastSecondary;
+ CPU_Message(" (Secondary Buffer Active 0x%08X)", pLastSecondary);
+ } else {
+ dwBuffer = MainBuffer;
+ pLastSecondary = RSPRecompPos;
+
+ if (pLastPrimary == NULL) {
+ pLastPrimary = RSPRecompCode;
+ }
+
+ RSPRecompPos = pLastPrimary;
+ CPU_Message(" (Primary Buffer Active 0x%08X)", pLastPrimary);
+ }
+}
+
+void ClearAllx86Code (void) {
+ extern uint32_t NoOfMaps, MapsCRC[32];
+ extern uint8_t *RSPJumpTables;
+
+ memset(&MapsCRC, 0, sizeof(uint32_t) * 0x20);
+ NoOfMaps = 0;
+ memset(RSPJumpTables,0,0x2000*32);
+
+ RSPRecompPos = RSPRecompCode;
+
+ pLastPrimary = NULL;
+ pLastSecondary = NULL;
+}
+
+/******************************************************
+** Link Branches
+**
+** Desc:
+** resolves all the collected branches, x86 style
+**
+********************************************************/
+
+void LinkBranches(RSP_BLOCK * Block) {
+ uint32_t Count, Target;
+ uint32_t * JumpWord;
+ uint8_t * X86Code;
+ RSP_BLOCK Save;
+
+ if (!RSPCurrentBlock.ResolveCount) {
+ return;
+ }
+ CPU_Message("***** Linking branches (%i) *****", RSPCurrentBlock.ResolveCount);
+
+ for (Count = 0; Count < RSPCurrentBlock.ResolveCount; Count++) {
+ Target = RSPCurrentBlock.BranchesToResolve[Count].TargetPC;
+ X86Code = *(RSPJumpTable + (Target >> 2));
+
+ if (!X86Code) {
+ *PrgCount = Target;
+ CPU_Message("");
+ CPU_Message("===== (Generate Code: %04X) =====", Target);
+ Save = *Block;
+
+ /* compile this block and link */
+ CompilerRSPBlock();
+ LinkBranches(Block);
+
+ *Block = Save;
+ CPU_Message("===== (End Generate Code: %04X) =====", Target);
+ CPU_Message("");
+ X86Code = *(RSPJumpTable + (Target >> 2));
+ }
+
+ JumpWord = RSPCurrentBlock.BranchesToResolve[Count].X86JumpLoc;
+ RSPx86_SetBranch32b(JumpWord, (uint32_t*)X86Code);
+
+ CPU_Message("Linked RSP branch from x86: %08X, to RSP: %X / x86: %08X",
+ JumpWord, Target, X86Code);
+ }
+ CPU_Message("***** Done Linking Branches *****");
+ CPU_Message("");
+}
+
+/******************************************************
+** BuildBranchLabels
+**
+** Desc:
+** Branch labels are used to start and stop re-ordering
+** sections as well as set the jump table to points
+** within a block that are safe
+**
+********************************************************/
+
+void BuildBranchLabels(void) {
+ RSPOPCODE RspOp;
+ uint32_t i, Dest;
+
+ #ifdef BUILD_BRANCHLABELS_VERBOSE
+ CPU_Message("***** Building branch labels *****");
+ #endif
+
+ for (i = 0; i < 0x1000; i += 4) {
+ RspOp.Hex = *(uint32_t*)(IMEM + i);
+
+ if (1 == IsOpcodeBranch(i, RspOp)) {
+ if (RspCode.LabelCount >= 175) {
+ CompilerWarning("Out of space for Branch Labels",1);
+ return;
+ }
+
+ RspCode.BranchLocations[RspCode.BranchCount++] = i;
+ if (RspOp.op == RSP_SPECIAL) {
+ /* register jump not predictable */
+ } else if (RspOp.op == RSP_J || RspOp.op == RSP_JAL) {
+ /* for JAL its a sub-block for returns */
+ Dest = (RspOp.target << 2) & 0xFFC;
+ RspCode.BranchLabels[RspCode.LabelCount] = Dest;
+ RspCode.LabelCount += 1;
+ #ifdef BUILD_BRANCHLABELS_VERBOSE
+ CPU_Message("[%02i] Added branch at %X to %X", RspCode.LabelCount, i, Dest);
+ #endif
+ } else {
+ Dest = (i + ((int16_t)RspOp.offset << 2) + 4) & 0xFFC;
+ RspCode.BranchLabels[RspCode.LabelCount] = Dest;
+ RspCode.LabelCount += 1;
+ #ifdef BUILD_BRANCHLABELS_VERBOSE
+ CPU_Message("[%02i] Added branch at %X to %X", RspCode.LabelCount, i, Dest);
+ #endif
+ }
+ }
+ }
+
+ #ifdef BUILD_BRANCHLABELS_VERBOSE
+ CPU_Message("***** End branch labels *****");
+ CPU_Message("");
+ #endif
+}
+
+int32_t IsJumpLabel(uint32_t PC) {
+ uint32_t Count;
+
+ if (!RspCode.LabelCount) {
+ return 0;
+ }
+
+ for (Count = 0; Count < RspCode.LabelCount; Count++) {
+ if (PC == RspCode.BranchLabels[Count]) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+
+void CompilerLinkBlocks(void) {
+ uint8_t * KnownCode = *(RSPJumpTable + (RSPCompilePC >> 2));
+
+ CPU_Message("***** Linking block to X86: %08X *****", KnownCode);
+ RSPNextInstruction = FINISH_BLOCK;
+
+ /* block linking scenario */
+ RSPJmpLabel32(0);
+ RSPx86_SetBranch32b(RSPRecompPos - 4, KnownCode);
+}
+
+
+void CompilerRSPBlock ( void ) {
+ uint32_t Count, Padding, X86BaseAddress = (uint32_t)RSPRecompPos;
+
+ RSPNextInstruction = NORMAL;
+ RSPCompilePC = *PrgCount;
+
+ memset(&RSPCurrentBlock, 0, sizeof(RSPCurrentBlock));
+ RSPCurrentBlock.StartPC = RSPCompilePC;
+ RSPCurrentBlock.CurrPC = RSPCompilePC;
+
+
+ /* Align the block to a boundary */
+ if (X86BaseAddress & 7) {
+ Padding = (8 - (X86BaseAddress & 7)) & 7;
+ for (Count = 0; Count < Padding; Count++) {
+ *(RSPRecompPos++) = 0x90;
+ }
+ }
+
+ if (Compiler.bReOrdering == 1) {
+ memcpy(&RSPCurrentBlock.IMEM[0], IMEM, 0x1000);
+ ReOrderSubBlock(&RSPCurrentBlock);
+ }
+
+ /* this is for the block about to be compiled */
+ *(RSPJumpTable + (RSPCompilePC >> 2)) = RSPRecompPos;
+
+
+#ifdef USEX64
+ RSPMoveConstQwordToX86reg(TLB_Map, x86_R15);
+#endif
+
+ do {
+ /*
+ ** Re-Ordering is setup to allow us to have loop labels
+ ** so here we see if this is one and put it in the jump table
+ **/
+
+ if (RSPNextInstruction == NORMAL && IsJumpLabel(RSPCompilePC)) {
+ /* jumps come around twice */
+ if (NULL == *(RSPJumpTable + (RSPCompilePC >> 2))) {
+ CPU_Message("***** Adding Jump Table Entry for PC: %04X at X86: %08X *****", RSPCompilePC, RSPRecompPos);
+ CPU_Message("");
+ *(RSPJumpTable + (RSPCompilePC >> 2)) = RSPRecompPos;
+
+ /* reorder from here to next label or branch */
+ RSPCurrentBlock.CurrPC = RSPCompilePC;
+ ReOrderSubBlock(&RSPCurrentBlock);
+ } else if (RSPNextInstruction != DELAY_SLOT_DONE) {
+ /*
+ * we could link the blocks here, but performance
+ * wise it might be better to just let it run
+ */
+ }
+ }
+
+ if (Compiler.bSections == 1) {
+ // if (1 == RSP_DoSections()) {
+ // continue;
+ // }
+ }
+
+ #ifdef X86_RECOMP_VERBOSE
+ if (0 == IsOpcodeNop(RSPCompilePC)) {
+ CPU_Message("X86 Address: %08X", RSPRecompPos);
+ }
+ #endif
+
+ RSP_LW_IMEM(RSPCompilePC, &RSPOpC.Hex);
+
+ if (RSPOpC.Hex == 0xFFFFFFFF) {
+ /* i think this pops up an unknown op dialog */
+ /* NextInstruction = FINISH_BLOCK; */
+ } else {
+ ((void (*)()) RSP_Opcode[ RSPOpC.op ])();
+ }
+
+ //printf("%08x\n", RSPNextInstruction);
+
+ switch (RSPNextInstruction) {
+ case NORMAL:
+ RSPCompilePC += 4;
+ break;
+ case DO_DELAY_SLOT:
+ RSPNextInstruction = DELAY_SLOT;
+ RSPCompilePC += 4;
+ break;
+ case DELAY_SLOT:
+ RSPNextInstruction = DELAY_SLOT_DONE;
+ RSPCompilePC -= 4;
+ break;
+ case FINISH_SUB_BLOCK:
+ RSPNextInstruction = NORMAL;
+ RSPCompilePC += 8;
+ if (RSPCompilePC >= 0x1000) {
+ RSPNextInstruction = FINISH_BLOCK;
+ } else if (NULL == *(RSPJumpTable + (RSPCompilePC >> 2))) {
+ /* this is for the new block being compiled now */
+ CPU_Message("**** Continuing static SubBlock (jump table entry added for PC: %04X at X86: %08X) *****", RSPCompilePC, RSPRecompPos);
+ *(RSPJumpTable + (RSPCompilePC >> 2)) = RSPRecompPos;
+
+ RSPCurrentBlock.CurrPC = RSPCompilePC;
+ /* reorder from after delay to next label or branch */
+ ReOrderSubBlock(&RSPCurrentBlock);
+ } else {
+ CompilerLinkBlocks();
+ }
+ break;
+
+ case FINISH_BLOCK: break;
+ default:
+ DisplayError("Rsp Main loop\n\nWTF NextInstruction = %d",RSPNextInstruction);
+ RSPCompilePC += 4;
+ break;
+ }
+ } while ( RSPNextInstruction != FINISH_BLOCK && RSPCompilePC < 0x1000);
+ CPU_Message("==== end of recompiled code ====");
+
+ if (Compiler.bReOrdering == 1) {
+ memcpy(IMEM, &RSPCurrentBlock.IMEM[0], 0x1000);
+ }
+}
+
+#include "types.h"
+
+
+void RunRecompilerCPU ( uint32_t Cycles ) {
+ uint8_t * Block = 0;
+
+ RSP_Running = 1;
+ RSPSetJumpTable();
+
+
+
+ while (RSP_Running) {
+
+ Block = *(RSPJumpTable + (*PrgCount >> 2));
+
+ if (Block == NULL) {
+ //__try {
+ memset(&RspCode, 0, sizeof(RspCode));
+ BuildBranchLabels();
+ DetectGPRConstants(&RspCode);
+ CompilerRSPBlock();
+ /*} __except(EXCEPTION_EXECUTE_HANDLER) {
+ DisplayError("Error RSPCompilePC = %08X", RSPCompilePC);
+ ClearAllx86Code();
+ continue;
+ }*/
+
+ Block = *(RSPJumpTable + (*PrgCount >> 2));
+
+ /*
+ ** we are done compiling, but we may have references
+ ** to fill in still either from this block, or jumps
+ ** that go out of it, let's rock
+ **/
+
+ LinkBranches(&RSPCurrentBlock);
+ }
+ {
+
+ void (*block)();
+ block=Block;
+#ifdef USEX64
+ __asm__ __volatile__("pushq %rax");
+ __asm__ __volatile__("pushq %rbx");
+ __asm__ __volatile__("pushq %rcx");
+ __asm__ __volatile__("pushq %rdx");
+ __asm__ __volatile__("pushq %rbp");
+ __asm__ __volatile__("pushq %r8");
+ __asm__ __volatile__("pushq %r9");
+ __asm__ __volatile__("pushq %r10");
+ __asm__ __volatile__("pushq %r11");
+ __asm__ __volatile__("pushq %r12");
+ __asm__ __volatile__("pushq %r13");
+ __asm__ __volatile__("pushq %r14");
+ __asm__ __volatile__("pushq %r15");
+
+ block();
+
+ __asm__ __volatile__("popq %r15");
+ __asm__ __volatile__("popq %r14");
+ __asm__ __volatile__("popq %r13");
+ __asm__ __volatile__("popq %r12");
+ __asm__ __volatile__("popq %r11");
+ __asm__ __volatile__("popq %r10");
+ __asm__ __volatile__("popq %r9");
+ __asm__ __volatile__("popq %r8");
+ __asm__ __volatile__("popq %rbp");
+ __asm__ __volatile__("popq %rdx");
+ __asm__ __volatile__("popq %rcx");
+ __asm__ __volatile__("popq %rbx");
+ __asm__ __volatile__("popq %rax");
+
+#else
+ __asm__ __volatile__("pusha");
+ block();
+ __asm__ __volatile__("popa");
+#endif
+ }
+
+ }
+
+// if (IsMmxEnabled == 1) {
+// _Emms();
+// }
+ return;
+}
diff --git a/src/usf/rsp_recompiler_cpu.h b/src/usf/rsp_recompiler_cpu.h new file mode 100644 index 0000000..e54f900 --- /dev/null +++ b/src/usf/rsp_recompiler_cpu.h @@ -0,0 +1,116 @@ +/*
+ * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator).
+ *
+ * (c) Copyright 2001 jabo (jabo@emulation64.com) and
+ * zilmar (zilmar@emulation64.com)
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+
+#include "rsp.h"
+
+extern uint32_t RSPCompilePC, RSPNextInstruction;
+
+//#define CompilerWarning if (ShowErrors) DisplayError
+//#define CompilerWarning(blah,blah2)
+#define CompilerWarning(...)
+
+#define High16BitAccum 1
+#define Middle16BitAccum 2
+#define Low16BitAccum 4
+#define EntireAccum (Low16BitAccum|Middle16BitAccum|High16BitAccum)
+
+int32_t WriteToAccum (int32_t Location, int32_t PC);
+int32_t WriteToVectorDest (uint32_t DestReg, int32_t PC);
+int32_t UseRspFlags (int32_t PC);
+
+int32_t DelaySlotAffectBranch(uint32_t PC);
+int32_t CompareInstructions(uint32_t PC, RSPOPCODE * Top, RSPOPCODE * Bottom);
+int32_t IsOpcodeBranch(uint32_t PC, RSPOPCODE RspOp);
+int32_t IsOpcodeNop(uint32_t PC);
+
+int32_t IsNextInstructionMmx(uint32_t PC);
+int32_t IsRegisterConstant (uint32_t Reg, uint32_t * Constant);
+
+void RSP_Element2Mmx(int32_t MmxReg);
+void RSP_MultiElement2Mmx(int32_t MmxReg1, int32_t MmxReg2);
+
+#define MainBuffer 0
+#define SecondaryBuffer 1
+
+void RunRecompilerCPU ( uint32_t Cycles );
+void BuildRecompilerCPU ( void );
+
+void CompilerRSPBlock ( void );
+void CompilerToggleBuffer (void);
+int32_t RSP_DoSections(void);
+
+void ClearAllx86Code (void);
+
+typedef struct {
+ uint32_t StartPC, CurrPC; /* block start */
+
+ struct {
+ uint32_t TargetPC; /* Target for this unknown branch */
+ uint32_t * X86JumpLoc; /* Our x86 dword to fill */
+ } BranchesToResolve[200]; /* Branches inside or outside block */
+
+ uint32_t ResolveCount; /* Branches with NULL jump table */
+ uint8_t IMEM[0x1000]; /* Saved off for re-order */
+} RSP_BLOCK;
+
+extern RSP_BLOCK RSPCurrentBlock;
+
+typedef struct {
+ int32_t bIsRegConst[32]; /* BOOLean toggle for constant */
+ uint32_t MipsRegConst[32]; /* Value of register 32-bit */
+ uint32_t BranchLabels[200];
+ uint32_t LabelCount;
+ uint32_t BranchLocations[200];
+ uint32_t BranchCount;
+} RSP_CODE;
+
+extern RSP_CODE RspCode;
+
+#define IsRegConst(i) (RspCode.bIsRegConst[i])
+#define MipsRegConst(i) (RspCode.MipsRegConst[i])
+
+typedef struct {
+ int32_t mmx, mmx2, sse; /* CPU specs and compiling */
+ int32_t bFlags; /* RSP Flag Analysis */
+ int32_t bReOrdering; /* Instruction reordering */
+ int32_t bSections; /* Microcode sections */
+ int32_t bDest; /* Vector destionation toggle */
+ int32_t bAccum; /* Accumulator toggle */
+ int32_t bGPRConstants; /* Analyze GPR constants */
+ int32_t bAlignVector; /* Align known vector loads */
+ int32_t bAlignGPR; /* Align known gpr loads */
+} RSP_COMPILER;
+
+extern RSP_COMPILER Compiler;
+
+
+extern uint8_t * pLastSecondary, * pLastPrimary;
+extern uint32_t RSPBlockID;
+extern uint32_t dwBuffer;
+
+#define IsMmxEnabled (Compiler.mmx)
+#define IsMmx2Enabled (Compiler.mmx2)
+#define IsSseEnabled (Compiler.sse)
diff --git a/src/usf/rsp_recompiler_ops.c b/src/usf/rsp_recompiler_ops.c new file mode 100644 index 0000000..dfdf628 --- /dev/null +++ b/src/usf/rsp_recompiler_ops.c @@ -0,0 +1,4619 @@ +/*
+ * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator).
+ *
+ * (c) Copyright 2001 jabo (jabo@emulation64.com) and
+ * zilmar (zilmar@emulation64.com)
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include "types.h"
+#include "rsp.h"
+#include "rsp_recompiler_cpu.h"
+#include "rsp_x86.h"
+#include "recompiler_cpu.h"
+#include "memory.h"
+#include "registers.h"
+#include "usf.h"
+#include "types.h"
+#include "main.h"
+
+MIPSUWORD Recp, RecpResult, SQroot, SQrootResult;
+uint32_t ESP_RegSave = 0, EBP_RegSave = 0;
+uint32_t RSPBranchCompare = 0;
+extern int runcount;
+/* align option affects: sw, lh, sh */
+/* align option affects: lrv, ssv, lsv */
+
+#if 1
+#define RSPCompile_Immediates /* ADDI, ADDIU, ANDI, ORI, XORI, LUI */
+
+#define RSPCompile_GPRLoads /* LB, LH, LW, LBU, LHU */
+#define RSPCompile_GPRStores /* SB, SH, SW */
+#define RSPCompile_Special /* SLL, SRL, SRA, SRLV */
+ /* XOR, OR, AND, SUB, SUBU, ADDU, ADD, SLT */
+
+#define RSPCompile_Cop0
+#define RSPCompile_Cop2
+
+#define RSP_VectorMuls
+#define RSP_VectorLoads
+#define RSP_VectorMisc
+
+#ifdef RSP_VectorMuls
+# define RSPCompileVmulf /* Verified 12/17/2000 - Jabo */
+# define RSPCompileVmacf /* Rewritten & Verified 12/15/2000 - Jabo */
+# define RSPCompileVmudm /* Verified 12/17/2000 - Jabo */
+# define RSPCompileVmudh /* Verified 12/17/2000 - Jabo */
+# define RSPCompileVmudn /* Verified 12/17/2000 - Jabo */
+# define RSPCompileVmudl /* Verified 12/17/2000 - Jabo */
+# define RSPCompileVmadl
+# define RSPCompileVmadm /* Verified 12/17/2000 - Jabo */
+# define RSPCompileVmadh /* Verified 12/15/2000 - Jabo */
+# define RSPCompileVmadn /* Verified 12/17/2000 - Jabo */
+#endif
+#ifdef RSP_VectorMisc
+# define RSPCompileVrsqh
+# define RSPCompileVrcph
+# define RSPCompileVsaw /* Verified 12/17/2000 - Jabo */
+# define RSPCompileVabs /* Verified 12/15/2000 - Jabo */
+# define RSPCompileVmov /* Verified 12/17/2000 - Jabo */
+# define RSPCompileVxor /* Verified 12/17/2000 - Jabo */
+# define RSPCompileVor /* Verified 12/17/2000 - Jabo */
+# define RSPCompileVand /* Verified 12/17/2000 - Jabo */
+# define RSPCompileVsub /* Verified 12/17/2000 - Jabo (watch flags) */
+# define RSPCompileVadd /* Verified 12/17/2000 - Jabo (watch flags) */
+# define RSPCompileVaddc
+# define RSPCompileVsubc
+# define RSPCompileVmrg
+#endif
+#ifdef RSP_VectorLoads
+# define RSPCompileSqv /* Verified 12/17/2000 - Jabo */
+# define RSPCompileSdv /* Verified 12/17/2000 - Jabo */
+# define RSPCompileSsv /* Verified 12/17/2000 - Jabo */
+# define RSPCompileLrv /* Rewritten & Verified 12/17/2000 - Jabo */
+# define RSPCompileLqv /* Verified 12/17/2000 - Jabo */
+# define RSPCompileLdv /* Verified 12/17/2000 - Jabo */
+# define RSPCompileLsv /* Verified 12/17/2000 - Jabo */
+# define RSPCompileLlv /* Verified 12/17/2000 - Jabo */
+# define RSPCompileSlv
+#endif
+#endif
+
+void RSPBranch_AddRef(uint32_t Target, uint32_t * X86Loc) {
+ if (RSPCurrentBlock.ResolveCount >= 150) {
+ //CompilerWarning(1);
+ } else {
+ uint8_t * KnownCode = *(RSPJumpTable + (Target >> 2));
+
+ if (KnownCode == NULL) {
+ uint32_t i = RSPCurrentBlock.ResolveCount;
+ RSPCurrentBlock.BranchesToResolve[i].TargetPC = Target;
+ RSPCurrentBlock.BranchesToResolve[i].X86JumpLoc = X86Loc;
+ RSPCurrentBlock.ResolveCount += 1;
+ } else {
+ CPU_Message( KnownCode);
+ RSPx86_SetBranch32b((uint32_t*)X86Loc, (uint32_t*)KnownCode);
+ }
+ }
+}
+
+int32_t test33 = 0;
+void RSPCheat_r4300iOpcode ( void * FunctAddress) {
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ RSPMoveConstToVariable(RSPCompilePC, &test33);
+ RSPPushad();
+ RSPMoveConstToVariable(RSPOpC.Hex, &RSPOpC.Hex );
+ RSPCall_Direct(FunctAddress);
+ RSPPopad();
+}
+
+void RSPCheat_r4300iOpcodeNoMessage( void * FunctAddress) {
+ RSPMoveConstToVariable(RSPCompilePC, &test33);
+ RSPPushad();
+ RSPMoveConstToVariable(RSPOpC.Hex, &RSPOpC.Hex );
+ RSPCall_Direct(FunctAddress);
+ RSPPopad();
+}
+
+void RSPx86_SetBranch8b(void * JumpByte, void * Destination) {
+ /* calculate 32-bit relative offset */
+ int32_t n = (uint8_t*)Destination - ((uint8_t*)JumpByte + 1);
+
+ /* check limits, no pun intended */
+ if (n > 0x80 || n < -0x7F) {
+ //CompilerWarning( n, RSPCompilePC);
+ } else
+ *(uint8_t*)(JumpByte) = (uint8_t)n;
+}
+
+void RSPx86_SetBranch32b(void * JumpByte, void * Destination) {
+ //intptr_t disp = (uintptr_t)Destination - (uintptr_t)JumpByte;
+
+ //if(disp < 0) disp = 0 - disp;
+ //if(disp >= 0x7f000000) {
+ // Int3();
+ //}
+ *(uint32_t*)(JumpByte) = (uint32_t)((uint8_t*)Destination - (uint8_t*)((uint32_t*)JumpByte + 1));
+}
+
+/************************* OpCode functions *************************/
+void RSPCompile_SPECIAL ( void ) {
+ ((void (*)()) RSP_Special[ RSPOpC.funct ])();
+}
+
+void RSPCompile_REGIMM ( void ) {
+ ((void (*)()) RSP_RegImm[ RSPOpC.rt ])();
+}
+
+void RSPCompile_J ( void ) {
+ if ( RSPNextInstruction == NORMAL ) {
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ RSPNextInstruction = DO_DELAY_SLOT;
+ } else if ( RSPNextInstruction == DELAY_SLOT_DONE ) {
+ RSPJmpLabel32 ( 0 );
+ RSPBranch_AddRef((RSPOpC.target << 2) & 0xFFC, (uint32_t*)(RSPRecompPos - 4));
+ RSPNextInstruction = FINISH_SUB_BLOCK;
+ } else {
+ CompilerWarning( NextInstruction);
+ }
+}
+
+void RSPCompile_JAL ( void ) {
+ if ( RSPNextInstruction == NORMAL ) {
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ RSPMoveConstToVariable(RSPCompilePC + 8, &RSP_GPR[31].UW);
+ RSPNextInstruction = DO_DELAY_SLOT;
+ } else if ( RSPNextInstruction == DELAY_SLOT_DONE ) {
+ RSPJmpLabel32 (0 );
+ RSPBranch_AddRef((RSPOpC.target << 2) & 0xFFC, (uint32_t*)(RSPRecompPos - 4));
+ RSPNextInstruction = FINISH_SUB_BLOCK;
+ } else {
+ CompilerWarning( NextInstruction);
+ }
+}
+
+void RSPCompile_BEQ ( void ) {
+ static int32_t bDelayAffect;
+
+ if ( RSPNextInstruction == NORMAL ) {
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ if (RSPOpC.rs == 0 && RSPOpC.rt == 0) {
+ RSPNextInstruction = DO_DELAY_SLOT;
+ return;
+ }
+ bDelayAffect = DelaySlotAffectBranch(RSPCompilePC);
+ if (0 == bDelayAffect) {
+ RSPNextInstruction = DO_DELAY_SLOT;
+ return;
+ }
+ if (RSPOpC.rt == 0) {
+ RSPCompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W);
+ } else if (RSPOpC.rs == 0) {
+ RSPCompConstToVariable(0,&RSP_GPR[RSPOpC.rt].W);
+ } else {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W,x86_EAX);
+ RSPCompX86regToVariable(x86_EAX,&RSP_GPR[RSPOpC.rs].W);
+ }
+ RSPSetzVariable(&RSPBranchCompare);
+ RSPNextInstruction = DO_DELAY_SLOT;
+ } else if ( RSPNextInstruction == DELAY_SLOT_DONE ) {
+ uint32_t Target = (RSPCompilePC + ((int16_t)RSPOpC.offset << 2) + 4) & 0xFFC;
+
+ if (RSPOpC.rs == 0 && RSPOpC.rt == 0) {
+ RSPJmpLabel32 (0 );
+ RSPBranch_AddRef(Target, (uint32_t*)(RSPRecompPos - 4));
+ RSPNextInstruction = FINISH_SUB_BLOCK;
+ return;
+ }
+ if (0 == bDelayAffect) {
+ if (RSPOpC.rt == 0) {
+ RSPCompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W);
+ } else if (RSPOpC.rs == 0) {
+ RSPCompConstToVariable(0,&RSP_GPR[RSPOpC.rt].W);
+ } else {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W,x86_EAX);
+ RSPCompX86regToVariable(x86_EAX,&RSP_GPR[RSPOpC.rs].W);
+ }
+ RSPJeLabel32( 0);
+ } else {
+ /* take a look at the branch compare variable */
+ RSPCompConstToVariable(1, &RSPBranchCompare);
+ RSPJeLabel32( 0);
+ }
+ RSPBranch_AddRef(Target, (uint32_t*)(RSPRecompPos - 4));
+ RSPNextInstruction = FINISH_SUB_BLOCK;
+ } else {
+ CompilerWarning( NextInstruction);
+ }
+}
+
+void RSPCompile_BNE ( void ) {
+ static int32_t bDelayAffect;
+
+ if ( RSPNextInstruction == NORMAL ) {
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ if (RSPOpC.rs == 0 && RSPOpC.rt == 0) {
+ RSPNextInstruction = DO_DELAY_SLOT;
+ return;
+ }
+
+ bDelayAffect = DelaySlotAffectBranch(RSPCompilePC);
+ if (0 == bDelayAffect) {
+ RSPNextInstruction = DO_DELAY_SLOT;
+ return;
+ }
+ if (RSPOpC.rt == 0) {
+ RSPCompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W);
+ } else if (RSPOpC.rs == 0) {
+ RSPCompConstToVariable(0,&RSP_GPR[RSPOpC.rt].W);
+ } else {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W,x86_EAX);
+ RSPCompX86regToVariable(x86_EAX,&RSP_GPR[RSPOpC.rs].W);
+ }
+ RSPSetnzVariable(&RSPBranchCompare);
+ RSPNextInstruction = DO_DELAY_SLOT;
+ } else if ( RSPNextInstruction == DELAY_SLOT_DONE ) {
+ uint32_t Target = (RSPCompilePC + ((int16_t)RSPOpC.offset << 2) + 4) & 0xFFC;
+
+ if (RSPOpC.rs == 0 && RSPOpC.rt == 0) {
+ RSPNextInstruction = FINISH_SUB_BLOCK;
+ return;
+ }
+
+ if (0 == bDelayAffect) {
+ if (RSPOpC.rt == 0) {
+ RSPCompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W);
+ } else if (RSPOpC.rs == 0) {
+ RSPCompConstToVariable(0,&RSP_GPR[RSPOpC.rt].W);
+ } else {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W,x86_EAX);
+ RSPCompX86regToVariable(x86_EAX,&RSP_GPR[RSPOpC.rs].W);
+ }
+ RSPJneLabel32( 0);
+ } else {
+ /* take a look at the branch compare variable */
+ RSPCompConstToVariable(1, &RSPBranchCompare);
+ RSPJeLabel32( 0);
+ }
+ //if(RSPCompilePC==0x24)
+ // Int3();
+ RSPBranch_AddRef(Target, (uint32_t*)(RSPRecompPos - 4));
+ RSPNextInstruction = FINISH_SUB_BLOCK;
+ } else {
+ CompilerWarning( NextInstruction);
+ }
+}
+
+void RSPCompile_BLEZ ( void ) {
+ static int32_t bDelayAffect;
+
+ if ( RSPNextInstruction == NORMAL ) {
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ if (RSPOpC.rs == 0) {
+ RSPNextInstruction = DO_DELAY_SLOT;
+ return;
+ }
+ bDelayAffect = DelaySlotAffectBranch(RSPCompilePC);
+ if (0 == bDelayAffect) {
+ RSPNextInstruction = DO_DELAY_SLOT;
+ return;
+ }
+ RSPCompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W);
+ RSPSetleVariable(&RSPBranchCompare);
+ RSPNextInstruction = DO_DELAY_SLOT;
+ } else if ( RSPNextInstruction == DELAY_SLOT_DONE ) {
+ uint32_t Target = (RSPCompilePC + ((int16_t)RSPOpC.offset << 2) + 4) & 0xFFC;
+
+ if (RSPOpC.rs == 0) {
+ RSPJmpLabel32 ( 0 );
+ RSPBranch_AddRef(Target, (uint32_t*)(RSPRecompPos - 4));
+ RSPNextInstruction = FINISH_SUB_BLOCK;
+ return;
+ }
+ if (0 == bDelayAffect) {
+ RSPCompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W);
+ RSPJleLabel32( 0);
+ } else {
+ /* take a look at the branch compare variable */
+ RSPCompConstToVariable(1, &RSPBranchCompare);
+ RSPJeLabel32( 0);
+ }
+
+ RSPBranch_AddRef(Target, (uint32_t*)(RSPRecompPos - 4));
+ RSPNextInstruction = FINISH_SUB_BLOCK;
+ } else {
+ CompilerWarning( NextInstruction);
+ }
+}
+
+void RSPCompile_BGTZ ( void ) {
+ static int32_t bDelayAffect;
+
+ if ( RSPNextInstruction == NORMAL ) {
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ if (RSPOpC.rs == 0) {
+ RSPNextInstruction = DO_DELAY_SLOT;
+ return;
+ }
+ bDelayAffect = DelaySlotAffectBranch(RSPCompilePC);
+ if (0 == bDelayAffect) {
+ RSPNextInstruction = DO_DELAY_SLOT;
+ return;
+ }
+ RSPCompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W);
+ RSPSetgVariable(&RSPBranchCompare);
+ RSPNextInstruction = DO_DELAY_SLOT;
+ } else if ( RSPNextInstruction == DELAY_SLOT_DONE ) {
+ uint32_t Target = (RSPCompilePC + ((int16_t)RSPOpC.offset << 2) + 4) & 0xFFC;
+
+ if (RSPOpC.rs == 0) {
+ RSPNextInstruction = FINISH_SUB_BLOCK;
+ return;
+ }
+ if (0 == bDelayAffect) {
+ RSPCompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W);
+ RSPJgLabel32( 0);
+ } else {
+ /* take a look at the branch compare variable */
+ RSPCompConstToVariable(1, &RSPBranchCompare);
+ RSPJeLabel32( 0);
+ }
+ RSPBranch_AddRef(Target, (uint32_t*)(RSPRecompPos - 4));
+ RSPNextInstruction = FINISH_SUB_BLOCK;
+ } else {
+ CompilerWarning( NextInstruction);
+ }
+}
+
+void RSPCompile_ADDI ( void ) {
+ int32_t Immediate = (int16_t)RSPOpC.immediate;
+
+ #ifndef RSPCompile_Immediates
+ RSPCheat_r4300iOpcode(RSP_Opcode_ADDI); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (RSPOpC.rt == 0) return;
+
+ if (RSPOpC.rt == RSPOpC.rs) {
+ RSPAddConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW);
+ } else if (RSPOpC.rs == 0) {
+ RSPMoveConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW);
+ } else {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, x86_EAX);
+ if (Immediate != 0) {
+ RSPAddConstToX86Reg(x86_EAX, Immediate);
+ }
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+ }
+}
+
+void RSPCompile_ADDIU ( void ) {
+ int32_t Immediate = (int16_t)RSPOpC.immediate;
+
+ #ifndef RSPCompile_Immediates
+ RSPCheat_r4300iOpcode(RSP_Opcode_ADDIU); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (RSPOpC.rt == 0) return;
+
+ if (RSPOpC.rt == RSPOpC.rs) {
+ RSPAddConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW);
+ } else if (RSPOpC.rs == 0) {
+ RSPMoveConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW);
+ } else {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, x86_EAX);
+ RSPAddConstToX86Reg(x86_EAX, Immediate);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+ }
+}
+
+void RSPCompile_SLTI ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Opcode_SLTI);
+}
+
+void RSPCompile_SLTIU ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Opcode_SLTIU);
+}
+
+void RSPCompile_ANDI ( void ) {
+ int32_t Immediate = (uint16_t)RSPOpC.immediate;
+
+ #ifndef RSPCompile_Immediates
+ RSPCheat_r4300iOpcode(RSP_Opcode_ANDI); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (RSPOpC.rt == 0) return;
+
+ if (RSPOpC.rt == RSPOpC.rs) {
+ RSPAndConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW);
+ } else if (RSPOpC.rs == 0) {
+ RSPMoveConstToVariable(0, &RSP_GPR[RSPOpC.rt].UW);
+ } else {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, x86_EAX);
+ RSPAndConstToX86Reg(x86_EAX, Immediate);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+ }
+}
+
+void RSPCompile_ORI ( void ) {
+ int32_t Immediate = (uint16_t)RSPOpC.immediate;
+
+ #ifndef RSPCompile_Immediates
+ RSPCheat_r4300iOpcode(RSP_Opcode_ORI); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (RSPOpC.rt == 0) return;
+
+ if (RSPOpC.rt == RSPOpC.rs) {
+ RSPOrConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW);
+ } else if (RSPOpC.rs == 0) {
+ RSPMoveConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW);
+ } else {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, x86_EAX);
+ if (Immediate != 0) {
+ RSPOrConstToX86Reg(Immediate, x86_EAX);
+ }
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+ }
+}
+
+void RSPCompile_XORI ( void ) {
+ int32_t Immediate = (uint16_t)RSPOpC.immediate;
+
+ #ifndef RSPCompile_Immediates
+ RSPCheat_r4300iOpcode(RSP_Opcode_XORI); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (RSPOpC.rt == 0) return;
+
+ if (RSPOpC.rt == RSPOpC.rs) {
+ RSPXorConstToVariable(&RSP_GPR[RSPOpC.rt].UW, Immediate);
+ } else if (RSPOpC.rs == 0) {
+ RSPMoveConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW);
+ } else {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, x86_EAX);
+ if (Immediate != 0) {
+ RSPXorConstToX86Reg(x86_EAX, Immediate);
+ }
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+ }
+}
+
+void RSPCompile_LUI ( void ) {
+ int32_t n = (int16_t)RSPOpC.offset << 16;
+
+ #ifndef RSPCompile_Immediates
+ RSPCheat_r4300iOpcode(RSP_Opcode_LUI); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (RSPOpC.rt == 0) return;
+ RSPMoveConstToVariable(n, &RSP_GPR[RSPOpC.rt].W);
+}
+
+void RSPCompile_COP0 (void) {
+ ((void (*)()) RSP_Cop0[ RSPOpC.rs ])();
+}
+
+void RSPCompile_COP2 (void) {
+ ((void (*)()) RSP_Cop2[ RSPOpC.rs ])();
+}
+
+void RSPCompile_LB ( void ) {
+ int32_t Offset = (int16_t)RSPOpC.offset;
+
+ #ifndef RSPCompile_GPRLoads
+ RSPCheat_r4300iOpcode(RSP_Opcode_LB); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, x86_EBX);
+ if (Offset != 0) RSPAddConstToX86Reg(x86_EBX, Offset);
+ RSPXorConstToX86Reg(x86_EBX, 3);
+ RSPAndConstToX86Reg(x86_EBX, 0x0fff);
+
+ RSPMoveSxN64MemToX86regByte(x86_EAX, x86_EBX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+}
+
+void RSPCompile_LH ( void ) {
+ int32_t Offset = (int16_t)RSPOpC.offset;
+ uint8_t * Jump[2];
+
+ #ifndef RSPCompile_GPRLoads
+ RSPCheat_r4300iOpcode(RSP_Opcode_LH); return;
+ #endif
+
+ if(RSPCompilePC == 0x108) {
+ // RSPBreakPoint();
+// _asm int32_t 3
+
+ }
+
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (IsRegConst(RSPOpC.base) == 1) {
+ uint32_t Addr = (MipsRegConst(RSPOpC.base) + Offset) ^ 2;
+ Addr &= 0xfff;
+
+ if ((Addr & 1) != 0) {
+ CompilerWarning( RSPCompilePC);
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Opcode_LH);
+ return;
+ } else {
+
+
+ RSPMoveSxVariableToX86regHalf(DMEM + Addr, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+ return;
+ }
+ }
+
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, x86_EBX);
+ if (Offset != 0) RSPAddConstToX86Reg(x86_EBX, Offset);
+
+ if (Compiler.bAlignGPR == 0) {
+ RSPTestConstToX86Reg(1, x86_EBX);
+ RSPJneLabel32( 0);
+ Jump[0] = RSPRecompPos - 4;
+
+ CompilerToggleBuffer();
+
+ CPU_Message(" Unaligned:");
+ RSPx86_SetBranch32b(Jump[0], RSPRecompPos);
+
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Opcode_LH);
+ RSPJmpLabel32( 0);
+ Jump[1] = RSPRecompPos - 4;
+
+ CompilerToggleBuffer();
+ }
+
+ RSPXorConstToX86Reg(x86_EBX, 2);
+ RSPAndConstToX86Reg(x86_EBX, 0x0fff);
+
+
+ RSPMoveSxN64MemToX86regHalf(x86_EAX, x86_EBX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+
+ if (Compiler.bAlignGPR == 0) {
+ CPU_Message(" Done:");
+ RSPx86_SetBranch32b(Jump[1], RSPRecompPos);
+ }
+}
+
+void RSPCompile_LW ( void ) {
+ int32_t Offset = (int16_t)RSPOpC.offset;
+ uint8_t * Jump[2];
+
+ #ifndef RSPCompile_GPRLoads
+ RSPCheat_r4300iOpcode(RSP_Opcode_LW); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (IsRegConst(RSPOpC.base) == 1) {
+ uint32_t Addr = (MipsRegConst(RSPOpC.base) + Offset) & 0xfff;
+
+ if ((Addr & 3) != 0) {
+ CompilerWarning( RSPCompilePC);
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Opcode_LW);
+ return;
+ } else {
+
+
+ RSPMoveVariableToX86reg(DMEM + Addr, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+ return;
+ }
+ }
+
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, x86_EBX);
+ if (Offset != 0) RSPAddConstToX86Reg(x86_EBX, Offset);
+
+ RSPTestConstToX86Reg(3, x86_EBX);
+ RSPJneLabel32( 0);
+ Jump[0] = RSPRecompPos - 4;
+
+ //if(runcount == 2)
+ //asm("int $3");
+
+ CompilerToggleBuffer();
+
+ RSPx86_SetBranch32b(Jump[0], RSPRecompPos);
+ CPU_Message(" Unaligned:");
+
+ RSPLeaSourceAndOffset(x86_ECX , x86_EBX, 2);
+ RSPLeaSourceAndOffset(x86_EDX , x86_EBX, 3);
+ RSPMoveX86RegToX86Reg(x86_EBX, x86_EAX);
+ RSPAddConstToX86Reg(x86_EBX, 1);
+
+ RSPXorConstToX86Reg(x86_EAX, 3);
+ RSPXorConstToX86Reg(x86_EBX, 3);
+ RSPXorConstToX86Reg(x86_ECX, 3);
+ RSPXorConstToX86Reg(x86_EDX, 3);
+ RSPMoveN64MemToX86regByte(x86_EAX, x86_EAX);
+ RSPMoveN64MemToX86regByte(x86_EBX, x86_EBX);
+ RSPMoveN64MemToX86regByte(x86_ECX, x86_ECX);
+ RSPMoveN64MemToX86regByte(x86_EDX, x86_EDX);
+ RSPMoveX86regByteToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UB[3]);
+ RSPMoveX86regByteToVariable(x86_EBX, &RSP_GPR[RSPOpC.rt].UB[2]);
+ RSPMoveX86regByteToVariable(x86_ECX, &RSP_GPR[RSPOpC.rt].UB[1]);
+ RSPMoveX86regByteToVariable(x86_EDX, &RSP_GPR[RSPOpC.rt].UB[0]);
+
+ RSPJmpLabel32( 0);
+ Jump[1] = RSPRecompPos - 4;
+ CompilerToggleBuffer();
+
+ RSPAndConstToX86Reg(x86_EBX, 0x0fff);
+ RSPMoveN64MemToX86reg(x86_EAX, x86_EBX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+
+ CPU_Message(" Done:");
+ RSPx86_SetBranch32b(Jump[1], RSPRecompPos);
+}
+
+void RSPCompile_LBU ( void ) {
+ int32_t Offset = (int16_t)RSPOpC.offset;
+
+ #ifndef RSPCompile_GPRLoads
+ RSPCheat_r4300iOpcode(RSP_Opcode_LBU); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, x86_EBX);
+ RSPXorX86RegToX86Reg(x86_EAX, x86_EAX);
+
+ if (Offset != 0) RSPAddConstToX86Reg(x86_EBX, Offset);
+ RSPXorConstToX86Reg(x86_EBX, 3);
+ RSPAndConstToX86Reg(x86_EBX, 0x0fff);
+
+ RSPMoveN64MemToX86regByte(x86_EAX, x86_EBX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+}
+
+void RSPCompile_LHU ( void ) {
+ int32_t Offset = (int16_t)RSPOpC.offset;
+ uint8_t * Jump[2];
+
+ #ifndef RSPCompile_GPRLoads
+ RSPCheat_r4300iOpcode(RSP_Opcode_LHU); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (IsRegConst(RSPOpC.base) == 1) {
+ uint32_t Addr = (MipsRegConst(RSPOpC.base) + Offset) ^ 2;
+ Addr &= 0xfff;
+
+
+ if ((Addr & 1) != 0) {
+ CompilerWarning( RSPCompilePC);
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Opcode_LHU);
+ return;
+ } else {
+
+
+ RSPMoveZxVariableToX86regHalf(DMEM + Addr, x86_ECX);
+ RSPMoveX86regToVariable(x86_ECX, &RSP_GPR[RSPOpC.rt].UW);
+ return;
+ }
+ }
+
+
+
+ /*
+ * should really just do it by bytes but whatever for now
+ */
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, x86_EBX);
+ if (Offset != 0) {
+ RSPAddConstToX86Reg(x86_EBX, Offset);
+ }
+ RSPTestConstToX86Reg(1, x86_EBX);
+ RSPJneLabel32( 0);
+ Jump[0] = RSPRecompPos - 4;
+
+ CompilerToggleBuffer();
+ CPU_Message(" Unaligned:");
+ RSPx86_SetBranch32b(Jump[0], RSPRecompPos);
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Opcode_LHU);
+ RSPJmpLabel32( 0);
+ Jump[1] = RSPRecompPos - 4;
+ CompilerToggleBuffer();
+
+ RSPXorConstToX86Reg(x86_EBX, 2);
+ RSPAndConstToX86Reg(x86_EBX, 0x0fff);
+ RSPMoveZxN64MemToX86regHalf(x86_EAX, x86_EBX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+
+ CPU_Message(" Done:");
+ RSPx86_SetBranch32b(Jump[1], RSPRecompPos);
+}
+
+void RSPCompile_SB ( void ) {
+ int32_t Offset = (int16_t)RSPOpC.offset;
+
+ #ifndef RSPCompile_GPRStores
+ RSPCheat_r4300iOpcode(RSP_Opcode_SB); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, x86_EBX);
+ RSPMoveVariableToX86regByte(&RSP_GPR[RSPOpC.rt].UW, x86_EAX);
+
+ if (Offset != 0) RSPAddConstToX86Reg(x86_EBX, Offset);
+ RSPXorConstToX86Reg(x86_EBX, 3);
+ RSPAndConstToX86Reg(x86_EBX, 0x0fff);
+
+ RSPMoveX86regByteToN64Mem(x86_EAX, x86_EBX);
+}
+
+void RSPCompile_SH ( void ) {
+ int32_t Offset = (int16_t)RSPOpC.offset;
+ uint8_t * Jump[2];
+
+ #ifndef RSPCompile_GPRStores
+ RSPCheat_r4300iOpcode(RSP_Opcode_SH); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (IsRegConst(RSPOpC.base) == 1) {
+ uint32_t Addr = (MipsRegConst(RSPOpC.base) + Offset) ^ 2;
+ Addr &= 0xfff;
+
+ if ((Offset & 1) != 0) {
+ CompilerWarning( RSPCompilePC);
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Opcode_SH);
+ return;
+ } else {
+
+
+ RSPMoveVariableToX86regHalf(&RSP_GPR[RSPOpC.rt].UW, x86_EAX);
+ RSPMoveX86regHalfToVariable(x86_EAX, DMEM + Addr);
+ return;
+ }
+ }
+
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, x86_EBX);
+ if (Offset != 0) RSPAddConstToX86Reg(x86_EBX, Offset);
+
+ if (Compiler.bAlignGPR == 0) {
+ RSPTestConstToX86Reg(1, x86_EBX);
+ RSPJneLabel32( 0);
+ Jump[0] = RSPRecompPos - 4;
+
+ CompilerToggleBuffer();
+
+ CPU_Message(" Unaligned:");
+ RSPx86_SetBranch32b(Jump[0], RSPRecompPos);
+
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Opcode_SH);
+ RSPJmpLabel32( 0);
+ Jump[1] = RSPRecompPos - 4;
+
+ CompilerToggleBuffer();
+ }
+
+ RSPXorConstToX86Reg(x86_EBX, 2);
+ RSPAndConstToX86Reg(x86_EBX, 0x0fff);
+
+ RSPMoveVariableToX86regHalf(&RSP_GPR[RSPOpC.rt].UW, x86_EAX);
+ RSPMoveX86regHalfToN64Mem(x86_EAX, x86_EBX);
+
+ if (Compiler.bAlignGPR == 0) {
+ CPU_Message(" Done:");
+ RSPx86_SetBranch32b(Jump[1], RSPRecompPos);
+ }
+}
+
+void RSPCompile_SW ( void ) {
+ int32_t Offset = (int16_t)RSPOpC.offset;
+ uint8_t * Jump[2];
+
+ #ifndef RSPCompile_GPRStores
+ RSPCheat_r4300iOpcode(RSP_Opcode_SW); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (IsRegConst(RSPOpC.base) == 1) {
+ uint32_t Addr = (MipsRegConst(RSPOpC.base) + Offset) & 0xfff;
+
+ if ((Addr & 3) != 0) {
+ CompilerWarning( RSPCompilePC);
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Opcode_SW);
+ return;
+ } else {
+
+
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, DMEM + Addr);
+ return;
+ }
+ }
+
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, x86_EBX);
+ if (Offset != 0) RSPAddConstToX86Reg(x86_EBX, Offset);
+
+ if (Compiler.bAlignGPR == 0) {
+ RSPTestConstToX86Reg(3, x86_EBX);
+ RSPJneLabel32( 0);
+ Jump[0] = RSPRecompPos - 4;
+
+ CompilerToggleBuffer();
+
+ CPU_Message(" Unaligned:");
+ RSPx86_SetBranch32b(Jump[0], RSPRecompPos);
+
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Opcode_SW);
+ RSPJmpLabel32( 0);
+ Jump[1] = RSPRecompPos - 4;
+
+ CompilerToggleBuffer();
+ }
+
+ RSPAndConstToX86Reg(x86_EBX, 0x0fff);
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, x86_EAX);
+ RSPMoveX86regToN64Mem(x86_EAX, x86_EBX);
+
+ if (Compiler.bAlignGPR == 0) {
+ CPU_Message(" Done:");
+ RSPx86_SetBranch32b(Jump[1], RSPRecompPos);
+ }
+}
+
+void RSPCompile_LC2 (void) {
+ ((void (*)()) RSP_Lc2 [ RSPOpC.rd ])();
+}
+
+void RSPCompile_SC2 (void) {
+ ((void (*)()) RSP_Sc2 [ RSPOpC.rd ])();
+}
+/********************** R4300i OpCodes: Special **********************/
+
+void RSPCompile_Special_SLL ( void ) {
+ #ifndef RSPCompile_Special
+ RSPCheat_r4300iOpcode(RSP_Special_SLL); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ if (RSPOpC.rd == 0) return;
+
+ if (RSPOpC.rd == RSPOpC.rt) {
+ RSPShiftLeftSignVariableImmed(&RSP_GPR[RSPOpC.rd].W, (uint8_t)RSPOpC.sa);
+ } else {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, x86_EAX);
+ RSPShiftLeftSignImmed(x86_EAX, (uint8_t)RSPOpC.sa);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ }
+}
+
+void RSPCompile_Special_SRL ( void ) {
+ #ifndef RSPCompile_Special
+ RSPCheat_r4300iOpcode(RSP_Special_SRL); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ if (RSPOpC.rd == 0) return;
+
+ if (RSPOpC.rd == RSPOpC.rt) {
+ RSPShiftRightUnsignVariableImmed(&RSP_GPR[RSPOpC.rd].W, (uint8_t)RSPOpC.sa);
+ } else {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, x86_EAX);
+ RSPShiftRightUnsignImmed(x86_EAX, (uint8_t)RSPOpC.sa);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ }
+}
+
+void RSPCompile_Special_SRA ( void ) {
+ #ifndef RSPCompile_Special
+ RSPCheat_r4300iOpcode(RSP_Special_SRA); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ if (RSPOpC.rd == 0) return;
+
+ if (RSPOpC.rd == RSPOpC.rt) {
+ RSPShiftRightSignVariableImmed(&RSP_GPR[RSPOpC.rd].W, (uint8_t)RSPOpC.sa);
+ } else {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, x86_EAX);
+ RSPShiftRightSignImmed(x86_EAX, (uint8_t)RSPOpC.sa);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ }
+}
+
+void RSPCompile_Special_SLLV ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Special_SLLV);
+}
+
+void RSPCompile_Special_SRLV ( void ) {
+ #ifndef RSPCompile_Special
+ RSPCheat_r4300iOpcode(RSP_Special_SRLV); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ if (RSPOpC.rd == 0) return;
+
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, x86_EAX);
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, x86_ECX);
+ RSPAndConstToX86Reg(x86_ECX, 0x1F);
+ RSPShiftRightUnsign(x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+}
+
+void RSPCompile_Special_SRAV ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Special_SRAV);
+}
+
+void RSPCompile_Special_JR (void) {
+ uint8_t * Jump;
+
+ if ( RSPNextInstruction == NORMAL ) {
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ /* transfer destination to location pointed to by PrgCount */
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W,x86_EAX);
+ RSPAndConstToX86Reg(x86_EAX,0xFFC);
+ RSPMoveX86regToVariable(x86_EAX,PrgCount);
+ RSPNextInstruction = DO_DELAY_SLOT;
+ } else if ( RSPNextInstruction == DELAY_SLOT_DONE ) {
+ //RSPBreakPoint();
+ RSPMoveVariableToX86reg(PrgCount, x86_EAX);
+#ifdef USEX64
+ RSPShiftLeftDoubleImmed(x86_EAX,x86_EAX,1);
+#endif
+ RSPAddVariableToX86reg(x86_RAX, &RSPJumpTable);
+ RSPMoveX86regPointerToX86reg(x86_RAX, x86_RAX);
+
+ RSPTestX86RegToX86Reg(x86_RAX, x86_RAX);
+ RSPJeLabel8( 0);
+ Jump = RSPRecompPos - 1;
+ RSPPush(x86_RAX);
+ RSPPop(x86_RAX);
+ RSPJumpX86Reg(x86_RAX);
+
+ RSPx86_SetBranch8b(Jump, RSPRecompPos);
+ CPU_Message(" Null:");
+ RSPRet();
+ RSPNextInstruction = FINISH_SUB_BLOCK;
+ } else {
+ CompilerWarning( NextInstruction);
+ }
+}
+
+int32_t llastjump = 0;
+void RSPCompile_Special_JALR ( void ) {
+ uint8_t * Jump;
+ uint32_t Const = (RSPCompilePC + 8) & 0xFFC;
+
+ if (RSPNextInstruction == NORMAL) {
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ RSPMoveConstToVariable(Const, &RSP_GPR[RSPOpC.rd].W);
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W,x86_EAX);
+ RSPAndConstToX86Reg(x86_EAX,0xFFC);
+ RSPMoveX86regToVariable(x86_EAX,PrgCount);
+ RSPNextInstruction = DO_DELAY_SLOT;
+ } else if (RSPNextInstruction == DELAY_SLOT_DONE) {
+
+ RSPMoveVariableToX86reg(PrgCount, x86_EAX);
+#ifdef USEX64
+ RSPShiftLeftDoubleImmed(x86_RAX,x86_EAX,1);
+#endif
+ RSPAddVariableToX86reg(x86_RAX, &RSPJumpTable);
+ RSPMoveX86regPointerToX86reg(x86_RAX, x86_RAX);
+
+ RSPTestX86RegToX86Reg(x86_RAX, x86_RAX);
+ RSPJeLabel8( 0);
+ Jump = RSPRecompPos - 1;
+
+ RSPJumpX86Reg(x86_RAX);
+
+ RSPx86_SetBranch8b(Jump, RSPRecompPos);
+ CPU_Message(" Null:");
+ RSPRet();
+ RSPNextInstruction = FINISH_SUB_BLOCK;
+ } else {
+ CompilerWarning( NextInstruction);
+ }
+}
+
+void RSPCompile_Special_BREAK ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Special_BREAK);
+ if (RSPNextInstruction != NORMAL) {
+ DisplayError("Compile_Special_BREAK: problem");
+ }
+ RSPMoveConstToVariable(RSPCompilePC + 4,PrgCount);
+ RSPRet();
+ RSPNextInstruction = FINISH_BLOCK;
+}
+
+void RSPCompile_Special_ADD ( void ) {
+ #ifndef RSPCompile_Special
+ RSPCheat_r4300iOpcode(RSP_Special_ADD); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (RSPOpC.rd == 0) return;
+
+ if (RSPOpC.rd == RSPOpC.rs) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, x86_EAX);
+ RSPAddX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ } else if (RSPOpC.rd == RSPOpC.rt) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, x86_EAX);
+ RSPAddX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ } else if (RSPOpC.rs == RSPOpC.rt) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, x86_EAX);
+ RSPAddX86RegToX86Reg(x86_EAX, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ } else if (RSPOpC.rs == 0) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ } else if (RSPOpC.rt == 0) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ } else {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, x86_EAX);
+ RSPAddVariableToX86reg(x86_EAX, &RSP_GPR[RSPOpC.rt].W);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ }
+}
+
+void RSPCompile_Special_ADDU ( void ) {
+ #ifndef RSPCompile_Special
+ RSPCheat_r4300iOpcode(RSP_Special_ADDU); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (RSPOpC.rd == 0) return;
+
+ if (RSPOpC.rd == RSPOpC.rs) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, x86_EAX);
+ RSPAddX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ } else if (RSPOpC.rd == RSPOpC.rt) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, x86_EAX);
+ RSPAddX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ } else if (RSPOpC.rs == RSPOpC.rt) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, x86_EAX);
+ RSPAddX86RegToX86Reg(x86_EAX, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ } else if (RSPOpC.rs == 0) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ } else if (RSPOpC.rt == 0) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ } else {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, x86_EAX);
+ RSPAddVariableToX86reg(x86_EAX, &RSP_GPR[RSPOpC.rt].W);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ }
+}
+
+void RSPCompile_Special_SUB ( void ) {
+ #ifndef RSPCompile_Special
+ RSPCheat_r4300iOpcode(RSP_Special_SUB); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (RSPOpC.rd == 0) return;
+
+ if (RSPOpC.rd == RSPOpC.rs) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, x86_EAX);
+ RSPSubX86regFromVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ } else if (RSPOpC.rs == RSPOpC.rt) {
+ RSPMoveConstToVariable(0, &RSP_GPR[RSPOpC.rd].W);
+ } else {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, x86_EAX);
+ RSPSubVariableFromX86reg(x86_EAX, &RSP_GPR[RSPOpC.rt].W);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ }
+}
+
+void RSPCompile_Special_SUBU ( void ) {
+ #ifndef RSPCompile_Special
+ RSPCheat_r4300iOpcode(RSP_Special_SUBU); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (RSPOpC.rd == 0) return;
+
+ if (RSPOpC.rd == RSPOpC.rs) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, x86_EAX);
+ RSPSubX86regFromVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ } else if (RSPOpC.rs == RSPOpC.rt) {
+ RSPMoveConstToVariable(0, &RSP_GPR[RSPOpC.rd].W);
+ } else {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, x86_EAX);
+ RSPSubVariableFromX86reg(x86_EAX, &RSP_GPR[RSPOpC.rt].W);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ }
+}
+
+void RSPCompile_Special_AND ( void ) {
+ #ifndef RSPCompile_Special
+ RSPCheat_r4300iOpcode(RSP_Special_AND); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (RSPOpC.rd == 0) return;
+
+ if (RSPOpC.rd == RSPOpC.rs) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, x86_EAX);
+ RSPAndX86RegToVariable(&RSP_GPR[RSPOpC.rd].W, x86_EAX);
+ } else if (RSPOpC.rd == RSPOpC.rt) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, x86_EAX);
+ RSPAndX86RegToVariable(&RSP_GPR[RSPOpC.rd].W, x86_EAX);
+ } else if (RSPOpC.rs == RSPOpC.rt) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ } else {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, x86_EAX);
+ RSPAndVariableToX86Reg(&RSP_GPR[RSPOpC.rt].W, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ }
+}
+
+void RSPCompile_Special_OR ( void ) {
+ #ifndef RSPCompile_Special
+ RSPCheat_r4300iOpcode(RSP_Special_OR); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (RSPOpC.rd == 0) return;
+
+ if (RSPOpC.rd == RSPOpC.rs) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, x86_EAX);
+ RSPOrX86RegToVariable(&RSP_GPR[RSPOpC.rd].W, x86_EAX);
+ } else if (RSPOpC.rd == RSPOpC.rt) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, x86_EAX);
+ RSPOrX86RegToVariable(&RSP_GPR[RSPOpC.rd].W, x86_EAX);
+ } else if (RSPOpC.rs == 0) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ } else if (RSPOpC.rt == 0) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ } else {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, x86_EAX);
+ RSPOrVariableToX86Reg(&RSP_GPR[RSPOpC.rt].W, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ }
+}
+
+void RSPCompile_Special_XOR ( void ) {
+ #ifndef RSPCompile_Special
+ RSPCheat_r4300iOpcode(RSP_Special_XOR); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (RSPOpC.rd == 0) return;
+
+ if (RSPOpC.rd == RSPOpC.rs) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, x86_EAX);
+ RSPXorX86RegToVariable(&RSP_GPR[RSPOpC.rd].W, x86_EAX);
+ } else if (RSPOpC.rd == RSPOpC.rt) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, x86_EAX);
+ RSPXorX86RegToVariable(&RSP_GPR[RSPOpC.rd].W, x86_EAX);
+ } else if (RSPOpC.rs == RSPOpC.rt) {
+ RSPMoveConstToVariable(0, &RSP_GPR[RSPOpC.rd].W);
+ } else {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, x86_EAX);
+ RSPXorVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W);
+ }
+}
+
+void RSPCompile_Special_NOR ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Special_NOR);
+}
+
+void RSPCompile_Special_SLT ( void ) {
+ #ifndef RSPCompile_Special
+ RSPCheat_r4300iOpcode(RSP_Special_SLT); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ if (RSPOpC.rt == 0) { return; }
+
+ if (RSPOpC.rt == RSPOpC.rs) {
+ RSPMoveConstToVariable(0, &RSP_GPR[RSPOpC.rd].UW);
+ } else {
+ RSPXorX86RegToX86Reg(x86_EBX, x86_EBX);
+ if (RSPOpC.rs == 0) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, x86_EAX);
+ RSPCompConstToX86reg(x86_EAX, 0);
+ RSPSetg(x86_EBX);
+ } else if (RSPOpC.rt == 0) {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, x86_EAX);
+ RSPCompConstToX86reg(x86_EAX, 0);
+ RSPSetl(x86_EBX);
+ } else {
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, x86_EAX);
+ RSPCompX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+ RSPSetl(x86_EBX);
+ }
+ RSPMoveX86regToVariable(x86_EBX, &RSP_GPR[RSPOpC.rd].UW);
+ }
+}
+
+void RSPCompile_Special_SLTU ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Special_SLTU);
+}
+
+/********************** R4300i OpCodes: RegImm **********************/
+void RSPCompile_RegImm_BLTZ ( void ) {
+ static int32_t bDelayAffect;
+
+ if ( RSPNextInstruction == NORMAL ) {
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ if (RSPOpC.rs == 0) {
+ RSPNextInstruction = DO_DELAY_SLOT;
+ return;
+ }
+ bDelayAffect = DelaySlotAffectBranch(RSPCompilePC);
+ if (0 == bDelayAffect) {
+ RSPNextInstruction = DO_DELAY_SLOT;
+ return;
+ }
+ RSPCompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W);
+ RSPSetlVariable(&RSPBranchCompare);
+ RSPNextInstruction = DO_DELAY_SLOT;
+ } else if ( RSPNextInstruction == DELAY_SLOT_DONE ) {
+ uint32_t Target = (RSPCompilePC + ((int16_t)RSPOpC.offset << 2) + 4) & 0xFFC;
+
+ if (RSPOpC.rs == 0) {
+ RSPNextInstruction = FINISH_SUB_BLOCK;
+ return;
+ }
+ if (0 == bDelayAffect) {
+ RSPCompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W);
+ RSPJlLabel32( 0);
+ } else {
+ /* take a look at the branch compare variable */
+ RSPCompConstToVariable(1, &RSPBranchCompare);
+ RSPJeLabel32( 0);
+ }
+ RSPBranch_AddRef(Target, (uint32_t*)(RSPRecompPos - 4));
+ RSPNextInstruction = FINISH_SUB_BLOCK;
+ } else {
+ //CompilerWarning( NextInstruction, RSPCompilePC);
+ }
+}
+
+void RSPCompile_RegImm_BGEZ ( void ) {
+ static int32_t bDelayAffect;
+
+ if ( RSPNextInstruction == NORMAL ) {
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ if (RSPOpC.rs == 0) {
+ RSPNextInstruction = DO_DELAY_SLOT;
+ return;
+ }
+ bDelayAffect = DelaySlotAffectBranch(RSPCompilePC);
+ if (0 == bDelayAffect) {
+ RSPNextInstruction = DO_DELAY_SLOT;
+ return;
+ }
+ RSPCompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W);
+ RSPSetgeVariable(&RSPBranchCompare);
+ RSPNextInstruction = DO_DELAY_SLOT;
+ } else if ( RSPNextInstruction == DELAY_SLOT_DONE ) {
+ uint32_t Target = (RSPCompilePC + ((int16_t)RSPOpC.offset << 2) + 4) & 0xFFC;
+
+ if (RSPOpC.rs == 0) {
+ RSPJmpLabel32 ( 0 );
+ RSPBranch_AddRef(Target, (uint32_t*)(RSPRecompPos - 4));
+ RSPNextInstruction = FINISH_SUB_BLOCK;
+ return;
+ }
+ if (0 == bDelayAffect) {
+ RSPCompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W);
+ RSPJgeLabel32( 0);
+ } else {
+ /* take a look at the branch compare variable */
+ RSPCompConstToVariable(1, &RSPBranchCompare);
+ RSPJeLabel32( 0);
+ }
+ RSPBranch_AddRef(Target, (uint32_t*)(RSPRecompPos - 4));
+ RSPNextInstruction = FINISH_SUB_BLOCK;
+ } else {
+ CompilerWarning( NextInstruction);
+ }
+}
+
+void RSPCompile_RegImm_BLTZAL ( void ) {
+ if ( RSPNextInstruction == NORMAL ) {
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ RSPMoveConstToVariable(RSPCompilePC + 8, &RSP_GPR[31].UW);
+ if (RSPOpC.rs == 0) {
+ RSPNextInstruction = DO_DELAY_SLOT;
+ return;
+ }
+ RSPCompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W);
+ RSPSetlVariable(&RSPBranchCompare);
+ RSPNextInstruction = DO_DELAY_SLOT;
+ } else if ( RSPNextInstruction == DELAY_SLOT_DONE ) {
+ uint32_t Target = (RSPCompilePC + ((int16_t)RSPOpC.offset << 2) + 4) & 0xFFC;
+
+ if (RSPOpC.rs == 0) {
+ RSPNextInstruction = FINISH_SUB_BLOCK;
+ return;
+ }
+
+ /* take a look at the branch compare variable */
+ RSPCompConstToVariable(1, &RSPBranchCompare);
+ RSPJeLabel32( 0);
+ RSPBranch_AddRef(Target, (uint32_t*)(RSPRecompPos - 4));
+ RSPNextInstruction = FINISH_SUB_BLOCK;
+ } else {
+ CompilerWarning( NextInstruction);
+ }
+}
+
+void RSPCompile_RegImm_BGEZAL ( void ) {
+ static int32_t bDelayAffect;
+
+ if ( RSPNextInstruction == NORMAL ) {
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ RSPMoveConstToVariable(RSPCompilePC + 8, &RSP_GPR[31].UW);
+ if (RSPOpC.rs == 0) {
+ RSPNextInstruction = DO_DELAY_SLOT;
+ return;
+ }
+ bDelayAffect = DelaySlotAffectBranch(RSPCompilePC);
+ if (0 == bDelayAffect) {
+ RSPNextInstruction = DO_DELAY_SLOT;
+ return;
+ }
+ RSPCompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W);
+ RSPSetgeVariable(&RSPBranchCompare);
+ RSPNextInstruction = DO_DELAY_SLOT;
+ } else if ( RSPNextInstruction == DELAY_SLOT_DONE ) {
+ uint32_t Target = (RSPCompilePC + ((int16_t)RSPOpC.offset << 2) + 4) & 0xFFC;
+
+ if (RSPOpC.rs == 0) {
+ RSPJmpLabel32 ( 0 );
+ RSPBranch_AddRef(Target, (uint32_t*)(RSPRecompPos - 4));
+ RSPNextInstruction = FINISH_SUB_BLOCK;
+ return;
+ }
+ if (0 == bDelayAffect) {
+ RSPCompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W);
+ RSPJgeLabel32( 0);
+ } else {
+ /* take a look at the branch compare variable */
+ RSPCompConstToVariable(1, &RSPBranchCompare);
+ RSPJeLabel32( 0);
+ }
+ RSPBranch_AddRef(Target, (uint32_t*)(RSPRecompPos - 4));
+ RSPNextInstruction = FINISH_SUB_BLOCK;
+ } else {
+ CompilerWarning( NextInstruction);
+ }
+}
+
+/************************** Cop0 functions *************************/
+
+void RSPCompile_Cop0_MF ( void ) {
+ #ifndef RSPCompile_Cop0
+ RSPCheat_r4300iOpcode(RSP_Cop0_MF); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ switch (RSPOpC.rd) {
+ case 4:
+ RSPMoveVariableToX86reg(&SP_STATUS_REG, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+ break;
+ case 5:
+ RSPMoveVariableToX86reg(&SP_DMA_FULL_REG, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+ break;
+ case 6:
+ RSPMoveVariableToX86reg(&SP_DMA_BUSY_REG, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+ break;
+ case 7:
+ RSPMoveConstToVariable(0, &RSP_GPR[RSPOpC.rt].UW);
+ //RSPCheat_r4300iOpcode(RSP_Cop0_MF);
+ break;
+ case 8:
+ RSPMoveVariableToX86reg(&DPC_START_REG, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+ break;
+ case 9:
+ RSPMoveVariableToX86reg(&DPC_END_REG, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+ break;
+ case 10:
+ RSPMoveVariableToX86reg(&DPC_CURRENT_REG, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+ break;
+ case 11:
+ RSPMoveVariableToX86reg(&DPC_STATUS_REG, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+ break;
+ case 12:
+ RSPMoveVariableToX86reg(&DPC_CLOCK_REG, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW);
+ break;
+
+ //default:
+ //CompilerWarning(COP0_Name(RSPOpC.rd),RSPOpC.rd);
+ }
+}
+
+void RSPCompile_Cop0_MT ( void ) {
+#ifndef RSPCompile_Cop0
+ RSPCheat_r4300iOpcode(RSP_Cop0_MT);
+#else
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ switch (RSPOpC.rd) {
+ case 0:
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &SP_MEM_ADDR_REG);
+ break;
+ case 1:
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &SP_DRAM_ADDR_REG);
+ break;
+ case 2:
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &SP_RD_LEN_REG);
+ RSPPushad();
+ RSPCall_Direct(RSP_SP_DMA_READ);
+ RSPPopad();
+ break;
+ case 3:
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &SP_WR_LEN_REG);
+ RSPPushad();
+ RSPCall_Direct(RSP_SP_DMA_WRITE);
+ RSPPopad();
+ break;
+ case 7:
+ RSPMoveConstToVariable(0, &SP_SEMAPHORE_REG);
+ break;
+ case 8:
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &DPC_START_REG);
+ RSPMoveX86regToVariable(x86_EAX, &DPC_CURRENT_REG);
+ break;
+ case 9:
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &DPC_END_REG);
+
+ break;
+ case 10:
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, x86_EAX);
+ RSPMoveX86regToVariable(x86_EAX, &DPC_CURRENT_REG);
+ break;
+
+ default:
+ RSPCheat_r4300iOpcode(RSP_Cop0_MT);
+ break;
+ }
+#endif
+ if (RSPOpC.rd == 2) {
+ uint8_t * Jump;
+
+ RSPTestConstToVariable(0x1000, &SP_MEM_ADDR_REG);
+ RSPJeLabel8( 0);
+ Jump = RSPRecompPos - 1;
+
+ RSPMoveConstToVariable(RSPCompilePC + 4,PrgCount);
+ RSPRet();
+
+ CPU_Message("DontExit:");
+ RSPx86_SetBranch8b(Jump, RSPRecompPos);
+ }
+}
+/************************** Cop2 functions *************************/
+
+void RSPCompile_Cop2_MF ( void ) {
+
+ int32_t element = (RSPOpC.sa >> 1);
+
+ int32_t element1 = 15 - element;
+ int32_t element2 = 15 - ((element + 1) % 16);
+
+ #ifndef RSPCompile_Cop2
+ RSPCheat_r4300iOpcode(RSP_Cop2_MF); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (element2 != (element1 - 1)) {
+ RSPXorX86RegToX86Reg(x86_EAX, x86_EAX);
+ RSPXorX86RegToX86Reg(x86_EBX, x86_EBX);
+
+
+ RSPMoveVariableToX86regByte(&RSP_Vect[RSPOpC.rd].B[element1], x86_EAX);
+
+
+ RSPMoveVariableToX86regByte(&RSP_Vect[RSPOpC.rd].B[element2], x86_EBX);
+
+ RSPShiftLeftSignImmed(x86_EAX, 8);
+ RSPOrX86RegToX86Reg(x86_EAX, x86_EBX);
+ RSPCwde();
+
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].W);
+ } else {
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].B[element2], x86_EAX);
+
+ RSPMoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].W);
+ }
+}
+
+void RSPCompile_Cop2_CF ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Cop2_CF);
+}
+
+void RSPCompile_Cop2_MT ( void ) {
+
+ int32_t element = 15 - (RSPOpC.sa >> 1);
+
+ #ifndef RSPCompile_Cop2
+ RSPCheat_r4300iOpcode(RSP_Cop2_MT); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ if (element == 0) {
+
+ RSPMoveVariableToX86regByte(&RSP_GPR[RSPOpC.rt].B[1], x86_EAX);
+
+
+ RSPMoveX86regByteToVariable(x86_EAX, &RSP_Vect[RSPOpC.rd].B[element]);
+ } else {
+
+ RSPMoveVariableToX86regHalf(&RSP_GPR[RSPOpC.rt].B[0], x86_EAX);
+
+
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.rd].B[element - 1]);
+ }
+}
+
+void RSPCompile_Cop2_CT ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Cop2_CT);
+}
+
+void RSPCompile_COP2_VECTOR (void) {
+ ((void (*)()) RSP_Vector[ RSPOpC.funct ])();
+}
+
+/************************** Vect functions **************************/
+
+MIPS_DWORD MMX_Scratch;
+
+void RSP_Element2Mmx(int32_t MmxReg) {
+
+
+ uint32_t Rs = RSPOpC.rs & 0x0f;
+ uint32_t el;
+
+ switch (Rs) {
+ case 0: case 1:
+ case 2: case 3:
+ case 4: case 5:
+ case 6: case 7:
+ //CompilerWarning("Unimplemented RSP_Element2Mmx");
+ break;
+
+ default:
+ /*
+ * Noticed the exclusive-or of seven to take into account
+ * the pseudo-swapping we have in the vector registers
+ */
+
+ el = (RSPOpC.rs & 0x07) ^ 7;
+
+ if (IsMmx2Enabled == 0) {
+
+ RSPMoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[el], x86_ECX);
+ RSPMoveX86regHalfToVariable(x86_ECX, &MMX_Scratch.HW[0]);
+ RSPMoveX86regHalfToVariable(x86_ECX, &MMX_Scratch.HW[1]);
+ RSPMoveX86regHalfToVariable(x86_ECX, &MMX_Scratch.HW[2]);
+ RSPMoveX86regHalfToVariable(x86_ECX, &MMX_Scratch.HW[3]);
+ RSPMmxMoveQwordVariableToReg(MmxReg, &MMX_Scratch.HW[0]);
+ } else {
+ uint32_t Qword;
+
+ Qword = (el >> 2) & 0x1;
+ el &= 0x3;
+
+
+ RSPMmxShuffleMemoryToReg(MmxReg,
+ &RSP_Vect[RSPOpC.rt].DW[Qword], _MMX_SHUFFLE(el, el, el, el));
+ }
+ break;
+ }
+}
+
+void RSP_MultiElement2Mmx(int32_t MmxReg1, int32_t MmxReg2) {
+
+ uint32_t Rs = RSPOpC.rs & 0x0f;
+
+ /*
+ * Ok, this is tricky, hopefully this clears it up:
+ *
+ * $vd[0] = $vd[0] + $vt[2]
+ * because of swapped registers becomes:
+ * $vd[7] = $vd[7] + $vt[5]
+ *
+ * we must perform this swap correctly, this involves the 3-bit
+ * xclusive or, 2-bits of which are done within a dword boundary,
+ * the last bit, is ignored because we are loading the source linearly,
+ * so the xclusive or has transparently happened on that side
+ *
+ */
+
+ switch (Rs) {
+ case 0:
+ case 1:
+
+ RSPMmxMoveQwordVariableToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].UHW[0]);
+
+ RSPMmxMoveQwordVariableToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].UHW[4]);
+ break;
+ case 2:
+ /* [0q] | 0 | 0 | 2 | 2 | 4 | 4 | 6 | 6 | */
+
+ RSPMmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], 0xF5);
+
+ RSPMmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], 0xF5);
+ break;
+ case 3:
+ /* [1q] | 1 | 1 | 3 | 3 | 5 | 5 | 7 | 7 | */
+
+ RSPMmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], 0xA0);
+ //RSPMmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], 0x0A);
+
+ RSPMmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], 0xA0);
+ //RSPMmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], 0x0A);
+ break;
+ case 4:
+ /* [0h] | 0 | 0 | 0 | 0 | 4 | 4 | 4 | 4 | */
+
+ RSPMmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], 0xFF);
+
+ RSPMmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], 0xFF);
+ break;
+ case 5:
+ /* [1h] | 1 | 1 | 1 | 1 | 5 | 5 | 5 | 5 | */
+
+ RSPMmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], 0xAA);
+
+ RSPMmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], 0xAA);
+ break;
+ case 6:
+ /* [2h] | 2 | 2 | 2 | 2 | 6 | 6 | 6 | 6 | */
+
+ RSPMmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], 0x55);
+
+ RSPMmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], 0x55);
+ break;
+ case 7:
+ /* [3h] | 3 | 3 | 3 | 3 | 7 | 7 | 7 | 7 | */
+
+ RSPMmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], 0x00);
+
+ RSPMmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], 0x00);
+ break;
+
+ default:
+ //CompilerWarning("Unimplemented RSP_MultiElement2Mmx [?]");
+ break;
+ }
+}
+
+int32_t RSPCompile_Vector_VMULF_MMX ( void ) {
+
+
+ /* Do our MMX checks here */
+ if (IsMmxEnabled == 0)
+ return 0;
+ if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == 0)
+ return 0;
+
+ /* NOTE: Problem here is the lack of +/- 0x8000 rounding */
+
+ RSPMmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0]);
+
+ RSPMmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4]);
+
+ if ((RSPOpC.rs & 0xF) < 2) {
+
+ RSPMmxPmulhwRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.rt].UHW[0]);
+
+ RSPMmxPmulhwRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.rt].UHW[4]);
+ } else if ((RSPOpC.rs & 0xF) >= 8) {
+ RSP_Element2Mmx(x86_MM2);
+ RSPMmxPmulhwRegToReg(x86_MM0, x86_MM2);
+ RSPMmxPmulhwRegToReg(x86_MM1, x86_MM2);
+ } else {
+ RSP_MultiElement2Mmx(x86_MM2, x86_MM3);
+ RSPMmxPmulhwRegToReg(x86_MM0, x86_MM2);
+ RSPMmxPmulhwRegToReg(x86_MM1, x86_MM3);
+ }
+ RSPMmxPsllwImmed(x86_MM0, 1);
+ RSPMmxPsllwImmed(x86_MM1, 1);
+
+
+ RSPMmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0]);
+
+ RSPMmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4]);
+
+ if (IsNextInstructionMmx(RSPCompilePC) == 0)
+ RSPMmxEmptyMultimediaState();
+
+ return 1;
+}
+
+void RSPCompile_Vector_VMULF ( void ) {
+
+ int32_t count, el, del;
+
+ int32_t bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? 1 : 0;
+ int32_t bWriteToAccum = WriteToAccum(EntireAccum, RSPCompilePC);
+ int32_t bWriteToDest = WriteToVectorDest(RSPOpC.sa, RSPCompilePC);
+
+ #ifndef RSPCompileVmulf
+ RSPCheat_r4300iOpcode(RSP_Vector_VMULF); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (bWriteToAccum == 0) {
+ if (1 == RSPCompile_Vector_VMULF_MMX())
+ return;
+ }
+
+ if (bOptimize == 1) {
+ del = (RSPOpC.rs & 0x07) ^ 7;
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ if (bWriteToDest == 1) {
+ RSPMoveConstToX86reg(0x7fff0000, x86_ESI);
+ }
+ if (bWriteToAccum == 1) {
+ RSPXorX86RegToX86Reg(x86_EDI, x86_EDI);
+ }
+
+ for (count = 0; count < 8; count++) {
+ CPU_Message( count);
+
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], x86_EAX);
+
+ if (RSPOpC.rt == RSPOpC.rd && !bOptimize) {
+ RSPimulX86reg(x86_EAX);
+ } else {
+ if (bOptimize == 0) {
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+ RSPimulX86reg(x86_EBX);
+ }
+
+ RSPShiftLeftSignImmed(x86_EAX, 1);
+ RSPAddConstToX86Reg(x86_EAX, 0x8000);
+
+ if (bWriteToAccum == 1) {
+ RSPMoveX86regToVariable(x86_EAX, &RSP_ACCUM[el].HW[1]);
+ /* calculate sign extension into edx */
+ RSPMoveX86RegToX86Reg(x86_EAX, x86_EDX);
+ RSPShiftRightSignImmed(x86_EDX, 31);
+ }
+
+ RSPCompConstToX86reg(x86_EAX, 0x80008000);
+
+ if (bWriteToAccum == 1) {
+ RSPCondMoveEqual(x86_EDX, x86_EDI);
+ RSPMoveX86regHalfToVariable(x86_EDX, &RSP_ACCUM[el].HW[3]);
+ }
+ if (bWriteToDest == 1) {
+ RSPCondMoveEqual(x86_EAX, x86_ESI);
+ RSPShiftRightUnsignImmed(x86_EAX, 16);
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el]);
+ }
+ }
+}
+
+void RSPCompile_Vector_VMULU ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Vector_VMULU);
+}
+
+int32_t RSPCompile_Vector_VMUDL_MMX ( void ) {
+
+
+ /* Do our MMX checks here */
+ if (IsMmxEnabled == 0)
+ return 0;
+ if (IsMmx2Enabled == 0)
+ return 0;
+
+
+ RSPMmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0]);
+
+ RSPMmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4]);
+
+ if ((RSPOpC.rs & 0xF) < 2) {
+
+ RSPMmxMoveQwordVariableToReg(x86_MM2, &RSP_Vect[RSPOpC.rt].UHW[0]);
+
+ RSPMmxMoveQwordVariableToReg(x86_MM3, &RSP_Vect[RSPOpC.rt].UHW[4]);
+
+ RSPMmxPmulhuwRegToReg(x86_MM0, x86_MM2);
+ RSPMmxPmulhuwRegToReg(x86_MM1, x86_MM3);
+ } else if ((RSPOpC.rs & 0xF) >= 8) {
+ RSP_Element2Mmx(x86_MM2);
+ RSPMmxPmulhuwRegToReg(x86_MM0, x86_MM2);
+ RSPMmxPmulhuwRegToReg(x86_MM1, x86_MM2);
+ } else {
+ RSP_MultiElement2Mmx(x86_MM2, x86_MM3);
+ RSPMmxPmulhuwRegToReg(x86_MM0, x86_MM2);
+ RSPMmxPmulhuwRegToReg(x86_MM1, x86_MM3);
+ }
+
+
+ RSPMmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0]);
+
+ RSPMmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4]);
+
+ if (IsNextInstructionMmx(RSPCompilePC) == 0)
+ RSPMmxEmptyMultimediaState();
+
+ return 1;
+}
+
+void RSPCompile_Vector_VMUDL ( void ) {
+
+ int32_t count, el, del;
+
+ int32_t bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? 1 : 0;
+ int32_t bWriteToDest = WriteToVectorDest(RSPOpC.sa, RSPCompilePC);
+ int32_t bWriteToAccum = WriteToAccum(EntireAccum, RSPCompilePC);
+
+ #ifndef RSPCompileVmudl
+ RSPCheat_r4300iOpcode(RSP_Vector_VMUDL); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (bWriteToAccum == 0) {
+ if (1 == RSPCompile_Vector_VMUDL_MMX())
+ return;
+ }
+
+ if (bOptimize == 1) {
+ del = (RSPOpC.rs & 0x07) ^ 7;
+
+ RSPMoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ if (bWriteToAccum == 1)
+ RSPXorX86RegToX86Reg(x86_EDI, x86_EDI);
+
+ for (count = 0; count < 8; count++) {
+ CPU_Message( count);
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+
+ RSPMoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].UHW[el], x86_EAX);
+
+ if (bOptimize == 0) {
+
+ RSPMoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ RSPimulX86reg(x86_EBX);
+
+ if (bWriteToAccum == 1) {
+
+ RSPMoveX86regToVariable(x86_EAX, &RSP_ACCUM[el].UW[0]);
+
+ RSPMoveX86regToVariable(x86_EDI, &RSP_ACCUM[el].UW[1]);
+ }
+
+ if (bWriteToDest == 1) {
+ RSPShiftRightUnsignImmed(x86_EAX, 16);
+
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el]);
+ }
+ }
+}
+
+int32_t RSPCompile_Vector_VMUDM_MMX ( void ) {
+
+
+ /* Do our MMX checks here */
+ if (IsMmxEnabled == 0)
+ return 0;
+ if (IsMmx2Enabled == 0)
+ return 0;
+
+
+ RSPMmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0]);
+
+ RSPMmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4]);
+
+ if ((RSPOpC.rs & 0xF) < 2) {
+
+ RSPMmxMoveQwordVariableToReg(x86_MM4, &RSP_Vect[RSPOpC.rt].UHW[0]);
+
+ RSPMmxMoveQwordVariableToReg(x86_MM5, &RSP_Vect[RSPOpC.rt].UHW[4]);
+
+ /* Copy the signed portion */
+ RSPMmxMoveRegToReg(x86_MM2, x86_MM0);
+ RSPMmxMoveRegToReg(x86_MM3, x86_MM1);
+
+ /* high((u16)a * b) */
+ RSPMmxPmulhuwRegToReg(x86_MM0, x86_MM4);
+ RSPMmxPmulhuwRegToReg(x86_MM1, x86_MM5);
+
+ /* low((a >> 15) * b) */
+ RSPMmxPsrawImmed(x86_MM2, 15);
+ RSPMmxPsrawImmed(x86_MM3, 15);
+ RSPMmxPmullwRegToReg(x86_MM2, x86_MM4);
+ RSPMmxPmullwRegToReg(x86_MM3, x86_MM5);
+ } else if ((RSPOpC.rs & 0xF) >= 8) {
+ RSP_Element2Mmx(x86_MM4);
+
+ /* Copy the signed portion */
+ RSPMmxMoveRegToReg(x86_MM2, x86_MM0);
+ RSPMmxMoveRegToReg(x86_MM3, x86_MM1);
+
+ /* high((u16)a * b) */
+ RSPMmxPmulhuwRegToReg(x86_MM0, x86_MM4);
+ RSPMmxPmulhuwRegToReg(x86_MM1, x86_MM4);
+
+ /* low((a >> 15) * b) */
+ RSPMmxPsrawImmed(x86_MM2, 15);
+ RSPMmxPsrawImmed(x86_MM3, 15);
+ RSPMmxPmullwRegToReg(x86_MM2, x86_MM4);
+ RSPMmxPmullwRegToReg(x86_MM3, x86_MM4);
+ } else {
+ RSP_MultiElement2Mmx(x86_MM4, x86_MM5);
+
+ /* Copy the signed portion */
+ RSPMmxMoveRegToReg(x86_MM2, x86_MM0);
+ RSPMmxMoveRegToReg(x86_MM3, x86_MM1);
+
+ /* high((u16)a * b) */
+ RSPMmxPmulhuwRegToReg(x86_MM0, x86_MM4);
+ RSPMmxPmulhuwRegToReg(x86_MM1, x86_MM5);
+
+ /* low((a >> 15) * b) */
+ RSPMmxPsrawImmed(x86_MM2, 15);
+ RSPMmxPsrawImmed(x86_MM3, 15);
+ RSPMmxPmullwRegToReg(x86_MM2, x86_MM4);
+ RSPMmxPmullwRegToReg(x86_MM3, x86_MM5);
+ }
+
+ /* Add them up */
+ RSPMmxPaddwRegToReg(x86_MM0, x86_MM2);
+ RSPMmxPaddwRegToReg(x86_MM1, x86_MM3);
+
+
+ RSPMmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0]);
+
+ RSPMmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4]);
+
+ if (IsNextInstructionMmx(RSPCompilePC) == 0)
+ RSPMmxEmptyMultimediaState();
+
+ return 1;
+}
+
+void RSPCompile_Vector_VMUDM ( void ) {
+
+ int32_t count, el, del;
+
+ int32_t bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? 1 : 0;
+ int32_t bWriteToDest = WriteToVectorDest(RSPOpC.sa, RSPCompilePC);
+ int32_t bWriteToAccum = WriteToAccum(EntireAccum, RSPCompilePC);
+
+ #ifndef RSPCompileVmudm
+ RSPCheat_r4300iOpcode(RSP_Vector_VMUDM); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (bWriteToAccum == 0) {
+ if (1 == RSPCompile_Vector_VMUDM_MMX())
+ return;
+ }
+
+ if (bOptimize == 1) {
+ del = (RSPOpC.rs & 0x07) ^ 7;
+
+ RSPMoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ RSPPush(x86_RBP);
+
+ RSPMoveConstQwordToX86reg((uintptr_t)&RSP_Vect[RSPOpC.rd].HW[0], x86_RBP);
+
+ if (bWriteToDest) {
+
+ RSPMoveConstQwordToX86reg((uintptr_t)&RSP_Vect[RSPOpC.sa].HW[0], x86_RCX);
+ } else if (!bOptimize) {
+
+ RSPMoveConstQwordToX86reg((uintptr_t)&RSP_Vect[RSPOpC.rt].HW[0], x86_RCX);
+ }
+
+ for (count = 0; count < 8; count++) {
+ CPU_Message( count);
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ /*
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], x86_EAX);*/
+ RSPMoveSxX86RegPtrDispToX86RegHalf(x86_RBP, el * 2, x86_EAX);
+
+ if (bOptimize == 0) {
+ if (bWriteToDest == 1) {
+
+ RSPMoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ } else {
+ RSPMoveZxX86RegPtrDispToX86RegHalf(x86_RCX, del * 2, x86_EBX);
+ }
+ }
+
+ RSPimulX86reg(x86_EBX);
+
+ if (bWriteToAccum == 0 && bWriteToDest == 1) {
+ RSPShiftRightUnsignImmed(x86_EAX, 16);
+ /*
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el]);*/
+ RSPMoveX86regHalfToX86regPointerDisp(x86_EAX, x86_ECX, el * 2);
+ } else {
+ RSPMoveX86RegToX86Reg(x86_EAX, x86_EDX);
+ RSPShiftRightSignImmed(x86_EDX, 16);
+ RSPShiftLeftSignImmed(x86_EAX, 16);
+
+ if (bWriteToAccum == 1) {
+
+ RSPMoveX86regToVariable(x86_EAX, &RSP_ACCUM[el].UW[0]);
+
+ RSPMoveX86regToVariable(x86_EDX ,&RSP_ACCUM[el].UW[1]);
+ }
+ if (bWriteToDest == 1) {
+ /*
+ RSPMoveX86regHalfToVariable(x86_EDX, &RSP_Vect[RSPOpC.sa].HW[el]);*/
+ RSPMoveX86regHalfToX86regPointerDisp(x86_EDX, x86_ECX, el * 2);
+ }
+ }
+ }
+
+ RSPPop(x86_RBP);
+}
+
+int32_t RSPCompile_Vector_VMUDN_MMX ( void ) {
+
+
+ /* Do our MMX checks here */
+ if (IsMmxEnabled == 0)
+ return 0;
+ if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == 0)
+ return 0;
+
+
+ RSPMmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0]);
+
+ RSPMmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4]);
+
+ if ((RSPOpC.rs & 0xF) < 2) {
+
+ RSPMmxPmullwVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rt].UHW[0]);
+
+ RSPMmxPmullwVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rt].UHW[4]);
+ } else if ((RSPOpC.rs & 0xF) >= 8) {
+ RSP_Element2Mmx(x86_MM2);
+ RSPMmxPmullwRegToReg(x86_MM0, x86_MM2);
+ RSPMmxPmullwRegToReg(x86_MM1, x86_MM2);
+ } else {
+ RSP_MultiElement2Mmx(x86_MM2, x86_MM3);
+ RSPMmxPmullwRegToReg(x86_MM0, x86_MM2);
+ RSPMmxPmullwRegToReg(x86_MM1, x86_MM3);
+ }
+
+
+ RSPMmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0]);
+
+ RSPMmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4]);
+
+ if (IsNextInstructionMmx(RSPCompilePC) == 0)
+ RSPMmxEmptyMultimediaState();
+
+ return 1;
+}
+
+void RSPCompile_Vector_VMUDN ( void ) {
+
+ int32_t count, el, del;
+
+ int32_t bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? 1 : 0;
+ int32_t bWriteToDest = WriteToVectorDest(RSPOpC.sa, RSPCompilePC);
+ int32_t bWriteToAccum = WriteToAccum(EntireAccum, RSPCompilePC);
+
+ #ifndef RSPCompileVmudn
+ RSPCheat_r4300iOpcode(RSP_Vector_VMUDN); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (bWriteToAccum == 0) {
+ if (1 == RSPCompile_Vector_VMUDN_MMX())
+ return;
+ }
+
+ if (bOptimize == 1) {
+ del = (RSPOpC.rs & 0x07) ^ 7;
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ RSPPush(x86_RBP);
+
+ RSPMoveConstQwordToX86reg((uintptr_t)&RSP_Vect[RSPOpC.rd].HW[0], x86_RBP);
+
+ for (count = 0; count < 8; count++) {
+ CPU_Message( count);
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ /*
+ RSPMoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].UHW[el], x86_EAX);*/
+ RSPMoveZxX86RegPtrDispToX86RegHalf(x86_RBP, el * 2, x86_EAX);
+
+ if (bOptimize == 0) {
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ RSPimulX86reg(x86_EBX);
+
+ if (bWriteToDest == 1) {
+
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el]);
+ }
+
+ if (bWriteToAccum == 1) {
+ RSPMoveX86RegToX86Reg(x86_EAX, x86_EDX);
+ RSPShiftRightSignImmed(x86_EDX, 16);
+ RSPShiftLeftSignImmed(x86_EAX, 16);
+
+ RSPMoveX86regToVariable(x86_EAX, &RSP_ACCUM[el].UW[0]);
+
+ RSPMoveX86regToVariable(x86_EDX, &RSP_ACCUM[el].UW[1]);
+ }
+ }
+ RSPPop(x86_RBP);
+}
+
+int32_t RSPCompile_Vector_VMUDH_MMX ( void ) {
+
+
+ /* Do our MMX checks here */
+ if (IsMmxEnabled == 0)
+ return 0;
+ if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == 0)
+ return 0;
+
+
+ RSPMmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].HW[0]);
+
+ RSPMmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].HW[4]);
+
+ /* Registers 4 & 5 are high */
+ RSPMmxMoveRegToReg(x86_MM4, x86_MM0);
+ RSPMmxMoveRegToReg(x86_MM5, x86_MM1);
+
+ if ((RSPOpC.rs & 0x0f) < 2) {
+
+ RSPMmxMoveQwordVariableToReg(x86_MM2, &RSP_Vect[RSPOpC.rt].HW[0]);
+
+ RSPMmxMoveQwordVariableToReg(x86_MM3, &RSP_Vect[RSPOpC.rt].HW[4]);
+
+ RSPMmxPmullwRegToReg(x86_MM0, x86_MM2);
+ RSPMmxPmulhwRegToReg(x86_MM4, x86_MM2);
+ RSPMmxPmullwRegToReg(x86_MM1, x86_MM3);
+ RSPMmxPmulhwRegToReg(x86_MM5, x86_MM3);
+ } else if ((RSPOpC.rs & 0x0f) >= 8) {
+ RSP_Element2Mmx(x86_MM2);
+
+ RSPMmxPmullwRegToReg(x86_MM0, x86_MM2);
+ RSPMmxPmulhwRegToReg(x86_MM4, x86_MM2);
+ RSPMmxPmullwRegToReg(x86_MM1, x86_MM2);
+ RSPMmxPmulhwRegToReg(x86_MM5, x86_MM2);
+ } else {
+ RSP_MultiElement2Mmx(x86_MM2, x86_MM3);
+
+ RSPMmxPmullwRegToReg(x86_MM0, x86_MM2);
+ RSPMmxPmulhwRegToReg(x86_MM4, x86_MM2);
+ RSPMmxPmullwRegToReg(x86_MM1, x86_MM3);
+ RSPMmxPmulhwRegToReg(x86_MM5, x86_MM3);
+ }
+
+ /* 0 & 1 are low, 4 & 5 are high */
+ RSPMmxMoveRegToReg(x86_MM6, x86_MM0);
+ RSPMmxMoveRegToReg(x86_MM7, x86_MM1);
+
+ RSPMmxUnpackLowWord(x86_MM0, x86_MM4);
+ RSPMmxUnpackHighWord(x86_MM6, x86_MM4);
+ RSPMmxUnpackLowWord(x86_MM1, x86_MM5);
+ RSPMmxUnpackHighWord(x86_MM7, x86_MM5);
+
+ /* Integrate copies */
+ RSPMmxPackSignedDwords(x86_MM0, x86_MM6);
+ RSPMmxPackSignedDwords(x86_MM1, x86_MM7);
+
+
+ RSPMmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].HW[0]);
+
+ RSPMmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].HW[4]);
+
+ if (IsNextInstructionMmx(RSPCompilePC) == 0)
+ RSPMmxEmptyMultimediaState();
+
+ return 1;
+}
+
+void RSPCompile_Vector_VMUDH ( void ) {
+
+ int32_t count, el, del;
+
+ int32_t bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? 1 : 0;
+ int32_t bWriteToDest = WriteToVectorDest(RSPOpC.sa, RSPCompilePC);
+ int32_t bWriteToAccum = WriteToAccum(EntireAccum, RSPCompilePC);
+
+// RSPBreakPoint();
+ #ifndef RSPCompileVmudh
+ RSPCheat_r4300iOpcode(RSP_Vector_VMUDH); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (bWriteToAccum == 0) {
+ if (1 == RSPCompile_Vector_VMUDH_MMX())
+ return;
+ }
+
+ if (bWriteToDest == 0 && bOptimize == 1) {
+ RSPPush(x86_RBP);
+
+
+ /* Load source */
+ del = (RSPOpC.rs & 0x07) ^ 7;
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+
+ /*
+ * Pipe lined segment 0
+ */
+
+
+ RSPMoveConstQwordToX86reg((uintptr_t)&RSP_Vect[RSPOpC.rd].HW[0], x86_RBP);
+
+ RSPMoveSxX86RegPtrDispToX86RegHalf(x86_RBP, 0, x86_EAX);
+ RSPMoveSxX86RegPtrDispToX86RegHalf(x86_RBP, 2, x86_ECX);
+ RSPMoveSxX86RegPtrDispToX86RegHalf(x86_RBP, 4, x86_EDI);
+ RSPMoveSxX86RegPtrDispToX86RegHalf(x86_RBP, 6, x86_ESI);
+
+ RSPImulX86RegToX86Reg(x86_EAX, x86_EBX);
+ RSPImulX86RegToX86Reg(x86_ECX, x86_EBX);
+ RSPImulX86RegToX86Reg(x86_EDI, x86_EBX);
+ RSPImulX86RegToX86Reg(x86_ESI, x86_EBX);
+ RSPXorX86RegToX86Reg(x86_EDX, x86_EDX);
+
+ RSPMoveConstQwordToX86reg((uintptr_t)&RSP_ACCUM[0].W[0], x86_RBP);
+
+ RSPMoveX86RegToX86regPointerDisp(x86_EDX, x86_RBP, 0);
+ RSPMoveX86RegToX86regPointerDisp(x86_EAX, x86_RBP, 4);
+ RSPMoveX86RegToX86regPointerDisp(x86_EDX, x86_RBP, 8);
+ RSPMoveX86RegToX86regPointerDisp(x86_ECX, x86_RBP, 12);
+ RSPMoveX86RegToX86regPointerDisp(x86_EDX, x86_RBP, 16);
+ RSPMoveX86RegToX86regPointerDisp(x86_EDI, x86_RBP, 20);
+ RSPMoveX86RegToX86regPointerDisp(x86_EDX, x86_RBP, 24);
+ RSPMoveX86RegToX86regPointerDisp(x86_ESI, x86_RBP, 28);
+
+ /*
+ * Pipe lined segment 1
+ */
+
+
+ RSPMoveConstQwordToX86reg((uintptr_t)&RSP_Vect[RSPOpC.rd].HW[0], x86_RBP);
+
+ RSPMoveSxX86RegPtrDispToX86RegHalf(x86_RBP, 8, x86_EAX);
+ RSPMoveSxX86RegPtrDispToX86RegHalf(x86_RBP, 10, x86_ECX);
+ RSPMoveSxX86RegPtrDispToX86RegHalf(x86_RBP, 12, x86_EDI);
+ RSPMoveSxX86RegPtrDispToX86RegHalf(x86_RBP, 14, x86_ESI);
+
+ RSPImulX86RegToX86Reg(x86_EAX, x86_EBX);
+ RSPImulX86RegToX86Reg(x86_ECX, x86_EBX);
+ RSPImulX86RegToX86Reg(x86_EDI, x86_EBX);
+ RSPImulX86RegToX86Reg(x86_ESI, x86_EBX);
+ RSPXorX86RegToX86Reg(x86_EDX, x86_EDX);
+
+ RSPMoveConstQwordToX86reg((uintptr_t)&RSP_ACCUM[0].W[0], x86_RBP);
+
+ RSPMoveX86RegToX86regPointerDisp(x86_EDX, x86_RBP, 32);
+ RSPMoveX86RegToX86regPointerDisp(x86_EAX, x86_RBP, 36);
+ RSPMoveX86RegToX86regPointerDisp(x86_EDX, x86_RBP, 40);
+ RSPMoveX86RegToX86regPointerDisp(x86_ECX, x86_RBP, 44);
+ RSPMoveX86RegToX86regPointerDisp(x86_EDX, x86_RBP, 48);
+ RSPMoveX86RegToX86regPointerDisp(x86_EDI, x86_RBP, 52);
+ RSPMoveX86RegToX86regPointerDisp(x86_EDX, x86_RBP, 56);
+ RSPMoveX86RegToX86regPointerDisp(x86_ESI, x86_RBP, 60);
+
+ RSPPop(x86_RBP);
+ } else {
+ if (bOptimize == 1) {
+ del = (RSPOpC.rs & 0x07) ^ 7;
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+ if (bWriteToDest == 1) {
+ /*
+ * Prepare for conditional moves
+ */
+ RSPMoveConstToX86reg(0x00007fff, x86_ESI);
+ RSPMoveConstToX86reg(0xFFFF8000, x86_EDI);
+ }
+
+ for (count = 0; count < 8; count++) {
+ CPU_Message( count);
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], x86_EAX);
+
+ if (bOptimize == 0) {
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+ RSPimulX86reg(x86_EBX);
+
+ if (bWriteToAccum == 1) {
+ RSPMoveX86regToVariable(x86_EAX, &RSP_ACCUM[el].W[1]);
+ RSPMoveConstToVariable(0, &RSP_ACCUM[el].W[0]);
+ }
+
+ if (bWriteToDest == 1) {
+ RSPCompX86RegToX86Reg(x86_EAX, x86_ESI);
+ RSPCondMoveGreater(x86_EAX, x86_ESI);
+ RSPCompX86RegToX86Reg(x86_EAX, x86_EDI);
+ RSPCondMoveLess(x86_EAX, x86_EDI);
+
+
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el]);
+ }
+ }
+ }
+}
+
+void RSPCompile_Vector_VMACF ( void ) {
+
+ int32_t count, el, del;
+
+ int32_t bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? 1 : 0;
+ int32_t bWriteToDest = WriteToVectorDest(RSPOpC.sa, RSPCompilePC);
+ int32_t bWriteToAccum = WriteToAccum(EntireAccum, RSPCompilePC);
+
+ #ifndef RSPCompileVmacf
+ RSPCheat_r4300iOpcode(RSP_Vector_VMACF); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (bWriteToDest == 1) {
+ /*
+ * Prepare for conditional moves
+ */
+ RSPMoveConstToX86reg(0x00007fff, x86_ESI);
+ RSPMoveConstToX86reg(0xFFFF8000, x86_EDI);
+ }
+ if (bOptimize == 1) {
+ del = (RSPOpC.rs & 0x07) ^ 7;
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ for (count = 0; count < 8; count++) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ CPU_Message( count);
+
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], x86_EAX);
+
+ if (bOptimize == 0) {
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ RSPimulX86reg(x86_EBX);
+
+ RSPMoveX86RegToX86Reg(x86_EAX, x86_EDX);
+ RSPShiftRightSignImmed(x86_EDX, 15);
+ RSPShiftLeftSignImmed(x86_EAX, 17);
+
+ RSPAddX86regToVariable(x86_EAX, &RSP_ACCUM[el].W[0]);
+ RSPAdcX86regToVariable(x86_EDX, &RSP_ACCUM[el].W[1]);
+
+ if (bWriteToDest == 1) {
+ RSPMoveVariableToX86reg(&RSP_ACCUM[el].W[1], x86_EAX);
+
+ RSPCompX86RegToX86Reg(x86_EAX, x86_ESI);
+ RSPCondMoveGreater(x86_EAX, x86_ESI);
+ RSPCompX86RegToX86Reg(x86_EAX, x86_EDI);
+ RSPCondMoveLess(x86_EAX, x86_EDI);
+
+
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el]);
+ }
+ }
+}
+
+void RSPCompile_Vector_VMACU ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Vector_VMACU);
+}
+
+void RSPCompile_Vector_VMACQ ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Vector_VMACQ);
+}
+
+void RSPCompile_Vector_VMADL ( void ) {
+
+ int32_t count, el, del;
+
+ int32_t bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? 1 : 0;
+ int32_t bWriteToDest = WriteToVectorDest(RSPOpC.sa, RSPCompilePC);
+
+ #ifndef RSPCompileVmadl
+ RSPCheat_r4300iOpcode(RSP_Vector_VMADL); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (bOptimize == 1) {
+ del = (RSPOpC.rs & 0x07) ^ 7;
+
+ RSPMoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ if (bWriteToDest == 1) {
+ /*
+ * Prepare for conditional moves
+ */
+ RSPMoveConstToX86reg(0x00007FFF, x86_ESI);
+ RSPMoveConstToX86reg(0xFFFF8000, x86_EDI);
+
+ RSPPush(x86_RBP);
+ RSPMoveConstToX86reg(0x0000FFFF, x86_EBP);
+ }
+
+ for (count = 0; count < 8; count++) {
+ CPU_Message( count);
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+
+ RSPMoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], x86_EAX);
+
+ if (bOptimize == 0) {
+
+ RSPMoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ RSPimulX86reg(x86_EBX);
+
+ RSPAddX86regToVariable(x86_EAX, &RSP_ACCUM[el].W[0]);
+
+ RSPAdcConstToVariable(&RSP_ACCUM[el].W[1], 0);
+
+ if (bWriteToDest != 0) {
+ RSPXorX86RegToX86Reg(x86_EDX, x86_EDX);
+ RSPMoveVariableToX86reg(&RSP_ACCUM[el].W[1], x86_EAX);
+ RSPMoveZxVariableToX86regHalf(&RSP_ACCUM[el].HW[1], x86_ECX);
+
+ RSPCompX86RegToX86Reg(x86_EAX, x86_ESI);
+ RSPCondMoveGreater(x86_ECX, x86_EBP);
+ RSPCompX86RegToX86Reg(x86_EAX, x86_EDI);
+ RSPCondMoveLess(x86_ECX, x86_EDX);
+
+
+ RSPMoveX86regHalfToVariable(x86_ECX, &RSP_Vect[RSPOpC.sa].HW[el]);
+ }
+ }
+
+ if (bWriteToDest == 1) {
+ RSPPop(x86_EBP);
+ }
+}
+
+void RSPCompile_Vector_VMADM ( void ) {
+
+ int32_t count, el, del;
+
+ int32_t bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? 1 : 0;
+ int32_t bWriteToDest = WriteToVectorDest(RSPOpC.sa, RSPCompilePC);
+ int32_t bWriteToAccum = WriteToAccum(EntireAccum, RSPCompilePC);
+
+ #ifndef RSPCompileVmadm
+ RSPCheat_r4300iOpcode(RSP_Vector_VMADM); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (bOptimize == 1) {
+ del = (RSPOpC.rs & 0x07) ^ 7;
+
+ RSPMoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+ if (bWriteToDest == 1) {
+ /*
+ * Prepare for conditional moves
+ */
+ RSPMoveConstToX86reg(0x00007fff, x86_ESI);
+ RSPMoveConstToX86reg(0xFFFF8000, x86_EDI);
+ }
+
+ RSPPush(x86_RBP);
+
+ RSPMoveConstQwordToX86reg((uintptr_t)&RSP_Vect[RSPOpC.rd].HW[0], x86_RBP);
+
+ if (bWriteToDest) {
+
+ RSPMoveConstQwordToX86reg((uintptr_t)&RSP_Vect[RSPOpC.sa].HW[0], x86_RCX);
+ } else if (!bOptimize) {
+
+ RSPMoveConstQwordToX86reg((uintptr_t)&RSP_Vect[RSPOpC.rt].HW[0], x86_RCX);
+ }
+
+ for (count = 0; count < 8; count++) {
+ CPU_Message( count);
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ /*
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], x86_EAX);*/
+ RSPMoveSxX86RegPtrDispToX86RegHalf(x86_RBP, el * 2, x86_EAX);
+
+ if (bOptimize == 0) {
+ if (bWriteToDest == 1) {
+
+ RSPMoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ } else {
+ RSPMoveZxX86RegPtrDispToX86RegHalf(x86_ECX, del * 2, x86_EBX);
+ }
+ }
+
+ RSPimulX86reg(x86_EBX);
+
+ RSPMoveX86RegToX86Reg(x86_EAX, x86_EDX);
+ RSPShiftRightSignImmed(x86_EDX, 16);
+ RSPShiftLeftSignImmed(x86_EAX, 16);
+ RSPAddX86regToVariable(x86_EAX, &RSP_ACCUM[el].W[0]);
+ RSPAdcX86regToVariable(x86_EDX, &RSP_ACCUM[el].W[1]);
+
+ if (bWriteToDest == 1) {
+ /* For compare */
+
+ RSPMoveVariableToX86reg(&RSP_ACCUM[el].W[1], x86_EAX);
+
+ RSPCompX86RegToX86Reg(x86_EAX, x86_ESI);
+ RSPCondMoveGreater(x86_EAX, x86_ESI);
+ RSPCompX86RegToX86Reg(x86_EAX, x86_EDI);
+ RSPCondMoveLess(x86_EAX, x86_EDI);
+
+ /*
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el]);*/
+ RSPMoveX86regHalfToX86regPointerDisp(x86_EAX, x86_ECX, el * 2);
+ }
+ }
+
+ RSPPop(x86_RBP);
+}
+
+void RSPCompile_Vector_VMADN ( void ) {
+
+ int32_t count, el, del;
+
+ int32_t bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? 1 : 0;
+ int32_t bWriteToDest = WriteToVectorDest(RSPOpC.sa, RSPCompilePC);
+ int32_t bWriteToAccum = WriteToAccum(EntireAccum, RSPCompilePC);
+
+ #ifndef RSPCompileVmadn
+ RSPCheat_r4300iOpcode(RSP_Vector_VMADN); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (bOptimize == 1) {
+ del = (RSPOpC.rs & 0x07) ^ 7;
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+ if (bWriteToDest == 1) {
+ /*
+ * Prepare for conditional moves
+ */
+ RSPMoveConstToX86reg(0x0000ffff, x86_ESI);
+ RSPMoveConstToX86reg(0x00000000, x86_EDI);
+ }
+
+ RSPPush(x86_RBP);
+
+ RSPMoveConstQwordToX86reg((uintptr_t)&RSP_Vect[RSPOpC.rd].HW[0], x86_RBP);
+
+ for (count = 0; count < 8; count++) {
+ CPU_Message( count);
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ /*
+ RSPMoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].UHW[el], x86_EAX);*/
+ RSPMoveZxX86RegPtrDispToX86RegHalf(x86_RBP, el * 2, x86_EAX);
+
+ if (bOptimize == 0) {
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ RSPimulX86reg(x86_EBX);
+
+ RSPMoveX86RegToX86Reg(x86_EAX, x86_EDX);
+ RSPShiftRightSignImmed(x86_EDX, 16);
+ RSPShiftLeftSignImmed(x86_EAX, 16);
+ RSPAddX86regToVariable(x86_EAX, &RSP_ACCUM[el].W[0]);
+ RSPAdcX86regToVariable(x86_EDX, &RSP_ACCUM[el].W[1]);
+
+ if (bWriteToDest == 1) {
+ /* For compare */
+
+ RSPMoveVariableToX86reg(&RSP_ACCUM[el].W[1], x86_EAX);
+
+ /* For vector */
+
+ RSPMoveVariableToX86regHalf(&RSP_ACCUM[el].HW[1], x86_ECX);
+
+ /* Weird eh */
+ RSPCompConstToX86reg(x86_EAX, 0x7fff);
+ RSPCondMoveGreater(x86_ECX, x86_ESI);
+ RSPCompConstToX86reg(x86_EAX, -0x8000);
+ RSPCondMoveLess(x86_ECX, x86_EDI);
+
+
+ RSPMoveX86regHalfToVariable(x86_ECX, &RSP_Vect[RSPOpC.sa].HW[el]);
+ }
+ }
+ RSPPop(x86_RBP);
+}
+
+void RSPCompile_Vector_VMADH ( void ) {
+
+ int32_t count, el, del;
+
+ int32_t bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? 1 : 0;
+ int32_t bWriteToDest = WriteToVectorDest(RSPOpC.sa, RSPCompilePC);
+
+ #ifndef RSPCompileVmadh
+ RSPCheat_r4300iOpcode(RSP_Vector_VMADH); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (bOptimize == 1) {
+ del = (RSPOpC.rs & 0x07) ^ 7;
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ if (bWriteToDest == 1) {
+ /*
+ * Prepare for conditional moves
+ */
+ RSPMoveConstToX86reg(0x00007fff, x86_ESI);
+ RSPMoveConstToX86reg(0xFFFF8000, x86_EDI);
+ }
+
+ if (bWriteToDest == 0 && bOptimize == 1) {
+ RSPPush(x86_RBP);
+
+ RSPMoveConstQwordToX86reg((uintptr_t)&RSP_Vect[RSPOpC.rd].HW[0], x86_RBP);
+
+ /*
+ * Pipe lined segment 0
+ */
+ RSPMoveSxX86RegPtrDispToX86RegHalf(x86_RBP, 0, x86_EAX);
+ RSPMoveSxX86RegPtrDispToX86RegHalf(x86_RBP, 2, x86_ECX);
+ RSPMoveSxX86RegPtrDispToX86RegHalf(x86_RBP, 4, x86_EDI);
+ RSPMoveSxX86RegPtrDispToX86RegHalf(x86_RBP, 6, x86_ESI);
+
+ RSPImulX86RegToX86Reg(x86_EAX, x86_EBX);
+ RSPImulX86RegToX86Reg(x86_ECX, x86_EBX);
+ RSPImulX86RegToX86Reg(x86_EDI, x86_EBX);
+ RSPImulX86RegToX86Reg(x86_ESI, x86_EBX);
+
+
+ RSPAddX86regToVariable(x86_EAX, &RSP_ACCUM[0].W[1]);
+
+ RSPAddX86regToVariable(x86_ECX, &RSP_ACCUM[1].W[1]);
+
+ RSPAddX86regToVariable(x86_EDI, &RSP_ACCUM[2].W[1]);
+
+ RSPAddX86regToVariable(x86_ESI, &RSP_ACCUM[3].W[1]);
+
+ /*
+ * Pipe lined segment 1
+ */
+ RSPMoveSxX86RegPtrDispToX86RegHalf(x86_RBP, 8, x86_EAX);
+ RSPMoveSxX86RegPtrDispToX86RegHalf(x86_RBP, 10, x86_ECX);
+ RSPMoveSxX86RegPtrDispToX86RegHalf(x86_RBP, 12, x86_EDI);
+ RSPMoveSxX86RegPtrDispToX86RegHalf(x86_RBP, 14, x86_ESI);
+
+ RSPImulX86RegToX86Reg(x86_EAX, x86_EBX);
+ RSPImulX86RegToX86Reg(x86_ECX, x86_EBX);
+ RSPImulX86RegToX86Reg(x86_EDI, x86_EBX);
+ RSPImulX86RegToX86Reg(x86_ESI, x86_EBX);
+
+
+ RSPAddX86regToVariable(x86_EAX, &RSP_ACCUM[4].W[1]);
+
+ RSPAddX86regToVariable(x86_ECX, &RSP_ACCUM[5].W[1]);
+
+ RSPAddX86regToVariable(x86_EDI, &RSP_ACCUM[6].W[1]);
+
+ RSPAddX86regToVariable(x86_ESI, &RSP_ACCUM[7].W[1]);
+
+ RSPPop(x86_EBP);
+ } else {
+ RSPPush(x86_RBP);
+
+ RSPMoveConstQwordToX86reg((uintptr_t)&RSP_Vect[RSPOpC.rd].HW[0], x86_RBP);
+
+ if (bWriteToDest) {
+
+ RSPMoveConstQwordToX86reg((uintptr_t)&RSP_Vect[RSPOpC.sa].HW[0], x86_RCX);
+ } else if (!bOptimize) {
+
+ RSPMoveConstQwordToX86reg((uintptr_t)&RSP_Vect[RSPOpC.rt].HW[0], x86_RCX);
+ }
+
+ for (count = 0; count < 8; count++) {
+ CPU_Message( count);
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ /*
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], x86_EAX);*/
+ RSPMoveSxX86RegPtrDispToX86RegHalf(x86_RBP, el * 2, x86_EAX);
+
+ if (bOptimize == 0) {
+ if (bWriteToDest == 1) {
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ } else {
+ RSPMoveSxX86RegPtrDispToX86RegHalf(x86_RCX, del * 2, x86_EBX);
+ }
+ }
+
+ RSPimulX86reg(x86_EBX);
+
+ RSPAddX86regToVariable(x86_EAX, &RSP_ACCUM[el].W[1]);
+
+ if (bWriteToDest == 1) {
+ RSPMoveVariableToX86reg(&RSP_ACCUM[el].W[1], x86_EAX);
+
+ RSPCompX86RegToX86Reg(x86_EAX, x86_ESI);
+ RSPCondMoveGreater(x86_EAX, x86_ESI);
+ RSPCompX86RegToX86Reg(x86_EAX, x86_EDI);
+ RSPCondMoveLess(x86_EAX, x86_EDI);
+
+ /*
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el]);*/
+ RSPMoveX86regHalfToX86regPointerDisp(x86_EAX, x86_ECX, el * 2);
+ }
+ }
+ RSPPop(x86_RBP);
+ }
+}
+
+int32_t RSPCompile_Vector_VADD_MMX ( void ) {
+
+
+ /* Do our MMX checks here */
+ if (IsMmxEnabled == 0)
+ return 0;
+ if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == 0)
+ return 0;
+
+
+ RSPMmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0]);
+
+ RSPMmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4]);
+
+ if ((RSPOpC.rs & 15) >= 8) {
+ RSP_Element2Mmx(x86_MM2);
+ RSPMmxPaddswRegToReg(x86_MM0, x86_MM2);
+ RSPMmxPaddswRegToReg(x86_MM1, x86_MM2);
+ } else if ((RSPOpC.rs & 15) < 2) {
+
+ RSPMmxPaddswVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rt].HW[0]);
+
+ RSPMmxPaddswVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rt].HW[4]);
+ } else {
+ RSP_MultiElement2Mmx(x86_MM2, x86_MM3);
+ RSPMmxPaddswRegToReg(x86_MM0, x86_MM2);
+ RSPMmxPaddswRegToReg(x86_MM1, x86_MM3);
+ }
+
+
+ RSPMmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0]);
+
+ RSPMmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4]);
+ RSPMmxEmptyMultimediaState();
+
+ return 1;
+}
+
+void RSPCompile_Vector_VADD ( void ) {
+
+ int32_t count, el, del;
+
+ int32_t bWriteToDest = WriteToVectorDest(RSPOpC.sa, RSPCompilePC);
+ int32_t bElement = ((RSPOpC.rs & 0x0f) >= 8) ? 1 : 0;
+ int32_t bWriteToAccum = WriteToAccum(Low16BitAccum, RSPCompilePC);
+ int32_t bFlagUseage = UseRspFlags(RSPCompilePC);
+
+ #ifndef RSPCompileVadd
+ RSPCheat_r4300iOpcode(RSP_Vector_VADD); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (bWriteToAccum == 0 && bFlagUseage == 0) {
+ if (1 == RSPCompile_Vector_VADD_MMX())
+ return;
+ }
+
+ if (bElement == 1) {
+ del = (RSPOpC.rs & 0x07) ^ 7;
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+ if (bWriteToDest == 1) {
+ /*
+ * Prepare for conditional moves
+ */
+ RSPMoveConstToX86reg(0x00007fff, x86_ESI);
+ RSPMoveConstToX86reg(0xffff8000, x86_EDI);
+ }
+
+ /* Used for involking x86 carry flag */
+ RSPXorX86RegToX86Reg(x86_ECX, x86_ECX);
+ RSPPush(x86_RBP);
+ RSPMoveVariableToX86reg(&RSP_Flags[0].UW, x86_EBP);
+
+ for (count = 0; count < 8; count++) {
+ CPU_Message( count);
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], x86_EAX);
+
+ if (bElement == 0) {
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ RSPMoveX86RegToX86Reg(x86_EBP, x86_EDX);
+ RSPAndConstToX86Reg(x86_EDX, 1 << (7 - el));
+ RSPCompX86RegToX86Reg(x86_ECX, x86_EDX);
+
+ RSPAdcX86RegToX86Reg(x86_EAX, x86_EBX);
+
+ if (bWriteToAccum == 1) {
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1]);
+ }
+ if (bWriteToDest == 1) {
+ RSPCompX86RegToX86Reg(x86_EAX, x86_ESI);
+ RSPCondMoveGreater(x86_EAX, x86_ESI);
+ RSPCompX86RegToX86Reg(x86_EAX, x86_EDI);
+ RSPCondMoveLess(x86_EAX, x86_EDI);
+
+
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el]);
+ }
+ }
+ RSPMoveConstToVariable(0, &RSP_Flags[0].UW);
+ RSPPop(x86_EBP);
+}
+
+void RSPCompile_Vector_VSUB ( void ) {
+
+ int32_t count, el, del;
+
+ int32_t bWriteToDest = WriteToVectorDest(RSPOpC.sa, RSPCompilePC);
+ int32_t bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? 1 : 0;
+ int32_t bWriteToAccum = WriteToAccum(Low16BitAccum, RSPCompilePC);
+
+ #ifndef RSPCompileVsub
+ RSPCheat_r4300iOpcode(RSP_Vector_VSUB); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ RSPPush(x86_RBP);
+
+ /* Used for involking the x86 carry flag */
+ RSPXorX86RegToX86Reg(x86_ECX, x86_ECX);
+ RSPMoveVariableToX86reg(&RSP_Flags[0].UW, x86_EBP);
+
+ if (bOptimize == 1) {
+ del = (RSPOpC.rs & 0x07) ^ 7;
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ if (bWriteToDest == 1) {
+ /*
+ * Prepare for conditional moves
+ */
+ RSPMoveConstToX86reg(0x00007fff, x86_ESI);
+ RSPMoveConstToX86reg(0xffff8000, x86_EDI);
+ }
+
+ for (count = 0; count < 8; count++) {
+ CPU_Message( count);
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], x86_EAX);
+ if (bOptimize == 0) {
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ RSPMoveX86RegToX86Reg(x86_EBP, x86_EDX);
+ RSPAndConstToX86Reg(x86_EDX, 1 << (7 - el));
+ RSPCompX86RegToX86Reg(x86_ECX, x86_EDX);
+
+ RSPSbbX86RegToX86Reg(x86_EAX, x86_EBX);
+
+ if (bWriteToAccum == 1) {
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1]);
+ }
+ if (bWriteToDest == 1) {
+ RSPCompX86RegToX86Reg(x86_EAX, x86_ESI);
+ RSPCondMoveGreater(x86_EAX, x86_ESI);
+ RSPCompX86RegToX86Reg(x86_EAX, x86_EDI);
+ RSPCondMoveLess(x86_EAX, x86_EDI);
+
+
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el]);
+ }
+ }
+
+ RSPMoveConstToVariable(0, &RSP_Flags[0].UW);
+ RSPPop(x86_EBP);
+}
+
+void RSPCompile_Vector_VABS ( void ) {
+ int32_t count, el, del;
+
+
+ int32_t bWriteToDest = WriteToVectorDest(RSPOpC.sa, RSPCompilePC);
+ int32_t bWriteToAccum = WriteToAccum(Low16BitAccum, RSPCompilePC);
+
+ #ifndef RSPCompileVabs
+ RSPCheat_r4300iOpcode(RSP_Vector_VABS); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ for (count = 0; count < 8; count++) {
+ CPU_Message( count);
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ if (RSPOpC.rd == RSPOpC.rt && (RSPOpC.rs & 0xF) < 2) {
+ /**
+ ** Optimize: EDI/ESI unused, and ECX is const etc
+ ***/
+
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], x86_EAX);
+
+ /*** Obtain the negative of the source ****/
+ RSPMoveX86RegToX86Reg(x86_EAX, x86_EBX);
+ RSPNegateX86reg(x86_EBX);
+
+ /**
+ ** determine negative value,
+ ** note: negate(FFFF8000h) == 00008000h
+ ***/
+
+ RSPMoveConstToX86reg(0x7fff, x86_ECX);
+ RSPCompConstToX86reg(x86_EBX, 0x00008000);
+ RSPCondMoveEqual(x86_EBX, x86_ECX);
+
+ /* sign clamp, dest = (eax >= 0) ? eax : ebx */
+ RSPCompConstToX86reg(x86_EAX, 0);
+ RSPCondMoveLess(x86_EAX, x86_EBX);
+
+ if (bWriteToDest == 1) {
+
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el]);
+ }
+ if (bWriteToAccum == 1) {
+
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1]);
+ }
+ } else {
+ /**
+ ** Optimize: ESI unused, and EDX is const etc
+ ***/
+
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], x86_EAX);
+
+ RSPMoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+
+ /*** Obtain the negative of the source ****/
+ RSPMoveX86RegToX86Reg(x86_EBX, x86_ECX);
+ RSPNegateX86reg(x86_EBX);
+
+ /**
+ ** determine negative value,
+ ** note: negate(FFFF8000h) == 00008000h
+ ***/
+
+ RSPMoveConstToX86reg(0x7fff, x86_EDX);
+ RSPCompConstToX86reg(x86_EBX, 0x00008000);
+ RSPCondMoveEqual(x86_EBX, x86_EDX);
+
+ /* sign clamp, dest = (eax >= 0) ? ecx : ebx */
+ RSPCompConstToX86reg(x86_EAX, 0);
+ RSPCondMoveGreaterEqual(x86_EDI, x86_ECX);
+ RSPCondMoveLess(x86_EDI, x86_EBX);
+
+ if (bWriteToDest == 1) {
+
+ RSPMoveX86regHalfToVariable(x86_EDI, &RSP_Vect[RSPOpC.sa].HW[el]);
+ }
+ if (bWriteToAccum == 1) {
+
+ RSPMoveX86regHalfToVariable(x86_EDI, &RSP_ACCUM[el].HW[1]);
+ }
+ }
+ }
+}
+
+void RSPCompile_Vector_VADDC ( void ) {
+
+ int32_t count, el, del;
+
+ int32_t bWriteToDest = WriteToVectorDest(RSPOpC.sa, RSPCompilePC);
+ int32_t bWriteToAccum = WriteToAccum(Low16BitAccum, RSPCompilePC);
+ int32_t bElement = ((RSPOpC.rs & 0x0f) >= 8) ? 1 : 0;
+
+ #ifndef RSPCompileVaddc
+ RSPCheat_r4300iOpcode(RSP_Vector_VADDC); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (bElement == 1) {
+ del = (RSPOpC.rs & 0x07) ^ 7;
+
+ RSPMoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ /* Initialize flag register */
+ RSPXorX86RegToX86Reg(x86_ECX, x86_ECX);
+
+ RSPPush(x86_RBP);
+
+ RSPMoveConstQwordToX86reg((uintptr_t)&RSP_Vect[RSPOpC.rd].HW[0], x86_RBP);
+
+ for (count = 0; count < 8; count++) {
+ CPU_Message( count);
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ /*
+ RSPMoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], x86_EAX);*/
+ RSPMoveZxX86RegPtrDispToX86RegHalf(x86_RBP, el * 2, x86_EAX);
+
+ if (bElement == 0) {
+
+ RSPMoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ RSPAddX86RegToX86Reg(x86_EAX, x86_EBX);
+
+ RSPXorX86RegToX86Reg(x86_EDX, x86_EDX);
+ RSPTestConstToX86Reg(0xFFFF0000, x86_EAX);
+ RSPSetnz(x86_EDX);
+ if ((7 - el) != 0) {
+ RSPShiftLeftSignImmed(x86_EDX, 7 - el);
+ }
+ RSPOrX86RegToX86Reg(x86_ECX, x86_EDX);
+
+ if (bWriteToAccum == 1) {
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1]);
+ }
+ if (bWriteToDest == 1) {
+
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el]);
+ }
+ }
+ RSPMoveX86regToVariable(x86_ECX, &RSP_Flags[0].UW);
+ RSPPop(x86_RBP);
+}
+
+void RSPCompile_Vector_VSUBC ( void ) {
+
+ int32_t count, el, del;
+
+ int32_t bWriteToDest = WriteToVectorDest(RSPOpC.sa, RSPCompilePC);
+ int32_t bWriteToAccum = WriteToAccum(Low16BitAccum, RSPCompilePC);
+ int32_t bElement = ((RSPOpC.rs & 0x0f) >= 8) ? 1 : 0;
+
+ #ifndef RSPCompileVsubc
+ RSPCheat_r4300iOpcode(RSP_Vector_VSUBC); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (bElement == 1) {
+ del = (RSPOpC.rs & 0x07) ^ 7;
+
+ RSPMoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ /* Initialize flag register */
+ RSPXorX86RegToX86Reg(x86_ECX, x86_ECX);
+
+ for (count = 0; count < 8; count++) {
+ CPU_Message( count);
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+
+ RSPMoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], x86_EAX);
+
+ if (bElement == 0) {
+
+ RSPMoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ RSPSubX86RegToX86Reg(x86_EAX, x86_EBX);
+
+ RSPXorX86RegToX86Reg(x86_EDX, x86_EDX);
+ RSPTestConstToX86Reg(0x0000FFFF, x86_EAX);
+ RSPSetnz(x86_EDX);
+ RSPShiftLeftSignImmed(x86_EDX, 15 - el);
+ RSPOrX86RegToX86Reg(x86_ECX, x86_EDX);
+
+ RSPXorX86RegToX86Reg(x86_EDX, x86_EDX);
+ RSPTestConstToX86Reg(0xFFFF0000, x86_EAX);
+ RSPSetnz(x86_EDX);
+ RSPShiftLeftSignImmed(x86_EDX, 7 - el);
+ RSPOrX86RegToX86Reg(x86_ECX, x86_EDX);
+
+ if (bWriteToAccum == 1) {
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1]);
+ }
+ if (bWriteToDest == 1) {
+
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el]);
+ }
+ }
+ RSPMoveX86regToVariable(x86_ECX, &RSP_Flags[0].UW);
+}
+
+void RSPCompile_Vector_VSAW ( void ) {
+
+ uint32_t Word;
+
+ #ifndef RSPCompileVsaw
+ RSPCheat_r4300iOpcode(RSP_Vector_VSAW); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ switch ((RSPOpC.rs & 0xF)) {
+ case 8: Word = 3; break;
+ case 9: Word = 2; break;
+ case 10: Word = 1; break;
+ default:
+ RSPMoveConstToVariable(0, &RSP_Vect[RSPOpC.sa].DW[1]);
+ RSPMoveConstToVariable(0, &RSP_Vect[RSPOpC.sa].DW[0]);
+ return;
+ }
+
+
+ RSPMoveVariableToX86regHalf(&RSP_ACCUM[1].HW[Word], x86_EAX);
+
+ RSPMoveVariableToX86regHalf(&RSP_ACCUM[3].HW[Word], x86_EBX);
+
+ RSPMoveVariableToX86regHalf(&RSP_ACCUM[5].HW[Word], x86_ECX);
+
+ RSPMoveVariableToX86regHalf(&RSP_ACCUM[7].HW[Word], x86_EDX);
+
+ RSPShiftLeftSignImmed(x86_EAX, 16);
+ RSPShiftLeftSignImmed(x86_EBX, 16);
+ RSPShiftLeftSignImmed(x86_ECX, 16);
+ RSPShiftLeftSignImmed(x86_EDX, 16);
+
+
+ RSPMoveVariableToX86regHalf(&RSP_ACCUM[0].HW[Word], x86_EAX);
+
+ RSPMoveVariableToX86regHalf(&RSP_ACCUM[2].HW[Word], x86_EBX);
+
+ RSPMoveVariableToX86regHalf(&RSP_ACCUM[4].HW[Word], x86_ECX);
+
+ RSPMoveVariableToX86regHalf(&RSP_ACCUM[6].HW[Word], x86_EDX);
+
+
+ RSPMoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[0]);
+
+ RSPMoveX86regToVariable(x86_EBX, &RSP_Vect[RSPOpC.sa].HW[2]);
+
+ RSPMoveX86regToVariable(x86_ECX, &RSP_Vect[RSPOpC.sa].HW[4]);
+
+ RSPMoveX86regToVariable(x86_EDX, &RSP_Vect[RSPOpC.sa].HW[6]);
+}
+
+void RSPCompile_Vector_VLT ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Vector_VLT);
+}
+
+void RSPCompile_Vector_VEQ ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Vector_VEQ);
+}
+
+void RSPCompile_Vector_VNE ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Vector_VNE);
+}
+
+int32_t RSPCompile_Vector_VGE_MMX(void) {
+
+
+ if ((RSPOpC.rs & 0xF) >= 2 && (RSPOpC.rs & 0xF) <= 7 && IsMmx2Enabled == 0)
+ return 0;
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ RSPMoveConstToVariable(0, &RSP_Flags[1].UW);
+
+
+ RSPMmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].HW[0]);
+
+ RSPMmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].HW[4]);
+ RSPMmxMoveRegToReg(x86_MM2, x86_MM0);
+ RSPMmxMoveRegToReg(x86_MM3, x86_MM1);
+
+ if ((RSPOpC.rs & 0x0f) < 2) {
+
+ RSPMmxMoveQwordVariableToReg(x86_MM4, &RSP_Vect[RSPOpC.rt].HW[0]);
+
+ RSPMmxMoveQwordVariableToReg(x86_MM5, &RSP_Vect[RSPOpC.rt].HW[4]);
+ } else if ((RSPOpC.rs & 0x0f) >= 8) {
+ RSP_Element2Mmx(x86_MM4);
+ } else {
+ RSP_MultiElement2Mmx(x86_MM4, x86_MM5);
+ }
+
+ RSPMmxCompareGreaterWordRegToReg(x86_MM2, x86_MM4);
+ RSPMmxCompareGreaterWordRegToReg(x86_MM3, ((RSPOpC.rs & 0x0f) >= 8) ? x86_MM4 : x86_MM5);
+
+ RSPMmxPandRegToReg(x86_MM0, x86_MM2);
+ RSPMmxPandRegToReg(x86_MM1, x86_MM3);
+ RSPMmxPandnRegToReg(x86_MM2, x86_MM4);
+ RSPMmxPandnRegToReg(x86_MM3, ((RSPOpC.rs & 0x0f) >= 8) ? x86_MM4 : x86_MM5);
+
+ RSPMmxPorRegToReg(x86_MM0, x86_MM2);
+ RSPMmxPorRegToReg(x86_MM1, x86_MM3);
+ RSPMoveConstToVariable(0, &RSP_Flags[0].UW);
+ return 1;
+}
+
+void RSPCompile_Vector_VGE ( void ) {
+/* int32_t bWriteToAccum = WriteToAccum(Low16BitAccum, RSPCompilePC);
+
+ /* FIXME: works ok, but needs careful flag analysis */
+/* #if defined (DLIST)
+ if (bWriteToAccum == 0 && 1 == RSPCompile_Vector_VGE_MMX()) {
+ return;
+ }
+ #endif
+*/
+ RSPCheat_r4300iOpcode(RSP_Vector_VGE);
+}
+
+void RSPCompile_Vector_VCL ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Vector_VCL);
+}
+
+void RSPCompile_Vector_VCH ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Vector_VCH);
+}
+
+void RSPCompile_Vector_VCR ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Vector_VCR);
+}
+
+void RSPCompile_Vector_VMRG ( void ) {
+
+ int32_t count, el, del;
+
+ #ifndef RSPCompileVmrg
+ RSPCheat_r4300iOpcode(RSP_Vector_VMRG); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ RSPMoveVariableToX86reg(&RSP_Flags[1].UW, x86_EDX);
+
+ for (count = 0;count < 8; count++) {
+ el = Indx[RSPOpC.rs].UB[count];
+ del = EleSpec[RSPOpC.rs].UB[el];
+ CPU_Message( count);
+
+
+ RSPMoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], x86_EAX);
+
+ RSPMoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+
+ RSPTestConstToX86Reg(1 << (7 - el), x86_EDX);
+ RSPCondMoveNotEqual(x86_ECX, x86_EAX);
+ RSPCondMoveEqual(x86_ECX, x86_EBX);
+
+
+ RSPMoveX86regHalfToVariable(x86_ECX, &RSP_Vect[RSPOpC.sa].HW[el]);
+ }
+}
+
+int32_t RSPCompile_Vector_VAND_MMX ( void ) {
+
+
+ /* Do our MMX checks here */
+ if (IsMmxEnabled == 0)
+ return 0;
+ if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == 0)
+ return 0;
+
+
+ RSPMmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0]);
+
+ RSPMmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4]);
+
+ if ((RSPOpC.rs & 0xF) >= 8) {
+ RSP_Element2Mmx(x86_MM2);
+ RSPMmxPandRegToReg(x86_MM0, x86_MM2);
+ RSPMmxPandRegToReg(x86_MM1, x86_MM2);
+ } else if ((RSPOpC.rs & 0xF) < 2) {
+
+ RSPMmxPandVariableToReg(&RSP_Vect[RSPOpC.rt].HW[0], x86_MM0);
+
+ RSPMmxPandVariableToReg(&RSP_Vect[RSPOpC.rt].HW[4], x86_MM1);
+ } else {
+ RSP_MultiElement2Mmx(x86_MM2, x86_MM3);
+ RSPMmxPandRegToReg(x86_MM0, x86_MM2);
+ RSPMmxPandRegToReg(x86_MM1, x86_MM3);
+ }
+
+
+ RSPMmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0]);
+
+ RSPMmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4]);
+
+ if (IsNextInstructionMmx(RSPCompilePC) == 0)
+ RSPMmxEmptyMultimediaState();
+
+ return 1;
+}
+
+void RSPCompile_Vector_VAND ( void ) {
+
+ int32_t el, del, count;
+ int32_t bElement = ((RSPOpC.rs & 0x0f) >= 8) ? 1 : 0;
+ int32_t bWriteToAccum = WriteToAccum(Low16BitAccum, RSPCompilePC);
+
+ #ifndef RSPCompileVand
+ RSPCheat_r4300iOpcode(RSP_Vector_VAND); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (bWriteToAccum == 0) {
+ if (1 == RSPCompile_Vector_VAND_MMX())
+ return;
+ }
+
+ if (bElement == 1) {
+ del = (RSPOpC.rs & 0x07) ^ 7;
+
+ RSPMoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ for (count = 0; count < 8; count++) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ CPU_Message( count);
+
+
+ RSPMoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], x86_EAX);
+
+ if (bElement == 0) {
+
+ RSPAndVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EAX);
+ } else {
+ RSPAndX86RegHalfToX86RegHalf(x86_EAX, x86_EBX);
+ }
+
+
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el]);
+
+ if (bWriteToAccum != 0) {
+
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1]);
+ }
+ }
+}
+
+void RSPCompile_Vector_VNAND ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Vector_VNAND);
+}
+
+int32_t RSPCompile_Vector_VOR_MMX ( void ) {
+
+
+ /* Do our MMX checks here */
+ if (IsMmxEnabled == 0)
+ return 0;
+ if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == 0)
+ return 0;
+
+
+ RSPMmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0]);
+
+ RSPMmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4]);
+
+ if ((RSPOpC.rs & 0xF) >= 8) {
+ RSP_Element2Mmx(x86_MM2);
+ RSPMmxPorRegToReg(x86_MM0, x86_MM2);
+ RSPMmxPorRegToReg(x86_MM1, x86_MM2);
+ } else if ((RSPOpC.rs & 0xF) < 2) {
+
+ RSPMmxPorVariableToReg(&RSP_Vect[RSPOpC.rt].HW[0], x86_MM0);
+
+ RSPMmxPorVariableToReg(&RSP_Vect[RSPOpC.rt].HW[4], x86_MM1);
+ } else {
+ RSP_MultiElement2Mmx(x86_MM2, x86_MM3);
+ RSPMmxPorRegToReg(x86_MM0, x86_MM2);
+ RSPMmxPorRegToReg(x86_MM1, x86_MM3);
+ }
+
+
+ RSPMmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0]);
+
+ RSPMmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4]);
+
+ if (IsNextInstructionMmx(RSPCompilePC) == 0)
+ RSPMmxEmptyMultimediaState();
+
+ return 1;
+}
+
+void RSPCompile_Vector_VOR ( void ) {
+
+ int32_t el, del, count;
+ int32_t bElement = ((RSPOpC.rs & 0x0f) >= 8) ? 1 : 0;
+ int32_t bWriteToAccum = WriteToAccum(Low16BitAccum, RSPCompilePC);
+
+ #ifndef RSPCompileVor
+ RSPCheat_r4300iOpcode(RSP_Vector_VOR); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (bWriteToAccum == 0) {
+ if (1 == RSPCompile_Vector_VOR_MMX())
+ return;
+ }
+
+ if (bElement == 1) {
+ del = (RSPOpC.rs & 0x07) ^ 7;
+
+ RSPMoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EBX);
+ }
+
+ for (count = 0; count < 8; count++) {
+ el = Indx[RSPOpC.rs].B[count];
+ del = EleSpec[RSPOpC.rs].B[el];
+
+ CPU_Message( count);
+
+
+ RSPMoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], x86_EAX);
+
+ if (bElement == 0) {
+
+ RSPOrVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], x86_EAX);
+ } else {
+ RSPOrX86RegToX86Reg(x86_EAX, x86_EBX);
+ }
+
+ if (bWriteToAccum == 1) {
+
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1]);
+ }
+
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el]);
+ }
+}
+
+void RSPCompile_Vector_VNOR ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Vector_VNOR);
+}
+
+int32_t RSPCompile_Vector_VXOR_MMX ( void ) {
+
+
+ /* Do our MMX checks here */
+ if (IsMmxEnabled == 1)
+ return 0;
+ if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == 0)
+ return 0;
+
+ if ((RSPOpC.rs & 0xF) < 2 && (RSPOpC.rd == RSPOpC.rt)) {
+ static uint32_t VXOR_DynaRegCount = 0;
+ RSPMmxXorRegToReg(VXOR_DynaRegCount+1, VXOR_DynaRegCount+1);
+
+
+ RSPMmxMoveQwordRegToVariable(VXOR_DynaRegCount+1, &RSP_Vect[RSPOpC.sa].UHW[0]);
+
+ RSPMmxMoveQwordRegToVariable(VXOR_DynaRegCount+1, &RSP_Vect[RSPOpC.sa].UHW[4]);
+ VXOR_DynaRegCount = (VXOR_DynaRegCount + 1) & 7;
+ } else {
+
+ RSPMmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0]);
+
+ RSPMmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4]);
+
+ if ((RSPOpC.rs & 0xF) >= 8) {
+ RSP_Element2Mmx(x86_MM2);
+ RSPMmxXorRegToReg(x86_MM0, x86_MM2);
+ RSPMmxXorRegToReg(x86_MM1, x86_MM2);
+ } else if ((RSPOpC.rs & 0xF) < 2) {
+
+ RSPMmxMoveQwordVariableToReg(x86_MM2, &RSP_Vect[RSPOpC.rt].HW[0]);
+
+ RSPMmxMoveQwordVariableToReg(x86_MM3, &RSP_Vect[RSPOpC.rt].HW[4]);
+
+ RSPMmxXorRegToReg(x86_MM0, x86_MM2);
+ RSPMmxXorRegToReg(x86_MM1, x86_MM3);
+ } else {
+ RSP_MultiElement2Mmx(x86_MM2, x86_MM3);
+ RSPMmxXorRegToReg(x86_MM0, x86_MM2);
+ RSPMmxXorRegToReg(x86_MM1, x86_MM3);
+ }
+
+
+ RSPMmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0]);
+
+ RSPMmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4]);
+ }
+
+ if (IsNextInstructionMmx(RSPCompilePC) == 0)
+ RSPMmxEmptyMultimediaState();
+
+ return 1;
+}
+
+void RSPCompile_Vector_VXOR ( void ) {
+ #ifdef RSPCompileVxor
+
+ uint32_t count;
+ int32_t bWriteToAccum = WriteToAccum(Low16BitAccum, RSPCompilePC);
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (!bWriteToAccum || ((RSPOpC.rs & 0xF) < 2 && RSPOpC.rd == RSPOpC.rt)) {
+ if (1 == RSPCompile_Vector_VXOR_MMX()) {
+ if (bWriteToAccum == 1) {
+ RSPXorX86RegToX86Reg(x86_EAX, x86_EAX);
+ for (count = 0; count < 8; count++) {
+
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[count].HW[1]);
+ }
+ }
+ return;
+ }
+ }
+ #endif
+
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Vector_VXOR);
+}
+
+void RSPCompile_Vector_VNXOR ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Vector_VNXOR);
+}
+
+void RSPCompile_Vector_VRCP ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Vector_VRCP);
+}
+
+void RSPCompile_Vector_VRCPL ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Vector_VRCPL);
+}
+
+void RSPCompile_Vector_VRCPH ( void ) {
+
+ int32_t count, el, last = -1;
+ int32_t bWriteToAccum = WriteToAccum(Low16BitAccum, RSPCompilePC);
+
+ #ifndef RSPCompileVrcph
+ RSPCheat_r4300iOpcode(RSP_Vector_VRCPH); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ el = EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)];
+
+ RSPMoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].UHW[el], x86_EDX);
+ RSPMoveX86regHalfToVariable(x86_EDX, &Recp.UHW[1]);
+
+ RSPMoveConstHalfToVariable(0, &Recp.UHW[0]);
+
+ RSPMoveVariableToX86regHalf(&RecpResult.UHW[1], x86_ECX);
+ el = 7 - (RSPOpC.rd & 0x7);
+
+ RSPMoveX86regHalfToVariable(x86_ECX, &RSP_Vect[RSPOpC.sa].UHW[el]);
+
+ if (bWriteToAccum == 0) return;
+
+ for (count = 0; count < 8; count++) {
+ el = EleSpec[RSPOpC.rs].B[count];
+
+ if (el != last) {
+
+ RSPMoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].UHW[el], x86_EAX);
+ last = el;
+ }
+
+
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[count].HW[1]);
+ }
+}
+
+void RSPCompile_Vector_VMOV ( void ) {
+
+ int32_t el;
+
+ #ifndef RSPCompileVmov
+ RSPCheat_r4300iOpcode(RSP_Vector_VMOV); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ el = EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)];
+
+
+ RSPMoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].UHW[el], x86_ECX);
+
+ el = 7 - (RSPOpC.rd & 0x7);
+
+
+ RSPMoveX86regHalfToVariable(x86_ECX, &RSP_Vect[RSPOpC.sa].UHW[el]);
+}
+
+void RSPCompile_Vector_VRSQ ( void ) {
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Vector_VRSQ);
+}
+
+void RSPCompile_Vector_VRSQL ( void ) {
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Vector_VRSQL);
+}
+
+void RSPCompile_Vector_VRSQH ( void ) {
+
+ int32_t count, el;
+
+ #ifndef RSPCompileVrsqh
+ RSPCheat_r4300iOpcode(RSP_Vector_VRSQH); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ el = EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)];
+
+ RSPMoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].UHW[el], x86_EDX);
+ RSPMoveX86regHalfToVariable(x86_EDX, &SQroot.UHW[1]);
+
+ RSPMoveVariableToX86regHalf(&SQrootResult.UHW[1], x86_ECX);
+ el = 7 - (RSPOpC.rd & 0x7);
+
+ RSPMoveX86regHalfToVariable(x86_ECX, &RSP_Vect[RSPOpC.sa].UHW[el]);
+
+ for (count = 0; count < 8; count++) {
+ el = EleSpec[RSPOpC.rs].B[count];
+
+ RSPMoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].UHW[el], x86_EAX);
+
+
+ RSPMoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[count].HW[1]);
+ }
+}
+
+void RSPCompile_Vector_VNOOP ( void ) {
+
+}
+
+/************************** lc2 functions **************************/
+
+void RSPCompile_Opcode_LBV ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Opcode_LBV);
+}
+
+void RSPCompile_Opcode_LSV ( void ) {
+
+ int32_t offset = (RSPOpC.voffset << 1);
+
+ if (RSPOpC.del > 14) {
+ rsp_UnknownOpcode();
+ return;
+ }
+
+ #ifndef RSPCompileLsv
+ RSPCheat_r4300iOpcode(RSP_Opcode_LSV); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (IsRegConst(RSPOpC.base) == 1) {
+ uint32_t Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff;
+
+ if ((Addr & 1) != 0) {
+
+ RSPMoveVariableToX86regByte(DMEM + ((Addr + 0) ^ 3), x86_ECX);
+
+ RSPMoveVariableToX86regByte(DMEM + ((Addr + 1) ^ 3), x86_EDX);
+
+
+ RSPMoveX86regByteToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 0)]);
+
+ RSPMoveX86regByteToVariable(x86_EDX, &RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)]);
+ } else {
+
+ RSPMoveVariableToX86regHalf(DMEM + (Addr ^ 2), x86_EDX);
+
+ RSPMoveX86regHalfToVariable(x86_EDX, &RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)]);
+ }
+ return;
+ }
+
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, x86_EBX);
+ if (offset != 0) RSPAddConstToX86Reg(x86_EBX, offset);
+ RSPAndConstToX86Reg(x86_EBX, 0x0FFF);
+
+ if (Compiler.bAlignVector == 1) {
+ RSPXorConstToX86Reg(x86_EBX, 2);
+ RSPMoveN64MemToX86regHalf(x86_ECX, x86_EBX);
+
+ RSPMoveX86regHalfToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)]);
+ } else {
+ RSPLeaSourceAndOffset(x86_EAX, x86_EBX, 1);
+ RSPXorConstToX86Reg(x86_EBX, 3);
+ RSPXorConstToX86Reg(x86_EAX, 3);
+
+ RSPMoveN64MemToX86regByte(x86_ECX, x86_EBX);
+ RSPMoveN64MemToX86regByte(x86_EDX, x86_EAX);
+
+
+ RSPMoveX86regByteToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 0)]);
+
+
+ RSPMoveX86regByteToVariable(x86_EDX, &RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)]);
+ }
+}
+
+void RSPCompile_Opcode_LLV ( void ) {
+
+ int32_t offset = (RSPOpC.voffset << 2);
+ uint8_t * Jump[2];
+
+ #ifndef RSPCompileLlv
+ RSPCheat_r4300iOpcode(RSP_Opcode_LLV); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if ((RSPOpC.del & 0x3) != 0) {
+ rsp_UnknownOpcode();
+ return;
+ }
+
+ if (IsRegConst(RSPOpC.base) == 1) {
+ uint32_t Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff;
+
+ if ((Addr & 3) != 0) {
+ //CompilerWarning("Unaligned LLV at constant address");
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Opcode_LLV);
+ return;
+ }
+
+
+ RSPMoveVariableToX86reg(DMEM + Addr, x86_EAX);
+
+ RSPMoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4]);
+ return;
+ }
+
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, x86_EBX);
+ if (offset != 0) RSPAddConstToX86Reg(x86_EBX, offset);
+
+ RSPTestConstToX86Reg(3, x86_EBX);
+ RSPJneLabel32( 0);
+ Jump[0] = RSPRecompPos - 4;
+
+ /*
+ * Unaligned
+ */
+ CompilerToggleBuffer();
+
+ CPU_Message(" Unaligned:");
+ *((uint32_t *)(Jump[0]))=(uint32_t)(RSPRecompPos - Jump[0] - 4);
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Opcode_LLV);
+ RSPJmpLabel32( 0);
+ Jump[1] = RSPRecompPos - 4;
+
+ CompilerToggleBuffer();
+
+ /*
+ * Aligned
+ */
+ RSPAndConstToX86Reg(x86_EBX, 0x0fff);
+ RSPMoveN64MemToX86reg(x86_EAX, x86_EBX);
+ /* Because of byte swapping this swizzle works nicely */
+
+ RSPMoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4]);
+
+ CPU_Message(" Done:");
+ *((uint32_t *)(Jump[1]))=(uint32_t)(RSPRecompPos - Jump[1] - 4);
+}
+
+void RSPCompile_Opcode_LDV ( void ) {
+
+ int32_t offset = (RSPOpC.voffset << 3);
+ uint8_t * Jump[2], * LoopEntry;
+ //RSPBreakPoint();
+
+ #ifndef RSPCompileLdv
+ RSPCheat_r4300iOpcode(RSP_Opcode_LDV); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ /* FIXME: Conker's hits this */
+ //if ((RSPOpC.del & 0x7) != 0) {
+ // rsp_UnknownOpcode();
+ // return;
+ //}
+
+ if (IsRegConst(RSPOpC.base) == 1) {
+ uint32_t Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff;
+
+ if ((Addr & 3) != 0) {
+ CompilerWarning( RSPCompilePC);
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Opcode_LDV);
+ return;
+ }
+
+
+ RSPMoveVariableToX86reg(DMEM + Addr + 0, x86_EAX);
+
+ RSPMoveVariableToX86reg(DMEM + Addr + 4, x86_ECX);
+
+
+ RSPMoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4]);
+
+ RSPMoveX86regToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 8]);
+ return;
+ }
+
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, x86_EBX);
+ if (offset != 0) {
+ RSPAddConstToX86Reg(x86_EBX, offset);
+ }
+ RSPAndConstToX86Reg(x86_EBX, 0x0fff);
+ RSPTestConstToX86Reg(3, x86_EBX);
+ RSPJneLabel32( 0);
+ Jump[0] = RSPRecompPos - 4;
+
+ CompilerToggleBuffer();
+ CPU_Message(" Unaligned:");
+ RSPx86_SetBranch32b(Jump[0], RSPRecompPos);
+
+ RSPMoveConstQwordToX86reg((uintptr_t)&RSP_Vect[RSPOpC.rt].UB[15 - RSPOpC.del], x86_RDI);
+ RSPMoveConstToX86reg(8, x86_ECX);
+
+/* mov eax, ebx
+ dec edi
+ xor eax, 3h
+ inc ebx
+ mov dl, byte ptr [eax+Dmem]
+ dec ecx
+ mov byte ptr [edi+1], dl
+ jne $Loop */
+
+ LoopEntry = RSPRecompPos;
+ CPU_Message(" Loop:");
+ RSPMoveX86RegToX86Reg(x86_EBX, x86_EAX);
+ RSPXorConstToX86Reg(x86_EAX, 3);
+ RSPMoveN64MemToX86regByte(x86_EDX, x86_EAX);
+ RSPMoveX86regByteToX86regPointer(x86_EDX, x86_EDI);
+ RSPIncX86reg(x86_EBX); /* address constant */
+ RSPDecX86reg(x86_RDI); /* vector pointer */
+ RSPDecX86reg(x86_ECX); /* counter */
+ RSPJneLabel8( 0);
+ RSPx86_SetBranch8b(RSPRecompPos - 1, LoopEntry);
+
+ RSPJmpLabel32( 0);
+ Jump[1] = RSPRecompPos - 4;
+ CompilerToggleBuffer();
+
+ RSPMoveN64MemToX86reg(x86_EAX, x86_EBX);
+ RSPMoveN64MemDispToX86reg(x86_ECX, x86_EBX, 4);
+
+ /* Because of byte swapping this swizzle works nicely */
+
+ RSPMoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4]);
+
+ RSPMoveX86regToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 8]);
+
+ CPU_Message(" Done:");
+ RSPx86_SetBranch32b(Jump[1], RSPRecompPos);
+}
+
+void RSPCompile_Opcode_LQV ( void ) {
+
+ int32_t offset = (RSPOpC.voffset << 4);
+ uint8_t * Jump[2], * Jump3;
+
+ #ifndef RSPCompileLqv
+ RSPCheat_r4300iOpcode(RSP_Opcode_LQV); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (RSPOpC.del != 0) {
+ rsp_UnknownOpcode();
+ return;
+ }
+
+ if (IsRegConst(RSPOpC.base) == 1) {
+ uint32_t Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff;
+
+ if (Addr & 15) {
+ CompilerWarning( RSPCompilePC);
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Opcode_LQV);
+ return;
+ }
+
+ /*
+ * Aligned store
+ */
+
+ if (IsSseEnabled == 0) {
+
+ RSPMoveVariableToX86reg(DMEM + Addr + 0, x86_EAX);
+
+ RSPMoveVariableToX86reg(DMEM + Addr + 4, x86_EBX);
+
+ RSPMoveVariableToX86reg(DMEM + Addr + 8, x86_ECX);
+
+ RSPMoveVariableToX86reg(DMEM + Addr + 12, x86_EDX);
+
+
+ RSPMoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.rt].B[12]);
+
+ RSPMoveX86regToVariable(x86_EBX, &RSP_Vect[RSPOpC.rt].B[8]);
+
+ RSPMoveX86regToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[4]);
+
+ RSPMoveX86regToVariable(x86_EDX, &RSP_Vect[RSPOpC.rt].B[0]);
+ } else {
+
+ RSPSseMoveUnalignedVariableToReg(DMEM + Addr, x86_XMM0);
+ RSPSseShuffleReg(x86_XMM0, x86_MM0, 0x1b);
+
+ RSPSseMoveAlignedRegToVariable(x86_XMM0, &RSP_Vect[RSPOpC.rt].B[0]);
+ }
+ return;
+ }
+
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, x86_EBX);
+ if (offset != 0) {
+ RSPAddConstToX86Reg(x86_EBX, offset);
+ }
+/*
+ //RSPBreakPoint();
+ RSPTestConstToX86Reg(15, x86_EBX);
+ RSPJeLabel32( 0);
+ Jump3 = RSPRecompPos - 4;
+
+ RSPBreakPoint();
+ RSPx86_SetBranch32b((uint32_t*)Jump3, (uint32_t*)RSPRecompPos);
+
+ RSPTestConstToX86Reg(15, x86_EBX);
+ RSPJneLabel32( 0);
+ Jump[0] = RSPRecompPos - 4;
+*/
+
+#define RSetJump32(Loc,JumpLoc) *(uint32_t *)(Loc)= (uint32_t)(((uint64_t)(JumpLoc)) - (((uint64_t)(Loc)) + 4));
+
+ RSPTestConstToX86Reg(15, x86_EBX);
+ RSPJeLabel32( 0);
+ Jump3 = RSPRecompPos - 4;
+// RSPBreakPoint();
+ //Int3();
+ RSPJmpLabel32( 0);
+ Jump[0] = RSPRecompPos - 4;
+ RSPx86_SetBranch32b((uint32_t*)Jump3, (uint32_t*)RSPRecompPos);
+
+ // 000000440000150E E9 15 EE FF FF jmp 0000004400000328
+ CompilerToggleBuffer();
+ CPU_Message(" Unaligned:");
+ //if(RSPRecompPos == 0x0000004400000328)
+ //Int3();
+// RSPx86_SetBranch32b(Jump[0], RSPRecompPos);
+//void RSPx86_SetBranch32b(void * JumpByte, void * Destination) {
+// *(uint32_t*)(JumpByte) = (uint32_t)((uint8_t*)Destination - (uint8_t*)((uint32_t*)JumpByte + 1));
+//}
+ //*(uint32_t*)(Jump[0]) = (uint32_t)((uint8_t*)RSPRecompPos - (uint8_t*)((Jump[0]) + 1));
+ RSetJump32(Jump[0], RSPRecompPos);
+
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Opcode_LQV);
+ RSPJmpLabel32( 0);
+ Jump[1] = RSPRecompPos - 4;
+ CompilerToggleBuffer();
+
+ RSPAndConstToX86Reg(x86_EBX, 0x0fff);
+ if (IsSseEnabled == 0) {
+ RSPMoveN64MemDispToX86reg(x86_EAX, x86_EBX, 0);
+ RSPMoveN64MemDispToX86reg(x86_ECX, x86_EBX, 4);
+ RSPMoveN64MemDispToX86reg(x86_EDX, x86_EBX, 8);
+ RSPMoveN64MemDispToX86reg(x86_EDI, x86_EBX, 12);
+
+
+ RSPMoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.rt].B[12]);
+
+ RSPMoveX86regToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[8]);
+
+ RSPMoveX86regToVariable(x86_EDX, &RSP_Vect[RSPOpC.rt].B[4]);
+
+ RSPMoveX86regToVariable(x86_EDI, &RSP_Vect[RSPOpC.rt].B[0]);
+ } else {
+ RSPSseMoveUnalignedN64MemToReg(x86_XMM0, x86_EBX);
+ RSPSseShuffleReg(x86_XMM0, x86_MM0, 0x1b);
+
+ RSPSseMoveAlignedRegToVariable(x86_XMM0, &RSP_Vect[RSPOpC.rt].B[0]);
+ }
+ CPU_Message(" Done:");
+ RSPx86_SetBranch32b((uint32_t*)Jump[1], (uint32_t*)RSPRecompPos);
+}
+
+void RSPCompile_Opcode_LRV ( void ) {
+ int32_t offset = (RSPOpC.voffset << 4);
+ uint8_t * Loop, * Jump[2];
+
+ #ifndef RSPCompileLrv
+ RSPCheat_r4300iOpcode(RSP_Opcode_LRV); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (RSPOpC.del != 0) {
+ rsp_UnknownOpcode();
+ return;
+ }
+
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, x86_EBX);
+ if (offset != 0) RSPAddConstToX86Reg(x86_EBX, offset);
+
+ if (Compiler.bAlignVector == 0) {
+ RSPTestConstToX86Reg(1, x86_EBX);
+ RSPJneLabel32( 0);
+ Jump[0] = RSPRecompPos - 4;
+
+ /* Unaligned */
+ CompilerToggleBuffer();
+
+ CPU_Message(" Unaligned:");
+ RSPx86_SetBranch32b(Jump[0], RSPRecompPos);
+
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Opcode_LRV);
+ RSPJmpLabel32( 0);
+ Jump[1] = RSPRecompPos - 4;
+
+ CompilerToggleBuffer();
+ }
+
+// RSPBreakPoint();
+
+ /* Aligned */
+ RSPMoveX86RegToX86Reg(x86_EBX, x86_EAX);
+ RSPAndConstToX86Reg(x86_EAX, 0x0F);
+ RSPAndConstToX86Reg(x86_EBX, 0x0ff0);
+
+ RSPMoveX86RegToX86Reg(x86_EAX, x86_ECX);
+ RSPShiftRightUnsignImmed(x86_ECX, 1);
+
+ RSPJeLabel8( 0);
+ Jump[0] = RSPRecompPos - 1;
+/*
+ RSPDecX86reg(x86_EAX);
+ RSPLeaSourceAndOffset(x86_EAX, x86_EAX, (uint32_t) &RSP_Vect[RSPOpC.rt].B[0]);
+ RSPDecX86reg(x86_EAX);
+*/
+
+// RSPBreakPoint();
+//Int3();
+ RSPAddQwordToX86Reg(x86_RAX, ((uintptr_t)&RSP_Vect[RSPOpC.rt].UB[0]) - 2);
+
+ CPU_Message(" Loop:");
+ Loop = RSPRecompPos;
+
+ RSPMoveX86RegToX86Reg(x86_EBX, x86_ESI);
+ RSPXorConstToX86Reg(x86_ESI, 2);
+ RSPMoveN64MemToX86regHalf(x86_EDX, x86_ESI);
+ RSPMoveX86regHalfToX86regPointer(x86_EDX, x86_RAX);
+
+ RSPAddConstToX86Reg(x86_EBX, 2); /* Dmem pointer */
+ RSPSubConstFromX86Reg(x86_RAX, 2); /* Vector pointer */
+ RSPDecX86reg(x86_ECX); /* Loop counter */
+ RSPJneLabel8( 0);
+ RSPx86_SetBranch8b(RSPRecompPos - 1, Loop);
+
+ if (Compiler.bAlignVector == 0) {
+ CPU_Message(" Done:");
+ RSPx86_SetBranch32b((uint32_t*)Jump[1], (uint32_t*)RSPRecompPos);
+ }
+
+ RSPx86_SetBranch8b(Jump[0], RSPRecompPos);
+}
+
+void RSPCompile_Opcode_LPV ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Opcode_LPV);
+}
+
+void RSPCompile_Opcode_LUV ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Opcode_LUV);
+}
+
+
+void RSPCompile_Opcode_LHV ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Opcode_LHV);
+}
+
+
+void RSPCompile_Opcode_LFV ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Opcode_LFV);
+}
+
+void RSPCompile_Opcode_LTV ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Opcode_LTV);
+}
+
+/************************** sc2 functions **************************/
+
+void RSPCompile_Opcode_SBV ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Opcode_SBV);
+}
+
+void RSPCompile_Opcode_SSV ( void ) {
+
+ int32_t offset = (RSPOpC.voffset << 1);
+
+ if (RSPOpC.del > 14) {
+ rsp_UnknownOpcode();
+ return;
+ }
+
+ #ifndef RSPCompileSsv
+ RSPCheat_r4300iOpcode(RSP_Opcode_SSV); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (IsRegConst(RSPOpC.base) == 1) {
+ uint32_t Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff;
+
+ if ((Addr & 1) != 0) {
+
+ RSPMoveVariableToX86regByte(&RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 0)], x86_ECX);
+
+ RSPMoveVariableToX86regByte(&RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)], x86_EDX);
+
+
+ RSPMoveX86regByteToVariable(x86_ECX, DMEM + ((Addr + 0) ^ 3));
+
+ RSPMoveX86regByteToVariable(x86_EDX, DMEM + ((Addr + 1) ^ 3));
+ } else {
+
+ RSPMoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)], x86_ECX);
+
+ RSPMoveX86regHalfToVariable(x86_ECX, DMEM + (Addr ^ 2));
+ }
+ return;
+ }
+
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, x86_EBX);
+ if (offset != 0) RSPAddConstToX86Reg(x86_EBX, offset);
+ RSPAndConstToX86Reg(x86_EBX, 0x0FFF);
+
+ if (Compiler.bAlignVector == 1) {
+
+ RSPMoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)], x86_ECX);
+ RSPXorConstToX86Reg(x86_EBX, 2);
+ RSPMoveX86regHalfToN64Mem(x86_ECX, x86_EBX);
+ } else {
+ RSPLeaSourceAndOffset(x86_EAX, x86_EBX, 1);
+ RSPXorConstToX86Reg(x86_EBX, 3);
+ RSPXorConstToX86Reg(x86_EAX, 3);
+
+
+ RSPMoveVariableToX86regByte(&RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 0)], x86_ECX);
+
+ RSPMoveVariableToX86regByte(&RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)], x86_EDX);
+
+ RSPMoveX86regByteToN64Mem(x86_ECX, x86_EBX);
+ RSPMoveX86regByteToN64Mem(x86_EDX, x86_EAX);
+ }
+}
+
+void RSPCompile_Opcode_SLV ( void ) {
+
+ int32_t offset = (RSPOpC.voffset << 2);
+ uint8_t * Jump[2];
+
+ #ifndef RSPCompileSlv
+ RSPCheat_r4300iOpcode(RSP_Opcode_SLV); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+// if ((RSPOpC.del & 0x3) != 0) {
+// rsp_UnknownOpcode();
+// return;
+// }
+
+ if (IsRegConst(RSPOpC.base) == 1) {
+ uint32_t Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff;
+
+ if ((Addr & 3) != 0) {
+ //CompilerWarning("Unaligned SLV at constant address");
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Opcode_SLV);
+ return;
+ }
+
+
+ RSPMoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4], x86_EAX);
+
+ RSPMoveX86regToVariable(x86_EAX, DMEM + Addr);
+ return;
+ }
+
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, x86_EBX);
+ if (offset != 0) RSPAddConstToX86Reg(x86_EBX, offset);
+
+ RSPTestConstToX86Reg(3, x86_EBX);
+ RSPJneLabel32( 0);
+ Jump[0] = RSPRecompPos - 4;
+
+ /*
+ * Unaligned
+ */
+ CompilerToggleBuffer();
+
+ CPU_Message(" Unaligned:");
+ *((uint32_t *)(Jump[0]))=(uint32_t)(RSPRecompPos - Jump[0] - 4);
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Opcode_SLV);
+ RSPJmpLabel32( 0);
+ Jump[1] = RSPRecompPos - 4;
+
+ CompilerToggleBuffer();
+
+ /*
+ * Aligned
+ */
+
+ /* Because of byte swapping this swizzle works nicely */
+
+ RSPMoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4], x86_EAX);
+
+ RSPAndConstToX86Reg(x86_EBX, 0x0fff);
+ RSPMoveX86regToN64Mem(x86_EAX, x86_EBX);
+
+ CPU_Message(" Done:");
+ *((uint32_t *)(Jump[1]))=(uint32_t)(RSPRecompPos - Jump[1] - 4);
+}
+
+void RSPCompile_Opcode_SDV ( void ) {
+
+ int32_t offset = (RSPOpC.voffset << 3);
+ uint8_t * Jump[2], * LoopEntry;
+
+ //if ((RSPOpC.del & 0x7) != 0) {
+ // rsp_UnknownOpcode();
+ // return;
+ //}
+
+ #ifndef RSPCompileSdv
+ RSPCheat_r4300iOpcode(RSP_Opcode_SDV); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (IsRegConst(RSPOpC.base) == 1) {
+ uint32_t Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff;
+
+ if ((Addr & 3) != 0) {
+ CompilerWarning( RSPCompilePC);
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Opcode_SDV);
+ return;
+ }
+
+
+ RSPMoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4], x86_EAX);
+
+ RSPMoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 8], x86_EBX);
+
+
+ RSPMoveX86regToVariable(x86_EAX, DMEM + Addr);
+
+ RSPMoveX86regToVariable(x86_EBX, DMEM + Addr + 4);
+ return;
+ }
+
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, x86_EBX);
+ if (offset != 0) {
+ RSPAddConstToX86Reg(x86_EBX, offset);
+ }
+ RSPAndConstToX86Reg(x86_EBX, 0x0fff);
+ RSPTestConstToX86Reg(3, x86_EBX);
+ RSPJneLabel32( 0);
+ Jump[0] = RSPRecompPos - 4;
+
+ CompilerToggleBuffer();
+ CPU_Message(" Unaligned:");
+ RSPx86_SetBranch32b((uint32_t*)Jump[0], (uint32_t*)RSPRecompPos);
+
+
+ RSPMoveConstQwordToX86reg((uintptr_t)&RSP_Vect[RSPOpC.rt].UB[15 - RSPOpC.del], x86_RDI);
+ RSPMoveConstToX86reg(8, x86_ECX);
+
+ CPU_Message(" Loop:");
+ LoopEntry = RSPRecompPos;
+ RSPMoveX86RegToX86Reg(x86_EBX, x86_EAX);
+ RSPXorConstToX86Reg(x86_EAX, 3);
+ RSPMoveX86regPointerToX86regByte(x86_EDX, x86_EDI);
+ RSPMoveX86regByteToN64Mem(x86_EDX, x86_EAX);
+ RSPIncX86reg(x86_EBX); /* address constant */
+ RSPDecX86reg(x86_RDI); /* vector pointer */
+ RSPDecX86reg(x86_ECX); /* counter */
+ RSPJneLabel8( 0);
+ RSPx86_SetBranch8b(RSPRecompPos - 1, LoopEntry);
+
+ RSPJmpLabel32( 0);
+ Jump[1] = RSPRecompPos - 4;
+ CompilerToggleBuffer();
+
+
+ RSPMoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4], x86_EAX);
+
+ RSPMoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 8], x86_ECX);
+ RSPMoveX86regToN64Mem(x86_EAX, x86_EBX);
+ RSPMoveX86regToN64MemDisp(x86_ECX, x86_EBX, 4);
+
+ CPU_Message(" Done:");
+ RSPx86_SetBranch32b((uint32_t*)Jump[1], (uint32_t*)RSPRecompPos);
+}
+
+void RSPCompile_Opcode_SQV ( void ) {
+
+ int32_t offset = (RSPOpC.voffset << 4);
+ uint8_t * Jump[2];
+
+ #ifndef RSPCompileSqv
+ RSPCheat_r4300iOpcode(RSP_Opcode_SQV); return;
+ #endif
+
+ CPU_Message(RSPCompilePC,RSPOpcodeName(RSPOpC.Hex,RSPCompilePC));
+
+ if (RSPOpC.del != 0) {
+ rsp_UnknownOpcode();
+ return;
+ }
+
+ if (IsRegConst(RSPOpC.base) == 1) {
+ uint32_t Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff;
+
+ if (Addr & 15) {
+ CompilerWarning( RSPCompilePC);
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Opcode_SQV);
+ return;
+ }
+
+ /*
+ * Aligned store
+ */
+
+ if (IsSseEnabled == 0) {
+
+ RSPMoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[12], x86_EAX);
+
+ RSPMoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[8], x86_EBX);
+
+ RSPMoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[4], x86_ECX);
+
+ RSPMoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[0], x86_EDX);
+
+
+ RSPMoveX86regToVariable(x86_EAX, DMEM + Addr + 0);
+
+ RSPMoveX86regToVariable(x86_EBX, DMEM + Addr + 4);
+
+ RSPMoveX86regToVariable(x86_ECX, DMEM + Addr + 8);
+
+ RSPMoveX86regToVariable(x86_EDX, DMEM + Addr + 12);
+ } else {
+
+ RSPSseMoveAlignedVariableToReg(&RSP_Vect[RSPOpC.rt].B[0], x86_XMM0);
+ RSPSseShuffleReg(x86_XMM0, x86_MM0, 0x1b);
+
+ RSPSseMoveUnalignedRegToVariable(x86_XMM0, DMEM + Addr);
+ }
+ return;
+ }
+
+ RSPMoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, x86_EBX);
+ if (offset != 0) {
+ RSPAddConstToX86Reg(x86_EBX, offset);
+ }
+ RSPTestConstToX86Reg(15, x86_EBX);
+ RSPJneLabel32( 0);
+ Jump[0] = RSPRecompPos - 4;
+
+ CompilerToggleBuffer();
+ CPU_Message(" Unaligned:");
+ RSPx86_SetBranch32b((uint32_t*)Jump[0], (uint32_t*)RSPRecompPos);
+ RSPCheat_r4300iOpcodeNoMessage(RSP_Opcode_SQV);
+ RSPJmpLabel32( 0);
+ Jump[1] = RSPRecompPos - 4;
+ CompilerToggleBuffer();
+
+ RSPAndConstToX86Reg(x86_EBX, 0x0fff);
+ if (IsSseEnabled == 0) {
+
+ RSPMoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[12], x86_EAX);
+
+ RSPMoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[8], x86_ECX);
+
+ RSPMoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[4], x86_EDX);
+
+ RSPMoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[0], x86_EDI);
+
+ RSPMoveX86regToN64MemDisp(x86_EAX, x86_EBX, 0);
+ RSPMoveX86regToN64MemDisp(x86_ECX, x86_EBX, 4);
+ RSPMoveX86regToN64MemDisp(x86_EDX, x86_EBX, 8);
+ RSPMoveX86regToN64MemDisp(x86_EDI, x86_EBX, 12);
+ } else {
+
+ RSPSseMoveAlignedVariableToReg(&RSP_Vect[RSPOpC.rt].B[0], x86_XMM0);
+ RSPSseShuffleReg(x86_XMM0, x86_MM0, 0x1b);
+ RSPSseMoveUnalignedRegToN64Mem(x86_XMM0, x86_EBX);
+ }
+ CPU_Message(" Done:");
+ RSPx86_SetBranch32b((uint32_t*)Jump[1], (uint32_t*)RSPRecompPos);
+}
+
+void RSPCompile_Opcode_SRV ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Opcode_SRV);
+}
+
+void RSPCompile_Opcode_SPV ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Opcode_SPV);
+}
+
+void RSPCompile_Opcode_SUV ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Opcode_SUV);
+}
+
+void RSPCompile_Opcode_SHV ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Opcode_SHV);
+}
+
+void RSPCompile_Opcode_SFV ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Opcode_SFV);
+}
+
+void RSPCompile_Opcode_STV ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Opcode_STV);
+}
+
+void RSPCompile_Opcode_SWV ( void ) {
+ RSPCheat_r4300iOpcode(RSP_Opcode_SWV);
+}
+
+/************************** Other functions **************************/
+
+void RSPCompile_UnknownOpcode (void) {
+ CPU_Message(RSPCompilePC, RSPOpcodeName(RSPOpC.Hex,RSPCompilePC) );
+ RSPNextInstruction = FINISH_BLOCK;
+ RSPMoveConstToVariable(RSPCompilePC,PrgCount);
+ RSPMoveConstToVariable(RSPOpC.Hex,&RSPOpC.Hex);
+ RSPCall_Direct(rsp_UnknownOpcode );
+ RSPRet();
+}
diff --git a/src/usf/rsp_recompiler_ops.h b/src/usf/rsp_recompiler_ops.h new file mode 100644 index 0000000..c13311a --- /dev/null +++ b/src/usf/rsp_recompiler_ops.h @@ -0,0 +1,158 @@ +/*
+ * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator).
+ *
+ * (c) Copyright 2001 jabo (jabo@emulation64.com) and
+ * zilmar (zilmar@emulation64.com)
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+
+/************************* OpCode functions *************************/
+void RSPCompile_SPECIAL ( void );
+void RSPCompile_REGIMM ( void );
+void RSPCompile_J ( void );
+void RSPCompile_JAL ( void );
+void RSPCompile_BEQ ( void );
+void RSPCompile_BNE ( void );
+void RSPCompile_BLEZ ( void );
+void RSPCompile_BGTZ ( void );
+void RSPCompile_ADDI ( void );
+void RSPCompile_ADDIU ( void );
+void RSPCompile_SLTI ( void );
+void RSPCompile_SLTIU ( void );
+void RSPCompile_ANDI ( void );
+void RSPCompile_ORI ( void );
+void RSPCompile_XORI ( void );
+void RSPCompile_LUI ( void );
+void RSPCompile_COP0 ( void );
+void RSPCompile_COP2 ( void );
+void RSPCompile_LB ( void );
+void RSPCompile_LH ( void );
+void RSPCompile_LW ( void );
+void RSPCompile_LBU ( void );
+void RSPCompile_LHU ( void );
+void RSPCompile_SB ( void );
+void RSPCompile_SH ( void );
+void RSPCompile_SW ( void );
+void RSPCompile_LC2 ( void );
+void RSPCompile_SC2 ( void );
+/********************** R4300i OpCodes: Special **********************/
+void RSPCompile_Special_SLL ( void );
+void RSPCompile_Special_SRL ( void );
+void RSPCompile_Special_SRA ( void );
+void RSPCompile_Special_SLLV ( void );
+void RSPCompile_Special_SRLV ( void );
+void RSPCompile_Special_SRAV ( void );
+void RSPCompile_Special_JR ( void );
+void RSPCompile_Special_JALR ( void );
+void RSPCompile_Special_BREAK ( void );
+void RSPCompile_Special_ADD ( void );
+void RSPCompile_Special_ADDU ( void );
+void RSPCompile_Special_SUB ( void );
+void RSPCompile_Special_SUBU ( void );
+void RSPCompile_Special_AND ( void );
+void RSPCompile_Special_OR ( void );
+void RSPCompile_Special_XOR ( void );
+void RSPCompile_Special_NOR ( void );
+void RSPCompile_Special_SLT ( void );
+void RSPCompile_Special_SLTU ( void );
+/********************** R4300i OpCodes: RegImm **********************/
+void RSPCompile_RegImm_BLTZ ( void );
+void RSPCompile_RegImm_BGEZ ( void );
+void RSPCompile_RegImm_BLTZAL ( void );
+void RSPCompile_RegImm_BGEZAL ( void );
+/************************** Cop0 functions *************************/
+void RSPCompile_Cop0_MF ( void );
+void RSPCompile_Cop0_MT ( void );
+/************************** Cop2 functions *************************/
+void RSPCompile_Cop2_MF ( void );
+void RSPCompile_Cop2_CF ( void );
+void RSPCompile_Cop2_MT ( void );
+void RSPCompile_Cop2_CT ( void );
+void RSPCompile_COP2_VECTOR ( void );
+/************************** Vect functions **************************/
+void RSPCompile_Vector_VMULF ( void );
+void RSPCompile_Vector_VMULU ( void );
+void RSPCompile_Vector_VMUDL ( void );
+void RSPCompile_Vector_VMUDM ( void );
+void RSPCompile_Vector_VMUDN ( void );
+void RSPCompile_Vector_VMUDH ( void );
+void RSPCompile_Vector_VMACF ( void );
+void RSPCompile_Vector_VMACU ( void );
+void RSPCompile_Vector_VMACQ ( void );
+void RSPCompile_Vector_VMADL ( void );
+void RSPCompile_Vector_VMADM ( void );
+void RSPCompile_Vector_VMADN ( void );
+void RSPCompile_Vector_VMADH ( void );
+void RSPCompile_Vector_VADD ( void );
+void RSPCompile_Vector_VSUB ( void );
+void RSPCompile_Vector_VABS ( void );
+void RSPCompile_Vector_VADDC ( void );
+void RSPCompile_Vector_VSUBC ( void );
+void RSPCompile_Vector_VSAW ( void );
+void RSPCompile_Vector_VLT ( void );
+void RSPCompile_Vector_VEQ ( void );
+void RSPCompile_Vector_VNE ( void );
+void RSPCompile_Vector_VGE ( void );
+void RSPCompile_Vector_VCL ( void );
+void RSPCompile_Vector_VCH ( void );
+void RSPCompile_Vector_VCR ( void );
+void RSPCompile_Vector_VMRG ( void );
+void RSPCompile_Vector_VAND ( void );
+void RSPCompile_Vector_VNAND ( void );
+void RSPCompile_Vector_VOR ( void );
+void RSPCompile_Vector_VNOR ( void );
+void RSPCompile_Vector_VXOR ( void );
+void RSPCompile_Vector_VNXOR ( void );
+void RSPCompile_Vector_VRCP ( void );
+void RSPCompile_Vector_VRCPL ( void );
+void RSPCompile_Vector_VRCPH ( void );
+void RSPCompile_Vector_VMOV ( void );
+void RSPCompile_Vector_VRSQ ( void );
+void RSPCompile_Vector_VRSQL ( void );
+void RSPCompile_Vector_VRSQH ( void );
+void RSPCompile_Vector_VNOOP ( void );
+/************************** lc2 functions **************************/
+void RSPCompile_Opcode_LBV ( void );
+void RSPCompile_Opcode_LSV ( void );
+void RSPCompile_Opcode_LLV ( void );
+void RSPCompile_Opcode_LDV ( void );
+void RSPCompile_Opcode_LQV ( void );
+void RSPCompile_Opcode_LRV ( void );
+void RSPCompile_Opcode_LPV ( void );
+void RSPCompile_Opcode_LUV ( void );
+void RSPCompile_Opcode_LHV ( void );
+void RSPCompile_Opcode_LFV ( void );
+void RSPCompile_Opcode_LTV ( void );
+/************************** sc2 functions **************************/
+void RSPCompile_Opcode_SBV ( void );
+void RSPCompile_Opcode_SSV ( void );
+void RSPCompile_Opcode_SLV ( void );
+void RSPCompile_Opcode_SDV ( void );
+void RSPCompile_Opcode_SQV ( void );
+void RSPCompile_Opcode_SRV ( void );
+void RSPCompile_Opcode_SPV ( void );
+void RSPCompile_Opcode_SUV ( void );
+void RSPCompile_Opcode_SHV ( void );
+void RSPCompile_Opcode_SFV ( void );
+void RSPCompile_Opcode_SWV ( void );
+void RSPCompile_Opcode_STV ( void );
+/************************** Other functions **************************/
+void RSPCompile_UnknownOpcode (void);
diff --git a/src/usf/rsp_registers.h b/src/usf/rsp_registers.h new file mode 100644 index 0000000..22fb196 --- /dev/null +++ b/src/usf/rsp_registers.h @@ -0,0 +1,149 @@ +/*
+ * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator).
+ *
+ * (c) Copyright 2001 jabo (jabo@emulation64.com) and
+ * zilmar (zilmar@emulation64.com)
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+
+#include "types.h"
+
+#define SP_STATUS_HALT 0x001 /* Bit 0: halt */
+#define SP_STATUS_BROKE 0x002 /* Bit 1: broke */
+#define SP_STATUS_DMA_BUSY 0x004 /* Bit 2: dma busy */
+#define SP_STATUS_DMA_FULL 0x008 /* Bit 3: dma full */
+#define SP_STATUS_IO_FULL 0x010 /* Bit 4: io full */
+#define SP_STATUS_SSTEP 0x020 /* Bit 5: single step */
+#define SP_STATUS_INTR_BREAK 0x040 /* Bit 6: interrupt on break */
+#define SP_STATUS_SIG0 0x080 /* Bit 7: signal 0 set */
+#define SP_STATUS_SIG1 0x100 /* Bit 8: signal 1 set */
+#define SP_STATUS_SIG2 0x200 /* Bit 9: signal 2 set */
+#define SP_STATUS_SIG3 0x400 /* Bit 10: signal 3 set */
+#define SP_STATUS_SIG4 0x800 /* Bit 11: signal 4 set */
+#define SP_STATUS_SIG5 0x1000 /* Bit 12: signal 5 set */
+#define SP_STATUS_SIG6 0x2000 /* Bit 13: signal 6 set */
+#define SP_STATUS_SIG7 0x4000 /* Bit 14: signal 7 set */
+
+#define SP_CLR_HALT 0x00001 /* Bit 0: clear halt */
+#define SP_SET_HALT 0x00002 /* Bit 1: set halt */
+#define SP_CLR_BROKE 0x00004 /* Bit 2: clear broke */
+#define SP_CLR_INTR 0x00008 /* Bit 3: clear intr */
+#define SP_SET_INTR 0x00010 /* Bit 4: set intr */
+#define SP_CLR_SSTEP 0x00020 /* Bit 5: clear sstep */
+#define SP_SET_SSTEP 0x00040 /* Bit 6: set sstep */
+#define SP_CLR_INTR_BREAK 0x00080 /* Bit 7: clear intr on break */
+#define SP_SET_INTR_BREAK 0x00100 /* Bit 8: set intr on break */
+#define SP_CLR_SIG0 0x00200 /* Bit 9: clear signal 0 */
+#define SP_SET_SIG0 0x00400 /* Bit 10: set signal 0 */
+#define SP_CLR_SIG1 0x00800 /* Bit 11: clear signal 1 */
+#define SP_SET_SIG1 0x01000 /* Bit 12: set signal 1 */
+#define SP_CLR_SIG2 0x02000 /* Bit 13: clear signal 2 */
+#define SP_SET_SIG2 0x04000 /* Bit 14: set signal 2 */
+#define SP_CLR_SIG3 0x08000 /* Bit 15: clear signal 3 */
+#define SP_SET_SIG3 0x10000 /* Bit 16: set signal 3 */
+#define SP_CLR_SIG4 0x20000 /* Bit 17: clear signal 4 */
+#define SP_SET_SIG4 0x40000 /* Bit 18: set signal 4 */
+#define SP_CLR_SIG5 0x80000 /* Bit 19: clear signal 5 */
+#define SP_SET_SIG5 0x100000 /* Bit 20: set signal 5 */
+#define SP_CLR_SIG6 0x200000 /* Bit 21: clear signal 6 */
+#define SP_SET_SIG6 0x400000 /* Bit 22: set signal 6 */
+#define SP_CLR_SIG7 0x800000 /* Bit 23: clear signal 7 */
+#define SP_SET_SIG7 0x1000000 /* Bit 24: set signal 7 */
+
+#define DPC_CLR_XBUS_DMEM_DMA 0x0001 /* Bit 0: clear xbus_dmem_dma */
+#define DPC_SET_XBUS_DMEM_DMA 0x0002 /* Bit 1: set xbus_dmem_dma */
+#define DPC_CLR_FREEZE 0x0004 /* Bit 2: clear freeze */
+#define DPC_SET_FREEZE 0x0008 /* Bit 3: set freeze */
+#define DPC_CLR_FLUSH 0x0010 /* Bit 4: clear flush */
+#define DPC_SET_FLUSH 0x0020 /* Bit 5: set flush */
+#define DPC_CLR_TMEM_CTR 0x0040 /* Bit 6: clear tmem ctr */
+#define DPC_CLR_PIPE_CTR 0x0080 /* Bit 7: clear pipe ctr */
+#define DPC_CLR_CMD_CTR 0x0100 /* Bit 8: clear cmd ctr */
+#define DPC_CLR_CLOCK_CTR 0x0200 /* Bit 9: clear clock ctr */
+
+#define DPC_STATUS_XBUS_DMEM_DMA 0x001 /* Bit 0: xbus_dmem_dma */
+#define DPC_STATUS_FREEZE 0x002 /* Bit 1: freeze */
+#define DPC_STATUS_FLUSH 0x004 /* Bit 2: flush */
+#define DPC_STATUS_START_GCLK 0x008 /* Bit 3: start gclk */
+#define DPC_STATUS_TMEM_BUSY 0x010 /* Bit 4: tmem busy */
+#define DPC_STATUS_PIPE_BUSY 0x020 /* Bit 5: pipe busy */
+#define DPC_STATUS_CMD_BUSY 0x040 /* Bit 6: cmd busy */
+#define DPC_STATUS_CBUF_READY 0x080 /* Bit 7: cbuf ready */
+#define DPC_STATUS_DMA_BUSY 0x100 /* Bit 8: dma busy */
+#define DPC_STATUS_END_VALID 0x200 /* Bit 9: end valid */
+#define DPC_STATUS_START_VALID 0x400 /* Bit 10: start valid */
+
+#define R4300i_SP_Intr 0x1
+
+extern char * x86_Strings[8];
+extern char * GPR_Strings[32];
+
+#define x86_Name(Reg) (x86_Strings[(Reg)])
+#define GPR_Name(Reg) (GPR_Strings[(Reg)])
+
+/*
+#define GPR_Name(Reg)\
+ (Reg) == 0 ? "R0" : (Reg) == 1 ? "AT" : (Reg) == 2 ? "V0" : (Reg) == 3 ? "V1" :\
+ (Reg) == 4 ? "A0" : (Reg) == 5 ? "A1" : (Reg) == 6 ? "A2" : (Reg) == 7 ? "A3" :\
+ (Reg) == 8 ? "T0" : (Reg) == 9 ? "T1" : (Reg) == 10 ? "T2" : (Reg) == 11 ? "T3" :\
+ (Reg) == 12 ? "T4" : (Reg) == 13 ? "T5" : (Reg) == 14 ? "T6" : (Reg) == 15 ? "T7" :\
+ (Reg) == 16 ? "S0" : (Reg) == 17 ? "S1" : (Reg) == 18 ? "S2" : (Reg) == 19 ? "S3" :\
+ (Reg) == 20 ? "S4" : (Reg) == 21 ? "S5" : (Reg) == 22 ? "S6" : (Reg) == 23 ? "S7" :\
+ (Reg) == 24 ? "T8" : (Reg) == 25 ? "T9" : (Reg) == 26 ? "K0" : (Reg) == 27 ? "K1" :\
+ (Reg) == 28 ? "GP" : (Reg) == 29 ? "SP" : (Reg) == 30 ? "S8" :\
+ (Reg) == 31 ? "RA" : "Unknown Register"
+*/
+
+#define COP0_Name(Reg)\
+ (Reg) == 0 ? "SP memory address" :\
+ (Reg) == 1 ? "SP DRAM DMA address" :\
+ (Reg) == 2 ? "SP read DMA length" :\
+ (Reg) == 3 ? "SP write DMA length" :\
+ (Reg) == 4 ? "SP status" :\
+ (Reg) == 5 ? "SP DMA full" :\
+ (Reg) == 6 ? "SP DMA busy" :\
+ (Reg) == 7 ? "SP semaphore" :\
+ (Reg) == 8 ? "DP CMD DMA start" :\
+ (Reg) == 9 ? "DP CMD DMA end" :\
+ (Reg) == 10 ? "DP CMD DMA current" :\
+ (Reg) == 11 ? "DP CMD status" :\
+ (Reg) == 12 ? "DP clock counter" :\
+ (Reg) == 13 ? "DP buffer busy counter" :\
+ (Reg) == 14 ? "DP pipe busy counter" :\
+ (Reg) == 15 ? "DP TMEM load counter" :\
+ "Unknown Register"
+
+#define ElementSpecifier(Elem)\
+ (Elem) == 0 ? "" : (Elem) == 1 ? "" : (Elem) == 2 ? " [0q]" :\
+ (Elem) == 3 ? " [1q]" : (Elem) == 4 ? " [0h]" : (Elem) == 5 ? " [1h]" :\
+ (Elem) == 6 ? " [2h]" : (Elem) == 7 ? " [3h]" : (Elem) == 8 ? " [0]" :\
+ (Elem) == 9 ? " [1]" : (Elem) == 10 ? " [2]" : (Elem) == 11 ? " [3]" :\
+ (Elem) == 12 ? " [4]" : (Elem) == 13 ? " [5]" : (Elem) == 14 ? " [6]" :\
+ (Elem) == 15 ? " [7]" : "Unknown Element"
+
+void InitilizeRSPRegisters (void);
+
+/*** RSP Registers ***/
+extern MIPSUWORD RSP_GPR[32], RSP_Flags[4];
+extern MIPSUDWORD RSP_ACCUM[8];
+extern VECTOR RSP_Vect[32];
+
+
diff --git a/src/usf/rsp_sse.c b/src/usf/rsp_sse.c new file mode 100644 index 0000000..2dc7d1c --- /dev/null +++ b/src/usf/rsp_sse.c @@ -0,0 +1,84 @@ +/*
+ * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator).
+ *
+ * (c) Copyright 2001 jabo (jabo@emulation64.com) and
+ * zilmar (zilmar@emulation64.com)
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+
+#include "types.h"
+#include "rsp.h"
+#include "rsp_x86.h"
+#include "recompiler_cpu.h"
+#include "memory.h"
+#include "types.h"
+
+extern uint8_t * DMEM;
+
+#define PUTDST8(dest,value) (*((uint8_t *)(dest))=(uint8_t)(value)); dest += 1;
+#define PUTDST16(dest,value) (*((uint16_t *)(dest))=(uint16_t)(value)); dest += 2;
+#define PUTDST32(dest,value) (*((uint32_t *)(dest))=(uint32_t)(value)); dest += 4;
+#define PUTDST64(dest,value) {(*((uint64_t *)(dest))=(uint64_t)(value)); dest += 8;}
+
+void RSPSseMoveAlignedVariableToReg(void * Variable, int32_t sseReg) {
+ OPCODE_REG_VARIABLE(,16,0x100F,sseReg,Variable);
+}
+
+void RSPSseMoveAlignedN64MemToReg(int32_t sseReg, int32_t AddrReg) {
+ OPCODE_REG_ADDR_DMEM(,16,0x100F,sseReg,AddrReg);
+}
+
+void RSPSseMoveAlignedRegToVariable(int32_t sseReg, void *Variable) {
+ OPCODE_REG_VARIABLE(,16,0x110f,sseReg,Variable); //290F
+}
+
+void RSPSseMoveAlignedRegToN64Mem(int32_t sseReg, int32_t AddrReg) {
+ OPCODE_REG_ADDR_DMEM(,16,0x110f,sseReg,AddrReg); //290F
+}
+
+void RSPSseMoveUnalignedVariableToReg(void *Variable, int32_t sseReg) {
+ OPCODE_REG_VARIABLE(,16,0x100F,sseReg,Variable);
+}
+
+void RSPSseMoveUnalignedN64MemToReg(int32_t sseReg, int32_t AddrReg) {
+ OPCODE_REG_ADDR_DMEM(,16,0x100f,sseReg,AddrReg);
+}
+
+void RSPSseMoveUnalignedRegToVariable(int32_t sseReg, void *Variable) {
+ OPCODE_REG_VARIABLE(,16,0x110F,sseReg,Variable);
+}
+
+void RSPSseMoveUnalignedRegToN64Mem(int32_t sseReg, int32_t AddrReg) {
+ OPCODE_REG_ADDR_DMEM(,16,0x110f,sseReg,AddrReg);
+}
+
+void RSPSseMoveRegToReg(int32_t Dest, int32_t Source) {
+ OPCODE_REG_REG(16,0x280F,Dest,Source)
+}
+
+void RSPSseXorRegToReg(int32_t Dest, int32_t Source) {
+ OPCODE_REG_REG(16,0x570F,Dest,Source)
+}
+
+void RSPSseShuffleReg(int32_t Dest, int32_t Source, uint8_t Immed) {
+ OPCODE_REG_REG(16,0xC60F,Dest,Source)
+ PUTDST8(RSPRecompPos, Immed);
+}
diff --git a/src/usf/rsp_x86.c b/src/usf/rsp_x86.c new file mode 100644 index 0000000..a7052b2 --- /dev/null +++ b/src/usf/rsp_x86.c @@ -0,0 +1,1366 @@ +/*
+ * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator).
+ *
+ * (c) Copyright 2001 jabo (jabo@emulation64.com) and
+ * zilmar (zilmar@emulation64.com)
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include "rsp.h"
+#include "rsp_x86.h"
+#include "recompiler_cpu.h"
+#include "memory.h"
+#include "types.h"
+#include "main.h"
+
+#define PUTDST8(dest,value) {(*((uint8_t *)(dest))=(uint8_t)(value)); dest += 1;}
+#define PUTDST16(dest,value) {(*((uint16_t *)(dest))=(uint16_t)(value)); dest += 2;}
+#define PUTDST32(dest,value) {(*((uint32_t *)(dest))=(uint32_t)(value)); dest += 4;}
+#define PUTDST64(dest,value) {(*((uint64_t *)(dest))=(uint64_t)(value)); dest += 8;}
+
+
+#define x64_Reg 0x10
+#define X64_Reg 0x10
+#define X64_Ext 0x20
+
+extern uint8_t Index[9];
+
+
+char * x86_Strings[8] = {
+ "eax", "ebx", "ecx", "edx",
+ "esi", "edi", "ebp", "esp"
+};
+
+char * x86_ByteStrings[8] = {
+ "al", "bl", "cl", "dl",
+ "?4", "?5", "?6", "?7"
+};
+
+char * x86_HalfStrings[8] = {
+ "ax", "bx", "cx", "dx",
+ "si", "di", "bp", "sp"
+};
+
+extern uint32_t ConditionalMove;
+
+#define x86Byte_Name(Reg) (x86_ByteStrings[(Reg)])
+#define x86Half_Name(Reg) (x86_HalfStrings[(Reg)])
+
+
+
+void RSPAdcX86regToVariable(int32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x11,x86reg,Variable)
+}
+
+void RSPAdcConstToVariable(void *Variable, uint8_t Constant) {
+ RSPBreakPoint();
+
+ /*if(((uintptr_t)Variable - (uintptr_t)TLB_Map) < 0x7FFFFFFF) {
+ RSPBreakPoint();
+ OPCODE_REG_MREG_IMM32(8,0x81,OP_D2,x86_R15,(uintptr_t)Variable - (uintptr_t)TLB_Map);
+ } else {
+ LOAD_VARIABLE(x86_TEMP, Variable);
+ OPCODE_REG_MREG(8,0x81,OP_D2,x86_TEMP);
+ }
+
+ PUTDST8(RSPRecompPos,Constant);
+ */
+}
+
+void RSPAdcX86RegToX86Reg(int32_t Destination, int32_t Source) {
+ OPCODE_REG_REG(8,0x13,Destination,Source);
+}
+
+void RSPAddConstToVariable (uint32_t Const, void *Variable) {
+ OPCODE_REG_VARIABLE(,8,0x81,OP_D0,Variable)
+ PUTDST32(RSPRecompPos,Const);
+}
+
+void RSPAddConstToX86Reg64 (int32_t x86reg, uint32_t Const) {
+ if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) {
+ OPCODE_REG_REG(8,0x81,OP_D0,x86reg | x64_Reg);
+ PUTDST32(RSPRecompPos, Const);
+ } else {
+ OPCODE_REG_REG(8,0x83,OP_D0,x86reg | x64_Reg);
+ PUTDST8(RSPRecompPos, Const);
+ }
+}
+
+void RSPAddConstToX86Reg (int32_t x86reg, uint32_t Const) {
+ if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) {
+ OPCODE_REG_REG(8,0x81,OP_D0,x86reg);
+ PUTDST32(RSPRecompPos, Const);
+ } else {
+ OPCODE_REG_REG(8,0x83,OP_D0,x86reg);
+ PUTDST8(RSPRecompPos, Const);
+ }
+}
+
+
+void RSPAddQwordToX86Reg (int32_t x86reg, uint64_t Const) {
+#ifdef USEX64
+ LOAD_VARIABLE(x86_TEMP, Const);
+ OPCODE_REG_REG(8,0x1,x86_TEMP,x86reg);
+#else
+ RSPAddConstToX86Reg(x86reg, Const);
+#endif
+}
+
+
+void RSPAddVariableToX86reg(int32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x3,x86reg,Variable)
+}
+
+void RSPAddX86regToVariable(int32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x1,x86reg,Variable)
+}
+
+void RSPAddX86RegToX86Reg(int32_t Destination, int32_t Source) {
+ OPCODE_REG_REG(8,0x3,Destination,Source);
+}
+
+void RSPAndConstToVariable (uint32_t Const, void *Variable) {
+ OPCODE_REG_VARIABLE(,8,0x81,OP_D4,Variable)
+ PUTDST32(RSPRecompPos,Const);
+}
+
+void RSPAndConstToX86Reg(int32_t x86reg, uint32_t Const) {
+ if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) {
+ OPCODE_REG_REG(8,0x81,OP_D4,x86reg);
+ PUTDST32(RSPRecompPos, Const);
+ } else {
+ OPCODE_REG_REG(8,0x83,OP_D4,x86reg);
+ PUTDST8(RSPRecompPos, Const);
+ }
+}
+
+void RSPAndVariableDispToX86Reg(void *Variable, int32_t x86reg, int32_t AddrReg, int32_t Multiplier) {
+#ifdef USEX64
+ if(((uintptr_t)Variable - (uintptr_t)TLB_Map) < 0x7FFFFFFF) {
+ OPCODE_REG_BASE_INDEX_SCALE_IMM32(8,0x23,x86reg,x86_R15,AddrReg,Index[Multiplier], (uintptr_t)Variable - (uintptr_t)TLB_Map);
+ } else {
+ LOAD_VARIABLE(x86_TEMP, Variable);
+ OPCODE_REG_BASE_INDEX_SCALE(8,0x23,x86reg,x86_TEMP,AddrReg,Index[Multiplier]);
+ }
+#else
+ OPCODE_REG_INDEX_SCALE_IMM32(8,0x23,x86reg,AddrReg,Index[Multiplier],Variable);
+#endif
+}
+
+void RSPAndVariableToX86Reg(void * Variable, int32_t x86reg) {
+ OPCODE_REG_VARIABLE(,8,0x23,x86reg,Variable)
+}
+
+void RSPAndX86RegToX86Reg(int32_t Destination, int32_t Source) {
+ OPCODE_REG_REG(8,0x21,Source,Destination);
+}
+
+void RSPBreakPoint (void) {
+ PUTDST8(RSPRecompPos,0xCC);
+}
+
+void RSPCall_Direct(void * FunctAddress) {
+ uintptr_t disp = 0;
+#ifdef USEX64
+ disp = (uintptr_t)FunctAddress-(uintptr_t)RSPRecompPos - 5;
+ RSPSubConstFromX86Reg(x86_RSP, 0x28);
+// if(disp <= 0x7fffffff) {
+// PUTDST8(RSPRecompPos,0xE8);
+// PUTDST32(RSPRecompPos,disp);
+// } else {
+ LOAD_VARIABLE(x86_TEMP, FunctAddress);
+ OPCODE_REG_REG(8,0xff,OP_D2,x86_TEMP);
+
+// }
+ RSPAddConstToX86Reg(x86_RSP, 0x28);
+#else
+ disp = (uintptr_t)FunctAddress-(uintptr_t)RSPRecompPos - 5;
+ PUTDST8(RSPRecompPos,0xE8);
+ PUTDST32(RSPRecompPos,disp);
+#endif
+}
+
+void RSPCompConstToVariable(uint32_t Const, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x81,OP_D7,Variable)
+ PUTDST32(RSPRecompPos,Const);
+}
+
+void RSPCompConstToX86reg(int32_t x86reg, uint32_t Const) {
+ if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) {
+ OPCODE_REG_REG(8,0x81,OP_D7,x86reg);
+ PUTDST32(RSPRecompPos,Const);
+ } else {
+ OPCODE_REG_REG(8,0x83,OP_D7,x86reg);
+ PUTDST8(RSPRecompPos, Const);
+ }
+}
+
+void RSPCompX86regToVariable(int32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x3B,x86reg,Variable)
+}
+
+void RSPCompX86RegToX86Reg(int32_t Destination, int32_t Source) {
+ OPCODE_REG_REG(8,0x3B,Destination,Source);
+}
+
+void RSPDecX86reg(x86reg) {
+ OPCODE_REG_REG(8,0xFF,OP_D1,x86reg);
+}
+
+void RSPDivX86reg(int32_t x86reg) {
+ OPCODE_REG_REG(8,0xF7,OP_D6,x86reg);
+}
+
+void RSPidivX86reg(int32_t x86reg) {
+ OPCODE_REG_REG(8,0xF7,OP_D7,x86reg);
+}
+
+void RSPimulX86reg(int32_t x86reg) {
+ OPCODE_REG_REG(8,0xF7,OP_D5,x86reg);
+}
+
+void RSPIncX86reg(int32_t x86reg) {
+ OPCODE_REG_REG(8,0xFF,OP_D0,x86reg);
+}
+
+void RSPJaeLabel8( uint8_t Value) {
+ PUTDST8(RSPRecompPos,0x73);
+ PUTDST8(RSPRecompPos,Value);
+}
+
+void RSPJaeLabel32(uint32_t Value) {
+ PUTDST16(RSPRecompPos,0x830F);
+ PUTDST32(RSPRecompPos,Value);
+}
+
+void RSPJaLabel8( uint8_t Value) {
+ PUTDST8(RSPRecompPos,0x77);
+ PUTDST8(RSPRecompPos,Value);
+}
+
+void RSPJaLabel32(uint32_t Value) {
+ PUTDST16(RSPRecompPos,0x870F);
+ PUTDST32(RSPRecompPos,Value);
+}
+
+void RSPJbLabel8( uint8_t Value) {
+ PUTDST8(RSPRecompPos,0x72);
+ PUTDST8(RSPRecompPos,Value);
+}
+
+void RSPJbLabel32(uint32_t Value) {
+ PUTDST16(RSPRecompPos,0x820F);
+ PUTDST32(RSPRecompPos,Value);
+}
+
+void RSPJecxzLabel8( uint8_t Value) {
+ PUTDST8(RSPRecompPos,0xE3);
+ PUTDST8(RSPRecompPos,Value);
+}
+
+void RSPJeLabel8( uint8_t Value) {
+ PUTDST8(RSPRecompPos,0x74);
+ PUTDST8(RSPRecompPos,Value);
+}
+
+void RSPJeLabel32(uint32_t Value) {
+ PUTDST16(RSPRecompPos,0x840F);
+ PUTDST32(RSPRecompPos,Value);
+}
+
+void RSPJgeLabel32(uint32_t Value) {
+ PUTDST16(RSPRecompPos,0x8D0F);
+ PUTDST32(RSPRecompPos,Value);
+}
+
+void RSPJgLabel8( uint8_t Value) {
+ PUTDST8(RSPRecompPos,0x7F);
+ PUTDST8(RSPRecompPos,Value);
+}
+
+void RSPJgLabel32(uint32_t Value) {
+ PUTDST16(RSPRecompPos,0x8F0F);
+ PUTDST32(RSPRecompPos,Value);
+}
+
+void RSPJleLabel8( uint8_t Value) {
+ PUTDST8(RSPRecompPos,0x7E);
+ PUTDST8(RSPRecompPos,Value);
+}
+
+void RSPJleLabel32(uint32_t Value) {
+ PUTDST16(RSPRecompPos,0x8E0F);
+ PUTDST32(RSPRecompPos,Value);
+}
+
+void RSPJlLabel8( uint8_t Value) {
+ PUTDST8(RSPRecompPos,0x7C);
+ PUTDST8(RSPRecompPos,Value);
+}
+
+void RSPJlLabel32(uint32_t Value) {
+ PUTDST16(RSPRecompPos,0x8C0F);
+ PUTDST32(RSPRecompPos,Value);
+}
+
+void RSPJzLabel8( uint8_t Value) {
+ PUTDST8(RSPRecompPos,0x74);
+ PUTDST8(RSPRecompPos,Value);
+}
+
+void RSPJnzLabel8( uint8_t Value) {
+ PUTDST8(RSPRecompPos,0x75);
+ PUTDST8(RSPRecompPos,Value);
+}
+
+
+void RSPJmpDirectReg( int32_t x86reg ) {
+ OPCODE_REG_REG(8,0xff,OP_D4,x86reg);
+}
+
+void RSPJmpLabel8( uint8_t Value) {
+ PUTDST8(RSPRecompPos,0xEB);
+ PUTDST8(RSPRecompPos,Value);
+}
+
+void RSPJmpLabel32( uint32_t Value) {
+ PUTDST8(RSPRecompPos,0xE9);
+ PUTDST32(RSPRecompPos,Value);
+}
+
+void RSPJneLabel8( uint8_t Value) {
+ PUTDST8(RSPRecompPos,0x75);
+ PUTDST8(RSPRecompPos,Value);
+}
+
+void RSPJneLabel32(uint32_t Value) {
+ PUTDST16(RSPRecompPos,0x850F);
+ PUTDST32(RSPRecompPos,Value);
+}
+
+void RSPJnsLabel8( uint8_t Value) {
+ PUTDST8(RSPRecompPos,0x79);
+ PUTDST8(RSPRecompPos,Value);
+}
+
+void RSPJnsLabel32(uint32_t Value) {
+ PUTDST16(RSPRecompPos,0x890F);
+ PUTDST32(RSPRecompPos,Value);
+}
+
+void RSPJsLabel32(uint32_t Value) {
+ PUTDST16(RSPRecompPos,0x880F);
+ PUTDST32(RSPRecompPos,Value);
+}
+
+void RSPLeaRegReg(int32_t x86RegDest, int32_t x86RegSrc, int32_t multiplier) {
+ OPCODE_REG_BASE_INDEX_SCALE(8,0x8D,x86RegDest,x86_EBP,x86RegSrc,Index[multiplier]);
+ PUTDST32(RSPRecompPos,0x00000000);
+}
+
+void RSPLeaSourceAndOffset(int32_t x86DestReg, int32_t x86SourceReg, int32_t offset) {
+ OPCODE_REG_MREG_IMM32(8,0x8D,x86DestReg,x86SourceReg,offset);
+}
+
+void RSPMoveConstByteToVariable (uint8_t Const,void *Variable) {
+ OPCODE_REG_VARIABLE(,8,0xC6,OP_D0,Variable)
+ PUTDST8(RSPRecompPos,Const);
+}
+
+void RSPMoveConstHalfToVariable (uint16_t Const,void *Variable) {
+ OPCODE_REG_VARIABLE(PUTDST8(RSPRecompPos,0x66),8,0xC7,OP_D0,Variable)
+ PUTDST16(RSPRecompPos,Const);
+}
+
+void RSPMoveConstHalfToX86regPointer(uint16_t Const, int32_t AddrReg1, int32_t AddrReg2) {
+ PUTDST8(RSPRecompPos,0x66);
+ OPCODE_REG_BASE_INDEX(8,0xC7,OP_D0,AddrReg1,AddrReg2);
+ PUTDST16(RSPRecompPos,Const);
+}
+
+void RSPMoveX86regByteToN64Mem(int32_t x86reg, int32_t AddrReg) {
+ OPCODE_REG_ADDR_DMEM(,8,0x88,x86reg,AddrReg);
+}
+
+void RSPMoveX86regHalfToN64Mem(int32_t x86reg, int32_t AddrReg) {
+ OPCODE_REG_ADDR_DMEM(PUTDST8(RSPRecompPos,0x66),8,0x89,x86reg,AddrReg);
+}
+
+void RSPMoveX86regToN64Mem(int32_t x86reg, int32_t AddrReg) {
+ OPCODE_REG_ADDR_DMEM(,8,0x89,x86reg,AddrReg);
+}
+
+
+void RSPMoveConstToVariable (uint32_t Const,void *Variable) {
+ OPCODE_REG_VARIABLE(,8,0xC7,OP_D0,Variable)
+ PUTDST32(RSPRecompPos,Const);
+}
+
+void RSPMoveConstToX86Pointer(uint32_t Const, int32_t X86Pointer) {
+ OPCODE_REG_MREG(8,0xC7,OP_D0,X86Pointer);
+ PUTDST32(RSPRecompPos,Const);
+}
+
+
+void RSPMoveOffsetToX86reg(uint32_t Const, int32_t x86reg) {
+ OPCODE_REG_REG(8,0xC7,OP_D0,x86reg);
+ PUTDST32(RSPRecompPos,Const);
+}
+
+
+void RSPMoveConstToX86reg(uint32_t Const, int32_t x86reg) {
+ OPCODE_REG_REG(8,0xC7,OP_D0,x86reg);
+ PUTDST32(RSPRecompPos,Const);
+}
+
+void RSPMoveConstQwordToX86reg(uintptr_t Const, int32_t x86reg) {
+#ifndef USEX64
+ OPCODE_REG_REG(8,0xC7,OP_D0,x86reg);
+ PUTDST32(RSPRecompPos,Const);
+#else
+ PUTDST8(RSPRecompPos, 0x48 | ((x86reg&0x20)>>5));
+ PUTDST8(RSPRecompPos, 0xB8 | ((x86reg-1)&0x7));
+ PUTDST64(RSPRecompPos,Const);
+#endif
+}
+
+void RSPMoveConstByteToX86regPointer(uint8_t Const, int32_t AddrReg1, int32_t AddrReg2) {
+ OPCODE_REG_BASE_INDEX(8,0xC6,OP_D0,AddrReg1,AddrReg2)
+ PUTDST8(RSPRecompPos,Const);
+}
+
+void RSPMoveConstToX86regPointer(uint32_t Const, int32_t AddrReg1, int32_t AddrReg2) {
+ OPCODE_REG_BASE_INDEX(8,0xC7,OP_D0,AddrReg1,AddrReg2);
+ PUTDST32(RSPRecompPos,Const);
+}
+
+void RSPMoveN64MemToX86reg(int32_t x86reg, int32_t AddrReg) {
+#ifdef USEX64
+ if(((uintptr_t)DMEM - (uintptr_t)TLB_Map) < 0x7FFFFFFF) {
+ OPCODE_REG_BASE_INDEX_IMM32(8,0x8B,x86reg,x86_R15,AddrReg,(uintptr_t)DMEM - (uintptr_t)TLB_Map);
+ } else {
+ LOAD_VARIABLE(x86_TEMP, DMEM);
+ OPCODE_REG_BASE_INDEX(8,0x8B,x86reg,x86_TEMP,AddrReg);
+ }
+#else
+ OPCODE_REG_MREG_IMM32(8,0x8B,x86reg,AddrReg,DMEM);
+#endif
+}
+
+void RSPMoveSxByteX86regPointerToX86reg(int32_t AddrReg1, int32_t AddrReg2, int32_t x86reg) {
+ OPCODE_REG_BASE_INDEX(16,0xBE0F,x86reg,AddrReg1,AddrReg2);
+}
+
+void RSPMoveSxHalfX86regPointerToX86reg(int32_t AddrReg1, int32_t AddrReg2, int32_t x86reg) {
+ OPCODE_REG_BASE_INDEX(16,0xBF0F,x86reg,AddrReg1,AddrReg2);
+}
+
+
+void RSPMoveN64MemToX86regByte(int32_t x86reg, int32_t AddrReg) {
+ OPCODE_REG_ADDR_DMEM(,8,0x8A,x86reg,AddrReg);
+}
+
+
+void RSPMoveSxN64MemToX86regByte(int32_t x86reg, int32_t AddrReg) {
+ OPCODE_REG_ADDR_DMEM(,16,0xBE0F,x86reg,AddrReg);
+}
+
+void RSPMoveSxVariableToX86regHalf(void *Variable, int32_t x86reg) {
+ OPCODE_REG_VARIABLE(,16,0xBF0F,x86reg,Variable);
+}
+
+
+void RSPMoveSxN64MemToX86regHalf(int32_t x86reg, int32_t AddrReg) {
+ OPCODE_REG_ADDR_DMEM(,16,0xBF0F,x86reg,AddrReg);
+}
+
+void RSPMoveZxN64MemToX86regHalf(int32_t x86reg, int32_t AddrReg) {
+ OPCODE_REG_ADDR_DMEM(,16,0xB70F,x86reg,AddrReg);
+}
+
+void RSPMoveVariableToX86reg(void *Variable, int32_t x86reg) {
+ OPCODE_REG_VARIABLE(,8,0x8B,x86reg,Variable);
+}
+
+void RSPMoveX86RegDispToX86Reg(int32_t x86reg, int32_t AddrReg, int32_t IndexReg, int32_t Multiplier) {
+ OPCODE_REG_BASE_INDEX_SCALE(8,0x8B,x86reg,AddrReg,IndexReg,Index[Multiplier]);
+}
+
+void RSPMoveN64MemDispToX86reg(int32_t x86reg, int32_t AddrReg, uint8_t Disp) {
+#ifdef USEX64
+ if(((uintptr_t)DMEM - (uintptr_t)TLB_Map) < 0x7FFFFFFF) {
+ OPCODE_REG_BASE_INDEX_SCALE_IMM32(8,0x8B,x86reg,x86_R15,AddrReg,Index[0],(((uintptr_t)DMEM - (uintptr_t)TLB_Map))+Disp);
+ } else {
+ LOAD_VARIABLE(x86_TEMP, DMEM);
+ OPCODE_REG_BASE_INDEX_SCALE_IMM8(8,0x8B,x86reg,x86_TEMP,AddrReg,Index[0],Disp);
+ }
+#else
+ OPCODE_REG_MREG_IMM32(8,0x8B,x86reg,AddrReg,DMEM+Disp);
+#endif
+}
+
+void RSPMoveVariableDispToX86Reg(void *Variable, int32_t x86reg, int32_t AddrReg, int32_t Multiplier) {
+#ifdef USEX64
+ if(((uintptr_t)Variable - (uintptr_t)TLB_Map) < 0x7FFFFFFF) {
+ OPCODE_REG_BASE_INDEX_SCALE_IMM32(8,0x8B,x86reg,x86_R15,AddrReg,Index[Multiplier],((uintptr_t)Variable - (uintptr_t)TLB_Map));
+ } else {
+ LOAD_VARIABLE(x86_TEMP, Variable);
+ OPCODE_REG_BASE_INDEX_SCALE(8,0x8B,x86reg,x86_TEMP,AddrReg,Index[Multiplier]);
+ }
+#else
+ OPCODE_REG_INDEX_SCALE_IMM32(8,0x8B,x86reg,AddrReg,Index[Multiplier],Variable);
+#endif
+}
+
+void RSPMoveN64MemToX86regHalf(int32_t x86reg, int32_t AddrReg)
+{
+ RSPMoveVariableDispToX86Reg(DMEM,x86reg,AddrReg,1);
+}
+
+
+void RSPMoveVariableToX86regByte(void *Variable, int32_t x86reg) {
+ OPCODE_REG_VARIABLE(,8,0x8A,x86reg,Variable);
+}
+
+void RSPMoveVariableToX86regHalf(void *Variable, int32_t x86reg) {
+ OPCODE_REG_VARIABLE(PUTDST8(RSPRecompPos,0x66),8,0x8B,x86reg,Variable);
+}
+
+void RSPMoveX86regByteToVariable(int32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x88,x86reg,Variable);
+}
+
+void RSPMoveX86regByteToX86regPointer(int32_t x86reg, int32_t AddrReg) {
+ OPCODE_REG_MREG(8,0x88,x86reg,AddrReg);
+}
+
+void RSPMoveX86regHalfToVariable(int32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(PUTDST8(RSPRecompPos,0x66),8,0x89,x86reg,Variable);
+}
+
+void RSPMoveX86regHalfToX86regPointer(int32_t x86reg, int32_t AddrReg) {
+ PUTDST8(RSPRecompPos,0x66);
+ OPCODE_REG_MREG(8,0x89,x86reg,AddrReg);
+}
+
+void RSPMoveX86PointerToX86reg(int32_t x86reg, int32_t X86Pointer) {
+ OPCODE_REG_MREG(8,0x8B,x86reg,X86Pointer);
+}
+
+void RSPMoveX86regPointerToX86reg(int32_t Destination, int32_t AddrReg) {
+ OPCODE_REG_MREG(8,0x8B,Destination,AddrReg);
+}
+
+void RSPMoveX86regPointerToX86regDisp8(int32_t AddrReg1, int32_t AddrReg2, int32_t x86reg, uint8_t offset) {
+ OPCODE_REG_BASE_INDEX_IMM8(8,0x8B,x86reg,AddrReg1,AddrReg2,offset);
+}
+
+void RSPMoveX86regToMemory(int32_t x86reg, int32_t AddrReg, uint32_t Disp) {
+ OPCODE_REG_MREG_IMM32(8,0x89,x86reg,AddrReg,Disp);
+}
+
+void RSPMoveX86regToVariable(int32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x89,x86reg,Variable);
+}
+
+void RSPMoveX86RegToX86Reg(int32_t Source, int32_t Destination) {
+ OPCODE_REG_REG(8,0x89,Source|X64_Reg, Destination|X64_Reg);
+}
+
+void RSPMoveX86regToX86Pointer(int32_t x86reg, int32_t X86Pointer) {
+ OPCODE_REG_MREG(8,0x89,x86reg, X86Pointer);
+}
+
+void RSPMoveX86regToX86regPointer(int32_t x86reg, int32_t AddrReg) {
+ OPCODE_REG_MREG(8,0x89,x86reg,AddrReg);
+}
+
+void RSPMoveZxByteX86regPointerToX86reg(int32_t AddrReg1, int32_t AddrReg2, int32_t x86reg) {
+ OPCODE_REG_BASE_INDEX(16,0xB60F,x86reg,AddrReg1,AddrReg2);
+}
+
+void RSPMoveZxHalfX86regPointerToX86reg(int32_t AddrReg1, int32_t AddrReg2, int32_t x86reg) {
+ OPCODE_REG_BASE_INDEX(16,0xB70F,x86reg,AddrReg1,AddrReg2);
+}
+
+void RSPMoveZxVariableToX86regByte(void *Variable, int32_t x86reg) {
+ OPCODE_REG_VARIABLE(,16,0xB60F,x86reg,Variable);
+}
+
+void RSPMoveZxVariableToX86regHalf(void *Variable, int32_t x86reg) {
+ OPCODE_REG_VARIABLE(,16,0xB70F,x86reg,Variable);
+}
+
+void RSPMulX86reg(int32_t x86reg) {
+ OPCODE_REG_REG(8,0xF7,OP_D4,x86reg);
+}
+
+void RSPNotX86Reg(int32_t x86reg) {
+ OPCODE_REG_REG(8,0xF7,OP_D2,x86reg);
+}
+
+void RSPOrConstToVariable(uint32_t Const, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x81,OP_D1,Variable);
+ PUTDST32(RSPRecompPos,Const);
+}
+
+void RSPOrConstToX86Reg(uint32_t Const, int32_t x86reg) {
+ if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) {
+ OPCODE_REG_REG(8,0x81,OP_D1,x86reg);
+ PUTDST32(RSPRecompPos, Const);
+ } else {
+ OPCODE_REG_REG(8,0x83,OP_D1,x86reg);
+ PUTDST8(RSPRecompPos, Const);
+ }
+}
+
+void RSPOrVariableToX86Reg(void * Variable, int32_t x86reg) {
+ OPCODE_REG_VARIABLE(,8,0xb,x86reg,Variable);
+}
+
+void RSPOrX86RegToVariable(void * Variable, int32_t x86reg) {
+ OPCODE_REG_VARIABLE(,8,0x9,x86reg,Variable);
+}
+
+void RSPOrX86RegToX86Reg(int32_t Destination, int32_t Source) {
+ OPCODE_REG_REG(8,0x0B,Destination,Source);
+}
+
+void RSPPushfd() {
+ PUTDST8(RSPRecompPos,0x9c);
+}
+
+void RSPPopfd() {
+ PUTDST8(RSPRecompPos,0x9d);
+}
+
+void RSPPopad(void) {
+#ifdef USEX64
+ PUTDST16(RSPRecompPos,0x5f41);
+ PUTDST16(RSPRecompPos,0x5e41);
+ PUTDST16(RSPRecompPos,0x5d41);
+ PUTDST16(RSPRecompPos,0x5c41);
+ PUTDST16(RSPRecompPos,0x5b41);
+ PUTDST16(RSPRecompPos,0x5a41);
+ PUTDST16(RSPRecompPos,0x5941);
+ PUTDST16(RSPRecompPos,0x5841);
+ PUTDST8(RSPRecompPos,0x5f);
+ PUTDST8(RSPRecompPos,0x5e);
+ PUTDST8(RSPRecompPos,0x5b);
+ PUTDST8(RSPRecompPos,0x5a);
+ PUTDST8(RSPRecompPos,0x59);
+ PUTDST8(RSPRecompPos,0x58);
+#else
+ PUTDST8(RSPRecompPos,0x61);
+#endif
+}
+
+void RSPPushad(void) {
+#ifdef USEX64
+ PUTDST8(RSPRecompPos,0x50);
+ PUTDST8(RSPRecompPos,0x51);
+ PUTDST8(RSPRecompPos,0x52);
+ PUTDST8(RSPRecompPos,0x53);
+ PUTDST8(RSPRecompPos,0x56);
+ PUTDST8(RSPRecompPos,0x57);
+ PUTDST16(RSPRecompPos,0x5041);
+ PUTDST16(RSPRecompPos,0x5141);
+ PUTDST16(RSPRecompPos,0x5241);
+ PUTDST16(RSPRecompPos,0x5341);
+ PUTDST16(RSPRecompPos,0x5441);
+ PUTDST16(RSPRecompPos,0x5541);
+ PUTDST16(RSPRecompPos,0x5641);
+ PUTDST16(RSPRecompPos,0x5741);
+#else
+PUTDST8(RSPRecompPos,0x60);
+#endif
+}
+
+void RSPPush(int32_t x86reg) {
+
+#ifdef USEX64
+ PUTDST8(RSPRecompPos, 0x40 | ((x86reg & 0x20) >> 5));
+#endif
+ switch(x86reg&0xf) {
+ case x86_EAX: PUTDST8(RSPRecompPos, 0x50); break;
+ case x86_EBX: PUTDST8(RSPRecompPos, 0x53); break;
+ case x86_ECX: PUTDST8(RSPRecompPos, 0x51); break;
+ case x86_EDX: PUTDST8(RSPRecompPos, 0x52); break;
+ case x86_ESI: PUTDST8(RSPRecompPos, 0x56); break;
+ case x86_EDI: PUTDST8(RSPRecompPos, 0x57); break;
+ case x86_ESP: PUTDST8(RSPRecompPos, 0x54); break;
+ case x86_EBP: PUTDST8(RSPRecompPos, 0x55); break;
+ }
+}
+
+void RSPPop(int32_t x86reg) {
+#ifdef USEX64
+ PUTDST8(RSPRecompPos, 0x40 | ((x86reg & 0x20) >> 5));
+#endif
+ switch(x86reg&0xf) {
+
+ case x86_EAX: PUTDST8(RSPRecompPos, 0x58); break;
+ case x86_EBX: PUTDST8(RSPRecompPos, 0x5B); break;
+ case x86_ECX: PUTDST8(RSPRecompPos, 0x59); break;
+ case x86_EDX: PUTDST8(RSPRecompPos, 0x5A); break;
+ case x86_ESI: PUTDST8(RSPRecompPos, 0x5E); break;
+ case x86_EDI: PUTDST8(RSPRecompPos, 0x5F); break;
+ case x86_ESP: PUTDST8(RSPRecompPos, 0x5C); break;
+ case x86_EBP: PUTDST8(RSPRecompPos, 0x5D); break;
+ }
+}
+
+void RSPPushImm32(uint32_t Value) {
+ PUTDST8(RSPRecompPos,0x68);
+ PUTDST32(RSPRecompPos,Value);
+}
+
+void RSPRet(void) {
+ PUTDST8(RSPRecompPos,0xC3);
+}
+
+void RSPSeta(int32_t x86reg) {
+ OPCODE_REG_REG(16,0x970F,OP_D0,x86reg);
+}
+
+void RSPSetaVariable(void * Variable) {
+ OPCODE_REG_VARIABLE(,16,0x970F,OP_D0,Variable);
+}
+
+void RSPSetae(int32_t x86reg) {
+ OPCODE_REG_REG(16,0x930F,OP_D0,x86reg);
+}
+
+void RSPSetb(int32_t x86reg) {
+ OPCODE_REG_REG(16,0x920F,OP_D0,x86reg);
+}
+
+void RSPSetbVariable(void * Variable) {
+ OPCODE_REG_VARIABLE(,16,0x920F,OP_D0,Variable);
+}
+
+void RSPSetg(int32_t x86reg) {
+ OPCODE_REG_REG(16,0x9F0F,OP_D0,x86reg);
+}
+
+void RSPSetgVariable(void * Variable) {
+ OPCODE_REG_VARIABLE(,16,0x9F0F,OP_D0,Variable);
+}
+
+void RSPSetl(int32_t x86reg) {
+ OPCODE_REG_REG(16,0x9C0F,OP_D0,x86reg);
+}
+
+void RSPSetlVariable(void * Variable) {
+ OPCODE_REG_VARIABLE(,16,0x9C0F,OP_D0,Variable);
+}
+
+void RSPShiftLeftSignVariableImmed(void *Variable, uint8_t Immediate) {
+ OPCODE_REG_VARIABLE(,8,0xC1,OP_D4,Variable);
+ PUTDST8(RSPRecompPos,Immediate);
+}
+
+void RSPShiftRightSignVariableImmed(void *Variable, uint8_t Immediate) {
+ OPCODE_REG_VARIABLE(,8,0xC1,OP_D7,Variable);
+ PUTDST8(RSPRecompPos,Immediate);
+}
+
+void RSPShiftRightUnsignVariableImmed(void *Variable, uint8_t Immediate) {
+ OPCODE_REG_VARIABLE(,8,0xC1,OP_D5,Variable);
+ PUTDST8(RSPRecompPos,Immediate);
+}
+
+void RSPSetzVariable(void *Variable) {
+ OPCODE_REG_VARIABLE(,16,0x940F,OP_D0,Variable);
+}
+
+void RSPSetnzVariable(void *Variable) {
+ OPCODE_REG_VARIABLE(,16,0x950F,OP_D0,Variable);
+}
+
+void RSPSetleVariable(void *Variable) {
+ RSPBreakPoint();
+ OPCODE_REG_VARIABLE(,16,0x9E0F,OP_D0,Variable);
+}
+
+void RSPSetgeVariable(void *Variable) {
+ RSPBreakPoint();
+ OPCODE_REG_VARIABLE(,16,0x9D0F,OP_D0,Variable);
+}
+
+void RSPSetz(int32_t x86reg) {
+ OPCODE_REG_REG(16,0x940F,OP_D0,x86reg);
+}
+
+void RSPSetnz(int32_t x86reg) {
+ OPCODE_REG_REG(16,0x950F,OP_D0,x86reg);
+}
+
+void RSPShiftLeftDouble(int32_t Destination, int32_t Source) {
+ OPCODE_REG_REG(16,0xA50F,Source,Destination);
+}
+
+void RSPShiftLeftDoubleImmed(int32_t Destination, int32_t Source, uint8_t Immediate) {
+ OPCODE_REG_REG(16,0xA40F,Source,Destination);
+ PUTDST8(RSPRecompPos,Immediate);
+}
+
+void RSPShiftLeftSign(int32_t x86reg) {
+ OPCODE_REG_REG(8,0xD3,OP_D4,x86reg);
+}
+
+void RSPShiftLeftSignImmed(int32_t x86reg, uint8_t Immediate) {
+ OPCODE_REG_REG(8,0xC1,OP_D4,x86reg);
+ PUTDST8(RSPRecompPos,Immediate);
+}
+
+void RSPShiftRightSign(int32_t x86reg) {
+ OPCODE_REG_REG(8,0xD3,OP_D7,x86reg);
+}
+
+void RSPShiftRightSignImmed(int32_t x86reg, uint8_t Immediate) {
+ OPCODE_REG_REG(8,0xC1,OP_D7,x86reg);
+ PUTDST8(RSPRecompPos,Immediate);
+}
+
+void RSPShiftRightUnsign(int32_t x86reg) {
+ OPCODE_REG_REG(8,0xD3,OP_D5,x86reg);
+}
+
+void RSPShiftRightDouble(int32_t Destination, int32_t Source) {
+ OPCODE_REG_REG(16,0xAD0F,Source,Destination);
+}
+
+void RSPShiftRightDoubleImmed(int32_t Destination, int32_t Source, uint8_t Immediate) {
+ OPCODE_REG_REG(16,0xAC0F,Source,Destination);
+ PUTDST8(RSPRecompPos,Immediate);
+}
+
+void RSPShiftRightUnsignImmed(int32_t x86reg, uint8_t Immediate) {
+ OPCODE_REG_REG(8,0xC1,OP_D5,x86reg);
+ PUTDST8(RSPRecompPos,Immediate);
+}
+
+void RSPSbbConstFromX86Reg (int32_t x86reg, uint32_t Const) {
+RSPBreakPoint();
+
+ if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) {
+ OPCODE_REG_REG(8,0x81,OP_D3,x86reg);
+ PUTDST32(RSPRecompPos, Const);
+ } else {
+ OPCODE_REG_REG(8,0x83,OP_D3,x86reg);
+ PUTDST8(RSPRecompPos, Const);
+ }
+}
+
+void RSPSbbVariableFromX86reg(int32_t x86reg, void * Variable) {
+ RSPBreakPoint();
+ OPCODE_REG_VARIABLE(,8,0x1B,x86reg,Variable);
+}
+
+void RSPSbbX86RegToX86Reg(int32_t Destination, int32_t Source) {
+ OPCODE_REG_REG(8,0x1B,Destination,Source);
+}
+
+void RSPSubConstFromVariable (uint32_t Const, void *Variable) {
+ OPCODE_REG_VARIABLE(,8,0x81,OP_D5,Variable);
+ PUTDST32(RSPRecompPos,Const);
+}
+
+void RSPSubConstFromX86Reg (int32_t x86reg, uint32_t Const) {
+ if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) {
+ OPCODE_REG_REG(8,0x81,OP_D5,x86reg);
+ PUTDST32(RSPRecompPos, Const);
+ } else {
+ OPCODE_REG_REG(8,0x83,OP_D5,x86reg);
+ PUTDST8(RSPRecompPos, Const);
+ }
+}
+
+void RSPSubVariableFromX86reg(int32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x2B,x86reg,Variable);
+}
+
+void RSPSubX86RegToX86Reg(int32_t Destination, int32_t Source) {
+ OPCODE_REG_REG(8,0x2B,Destination,Source);
+}
+
+void RSPTestConstToX86Reg(uint32_t Const, int32_t x86reg) {
+ OPCODE_REG_REG(8,0xF7,OP_D0,x86reg);
+ PUTDST32(RSPRecompPos,Const);
+}
+
+void RSPTestVariable(uint32_t Const, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0xf7,OP_D0,Variable);
+ PUTDST32(RSPRecompPos,Const);
+}
+
+void RSPTestX86RegToX86Reg(int32_t Destination, int32_t Source) {
+ OPCODE_REG_REG(8,0x85,Destination,Source);
+}
+
+void RSPTestVariableToX86Reg(uint32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x85,x86reg,Variable);
+}
+
+void RSPXorConstToX86Reg(int32_t x86reg, uint32_t Const) {
+ if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) {
+ OPCODE_REG_REG(8,0x81,OP_D6,x86reg);
+ PUTDST32(RSPRecompPos, Const);
+ } else {
+ OPCODE_REG_REG(8,0x83,OP_D6,x86reg);
+ PUTDST8(RSPRecompPos, Const);
+ }
+}
+
+
+void RSPXorX86RegToX86Reg(int32_t Source, int32_t Destination) {
+ OPCODE_REG_REG(8,0x31,Destination,Source);
+}
+
+void RSPXorVariableToX86reg(void *Variable, int32_t x86reg) {
+ RSPBreakPoint();
+ OPCODE_REG_VARIABLE(,8,0x33,x86reg,Variable);
+}
+
+
+void RSPXorConstToVariable(void *Variable, uint32_t Const) {
+ OPCODE_REG_VARIABLE(,8,0x81,OP_D6,Variable);
+ PUTDST32(RSPRecompPos,Const);
+}
+
+// ********************************************************************************************
+
+void RSPAndX86RegToVariable(void * Variable, int32_t x86Reg) {
+ OPCODE_REG_VARIABLE(,8,0x21,x86Reg,Variable);
+}
+
+void RSPXorX86RegToVariable(void *Variable, int32_t x86reg) {
+ OPCODE_REG_VARIABLE(,8,0x31,x86reg,Variable);
+}
+
+void RSPTestConstToVariable(uint32_t Const, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0xf7,OP_D0,Variable);
+ PUTDST32(RSPRecompPos,Const);
+}
+
+void RSPCondMoveGreaterEqual(int32_t Destination, int32_t Source) {
+ if (ConditionalMove == 0) {
+ uint8_t * Jump;
+ // CPU_Message(" [*]cmovge %s, %s",x86_Name(Destination),x86_Name(Source));
+
+ RSPJlLabel8(0);
+ Jump = RSPRecompPos - 1;
+ RSPMoveX86RegToX86Reg(Source, Destination);
+ // CPU_Message(" label:");
+ RSPx86_SetBranch8b(Jump, RSPRecompPos);
+ } else {
+ uint8_t x86Command;
+ // CPU_Message(" cmovge %s, %s",x86_Name(Destination),x86_Name(Source));
+
+ PUTDST16(RSPRecompPos,0x4D0F);
+
+ switch (Source&0xf) {
+ case x86_EAX: x86Command = 0x00; break;
+ case x86_EBX: x86Command = 0x03; break;
+ case x86_ECX: x86Command = 0x01; break;
+ case x86_EDX: x86Command = 0x02; break;
+ case x86_ESI: x86Command = 0x06; break;
+ case x86_EDI: x86Command = 0x07; break;
+ case x86_ESP: x86Command = 0x04; break;
+ case x86_EBP: x86Command = 0x05; break;
+ }
+
+ switch (Destination&0xf) {
+ case x86_EAX: x86Command += 0xC0; break;
+ case x86_EBX: x86Command += 0xD8; break;
+ case x86_ECX: x86Command += 0xC8; break;
+ case x86_EDX: x86Command += 0xD0; break;
+ case x86_ESI: x86Command += 0xF0; break;
+ case x86_EDI: x86Command += 0xF8; break;
+ case x86_ESP: x86Command += 0xE0; break;
+ case x86_EBP: x86Command += 0xE8; break;
+ }
+
+ PUTDST8(RSPRecompPos, x86Command);
+ }
+}
+
+void RSPMoveX86regPointerToX86regByte(int32_t Destination, int32_t AddrReg) {
+ uint8_t x86Command = 0;
+
+ // CPU_Message(" mov %s, byte ptr [%s]",x86Byte_Name(Destination), x86_Name(AddrReg));
+
+ switch (AddrReg&0xf) {
+ case x86_EAX: x86Command = 0x00; break;
+ case x86_EBX: x86Command = 0x03; break;
+ case x86_ECX: x86Command = 0x01; break;
+ case x86_EDX: x86Command = 0x02; break;
+ case x86_ESI: x86Command = 0x06; break;
+ case x86_EDI: x86Command = 0x07; break;
+ default: DisplayError("MoveX86regPointerToX86regByte\nUnknown x86 Register");
+ }
+
+ switch (Destination&0xf) {
+ case x86_EAX: x86Command += 0x00; break;
+ case x86_EBX: x86Command += 0x18; break;
+ case x86_ECX: x86Command += 0x08; break;
+ case x86_EDX: x86Command += 0x10; break;
+ default: DisplayError("MoveX86regPointerToX86regByte\nUnknown x86 Register");
+ }
+
+ PUTDST8(RSPRecompPos, 0x8A);
+ PUTDST8(RSPRecompPos, x86Command);
+}
+
+void RSPMoveX86regToN64MemDisp(int32_t x86reg, int32_t AddrReg, uint8_t Disp) {
+#ifdef USEX64
+ if(((uintptr_t)DMEM - (uintptr_t)TLB_Map) < 0x7FFFFFFF) {
+ OPCODE_REG_BASE_INDEX_IMM32(8,0x89,x86reg,x86_R15,AddrReg,((uintptr_t)DMEM - (uintptr_t)TLB_Map) + Disp);
+ } else {
+ LOAD_VARIABLE(x86_TEMP, DMEM);
+ OPCODE_REG_MREG_IMM8(8,0xf7,x86reg,x86_TEMP,Disp);
+ }
+#else
+ OPCODE_REG_MREG_IMM32(8,0x89,x86reg,AddrReg,DMEM + Disp);
+#endif
+}
+
+void RSPOrVariableToX86regHalf(void * Variable, int32_t x86Reg) {
+ OPCODE_REG_VARIABLE(PUTDST8(RSPRecompPos,0x66),8,0xb,x86Reg,Variable);
+}
+
+void RSPAndVariableToX86regHalf(void * Variable, int32_t x86Reg) {
+ OPCODE_REG_VARIABLE(PUTDST8(RSPRecompPos,0x66),8,0x23,x86Reg,Variable);
+}
+
+void RSPAndX86RegHalfToX86RegHalf(int32_t Destination, int32_t Source) {
+ PUTDST8(RSPRecompPos, 0x66);
+ OPCODE_REG_REG(8,0x21,Source,Destination);
+}
+
+void RSPCondMoveNotEqual(int32_t Destination, int32_t Source) {
+ if (ConditionalMove == 0) {
+ uint8_t * Jump;
+ // CPU_Message(" [*]cmovne %s, %s",x86_Name(Destination),x86_Name(Source));
+
+ RSPJeLabel8(0);
+ Jump = RSPRecompPos - 1;
+ RSPMoveX86RegToX86Reg(Source, Destination);
+ // CPU_Message(" label:");
+ RSPx86_SetBranch8b(Jump, RSPRecompPos);
+ } else {
+ uint8_t x86Command;
+ // CPU_Message(" cmovne %s, %s",x86_Name(Destination),x86_Name(Source));
+
+ PUTDST16(RSPRecompPos,0x450F);
+
+ switch (Source&0xf) {
+ case x86_EAX: x86Command = 0x00; break;
+ case x86_EBX: x86Command = 0x03; break;
+ case x86_ECX: x86Command = 0x01; break;
+ case x86_EDX: x86Command = 0x02; break;
+ case x86_ESI: x86Command = 0x06; break;
+ case x86_EDI: x86Command = 0x07; break;
+ case x86_ESP: x86Command = 0x04; break;
+ case x86_EBP: x86Command = 0x05; break;
+ }
+
+ switch (Destination&0xf) {
+ case x86_EAX: x86Command += 0xC0; break;
+ case x86_EBX: x86Command += 0xD8; break;
+ case x86_ECX: x86Command += 0xC8; break;
+ case x86_EDX: x86Command += 0xD0; break;
+ case x86_ESI: x86Command += 0xF0; break;
+ case x86_EDI: x86Command += 0xF8; break;
+ case x86_ESP: x86Command += 0xE0; break;
+ case x86_EBP: x86Command += 0xE8; break;
+ }
+
+ PUTDST8(RSPRecompPos, x86Command);
+ }
+}
+
+
+void RSPNegateX86reg(int32_t x86reg) {
+ // CPU_Message(" neg %s", x86_Name(x86reg));
+ switch (x86reg&0xf) {
+ case x86_EAX: PUTDST16(RSPRecompPos,0xd8f7); break;
+ case x86_EBX: PUTDST16(RSPRecompPos,0xdbf7); break;
+ case x86_ECX: PUTDST16(RSPRecompPos,0xd9f7); break;
+ case x86_EDX: PUTDST16(RSPRecompPos,0xdaf7); break;
+ case x86_ESI: PUTDST16(RSPRecompPos,0xdef7); break;
+ case x86_EDI: PUTDST16(RSPRecompPos,0xdff7); break;
+ case x86_ESP: PUTDST16(RSPRecompPos,0xdcf7); break;
+ case x86_EBP: PUTDST16(RSPRecompPos,0xddf7); break;
+ default:
+ DisplayError("NegateX86reg\nUnknown x86 Register");
+ }
+}
+
+
+void RSPImulX86RegToX86Reg(int32_t Destination, int32_t Source) {
+ uint8_t x86Command;
+
+ // CPU_Message(" imul %s, %s",x86_Name(Destination), x86_Name(Source));
+
+ switch (Source&0xf) {
+ case x86_EAX: x86Command = 0x00; break;
+ case x86_EBX: x86Command = 0x03; break;
+ case x86_ECX: x86Command = 0x01; break;
+ case x86_EDX: x86Command = 0x02; break;
+ case x86_ESI: x86Command = 0x06; break;
+ case x86_EDI: x86Command = 0x07; break;
+ case x86_ESP: x86Command = 0x04; break;
+ case x86_EBP: x86Command = 0x05; break;
+ }
+
+ switch (Destination&0xf) {
+ case x86_EAX: x86Command += 0xC0; break;
+ case x86_EBX: x86Command += 0xD8; break;
+ case x86_ECX: x86Command += 0xC8; break;
+ case x86_EDX: x86Command += 0xD0; break;
+ case x86_ESI: x86Command += 0xF0; break;
+ case x86_EDI: x86Command += 0xF8; break;
+ case x86_ESP: x86Command += 0xE0; break;
+ case x86_EBP: x86Command += 0xE8; break;
+ }
+
+ PUTDST16(RSPRecompPos, 0xAF0F);
+ PUTDST8(RSPRecompPos, x86Command);
+}
+
+
+void RSPMoveX86RegToX86regPointerDisp ( int32_t Source, int32_t AddrReg, uint8_t Disp ) {
+ OPCODE_REG_MREG_IMM8(8,0x89,Source,AddrReg,Disp);
+}
+
+void RSPCondMoveGreater(int32_t Destination, int32_t Source) {
+ if (ConditionalMove == 0) {
+ uint8_t * Jump;
+ // CPU_Message(" [*]cmovg %s, %s",x86_Name(Destination),x86_Name(Source));
+
+ RSPJleLabel8(0);
+ Jump = RSPRecompPos - 1;
+ RSPMoveX86RegToX86Reg(Source, Destination);
+ // CPU_Message(" label:");
+ RSPx86_SetBranch8b(Jump, RSPRecompPos);
+ } else {
+ uint8_t x86Command;
+ // CPU_Message(" cmovg %s, %s",x86_Name(Destination),x86_Name(Source));
+
+ PUTDST16(RSPRecompPos,0x4F0F);
+
+ switch (Source&0xf) {
+ case x86_EAX: x86Command = 0x00; break;
+ case x86_EBX: x86Command = 0x03; break;
+ case x86_ECX: x86Command = 0x01; break;
+ case x86_EDX: x86Command = 0x02; break;
+ case x86_ESI: x86Command = 0x06; break;
+ case x86_EDI: x86Command = 0x07; break;
+ case x86_ESP: x86Command = 0x04; break;
+ case x86_EBP: x86Command = 0x05; break;
+ }
+
+ switch (Destination&0xf) {
+ case x86_EAX: x86Command += 0xC0; break;
+ case x86_EBX: x86Command += 0xD8; break;
+ case x86_ECX: x86Command += 0xC8; break;
+ case x86_EDX: x86Command += 0xD0; break;
+ case x86_ESI: x86Command += 0xF0; break;
+ case x86_EDI: x86Command += 0xF8; break;
+ case x86_ESP: x86Command += 0xE0; break;
+ case x86_EBP: x86Command += 0xE8; break;
+ }
+
+ PUTDST8(RSPRecompPos, x86Command);
+ }
+}
+
+void RSPCondMoveLess(int32_t Destination, int32_t Source) {
+ if (ConditionalMove == 0) {
+ uint8_t * Jump;
+ // CPU_Message(" [*]cmovl %s, %s",x86_Name(Destination),x86_Name(Source));
+
+ RSPJgeLabel8(0);
+ Jump = RSPRecompPos - 1;
+ RSPMoveX86RegToX86Reg(Source, Destination);
+ // CPU_Message(" label:");
+ RSPx86_SetBranch8b(Jump, RSPRecompPos);
+ } else {
+ uint8_t x86Command;
+ // CPU_Message(" cmovl %s, %s",x86_Name(Destination),x86_Name(Source));
+
+ PUTDST16(RSPRecompPos,0x4C0F);
+
+ switch (Source&0xf) {
+ case x86_EAX: x86Command = 0x00; break;
+ case x86_EBX: x86Command = 0x03; break;
+ case x86_ECX: x86Command = 0x01; break;
+ case x86_EDX: x86Command = 0x02; break;
+ case x86_ESI: x86Command = 0x06; break;
+ case x86_EDI: x86Command = 0x07; break;
+ case x86_ESP: x86Command = 0x04; break;
+ case x86_EBP: x86Command = 0x05; break;
+ }
+
+ switch (Destination&0xf) {
+ case x86_EAX: x86Command += 0xC0; break;
+ case x86_EBX: x86Command += 0xD8; break;
+ case x86_ECX: x86Command += 0xC8; break;
+ case x86_EDX: x86Command += 0xD0; break;
+ case x86_ESI: x86Command += 0xF0; break;
+ case x86_EDI: x86Command += 0xF8; break;
+ case x86_ESP: x86Command += 0xE0; break;
+ case x86_EBP: x86Command += 0xE8; break;
+ }
+
+ PUTDST8(RSPRecompPos, x86Command);
+ }
+}
+
+void RSPMoveSxX86RegPtrDispToX86RegHalf(int32_t AddrReg, uint8_t Disp, int32_t Destination) {
+ OPCODE_REG_MREG_IMM8(16,0xBF0F,Destination,AddrReg,Disp);
+
+}
+
+
+void RSPMoveZxX86RegPtrDispToX86RegHalf(int32_t AddrReg, uint8_t Disp, int32_t Destination) {
+ OPCODE_REG_MREG_IMM8(16,0xB70F,Destination,AddrReg,Disp);
+}
+
+
+void RSPMoveX86regHalfToX86regPointerDisp(int32_t Source, int32_t AddrReg, uint8_t Disp) {
+ uint8_t x86Amb;
+
+ // CPU_Message(" mov word ptr [%s+%X], %s",x86_Name(AddrReg), Disp, x86Half_Name(Source));
+
+ switch (AddrReg&0xf) {
+ case x86_EAX: x86Amb = 0x00; break;
+ case x86_EBX: x86Amb = 0x03; break;
+ case x86_ECX: x86Amb = 0x01; break;
+ case x86_EDX: x86Amb = 0x02; break;
+ case x86_ESI: x86Amb = 0x06; break;
+ case x86_EDI: x86Amb = 0x07; break;
+ case x86_ESP: x86Amb = 0x04; break;
+ case x86_EBP: x86Amb = 0x05; break;
+ default: DisplayError("MoveX86regBytePointer\nUnknown x86 Register");
+ }
+
+ switch (Source&0xf) {
+ case x86_EAX: x86Amb += 0x00; break;
+ case x86_ECX: x86Amb += 0x08; break;
+ case x86_EDX: x86Amb += 0x10; break;
+ case x86_EBX: x86Amb += 0x18; break;
+ case x86_ESI: x86Amb += 0x30; break;
+ case x86_EDI: x86Amb += 0x38; break;
+ case x86_ESP: x86Amb += 0x20; break;
+ case x86_EBP: x86Amb += 0x28; break;
+ default: DisplayError("MoveX86regBytePointer\nUnknown x86 Register");
+ }
+
+ PUTDST16(RSPRecompPos, 0x8966);
+ PUTDST8(RSPRecompPos, x86Amb | 0x40);
+ PUTDST8(RSPRecompPos, Disp);
+}
+
+void RSPCondMoveEqual(int32_t Destination, int32_t Source) {
+ if (ConditionalMove == 0) {
+ uint8_t * Jump;
+ // CPU_Message(" [*]cmove %s, %s",x86_Name(Destination),x86_Name(Source));
+
+ RSPJneLabel8(0);
+ Jump = RSPRecompPos - 1;
+ RSPMoveX86RegToX86Reg(Source, Destination);
+ // CPU_Message(" label:");
+ RSPx86_SetBranch8b(Jump, RSPRecompPos);
+ } else {
+ uint8_t x86Command;
+ // CPU_Message(" cmove %s, %s",x86_Name(Destination),x86_Name(Source));
+
+ PUTDST16(RSPRecompPos,0x440F);
+
+ switch (Source&0xf) {
+ case x86_EAX: x86Command = 0x00; break;
+ case x86_EBX: x86Command = 0x03; break;
+ case x86_ECX: x86Command = 0x01; break;
+ case x86_EDX: x86Command = 0x02; break;
+ case x86_ESI: x86Command = 0x06; break;
+ case x86_EDI: x86Command = 0x07; break;
+ case x86_ESP: x86Command = 0x04; break;
+ case x86_EBP: x86Command = 0x05; break;
+ }
+
+ switch (Destination&0xf) {
+ case x86_EAX: x86Command += 0xC0; break;
+ case x86_EBX: x86Command += 0xD8; break;
+ case x86_ECX: x86Command += 0xC8; break;
+ case x86_EDX: x86Command += 0xD0; break;
+ case x86_ESI: x86Command += 0xF0; break;
+ case x86_EDI: x86Command += 0xF8; break;
+ case x86_ESP: x86Command += 0xE0; break;
+ case x86_EBP: x86Command += 0xE8; break;
+ }
+
+ PUTDST8(RSPRecompPos, x86Command);
+ }
+}
+
+
+void RSPCwd(void) {
+ // CPU_Message(" cwd");
+ PUTDST16(RSPRecompPos, 0x9966);
+}
+
+void RSPCwde(void) {
+ // CPU_Message(" cwde");
+ PUTDST8(RSPRecompPos, 0x98);
+}
+
+void RSPSubX86regFromVariable(int32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x29,x86reg,Variable);
+}
+
+void RSPJumpX86Reg( int32_t x86reg ) {
+ // CPU_Message(" jmp %s",x86_Name(x86reg));
+/*
+ switch (x86reg) {
+ case x86_EAX: PUTDST16(RSPRecompPos,0xe0ff); break;
+ case x86_EBX: PUTDST16(RSPRecompPos,0xe3ff); break;
+ case x86_ECX: PUTDST16(RSPRecompPos,0xe1ff); break;
+ case x86_EDX: PUTDST16(RSPRecompPos,0xe2ff); break;
+ case x86_ESI: PUTDST16(RSPRecompPos,0xe6ff); break;
+ case x86_EDI: PUTDST16(RSPRecompPos,0xe7ff); break;
+ default: DisplayError("JumpX86Reg: Unknown reg (%08x)", x86reg); Int3();
+ }*/
+ OPCODE_REG_REG(8,0xFF,OP_D4,x86reg);
+}
+
+
+
+
+void RSPJgeLabel8(uint8_t Value) {
+ PUTDST8(RSPRecompPos,0x7D);
+ PUTDST8(RSPRecompPos,Value);
+}
+
diff --git a/src/usf/rsp_x86.h b/src/usf/rsp_x86.h new file mode 100644 index 0000000..0b7df86 --- /dev/null +++ b/src/usf/rsp_x86.h @@ -0,0 +1,552 @@ +/*
+ * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator).
+ *
+ * (c) Copyright 2001 jabo (jabo@emulation64.com) and
+ * zilmar (zilmar@emulation64.com)
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+
+/*enum x86RegValues {
+ x86_EAX = 0, x86_EBX = 1, x86_ECX = 2, x86_EDX = 3,
+ x86_ESI = 4, x86_EDI = 5, x86_EBP = 6, x86_ESP = 7
+};*/
+
+#include "types.h"
+
+enum mmxRegValues {
+ x86_MM0 = 1, x86_MM1 = 2, x86_MM2 = 3, x86_MM3 = 4,
+ x86_MM4 = 5, x86_MM5 = 6, x86_MM6 = 7, x86_MM7 = 8
+};
+
+enum sseRegValues {
+ x86_XMM0 = 1, x86_XMM1 = 2, x86_XMM2 = 3, x86_XMM3 = 4,
+ x86_XMM4 = 5, x86_XMM5 = 6, x86_XMM6 = 7, x86_XMM7 = 8
+};
+
+#ifdef USEX64
+enum x86RegValues {
+
+ x86_Any = 0,
+ x86_EAX,x86_ECX,x86_EDX,x86_EBX,x86_ESP,x86_EBP,x86_ESI,x86_EDI,x86_Any8Bit=0x40,x64_Any = 0x40,
+
+ x86_RAX = 0x11,x86_RCX,x86_RDX,x86_RBX,x86_RSP,x86_RBP,x86_RSI,x86_RDI,
+
+ x86_R8D = 0x21,x86_R9D,x86_R10D,x86_R11D,x86_R12D,x86_R13D,x86_R14D,x86_R15D,
+
+ x86_R8 = 0x31,x86_R9,x86_R10,x86_R11,x86_R12,x86_R13,x86_R14,x86_R15,
+
+};
+
+enum x86FpuValues {
+ x86_ST0,x86_ST1,x86_ST2,x86_ST3,x86_ST4,x86_ST5,x86_ST6,x86_ST7
+};
+
+#define x86_TEMP x86_R8
+#define x86_TEMPD x86_R8D
+
+#define OP_D0 1
+#define OP_D1 2
+#define OP_D2 3
+#define OP_D3 4
+#define OP_D4 5
+#define OP_D5 6
+#define OP_D6 7
+#define OP_D7 8
+
+#define LOAD_VARIABLE(reg,variable) \
+ PUTDST8(RSPRecompPos, 0x48 | (((reg)&0x20)>>5)); \
+ PUTDST8(RSPRecompPos,0xB8 | ((reg)-1)&0xf); \
+ PUTDST64(RSPRecompPos,variable);
+
+// // 43 0F B6 0C 0D 40 83 C7 04 movzx ecx,byte ptr [r9+4C78340h]
+
+#define OPCODE_REG_REG(oplen,opcode,reg,rm) \
+ PUTDST8(RSPRecompPos, 0x40 | (((rm)&0x20)>>5) | ((((rm|reg))&0x10)>>1) | (((reg)&0x20)>>3)); \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ PUTDST8(RSPRecompPos, 0xC0 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3));
+
+#define OPCODE_REG_MREG(oplen,opcode,reg,rm) \
+ PUTDST8(RSPRecompPos, 0x40 | (((rm)&0x20)>>5) | (((reg)&0x10)>>1) | (((reg)&0x20)>>3)); \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ if(((rm)&0xf)==0x6) { \
+ PUTDST8(RSPRecompPos, 0x40 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, 0); \
+ } else if(((rm)&0xf)==0x5) { \
+ PUTDST8(RSPRecompPos, 0x0 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, 0x24); \
+ } else { \
+ PUTDST8(RSPRecompPos, 0x00 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ }
+
+#define OPCODE_REG_MREG_IMM32(oplen,opcode,reg,rm,imm32) \
+ PUTDST8(RSPRecompPos, 0x40 | (((rm)&0x20)>>5) | (((reg)&0x10)>>1) | (((reg)&0x20)>>3)); \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ if(((rm)&0xf)==0x5) { \
+ PUTDST8(RSPRecompPos, 0x80 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, 0x24); \
+ } else { \
+ PUTDST8(RSPRecompPos, 0x80 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ } \
+ PUTDST32(RSPRecompPos,imm32);
+
+#define OPCODE_REG_BASE_INDEX(oplen,opcode,reg,base,index) \
+ PUTDST8(RSPRecompPos, 0x40 | (((base)&0x20)>>5) | (((reg)&0x10)>>1) | (((reg)&0x20)>>3)| (((index)&0x20)>>4)); \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ if(((base)&0xf)!=0x6) { \
+ PUTDST8(RSPRecompPos, 0x04 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, 0x00 | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ } else {\
+ PUTDST8(RSPRecompPos, 0x44 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, 0x00 | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST8(RSPRecompPos, 0); \
+ }
+
+#define OPCODE_REG_MREG_IMM8(oplen,opcode,reg,rm,imm8) \
+ PUTDST8(RSPRecompPos, 0x40 | (((rm)&0x20)>>5) | (((reg)&0x10)>>1) | (((reg)&0x20)>>3)); \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ PUTDST8(RSPRecompPos, 0x40 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos,imm8);
+
+/*scale is: 0=1,0x40=2,0x80=4,0xc0=8 ??*/
+
+#define OPCODE_REG_INDEX_SCALE(oplen,opcode,reg,base,index,scale) \
+ PUTDST8(RSPRecompPos, 0x40 | (((base)&0x20)>>5) | (((reg)&0x10)>>1) | (((reg)&0x20)>>3)| (((index)&0x20)>>4)); \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ PUTDST8(RSPRecompPos, 0x04 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, (((scale)-1)*0x40) | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) );
+
+#define OPCODE_REG_BASE_INDEX_SCALE(oplen,opcode,reg,base,index,scale) \
+ PUTDST8(RSPRecompPos, 0x40 | (((base)&0x20)>>5) | (((reg)&0x10)>>1) | (((reg)&0x20)>>3)| (((index)&0x20)>>4)); \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ PUTDST8(RSPRecompPos, 0x04 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, (scale) | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) );
+
+#define OPCODE_REG_BASE_INDEX_SCALE_IMM32(oplen,opcode,reg,base,index,scale,imm32) \
+ PUTDST8(RSPRecompPos, 0x40 | (((base)&0x20)>>5) | (((reg)&0x10)>>1) | (((reg)&0x20)>>3)| (((index)&0x20)>>4)); \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ PUTDST8(RSPRecompPos, 0x84 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, (scale) | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST32(RSPRecompPos,imm32);
+
+#define OPCODE_REG_BASE_INDEX_SCALE_IMM8(oplen,opcode,reg,base,index,scale,imm32) \
+ PUTDST8(RSPRecompPos, 0x40 | (((base)&0x20)>>5) | (((reg)&0x10)>>1) | (((reg)&0x20)>>3)| (((index)&0x20)>>4)); \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ PUTDST8(RSPRecompPos, 0x44 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, (scale) | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST32(RSPRecompPos,imm32);
+
+
+
+#define OPCODE_REG_BASE_INDEX_IMM8(oplen,opcode,reg,base,index,imm8) \
+ PUTDST8(RSPRecompPos, 0x40 | (((base)&0x20)>>5) | (((reg)&0x10)>>1) | (((reg)&0x20)>>3)| (((index)&0x20)>>4)); \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ PUTDST8(RSPRecompPos, 0x44 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST8(RSPRecompPos, imm8);
+
+#define OPCODE_REG_BASE_INDEX_IMM32(oplen,opcode,reg,base,index,imm32) \
+ PUTDST8(RSPRecompPos, 0x40 | (((base)&0x20)>>5) | (((reg)&0x10)>>1) | (((reg)&0x20)>>3)| (((index)&0x20)>>4)); \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ PUTDST8(RSPRecompPos, 0x84 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST32(RSPRecompPos, imm32);
+
+#else
+
+enum x86RegValues {
+
+ x86_Any = 0,
+ x86_EAX,x86_ECX,x86_EDX,x86_EBX,x86_ESP,x86_EBP,x86_ESI,x86_EDI,x86_Any8Bit=0x40,x64_Any = 0x0,
+ x86_RAX = 0x1,x86_RCX,x86_RDX,x86_RBX,x86_RSP,x86_RBP,x86_RSI,x86_RDI,
+
+};
+
+enum x86FpuValues {
+ x86_ST0,x86_ST1,x86_ST2,x86_ST3,x86_ST4,x86_ST5,x86_ST6,x86_ST7
+};
+
+
+#define OP_D0 1
+#define OP_D1 2
+#define OP_D2 3
+#define OP_D3 4
+#define OP_D4 5
+#define OP_D5 6
+#define OP_D6 7
+#define OP_D7 8
+
+// // 43 0F B6 0C 0D 40 83 C7 04 movzx ecx,byte ptr [r9+4C78340h]
+
+
+#define OPCODE_REG_DISP(oplen,opcode,reg,disp32) \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ PUTDST8(RSPRecompPos, 0x5 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST32(RSPRecompPos,disp32);
+
+
+#define OPCODE_REG_REG(oplen,opcode,reg,rm) \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ PUTDST8(RSPRecompPos, 0xC0 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3));
+
+#define OPCODE_REG_MREG(oplen,opcode,reg,rm) \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ if(((rm)&0xf)==0x6) { \
+ PUTDST8(RSPRecompPos, 0x40 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, 0); \
+ } else if(((rm)&0xf)==0x5) { \
+ PUTDST8(RSPRecompPos, 0x0 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, 0x24); \
+ } else { \
+ PUTDST8(RSPRecompPos, 0x00 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ }
+
+#define OPCODE_REG_MREG_IMM32(oplen,opcode,reg,rm,imm32) \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ if(((rm)&0xf)==0x5) { \
+ PUTDST8(RSPRecompPos, 0x80 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, 0x24); \
+ } else { \
+ PUTDST8(RSPRecompPos, 0x80 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ } \
+ PUTDST32(RSPRecompPos,imm32);
+
+#define OPCODE_REG_BASE_INDEX(oplen,opcode,reg,base,index) \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ if(((base)&0xf)!=0x6) { \
+ PUTDST8(RSPRecompPos, 0x04 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, 0x00 | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ } else {\
+ PUTDST8(RSPRecompPos, 0x44 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, 0x00 | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST8(RSPRecompPos, 0); \
+ }
+
+#define OPCODE_REG_MREG_IMM8(oplen,opcode,reg,rm,imm8) \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ PUTDST8(RSPRecompPos, 0x40 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos,imm8);
+
+#define OPCODE_REG_INDEX_SCALE(oplen,opcode,reg,base,index,scale) \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ PUTDST8(RSPRecompPos, 0x04 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, (((scale)-1)*0x40) | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) );
+
+#define OPCODE_REG_BASE_INDEX_SCALE(oplen,opcode,reg,base,index,scale) \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ PUTDST8(RSPRecompPos, 0x04 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, (scale) | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) );
+
+#define OPCODE_REG_BASE_INDEX_SCALE_IMM32(oplen,opcode,reg,base,index,scale,imm32) \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ PUTDST8(RSPRecompPos, 0x84 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, (scale) | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST32(RSPRecompPos,imm32);
+
+#define OPCODE_REG_BASE_INDEX_SCALE_IMM8(oplen,opcode,reg,base,index,scale,imm32) \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ PUTDST8(RSPRecompPos, 0x44 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, (scale) | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST32(RSPRecompPos,imm32);
+
+
+#define OPCODE_REG_BASE_INDEX_IMM8(oplen,opcode,reg,base,index,imm8) \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ PUTDST8(RSPRecompPos, 0x44 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST8(RSPRecompPos, imm8);
+
+#define OPCODE_REG_BASE_INDEX_IMM32(oplen,opcode,reg,base,index,imm32) \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ PUTDST8(RSPRecompPos, 0x84 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST32(RSPRecompPos, imm32);
+
+#define OPCODE_REG_INDEX_SCALE_IMM32(oplen,opcode,reg,index,scale,imm32) \
+ PUTDST##oplen (RSPRecompPos, opcode); \
+ PUTDST8(RSPRecompPos, 0x4 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RSPRecompPos, 0x5 | (scale) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST32(RSPRecompPos,imm32);
+
+#endif
+
+
+#ifndef USEX64
+
+#define OPCODE_REG_VARIABLE(PREFIX,oplen,opcode,reg,variable) \
+ PREFIX \
+ OPCODE_REG_DISP(oplen,opcode,reg,variable);
+
+#define OPCODE_REG_ADDR_DMEM(PREFIX,oplen,opcode,reg,addr) \
+ PREFIX \
+ OPCODE_REG_MREG_IMM32(oplen,opcode,reg,addr,DMEM);
+
+#else
+
+#define OPCODE_REG_VARIABLE(PREFIX,oplen,opcode,reg,Variable) \
+ if(((uintptr_t)(Variable) - (uintptr_t)TLB_Map) < 0x7FFFFFFF) { \
+ PREFIX \
+ OPCODE_REG_MREG_IMM32(oplen,opcode,reg,x86_R15,(uintptr_t)(Variable) - (uintptr_t)TLB_Map); \
+ } else { \
+ LOAD_VARIABLE(x86_TEMP, (Variable)); \
+ PREFIX \
+ OPCODE_REG_MREG(oplen,opcode,reg,x86_TEMP); \
+ }
+
+#define OPCODE_REG_ADDR_DMEM(PREFIX,oplen,opcode,reg,addr) \
+ if(((uintptr_t)(DMEM) - (uintptr_t)TLB_Map) < 0x7FFFFFFF) { \
+ PREFIX \
+ OPCODE_REG_BASE_INDEX_IMM32(oplen,opcode,reg,x86_R15,addr,(uintptr_t)(DMEM) - (uintptr_t)TLB_Map); \
+ } else { \
+ LOAD_VARIABLE(x86_TEMP, (DMEM)); \
+ PREFIX \
+ OPCODE_REG_BASE_INDEX(oplen,opcode,reg,x86_TEMP,addr); \
+ }
+
+#endif
+
+#ifdef USEX64
+ #define LOAD_FROM_DMEM(dstreg,srcreg) MoveX86RegDispToX86Reg(dstreg, x86_R15, srcreg, 8);
+#else
+ #define LOAD_FROM_DMEM(dstreg,srcreg) MoveVariableDispToX86Reg(DMEM,dstreg,srcreg,4);
+#endif
+
+
+void RSPAdcX86RegToX86Reg ( int32_t Destination, int32_t Source );
+void RSPAdcX86regToVariable ( int32_t x86reg, void * Variable );
+void RSPAdcX86regHalfToVariable ( int32_t x86reg, void * Variable );
+void RSPAdcConstToX86reg ( uint8_t Constant, int32_t x86reg );
+void RSPAdcConstToVariable ( void *Variable, uint8_t Constant );
+void RSPAdcConstHalfToVariable ( void *Variable, uint8_t Constant );
+void RSPAddConstToVariable ( uint32_t Const, void *Variable );
+void RSPAddConstToX86Reg ( int32_t x86Reg, uint32_t Const );
+void RSPAddQwordToX86Reg (int32_t x86reg, uint64_t Const);
+void RSPAddVariableToX86reg ( int32_t x86reg, void * Variable );
+void RSPAddX86regToVariable ( int32_t x86reg, void * Variable );
+void RSPAddX86regHalfToVariable ( int32_t x86reg, void * Variable );
+void RSPAddX86RegToX86Reg ( int32_t Destination, int32_t Source );
+void RSPAndConstToVariable ( uint32_t Const, void *Variable );
+void RSPAndConstToX86Reg ( int32_t x86Reg, uint32_t Const );
+void RSPAndVariableToX86Reg ( void * Variable, int32_t x86Reg );
+void RSPAndVariableToX86regHalf ( void * Variable, int32_t x86Reg );
+void RSPAndX86RegToVariable ( void * Variable, int32_t x86Reg );
+void RSPAndX86RegToX86Reg ( int32_t Destination, int32_t Source );
+void RSPAndX86RegHalfToX86RegHalf ( int32_t Destination, int32_t Source );
+void RSPBreakPoint (void);
+void RSPCall_Direct ( void * FunctAddress );
+void RSPCall_Indirect ( void * FunctAddress );
+void RSPCondMoveEqual ( int32_t Destination, int32_t Source );
+void RSPCondMoveNotEqual ( int32_t Destination, int32_t Source );
+void RSPCondMoveGreater ( int32_t Destination, int32_t Source );
+void RSPCondMoveGreaterEqual ( int32_t Destination, int32_t Source );
+void RSPCondMoveLess ( int32_t Destination, int32_t Source );
+void RSPCondMoveLessEqual ( int32_t Destination, int32_t Source );
+void RSPCompConstToVariable ( uint32_t Const, void * Variable );
+void RSPCompConstHalfToVariable ( uint16_t Const, void * Variable );
+void RSPCompConstToX86reg ( int32_t x86Reg, uint32_t Const );
+void RSPCompX86regToVariable ( int32_t x86Reg, void * Variable );
+void RSPCompVariableToX86reg ( int32_t x86Reg, void * Variable );
+void RSPCompX86RegToX86Reg ( int32_t Destination, int32_t Source );
+void RSPMoveConstQwordToX86reg ( uintptr_t, int32_t);
+void RSPCwd ( void );
+void RSPCwde ( void );
+void RSPDecX86reg ( int32_t x86Reg );
+void RSPDivX86reg ( int32_t x86reg );
+void RSPidivX86reg ( int32_t x86reg );
+void RSPimulX86reg ( int32_t x86reg );
+void RSPImulX86RegToX86Reg ( int32_t Destination, int32_t Source );
+void RSPIncX86reg ( int32_t x86Reg );
+void RSPJaeLabel32 ( uint32_t Value );
+void RSPJaLabel8 ( uint8_t Value );
+void RSPJaLabel32 ( uint32_t Value );
+void RSPJbLabel8 ( uint8_t Value );
+void RSPJbLabel32 ( uint32_t Value );
+void RSPJeLabel8 ( uint8_t Value );
+void RSPJeLabel32 ( uint32_t Value );
+void RSPJgeLabel8 ( uint8_t Value );
+void RSPJgeLabel32 ( uint32_t Value );
+void RSPJgLabel8 ( uint8_t Value );
+void RSPJgLabel32 ( uint32_t Value );
+void RSPJleLabel8 ( uint8_t Value );
+void RSPJleLabel32 ( uint32_t Value );
+void RSPJlLabel8 ( uint8_t Value );
+void RSPJlLabel32 ( uint32_t Value );
+void RSPJumpX86Reg ( int32_t x86reg );
+void RSPJmpLabel8 ( uint8_t Value );
+void RSPJmpLabel32 ( uint32_t Value);
+void RSPJneLabel8 ( uint8_t Value );
+void RSPJneLabel32 ( uint32_t Value );
+void RSPJnsLabel8 ( uint8_t Value );
+void RSPJnsLabel32 ( uint32_t Value );
+void RSPJsLabel32 ( uint32_t Value );
+void RSPLeaSourceAndOffset ( int32_t x86DestReg, int32_t x86SourceReg, int32_t offset );
+void RSPMoveConstByteToN64Mem ( uint8_t Const, int32_t AddrReg );
+void RSPMoveConstHalfToN64Mem ( uint16_t Const, int32_t AddrReg );
+void RSPMoveConstByteToVariable ( uint8_t Const,void *Variable );
+void RSPMoveConstHalfToVariable ( uint16_t Const, void *Variable );
+void RSPMoveConstToN64Mem ( uint32_t Const, int32_t AddrReg );
+void RSPMoveConstToN64MemDisp ( uint32_t Const, int32_t AddrReg, uint8_t Disp );
+void RSPMoveConstToVariable ( uint32_t Const, void *Variable );
+void RSPMoveConstToX86reg ( uint32_t Const, int32_t x86reg );
+void RSPMoveOffsetToX86reg ( uint32_t Const, int32_t x86reg );
+void RSPMoveX86regByteToX86regPointer ( int32_t Source, int32_t AddrReg );
+void RSPMoveX86regHalfToX86regPointer ( int32_t Source, int32_t AddrReg );
+void RSPMoveX86regHalfToX86regPointerDisp ( int32_t Source, int32_t AddrReg, uint8_t Disp);
+void RSPMoveX86regToX86regPointer ( int32_t Source, int32_t AddrReg );
+void RSPMoveX86RegToX86regPointerDisp ( int32_t Source, int32_t AddrReg, uint8_t Disp );
+void RSPMoveX86regPointerToX86regByte ( int32_t Destination, int32_t AddrReg );
+void RSPMoveX86regPointerToX86regHalf ( int32_t Destination, int32_t AddrReg );
+void RSPMoveX86regPointerToX86reg ( int32_t Destination, int32_t AddrReg );
+void RSPMoveN64MemDispToX86reg ( int32_t x86reg, int32_t AddrReg, uint8_t Disp );
+void RSPMoveN64MemToX86reg ( int32_t x86reg, int32_t AddrReg );
+void RSPMoveN64MemToX86regByte ( int32_t x86reg, int32_t AddrReg );
+void RSPMoveN64MemToX86regHalf ( int32_t x86reg, int32_t AddrReg );
+void RSPMoveX86regByteToN64Mem ( int32_t x86reg, int32_t AddrReg );
+void RSPMoveX86regByteToVariable ( int32_t x86reg, void * Variable );
+void RSPMoveX86regHalfToN64Mem ( int32_t x86reg, int32_t AddrReg );
+void RSPMoveX86regHalfToVariable ( int32_t x86reg, void * Variable );
+void RSPMoveX86regToN64Mem ( int32_t x86reg, int32_t AddrReg );
+void RSPMoveX86regToN64MemDisp ( int32_t x86reg, int32_t AddrReg, uint8_t Disp );
+void RSPMoveX86regToVariable ( int32_t x86reg, void * Variable );
+void RSPMoveX86RegToX86Reg ( int32_t Source, int32_t Destination );
+void RSPMoveVariableToX86reg ( void *Variable, int32_t x86reg );
+void RSPMoveVariableToX86regByte ( void *Variable, int32_t x86reg );
+void RSPMoveVariableToX86regHalf ( void *Variable, int32_t x86reg );
+void RSPMoveSxX86RegHalfToX86Reg ( int32_t Source, int32_t Destination );
+void RSPMoveSxX86RegPtrDispToX86RegHalf( int32_t AddrReg, uint8_t Disp, int32_t Destination );
+void RSPMoveSxN64MemToX86regByte ( int32_t x86reg, int32_t AddrReg );
+void RSPMoveSxN64MemToX86regHalf ( int32_t x86reg, int32_t AddrReg );
+void RSPMoveSxVariableToX86regHalf ( void *Variable, int32_t x86reg );
+void RSPMoveZxX86RegHalfToX86Reg ( int32_t Source, int32_t Destination );
+void RSPMoveZxX86RegPtrDispToX86RegHalf( int32_t AddrReg, uint8_t Disp, int32_t Destination );
+void RSPMoveZxN64MemToX86regByte ( int32_t x86reg, int32_t AddrReg );
+void RSPMoveZxN64MemToX86regHalf ( int32_t x86reg, int32_t AddrReg );
+void RSPMoveZxVariableToX86regHalf ( void *Variable, int32_t x86reg );
+void RSPMulX86reg ( int32_t x86reg );
+void RSPNegateX86reg ( int32_t x86reg );
+void RSPOrConstToVariable ( uint32_t Const, void * Variable );
+void RSPOrConstToX86Reg ( uint32_t Const, int32_t x86Reg );
+void RSPOrVariableToX86Reg ( void * Variable, int32_t x86Reg );
+void RSPOrVariableToX86regHalf ( void * Variable, int32_t x86Reg );
+void RSPOrX86RegToVariable ( void * Variable, int32_t x86Reg );
+void RSPOrX86RegToX86Reg ( int32_t Destination, int32_t Source );
+void RSPPopad ( void );
+void RSPPushad ( void );
+void RSPPush ( int32_t x86reg );
+void RSPPop ( int32_t x86reg );
+void RSPPushImm32 ( uint32_t Value );
+void RSPRet ( void );
+void RSPSeta ( int32_t x86reg );
+void RSPSetae ( int32_t x86reg );
+void RSPSetl ( int32_t x86reg );
+void RSPSetb ( int32_t x86reg );
+void RSPSetg ( int32_t x86reg );
+void RSPSetz ( int32_t x86reg );
+void RSPSetnz ( int32_t x86reg );
+void RSPSetlVariable ( void * Variable );
+void RSPSetleVariable ( void * Variable );
+void RSPSetgVariable ( void * Variable );
+void RSPSetgeVariable ( void * Variable );
+void RSPSetbVariable ( void * Variable );
+void RSPSetaVariable ( void * Variable );
+void RSPSetzVariable ( void * Variable );
+void RSPSetnzVariable ( void * Variable );
+void RSPShiftLeftSign ( int32_t x86reg );
+void RSPShiftLeftSignImmed ( int32_t x86reg, uint8_t Immediate );
+void RSPShiftLeftSignVariableImmed ( void *Variable, uint8_t Immediate );
+void RSPShiftRightSignImmed ( int32_t x86reg, uint8_t Immediate );
+void RSPShiftRightSignVariableImmed ( void *Variable, uint8_t Immediate );
+void RSPShiftRightUnsign ( int32_t x86reg );
+void RSPShiftRightUnsignImmed ( int32_t x86reg, uint8_t Immediate );
+void RSPShiftRightUnsignVariableImmed ( void *Variable, uint8_t Immediate );
+void RSPShiftLeftDoubleImmed ( int32_t Destination, int32_t Source, uint8_t Immediate );
+void RSPShiftRightDoubleImmed ( int32_t Destination, int32_t Source, uint8_t Immediate );
+void RSPSubConstFromVariable ( uint32_t Const, void *Variable );
+void RSPSubConstFromX86Reg ( int32_t x86Reg, uint32_t Const );
+void RSPSubVariableFromX86reg ( int32_t x86reg, void * Variable );
+void RSPSubX86RegToX86Reg ( int32_t Destination, int32_t Source );
+void RSPSubX86regFromVariable ( int32_t x86reg, void * Variable );
+void RSPSbbX86RegToX86Reg ( int32_t Destination, int32_t Source );
+void RSPTestConstToVariable ( uint32_t Const, void * Variable );
+void RSPTestConstToX86Reg ( uint32_t Const, int32_t x86reg );
+void RSPTestX86RegToX86Reg ( int32_t Destination, int32_t Source );
+void RSPXorConstToX86Reg ( int32_t x86Reg, uint32_t Const );
+void RSPXorX86RegToX86Reg ( int32_t Source, int32_t Destination );
+void RSPXorVariableToX86reg ( void *Variable, int32_t x86reg );
+void RSPXorX86RegToVariable ( void *Variable, int32_t x86reg );
+void RSPXorConstToVariable ( void *Variable, uint32_t Const );
+
+#define _MMX_SHUFFLE(a, b, c, d) \
+ ((uint8_t)(((a) << 6) | ((b) << 4) | ((c) << 2) | (d)))
+
+void RSPMmxMoveRegToReg ( int32_t Dest, int32_t Source );
+void RSPMmxMoveQwordRegToVariable ( int32_t Dest, void *Variable );
+void RSPMmxMoveQwordVariableToReg ( int32_t Dest, void *Variable );
+void RSPMmxPandRegToReg ( int32_t Dest, int32_t Source );
+void RSPMmxPandnRegToReg ( int32_t Dest, int32_t Source );
+void RSPMmxPandVariableToReg ( void * Variable, int32_t Dest );
+void RSPMmxPorRegToReg ( int32_t Dest, int32_t Source );
+void RSPMmxPorVariableToReg ( void * Variable, int32_t Dest );
+void RSPMmxXorRegToReg ( int32_t Dest, int32_t Source );
+void RSPMmxShuffleMemoryToReg ( int32_t Dest, void * Variable, uint8_t Immed );
+void RSPMmxPmullwRegToReg ( int32_t Dest, int32_t Source );
+void RSPMmxPmullwVariableToReg ( int32_t Dest, void * Variable );
+void RSPMmxPmulhuwRegToReg ( int32_t Dest, int32_t Source );
+void RSPMmxPmulhwRegToReg ( int32_t Dest, int32_t Source );
+void RSPMmxPmulhwRegToVariable ( int32_t Dest, void * Variable );
+void RSPMmxPsrlwImmed ( int32_t Dest, uint8_t Immed );
+void RSPMmxPsrawImmed ( int32_t Dest, uint8_t Immed );
+void RSPMmxPsllwImmed ( int32_t Dest, uint8_t Immed );
+void RSPMmxPaddswRegToReg ( int32_t Dest, int32_t Source );
+void RSPMmxPaddswVariableToReg ( int32_t Dest, void * Variable );
+void RSPMmxPaddwRegToReg ( int32_t Dest, int32_t Source );
+void RSPMmxPackSignedDwords ( int32_t Dest, int32_t Source );
+void RSPMmxUnpackLowWord ( int32_t Dest, int32_t Source );
+void RSPMmxUnpackHighWord ( int32_t Dest, int32_t Source );
+void RSPMmxCompareGreaterWordRegToReg ( int32_t Dest, int32_t Source );
+void RSPMmxEmptyMultimediaState ( void );
+
+void RSPSseMoveAlignedVariableToReg ( void *Variable, int32_t sseReg );
+void RSPSseMoveAlignedRegToVariable ( int32_t sseReg, void *Variable );
+void RSPSseMoveAlignedN64MemToReg ( int32_t sseReg, int32_t AddrReg );
+void RSPSseMoveAlignedRegToN64Mem ( int32_t sseReg, int32_t AddrReg );
+void RSPSseMoveUnalignedVariableToReg ( void *Variable, int32_t sseReg );
+void RSPSseMoveUnalignedRegToVariable ( int32_t sseReg, void *Variable );
+void RSPSseMoveUnalignedN64MemToReg ( int32_t sseReg, int32_t AddrReg );
+void RSPSseMoveUnalignedRegToN64Mem ( int32_t sseReg, int32_t AddrReg );
+void RSPSseMoveRegToReg ( int32_t Dest, int32_t Source );
+void RSPSseXorRegToReg ( int32_t Dest, int32_t Source );
+
+typedef struct {
+ union {
+ struct {
+ unsigned Reg0 : 2;
+ unsigned Reg1 : 2;
+ unsigned Reg2 : 2;
+ unsigned Reg3 : 2;
+ };
+ unsigned UB:8;
+ };
+} SHUFFLE;
+
+void RSPSseShuffleReg ( int32_t Dest, int32_t Source, uint8_t Immed );
+
+void RSPx86_SetBranch32b(void * JumpByte, void * Destination);
+void RSPx86_SetBranch8b(void * JumpByte, void * Destination);
\ No newline at end of file diff --git a/src/usf/tlb.c b/src/usf/tlb.c new file mode 100644 index 0000000..ab94197 --- /dev/null +++ b/src/usf/tlb.c @@ -0,0 +1,200 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+
+#include "main.h"
+#include "cpu.h"
+
+void SetupTLB_Entry (int32_t Entry);
+
+FASTTLB FastTlb[64];
+TLB tlb[32];
+
+uint32_t AddressDefined ( uintptr_t VAddr) {
+ uint32_t i;
+
+ if (VAddr >= 0x80000000 && VAddr <= 0xBFFFFFFF) {
+ return 1;
+ }
+
+ for (i = 0; i < 64; i++) {
+ if (FastTlb[i].ValidEntry == 0) { continue; }
+ if (VAddr >= FastTlb[i].VSTART && VAddr <= FastTlb[i].VEND) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void InitilizeTLB (void) {
+ uint32_t count;
+
+ for (count = 0; count < 32; count++) { tlb[count].EntryDefined = 0; }
+ for (count = 0; count < 64; count++) { FastTlb[count].ValidEntry = 0; }
+ SetupTLB();
+}
+
+void SetupTLB (void) {
+ uint32_t count;
+
+ memset(TLB_Map,0,(0xFFFFF * sizeof(uintptr_t)));
+ for (count = 0x80000000; count < 0xC0000000; count += 0x1000) {
+ TLB_Map[count >> 12] = ((uintptr_t)N64MEM + (count & 0x1FFFFFFF)) - count;
+ }
+ for (count = 0; count < 32; count ++) { SetupTLB_Entry(count); }
+}
+/*
+test=(BYTE *) VirtualAlloc( 0x10, 0x70000, MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+ if(test == 0) {
+ printf("FAIL!\n");
+ exit(0);
+ }
+*/
+
+void SetupTLB_Entry (int Entry) {
+ uint32_t FastIndx;
+
+
+ if (!tlb[Entry].EntryDefined) { return; }
+ FastIndx = Entry << 1;
+ FastTlb[FastIndx].VSTART=tlb[Entry].EntryHi.VPN2 << 13;
+ FastTlb[FastIndx].VEND = FastTlb[FastIndx].VSTART + (tlb[Entry].PageMask.Mask << 12) + 0xFFF;
+ FastTlb[FastIndx].PHYSSTART = tlb[Entry].EntryLo0.PFN << 12;
+ FastTlb[FastIndx].VALID = tlb[Entry].EntryLo0.V;
+ FastTlb[FastIndx].DIRTY = tlb[Entry].EntryLo0.D;
+ FastTlb[FastIndx].GLOBAL = tlb[Entry].EntryLo0.GLOBAL & tlb[Entry].EntryLo1.GLOBAL;
+ FastTlb[FastIndx].ValidEntry = 0;
+
+ FastIndx = (Entry << 1) + 1;
+ FastTlb[FastIndx].VSTART=(tlb[Entry].EntryHi.VPN2 << 13) + ((tlb[Entry].PageMask.Mask << 12) + 0xFFF + 1);
+ FastTlb[FastIndx].VEND = FastTlb[FastIndx].VSTART + (tlb[Entry].PageMask.Mask << 12) + 0xFFF;
+ FastTlb[FastIndx].PHYSSTART = tlb[Entry].EntryLo1.PFN << 12;
+ FastTlb[FastIndx].VALID = tlb[Entry].EntryLo1.V;
+ FastTlb[FastIndx].DIRTY = tlb[Entry].EntryLo1.D;
+ FastTlb[FastIndx].GLOBAL = tlb[Entry].EntryLo0.GLOBAL & tlb[Entry].EntryLo1.GLOBAL;
+ FastTlb[FastIndx].ValidEntry = 0;
+
+ for ( FastIndx = Entry << 1; FastIndx <= (Entry << 1) + 1; FastIndx++) {
+ uint32_t count;
+
+ if (!FastTlb[FastIndx].VALID) {
+ FastTlb[FastIndx].ValidEntry = 1;
+ continue;
+ }
+ if (FastTlb[FastIndx].VEND <= FastTlb[FastIndx].VSTART) {
+ continue;
+ }
+ if (FastTlb[FastIndx].VSTART >= 0x80000000 && FastTlb[FastIndx].VEND <= 0xBFFFFFFF) {
+ continue;
+ }
+ if (FastTlb[FastIndx].PHYSSTART > 0x1FFFFFFF) {
+ continue;
+ }
+
+
+ //exit(0);
+ //"c:\music\xsf\usf\pdusf\03 - Carrington Institute.miniusf"
+ //"c:\music\xsf\usf\pdusf\03 - Carrington Institute.miniusf"
+
+
+ //test if overlap
+ FastTlb[FastIndx].ValidEntry = 1;
+ for (count = FastTlb[FastIndx].VSTART; count < FastTlb[FastIndx].VEND; count += 0x1000) {
+ TLB_Map[count >> 12] = ((uintptr_t)N64MEM + (count - FastTlb[FastIndx].VSTART + FastTlb[FastIndx].PHYSSTART)) - count;
+ }
+ }
+}
+
+void TLB_Probe (void) {
+ uint32_t Counter;
+
+
+ INDEX_REGISTER |= 0x80000000;
+ for (Counter = 0; Counter < 32; Counter ++) {
+ uint32_t TlbValue = tlb[Counter].EntryHi.Value & (~tlb[Counter].PageMask.Mask << 13);
+ uint32_t EntryHi = ENTRYHI_REGISTER & (~tlb[Counter].PageMask.Mask << 13);
+
+ if (TlbValue == EntryHi) {
+ uint32_t Global = (tlb[Counter].EntryHi.Value & 0x100) != 0;
+ uint32_t SameAsid = ((tlb[Counter].EntryHi.Value & 0xFF) == (ENTRYHI_REGISTER & 0xFF));
+
+ if (Global || SameAsid) {
+ INDEX_REGISTER = Counter;
+ return;
+ }
+ }
+ }
+}
+
+void TLB_Read (void) {
+ uint32_t index = INDEX_REGISTER & 0x1F;
+
+ PAGE_MASK_REGISTER = tlb[index].PageMask.Value ;
+ ENTRYHI_REGISTER = (tlb[index].EntryHi.Value & ~tlb[index].PageMask.Value) ;
+ ENTRYLO0_REGISTER = tlb[index].EntryLo0.Value;
+ ENTRYLO1_REGISTER = tlb[index].EntryLo1.Value;
+}
+
+uint32_t TranslateVaddr ( uintptr_t * Addr) {
+ if (TLB_Map[((*Addr) & 0xffffffff) >> 12] == 0) { return 0; }
+ *Addr = (uintptr_t)((uint8_t *)(TLB_Map[((*Addr) & 0xffffffff) >> 12] + ((*Addr) & 0xffffffff)) - (uintptr_t)N64MEM);
+ return 1;
+}
+
+void WriteTLBEntry (int32_t index) {
+ uint32_t FastIndx;
+
+ FastIndx = index << 1;
+ if ((PROGRAM_COUNTER >= FastTlb[FastIndx].VSTART &&
+ PROGRAM_COUNTER < FastTlb[FastIndx].VEND &&
+ FastTlb[FastIndx].ValidEntry && FastTlb[FastIndx].VALID)
+ ||
+ (PROGRAM_COUNTER >= FastTlb[FastIndx + 1].VSTART &&
+ PROGRAM_COUNTER < FastTlb[FastIndx + 1].VEND &&
+ FastTlb[FastIndx + 1].ValidEntry && FastTlb[FastIndx + 1].VALID))
+ {
+ return;
+ }
+
+ if (tlb[index].EntryDefined) {
+ uint32_t count;
+
+ for ( FastIndx = index << 1; FastIndx <= (index << 1) + 1; FastIndx++) {
+ if (!FastTlb[FastIndx].ValidEntry) { continue; }
+ if (!FastTlb[FastIndx].VALID) { continue; }
+ for (count = FastTlb[FastIndx].VSTART; count < FastTlb[FastIndx].VEND; count += 0x1000) {
+ TLB_Map[count >> 12] = 0;
+ }
+ }
+ }
+ tlb[index].PageMask.Value = PAGE_MASK_REGISTER;
+ tlb[index].EntryHi.Value = ENTRYHI_REGISTER;
+ tlb[index].EntryLo0.Value = ENTRYLO0_REGISTER;
+ tlb[index].EntryLo1.Value = ENTRYLO1_REGISTER;
+ tlb[index].EntryDefined = 1;
+
+
+ SetupTLB_Entry(index);
+}
diff --git a/src/usf/tlb.h b/src/usf/tlb.h new file mode 100644 index 0000000..32a2075 --- /dev/null +++ b/src/usf/tlb.h @@ -0,0 +1,108 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+#ifndef _TLB_H_
+#define _TLB_H_
+
+typedef struct {
+ uint32_t EntryDefined;
+ union {
+ uint32_t Value;
+ uint8_t A[4];
+
+ struct {
+ unsigned zero : 13;
+ unsigned Mask : 12;
+ unsigned zero2 : 7;
+ } ;
+
+ } PageMask;
+
+ union {
+ uint32_t Value;
+ uint8_t A[4];
+
+ struct {
+ unsigned ASID : 8;
+ unsigned Zero : 4;
+ unsigned G : 1;
+ unsigned VPN2 : 19;
+ };
+
+ } EntryHi;
+
+ union {
+ uint32_t Value;
+ uint8_t A[4];
+
+ struct {
+ unsigned GLOBAL: 1;
+ unsigned V : 1;
+ unsigned D : 1;
+ unsigned C : 3;
+ unsigned PFN : 20;
+ unsigned ZERO: 6;
+ };
+
+ } EntryLo0;
+
+ union {
+ uint32_t Value;
+ uint8_t A[4];
+
+ struct {
+ unsigned GLOBAL: 1;
+ unsigned V : 1;
+ unsigned D : 1;
+ unsigned C : 3;
+ unsigned PFN : 20;
+ unsigned ZERO: 6;
+ } ;
+
+ } EntryLo1;
+} TLB;
+
+typedef struct {
+ uint32_t VSTART;
+ uint32_t VEND;
+ uint32_t PHYSSTART;
+ uint32_t VALID;
+ uint32_t DIRTY;
+ uint32_t GLOBAL;
+ uint32_t ValidEntry;
+} FASTTLB;
+
+extern FASTTLB FastTlb[64];
+extern TLB tlb[32];
+
+uint32_t AddressDefined ( uintptr_t VAddr);
+void InitilizeTLB ( void );
+void SetupTLB ( void );
+void TLB_Probe ( void );
+void TLB_Read ( void );
+uint32_t TranslateVaddr ( uintptr_t * Addr);
+void WriteTLBEntry ( int32_t index );
+
+#endif
diff --git a/src/usf/types.h b/src/usf/types.h new file mode 100644 index 0000000..c56d3ff --- /dev/null +++ b/src/usf/types.h @@ -0,0 +1,77 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+#ifndef __Types_h
+#define __Types_h
+
+#ifdef __LP64__
+#define USEX64
+#define EXTREGS
+#endif
+
+#include <stdint.h>
+typedef uint64_t QWORD;
+
+typedef union tagVect {
+ double FD[2];
+ int64_t DW[2];
+ uint64_t UDW[2];
+ int32_t W[4];
+ float FS[4];
+ uint32_t UW[4];
+ int16_t HW[8];
+ uint16_t UHW[8];
+ int8_t B[16];
+ uint8_t UB[16];
+} VECTOR;
+
+typedef union tagUWORD {
+ int32_t W;
+ uint32_t UW;
+ int16_t HW[2];
+ uint16_t UHW[2];
+ int8_t B[4];
+ uint8_t UB[4];
+ float F;
+} MIPS_WORD;
+
+typedef union tagUDWORD {
+ double D;
+ int64_t DW;
+ uint64_t UDW;
+ int32_t W[2];
+ uint32_t UW[2];
+ int16_t HW[4];
+ uint16_t UHW[4];
+ int8_t B[8];
+ uint8_t UB[8];
+ float F[2];
+} MIPS_DWORD;
+
+typedef MIPS_WORD MIPSUWORD;
+typedef MIPS_DWORD MIPSUDWORD;
+
+
+#endif
diff --git a/src/usf/usf.c b/src/usf/usf.c new file mode 100644 index 0000000..05b19d5 --- /dev/null +++ b/src/usf/usf.c @@ -0,0 +1,522 @@ +
+#include <stdint.h>
+#include "usf.h"
+#include "cpu.h"
+#include "memory.h"
+#include "audio.h"
+#include "psftag.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <audacious/plugin.h>
+
+#include <unistd.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "types.h"
+
+extern int SampleRate;
+
+extern InputPlugin usf_ip;
+InputPlayback * pcontext = 0;
+
+void usf_mseek(InputPlayback * context, gulong millisecond);
+int8_t filename[512];
+uint32_t cpu_running = 0, use_interpreter = 0, use_audiohle = 0, is_paused = 0, cpu_stopped = 1, fake_seek_stopping = 0;
+uint32_t is_fading = 0, fade_type = 1, fade_time = 5000, is_seeking = 0, seek_backwards = 0, track_time = 180000;
+double seek_time = 0.0, play_time = 0.0, rel_volume = 1.0;
+
+uint32_t enablecompare = 0, enableFIFOfull = 0;
+
+uint32_t usf_length = 0, usf_fade_length = 0;
+
+int8_t title[100];
+uint8_t title_format[] = "%game% - %title%";
+
+extern int32_t RSP_Cpu;
+
+uint32_t get_length_from_string(uint8_t * str_length) {
+ uint32_t ttime = 0, temp = 0, mult = 1, level = 1;
+ char Source[1024];
+ uint8_t * src = Source + strlen(str_length);
+ strcpy(&Source[1], str_length);
+ Source[0] = 0;
+
+ while(*src) {
+ if((*src >= '0') && (*src <= '9')) {
+ temp += ((*src - '0') * mult);
+ mult *= 10;
+ } else {
+ mult = 1;
+ if(*src == '.') {
+ ttime = temp;
+ temp = 0;
+ } else if(*src == ':') {
+ ttime += (temp * (1000 * level));
+ temp = 0;
+ level *= 60;
+ }
+ }
+ src--;
+ }
+
+ ttime += (temp * (1000 * level));
+ return ttime;
+}
+
+int LoadUSF(const gchar * fn)
+{
+ VFSFile * fil = NULL;
+ uint32_t reservedsize = 0, codesize = 0, crc = 0, tagstart = 0, reservestart = 0;
+ uint32_t filesize = 0, tagsize = 0, temp = 0;
+ uint8_t buffer[16], * buffer2 = NULL, * tagbuffer = NULL;
+
+ is_fading = 0;
+ fade_type = 1;
+ fade_time = 5000;
+ track_time = 180000;
+ play_time = 0;
+ is_seeking = 0;
+ seek_backwards = 0;
+ seek_time = 0;
+
+ fil = vfs_fopen(fn, "rb");
+
+ if(!fil) {
+ printf("Could not open USF!\n");
+ return 0;
+ }
+
+ vfs_fread(buffer,4 ,1 ,fil);
+ if(buffer[0] != 'P' && buffer[1] != 'S' && buffer[2] != 'F' && buffer[3] != 0x21) {
+ printf("Invalid header in file!\n");
+ vfs_fclose(fil);
+ return 0;
+ }
+
+ vfs_fread(&reservedsize, 4, 1, fil);
+ vfs_fread(&codesize, 4, 1, fil);
+ vfs_fread(&crc, 4, 1, fil);
+
+ vfs_fseek(fil, 0, SEEK_END);
+ filesize = vfs_ftell(fil);
+
+ reservestart = 0x10;
+ tagstart = reservestart + reservedsize;
+ tagsize = filesize - tagstart;
+
+ if(tagsize) {
+ vfs_fseek(fil, tagstart, SEEK_SET);
+ vfs_fread(buffer, 5, 1, fil);
+
+ if(buffer[0] != '[' && buffer[1] != 'T' && buffer[2] != 'A' && buffer[3] != 'G' && buffer[4] != ']') {
+ printf("Erroneous data in tag area! %" PRIu32 "\n", tagsize);
+ vfs_fclose(fil);
+ return 0;
+ }
+
+ buffer2 = malloc(50001);
+ tagbuffer = malloc(tagsize);
+
+ vfs_fread(tagbuffer, tagsize, 1, fil);
+
+ psftag_raw_getvar(tagbuffer,"_lib",buffer2,50000);
+
+ if(strlen(buffer2)) {
+ char path[512];
+ int pathlength = 0;
+
+ if(strrchr(fn, '/')) //linux
+ pathlength = strrchr(fn, '/') - fn + 1;
+ else if(strrchr(fn, '\\')) //windows
+ pathlength = strrchr(fn, '\\') - fn + 1;
+ else //no path
+ pathlength = strlen(fn);
+
+ strncpy(path, fn, pathlength);
+ path[pathlength] = 0;
+ strcat(path, buffer2);
+
+ LoadUSF(path);
+ }
+
+ psftag_raw_getvar(tagbuffer,"_enablecompare",buffer2,50000);
+ if(strlen(buffer2))
+ enablecompare = 1;
+ else
+ enablecompare = 0;
+
+ psftag_raw_getvar(tagbuffer,"_enableFIFOfull",buffer2,50000);
+ if(strlen(buffer2))
+ enableFIFOfull = 1;
+ else
+ enableFIFOfull = 0;
+
+ psftag_raw_getvar(tagbuffer, "length", buffer2, 50000);
+ if(strlen(buffer2)) {
+ track_time = get_length_from_string(buffer2);
+ }
+
+ psftag_raw_getvar(tagbuffer, "fade", buffer2, 50000);
+ if(strlen(buffer2)) {
+ fade_time = get_length_from_string(buffer2);
+ }
+
+ psftag_raw_getvar(tagbuffer, "title", buffer2, 50000);
+ if(strlen(buffer2))
+ strcpy(title, buffer2);
+ else
+ {
+ int pathlength = 0;
+
+ if(strrchr(fn, '/')) //linux
+ pathlength = strrchr(fn, '/') - fn + 1;
+ else if(strrchr(fn, '\\')) //windows
+ pathlength = strrchr(fn, '\\') - fn + 1;
+ else //no path
+ pathlength = 7;
+
+ strcpy(title, &fn[pathlength]);
+
+ }
+
+ free(buffer2);
+ buffer2 = NULL;
+
+ free(tagbuffer);
+ tagbuffer = NULL;
+
+ }
+
+ vfs_fseek(fil, reservestart, SEEK_SET);
+ vfs_fread(&temp, 4, 1, fil);
+
+ if(temp == 0x34365253) { //there is a rom section
+ int len = 0, start = 0;
+ vfs_fread(&len, 4, 1, fil);
+
+ while(len) {
+ vfs_fread(&start, 4, 1, fil);
+
+ while(len) {
+ int page = start >> 16;
+ int readLen = ( ((start + len) >> 16) > page) ? (((page + 1) << 16) - start) : len;
+
+ if(ROMPages[page] == 0) {
+ ROMPages[page] = malloc(0x10000);
+ memset(ROMPages[page], 0, 0x10000);
+ }
+
+ vfs_fread(ROMPages[page] + (start & 0xffff), readLen, 1, fil);
+
+ start += readLen;
+ len -= readLen;
+ }
+
+ vfs_fread(&len, 4, 1, fil);
+ }
+
+ }
+
+
+
+ vfs_fread(&temp, 4, 1, fil);
+ if(temp == 0x34365253) {
+ int len = 0, start = 0;
+ vfs_fread(&len, 4, 1, fil);
+
+ while(len) {
+ vfs_fread(&start, 4, 1, fil);
+
+ vfs_fread(savestatespace + start, len, 1, fil);
+
+ vfs_fread(&len, 4, 1, fil);
+ }
+ }
+
+ // Detect the Ramsize before the memory allocation
+
+ if(*(uint32_t*)(savestatespace + 4) == 0x400000) {
+ RdramSize = 0x400000;
+ savestatespace = realloc(savestatespace, 0x40275c);
+ } else if(*(uint32_t*)(savestatespace + 4) == 0x800000)
+ RdramSize = 0x800000;
+
+ vfs_fclose(fil);
+
+ return 1;
+}
+
+
+void usf_init()
+{
+ use_audiohle = 0;
+ use_interpreter = 0;
+ RSP_Cpu = 0; // 0 is recompiler, 1 is interpreter
+}
+
+void usf_destroy()
+{
+
+}
+
+void usf_seek(InputPlayback * context, gint time)
+{
+ usf_mseek(context, time * 1000);
+}
+
+
+void usf_mseek(InputPlayback * context, gulong millisecond)
+{
+ if(millisecond < play_time) {
+ is_paused = 0;
+
+ fake_seek_stopping = 1;
+ CloseCpu();
+
+ while(!cpu_stopped)
+ usleep(1);
+
+ is_seeking = 1;
+ seek_time = (double)millisecond;
+
+ fake_seek_stopping = 2;
+ } else {
+ is_seeking = 1;
+ seek_time = (double)millisecond;
+ }
+
+ context->output->flush(millisecond/1000);
+}
+
+void usf_play(InputPlayback * context)
+{
+ if(!context->filename)
+ return;
+
+ // Defaults (which would be overriden by Tags / playing
+ savestatespace = NULL;
+ cpu_running = is_paused = fake_seek_stopping = 0;
+ cpu_stopped = 1;
+ is_fading = 0;
+ fade_type = 1;
+ fade_time = 5000;
+ is_seeking = 0;
+ seek_backwards = 0;
+ track_time = 180000;
+ seek_time = 0.0;
+ play_time = 0.0;
+ rel_volume = 1.0;
+
+
+ pcontext = context;
+
+ // Allocate main memory after usf loads (to determine ram size)
+
+ PreAllocate_Memory();
+
+ if(!LoadUSF(context->filename)) {
+ Release_Memory();
+ return;
+ }
+
+ context->set_pb_ready(context);
+
+ Allocate_Memory();
+
+ context->playing = TRUE;
+ while(context->playing) {
+ is_fading = 0;
+ play_time = 0;
+
+ StartEmulationFromSave(savestatespace);
+ if(!fake_seek_stopping) break;
+ while(fake_seek_stopping != 2)
+ usleep(1);
+ fake_seek_stopping = 4;
+ }
+
+ Release_Memory();
+ context->playing = FALSE;
+ context->eof = TRUE;
+
+ context->output->close_audio();
+}
+
+void usf_stop(InputPlayback *context)
+{
+ while (cpu_running == 1)
+ {
+ cpu_running = 0;
+ CloseCpu();
+ }
+
+ context->playing = FALSE;
+ is_paused = 0;
+ context->eof = FALSE;
+}
+
+void usf_pause(InputPlayback *context, gshort paused)
+{
+ is_paused = paused;//is_paused?0:1;
+}
+
+static const gchar *usf_exts [] =
+{
+ "usf",
+ "miniusf",
+ NULL
+};
+
+
+Tuple * usf_get_song_tuple(const gchar * fn)
+{
+ Tuple * tuple = NULL;
+
+ VFSFile * fil = NULL;
+ uint32_t reservedsize = 0, codesize = 0, crc = 0, tagstart = 0, reservestart = 0, filesize = 0, tagsize = 0;
+ uint8_t buffer[16], * buffer2 = NULL, * tagbuffer = NULL;
+
+ fil = vfs_fopen(fn, "rb");
+
+ if(!fil) {
+ printf("Could not open USF!\n");
+ return NULL;
+ }
+
+ vfs_fread(buffer,4 ,1 ,fil);
+
+ if(buffer[0] != 'P' && buffer[1] != 'S' && buffer[2] != 'F' && buffer[3] != 0x21) {
+ printf("Invalid header in file!\n");
+ vfs_fclose(fil);
+ return NULL;
+ }
+
+ vfs_fread(&reservedsize, 4, 1, fil);
+ vfs_fread(&codesize, 4, 1, fil);
+ vfs_fread(&crc, 4, 1, fil);
+
+ vfs_fseek(fil, 0, SEEK_END);
+ filesize = vfs_ftell(fil);
+
+ reservestart = 0x10;
+ tagstart = reservestart + reservedsize;
+ tagsize = filesize - tagstart;
+
+ tuple = tuple_new_from_filename(fn);
+
+ if(tagsize) {
+ int temp_fade = 0;
+ vfs_fseek(fil, tagstart, SEEK_SET);
+ vfs_fread(buffer, 5, 1, fil);
+
+ if(buffer[0] != '[' && buffer[1] != 'T' && buffer[2] != 'A' && buffer[3] != 'G' && buffer[4] != ']') {
+ printf("Erroneous data in tag area! %" PRIu32 "\n", tagsize);
+ vfs_fclose(fil);
+ return NULL;
+ }
+
+ buffer2 = malloc(50001);
+ tagbuffer = malloc(tagsize);
+
+ vfs_fread(tagbuffer, tagsize, 1, fil);
+
+ psftag_raw_getvar(tagbuffer, "fade", buffer2, 50000);
+ if(strlen(buffer2))
+ temp_fade = get_length_from_string(buffer2);
+
+ psftag_raw_getvar(tagbuffer, "length", buffer2, 50000);
+ if(strlen(buffer2))
+ tuple_associate_int(tuple, FIELD_LENGTH, NULL, get_length_from_string(buffer2) + temp_fade);
+ else
+ tuple_associate_int(tuple, FIELD_LENGTH, NULL, (180*1000));
+
+ psftag_raw_getvar(tagbuffer, "title", buffer2, 50000);
+ if(strlen(buffer2))
+ tuple_associate_string(tuple, FIELD_TITLE, NULL, buffer2);
+ else
+ {
+ char title[512];
+ int pathlength = 0;
+
+ if(strrchr(fn, '/')) //linux
+ pathlength = strrchr(fn, '/') - fn + 1;
+ else if(strrchr(fn, '\\')) //windows
+ pathlength = strrchr(fn, '\\') - fn + 1;
+ else //no path
+ pathlength = 7;
+
+ strcpy(title, &fn[pathlength]);
+
+ tuple_associate_string(tuple, FIELD_TITLE, NULL, title);
+
+ }
+
+ psftag_raw_getvar(tagbuffer, "artist", buffer2, 50000);
+ if(strlen(buffer2))
+ tuple_associate_string(tuple, FIELD_ARTIST, NULL, buffer2);
+
+ psftag_raw_getvar(tagbuffer, "game", buffer2, 50000);
+ if(strlen(buffer2)) {
+ tuple_associate_string(tuple, FIELD_ALBUM, NULL, buffer2);
+ tuple_associate_string(tuple, -1, "game", buffer2);
+ }
+
+ psftag_raw_getvar(tagbuffer, "copyright", buffer2, 50000);
+ if(strlen(buffer2))
+ tuple_associate_string(tuple, FIELD_COPYRIGHT, NULL, buffer2);
+
+ // This for unknown reasons turns the "Kbps" in the UI to "channels"
+ //tuple_associate_string(tuple, FIELD_QUALITY, NULL, "sequenced");
+
+ tuple_associate_string(tuple, FIELD_CODEC, NULL, "Nintendo 64 Audio");
+ tuple_associate_string(tuple, -1, "console", "Nintendo 64");
+
+ free(tagbuffer);
+ free(buffer2);
+ }
+ else
+ {
+ char title[512];
+ int pathlength = 0;
+
+ if(strrchr(fn, '/')) //linux
+ pathlength = strrchr(fn, '/') - fn + 1;
+ else if(strrchr(fn, '\\')) //windows
+ pathlength = strrchr(fn, '\\') - fn + 1;
+ else //no path
+ pathlength = 7;
+
+ strcpy(title, &fn[pathlength]);
+
+
+ tuple_associate_int(tuple, FIELD_LENGTH, NULL, (180 * 1000));
+ tuple_associate_string(tuple, FIELD_TITLE, NULL, title);
+ }
+
+ vfs_fclose(fil);
+
+ return tuple;
+}
+
+InputPlugin usf_ip = {
+ .description = "USF Plugin",
+ .init = usf_init,
+ .play_file = usf_play,
+ .stop = usf_stop,
+ .pause = usf_pause,
+ .seek = usf_seek,
+ .mseek = usf_mseek,
+ .vfs_extensions = (gchar **)usf_exts,
+ .get_song_tuple = usf_get_song_tuple,
+};
+
+
+
+static InputPlugin *usf_iplist[] = { &usf_ip, NULL };
+
+DECLARE_PLUGIN(usf_iplist, NULL, NULL, usf_iplist, NULL, NULL, NULL, NULL, NULL);
+
diff --git a/src/usf/usf.h b/src/usf/usf.h new file mode 100644 index 0000000..f3853b7 --- /dev/null +++ b/src/usf/usf.h @@ -0,0 +1,27 @@ +#ifndef _USF_H_
+#define _USF_H_
+#define _CRT_SECURE_NO_WARNINGS
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <stdint.h>
+
+
+
+#include "usf.h"
+#include "cpu.h"
+#include "memory.h"
+
+extern int8_t filename[512], title[100];
+extern uint32_t cpu_running, use_interpreter, use_audiohle, is_paused, cpu_stopped, fake_seek_stopping;
+extern uint32_t is_fading, fade_type, fade_time, is_seeking, seek_backwards, track_time;
+extern double seek_time, play_time, rel_volume;
+
+extern uint32_t enablecompare, enableFIFOfull;
+
+
+#endif
+
diff --git a/src/usf/x86.c b/src/usf/x86.c new file mode 100644 index 0000000..038ab35 --- /dev/null +++ b/src/usf/x86.c @@ -0,0 +1,810 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+
+#include "main.h"
+#include "cpu.h"
+#include "x86.h"
+#include "types.h"
+
+uint8_t Index[9] = {0,0,0x40,0,0x80,0,0,0,0xC0};
+
+
+void AdcX86regToVariable(int32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x11,x86reg,Variable);
+}
+
+void AdcConstToVariable(void *Variable, uint8_t Constant) {
+ OPCODE_REG_VARIABLE(,8,0x81,OP_D2,Variable);
+ PUTDST8(RecompPos,Constant);
+}
+
+void AdcConstToX86Reg (int32_t x86reg, uint32_t Const) {
+ if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) {
+ OPCODE_REG_REG(8,0x81,OP_D2,x86reg);
+ PUTDST32(RecompPos, Const);
+ } else {
+ OPCODE_REG_REG(8,0x83,OP_D2,x86reg);
+ PUTDST8(RecompPos, Const);
+ }
+}
+
+void AdcVariableToX86reg(int32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x13 ,x86reg,Variable);
+}
+
+void AdcX86RegToX86Reg(int32_t Destination, int32_t Source) {
+ OPCODE_REG_REG(8,0x13,Destination,Source);
+}
+
+void AddConstToVariable (uint32_t Const, void *Variable) {
+ OPCODE_REG_VARIABLE(,8,0x81,OP_D0,Variable);
+ PUTDST32(RecompPos,Const);
+}
+
+void AddConstToX86Reg64 (int32_t x86reg, uint32_t Const) {
+ if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) {
+ OPCODE_REG_REG(8,0x81,OP_D0,x86reg | x64_Reg);
+ PUTDST32(RecompPos, Const);
+ } else {
+ OPCODE_REG_REG(8,0x83,OP_D0,x86reg | x64_Reg);
+ PUTDST8(RecompPos, Const);
+ }
+}
+
+void AddConstToX86Reg (int32_t x86reg, uint32_t Const) {
+ if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) {
+ OPCODE_REG_REG(8,0x81,OP_D0,x86reg);
+ PUTDST32(RecompPos, Const);
+ } else {
+ OPCODE_REG_REG(8,0x83,OP_D0,x86reg);
+ PUTDST8(RecompPos, Const);
+ }
+}
+
+void AddVariableToX86reg(int32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x3,x86reg,Variable);
+}
+
+void AddX86regToVariable(int32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x1,x86reg,Variable);
+}
+
+void AddX86RegToX86Reg(int32_t Destination, int32_t Source) {
+ OPCODE_REG_REG(8,0x3,Destination,Source);
+}
+
+void AndConstToVariable (uint32_t Const, void *Variable) {
+ OPCODE_REG_VARIABLE(,8,0x81,OP_D4,Variable);
+ PUTDST32(RecompPos,Const);
+}
+
+void AndConstToX86Reg(int32_t x86reg, uint32_t Const) {
+ if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) {
+ OPCODE_REG_REG(8,0x81,OP_D4,x86reg);
+ PUTDST32(RecompPos, Const);
+ } else {
+ OPCODE_REG_REG(8,0x83,OP_D4,x86reg);
+ PUTDST8(RecompPos, Const);
+ }
+}
+
+void AndVariableDispToX86Reg(void *Variable, int32_t x86reg, int32_t AddrReg, int32_t Multiplier) {
+#ifdef USEX64
+ if(((uintptr_t)Variable - (uintptr_t)TLB_Map) < 0x7FFFFFFF) {
+ OPCODE_REG_BASE_INDEX_SCALE_IMM32(8,0x23,x86reg,x86_R15,AddrReg,Index[Multiplier], (uintptr_t)Variable - (uintptr_t)TLB_Map);
+ } else {
+ LOAD_VARIABLE(x86_TEMP, Variable);
+ OPCODE_REG_BASE_INDEX_SCALE(8,0x23,x86reg,x86_TEMP,AddrReg,Index[Multiplier]);
+ }
+#else
+ OPCODE_REG_INDEX_SCALE_IMM32(8,0x23,x86reg,AddrReg,Index[Multiplier],Variable);
+#endif
+}
+
+void AndVariableToX86Reg(void * Variable, int32_t x86reg) {
+ OPCODE_REG_VARIABLE(,8,0x23,x86reg,Variable);
+}
+
+void AndX86RegToX86Reg(int32_t Destination, int32_t Source) {
+ OPCODE_REG_REG(8,0x21,Source,Destination);
+}
+
+void BreakPoint (void) {
+ PUTDST8(RecompPos,0xCC);
+}
+
+void Call_Direct(void * FunctAddress) {
+ uintptr_t disp;
+#ifdef USEX64
+ disp = (uintptr_t)FunctAddress-(uintptr_t)RecompPos - 5;
+ SubConstFromX86Reg(x86_RSP, 0x28);
+ if(disp <= 0x7fffffff) {
+ PUTDST8(RecompPos,0xE8);
+ PUTDST32(RecompPos,disp);
+ } else {
+ LOAD_VARIABLE(x86_TEMP, FunctAddress);
+ OPCODE_REG_REG(8,0xff,OP_D2,x86_TEMP);
+
+ }
+ AddConstToX86Reg(x86_RSP, 0x28);
+#else
+ //BreakPoint();
+ disp = (uintptr_t)FunctAddress-(uintptr_t)RecompPos - 5;
+ PUTDST8(RecompPos,0xE8);
+ PUTDST32(RecompPos,disp);
+#endif
+}
+
+void CompConstToVariable(uint32_t Const, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x81,OP_D7,Variable);
+ PUTDST32(RecompPos,Const);
+}
+
+void CompConstToX86reg(int32_t x86reg, uint32_t Const) {
+ if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) {
+ OPCODE_REG_REG(8,0x81,OP_D7,x86reg);
+ PUTDST32(RecompPos,Const);
+ } else {
+ OPCODE_REG_REG(8,0x83,OP_D7,x86reg);
+ PUTDST8(RecompPos, Const);
+ }
+}
+
+void CompX86regToVariable(int32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x3B,x86reg,Variable);
+}
+
+void CompX86RegToX86Reg(int32_t Destination, int32_t Source) {
+ OPCODE_REG_REG(8,0x3B,Destination,Source);
+}
+
+void DecX86reg(x86reg) {
+ OPCODE_REG_REG(8,0xFF,OP_D1,x86reg);
+}
+
+void DivX86reg(int32_t x86reg) {
+ OPCODE_REG_REG(8,0xF7,OP_D6,x86reg);
+}
+
+void idivX86reg(int32_t x86reg) {
+ OPCODE_REG_REG(8,0xF7,OP_D7,x86reg);
+}
+
+void imulX86reg(int32_t x86reg) {
+ OPCODE_REG_REG(8,0xF7,OP_D5,x86reg);
+}
+
+void IncX86reg(int32_t x86reg) {
+ OPCODE_REG_REG(8,0xFF,OP_D0,x86reg);
+}
+
+void JaeLabel8( uint8_t Value) {
+ PUTDST8(RecompPos,0x73);
+ PUTDST8(RecompPos,Value);
+}
+
+void JaeLabel32(uint32_t Value) {
+ PUTDST16(RecompPos,0x830F);
+ PUTDST32(RecompPos,Value);
+}
+
+void JaLabel8( uint8_t Value) {
+ PUTDST8(RecompPos,0x77);
+ PUTDST8(RecompPos,Value);
+}
+
+void JaLabel32(uint32_t Value) {
+ PUTDST16(RecompPos,0x870F);
+ PUTDST32(RecompPos,Value);
+}
+
+void JbLabel8( uint8_t Value) {
+ PUTDST8(RecompPos,0x72);
+ PUTDST8(RecompPos,Value);
+}
+
+void JbLabel32(uint32_t Value) {
+ PUTDST16(RecompPos,0x820F);
+ PUTDST32(RecompPos,Value);
+}
+
+void JecxzLabel8( uint8_t Value) {
+ PUTDST8(RecompPos,0xE3);
+ PUTDST8(RecompPos,Value);
+}
+
+void JeLabel8( uint8_t Value) {
+ PUTDST8(RecompPos,0x74);
+ PUTDST8(RecompPos,Value);
+}
+
+void JeLabel32(uint32_t Value) {
+ PUTDST16(RecompPos,0x840F);
+ PUTDST32(RecompPos,Value);
+}
+
+void JgeLabel32(uint32_t Value) {
+ PUTDST16(RecompPos,0x8D0F);
+ PUTDST32(RecompPos,Value);
+}
+
+void JgLabel8( uint8_t Value) {
+ PUTDST8(RecompPos,0x7F);
+ PUTDST8(RecompPos,Value);
+}
+
+void JgLabel32(uint32_t Value) {
+ PUTDST16(RecompPos,0x8F0F);
+ PUTDST32(RecompPos,Value);
+}
+
+void JleLabel8( uint8_t Value) {
+ PUTDST8(RecompPos,0x7E);
+ PUTDST8(RecompPos,Value);
+}
+
+void JleLabel32(uint32_t Value) {
+ PUTDST16(RecompPos,0x8E0F);
+ PUTDST32(RecompPos,Value);
+}
+
+void JlLabel8( uint8_t Value) {
+ PUTDST8(RecompPos,0x7C);
+ PUTDST8(RecompPos,Value);
+}
+
+void JlLabel32(uint32_t Value) {
+ PUTDST16(RecompPos,0x8C0F);
+ PUTDST32(RecompPos,Value);
+}
+
+void JzLabel8( uint8_t Value) {
+ PUTDST8(RecompPos,0x74);
+ PUTDST8(RecompPos,Value);
+}
+
+void JnzLabel8( uint8_t Value) {
+ PUTDST8(RecompPos,0x75);
+ PUTDST8(RecompPos,Value);
+}
+
+
+void JmpDirectReg( int32_t x86reg ) {
+ OPCODE_REG_REG(8,0xff,OP_D4,x86reg);
+}
+
+void JmpLabel8( uint8_t Value) {
+ PUTDST8(RecompPos,0xEB);
+ PUTDST8(RecompPos,Value);
+}
+
+void JmpLabel32( uint32_t Value) {
+ PUTDST8(RecompPos,0xE9);
+ PUTDST32(RecompPos,Value);
+}
+
+void JneLabel8( uint8_t Value) {
+ PUTDST8(RecompPos,0x75);
+ PUTDST8(RecompPos,Value);
+}
+
+void JneLabel32(uint32_t Value) {
+ PUTDST16(RecompPos,0x850F);
+ PUTDST32(RecompPos,Value);
+}
+
+void JnsLabel8( uint8_t Value) {
+ PUTDST8(RecompPos,0x79);
+ PUTDST8(RecompPos,Value);
+}
+
+void JnsLabel32(uint32_t Value) {
+ PUTDST16(RecompPos,0x890F);
+ PUTDST32(RecompPos,Value);
+}
+
+void JsLabel32(uint32_t Value) {
+ PUTDST16(RecompPos,0x880F);
+ PUTDST32(RecompPos,Value);
+}
+
+void LeaRegReg(int32_t x86RegDest, int32_t x86RegSrc, int32_t multiplier) {
+ OPCODE_REG_BASE_INDEX_SCALE(8,0x8D,x86RegDest,x86_EBP,x86RegSrc,Index[multiplier]);
+ PUTDST32(RecompPos,0x00000000);
+}
+
+void LeaSourceAndOffset(int32_t x86DestReg, int32_t x86SourceReg, int32_t offset) {
+ OPCODE_REG_MREG_IMM32(8,0x8D,x86DestReg,x86SourceReg,offset);
+}
+
+void MoveConstByteToVariable (uint8_t Const,void *Variable) {
+ OPCODE_REG_VARIABLE(,8,0xC6,OP_D0,Variable);
+ PUTDST8(RecompPos,Const);
+}
+
+void MoveConstHalfToVariable (uint16_t Const,void *Variable) {
+ OPCODE_REG_VARIABLE(PUTDST8(RecompPos,0x66),8,0xC7,OP_D0,Variable);
+ PUTDST16(RecompPos,Const);
+}
+
+void MoveConstHalfToX86regPointer(uint16_t Const, int32_t AddrReg1, int32_t AddrReg2) {
+ PUTDST8(RecompPos,0x66);
+ OPCODE_REG_BASE_INDEX(8,0xC7,OP_D0,AddrReg1,AddrReg2);
+ PUTDST16(RecompPos,Const);
+}
+
+void MoveConstToVariable (uint32_t Const,void *Variable) {
+ OPCODE_REG_VARIABLE(,8,0xC7,OP_D0,Variable);
+ PUTDST32(RecompPos,Const);
+}
+
+void MoveConstToX86Pointer(uint32_t Const, int32_t X86Pointer) {
+ OPCODE_REG_MREG(8,0xC7,OP_D0,X86Pointer);
+ PUTDST32(RecompPos,Const);
+}
+
+
+void MoveConstToX86reg(uint32_t Const, int32_t x86reg) {
+ OPCODE_REG_REG(8,0xC7,OP_D0,x86reg);
+ PUTDST32(RecompPos,Const);
+}
+
+void MoveConstQwordToX86reg(uint64_t Const, int32_t x86reg) {
+ PUTDST8(RecompPos, 0x48 | ((x86reg&0x20)>>5));
+ PUTDST8(RecompPos, 0xB8 | ((x86reg-1)&0x7));
+ PUTDST64(RecompPos,Const);
+}
+
+void MoveConstByteToX86regPointer(uint8_t Const, int32_t AddrReg1, int32_t AddrReg2) {
+ OPCODE_REG_BASE_INDEX(8,0xC6,OP_D0,AddrReg1,AddrReg2)
+ PUTDST8(RecompPos,Const);
+}
+
+void MoveConstToX86regPointer(uint32_t Const, int32_t AddrReg1, int32_t AddrReg2) {
+ OPCODE_REG_BASE_INDEX(8,0xC7,OP_D0,AddrReg1,AddrReg2);
+ PUTDST32(RecompPos,Const);
+}
+
+void MoveSxByteX86regPointerToX86reg(int32_t AddrReg1, int32_t AddrReg2, int32_t x86reg) {
+ OPCODE_REG_BASE_INDEX(16,0xBE0F,x86reg,AddrReg1,AddrReg2);
+}
+
+void MoveSxHalfX86regPointerToX86reg(int32_t AddrReg1, int32_t AddrReg2, int32_t x86reg) {
+ OPCODE_REG_BASE_INDEX(16,0xBF0F,x86reg,AddrReg1,AddrReg2);
+}
+
+void MoveSxVariableToX86regByte(void *Variable, int32_t x86reg) {
+ OPCODE_REG_VARIABLE(,16,0xBE0F,x86reg,Variable);
+}
+
+void MoveSxVariableToX86regHalf(void *Variable, int32_t x86reg) {
+ OPCODE_REG_VARIABLE(,16,0xBF0F,x86reg,Variable);
+}
+
+void MoveVariableToX86reg(void *Variable, int32_t x86reg) {
+ OPCODE_REG_VARIABLE(,8,0x8B,x86reg,Variable);
+}
+
+void MovePointerToX86reg(void *Variable, int32_t x86reg) {
+#ifdef USEX64
+ OPCODE_REG_VARIABLE(,8,0x8B,x86reg|x64_Reg,Variable);
+#else
+ OPCODE_REG_VARIABLE(,8,0x8B,x86reg,Variable);
+#endif
+}
+
+void MoveX86RegDispToX86Reg(int32_t x86reg, int32_t AddrReg, int32_t IndexReg, int32_t Multiplier) {
+ OPCODE_REG_BASE_INDEX_SCALE(8,0x8B,x86reg,AddrReg,IndexReg,Index[Multiplier]);
+}
+
+void MoveVariableDispToX86Reg(void *Variable, int32_t x86reg, int32_t AddrReg, int32_t Multiplier) {
+#ifdef USEX64
+ if(((uintptr_t)Variable - (uintptr_t)TLB_Map) < 0x7FFFFFFF) {
+ OPCODE_REG_BASE_INDEX_SCALE_IMM32(8,0x8B,x86reg,x86_R15,AddrReg,Index[Multiplier],((uintptr_t)Variable - (uintptr_t)TLB_Map));
+ } else {
+ LOAD_VARIABLE(x86_TEMP, Variable);
+ OPCODE_REG_BASE_INDEX_SCALE(8,0x8B,x86reg,x86_TEMP,AddrReg,Index[Multiplier]);
+ }
+#else
+ OPCODE_REG_INDEX_SCALE_IMM32(8,0x8B,x86reg,AddrReg,Index[Multiplier],Variable);
+#endif
+}
+
+void MoveVariableToX86regByte(void *Variable, int32_t x86reg) {
+ OPCODE_REG_VARIABLE(,8,0x8A,x86reg,Variable);
+}
+
+void MoveVariableToX86regHalf(void *Variable, int32_t x86reg) {
+ BreakPoint();
+ OPCODE_REG_VARIABLE(PUTDST8(RecompPos,0x66),8,0x8B,x86reg,Variable);
+}
+
+void MoveX86regByteToVariable(int32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x88,x86reg,Variable);
+}
+
+void MoveX86regByteToX86regPointer(int32_t x86reg, int32_t AddrReg1, int32_t AddrReg2) {
+ OPCODE_REG_BASE_INDEX(8,0x88,x86reg,AddrReg1,AddrReg2);
+}
+
+void MoveX86regHalfToVariable(int32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(PUTDST8(RecompPos,0x66), 8,0x89,x86reg,Variable);
+}
+
+void MoveX86regHalfToX86regPointer(int32_t x86reg, int32_t AddrReg1, int32_t AddrReg2) {
+ PUTDST8(RecompPos,0x66);
+ OPCODE_REG_BASE_INDEX(8,0x89,x86reg,AddrReg1,AddrReg2);
+}
+
+void MoveX86PointerToX86reg(int32_t x86reg, int32_t X86Pointer) {
+ OPCODE_REG_MREG(8,0x8B,x86reg,X86Pointer);
+}
+
+void MoveX86regPointerToX86reg(int32_t AddrReg1, int32_t AddrReg2, int32_t x86reg) {
+ OPCODE_REG_BASE_INDEX(8,0x8B,x86reg,AddrReg1,AddrReg2);
+}
+
+void MoveX86regPointerToX86regDisp8(int32_t AddrReg1, int32_t AddrReg2, int32_t x86reg, uint8_t offset) {
+ OPCODE_REG_BASE_INDEX_IMM8(8,0x8B,x86reg,AddrReg1,AddrReg2,offset);
+}
+
+void MoveX86regToMemory(int32_t x86reg, int32_t AddrReg, uint32_t Disp) {
+ OPCODE_REG_MREG_IMM32(8,0x89,x86reg,AddrReg,Disp);
+}
+
+void MoveX86regToVariable(int32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x89,x86reg,Variable);
+}
+
+void MoveX86RegToX86Reg(int32_t Source, int32_t Destination) {
+ OPCODE_REG_REG(8,0x89,Source|X64_Reg, Destination|X64_Reg);
+}
+
+void MoveX86regToX86Pointer(int32_t x86reg, int32_t X86Pointer) {
+ OPCODE_REG_MREG(8,0x89,x86reg, X86Pointer);
+}
+
+void MoveX86regToX86regPointer(int32_t x86reg, int32_t AddrReg1, int32_t AddrReg2) {
+ OPCODE_REG_BASE_INDEX(8,0x89,x86reg,AddrReg1,AddrReg2);
+}
+
+void MoveZxByteX86regPointerToX86reg(int32_t AddrReg1, int32_t AddrReg2, int32_t x86reg) {
+ OPCODE_REG_BASE_INDEX(16,0xB60F,x86reg,AddrReg1,AddrReg2);
+}
+
+void MoveZxHalfX86regPointerToX86reg(int32_t AddrReg1, int32_t AddrReg2, int32_t x86reg) {
+ OPCODE_REG_BASE_INDEX(16,0xB70F,x86reg,AddrReg1,AddrReg2);
+}
+
+void MoveZxVariableToX86regByte(void *Variable, int32_t x86reg) {
+ OPCODE_REG_VARIABLE(,16,0xB60F,x86reg,Variable);
+}
+
+void MoveZxVariableToX86regHalf(void *Variable, int32_t x86reg) {
+ OPCODE_REG_VARIABLE(,16,0xB70F,x86reg,Variable);
+}
+
+void MulX86reg(int32_t x86reg) {
+ OPCODE_REG_REG(8,0xF7,OP_D4,x86reg);
+}
+
+void NotX86Reg(int32_t x86reg) {
+ OPCODE_REG_REG(8,0xF7,OP_D2,x86reg);
+}
+
+void OrConstToVariable(uint32_t Const, void * Variable) {
+ if(Const < 0x80) {
+ OPCODE_REG_VARIABLE(,8,0x83,OP_D1,Variable);
+ PUTDST8(RecompPos,Const);
+ } else {
+ OPCODE_REG_VARIABLE(,8,0x81,OP_D1,Variable);
+ PUTDST32(RecompPos,Const);
+ }
+}
+
+void OrConstToX86Reg(uint32_t Const, int32_t x86reg) {
+ if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) {
+ OPCODE_REG_REG(8,0x81,OP_D1,x86reg);
+ PUTDST32(RecompPos, Const);
+ } else {
+ OPCODE_REG_REG(8,0x83,OP_D1,x86reg);
+ PUTDST8(RecompPos, Const);
+ }
+}
+
+void OrVariableToX86Reg(void * Variable, int32_t x86reg) {
+ OPCODE_REG_VARIABLE(,8,0xb,x86reg,Variable);
+}
+
+void OrX86RegToVariable(void * Variable, int32_t x86reg) {
+ OPCODE_REG_VARIABLE(,8,0x9,x86reg,Variable);
+}
+
+void OrX86RegToX86Reg(int32_t Destination, int32_t Source) {
+ OPCODE_REG_REG(8,0x0B,Destination,Source);
+}
+
+void Pushfd() {
+ PUTDST8(RecompPos,0x9c);
+}
+
+void Popfd() {
+ PUTDST8(RecompPos,0x9d);
+}
+
+void Popad(void) {
+#ifdef USEX64
+ PUTDST16(RecompPos,0x5f41);
+ PUTDST16(RecompPos,0x5e41);
+ PUTDST16(RecompPos,0x5d41);
+ PUTDST16(RecompPos,0x5c41);
+ PUTDST16(RecompPos,0x5b41);
+ PUTDST16(RecompPos,0x5a41);
+ PUTDST16(RecompPos,0x5941);
+ PUTDST16(RecompPos,0x5841);
+ PUTDST8(RecompPos,0x5f);
+ PUTDST8(RecompPos,0x5e);
+ PUTDST8(RecompPos,0x5b);
+ PUTDST8(RecompPos,0x5a);
+ PUTDST8(RecompPos,0x59);
+ PUTDST8(RecompPos,0x58);
+#else
+ PUTDST8(RecompPos,0x61);
+#endif
+
+}
+
+void Pushad(void) {
+#ifdef USEX64
+ PUTDST8(RecompPos,0x50);
+ PUTDST8(RecompPos,0x51);
+ PUTDST8(RecompPos,0x52);
+ PUTDST8(RecompPos,0x53);
+ PUTDST8(RecompPos,0x56);
+ PUTDST8(RecompPos,0x57);
+ PUTDST16(RecompPos,0x5041);
+ PUTDST16(RecompPos,0x5141);
+ PUTDST16(RecompPos,0x5241);
+ PUTDST16(RecompPos,0x5341);
+ PUTDST16(RecompPos,0x5441);
+ PUTDST16(RecompPos,0x5541);
+ PUTDST16(RecompPos,0x5641);
+ PUTDST16(RecompPos,0x5741);
+#else
+ PUTDST8(RecompPos,0x60);
+#endif
+}
+
+void Push(int32_t x86reg) {
+#ifdef USEX64
+ PUTDST8(RecompPos, 0x40 | ((x86reg & 0x20) >> 5));
+#endif
+ switch(x86reg&0xf) {
+ case x86_EAX: PUTDST8(RecompPos, 0x50); break;
+ case x86_EBX: PUTDST8(RecompPos, 0x53); break;
+ case x86_ECX: PUTDST8(RecompPos, 0x51); break;
+ case x86_EDX: PUTDST8(RecompPos, 0x52); break;
+ case x86_ESI: PUTDST8(RecompPos, 0x56); break;
+ case x86_EDI: PUTDST8(RecompPos, 0x57); break;
+ case x86_ESP: PUTDST8(RecompPos, 0x54); break;
+ case x86_EBP: PUTDST8(RecompPos, 0x55); break;
+ }
+}
+
+void Pop(int32_t x86reg) {
+#ifdef USEX64
+ PUTDST8(RecompPos, 0x40 | ((x86reg & 0x20) >> 5));
+#endif
+ switch(x86reg&0xf) {
+
+ case x86_EAX: PUTDST8(RecompPos, 0x58); break;
+ case x86_EBX: PUTDST8(RecompPos, 0x5B); break;
+ case x86_ECX: PUTDST8(RecompPos, 0x59); break;
+ case x86_EDX: PUTDST8(RecompPos, 0x5A); break;
+ case x86_ESI: PUTDST8(RecompPos, 0x5E); break;
+ case x86_EDI: PUTDST8(RecompPos, 0x5F); break;
+ case x86_ESP: PUTDST8(RecompPos, 0x5C); break;
+ case x86_EBP: PUTDST8(RecompPos, 0x5D); break;
+ }
+}
+
+void PushImm32(uint32_t Value) {
+ PUTDST8(RecompPos,0x68);
+ PUTDST32(RecompPos,Value);
+}
+
+void Ret(void) {
+ PUTDST8(RecompPos,0xC3);
+}
+
+void Seta(int32_t x86reg) {
+ OPCODE_REG_REG(16,0x970F,OP_D0,x86reg);
+}
+
+void SetaVariable(void * Variable) {
+ OPCODE_REG_VARIABLE(,16,0x970F,OP_D0,Variable);
+}
+
+void Setae(int32_t x86reg) {
+ OPCODE_REG_REG(16,0x930F,OP_D0,x86reg);
+}
+
+void Setb(int32_t x86reg) {
+ OPCODE_REG_REG(16,0x920F,OP_D0,x86reg);
+}
+
+void SetbVariable(void * Variable) {
+ OPCODE_REG_VARIABLE(,16,0x920F,OP_D0,Variable);
+}
+
+void Setg(int32_t x86reg) {
+ OPCODE_REG_REG(16,0x9F0F,OP_D0,x86reg);
+}
+
+void SetgVariable(void * Variable) {
+ OPCODE_REG_VARIABLE(,16,0x9F0F,OP_D0,Variable);
+}
+
+void Setl(int32_t x86reg) {
+ OPCODE_REG_REG(16,0x9C0F,OP_D0,x86reg);
+}
+
+void SetlVariable(void * Variable) {
+ OPCODE_REG_VARIABLE(,16,0x9C0F,OP_D0,Variable);
+}
+
+
+void Setz(int32_t x86reg) {
+ OPCODE_REG_REG(16,0x940F,OP_D0,x86reg);
+}
+
+void Setnz(int32_t x86reg) {
+ OPCODE_REG_REG(16,0x950F,OP_D0,x86reg);
+}
+
+void ShiftLeftDouble(int32_t Destination, int32_t Source) {
+ OPCODE_REG_REG(16,0xA50F,Source,Destination);
+}
+
+void ShiftLeftDoubleImmed(int32_t Destination, int32_t Source, uint8_t Immediate) {
+ OPCODE_REG_REG(16,0xA40F,Source,Destination);
+ PUTDST8(RecompPos,Immediate);
+}
+
+void ShiftLeftSign(int32_t x86reg) {
+ OPCODE_REG_REG(8,0xD3,OP_D4,x86reg);
+}
+
+void ShiftLeftSignImmed(int32_t x86reg, uint8_t Immediate) {
+ OPCODE_REG_REG(8,0xC1,OP_D4,x86reg);
+ PUTDST8(RecompPos,Immediate);
+}
+
+void ShiftRightSign(int32_t x86reg) {
+ OPCODE_REG_REG(8,0xD3,OP_D7,x86reg);
+}
+
+void ShiftRightSignImmed(int32_t x86reg, uint8_t Immediate) {
+ OPCODE_REG_REG(8,0xC1,OP_D7,x86reg);
+ PUTDST8(RecompPos,Immediate);
+}
+
+void ShiftRightUnsign(int32_t x86reg) {
+ OPCODE_REG_REG(8,0xD3,OP_D5,x86reg);
+}
+
+void ShiftRightDouble(int32_t Destination, int32_t Source) {
+ OPCODE_REG_REG(16,0xAD0F,Source,Destination);
+}
+
+void ShiftRightDoubleImmed(int32_t Destination, int32_t Source, uint8_t Immediate) {
+ OPCODE_REG_REG(16,0xAC0F,Source,Destination);
+ PUTDST8(RecompPos,Immediate);
+}
+
+void ShiftRightUnsignImmed(int32_t x86reg, uint8_t Immediate) {
+ OPCODE_REG_REG(8,0xC1,OP_D5,x86reg);
+ PUTDST8(RecompPos,Immediate);
+}
+
+void SbbConstFromX86Reg (int32_t x86reg, uint32_t Const) {
+ if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) {
+ OPCODE_REG_REG(8,0x81,OP_D3,x86reg);
+ PUTDST32(RecompPos, Const);
+ } else {
+ OPCODE_REG_REG(8,0x83,OP_D3,x86reg);
+ PUTDST8(RecompPos, Const);
+ }
+}
+
+void SbbVariableFromX86reg(int32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x1b,x86reg,Variable);
+}
+
+void SbbX86RegToX86Reg(int32_t Destination, int32_t Source) {
+ OPCODE_REG_REG(8,0x1B,Destination,Source);
+}
+
+void SubConstFromVariable (uint32_t Const, void *Variable) {
+ OPCODE_REG_VARIABLE(,8,0x81,OP_D5,Variable);
+ PUTDST32(RecompPos,Const);
+}
+
+void SubConstFromX86Reg (int32_t x86reg, uint32_t Const) {
+ if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) {
+ OPCODE_REG_REG(8,0x81,OP_D5,x86reg);
+ PUTDST32(RecompPos, Const);
+ } else {
+ OPCODE_REG_REG(8,0x83,OP_D5,x86reg);
+ PUTDST8(RecompPos, Const);
+ }
+}
+
+void SubVariableFromX86reg(int32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x2B,x86reg,Variable);
+}
+
+void SubX86RegToX86Reg(int32_t Destination, int32_t Source) {
+ OPCODE_REG_REG(8,0x2B,Destination,Source);
+}
+
+void TestConstToX86Reg(uint32_t Const, int32_t x86reg) {
+ OPCODE_REG_REG(8,0xF7,OP_D0,x86reg);
+ PUTDST32(RecompPos,Const);
+}
+
+void TestVariable(uint32_t Const, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0xf7,OP_D0,Variable);
+ PUTDST32(RecompPos,Const);
+}
+
+void TestX86RegToX86Reg(int32_t Destination, int32_t Source) {
+ OPCODE_REG_REG(8,0x85,Destination,Source);
+}
+
+void TestVariableToX86Reg(uint32_t x86reg, void * Variable) {
+ OPCODE_REG_VARIABLE(,8,0x85,x86reg,Variable);
+}
+
+void XorConstToX86Reg(int32_t x86reg, uint32_t Const) {
+ if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) {
+ OPCODE_REG_REG(8,0x81,OP_D6,x86reg);
+ PUTDST32(RecompPos, Const);
+ } else {
+ OPCODE_REG_REG(8,0x83,OP_D6,x86reg);
+ PUTDST8(RecompPos, Const);
+ }
+}
+
+void XorX86RegToX86Reg(int32_t Source, int32_t Destination) {
+ OPCODE_REG_REG(8,0x31,Destination,Source);
+}
+
+void XorVariableToX86reg(void *Variable, int32_t x86reg) {
+ OPCODE_REG_VARIABLE(,8,0x33,x86reg,Variable);
+}
+
+
diff --git a/src/usf/x86.h b/src/usf/x86.h new file mode 100644 index 0000000..751f63d --- /dev/null +++ b/src/usf/x86.h @@ -0,0 +1,544 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+
+
+#define PUTDST8(dest,value) {(*((uint8_t *)(dest))=(uint8_t)(value)); dest += 1;}
+#define PUTDST16(dest,value) {(*((uint16_t *)(dest))=(uint16_t)(value)); dest += 2;}
+#define PUTDST32(dest,value) {(*((uint32_t *)(dest))=(uint32_t)(value)); dest += 4;}
+#define PUTDST64(dest,value) {(*((uint64_t *)(dest))=(uint64_t)(value)); dest += 8;}
+
+#include "types.h"
+
+#ifdef USEX64
+
+#define x64_Reg 0x10
+#define X64_Reg 0x10
+#define X64_Ext 0x20
+
+extern uint8_t Index[9];
+
+enum x86RegValues {
+
+ x86_Any = 0,
+ x86_EAX,x86_ECX,x86_EDX,x86_EBX,x86_ESP,x86_EBP,x86_ESI,x86_EDI,x86_Any8Bit=0x40,x64_Any = 0x40,
+
+ x86_RAX = 0x11,x86_RCX,x86_RDX,x86_RBX,x86_RSP,x86_RBP,x86_RSI,x86_RDI,
+
+ x86_R8D = 0x21,x86_R9D,x86_R10D,x86_R11D,x86_R12D,x86_R13D,x86_R14D,x86_R15D,
+
+ x86_R8 = 0x31,x86_R9,x86_R10,x86_R11,x86_R12,x86_R13,x86_R14,x86_R15,
+
+};
+
+enum x86FpuValues {
+ x86_ST0,x86_ST1,x86_ST2,x86_ST3,x86_ST4,x86_ST5,x86_ST6,x86_ST7
+};
+
+#define x86_TEMP x86_R8
+#define x86_TEMPD x86_R8D
+
+#define OP_D0 1
+#define OP_D1 2
+#define OP_D2 3
+#define OP_D3 4
+#define OP_D4 5
+#define OP_D5 6
+#define OP_D6 7
+#define OP_D7 8
+
+#define LOAD_VARIABLE(reg,variable) \
+ PUTDST8(RecompPos, 0x48 | (((reg)&0x20)>>5)); \
+ PUTDST8(RecompPos,0xB8 | ((reg)-1)&0xf); \
+ PUTDST64(RecompPos,variable);
+
+// // 43 0F B6 0C 0D 40 83 C7 04 movzx ecx,byte ptr [r9+4C78340h]
+
+#define OPCODE_REG_REG(oplen,opcode,reg,rm) \
+ PUTDST8(RecompPos, 0x40 | (((rm)&0x20)>>5) | ((((rm|reg))&0x10)>>1) | (((reg)&0x20)>>3)); \
+ PUTDST##oplen (RecompPos, opcode); \
+ PUTDST8(RecompPos, 0xC0 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3));
+
+#define OPCODE_REG_MREG(oplen,opcode,reg,rm) \
+ PUTDST8(RecompPos, 0x40 | (((rm)&0x20)>>5) | (((reg)&0x10)>>1) | (((reg)&0x20)>>3)); \
+ PUTDST##oplen (RecompPos, opcode); \
+ if(((rm)&0xf)==0x6) { \
+ PUTDST8(RecompPos, 0x40 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, 0); \
+ } else if(((rm)&0xf)==0x5) { \
+ PUTDST8(RecompPos, 0x0 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, 0x24); \
+ } else { \
+ PUTDST8(RecompPos, 0x00 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ }
+
+#define OPCODE_REG_MREG_IMM32(oplen,opcode,reg,rm,imm32) \
+ PUTDST8(RecompPos, 0x40 | (((rm)&0x20)>>5) | (((reg)&0x10)>>1) | (((reg)&0x20)>>3)); \
+ PUTDST##oplen (RecompPos, opcode); \
+ if(((rm)&0xf)==0x5) { \
+ PUTDST8(RecompPos, 0x80 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, 0x24); \
+ } else { \
+ PUTDST8(RecompPos, 0x80 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ } \
+ PUTDST32(RecompPos,imm32);
+
+#define OPCODE_REG_BASE_INDEX(oplen,opcode,reg,base,index) \
+ PUTDST8(RecompPos, 0x40 | (((base)&0x20)>>5) | (((reg)&0x10)>>1) | (((reg)&0x20)>>3)| (((index)&0x20)>>4)); \
+ PUTDST##oplen (RecompPos, opcode); \
+ if(((base)&0xf)!=0x6) { \
+ PUTDST8(RecompPos, 0x04 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, 0x00 | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ } else {\
+ PUTDST8(RecompPos, 0x44 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, 0x00 | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST8(RecompPos, 0); \
+ }
+
+#define OPCODE_REG_MREG_IMM8(oplen,opcode,reg,rm,imm8) \
+ PUTDST8(RecompPos, 0x40 | (((rm)&0x20)>>5) | (((reg)&0x10)>>1) | (((reg)&0x20)>>3)); \
+ PUTDST##oplen (RecompPos, opcode); \
+ PUTDST8(RecompPos, 0x40 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ PUTDST32(RecompPos,imm8);
+
+/*scale is: 0=1,0x40=2,0x80=4,0xc0=8 ??*/
+
+#define OPCODE_REG_INDEX_SCALE(oplen,opcode,reg,base,index,scale) \
+ PUTDST8(RecompPos, 0x40 | (((base)&0x20)>>5) | (((reg)&0x10)>>1) | (((reg)&0x20)>>3)| (((index)&0x20)>>4)); \
+ PUTDST##oplen (RecompPos, opcode); \
+ PUTDST8(RecompPos, 0x04 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, (((scale)-1)*0x40) | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) );
+
+#define OPCODE_REG_BASE_INDEX_SCALE(oplen,opcode,reg,base,index,scale) \
+ PUTDST8(RecompPos, 0x40 | (((base)&0x20)>>5) | (((reg)&0x10)>>1) | (((reg)&0x20)>>3)| (((index)&0x20)>>4)); \
+ PUTDST##oplen (RecompPos, opcode); \
+ PUTDST8(RecompPos, 0x04 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, (scale) | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) );
+
+#define OPCODE_REG_BASE_INDEX_SCALE_IMM32(oplen,opcode,reg,base,index,scale,imm32) \
+ PUTDST8(RecompPos, 0x40 | (((base)&0x20)>>5) | (((reg)&0x10)>>1) | (((reg)&0x20)>>3)| (((index)&0x20)>>4)); \
+ PUTDST##oplen (RecompPos, opcode); \
+ PUTDST8(RecompPos, 0x84 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, (scale) | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST32(RecompPos,imm32);
+
+#define OPCODE_REG_BASE_INDEX_SCALE_IMM8(oplen,opcode,reg,base,index,scale,imm32) \
+ PUTDST8(RecompPos, 0x40 | (((base)&0x20)>>5) | (((reg)&0x10)>>1) | (((reg)&0x20)>>3)| (((index)&0x20)>>4)); \
+ PUTDST##oplen (RecompPos, opcode); \
+ PUTDST8(RecompPos, 0x44 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, (scale) | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST32(RecompPos,imm32);
+
+
+#define OPCODE_REG_BASE_INDEX_IMM8(oplen,opcode,reg,base,index,imm8) \
+ PUTDST8(RecompPos, 0x40 | (((base)&0x20)>>5) | (((reg)&0x10)>>1) | (((reg)&0x20)>>3)| (((index)&0x20)>>4)); \
+ PUTDST##oplen (RecompPos, opcode); \
+ PUTDST8(RecompPos, 0x44 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST8(RecompPos, imm8);
+
+#define OPCODE_REG_BASE_INDEX_IMM32(oplen,opcode,reg,base,index,imm32) \
+ PUTDST8(RecompPos, 0x40 | (((base)&0x20)>>5) | (((reg)&0x10)>>1) | (((reg)&0x20)>>3)| (((index)&0x20)>>4)); \
+ PUTDST##oplen (RecompPos, opcode); \
+ PUTDST8(RecompPos, 0x44 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST8(RecompPos, imm32);
+
+#else /* !USEX64 */
+
+#define x64_Reg 0
+#define X64_Reg 0
+#define X64_Ext 0
+
+
+extern uint8_t Index[9];
+
+enum x86RegValues {
+
+ x64_Any = 0, x86_Any = 0,
+ x86_EAX,x86_ECX,x86_EDX,x86_EBX,x86_ESP,x86_EBP,x86_ESI,x86_EDI,x86_Any8Bit=0x40,
+
+};
+
+enum x86FpuValues {
+ x86_ST0,x86_ST1,x86_ST2,x86_ST3,x86_ST4,x86_ST5,x86_ST6,x86_ST7
+};
+
+#define OP_D0 1
+#define OP_D1 2
+#define OP_D2 3
+#define OP_D3 4
+#define OP_D4 5
+#define OP_D5 6
+#define OP_D6 7
+#define OP_D7 8
+
+// // 43 0F B6 0C 0D 40 83 C7 04 movzx ecx,byte ptr [r9+4C78340h]
+
+#define OPCODE_REG_DISP(oplen,opcode,reg,disp32) \
+ PUTDST##oplen (RecompPos, opcode); \
+ PUTDST8(RecompPos, 0x5 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST32(RecompPos,disp32);
+
+#define OPCODE_REG_REG(oplen,opcode,reg,rm) \
+ PUTDST##oplen (RecompPos, opcode); \
+ PUTDST8(RecompPos, 0xC0 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3));
+
+#define OPCODE_REG_MREG(oplen,opcode,reg,rm) \
+ PUTDST##oplen (RecompPos, opcode); \
+ if(((rm)&0xf)==0x6) { \
+ PUTDST8(RecompPos, 0x40 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, 0); \
+ } else if(((rm)&0xf)==0x5) { \
+ PUTDST8(RecompPos, 0x0 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, 0x24); \
+ } else { \
+ PUTDST8(RecompPos, 0x00 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ }
+
+#define OPCODE_REG_MREG_IMM32(oplen,opcode,reg,rm,imm32) \
+ PUTDST##oplen (RecompPos, opcode); \
+ if(((rm)&0xf)==0x5) { \
+ PUTDST8(RecompPos, 0x80 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, 0x24); \
+ } else { \
+ PUTDST8(RecompPos, 0x80 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ } \
+ PUTDST32(RecompPos,imm32);
+
+#define OPCODE_REG_BASE_INDEX(oplen,opcode,reg,base,index) \
+ PUTDST##oplen (RecompPos, opcode); \
+ if(((base)&0xf)!=0x6) { \
+ PUTDST8(RecompPos, 0x04 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, 0x00 | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ } else {\
+ PUTDST8(RecompPos, 0x44 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, 0x00 | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST8(RecompPos, 0); \
+ }
+
+#define OPCODE_REG_MREG_IMM8(oplen,opcode,reg,rm,imm8) \
+ PUTDST##oplen (RecompPos, opcode); \
+ PUTDST8(RecompPos, 0x40 | (((rm)-1)&0x7) | ((((reg)-1)&0x7) << 3)); \
+ PUTDST32(RecompPos,imm8);
+
+/*scale is: 0=1,0x40=2,0x80=4,0xc0=8 ??*/
+
+#define OPCODE_REG_INDEX_SCALE(oplen,opcode,reg,base,index,scale) \
+ PUTDST##oplen (RecompPos, opcode); \
+ PUTDST8(RecompPos, 0x04 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, (((scale)-1)*0x40) | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) );
+
+#define OPCODE_REG_BASE_INDEX_SCALE(oplen,opcode,reg,base,index,scale) \
+ PUTDST##oplen (RecompPos, opcode); \
+ PUTDST8(RecompPos, 0x04 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, (scale) | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) );
+
+#define OPCODE_REG_BASE_INDEX_SCALE_IMM32(oplen,opcode,reg,base,index,scale,imm32) \
+ PUTDST##oplen (RecompPos, opcode); \
+ PUTDST8(RecompPos, 0x84 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, (scale) | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST32(RecompPos,imm32);
+
+#define OPCODE_REG_BASE_INDEX_SCALE_IMM8(oplen,opcode,reg,base,index,scale,imm32) \
+ PUTDST##oplen (RecompPos, opcode); \
+ PUTDST8(RecompPos, 0x44 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, (scale) | (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST32(RecompPos,imm32);
+
+
+#define OPCODE_REG_BASE_INDEX_IMM8(oplen,opcode,reg,base,index,imm8) \
+ PUTDST##oplen (RecompPos, opcode); \
+ PUTDST8(RecompPos, 0x44 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST8(RecompPos, imm8);
+
+#define OPCODE_REG_BASE_INDEX_IMM32(oplen,opcode,reg,base,index,imm32) \
+ PUTDST##oplen (RecompPos, opcode); \
+ PUTDST8(RecompPos, 0x44 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, (((base)-1)&0x7) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST8(RecompPos, imm32);
+
+#define OPCODE_REG_INDEX_SCALE_IMM32(oplen,opcode,reg,index,scale,imm32) \
+ PUTDST##oplen (RecompPos, opcode); \
+ PUTDST8(RecompPos, 0x4 | ((((reg)-1)&0x7) << 3)); \
+ PUTDST8(RecompPos, 0x5 | (scale) | ((((index)-1)&0x7) << 3) ); \
+ PUTDST32(RecompPos,imm32);
+
+#endif
+
+#ifndef USEX64
+
+#define OPCODE_REG_VARIABLE(PREFIX,oplen,opcode,reg,variable) \
+ PREFIX \
+ OPCODE_REG_DISP(oplen,opcode,reg,variable);
+#else
+
+#define OPCODE_REG_VARIABLE(PREFIX,oplen,opcode,reg,Variable) \
+ if(((uintptr_t)(Variable) - (uintptr_t)TLB_Map) < 0x7FFFFFFF) { \
+ PREFIX \
+ OPCODE_REG_MREG_IMM32(oplen,opcode,reg,x86_R15,(uintptr_t)(Variable) - (uintptr_t)TLB_Map); \
+ } else { \
+ LOAD_VARIABLE(x86_TEMP, (Variable)); \
+ PREFIX \
+ OPCODE_REG_MREG(oplen,opcode,reg,x86_TEMP); \
+ }
+#endif
+
+#ifdef USEX64
+ #define LOAD_FROM_TLB(dstreg,srcreg) MoveX86RegDispToX86Reg(dstreg, x86_R15, srcreg, 8);
+#else
+ #define LOAD_FROM_TLB(dstreg,srcreg) MoveVariableDispToX86Reg(TLB_Map,dstreg,srcreg,4);
+#endif
+
+
+void MoveX86RegDispToX86Reg(int32_t x86Reg, int32_t AddrReg, int32_t IndexReg, int32_t Multiplier);
+void MoveVariableToX86reg64(void *Variable, int32_t x86reg);
+void MovePointerToX86reg(void *Variable, int32_t x86reg);
+void AddConstToX86Reg64 (int32_t x86Reg, uint32_t Const);
+void MoveConstQwordToX86reg(uint64_t Const, int32_t x86reg);
+
+void AdcX86regToVariable ( int32_t x86reg, void * Variable );
+void AdcConstToVariable ( void *Variable, uint8_t Constant );
+void AdcConstToX86Reg ( int32_t x86Reg, uint32_t Const );
+void AdcVariableToX86reg ( int32_t x86reg, void * Variable );
+void AdcX86RegToX86Reg ( int32_t Destination, int32_t Source );
+void AddConstToVariable ( uint32_t Const, void *Variable );
+void AddConstToX86Reg ( int32_t x86Reg, uint32_t Const );
+void AddVariableToX86reg ( int32_t x86reg, void * Variable );
+void AddX86regToVariable ( int32_t x86reg, void * Variable );
+void AddX86RegToX86Reg ( int32_t Destination, int32_t Source );
+void AndConstToVariable ( uint32_t Const, void *Variable );
+void AndConstToX86Reg ( int32_t x86Reg, uint32_t Const );
+void AndVariableToX86Reg ( void * Variable, int32_t x86Reg );
+void AndVariableDispToX86Reg ( void * Variable, int32_t x86Reg, int32_t AddrReg, int32_t Multiplier);
+void AndX86RegToX86Reg ( int32_t Destination, int32_t Source );
+void BreakPoint ( void );
+void Call_Direct ( void * FunctAddress);
+void Call_Indirect ( void * FunctAddress);
+void CompConstToVariable ( uint32_t Const, void * Variable );
+void CompConstToX86reg ( int32_t x86Reg, uint32_t Const );
+void CompX86regToVariable ( int32_t x86Reg, void * Variable );
+void CompVariableToX86reg ( int32_t x86Reg, void * Variable );
+void CompX86RegToX86Reg ( int32_t Destination, int32_t Source );
+void DecX86reg ( int32_t x86Reg );
+void DivX86reg ( int32_t x86reg );
+void idivX86reg ( int32_t x86reg );
+void imulX86reg ( int32_t x86reg );
+void IncX86reg ( int32_t x86Reg );
+void JaeLabel8 ( uint8_t Value );
+void JaeLabel32 ( uint32_t Value );
+void JaLabel8 ( uint8_t Value );
+void JaLabel32 ( uint32_t Value );
+void JbLabel8 ( uint8_t Value );
+void JbLabel32 ( uint32_t Value );
+void JecxzLabel8 ( uint8_t Value );
+void JeLabel8 ( uint8_t Value );
+void JeLabel32 ( uint32_t Value );
+void JgeLabel32 ( uint32_t Value );
+void JgLabel8 ( uint8_t Value );
+void JgLabel32 ( uint32_t Value );
+void JleLabel8 ( uint8_t Value );
+void JleLabel32 ( uint32_t Value );
+void JlLabel8 ( uint8_t Value );
+void JlLabel32 ( uint32_t Value );
+void JzLabel8 ( uint8_t Value );
+void JnzLabel8 ( uint8_t Value );
+void JmpDirectReg ( int32_t x86reg );
+void JmpIndirectLabel32 ( uint32_t location );
+void JmpIndirectReg ( int32_t x86reg );
+void JmpLabel8 ( uint8_t Value );
+void JmpLabel32 ( uint32_t Value );
+void JneLabel8 ( uint8_t Value );
+void JneLabel32 ( uint32_t Value );
+void JnsLabel8 ( uint8_t Value );
+void JnsLabel32 ( uint32_t Value );
+void JsLabel32 ( uint32_t Value );
+void LeaRegReg ( int32_t x86RegDest, int32_t x86RegSrc, int32_t multiplier );
+void LeaSourceAndOffset ( int32_t x86DestReg, int32_t x86SourceReg, int32_t offset );
+void MoveConstByteToN64Mem ( uint8_t Const, int32_t AddrReg );
+void MoveConstHalfToN64Mem ( uint16_t Const, int32_t AddrReg );
+void MoveConstByteToVariable ( uint8_t Const,void *Variable );
+void MoveConstByteToX86regPointer ( uint8_t Const, int32_t AddrReg1, int32_t AddrReg2 );
+void MoveConstHalfToVariable ( uint16_t Const, void *Variable );
+void MoveConstHalfToX86regPointer ( uint16_t Const, int32_t AddrReg1, int32_t AddrReg2 );
+void MoveConstToMemoryDisp ( uint32_t Const, int32_t AddrReg, uint32_t Disp );
+void MoveConstToN64Mem ( uint32_t Const, int32_t AddrReg );
+void MoveConstToN64MemDisp ( uint32_t Const, int32_t AddrReg, uint8_t Disp );
+void MoveConstToVariable ( uint32_t Const, void *Variable );
+void MoveConstToX86Pointer ( uint32_t Const, int32_t X86Pointer );
+void MoveConstToX86reg ( uint32_t Const, int32_t x86reg );
+void MoveConstToX86regPointer ( uint32_t Const, int32_t AddrReg1, int32_t AddrReg2 );
+void MoveN64MemDispToX86reg ( int32_t x86reg, int32_t AddrReg, uint8_t Disp );
+void MoveN64MemToX86reg ( int32_t x86reg, int32_t AddrReg );
+void MoveN64MemToX86regByte ( int32_t x86reg, int32_t AddrReg );
+void MoveN64MemToX86regHalf ( int32_t x86reg, int32_t AddrReg );
+void MoveSxByteX86regPointerToX86reg ( int32_t AddrReg1, int32_t AddrReg2, int32_t x86reg );
+void MoveSxHalfX86regPointerToX86reg ( int32_t AddrReg1, int32_t AddrReg2, int32_t x86reg );
+void MoveSxN64MemToX86regByte ( int32_t x86reg, int32_t AddrReg );
+void MoveSxN64MemToX86regHalf ( int32_t x86reg, int32_t AddrReg );
+void MoveSxVariableToX86regByte ( void *Variable, int32_t x86reg );
+void MoveSxVariableToX86regHalf ( void *Variable, int32_t x86reg );
+void MoveVariableDispToX86Reg ( void *Variable, int32_t x86Reg, int32_t AddrReg, int32_t Multiplier );
+void MoveVariableToX86reg ( void *Variable, int32_t x86reg );
+void MoveVariableToX86regByte ( void *Variable, int32_t x86reg );
+void MoveVariableToX86regHalf ( void *Variable, int32_t x86reg );
+void MoveX86PointerToX86reg ( int32_t x86reg, int32_t X86Pointer );
+void MoveX86regByteToN64Mem ( int32_t x86reg, int32_t AddrReg );
+void MoveX86regByteToVariable ( int32_t x86reg, void * Variable );
+void MoveX86regByteToX86regPointer ( int32_t x86reg, int32_t AddrReg1, int32_t AddrReg2 );
+void MoveX86regHalfToN64Mem ( int32_t x86reg, int32_t AddrReg );
+void MoveX86regHalfToVariable ( int32_t x86reg, void * Variable );
+void MoveX86regHalfToX86regPointer ( int32_t x86reg, int32_t AddrReg1, int32_t AddrReg2 );
+void MoveX86regPointerToX86reg ( int32_t AddrReg1, int32_t AddrReg2, int32_t x86reg );
+void MoveX86regPointerToX86regDisp8 ( int32_t AddrReg1, int32_t AddrReg2, int32_t x86reg, uint8_t offset );
+void MoveX86regToMemory ( int32_t x86reg, int32_t AddrReg, uint32_t Disp );
+void MoveX86regToN64Mem ( int32_t x86reg, int32_t AddrReg );
+void MoveX86regToN64MemDisp ( int32_t x86reg, int32_t AddrReg, uint8_t Disp );
+void MoveX86regToVariable ( int32_t x86reg, void * Variable );
+void MoveX86RegToX86Reg ( int32_t Source, int32_t Destination );
+void MoveX86regToX86Pointer ( int32_t x86reg, int32_t X86Pointer );
+void MoveX86regToX86regPointer ( int32_t x86reg, int32_t AddrReg1, int32_t AddrReg2 );
+void MoveZxByteX86regPointerToX86reg ( int32_t AddrReg1, int32_t AddrReg2, int32_t x86reg );
+void MoveZxHalfX86regPointerToX86reg ( int32_t AddrReg1, int32_t AddrReg2, int32_t x86reg );
+void MoveZxN64MemToX86regByte ( int32_t x86reg, int32_t AddrReg );
+void MoveZxN64MemToX86regHalf ( int32_t x86reg, int32_t AddrReg );
+void MoveZxVariableToX86regByte ( void *Variable, int32_t x86reg );
+void MoveZxVariableToX86regHalf ( void *Variable, int32_t x86reg );
+void MulX86reg ( int32_t x86reg );
+void NotX86Reg ( int32_t x86Reg );
+void OrConstToVariable ( uint32_t Const, void * Variable );
+void OrConstToX86Reg ( uint32_t Const, int32_t x86Reg );
+void OrVariableToX86Reg ( void * Variable, int32_t x86Reg );
+void OrX86RegToVariable ( void * Variable, int32_t x86Reg );
+void OrX86RegToX86Reg ( int32_t Destination, int32_t Source );
+void Popad ( void );
+void Pushad ( void );
+void Push ( int32_t x86reg );
+void Pop ( int32_t x86reg );
+void PushImm32 ( uint32_t Value );
+void Ret ( void );
+void Seta ( int32_t x86reg );
+void Setae ( int32_t x86reg );
+void SetaVariable ( void * Variable );
+void Setb ( int32_t x86reg );
+void SetbVariable ( void * Variable );
+void Setg ( int32_t x86reg );
+void SetgVariable ( void * Variable );
+void Setl ( int32_t x86reg );
+void SetlVariable ( void * Variable );
+void Setz ( int32_t x86reg );
+void Setnz ( int32_t x86reg );
+void ShiftLeftDouble ( int32_t Destination, int32_t Source );
+void ShiftLeftDoubleImmed ( int32_t Destination, int32_t Source, uint8_t Immediate );
+void ShiftLeftSign ( int32_t x86reg );
+void ShiftLeftSignImmed ( int32_t x86reg, uint8_t Immediate );
+void ShiftRightDouble ( int32_t Destination, int32_t Source );
+void ShiftRightDoubleImmed ( int32_t Destination, int32_t Source, uint8_t Immediate );
+void ShiftRightSign ( int32_t x86reg );
+void ShiftRightSignImmed ( int32_t x86reg, uint8_t Immediate );
+void ShiftRightUnsign ( int32_t x86reg );
+void ShiftRightUnsignImmed ( int32_t x86reg, uint8_t Immediate );
+void SbbConstFromX86Reg ( int32_t x86Reg, uint32_t Const );
+void SbbVariableFromX86reg ( int32_t x86reg, void * Variable );
+void SbbX86RegToX86Reg ( int32_t Destination, int32_t Source );
+void SubConstFromVariable ( uint32_t Const, void *Variable );
+void SubConstFromX86Reg ( int32_t x86Reg, uint32_t Const );
+void SubVariableFromX86reg ( int32_t x86reg, void * Variable );
+void SubX86RegToX86Reg ( int32_t Destination, int32_t Source );
+void TestConstToX86Reg ( uint32_t Const, int32_t x86reg );
+void TestVariable ( uint32_t Const, void * Variable );
+void TestX86RegToX86Reg ( int32_t Destination, int32_t Source );
+void TestVariableToX86Reg ( uint32_t x86reg, void * Variable);
+void XorConstToX86Reg ( int32_t x86Reg, uint32_t Const );
+void XorX86RegToX86Reg ( int32_t Source, int32_t Destination );
+void XorVariableToX86reg ( void *Variable, int32_t x86reg );
+
+
+void fpuAbs ( void );
+void fpuAddDword ( void *Variable );
+void fpuAddDwordRegPointer ( int32_t x86Pointer );
+void fpuAddQword ( void *Variable );
+void fpuAddQwordRegPointer ( int32_t x86Pointer );
+void fpuAddReg ( int32_t x86reg );
+void fpuAddRegPop ( int32_t * StackPos, int32_t x86reg );
+void fpuComDword ( void *Variable, uint32_t Pop );
+void fpuComDwordRegPointer ( int32_t x86Pointer, uint32_t Pop );
+void fpuComQword ( void *Variable, uint32_t Pop );
+void fpuComQwordRegPointer ( int32_t x86Pointer, uint32_t Pop );
+void fpuComReg ( int32_t x86reg, uint32_t Pop );
+void fpuDivDword ( void *Variable );
+void fpuDivDwordRegPointer ( int32_t x86Pointer );
+void fpuDivQword ( void *Variable );
+void fpuDivQwordRegPointer ( int32_t x86Pointer );
+void fpuDivReg ( int32_t Reg );
+void fpuDivRegPop ( int32_t x86reg );
+void fpuExchange ( int32_t Reg );
+void fpuFree ( int32_t Reg );
+void fpuDecStack ( int32_t * StackPos );
+void fpuIncStack ( int32_t * StackPos );
+void fpuLoadControl ( void *Variable );
+void fpuLoadDword ( int32_t * StackPos, void *Variable );
+void fpuLoadDwordFromX86Reg ( int32_t * StackPos, int32_t x86reg );
+void fpuLoadDwordFromN64Mem ( int32_t * StackPos, int32_t x86reg );
+void fpuLoadInt32bFromN64Mem ( int32_t * StackPos, int32_t x86reg );
+void fpuLoadIntegerDword ( int32_t * StackPos, void *Variable );
+void fpuLoadIntegerDwordFromX86Reg ( int32_t * StackPos,int32_t x86Reg );
+void fpuLoadIntegerQword ( int32_t * StackPos, void *Variable );
+void fpuLoadIntegerQwordFromX86Reg ( int32_t * StackPos,int32_t x86Reg );
+void fpuLoadQword ( int32_t * StackPos, void *Variable );
+void fpuLoadQwordFromX86Reg ( int32_t * StackPos, int32_t x86Reg );
+void fpuLoadQwordFromN64Mem ( int32_t * StackPos, int32_t x86reg );
+void fpuLoadReg ( int32_t * StackPos, int32_t Reg );
+void fpuMulDword ( void *Variable);
+void fpuMulDwordRegPointer ( int32_t x86Pointer );
+void fpuMulQword ( void *Variable);
+void fpuMulQwordRegPointer ( int32_t x86Pointer );
+void fpuMulReg ( int32_t x86reg );
+void fpuMulRegPop ( int32_t x86reg );
+void fpuNeg ( void );
+void fpuRound ( void );
+void fpuSqrt ( void );
+void fpuStoreControl ( void *Variable );
+void fpuStoreDword ( int32_t * StackPos, void *Variable, uint32_t pop );
+void fpuStoreDwordFromX86Reg ( int32_t * StackPos,int32_t x86Reg, uint32_t pop );
+void fpuStoreDwordToN64Mem ( int32_t * StackPos, int32_t x86reg, uint32_t Pop );
+void fpuStoreIntegerDword ( int32_t * StackPos, void *Variable, uint32_t pop );
+void fpuStoreIntegerDwordFromX86Reg ( int32_t * StackPos,int32_t x86Reg, uint32_t pop );
+void fpuStoreIntegerQword ( int32_t * StackPos, void *Variable, uint32_t pop );
+void fpuStoreIntegerQwordFromX86Reg ( int32_t * StackPos, int32_t x86Reg, uint32_t pop );
+void fpuStoreQword ( int32_t * StackPos, void *Variable, uint32_t pop );
+void fpuStoreQwordFromX86Reg ( int32_t * StackPos, int32_t x86Reg, uint32_t pop );
+void fpuStoreStatus ( void );
+void fpuSubDword ( void *Variable );
+void fpuSubDwordRegPointer ( int32_t x86Pointer );
+void fpuSubDwordReverse ( void *Variable );
+void fpuSubQword ( void *Variable );
+void fpuSubQwordRegPointer ( int32_t x86Pointer );
+void fpuSubQwordReverse ( void *Variable );
+void fpuSubReg ( int32_t x86reg );
+void fpuSubRegPop ( int32_t x86reg );
+
+void MoveVariable64ToX86reg(void *Variable, int32_t x86reg);
diff --git a/src/usf/x86_fpu.c b/src/usf/x86_fpu.c new file mode 100644 index 0000000..02fb9d2 --- /dev/null +++ b/src/usf/x86_fpu.c @@ -0,0 +1,529 @@ +/*
+ * Project 64 - A Nintendo 64 emulator.
+ *
+ * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
+ * Jabo (jabo@emulation64.com).
+ *
+ * pj64 homepage: www.pj64.net
+ *
+ * Permission to use, copy, modify and distribute Project64 in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Project64 is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Project64 or software derived from Project64.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so if they want them.
+ *
+ */
+#include "main.h"
+#include "cpu.h"
+#include "x86.h"
+#include "types.h"
+
+void fpuAbs(void) {
+ PUTDST16(RecompPos,0xE1D9);
+}
+
+void fpuAddDword(void *Variable) {
+ BreakPoint();
+ PUTDST16(RecompPos,0x05D8);
+ PUTDST32(RecompPos,Variable);
+}
+
+void fpuAddDwordRegPointer(int x86Pointer) {
+ OPCODE_REG_MREG(8,0xD8,OP_D0,x86Pointer);
+}
+
+void fpuAddQword(void *Variable) {
+ BreakPoint();
+ PUTDST16(RecompPos,0x05DC);
+ PUTDST32(RecompPos,Variable);
+}
+
+void fpuAddQwordRegPointer(int x86Pointer) {
+ OPCODE_REG_MREG(8,0xDC,OP_D0,x86Pointer);
+}
+
+void fpuAddReg(int x86reg) {
+ switch (x86reg&0xf) {
+ case x86_ST0: PUTDST16(RecompPos,0xC0D8); break;
+ case x86_ST1: PUTDST16(RecompPos,0xC1D8); break;
+ case x86_ST2: PUTDST16(RecompPos,0xC2D8); break;
+ case x86_ST3: PUTDST16(RecompPos,0xC3D8); break;
+ case x86_ST4: PUTDST16(RecompPos,0xC4D8); break;
+ case x86_ST5: PUTDST16(RecompPos,0xC5D8); break;
+ case x86_ST6: PUTDST16(RecompPos,0xC6D8); break;
+ case x86_ST7: PUTDST16(RecompPos,0xC7D8); break;
+ }
+}
+
+void fpuAddRegPop(int * StackPos, int x86reg) {
+ *StackPos = (*StackPos + 1) & 7;
+ switch (x86reg&0xf) {
+ case x86_ST0: PUTDST16(RecompPos,0xC0DE); break;
+ case x86_ST1: PUTDST16(RecompPos,0xC1DE); break;
+ case x86_ST2: PUTDST16(RecompPos,0xC2DE); break;
+ case x86_ST3: PUTDST16(RecompPos,0xC3DE); break;
+ case x86_ST4: PUTDST16(RecompPos,0xC4DE); break;
+ case x86_ST5: PUTDST16(RecompPos,0xC5DE); break;
+ case x86_ST6: PUTDST16(RecompPos,0xC6DE); break;
+ case x86_ST7: PUTDST16(RecompPos,0xC7DE); break;
+ }
+}
+
+void fpuComDword(void *Variable, uint32_t Pop) {
+ BreakPoint();
+ PUTDST16(RecompPos, (Pop == 1) ? 0x1DD8 : 0x15D8);
+ PUTDST32(RecompPos,Variable);
+}
+
+void fpuComDwordRegPointer(int x86Pointer, uint32_t Pop) {
+ if(Pop) {
+ OPCODE_REG_MREG(8,0xD8,OP_D3,x86Pointer);
+ } else {
+ OPCODE_REG_MREG(8,0xD8,OP_D2,x86Pointer);
+ }
+}
+
+void fpuComQword(void *Variable, uint32_t Pop) {
+ BreakPoint();
+ PUTDST16(RecompPos, (Pop == 1) ? 0x1DDC : 0x15DC);
+ PUTDST32(RecompPos,Variable);
+}
+
+void fpuComQwordRegPointer(int x86Pointer, uint32_t Pop) {
+ if(Pop) {
+ OPCODE_REG_MREG(8,0xDC,OP_D3,x86Pointer);
+ } else {
+ OPCODE_REG_MREG(8,0xDC,OP_D2,x86Pointer);
+ }
+}
+
+void fpuComReg(int x86reg, uint32_t Pop) {
+ int s = (Pop == 1) ? 0x0800 : 0x0000;
+
+ switch (x86reg&0xf) {
+ case x86_ST0: PUTDST16(RecompPos,0xD0D8|s); break;
+ case x86_ST1: PUTDST16(RecompPos,0xD1D8|s); break;
+ case x86_ST2: PUTDST16(RecompPos,0xD2D8|s); break;
+ case x86_ST3: PUTDST16(RecompPos,0xD3D8|s); break;
+ case x86_ST4: PUTDST16(RecompPos,0xD4D8|s); break;
+ case x86_ST5: PUTDST16(RecompPos,0xD5D8|s); break;
+ case x86_ST6: PUTDST16(RecompPos,0xD6D8|s); break;
+ case x86_ST7: PUTDST16(RecompPos,0xD7D8|s); break;
+ }
+}
+
+void fpuDivDword(void *Variable) {
+ BreakPoint();
+ PUTDST16(RecompPos,0x35D8);
+ PUTDST32(RecompPos,Variable);
+}
+
+void fpuDivDwordRegPointer(int x86Pointer) {
+ OPCODE_REG_MREG(8,0xD8,OP_D6,x86Pointer);
+}
+
+void fpuDivQword(void *Variable) {
+ BreakPoint();
+ PUTDST16(RecompPos,0x35DC);
+ PUTDST32(RecompPos,Variable);
+}
+
+void fpuDivQwordRegPointer(int x86Pointer) {
+ OPCODE_REG_MREG(8,0xDC,OP_D6,x86Pointer);
+}
+
+void fpuDivReg(int Reg) {
+ switch (Reg) {
+ case x86_ST0: PUTDST16(RecompPos,0xF0D8); break;
+ case x86_ST1: PUTDST16(RecompPos,0xF1D8); break;
+ case x86_ST2: PUTDST16(RecompPos,0xF2D8); break;
+ case x86_ST3: PUTDST16(RecompPos,0xF3D8); break;
+ case x86_ST4: PUTDST16(RecompPos,0xF4D8); break;
+ case x86_ST5: PUTDST16(RecompPos,0xF5D8); break;
+ case x86_ST6: PUTDST16(RecompPos,0xF6D8); break;
+ case x86_ST7: PUTDST16(RecompPos,0xF7D8); break;
+ }
+}
+
+void fpuDivRegPop(int x86reg) {
+ switch (x86reg&0xf) {
+ case x86_ST0: PUTDST16(RecompPos,0xF8DE); break;
+ case x86_ST1: PUTDST16(RecompPos,0xF9DE); break;
+ case x86_ST2: PUTDST16(RecompPos,0xFADE); break;
+ case x86_ST3: PUTDST16(RecompPos,0xFBDE); break;
+ case x86_ST4: PUTDST16(RecompPos,0xFCDE); break;
+ case x86_ST5: PUTDST16(RecompPos,0xFDDE); break;
+ case x86_ST6: PUTDST16(RecompPos,0xFEDE); break;
+ case x86_ST7: PUTDST16(RecompPos,0xFFDE); break;
+ }
+}
+
+void fpuExchange(int Reg) {
+ switch (Reg) {
+ case x86_ST0: PUTDST16(RecompPos,0xC8D9); break;
+ case x86_ST1: PUTDST16(RecompPos,0xC9D9); break;
+ case x86_ST2: PUTDST16(RecompPos,0xCAD9); break;
+ case x86_ST3: PUTDST16(RecompPos,0xCBD9); break;
+ case x86_ST4: PUTDST16(RecompPos,0xCCD9); break;
+ case x86_ST5: PUTDST16(RecompPos,0xCDD9); break;
+ case x86_ST6: PUTDST16(RecompPos,0xCED9); break;
+ case x86_ST7: PUTDST16(RecompPos,0xCFD9); break;
+ }
+}
+
+void fpuFree(int Reg) {
+ switch (Reg) {
+ case x86_ST0: PUTDST16(RecompPos,0xC0DD); break;
+ case x86_ST1: PUTDST16(RecompPos,0xC1DD); break;
+ case x86_ST2: PUTDST16(RecompPos,0xC2DD); break;
+ case x86_ST3: PUTDST16(RecompPos,0xC3DD); break;
+ case x86_ST4: PUTDST16(RecompPos,0xC4DD); break;
+ case x86_ST5: PUTDST16(RecompPos,0xC5DD); break;
+ case x86_ST6: PUTDST16(RecompPos,0xC6DD); break;
+ case x86_ST7: PUTDST16(RecompPos,0xC7DD); break;
+ }
+}
+
+void fpuDecStack(int * StackPos) {
+ *StackPos = (*StackPos - 1) & 7;
+ PUTDST16(RecompPos,0xF6D9);
+}
+
+void fpuIncStack(int * StackPos) {
+ *StackPos = (*StackPos + 1) & 7;
+ PUTDST16(RecompPos,0xF7D9);
+}
+
+void fpuLoadControl(void *Variable) {
+#ifdef USEX64
+ PUTDST16(RecompPos,0xB849);
+ PUTDST64(RecompPos,Variable);
+ PUTDST8(RecompPos,0x41);
+ PUTDST16(RecompPos,0x28D9);
+#else
+ PUTDST16(RecompPos,0x2DD9);
+ PUTDST32(RecompPos,Variable);
+#endif
+}
+
+void fpuLoadDword(int * StackPos,void *Variable) {
+ *StackPos = (*StackPos - 1) & 7;
+ BreakPoint();
+ PUTDST16(RecompPos,0x05D9);
+ PUTDST32(RecompPos,Variable);
+}
+
+void fpuLoadDwordFromX86Reg(int * StackPos, int x86reg) {
+ *StackPos = (*StackPos - 1) & 7;
+ OPCODE_REG_MREG(8,0xD9,OP_D0,x86reg);
+}
+
+void fpuLoadIntegerDword(int * StackPos,void *Variable) {
+ *StackPos = (*StackPos - 1) & 7;
+ BreakPoint();
+ PUTDST16(RecompPos,0x05DB);
+ PUTDST32(RecompPos,Variable);
+}
+
+void fpuLoadIntegerDwordFromX86Reg(int * StackPos,int x86reg) {
+ *StackPos = (*StackPos - 1) & 7;
+ OPCODE_REG_MREG(8,0xDB,OP_D0,x86reg);
+}
+
+void fpuLoadIntegerQword(int * StackPos,void *Variable) {
+ *StackPos = (*StackPos - 1) & 7;
+ BreakPoint();
+ PUTDST16(RecompPos,0x2DDF);
+ PUTDST32(RecompPos,Variable);
+}
+
+void fpuLoadIntegerQwordFromX86Reg(int * StackPos,int x86reg) {
+ *StackPos = (*StackPos - 1) & 7;
+ OPCODE_REG_MREG(8,0xDF,OP_D5,x86reg);
+}
+
+void fpuLoadQword(int * StackPos,void *Variable) {
+ *StackPos = (*StackPos - 1) & 7;
+ BreakPoint();
+ PUTDST16(RecompPos,0x05DD);
+ PUTDST32(RecompPos,Variable);
+}
+
+void fpuLoadQwordFromX86Reg(int * StackPos, int x86reg) {
+ *StackPos = (*StackPos - 1) & 7;
+ OPCODE_REG_MREG(8,0xDD,OP_D0,x86reg);
+}
+void fpuLoadReg(int * StackPos,int Reg) {
+ *StackPos = (*StackPos - 1) & 7;
+ switch (Reg) {
+ case x86_ST0: PUTDST16(RecompPos,0xC0D9); break;
+ case x86_ST1: PUTDST16(RecompPos,0xC1D9); break;
+ case x86_ST2: PUTDST16(RecompPos,0xC2D9); break;
+ case x86_ST3: PUTDST16(RecompPos,0xC3D9); break;
+ case x86_ST4: PUTDST16(RecompPos,0xC4D9); break;
+ case x86_ST5: PUTDST16(RecompPos,0xC5D9); break;
+ case x86_ST6: PUTDST16(RecompPos,0xC6D9); break;
+ case x86_ST7: PUTDST16(RecompPos,0xC7D9); break;
+ break;
+ }
+}
+
+void fpuMulDword(void *Variable) {
+ BreakPoint();
+ PUTDST16(RecompPos,0x0DD8);
+ PUTDST32(RecompPos,Variable);
+}
+
+void fpuMulDwordRegPointer(int x86Pointer) {
+ OPCODE_REG_MREG(8,0xD8,OP_D1,x86Pointer);
+}
+
+void fpuMulQword(void *Variable) {
+BreakPoint();
+ PUTDST16(RecompPos,0x0DDC);
+ PUTDST32(RecompPos,Variable);
+}
+
+void fpuMulQwordRegPointer(int x86Pointer) {
+ OPCODE_REG_MREG(8,0xDC,OP_D1,x86Pointer);
+}
+
+void fpuMulReg(int x86reg) {
+ switch (x86reg&0xf) {
+ case x86_ST0: PUTDST16(RecompPos,0xC8D8); break;
+ case x86_ST1: PUTDST16(RecompPos,0xC9D8); break;
+ case x86_ST2: PUTDST16(RecompPos,0xCAD8); break;
+ case x86_ST3: PUTDST16(RecompPos,0xCBD8); break;
+ case x86_ST4: PUTDST16(RecompPos,0xCCD8); break;
+ case x86_ST5: PUTDST16(RecompPos,0xCDD8); break;
+ case x86_ST6: PUTDST16(RecompPos,0xCED8); break;
+ case x86_ST7: PUTDST16(RecompPos,0xCFD8); break;
+ }
+}
+
+void fpuMulRegPop(int x86reg) {
+ switch (x86reg&0xf) {
+ case x86_ST0: PUTDST16(RecompPos,0xC8DE); break;
+ case x86_ST1: PUTDST16(RecompPos,0xC9DE); break;
+ case x86_ST2: PUTDST16(RecompPos,0xCADE); break;
+ case x86_ST3: PUTDST16(RecompPos,0xCBDE); break;
+ case x86_ST4: PUTDST16(RecompPos,0xCCDE); break;
+ case x86_ST5: PUTDST16(RecompPos,0xCDDE); break;
+ case x86_ST6: PUTDST16(RecompPos,0xCEDE); break;
+ case x86_ST7: PUTDST16(RecompPos,0xCFDE); break;
+ }
+}
+
+void fpuNeg(void) {
+ PUTDST16(RecompPos,0xE0D9);
+}
+
+void fpuRound(void) {
+ PUTDST16(RecompPos,0xFCD9);
+}
+
+void fpuSqrt(void) {
+ PUTDST16(RecompPos,0xFAD9);
+}
+
+void fpuStoreControl(void *Variable) {
+
+#ifdef USEX64
+ PUTDST16(RecompPos,0xB849);
+ PUTDST64(RecompPos,Variable);
+ PUTDST8(RecompPos,0x41);
+ PUTDST16(RecompPos,0x38D9);
+#else
+ PUTDST16(RecompPos,0x3DD9);
+ PUTDST32(RecompPos,Variable);
+#endif
+}
+
+void fpuStoreDword(int * StackPos,void *Variable, uint32_t pop) {
+ if (pop) { *StackPos = (*StackPos + 1) & 7; }
+ BreakPoint();
+ PUTDST16(RecompPos,(pop == 0) ? 0x15D9 : 0x1DD9);
+ PUTDST32(RecompPos,Variable);
+}
+
+void fpuStoreDwordFromX86Reg(int * StackPos,int x86reg, uint32_t pop) {
+ if (pop) { *StackPos = (*StackPos + 1) & 7; }
+
+ if(pop) {
+ OPCODE_REG_MREG(8,0xD9,OP_D3,x86reg);
+ } else {
+ OPCODE_REG_MREG(8,0xD9,OP_D2,x86reg);
+ }
+}
+
+
+void fpuStoreIntegerDword(int * StackPos,void *Variable, uint32_t pop) {
+ if (pop) { *StackPos = (*StackPos + 1) & 7; }
+ BreakPoint();
+ PUTDST16(RecompPos, (pop == 0) ? 0x15DB : 0x1DDB);
+ PUTDST32(RecompPos,Variable);
+}
+
+void fpuStoreIntegerDwordFromX86Reg(int * StackPos,int x86reg, uint32_t pop) {
+ if (pop) { *StackPos = (*StackPos + 1) & 7; }
+
+ if(pop) {
+ OPCODE_REG_MREG(8,0xDB,OP_D3,x86reg);
+ } else {
+ OPCODE_REG_MREG(8,0xDB,OP_D2,x86reg);
+ }
+}
+
+void fpuStoreIntegerQword(int * StackPos,void *Variable, uint32_t pop) {
+ if (pop) { *StackPos = (*StackPos + 1) & 7; }
+ BreakPoint();
+ PUTDST16(RecompPos, (pop == 0) ? 0x35DF : 0x3DDF);
+ PUTDST32(RecompPos,Variable);
+ if (!pop) { BreakPoint(); }
+}
+
+void fpuStoreIntegerQwordFromX86Reg(int * StackPos, int x86reg, uint32_t pop) {
+ if (pop) { *StackPos = (*StackPos + 1) & 7; }
+
+ BreakPoint();
+ if(pop) {
+ OPCODE_REG_MREG(8,0xDF,OP_D5,x86reg);
+ } else {
+ OPCODE_REG_MREG(8,0xDF,OP_D4,x86reg);
+ }
+
+}
+
+void fpuStoreQwordFromX86Reg(int * StackPos, int x86reg, uint32_t pop) {
+ if (pop) { *StackPos = (*StackPos + 1) & 7; }
+
+ if(pop) {
+ OPCODE_REG_MREG(8,0xDD,OP_D3,x86reg);
+ } else {
+ OPCODE_REG_MREG(8,0xDD,OP_D2,x86reg);
+ }
+
+}
+
+void fpuStoreStatus(void) {
+ PUTDST16(RecompPos,0xE0DF);
+}
+
+void fpuSubDword(void *Variable) {
+ BreakPoint();
+ PUTDST16(RecompPos,0x25D8);
+ PUTDST32(RecompPos,Variable);
+}
+
+void fpuSubDwordRegPointer(int x86Pointer) {
+ OPCODE_REG_MREG(8,0xD8,OP_D4,x86Pointer);
+}
+
+void fpuSubDwordReverse(void *Variable) {
+BreakPoint();
+ PUTDST16(RecompPos,0x2DD8);
+ PUTDST32(RecompPos,Variable);
+}
+
+void fpuSubQword(void *Variable) {
+BreakPoint();
+ PUTDST16(RecompPos,0x25DC);
+ PUTDST32(RecompPos,Variable);
+}
+
+void fpuSubQwordRegPointer(int x86Pointer) {
+ OPCODE_REG_MREG(8,0xDC,OP_D4,x86Pointer);
+}
+
+void fpuSubQwordReverse(void *Variable) {
+ BreakPoint();
+ PUTDST16(RecompPos,0x2DDC);
+ PUTDST32(RecompPos,Variable);
+}
+
+void fpuSubReg(int x86reg) {
+ switch (x86reg&0xf) {
+ case x86_ST0: PUTDST16(RecompPos,0xE0D8); break;
+ case x86_ST1: PUTDST16(RecompPos,0xE1D8); break;
+ case x86_ST2: PUTDST16(RecompPos,0xE2D8); break;
+ case x86_ST3: PUTDST16(RecompPos,0xE3D8); break;
+ case x86_ST4: PUTDST16(RecompPos,0xE4D8); break;
+ case x86_ST5: PUTDST16(RecompPos,0xE5D8); break;
+ case x86_ST6: PUTDST16(RecompPos,0xE6D8); break;
+ case x86_ST7: PUTDST16(RecompPos,0xE7D8); break;
+ break;
+ }
+}
+
+void fpuSubRegPop(int x86reg) {
+ switch (x86reg&0xf) {
+ case x86_ST0: PUTDST16(RecompPos,0xE8DE); break;
+ case x86_ST1: PUTDST16(RecompPos,0xE9DE); break;
+ case x86_ST2: PUTDST16(RecompPos,0xEADE); break;
+ case x86_ST3: PUTDST16(RecompPos,0xEBDE); break;
+ case x86_ST4: PUTDST16(RecompPos,0xECDE); break;
+ case x86_ST5: PUTDST16(RecompPos,0xEDDE); break;
+ case x86_ST6: PUTDST16(RecompPos,0xEEDE); break;
+ case x86_ST7: PUTDST16(RecompPos,0xEFDE); break;
+ }
+}
+void fpuDivDwordReverse(void *Variable) {
+ BreakPoint();
+ PUTDST16(RecompPos,0x3DD8);
+ PUTDST32(RecompPos,Variable);
+}
+
+
+void fpuDivQwordReverse(void *Variable) {
+ BreakPoint();
+ PUTDST16(RecompPos,0x3DDC);
+ PUTDST32(RecompPos,Variable);
+}
+
+unsigned int fpucontrol;
+
+/* returns and pushes current fpu state, bool for set normal */
+int fpuSaveControl(uint32_t bSetNormal) {
+/* _asm {
+ fnstcw word ptr [fpucontrol]
+ }
+
+ if (bSetNormal == 1) {
+ unsigned short fpunormal = fpucontrol & 0xF3FF;
+ _asm {
+ fldcw word ptr [fpunormal]
+ }
+ }
+*/
+ return fpucontrol;
+}
+
+/* returns and pops fpu state previously pushed */
+int fpuRestoreControl() {
+/* _asm {
+ fldcw word ptr [fpucontrol]
+ }*/
+ return fpucontrol;
+}
+
+void fpuSetupDouble(void) {
+/*
+ int temp = 0;
+ _asm {
+ fnstcw word ptr [temp]
+ or [temp], 0x300
+ and [temp], 0xFFFFF3FF
+ fldcw word ptr [temp]
+ } */
+}
+
diff --git a/src/vfstrace/Makefile b/src/vfstrace/Makefile deleted file mode 100644 index 673608d..0000000 --- a/src/vfstrace/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -PLUGIN = vfstrace${PLUGIN_SUFFIX} - -SRCS = vfstrace.c - -include ../../buildsys.mk -include ../../extra.mk - -plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR} - -CFLAGS += ${PLUGIN_CFLAGS} -CPPFLAGS += ${PLUGIN_CPPFLAGS} ${MOWGLI_CFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} ${ARCH_DEFINES} ${XML_CPPFLAGS} -I../.. -LIBS += ${GTK_LIBS} ${GLIB_LIBS} ${XML_LIBS} diff --git a/src/vfstrace/vfstrace.c b/src/vfstrace/vfstrace.c deleted file mode 100644 index 8386fd2..0000000 --- a/src/vfstrace/vfstrace.c +++ /dev/null @@ -1,226 +0,0 @@ -/* Audacious - * Copyright (c) 2009 William Pitcock - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include <audacious/plugin.h> -#include "config.h" -#ifdef HAVE_INTTYPES_H -#include <inttypes.h> -#else -#define PRIu64 "llu" -#endif - -VFSFile *(*vfs_fopen_impl)(const gchar *path, const gchar *mode) = NULL; -gint (*vfs_fclose_impl)(VFSFile * file) = NULL; -gint64 (* vfs_fread_impl) (void * ptr, gint64 size, gint64 nmemb, VFSFile * - file) = NULL; -gint64 (* vfs_fwrite_impl) (const void * ptr, gint64 size, gint64 nmemb, - VFSFile * file) = NULL; -gint (*vfs_getc_impl)(VFSFile *stream) = NULL; -gint (*vfs_ungetc_impl)(gint c, VFSFile *stream) = NULL; -gint (*vfs_fseek_impl)(VFSFile *file, glong offset, gint whence) = NULL; -void (*vfs_rewind_impl)(VFSFile *file) = NULL; -glong (*vfs_ftell_impl)(VFSFile *file) = NULL; -gboolean (*vfs_feof_impl)(VFSFile *file) = NULL; -gint (* vfs_ftruncate_impl) (VFSFile * file, gint64 length) = NULL; -off_t (*vfs_fsize_impl)(VFSFile *file) = NULL; - -VFSFile * -vt_vfs_fopen_impl(const gchar *path, const gchar *mode) -{ - VFSFile *ret; - - ret = vfs_fopen_impl(path, mode); - g_print("%p fopen : path:%s : mode:%s : ret:%p\n", ret, path, mode, ret); - - return ret; -} - -gint -vt_vfs_fclose_impl(VFSFile *file) -{ - gint ret; - - ret = vfs_fclose_impl(file); - g_print("%p fclose : file:%p : ret:%d\n", file, file, ret); - - return ret; -} - -gint64 vt_vfs_fread_impl (void * ptr, gint64 size, gint64 nmemb, VFSFile * file) -{ - gsize ret; - - ret = vfs_fread_impl(ptr, size, nmemb, file); - g_print("%p fread : size:%" PRIu64 " : nmemb:%" PRIu64 " : ret:%" PRIu64 "\n", - file, (guint64) size, (guint64) nmemb, (guint64) ret); - - return ret; -} - -gint64 vt_vfs_fwrite_impl (const void * ptr, gint64 size, gint64 nmemb, - VFSFile * file) -{ - gsize ret; - - ret = vfs_fwrite_impl(ptr, size, nmemb, file); - g_print("%p fwrite : size:%" PRIu64 " : nmemb:%" PRIu64 " : ret:%" PRIu64 "\n", - file, (guint64) size, (guint64) nmemb, (guint64) ret); - - return ret; -} - -gint -vt_vfs_getc_impl(VFSFile *stream) -{ - gint ret; - - ret = vfs_getc_impl(stream); - g_print("%p getc : ret:%d\n", stream, ret); - - return ret; -} - -gint -vt_vfs_ungetc_impl(gint c, VFSFile *stream) -{ - gint ret; - - ret = vfs_ungetc_impl(c, stream); - g_print("%p ungetc : c:%d : ret:%d\n", stream, c, ret); - - return ret; -} - -gint -vt_vfs_fseek_impl(VFSFile *file, glong offset, gint whence) -{ - gint ret; - - ret = vfs_fseek_impl(file, offset, whence); - g_print("%p fseek : offset:%ld : whence:%d : ret:%d\n", file, offset, whence, ret); - - return ret; -} - -void -vt_vfs_rewind_impl(VFSFile *file) -{ - vfs_rewind_impl(file); - g_print("%p rewind\n", file); -} - -glong -vt_vfs_ftell_impl(VFSFile *file) -{ - glong ret; - - ret = vfs_ftell_impl(file); - g_print("%p ftell : ret:%ld\n", file, ret); - - return ret; -} - -gboolean -vt_vfs_feof_impl(VFSFile *file) -{ - gboolean ret; - - ret = vfs_feof_impl(file); - g_print("%p feof : ret:%d\n", file, ret); - - return ret; -} - -gint vt_vfs_ftruncate_impl (VFSFile * file, gint64 length) -{ - gboolean ret; - - ret = vfs_ftruncate_impl (file, length); - g_print("%p truncate : length:%ld : ret:%d\n", file, length, ret); - - return ret; -} - -off_t -vt_vfs_fsize_impl(VFSFile *file) -{ - off_t ret; - - ret = vfs_fsize_impl(file); - g_print("%p fsize : ret:%lu\n", file, ret); - - return ret; -} - -void -patch_vfs(void) -{ - vfs_fopen_impl = aud_vfs_fopen; - vfs_fclose_impl = aud_vfs_fclose; - vfs_fread_impl = aud_vfs_fread; - vfs_fwrite_impl = aud_vfs_fwrite; - vfs_getc_impl = aud_vfs_getc; - vfs_ungetc_impl = aud_vfs_ungetc; - vfs_fseek_impl = aud_vfs_fseek; - vfs_rewind_impl = aud_vfs_rewind; - vfs_ftell_impl = aud_vfs_ftell; - vfs_feof_impl = aud_vfs_feof; - vfs_ftruncate_impl = aud_vfs_ftruncate; - vfs_fsize_impl = aud_vfs_fsize; - - aud_vfs_fopen = vt_vfs_fopen_impl; - aud_vfs_fclose = vt_vfs_fclose_impl; - aud_vfs_fread = vt_vfs_fread_impl; - aud_vfs_fwrite = vt_vfs_fwrite_impl; - aud_vfs_getc = vt_vfs_getc_impl; - aud_vfs_ungetc = vt_vfs_ungetc_impl; - aud_vfs_fseek = vt_vfs_fseek_impl; - aud_vfs_rewind = vt_vfs_rewind_impl; - aud_vfs_ftell = vt_vfs_ftell_impl; - aud_vfs_feof = vt_vfs_feof_impl; - aud_vfs_ftruncate = vt_vfs_ftruncate_impl; - aud_vfs_fsize = vt_vfs_fsize_impl; -} - -void -unpatch_vfs(void) -{ - aud_vfs_fopen = vfs_fopen_impl; - aud_vfs_fclose = vfs_fclose_impl; - aud_vfs_fread = vfs_fread_impl; - aud_vfs_fwrite = vfs_fwrite_impl; - aud_vfs_getc = vfs_getc_impl; - aud_vfs_ungetc = vfs_ungetc_impl; - aud_vfs_fseek = vfs_fseek_impl; - aud_vfs_rewind = vfs_rewind_impl; - aud_vfs_ftell = vfs_ftell_impl; - aud_vfs_feof = vfs_feof_impl; - aud_vfs_ftruncate = vfs_ftruncate_impl; - aud_vfs_fsize = vfs_fsize_impl; -} - -static GeneralPlugin vfstrace_plugin = -{ - .description = "VFSTrace", - .init = patch_vfs, - .cleanup = unpatch_vfs, -}; - -GeneralPlugin *vfstrace_gplist[] = { &vfstrace_plugin, NULL }; -SIMPLE_GENERAL_PLUGIN(vfstrace, vfstrace_gplist); - diff --git a/src/voice_removal/voice_removal.c b/src/voice_removal/voice_removal.c index f71abb9..99e2c9f 100644 --- a/src/voice_removal/voice_removal.c +++ b/src/voice_removal/voice_removal.c @@ -1,76 +1,84 @@ /* - * libxmmsstandard - XMMS plugin. - * Copyright (C) 2000-2001 Konstantin Laevsky <debleek63@yahoo.com> + * Copyright (c) 2010 William Pitcock <nenolod@dereferenced.org>. * - * audacious port of the voice removal code from libxmmsstandard - * by Thomas Cort <linuxgeek@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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. */ + #include "config.h" -#include <gtk/gtk.h> #include <audacious/plugin.h> +static gint voice_channels; -static int apply_effect (gpointer *d, gint length, AFormat afmt, - gint srate, gint nch); -static void query_format (AFormat *fmt, gint *rate, gint *nch); +static void voice_start(gint *channels, gint *rate) +{ + voice_channels = *channels; +} -static EffectPlugin xmms_plugin = { - .description = "Voice Removal Plugin", - .mod_samples = apply_effect, - .query_format = query_format -}; +static void voice_process(gfloat **d, gint *samples) +{ + gfloat *f = *d, *end; + end = *d + *samples; -EffectPlugin *voice_eplist[] = { &xmms_plugin, NULL }; + if (voice_channels != 2 || samples == 0) + return; -DECLARE_PLUGIN(voice_removal, NULL, NULL, NULL, NULL, voice_eplist, NULL, NULL, NULL); + for (f = *d; f < end; f += 2) + { + gfloat left, right; -static void query_format (AFormat *fmt, gint *rate, gint *nch) -{ - if (!((*fmt == FMT_S16_NE) || - (*fmt == FMT_S16_LE && G_BYTE_ORDER == G_LITTLE_ENDIAN) || - (*fmt == FMT_S16_BE && G_BYTE_ORDER == G_BIG_ENDIAN))) - *fmt = FMT_S16_NE; + left = (f[1] - f[0]); + right = (f[0] - f[1]); - if (*nch != 2) - *nch = 2; + f[0] = left; + f[1] = right; + } } -static int apply_effect (gpointer *d, gint length, AFormat afmt, - gint srate, gint nch) { - int x; - int left, right; - gint16 *dataptr = (gint16 *) * d; - - if (!((afmt == FMT_S16_NE) || - (afmt == FMT_S16_LE && G_BYTE_ORDER == G_LITTLE_ENDIAN) || - (afmt == FMT_S16_BE && G_BYTE_ORDER == G_BIG_ENDIAN)) || - (nch != 2)) { - return length; - } +static void voice_finish(gfloat **d, gint *samples) +{ + voice_process(d, samples); +} - for (x = 0; x < length; x += 4) { - left = CLAMP(dataptr[1] - dataptr[0], -32768, 32767); - right = CLAMP(dataptr[0] - dataptr[1], -32768, 32767); - dataptr[0] = left; - dataptr[1] = right; - dataptr += 2; - } +static void voice_flush(void) +{ - return (length); } + +static gint voice_decoder_to_output_time(gint time) +{ + return time; +} + +static gint voice_output_to_decoder_time(gint time) +{ + return time; +} + +static EffectPlugin voice = { + .description = "Voice Removal Plugin", + .start = voice_start, + .process = voice_process, + .finish = voice_finish, + .flush = voice_flush, + .decoder_to_output_time = voice_decoder_to_output_time, + .output_to_decoder_time = voice_output_to_decoder_time +}; + +EffectPlugin *voice_eplist[] = { &voice, NULL }; + +SIMPLE_EFFECT_PLUGIN(voice_removal, voice_eplist); diff --git a/src/vorbis/configure.c b/src/vorbis/configure.c index 9ad847e..2efb21d 100644 --- a/src/vorbis/configure.c +++ b/src/vorbis/configure.c @@ -6,7 +6,9 @@ #include <stdlib.h> #include <string.h> +#include <audacious/configdb.h> #include <audacious/plugin.h> +#include <audacious/preferences.h> #include <audacious/i18n.h> vorbis_config_t vorbis_cfg; diff --git a/src/vorbis/vcedit.c b/src/vorbis/vcedit.c index a900f36..9dd6c01 100644 --- a/src/vorbis/vcedit.c +++ b/src/vorbis/vcedit.c @@ -179,8 +179,8 @@ int vcedit_open(vcedit_state * state, VFSFile * in) { return vcedit_open_callbacks(state, (void *) in, - (vcedit_read_func) aud_vfs_fread, - (vcedit_write_func) aud_vfs_fwrite); + (vcedit_read_func) vfs_fread, + (vcedit_write_func) vfs_fwrite); } int diff --git a/src/vorbis/vcupdate.c b/src/vorbis/vcupdate.c index 7b2390d..7fc1df5 100644 --- a/src/vorbis/vcupdate.c +++ b/src/vorbis/vcupdate.c @@ -32,8 +32,10 @@ #include <unistd.h> +#include <audacious/debug.h> #include <audacious/plugin.h> #include <audacious/i18n.h> +#include <libaudcore/audstrings.h> #include <mowgli.h> @@ -84,24 +86,24 @@ dictionary_to_vorbis_comment(vorbis_comment * vc, mowgli_dictionary_t * dict) } } -static void -insert_str_tuple_field_to_dictionary(Tuple *tuple, int fieldn, mowgli_dictionary_t *dict, char *key) +static void insert_str_tuple_field_to_dictionary (const Tuple * tuple, int + fieldn, mowgli_dictionary_t * dict, char * key) { if(mowgli_dictionary_find(dict, key) != NULL) g_free(mowgli_dictionary_delete(dict, key)); - gchar *tmp = (gchar*)aud_tuple_get_string(tuple, fieldn, NULL); + gchar *tmp = (gchar*)tuple_get_string(tuple, fieldn, NULL); if(tmp != NULL && strlen(tmp) != 0) mowgli_dictionary_add(dict, key, g_strdup(tmp)); } -static void -insert_int_tuple_field_to_dictionary(Tuple *tuple, int fieldn, mowgli_dictionary_t *dict, char *key) +static void insert_int_tuple_field_to_dictionary (const Tuple * tuple, int + fieldn, mowgli_dictionary_t * dict, char * key) { int val; if(mowgli_dictionary_find(dict, key) != NULL) g_free(mowgli_dictionary_delete(dict, key)); - if(aud_tuple_get_value_type(tuple, fieldn, NULL) == TUPLE_INT && (val = aud_tuple_get_int(tuple, fieldn, NULL)) >= 0) { + if(tuple_get_value_type(tuple, fieldn, NULL) == TUPLE_INT && (val = tuple_get_int(tuple, fieldn, NULL)) >= 0) { gchar *tmp = g_strdup_printf("%d", val); mowgli_dictionary_add(dict, key, tmp); } @@ -113,8 +115,7 @@ destroy_cb(mowgli_dictionary_elem_t *delem, void *privdata) g_free(delem->data); } -gboolean -vorbis_update_song_tuple (Tuple *tuple, VFSFile *fd) +gboolean vorbis_update_song_tuple (const Tuple * tuple, VFSFile * fd) { vcedit_state *state; @@ -155,7 +156,7 @@ vorbis_update_song_tuple (Tuple *tuple, VFSFile *fd) /* from stdio VFS plugin */ static gchar * -aud_vfs_stdio_urldecode_path(const gchar * encoded_path) +vfs_stdio_urldecode_path(const gchar * encoded_path) { const gchar *cur, *ext; gchar *path, *tmp; @@ -164,12 +165,12 @@ aud_vfs_stdio_urldecode_path(const gchar * encoded_path) if (!encoded_path) return NULL; - if (!aud_str_has_prefix_nocase(encoded_path, "file:")) + if (!str_has_prefix_nocase(encoded_path, "file:")) return NULL; cur = encoded_path + 5; - if (aud_str_has_prefix_nocase(cur, "//localhost")) + if (str_has_prefix_nocase(cur, "//localhost")) cur += 11; if (*cur == '/') @@ -209,7 +210,7 @@ write_and_pivot_files(vcedit_state * state) AUDDBG("creating temp file: %s\n", tmpfn); - if ((out = aud_vfs_fopen(tmpfn, "wb")) == NULL) { + if ((out = vfs_fopen(tmpfn, "wb")) == NULL) { g_free(tmpfn); AUDDBG("fileinfo.c: couldn't create temp file, %s\n", tmpfn); return FALSE; @@ -217,15 +218,15 @@ write_and_pivot_files(vcedit_state * state) if (vcedit_write(state, out) < 0) { g_free(tmpfn); - aud_vfs_fclose(out); + vfs_fclose(out); AUDDBG("vcedit_write: %s\n", state->lasterror); return FALSE; } - aud_vfs_fclose(out); + vfs_fclose(out); - unq_tmpfn = aud_vfs_stdio_urldecode_path(tmpfn); - unq_in = aud_vfs_stdio_urldecode_path(((VFSFile*)state->in)->uri); + unq_tmpfn = vfs_stdio_urldecode_path(tmpfn); + unq_in = vfs_stdio_urldecode_path(((VFSFile*)state->in)->uri); if((retval = rename(unq_tmpfn, unq_in)) == 0) { AUDDBG("fileinfo.c: file %s renamed successfully to %s\n", unq_tmpfn, unq_in); diff --git a/src/vorbis/vorbis.c b/src/vorbis/vorbis.c index 4734845..467e576 100644 --- a/src/vorbis/vorbis.c +++ b/src/vorbis/vorbis.c @@ -38,19 +38,35 @@ #include <vorbis/codec.h> #include <vorbis/vorbisfile.h> -#include <audacious/plugin.h> +#include <audacious/configdb.h> #include <audacious/i18n.h> +#include <audacious/misc.h> +#include <audacious/plugin.h> +#include <libaudcore/audstrings.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> #include "vorbis.h" +static size_t ovcb_read (void * buffer, size_t size, size_t count, void * file) +{ + return vfs_fread (buffer, size, count, file); +} + +static int ovcb_seek (void * file, ogg_int64_t offset, int whence) +{ + return vfs_fseek (file, offset, whence); +} + +static int ovcb_close (void * file) +{ + return 0; +} -static size_t ovcb_read(void *ptr, size_t size, size_t nmemb, - void *datasource); -static int ovcb_seek(void *datasource, int64_t offset, int whence); -static int ovcb_close(void *datasource); -static long ovcb_tell(void *datasource); +static long ovcb_tell (void * file) +{ + return vfs_ftell (file); +} ov_callbacks vorbis_callbacks = { ovcb_read, @@ -69,7 +85,6 @@ ov_callbacks vorbis_callbacks_stream = { static volatile gint seek_value = -1; static GMutex * seek_mutex = NULL; static GCond * seek_cond = NULL; -static gboolean pause_flag; gchar **vorbis_tag_encoding_list = NULL; @@ -79,11 +94,6 @@ vorbis_check_fd(const gchar *filename, VFSFile *stream) { OggVorbis_File vfile; gint result; - VFSVorbisFile *fd; - - fd = g_new0(VFSVorbisFile, 1); - fd->fd = stream; - fd->probe = TRUE; /* * The open function performs full stream detection and machine @@ -93,7 +103,8 @@ vorbis_check_fd(const gchar *filename, VFSFile *stream) memset(&vfile, 0, sizeof(vfile)); - result = ov_test_callbacks(fd, &vfile, NULL, 0, aud_vfs_is_streaming(stream) ? vorbis_callbacks_stream : vorbis_callbacks); + result = ov_test_callbacks (stream, & vfile, NULL, 0, vfs_is_streaming + (stream) ? vorbis_callbacks_stream : vorbis_callbacks); switch (result) { case OV_EREAD: @@ -134,8 +145,7 @@ vorbis_check_fd(const gchar *filename, VFSFile *stream) break; } - ov_clear(&vfile); /* once the ov_open succeeds, the stream belongs to - vorbisfile.a. ov_clear will fclose it */ + ov_clear(&vfile); return TRUE; } @@ -145,28 +155,28 @@ set_tuple_str(Tuple *tuple, const gint nfield, const gchar *field, { gchar *str = vorbis_comment_query(comment, key, 0); if (str != NULL) { - gchar *tmp = aud_str_to_utf8(str); - aud_tuple_associate_string(tuple, nfield, field, tmp); + gchar *tmp = str_to_utf8(str); + tuple_associate_string(tuple, nfield, field, tmp); g_free(tmp); } } static Tuple * -get_aud_tuple_for_vorbisfile(OggVorbis_File * vorbisfile, const gchar *filename) +get_tuple_for_vorbisfile(OggVorbis_File * vorbisfile, const gchar *filename) { - VFSVorbisFile *vfd = (VFSVorbisFile *) vorbisfile->datasource; Tuple *tuple; gint length; vorbis_comment *comment = NULL; - tuple = aud_tuple_new_from_filename(filename); + tuple = tuple_new_from_filename(filename); - length = aud_vfs_is_streaming(vfd->fd) ? -1 : ov_time_total(vorbisfile, -1) * 1000; + length = vfs_is_streaming (vorbisfile->datasource) ? -1 : ov_time_total + (vorbisfile, -1) * 1000; /* associate with tuple */ - aud_tuple_associate_int(tuple, FIELD_LENGTH, NULL, length); + tuple_associate_int(tuple, FIELD_LENGTH, NULL, length); /* maybe, it would be better to display nominal bitrate (like in main win), not average? --eugene */ - aud_tuple_associate_int(tuple, FIELD_BITRATE, NULL, ov_bitrate(vorbisfile, -1) / 1000); + tuple_associate_int(tuple, FIELD_BITRATE, NULL, ov_bitrate(vorbisfile, -1) / 1000); if ((comment = ov_comment(vorbisfile, -1)) != NULL) { gchar *tmps; @@ -177,24 +187,24 @@ get_aud_tuple_for_vorbisfile(OggVorbis_File * vorbisfile, const gchar *filename) set_tuple_str(tuple, FIELD_COMMENT, NULL, comment, "comment"); if ((tmps = vorbis_comment_query(comment, "tracknumber", 0)) != NULL) - aud_tuple_associate_int(tuple, FIELD_TRACK_NUMBER, NULL, atoi(tmps)); + tuple_associate_int(tuple, FIELD_TRACK_NUMBER, NULL, atoi(tmps)); if ((tmps = vorbis_comment_query (comment, "date", 0)) != NULL) - aud_tuple_associate_int (tuple, FIELD_YEAR, NULL, atoi (tmps)); + tuple_associate_int (tuple, FIELD_YEAR, NULL, atoi (tmps)); } - aud_tuple_associate_string(tuple, FIELD_QUALITY, NULL, "lossy"); + tuple_associate_string(tuple, FIELD_QUALITY, NULL, "lossy"); if (comment != NULL && comment->vendor != NULL) { gchar *codec = g_strdup_printf("Ogg Vorbis [%s]", comment->vendor); - aud_tuple_associate_string(tuple, FIELD_CODEC, NULL, codec); + tuple_associate_string(tuple, FIELD_CODEC, NULL, codec); g_free(codec); } else - aud_tuple_associate_string(tuple, FIELD_CODEC, NULL, "Ogg Vorbis"); + tuple_associate_string(tuple, FIELD_CODEC, NULL, "Ogg Vorbis"); - aud_tuple_associate_string(tuple, FIELD_MIMETYPE, NULL, "application/ogg"); + tuple_associate_string(tuple, FIELD_MIMETYPE, NULL, "application/ogg"); return tuple; } @@ -290,36 +300,27 @@ vorbis_interleave_buffer(float **pcm, int samples, int ch, float *pcmout) #define PCM_FRAMES 1024 #define PCM_BUFSIZE (PCM_FRAMES * 2) -static void -vorbis_play(InputPlayback *playback) +static gboolean vorbis_play (InputPlayback * playback, const gchar * filename, + VFSFile * file, gint start_time, gint stop_time, gboolean pause) { + if (file == NULL) + return FALSE; + vorbis_info *vi; OggVorbis_File vf; - VFSVorbisFile fd; - VFSFile *stream = NULL; gint last_section = -1; ReplayGainInfo rg_info; gfloat pcmout[PCM_BUFSIZE*sizeof(float)], **pcm; gint bytes, channels, samplerate, br; - gboolean paused = FALSE; gchar * title = NULL; playback->error = FALSE; - seek_value = -1; - pause_flag = FALSE; + seek_value = (start_time > 0) ? start_time : -1; memset(&vf, 0, sizeof(vf)); - if ((stream = aud_vfs_fopen(playback->filename, "r")) == NULL) { - playback->error = TRUE; - goto play_cleanup; - } - - fd.fd = stream; - - if (ov_open_callbacks (& fd, & vf, NULL, 0, aud_vfs_is_streaming (stream) ? + if (ov_open_callbacks (file, & vf, NULL, 0, vfs_is_streaming (file) ? vorbis_callbacks_stream : vorbis_callbacks) < 0) { - vorbis_callbacks.close_func (& fd); playback->error = TRUE; goto play_cleanup; } @@ -343,6 +344,9 @@ vorbis_play(InputPlayback *playback) goto play_cleanup; } + if (pause) + playback->output->pause (TRUE); + vorbis_update_replaygain(&vf, &rg_info); playback->output->set_replaygain_info (& rg_info); @@ -363,7 +367,8 @@ vorbis_play(InputPlayback *playback) while (1) { - gint current_section = last_section; + if (stop_time >= 0 && playback->output->written_time () >= stop_time) + goto DRAIN; g_mutex_lock (seek_mutex); @@ -381,28 +386,16 @@ vorbis_play(InputPlayback *playback) g_cond_signal (seek_cond); } - if (pause_flag != paused) - { - playback->output->pause (pause_flag); - paused = pause_flag; - g_cond_signal (seek_cond); - } - - if (paused) - { - g_cond_wait (seek_cond, seek_mutex); - g_mutex_unlock (seek_mutex); - continue; - } - g_mutex_unlock (seek_mutex); + gint current_section = last_section; bytes = ov_read_float(&vf, &pcm, PCM_FRAMES, ¤t_section); if (bytes == OV_HOLE) continue; if (bytes <= 0) { +DRAIN: while (playback->output->buffer_playing ()) g_usleep (10000); @@ -422,7 +415,7 @@ vorbis_play(InputPlayback *playback) g_free (title); title = g_strdup (new_title); - playback->set_tuple (playback, get_aud_tuple_for_vorbisfile + playback->set_tuple (playback, get_tuple_for_vorbisfile (& vf, playback->filename)); } } @@ -476,17 +469,18 @@ stop_processing: } } /* main loop */ + g_mutex_lock (seek_mutex); + playback->playing = FALSE; + g_cond_signal (seek_cond); /* wake up any waiting request */ + g_mutex_unlock (seek_mutex); + playback->output->close_audio (); play_cleanup: ov_clear(&vf); g_free (title); - - g_mutex_lock (seek_mutex); - playback->playing = FALSE; - g_cond_signal (seek_cond); /* wake up any waiting request */ - g_mutex_unlock (seek_mutex); + return ! playback->error; } static void vorbis_stop (InputPlayback * playback) @@ -496,25 +490,19 @@ static void vorbis_stop (InputPlayback * playback) if (playback->playing) { playback->playing = FALSE; + playback->output->abort_write (); g_cond_signal (seek_cond); - g_mutex_unlock (seek_mutex); - g_thread_join (playback->thread); - playback->thread = NULL; } - else - g_mutex_unlock (seek_mutex); + + g_mutex_unlock (seek_mutex); } -static void vorbis_pause (InputPlayback * playback, gshort p) +static void vorbis_pause (InputPlayback * playback, gshort pause) { g_mutex_lock (seek_mutex); if (playback->playing) - { - pause_flag = p; - g_cond_signal (seek_cond); - g_cond_wait (seek_cond, seek_mutex); - } + playback->output->pause (pause); g_mutex_unlock (seek_mutex); } @@ -526,6 +514,7 @@ static void vorbis_mseek (InputPlayback * playback, gulong time) if (playback->playing) { seek_value = time; + playback->output->abort_write (); g_cond_signal (seek_cond); g_cond_wait (seek_cond, seek_mutex); } @@ -533,36 +522,22 @@ static void vorbis_mseek (InputPlayback * playback, gulong time) g_mutex_unlock (seek_mutex); } -static void vorbis_seek (InputPlayback * playback, gint time) -{ - vorbis_mseek (playback, 1000 * time); -} - -static Tuple * get_song_tuple (const gchar * filename, VFSFile * handle) +static Tuple * get_song_tuple (const gchar * filename, VFSFile * file) { OggVorbis_File vfile; /* avoid thread interaction */ Tuple *tuple = NULL; - VFSVorbisFile fd; - - fd.fd = handle; /* * The open function performs full stream detection and * machine initialization. If it returns zero, the stream * *is* Vorbis and we're fully ready to decode. */ - if (ov_open_callbacks (& fd, & vfile, NULL, 0, aud_vfs_is_streaming (handle) - ? vorbis_callbacks_stream : vorbis_callbacks) < 0) + if (ov_open_callbacks (file, & vfile, NULL, 0, vfs_is_streaming (file) ? + vorbis_callbacks_stream : vorbis_callbacks) < 0) return NULL; - tuple = get_aud_tuple_for_vorbisfile(&vfile, filename); - - /* - * once the ov_open succeeds, the stream belongs to - * vorbisfile.a. ov_clear will fclose it - */ + tuple = get_tuple_for_vorbisfile(&vfile, filename); ov_clear(&vfile); - return tuple; } @@ -683,38 +658,6 @@ vorbis_cleanup(void) g_cond_free(seek_cond); } -static size_t -ovcb_read(void *ptr, size_t size, size_t nmemb, void *datasource) -{ - VFSVorbisFile *handle = (VFSVorbisFile *) datasource; - - return aud_vfs_fread(ptr, size, nmemb, handle->fd); -} - -static int -ovcb_seek(void *datasource, int64_t offset, int whence) -{ - VFSVorbisFile *handle = (VFSVorbisFile *) datasource; - - return aud_vfs_fseek(handle->fd, offset, whence); -} - -static int -ovcb_close(void *datasource) -{ - VFSVorbisFile *handle = (VFSVorbisFile *) datasource; - - return handle->probe ? 0 : aud_vfs_fclose(handle->fd); -} - -static long -ovcb_tell(void *datasource) -{ - VFSVorbisFile *handle = (VFSVorbisFile *) datasource; - - return aud_vfs_ftell(handle->fd); -} - extern PluginPreferences preferences; static gchar *vorbis_fmts[] = { "ogg", "ogm", "oga", NULL }; @@ -724,10 +667,9 @@ static InputPlugin vorbis_ip = { .init = vorbis_init, .about = vorbis_aboutbox, .settings = &preferences, - .play_file = vorbis_play, + .play = vorbis_play, .stop = vorbis_stop, .pause = vorbis_pause, - .seek = vorbis_seek, .mseek = vorbis_mseek, .cleanup = vorbis_cleanup, .probe_for_tuple = get_song_tuple, diff --git a/src/vorbis/vorbis.h b/src/vorbis/vorbis.h index c9c6391..6fd5855 100644 --- a/src/vorbis/vorbis.h +++ b/src/vorbis/vorbis.h @@ -5,14 +5,9 @@ #include <audacious/plugin.h> -typedef struct { - VFSFile *fd; - gboolean probe; -} VFSVorbisFile; - extern ov_callbacks vorbis_callbacks; -gboolean vorbis_update_song_tuple (Tuple *tuple, VFSFile *fd); +gboolean vorbis_update_song_tuple (const Tuple * tuple, VFSFile * fd); typedef struct { gint http_buffer_size; diff --git a/src/vtx/vtx.c b/src/vtx/vtx.c index 9f04b5e..d315b19 100644 --- a/src/vtx/vtx.c +++ b/src/vtx/vtx.c @@ -17,8 +17,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include <audacious/plugin.h> +#include <audacious/configdb.h> #include <audacious/i18n.h> +#include <audacious/misc.h> +#include <audacious/plugin.h> +#include <libaudcore/tuple_formatter.h> #include "vtx.h" #include "ayemu.h" @@ -68,7 +71,7 @@ vtx_is_our_fd (const gchar *filename, VFSFile *fp) { char buf[2]; - aud_vfs_fread (buf, 2, 1, fp); + vfs_fread (buf, 2, 1, fp); return (!strncasecmp (buf, "ay", 2) || !strncasecmp (buf, "ym", 2)); } @@ -78,9 +81,9 @@ vtx_is_our_file (const gchar *filename) gboolean ret; VFSFile *fp; - fp = aud_vfs_fopen(filename, "rb"); + fp = vfs_fopen(filename, "rb"); ret = vtx_is_our_fd(filename, fp); - aud_vfs_fclose(fp); + vfs_fclose(fp); return ret; } @@ -88,22 +91,22 @@ vtx_is_our_file (const gchar *filename) Tuple * vtx_get_song_tuple_from_vtx(const gchar *filename, ayemu_vtx_t *in) { - Tuple *out = aud_tuple_new_from_filename(filename); + Tuple *out = tuple_new_from_filename(filename); - aud_tuple_associate_string(out, FIELD_ARTIST, NULL, in->hdr.author); - aud_tuple_associate_string(out, FIELD_TITLE, NULL, in->hdr.title); + tuple_associate_string(out, FIELD_ARTIST, NULL, in->hdr.author); + tuple_associate_string(out, FIELD_TITLE, NULL, in->hdr.title); - aud_tuple_associate_int(out, FIELD_LENGTH, NULL, in->hdr.regdata_size / 14 * 1000 / 50); + tuple_associate_int(out, FIELD_LENGTH, NULL, in->hdr.regdata_size / 14 * 1000 / 50); - aud_tuple_associate_string(out, FIELD_GENRE, NULL, (in->hdr.chiptype == AYEMU_AY)? "AY chiptunes" : "YM chiptunes"); - aud_tuple_associate_string(out, FIELD_ALBUM, NULL, in->hdr.from); - aud_tuple_associate_string(out, -1, "game", in->hdr.from); + tuple_associate_string(out, FIELD_GENRE, NULL, (in->hdr.chiptype == AYEMU_AY)? "AY chiptunes" : "YM chiptunes"); + tuple_associate_string(out, FIELD_ALBUM, NULL, in->hdr.from); + tuple_associate_string(out, -1, "game", in->hdr.from); - aud_tuple_associate_string(out, FIELD_QUALITY, NULL, "sequenced"); - aud_tuple_associate_string(out, FIELD_CODEC, NULL, in->hdr.tracker); - aud_tuple_associate_string(out, -1, "tracker", in->hdr.tracker); + tuple_associate_string(out, FIELD_QUALITY, NULL, "sequenced"); + tuple_associate_string(out, FIELD_CODEC, NULL, in->hdr.tracker); + tuple_associate_string(out, -1, "tracker", in->hdr.tracker); - aud_tuple_associate_int(out, FIELD_YEAR, NULL, in->hdr.year); + tuple_associate_int(out, FIELD_YEAR, NULL, in->hdr.year); return out; } @@ -220,14 +223,14 @@ void vtx_play_file (InputPlayback *playback) seek_to = -1; ti = vtx_get_song_tuple_from_vtx(playback->filename, &vtx); - buf = aud_tuple_formatter_make_title_string(ti, aud_get_gentitle_format()); + buf = tuple_formatter_make_title_string(ti, aud_get_gentitle_format()); playback->set_params (playback, buf, vtx.hdr.regdata_size / 14 * 1000 / 50, 14 * 50 * 8, freq, bits / 8); g_free (buf); - aud_tuple_free(ti); + tuple_free(ti); playback->playing = TRUE; play_thread = g_thread_self(); diff --git a/src/vtx/vtxfile.c b/src/vtx/vtxfile.c index a0241db..590e7bc 100644 --- a/src/vtx/vtxfile.c +++ b/src/vtx/vtxfile.c @@ -19,7 +19,7 @@ extern void lh5_decode(unsigned char *inp,unsigned char *outp,unsigned long orig static int read_byte(VFSFile *fp, int *p) { int c; - if ((c = aud_vfs_getc(fp)) == EOF) { + if ((c = vfs_getc(fp)) == EOF) { perror("libayemu: read_byte()"); return 1; } @@ -33,13 +33,13 @@ static int read_byte(VFSFile *fp, int *p) static int read_word16(VFSFile *fp, int *p) { int c; - if ((c = aud_vfs_getc(fp)) == EOF) { + if ((c = vfs_getc(fp)) == EOF) { perror("libayemu: read_word16()"); return 1; } *p = c; - if ((c = aud_vfs_getc(fp)) == EOF) { + if ((c = vfs_getc(fp)) == EOF) { perror("libayemu: read_word16()"); return 1; } @@ -55,25 +55,25 @@ static int read_word32(VFSFile *fp, int32_t *p) { int c; - if ((c = aud_vfs_getc(fp)) == EOF) { + if ((c = vfs_getc(fp)) == EOF) { perror("libayemu: read_word32()"); return 1; } *p = c; - if ((c = aud_vfs_getc(fp)) == EOF) { + if ((c = vfs_getc(fp)) == EOF) { perror("libayemu: read_word32()"); return 1; } *p += c << 8; - if ((c = aud_vfs_getc(fp)) == EOF) { + if ((c = vfs_getc(fp)) == EOF) { perror("libayemu: read_word32()"); return 1; } *p += c << 16; - if ((c = aud_vfs_getc(fp)) == EOF) { + if ((c = vfs_getc(fp)) == EOF) { perror("libayemu: read_word32()"); return 1; } @@ -88,7 +88,7 @@ static int read_word32(VFSFile *fp, int32_t *p) static int read_NTstring(VFSFile *fp, char s[]) { int i, c; - for (i = 0 ; i < AYEMU_VTX_NTSTRING_MAX && (c = aud_vfs_getc(fp)) != EOF && c ; i++) + for (i = 0 ; i < AYEMU_VTX_NTSTRING_MAX && (c = vfs_getc(fp)) != EOF && c ; i++) s[i] = c; s[i] = '\0'; if (c == EOF) { @@ -111,12 +111,12 @@ int ayemu_vtx_open (ayemu_vtx_t *vtx, const char *filename) vtx->regdata = NULL; - if ((vtx->fp = aud_vfs_fopen (filename, "rb")) == NULL) { + if ((vtx->fp = vfs_fopen (filename, "rb")) == NULL) { fprintf(stderr, "ayemu_vtx_open: Cannot open file %s: %s\n", filename, strerror(errno)); return 0; } - if (aud_vfs_fread(buf, 2, 1, vtx->fp) != 1) { + if (vfs_fread(buf, 2, 1, vtx->fp) != 1) { fprintf(stderr,"ayemu_vtx_open: Can't read from %s: %s\n", filename, strerror(errno)); error = 1; } @@ -151,7 +151,7 @@ int ayemu_vtx_open (ayemu_vtx_t *vtx, const char *filename) if (!error) error = read_NTstring (vtx->fp, vtx->hdr.comment); if (error) { - aud_vfs_fclose(vtx->fp); + vfs_fclose(vtx->fp); vtx->fp = NULL; } return !error; @@ -177,19 +177,19 @@ char *ayemu_vtx_load_data (ayemu_vtx_t *vtx) buf_alloc = 4096; packed_data = (char *) malloc (buf_alloc); /* read packed AY register data to end of file. */ - while ((c = aud_vfs_getc (vtx->fp)) != EOF) { + while ((c = vfs_getc (vtx->fp)) != EOF) { if (buf_alloc < packed_size) { buf_alloc *= 2; packed_data = (char *) realloc (packed_data, buf_alloc); if (packed_data == NULL) { fprintf (stderr, "ayemu_vtx_load_data: Packed data out of memory!\n"); - aud_vfs_fclose (vtx->fp); + vfs_fclose (vtx->fp); return NULL; } } packed_data[packed_size++] = c; } - aud_vfs_fclose (vtx->fp); + vfs_fclose (vtx->fp); vtx->fp = NULL; if ((vtx->regdata = (char *) malloc (vtx->hdr.regdata_size)) == NULL) { fprintf (stderr, "ayemu_vtx_load_data: Can allocate %d bytes for unpack register data\n", (int)(vtx->hdr.regdata_size)); @@ -318,7 +318,7 @@ void ayemu_vtx_sprintname (const ayemu_vtx_t *vtx, char *const buf, const int sz void ayemu_vtx_free (ayemu_vtx_t *vtx) { if (vtx->fp) { - aud_vfs_fclose(vtx->fp); + vfs_fclose(vtx->fp); vtx->fp = NULL; } diff --git a/src/wavpack/wavpack.c b/src/wavpack/wavpack.c index 8b9fa56..9eee110 100644 --- a/src/wavpack/wavpack.c +++ b/src/wavpack/wavpack.c @@ -2,6 +2,8 @@ #include "config.h" #include <wavpack/wavpack.h> + +#include <audacious/debug.h> #include <audacious/plugin.h> #include <audacious/i18n.h> #include <libaudgui/libaudgui.h> @@ -30,31 +32,31 @@ static gboolean pause_flag; static gint32 wv_read_bytes(void *id, void *data, gint32 bcount) { - return aud_vfs_fread(data, 1, bcount, (VFSFile *) id); + return vfs_fread(data, 1, bcount, (VFSFile *) id); } static guint32 wv_get_pos(void *id) { - return aud_vfs_ftell((VFSFile *) id); + return vfs_ftell((VFSFile *) id); } static gint wv_set_pos_abs(void *id, guint32 pos) { - return aud_vfs_fseek((VFSFile *) id, pos, SEEK_SET); + return vfs_fseek((VFSFile *) id, pos, SEEK_SET); } static gint wv_set_pos_rel(void *id, gint32 delta, gint mode) { - return aud_vfs_fseek((VFSFile *) id, delta, mode); + return vfs_fseek((VFSFile *) id, delta, mode); } static gint wv_push_back_byte(void *id, gint c) { - return aud_vfs_ungetc(c, (VFSFile *) id); + return vfs_ungetc(c, (VFSFile *) id); } static guint32 @@ -65,17 +67,17 @@ wv_get_length(void *id) if (file == NULL) return 0; - return aud_vfs_fsize(file); + return vfs_fsize(file); } static gint wv_can_seek(void *id) { - return (aud_vfs_is_streaming((VFSFile *) id) == FALSE); + return (vfs_is_streaming((VFSFile *) id) == FALSE); } static gint32 wv_write_bytes(void *id, void *data, gint32 bcount) { - return aud_vfs_fwrite(data, 1, bcount, (VFSFile *) id); + return vfs_fwrite(data, 1, bcount, (VFSFile *) id); } WavpackStreamReader wv_readers = { @@ -89,22 +91,20 @@ WavpackStreamReader wv_readers = { wv_write_bytes }; -gboolean wv_attach(const gchar *filename, VFSFile **wv_input, VFSFile **wvc_input, WavpackContext **ctx, gchar *error, gint flags) +static gboolean wv_attach (const gchar * filename, VFSFile * wv_input, + VFSFile * * wvc_input, WavpackContext * * ctx, gchar * error, gint flags) { gchar *corrFilename; - *wv_input = aud_vfs_fopen(filename, "rb"); - if (*wv_input == NULL) - return FALSE; - if (flags & OPEN_WVC) { corrFilename = g_strconcat(filename, "c", NULL); - *wvc_input = aud_vfs_fopen(corrFilename, "rb"); + *wvc_input = vfs_fopen(corrFilename, "rb"); g_free(corrFilename); } - *ctx = WavpackOpenFileInputEx(&wv_readers, *wv_input, *wvc_input, error, flags, 0); + * ctx = WavpackOpenFileInputEx (& wv_readers, wv_input, * wvc_input, error, + flags, 0); if (ctx == NULL) return FALSE; @@ -112,17 +112,19 @@ gboolean wv_attach(const gchar *filename, VFSFile **wv_input, VFSFile **wvc_inpu return TRUE; } -void wv_deattach(VFSFile *wv_input, VFSFile *wvc_input, WavpackContext *ctx) +static void wv_deattach (VFSFile * wvc_input, WavpackContext * ctx) { - if (wv_input != NULL) - aud_vfs_fclose(wv_input); if (wvc_input != NULL) - aud_vfs_fclose(wvc_input); + vfs_fclose(wvc_input); WavpackCloseFile(ctx); } -void wv_play(InputPlayback * playback) +static gboolean wv_play (InputPlayback * playback, const gchar * filename, + VFSFile * file, gint start_time, gint stop_time, gboolean pause) { + if (file == NULL) + return FALSE; + gshort paused = 0; gint32 *input = NULL; void *output = NULL; @@ -130,9 +132,10 @@ void wv_play(InputPlayback * playback) guint num_samples, length; gchar error[1024]; // fixme?! FIX ME halb apua hilfe scheisse --ccr WavpackContext *ctx = NULL; - VFSFile *wv_input = NULL, *wvc_input = NULL; + VFSFile *wvc_input = NULL; - if (!wv_attach(playback->filename, &wv_input, &wvc_input, &ctx, (gchar *)&error, OPEN_TAGS | OPEN_WVC)) + if (! wv_attach (filename, file, & wvc_input, & ctx, error, OPEN_TAGS | + OPEN_WVC)) { g_warning("Error opening Wavpack file '%s'.", playback->filename); playback->error = 2; @@ -165,13 +168,17 @@ void wv_play(InputPlayback * playback) (gint) WavpackGetAverageBitrate(ctx, num_channels), sample_rate, num_channels); + pause_flag = pause; + seek_value = (start_time > 0) ? start_time : -1; + playback->playing = TRUE; playback->eof = FALSE; playback->set_pb_ready(playback); g_mutex_unlock(ctrl_mutex); - while (playback->playing && !playback->eof) + while (playback->playing && ! playback->eof && (stop_time < 0 || + playback->output->written_time () < stop_time)) { gint ret; guint samples_left; @@ -181,8 +188,8 @@ void wv_play(InputPlayback * playback) if (seek_value >= 0) { - playback->output->flush(seek_value * 1000); - WavpackSeekSample(ctx, (gint) (seek_value * sample_rate)); + playback->output->flush (seek_value); + WavpackSeekSample (ctx, (gint64) seek_value * sample_rate / 1000); seek_value = -1; g_cond_signal(ctrl_cond); } @@ -256,10 +263,11 @@ error_exit: g_free(input); g_free(output); - wv_deattach(wv_input, wvc_input, ctx); + wv_deattach (wvc_input, ctx); playback->playing = FALSE; playback->output->close_audio(); + return ! playback->error; } static void @@ -288,8 +296,7 @@ wv_pause(InputPlayback * playback, gshort p) g_mutex_unlock(ctrl_mutex); } -static void -wv_seek(InputPlayback * playback, gint time) +static void wv_seek (InputPlayback * playback, gulong time) { g_mutex_lock(ctrl_mutex); @@ -338,16 +345,16 @@ wv_probe_for_tuple(const gchar * filename, VFSFile * fd) AUDDBG("starting probe of %p\n", fd); - aud_vfs_fseek(fd, 0, SEEK_SET); - tu = aud_tuple_new_from_filename(filename); + vfs_fseek(fd, 0, SEEK_SET); + tu = tuple_new_from_filename(filename); - aud_vfs_fseek(fd, 0, SEEK_SET); + vfs_fseek(fd, 0, SEEK_SET); tag_tuple_read(tu, fd); - aud_tuple_associate_int(tu, FIELD_LENGTH, NULL, + tuple_associate_int(tu, FIELD_LENGTH, NULL, ((guint64) WavpackGetNumSamples(ctx) * 1000) / (guint64) WavpackGetSampleRate(ctx)); - aud_tuple_associate_string(tu, FIELD_CODEC, NULL, "WavPack"); - aud_tuple_associate_string(tu, FIELD_QUALITY, NULL, wv_get_quality(ctx)); + tuple_associate_string(tu, FIELD_CODEC, NULL, "WavPack"); + tuple_associate_string(tu, FIELD_QUALITY, NULL, wv_get_quality(ctx)); WavpackCloseFile(ctx); @@ -381,7 +388,7 @@ wv_cleanup(void) g_cond_free(ctrl_cond); } -static gboolean wv_write_tag (Tuple *tuple, VFSFile *handle) +static gboolean wv_write_tag (const Tuple * tuple, VFSFile * handle) { return tag_tuple_write(tuple, handle, TAG_TYPE_APE); } @@ -395,10 +402,10 @@ static InputPlugin wvpack = { .init = wv_init, .cleanup = wv_cleanup, .about = wv_about_box, - .play_file = wv_play, + .play = wv_play, .stop = wv_stop, .pause = wv_pause, - .seek = wv_seek, + .mseek = wv_seek, .vfs_extensions = wv_fmts, .probe_for_tuple = wv_probe_for_tuple, .update_song_tuple = wv_write_tag, diff --git a/src/xsf/plugin.c b/src/xsf/plugin.c index 70c89de..0495a8b 100644 --- a/src/xsf/plugin.c +++ b/src/xsf/plugin.c @@ -28,7 +28,9 @@ #include <stdlib.h> #include <string.h> +#include <audacious/misc.h> #include <audacious/plugin.h> +#include <libaudcore/tuple_formatter.h> #include "ao.h" #include "corlett.h" @@ -38,13 +40,13 @@ static gchar *path; int xsf_get_lib(char *filename, void **buffer, unsigned int *length) { - guchar *filebuf; + void *filebuf; gint64 size; char buf[PATH_MAX]; snprintf(buf, PATH_MAX, "%s/%s", dirname(path), filename); - aud_vfs_file_get_contents (buf, & filebuf, & size); + vfs_file_get_contents (buf, & filebuf, & size); *buffer = filebuf; *length = (uint64)size; @@ -57,10 +59,10 @@ Tuple *xsf_tuple(const gchar *filename) { Tuple *t; corlett_t *c; - guchar *buf; + void *buf; gint64 sz; - aud_vfs_file_get_contents (filename, & buf, & sz); + vfs_file_get_contents (filename, & buf, & sz); if (!buf) return NULL; @@ -68,17 +70,17 @@ Tuple *xsf_tuple(const gchar *filename) if (corlett_decode(buf, sz, NULL, NULL, &c) != AO_SUCCESS) return NULL; - t = aud_tuple_new_from_filename(filename); + t = tuple_new_from_filename(filename); - aud_tuple_associate_int(t, FIELD_LENGTH, NULL, c->inf_length ? psfTimeToMS(c->inf_length) + psfTimeToMS(c->inf_fade) : -1); - aud_tuple_associate_string(t, FIELD_ARTIST, NULL, c->inf_artist); - aud_tuple_associate_string(t, FIELD_ALBUM, NULL, c->inf_game); - aud_tuple_associate_string(t, -1, "game", c->inf_game); - aud_tuple_associate_string(t, FIELD_TITLE, NULL, c->inf_title); - aud_tuple_associate_string(t, FIELD_COPYRIGHT, NULL, c->inf_copy); - aud_tuple_associate_string(t, FIELD_QUALITY, NULL, "sequenced"); - aud_tuple_associate_string(t, FIELD_CODEC, NULL, "GBA/Nintendo DS Audio"); - aud_tuple_associate_string(t, -1, "console", "GBA/Nintendo DS"); + tuple_associate_int(t, FIELD_LENGTH, NULL, c->inf_length ? psfTimeToMS(c->inf_length) + psfTimeToMS(c->inf_fade) : -1); + tuple_associate_string(t, FIELD_ARTIST, NULL, c->inf_artist); + tuple_associate_string(t, FIELD_ALBUM, NULL, c->inf_game); + tuple_associate_string(t, -1, "game", c->inf_game); + tuple_associate_string(t, FIELD_TITLE, NULL, c->inf_title); + tuple_associate_string(t, FIELD_COPYRIGHT, NULL, c->inf_copy); + tuple_associate_string(t, FIELD_QUALITY, NULL, "sequenced"); + tuple_associate_string(t, FIELD_CODEC, NULL, "GBA/Nintendo DS Audio"); + tuple_associate_string(t, -1, "console", "GBA/Nintendo DS"); free(c); g_free(buf); @@ -93,9 +95,9 @@ gchar *xsf_title(gchar *filename, gint *length) if (tuple != NULL) { - title = aud_tuple_formatter_make_title_string(tuple, aud_get_gentitle_format()); - *length = aud_tuple_get_int(tuple, FIELD_LENGTH, NULL); - aud_tuple_free(tuple); + title = tuple_formatter_make_title_string(tuple, aud_get_gentitle_format()); + *length = tuple_get_int(tuple, FIELD_LENGTH, NULL); + tuple_free(tuple); } else { @@ -110,7 +112,7 @@ void xsf_update(unsigned char *buffer, long count, InputPlayback *playback); void xsf_play(InputPlayback *data) { - guchar *buffer; + void *buffer; gint64 size; gint length; gchar *title = xsf_title(data->filename, &length); @@ -119,7 +121,7 @@ void xsf_play(InputPlayback *data) gfloat pos; path = g_strdup(data->filename); - aud_vfs_file_get_contents (data->filename, & buffer, & size); + vfs_file_get_contents (data->filename, & buffer, & size); if (xsf_start(buffer, size) != AO_SUCCESS) { @@ -244,7 +246,7 @@ void xsf_pause(InputPlayback *playback, short p) gint xsf_is_our_fd(const gchar *filename, VFSFile *file) { gchar magic[4]; - aud_vfs_fread(magic, 1, 4, file); + vfs_fread(magic, 1, 4, file); if (!memcmp(magic, "PSF$", 4)) return 1; diff --git a/src/xspf/xspf.c b/src/xspf/xspf.c index 66a10bb..45996c1 100644 --- a/src/xspf/xspf.c +++ b/src/xspf/xspf.c @@ -33,8 +33,6 @@ #include <sys/stat.h> #include <sys/errno.h> -#include <audacious/plugin.h> - #include <libxml/tree.h> #include <libxml/parser.h> #include <libxml/xmlreader.h> @@ -42,6 +40,11 @@ #include <libxml/xpathInternals.h> #include <libxml/uri.h> +#include <audacious/debug.h> +#include <audacious/misc.h> +#include <audacious/playlist.h> +#include <audacious/plugin.h> + #define XSPF_ROOT_NODE_NAME "playlist" #define XSPF_XMLNS "http://xspf.org/ns/0/" @@ -105,9 +108,9 @@ static void xspf_add_file (xmlNode * track, const gchar * filename, const gchar Tuple *tuple; gchar *location = NULL; - tuple = aud_tuple_new(); - aud_tuple_associate_int(tuple, FIELD_LENGTH, NULL, -1); - aud_tuple_associate_int(tuple, FIELD_MTIME, NULL, -1); + tuple = tuple_new(); + tuple_associate_int(tuple, FIELD_LENGTH, NULL, -1); + tuple_associate_int(tuple, FIELD_MTIME, NULL, -1); for (nptr = track->children; nptr != NULL; nptr = nptr->next) { @@ -156,12 +159,12 @@ static void xspf_add_file (xmlNode * track, const gchar * filename, const gchar xmlChar *str = xmlNodeGetContent(nptr); switch (xspf_entries[i].type) { case TUPLE_STRING: - aud_tuple_associate_string(tuple, xspf_entries[i].tupleField, NULL, (gchar *)str); + tuple_associate_string(tuple, xspf_entries[i].tupleField, NULL, (gchar *)str); break; case TUPLE_INT: AUDDBG("field=%s val=%s\n", xspf_entries[i].xspfName, str); - aud_tuple_associate_int(tuple, xspf_entries[i].tupleField, NULL, atol((char *)str)); + tuple_associate_int(tuple, xspf_entries[i].tupleField, NULL, atol((char *)str)); break; default: @@ -429,7 +432,8 @@ static void xspf_playlist_save(const gchar *filename, gint pos) { const gchar * filename = aud_playlist_entry_get_filename (playlist, count); - const Tuple * tuple = aud_playlist_entry_get_tuple (playlist, count); + const Tuple * tuple = aud_playlist_entry_get_tuple (playlist, count, + FALSE); xmlNodePtr track, location; const gchar *scratch = NULL; gint scratchi = 0; @@ -450,7 +454,7 @@ static void xspf_playlist_save(const gchar *filename, gint pos) switch (xs->type) { case TUPLE_STRING: - scratch = aud_tuple_get_string ((Tuple *) tuple, + scratch = tuple_get_string ((Tuple *) tuple, xs->tupleField, NULL); switch (xs->compare) { @@ -462,7 +466,7 @@ static void xspf_playlist_save(const gchar *filename, gint pos) break; case TUPLE_INT: - scratchi = aud_tuple_get_int ((Tuple *) tuple, + scratchi = tuple_get_int ((Tuple *) tuple, xs->tupleField, NULL); switch (xs->compare) { |