summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenjamin Drung <bdrung@ubuntu.com>2010-07-22 20:51:38 +0200
committerBenjamin Drung <bdrung@ubuntu.com>2010-07-22 20:51:38 +0200
commitf2fe41914ec32e767ec333a0cd7342e9d9bf4e13 (patch)
tree8b185d5ab501e1c1a8e8e9dd66529c84f723fcb7 /src
parent43e43d5922dd91aafb58be41f2112797fdd627db (diff)
Imported Upstream version 2.4~beta1
Diffstat (limited to 'src')
-rw-r--r--src/CoreAudio/audio.c32
-rw-r--r--src/CoreAudio/coreaudio.h8
-rw-r--r--src/OSS/OSS.c2
-rw-r--r--src/OSS/OSS.h4
-rw-r--r--src/OSS/audio.c12
-rw-r--r--src/OSS/configure.c2
-rw-r--r--src/aac/libmp4.c73
-rw-r--r--src/adplug/adplug-xmms.cc42
-rw-r--r--src/adplug/core/adplug.cxx2
-rw-r--r--src/adplug/core/adtrack.cxx4
-rw-r--r--src/adplug/core/binio_virtual.h36
-rw-r--r--src/adplug/core/ksm.cxx4
-rw-r--r--src/adplug/core/mid.cxx6
-rw-r--r--src/adplug/core/rol.cxx4
-rw-r--r--src/alarm/alarm.c60
-rwxr-xr-xsrc/alsa/alsa.c143
-rw-r--r--src/alsa/alsa.h8
-rw-r--r--src/alsa/config.c3
-rw-r--r--src/alsa/plugin.c2
-rw-r--r--src/amidi-plug/amidi-plug.c15
-rw-r--r--src/amidi-plug/amidi-plug.h4
-rw-r--r--src/amidi-plug/i_configure.c13
-rw-r--r--src/amidi-plug/i_vfslayer.h14
-rw-r--r--src/aosd/aosd_cfg.c5
-rw-r--r--src/aosd/aosd_trigger.c68
-rw-r--r--src/bluetooth/bluetooth.c4
-rw-r--r--src/blur_scope/blur_scope.c19
-rw-r--r--src/blur_scope/config.c4
-rw-r--r--src/bs2b/plugin.c1
-rw-r--r--src/cd-menu-items/cd-menu-items.c7
-rw-r--r--src/cdaudio-ng/cdaudio-ng.c26
-rw-r--r--src/compressor/plugin.c2
-rw-r--r--src/console/Audacious_Driver.cxx99
-rw-r--r--src/console/Vfs_File.cxx16
-rw-r--r--src/console/abstract_file.cxx20
-rw-r--r--src/console/configure.c2
-rw-r--r--src/crossfade/crossfade.c6
-rw-r--r--src/crossfade/plugin.c4
-rw-r--r--src/crystalizer/crystalizer.c3
-rw-r--r--src/cue/Makefile4
-rw-r--r--src/cue/cue.c122
-rw-r--r--src/daap/daap.c58
-rw-r--r--src/dockalbumart/dockalbumart.c12
-rw-r--r--src/echo_plugin/echo.c133
-rw-r--r--src/echo_plugin/gui.c15
-rw-r--r--src/esd/Makefile17
-rw-r--r--src/esd/about.c47
-rw-r--r--src/esd/audio.c435
-rw-r--r--src/esd/configure.c232
-rw-r--r--src/esd/esd.c45
-rw-r--r--src/esd/esdout.h68
-rw-r--r--src/esd/init.c92
-rw-r--r--src/esd/mixer.c234
-rw-r--r--src/evdev-plug/ed.c65
-rw-r--r--src/evdev-plug/ed_internals.c17
-rw-r--r--src/ffaudio/ffaudio-audvfs.c43
-rw-r--r--src/ffaudio/ffaudio-core.c94
-rw-r--r--src/ffaudio/ffaudio-stdinc.h1
-rw-r--r--src/filewriter/convert.c6
-rw-r--r--src/filewriter/convert.h2
-rw-r--r--src/filewriter/filewriter.c33
-rw-r--r--src/filewriter/filewriter.h6
-rw-r--r--src/filewriter/flac.c22
-rw-r--r--src/filewriter/mp3.c23
-rw-r--r--src/filewriter/vorbis.c22
-rw-r--r--src/filewriter/wav.c8
-rw-r--r--src/flacng/debug.h35
-rw-r--r--src/flacng/flac_compat112.c9
-rw-r--r--src/flacng/flacng.h12
-rw-r--r--src/flacng/plugin.c676
-rw-r--r--src/flacng/seekable_stream_callbacks.c397
-rw-r--r--src/flacng/tools.c368
-rw-r--r--src/flacng/tools.h23
-rw-r--r--src/gio/gio.c56
-rw-r--r--src/gnomeshortcuts/gnomeshortcuts.c25
-rw-r--r--src/gntui/fileselector.c2
-rw-r--r--src/gntui/gntui.c40
-rw-r--r--src/gtkui/Makefile1
-rw-r--r--src/gtkui/actions-mainwin.h1
-rw-r--r--src/gtkui/actions-playlist.h2
-rw-r--r--src/gtkui/actions.c192
-rw-r--r--src/gtkui/gtkui_cfg.c3
-rw-r--r--src/gtkui/gtkui_cfg.h1
-rw-r--r--src/gtkui/playlist_util.c6
-rw-r--r--src/gtkui/ui/player.ui6
-rw-r--r--src/gtkui/ui_gtk.c165
-rw-r--r--src/gtkui/ui_gtk.h7
-rw-r--r--src/gtkui/ui_infoarea.c221
-rw-r--r--src/gtkui/ui_manager.c48
-rw-r--r--src/gtkui/ui_playlist_model.c75
-rw-r--r--src/gtkui/ui_playlist_model.h3
-rw-r--r--src/gtkui/ui_playlist_notebook.c2
-rw-r--r--src/gtkui/ui_playlist_widget.c84
-rw-r--r--src/gtkui/ui_statusbar.c151
-rw-r--r--src/gtkui/ui_statusbar.h27
-rw-r--r--src/gtkui/util.c7
-rw-r--r--src/hotkey/plugin.c93
-rw-r--r--src/jack/configure.c2
-rw-r--r--src/jack/jack.c20
-rw-r--r--src/ladspa/ladspa.c160
-rw-r--r--src/lirc/lirc.c113
-rw-r--r--src/lirc/lirc_cfg.c4
-rw-r--r--src/lyricwiki/Makefile12
-rw-r--r--src/lyricwiki/lyricwiki.c392
-rw-r--r--src/lyricwiki/urlencode.c120
-rw-r--r--src/lyricwiki/urlencode.h2
-rw-r--r--src/m3u/m3u.c38
-rw-r--r--src/metronom/metronom.c9
-rw-r--r--src/mms/mms.c52
-rw-r--r--src/modplug/archive/arch_raw.cxx12
-rw-r--r--src/modplug/modplugbmp.cxx24
-rw-r--r--src/modplug/modplugbmp.h2
-rw-r--r--src/modplug/plugin.cxx1
-rw-r--r--src/mpg123/libmpg123/README6
-rw-r--r--src/mpg123/libmpg123/id3.c2
-rw-r--r--src/mpg123/libmpg123/mpg123.h2
-rw-r--r--src/mpg123/libmpg123/readers.c5
-rw-r--r--src/mpg123/mpg123.c341
-rw-r--r--src/mtp_up/mtp.c81
-rw-r--r--src/neon/cert_verification.c2
-rw-r--r--src/neon/cert_verification.h2
-rw-r--r--src/neon/neon.c124
-rw-r--r--src/notify/Makefile14
-rw-r--r--src/notify/libnotify-aosd.c71
-rw-r--r--src/notify/libnotify-aosd.h27
-rw-r--r--src/notify/libnotify-aosd_common.h35
-rw-r--r--src/notify/libnotify-aosd_event.c70
-rw-r--r--src/notify/libnotify-aosd_event.h28
-rw-r--r--src/notify/libnotify-aosd_osd.c61
-rw-r--r--src/notify/libnotify-aosd_osd.h27
-rw-r--r--src/null/null.c6
-rw-r--r--src/oss4/configure.c69
-rw-r--r--src/oss4/oss.c92
-rw-r--r--src/oss4/oss.h8
-rw-r--r--src/oss4/plugin.c5
-rw-r--r--src/oss4/utils.c14
-rw-r--r--src/paranormal/Makefile2
-rw-r--r--src/paranormal/cfg.c13
-rw-r--r--src/paranormal/libcalc/parser.c16
-rw-r--r--src/pls/Makefile2
-rw-r--r--src/pls/pls.c30
-rw-r--r--src/pls/util.c284
-rw-r--r--src/pls/util.h38
-rwxr-xr-xsrc/projectm-1.0/gtk_projectm_impl.cxx28
-rw-r--r--src/projectm-1.0/main.c29
-rw-r--r--src/projectm/main.c4
-rw-r--r--src/psf/plugin.c42
-rw-r--r--src/pulse_audio/pulse_audio.c23
-rw-r--r--src/resample/plugin.c4
-rw-r--r--src/roaraudio/KNOWN-ISSUES6
-rw-r--r--src/roaraudio/Makefile8
-rw-r--r--src/roaraudio/all.h90
-rw-r--r--src/roaraudio/gui.c339
-rw-r--r--src/roaraudio/roar.c644
-rw-r--r--src/scrobbler/Makefile3
-rw-r--r--src/scrobbler/configure.c25
-rw-r--r--src/scrobbler/images/audioscrobbler.pngbin2969 -> 0 bytes
-rw-r--r--src/scrobbler/images/audioscrobbler_badge.pngbin1899 -> 0 bytes
-rw-r--r--src/scrobbler/plugin.c26
-rw-r--r--src/scrobbler/scrobbler.c66
-rw-r--r--src/sid/Makefile2
-rw-r--r--src/sid/xmms-sid.c48
-rw-r--r--src/sid/xs_config.c163
-rw-r--r--src/sid/xs_fileinfo.c8
-rw-r--r--src/sid/xs_filter.c6
-rw-r--r--src/sid/xs_filter.h2
-rw-r--r--src/sid/xs_player.h2
-rw-r--r--src/sid/xs_support.c2
-rw-r--r--src/sid/xs_support.h16
-rw-r--r--src/skins/Makefile2
-rw-r--r--src/skins/actions-playlist.h1
-rw-r--r--src/skins/plugin.c16
-rw-r--r--src/skins/plugin.h3
-rw-r--r--src/skins/skins_cfg.c17
-rw-r--r--src/skins/ui/mainwin.ui2
-rw-r--r--src/skins/ui/playlist.ui1
-rw-r--r--src/skins/ui_equalizer.c35
-rw-r--r--src/skins/ui_main.c195
-rw-r--r--src/skins/ui_main_evlisteners.c220
-rw-r--r--src/skins/ui_main_evlisteners.h3
-rw-r--r--src/skins/ui_manager.c48
-rw-r--r--src/skins/ui_playlist.c98
-rw-r--r--src/skins/ui_playlist_evlisteners.c9
-rw-r--r--src/skins/ui_skin.c182
-rw-r--r--src/skins/ui_skinned_equalizer_graph.c2
-rw-r--r--src/skins/ui_skinned_playlist.c16
-rw-r--r--src/skins/ui_skinned_textbox.c8
-rw-r--r--src/skins/ui_svis.c13
-rw-r--r--src/skins/util.c15
-rw-r--r--src/skins/util.h1
-rw-r--r--src/smb/smb.c58
-rw-r--r--src/sndfile/plugin.c79
-rw-r--r--src/sndstretch/sndstretch_xmms.c6
-rw-r--r--src/song_change/song_change.c57
-rw-r--r--src/statusicon/config.c2
-rw-r--r--src/statusicon/statusicon.c19
-rw-r--r--src/statusicon/statusicon.h1
-rw-r--r--src/statusicon/util.c19
-rw-r--r--src/stereo_plugin/stereo.c3
-rw-r--r--src/streambrowser/bookmarks.c2
-rw-r--r--src/streambrowser/shoutcast.c2
-rw-r--r--src/streambrowser/streambrowser.c38
-rw-r--r--src/streambrowser/xiph.c10
-rw-r--r--src/sun/audio.c14
-rw-r--r--src/sun/sun.h4
-rw-r--r--src/tonegen/tonegen.c8
-rw-r--r--src/unix-io/unix-io.c3
-rw-r--r--src/usf/Makefile43
-rw-r--r--src/usf/audio.c112
-rw-r--r--src/usf/audio.h13
-rw-r--r--src/usf/audio_hle.h140
-rw-r--r--src/usf/audio_hle_main.c83
-rw-r--r--src/usf/audio_ucode1.c755
-rw-r--r--src/usf/audio_ucode2.c904
-rw-r--r--src/usf/audio_ucode3.c666
-rw-r--r--src/usf/audio_ucode3mp3.c588
-rw-r--r--src/usf/config.h63
-rw-r--r--src/usf/cpu.c640
-rw-r--r--src/usf/cpu.h108
-rw-r--r--src/usf/dma.c177
-rw-r--r--src/usf/dma.h34
-rw-r--r--src/usf/exception.c228
-rw-r--r--src/usf/exception.h75
-rw-r--r--src/usf/interpreter_cpu.c738
-rw-r--r--src/usf/interpreter_cpu.h37
-rw-r--r--src/usf/interpreter_ops.c1362
-rw-r--r--src/usf/interpreter_ops.h210
-rw-r--r--src/usf/main.c41
-rw-r--r--src/usf/main.h10
-rw-r--r--src/usf/memory.c1890
-rw-r--r--src/usf/memory.h84
-rw-r--r--src/usf/opcode.h274
-rw-r--r--src/usf/pif.c97
-rw-r--r--src/usf/pif.h31
-rw-r--r--src/usf/psftag.c528
-rw-r--r--src/usf/psftag.h57
-rw-r--r--src/usf/recompiler_cpu.c2780
-rw-r--r--src/usf/recompiler_cpu.h240
-rw-r--r--src/usf/recompiler_fpu_ops.c1089
-rw-r--r--src/usf/recompiler_ops.c4657
-rw-r--r--src/usf/recompiler_ops.h196
-rw-r--r--src/usf/registers.c1054
-rw-r--r--src/usf/registers.h403
-rw-r--r--src/usf/rsp.c1065
-rw-r--r--src/usf/rsp.h423
-rw-r--r--src/usf/rsp_interpreter_cpu.c1706
-rw-r--r--src/usf/rsp_mmx.c143
-rw-r--r--src/usf/rsp_recompiler_analysis.c1780
-rw-r--r--src/usf/rsp_recompiler_cpu.c954
-rw-r--r--src/usf/rsp_recompiler_cpu.h116
-rw-r--r--src/usf/rsp_recompiler_ops.c4619
-rw-r--r--src/usf/rsp_recompiler_ops.h158
-rw-r--r--src/usf/rsp_registers.h149
-rw-r--r--src/usf/rsp_sse.c84
-rw-r--r--src/usf/rsp_x86.c1366
-rw-r--r--src/usf/rsp_x86.h552
-rw-r--r--src/usf/tlb.c200
-rw-r--r--src/usf/tlb.h108
-rw-r--r--src/usf/types.h77
-rw-r--r--src/usf/usf.c522
-rw-r--r--src/usf/usf.h27
-rw-r--r--src/usf/x86.c810
-rw-r--r--src/usf/x86.h544
-rw-r--r--src/usf/x86_fpu.c529
-rw-r--r--src/vfstrace/Makefile12
-rw-r--r--src/vfstrace/vfstrace.c226
-rw-r--r--src/voice_removal/voice_removal.c122
-rw-r--r--src/vorbis/configure.c2
-rw-r--r--src/vorbis/vcedit.c4
-rw-r--r--src/vorbis/vcupdate.c33
-rw-r--r--src/vorbis/vorbis.c200
-rw-r--r--src/vorbis/vorbis.h7
-rw-r--r--src/vtx/vtx.c37
-rw-r--r--src/vtx/vtxfile.c30
-rw-r--r--src/wavpack/wavpack.c81
-rw-r--r--src/xsf/plugin.c42
-rw-r--r--src/xspf/xspf.c24
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 (&current_volume);
+ aud_drct_get_volume_main (&current_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 (&current_volume);
+ aud_drct_get_volume_main (&current_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, &param) == -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, &param) == -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 = &empty;
- 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 = &empty;
+ 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 = &empty;
+ 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 = &empty;
- 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
deleted file mode 100644
index 784ce4b..0000000
--- a/src/scrobbler/images/audioscrobbler.png
+++ /dev/null
Binary files differ
diff --git a/src/scrobbler/images/audioscrobbler_badge.png b/src/scrobbler/images/audioscrobbler_badge.png
deleted file mode 100644
index 3fe05f0..0000000
--- a/src/scrobbler/images/audioscrobbler_badge.png
+++ /dev/null
Binary files differ
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, &current_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) {