diff --git a/mupen64plus-core/projects/msvc/mupen64plus-core.vcxproj b/mupen64plus-core/projects/msvc/mupen64plus-core.vcxproj
index 33b4246..ef1d1dd 100644
--- a/mupen64plus-core/projects/msvc/mupen64plus-core.vcxproj
+++ b/mupen64plus-core/projects/msvc/mupen64plus-core.vcxproj
@@ -133,6 +133,7 @@
+
@@ -437,6 +438,7 @@
+
diff --git a/mupen64plus-core/projects/msvc/mupen64plus-core.vcxproj.filters b/mupen64plus-core/projects/msvc/mupen64plus-core.vcxproj.filters
index 32efb28..caf7af7 100644
--- a/mupen64plus-core/projects/msvc/mupen64plus-core.vcxproj.filters
+++ b/mupen64plus-core/projects/msvc/mupen64plus-core.vcxproj.filters
@@ -339,6 +339,9 @@
device\cart
+
+ device\cart
+
device\cart
@@ -683,6 +686,9 @@
device\cart
+
+ device\cart
+
device\cart
diff --git a/mupen64plus-core/projects/unix/Makefile b/mupen64plus-core/projects/unix/Makefile
index e50eee8..d518008 100755
--- a/mupen64plus-core/projects/unix/Makefile
+++ b/mupen64plus-core/projects/unix/Makefile
@@ -504,6 +504,7 @@ SOURCE = \
$(SRCDIR)/device/cart/cart_rom.c \
$(SRCDIR)/device/cart/eeprom.c \
$(SRCDIR)/device/cart/flashram.c \
+ $(SRCDIR)/device/cart/is_viewer.c \
$(SRCDIR)/device/cart/sram.c \
$(SRCDIR)/device/controllers/game_controller.c \
$(SRCDIR)/device/controllers/vru_controller.c \
diff --git a/mupen64plus-core/src/device/cart/is_viewer.c b/mupen64plus-core/src/device/cart/is_viewer.c
new file mode 100644
index 0000000..dc2e8a2
--- /dev/null
+++ b/mupen64plus-core/src/device/cart/is_viewer.c
@@ -0,0 +1,75 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Mupen64plus - is_viewer.c *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2021 loganmc10 *
+ * *
+ * 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 "is_viewer.h"
+
+#define M64P_CORE_PROTOTYPES 1
+#include "api/callbacks.h"
+#include "main/util.h"
+
+#define __STDC_FORMAT_MACROS
+#include
+#include
+
+#define IS_ADDR_MASK UINT32_C(0x0000ffff)
+
+void poweron_is_viewer(struct is_viewer* is_viewer)
+{
+ memset(is_viewer->buffer, 0, 0x200);
+ memset(is_viewer->output_buffer, 0, 0x200);
+ is_viewer->buffer_pos = 0;
+}
+
+void read_is_viewer(void* opaque, uint32_t address, uint32_t* value)
+{
+ struct is_viewer* is_viewer = (struct is_viewer*)opaque;
+ address &= IS_ADDR_MASK;
+ memcpy(value, &is_viewer->buffer[address], 4);
+ *value = m64p_swap32(*value);
+}
+
+void write_is_viewer(void* opaque, uint32_t address, uint32_t value, uint32_t mask)
+{
+ struct is_viewer* is_viewer = (struct is_viewer*)opaque;
+ address &= IS_ADDR_MASK;
+ uint32_t word = value & mask;
+ if (address == 0x14)
+ {
+ if (word > 0)
+ {
+ memcpy(is_viewer->output_buffer + is_viewer->buffer_pos, is_viewer->buffer + 0x20, word);
+ is_viewer->buffer_pos += word;
+ if (memchr(is_viewer->output_buffer, '\n', is_viewer->buffer_pos))
+ {
+ is_viewer->output_buffer[is_viewer->buffer_pos - 1] = '\0';
+ DebugMessage(M64MSG_INFO, "IS64: %s", is_viewer->output_buffer);
+ memset(is_viewer->output_buffer, 0, is_viewer->buffer_pos);
+ is_viewer->buffer_pos = 0;
+ }
+ }
+ memset(is_viewer->buffer + 0x20, 0, word);
+ }
+ else
+ {
+ word = m64p_swap32(word);
+ memcpy(is_viewer->buffer + address, &word, sizeof(word));
+ }
+}
diff --git a/mupen64plus-core/src/device/cart/is_viewer.h b/mupen64plus-core/src/device/cart/is_viewer.h
new file mode 100644
index 0000000..8e854b6
--- /dev/null
+++ b/mupen64plus-core/src/device/cart/is_viewer.h
@@ -0,0 +1,40 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Mupen64plus - is_viewer.h *
+ * Mupen64Plus homepage: https://mupen64plus.org/ *
+ * Copyright (C) 2021 loganmc10 *
+ * *
+ * 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 M64P_DEVICE_PI_IS_VIEWER_H
+#define M64P_DEVICE_PI_IS_VIEWER_H
+
+#include
+#include
+
+struct is_viewer
+{
+ char buffer[0x200];
+ char output_buffer[0x200];
+ uint32_t buffer_pos;
+};
+
+void poweron_is_viewer(struct is_viewer* is_viewer);
+
+void read_is_viewer(void* opaque, uint32_t address, uint32_t* value);
+void write_is_viewer(void* opaque, uint32_t address, uint32_t value, uint32_t mask);
+
+#endif
diff --git a/mupen64plus-core/src/device/device.c b/mupen64plus-core/src/device/device.c
index 6a8e8ec..7bf406c 100644
--- a/mupen64plus-core/src/device/device.c
+++ b/mupen64plus-core/src/device/device.c
@@ -150,6 +150,7 @@ void init_device(struct device* dev,
{ A(MM_DOM2_ADDR1, 0xffffff), M64P_MEM_NOTHING, { NULL, RW(open_bus) } },
{ A(MM_DD_ROM, 0x1ffffff), M64P_MEM_NOTHING, { NULL, RW(open_bus) } },
{ A(MM_DOM2_ADDR2, 0x1ffff), M64P_MEM_FLASHRAMSTAT, { &dev->cart, RW(cart_dom2) } },
+ { A(MM_IS_VIEWER, 0x1000), M64P_MEM_NOTHING, { &dev->is, RW(is_viewer) } },
{ A(MM_CART_ROM, rom_size-1), M64P_MEM_ROM, { &dev->cart.cart_rom, RW(cart_rom) } },
{ A(MM_PIF_MEM, 0xffff), M64P_MEM_PIF, { &dev->pif, RW(pif_mem) } }
};
@@ -236,6 +237,8 @@ void poweron_device(struct device* dev)
poweron_cart(&dev->cart);
+ poweron_is_viewer(&dev->is);
+
/* poweron for controllers */
for(i = 0; i < GAME_CONTROLLERS_COUNT; ++i) {
struct pif_channel* channel = &dev->pif.channels[i];
diff --git a/mupen64plus-core/src/device/device.h b/mupen64plus-core/src/device/device.h
index 0aafb39..de174c1 100644
--- a/mupen64plus-core/src/device/device.h
+++ b/mupen64plus-core/src/device/device.h
@@ -26,6 +26,7 @@
#include
#include "cart/cart.h"
+#include "cart/is_viewer.h"
#include "controllers/game_controller.h"
#include "controllers/paks/biopak.h"
#include "controllers/paks/mempak.h"
@@ -79,6 +80,7 @@ enum { GAME_CONTROLLERS_COUNT = 4 };
#define MM_DOM2_ADDR2 UINT32_C(0x08000000)
#define MM_CART_ROM UINT32_C(0x10000000) /* dom1 addr2 */
+#define MM_IS_VIEWER UINT32_C(0x13ff0000) /* IS-Viewer */
#define MM_PIF_MEM UINT32_C(0x1fc00000)
#define MM_CART_DOM3 UINT32_C(0x1fd00000) /* dom2 addr2 */
@@ -98,6 +100,7 @@ struct device
struct pif pif;
struct rdram rdram;
struct memory mem;
+ struct is_viewer is;
struct game_controller controllers[GAME_CONTROLLERS_COUNT];
struct biopak biopaks[GAME_CONTROLLERS_COUNT];